summaryrefslogtreecommitdiff
path: root/servconf.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2008-07-22 19:45:18 +0000
committerColin Watson <cjwatson@debian.org>2008-07-22 19:45:18 +0000
commit137d76ba65883aa8143af1fcad83b57e7badef0c (patch)
treef426e804bb5248ceafedfab7bb78ae6e6752942c /servconf.c
parentdac7d049dad31f5f84d421d4eb628a7e13f977d7 (diff)
parentef94e5613d37bcbf880f21ee6094e4b1c7683a4c (diff)
* New upstream release (closes: #474301). Important changes not previously
backported to 4.7p1: - 4.9/4.9p1 (http://www.openssh.com/txt/release-4.9): + Added chroot(2) support for sshd(8), controlled by a new option "ChrootDirectory" (closes: #139047, LP: #24777). + Linked sftp-server(8) into sshd(8). The internal sftp server is used when the command "internal-sftp" is specified in a Subsystem or ForceCommand declaration. When used with ChrootDirectory, the internal sftp server requires no special configuration of files inside the chroot environment. + Added a protocol extension method "posix-rename@openssh.com" for sftp-server(8) to perform POSIX atomic rename() operations; sftp(1) prefers this if available (closes: #308561). + Removed the fixed limit of 100 file handles in sftp-server(8). + ssh(8) will now skip generation of SSH protocol 1 ephemeral server keys when in inetd mode and protocol 2 connections are negotiated. This speeds up protocol 2 connections to inetd-mode servers that also allow Protocol 1. + Accept the PermitRootLogin directive in a sshd_config(5) Match block. Allows for, e.g. permitting root only from the local network. + Reworked sftp(1) argument splitting and escaping to be more internally consistent (i.e. between sftp commands) and more consistent with sh(1). Please note that this will change the interpretation of some quoted strings, especially those with embedded backslash escape sequences. + Support "Banner=none" in sshd_config(5) to disable sending of a pre-login banner (e.g. in a Match block). + ssh(1) ProxyCommands are now executed with $SHELL rather than /bin/sh. + ssh(1)'s ConnectTimeout option is now applied to both the TCP connection and the SSH banner exchange (previously it just covered the TCP connection). This allows callers of ssh(1) to better detect and deal with stuck servers that accept a TCP connection but don't progress the protocol, and also makes ConnectTimeout useful for connections via a ProxyCommand. + scp(1) incorrectly reported "stalled" on slow copies (closes: #140828). + scp(1) date underflow for timestamps before epoch. + ssh(1) used the obsolete SIG DNS RRtype for host keys in DNS, instead of the current standard RRSIG. + Correctly drain ACKs when a sftp(1) upload write fails midway, avoids a fatal() exit from what should be a recoverable condition. + Fixed ssh-keygen(1) selective host key hashing (i.e. "ssh-keygen -HF hostname") to not include any IP address in the data to be hashed. + Make ssh(1) skip listening on the IPv6 wildcard address when a binding address of 0.0.0.0 is used against an old SSH server that does not support the RFC4254 syntax for wildcard bind addresses. + Enable IPV6_V6ONLY socket option on sshd(8) listen socket, as is already done for X11/TCP forwarding sockets (closes: #439661). + Fix FD leak that could hang a ssh(1) connection multiplexing master. + Make ssh(1) -q option documentation consistent with reality. + Fixed sshd(8) PAM support not calling pam_session_close(), or failing to call it with root privileges (closes: #372680). + Fix activation of OpenSSL engine support when requested in configure (LP: #119295). - 5.1/5.1p1 (http://www.openssh.com/txt/release-5.1): + Introduce experimental SSH Fingerprint ASCII Visualisation to ssh(1) and ssh-keygen(1). Visual fingerprint display is controlled by a new ssh_config(5) option "VisualHostKey". The intent is to render SSH host keys in a visual form that is amenable to easy recall and rejection of changed host keys. + sshd_config(5) now supports CIDR address/masklen matching in "Match address" blocks, with a fallback to classic wildcard matching. + sshd(8) now supports CIDR matching in ~/.ssh/authorized_keys from="..." restrictions, also with a fallback to classic wildcard matching. + Added an extended test mode (-T) to sshd(8) to request that it write its effective configuration to stdout and exit. Extended test mode also supports the specification of connection parameters (username, source address and hostname) to test the application of sshd_config(5) Match rules. + ssh(1) now prints the number of bytes transferred and the overall connection throughput for SSH protocol 2 sessions when in verbose mode (previously these statistics were displayed for protocol 1 connections only). + sftp-server(8) now supports extension methods statvfs@openssh.com and fstatvfs@openssh.com that implement statvfs(2)-like operations. + sftp(1) now has a "df" command to the sftp client that uses the statvfs@openssh.com to produce a df(1)-like display of filesystem space and inode utilisation (requires statvfs@openssh.com support on the server). + Added a MaxSessions option to sshd_config(5) to allow control of the number of multiplexed sessions supported over a single TCP connection. This allows increasing the number of allowed sessions above the previous default of 10, disabling connection multiplexing (MaxSessions=1) or disallowing login/shell/subsystem sessions entirely (MaxSessions=0). + Added a no-more-sessions@openssh.com global request extension that is sent from ssh(1) to sshd(8) when the client knows that it will never request another session (i.e. when session multiplexing is disabled). This allows a server to disallow further session requests and terminate the session in cases where the client has been hijacked. + ssh-keygen(1) now supports the use of the -l option in combination with -F to search for a host in ~/.ssh/known_hosts and display its fingerprint. + ssh-keyscan(1) now defaults to "rsa" (protocol 2) keys, instead of "rsa1". + Added an AllowAgentForwarding option to sshd_config(8) to control whether authentication agent forwarding is permitted. Note that this is a loose control, as a client may install their own unofficial forwarder. + ssh(1) and sshd(8): avoid unnecessary malloc/copy/free when receiving network data, resulting in a ~10% speedup. + ssh(1) and sshd(8) will now try additional addresses when connecting to a port forward destination whose DNS name resolves to more than one address. The previous behaviour was to try the only first address and give up if that failed. + ssh(1) and sshd(8) now support signalling that channels are half-closed for writing, through a channel protocol extension notification "eow@openssh.com". This allows propagation of closed file descriptors, so that commands such as "ssh -2 localhost od /bin/ls | true" do not send unnecessary data over the wire. + sshd(8): increased the default size of ssh protocol 1 ephemeral keys from 768 to 1024 bits. + When ssh(1) has been requested to fork after authentication ("ssh -f") with ExitOnForwardFailure enabled, delay the fork until after replies for any -R forwards have been seen. Allows for robust detection of -R forward failure when using -f. + "Match group" blocks in sshd_config(5) now support negation of groups. E.g. "Match group staff,!guests". + sftp(1) and sftp-server(8) now allow chmod-like operations to set set[ug]id/sticky bits. + The MaxAuthTries option is now permitted in sshd_config(5) match blocks. + Multiplexed ssh(1) sessions now support a subset of the ~ escapes that are available to a primary connection. + ssh(1) connection multiplexing will now fall back to creating a new connection in most error cases (closes: #352830). + Make ssh(1) deal more gracefully with channel requests that fail. Previously it would optimistically assume that requests would always succeed, which could cause hangs if they did not (e.g. when the server runs out of file descriptors). + ssh(1) now reports multiplexing errors via the multiplex slave's stderr where possible (subject to LogLevel in the mux master). + Prevent sshd(8) from erroneously applying public key restrictions leaned from ~/.ssh/authorized_keys to other authentication methods when public key authentication subsequently fails (LP: #161047). + Fixed an UMAC alignment problem that manifested on Itanium platforms.
Diffstat (limited to 'servconf.c')
-rw-r--r--servconf.c359
1 files changed, 301 insertions, 58 deletions
diff --git a/servconf.c b/servconf.c
index c5688912d..6760401ff 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: servconf.c,v 1.172 2007/04/23 10:15:39 dtucker Exp $ */ 1/* $OpenBSD: servconf.c,v 1.186 2008/07/04 03:44:59 djm Exp $ */
2/* 2/*
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved 4 * All rights reserved
@@ -23,7 +23,9 @@
23#include <signal.h> 23#include <signal.h>
24#include <unistd.h> 24#include <unistd.h>
25#include <stdarg.h> 25#include <stdarg.h>
26#include <errno.h>
26 27
28#include "openbsd-compat/sys-queue.h"
27#include "xmalloc.h" 29#include "xmalloc.h"
28#include "ssh.h" 30#include "ssh.h"
29#include "log.h" 31#include "log.h"
@@ -102,6 +104,7 @@ initialize_server_options(ServerOptions *options)
102 options->use_login = -1; 104 options->use_login = -1;
103 options->compression = -1; 105 options->compression = -1;
104 options->allow_tcp_forwarding = -1; 106 options->allow_tcp_forwarding = -1;
107 options->allow_agent_forwarding = -1;
105 options->num_allow_users = 0; 108 options->num_allow_users = 0;
106 options->num_deny_users = 0; 109 options->num_deny_users = 0;
107 options->num_allow_groups = 0; 110 options->num_allow_groups = 0;
@@ -115,6 +118,7 @@ initialize_server_options(ServerOptions *options)
115 options->max_startups_rate = -1; 118 options->max_startups_rate = -1;
116 options->max_startups = -1; 119 options->max_startups = -1;
117 options->max_authtries = -1; 120 options->max_authtries = -1;
121 options->max_sessions = -1;
118 options->banner = NULL; 122 options->banner = NULL;
119 options->use_dns = -1; 123 options->use_dns = -1;
120 options->client_alive_interval = -1; 124 options->client_alive_interval = -1;
@@ -125,6 +129,7 @@ initialize_server_options(ServerOptions *options)
125 options->permit_tun = -1; 129 options->permit_tun = -1;
126 options->num_permitted_opens = -1; 130 options->num_permitted_opens = -1;
127 options->adm_forced_command = NULL; 131 options->adm_forced_command = NULL;
132 options->chroot_directory = NULL;
128} 133}
129 134
130void 135void
@@ -156,7 +161,7 @@ fill_default_server_options(ServerOptions *options)
156 if (options->pid_file == NULL) 161 if (options->pid_file == NULL)
157 options->pid_file = _PATH_SSH_DAEMON_PID_FILE; 162 options->pid_file = _PATH_SSH_DAEMON_PID_FILE;
158 if (options->server_key_bits == -1) 163 if (options->server_key_bits == -1)
159 options->server_key_bits = 768; 164 options->server_key_bits = 1024;
160 if (options->login_grace_time == -1) 165 if (options->login_grace_time == -1)
161 options->login_grace_time = 120; 166 options->login_grace_time = 120;
162 if (options->key_regeneration_time == -1) 167 if (options->key_regeneration_time == -1)
@@ -231,6 +236,8 @@ fill_default_server_options(ServerOptions *options)
231 options->compression = COMP_DELAYED; 236 options->compression = COMP_DELAYED;
232 if (options->allow_tcp_forwarding == -1) 237 if (options->allow_tcp_forwarding == -1)
233 options->allow_tcp_forwarding = 1; 238 options->allow_tcp_forwarding = 1;
239 if (options->allow_agent_forwarding == -1)
240 options->allow_agent_forwarding = 1;
234 if (options->gateway_ports == -1) 241 if (options->gateway_ports == -1)
235 options->gateway_ports = 0; 242 options->gateway_ports = 0;
236 if (options->max_startups == -1) 243 if (options->max_startups == -1)
@@ -241,6 +248,8 @@ fill_default_server_options(ServerOptions *options)
241 options->max_startups_begin = options->max_startups; 248 options->max_startups_begin = options->max_startups;
242 if (options->max_authtries == -1) 249 if (options->max_authtries == -1)
243 options->max_authtries = DEFAULT_AUTH_FAIL_MAX; 250 options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
251 if (options->max_sessions == -1)
252 options->max_sessions = DEFAULT_SESSIONS_MAX;
244 if (options->use_dns == -1) 253 if (options->use_dns == -1)
245 options->use_dns = 1; 254 options->use_dns = 1;
246 if (options->client_alive_interval == -1) 255 if (options->client_alive_interval == -1)
@@ -295,15 +304,15 @@ typedef enum {
295 sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, 304 sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
296 sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile, 305 sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
297 sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, 306 sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
298 sMaxStartups, sMaxAuthTries, 307 sMaxStartups, sMaxAuthTries, sMaxSessions,
299 sBanner, sUseDNS, sHostbasedAuthentication, 308 sBanner, sUseDNS, sHostbasedAuthentication,
300 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, 309 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
301 sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, 310 sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
302 sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, 311 sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
303 sGssKeyEx, 312 sGssKeyEx,
304 sAcceptEnv, sPermitTunnel, 313 sAcceptEnv, sPermitTunnel,
305 sMatch, sPermitOpen, sForceCommand, 314 sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
306 sUsePrivilegeSeparation, 315 sUsePrivilegeSeparation, sAllowAgentForwarding,
307 sDeprecated, sUnsupported 316 sDeprecated, sUnsupported
308} ServerOpCodes; 317} ServerOpCodes;
309 318
@@ -332,7 +341,7 @@ static struct {
332 { "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL }, 341 { "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL },
333 { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL }, 342 { "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL },
334 { "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL }, 343 { "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL },
335 { "permitrootlogin", sPermitRootLogin, SSHCFG_GLOBAL }, 344 { "permitrootlogin", sPermitRootLogin, SSHCFG_ALL },
336 { "syslogfacility", sLogFacility, SSHCFG_GLOBAL }, 345 { "syslogfacility", sLogFacility, SSHCFG_GLOBAL },
337 { "loglevel", sLogLevel, SSHCFG_GLOBAL }, 346 { "loglevel", sLogLevel, SSHCFG_GLOBAL },
338 { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL }, 347 { "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
@@ -398,6 +407,7 @@ static struct {
398 { "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, 407 { "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL },
399 { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */ 408 { "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL }, /* obsolete alias */
400 { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL }, 409 { "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL },
410 { "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL },
401 { "allowusers", sAllowUsers, SSHCFG_GLOBAL }, 411 { "allowusers", sAllowUsers, SSHCFG_GLOBAL },
402 { "denyusers", sDenyUsers, SSHCFG_GLOBAL }, 412 { "denyusers", sDenyUsers, SSHCFG_GLOBAL },
403 { "allowgroups", sAllowGroups, SSHCFG_GLOBAL }, 413 { "allowgroups", sAllowGroups, SSHCFG_GLOBAL },
@@ -408,7 +418,8 @@ static struct {
408 { "gatewayports", sGatewayPorts, SSHCFG_ALL }, 418 { "gatewayports", sGatewayPorts, SSHCFG_ALL },
409 { "subsystem", sSubsystem, SSHCFG_GLOBAL }, 419 { "subsystem", sSubsystem, SSHCFG_GLOBAL },
410 { "maxstartups", sMaxStartups, SSHCFG_GLOBAL }, 420 { "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
411 { "maxauthtries", sMaxAuthTries, SSHCFG_GLOBAL }, 421 { "maxauthtries", sMaxAuthTries, SSHCFG_ALL },
422 { "maxsessions", sMaxSessions, SSHCFG_ALL },
412 { "banner", sBanner, SSHCFG_ALL }, 423 { "banner", sBanner, SSHCFG_ALL },
413 { "usedns", sUseDNS, SSHCFG_GLOBAL }, 424 { "usedns", sUseDNS, SSHCFG_GLOBAL },
414 { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL }, 425 { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
@@ -423,9 +434,21 @@ static struct {
423 { "match", sMatch, SSHCFG_ALL }, 434 { "match", sMatch, SSHCFG_ALL },
424 { "permitopen", sPermitOpen, SSHCFG_ALL }, 435 { "permitopen", sPermitOpen, SSHCFG_ALL },
425 { "forcecommand", sForceCommand, SSHCFG_ALL }, 436 { "forcecommand", sForceCommand, SSHCFG_ALL },
437 { "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
426 { NULL, sBadOption, 0 } 438 { NULL, sBadOption, 0 }
427}; 439};
428 440
441static struct {
442 int val;
443 char *text;
444} tunmode_desc[] = {
445 { SSH_TUNMODE_NO, "no" },
446 { SSH_TUNMODE_POINTOPOINT, "point-to-point" },
447 { SSH_TUNMODE_ETHERNET, "ethernet" },
448 { SSH_TUNMODE_YES, "yes" },
449 { -1, NULL }
450};
451
429/* 452/*
430 * Returns the number of the token pointed to by cp or sBadOption. 453 * Returns the number of the token pointed to by cp or sBadOption.
431 */ 454 */
@@ -478,7 +501,7 @@ add_one_listen_addr(ServerOptions *options, char *addr, u_short port)
478 if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0) 501 if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
479 fatal("bad addr or host: %s (%s)", 502 fatal("bad addr or host: %s (%s)",
480 addr ? addr : "<NULL>", 503 addr ? addr : "<NULL>",
481 gai_strerror(gaierr)); 504 ssh_gai_strerror(gaierr));
482 for (ai = aitop; ai->ai_next; ai = ai->ai_next) 505 for (ai = aitop; ai->ai_next; ai = ai->ai_next)
483 ; 506 ;
484 ai->ai_next = options->listen_addrs; 507 ai->ai_next = options->listen_addrs;
@@ -522,24 +545,8 @@ static int
522match_cfg_line_group(const char *grps, int line, const char *user) 545match_cfg_line_group(const char *grps, int line, const char *user)
523{ 546{
524 int result = 0; 547 int result = 0;
525 u_int ngrps = 0;
526 char *arg, *p, *cp, *grplist[MAX_MATCH_GROUPS];
527 struct passwd *pw; 548 struct passwd *pw;
528 549
529 /*
530 * Even if we do not have a user yet, we still need to check for
531 * valid syntax.
532 */
533 arg = cp = xstrdup(grps);
534 while ((p = strsep(&cp, ",")) != NULL && *p != '\0') {
535 if (ngrps >= MAX_MATCH_GROUPS) {
536 error("line %d: too many groups in Match Group", line);
537 result = -1;
538 goto out;
539 }
540 grplist[ngrps++] = p;
541 }
542
543 if (user == NULL) 550 if (user == NULL)
544 goto out; 551 goto out;
545 552
@@ -549,17 +556,16 @@ match_cfg_line_group(const char *grps, int line, const char *user)
549 } else if (ga_init(pw->pw_name, pw->pw_gid) == 0) { 556 } else if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
550 debug("Can't Match group because user %.100s not in any group " 557 debug("Can't Match group because user %.100s not in any group "
551 "at line %d", user, line); 558 "at line %d", user, line);
552 } else if (ga_match(grplist, ngrps) != 1) { 559 } else if (ga_match_pattern_list(grps) != 1) {
553 debug("user %.100s does not match group %.100s at line %d", 560 debug("user %.100s does not match group list %.100s at line %d",
554 user, arg, line); 561 user, grps, line);
555 } else { 562 } else {
556 debug("user %.100s matched group %.100s at line %d", user, 563 debug("user %.100s matched group list %.100s at line %d", user,
557 arg, line); 564 grps, line);
558 result = 1; 565 result = 1;
559 } 566 }
560out: 567out:
561 ga_free(); 568 ga_free();
562 xfree(arg);
563 return result; 569 return result;
564} 570}
565 571
@@ -612,15 +618,18 @@ match_cfg_line(char **condition, int line, const char *user, const char *host,
612 debug("connection from %.100s matched 'Host " 618 debug("connection from %.100s matched 'Host "
613 "%.100s' at line %d", host, arg, line); 619 "%.100s' at line %d", host, arg, line);
614 } else if (strcasecmp(attrib, "address") == 0) { 620 } else if (strcasecmp(attrib, "address") == 0) {
615 if (!address) { 621 switch (addr_match_list(address, arg)) {
616 result = 0; 622 case 1:
617 continue;
618 }
619 if (match_hostname(address, arg, len) != 1)
620 result = 0;
621 else
622 debug("connection from %.100s matched 'Address " 623 debug("connection from %.100s matched 'Address "
623 "%.100s' at line %d", address, arg, line); 624 "%.100s' at line %d", address, arg, line);
625 break;
626 case 0:
627 case -1:
628 result = 0;
629 break;
630 case -2:
631 return -1;
632 }
624 } else { 633 } else {
625 error("Unsupported Match attribute %s", attrib); 634 error("Unsupported Match attribute %s", attrib);
626 return -1; 635 return -1;
@@ -641,6 +650,8 @@ process_server_config_line(ServerOptions *options, char *line,
641{ 650{
642 char *cp, **charptr, *arg, *p; 651 char *cp, **charptr, *arg, *p;
643 int cmdline = 0, *intptr, value, n; 652 int cmdline = 0, *intptr, value, n;
653 SyslogFacility *log_facility_ptr;
654 LogLevel *log_level_ptr;
644 ServerOpCodes opcode; 655 ServerOpCodes opcode;
645 u_short port; 656 u_short port;
646 u_int i, flags = 0; 657 u_int i, flags = 0;
@@ -706,7 +717,7 @@ process_server_config_line(ServerOptions *options, char *line,
706 717
707 case sServerKeyBits: 718 case sServerKeyBits:
708 intptr = &options->server_key_bits; 719 intptr = &options->server_key_bits;
709parse_int: 720 parse_int:
710 arg = strdelim(&cp); 721 arg = strdelim(&cp);
711 if (!arg || *arg == '\0') 722 if (!arg || *arg == '\0')
712 fatal("%s line %d: missing integer value.", 723 fatal("%s line %d: missing integer value.",
@@ -718,7 +729,7 @@ parse_int:
718 729
719 case sLoginGraceTime: 730 case sLoginGraceTime:
720 intptr = &options->login_grace_time; 731 intptr = &options->login_grace_time;
721parse_time: 732 parse_time:
722 arg = strdelim(&cp); 733 arg = strdelim(&cp);
723 if (!arg || *arg == '\0') 734 if (!arg || *arg == '\0')
724 fatal("%s line %d: missing time value.", 735 fatal("%s line %d: missing time value.",
@@ -787,7 +798,7 @@ parse_time:
787 fatal("%s line %d: too many host keys specified (max %d).", 798 fatal("%s line %d: too many host keys specified (max %d).",
788 filename, linenum, MAX_HOSTKEYS); 799 filename, linenum, MAX_HOSTKEYS);
789 charptr = &options->host_key_files[*intptr]; 800 charptr = &options->host_key_files[*intptr];
790parse_filename: 801 parse_filename:
791 arg = strdelim(&cp); 802 arg = strdelim(&cp);
792 if (!arg || *arg == '\0') 803 if (!arg || *arg == '\0')
793 fatal("%s line %d: missing file name.", 804 fatal("%s line %d: missing file name.",
@@ -824,13 +835,13 @@ parse_filename:
824 fatal("%s line %d: Bad yes/" 835 fatal("%s line %d: Bad yes/"
825 "without-password/forced-commands-only/no " 836 "without-password/forced-commands-only/no "
826 "argument: %s", filename, linenum, arg); 837 "argument: %s", filename, linenum, arg);
827 if (*intptr == -1) 838 if (*activep && *intptr == -1)
828 *intptr = value; 839 *intptr = value;
829 break; 840 break;
830 841
831 case sIgnoreRhosts: 842 case sIgnoreRhosts:
832 intptr = &options->ignore_rhosts; 843 intptr = &options->ignore_rhosts;
833parse_flag: 844 parse_flag:
834 arg = strdelim(&cp); 845 arg = strdelim(&cp);
835 if (!arg || *arg == '\0') 846 if (!arg || *arg == '\0')
836 fatal("%s line %d: missing yes/no argument.", 847 fatal("%s line %d: missing yes/no argument.",
@@ -1008,31 +1019,35 @@ parse_flag:
1008 goto parse_flag; 1019 goto parse_flag;
1009 1020
1010 case sLogFacility: 1021 case sLogFacility:
1011 intptr = (int *) &options->log_facility; 1022 log_facility_ptr = &options->log_facility;
1012 arg = strdelim(&cp); 1023 arg = strdelim(&cp);
1013 value = log_facility_number(arg); 1024 value = log_facility_number(arg);
1014 if (value == SYSLOG_FACILITY_NOT_SET) 1025 if (value == SYSLOG_FACILITY_NOT_SET)
1015 fatal("%.200s line %d: unsupported log facility '%s'", 1026 fatal("%.200s line %d: unsupported log facility '%s'",
1016 filename, linenum, arg ? arg : "<NONE>"); 1027 filename, linenum, arg ? arg : "<NONE>");
1017 if (*intptr == -1) 1028 if (*log_facility_ptr == -1)
1018 *intptr = (SyslogFacility) value; 1029 *log_facility_ptr = (SyslogFacility) value;
1019 break; 1030 break;
1020 1031
1021 case sLogLevel: 1032 case sLogLevel:
1022 intptr = (int *) &options->log_level; 1033 log_level_ptr = &options->log_level;
1023 arg = strdelim(&cp); 1034 arg = strdelim(&cp);
1024 value = log_level_number(arg); 1035 value = log_level_number(arg);
1025 if (value == SYSLOG_LEVEL_NOT_SET) 1036 if (value == SYSLOG_LEVEL_NOT_SET)
1026 fatal("%.200s line %d: unsupported log level '%s'", 1037 fatal("%.200s line %d: unsupported log level '%s'",
1027 filename, linenum, arg ? arg : "<NONE>"); 1038 filename, linenum, arg ? arg : "<NONE>");
1028 if (*intptr == -1) 1039 if (*log_level_ptr == -1)
1029 *intptr = (LogLevel) value; 1040 *log_level_ptr = (LogLevel) value;
1030 break; 1041 break;
1031 1042
1032 case sAllowTcpForwarding: 1043 case sAllowTcpForwarding:
1033 intptr = &options->allow_tcp_forwarding; 1044 intptr = &options->allow_tcp_forwarding;
1034 goto parse_flag; 1045 goto parse_flag;
1035 1046
1047 case sAllowAgentForwarding:
1048 intptr = &options->allow_agent_forwarding;
1049 goto parse_flag;
1050
1036 case sUsePrivilegeSeparation: 1051 case sUsePrivilegeSeparation:
1037 intptr = &use_privsep; 1052 intptr = &use_privsep;
1038 goto parse_flag; 1053 goto parse_flag;
@@ -1174,9 +1189,14 @@ parse_flag:
1174 intptr = &options->max_authtries; 1189 intptr = &options->max_authtries;
1175 goto parse_int; 1190 goto parse_int;
1176 1191
1192 case sMaxSessions:
1193 intptr = &options->max_sessions;
1194 goto parse_int;
1195
1177 case sBanner: 1196 case sBanner:
1178 charptr = &options->banner; 1197 charptr = &options->banner;
1179 goto parse_filename; 1198 goto parse_filename;
1199
1180 /* 1200 /*
1181 * These options can contain %X options expanded at 1201 * These options can contain %X options expanded at
1182 * connect time, so that you can specify paths like: 1202 * connect time, so that you can specify paths like:
@@ -1219,16 +1239,13 @@ parse_flag:
1219 if (!arg || *arg == '\0') 1239 if (!arg || *arg == '\0')
1220 fatal("%s line %d: Missing yes/point-to-point/" 1240 fatal("%s line %d: Missing yes/point-to-point/"
1221 "ethernet/no argument.", filename, linenum); 1241 "ethernet/no argument.", filename, linenum);
1222 value = 0; /* silence compiler */ 1242 value = -1;
1223 if (strcasecmp(arg, "ethernet") == 0) 1243 for (i = 0; tunmode_desc[i].val != -1; i++)
1224 value = SSH_TUNMODE_ETHERNET; 1244 if (strcmp(tunmode_desc[i].text, arg) == 0) {
1225 else if (strcasecmp(arg, "point-to-point") == 0) 1245 value = tunmode_desc[i].val;
1226 value = SSH_TUNMODE_POINTOPOINT; 1246 break;
1227 else if (strcasecmp(arg, "yes") == 0) 1247 }
1228 value = SSH_TUNMODE_YES; 1248 if (value == -1)
1229 else if (strcasecmp(arg, "no") == 0)
1230 value = SSH_TUNMODE_NO;
1231 else
1232 fatal("%s line %d: Bad yes/point-to-point/ethernet/" 1249 fatal("%s line %d: Bad yes/point-to-point/ethernet/"
1233 "no argument: %s", filename, linenum, arg); 1250 "no argument: %s", filename, linenum, arg);
1234 if (*intptr == -1) 1251 if (*intptr == -1)
@@ -1285,6 +1302,17 @@ parse_flag:
1285 options->adm_forced_command = xstrdup(cp + len); 1302 options->adm_forced_command = xstrdup(cp + len);
1286 return 0; 1303 return 0;
1287 1304
1305 case sChrootDirectory:
1306 charptr = &options->chroot_directory;
1307
1308 arg = strdelim(&cp);
1309 if (!arg || *arg == '\0')
1310 fatal("%s line %d: missing file name.",
1311 filename, linenum);
1312 if (*activep && *charptr == NULL)
1313 *charptr = xstrdup(arg);
1314 break;
1315
1288 case sDeprecated: 1316 case sDeprecated:
1289 logit("%s line %d: Deprecated option %s", 1317 logit("%s line %d: Deprecated option %s",
1290 filename, linenum, arg); 1318 filename, linenum, arg);
@@ -1381,17 +1409,22 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
1381 M_CP_INTOPT(kerberos_authentication); 1409 M_CP_INTOPT(kerberos_authentication);
1382 M_CP_INTOPT(hostbased_authentication); 1410 M_CP_INTOPT(hostbased_authentication);
1383 M_CP_INTOPT(kbd_interactive_authentication); 1411 M_CP_INTOPT(kbd_interactive_authentication);
1412 M_CP_INTOPT(permit_root_login);
1384 1413
1385 M_CP_INTOPT(allow_tcp_forwarding); 1414 M_CP_INTOPT(allow_tcp_forwarding);
1415 M_CP_INTOPT(allow_agent_forwarding);
1386 M_CP_INTOPT(gateway_ports); 1416 M_CP_INTOPT(gateway_ports);
1387 M_CP_INTOPT(x11_display_offset); 1417 M_CP_INTOPT(x11_display_offset);
1388 M_CP_INTOPT(x11_forwarding); 1418 M_CP_INTOPT(x11_forwarding);
1389 M_CP_INTOPT(x11_use_localhost); 1419 M_CP_INTOPT(x11_use_localhost);
1420 M_CP_INTOPT(max_sessions);
1421 M_CP_INTOPT(max_authtries);
1390 1422
1391 M_CP_STROPT(banner); 1423 M_CP_STROPT(banner);
1392 if (preauth) 1424 if (preauth)
1393 return; 1425 return;
1394 M_CP_STROPT(adm_forced_command); 1426 M_CP_STROPT(adm_forced_command);
1427 M_CP_STROPT(chroot_directory);
1395} 1428}
1396 1429
1397#undef M_CP_INTOPT 1430#undef M_CP_INTOPT
@@ -1419,3 +1452,213 @@ parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
1419 fatal("%s: terminating, %d bad configuration options", 1452 fatal("%s: terminating, %d bad configuration options",
1420 filename, bad_options); 1453 filename, bad_options);
1421} 1454}
1455
1456static const char *
1457fmt_intarg(ServerOpCodes code, int val)
1458{
1459 if (code == sAddressFamily) {
1460 switch (val) {
1461 case AF_INET:
1462 return "inet";
1463 case AF_INET6:
1464 return "inet6";
1465 case AF_UNSPEC:
1466 return "any";
1467 default:
1468 return "UNKNOWN";
1469 }
1470 }
1471 if (code == sPermitRootLogin) {
1472 switch (val) {
1473 case PERMIT_NO_PASSWD:
1474 return "without-passord";
1475 case PERMIT_FORCED_ONLY:
1476 return "forced-commands-only";
1477 case PERMIT_YES:
1478 return "yes";
1479 }
1480 }
1481 if (code == sProtocol) {
1482 switch (val) {
1483 case SSH_PROTO_1:
1484 return "1";
1485 case SSH_PROTO_2:
1486 return "2";
1487 case (SSH_PROTO_1|SSH_PROTO_2):
1488 return "2,1";
1489 default:
1490 return "UNKNOWN";
1491 }
1492 }
1493 if (code == sGatewayPorts && val == 2)
1494 return "clientspecified";
1495 if (code == sCompression && val == COMP_DELAYED)
1496 return "delayed";
1497 switch (val) {
1498 case -1:
1499 return "unset";
1500 case 0:
1501 return "no";
1502 case 1:
1503 return "yes";
1504 }
1505 return "UNKNOWN";
1506}
1507
1508static const char *
1509lookup_opcode_name(ServerOpCodes code)
1510{
1511 u_int i;
1512
1513 for (i = 0; keywords[i].name != NULL; i++)
1514 if (keywords[i].opcode == code)
1515 return(keywords[i].name);
1516 return "UNKNOWN";
1517}
1518
1519static void
1520dump_cfg_int(ServerOpCodes code, int val)
1521{
1522 printf("%s %d\n", lookup_opcode_name(code), val);
1523}
1524
1525static void
1526dump_cfg_fmtint(ServerOpCodes code, int val)
1527{
1528 printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
1529}
1530
1531static void
1532dump_cfg_string(ServerOpCodes code, const char *val)
1533{
1534 if (val == NULL)
1535 return;
1536 printf("%s %s\n", lookup_opcode_name(code), val);
1537}
1538
1539static void
1540dump_cfg_strarray(ServerOpCodes code, u_int count, char **vals)
1541{
1542 u_int i;
1543
1544 for (i = 0; i < count; i++)
1545 printf("%s %s\n", lookup_opcode_name(code), vals[i]);
1546}
1547
1548void
1549dump_config(ServerOptions *o)
1550{
1551 u_int i;
1552 int ret;
1553 struct addrinfo *ai;
1554 char addr[NI_MAXHOST], port[NI_MAXSERV], *s = NULL;
1555
1556 /* these are usually at the top of the config */
1557 for (i = 0; i < o->num_ports; i++)
1558 printf("port %d\n", o->ports[i]);
1559 dump_cfg_fmtint(sProtocol, o->protocol);
1560 dump_cfg_fmtint(sAddressFamily, o->address_family);
1561
1562 /* ListenAddress must be after Port */
1563 for (ai = o->listen_addrs; ai; ai = ai->ai_next) {
1564 if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr,
1565 sizeof(addr), port, sizeof(port),
1566 NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
1567 error("getnameinfo failed: %.100s",
1568 (ret != EAI_SYSTEM) ? gai_strerror(ret) :
1569 strerror(errno));
1570 } else {
1571 if (ai->ai_family == AF_INET6)
1572 printf("listenaddress [%s]:%s\n", addr, port);
1573 else
1574 printf("listenaddress %s:%s\n", addr, port);
1575 }
1576 }
1577
1578 /* integer arguments */
1579 dump_cfg_int(sServerKeyBits, o->server_key_bits);
1580 dump_cfg_int(sLoginGraceTime, o->login_grace_time);
1581 dump_cfg_int(sKeyRegenerationTime, o->key_regeneration_time);
1582 dump_cfg_int(sX11DisplayOffset, o->x11_display_offset);
1583 dump_cfg_int(sMaxAuthTries, o->max_authtries);
1584 dump_cfg_int(sClientAliveInterval, o->client_alive_interval);
1585 dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max);
1586
1587 /* formatted integer arguments */
1588 dump_cfg_fmtint(sPermitRootLogin, o->permit_root_login);
1589 dump_cfg_fmtint(sIgnoreRhosts, o->ignore_rhosts);
1590 dump_cfg_fmtint(sIgnoreUserKnownHosts, o->ignore_user_known_hosts);
1591 dump_cfg_fmtint(sRhostsRSAAuthentication, o->rhosts_rsa_authentication);
1592 dump_cfg_fmtint(sHostbasedAuthentication, o->hostbased_authentication);
1593 dump_cfg_fmtint(sHostbasedUsesNameFromPacketOnly,
1594 o->hostbased_uses_name_from_packet_only);
1595 dump_cfg_fmtint(sRSAAuthentication, o->rsa_authentication);
1596 dump_cfg_fmtint(sPubkeyAuthentication, o->pubkey_authentication);
1597 dump_cfg_fmtint(sKerberosAuthentication, o->kerberos_authentication);
1598 dump_cfg_fmtint(sKerberosOrLocalPasswd, o->kerberos_or_local_passwd);
1599 dump_cfg_fmtint(sKerberosTicketCleanup, o->kerberos_ticket_cleanup);
1600 dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token);
1601 dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
1602 dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
1603 dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
1604 dump_cfg_fmtint(sKbdInteractiveAuthentication,
1605 o->kbd_interactive_authentication);
1606 dump_cfg_fmtint(sChallengeResponseAuthentication,
1607 o->challenge_response_authentication);
1608 dump_cfg_fmtint(sPrintMotd, o->print_motd);
1609 dump_cfg_fmtint(sPrintLastLog, o->print_lastlog);
1610 dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding);
1611 dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost);
1612 dump_cfg_fmtint(sStrictModes, o->strict_modes);
1613 dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive);
1614 dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd);
1615 dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
1616 dump_cfg_fmtint(sUseLogin, o->use_login);
1617 dump_cfg_fmtint(sCompression, o->compression);
1618 dump_cfg_fmtint(sGatewayPorts, o->gateway_ports);
1619 dump_cfg_fmtint(sUseDNS, o->use_dns);
1620 dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
1621 dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
1622
1623 /* string arguments */
1624 dump_cfg_string(sPidFile, o->pid_file);
1625 dump_cfg_string(sXAuthLocation, o->xauth_location);
1626 dump_cfg_string(sCiphers, o->ciphers);
1627 dump_cfg_string(sMacs, o->macs);
1628 dump_cfg_string(sBanner, o->banner);
1629 dump_cfg_string(sAuthorizedKeysFile, o->authorized_keys_file);
1630 dump_cfg_string(sAuthorizedKeysFile2, o->authorized_keys_file2);
1631 dump_cfg_string(sForceCommand, o->adm_forced_command);
1632
1633 /* string arguments requiring a lookup */
1634 dump_cfg_string(sLogLevel, log_level_name(o->log_level));
1635 dump_cfg_string(sLogFacility, log_facility_name(o->log_facility));
1636
1637 /* string array arguments */
1638 dump_cfg_strarray(sHostKeyFile, o->num_host_key_files,
1639 o->host_key_files);
1640 dump_cfg_strarray(sAllowUsers, o->num_allow_users, o->allow_users);
1641 dump_cfg_strarray(sDenyUsers, o->num_deny_users, o->deny_users);
1642 dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups);
1643 dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups);
1644 dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env);
1645
1646 /* other arguments */
1647 for (i = 0; i < o->num_subsystems; i++)
1648 printf("subsystem %s %s\n", o->subsystem_name[i],
1649 o->subsystem_args[i]);
1650
1651 printf("maxstartups %d:%d:%d\n", o->max_startups_begin,
1652 o->max_startups_rate, o->max_startups);
1653
1654 for (i = 0; tunmode_desc[i].val != -1; i++)
1655 if (tunmode_desc[i].val == o->permit_tun) {
1656 s = tunmode_desc[i].text;
1657 break;
1658 }
1659 dump_cfg_string(sPermitTunnel, s);
1660
1661 printf("permitopen");
1662 channel_print_adm_permitted_opens();
1663 printf("\n");
1664}