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

Diff for /src/usr.bin/ssh/servconf.c between version 1.314 and 1.315

version 1.314, 2017/10/05 15:52:03 version 1.315, 2017/10/25 00:15:35
Line 14 
Line 14 
 #include <sys/types.h>  #include <sys/types.h>
 #include <sys/socket.h>  #include <sys/socket.h>
 #include <sys/queue.h>  #include <sys/queue.h>
   #include <sys/sysctl.h>
   
 #include <netinet/in.h>  #include <netinet/in.h>
 #include <netinet/ip.h>  #include <netinet/ip.h>
   #include <net/route.h>
   
 #include <ctype.h>  #include <ctype.h>
 #include <netdb.h>  #include <netdb.h>
Line 53 
Line 55 
 #include "myproposal.h"  #include "myproposal.h"
 #include "digest.h"  #include "digest.h"
   
 static void add_listen_addr(ServerOptions *, char *, int);  static void add_listen_addr(ServerOptions *, const char *,
 static void add_one_listen_addr(ServerOptions *, char *, int);      const char *, int);
   static void add_one_listen_addr(ServerOptions *, const char *,
       const char *, int);
   
 /* Use of privilege separation or not */  /* Use of privilege separation or not */
 extern int use_privsep;  extern int use_privsep;
Line 71 
Line 75 
         options->queued_listen_addrs = NULL;          options->queued_listen_addrs = NULL;
         options->num_queued_listens = 0;          options->num_queued_listens = 0;
         options->listen_addrs = NULL;          options->listen_addrs = NULL;
           options->num_listen_addrs = 0;
         options->address_family = -1;          options->address_family = -1;
         options->num_host_key_files = 0;          options->num_host_key_files = 0;
         options->num_host_cert_files = 0;          options->num_host_cert_files = 0;
Line 235 
Line 240 
         if (options->address_family == -1)          if (options->address_family == -1)
                 options->address_family = AF_UNSPEC;                  options->address_family = AF_UNSPEC;
         if (options->listen_addrs == NULL)          if (options->listen_addrs == NULL)
                 add_listen_addr(options, NULL, 0);                  add_listen_addr(options, NULL, NULL, 0);
         if (options->pid_file == NULL)          if (options->pid_file == NULL)
                 options->pid_file = xstrdup(_PATH_SSH_DAEMON_PID_FILE);                  options->pid_file = xstrdup(_PATH_SSH_DAEMON_PID_FILE);
         if (options->login_grace_time == -1)          if (options->login_grace_time == -1)
