Annotation of embedaddon/rsync/clientserver.c, revision 1.1.1.2
1.1 misho 1: /*
2: * The socket based protocol for setting up a connection with rsyncd.
3: *
4: * Copyright (C) 1998-2001 Andrew Tridgell <tridge@samba.org>
5: * Copyright (C) 2001-2002 Martin Pool <mbp@samba.org>
1.1.1.2 ! misho 6: * Copyright (C) 2002-2013 Wayne Davison
1.1 misho 7: *
8: * This program is free software; you can redistribute it and/or modify
9: * it under the terms of the GNU General Public License as published by
10: * the Free Software Foundation; either version 3 of the License, or
11: * (at your option) any later version.
12: *
13: * This program is distributed in the hope that it will be useful,
14: * but WITHOUT ANY WARRANTY; without even the implied warranty of
15: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16: * GNU General Public License for more details.
17: *
18: * You should have received a copy of the GNU General Public License along
19: * with this program; if not, visit the http://fsf.org website.
20: */
21:
22: #include "rsync.h"
1.1.1.2 ! misho 23: #include "itypes.h"
1.1 misho 24:
25: extern int quiet;
26: extern int dry_run;
27: extern int output_motd;
28: extern int list_only;
29: extern int am_sender;
30: extern int am_server;
31: extern int am_daemon;
32: extern int am_root;
33: extern int rsync_port;
34: extern int protect_args;
35: extern int ignore_errors;
36: extern int preserve_xattrs;
37: extern int kluge_around_eof;
38: extern int daemon_over_rsh;
1.1.1.2 ! misho 39: extern int munge_symlinks;
1.1 misho 40: extern int sanitize_paths;
41: extern int numeric_ids;
42: extern int filesfrom_fd;
43: extern int remote_protocol;
44: extern int protocol_version;
45: extern int io_timeout;
46: extern int no_detach;
47: extern int write_batch;
48: extern int default_af_hint;
49: extern int logfile_format_has_i;
50: extern int logfile_format_has_o_or_i;
51: extern char *bind_address;
52: extern char *config_file;
53: extern char *logfile_format;
54: extern char *files_from;
55: extern char *tmpdir;
56: extern struct chmod_mode_struct *chmod_modes;
1.1.1.2 ! misho 57: extern filter_rule_list daemon_filter_list;
1.1 misho 58: #ifdef ICONV_OPTION
59: extern char *iconv_opt;
60: extern iconv_t ic_send, ic_recv;
61: #endif
62:
1.1.1.2 ! misho 63: #define MAX_GID_LIST 32
! 64:
1.1 misho 65: char *auth_user;
66: int read_only = 0;
67: int module_id = -1;
68: struct chmod_mode_struct *daemon_chmod_modes;
69:
70: /* module_dirlen is the length of the module_dir string when in daemon
71: * mode and module_dir is not "/"; otherwise 0. (Note that a chroot-
72: * enabled module can have a non-"/" module_dir these days.) */
73: char *module_dir = NULL;
74: unsigned int module_dirlen = 0;
75:
76: char *full_module_path;
77:
78: static int rl_nulls = 0;
79:
80: #ifdef HAVE_SIGACTION
81: static struct sigaction sigact;
82: #endif
83:
1.1.1.2 ! misho 84: static gid_t gid_list[MAX_GID_LIST];
! 85: static int gid_count = 0;
! 86:
! 87: /* Used when "reverse lookup" is off. */
! 88: const char undetermined_hostname[] = "UNDETERMINED";
! 89:
1.1 misho 90: /**
91: * Run a client connected to an rsyncd. The alternative to this
92: * function for remote-shell connections is do_cmd().
93: *
94: * After negotiating which module to use and reading the server's
95: * motd, this hands over to client_run(). Telling the server the
96: * module will cause it to chroot/setuid/etc.
97: *
98: * Instead of doing a transfer, the client may at this stage instead
99: * get a listing of remote modules and exit.
100: *
101: * @return -1 for error in startup, or the result of client_run().
102: * Either way, it eventually gets passed to exit_cleanup().
103: **/
104: int start_socket_client(char *host, int remote_argc, char *remote_argv[],
105: int argc, char *argv[])
106: {
107: int fd, ret;
108: char *p, *user = NULL;
109:
110: /* This is redundant with code in start_inband_exchange(), but this
111: * short-circuits a problem in the client before we open a socket,
112: * and the extra check won't hurt. */
113: if (**remote_argv == '/') {
114: rprintf(FERROR,
115: "ERROR: The remote path must start with a module name not a /\n");
116: return -1;
117: }
118:
119: if ((p = strrchr(host, '@')) != NULL) {
120: user = host;
121: host = p+1;
122: *p = '\0';
123: }
124:
125: fd = open_socket_out_wrapped(host, rsync_port, bind_address,
126: default_af_hint);
127: if (fd == -1)
128: exit_cleanup(RERR_SOCKETIO);
129:
130: #ifdef ICONV_CONST
131: setup_iconv();
132: #endif
133:
134: ret = start_inband_exchange(fd, fd, user, remote_argc, remote_argv);
135:
136: return ret ? ret : client_run(fd, fd, -1, argc, argv);
137: }
138:
139: static int exchange_protocols(int f_in, int f_out, char *buf, size_t bufsiz, int am_client)
140: {
141: int remote_sub = -1;
142: #if SUBPROTOCOL_VERSION != 0
143: int our_sub = protocol_version < PROTOCOL_VERSION ? 0 : SUBPROTOCOL_VERSION;
144: #else
145: int our_sub = 0;
146: #endif
147: char *motd;
148:
149: io_printf(f_out, "@RSYNCD: %d.%d\n", protocol_version, our_sub);
150:
151: if (!am_client) {
152: motd = lp_motd_file();
153: if (motd && *motd) {
154: FILE *f = fopen(motd,"r");
155: while (f && !feof(f)) {
156: int len = fread(buf, 1, bufsiz - 1, f);
157: if (len > 0)
158: write_buf(f_out, buf, len);
159: }
160: if (f)
161: fclose(f);
162: write_sbuf(f_out, "\n");
163: }
164: }
165:
166: /* This strips the \n. */
1.1.1.2 ! misho 167: if (!read_line_old(f_in, buf, bufsiz, 0)) {
1.1 misho 168: if (am_client)
169: rprintf(FERROR, "rsync: did not see server greeting\n");
170: return -1;
171: }
172:
173: if (sscanf(buf, "@RSYNCD: %d.%d", &remote_protocol, &remote_sub) < 1) {
174: if (am_client)
175: rprintf(FERROR, "rsync: server sent \"%s\" rather than greeting\n", buf);
176: else
177: io_printf(f_out, "@ERROR: protocol startup error\n");
178: return -1;
179: }
180:
181: if (remote_sub < 0) {
182: if (remote_protocol == 30) {
183: if (am_client)
184: rprintf(FERROR, "rsync: server is speaking an incompatible beta of protocol 30\n");
185: else
186: io_printf(f_out, "@ERROR: your client is speaking an incompatible beta of protocol 30\n");
187: return -1;
188: }
189: remote_sub = 0;
190: }
191:
192: if (protocol_version > remote_protocol) {
193: protocol_version = remote_protocol;
194: if (remote_sub)
195: protocol_version--;
196: } else if (protocol_version == remote_protocol) {
197: if (remote_sub != our_sub)
198: protocol_version--;
199: }
200: #if SUBPROTOCOL_VERSION != 0
201: else if (protocol_version < remote_protocol) {
202: if (our_sub)
203: protocol_version--;
204: }
205: #endif
206:
207: if (protocol_version >= 30)
208: rl_nulls = 1;
209:
210: return 0;
211: }
212:
213: int start_inband_exchange(int f_in, int f_out, const char *user, int argc, char *argv[])
214: {
215: int i, modlen;
216: char line[BIGPATHBUFLEN];
217: char *sargs[MAX_ARGS];
218: int sargc = 0;
219: char *p, *modname;
220:
221: assert(argc > 0 && *argv != NULL);
222:
223: if (**argv == '/') {
224: rprintf(FERROR,
225: "ERROR: The remote path must start with a module name\n");
226: return -1;
227: }
228:
229: if (!(p = strchr(*argv, '/')))
230: modlen = strlen(*argv);
231: else
232: modlen = p - *argv;
233:
234: if (!(modname = new_array(char, modlen+1+1))) /* room for '/' & '\0' */
235: out_of_memory("start_inband_exchange");
236: strlcpy(modname, *argv, modlen + 1);
237: modname[modlen] = '/';
238: modname[modlen+1] = '\0';
239:
240: if (!user)
241: user = getenv("USER");
242: if (!user)
243: user = getenv("LOGNAME");
244:
245: if (exchange_protocols(f_in, f_out, line, sizeof line, 1) < 0)
246: return -1;
247:
248: /* set daemon_over_rsh to false since we need to build the
249: * true set of args passed through the rsh/ssh connection;
250: * this is a no-op for direct-socket-connection mode */
251: daemon_over_rsh = 0;
252: server_options(sargs, &sargc);
253:
254: if (sargc >= MAX_ARGS - 2)
255: goto arg_overflow;
256:
257: sargs[sargc++] = ".";
258:
259: while (argc > 0) {
260: if (sargc >= MAX_ARGS - 1) {
261: arg_overflow:
262: rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
263: exit_cleanup(RERR_SYNTAX);
264: }
265: if (strncmp(*argv, modname, modlen) == 0
266: && argv[0][modlen] == '\0')
267: sargs[sargc++] = modname; /* we send "modname/" */
268: else if (**argv == '-') {
269: if (asprintf(sargs + sargc++, "./%s", *argv) < 0)
270: out_of_memory("start_inband_exchange");
271: } else
272: sargs[sargc++] = *argv;
273: argv++;
274: argc--;
275: }
276:
277: sargs[sargc] = NULL;
278:
1.1.1.2 ! misho 279: if (DEBUG_GTE(CMD, 1))
1.1 misho 280: print_child_argv("sending daemon args:", sargs);
281:
282: io_printf(f_out, "%.*s\n", modlen, modname);
283:
284: /* Old servers may just drop the connection here,
285: rather than sending a proper EXIT command. Yuck. */
286: kluge_around_eof = list_only && protocol_version < 25 ? 1 : 0;
287:
288: while (1) {
1.1.1.2 ! misho 289: if (!read_line_old(f_in, line, sizeof line, 0)) {
1.1 misho 290: rprintf(FERROR, "rsync: didn't get server startup line\n");
291: return -1;
292: }
293:
294: if (strncmp(line,"@RSYNCD: AUTHREQD ",18) == 0) {
295: auth_client(f_out, user, line+18);
296: continue;
297: }
298:
299: if (strcmp(line,"@RSYNCD: OK") == 0)
300: break;
301:
302: if (strcmp(line,"@RSYNCD: EXIT") == 0) {
303: /* This is sent by recent versions of the
304: * server to terminate the listing of modules.
305: * We don't want to go on and transfer
306: * anything; just exit. */
307: exit(0);
308: }
309:
310: if (strncmp(line, "@ERROR", 6) == 0) {
311: rprintf(FERROR, "%s\n", line);
312: /* This is always fatal; the server will now
313: * close the socket. */
314: return -1;
315: }
316:
317: /* This might be a MOTD line or a module listing, but there is
318: * no way to differentiate it. The manpage mentions this. */
319: if (output_motd)
320: rprintf(FINFO, "%s\n", line);
321: }
322: kluge_around_eof = 0;
323:
324: if (rl_nulls) {
325: for (i = 0; i < sargc; i++) {
326: if (!sargs[i]) /* stop at --protect-args NULL */
327: break;
328: write_sbuf(f_out, sargs[i]);
329: write_byte(f_out, 0);
330: }
331: write_byte(f_out, 0);
332: } else {
333: for (i = 0; i < sargc; i++)
334: io_printf(f_out, "%s\n", sargs[i]);
335: write_sbuf(f_out, "\n");
336: }
337:
338: if (protect_args)
339: send_protected_args(f_out, sargs);
340:
341: if (protocol_version < 23) {
342: if (protocol_version == 22 || !am_sender)
1.1.1.2 ! misho 343: io_start_multiplex_in(f_in);
1.1 misho 344: }
345:
346: free(modname);
347:
348: return 0;
349: }
350:
1.1.1.2 ! misho 351: static char *finish_pre_exec(pid_t pid, int write_fd, int read_fd, char *request,
1.1 misho 352: char **early_argv, char **argv)
353: {
1.1.1.2 ! misho 354: char buf[BIGPATHBUFLEN], *bp;
! 355: int j = 0, status = -1, msglen = sizeof buf - 1;
1.1 misho 356:
357: if (!request)
358: request = "(NONE)";
359:
1.1.1.2 ! misho 360: write_buf(write_fd, request, strlen(request)+1);
1.1 misho 361: if (early_argv) {
362: for ( ; *early_argv; early_argv++)
1.1.1.2 ! misho 363: write_buf(write_fd, *early_argv, strlen(*early_argv)+1);
1.1 misho 364: j = 1; /* Skip arg0 name in argv. */
365: }
1.1.1.2 ! misho 366: for ( ; argv[j]; j++)
! 367: write_buf(write_fd, argv[j], strlen(argv[j])+1);
! 368: write_byte(write_fd, 0);
! 369:
! 370: close(write_fd);
! 371:
! 372: /* Read the stdout from the pre-xfer exec program. This it is only
! 373: * displayed to the user if the script also returns an error status. */
! 374: for (bp = buf; msglen > 0; msglen -= j) {
! 375: if ((j = read(read_fd, bp, msglen)) <= 0) {
! 376: if (j == 0)
! 377: break;
! 378: if (errno == EINTR)
! 379: continue;
! 380: break; /* Just ignore the read error for now... */
! 381: }
! 382: bp += j;
! 383: if (j > 1 && bp[-1] == '\n' && bp[-2] == '\r') {
! 384: bp--;
! 385: j--;
! 386: bp[-1] = '\n';
! 387: }
1.1 misho 388: }
1.1.1.2 ! misho 389: *bp = '\0';
1.1 misho 390:
1.1.1.2 ! misho 391: close(read_fd);
1.1 misho 392:
393: if (wait_process(pid, &status, 0) < 0
394: || !WIFEXITED(status) || WEXITSTATUS(status) != 0) {
395: char *e;
1.1.1.2 ! misho 396: if (asprintf(&e, "pre-xfer exec returned failure (%d)%s%s%s\n%s",
1.1 misho 397: status, status < 0 ? ": " : "",
1.1.1.2 ! misho 398: status < 0 ? strerror(errno) : "",
! 399: *buf ? ":" : "", buf) < 0)
! 400: return "out_of_memory in finish_pre_exec\n";
1.1 misho 401: return e;
402: }
403: return NULL;
404: }
405:
1.1.1.2 ! misho 406: #ifdef HAVE_PUTENV
1.1 misho 407: static int read_arg_from_pipe(int fd, char *buf, int limit)
408: {
409: char *bp = buf, *eob = buf + limit - 1;
410:
411: while (1) {
1.1.1.2 ! misho 412: int got = read(fd, bp, 1);
! 413: if (got != 1) {
! 414: if (got < 0 && errno == EINTR)
! 415: continue;
! 416: return -1;
! 417: }
! 418: if (*bp == '\0')
! 419: break;
! 420: if (bp < eob)
! 421: bp++;
1.1 misho 422: }
423: *bp = '\0';
424:
425: return bp - buf;
426: }
1.1.1.2 ! misho 427: #endif
1.1 misho 428:
429: static int path_failure(int f_out, const char *dir, BOOL was_chdir)
430: {
431: if (was_chdir)
432: rsyserr(FLOG, errno, "chdir %s failed\n", dir);
433: else
434: rprintf(FLOG, "normalize_path(%s) failed\n", dir);
435: io_printf(f_out, "@ERROR: chdir failed\n");
436: return -1;
437: }
438:
1.1.1.2 ! misho 439: static int add_a_group(int f_out, const char *gname)
! 440: {
! 441: gid_t gid;
! 442: if (!group_to_gid(gname, &gid, True)) {
! 443: rprintf(FLOG, "Invalid gid %s\n", gname);
! 444: io_printf(f_out, "@ERROR: invalid gid %s\n", gname);
! 445: return -1;
! 446: }
! 447: if (gid_count == MAX_GID_LIST) {
! 448: rprintf(FLOG, "Too many groups specified via gid parameter.\n");
! 449: io_printf(f_out, "@ERROR: too many groups\n");
! 450: return -1;
! 451: }
! 452: gid_list[gid_count++] = gid;
! 453: return 0;
! 454: }
! 455:
! 456: #ifdef HAVE_GETGROUPLIST
! 457: static int want_all_groups(int f_out, uid_t uid)
! 458: {
! 459: const char *err;
! 460: gid_count = MAX_GID_LIST;
! 461: if ((err = getallgroups(uid, gid_list, &gid_count)) != NULL) {
! 462: rsyserr(FLOG, errno, "%s", err);
! 463: io_printf(f_out, "@ERROR: %s\n", err);
! 464: return -1;
! 465: }
! 466: return 0;
! 467: }
! 468: #elif defined HAVE_INITGROUPS
! 469: static struct passwd *want_all_groups(int f_out, uid_t uid)
! 470: {
! 471: struct passwd *pw;
! 472: if ((pw = getpwuid(uid)) == NULL) {
! 473: rsyserr(FLOG, errno, "getpwuid failed");
! 474: io_printf(f_out, "@ERROR: getpwuid failed\n");
! 475: return NULL;
! 476: }
! 477: /* Start with the default group and initgroups() will add the reset. */
! 478: gid_count = 1;
! 479: gid_list[0] = pw->pw_gid;
! 480: return pw;
! 481: }
! 482: #endif
! 483:
! 484: static void set_env_str(const char *var, const char *str)
! 485: {
! 486: #ifdef HAVE_PUTENV
! 487: char *mem;
! 488: if (asprintf(&mem, "%s=%s", var, str) < 0)
! 489: out_of_memory("set_env_str");
! 490: putenv(mem);
! 491: #endif
! 492: }
! 493:
! 494: #ifdef HAVE_PUTENV
! 495: static void set_env_num(const char *var, long num)
! 496: {
! 497: char *mem;
! 498: if (asprintf(&mem, "%s=%ld", var, num) < 0)
! 499: out_of_memory("set_env_num");
! 500: putenv(mem);
! 501: }
! 502: #endif
! 503:
! 504: static int rsync_module(int f_in, int f_out, int i, const char *addr, const char *host)
1.1 misho 505: {
506: int argc;
507: char **argv, **orig_argv, **orig_early_argv, *module_chdir;
508: char line[BIGPATHBUFLEN];
1.1.1.2 ! misho 509: #if defined HAVE_INITGROUPS && !defined HAVE_GETGROUPLIST
! 510: struct passwd *pw = NULL;
! 511: #endif
! 512: uid_t uid;
! 513: int set_uid;
1.1 misho 514: char *p, *err_msg = NULL;
515: char *name = lp_name(i);
516: int use_chroot = lp_use_chroot(i);
1.1.1.2 ! misho 517: int ret, pre_exec_arg_fd = -1, pre_exec_error_fd = -1;
! 518: int save_munge_symlinks;
1.1 misho 519: pid_t pre_exec_pid = 0;
520: char *request = NULL;
521:
1.1.1.2 ! misho 522: set_env_str("RSYNC_MODULE_NAME", name);
! 523:
1.1 misho 524: #ifdef ICONV_OPTION
525: iconv_opt = lp_charset(i);
526: if (*iconv_opt)
527: setup_iconv();
528: iconv_opt = NULL;
529: #endif
530:
1.1.1.2 ! misho 531: /* If reverse lookup is disabled globally but enabled for this module,
! 532: * we need to do it now before the access check. */
! 533: if (host == undetermined_hostname && lp_reverse_lookup(i))
! 534: host = client_name(f_in);
! 535: set_env_str("RSYNC_HOST_NAME", host);
! 536: set_env_str("RSYNC_HOST_ADDR", addr);
! 537:
! 538: if (!allow_access(addr, &host, i)) {
1.1 misho 539: rprintf(FLOG, "rsync denied on module %s from %s (%s)\n",
540: name, host, addr);
541: if (!lp_list(i))
542: io_printf(f_out, "@ERROR: Unknown module '%s'\n", name);
543: else {
544: io_printf(f_out,
545: "@ERROR: access denied to %s from %s (%s)\n",
546: name, host, addr);
547: }
548: return -1;
549: }
550:
551: if (am_daemon && am_server) {
552: rprintf(FLOG, "rsync allowed access on module %s from %s (%s)\n",
553: name, host, addr);
554: }
555:
556: if (!claim_connection(lp_lock_file(i), lp_max_connections(i))) {
557: if (errno) {
558: rsyserr(FLOG, errno, "failed to open lock file %s",
559: lp_lock_file(i));
560: io_printf(f_out, "@ERROR: failed to open lock file\n");
561: } else {
562: rprintf(FLOG, "max connections (%d) reached\n",
563: lp_max_connections(i));
564: io_printf(f_out, "@ERROR: max connections (%d) reached -- try again later\n",
565: lp_max_connections(i));
566: }
567: return -1;
568: }
569:
1.1.1.2 ! misho 570: read_only = lp_read_only(i); /* may also be overridden by auth_server() */
1.1 misho 571: auth_user = auth_server(f_in, f_out, i, host, addr, "@RSYNCD: AUTHREQD ");
572:
573: if (!auth_user) {
574: io_printf(f_out, "@ERROR: auth failed on module %s\n", name);
575: return -1;
576: }
1.1.1.2 ! misho 577: set_env_str("RSYNC_USER_NAME", auth_user);
1.1 misho 578:
579: module_id = i;
580:
581: if (lp_transfer_logging(i) && !logfile_format)
582: logfile_format = lp_log_format(i);
583: if (log_format_has(logfile_format, 'i'))
584: logfile_format_has_i = 1;
585: if (logfile_format_has_i || log_format_has(logfile_format, 'o'))
586: logfile_format_has_o_or_i = 1;
587:
1.1.1.2 ! misho 588: uid = MY_UID();
! 589: am_root = (uid == 0);
1.1 misho 590:
1.1.1.2 ! misho 591: p = *lp_uid(i) ? lp_uid(i) : am_root ? NOBODY_USER : NULL;
! 592: if (p) {
! 593: if (!user_to_uid(p, &uid, True)) {
! 594: rprintf(FLOG, "Invalid uid %s\n", p);
! 595: io_printf(f_out, "@ERROR: invalid uid %s\n", p);
! 596: return -1;
1.1 misho 597: }
1.1.1.2 ! misho 598: set_uid = 1;
! 599: } else
! 600: set_uid = 0;
1.1 misho 601:
1.1.1.2 ! misho 602: p = *lp_gid(i) ? strtok(lp_gid(i), ", ") : NULL;
! 603: if (p) {
! 604: /* The "*" gid must be the first item in the list. */
! 605: if (strcmp(p, "*") == 0) {
! 606: #ifdef HAVE_GETGROUPLIST
! 607: if (want_all_groups(f_out, uid) < 0)
! 608: return -1;
! 609: #elif defined HAVE_INITGROUPS
! 610: if ((pw = want_all_groups(f_out, uid)) == NULL)
! 611: return -1;
! 612: #else
! 613: rprintf(FLOG, "This rsync does not support a gid of \"*\"\n");
! 614: io_printf(f_out, "@ERROR: invalid gid setting.\n");
! 615: return -1;
! 616: #endif
! 617: } else if (add_a_group(f_out, p) < 0)
! 618: return -1;
! 619: while ((p = strtok(NULL, ", ")) != NULL) {
! 620: #if defined HAVE_INITGROUPS && !defined HAVE_GETGROUPLIST
! 621: if (pw) {
! 622: rprintf(FLOG, "This rsync cannot add groups after \"*\".\n");
! 623: io_printf(f_out, "@ERROR: invalid gid setting.\n");
1.1 misho 624: return -1;
625: }
1.1.1.2 ! misho 626: #endif
! 627: if (add_a_group(f_out, p) < 0)
! 628: return -1;
1.1 misho 629: }
1.1.1.2 ! misho 630: } else if (am_root) {
! 631: if (add_a_group(f_out, NOBODY_GROUP) < 0)
! 632: return -1;
1.1 misho 633: }
634:
635: module_dir = lp_path(i);
636: if (*module_dir == '\0') {
637: rprintf(FLOG, "No path specified for module %s\n", name);
638: io_printf(f_out, "@ERROR: no path setting.\n");
639: return -1;
640: }
641: if (use_chroot) {
642: if ((p = strstr(module_dir, "/./")) != NULL) {
643: *p = '\0'; /* Temporary... */
644: if (!(module_chdir = normalize_path(module_dir, True, NULL)))
645: return path_failure(f_out, module_dir, False);
646: *p = '/';
647: if (!(p = normalize_path(p + 2, True, &module_dirlen)))
648: return path_failure(f_out, strstr(module_dir, "/./"), False);
649: if (!(full_module_path = normalize_path(module_dir, False, NULL)))
650: full_module_path = module_dir;
651: module_dir = p;
652: } else {
653: if (!(module_chdir = normalize_path(module_dir, False, NULL)))
654: return path_failure(f_out, module_dir, False);
655: full_module_path = module_chdir;
656: module_dir = "/";
657: module_dirlen = 1;
658: }
659: } else {
660: if (!(module_chdir = normalize_path(module_dir, False, &module_dirlen)))
661: return path_failure(f_out, module_dir, False);
662: full_module_path = module_dir = module_chdir;
663: }
1.1.1.2 ! misho 664: set_env_str("RSYNC_MODULE_PATH", full_module_path);
1.1 misho 665:
666: if (module_dirlen == 1) {
667: module_dirlen = 0;
668: set_filter_dir("/", 1);
669: } else
670: set_filter_dir(module_dir, module_dirlen);
671:
672: p = lp_filter(i);
1.1.1.2 ! misho 673: parse_filter_str(&daemon_filter_list, p, rule_template(FILTRULE_WORD_SPLIT),
1.1 misho 674: XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3);
675:
676: p = lp_include_from(i);
1.1.1.2 ! misho 677: parse_filter_file(&daemon_filter_list, p, rule_template(FILTRULE_INCLUDE),
1.1 misho 678: XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
679:
680: p = lp_include(i);
1.1.1.2 ! misho 681: parse_filter_str(&daemon_filter_list, p,
! 682: rule_template(FILTRULE_INCLUDE | FILTRULE_WORD_SPLIT),
1.1 misho 683: XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES);
684:
685: p = lp_exclude_from(i);
1.1.1.2 ! misho 686: parse_filter_file(&daemon_filter_list, p, rule_template(0),
1.1 misho 687: XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES | XFLG_FATAL_ERRORS);
688:
689: p = lp_exclude(i);
1.1.1.2 ! misho 690: parse_filter_str(&daemon_filter_list, p, rule_template(FILTRULE_WORD_SPLIT),
1.1 misho 691: XFLG_ABS_IF_SLASH | XFLG_DIR2WILD3 | XFLG_OLD_PREFIXES);
692:
693: log_init(1);
694:
695: #ifdef HAVE_PUTENV
696: if (*lp_prexfer_exec(i) || *lp_postxfer_exec(i)) {
697: int status;
698:
699: /* For post-xfer exec, fork a new process to run the rsync
700: * daemon while this process waits for the exit status and
701: * runs the indicated command at that point. */
702: if (*lp_postxfer_exec(i)) {
703: pid_t pid = fork();
704: if (pid < 0) {
705: rsyserr(FLOG, errno, "fork failed");
706: io_printf(f_out, "@ERROR: fork failed\n");
707: return -1;
708: }
709: if (pid) {
1.1.1.2 ! misho 710: close(f_in);
! 711: if (f_out != f_in)
! 712: close(f_out);
! 713: set_env_num("RSYNC_PID", (long)pid);
1.1 misho 714: if (wait_process(pid, &status, 0) < 0)
715: status = -1;
1.1.1.2 ! misho 716: set_env_num("RSYNC_RAW_STATUS", status);
1.1 misho 717: if (WIFEXITED(status))
718: status = WEXITSTATUS(status);
719: else
720: status = -1;
1.1.1.2 ! misho 721: set_env_num("RSYNC_EXIT_STATUS", status);
1.1 misho 722: if (system(lp_postxfer_exec(i)) < 0)
723: status = -1;
724: _exit(status);
725: }
726: }
727: /* For pre-xfer exec, fork a child process to run the indicated
728: * command, though it first waits for the parent process to
729: * send us the user's request via a pipe. */
730: if (*lp_prexfer_exec(i)) {
1.1.1.2 ! misho 731: int arg_fds[2], error_fds[2];
! 732: set_env_num("RSYNC_PID", (long)getpid());
! 733: if (pipe(arg_fds) < 0 || pipe(error_fds) < 0 || (pre_exec_pid = fork()) < 0) {
1.1 misho 734: rsyserr(FLOG, errno, "pre-xfer exec preparation failed");
735: io_printf(f_out, "@ERROR: pre-xfer exec preparation failed\n");
736: return -1;
737: }
738: if (pre_exec_pid == 0) {
739: char buf[BIGPATHBUFLEN];
740: int j, len;
1.1.1.2 ! misho 741: close(arg_fds[1]);
! 742: close(error_fds[0]);
! 743: pre_exec_arg_fd = arg_fds[0];
! 744: pre_exec_error_fd = error_fds[1];
! 745: set_blocking(pre_exec_arg_fd);
! 746: set_blocking(pre_exec_error_fd);
! 747: len = read_arg_from_pipe(pre_exec_arg_fd, buf, BIGPATHBUFLEN);
1.1 misho 748: if (len <= 0)
749: _exit(1);
1.1.1.2 ! misho 750: set_env_str("RSYNC_REQUEST", buf);
1.1 misho 751: for (j = 0; ; j++) {
1.1.1.2 ! misho 752: len = read_arg_from_pipe(pre_exec_arg_fd, buf,
1.1 misho 753: BIGPATHBUFLEN);
754: if (len <= 0) {
755: if (!len)
756: break;
757: _exit(1);
758: }
1.1.1.2 ! misho 759: if (asprintf(&p, "RSYNC_ARG%d=%s", j, buf) >= 0)
1.1 misho 760: putenv(p);
761: }
1.1.1.2 ! misho 762: close(pre_exec_arg_fd);
1.1 misho 763: close(STDIN_FILENO);
1.1.1.2 ! misho 764: dup2(pre_exec_error_fd, STDOUT_FILENO);
! 765: close(pre_exec_error_fd);
1.1 misho 766: status = system(lp_prexfer_exec(i));
767: if (!WIFEXITED(status))
768: _exit(1);
769: _exit(WEXITSTATUS(status));
770: }
1.1.1.2 ! misho 771: close(arg_fds[0]);
! 772: close(error_fds[1]);
! 773: pre_exec_arg_fd = arg_fds[1];
! 774: pre_exec_error_fd = error_fds[0];
! 775: set_blocking(pre_exec_arg_fd);
! 776: set_blocking(pre_exec_error_fd);
1.1 misho 777: }
778: }
779: #endif
780:
781: if (use_chroot) {
782: /*
783: * XXX: The 'use chroot' flag is a fairly reliable
784: * source of confusion, because it fails under two
785: * important circumstances: running as non-root,
786: * running on Win32 (or possibly others). On the
787: * other hand, if you are running as root, then it
788: * might be better to always use chroot.
789: *
790: * So, perhaps if we can't chroot we should just issue
791: * a warning, unless a "require chroot" flag is set,
792: * in which case we fail.
793: */
794: if (chroot(module_chdir)) {
795: rsyserr(FLOG, errno, "chroot %s failed", module_chdir);
796: io_printf(f_out, "@ERROR: chroot failed\n");
797: return -1;
798: }
799: module_chdir = module_dir;
800: }
801:
802: if (!change_dir(module_chdir, CD_NORMAL))
803: return path_failure(f_out, module_chdir, True);
804: if (module_dirlen || !use_chroot)
805: sanitize_paths = 1;
806:
807: if ((munge_symlinks = lp_munge_symlinks(i)) < 0)
808: munge_symlinks = !use_chroot || module_dirlen;
809: if (munge_symlinks) {
810: STRUCT_STAT st;
1.1.1.2 ! misho 811: char prefix[SYMLINK_PREFIX_LEN]; /* NOT +1 ! */
! 812: strlcpy(prefix, SYMLINK_PREFIX, sizeof prefix); /* trim the trailing slash */
! 813: if (do_stat(prefix, &st) == 0 && S_ISDIR(st.st_mode)) {
! 814: rprintf(FLOG, "Symlink munging is unsafe when a %s directory exists.\n",
! 815: prefix);
1.1 misho 816: io_printf(f_out, "@ERROR: daemon security issue -- contact admin\n", name);
817: exit_cleanup(RERR_UNSUPPORTED);
818: }
819: }
820:
1.1.1.2 ! misho 821: if (gid_count) {
! 822: if (setgid(gid_list[0])) {
! 823: rsyserr(FLOG, errno, "setgid %ld failed", (long)gid_list[0]);
1.1 misho 824: io_printf(f_out, "@ERROR: setgid failed\n");
825: return -1;
826: }
827: #ifdef HAVE_SETGROUPS
1.1.1.2 ! misho 828: /* Set the group(s) we want to be active. */
! 829: if (setgroups(gid_count, gid_list)) {
1.1 misho 830: rsyserr(FLOG, errno, "setgroups failed");
831: io_printf(f_out, "@ERROR: setgroups failed\n");
832: return -1;
833: }
834: #endif
1.1.1.2 ! misho 835: #if defined HAVE_INITGROUPS && !defined HAVE_GETGROUPLIST
! 836: /* pw is set if the user wants all the user's groups. */
! 837: if (pw && initgroups(pw->pw_name, pw->pw_gid) < 0) {
! 838: rsyserr(FLOG, errno, "initgroups failed");
! 839: io_printf(f_out, "@ERROR: initgroups failed\n");
! 840: return -1;
! 841: }
! 842: #endif
! 843: }
1.1 misho 844:
1.1.1.2 ! misho 845: if (set_uid) {
1.1 misho 846: if (setuid(uid) < 0
847: #ifdef HAVE_SETEUID
848: || seteuid(uid) < 0
849: #endif
850: ) {
1.1.1.2 ! misho 851: rsyserr(FLOG, errno, "setuid %ld failed", (long)uid);
1.1 misho 852: io_printf(f_out, "@ERROR: setuid failed\n");
853: return -1;
854: }
855:
856: am_root = (MY_UID() == 0);
857: }
858:
859: if (lp_temp_dir(i) && *lp_temp_dir(i)) {
860: tmpdir = lp_temp_dir(i);
861: if (strlen(tmpdir) >= MAXPATHLEN - 10) {
862: rprintf(FLOG,
863: "the 'temp dir' value for %s is WAY too long -- ignoring.\n",
864: name);
865: tmpdir = NULL;
866: }
867: }
868:
869: io_printf(f_out, "@RSYNCD: OK\n");
870:
871: read_args(f_in, name, line, sizeof line, rl_nulls, &argv, &argc, &request);
872: orig_argv = argv;
873:
1.1.1.2 ! misho 874: save_munge_symlinks = munge_symlinks;
! 875:
! 876: reset_output_levels(); /* future verbosity is controlled by client options */
1.1 misho 877: ret = parse_arguments(&argc, (const char ***) &argv);
878: if (protect_args && ret) {
879: orig_early_argv = orig_argv;
880: protect_args = 2;
881: read_args(f_in, name, line, sizeof line, 1, &argv, &argc, &request);
882: orig_argv = argv;
883: ret = parse_arguments(&argc, (const char ***) &argv);
884: } else
885: orig_early_argv = NULL;
886:
1.1.1.2 ! misho 887: munge_symlinks = save_munge_symlinks; /* The client mustn't control this. */
! 888:
1.1 misho 889: if (pre_exec_pid) {
1.1.1.2 ! misho 890: err_msg = finish_pre_exec(pre_exec_pid, pre_exec_arg_fd, pre_exec_error_fd,
! 891: request, orig_early_argv, orig_argv);
1.1 misho 892: }
893:
894: if (orig_early_argv)
895: free(orig_early_argv);
896:
897: am_server = 1; /* Don't let someone try to be tricky. */
898: quiet = 0;
899: if (lp_ignore_errors(module_id))
900: ignore_errors = 1;
901: if (write_batch < 0)
902: dry_run = 1;
903:
904: if (lp_fake_super(i)) {
905: if (preserve_xattrs > 1)
906: preserve_xattrs = 1;
907: am_root = -1;
908: } else if (am_root < 0) /* Treat --fake-super from client as --super. */
909: am_root = 2;
910:
911: if (filesfrom_fd == 0)
912: filesfrom_fd = f_in;
913:
914: if (request) {
915: if (*auth_user) {
916: rprintf(FLOG, "rsync %s %s from %s@%s (%s)\n",
917: am_sender ? "on" : "to",
918: request, auth_user, host, addr);
919: } else {
920: rprintf(FLOG, "rsync %s %s from %s (%s)\n",
921: am_sender ? "on" : "to",
922: request, host, addr);
923: }
924: free(request);
925: }
926:
927: #ifndef DEBUG
928: /* don't allow the logs to be flooded too fast */
1.1.1.2 ! misho 929: limit_output_verbosity(lp_max_verbosity(i));
1.1 misho 930: #endif
931:
932: if (protocol_version < 23
933: && (protocol_version == 22 || am_sender))
1.1.1.2 ! misho 934: io_start_multiplex_out(f_out);
1.1 misho 935: else if (!ret || err_msg) {
936: /* We have to get I/O multiplexing started so that we can
937: * get the error back to the client. This means getting
938: * the protocol setup finished first in later versions. */
939: setup_protocol(f_out, f_in);
940: if (!am_sender) {
941: /* Since we failed in our option parsing, we may not
942: * have finished parsing that the client sent us a
943: * --files-from option, so look for it manually.
944: * Without this, the socket would be in the wrong
945: * state for the upcoming error message. */
946: if (!files_from) {
947: int i;
948: for (i = 0; i < argc; i++) {
949: if (strncmp(argv[i], "--files-from", 12) == 0) {
950: files_from = "";
951: break;
952: }
953: }
954: }
955: if (files_from)
956: write_byte(f_out, 0);
957: }
1.1.1.2 ! misho 958: io_start_multiplex_out(f_out);
1.1 misho 959: }
960:
961: if (!ret || err_msg) {
1.1.1.2 ! misho 962: if (err_msg) {
! 963: while ((p = strchr(err_msg, '\n')) != NULL) {
! 964: int len = p - err_msg + 1;
! 965: rwrite(FERROR, err_msg, len, 0);
! 966: err_msg += len;
! 967: }
! 968: if (*err_msg)
! 969: rprintf(FERROR, "%s\n", err_msg);
! 970: } else
1.1 misho 971: option_error();
972: msleep(400);
973: exit_cleanup(RERR_UNSUPPORTED);
974: }
975:
976: #ifdef ICONV_OPTION
977: if (!iconv_opt) {
978: if (ic_send != (iconv_t)-1) {
979: iconv_close(ic_send);
980: ic_send = (iconv_t)-1;
981: }
982: if (ic_recv != (iconv_t)-1) {
983: iconv_close(ic_recv);
984: ic_recv = (iconv_t)-1;
985: }
986: }
987: #endif
988:
989: if (!numeric_ids
990: && (use_chroot ? lp_numeric_ids(i) != False : lp_numeric_ids(i) == True))
991: numeric_ids = -1; /* Set --numeric-ids w/o breaking protocol. */
992:
993: if (lp_timeout(i) && (!io_timeout || lp_timeout(i) < io_timeout))
994: set_io_timeout(lp_timeout(i));
995:
996: /* If we have some incoming/outgoing chmod changes, append them to
997: * any user-specified changes (making our changes have priority).
998: * We also get a pointer to just our changes so that a receiver
999: * process can use them separately if --perms wasn't specified. */
1000: if (am_sender)
1001: p = lp_outgoing_chmod(i);
1002: else
1003: p = lp_incoming_chmod(i);
1004: if (*p && !(daemon_chmod_modes = parse_chmod(p, &chmod_modes))) {
1005: rprintf(FLOG, "Invalid \"%sing chmod\" directive: %s\n",
1006: am_sender ? "outgo" : "incom", p);
1007: }
1008:
1009: start_server(f_in, f_out, argc, argv);
1010:
1011: return 0;
1012: }
1013:
1014: /* send a list of available modules to the client. Don't list those
1015: with "list = False". */
1016: static void send_listing(int fd)
1017: {
1.1.1.2 ! misho 1018: int n = lp_num_modules();
1.1 misho 1019: int i;
1020:
1021: for (i = 0; i < n; i++) {
1022: if (lp_list(i))
1023: io_printf(fd, "%-15s\t%s\n", lp_name(i), lp_comment(i));
1024: }
1025:
1026: if (protocol_version >= 25)
1027: io_printf(fd,"@RSYNCD: EXIT\n");
1028: }
1029:
1030: static int load_config(int globals_only)
1031: {
1032: if (!config_file) {
1033: if (am_server && am_root <= 0)
1034: config_file = RSYNCD_USERCONF;
1035: else
1036: config_file = RSYNCD_SYSCONF;
1037: }
1038: return lp_load(config_file, globals_only);
1039: }
1040:
1041: /* this is called when a connection is established to a client
1042: and we want to start talking. The setup of the system is done from
1043: here */
1044: int start_daemon(int f_in, int f_out)
1045: {
1046: char line[1024];
1.1.1.2 ! misho 1047: const char *addr, *host;
1.1 misho 1048: int i;
1049:
1050: io_set_sock_fds(f_in, f_out);
1051:
1052: /* We must load the config file before calling any function that
1053: * might cause log-file output to occur. This ensures that the
1054: * "log file" param gets honored for the 2 non-forked use-cases
1055: * (when rsync is run by init and run by a remote shell). */
1056: if (!load_config(0))
1057: exit_cleanup(RERR_SYNTAX);
1058:
1059: addr = client_addr(f_in);
1.1.1.2 ! misho 1060: host = lp_reverse_lookup(-1) ? client_name(f_in) : undetermined_hostname;
1.1 misho 1061: rprintf(FLOG, "connect from %s (%s)\n", host, addr);
1062:
1063: if (!am_server) {
1064: set_socket_options(f_in, "SO_KEEPALIVE");
1065: set_nonblocking(f_in);
1066: }
1067:
1068: if (exchange_protocols(f_in, f_out, line, sizeof line, 0) < 0)
1069: return -1;
1070:
1071: line[0] = 0;
1.1.1.2 ! misho 1072: if (!read_line_old(f_in, line, sizeof line, 0))
1.1 misho 1073: return -1;
1074:
1075: if (!*line || strcmp(line, "#list") == 0) {
1076: rprintf(FLOG, "module-list request from %s (%s)\n",
1077: host, addr);
1078: send_listing(f_out);
1079: return -1;
1080: }
1081:
1082: if (*line == '#') {
1083: /* it's some sort of command that I don't understand */
1084: io_printf(f_out, "@ERROR: Unknown command '%s'\n", line);
1085: return -1;
1086: }
1087:
1088: if ((i = lp_number(line)) < 0) {
1089: rprintf(FLOG, "unknown module '%s' tried from %s (%s)\n",
1090: line, host, addr);
1091: io_printf(f_out, "@ERROR: Unknown module '%s'\n", line);
1092: return -1;
1093: }
1094:
1095: #ifdef HAVE_SIGACTION
1096: sigact.sa_flags = SA_NOCLDSTOP;
1097: #endif
1098: SIGACTION(SIGCHLD, remember_children);
1099:
1100: return rsync_module(f_in, f_out, i, addr, host);
1101: }
1102:
1103: static void create_pid_file(void)
1104: {
1105: char *pid_file = lp_pid_file();
1106: char pidbuf[16];
1107: pid_t pid = getpid();
1108: int fd, len;
1109:
1110: if (!pid_file || !*pid_file)
1111: return;
1112:
1113: cleanup_set_pid(pid);
1.1.1.2 ! misho 1114: if ((fd = do_open(pid_file, O_WRONLY|O_CREAT|O_EXCL, 0666)) == -1) {
1.1 misho 1115: failure:
1116: cleanup_set_pid(0);
1117: fprintf(stderr, "failed to create pid file %s: %s\n", pid_file, strerror(errno));
1118: rsyserr(FLOG, errno, "failed to create pid file %s", pid_file);
1119: exit_cleanup(RERR_FILEIO);
1120: }
1.1.1.2 ! misho 1121: snprintf(pidbuf, sizeof pidbuf, "%d\n", (int)pid);
1.1 misho 1122: len = strlen(pidbuf);
1123: if (write(fd, pidbuf, len) != len)
1124: goto failure;
1125: close(fd);
1126: }
1127:
1128: /* Become a daemon, discarding the controlling terminal. */
1129: static void become_daemon(void)
1130: {
1131: int i;
1132: pid_t pid = fork();
1133:
1134: if (pid) {
1135: if (pid < 0) {
1136: fprintf(stderr, "failed to fork: %s\n", strerror(errno));
1137: exit_cleanup(RERR_FILEIO);
1138: }
1139: _exit(0);
1140: }
1141:
1142: create_pid_file();
1143:
1144: /* detach from the terminal */
1145: #ifdef HAVE_SETSID
1146: setsid();
1147: #elif defined TIOCNOTTY
1148: i = open("/dev/tty", O_RDWR);
1149: if (i >= 0) {
1150: ioctl(i, (int)TIOCNOTTY, (char *)0);
1151: close(i);
1152: }
1153: #endif
1154: /* make sure that stdin, stdout an stderr don't stuff things
1155: * up (library functions, for example) */
1156: for (i = 0; i < 3; i++) {
1157: close(i);
1158: open("/dev/null", O_RDWR);
1159: }
1160: }
1161:
1162: int daemon_main(void)
1163: {
1164: if (is_a_socket(STDIN_FILENO)) {
1165: int i;
1166:
1167: /* we are running via inetd - close off stdout and
1168: * stderr so that library functions (and getopt) don't
1169: * try to use them. Redirect them to /dev/null */
1170: for (i = 1; i < 3; i++) {
1171: close(i);
1172: open("/dev/null", O_RDWR);
1173: }
1174:
1175: return start_daemon(STDIN_FILENO, STDIN_FILENO);
1176: }
1177:
1178: if (!load_config(1)) {
1179: fprintf(stderr, "Failed to parse config file: %s\n", config_file);
1180: exit_cleanup(RERR_SYNTAX);
1181: }
1.1.1.2 ! misho 1182: set_dparams(0);
1.1 misho 1183:
1184: if (no_detach)
1185: create_pid_file();
1186: else
1187: become_daemon();
1188:
1189: if (rsync_port == 0 && (rsync_port = lp_rsync_port()) == 0)
1190: rsync_port = RSYNC_PORT;
1191: if (bind_address == NULL && *lp_bind_address())
1192: bind_address = lp_bind_address();
1193:
1194: log_init(0);
1195:
1196: rprintf(FLOG, "rsyncd version %s starting, listening on port %d\n",
1197: RSYNC_VERSION, rsync_port);
1198: /* TODO: If listening on a particular address, then show that
1199: * address too. In fact, why not just do getnameinfo on the
1200: * local address??? */
1201:
1202: start_accept_loop(rsync_port, start_daemon);
1203: return -1;
1204: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>