summaryrefslogtreecommitdiff
path: root/scp.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2008-07-22 19:45:18 +0000
committerColin Watson <cjwatson@debian.org>2008-07-22 19:45:18 +0000
commit137d76ba65883aa8143af1fcad83b57e7badef0c (patch)
treef426e804bb5248ceafedfab7bb78ae6e6752942c /scp.c
parentdac7d049dad31f5f84d421d4eb628a7e13f977d7 (diff)
parentef94e5613d37bcbf880f21ee6094e4b1c7683a4c (diff)
* New upstream release (closes: #474301). Important changes not previously
backported to 4.7p1: - 4.9/4.9p1 (http://www.openssh.com/txt/release-4.9): + Added chroot(2) support for sshd(8), controlled by a new option "ChrootDirectory" (closes: #139047, LP: #24777). + Linked sftp-server(8) into sshd(8). The internal sftp server is used when the command "internal-sftp" is specified in a Subsystem or ForceCommand declaration. When used with ChrootDirectory, the internal sftp server requires no special configuration of files inside the chroot environment. + Added a protocol extension method "posix-rename@openssh.com" for sftp-server(8) to perform POSIX atomic rename() operations; sftp(1) prefers this if available (closes: #308561). + Removed the fixed limit of 100 file handles in sftp-server(8). + ssh(8) will now skip generation of SSH protocol 1 ephemeral server keys when in inetd mode and protocol 2 connections are negotiated. This speeds up protocol 2 connections to inetd-mode servers that also allow Protocol 1. + Accept the PermitRootLogin directive in a sshd_config(5) Match block. Allows for, e.g. permitting root only from the local network. + Reworked sftp(1) argument splitting and escaping to be more internally consistent (i.e. between sftp commands) and more consistent with sh(1). Please note that this will change the interpretation of some quoted strings, especially those with embedded backslash escape sequences. + Support "Banner=none" in sshd_config(5) to disable sending of a pre-login banner (e.g. in a Match block). + ssh(1) ProxyCommands are now executed with $SHELL rather than /bin/sh. + ssh(1)'s ConnectTimeout option is now applied to both the TCP connection and the SSH banner exchange (previously it just covered the TCP connection). This allows callers of ssh(1) to better detect and deal with stuck servers that accept a TCP connection but don't progress the protocol, and also makes ConnectTimeout useful for connections via a ProxyCommand. + scp(1) incorrectly reported "stalled" on slow copies (closes: #140828). + scp(1) date underflow for timestamps before epoch. + ssh(1) used the obsolete SIG DNS RRtype for host keys in DNS, instead of the current standard RRSIG. + Correctly drain ACKs when a sftp(1) upload write fails midway, avoids a fatal() exit from what should be a recoverable condition. + Fixed ssh-keygen(1) selective host key hashing (i.e. "ssh-keygen -HF hostname") to not include any IP address in the data to be hashed. + Make ssh(1) skip listening on the IPv6 wildcard address when a binding address of 0.0.0.0 is used against an old SSH server that does not support the RFC4254 syntax for wildcard bind addresses. + Enable IPV6_V6ONLY socket option on sshd(8) listen socket, as is already done for X11/TCP forwarding sockets (closes: #439661). + Fix FD leak that could hang a ssh(1) connection multiplexing master. + Make ssh(1) -q option documentation consistent with reality. + Fixed sshd(8) PAM support not calling pam_session_close(), or failing to call it with root privileges (closes: #372680). + Fix activation of OpenSSL engine support when requested in configure (LP: #119295). - 5.1/5.1p1 (http://www.openssh.com/txt/release-5.1): + Introduce experimental SSH Fingerprint ASCII Visualisation to ssh(1) and ssh-keygen(1). Visual fingerprint display is controlled by a new ssh_config(5) option "VisualHostKey". The intent is to render SSH host keys in a visual form that is amenable to easy recall and rejection of changed host keys. + sshd_config(5) now supports CIDR address/masklen matching in "Match address" blocks, with a fallback to classic wildcard matching. + sshd(8) now supports CIDR matching in ~/.ssh/authorized_keys from="..." restrictions, also with a fallback to classic wildcard matching. + Added an extended test mode (-T) to sshd(8) to request that it write its effective configuration to stdout and exit. Extended test mode also supports the specification of connection parameters (username, source address and hostname) to test the application of sshd_config(5) Match rules. + ssh(1) now prints the number of bytes transferred and the overall connection throughput for SSH protocol 2 sessions when in verbose mode (previously these statistics were displayed for protocol 1 connections only). + sftp-server(8) now supports extension methods statvfs@openssh.com and fstatvfs@openssh.com that implement statvfs(2)-like operations. + sftp(1) now has a "df" command to the sftp client that uses the statvfs@openssh.com to produce a df(1)-like display of filesystem space and inode utilisation (requires statvfs@openssh.com support on the server). + Added a MaxSessions option to sshd_config(5) to allow control of the number of multiplexed sessions supported over a single TCP connection. This allows increasing the number of allowed sessions above the previous default of 10, disabling connection multiplexing (MaxSessions=1) or disallowing login/shell/subsystem sessions entirely (MaxSessions=0). + Added a no-more-sessions@openssh.com global request extension that is sent from ssh(1) to sshd(8) when the client knows that it will never request another session (i.e. when session multiplexing is disabled). This allows a server to disallow further session requests and terminate the session in cases where the client has been hijacked. + ssh-keygen(1) now supports the use of the -l option in combination with -F to search for a host in ~/.ssh/known_hosts and display its fingerprint. + ssh-keyscan(1) now defaults to "rsa" (protocol 2) keys, instead of "rsa1". + Added an AllowAgentForwarding option to sshd_config(8) to control whether authentication agent forwarding is permitted. Note that this is a loose control, as a client may install their own unofficial forwarder. + ssh(1) and sshd(8): avoid unnecessary malloc/copy/free when receiving network data, resulting in a ~10% speedup. + ssh(1) and sshd(8) will now try additional addresses when connecting to a port forward destination whose DNS name resolves to more than one address. The previous behaviour was to try the only first address and give up if that failed. + ssh(1) and sshd(8) now support signalling that channels are half-closed for writing, through a channel protocol extension notification "eow@openssh.com". This allows propagation of closed file descriptors, so that commands such as "ssh -2 localhost od /bin/ls | true" do not send unnecessary data over the wire. + sshd(8): increased the default size of ssh protocol 1 ephemeral keys from 768 to 1024 bits. + When ssh(1) has been requested to fork after authentication ("ssh -f") with ExitOnForwardFailure enabled, delay the fork until after replies for any -R forwards have been seen. Allows for robust detection of -R forward failure when using -f. + "Match group" blocks in sshd_config(5) now support negation of groups. E.g. "Match group staff,!guests". + sftp(1) and sftp-server(8) now allow chmod-like operations to set set[ug]id/sticky bits. + The MaxAuthTries option is now permitted in sshd_config(5) match blocks. + Multiplexed ssh(1) sessions now support a subset of the ~ escapes that are available to a primary connection. + ssh(1) connection multiplexing will now fall back to creating a new connection in most error cases (closes: #352830). + Make ssh(1) deal more gracefully with channel requests that fail. Previously it would optimistically assume that requests would always succeed, which could cause hangs if they did not (e.g. when the server runs out of file descriptors). + ssh(1) now reports multiplexing errors via the multiplex slave's stderr where possible (subject to LogLevel in the mux master). + Prevent sshd(8) from erroneously applying public key restrictions leaned from ~/.ssh/authorized_keys to other authentication methods when public key authentication subsequently fails (LP: #161047). + Fixed an UMAC alignment problem that manifested on Itanium platforms.
Diffstat (limited to 'scp.c')
-rw-r--r--scp.c116
1 files changed, 85 insertions, 31 deletions
diff --git a/scp.c b/scp.c
index 5d9e4bc29..e2eee035d 100644
--- a/scp.c
+++ b/scp.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: scp.c,v 1.160 2007/08/06 19:16:06 sobrado Exp $ */ 1/* $OpenBSD: scp.c,v 1.163 2008/06/13 18:55:22 dtucker Exp $ */
2/* 2/*
3 * scp - secure remote copy. This is basically patched BSD rcp which 3 * scp - secure remote copy. This is basically patched BSD rcp which
4 * uses ssh to do the data transfer (instead of using rcmd). 4 * uses ssh to do the data transfer (instead of using rcmd).
@@ -78,6 +78,13 @@
78#ifdef HAVE_SYS_STAT_H 78#ifdef HAVE_SYS_STAT_H
79# include <sys/stat.h> 79# include <sys/stat.h>
80#endif 80#endif
81#ifdef HAVE_POLL_H
82#include <poll.h>
83#else
84# ifdef HAVE_SYS_POLL_H
85# include <sys/poll.h>
86# endif
87#endif
81#ifdef HAVE_SYS_TIME_H 88#ifdef HAVE_SYS_TIME_H
82# include <sys/time.h> 89# include <sys/time.h>
83#endif 90#endif
@@ -109,6 +116,8 @@
109 116
110extern char *__progname; 117extern char *__progname;
111 118
119#define COPY_BUFLEN 16384
120
112int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout); 121int do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout);
113 122
114void bwlimit(int); 123void bwlimit(int);
@@ -290,6 +299,7 @@ void sink(int, char *[]);
290void source(int, char *[]); 299void source(int, char *[]);
291void tolocal(int, char *[]); 300void tolocal(int, char *[]);
292void toremote(char *, int, char *[]); 301void toremote(char *, int, char *[]);
302size_t scpio(ssize_t (*)(int, void *, size_t), int, void *, size_t, off_t *);
293void usage(void); 303void usage(void);
294 304
295int 305int
@@ -449,6 +459,43 @@ main(int argc, char **argv)
449 exit(errs != 0); 459 exit(errs != 0);
450} 460}
451 461
462/*
463 * atomicio-like wrapper that also applies bandwidth limits and updates
464 * the progressmeter counter.
465 */
466size_t
467scpio(ssize_t (*f)(int, void *, size_t), int fd, void *_p, size_t l, off_t *c)
468{
469 u_char *p = (u_char *)_p;
470 size_t offset;
471 ssize_t r;
472 struct pollfd pfd;
473
474 pfd.fd = fd;
475 pfd.events = f == read ? POLLIN : POLLOUT;
476 for (offset = 0; offset < l;) {
477 r = f(fd, p + offset, l - offset);
478 if (r == 0) {
479 errno = EPIPE;
480 return offset;
481 }
482 if (r < 0) {
483 if (errno == EINTR)
484 continue;
485 if (errno == EAGAIN || errno == EWOULDBLOCK) {
486 (void)poll(&pfd, 1, -1); /* Ignore errors */
487 continue;
488 }
489 return offset;
490 }
491 offset += (size_t)r;
492 *c += (off_t)r;
493 if (limit_rate)
494 bwlimit(r);
495 }
496 return offset;
497}
498
452void 499void
453toremote(char *targ, int argc, char **argv) 500toremote(char *targ, int argc, char **argv)
454{ 501{
@@ -590,8 +637,8 @@ source(int argc, char **argv)
590 struct stat stb; 637 struct stat stb;
591 static BUF buffer; 638 static BUF buffer;
592 BUF *bp; 639 BUF *bp;
593 off_t i, amt, statbytes; 640 off_t i, statbytes;
594 size_t result; 641 size_t amt;
595 int fd = -1, haderr, indx; 642 int fd = -1, haderr, indx;
596 char *last, *name, buf[2048], encname[MAXPATHLEN]; 643 char *last, *name, buf[2048], encname[MAXPATHLEN];
597 int len; 644 int len;
@@ -612,6 +659,10 @@ source(int argc, char **argv)
612syserr: run_err("%s: %s", name, strerror(errno)); 659syserr: run_err("%s: %s", name, strerror(errno));
613 goto next; 660 goto next;
614 } 661 }
662 if (stb.st_size < 0) {
663 run_err("%s: %s", name, "Negative file size");
664 goto next;
665 }
615 unset_nonblock(fd); 666 unset_nonblock(fd);
616 switch (stb.st_mode & S_IFMT) { 667 switch (stb.st_mode & S_IFMT) {
617 case S_IFREG: 668 case S_IFREG:
@@ -637,8 +688,14 @@ syserr: run_err("%s: %s", name, strerror(errno));
637 * versions expecting microseconds. 688 * versions expecting microseconds.
638 */ 689 */
639 (void) snprintf(buf, sizeof buf, "T%lu 0 %lu 0\n", 690 (void) snprintf(buf, sizeof buf, "T%lu 0 %lu 0\n",
640 (u_long) stb.st_mtime, 691 (u_long) (stb.st_mtime < 0 ? 0 : stb.st_mtime),
641 (u_long) stb.st_atime); 692 (u_long) (stb.st_atime < 0 ? 0 : stb.st_atime));
693 if (verbose_mode) {
694 fprintf(stderr, "File mtime %ld atime %ld\n",
695 (long)stb.st_mtime, (long)stb.st_atime);
696 fprintf(stderr, "Sending file timestamps: %s",
697 buf);
698 }
642 (void) atomicio(vwrite, remout, buf, strlen(buf)); 699 (void) atomicio(vwrite, remout, buf, strlen(buf));
643 if (response() < 0) 700 if (response() < 0)
644 goto next; 701 goto next;
@@ -653,7 +710,7 @@ syserr: run_err("%s: %s", name, strerror(errno));
653 (void) atomicio(vwrite, remout, buf, strlen(buf)); 710 (void) atomicio(vwrite, remout, buf, strlen(buf));
654 if (response() < 0) 711 if (response() < 0)
655 goto next; 712 goto next;
656 if ((bp = allocbuf(&buffer, fd, 2048)) == NULL) { 713 if ((bp = allocbuf(&buffer, fd, COPY_BUFLEN)) == NULL) {
657next: if (fd != -1) { 714next: if (fd != -1) {
658 (void) close(fd); 715 (void) close(fd);
659 fd = -1; 716 fd = -1;
@@ -662,27 +719,25 @@ next: if (fd != -1) {
662 } 719 }
663 if (showprogress) 720 if (showprogress)
664 start_progress_meter(curfile, stb.st_size, &statbytes); 721 start_progress_meter(curfile, stb.st_size, &statbytes);
665 /* Keep writing after an error so that we stay sync'd up. */ 722 set_nonblock(remout);
666 for (haderr = i = 0; i < stb.st_size; i += bp->cnt) { 723 for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
667 amt = bp->cnt; 724 amt = bp->cnt;
668 if (i + amt > stb.st_size) 725 if (i + (off_t)amt > stb.st_size)
669 amt = stb.st_size - i; 726 amt = stb.st_size - i;
670 if (!haderr) { 727 if (!haderr) {
671 result = atomicio(read, fd, bp->buf, amt); 728 if (atomicio(read, fd, bp->buf, amt) != amt)
672 if (result != amt)
673 haderr = errno; 729 haderr = errno;
674 } 730 }
675 if (haderr) 731 /* Keep writing after error to retain sync */
676 (void) atomicio(vwrite, remout, bp->buf, amt); 732 if (haderr) {
677 else { 733 (void)atomicio(vwrite, remout, bp->buf, amt);
678 result = atomicio(vwrite, remout, bp->buf, amt); 734 continue;
679 if (result != amt)
680 haderr = errno;
681 statbytes += result;
682 } 735 }
683 if (limit_rate) 736 if (scpio(vwrite, remout, bp->buf, amt,
684 bwlimit(amt); 737 &statbytes) != amt)
738 haderr = errno;
685 } 739 }
740 unset_nonblock(remout);
686 if (showprogress) 741 if (showprogress)
687 stop_progress_meter(); 742 stop_progress_meter();
688 743
@@ -788,10 +843,10 @@ bwlimit(int amount)
788 thresh /= 2; 843 thresh /= 2;
789 if (thresh < 2048) 844 if (thresh < 2048)
790 thresh = 2048; 845 thresh = 2048;
791 } else if (bwend.tv_usec < 100) { 846 } else if (bwend.tv_usec < 10000) {
792 thresh *= 2; 847 thresh *= 2;
793 if (thresh > 32768) 848 if (thresh > COPY_BUFLEN * 4)
794 thresh = 32768; 849 thresh = COPY_BUFLEN * 4;
795 } 850 }
796 851
797 TIMEVAL_TO_TIMESPEC(&bwend, &ts); 852 TIMEVAL_TO_TIMESPEC(&bwend, &ts);
@@ -982,7 +1037,7 @@ bad: run_err("%s: %s", np, strerror(errno));
982 continue; 1037 continue;
983 } 1038 }
984 (void) atomicio(vwrite, remout, "", 1); 1039 (void) atomicio(vwrite, remout, "", 1);
985 if ((bp = allocbuf(&buffer, ofd, 4096)) == NULL) { 1040 if ((bp = allocbuf(&buffer, ofd, COPY_BUFLEN)) == NULL) {
986 (void) close(ofd); 1041 (void) close(ofd);
987 continue; 1042 continue;
988 } 1043 }
@@ -992,26 +1047,24 @@ bad: run_err("%s: %s", np, strerror(errno));
992 statbytes = 0; 1047 statbytes = 0;
993 if (showprogress) 1048 if (showprogress)
994 start_progress_meter(curfile, size, &statbytes); 1049 start_progress_meter(curfile, size, &statbytes);
995 for (count = i = 0; i < size; i += 4096) { 1050 set_nonblock(remin);
996 amt = 4096; 1051 for (count = i = 0; i < size; i += bp->cnt) {
1052 amt = bp->cnt;
997 if (i + amt > size) 1053 if (i + amt > size)
998 amt = size - i; 1054 amt = size - i;
999 count += amt; 1055 count += amt;
1000 do { 1056 do {
1001 j = atomicio(read, remin, cp, amt); 1057 j = scpio(read, remin, cp, amt, &statbytes);
1002 if (j == 0) { 1058 if (j == 0) {
1003 run_err("%s", j ? strerror(errno) : 1059 run_err("%s", j != EPIPE ?
1060 strerror(errno) :
1004 "dropped connection"); 1061 "dropped connection");
1005 exit(1); 1062 exit(1);
1006 } 1063 }
1007 amt -= j; 1064 amt -= j;
1008 cp += j; 1065 cp += j;
1009 statbytes += j;
1010 } while (amt > 0); 1066 } while (amt > 0);
1011 1067
1012 if (limit_rate)
1013 bwlimit(4096);
1014
1015 if (count == bp->cnt) { 1068 if (count == bp->cnt) {
1016 /* Keep reading so we stay sync'd up. */ 1069 /* Keep reading so we stay sync'd up. */
1017 if (wrerr == NO) { 1070 if (wrerr == NO) {
@@ -1025,6 +1078,7 @@ bad: run_err("%s: %s", np, strerror(errno));
1025 cp = bp->buf; 1078 cp = bp->buf;
1026 } 1079 }
1027 } 1080 }
1081 unset_nonblock(remin);
1028 if (showprogress) 1082 if (showprogress)
1029 stop_progress_meter(); 1083 stop_progress_meter();
1030 if (count != 0 && wrerr == NO && 1084 if (count != 0 && wrerr == NO &&