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 5b3f6f50b..5b8c686c2 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); |
@@ -142,6 +145,7 @@ initialize_server_options(ServerOptions *options) | |||
142 | options->authorized_principals_file = NULL; | 145 | options->authorized_principals_file = NULL; |
143 | options->ip_qos_interactive = -1; | 146 | options->ip_qos_interactive = -1; |
144 | options->ip_qos_bulk = -1; | 147 | options->ip_qos_bulk = -1; |
148 | options->version_addendum = NULL; | ||
145 | options->debian_banner = -1; | 149 | options->debian_banner = -1; |
146 | } | 150 | } |
147 | 151 | ||
@@ -290,12 +294,13 @@ fill_default_server_options(ServerOptions *options) | |||
290 | options->ip_qos_interactive = IPTOS_LOWDELAY; | 294 | options->ip_qos_interactive = IPTOS_LOWDELAY; |
291 | if (options->ip_qos_bulk == -1) | 295 | if (options->ip_qos_bulk == -1) |
292 | options->ip_qos_bulk = IPTOS_THROUGHPUT; | 296 | options->ip_qos_bulk = IPTOS_THROUGHPUT; |
297 | if (options->version_addendum == NULL) | ||
298 | options->version_addendum = xstrdup(""); | ||
293 | if (options->debian_banner == -1) | 299 | if (options->debian_banner == -1) |
294 | options->debian_banner = 1; | 300 | options->debian_banner = 1; |
295 | |||
296 | /* Turn privilege separation on by default */ | 301 | /* Turn privilege separation on by default */ |
297 | if (use_privsep == -1) | 302 | if (use_privsep == -1) |
298 | use_privsep = PRIVSEP_ON; | 303 | use_privsep = PRIVSEP_NOSANDBOX; |
299 | 304 | ||
300 | #ifndef HAVE_MMAP | 305 | #ifndef HAVE_MMAP |
301 | if (use_privsep && options->compression == 1) { | 306 | if (use_privsep && options->compression == 1) { |
@@ -340,7 +345,7 @@ typedef enum { | |||
340 | sUsePrivilegeSeparation, sAllowAgentForwarding, | 345 | sUsePrivilegeSeparation, sAllowAgentForwarding, |
341 | sZeroKnowledgePasswordAuthentication, sHostCertificate, | 346 | sZeroKnowledgePasswordAuthentication, sHostCertificate, |
342 | sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, | 347 | sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, |
343 | sKexAlgorithms, sIPQoS, | 348 | sKexAlgorithms, sIPQoS, sVersionAddendum, |
344 | sDebianBanner, | 349 | sDebianBanner, |
345 | sDeprecated, sUnsupported | 350 | sDeprecated, sUnsupported |
346 | } ServerOpCodes; | 351 | } ServerOpCodes; |
@@ -444,10 +449,10 @@ static struct { | |||
444 | { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */ | 449 | { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */ |
445 | { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL }, | 450 | { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL }, |
446 | { "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL }, | 451 | { "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL }, |
447 | { "allowusers", sAllowUsers, SSHCFG_GLOBAL }, | 452 | { "allowusers", sAllowUsers, SSHCFG_ALL }, |
448 | { "denyusers", sDenyUsers, SSHCFG_GLOBAL }, | 453 | { "denyusers", sDenyUsers, SSHCFG_ALL }, |
449 | { "allowgroups", sAllowGroups, SSHCFG_GLOBAL }, | 454 | { "allowgroups", sAllowGroups, SSHCFG_ALL }, |
450 | { "denygroups", sDenyGroups, SSHCFG_GLOBAL }, | 455 | { "denygroups", sDenyGroups, SSHCFG_ALL }, |
451 | { "ciphers", sCiphers, SSHCFG_GLOBAL }, | 456 | { "ciphers", sCiphers, SSHCFG_GLOBAL }, |
452 | { "macs", sMacs, SSHCFG_GLOBAL }, | 457 | { "macs", sMacs, SSHCFG_GLOBAL }, |
453 | { "protocol", sProtocol, SSHCFG_GLOBAL }, | 458 | { "protocol", sProtocol, SSHCFG_GLOBAL }, |
@@ -465,7 +470,7 @@ static struct { | |||
465 | { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL }, | 470 | { "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_ALL }, |
466 | { "authorizedkeysfile2", sDeprecated, SSHCFG_ALL }, | 471 | { "authorizedkeysfile2", sDeprecated, SSHCFG_ALL }, |
467 | { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL}, | 472 | { "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL}, |
468 | { "acceptenv", sAcceptEnv, SSHCFG_GLOBAL }, | 473 | { "acceptenv", sAcceptEnv, SSHCFG_ALL }, |
469 | { "permittunnel", sPermitTunnel, SSHCFG_ALL }, | 474 | { "permittunnel", sPermitTunnel, SSHCFG_ALL }, |
470 | { "match", sMatch, SSHCFG_ALL }, | 475 | { "match", sMatch, SSHCFG_ALL }, |
471 | { "permitopen", sPermitOpen, SSHCFG_ALL }, | 476 | { "permitopen", sPermitOpen, SSHCFG_ALL }, |
@@ -477,6 +482,7 @@ static struct { | |||
477 | { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, | 482 | { "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, |
478 | { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, | 483 | { "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, |
479 | { "ipqos", sIPQoS, SSHCFG_ALL }, | 484 | { "ipqos", sIPQoS, SSHCFG_ALL }, |
485 | { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, | ||
480 | { "debianbanner", sDebianBanner, SSHCFG_GLOBAL }, | 486 | { "debianbanner", sDebianBanner, SSHCFG_GLOBAL }, |
481 | { NULL, sBadOption, 0 } | 487 | { NULL, sBadOption, 0 } |
482 | }; | 488 | }; |
@@ -566,6 +572,20 @@ add_one_listen_addr(ServerOptions *options, char *addr, int port) | |||
566 | options->listen_addrs = aitop; | 572 | options->listen_addrs = aitop; |
567 | } | 573 | } |
568 | 574 | ||
575 | struct connection_info * | ||
576 | get_connection_info(int populate, int use_dns) | ||
577 | { | ||
578 | static struct connection_info ci; | ||
579 | |||
580 | if (!populate) | ||
581 | return &ci; | ||
582 | ci.host = get_canonical_hostname(use_dns); | ||
583 | ci.address = get_remote_ipaddr(); | ||
584 | ci.laddress = get_local_ipaddr(packet_get_connection_in()); | ||
585 | ci.lport = get_local_port(); | ||
586 | return &ci; | ||
587 | } | ||
588 | |||
569 | /* | 589 | /* |
570 | * The strategy for the Match blocks is that the config file is parsed twice. | 590 | * The strategy for the Match blocks is that the config file is parsed twice. |
571 | * | 591 | * |
@@ -627,20 +647,25 @@ out: | |||
627 | return result; | 647 | return result; |
628 | } | 648 | } |
629 | 649 | ||
650 | /* | ||
651 | * All of the attributes on a single Match line are ANDed together, so we need to check every | ||
652 | * attribute and set the result to zero if any attribute does not match. | ||
653 | */ | ||
630 | static int | 654 | static int |
631 | match_cfg_line(char **condition, int line, const char *user, const char *host, | 655 | match_cfg_line(char **condition, int line, struct connection_info *ci) |
632 | const char *address) | ||
633 | { | 656 | { |
634 | int result = 1; | 657 | int result = 1, port; |
635 | char *arg, *attrib, *cp = *condition; | 658 | char *arg, *attrib, *cp = *condition; |
636 | size_t len; | 659 | size_t len; |
637 | 660 | ||
638 | if (user == NULL) | 661 | if (ci == NULL) |
639 | debug3("checking syntax for 'Match %s'", cp); | 662 | debug3("checking syntax for 'Match %s'", cp); |
640 | else | 663 | else |
641 | debug3("checking match for '%s' user %s host %s addr %s", cp, | 664 | debug3("checking match for '%s' user %s host %s addr %s " |
642 | user ? user : "(null)", host ? host : "(null)", | 665 | "laddr %s lport %d", cp, ci->user ? ci->user : "(null)", |
643 | address ? address : "(null)"); | 666 | ci->host ? ci->host : "(null)", |
667 | ci->address ? ci->address : "(null)", | ||
668 | ci->laddress ? ci->laddress : "(null)", ci->lport); | ||
644 | 669 | ||
645 | while ((attrib = strdelim(&cp)) && *attrib != '\0') { | 670 | while ((attrib = strdelim(&cp)) && *attrib != '\0') { |
646 | if ((arg = strdelim(&cp)) == NULL || *arg == '\0') { | 671 | if ((arg = strdelim(&cp)) == NULL || *arg == '\0') { |
@@ -649,37 +674,45 @@ match_cfg_line(char **condition, int line, const char *user, const char *host, | |||
649 | } | 674 | } |
650 | len = strlen(arg); | 675 | len = strlen(arg); |
651 | if (strcasecmp(attrib, "user") == 0) { | 676 | if (strcasecmp(attrib, "user") == 0) { |
652 | if (!user) { | 677 | if (ci == NULL || ci->user == NULL) { |
653 | result = 0; | 678 | result = 0; |
654 | continue; | 679 | continue; |
655 | } | 680 | } |
656 | if (match_pattern_list(user, arg, len, 0) != 1) | 681 | if (match_pattern_list(ci->user, arg, len, 0) != 1) |
657 | result = 0; | 682 | result = 0; |
658 | else | 683 | else |
659 | debug("user %.100s matched 'User %.100s' at " | 684 | debug("user %.100s matched 'User %.100s' at " |
660 | "line %d", user, arg, line); | 685 | "line %d", ci->user, arg, line); |
661 | } else if (strcasecmp(attrib, "group") == 0) { | 686 | } else if (strcasecmp(attrib, "group") == 0) { |
662 | switch (match_cfg_line_group(arg, line, user)) { | 687 | if (ci == NULL || ci->user == NULL) { |
688 | result = 0; | ||
689 | continue; | ||
690 | } | ||
691 | switch (match_cfg_line_group(arg, line, ci->user)) { | ||
663 | case -1: | 692 | case -1: |
664 | return -1; | 693 | return -1; |
665 | case 0: | 694 | case 0: |
666 | result = 0; | 695 | result = 0; |
667 | } | 696 | } |
668 | } else if (strcasecmp(attrib, "host") == 0) { | 697 | } else if (strcasecmp(attrib, "host") == 0) { |
669 | if (!host) { | 698 | if (ci == NULL || ci->host == NULL) { |
670 | result = 0; | 699 | result = 0; |
671 | continue; | 700 | continue; |
672 | } | 701 | } |
673 | if (match_hostname(host, arg, len) != 1) | 702 | if (match_hostname(ci->host, arg, len) != 1) |
674 | result = 0; | 703 | result = 0; |
675 | else | 704 | else |
676 | debug("connection from %.100s matched 'Host " | 705 | debug("connection from %.100s matched 'Host " |
677 | "%.100s' at line %d", host, arg, line); | 706 | "%.100s' at line %d", ci->host, arg, line); |
678 | } else if (strcasecmp(attrib, "address") == 0) { | 707 | } else if (strcasecmp(attrib, "address") == 0) { |
679 | switch (addr_match_list(address, arg)) { | 708 | if (ci == NULL || ci->address == NULL) { |
709 | result = 0; | ||
710 | continue; | ||
711 | } | ||
712 | switch (addr_match_list(ci->address, arg)) { | ||
680 | case 1: | 713 | case 1: |
681 | debug("connection from %.100s matched 'Address " | 714 | debug("connection from %.100s matched 'Address " |
682 | "%.100s' at line %d", address, arg, line); | 715 | "%.100s' at line %d", ci->address, arg, line); |
683 | break; | 716 | break; |
684 | case 0: | 717 | case 0: |
685 | case -1: | 718 | case -1: |
@@ -688,12 +721,47 @@ match_cfg_line(char **condition, int line, const char *user, const char *host, | |||
688 | case -2: | 721 | case -2: |
689 | return -1; | 722 | return -1; |
690 | } | 723 | } |
724 | } else if (strcasecmp(attrib, "localaddress") == 0){ | ||
725 | if (ci == NULL || ci->laddress == NULL) { | ||
726 | result = 0; | ||
727 | continue; | ||
728 | } | ||
729 | switch (addr_match_list(ci->laddress, arg)) { | ||
730 | case 1: | ||
731 | debug("connection from %.100s matched " | ||
732 | "'LocalAddress %.100s' at line %d", | ||
733 | ci->laddress, arg, line); | ||
734 | break; | ||
735 | case 0: | ||
736 | case -1: | ||
737 | result = 0; | ||
738 | break; | ||
739 | case -2: | ||
740 | return -1; | ||
741 | } | ||
742 | } else if (strcasecmp(attrib, "localport") == 0) { | ||
743 | if ((port = a2port(arg)) == -1) { | ||
744 | error("Invalid LocalPort '%s' on Match line", | ||
745 | arg); | ||
746 | return -1; | ||
747 | } | ||
748 | if (ci == NULL || ci->lport == 0) { | ||
749 | result = 0; | ||
750 | continue; | ||
751 | } | ||
752 | /* TODO support port lists */ | ||
753 | if (port == ci->lport) | ||
754 | debug("connection from %.100s matched " | ||
755 | "'LocalPort %d' at line %d", | ||
756 | ci->laddress, port, line); | ||
757 | else | ||
758 | result = 0; | ||
691 | } else { | 759 | } else { |
692 | error("Unsupported Match attribute %s", attrib); | 760 | error("Unsupported Match attribute %s", attrib); |
693 | return -1; | 761 | return -1; |
694 | } | 762 | } |
695 | } | 763 | } |
696 | if (user != NULL) | 764 | if (ci != NULL) |
697 | debug3("match %sfound", result ? "" : "not "); | 765 | debug3("match %sfound", result ? "" : "not "); |
698 | *condition = cp; | 766 | *condition = cp; |
699 | return result; | 767 | return result; |
@@ -732,16 +800,17 @@ static const struct multistate multistate_gatewayports[] = { | |||
732 | { NULL, -1 } | 800 | { NULL, -1 } |
733 | }; | 801 | }; |
734 | static const struct multistate multistate_privsep[] = { | 802 | static const struct multistate multistate_privsep[] = { |
735 | { "sandbox", PRIVSEP_SANDBOX }, | 803 | { "yes", PRIVSEP_NOSANDBOX }, |
736 | { "yes", PRIVSEP_ON }, | 804 | { "sandbox", PRIVSEP_ON }, |
805 | { "nosandbox", PRIVSEP_NOSANDBOX }, | ||
737 | { "no", PRIVSEP_OFF }, | 806 | { "no", PRIVSEP_OFF }, |
738 | { NULL, -1 } | 807 | { NULL, -1 } |
739 | }; | 808 | }; |
740 | 809 | ||
741 | int | 810 | int |
742 | process_server_config_line(ServerOptions *options, char *line, | 811 | process_server_config_line(ServerOptions *options, char *line, |
743 | const char *filename, int linenum, int *activep, const char *user, | 812 | const char *filename, int linenum, int *activep, |
744 | const char *host, const char *address) | 813 | struct connection_info *connectinfo) |
745 | { | 814 | { |
746 | char *cp, **charptr, *arg, *p; | 815 | char *cp, **charptr, *arg, *p; |
747 | int cmdline = 0, *intptr, value, value2, n; | 816 | int cmdline = 0, *intptr, value, value2, n; |
@@ -772,7 +841,7 @@ process_server_config_line(ServerOptions *options, char *line, | |||
772 | if (*activep && opcode != sMatch) | 841 | if (*activep && opcode != sMatch) |
773 | debug3("%s:%d setting %s %s", filename, linenum, arg, cp); | 842 | debug3("%s:%d setting %s %s", filename, linenum, arg, cp); |
774 | if (*activep == 0 && !(flags & SSHCFG_MATCH)) { | 843 | if (*activep == 0 && !(flags & SSHCFG_MATCH)) { |
775 | if (user == NULL) { | 844 | if (connectinfo == NULL) { |
776 | fatal("%s line %d: Directive '%s' is not allowed " | 845 | fatal("%s line %d: Directive '%s' is not allowed " |
777 | "within a Match block", filename, linenum, arg); | 846 | "within a Match block", filename, linenum, arg); |
778 | } else { /* this is a directive we have already processed */ | 847 | } else { /* this is a directive we have already processed */ |
@@ -1126,6 +1195,8 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1126 | if (options->num_allow_users >= MAX_ALLOW_USERS) | 1195 | if (options->num_allow_users >= MAX_ALLOW_USERS) |
1127 | fatal("%s line %d: too many allow users.", | 1196 | fatal("%s line %d: too many allow users.", |
1128 | filename, linenum); | 1197 | filename, linenum); |
1198 | if (!*activep) | ||
1199 | continue; | ||
1129 | options->allow_users[options->num_allow_users++] = | 1200 | options->allow_users[options->num_allow_users++] = |
1130 | xstrdup(arg); | 1201 | xstrdup(arg); |
1131 | } | 1202 | } |
@@ -1136,6 +1207,8 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1136 | if (options->num_deny_users >= MAX_DENY_USERS) | 1207 | if (options->num_deny_users >= MAX_DENY_USERS) |
1137 | fatal("%s line %d: too many deny users.", | 1208 | fatal("%s line %d: too many deny users.", |
1138 | filename, linenum); | 1209 | filename, linenum); |
1210 | if (!*activep) | ||
1211 | continue; | ||
1139 | options->deny_users[options->num_deny_users++] = | 1212 | options->deny_users[options->num_deny_users++] = |
1140 | xstrdup(arg); | 1213 | xstrdup(arg); |
1141 | } | 1214 | } |
@@ -1146,6 +1219,8 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1146 | if (options->num_allow_groups >= MAX_ALLOW_GROUPS) | 1219 | if (options->num_allow_groups >= MAX_ALLOW_GROUPS) |
1147 | fatal("%s line %d: too many allow groups.", | 1220 | fatal("%s line %d: too many allow groups.", |
1148 | filename, linenum); | 1221 | filename, linenum); |
1222 | if (!*activep) | ||
1223 | continue; | ||
1149 | options->allow_groups[options->num_allow_groups++] = | 1224 | options->allow_groups[options->num_allow_groups++] = |
1150 | xstrdup(arg); | 1225 | xstrdup(arg); |
1151 | } | 1226 | } |
@@ -1156,7 +1231,10 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1156 | if (options->num_deny_groups >= MAX_DENY_GROUPS) | 1231 | if (options->num_deny_groups >= MAX_DENY_GROUPS) |
1157 | fatal("%s line %d: too many deny groups.", | 1232 | fatal("%s line %d: too many deny groups.", |
1158 | filename, linenum); | 1233 | filename, linenum); |
1159 | options->deny_groups[options->num_deny_groups++] = xstrdup(arg); | 1234 | if (!*activep) |
1235 | continue; | ||
1236 | options->deny_groups[options->num_deny_groups++] = | ||
1237 | xstrdup(arg); | ||
1160 | } | 1238 | } |
1161 | break; | 1239 | break; |
1162 | 1240 | ||
@@ -1330,7 +1408,7 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1330 | fatal("%s line %d: too many allow env.", | 1408 | fatal("%s line %d: too many allow env.", |
1331 | filename, linenum); | 1409 | filename, linenum); |
1332 | if (!*activep) | 1410 | if (!*activep) |
1333 | break; | 1411 | continue; |
1334 | options->accept_env[options->num_accept_env++] = | 1412 | options->accept_env[options->num_accept_env++] = |
1335 | xstrdup(arg); | 1413 | xstrdup(arg); |
1336 | } | 1414 | } |
@@ -1359,7 +1437,7 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1359 | if (cmdline) | 1437 | if (cmdline) |
1360 | fatal("Match directive not supported as a command-line " | 1438 | fatal("Match directive not supported as a command-line " |
1361 | "option"); | 1439 | "option"); |
1362 | value = match_cfg_line(&cp, linenum, user, host, address); | 1440 | value = match_cfg_line(&cp, linenum, connectinfo); |
1363 | if (value < 0) | 1441 | if (value < 0) |
1364 | fatal("%s line %d: Bad Match condition", filename, | 1442 | fatal("%s line %d: Bad Match condition", filename, |
1365 | linenum); | 1443 | linenum); |
@@ -1379,6 +1457,14 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1379 | } | 1457 | } |
1380 | break; | 1458 | break; |
1381 | } | 1459 | } |
1460 | if (strcmp(arg, "none") == 0) { | ||
1461 | if (*activep && n == -1) { | ||
1462 | channel_clear_adm_permitted_opens(); | ||
1463 | options->num_permitted_opens = 1; | ||
1464 | channel_disable_adm_local_opens(); | ||
1465 | } | ||
1466 | break; | ||
1467 | } | ||
1382 | if (*activep && n == -1) | 1468 | if (*activep && n == -1) |
1383 | channel_clear_adm_permitted_opens(); | 1469 | channel_clear_adm_permitted_opens(); |
1384 | for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) { | 1470 | for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) { |
@@ -1441,6 +1527,22 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1441 | } | 1527 | } |
1442 | break; | 1528 | break; |
1443 | 1529 | ||
1530 | case sVersionAddendum: | ||
1531 | if (cp == NULL) | ||
1532 | fatal("%.200s line %d: Missing argument.", filename, | ||
1533 | linenum); | ||
1534 | len = strspn(cp, WHITESPACE); | ||
1535 | if (*activep && options->version_addendum == NULL) { | ||
1536 | if (strcasecmp(cp + len, "none") == 0) | ||
1537 | options->version_addendum = xstrdup(""); | ||
1538 | else if (strchr(cp + len, '\r') != NULL) | ||
1539 | fatal("%.200s line %d: Invalid argument", | ||
1540 | filename, linenum); | ||
1541 | else | ||
1542 | options->version_addendum = xstrdup(cp + len); | ||
1543 | } | ||
1544 | return 0; | ||
1545 | |||
1444 | case sDebianBanner: | 1546 | case sDebianBanner: |
1445 | intptr = &options->debian_banner; | 1547 | intptr = &options->debian_banner; |
1446 | goto parse_int; | 1548 | goto parse_int; |
@@ -1474,8 +1576,9 @@ process_server_config_line(ServerOptions *options, char *line, | |||
1474 | void | 1576 | void |
1475 | load_server_config(const char *filename, Buffer *conf) | 1577 | load_server_config(const char *filename, Buffer *conf) |
1476 | { | 1578 | { |
1477 | char line[1024], *cp; | 1579 | char line[4096], *cp; |
1478 | FILE *f; | 1580 | FILE *f; |
1581 | int lineno = 0; | ||
1479 | 1582 | ||
1480 | debug2("%s: filename %s", __func__, filename); | 1583 | debug2("%s: filename %s", __func__, filename); |
1481 | if ((f = fopen(filename, "r")) == NULL) { | 1584 | if ((f = fopen(filename, "r")) == NULL) { |
@@ -1484,6 +1587,9 @@ load_server_config(const char *filename, Buffer *conf) | |||
1484 | } | 1587 | } |
1485 | buffer_clear(conf); | 1588 | buffer_clear(conf); |
1486 | while (fgets(line, sizeof(line), f)) { | 1589 | while (fgets(line, sizeof(line), f)) { |
1590 | lineno++; | ||
1591 | if (strlen(line) == sizeof(line) - 1) | ||
1592 | fatal("%s line %d too long", filename, lineno); | ||
1487 | /* | 1593 | /* |
1488 | * Trim out comments and strip whitespace | 1594 | * Trim out comments and strip whitespace |
1489 | * NB - preserve newlines, they are needed to reproduce | 1595 | * NB - preserve newlines, they are needed to reproduce |
@@ -1501,16 +1607,58 @@ load_server_config(const char *filename, Buffer *conf) | |||
1501 | } | 1607 | } |
1502 | 1608 | ||
1503 | void | 1609 | void |
1504 | parse_server_match_config(ServerOptions *options, const char *user, | 1610 | parse_server_match_config(ServerOptions *options, |
1505 | const char *host, const char *address) | 1611 | struct connection_info *connectinfo) |
1506 | { | 1612 | { |
1507 | ServerOptions mo; | 1613 | ServerOptions mo; |
1508 | 1614 | ||
1509 | initialize_server_options(&mo); | 1615 | initialize_server_options(&mo); |
1510 | parse_server_config(&mo, "reprocess config", &cfg, user, host, address); | 1616 | parse_server_config(&mo, "reprocess config", &cfg, connectinfo); |
1511 | copy_set_server_options(options, &mo, 0); | 1617 | copy_set_server_options(options, &mo, 0); |
1512 | } | 1618 | } |
1513 | 1619 | ||
1620 | int parse_server_match_testspec(struct connection_info *ci, char *spec) | ||
1621 | { | ||
1622 | char *p; | ||
1623 | |||
1624 | while ((p = strsep(&spec, ",")) && *p != '\0') { | ||
1625 | if (strncmp(p, "addr=", 5) == 0) { | ||
1626 | ci->address = xstrdup(p + 5); | ||
1627 | } else if (strncmp(p, "host=", 5) == 0) { | ||
1628 | ci->host = xstrdup(p + 5); | ||
1629 | } else if (strncmp(p, "user=", 5) == 0) { | ||
1630 | ci->user = xstrdup(p + 5); | ||
1631 | } else if (strncmp(p, "laddr=", 6) == 0) { | ||
1632 | ci->laddress = xstrdup(p + 6); | ||
1633 | } else if (strncmp(p, "lport=", 6) == 0) { | ||
1634 | ci->lport = a2port(p + 6); | ||
1635 | if (ci->lport == -1) { | ||
1636 | fprintf(stderr, "Invalid port '%s' in test mode" | ||
1637 | " specification %s\n", p+6, p); | ||
1638 | return -1; | ||
1639 | } | ||
1640 | } else { | ||
1641 | fprintf(stderr, "Invalid test mode specification %s\n", | ||
1642 | p); | ||
1643 | return -1; | ||
1644 | } | ||
1645 | } | ||
1646 | return 0; | ||
1647 | } | ||
1648 | |||
1649 | /* | ||
1650 | * returns 1 for a complete spec, 0 for partial spec and -1 for an | ||
1651 | * empty spec. | ||
1652 | */ | ||
1653 | int server_match_spec_complete(struct connection_info *ci) | ||
1654 | { | ||
1655 | if (ci->user && ci->host && ci->address) | ||
1656 | return 1; /* complete */ | ||
1657 | if (!ci->user && !ci->host && !ci->address) | ||
1658 | return -1; /* empty */ | ||
1659 | return 0; /* partial */ | ||
1660 | } | ||
1661 | |||
1514 | /* Helper macros */ | 1662 | /* Helper macros */ |
1515 | #define M_CP_INTOPT(n) do {\ | 1663 | #define M_CP_INTOPT(n) do {\ |
1516 | if (src->n != -1) \ | 1664 | if (src->n != -1) \ |
@@ -1584,7 +1732,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) | |||
1584 | 1732 | ||
1585 | void | 1733 | void |
1586 | parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, | 1734 | parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, |
1587 | const char *user, const char *host, const char *address) | 1735 | struct connection_info *connectinfo) |
1588 | { | 1736 | { |
1589 | int active, linenum, bad_options = 0; | 1737 | int active, linenum, bad_options = 0; |
1590 | char *cp, *obuf, *cbuf; | 1738 | char *cp, *obuf, *cbuf; |
@@ -1592,11 +1740,11 @@ parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, | |||
1592 | debug2("%s: config %s len %d", __func__, filename, buffer_len(conf)); | 1740 | debug2("%s: config %s len %d", __func__, filename, buffer_len(conf)); |
1593 | 1741 | ||
1594 | obuf = cbuf = xstrdup(buffer_ptr(conf)); | 1742 | obuf = cbuf = xstrdup(buffer_ptr(conf)); |
1595 | active = user ? 0 : 1; | 1743 | active = connectinfo ? 0 : 1; |
1596 | linenum = 1; | 1744 | linenum = 1; |
1597 | while ((cp = strsep(&cbuf, "\n")) != NULL) { | 1745 | while ((cp = strsep(&cbuf, "\n")) != NULL) { |
1598 | if (process_server_config_line(options, cp, filename, | 1746 | if (process_server_config_line(options, cp, filename, |
1599 | linenum++, &active, user, host, address) != 0) | 1747 | linenum++, &active, connectinfo) != 0) |
1600 | bad_options++; | 1748 | bad_options++; |
1601 | } | 1749 | } |
1602 | xfree(obuf); | 1750 | xfree(obuf); |
@@ -1812,6 +1960,7 @@ dump_config(ServerOptions *o) | |||
1812 | dump_cfg_string(sRevokedKeys, o->revoked_keys_file); | 1960 | dump_cfg_string(sRevokedKeys, o->revoked_keys_file); |
1813 | dump_cfg_string(sAuthorizedPrincipalsFile, | 1961 | dump_cfg_string(sAuthorizedPrincipalsFile, |
1814 | o->authorized_principals_file); | 1962 | o->authorized_principals_file); |
1963 | dump_cfg_string(sVersionAddendum, o->version_addendum); | ||
1815 | 1964 | ||
1816 | /* string arguments requiring a lookup */ | 1965 | /* string arguments requiring a lookup */ |
1817 | dump_cfg_string(sLogLevel, log_level_name(o->log_level)); | 1966 | dump_cfg_string(sLogLevel, log_level_name(o->log_level)); |