[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Shipping non-OpenSSH scp(1) binary



On Tue, 11 Jul 2017 at 15:00:02 +0100, Colin Watson wrote:
> On Mon, Jul 10, 2017 at 09:55:15PM +0300, Guilhem Moulin wrote:
>> Meanwhile I had a look at dropbear's scp variant and AFAICT it's
>> actually an almost exact copy of OpenSSH 4.3p2's.  (It's mentioned in
>> the headers, and the diff is pretty minimal.)
> 
> Could you attach the diff?

Attached.

-- 
Guilhem.
diff -u a/scp.c b/scp.c
--- a/scp.c
+++ b/scp.c
@@ -1,3 +1,6 @@
+/* Dropbear Note: This file is based on OpenSSH 4.3p2. Avoid unnecessary 
+   changes to simplify future updates */
+
 /*
  * scp - secure remote copy.  This is basically patched BSD rcp which
  * uses ssh to do the data transfer (instead of using rcmd).
@@ -71,17 +74,13 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: scp.c,v 1.130 2006/01/31 10:35:43 djm Exp $");
+/*RCSID("$OpenBSD: scp.c,v 1.130 2006/01/31 10:35:43 djm Exp $");*/
 
-#include "xmalloc.h"
 #include "atomicio.h"
-#include "pathnames.h"
-#include "log.h"
-#include "misc.h"
+#include "compat.h"
+#include "scpmisc.h"
 #include "progressmeter.h"
 
-extern char *__progname;
-
 void bwlimit(int);
 
 /* Struct for addargs */
@@ -100,7 +99,7 @@
 int showprogress = 1;
 
 /* This is the program to execute for the secured connection. ("ssh" or -S) */
-char *ssh_program = _PATH_SSH_PROGRAM;
+char *ssh_program = DROPBEAR_PATH_SSH_PROGRAM;
 
 /* This is used to store the pid of ssh_program */
 pid_t do_cmd_pid = -1;
@@ -134,13 +133,22 @@
 			fprintf(stderr, " %s", a->list[i]);
 		fprintf(stderr, "\n");
 	}
-	if ((pid = fork()) == -1)
+#ifdef USE_VFORK
+	pid = vfork();
+#else
+	pid = fork();
+#endif
+	if (pid == -1)
 		fatal("do_local_cmd: fork: %s", strerror(errno));
 
 	if (pid == 0) {
 		execvp(a->list[0], a->list);
 		perror(a->list[0]);
+#ifdef USE_VFORK
+		_exit(1);
+#else
 		exit(1);
+#endif
 	}
 
 	do_cmd_pid = pid;
@@ -166,6 +174,16 @@
  * assigns the input and output file descriptors on success.
  */
 
