mirror of
https://github.com/RsyncProject/rsync.git
synced 2026-03-14 12:27:09 -04:00
added the --safe-links option to disallow symlinks outside the
destination tree
This commit is contained in:
5
rsync.yo
5
rsync.yo
@@ -315,11 +315,6 @@ option all symbolic links are skipped.
|
||||
dit(bf(-L, --copy-links)) This tells rsync to treat symbolic links just
|
||||
like ordinary files.
|
||||
|
||||
dit(bf(--safe-links)) This tells rsync to ignore any symbolic links
|
||||
which point outside the destination tree. All absolute symlinks are
|
||||
also ignored. Using this option in conjunction with --relative may
|
||||
give unexpecetd results.
|
||||
|
||||
dit(bf(-H, --hard-links)) This tells rsync to recreate hard links on
|
||||
the remote system to be the same as the local system. Without this
|
||||
option hard links are treated like regular files.
|
||||
|
||||
47
util.c
47
util.c
@@ -710,3 +710,50 @@ void show_progress(OFF_T ofs, OFF_T size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* determine if a symlink points outside the current directory tree */
|
||||
int unsafe_symlink(char *dest, char *src)
|
||||
{
|
||||
char *tok;
|
||||
int depth = 0;
|
||||
|
||||
/* all absolute and null symlinks are unsafe */
|
||||
if (!dest || !(*dest) || (*dest == '/')) return 1;
|
||||
|
||||
src = strdup(src);
|
||||
if (!src) out_of_memory("unsafe_symlink");
|
||||
|
||||
/* find out what our safety margin is */
|
||||
for (tok=strtok(src,"/"); tok; tok=strtok(NULL,"/")) {
|
||||
if (strcmp(tok,"..") == 0) {
|
||||
depth=0;
|
||||
} else if (strcmp(tok,".") == 0) {
|
||||
/* nothing */
|
||||
} else {
|
||||
depth++;
|
||||
}
|
||||
}
|
||||
free(src);
|
||||
|
||||
/* drop by one to account for the filename portion */
|
||||
depth--;
|
||||
|
||||
dest = strdup(dest);
|
||||
if (!dest) out_of_memory("unsafe_symlink");
|
||||
|
||||
for (tok=strtok(dest,"/"); tok; tok=strtok(NULL,"/")) {
|
||||
if (strcmp(tok,"..") == 0) {
|
||||
depth--;
|
||||
} else if (strcmp(tok,".") == 0) {
|
||||
/* nothing */
|
||||
} else {
|
||||
depth++;
|
||||
}
|
||||
/* if at any point we go outside the current directory then
|
||||
stop - it is unsafe */
|
||||
if (depth < 0) break;
|
||||
}
|
||||
|
||||
free(dest);
|
||||
return (depth < 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user