Line 612 
Line 617 
 }  }
   
 static void  static void
 add_listen_addr(ServerOptions *options, char *addr, int port)  add_listen_addr(ServerOptions *options, const char *addr,
       const char *rdomain, int port)
 {  {
         u_int i;          u_int i;
   
         if (port == 0)          if (port > 0)
                 for (i = 0; i < options->num_ports; i++)                  add_one_listen_addr(options, addr, rdomain, port);
                         add_one_listen_addr(options, addr, options->ports[i]);          else {
         else                  for (i = 0; i < options->num_ports; i++) {
                 add_one_listen_addr(options, addr, port);                          add_one_listen_addr(options, addr, rdomain,
                               options->ports[i]);
                   }
           }
 }  }
   
 static void  static void
 add_one_listen_addr(ServerOptions *options, char *addr, int port)  add_one_listen_addr(ServerOptions *options, const char *addr,
       const char *rdomain, int port)
 {  {
         struct addrinfo hints, *ai, *aitop;          struct addrinfo hints, *ai, *aitop;
         char strport[NI_MAXSERV];          char strport[NI_MAXSERV];
         int gaierr;          int gaierr;
           u_int i;
   
           /* Find listen_addrs entry for this rdomain */
           for (i = 0; i < options->num_listen_addrs; i++) {
                   if (rdomain == NULL && options->listen_addrs[i].rdomain == NULL)
                           break;
                   if (rdomain == NULL || options->listen_addrs[i].rdomain == NULL)
                           continue;
                   if (strcmp(rdomain, options->listen_addrs[i].rdomain) == 0)
                           break;
           }
           if (i >= options->num_listen_addrs) {
                   /* No entry for this rdomain; allocate one */
                   if (i >= INT_MAX)
                           fatal("%s: too many listen addresses", __func__);
                   options->listen_addrs = xrecallocarray(options->listen_addrs,
                       options->num_listen_addrs, options->num_listen_addrs + 1,
                       sizeof(*options->listen_addrs));
                   i = options->num_listen_addrs++;
                   if (rdomain != NULL)
                           options->listen_addrs[i].rdomain = xstrdup(rdomain);
           }
           /* options->listen_addrs[i] points to the addresses for this rdomain */
   
         memset(&hints, 0, sizeof(hints));          memset(&hints, 0, sizeof(hints));
         hints.ai_family = options->address_family;          hints.ai_family = options->address_family;
         hints.ai_socktype = SOCK_STREAM;          hints.ai_socktype = SOCK_STREAM;
Line 641 
Line 674 
                     ssh_gai_strerror(gaierr));                      ssh_gai_strerror(gaierr));
         for (ai = aitop; ai->ai_next; ai = ai->ai_next)          for (ai = aitop; ai->ai_next; ai = ai->ai_next)
                 ;                  ;
         ai->ai_next = options->listen_addrs;          ai->ai_next = options->listen_addrs[i].addrs;
         options->listen_addrs = aitop;          options->listen_addrs[i].addrs = aitop;
 }  }
   
   /* Returns nonzero if the routing domain name is valid */
   static int
   valid_rdomain(const char *name)
   {
           const char *errstr;
           long long num;
           struct rt_tableinfo info;
           int mib[6];
           size_t miblen = sizeof(mib);
   
           if (name == NULL)
                   return 1;
   
           num = strtonum(name, 0, 255, &errstr);
           if (errstr != NULL)
                   return 0;
   
           /* Check whether the table actually exists */
           memset(mib, 0, sizeof(mib));
           mib[0] = CTL_NET;
           mib[1] = PF_ROUTE;
           mib[4] = NET_RT_TABLE;
           mib[5] = (int)num;
           if (sysctl(mib, 6, &info, &miblen, NULL, 0) == -1)
                   return 0;
   
           return 1;
   }
   
 /*  /*
  * Queue a ListenAddress to be processed once we have all of the Ports   * Queue a ListenAddress to be processed once we have all of the Ports
  * and AddressFamily options.   * and AddressFamily options.
  */   */
 static void  static void
 queue_listen_addr(ServerOptions *options, char *addr, int port)  queue_listen_addr(ServerOptions *options, const char *addr,
       const char *rdomain, int port)
 {  {
         options->queued_listen_addrs = xreallocarray(          struct queued_listenaddr *qla;
             options->queued_listen_addrs, options->num_queued_listens + 1,  
             sizeof(addr));          options->queued_listen_addrs = xrecallocarray(
         options->queued_listen_ports = xreallocarray(              options->queued_listen_addrs,
             options->queued_listen_ports, options->num_queued_listens + 1,              options->num_queued_listens, options->num_queued_listens + 1,
             sizeof(port));              sizeof(*options->queued_listen_addrs));
         options->queued_listen_addrs[options->num_queued_listens] =          qla = &options->queued_listen_addrs[options->num_queued_listens++];
             xstrdup(addr);          qla->addr = xstrdup(addr);
         options->queued_listen_ports[options->num_queued_listens] = port;          qla->port = port;
         options->num_queued_listens++;          qla->rdomain = rdomain == NULL ? NULL : xstrdup(rdomain);
 }  }
   
 /*  /*
Line 671 
Line 734 
 process_queued_listen_addrs(ServerOptions *options)  process_queued_listen_addrs(ServerOptions *options)
 {  {
         u_int i;          u_int i;
           struct queued_listenaddr *qla;
   
         if (options->num_ports == 0)          if (options->num_ports == 0)
                 options->ports[options->num_ports++] = SSH_DEFAULT_PORT;                  options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
Line 678 
Line 742 
                 options->address_family = AF_UNSPEC;                  options->address_family = AF_UNSPEC;
   
         for (i = 0; i < options->num_queued_listens; i++) {          for (i = 0; i < options->num_queued_listens; i++) {
                 add_listen_addr(options, options->queued_listen_addrs[i],                  qla = &options->queued_listen_addrs[i];
                     options->queued_listen_ports[i]);                  add_listen_addr(options, qla->addr, qla->rdomain, qla->port);
                 free(options->queued_listen_addrs[i]);                  free(qla->addr);
                 options->queued_listen_addrs[i] = NULL;                  free(qla->rdomain);
         }          }
         free(options->queued_listen_addrs);          free(options->queued_listen_addrs);
         options->queued_listen_addrs = NULL;          options->queued_listen_addrs = NULL;
         free(options->queued_listen_ports);  
         options->queued_listen_ports = NULL;  
         options->num_queued_listens = 0;          options->num_queued_listens = 0;
 }  }
   
Line 1075 
Line 1137 
                 /* check for bare IPv6 address: no "[]" and 2 or more ":" */                  /* check for bare IPv6 address: no "[]" and 2 or more ":" */
                 if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL                  if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL
                     && strchr(p+1, ':') != NULL) {                      && strchr(p+1, ':') != NULL) {
                         queue_listen_addr(options, arg, 0);  
                         break;  
                 }  
                 p = hpdelim(&arg);  
                 if (p == NULL)  
                         fatal("%s line %d: bad address:port usage",  
                             filename, linenum);  
                 p = cleanhostname(p);  
                 if (arg == NULL)  
                         port = 0;                          port = 0;
                 else if ((port = a2port(arg)) <= 0)                          p = arg;
                         fatal("%s line %d: bad port number", filename, linenum);                  } else {
                           p = hpdelim(&arg);
                           if (p == NULL)
                                   fatal("%s line %d: bad address:port usage",
                                       filename, linenum);
                           p = cleanhostname(p);
                           if (arg == NULL)
                                   port = 0;
                           else if ((port = a2port(arg)) <= 0)
                                   fatal("%s line %d: bad port number",
                                       filename, linenum);
                   }
                   /* Optional routing table */
                   arg2 = NULL;
                   if ((arg = strdelim(&cp)) != NULL) {
                           if (strcmp(arg, "rdomain") != 0 ||
                               (arg2 = strdelim(&cp)) == NULL)
                                   fatal("%s line %d: bad ListenAddress syntax",
                                       filename, linenum);
                           if (!valid_rdomain(arg2))
                                   fatal("%s line %d: bad routing domain",
                                       filename, linenum);
                   }
   
                 queue_listen_addr(options, p, port);                  queue_listen_addr(options, p, arg2, port);
   
                 break;                  break;
   