+static void
+arg_setup(char *host, char *remuser, char *cmd)
+{
+	replacearg(&args, 0, "%s", ssh_program);
+	if (remuser != NULL)
+		addargs(&args, "-l%s", remuser);
+	addargs(&args, "%s", host);
+	addargs(&args, "%s", cmd);
+}
+
 int
 do_cmd(char *host, char *remuser, char *cmd, int *fdin, int *fdout, int argc)
 {
@@ -193,8 +211,19 @@
 	close(reserved[0]);
 	close(reserved[1]);
 
+	/* uClinux needs to build the args here before vforking,
+	   otherwise we do it later on. */
+#ifdef USE_VFORK
+	arg_setup(host, remuser, cmd);
+#endif
+
 	/* Fork a child to execute the command on the remote host using ssh. */
+#ifdef USE_VFORK
+	do_cmd_pid = vfork();
+#else
 	do_cmd_pid = fork();
+#endif
+
 	if (do_cmd_pid == 0) {
 		/* Child. */
 		close(pin[1]);
@@ -204,18 +233,39 @@
 		close(pin[0]);
 		close(pout[1]);
 
-		replacearg(&args, 0, "%s", ssh_program);
-		if (remuser != NULL)
-			addargs(&args, "-l%s", remuser);
-		addargs(&args, "%s", host);
-		addargs(&args, "%s", cmd);
+#ifndef USE_VFORK
+		arg_setup(host, remuser, cmd);
+#endif
 
 		execvp(ssh_program, args.list);
 		perror(ssh_program);
+#ifdef USE_VFORK
+		_exit(1);
+#else
 		exit(1);
+#endif
 	} else if (do_cmd_pid == -1) {
 		fatal("fork: %s", strerror(errno));
 	}
+
+#ifdef USE_VFORK
+	/* clean up command */
+	/* pop cmd */
+	xfree(args.list[args.num-1]);
+	args.list[args.num-1]=NULL;
+	args.num--;
+	/* pop host */
+	xfree(args.list[args.num-1]);
+	args.list[args.num-1]=NULL;
+	args.num--;
+	/* pop user */
+	if (remuser != NULL) {
+		xfree(args.list[args.num-1]);
+		args.list[args.num-1]=NULL;
+		args.num--;
+	}
+#endif
+
 	/* Parent.  Close the other side, and return the local side. */
 	close(pin[0]);
 	*fdout = pin[1];
@@ -239,7 +289,6 @@
 void run_err(const char *,...);
 void verifydir(char *);
 
-struct passwd *pwd;
 uid_t userid;
 int errs, remin, remout;
 int pflag, iamremote, iamrecursive, targetshouldbedirectory;
@@ -255,8 +304,13 @@
 void toremote(char *, int, char *[]);
 void usage(void);
 
+#if defined(DBMULTI_scp) || !defined(DROPBEAR_MULTI)
+#if defined(DBMULTI_scp) && defined(DROPBEAR_MULTI)
+int scp_main(int argc, char **argv)
+#else
 int
 main(int argc, char **argv)
+#endif
 {
 	int ch, fflag, tflag, status;
 	double speed;
@@ -267,15 +321,9 @@
 	/* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
 	sanitise_stdfd();
 
-	__progname = ssh_get_progname(argv[0]);
-
 	memset(&args, '\0', sizeof(args));
 	args.list = NULL;
 	addargs(&args, "%s", ssh_program);
-	addargs(&args, "-x");
-	addargs(&args, "-oForwardAgent no");
-	addargs(&args, "-oPermitLocalCommand no");
-	addargs(&args, "-oClearAllForwardings yes");
 
 	fflag = tflag = 0;
 	while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q1246S:o:F:")) != -1)
@@ -298,7 +346,7 @@
 			addargs(&args, "-p%s", optarg);
 			break;
 		case 'B':
-			addargs(&args, "-oBatchmode yes");
+			fprintf(stderr, "Note: -B option is disabled in this version of scp");
 			break;
 		case 'l':
 			speed = strtod(optarg, &endp);
@@ -320,8 +368,10 @@
 			verbose_mode = 1;
 			break;
 		case 'q':
+#ifdef PROGRESS_METER
 			addargs(&args, "-q");
 			showprogress = 0;
+#endif
 			break;
 
 		/* Server options. */
@@ -345,9 +395,6 @@
 	argc -= optind;
 	argv += optind;
 
-	if ((pwd = getpwuid(userid = getuid())) == NULL)
-		fatal("unknown user %u", (u_int) userid);
-
 	if (!isatty(STDERR_FILENO))
 		showprogress = 0;
 
@@ -389,13 +436,13 @@
 	}
 	/*
 	 * Finally check the exit status of the ssh process, if one was forked
-	 * and no error has occured yet
+	 * and no error has occurred yet
 	 */
 	if (do_cmd_pid != -1 && errs == 0) {
 		if (remin != -1)
-		    (void) close(remin);
+			(void) close(remin);
 		if (remout != -1)
-		    (void) close(remout);
+			(void) close(remout);
 		if (waitpid(do_cmd_pid, &status, 0) == -1)
 			errs = 1;
 		else {
@@ -405,6 +452,7 @@
 	}
 	exit(errs != 0);
 }
+#endif /* DBMULTI_scp stuff */
 
 void
 toremote(char *targ, int argc, char **argv)
@@ -444,9 +492,13 @@
 			addargs(&alist, "%s", ssh_program);
 			if (verbose_mode)
 				addargs(&alist, "-v");
+#if 0
+			/* Disabled since dbclient won't understand them
+			   and scp works fine without them. */
 			addargs(&alist, "-x");
 			addargs(&alist, "-oClearAllForwardings yes");
 			addargs(&alist, "-n");
+#endif
 
 			*src++ = 0;
 			if (*src == 0)
@@ -458,7 +510,7 @@
 				host = cleanhostname(host);
 				suser = argv[i];
 				if (*suser == '\0')
-					suser = pwd->pw_name;
+					continue; /* pretend there wasn't any @ at all */
 				else if (!okname(suser))
 					continue;
 				addargs(&alist, "-l");
@@ -526,7 +578,7 @@
 			*host++ = 0;
 			suser = argv[i];
 			if (*suser == '\0')
-				suser = pwd->pw_name;
+				suser = NULL;
 		}
 		host = cleanhostname(host);
 		len = strlen(src) + CMDNEEDS + 20;
@@ -620,8 +672,10 @@
 			}
 			continue;
 		}
+#ifdef PROGRESS_METER
 		if (showprogress)
 			start_progress_meter(curfile, stb.st_size, &statbytes);
+#endif
 		/* Keep writing after an error so that we stay sync'd up. */
 		for (haderr = i = 0; i < stb.st_size; i += bp->cnt) {
 			amt = bp->cnt;
@@ -643,8 +697,10 @@
 			if (limit_rate)
 				bwlimit(amt);
 		}
+#ifdef PROGRESS_METER
 		if (showprogress)
 			stop_progress_meter();
