diff options
Diffstat (limited to 'crypto/openssh/servconf.c')
-rw-r--r-- | crypto/openssh/servconf.c | 289 |
1 files changed, 153 insertions, 136 deletions
diff --git a/crypto/openssh/servconf.c b/crypto/openssh/servconf.c index 96761e7..1d88bbf 100644 --- a/crypto/openssh/servconf.c +++ b/crypto/openssh/servconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: servconf.c,v 1.213 2010/11/13 23:27:50 djm Exp $ */ +/* $OpenBSD: servconf.c,v 1.222 2011/06/22 21:57:01 djm Exp $ */ /* $FreeBSD$ */ /* * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland @@ -129,8 +129,7 @@ initialize_server_options(ServerOptions *options) options->use_dns = -1; options->client_alive_interval = -1; options->client_alive_count_max = -1; - options->authorized_keys_file = NULL; - options->authorized_keys_file2 = NULL; + options->num_authkeys_files = 0; options->num_accept_env = 0; options->permit_tun = -1; options->num_permitted_opens = -1; @@ -273,15 +272,12 @@ fill_default_server_options(ServerOptions *options) options->client_alive_interval = 0; if (options->client_alive_count_max == -1) options->client_alive_count_max = 3; - if (options->authorized_keys_file2 == NULL) { - /* authorized_keys_file2 falls back to authorized_keys_file */ - if (options->authorized_keys_file != NULL) - options->authorized_keys_file2 = xstrdup(options->authorized_keys_file); - else - options->authorized_keys_file2 = xstrdup(_PATH_SSH_USER_PERMITTED_KEYS2); + if (options->num_authkeys_files == 0) { + options->authorized_keys_files[options->num_authkeys_files++] = + xstrdup(_PATH_SSH_USER_PERMITTED_KEYS); + options->authorized_keys_files[options->num_authkeys_files++] = + xstrdup(_PATH_SSH_USER_PERMITTED_KEYS2); } - if (options->authorized_keys_file == NULL) - options->authorized_keys_file = xstrdup(_PATH_SSH_USER_PERMITTED_KEYS); if (options->permit_tun == -1) options->permit_tun = SSH_TUNMODE_NO; if (options->zero_knowledge_password_authentication == -1) @@ -324,7 +320,7 @@ fill_default_server_options(ServerOptions *options) /* Turn privilege separation on by default */ if (use_privsep == -1) - use_privsep = 1; + use_privsep = PRIVSEP_ON; #ifndef HAVE_MMAP if (use_privsep && options->compression == 1) { @@ -361,7 +357,7 @@ typedef enum { sMaxStartups, sMaxAuthTries, sMaxSessions, sBanner, sUseDNS, sHostbasedAuthentication, sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, - sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, + sClientAliveCountMax, sAuthorizedKeysFile, sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel, sMatch, sPermitOpen, sForceCommand, sChrootDirectory, sUsePrivilegeSeparation, sAllowAgentForwarding, @@ -483,7 +479,7 @@ static struct { { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL }, { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL }, { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL }, - { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_ALL }, + { "authorizedkeysfile2", sDeprecated, SSHCFG_ALL }, { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL}, { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL }, { "permittunnel", sPermitTunnel, SSHCFG_ALL }, @@ -727,6 +723,43 @@ match_cfg_line(char **condition, int line, const char *user, const char *host, #define WHITESPACE " \t\r\n" +/* Multistate option parsing */ +struct multistate { + char *key; + int value; +}; +static const struct multistate multistate_addressfamily[] = { + { "inet", AF_INET }, + { "inet6", AF_INET6 }, + { "any", AF_UNSPEC }, + { NULL, -1 } +}; +static const struct multistate multistate_permitrootlogin[] = { + { "without-password", PERMIT_NO_PASSWD }, + { "forced-commands-only", PERMIT_FORCED_ONLY }, + { "yes", PERMIT_YES }, + { "no", PERMIT_NO }, + { NULL, -1 } +}; +static const struct multistate multistate_compression[] = { + { "delayed", COMP_DELAYED }, + { "yes", COMP_ZLIB }, + { "no", COMP_NONE }, + { NULL, -1 } +}; +static const struct multistate multistate_gatewayports[] = { + { "clientspecified", 2 }, + { "yes", 1 }, + { "no", 0 }, + { NULL, -1 } +}; +static const struct multistate multistate_privsep[] = { + { "sandbox", PRIVSEP_SANDBOX }, + { "yes", PRIVSEP_ON }, + { "no", PRIVSEP_OFF }, + { NULL, -1 } +}; + int process_server_config_line(ServerOptions *options, char *line, const char *filename, int linenum, int *activep, const char *user, @@ -740,6 +773,7 @@ process_server_config_line(ServerOptions *options, char *line, int port; u_int i, flags = 0; size_t len; + const struct multistate *multistate_ptr; cp = line; if ((arg = strdelim(&cp)) == NULL) @@ -855,24 +889,27 @@ process_server_config_line(ServerOptions *options, char *line, break; case sAddressFamily: + intptr = &options->address_family; + multistate_ptr = multistate_addressfamily; + if (options->listen_addrs != NULL) + fatal("%s line %d: address family must be specified " + "before ListenAddress.", filename, linenum); + parse_multistate: arg = strdelim(&cp); if (!arg || *arg == '\0') - fatal("%s line %d: missing address family.", + fatal("%s line %d: missing argument.", filename, linenum); - intptr = &options->address_family; - if (options->listen_addrs != NULL) - fatal("%s line %d: address family must be specified before " - "ListenAddress.", filename, linenum); - if (strcasecmp(arg, "inet") == 0) - value = AF_INET; - else if (strcasecmp(arg, "inet6") == 0) - value = AF_INET6; - else if (strcasecmp(arg, "any") == 0) - value = AF_UNSPEC; - else - fatal("%s line %d: unsupported address family \"%s\".", + value = -1; + for (i = 0; multistate_ptr[i].key != NULL; i++) { + if (strcasecmp(arg, multistate_ptr[i].key) == 0) { + value = multistate_ptr[i].value; + break; + } + } + if (value == -1) + fatal("%s line %d: unsupported option \"%s\".", filename, linenum, arg); - if (*intptr == -1) + if (*activep && *intptr == -1) *intptr = value; break; @@ -911,27 +948,8 @@ process_server_config_line(ServerOptions *options, char *line, case sPermitRootLogin: intptr = &options->permit_root_login; - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing yes/" - "without-password/forced-commands-only/no " - "argument.", filename, linenum); - value = 0; /* silence compiler */ - if (strcmp(arg, "without-password") == 0) - value = PERMIT_NO_PASSWD; - else if (strcmp(arg, "forced-commands-only") == 0) - value = PERMIT_FORCED_ONLY; - else if (strcmp(arg, "yes") == 0) - value = PERMIT_YES; - else if (strcmp(arg, "no") == 0) - value = PERMIT_NO; - else - fatal("%s line %d: Bad yes/" - "without-password/forced-commands-only/no " - "argument: %s", filename, linenum, arg); - if (*activep && *intptr == -1) - *intptr = value; - break; + multistate_ptr = multistate_permitrootlogin; + goto parse_multistate; case sIgnoreRhosts: intptr = &options->ignore_rhosts; @@ -1062,43 +1080,13 @@ process_server_config_line(ServerOptions *options, char *line, case sCompression: intptr = &options->compression; - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing yes/no/delayed " - "argument.", filename, linenum); - value = 0; /* silence compiler */ - if (strcmp(arg, "delayed") == 0) - value = COMP_DELAYED; - else if (strcmp(arg, "yes") == 0) - value = COMP_ZLIB; - else if (strcmp(arg, "no") == 0) - value = COMP_NONE; - else - fatal("%s line %d: Bad yes/no/delayed " - "argument: %s", filename, linenum, arg); - if (*intptr == -1) - *intptr = value; - break; + multistate_ptr = multistate_compression; + goto parse_multistate; case sGatewayPorts: intptr = &options->gateway_ports; - arg = strdelim(&cp); - if (!arg || *arg == '\0') - fatal("%s line %d: missing yes/no/clientspecified " - "argument.", filename, linenum); - value = 0; /* silence compiler */ - if (strcmp(arg, "clientspecified") == 0) - value = 2; - else if (strcmp(arg, "yes") == 0) - value = 1; - else if (strcmp(arg, "no") == 0) - value = 0; - else - fatal("%s line %d: Bad yes/no/clientspecified " - "argument: %s", filename, linenum, arg); - if (*activep && *intptr == -1) - *intptr = value; - break; + multistate_ptr = multistate_gatewayports; + goto parse_multistate; case sUseDNS: intptr = &options->use_dns; @@ -1136,7 +1124,8 @@ process_server_config_line(ServerOptions *options, char *line, case sUsePrivilegeSeparation: intptr = &use_privsep; - goto parse_flag; + multistate_ptr = multistate_privsep; + goto parse_multistate; case sAllowUsers: while ((arg = strdelim(&cp)) && *arg != '\0') { @@ -1302,14 +1291,22 @@ process_server_config_line(ServerOptions *options, char *line, * AuthorizedKeysFile /etc/ssh_keys/%u */ case sAuthorizedKeysFile: - charptr = &options->authorized_keys_file; - goto parse_tilde_filename; - case sAuthorizedKeysFile2: - charptr = &options->authorized_keys_file2; - goto parse_tilde_filename; + if (*activep && options->num_authkeys_files == 0) { + while ((arg = strdelim(&cp)) && *arg != '\0') { + if (options->num_authkeys_files >= + MAX_AUTHKEYS_FILES) + fatal("%s line %d: " + "too many authorized keys files.", + filename, linenum); + options->authorized_keys_files[ + options->num_authkeys_files++] = + tilde_expand_filename(arg, getuid()); + } + } + return 0; + case sAuthorizedPrincipalsFile: charptr = &options->authorized_principals_file; - parse_tilde_filename: arg = strdelim(&cp); if (!arg || *arg == '\0') fatal("%s line %d: missing file name.", @@ -1553,6 +1550,12 @@ parse_server_match_config(ServerOptions *options, const char *user, dst->n = src->n; \ } \ } while(0) +#define M_CP_STRARRAYOPT(n, num_n) do {\ + if (src->num_n != 0) { \ + for (dst->num_n = 0; dst->num_n < src->num_n; dst->num_n++) \ + dst->n[dst->num_n] = xstrdup(src->n[dst->num_n]); \ + } \ +} while(0) /* * Copy any supported values that are set. @@ -1588,20 +1591,23 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) M_CP_INTOPT(ip_qos_interactive); M_CP_INTOPT(ip_qos_bulk); - M_CP_STROPT(banner); + /* See comment in servconf.h */ + COPY_MATCH_STRING_OPTS(); + + /* + * The only things that should be below this point are string options + * which are only used after authentication. + */ if (preauth) return; + M_CP_STROPT(adm_forced_command); M_CP_STROPT(chroot_directory); - M_CP_STROPT(trusted_user_ca_keys); - M_CP_STROPT(revoked_keys_file); - M_CP_STROPT(authorized_keys_file); - M_CP_STROPT(authorized_keys_file2); - M_CP_STROPT(authorized_principals_file); } #undef M_CP_INTOPT #undef M_CP_STROPT +#undef M_CP_STRARRAYOPT void parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, @@ -1627,31 +1633,34 @@ parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, } static const char * -fmt_intarg(ServerOpCodes code, int val) +fmt_multistate_int(int val, const struct multistate *m) { - if (code == sAddressFamily) { - switch (val) { - case AF_INET: - return "inet"; - case AF_INET6: - return "inet6"; - case AF_UNSPEC: - return "any"; - default: - return "UNKNOWN"; - } - } - if (code == sPermitRootLogin) { - switch (val) { - case PERMIT_NO_PASSWD: - return "without-password"; - case PERMIT_FORCED_ONLY: - return "forced-commands-only"; - case PERMIT_YES: - return "yes"; - } + u_int i; + + for (i = 0; m[i].key != NULL; i++) { + if (m[i].value == val) + return m[i].key; } - if (code == sProtocol) { + return "UNKNOWN"; +} + +static const char * +fmt_intarg(ServerOpCodes code, int val) +{ + if (val == -1) + return "unset"; + switch (code) { + case sAddressFamily: + return fmt_multistate_int(val, multistate_addressfamily); + case sPermitRootLogin: + return fmt_multistate_int(val, multistate_permitrootlogin); + case sGatewayPorts: + return fmt_multistate_int(val, multistate_gatewayports); + case sCompression: + return fmt_multistate_int(val, multistate_compression); + case sUsePrivilegeSeparation: + return fmt_multistate_int(val, multistate_privsep); + case sProtocol: switch (val) { case SSH_PROTO_1: return "1"; @@ -1662,20 +1671,16 @@ fmt_intarg(ServerOpCodes code, int val) default: return "UNKNOWN"; } + default: + switch (val) { + case 0: + return "no"; + case 1: + return "yes"; + default: + return "UNKNOWN"; + } } - if (code == sGatewayPorts && val == 2) - return "clientspecified"; - if (code == sCompression && val == COMP_DELAYED) - return "delayed"; - switch (val) { - case -1: - return "unset"; - case 0: - return "no"; - case 1: - return "yes"; - } - return "UNKNOWN"; } static const char * @@ -1715,7 +1720,18 @@ dump_cfg_strarray(ServerOpCodes code, u_int count, char **vals) u_int i; for (i = 0; i < count; i++) - printf("%s %s\n", lookup_opcode_name(code), vals[i]); + printf("%s %s\n", lookup_opcode_name(code), vals[i]); +} + +static void +dump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals) +{ + u_int i; + + printf("%s", lookup_opcode_name(code)); + for (i = 0; i < count; i++) + printf(" %s", vals[i]); + printf("\n"); } void @@ -1813,8 +1829,6 @@ dump_config(ServerOptions *o) dump_cfg_string(sCiphers, o->ciphers); dump_cfg_string(sMacs, o->macs); dump_cfg_string(sBanner, o->banner); - dump_cfg_string(sAuthorizedKeysFile, o->authorized_keys_file); - dump_cfg_string(sAuthorizedKeysFile2, o->authorized_keys_file2); dump_cfg_string(sForceCommand, o->adm_forced_command); dump_cfg_string(sChrootDirectory, o->chroot_directory); dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys); @@ -1827,6 +1841,8 @@ dump_config(ServerOptions *o) dump_cfg_string(sLogFacility, log_facility_name(o->log_facility)); /* string array arguments */ + dump_cfg_strarray_oneline(sAuthorizedKeysFile, o->num_authkeys_files, + o->authorized_keys_files); dump_cfg_strarray(sHostKeyFile, o->num_host_key_files, o->host_key_files); dump_cfg_strarray(sHostKeyFile, o->num_host_cert_files, @@ -1852,7 +1868,8 @@ dump_config(ServerOptions *o) } dump_cfg_string(sPermitTunnel, s); - printf("ipqos 0x%02x 0x%02x\n", o->ip_qos_interactive, o->ip_qos_bulk); + printf("ipqos %s ", iptos2str(o->ip_qos_interactive)); + printf("%s\n", iptos2str(o->ip_qos_bulk)); channel_print_adm_permitted_opens(); } |