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