--- 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 */
 		}
 	}
