diff options
Diffstat (limited to 'servconf.c')
-rw-r--r-- | servconf.c | 231 |
1 files changed, 190 insertions, 41 deletions
diff --git a/servconf.c b/servconf.c index 9937f8f2f..5be0c7bbf 100644 --- a/servconf.c +++ b/servconf.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* $OpenBSD: servconf.c,v 1.223 2011/09/23 00:22:04 dtucker Exp $ */ | 1 | |
2 | /* $OpenBSD: servconf.c,v 1.229 2012/07/13 01:35:21 dtucker Exp $ */ | ||
2 | /* | 3 | /* |
3 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland | 4 | * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland |
4 | * All rights reserved | 5 | * All rights reserved |
@@ -45,6 +46,8 @@ | |||
45 | #include "match.h" | 46 | #include "match.h" |
46 | #include "channels.h" | 47 | #include "channels.h" |
47 | #include "groupaccess.h" | 48 | #include "groupaccess.h" |
49 | #include "canohost.h" | ||
50 | #include "packet.h" | ||
48 | 51 | ||
49 | static void add_listen_addr(ServerOptions *, char *, int); | 52 | static void add_listen_addr(ServerOptions *, char *, int); |
50 | static void add_one_listen_addr(ServerOptions *, char *, int); | 53 | static void add_one_listen_addr(ServerOptions *, char *, int); |
@@ -141,6 +144,7 @@ initialize_server_options(ServerOptions *options) | |||
141 | options->authorized_principals_file = NULL; | 144 | options->authorized_principals_file = NULL; |
142 | options->ip_qos_interactive = -1; | 145 | options->ip_qos_interactive = -1; |
143 | options->ip_qos_bulk = -1; | 146 | options->ip_qos_bulk = -1; |
147 | options->version_addendum = NULL; | ||
144 | } | 148 | } |
145 | 149 | ||
146 | void | 150 | void |
@@ -286,10 +290,11 @@ fill_default_server_options(ServerOptions *options) | |||
286 | options->ip_qos_interactive = IPTOS_LOWDELAY; | 290 | options->ip_qos_interactive = IPTOS_LOWDELAY; |
287 | if (options->ip_qos_bulk == -1) | 291 | if (options->ip_qos_bulk == -1) |
288 | options->ip_qos_bulk = IPTOS_THROUGHPUT; | 292 | options->ip_qos_bulk = IPTOS_THROUGHPUT; |
289 | 293 | if (options->version_addendum == NULL) | |
294 | options->version_addendum = xstrdup(""); | ||
290 | /* Turn privilege separation on by default */ | 295 | /* Turn privilege separation on by default */ |
291 | if (use_privsep == -1) | 296 | if (use_privsep == -1) |
292 | use_privsep = PRIVSEP_ON; | 297 | use_privsep = PRIVSEP_NOSANDBOX; |
293 | 298 | ||
294 | #ifndef HAVE_MMAP | 299 | #ifndef HAVE_MMAP |
295 | if (use_privsep && options->compression == 1) { | 300 | if (use_privsep && options->compression == 1) { |
@@ -334,7 +339,7 @@ typedef enum { | |||
334 | sUsePrivilegeSeparation, sAllowAgentForwarding, | 339 | sUsePrivilegeSeparation, sAllowAgentForwarding, |
335 | sZeroKnowledgePasswordAuthentication, sHostCertificate, | 340 | sZeroKnowledgePasswordAuthentication, sHostCertificate, |
336 | sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, | 341 | sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, |
337 | sKexAlgorithms, sIPQoS, | 342 | sKexAlgorithms, sIPQoS, sVersionAddendum, |
338 | sDeprecated, sUnsupported | 343 | sDeprecated, sUnsupported |
339 | } ServerOpCodes; | 344 | } ServerOpCodes; |
340 | 345 | ||
@@ -436,10 +441,10 @@ static struct { | |||
436 | { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */ | 441 | { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */ |
437 | { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL }, | 442 | { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL }, |
438 | { "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL }, | 443 | { "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL }, |
439 | { "allowusers", sAllowUsers, SSHCFG_GLOBAL }, | 444 | { "allowusers", sAllowUsers, SSHCFG_ALL }, |
440 | { "denyusers", sDenyUsers, SSHCFG_GLOBAL }, | 445 | { "denyusers", sDenyUsers, SSHCFG_ALL }, |
441 | { "allowgroups", sAllowGroups, SSHCFG_GLOBAL }, | 446 | { "allowgroups", sAllowGroups, SSHCFG_ALL }, |
442 | { "denygroups", sDenyGroups, SSHCFG_GLOBAL }, | 447 | { "denygroups", sDenyGroups, SSHCFG_ALL }, |
443 | { "ciphers", sCiphers, SSHCFG_GLOBAL }, | 448 | { "ciphers", sCiphers, SSHCFG_GLOBAL }, |
444 | { "macs", sMacs, SSHCFG_GLOBAL }, | 449 | { "macs", sMacs, SSHCFG_GLOBAL }, |
445 | { "protocol", sProtocol, SSHCFG_GLOBAL }, | 450 | { "protocol", sProtocol, SSHCFG_GLOBAL }, |
@@ -457,7 +462,7 @@ static struct { | |||
457 | { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL }, | 462 | { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL }, |
458 | { "authorizedkeysfile2", sDeprecated, SSHCFG_ALL }, | 463 | { "authorizedkeysfile2", sDeprecated, SSHCFG_ALL }, |
459 | { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL}, | 464 | { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL}, |
460 | { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL }, | 465 | { "acceptenv", sAcceptEnv, SSHCFG_ALL }, |
461 | { "permittunnel", sPermitTunnel, SSHCFG_ALL }, | 466 | { "permittunnel", sPermitTunnel, SSHCFG_ALL }, |
462 | { "match", sMatch, SSHCFG_ALL }, | 467 | { "match", sMatch, SSHCFG_ALL }, |
463 | { "permitopen", sPermitOpen, SSHCFG_ALL }, | 468 | { "permitopen", sPermitOpen, SSHCFG_ALL }, |
@@ -469,6 +474,7 @@ static struct { | |||
469 | { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, | 474 | { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, |
470 | { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, | 475 | { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, |
471 | { "ipqos", sIPQoS, SSHCFG_ALL }, | 476 | { "ipqos", sIPQoS, SSHCFG_ALL }, |
477 | { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, | ||
472 | { NULL, sBadOption, 0 } | 478 | { NULL, sBadOption, 0 } |
473 | }; | 479 | }; |
474 | 480 | ||
@@ -557,6 +563,20 @@ add_one_listen_addr(ServerOptions *options, char *addr, int port) | |||
557 | options->listen_addrs = aitop; | 563 | options->listen_addrs = aitop; |
558 | } | 564 | } |
559 | 565 | ||
566 | struct connection_info * | ||
567 | get_connection_info(int populate, int use_dns) | ||
568 | { | ||
569 | static struct connection_info ci; | ||
570 | |||
571 | if (!populate) | ||
572 | return &ci; | ||
573 | ci.host = get_canonical_hostname(use_dns); | ||
574 | ci.address = get_remote_ipaddr(); | ||
575 | ci.laddress = get_local_ipaddr(packet_get_connection_in()); | ||
576 | ci.lport = get_local_port(); | ||
577 | return &ci; | ||
578 | } | ||
579 | |||
560 | /* | 580 | /* |
561 | * The strategy for the Match blocks is that the config file is parsed twice. | 581 | * The strategy for the Match blocks is that the config file is parsed twice. |
562 | * | 582 | * |
@@ -618,20 +638,25 @@ out: | |||
618 | return result; | 638 | return result; |
619 | } | 639 | } |
620 | 640 | ||
641 | /* | ||
642 | * All of the attributes on a single Match line are ANDed together, so we need to check every | ||
643 | * attribute and set the result to zero if any attribute does not match. | ||
644 | */ | ||
621 | static int | 645 | static int |
622 | match_cfg_line(char **condition, int line, const char *user, const char *host, | 646 | match_cfg_line(char **condition, int line, struct connection_info *ci) |
623 | const char *address) | ||
624 | { | 647 | { |
625 | int result = 1; | 648 | int result = 1, port; |
626 | char *arg, *attrib, *cp = *condition; | 649 | char *arg, *attrib, *cp = *condition; |
627 | size_t len; | 650 | size_t len; |
628 | 651 | ||
629 | if (user == NULL) | 652 | if (ci == NULL) |
630 | debug3("checking syntax for 'Match %s'", cp); | 653 | debug3("checking syntax for 'Match %s'", cp); |
631 | else | 654 | else |
632 | debug3("checking match for '%s' user %s host %s addr %s", cp, | 655 | debug3("checking match for '%s' user %s host %s addr %s " |
633 | user ? user : "(null)", host ? host : "(null)", | 656 | "laddr %s lport %d", cp, ci->user ? ci->user : "(null)", |
634 | address ? address : "(null)"); | 657 | ci->host ? ci->host : "(null)", |
658 | ci->address ? ci->address : "(null)", | ||
659 | ci->laddress ? ci->laddress : "(null)", ci->lport); | ||
635 | 660 | ||
636 | while ((attrib = strdelim(&cp)) && *attrib != '\0') { | 661 | while ((attrib = strdelim(&cp)) && *attrib != '\0') { |
637 | if ((arg = strdelim(&cp)) == NULL || *arg == '\0') { | 662 | if ((arg = strdelim(&cp)) == NULL || *arg == '\0') { |
@@ -640,37 +665,45 @@ match_cfg_line(char **condition, int line, const char *user, const char *host, | |||
640 | } | 665 | } |
641 | len = strlen(arg); | 666 | len = strlen(arg); |
642 | if (strcasecmp(attrib, "user") == 0) { | 667 | if (strcasecmp(attrib, "user") == 0) { |
643 | if (!user) { | 668 | if (ci == NULL || ci->user == NULL) { |
644 | result = 0; | 669 | result = 0; |
645 | continue; | 670 | continue; |
646 | } | 671 | } |
647 | if (match_pattern_list(user, arg, len, 0) != 1) | 672 | if (match_pattern_list(ci->user, arg, len, 0) != 1) |
648 | result = 0; | 673 | result = 0; |
649 | else | 674 | else |
650 | debug("user %.100s matched 'User %.100s' at " | 675 | debug("user %.100s matched 'User %.100s' at " |
651 | "line %d", user, arg, line); | 676 | "line %d", ci->user, arg, line); |
652 | } else if (strcasecmp(attrib, "group") == 0) { | 677 | } else if (strcasecmp(attrib, "group") == 0) { |
653 | switch (match_cfg_line_group(arg, line, user)) { | 678 | if (ci == NULL || ci->user == NULL) { |
679 | result = 0; | ||
680 | continue; | ||
681 | } | ||
682 | switch (match_cfg_line_group(arg, line, ci->user)) { | ||
654 | case -1: | 683 | case -1: |
655 | return -1; | 684 | return -1; |
656 | case 0: | 685 | case 0: |
657 | result = 0; | 686 | result = 0; |
658 | } | 687 | } |
659 | } else if (strcasecmp(attrib, "host") == 0) { | 688 | } else if (strcasecmp(attrib, "host") == 0) { |
660 | if (!host) { | 689 | if (ci == NULL || ci->host == NULL) { |
661 | result = 0; | 690 | result = 0; |
662 | continue; | 691 | continue; |
663 | } | 692 | } |
664 | if (match_hostname(host, arg, len) != 1) | 693 | if (match_hostname(ci->host, arg, len) != 1) |
665 | result = 0; | 694 | result = 0; |
666 | else | 695 | else |
667 | debug("connection from %.100s matched 'Host " | 696 | debug("connection from %.100s matched 'Host " |
668 | "%.100s' at line %d", host, arg, line); | 697 | "%.100s' at line %d", ci->host, arg, line); |
669 | } else if (strcasecmp(attrib, "address") == 0) { | 698 | } else if (strcasecmp(attrib, "address") == 0) { |
670 | switch (addr_match_list(address, arg)) { | 699 | if (ci == NULL || ci->address == NULL) { |
700 | result = 0; | ||
701 | continue; | ||
702 | } | ||
703 | switch (addr_match_list(ci->address, arg)) { | ||
671 | case 1: | 704 | case 1: |
672 | debug("connection from %.100s matched 'Address " | 705 | debug("connection from %.100s matched 'Address " |
673 | "%.100s' at line %d", address, arg, line); | 706 | "%.100s' at line %d", ci->address, arg, line); |
674 | break; | 707 | break; |
675 | case 0: | 708 | case 0: |
676 | case -1: | 709 | case -1: |
@@ -679,12 +712,47 @@ match_cfg_line(char **condition, int line, const char *user, const char *host, | |||
679 | case -2: | 712 | case -2: |
680 | return -1; | 713 | return -1; |
681 | } | 714 | } |
715 | } else if (strcasecmp(attrib, "localaddress") == 0){ | ||
716 | if (ci == NULL || ci->laddress == NULL) { | ||
717 | result = 0; | ||
718 | continue; | ||
719 | } | ||
720 | switch (addr_match_list(ci->laddress, arg)) { | ||
721 | case 1: | ||
722 | debug("connection from %.100s matched " | ||
723 | "'LocalAddress %.100s' at line %d", | ||
724 | ci->laddress, arg, line); | ||
725 | break; | ||
726 | case 0: | ||
727 | case -1: | ||
728 | result = 0; | ||
729 | break; | ||
730 | case -2: | ||
731 | return -1; | ||
732 | } | ||
733 | } else if (strcasecmp(attrib, "localport") == 0) { | ||
734 | if ((port = a2port(arg)) == -1) { | ||
735 | error("Invalid LocalPort '%s' on Match line", | ||
736 | arg); | ||
737 | return -1; | ||
738 | } | ||
739 | if (ci == NULL || ci->lport == 0) { | ||
740 | result = 0; | ||
741 | continue; | ||
742 | } | ||
743 | /* TODO support port lists */ | ||
744 | if (port == ci->lport) | ||
745 | debug("connection from %.100s matched " | ||
746 | "'LocalPort %d' at line %d", | ||
747 | ci->laddress, port, line); | ||
748 | else | ||
749 | result = 0; | ||
682 | } else { | 750 | } else { |
683 | error("Unsupported Match attribute %s", attrib); | 751 | error("Unsupported Match attribute %s", attrib); |
684 | return -1; | 752 | return -1; |
685 | } | 753 | } |
686 | } | 754 | } |
687 | if (user != NULL) | 755 | if (ci != NULL) |
688 | debug3("match %sfound", result ? "" : "not "); | 756 | debug3("match %sfound", result ? "" : "not "); |
689 | *condition = cp; | 757 | *condition = cp; |
690 | return result; | 758 | return result; |
@@ -723,16 +791,17 @@ static const struct multistate multistate_gatewayports[] = { | |||
723 | { NULL, -1 } | 791 | { NULL, -1 } |
724 | }; | 792 | }; |
725 | static const struct multistate multistate_privsep[] = { | 793 | static const struct multistate multistate_privsep[] = { |
726 | { "sandbox", PRIVSEP_SANDBOX }, | 794 | { "yes", PRIVSEP_NOSANDBOX }, |
727 | { "yes", PRIVSEP_ON }, | 795 | { "sandbox", PRIVSEP_ON }, |
796 | { "nosandbox", PRIVSEP_NOSANDBOX }, | ||
728 | { "no", PRIVSEP_OFF }, | 797 | { "no", PRIVSEP_OFF }, |
729 | { NULL, -1 } | 798 | { NULL, -1 } |
730 | }; | 799 | }; |
731 | 800 | ||
732 | int | 801 | int |
733 | process_server_config_line(ServerOptions *options, char *line, | 802 | process_server_config_line(ServerOptions *options, char *line, |
734 | const char *filename, int linenum, int *activep, const char *user, | 803 | const char *filename, int linenum, int *activep, |
735 | const char *host, const char *address) | 804 | struct connection_info *connectinfo) |
736 | { | 805 | { |
737 | char *cp, **charptr, *arg, *p; | 806 | char *cp, **charptr, *arg, *p; |
738 | int cmdline = 0, *intptr, value, value2, n; | 807 | int cmdline = 0, *intptr, value, value2, n; |
@@ -763,7 +832,7 @@ process_server_config_line(ServerOptions *options, char *line, | |||
763 | if (*activep && opcode != sMatch) | 832 | if (*activep && opcode != sMatch) |
764 | debug3("%s:%d setting %s %s", filename, linenum, arg, cp); | 833 | debug3("%s:%d setting %s %s", filename, linenum, arg, cp); |
765 | if (*activep == 0 && !(flags & SSHCFG_MATCH)) { | 834 | if (*activep == 0 && !(flags & SSHCFG_MATCH)) { |
766 | if (user == NULL) { | 835 | if (connectinfo == NULL) { |
767 | fatal("%s line %d: Directive '%s' is not allowed " | 836 | fatal("%s line %d: Directive '%s' is not allowed " |
768 | "within a Match block", filename, linenum, arg); | 837 | "within a Match block", filename, linenum, arg); |
769 | } else { /* this is a directive we have already processed */ | 838 | } else { /* this is a directive we have already processed */ |
@@ -1113,6 +1182,8 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1113 | if (options->num_allow_users >= MAX_ALLOW_USERS) | 1182 | if (options->num_allow_users >= MAX_ALLOW_USERS) |
1114 | fatal("%s line %d: too many allow users.", | 1183 | fatal("%s line %d: too many allow users.", |
1115 | filename, linenum); | 1184 | filename, linenum); |
1185 | if (!*activep) | ||
1186 | continue; | ||
1116 | options->allow_users[options->num_allow_users++] = | 1187 | options->allow_users[options->num_allow_users++] = |
1117 | xstrdup(arg); | 1188 | xstrdup(arg); |
1118 | } | 1189 | } |
@@ -1123,6 +1194,8 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1123 | if (options->num_deny_users >= MAX_DENY_USERS) | 1194 | if (options->num_deny_users >= MAX_DENY_USERS) |
1124 | fatal("%s line %d: too many deny users.", | 1195 | fatal("%s line %d: too many deny users.", |
1125 | filename, linenum); | 1196 | filename, linenum); |
1197 | if (!*activep) | ||
1198 | continue; | ||
1126 | options->deny_users[options->num_deny_users++] = | 1199 | options->deny_users[options->num_deny_users++] = |
1127 | xstrdup(arg); | 1200 | xstrdup(arg); |
1128 | } | 1201 | } |
@@ -1133,6 +1206,8 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1133 | if (options->num_allow_groups >= MAX_ALLOW_GROUPS) | 1206 | if (options->num_allow_groups >= MAX_ALLOW_GROUPS) |
1134 | fatal("%s line %d: too many allow groups.", | 1207 | fatal("%s line %d: too many allow groups.", |
1135 | filename, linenum); | 1208 | filename, linenum); |
1209 | if (!*activep) | ||
1210 | continue; | ||
1136 | options->allow_groups[options->num_allow_groups++] = | 1211 | options->allow_groups[options->num_allow_groups++] = |
1137 | xstrdup(arg); | 1212 | xstrdup(arg); |
1138 | } | 1213 | } |
@@ -1143,7 +1218,10 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1143 | if (options->num_deny_groups >= MAX_DENY_GROUPS) | 1218 | if (options->num_deny_groups >= MAX_DENY_GROUPS) |
1144 | fatal("%s line %d: too many deny groups.", | 1219 | fatal("%s line %d: too many deny groups.", |
1145 | filename, linenum); | 1220 | filename, linenum); |
1146 | options->deny_groups[options->num_deny_groups++] = xstrdup(arg); | 1221 | if (!*activep) |
1222 | continue; | ||
1223 | options->deny_groups[options->num_deny_groups++] = | ||
1224 | xstrdup(arg); | ||
1147 | } | 1225 | } |
1148 | break; | 1226 | break; |
1149 | 1227 | ||
@@ -1317,7 +1395,7 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1317 | fatal("%s line %d: too many allow env.", | 1395 | fatal("%s line %d: too many allow env.", |
1318 | filename, linenum); | 1396 | filename, linenum); |
1319 | if (!*activep) | 1397 | if (!*activep) |
1320 | break; | 1398 | continue; |
1321 | options->accept_env[options->num_accept_env++] = | 1399 | options->accept_env[options->num_accept_env++] = |
1322 | xstrdup(arg); | 1400 | xstrdup(arg); |
1323 | } | 1401 | } |
@@ -1346,7 +1424,7 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1346 | if (cmdline) | 1424 | if (cmdline) |
1347 | fatal("Match directive not supported as a command-line " | 1425 | fatal("Match directive not supported as a command-line " |
1348 | "option"); | 1426 | "option"); |
1349 | value = match_cfg_line(&cp, linenum, user, host, address); | 1427 | value = match_cfg_line(&cp, linenum, connectinfo); |
1350 | if (value < 0) | 1428 | if (value < 0) |
1351 | fatal("%s line %d: Bad Match condition", filename, | 1429 | fatal("%s line %d: Bad Match condition", filename, |
1352 | linenum); | 1430 | linenum); |
@@ -1366,6 +1444,14 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1366 | } | 1444 | } |
1367 | break; | 1445 | break; |
1368 | } | 1446 | } |
1447 | if (strcmp(arg, "none") == 0) { | ||
1448 | if (*activep && n == -1) { | ||
1449 | channel_clear_adm_permitted_opens(); | ||
1450 | options->num_permitted_opens = 1; | ||
1451 | channel_disable_adm_local_opens(); | ||
1452 | } | ||
1453 | break; | ||
1454 | } | ||
1369 | if (*activep && n == -1) | 1455 | if (*activep && n == -1) |
1370 | channel_clear_adm_permitted_opens(); | 1456 | channel_clear_adm_permitted_opens(); |
1371 | for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) { | 1457 | for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) { |
@@ -1428,6 +1514,22 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1428 | } | 1514 | } |
1429 | break; | 1515 | break; |
1430 | 1516 | ||
1517 | case sVersionAddendum: | ||
1518 | if (cp == NULL) | ||
1519 | fatal("%.200s line %d: Missing argument.", filename, | ||
1520 | linenum); | ||
1521 | len = strspn(cp, WHITESPACE); | ||
1522 | if (*activep && options->version_addendum == NULL) { | ||
1523 | if (strcasecmp(cp + len, "none") == 0) | ||
1524 | options->version_addendum = xstrdup(""); | ||
1525 | else if (strchr(cp + len, '\r') != NULL) | ||
1526 | fatal("%.200s line %d: Invalid argument", | ||
1527 | filename, linenum); | ||
1528 | else | ||
1529 | options->version_addendum = xstrdup(cp + len); | ||
1530 | } | ||
1531 | return 0; | ||
1532 | |||
1431 | case sDeprecated: | 1533 | case sDeprecated: |
1432 | logit("%s line %d: Deprecated option %s", | 1534 | logit("%s line %d: Deprecated option %s", |
1433 | filename, linenum, arg); | 1535 | filename, linenum, arg); |
@@ -1457,8 +1559,9 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1457 | void | 1559 | void |
1458 | load_server_config(const char *filename, Buffer *conf) | 1560 | load_server_config(const char *filename, Buffer *conf) |
1459 | { | 1561 | { |
1460 | char line[1024], *cp; | 1562 | char line[4096], *cp; |
1461 | FILE *f; | 1563 | FILE *f; |
1564 | int lineno = 0; | ||
1462 | 1565 | ||
1463 | debug2("%s: filename %s", __func__, filename); | 1566 | debug2("%s: filename %s", __func__, filename); |
1464 | if ((f = fopen(filename, "r")) == NULL) { | 1567 | if ((f = fopen(filename, "r")) == NULL) { |
@@ -1467,6 +1570,9 @@ load_server_config(const char *filename, Buffer *conf) | |||
1467 | } | 1570 | } |
1468 | buffer_clear(conf); | 1571 | buffer_clear(conf); |
1469 | while (fgets(line, sizeof(line), f)) { | 1572 | while (fgets(line, sizeof(line), f)) { |
1573 | lineno++; | ||
1574 | if (strlen(line) == sizeof(line) - 1) | ||
1575 | fatal("%s line %d too long", filename, lineno); | ||
1470 | /* | 1576 | /* |
1471 | * Trim out comments and strip whitespace | 1577 | * Trim out comments and strip whitespace |
1472 | * NB - preserve newlines, they are needed to reproduce | 1578 | * NB - preserve newlines, they are needed to reproduce |
@@ -1484,16 +1590,58 @@ load_server_config(const char *filename, Buffer *conf) | |||
1484 | } | 1590 | } |
1485 | 1591 | ||
1486 | void | 1592 | void |
1487 | parse_server_match_config(ServerOptions *options, const char *user, | 1593 | parse_server_match_config(ServerOptions *options, |
1488 | const char *host, const char *address) | 1594 | struct connection_info *connectinfo) |
1489 | { | 1595 | { |
1490 | ServerOptions mo; | 1596 | ServerOptions mo; |
1491 | 1597 | ||
1492 | initialize_server_options(&mo); | 1598 | initialize_server_options(&mo); |
1493 | parse_server_config(&mo, "reprocess config", &cfg, user, host, address); | 1599 | parse_server_config(&mo, "reprocess config", &cfg, connectinfo); |
1494 | copy_set_server_options(options, &mo, 0); | 1600 | copy_set_server_options(options, &mo, 0); |
1495 | } | 1601 | } |
1496 | 1602 | ||
1603 | int parse_server_match_testspec(struct connection_info *ci, char *spec) | ||
1604 | { | ||
1605 | char *p; | ||
1606 | |||
1607 | while ((p = strsep(&spec, ",")) && *p != '\0') { | ||
1608 | if (strncmp(p, "addr=", 5) == 0) { | ||
1609 | ci->address = xstrdup(p + 5); | ||
1610 | } else if (strncmp(p, "host=", 5) == 0) { | ||
1611 | ci->host = xstrdup(p + 5); | ||
1612 | } else if (strncmp(p, "user=", 5) == 0) { | ||
1613 | ci->user = xstrdup(p + 5); | ||
1614 | } else if (strncmp(p, "laddr=", 6) == 0) { | ||
1615 | ci->laddress = xstrdup(p + 6); | ||
1616 | } else if (strncmp(p, "lport=", 6) == 0) { | ||
1617 | ci->lport = a2port(p + 6); | ||
1618 | if (ci->lport == -1) { | ||
1619 | fprintf(stderr, "Invalid port '%s' in test mode" | ||
1620 | " specification %s\n", p+6, p); | ||
1621 | return -1; | ||
1622 | } | ||
1623 | } else { | ||
1624 | fprintf(stderr, "Invalid test mode specification %s\n", | ||
1625 | p); | ||
1626 | return -1; | ||
1627 | } | ||
1628 | } | ||
1629 | return 0; | ||
1630 | } | ||
1631 | |||
1632 | /* | ||
1633 | * returns 1 for a complete spec, 0 for partial spec and -1 for an | ||
1634 | * empty spec. | ||
1635 | */ | ||
1636 | int server_match_spec_complete(struct connection_info *ci) | ||
1637 | { | ||
1638 | if (ci->user && ci->host && ci->address) | ||
1639 | return 1; /* complete */ | ||
1640 | if (!ci->user && !ci->host && !ci->address) | ||
1641 | return -1; /* empty */ | ||
1642 | return 0; /* partial */ | ||
1643 | } | ||
1644 | |||
1497 | /* Helper macros */ | 1645 | /* Helper macros */ |
1498 | #define M_CP_INTOPT(n) do {\ | 1646 | #define M_CP_INTOPT(n) do {\ |
1499 | if (src->n != -1) \ | 1647 | if (src->n != -1) \ |
@@ -1567,7 +1715,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) | |||
1567 | 1715 | ||
1568 | void | 1716 | void |
1569 | parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, | 1717 | parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, |
1570 | const char *user, const char *host, const char *address) | 1718 | struct connection_info *connectinfo) |
1571 | { | 1719 | { |
1572 | int active, linenum, bad_options = 0; | 1720 | int active, linenum, bad_options = 0; |
1573 | char *cp, *obuf, *cbuf; | 1721 | char *cp, *obuf, *cbuf; |
@@ -1575,11 +1723,11 @@ parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, | |||
1575 | debug2("%s: config %s len %d", __func__, filename, buffer_len(conf)); | 1723 | debug2("%s: config %s len %d", __func__, filename, buffer_len(conf)); |
1576 | 1724 | ||
1577 | obuf = cbuf = xstrdup(buffer_ptr(conf)); | 1725 | obuf = cbuf = xstrdup(buffer_ptr(conf)); |
1578 | active = user ? 0 : 1; | 1726 | active = connectinfo ? 0 : 1; |
1579 | linenum = 1; | 1727 | linenum = 1; |
1580 | while ((cp = strsep(&cbuf, "\n")) != NULL) { | 1728 | while ((cp = strsep(&cbuf, "\n")) != NULL) { |
1581 | if (process_server_config_line(options, cp, filename, | 1729 | if (process_server_config_line(options, cp, filename, |
1582 | linenum++, &active, user, host, address) != 0) | 1730 | linenum++, &active, connectinfo) != 0) |
1583 | bad_options++; | 1731 | bad_options++; |
1584 | } | 1732 | } |
1585 | xfree(obuf); | 1733 | xfree(obuf); |
@@ -1794,6 +1942,7 @@ dump_config(ServerOptions *o) | |||
1794 | dump_cfg_string(sRevokedKeys, o->revoked_keys_file); | 1942 | dump_cfg_string(sRevokedKeys, o->revoked_keys_file); |
1795 | dump_cfg_string(sAuthorizedPrincipalsFile, | 1943 | dump_cfg_string(sAuthorizedPrincipalsFile, |
1796 | o->authorized_principals_file); | 1944 | o->authorized_principals_file); |
1945 | dump_cfg_string(sVersionAddendum, o->version_addendum); | ||
1797 | 1946 | ||
1798 | /* string arguments requiring a lookup */ | 1947 | /* string arguments requiring a lookup */ |
1799 | dump_cfg_string(sLogLevel, log_level_name(o->log_level)); | 1948 | dump_cfg_string(sLogLevel, log_level_name(o->log_level)); |