On 1/3/07, Bill @ 83 North <[EMAIL PROTECTED]> wrote:
I want to vary the path rsync uses based on the user that authenitcated to
the module.
[...]
Is there a function in rsync that does this?

No, the standard rsync does not support appending the username to the
module path.  However, this would be easy to implement in a custom
version of rsync.  In fact, I implemented it; the patch to rsync is
attached.

Is there an ability to use the
pre transfer execute to modify a variable to make that happen?

You could have the module path point to a symlink and have the
pre-xfer command modify that symlink to point to the appropriate
directory based on $RSYNC_USER_NAME.  However, concurrent connections
might fight over the symlink so that some clients would end up
accessing the wrong user's directory, so you should set max
connections = 1 for that module.

I feel that having a module that behaves differently for different
users is kludgy.  It would be better to have a different module for
each user but only show each user his/her own module.  To this end,
the daemon could ask a client requesting a module listing to provide a
username and password and then show the client the modules it could
access with those credentials.  The standard rsync daemon never asks
the client to provide credentials for a module listing, but it looks
like the standard rsync client would prompt the user  and provide the
credentials correctly; I can't speak for your GUI wrapper for the
client.

However, this technique is awkward to implement because checking a
single username and password against many modules (which might even
have different secrets files) would require significant rearrangements
to authenticate.c .  It would become even more awkward if support for
keyboard-interactive PAM authentication were added to the rsync
daemon, because authentication for different modules might even
require different PAM conversations.

Matt
Index: clientserver.c
===================================================================
RCS file: /cvsroot/rsync/clientserver.c,v
retrieving revision 1.194
diff -u -r1.194 clientserver.c
--- clientserver.c	25 Dec 2006 17:49:19 -0000	1.194
+++ clientserver.c	3 Jan 2007 23:12:37 -0000
@@ -271,6 +271,10 @@
 	return bp - buf;
 }
 
