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 11a69f819..1911ac540 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
@@ -130,8 +130,7 @@ initialize_server_options(ServerOptions *options)
130 options->use_dns = -1; 130 options->use_dns = -1;
131 options->client_alive_interval = -1; 131 options->client_alive_interval = -1;
132 options->client_alive_count_max = -1; 132 options->client_alive_count_max = -1;
133 options->authorized_keys_file = NULL; 133 options->num_authkeys_files = 0;
134 options->authorized_keys_file2 = NULL;
135 options->num_accept_env = 0; 134 options->num_accept_env = 0;
136 options->permit_tun = -1; 135 options->permit_tun = -1;
137 options->num_permitted_opens = -1; 136 options->num_permitted_opens = -1;
@@ -277,15 +276,12 @@ fill_default_server_options(ServerOptions *options)
277 options->client_alive_interval = 0; 276 options->client_alive_interval = 0;
278 if (options->client_alive_count_max == -1) 277 if (options->client_alive_count_max == -1)
279 options->client_alive_count_max = 3; 278 options->client_alive_count_max = 3;
280 if (options->authorized_keys_file2 == NULL) { 279 if (options->num_authkeys_files == 0) {
281 /* authorized_keys_file2 falls back to authorized_keys_file */ 280 options->authorized_keys_files[options->num_authkeys_files++] =
282 if (options->authorized_keys_file != NULL) 281 xstrdup(_PATH_SSH_USER_PERMITTED_KEYS);
283 options->authorized_keys_file2 = xstrdup(options->authorized_keys_file); 282 options->authorized_keys_files[options->num_authkeys_files++] =
284 else 283 xstrdup(_PATH_SSH_USER_PERMITTED_KEYS2);
285 options->authorized_keys_file2 = xstrdup(_PATH_SSH_USER_PERMITTED_KEYS2);
286 } 284 }
287 if (options->authorized_keys_file == NULL)
288 options->authorized_keys_file = xstrdup(_PATH_SSH_USER_PERMITTED_KEYS);
289 if (options->permit_tun == -1) 285 if (options->permit_tun == -1)
290 options->permit_tun = SSH_TUNMODE_NO; 286 options->permit_tun = SSH_TUNMODE_NO;
291 if (options->zero_knowledge_password_authentication == -1) 287 if (options->zero_knowledge_password_authentication == -1)
@@ -299,7 +295,7 @@ fill_default_server_options(ServerOptions *options)
299 295
300 /* Turn privilege separation on by default */ 296 /* Turn privilege separation on by default */
301 if (use_privsep == -1) 297 if (use_privsep == -1)
302 use_privsep = 1; 298 use_privsep = PRIVSEP_ON;
303 299
304#ifndef HAVE_MMAP 300#ifndef HAVE_MMAP
305 if (use_privsep && options->compression == 1) { 301 if (use_privsep && options->compression == 1) {
@@ -336,7 +332,7 @@ typedef enum {
336 sMaxStartups, sMaxAuthTries, sMaxSessions, 332 sMaxStartups, sMaxAuthTries, sMaxSessions,
337 sBanner, sUseDNS, sHostbasedAuthentication, 333 sBanner, sUseDNS, sHostbasedAuthentication,
338 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, 334 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
339 sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, 335 sClientAliveCountMax, sAuthorizedKeysFile,
340 sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, 336 sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
341 sGssKeyEx, sGssStoreRekey, 337 sGssKeyEx, sGssStoreRekey,
342 sAcceptEnv, sPermitTunnel, 338 sAcceptEnv, sPermitTunnel,
@@ -467,7 +463,7 @@ static struct {
467 { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL }, 463 { "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL },
468 { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL }, 464 { "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL },
469 { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL }, 465 { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL },
470 { "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_ALL }, 466 { "authorizedkeysfile2", sDeprecated, SSHCFG_ALL },
471 { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL}, 467 { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL},
472 { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL }, 468 { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL },
473 { "permittunnel", sPermitTunnel, SSHCFG_ALL }, 469 { "permittunnel", sPermitTunnel, SSHCFG_ALL },
@@ -705,6 +701,43 @@ match_cfg_line(char **condition, int line, const char *user, const char *host,
705 701
706#define WHITESPACE " \t\r\n" 702#define WHITESPACE " \t\r\n"
707 703
704/* Multistate option parsing */
705struct multistate {
706 char *key;
707 int value;
708};
709static const struct multistate multistate_addressfamily[] = {
710 { "inet", AF_INET },
711 { "inet6", AF_INET6 },
712 { "any", AF_UNSPEC },
713 { NULL, -1 }
714};
715static const struct multistate multistate_permitrootlogin[] = {
716 { "without-password", PERMIT_NO_PASSWD },
717 { "forced-commands-only", PERMIT_FORCED_ONLY },
718 { "yes", PERMIT_YES },
719 { "no", PERMIT_NO },
720 { NULL, -1 }
721};
722static const struct multistate multistate_compression[] = {
723 { "delayed", COMP_DELAYED },
724 { "yes", COMP_ZLIB },
725 { "no", COMP_NONE },
726 { NULL, -1 }
727};
728static const struct multistate multistate_gatewayports[] = {
729 { "clientspecified", 2 },
730 { "yes", 1 },
731 { "no", 0 },
732 { NULL, -1 }
733};
734static const struct multistate multistate_privsep[] = {
735 { "sandbox", PRIVSEP_SANDBOX },
736 { "yes", PRIVSEP_ON },
737 { "no", PRIVSEP_OFF },
738 { NULL, -1 }
739};
740
708int 741int
709process_server_config_line(ServerOptions *options, char *line, 742process_server_config_line(ServerOptions *options, char *line,
710 const char *filename, int linenum, int *activep, const char *user, 743 const char *filename, int linenum, int *activep, const char *user,
@@ -718,6 +751,7 @@ process_server_config_line(ServerOptions *options, char *line,
718 int port; 751 int port;
719 u_int i, flags = 0; 752 u_int i, flags = 0;
720 size_t len; 753 size_t len;
754 const struct multistate *multistate_ptr;
721 755
722 cp = line; 756 cp = line;
723 if ((arg = strdelim(&cp)) == NULL) 757 if ((arg = strdelim(&cp)) == NULL)
@@ -833,24 +867,27 @@ process_server_config_line(ServerOptions *options, char *line,
833 break; 867 break;
834 868
835 case sAddressFamily: 869 case sAddressFamily:
870 intptr = &options->address_family;
871 multistate_ptr = multistate_addressfamily;
872 if (options->listen_addrs != NULL)
873 fatal("%s line %d: address family must be specified "
874 "before ListenAddress.", filename, linenum);
875 parse_multistate:
836 arg = strdelim(&cp); 876 arg = strdelim(&cp);
837 if (!arg || *arg == '\0') 877 if (!arg || *arg == '\0')
838 fatal("%s line %d: missing address family.", 878 fatal("%s line %d: missing argument.",
839 filename, linenum); 879 filename, linenum);
840 intptr = &options->address_family; 880 value = -1;
841 if (options->listen_addrs != NULL) 881 for (i = 0; multistate_ptr[i].key != NULL; i++) {
842 fatal("%s line %d: address family must be specified before " 882 if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
843 "ListenAddress.", filename, linenum); 883 value = multistate_ptr[i].value;
844 if (strcasecmp(arg, "inet") == 0) 884 break;
845 value = AF_INET; 885 }
846 else if (strcasecmp(arg, "inet6") == 0) 886 }
847 value = AF_INET6; 887 if (value == -1)
848 else if (strcasecmp(arg, "any") == 0) 888 fatal("%s line %d: unsupported option \"%s\".",
849 value = AF_UNSPEC;
850 else
851 fatal("%s line %d: unsupported address family \"%s\".",
852 filename, linenum, arg); 889 filename, linenum, arg);
853 if (*intptr == -1) 890 if (*activep && *intptr == -1)
854 *intptr = value; 891 *intptr = value;
855 break; 892 break;
856 893
@@ -889,27 +926,8 @@ process_server_config_line(ServerOptions *options, char *line,
889 926
890 case sPermitRootLogin: 927 case sPermitRootLogin:
891 intptr = &options->permit_root_login; 928 intptr = &options->permit_root_login;
892 arg = strdelim(&cp); 929 multistate_ptr = multistate_permitrootlogin;
893 if (!arg || *arg == '\0') 930 goto parse_multistate;
894 fatal("%s line %d: missing yes/"
895 "without-password/forced-commands-only/no "
896 "argument.", filename, linenum);
897 value = 0; /* silence compiler */
898 if (strcmp(arg, "without-password") == 0)
899 value = PERMIT_NO_PASSWD;
900 else if (strcmp(arg, "forced-commands-only") == 0)
901 value = PERMIT_FORCED_ONLY;
902 else if (strcmp(arg, "yes") == 0)
903 value = PERMIT_YES;
904 else if (strcmp(arg, "no") == 0)
905 value = PERMIT_NO;
906 else
907 fatal("%s line %d: Bad yes/"
908 "without-password/forced-commands-only/no "
909 "argument: %s", filename, linenum, arg);
910 if (*activep && *intptr == -1)
911 *intptr = value;
912 break;
913 931
914 case sIgnoreRhosts: 932 case sIgnoreRhosts:
915 intptr = &options->ignore_rhosts; 933 intptr = &options->ignore_rhosts;
@@ -1056,43 +1074,13 @@ process_server_config_line(ServerOptions *options, char *line,
1056 1074
1057 case sCompression: 1075 case sCompression:
1058 intptr = &options->compression; 1076 intptr = &options->compression;
1059 arg = strdelim(&cp); 1077 multistate_ptr = multistate_compression;
1060 if (!arg || *arg == '\0') 1078 goto parse_multistate;
1061 fatal("%s line %d: missing yes/no/delayed "
1062 "argument.", filename, linenum);
1063 value = 0; /* silence compiler */
1064 if (strcmp(arg, "delayed") == 0)
1065 value = COMP_DELAYED;
1066 else if (strcmp(arg, "yes") == 0)
1067 value = COMP_ZLIB;
1068 else if (strcmp(arg, "no") == 0)
1069 value = COMP_NONE;
1070 else
1071 fatal("%s line %d: Bad yes/no/delayed "
1072 "argument: %s", filename, linenum, arg);
1073 if (*intptr == -1)
1074 *intptr = value;
1075 break;
1076 1079
1077 case sGatewayPorts: 1080 case sGatewayPorts:
1078 intptr = &options->gateway_ports; 1081 intptr = &options->gateway_ports;
1079 arg = strdelim(&cp); 1082 multistate_ptr = multistate_gatewayports;
1080 if (!arg || *arg == '\0') 1083 goto parse_multistate;
1081 fatal("%s line %d: missing yes/no/clientspecified "
1082 "argument.", filename, linenum);
1083 value = 0; /* silence compiler */
1084 if (strcmp(arg, "clientspecified") == 0)
1085 value = 2;
1086 else if (strcmp(arg, "yes") == 0)
1087 value = 1;
1088 else if (strcmp(arg, "no") == 0)
1089 value = 0;
1090 else
1091 fatal("%s line %d: Bad yes/no/clientspecified "
1092 "argument: %s", filename, linenum, arg);
1093 if (*activep && *intptr == -1)
1094 *intptr = value;
1095 break;
1096 1084
1097 case sUseDNS: 1085 case sUseDNS:
1098 intptr = &options->use_dns; 1086 intptr = &options->use_dns;
@@ -1130,7 +1118,8 @@ process_server_config_line(ServerOptions *options, char *line,
1130 1118
1131 case sUsePrivilegeSeparation: 1119 case sUsePrivilegeSeparation:
1132 intptr = &use_privsep; 1120 intptr = &use_privsep;
1133 goto parse_flag; 1121 multistate_ptr = multistate_privsep;
1122 goto parse_multistate;
1134 1123
1135 case sAllowUsers: 1124 case sAllowUsers:
1136 while ((arg = strdelim(&cp)) && *arg != '\0') { 1125 while ((arg = strdelim(&cp)) && *arg != '\0') {
@@ -1296,14 +1285,22 @@ process_server_config_line(ServerOptions *options, char *line,
1296 * AuthorizedKeysFile /etc/ssh_keys/%u 1285 * AuthorizedKeysFile /etc/ssh_keys/%u
1297 */ 1286 */
1298 case sAuthorizedKeysFile: 1287 case sAuthorizedKeysFile:
1299 charptr = &options->authorized_keys_file; 1288 if (*activep && options->num_authkeys_files == 0) {
1300 goto parse_tilde_filename; 1289 while ((arg = strdelim(&cp)) && *arg != '\0') {
1301 case sAuthorizedKeysFile2: 1290 if (options->num_authkeys_files >=
1302 charptr = &options->authorized_keys_file2; 1291 MAX_AUTHKEYS_FILES)
1303 goto parse_tilde_filename; 1292 fatal("%s line %d: "
1293 "too many authorized keys files.",
1294 filename, linenum);
1295 options->authorized_keys_files[
1296 options->num_authkeys_files++] =
1297 tilde_expand_filename(arg, getuid());
1298 }
1299 }
1300 return 0;
1301
1304 case sAuthorizedPrincipalsFile: 1302 case sAuthorizedPrincipalsFile:
1305 charptr = &options->authorized_principals_file; 1303 charptr = &options->authorized_principals_file;
1306 parse_tilde_filename:
1307 arg = strdelim(&cp); 1304 arg = strdelim(&cp);
1308 if (!arg || *arg == '\0') 1305 if (!arg || *arg == '\0')
1309 fatal("%s line %d: missing file name.", 1306 fatal("%s line %d: missing file name.",
@@ -1526,6 +1523,12 @@ parse_server_match_config(ServerOptions *options, const char *user,
1526 dst->n = src->n; \ 1523 dst->n = src->n; \
1527 } \ 1524 } \
1528} while(0) 1525} while(0)
1526#define M_CP_STRARRAYOPT(n, num_n) do {\
1527 if (src->num_n != 0) { \
1528 for (dst->num_n = 0; dst->num_n < src->num_n; dst->num_n++) \
1529 dst->n[dst->num_n] = xstrdup(src->n[dst->num_n]); \
1530 } \
1531} while(0)
1529 1532
1530/* 1533/*
1531 * Copy any supported values that are set. 1534 * Copy any supported values that are set.
@@ -1561,20 +1564,23 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
1561 M_CP_INTOPT(ip_qos_interactive); 1564 M_CP_INTOPT(ip_qos_interactive);
1562 M_CP_INTOPT(ip_qos_bulk); 1565 M_CP_INTOPT(ip_qos_bulk);
1563 1566
1564 M_CP_STROPT(banner); 1567 /* See comment in servconf.h */
1568 COPY_MATCH_STRING_OPTS();
1569
1570 /*
1571 * The only things that should be below this point are string options
1572 * which are only used after authentication.
1573 */
1565 if (preauth) 1574 if (preauth)
1566 return; 1575 return;
1576
1567 M_CP_STROPT(adm_forced_command); 1577 M_CP_STROPT(adm_forced_command);
1568 M_CP_STROPT(chroot_directory); 1578 M_CP_STROPT(chroot_directory);
1569 M_CP_STROPT(trusted_user_ca_keys);
1570 M_CP_STROPT(revoked_keys_file);
1571 M_CP_STROPT(authorized_keys_file);
1572 M_CP_STROPT(authorized_keys_file2);
1573 M_CP_STROPT(authorized_principals_file);
1574} 1579}
1575 1580
1576#undef M_CP_INTOPT 1581#undef M_CP_INTOPT
1577#undef M_CP_STROPT 1582#undef M_CP_STROPT
1583#undef M_CP_STRARRAYOPT
1578 1584
1579void 1585void
1580parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, 1586parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
@@ -1600,31 +1606,34 @@ parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
1600} 1606}
1601 1607
1602static const char * 1608static const char *
1603fmt_intarg(ServerOpCodes code, int val) 1609fmt_multistate_int(int val, const struct multistate *m)
1604{ 1610{
1605 if (code == sAddressFamily) { 1611 u_int i;
1606 switch (val) { 1612
1607 case AF_INET: 1613 for (i = 0; m[i].key != NULL; i++) {
1608 return "inet"; 1614 if (m[i].value == val)
1609 case AF_INET6: 1615 return m[i].key;
1610 return "inet6";
1611 case AF_UNSPEC:
1612 return "any";
1613 default:
1614 return "UNKNOWN";
1615 }
1616 }
1617 if (code == sPermitRootLogin) {
1618 switch (val) {
1619 case PERMIT_NO_PASSWD:
1620 return "without-password";
1621 case PERMIT_FORCED_ONLY:
1622 return "forced-commands-only";
1623 case PERMIT_YES:
1624 return "yes";
1625 }
1626 } 1616 }
1627 if (code == sProtocol) { 1617 return "UNKNOWN";
1618}
1619
1620static const char *
1621fmt_intarg(ServerOpCodes code, int val)
1622{
1623 if (val == -1)
1624 return "unset";
1625 switch (code) {
1626 case sAddressFamily:
1627 return fmt_multistate_int(val, multistate_addressfamily);
1628 case sPermitRootLogin:
1629 return fmt_multistate_int(val, multistate_permitrootlogin);
1630 case sGatewayPorts:
1631 return fmt_multistate_int(val, multistate_gatewayports);
1632 case sCompression:
1633 return fmt_multistate_int(val, multistate_compression);
1634 case sUsePrivilegeSeparation:
1635 return fmt_multistate_int(val, multistate_privsep);
1636 case sProtocol:
1628 switch (val) { 1637 switch (val) {
1629 case SSH_PROTO_1: 1638 case SSH_PROTO_1:
1630 return "1"; 1639 return "1";
@@ -1635,20 +1644,16 @@ fmt_intarg(ServerOpCodes code, int val)
1635 default: 1644 default:
1636 return "UNKNOWN"; 1645 return "UNKNOWN";
1637 } 1646 }
1647 default:
1648 switch (val) {
1649 case 0:
1650 return "no";
1651 case 1:
1652 return "yes";
1653 default:
1654 return "UNKNOWN";
1655 }
1638 } 1656 }
1639 if (code == sGatewayPorts && val == 2)
1640 return "clientspecified";
1641 if (code == sCompression && val == COMP_DELAYED)
1642 return "delayed";
1643 switch (val) {
1644 case -1:
1645 return "unset";
1646 case 0:
1647 return "no";
1648 case 1:
1649 return "yes";
1650 }
1651 return "UNKNOWN";
1652} 1657}
1653 1658
1654static const char * 1659static const char *
@@ -1688,7 +1693,18 @@ dump_cfg_strarray(ServerOpCodes code, u_int count, char **vals)
1688 u_int i; 1693 u_int i;
1689 1694
1690 for (i = 0; i < count; i++) 1695 for (i = 0; i < count; i++)
1691 printf("%s %s\n", lookup_opcode_name(code), vals[i]); 1696 printf("%s %s\n", lookup_opcode_name(code), vals[i]);
1697}
1698
1699static void
1700dump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals)
1701{
1702 u_int i;
1703
1704 printf("%s", lookup_opcode_name(code));
1705 for (i = 0; i < count; i++)
1706 printf(" %s", vals[i]);
1707 printf("\n");
1692} 1708}
1693 1709
1694void 1710void
@@ -1790,8 +1806,6 @@ dump_config(ServerOptions *o)
1790 dump_cfg_string(sCiphers, o->ciphers); 1806 dump_cfg_string(sCiphers, o->ciphers);
1791 dump_cfg_string(sMacs, o->macs); 1807 dump_cfg_string(sMacs, o->macs);
1792 dump_cfg_string(sBanner, o->banner); 1808 dump_cfg_string(sBanner, o->banner);
1793 dump_cfg_string(sAuthorizedKeysFile, o->authorized_keys_file);
1794 dump_cfg_string(sAuthorizedKeysFile2, o->authorized_keys_file2);
1795 dump_cfg_string(sForceCommand, o->adm_forced_command); 1809 dump_cfg_string(sForceCommand, o->adm_forced_command);
1796 dump_cfg_string(sChrootDirectory, o->chroot_directory); 1810 dump_cfg_string(sChrootDirectory, o->chroot_directory);
1797 dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys); 1811 dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys);
@@ -1804,6 +1818,8 @@ dump_config(ServerOptions *o)
1804 dump_cfg_string(sLogFacility, log_facility_name(o->log_facility)); 1818 dump_cfg_string(sLogFacility, log_facility_name(o->log_facility));
1805 1819
1806 /* string array arguments */ 1820 /* string array arguments */
1821 dump_cfg_strarray_oneline(sAuthorizedKeysFile, o->num_authkeys_files,
1822 o->authorized_keys_files);
1807 dump_cfg_strarray(sHostKeyFile, o->num_host_key_files, 1823 dump_cfg_strarray(sHostKeyFile, o->num_host_key_files,
1808 o->host_key_files); 1824 o->host_key_files);
1809 dump_cfg_strarray(sHostKeyFile, o->num_host_cert_files, 1825 dump_cfg_strarray(sHostKeyFile, o->num_host_cert_files,
@@ -1829,7 +1845,8 @@ dump_config(ServerOptions *o)
1829 } 1845 }
1830 dump_cfg_string(sPermitTunnel, s); 1846 dump_cfg_string(sPermitTunnel, s);
1831 1847
1832 printf("ipqos 0x%02x 0x%02x\n", o->ip_qos_interactive, o->ip_qos_bulk); 1848 printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
1849 printf("%s\n", iptos2str(o->ip_qos_bulk));
1833 1850
1834 channel_print_adm_permitted_opens(); 1851 channel_print_adm_permitted_opens();
1835} 1852}