[BACK]Return to misc.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Diff for /src/usr.bin/ssh/misc.c between version 1.34.2.2 and 1.35

version 1.34.2.2, 2006/10/06 03:19:32 version 1.35, 2005/09/13 23:40:07
Line 1 
Line 1 
 /* $OpenBSD$ */  
 /*  /*
  * 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 Damien Miller.  All rights reserved.
  *   *
  * Redistribution and use in source and binary forms, with or without   * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions   * modification, are permitted provided that the following conditions
Line 24 
Line 23 
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */   */
   
 #include <sys/types.h>  #include "includes.h"
 #include <sys/ioctl.h>  RCSID("$OpenBSD$");
 #include <sys/socket.h>  
 #include <sys/param.h>  
   
 #include <net/if.h>  
 #include <netinet/in.h>  
 #include <netinet/tcp.h>  
   
 #include <errno.h>  
 #include <fcntl.h>  
 #include <paths.h>  
 #include <pwd.h>  
 #include <stdarg.h>  
 #include <stdio.h>  
 #include <stdlib.h>  
 #include <string.h>  
 #include <unistd.h>  
   
 #include "xmalloc.h"  
 #include "misc.h"  #include "misc.h"
 #include "log.h"  #include "log.h"
 #include "ssh.h"  #include "xmalloc.h"
   
 /* remove newline at end of string */  /* remove newline at end of string */
 char *  char *
Line 137 
Line 119 
   
 /* Characters considered whitespace in strsep calls. */  /* Characters considered whitespace in strsep calls. */
 #define WHITESPACE " \t\r\n"  #define WHITESPACE " \t\r\n"
 #define QUOTE   "\""  
   
 /* return next token in configuration line */  /* return next token in configuration line */
 char *  char *
Line 151 
Line 132 
   
         old = *s;          old = *s;
   
         *s = strpbrk(*s, WHITESPACE QUOTE "=");          *s = strpbrk(*s, WHITESPACE "=");
         if (*s == NULL)          if (*s == NULL)
                 return (old);                  return (old);
   
         if (*s[0] == '\"') {  
                 memmove(*s, *s + 1, strlen(*s)); /* move nul too */  
                 /* Find matching quote */  
                 if ((*s = strpbrk(*s, QUOTE)) == NULL) {  
                         return (NULL);          /* no matching quote */  
                 } else {  
                         *s[0] = '\0';  
                         return (old);  
                 }  
         }  
   
         /* Allow only one '=' to be skipped */          /* Allow only one '=' to be skipped */
         if (*s[0] == '=')          if (*s[0] == '=')
                 wspace = 1;                  wspace = 1;
         *s[0] = '\0';          *s[0] = '\0';
   
         /* Skip any extra whitespace after first token */  
         *s += strspn(*s + 1, WHITESPACE) + 1;          *s += strspn(*s + 1, WHITESPACE) + 1;
         if (*s[0] == '=' && !wspace)          if (*s[0] == '=' && !wspace)
                 *s += strspn(*s + 1, WHITESPACE) + 1;                  *s += strspn(*s + 1, WHITESPACE) + 1;
