[BACK]Return to misc.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / crypto / external / bsd / openssh / dist

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/crypto/external/bsd/openssh/dist/misc.c between version 1.17.2.2 and 1.18

version 1.17.2.2, 2020/04/13 07:45:20 version 1.18, 2018/08/26 07:46:36
Line 1 
Line 1 
 /*      $NetBSD$        */  /*      $NetBSD$        */
 /* $OpenBSD: misc.c,v 1.146 2020/01/28 01:49:36 djm Exp $ */  /* $OpenBSD: misc.c,v 1.131 2018/07/27 05:13:02 dtucker Exp $ */
   
 /*  /*
  * Copyright (c) 2000 Markus Friedl.  All rights reserved.   * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  * Copyright (c) 2005,2006 Damien Miller.  All rights reserved.   * Copyright (c) 2005,2006 Damien Miller.  All rights reserved.
Line 40  __RCSID("$NetBSD$");
Line 41  __RCSID("$NetBSD$");
 #include <netinet/in.h>  #include <netinet/in.h>
 #include <netinet/ip.h>  #include <netinet/ip.h>
 #include <netinet/tcp.h>  #include <netinet/tcp.h>
 #include <arpa/inet.h>  
   
 #include <ctype.h>  #include <ctype.h>
 #include <errno.h>  #include <errno.h>
Line 50  __RCSID("$NetBSD$");
Line 50  __RCSID("$NetBSD$");
 #include <pwd.h>  #include <pwd.h>
 #include <libgen.h>  #include <libgen.h>
 #include <limits.h>  #include <limits.h>
 #include <poll.h>  
 #include <signal.h>  #include <signal.h>
 #include <stdarg.h>  #include <stdarg.h>
 #include <stdio.h>  #include <stdio.h>
Line 88  set_nonblock(int fd)
Line 87  set_nonblock(int fd)
         int val;          int val;
   
         val = fcntl(fd, F_GETFL);          val = fcntl(fd, F_GETFL);
         if (val == -1) {          if (val < 0) {
                 error("fcntl(%d, F_GETFL): %s", fd, strerror(errno));                  error("fcntl(%d, F_GETFL): %s", fd, strerror(errno));
                 return (-1);                  return (-1);
         }          }
Line 112  unset_nonblock(int fd)
Line 111  unset_nonblock(int fd)
         int val;          int val;
   
         val = fcntl(fd, F_GETFL);          val = fcntl(fd, F_GETFL);
         if (val == -1) {          if (val < 0) {
                 error("fcntl(%d, F_GETFL): %s", fd, strerror(errno));                  error("fcntl(%d, F_GETFL): %s", fd, strerror(errno));
                 return (-1);                  return (-1);
         }          }
Line 222  set_rdomain(int fd, const char *name)
Line 221  set_rdomain(int fd, const char *name)
 #endif  #endif
 }  }
   
 /*  
  * Wait up to *timeoutp milliseconds for events on fd. Updates  
  * *timeoutp with time remaining.  
  * Returns 0 if fd ready or -1 on timeout or error (see errno).  
  */  
 static int  
 waitfd(int fd, int *timeoutp, short events)  
 {  
         struct pollfd pfd;  
         struct timeval t_start;  
         int oerrno, r;  
   
         monotime_tv(&t_start);  
         pfd.fd = fd;  
         pfd.events = events;  
         for (; *timeoutp >= 0;) {  
                 r = poll(&pfd, 1, *timeoutp);  
                 oerrno = errno;  
                 ms_subtract_diff(&t_start, timeoutp);  
                 errno = oerrno;  
                 if (r > 0)  
                         return 0;  
                 else if (r == -1 && errno != EAGAIN)  
                         return -1;  
                 else if (r == 0)  
                         break;  
         }  
         /* timeout */  
         errno = ETIMEDOUT;  
         return -1;  
 }  
   
 /*  
  * Wait up to *timeoutp milliseconds for fd to be readable. Updates  
  * *timeoutp with time remaining.  
  * Returns 0 if fd ready or -1 on timeout or error (see errno).  
  */  
 int  
 waitrfd(int fd, int *timeoutp) {  
         return waitfd(fd, timeoutp, POLLIN);  
 }  
   
 /*  
  * Attempt a non-blocking connect(2) to the specified address, waiting up to  
  * *timeoutp milliseconds for the connection to complete. If the timeout is  
  * <=0, then wait indefinitely.  
  *  
  * Returns 0 on success or -1 on failure.  
  */  
 int  
 timeout_connect(int sockfd, const struct sockaddr *serv_addr,  
     socklen_t addrlen, int *timeoutp)  
 {  
         int optval = 0;  
         socklen_t optlen = sizeof(optval);  
   
         /* No timeout: just do a blocking connect() */  
         if (timeoutp == NULL || *timeoutp <= 0)  
                 return connect(sockfd, serv_addr, addrlen);  
   
         set_nonblock(sockfd);  
         if (connect(sockfd, serv_addr, addrlen) == 0) {  
                 /* Succeeded already? */  
                 unset_nonblock(sockfd);  
                 return 0;  
         } else if (errno != EINPROGRESS)  
                 return -1;  
   
         if (waitfd(sockfd, timeoutp, POLLIN | POLLOUT) == -1)  
                 return -1;  
   
         /* Completed or failed */  
         if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1) {  
                 debug("getsockopt: %s", strerror(errno));  
                 return -1;  
         }  
         if (optval != 0) {  
                 errno = optval;  
                 return -1;  
         }  
         unset_nonblock(sockfd);  
         return 0;  
 }  
   
 /* Characters considered whitespace in strsep calls. */  /* Characters considered whitespace in strsep calls. */
 #define WHITESPACE " \t\r\n"  #define WHITESPACE " \t\r\n"
 #define QUOTE   "\""  #define QUOTE   "\""
