[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.93 and 1.94

version 1.93, 2001/12/05 10:06:12 version 1.94, 2001/12/06 13:30:05
Line 376 
Line 376 
         options->listen_addrs = aitop;          options->listen_addrs = aitop;
 }  }
   
 /* Reads the server configuration file. */  int
   process_server_config_line(ServerOptions *options, char *line,
 void      const char *filename, int linenum)
 read_server_config(ServerOptions *options, const char *filename)  
 {  {
         FILE *f;  
         char line[1024];  
         char *cp, **charptr, *arg, *p;          char *cp, **charptr, *arg, *p;
         int linenum, *intptr, value;          int *intptr, value;
         int bad_options = 0;  
         ServerOpCodes opcode;          ServerOpCodes opcode;
         int i, n;          int i, n;
   
         f = fopen(filename, "r");          cp = line;
         if (!f) {          arg = strdelim(&cp);
                 perror(filename);          /* Ignore leading whitespace */
                 exit(1);          if (*arg == '\0')
         }  
         linenum = 0;  
         while (fgets(line, sizeof(line), f)) {  
                 linenum++;  
                 cp = line;  
                 arg = strdelim(&cp);                  arg = strdelim(&cp);
                 /* Ignore leading whitespace */          if (!arg || !*arg || *arg == '#')
                 if (*arg == '\0')                  return 0;
                         arg = strdelim(&cp);          intptr = NULL;
                 if (!arg || !*arg || *arg == '#')          charptr = NULL;
                         continue;          opcode = parse_token(arg, filename, linenum);
                 intptr = NULL;          switch (opcode) {
                 charptr = NULL;          case sBadOption:
                 opcode = parse_token(arg, filename, linenum);                  return -1;
                 switch (opcode) {          case sPort:
                 case sBadOption:                  /* ignore ports from configfile if cmdline specifies ports */
                         bad_options++;                  if (options->ports_from_cmdline)
                         continue;                          return 0;
                 case sPort:                  if (options->listen_addrs != NULL)
                         /* ignore ports from configfile if cmdline specifies ports */                          fatal("%s line %d: ports must be specified before "
                         if (options->ports_from_cmdline)                              "ListenAdress.", filename, linenum);
                                 continue;                  if (options->num_ports >= MAX_PORTS)
                         if (options->listen_addrs != NULL)                          fatal("%s line %d: too many ports.",
                                 fatal("%s line %d: ports must be specified before "                              filename, linenum);
                                     "ListenAdress.", filename, linenum);                  arg = strdelim(&cp);
                         if (options->num_ports >= MAX_PORTS)                  if (!arg || *arg == '\0')
                                 fatal("%s line %d: too many ports.",                          fatal("%s line %d: missing port number.",
                                     filename, linenum);                              filename, linenum);
                         arg = strdelim(&cp);                  options->ports[options->num_ports++] = a2port(arg);
                         if (!arg || *arg == '\0')                  if (options->ports[options->num_ports-1] == 0)
                                 fatal("%s line %d: missing port number.",                          fatal("%s line %d: Badly formatted port number.",
                                     filename, linenum);                              filename, linenum);
                         options->ports[options->num_ports++] = a2port(arg);                  break;
                         if (options->ports[options->num_ports-1] == 0)  
                                 fatal("%s line %d: Badly formatted port number.",  
                                     filename, linenum);  
                         break;  
   
                 case sServerKeyBits:          case sServerKeyBits:
                         intptr = &options->server_key_bits;                  intptr = &options->server_key_bits;
 parse_int:  parse_int:
                         arg = strdelim(&cp);                  arg = strdelim(&cp);
                         if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                                 fatal("%s line %d: missing integer value.",                          fatal("%s line %d: missing integer value.",
                                     filename, linenum);                              filename, linenum);
                         value = atoi(arg);                  value = atoi(arg);
                         if (*intptr == -1)                  if (*intptr == -1)
                                 *intptr = value;                          *intptr = value;
                         break;                  break;
   
                 case sLoginGraceTime:          case sLoginGraceTime:
                         intptr = &options->login_grace_time;                  intptr = &options->login_grace_time;
 parse_time:  parse_time:
                         arg = strdelim(&cp);                  arg = strdelim(&cp);
                         if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                                 fatal("%s line %d: missing time value.",                          fatal("%s line %d: missing time value.",
                               filename, linenum);
                   if ((value = convtime(arg)) == -1)
                           fatal("%s line %d: invalid time value.",
                               filename, linenum);
                   if (*intptr == -1)
                           *intptr = value;
                   break;
   
           case sKeyRegenerationTime:
                   intptr = &options->key_regeneration_time;
                   goto parse_time;
   
           case sListenAddress:
                   arg = strdelim(&cp);
                   if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0)
                           fatal("%s line %d: missing inet addr.",
                               filename, linenum);
                   if (*arg == '[') {
                           if ((p = strchr(arg, ']')) == NULL)
                                   fatal("%s line %d: bad ipv6 inet addr usage.",
                                     filename, linenum);                                      filename, linenum);
                         if ((value = convtime(arg)) == -1)                          arg++;
                                 fatal("%s line %d: invalid time value.",                          memmove(p, p+1, strlen(p+1)+1);
                                     filename, linenum);                  } else if (((p = strchr(arg, ':')) == NULL) ||
                         if (*intptr == -1)                              (strchr(p+1, ':') != NULL)) {
                                 *intptr = value;                          add_listen_addr(options, arg, 0);
                         break;                          break;
                   }
                   if (*p == ':') {
                           u_short port;
   
                 case sKeyRegenerationTime:                          p++;
                         intptr = &options->key_regeneration_time;                          if (*p == '\0')
                         goto parse_time;                                  fatal("%s line %d: bad inet addr:port usage.",
   
                 case sListenAddress:  
                         arg = strdelim(&cp);  
                         if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0)  
                                 fatal("%s line %d: missing inet addr.",  
                                     filename, linenum);                                      filename, linenum);
                         if (*arg == '[') {                          else {
                                 if ((p = strchr(arg, ']')) == NULL)                                  *(p-1) = '\0';
                                         fatal("%s line %d: bad ipv6 inet addr usage.",                                  if ((port = a2port(p)) == 0)
                                           fatal("%s line %d: bad port number.",
                                             filename, linenum);                                              filename, linenum);
                                 arg++;                                  add_listen_addr(options, arg, port);
                                 memmove(p, p+1, strlen(p+1)+1);  
                         } else if (((p = strchr(arg, ':')) == NULL) ||  
                                     (strchr(p+1, ':') != NULL)) {  
                                 add_listen_addr(options, arg, 0);  
                                 break;  
                         }                          }
                         if (*p == ':') {                  } else if (*p == '\0')
                                 u_short port;                          add_listen_addr(options, arg, 0);
                   else
                           fatal("%s line %d: bad inet addr usage.",
                               filename, linenum);
                   break;
   
                                 p++;          case sHostKeyFile:
                                 if (*p == '\0')                  intptr = &options->num_host_key_files;
                                         fatal("%s line %d: bad inet addr:port usage.",                  if (*intptr >= MAX_HOSTKEYS)
                                             filename, linenum);                          fatal("%s line %d: too many host keys specified (max %d).",
                                 else {                              filename, linenum, MAX_HOSTKEYS);
                                         *(p-1) = '\0';                  charptr = &options->host_key_files[*intptr];
                                         if ((port = a2port(p)) == 0)  
                                                 fatal("%s line %d: bad port number.",  
                                                     filename, linenum);  
                                         add_listen_addr(options, arg, port);  
                                 }  
                         } else if (*p == '\0')  
                                 add_listen_addr(options, arg, 0);  
                         else  
                                 fatal("%s line %d: bad inet addr usage.",  
                                     filename, linenum);  
                         break;  
   
                 case sHostKeyFile:  
                         intptr = &options->num_host_key_files;  
                         if (*intptr >= MAX_HOSTKEYS)  
                                 fatal("%s line %d: too many host keys specified (max %d).",  
                                     filename, linenum, MAX_HOSTKEYS);  
                         charptr = &options->host_key_files[*intptr];  
 parse_filename:  parse_filename:
                         arg = strdelim(&cp);                  arg = strdelim(&cp);
                         if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                                 fatal("%s line %d: missing file name.",                          fatal("%s line %d: missing file name.",
                                     filename, linenum);                              filename, linenum);
                         if (*charptr == NULL) {                  if (*charptr == NULL) {
                                 *charptr = tilde_expand_filename(arg, getuid());                          *charptr = tilde_expand_filename(arg, getuid());
                                 /* increase optional counter */                          /* increase optional counter */
                                 if (intptr != NULL)                          if (intptr != NULL)
                                         *intptr = *intptr + 1;                                  *intptr = *intptr + 1;
                         }                  }
                         break;                  break;
   
                 case sPidFile:          case sPidFile:
                         charptr = &options->pid_file;                  charptr = &options->pid_file;
                         goto parse_filename;                  goto parse_filename;
   
                 case sPermitRootLogin:          case sPermitRootLogin:
                         intptr = &options->permit_root_login;                  intptr = &options->permit_root_login;
                         arg = strdelim(&cp);                  arg = strdelim(&cp);
                         if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                                 fatal("%s line %d: missing yes/"                          fatal("%s line %d: missing yes/"
                                     "without-password/forced-commands-only/no "                              "without-password/forced-commands-only/no "
                                     "argument.", filename, linenum);                              "argument.", filename, linenum);
                         value = 0;      /* silence compiler */                  value = 0;      /* silence compiler */
                         if (strcmp(arg, "without-password") == 0)                  if (strcmp(arg, "without-password") == 0)
                                 value = PERMIT_NO_PASSWD;                          value = PERMIT_NO_PASSWD;
                         else if (strcmp(arg, "forced-commands-only") == 0)                  else if (strcmp(arg, "forced-commands-only") == 0)
                                 value = PERMIT_FORCED_ONLY;                          value = PERMIT_FORCED_ONLY;
                         else if (strcmp(arg, "yes") == 0)                  else if (strcmp(arg, "yes") == 0)
                                 value = PERMIT_YES;                          value = PERMIT_YES;
                         else if (strcmp(arg, "no") == 0)                  else if (strcmp(arg, "no") == 0)
                                 value = PERMIT_NO;                          value = PERMIT_NO;
                         else                  else
                                 fatal("%s line %d: Bad yes/"                          fatal("%s line %d: Bad yes/"
                                     "without-password/forced-commands-only/no "                              "without-password/forced-commands-only/no "
                                     "argument: %s", filename, linenum, arg);                              "argument: %s", filename, linenum, arg);
                         if (*intptr == -1)                  if (*intptr == -1)
                                 *intptr = value;                          *intptr = value;
                         break;                  break;
   
                 case sIgnoreRhosts:          case sIgnoreRhosts:
                         intptr = &options->ignore_rhosts;                  intptr = &options->ignore_rhosts;
 parse_flag:  parse_flag:
                         arg = strdelim(&cp);                  arg = strdelim(&cp);
                         if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                                 fatal("%s line %d: missing yes/no argument.",                          fatal("%s line %d: missing yes/no argument.",
                                     filename, linenum);                              filename, linenum);
                         value = 0;      /* silence compiler */                  value = 0;      /* silence compiler */
                         if (strcmp(arg, "yes") == 0)                  if (strcmp(arg, "yes") == 0)
                                 value = 1;                          value = 1;
                         else if (strcmp(arg, "no") == 0)                  else if (strcmp(arg, "no") == 0)
                                 value = 0;                          value = 0;
                         else                  else
                                 fatal("%s line %d: Bad yes/no argument: %s",                          fatal("%s line %d: Bad yes/no argument: %s",
                                         filename, linenum, arg);                                  filename, linenum, arg);
                         if (*intptr == -1)                  if (*intptr == -1)
                                 *intptr = value;                          *intptr = value;
                         break;                  break;
   
                 case sIgnoreUserKnownHosts:          case sIgnoreUserKnownHosts:
                         intptr = &options->ignore_user_known_hosts;                  intptr = &options->ignore_user_known_hosts;
                         goto parse_flag;                  goto parse_flag;
   
                 case sRhostsAuthentication:          case sRhostsAuthentication:
                         intptr = &options->rhosts_authentication;                  intptr = &options->rhosts_authentication;
                         goto parse_flag;                  goto parse_flag;
   
                 case sRhostsRSAAuthentication:          case sRhostsRSAAuthentication:
                         intptr = &options->rhosts_rsa_authentication;                  intptr = &options->rhosts_rsa_authentication;
                         goto parse_flag;                  goto parse_flag;
   
                 case sHostbasedAuthentication:          case sHostbasedAuthentication:
                         intptr = &options->hostbased_authentication;                  intptr = &options->hostbased_authentication;
                         goto parse_flag;                  goto parse_flag;
   
                 case sHostbasedUsesNameFromPacketOnly:          case sHostbasedUsesNameFromPacketOnly:
                         intptr = &options->hostbased_uses_name_from_packet_only;                  intptr = &options->hostbased_uses_name_from_packet_only;
                         goto parse_flag;                  goto parse_flag;
   
                 case sRSAAuthentication:          case sRSAAuthentication:
                         intptr = &options->rsa_authentication;                  intptr = &options->rsa_authentication;
                         goto parse_flag;                  goto parse_flag;
   
                 case sPubkeyAuthentication:          case sPubkeyAuthentication:
                         intptr = &options->pubkey_authentication;                  intptr = &options->pubkey_authentication;
                         goto parse_flag;                  goto parse_flag;
 #if defined(KRB4) || defined(KRB5)  #if defined(KRB4) || defined(KRB5)
                 case sKerberosAuthentication:          case sKerberosAuthentication:
                         intptr = &options->kerberos_authentication;                  intptr = &options->kerberos_authentication;
                         goto parse_flag;                  goto parse_flag;
   
                 case sKerberosOrLocalPasswd:          case sKerberosOrLocalPasswd:
                         intptr = &options->kerberos_or_local_passwd;                  intptr = &options->kerberos_or_local_passwd;
                         goto parse_flag;                  goto parse_flag;
   
                 case sKerberosTicketCleanup:          case sKerberosTicketCleanup:
                         intptr = &options->kerberos_ticket_cleanup;                  intptr = &options->kerberos_ticket_cleanup;
                         goto parse_flag;                  goto parse_flag;
 #endif  #endif
 #if defined(AFS) || defined(KRB5)  #if defined(AFS) || defined(KRB5)
                 case sKerberosTgtPassing:          case sKerberosTgtPassing:
                         intptr = &options->kerberos_tgt_passing;                  intptr = &options->kerberos_tgt_passing;
                         goto parse_flag;                  goto parse_flag;
 #endif  #endif
 #ifdef AFS  #ifdef AFS
                 case sAFSTokenPassing:          case sAFSTokenPassing:
                         intptr = &options->afs_token_passing;                  intptr = &options->afs_token_passing;
                         goto parse_flag;                  goto parse_flag;
 #endif  #endif
   
                 case sPasswordAuthentication:          case sPasswordAuthentication:
                         intptr = &options->password_authentication;                  intptr = &options->password_authentication;
                         goto parse_flag;                  goto parse_flag;
   
                 case sKbdInteractiveAuthentication:          case sKbdInteractiveAuthentication:
                         intptr = &options->kbd_interactive_authentication;                  intptr = &options->kbd_interactive_authentication;
                         goto parse_flag;                  goto parse_flag;
   
                 case sChallengeResponseAuthentication:          case sChallengeResponseAuthentication:
                         intptr = &options->challenge_response_authentication;                  intptr = &options->challenge_response_authentication;
                         goto parse_flag;                  goto parse_flag;
   
                 case sPrintMotd:          case sPrintMotd:
                         intptr = &options->print_motd;                  intptr = &options->print_motd;
                         goto parse_flag;                  goto parse_flag;
   
                 case sPrintLastLog:          case sPrintLastLog:
                         intptr = &options->print_lastlog;                  intptr = &options->print_lastlog;
                         goto parse_flag;                  goto parse_flag;
   
                 case sX11Forwarding:          case sX11Forwarding:
                         intptr = &options->x11_forwarding;                  intptr = &options->x11_forwarding;
                         goto parse_flag;                  goto parse_flag;
   
                 case sX11DisplayOffset:          case sX11DisplayOffset:
                         intptr = &options->x11_display_offset;                  intptr = &options->x11_display_offset;
                         goto parse_int;                  goto parse_int;
   
                 case sXAuthLocation:          case sXAuthLocation:
                         charptr = &options->xauth_location;                  charptr = &options->xauth_location;
                         goto parse_filename;                  goto parse_filename;
   
                 case sStrictModes:          case sStrictModes:
                         intptr = &options->strict_modes;                  intptr = &options->strict_modes;
                         goto parse_flag;                  goto parse_flag;
   
                 case sKeepAlives:          case sKeepAlives:
                         intptr = &options->keepalives;                  intptr = &options->keepalives;
                         goto parse_flag;                  goto parse_flag;
   
                 case sEmptyPasswd:          case sEmptyPasswd:
                         intptr = &options->permit_empty_passwd;                  intptr = &options->permit_empty_passwd;
                         goto parse_flag;                  goto parse_flag;
   
                 case sUseLogin:          case sUseLogin:
                         intptr = &options->use_login;                  intptr = &options->use_login;
                         goto parse_flag;                  goto parse_flag;
   
                 case sGatewayPorts:          case sGatewayPorts:
                         intptr = &options->gateway_ports;                  intptr = &options->gateway_ports;
                         goto parse_flag;                  goto parse_flag;
   
                 case sReverseMappingCheck:          case sReverseMappingCheck:
                         intptr = &options->reverse_mapping_check;                  intptr = &options->reverse_mapping_check;
                         goto parse_flag;                  goto parse_flag;
   
                 case sLogFacility:          case sLogFacility:
                         intptr = (int *) &options->log_facility;                  intptr = (int *) &options->log_facility;
                         arg = strdelim(&cp);                  arg = strdelim(&cp);
                         value = log_facility_number(arg);                  value = log_facility_number(arg);
                         if (value == (SyslogFacility) - 1)                  if (value == (SyslogFacility) - 1)
                                 fatal("%.200s line %d: unsupported log facility '%s'",                          fatal("%.200s line %d: unsupported log facility '%s'",
                                     filename, linenum, arg ? arg : "<NONE>");                              filename, linenum, arg ? arg : "<NONE>");
                         if (*intptr == -1)                  if (*intptr == -1)
                                 *intptr = (SyslogFacility) value;                          *intptr = (SyslogFacility) value;
                         break;                  break;
   
                 case sLogLevel:          case sLogLevel:
                         intptr = (int *) &options->log_level;                  intptr = (int *) &options->log_level;
                         arg = strdelim(&cp);                  arg = strdelim(&cp);
                         value = log_level_number(arg);                  value = log_level_number(arg);
                         if (value == (LogLevel) - 1)                  if (value == (LogLevel) - 1)
                                 fatal("%.200s line %d: unsupported log level '%s'",                          fatal("%.200s line %d: unsupported log level '%s'",
                                     filename, linenum, arg ? arg : "<NONE>");                              filename, linenum, arg ? arg : "<NONE>");
                         if (*intptr == -1)                  if (*intptr == -1)
                                 *intptr = (LogLevel) value;                          *intptr = (LogLevel) value;
                         break;                  break;
   
                 case sAllowTcpForwarding:          case sAllowTcpForwarding:
                         intptr = &options->allow_tcp_forwarding;                  intptr = &options->allow_tcp_forwarding;
                         goto parse_flag;                  goto parse_flag;
   
                 case sAllowUsers:          case sAllowUsers:
                         while ((arg = strdelim(&cp)) && *arg != '\0') {                  while ((arg = strdelim(&cp)) && *arg != '\0') {
                                 if (options->num_allow_users >= MAX_ALLOW_USERS)                          if (options->num_allow_users >= MAX_ALLOW_USERS)
                                         fatal("%s line %d: too many allow users.",                                  fatal("%s line %d: too many allow users.",
                                             filename, linenum);                                      filename, linenum);
                                 options->allow_users[options->num_allow_users++] = xstrdup(arg);                          options->allow_users[options->num_allow_users++] = xstrdup(arg);
                         }                  }
                         break;                  break;
   
                 case sDenyUsers:          case sDenyUsers:
                         while ((arg = strdelim(&cp)) && *arg != '\0') {                  while ((arg = strdelim(&cp)) && *arg != '\0') {
                                 if (options->num_deny_users >= MAX_DENY_USERS)                          if (options->num_deny_users >= MAX_DENY_USERS)
                                         fatal( "%s line %d: too many deny users.",                                  fatal( "%s line %d: too many deny users.",
                                             filename, linenum);                                      filename, linenum);
                                 options->deny_users[options->num_deny_users++] = xstrdup(arg);                          options->deny_users[options->num_deny_users++] = xstrdup(arg);
                         }                  }
                         break;                  break;
   
                 case sAllowGroups:          case sAllowGroups:
                         while ((arg = strdelim(&cp)) && *arg != '\0') {                  while ((arg = strdelim(&cp)) && *arg != '\0') {
                                 if (options->num_allow_groups >= MAX_ALLOW_GROUPS)                          if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
                                         fatal("%s line %d: too many allow groups.",                                  fatal("%s line %d: too many allow groups.",
                                             filename, linenum);                                      filename, linenum);
                                 options->allow_groups[options->num_allow_groups++] = xstrdup(arg);                          options->allow_groups[options->num_allow_groups++] = xstrdup(arg);
                         }                  }
                         break;                  break;
   
                 case sDenyGroups:          case sDenyGroups:
                         while ((arg = strdelim(&cp)) && *arg != '\0') {                  while ((arg = strdelim(&cp)) && *arg != '\0') {
                                 if (options->num_deny_groups >= MAX_DENY_GROUPS)                          if (options->num_deny_groups >= MAX_DENY_GROUPS)
                                         fatal("%s line %d: too many deny groups.",                                  fatal("%s line %d: too many deny groups.",
                                             filename, linenum);                                      filename, linenum);
                                 options->deny_groups[options->num_deny_groups++] = xstrdup(arg);                          options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
                         }                  }
                         break;                  break;
   
                 case sCiphers:          case sCiphers:
                         arg = strdelim(&cp);                  arg = strdelim(&cp);
                         if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                                 fatal("%s line %d: Missing argument.", filename, linenum);                          fatal("%s line %d: Missing argument.", filename, linenum);
                         if (!ciphers_valid(arg))                  if (!ciphers_valid(arg))
                                 fatal("%s line %d: Bad SSH2 cipher spec '%s'.",                          fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
                                     filename, linenum, arg ? arg : "<NONE>");                              filename, linenum, arg ? arg : "<NONE>");
                         if (options->ciphers == NULL)                  if (options->ciphers == NULL)
                                 options->ciphers = xstrdup(arg);                          options->ciphers = xstrdup(arg);
                         break;                  break;
   
                 case sMacs:          case sMacs:
                         arg = strdelim(&cp);                  arg = strdelim(&cp);
                         if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                                 fatal("%s line %d: Missing argument.", filename, linenum);                          fatal("%s line %d: Missing argument.", filename, linenum);
                         if (!mac_valid(arg))                  if (!mac_valid(arg))
                                 fatal("%s line %d: Bad SSH2 mac spec '%s'.",                          fatal("%s line %d: Bad SSH2 mac spec '%s'.",
                                     filename, linenum, arg ? arg : "<NONE>");                              filename, linenum, arg ? arg : "<NONE>");
                         if (options->macs == NULL)                  if (options->macs == NULL)
                                 options->macs = xstrdup(arg);                          options->macs = xstrdup(arg);
                         break;                  break;
   
                 case sProtocol:          case sProtocol:
                         intptr = &options->protocol;                  intptr = &options->protocol;
                         arg = strdelim(&cp);                  arg = strdelim(&cp);
                         if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                                 fatal("%s line %d: Missing argument.", filename, linenum);                          fatal("%s line %d: Missing argument.", filename, linenum);
                         value = proto_spec(arg);                  value = proto_spec(arg);
                         if (value == SSH_PROTO_UNKNOWN)                  if (value == SSH_PROTO_UNKNOWN)
                                 fatal("%s line %d: Bad protocol spec '%s'.",                          fatal("%s line %d: Bad protocol spec '%s'.",
                                       filename, linenum, arg ? arg : "<NONE>");                                filename, linenum, arg ? arg : "<NONE>");
                         if (*intptr == SSH_PROTO_UNKNOWN)                  if (*intptr == SSH_PROTO_UNKNOWN)
                                 *intptr = value;                          *intptr = value;
                         break;                  break;
   
                 case sSubsystem:          case sSubsystem:
                         if (options->num_subsystems >= MAX_SUBSYSTEMS) {                  if (options->num_subsystems >= MAX_SUBSYSTEMS) {
                                 fatal("%s line %d: too many subsystems defined.",                          fatal("%s line %d: too many subsystems defined.",
                                       filename, linenum);                                filename, linenum);
                         }                  }
                         arg = strdelim(&cp);                  arg = strdelim(&cp);
                         if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                                 fatal("%s line %d: Missing subsystem name.",                          fatal("%s line %d: Missing subsystem name.",
                                       filename, linenum);                                filename, linenum);
                         for (i = 0; i < options->num_subsystems; i++)                  for (i = 0; i < options->num_subsystems; i++)
                                 if (strcmp(arg, options->subsystem_name[i]) == 0)                          if (strcmp(arg, options->subsystem_name[i]) == 0)
                                         fatal("%s line %d: Subsystem '%s' already defined.",                                  fatal("%s line %d: Subsystem '%s' already defined.",
                                               filename, linenum, arg);                                        filename, linenum, arg);
                         options->subsystem_name[options->num_subsystems] = xstrdup(arg);                  options->subsystem_name[options->num_subsystems] = xstrdup(arg);
                         arg = strdelim(&cp);                  arg = strdelim(&cp);
                         if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                                 fatal("%s line %d: Missing subsystem command.",                          fatal("%s line %d: Missing subsystem command.",
                                       filename, linenum);                                filename, linenum);
                         options->subsystem_command[options->num_subsystems] = xstrdup(arg);                  options->subsystem_command[options->num_subsystems] = xstrdup(arg);
                         options->num_subsystems++;                  options->num_subsystems++;
                         break;                  break;
   
                 case sMaxStartups:          case sMaxStartups:
                         arg = strdelim(&cp);                  arg = strdelim(&cp);
                         if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                                 fatal("%s line %d: Missing MaxStartups spec.",                          fatal("%s line %d: Missing MaxStartups spec.",
                                       filename, linenum);                                filename, linenum);
                         if ((n = sscanf(arg, "%d:%d:%d",                  if ((n = sscanf(arg, "%d:%d:%d",
                             &options->max_startups_begin,                      &options->max_startups_begin,
                             &options->max_startups_rate,                      &options->max_startups_rate,
                             &options->max_startups)) == 3) {                      &options->max_startups)) == 3) {
                                 if (options->max_startups_begin >                          if (options->max_startups_begin >
                                     options->max_startups ||                              options->max_startups ||
                                     options->max_startups_rate > 100 ||                              options->max_startups_rate > 100 ||
                                     options->max_startups_rate < 1)                              options->max_startups_rate < 1)
                                         fatal("%s line %d: Illegal MaxStartups spec.",  
                                             filename, linenum);  
                         } else if (n != 1)  
                                 fatal("%s line %d: Illegal MaxStartups spec.",                                  fatal("%s line %d: Illegal MaxStartups spec.",
                                     filename, linenum);                                      filename, linenum);
                         else                  } else if (n != 1)
                                 options->max_startups = options->max_startups_begin;                          fatal("%s line %d: Illegal MaxStartups spec.",
                         break;                              filename, linenum);
                   else
                           options->max_startups = options->max_startups_begin;
                   break;
   
                 case sBanner:          case sBanner:
                         charptr = &options->banner;                  charptr = &options->banner;
                         goto parse_filename;                  goto parse_filename;
                 /*          /*
                  * These options can contain %X options expanded at           * These options can contain %X options expanded at
                  * connect time, so that you can specify paths like:           * connect time, so that you can specify paths like:
                  *           *
                  * AuthorizedKeysFile   /etc/ssh_keys/%u           * AuthorizedKeysFile   /etc/ssh_keys/%u
                  */           */
                 case sAuthorizedKeysFile:          case sAuthorizedKeysFile:
                 case sAuthorizedKeysFile2:          case sAuthorizedKeysFile2:
                         charptr = (opcode == sAuthorizedKeysFile ) ?                  charptr = (opcode == sAuthorizedKeysFile ) ?
                             &options->authorized_keys_file :                      &options->authorized_keys_file :
                             &options->authorized_keys_file2;                      &options->authorized_keys_file2;
                         goto parse_filename;                  goto parse_filename;
   
                 case sClientAliveInterval:          case sClientAliveInterval:
                         intptr = &options->client_alive_interval;                  intptr = &options->client_alive_interval;
                         goto parse_time;                  goto parse_time;
   
                 case sClientAliveCountMax:          case sClientAliveCountMax:
                         intptr = &options->client_alive_count_max;                  intptr = &options->client_alive_count_max;
                         goto parse_int;                  goto parse_int;
   
                 case sDeprecated:          case sDeprecated:
                         log("%s line %d: Deprecated option %s",                  log("%s line %d: Deprecated option %s",
                             filename, linenum, arg);                      filename, linenum, arg);
                         while (arg)                  while (arg)
                             arg = strdelim(&cp);                      arg = strdelim(&cp);
                         break;                  break;
   
                 default:          default:
                         fatal("%s line %d: Missing handler for opcode %s (%d)",                  fatal("%s line %d: Missing handler for opcode %s (%d)",
                             filename, linenum, arg, opcode);                      filename, linenum, arg, opcode);
                 }          }
                 if ((arg = strdelim(&cp)) != NULL && *arg != '\0')          if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
                         fatal("%s line %d: garbage at end of line; \"%.200s\".",                  fatal("%s line %d: garbage at end of line; \"%.200s\".",
                             filename, linenum, arg);                      filename, linenum, arg);
           return 0;
   }
   
   /* Reads the server configuration file. */
   
   void
   read_server_config(ServerOptions *options, const char *filename)
   {
           FILE *f;
           char line[1024];
           int linenum;
           int bad_options = 0;
   
           f = fopen(filename, "r");
           if (!f) {
                   perror(filename);
                   exit(1);
           }
           linenum = 0;
           while (fgets(line, sizeof(line), f)) {
                   /* Update line number counter. */
                   linenum++;
                   if (process_server_config_line(options, line, filename, linenum) != 0)
                           bad_options++;
         }          }
         fclose(f);          fclose(f);
         if (bad_options > 0)          if (bad_options > 0)

Legend:
Removed from v.1.93  
changed lines
  Added in v.1.94