Line 2199 
Line 2274 
         printf("\n");          printf("\n");
 }  }
   
 void  static char *
 dump_config(ServerOptions *o)  format_listen_addrs(struct listenaddr *la)
 {  {
         u_int i;          int r;
         int ret;  
         struct addrinfo *ai;          struct addrinfo *ai;
         char addr[NI_MAXHOST], port[NI_MAXSERV], *s = NULL;          char addr[NI_MAXHOST], port[NI_MAXSERV];
         char *laddr1 = xstrdup(""), *laddr2 = NULL;          char *laddr1 = xstrdup(""), *laddr2 = NULL;
   
         /* these are usually at the top of the config */  
         for (i = 0; i < o->num_ports; i++)  
                 printf("port %d\n", o->ports[i]);  
         dump_cfg_fmtint(sAddressFamily, o->address_family);  
   
         /*          /*
          * ListenAddress must be after Port.  add_one_listen_addr pushes           * ListenAddress must be after Port.  add_one_listen_addr pushes
          * addresses onto a stack, so to maintain ordering we need to           * addresses onto a stack, so to maintain ordering we need to
          * print these in reverse order.           * print these in reverse order.
          */           */
         for (ai = o->listen_addrs; ai; ai = ai->ai_next) {          for (ai = la->addrs; ai; ai = ai->ai_next) {
                 if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr,                  if ((r = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr,
                     sizeof(addr), port, sizeof(port),                      sizeof(addr), port, sizeof(port),
                     NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {                      NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
                         error("getnameinfo failed: %.100s",                          error("getnameinfo: %.100s", ssh_gai_strerror(r));
                             (ret != EAI_SYSTEM) ? gai_strerror(ret) :                          continue;
                             strerror(errno));                  }
                   laddr2 = laddr1;
                   if (ai->ai_family == AF_INET6) {
                           xasprintf(&laddr1, "listenaddress [%s]:%s%s%s\n%s",
                               addr, port,
                               la->rdomain == NULL ? "" : " rdomain ",
                               la->rdomain == NULL ? "" : la->rdomain,
                               laddr2);
                 } else {                  } else {
                         laddr2 = laddr1;                          xasprintf(&laddr1, "listenaddress %s:%s%s%s\n%s",
                         if (ai->ai_family == AF_INET6)                              addr, port,
                                 xasprintf(&laddr1, "listenaddress [%s]:%s\n%s",                              la->rdomain == NULL ? "" : " rdomain ",
                                     addr, port, laddr2);                              la->rdomain == NULL ? "" : la->rdomain,
                         else                              laddr2);
                                 xasprintf(&laddr1, "listenaddress %s:%s\n%s",  
                                     addr, port, laddr2);  
                         free(laddr2);  
                 }                  }
                   free(laddr2);
         }          }
         printf("%s", laddr1);          return laddr1;
         free(laddr1);  }
   
   void
   dump_config(ServerOptions *o)
   {
           char *s;
           u_int i;
   
           /* these are usually at the top of the config */
           for (i = 0; i < o->num_ports; i++)
                   printf("port %d\n", o->ports[i]);
           dump_cfg_fmtint(sAddressFamily, o->address_family);
   
           for (i = 0; i < o->num_listen_addrs; i++) {
                   s = format_listen_addrs(&o->listen_addrs[i]);
                   printf("%s", s);
                   free(s);
           }
   
         /* integer arguments */          /* integer arguments */
         dump_cfg_int(sLoginGraceTime, o->login_grace_time);          dump_cfg_int(sLoginGraceTime, o->login_grace_time);

Legend:
Removed from v.1.314  
changed lines
  Added in v.1.315