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