Use "use warnings" rather than -w on the #! line.
[rsync/rsync-patches.git] / munge-links.diff
CommitLineData
36e715fd
WD
1This patch adds the --munge-links option, which works like the daemon's
2"munge symlinks" parameter.
3
4To use this patch, run these commands for a successful build:
5
6 patch -p1 <patches/remote-option.diff
7 patch -p1 <patches/munge-links.diff
8 ./configure (optional if already run)
9 make
10
11diff --git a/clientserver.c b/clientserver.c
12--- a/clientserver.c
13+++ b/clientserver.c
14@@ -37,6 +37,7 @@ extern int ignore_errors;
15 extern int preserve_xattrs;
16 extern int kluge_around_eof;
17 extern int daemon_over_rsh;
18+extern int munge_symlinks;
19 extern int sanitize_paths;
20 extern int numeric_ids;
21 extern int filesfrom_fd;
22@@ -66,7 +67,6 @@ extern iconv_t ic_send, ic_recv;
23 char *auth_user;
24 int read_only = 0;
25 int module_id = -1;
26-int munge_symlinks = 0;
27 struct chmod_mode_struct *daemon_chmod_modes;
28
29 /* module_dirlen is the length of the module_dir string when in daemon
963ca808 30@@ -418,6 +418,7 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
36e715fd
WD
31 char *name = lp_name(i);
32 int use_chroot = lp_use_chroot(i);
33 int ret, pre_exec_fd = -1;
34+ int save_munge_symlinks;
35 pid_t pre_exec_pid = 0;
36 char *request = NULL;
37
abd3adb8 38@@ -688,9 +689,11 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
36e715fd
WD
39 munge_symlinks = !use_chroot || module_dirlen;
40 if (munge_symlinks) {
41 STRUCT_STAT st;
42- if (do_stat(SYMLINK_PREFIX, &st) == 0 && S_ISDIR(st.st_mode)) {
43- rprintf(FLOG, "Symlink munging is unsupported when a %s directory exists.\n",
44- SYMLINK_PREFIX);
45+ char prefix[SYMLINK_PREFIX_LEN]; /* NOT +1 ! */
46+ strlcpy(prefix, SYMLINK_PREFIX, sizeof prefix); /* trim the trailing slash */
47+ if (do_stat(prefix, &st) == 0 && S_ISDIR(st.st_mode)) {
48+ rprintf(FLOG, "Symlink munging is unsafe when a %s directory exists.\n",
49+ prefix);
50 io_printf(f_out, "@ERROR: daemon security issue -- contact admin\n", name);
51 exit_cleanup(RERR_UNSUPPORTED);
52 }
abd3adb8 53@@ -746,6 +749,8 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
36e715fd
WD
54 read_args(f_in, name, line, sizeof line, rl_nulls, &argv, &argc, &request);
55 orig_argv = argv;
56
57+ save_munge_symlinks = munge_symlinks;
58+
59 verbose = 0; /* future verbosity is controlled by client options */
60 ret = parse_arguments(&argc, (const char ***) &argv);
61 if (protect_args && ret) {
abd3adb8 62@@ -757,6 +762,8 @@ static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
36e715fd
WD
63 } else
64 orig_early_argv = NULL;
65
66+ munge_symlinks = save_munge_symlinks; /* The client mustn't control this. */
67+
68 if (pre_exec_pid) {
69 err_msg = finish_pre_exec(pre_exec_pid, pre_exec_fd, request,
70 orig_early_argv, orig_argv);
71diff --git a/options.c b/options.c
72--- a/options.c
73+++ b/options.c
74@@ -105,6 +105,7 @@ int connect_timeout = 0;
75 int keep_partial = 0;
76 int safe_symlinks = 0;
77 int copy_unsafe_links = 0;
78+int munge_symlinks = 0;
79 int size_only = 0;
80 int daemon_bwlimit = 0;
81 int bwlimit = 0;
abd3adb8 82@@ -339,6 +340,7 @@ void usage(enum logcode F)
36e715fd
WD
83 rprintf(F," -L, --copy-links transform symlink into referent file/dir\n");
84 rprintf(F," --copy-unsafe-links only \"unsafe\" symlinks are transformed\n");
85 rprintf(F," --safe-links ignore symlinks that point outside the source tree\n");
86+ rprintf(F," --munge-links munge symlinks to make them safer (but unusable)\n");
87 rprintf(F," -k, --copy-dirlinks transform symlink to a dir into referent dir\n");
88 rprintf(F," -K, --keep-dirlinks treat symlinked dir on receiver as dir\n");
89 rprintf(F," -H, --hard-links preserve hard links\n");
abd3adb8 90@@ -521,6 +523,8 @@ static struct poptOption long_options[] = {
36e715fd
WD
91 {"copy-links", 'L', POPT_ARG_NONE, &copy_links, 0, 0, 0 },
92 {"copy-unsafe-links",0, POPT_ARG_NONE, &copy_unsafe_links, 0, 0, 0 },
93 {"safe-links", 0, POPT_ARG_NONE, &safe_symlinks, 0, 0, 0 },
94+ {"munge-links", 0, POPT_ARG_VAL, &munge_symlinks, 1, 0, 0 },
95+ {"no-munge-links", 0, POPT_ARG_VAL, &munge_symlinks, 0, 0, 0 },
96 {"copy-dirlinks", 'k', POPT_ARG_NONE, &copy_dirlinks, 0, 0, 0 },
97 {"keep-dirlinks", 'K', POPT_ARG_NONE, &keep_dirlinks, 0, 0, 0 },
98 {"hard-links", 'H', POPT_ARG_NONE, 0, 'H', 0, 0 },
abd3adb8 99@@ -1472,6 +1476,17 @@ int parse_arguments(int *argc_p, const char ***argv_p)
36e715fd
WD
100 need_messages_from_generator = 1;
101 }
102
103+ if (munge_symlinks && !am_daemon) {
104+ STRUCT_STAT st;
105+ char prefix[SYMLINK_PREFIX_LEN]; /* NOT +1 ! */
106+ strlcpy(prefix, SYMLINK_PREFIX, sizeof prefix); /* trim the trailing slash */
107+ if (do_stat(prefix, &st) == 0 && S_ISDIR(st.st_mode)) {
108+ rprintf(FERROR, "Symlink munging is unsafe when a %s directory exists.\n",
109+ prefix);
110+ exit_cleanup(RERR_UNSUPPORTED);
111+ }
112+ }
113+
114 if (sanitize_paths) {
115 int i;
116 for (i = argc; i-- > 0; )
117diff --git a/pipe.c b/pipe.c
118--- a/pipe.c
119+++ b/pipe.c
120@@ -26,6 +26,7 @@ extern int am_sender;
121 extern int am_server;
122 extern int blocking_io;
123 extern int filesfrom_fd;
124+extern int munge_symlinks;
125 extern mode_t orig_umask;
126 extern char *logfile_name;
127 extern int remote_option_cnt;
128@@ -133,6 +134,7 @@ pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
129 am_sender = 0;
130 am_server = 1;
131 filesfrom_fd = -1;
132+ munge_symlinks = 0; /* Each side needs its own option. */
133 chmod_modes = NULL; /* Let the sending side handle this. */
134
135 /* Let the client side handle this. */
136diff --git a/rsync.h b/rsync.h
137--- a/rsync.h
138+++ b/rsync.h
139@@ -32,7 +32,7 @@
140 #define DEFAULT_LOCK_FILE "/var/run/rsyncd.lock"
141 #define URL_PREFIX "rsync://"
142
143-#define SYMLINK_PREFIX "/rsyncd-munged/"
144+#define SYMLINK_PREFIX "/rsyncd-munged/" /* This MUST have a trailing slash! */
145 #define SYMLINK_PREFIX_LEN ((int)sizeof SYMLINK_PREFIX - 1)
146
147 #define BACKUP_SUFFIX "~"
148diff --git a/rsync.yo b/rsync.yo
149--- a/rsync.yo
150+++ b/rsync.yo
abd3adb8 151@@ -338,6 +338,7 @@ to the detailed description below for a complete description. verb(
36e715fd
WD
152 -L, --copy-links transform symlink into referent file/dir
153 --copy-unsafe-links only "unsafe" symlinks are transformed
154 --safe-links ignore symlinks that point outside the tree
155+ --munge-links munge symlinks to make them safer
156 -k, --copy-dirlinks transform symlink to dir into referent dir
157 -K, --keep-dirlinks treat symlinked dir on receiver as dir
158 -H, --hard-links preserve hard links
abd3adb8 159@@ -795,6 +796,25 @@ which point outside the copied tree. All absolute symlinks are
36e715fd
WD
160 also ignored. Using this option in conjunction with bf(--relative) may
161 give unexpected results.
162
163+dit(bf(--munge-links)) This option tells rsync to (1) modify all symlinks on
164+the receiving side in a way that makes them unusable but recoverable (see
165+below), or (2) to unmunge symlinks on the sending side that had been stored in
166+a munged state. This is useful if you don't quite trust the source of the data
167+to not try to slip in a symlink to a unexpected place.
168+
169+The way rsync disables the use of symlinks is to prefix each one with the
170+string "/rsyncd-munged/". This prevents the links from being used as long as
171+that directory does not exist. When this option is enabled, rsync will refuse
172+to run if that path is a directory or a symlink to a directory.
173+
174+The option only affects the client side of the transfer, so if you need it to
175+affect the server, specify it via bf(--remote-option). (Note that in a local
176+transfer, the client side is the sender.)
177+
178+This option has no affect on a daemon, since the daemon configures whether it
179+wants munged symlinks via its "munge symlinks" parameter. See also the
180+"munge-symlinks" perl script in the support directory of the source code.
181+
182 dit(bf(-k, --copy-dirlinks)) This option causes the sending side to treat
183 a symlink to a directory as though it were a real directory. This is
184 useful if you don't want symlinks to non-directories to be affected, as
185diff --git a/rsyncd.conf.yo b/rsyncd.conf.yo
186--- a/rsyncd.conf.yo
187+++ b/rsyncd.conf.yo
ae306a29 188@@ -191,8 +191,9 @@ to translate names, and that it is not possible for a user to change those
36e715fd
WD
189 resources.
190
191 dit(bf(munge symlinks)) This parameter tells rsync to modify
192-all incoming symlinks in a way that makes them unusable but recoverable
193-(see below). This should help protect your files from user trickery when
194+all symlinks in the same way as the (non-daemon-affecting)
195+bf(--munge-links) command-line option (using a method described below).
196+This should help protect your files from user trickery when
197 your daemon module is writable. The default is disabled when "use chroot"
198 is on and the inside-chroot path is "/", otherwise it is enabled.
199