extern gid_t our_gid;
char *auth_user;
+char *daemon_auth_choices;
int read_only = 0;
int module_id = -1;
int pid_file_fd = -1;
static int exchange_protocols(int f_in, int f_out, char *buf, size_t bufsiz, int am_client)
{
int remote_sub = -1;
-#if SUBPROTOCOL_VERSION != 0
- int our_sub = protocol_version < PROTOCOL_VERSION ? 0 : SUBPROTOCOL_VERSION;
-#else
- int our_sub = 0;
-#endif
+ int our_sub = get_subprotocol_version();
- io_printf(f_out, "@RSYNCD: %d.%d\n", protocol_version, our_sub);
+ output_daemon_greeting(f_out, am_client);
if (!am_client) {
char *motd = lp_motd_file();
if (motd && *motd) {
}
if (remote_sub < 0) {
- if (remote_protocol == 30) {
+ if (remote_protocol >= 30) {
if (am_client)
- rprintf(FERROR, "rsync: server is speaking an incompatible beta of protocol 30\n");
+ rprintf(FERROR, "rsync: the server omitted the subprotocol value: %s\n", buf);
else
- io_printf(f_out, "@ERROR: your client is speaking an incompatible beta of protocol 30\n");
+ io_printf(f_out, "@ERROR: your client omitted the subprotocol value: %s\n", buf);
return -1;
}
remote_sub = 0;
}
+ daemon_auth_choices = strchr(buf + 9, ' ');
+ if (daemon_auth_choices) {
+ char *cp;
+ daemon_auth_choices = strdup(daemon_auth_choices + 1);
+ if ((cp = strchr(daemon_auth_choices, '\n')) != NULL)
+ *cp = '\0';
+ } else if (remote_protocol > 31) {
+ if (am_client)
+ rprintf(FERROR, "rsync: the server omitted the digest name list: %s\n", buf);
+ else
+ io_printf(f_out, "@ERROR: your client omitted the digest name list: %s\n", buf);
+ return -1;
+ }
+
if (protocol_version > remote_protocol) {
protocol_version = remote_protocol;
if (remote_sub)
if (rl_nulls) {
for (i = 0; i < sargc; i++) {
- if (!sargs[i]) /* stop at --protect-args NULL */
+ if (!sargs[i]) /* stop at --secluded-args NULL */
break;
write_sbuf(f_out, sargs[i]);
write_byte(f_out, 0);
}
#endif
-static void set_env_str(const char *var, const char *str)
+void set_env_str(const char *var, const char *str)
{
#ifdef HAVE_SETENV
if (setenv(var, str, 1) < 0)
int set_uid;
char *p, *err_msg = NULL;
char *name = lp_name(i);
- int use_chroot = lp_use_chroot(i);
+ int use_chroot = lp_use_chroot(i); /* might be 1 (yes), 0 (no), or -1 (unset) */
int ret, pre_exec_arg_fd = -1, pre_exec_error_fd = -1;
int save_munge_symlinks;
pid_t pre_exec_pid = 0;
io_printf(f_out, "@ERROR: no path setting.\n");
return -1;
}
+ if (use_chroot < 0) {
+ if (strstr(module_dir, "/./") != NULL)
+ use_chroot = 1; /* The module is expecting a chroot inner & outer path. */
+ else if (chroot("/") < 0) {
+ rprintf(FLOG, "chroot test failed: %s. "
+ "Switching 'use chroot' from unset to false.\n",
+ strerror(errno));
+ use_chroot = 0;
+ } else {
+ if (chdir("/") < 0)
+ rsyserr(FLOG, errno, "chdir(\"/\") failed");
+ use_chroot = 1;
+ }
+ }
if (use_chroot) {
if ((p = strstr(module_dir, "/./")) != NULL) {
*p = '\0'; /* Temporary... */
}
if (use_chroot) {
- /*
- * XXX: The 'use chroot' flag is a fairly reliable
- * source of confusion, because it fails under two
- * important circumstances: running as non-root,
- * running on Win32 (or possibly others). On the
- * other hand, if you are running as root, then it
- * might be better to always use chroot.
- *
- * So, perhaps if we can't chroot we should just issue
- * a warning, unless a "require chroot" flag is set,
- * in which case we fail.
- */
if (chroot(module_chdir)) {
- rsyserr(FLOG, errno, "chroot %s failed", module_chdir);
+ rsyserr(FLOG, errno, "chroot(\"%s\") failed", module_chdir);
io_printf(f_out, "@ERROR: chroot failed\n");
return -1;
}
if (!change_dir(module_chdir, CD_NORMAL))
return path_failure(f_out, module_chdir, True);
- if (module_dirlen || (!use_chroot && !*lp_daemon_chroot()))
+ if (module_dirlen)
sanitize_paths = 1;
if ((munge_symlinks = lp_munge_symlinks(module_id)) < 0)
p = lp_daemon_chroot();
if (*p) {
log_init(0); /* Make use we've initialized syslog before chrooting. */
- if (chroot(p) < 0 || chdir("/") < 0) {
- rsyserr(FLOG, errno, "daemon chroot %s failed", p);
+ if (chroot(p) < 0) {
+ rsyserr(FLOG, errno, "daemon chroot(\"%s\") failed", p);
+ return -1;
+ }
+ if (chdir("/") < 0) {
+ rsyserr(FLOG, errno, "daemon chdir(\"/\") failed");
return -1;
}
}