summaryrefslogtreecommitdiff
path: root/servconf.c
diff options
context:
space:
mode:
Diffstat (limited to 'servconf.c')
-rw-r--r--servconf.c231
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
49static void add_listen_addr(ServerOptions *, char *, int); 52static void add_listen_addr(ServerOptions *, char *, int);
50static void add_one_listen_addr(ServerOptions *, char *, int); 53static 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
575struct connection_info *
576get_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 */
630static int 654static int
631match_cfg_line(char **condition, int line, const char *user, const char *host, 655match_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};
734static const struct multistate multistate_privsep[] = { 802static 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
741int 810int
742process_server_config_line(ServerOptions *options, char *line, 811process_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,
1474void 1576void
1475load_server_config(const char *filename, Buffer *conf) 1577load_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
1503void 1609void
1504parse_server_match_config(ServerOptions *options, const char *user, 1610parse_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
1620int 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 */
1653int 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
1585void 1733void
1586parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, 1734parse_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));