Line 182 
Line 151 
 struct passwd *  struct passwd *
 pwcopy(struct passwd *pw)  pwcopy(struct passwd *pw)
 {  {
         struct passwd *copy = xcalloc(1, sizeof(*copy));          struct passwd *copy = xmalloc(sizeof(*copy));
   
           memset(copy, 0, sizeof(*copy));
         copy->pw_name = xstrdup(pw->pw_name);          copy->pw_name = xstrdup(pw->pw_name);
         copy->pw_passwd = xstrdup(pw->pw_passwd);          copy->pw_passwd = xstrdup(pw->pw_passwd);
         copy->pw_gecos = xstrdup(pw->pw_gecos);          copy->pw_gecos = xstrdup(pw->pw_gecos);
Line 218 
Line 188 
         return port;          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 SECONDS         1
 #define MINUTES         (SECONDS * 60)  #define MINUTES         (SECONDS * 60)
 #define HOURS           (MINUTES * 60)  #define HOURS           (MINUTES * 60)
Line 300 
Line 239 
                 switch (*endp++) {                  switch (*endp++) {
                 case '\0':                  case '\0':
                         endp--;                          endp--;
                         break;  
                 case 's':                  case 's':
                 case 'S':                  case 'S':
                         break;                          break;
Line 333 
Line 271 
 }  }
   
 /*  /*
  * Returns a standardized host+port identifier string.  
  * Caller must free returned string.  
  */  
 char *  
 put_host_port(const char *host, u_short port)  
 {  
         char *hoststr;  
   
         if (port == 0 || port == SSH_DEFAULT_PORT)  
                 return(xstrdup(host));  
         if (asprintf(&hoststr, "[%s]:%d", host, (int)port) < 0)  
                 fatal("put_host_port: asprintf: %s", strerror(errno));  
         debug3("put_host_port: %s", hoststr);  
         return hoststr;  
 }  
   
 /*  
  * Search for next delimiter between hostnames/addresses and ports.   * Search for next delimiter between hostnames/addresses and ports.
  * Argument may be modified (for termination).   * Argument may be modified (for termination).
  * Returns *cp if parsing succeeds.   * Returns *cp if parsing succeeds.
Line 429 
Line 350 
 addargs(arglist *args, char *fmt, ...)  addargs(arglist *args, char *fmt, ...)
 {  {
         va_list ap;          va_list ap;
         char *cp;          char buf[1024];
         u_int nalloc;          u_int nalloc;
         int r;  
   
         va_start(ap, fmt);          va_start(ap, fmt);
         r = vasprintf(&cp, fmt, ap);          vsnprintf(buf, sizeof(buf), fmt, ap);
         va_end(ap);          va_end(ap);
         if (r == -1)  
                 fatal("addargs: argument too long");  
   
         nalloc = args->nalloc;          nalloc = args->nalloc;
         if (args->list == NULL) {          if (args->list == NULL) {
Line 446 
Line 364 
         } else if (args->num+2 >= nalloc)          } else if (args->num+2 >= nalloc)
                 nalloc *= 2;                  nalloc *= 2;
   
         args->list = xrealloc(args->list, nalloc, sizeof(char *));          args->list = xrealloc(args->list, nalloc * sizeof(char *));
         args->nalloc = nalloc;          args->nalloc = nalloc;
         args->list[args->num++] = cp;          args->list[args->num++] = xstrdup(buf);
         args->list[args->num] = NULL;          args->list[args->num] = NULL;
 }  }
   
 void  
 replacearg(arglist *args, u_int which, char *fmt, ...)  
 {  
         va_list ap;  
         char *cp;  
         int r;  
   
         va_start(ap, fmt);  
         r = vasprintf(&cp, fmt, ap);  
         va_end(ap);  
         if (r == -1)  
                 fatal("replacearg: argument too long");  
   
         if (which >= args->num)  
                 fatal("replacearg: tried to replace invalid arg %d >= %d",  
                     which, args->num);  
         xfree(args->list[which]);  
         args->list[which] = cp;  
 }  
   
 void  
 freeargs(arglist *args)  
 {  
         u_int i;  
   
         if (args->list != NULL) {  
                 for (i = 0; i < args->num; i++)  
                         xfree(args->list[i]);  
                 xfree(args->list);  
                 args->nalloc = args->num = 0;  
                 args->list = NULL;  
         }  
 }  
   
 /*  /*
  * Expands tildes in the file name.  Returns data allocated by xmalloc.   * Expands tildes in the file name.  Returns data allocated by xmalloc.
  * Warning: this calls getpw*.   * Warning: this calls getpw*.
Line 617 
Line 501 
         return -1;          return -1;
 }  }
   
 int  
 tun_open(int tun, int mode)  
 {  
         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);  
 }  
   
 void  void
 sanitise_stdfd(void)  sanitise_stdfd(void)
 {  {
         int nullfd, dupfd;          int nullfd;
   
         if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) {          if ((nullfd = open(_PATH_DEVNULL, O_RDWR)) == -1) {
                 fprintf(stderr, "Couldn't open /dev/null: %s", strerror(errno));                  fprintf(stderr, "Couldn't open /dev/null: %s", strerror(errno));
                 exit(1);                  exit(1);
         }          }
         while (++dupfd <= 2) {          while (nullfd < 2) {
                 /* Only clobber closed fds */                  if (dup2(nullfd, nullfd + 1) == -1) {
                 if (fcntl(dupfd, F_GETFL, 0) >= 0)  
                         continue;  
                 if (dup2(nullfd, dupfd) == -1) {  
                         fprintf(stderr, "dup2: %s", strerror(errno));                          fprintf(stderr, "dup2: %s", strerror(errno));
                         exit(1);                          exit(1);
                 }                  }
                   nullfd++;
         }          }
         if (nullfd > 2)          if (nullfd > 2)
                 close(nullfd);                  close(nullfd);
 }  }
   
 char *  char *
 tohex(const void *vp, size_t l)  tohex(const u_char *d, u_int l)
 {  {
         const u_char *p = (const u_char *)vp;  
         char b[3], *r;          char b[3], *r;
         size_t i, hl;          u_int i, hl;
   
         if (l > 65536)  
                 return xstrdup("tohex: length > 65536");  
   
         hl = l * 2 + 1;          hl = l * 2 + 1;
         r = xcalloc(1, hl);          r = xmalloc(hl);
           *r = '\0';
         for (i = 0; i < l; i++) {          for (i = 0; i < l; i++) {
                 snprintf(b, sizeof(b), "%02x", p[i]);                  snprintf(b, sizeof(b), "%02x", d[i]);
                 strlcat(r, b, hl);                  strlcat(r, b, hl);
         }          }
         return (r);          return (r);
 }  }
   
 u_int64_t  
 get_u64(const void *vp)  
 {  
         const u_char *p = (const u_char *)vp;  
         u_int64_t v;  
   
         v  = (u_int64_t)p[0] << 56;  
         v |= (u_int64_t)p[1] << 48;  
         v |= (u_int64_t)p[2] << 40;  
         v |= (u_int64_t)p[3] << 32;  
         v |= (u_int64_t)p[4] << 24;  
         v |= (u_int64_t)p[5] << 16;  
         v |= (u_int64_t)p[6] << 8;  
         v |= (u_int64_t)p[7];  
   
         return (v);  
 }  
   
 u_int32_t  
 get_u32(const void *vp)  
 {  
         const u_char *p = (const u_char *)vp;  
         u_int32_t v;  
   
         v  = (u_int32_t)p[0] << 24;  
         v |= (u_int32_t)p[1] << 16;  
         v |= (u_int32_t)p[2] << 8;  
         v |= (u_int32_t)p[3];  
   
         return (v);  
 }  
   
 u_int16_t  
 get_u16(const void *vp)  
 {  
         const u_char *p = (const u_char *)vp;  
         u_int16_t v;  
   
         v  = (u_int16_t)p[0] << 8;  
         v |= (u_int16_t)p[1];  
   
         return (v);  
 }  
   
 void  
 put_u64(void *vp, u_int64_t v)  
 {  
         u_char *p = (u_char *)vp;  
   
         p[0] = (u_char)(v >> 56) & 0xff;  
         p[1] = (u_char)(v >> 48) & 0xff;  
         p[2] = (u_char)(v >> 40) & 0xff;  
         p[3] = (u_char)(v >> 32) & 0xff;  
         p[4] = (u_char)(v >> 24) & 0xff;  
         p[5] = (u_char)(v >> 16) & 0xff;  
         p[6] = (u_char)(v >> 8) & 0xff;  
         p[7] = (u_char)v & 0xff;  
 }  
   
 void  
 put_u32(void *vp, u_int32_t v)  
 {  
         u_char *p = (u_char *)vp;  
   
         p[0] = (u_char)(v >> 24) & 0xff;  
         p[1] = (u_char)(v >> 16) & 0xff;  
         p[2] = (u_char)(v >> 8) & 0xff;  
         p[3] = (u_char)v & 0xff;  
 }  
   
   
 void  
 put_u16(void *vp, u_int16_t v)  
 {  
         u_char *p = (u_char *)vp;  
   
         p[0] = (u_char)(v >> 8) & 0xff;  
         p[1] = (u_char)v & 0xff;  
 }  

Legend:
Removed from v.1.34.2.2  
changed lines
  Added in v.1.35