+/* Effective path of the current module, including the appended username
+ * if applicable */
+char *current_module_path;
+
 static int rsync_module(int f_in, int f_out, int i, char *addr, char *host)
 {
 	int argc = 0;
@@ -328,6 +332,13 @@
 
 	module_id = i;
 
+	if (lp_append_username(i) && lp_auth_users(i)) {
+		if (asprintf(&current_module_path, "%s/%s",
+			lp_path(i), auth_user) < 0)
+			out_of_memory("rsync_module");
+	} else
+		current_module_path = lp_path(i);
+
 	if (lp_read_only(i))
 		read_only = 1;
 
@@ -369,11 +380,11 @@
 	/* TODO: Perhaps take a list of gids, and make them into the
 	 * supplementary groups. */
 
-	if (use_chroot || (module_dirlen = strlen(lp_path(i))) == 1) {
+	if (use_chroot || (module_dirlen = strlen(current_module_path)) == 1) {
 		module_dirlen = 0;
 		set_filter_dir("/", 1);
 	} else
-		set_filter_dir(lp_path(i), module_dirlen);
+		set_filter_dir(current_module_path, module_dirlen);
 
 	p = lp_filter(i);
 	parse_rule(&server_filter_list, p, MATCHFLG_WORD_SPLIT,
@@ -403,7 +414,7 @@
 		char *modname, *modpath, *hostaddr, *hostname, *username;
 		int status;
 		if (asprintf(&modname, "RSYNC_MODULE_NAME=%s", name) < 0
-		 || asprintf(&modpath, "RSYNC_MODULE_PATH=%s", lp_path(i)) < 0
+		 || asprintf(&modpath, "RSYNC_MODULE_PATH=%s", current_module_path) < 0
 		 || asprintf(&hostaddr, "RSYNC_HOST_ADDR=%s", addr) < 0
 		 || asprintf(&hostname, "RSYNC_HOST_NAME=%s", host) < 0
 		 || asprintf(&username, "RSYNC_USER_NAME=%s", auth_user) < 0)
@@ -503,24 +514,24 @@
 		 * a warning, unless a "require chroot" flag is set,
 		 * in which case we fail.
 		 */
-		if (chroot(lp_path(i))) {
+		if (chroot(current_module_path)) {
 			rsyserr(FLOG, errno, "chroot %s failed",
-				lp_path(i));
+				current_module_path);
 			io_printf(f_out, "@ERROR: chroot failed\n");
 			return -1;
 		}
 
 		if (!push_dir("/", 0)) {
 			rsyserr(FLOG, errno, "chdir %s failed\n",
-				lp_path(i));
+				current_module_path);
 			io_printf(f_out, "@ERROR: chdir failed\n");
 			return -1;
 		}
 
 	} else {
-		if (!push_dir(lp_path(i), 0)) {
+		if (!push_dir(current_module_path, 0)) {
 			rsyserr(FLOG, errno, "chdir %s failed\n",
-				lp_path(i));
+				current_module_path);
 			io_printf(f_out, "@ERROR: chdir failed\n");
 			return -1;
 		}
Index: rsyncd.conf.5
===================================================================
RCS file: /cvsroot/rsync/rsyncd.conf.5,v
retrieving revision 1.143
diff -u -r1.143 rsyncd.conf.5
--- rsyncd.conf.5	14 Nov 2006 07:56:23 -0000	1.143
+++ rsyncd.conf.5	3 Jan 2007 23:12:39 -0000
@@ -350,6 +350,13 @@
 rsyncd.conf\-level username that differs from the remote-shell-level
 username when using a remote shell to connect to an rsync daemon.
 .IP 
+.IP "\fBappend username\fP"
+If \(lqappend username\(rq is true, the daemon will
+append the name of the user to the module path.  For example, if a user
+named \(lqfoo\(rq accesses a module whose path is given as \(lqbar/baz\(rq, the user
+will actually access \(lqbar/baz/foo\(rq.  This option is ignored if \(lqauth users\(rq
+is not set.
+.IP 
 .IP "\fBsecrets file\fP"
 The \(lqsecrets file\(rq option specifies the name of
 a file that contains the username:password pairs used for
Index: proto.h
===================================================================
RCS file: /cvsroot/rsync/proto.h,v
retrieving revision 1.328
diff -u -r1.328 proto.h
--- proto.h	29 Dec 2006 00:04:12 -0000	1.328
+++ proto.h	3 Jan 2007 23:12:39 -0000
@@ -187,6 +187,7 @@
 int lp_max_connections(int );
 int lp_max_verbosity(int );
 int lp_timeout(int );
+BOOL lp_append_username(int );
 BOOL lp_ignore_errors(int );
 BOOL lp_ignore_nonreadable(int );
 BOOL lp_list(int );
Index: loadparm.c
===================================================================
RCS file: /cvsroot/rsync/loadparm.c,v
retrieving revision 1.74
diff -u -r1.74 loadparm.c
--- loadparm.c	9 Nov 2006 02:39:29 -0000	1.74
+++ loadparm.c	3 Jan 2007 23:12:38 -0000
@@ -150,6 +150,7 @@
 	int syslog_facility;
 	int timeout;
 
+	BOOL append_username;
 	BOOL ignore_errors;
 	BOOL ignore_nonreadable;
 	BOOL list;
@@ -197,6 +198,7 @@
  /* syslog_facility; */		LOG_DAEMON,
  /* timeout; */			0,
 
+ /* append_username; */		False,
  /* ignore_errors; */		False,
  /* ignore_nonreadable; */	False,
  /* list; */			True,
@@ -293,6 +295,7 @@
  {"port",              P_INTEGER,P_GLOBAL,&Globals.rsync_port,         NULL,0},
  {"socket options",    P_STRING, P_GLOBAL,&Globals.socket_options,     NULL,0},
 
+ {"append username",   P_BOOL,   P_LOCAL, &sDefault.append_username,   NULL,0},
  {"auth users",        P_STRING, P_LOCAL, &sDefault.auth_users,        NULL,0},
  {"comment",           P_STRING, P_LOCAL, &sDefault.comment,           NULL,0},
  {"dont compress",     P_STRING, P_LOCAL, &sDefault.dont_compress,     NULL,0},
@@ -412,6 +415,7 @@
 FN_LOCAL_INTEGER(lp_max_verbosity, max_verbosity)
 FN_LOCAL_INTEGER(lp_timeout, timeout)
 
+FN_LOCAL_BOOL(lp_append_username, append_username)
 FN_LOCAL_BOOL(lp_ignore_errors, ignore_errors)
 FN_LOCAL_BOOL(lp_ignore_nonreadable, ignore_nonreadable)
 FN_LOCAL_BOOL(lp_list, list)
Index: log.c
===================================================================
RCS file: /cvsroot/rsync/log.c,v
retrieving revision 1.170
diff -u -r1.170 log.c
--- log.c	23 Dec 2006 20:48:29 -0000	1.170
+++ log.c	3 Jan 2007 23:12:38 -0000
@@ -45,6 +45,7 @@
 extern int logfile_format_has_o_or_i;
 extern mode_t orig_umask;
 extern char *auth_user;
+extern char *current_module_path;
 extern char *stdout_format;
 extern char *logfile_format;
 extern char *logfile_name;
@@ -575,7 +576,7 @@
 			n = timestring(time(NULL));
 			break;
 		case 'P':
-			n = lp_path(module_id);
+			n = current_module_path;
 			break;
 		case 'u':
 			n = auth_user;
Index: util.c
===================================================================
RCS file: /cvsroot/rsync/util.c,v
retrieving revision 1.220
diff -u -r1.220 util.c
--- util.c	28 Nov 2006 19:34:01 -0000	1.220
+++ util.c	3 Jan 2007 23:12:40 -0000
@@ -31,6 +31,7 @@
 extern int human_readable;
 extern unsigned int module_dirlen;
 extern mode_t orig_umask;
+extern char *current_module_path;
 extern char *partial_dir;
 extern struct filter_list_struct server_filter_list;
 
@@ -750,7 +751,7 @@
  * rootdir will be ignored to avoid expansion of the string.
  *
  * The rootdir string contains a value to use in place of a leading slash.
- * Specify NULL to get the default of lp_path(module_id).
+ * Specify NULL to get the default of current_module_path.
  *
  * The depth var is a count of how many '..'s to allow at the start of the
  * path.  If symlink is set, combine its value with the "p" value to get
@@ -779,7 +780,7 @@
 		int plen = strlen(p);
 		if (*p == '/') {
 			if (!rootdir)
-				rootdir = lp_path(module_id);
+				rootdir = current_module_path;
 			rlen = strlen(rootdir);
 			depth = 0;
 			p++;
Index: rsyncd.conf.yo
===================================================================
RCS file: /cvsroot/rsync/rsyncd.conf.yo,v
retrieving revision 1.144
diff -u -r1.144 rsyncd.conf.yo
--- rsyncd.conf.yo	14 Nov 2006 07:55:47 -0000	1.144
+++ rsyncd.conf.yo	3 Jan 2007 23:12:39 -0000
@@ -305,6 +305,12 @@
 rsyncd.conf-level username that differs from the remote-shell-level
 username when using a remote shell to connect to an rsync daemon.
 
+dit(bf(append username)) If "append username" is true, the daemon will
+append the name of the user to the module path.  For example, if a user
+named "foo" accesses a module whose path is given as "bar/baz", the user
+will actually access "bar/baz/foo".  This option is ignored if "auth users"
+is not set.
+
 dit(bf(secrets file)) The "secrets file" option specifies the name of
 a file that contains the username:password pairs used for
 authenticating this module. This file is only consulted if the "auth
Index: patches/ODBC-dblog.diff
===================================================================
RCS file: /cvsroot/rsync/patches/ODBC-dblog.diff,v
retrieving revision 1.61
diff -u -r1.61 ODBC-dblog.diff
--- patches/ODBC-dblog.diff	28 Dec 2006 16:11:25 -0000	1.61
+++ patches/ODBC-dblog.diff	3 Jan 2007 23:12:40 -0000
@@ -604,13 +604,13 @@
 +			snprintf(strSqlStatement, sizeof strSqlStatement,
 +			    "INSERT INTO %s (id, date, ip_address, username, module_name, module_path, process_id) VALUES ('%ld', '%s', '%s', '%s','%s','%s','%d');",
 +			    lp_session_table_name(module_id), session_id, timestring(time(NULL)), client_addr(0),
-+			    auth_user, lp_name(module_id), lp_path(module_id), getpid());
++			    auth_user, lp_name(module_id), current_module_path, getpid());
 +		} else {
 +			/* Otherwise the ID gets created automatically, and we get the ID it used after the insert. */
 +			snprintf(strSqlStatement, sizeof strSqlStatement,
 +			    "INSERT INTO %s (date, ip_address, username, module_name, module_path, process_id) VALUES ('%s', '%s', '%s', '%s','%s','%d');",
 +			    lp_session_table_name(module_id), timestring(time(NULL)), client_addr(0), auth_user,
-+			    lp_name(module_id), lp_path(module_id), getpid());
++			    lp_name(module_id), current_module_path, getpid());
 +		}
 +
 +		/* Insert the new session into the database */
-- 
To unsubscribe or change options: https://lists.samba.org/mailman/listinfo/rsync
Before posting, read: http://www.catb.org/~esr/faqs/smart-questions.html

Reply via email to