Line 397  pwcopy(struct passwd *pw)
Line 312  pwcopy(struct passwd *pw)
 int  int
 a2port(const char *s)  a2port(const char *s)
 {  {
         struct servent *se;  
         long long port;          long long port;
         const char *errstr;          const char *errstr;
   
         port = strtonum(s, 0, 65535, &errstr);          port = strtonum(s, 0, 65535, &errstr);
         if (errstr == NULL)          if (errstr != NULL)
                 return (int)port;                  return -1;
         if ((se = getservbyname(s, "tcp")) != NULL)          return (int)port;
                 return ntohs(se->s_port);  
         return -1;  
 }  }
   
 int  int
Line 539  put_host_port(const char *host, u_short 
Line 451  put_host_port(const char *host, u_short 
   
         if (port == 0 || port == SSH_DEFAULT_PORT)          if (port == 0 || port == SSH_DEFAULT_PORT)
                 return(xstrdup(host));                  return(xstrdup(host));
         if (asprintf(&hoststr, "[%s]:%d", host, (int)port) == -1)          if (asprintf(&hoststr, "[%s]:%d", host, (int)port) < 0)
                 fatal("put_host_port: asprintf: %s", strerror(errno));                  fatal("put_host_port: asprintf: %s", strerror(errno));
         debug3("put_host_port: %s", hoststr);          debug3("put_host_port: %s", hoststr);
         return hoststr;          return hoststr;
Line 553  put_host_port(const char *host, u_short 
Line 465  put_host_port(const char *host, u_short 
  * The delimiter char, if present, is stored in delim.   * The delimiter char, if present, is stored in delim.
  * If this is the last field, *cp is set to NULL.   * If this is the last field, *cp is set to NULL.
  */   */
 char *  static char *
 hpdelim2(char **cp, char *delim)  hpdelim2(char **cp, char *delim)
 {  {
         char *s, *old;          char *s, *old;
Line 1044  char *
Line 956  char *
 percent_expand(const char *string, ...)  percent_expand(const char *string, ...)
 {  {
 #define EXPAND_MAX_KEYS 16  #define EXPAND_MAX_KEYS 16
         u_int num_keys, i;          u_int num_keys, i, j;
         struct {          struct {
                 const char *key;                  const char *key;
                 const char *repl;                  const char *repl;
         } keys[EXPAND_MAX_KEYS];          } keys[EXPAND_MAX_KEYS];
         struct sshbuf *buf;          char buf[4096];
         va_list ap;          va_list ap;
         int r;  
         char *ret;  
   
         if ((buf = sshbuf_new()) == NULL)  
                 fatal("%s: sshbuf_new failed", __func__);  
   
         /* Gather keys */          /* Gather keys */
         va_start(ap, string);          va_start(ap, string);
Line 1072  percent_expand(const char *string, ...)
Line 979  percent_expand(const char *string, ...)
         va_end(ap);          va_end(ap);
   
         /* Expand string */          /* Expand string */
           *buf = '\0';
         for (i = 0; *string != '\0'; string++) {          for (i = 0; *string != '\0'; string++) {
                 if (*string != '%') {                  if (*string != '%') {
  append:   append:
                         if ((r = sshbuf_put_u8(buf, *string)) != 0) {                          buf[i++] = *string;
                                 fatal("%s: sshbuf_put_u8: %s",                          if (i >= sizeof(buf))
                                     __func__, ssh_err(r));                                  fatal("%s: string too long", __func__);
                         }                          buf[i] = '\0';
                         continue;                          continue;
                 }                  }
                 string++;                  string++;
Line 1087  percent_expand(const char *string, ...)
Line 995  percent_expand(const char *string, ...)
                         goto append;                          goto append;
                 if (*string == '\0')                  if (*string == '\0')
                         fatal("%s: invalid format", __func__);                          fatal("%s: invalid format", __func__);
                 for (i = 0; i < num_keys; i++) {                  for (j = 0; j < num_keys; j++) {
                         if (strchr(keys[i].key, *string) != NULL) {                          if (strchr(keys[j].key, *string) != NULL) {
                                 if ((r = sshbuf_put(buf, keys[i].repl,                                  i = strlcat(buf, keys[j].repl, sizeof(buf));
                                     strlen(keys[i].repl))) != 0) {                                  if (i >= sizeof(buf))
                                         fatal("%s: sshbuf_put: %s",                                          fatal("%s: string too long", __func__);
                                             __func__, ssh_err(r));  
                                 }  
                                 break;                                  break;
                         }                          }
                 }                  }
                 if (i >= num_keys)                  if (j >= num_keys)
                         fatal("%s: unknown key %%%c", __func__, *string);                          fatal("%s: unknown key %%%c", __func__, *string);
         }          }
         if ((ret = sshbuf_dup_string(buf)) == NULL)          return (xstrdup(buf));
                 fatal("%s: sshbuf_dup_string failed", __func__);  
         sshbuf_free(buf);  
         return ret;  
 #undef EXPAND_MAX_KEYS  #undef EXPAND_MAX_KEYS
 }  }
   
Line 1137  tun_open(int tun, int mode, char **ifnam
Line 1040  tun_open(int tun, int mode, char **ifnam
                 return -1;                  return -1;
         }          }
   
         if (fd == -1) {          if (fd < 0) {
                 debug("%s: %s open: %s", __func__, name, strerror(errno));                  debug("%s: %s open: %s", __func__, name, strerror(errno));
                 return -1;                  return -1;
         }          }
Line 1234  tohex(const void *vp, size_t l)
Line 1137  tohex(const void *vp, size_t l)
         return (r);          return (r);
 }  }
   
 /*  
  * Extend string *sp by the specified format. If *sp is not NULL (or empty),  
  * then the separator 'sep' will be prepended before the formatted arguments.  
  * Extended strings are heap allocated.  
  */  
 void  
 xextendf(char **sp, const char *sep, const char *fmt, ...)  
 {  
         va_list ap;  
         char *tmp1, *tmp2;  
   
         va_start(ap, fmt);  
         xvasprintf(&tmp1, fmt, ap);  
         va_end(ap);  
   
         if (*sp == NULL || **sp == '\0') {  
                 free(*sp);  
                 *sp = tmp1;  
                 return;  
         }  
         xasprintf(&tmp2, "%s%s%s", *sp, sep == NULL ? "" : sep, tmp1);  
         free(tmp1);  
         free(*sp);  
         *sp = tmp2;  
 }  
   
   
 u_int64_t  u_int64_t
 get_u64(const void *vp)  get_u64(const void *vp)
 {  {
Line 1424  bandwidth_limit_init(struct bwlimit *bw,
Line 1300  bandwidth_limit_init(struct bwlimit *bw,
 {  {
         bw->buflen = buflen;          bw->buflen = buflen;
         bw->rate = kbps;          bw->rate = kbps;
         bw->thresh = buflen;          bw->thresh = bw->rate;
         bw->lamt = 0;          bw->lamt = 0;
         timerclear(&bw->bwstart);          timerclear(&bw->bwstart);
         timerclear(&bw->bwend);          timerclear(&bw->bwend);
 }  }
   
 /* Callback from read/write loop to insert bandwidth-limiting delays */  /* Callback from read/write loop to insert bandwidth-limiting delays */
 void  void
Line 1437  bandwidth_limit(struct bwlimit *bw, size
Line 1313  bandwidth_limit(struct bwlimit *bw, size
         u_int64_t waitlen;          u_int64_t waitlen;
         struct timespec ts, rm;          struct timespec ts, rm;
   
         bw->lamt += read_len;  
         if (!timerisset(&bw->bwstart)) {          if (!timerisset(&bw->bwstart)) {
                 monotime_tv(&bw->bwstart);                  monotime_tv(&bw->bwstart);
                 return;                  return;
         }          }
   
           bw->lamt += read_len;
         if (bw->lamt < bw->thresh)          if (bw->lamt < bw->thresh)
                 return;                  return;
   
Line 1525  static const struct {
Line 1402  static const struct {
         { "cs6", IPTOS_DSCP_CS6 },          { "cs6", IPTOS_DSCP_CS6 },
         { "cs7", IPTOS_DSCP_CS7 },          { "cs7", IPTOS_DSCP_CS7 },
         { "ef", IPTOS_DSCP_EF },          { "ef", IPTOS_DSCP_EF },
 #ifdef IPTOS_DSCP_LE  
         { "le", IPTOS_DSCP_LE },  
 #endif  
         { "lowdelay", IPTOS_LOWDELAY },          { "lowdelay", IPTOS_LOWDELAY },
         { "throughput", IPTOS_THROUGHPUT },          { "throughput", IPTOS_THROUGHPUT },
         { "reliability", IPTOS_RELIABILITY },          { "reliability", IPTOS_RELIABILITY },
Line 1592  unix_listener(const char *path, int back
Line 1466  unix_listener(const char *path, int back
         }          }
   
         sock = socket(PF_UNIX, SOCK_STREAM, 0);          sock = socket(PF_UNIX, SOCK_STREAM, 0);
         if (sock == -1) {          if (sock < 0) {
                 saved_errno = errno;                  saved_errno = errno;
                 error("%s: socket: %.100s", __func__, strerror(errno));                  error("%s: socket: %.100s", __func__, strerror(errno));
                 errno = saved_errno;                  errno = saved_errno;
Line 1602  unix_listener(const char *path, int back
Line 1476  unix_listener(const char *path, int back
                 if (unlink(path) != 0 && errno != ENOENT)                  if (unlink(path) != 0 && errno != ENOENT)
                         error("unlink(%s): %.100s", path, strerror(errno));                          error("unlink(%s): %.100s", path, strerror(errno));
         }          }
         if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) {          if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
                 saved_errno = errno;                  saved_errno = errno;
                 error("%s: cannot bind to path %s: %s",                  error("%s: cannot bind to path %s: %s",
                     __func__, path, strerror(errno));                      __func__, path, strerror(errno));
Line 1610  unix_listener(const char *path, int back
Line 1484  unix_listener(const char *path, int back
                 errno = saved_errno;                  errno = saved_errno;
                 return -1;                  return -1;
         }          }
         if (listen(sock, backlog) == -1) {          if (listen(sock, backlog) < 0) {
                 saved_errno = errno;                  saved_errno = errno;
                 error("%s: cannot listen on path %s: %s",                  error("%s: cannot listen on path %s: %s",
                     __func__, path, strerror(errno));                      __func__, path, strerror(errno));
Line 1880  safe_path(const char *name, struct stat 
Line 1754  safe_path(const char *name, struct stat 
                 }                  }
                 strlcpy(buf, cp, sizeof(buf));                  strlcpy(buf, cp, sizeof(buf));
   
                 if (stat(buf, &st) == -1 ||                  if (stat(buf, &st) < 0 ||
                     (st.st_uid != 0 && st.st_uid != uid) ||                      (st.st_uid != 0 && st.st_uid != uid) ||
                     (st.st_mode & 022) != 0) {                      (st.st_mode & 022) != 0) {
                         snprintf(err, errlen,                          snprintf(err, errlen,
Line 1915  safe_path_fd(int fd, const char *file, s
Line 1789  safe_path_fd(int fd, const char *file, s
         struct stat st;          struct stat st;
   
         /* check the open file to avoid races */          /* check the open file to avoid races */
         if (fstat(fd, &st) == -1) {          if (fstat(fd, &st) < 0) {
                 snprintf(err, errlen, "cannot stat file %s: %s",                  snprintf(err, errlen, "cannot stat file %s: %s",
                     file, strerror(errno));                      file, strerror(errno));
                 return -1;                  return -1;
Line 2021  bad:
Line 1895  bad:
         return 0;          return 0;
 }  }
   
 /*  
  * Verify that a environment variable name (not including initial '$') is  
  * valid; consisting of one or more alphanumeric or underscore characters only.  
  * Returns 1 on valid, 0 otherwise.  
  */  
 int  
 valid_env_name(const char *name)  
 {  
         const char *cp;  
   
         if (name[0] == '\0')  
                 return 0;  
         for (cp = name; *cp != '\0'; cp++) {  
                 if (!isalnum((u_char)*cp) && *cp != '_')  
                         return 0;  
         }  
         return 1;  
 }  
   
 const char *  const char *
 atoi_err(const char *nptr, int *val)  atoi_err(const char *nptr, int *val)
 {  {
Line 2107  format_absolute_time(uint64_t t, char *b
Line 1962  format_absolute_time(uint64_t t, char *b
         localtime_r(&tt, &tm);          localtime_r(&tt, &tm);
         strftime(buf, len, "%Y-%m-%dT%H:%M:%S", &tm);          strftime(buf, len, "%Y-%m-%dT%H:%M:%S", &tm);
 }  }
   
 /* check if path is absolute */  
 int  
 path_absolute(const char *path)  
 {  
         return (*path == '/') ? 1 : 0;  
 }  
   
 void  
 skip_space(char **cpp)  
 {  
         char *cp;  
   
         for (cp = *cpp; *cp == ' ' || *cp == '\t'; cp++)  
                 ;  
         *cpp = cp;  
 }  
   
 /* authorized_key-style options parsing helpers */  
   
 /*  
  * Match flag 'opt' in *optsp, and if allow_negate is set then also match  
  * 'no-opt'. Returns -1 if option not matched, 1 if option matches or 0  
  * if negated option matches.  
  * If the option or negated option matches, then *optsp is updated to  
  * point to the first character after the option.  
  */  
 int  
 opt_flag(const char *opt, int allow_negate, const char **optsp)  
 {  
         size_t opt_len = strlen(opt);  
         const char *opts = *optsp;  
         int negate = 0;  
   
         if (allow_negate && strncasecmp(opts, "no-", 3) == 0) {  
                 opts += 3;  
                 negate = 1;  
         }  
         if (strncasecmp(opts, opt, opt_len) == 0) {  
                 *optsp = opts + opt_len;  
                 return negate ? 0 : 1;  
         }  
         return -1;  
 }  
   
 char *  
 opt_dequote(const char **sp, const char **errstrp)  
 {  
         const char *s = *sp;  
         char *ret;  
         size_t i;  
   
         *errstrp = NULL;  
         if (*s != '"') {  
                 *errstrp = "missing start quote";  
                 return NULL;  
         }  
         s++;  
         if ((ret = malloc(strlen((s)) + 1)) == NULL) {  
                 *errstrp = "memory allocation failed";  
                 return NULL;  
         }  
         for (i = 0; *s != '\0' && *s != '"';) {  
                 if (s[0] == '\\' && s[1] == '"')  
                         s++;  
                 ret[i++] = *s++;  
         }  
         if (*s == '\0') {  
                 *errstrp = "missing end quote";  
                 free(ret);  
                 return NULL;  
         }  
         ret[i] = '\0';  
         s++;  
         *sp = s;  
         return ret;  
 }  
   
 int  
 opt_match(const char **opts, const char *term)  
 {  
         if (strncasecmp((*opts), term, strlen(term)) == 0 &&  
             (*opts)[strlen(term)] == '=') {  
                 *opts += strlen(term) + 1;  
                 return 1;  
         }  
         return 0;  
 }  
   
 sshsig_t  
 ssh_signal(int signum, sshsig_t handler)  
 {  
         struct sigaction sa, osa;  
   
         /* mask all other signals while in handler */  
         bzero(&sa, sizeof(sa));  
         sa.sa_handler = handler;  
         sigfillset(&sa.sa_mask);  
         if (signum != SIGALRM)  
                 sa.sa_flags = SA_RESTART;  
         if (sigaction(signum, &sa, &osa) == -1) {  
                 debug3("sigaction(%s): %s", strsignal(signum), strerror(errno));  
                 return SIG_ERR;  
         }  
         return osa.sa_handler;  
 }  

Legend:
Removed from v.1.17.2.2  
changed lines
  Added in v.1.18

CVSweb <webmaster@jp.NetBSD.org>