+#endif
 
 		if (fd != -1) {
 			if (close(fd) < 0 && !haderr)
@@ -716,8 +772,8 @@
 bwlimit(int amount)
 {
 	static struct timeval bwstart, bwend;
-	static int lamt, thresh = 16384;
-	u_int64_t waitlen;
+	static int lamt = 0, thresh = 16384;
+	uint64_t waitlen;
 	struct timespec ts, rm;
 
 	if (!timerisset(&bwstart)) {
@@ -785,7 +841,7 @@
 
 #define	atime	tv[0]
 #define	mtime	tv[1]
-#define	SCREWUP(str)	{ why = str; goto screwup; }
+#define	SCREWUP(str)	do { why = str; goto screwup; } while (0)
 
 	setimes = targisdir = 0;
 	mask = umask(0);
@@ -884,8 +940,8 @@
 			exit(1);
 		}
 		if (targisdir) {
-			static char *namebuf;
-			static size_t cursize;
+			static char *namebuf = NULL;
+			static size_t cursize = 0;
 			size_t need;
 
 			need = strlen(targ) + strlen(cp) + 250;
@@ -935,7 +991,7 @@
 			continue;
 		}
 		omode = mode;
-		mode |= S_IWRITE;
+		mode |= S_IWUSR;
 		if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) {
 bad:			run_err("%s: %s", np, strerror(errno));
 			continue;
@@ -949,8 +1005,10 @@
 		wrerr = NO;
 
 		statbytes = 0;
+#ifdef PROGRESS_METER
 		if (showprogress)
 			start_progress_meter(curfile, size, &statbytes);
+#endif
 		for (count = i = 0; i < size; i += 4096) {
 			amt = 4096;
 			if (i + amt > size)
@@ -984,8 +1042,10 @@
 				cp = bp->buf;
 			}
 		}
+#ifdef PROGRESS_METER
 		if (showprogress)
 			stop_progress_meter();
+#endif
 		if (count != 0 && wrerr == NO &&
 		    atomicio(vwrite, ofd, bp->buf, count) != count) {
 			wrerr = YES;
@@ -1085,7 +1145,7 @@
 {
 	(void) fprintf(stderr,
 	    "usage: scp [-1246BCpqrv] [-c cipher] [-F ssh_config] [-i identity_file]\n"
-	    "           [-l limit] [-o ssh_option] [-P port] [-S program]\n"
+	    "           [-l limit] [-P port] [-S program]\n"
 	    "           [[user@]host1:]file1 [...] [[user@]host2:]file2\n");
 	exit(1);
 }
@@ -1093,7 +1153,7 @@
 void
 run_err(const char *fmt,...)
 {
-	static FILE *fp;
+	static FILE *fp = NULL;
 	va_list ap;
 
 	++errs;
diff -u a/atomicio.h b/atomicio.h
--- a/atomicio.h
+++ b/atomicio.h
@@ -1,6 +1,9 @@
-/*	$OpenBSD: atomicio.h,v 1.6 2005/05/24 17:32:43 avsm Exp $	*/
 
 /*
+ * Copied from OpenSSH 3.6.1p2, required for loginrec.c
+ *
+ * $OpenBSD: atomicio.h,v 1.4 2001/06/26 06:32:46 itojun Exp $
+ *
  * Copyright (c) 1995,1999 Theo de Raadt.  All rights reserved.
  * All rights reserved.
  *
@@ -25,9 +28,9 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include "includes.h"
+
 /*
- * Ensure all of data on socket comes through. f==read || f==vwrite
+ * Ensure all of data on socket comes through. f==read || f==write
  */
-size_t	atomicio(ssize_t (*)(int, void *, size_t), int, void *, size_t);
-
-#define vwrite (ssize_t (*)(int, void *, size_t))write
+ssize_t	atomicio(ssize_t (*)(), int, void *, size_t);
diff -u a/atomicio.c b/atomicio.c
--- a/atomicio.c
+++ b/atomicio.c
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
+ * Copied from OpenSSH 3.6.1p2.
+ * 
  * Copyright (c) 1995,1999 Theo de Raadt.  All rights reserved.
  * All rights reserved.
  *
@@ -24,24 +25,23 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "includes.h"
-RCSID("$OpenBSD: atomicio.c,v 1.13 2005/05/24 17:32:43 avsm Exp $");
+/* RCSID("OpenBSD: atomicio.c,v 1.10 2001/05/08 22:48:07 markus Exp "); */
 
 #include "atomicio.h"
 
 /*
- * ensure all of data on socket comes through. f==read || f==vwrite
+ * ensure all of data on socket comes through. f==read || f==write
  */
-size_t
+ssize_t
 atomicio(f, fd, _s, n)
-	ssize_t (*f) (int, void *, size_t);
+	ssize_t (*f) ();
 	int fd;
 	void *_s;
 	size_t n;
 {
 	char *s = _s;
-	size_t pos = 0;
 	ssize_t res;
+	size_t pos = 0;
 
 	while (n > pos) {
 		res = (f) (fd, s + pos, n - pos);
@@ -53,12 +53,11 @@
 			if (errno == EINTR || errno == EAGAIN)
 #endif
 				continue;
-			return 0;
+			/* FALLTHROUGH */
 		case 0:
-			errno = EPIPE;
-			return pos;
+			return (res);
 		default:
-			pos += (u_int)res;
+			pos += res;
 		}
 	}
 	return (pos);
diff -u a/misc.h b/scpmisc.h
--- a/misc.h
+++ b/scpmisc.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: misc.h,v 1.29 2006/01/31 10:19:02 djm Exp $	*/
+/*	$OpenBSD: misc.h,v 1.12 2002/03/19 10:49:35 markus Exp $	*/
 
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -12,58 +12,58 @@
  * called by a name other than "ssh" or "Secure Shell".
  */
 
-/* misc.c */
+/* actually from atomicio, but is only used in scp code */
+#define vwrite (ssize_t (*)(int, void *, size_t))write
 
 char	*chop(char *);
 char	*strdelim(char **);
-int	 set_nonblock(int);
-int	 unset_nonblock(int);
+void	 set_nonblock(int);
+void	 unset_nonblock(int);
 void	 set_nodelay(int);
 int	 a2port(const char *);
-int	 a2tun(const char *, int *);
-char	*hpdelim(char **);
 char	*cleanhostname(char *);
 char	*colon(char *);
 long	 convtime(const char *);
-char	*tilde_expand_filename(const char *, uid_t);
-char	*percent_expand(const char *, ...) __attribute__((__sentinel__));
-char	*tohex(const u_char *, u_int);
-void	 sanitise_stdfd(void);
 
 struct passwd *pwcopy(struct passwd *);
 
 typedef struct arglist arglist;
 struct arglist {
 	char    **list;
-	u_int   num;
-	u_int   nalloc;
+	int     num;
+	int     nalloc;
 };
-void	 addargs(arglist *, char *, ...)
-	     __attribute__((format(printf, 2, 3)));
-void	 replacearg(arglist *, u_int, char *, ...)
-	     __attribute__((format(printf, 3, 4)));
+void	 addargs(arglist *, char *, ...);
+void	 replacearg(arglist *, u_int, char *, ...);
 void	 freeargs(arglist *);
 
-/* readpass.c */
+/* from xmalloc.h */
+void	*xmalloc(size_t);
+void	*xrealloc(void *, size_t);
+void     xfree(void *);
+char	*xstrdup(const char *);
+
+char *ssh_get_progname(char *);
+void fatal(char* fmt,...);
+void sanitise_stdfd(void);
+
+/* Required for non-BSD platforms, from OpenSSH's defines.h */
+#ifndef timersub
+#define timersub(a, b, result)                  \
+   do {                             \
+      (result)->tv_sec = (a)->tv_sec - (b)->tv_sec;     \
+      (result)->tv_usec = (a)->tv_usec - (b)->tv_usec;      \
+      if ((result)->tv_usec < 0) {              \
+     --(result)->tv_sec;                    \
+     (result)->tv_usec += 1000000;              \
+      }                             \
+   } while (0)
+#endif
+
+#ifndef TIMEVAL_TO_TIMESPEC
+#define TIMEVAL_TO_TIMESPEC(tv, ts) {                   \
+    (ts)->tv_sec = (tv)->tv_sec;                    \
+    (ts)->tv_nsec = (tv)->tv_usec * 1000;               \
+}
+#endif
 
-#define RP_ECHO			0x0001
-#define RP_ALLOW_STDIN		0x0002
-#define RP_ALLOW_EOF		0x0004
-#define RP_USE_ASKPASS		0x0008
-
-char	*read_passphrase(const char *, int);
-int	 ask_permission(const char *, ...) __attribute__((format(printf, 1, 2)));
-int	 read_keyfile_line(FILE *, const char *, char *, size_t, u_long *);
-
-int	 tun_open(int, int);
-
-/* Common definitions for ssh tunnel device forwarding */
-#define SSH_TUNMODE_NO		0x00
-#define SSH_TUNMODE_POINTOPOINT	0x01
-#define SSH_TUNMODE_ETHERNET	0x02
-#define SSH_TUNMODE_DEFAULT	SSH_TUNMODE_POINTOPOINT
-#define SSH_TUNMODE_YES		(SSH_TUNMODE_POINTOPOINT|SSH_TUNMODE_ETHERNET)
-
-#define SSH_TUNID_ANY		0x7fffffff
-#define SSH_TUNID_ERR		(SSH_TUNID_ANY - 1)
-#define SSH_TUNID_MAX		(SSH_TUNID_ANY - 2)
diff -u a/misc.c b/scpmisc.c
--- a/misc.c
+++ b/scpmisc.c
@@ -1,6 +1,8 @@
+/* Dropbear Note: This file is based on OpenSSH 4.3p2. Avoid unnecessary 
+   changes to simplify future updates */
+
 /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.
- * Copyright (c) 2005 Damien Miller.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -23,334 +25,85 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include "includes.h"
-RCSID("$OpenBSD: misc.c,v 1.42 2006/01/31 10:19:02 djm Exp $");
-
-#ifdef SSH_TUN_OPENBSD
-#include <net/if.h>
-#endif
+/*RCSID("OpenBSD: misc.c,v 1.22 2003/09/18 08:49:45 markus Exp ");*/
 
-#include "misc.h"
-#include "log.h"
-#include "xmalloc.h"
+/* For xmalloc, xfree etc:
+ * Author: Tatu Ylonen <ylo@cs.hut.fi>
+ * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
+ *                    All rights reserved
+ * Versions of malloc and friends that check their results, and never return
+ * failure (they call fatal if they encounter an error).
+ *
+ * As far as I am concerned, the code I have written for this software
+ * can be used freely for any purpose.  Any derived versions of this
+ * software must be clearly marked as such, and if the derived work is
+ * incompatible with the protocol description in the RFC file, it must be
+ * called by a name other than "ssh" or "Secure Shell".
+ */
 
-/* remove newline at end of string */
-char *
-chop(char *s)
-{
-	char *t = s;
-	while (*t) {
-		if (*t == '\n' || *t == '\r') {
-			*t = '\0';
-			return s;
-		}
-		t++;
-	}
-	return s;
+/*RCSID("OpenBSD: xmalloc.c,v 1.16 2001/07/23 18:21:46 stevesk Exp ");*/
 
-}
+#define _GNU_SOURCE
+#include "includes.h"
+#include "scpmisc.h"
 
-/* set/unset filedescriptor to non-blocking */
-int
-set_nonblock(int fd)
+void *
+xmalloc(size_t size)
 {
-	int val;
+	void *ptr;
 
-	val = fcntl(fd, F_GETFL, 0);
-	if (val < 0) {
-		error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
-		return (-1);
-	}
-	if (val & O_NONBLOCK) {
-		debug3("fd %d is O_NONBLOCK", fd);
-		return (0);
+	if (size == 0) {
+		fprintf(stderr, "xmalloc: zero size\n");
+		exit(EXIT_FAILURE);
 	}
-	debug2("fd %d setting O_NONBLOCK", fd);
-	val |= O_NONBLOCK;
-	if (fcntl(fd, F_SETFL, val) == -1) {
-		debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", fd,
-		    strerror(errno));
-		return (-1);
+	ptr = malloc(size);
+	if (ptr == NULL) {
+		fprintf(stderr, "xmalloc: out of memory (allocating %lu bytes)\n", (u_long) size);
+		exit(EXIT_FAILURE);
 	}
-	return (0);
+	return ptr;
 }
 
-int
-unset_nonblock(int fd)
+void *
+xrealloc(void *ptr, size_t new_size)
 {
-	int val;
+	void *new_ptr;
 
-	val = fcntl(fd, F_GETFL, 0);
-	if (val < 0) {
-		error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno));
-		return (-1);
-	}
-	if (!(val & O_NONBLOCK)) {
-		debug3("fd %d is not O_NONBLOCK", fd);
-		return (0);
+	if (new_size == 0) {
+		fprintf(stderr, "xrealloc: zero size\n");
+		exit(EXIT_FAILURE);
 	}
-	debug("fd %d clearing O_NONBLOCK", fd);
-	val &= ~O_NONBLOCK;
-	if (fcntl(fd, F_SETFL, val) == -1) {
-		debug("fcntl(%d, F_SETFL, ~O_NONBLOCK): %s",
-		    fd, strerror(errno));
-		return (-1);
+	if (ptr == NULL)
+		new_ptr = malloc(new_size);
+	else
+		new_ptr = realloc(ptr, new_size);
+	if (new_ptr == NULL) {
+		fprintf(stderr, "xrealloc: out of memory (new_size %lu bytes)\n", (u_long) new_size);
+		exit(EXIT_FAILURE);
 	}
-	return (0);
+	return new_ptr;
 }
 
-/* disable nagle on socket */
 void
-set_nodelay(int fd)
-{
-	int opt;
-	socklen_t optlen;
-
-	optlen = sizeof opt;
-	if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) {
-		debug("getsockopt TCP_NODELAY: %.100s", strerror(errno));
-		return;
-	}
-	if (opt == 1) {
-		debug2("fd %d is TCP_NODELAY", fd);
-		return;
-	}
-	opt = 1;
-	debug2("fd %d setting TCP_NODELAY", fd);
-	if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1)
-		error("setsockopt TCP_NODELAY: %.100s", strerror(errno));
-}
-
-/* Characters considered whitespace in strsep calls. */
-#define WHITESPACE " \t\r\n"
-
-/* return next token in configuration line */
-char *
-strdelim(char **s)
-{
-	char *old;
-	int wspace = 0;
-
-	if (*s == NULL)
-		return NULL;
-
-	old = *s;
-
-	*s = strpbrk(*s, WHITESPACE "=");
-	if (*s == NULL)
-		return (old);
-
-	/* Allow only one '=' to be skipped */
-	if (*s[0] == '=')
-		wspace = 1;
-	*s[0] = '\0';
-
-	*s += strspn(*s + 1, WHITESPACE) + 1;
-	if (*s[0] == '=' && !wspace)
-		*s += strspn(*s + 1, WHITESPACE) + 1;
-
-	return (old);
-}
-
-struct passwd *
-pwcopy(struct passwd *pw)
-{
-	struct passwd *copy = xmalloc(sizeof(*copy));
-
-	memset(copy, 0, sizeof(*copy));
-	copy->pw_name = xstrdup(pw->pw_name);
-	copy->pw_passwd = xstrdup(pw->pw_passwd);
-	copy->pw_gecos = xstrdup(pw->pw_gecos);
-	copy->pw_uid = pw->pw_uid;
-	copy->pw_gid = pw->pw_gid;
-#ifdef HAVE_PW_EXPIRE_IN_PASSWD
-	copy->pw_expire = pw->pw_expire;
-#endif
-#ifdef HAVE_PW_CHANGE_IN_PASSWD
-	copy->pw_change = pw->pw_change;
-#endif
-#ifdef HAVE_PW_CLASS_IN_PASSWD
-	copy->pw_class = xstrdup(pw->pw_class);
-#endif
-	copy->pw_dir = xstrdup(pw->pw_dir);
-	copy->pw_shell = xstrdup(pw->pw_shell);
-	return copy;
-}
-
-/*
- * Convert ASCII string to TCP/IP port number.
- * Port must be >0 and <=65535.
- * Return 0 if invalid.
- */
-int
-a2port(const char *s)
-{
-	long port;
-	char *endp;
-
-	errno = 0;
-	port = strtol(s, &endp, 0);
-	if (s == endp || *endp != '\0' ||
-	    (errno == ERANGE && (port == LONG_MIN || port == LONG_MAX)) ||
-	    port <= 0 || port > 65535)
-		return 0;
-
-	return port;
-}
-
-int
-a2tun(const char *s, int *remote)
-{
-	const char *errstr = NULL;
-	char *sp, *ep;
-	int tun;
-
-	if (remote != NULL) {
-		*remote = SSH_TUNID_ANY;
-		sp = xstrdup(s);
-		if ((ep = strchr(sp, ':')) == NULL) {
-			xfree(sp);
-			return (a2tun(s, NULL));
-		}
-		ep[0] = '\0'; ep++;
-		*remote = a2tun(ep, NULL);
-		tun = a2tun(sp, NULL);
-		xfree(sp);
-		return (*remote == SSH_TUNID_ERR ? *remote : tun);
-	}
-
-	if (strcasecmp(s, "any") == 0)
-		return (SSH_TUNID_ANY);
-
-	tun = strtonum(s, 0, SSH_TUNID_MAX, &errstr);
-	if (errstr != NULL)
-		return (SSH_TUNID_ERR);
-
-	return (tun);
-}
-
-#define SECONDS		1
-#define MINUTES		(SECONDS * 60)
-#define HOURS		(MINUTES * 60)
-#define DAYS		(HOURS * 24)
-#define WEEKS		(DAYS * 7)
-
-/*
- * Convert a time string into seconds; format is
- * a sequence of:
- *      time[qualifier]
- *
- * Valid time qualifiers are:
- *      <none>  seconds
- *      s|S     seconds
- *      m|M     minutes
- *      h|H     hours
- *      d|D     days
- *      w|W     weeks
- *
- * Examples:
- *      90m     90 minutes
- *      1h30m   90 minutes
- *      2d      2 days
- *      1w      1 week
- *
- * Return -1 if time string is invalid.
- */
-long
-convtime(const char *s)
+xfree(void *ptr)
 {
-	long total, secs;
-	const char *p;
-	char *endp;
-
-	errno = 0;
-	total = 0;
-	p = s;
-
-	if (p == NULL || *p == '\0')
-		return -1;
-
-	while (*p) {
-		secs = strtol(p, &endp, 10);
-		if (p == endp ||
-		    (errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) ||
-		    secs < 0)
-			return -1;
-
-		switch (*endp++) {
-		case '\0':
-			endp--;
-		case 's':
-		case 'S':
-			break;
-		case 'm':
-		case 'M':
-			secs *= MINUTES;
-			break;
-		case 'h':
-		case 'H':
-			secs *= HOURS;
-			break;
-		case 'd':
-		case 'D':
-			secs *= DAYS;
-			break;
-		case 'w':
-		case 'W':
-			secs *= WEEKS;
-			break;
-		default:
-			return -1;
-		}
-		total += secs;
-		if (total < 0)
-			return -1;
-		p = endp;
+	if (ptr == NULL) {
+		fprintf(stderr, "xfree: NULL pointer given as argument\n");
+		exit(EXIT_FAILURE);
 	}
-
-	return total;
+	free(ptr);
 }
 
-/*
- * Search for next delimiter between hostnames/addresses and ports.
- * Argument may be modified (for termination).
- * Returns *cp if parsing succeeds.
- * *cp is set to the start of the next delimiter, if one was found.
- * If this is the last field, *cp is set to NULL.
- */
 char *
-hpdelim(char **cp)
+xstrdup(const char *str)
 {
-	char *s, *old;
-
-	if (cp == NULL || *cp == NULL)
-		return NULL;
-
-	old = s = *cp;
-	if (*s == '[') {
-		if ((s = strchr(s, ']')) == NULL)
-			return NULL;
-		else
-			s++;
-	} else if ((s = strpbrk(s, ":/")) == NULL)
-		s = *cp + strlen(*cp); /* skip to end (see first case below) */
-
-	switch (*s) {
-	case '\0':
-		*cp = NULL;	/* no more fields*/
-		break;
-
-	case ':':
-	case '/':
-		*s = '\0';	/* terminate */
-		*cp = s + 1;
-		break;
-
-	default:
-		return NULL;
-	}
+	size_t len;
+	char *cp;
 
-	return old;
+	len = strlen(str) + 1;
+	cp = xmalloc(len);
+	strncpy(cp, str, len);
+	return cp;
 }
 
 char *
@@ -449,205 +202,32 @@
 }
 
 /*
- * Expands tildes in the file name.  Returns data allocated by xmalloc.
- * Warning: this calls getpw*.
- */
-char *
-tilde_expand_filename(const char *filename, uid_t uid)
-{
-	const char *path;
-	char user[128], ret[MAXPATHLEN];
-	struct passwd *pw;
-	u_int len, slash;
-
-	if (*filename != '~')
-		return (xstrdup(filename));
-	filename++;
-
-	path = strchr(filename, '/');
-	if (path != NULL && path > filename) {		/* ~user/path */
-		slash = path - filename;
-		if (slash > sizeof(user) - 1)
-			fatal("tilde_expand_filename: ~username too long");
-		memcpy(user, filename, slash);
-		user[slash] = '\0';
-		if ((pw = getpwnam(user)) == NULL)
-			fatal("tilde_expand_filename: No such user %s", user);
-	} else if ((pw = getpwuid(uid)) == NULL)	/* ~/path */
-		fatal("tilde_expand_filename: No such uid %d", uid);
-
-	if (strlcpy(ret, pw->pw_dir, sizeof(ret)) >= sizeof(ret))
-		fatal("tilde_expand_filename: Path too long");
-
-	/* Make sure directory has a trailing '/' */
-	len = strlen(pw->pw_dir);
-	if ((len == 0 || pw->pw_dir[len - 1] != '/') &&
-	    strlcat(ret, "/", sizeof(ret)) >= sizeof(ret))
-		fatal("tilde_expand_filename: Path too long");
-
-	/* Skip leading '/' from specified path */
-	if (path != NULL)
-		filename = path + 1;
-	if (strlcat(ret, filename, sizeof(ret)) >= sizeof(ret))
-		fatal("tilde_expand_filename: Path too long");
-
-	return (xstrdup(ret));
-}
-
-/*
- * Expand a string with a set of %[char] escapes. A number of escapes may be
- * specified as (char *escape_chars, char *replacement) pairs. The list must
- * be terminated by a NULL escape_char. Returns replaced string in memory
- * allocated by xmalloc.
+ * NB. duplicate __progname in case it is an alias for argv[0]
+ * Otherwise it may get clobbered by setproctitle()
  */
-char *
-percent_expand(const char *string, ...)
+char *ssh_get_progname(char *argv0)
 {
-#define EXPAND_MAX_KEYS	16
-	struct {
-		const char *key;
-		const char *repl;
-	} keys[EXPAND_MAX_KEYS];
-	u_int num_keys, i, j;
-	char buf[4096];
-	va_list ap;
-
-	/* Gather keys */
-	va_start(ap, string);
-	for (num_keys = 0; num_keys < EXPAND_MAX_KEYS; num_keys++) {
-		keys[num_keys].key = va_arg(ap, char *);
-		if (keys[num_keys].key == NULL)
-			break;
-		keys[num_keys].repl = va_arg(ap, char *);
-		if (keys[num_keys].repl == NULL)
-			fatal("percent_expand: NULL replacement");
-	}
-	va_end(ap);
-
-	if (num_keys >= EXPAND_MAX_KEYS)
-		fatal("percent_expand: too many keys");
+	char *p;
 
-	/* Expand string */
-	*buf = '\0';
-	for (i = 0; *string != '\0'; string++) {
-		if (*string != '%') {
- append:
-			buf[i++] = *string;
-			if (i >= sizeof(buf))
-				fatal("percent_expand: string too long");
-			buf[i] = '\0';
-			continue;
-		}
-		string++;
-		if (*string == '%')
-			goto append;
-		for (j = 0; j < num_keys; j++) {
-			if (strchr(keys[j].key, *string) != NULL) {
-				i = strlcat(buf, keys[j].repl, sizeof(buf));
-				if (i >= sizeof(buf))
-					fatal("percent_expand: string too long");
-				break;
-			}
-		}
-		if (j >= num_keys)
-			fatal("percent_expand: unknown key %%%c", *string);
-	}
-	return (xstrdup(buf));
-#undef EXPAND_MAX_KEYS
-}
+	if (argv0 == NULL)
+		return ("unknown");	/* XXX */
+	p = strrchr(argv0, '/');
+	if (p == NULL)
+		p = argv0;
+	else
+		p++;
 
-/*
- * Read an entire line from a public key file into a static buffer, discarding
- * lines that exceed the buffer size.  Returns 0 on success, -1 on failure.
- */
-int
-read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz,
-   u_long *lineno)
-{
-	while (fgets(buf, bufsz, f) != NULL) {
-		(*lineno)++;
-		if (buf[strlen(buf) - 1] == '\n' || feof(f)) {
-			return 0;
-		} else {
-			debug("%s: %s line %lu exceeds size limit", __func__,
-			    filename, *lineno);
-			/* discard remainder of line */
-			while (fgetc(f) != '\n' && !feof(f))
-				;	/* nothing */
-		}
-	}
-	return -1;
+	return (xstrdup(p));
 }
 
