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(¤t_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