xref: /titanic_44/usr/src/cmd/ssh/sshd/servconf.c (revision 4a2e944d74dafc80c85d74c8b11430bbecd98824)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
37c478bd9Sstevel@tonic-gate  *                    All rights reserved
47c478bd9Sstevel@tonic-gate  *
57c478bd9Sstevel@tonic-gate  * As far as I am concerned, the code I have written for this software
67c478bd9Sstevel@tonic-gate  * can be used freely for any purpose.  Any derived versions of this
77c478bd9Sstevel@tonic-gate  * software must be clearly marked as such, and if the derived work is
87c478bd9Sstevel@tonic-gate  * incompatible with the protocol description in the RFC file, it must be
97c478bd9Sstevel@tonic-gate  * called by a name other than "ssh" or "Secure Shell".
107c478bd9Sstevel@tonic-gate  */
117c478bd9Sstevel@tonic-gate /*
12bdb005b5SDarren J Moffat  * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
137c478bd9Sstevel@tonic-gate  */
147c478bd9Sstevel@tonic-gate 
157c478bd9Sstevel@tonic-gate #include "includes.h"
167c478bd9Sstevel@tonic-gate RCSID("$OpenBSD: servconf.c,v 1.115 2002/09/04 18:52:42 stevesk Exp $");
177c478bd9Sstevel@tonic-gate 
187c478bd9Sstevel@tonic-gate #ifdef HAVE_DEFOPEN
197c478bd9Sstevel@tonic-gate #include <deflt.h>
207c478bd9Sstevel@tonic-gate #endif /* HAVE_DEFOPEN */
217c478bd9Sstevel@tonic-gate 
227c478bd9Sstevel@tonic-gate #if defined(KRB4)
237c478bd9Sstevel@tonic-gate #include <krb.h>
247c478bd9Sstevel@tonic-gate #endif
257c478bd9Sstevel@tonic-gate #if defined(KRB5)
267c478bd9Sstevel@tonic-gate #ifdef HEIMDAL
277c478bd9Sstevel@tonic-gate #include <krb.h>
287c478bd9Sstevel@tonic-gate #else
297c478bd9Sstevel@tonic-gate /* Bodge - but then, so is using the kerberos IV KEYFILE to get a Kerberos V
307c478bd9Sstevel@tonic-gate  * keytab */
317c478bd9Sstevel@tonic-gate #define KEYFILE "/etc/krb5.keytab"
327c478bd9Sstevel@tonic-gate #endif
337c478bd9Sstevel@tonic-gate #endif
347c478bd9Sstevel@tonic-gate #ifdef AFS
357c478bd9Sstevel@tonic-gate #include <kafs.h>
367c478bd9Sstevel@tonic-gate #endif
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate #include "ssh.h"
397c478bd9Sstevel@tonic-gate #include "log.h"
40b07b2f5cSHuie-Ying Lee #include "buffer.h"
417c478bd9Sstevel@tonic-gate #include "servconf.h"
427c478bd9Sstevel@tonic-gate #include "xmalloc.h"
437c478bd9Sstevel@tonic-gate #include "compat.h"
447c478bd9Sstevel@tonic-gate #include "pathnames.h"
457c478bd9Sstevel@tonic-gate #include "tildexpand.h"
467c478bd9Sstevel@tonic-gate #include "misc.h"
477c478bd9Sstevel@tonic-gate #include "cipher.h"
487c478bd9Sstevel@tonic-gate #include "kex.h"
497c478bd9Sstevel@tonic-gate #include "mac.h"
507c478bd9Sstevel@tonic-gate #include "auth.h"
51b07b2f5cSHuie-Ying Lee #include "match.h"
52b07b2f5cSHuie-Ying Lee #include "groupaccess.h"
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate static void add_listen_addr(ServerOptions *, char *, u_short);
557c478bd9Sstevel@tonic-gate static void add_one_listen_addr(ServerOptions *, char *, u_short);
567c478bd9Sstevel@tonic-gate 
57b07b2f5cSHuie-Ying Lee extern Buffer cfg;
58b07b2f5cSHuie-Ying Lee 
597c478bd9Sstevel@tonic-gate /* AF_UNSPEC or AF_INET or AF_INET6 */
607c478bd9Sstevel@tonic-gate extern int IPv4or6;
617c478bd9Sstevel@tonic-gate 
626f8d59d8SJan Pechanec /*
636f8d59d8SJan Pechanec  * Initializes the server options to their initial (unset) values. Some of those
646f8d59d8SJan Pechanec  * that stay unset after the command line options and configuration files are
656f8d59d8SJan Pechanec  * read are set to their default values in fill_default_server_options().
666f8d59d8SJan Pechanec  */
677c478bd9Sstevel@tonic-gate void
687c478bd9Sstevel@tonic-gate initialize_server_options(ServerOptions *options)
697c478bd9Sstevel@tonic-gate {
707c478bd9Sstevel@tonic-gate 	(void) memset(options, 0, sizeof(*options));
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate 	/* Standard Options */
737c478bd9Sstevel@tonic-gate 	options->num_ports = 0;
747c478bd9Sstevel@tonic-gate 	options->ports_from_cmdline = 0;
757c478bd9Sstevel@tonic-gate 	options->listen_addrs = NULL;
767c478bd9Sstevel@tonic-gate 	options->num_host_key_files = 0;
777c478bd9Sstevel@tonic-gate 	options->pid_file = NULL;
787c478bd9Sstevel@tonic-gate 	options->server_key_bits = -1;
797c478bd9Sstevel@tonic-gate 	options->login_grace_time = -1;
807c478bd9Sstevel@tonic-gate 	options->key_regeneration_time = -1;
817c478bd9Sstevel@tonic-gate 	options->permit_root_login = PERMIT_NOT_SET;
827c478bd9Sstevel@tonic-gate 	options->ignore_rhosts = -1;
837c478bd9Sstevel@tonic-gate 	options->ignore_user_known_hosts = -1;
847c478bd9Sstevel@tonic-gate 	options->print_motd = -1;
857c478bd9Sstevel@tonic-gate 	options->print_lastlog = -1;
867c478bd9Sstevel@tonic-gate 	options->x11_forwarding = -1;
877c478bd9Sstevel@tonic-gate 	options->x11_display_offset = -1;
887c478bd9Sstevel@tonic-gate 	options->x11_use_localhost = -1;
897c478bd9Sstevel@tonic-gate 	options->xauth_location = NULL;
907c478bd9Sstevel@tonic-gate 	options->strict_modes = -1;
917c478bd9Sstevel@tonic-gate 	options->keepalives = -1;
927c478bd9Sstevel@tonic-gate 	options->log_facility = SYSLOG_FACILITY_NOT_SET;
937c478bd9Sstevel@tonic-gate 	options->log_level = SYSLOG_LEVEL_NOT_SET;
947c478bd9Sstevel@tonic-gate 	options->rhosts_authentication = -1;
957c478bd9Sstevel@tonic-gate 	options->rhosts_rsa_authentication = -1;
967c478bd9Sstevel@tonic-gate 	options->hostbased_authentication = -1;
977c478bd9Sstevel@tonic-gate 	options->hostbased_uses_name_from_packet_only = -1;
987c478bd9Sstevel@tonic-gate 	options->rsa_authentication = -1;
997c478bd9Sstevel@tonic-gate 	options->pubkey_authentication = -1;
1007c478bd9Sstevel@tonic-gate #ifdef GSSAPI
1017c478bd9Sstevel@tonic-gate 	options->gss_authentication = -1;
1027c478bd9Sstevel@tonic-gate 	options->gss_keyex = -1;
1037c478bd9Sstevel@tonic-gate 	options->gss_store_creds = -1;
1047c478bd9Sstevel@tonic-gate 	options->gss_use_session_ccache = -1;
1057c478bd9Sstevel@tonic-gate 	options->gss_cleanup_creds = -1;
1067c478bd9Sstevel@tonic-gate #endif
1077c478bd9Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5)
1087c478bd9Sstevel@tonic-gate 	options->kerberos_authentication = -1;
1097c478bd9Sstevel@tonic-gate 	options->kerberos_or_local_passwd = -1;
1107c478bd9Sstevel@tonic-gate 	options->kerberos_ticket_cleanup = -1;
1117c478bd9Sstevel@tonic-gate #endif
1127c478bd9Sstevel@tonic-gate #if defined(AFS) || defined(KRB5)
1137c478bd9Sstevel@tonic-gate 	options->kerberos_tgt_passing = -1;
1147c478bd9Sstevel@tonic-gate #endif
1157c478bd9Sstevel@tonic-gate #ifdef AFS
1167c478bd9Sstevel@tonic-gate 	options->afs_token_passing = -1;
1177c478bd9Sstevel@tonic-gate #endif
1187c478bd9Sstevel@tonic-gate 	options->password_authentication = -1;
1197c478bd9Sstevel@tonic-gate 	options->kbd_interactive_authentication = -1;
1207c478bd9Sstevel@tonic-gate 	options->challenge_response_authentication = -1;
121*4a2e944dSJan Pechanec 	options->pam_authentication_via_kbd_int = -1;
1227c478bd9Sstevel@tonic-gate 	options->permit_empty_passwd = -1;
1237c478bd9Sstevel@tonic-gate 	options->permit_user_env = -1;
1247c478bd9Sstevel@tonic-gate 	options->compression = -1;
1257c478bd9Sstevel@tonic-gate 	options->allow_tcp_forwarding = -1;
1267c478bd9Sstevel@tonic-gate 	options->num_allow_users = 0;
1277c478bd9Sstevel@tonic-gate 	options->num_deny_users = 0;
1287c478bd9Sstevel@tonic-gate 	options->num_allow_groups = 0;
1297c478bd9Sstevel@tonic-gate 	options->num_deny_groups = 0;
1307c478bd9Sstevel@tonic-gate 	options->ciphers = NULL;
1317c478bd9Sstevel@tonic-gate 	options->macs = NULL;
1327c478bd9Sstevel@tonic-gate 	options->protocol = SSH_PROTO_UNKNOWN;
1337c478bd9Sstevel@tonic-gate 	options->gateway_ports = -1;
1347c478bd9Sstevel@tonic-gate 	options->num_subsystems = 0;
1357c478bd9Sstevel@tonic-gate 	options->max_startups_begin = -1;
1367c478bd9Sstevel@tonic-gate 	options->max_startups_rate = -1;
1377c478bd9Sstevel@tonic-gate 	options->max_startups = -1;
1387c478bd9Sstevel@tonic-gate 	options->banner = NULL;
1397c478bd9Sstevel@tonic-gate 	options->verify_reverse_mapping = -1;
1407c478bd9Sstevel@tonic-gate 	options->client_alive_interval = -1;
1417c478bd9Sstevel@tonic-gate 	options->client_alive_count_max = -1;
1427c478bd9Sstevel@tonic-gate 	options->authorized_keys_file = NULL;
1437c478bd9Sstevel@tonic-gate 	options->authorized_keys_file2 = NULL;
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	options->max_auth_tries = -1;
1467c478bd9Sstevel@tonic-gate 	options->max_auth_tries_log = -1;
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	options->max_init_auth_tries = -1;
1497c478bd9Sstevel@tonic-gate 	options->max_init_auth_tries_log = -1;
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	options->lookup_client_hostnames = -1;
152cd7d5fafSJan Pechanec 	options->use_openssl_engine = -1;
1536f8d59d8SJan Pechanec 	options->chroot_directory = NULL;
154d8a94255SErik Trauschke 	options->pre_userauth_hook = NULL;
155bdb005b5SDarren J Moffat 	options->pam_service_name = NULL;
156bdb005b5SDarren J Moffat 	options->pam_service_prefix = NULL;
1577c478bd9Sstevel@tonic-gate }
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate #ifdef HAVE_DEFOPEN
1607c478bd9Sstevel@tonic-gate /*
1617c478bd9Sstevel@tonic-gate  * Reads /etc/default/login and defaults several ServerOptions:
1627c478bd9Sstevel@tonic-gate  *
1637c478bd9Sstevel@tonic-gate  * PermitRootLogin
1647c478bd9Sstevel@tonic-gate  * PermitEmptyPasswords
1657c478bd9Sstevel@tonic-gate  * LoginGraceTime
1667c478bd9Sstevel@tonic-gate  *
1677c478bd9Sstevel@tonic-gate  * CONSOLE=*      -> PermitRootLogin=without-password
1687c478bd9Sstevel@tonic-gate  * #CONSOLE=*     -> PermitRootLogin=yes
1697c478bd9Sstevel@tonic-gate  *
1707c478bd9Sstevel@tonic-gate  * PASSREQ=YES    -> PermitEmptyPasswords=no
1717c478bd9Sstevel@tonic-gate  * PASSREQ=NO     -> PermitEmptyPasswords=yes
1727c478bd9Sstevel@tonic-gate  * #PASSREQ=*     -> PermitEmptyPasswords=no
1737c478bd9Sstevel@tonic-gate  *
1747c478bd9Sstevel@tonic-gate  * TIMEOUT=<secs> -> LoginGraceTime=<secs>
1757c478bd9Sstevel@tonic-gate  * #TIMEOUT=<secs> -> LoginGraceTime=300
1767c478bd9Sstevel@tonic-gate  */
1777c478bd9Sstevel@tonic-gate static
1787c478bd9Sstevel@tonic-gate void
1797c478bd9Sstevel@tonic-gate deflt_fill_default_server_options(ServerOptions *options)
1807c478bd9Sstevel@tonic-gate {
1817c478bd9Sstevel@tonic-gate 	int	flags;
1827c478bd9Sstevel@tonic-gate 	char	*ptr;
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 	if (defopen(_PATH_DEFAULT_LOGIN))
1857c478bd9Sstevel@tonic-gate 		return;
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate 	/* Ignore case */
1887c478bd9Sstevel@tonic-gate 	flags = defcntl(DC_GETFLAGS, 0);
1897c478bd9Sstevel@tonic-gate 	TURNOFF(flags, DC_CASE);
1907c478bd9Sstevel@tonic-gate 	(void) defcntl(DC_SETFLAGS, flags);
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 	if (options->permit_root_login == PERMIT_NOT_SET &&
1937c478bd9Sstevel@tonic-gate 	    (ptr = defread("CONSOLE=")) != NULL)
1947c478bd9Sstevel@tonic-gate 		options->permit_root_login = PERMIT_NO_PASSWD;
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	if (options->permit_empty_passwd == -1 &&
1977c478bd9Sstevel@tonic-gate 	    (ptr = defread("PASSREQ=")) != NULL) {
1987c478bd9Sstevel@tonic-gate 		if (strcasecmp("YES", ptr) == 0)
1997c478bd9Sstevel@tonic-gate 			options->permit_empty_passwd = 0;
2007c478bd9Sstevel@tonic-gate 		else if (strcasecmp("NO", ptr) == 0)
2017c478bd9Sstevel@tonic-gate 			options->permit_empty_passwd = 1;
2027c478bd9Sstevel@tonic-gate 	}
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	if (options->max_init_auth_tries == -1 &&
2057c478bd9Sstevel@tonic-gate 	    (ptr = defread("RETRIES=")) != NULL) {
2067c478bd9Sstevel@tonic-gate 		options->max_init_auth_tries = atoi(ptr);
2077c478bd9Sstevel@tonic-gate 	}
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 	if (options->max_init_auth_tries_log == -1 &&
2107c478bd9Sstevel@tonic-gate 	    (ptr = defread("SYSLOG_FAILED_LOGINS=")) != NULL) {
2117c478bd9Sstevel@tonic-gate 		options->max_init_auth_tries_log = atoi(ptr);
2127c478bd9Sstevel@tonic-gate 	}
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 	if (options->login_grace_time == -1) {
2157c478bd9Sstevel@tonic-gate 		if ((ptr = defread("TIMEOUT=")) != NULL)
2167c478bd9Sstevel@tonic-gate 			options->login_grace_time = (unsigned)atoi(ptr);
2177c478bd9Sstevel@tonic-gate 		else
2187c478bd9Sstevel@tonic-gate 			options->login_grace_time = 300;
2197c478bd9Sstevel@tonic-gate 	}
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 	(void) defopen((char *)NULL);
2227c478bd9Sstevel@tonic-gate }
2237c478bd9Sstevel@tonic-gate #endif /* HAVE_DEFOPEN */
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate void
2267c478bd9Sstevel@tonic-gate fill_default_server_options(ServerOptions *options)
2277c478bd9Sstevel@tonic-gate {
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate #ifdef HAVE_DEFOPEN
2307c478bd9Sstevel@tonic-gate 	deflt_fill_default_server_options(options);
2317c478bd9Sstevel@tonic-gate #endif /* HAVE_DEFOPEN */
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	/* Standard Options */
2347c478bd9Sstevel@tonic-gate 	if (options->protocol == SSH_PROTO_UNKNOWN)
2357c478bd9Sstevel@tonic-gate 		options->protocol = SSH_PROTO_1|SSH_PROTO_2;
2367c478bd9Sstevel@tonic-gate 	if (options->num_host_key_files == 0) {
2377c478bd9Sstevel@tonic-gate 		/* fill default hostkeys for protocols */
2387c478bd9Sstevel@tonic-gate 		if (options->protocol & SSH_PROTO_1)
2397c478bd9Sstevel@tonic-gate 			options->host_key_files[options->num_host_key_files++] =
2407c478bd9Sstevel@tonic-gate 			    _PATH_HOST_KEY_FILE;
2417c478bd9Sstevel@tonic-gate #ifndef GSSAPI
2427c478bd9Sstevel@tonic-gate 		/* With GSS keyex we can run v2 w/ no host keys */
2437c478bd9Sstevel@tonic-gate 		if (options->protocol & SSH_PROTO_2) {
2447c478bd9Sstevel@tonic-gate 			options->host_key_files[options->num_host_key_files++] =
2457c478bd9Sstevel@tonic-gate 			    _PATH_HOST_RSA_KEY_FILE;
2467c478bd9Sstevel@tonic-gate 			options->host_key_files[options->num_host_key_files++] =
2477c478bd9Sstevel@tonic-gate 			    _PATH_HOST_DSA_KEY_FILE;
2487c478bd9Sstevel@tonic-gate 		}
2497c478bd9Sstevel@tonic-gate #endif /* GSSAPI */
2507c478bd9Sstevel@tonic-gate 	}
2517c478bd9Sstevel@tonic-gate 	if (options->num_ports == 0)
2527c478bd9Sstevel@tonic-gate 		options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
2537c478bd9Sstevel@tonic-gate 	if (options->listen_addrs == NULL)
2547c478bd9Sstevel@tonic-gate 		add_listen_addr(options, NULL, 0);
2557c478bd9Sstevel@tonic-gate 	if (options->pid_file == NULL)
2567c478bd9Sstevel@tonic-gate 		options->pid_file = _PATH_SSH_DAEMON_PID_FILE;
2577c478bd9Sstevel@tonic-gate 	if (options->server_key_bits == -1)
2587c478bd9Sstevel@tonic-gate 		options->server_key_bits = 768;
2597c478bd9Sstevel@tonic-gate 	if (options->login_grace_time == -1)
2607c478bd9Sstevel@tonic-gate 		options->login_grace_time = 120;
2617c478bd9Sstevel@tonic-gate 	if (options->key_regeneration_time == -1)
2627c478bd9Sstevel@tonic-gate 		options->key_regeneration_time = 3600;
2637c478bd9Sstevel@tonic-gate 	if (options->permit_root_login == PERMIT_NOT_SET)
2647c478bd9Sstevel@tonic-gate 		options->permit_root_login = PERMIT_YES;
2657c478bd9Sstevel@tonic-gate 	if (options->ignore_rhosts == -1)
2667c478bd9Sstevel@tonic-gate 		options->ignore_rhosts = 1;
2677c478bd9Sstevel@tonic-gate 	if (options->ignore_user_known_hosts == -1)
2687c478bd9Sstevel@tonic-gate 		options->ignore_user_known_hosts = 0;
2697c478bd9Sstevel@tonic-gate 	if (options->print_motd == -1)
2707c478bd9Sstevel@tonic-gate 		options->print_motd = 1;
2717c478bd9Sstevel@tonic-gate 	if (options->print_lastlog == -1)
2727c478bd9Sstevel@tonic-gate 		options->print_lastlog = 1;
2737c478bd9Sstevel@tonic-gate 	if (options->x11_forwarding == -1)
2747c478bd9Sstevel@tonic-gate 		options->x11_forwarding = 1;
2757c478bd9Sstevel@tonic-gate 	if (options->x11_display_offset == -1)
2767c478bd9Sstevel@tonic-gate 		options->x11_display_offset = 10;
2777c478bd9Sstevel@tonic-gate 	if (options->x11_use_localhost == -1)
2787c478bd9Sstevel@tonic-gate 		options->x11_use_localhost = 1;
2797c478bd9Sstevel@tonic-gate 	if (options->xauth_location == NULL)
2807c478bd9Sstevel@tonic-gate 		options->xauth_location = _PATH_XAUTH;
2817c478bd9Sstevel@tonic-gate 	if (options->strict_modes == -1)
2827c478bd9Sstevel@tonic-gate 		options->strict_modes = 1;
2837c478bd9Sstevel@tonic-gate 	if (options->keepalives == -1)
2847c478bd9Sstevel@tonic-gate 		options->keepalives = 1;
2857c478bd9Sstevel@tonic-gate 	if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
2867c478bd9Sstevel@tonic-gate 		options->log_facility = SYSLOG_FACILITY_AUTH;
2877c478bd9Sstevel@tonic-gate 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
2887c478bd9Sstevel@tonic-gate 		options->log_level = SYSLOG_LEVEL_INFO;
2897c478bd9Sstevel@tonic-gate 	if (options->rhosts_authentication == -1)
2907c478bd9Sstevel@tonic-gate 		options->rhosts_authentication = 0;
2917c478bd9Sstevel@tonic-gate 	if (options->rhosts_rsa_authentication == -1)
2927c478bd9Sstevel@tonic-gate 		options->rhosts_rsa_authentication = 0;
2937c478bd9Sstevel@tonic-gate 	if (options->hostbased_authentication == -1)
2947c478bd9Sstevel@tonic-gate 		options->hostbased_authentication = 0;
2957c478bd9Sstevel@tonic-gate 	if (options->hostbased_uses_name_from_packet_only == -1)
2967c478bd9Sstevel@tonic-gate 		options->hostbased_uses_name_from_packet_only = 0;
2977c478bd9Sstevel@tonic-gate 	if (options->rsa_authentication == -1)
2987c478bd9Sstevel@tonic-gate 		options->rsa_authentication = 1;
2997c478bd9Sstevel@tonic-gate 	if (options->pubkey_authentication == -1)
3007c478bd9Sstevel@tonic-gate 		options->pubkey_authentication = 1;
3017c478bd9Sstevel@tonic-gate #ifdef GSSAPI
3027c478bd9Sstevel@tonic-gate 	if (options->gss_authentication == -1)
3037c478bd9Sstevel@tonic-gate 		options->gss_authentication = 1;
3047c478bd9Sstevel@tonic-gate 	if (options->gss_keyex == -1)
3057c478bd9Sstevel@tonic-gate 		options->gss_keyex = 1;
3067c478bd9Sstevel@tonic-gate 	if (options->gss_store_creds == -1)
3077c478bd9Sstevel@tonic-gate 		options->gss_store_creds = 1;
3087c478bd9Sstevel@tonic-gate 	if (options->gss_use_session_ccache == -1)
3097c478bd9Sstevel@tonic-gate 		options->gss_use_session_ccache = 1;
3107c478bd9Sstevel@tonic-gate 	if (options->gss_cleanup_creds == -1)
3117c478bd9Sstevel@tonic-gate 		options->gss_cleanup_creds = 1;
3127c478bd9Sstevel@tonic-gate #endif
3137c478bd9Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5)
3147c478bd9Sstevel@tonic-gate 	if (options->kerberos_authentication == -1)
3157c478bd9Sstevel@tonic-gate 		options->kerberos_authentication = 0;
3167c478bd9Sstevel@tonic-gate 	if (options->kerberos_or_local_passwd == -1)
3177c478bd9Sstevel@tonic-gate 		options->kerberos_or_local_passwd = 1;
3187c478bd9Sstevel@tonic-gate 	if (options->kerberos_ticket_cleanup == -1)
3197c478bd9Sstevel@tonic-gate 		options->kerberos_ticket_cleanup = 1;
3207c478bd9Sstevel@tonic-gate #endif
3217c478bd9Sstevel@tonic-gate #if defined(AFS) || defined(KRB5)
3227c478bd9Sstevel@tonic-gate 	if (options->kerberos_tgt_passing == -1)
3237c478bd9Sstevel@tonic-gate 		options->kerberos_tgt_passing = 0;
3247c478bd9Sstevel@tonic-gate #endif
3257c478bd9Sstevel@tonic-gate #ifdef AFS
3267c478bd9Sstevel@tonic-gate 	if (options->afs_token_passing == -1)
3277c478bd9Sstevel@tonic-gate 		options->afs_token_passing = 0;
3287c478bd9Sstevel@tonic-gate #endif
3297c478bd9Sstevel@tonic-gate 	if (options->password_authentication == -1)
3307c478bd9Sstevel@tonic-gate 		options->password_authentication = 1;
331*4a2e944dSJan Pechanec 	/*
332*4a2e944dSJan Pechanec 	 * options->pam_authentication_via_kbd_int has intentionally no default
333*4a2e944dSJan Pechanec 	 * value since we do not need it.
334*4a2e944dSJan Pechanec 	 */
3357c478bd9Sstevel@tonic-gate 	if (options->kbd_interactive_authentication == -1)
336*4a2e944dSJan Pechanec 		options->kbd_interactive_authentication = 1;
3377c478bd9Sstevel@tonic-gate 	if (options->challenge_response_authentication == -1)
3387c478bd9Sstevel@tonic-gate 		options->challenge_response_authentication = 1;
3397c478bd9Sstevel@tonic-gate 	if (options->permit_empty_passwd == -1)
3407c478bd9Sstevel@tonic-gate 		options->permit_empty_passwd = 0;
3417c478bd9Sstevel@tonic-gate 	if (options->permit_user_env == -1)
3427c478bd9Sstevel@tonic-gate 		options->permit_user_env = 0;
3437c478bd9Sstevel@tonic-gate 	if (options->compression == -1)
3447c478bd9Sstevel@tonic-gate 		options->compression = 1;
3457c478bd9Sstevel@tonic-gate 	if (options->allow_tcp_forwarding == -1)
3467c478bd9Sstevel@tonic-gate 		options->allow_tcp_forwarding = 1;
3477c478bd9Sstevel@tonic-gate 	if (options->gateway_ports == -1)
3487c478bd9Sstevel@tonic-gate 		options->gateway_ports = 0;
3497c478bd9Sstevel@tonic-gate 	if (options->max_startups == -1)
3507c478bd9Sstevel@tonic-gate 		options->max_startups = 10;
3517c478bd9Sstevel@tonic-gate 	if (options->max_startups_rate == -1)
3527c478bd9Sstevel@tonic-gate 		options->max_startups_rate = 100;		/* 100% */
3537c478bd9Sstevel@tonic-gate 	if (options->max_startups_begin == -1)
3547c478bd9Sstevel@tonic-gate 		options->max_startups_begin = options->max_startups;
3557c478bd9Sstevel@tonic-gate 	if (options->verify_reverse_mapping == -1)
3567c478bd9Sstevel@tonic-gate 		options->verify_reverse_mapping = 0;
3577c478bd9Sstevel@tonic-gate 	if (options->client_alive_interval == -1)
3587c478bd9Sstevel@tonic-gate 		options->client_alive_interval = 0;
3597c478bd9Sstevel@tonic-gate 	if (options->client_alive_count_max == -1)
3607c478bd9Sstevel@tonic-gate 		options->client_alive_count_max = 3;
3617c478bd9Sstevel@tonic-gate 	if (options->authorized_keys_file2 == NULL) {
3627c478bd9Sstevel@tonic-gate 		/* authorized_keys_file2 falls back to authorized_keys_file */
3637c478bd9Sstevel@tonic-gate 		if (options->authorized_keys_file != NULL)
3647c478bd9Sstevel@tonic-gate 			options->authorized_keys_file2 = options->authorized_keys_file;
3657c478bd9Sstevel@tonic-gate 		else
3667c478bd9Sstevel@tonic-gate 			options->authorized_keys_file2 = _PATH_SSH_USER_PERMITTED_KEYS2;
3677c478bd9Sstevel@tonic-gate 	}
3687c478bd9Sstevel@tonic-gate 	if (options->authorized_keys_file == NULL)
3697c478bd9Sstevel@tonic-gate 		options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS;
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 	if (options->max_auth_tries == -1)
3727c478bd9Sstevel@tonic-gate 		options->max_auth_tries = AUTH_FAIL_MAX;
3737c478bd9Sstevel@tonic-gate 	if (options->max_auth_tries_log == -1)
3747c478bd9Sstevel@tonic-gate 		options->max_auth_tries_log = options->max_auth_tries / 2;
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 	if (options->max_init_auth_tries == -1)
3777c478bd9Sstevel@tonic-gate 		options->max_init_auth_tries = AUTH_FAIL_MAX;
3787c478bd9Sstevel@tonic-gate 	if (options->max_init_auth_tries_log == -1)
3797c478bd9Sstevel@tonic-gate 		options->max_init_auth_tries_log = options->max_init_auth_tries / 2;
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 	if (options->lookup_client_hostnames == -1)
3827c478bd9Sstevel@tonic-gate 		options->lookup_client_hostnames = 1;
383cd7d5fafSJan Pechanec 	if (options->use_openssl_engine == -1)
384cd7d5fafSJan Pechanec 		options->use_openssl_engine = 1;
385bdb005b5SDarren J Moffat 	if (options->pam_service_prefix == NULL)
386bdb005b5SDarren J Moffat 		options->pam_service_prefix = _SSH_PAM_SERVICE_PREFIX;
387bdb005b5SDarren J Moffat 	if (options->pam_service_name == NULL)
388bdb005b5SDarren J Moffat 		options->pam_service_name = NULL;
3897c478bd9Sstevel@tonic-gate }
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate /* Keyword tokens. */
3927c478bd9Sstevel@tonic-gate typedef enum {
3937c478bd9Sstevel@tonic-gate 	sBadOption,		/* == unknown option */
3947c478bd9Sstevel@tonic-gate 	/* Portable-specific options */
3957c478bd9Sstevel@tonic-gate 	sPAMAuthenticationViaKbdInt,
3967c478bd9Sstevel@tonic-gate 	/* Standard Options */
3977c478bd9Sstevel@tonic-gate 	sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
3987c478bd9Sstevel@tonic-gate 	sPermitRootLogin, sLogFacility, sLogLevel,
3997c478bd9Sstevel@tonic-gate 	sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication,
4007c478bd9Sstevel@tonic-gate #ifdef GSSAPI
4017c478bd9Sstevel@tonic-gate 	sGssAuthentication, sGssKeyEx, sGssStoreDelegCreds,
4027c478bd9Sstevel@tonic-gate 	sGssUseSessionCredCache, sGssCleanupCreds,
4037c478bd9Sstevel@tonic-gate #endif /* GSSAPI */
4047c478bd9Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5)
4057c478bd9Sstevel@tonic-gate 	sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
4067c478bd9Sstevel@tonic-gate #endif
4077c478bd9Sstevel@tonic-gate #if defined(AFS) || defined(KRB5)
4087c478bd9Sstevel@tonic-gate 	sKerberosTgtPassing,
4097c478bd9Sstevel@tonic-gate #endif
4107c478bd9Sstevel@tonic-gate #ifdef AFS
4117c478bd9Sstevel@tonic-gate 	sAFSTokenPassing,
4127c478bd9Sstevel@tonic-gate #endif
4137c478bd9Sstevel@tonic-gate 	sChallengeResponseAuthentication,
4147c478bd9Sstevel@tonic-gate 	sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress,
4157c478bd9Sstevel@tonic-gate 	sPrintMotd, sPrintLastLog, sIgnoreRhosts,
4167c478bd9Sstevel@tonic-gate 	sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
4177c478bd9Sstevel@tonic-gate 	sStrictModes, sEmptyPasswd, sKeepAlives,
4187c478bd9Sstevel@tonic-gate 	sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
4197c478bd9Sstevel@tonic-gate 	sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
4207c478bd9Sstevel@tonic-gate 	sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
4217c478bd9Sstevel@tonic-gate 	sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups,
4227c478bd9Sstevel@tonic-gate 	sBanner, sVerifyReverseMapping, sHostbasedAuthentication,
4237c478bd9Sstevel@tonic-gate 	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
4247c478bd9Sstevel@tonic-gate 	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
4257c478bd9Sstevel@tonic-gate 	sMaxAuthTries, sMaxAuthTriesLog, sUsePrivilegeSeparation,
4266f8d59d8SJan Pechanec 	sLookupClientHostnames, sUseOpenSSLEngine, sChrootDirectory,
427bdb005b5SDarren J Moffat 	sPreUserauthHook, sMatch, sPAMServicePrefix, sPAMServiceName,
4287c478bd9Sstevel@tonic-gate 	sDeprecated
4297c478bd9Sstevel@tonic-gate } ServerOpCodes;
4307c478bd9Sstevel@tonic-gate 
431b07b2f5cSHuie-Ying Lee #define SSHCFG_GLOBAL	0x01	/* allowed in main section of sshd_config */
432b07b2f5cSHuie-Ying Lee #define SSHCFG_MATCH	0x02	/* allowed inside a Match section */
433b07b2f5cSHuie-Ying Lee #define SSHCFG_ALL	(SSHCFG_GLOBAL|SSHCFG_MATCH)
434b07b2f5cSHuie-Ying Lee 
4357c478bd9Sstevel@tonic-gate /* Textual representation of the tokens. */
4367c478bd9Sstevel@tonic-gate static struct {
4377c478bd9Sstevel@tonic-gate 	const char *name;
4387c478bd9Sstevel@tonic-gate 	ServerOpCodes opcode;
439b07b2f5cSHuie-Ying Lee 	u_int flags;
4407c478bd9Sstevel@tonic-gate } keywords[] = {
4417c478bd9Sstevel@tonic-gate 	/* Portable-specific options */
442b07b2f5cSHuie-Ying Lee 	{ "PAMAuthenticationViaKbdInt", sPAMAuthenticationViaKbdInt, SSHCFG_GLOBAL },
4437c478bd9Sstevel@tonic-gate 	/* Standard Options */
444b07b2f5cSHuie-Ying Lee 	{ "port", sPort, SSHCFG_GLOBAL },
445b07b2f5cSHuie-Ying Lee 	{ "hostkey", sHostKeyFile, SSHCFG_GLOBAL },
446b07b2f5cSHuie-Ying Lee 	{ "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL },			/* alias */
447b07b2f5cSHuie-Ying Lee 	{ "pidfile", sPidFile, SSHCFG_GLOBAL },
448b07b2f5cSHuie-Ying Lee 	{ "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL },
449b07b2f5cSHuie-Ying Lee 	{ "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL },
450b07b2f5cSHuie-Ying Lee 	{ "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL },
451b07b2f5cSHuie-Ying Lee 	{ "permitrootlogin", sPermitRootLogin, SSHCFG_ALL },
452b07b2f5cSHuie-Ying Lee 	{ "syslogfacility", sLogFacility, SSHCFG_GLOBAL },
453b07b2f5cSHuie-Ying Lee 	{ "loglevel", sLogLevel, SSHCFG_GLOBAL },
454b07b2f5cSHuie-Ying Lee 	{ "rhostsauthentication", sRhostsAuthentication, SSHCFG_GLOBAL },
455b07b2f5cSHuie-Ying Lee 	{ "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_ALL },
456b07b2f5cSHuie-Ying Lee 	{ "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL },
4577c478bd9Sstevel@tonic-gate 	{ "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly },
458b07b2f5cSHuie-Ying Lee 	{ "rsaauthentication", sRSAAuthentication, SSHCFG_ALL },
459b07b2f5cSHuie-Ying Lee 	{ "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
460b07b2f5cSHuie-Ying Lee 	{ "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL },	/* alias */
4617c478bd9Sstevel@tonic-gate #ifdef GSSAPI
462b07b2f5cSHuie-Ying Lee 	{ "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
463b07b2f5cSHuie-Ying Lee 	{ "gssapikeyexchange", sGssKeyEx,   SSHCFG_GLOBAL },
464b07b2f5cSHuie-Ying Lee 	{ "gssapistoredelegatedcredentials", sGssStoreDelegCreds, SSHCFG_GLOBAL },
465b07b2f5cSHuie-Ying Lee 	{ "gssauthentication", sGssAuthentication, SSHCFG_GLOBAL },	/* alias */
466b07b2f5cSHuie-Ying Lee 	{ "gsskeyex", sGssKeyEx, SSHCFG_GLOBAL },	/* alias */
467b07b2f5cSHuie-Ying Lee 	{ "gssstoredelegcreds", sGssStoreDelegCreds, SSHCFG_GLOBAL },	/* alias */
4687c478bd9Sstevel@tonic-gate #ifndef SUNW_GSSAPI
469b07b2f5cSHuie-Ying Lee 	{ "gssusesessionccache", sGssUseSessionCredCache, SSHCFG_GLOBAL },
470b07b2f5cSHuie-Ying Lee 	{ "gssusesessioncredcache", sGssUseSessionCredCache, SSHCFG_GLOBAL },
471b07b2f5cSHuie-Ying Lee 	{ "gsscleanupcreds", sGssCleanupCreds, SSHCFG_GLOBAL },
4727c478bd9Sstevel@tonic-gate #endif /* SUNW_GSSAPI */
4737c478bd9Sstevel@tonic-gate #endif
4747c478bd9Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5)
475b07b2f5cSHuie-Ying Lee 	{ "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL },
476b07b2f5cSHuie-Ying Lee 	{ "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL },
477b07b2f5cSHuie-Ying Lee 	{ "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL },
4787c478bd9Sstevel@tonic-gate #endif
4797c478bd9Sstevel@tonic-gate #if defined(AFS) || defined(KRB5)
480b07b2f5cSHuie-Ying Lee 	{ "kerberostgtpassing", sKerberosTgtPassing, SSHCFG_GLOBAL },
4817c478bd9Sstevel@tonic-gate #endif
4827c478bd9Sstevel@tonic-gate #ifdef AFS
483b07b2f5cSHuie-Ying Lee 	{ "afstokenpassing", sAFSTokenPassing, SSHCFG_GLOBAL },
4847c478bd9Sstevel@tonic-gate #endif
485b07b2f5cSHuie-Ying Lee 	{ "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
486b07b2f5cSHuie-Ying Lee 	{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
487b07b2f5cSHuie-Ying Lee 	{ "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
488b07b2f5cSHuie-Ying Lee 	{ "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */
489b07b2f5cSHuie-Ying Lee 	{ "checkmail", sDeprecated, SSHCFG_GLOBAL },
490b07b2f5cSHuie-Ying Lee 	{ "listenaddress", sListenAddress, SSHCFG_GLOBAL },
491b07b2f5cSHuie-Ying Lee 	{ "printmotd", sPrintMotd, SSHCFG_GLOBAL },
492b07b2f5cSHuie-Ying Lee 	{ "printlastlog", sPrintLastLog, SSHCFG_GLOBAL },
493b07b2f5cSHuie-Ying Lee 	{ "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL },
494b07b2f5cSHuie-Ying Lee 	{ "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL },
495b07b2f5cSHuie-Ying Lee 	{ "x11forwarding", sX11Forwarding, SSHCFG_ALL },
496b07b2f5cSHuie-Ying Lee 	{ "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL },
497b07b2f5cSHuie-Ying Lee 	{ "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
498b07b2f5cSHuie-Ying Lee 	{ "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
499b07b2f5cSHuie-Ying Lee 	{ "strictmodes", sStrictModes, SSHCFG_GLOBAL },
500b07b2f5cSHuie-Ying Lee 	{ "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL },
501b07b2f5cSHuie-Ying Lee 	{ "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL },
502b07b2f5cSHuie-Ying Lee 	{ "uselogin", sUseLogin, SSHCFG_GLOBAL },
503b07b2f5cSHuie-Ying Lee 	{ "compression", sCompression, SSHCFG_GLOBAL },
504b07b2f5cSHuie-Ying Lee 	{ "keepalive", sKeepAlives, SSHCFG_GLOBAL },
505b07b2f5cSHuie-Ying Lee 	{ "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL },
506b07b2f5cSHuie-Ying Lee 	{ "allowusers", sAllowUsers, SSHCFG_GLOBAL },
507b07b2f5cSHuie-Ying Lee 	{ "denyusers", sDenyUsers, SSHCFG_GLOBAL },
508b07b2f5cSHuie-Ying Lee 	{ "allowgroups", sAllowGroups, SSHCFG_GLOBAL },
509b07b2f5cSHuie-Ying Lee 	{ "denygroups", sDenyGroups, SSHCFG_GLOBAL },
510b07b2f5cSHuie-Ying Lee 	{ "ciphers", sCiphers, SSHCFG_GLOBAL },
511b07b2f5cSHuie-Ying Lee 	{ "macs", sMacs, SSHCFG_GLOBAL},
512b07b2f5cSHuie-Ying Lee 	{ "protocol", sProtocol,SSHCFG_GLOBAL },
513b07b2f5cSHuie-Ying Lee 	{ "gatewayports", sGatewayPorts, SSHCFG_ALL },
514b07b2f5cSHuie-Ying Lee 	{ "subsystem", sSubsystem, SSHCFG_GLOBAL},
515b07b2f5cSHuie-Ying Lee 	{ "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
516b07b2f5cSHuie-Ying Lee 	{ "banner", sBanner, SSHCFG_ALL },
517b07b2f5cSHuie-Ying Lee 	{ "verifyreversemapping", sVerifyReverseMapping, SSHCFG_GLOBAL },
518b07b2f5cSHuie-Ying Lee 	{ "reversemappingcheck", sVerifyReverseMapping,SSHCFG_GLOBAL },
519b07b2f5cSHuie-Ying Lee 	{ "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL },
520b07b2f5cSHuie-Ying Lee 	{ "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL },
521b07b2f5cSHuie-Ying Lee 	{ "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_GLOBAL },
522b07b2f5cSHuie-Ying Lee 	{ "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_GLOBAL },
523b07b2f5cSHuie-Ying Lee 	{ "maxauthtries", sMaxAuthTries, SSHCFG_ALL },
524b07b2f5cSHuie-Ying Lee 	{ "maxauthtrieslog", sMaxAuthTriesLog, SSHCFG_GLOBAL },
525b07b2f5cSHuie-Ying Lee 	{ "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL },
526b07b2f5cSHuie-Ying Lee 	{ "lookupclienthostnames", sLookupClientHostnames, SSHCFG_GLOBAL },
527b07b2f5cSHuie-Ying Lee 	{ "useopensslengine", sUseOpenSSLEngine, SSHCFG_GLOBAL },
528b07b2f5cSHuie-Ying Lee 	{ "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
529d8a94255SErik Trauschke 	{ "preuserauthhook", sPreUserauthHook, SSHCFG_ALL},
530b07b2f5cSHuie-Ying Lee 	{ "match", sMatch, SSHCFG_ALL },
531bdb005b5SDarren J Moffat 	{ "pamserviceprefix", sPAMServicePrefix, SSHCFG_GLOBAL },
532bdb005b5SDarren J Moffat 	{ "pamservicename", sPAMServiceName, SSHCFG_GLOBAL },
533b07b2f5cSHuie-Ying Lee 
534b07b2f5cSHuie-Ying Lee 	{ NULL, sBadOption, 0 }
5357c478bd9Sstevel@tonic-gate };
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate /*
5387c478bd9Sstevel@tonic-gate  * Returns the number of the token pointed to by cp or sBadOption.
5397c478bd9Sstevel@tonic-gate  */
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate static ServerOpCodes
5427c478bd9Sstevel@tonic-gate parse_token(const char *cp, const char *filename,
543b07b2f5cSHuie-Ying Lee 	    int linenum, u_int *flags)
5447c478bd9Sstevel@tonic-gate {
5457c478bd9Sstevel@tonic-gate 	u_int i;
5467c478bd9Sstevel@tonic-gate 
5477c478bd9Sstevel@tonic-gate 	for (i = 0; keywords[i].name; i++)
548b07b2f5cSHuie-Ying Lee 		if (strcasecmp(cp, keywords[i].name) == 0) {
549b07b2f5cSHuie-Ying Lee 			*flags = keywords[i].flags;
5507c478bd9Sstevel@tonic-gate 			return keywords[i].opcode;
551b07b2f5cSHuie-Ying Lee 		}
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 	error("%s: line %d: Bad configuration option: %s",
5547c478bd9Sstevel@tonic-gate 	    filename, linenum, cp);
5557c478bd9Sstevel@tonic-gate 	return sBadOption;
5567c478bd9Sstevel@tonic-gate }
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate static void
5597c478bd9Sstevel@tonic-gate add_listen_addr(ServerOptions *options, char *addr, u_short port)
5607c478bd9Sstevel@tonic-gate {
5617c478bd9Sstevel@tonic-gate 	int i;
5627c478bd9Sstevel@tonic-gate 
5637c478bd9Sstevel@tonic-gate 	if (options->num_ports == 0)
5647c478bd9Sstevel@tonic-gate 		options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
5657c478bd9Sstevel@tonic-gate 	if (port == 0)
5667c478bd9Sstevel@tonic-gate 		for (i = 0; i < options->num_ports; i++)
5677c478bd9Sstevel@tonic-gate 			add_one_listen_addr(options, addr, options->ports[i]);
5687c478bd9Sstevel@tonic-gate 	else
5697c478bd9Sstevel@tonic-gate 		add_one_listen_addr(options, addr, port);
5707c478bd9Sstevel@tonic-gate }
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate static void
5737c478bd9Sstevel@tonic-gate add_one_listen_addr(ServerOptions *options, char *addr, u_short port)
5747c478bd9Sstevel@tonic-gate {
5757c478bd9Sstevel@tonic-gate 	struct addrinfo hints, *ai, *aitop;
5767c478bd9Sstevel@tonic-gate 	char strport[NI_MAXSERV];
5777c478bd9Sstevel@tonic-gate 	int gaierr;
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate 	(void) memset(&hints, 0, sizeof(hints));
5807c478bd9Sstevel@tonic-gate 	hints.ai_family = IPv4or6;
5817c478bd9Sstevel@tonic-gate 	hints.ai_socktype = SOCK_STREAM;
5827c478bd9Sstevel@tonic-gate 	hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
5837c478bd9Sstevel@tonic-gate 	(void) snprintf(strport, sizeof strport, "%u", port);
5847c478bd9Sstevel@tonic-gate 	if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
5857c478bd9Sstevel@tonic-gate 		fatal("bad addr or host: %s (%s)",
5867c478bd9Sstevel@tonic-gate 		    addr ? addr : "<NULL>",
5877c478bd9Sstevel@tonic-gate 		    gai_strerror(gaierr));
5887c478bd9Sstevel@tonic-gate 	for (ai = aitop; ai->ai_next; ai = ai->ai_next)
5897c478bd9Sstevel@tonic-gate 		;
5907c478bd9Sstevel@tonic-gate 	ai->ai_next = options->listen_addrs;
5917c478bd9Sstevel@tonic-gate 	options->listen_addrs = aitop;
5927c478bd9Sstevel@tonic-gate }
5937c478bd9Sstevel@tonic-gate 
594b07b2f5cSHuie-Ying Lee /*
595b07b2f5cSHuie-Ying Lee  * The strategy for the Match blocks is that the config file is parsed twice.
596b07b2f5cSHuie-Ying Lee  *
597b07b2f5cSHuie-Ying Lee  * The first time is at startup.  activep is initialized to 1 and the
598b07b2f5cSHuie-Ying Lee  * directives in the global context are processed and acted on.  Hitting a
599b07b2f5cSHuie-Ying Lee  * Match directive unsets activep and the directives inside the block are
600b07b2f5cSHuie-Ying Lee  * checked for syntax only.
601b07b2f5cSHuie-Ying Lee  *
602b07b2f5cSHuie-Ying Lee  * The second time is after a connection has been established but before
603b07b2f5cSHuie-Ying Lee  * authentication.  activep is initialized to 2 and global config directives
604b07b2f5cSHuie-Ying Lee  * are ignored since they have already been processed.  If the criteria in a
605b07b2f5cSHuie-Ying Lee  * Match block is met, activep is set and the subsequent directives
606b07b2f5cSHuie-Ying Lee  * processed and actioned until EOF or another Match block unsets it.  Any
607b07b2f5cSHuie-Ying Lee  * options set are copied into the main server config.
608b07b2f5cSHuie-Ying Lee  *
609b07b2f5cSHuie-Ying Lee  * Potential additions/improvements:
610b07b2f5cSHuie-Ying Lee  *  - Add Match support for pre-kex directives, eg Protocol, Ciphers.
611b07b2f5cSHuie-Ying Lee  *
612b07b2f5cSHuie-Ying Lee  *  - Add a Tag directive (idea from David Leonard) ala pf, eg:
613b07b2f5cSHuie-Ying Lee  *	Match Address 192.168.0.*
614b07b2f5cSHuie-Ying Lee  *		Tag trusted
615b07b2f5cSHuie-Ying Lee  *	Match Group wheel
616b07b2f5cSHuie-Ying Lee  *		Tag trusted
617b07b2f5cSHuie-Ying Lee  *	Match Tag trusted
618b07b2f5cSHuie-Ying Lee  *		AllowTcpForwarding yes
619b07b2f5cSHuie-Ying Lee  *		GatewayPorts clientspecified
620b07b2f5cSHuie-Ying Lee  *		[...]
621b07b2f5cSHuie-Ying Lee  *
622b07b2f5cSHuie-Ying Lee  *  - Add a PermittedChannelRequests directive
623b07b2f5cSHuie-Ying Lee  *	Match Group shell
624b07b2f5cSHuie-Ying Lee  *		PermittedChannelRequests session,forwarded-tcpip
625b07b2f5cSHuie-Ying Lee  */
626b07b2f5cSHuie-Ying Lee 
627b07b2f5cSHuie-Ying Lee static int
628b07b2f5cSHuie-Ying Lee match_cfg_line_group(const char *grps, int line, const char *user)
629b07b2f5cSHuie-Ying Lee {
630b07b2f5cSHuie-Ying Lee 	int result = 0;
631b07b2f5cSHuie-Ying Lee 	struct passwd *pw;
632b07b2f5cSHuie-Ying Lee 
633b07b2f5cSHuie-Ying Lee 	if (user == NULL)
634b07b2f5cSHuie-Ying Lee 		goto out;
635b07b2f5cSHuie-Ying Lee 
636b07b2f5cSHuie-Ying Lee 	if ((pw = getpwnam(user)) == NULL) {
637b07b2f5cSHuie-Ying Lee 		debug("Can't match group at line %d because user %.100s does "
638b07b2f5cSHuie-Ying Lee 		    "not exist", line, user);
639b07b2f5cSHuie-Ying Lee 	} else if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
640b07b2f5cSHuie-Ying Lee 		debug("Can't Match group because user %.100s not in any group "
641b07b2f5cSHuie-Ying Lee 		    "at line %d", user, line);
642b07b2f5cSHuie-Ying Lee 	} else if (ga_match_pattern_list(grps) != 1) {
643b07b2f5cSHuie-Ying Lee 		debug("user %.100s does not match group list %.100s at line %d",
644b07b2f5cSHuie-Ying Lee 		    user, grps, line);
645b07b2f5cSHuie-Ying Lee 	} else {
646b07b2f5cSHuie-Ying Lee 		debug("user %.100s matched group list %.100s at line %d", user,
647b07b2f5cSHuie-Ying Lee 		    grps, line);
648b07b2f5cSHuie-Ying Lee 		result = 1;
649b07b2f5cSHuie-Ying Lee 	}
650b07b2f5cSHuie-Ying Lee out:
651b07b2f5cSHuie-Ying Lee 	ga_free();
652b07b2f5cSHuie-Ying Lee 	return result;
653b07b2f5cSHuie-Ying Lee }
654b07b2f5cSHuie-Ying Lee 
655b07b2f5cSHuie-Ying Lee static int
656b07b2f5cSHuie-Ying Lee match_cfg_line(char **condition, int line, const char *user, const char *host,
657b07b2f5cSHuie-Ying Lee     const char *address)
658b07b2f5cSHuie-Ying Lee {
659b07b2f5cSHuie-Ying Lee 	int result = 1;
660b07b2f5cSHuie-Ying Lee 	char *arg, *attrib, *cp = *condition;
661b07b2f5cSHuie-Ying Lee 	size_t len;
662b07b2f5cSHuie-Ying Lee 
663b07b2f5cSHuie-Ying Lee 	if (user == NULL)
664b07b2f5cSHuie-Ying Lee 		debug3("checking syntax for 'Match %s'", cp);
665b07b2f5cSHuie-Ying Lee 	else
666b07b2f5cSHuie-Ying Lee 		debug3("checking match for '%s' user %s host %s addr %s", cp,
667b07b2f5cSHuie-Ying Lee 		    user ? user : "(null)", host ? host : "(null)",
668b07b2f5cSHuie-Ying Lee 		    address ? address : "(null)");
669b07b2f5cSHuie-Ying Lee 
67056e7e6c6SHuie-Ying Lee 	while ((attrib = strdelim(&cp)) != NULL && *attrib != '\0') {
671b07b2f5cSHuie-Ying Lee 		if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
672b07b2f5cSHuie-Ying Lee 			error("Missing Match criteria for %s", attrib);
673b07b2f5cSHuie-Ying Lee 			return -1;
674b07b2f5cSHuie-Ying Lee 		}
675b07b2f5cSHuie-Ying Lee 		len = strlen(arg);
676b07b2f5cSHuie-Ying Lee 		if (strcasecmp(attrib, "user") == 0) {
677b07b2f5cSHuie-Ying Lee 			if (!user) {
678b07b2f5cSHuie-Ying Lee 				result = 0;
679b07b2f5cSHuie-Ying Lee 				continue;
680b07b2f5cSHuie-Ying Lee 			}
681b07b2f5cSHuie-Ying Lee 			if (match_pattern_list(user, arg, len, 0) != 1)
682b07b2f5cSHuie-Ying Lee 				result = 0;
683b07b2f5cSHuie-Ying Lee 			else
684b07b2f5cSHuie-Ying Lee 				debug("user %.100s matched 'User %.100s' at "
685b07b2f5cSHuie-Ying Lee 				    "line %d", user, arg, line);
686b07b2f5cSHuie-Ying Lee 		} else if (strcasecmp(attrib, "group") == 0) {
687b07b2f5cSHuie-Ying Lee 			switch (match_cfg_line_group(arg, line, user)) {
688b07b2f5cSHuie-Ying Lee 			case -1:
689b07b2f5cSHuie-Ying Lee 				return -1;
690b07b2f5cSHuie-Ying Lee 			case 0:
691b07b2f5cSHuie-Ying Lee 				result = 0;
692b07b2f5cSHuie-Ying Lee 			}
693b07b2f5cSHuie-Ying Lee 		} else if (strcasecmp(attrib, "host") == 0) {
694b07b2f5cSHuie-Ying Lee 			if (!host) {
695b07b2f5cSHuie-Ying Lee 				result = 0;
696b07b2f5cSHuie-Ying Lee 				continue;
697b07b2f5cSHuie-Ying Lee 			}
698b07b2f5cSHuie-Ying Lee 			if (match_hostname(host, arg, len) != 1)
699b07b2f5cSHuie-Ying Lee 				result = 0;
700b07b2f5cSHuie-Ying Lee 			else
701b07b2f5cSHuie-Ying Lee 				debug("connection from %.100s matched 'Host "
702b07b2f5cSHuie-Ying Lee 				    "%.100s' at line %d", host, arg, line);
703b07b2f5cSHuie-Ying Lee 		} else if (strcasecmp(attrib, "address") == 0) {
704b07b2f5cSHuie-Ying Lee 			switch (addr_match_list(address, arg)) {
705b07b2f5cSHuie-Ying Lee 			case 1:
706b07b2f5cSHuie-Ying Lee 				debug("connection from %.100s matched 'Address "
707b07b2f5cSHuie-Ying Lee 				    "%.100s' at line %d", address, arg, line);
708b07b2f5cSHuie-Ying Lee 				break;
709b07b2f5cSHuie-Ying Lee 			case 0:
710b07b2f5cSHuie-Ying Lee 			case -1:
711b07b2f5cSHuie-Ying Lee 				result = 0;
712b07b2f5cSHuie-Ying Lee 				break;
713b07b2f5cSHuie-Ying Lee 			case -2:
714b07b2f5cSHuie-Ying Lee 				return -1;
715b07b2f5cSHuie-Ying Lee 			}
716b07b2f5cSHuie-Ying Lee 		} else {
717b07b2f5cSHuie-Ying Lee 			error("Unsupported Match attribute %s", attrib);
718b07b2f5cSHuie-Ying Lee 			return -1;
719b07b2f5cSHuie-Ying Lee 		}
720b07b2f5cSHuie-Ying Lee 	}
721b07b2f5cSHuie-Ying Lee 	if (user != NULL)
722b07b2f5cSHuie-Ying Lee 		debug3("match %sfound", result ? "" : "not ");
723b07b2f5cSHuie-Ying Lee 	*condition = cp;
724b07b2f5cSHuie-Ying Lee 	return result;
725b07b2f5cSHuie-Ying Lee }
726b07b2f5cSHuie-Ying Lee 
727b07b2f5cSHuie-Ying Lee #define WHITESPACE " \t\r\n"
728b07b2f5cSHuie-Ying Lee 
7297c478bd9Sstevel@tonic-gate int
7307c478bd9Sstevel@tonic-gate process_server_config_line(ServerOptions *options, char *line,
731b07b2f5cSHuie-Ying Lee     const char *filename, int linenum, int *activep, const char *user,
732b07b2f5cSHuie-Ying Lee     const char *host, const char *address)
7337c478bd9Sstevel@tonic-gate {
7347c478bd9Sstevel@tonic-gate 	char *cp, **charptr, *arg, *p;
735b07b2f5cSHuie-Ying Lee 	int cmdline = 0, *intptr, value, n;
7367c478bd9Sstevel@tonic-gate 	ServerOpCodes opcode;
737b07b2f5cSHuie-Ying Lee 	u_int i, flags = 0;
7386f8d59d8SJan Pechanec 	size_t len;
7397c478bd9Sstevel@tonic-gate 
7407c478bd9Sstevel@tonic-gate 	cp = line;
7417c478bd9Sstevel@tonic-gate 	arg = strdelim(&cp);
7427c478bd9Sstevel@tonic-gate 	/* Ignore leading whitespace */
7437c478bd9Sstevel@tonic-gate 	if (*arg == '\0')
7447c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
7457c478bd9Sstevel@tonic-gate 	if (!arg || !*arg || *arg == '#')
7467c478bd9Sstevel@tonic-gate 		return 0;
7477c478bd9Sstevel@tonic-gate 	intptr = NULL;
7487c478bd9Sstevel@tonic-gate 	charptr = NULL;
749b07b2f5cSHuie-Ying Lee 	opcode = parse_token(arg, filename, linenum, &flags);
750b07b2f5cSHuie-Ying Lee 
751b07b2f5cSHuie-Ying Lee 	if (activep == NULL) { /* We are processing a command line directive */
752b07b2f5cSHuie-Ying Lee 		cmdline = 1;
753b07b2f5cSHuie-Ying Lee 		activep = &cmdline;
754b07b2f5cSHuie-Ying Lee 	}
755b07b2f5cSHuie-Ying Lee 	if (*activep && opcode != sMatch)
756b07b2f5cSHuie-Ying Lee 		debug3("%s:%d setting %s %s", filename, linenum, arg, cp);
757b07b2f5cSHuie-Ying Lee 	if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
758b07b2f5cSHuie-Ying Lee 		if (user == NULL) {
759b07b2f5cSHuie-Ying Lee 			fatal("%s line %d: Directive '%s' is not allowed "
760b07b2f5cSHuie-Ying Lee 			    "within a Match block", filename, linenum, arg);
761b07b2f5cSHuie-Ying Lee 		} else { /* this is a directive we have already processed */
762b07b2f5cSHuie-Ying Lee 			while (arg)
763b07b2f5cSHuie-Ying Lee 				arg = strdelim(&cp);
764b07b2f5cSHuie-Ying Lee 			return 0;
765b07b2f5cSHuie-Ying Lee 		}
766b07b2f5cSHuie-Ying Lee 	}
767b07b2f5cSHuie-Ying Lee 
7687c478bd9Sstevel@tonic-gate 	switch (opcode) {
7697c478bd9Sstevel@tonic-gate 	/* Portable-specific options */
7707c478bd9Sstevel@tonic-gate 	case sPAMAuthenticationViaKbdInt:
771*4a2e944dSJan Pechanec 		log("%s line %d: PAMAuthenticationViaKbdInt has been "
772*4a2e944dSJan Pechanec 		    "deprecated. You should use KbdInteractiveAuthentication "
773*4a2e944dSJan Pechanec 		    "instead (which defaults to \"yes\").", filename, linenum);
7747c478bd9Sstevel@tonic-gate 		intptr = &options->pam_authentication_via_kbd_int;
7757c478bd9Sstevel@tonic-gate 		goto parse_flag;
7767c478bd9Sstevel@tonic-gate 
7777c478bd9Sstevel@tonic-gate 	/* Standard Options */
7787c478bd9Sstevel@tonic-gate 	case sBadOption:
7797c478bd9Sstevel@tonic-gate 		return -1;
7807c478bd9Sstevel@tonic-gate 	case sPort:
7817c478bd9Sstevel@tonic-gate 		/* ignore ports from configfile if cmdline specifies ports */
7827c478bd9Sstevel@tonic-gate 		if (options->ports_from_cmdline)
7837c478bd9Sstevel@tonic-gate 			return 0;
7847c478bd9Sstevel@tonic-gate 		if (options->listen_addrs != NULL)
7857c478bd9Sstevel@tonic-gate 			fatal("%s line %d: ports must be specified before "
7867c478bd9Sstevel@tonic-gate 			    "ListenAddress.", filename, linenum);
7877c478bd9Sstevel@tonic-gate 		if (options->num_ports >= MAX_PORTS)
7887c478bd9Sstevel@tonic-gate 			fatal("%s line %d: too many ports.",
7897c478bd9Sstevel@tonic-gate 			    filename, linenum);
7907c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
7917c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0')
7927c478bd9Sstevel@tonic-gate 			fatal("%s line %d: missing port number.",
7937c478bd9Sstevel@tonic-gate 			    filename, linenum);
7947c478bd9Sstevel@tonic-gate 		options->ports[options->num_ports++] = a2port(arg);
7957c478bd9Sstevel@tonic-gate 		if (options->ports[options->num_ports-1] == 0)
7967c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Badly formatted port number.",
7977c478bd9Sstevel@tonic-gate 			    filename, linenum);
7987c478bd9Sstevel@tonic-gate 		break;
7997c478bd9Sstevel@tonic-gate 
8007c478bd9Sstevel@tonic-gate 	case sServerKeyBits:
8017c478bd9Sstevel@tonic-gate 		intptr = &options->server_key_bits;
8027c478bd9Sstevel@tonic-gate parse_int:
8037c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
8047c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0')
8057c478bd9Sstevel@tonic-gate 			fatal("%s line %d: missing integer value.",
8067c478bd9Sstevel@tonic-gate 			    filename, linenum);
8077c478bd9Sstevel@tonic-gate 		value = atoi(arg);
808b07b2f5cSHuie-Ying Lee 		if (*activep && *intptr == -1)
8097c478bd9Sstevel@tonic-gate 			*intptr = value;
8107c478bd9Sstevel@tonic-gate 		break;
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate 	case sLoginGraceTime:
8137c478bd9Sstevel@tonic-gate 		intptr = &options->login_grace_time;
8147c478bd9Sstevel@tonic-gate parse_time:
8157c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
8167c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0')
8177c478bd9Sstevel@tonic-gate 			fatal("%s line %d: missing time value.",
8187c478bd9Sstevel@tonic-gate 			    filename, linenum);
8197c478bd9Sstevel@tonic-gate 		if ((value = convtime(arg)) == -1)
8207c478bd9Sstevel@tonic-gate 			fatal("%s line %d: invalid time value.",
8217c478bd9Sstevel@tonic-gate 			    filename, linenum);
8227c478bd9Sstevel@tonic-gate 		if (*intptr == -1)
8237c478bd9Sstevel@tonic-gate 			*intptr = value;
8247c478bd9Sstevel@tonic-gate 		break;
8257c478bd9Sstevel@tonic-gate 
8267c478bd9Sstevel@tonic-gate 	case sKeyRegenerationTime:
8277c478bd9Sstevel@tonic-gate 		intptr = &options->key_regeneration_time;
8287c478bd9Sstevel@tonic-gate 		goto parse_time;
8297c478bd9Sstevel@tonic-gate 
8307c478bd9Sstevel@tonic-gate 	case sListenAddress:
8317c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
8327c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0)
8337c478bd9Sstevel@tonic-gate 			fatal("%s line %d: missing inet addr.",
8347c478bd9Sstevel@tonic-gate 			    filename, linenum);
8357c478bd9Sstevel@tonic-gate 		if (*arg == '[') {
8367c478bd9Sstevel@tonic-gate 			if ((p = strchr(arg, ']')) == NULL)
8377c478bd9Sstevel@tonic-gate 				fatal("%s line %d: bad ipv6 inet addr usage.",
8387c478bd9Sstevel@tonic-gate 				    filename, linenum);
8397c478bd9Sstevel@tonic-gate 			arg++;
8407c478bd9Sstevel@tonic-gate 			(void) memmove(p, p+1, strlen(p+1)+1);
8417c478bd9Sstevel@tonic-gate 		} else if (((p = strchr(arg, ':')) == NULL) ||
8427c478bd9Sstevel@tonic-gate 			    (strchr(p+1, ':') != NULL)) {
8437c478bd9Sstevel@tonic-gate 			add_listen_addr(options, arg, 0);
8447c478bd9Sstevel@tonic-gate 			break;
8457c478bd9Sstevel@tonic-gate 		}
8467c478bd9Sstevel@tonic-gate 		if (*p == ':') {
8477c478bd9Sstevel@tonic-gate 			u_short port;
8487c478bd9Sstevel@tonic-gate 
8497c478bd9Sstevel@tonic-gate 			p++;
8507c478bd9Sstevel@tonic-gate 			if (*p == '\0')
8517c478bd9Sstevel@tonic-gate 				fatal("%s line %d: bad inet addr:port usage.",
8527c478bd9Sstevel@tonic-gate 				    filename, linenum);
8537c478bd9Sstevel@tonic-gate 			else {
8547c478bd9Sstevel@tonic-gate 				*(p-1) = '\0';
8557c478bd9Sstevel@tonic-gate 				if ((port = a2port(p)) == 0)
8567c478bd9Sstevel@tonic-gate 					fatal("%s line %d: bad port number.",
8577c478bd9Sstevel@tonic-gate 					    filename, linenum);
8587c478bd9Sstevel@tonic-gate 				add_listen_addr(options, arg, port);
8597c478bd9Sstevel@tonic-gate 			}
8607c478bd9Sstevel@tonic-gate 		} else if (*p == '\0')
8617c478bd9Sstevel@tonic-gate 			add_listen_addr(options, arg, 0);
8627c478bd9Sstevel@tonic-gate 		else
8637c478bd9Sstevel@tonic-gate 			fatal("%s line %d: bad inet addr usage.",
8647c478bd9Sstevel@tonic-gate 			    filename, linenum);
8657c478bd9Sstevel@tonic-gate 		break;
8667c478bd9Sstevel@tonic-gate 
8677c478bd9Sstevel@tonic-gate 	case sHostKeyFile:
8687c478bd9Sstevel@tonic-gate 		intptr = &options->num_host_key_files;
8697c478bd9Sstevel@tonic-gate 		if (*intptr >= MAX_HOSTKEYS)
8707c478bd9Sstevel@tonic-gate 			fatal("%s line %d: too many host keys specified (max %d).",
8717c478bd9Sstevel@tonic-gate 			    filename, linenum, MAX_HOSTKEYS);
8727c478bd9Sstevel@tonic-gate 		charptr = &options->host_key_files[*intptr];
8737c478bd9Sstevel@tonic-gate parse_filename:
8747c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
8757c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0')
8767c478bd9Sstevel@tonic-gate 			fatal("%s line %d: missing file name.",
8777c478bd9Sstevel@tonic-gate 			    filename, linenum);
878b07b2f5cSHuie-Ying Lee 		if (*activep && *charptr == NULL) {
8797c478bd9Sstevel@tonic-gate 			*charptr = tilde_expand_filename(arg, getuid());
8807c478bd9Sstevel@tonic-gate 			/* increase optional counter */
8817c478bd9Sstevel@tonic-gate 			if (intptr != NULL)
8827c478bd9Sstevel@tonic-gate 				*intptr = *intptr + 1;
8837c478bd9Sstevel@tonic-gate 		}
8847c478bd9Sstevel@tonic-gate 		break;
8857c478bd9Sstevel@tonic-gate 
8867c478bd9Sstevel@tonic-gate 	case sPidFile:
8877c478bd9Sstevel@tonic-gate 		charptr = &options->pid_file;
8887c478bd9Sstevel@tonic-gate 		goto parse_filename;
8897c478bd9Sstevel@tonic-gate 
8907c478bd9Sstevel@tonic-gate 	case sPermitRootLogin:
8917c478bd9Sstevel@tonic-gate 		intptr = &options->permit_root_login;
8927c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
8937c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0')
8947c478bd9Sstevel@tonic-gate 			fatal("%s line %d: missing yes/"
8957c478bd9Sstevel@tonic-gate 			    "without-password/forced-commands-only/no "
8967c478bd9Sstevel@tonic-gate 			    "argument.", filename, linenum);
8977c478bd9Sstevel@tonic-gate 		value = 0;	/* silence compiler */
8987c478bd9Sstevel@tonic-gate 		if (strcmp(arg, "without-password") == 0)
8997c478bd9Sstevel@tonic-gate 			value = PERMIT_NO_PASSWD;
9007c478bd9Sstevel@tonic-gate 		else if (strcmp(arg, "forced-commands-only") == 0)
9017c478bd9Sstevel@tonic-gate 			value = PERMIT_FORCED_ONLY;
9027c478bd9Sstevel@tonic-gate 		else if (strcmp(arg, "yes") == 0)
9037c478bd9Sstevel@tonic-gate 			value = PERMIT_YES;
9047c478bd9Sstevel@tonic-gate 		else if (strcmp(arg, "no") == 0)
9057c478bd9Sstevel@tonic-gate 			value = PERMIT_NO;
9067c478bd9Sstevel@tonic-gate 		else
9077c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Bad yes/"
9087c478bd9Sstevel@tonic-gate 			    "without-password/forced-commands-only/no "
9097c478bd9Sstevel@tonic-gate 			    "argument: %s", filename, linenum, arg);
910b07b2f5cSHuie-Ying Lee 		if (*activep && *intptr == -1)
9117c478bd9Sstevel@tonic-gate 			*intptr = value;
9127c478bd9Sstevel@tonic-gate 		break;
9137c478bd9Sstevel@tonic-gate 
9147c478bd9Sstevel@tonic-gate 	case sIgnoreRhosts:
9157c478bd9Sstevel@tonic-gate 		intptr = &options->ignore_rhosts;
9167c478bd9Sstevel@tonic-gate parse_flag:
9177c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
9187c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0')
9197c478bd9Sstevel@tonic-gate 			fatal("%s line %d: missing yes/no argument.",
9207c478bd9Sstevel@tonic-gate 			    filename, linenum);
9217c478bd9Sstevel@tonic-gate 		value = 0;	/* silence compiler */
9227c478bd9Sstevel@tonic-gate 		if (strcmp(arg, "yes") == 0)
9237c478bd9Sstevel@tonic-gate 			value = 1;
9247c478bd9Sstevel@tonic-gate 		else if (strcmp(arg, "no") == 0)
9257c478bd9Sstevel@tonic-gate 			value = 0;
9267c478bd9Sstevel@tonic-gate 		else
9277c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Bad yes/no argument: %s",
9287c478bd9Sstevel@tonic-gate 				filename, linenum, arg);
929b07b2f5cSHuie-Ying Lee 		if (*activep && *intptr == -1)
9307c478bd9Sstevel@tonic-gate 			*intptr = value;
9317c478bd9Sstevel@tonic-gate 		break;
9327c478bd9Sstevel@tonic-gate 
9337c478bd9Sstevel@tonic-gate 	case sIgnoreUserKnownHosts:
9347c478bd9Sstevel@tonic-gate 		intptr = &options->ignore_user_known_hosts;
9357c478bd9Sstevel@tonic-gate 		goto parse_flag;
9367c478bd9Sstevel@tonic-gate 
9377c478bd9Sstevel@tonic-gate 	case sRhostsAuthentication:
9387c478bd9Sstevel@tonic-gate 		intptr = &options->rhosts_authentication;
9397c478bd9Sstevel@tonic-gate 		goto parse_flag;
9407c478bd9Sstevel@tonic-gate 
9417c478bd9Sstevel@tonic-gate 	case sRhostsRSAAuthentication:
9427c478bd9Sstevel@tonic-gate 		intptr = &options->rhosts_rsa_authentication;
9437c478bd9Sstevel@tonic-gate 		goto parse_flag;
9447c478bd9Sstevel@tonic-gate 
9457c478bd9Sstevel@tonic-gate 	case sHostbasedAuthentication:
9467c478bd9Sstevel@tonic-gate 		intptr = &options->hostbased_authentication;
9477c478bd9Sstevel@tonic-gate 		goto parse_flag;
9487c478bd9Sstevel@tonic-gate 
9497c478bd9Sstevel@tonic-gate 	case sHostbasedUsesNameFromPacketOnly:
9507c478bd9Sstevel@tonic-gate 		intptr = &options->hostbased_uses_name_from_packet_only;
9517c478bd9Sstevel@tonic-gate 		goto parse_flag;
9527c478bd9Sstevel@tonic-gate 
9537c478bd9Sstevel@tonic-gate 	case sRSAAuthentication:
9547c478bd9Sstevel@tonic-gate 		intptr = &options->rsa_authentication;
9557c478bd9Sstevel@tonic-gate 		goto parse_flag;
9567c478bd9Sstevel@tonic-gate 
9577c478bd9Sstevel@tonic-gate 	case sPubkeyAuthentication:
9587c478bd9Sstevel@tonic-gate 		intptr = &options->pubkey_authentication;
9597c478bd9Sstevel@tonic-gate 		goto parse_flag;
9607c478bd9Sstevel@tonic-gate #ifdef GSSAPI
9617c478bd9Sstevel@tonic-gate 	case sGssAuthentication:
9627c478bd9Sstevel@tonic-gate 		intptr = &options->gss_authentication;
9637c478bd9Sstevel@tonic-gate 		goto parse_flag;
9647c478bd9Sstevel@tonic-gate 	case sGssKeyEx:
9657c478bd9Sstevel@tonic-gate 		intptr = &options->gss_keyex;
9667c478bd9Sstevel@tonic-gate 		goto parse_flag;
9677c478bd9Sstevel@tonic-gate 	case sGssStoreDelegCreds:
9687c478bd9Sstevel@tonic-gate 		intptr = &options->gss_keyex;
9697c478bd9Sstevel@tonic-gate 		goto parse_flag;
9707c478bd9Sstevel@tonic-gate #ifndef SUNW_GSSAPI
9717c478bd9Sstevel@tonic-gate 	case sGssUseSessionCredCache:
9727c478bd9Sstevel@tonic-gate 		intptr = &options->gss_use_session_ccache;
9737c478bd9Sstevel@tonic-gate 		goto parse_flag;
9747c478bd9Sstevel@tonic-gate 	case sGssCleanupCreds:
9757c478bd9Sstevel@tonic-gate 		intptr = &options->gss_cleanup_creds;
9767c478bd9Sstevel@tonic-gate 		goto parse_flag;
9777c478bd9Sstevel@tonic-gate #endif /* SUNW_GSSAPI */
9787c478bd9Sstevel@tonic-gate #endif /* GSSAPI */
9797c478bd9Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5)
9807c478bd9Sstevel@tonic-gate 	case sKerberosAuthentication:
9817c478bd9Sstevel@tonic-gate 		intptr = &options->kerberos_authentication;
9827c478bd9Sstevel@tonic-gate 		goto parse_flag;
9837c478bd9Sstevel@tonic-gate 
9847c478bd9Sstevel@tonic-gate 	case sKerberosOrLocalPasswd:
9857c478bd9Sstevel@tonic-gate 		intptr = &options->kerberos_or_local_passwd;
9867c478bd9Sstevel@tonic-gate 		goto parse_flag;
9877c478bd9Sstevel@tonic-gate 
9887c478bd9Sstevel@tonic-gate 	case sKerberosTicketCleanup:
9897c478bd9Sstevel@tonic-gate 		intptr = &options->kerberos_ticket_cleanup;
9907c478bd9Sstevel@tonic-gate 		goto parse_flag;
9917c478bd9Sstevel@tonic-gate #endif
9927c478bd9Sstevel@tonic-gate #if defined(AFS) || defined(KRB5)
9937c478bd9Sstevel@tonic-gate 	case sKerberosTgtPassing:
9947c478bd9Sstevel@tonic-gate 		intptr = &options->kerberos_tgt_passing;
9957c478bd9Sstevel@tonic-gate 		goto parse_flag;
9967c478bd9Sstevel@tonic-gate #endif
9977c478bd9Sstevel@tonic-gate #ifdef AFS
9987c478bd9Sstevel@tonic-gate 	case sAFSTokenPassing:
9997c478bd9Sstevel@tonic-gate 		intptr = &options->afs_token_passing;
10007c478bd9Sstevel@tonic-gate 		goto parse_flag;
10017c478bd9Sstevel@tonic-gate #endif
10027c478bd9Sstevel@tonic-gate 
10037c478bd9Sstevel@tonic-gate 	case sPasswordAuthentication:
10047c478bd9Sstevel@tonic-gate 		intptr = &options->password_authentication;
10057c478bd9Sstevel@tonic-gate 		goto parse_flag;
10067c478bd9Sstevel@tonic-gate 
10077c478bd9Sstevel@tonic-gate 	case sKbdInteractiveAuthentication:
10087c478bd9Sstevel@tonic-gate 		intptr = &options->kbd_interactive_authentication;
10097c478bd9Sstevel@tonic-gate 		goto parse_flag;
10107c478bd9Sstevel@tonic-gate 
10117c478bd9Sstevel@tonic-gate 	case sChallengeResponseAuthentication:
10127c478bd9Sstevel@tonic-gate 		intptr = &options->challenge_response_authentication;
10137c478bd9Sstevel@tonic-gate 		goto parse_flag;
10147c478bd9Sstevel@tonic-gate 
10157c478bd9Sstevel@tonic-gate 	case sPrintMotd:
10167c478bd9Sstevel@tonic-gate 		intptr = &options->print_motd;
10177c478bd9Sstevel@tonic-gate 		goto parse_flag;
10187c478bd9Sstevel@tonic-gate 
10197c478bd9Sstevel@tonic-gate 	case sPrintLastLog:
10207c478bd9Sstevel@tonic-gate 		intptr = &options->print_lastlog;
10217c478bd9Sstevel@tonic-gate 		goto parse_flag;
10227c478bd9Sstevel@tonic-gate 
10237c478bd9Sstevel@tonic-gate 	case sX11Forwarding:
10247c478bd9Sstevel@tonic-gate 		intptr = &options->x11_forwarding;
10257c478bd9Sstevel@tonic-gate 		goto parse_flag;
10267c478bd9Sstevel@tonic-gate 
10277c478bd9Sstevel@tonic-gate 	case sX11DisplayOffset:
10287c478bd9Sstevel@tonic-gate 		intptr = &options->x11_display_offset;
10297c478bd9Sstevel@tonic-gate 		goto parse_int;
10307c478bd9Sstevel@tonic-gate 
10317c478bd9Sstevel@tonic-gate 	case sX11UseLocalhost:
10327c478bd9Sstevel@tonic-gate 		intptr = &options->x11_use_localhost;
10337c478bd9Sstevel@tonic-gate 		goto parse_flag;
10347c478bd9Sstevel@tonic-gate 
10357c478bd9Sstevel@tonic-gate 	case sXAuthLocation:
10367c478bd9Sstevel@tonic-gate 		charptr = &options->xauth_location;
10377c478bd9Sstevel@tonic-gate 		goto parse_filename;
10387c478bd9Sstevel@tonic-gate 
10397c478bd9Sstevel@tonic-gate 	case sStrictModes:
10407c478bd9Sstevel@tonic-gate 		intptr = &options->strict_modes;
10417c478bd9Sstevel@tonic-gate 		goto parse_flag;
10427c478bd9Sstevel@tonic-gate 
10437c478bd9Sstevel@tonic-gate 	case sKeepAlives:
10447c478bd9Sstevel@tonic-gate 		intptr = &options->keepalives;
10457c478bd9Sstevel@tonic-gate 		goto parse_flag;
10467c478bd9Sstevel@tonic-gate 
10477c478bd9Sstevel@tonic-gate 	case sEmptyPasswd:
10487c478bd9Sstevel@tonic-gate 		intptr = &options->permit_empty_passwd;
10497c478bd9Sstevel@tonic-gate 		goto parse_flag;
10507c478bd9Sstevel@tonic-gate 
10517c478bd9Sstevel@tonic-gate 	case sPermitUserEnvironment:
10527c478bd9Sstevel@tonic-gate 		intptr = &options->permit_user_env;
10537c478bd9Sstevel@tonic-gate 		goto parse_flag;
10547c478bd9Sstevel@tonic-gate 
10557c478bd9Sstevel@tonic-gate 	case sUseLogin:
1056b9aa66a7SJan Pechanec 		log("%s line %d: ignoring UseLogin option value."
1057b9aa66a7SJan Pechanec 		    " This option is always off.", filename, linenum);
1058b9aa66a7SJan Pechanec 		while (arg)
1059b9aa66a7SJan Pechanec 			arg = strdelim(&cp);
1060b9aa66a7SJan Pechanec 		break;
10617c478bd9Sstevel@tonic-gate 
10627c478bd9Sstevel@tonic-gate 	case sCompression:
10637c478bd9Sstevel@tonic-gate 		intptr = &options->compression;
10647c478bd9Sstevel@tonic-gate 		goto parse_flag;
10657c478bd9Sstevel@tonic-gate 
10667c478bd9Sstevel@tonic-gate 	case sGatewayPorts:
1067b07b2f5cSHuie-Ying Lee 		intptr = &options->gateway_ports;
10689b03ea0fSjp161948 		arg = strdelim(&cp);
1069b07b2f5cSHuie-Ying Lee 		if (!arg || *arg == '\0')
1070b07b2f5cSHuie-Ying Lee 			fatal("%s line %d: missing yes/no/clientspecified "
10719b03ea0fSjp161948 			    "argument.", filename, linenum);
1072b07b2f5cSHuie-Ying Lee 		value = 0;	/* silence compiler */
1073b07b2f5cSHuie-Ying Lee 		if (strcmp(arg, "clientspecified") == 0)
1074b07b2f5cSHuie-Ying Lee 			value = 2;
1075b07b2f5cSHuie-Ying Lee 		else if (strcmp(arg, "yes") == 0)
1076b07b2f5cSHuie-Ying Lee 			value = 1;
1077b07b2f5cSHuie-Ying Lee 		else if (strcmp(arg, "no") == 0)
1078b07b2f5cSHuie-Ying Lee 			value = 0;
1079b07b2f5cSHuie-Ying Lee 		else
1080b07b2f5cSHuie-Ying Lee 			fatal("%s line %d: Bad yes/no/clientspecified "
1081b07b2f5cSHuie-Ying Lee 			    "argument: %s", filename, linenum, arg);
1082b07b2f5cSHuie-Ying Lee 		if (*activep && *intptr == -1)
1083b07b2f5cSHuie-Ying Lee 			*intptr = value;
10849b03ea0fSjp161948 		break;
10857c478bd9Sstevel@tonic-gate 
10867c478bd9Sstevel@tonic-gate 	case sVerifyReverseMapping:
10877c478bd9Sstevel@tonic-gate 		intptr = &options->verify_reverse_mapping;
10887c478bd9Sstevel@tonic-gate 		goto parse_flag;
10897c478bd9Sstevel@tonic-gate 
10907c478bd9Sstevel@tonic-gate 	case sLogFacility:
10917c478bd9Sstevel@tonic-gate 		intptr = (int *) &options->log_facility;
10927c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
10937c478bd9Sstevel@tonic-gate 		value = log_facility_number(arg);
10947c478bd9Sstevel@tonic-gate 		if (value == SYSLOG_FACILITY_NOT_SET)
10957c478bd9Sstevel@tonic-gate 			fatal("%.200s line %d: unsupported log facility '%s'",
10967c478bd9Sstevel@tonic-gate 			    filename, linenum, arg ? arg : "<NONE>");
10977c478bd9Sstevel@tonic-gate 		if (*intptr == -1)
10987c478bd9Sstevel@tonic-gate 			*intptr = (SyslogFacility) value;
10997c478bd9Sstevel@tonic-gate 		break;
11007c478bd9Sstevel@tonic-gate 
11017c478bd9Sstevel@tonic-gate 	case sLogLevel:
11027c478bd9Sstevel@tonic-gate 		intptr = (int *) &options->log_level;
11037c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
11047c478bd9Sstevel@tonic-gate 		value = log_level_number(arg);
11057c478bd9Sstevel@tonic-gate 		if (value == SYSLOG_LEVEL_NOT_SET)
11067c478bd9Sstevel@tonic-gate 			fatal("%.200s line %d: unsupported log level '%s'",
11077c478bd9Sstevel@tonic-gate 			    filename, linenum, arg ? arg : "<NONE>");
11087c478bd9Sstevel@tonic-gate 		if (*intptr == -1)
11097c478bd9Sstevel@tonic-gate 			*intptr = (LogLevel) value;
11107c478bd9Sstevel@tonic-gate 		break;
11117c478bd9Sstevel@tonic-gate 
11127c478bd9Sstevel@tonic-gate 	case sAllowTcpForwarding:
11137c478bd9Sstevel@tonic-gate 		intptr = &options->allow_tcp_forwarding;
11147c478bd9Sstevel@tonic-gate 		goto parse_flag;
11157c478bd9Sstevel@tonic-gate 
11167c478bd9Sstevel@tonic-gate 	case sUsePrivilegeSeparation:
11179a8058b5Sjp161948 		log("%s line %d: ignoring UsePrivilegeSeparation option value."
11189a8058b5Sjp161948 		    " This option is always on.", filename, linenum);
11199a8058b5Sjp161948 		while (arg)
11209a8058b5Sjp161948 			arg = strdelim(&cp);
11219a8058b5Sjp161948 		break;
11227c478bd9Sstevel@tonic-gate 
11237c478bd9Sstevel@tonic-gate 	case sAllowUsers:
11247c478bd9Sstevel@tonic-gate 		while (((arg = strdelim(&cp)) != NULL) && *arg != '\0') {
11257c478bd9Sstevel@tonic-gate 			if (options->num_allow_users >= MAX_ALLOW_USERS)
11267c478bd9Sstevel@tonic-gate 				fatal("%s line %d: too many allow users.",
11277c478bd9Sstevel@tonic-gate 				    filename, linenum);
11287c478bd9Sstevel@tonic-gate 			options->allow_users[options->num_allow_users++] =
11297c478bd9Sstevel@tonic-gate 			    xstrdup(arg);
11307c478bd9Sstevel@tonic-gate 		}
11317c478bd9Sstevel@tonic-gate 		break;
11327c478bd9Sstevel@tonic-gate 
11337c478bd9Sstevel@tonic-gate 	case sDenyUsers:
11347c478bd9Sstevel@tonic-gate 		while (((arg = strdelim(&cp)) != NULL) && *arg != '\0') {
11357c478bd9Sstevel@tonic-gate 			if (options->num_deny_users >= MAX_DENY_USERS)
11367c478bd9Sstevel@tonic-gate 				fatal( "%s line %d: too many deny users.",
11377c478bd9Sstevel@tonic-gate 				    filename, linenum);
11387c478bd9Sstevel@tonic-gate 			options->deny_users[options->num_deny_users++] =
11397c478bd9Sstevel@tonic-gate 			    xstrdup(arg);
11407c478bd9Sstevel@tonic-gate 		}
11417c478bd9Sstevel@tonic-gate 		break;
11427c478bd9Sstevel@tonic-gate 
11437c478bd9Sstevel@tonic-gate 	case sAllowGroups:
11447c478bd9Sstevel@tonic-gate 		while (((arg = strdelim(&cp)) != NULL) && *arg != '\0') {
11457c478bd9Sstevel@tonic-gate 			if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
11467c478bd9Sstevel@tonic-gate 				fatal("%s line %d: too many allow groups.",
11477c478bd9Sstevel@tonic-gate 				    filename, linenum);
11487c478bd9Sstevel@tonic-gate 			options->allow_groups[options->num_allow_groups++] =
11497c478bd9Sstevel@tonic-gate 			    xstrdup(arg);
11507c478bd9Sstevel@tonic-gate 		}
11517c478bd9Sstevel@tonic-gate 		break;
11527c478bd9Sstevel@tonic-gate 
11537c478bd9Sstevel@tonic-gate 	case sDenyGroups:
11547c478bd9Sstevel@tonic-gate 		while (((arg = strdelim(&cp)) != NULL) && *arg != '\0') {
11557c478bd9Sstevel@tonic-gate 			if (options->num_deny_groups >= MAX_DENY_GROUPS)
11567c478bd9Sstevel@tonic-gate 				fatal("%s line %d: too many deny groups.",
11577c478bd9Sstevel@tonic-gate 				    filename, linenum);
11587c478bd9Sstevel@tonic-gate 			options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
11597c478bd9Sstevel@tonic-gate 		}
11607c478bd9Sstevel@tonic-gate 		break;
11617c478bd9Sstevel@tonic-gate 
11627c478bd9Sstevel@tonic-gate 	case sCiphers:
11637c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
11647c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0')
11657c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Missing argument.", filename, linenum);
11667c478bd9Sstevel@tonic-gate 		if (!ciphers_valid(arg))
11677c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
11687c478bd9Sstevel@tonic-gate 			    filename, linenum, arg ? arg : "<NONE>");
11697c478bd9Sstevel@tonic-gate 		if (options->ciphers == NULL)
11707c478bd9Sstevel@tonic-gate 			options->ciphers = xstrdup(arg);
11717c478bd9Sstevel@tonic-gate 		break;
11727c478bd9Sstevel@tonic-gate 
11737c478bd9Sstevel@tonic-gate 	case sMacs:
11747c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
11757c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0')
11767c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Missing argument.", filename, linenum);
11777c478bd9Sstevel@tonic-gate 		if (!mac_valid(arg))
11787c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Bad SSH2 mac spec '%s'.",
11797c478bd9Sstevel@tonic-gate 			    filename, linenum, arg ? arg : "<NONE>");
11807c478bd9Sstevel@tonic-gate 		if (options->macs == NULL)
11817c478bd9Sstevel@tonic-gate 			options->macs = xstrdup(arg);
11827c478bd9Sstevel@tonic-gate 		break;
11837c478bd9Sstevel@tonic-gate 
11847c478bd9Sstevel@tonic-gate 	case sProtocol:
11857c478bd9Sstevel@tonic-gate 		intptr = &options->protocol;
11867c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
11877c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0')
11887c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Missing argument.", filename, linenum);
11897c478bd9Sstevel@tonic-gate 		value = proto_spec(arg);
11907c478bd9Sstevel@tonic-gate 		if (value == SSH_PROTO_UNKNOWN)
11917c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Bad protocol spec '%s'.",
11927c478bd9Sstevel@tonic-gate 			    filename, linenum, arg ? arg : "<NONE>");
11937c478bd9Sstevel@tonic-gate 		if (*intptr == SSH_PROTO_UNKNOWN)
11947c478bd9Sstevel@tonic-gate 			*intptr = value;
11957c478bd9Sstevel@tonic-gate 		break;
11967c478bd9Sstevel@tonic-gate 
11977c478bd9Sstevel@tonic-gate 	case sSubsystem:
11987c478bd9Sstevel@tonic-gate 		if (options->num_subsystems >= MAX_SUBSYSTEMS) {
11997c478bd9Sstevel@tonic-gate 			fatal("%s line %d: too many subsystems defined.",
12007c478bd9Sstevel@tonic-gate 			    filename, linenum);
12017c478bd9Sstevel@tonic-gate 		}
12027c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
12037c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0')
12047c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Missing subsystem name.",
12057c478bd9Sstevel@tonic-gate 			    filename, linenum);
1206b07b2f5cSHuie-Ying Lee 		if (!*activep) {
1207b07b2f5cSHuie-Ying Lee 			arg = strdelim(&cp);
1208b07b2f5cSHuie-Ying Lee 			break;
1209b07b2f5cSHuie-Ying Lee 		}
12107c478bd9Sstevel@tonic-gate 		for (i = 0; i < options->num_subsystems; i++)
12117c478bd9Sstevel@tonic-gate 			if (strcmp(arg, options->subsystem_name[i]) == 0)
12127c478bd9Sstevel@tonic-gate 				fatal("%s line %d: Subsystem '%s' already defined.",
12137c478bd9Sstevel@tonic-gate 				    filename, linenum, arg);
12147c478bd9Sstevel@tonic-gate 		options->subsystem_name[options->num_subsystems] = xstrdup(arg);
12157c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
12167c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0')
12177c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Missing subsystem command.",
12187c478bd9Sstevel@tonic-gate 			    filename, linenum);
12197c478bd9Sstevel@tonic-gate 		options->subsystem_command[options->num_subsystems] = xstrdup(arg);
12206f8d59d8SJan Pechanec 
12216f8d59d8SJan Pechanec 		/*
12226f8d59d8SJan Pechanec 		 * Collect arguments (separate to executable), including the
12236f8d59d8SJan Pechanec 		 * name of the executable, in a way that is easier to parse
12246f8d59d8SJan Pechanec 		 * later.
12256f8d59d8SJan Pechanec 		 */
12266f8d59d8SJan Pechanec 		p = xstrdup(arg);
12276f8d59d8SJan Pechanec 		len = strlen(p) + 1;
12286f8d59d8SJan Pechanec 		while ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
12296f8d59d8SJan Pechanec 			len += 1 + strlen(arg);
12306f8d59d8SJan Pechanec 			p = xrealloc(p, len);
12316f8d59d8SJan Pechanec 			strlcat(p, " ", len);
12326f8d59d8SJan Pechanec 			strlcat(p, arg, len);
12336f8d59d8SJan Pechanec 		}
12346f8d59d8SJan Pechanec 		options->subsystem_args[options->num_subsystems] = p;
12357c478bd9Sstevel@tonic-gate 		options->num_subsystems++;
12367c478bd9Sstevel@tonic-gate 		break;
12377c478bd9Sstevel@tonic-gate 
12387c478bd9Sstevel@tonic-gate 	case sMaxStartups:
12397c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
12407c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0')
12417c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Missing MaxStartups spec.",
12427c478bd9Sstevel@tonic-gate 			    filename, linenum);
12437c478bd9Sstevel@tonic-gate 		if ((n = sscanf(arg, "%d:%d:%d",
12447c478bd9Sstevel@tonic-gate 		    &options->max_startups_begin,
12457c478bd9Sstevel@tonic-gate 		    &options->max_startups_rate,
12467c478bd9Sstevel@tonic-gate 		    &options->max_startups)) == 3) {
12477c478bd9Sstevel@tonic-gate 			if (options->max_startups_begin >
12487c478bd9Sstevel@tonic-gate 			    options->max_startups ||
12497c478bd9Sstevel@tonic-gate 			    options->max_startups_rate > 100 ||
12507c478bd9Sstevel@tonic-gate 			    options->max_startups_rate < 1)
12517c478bd9Sstevel@tonic-gate 				fatal("%s line %d: Illegal MaxStartups spec.",
12527c478bd9Sstevel@tonic-gate 				    filename, linenum);
12537c478bd9Sstevel@tonic-gate 		} else if (n != 1)
12547c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Illegal MaxStartups spec.",
12557c478bd9Sstevel@tonic-gate 			    filename, linenum);
12567c478bd9Sstevel@tonic-gate 		else
12577c478bd9Sstevel@tonic-gate 			options->max_startups = options->max_startups_begin;
12587c478bd9Sstevel@tonic-gate 		break;
12597c478bd9Sstevel@tonic-gate 
12607c478bd9Sstevel@tonic-gate 	case sBanner:
12617c478bd9Sstevel@tonic-gate 		charptr = &options->banner;
12627c478bd9Sstevel@tonic-gate 		goto parse_filename;
12637c478bd9Sstevel@tonic-gate 	/*
12647c478bd9Sstevel@tonic-gate 	 * These options can contain %X options expanded at
12657c478bd9Sstevel@tonic-gate 	 * connect time, so that you can specify paths like:
12667c478bd9Sstevel@tonic-gate 	 *
12677c478bd9Sstevel@tonic-gate 	 * AuthorizedKeysFile	/etc/ssh_keys/%u
12687c478bd9Sstevel@tonic-gate 	 */
12697c478bd9Sstevel@tonic-gate 	case sAuthorizedKeysFile:
12707c478bd9Sstevel@tonic-gate 	case sAuthorizedKeysFile2:
12717c478bd9Sstevel@tonic-gate 		charptr = (opcode == sAuthorizedKeysFile) ?
12727c478bd9Sstevel@tonic-gate 		    &options->authorized_keys_file :
12737c478bd9Sstevel@tonic-gate 		    &options->authorized_keys_file2;
12747c478bd9Sstevel@tonic-gate 		goto parse_filename;
12757c478bd9Sstevel@tonic-gate 
12767c478bd9Sstevel@tonic-gate 	case sClientAliveInterval:
12777c478bd9Sstevel@tonic-gate 		intptr = &options->client_alive_interval;
12787c478bd9Sstevel@tonic-gate 		goto parse_time;
12797c478bd9Sstevel@tonic-gate 
12807c478bd9Sstevel@tonic-gate 	case sClientAliveCountMax:
12817c478bd9Sstevel@tonic-gate 		intptr = &options->client_alive_count_max;
12827c478bd9Sstevel@tonic-gate 		goto parse_int;
12837c478bd9Sstevel@tonic-gate 
12847c478bd9Sstevel@tonic-gate 	case sMaxAuthTries:
12857c478bd9Sstevel@tonic-gate 		intptr = &options->max_auth_tries;
12867c478bd9Sstevel@tonic-gate 		goto parse_int;
12877c478bd9Sstevel@tonic-gate 
12887c478bd9Sstevel@tonic-gate 	case sMaxAuthTriesLog:
12897c478bd9Sstevel@tonic-gate 		intptr = &options->max_auth_tries_log;
12907c478bd9Sstevel@tonic-gate 		goto parse_int;
12917c478bd9Sstevel@tonic-gate 
12927c478bd9Sstevel@tonic-gate 	case sLookupClientHostnames:
12937c478bd9Sstevel@tonic-gate 		intptr = &options->lookup_client_hostnames;
12947c478bd9Sstevel@tonic-gate 		goto parse_flag;
12956f8d59d8SJan Pechanec 
1296cd7d5fafSJan Pechanec 	case sUseOpenSSLEngine:
1297cd7d5fafSJan Pechanec 		intptr = &options->use_openssl_engine;
1298cd7d5fafSJan Pechanec 		goto parse_flag;
12997c478bd9Sstevel@tonic-gate 
13006f8d59d8SJan Pechanec 	case sChrootDirectory:
13016f8d59d8SJan Pechanec 		charptr = &options->chroot_directory;
13026f8d59d8SJan Pechanec 
13036f8d59d8SJan Pechanec 		arg = strdelim(&cp);
13046f8d59d8SJan Pechanec 		if (arg == NULL || *arg == '\0')
13056f8d59d8SJan Pechanec 			fatal("%s line %d: missing directory name for "
13066f8d59d8SJan Pechanec 			    "ChrootDirectory.", filename, linenum);
1307b07b2f5cSHuie-Ying Lee 		if (*activep && *charptr == NULL)
13086f8d59d8SJan Pechanec 			*charptr = xstrdup(arg);
13096f8d59d8SJan Pechanec 		break;
13106f8d59d8SJan Pechanec 
1311d8a94255SErik Trauschke 	case sPreUserauthHook:
1312d8a94255SErik Trauschke 		charptr = &options->pre_userauth_hook;
1313d8a94255SErik Trauschke 		goto parse_filename;
1314d8a94255SErik Trauschke 
1315b07b2f5cSHuie-Ying Lee 	case sMatch:
1316b07b2f5cSHuie-Ying Lee 		if (cmdline)
1317b07b2f5cSHuie-Ying Lee 			fatal("Match directive not supported as a command-line "
1318b07b2f5cSHuie-Ying Lee 			   "option");
1319b07b2f5cSHuie-Ying Lee 		value = match_cfg_line(&cp, linenum, user, host, address);
1320b07b2f5cSHuie-Ying Lee 		if (value < 0)
1321b07b2f5cSHuie-Ying Lee 			fatal("%s line %d: Bad Match condition", filename,
1322b07b2f5cSHuie-Ying Lee 			    linenum);
1323b07b2f5cSHuie-Ying Lee 		*activep = value;
1324b07b2f5cSHuie-Ying Lee 		break;
1325b07b2f5cSHuie-Ying Lee 
13267c478bd9Sstevel@tonic-gate 	case sDeprecated:
13277c478bd9Sstevel@tonic-gate 		log("%s line %d: Deprecated option %s",
13287c478bd9Sstevel@tonic-gate 		    filename, linenum, arg);
13297c478bd9Sstevel@tonic-gate 		while (arg)
13307c478bd9Sstevel@tonic-gate 		    arg = strdelim(&cp);
13317c478bd9Sstevel@tonic-gate 		break;
13327c478bd9Sstevel@tonic-gate 
1333bdb005b5SDarren J Moffat 	case sPAMServicePrefix:
1334bdb005b5SDarren J Moffat 		arg = strdelim(&cp);
1335bdb005b5SDarren J Moffat 		if (!arg || *arg == '\0')
1336bdb005b5SDarren J Moffat 			fatal("%s line %d: Missing argument.",
1337bdb005b5SDarren J Moffat 			    filename, linenum);
1338bdb005b5SDarren J Moffat 		if (options->pam_service_name != NULL)
1339bdb005b5SDarren J Moffat 			fatal("%s line %d: PAMServiceName and PAMServicePrefix "
1340bdb005b5SDarren J Moffat 			    "are mutually exclusive.", filename, linenum);
1341bdb005b5SDarren J Moffat 		if (options->pam_service_prefix == NULL)
1342bdb005b5SDarren J Moffat 			options->pam_service_prefix = xstrdup(arg);
1343bdb005b5SDarren J Moffat 		break;
1344bdb005b5SDarren J Moffat 
1345bdb005b5SDarren J Moffat 	case sPAMServiceName:
1346bdb005b5SDarren J Moffat 		arg = strdelim(&cp);
1347bdb005b5SDarren J Moffat 		if (!arg || *arg == '\0')
1348bdb005b5SDarren J Moffat 			fatal("%s line %d: Missing argument.",
1349bdb005b5SDarren J Moffat 			    filename, linenum);
1350bdb005b5SDarren J Moffat 		if (options->pam_service_prefix != NULL)
1351bdb005b5SDarren J Moffat 			fatal("%s line %d: PAMServiceName and PAMServicePrefix "
1352bdb005b5SDarren J Moffat 			    "are mutually exclusive.", filename, linenum);
1353bdb005b5SDarren J Moffat 		if (options->pam_service_name == NULL)
1354bdb005b5SDarren J Moffat 			options->pam_service_name = xstrdup(arg);
1355bdb005b5SDarren J Moffat 		break;
1356bdb005b5SDarren J Moffat 
13577c478bd9Sstevel@tonic-gate 	default:
13587c478bd9Sstevel@tonic-gate 		fatal("%s line %d: Missing handler for opcode %s (%d)",
13597c478bd9Sstevel@tonic-gate 		    filename, linenum, arg, opcode);
13607c478bd9Sstevel@tonic-gate 	}
13617c478bd9Sstevel@tonic-gate 	if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
13627c478bd9Sstevel@tonic-gate 		fatal("%s line %d: garbage at end of line; \"%.200s\".",
13637c478bd9Sstevel@tonic-gate 		    filename, linenum, arg);
13647c478bd9Sstevel@tonic-gate 	return 0;
13657c478bd9Sstevel@tonic-gate }
13667c478bd9Sstevel@tonic-gate 
1367b07b2f5cSHuie-Ying Lee 
13687c478bd9Sstevel@tonic-gate /* Reads the server configuration file. */
13697c478bd9Sstevel@tonic-gate 
13707c478bd9Sstevel@tonic-gate void
1371b07b2f5cSHuie-Ying Lee load_server_config(const char *filename, Buffer *conf)
13727c478bd9Sstevel@tonic-gate {
1373b07b2f5cSHuie-Ying Lee 	char line[1024], *cp;
13747c478bd9Sstevel@tonic-gate 	FILE *f;
13757c478bd9Sstevel@tonic-gate 
1376b07b2f5cSHuie-Ying Lee 	debug2("%s: filename %s", __func__, filename);
1377b07b2f5cSHuie-Ying Lee 	if ((f = fopen(filename, "r")) == NULL) {
13787c478bd9Sstevel@tonic-gate 		perror(filename);
13797c478bd9Sstevel@tonic-gate 		exit(1);
13807c478bd9Sstevel@tonic-gate 	}
1381b07b2f5cSHuie-Ying Lee 	buffer_clear(conf);
13827c478bd9Sstevel@tonic-gate 	while (fgets(line, sizeof(line), f)) {
1383b07b2f5cSHuie-Ying Lee 		/*
1384b07b2f5cSHuie-Ying Lee 		 * Trim out comments and strip whitespace
1385b07b2f5cSHuie-Ying Lee 		 * NB - preserve newlines, they are needed to reproduce
1386b07b2f5cSHuie-Ying Lee 		 * line numbers later for error messages
1387b07b2f5cSHuie-Ying Lee 		 */
1388b07b2f5cSHuie-Ying Lee 		if ((cp = strchr(line, '#')) != NULL)
1389b07b2f5cSHuie-Ying Lee 			memcpy(cp, "\n", 2);
1390b07b2f5cSHuie-Ying Lee 		cp = line + strspn(line, " \t\r");
1391b07b2f5cSHuie-Ying Lee 
1392b07b2f5cSHuie-Ying Lee 		buffer_append(conf, cp, strlen(cp));
1393b07b2f5cSHuie-Ying Lee 	}
1394b07b2f5cSHuie-Ying Lee 	buffer_append(conf, "\0", 1);
1395b07b2f5cSHuie-Ying Lee 	fclose(f);
1396b07b2f5cSHuie-Ying Lee 	debug2("%s: done config len = %d", __func__, buffer_len(conf));
1397b07b2f5cSHuie-Ying Lee }
1398b07b2f5cSHuie-Ying Lee 
1399b07b2f5cSHuie-Ying Lee void
1400b07b2f5cSHuie-Ying Lee parse_server_match_config(ServerOptions *options, const char *user,
1401b07b2f5cSHuie-Ying Lee     const char *host, const char *address)
1402b07b2f5cSHuie-Ying Lee {
1403b07b2f5cSHuie-Ying Lee 	ServerOptions mo;
1404b07b2f5cSHuie-Ying Lee 
1405b07b2f5cSHuie-Ying Lee 	initialize_server_options(&mo);
1406b07b2f5cSHuie-Ying Lee 	parse_server_config(&mo, "reprocess config", &cfg, user, host, address);
1407b07b2f5cSHuie-Ying Lee 	copy_set_server_options(options, &mo, 0);
1408b07b2f5cSHuie-Ying Lee }
1409b07b2f5cSHuie-Ying Lee 
1410b07b2f5cSHuie-Ying Lee 
1411b07b2f5cSHuie-Ying Lee 
1412b07b2f5cSHuie-Ying Lee /* Helper macros */
1413b07b2f5cSHuie-Ying Lee #define M_CP_INTOPT(n) do {\
1414b07b2f5cSHuie-Ying Lee 	if (src->n != -1) \
1415b07b2f5cSHuie-Ying Lee 		dst->n = src->n; \
1416b07b2f5cSHuie-Ying Lee } while (0)
1417b07b2f5cSHuie-Ying Lee #define M_CP_STROPT(n) do {\
1418b07b2f5cSHuie-Ying Lee 	if (src->n != NULL) { \
1419b07b2f5cSHuie-Ying Lee 		if (dst->n != NULL) \
1420b07b2f5cSHuie-Ying Lee 			xfree(dst->n); \
1421b07b2f5cSHuie-Ying Lee 		dst->n = src->n; \
1422b07b2f5cSHuie-Ying Lee 	} \
1423b07b2f5cSHuie-Ying Lee } while(0)
1424b07b2f5cSHuie-Ying Lee 
1425b07b2f5cSHuie-Ying Lee /*
1426b07b2f5cSHuie-Ying Lee  * Copy any supported values that are set.
1427b07b2f5cSHuie-Ying Lee  *
1428b07b2f5cSHuie-Ying Lee  * If the preauth flag is set, we do not bother copying the the string or
1429b07b2f5cSHuie-Ying Lee  * array values that are not used pre-authentication, because any that we
1430b07b2f5cSHuie-Ying Lee  * do use must be explictly sent in mm_getpwnamallow().
1431b07b2f5cSHuie-Ying Lee  */
1432b07b2f5cSHuie-Ying Lee void
1433b07b2f5cSHuie-Ying Lee copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
1434b07b2f5cSHuie-Ying Lee {
1435b07b2f5cSHuie-Ying Lee 	M_CP_INTOPT(password_authentication);
1436b07b2f5cSHuie-Ying Lee 	M_CP_INTOPT(gss_authentication);
1437b07b2f5cSHuie-Ying Lee 	M_CP_INTOPT(rsa_authentication);
1438b07b2f5cSHuie-Ying Lee 	M_CP_INTOPT(pubkey_authentication);
1439b07b2f5cSHuie-Ying Lee 	M_CP_INTOPT(hostbased_authentication);
1440b07b2f5cSHuie-Ying Lee 	M_CP_INTOPT(kbd_interactive_authentication);
1441b07b2f5cSHuie-Ying Lee 	M_CP_INTOPT(permit_root_login);
1442b07b2f5cSHuie-Ying Lee 	M_CP_INTOPT(permit_empty_passwd);
1443b07b2f5cSHuie-Ying Lee 	M_CP_INTOPT(allow_tcp_forwarding);
1444b07b2f5cSHuie-Ying Lee 	M_CP_INTOPT(gateway_ports);
1445b07b2f5cSHuie-Ying Lee 	M_CP_INTOPT(x11_display_offset);
1446b07b2f5cSHuie-Ying Lee 	M_CP_INTOPT(x11_forwarding);
1447b07b2f5cSHuie-Ying Lee 	M_CP_INTOPT(x11_use_localhost);
1448b07b2f5cSHuie-Ying Lee 	M_CP_INTOPT(max_auth_tries);
1449b07b2f5cSHuie-Ying Lee 	M_CP_STROPT(banner);
1450b07b2f5cSHuie-Ying Lee 
1451b07b2f5cSHuie-Ying Lee 	if (preauth)
1452b07b2f5cSHuie-Ying Lee 		return;
1453b07b2f5cSHuie-Ying Lee 	M_CP_STROPT(chroot_directory);
1454b07b2f5cSHuie-Ying Lee }
1455b07b2f5cSHuie-Ying Lee 
1456b07b2f5cSHuie-Ying Lee #undef M_CP_INTOPT
1457b07b2f5cSHuie-Ying Lee #undef M_CP_STROPT
1458b07b2f5cSHuie-Ying Lee 
1459b07b2f5cSHuie-Ying Lee void
1460b07b2f5cSHuie-Ying Lee parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
1461b07b2f5cSHuie-Ying Lee     const char *user, const char *host, const char *address)
1462b07b2f5cSHuie-Ying Lee {
1463b07b2f5cSHuie-Ying Lee 	int active, linenum, bad_options = 0;
1464b07b2f5cSHuie-Ying Lee 	char *cp, *obuf, *cbuf;
1465b07b2f5cSHuie-Ying Lee 
1466b07b2f5cSHuie-Ying Lee 	debug2("%s: config %s len %d", __func__, filename, buffer_len(conf));
1467b07b2f5cSHuie-Ying Lee 
1468b07b2f5cSHuie-Ying Lee 	obuf = cbuf = xstrdup(buffer_ptr(conf));
1469b07b2f5cSHuie-Ying Lee 	active = user ? 0 : 1;
1470b07b2f5cSHuie-Ying Lee 	linenum = 1;
1471b07b2f5cSHuie-Ying Lee 	while ((cp = strsep(&cbuf, "\n")) != NULL) {
1472b07b2f5cSHuie-Ying Lee 		if (process_server_config_line(options, cp, filename,
1473b07b2f5cSHuie-Ying Lee 		    linenum++, &active, user, host, address) != 0)
14747c478bd9Sstevel@tonic-gate 			bad_options++;
14757c478bd9Sstevel@tonic-gate 	}
1476b07b2f5cSHuie-Ying Lee 	xfree(obuf);
14777c478bd9Sstevel@tonic-gate 	if (bad_options > 0)
14787c478bd9Sstevel@tonic-gate 		fatal("%s: terminating, %d bad configuration options",
14797c478bd9Sstevel@tonic-gate 		    filename, bad_options);
14807c478bd9Sstevel@tonic-gate }
14816f8d59d8SJan Pechanec 
1482b07b2f5cSHuie-Ying Lee 
14836f8d59d8SJan Pechanec /*
14846f8d59d8SJan Pechanec  * Note that "none" is a special path having the same affect on sshd
14856f8d59d8SJan Pechanec  * configuration as not specifying ChrootDirectory at all.
14866f8d59d8SJan Pechanec  */
14876f8d59d8SJan Pechanec int
14886f8d59d8SJan Pechanec chroot_requested(char *chroot_directory)
14896f8d59d8SJan Pechanec {
14906f8d59d8SJan Pechanec 	return (chroot_directory != NULL &&
14916f8d59d8SJan Pechanec 	    strcasecmp(chroot_directory, "none") != 0);
14926f8d59d8SJan Pechanec }
1493