-int
-tun_open(int tun, int mode)
+void fatal(char* fmt,...)
 {
-#if defined(CUSTOM_SYS_TUN_OPEN)
-	return (sys_tun_open(tun, mode));
-#elif defined(SSH_TUN_OPENBSD)
-	struct ifreq ifr;
-	char name[100];
-	int fd = -1, sock;
-
-	/* Open the tunnel device */
-	if (tun <= SSH_TUNID_MAX) {
-		snprintf(name, sizeof(name), "/dev/tun%d", tun);
-		fd = open(name, O_RDWR);
-	} else if (tun == SSH_TUNID_ANY) {
-		for (tun = 100; tun >= 0; tun--) {
-			snprintf(name, sizeof(name), "/dev/tun%d", tun);
-			if ((fd = open(name, O_RDWR)) >= 0)
-				break;
-		}
-	} else {
-		debug("%s: invalid tunnel %u", __func__, tun);
-		return (-1);
-	}
-
-	if (fd < 0) {
-		debug("%s: %s open failed: %s", __func__, name, strerror(errno));
-		return (-1);
-	}
-
-	debug("%s: %s mode %d fd %d", __func__, name, mode, fd);
-
-	/* Set the tunnel device operation mode */
-	snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "tun%d", tun);
-	if ((sock = socket(PF_UNIX, SOCK_STREAM, 0)) == -1)
-		goto failed;
-
-	if (ioctl(sock, SIOCGIFFLAGS, &ifr) == -1)
-		goto failed;
-
-	/* Set interface mode */
-	ifr.ifr_flags &= ~IFF_UP;
-	if (mode == SSH_TUNMODE_ETHERNET)
-		ifr.ifr_flags |= IFF_LINK0;
-	else
-		ifr.ifr_flags &= ~IFF_LINK0;
-	if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
-		goto failed;
-
-	/* Bring interface up */
-	ifr.ifr_flags |= IFF_UP;
-	if (ioctl(sock, SIOCSIFFLAGS, &ifr) == -1)
-		goto failed;
-
-	close(sock);
-	return (fd);
-
- failed:
-	if (fd >= 0)
-		close(fd);
-	if (sock >= 0)
-		close(sock);
-	debug("%s: failed to set %s mode %d: %s", __func__, name,
-	    mode, strerror(errno));
-	return (-1);
-#else
-	error("Tunnel interfaces are not supported on this platform");
-	return (-1);
-#endif
+	va_list args;
+	va_start(args, fmt);
+	vfprintf(stderr, fmt, args);
+	va_end(args);
+	fputc('\n', stderr);
+	exit(255);
 }
 
 void
