2 Copyright (C) Andrew Tridgell 1998
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* the socket based protocol for setting up a connection wit rsyncd */
26 extern int rsync_port
;
28 int start_socket_client(char *host
, char *path
, int argc
, char *argv
[])
31 char *sargs
[MAX_ARGS
];
33 char line
[MAXPATHLEN
];
35 extern int remote_version
;
39 p
= strchr(host
, '@');
46 if (!user
) user
= getenv("USER");
47 if (!user
) user
= getenv("LOGNAME");
51 fd
= open_socket_out(host
, rsync_port
);
56 server_options(sargs
,&sargc
);
61 sargs
[sargc
++] = path
;
65 io_printf(fd
,"@RSYNCD: %d\n", PROTOCOL_VERSION
);
67 if (!read_line(fd
, line
, sizeof(line
)-1)) {
71 if (sscanf(line
,"@RSYNCD: %d", &remote_version
) != 1) {
77 io_printf(fd
,"%s\n",path
);
81 if (!read_line(fd
, line
, sizeof(line
)-1)) {
85 if (strncmp(line
,"@RSYNCD: AUTHREQD ",18) == 0) {
86 auth_client(fd
, user
, line
+18);
90 if (strcmp(line
,"@RSYNCD: OK") == 0) break;
91 rprintf(FINFO
,"%s\n", line
);
94 for (i
=0;i
<sargc
;i
++) {
95 io_printf(fd
,"%s\n", sargs
[i
]);
99 if (remote_version
> 17 && !am_sender
)
100 io_start_multiplex_in(fd
);
102 return client_run(fd
, fd
, -1, argc
, argv
);
107 static int rsync_module(int fd
, int i
)
110 char *argv
[MAX_ARGS
];
112 char line
[MAXPATHLEN
];
113 uid_t uid
= (uid_t
)-2;
114 gid_t gid
= (gid_t
)-2;
116 char *addr
= client_addr(fd
);
117 char *host
= client_name(fd
);
118 char *name
= lp_name(i
);
122 extern int am_sender
;
123 extern int remote_version
;
126 if (!allow_access(addr
, host
, lp_hosts_allow(i
), lp_hosts_deny(i
))) {
127 rprintf(FERROR
,"rsync denied on module %s from %s (%s)\n",
128 name
, client_name(fd
), client_addr(fd
));
129 io_printf(fd
,"@ERROR: access denied to %s from %s (%s)\n",
130 name
, client_name(fd
), client_addr(fd
));
134 if (!claim_connection(lp_lock_file(), lp_max_connections())) {
135 rprintf(FERROR
,"max connections (%d) reached\n",
136 lp_max_connections());
137 io_printf(fd
,"@ERROR: max connections (%d) reached - try again later\n", lp_max_connections());
142 user
= auth_server(fd
, i
, addr
, "@RSYNCD: AUTHREQD ");
145 rprintf(FERROR
,"auth failed on module %s from %s (%s)\n",
146 name
, client_name(fd
), client_addr(fd
));
147 io_printf(fd
,"@ERROR: auth failed on module %s\n",name
);
157 if (!name_to_uid(p
, &uid
)) {
159 rprintf(FERROR
,"Invalid uid %s\n", p
);
160 io_printf(fd
,"@ERROR: invalid uid\n");
167 if (!name_to_gid(p
, &gid
)) {
169 rprintf(FERROR
,"Invalid gid %s\n", p
);
170 io_printf(fd
,"@ERROR: invalid gid\n");
176 p
= lp_exclude_from(i
);
177 add_exclude_file(p
, 1, 0);
184 if (chroot(lp_path(i
))) {
185 rprintf(FERROR
,"chroot %s failed\n", lp_path(i
));
186 io_printf(fd
,"@ERROR: chroot failed\n");
191 rprintf(FERROR
,"chdir %s failed\n", lp_path(i
));
192 io_printf(fd
,"@ERROR: chdir failed\n");
196 if (setgid(gid
) || getgid() != gid
) {
197 rprintf(FERROR
,"setgid %d failed\n", gid
);
198 io_printf(fd
,"@ERROR: setgid failed\n");
202 if (setuid(uid
) || getuid() != uid
) {
203 rprintf(FERROR
,"setuid %d failed\n", uid
);
204 io_printf(fd
,"@ERROR: setuid failed\n");
208 am_root
= (getuid() == 0);
210 io_printf(fd
,"@RSYNCD: OK\n");
212 argv
[argc
++] = "rsyncd";
215 if (!read_line(fd
, line
, sizeof(line
)-1)) {
223 argv
[argc
] = strdup(p
);
229 if (start_glob
== 1) {
233 glob_expand(name
, argv
, &argc
, MAX_ARGS
);
238 if (strcmp(line
,".") == 0) {
242 if (argc
== MAX_ARGS
) {
247 parse_arguments(argc
, argv
);
251 rprintf(FINFO
,"rsync %s %s from %s@%s (%s)\n",
253 request
, user
, host
, addr
);
255 rprintf(FINFO
,"rsync %s %s from %s (%s)\n",
257 request
, host
, addr
);
262 /* don't allow the logs to be flooded too fast */
263 if (verbose
> 1) verbose
= 1;
266 argp
= argv
+ optind
;
269 if (remote_version
> 17 && am_sender
)
270 io_start_multiplex_out(fd
);
272 start_server(fd
, fd
, argc
, argp
);
277 /* send a list of available modules to the client. Don't list those
278 with "list = False". */
279 static void send_listing(int fd
)
281 int n
= lp_numservices();
286 io_printf(fd
, "%-15s\t%s\n", lp_name(i
), lp_comment(i
));
289 /* this is called when a socket connection is established to a client
290 and we want to start talking. The setup of the system is done from
292 static int start_daemon(int fd
)
297 extern char *config_file
;
298 extern int remote_version
;
300 if (!lp_load(config_file
, 0)) {
304 set_socket_options(fd
,"SO_KEEPALIVE");
305 set_socket_options(fd
,lp_socket_options());
308 io_printf(fd
,"@RSYNCD: %d\n", PROTOCOL_VERSION
);
310 motd
= lp_motd_file();
312 FILE *f
= fopen(motd
,"r");
313 while (f
&& !feof(f
)) {
314 int len
= fread(line
, 1, sizeof(line
)-1, f
);
317 io_printf(fd
,"%s", line
);
324 if (!read_line(fd
, line
, sizeof(line
)-1)) {
328 if (sscanf(line
,"@RSYNCD: %d", &remote_version
) != 1) {
329 io_printf(fd
,"@ERROR: protocol startup error\n");
335 if (!read_line(fd
, line
, sizeof(line
)-1)) {
339 if (!*line
|| strcmp(line
,"#list")==0) {
345 /* it's some sort of command that I don't understand */
346 io_printf(fd
,"@ERROR: Unknown command '%s'\n", line
);
352 io_printf(fd
,"@ERROR: Unknown module '%s'\n", line
);
357 return rsync_module(fd
, i
);
361 int daemon_main(void)
363 extern char *config_file
;
365 /* this ensures that we don't call getcwd after the chroot,
366 which doesn't work on platforms that use popen("pwd","r")
370 if (is_a_socket(STDIN_FILENO
)) {
371 /* we are running via inetd */
372 return start_daemon(STDIN_FILENO
);
377 if (!lp_load(config_file
, 1)) {
378 fprintf(stderr
,"failed to load config file %s\n", config_file
);
384 rprintf(FINFO
,"rsyncd version %s starting\n",VERSION
);
386 start_accept_loop(rsync_port
, start_daemon
);