xref: /titanic_50/usr/src/cmd/ssh/sshd/servconf.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
3*7c478bd9Sstevel@tonic-gate  *                    All rights reserved
4*7c478bd9Sstevel@tonic-gate  *
5*7c478bd9Sstevel@tonic-gate  * As far as I am concerned, the code I have written for this software
6*7c478bd9Sstevel@tonic-gate  * can be used freely for any purpose.  Any derived versions of this
7*7c478bd9Sstevel@tonic-gate  * software must be clearly marked as such, and if the derived work is
8*7c478bd9Sstevel@tonic-gate  * incompatible with the protocol description in the RFC file, it must be
9*7c478bd9Sstevel@tonic-gate  * called by a name other than "ssh" or "Secure Shell".
10*7c478bd9Sstevel@tonic-gate  */
11*7c478bd9Sstevel@tonic-gate /*
12*7c478bd9Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
13*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
14*7c478bd9Sstevel@tonic-gate  */
15*7c478bd9Sstevel@tonic-gate 
16*7c478bd9Sstevel@tonic-gate #include "includes.h"
17*7c478bd9Sstevel@tonic-gate RCSID("$OpenBSD: servconf.c,v 1.115 2002/09/04 18:52:42 stevesk Exp $");
18*7c478bd9Sstevel@tonic-gate 
19*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
20*7c478bd9Sstevel@tonic-gate 
21*7c478bd9Sstevel@tonic-gate #ifdef HAVE_DEFOPEN
22*7c478bd9Sstevel@tonic-gate #include <deflt.h>
23*7c478bd9Sstevel@tonic-gate #endif /* HAVE_DEFOPEN */
24*7c478bd9Sstevel@tonic-gate 
25*7c478bd9Sstevel@tonic-gate #if defined(KRB4)
26*7c478bd9Sstevel@tonic-gate #include <krb.h>
27*7c478bd9Sstevel@tonic-gate #endif
28*7c478bd9Sstevel@tonic-gate #if defined(KRB5)
29*7c478bd9Sstevel@tonic-gate #ifdef HEIMDAL
30*7c478bd9Sstevel@tonic-gate #include <krb.h>
31*7c478bd9Sstevel@tonic-gate #else
32*7c478bd9Sstevel@tonic-gate /* Bodge - but then, so is using the kerberos IV KEYFILE to get a Kerberos V
33*7c478bd9Sstevel@tonic-gate  * keytab */
34*7c478bd9Sstevel@tonic-gate #define KEYFILE "/etc/krb5.keytab"
35*7c478bd9Sstevel@tonic-gate #endif
36*7c478bd9Sstevel@tonic-gate #endif
37*7c478bd9Sstevel@tonic-gate #ifdef AFS
38*7c478bd9Sstevel@tonic-gate #include <kafs.h>
39*7c478bd9Sstevel@tonic-gate #endif
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate #include "ssh.h"
42*7c478bd9Sstevel@tonic-gate #include "log.h"
43*7c478bd9Sstevel@tonic-gate #include "servconf.h"
44*7c478bd9Sstevel@tonic-gate #include "xmalloc.h"
45*7c478bd9Sstevel@tonic-gate #include "compat.h"
46*7c478bd9Sstevel@tonic-gate #include "pathnames.h"
47*7c478bd9Sstevel@tonic-gate #include "tildexpand.h"
48*7c478bd9Sstevel@tonic-gate #include "misc.h"
49*7c478bd9Sstevel@tonic-gate #include "cipher.h"
50*7c478bd9Sstevel@tonic-gate #include "kex.h"
51*7c478bd9Sstevel@tonic-gate #include "mac.h"
52*7c478bd9Sstevel@tonic-gate #include "auth.h"
53*7c478bd9Sstevel@tonic-gate 
54*7c478bd9Sstevel@tonic-gate static void add_listen_addr(ServerOptions *, char *, u_short);
55*7c478bd9Sstevel@tonic-gate static void add_one_listen_addr(ServerOptions *, char *, u_short);
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate /* AF_UNSPEC or AF_INET or AF_INET6 */
58*7c478bd9Sstevel@tonic-gate extern int IPv4or6;
59*7c478bd9Sstevel@tonic-gate /* Use of privilege separation or not */
60*7c478bd9Sstevel@tonic-gate extern int use_privsep;
61*7c478bd9Sstevel@tonic-gate 
62*7c478bd9Sstevel@tonic-gate /* Initializes the server options to their default values. */
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate void
65*7c478bd9Sstevel@tonic-gate initialize_server_options(ServerOptions *options)
66*7c478bd9Sstevel@tonic-gate {
67*7c478bd9Sstevel@tonic-gate 	(void) memset(options, 0, sizeof(*options));
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate 	/* Portable-specific options */
70*7c478bd9Sstevel@tonic-gate 	options->pam_authentication_via_kbd_int = -1;
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate 	/* Standard Options */
73*7c478bd9Sstevel@tonic-gate 	options->num_ports = 0;
74*7c478bd9Sstevel@tonic-gate 	options->ports_from_cmdline = 0;
75*7c478bd9Sstevel@tonic-gate 	options->listen_addrs = NULL;
76*7c478bd9Sstevel@tonic-gate 	options->num_host_key_files = 0;
77*7c478bd9Sstevel@tonic-gate 	options->pid_file = NULL;
78*7c478bd9Sstevel@tonic-gate 	options->server_key_bits = -1;
79*7c478bd9Sstevel@tonic-gate 	options->login_grace_time = -1;
80*7c478bd9Sstevel@tonic-gate 	options->key_regeneration_time = -1;
81*7c478bd9Sstevel@tonic-gate 	options->permit_root_login = PERMIT_NOT_SET;
82*7c478bd9Sstevel@tonic-gate 	options->ignore_rhosts = -1;
83*7c478bd9Sstevel@tonic-gate 	options->ignore_user_known_hosts = -1;
84*7c478bd9Sstevel@tonic-gate 	options->print_motd = -1;
85*7c478bd9Sstevel@tonic-gate 	options->print_lastlog = -1;
86*7c478bd9Sstevel@tonic-gate 	options->x11_forwarding = -1;
87*7c478bd9Sstevel@tonic-gate 	options->x11_display_offset = -1;
88*7c478bd9Sstevel@tonic-gate 	options->x11_use_localhost = -1;
89*7c478bd9Sstevel@tonic-gate 	options->xauth_location = NULL;
90*7c478bd9Sstevel@tonic-gate 	options->strict_modes = -1;
91*7c478bd9Sstevel@tonic-gate 	options->keepalives = -1;
92*7c478bd9Sstevel@tonic-gate 	options->log_facility = SYSLOG_FACILITY_NOT_SET;
93*7c478bd9Sstevel@tonic-gate 	options->log_level = SYSLOG_LEVEL_NOT_SET;
94*7c478bd9Sstevel@tonic-gate 	options->rhosts_authentication = -1;
95*7c478bd9Sstevel@tonic-gate 	options->rhosts_rsa_authentication = -1;
96*7c478bd9Sstevel@tonic-gate 	options->hostbased_authentication = -1;
97*7c478bd9Sstevel@tonic-gate 	options->hostbased_uses_name_from_packet_only = -1;
98*7c478bd9Sstevel@tonic-gate 	options->rsa_authentication = -1;
99*7c478bd9Sstevel@tonic-gate 	options->pubkey_authentication = -1;
100*7c478bd9Sstevel@tonic-gate #ifdef GSSAPI
101*7c478bd9Sstevel@tonic-gate 	options->gss_authentication = -1;
102*7c478bd9Sstevel@tonic-gate 	options->gss_keyex = -1;
103*7c478bd9Sstevel@tonic-gate 	options->gss_store_creds = -1;
104*7c478bd9Sstevel@tonic-gate 	options->gss_use_session_ccache = -1;
105*7c478bd9Sstevel@tonic-gate 	options->gss_cleanup_creds = -1;
106*7c478bd9Sstevel@tonic-gate #endif
107*7c478bd9Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5)
108*7c478bd9Sstevel@tonic-gate 	options->kerberos_authentication = -1;
109*7c478bd9Sstevel@tonic-gate 	options->kerberos_or_local_passwd = -1;
110*7c478bd9Sstevel@tonic-gate 	options->kerberos_ticket_cleanup = -1;
111*7c478bd9Sstevel@tonic-gate #endif
112*7c478bd9Sstevel@tonic-gate #if defined(AFS) || defined(KRB5)
113*7c478bd9Sstevel@tonic-gate 	options->kerberos_tgt_passing = -1;
114*7c478bd9Sstevel@tonic-gate #endif
115*7c478bd9Sstevel@tonic-gate #ifdef AFS
116*7c478bd9Sstevel@tonic-gate 	options->afs_token_passing = -1;
117*7c478bd9Sstevel@tonic-gate #endif
118*7c478bd9Sstevel@tonic-gate 	options->password_authentication = -1;
119*7c478bd9Sstevel@tonic-gate 	options->kbd_interactive_authentication = -1;
120*7c478bd9Sstevel@tonic-gate 	options->challenge_response_authentication = -1;
121*7c478bd9Sstevel@tonic-gate 	options->permit_empty_passwd = -1;
122*7c478bd9Sstevel@tonic-gate 	options->permit_user_env = -1;
123*7c478bd9Sstevel@tonic-gate 	options->use_login = -1;
124*7c478bd9Sstevel@tonic-gate 	options->compression = -1;
125*7c478bd9Sstevel@tonic-gate 	options->allow_tcp_forwarding = -1;
126*7c478bd9Sstevel@tonic-gate 	options->num_allow_users = 0;
127*7c478bd9Sstevel@tonic-gate 	options->num_deny_users = 0;
128*7c478bd9Sstevel@tonic-gate 	options->num_allow_groups = 0;
129*7c478bd9Sstevel@tonic-gate 	options->num_deny_groups = 0;
130*7c478bd9Sstevel@tonic-gate 	options->ciphers = NULL;
131*7c478bd9Sstevel@tonic-gate 	options->macs = NULL;
132*7c478bd9Sstevel@tonic-gate 	options->protocol = SSH_PROTO_UNKNOWN;
133*7c478bd9Sstevel@tonic-gate 	options->gateway_ports = -1;
134*7c478bd9Sstevel@tonic-gate 	options->num_subsystems = 0;
135*7c478bd9Sstevel@tonic-gate 	options->max_startups_begin = -1;
136*7c478bd9Sstevel@tonic-gate 	options->max_startups_rate = -1;
137*7c478bd9Sstevel@tonic-gate 	options->max_startups = -1;
138*7c478bd9Sstevel@tonic-gate 	options->banner = NULL;
139*7c478bd9Sstevel@tonic-gate 	options->verify_reverse_mapping = -1;
140*7c478bd9Sstevel@tonic-gate 	options->client_alive_interval = -1;
141*7c478bd9Sstevel@tonic-gate 	options->client_alive_count_max = -1;
142*7c478bd9Sstevel@tonic-gate 	options->authorized_keys_file = NULL;
143*7c478bd9Sstevel@tonic-gate 	options->authorized_keys_file2 = NULL;
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate 	options->max_auth_tries = -1;
146*7c478bd9Sstevel@tonic-gate 	options->max_auth_tries_log = -1;
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate 	options->max_init_auth_tries = -1;
149*7c478bd9Sstevel@tonic-gate 	options->max_init_auth_tries_log = -1;
150*7c478bd9Sstevel@tonic-gate 
151*7c478bd9Sstevel@tonic-gate 	options->lookup_client_hostnames = -1;
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 	/* Needs to be accessable in many places */
154*7c478bd9Sstevel@tonic-gate 	use_privsep = -1;
155*7c478bd9Sstevel@tonic-gate }
156*7c478bd9Sstevel@tonic-gate 
157*7c478bd9Sstevel@tonic-gate #ifdef HAVE_DEFOPEN
158*7c478bd9Sstevel@tonic-gate /*
159*7c478bd9Sstevel@tonic-gate  * Reads /etc/default/login and defaults several ServerOptions:
160*7c478bd9Sstevel@tonic-gate  *
161*7c478bd9Sstevel@tonic-gate  * PermitRootLogin
162*7c478bd9Sstevel@tonic-gate  * PermitEmptyPasswords
163*7c478bd9Sstevel@tonic-gate  * LoginGraceTime
164*7c478bd9Sstevel@tonic-gate  *
165*7c478bd9Sstevel@tonic-gate  * CONSOLE=*      -> PermitRootLogin=without-password
166*7c478bd9Sstevel@tonic-gate  * #CONSOLE=*     -> PermitRootLogin=yes
167*7c478bd9Sstevel@tonic-gate  *
168*7c478bd9Sstevel@tonic-gate  * PASSREQ=YES    -> PermitEmptyPasswords=no
169*7c478bd9Sstevel@tonic-gate  * PASSREQ=NO     -> PermitEmptyPasswords=yes
170*7c478bd9Sstevel@tonic-gate  * #PASSREQ=*     -> PermitEmptyPasswords=no
171*7c478bd9Sstevel@tonic-gate  *
172*7c478bd9Sstevel@tonic-gate  * TIMEOUT=<secs> -> LoginGraceTime=<secs>
173*7c478bd9Sstevel@tonic-gate  * #TIMEOUT=<secs> -> LoginGraceTime=300
174*7c478bd9Sstevel@tonic-gate  */
175*7c478bd9Sstevel@tonic-gate static
176*7c478bd9Sstevel@tonic-gate void
177*7c478bd9Sstevel@tonic-gate deflt_fill_default_server_options(ServerOptions *options)
178*7c478bd9Sstevel@tonic-gate {
179*7c478bd9Sstevel@tonic-gate 	int	flags;
180*7c478bd9Sstevel@tonic-gate 	char	*ptr;
181*7c478bd9Sstevel@tonic-gate 
182*7c478bd9Sstevel@tonic-gate 	if (defopen(_PATH_DEFAULT_LOGIN))
183*7c478bd9Sstevel@tonic-gate 		return;
184*7c478bd9Sstevel@tonic-gate 
185*7c478bd9Sstevel@tonic-gate 	/* Ignore case */
186*7c478bd9Sstevel@tonic-gate 	flags = defcntl(DC_GETFLAGS, 0);
187*7c478bd9Sstevel@tonic-gate 	TURNOFF(flags, DC_CASE);
188*7c478bd9Sstevel@tonic-gate 	(void) defcntl(DC_SETFLAGS, flags);
189*7c478bd9Sstevel@tonic-gate 
190*7c478bd9Sstevel@tonic-gate 	if (options->permit_root_login == PERMIT_NOT_SET &&
191*7c478bd9Sstevel@tonic-gate 	    (ptr = defread("CONSOLE=")) != NULL)
192*7c478bd9Sstevel@tonic-gate 		options->permit_root_login = PERMIT_NO_PASSWD;
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate 	if (options->permit_empty_passwd == -1 &&
195*7c478bd9Sstevel@tonic-gate 	    (ptr = defread("PASSREQ=")) != NULL) {
196*7c478bd9Sstevel@tonic-gate 		if (strcasecmp("YES", ptr) == 0)
197*7c478bd9Sstevel@tonic-gate 			options->permit_empty_passwd = 0;
198*7c478bd9Sstevel@tonic-gate 		else if (strcasecmp("NO", ptr) == 0)
199*7c478bd9Sstevel@tonic-gate 			options->permit_empty_passwd = 1;
200*7c478bd9Sstevel@tonic-gate 	}
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate 	if (options->max_init_auth_tries == -1 &&
203*7c478bd9Sstevel@tonic-gate 	    (ptr = defread("RETRIES=")) != NULL) {
204*7c478bd9Sstevel@tonic-gate 		options->max_init_auth_tries = atoi(ptr);
205*7c478bd9Sstevel@tonic-gate 	}
206*7c478bd9Sstevel@tonic-gate 
207*7c478bd9Sstevel@tonic-gate 	if (options->max_init_auth_tries_log == -1 &&
208*7c478bd9Sstevel@tonic-gate 	    (ptr = defread("SYSLOG_FAILED_LOGINS=")) != NULL) {
209*7c478bd9Sstevel@tonic-gate 		options->max_init_auth_tries_log = atoi(ptr);
210*7c478bd9Sstevel@tonic-gate 	}
211*7c478bd9Sstevel@tonic-gate 
212*7c478bd9Sstevel@tonic-gate 	if (options->login_grace_time == -1) {
213*7c478bd9Sstevel@tonic-gate 		if ((ptr = defread("TIMEOUT=")) != NULL)
214*7c478bd9Sstevel@tonic-gate 			options->login_grace_time = (unsigned)atoi(ptr);
215*7c478bd9Sstevel@tonic-gate 		else
216*7c478bd9Sstevel@tonic-gate 			options->login_grace_time = 300;
217*7c478bd9Sstevel@tonic-gate 	}
218*7c478bd9Sstevel@tonic-gate 
219*7c478bd9Sstevel@tonic-gate 	(void) defopen((char *)NULL);
220*7c478bd9Sstevel@tonic-gate }
221*7c478bd9Sstevel@tonic-gate #endif /* HAVE_DEFOPEN */
222*7c478bd9Sstevel@tonic-gate 
223*7c478bd9Sstevel@tonic-gate void
224*7c478bd9Sstevel@tonic-gate fill_default_server_options(ServerOptions *options)
225*7c478bd9Sstevel@tonic-gate {
226*7c478bd9Sstevel@tonic-gate 
227*7c478bd9Sstevel@tonic-gate #ifdef HAVE_DEFOPEN
228*7c478bd9Sstevel@tonic-gate 	deflt_fill_default_server_options(options);
229*7c478bd9Sstevel@tonic-gate #endif /* HAVE_DEFOPEN */
230*7c478bd9Sstevel@tonic-gate 
231*7c478bd9Sstevel@tonic-gate 	/* Portable-specific options */
232*7c478bd9Sstevel@tonic-gate 	if (options->pam_authentication_via_kbd_int == -1)
233*7c478bd9Sstevel@tonic-gate 		options->pam_authentication_via_kbd_int = 0;
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate 	/* Standard Options */
236*7c478bd9Sstevel@tonic-gate 	if (options->protocol == SSH_PROTO_UNKNOWN)
237*7c478bd9Sstevel@tonic-gate 		options->protocol = SSH_PROTO_1|SSH_PROTO_2;
238*7c478bd9Sstevel@tonic-gate 	if (options->num_host_key_files == 0) {
239*7c478bd9Sstevel@tonic-gate 		/* fill default hostkeys for protocols */
240*7c478bd9Sstevel@tonic-gate 		if (options->protocol & SSH_PROTO_1)
241*7c478bd9Sstevel@tonic-gate 			options->host_key_files[options->num_host_key_files++] =
242*7c478bd9Sstevel@tonic-gate 			    _PATH_HOST_KEY_FILE;
243*7c478bd9Sstevel@tonic-gate #ifndef GSSAPI
244*7c478bd9Sstevel@tonic-gate 		/* With GSS keyex we can run v2 w/ no host keys */
245*7c478bd9Sstevel@tonic-gate 		if (options->protocol & SSH_PROTO_2) {
246*7c478bd9Sstevel@tonic-gate 			options->host_key_files[options->num_host_key_files++] =
247*7c478bd9Sstevel@tonic-gate 			    _PATH_HOST_RSA_KEY_FILE;
248*7c478bd9Sstevel@tonic-gate 			options->host_key_files[options->num_host_key_files++] =
249*7c478bd9Sstevel@tonic-gate 			    _PATH_HOST_DSA_KEY_FILE;
250*7c478bd9Sstevel@tonic-gate 		}
251*7c478bd9Sstevel@tonic-gate #endif /* GSSAPI */
252*7c478bd9Sstevel@tonic-gate 	}
253*7c478bd9Sstevel@tonic-gate 	if (options->num_ports == 0)
254*7c478bd9Sstevel@tonic-gate 		options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
255*7c478bd9Sstevel@tonic-gate 	if (options->listen_addrs == NULL)
256*7c478bd9Sstevel@tonic-gate 		add_listen_addr(options, NULL, 0);
257*7c478bd9Sstevel@tonic-gate 	if (options->pid_file == NULL)
258*7c478bd9Sstevel@tonic-gate 		options->pid_file = _PATH_SSH_DAEMON_PID_FILE;
259*7c478bd9Sstevel@tonic-gate 	if (options->server_key_bits == -1)
260*7c478bd9Sstevel@tonic-gate 		options->server_key_bits = 768;
261*7c478bd9Sstevel@tonic-gate 	if (options->login_grace_time == -1)
262*7c478bd9Sstevel@tonic-gate 		options->login_grace_time = 120;
263*7c478bd9Sstevel@tonic-gate 	if (options->key_regeneration_time == -1)
264*7c478bd9Sstevel@tonic-gate 		options->key_regeneration_time = 3600;
265*7c478bd9Sstevel@tonic-gate 	if (options->permit_root_login == PERMIT_NOT_SET)
266*7c478bd9Sstevel@tonic-gate 		options->permit_root_login = PERMIT_YES;
267*7c478bd9Sstevel@tonic-gate 	if (options->ignore_rhosts == -1)
268*7c478bd9Sstevel@tonic-gate 		options->ignore_rhosts = 1;
269*7c478bd9Sstevel@tonic-gate 	if (options->ignore_user_known_hosts == -1)
270*7c478bd9Sstevel@tonic-gate 		options->ignore_user_known_hosts = 0;
271*7c478bd9Sstevel@tonic-gate 	if (options->print_motd == -1)
272*7c478bd9Sstevel@tonic-gate 		options->print_motd = 1;
273*7c478bd9Sstevel@tonic-gate 	if (options->print_lastlog == -1)
274*7c478bd9Sstevel@tonic-gate 		options->print_lastlog = 1;
275*7c478bd9Sstevel@tonic-gate 	if (options->x11_forwarding == -1)
276*7c478bd9Sstevel@tonic-gate 		options->x11_forwarding = 1;
277*7c478bd9Sstevel@tonic-gate 	if (options->x11_display_offset == -1)
278*7c478bd9Sstevel@tonic-gate 		options->x11_display_offset = 10;
279*7c478bd9Sstevel@tonic-gate 	if (options->x11_use_localhost == -1)
280*7c478bd9Sstevel@tonic-gate 		options->x11_use_localhost = 1;
281*7c478bd9Sstevel@tonic-gate 	if (options->xauth_location == NULL)
282*7c478bd9Sstevel@tonic-gate 		options->xauth_location = _PATH_XAUTH;
283*7c478bd9Sstevel@tonic-gate 	if (options->strict_modes == -1)
284*7c478bd9Sstevel@tonic-gate 		options->strict_modes = 1;
285*7c478bd9Sstevel@tonic-gate 	if (options->keepalives == -1)
286*7c478bd9Sstevel@tonic-gate 		options->keepalives = 1;
287*7c478bd9Sstevel@tonic-gate 	if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
288*7c478bd9Sstevel@tonic-gate 		options->log_facility = SYSLOG_FACILITY_AUTH;
289*7c478bd9Sstevel@tonic-gate 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
290*7c478bd9Sstevel@tonic-gate 		options->log_level = SYSLOG_LEVEL_INFO;
291*7c478bd9Sstevel@tonic-gate 	if (options->rhosts_authentication == -1)
292*7c478bd9Sstevel@tonic-gate 		options->rhosts_authentication = 0;
293*7c478bd9Sstevel@tonic-gate 	if (options->rhosts_rsa_authentication == -1)
294*7c478bd9Sstevel@tonic-gate 		options->rhosts_rsa_authentication = 0;
295*7c478bd9Sstevel@tonic-gate 	if (options->hostbased_authentication == -1)
296*7c478bd9Sstevel@tonic-gate 		options->hostbased_authentication = 0;
297*7c478bd9Sstevel@tonic-gate 	if (options->hostbased_uses_name_from_packet_only == -1)
298*7c478bd9Sstevel@tonic-gate 		options->hostbased_uses_name_from_packet_only = 0;
299*7c478bd9Sstevel@tonic-gate 	if (options->rsa_authentication == -1)
300*7c478bd9Sstevel@tonic-gate 		options->rsa_authentication = 1;
301*7c478bd9Sstevel@tonic-gate 	if (options->pubkey_authentication == -1)
302*7c478bd9Sstevel@tonic-gate 		options->pubkey_authentication = 1;
303*7c478bd9Sstevel@tonic-gate #ifdef GSSAPI
304*7c478bd9Sstevel@tonic-gate 	if (options->gss_authentication == -1)
305*7c478bd9Sstevel@tonic-gate 		options->gss_authentication = 1;
306*7c478bd9Sstevel@tonic-gate 	if (options->gss_keyex == -1)
307*7c478bd9Sstevel@tonic-gate 		options->gss_keyex = 1;
308*7c478bd9Sstevel@tonic-gate 	if (options->gss_store_creds == -1)
309*7c478bd9Sstevel@tonic-gate 		options->gss_store_creds = 1;
310*7c478bd9Sstevel@tonic-gate 	if (options->gss_use_session_ccache == -1)
311*7c478bd9Sstevel@tonic-gate 		options->gss_use_session_ccache = 1;
312*7c478bd9Sstevel@tonic-gate 	if (options->gss_cleanup_creds == -1)
313*7c478bd9Sstevel@tonic-gate 		options->gss_cleanup_creds = 1;
314*7c478bd9Sstevel@tonic-gate #endif
315*7c478bd9Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5)
316*7c478bd9Sstevel@tonic-gate 	if (options->kerberos_authentication == -1)
317*7c478bd9Sstevel@tonic-gate 		options->kerberos_authentication = 0;
318*7c478bd9Sstevel@tonic-gate 	if (options->kerberos_or_local_passwd == -1)
319*7c478bd9Sstevel@tonic-gate 		options->kerberos_or_local_passwd = 1;
320*7c478bd9Sstevel@tonic-gate 	if (options->kerberos_ticket_cleanup == -1)
321*7c478bd9Sstevel@tonic-gate 		options->kerberos_ticket_cleanup = 1;
322*7c478bd9Sstevel@tonic-gate #endif
323*7c478bd9Sstevel@tonic-gate #if defined(AFS) || defined(KRB5)
324*7c478bd9Sstevel@tonic-gate 	if (options->kerberos_tgt_passing == -1)
325*7c478bd9Sstevel@tonic-gate 		options->kerberos_tgt_passing = 0;
326*7c478bd9Sstevel@tonic-gate #endif
327*7c478bd9Sstevel@tonic-gate #ifdef AFS
328*7c478bd9Sstevel@tonic-gate 	if (options->afs_token_passing == -1)
329*7c478bd9Sstevel@tonic-gate 		options->afs_token_passing = 0;
330*7c478bd9Sstevel@tonic-gate #endif
331*7c478bd9Sstevel@tonic-gate 	if (options->password_authentication == -1)
332*7c478bd9Sstevel@tonic-gate 		options->password_authentication = 1;
333*7c478bd9Sstevel@tonic-gate 	if (options->kbd_interactive_authentication == -1)
334*7c478bd9Sstevel@tonic-gate 		options->kbd_interactive_authentication = 0;
335*7c478bd9Sstevel@tonic-gate 	if (options->challenge_response_authentication == -1)
336*7c478bd9Sstevel@tonic-gate 		options->challenge_response_authentication = 1;
337*7c478bd9Sstevel@tonic-gate 	if (options->permit_empty_passwd == -1)
338*7c478bd9Sstevel@tonic-gate 		options->permit_empty_passwd = 0;
339*7c478bd9Sstevel@tonic-gate 	if (options->permit_user_env == -1)
340*7c478bd9Sstevel@tonic-gate 		options->permit_user_env = 0;
341*7c478bd9Sstevel@tonic-gate 	if (options->use_login == -1)
342*7c478bd9Sstevel@tonic-gate 		options->use_login = 0;
343*7c478bd9Sstevel@tonic-gate 	if (options->compression == -1)
344*7c478bd9Sstevel@tonic-gate 		options->compression = 1;
345*7c478bd9Sstevel@tonic-gate 	if (options->allow_tcp_forwarding == -1)
346*7c478bd9Sstevel@tonic-gate 		options->allow_tcp_forwarding = 1;
347*7c478bd9Sstevel@tonic-gate 	if (options->gateway_ports == -1)
348*7c478bd9Sstevel@tonic-gate 		options->gateway_ports = 0;
349*7c478bd9Sstevel@tonic-gate 	if (options->max_startups == -1)
350*7c478bd9Sstevel@tonic-gate 		options->max_startups = 10;
351*7c478bd9Sstevel@tonic-gate 	if (options->max_startups_rate == -1)
352*7c478bd9Sstevel@tonic-gate 		options->max_startups_rate = 100;		/* 100% */
353*7c478bd9Sstevel@tonic-gate 	if (options->max_startups_begin == -1)
354*7c478bd9Sstevel@tonic-gate 		options->max_startups_begin = options->max_startups;
355*7c478bd9Sstevel@tonic-gate 	if (options->verify_reverse_mapping == -1)
356*7c478bd9Sstevel@tonic-gate 		options->verify_reverse_mapping = 0;
357*7c478bd9Sstevel@tonic-gate 	if (options->client_alive_interval == -1)
358*7c478bd9Sstevel@tonic-gate 		options->client_alive_interval = 0;
359*7c478bd9Sstevel@tonic-gate 	if (options->client_alive_count_max == -1)
360*7c478bd9Sstevel@tonic-gate 		options->client_alive_count_max = 3;
361*7c478bd9Sstevel@tonic-gate 	if (options->authorized_keys_file2 == NULL) {
362*7c478bd9Sstevel@tonic-gate 		/* authorized_keys_file2 falls back to authorized_keys_file */
363*7c478bd9Sstevel@tonic-gate 		if (options->authorized_keys_file != NULL)
364*7c478bd9Sstevel@tonic-gate 			options->authorized_keys_file2 = options->authorized_keys_file;
365*7c478bd9Sstevel@tonic-gate 		else
366*7c478bd9Sstevel@tonic-gate 			options->authorized_keys_file2 = _PATH_SSH_USER_PERMITTED_KEYS2;
367*7c478bd9Sstevel@tonic-gate 	}
368*7c478bd9Sstevel@tonic-gate 	if (options->authorized_keys_file == NULL)
369*7c478bd9Sstevel@tonic-gate 		options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS;
370*7c478bd9Sstevel@tonic-gate 
371*7c478bd9Sstevel@tonic-gate 	if (options->max_auth_tries == -1)
372*7c478bd9Sstevel@tonic-gate 		options->max_auth_tries = AUTH_FAIL_MAX;
373*7c478bd9Sstevel@tonic-gate 	if (options->max_auth_tries_log == -1)
374*7c478bd9Sstevel@tonic-gate 		options->max_auth_tries_log = options->max_auth_tries / 2;
375*7c478bd9Sstevel@tonic-gate 
376*7c478bd9Sstevel@tonic-gate 	if (options->max_init_auth_tries == -1)
377*7c478bd9Sstevel@tonic-gate 		options->max_init_auth_tries = AUTH_FAIL_MAX;
378*7c478bd9Sstevel@tonic-gate 	if (options->max_init_auth_tries_log == -1)
379*7c478bd9Sstevel@tonic-gate 		options->max_init_auth_tries_log = options->max_init_auth_tries / 2;
380*7c478bd9Sstevel@tonic-gate 
381*7c478bd9Sstevel@tonic-gate 	if (options->lookup_client_hostnames == -1)
382*7c478bd9Sstevel@tonic-gate 		options->lookup_client_hostnames = 1;
383*7c478bd9Sstevel@tonic-gate 
384*7c478bd9Sstevel@tonic-gate 	/* XXX SUNWssh resync */
385*7c478bd9Sstevel@tonic-gate 	/* Turn privilege separation OFF by default */
386*7c478bd9Sstevel@tonic-gate 	if (use_privsep == -1)
387*7c478bd9Sstevel@tonic-gate 		use_privsep = 0;
388*7c478bd9Sstevel@tonic-gate 
389*7c478bd9Sstevel@tonic-gate #ifndef HAVE_MMAP
390*7c478bd9Sstevel@tonic-gate 	if (use_privsep && options->compression == 1) {
391*7c478bd9Sstevel@tonic-gate 		error("This platform does not support both privilege "
392*7c478bd9Sstevel@tonic-gate 		    "separation and compression");
393*7c478bd9Sstevel@tonic-gate 		error("Compression disabled");
394*7c478bd9Sstevel@tonic-gate 		options->compression = 0;
395*7c478bd9Sstevel@tonic-gate 	}
396*7c478bd9Sstevel@tonic-gate #endif
397*7c478bd9Sstevel@tonic-gate 
398*7c478bd9Sstevel@tonic-gate }
399*7c478bd9Sstevel@tonic-gate 
400*7c478bd9Sstevel@tonic-gate /* Keyword tokens. */
401*7c478bd9Sstevel@tonic-gate typedef enum {
402*7c478bd9Sstevel@tonic-gate 	sBadOption,		/* == unknown option */
403*7c478bd9Sstevel@tonic-gate 	/* Portable-specific options */
404*7c478bd9Sstevel@tonic-gate 	sPAMAuthenticationViaKbdInt,
405*7c478bd9Sstevel@tonic-gate 	/* Standard Options */
406*7c478bd9Sstevel@tonic-gate 	sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
407*7c478bd9Sstevel@tonic-gate 	sPermitRootLogin, sLogFacility, sLogLevel,
408*7c478bd9Sstevel@tonic-gate 	sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication,
409*7c478bd9Sstevel@tonic-gate #ifdef GSSAPI
410*7c478bd9Sstevel@tonic-gate 	sGssAuthentication, sGssKeyEx, sGssStoreDelegCreds,
411*7c478bd9Sstevel@tonic-gate 	sGssUseSessionCredCache, sGssCleanupCreds,
412*7c478bd9Sstevel@tonic-gate #endif /* GSSAPI */
413*7c478bd9Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5)
414*7c478bd9Sstevel@tonic-gate 	sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
415*7c478bd9Sstevel@tonic-gate #endif
416*7c478bd9Sstevel@tonic-gate #if defined(AFS) || defined(KRB5)
417*7c478bd9Sstevel@tonic-gate 	sKerberosTgtPassing,
418*7c478bd9Sstevel@tonic-gate #endif
419*7c478bd9Sstevel@tonic-gate #ifdef AFS
420*7c478bd9Sstevel@tonic-gate 	sAFSTokenPassing,
421*7c478bd9Sstevel@tonic-gate #endif
422*7c478bd9Sstevel@tonic-gate 	sChallengeResponseAuthentication,
423*7c478bd9Sstevel@tonic-gate 	sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress,
424*7c478bd9Sstevel@tonic-gate 	sPrintMotd, sPrintLastLog, sIgnoreRhosts,
425*7c478bd9Sstevel@tonic-gate 	sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
426*7c478bd9Sstevel@tonic-gate 	sStrictModes, sEmptyPasswd, sKeepAlives,
427*7c478bd9Sstevel@tonic-gate 	sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
428*7c478bd9Sstevel@tonic-gate 	sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
429*7c478bd9Sstevel@tonic-gate 	sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
430*7c478bd9Sstevel@tonic-gate 	sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem, sMaxStartups,
431*7c478bd9Sstevel@tonic-gate 	sBanner, sVerifyReverseMapping, sHostbasedAuthentication,
432*7c478bd9Sstevel@tonic-gate 	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
433*7c478bd9Sstevel@tonic-gate 	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
434*7c478bd9Sstevel@tonic-gate 	sMaxAuthTries, sMaxAuthTriesLog, sUsePrivilegeSeparation,
435*7c478bd9Sstevel@tonic-gate 	sLookupClientHostnames,
436*7c478bd9Sstevel@tonic-gate 	sDeprecated
437*7c478bd9Sstevel@tonic-gate } ServerOpCodes;
438*7c478bd9Sstevel@tonic-gate 
439*7c478bd9Sstevel@tonic-gate /* Textual representation of the tokens. */
440*7c478bd9Sstevel@tonic-gate static struct {
441*7c478bd9Sstevel@tonic-gate 	const char *name;
442*7c478bd9Sstevel@tonic-gate 	ServerOpCodes opcode;
443*7c478bd9Sstevel@tonic-gate } keywords[] = {
444*7c478bd9Sstevel@tonic-gate 	/* Portable-specific options */
445*7c478bd9Sstevel@tonic-gate 	{ "PAMAuthenticationViaKbdInt", sPAMAuthenticationViaKbdInt },
446*7c478bd9Sstevel@tonic-gate 	/* Standard Options */
447*7c478bd9Sstevel@tonic-gate 	{ "port", sPort },
448*7c478bd9Sstevel@tonic-gate 	{ "hostkey", sHostKeyFile },
449*7c478bd9Sstevel@tonic-gate 	{ "hostdsakey", sHostKeyFile },					/* alias */
450*7c478bd9Sstevel@tonic-gate 	{ "pidfile", sPidFile },
451*7c478bd9Sstevel@tonic-gate 	{ "serverkeybits", sServerKeyBits },
452*7c478bd9Sstevel@tonic-gate 	{ "logingracetime", sLoginGraceTime },
453*7c478bd9Sstevel@tonic-gate 	{ "keyregenerationinterval", sKeyRegenerationTime },
454*7c478bd9Sstevel@tonic-gate 	{ "permitrootlogin", sPermitRootLogin },
455*7c478bd9Sstevel@tonic-gate 	{ "syslogfacility", sLogFacility },
456*7c478bd9Sstevel@tonic-gate 	{ "loglevel", sLogLevel },
457*7c478bd9Sstevel@tonic-gate 	{ "rhostsauthentication", sRhostsAuthentication },
458*7c478bd9Sstevel@tonic-gate 	{ "rhostsrsaauthentication", sRhostsRSAAuthentication },
459*7c478bd9Sstevel@tonic-gate 	{ "hostbasedauthentication", sHostbasedAuthentication },
460*7c478bd9Sstevel@tonic-gate 	{ "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly },
461*7c478bd9Sstevel@tonic-gate 	{ "rsaauthentication", sRSAAuthentication },
462*7c478bd9Sstevel@tonic-gate 	{ "pubkeyauthentication", sPubkeyAuthentication },
463*7c478bd9Sstevel@tonic-gate 	{ "dsaauthentication", sPubkeyAuthentication },			/* alias */
464*7c478bd9Sstevel@tonic-gate #ifdef GSSAPI
465*7c478bd9Sstevel@tonic-gate 	{ "gssapiauthentication", sGssAuthentication },
466*7c478bd9Sstevel@tonic-gate 	{ "gssapikeyexchange", sGssKeyEx },
467*7c478bd9Sstevel@tonic-gate 	{ "gssapistoredelegatedcredentials", sGssStoreDelegCreds },
468*7c478bd9Sstevel@tonic-gate 	{ "gssauthentication", sGssAuthentication },			/* alias */
469*7c478bd9Sstevel@tonic-gate 	{ "gsskeyex", sGssKeyEx },					/* alias */
470*7c478bd9Sstevel@tonic-gate 	{ "gssstoredelegcreds", sGssStoreDelegCreds },			/* alias */
471*7c478bd9Sstevel@tonic-gate #ifndef SUNW_GSSAPI
472*7c478bd9Sstevel@tonic-gate 	{ "gssusesessionccache", sGssUseSessionCredCache },
473*7c478bd9Sstevel@tonic-gate 	{ "gssusesessioncredcache", sGssUseSessionCredCache },
474*7c478bd9Sstevel@tonic-gate 	{ "gsscleanupcreds", sGssCleanupCreds },
475*7c478bd9Sstevel@tonic-gate #endif /* SUNW_GSSAPI */
476*7c478bd9Sstevel@tonic-gate #endif
477*7c478bd9Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5)
478*7c478bd9Sstevel@tonic-gate 	{ "kerberosauthentication", sKerberosAuthentication },
479*7c478bd9Sstevel@tonic-gate 	{ "kerberosorlocalpasswd", sKerberosOrLocalPasswd },
480*7c478bd9Sstevel@tonic-gate 	{ "kerberosticketcleanup", sKerberosTicketCleanup },
481*7c478bd9Sstevel@tonic-gate #endif
482*7c478bd9Sstevel@tonic-gate #if defined(AFS) || defined(KRB5)
483*7c478bd9Sstevel@tonic-gate 	{ "kerberostgtpassing", sKerberosTgtPassing },
484*7c478bd9Sstevel@tonic-gate #endif
485*7c478bd9Sstevel@tonic-gate #ifdef AFS
486*7c478bd9Sstevel@tonic-gate 	{ "afstokenpassing", sAFSTokenPassing },
487*7c478bd9Sstevel@tonic-gate #endif
488*7c478bd9Sstevel@tonic-gate 	{ "passwordauthentication", sPasswordAuthentication },
489*7c478bd9Sstevel@tonic-gate 	{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication },
490*7c478bd9Sstevel@tonic-gate 	{ "challengeresponseauthentication", sChallengeResponseAuthentication },
491*7c478bd9Sstevel@tonic-gate 	{ "skeyauthentication", sChallengeResponseAuthentication }, /* alias */
492*7c478bd9Sstevel@tonic-gate 	{ "checkmail", sDeprecated },
493*7c478bd9Sstevel@tonic-gate 	{ "listenaddress", sListenAddress },
494*7c478bd9Sstevel@tonic-gate 	{ "printmotd", sPrintMotd },
495*7c478bd9Sstevel@tonic-gate 	{ "printlastlog", sPrintLastLog },
496*7c478bd9Sstevel@tonic-gate 	{ "ignorerhosts", sIgnoreRhosts },
497*7c478bd9Sstevel@tonic-gate 	{ "ignoreuserknownhosts", sIgnoreUserKnownHosts },
498*7c478bd9Sstevel@tonic-gate 	{ "x11forwarding", sX11Forwarding },
499*7c478bd9Sstevel@tonic-gate 	{ "x11displayoffset", sX11DisplayOffset },
500*7c478bd9Sstevel@tonic-gate 	{ "x11uselocalhost", sX11UseLocalhost },
501*7c478bd9Sstevel@tonic-gate 	{ "xauthlocation", sXAuthLocation },
502*7c478bd9Sstevel@tonic-gate 	{ "strictmodes", sStrictModes },
503*7c478bd9Sstevel@tonic-gate 	{ "permitemptypasswords", sEmptyPasswd },
504*7c478bd9Sstevel@tonic-gate 	{ "permituserenvironment", sPermitUserEnvironment },
505*7c478bd9Sstevel@tonic-gate 	{ "uselogin", sUseLogin },
506*7c478bd9Sstevel@tonic-gate 	{ "compression", sCompression },
507*7c478bd9Sstevel@tonic-gate 	{ "keepalive", sKeepAlives },
508*7c478bd9Sstevel@tonic-gate 	{ "allowtcpforwarding", sAllowTcpForwarding },
509*7c478bd9Sstevel@tonic-gate 	{ "allowusers", sAllowUsers },
510*7c478bd9Sstevel@tonic-gate 	{ "denyusers", sDenyUsers },
511*7c478bd9Sstevel@tonic-gate 	{ "allowgroups", sAllowGroups },
512*7c478bd9Sstevel@tonic-gate 	{ "denygroups", sDenyGroups },
513*7c478bd9Sstevel@tonic-gate 	{ "ciphers", sCiphers },
514*7c478bd9Sstevel@tonic-gate 	{ "macs", sMacs },
515*7c478bd9Sstevel@tonic-gate 	{ "protocol", sProtocol },
516*7c478bd9Sstevel@tonic-gate 	{ "gatewayports", sGatewayPorts },
517*7c478bd9Sstevel@tonic-gate 	{ "subsystem", sSubsystem },
518*7c478bd9Sstevel@tonic-gate 	{ "maxstartups", sMaxStartups },
519*7c478bd9Sstevel@tonic-gate 	{ "banner", sBanner },
520*7c478bd9Sstevel@tonic-gate 	{ "verifyreversemapping", sVerifyReverseMapping },
521*7c478bd9Sstevel@tonic-gate 	{ "reversemappingcheck", sVerifyReverseMapping },
522*7c478bd9Sstevel@tonic-gate 	{ "clientaliveinterval", sClientAliveInterval },
523*7c478bd9Sstevel@tonic-gate 	{ "clientalivecountmax", sClientAliveCountMax },
524*7c478bd9Sstevel@tonic-gate 	{ "authorizedkeysfile", sAuthorizedKeysFile },
525*7c478bd9Sstevel@tonic-gate 	{ "authorizedkeysfile2", sAuthorizedKeysFile2 },
526*7c478bd9Sstevel@tonic-gate 	{ "maxauthtries", sMaxAuthTries },
527*7c478bd9Sstevel@tonic-gate 	{ "maxauthtrieslog", sMaxAuthTriesLog },
528*7c478bd9Sstevel@tonic-gate 	{ "useprivilegeseparation", sUsePrivilegeSeparation},
529*7c478bd9Sstevel@tonic-gate 	{ "lookupclienthostnames", sLookupClientHostnames},
530*7c478bd9Sstevel@tonic-gate 	{ NULL, sBadOption }
531*7c478bd9Sstevel@tonic-gate };
532*7c478bd9Sstevel@tonic-gate 
533*7c478bd9Sstevel@tonic-gate /*
534*7c478bd9Sstevel@tonic-gate  * Returns the number of the token pointed to by cp or sBadOption.
535*7c478bd9Sstevel@tonic-gate  */
536*7c478bd9Sstevel@tonic-gate 
537*7c478bd9Sstevel@tonic-gate static ServerOpCodes
538*7c478bd9Sstevel@tonic-gate parse_token(const char *cp, const char *filename,
539*7c478bd9Sstevel@tonic-gate 	    int linenum)
540*7c478bd9Sstevel@tonic-gate {
541*7c478bd9Sstevel@tonic-gate 	u_int i;
542*7c478bd9Sstevel@tonic-gate 
543*7c478bd9Sstevel@tonic-gate 	for (i = 0; keywords[i].name; i++)
544*7c478bd9Sstevel@tonic-gate 		if (strcasecmp(cp, keywords[i].name) == 0)
545*7c478bd9Sstevel@tonic-gate 			return keywords[i].opcode;
546*7c478bd9Sstevel@tonic-gate 
547*7c478bd9Sstevel@tonic-gate 	error("%s: line %d: Bad configuration option: %s",
548*7c478bd9Sstevel@tonic-gate 	    filename, linenum, cp);
549*7c478bd9Sstevel@tonic-gate 	return sBadOption;
550*7c478bd9Sstevel@tonic-gate }
551*7c478bd9Sstevel@tonic-gate 
552*7c478bd9Sstevel@tonic-gate static void
553*7c478bd9Sstevel@tonic-gate add_listen_addr(ServerOptions *options, char *addr, u_short port)
554*7c478bd9Sstevel@tonic-gate {
555*7c478bd9Sstevel@tonic-gate 	int i;
556*7c478bd9Sstevel@tonic-gate 
557*7c478bd9Sstevel@tonic-gate 	if (options->num_ports == 0)
558*7c478bd9Sstevel@tonic-gate 		options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
559*7c478bd9Sstevel@tonic-gate 	if (port == 0)
560*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < options->num_ports; i++)
561*7c478bd9Sstevel@tonic-gate 			add_one_listen_addr(options, addr, options->ports[i]);
562*7c478bd9Sstevel@tonic-gate 	else
563*7c478bd9Sstevel@tonic-gate 		add_one_listen_addr(options, addr, port);
564*7c478bd9Sstevel@tonic-gate }
565*7c478bd9Sstevel@tonic-gate 
566*7c478bd9Sstevel@tonic-gate static void
567*7c478bd9Sstevel@tonic-gate add_one_listen_addr(ServerOptions *options, char *addr, u_short port)
568*7c478bd9Sstevel@tonic-gate {
569*7c478bd9Sstevel@tonic-gate 	struct addrinfo hints, *ai, *aitop;
570*7c478bd9Sstevel@tonic-gate 	char strport[NI_MAXSERV];
571*7c478bd9Sstevel@tonic-gate 	int gaierr;
572*7c478bd9Sstevel@tonic-gate 
573*7c478bd9Sstevel@tonic-gate 	(void) memset(&hints, 0, sizeof(hints));
574*7c478bd9Sstevel@tonic-gate 	hints.ai_family = IPv4or6;
575*7c478bd9Sstevel@tonic-gate 	hints.ai_socktype = SOCK_STREAM;
576*7c478bd9Sstevel@tonic-gate 	hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
577*7c478bd9Sstevel@tonic-gate 	(void) snprintf(strport, sizeof strport, "%u", port);
578*7c478bd9Sstevel@tonic-gate 	if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
579*7c478bd9Sstevel@tonic-gate 		fatal("bad addr or host: %s (%s)",
580*7c478bd9Sstevel@tonic-gate 		    addr ? addr : "<NULL>",
581*7c478bd9Sstevel@tonic-gate 		    gai_strerror(gaierr));
582*7c478bd9Sstevel@tonic-gate 	for (ai = aitop; ai->ai_next; ai = ai->ai_next)
583*7c478bd9Sstevel@tonic-gate 		;
584*7c478bd9Sstevel@tonic-gate 	ai->ai_next = options->listen_addrs;
585*7c478bd9Sstevel@tonic-gate 	options->listen_addrs = aitop;
586*7c478bd9Sstevel@tonic-gate }
587*7c478bd9Sstevel@tonic-gate 
588*7c478bd9Sstevel@tonic-gate int
589*7c478bd9Sstevel@tonic-gate process_server_config_line(ServerOptions *options, char *line,
590*7c478bd9Sstevel@tonic-gate     const char *filename, int linenum)
591*7c478bd9Sstevel@tonic-gate {
592*7c478bd9Sstevel@tonic-gate 	char *cp, **charptr, *arg, *p;
593*7c478bd9Sstevel@tonic-gate 	int *intptr, value, i, n;
594*7c478bd9Sstevel@tonic-gate 	ServerOpCodes opcode;
595*7c478bd9Sstevel@tonic-gate 
596*7c478bd9Sstevel@tonic-gate 	cp = line;
597*7c478bd9Sstevel@tonic-gate 	arg = strdelim(&cp);
598*7c478bd9Sstevel@tonic-gate 	/* Ignore leading whitespace */
599*7c478bd9Sstevel@tonic-gate 	if (*arg == '\0')
600*7c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
601*7c478bd9Sstevel@tonic-gate 	if (!arg || !*arg || *arg == '#')
602*7c478bd9Sstevel@tonic-gate 		return 0;
603*7c478bd9Sstevel@tonic-gate 	intptr = NULL;
604*7c478bd9Sstevel@tonic-gate 	charptr = NULL;
605*7c478bd9Sstevel@tonic-gate 	opcode = parse_token(arg, filename, linenum);
606*7c478bd9Sstevel@tonic-gate 	switch (opcode) {
607*7c478bd9Sstevel@tonic-gate 	/* Portable-specific options */
608*7c478bd9Sstevel@tonic-gate 	case sPAMAuthenticationViaKbdInt:
609*7c478bd9Sstevel@tonic-gate 		intptr = &options->pam_authentication_via_kbd_int;
610*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
611*7c478bd9Sstevel@tonic-gate 
612*7c478bd9Sstevel@tonic-gate 	/* Standard Options */
613*7c478bd9Sstevel@tonic-gate 	case sBadOption:
614*7c478bd9Sstevel@tonic-gate 		return -1;
615*7c478bd9Sstevel@tonic-gate 	case sPort:
616*7c478bd9Sstevel@tonic-gate 		/* ignore ports from configfile if cmdline specifies ports */
617*7c478bd9Sstevel@tonic-gate 		if (options->ports_from_cmdline)
618*7c478bd9Sstevel@tonic-gate 			return 0;
619*7c478bd9Sstevel@tonic-gate 		if (options->listen_addrs != NULL)
620*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: ports must be specified before "
621*7c478bd9Sstevel@tonic-gate 			    "ListenAddress.", filename, linenum);
622*7c478bd9Sstevel@tonic-gate 		if (options->num_ports >= MAX_PORTS)
623*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: too many ports.",
624*7c478bd9Sstevel@tonic-gate 			    filename, linenum);
625*7c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
626*7c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0')
627*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: missing port number.",
628*7c478bd9Sstevel@tonic-gate 			    filename, linenum);
629*7c478bd9Sstevel@tonic-gate 		options->ports[options->num_ports++] = a2port(arg);
630*7c478bd9Sstevel@tonic-gate 		if (options->ports[options->num_ports-1] == 0)
631*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Badly formatted port number.",
632*7c478bd9Sstevel@tonic-gate 			    filename, linenum);
633*7c478bd9Sstevel@tonic-gate 		break;
634*7c478bd9Sstevel@tonic-gate 
635*7c478bd9Sstevel@tonic-gate 	case sServerKeyBits:
636*7c478bd9Sstevel@tonic-gate 		intptr = &options->server_key_bits;
637*7c478bd9Sstevel@tonic-gate parse_int:
638*7c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
639*7c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0')
640*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: missing integer value.",
641*7c478bd9Sstevel@tonic-gate 			    filename, linenum);
642*7c478bd9Sstevel@tonic-gate 		value = atoi(arg);
643*7c478bd9Sstevel@tonic-gate 		if (*intptr == -1)
644*7c478bd9Sstevel@tonic-gate 			*intptr = value;
645*7c478bd9Sstevel@tonic-gate 		break;
646*7c478bd9Sstevel@tonic-gate 
647*7c478bd9Sstevel@tonic-gate 	case sLoginGraceTime:
648*7c478bd9Sstevel@tonic-gate 		intptr = &options->login_grace_time;
649*7c478bd9Sstevel@tonic-gate parse_time:
650*7c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
651*7c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0')
652*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: missing time value.",
653*7c478bd9Sstevel@tonic-gate 			    filename, linenum);
654*7c478bd9Sstevel@tonic-gate 		if ((value = convtime(arg)) == -1)
655*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: invalid time value.",
656*7c478bd9Sstevel@tonic-gate 			    filename, linenum);
657*7c478bd9Sstevel@tonic-gate 		if (*intptr == -1)
658*7c478bd9Sstevel@tonic-gate 			*intptr = value;
659*7c478bd9Sstevel@tonic-gate 		break;
660*7c478bd9Sstevel@tonic-gate 
661*7c478bd9Sstevel@tonic-gate 	case sKeyRegenerationTime:
662*7c478bd9Sstevel@tonic-gate 		intptr = &options->key_regeneration_time;
663*7c478bd9Sstevel@tonic-gate 		goto parse_time;
664*7c478bd9Sstevel@tonic-gate 
665*7c478bd9Sstevel@tonic-gate 	case sListenAddress:
666*7c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
667*7c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0)
668*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: missing inet addr.",
669*7c478bd9Sstevel@tonic-gate 			    filename, linenum);
670*7c478bd9Sstevel@tonic-gate 		if (*arg == '[') {
671*7c478bd9Sstevel@tonic-gate 			if ((p = strchr(arg, ']')) == NULL)
672*7c478bd9Sstevel@tonic-gate 				fatal("%s line %d: bad ipv6 inet addr usage.",
673*7c478bd9Sstevel@tonic-gate 				    filename, linenum);
674*7c478bd9Sstevel@tonic-gate 			arg++;
675*7c478bd9Sstevel@tonic-gate 			(void) memmove(p, p+1, strlen(p+1)+1);
676*7c478bd9Sstevel@tonic-gate 		} else if (((p = strchr(arg, ':')) == NULL) ||
677*7c478bd9Sstevel@tonic-gate 			    (strchr(p+1, ':') != NULL)) {
678*7c478bd9Sstevel@tonic-gate 			add_listen_addr(options, arg, 0);
679*7c478bd9Sstevel@tonic-gate 			break;
680*7c478bd9Sstevel@tonic-gate 		}
681*7c478bd9Sstevel@tonic-gate 		if (*p == ':') {
682*7c478bd9Sstevel@tonic-gate 			u_short port;
683*7c478bd9Sstevel@tonic-gate 
684*7c478bd9Sstevel@tonic-gate 			p++;
685*7c478bd9Sstevel@tonic-gate 			if (*p == '\0')
686*7c478bd9Sstevel@tonic-gate 				fatal("%s line %d: bad inet addr:port usage.",
687*7c478bd9Sstevel@tonic-gate 				    filename, linenum);
688*7c478bd9Sstevel@tonic-gate 			else {
689*7c478bd9Sstevel@tonic-gate 				*(p-1) = '\0';
690*7c478bd9Sstevel@tonic-gate 				if ((port = a2port(p)) == 0)
691*7c478bd9Sstevel@tonic-gate 					fatal("%s line %d: bad port number.",
692*7c478bd9Sstevel@tonic-gate 					    filename, linenum);
693*7c478bd9Sstevel@tonic-gate 				add_listen_addr(options, arg, port);
694*7c478bd9Sstevel@tonic-gate 			}
695*7c478bd9Sstevel@tonic-gate 		} else if (*p == '\0')
696*7c478bd9Sstevel@tonic-gate 			add_listen_addr(options, arg, 0);
697*7c478bd9Sstevel@tonic-gate 		else
698*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: bad inet addr usage.",
699*7c478bd9Sstevel@tonic-gate 			    filename, linenum);
700*7c478bd9Sstevel@tonic-gate 		break;
701*7c478bd9Sstevel@tonic-gate 
702*7c478bd9Sstevel@tonic-gate 	case sHostKeyFile:
703*7c478bd9Sstevel@tonic-gate 		intptr = &options->num_host_key_files;
704*7c478bd9Sstevel@tonic-gate 		if (*intptr >= MAX_HOSTKEYS)
705*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: too many host keys specified (max %d).",
706*7c478bd9Sstevel@tonic-gate 			    filename, linenum, MAX_HOSTKEYS);
707*7c478bd9Sstevel@tonic-gate 		charptr = &options->host_key_files[*intptr];
708*7c478bd9Sstevel@tonic-gate parse_filename:
709*7c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
710*7c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0')
711*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: missing file name.",
712*7c478bd9Sstevel@tonic-gate 			    filename, linenum);
713*7c478bd9Sstevel@tonic-gate 		if (*charptr == NULL) {
714*7c478bd9Sstevel@tonic-gate 			*charptr = tilde_expand_filename(arg, getuid());
715*7c478bd9Sstevel@tonic-gate 			/* increase optional counter */
716*7c478bd9Sstevel@tonic-gate 			if (intptr != NULL)
717*7c478bd9Sstevel@tonic-gate 				*intptr = *intptr + 1;
718*7c478bd9Sstevel@tonic-gate 		}
719*7c478bd9Sstevel@tonic-gate 		break;
720*7c478bd9Sstevel@tonic-gate 
721*7c478bd9Sstevel@tonic-gate 	case sPidFile:
722*7c478bd9Sstevel@tonic-gate 		charptr = &options->pid_file;
723*7c478bd9Sstevel@tonic-gate 		goto parse_filename;
724*7c478bd9Sstevel@tonic-gate 
725*7c478bd9Sstevel@tonic-gate 	case sPermitRootLogin:
726*7c478bd9Sstevel@tonic-gate 		intptr = &options->permit_root_login;
727*7c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
728*7c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0')
729*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: missing yes/"
730*7c478bd9Sstevel@tonic-gate 			    "without-password/forced-commands-only/no "
731*7c478bd9Sstevel@tonic-gate 			    "argument.", filename, linenum);
732*7c478bd9Sstevel@tonic-gate 		value = 0;	/* silence compiler */
733*7c478bd9Sstevel@tonic-gate 		if (strcmp(arg, "without-password") == 0)
734*7c478bd9Sstevel@tonic-gate 			value = PERMIT_NO_PASSWD;
735*7c478bd9Sstevel@tonic-gate 		else if (strcmp(arg, "forced-commands-only") == 0)
736*7c478bd9Sstevel@tonic-gate 			value = PERMIT_FORCED_ONLY;
737*7c478bd9Sstevel@tonic-gate 		else if (strcmp(arg, "yes") == 0)
738*7c478bd9Sstevel@tonic-gate 			value = PERMIT_YES;
739*7c478bd9Sstevel@tonic-gate 		else if (strcmp(arg, "no") == 0)
740*7c478bd9Sstevel@tonic-gate 			value = PERMIT_NO;
741*7c478bd9Sstevel@tonic-gate 		else
742*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Bad yes/"
743*7c478bd9Sstevel@tonic-gate 			    "without-password/forced-commands-only/no "
744*7c478bd9Sstevel@tonic-gate 			    "argument: %s", filename, linenum, arg);
745*7c478bd9Sstevel@tonic-gate 		if (*intptr == -1)
746*7c478bd9Sstevel@tonic-gate 			*intptr = value;
747*7c478bd9Sstevel@tonic-gate 		break;
748*7c478bd9Sstevel@tonic-gate 
749*7c478bd9Sstevel@tonic-gate 	case sIgnoreRhosts:
750*7c478bd9Sstevel@tonic-gate 		intptr = &options->ignore_rhosts;
751*7c478bd9Sstevel@tonic-gate parse_flag:
752*7c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
753*7c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0')
754*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: missing yes/no argument.",
755*7c478bd9Sstevel@tonic-gate 			    filename, linenum);
756*7c478bd9Sstevel@tonic-gate 		value = 0;	/* silence compiler */
757*7c478bd9Sstevel@tonic-gate 		if (strcmp(arg, "yes") == 0)
758*7c478bd9Sstevel@tonic-gate 			value = 1;
759*7c478bd9Sstevel@tonic-gate 		else if (strcmp(arg, "no") == 0)
760*7c478bd9Sstevel@tonic-gate 			value = 0;
761*7c478bd9Sstevel@tonic-gate 		else
762*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Bad yes/no argument: %s",
763*7c478bd9Sstevel@tonic-gate 				filename, linenum, arg);
764*7c478bd9Sstevel@tonic-gate 		if (*intptr == -1)
765*7c478bd9Sstevel@tonic-gate 			*intptr = value;
766*7c478bd9Sstevel@tonic-gate 		break;
767*7c478bd9Sstevel@tonic-gate 
768*7c478bd9Sstevel@tonic-gate 	case sIgnoreUserKnownHosts:
769*7c478bd9Sstevel@tonic-gate 		intptr = &options->ignore_user_known_hosts;
770*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
771*7c478bd9Sstevel@tonic-gate 
772*7c478bd9Sstevel@tonic-gate 	case sRhostsAuthentication:
773*7c478bd9Sstevel@tonic-gate 		intptr = &options->rhosts_authentication;
774*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
775*7c478bd9Sstevel@tonic-gate 
776*7c478bd9Sstevel@tonic-gate 	case sRhostsRSAAuthentication:
777*7c478bd9Sstevel@tonic-gate 		intptr = &options->rhosts_rsa_authentication;
778*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
779*7c478bd9Sstevel@tonic-gate 
780*7c478bd9Sstevel@tonic-gate 	case sHostbasedAuthentication:
781*7c478bd9Sstevel@tonic-gate 		intptr = &options->hostbased_authentication;
782*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
783*7c478bd9Sstevel@tonic-gate 
784*7c478bd9Sstevel@tonic-gate 	case sHostbasedUsesNameFromPacketOnly:
785*7c478bd9Sstevel@tonic-gate 		intptr = &options->hostbased_uses_name_from_packet_only;
786*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
787*7c478bd9Sstevel@tonic-gate 
788*7c478bd9Sstevel@tonic-gate 	case sRSAAuthentication:
789*7c478bd9Sstevel@tonic-gate 		intptr = &options->rsa_authentication;
790*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
791*7c478bd9Sstevel@tonic-gate 
792*7c478bd9Sstevel@tonic-gate 	case sPubkeyAuthentication:
793*7c478bd9Sstevel@tonic-gate 		intptr = &options->pubkey_authentication;
794*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
795*7c478bd9Sstevel@tonic-gate #ifdef GSSAPI
796*7c478bd9Sstevel@tonic-gate 	case sGssAuthentication:
797*7c478bd9Sstevel@tonic-gate 		intptr = &options->gss_authentication;
798*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
799*7c478bd9Sstevel@tonic-gate 	case sGssKeyEx:
800*7c478bd9Sstevel@tonic-gate 		intptr = &options->gss_keyex;
801*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
802*7c478bd9Sstevel@tonic-gate 	case sGssStoreDelegCreds:
803*7c478bd9Sstevel@tonic-gate 		intptr = &options->gss_keyex;
804*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
805*7c478bd9Sstevel@tonic-gate #ifndef SUNW_GSSAPI
806*7c478bd9Sstevel@tonic-gate 	case sGssUseSessionCredCache:
807*7c478bd9Sstevel@tonic-gate 		intptr = &options->gss_use_session_ccache;
808*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
809*7c478bd9Sstevel@tonic-gate 	case sGssCleanupCreds:
810*7c478bd9Sstevel@tonic-gate 		intptr = &options->gss_cleanup_creds;
811*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
812*7c478bd9Sstevel@tonic-gate #endif /* SUNW_GSSAPI */
813*7c478bd9Sstevel@tonic-gate #endif /* GSSAPI */
814*7c478bd9Sstevel@tonic-gate #if defined(KRB4) || defined(KRB5)
815*7c478bd9Sstevel@tonic-gate 	case sKerberosAuthentication:
816*7c478bd9Sstevel@tonic-gate 		intptr = &options->kerberos_authentication;
817*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
818*7c478bd9Sstevel@tonic-gate 
819*7c478bd9Sstevel@tonic-gate 	case sKerberosOrLocalPasswd:
820*7c478bd9Sstevel@tonic-gate 		intptr = &options->kerberos_or_local_passwd;
821*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
822*7c478bd9Sstevel@tonic-gate 
823*7c478bd9Sstevel@tonic-gate 	case sKerberosTicketCleanup:
824*7c478bd9Sstevel@tonic-gate 		intptr = &options->kerberos_ticket_cleanup;
825*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
826*7c478bd9Sstevel@tonic-gate #endif
827*7c478bd9Sstevel@tonic-gate #if defined(AFS) || defined(KRB5)
828*7c478bd9Sstevel@tonic-gate 	case sKerberosTgtPassing:
829*7c478bd9Sstevel@tonic-gate 		intptr = &options->kerberos_tgt_passing;
830*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
831*7c478bd9Sstevel@tonic-gate #endif
832*7c478bd9Sstevel@tonic-gate #ifdef AFS
833*7c478bd9Sstevel@tonic-gate 	case sAFSTokenPassing:
834*7c478bd9Sstevel@tonic-gate 		intptr = &options->afs_token_passing;
835*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
836*7c478bd9Sstevel@tonic-gate #endif
837*7c478bd9Sstevel@tonic-gate 
838*7c478bd9Sstevel@tonic-gate 	case sPasswordAuthentication:
839*7c478bd9Sstevel@tonic-gate 		intptr = &options->password_authentication;
840*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
841*7c478bd9Sstevel@tonic-gate 
842*7c478bd9Sstevel@tonic-gate 	case sKbdInteractiveAuthentication:
843*7c478bd9Sstevel@tonic-gate 		intptr = &options->kbd_interactive_authentication;
844*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
845*7c478bd9Sstevel@tonic-gate 
846*7c478bd9Sstevel@tonic-gate 	case sChallengeResponseAuthentication:
847*7c478bd9Sstevel@tonic-gate 		intptr = &options->challenge_response_authentication;
848*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
849*7c478bd9Sstevel@tonic-gate 
850*7c478bd9Sstevel@tonic-gate 	case sPrintMotd:
851*7c478bd9Sstevel@tonic-gate 		intptr = &options->print_motd;
852*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
853*7c478bd9Sstevel@tonic-gate 
854*7c478bd9Sstevel@tonic-gate 	case sPrintLastLog:
855*7c478bd9Sstevel@tonic-gate 		intptr = &options->print_lastlog;
856*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
857*7c478bd9Sstevel@tonic-gate 
858*7c478bd9Sstevel@tonic-gate 	case sX11Forwarding:
859*7c478bd9Sstevel@tonic-gate 		intptr = &options->x11_forwarding;
860*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
861*7c478bd9Sstevel@tonic-gate 
862*7c478bd9Sstevel@tonic-gate 	case sX11DisplayOffset:
863*7c478bd9Sstevel@tonic-gate 		intptr = &options->x11_display_offset;
864*7c478bd9Sstevel@tonic-gate 		goto parse_int;
865*7c478bd9Sstevel@tonic-gate 
866*7c478bd9Sstevel@tonic-gate 	case sX11UseLocalhost:
867*7c478bd9Sstevel@tonic-gate 		intptr = &options->x11_use_localhost;
868*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
869*7c478bd9Sstevel@tonic-gate 
870*7c478bd9Sstevel@tonic-gate 	case sXAuthLocation:
871*7c478bd9Sstevel@tonic-gate 		charptr = &options->xauth_location;
872*7c478bd9Sstevel@tonic-gate 		goto parse_filename;
873*7c478bd9Sstevel@tonic-gate 
874*7c478bd9Sstevel@tonic-gate 	case sStrictModes:
875*7c478bd9Sstevel@tonic-gate 		intptr = &options->strict_modes;
876*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
877*7c478bd9Sstevel@tonic-gate 
878*7c478bd9Sstevel@tonic-gate 	case sKeepAlives:
879*7c478bd9Sstevel@tonic-gate 		intptr = &options->keepalives;
880*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
881*7c478bd9Sstevel@tonic-gate 
882*7c478bd9Sstevel@tonic-gate 	case sEmptyPasswd:
883*7c478bd9Sstevel@tonic-gate 		intptr = &options->permit_empty_passwd;
884*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
885*7c478bd9Sstevel@tonic-gate 
886*7c478bd9Sstevel@tonic-gate 	case sPermitUserEnvironment:
887*7c478bd9Sstevel@tonic-gate 		intptr = &options->permit_user_env;
888*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
889*7c478bd9Sstevel@tonic-gate 
890*7c478bd9Sstevel@tonic-gate 	case sUseLogin:
891*7c478bd9Sstevel@tonic-gate 		intptr = &options->use_login;
892*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
893*7c478bd9Sstevel@tonic-gate 
894*7c478bd9Sstevel@tonic-gate 	case sCompression:
895*7c478bd9Sstevel@tonic-gate 		intptr = &options->compression;
896*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
897*7c478bd9Sstevel@tonic-gate 
898*7c478bd9Sstevel@tonic-gate 	case sGatewayPorts:
899*7c478bd9Sstevel@tonic-gate 		intptr = &options->gateway_ports;
900*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
901*7c478bd9Sstevel@tonic-gate 
902*7c478bd9Sstevel@tonic-gate 	case sVerifyReverseMapping:
903*7c478bd9Sstevel@tonic-gate 		intptr = &options->verify_reverse_mapping;
904*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
905*7c478bd9Sstevel@tonic-gate 
906*7c478bd9Sstevel@tonic-gate 	case sLogFacility:
907*7c478bd9Sstevel@tonic-gate 		intptr = (int *) &options->log_facility;
908*7c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
909*7c478bd9Sstevel@tonic-gate 		value = log_facility_number(arg);
910*7c478bd9Sstevel@tonic-gate 		if (value == SYSLOG_FACILITY_NOT_SET)
911*7c478bd9Sstevel@tonic-gate 			fatal("%.200s line %d: unsupported log facility '%s'",
912*7c478bd9Sstevel@tonic-gate 			    filename, linenum, arg ? arg : "<NONE>");
913*7c478bd9Sstevel@tonic-gate 		if (*intptr == -1)
914*7c478bd9Sstevel@tonic-gate 			*intptr = (SyslogFacility) value;
915*7c478bd9Sstevel@tonic-gate 		break;
916*7c478bd9Sstevel@tonic-gate 
917*7c478bd9Sstevel@tonic-gate 	case sLogLevel:
918*7c478bd9Sstevel@tonic-gate 		intptr = (int *) &options->log_level;
919*7c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
920*7c478bd9Sstevel@tonic-gate 		value = log_level_number(arg);
921*7c478bd9Sstevel@tonic-gate 		if (value == SYSLOG_LEVEL_NOT_SET)
922*7c478bd9Sstevel@tonic-gate 			fatal("%.200s line %d: unsupported log level '%s'",
923*7c478bd9Sstevel@tonic-gate 			    filename, linenum, arg ? arg : "<NONE>");
924*7c478bd9Sstevel@tonic-gate 		if (*intptr == -1)
925*7c478bd9Sstevel@tonic-gate 			*intptr = (LogLevel) value;
926*7c478bd9Sstevel@tonic-gate 		break;
927*7c478bd9Sstevel@tonic-gate 
928*7c478bd9Sstevel@tonic-gate 	case sAllowTcpForwarding:
929*7c478bd9Sstevel@tonic-gate 		intptr = &options->allow_tcp_forwarding;
930*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
931*7c478bd9Sstevel@tonic-gate 
932*7c478bd9Sstevel@tonic-gate 	case sUsePrivilegeSeparation:
933*7c478bd9Sstevel@tonic-gate 		intptr = &use_privsep;
934*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
935*7c478bd9Sstevel@tonic-gate 
936*7c478bd9Sstevel@tonic-gate 	case sAllowUsers:
937*7c478bd9Sstevel@tonic-gate 		while (((arg = strdelim(&cp)) != NULL) && *arg != '\0') {
938*7c478bd9Sstevel@tonic-gate 			if (options->num_allow_users >= MAX_ALLOW_USERS)
939*7c478bd9Sstevel@tonic-gate 				fatal("%s line %d: too many allow users.",
940*7c478bd9Sstevel@tonic-gate 				    filename, linenum);
941*7c478bd9Sstevel@tonic-gate 			options->allow_users[options->num_allow_users++] =
942*7c478bd9Sstevel@tonic-gate 			    xstrdup(arg);
943*7c478bd9Sstevel@tonic-gate 		}
944*7c478bd9Sstevel@tonic-gate 		break;
945*7c478bd9Sstevel@tonic-gate 
946*7c478bd9Sstevel@tonic-gate 	case sDenyUsers:
947*7c478bd9Sstevel@tonic-gate 		while (((arg = strdelim(&cp)) != NULL) && *arg != '\0') {
948*7c478bd9Sstevel@tonic-gate 			if (options->num_deny_users >= MAX_DENY_USERS)
949*7c478bd9Sstevel@tonic-gate 				fatal( "%s line %d: too many deny users.",
950*7c478bd9Sstevel@tonic-gate 				    filename, linenum);
951*7c478bd9Sstevel@tonic-gate 			options->deny_users[options->num_deny_users++] =
952*7c478bd9Sstevel@tonic-gate 			    xstrdup(arg);
953*7c478bd9Sstevel@tonic-gate 		}
954*7c478bd9Sstevel@tonic-gate 		break;
955*7c478bd9Sstevel@tonic-gate 
956*7c478bd9Sstevel@tonic-gate 	case sAllowGroups:
957*7c478bd9Sstevel@tonic-gate 		while (((arg = strdelim(&cp)) != NULL) && *arg != '\0') {
958*7c478bd9Sstevel@tonic-gate 			if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
959*7c478bd9Sstevel@tonic-gate 				fatal("%s line %d: too many allow groups.",
960*7c478bd9Sstevel@tonic-gate 				    filename, linenum);
961*7c478bd9Sstevel@tonic-gate 			options->allow_groups[options->num_allow_groups++] =
962*7c478bd9Sstevel@tonic-gate 			    xstrdup(arg);
963*7c478bd9Sstevel@tonic-gate 		}
964*7c478bd9Sstevel@tonic-gate 		break;
965*7c478bd9Sstevel@tonic-gate 
966*7c478bd9Sstevel@tonic-gate 	case sDenyGroups:
967*7c478bd9Sstevel@tonic-gate 		while (((arg = strdelim(&cp)) != NULL) && *arg != '\0') {
968*7c478bd9Sstevel@tonic-gate 			if (options->num_deny_groups >= MAX_DENY_GROUPS)
969*7c478bd9Sstevel@tonic-gate 				fatal("%s line %d: too many deny groups.",
970*7c478bd9Sstevel@tonic-gate 				    filename, linenum);
971*7c478bd9Sstevel@tonic-gate 			options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
972*7c478bd9Sstevel@tonic-gate 		}
973*7c478bd9Sstevel@tonic-gate 		break;
974*7c478bd9Sstevel@tonic-gate 
975*7c478bd9Sstevel@tonic-gate 	case sCiphers:
976*7c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
977*7c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0')
978*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Missing argument.", filename, linenum);
979*7c478bd9Sstevel@tonic-gate 		if (!ciphers_valid(arg))
980*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
981*7c478bd9Sstevel@tonic-gate 			    filename, linenum, arg ? arg : "<NONE>");
982*7c478bd9Sstevel@tonic-gate 		if (options->ciphers == NULL)
983*7c478bd9Sstevel@tonic-gate 			options->ciphers = xstrdup(arg);
984*7c478bd9Sstevel@tonic-gate 		break;
985*7c478bd9Sstevel@tonic-gate 
986*7c478bd9Sstevel@tonic-gate 	case sMacs:
987*7c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
988*7c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0')
989*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Missing argument.", filename, linenum);
990*7c478bd9Sstevel@tonic-gate 		if (!mac_valid(arg))
991*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Bad SSH2 mac spec '%s'.",
992*7c478bd9Sstevel@tonic-gate 			    filename, linenum, arg ? arg : "<NONE>");
993*7c478bd9Sstevel@tonic-gate 		if (options->macs == NULL)
994*7c478bd9Sstevel@tonic-gate 			options->macs = xstrdup(arg);
995*7c478bd9Sstevel@tonic-gate 		break;
996*7c478bd9Sstevel@tonic-gate 
997*7c478bd9Sstevel@tonic-gate 	case sProtocol:
998*7c478bd9Sstevel@tonic-gate 		intptr = &options->protocol;
999*7c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
1000*7c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0')
1001*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Missing argument.", filename, linenum);
1002*7c478bd9Sstevel@tonic-gate 		value = proto_spec(arg);
1003*7c478bd9Sstevel@tonic-gate 		if (value == SSH_PROTO_UNKNOWN)
1004*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Bad protocol spec '%s'.",
1005*7c478bd9Sstevel@tonic-gate 			    filename, linenum, arg ? arg : "<NONE>");
1006*7c478bd9Sstevel@tonic-gate 		if (*intptr == SSH_PROTO_UNKNOWN)
1007*7c478bd9Sstevel@tonic-gate 			*intptr = value;
1008*7c478bd9Sstevel@tonic-gate 		break;
1009*7c478bd9Sstevel@tonic-gate 
1010*7c478bd9Sstevel@tonic-gate 	case sSubsystem:
1011*7c478bd9Sstevel@tonic-gate 		if (options->num_subsystems >= MAX_SUBSYSTEMS) {
1012*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: too many subsystems defined.",
1013*7c478bd9Sstevel@tonic-gate 			    filename, linenum);
1014*7c478bd9Sstevel@tonic-gate 		}
1015*7c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
1016*7c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0')
1017*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Missing subsystem name.",
1018*7c478bd9Sstevel@tonic-gate 			    filename, linenum);
1019*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < options->num_subsystems; i++)
1020*7c478bd9Sstevel@tonic-gate 			if (strcmp(arg, options->subsystem_name[i]) == 0)
1021*7c478bd9Sstevel@tonic-gate 				fatal("%s line %d: Subsystem '%s' already defined.",
1022*7c478bd9Sstevel@tonic-gate 				    filename, linenum, arg);
1023*7c478bd9Sstevel@tonic-gate 		options->subsystem_name[options->num_subsystems] = xstrdup(arg);
1024*7c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
1025*7c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0')
1026*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Missing subsystem command.",
1027*7c478bd9Sstevel@tonic-gate 			    filename, linenum);
1028*7c478bd9Sstevel@tonic-gate 		options->subsystem_command[options->num_subsystems] = xstrdup(arg);
1029*7c478bd9Sstevel@tonic-gate 		options->num_subsystems++;
1030*7c478bd9Sstevel@tonic-gate 		break;
1031*7c478bd9Sstevel@tonic-gate 
1032*7c478bd9Sstevel@tonic-gate 	case sMaxStartups:
1033*7c478bd9Sstevel@tonic-gate 		arg = strdelim(&cp);
1034*7c478bd9Sstevel@tonic-gate 		if (!arg || *arg == '\0')
1035*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Missing MaxStartups spec.",
1036*7c478bd9Sstevel@tonic-gate 			    filename, linenum);
1037*7c478bd9Sstevel@tonic-gate 		if ((n = sscanf(arg, "%d:%d:%d",
1038*7c478bd9Sstevel@tonic-gate 		    &options->max_startups_begin,
1039*7c478bd9Sstevel@tonic-gate 		    &options->max_startups_rate,
1040*7c478bd9Sstevel@tonic-gate 		    &options->max_startups)) == 3) {
1041*7c478bd9Sstevel@tonic-gate 			if (options->max_startups_begin >
1042*7c478bd9Sstevel@tonic-gate 			    options->max_startups ||
1043*7c478bd9Sstevel@tonic-gate 			    options->max_startups_rate > 100 ||
1044*7c478bd9Sstevel@tonic-gate 			    options->max_startups_rate < 1)
1045*7c478bd9Sstevel@tonic-gate 				fatal("%s line %d: Illegal MaxStartups spec.",
1046*7c478bd9Sstevel@tonic-gate 				    filename, linenum);
1047*7c478bd9Sstevel@tonic-gate 		} else if (n != 1)
1048*7c478bd9Sstevel@tonic-gate 			fatal("%s line %d: Illegal MaxStartups spec.",
1049*7c478bd9Sstevel@tonic-gate 			    filename, linenum);
1050*7c478bd9Sstevel@tonic-gate 		else
1051*7c478bd9Sstevel@tonic-gate 			options->max_startups = options->max_startups_begin;
1052*7c478bd9Sstevel@tonic-gate 		break;
1053*7c478bd9Sstevel@tonic-gate 
1054*7c478bd9Sstevel@tonic-gate 	case sBanner:
1055*7c478bd9Sstevel@tonic-gate 		charptr = &options->banner;
1056*7c478bd9Sstevel@tonic-gate 		goto parse_filename;
1057*7c478bd9Sstevel@tonic-gate 	/*
1058*7c478bd9Sstevel@tonic-gate 	 * These options can contain %X options expanded at
1059*7c478bd9Sstevel@tonic-gate 	 * connect time, so that you can specify paths like:
1060*7c478bd9Sstevel@tonic-gate 	 *
1061*7c478bd9Sstevel@tonic-gate 	 * AuthorizedKeysFile	/etc/ssh_keys/%u
1062*7c478bd9Sstevel@tonic-gate 	 */
1063*7c478bd9Sstevel@tonic-gate 	case sAuthorizedKeysFile:
1064*7c478bd9Sstevel@tonic-gate 	case sAuthorizedKeysFile2:
1065*7c478bd9Sstevel@tonic-gate 		charptr = (opcode == sAuthorizedKeysFile ) ?
1066*7c478bd9Sstevel@tonic-gate 		    &options->authorized_keys_file :
1067*7c478bd9Sstevel@tonic-gate 		    &options->authorized_keys_file2;
1068*7c478bd9Sstevel@tonic-gate 		goto parse_filename;
1069*7c478bd9Sstevel@tonic-gate 
1070*7c478bd9Sstevel@tonic-gate 	case sClientAliveInterval:
1071*7c478bd9Sstevel@tonic-gate 		intptr = &options->client_alive_interval;
1072*7c478bd9Sstevel@tonic-gate 		goto parse_time;
1073*7c478bd9Sstevel@tonic-gate 
1074*7c478bd9Sstevel@tonic-gate 	case sClientAliveCountMax:
1075*7c478bd9Sstevel@tonic-gate 		intptr = &options->client_alive_count_max;
1076*7c478bd9Sstevel@tonic-gate 		goto parse_int;
1077*7c478bd9Sstevel@tonic-gate 
1078*7c478bd9Sstevel@tonic-gate 	case sMaxAuthTries:
1079*7c478bd9Sstevel@tonic-gate 		intptr = &options->max_auth_tries;
1080*7c478bd9Sstevel@tonic-gate 		goto parse_int;
1081*7c478bd9Sstevel@tonic-gate 
1082*7c478bd9Sstevel@tonic-gate 	case sMaxAuthTriesLog:
1083*7c478bd9Sstevel@tonic-gate 		intptr = &options->max_auth_tries_log;
1084*7c478bd9Sstevel@tonic-gate 		goto parse_int;
1085*7c478bd9Sstevel@tonic-gate 
1086*7c478bd9Sstevel@tonic-gate 	case sLookupClientHostnames:
1087*7c478bd9Sstevel@tonic-gate 		intptr = &options->lookup_client_hostnames;
1088*7c478bd9Sstevel@tonic-gate 		goto parse_flag;
1089*7c478bd9Sstevel@tonic-gate 
1090*7c478bd9Sstevel@tonic-gate 	case sDeprecated:
1091*7c478bd9Sstevel@tonic-gate 		log("%s line %d: Deprecated option %s",
1092*7c478bd9Sstevel@tonic-gate 		    filename, linenum, arg);
1093*7c478bd9Sstevel@tonic-gate 		while (arg)
1094*7c478bd9Sstevel@tonic-gate 		    arg = strdelim(&cp);
1095*7c478bd9Sstevel@tonic-gate 		break;
1096*7c478bd9Sstevel@tonic-gate 
1097*7c478bd9Sstevel@tonic-gate 	default:
1098*7c478bd9Sstevel@tonic-gate 		fatal("%s line %d: Missing handler for opcode %s (%d)",
1099*7c478bd9Sstevel@tonic-gate 		    filename, linenum, arg, opcode);
1100*7c478bd9Sstevel@tonic-gate 	}
1101*7c478bd9Sstevel@tonic-gate 	if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
1102*7c478bd9Sstevel@tonic-gate 		fatal("%s line %d: garbage at end of line; \"%.200s\".",
1103*7c478bd9Sstevel@tonic-gate 		    filename, linenum, arg);
1104*7c478bd9Sstevel@tonic-gate 	return 0;
1105*7c478bd9Sstevel@tonic-gate }
1106*7c478bd9Sstevel@tonic-gate 
1107*7c478bd9Sstevel@tonic-gate /* Reads the server configuration file. */
1108*7c478bd9Sstevel@tonic-gate 
1109*7c478bd9Sstevel@tonic-gate void
1110*7c478bd9Sstevel@tonic-gate read_server_config(ServerOptions *options, const char *filename)
1111*7c478bd9Sstevel@tonic-gate {
1112*7c478bd9Sstevel@tonic-gate 	int linenum, bad_options = 0;
1113*7c478bd9Sstevel@tonic-gate 	char line[1024];
1114*7c478bd9Sstevel@tonic-gate 	FILE *f;
1115*7c478bd9Sstevel@tonic-gate 
1116*7c478bd9Sstevel@tonic-gate 	f = fopen(filename, "r");
1117*7c478bd9Sstevel@tonic-gate 	if (!f) {
1118*7c478bd9Sstevel@tonic-gate 		perror(filename);
1119*7c478bd9Sstevel@tonic-gate 		exit(1);
1120*7c478bd9Sstevel@tonic-gate 	}
1121*7c478bd9Sstevel@tonic-gate 	linenum = 0;
1122*7c478bd9Sstevel@tonic-gate 	while (fgets(line, sizeof(line), f)) {
1123*7c478bd9Sstevel@tonic-gate 		/* Update line number counter. */
1124*7c478bd9Sstevel@tonic-gate 		linenum++;
1125*7c478bd9Sstevel@tonic-gate 		if (process_server_config_line(options, line, filename, linenum) != 0)
1126*7c478bd9Sstevel@tonic-gate 			bad_options++;
1127*7c478bd9Sstevel@tonic-gate 	}
1128*7c478bd9Sstevel@tonic-gate 	(void) fclose(f);
1129*7c478bd9Sstevel@tonic-gate 	if (bad_options > 0)
1130*7c478bd9Sstevel@tonic-gate 		fatal("%s: terminating, %d bad configuration options",
1131*7c478bd9Sstevel@tonic-gate 		    filename, bad_options);
1132*7c478bd9Sstevel@tonic-gate }
1133