*
* Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org>
* Copyright (C) 2001-2002 Martin Pool <mbp@samba.org>
- * Copyright (C) 2002-2009 Wayne Davison
+ * Copyright (C) 2002-2018 Wayne Davison
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
extern char *iconv_opt;
extern iconv_t ic_send, ic_recv;
#endif
-
-#define MAX_GID_LIST 32
+extern uid_t our_uid;
+extern gid_t our_gid;
char *auth_user;
int read_only = 0;
static struct sigaction sigact;
#endif
-static gid_t gid_list[MAX_GID_LIST];
-static int gid_count = 0;
+static item_list gid_list = EMPTY_ITEM_LIST;
/* Used when "reverse lookup" is off. */
const char undetermined_hostname[] = "UNDETERMINED";
static int path_failure(int f_out, const char *dir, BOOL was_chdir)
{
if (was_chdir)
- rsyserr(FLOG, errno, "chdir %s failed\n", dir);
+ rsyserr(FLOG, errno, "chdir %s failed", dir);
else
rprintf(FLOG, "normalize_path(%s) failed\n", dir);
io_printf(f_out, "@ERROR: chdir failed\n");
static int add_a_group(int f_out, const char *gname)
{
- gid_t gid;
+ gid_t gid, *gid_p;
if (!group_to_gid(gname, &gid, True)) {
rprintf(FLOG, "Invalid gid %s\n", gname);
io_printf(f_out, "@ERROR: invalid gid %s\n", gname);
return -1;
}
- if (gid_count == MAX_GID_LIST) {
- rprintf(FLOG, "Too many groups specified via gid parameter.\n");
- io_printf(f_out, "@ERROR: too many groups\n");
- return -1;
- }
- gid_list[gid_count++] = gid;
+ gid_p = EXPAND_ITEM_LIST(&gid_list, gid_t, -32);
+ *gid_p = gid;
return 0;
}
static int want_all_groups(int f_out, uid_t uid)
{
const char *err;
- gid_count = MAX_GID_LIST;
- if ((err = getallgroups(uid, gid_list, &gid_count)) != NULL) {
+ if ((err = getallgroups(uid, &gid_list)) != NULL) {
rsyserr(FLOG, errno, "%s", err);
io_printf(f_out, "@ERROR: %s\n", err);
return -1;
static struct passwd *want_all_groups(int f_out, uid_t uid)
{
struct passwd *pw;
+ gid_t *gid_p;
if ((pw = getpwuid(uid)) == NULL) {
rsyserr(FLOG, errno, "getpwuid failed");
io_printf(f_out, "@ERROR: getpwuid failed\n");
return NULL;
}
- /* Start with the default group and initgroups() will add the reset. */
- gid_count = 1;
- gid_list[0] = pw->pw_gid;
+ /* Start with the default group and initgroups() will add the rest. */
+ gid_p = EXPAND_ITEM_LIST(&gid_list, gid_t, -32);
+ *gid_p = pw->pw_gid;
return pw;
}
#endif
} else
set_uid = 0;
- p = *lp_gid(i) ? strtok(lp_gid(i), ", ") : NULL;
+ p = *lp_gid(i) ? conf_strtok(lp_gid(i)) : NULL;
if (p) {
/* The "*" gid must be the first item in the list. */
if (strcmp(p, "*") == 0) {
#endif
} else if (add_a_group(f_out, p) < 0)
return -1;
- while ((p = strtok(NULL, ", ")) != NULL) {
+ while ((p = conf_strtok(NULL)) != NULL) {
#if defined HAVE_INITGROUPS && !defined HAVE_GETGROUPLIST
if (pw) {
rprintf(FLOG, "This rsync cannot add groups after \"*\".\n");
log_init(1);
#ifdef HAVE_PUTENV
- if (*lp_prexfer_exec(i) || *lp_postxfer_exec(i)) {
+ if ((*lp_prexfer_exec(i) || *lp_postxfer_exec(i)) && !getenv("RSYNC_NO_XFER_EXEC")) {
int status;
/* For post-xfer exec, fork a new process to run the rsync
else
status = -1;
set_env_num("RSYNC_EXIT_STATUS", status);
- if (system(lp_postxfer_exec(i)) < 0)
+ if (shell_exec(lp_postxfer_exec(i)) < 0)
status = -1;
_exit(status);
}
close(STDIN_FILENO);
dup2(pre_exec_error_fd, STDOUT_FILENO);
close(pre_exec_error_fd);
- status = system(lp_prexfer_exec(i));
+ status = shell_exec(lp_prexfer_exec(i));
if (!WIFEXITED(status))
_exit(1);
_exit(WEXITSTATUS(status));
if (!change_dir(module_chdir, CD_NORMAL))
return path_failure(f_out, module_chdir, True);
- if (module_dirlen || !use_chroot)
+ if (module_dirlen || (!use_chroot && !*lp_daemon_chroot()))
sanitize_paths = 1;
if ((munge_symlinks = lp_munge_symlinks(i)) < 0)
}
}
- if (gid_count) {
- if (setgid(gid_list[0])) {
- rsyserr(FLOG, errno, "setgid %ld failed", (long)gid_list[0]);
+ if (gid_list.count) {
+ gid_t *gid_array = gid_list.items;
+ if (setgid(gid_array[0])) {
+ rsyserr(FLOG, errno, "setgid %ld failed", (long)gid_array[0]);
io_printf(f_out, "@ERROR: setgid failed\n");
return -1;
}
#ifdef HAVE_SETGROUPS
/* Set the group(s) we want to be active. */
- if (setgroups(gid_count, gid_list)) {
+ if (setgroups(gid_list.count, gid_array)) {
rsyserr(FLOG, errno, "setgroups failed");
io_printf(f_out, "@ERROR: setgroups failed\n");
return -1;
return -1;
}
#endif
+ our_gid = MY_GID();
}
if (set_uid) {
return -1;
}
- am_root = (MY_UID() == 0);
+ our_uid = MY_UID();
+ am_root = (our_uid == 0);
}
if (lp_temp_dir(i) && *lp_temp_dir(i)) {
{
char line[1024];
const char *addr, *host;
+ char *p;
int i;
io_set_sock_fds(f_in, f_out);
if (!load_config(0))
exit_cleanup(RERR_SYNTAX);
+ 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);
+ return -1;
+ }
+ }
+ p = lp_daemon_gid();
+ if (*p) {
+ gid_t gid;
+ if (!group_to_gid(p, &gid, True)) {
+ rprintf(FLOG, "Invalid daemon gid: %s\n", p);
+ return -1;
+ }
+ if (setgid(gid) < 0) {
+ rsyserr(FLOG, errno, "Unable to set group to daemon gid %ld", (long)gid);
+ return -1;
+ }
+ our_gid = MY_GID();
+ }
+ p = lp_daemon_uid();
+ if (*p) {
+ uid_t uid;
+ if (!user_to_uid(p, &uid, True)) {
+ rprintf(FLOG, "Invalid daemon uid: %s\n", p);
+ return -1;
+ }
+ if (setuid(uid) < 0) {
+ rsyserr(FLOG, errno, "Unable to set user to daemon uid %ld", (long)uid);
+ return -1;
+ }
+ our_uid = MY_UID();
+ am_root = (our_uid == 0);
+ }
+
addr = client_addr(f_in);
host = lp_reverse_lookup(-1) ? client_name(f_in) : undetermined_hostname;
rprintf(FLOG, "connect from %s (%s)\n", host, addr);