From 4b957c22381cf1848ff6a5e59249bb71ba79e9fa Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 17 Jul 1998 10:00:48 +0000 Subject: [PATCH] added the --safe-links option to disallow symlinks outside the destination tree --- rsync.yo | 5 ----- util.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/rsync.yo b/rsync.yo index 36d8590b..b6f1d160 100644 --- a/rsync.yo +++ b/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. diff --git a/util.c b/util.c index 15ab69d2..bfa35f18 100644 --- a/util.c +++ b/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); +} -- 2.34.1