rsync server over SSH [includes code patches]
JD Paul
jdpaul at interstel.net
Wed Nov 21 14:44:22 EST 2001
Hi --
I've made the changes to my code changes and the new diffs (against
2.4.6 again) are included below.
Syntax for running rsync server over a remote shell (e.g. ssh) is now:
rsync [options] -e ssh source [user@]host::module[/dest]
rsync [options] -e ssh [user@]host::module[/source] dest
Cheers --
JD
jdpaul at interstel.net
On Tue, 20 Nov 2001, JD Paul wrote:
> On Tue, 20 Nov 2001, Dave Dykstra wrote:
>
> > I'm uncomfortable with adding yet another syntax. I'd prefer just keying
> > off the "-e" when the two colons are used. Currently "-e" is ignored if
> > you use two colons, so we don't need to worry about upward compatibility
> > except from people who had no idea what they were doing.
> >
> That's a very good point. In my thinking about syntax, I was somewhat
> misled by the standard practice at my site -- we habitually use
> RSYNC_RSH=ssh in the environment instead of '-e ssh' (so I tend to
> forget about that option).
>
> I'll get rid of the ':::' (as much as I'm fond of it) and re-submit
> the diffs; that change won't take much. It'll probably take more time
> to modify the man page than the code...
-----------------------------<cut here>------------------------------
Index: authenticate.c
===================================================================
RCS file: /juno/repository/usr/local/pkg/rsync/authenticate.c,v
retrieving revision 1.1.1.4
retrieving revision 1.3
diff -c -b -r1.1.1.4 -r1.3
*** authenticate.c 2001/10/19 04:10:00 1.1.1.4
--- authenticate.c 2001/10/24 22:00:38 1.3
***************
*** 202,208 ****
otherwise return username
*/
! char *auth_server(int fd, int module, char *addr, char *leader)
{
char *users = lp_auth_users(module);
char challenge[16];
--- 202,208 ----
otherwise return username
*/
! char *auth_server(int f_in, int f_out, int module, char *addr, char *leader)
{
char *users = lp_auth_users(module);
char challenge[16];
***************
*** 221,229 ****
base64_encode(challenge, 16, b64_challenge);
! io_printf(fd,"%s%s\n", leader, b64_challenge);
! if (!read_line(fd, line, sizeof(line)-1)) {
return NULL;
}
--- 221,229 ----
base64_encode(challenge, 16, b64_challenge);
! io_printf(f_out,"%s%s\n", leader, b64_challenge);
! if (!read_line(f_in, line, sizeof(line)-1)) {
return NULL;
}
Index: clientserver.c
===================================================================
RCS file: /juno/repository/usr/local/pkg/rsync/clientserver.c,v
retrieving revision 1.1.1.4
retrieving revision 1.5
diff -c -b -r1.1.1.4 -r1.5
*** clientserver.c 2001/10/19 04:09:27 1.1.1.4
--- clientserver.c 2001/11/21 03:37:30 1.5
***************
*** 29,48 ****
int start_socket_client(char *host, char *path, int argc, char *argv[])
{
! int fd, i;
! char *sargs[MAX_ARGS];
! int sargc=0;
! char line[MAXPATHLEN];
char *p, *user=NULL;
- extern int remote_version;
- extern int am_sender;
extern struct in_addr socket_address;
-
- if (argc == 0 && !am_sender) {
- extern int list_only;
- list_only = 1;
- }
if (*path == '/') {
rprintf(FERROR,"ERROR: The remote path must start with a module name\n");
return -1;
--- 29,42 ----
int start_socket_client(char *host, char *path, int argc, char *argv[])
{
! int fd;
! int ret;
char *p, *user=NULL;
extern struct in_addr socket_address;
+ /* this is redundant with code in start_inband_exchange(), but
+ this short-circuits a problem before we open a socket, and
+ the extra check won't hurt */
if (*path == '/') {
rprintf(FERROR,"ERROR: The remote path must start with a module name\n");
return -1;
***************
*** 55,68 ****
*p = 0;
}
- if (!user) user = getenv("USER");
- if (!user) user = getenv("LOGNAME");
-
fd = open_socket_out(host, rsync_port, &socket_address);
if (fd == -1) {
exit_cleanup(RERR_SOCKETIO);
}
server_options(sargs,&sargc);
sargs[sargc++] = ".";
--- 49,96 ----
*p = 0;
}
fd = open_socket_out(host, rsync_port, &socket_address);
if (fd == -1) {
exit_cleanup(RERR_SOCKETIO);
}
+ ret = start_inband_exchange(user, path, fd, fd, argc, argv);
+
+ return (ret < 0 ) ? ret : client_run(fd, fd, -1, argc, argv);
+ }
+
+ int start_inband_exchange(char *user, char *path, int f_in, int f_out, int argc, char *argv[])
+ {
+ int i;
+ char *sargs[MAX_ARGS];
+ int sargc = 0;
+ char line[MAXPATHLEN];
+ char *p;
+ extern int remote_version;
+ extern int am_sender;
+ extern int daemon_over_rsh;
+ extern char *remote_user;
+
+ if (argc == 0 && !am_sender) {
+ extern int list_only;
+ list_only = 1;
+ }
+
+ if (*path == '/') {
+ rprintf(FERROR,"ERROR: The remote path must start with a module name\n");
+ return -1;
+ }
+
+ if (!user) user = getenv("USER");
+ if (!user) user = getenv("LOGNAME");
+ if (!remote_user) {
+ remote_user = user;
+ }
+
+ /* set daemon_over_rsh to false since we need to build the
+ true set of args passed through the rsh/ssh connection;
+ this is a no-op for direct-socket-connection mode */
+ daemon_over_rsh = 0;
server_options(sargs,&sargc);
sargs[sargc++] = ".";
***************
*** 72,80 ****
sargs[sargc] = NULL;
! io_printf(fd,"@RSYNCD: %d\n", PROTOCOL_VERSION);
! if (!read_line(fd, line, sizeof(line)-1)) {
return -1;
}
--- 100,108 ----
sargs[sargc] = NULL;
! io_printf(f_out,"@RSYNCD: %d\n", PROTOCOL_VERSION);
! if (!read_line(f_in, line, sizeof(line)-1)) {
return -1;
}
***************
*** 84,99 ****
p = strchr(path,'/');
if (p) *p = 0;
! io_printf(fd,"%s\n",path);
if (p) *p = '/';
while (1) {
! if (!read_line(fd, line, sizeof(line)-1)) {
return -1;
}
if (strncmp(line,"@RSYNCD: AUTHREQD ",18) == 0) {
! auth_client(fd, user, line+18);
continue;
}
--- 112,127 ----
p = strchr(path,'/');
if (p) *p = 0;
! io_printf(f_out,"%s\n",path);
if (p) *p = '/';
while (1) {
! if (!read_line(f_in, line, sizeof(line)-1)) {
return -1;
}
if (strncmp(line,"@RSYNCD: AUTHREQD ",18) == 0) {
! auth_client(f_out, remote_user, line+18);
continue;
}
***************
*** 102,122 ****
}
for (i=0;i<sargc;i++) {
! io_printf(fd,"%s\n", sargs[i]);
}
! io_printf(fd,"\n");
if (remote_version < 23) {
if (remote_version == 22 || (remote_version > 17 && !am_sender))
! io_start_multiplex_in(fd);
}
! return client_run(fd, fd, -1, argc, argv);
! }
! static int rsync_module(int fd, int i)
{
int argc=0;
char *argv[MAX_ARGS];
--- 130,150 ----
}
for (i=0;i<sargc;i++) {
! io_printf(f_out,"%s\n", sargs[i]);
}
! io_printf(f_out,"\n");
if (remote_version < 23) {
if (remote_version == 22 || (remote_version > 17 && !am_sender))
! io_start_multiplex_in(f_in);
}
! return 0;
+ }
! static int rsync_module(int f_in, int f_out, int i)
{
int argc=0;
char *argv[MAX_ARGS];
***************
*** 125,170 ****
uid_t uid = (uid_t)-2;
gid_t gid = (gid_t)-2;
char *p;
! char *addr = client_addr(fd);
! char *host = client_name(fd);
char *name = lp_name(i);
int use_chroot = lp_use_chroot(i);
int start_glob=0;
int ret;
char *request=NULL;
extern int am_sender;
extern int remote_version;
extern int am_root;
if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
rprintf(FERROR,"rsync denied on module %s from %s (%s)\n",
! name, client_name(fd), client_addr(fd));
! io_printf(fd,"@ERROR: access denied to %s from %s (%s)\n",
! name, client_name(fd), client_addr(fd));
return -1;
}
if (!claim_connection(lp_lock_file(i), lp_max_connections(i))) {
if (errno) {
rprintf(FERROR,"failed to open lock file %s : %s\n",
lp_lock_file(i), strerror(errno));
! io_printf(fd,"@ERROR: failed to open lock file %s : %s\n",
lp_lock_file(i), strerror(errno));
} else {
rprintf(FERROR,"max connections (%d) reached\n",
lp_max_connections(i));
! io_printf(fd,"@ERROR: max connections (%d) reached - try again later\n", lp_max_connections(i));
}
return -1;
}
! auth_user = auth_server(fd, i, addr, "@RSYNCD: AUTHREQD ");
if (!auth_user) {
rprintf(FERROR,"auth failed on module %s from %s (%s)\n",
! name, client_name(fd), client_addr(fd));
! io_printf(fd,"@ERROR: auth failed on module %s\n",name);
return -1;
}
--- 153,214 ----
uid_t uid = (uid_t)-2;
gid_t gid = (gid_t)-2;
char *p;
! char *addr;
! char *host;
char *name = lp_name(i);
int use_chroot = lp_use_chroot(i);
int start_glob=0;
int ret;
char *request=NULL;
extern int am_sender;
+ extern int am_server;
+ extern int am_daemon;
extern int remote_version;
extern int am_root;
+ if (is_a_socket(f_in)) {
+ addr = client_addr(f_in);
+ host = client_name(f_in);
+ } else {
+ char *ssh_client = getenv("SSH_CLIENT");
+ addr = ssh_client ? ssh_client : "n/a";
+ host = "remote shell connection";
+ }
+
if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
rprintf(FERROR,"rsync denied on module %s from %s (%s)\n",
! name, host, addr);
! io_printf(f_out,"@ERROR: access denied to %s from %s (%s)\n",
! name, host, addr);
return -1;
}
+ if (am_daemon && am_server) {
+ rprintf(FINFO, "rsync allowed access on module %s from %s (%s)\n",
+ name, host, addr);
+ }
+
if (!claim_connection(lp_lock_file(i), lp_max_connections(i))) {
if (errno) {
rprintf(FERROR,"failed to open lock file %s : %s\n",
lp_lock_file(i), strerror(errno));
! io_printf(f_out,"@ERROR: failed to open lock file %s : %s\n",
lp_lock_file(i), strerror(errno));
} else {
rprintf(FERROR,"max connections (%d) reached\n",
lp_max_connections(i));
! io_printf(f_out,"@ERROR: max connections (%d) reached - try again later\n", lp_max_connections(i));
}
return -1;
}
! auth_user = auth_server(f_in, f_out, i, addr, "@RSYNCD: AUTHREQD ");
if (!auth_user) {
rprintf(FERROR,"auth failed on module %s from %s (%s)\n",
! name, host, addr);
! io_printf(f_out,"@ERROR: auth failed on module %s\n",name);
return -1;
}
***************
*** 177,183 ****
if (!name_to_uid(p, &uid)) {
if (!isdigit(*p)) {
rprintf(FERROR,"Invalid uid %s\n", p);
! io_printf(fd,"@ERROR: invalid uid\n");
return -1;
}
uid = atoi(p);
--- 221,227 ----
if (!name_to_uid(p, &uid)) {
if (!isdigit(*p)) {
rprintf(FERROR,"Invalid uid %s\n", p);
! io_printf(f_out,"@ERROR: invalid uid\n");
return -1;
}
uid = atoi(p);
***************
*** 187,193 ****
if (!name_to_gid(p, &gid)) {
if (!isdigit(*p)) {
rprintf(FERROR,"Invalid gid %s\n", p);
! io_printf(fd,"@ERROR: invalid gid\n");
return -1;
}
gid = atoi(p);
--- 231,237 ----
if (!name_to_gid(p, &gid)) {
if (!isdigit(*p)) {
rprintf(FERROR,"Invalid gid %s\n", p);
! io_printf(f_out,"@ERROR: invalid gid\n");
return -1;
}
gid = atoi(p);
***************
*** 211,230 ****
if (use_chroot) {
if (chroot(lp_path(i))) {
rprintf(FERROR,"chroot %s failed\n", lp_path(i));
! io_printf(fd,"@ERROR: chroot failed\n");
return -1;
}
if (!push_dir("/", 0)) {
rprintf(FERROR,"chdir %s failed\n", lp_path(i));
! io_printf(fd,"@ERROR: chdir failed\n");
return -1;
}
} else {
if (!push_dir(lp_path(i), 0)) {
rprintf(FERROR,"chdir %s failed\n", lp_path(i));
! io_printf(fd,"@ERROR: chdir failed\n");
return -1;
}
sanitize_paths = 1;
--- 255,274 ----
if (use_chroot) {
if (chroot(lp_path(i))) {
rprintf(FERROR,"chroot %s failed\n", lp_path(i));
! io_printf(f_out,"@ERROR: chroot failed\n");
return -1;
}
if (!push_dir("/", 0)) {
rprintf(FERROR,"chdir %s failed\n", lp_path(i));
! io_printf(f_out,"@ERROR: chdir failed\n");
return -1;
}
} else {
if (!push_dir(lp_path(i), 0)) {
rprintf(FERROR,"chdir %s failed\n", lp_path(i));
! io_printf(f_out,"@ERROR: chdir failed\n");
return -1;
}
sanitize_paths = 1;
***************
*** 233,257 ****
if (am_root) {
if (setgid(gid)) {
rprintf(FERROR,"setgid %d failed\n", gid);
! io_printf(fd,"@ERROR: setgid failed\n");
return -1;
}
if (setuid(uid)) {
rprintf(FERROR,"setuid %d failed\n", uid);
! io_printf(fd,"@ERROR: setuid failed\n");
return -1;
}
am_root = (getuid() == 0);
}
! io_printf(fd,"@RSYNCD: OK\n");
argv[argc++] = "rsyncd";
while (1) {
! if (!read_line(fd, line, sizeof(line)-1)) {
return -1;
}
--- 277,301 ----
if (am_root) {
if (setgid(gid)) {
rprintf(FERROR,"setgid %d failed\n", gid);
! io_printf(f_out,"@ERROR: setgid failed\n");
return -1;
}
if (setuid(uid)) {
rprintf(FERROR,"setuid %d failed\n", uid);
! io_printf(f_out,"@ERROR: setuid failed\n");
return -1;
}
am_root = (getuid() == 0);
}
! io_printf(f_out,"@RSYNCD: OK\n");
argv[argc++] = "rsyncd";
while (1) {
! if (!read_line(f_in, line, sizeof(line)-1)) {
return -1;
}
***************
*** 322,328 ****
if (remote_version < 23) {
if (remote_version == 22 || (remote_version > 17 && am_sender))
! io_start_multiplex_out(fd);
}
if (!ret) {
--- 366,372 ----
if (remote_version < 23) {
if (remote_version == 22 || (remote_version > 17 && am_sender))
! io_start_multiplex_out(f_out);
}
if (!ret) {
***************
*** 334,340 ****
io_timeout = lp_timeout(i);
}
! start_server(fd, fd, argc, argp);
return 0;
}
--- 378,384 ----
io_timeout = lp_timeout(i);
}
! start_server(f_in, f_out, argc, argp);
return 0;
}
***************
*** 351,376 ****
io_printf(fd, "%-15s\t%s\n", lp_name(i), lp_comment(i));
}
! /* this is called when a socket connection is established to a client
and we want to start talking. The setup of the system is done from
here */
! static int start_daemon(int fd)
{
char line[200];
char *motd;
int i = -1;
extern char *config_file;
extern int remote_version;
if (!lp_load(config_file, 0)) {
exit_cleanup(RERR_SYNTAX);
}
! set_socket_options(fd,"SO_KEEPALIVE");
! set_socket_options(fd,lp_socket_options());
! set_nonblocking(fd);
! io_printf(fd,"@RSYNCD: %d\n", PROTOCOL_VERSION);
motd = lp_motd_file();
if (motd && *motd) {
--- 395,423 ----
io_printf(fd, "%-15s\t%s\n", lp_name(i), lp_comment(i));
}
! /* this is called when a connection is established to a client
and we want to start talking. The setup of the system is done from
here */
! int start_daemon(int f_in, int f_out)
{
char line[200];
char *motd;
int i = -1;
extern char *config_file;
extern int remote_version;
+ extern int am_server;
if (!lp_load(config_file, 0)) {
exit_cleanup(RERR_SYNTAX);
}
! if ( !am_server ) {
! set_socket_options(f_in,"SO_KEEPALIVE");
! set_socket_options(f_in,lp_socket_options());
! set_nonblocking(f_in);
! }
! io_printf(f_out,"@RSYNCD: %d\n", PROTOCOL_VERSION);
motd = lp_motd_file();
if (motd && *motd) {
***************
*** 379,428 ****
int len = fread(line, 1, sizeof(line)-1, f);
if (len > 0) {
line[len] = 0;
! io_printf(fd,"%s", line);
}
}
if (f) fclose(f);
! io_printf(fd,"\n");
}
! if (!read_line(fd, line, sizeof(line)-1)) {
return -1;
}
if (sscanf(line,"@RSYNCD: %d", &remote_version) != 1) {
! io_printf(fd,"@ERROR: protocol startup error\n");
return -1;
}
while (i == -1) {
line[0] = 0;
! if (!read_line(fd, line, sizeof(line)-1)) {
return -1;
}
if (!*line || strcmp(line,"#list")==0) {
! send_listing(fd);
return -1;
}
if (*line == '#') {
/* it's some sort of command that I don't understand */
! io_printf(fd,"@ERROR: Unknown command '%s'\n", line);
return -1;
}
i = lp_number(line);
if (i == -1) {
! io_printf(fd,"@ERROR: Unknown module '%s'\n", line);
return -1;
}
}
! return rsync_module(fd, i);
}
-
int daemon_main(void)
{
extern char *config_file;
--- 426,474 ----
int len = fread(line, 1, sizeof(line)-1, f);
if (len > 0) {
line[len] = 0;
! io_printf(f_out,"%s", line);
}
}
if (f) fclose(f);
! io_printf(f_out,"\n");
}
! if (!read_line(f_in, line, sizeof(line)-1)) {
return -1;
}
if (sscanf(line,"@RSYNCD: %d", &remote_version) != 1) {
! io_printf(f_out,"@ERROR: protocol startup error\n");
return -1;
}
while (i == -1) {
line[0] = 0;
! if (!read_line(f_in, line, sizeof(line)-1)) {
return -1;
}
if (!*line || strcmp(line,"#list")==0) {
! send_listing(f_out);
return -1;
}
if (*line == '#') {
/* it's some sort of command that I don't understand */
! io_printf(f_out,"@ERROR: Unknown command '%s'\n", line);
return -1;
}
i = lp_number(line);
if (i == -1) {
! io_printf(f_out,"@ERROR: Unknown module '%s'\n", line);
return -1;
}
}
! return rsync_module(f_in, f_out, i);
}
int daemon_main(void)
{
extern char *config_file;
***************
*** 440,446 ****
open("/dev/null", O_RDWR);
}
! return start_daemon(STDIN_FILENO);
}
become_daemon();
--- 486,492 ----
open("/dev/null", O_RDWR);
}
! return start_daemon(STDIN_FILENO, STDIN_FILENO);
}
become_daemon();
Index: main.c
===================================================================
RCS file: /juno/repository/usr/local/pkg/rsync/main.c,v
retrieving revision 1.1.1.6
retrieving revision 1.5
diff -c -b -r1.1.1.6 -r1.5
*** main.c 2001/10/19 04:09:33 1.1.1.6
--- main.c 2001/11/21 03:37:30 1.5
***************
*** 126,131 ****
--- 126,132 ----
extern int local_server;
extern char *rsync_path;
extern int blocking_io;
+ extern int daemon_over_rsh;
if (!local_server) {
if (!cmd)
***************
*** 165,172 ****
--- 166,175 ----
args[argc++] = ".";
+ if (!daemon_over_rsh) {
if (path && *path)
args[argc++] = path;
+ }
args[argc] = NULL;
***************
*** 555,561 ****
--- 558,566 ----
extern int am_sender;
extern char *shell_cmd;
extern int rsync_port;
+ extern int daemon_over_rsh;
+ /* rsync:// always uses rsync server over direct socket connection */
if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
char *host, *path;
***************
*** 580,586 ****
if (p) {
if (p[1] == ':') {
*p = 0;
! return start_socket_client(argv[0], p+2, argc-1, argv+1);
}
if (argc < 1) {
--- 585,597 ----
if (p) {
if (p[1] == ':') {
*p = 0;
! if (!shell_cmd) {
! return start_socket_client(argv[0], p+2,
! argc-1, argv+1);
! } else {
! ++p;
! daemon_over_rsh = 1;
! }
}
if (argc < 1) {
***************
*** 602,608 ****
local_server = 1;
} else if (p[1] == ':') {
*p = 0;
! return start_socket_client(argv[argc-1], p+2, argc-1, argv);
}
if (argc < 2) {
--- 613,625 ----
local_server = 1;
} else if (p[1] == ':') {
*p = 0;
! if (!shell_cmd) {
! return start_socket_client(argv[argc-1], p+2,
! argc-1, argv);
! } else {
! ++p;
! daemon_over_rsh = 1;
! }
}
if (argc < 2) {
***************
*** 647,654 ****
extern int list_only;
list_only = 1;
}
! pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,&f_in,&f_out);
ret = client_run(f_in, f_out, pid, argc, argv);
--- 664,683 ----
extern int list_only;
list_only = 1;
}
+
+ pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path,
+ &f_in,&f_out);
! /* if we're running an rsync server on the remote host over a
! remote shell command, we need to do the RSYNCD protocol first */
! if (daemon_over_rsh) {
! int tmpret;
! tmpret = start_inband_exchange(shell_user, shell_path,
! f_in, f_out, argc, argv);
! if ( tmpret < 0 ) {
! return tmpret;
! }
! }
ret = client_run(f_in, f_out, pid, argc, argv);
***************
*** 712,718 ****
that implement getcwd that way "pwd" can't be found after chroot. */
push_dir(NULL,0);
! if (am_daemon) {
return daemon_main();
}
--- 741,747 ----
that implement getcwd that way "pwd" can't be found after chroot. */
push_dir(NULL,0);
! if (am_daemon && !am_server) {
return daemon_main();
}
***************
*** 734,740 ****
--- 763,773 ----
if (am_server) {
set_nonblocking(STDIN_FILENO);
set_nonblocking(STDOUT_FILENO);
+ if (am_daemon) {
+ return start_daemon(STDIN_FILENO, STDOUT_FILENO);
+ } else {
start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);
+ }
}
return start_client(argc, argv);
Index: options.c
===================================================================
RCS file: /juno/repository/usr/local/pkg/rsync/options.c,v
retrieving revision 1.1.1.4
retrieving revision 1.5
diff -c -b -r1.1.1.4 -r1.5
*** options.c 2001/10/19 04:09:46 1.1.1.4
--- options.c 2001/11/21 03:37:30 1.5
***************
*** 53,58 ****
--- 53,59 ----
int module_id = -1;
int am_server = 0;
int am_sender=0;
+ int daemon_over_rsh = 0;
int recurse = 0;
int am_daemon=0;
int do_stats=0;
***************
*** 84,89 ****
--- 85,91 ----
char *rsync_path = RSYNC_NAME;
char *backup_dir = NULL;
int rsync_port = RSYNC_PORT;
+ char *remote_user = NULL;
int verbose = 0;
int quiet = 0;
***************
*** 104,109 ****
--- 106,113 ----
rprintf(F,"Usage: rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST\n");
rprintf(F," or rsync [OPTION]... [USER@]HOST:SRC DEST\n");
+ rprintf(F," or rsync [OPTION]... SRC [SRC]... [USER@]HOST:::DEST\n");
+ rprintf(F," or rsync [OPTION]... [USER@]HOST:::SRC DEST\n");
rprintf(F," or rsync [OPTION]... SRC [SRC]... DEST\n");
rprintf(F," or rsync [OPTION]... [USER@]HOST::SRC [DEST]\n");
rprintf(F," or rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST\n");
***************
*** 165,170 ****
--- 169,175 ----
rprintf(F," --daemon run as a rsync daemon\n");
rprintf(F," --address bind to the specified address\n");
rprintf(F," --config=FILE specify alternate rsyncd.conf file\n");
+ rprintf(F," --remote-user=USER remote username for ::: mode\n");
rprintf(F," --port=PORT specify alternate rsyncd port number\n");
rprintf(F," --blocking-io use blocking IO for the remote shell\n");
rprintf(F," --stats give some file transfer stats\n");
***************
*** 188,194 ****
OPT_LOG_FORMAT, OPT_PASSWORD_FILE, OPT_SIZE_ONLY, OPT_ADDRESS,
OPT_DELETE_AFTER, OPT_EXISTING, OPT_MAX_DELETE, OPT_BACKUP_DIR,
OPT_IGNORE_ERRORS, OPT_BWLIMIT, OPT_BLOCKING_IO,
! OPT_MODIFY_WINDOW};
static char *short_options = "oblLWHpguDCtcahvqrRIxnSe:B:T:zP";
--- 193,199 ----
OPT_LOG_FORMAT, OPT_PASSWORD_FILE, OPT_SIZE_ONLY, OPT_ADDRESS,
OPT_DELETE_AFTER, OPT_EXISTING, OPT_MAX_DELETE, OPT_BACKUP_DIR,
OPT_IGNORE_ERRORS, OPT_BWLIMIT, OPT_BLOCKING_IO,
! OPT_MODIFY_WINDOW, OPT_REMOTE_USER};
static char *short_options = "oblLWHpguDCtcahvqrRIxnSe:B:T:zP";
***************
*** 249,254 ****
--- 254,260 ----
{"ignore-errors",0, 0, OPT_IGNORE_ERRORS},
{"blocking-io" ,0, 0, OPT_BLOCKING_IO},
{"config", 1, 0, OPT_CONFIG},
+ {"remote-user", 1, 0, OPT_REMOTE_USER},
{"port", 1, 0, OPT_PORT},
{"log-format", 1, 0, OPT_LOG_FORMAT},
{"bwlimit", 1, 0, OPT_BWLIMIT},
***************
*** 571,576 ****
--- 577,586 ----
config_file = optarg;
break;
+ case OPT_REMOTE_USER:
+ remote_user = optarg;
+ break;
+
case OPT_PORT:
rsync_port = atoi(optarg);
break;
***************
*** 620,625 ****
--- 630,642 ----
int i, x;
args[ac++] = "--server";
+
+ if (daemon_over_rsh) {
+ args[ac++] = "--daemon";
+ *argc = ac;
+ /* if we're passing --daemon, we're done */
+ return;
+ }
if (!am_sender)
args[ac++] = "--sender";
Index: proto.h
===================================================================
RCS file: /juno/repository/usr/local/pkg/rsync/proto.h,v
retrieving revision 1.1.1.6
retrieving revision 1.4
diff -c -b -r1.1.1.6 -r1.4
*** proto.h 2001/10/19 04:09:57 1.1.1.6
--- proto.h 2001/11/19 20:31:47 1.4
***************
*** 1,7 ****
/* This file is automatically generated with "make proto". DO NOT EDIT */
int allow_access(char *addr, char *host, char *allow_list, char *deny_list);
! char *auth_server(int fd, int module, char *addr, char *leader);
void auth_client(int fd, char *user, char *challenge);
int make_backup(char *fname);
uint32 get_checksum1(char *buf1,int len);
--- 1,7 ----
/* This file is automatically generated with "make proto". DO NOT EDIT */
int allow_access(char *addr, char *host, char *allow_list, char *deny_list);
! char *auth_server(int f_in, int f_out, int module, char *addr, char *leader);
void auth_client(int fd, char *user, char *challenge);
int make_backup(char *fname);
uint32 get_checksum1(char *buf1,int len);
***************
*** 17,22 ****
--- 17,24 ----
struct map_struct *buf, int fd1, int fd2);
void cleanup_set_pid(int pid);
int start_socket_client(char *host, char *path, int argc, char *argv[]);
+ int start_inband_exchange(char *user, char *path, int f_in, int f_out, int argc, char *argv[]);
+ int start_daemon(int f_in, int f_out);
int daemon_main(void);
void setup_protocol(int f_out,int f_in);
int claim_connection(char *fname,int max_connections);
***************
*** 145,151 ****
void send_files(struct file_list *flist,int f_out,int f_in);
int open_socket_out(char *host, int port, struct in_addr *address);
int is_a_socket(int fd);
! void start_accept_loop(int port, int (*fn)(int ));
void set_socket_options(int fd, char *options);
void become_daemon(void);
char *client_addr(int fd);
--- 147,153 ----
void send_files(struct file_list *flist,int f_out,int f_in);
int open_socket_out(char *host, int port, struct in_addr *address);
int is_a_socket(int fd);
! void start_accept_loop(int port, int (*fn)(int, int));
void set_socket_options(int fd, char *options);
void become_daemon(void);
char *client_addr(int fd);
Index: rsync.1
===================================================================
RCS file: /juno/repository/usr/local/pkg/rsync/rsync.1,v
retrieving revision 1.1.1.6
retrieving revision 1.5
diff -c -b -r1.1.1.6 -r1.5
*** rsync.1 2001/10/19 04:09:42 1.1.1.6
--- rsync.1 2001/11/21 03:37:31 1.5
***************
*** 1,4 ****
! .TH "rsync" "1" "1 Mar 1999" "" ""
.SH "NAME"
rsync \- faster, flexible replacement for rcp
.SH "SYNOPSIS"
--- 1,4 ----
! .TH "rsync" "1" "31 Oct 2001" "" ""
.SH "NAME"
rsync \- faster, flexible replacement for rcp
.SH "SYNOPSIS"
***************
*** 47,53 ****
.PP
.SH "GENERAL"
.PP
! There are six different ways of using rsync\&. They are:
.PP
.IP o
for copying local files\&. This is invoked when neither
--- 47,53 ----
.PP
.SH "GENERAL"
.PP
! There are eight different ways of using rsync\&. They are:
.PP
.IP o
for copying local files\&. This is invoked when neither
***************
*** 75,80 ****
--- 75,92 ----
separator\&.
.IP
.IP o
+ for copying from a remote machine using a remote shell program as the
+ transport, using rsync server on the remote machine\&. This is
+ invoked when the source path contains a :: separator and the \fB-e
+ remote-shell\fR option is also provided\&.
+ .IP
+ .IP o
+ for copying from the local machine to a remote machine using a remote
+ shell program as the transport, using rsync server on the remote
+ machine\&. This is invoked when the destination path contains a ::
+ separator and the \fB-e remote-shell\fR option is also provided\&.
+ .IP
+ .IP o
for listing files on a remote machine\&. This is done the
same way as rsync transfers except that you leave off the
local destination\&.
***************
*** 155,161 ****
transport\&. In this case you will connect to a remote rsync server
running on TCP port 873\&.
.PP
! You may establish the connetcion via a web proxy by setting the
environment variable RSYNC_PROXY to a hostname:port pair pointing to
your web proxy\&. Note that your web proxy must allow proxying to port
873, this must be configured in your proxy servers ruleset\&.
--- 167,173 ----
transport\&. In this case you will connect to a remote rsync server
running on TCP port 873\&.
.PP
! You may establish the connection via a web proxy by setting the
environment variable RSYNC_PROXY to a hostname:port pair pointing to
your web proxy\&. Note that your web proxy must allow proxying to port
873, this must be configured in your proxy servers ruleset\&.
***************
*** 188,199 ****
--- 200,258 ----
WARNING: On some systems environment variables are visible to all
users\&. On those systems using --password-file is recommended\&.
.PP
+ .SH "CONNECTING TO AN RSYNC SERVER OVER A REMOTE SHELL PROGRAM"
+ .PP
+ It is sometimes useful to be able to set up file transfers using rsync
+ server capabilities on the remote machine, while still using rsh or
+ ssh for transport. This is especially useful when you want to connect
+ to a remote machine via ssh (for encryption or to get through a
+ firewall), but you still want to have access to the rsync server
+ features (see \fBRUNNING AN RSYNC SERVER OVER A REMOTE SHELL
+ PROGRAM\fR, below).
+ .PP
+ From the user's perspective, using rsync in this way is the same as
+ using it to connect to an rsync server, except that you must
+ explicitly set the remote shell program on the command line with \fB-e
+ remote-shell\fR. (Setting RSYNC_RSH in the environment will not turn
+ on this functionality\&.)
+ .PP
+ If you connect to a remote host as a user, e.g. via
+ .PP
+ rsync -a local-path user at host::module/remote-path
+ .PP
+ then the \fBuser\fR is for the remote shell connection. If you want
+ to be able to also use different users defined in rsyncd.conf, then
+ you can use the --remote-user=USER option (see below)\&.
+ .PP
.SH "RUNNING AN RSYNC SERVER"
.PP
An rsync server is configured using a config file which by default is
called /etc/rsyncd\&.conf\&. Please see the rsyncd\&.conf(5) man page for more
information\&.
.PP
+ .SH "RUNNING AN RSYNC SERVER OVER A REMOTE SHELL PROGRAM"
+ .PP
+ See the rsyncd\&.conf(5) man page for full information on the rsync
+ server configuration file.
+ .PP
+ Several configuration options will not be available unless the remote
+ user is root (e.g. chroot, setuid/setgid, etc.). There is no need to
+ configure inetd or the services map to include the rsync server port
+ if you run an rsync server via a remote shell program.
+ .PP
+ To run an rsync server out of a single-use ssh key, use the
+ "command=\fIcommand\fR" syntax in the remote user's
+ \fIauthorized_keys\fR entry, where \fIcommand\fR would be
+ .PP
+ rsync --server --daemon .
+ .PP
+ (rsync's argument parsing expects the trailing ".", so make sure that
+ it's there). If you want to use a rsyncd\&.conf(5)-style
+ configuration file other than /etc/rsyncd.conf, you can added a
+ --config-file option to the \fIcommand\fR:
+ .PP
+ rsync --server --daemon --config-file=<file> .
+ .PP
.SH "EXAMPLES"
.PP
Here are some examples of how I use rsync\&.
***************
*** 298,303 ****
--- 357,363 ----
--daemon run as a rsync daemon
--address bind to the specified address
--config=FILE specify alternate rsyncd\&.conf file
+ --remote-user=USER remote username for :: mode
--port=PORT specify alternate rsyncd port number
--blocking-io use blocking IO for the remote shell
--stats give some file transfer stats
***************
*** 566,573 ****
remote copies of rsync\&. By default, rsync will use rsh, but you may
like to instead use ssh because of its high security\&.
.IP
You can also choose the remote shell program using the RSYNC_RSH
! environment variable\&.
.IP
.IP "\fB--rsync-path=PATH\fP"
Use this to specify the path to the copy of
--- 626,641 ----
remote copies of rsync\&. By default, rsync will use rsh, but you may
like to instead use ssh because of its high security\&.
.IP
+ If this option is used with \fB[user@]host::module/path\fR, then the
+ remote shell COMMAND will be used to run an rsync server on the remote
+ host, and all data will be transmitted through that remote shell
+ connection, rather than through a direct socket connection to a
+ running rsync server on the remote host\&.
+ .IP
You can also choose the remote shell program using the RSYNC_RSH
! environment variable\&. However, this will not trigger the
! run-rsync-server-over-a-remote-shell behavior if the :: form is used
! for SOURCE or DEST; that requires an explicit \fB-e remote-shell\fR.
.IP
.IP "\fB--rsync-path=PATH\fP"
Use this to specify the path to the copy of
***************
*** 713,718 ****
--- 781,797 ----
This specifies an alternate config file than
the default /etc/rsyncd\&.conf\&. This is only relevant when --daemon is
specified\&.
+ .IP
+ .IP "\fB--remote-user=USER\fP"
+ This option allows you to specify the \fIrsyncd.conf\fR-level username
+ separately from the rsh/ssh-level username, e.g. when using
+ \fB-e remote-shell\fR and \fBrsh-user at host::module/path\fR. The
+ \fBrsh-user\fR is used for logging into the remote \fBhost\fR at the
+ rsh/ssh level -- and is not necessarily the \fBUSER\fR you want to use
+ at the \fIrsyncd.conf\fR level. Use of this option will use
+ \fBUSER\fR instead of the \fBuser\fR obtained from
+ \fBuser at host::module/path\fR in the protocol between the rsync client
+ and rsync server.
.IP
.IP "\fB--port=PORT\fP"
This specifies an alternate TCP port number to use
Index: socket.c
===================================================================
RCS file: /juno/repository/usr/local/pkg/rsync/socket.c,v
retrieving revision 1.1.1.4
retrieving revision 1.2
diff -c -b -r1.1.1.4 -r1.2
*** socket.c 2001/10/19 04:09:53 1.1.1.4
--- socket.c 2001/11/19 20:31:48 1.2
***************
*** 222,228 ****
}
! void start_accept_loop(int port, int (*fn)(int ))
{
int s;
extern struct in_addr socket_address;
--- 222,228 ----
}
! void start_accept_loop(int port, int (*fn)(int, int))
{
int s;
extern struct in_addr socket_address;
***************
*** 272,278 ****
if (fork()==0) {
close(s);
! _exit(fn(fd));
}
close(fd);
--- 272,278 ----
if (fork()==0) {
close(s);
! _exit(fn(fd, fd));
}
close(fd);
More information about the rsync
mailing list