summaryrefslogtreecommitdiff
path: root/servconf.c
diff options
context:
space:
mode:
Diffstat (limited to 'servconf.c')
-rw-r--r--servconf.c289
1 files changed, 153 insertions, 136 deletions
diff --git a/servconf.c b/servconf.c
index b08772601..9bff59de3 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: servconf.c,v 1.213 2010/11/13 23:27:50 djm Exp $ */ 1/* $OpenBSD: servconf.c,v 1.222 2011/06/22 21:57:01 djm Exp $ */
2/* 2/*
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved 4 * All rights reserved
@@ -129,8 +129,7 @@ initialize_server_options(ServerOptions *options)
129 options->use_dns = -1; 129 options->use_dns = -1;
130 options->client_alive_interval = -1; 130 options->client_alive_interval = -1;
131 options->client_alive_count_max = -1; 131 options->client_alive_count_max = -1;
132 options->authorized_keys_file = NULL; 132 options->num_authkeys_files = 0;
133 options->authorized_keys_file2 = NULL;
134 options->num_accept_env = 0; 133 options->num_accept_env = 0;
135 options->permit_tun = -1; 134 options->permit_tun = -1;
136 options->num_permitted_opens = -1; 135 options->num_permitted_opens = -1;
@@ -273,15 +272,12 @@ fill_default_server_options(ServerOptions *options)
273 options->client_alive_interval = 0; 272 options->client_alive_interval = 0;
274 if (options->client_alive_count_max == -1) 273 if (options->client_alive_count_max == -1)
275 options->client_alive_count_max = 3; 274 options->client_alive_count_max = 3;
276 if (options->authorized_keys_file2 == NULL) { 275 if (options->num_authkeys_files == 0) {
277 /* authorized_keys_file2 falls back to authorized_keys_file */ 276 options->authorized_keys_files[options->num_authkeys_files++] =
278 if (options->authorized_keys_file != NULL) 277 xstrdup(_PATH_SSH_USER_PERMITTED_KEYS);
279 options->authorized_keys_file2 = xstrdup(options->authorized_keys_file); 278 options->authorized_keys_files[options->num_authkeys_files++] =
280 else 279 xstrdup(_PATH_SSH_USER_PERMITTED_KEYS2);
281 options->authorized_keys_file2 = xstrdup(_PATH_SSH_USER_PERMITTED_KEYS2);
282 } 280 }
283 if (options->authorized_keys_file == NULL)
284 options->authorized_keys_file = xstrdup(_PATH_SSH_USER_PERMITTED_KEYS);
285 if (options->permit_tun == -1) 281 if (options->permit_tun == -1)
286 options->permit_tun = SSH_TUNMODE_NO; 282 options->permit_tun = SSH_TUNMODE_NO;
287 if (options->zero_knowledge_password_authentication == -1) 283 if (options->zero_knowledge_password_authentication == -1)
@@ -293,7 +289,7 @@ fill_default_server_options(ServerOptions *options)
293 289
294 /* Turn privilege separation on by default */ 290 /* Turn privilege separation on by default */
295 if (use_privsep == -1) 291 if (use_privsep == -1)
296 use_privsep = 1; 292 use_privsep = PRIVSEP_ON;
297 293
298#ifndef HAVE_MMAP 294#ifndef HAVE_MMAP
299 if (use_privsep && options->compression == 1) { 295 if (use_privsep && options->compression == 1) {
@@ -330,7 +326,7 @@ typedef enum {
330 sMaxStartups, sMaxAuthTries, sMaxSessions, 326 sMaxStartups, sMaxAuthTries, sMaxSessions,
331 sBanner, sUseDNS, sHostbasedAuthentication, 327 sBanner, sUseDNS, sHostbasedAuthentication,
332 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, 328 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
333 sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, 329 sClientAliveCountMax, sAuthorizedKeysFile,
334 sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, 330 sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
335 sGssKeyEx, sGssStoreRekey, 331 sGssKeyEx, sGssStoreRekey,
336 sAcceptEnv, sPermitTunnel, 332 sAcceptEnv, sPermitTunnel,
@@ -459,7 +455,7 @@ static struct {
459 { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL }, 455 { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL },
460 { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL }, 456 { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL },
461 { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL }, 457 { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL },
462 { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_ALL }, 458 { "authorizedkeysfile2", sDeprecated, SSHCFG_ALL },
463 { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL}, 459 { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL},
464 { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL }, 460 { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL },
465 { "permittunnel", sPermitTunnel, SSHCFG_ALL }, 461 { "permittunnel", sPermitTunnel, SSHCFG_ALL },
@@ -696,6 +692,43 @@ match_cfg_line(char **condition, int line, const char *user, const char *host,
696 692
697#define WHITESPACE " \t\r\n" 693#define WHITESPACE " \t\r\n"
698 694
695/* Multistate option parsing */
696struct multistate {
697 char *key;
698 int value;
699};
700static const struct multistate multistate_addressfamily[] = {
701 { "inet", AF_INET },
702 { "inet6", AF_INET6 },
703 { "any", AF_UNSPEC },
704 { NULL, -1 }
705};
706static const struct multistate multistate_permitrootlogin[] = {
707 { "without-password", PERMIT_NO_PASSWD },
708 { "forced-commands-only", PERMIT_FORCED_ONLY },
709 { "yes", PERMIT_YES },
710 { "no", PERMIT_NO },
711 { NULL, -1 }
712};
713static const struct multistate multistate_compression[] = {
714 { "delayed", COMP_DELAYED },
715 { "yes", COMP_ZLIB },
716 { "no", COMP_NONE },
717 { NULL, -1 }
718};
719static const struct multistate multistate_gatewayports[] = {
720 { "clientspecified", 2 },
721 { "yes", 1 },
722 { "no", 0 },
723 { NULL, -1 }
724};
725static const struct multistate multistate_privsep[] = {
726 { "sandbox", PRIVSEP_SANDBOX },
727 { "yes", PRIVSEP_ON },
728 { "no", PRIVSEP_OFF },
729 { NULL, -1 }
730};
731
699int 732int
700process_server_config_line(ServerOptions *options, char *line, 733process_server_config_line(ServerOptions *options, char *line,
701 const char *filename, int linenum, int *activep, const char *user, 734 const char *filename, int linenum, int *activep, const char *user,
@@ -709,6 +742,7 @@ process_server_config_line(ServerOptions *options, char *line,
709 int port; 742 int port;
710 u_int i, flags = 0; 743 u_int i, flags = 0;
711 size_t len; 744 size_t len;
745 const struct multistate *multistate_ptr;
712 746
713 cp = line; 747 cp = line;
714 if ((arg = strdelim(&cp)) == NULL) 748 if ((arg = strdelim(&cp)) == NULL)
@@ -824,24 +858,27 @@ process_server_config_line(ServerOptions *options, char *line,
824 break; 858 break;
825 859
826 case sAddressFamily: 860 case sAddressFamily:
861 intptr = &options->address_family;
862 multistate_ptr = multistate_addressfamily;
863 if (options->listen_addrs != NULL)
864 fatal("%s line %d: address family must be specified "
865 "before ListenAddress.", filename, linenum);
866 parse_multistate:
827 arg = strdelim(&cp); 867 arg = strdelim(&cp);
828 if (!arg || *arg == '\0') 868 if (!arg || *arg == '\0')
829 fatal("%s line %d: missing address family.", 869 fatal("%s line %d: missing argument.",
830 filename, linenum); 870 filename, linenum);
831 intptr = &options->address_family; 871 value = -1;
832 if (options->listen_addrs != NULL) 872 for (i = 0; multistate_ptr[i].key != NULL; i++) {
833 fatal("%s line %d: address family must be specified before " 873 if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
834 "ListenAddress.", filename, linenum); 874 value = multistate_ptr[i].value;
835 if (strcasecmp(arg, "inet") == 0) 875 break;
836 value = AF_INET; 876 }
837 else if (strcasecmp(arg, "inet6") == 0) 877 }
838 value = AF_INET6; 878 if (value == -1)
839 else if (strcasecmp(arg, "any") == 0) 879 fatal("%s line %d: unsupported option \"%s\".",
840 value = AF_UNSPEC;
841 else
842 fatal("%s line %d: unsupported address family \"%s\".",
843 filename, linenum, arg); 880 filename, linenum, arg);
844 if (*intptr == -1) 881 if (*activep && *intptr == -1)
845 *intptr = value; 882 *intptr = value;
846 break; 883 break;
847 884
@@ -880,27 +917,8 @@ process_server_config_line(ServerOptions *options, char *line,
880 917
881 case sPermitRootLogin: 918 case sPermitRootLogin:
882 intptr = &options->permit_root_login; 919 intptr = &options->permit_root_login;
883 arg = strdelim(&cp); 920 multistate_ptr = multistate_permitrootlogin;
884 if (!arg || *arg == '\0') 921 goto parse_multistate;
885 fatal("%s line %d: missing yes/"
886 "without-password/forced-commands-only/no "
887 "argument.", filename, linenum);
888 value = 0; /* silence compiler */
889 if (strcmp(arg, "without-password") == 0)
890 value = PERMIT_NO_PASSWD;
891 else if (strcmp(arg, "forced-commands-only") == 0)
892 value = PERMIT_FORCED_ONLY;
893 else if (strcmp(arg, "yes") == 0)
894 value = PERMIT_YES;
895 else if (strcmp(arg, "no") == 0)
896 value = PERMIT_NO;
897 else
898 fatal("%s line %d: Bad yes/"
899 "without-password/forced-commands-only/no "
900 "argument: %s", filename, linenum, arg);
901 if (*activep && *intptr == -1)
902 *intptr = value;
903 break;
904 922
905 case sIgnoreRhosts: 923 case sIgnoreRhosts:
906 intptr = &options->ignore_rhosts; 924 intptr = &options->ignore_rhosts;
@@ -1043,43 +1061,13 @@ process_server_config_line(ServerOptions *options, char *line,
1043 1061
1044 case sCompression: 1062 case sCompression:
1045 intptr = &options->compression; 1063 intptr = &options->compression;
1046 arg = strdelim(&cp); 1064 multistate_ptr = multistate_compression;
1047 if (!arg || *arg == '\0') 1065 goto parse_multistate;
1048 fatal("%s line %d: missing yes/no/delayed "
1049 "argument.", filename, linenum);
1050 value = 0; /* silence compiler */
1051 if (strcmp(arg, "delayed") == 0)
1052 value = COMP_DELAYED;
1053 else if (strcmp(arg, "yes") == 0)
1054 value = COMP_ZLIB;
1055 else if (strcmp(arg, "no") == 0)
1056 value = COMP_NONE;
1057 else
1058 fatal("%s line %d: Bad yes/no/delayed "
1059 "argument: %s", filename, linenum, arg);
1060 if (*intptr == -1)
1061 *intptr = value;
1062 break;
1063 1066
1064 case sGatewayPorts: 1067 case sGatewayPorts:
1065 intptr = &options->gateway_ports; 1068 intptr = &options->gateway_ports;
1066 arg = strdelim(&cp); 1069 multistate_ptr = multistate_gatewayports;
1067 if (!arg || *arg == '\0') 1070 goto parse_multistate;
1068 fatal("%s line %d: missing yes/no/clientspecified "
1069 "argument.", filename, linenum);
1070 value = 0; /* silence compiler */
1071 if (strcmp(arg, "clientspecified") == 0)
1072 value = 2;
1073 else if (strcmp(arg, "yes") == 0)
1074 value = 1;
1075 else if (strcmp(arg, "no") == 0)
1076 value = 0;
1077 else
1078 fatal("%s line %d: Bad yes/no/clientspecified "
1079 "argument: %s", filename, linenum, arg);
1080 if (*activep && *intptr == -1)
1081 *intptr = value;
1082 break;
1083 1071
1084 case sUseDNS: 1072 case sUseDNS:
1085 intptr = &options->use_dns; 1073 intptr = &options->use_dns;
@@ -1117,7 +1105,8 @@ process_server_config_line(ServerOptions *options, char *line,
1117 1105
1118 case sUsePrivilegeSeparation: 1106 case sUsePrivilegeSeparation:
1119 intptr = &use_privsep; 1107 intptr = &use_privsep;
1120 goto parse_flag; 1108 multistate_ptr = multistate_privsep;
1109 goto parse_multistate;
1121 1110
1122 case sAllowUsers: 1111 case sAllowUsers:
1123 while ((arg = strdelim(&cp)) && *arg != '\0') { 1112 while ((arg = strdelim(&cp)) && *arg != '\0') {
@@ -1283,14 +1272,22 @@ process_server_config_line(ServerOptions *options, char *line,
1283 * AuthorizedKeysFile /etc/ssh_keys/%u 1272 * AuthorizedKeysFile /etc/ssh_keys/%u
1284 */ 1273 */
1285 case sAuthorizedKeysFile: 1274 case sAuthorizedKeysFile:
1286 charptr = &options->authorized_keys_file; 1275 if (*activep && options->num_authkeys_files == 0) {
1287 goto parse_tilde_filename; 1276 while ((arg = strdelim(&cp)) && *arg != '\0') {
1288 case sAuthorizedKeysFile2: 1277 if (options->num_authkeys_files >=
1289 charptr = &options->authorized_keys_file2; 1278 MAX_AUTHKEYS_FILES)
1290 goto parse_tilde_filename; 1279 fatal("%s line %d: "
1280 "too many authorized keys files.",
1281 filename, linenum);
1282 options->authorized_keys_files[
1283 options->num_authkeys_files++] =
1284 tilde_expand_filename(arg, getuid());
1285 }
1286 }
1287 return 0;
1288
1291 case sAuthorizedPrincipalsFile: 1289 case sAuthorizedPrincipalsFile:
1292 charptr = &options->authorized_principals_file; 1290 charptr = &options->authorized_principals_file;
1293 parse_tilde_filename:
1294 arg = strdelim(&cp); 1291 arg = strdelim(&cp);
1295 if (!arg || *arg == '\0') 1292 if (!arg || *arg == '\0')
1296 fatal("%s line %d: missing file name.", 1293 fatal("%s line %d: missing file name.",
@@ -1509,6 +1506,12 @@ parse_server_match_config(ServerOptions *options, const char *user,
1509 dst->n = src->n; \ 1506 dst->n = src->n; \
1510 } \ 1507 } \
1511} while(0) 1508} while(0)
1509#define M_CP_STRARRAYOPT(n, num_n) do {\
1510 if (src->num_n != 0) { \
1511 for (dst->num_n = 0; dst->num_n < src->num_n; dst->num_n++) \
1512 dst->n[dst->num_n] = xstrdup(src->n[dst->num_n]); \
1513 } \
1514} while(0)
1512 1515
1513/* 1516/*
1514 * Copy any supported values that are set. 1517 * Copy any supported values that are set.
@@ -1544,20 +1547,23 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
1544 M_CP_INTOPT(ip_qos_interactive); 1547 M_CP_INTOPT(ip_qos_interactive);
1545 M_CP_INTOPT(ip_qos_bulk); 1548 M_CP_INTOPT(ip_qos_bulk);
1546 1549
1547 M_CP_STROPT(banner); 1550 /* See comment in servconf.h */
1551 COPY_MATCH_STRING_OPTS();
1552
1553 /*
1554 * The only things that should be below this point are string options
1555 * which are only used after authentication.
1556 */
1548 if (preauth) 1557 if (preauth)
1549 return; 1558 return;
1559
1550 M_CP_STROPT(adm_forced_command); 1560 M_CP_STROPT(adm_forced_command);
1551 M_CP_STROPT(chroot_directory); 1561 M_CP_STROPT(chroot_directory);
1552 M_CP_STROPT(trusted_user_ca_keys);
1553 M_CP_STROPT(revoked_keys_file);
1554 M_CP_STROPT(authorized_keys_file);
1555 M_CP_STROPT(authorized_keys_file2);
1556 M_CP_STROPT(authorized_principals_file);
1557} 1562}
1558 1563
1559#undef M_CP_INTOPT 1564#undef M_CP_INTOPT
1560#undef M_CP_STROPT 1565#undef M_CP_STROPT
1566#undef M_CP_STRARRAYOPT
1561 1567
1562void 1568void
1563parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, 1569parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
@@ -1583,31 +1589,34 @@ parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
1583} 1589}
1584 1590
1585static const char * 1591static const char *
1586fmt_intarg(ServerOpCodes code, int val) 1592fmt_multistate_int(int val, const struct multistate *m)
1587{ 1593{
1588 if (code == sAddressFamily) { 1594 u_int i;
1589 switch (val) { 1595
1590 case AF_INET: 1596 for (i = 0; m[i].key != NULL; i++) {
1591 return "inet"; 1597 if (m[i].value == val)
1592 case AF_INET6: 1598 return m[i].key;
1593 return "inet6";
1594 case AF_UNSPEC:
1595 return "any";
1596 default:
1597 return "UNKNOWN";
1598 }
1599 }
1600 if (code == sPermitRootLogin) {
1601 switch (val) {
1602 case PERMIT_NO_PASSWD:
1603 return "without-password";
1604 case PERMIT_FORCED_ONLY:
1605 return "forced-commands-only";
1606 case PERMIT_YES:
1607 return "yes";
1608 }
1609 } 1599 }
1610 if (code == sProtocol) { 1600 return "UNKNOWN";
1601}
1602
1603static const char *
1604fmt_intarg(ServerOpCodes code, int val)
1605{
1606 if (val == -1)
1607 return "unset";
1608 switch (code) {
1609 case sAddressFamily:
1610 return fmt_multistate_int(val, multistate_addressfamily);
1611 case sPermitRootLogin:
1612 return fmt_multistate_int(val, multistate_permitrootlogin);
1613 case sGatewayPorts:
1614 return fmt_multistate_int(val, multistate_gatewayports);
1615 case sCompression:
1616 return fmt_multistate_int(val, multistate_compression);
1617 case sUsePrivilegeSeparation:
1618 return fmt_multistate_int(val, multistate_privsep);
1619 case sProtocol:
1611 switch (val) { 1620 switch (val) {
1612 case SSH_PROTO_1: 1621 case SSH_PROTO_1:
1613 return "1"; 1622 return "1";
@@ -1618,20 +1627,16 @@ fmt_intarg(ServerOpCodes code, int val)
1618 default: 1627 default:
1619 return "UNKNOWN"; 1628 return "UNKNOWN";
1620 } 1629 }
1630 default:
1631 switch (val) {
1632 case 0:
1633 return "no";
1634 case 1:
1635 return "yes";
1636 default:
1637 return "UNKNOWN";
1638 }
1621 } 1639 }
1622 if (code == sGatewayPorts && val == 2)
1623 return "clientspecified";
1624 if (code == sCompression && val == COMP_DELAYED)
1625 return "delayed";
1626 switch (val) {
1627 case -1:
1628 return "unset";
1629 case 0:
1630 return "no";
1631 case 1:
1632 return "yes";
1633 }
1634 return "UNKNOWN";
1635} 1640}
1636 1641
1637static const char * 1642static const char *
@@ -1671,7 +1676,18 @@ dump_cfg_strarray(ServerOpCodes code, u_int count, char **vals)
1671 u_int i; 1676 u_int i;
1672 1677
1673 for (i = 0; i < count; i++) 1678 for (i = 0; i < count; i++)
1674 printf("%s %s\n", lookup_opcode_name(code), vals[i]); 1679 printf("%s %s\n", lookup_opcode_name(code), vals[i]);
1680}
1681
1682static void
1683dump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals)
1684{
1685 u_int i;
1686
1687 printf("%s", lookup_opcode_name(code));
1688 for (i = 0; i < count; i++)
1689 printf(" %s", vals[i]);
1690 printf("\n");
1675} 1691}
1676 1692
1677void 1693void
@@ -1772,8 +1788,6 @@ dump_config(ServerOptions *o)
1772 dump_cfg_string(sCiphers, o->ciphers); 1788 dump_cfg_string(sCiphers, o->ciphers);
1773 dump_cfg_string(sMacs, o->macs); 1789 dump_cfg_string(sMacs, o->macs);
1774 dump_cfg_string(sBanner, o->banner); 1790 dump_cfg_string(sBanner, o->banner);
1775 dump_cfg_string(sAuthorizedKeysFile, o->authorized_keys_file);
1776 dump_cfg_string(sAuthorizedKeysFile2, o->authorized_keys_file2);
1777 dump_cfg_string(sForceCommand, o->adm_forced_command); 1791 dump_cfg_string(sForceCommand, o->adm_forced_command);
1778 dump_cfg_string(sChrootDirectory, o->chroot_directory); 1792 dump_cfg_string(sChrootDirectory, o->chroot_directory);
1779 dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys); 1793 dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys);
@@ -1786,6 +1800,8 @@ dump_config(ServerOptions *o)
1786 dump_cfg_string(sLogFacility, log_facility_name(o->log_facility)); 1800 dump_cfg_string(sLogFacility, log_facility_name(o->log_facility));
1787 1801
1788 /* string array arguments */ 1802 /* string array arguments */
1803 dump_cfg_strarray_oneline(sAuthorizedKeysFile, o->num_authkeys_files,
1804 o->authorized_keys_files);
1789 dump_cfg_strarray(sHostKeyFile, o->num_host_key_files, 1805 dump_cfg_strarray(sHostKeyFile, o->num_host_key_files,
1790 o->host_key_files); 1806 o->host_key_files);
1791 dump_cfg_strarray(sHostKeyFile, o->num_host_cert_files, 1807 dump_cfg_strarray(sHostKeyFile, o->num_host_cert_files,
@@ -1811,7 +1827,8 @@ dump_config(ServerOptions *o)
1811 } 1827 }
1812 dump_cfg_string(sPermitTunnel, s); 1828 dump_cfg_string(sPermitTunnel, s);
1813 1829
1814 printf("ipqos 0x%02x 0x%02x\n", o->ip_qos_interactive, o->ip_qos_bulk); 1830 printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
1831 printf("%s\n", iptos2str(o->ip_qos_bulk));
1815 1832
1816 channel_print_adm_permitted_opens(); 1833 channel_print_adm_permitted_opens();
1817} 1834}