@@ -671,20 +251,3 @@
 	if (nullfd > 2)
 		close(nullfd);
 }
-
-char *
-tohex(const u_char *d, u_int l)
-{
-	char b[3], *r;
-	u_int i, hl;
-
-	hl = l * 2 + 1;
-	r = xmalloc(hl);
-	*r = '\0';
-	for (i = 0; i < l; i++) {
-		snprintf(b, sizeof(b), "%02x", d[i]);
-		strlcat(r, b, hl);
-	}
-	return (r);
-}
-
diff -u a/progressmeter.c b/progressmeter.c
--- a/progressmeter.c
+++ b/progressmeter.c
@@ -1,3 +1,4 @@
+#ifdef PROGRESS_METER
 /*
  * Copyright (c) 2003 Nils Nordman.  All rights reserved.
  *
@@ -23,11 +24,11 @@
  */
 
 #include "includes.h"
-RCSID("$OpenBSD: progressmeter.c,v 1.24 2005/06/07 13:25:23 jaredy Exp $");
+/*RCSID("$OpenBSD: progressmeter.c,v 1.24 2005/06/07 13:25:23 jaredy Exp $");*/
 
 #include "progressmeter.h"
 #include "atomicio.h"
-#include "misc.h"
+#include "scpmisc.h"
 
 #define DEFAULT_WINSIZE 80
 #define MAX_WINSIZE 512
@@ -290,3 +291,4 @@
 		win_size = DEFAULT_WINSIZE;
 	win_size += 1;					/* trailing \0 */
 }
+#endif /* PROGRESS_METER */

Attachment: signature.asc
Description: PGP signature


Reply to: