Commit 4b957c22 authored by Andrew Tridgell's avatar Andrew Tridgell

added the --safe-links option to disallow symlinks outside the

destination tree
parent d853783f
......@@ -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.
......
......@@ -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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment