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 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
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);
@@ -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
146void 150void
@@ -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
566struct connection_info *
567get_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 */
621static int 645static int
622match_cfg_line(char **condition, int line, const char *user, const char *host, 646match_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};
725static const struct multistate multistate_privsep[] = { 793static 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
732int 801int
733process_server_config_line(ServerOptions *options, char *line, 802process_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,
1457void 1559void
1458load_server_config(const char *filename, Buffer *conf) 1560load_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
1486void 1592void
1487parse_server_match_config(ServerOptions *options, const char *user, 1593parse_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
1603int 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 */
1636int 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
1568void 1716void
1569parse_server_config(ServerOptions *options, const char *filename, Buffer *conf, 1717parse_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));