[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.379 and 1.380

version 1.379, 2021/04/03 06:18:40 version 1.380, 2021/06/08 07:09:42
Line 997 
Line 997 
                     ci->laddress ? ci->laddress : "(null)", ci->lport);                      ci->laddress ? ci->laddress : "(null)", ci->lport);
   
         while ((attrib = strdelim(&cp)) && *attrib != '\0') {          while ((attrib = strdelim(&cp)) && *attrib != '\0') {
                   /* Terminate on comment */
                   if (*attrib == '#') {
                           cp = NULL; /* mark all arguments consumed */
                           break;
                   }
                   arg = NULL;
                 attributes++;                  attributes++;
                   /* Criterion "all" has no argument and must appear alone */
                 if (strcasecmp(attrib, "all") == 0) {                  if (strcasecmp(attrib, "all") == 0) {
                         if (attributes != 1 ||                          if (attributes > 1 || ((arg = strdelim(&cp)) != NULL &&
                             ((arg = strdelim(&cp)) != NULL && *arg != '\0')) {                              *arg != '\0' && *arg != '#')) {
                                 error("'all' cannot be combined with other "                                  error("'all' cannot be combined with other "
                                     "Match attributes");                                      "Match attributes");
                                 return -1;                                  return -1;
                         }                          }
                           if (arg != NULL && *arg == '#')
                                   cp = NULL; /* mark all arguments consumed */
                         *condition = cp;                          *condition = cp;
                         return 1;                          return 1;
                 }                  }
                 if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {                  /* All other criteria require an argument */
                   if ((arg = strdelim(&cp)) == NULL ||
                       *arg == '\0' || *arg == '#') {
                         error("Missing Match criteria for %s", attrib);                          error("Missing Match criteria for %s", attrib);
                         return -1;                          return -1;
                 }                  }
Line 1203 
Line 1214 
     struct connection_info *connectinfo, int *inc_flags, int depth,      struct connection_info *connectinfo, int *inc_flags, int depth,
     struct include_list *includes)      struct include_list *includes)
 {  {
         char ch, *cp, ***chararrayptr, **charptr, *arg, *arg2, *p;          char ch, *str, ***chararrayptr, **charptr, *arg, *arg2, *p, *keyword;
         int cmdline = 0, *intptr, value, value2, n, port, oactive, r, found;          int cmdline = 0, *intptr, value, value2, n, port, oactive, r, found;
         SyslogFacility *log_facility_ptr;          SyslogFacility *log_facility_ptr;
         LogLevel *log_level_ptr;          LogLevel *log_level_ptr;
Line 1215 
Line 1226 
         const char *errstr;          const char *errstr;
         struct include_item *item;          struct include_item *item;
         glob_t gbuf;          glob_t gbuf;
           char **oav = NULL, **av;
           int oac = 0, ac;
           int ret = -1;
   
         /* Strip trailing whitespace. Allow \f (form feed) at EOL only */          /* Strip trailing whitespace. Allow \f (form feed) at EOL only */
         if ((len = strlen(line)) == 0)          if ((len = strlen(line)) == 0)
Line 1225 
Line 1239 
                 line[len] = '\0';                  line[len] = '\0';
         }          }
   
         cp = line;          str = line;
         if ((arg = strdelim(&cp)) == NULL)          if ((keyword = strdelim(&str)) == NULL)
                 return 0;                  return 0;
         /* Ignore leading whitespace */          /* Ignore leading whitespace */
         if (*arg == '\0')          if (*keyword == '\0')
                 arg = strdelim(&cp);                  keyword = strdelim(&str);
         if (!arg || !*arg || *arg == '#')          if (!keyword || !*keyword || *keyword == '#')
                 return 0;                  return 0;
           if (str == NULL || *str == '\0') {
                   error("%s line %d: no argument after keyword \"%s\"",
                       filename, linenum, keyword);
                   return -1;
           }
         intptr = NULL;          intptr = NULL;
         charptr = NULL;          charptr = NULL;
         opcode = parse_token(arg, filename, linenum, &flags);          opcode = parse_token(keyword, filename, linenum, &flags);
   
           if (argv_split(str, &oac, &oav, 1) != 0) {
                   error("%s line %d: invalid quotes", filename, linenum);
                   return -1;
           }
           ac = oac;
           av = oav;
   
         if (activep == NULL) { /* We are processing a command line directive */          if (activep == NULL) { /* We are processing a command line directive */
                 cmdline = 1;                  cmdline = 1;
                 activep = &cmdline;                  activep = &cmdline;
         }          }
         if (*activep && opcode != sMatch && opcode != sInclude)          if (*activep && opcode != sMatch && opcode != sInclude)
                 debug3("%s:%d setting %s %s", filename, linenum, arg, cp);                  debug3("%s:%d setting %s %s", filename, linenum, keyword, str);
         if (*activep == 0 && !(flags & SSHCFG_MATCH)) {          if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
                 if (connectinfo == NULL) {                  if (connectinfo == NULL) {
                         fatal("%s line %d: Directive '%s' is not allowed "                          fatal("%s line %d: Directive '%s' is not allowed "
                             "within a Match block", filename, linenum, arg);                              "within a Match block", filename, linenum, keyword);
                 } else { /* this is a directive we have already processed */                  } else { /* this is a directive we have already processed */
                         while (arg)                          ret = 0;
                                 arg = strdelim(&cp);                          goto out;
                         return 0;  
                 }                  }
         }          }
   
         switch (opcode) {          switch (opcode) {
         case sBadOption:          case sBadOption:
                 return -1;                  goto out;
         case sPort:          case sPort:
                 /* ignore ports from configfile if cmdline specifies ports */                  /* ignore ports from configfile if cmdline specifies ports */
                 if (options->ports_from_cmdline)                  if (options->ports_from_cmdline) {
                         return 0;                          argv_consume(&ac);
                           break;
                   }
                 if (options->num_ports >= MAX_PORTS)                  if (options->num_ports >= MAX_PORTS)
                         fatal("%s line %d: too many ports.",                          fatal("%s line %d: too many ports.",
                             filename, linenum);                              filename, linenum);
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                         fatal("%s line %d: missing port number.",                          fatal("%s line %d: missing port number.",
                             filename, linenum);                              filename, linenum);
Line 1277 
Line 1304 
         case sLoginGraceTime:          case sLoginGraceTime:
                 intptr = &options->login_grace_time;                  intptr = &options->login_grace_time;
  parse_time:   parse_time:
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                         fatal("%s line %d: missing time value.",                          fatal("%s line %d: missing time value.",
                             filename, linenum);                              filename, linenum);
Line 1289 
Line 1316 
                 break;                  break;
   
         case sListenAddress:          case sListenAddress:
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if (arg == NULL || *arg == '\0')                  if (arg == NULL || *arg == '\0')
                         fatal("%s line %d: missing address",                          fatal("%s line %d: missing address",
                             filename, linenum);                              filename, linenum);
Line 1314 
Line 1341 
                 }                  }
                 /* Optional routing table */                  /* Optional routing table */
                 arg2 = NULL;                  arg2 = NULL;
                 if ((arg = strdelim(&cp)) != NULL) {                  if ((arg = argv_next(&ac, &av)) != NULL) {
                         if (strcmp(arg, "rdomain") != 0 ||                          if (strcmp(arg, "rdomain") != 0 ||
                             (arg2 = strdelim(&cp)) == NULL)                              (arg2 = argv_next(&ac, &av)) == NULL)
                                 fatal("%s line %d: bad ListenAddress syntax",                                  fatal("%s line %d: bad ListenAddress syntax",
                                     filename, linenum);                                      filename, linenum);
                         if (!valid_rdomain(arg2))                          if (!valid_rdomain(arg2))
                                 fatal("%s line %d: bad routing domain",                                  fatal("%s line %d: bad routing domain",
                                     filename, linenum);                                      filename, linenum);
                 }                  }
   
                 queue_listen_addr(options, p, arg2, port);                  queue_listen_addr(options, p, arg2, port);
   
                 break;                  break;
