xref: /freebsd/crypto/openssh/servconf.c (revision b15c83408cb1e9b86c1895af0f097de05fc92ccf)
1b15c8340SDag-Erling Smørgrav /* $OpenBSD: servconf.c,v 1.204 2010/03/04 10:36:03 djm Exp $ */
2511b41d2SMark Murray /*
3511b41d2SMark Murray  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4511b41d2SMark Murray  *                    All rights reserved
5511b41d2SMark Murray  *
6c2d3a559SKris Kennaway  * As far as I am concerned, the code I have written for this software
7c2d3a559SKris Kennaway  * can be used freely for any purpose.  Any derived versions of this
8c2d3a559SKris Kennaway  * software must be clearly marked as such, and if the derived work is
9c2d3a559SKris Kennaway  * incompatible with the protocol description in the RFC file, it must be
10c2d3a559SKris Kennaway  * called by a name other than "ssh" or "Secure Shell".
11511b41d2SMark Murray  */
12511b41d2SMark Murray 
13511b41d2SMark Murray #include "includes.h"
14333ee039SDag-Erling Smørgrav __RCSID("$FreeBSD$");
15511b41d2SMark Murray 
16333ee039SDag-Erling Smørgrav #include <sys/types.h>
17333ee039SDag-Erling Smørgrav #include <sys/socket.h>
18333ee039SDag-Erling Smørgrav 
19333ee039SDag-Erling Smørgrav #include <netdb.h>
20333ee039SDag-Erling Smørgrav #include <pwd.h>
21333ee039SDag-Erling Smørgrav #include <stdio.h>
22333ee039SDag-Erling Smørgrav #include <stdlib.h>
23333ee039SDag-Erling Smørgrav #include <string.h>
24333ee039SDag-Erling Smørgrav #include <signal.h>
25333ee039SDag-Erling Smørgrav #include <unistd.h>
26333ee039SDag-Erling Smørgrav #include <stdarg.h>
27d4af9e69SDag-Erling Smørgrav #include <errno.h>
28333ee039SDag-Erling Smørgrav 
29d4af9e69SDag-Erling Smørgrav #include "openbsd-compat/sys-queue.h"
30333ee039SDag-Erling Smørgrav #include "xmalloc.h"
31511b41d2SMark Murray #include "ssh.h"
32ca3176e7SBrian Feldman #include "log.h"
33333ee039SDag-Erling Smørgrav #include "buffer.h"
34511b41d2SMark Murray #include "servconf.h"
35e8aafc91SKris Kennaway #include "compat.h"
36ca3176e7SBrian Feldman #include "pathnames.h"
37ca3176e7SBrian Feldman #include "misc.h"
38ca3176e7SBrian Feldman #include "cipher.h"
39333ee039SDag-Erling Smørgrav #include "key.h"
40ca3176e7SBrian Feldman #include "kex.h"
41ca3176e7SBrian Feldman #include "mac.h"
42333ee039SDag-Erling Smørgrav #include "match.h"
43333ee039SDag-Erling Smørgrav #include "channels.h"
44333ee039SDag-Erling Smørgrav #include "groupaccess.h"
45b15c8340SDag-Erling Smørgrav #include "version.h"
46511b41d2SMark Murray 
47cce7d346SDag-Erling Smørgrav static void add_listen_addr(ServerOptions *, char *, int);
48cce7d346SDag-Erling Smørgrav static void add_one_listen_addr(ServerOptions *, char *, int);
49ca3176e7SBrian Feldman 
5080628bacSDag-Erling Smørgrav /* Use of privilege separation or not */
5180628bacSDag-Erling Smørgrav extern int use_privsep;
52333ee039SDag-Erling Smørgrav extern Buffer cfg;
53511b41d2SMark Murray 
54511b41d2SMark Murray /* Initializes the server options to their default values. */
55511b41d2SMark Murray 
56511b41d2SMark Murray void
57511b41d2SMark Murray initialize_server_options(ServerOptions *options)
58511b41d2SMark Murray {
59511b41d2SMark Murray 	memset(options, 0, sizeof(*options));
60989dd127SDag-Erling Smørgrav 
61989dd127SDag-Erling Smørgrav 	/* Portable-specific options */
62cf2b5f3bSDag-Erling Smørgrav 	options->use_pam = -1;
63989dd127SDag-Erling Smørgrav 
64989dd127SDag-Erling Smørgrav 	/* Standard Options */
65511b41d2SMark Murray 	options->num_ports = 0;
66511b41d2SMark Murray 	options->ports_from_cmdline = 0;
67511b41d2SMark Murray 	options->listen_addrs = NULL;
68aa49c926SDag-Erling Smørgrav 	options->address_family = -1;
69ca3176e7SBrian Feldman 	options->num_host_key_files = 0;
70b15c8340SDag-Erling Smørgrav 	options->num_host_cert_files = 0;
71e8aafc91SKris Kennaway 	options->pid_file = NULL;
72511b41d2SMark Murray 	options->server_key_bits = -1;
73511b41d2SMark Murray 	options->login_grace_time = -1;
74511b41d2SMark Murray 	options->key_regeneration_time = -1;
75ca3176e7SBrian Feldman 	options->permit_root_login = PERMIT_NOT_SET;
76511b41d2SMark Murray 	options->ignore_rhosts = -1;
77511b41d2SMark Murray 	options->ignore_user_known_hosts = -1;
78511b41d2SMark Murray 	options->print_motd = -1;
79ca3176e7SBrian Feldman 	options->print_lastlog = -1;
80511b41d2SMark Murray 	options->x11_forwarding = -1;
81511b41d2SMark Murray 	options->x11_display_offset = -1;
82af12a3e7SDag-Erling Smørgrav 	options->x11_use_localhost = -1;
83c2d3a559SKris Kennaway 	options->xauth_location = NULL;
84511b41d2SMark Murray 	options->strict_modes = -1;
851ec0d754SDag-Erling Smørgrav 	options->tcp_keep_alive = -1;
86af12a3e7SDag-Erling Smørgrav 	options->log_facility = SYSLOG_FACILITY_NOT_SET;
87af12a3e7SDag-Erling Smørgrav 	options->log_level = SYSLOG_LEVEL_NOT_SET;
88511b41d2SMark Murray 	options->rhosts_rsa_authentication = -1;
89ca3176e7SBrian Feldman 	options->hostbased_authentication = -1;
90ca3176e7SBrian Feldman 	options->hostbased_uses_name_from_packet_only = -1;
91511b41d2SMark Murray 	options->rsa_authentication = -1;
92ca3176e7SBrian Feldman 	options->pubkey_authentication = -1;
93cb96ab36SAssar Westerlund 	options->kerberos_authentication = -1;
94af12a3e7SDag-Erling Smørgrav 	options->kerberos_or_local_passwd = -1;
95af12a3e7SDag-Erling Smørgrav 	options->kerberos_ticket_cleanup = -1;
961ec0d754SDag-Erling Smørgrav 	options->kerberos_get_afs_token = -1;
97cf2b5f3bSDag-Erling Smørgrav 	options->gss_authentication=-1;
98cf2b5f3bSDag-Erling Smørgrav 	options->gss_cleanup_creds = -1;
99511b41d2SMark Murray 	options->password_authentication = -1;
10009958426SBrian Feldman 	options->kbd_interactive_authentication = -1;
101af12a3e7SDag-Erling Smørgrav 	options->challenge_response_authentication = -1;
102511b41d2SMark Murray 	options->permit_empty_passwd = -1;
103f388f5efSDag-Erling Smørgrav 	options->permit_user_env = -1;
104511b41d2SMark Murray 	options->use_login = -1;
10580628bacSDag-Erling Smørgrav 	options->compression = -1;
10609958426SBrian Feldman 	options->allow_tcp_forwarding = -1;
107d4af9e69SDag-Erling Smørgrav 	options->allow_agent_forwarding = -1;
108511b41d2SMark Murray 	options->num_allow_users = 0;
109511b41d2SMark Murray 	options->num_deny_users = 0;
110511b41d2SMark Murray 	options->num_allow_groups = 0;
111511b41d2SMark Murray 	options->num_deny_groups = 0;
112e8aafc91SKris Kennaway 	options->ciphers = NULL;
113ca3176e7SBrian Feldman 	options->macs = NULL;
114e8aafc91SKris Kennaway 	options->protocol = SSH_PROTO_UNKNOWN;
115e8aafc91SKris Kennaway 	options->gateway_ports = -1;
116c2d3a559SKris Kennaway 	options->num_subsystems = 0;
117c2d3a559SKris Kennaway 	options->max_startups_begin = -1;
118c2d3a559SKris Kennaway 	options->max_startups_rate = -1;
119c2d3a559SKris Kennaway 	options->max_startups = -1;
12021e764dfSDag-Erling Smørgrav 	options->max_authtries = -1;
121d4af9e69SDag-Erling Smørgrav 	options->max_sessions = -1;
122ca3176e7SBrian Feldman 	options->banner = NULL;
123cf2b5f3bSDag-Erling Smørgrav 	options->use_dns = -1;
124ca3176e7SBrian Feldman 	options->client_alive_interval = -1;
125ca3176e7SBrian Feldman 	options->client_alive_count_max = -1;
126af12a3e7SDag-Erling Smørgrav 	options->authorized_keys_file = NULL;
127af12a3e7SDag-Erling Smørgrav 	options->authorized_keys_file2 = NULL;
12821e764dfSDag-Erling Smørgrav 	options->num_accept_env = 0;
129b74df5b2SDag-Erling Smørgrav 	options->permit_tun = -1;
130333ee039SDag-Erling Smørgrav 	options->num_permitted_opens = -1;
131333ee039SDag-Erling Smørgrav 	options->adm_forced_command = NULL;
132d4af9e69SDag-Erling Smørgrav 	options->chroot_directory = NULL;
133cce7d346SDag-Erling Smørgrav 	options->zero_knowledge_password_authentication = -1;
134b15c8340SDag-Erling Smørgrav 	options->revoked_keys_file = NULL;
135b15c8340SDag-Erling Smørgrav 	options->trusted_user_ca_keys = NULL;
136511b41d2SMark Murray }
137511b41d2SMark Murray 
138511b41d2SMark Murray void
139511b41d2SMark Murray fill_default_server_options(ServerOptions *options)
140511b41d2SMark Murray {
141989dd127SDag-Erling Smørgrav 	/* Portable-specific options */
142cf2b5f3bSDag-Erling Smørgrav 	if (options->use_pam == -1)
143f0477b26SDag-Erling Smørgrav 		options->use_pam = 1;
144989dd127SDag-Erling Smørgrav 
145989dd127SDag-Erling Smørgrav 	/* Standard Options */
146ca3176e7SBrian Feldman 	if (options->protocol == SSH_PROTO_UNKNOWN)
147028c324aSDag-Erling Smørgrav 		options->protocol = SSH_PROTO_2;
148ca3176e7SBrian Feldman 	if (options->num_host_key_files == 0) {
149ca3176e7SBrian Feldman 		/* fill default hostkeys for protocols */
150ca3176e7SBrian Feldman 		if (options->protocol & SSH_PROTO_1)
151af12a3e7SDag-Erling Smørgrav 			options->host_key_files[options->num_host_key_files++] =
152af12a3e7SDag-Erling Smørgrav 			    _PATH_HOST_KEY_FILE;
153af12a3e7SDag-Erling Smørgrav 		if (options->protocol & SSH_PROTO_2) {
154af12a3e7SDag-Erling Smørgrav 			options->host_key_files[options->num_host_key_files++] =
155d4af9e69SDag-Erling Smørgrav                             _PATH_HOST_RSA_KEY_FILE;
156d4af9e69SDag-Erling Smørgrav 			options->host_key_files[options->num_host_key_files++] =
157af12a3e7SDag-Erling Smørgrav 			    _PATH_HOST_DSA_KEY_FILE;
158af12a3e7SDag-Erling Smørgrav 		}
159ca3176e7SBrian Feldman 	}
160b15c8340SDag-Erling Smørgrav 	/* No certificates by default */
161511b41d2SMark Murray 	if (options->num_ports == 0)
162511b41d2SMark Murray 		options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
163511b41d2SMark Murray 	if (options->listen_addrs == NULL)
164ca3176e7SBrian Feldman 		add_listen_addr(options, NULL, 0);
165e8aafc91SKris Kennaway 	if (options->pid_file == NULL)
166ca3176e7SBrian Feldman 		options->pid_file = _PATH_SSH_DAEMON_PID_FILE;
167511b41d2SMark Murray 	if (options->server_key_bits == -1)
168d4af9e69SDag-Erling Smørgrav 		options->server_key_bits = 1024;
169511b41d2SMark Murray 	if (options->login_grace_time == -1)
170975616f0SDag-Erling Smørgrav 		options->login_grace_time = 120;
171511b41d2SMark Murray 	if (options->key_regeneration_time == -1)
172511b41d2SMark Murray 		options->key_regeneration_time = 3600;
173ca3176e7SBrian Feldman 	if (options->permit_root_login == PERMIT_NOT_SET)
174975616f0SDag-Erling Smørgrav 		options->permit_root_login = PERMIT_NO;
175511b41d2SMark Murray 	if (options->ignore_rhosts == -1)
176fe5fd017SMark Murray 		options->ignore_rhosts = 1;
177511b41d2SMark Murray 	if (options->ignore_user_known_hosts == -1)
178511b41d2SMark Murray 		options->ignore_user_known_hosts = 0;
179511b41d2SMark Murray 	if (options->print_motd == -1)
180511b41d2SMark Murray 		options->print_motd = 1;
181ca3176e7SBrian Feldman 	if (options->print_lastlog == -1)
182ca3176e7SBrian Feldman 		options->print_lastlog = 1;
183511b41d2SMark Murray 	if (options->x11_forwarding == -1)
184975616f0SDag-Erling Smørgrav 		options->x11_forwarding = 1;
185511b41d2SMark Murray 	if (options->x11_display_offset == -1)
186fe5fd017SMark Murray 		options->x11_display_offset = 10;
187af12a3e7SDag-Erling Smørgrav 	if (options->x11_use_localhost == -1)
188af12a3e7SDag-Erling Smørgrav 		options->x11_use_localhost = 1;
189c2d3a559SKris Kennaway 	if (options->xauth_location == NULL)
190af12a3e7SDag-Erling Smørgrav 		options->xauth_location = _PATH_XAUTH;
191511b41d2SMark Murray 	if (options->strict_modes == -1)
192511b41d2SMark Murray 		options->strict_modes = 1;
1931ec0d754SDag-Erling Smørgrav 	if (options->tcp_keep_alive == -1)
1941ec0d754SDag-Erling Smørgrav 		options->tcp_keep_alive = 1;
195af12a3e7SDag-Erling Smørgrav 	if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
196511b41d2SMark Murray 		options->log_facility = SYSLOG_FACILITY_AUTH;
197af12a3e7SDag-Erling Smørgrav 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
198511b41d2SMark Murray 		options->log_level = SYSLOG_LEVEL_INFO;
199511b41d2SMark Murray 	if (options->rhosts_rsa_authentication == -1)
200fe5fd017SMark Murray 		options->rhosts_rsa_authentication = 0;
201ca3176e7SBrian Feldman 	if (options->hostbased_authentication == -1)
202ca3176e7SBrian Feldman 		options->hostbased_authentication = 0;
203ca3176e7SBrian Feldman 	if (options->hostbased_uses_name_from_packet_only == -1)
204ca3176e7SBrian Feldman 		options->hostbased_uses_name_from_packet_only = 0;
205511b41d2SMark Murray 	if (options->rsa_authentication == -1)
206511b41d2SMark Murray 		options->rsa_authentication = 1;
207ca3176e7SBrian Feldman 	if (options->pubkey_authentication == -1)
208ca3176e7SBrian Feldman 		options->pubkey_authentication = 1;
209989dd127SDag-Erling Smørgrav 	if (options->kerberos_authentication == -1)
210cf2b5f3bSDag-Erling Smørgrav 		options->kerberos_authentication = 0;
211af12a3e7SDag-Erling Smørgrav 	if (options->kerberos_or_local_passwd == -1)
212af12a3e7SDag-Erling Smørgrav 		options->kerberos_or_local_passwd = 1;
213af12a3e7SDag-Erling Smørgrav 	if (options->kerberos_ticket_cleanup == -1)
214af12a3e7SDag-Erling Smørgrav 		options->kerberos_ticket_cleanup = 1;
2151ec0d754SDag-Erling Smørgrav 	if (options->kerberos_get_afs_token == -1)
2161ec0d754SDag-Erling Smørgrav 		options->kerberos_get_afs_token = 0;
217cf2b5f3bSDag-Erling Smørgrav 	if (options->gss_authentication == -1)
218cf2b5f3bSDag-Erling Smørgrav 		options->gss_authentication = 0;
219cf2b5f3bSDag-Erling Smørgrav 	if (options->gss_cleanup_creds == -1)
220cf2b5f3bSDag-Erling Smørgrav 		options->gss_cleanup_creds = 1;
221511b41d2SMark Murray 	if (options->password_authentication == -1)
222b909c84bSDag-Erling Smørgrav 		options->password_authentication = 0;
22309958426SBrian Feldman 	if (options->kbd_interactive_authentication == -1)
22409958426SBrian Feldman 		options->kbd_interactive_authentication = 0;
225af12a3e7SDag-Erling Smørgrav 	if (options->challenge_response_authentication == -1)
22680241871SDag-Erling Smørgrav 		options->challenge_response_authentication = 1;
227511b41d2SMark Murray 	if (options->permit_empty_passwd == -1)
228fe5fd017SMark Murray 		options->permit_empty_passwd = 0;
229f388f5efSDag-Erling Smørgrav 	if (options->permit_user_env == -1)
230f388f5efSDag-Erling Smørgrav 		options->permit_user_env = 0;
231511b41d2SMark Murray 	if (options->use_login == -1)
232511b41d2SMark Murray 		options->use_login = 0;
23380628bacSDag-Erling Smørgrav 	if (options->compression == -1)
234d4ecd108SDag-Erling Smørgrav 		options->compression = COMP_DELAYED;
23509958426SBrian Feldman 	if (options->allow_tcp_forwarding == -1)
23609958426SBrian Feldman 		options->allow_tcp_forwarding = 1;
237d4af9e69SDag-Erling Smørgrav 	if (options->allow_agent_forwarding == -1)
238d4af9e69SDag-Erling Smørgrav 		options->allow_agent_forwarding = 1;
239e8aafc91SKris Kennaway 	if (options->gateway_ports == -1)
240e8aafc91SKris Kennaway 		options->gateway_ports = 0;
241c2d3a559SKris Kennaway 	if (options->max_startups == -1)
242c2d3a559SKris Kennaway 		options->max_startups = 10;
243c2d3a559SKris Kennaway 	if (options->max_startups_rate == -1)
244c2d3a559SKris Kennaway 		options->max_startups_rate = 100;		/* 100% */
245c2d3a559SKris Kennaway 	if (options->max_startups_begin == -1)
246c2d3a559SKris Kennaway 		options->max_startups_begin = options->max_startups;
24721e764dfSDag-Erling Smørgrav 	if (options->max_authtries == -1)
24821e764dfSDag-Erling Smørgrav 		options->max_authtries = DEFAULT_AUTH_FAIL_MAX;
249d4af9e69SDag-Erling Smørgrav 	if (options->max_sessions == -1)
250d4af9e69SDag-Erling Smørgrav 		options->max_sessions = DEFAULT_SESSIONS_MAX;
251cf2b5f3bSDag-Erling Smørgrav 	if (options->use_dns == -1)
252cf2b5f3bSDag-Erling Smørgrav 		options->use_dns = 1;
253ca3176e7SBrian Feldman 	if (options->client_alive_interval == -1)
254ca3176e7SBrian Feldman 		options->client_alive_interval = 0;
255ca3176e7SBrian Feldman 	if (options->client_alive_count_max == -1)
256ca3176e7SBrian Feldman 		options->client_alive_count_max = 3;
257af12a3e7SDag-Erling Smørgrav 	if (options->authorized_keys_file2 == NULL) {
258af12a3e7SDag-Erling Smørgrav 		/* authorized_keys_file2 falls back to authorized_keys_file */
259af12a3e7SDag-Erling Smørgrav 		if (options->authorized_keys_file != NULL)
260af12a3e7SDag-Erling Smørgrav 			options->authorized_keys_file2 = options->authorized_keys_file;
261af12a3e7SDag-Erling Smørgrav 		else
262af12a3e7SDag-Erling Smørgrav 			options->authorized_keys_file2 = _PATH_SSH_USER_PERMITTED_KEYS2;
263af12a3e7SDag-Erling Smørgrav 	}
264af12a3e7SDag-Erling Smørgrav 	if (options->authorized_keys_file == NULL)
265af12a3e7SDag-Erling Smørgrav 		options->authorized_keys_file = _PATH_SSH_USER_PERMITTED_KEYS;
266b74df5b2SDag-Erling Smørgrav 	if (options->permit_tun == -1)
267b74df5b2SDag-Erling Smørgrav 		options->permit_tun = SSH_TUNMODE_NO;
268cce7d346SDag-Erling Smørgrav 	if (options->zero_knowledge_password_authentication == -1)
269cce7d346SDag-Erling Smørgrav 		options->zero_knowledge_password_authentication = 0;
27080628bacSDag-Erling Smørgrav 
271989dd127SDag-Erling Smørgrav 	/* Turn privilege separation on by default */
27280628bacSDag-Erling Smørgrav 	if (use_privsep == -1)
273989dd127SDag-Erling Smørgrav 		use_privsep = 1;
274989dd127SDag-Erling Smørgrav 
275f388f5efSDag-Erling Smørgrav #ifndef HAVE_MMAP
276989dd127SDag-Erling Smørgrav 	if (use_privsep && options->compression == 1) {
277989dd127SDag-Erling Smørgrav 		error("This platform does not support both privilege "
278989dd127SDag-Erling Smørgrav 		    "separation and compression");
279989dd127SDag-Erling Smørgrav 		error("Compression disabled");
280989dd127SDag-Erling Smørgrav 		options->compression = 0;
281989dd127SDag-Erling Smørgrav 	}
282989dd127SDag-Erling Smørgrav #endif
283989dd127SDag-Erling Smørgrav 
284511b41d2SMark Murray }
285511b41d2SMark Murray 
286511b41d2SMark Murray /* Keyword tokens. */
287511b41d2SMark Murray typedef enum {
288511b41d2SMark Murray 	sBadOption,		/* == unknown option */
289989dd127SDag-Erling Smørgrav 	/* Portable-specific options */
290cf2b5f3bSDag-Erling Smørgrav 	sUsePAM,
291989dd127SDag-Erling Smørgrav 	/* Standard Options */
292511b41d2SMark Murray 	sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime,
293511b41d2SMark Murray 	sPermitRootLogin, sLogFacility, sLogLevel,
294cf2b5f3bSDag-Erling Smørgrav 	sRhostsRSAAuthentication, sRSAAuthentication,
295af12a3e7SDag-Erling Smørgrav 	sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
2961ec0d754SDag-Erling Smørgrav 	sKerberosGetAFSToken,
297cf2b5f3bSDag-Erling Smørgrav 	sKerberosTgtPassing, sChallengeResponseAuthentication,
298aa49c926SDag-Erling Smørgrav 	sPasswordAuthentication, sKbdInteractiveAuthentication,
299aa49c926SDag-Erling Smørgrav 	sListenAddress, sAddressFamily,
300ca3176e7SBrian Feldman 	sPrintMotd, sPrintLastLog, sIgnoreRhosts,
301af12a3e7SDag-Erling Smørgrav 	sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
3021ec0d754SDag-Erling Smørgrav 	sStrictModes, sEmptyPasswd, sTCPKeepAlive,
303f388f5efSDag-Erling Smørgrav 	sPermitUserEnvironment, sUseLogin, sAllowTcpForwarding, sCompression,
30409958426SBrian Feldman 	sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups,
305ca3176e7SBrian Feldman 	sIgnoreUserKnownHosts, sCiphers, sMacs, sProtocol, sPidFile,
30621e764dfSDag-Erling Smørgrav 	sGatewayPorts, sPubkeyAuthentication, sXAuthLocation, sSubsystem,
307d4af9e69SDag-Erling Smørgrav 	sMaxStartups, sMaxAuthTries, sMaxSessions,
308cf2b5f3bSDag-Erling Smørgrav 	sBanner, sUseDNS, sHostbasedAuthentication,
309ca3176e7SBrian Feldman 	sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
310af12a3e7SDag-Erling Smørgrav 	sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
311b74df5b2SDag-Erling Smørgrav 	sGssAuthentication, sGssCleanupCreds, sAcceptEnv, sPermitTunnel,
312d4af9e69SDag-Erling Smørgrav 	sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
313d4af9e69SDag-Erling Smørgrav 	sUsePrivilegeSeparation, sAllowAgentForwarding,
314b15c8340SDag-Erling Smørgrav 	sZeroKnowledgePasswordAuthentication, sHostCertificate,
315b15c8340SDag-Erling Smørgrav 	sRevokedKeys, sTrustedUserCAKeys,
316db58a8e4SDag-Erling Smørgrav 	sVersionAddendum,
317cf2b5f3bSDag-Erling Smørgrav 	sDeprecated, sUnsupported
318511b41d2SMark Murray } ServerOpCodes;
319511b41d2SMark Murray 
320333ee039SDag-Erling Smørgrav #define SSHCFG_GLOBAL	0x01	/* allowed in main section of sshd_config */
321333ee039SDag-Erling Smørgrav #define SSHCFG_MATCH	0x02	/* allowed inside a Match section */
322333ee039SDag-Erling Smørgrav #define SSHCFG_ALL	(SSHCFG_GLOBAL|SSHCFG_MATCH)
323333ee039SDag-Erling Smørgrav 
324511b41d2SMark Murray /* Textual representation of the tokens. */
325511b41d2SMark Murray static struct {
326511b41d2SMark Murray 	const char *name;
327511b41d2SMark Murray 	ServerOpCodes opcode;
328333ee039SDag-Erling Smørgrav 	u_int flags;
329511b41d2SMark Murray } keywords[] = {
330989dd127SDag-Erling Smørgrav 	/* Portable-specific options */
331cf2b5f3bSDag-Erling Smørgrav #ifdef USE_PAM
332333ee039SDag-Erling Smørgrav 	{ "usepam", sUsePAM, SSHCFG_GLOBAL },
333cf2b5f3bSDag-Erling Smørgrav #else
334333ee039SDag-Erling Smørgrav 	{ "usepam", sUnsupported, SSHCFG_GLOBAL },
335975616f0SDag-Erling Smørgrav #endif
336333ee039SDag-Erling Smørgrav 	{ "pamauthenticationviakbdint", sDeprecated, SSHCFG_GLOBAL },
337989dd127SDag-Erling Smørgrav 	/* Standard Options */
338333ee039SDag-Erling Smørgrav 	{ "port", sPort, SSHCFG_GLOBAL },
339333ee039SDag-Erling Smørgrav 	{ "hostkey", sHostKeyFile, SSHCFG_GLOBAL },
340333ee039SDag-Erling Smørgrav 	{ "hostdsakey", sHostKeyFile, SSHCFG_GLOBAL },		/* alias */
341333ee039SDag-Erling Smørgrav 	{ "pidfile", sPidFile, SSHCFG_GLOBAL },
342333ee039SDag-Erling Smørgrav 	{ "serverkeybits", sServerKeyBits, SSHCFG_GLOBAL },
343333ee039SDag-Erling Smørgrav 	{ "logingracetime", sLoginGraceTime, SSHCFG_GLOBAL },
344333ee039SDag-Erling Smørgrav 	{ "keyregenerationinterval", sKeyRegenerationTime, SSHCFG_GLOBAL },
345d4af9e69SDag-Erling Smørgrav 	{ "permitrootlogin", sPermitRootLogin, SSHCFG_ALL },
346333ee039SDag-Erling Smørgrav 	{ "syslogfacility", sLogFacility, SSHCFG_GLOBAL },
347333ee039SDag-Erling Smørgrav 	{ "loglevel", sLogLevel, SSHCFG_GLOBAL },
348333ee039SDag-Erling Smørgrav 	{ "rhostsauthentication", sDeprecated, SSHCFG_GLOBAL },
349d4af9e69SDag-Erling Smørgrav 	{ "rhostsrsaauthentication", sRhostsRSAAuthentication, SSHCFG_ALL },
350d4af9e69SDag-Erling Smørgrav 	{ "hostbasedauthentication", sHostbasedAuthentication, SSHCFG_ALL },
351333ee039SDag-Erling Smørgrav 	{ "hostbasedusesnamefrompacketonly", sHostbasedUsesNameFromPacketOnly, SSHCFG_GLOBAL },
352d4af9e69SDag-Erling Smørgrav 	{ "rsaauthentication", sRSAAuthentication, SSHCFG_ALL },
353d4af9e69SDag-Erling Smørgrav 	{ "pubkeyauthentication", sPubkeyAuthentication, SSHCFG_ALL },
354333ee039SDag-Erling Smørgrav 	{ "dsaauthentication", sPubkeyAuthentication, SSHCFG_GLOBAL }, /* alias */
355cf2b5f3bSDag-Erling Smørgrav #ifdef KRB5
356d4af9e69SDag-Erling Smørgrav 	{ "kerberosauthentication", sKerberosAuthentication, SSHCFG_ALL },
357333ee039SDag-Erling Smørgrav 	{ "kerberosorlocalpasswd", sKerberosOrLocalPasswd, SSHCFG_GLOBAL },
358333ee039SDag-Erling Smørgrav 	{ "kerberosticketcleanup", sKerberosTicketCleanup, SSHCFG_GLOBAL },
3591ec0d754SDag-Erling Smørgrav #ifdef USE_AFS
360333ee039SDag-Erling Smørgrav 	{ "kerberosgetafstoken", sKerberosGetAFSToken, SSHCFG_GLOBAL },
3611ec0d754SDag-Erling Smørgrav #else
362333ee039SDag-Erling Smørgrav 	{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
3631ec0d754SDag-Erling Smørgrav #endif
364cf2b5f3bSDag-Erling Smørgrav #else
365d4af9e69SDag-Erling Smørgrav 	{ "kerberosauthentication", sUnsupported, SSHCFG_ALL },
366333ee039SDag-Erling Smørgrav 	{ "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL },
367333ee039SDag-Erling Smørgrav 	{ "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL },
368333ee039SDag-Erling Smørgrav 	{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
369cb96ab36SAssar Westerlund #endif
370333ee039SDag-Erling Smørgrav 	{ "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL },
371333ee039SDag-Erling Smørgrav 	{ "afstokenpassing", sUnsupported, SSHCFG_GLOBAL },
372cf2b5f3bSDag-Erling Smørgrav #ifdef GSSAPI
373d4af9e69SDag-Erling Smørgrav 	{ "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
374333ee039SDag-Erling Smørgrav 	{ "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
375cf2b5f3bSDag-Erling Smørgrav #else
376d4af9e69SDag-Erling Smørgrav 	{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },
377333ee039SDag-Erling Smørgrav 	{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
378511b41d2SMark Murray #endif
379d4af9e69SDag-Erling Smørgrav 	{ "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
380d4af9e69SDag-Erling Smørgrav 	{ "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
381333ee039SDag-Erling Smørgrav 	{ "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
382333ee039SDag-Erling Smørgrav 	{ "skeyauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, /* alias */
383cce7d346SDag-Erling Smørgrav #ifdef JPAKE
384cce7d346SDag-Erling Smørgrav 	{ "zeroknowledgepasswordauthentication", sZeroKnowledgePasswordAuthentication, SSHCFG_ALL },
385cce7d346SDag-Erling Smørgrav #else
386cce7d346SDag-Erling Smørgrav 	{ "zeroknowledgepasswordauthentication", sUnsupported, SSHCFG_ALL },
387cce7d346SDag-Erling Smørgrav #endif
388333ee039SDag-Erling Smørgrav 	{ "checkmail", sDeprecated, SSHCFG_GLOBAL },
389333ee039SDag-Erling Smørgrav 	{ "listenaddress", sListenAddress, SSHCFG_GLOBAL },
390333ee039SDag-Erling Smørgrav 	{ "addressfamily", sAddressFamily, SSHCFG_GLOBAL },
391333ee039SDag-Erling Smørgrav 	{ "printmotd", sPrintMotd, SSHCFG_GLOBAL },
392333ee039SDag-Erling Smørgrav 	{ "printlastlog", sPrintLastLog, SSHCFG_GLOBAL },
393333ee039SDag-Erling Smørgrav 	{ "ignorerhosts", sIgnoreRhosts, SSHCFG_GLOBAL },
394333ee039SDag-Erling Smørgrav 	{ "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL },
395333ee039SDag-Erling Smørgrav 	{ "x11forwarding", sX11Forwarding, SSHCFG_ALL },
396333ee039SDag-Erling Smørgrav 	{ "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL },
397333ee039SDag-Erling Smørgrav 	{ "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
398333ee039SDag-Erling Smørgrav 	{ "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
399333ee039SDag-Erling Smørgrav 	{ "strictmodes", sStrictModes, SSHCFG_GLOBAL },
400cce7d346SDag-Erling Smørgrav 	{ "permitemptypasswords", sEmptyPasswd, SSHCFG_ALL },
401333ee039SDag-Erling Smørgrav 	{ "permituserenvironment", sPermitUserEnvironment, SSHCFG_GLOBAL },
402333ee039SDag-Erling Smørgrav 	{ "uselogin", sUseLogin, SSHCFG_GLOBAL },
403333ee039SDag-Erling Smørgrav 	{ "compression", sCompression, SSHCFG_GLOBAL },
404333ee039SDag-Erling Smørgrav 	{ "tcpkeepalive", sTCPKeepAlive, SSHCFG_GLOBAL },
405333ee039SDag-Erling Smørgrav 	{ "keepalive", sTCPKeepAlive, SSHCFG_GLOBAL },	/* obsolete alias */
406333ee039SDag-Erling Smørgrav 	{ "allowtcpforwarding", sAllowTcpForwarding, SSHCFG_ALL },
407d4af9e69SDag-Erling Smørgrav 	{ "allowagentforwarding", sAllowAgentForwarding, SSHCFG_ALL },
408333ee039SDag-Erling Smørgrav 	{ "allowusers", sAllowUsers, SSHCFG_GLOBAL },
409333ee039SDag-Erling Smørgrav 	{ "denyusers", sDenyUsers, SSHCFG_GLOBAL },
410333ee039SDag-Erling Smørgrav 	{ "allowgroups", sAllowGroups, SSHCFG_GLOBAL },
411333ee039SDag-Erling Smørgrav 	{ "denygroups", sDenyGroups, SSHCFG_GLOBAL },
412333ee039SDag-Erling Smørgrav 	{ "ciphers", sCiphers, SSHCFG_GLOBAL },
413333ee039SDag-Erling Smørgrav 	{ "macs", sMacs, SSHCFG_GLOBAL },
414333ee039SDag-Erling Smørgrav 	{ "protocol", sProtocol, SSHCFG_GLOBAL },
415333ee039SDag-Erling Smørgrav 	{ "gatewayports", sGatewayPorts, SSHCFG_ALL },
416333ee039SDag-Erling Smørgrav 	{ "subsystem", sSubsystem, SSHCFG_GLOBAL },
417333ee039SDag-Erling Smørgrav 	{ "maxstartups", sMaxStartups, SSHCFG_GLOBAL },
418d4af9e69SDag-Erling Smørgrav 	{ "maxauthtries", sMaxAuthTries, SSHCFG_ALL },
419d4af9e69SDag-Erling Smørgrav 	{ "maxsessions", sMaxSessions, SSHCFG_ALL },
420d4af9e69SDag-Erling Smørgrav 	{ "banner", sBanner, SSHCFG_ALL },
421333ee039SDag-Erling Smørgrav 	{ "usedns", sUseDNS, SSHCFG_GLOBAL },
422333ee039SDag-Erling Smørgrav 	{ "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL },
423333ee039SDag-Erling Smørgrav 	{ "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL },
424333ee039SDag-Erling Smørgrav 	{ "clientaliveinterval", sClientAliveInterval, SSHCFG_GLOBAL },
425333ee039SDag-Erling Smørgrav 	{ "clientalivecountmax", sClientAliveCountMax, SSHCFG_GLOBAL },
426333ee039SDag-Erling Smørgrav 	{ "authorizedkeysfile", sAuthorizedKeysFile, SSHCFG_GLOBAL },
427333ee039SDag-Erling Smørgrav 	{ "authorizedkeysfile2", sAuthorizedKeysFile2, SSHCFG_GLOBAL },
428333ee039SDag-Erling Smørgrav 	{ "useprivilegeseparation", sUsePrivilegeSeparation, SSHCFG_GLOBAL},
429333ee039SDag-Erling Smørgrav 	{ "acceptenv", sAcceptEnv, SSHCFG_GLOBAL },
430333ee039SDag-Erling Smørgrav 	{ "permittunnel", sPermitTunnel, SSHCFG_GLOBAL },
431333ee039SDag-Erling Smørgrav 	{ "match", sMatch, SSHCFG_ALL },
432333ee039SDag-Erling Smørgrav 	{ "permitopen", sPermitOpen, SSHCFG_ALL },
433333ee039SDag-Erling Smørgrav 	{ "forcecommand", sForceCommand, SSHCFG_ALL },
434d4af9e69SDag-Erling Smørgrav 	{ "chrootdirectory", sChrootDirectory, SSHCFG_ALL },
435b15c8340SDag-Erling Smørgrav 	{ "hostcertificate", sHostCertificate, SSHCFG_GLOBAL },
436b15c8340SDag-Erling Smørgrav 	{ "revokedkeys", sRevokedKeys, SSHCFG_ALL },
437b15c8340SDag-Erling Smørgrav 	{ "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL },
438333ee039SDag-Erling Smørgrav 	{ "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
439333ee039SDag-Erling Smørgrav 	{ NULL, sBadOption, 0 }
440511b41d2SMark Murray };
441511b41d2SMark Murray 
442d4af9e69SDag-Erling Smørgrav static struct {
443d4af9e69SDag-Erling Smørgrav 	int val;
444d4af9e69SDag-Erling Smørgrav 	char *text;
445d4af9e69SDag-Erling Smørgrav } tunmode_desc[] = {
446d4af9e69SDag-Erling Smørgrav 	{ SSH_TUNMODE_NO, "no" },
447d4af9e69SDag-Erling Smørgrav 	{ SSH_TUNMODE_POINTOPOINT, "point-to-point" },
448d4af9e69SDag-Erling Smørgrav 	{ SSH_TUNMODE_ETHERNET, "ethernet" },
449d4af9e69SDag-Erling Smørgrav 	{ SSH_TUNMODE_YES, "yes" },
450d4af9e69SDag-Erling Smørgrav 	{ -1, NULL }
451d4af9e69SDag-Erling Smørgrav };
452d4af9e69SDag-Erling Smørgrav 
453511b41d2SMark Murray /*
454ca3176e7SBrian Feldman  * Returns the number of the token pointed to by cp or sBadOption.
455511b41d2SMark Murray  */
456511b41d2SMark Murray 
457511b41d2SMark Murray static ServerOpCodes
458511b41d2SMark Murray parse_token(const char *cp, const char *filename,
459333ee039SDag-Erling Smørgrav 	    int linenum, u_int *flags)
460511b41d2SMark Murray {
461ca3176e7SBrian Feldman 	u_int i;
462511b41d2SMark Murray 
463511b41d2SMark Murray 	for (i = 0; keywords[i].name; i++)
464333ee039SDag-Erling Smørgrav 		if (strcasecmp(cp, keywords[i].name) == 0) {
465333ee039SDag-Erling Smørgrav 			*flags = keywords[i].flags;
466511b41d2SMark Murray 			return keywords[i].opcode;
467333ee039SDag-Erling Smørgrav 		}
468511b41d2SMark Murray 
469ca3176e7SBrian Feldman 	error("%s: line %d: Bad configuration option: %s",
470511b41d2SMark Murray 	    filename, linenum, cp);
471511b41d2SMark Murray 	return sBadOption;
472511b41d2SMark Murray }
473511b41d2SMark Murray 
474b15c8340SDag-Erling Smørgrav char *
475b15c8340SDag-Erling Smørgrav derelativise_path(const char *path)
476b15c8340SDag-Erling Smørgrav {
477b15c8340SDag-Erling Smørgrav 	char *expanded, *ret, *cwd;
478b15c8340SDag-Erling Smørgrav 
479b15c8340SDag-Erling Smørgrav 	expanded = tilde_expand_filename(path, getuid());
480b15c8340SDag-Erling Smørgrav 	if (*expanded == '/')
481b15c8340SDag-Erling Smørgrav 		return expanded;
482b15c8340SDag-Erling Smørgrav 	if ((cwd = getcwd(NULL, 0)) == NULL)
483b15c8340SDag-Erling Smørgrav 		fatal("%s: getcwd: %s", __func__, strerror(errno));
484b15c8340SDag-Erling Smørgrav 	xasprintf(&ret, "%s/%s", cwd, expanded);
485b15c8340SDag-Erling Smørgrav 	xfree(cwd);
486b15c8340SDag-Erling Smørgrav 	xfree(expanded);
487b15c8340SDag-Erling Smørgrav 	return ret;
488b15c8340SDag-Erling Smørgrav }
489b15c8340SDag-Erling Smørgrav 
490af12a3e7SDag-Erling Smørgrav static void
491cce7d346SDag-Erling Smørgrav add_listen_addr(ServerOptions *options, char *addr, int port)
492511b41d2SMark Murray {
493d4ecd108SDag-Erling Smørgrav 	u_int i;
494511b41d2SMark Murray 
495511b41d2SMark Murray 	if (options->num_ports == 0)
496511b41d2SMark Murray 		options->ports[options->num_ports++] = SSH_DEFAULT_PORT;
497aa49c926SDag-Erling Smørgrav 	if (options->address_family == -1)
498aa49c926SDag-Erling Smørgrav 		options->address_family = AF_UNSPEC;
499ca3176e7SBrian Feldman 	if (port == 0)
500ca3176e7SBrian Feldman 		for (i = 0; i < options->num_ports; i++)
501ca3176e7SBrian Feldman 			add_one_listen_addr(options, addr, options->ports[i]);
502ca3176e7SBrian Feldman 	else
503ca3176e7SBrian Feldman 		add_one_listen_addr(options, addr, port);
504ca3176e7SBrian Feldman }
505ca3176e7SBrian Feldman 
506af12a3e7SDag-Erling Smørgrav static void
507cce7d346SDag-Erling Smørgrav add_one_listen_addr(ServerOptions *options, char *addr, int port)
508ca3176e7SBrian Feldman {
509ca3176e7SBrian Feldman 	struct addrinfo hints, *ai, *aitop;
510ca3176e7SBrian Feldman 	char strport[NI_MAXSERV];
511ca3176e7SBrian Feldman 	int gaierr;
512ca3176e7SBrian Feldman 
513511b41d2SMark Murray 	memset(&hints, 0, sizeof(hints));
514aa49c926SDag-Erling Smørgrav 	hints.ai_family = options->address_family;
515511b41d2SMark Murray 	hints.ai_socktype = SOCK_STREAM;
516511b41d2SMark Murray 	hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0;
517cce7d346SDag-Erling Smørgrav 	snprintf(strport, sizeof strport, "%d", port);
518511b41d2SMark Murray 	if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0)
519ca3176e7SBrian Feldman 		fatal("bad addr or host: %s (%s)",
520511b41d2SMark Murray 		    addr ? addr : "<NULL>",
521d4af9e69SDag-Erling Smørgrav 		    ssh_gai_strerror(gaierr));
522511b41d2SMark Murray 	for (ai = aitop; ai->ai_next; ai = ai->ai_next)
523511b41d2SMark Murray 		;
524511b41d2SMark Murray 	ai->ai_next = options->listen_addrs;
525511b41d2SMark Murray 	options->listen_addrs = aitop;
526511b41d2SMark Murray }
527511b41d2SMark Murray 
528333ee039SDag-Erling Smørgrav /*
529333ee039SDag-Erling Smørgrav  * The strategy for the Match blocks is that the config file is parsed twice.
530333ee039SDag-Erling Smørgrav  *
531333ee039SDag-Erling Smørgrav  * The first time is at startup.  activep is initialized to 1 and the
532333ee039SDag-Erling Smørgrav  * directives in the global context are processed and acted on.  Hitting a
533333ee039SDag-Erling Smørgrav  * Match directive unsets activep and the directives inside the block are
534333ee039SDag-Erling Smørgrav  * checked for syntax only.
535333ee039SDag-Erling Smørgrav  *
536333ee039SDag-Erling Smørgrav  * The second time is after a connection has been established but before
537333ee039SDag-Erling Smørgrav  * authentication.  activep is initialized to 2 and global config directives
538333ee039SDag-Erling Smørgrav  * are ignored since they have already been processed.  If the criteria in a
539333ee039SDag-Erling Smørgrav  * Match block is met, activep is set and the subsequent directives
540333ee039SDag-Erling Smørgrav  * processed and actioned until EOF or another Match block unsets it.  Any
541333ee039SDag-Erling Smørgrav  * options set are copied into the main server config.
542333ee039SDag-Erling Smørgrav  *
543333ee039SDag-Erling Smørgrav  * Potential additions/improvements:
544333ee039SDag-Erling Smørgrav  *  - Add Match support for pre-kex directives, eg Protocol, Ciphers.
545333ee039SDag-Erling Smørgrav  *
546333ee039SDag-Erling Smørgrav  *  - Add a Tag directive (idea from David Leonard) ala pf, eg:
547333ee039SDag-Erling Smørgrav  *	Match Address 192.168.0.*
548333ee039SDag-Erling Smørgrav  *		Tag trusted
549333ee039SDag-Erling Smørgrav  *	Match Group wheel
550333ee039SDag-Erling Smørgrav  *		Tag trusted
551333ee039SDag-Erling Smørgrav  *	Match Tag trusted
552333ee039SDag-Erling Smørgrav  *		AllowTcpForwarding yes
553333ee039SDag-Erling Smørgrav  *		GatewayPorts clientspecified
554333ee039SDag-Erling Smørgrav  *		[...]
555333ee039SDag-Erling Smørgrav  *
556333ee039SDag-Erling Smørgrav  *  - Add a PermittedChannelRequests directive
557333ee039SDag-Erling Smørgrav  *	Match Group shell
558333ee039SDag-Erling Smørgrav  *		PermittedChannelRequests session,forwarded-tcpip
559333ee039SDag-Erling Smørgrav  */
560333ee039SDag-Erling Smørgrav 
561333ee039SDag-Erling Smørgrav static int
562333ee039SDag-Erling Smørgrav match_cfg_line_group(const char *grps, int line, const char *user)
563333ee039SDag-Erling Smørgrav {
564333ee039SDag-Erling Smørgrav 	int result = 0;
565333ee039SDag-Erling Smørgrav 	struct passwd *pw;
566333ee039SDag-Erling Smørgrav 
567333ee039SDag-Erling Smørgrav 	if (user == NULL)
568333ee039SDag-Erling Smørgrav 		goto out;
569333ee039SDag-Erling Smørgrav 
570333ee039SDag-Erling Smørgrav 	if ((pw = getpwnam(user)) == NULL) {
571333ee039SDag-Erling Smørgrav 		debug("Can't match group at line %d because user %.100s does "
572333ee039SDag-Erling Smørgrav 		    "not exist", line, user);
573333ee039SDag-Erling Smørgrav 	} else if (ga_init(pw->pw_name, pw->pw_gid) == 0) {
574333ee039SDag-Erling Smørgrav 		debug("Can't Match group because user %.100s not in any group "
575333ee039SDag-Erling Smørgrav 		    "at line %d", user, line);
576d4af9e69SDag-Erling Smørgrav 	} else if (ga_match_pattern_list(grps) != 1) {
577d4af9e69SDag-Erling Smørgrav 		debug("user %.100s does not match group list %.100s at line %d",
578d4af9e69SDag-Erling Smørgrav 		    user, grps, line);
579333ee039SDag-Erling Smørgrav 	} else {
580d4af9e69SDag-Erling Smørgrav 		debug("user %.100s matched group list %.100s at line %d", user,
581d4af9e69SDag-Erling Smørgrav 		    grps, line);
582333ee039SDag-Erling Smørgrav 		result = 1;
583333ee039SDag-Erling Smørgrav 	}
584333ee039SDag-Erling Smørgrav out:
585333ee039SDag-Erling Smørgrav 	ga_free();
586333ee039SDag-Erling Smørgrav 	return result;
587333ee039SDag-Erling Smørgrav }
588333ee039SDag-Erling Smørgrav 
589333ee039SDag-Erling Smørgrav static int
590333ee039SDag-Erling Smørgrav match_cfg_line(char **condition, int line, const char *user, const char *host,
591333ee039SDag-Erling Smørgrav     const char *address)
592333ee039SDag-Erling Smørgrav {
593333ee039SDag-Erling Smørgrav 	int result = 1;
594333ee039SDag-Erling Smørgrav 	char *arg, *attrib, *cp = *condition;
595333ee039SDag-Erling Smørgrav 	size_t len;
596333ee039SDag-Erling Smørgrav 
597333ee039SDag-Erling Smørgrav 	if (user == NULL)
598333ee039SDag-Erling Smørgrav 		debug3("checking syntax for 'Match %s'", cp);
599333ee039SDag-Erling Smørgrav 	else
600333ee039SDag-Erling Smørgrav 		debug3("checking match for '%s' user %s host %s addr %s", cp,
601333ee039SDag-Erling Smørgrav 		    user ? user : "(null)", host ? host : "(null)",
602333ee039SDag-Erling Smørgrav 		    address ? address : "(null)");
603333ee039SDag-Erling Smørgrav 
604333ee039SDag-Erling Smørgrav 	while ((attrib = strdelim(&cp)) && *attrib != '\0') {
605333ee039SDag-Erling Smørgrav 		if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
606333ee039SDag-Erling Smørgrav 			error("Missing Match criteria for %s", attrib);
607333ee039SDag-Erling Smørgrav 			return -1;
608333ee039SDag-Erling Smørgrav 		}
609333ee039SDag-Erling Smørgrav 		len = strlen(arg);
610333ee039SDag-Erling Smørgrav 		if (strcasecmp(attrib, "user") == 0) {
611333ee039SDag-Erling Smørgrav 			if (!user) {
612333ee039SDag-Erling Smørgrav 				result = 0;
613333ee039SDag-Erling Smørgrav 				continue;
614333ee039SDag-Erling Smørgrav 			}
615333ee039SDag-Erling Smørgrav 			if (match_pattern_list(user, arg, len, 0) != 1)
616333ee039SDag-Erling Smørgrav 				result = 0;
617333ee039SDag-Erling Smørgrav 			else
618333ee039SDag-Erling Smørgrav 				debug("user %.100s matched 'User %.100s' at "
619333ee039SDag-Erling Smørgrav 				    "line %d", user, arg, line);
620333ee039SDag-Erling Smørgrav 		} else if (strcasecmp(attrib, "group") == 0) {
621333ee039SDag-Erling Smørgrav 			switch (match_cfg_line_group(arg, line, user)) {
622333ee039SDag-Erling Smørgrav 			case -1:
623333ee039SDag-Erling Smørgrav 				return -1;
624333ee039SDag-Erling Smørgrav 			case 0:
625333ee039SDag-Erling Smørgrav 				result = 0;
626333ee039SDag-Erling Smørgrav 			}
627333ee039SDag-Erling Smørgrav 		} else if (strcasecmp(attrib, "host") == 0) {
628333ee039SDag-Erling Smørgrav 			if (!host) {
629333ee039SDag-Erling Smørgrav 				result = 0;
630333ee039SDag-Erling Smørgrav 				continue;
631333ee039SDag-Erling Smørgrav 			}
632333ee039SDag-Erling Smørgrav 			if (match_hostname(host, arg, len) != 1)
633333ee039SDag-Erling Smørgrav 				result = 0;
634333ee039SDag-Erling Smørgrav 			else
635333ee039SDag-Erling Smørgrav 				debug("connection from %.100s matched 'Host "
636333ee039SDag-Erling Smørgrav 				    "%.100s' at line %d", host, arg, line);
637333ee039SDag-Erling Smørgrav 		} else if (strcasecmp(attrib, "address") == 0) {
638d4af9e69SDag-Erling Smørgrav 			switch (addr_match_list(address, arg)) {
639d4af9e69SDag-Erling Smørgrav 			case 1:
640333ee039SDag-Erling Smørgrav 				debug("connection from %.100s matched 'Address "
641333ee039SDag-Erling Smørgrav 				    "%.100s' at line %d", address, arg, line);
642d4af9e69SDag-Erling Smørgrav 				break;
643d4af9e69SDag-Erling Smørgrav 			case 0:
644d4af9e69SDag-Erling Smørgrav 			case -1:
645d4af9e69SDag-Erling Smørgrav 				result = 0;
646d4af9e69SDag-Erling Smørgrav 				break;
647d4af9e69SDag-Erling Smørgrav 			case -2:
648d4af9e69SDag-Erling Smørgrav 				return -1;
649d4af9e69SDag-Erling Smørgrav 			}
650333ee039SDag-Erling Smørgrav 		} else {
651333ee039SDag-Erling Smørgrav 			error("Unsupported Match attribute %s", attrib);
652333ee039SDag-Erling Smørgrav 			return -1;
653333ee039SDag-Erling Smørgrav 		}
654333ee039SDag-Erling Smørgrav 	}
655333ee039SDag-Erling Smørgrav 	if (user != NULL)
656333ee039SDag-Erling Smørgrav 		debug3("match %sfound", result ? "" : "not ");
657333ee039SDag-Erling Smørgrav 	*condition = cp;
658333ee039SDag-Erling Smørgrav 	return result;
659333ee039SDag-Erling Smørgrav }
660333ee039SDag-Erling Smørgrav 
661333ee039SDag-Erling Smørgrav #define WHITESPACE " \t\r\n"
662333ee039SDag-Erling Smørgrav 
663af12a3e7SDag-Erling Smørgrav int
664af12a3e7SDag-Erling Smørgrav process_server_config_line(ServerOptions *options, char *line,
665333ee039SDag-Erling Smørgrav     const char *filename, int linenum, int *activep, const char *user,
666333ee039SDag-Erling Smørgrav     const char *host, const char *address)
667511b41d2SMark Murray {
668ca3176e7SBrian Feldman 	char *cp, **charptr, *arg, *p;
669333ee039SDag-Erling Smørgrav 	int cmdline = 0, *intptr, value, n;
670d4af9e69SDag-Erling Smørgrav 	SyslogFacility *log_facility_ptr;
671d4af9e69SDag-Erling Smørgrav 	LogLevel *log_level_ptr;
672511b41d2SMark Murray 	ServerOpCodes opcode;
673cce7d346SDag-Erling Smørgrav 	int port;
674333ee039SDag-Erling Smørgrav 	u_int i, flags = 0;
675333ee039SDag-Erling Smørgrav 	size_t len;
676511b41d2SMark Murray 
677c2d3a559SKris Kennaway 	cp = line;
678333ee039SDag-Erling Smørgrav 	if ((arg = strdelim(&cp)) == NULL)
679333ee039SDag-Erling Smørgrav 		return 0;
680c2d3a559SKris Kennaway 	/* Ignore leading whitespace */
681c2d3a559SKris Kennaway 	if (*arg == '\0')
682c2d3a559SKris Kennaway 		arg = strdelim(&cp);
683ca3176e7SBrian Feldman 	if (!arg || !*arg || *arg == '#')
684af12a3e7SDag-Erling Smørgrav 		return 0;
685ca3176e7SBrian Feldman 	intptr = NULL;
686ca3176e7SBrian Feldman 	charptr = NULL;
687333ee039SDag-Erling Smørgrav 	opcode = parse_token(arg, filename, linenum, &flags);
688333ee039SDag-Erling Smørgrav 
689333ee039SDag-Erling Smørgrav 	if (activep == NULL) { /* We are processing a command line directive */
690333ee039SDag-Erling Smørgrav 		cmdline = 1;
691333ee039SDag-Erling Smørgrav 		activep = &cmdline;
692333ee039SDag-Erling Smørgrav 	}
693333ee039SDag-Erling Smørgrav 	if (*activep && opcode != sMatch)
694333ee039SDag-Erling Smørgrav 		debug3("%s:%d setting %s %s", filename, linenum, arg, cp);
695333ee039SDag-Erling Smørgrav 	if (*activep == 0 && !(flags & SSHCFG_MATCH)) {
696333ee039SDag-Erling Smørgrav 		if (user == NULL) {
697333ee039SDag-Erling Smørgrav 			fatal("%s line %d: Directive '%s' is not allowed "
698333ee039SDag-Erling Smørgrav 			    "within a Match block", filename, linenum, arg);
699333ee039SDag-Erling Smørgrav 		} else { /* this is a directive we have already processed */
700333ee039SDag-Erling Smørgrav 			while (arg)
701333ee039SDag-Erling Smørgrav 				arg = strdelim(&cp);
702333ee039SDag-Erling Smørgrav 			return 0;
703333ee039SDag-Erling Smørgrav 		}
704333ee039SDag-Erling Smørgrav 	}
705333ee039SDag-Erling Smørgrav 
706511b41d2SMark Murray 	switch (opcode) {
707989dd127SDag-Erling Smørgrav 	/* Portable-specific options */
708cf2b5f3bSDag-Erling Smørgrav 	case sUsePAM:
709cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->use_pam;
710989dd127SDag-Erling Smørgrav 		goto parse_flag;
711989dd127SDag-Erling Smørgrav 
712989dd127SDag-Erling Smørgrav 	/* Standard Options */
713511b41d2SMark Murray 	case sBadOption:
714af12a3e7SDag-Erling Smørgrav 		return -1;
715511b41d2SMark Murray 	case sPort:
716511b41d2SMark Murray 		/* ignore ports from configfile if cmdline specifies ports */
717511b41d2SMark Murray 		if (options->ports_from_cmdline)
718af12a3e7SDag-Erling Smørgrav 			return 0;
719511b41d2SMark Murray 		if (options->listen_addrs != NULL)
720511b41d2SMark Murray 			fatal("%s line %d: ports must be specified before "
721af12a3e7SDag-Erling Smørgrav 			    "ListenAddress.", filename, linenum);
722511b41d2SMark Murray 		if (options->num_ports >= MAX_PORTS)
723ca3176e7SBrian Feldman 			fatal("%s line %d: too many ports.",
724511b41d2SMark Murray 			    filename, linenum);
725c2d3a559SKris Kennaway 		arg = strdelim(&cp);
726c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
727ca3176e7SBrian Feldman 			fatal("%s line %d: missing port number.",
728511b41d2SMark Murray 			    filename, linenum);
729ca3176e7SBrian Feldman 		options->ports[options->num_ports++] = a2port(arg);
730cce7d346SDag-Erling Smørgrav 		if (options->ports[options->num_ports-1] <= 0)
731ca3176e7SBrian Feldman 			fatal("%s line %d: Badly formatted port number.",
732ca3176e7SBrian Feldman 			    filename, linenum);
733511b41d2SMark Murray 		break;
734511b41d2SMark Murray 
735511b41d2SMark Murray 	case sServerKeyBits:
736511b41d2SMark Murray 		intptr = &options->server_key_bits;
737511b41d2SMark Murray  parse_int:
738c2d3a559SKris Kennaway 		arg = strdelim(&cp);
739ca3176e7SBrian Feldman 		if (!arg || *arg == '\0')
740ca3176e7SBrian Feldman 			fatal("%s line %d: missing integer value.",
741511b41d2SMark Murray 			    filename, linenum);
742c2d3a559SKris Kennaway 		value = atoi(arg);
743333ee039SDag-Erling Smørgrav 		if (*activep && *intptr == -1)
744511b41d2SMark Murray 			*intptr = value;
745511b41d2SMark Murray 		break;
746511b41d2SMark Murray 
747511b41d2SMark Murray 	case sLoginGraceTime:
748511b41d2SMark Murray 		intptr = &options->login_grace_time;
749af12a3e7SDag-Erling Smørgrav  parse_time:
750af12a3e7SDag-Erling Smørgrav 		arg = strdelim(&cp);
751af12a3e7SDag-Erling Smørgrav 		if (!arg || *arg == '\0')
752af12a3e7SDag-Erling Smørgrav 			fatal("%s line %d: missing time value.",
753af12a3e7SDag-Erling Smørgrav 			    filename, linenum);
754af12a3e7SDag-Erling Smørgrav 		if ((value = convtime(arg)) == -1)
755af12a3e7SDag-Erling Smørgrav 			fatal("%s line %d: invalid time value.",
756af12a3e7SDag-Erling Smørgrav 			    filename, linenum);
757af12a3e7SDag-Erling Smørgrav 		if (*intptr == -1)
758af12a3e7SDag-Erling Smørgrav 			*intptr = value;
759af12a3e7SDag-Erling Smørgrav 		break;
760511b41d2SMark Murray 
761511b41d2SMark Murray 	case sKeyRegenerationTime:
762511b41d2SMark Murray 		intptr = &options->key_regeneration_time;
763af12a3e7SDag-Erling Smørgrav 		goto parse_time;
764511b41d2SMark Murray 
765511b41d2SMark Murray 	case sListenAddress:
766c2d3a559SKris Kennaway 		arg = strdelim(&cp);
767aa49c926SDag-Erling Smørgrav 		if (arg == NULL || *arg == '\0')
768aa49c926SDag-Erling Smørgrav 			fatal("%s line %d: missing address",
769511b41d2SMark Murray 			    filename, linenum);
770d4ecd108SDag-Erling Smørgrav 		/* check for bare IPv6 address: no "[]" and 2 or more ":" */
771d4ecd108SDag-Erling Smørgrav 		if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL
772d4ecd108SDag-Erling Smørgrav 		    && strchr(p+1, ':') != NULL) {
773d4ecd108SDag-Erling Smørgrav 			add_listen_addr(options, arg, 0);
774d4ecd108SDag-Erling Smørgrav 			break;
775d4ecd108SDag-Erling Smørgrav 		}
776aa49c926SDag-Erling Smørgrav 		p = hpdelim(&arg);
777aa49c926SDag-Erling Smørgrav 		if (p == NULL)
778aa49c926SDag-Erling Smørgrav 			fatal("%s line %d: bad address:port usage",
779ca3176e7SBrian Feldman 			    filename, linenum);
780aa49c926SDag-Erling Smørgrav 		p = cleanhostname(p);
781aa49c926SDag-Erling Smørgrav 		if (arg == NULL)
782aa49c926SDag-Erling Smørgrav 			port = 0;
783cce7d346SDag-Erling Smørgrav 		else if ((port = a2port(arg)) <= 0)
784aa49c926SDag-Erling Smørgrav 			fatal("%s line %d: bad port number", filename, linenum);
785ca3176e7SBrian Feldman 
786aa49c926SDag-Erling Smørgrav 		add_listen_addr(options, p, port);
787aa49c926SDag-Erling Smørgrav 
788aa49c926SDag-Erling Smørgrav 		break;
789aa49c926SDag-Erling Smørgrav 
790aa49c926SDag-Erling Smørgrav 	case sAddressFamily:
791aa49c926SDag-Erling Smørgrav 		arg = strdelim(&cp);
792d4ecd108SDag-Erling Smørgrav 		if (!arg || *arg == '\0')
793d4ecd108SDag-Erling Smørgrav 			fatal("%s line %d: missing address family.",
794d4ecd108SDag-Erling Smørgrav 			    filename, linenum);
795aa49c926SDag-Erling Smørgrav 		intptr = &options->address_family;
796aa49c926SDag-Erling Smørgrav 		if (options->listen_addrs != NULL)
797aa49c926SDag-Erling Smørgrav 			fatal("%s line %d: address family must be specified before "
798aa49c926SDag-Erling Smørgrav 			    "ListenAddress.", filename, linenum);
799aa49c926SDag-Erling Smørgrav 		if (strcasecmp(arg, "inet") == 0)
800aa49c926SDag-Erling Smørgrav 			value = AF_INET;
801aa49c926SDag-Erling Smørgrav 		else if (strcasecmp(arg, "inet6") == 0)
802aa49c926SDag-Erling Smørgrav 			value = AF_INET6;
803aa49c926SDag-Erling Smørgrav 		else if (strcasecmp(arg, "any") == 0)
804aa49c926SDag-Erling Smørgrav 			value = AF_UNSPEC;
805ca3176e7SBrian Feldman 		else
806aa49c926SDag-Erling Smørgrav 			fatal("%s line %d: unsupported address family \"%s\".",
807aa49c926SDag-Erling Smørgrav 			    filename, linenum, arg);
808aa49c926SDag-Erling Smørgrav 		if (*intptr == -1)
809aa49c926SDag-Erling Smørgrav 			*intptr = value;
810511b41d2SMark Murray 		break;
811511b41d2SMark Murray 
812511b41d2SMark Murray 	case sHostKeyFile:
813ca3176e7SBrian Feldman 		intptr = &options->num_host_key_files;
814ca3176e7SBrian Feldman 		if (*intptr >= MAX_HOSTKEYS)
815ca3176e7SBrian Feldman 			fatal("%s line %d: too many host keys specified (max %d).",
816ca3176e7SBrian Feldman 			    filename, linenum, MAX_HOSTKEYS);
817ca3176e7SBrian Feldman 		charptr = &options->host_key_files[*intptr];
818c2d3a559SKris Kennaway  parse_filename:
819c2d3a559SKris Kennaway 		arg = strdelim(&cp);
820ca3176e7SBrian Feldman 		if (!arg || *arg == '\0')
821ca3176e7SBrian Feldman 			fatal("%s line %d: missing file name.",
822e8aafc91SKris Kennaway 			    filename, linenum);
823333ee039SDag-Erling Smørgrav 		if (*activep && *charptr == NULL) {
824b15c8340SDag-Erling Smørgrav 			*charptr = derelativise_path(arg);
825ca3176e7SBrian Feldman 			/* increase optional counter */
826ca3176e7SBrian Feldman 			if (intptr != NULL)
827ca3176e7SBrian Feldman 				*intptr = *intptr + 1;
828ca3176e7SBrian Feldman 		}
829e8aafc91SKris Kennaway 		break;
830e8aafc91SKris Kennaway 
831b15c8340SDag-Erling Smørgrav 	case sHostCertificate:
832b15c8340SDag-Erling Smørgrav 		intptr = &options->num_host_cert_files;
833b15c8340SDag-Erling Smørgrav 		if (*intptr >= MAX_HOSTKEYS)
834b15c8340SDag-Erling Smørgrav 			fatal("%s line %d: too many host certificates "
835b15c8340SDag-Erling Smørgrav 			    "specified (max %d).", filename, linenum,
836b15c8340SDag-Erling Smørgrav 			    MAX_HOSTCERTS);
837b15c8340SDag-Erling Smørgrav 		charptr = &options->host_cert_files[*intptr];
838b15c8340SDag-Erling Smørgrav 		goto parse_filename;
839b15c8340SDag-Erling Smørgrav 		break;
840b15c8340SDag-Erling Smørgrav 
841e8aafc91SKris Kennaway 	case sPidFile:
842e8aafc91SKris Kennaway 		charptr = &options->pid_file;
843c2d3a559SKris Kennaway 		goto parse_filename;
844511b41d2SMark Murray 
845511b41d2SMark Murray 	case sPermitRootLogin:
846511b41d2SMark Murray 		intptr = &options->permit_root_login;
847c2d3a559SKris Kennaway 		arg = strdelim(&cp);
848ca3176e7SBrian Feldman 		if (!arg || *arg == '\0')
849ca3176e7SBrian Feldman 			fatal("%s line %d: missing yes/"
850ca3176e7SBrian Feldman 			    "without-password/forced-commands-only/no "
851ca3176e7SBrian Feldman 			    "argument.", filename, linenum);
852ca3176e7SBrian Feldman 		value = 0;	/* silence compiler */
853c2d3a559SKris Kennaway 		if (strcmp(arg, "without-password") == 0)
854ca3176e7SBrian Feldman 			value = PERMIT_NO_PASSWD;
855ca3176e7SBrian Feldman 		else if (strcmp(arg, "forced-commands-only") == 0)
856ca3176e7SBrian Feldman 			value = PERMIT_FORCED_ONLY;
857c2d3a559SKris Kennaway 		else if (strcmp(arg, "yes") == 0)
858ca3176e7SBrian Feldman 			value = PERMIT_YES;
859c2d3a559SKris Kennaway 		else if (strcmp(arg, "no") == 0)
860ca3176e7SBrian Feldman 			value = PERMIT_NO;
861ca3176e7SBrian Feldman 		else
862ca3176e7SBrian Feldman 			fatal("%s line %d: Bad yes/"
863ca3176e7SBrian Feldman 			    "without-password/forced-commands-only/no "
864ca3176e7SBrian Feldman 			    "argument: %s", filename, linenum, arg);
865d4af9e69SDag-Erling Smørgrav 		if (*activep && *intptr == -1)
866511b41d2SMark Murray 			*intptr = value;
867511b41d2SMark Murray 		break;
868511b41d2SMark Murray 
869511b41d2SMark Murray 	case sIgnoreRhosts:
870511b41d2SMark Murray 		intptr = &options->ignore_rhosts;
871511b41d2SMark Murray  parse_flag:
872c2d3a559SKris Kennaway 		arg = strdelim(&cp);
873ca3176e7SBrian Feldman 		if (!arg || *arg == '\0')
874ca3176e7SBrian Feldman 			fatal("%s line %d: missing yes/no argument.",
875511b41d2SMark Murray 			    filename, linenum);
876ca3176e7SBrian Feldman 		value = 0;	/* silence compiler */
877c2d3a559SKris Kennaway 		if (strcmp(arg, "yes") == 0)
878511b41d2SMark Murray 			value = 1;
879c2d3a559SKris Kennaway 		else if (strcmp(arg, "no") == 0)
880511b41d2SMark Murray 			value = 0;
881ca3176e7SBrian Feldman 		else
882ca3176e7SBrian Feldman 			fatal("%s line %d: Bad yes/no argument: %s",
883c2d3a559SKris Kennaway 				filename, linenum, arg);
884333ee039SDag-Erling Smørgrav 		if (*activep && *intptr == -1)
885511b41d2SMark Murray 			*intptr = value;
886511b41d2SMark Murray 		break;
887511b41d2SMark Murray 
888511b41d2SMark Murray 	case sIgnoreUserKnownHosts:
889511b41d2SMark Murray 		intptr = &options->ignore_user_known_hosts;
890962a3f4eSSheldon Hearn 		goto parse_flag;
891511b41d2SMark Murray 
892511b41d2SMark Murray 	case sRhostsRSAAuthentication:
893511b41d2SMark Murray 		intptr = &options->rhosts_rsa_authentication;
894511b41d2SMark Murray 		goto parse_flag;
895511b41d2SMark Murray 
896ca3176e7SBrian Feldman 	case sHostbasedAuthentication:
897ca3176e7SBrian Feldman 		intptr = &options->hostbased_authentication;
898ca3176e7SBrian Feldman 		goto parse_flag;
899ca3176e7SBrian Feldman 
900ca3176e7SBrian Feldman 	case sHostbasedUsesNameFromPacketOnly:
901ca3176e7SBrian Feldman 		intptr = &options->hostbased_uses_name_from_packet_only;
902ca3176e7SBrian Feldman 		goto parse_flag;
903ca3176e7SBrian Feldman 
904511b41d2SMark Murray 	case sRSAAuthentication:
905511b41d2SMark Murray 		intptr = &options->rsa_authentication;
906511b41d2SMark Murray 		goto parse_flag;
907511b41d2SMark Murray 
908ca3176e7SBrian Feldman 	case sPubkeyAuthentication:
909ca3176e7SBrian Feldman 		intptr = &options->pubkey_authentication;
910e8aafc91SKris Kennaway 		goto parse_flag;
911cf2b5f3bSDag-Erling Smørgrav 
912cb96ab36SAssar Westerlund 	case sKerberosAuthentication:
913cb96ab36SAssar Westerlund 		intptr = &options->kerberos_authentication;
914511b41d2SMark Murray 		goto parse_flag;
915511b41d2SMark Murray 
916af12a3e7SDag-Erling Smørgrav 	case sKerberosOrLocalPasswd:
917af12a3e7SDag-Erling Smørgrav 		intptr = &options->kerberos_or_local_passwd;
918511b41d2SMark Murray 		goto parse_flag;
919511b41d2SMark Murray 
920af12a3e7SDag-Erling Smørgrav 	case sKerberosTicketCleanup:
921af12a3e7SDag-Erling Smørgrav 		intptr = &options->kerberos_ticket_cleanup;
922511b41d2SMark Murray 		goto parse_flag;
923cf2b5f3bSDag-Erling Smørgrav 
9241ec0d754SDag-Erling Smørgrav 	case sKerberosGetAFSToken:
9251ec0d754SDag-Erling Smørgrav 		intptr = &options->kerberos_get_afs_token;
9261ec0d754SDag-Erling Smørgrav 		goto parse_flag;
9271ec0d754SDag-Erling Smørgrav 
928cf2b5f3bSDag-Erling Smørgrav 	case sGssAuthentication:
929cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->gss_authentication;
930fe5fd017SMark Murray 		goto parse_flag;
931cf2b5f3bSDag-Erling Smørgrav 
932cf2b5f3bSDag-Erling Smørgrav 	case sGssCleanupCreds:
933cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->gss_cleanup_creds;
934511b41d2SMark Murray 		goto parse_flag;
935511b41d2SMark Murray 
936511b41d2SMark Murray 	case sPasswordAuthentication:
937511b41d2SMark Murray 		intptr = &options->password_authentication;
938511b41d2SMark Murray 		goto parse_flag;
939511b41d2SMark Murray 
940cce7d346SDag-Erling Smørgrav 	case sZeroKnowledgePasswordAuthentication:
941cce7d346SDag-Erling Smørgrav 		intptr = &options->zero_knowledge_password_authentication;
942cce7d346SDag-Erling Smørgrav 		goto parse_flag;
943cce7d346SDag-Erling Smørgrav 
94409958426SBrian Feldman 	case sKbdInteractiveAuthentication:
94509958426SBrian Feldman 		intptr = &options->kbd_interactive_authentication;
94609958426SBrian Feldman 		goto parse_flag;
94709958426SBrian Feldman 
948ca3176e7SBrian Feldman 	case sChallengeResponseAuthentication:
949af12a3e7SDag-Erling Smørgrav 		intptr = &options->challenge_response_authentication;
950511b41d2SMark Murray 		goto parse_flag;
951511b41d2SMark Murray 
952511b41d2SMark Murray 	case sPrintMotd:
953511b41d2SMark Murray 		intptr = &options->print_motd;
954511b41d2SMark Murray 		goto parse_flag;
955511b41d2SMark Murray 
956ca3176e7SBrian Feldman 	case sPrintLastLog:
957ca3176e7SBrian Feldman 		intptr = &options->print_lastlog;
958ca3176e7SBrian Feldman 		goto parse_flag;
959ca3176e7SBrian Feldman 
960511b41d2SMark Murray 	case sX11Forwarding:
961511b41d2SMark Murray 		intptr = &options->x11_forwarding;
962511b41d2SMark Murray 		goto parse_flag;
963511b41d2SMark Murray 
964511b41d2SMark Murray 	case sX11DisplayOffset:
965511b41d2SMark Murray 		intptr = &options->x11_display_offset;
966511b41d2SMark Murray 		goto parse_int;
967511b41d2SMark Murray 
968af12a3e7SDag-Erling Smørgrav 	case sX11UseLocalhost:
969af12a3e7SDag-Erling Smørgrav 		intptr = &options->x11_use_localhost;
970af12a3e7SDag-Erling Smørgrav 		goto parse_flag;
971af12a3e7SDag-Erling Smørgrav 
972c2d3a559SKris Kennaway 	case sXAuthLocation:
973c2d3a559SKris Kennaway 		charptr = &options->xauth_location;
974c2d3a559SKris Kennaway 		goto parse_filename;
975c2d3a559SKris Kennaway 
976511b41d2SMark Murray 	case sStrictModes:
977511b41d2SMark Murray 		intptr = &options->strict_modes;
978511b41d2SMark Murray 		goto parse_flag;
979511b41d2SMark Murray 
9801ec0d754SDag-Erling Smørgrav 	case sTCPKeepAlive:
9811ec0d754SDag-Erling Smørgrav 		intptr = &options->tcp_keep_alive;
982511b41d2SMark Murray 		goto parse_flag;
983511b41d2SMark Murray 
984511b41d2SMark Murray 	case sEmptyPasswd:
985511b41d2SMark Murray 		intptr = &options->permit_empty_passwd;
986511b41d2SMark Murray 		goto parse_flag;
987511b41d2SMark Murray 
988f388f5efSDag-Erling Smørgrav 	case sPermitUserEnvironment:
989f388f5efSDag-Erling Smørgrav 		intptr = &options->permit_user_env;
990f388f5efSDag-Erling Smørgrav 		goto parse_flag;
991f388f5efSDag-Erling Smørgrav 
992511b41d2SMark Murray 	case sUseLogin:
993511b41d2SMark Murray 		intptr = &options->use_login;
994511b41d2SMark Murray 		goto parse_flag;
995511b41d2SMark Murray 
99680628bacSDag-Erling Smørgrav 	case sCompression:
99780628bacSDag-Erling Smørgrav 		intptr = &options->compression;
998d4ecd108SDag-Erling Smørgrav 		arg = strdelim(&cp);
999d4ecd108SDag-Erling Smørgrav 		if (!arg || *arg == '\0')
1000d4ecd108SDag-Erling Smørgrav 			fatal("%s line %d: missing yes/no/delayed "
1001d4ecd108SDag-Erling Smørgrav 			    "argument.", filename, linenum);
1002d4ecd108SDag-Erling Smørgrav 		value = 0;	/* silence compiler */
1003d4ecd108SDag-Erling Smørgrav 		if (strcmp(arg, "delayed") == 0)
1004d4ecd108SDag-Erling Smørgrav 			value = COMP_DELAYED;
1005d4ecd108SDag-Erling Smørgrav 		else if (strcmp(arg, "yes") == 0)
1006d4ecd108SDag-Erling Smørgrav 			value = COMP_ZLIB;
1007d4ecd108SDag-Erling Smørgrav 		else if (strcmp(arg, "no") == 0)
1008d4ecd108SDag-Erling Smørgrav 			value = COMP_NONE;
1009d4ecd108SDag-Erling Smørgrav 		else
1010d4ecd108SDag-Erling Smørgrav 			fatal("%s line %d: Bad yes/no/delayed "
1011d4ecd108SDag-Erling Smørgrav 			    "argument: %s", filename, linenum, arg);
1012d4ecd108SDag-Erling Smørgrav 		if (*intptr == -1)
1013d4ecd108SDag-Erling Smørgrav 			*intptr = value;
1014d4ecd108SDag-Erling Smørgrav 		break;
101580628bacSDag-Erling Smørgrav 
1016e8aafc91SKris Kennaway 	case sGatewayPorts:
1017e8aafc91SKris Kennaway 		intptr = &options->gateway_ports;
1018aa49c926SDag-Erling Smørgrav 		arg = strdelim(&cp);
1019aa49c926SDag-Erling Smørgrav 		if (!arg || *arg == '\0')
1020aa49c926SDag-Erling Smørgrav 			fatal("%s line %d: missing yes/no/clientspecified "
1021aa49c926SDag-Erling Smørgrav 			    "argument.", filename, linenum);
1022aa49c926SDag-Erling Smørgrav 		value = 0;	/* silence compiler */
1023aa49c926SDag-Erling Smørgrav 		if (strcmp(arg, "clientspecified") == 0)
1024aa49c926SDag-Erling Smørgrav 			value = 2;
1025aa49c926SDag-Erling Smørgrav 		else if (strcmp(arg, "yes") == 0)
1026aa49c926SDag-Erling Smørgrav 			value = 1;
1027aa49c926SDag-Erling Smørgrav 		else if (strcmp(arg, "no") == 0)
1028aa49c926SDag-Erling Smørgrav 			value = 0;
1029aa49c926SDag-Erling Smørgrav 		else
1030aa49c926SDag-Erling Smørgrav 			fatal("%s line %d: Bad yes/no/clientspecified "
1031aa49c926SDag-Erling Smørgrav 			    "argument: %s", filename, linenum, arg);
1032d4af9e69SDag-Erling Smørgrav 		if (*activep && *intptr == -1)
1033aa49c926SDag-Erling Smørgrav 			*intptr = value;
1034aa49c926SDag-Erling Smørgrav 		break;
1035e8aafc91SKris Kennaway 
1036cf2b5f3bSDag-Erling Smørgrav 	case sUseDNS:
1037cf2b5f3bSDag-Erling Smørgrav 		intptr = &options->use_dns;
1038ca3176e7SBrian Feldman 		goto parse_flag;
1039ca3176e7SBrian Feldman 
1040511b41d2SMark Murray 	case sLogFacility:
1041d4af9e69SDag-Erling Smørgrav 		log_facility_ptr = &options->log_facility;
1042c2d3a559SKris Kennaway 		arg = strdelim(&cp);
1043c2d3a559SKris Kennaway 		value = log_facility_number(arg);
1044af12a3e7SDag-Erling Smørgrav 		if (value == SYSLOG_FACILITY_NOT_SET)
1045ca3176e7SBrian Feldman 			fatal("%.200s line %d: unsupported log facility '%s'",
1046c2d3a559SKris Kennaway 			    filename, linenum, arg ? arg : "<NONE>");
1047d4af9e69SDag-Erling Smørgrav 		if (*log_facility_ptr == -1)
1048d4af9e69SDag-Erling Smørgrav 			*log_facility_ptr = (SyslogFacility) value;
1049511b41d2SMark Murray 		break;
1050511b41d2SMark Murray 
1051511b41d2SMark Murray 	case sLogLevel:
1052d4af9e69SDag-Erling Smørgrav 		log_level_ptr = &options->log_level;
1053c2d3a559SKris Kennaway 		arg = strdelim(&cp);
1054c2d3a559SKris Kennaway 		value = log_level_number(arg);
1055af12a3e7SDag-Erling Smørgrav 		if (value == SYSLOG_LEVEL_NOT_SET)
1056ca3176e7SBrian Feldman 			fatal("%.200s line %d: unsupported log level '%s'",
1057c2d3a559SKris Kennaway 			    filename, linenum, arg ? arg : "<NONE>");
1058d4af9e69SDag-Erling Smørgrav 		if (*log_level_ptr == -1)
1059d4af9e69SDag-Erling Smørgrav 			*log_level_ptr = (LogLevel) value;
1060511b41d2SMark Murray 		break;
1061511b41d2SMark Murray 
106209958426SBrian Feldman 	case sAllowTcpForwarding:
106309958426SBrian Feldman 		intptr = &options->allow_tcp_forwarding;
106409958426SBrian Feldman 		goto parse_flag;
106509958426SBrian Feldman 
1066d4af9e69SDag-Erling Smørgrav 	case sAllowAgentForwarding:
1067d4af9e69SDag-Erling Smørgrav 		intptr = &options->allow_agent_forwarding;
1068d4af9e69SDag-Erling Smørgrav 		goto parse_flag;
1069d4af9e69SDag-Erling Smørgrav 
107080628bacSDag-Erling Smørgrav 	case sUsePrivilegeSeparation:
107180628bacSDag-Erling Smørgrav 		intptr = &use_privsep;
107280628bacSDag-Erling Smørgrav 		goto parse_flag;
107380628bacSDag-Erling Smørgrav 
1074511b41d2SMark Murray 	case sAllowUsers:
1075c2d3a559SKris Kennaway 		while ((arg = strdelim(&cp)) && *arg != '\0') {
107642f71286SMark Murray 			if (options->num_allow_users >= MAX_ALLOW_USERS)
1077af12a3e7SDag-Erling Smørgrav 				fatal("%s line %d: too many allow users.",
1078e8aafc91SKris Kennaway 				    filename, linenum);
1079a82e551fSDag-Erling Smørgrav 			options->allow_users[options->num_allow_users++] =
1080a82e551fSDag-Erling Smørgrav 			    xstrdup(arg);
1081511b41d2SMark Murray 		}
1082511b41d2SMark Murray 		break;
1083511b41d2SMark Murray 
1084511b41d2SMark Murray 	case sDenyUsers:
1085c2d3a559SKris Kennaway 		while ((arg = strdelim(&cp)) && *arg != '\0') {
10862803b77eSBrian Feldman 			if (options->num_deny_users >= MAX_DENY_USERS)
1087af12a3e7SDag-Erling Smørgrav 				fatal("%s line %d: too many deny users.",
1088e8aafc91SKris Kennaway 				    filename, linenum);
1089a82e551fSDag-Erling Smørgrav 			options->deny_users[options->num_deny_users++] =
1090a82e551fSDag-Erling Smørgrav 			    xstrdup(arg);
1091511b41d2SMark Murray 		}
1092511b41d2SMark Murray 		break;
1093511b41d2SMark Murray 
1094511b41d2SMark Murray 	case sAllowGroups:
1095c2d3a559SKris Kennaway 		while ((arg = strdelim(&cp)) && *arg != '\0') {
109642f71286SMark Murray 			if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
1097af12a3e7SDag-Erling Smørgrav 				fatal("%s line %d: too many allow groups.",
1098e8aafc91SKris Kennaway 				    filename, linenum);
1099a82e551fSDag-Erling Smørgrav 			options->allow_groups[options->num_allow_groups++] =
1100a82e551fSDag-Erling Smørgrav 			    xstrdup(arg);
1101511b41d2SMark Murray 		}
1102511b41d2SMark Murray 		break;
1103511b41d2SMark Murray 
1104511b41d2SMark Murray 	case sDenyGroups:
1105c2d3a559SKris Kennaway 		while ((arg = strdelim(&cp)) && *arg != '\0') {
110642f71286SMark Murray 			if (options->num_deny_groups >= MAX_DENY_GROUPS)
1107af12a3e7SDag-Erling Smørgrav 				fatal("%s line %d: too many deny groups.",
1108e8aafc91SKris Kennaway 				    filename, linenum);
1109c2d3a559SKris Kennaway 			options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
1110511b41d2SMark Murray 		}
1111511b41d2SMark Murray 		break;
1112511b41d2SMark Murray 
1113e8aafc91SKris Kennaway 	case sCiphers:
1114c2d3a559SKris Kennaway 		arg = strdelim(&cp);
1115c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
1116c322fe35SKris Kennaway 			fatal("%s line %d: Missing argument.", filename, linenum);
1117c2d3a559SKris Kennaway 		if (!ciphers_valid(arg))
1118e8aafc91SKris Kennaway 			fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
1119c2d3a559SKris Kennaway 			    filename, linenum, arg ? arg : "<NONE>");
1120e8aafc91SKris Kennaway 		if (options->ciphers == NULL)
1121c2d3a559SKris Kennaway 			options->ciphers = xstrdup(arg);
1122e8aafc91SKris Kennaway 		break;
1123e8aafc91SKris Kennaway 
1124ca3176e7SBrian Feldman 	case sMacs:
1125ca3176e7SBrian Feldman 		arg = strdelim(&cp);
1126ca3176e7SBrian Feldman 		if (!arg || *arg == '\0')
1127ca3176e7SBrian Feldman 			fatal("%s line %d: Missing argument.", filename, linenum);
1128ca3176e7SBrian Feldman 		if (!mac_valid(arg))
1129ca3176e7SBrian Feldman 			fatal("%s line %d: Bad SSH2 mac spec '%s'.",
1130ca3176e7SBrian Feldman 			    filename, linenum, arg ? arg : "<NONE>");
1131ca3176e7SBrian Feldman 		if (options->macs == NULL)
1132ca3176e7SBrian Feldman 			options->macs = xstrdup(arg);
1133ca3176e7SBrian Feldman 		break;
1134ca3176e7SBrian Feldman 
1135e8aafc91SKris Kennaway 	case sProtocol:
1136e8aafc91SKris Kennaway 		intptr = &options->protocol;
1137c2d3a559SKris Kennaway 		arg = strdelim(&cp);
1138c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
1139c322fe35SKris Kennaway 			fatal("%s line %d: Missing argument.", filename, linenum);
1140c2d3a559SKris Kennaway 		value = proto_spec(arg);
1141e8aafc91SKris Kennaway 		if (value == SSH_PROTO_UNKNOWN)
1142e8aafc91SKris Kennaway 			fatal("%s line %d: Bad protocol spec '%s'.",
1143c2d3a559SKris Kennaway 			    filename, linenum, arg ? arg : "<NONE>");
1144e8aafc91SKris Kennaway 		if (*intptr == SSH_PROTO_UNKNOWN)
1145e8aafc91SKris Kennaway 			*intptr = value;
1146e8aafc91SKris Kennaway 		break;
1147e8aafc91SKris Kennaway 
1148c2d3a559SKris Kennaway 	case sSubsystem:
1149c2d3a559SKris Kennaway 		if (options->num_subsystems >= MAX_SUBSYSTEMS) {
1150c2d3a559SKris Kennaway 			fatal("%s line %d: too many subsystems defined.",
1151c2d3a559SKris Kennaway 			    filename, linenum);
1152c2d3a559SKris Kennaway 		}
1153c2d3a559SKris Kennaway 		arg = strdelim(&cp);
1154c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
1155c2d3a559SKris Kennaway 			fatal("%s line %d: Missing subsystem name.",
1156c2d3a559SKris Kennaway 			    filename, linenum);
1157333ee039SDag-Erling Smørgrav 		if (!*activep) {
1158333ee039SDag-Erling Smørgrav 			arg = strdelim(&cp);
1159333ee039SDag-Erling Smørgrav 			break;
1160333ee039SDag-Erling Smørgrav 		}
1161c2d3a559SKris Kennaway 		for (i = 0; i < options->num_subsystems; i++)
1162c2d3a559SKris Kennaway 			if (strcmp(arg, options->subsystem_name[i]) == 0)
1163c2d3a559SKris Kennaway 				fatal("%s line %d: Subsystem '%s' already defined.",
1164c2d3a559SKris Kennaway 				    filename, linenum, arg);
1165c2d3a559SKris Kennaway 		options->subsystem_name[options->num_subsystems] = xstrdup(arg);
1166c2d3a559SKris Kennaway 		arg = strdelim(&cp);
1167c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
1168c2d3a559SKris Kennaway 			fatal("%s line %d: Missing subsystem command.",
1169c2d3a559SKris Kennaway 			    filename, linenum);
1170c2d3a559SKris Kennaway 		options->subsystem_command[options->num_subsystems] = xstrdup(arg);
1171333ee039SDag-Erling Smørgrav 
1172333ee039SDag-Erling Smørgrav 		/* Collect arguments (separate to executable) */
1173333ee039SDag-Erling Smørgrav 		p = xstrdup(arg);
1174333ee039SDag-Erling Smørgrav 		len = strlen(p) + 1;
1175333ee039SDag-Erling Smørgrav 		while ((arg = strdelim(&cp)) != NULL && *arg != '\0') {
1176333ee039SDag-Erling Smørgrav 			len += 1 + strlen(arg);
1177333ee039SDag-Erling Smørgrav 			p = xrealloc(p, 1, len);
1178333ee039SDag-Erling Smørgrav 			strlcat(p, " ", len);
1179333ee039SDag-Erling Smørgrav 			strlcat(p, arg, len);
1180333ee039SDag-Erling Smørgrav 		}
1181333ee039SDag-Erling Smørgrav 		options->subsystem_args[options->num_subsystems] = p;
1182c2d3a559SKris Kennaway 		options->num_subsystems++;
1183c2d3a559SKris Kennaway 		break;
1184c2d3a559SKris Kennaway 
1185c2d3a559SKris Kennaway 	case sMaxStartups:
1186c2d3a559SKris Kennaway 		arg = strdelim(&cp);
1187c2d3a559SKris Kennaway 		if (!arg || *arg == '\0')
1188c2d3a559SKris Kennaway 			fatal("%s line %d: Missing MaxStartups spec.",
1189c2d3a559SKris Kennaway 			    filename, linenum);
1190af12a3e7SDag-Erling Smørgrav 		if ((n = sscanf(arg, "%d:%d:%d",
1191c2d3a559SKris Kennaway 		    &options->max_startups_begin,
1192c2d3a559SKris Kennaway 		    &options->max_startups_rate,
1193af12a3e7SDag-Erling Smørgrav 		    &options->max_startups)) == 3) {
1194c2d3a559SKris Kennaway 			if (options->max_startups_begin >
1195c2d3a559SKris Kennaway 			    options->max_startups ||
1196c2d3a559SKris Kennaway 			    options->max_startups_rate > 100 ||
1197c2d3a559SKris Kennaway 			    options->max_startups_rate < 1)
1198c2d3a559SKris Kennaway 				fatal("%s line %d: Illegal MaxStartups spec.",
1199c2d3a559SKris Kennaway 				    filename, linenum);
1200af12a3e7SDag-Erling Smørgrav 		} else if (n != 1)
1201af12a3e7SDag-Erling Smørgrav 			fatal("%s line %d: Illegal MaxStartups spec.",
1202af12a3e7SDag-Erling Smørgrav 			    filename, linenum);
1203af12a3e7SDag-Erling Smørgrav 		else
1204af12a3e7SDag-Erling Smørgrav 			options->max_startups = options->max_startups_begin;
1205933ca70fSBrian Feldman 		break;
1206933ca70fSBrian Feldman 
120721e764dfSDag-Erling Smørgrav 	case sMaxAuthTries:
120821e764dfSDag-Erling Smørgrav 		intptr = &options->max_authtries;
120921e764dfSDag-Erling Smørgrav 		goto parse_int;
121021e764dfSDag-Erling Smørgrav 
1211d4af9e69SDag-Erling Smørgrav 	case sMaxSessions:
1212d4af9e69SDag-Erling Smørgrav 		intptr = &options->max_sessions;
1213d4af9e69SDag-Erling Smørgrav 		goto parse_int;
1214d4af9e69SDag-Erling Smørgrav 
1215ca3176e7SBrian Feldman 	case sBanner:
1216ca3176e7SBrian Feldman 		charptr = &options->banner;
1217ca3176e7SBrian Feldman 		goto parse_filename;
1218d4af9e69SDag-Erling Smørgrav 
1219af12a3e7SDag-Erling Smørgrav 	/*
1220af12a3e7SDag-Erling Smørgrav 	 * These options can contain %X options expanded at
1221af12a3e7SDag-Erling Smørgrav 	 * connect time, so that you can specify paths like:
1222af12a3e7SDag-Erling Smørgrav 	 *
1223af12a3e7SDag-Erling Smørgrav 	 * AuthorizedKeysFile	/etc/ssh_keys/%u
1224af12a3e7SDag-Erling Smørgrav 	 */
1225af12a3e7SDag-Erling Smørgrav 	case sAuthorizedKeysFile:
1226af12a3e7SDag-Erling Smørgrav 	case sAuthorizedKeysFile2:
1227af12a3e7SDag-Erling Smørgrav 		charptr = (opcode == sAuthorizedKeysFile) ?
1228af12a3e7SDag-Erling Smørgrav 		    &options->authorized_keys_file :
1229af12a3e7SDag-Erling Smørgrav 		    &options->authorized_keys_file2;
1230af12a3e7SDag-Erling Smørgrav 		goto parse_filename;
1231af12a3e7SDag-Erling Smørgrav 
1232ca3176e7SBrian Feldman 	case sClientAliveInterval:
1233ca3176e7SBrian Feldman 		intptr = &options->client_alive_interval;
1234af12a3e7SDag-Erling Smørgrav 		goto parse_time;
1235af12a3e7SDag-Erling Smørgrav 
1236ca3176e7SBrian Feldman 	case sClientAliveCountMax:
1237ca3176e7SBrian Feldman 		intptr = &options->client_alive_count_max;
1238ca3176e7SBrian Feldman 		goto parse_int;
1239af12a3e7SDag-Erling Smørgrav 
124021e764dfSDag-Erling Smørgrav 	case sAcceptEnv:
124121e764dfSDag-Erling Smørgrav 		while ((arg = strdelim(&cp)) && *arg != '\0') {
124221e764dfSDag-Erling Smørgrav 			if (strchr(arg, '=') != NULL)
124321e764dfSDag-Erling Smørgrav 				fatal("%s line %d: Invalid environment name.",
124421e764dfSDag-Erling Smørgrav 				    filename, linenum);
124521e764dfSDag-Erling Smørgrav 			if (options->num_accept_env >= MAX_ACCEPT_ENV)
124621e764dfSDag-Erling Smørgrav 				fatal("%s line %d: too many allow env.",
124721e764dfSDag-Erling Smørgrav 				    filename, linenum);
1248333ee039SDag-Erling Smørgrav 			if (!*activep)
1249333ee039SDag-Erling Smørgrav 				break;
125021e764dfSDag-Erling Smørgrav 			options->accept_env[options->num_accept_env++] =
125121e764dfSDag-Erling Smørgrav 			    xstrdup(arg);
125221e764dfSDag-Erling Smørgrav 		}
125321e764dfSDag-Erling Smørgrav 		break;
125421e764dfSDag-Erling Smørgrav 
1255b74df5b2SDag-Erling Smørgrav 	case sPermitTunnel:
1256b74df5b2SDag-Erling Smørgrav 		intptr = &options->permit_tun;
1257b74df5b2SDag-Erling Smørgrav 		arg = strdelim(&cp);
1258b74df5b2SDag-Erling Smørgrav 		if (!arg || *arg == '\0')
1259b74df5b2SDag-Erling Smørgrav 			fatal("%s line %d: Missing yes/point-to-point/"
1260b74df5b2SDag-Erling Smørgrav 			    "ethernet/no argument.", filename, linenum);
1261d4af9e69SDag-Erling Smørgrav 		value = -1;
1262d4af9e69SDag-Erling Smørgrav 		for (i = 0; tunmode_desc[i].val != -1; i++)
1263d4af9e69SDag-Erling Smørgrav 			if (strcmp(tunmode_desc[i].text, arg) == 0) {
1264d4af9e69SDag-Erling Smørgrav 				value = tunmode_desc[i].val;
1265d4af9e69SDag-Erling Smørgrav 				break;
1266d4af9e69SDag-Erling Smørgrav 			}
1267d4af9e69SDag-Erling Smørgrav 		if (value == -1)
1268b74df5b2SDag-Erling Smørgrav 			fatal("%s line %d: Bad yes/point-to-point/ethernet/"
1269b74df5b2SDag-Erling Smørgrav 			    "no argument: %s", filename, linenum, arg);
1270b74df5b2SDag-Erling Smørgrav 		if (*intptr == -1)
1271b74df5b2SDag-Erling Smørgrav 			*intptr = value;
1272b74df5b2SDag-Erling Smørgrav 		break;
1273b74df5b2SDag-Erling Smørgrav 
1274333ee039SDag-Erling Smørgrav 	case sMatch:
1275333ee039SDag-Erling Smørgrav 		if (cmdline)
1276333ee039SDag-Erling Smørgrav 			fatal("Match directive not supported as a command-line "
1277333ee039SDag-Erling Smørgrav 			   "option");
1278333ee039SDag-Erling Smørgrav 		value = match_cfg_line(&cp, linenum, user, host, address);
1279333ee039SDag-Erling Smørgrav 		if (value < 0)
1280333ee039SDag-Erling Smørgrav 			fatal("%s line %d: Bad Match condition", filename,
1281333ee039SDag-Erling Smørgrav 			    linenum);
1282333ee039SDag-Erling Smørgrav 		*activep = value;
1283333ee039SDag-Erling Smørgrav 		break;
1284333ee039SDag-Erling Smørgrav 
1285333ee039SDag-Erling Smørgrav 	case sPermitOpen:
1286333ee039SDag-Erling Smørgrav 		arg = strdelim(&cp);
1287333ee039SDag-Erling Smørgrav 		if (!arg || *arg == '\0')
1288333ee039SDag-Erling Smørgrav 			fatal("%s line %d: missing PermitOpen specification",
1289333ee039SDag-Erling Smørgrav 			    filename, linenum);
1290d4af9e69SDag-Erling Smørgrav 		n = options->num_permitted_opens;	/* modified later */
1291333ee039SDag-Erling Smørgrav 		if (strcmp(arg, "any") == 0) {
1292d4af9e69SDag-Erling Smørgrav 			if (*activep && n == -1) {
1293333ee039SDag-Erling Smørgrav 				channel_clear_adm_permitted_opens();
1294333ee039SDag-Erling Smørgrav 				options->num_permitted_opens = 0;
1295333ee039SDag-Erling Smørgrav 			}
1296333ee039SDag-Erling Smørgrav 			break;
1297333ee039SDag-Erling Smørgrav 		}
1298d4af9e69SDag-Erling Smørgrav 		if (*activep && n == -1)
1299d4af9e69SDag-Erling Smørgrav 			channel_clear_adm_permitted_opens();
1300333ee039SDag-Erling Smørgrav 		for (; arg != NULL && *arg != '\0'; arg = strdelim(&cp)) {
1301333ee039SDag-Erling Smørgrav 			p = hpdelim(&arg);
1302333ee039SDag-Erling Smørgrav 			if (p == NULL)
1303333ee039SDag-Erling Smørgrav 				fatal("%s line %d: missing host in PermitOpen",
1304333ee039SDag-Erling Smørgrav 				    filename, linenum);
1305333ee039SDag-Erling Smørgrav 			p = cleanhostname(p);
1306cce7d346SDag-Erling Smørgrav 			if (arg == NULL || (port = a2port(arg)) <= 0)
1307333ee039SDag-Erling Smørgrav 				fatal("%s line %d: bad port number in "
1308333ee039SDag-Erling Smørgrav 				    "PermitOpen", filename, linenum);
1309d4af9e69SDag-Erling Smørgrav 			if (*activep && n == -1)
1310333ee039SDag-Erling Smørgrav 				options->num_permitted_opens =
1311333ee039SDag-Erling Smørgrav 				    channel_add_adm_permitted_opens(p, port);
1312333ee039SDag-Erling Smørgrav 		}
1313333ee039SDag-Erling Smørgrav 		break;
1314333ee039SDag-Erling Smørgrav 
1315333ee039SDag-Erling Smørgrav 	case sForceCommand:
1316333ee039SDag-Erling Smørgrav 		if (cp == NULL)
1317333ee039SDag-Erling Smørgrav 			fatal("%.200s line %d: Missing argument.", filename,
1318333ee039SDag-Erling Smørgrav 			    linenum);
1319333ee039SDag-Erling Smørgrav 		len = strspn(cp, WHITESPACE);
1320333ee039SDag-Erling Smørgrav 		if (*activep && options->adm_forced_command == NULL)
1321333ee039SDag-Erling Smørgrav 			options->adm_forced_command = xstrdup(cp + len);
1322333ee039SDag-Erling Smørgrav 		return 0;
1323333ee039SDag-Erling Smørgrav 
1324d4af9e69SDag-Erling Smørgrav 	case sChrootDirectory:
1325d4af9e69SDag-Erling Smørgrav 		charptr = &options->chroot_directory;
1326d4af9e69SDag-Erling Smørgrav 
1327d4af9e69SDag-Erling Smørgrav 		arg = strdelim(&cp);
1328d4af9e69SDag-Erling Smørgrav 		if (!arg || *arg == '\0')
1329d4af9e69SDag-Erling Smørgrav 			fatal("%s line %d: missing file name.",
1330d4af9e69SDag-Erling Smørgrav 			    filename, linenum);
1331d4af9e69SDag-Erling Smørgrav 		if (*activep && *charptr == NULL)
1332d4af9e69SDag-Erling Smørgrav 			*charptr = xstrdup(arg);
1333d4af9e69SDag-Erling Smørgrav 		break;
1334d4af9e69SDag-Erling Smørgrav 
1335b15c8340SDag-Erling Smørgrav 	case sTrustedUserCAKeys:
1336b15c8340SDag-Erling Smørgrav 		charptr = &options->trusted_user_ca_keys;
1337b15c8340SDag-Erling Smørgrav 		goto parse_filename;
1338b15c8340SDag-Erling Smørgrav 
1339b15c8340SDag-Erling Smørgrav 	case sRevokedKeys:
1340b15c8340SDag-Erling Smørgrav 		charptr = &options->revoked_keys_file;
1341b15c8340SDag-Erling Smørgrav 		goto parse_filename;
1342b15c8340SDag-Erling Smørgrav 
1343db58a8e4SDag-Erling Smørgrav 	case sVersionAddendum:
1344db58a8e4SDag-Erling Smørgrav                 ssh_version_set_addendum(strtok(cp, "\n"));
1345db58a8e4SDag-Erling Smørgrav                 do {
1346db58a8e4SDag-Erling Smørgrav                         arg = strdelim(&cp);
1347db58a8e4SDag-Erling Smørgrav                 } while (arg != NULL && *arg != '\0');
1348db58a8e4SDag-Erling Smørgrav 		break;
1349db58a8e4SDag-Erling Smørgrav 
1350af12a3e7SDag-Erling Smørgrav 	case sDeprecated:
1351cf2b5f3bSDag-Erling Smørgrav 		logit("%s line %d: Deprecated option %s",
1352cf2b5f3bSDag-Erling Smørgrav 		    filename, linenum, arg);
1353cf2b5f3bSDag-Erling Smørgrav 		while (arg)
1354cf2b5f3bSDag-Erling Smørgrav 		    arg = strdelim(&cp);
1355cf2b5f3bSDag-Erling Smørgrav 		break;
1356cf2b5f3bSDag-Erling Smørgrav 
1357cf2b5f3bSDag-Erling Smørgrav 	case sUnsupported:
1358cf2b5f3bSDag-Erling Smørgrav 		logit("%s line %d: Unsupported option %s",
1359af12a3e7SDag-Erling Smørgrav 		    filename, linenum, arg);
1360af12a3e7SDag-Erling Smørgrav 		while (arg)
1361af12a3e7SDag-Erling Smørgrav 		    arg = strdelim(&cp);
1362af12a3e7SDag-Erling Smørgrav 		break;
1363af12a3e7SDag-Erling Smørgrav 
136442f71286SMark Murray 	default:
1365af12a3e7SDag-Erling Smørgrav 		fatal("%s line %d: Missing handler for opcode %s (%d)",
1366c2d3a559SKris Kennaway 		    filename, linenum, arg, opcode);
1367511b41d2SMark Murray 	}
1368ca3176e7SBrian Feldman 	if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
1369ca3176e7SBrian Feldman 		fatal("%s line %d: garbage at end of line; \"%.200s\".",
1370c2d3a559SKris Kennaway 		    filename, linenum, arg);
1371af12a3e7SDag-Erling Smørgrav 	return 0;
1372af12a3e7SDag-Erling Smørgrav }
1373af12a3e7SDag-Erling Smørgrav 
1374af12a3e7SDag-Erling Smørgrav /* Reads the server configuration file. */
1375af12a3e7SDag-Erling Smørgrav 
1376af12a3e7SDag-Erling Smørgrav void
137721e764dfSDag-Erling Smørgrav load_server_config(const char *filename, Buffer *conf)
1378af12a3e7SDag-Erling Smørgrav {
137921e764dfSDag-Erling Smørgrav 	char line[1024], *cp;
1380a82e551fSDag-Erling Smørgrav 	FILE *f;
1381af12a3e7SDag-Erling Smørgrav 
138221e764dfSDag-Erling Smørgrav 	debug2("%s: filename %s", __func__, filename);
138321e764dfSDag-Erling Smørgrav 	if ((f = fopen(filename, "r")) == NULL) {
1384af12a3e7SDag-Erling Smørgrav 		perror(filename);
1385af12a3e7SDag-Erling Smørgrav 		exit(1);
1386af12a3e7SDag-Erling Smørgrav 	}
138721e764dfSDag-Erling Smørgrav 	buffer_clear(conf);
1388af12a3e7SDag-Erling Smørgrav 	while (fgets(line, sizeof(line), f)) {
138921e764dfSDag-Erling Smørgrav 		/*
139021e764dfSDag-Erling Smørgrav 		 * Trim out comments and strip whitespace
139121e764dfSDag-Erling Smørgrav 		 * NB - preserve newlines, they are needed to reproduce
139221e764dfSDag-Erling Smørgrav 		 * line numbers later for error messages
139321e764dfSDag-Erling Smørgrav 		 */
139421e764dfSDag-Erling Smørgrav 		if ((cp = strchr(line, '#')) != NULL)
139521e764dfSDag-Erling Smørgrav 			memcpy(cp, "\n", 2);
139621e764dfSDag-Erling Smørgrav 		cp = line + strspn(line, " \t\r");
139721e764dfSDag-Erling Smørgrav 
139821e764dfSDag-Erling Smørgrav 		buffer_append(conf, cp, strlen(cp));
139921e764dfSDag-Erling Smørgrav 	}
140021e764dfSDag-Erling Smørgrav 	buffer_append(conf, "\0", 1);
140121e764dfSDag-Erling Smørgrav 	fclose(f);
140221e764dfSDag-Erling Smørgrav 	debug2("%s: done config len = %d", __func__, buffer_len(conf));
140321e764dfSDag-Erling Smørgrav }
140421e764dfSDag-Erling Smørgrav 
140521e764dfSDag-Erling Smørgrav void
1406333ee039SDag-Erling Smørgrav parse_server_match_config(ServerOptions *options, const char *user,
1407333ee039SDag-Erling Smørgrav     const char *host, const char *address)
140821e764dfSDag-Erling Smørgrav {
1409333ee039SDag-Erling Smørgrav 	ServerOptions mo;
1410333ee039SDag-Erling Smørgrav 
1411333ee039SDag-Erling Smørgrav 	initialize_server_options(&mo);
1412333ee039SDag-Erling Smørgrav 	parse_server_config(&mo, "reprocess config", &cfg, user, host, address);
1413d4af9e69SDag-Erling Smørgrav 	copy_set_server_options(options, &mo, 0);
1414333ee039SDag-Erling Smørgrav }
1415333ee039SDag-Erling Smørgrav 
1416d4af9e69SDag-Erling Smørgrav /* Helper macros */
1417d4af9e69SDag-Erling Smørgrav #define M_CP_INTOPT(n) do {\
1418d4af9e69SDag-Erling Smørgrav 	if (src->n != -1) \
1419d4af9e69SDag-Erling Smørgrav 		dst->n = src->n; \
1420d4af9e69SDag-Erling Smørgrav } while (0)
1421d4af9e69SDag-Erling Smørgrav #define M_CP_STROPT(n) do {\
1422d4af9e69SDag-Erling Smørgrav 	if (src->n != NULL) { \
1423d4af9e69SDag-Erling Smørgrav 		if (dst->n != NULL) \
1424d4af9e69SDag-Erling Smørgrav 			xfree(dst->n); \
1425d4af9e69SDag-Erling Smørgrav 		dst->n = src->n; \
1426d4af9e69SDag-Erling Smørgrav 	} \
1427d4af9e69SDag-Erling Smørgrav } while(0)
1428d4af9e69SDag-Erling Smørgrav 
1429d4af9e69SDag-Erling Smørgrav /*
1430d4af9e69SDag-Erling Smørgrav  * Copy any supported values that are set.
1431d4af9e69SDag-Erling Smørgrav  *
14327aee6ffeSDag-Erling Smørgrav  * If the preauth flag is set, we do not bother copying the string or
1433d4af9e69SDag-Erling Smørgrav  * array values that are not used pre-authentication, because any that we
1434d4af9e69SDag-Erling Smørgrav  * do use must be explictly sent in mm_getpwnamallow().
1435d4af9e69SDag-Erling Smørgrav  */
1436333ee039SDag-Erling Smørgrav void
1437d4af9e69SDag-Erling Smørgrav copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
1438333ee039SDag-Erling Smørgrav {
1439d4af9e69SDag-Erling Smørgrav 	M_CP_INTOPT(password_authentication);
1440d4af9e69SDag-Erling Smørgrav 	M_CP_INTOPT(gss_authentication);
1441d4af9e69SDag-Erling Smørgrav 	M_CP_INTOPT(rsa_authentication);
1442d4af9e69SDag-Erling Smørgrav 	M_CP_INTOPT(pubkey_authentication);
1443d4af9e69SDag-Erling Smørgrav 	M_CP_INTOPT(kerberos_authentication);
1444d4af9e69SDag-Erling Smørgrav 	M_CP_INTOPT(hostbased_authentication);
1445d4af9e69SDag-Erling Smørgrav 	M_CP_INTOPT(kbd_interactive_authentication);
1446cce7d346SDag-Erling Smørgrav 	M_CP_INTOPT(zero_knowledge_password_authentication);
1447d4af9e69SDag-Erling Smørgrav 	M_CP_INTOPT(permit_root_login);
1448cce7d346SDag-Erling Smørgrav 	M_CP_INTOPT(permit_empty_passwd);
1449d4af9e69SDag-Erling Smørgrav 
1450d4af9e69SDag-Erling Smørgrav 	M_CP_INTOPT(allow_tcp_forwarding);
1451d4af9e69SDag-Erling Smørgrav 	M_CP_INTOPT(allow_agent_forwarding);
1452d4af9e69SDag-Erling Smørgrav 	M_CP_INTOPT(gateway_ports);
1453d4af9e69SDag-Erling Smørgrav 	M_CP_INTOPT(x11_display_offset);
1454d4af9e69SDag-Erling Smørgrav 	M_CP_INTOPT(x11_forwarding);
1455d4af9e69SDag-Erling Smørgrav 	M_CP_INTOPT(x11_use_localhost);
1456d4af9e69SDag-Erling Smørgrav 	M_CP_INTOPT(max_sessions);
1457d4af9e69SDag-Erling Smørgrav 	M_CP_INTOPT(max_authtries);
1458d4af9e69SDag-Erling Smørgrav 
1459d4af9e69SDag-Erling Smørgrav 	M_CP_STROPT(banner);
1460d4af9e69SDag-Erling Smørgrav 	if (preauth)
1461d4af9e69SDag-Erling Smørgrav 		return;
1462d4af9e69SDag-Erling Smørgrav 	M_CP_STROPT(adm_forced_command);
1463d4af9e69SDag-Erling Smørgrav 	M_CP_STROPT(chroot_directory);
1464b15c8340SDag-Erling Smørgrav 	M_CP_STROPT(trusted_user_ca_keys);
1465b15c8340SDag-Erling Smørgrav 	M_CP_STROPT(revoked_keys_file);
1466333ee039SDag-Erling Smørgrav }
1467d4af9e69SDag-Erling Smørgrav 
1468d4af9e69SDag-Erling Smørgrav #undef M_CP_INTOPT
1469d4af9e69SDag-Erling Smørgrav #undef M_CP_STROPT
1470333ee039SDag-Erling Smørgrav 
1471333ee039SDag-Erling Smørgrav void
1472333ee039SDag-Erling Smørgrav parse_server_config(ServerOptions *options, const char *filename, Buffer *conf,
1473333ee039SDag-Erling Smørgrav     const char *user, const char *host, const char *address)
1474333ee039SDag-Erling Smørgrav {
1475333ee039SDag-Erling Smørgrav 	int active, linenum, bad_options = 0;
147621e764dfSDag-Erling Smørgrav 	char *cp, *obuf, *cbuf;
147721e764dfSDag-Erling Smørgrav 
147821e764dfSDag-Erling Smørgrav 	debug2("%s: config %s len %d", __func__, filename, buffer_len(conf));
147921e764dfSDag-Erling Smørgrav 
148021e764dfSDag-Erling Smørgrav 	obuf = cbuf = xstrdup(buffer_ptr(conf));
1481333ee039SDag-Erling Smørgrav 	active = user ? 0 : 1;
148221e764dfSDag-Erling Smørgrav 	linenum = 1;
148321e764dfSDag-Erling Smørgrav 	while ((cp = strsep(&cbuf, "\n")) != NULL) {
148421e764dfSDag-Erling Smørgrav 		if (process_server_config_line(options, cp, filename,
1485333ee039SDag-Erling Smørgrav 		    linenum++, &active, user, host, address) != 0)
1486af12a3e7SDag-Erling Smørgrav 			bad_options++;
1487511b41d2SMark Murray 	}
148821e764dfSDag-Erling Smørgrav 	xfree(obuf);
1489ca3176e7SBrian Feldman 	if (bad_options > 0)
1490af12a3e7SDag-Erling Smørgrav 		fatal("%s: terminating, %d bad configuration options",
1491511b41d2SMark Murray 		    filename, bad_options);
1492511b41d2SMark Murray }
1493d4af9e69SDag-Erling Smørgrav 
1494d4af9e69SDag-Erling Smørgrav static const char *
1495d4af9e69SDag-Erling Smørgrav fmt_intarg(ServerOpCodes code, int val)
1496d4af9e69SDag-Erling Smørgrav {
1497d4af9e69SDag-Erling Smørgrav 	if (code == sAddressFamily) {
1498d4af9e69SDag-Erling Smørgrav 		switch (val) {
1499d4af9e69SDag-Erling Smørgrav 		case AF_INET:
1500d4af9e69SDag-Erling Smørgrav 			return "inet";
1501d4af9e69SDag-Erling Smørgrav 		case AF_INET6:
1502d4af9e69SDag-Erling Smørgrav 			return "inet6";
1503d4af9e69SDag-Erling Smørgrav 		case AF_UNSPEC:
1504d4af9e69SDag-Erling Smørgrav 			return "any";
1505d4af9e69SDag-Erling Smørgrav 		default:
1506d4af9e69SDag-Erling Smørgrav 			return "UNKNOWN";
1507d4af9e69SDag-Erling Smørgrav 		}
1508d4af9e69SDag-Erling Smørgrav 	}
1509d4af9e69SDag-Erling Smørgrav 	if (code == sPermitRootLogin) {
1510d4af9e69SDag-Erling Smørgrav 		switch (val) {
1511d4af9e69SDag-Erling Smørgrav 		case PERMIT_NO_PASSWD:
1512cce7d346SDag-Erling Smørgrav 			return "without-password";
1513d4af9e69SDag-Erling Smørgrav 		case PERMIT_FORCED_ONLY:
1514d4af9e69SDag-Erling Smørgrav 			return "forced-commands-only";
1515d4af9e69SDag-Erling Smørgrav 		case PERMIT_YES:
1516d4af9e69SDag-Erling Smørgrav 			return "yes";
1517d4af9e69SDag-Erling Smørgrav 		}
1518d4af9e69SDag-Erling Smørgrav 	}
1519d4af9e69SDag-Erling Smørgrav 	if (code == sProtocol) {
1520d4af9e69SDag-Erling Smørgrav 		switch (val) {
1521d4af9e69SDag-Erling Smørgrav 		case SSH_PROTO_1:
1522d4af9e69SDag-Erling Smørgrav 			return "1";
1523d4af9e69SDag-Erling Smørgrav 		case SSH_PROTO_2:
1524d4af9e69SDag-Erling Smørgrav 			return "2";
1525d4af9e69SDag-Erling Smørgrav 		case (SSH_PROTO_1|SSH_PROTO_2):
1526d4af9e69SDag-Erling Smørgrav 			return "2,1";
1527d4af9e69SDag-Erling Smørgrav 		default:
1528d4af9e69SDag-Erling Smørgrav 			return "UNKNOWN";
1529d4af9e69SDag-Erling Smørgrav 		}
1530d4af9e69SDag-Erling Smørgrav 	}
1531d4af9e69SDag-Erling Smørgrav 	if (code == sGatewayPorts && val == 2)
1532d4af9e69SDag-Erling Smørgrav 		return "clientspecified";
1533d4af9e69SDag-Erling Smørgrav 	if (code == sCompression && val == COMP_DELAYED)
1534d4af9e69SDag-Erling Smørgrav 		return "delayed";
1535d4af9e69SDag-Erling Smørgrav 	switch (val) {
1536d4af9e69SDag-Erling Smørgrav 	case -1:
1537d4af9e69SDag-Erling Smørgrav 		return "unset";
1538d4af9e69SDag-Erling Smørgrav 	case 0:
1539d4af9e69SDag-Erling Smørgrav 		return "no";
1540d4af9e69SDag-Erling Smørgrav 	case 1:
1541d4af9e69SDag-Erling Smørgrav 		return "yes";
1542d4af9e69SDag-Erling Smørgrav 	}
1543d4af9e69SDag-Erling Smørgrav 	return "UNKNOWN";
1544d4af9e69SDag-Erling Smørgrav }
1545d4af9e69SDag-Erling Smørgrav 
1546d4af9e69SDag-Erling Smørgrav static const char *
1547d4af9e69SDag-Erling Smørgrav lookup_opcode_name(ServerOpCodes code)
1548d4af9e69SDag-Erling Smørgrav {
1549d4af9e69SDag-Erling Smørgrav 	u_int i;
1550d4af9e69SDag-Erling Smørgrav 
1551d4af9e69SDag-Erling Smørgrav 	for (i = 0; keywords[i].name != NULL; i++)
1552d4af9e69SDag-Erling Smørgrav 		if (keywords[i].opcode == code)
1553d4af9e69SDag-Erling Smørgrav 			return(keywords[i].name);
1554d4af9e69SDag-Erling Smørgrav 	return "UNKNOWN";
1555d4af9e69SDag-Erling Smørgrav }
1556d4af9e69SDag-Erling Smørgrav 
1557d4af9e69SDag-Erling Smørgrav static void
1558d4af9e69SDag-Erling Smørgrav dump_cfg_int(ServerOpCodes code, int val)
1559d4af9e69SDag-Erling Smørgrav {
1560d4af9e69SDag-Erling Smørgrav 	printf("%s %d\n", lookup_opcode_name(code), val);
1561d4af9e69SDag-Erling Smørgrav }
1562d4af9e69SDag-Erling Smørgrav 
1563d4af9e69SDag-Erling Smørgrav static void
1564d4af9e69SDag-Erling Smørgrav dump_cfg_fmtint(ServerOpCodes code, int val)
1565d4af9e69SDag-Erling Smørgrav {
1566d4af9e69SDag-Erling Smørgrav 	printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
1567d4af9e69SDag-Erling Smørgrav }
1568d4af9e69SDag-Erling Smørgrav 
1569d4af9e69SDag-Erling Smørgrav static void
1570d4af9e69SDag-Erling Smørgrav dump_cfg_string(ServerOpCodes code, const char *val)
1571d4af9e69SDag-Erling Smørgrav {
1572d4af9e69SDag-Erling Smørgrav 	if (val == NULL)
1573d4af9e69SDag-Erling Smørgrav 		return;
1574d4af9e69SDag-Erling Smørgrav 	printf("%s %s\n", lookup_opcode_name(code), val);
1575d4af9e69SDag-Erling Smørgrav }
1576d4af9e69SDag-Erling Smørgrav 
1577d4af9e69SDag-Erling Smørgrav static void
1578d4af9e69SDag-Erling Smørgrav dump_cfg_strarray(ServerOpCodes code, u_int count, char **vals)
1579d4af9e69SDag-Erling Smørgrav {
1580d4af9e69SDag-Erling Smørgrav 	u_int i;
1581d4af9e69SDag-Erling Smørgrav 
1582d4af9e69SDag-Erling Smørgrav 	for (i = 0; i < count; i++)
1583d4af9e69SDag-Erling Smørgrav 		printf("%s %s\n", lookup_opcode_name(code),  vals[i]);
1584d4af9e69SDag-Erling Smørgrav }
1585d4af9e69SDag-Erling Smørgrav 
1586d4af9e69SDag-Erling Smørgrav void
1587d4af9e69SDag-Erling Smørgrav dump_config(ServerOptions *o)
1588d4af9e69SDag-Erling Smørgrav {
1589d4af9e69SDag-Erling Smørgrav 	u_int i;
1590d4af9e69SDag-Erling Smørgrav 	int ret;
1591d4af9e69SDag-Erling Smørgrav 	struct addrinfo *ai;
1592d4af9e69SDag-Erling Smørgrav 	char addr[NI_MAXHOST], port[NI_MAXSERV], *s = NULL;
1593d4af9e69SDag-Erling Smørgrav 
1594d4af9e69SDag-Erling Smørgrav 	/* these are usually at the top of the config */
1595d4af9e69SDag-Erling Smørgrav 	for (i = 0; i < o->num_ports; i++)
1596d4af9e69SDag-Erling Smørgrav 		printf("port %d\n", o->ports[i]);
1597d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sProtocol, o->protocol);
1598d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sAddressFamily, o->address_family);
1599d4af9e69SDag-Erling Smørgrav 
1600d4af9e69SDag-Erling Smørgrav 	/* ListenAddress must be after Port */
1601d4af9e69SDag-Erling Smørgrav 	for (ai = o->listen_addrs; ai; ai = ai->ai_next) {
1602d4af9e69SDag-Erling Smørgrav 		if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr,
1603d4af9e69SDag-Erling Smørgrav 		    sizeof(addr), port, sizeof(port),
1604d4af9e69SDag-Erling Smørgrav 		    NI_NUMERICHOST|NI_NUMERICSERV)) != 0) {
1605d4af9e69SDag-Erling Smørgrav 			error("getnameinfo failed: %.100s",
1606d4af9e69SDag-Erling Smørgrav 			    (ret != EAI_SYSTEM) ? gai_strerror(ret) :
1607d4af9e69SDag-Erling Smørgrav 			    strerror(errno));
1608d4af9e69SDag-Erling Smørgrav 		} else {
1609d4af9e69SDag-Erling Smørgrav 			if (ai->ai_family == AF_INET6)
1610d4af9e69SDag-Erling Smørgrav 				printf("listenaddress [%s]:%s\n", addr, port);
1611d4af9e69SDag-Erling Smørgrav 			else
1612d4af9e69SDag-Erling Smørgrav 				printf("listenaddress %s:%s\n", addr, port);
1613d4af9e69SDag-Erling Smørgrav 		}
1614d4af9e69SDag-Erling Smørgrav 	}
1615d4af9e69SDag-Erling Smørgrav 
1616d4af9e69SDag-Erling Smørgrav 	/* integer arguments */
1617cce7d346SDag-Erling Smørgrav #ifdef USE_PAM
1618cce7d346SDag-Erling Smørgrav 	dump_cfg_int(sUsePAM, o->use_pam);
1619cce7d346SDag-Erling Smørgrav #endif
1620d4af9e69SDag-Erling Smørgrav 	dump_cfg_int(sServerKeyBits, o->server_key_bits);
1621d4af9e69SDag-Erling Smørgrav 	dump_cfg_int(sLoginGraceTime, o->login_grace_time);
1622d4af9e69SDag-Erling Smørgrav 	dump_cfg_int(sKeyRegenerationTime, o->key_regeneration_time);
1623d4af9e69SDag-Erling Smørgrav 	dump_cfg_int(sX11DisplayOffset, o->x11_display_offset);
1624d4af9e69SDag-Erling Smørgrav 	dump_cfg_int(sMaxAuthTries, o->max_authtries);
1625cce7d346SDag-Erling Smørgrav 	dump_cfg_int(sMaxSessions, o->max_sessions);
1626d4af9e69SDag-Erling Smørgrav 	dump_cfg_int(sClientAliveInterval, o->client_alive_interval);
1627d4af9e69SDag-Erling Smørgrav 	dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max);
1628d4af9e69SDag-Erling Smørgrav 
1629d4af9e69SDag-Erling Smørgrav 	/* formatted integer arguments */
1630d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sPermitRootLogin, o->permit_root_login);
1631d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sIgnoreRhosts, o->ignore_rhosts);
1632d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sIgnoreUserKnownHosts, o->ignore_user_known_hosts);
1633d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sRhostsRSAAuthentication, o->rhosts_rsa_authentication);
1634d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sHostbasedAuthentication, o->hostbased_authentication);
1635d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sHostbasedUsesNameFromPacketOnly,
1636d4af9e69SDag-Erling Smørgrav 	    o->hostbased_uses_name_from_packet_only);
1637d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sRSAAuthentication, o->rsa_authentication);
1638d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sPubkeyAuthentication, o->pubkey_authentication);
1639cce7d346SDag-Erling Smørgrav #ifdef KRB5
1640d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sKerberosAuthentication, o->kerberos_authentication);
1641d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sKerberosOrLocalPasswd, o->kerberos_or_local_passwd);
1642d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sKerberosTicketCleanup, o->kerberos_ticket_cleanup);
1643cce7d346SDag-Erling Smørgrav # ifdef USE_AFS
1644d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token);
1645cce7d346SDag-Erling Smørgrav # endif
1646cce7d346SDag-Erling Smørgrav #endif
1647cce7d346SDag-Erling Smørgrav #ifdef GSSAPI
1648d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
1649d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
1650cce7d346SDag-Erling Smørgrav #endif
1651cce7d346SDag-Erling Smørgrav #ifdef JPAKE
1652cce7d346SDag-Erling Smørgrav 	dump_cfg_fmtint(sZeroKnowledgePasswordAuthentication,
1653cce7d346SDag-Erling Smørgrav 	    o->zero_knowledge_password_authentication);
1654cce7d346SDag-Erling Smørgrav #endif
1655d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
1656d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sKbdInteractiveAuthentication,
1657d4af9e69SDag-Erling Smørgrav 	    o->kbd_interactive_authentication);
1658d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sChallengeResponseAuthentication,
1659d4af9e69SDag-Erling Smørgrav 	    o->challenge_response_authentication);
1660d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sPrintMotd, o->print_motd);
1661d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sPrintLastLog, o->print_lastlog);
1662d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding);
1663d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost);
1664d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sStrictModes, o->strict_modes);
1665d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive);
1666d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd);
1667d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
1668d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sUseLogin, o->use_login);
1669d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sCompression, o->compression);
1670d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sGatewayPorts, o->gateway_ports);
1671d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sUseDNS, o->use_dns);
1672d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
1673d4af9e69SDag-Erling Smørgrav 	dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
1674d4af9e69SDag-Erling Smørgrav 
1675d4af9e69SDag-Erling Smørgrav 	/* string arguments */
1676d4af9e69SDag-Erling Smørgrav 	dump_cfg_string(sPidFile, o->pid_file);
1677d4af9e69SDag-Erling Smørgrav 	dump_cfg_string(sXAuthLocation, o->xauth_location);
1678d4af9e69SDag-Erling Smørgrav 	dump_cfg_string(sCiphers, o->ciphers);
1679d4af9e69SDag-Erling Smørgrav 	dump_cfg_string(sMacs, o->macs);
1680d4af9e69SDag-Erling Smørgrav 	dump_cfg_string(sBanner, o->banner);
1681d4af9e69SDag-Erling Smørgrav 	dump_cfg_string(sAuthorizedKeysFile, o->authorized_keys_file);
1682d4af9e69SDag-Erling Smørgrav 	dump_cfg_string(sAuthorizedKeysFile2, o->authorized_keys_file2);
1683d4af9e69SDag-Erling Smørgrav 	dump_cfg_string(sForceCommand, o->adm_forced_command);
1684b15c8340SDag-Erling Smørgrav 	dump_cfg_string(sChrootDirectory, o->chroot_directory);
1685b15c8340SDag-Erling Smørgrav 	dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys);
1686b15c8340SDag-Erling Smørgrav 	dump_cfg_string(sRevokedKeys, o->revoked_keys_file);
1687d4af9e69SDag-Erling Smørgrav 
1688d4af9e69SDag-Erling Smørgrav 	/* string arguments requiring a lookup */
1689d4af9e69SDag-Erling Smørgrav 	dump_cfg_string(sLogLevel, log_level_name(o->log_level));
1690d4af9e69SDag-Erling Smørgrav 	dump_cfg_string(sLogFacility, log_facility_name(o->log_facility));
1691d4af9e69SDag-Erling Smørgrav 
1692d4af9e69SDag-Erling Smørgrav 	/* string array arguments */
1693d4af9e69SDag-Erling Smørgrav 	dump_cfg_strarray(sHostKeyFile, o->num_host_key_files,
1694d4af9e69SDag-Erling Smørgrav 	     o->host_key_files);
1695b15c8340SDag-Erling Smørgrav 	dump_cfg_strarray(sHostKeyFile, o->num_host_cert_files,
1696b15c8340SDag-Erling Smørgrav 	     o->host_cert_files);
1697d4af9e69SDag-Erling Smørgrav 	dump_cfg_strarray(sAllowUsers, o->num_allow_users, o->allow_users);
1698d4af9e69SDag-Erling Smørgrav 	dump_cfg_strarray(sDenyUsers, o->num_deny_users, o->deny_users);
1699d4af9e69SDag-Erling Smørgrav 	dump_cfg_strarray(sAllowGroups, o->num_allow_groups, o->allow_groups);
1700d4af9e69SDag-Erling Smørgrav 	dump_cfg_strarray(sDenyGroups, o->num_deny_groups, o->deny_groups);
1701d4af9e69SDag-Erling Smørgrav 	dump_cfg_strarray(sAcceptEnv, o->num_accept_env, o->accept_env);
1702d4af9e69SDag-Erling Smørgrav 
1703d4af9e69SDag-Erling Smørgrav 	/* other arguments */
1704d4af9e69SDag-Erling Smørgrav 	for (i = 0; i < o->num_subsystems; i++)
1705d4af9e69SDag-Erling Smørgrav 		printf("subsystem %s %s\n", o->subsystem_name[i],
1706d4af9e69SDag-Erling Smørgrav 		    o->subsystem_args[i]);
1707d4af9e69SDag-Erling Smørgrav 
1708d4af9e69SDag-Erling Smørgrav 	printf("maxstartups %d:%d:%d\n", o->max_startups_begin,
1709d4af9e69SDag-Erling Smørgrav 	    o->max_startups_rate, o->max_startups);
1710d4af9e69SDag-Erling Smørgrav 
1711d4af9e69SDag-Erling Smørgrav 	for (i = 0; tunmode_desc[i].val != -1; i++)
1712d4af9e69SDag-Erling Smørgrav 		if (tunmode_desc[i].val == o->permit_tun) {
1713d4af9e69SDag-Erling Smørgrav 			s = tunmode_desc[i].text;
1714d4af9e69SDag-Erling Smørgrav 			break;
1715d4af9e69SDag-Erling Smørgrav 		}
1716d4af9e69SDag-Erling Smørgrav 	dump_cfg_string(sPermitTunnel, s);
1717d4af9e69SDag-Erling Smørgrav 
1718d4af9e69SDag-Erling Smørgrav 	channel_print_adm_permitted_opens();
1719d4af9e69SDag-Erling Smørgrav }
1720