--- a/clientserver.c +++ b/clientserver.c @@ -34,6 +34,7 @@ extern int rsync_port; extern int kluge_around_eof; extern int daemon_over_rsh; extern int sanitize_paths; +extern int numeric_ids; extern int filesfrom_fd; extern int remote_protocol; extern int protocol_version; @@ -698,6 +699,10 @@ static int rsync_module(int f_in, int f_ exit_cleanup(RERR_UNSUPPORTED); } + if (!numeric_ids + && (use_chroot ? lp_numeric_ids(i) != False : lp_numeric_ids(i) == True)) + numeric_ids = -1; /* Set --numeric-ids w/o breaking protocol. */ + if (lp_timeout(i) && lp_timeout(i) > io_timeout) set_io_timeout(lp_timeout(i)); --- a/loadparm.c +++ b/loadparm.c @@ -154,6 +154,7 @@ typedef struct BOOL ignore_nonreadable; BOOL list; BOOL munge_symlinks; + BOOL numeric_ids; BOOL read_only; BOOL strict_modes; BOOL transfer_logging; @@ -202,6 +203,7 @@ static service sDefault = /* ignore_nonreadable; */ False, /* list; */ True, /* munge_symlinks; */ (BOOL)-1, + /* numeric_ids; */ (BOOL)-1, /* read_only; */ True, /* strict_modes; */ True, /* transfer_logging; */ False, @@ -317,6 +319,7 @@ static struct parm_struct parm_table[] = {"max verbosity", P_INTEGER,P_LOCAL, &sDefault.max_verbosity, NULL,0}, {"munge symlinks", P_BOOL, P_LOCAL, &sDefault.munge_symlinks, NULL,0}, {"name", P_STRING, P_LOCAL, &sDefault.name, NULL,0}, + {"numeric ids", P_BOOL, P_LOCAL, &sDefault.numeric_ids, NULL,0}, {"outgoing chmod", P_STRING, P_LOCAL, &sDefault.outgoing_chmod, NULL,0}, {"path", P_PATH, P_LOCAL, &sDefault.path, NULL,0}, #ifdef HAVE_PUTENV @@ -419,6 +422,7 @@ FN_LOCAL_BOOL(lp_ignore_errors, ignore_e FN_LOCAL_BOOL(lp_ignore_nonreadable, ignore_nonreadable) FN_LOCAL_BOOL(lp_list, list) FN_LOCAL_BOOL(lp_munge_symlinks, munge_symlinks) +FN_LOCAL_BOOL(lp_numeric_ids, numeric_ids) FN_LOCAL_BOOL(lp_read_only, read_only) FN_LOCAL_BOOL(lp_strict_modes, strict_modes) FN_LOCAL_BOOL(lp_transfer_logging, transfer_logging) --- a/proto.h +++ b/proto.h @@ -177,6 +177,7 @@ BOOL lp_ignore_errors(int ); BOOL lp_ignore_nonreadable(int ); BOOL lp_list(int ); BOOL lp_munge_symlinks(int ); +BOOL lp_numeric_ids(int ); BOOL lp_read_only(int ); BOOL lp_strict_modes(int ); BOOL lp_transfer_logging(int ); --- a/rsyncd.conf.5 +++ b/rsyncd.conf.5 @@ -144,8 +144,9 @@ to the "path" before starting the file t the advantage of extra protection against possible implementation security holes, but it has the disadvantages of requiring super-user privileges, of not being able to follow symbolic links that are either absolute or outside -of the new root path, and of complicating the preservation of usernames and groups -(see below)\&. When "use chroot" is false, rsync will: (1) munge symlinks by +of the new root path, and of complicating the preservation of users and groups +by name (see below)\&. +When "use chroot" is false, rsync will: (1) munge symlinks by default for security reasons (see "munge symlinks" for a way to turn this off, but only if you trust your users), (2) substitute leading slashes in absolute paths with the module\&'s path (so that options such as @@ -155,7 +156,9 @@ args if rsync believes they would escape The default for "use chroot" is true, and is the safer choice (especially if the module is not read-only)\&. .IP -In order to preserve usernames and groupnames, rsync needs to be able to +When this option is enabled, rsync will not attempt to map users and groups +by name (by default), but instead copy IDs as though \fB\-\-numeric\-ids\fP had +been specified\&. In order to enable name-mapping, rsync needs to be able to use the standard library functions for looking up names and IDs (i\&.e\&. \f(CWgetpwuid()\fP , @@ -164,25 +167,35 @@ use the standard library functions for l \f(CWgetpwname()\fP , and \f(CWgetgrnam()\fP -)\&. This means a -process in the chroot namespace will need to have access to the resources +)\&. +This means the rsync +process in the chroot hierarchy will need to have access to the resources used by these library functions (traditionally /etc/passwd and -/etc/group)\&. If these resources are not available, rsync will only be -able to copy the IDs, just as if the \fB\-\-numeric\-ids\fP option had been -specified\&. -.IP -Note that you are free to setup user/group information in the chroot area -differently from your normal system\&. For example, you could abbreviate -the list of users and groups\&. Also, you can protect this information from -being downloaded/uploaded by adding an exclude rule to the rsyncd\&.conf file -(e\&.g\&. "exclude = /etc/**")\&. Note that having the exclusion affect uploads -is a relatively new feature in rsync, so make sure your daemon is -at least 2\&.6\&.3 to effect this\&. Also note that it is safest to exclude a -directory and all its contents combining the rule "/some/dir/" with the -rule "/some/dir/**" just to be sure that rsync will not allow deeper -access to some of the excluded files inside the directory (rsync tries to -do this automatically, but you might as well specify both to be extra -sure)\&. +/etc/group, but perhaps additional dynamic libraries as well)\&. +.IP +If you copy the necessary resources into the module\&'s chroot area, you +should protect them through your OS\&'s normal user/group or ACL settings (to +prevent the rsync module\&'s user from being able to change them), and then +hide them from the user\&'s view via "exclude" (see how in the discussion of +that option)\&. At that point it will be safe to enable the mapping of users +and groups by name using the "numeric ids" daemon option (see below)\&. +.IP +Note also that you are free to setup custom user/group information in the +chroot area that is different from your normal system\&. For example, you +could abbreviate the list of users and groups\&. +.IP +.IP "\fBnumeric ids\fP" +Enabling the "numeric ids" option disables the mapping +of users and groups by name for the current daemon module\&. This prevents +the daemon from trying to load any user/group-related files or libraries\&. +Enabling this option makes the transfer behave as if the client had passed +the \fB\-\-numeric\-ids\fP command-line option\&. By default, this parameter is +enabled for chroot modules and disabled for non-chroot modules\&. +.IP +A chroot-enabled module should not have this option enabled unless you\&'ve +taken steps to ensure that the module has the necessary resources it needs +to translate names, and that it is not possible for a user to change those +resources\&. .IP .IP "\fBmunge symlinks\fP" The "munge symlinks" option tells rsync to modify @@ -326,6 +339,13 @@ from a daemon and files deleted on a dae it doesn\&'t exclude files from being deleted on a client when receiving from a daemon\&. .IP +When you want to exclude a directory and all its contents, it is safest to +use a rule that does both, such as "/some/dir/***" (the three stars tells +rsync to exclude the directory itself and everything inside it)\&. This is +better than just excluding the directory alone with "/some/dir/", as it +helps to guard against attempts to trick rsync into accessing files deeper +in the hierarchy\&. +.IP .IP "\fBexclude from\fP" The "exclude from" option specifies a filename on the daemon that contains exclude patterns, one per line\&. --- a/rsyncd.conf.yo +++ b/rsyncd.conf.yo @@ -128,8 +128,9 @@ to the "path" before starting the file t the advantage of extra protection against possible implementation security holes, but it has the disadvantages of requiring super-user privileges, of not being able to follow symbolic links that are either absolute or outside -of the new root path, and of complicating the preservation of usernames and groups -(see below). When "use chroot" is false, rsync will: (1) munge symlinks by +of the new root path, and of complicating the preservation of users and groups +by name (see below). +When "use chroot" is false, rsync will: (1) munge symlinks by default for security reasons (see "munge symlinks" for a way to turn this off, but only if you trust your users), (2) substitute leading slashes in absolute paths with the module's path (so that options such as @@ -139,27 +140,38 @@ args if rsync believes they would escape The default for "use chroot" is true, and is the safer choice (especially if the module is not read-only). -In order to preserve usernames and groupnames, rsync needs to be able to +When this option is enabled, rsync will not attempt to map users and groups +by name (by default), but instead copy IDs as though bf(--numeric-ids) had +been specified. In order to enable name-mapping, rsync needs to be able to use the standard library functions for looking up names and IDs (i.e. -code(getpwuid()), code(getgrgid()), code(getpwname()), and code(getgrnam())). This means a -process in the chroot namespace will need to have access to the resources +code(getpwuid()), code(getgrgid()), code(getpwname()), and code(getgrnam())). +This means the rsync +process in the chroot hierarchy will need to have access to the resources used by these library functions (traditionally /etc/passwd and -/etc/group). If these resources are not available, rsync will only be -able to copy the IDs, just as if the bf(--numeric-ids) option had been -specified. - -Note that you are free to setup user/group information in the chroot area -differently from your normal system. For example, you could abbreviate -the list of users and groups. Also, you can protect this information from -being downloaded/uploaded by adding an exclude rule to the rsyncd.conf file -(e.g. "exclude = /etc/**"). Note that having the exclusion affect uploads -is a relatively new feature in rsync, so make sure your daemon is -at least 2.6.3 to effect this. Also note that it is safest to exclude a -directory and all its contents combining the rule "/some/dir/" with the -rule "/some/dir/**" just to be sure that rsync will not allow deeper -access to some of the excluded files inside the directory (rsync tries to -do this automatically, but you might as well specify both to be extra -sure). +/etc/group, but perhaps additional dynamic libraries as well). + +If you copy the necessary resources into the module's chroot area, you +should protect them through your OS's normal user/group or ACL settings (to +prevent the rsync module's user from being able to change them), and then +hide them from the user's view via "exclude" (see how in the discussion of +that option). At that point it will be safe to enable the mapping of users +and groups by name using the "numeric ids" daemon option (see below). + +Note also that you are free to setup custom user/group information in the +chroot area that is different from your normal system. For example, you +could abbreviate the list of users and groups. + +dit(bf(numeric ids)) Enabling the "numeric ids" option disables the mapping +of users and groups by name for the current daemon module. This prevents +the daemon from trying to load any user/group-related files or libraries. +Enabling this option makes the transfer behave as if the client had passed +the bf(--numeric-ids) command-line option. By default, this parameter is +enabled for chroot modules and disabled for non-chroot modules. + +A chroot-enabled module should not have this option enabled unless you've +taken steps to ensure that the module has the necessary resources it needs +to translate names, and that it is not possible for a user to change those +resources. dit(bf(munge symlinks)) The "munge symlinks" option tells rsync to modify all incoming symlinks in a way that makes them unusable but recoverable @@ -286,6 +298,13 @@ from a daemon and files deleted on a dae it doesn't exclude files from being deleted on a client when receiving from a daemon. +When you want to exclude a directory and all its contents, it is safest to +use a rule that does both, such as "/some/dir/***" (the three stars tells +rsync to exclude the directory itself and everything inside it). This is +better than just excluding the directory alone with "/some/dir/", as it +helps to guard against attempts to trick rsync into accessing files deeper +in the hierarchy. + dit(bf(exclude from)) The "exclude from" option specifies a filename on the daemon that contains exclude patterns, one per line. This is only superficially equivalent --- a/uidlist.c +++ b/uidlist.c @@ -270,7 +270,7 @@ void send_uid_list(int f) { struct idlist *list; - if (numeric_ids) + if (numeric_ids > 0) return; if (preserve_uid) { @@ -311,7 +311,7 @@ void recv_uid_list(int f, struct file_li int id, i; char *name; - if (preserve_uid && !numeric_ids) { + if (preserve_uid && numeric_ids <= 0) { /* read the uid list */ while ((id = read_int(f)) != 0) { int len = read_byte(f); @@ -319,11 +319,15 @@ void recv_uid_list(int f, struct file_li if (!name) out_of_memory("recv_uid_list"); read_sbuf(f, name, len); + if (numeric_ids < 0) { + free(name); + name = NULL; + } recv_add_uid(id, name); /* node keeps name's memory */ } } - if (preserve_gid && !numeric_ids) { + if (preserve_gid && numeric_ids <= 0) { /* read the gid list */ while ((id = read_int(f)) != 0) { int len = read_byte(f); @@ -331,6 +335,10 @@ void recv_uid_list(int f, struct file_li if (!name) out_of_memory("recv_uid_list"); read_sbuf(f, name, len); + if (numeric_ids < 0) { + free(name); + name = NULL; + } recv_add_gid(id, name); /* node keeps name's memory */ } }