Line 1332 
Line 1358 
                 intptr = &options->address_family;                  intptr = &options->address_family;
                 multistate_ptr = multistate_addressfamily;                  multistate_ptr = multistate_addressfamily;
  parse_multistate:   parse_multistate:
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                         fatal("%s line %d: missing argument.",                          fatal("%s line %d: missing argument.",
                             filename, linenum);                              filename, linenum);
Line 1351 
Line 1377 
                 break;                  break;
   
         case sHostKeyFile:          case sHostKeyFile:
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 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);
Line 1363 
Line 1389 
   
         case sHostKeyAgent:          case sHostKeyAgent:
                 charptr = &options->host_key_agent;                  charptr = &options->host_key_agent;
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                         fatal("%s line %d: missing socket name.",                          fatal("%s line %d: missing socket name.",
                             filename, linenum);                              filename, linenum);
Line 1373 
Line 1399 
                 break;                  break;
   
         case sHostCertificate:          case sHostCertificate:
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 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);
Line 1384 
Line 1410 
         case sPidFile:          case sPidFile:
                 charptr = &options->pid_file;                  charptr = &options->pid_file;
  parse_filename:   parse_filename:
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 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);
Line 1427 
Line 1453 
         case sHostbasedAcceptedAlgorithms:          case sHostbasedAcceptedAlgorithms:
                 charptr = &options->hostbased_accepted_algos;                  charptr = &options->hostbased_accepted_algos;
  parse_pubkey_algos:   parse_pubkey_algos:
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                         fatal("%s line %d: Missing argument.",                          fatal("%s line %d: Missing argument.",
                             filename, linenum);                              filename, linenum);
Line 1459 
Line 1485 
         case sPubkeyAuthOptions:          case sPubkeyAuthOptions:
                 intptr = &options->pubkey_auth_options;                  intptr = &options->pubkey_auth_options;
                 value = 0;                  value = 0;
                 while ((arg = strdelim(&cp)) && *arg != '\0') {                  while ((arg = argv_next(&ac, &av)) != NULL) {
                         if (strcasecmp(arg, "none") == 0)                          if (strcasecmp(arg, "none") == 0)
                                 continue;                                  continue;
                         if (strcasecmp(arg, "touch-required") == 0)                          if (strcasecmp(arg, "touch-required") == 0)
Line 1467 
Line 1493 
                         else if (strcasecmp(arg, "verify-required") == 0)                          else if (strcasecmp(arg, "verify-required") == 0)
                                 value |= PUBKEYAUTH_VERIFY_REQUIRED;                                  value |= PUBKEYAUTH_VERIFY_REQUIRED;
                         else {                          else {
                                 fatal("%s line %d: unsupported "                                  error("%s line %d: unsupported %s option %s",
                                     "PubkeyAuthOptions option %s",                                      filename, linenum, keyword, arg);
                                     filename, linenum, arg);                                  goto out;
                         }                          }
                 }                  }
                 if (*activep && *intptr == -1)                  if (*activep && *intptr == -1)
Line 1531 
Line 1557 
         case sX11DisplayOffset:          case sX11DisplayOffset:
                 intptr = &options->x11_display_offset;                  intptr = &options->x11_display_offset;
  parse_int:   parse_int:
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if ((errstr = atoi_err(arg, &value)) != NULL)                  if ((errstr = atoi_err(arg, &value)) != NULL)
                         fatal("%s line %d: integer value %s.",                          fatal("%s line %d: %s integer value %s.",
                             filename, linenum, errstr);                              filename, linenum, keyword, errstr);
                 if (*activep && *intptr == -1)                  if (*activep && *intptr == -1)
                         *intptr = value;                          *intptr = value;
                 break;                  break;
Line 1570 
Line 1596 
         case sPermitUserEnvironment:          case sPermitUserEnvironment:
                 intptr = &options->permit_user_env;                  intptr = &options->permit_user_env;
                 charptr = &options->permit_user_env_allowlist;                  charptr = &options->permit_user_env_allowlist;
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                         fatal("%s line %d: missing argument.",                          fatal("%s line %d: %s missing argument.",
                             filename, linenum);                              filename, linenum, keyword);
                 value = 0;                  value = 0;
                 p = NULL;                  p = NULL;
                 if (strcmp(arg, "yes") == 0)                  if (strcmp(arg, "yes") == 0)
Line 1599 
Line 1625 
                 goto parse_multistate;                  goto parse_multistate;
   
         case sRekeyLimit:          case sRekeyLimit:
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                         fatal("%.200s line %d: Missing argument.", filename,                          fatal("%s line %d: %s missing argument.",
                             linenum);                              filename, linenum, keyword);
                 if (strcmp(arg, "default") == 0) {                  if (strcmp(arg, "default") == 0) {
                         val64 = 0;                          val64 = 0;
                 } else {                  } else {
                         if (scan_scaled(arg, &val64) == -1)                          if (scan_scaled(arg, &val64) == -1)
                                 fatal("%.200s line %d: Bad number '%s': %s",                                  fatal("%.200s line %d: Bad %s number '%s': %s",
                                     filename, linenum, arg, strerror(errno));                                      filename, linenum, keyword,
                                       arg, strerror(errno));
                         if (val64 != 0 && val64 < 16)                          if (val64 != 0 && val64 < 16)
                                 fatal("%.200s line %d: RekeyLimit too small",                                  fatal("%.200s line %d: %s too small",
                                     filename, linenum);                                      filename, linenum, keyword);
                 }                  }
                 if (*activep && options->rekey_limit == -1)                  if (*activep && options->rekey_limit == -1)
                         options->rekey_limit = val64;                          options->rekey_limit = val64;
                 if (cp != NULL) { /* optional rekey interval present */                  if (ac != 0) { /* optional rekey interval present */
                         if (strcmp(cp, "none") == 0) {                          if (strcmp(av[0], "none") == 0) {
                                 (void)strdelim(&cp);    /* discard */                                  (void)argv_next(&ac, &av);      /* discard */
                                 break;                                  break;
                         }                          }
                         intptr = &options->rekey_interval;                          intptr = &options->rekey_interval;
Line 1636 
Line 1663 
   
         case sLogFacility:          case sLogFacility:
                 log_facility_ptr = &options->log_facility;                  log_facility_ptr = &options->log_facility;
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 value = log_facility_number(arg);                  value = log_facility_number(arg);
                 if (value == SYSLOG_FACILITY_NOT_SET)                  if (value == SYSLOG_FACILITY_NOT_SET)
                         fatal("%.200s line %d: unsupported log facility '%s'",                          fatal("%.200s line %d: unsupported log facility '%s'",
Line 1647 
Line 1674 
   
         case sLogLevel:          case sLogLevel:
                 log_level_ptr = &options->log_level;                  log_level_ptr = &options->log_level;
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 value = log_level_number(arg);                  value = log_level_number(arg);
                 if (value == SYSLOG_LEVEL_NOT_SET)                  if (value == SYSLOG_LEVEL_NOT_SET)
                         fatal("%.200s line %d: unsupported log level '%s'",                          fatal("%.200s line %d: unsupported log level '%s'",
Line 1657 
Line 1684 
                 break;                  break;
   
         case sLogVerbose:          case sLogVerbose:
                 while ((arg = strdelim(&cp)) && *arg != '\0') {                  found = options->num_log_verbose == 0;
                         if (!*activep)                  i = 0;
                   while ((arg = argv_next(&ac, &av)) != NULL) {
                           if (*arg == '\0') {
                                   error("%s line %d: keyword %s empty argument",
                                       filename, linenum, keyword);
                                   goto out;
                           }
                           /* Allow "none" only in first position */
                           if (strcasecmp(arg, "none") == 0) {
                                   if (i > 0 || ac > 0) {
                                           error("%s line %d: keyword %s \"none\" "
                                               "argument must appear alone.",
                                               filename, linenum, keyword);
                                           goto out;
                                   }
                           }
                           i++;
                           if (!found || !*activep)
                                 continue;                                  continue;
                         opt_array_append(filename, linenum, "oLogVerbose",                          opt_array_append(filename, linenum, keyword,
                             &options->log_verbose, &options->num_log_verbose,                              &options->log_verbose, &options->num_log_verbose,
                             arg);                              arg);
                 }                  }
Line 1685 
Line 1729 
                 goto parse_flag;                  goto parse_flag;
   
         case sAllowUsers:          case sAllowUsers:
                 while ((arg = strdelim(&cp)) && *arg != '\0') {                  chararrayptr = &options->allow_users;
                         if (match_user(NULL, NULL, NULL, arg) == -1)                  uintptr = &options->num_allow_users;
                                 fatal("%s line %d: invalid AllowUsers pattern: "   parse_allowdenyusers:
                                     "\"%.100s\"", filename, linenum, arg);                  while ((arg = argv_next(&ac, &av)) != NULL) {
                           if (*arg == '\0' ||
                               match_user(NULL, NULL, NULL, arg) == -1)
                                   fatal("%s line %d: invalid %s pattern: \"%s\"",
                                       filename, linenum, keyword, arg);
                         if (!*activep)                          if (!*activep)
                                 continue;                                  continue;
                         opt_array_append(filename, linenum, "AllowUsers",                          opt_array_append(filename, linenum, keyword,
                             &options->allow_users, &options->num_allow_users,                              chararrayptr, uintptr, arg);
                             arg);  
                 }                  }
                 break;                  break;
   
         case sDenyUsers:          case sDenyUsers:
                 while ((arg = strdelim(&cp)) && *arg != '\0') {                  chararrayptr = &options->deny_users;
                         if (match_user(NULL, NULL, NULL, arg) == -1)                  uintptr = &options->num_deny_users;
                                 fatal("%s line %d: invalid DenyUsers pattern: "                  goto parse_allowdenyusers;
                                     "\"%.100s\"", filename, linenum, arg);  
                         if (!*activep)  
                                 continue;  
                         opt_array_append(filename, linenum, "DenyUsers",  
                             &options->deny_users, &options->num_deny_users,  
                             arg);  
                 }  
                 break;  
   
         case sAllowGroups:          case sAllowGroups:
                 while ((arg = strdelim(&cp)) && *arg != '\0') {                  chararrayptr = &options->allow_groups;
                   uintptr = &options->num_allow_groups;
    parse_allowdenygroups:
                   while ((arg = argv_next(&ac, &av)) != NULL) {
                           if (*arg == '\0')
                                   fatal("%s line %d: empty %s pattern",
                                       filename, linenum, keyword);
                         if (!*activep)                          if (!*activep)
                                 continue;                                  continue;
                         opt_array_append(filename, linenum, "AllowGroups",                          opt_array_append(filename, linenum, keyword,
                             &options->allow_groups, &options->num_allow_groups,                              chararrayptr, uintptr, arg);
                             arg);  
                 }                  }
                 break;                  break;
   
         case sDenyGroups:          case sDenyGroups:
                 while ((arg = strdelim(&cp)) && *arg != '\0') {                  chararrayptr = &options->deny_groups;
                         if (!*activep)                  uintptr = &options->num_deny_groups;
                                 continue;                  goto parse_allowdenygroups;
                         opt_array_append(filename, linenum, "DenyGroups",  
                             &options->deny_groups, &options->num_deny_groups,  
                             arg);  
                 }  
                 break;  
   
         case sCiphers:          case sCiphers:
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                         fatal("%s line %d: Missing argument.", filename, linenum);                          fatal("%s line %d: %s missing argument.",
                               filename, linenum, keyword);
                 if (*arg != '-' &&                  if (*arg != '-' &&
                     !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg))                      !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg))
                         fatal("%s line %d: Bad SSH2 cipher spec '%s'.",                          fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
Line 1743 
Line 1783 
                 break;                  break;
   
         case sMacs:          case sMacs:
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                         fatal("%s line %d: Missing argument.", filename, linenum);                          fatal("%s line %d: %s missing argument.",
                               filename, linenum, keyword);
                 if (*arg != '-' &&                  if (*arg != '-' &&
                     !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg))                      !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg))
                         fatal("%s line %d: Bad SSH2 mac spec '%s'.",                          fatal("%s line %d: Bad SSH2 mac spec '%s'.",
Line 1755 
Line 1796 
                 break;                  break;
   
         case sKexAlgorithms:          case sKexAlgorithms:
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                         fatal("%s line %d: Missing argument.",                          fatal("%s line %d: %s missing argument.",
                             filename, linenum);                              filename, linenum, keyword);
                 if (*arg != '-' &&                  if (*arg != '-' &&
                     !kex_names_valid(*arg == '+' || *arg == '^' ?                      !kex_names_valid(*arg == '+' || *arg == '^' ?
                     arg + 1 : arg))                      arg + 1 : arg))
Line 1773 
Line 1814 
                         fatal("%s line %d: too many subsystems defined.",                          fatal("%s line %d: too many subsystems defined.",
                             filename, linenum);                              filename, linenum);
                 }                  }
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                         fatal("%s line %d: Missing subsystem name.",                          fatal("%s line %d: %s missing argument.",
                             filename, linenum);                              filename, linenum, keyword);
                 if (!*activep) {                  if (!*activep) {
                         arg = strdelim(&cp);                          arg = argv_next(&ac, &av);
                         break;                          break;
                 }                  }
                 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' "
                                     filename, linenum, arg);                                      "already defined.", filename, linenum, arg);
                 options->subsystem_name[options->num_subsystems] = xstrdup(arg);                  options->subsystem_name[options->num_subsystems] = xstrdup(arg);
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 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);
Line 1795 
Line 1836 
                 /* Collect arguments (separate to executable) */                  /* Collect arguments (separate to executable) */
                 p = xstrdup(arg);                  p = xstrdup(arg);
                 len = strlen(p) + 1;                  len = strlen(p) + 1;
                 while ((arg = strdelim(&cp)) != NULL && *arg != '\0') {                  while ((arg = argv_next(&ac, &av)) != NULL) {
                         len += 1 + strlen(arg);                          len += 1 + strlen(arg);
                         p = xreallocarray(p, 1, len);                          p = xreallocarray(p, 1, len);
                         strlcat(p, " ", len);                          strlcat(p, " ", len);
Line 1806 
Line 1847 
                 break;                  break;
   
         case sMaxStartups:          case sMaxStartups:
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                         fatal("%s line %d: Missing MaxStartups spec.",                          fatal("%s line %d: %s missing argument.",
                             filename, linenum);                              filename, linenum, keyword);
                 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,
Line 1818 
Line 1859 
                             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.",                                  fatal("%s line %d: Invalid %s spec.",
                                     filename, linenum);                                      filename, linenum, keyword);
                 } else if (n != 1)                  } else if (n != 1)
                         fatal("%s line %d: Illegal MaxStartups spec.",                          fatal("%s line %d: Invalid %s spec.",
                             filename, linenum);                              filename, linenum, keyword);
                 else                  else
                         options->max_startups = options->max_startups_begin;                          options->max_startups = options->max_startups_begin;
                 break;                  break;
   
         case sPerSourceNetBlockSize:          case sPerSourceNetBlockSize:
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                         fatal("%s line %d: Missing PerSourceNetBlockSize spec.",                          fatal("%s line %d: %s missing argument.",
                             filename, linenum);                              filename, linenum, keyword);
                 switch (n = sscanf(arg, "%d:%d", &value, &value2)) {                  switch (n = sscanf(arg, "%d:%d", &value, &value2)) {
                 case 2:                  case 2:
                         if (value2 < 0 || value2 > 128)                          if (value2 < 0 || value2 > 128)
Line 1842 
Line 1883 
                                 n = -1;                                  n = -1;
                 }                  }
                 if (n != 1 && n != 2)                  if (n != 1 && n != 2)
                         fatal("%s line %d: Invalid PerSourceNetBlockSize"                          fatal("%s line %d: Invalid %s spec.",
                             " spec.", filename, linenum);                              filename, linenum, keyword);
                 if (*activep) {                  if (*activep) {
                         options->per_source_masklen_ipv4 = value;                          options->per_source_masklen_ipv4 = value;
                         options->per_source_masklen_ipv6 = value2;                          options->per_source_masklen_ipv6 = value2;
Line 1851 
Line 1892 
                 break;                  break;
   
         case sPerSourceMaxStartups:          case sPerSourceMaxStartups:
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                         fatal("%s line %d: Missing PerSourceMaxStartups spec.",                          fatal("%s line %d: %s missing argument.",
                             filename, linenum);                              filename, linenum, keyword);
                 if (strcmp(arg, "none") == 0) { /* no limit */                  if (strcmp(arg, "none") == 0) { /* no limit */
                         value = INT_MAX;                          value = INT_MAX;
                 } else {                  } else {
                         if ((errstr = atoi_err(arg, &value)) != NULL)                          if ((errstr = atoi_err(arg, &value)) != NULL)
                                 fatal("%s line %d: integer value %s.",                                  fatal("%s line %d: %s integer value %s.",
                                     filename, linenum, errstr);                                      filename, linenum, keyword, errstr);
                 }                  }
                 if (*activep)                  if (*activep)
                         options->per_source_max_startups = value;                          options->per_source_max_startups = value;
Line 1885 
Line 1926 
          * AuthorizedKeysFile   /etc/ssh_keys/%u           * AuthorizedKeysFile   /etc/ssh_keys/%u
          */           */
         case sAuthorizedKeysFile:          case sAuthorizedKeysFile:
                 if (*activep && options->num_authkeys_files == 0) {                  uvalue = options->num_authkeys_files;
                         while ((arg = strdelim(&cp)) && *arg != '\0') {                  while ((arg = argv_next(&ac, &av)) != NULL) {
                                 arg = tilde_expand_filename(arg, getuid());                          if (*arg == '\0') {
                                 opt_array_append(filename, linenum,                                  error("%s line %d: keyword %s empty argument",
                                     "AuthorizedKeysFile",                                      filename, linenum, keyword);
                                   goto out;
                           }
                           arg2 = tilde_expand_filename(arg, getuid());
                           if (*activep && uvalue == 0) {
                                   opt_array_append(filename, linenum, keyword,
                                     &options->authorized_keys_files,                                      &options->authorized_keys_files,
                                     &options->num_authkeys_files, arg);                                      &options->num_authkeys_files, arg2);
                                 free(arg);  
                         }                          }
                           free(arg2);
                 }                  }
                 return 0;                  break;
   
         case sAuthorizedPrincipalsFile:          case sAuthorizedPrincipalsFile:
                 charptr = &options->authorized_principals_file;                  charptr = &options->authorized_principals_file;
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                         fatal("%s line %d: missing file name.",                          fatal("%s line %d: %s missing argument.",
                             filename, linenum);                              filename, linenum, keyword);
                 if (*activep && *charptr == NULL) {                  if (*activep && *charptr == NULL) {
                         *charptr = tilde_expand_filename(arg, getuid());                          *charptr = tilde_expand_filename(arg, getuid());
                         /* increase optional counter */                          /* increase optional counter */
Line 1920 
Line 1966 
                 goto parse_int;                  goto parse_int;
   
         case sAcceptEnv:          case sAcceptEnv:
                 while ((arg = strdelim(&cp)) && *arg != '\0') {                  while ((arg = argv_next(&ac, &av)) != NULL) {
                         if (strchr(arg, '=') != NULL)                          if (*arg == '\0' || strchr(arg, '=') != NULL)
                                 fatal("%s line %d: Invalid environment name.",                                  fatal("%s line %d: Invalid environment name.",
                                     filename, linenum);                                      filename, linenum);
                         if (!*activep)                          if (!*activep)
                                 continue;                                  continue;
                         opt_array_append(filename, linenum, "AcceptEnv",                          opt_array_append(filename, linenum, keyword,
                             &options->accept_env, &options->num_accept_env,                              &options->accept_env, &options->num_accept_env,
                             arg);                              arg);
                 }                  }
Line 1934 
Line 1980 
   
         case sSetEnv:          case sSetEnv:
                 uvalue = options->num_setenv;                  uvalue = options->num_setenv;
                 while ((arg = strdelimw(&cp)) && *arg != '\0') {                  while ((arg = argv_next(&ac, &av)) != NULL) {
                         if (strchr(arg, '=') == NULL)                          if (*arg == '\0' || strchr(arg, '=') == NULL)
                                 fatal("%s line %d: Invalid environment.",                                  fatal("%s line %d: Invalid environment.",
                                     filename, linenum);                                      filename, linenum);
                         if (!*activep || uvalue != 0)                          if (!*activep || uvalue != 0)
                                 continue;                                  continue;
                         opt_array_append(filename, linenum, "SetEnv",                          opt_array_append(filename, linenum, keyword,
                             &options->setenv, &options->num_setenv, arg);                              &options->setenv, &options->num_setenv, arg);
                 }                  }
                 break;                  break;
   
         case sPermitTunnel:          case sPermitTunnel:
                 intptr = &options->permit_tun;                  intptr = &options->permit_tun;
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                         fatal("%s line %d: Missing yes/point-to-point/"                          fatal("%s line %d: %s missing argument.",
                             "ethernet/no argument.", filename, linenum);                              filename, linenum, keyword);
                 value = -1;                  value = -1;
                 for (i = 0; tunmode_desc[i].val != -1; i++)                  for (i = 0; tunmode_desc[i].val != -1; i++)
                         if (strcmp(tunmode_desc[i].text, arg) == 0) {                          if (strcmp(tunmode_desc[i].text, arg) == 0) {
Line 1958 
Line 2004 
                                 break;                                  break;
                         }                          }
                 if (value == -1)                  if (value == -1)
                         fatal("%s line %d: Bad yes/point-to-point/ethernet/"                          fatal("%s line %d: bad %s argument %s",
                             "no argument: %s", filename, linenum, arg);                              filename, linenum, keyword, arg);
                 if (*activep && *intptr == -1)                  if (*activep && *intptr == -1)
                         *intptr = value;                          *intptr = value;
                 break;                  break;
Line 1970 
Line 2016 
                             "command-line option");                              "command-line option");
                 }                  }
                 value = 0;                  value = 0;
                 while ((arg2 = strdelim(&cp)) != NULL && *arg2 != '\0') {                  while ((arg2 = argv_next(&ac, &av)) != NULL) {
                           if (*arg2 == '\0') {
                                   error("%s line %d: keyword %s empty argument",
                                       filename, linenum, keyword);
                                   goto out;
                           }
                         value++;                          value++;
                         found = 0;                          found = 0;
                         if (*arg2 != '/' && *arg2 != '~') {                          if (*arg2 != '/' && *arg2 != '~') {
Line 2010 
Line 2061 
                             filename, linenum, arg);                              filename, linenum, arg);
                         if ((r = glob(arg, 0, NULL, &gbuf)) != 0) {                          if ((r = glob(arg, 0, NULL, &gbuf)) != 0) {
                                 if (r != GLOB_NOMATCH) {                                  if (r != GLOB_NOMATCH) {
                                         fatal("%s line %d: include \"%s\" "                                          fatal("%s line %d: include \"%s\" glob "
                                             "glob failed", filename,                                              "failed", filename, linenum, arg);
                                             linenum, arg);  
                                 }                                  }
                                 /*                                  /*
                                  * If no entry matched then record a                                   * If no entry matched then record a
Line 2051 
Line 2101 
                         free(arg);                          free(arg);
                 }                  }
                 if (value == 0) {                  if (value == 0) {
                         fatal("%s line %d: Include missing filename argument",                          fatal("%s line %d: %s missing filename argument",
                             filename, linenum);                              filename, linenum, keyword);
                 }                  }
                 break;                  break;
   
Line 2060 
Line 2110 
                 if (cmdline)                  if (cmdline)
                         fatal("Match directive not supported as a command-line "                          fatal("Match directive not supported as a command-line "
                             "option");                              "option");
                 value = match_cfg_line(&cp, linenum,                  value = match_cfg_line(&str, linenum,
                     (*inc_flags & SSHCFG_NEVERMATCH ? NULL : connectinfo));                      (*inc_flags & SSHCFG_NEVERMATCH ? NULL : connectinfo));
                 if (value < 0)                  if (value < 0)
                         fatal("%s line %d: Bad Match condition", filename,                          fatal("%s line %d: Bad Match condition", filename,
                             linenum);                              linenum);
                 *activep = (*inc_flags & SSHCFG_NEVERMATCH) ? 0 : value;                  *activep = (*inc_flags & SSHCFG_NEVERMATCH) ? 0 : value;
                 /* The MATCH_ONLY is applicable only until the first match block */                  /*
                    * The MATCH_ONLY flag is applicable only until the first
                    * match block.
                    */
                 *inc_flags &= ~SSHCFG_MATCH_ONLY;                  *inc_flags &= ~SSHCFG_MATCH_ONLY;
                   /*
                    * If match_cfg_line() didn't consume all its arguments then
                    * arrange for the extra arguments check below to fail.
                    */
                   if (str == NULL || *str == '\0')
                           argv_consume(&ac);
                 break;                  break;
   
         case sPermitListen:          case sPermitListen:
Line 2079 
Line 2138 
                         uintptr = &options->num_permitted_opens;                          uintptr = &options->num_permitted_opens;
                         chararrayptr = &options->permitted_opens;                          chararrayptr = &options->permitted_opens;
                 }                  }
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                         fatal("%s line %d: missing %s specification",                          fatal("%s line %d: %s missing argument.",
                             filename, linenum, lookup_opcode_name(opcode));                              filename, linenum, keyword);
                 uvalue = *uintptr;      /* modified later */                  uvalue = *uintptr;      /* modified later */
                 if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) {                  if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) {
                         if (*activep && uvalue == 0) {                          if (*activep && uvalue == 0) {
Line 2093 
Line 2152 
                         }                          }
                         break;                          break;
                 }                  }
                 for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) {                  for (; arg != NULL && *arg != '\0'; arg = argv_next(&ac, &av)) {
                         if (opcode == sPermitListen &&                          if (opcode == sPermitListen &&
                             strchr(arg, ':') == NULL) {                              strchr(arg, ':') == NULL) {
                                 /*                                  /*
Line 2106 
Line 2165 
                                 ch = '\0';                                  ch = '\0';
                                 p = hpdelim2(&arg, &ch);                                  p = hpdelim2(&arg, &ch);
                                 if (p == NULL || ch == '/') {                                  if (p == NULL || ch == '/') {
                                         fatal("%s line %d: missing host in %s",                                          fatal("%s line %d: %s missing host",
                                             filename, linenum,                                              filename, linenum, keyword);
                                             lookup_opcode_name(opcode));  
                                 }                                  }
                                 p = cleanhostname(p);                                  p = cleanhostname(p);
                         }                          }
                         if (arg == NULL ||                          if (arg == NULL ||
                             ((port = permitopen_port(arg)) < 0)) {                              ((port = permitopen_port(arg)) < 0)) {
                                 fatal("%s line %d: bad port number in %s",                                  fatal("%s line %d: %s bad port number",
                                     filename, linenum,                                      filename, linenum, keyword);
                                     lookup_opcode_name(opcode));  
                         }                          }
                         if (*activep && uvalue == 0) {                          if (*activep && uvalue == 0) {
                                 opt_array_append(filename, linenum,                                  opt_array_append(filename, linenum, keyword,
                                     lookup_opcode_name(opcode),  
                                     chararrayptr, uintptr, arg2);                                      chararrayptr, uintptr, arg2);
                         }                          }
                         free(arg2);                          free(arg2);
Line 2128 
Line 2184 
                 break;                  break;
   
         case sForceCommand:          case sForceCommand:
                 if (cp == NULL || *cp == '\0')                  if (str == NULL || *str == '\0')
                         fatal("%.200s line %d: Missing argument.", filename,                          fatal("%s line %d: %s missing argument.",
                             linenum);                              filename, linenum, keyword);
                 len = strspn(cp, WHITESPACE);                  len = strspn(str, WHITESPACE);
                 if (*activep && options->adm_forced_command == NULL)                  if (*activep && options->adm_forced_command == NULL)
                         options->adm_forced_command = xstrdup(cp + len);                          options->adm_forced_command = xstrdup(str + len);
                 return 0;                  argv_consume(&ac);
                   break;
   
         case sChrootDirectory:          case sChrootDirectory:
                 charptr = &options->chroot_directory;                  charptr = &options->chroot_directory;
   
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                         fatal("%s line %d: missing file name.",                          fatal("%s line %d: %s missing argument.",
                             filename, linenum);                              filename, linenum, keyword);
                 if (*activep && *charptr == NULL)                  if (*activep && *charptr == NULL)
                         *charptr = xstrdup(arg);                          *charptr = xstrdup(arg);
                 break;                  break;
Line 2157 
Line 2214 
   
         case sSecurityKeyProvider:          case sSecurityKeyProvider:
                 charptr = &options->sk_provider;                  charptr = &options->sk_provider;
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                         fatal("%s line %d: missing file name.",                          fatal("%s line %d: %s missing argument.",
                             filename, linenum);                              filename, linenum, keyword);
                 if (*activep && *charptr == NULL) {                  if (*activep && *charptr == NULL) {
                         *charptr = strcasecmp(arg, "internal") == 0 ?                          *charptr = strcasecmp(arg, "internal") == 0 ?
                             xstrdup(arg) : derelativise_path(arg);                              xstrdup(arg) : derelativise_path(arg);
Line 2171 
Line 2228 
                 break;                  break;
   
         case sIPQoS:          case sIPQoS:
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                   if (!arg || *arg == '\0')
                           fatal("%s line %d: %s missing argument.",
                               filename, linenum, keyword);
                 if ((value = parse_ipqos(arg)) == -1)                  if ((value = parse_ipqos(arg)) == -1)
                         fatal("%s line %d: Bad IPQoS value: %s",                          fatal("%s line %d: Bad %s value: %s",
                             filename, linenum, arg);                              filename, linenum, keyword, arg);
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if (arg == NULL)                  if (arg == NULL)
                         value2 = value;                          value2 = value;
                 else if ((value2 = parse_ipqos(arg)) == -1)                  else if ((value2 = parse_ipqos(arg)) == -1)
                         fatal("%s line %d: Bad IPQoS value: %s",                          fatal("%s line %d: Bad %s value: %s",
                             filename, linenum, arg);                              filename, linenum, keyword, arg);
                 if (*activep) {                  if (*activep) {
                         options->ip_qos_interactive = value;                          options->ip_qos_interactive = value;
                         options->ip_qos_bulk = value2;                          options->ip_qos_bulk = value2;
Line 2188 
Line 2248 
                 break;                  break;
   
         case sVersionAddendum:          case sVersionAddendum:
                 if (cp == NULL || *cp == '\0')                  if (str == NULL || *str == '\0')
                         fatal("%.200s line %d: Missing argument.", filename,                          fatal("%s line %d: %s missing argument.",
                             linenum);                              filename, linenum, keyword);
                 len = strspn(cp, WHITESPACE);                  len = strspn(str, WHITESPACE);
                   if (strchr(str + len, '\r') != NULL) {
                           fatal("%.200s line %d: Invalid %s argument",
                               filename, linenum, keyword);
                   }
                   if ((arg = strchr(line, '#')) != NULL) {
                           *arg = '\0';
                           rtrim(line);
                   }
                 if (*activep && options->version_addendum == NULL) {                  if (*activep && options->version_addendum == NULL) {
                         if (strcasecmp(cp + len, "none") == 0)                          if (strcasecmp(str + len, "none") == 0)
                                 options->version_addendum = xstrdup("");                                  options->version_addendum = xstrdup("");
                         else if (strchr(cp + len, '\r') != NULL)  
                                 fatal("%.200s line %d: Invalid argument",  
                                     filename, linenum);  
                         else                          else
                                 options->version_addendum = xstrdup(cp + len);                                  options->version_addendum = xstrdup(str + len);
                 }                  }
                 return 0;                  argv_consume(&ac);
                   break;
   
         case sAuthorizedKeysCommand:          case sAuthorizedKeysCommand:
                 if (cp == NULL)                  charptr = &options->authorized_keys_command;
                         fatal("%.200s line %d: Missing argument.", filename,   parse_command:
                             linenum);                  len = strspn(str, WHITESPACE);
                 len = strspn(cp, WHITESPACE);                  if (str[len] != '/' && strcasecmp(str + len, "none") != 0) {
                 if (*activep && options->authorized_keys_command == NULL) {                          fatal("%.200s line %d: %s must be an absolute path",
                         if (cp[len] != '/' && strcasecmp(cp + len, "none") != 0)                              filename, linenum, keyword);
                                 fatal("%.200s line %d: AuthorizedKeysCommand "  
                                     "must be an absolute path",  
                                     filename, linenum);  
                         options->authorized_keys_command = xstrdup(cp + len);  
                 }                  }
                 return 0;                  if (*activep && options->authorized_keys_command == NULL)
                           *charptr = xstrdup(str + len);
                   argv_consume(&ac);
                   break;
   
         case sAuthorizedKeysCommandUser:          case sAuthorizedKeysCommandUser:
                 charptr = &options->authorized_keys_command_user;                  charptr = &options->authorized_keys_command_user;
    parse_localuser:
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if (!arg || *arg == '\0')                  if (!arg || *arg == '\0') {
                         fatal("%s line %d: missing AuthorizedKeysCommandUser "                          fatal("%s line %d: missing %s argument.",
                             "argument.", filename, linenum);                              filename, linenum, keyword);
                   }
                 if (*activep && *charptr == NULL)                  if (*activep && *charptr == NULL)
                         *charptr = xstrdup(arg);                          *charptr = xstrdup(arg);
                 break;                  break;
   
         case sAuthorizedPrincipalsCommand:          case sAuthorizedPrincipalsCommand:
                 if (cp == NULL)                  charptr = &options->authorized_principals_command;
                         fatal("%.200s line %d: Missing argument.", filename,                  goto parse_command;
                             linenum);  
                 len = strspn(cp, WHITESPACE);  
                 if (*activep &&  
                     options->authorized_principals_command == NULL) {  
                         if (cp[len] != '/' && strcasecmp(cp + len, "none") != 0)  
                                 fatal("%.200s line %d: "  
                                     "AuthorizedPrincipalsCommand must be "  
                                     "an absolute path", filename, linenum);  
                         options->authorized_principals_command =  
                             xstrdup(cp + len);  
                 }  
                 return 0;  
   
         case sAuthorizedPrincipalsCommandUser:          case sAuthorizedPrincipalsCommandUser:
                 charptr = &options->authorized_principals_command_user;                  charptr = &options->authorized_principals_command_user;
                   goto parse_localuser;
   
                 arg = strdelim(&cp);  
                 if (!arg || *arg == '\0')  
                         fatal("%s line %d: missing "  
                             "AuthorizedPrincipalsCommandUser argument.",  
                             filename, linenum);  
                 if (*activep && *charptr == NULL)  
                         *charptr = xstrdup(arg);  
                 break;  
   
         case sAuthenticationMethods:          case sAuthenticationMethods:
                 if (options->num_auth_methods == 0) {                  found = options->num_auth_methods == 0;
                         value = 0; /* seen "any" pseudo-method */                  value = 0; /* seen "any" pseudo-method */
                         value2 = 0; /* successfully parsed any method */                  value2 = 0; /* successfully parsed any method */
                         while ((arg = strdelim(&cp)) && *arg != '\0') {                  while ((arg = argv_next(&ac, &av)) != NULL) {
                                 if (strcmp(arg, "any") == 0) {                          if (strcmp(arg, "any") == 0) {
                                         if (options->num_auth_methods > 0) {                                  if (options->num_auth_methods > 0) {
                                                 fatal("%s line %d: \"any\" "                                          fatal("%s line %d: \"any\" must "
                                                     "must appear alone in "                                              "appear alone in %s",
                                                     "AuthenticationMethods",                                              filename, linenum, keyword);
                                                     filename, linenum);  
                                         }  
                                         value = 1;  
                                 } else if (value) {  
                                         fatal("%s line %d: \"any\" must appear "  
                                             "alone in AuthenticationMethods",  
                                             filename, linenum);  
                                 } else if (auth2_methods_valid(arg, 0) != 0) {  
                                         fatal("%s line %d: invalid "  
                                             "authentication method list.",  
                                             filename, linenum);  
                                 }                                  }
                                 value2 = 1;                                  value = 1;
                                 if (!*activep)                          } else if (value) {
                                         continue;                                  fatal("%s line %d: \"any\" must appear "
                                 opt_array_append(filename, linenum,                                      "alone in %s", filename, linenum, keyword);
                                     "AuthenticationMethods",                          } else if (auth2_methods_valid(arg, 0) != 0) {
                                     &options->auth_methods,                                  fatal("%s line %d: invalid %s method list.",
                                     &options->num_auth_methods, arg);                                      filename, linenum, keyword);
                         }                          }
                         if (value2 == 0) {                          value2 = 1;
                                 fatal("%s line %d: no AuthenticationMethods "                          if (!found || !*activep)
                                     "specified", filename, linenum);                                  continue;
                         }                          opt_array_append(filename, linenum, keyword,
                               &options->auth_methods,
                               &options->num_auth_methods, arg);
                 }                  }
                 return 0;                  if (value2 == 0) {
                           fatal("%s line %d: no %s specified",
                               filename, linenum, keyword);
                   }
                   break;
   
         case sStreamLocalBindMask:          case sStreamLocalBindMask:
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                         fatal("%s line %d: missing StreamLocalBindMask "                          fatal("%s line %d: %s missing argument.",
                             "argument.", filename, linenum);                              filename, linenum, keyword);
                 /* Parse mode in octal format */                  /* Parse mode in octal format */
                 value = strtol(arg, &p, 8);                  value = strtol(arg, &p, 8);
                 if (arg == p || value < 0 || value > 0777)                  if (arg == p || value < 0 || value > 0777)
                         fatal("%s line %d: Bad mask.", filename, linenum);                          fatal("%s line %d: Invalid %s.",
                               filename, linenum, keyword);
                 if (*activep)                  if (*activep)
                         options->fwd_opts.streamlocal_bind_mask = (mode_t)value;                          options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
                 break;                  break;
Line 2311 
Line 2353 
                 goto parse_flag;                  goto parse_flag;
   
         case sFingerprintHash:          case sFingerprintHash:
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                         fatal("%.200s line %d: Missing argument.",                          fatal("%s line %d: %s missing argument.",
                             filename, linenum);                              filename, linenum, keyword);
                 if ((value = ssh_digest_alg_by_name(arg)) == -1)                  if ((value = ssh_digest_alg_by_name(arg)) == -1)
                         fatal("%.200s line %d: Invalid hash algorithm \"%s\".",                          fatal("%.200s line %d: Invalid %s algorithm \"%s\".",
                             filename, linenum, arg);                              filename, linenum, keyword, arg);
                 if (*activep)                  if (*activep)
                         options->fingerprint_hash = value;                          options->fingerprint_hash = value;
                 break;                  break;
Line 2328 
Line 2370 
   
         case sRDomain:          case sRDomain:
                 charptr = &options->routing_domain;                  charptr = &options->routing_domain;
                 arg = strdelim(&cp);                  arg = argv_next(&ac, &av);
                 if (!arg || *arg == '\0')                  if (!arg || *arg == '\0')
                         fatal("%.200s line %d: Missing argument.",                          fatal("%s line %d: %s missing argument.",
                             filename, linenum);                              filename, linenum, keyword);
                 if (strcasecmp(arg, "none") != 0 && strcmp(arg, "%D") != 0 &&                  if (strcasecmp(arg, "none") != 0 && strcmp(arg, "%D") != 0 &&
                     !valid_rdomain(arg))                      !valid_rdomain(arg))
                         fatal("%s line %d: bad routing domain",                          fatal("%s line %d: invalid routing domain",
                             filename, linenum);                              filename, linenum);
                 if (*activep && *charptr == NULL)                  if (*activep && *charptr == NULL)
                         *charptr = xstrdup(arg);                          *charptr = xstrdup(arg);
Line 2346 
Line 2388 
                 do_log2(opcode == sIgnore ?                  do_log2(opcode == sIgnore ?
                     SYSLOG_LEVEL_DEBUG2 : SYSLOG_LEVEL_INFO,                      SYSLOG_LEVEL_DEBUG2 : SYSLOG_LEVEL_INFO,
                     "%s line %d: %s option %s", filename, linenum,                      "%s line %d: %s option %s", filename, linenum,
                     opcode == sUnsupported ? "Unsupported" : "Deprecated", arg);                      opcode == sUnsupported ? "Unsupported" : "Deprecated",
                 while (arg)                      keyword);
                     arg = strdelim(&cp);                  argv_consume(&ac);
                 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, keyword, opcode);
         }          }
         if ((arg = strdelim(&cp)) != NULL && *arg != '\0')          /* Check that there is no garbage at end of line. */
                 fatal("%s line %d: garbage at end of line; \"%.200s\".",          if (ac > 0) {
                     filename, linenum, arg);                  error("%.200s line %d: keyword %s extra arguments "
         return 0;                      "at end of line", filename, linenum, keyword);
                   goto out;
           }
   
           /* success */
           ret = 0;
    out:
           argv_free(oav, oac);
           return ret;
 }  }
   
 int  int
Line 2397 
Line 2447 
         while (getline(&line, &linesize, f) != -1) {          while (getline(&line, &linesize, f) != -1) {
                 lineno++;                  lineno++;
                 /*                  /*
                  * Trim out comments and strip whitespace                   * Strip whitespace
                  * NB - preserve newlines, they are needed to reproduce                   * NB - preserve newlines, they are needed to reproduce
                  * line numbers later for error messages                   * line numbers later for error messages
                  */                   */
                 if ((cp = strchr(line, '#')) != NULL)  
                         memcpy(cp, "\n", 2);  
                 cp = line + strspn(line, " \t\r");                  cp = line + strspn(line, " \t\r");
                 if ((r = sshbuf_put(conf, cp, strlen(cp))) != 0)                  if ((r = sshbuf_put(conf, cp, strlen(cp))) != 0)
                         fatal_fr(r, "sshbuf_put");                          fatal_fr(r, "sshbuf_put");

Legend:
Removed from v.1.379  
changed lines
  Added in v.1.380