xref: /netbsd-src/crypto/external/bsd/openssh/dist/readconf.c (revision 9469f4f13c84743995b7d51c506f9c9849ba30de)
1 /*	$NetBSD: readconf.c,v 1.47 2024/09/24 21:32:18 christos Exp $	*/
2 /* $OpenBSD: readconf.c,v 1.390 2024/09/15 00:57:36 djm Exp $ */
3 
4 /*
5  * Author: Tatu Ylonen <ylo@cs.hut.fi>
6  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
7  *                    All rights reserved
8  * Functions for reading the configuration files.
9  *
10  * As far as I am concerned, the code I have written for this software
11  * can be used freely for any purpose.  Any derived versions of this
12  * software must be clearly marked as such, and if the derived work is
13  * incompatible with the protocol description in the RFC file, it must be
14  * called by a name other than "ssh" or "Secure Shell".
15  */
16 
17 #include "includes.h"
18 __RCSID("$NetBSD: readconf.c,v 1.47 2024/09/24 21:32:18 christos Exp $");
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <sys/socket.h>
22 #include <sys/wait.h>
23 #include <sys/un.h>
24 
25 #include <net/if.h>
26 #include <netinet/in.h>
27 #include <netinet/ip.h>
28 
29 #include <ctype.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <glob.h>
33 #include <ifaddrs.h>
34 #include <netdb.h>
35 #include <paths.h>
36 #include <pwd.h>
37 #include <signal.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <stdarg.h>
41 #include <unistd.h>
42 #include <limits.h>
43 #include <util.h>
44 #include <vis.h>
45 
46 #include "xmalloc.h"
47 #include "ssh.h"
48 #include "sshbuf.h"
49 #include "ssherr.h"
50 #include "cipher.h"
51 #include "pathnames.h"
52 #include "log.h"
53 #include "sshkey.h"
54 #include "misc.h"
55 #include "readconf.h"
56 #include "match.h"
57 #include "kex.h"
58 #include "mac.h"
59 #include "fmt_scaled.h"
60 #include "uidswap.h"
61 #include "myproposal.h"
62 #include "digest.h"
63 
64 /* Format of the configuration file:
65 
66    # Configuration data is parsed as follows:
67    #  1. command line options
68    #  2. user-specific file
69    #  3. system-wide file
70    # Any configuration value is only changed the first time it is set.
71    # Thus, host-specific definitions should be at the beginning of the
72    # configuration file, and defaults at the end.
73 
74    # Host-specific declarations.  These may override anything above.  A single
75    # host may match multiple declarations; these are processed in the order
76    # that they are given in.
77 
78    Host *.ngs.fi ngs.fi
79      User foo
80 
81    Host fake.com
82      Hostname another.host.name.real.org
83      User blaah
84      Port 34289
85      ForwardX11 no
86      ForwardAgent no
87 
88    Host books.com
89      RemoteForward 9999 shadows.cs.hut.fi:9999
90      Ciphers 3des-cbc
91 
92    Host fascist.blob.com
93      Port 23123
94      User tylonen
95      PasswordAuthentication no
96 
97    Host puukko.hut.fi
98      User t35124p
99      ProxyCommand ssh-proxy %h %p
100 
101    Host *.fr
102      PublicKeyAuthentication no
103 
104    Host *.su
105      Ciphers aes128-ctr
106      PasswordAuthentication no
107 
108    Host vpn.fake.com
109      Tunnel yes
110      TunnelDevice 3
111 
112    # Defaults for various options
113    Host *
114      ForwardAgent no
115      ForwardX11 no
116      PasswordAuthentication yes
117      StrictHostKeyChecking yes
118      TcpKeepAlive no
119      IdentityFile ~/.ssh/identity
120      Port 22
121      EscapeChar ~
122 
123 */
124 
125 static int read_config_file_depth(const char *filename, struct passwd *pw,
126     const char *host, const char *original_host, Options *options,
127     int flags, int *activep, int *want_final_pass, int depth);
128 static int process_config_line_depth(Options *options, struct passwd *pw,
129     const char *host, const char *original_host, char *line,
130     const char *filename, int linenum, int *activep, int flags,
131     int *want_final_pass, int depth);
132 
133 /* Keyword tokens. */
134 
135 typedef enum {
136 	oBadOption,
137 	oHost, oMatch, oInclude, oTag,
138 	oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
139 	oGatewayPorts, oExitOnForwardFailure,
140 	oPasswordAuthentication,
141 	oXAuthLocation,
142 #if defined(KRB4) || defined(KRB5)
143 	oKerberosAuthentication,
144 #endif
145 #if defined(AFS) || defined(KRB5)
146 	oKerberosTgtPassing,
147 #endif
148 #ifdef AFS
149 	oAFSTokenPassing,
150 #endif
151 	oIdentityFile, oHostname, oPort, oRemoteForward, oLocalForward,
152 	oPermitRemoteOpen,
153 	oCertificateFile, oAddKeysToAgent, oIdentityAgent,
154 	oUser, oEscapeChar, oProxyCommand,
155 	oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
156 	oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
157 	oTCPKeepAlive, oNumberOfPasswordPrompts,
158 	oLogFacility, oLogLevel, oLogVerbose, oCiphers, oMacs,
159 	oPubkeyAuthentication,
160 	oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
161 	oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
162 	oHostKeyAlgorithms, oBindAddress, oBindInterface, oPKCS11Provider,
163 	oIPv6PreferTemporary,
164 	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
165 	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
166 	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
167 	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
168 	oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist,
169 	oHashKnownHosts,
170 	oTunnel, oTunnelDevice,
171 	oLocalCommand, oPermitLocalCommand, oRemoteCommand,
172 	oVisualHostKey,
173 	oKexAlgorithms, oIPQoS, oRequestTTY, oSessionType, oStdinNull,
174 	oForkAfterAuthentication, oIgnoreUnknown, oProxyUseFdpass,
175 	oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
176 	oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
177 	oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
178 	oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms,
179 	oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump,
180 	oSecurityKeyProvider, oKnownHostsCommand, oRequiredRSASize,
181 	oEnableEscapeCommandline, oObscureKeystrokeTiming, oChannelTimeout,
182 	oNoneEnabled, oTcpRcvBufPoll, oTcpRcvBuf, oNoneSwitch, oHPNDisabled,
183 	oHPNBufferSize,
184 	oSendVersionFirst,
185 	oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
186 } OpCodes;
187 
188 /* Textual representations of the tokens. */
189 
190 static struct {
191 	const char *name;
192 	OpCodes opcode;
193 } keywords[] = {
194 	/* Deprecated options */
195 	{ "protocol", oIgnore }, /* NB. silently ignored */
196 	{ "cipher", oDeprecated },
197 	{ "fallbacktorsh", oDeprecated },
198 	{ "globalknownhostsfile2", oDeprecated },
199 	{ "rhostsauthentication", oDeprecated },
200 	{ "userknownhostsfile2", oDeprecated },
201 	{ "useroaming", oDeprecated },
202 	{ "usersh", oDeprecated },
203 	{ "useprivilegedport", oDeprecated },
204 
205 	/* Unsupported options */
206 #ifdef AFS
207 	{ "afstokenpassing", oAFSTokenPassing },
208 #else
209 	{ "afstokenpassing", oUnsupported },
210 #endif
211 #if defined(KRB4) || defined(KRB5)
212 	{ "kerberosauthentication", oKerberosAuthentication },
213 #else
214 	{ "kerberosauthentication", oUnsupported },
215 #endif
216 #if defined(AFS) || defined(KRB5)
217 	{ "kerberostgtpassing", oKerberosTgtPassing },
218 	{ "kerberos5tgtpassing", oKerberosTgtPassing },		/* alias */
219 	{ "kerberos4tgtpassing", oKerberosTgtPassing },		/* alias */
220 #else
221 	{ "kerberostgtpassing", oUnsupported },
222 	{ "kerberos5tgtpassing", oUnsupported },
223 	{ "kerberos4tgtpassing", oUnsupported },
224 #endif
225 	{ "rsaauthentication", oUnsupported },
226 	{ "rhostsrsaauthentication", oUnsupported },
227 	{ "compressionlevel", oUnsupported },
228 
229 	/* Sometimes-unsupported options */
230 #if defined(GSSAPI)
231 	{ "gssapiauthentication", oGssAuthentication },
232 	{ "gssapidelegatecredentials", oGssDelegateCreds },
233 # else
234 	{ "gssapiauthentication", oUnsupported },
235 	{ "gssapidelegatecredentials", oUnsupported },
236 #endif
237 #ifdef ENABLE_PKCS11
238 	{ "pkcs11provider", oPKCS11Provider },
239 	{ "smartcarddevice", oPKCS11Provider },
240 # else
241 	{ "smartcarddevice", oUnsupported },
242 	{ "pkcs11provider", oUnsupported },
243 #endif
244 
245 	{ "forwardagent", oForwardAgent },
246 	{ "forwardx11", oForwardX11 },
247 	{ "forwardx11trusted", oForwardX11Trusted },
248 	{ "forwardx11timeout", oForwardX11Timeout },
249 	{ "exitonforwardfailure", oExitOnForwardFailure },
250 	{ "xauthlocation", oXAuthLocation },
251 	{ "gatewayports", oGatewayPorts },
252 	{ "passwordauthentication", oPasswordAuthentication },
253 	{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
254 	{ "kbdinteractivedevices", oKbdInteractiveDevices },
255 	{ "challengeresponseauthentication", oKbdInteractiveAuthentication }, /* alias */
256 	{ "skeyauthentication", oKbdInteractiveAuthentication }, /* alias */
257 	{ "tisauthentication", oKbdInteractiveAuthentication },  /* alias */
258 	{ "pubkeyauthentication", oPubkeyAuthentication },
259 	{ "dsaauthentication", oPubkeyAuthentication },		    /* alias */
260 	{ "hostbasedauthentication", oHostbasedAuthentication },
261 #if defined(GSSAPI)
262 	{ "gssapiauthentication", oGssAuthentication },
263 	{ "gssapidelegatecredentials", oGssDelegateCreds },
264 #else
265 	{ "gssapiauthentication", oUnsupported },
266 	{ "gssapidelegatecredentials", oUnsupported },
267 #endif
268 	{ "identityfile", oIdentityFile },
269 	{ "identityfile2", oIdentityFile },			/* obsolete */
270 	{ "identitiesonly", oIdentitiesOnly },
271 	{ "certificatefile", oCertificateFile },
272 	{ "addkeystoagent", oAddKeysToAgent },
273 	{ "identityagent", oIdentityAgent },
274 	{ "hostname", oHostname },
275 	{ "hostkeyalias", oHostKeyAlias },
276 	{ "proxycommand", oProxyCommand },
277 	{ "port", oPort },
278 	{ "ciphers", oCiphers },
279 	{ "macs", oMacs },
280 	{ "remoteforward", oRemoteForward },
281 	{ "localforward", oLocalForward },
282 	{ "permitremoteopen", oPermitRemoteOpen },
283 	{ "user", oUser },
284 	{ "host", oHost },
285 	{ "match", oMatch },
286 	{ "tag", oTag },
287 	{ "escapechar", oEscapeChar },
288 	{ "globalknownhostsfile", oGlobalKnownHostsFile },
289 	{ "userknownhostsfile", oUserKnownHostsFile },
290 	{ "connectionattempts", oConnectionAttempts },
291 	{ "batchmode", oBatchMode },
292 	{ "checkhostip", oCheckHostIP },
293 	{ "stricthostkeychecking", oStrictHostKeyChecking },
294 	{ "compression", oCompression },
295 	{ "tcpkeepalive", oTCPKeepAlive },
296 	{ "keepalive", oTCPKeepAlive },				/* obsolete */
297 	{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
298 	{ "syslogfacility", oLogFacility },
299 	{ "loglevel", oLogLevel },
300 	{ "logverbose", oLogVerbose },
301 	{ "dynamicforward", oDynamicForward },
302 	{ "preferredauthentications", oPreferredAuthentications },
303 	{ "hostkeyalgorithms", oHostKeyAlgorithms },
304 	{ "casignaturealgorithms", oCASignatureAlgorithms },
305 	{ "bindaddress", oBindAddress },
306 	{ "bindinterface", oBindInterface },
307 	{ "ipv6prefertemporary", oIPv6PreferTemporary },
308 	{ "clearallforwardings", oClearAllForwardings },
309 	{ "enablesshkeysign", oEnableSSHKeysign },
310 	{ "verifyhostkeydns", oVerifyHostKeyDNS },
311 	{ "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
312 	{ "rekeylimit", oRekeyLimit },
313 	{ "connecttimeout", oConnectTimeout },
314 	{ "addressfamily", oAddressFamily },
315 	{ "serveraliveinterval", oServerAliveInterval },
316 	{ "serveralivecountmax", oServerAliveCountMax },
317 	{ "sendenv", oSendEnv },
318 	{ "setenv", oSetEnv },
319 	{ "controlpath", oControlPath },
320 	{ "controlmaster", oControlMaster },
321 	{ "controlpersist", oControlPersist },
322 	{ "hashknownhosts", oHashKnownHosts },
323 	{ "include", oInclude },
324 	{ "tunnel", oTunnel },
325 	{ "tunneldevice", oTunnelDevice },
326 	{ "localcommand", oLocalCommand },
327 	{ "permitlocalcommand", oPermitLocalCommand },
328 	{ "remotecommand", oRemoteCommand },
329 	{ "visualhostkey", oVisualHostKey },
330 	{ "kexalgorithms", oKexAlgorithms },
331 	{ "ipqos", oIPQoS },
332 	{ "requesttty", oRequestTTY },
333 	{ "sessiontype", oSessionType },
334 	{ "stdinnull", oStdinNull },
335 	{ "forkafterauthentication", oForkAfterAuthentication },
336 	{ "proxyusefdpass", oProxyUseFdpass },
337 	{ "canonicaldomains", oCanonicalDomains },
338 	{ "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
339 	{ "canonicalizehostname", oCanonicalizeHostname },
340 	{ "canonicalizemaxdots", oCanonicalizeMaxDots },
341 	{ "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
342 	{ "streamlocalbindmask", oStreamLocalBindMask },
343 	{ "streamlocalbindunlink", oStreamLocalBindUnlink },
344 	{ "revokedhostkeys", oRevokedHostKeys },
345 	{ "fingerprinthash", oFingerprintHash },
346 	{ "updatehostkeys", oUpdateHostkeys },
347 	{ "hostbasedacceptedalgorithms", oHostbasedAcceptedAlgorithms },
348 	{ "hostbasedkeytypes", oHostbasedAcceptedAlgorithms }, /* obsolete */
349 	{ "pubkeyacceptedalgorithms", oPubkeyAcceptedAlgorithms },
350 	{ "pubkeyacceptedkeytypes", oPubkeyAcceptedAlgorithms }, /* obsolete */
351 	{ "proxyjump", oProxyJump },
352 	{ "noneenabled", oNoneEnabled },
353 	{ "tcprcvbufpoll", oTcpRcvBufPoll },
354 	{ "tcprcvbuf", oTcpRcvBuf },
355 	{ "noneswitch", oNoneSwitch },
356 	{ "hpndisabled", oHPNDisabled },
357 	{ "hpnbuffersize", oHPNBufferSize },
358 	{ "sendversionfirst", oSendVersionFirst },
359 	{ "ignoreunknown", oIgnoreUnknown },
360 	{ "proxyjump", oProxyJump },
361 	{ "securitykeyprovider", oSecurityKeyProvider },
362 	{ "knownhostscommand", oKnownHostsCommand },
363 	{ "requiredrsasize", oRequiredRSASize },
364 	{ "enableescapecommandline", oEnableEscapeCommandline },
365 	{ "obscurekeystroketiming", oObscureKeystrokeTiming },
366 	{ "channeltimeout", oChannelTimeout },
367 
368 	{ NULL, oBadOption }
369 };
370 
371 static const char *lookup_opcode_name(OpCodes code);
372 
373 const char *
374 kex_default_pk_alg(void)
375 {
376 	static char *pkalgs;
377 
378 	if (pkalgs == NULL) {
379 		char *all_key;
380 
381 		all_key = sshkey_alg_list(0, 0, 1, ',');
382 		pkalgs = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
383 		free(all_key);
384 	}
385 	return pkalgs;
386 }
387 
388 char *
389 ssh_connection_hash(const char *thishost, const char *host, const char *portstr,
390     const char *user, const char *jumphost)
391 {
392 	struct ssh_digest_ctx *md;
393 	u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
394 
395 	if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL ||
396 	    ssh_digest_update(md, thishost, strlen(thishost)) < 0 ||
397 	    ssh_digest_update(md, host, strlen(host)) < 0 ||
398 	    ssh_digest_update(md, portstr, strlen(portstr)) < 0 ||
399 	    ssh_digest_update(md, user, strlen(user)) < 0 ||
400 	    ssh_digest_update(md, jumphost, strlen(jumphost)) < 0 ||
401 	    ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0)
402 		fatal_f("mux digest failed");
403 	ssh_digest_free(md);
404 	return tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1));
405 }
406 
407 /*
408  * Adds a local TCP/IP port forward to options.  Never returns if there is an
409  * error.
410  */
411 
412 void
413 add_local_forward(Options *options, const struct Forward *newfwd)
414 {
415 	struct Forward *fwd;
416 	int i;
417 
418 	/* Don't add duplicates */
419 	for (i = 0; i < options->num_local_forwards; i++) {
420 		if (forward_equals(newfwd, options->local_forwards + i))
421 			return;
422 	}
423 	options->local_forwards = xreallocarray(options->local_forwards,
424 	    options->num_local_forwards + 1,
425 	    sizeof(*options->local_forwards));
426 	fwd = &options->local_forwards[options->num_local_forwards++];
427 
428 	fwd->listen_host = newfwd->listen_host;
429 	fwd->listen_port = newfwd->listen_port;
430 	fwd->listen_path = newfwd->listen_path;
431 	fwd->connect_host = newfwd->connect_host;
432 	fwd->connect_port = newfwd->connect_port;
433 	fwd->connect_path = newfwd->connect_path;
434 }
435 
436 /*
437  * Adds a remote TCP/IP port forward to options.  Never returns if there is
438  * an error.
439  */
440 
441 void
442 add_remote_forward(Options *options, const struct Forward *newfwd)
443 {
444 	struct Forward *fwd;
445 	int i;
446 
447 	/* Don't add duplicates */
448 	for (i = 0; i < options->num_remote_forwards; i++) {
449 		if (forward_equals(newfwd, options->remote_forwards + i))
450 			return;
451 	}
452 	options->remote_forwards = xreallocarray(options->remote_forwards,
453 	    options->num_remote_forwards + 1,
454 	    sizeof(*options->remote_forwards));
455 	fwd = &options->remote_forwards[options->num_remote_forwards++];
456 
457 	fwd->listen_host = newfwd->listen_host;
458 	fwd->listen_port = newfwd->listen_port;
459 	fwd->listen_path = newfwd->listen_path;
460 	fwd->connect_host = newfwd->connect_host;
461 	fwd->connect_port = newfwd->connect_port;
462 	fwd->connect_path = newfwd->connect_path;
463 	fwd->handle = newfwd->handle;
464 	fwd->allocated_port = 0;
465 }
466 
467 static void
468 clear_forwardings(Options *options)
469 {
470 	int i;
471 
472 	for (i = 0; i < options->num_local_forwards; i++) {
473 		free(options->local_forwards[i].listen_host);
474 		free(options->local_forwards[i].listen_path);
475 		free(options->local_forwards[i].connect_host);
476 		free(options->local_forwards[i].connect_path);
477 	}
478 	if (options->num_local_forwards > 0) {
479 		free(options->local_forwards);
480 		options->local_forwards = NULL;
481 	}
482 	options->num_local_forwards = 0;
483 	for (i = 0; i < options->num_remote_forwards; i++) {
484 		free(options->remote_forwards[i].listen_host);
485 		free(options->remote_forwards[i].listen_path);
486 		free(options->remote_forwards[i].connect_host);
487 		free(options->remote_forwards[i].connect_path);
488 	}
489 	if (options->num_remote_forwards > 0) {
490 		free(options->remote_forwards);
491 		options->remote_forwards = NULL;
492 	}
493 	options->num_remote_forwards = 0;
494 	options->tun_open = SSH_TUNMODE_NO;
495 }
496 
497 void
498 add_certificate_file(Options *options, const char *path, int userprovided)
499 {
500 	int i;
501 
502 	if (options->num_certificate_files >= SSH_MAX_CERTIFICATE_FILES)
503 		fatal("Too many certificate files specified (max %d)",
504 		    SSH_MAX_CERTIFICATE_FILES);
505 
506 	/* Avoid registering duplicates */
507 	for (i = 0; i < options->num_certificate_files; i++) {
508 		if (options->certificate_file_userprovided[i] == userprovided &&
509 		    strcmp(options->certificate_files[i], path) == 0) {
510 			debug2_f("ignoring duplicate key %s", path);
511 			return;
512 		}
513 	}
514 
515 	options->certificate_file_userprovided[options->num_certificate_files] =
516 	    userprovided;
517 	options->certificate_files[options->num_certificate_files++] =
518 	    xstrdup(path);
519 }
520 
521 void
522 add_identity_file(Options *options, const char *dir, const char *filename,
523     int userprovided)
524 {
525 	char *path;
526 	int i;
527 
528 	if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
529 		fatal("Too many identity files specified (max %d)",
530 		    SSH_MAX_IDENTITY_FILES);
531 
532 	if (dir == NULL) /* no dir, filename is absolute */
533 		path = xstrdup(filename);
534 	else if (xasprintf(&path, "%s%s", dir, filename) >= PATH_MAX)
535 		fatal("Identity file path %s too long", path);
536 
537 	/* Avoid registering duplicates */
538 	for (i = 0; i < options->num_identity_files; i++) {
539 		if (options->identity_file_userprovided[i] == userprovided &&
540 		    strcmp(options->identity_files[i], path) == 0) {
541 			debug2_f("ignoring duplicate key %s", path);
542 			free(path);
543 			return;
544 		}
545 	}
546 
547 	options->identity_file_userprovided[options->num_identity_files] =
548 	    userprovided;
549 	options->identity_files[options->num_identity_files++] = path;
550 }
551 
552 int
553 default_ssh_port(void)
554 {
555 	static int port;
556 	struct servent *sp;
557 
558 	if (port == 0) {
559 		sp = getservbyname(SSH_SERVICE_NAME, "tcp");
560 		port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
561 	}
562 	return port;
563 }
564 
565 /*
566  * Execute a command in a shell.
567  * Return its exit status or -1 on abnormal exit.
568  */
569 static int
570 execute_in_shell(const char *cmd)
571 {
572 	const char *shell;
573 	pid_t pid;
574 	int status;
575 
576 	if ((shell = getenv("SHELL")) == NULL)
577 		shell = _PATH_BSHELL;
578 
579 	if (access(shell, X_OK) == -1) {
580 		fatal("Shell \"%s\" is not executable: %s",
581 		    shell, strerror(errno));
582 	}
583 
584 	debug("Executing command: '%.500s'", cmd);
585 
586 	/* Fork and execute the command. */
587 	if ((pid = fork()) == 0) {
588 		char *argv[4];
589 
590 		if (stdfd_devnull(1, 1, 0) == -1)
591 			fatal_f("stdfd_devnull failed");
592 		closefrom(STDERR_FILENO + 1);
593 
594 		argv[0] = __UNCONST(shell);
595 		argv[1] = __UNCONST("-c");
596 		argv[2] = xstrdup(cmd);
597 		argv[3] = NULL;
598 
599 		execv(argv[0], argv);
600 		error("Unable to execute '%.100s': %s", cmd, strerror(errno));
601 		/* Die with signal to make this error apparent to parent. */
602 		ssh_signal(SIGTERM, SIG_DFL);
603 		kill(getpid(), SIGTERM);
604 		_exit(1);
605 	}
606 	/* Parent. */
607 	if (pid == -1)
608 		fatal_f("fork: %.100s", strerror(errno));
609 
610 	while (waitpid(pid, &status, 0) == -1) {
611 		if (errno != EINTR && errno != EAGAIN)
612 			fatal_f("waitpid: %s", strerror(errno));
613 	}
614 	if (!WIFEXITED(status)) {
615 		error("command '%.100s' exited abnormally", cmd);
616 		return -1;
617 	}
618 	debug3("command returned status %d", WEXITSTATUS(status));
619 	return WEXITSTATUS(status);
620 }
621 
622 /*
623  * Check whether a local network interface address appears in CIDR pattern-
624  * list 'addrlist'. Returns 1 if matched or 0 otherwise.
625  */
626 static int
627 check_match_ifaddrs(const char *addrlist)
628 {
629 	struct ifaddrs *ifa, *ifaddrs = NULL;
630 	int r, found = 0;
631 	char addr[NI_MAXHOST];
632 	socklen_t salen;
633 
634 	if (getifaddrs(&ifaddrs) != 0) {
635 		error("match localnetwork: getifaddrs failed: %s",
636 		    strerror(errno));
637 		return 0;
638 	}
639 	for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
640 		if (ifa->ifa_addr == NULL || ifa->ifa_name == NULL ||
641 		    (ifa->ifa_flags & IFF_UP) == 0)
642 			continue;
643 		switch (ifa->ifa_addr->sa_family) {
644 		case AF_INET:
645 			salen = sizeof(struct sockaddr_in);
646 			break;
647 		case AF_INET6:
648 			salen = sizeof(struct sockaddr_in6);
649 			break;
650 		case AF_LINK:
651 			/* ignore */
652 			continue;
653 		default:
654 			debug2_f("interface %s: unsupported address family %d",
655 			    ifa->ifa_name, ifa->ifa_addr->sa_family);
656 			continue;
657 		}
658 		if ((r = getnameinfo(ifa->ifa_addr, salen, addr, sizeof(addr),
659 		    NULL, 0, NI_NUMERICHOST)) != 0) {
660 			debug2_f("interface %s getnameinfo failed: %s",
661 			    ifa->ifa_name, gai_strerror(r));
662 			continue;
663 		}
664 		debug3_f("interface %s addr %s", ifa->ifa_name, addr);
665 		if (addr_match_cidr_list(addr, addrlist) == 1) {
666 			debug3_f("matched interface %s: address %s in %s",
667 			    ifa->ifa_name, addr, addrlist);
668 			found = 1;
669 			break;
670 		}
671 	}
672 	freeifaddrs(ifaddrs);
673 	return found;
674 }
675 
676 /*
677  * Expand a "match exec" command or an Include path, caller must free returned
678  * value.
679  */
680 static char *
681 expand_match_exec_or_include_path(const char *path, Options *options,
682     struct passwd *pw, const char *host_arg, const char *original_host,
683     int final_pass, int is_include_path)
684 {
685 	char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
686 	char uidstr[32], *conn_hash_hex, *keyalias, *ruser;
687 	const char *jmphost;
688 	char *host, *ret;
689 	int port;
690 
691 	port = options->port <= 0 ? default_ssh_port() : options->port;
692 	ruser = options->user == NULL ? pw->pw_name : options->user;
693 	if (final_pass) {
694 		host = xstrdup(options->hostname);
695 	} else if (options->hostname != NULL) {
696 		/* NB. Please keep in sync with ssh.c:main() */
697 		host = percent_expand(options->hostname,
698 		    "h", host_arg, (char *)NULL);
699 	} else {
700 		host = xstrdup(host_arg);
701 	}
702 	if (gethostname(thishost, sizeof(thishost)) == -1)
703 		fatal("gethostname: %s", strerror(errno));
704 	jmphost = option_clear_or_none(options->jump_host) ?
705 	    "" : options->jump_host;
706 	strlcpy(shorthost, thishost, sizeof(shorthost));
707 	shorthost[strcspn(thishost, ".")] = '\0';
708 	snprintf(portstr, sizeof(portstr), "%d", port);
709 	snprintf(uidstr, sizeof(uidstr), "%llu",
710 	    (unsigned long long)pw->pw_uid);
711 	conn_hash_hex = ssh_connection_hash(thishost, host,
712 	    portstr, ruser, jmphost);
713 	keyalias = options->host_key_alias ?  options->host_key_alias : host;
714 
715 	ret = (is_include_path ? percent_dollar_expand : percent_expand)(path,
716 	    "C", conn_hash_hex,
717 	    "L", shorthost,
718 	    "d", pw->pw_dir,
719 	    "h", host,
720 	    "k", keyalias,
721 	    "l", thishost,
722 	    "n", original_host,
723 	    "p", portstr,
724 	    "r", ruser,
725 	    "u", pw->pw_name,
726 	    "i", uidstr,
727 	    "j", jmphost,
728 	    (char *)NULL);
729 	free(host);
730 	free(conn_hash_hex);
731 	return ret;
732 }
733 
734 /*
735  * Parse and execute a Match directive.
736  */
737 static int
738 match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp,
739     struct passwd *pw, const char *host_arg, const char *original_host,
740     int final_pass, int *want_final_pass, const char *filename, int linenum)
741 {
742 	char *arg, *oattrib, *attrib, *cmd, *host, *criteria;
743 	const char *ruser;
744 	int r, this_result, result = 1, attributes = 0, negate;
745 
746 	/*
747 	 * Configuration is likely to be incomplete at this point so we
748 	 * must be prepared to use default values.
749 	 */
750 	ruser = options->user == NULL ? pw->pw_name : options->user;
751 	if (final_pass) {
752 		host = xstrdup(options->hostname);
753 	} else if (options->hostname != NULL) {
754 		/* NB. Please keep in sync with ssh.c:main() */
755 		host = percent_expand(options->hostname,
756 		    "h", host_arg, (char *)NULL);
757 	} else {
758 		host = xstrdup(host_arg);
759 	}
760 
761 	debug2("checking match for '%s' host %s originally %s",
762 	    full_line, host, original_host);
763 	while ((oattrib = attrib = argv_next(acp, avp)) != NULL) {
764 		/* Terminate on comment */
765 		if (*attrib == '#') {
766 			argv_consume(acp);
767 			break;
768 		}
769 		arg = criteria = NULL;
770 		this_result = 1;
771 		if ((negate = (attrib[0] == '!')))
772 			attrib++;
773 		/* Criterion "all" has no argument and must appear alone */
774 		if (strcasecmp(attrib, "all") == 0) {
775 			if (attributes > 1 ||
776 			    ((arg = argv_next(acp, avp)) != NULL &&
777 			    *arg != '\0' && *arg != '#')) {
778 				error("%.200s line %d: '%s' cannot be combined "
779 				    "with other Match attributes",
780 				    filename, linenum, oattrib);
781 				result = -1;
782 				goto out;
783 			}
784 			if (arg != NULL && *arg == '#')
785 				argv_consume(acp); /* consume remaining args */
786 			if (result)
787 				result = negate ? 0 : 1;
788 			goto out;
789 		}
790 		attributes++;
791 		/* criteria "final" and "canonical" have no argument */
792 		if (strcasecmp(attrib, "canonical") == 0 ||
793 		    strcasecmp(attrib, "final") == 0) {
794 			/*
795 			 * If the config requests "Match final" then remember
796 			 * this so we can perform a second pass later.
797 			 */
798 			if (strcasecmp(attrib, "final") == 0 &&
799 			    want_final_pass != NULL)
800 				*want_final_pass = 1;
801 			r = !!final_pass;  /* force bitmask member to boolean */
802 			if (r == (negate ? 1 : 0))
803 				this_result = result = 0;
804 			debug3("%.200s line %d: %smatched '%s'",
805 			    filename, linenum,
806 			    this_result ? "" : "not ", oattrib);
807 			continue;
808 		}
809 		/* All other criteria require an argument */
810 		if ((arg = argv_next(acp, avp)) == NULL ||
811 		    *arg == '\0' || *arg == '#') {
812 			error("Missing Match criteria for %s", attrib);
813 			result = -1;
814 			goto out;
815 		}
816 		if (strcasecmp(attrib, "host") == 0) {
817 			criteria = xstrdup(host);
818 			r = match_hostname(host, arg) == 1;
819 			if (r == (negate ? 1 : 0))
820 				this_result = result = 0;
821 		} else if (strcasecmp(attrib, "originalhost") == 0) {
822 			criteria = xstrdup(original_host);
823 			r = match_hostname(original_host, arg) == 1;
824 			if (r == (negate ? 1 : 0))
825 				this_result = result = 0;
826 		} else if (strcasecmp(attrib, "user") == 0) {
827 			criteria = xstrdup(ruser);
828 			r = match_pattern_list(ruser, arg, 0) == 1;
829 			if (r == (negate ? 1 : 0))
830 				this_result = result = 0;
831 		} else if (strcasecmp(attrib, "localuser") == 0) {
832 			criteria = xstrdup(pw->pw_name);
833 			r = match_pattern_list(pw->pw_name, arg, 0) == 1;
834 			if (r == (negate ? 1 : 0))
835 				this_result = result = 0;
836 		} else if (strcasecmp(attrib, "localnetwork") == 0) {
837 			if (addr_match_cidr_list(NULL, arg) == -1) {
838 				/* Error already printed */
839 				result = -1;
840 				goto out;
841 			}
842 			r = check_match_ifaddrs(arg) == 1;
843 			if (r == (negate ? 1 : 0))
844 				this_result = result = 0;
845 		} else if (strcasecmp(attrib, "tagged") == 0) {
846 			criteria = xstrdup(options->tag == NULL ? "" :
847 			    options->tag);
848 			r = match_pattern_list(criteria, arg, 0) == 1;
849 			if (r == (negate ? 1 : 0))
850 				this_result = result = 0;
851 		} else if (strcasecmp(attrib, "exec") == 0) {
852 			if ((cmd = expand_match_exec_or_include_path(arg,
853 			    options, pw, host_arg, original_host,
854 			    final_pass, 0)) == NULL) {
855 				fatal("%.200s line %d: failed to expand match "
856 				    "exec '%.100s'", filename, linenum, arg);
857 			}
858 			if (result != 1) {
859 				/* skip execution if prior predicate failed */
860 				debug3("%.200s line %d: skipped exec "
861 				    "\"%.100s\"", filename, linenum, cmd);
862 				free(cmd);
863 				continue;
864 			}
865 			r = execute_in_shell(cmd);
866 			if (r == -1) {
867 				fatal("%.200s line %d: match exec "
868 				    "'%.100s' error", filename,
869 				    linenum, cmd);
870 			}
871 			criteria = xstrdup(cmd);
872 			free(cmd);
873 			/* Force exit status to boolean */
874 			r = r == 0;
875 			if (r == (negate ? 1 : 0))
876 				this_result = result = 0;
877 		} else {
878 			error("Unsupported Match attribute %s", attrib);
879 			result = -1;
880 			goto out;
881 		}
882 		debug3("%.200s line %d: %smatched '%s%s%.100s%s' ",
883 		    filename, linenum, this_result ? "": "not ", oattrib,
884 		    criteria == NULL ? "" : " \"",
885 		    criteria == NULL ? "" : criteria,
886 		    criteria == NULL ? "" : "\"");
887 		free(criteria);
888 	}
889 	if (attributes == 0) {
890 		error("One or more attributes required for Match");
891 		result = -1;
892 		goto out;
893 	}
894  out:
895 	if (result != -1)
896 		debug2("match %sfound", result ? "" : "not ");
897 	free(host);
898 	return result;
899 }
900 
901 /* Remove environment variable by pattern */
902 static void
903 rm_env(Options *options, const char *arg, const char *filename, int linenum)
904 {
905 	u_int i, j, onum_send_env = options->num_send_env;
906 
907 	/* Remove an environment variable */
908 	for (i = 0; i < options->num_send_env; ) {
909 		if (!match_pattern(options->send_env[i], arg + 1)) {
910 			i++;
911 			continue;
912 		}
913 		debug3("%s line %d: removing environment %s",
914 		    filename, linenum, options->send_env[i]);
915 		free(options->send_env[i]);
916 		options->send_env[i] = NULL;
917 		for (j = i; j < options->num_send_env - 1; j++) {
918 			options->send_env[j] = options->send_env[j + 1];
919 			options->send_env[j + 1] = NULL;
920 		}
921 		options->num_send_env--;
922 		/* NB. don't increment i */
923 	}
924 	if (onum_send_env != options->num_send_env) {
925 		options->send_env = xrecallocarray(options->send_env,
926 		    onum_send_env, options->num_send_env,
927 		    sizeof(*options->send_env));
928 	}
929 }
930 
931 /*
932  * Returns the number of the token pointed to by cp or oBadOption.
933  */
934 static OpCodes
935 parse_token(const char *cp, const char *filename, int linenum,
936     const char *ignored_unknown)
937 {
938 	int i;
939 
940 	for (i = 0; keywords[i].name; i++)
941 		if (strcmp(cp, keywords[i].name) == 0)
942 			return keywords[i].opcode;
943 	if (ignored_unknown != NULL &&
944 	    match_pattern_list(cp, ignored_unknown, 1) == 1)
945 		return oIgnoredUnknownOption;
946 	error("%s: line %d: Bad configuration option: %s",
947 	    filename, linenum, cp);
948 	return oBadOption;
949 }
950 
951 static void
952 free_canon_cnames(struct allowed_cname *cnames, u_int n)
953 {
954 	u_int i;
955 
956 	if (cnames == NULL || n == 0)
957 		return;
958 	for (i = 0; i < n; i++) {
959 		free(cnames[i].source_list);
960 		free(cnames[i].target_list);
961 	}
962 	free(cnames);
963 }
964 
965 /* Multistate option parsing */
966 struct multistate {
967 	const char *key;
968 	int value;
969 };
970 static const struct multistate multistate_flag[] = {
971 	{ "true",			1 },
972 	{ "false",			0 },
973 	{ "yes",			1 },
974 	{ "no",				0 },
975 	{ NULL, -1 }
976 };
977 static const struct multistate multistate_yesnoask[] = {
978 	{ "true",			1 },
979 	{ "false",			0 },
980 	{ "yes",			1 },
981 	{ "no",				0 },
982 	{ "ask",			2 },
983 	{ NULL, -1 }
984 };
985 static const struct multistate multistate_strict_hostkey[] = {
986 	{ "true",			SSH_STRICT_HOSTKEY_YES },
987 	{ "false",			SSH_STRICT_HOSTKEY_OFF },
988 	{ "yes",			SSH_STRICT_HOSTKEY_YES },
989 	{ "no",				SSH_STRICT_HOSTKEY_OFF },
990 	{ "ask",			SSH_STRICT_HOSTKEY_ASK },
991 	{ "off",			SSH_STRICT_HOSTKEY_OFF },
992 	{ "accept-new",			SSH_STRICT_HOSTKEY_NEW },
993 	{ NULL, -1 }
994 };
995 static const struct multistate multistate_yesnoaskconfirm[] = {
996 	{ "true",			1 },
997 	{ "false",			0 },
998 	{ "yes",			1 },
999 	{ "no",				0 },
1000 	{ "ask",			2 },
1001 	{ "confirm",			3 },
1002 	{ NULL, -1 }
1003 };
1004 static const struct multistate multistate_addressfamily[] = {
1005 	{ "inet",			AF_INET },
1006 	{ "inet6",			AF_INET6 },
1007 	{ "any",			AF_UNSPEC },
1008 	{ NULL, -1 }
1009 };
1010 static const struct multistate multistate_controlmaster[] = {
1011 	{ "true",			SSHCTL_MASTER_YES },
1012 	{ "yes",			SSHCTL_MASTER_YES },
1013 	{ "false",			SSHCTL_MASTER_NO },
1014 	{ "no",				SSHCTL_MASTER_NO },
1015 	{ "auto",			SSHCTL_MASTER_AUTO },
1016 	{ "ask",			SSHCTL_MASTER_ASK },
1017 	{ "autoask",			SSHCTL_MASTER_AUTO_ASK },
1018 	{ NULL, -1 }
1019 };
1020 static const struct multistate multistate_tunnel[] = {
1021 	{ "ethernet",			SSH_TUNMODE_ETHERNET },
1022 	{ "point-to-point",		SSH_TUNMODE_POINTOPOINT },
1023 	{ "true",			SSH_TUNMODE_DEFAULT },
1024 	{ "yes",			SSH_TUNMODE_DEFAULT },
1025 	{ "false",			SSH_TUNMODE_NO },
1026 	{ "no",				SSH_TUNMODE_NO },
1027 	{ NULL, -1 }
1028 };
1029 static const struct multistate multistate_requesttty[] = {
1030 	{ "true",			REQUEST_TTY_YES },
1031 	{ "yes",			REQUEST_TTY_YES },
1032 	{ "false",			REQUEST_TTY_NO },
1033 	{ "no",				REQUEST_TTY_NO },
1034 	{ "force",			REQUEST_TTY_FORCE },
1035 	{ "auto",			REQUEST_TTY_AUTO },
1036 	{ NULL, -1 }
1037 };
1038 static const struct multistate multistate_sessiontype[] = {
1039 	{ "none",			SESSION_TYPE_NONE },
1040 	{ "subsystem",			SESSION_TYPE_SUBSYSTEM },
1041 	{ "default",			SESSION_TYPE_DEFAULT },
1042 	{ NULL, -1 }
1043 };
1044 static const struct multistate multistate_canonicalizehostname[] = {
1045 	{ "true",			SSH_CANONICALISE_YES },
1046 	{ "false",			SSH_CANONICALISE_NO },
1047 	{ "yes",			SSH_CANONICALISE_YES },
1048 	{ "no",				SSH_CANONICALISE_NO },
1049 	{ "always",			SSH_CANONICALISE_ALWAYS },
1050 	{ NULL, -1 }
1051 };
1052 static const struct multistate multistate_pubkey_auth[] = {
1053 	{ "true",			SSH_PUBKEY_AUTH_ALL },
1054 	{ "false",			SSH_PUBKEY_AUTH_NO },
1055 	{ "yes",			SSH_PUBKEY_AUTH_ALL },
1056 	{ "no",				SSH_PUBKEY_AUTH_NO },
1057 	{ "unbound",			SSH_PUBKEY_AUTH_UNBOUND },
1058 	{ "host-bound",			SSH_PUBKEY_AUTH_HBOUND },
1059 	{ NULL, -1 }
1060 };
1061 static const struct multistate multistate_compression[] = {
1062 #ifdef WITH_ZLIB
1063 	{ "yes",			COMP_DELAYED },
1064 #endif
1065 	{ "no",				COMP_NONE },
1066 	{ NULL, -1 }
1067 };
1068 
1069 static int
1070 parse_multistate_value(const char *arg, const char *filename, int linenum,
1071     const struct multistate *multistate_ptr)
1072 {
1073 	int i;
1074 
1075 	if (!arg || *arg == '\0') {
1076 		error("%s line %d: missing argument.", filename, linenum);
1077 		return -1;
1078 	}
1079 	for (i = 0; multistate_ptr[i].key != NULL; i++) {
1080 		if (strcasecmp(arg, multistate_ptr[i].key) == 0)
1081 			return multistate_ptr[i].value;
1082 	}
1083 	return -1;
1084 }
1085 
1086 /*
1087  * Processes a single option line as used in the configuration files. This
1088  * only sets those values that have not already been set.
1089  */
1090 int
1091 process_config_line(Options *options, struct passwd *pw, const char *host,
1092     const char *original_host, char *line, const char *filename,
1093     int linenum, int *activep, int flags)
1094 {
1095 	return process_config_line_depth(options, pw, host, original_host,
1096 	    line, filename, linenum, activep, flags, NULL, 0);
1097 }
1098 
1099 #define WHITESPACE " \t\r\n"
1100 static int
1101 process_config_line_depth(Options *options, struct passwd *pw, const char *host,
1102     const char *original_host, char *line, const char *filename,
1103     int linenum, int *activep, int flags, int *want_final_pass, int depth)
1104 {
1105 	char *str, **charptr, *endofnumber, *keyword, *arg, *arg2, *p;
1106 	char **cpptr, ***cppptr, fwdarg[256];
1107 	u_int i, *uintptr, max_entries = 0;
1108 	int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
1109 	int remotefwd, dynamicfwd, ca_only = 0, found = 0;
1110 	LogLevel *log_level_ptr;
1111 	SyslogFacility *log_facility_ptr;
1112 	long long val64;
1113 	size_t len;
1114 	struct Forward fwd;
1115 	const struct multistate *multistate_ptr;
1116 	glob_t gl;
1117 	const char *errstr;
1118 	char **oav = NULL, **av;
1119 	int oac = 0, ac;
1120 	int ret = -1;
1121 	struct allowed_cname *cnames = NULL;
1122 	u_int ncnames = 0;
1123 	char **strs = NULL; /* string array arguments; freed implicitly */
1124 	u_int nstrs = 0;
1125 
1126 	if (activep == NULL) { /* We are processing a command line directive */
1127 		cmdline = 1;
1128 		activep = &cmdline;
1129 	}
1130 
1131 	/* Strip trailing whitespace. Allow \f (form feed) at EOL only */
1132 	if ((len = strlen(line)) == 0)
1133 		return 0;
1134 	for (len--; len > 0; len--) {
1135 		if (strchr(WHITESPACE "\f", line[len]) == NULL)
1136 			break;
1137 		line[len] = '\0';
1138 	}
1139 
1140 	str = line;
1141 	/* Get the keyword. (Each line is supposed to begin with a keyword). */
1142 	if ((keyword = strdelim(&str)) == NULL)
1143 		return 0;
1144 	/* Ignore leading whitespace. */
1145 	if (*keyword == '\0')
1146 		keyword = strdelim(&str);
1147 	if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
1148 		return 0;
1149 	/* Match lowercase keyword */
1150 	lowercase(keyword);
1151 
1152 	/* Prepare to parse remainder of line */
1153 	if (str != NULL)
1154 		str += strspn(str, WHITESPACE);
1155 	if (str == NULL || *str == '\0') {
1156 		error("%s line %d: no argument after keyword \"%s\"",
1157 		    filename, linenum, keyword);
1158 		return -1;
1159 	}
1160 	opcode = parse_token(keyword, filename, linenum,
1161 	    options->ignored_unknown);
1162 	if (argv_split(str, &oac, &oav, 1) != 0) {
1163 		error("%s line %d: invalid quotes", filename, linenum);
1164 		return -1;
1165 	}
1166 	ac = oac;
1167 	av = oav;
1168 
1169 	switch (opcode) {
1170 	case oBadOption:
1171 		/* don't panic, but count bad options */
1172 		goto out;
1173 	case oIgnore:
1174 		argv_consume(&ac);
1175 		break;
1176 	case oIgnoredUnknownOption:
1177 		debug("%s line %d: Ignored unknown option \"%s\"",
1178 		    filename, linenum, keyword);
1179 		argv_consume(&ac);
1180 		break;
1181 	case oConnectTimeout:
1182 		intptr = &options->connection_timeout;
1183 parse_time:
1184 		arg = argv_next(&ac, &av);
1185 		if (!arg || *arg == '\0') {
1186 			error("%s line %d: missing time value.",
1187 			    filename, linenum);
1188 			goto out;
1189 		}
1190 		if (strcmp(arg, "none") == 0)
1191 			value = -1;
1192 		else if ((value = convtime(arg)) == -1) {
1193 			error("%s line %d: invalid time value.",
1194 			    filename, linenum);
1195 			goto out;
1196 		}
1197 		if (*activep && *intptr == -1)
1198 			*intptr = value;
1199 		break;
1200 
1201 	case oForwardAgent:
1202 		intptr = &options->forward_agent;
1203 
1204 		arg = argv_next(&ac, &av);
1205 		if (!arg || *arg == '\0') {
1206 			error("%s line %d: missing argument.",
1207 			    filename, linenum);
1208 			goto out;
1209 		}
1210 
1211 		value = -1;
1212 		multistate_ptr = multistate_flag;
1213 		for (i = 0; multistate_ptr[i].key != NULL; i++) {
1214 			if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
1215 				value = multistate_ptr[i].value;
1216 				break;
1217 			}
1218 		}
1219 		if (value != -1) {
1220 			if (*activep && *intptr == -1)
1221 				*intptr = value;
1222 			break;
1223 		}
1224 		/* ForwardAgent wasn't 'yes' or 'no', assume a path */
1225 		if (*activep && *intptr == -1)
1226 			*intptr = 1;
1227 
1228 		charptr = &options->forward_agent_sock_path;
1229 		goto parse_agent_path;
1230 
1231 	case oForwardX11:
1232 		intptr = &options->forward_x11;
1233  parse_flag:
1234 		multistate_ptr = multistate_flag;
1235  parse_multistate:
1236 		arg = argv_next(&ac, &av);
1237 		if ((value = parse_multistate_value(arg, filename, linenum,
1238 		    multistate_ptr)) == -1) {
1239 			error("%s line %d: unsupported option \"%s\".",
1240 			    filename, linenum, arg);
1241 			goto out;
1242 		}
1243 		if (*activep && *intptr == -1)
1244 			*intptr = value;
1245 		break;
1246 
1247 	case oForwardX11Trusted:
1248 		intptr = &options->forward_x11_trusted;
1249 		goto parse_flag;
1250 
1251 	case oForwardX11Timeout:
1252 		intptr = &options->forward_x11_timeout;
1253 		goto parse_time;
1254 
1255 	case oGatewayPorts:
1256 		intptr = &options->fwd_opts.gateway_ports;
1257 		goto parse_flag;
1258 
1259 	case oExitOnForwardFailure:
1260 		intptr = &options->exit_on_forward_failure;
1261 		goto parse_flag;
1262 
1263 	case oPasswordAuthentication:
1264 		intptr = &options->password_authentication;
1265 		goto parse_flag;
1266 
1267 	case oKbdInteractiveAuthentication:
1268 		intptr = &options->kbd_interactive_authentication;
1269 		goto parse_flag;
1270 
1271 	case oKbdInteractiveDevices:
1272 		charptr = &options->kbd_interactive_devices;
1273 		goto parse_string;
1274 
1275 	case oPubkeyAuthentication:
1276 		multistate_ptr = multistate_pubkey_auth;
1277 		intptr = &options->pubkey_authentication;
1278 		goto parse_multistate;
1279 
1280 	case oHostbasedAuthentication:
1281 		intptr = &options->hostbased_authentication;
1282 		goto parse_flag;
1283 
1284 #if defined(KRB4) || defined(KRB5)
1285 	case oKerberosAuthentication:
1286 		intptr = &options->kerberos_authentication;
1287 		goto parse_flag;
1288 #endif
1289 #if defined(AFS) || defined(KRB5)
1290 	case oKerberosTgtPassing:
1291 		intptr = &options->kerberos_tgt_passing;
1292 		goto parse_flag;
1293 #endif
1294 
1295 	case oGssAuthentication:
1296 		intptr = &options->gss_authentication;
1297 		goto parse_flag;
1298 
1299 #ifdef AFS
1300 	case oAFSTokenPassing:
1301 		intptr = &options->afs_token_passing;
1302  		goto parse_flag;
1303 #endif
1304 
1305 	case oGssDelegateCreds:
1306 		intptr = &options->gss_deleg_creds;
1307 		goto parse_flag;
1308 
1309 	case oBatchMode:
1310 		intptr = &options->batch_mode;
1311 		goto parse_flag;
1312 
1313 	case oCheckHostIP:
1314 		intptr = &options->check_host_ip;
1315 		goto parse_flag;
1316 
1317 	case oNoneEnabled:
1318 		intptr = &options->none_enabled;
1319 		goto parse_flag;
1320 
1321 	/* we check to see if the command comes from the */
1322 	/* command line or not. If it does then enable it */
1323 	/* otherwise fail. NONE should never be a default configuration */
1324 	case oNoneSwitch:
1325 		if(strcmp(filename,"command-line")==0)
1326 		{
1327 		    intptr = &options->none_switch;
1328 		    goto parse_flag;
1329 		} else {
1330 		    error("NoneSwitch is found in %.200s.\nYou may only use this configuration option from the command line", filename);
1331 		    error("Continuing...");
1332 		    debug("NoneSwitch directive found in %.200s.", filename);
1333 		    return 0;
1334 	        }
1335 
1336 	case oHPNDisabled:
1337 		intptr = &options->hpn_disabled;
1338 		goto parse_flag;
1339 
1340 	case oHPNBufferSize:
1341 		intptr = &options->hpn_buffer_size;
1342 		goto parse_int;
1343 
1344 	case oTcpRcvBufPoll:
1345 		intptr = &options->tcp_rcv_buf_poll;
1346 		goto parse_flag;
1347 
1348 	case oVerifyHostKeyDNS:
1349 		intptr = &options->verify_host_key_dns;
1350 		multistate_ptr = multistate_yesnoask;
1351 		goto parse_multistate;
1352 
1353 	case oStrictHostKeyChecking:
1354 		intptr = &options->strict_host_key_checking;
1355 		multistate_ptr = multistate_strict_hostkey;
1356 		goto parse_multistate;
1357 
1358 	case oCompression:
1359 		intptr = &options->compression;
1360 		multistate_ptr = multistate_compression;
1361 		goto parse_multistate;
1362 
1363 	case oTCPKeepAlive:
1364 		intptr = &options->tcp_keep_alive;
1365 		goto parse_flag;
1366 
1367 	case oNoHostAuthenticationForLocalhost:
1368 		intptr = &options->no_host_authentication_for_localhost;
1369 		goto parse_flag;
1370 
1371 	case oNumberOfPasswordPrompts:
1372 		intptr = &options->number_of_password_prompts;
1373 		goto parse_int;
1374 
1375 	case oRekeyLimit:
1376 		arg = argv_next(&ac, &av);
1377 		if (!arg || *arg == '\0') {
1378 			error("%.200s line %d: Missing argument.", filename,
1379 			    linenum);
1380 			goto out;
1381 		}
1382 		if (strcmp(arg, "default") == 0) {
1383 			val64 = 0;
1384 		} else {
1385 			if (scan_scaled(arg, &val64) == -1) {
1386 				error("%.200s line %d: Bad number '%s': %s",
1387 				    filename, linenum, arg, strerror(errno));
1388 				goto out;
1389 			}
1390 			if (val64 != 0 && val64 < 16) {
1391 				error("%.200s line %d: RekeyLimit too small",
1392 				    filename, linenum);
1393 				goto out;
1394 			}
1395 		}
1396 		if (*activep && options->rekey_limit == -1)
1397 			options->rekey_limit = val64;
1398 		if (ac != 0) { /* optional rekey interval present */
1399 			if (strcmp(av[0], "none") == 0) {
1400 				(void)argv_next(&ac, &av);	/* discard */
1401 				break;
1402 			}
1403 			intptr = &options->rekey_interval;
1404 			goto parse_time;
1405 		}
1406 		break;
1407 
1408 	case oIdentityFile:
1409 		arg = argv_next(&ac, &av);
1410 		if (!arg || *arg == '\0') {
1411 			error("%.200s line %d: Missing argument.",
1412 			    filename, linenum);
1413 			goto out;
1414 		}
1415 		if (*activep) {
1416 			intptr = &options->num_identity_files;
1417 			if (*intptr >= SSH_MAX_IDENTITY_FILES) {
1418 				error("%.200s line %d: Too many identity files "
1419 				    "specified (max %d).", filename, linenum,
1420 				    SSH_MAX_IDENTITY_FILES);
1421 				goto out;
1422 			}
1423 			add_identity_file(options, NULL,
1424 			    arg, flags & SSHCONF_USERCONF);
1425 		}
1426 		break;
1427 
1428 	case oCertificateFile:
1429 		arg = argv_next(&ac, &av);
1430 		if (!arg || *arg == '\0') {
1431 			error("%.200s line %d: Missing argument.",
1432 			    filename, linenum);
1433 			goto out;
1434 		}
1435 		if (*activep) {
1436 			intptr = &options->num_certificate_files;
1437 			if (*intptr >= SSH_MAX_CERTIFICATE_FILES) {
1438 				error("%.200s line %d: Too many certificate "
1439 				    "files specified (max %d).",
1440 				    filename, linenum,
1441 				    SSH_MAX_CERTIFICATE_FILES);
1442 				goto out;
1443 			}
1444 			add_certificate_file(options, arg,
1445 			    flags & SSHCONF_USERCONF);
1446 		}
1447 		break;
1448 
1449 	case oXAuthLocation:
1450 		charptr=&options->xauth_location;
1451 		goto parse_string;
1452 
1453 	case oUser:
1454 		charptr = &options->user;
1455 parse_string:
1456 		arg = argv_next(&ac, &av);
1457 		if (!arg || *arg == '\0') {
1458 			error("%.200s line %d: Missing argument.",
1459 			    filename, linenum);
1460 			goto out;
1461 		}
1462 		if (*activep && *charptr == NULL)
1463 			*charptr = xstrdup(arg);
1464 		break;
1465 
1466 	case oGlobalKnownHostsFile:
1467 		cpptr = (char **)&options->system_hostfiles;
1468 		uintptr = &options->num_system_hostfiles;
1469 		max_entries = SSH_MAX_HOSTS_FILES;
1470 parse_char_array:
1471 		i = 0;
1472 		value = *uintptr == 0; /* was array empty when we started? */
1473 		while ((arg = argv_next(&ac, &av)) != NULL) {
1474 			if (*arg == '\0') {
1475 				error("%s line %d: keyword %s empty argument",
1476 				    filename, linenum, keyword);
1477 				goto out;
1478 			}
1479 			/* Allow "none" only in first position */
1480 			if (strcasecmp(arg, "none") == 0) {
1481 				if (i > 0 || ac > 0) {
1482 					error("%s line %d: keyword %s \"none\" "
1483 					    "argument must appear alone.",
1484 					    filename, linenum, keyword);
1485 					goto out;
1486 				}
1487 			}
1488 			i++;
1489 			if (*activep && value) {
1490 				if ((*uintptr) >= max_entries) {
1491 					error("%s line %d: too many %s "
1492 					    "entries.", filename, linenum,
1493 					    keyword);
1494 					goto out;
1495 				}
1496 				cpptr[(*uintptr)++] = xstrdup(arg);
1497 			}
1498 		}
1499 		break;
1500 
1501 	case oUserKnownHostsFile:
1502 		cpptr = (char **)&options->user_hostfiles;
1503 		uintptr = &options->num_user_hostfiles;
1504 		max_entries = SSH_MAX_HOSTS_FILES;
1505 		goto parse_char_array;
1506 
1507 	case oHostname:
1508 		charptr = &options->hostname;
1509 		goto parse_string;
1510 
1511 	case oTag:
1512 		charptr = &options->tag;
1513 		goto parse_string;
1514 
1515 	case oHostKeyAlias:
1516 		charptr = &options->host_key_alias;
1517 		goto parse_string;
1518 
1519 	case oPreferredAuthentications:
1520 		charptr = &options->preferred_authentications;
1521 		goto parse_string;
1522 
1523 	case oBindAddress:
1524 		charptr = &options->bind_address;
1525 		goto parse_string;
1526 
1527 	case oBindInterface:
1528 		charptr = &options->bind_interface;
1529 		goto parse_string;
1530 
1531 	case oIPv6PreferTemporary:
1532 		intptr = &options->ipv6_prefer_temporary;
1533 		goto parse_flag;
1534 
1535 	case oPKCS11Provider:
1536 		charptr = &options->pkcs11_provider;
1537 		goto parse_string;
1538 
1539 	case oSecurityKeyProvider:
1540 		charptr = &options->sk_provider;
1541 		goto parse_string;
1542 
1543 	case oKnownHostsCommand:
1544 		charptr = &options->known_hosts_command;
1545 		goto parse_command;
1546 
1547 	case oProxyCommand:
1548 		charptr = &options->proxy_command;
1549 		/* Ignore ProxyCommand if ProxyJump already specified */
1550 		if (options->jump_host != NULL)
1551 			charptr = &options->jump_host; /* Skip below */
1552 parse_command:
1553 		if (str == NULL) {
1554 			error("%.200s line %d: Missing argument.",
1555 			    filename, linenum);
1556 			goto out;
1557 		}
1558 		len = strspn(str, WHITESPACE "=");
1559 		if (*activep && *charptr == NULL)
1560 			*charptr = xstrdup(str + len);
1561 		argv_consume(&ac);
1562 		break;
1563 
1564 	case oProxyJump:
1565 		if (str == NULL) {
1566 			error("%.200s line %d: Missing argument.",
1567 			    filename, linenum);
1568 			goto out;
1569 		}
1570 		len = strspn(str, WHITESPACE "=");
1571 		/* XXX use argv? */
1572 		if (parse_jump(str + len, options, *activep) == -1) {
1573 			error("%.200s line %d: Invalid ProxyJump \"%s\"",
1574 			    filename, linenum, str + len);
1575 			goto out;
1576 		}
1577 		argv_consume(&ac);
1578 		break;
1579 
1580 	case oPort:
1581 		arg = argv_next(&ac, &av);
1582 		if (!arg || *arg == '\0') {
1583 			error("%.200s line %d: Missing argument.",
1584 			    filename, linenum);
1585 			goto out;
1586 		}
1587 		value = a2port(arg);
1588 		if (value <= 0) {
1589 			error("%.200s line %d: Bad port '%s'.",
1590 			    filename, linenum, arg);
1591 			goto out;
1592 		}
1593 		if (*activep && options->port == -1)
1594 			options->port = value;
1595 		break;
1596 
1597 	case oConnectionAttempts:
1598 		intptr = &options->connection_attempts;
1599 parse_int:
1600 		arg = argv_next(&ac, &av);
1601 		if ((errstr = atoi_err(arg, &value)) != NULL) {
1602 			error("%s line %d: integer value %s.",
1603 			    filename, linenum, errstr);
1604 			goto out;
1605 		}
1606 		if (*activep && *intptr == -1)
1607 			*intptr = value;
1608 		break;
1609 
1610 	case oTcpRcvBuf:
1611 		intptr = &options->tcp_rcv_buf;
1612 		goto parse_int;
1613 
1614 	case oCiphers:
1615 		arg = argv_next(&ac, &av);
1616 		if (!arg || *arg == '\0') {
1617 			error("%.200s line %d: Missing argument.",
1618 			    filename, linenum);
1619 			goto out;
1620 		}
1621 		if (*arg != '-' &&
1622 		    !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)){
1623 			error("%.200s line %d: Bad SSH2 cipher spec '%s'.",
1624 			    filename, linenum, arg ? arg : "<NONE>");
1625 			goto out;
1626 		}
1627 		if (*activep && options->ciphers == NULL)
1628 			options->ciphers = xstrdup(arg);
1629 		break;
1630 
1631 	case oMacs:
1632 		arg = argv_next(&ac, &av);
1633 		if (!arg || *arg == '\0') {
1634 			error("%.200s line %d: Missing argument.",
1635 			    filename, linenum);
1636 			goto out;
1637 		}
1638 		if (*arg != '-' &&
1639 		    !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) {
1640 			error("%.200s line %d: Bad SSH2 MAC spec '%s'.",
1641 			    filename, linenum, arg ? arg : "<NONE>");
1642 			goto out;
1643 		}
1644 		if (*activep && options->macs == NULL)
1645 			options->macs = xstrdup(arg);
1646 		break;
1647 
1648 	case oKexAlgorithms:
1649 		arg = argv_next(&ac, &av);
1650 		if (!arg || *arg == '\0') {
1651 			error("%.200s line %d: Missing argument.",
1652 			    filename, linenum);
1653 			goto out;
1654 		}
1655 		if (*arg != '-' &&
1656 		    !kex_names_valid(*arg == '+' || *arg == '^' ?
1657 		    arg + 1 : arg)) {
1658 			error("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
1659 			    filename, linenum, arg ? arg : "<NONE>");
1660 			goto out;
1661 		}
1662 		if (*activep && options->kex_algorithms == NULL)
1663 			options->kex_algorithms = xstrdup(arg);
1664 		break;
1665 
1666 	case oHostKeyAlgorithms:
1667 		charptr = &options->hostkeyalgorithms;
1668 		ca_only = 0;
1669 parse_pubkey_algos:
1670 		arg = argv_next(&ac, &av);
1671 		if (!arg || *arg == '\0') {
1672 			error("%.200s line %d: Missing argument.",
1673 			    filename, linenum);
1674 			goto out;
1675 		}
1676 		if (*arg != '-' &&
1677 		    !sshkey_names_valid2(*arg == '+' || *arg == '^' ?
1678 		    arg + 1 : arg, 1, ca_only)) {
1679 			error("%s line %d: Bad key types '%s'.",
1680 			    filename, linenum, arg ? arg : "<NONE>");
1681 			goto out;
1682 		}
1683 		if (*activep && *charptr == NULL)
1684 			*charptr = xstrdup(arg);
1685 		break;
1686 
1687 	case oCASignatureAlgorithms:
1688 		charptr = &options->ca_sign_algorithms;
1689 		ca_only = 1;
1690 		goto parse_pubkey_algos;
1691 
1692 	case oLogLevel:
1693 		log_level_ptr = &options->log_level;
1694 		arg = argv_next(&ac, &av);
1695 		value = log_level_number(arg);
1696 		if (value == SYSLOG_LEVEL_NOT_SET) {
1697 			error("%.200s line %d: unsupported log level '%s'",
1698 			    filename, linenum, arg ? arg : "<NONE>");
1699 			goto out;
1700 		}
1701 		if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
1702 			*log_level_ptr = (LogLevel) value;
1703 		break;
1704 
1705 	case oLogFacility:
1706 		log_facility_ptr = &options->log_facility;
1707 		arg = argv_next(&ac, &av);
1708 		value = log_facility_number(arg);
1709 		if (value == SYSLOG_FACILITY_NOT_SET) {
1710 			error("%.200s line %d: unsupported log facility '%s'",
1711 			    filename, linenum, arg ? arg : "<NONE>");
1712 			goto out;
1713 		}
1714 		if (*log_facility_ptr == -1)
1715 			*log_facility_ptr = (SyslogFacility) value;
1716 		break;
1717 
1718 	case oLogVerbose:
1719 		cppptr = &options->log_verbose;
1720 		uintptr = &options->num_log_verbose;
1721 		i = 0;
1722 		while ((arg = argv_next(&ac, &av)) != NULL) {
1723 			if (*arg == '\0') {
1724 				error("%s line %d: keyword %s empty argument",
1725 				    filename, linenum, keyword);
1726 				goto out;
1727 			}
1728 			/* Allow "none" only in first position */
1729 			if (strcasecmp(arg, "none") == 0) {
1730 				if (i > 0 || ac > 0) {
1731 					error("%s line %d: keyword %s \"none\" "
1732 					    "argument must appear alone.",
1733 					    filename, linenum, keyword);
1734 					goto out;
1735 				}
1736 			}
1737 			i++;
1738 			if (*activep && *uintptr == 0) {
1739 				*cppptr = xrecallocarray(*cppptr, *uintptr,
1740 				    *uintptr + 1, sizeof(**cppptr));
1741 				(*cppptr)[(*uintptr)++] = xstrdup(arg);
1742 			}
1743 		}
1744 		break;
1745 
1746 	case oLocalForward:
1747 	case oRemoteForward:
1748 	case oDynamicForward:
1749 		arg = argv_next(&ac, &av);
1750 		if (!arg || *arg == '\0') {
1751 			error("%.200s line %d: Missing argument.",
1752 			    filename, linenum);
1753 			goto out;
1754 		}
1755 
1756 		remotefwd = (opcode == oRemoteForward);
1757 		dynamicfwd = (opcode == oDynamicForward);
1758 
1759 		if (!dynamicfwd) {
1760 			arg2 = argv_next(&ac, &av);
1761 			if (arg2 == NULL || *arg2 == '\0') {
1762 				if (remotefwd)
1763 					dynamicfwd = 1;
1764 				else {
1765 					error("%.200s line %d: Missing target "
1766 					    "argument.", filename, linenum);
1767 					goto out;
1768 				}
1769 			} else {
1770 				/* construct a string for parse_forward */
1771 				snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg,
1772 				    arg2);
1773 			}
1774 		}
1775 		if (dynamicfwd)
1776 			strlcpy(fwdarg, arg, sizeof(fwdarg));
1777 
1778 		if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0) {
1779 			error("%.200s line %d: Bad forwarding specification.",
1780 			    filename, linenum);
1781 			goto out;
1782 		}
1783 
1784 		if (*activep) {
1785 			if (remotefwd) {
1786 				add_remote_forward(options, &fwd);
1787 			} else {
1788 				add_local_forward(options, &fwd);
1789 			}
1790 		}
1791 		break;
1792 
1793 	case oPermitRemoteOpen:
1794 		uintptr = &options->num_permitted_remote_opens;
1795 		cppptr = &options->permitted_remote_opens;
1796 		found = *uintptr == 0;
1797 		while ((arg = argv_next(&ac, &av)) != NULL) {
1798 			arg2 = xstrdup(arg);
1799 			/* Allow any/none only in first position */
1800 			if (strcasecmp(arg, "none") == 0 ||
1801 			    strcasecmp(arg, "any") == 0) {
1802 				if (nstrs > 0 || ac > 0) {
1803 					error("%s line %d: keyword %s \"%s\" "
1804 					    "argument must appear alone.",
1805 					    filename, linenum, keyword, arg);
1806 					free(arg2);
1807 					goto out;
1808 				}
1809 			} else {
1810 				p = hpdelim(&arg);
1811 				if (p == NULL) {
1812 					fatal("%s line %d: missing host in %s",
1813 					    filename, linenum,
1814 					    lookup_opcode_name(opcode));
1815 				}
1816 				p = cleanhostname(p);
1817 				/*
1818 				 * don't want to use permitopen_port to avoid
1819 				 * dependency on channels.[ch] here.
1820 				 */
1821 				if (arg == NULL || (strcmp(arg, "*") != 0 &&
1822 				    a2port(arg) <= 0)) {
1823 					fatal("%s line %d: bad port number "
1824 					    "in %s", filename, linenum,
1825 					    lookup_opcode_name(opcode));
1826 				}
1827 			}
1828 			opt_array_append(filename, linenum,
1829 			    lookup_opcode_name(opcode),
1830 			    &strs, &nstrs, arg2);
1831 			free(arg2);
1832 		}
1833 		if (nstrs == 0)
1834 			fatal("%s line %d: missing %s specification",
1835 			    filename, linenum, lookup_opcode_name(opcode));
1836 		if (found && *activep) {
1837 			*cppptr = strs;
1838 			*uintptr = nstrs;
1839 			strs = NULL; /* transferred */
1840 			nstrs = 0;
1841 		}
1842 		break;
1843 
1844 	case oClearAllForwardings:
1845 		intptr = &options->clear_forwardings;
1846 		goto parse_flag;
1847 
1848 	case oHost:
1849 		if (cmdline) {
1850 			error("Host directive not supported as a command-line "
1851 			    "option");
1852 			goto out;
1853 		}
1854 		*activep = 0;
1855 		arg2 = NULL;
1856 		while ((arg = argv_next(&ac, &av)) != NULL) {
1857 			if (*arg == '\0') {
1858 				error("%s line %d: keyword %s empty argument",
1859 				    filename, linenum, keyword);
1860 				goto out;
1861 			}
1862 			if ((flags & SSHCONF_NEVERMATCH) != 0) {
1863 				argv_consume(&ac);
1864 				break;
1865 			}
1866 			negated = *arg == '!';
1867 			if (negated)
1868 				arg++;
1869 			if (match_pattern(host, arg)) {
1870 				if (negated) {
1871 					debug("%.200s line %d: Skipping Host "
1872 					    "block because of negated match "
1873 					    "for %.100s", filename, linenum,
1874 					    arg);
1875 					*activep = 0;
1876 					argv_consume(&ac);
1877 					break;
1878 				}
1879 				if (!*activep)
1880 					arg2 = arg; /* logged below */
1881 				*activep = 1;
1882 			}
1883 		}
1884 		if (*activep)
1885 			debug("%.200s line %d: Applying options for %.100s",
1886 			    filename, linenum, arg2);
1887 		break;
1888 
1889 	case oMatch:
1890 		if (cmdline) {
1891 			error("Host directive not supported as a command-line "
1892 			    "option");
1893 			goto out;
1894 		}
1895 		value = match_cfg_line(options, str, &ac, &av, pw, host,
1896 		    original_host, flags & SSHCONF_FINAL, want_final_pass,
1897 		    filename, linenum);
1898 		if (value < 0) {
1899 			error("%.200s line %d: Bad Match condition", filename,
1900 			    linenum);
1901 			goto out;
1902 		}
1903 		*activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value;
1904 		break;
1905 
1906 	case oEscapeChar:
1907 		intptr = &options->escape_char;
1908 		arg = argv_next(&ac, &av);
1909 		if (!arg || *arg == '\0') {
1910 			error("%.200s line %d: Missing argument.",
1911 			    filename, linenum);
1912 			goto out;
1913 		}
1914 		if (strcmp(arg, "none") == 0)
1915 			value = SSH_ESCAPECHAR_NONE;
1916 		else if (arg[1] == '\0')
1917 			value = (u_char) arg[0];
1918 		else if (arg[0] == '^' && arg[2] == 0 &&
1919 		    (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
1920 			value = (u_char) arg[1] & 31;
1921 		else {
1922 			error("%.200s line %d: Bad escape character.",
1923 			    filename, linenum);
1924 			goto out;
1925 		}
1926 		if (*activep && *intptr == -1)
1927 			*intptr = value;
1928 		break;
1929 
1930 	case oAddressFamily:
1931 		intptr = &options->address_family;
1932 		multistate_ptr = multistate_addressfamily;
1933 		goto parse_multistate;
1934 
1935 	case oEnableSSHKeysign:
1936 		intptr = &options->enable_ssh_keysign;
1937 		goto parse_flag;
1938 
1939 	case oIdentitiesOnly:
1940 		intptr = &options->identities_only;
1941 		goto parse_flag;
1942 
1943 	case oServerAliveInterval:
1944 		intptr = &options->server_alive_interval;
1945 		goto parse_time;
1946 
1947 	case oServerAliveCountMax:
1948 		intptr = &options->server_alive_count_max;
1949 		goto parse_int;
1950 
1951 	case oSendEnv:
1952 		/* XXX appends to list; doesn't respect first-match-wins */
1953 		while ((arg = argv_next(&ac, &av)) != NULL) {
1954 			if (*arg == '\0' || strchr(arg, '=') != NULL) {
1955 				error("%s line %d: Invalid environment name.",
1956 				    filename, linenum);
1957 				goto out;
1958 			}
1959 			found = 1;
1960 			if (!*activep)
1961 				continue;
1962 			if (*arg == '-') {
1963 				/* Removing an env var */
1964 				rm_env(options, arg, filename, linenum);
1965 				continue;
1966 			}
1967 			opt_array_append(filename, linenum,
1968 			    lookup_opcode_name(opcode),
1969 			    &options->send_env, &options->num_send_env, arg);
1970 		}
1971 		if (!found) {
1972 			fatal("%s line %d: no %s specified",
1973 			    filename, linenum, keyword);
1974 		}
1975 		break;
1976 
1977 	case oSetEnv:
1978 		found = options->num_setenv == 0;
1979 		while ((arg = argv_next(&ac, &av)) != NULL) {
1980 			if (strchr(arg, '=') == NULL) {
1981 				error("%s line %d: Invalid SetEnv.",
1982 				    filename, linenum);
1983 				goto out;
1984 			}
1985 			if (lookup_setenv_in_list(arg, strs, nstrs) != NULL) {
1986 				debug2("%s line %d: ignoring duplicate env "
1987 				    "name \"%.64s\"", filename, linenum, arg);
1988 				continue;
1989 			}
1990 			opt_array_append(filename, linenum,
1991 			    lookup_opcode_name(opcode),
1992 			    &strs, &nstrs, arg);
1993 		}
1994 		if (nstrs == 0) {
1995 			fatal("%s line %d: no %s specified",
1996 			    filename, linenum, keyword);
1997 		}
1998 		if (found && *activep) {
1999 			options->setenv = strs;
2000 			options->num_setenv = nstrs;
2001 			strs = NULL; /* transferred */
2002 			nstrs = 0;
2003 		}
2004 		break;
2005 
2006 	case oControlPath:
2007 		charptr = &options->control_path;
2008 		goto parse_string;
2009 
2010 	case oControlMaster:
2011 		intptr = &options->control_master;
2012 		multistate_ptr = multistate_controlmaster;
2013 		goto parse_multistate;
2014 
2015 	case oControlPersist:
2016 		/* no/false/yes/true, or a time spec */
2017 		intptr = &options->control_persist;
2018 		arg = argv_next(&ac, &av);
2019 		if (!arg || *arg == '\0') {
2020 			error("%.200s line %d: Missing ControlPersist"
2021 			    " argument.", filename, linenum);
2022 			goto out;
2023 		}
2024 		value = 0;
2025 		value2 = 0;	/* timeout */
2026 		if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
2027 			value = 0;
2028 		else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
2029 			value = 1;
2030 		else if ((value2 = convtime(arg)) >= 0)
2031 			value = 1;
2032 		else {
2033 			error("%.200s line %d: Bad ControlPersist argument.",
2034 			    filename, linenum);
2035 			goto out;
2036 		}
2037 		if (*activep && *intptr == -1) {
2038 			*intptr = value;
2039 			options->control_persist_timeout = value2;
2040 		}
2041 		break;
2042 
2043 	case oHashKnownHosts:
2044 		intptr = &options->hash_known_hosts;
2045 		goto parse_flag;
2046 
2047 	case oTunnel:
2048 		intptr = &options->tun_open;
2049 		multistate_ptr = multistate_tunnel;
2050 		goto parse_multistate;
2051 
2052 	case oTunnelDevice:
2053 		arg = argv_next(&ac, &av);
2054 		if (!arg || *arg == '\0') {
2055 			error("%.200s line %d: Missing argument.",
2056 			    filename, linenum);
2057 			goto out;
2058 		}
2059 		value = a2tun(arg, &value2);
2060 		if (value == SSH_TUNID_ERR) {
2061 			error("%.200s line %d: Bad tun device.",
2062 			    filename, linenum);
2063 			goto out;
2064 		}
2065 		if (*activep && options->tun_local == -1) {
2066 			options->tun_local = value;
2067 			options->tun_remote = value2;
2068 		}
2069 		break;
2070 
2071 	case oLocalCommand:
2072 		charptr = &options->local_command;
2073 		goto parse_command;
2074 
2075 	case oPermitLocalCommand:
2076 		intptr = &options->permit_local_command;
2077 		goto parse_flag;
2078 
2079 	case oRemoteCommand:
2080 		charptr = &options->remote_command;
2081 		goto parse_command;
2082 
2083 	case oVisualHostKey:
2084 		intptr = &options->visual_host_key;
2085 		goto parse_flag;
2086 
2087 	case oInclude:
2088 		if (cmdline) {
2089 			error("Include directive not supported as a "
2090 			    "command-line option");
2091 			goto out;
2092 		}
2093 		value = 0;
2094 		while ((arg = argv_next(&ac, &av)) != NULL) {
2095 			if (*arg == '\0') {
2096 				error("%s line %d: keyword %s empty argument",
2097 				    filename, linenum, keyword);
2098 				goto out;
2099 			}
2100 			/* Expand %tokens and environment variables */
2101 			if ((p = expand_match_exec_or_include_path(arg,
2102 			    options, pw, host, original_host,
2103 			    flags & SSHCONF_FINAL, 1)) == NULL) {
2104 				error("%.200s line %d: Unable to expand user "
2105 				    "config file '%.100s'",
2106 				    filename, linenum, arg);
2107 				continue;
2108 			}
2109 			/*
2110 			 * Ensure all paths are anchored. User configuration
2111 			 * files may begin with '~/' but system configurations
2112 			 * must not. If the path is relative, then treat it
2113 			 * as living in ~/.ssh for user configurations or
2114 			 * /etc/ssh for system ones.
2115 			 */
2116 			if (*p == '~' && (flags & SSHCONF_USERCONF) == 0) {
2117 				error("%.200s line %d: bad include path %s.",
2118 				    filename, linenum, p);
2119 				goto out;
2120 			}
2121 			if (!path_absolute(p) && *p != '~') {
2122 				xasprintf(&arg2, "%s/%s",
2123 				    (flags & SSHCONF_USERCONF) ?
2124 				    "~/" _PATH_SSH_USER_DIR : SSHDIR, p);
2125 			} else {
2126 				arg2 = xstrdup(p);
2127 			}
2128 			free(p);
2129 			memset(&gl, 0, sizeof(gl));
2130 			r = glob(arg2, GLOB_TILDE | GLOB_LIMIT, NULL, &gl);
2131 			if (r == GLOB_NOMATCH) {
2132 				debug("%.200s line %d: include %s matched no "
2133 				    "files",filename, linenum, arg2);
2134 				free(arg2);
2135 				continue;
2136 			} else if (r != 0) {
2137 				error("%.200s line %d: glob failed for %s.",
2138 				    filename, linenum, arg2);
2139 				goto out;
2140 			}
2141 			free(arg2);
2142 			oactive = *activep;
2143 			for (i = 0; i < gl.gl_pathc; i++) {
2144 				debug3("%.200s line %d: Including file %s "
2145 				    "depth %d%s", filename, linenum,
2146 				    gl.gl_pathv[i], depth,
2147 				    oactive ? "" : " (parse only)");
2148 				r = read_config_file_depth(gl.gl_pathv[i],
2149 				    pw, host, original_host, options,
2150 				    flags | SSHCONF_CHECKPERM |
2151 				    (oactive ? 0 : SSHCONF_NEVERMATCH),
2152 				    activep, want_final_pass, depth + 1);
2153 				if (r != 1 && errno != ENOENT) {
2154 					error("%.200s line %d: Can't open user "
2155 					    "config file %.100s: %.100s",
2156 					    filename, linenum, gl.gl_pathv[i],
2157 					    strerror(errno));
2158 					globfree(&gl);
2159 					goto out;
2160 				}
2161 				/*
2162 				 * don't let Match in includes clobber the
2163 				 * containing file's Match state.
2164 				 */
2165 				*activep = oactive;
2166 				if (r != 1)
2167 					value = -1;
2168 			}
2169 			globfree(&gl);
2170 		}
2171 		if (value != 0)
2172 			ret = value;
2173 		break;
2174 
2175 	case oIPQoS:
2176 		arg = argv_next(&ac, &av);
2177 		if ((value = parse_ipqos(arg)) == -1) {
2178 			error("%s line %d: Bad IPQoS value: %s",
2179 			    filename, linenum, arg);
2180 			goto out;
2181 		}
2182 		arg = argv_next(&ac, &av);
2183 		if (arg == NULL)
2184 			value2 = value;
2185 		else if ((value2 = parse_ipqos(arg)) == -1) {
2186 			error("%s line %d: Bad IPQoS value: %s",
2187 			    filename, linenum, arg);
2188 			goto out;
2189 		}
2190 		if (*activep && options->ip_qos_interactive == -1) {
2191 			options->ip_qos_interactive = value;
2192 			options->ip_qos_bulk = value2;
2193 		}
2194 		break;
2195 
2196 	case oRequestTTY:
2197 		intptr = &options->request_tty;
2198 		multistate_ptr = multistate_requesttty;
2199 		goto parse_multistate;
2200 
2201 	case oSendVersionFirst:
2202 		intptr = &options->send_version_first;
2203 		goto parse_flag;
2204 
2205 	case oSessionType:
2206 		intptr = &options->session_type;
2207 		multistate_ptr = multistate_sessiontype;
2208 		goto parse_multistate;
2209 
2210 	case oStdinNull:
2211 		intptr = &options->stdin_null;
2212 		goto parse_flag;
2213 
2214 	case oForkAfterAuthentication:
2215 		intptr = &options->fork_after_authentication;
2216 		goto parse_flag;
2217 
2218 	case oIgnoreUnknown:
2219 		charptr = &options->ignored_unknown;
2220 		goto parse_string;
2221 
2222 	case oProxyUseFdpass:
2223 		intptr = &options->proxy_use_fdpass;
2224 		goto parse_flag;
2225 
2226 	case oCanonicalDomains:
2227 		found = options->num_canonical_domains == 0;
2228 		while ((arg = argv_next(&ac, &av)) != NULL) {
2229 			/* Allow "none" only in first position */
2230 			if (strcasecmp(arg, "none") == 0) {
2231 				if (nstrs > 0 || ac > 0) {
2232 					error("%s line %d: keyword %s \"none\" "
2233 					    "argument must appear alone.",
2234 					    filename, linenum, keyword);
2235 					goto out;
2236 				}
2237 			}
2238 			if (!valid_domain(arg, 1, &errstr)) {
2239 				error("%s line %d: %s", filename, linenum,
2240 				    errstr);
2241 				goto out;
2242 			}
2243 			opt_array_append(filename, linenum, keyword,
2244 			    &strs, &nstrs, arg);
2245 		}
2246 		if (nstrs == 0) {
2247 			fatal("%s line %d: no %s specified",
2248 			    filename, linenum, keyword);
2249 		}
2250 		if (found && *activep) {
2251 			options->canonical_domains = strs;
2252 			options->num_canonical_domains = nstrs;
2253 			strs = NULL; /* transferred */
2254 			nstrs = 0;
2255 		}
2256 		break;
2257 
2258 	case oCanonicalizePermittedCNAMEs:
2259 		found = options->num_permitted_cnames == 0;
2260 		while ((arg = argv_next(&ac, &av)) != NULL) {
2261 			char empty[] = "";
2262 			/*
2263 			 * Either 'none' (only in first position), '*' for
2264 			 * everything or 'list:list'
2265 			 */
2266 			if (strcasecmp(arg, "none") == 0) {
2267 				if (ncnames > 0 || ac > 0) {
2268 					error("%s line %d: keyword %s \"none\" "
2269 					    "argument must appear alone.",
2270 					    filename, linenum, keyword);
2271 					goto out;
2272 				}
2273 				arg2 = empty;
2274 			} else if (strcmp(arg, "*") == 0) {
2275 				arg2 = arg;
2276 			} else {
2277 				lowercase(arg);
2278 				if ((arg2 = strchr(arg, ':')) == NULL ||
2279 				    arg2[1] == '\0') {
2280 					error("%s line %d: "
2281 					    "Invalid permitted CNAME \"%s\"",
2282 					    filename, linenum, arg);
2283 					goto out;
2284 				}
2285 				*arg2 = '\0';
2286 				arg2++;
2287 			}
2288 			cnames = xrecallocarray(cnames, ncnames, ncnames + 1,
2289 			    sizeof(*cnames));
2290 			cnames[ncnames].source_list = xstrdup(arg);
2291 			cnames[ncnames].target_list = xstrdup(arg2);
2292 			ncnames++;
2293 		}
2294 		if (ncnames == 0) {
2295 			fatal("%s line %d: no %s specified",
2296 			    filename, linenum, keyword);
2297 		}
2298 		if (found && *activep) {
2299 			options->permitted_cnames = cnames;
2300 			options->num_permitted_cnames = ncnames;
2301 			cnames = NULL; /* transferred */
2302 			ncnames = 0;
2303 		}
2304 		/* un-transferred cnames is cleaned up before exit */
2305 		break;
2306 
2307 	case oCanonicalizeHostname:
2308 		intptr = &options->canonicalize_hostname;
2309 		multistate_ptr = multistate_canonicalizehostname;
2310 		goto parse_multistate;
2311 
2312 	case oCanonicalizeMaxDots:
2313 		intptr = &options->canonicalize_max_dots;
2314 		goto parse_int;
2315 
2316 	case oCanonicalizeFallbackLocal:
2317 		intptr = &options->canonicalize_fallback_local;
2318 		goto parse_flag;
2319 
2320 	case oStreamLocalBindMask:
2321 		arg = argv_next(&ac, &av);
2322 		if (!arg || *arg == '\0') {
2323 			error("%.200s line %d: Missing StreamLocalBindMask "
2324 			    "argument.", filename, linenum);
2325 			goto out;
2326 		}
2327 		/* Parse mode in octal format */
2328 		value = strtol(arg, &endofnumber, 8);
2329 		if (arg == endofnumber || value < 0 || value > 0777) {
2330 			error("%.200s line %d: Bad mask.", filename, linenum);
2331 			goto out;
2332 		}
2333 		options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
2334 		break;
2335 
2336 	case oStreamLocalBindUnlink:
2337 		intptr = &options->fwd_opts.streamlocal_bind_unlink;
2338 		goto parse_flag;
2339 
2340 	case oRevokedHostKeys:
2341 		charptr = &options->revoked_host_keys;
2342 		goto parse_string;
2343 
2344 	case oFingerprintHash:
2345 		intptr = &options->fingerprint_hash;
2346 		arg = argv_next(&ac, &av);
2347 		if (!arg || *arg == '\0') {
2348 			error("%.200s line %d: Missing argument.",
2349 			    filename, linenum);
2350 			goto out;
2351 		}
2352 		if ((value = ssh_digest_alg_by_name(arg)) == -1) {
2353 			error("%.200s line %d: Invalid hash algorithm \"%s\".",
2354 			    filename, linenum, arg);
2355 			goto out;
2356 		}
2357 		if (*activep && *intptr == -1)
2358 			*intptr = value;
2359 		break;
2360 
2361 	case oUpdateHostkeys:
2362 		intptr = &options->update_hostkeys;
2363 		multistate_ptr = multistate_yesnoask;
2364 		goto parse_multistate;
2365 
2366 	case oHostbasedAcceptedAlgorithms:
2367 		charptr = &options->hostbased_accepted_algos;
2368 		ca_only = 0;
2369 		goto parse_pubkey_algos;
2370 
2371 	case oPubkeyAcceptedAlgorithms:
2372 		charptr = &options->pubkey_accepted_algos;
2373 		ca_only = 0;
2374 		goto parse_pubkey_algos;
2375 
2376 	case oAddKeysToAgent:
2377 		arg = argv_next(&ac, &av);
2378 		arg2 = argv_next(&ac, &av);
2379 		value = parse_multistate_value(arg, filename, linenum,
2380 		    multistate_yesnoaskconfirm);
2381 		value2 = 0; /* unlimited lifespan by default */
2382 		if (value == 3 && arg2 != NULL) {
2383 			/* allow "AddKeysToAgent confirm 5m" */
2384 			if ((value2 = convtime(arg2)) == -1) {
2385 				error("%s line %d: invalid time value.",
2386 				    filename, linenum);
2387 				goto out;
2388 			}
2389 		} else if (value == -1 && arg2 == NULL) {
2390 			if ((value2 = convtime(arg)) == -1) {
2391 				error("%s line %d: unsupported option",
2392 				    filename, linenum);
2393 				goto out;
2394 			}
2395 			value = 1; /* yes */
2396 		} else if (value == -1 || arg2 != NULL) {
2397 			error("%s line %d: unsupported option",
2398 			    filename, linenum);
2399 			goto out;
2400 		}
2401 		if (*activep && options->add_keys_to_agent == -1) {
2402 			options->add_keys_to_agent = value;
2403 			options->add_keys_to_agent_lifespan = value2;
2404 		}
2405 		break;
2406 
2407 	case oIdentityAgent:
2408 		charptr = &options->identity_agent;
2409 		arg = argv_next(&ac, &av);
2410 		if (!arg || *arg == '\0') {
2411 			error("%.200s line %d: Missing argument.",
2412 			    filename, linenum);
2413 			goto out;
2414 		}
2415   parse_agent_path:
2416 		/* Extra validation if the string represents an env var. */
2417 		if ((arg2 = dollar_expand(&r, arg)) == NULL || r) {
2418 			error("%.200s line %d: Invalid environment expansion "
2419 			    "%s.", filename, linenum, arg);
2420 			goto out;
2421 		}
2422 		free(arg2);
2423 		/* check for legacy environment format */
2424 		if (arg[0] == '$' && arg[1] != '{' &&
2425 		    !valid_env_name(arg + 1)) {
2426 			error("%.200s line %d: Invalid environment name %s.",
2427 			    filename, linenum, arg);
2428 			goto out;
2429 		}
2430 		if (*activep && *charptr == NULL)
2431 			*charptr = xstrdup(arg);
2432 		break;
2433 
2434 	case oEnableEscapeCommandline:
2435 		intptr = &options->enable_escape_commandline;
2436 		goto parse_flag;
2437 
2438 	case oRequiredRSASize:
2439 		intptr = &options->required_rsa_size;
2440 		goto parse_int;
2441 
2442 	case oObscureKeystrokeTiming:
2443 		value = -1;
2444 		while ((arg = argv_next(&ac, &av)) != NULL) {
2445 			if (value != -1) {
2446 				error("%s line %d: invalid arguments",
2447 				    filename, linenum);
2448 				goto out;
2449 			}
2450 			if (strcmp(arg, "yes") == 0 ||
2451 			    strcmp(arg, "true") == 0)
2452 				value = SSH_KEYSTROKE_DEFAULT_INTERVAL_MS;
2453 			else if (strcmp(arg, "no") == 0 ||
2454 			    strcmp(arg, "false") == 0)
2455 				value = 0;
2456 			else if (strncmp(arg, "interval:", 9) == 0) {
2457 				if ((errstr = atoi_err(arg + 9,
2458 				    &value)) != NULL) {
2459 					error("%s line %d: integer value %s.",
2460 					    filename, linenum, errstr);
2461 					goto out;
2462 				}
2463 				if (value <= 0 || value > 1000) {
2464 					error("%s line %d: value out of range.",
2465 					    filename, linenum);
2466 					goto out;
2467 				}
2468 			} else {
2469 				error("%s line %d: unsupported argument \"%s\"",
2470 				    filename, linenum, arg);
2471 				goto out;
2472 			}
2473 		}
2474 		if (value == -1) {
2475 			error("%s line %d: missing argument",
2476 			    filename, linenum);
2477 			goto out;
2478 		}
2479 		intptr = &options->obscure_keystroke_timing_interval;
2480 		if (*activep && *intptr == -1)
2481 			*intptr = value;
2482 		break;
2483 
2484 	case oChannelTimeout:
2485 		found = options->num_channel_timeouts == 0;
2486 		while ((arg = argv_next(&ac, &av)) != NULL) {
2487 			/* Allow "none" only in first position */
2488 			if (strcasecmp(arg, "none") == 0) {
2489 				if (nstrs > 0 || ac > 0) {
2490 					error("%s line %d: keyword %s \"none\" "
2491 					    "argument must appear alone.",
2492 					    filename, linenum, keyword);
2493 					goto out;
2494 				}
2495 			} else if (parse_pattern_interval(arg,
2496 			    NULL, NULL) != 0) {
2497 				fatal("%s line %d: invalid channel timeout %s",
2498 				    filename, linenum, arg);
2499 			}
2500 			opt_array_append(filename, linenum, keyword,
2501 			    &strs, &nstrs, arg);
2502 		}
2503 		if (nstrs == 0) {
2504 			fatal("%s line %d: no %s specified",
2505 			    filename, linenum, keyword);
2506 		}
2507 		if (found && *activep) {
2508 			options->channel_timeouts = strs;
2509 			options->num_channel_timeouts = nstrs;
2510 			strs = NULL; /* transferred */
2511 			nstrs = 0;
2512 		}
2513 		break;
2514 
2515 	case oDeprecated:
2516 		debug("%s line %d: Deprecated option \"%s\"",
2517 		    filename, linenum, keyword);
2518 		argv_consume(&ac);
2519 		break;
2520 
2521 	case oUnsupported:
2522 		error("%s line %d: Unsupported option \"%s\"",
2523 		    filename, linenum, keyword);
2524 		argv_consume(&ac);
2525 		break;
2526 
2527 	default:
2528 		error("%s line %d: Unimplemented opcode %d",
2529 		    filename, linenum, opcode);
2530 		goto out;
2531 	}
2532 
2533 	/* Check that there is no garbage at end of line. */
2534 	if (ac > 0) {
2535 		error("%.200s line %d: keyword %s extra arguments "
2536 		    "at end of line", filename, linenum, keyword);
2537 		goto out;
2538 	}
2539 
2540 	/* success */
2541 	ret = 0;
2542  out:
2543 	free_canon_cnames(cnames, ncnames);
2544 	opt_array_free2(strs, NULL, nstrs);
2545 	argv_free(oav, oac);
2546 	return ret;
2547 }
2548 
2549 /*
2550  * Reads the config file and modifies the options accordingly.  Options
2551  * should already be initialized before this call.  This never returns if
2552  * there is an error.  If the file does not exist, this returns 0.
2553  */
2554 int
2555 read_config_file(const char *filename, struct passwd *pw, const char *host,
2556     const char *original_host, Options *options, int flags,
2557     int *want_final_pass)
2558 {
2559 	int active = 1;
2560 
2561 	return read_config_file_depth(filename, pw, host, original_host,
2562 	    options, flags, &active, want_final_pass, 0);
2563 }
2564 
2565 #define READCONF_MAX_DEPTH	16
2566 static int
2567 read_config_file_depth(const char *filename, struct passwd *pw,
2568     const char *host, const char *original_host, Options *options,
2569     int flags, int *activep, int *want_final_pass, int depth)
2570 {
2571 	FILE *f;
2572 	char *line = NULL;
2573 	size_t linesize = 0;
2574 	int linenum;
2575 	int bad_options = 0;
2576 
2577 	if (depth < 0 || depth > READCONF_MAX_DEPTH)
2578 		fatal("Too many recursive configuration includes");
2579 
2580 	if ((f = fopen(filename, "r")) == NULL)
2581 		return 0;
2582 
2583 	if (flags & SSHCONF_CHECKPERM) {
2584 		struct stat sb;
2585 
2586 		if (fstat(fileno(f), &sb) == -1)
2587 			fatal("fstat %s: %s", filename, strerror(errno));
2588 		if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
2589 		    (sb.st_mode & 022) != 0))
2590 			fatal("Bad owner or permissions on %s", filename);
2591 	}
2592 
2593 	debug("Reading configuration data %.200s", filename);
2594 
2595 	/*
2596 	 * Mark that we are now processing the options.  This flag is turned
2597 	 * on/off by Host specifications.
2598 	 */
2599 	linenum = 0;
2600 	while (getline(&line, &linesize, f) != -1) {
2601 		/* Update line number counter. */
2602 		linenum++;
2603 		/*
2604 		 * Trim out comments and strip whitespace.
2605 		 * NB - preserve newlines, they are needed to reproduce
2606 		 * line numbers later for error messages.
2607 		 */
2608 		if (process_config_line_depth(options, pw, host, original_host,
2609 		    line, filename, linenum, activep, flags, want_final_pass,
2610 		    depth) != 0)
2611 			bad_options++;
2612 	}
2613 	free(line);
2614 	fclose(f);
2615 	if (bad_options > 0)
2616 		fatal("%s: terminating, %d bad configuration options",
2617 		    filename, bad_options);
2618 	return 1;
2619 }
2620 
2621 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
2622 int
2623 option_clear_or_none(const char *o)
2624 {
2625 	return o == NULL || strcasecmp(o, "none") == 0;
2626 }
2627 
2628 /*
2629  * Returns 1 if CanonicalizePermittedCNAMEs have been specified, 0 otherwise.
2630  * Allowed to be called on non-final configuration.
2631  */
2632 int
2633 config_has_permitted_cnames(Options *options)
2634 {
2635 	if (options->num_permitted_cnames == 1 &&
2636 	    strcasecmp(options->permitted_cnames[0].source_list, "none") == 0 &&
2637 	    strcmp(options->permitted_cnames[0].target_list, "") == 0)
2638 		return 0;
2639 	return options->num_permitted_cnames > 0;
2640 }
2641 
2642 /*
2643  * Initializes options to special values that indicate that they have not yet
2644  * been set.  Read_config_file will only set options with this value. Options
2645  * are processed in the following order: command line, user config file,
2646  * system config file.  Last, fill_default_options is called.
2647  */
2648 
2649 void
2650 initialize_options(Options * options)
2651 {
2652 	memset(options, 'X', sizeof(*options));
2653 	options->host_arg = NULL;
2654 	options->forward_agent = -1;
2655 	options->forward_agent_sock_path = NULL;
2656 	options->forward_x11 = -1;
2657 	options->forward_x11_trusted = -1;
2658 	options->forward_x11_timeout = -1;
2659 	options->stdio_forward_host = NULL;
2660 	options->stdio_forward_port = 0;
2661 	options->clear_forwardings = -1;
2662 	options->exit_on_forward_failure = -1;
2663 	options->xauth_location = NULL;
2664 	options->fwd_opts.gateway_ports = -1;
2665 	options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
2666 	options->fwd_opts.streamlocal_bind_unlink = -1;
2667 	options->pubkey_authentication = -1;
2668 #if defined(KRB4) || defined(KRB5)
2669 	options->kerberos_authentication = -1;
2670 #endif
2671 #if defined(AFS) || defined(KRB5)
2672 	options->kerberos_tgt_passing = -1;
2673 #endif
2674 #ifdef AFS
2675 	options->afs_token_passing = -1;
2676 #endif
2677 	options->gss_authentication = -1;
2678 	options->gss_deleg_creds = -1;
2679 	options->password_authentication = -1;
2680 	options->kbd_interactive_authentication = -1;
2681 	options->kbd_interactive_devices = NULL;
2682 	options->hostbased_authentication = -1;
2683 	options->batch_mode = -1;
2684 	options->check_host_ip = -1;
2685 	options->strict_host_key_checking = -1;
2686 	options->compression = -1;
2687 	options->tcp_keep_alive = -1;
2688 	options->port = -1;
2689 	options->address_family = -1;
2690 	options->connection_attempts = -1;
2691 	options->connection_timeout = -1;
2692 	options->number_of_password_prompts = -1;
2693 	options->ciphers = NULL;
2694 	options->macs = NULL;
2695 	options->kex_algorithms = NULL;
2696 	options->hostkeyalgorithms = NULL;
2697 	options->ca_sign_algorithms = NULL;
2698 	options->num_identity_files = 0;
2699 	memset(options->identity_keys, 0, sizeof(options->identity_keys));
2700 	options->num_certificate_files = 0;
2701 	memset(options->certificates, 0, sizeof(options->certificates));
2702 	options->hostname = NULL;
2703 	options->host_key_alias = NULL;
2704 	options->proxy_command = NULL;
2705 	options->jump_user = NULL;
2706 	options->jump_host = NULL;
2707 	options->jump_port = -1;
2708 	options->jump_extra = NULL;
2709 	options->user = NULL;
2710 	options->escape_char = -1;
2711 	options->num_system_hostfiles = 0;
2712 	options->num_user_hostfiles = 0;
2713 	options->local_forwards = NULL;
2714 	options->num_local_forwards = 0;
2715 	options->remote_forwards = NULL;
2716 	options->num_remote_forwards = 0;
2717 	options->permitted_remote_opens = NULL;
2718 	options->num_permitted_remote_opens = 0;
2719 	options->log_facility = SYSLOG_FACILITY_NOT_SET;
2720 	options->log_level = SYSLOG_LEVEL_NOT_SET;
2721 	options->num_log_verbose = 0;
2722 	options->log_verbose = NULL;
2723 	options->preferred_authentications = NULL;
2724 	options->bind_address = NULL;
2725 	options->bind_interface = NULL;
2726 	options->ipv6_prefer_temporary = -1;
2727 	options->pkcs11_provider = NULL;
2728 	options->sk_provider = NULL;
2729 	options->enable_ssh_keysign = - 1;
2730 	options->no_host_authentication_for_localhost = - 1;
2731 	options->identities_only = - 1;
2732 	options->rekey_limit = - 1;
2733 	options->rekey_interval = -1;
2734 	options->verify_host_key_dns = -1;
2735 	options->server_alive_interval = -1;
2736 	options->server_alive_count_max = -1;
2737 	options->send_env = NULL;
2738 	options->num_send_env = 0;
2739 	options->setenv = NULL;
2740 	options->num_setenv = 0;
2741 	options->control_path = NULL;
2742 	options->control_master = -1;
2743 	options->control_persist = -1;
2744 	options->control_persist_timeout = 0;
2745 	options->hash_known_hosts = -1;
2746 	options->tun_open = -1;
2747 	options->tun_local = -1;
2748 	options->tun_remote = -1;
2749 	options->local_command = NULL;
2750 	options->permit_local_command = -1;
2751 	options->remote_command = NULL;
2752 	options->add_keys_to_agent = -1;
2753 	options->add_keys_to_agent_lifespan = -1;
2754 	options->identity_agent = NULL;
2755 	options->visual_host_key = -1;
2756 	options->ip_qos_interactive = -1;
2757 	options->ip_qos_bulk = -1;
2758 	options->request_tty = -1;
2759 	options->session_type = -1;
2760 	options->stdin_null = -1;
2761 	options->fork_after_authentication = -1;
2762 	options->proxy_use_fdpass = -1;
2763 	options->ignored_unknown = NULL;
2764 	options->num_canonical_domains = 0;
2765 	options->num_permitted_cnames = 0;
2766 	options->canonicalize_max_dots = -1;
2767 	options->canonicalize_fallback_local = -1;
2768 	options->canonicalize_hostname = -1;
2769 	options->revoked_host_keys = NULL;
2770 	options->fingerprint_hash = -1;
2771 	options->update_hostkeys = -1;
2772 	options->hostbased_accepted_algos = NULL;
2773 	options->pubkey_accepted_algos = NULL;
2774 	options->known_hosts_command = NULL;
2775 	options->required_rsa_size = -1;
2776 	options->enable_escape_commandline = -1;
2777 	options->obscure_keystroke_timing_interval = -1;
2778 	options->tag = NULL;
2779 	options->channel_timeouts = NULL;
2780 	options->num_channel_timeouts = 0;
2781 	options->none_switch = -1;
2782 	options->none_enabled = -1;
2783 	options->hpn_disabled = -1;
2784 	options->hpn_buffer_size = -1;
2785 	options->tcp_rcv_buf_poll = -1;
2786 	options->tcp_rcv_buf = -1;
2787 	options->send_version_first = -1;
2788 }
2789 
2790 /*
2791  * A petite version of fill_default_options() that just fills the options
2792  * needed for hostname canonicalization to proceed.
2793  */
2794 void
2795 fill_default_options_for_canonicalization(Options *options)
2796 {
2797 	if (options->canonicalize_max_dots == -1)
2798 		options->canonicalize_max_dots = 1;
2799 	if (options->canonicalize_fallback_local == -1)
2800 		options->canonicalize_fallback_local = 1;
2801 	if (options->canonicalize_hostname == -1)
2802 		options->canonicalize_hostname = SSH_CANONICALISE_NO;
2803 }
2804 
2805 /*
2806  * Called after processing other sources of option data, this fills those
2807  * options for which no value has been specified with their default values.
2808  */
2809 int
2810 fill_default_options(Options * options)
2811 {
2812 	char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig;
2813 	char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig;
2814 	int ret = 0, r;
2815 
2816 	if (options->forward_agent == -1)
2817 		options->forward_agent = 0;
2818 	if (options->forward_x11 == -1)
2819 		options->forward_x11 = 0;
2820 	if (options->forward_x11_trusted == -1)
2821 		options->forward_x11_trusted = 0;
2822 	if (options->forward_x11_timeout == -1)
2823 		options->forward_x11_timeout = 1200;
2824 	/*
2825 	 * stdio forwarding (-W) changes the default for these but we defer
2826 	 * setting the values so they can be overridden.
2827 	 */
2828 	if (options->exit_on_forward_failure == -1)
2829 		options->exit_on_forward_failure =
2830 		    options->stdio_forward_host != NULL ? 1 : 0;
2831 	if (options->clear_forwardings == -1)
2832 		options->clear_forwardings =
2833 		    options->stdio_forward_host != NULL ? 1 : 0;
2834 	if (options->clear_forwardings == 1)
2835 		clear_forwardings(options);
2836 
2837 	if (options->xauth_location == NULL)
2838 		options->xauth_location = xstrdup(_PATH_XAUTH);
2839 	if (options->fwd_opts.gateway_ports == -1)
2840 		options->fwd_opts.gateway_ports = 0;
2841 	if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
2842 		options->fwd_opts.streamlocal_bind_mask = 0177;
2843 	if (options->fwd_opts.streamlocal_bind_unlink == -1)
2844 		options->fwd_opts.streamlocal_bind_unlink = 0;
2845 	if (options->pubkey_authentication == -1)
2846 		options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL;
2847 #if defined(KRB4) || defined(KRB5)
2848 	if (options->kerberos_authentication == -1)
2849 		options->kerberos_authentication = 1;
2850 #endif
2851 #if defined(AFS) || defined(KRB5)
2852 	if (options->kerberos_tgt_passing == -1)
2853 		options->kerberos_tgt_passing = 1;
2854 #endif
2855 #ifdef AFS
2856 	if (options->afs_token_passing == -1)
2857 		options->afs_token_passing = 1;
2858 #endif
2859 	if (options->gss_authentication == -1)
2860 		options->gss_authentication = 0;
2861 	if (options->gss_deleg_creds == -1)
2862 		options->gss_deleg_creds = 0;
2863 	if (options->password_authentication == -1)
2864 		options->password_authentication = 1;
2865 	if (options->kbd_interactive_authentication == -1)
2866 		options->kbd_interactive_authentication = 1;
2867 	if (options->hostbased_authentication == -1)
2868 		options->hostbased_authentication = 0;
2869 	if (options->batch_mode == -1)
2870 		options->batch_mode = 0;
2871 	if (options->check_host_ip == -1)
2872 		options->check_host_ip = 0;
2873 	if (options->strict_host_key_checking == -1)
2874 		options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK;
2875 	if (options->compression == -1)
2876 		options->compression = 0;
2877 	if (options->tcp_keep_alive == -1)
2878 		options->tcp_keep_alive = 1;
2879 	if (options->port == -1)
2880 		options->port = 0;	/* Filled in ssh_connect. */
2881 	if (options->address_family == -1)
2882 		options->address_family = AF_UNSPEC;
2883 	if (options->connection_attempts == -1)
2884 		options->connection_attempts = 1;
2885 	if (options->number_of_password_prompts == -1)
2886 		options->number_of_password_prompts = 3;
2887 	/* options->hostkeyalgorithms, default set in myproposals.h */
2888 	if (options->add_keys_to_agent == -1) {
2889 		options->add_keys_to_agent = 0;
2890 		options->add_keys_to_agent_lifespan = 0;
2891 	}
2892 	if (options->num_identity_files == 0) {
2893 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0);
2894 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0);
2895 		add_identity_file(options, "~/",
2896 		    _PATH_SSH_CLIENT_ID_ECDSA_SK, 0);
2897 		add_identity_file(options, "~/",
2898 		    _PATH_SSH_CLIENT_ID_ED25519, 0);
2899 		add_identity_file(options, "~/",
2900 		    _PATH_SSH_CLIENT_ID_ED25519_SK, 0);
2901 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0);
2902 #ifdef WITH_DSA
2903 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0);
2904 #endif
2905 	}
2906 	if (options->escape_char == -1)
2907 		options->escape_char = '~';
2908 	if (options->num_system_hostfiles == 0) {
2909 		options->system_hostfiles[options->num_system_hostfiles++] =
2910 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
2911 		options->system_hostfiles[options->num_system_hostfiles++] =
2912 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
2913 	}
2914 	if (options->update_hostkeys == -1) {
2915 		if (options->verify_host_key_dns <= 0 &&
2916 		    (options->num_user_hostfiles == 0 ||
2917 		    (options->num_user_hostfiles == 1 && strcmp(options->
2918 		    user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0)))
2919 			options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES;
2920 		else
2921 			options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO;
2922 	}
2923 	if (options->num_user_hostfiles == 0) {
2924 		options->user_hostfiles[options->num_user_hostfiles++] =
2925 		    xstrdup(_PATH_SSH_USER_HOSTFILE);
2926 		options->user_hostfiles[options->num_user_hostfiles++] =
2927 		    xstrdup(_PATH_SSH_USER_HOSTFILE2);
2928 	}
2929 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
2930 		options->log_level = SYSLOG_LEVEL_INFO;
2931 	if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
2932 		options->log_facility = SYSLOG_FACILITY_USER;
2933 	if (options->no_host_authentication_for_localhost == - 1)
2934 		options->no_host_authentication_for_localhost = 0;
2935 	if (options->identities_only == -1)
2936 		options->identities_only = 0;
2937 	if (options->enable_ssh_keysign == -1)
2938 		options->enable_ssh_keysign = 0;
2939 	if (options->rekey_limit == -1)
2940 		options->rekey_limit = 0;
2941 	if (options->rekey_interval == -1)
2942 		options->rekey_interval = 0;
2943 	if (options->verify_host_key_dns == -1)
2944 		options->verify_host_key_dns = 0;
2945 	if (options->server_alive_interval == -1)
2946 		options->server_alive_interval = 0;
2947 	if (options->server_alive_count_max == -1)
2948 		options->server_alive_count_max = 3;
2949 	if (options->none_switch == -1)
2950 	        options->none_switch = 0;
2951 	if (options->hpn_disabled == -1)
2952 	        options->hpn_disabled = 0;
2953 	if (options->hpn_buffer_size > -1)
2954 	{
2955 	  /* if a user tries to set the size to 0 set it to 1KB */
2956 		if (options->hpn_buffer_size == 0)
2957 			options->hpn_buffer_size = 1;
2958 		/*limit the buffer to 64MB*/
2959 		if (options->hpn_buffer_size > (SSHBUF_SIZE_MAX / 1024))
2960 		{
2961 			options->hpn_buffer_size = SSHBUF_SIZE_MAX;
2962 			debug("User requested buffer larger than 256MB. Request reverted to 256MB");
2963 		} else
2964 			options->hpn_buffer_size *= 1024;
2965 		debug("hpn_buffer_size set to %d", options->hpn_buffer_size);
2966 	}
2967 	if (options->tcp_rcv_buf == 0)
2968 		options->tcp_rcv_buf = 1;
2969 	if (options->tcp_rcv_buf > -1)
2970 		options->tcp_rcv_buf *=1024;
2971 	if (options->tcp_rcv_buf_poll == -1)
2972 		options->tcp_rcv_buf_poll = 1;
2973 	if (options->control_master == -1)
2974 		options->control_master = 0;
2975 	if (options->control_persist == -1) {
2976 		options->control_persist = 0;
2977 		options->control_persist_timeout = 0;
2978 	}
2979 	if (options->hash_known_hosts == -1)
2980 		options->hash_known_hosts = 0;
2981 	if (options->tun_open == -1)
2982 		options->tun_open = SSH_TUNMODE_NO;
2983 	if (options->tun_local == -1)
2984 		options->tun_local = SSH_TUNID_ANY;
2985 	if (options->tun_remote == -1)
2986 		options->tun_remote = SSH_TUNID_ANY;
2987 	if (options->permit_local_command == -1)
2988 		options->permit_local_command = 0;
2989 	if (options->visual_host_key == -1)
2990 		options->visual_host_key = 0;
2991 	if (options->ip_qos_interactive == -1)
2992 		options->ip_qos_interactive = IPTOS_DSCP_AF21;
2993 	if (options->ip_qos_bulk == -1)
2994 		options->ip_qos_bulk = IPTOS_DSCP_CS1;
2995 	if (options->request_tty == -1)
2996 		options->request_tty = REQUEST_TTY_AUTO;
2997 	if (options->session_type == -1)
2998 		options->session_type = SESSION_TYPE_DEFAULT;
2999 	if (options->stdin_null == -1)
3000 		options->stdin_null = 0;
3001 	if (options->fork_after_authentication == -1)
3002 		options->fork_after_authentication = 0;
3003 	if (options->proxy_use_fdpass == -1)
3004 		options->proxy_use_fdpass = 0;
3005 	if (options->canonicalize_max_dots == -1)
3006 		options->canonicalize_max_dots = 1;
3007 	if (options->canonicalize_fallback_local == -1)
3008 		options->canonicalize_fallback_local = 1;
3009 	if (options->canonicalize_hostname == -1)
3010 		options->canonicalize_hostname = SSH_CANONICALISE_NO;
3011 	if (options->fingerprint_hash == -1)
3012 		options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
3013 	if (options->sk_provider == NULL)
3014 		options->sk_provider = xstrdup("internal");
3015 	if (options->required_rsa_size == -1)
3016 		options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
3017 	if (options->enable_escape_commandline == -1)
3018 		options->enable_escape_commandline = 0;
3019 	if (options->obscure_keystroke_timing_interval == -1) {
3020 		options->obscure_keystroke_timing_interval =
3021 		    SSH_KEYSTROKE_DEFAULT_INTERVAL_MS;
3022 	}
3023 
3024 	/* Expand KEX name lists */
3025 	all_cipher = cipher_alg_list(',', 0);
3026 	all_mac = mac_alg_list(',');
3027 	all_kex = kex_alg_list(',');
3028 	all_key = sshkey_alg_list(0, 0, 1, ',');
3029 	all_sig = sshkey_alg_list(0, 1, 1, ',');
3030 	/* remove unsupported algos from default lists */
3031 	def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher);
3032 	def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac);
3033 	def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex);
3034 	def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
3035 	def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
3036 #define ASSEMBLE(what, defaults, all) \
3037 	do { \
3038 		if ((r = kex_assemble_names(&options->what, \
3039 		    defaults, all)) != 0) { \
3040 			error_fr(r, "%s", #what); \
3041 			goto fail; \
3042 		} \
3043 	} while (0)
3044 	ASSEMBLE(ciphers, def_cipher, all_cipher);
3045 	ASSEMBLE(macs, def_mac, all_mac);
3046 	ASSEMBLE(kex_algorithms, def_kex, all_kex);
3047 	ASSEMBLE(hostbased_accepted_algos, def_key, all_key);
3048 	ASSEMBLE(pubkey_accepted_algos, def_key, all_key);
3049 	ASSEMBLE(ca_sign_algorithms, def_sig, all_sig);
3050 #undef ASSEMBLE
3051 
3052 	if (options->send_version_first == -1)
3053 		options->send_version_first = 1;
3054 #define CLEAR_ON_NONE(v) \
3055 	do { \
3056 		if (option_clear_or_none(v)) { \
3057 			free(v); \
3058 			v = NULL; \
3059 		} \
3060 	} while(0)
3061 #define CLEAR_ON_NONE_ARRAY(v, nv, none) \
3062 	do { \
3063 		if (options->nv == 1 && \
3064 		    strcasecmp(options->v[0], none) == 0) { \
3065 			free(options->v[0]); \
3066 			free(options->v); \
3067 			options->v = NULL; \
3068 			options->nv = 0; \
3069 		} \
3070 	} while (0)
3071 	CLEAR_ON_NONE(options->local_command);
3072 	CLEAR_ON_NONE(options->remote_command);
3073 	CLEAR_ON_NONE(options->proxy_command);
3074 	CLEAR_ON_NONE(options->control_path);
3075 	CLEAR_ON_NONE(options->revoked_host_keys);
3076 	CLEAR_ON_NONE(options->pkcs11_provider);
3077 	CLEAR_ON_NONE(options->sk_provider);
3078 	CLEAR_ON_NONE(options->known_hosts_command);
3079 	CLEAR_ON_NONE_ARRAY(channel_timeouts, num_channel_timeouts, "none");
3080 #undef CLEAR_ON_NONE
3081 #undef CLEAR_ON_NONE_ARRAY
3082 	if (options->jump_host != NULL &&
3083 	    strcmp(options->jump_host, "none") == 0 &&
3084 	    options->jump_port == 0 && options->jump_user == NULL) {
3085 		free(options->jump_host);
3086 		options->jump_host = NULL;
3087 	}
3088 	if (options->num_permitted_cnames == 1 &&
3089 	    !config_has_permitted_cnames(options)) {
3090 		/* clean up CanonicalizePermittedCNAMEs=none */
3091 		free(options->permitted_cnames[0].source_list);
3092 		free(options->permitted_cnames[0].target_list);
3093 		memset(options->permitted_cnames, '\0',
3094 		    sizeof(*options->permitted_cnames));
3095 		options->num_permitted_cnames = 0;
3096 	}
3097 	/* options->identity_agent distinguishes NULL from 'none' */
3098 	/* options->user will be set in the main program if appropriate */
3099 	/* options->hostname will be set in the main program if appropriate */
3100 	/* options->host_key_alias should not be set by default */
3101 	/* options->preferred_authentications will be set in ssh */
3102 
3103 	/* success */
3104 	ret = 0;
3105  fail:
3106 	free(all_cipher);
3107 	free(all_mac);
3108 	free(all_kex);
3109 	free(all_key);
3110 	free(all_sig);
3111 	free(def_cipher);
3112 	free(def_mac);
3113 	free(def_kex);
3114 	free(def_key);
3115 	free(def_sig);
3116 	return ret;
3117 }
3118 
3119 void
3120 free_options(Options *o)
3121 {
3122 	int i;
3123 
3124 	if (o == NULL)
3125 		return;
3126 
3127 #define FREE_ARRAY(type, n, a) \
3128 	do { \
3129 		type _i; \
3130 		for (_i = 0; _i < (n); _i++) \
3131 			free((a)[_i]); \
3132 	} while (0)
3133 
3134 	free(o->forward_agent_sock_path);
3135 	free(o->xauth_location);
3136 	FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose);
3137 	free(o->log_verbose);
3138 	free(o->ciphers);
3139 	free(o->macs);
3140 	free(o->hostkeyalgorithms);
3141 	free(o->kex_algorithms);
3142 	free(o->ca_sign_algorithms);
3143 	free(o->hostname);
3144 	free(o->host_key_alias);
3145 	free(o->proxy_command);
3146 	free(o->user);
3147 	FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles);
3148 	FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles);
3149 	free(o->preferred_authentications);
3150 	free(o->bind_address);
3151 	free(o->bind_interface);
3152 	free(o->pkcs11_provider);
3153 	free(o->sk_provider);
3154 	for (i = 0; i < o->num_identity_files; i++) {
3155 		free(o->identity_files[i]);
3156 		sshkey_free(o->identity_keys[i]);
3157 	}
3158 	for (i = 0; i < o->num_certificate_files; i++) {
3159 		free(o->certificate_files[i]);
3160 		sshkey_free(o->certificates[i]);
3161 	}
3162 	free(o->identity_agent);
3163 	for (i = 0; i < o->num_local_forwards; i++) {
3164 		free(o->local_forwards[i].listen_host);
3165 		free(o->local_forwards[i].listen_path);
3166 		free(o->local_forwards[i].connect_host);
3167 		free(o->local_forwards[i].connect_path);
3168 	}
3169 	free(o->local_forwards);
3170 	for (i = 0; i < o->num_remote_forwards; i++) {
3171 		free(o->remote_forwards[i].listen_host);
3172 		free(o->remote_forwards[i].listen_path);
3173 		free(o->remote_forwards[i].connect_host);
3174 		free(o->remote_forwards[i].connect_path);
3175 	}
3176 	free(o->remote_forwards);
3177 	free(o->stdio_forward_host);
3178 	FREE_ARRAY(u_int, o->num_send_env, o->send_env);
3179 	free(o->send_env);
3180 	FREE_ARRAY(u_int, o->num_setenv, o->setenv);
3181 	free(o->setenv);
3182 	free(o->control_path);
3183 	free(o->local_command);
3184 	free(o->remote_command);
3185 	FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains);
3186 	for (i = 0; i < o->num_permitted_cnames; i++) {
3187 		free(o->permitted_cnames[i].source_list);
3188 		free(o->permitted_cnames[i].target_list);
3189 	}
3190 	free(o->revoked_host_keys);
3191 	free(o->hostbased_accepted_algos);
3192 	free(o->pubkey_accepted_algos);
3193 	free(o->jump_user);
3194 	free(o->jump_host);
3195 	free(o->jump_extra);
3196 	free(o->ignored_unknown);
3197 	explicit_bzero(o, sizeof(*o));
3198 #undef FREE_ARRAY
3199 }
3200 
3201 struct fwdarg {
3202 	char *arg;
3203 	int ispath;
3204 };
3205 
3206 /*
3207  * parse_fwd_field
3208  * parses the next field in a port forwarding specification.
3209  * sets fwd to the parsed field and advances p past the colon
3210  * or sets it to NULL at end of string.
3211  * returns 0 on success, else non-zero.
3212  */
3213 static int
3214 parse_fwd_field(char **p, struct fwdarg *fwd)
3215 {
3216 	char *ep, *cp = *p;
3217 	int ispath = 0;
3218 
3219 	if (*cp == '\0') {
3220 		*p = NULL;
3221 		return -1;	/* end of string */
3222 	}
3223 
3224 	/*
3225 	 * A field escaped with square brackets is used literally.
3226 	 * XXX - allow ']' to be escaped via backslash?
3227 	 */
3228 	if (*cp == '[') {
3229 		/* find matching ']' */
3230 		for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
3231 			if (*ep == '/')
3232 				ispath = 1;
3233 		}
3234 		/* no matching ']' or not at end of field. */
3235 		if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
3236 			return -1;
3237 		/* NUL terminate the field and advance p past the colon */
3238 		*ep++ = '\0';
3239 		if (*ep != '\0')
3240 			*ep++ = '\0';
3241 		fwd->arg = cp + 1;
3242 		fwd->ispath = ispath;
3243 		*p = ep;
3244 		return 0;
3245 	}
3246 
3247 	for (cp = *p; *cp != '\0'; cp++) {
3248 		switch (*cp) {
3249 		case '\\':
3250 			memmove(cp, cp + 1, strlen(cp + 1) + 1);
3251 			if (*cp == '\0')
3252 				return -1;
3253 			break;
3254 		case '/':
3255 			ispath = 1;
3256 			break;
3257 		case ':':
3258 			*cp++ = '\0';
3259 			goto done;
3260 		}
3261 	}
3262 done:
3263 	fwd->arg = *p;
3264 	fwd->ispath = ispath;
3265 	*p = cp;
3266 	return 0;
3267 }
3268 
3269 /*
3270  * parse_forward
3271  * parses a string containing a port forwarding specification of the form:
3272  *   dynamicfwd == 0
3273  *	[listenhost:]listenport|listenpath:connecthost:connectport|connectpath
3274  *	listenpath:connectpath
3275  *   dynamicfwd == 1
3276  *	[listenhost:]listenport
3277  * returns number of arguments parsed or zero on error
3278  */
3279 int
3280 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
3281 {
3282 	struct fwdarg fwdargs[4];
3283 	char *p, *cp;
3284 	int i, err;
3285 
3286 	memset(fwd, 0, sizeof(*fwd));
3287 	memset(fwdargs, 0, sizeof(fwdargs));
3288 
3289 	/*
3290 	 * We expand environment variables before checking if we think they're
3291 	 * paths so that if ${VAR} expands to a fully qualified path it is
3292 	 * treated as a path.
3293 	 */
3294 	cp = p = dollar_expand(&err, fwdspec);
3295 	if (p == NULL || err)
3296 		return 0;
3297 
3298 	/* skip leading spaces */
3299 	while (isspace((u_char)*cp))
3300 		cp++;
3301 
3302 	for (i = 0; i < 4; ++i) {
3303 		if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
3304 			break;
3305 	}
3306 
3307 	/* Check for trailing garbage */
3308 	if (cp != NULL && *cp != '\0') {
3309 		i = 0;	/* failure */
3310 	}
3311 
3312 	switch (i) {
3313 	case 1:
3314 		if (fwdargs[0].ispath) {
3315 			fwd->listen_path = xstrdup(fwdargs[0].arg);
3316 			fwd->listen_port = PORT_STREAMLOCAL;
3317 		} else {
3318 			fwd->listen_host = NULL;
3319 			fwd->listen_port = a2port(fwdargs[0].arg);
3320 		}
3321 		fwd->connect_host = xstrdup("socks");
3322 		break;
3323 
3324 	case 2:
3325 		if (fwdargs[0].ispath && fwdargs[1].ispath) {
3326 			fwd->listen_path = xstrdup(fwdargs[0].arg);
3327 			fwd->listen_port = PORT_STREAMLOCAL;
3328 			fwd->connect_path = xstrdup(fwdargs[1].arg);
3329 			fwd->connect_port = PORT_STREAMLOCAL;
3330 		} else if (fwdargs[1].ispath) {
3331 			fwd->listen_host = NULL;
3332 			fwd->listen_port = a2port(fwdargs[0].arg);
3333 			fwd->connect_path = xstrdup(fwdargs[1].arg);
3334 			fwd->connect_port = PORT_STREAMLOCAL;
3335 		} else {
3336 			fwd->listen_host = xstrdup(fwdargs[0].arg);
3337 			fwd->listen_port = a2port(fwdargs[1].arg);
3338 			fwd->connect_host = xstrdup("socks");
3339 		}
3340 		break;
3341 
3342 	case 3:
3343 		if (fwdargs[0].ispath) {
3344 			fwd->listen_path = xstrdup(fwdargs[0].arg);
3345 			fwd->listen_port = PORT_STREAMLOCAL;
3346 			fwd->connect_host = xstrdup(fwdargs[1].arg);
3347 			fwd->connect_port = a2port(fwdargs[2].arg);
3348 		} else if (fwdargs[2].ispath) {
3349 			fwd->listen_host = xstrdup(fwdargs[0].arg);
3350 			fwd->listen_port = a2port(fwdargs[1].arg);
3351 			fwd->connect_path = xstrdup(fwdargs[2].arg);
3352 			fwd->connect_port = PORT_STREAMLOCAL;
3353 		} else {
3354 			fwd->listen_host = NULL;
3355 			fwd->listen_port = a2port(fwdargs[0].arg);
3356 			fwd->connect_host = xstrdup(fwdargs[1].arg);
3357 			fwd->connect_port = a2port(fwdargs[2].arg);
3358 		}
3359 		break;
3360 
3361 	case 4:
3362 		fwd->listen_host = xstrdup(fwdargs[0].arg);
3363 		fwd->listen_port = a2port(fwdargs[1].arg);
3364 		fwd->connect_host = xstrdup(fwdargs[2].arg);
3365 		fwd->connect_port = a2port(fwdargs[3].arg);
3366 		break;
3367 	default:
3368 		i = 0; /* failure */
3369 	}
3370 
3371 	free(p);
3372 
3373 	if (dynamicfwd) {
3374 		if (!(i == 1 || i == 2))
3375 			goto fail_free;
3376 	} else {
3377 		if (!(i == 3 || i == 4)) {
3378 			if (fwd->connect_path == NULL &&
3379 			    fwd->listen_path == NULL)
3380 				goto fail_free;
3381 		}
3382 		if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
3383 			goto fail_free;
3384 	}
3385 
3386 	if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
3387 	    (!remotefwd && fwd->listen_port == 0))
3388 		goto fail_free;
3389 	if (fwd->connect_host != NULL &&
3390 	    strlen(fwd->connect_host) >= NI_MAXHOST)
3391 		goto fail_free;
3392 	/*
3393 	 * XXX - if connecting to a remote socket, max sun len may not
3394 	 * match this host
3395 	 */
3396 	if (fwd->connect_path != NULL &&
3397 	    strlen(fwd->connect_path) >= PATH_MAX_SUN)
3398 		goto fail_free;
3399 	if (fwd->listen_host != NULL &&
3400 	    strlen(fwd->listen_host) >= NI_MAXHOST)
3401 		goto fail_free;
3402 	if (fwd->listen_path != NULL &&
3403 	    strlen(fwd->listen_path) >= PATH_MAX_SUN)
3404 		goto fail_free;
3405 
3406 	return (i);
3407 
3408  fail_free:
3409 	free(fwd->connect_host);
3410 	fwd->connect_host = NULL;
3411 	free(fwd->connect_path);
3412 	fwd->connect_path = NULL;
3413 	free(fwd->listen_host);
3414 	fwd->listen_host = NULL;
3415 	free(fwd->listen_path);
3416 	fwd->listen_path = NULL;
3417 	return (0);
3418 }
3419 
3420 int
3421 parse_jump(const char *s, Options *o, int active)
3422 {
3423 	char *orig, *sdup, *cp;
3424 	char *host = NULL, *user = NULL;
3425 	int r, ret = -1, port = -1, first;
3426 
3427 	active &= o->proxy_command == NULL && o->jump_host == NULL;
3428 
3429 	orig = sdup = xstrdup(s);
3430 
3431 	/* Remove comment and trailing whitespace */
3432 	if ((cp = strchr(orig, '#')) != NULL)
3433 		*cp = '\0';
3434 	rtrim(orig);
3435 
3436 	first = active;
3437 	do {
3438 		if (strcasecmp(s, "none") == 0)
3439 			break;
3440 		if ((cp = strrchr(sdup, ',')) == NULL)
3441 			cp = sdup; /* last */
3442 		else
3443 			*cp++ = '\0';
3444 
3445 		if (first) {
3446 			/* First argument and configuration is active */
3447 			r = parse_ssh_uri(cp, &user, &host, &port);
3448 			if (r == -1 || (r == 1 &&
3449 			    parse_user_host_port(cp, &user, &host, &port) != 0))
3450 				goto out;
3451 		} else {
3452 			/* Subsequent argument or inactive configuration */
3453 			r = parse_ssh_uri(cp, NULL, NULL, NULL);
3454 			if (r == -1 || (r == 1 &&
3455 			    parse_user_host_port(cp, NULL, NULL, NULL) != 0))
3456 				goto out;
3457 		}
3458 		first = 0; /* only check syntax for subsequent hosts */
3459 	} while (cp != sdup);
3460 	/* success */
3461 	if (active) {
3462 		if (strcasecmp(s, "none") == 0) {
3463 			o->jump_host = xstrdup("none");
3464 			o->jump_port = 0;
3465 		} else {
3466 			o->jump_user = user;
3467 			o->jump_host = host;
3468 			o->jump_port = port;
3469 			o->proxy_command = xstrdup("none");
3470 			user = host = NULL;
3471 			if ((cp = strrchr(s, ',')) != NULL && cp != s) {
3472 				o->jump_extra = xstrdup(s);
3473 				o->jump_extra[cp - s] = '\0';
3474 			}
3475 		}
3476 	}
3477 	ret = 0;
3478  out:
3479 	free(orig);
3480 	free(user);
3481 	free(host);
3482 	return ret;
3483 }
3484 
3485 int
3486 parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp)
3487 {
3488 	char *user = NULL, *host = NULL, *path = NULL;
3489 	int r, port;
3490 
3491 	r = parse_uri("ssh", uri, &user, &host, &port, &path);
3492 	if (r == 0 && path != NULL)
3493 		r = -1;		/* path not allowed */
3494 	if (r == 0) {
3495 		if (userp != NULL) {
3496 			*userp = user;
3497 			user = NULL;
3498 		}
3499 		if (hostp != NULL) {
3500 			*hostp = host;
3501 			host = NULL;
3502 		}
3503 		if (portp != NULL)
3504 			*portp = port;
3505 	}
3506 	free(user);
3507 	free(host);
3508 	free(path);
3509 	return r;
3510 }
3511 
3512 /* XXX the following is a near-verbatim copy from servconf.c; refactor */
3513 static const char *
3514 fmt_multistate_int(int val, const struct multistate *m)
3515 {
3516 	u_int i;
3517 
3518 	for (i = 0; m[i].key != NULL; i++) {
3519 		if (m[i].value == val)
3520 			return m[i].key;
3521 	}
3522 	return "UNKNOWN";
3523 }
3524 
3525 static const char *
3526 fmt_intarg(OpCodes code, int val)
3527 {
3528 	if (val == -1)
3529 		return "unset";
3530 	switch (code) {
3531 	case oAddressFamily:
3532 		return fmt_multistate_int(val, multistate_addressfamily);
3533 	case oVerifyHostKeyDNS:
3534 	case oUpdateHostkeys:
3535 		return fmt_multistate_int(val, multistate_yesnoask);
3536 	case oStrictHostKeyChecking:
3537 		return fmt_multistate_int(val, multistate_strict_hostkey);
3538 	case oControlMaster:
3539 		return fmt_multistate_int(val, multistate_controlmaster);
3540 	case oTunnel:
3541 		return fmt_multistate_int(val, multistate_tunnel);
3542 	case oRequestTTY:
3543 		return fmt_multistate_int(val, multistate_requesttty);
3544 	case oSessionType:
3545 		return fmt_multistate_int(val, multistate_sessiontype);
3546 	case oCanonicalizeHostname:
3547 		return fmt_multistate_int(val, multistate_canonicalizehostname);
3548 	case oAddKeysToAgent:
3549 		return fmt_multistate_int(val, multistate_yesnoaskconfirm);
3550 	case oPubkeyAuthentication:
3551 		return fmt_multistate_int(val, multistate_pubkey_auth);
3552 	case oFingerprintHash:
3553 		return ssh_digest_alg_name(val);
3554 	default:
3555 		switch (val) {
3556 		case 0:
3557 			return "no";
3558 		case 1:
3559 			return "yes";
3560 		default:
3561 			return "UNKNOWN";
3562 		}
3563 	}
3564 }
3565 
3566 static const char *
3567 lookup_opcode_name(OpCodes code)
3568 {
3569 	u_int i;
3570 
3571 	for (i = 0; keywords[i].name != NULL; i++)
3572 		if (keywords[i].opcode == code)
3573 			return(keywords[i].name);
3574 	return "UNKNOWN";
3575 }
3576 
3577 static void
3578 dump_cfg_int(OpCodes code, int val)
3579 {
3580 	if (code == oObscureKeystrokeTiming) {
3581 		if (val == 0) {
3582 			printf("%s no\n", lookup_opcode_name(code));
3583 			return;
3584 		} else if (val == SSH_KEYSTROKE_DEFAULT_INTERVAL_MS) {
3585 			printf("%s yes\n", lookup_opcode_name(code));
3586 			return;
3587 		}
3588 		/* FALLTHROUGH */
3589 	}
3590 	printf("%s %d\n", lookup_opcode_name(code), val);
3591 }
3592 
3593 static void
3594 dump_cfg_fmtint(OpCodes code, int val)
3595 {
3596 	printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
3597 }
3598 
3599 static void
3600 dump_cfg_string(OpCodes code, const char *val)
3601 {
3602 	if (val == NULL)
3603 		return;
3604 	printf("%s %s\n", lookup_opcode_name(code), val);
3605 }
3606 
3607 static void
3608 dump_cfg_strarray(OpCodes code, u_int count, char **vals)
3609 {
3610 	u_int i;
3611 
3612 	for (i = 0; i < count; i++)
3613 		printf("%s %s\n", lookup_opcode_name(code), vals[i]);
3614 }
3615 
3616 static void
3617 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
3618 {
3619 	u_int i;
3620 
3621 	printf("%s", lookup_opcode_name(code));
3622 	if (count == 0)
3623 		printf(" none");
3624 	for (i = 0; i < count; i++)
3625 		printf(" %s",  vals[i]);
3626 	printf("\n");
3627 }
3628 
3629 static void
3630 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
3631 {
3632 	const struct Forward *fwd;
3633 	u_int i;
3634 
3635 	/* oDynamicForward */
3636 	for (i = 0; i < count; i++) {
3637 		fwd = &fwds[i];
3638 		if (code == oDynamicForward && fwd->connect_host != NULL &&
3639 		    strcmp(fwd->connect_host, "socks") != 0)
3640 			continue;
3641 		if (code == oLocalForward && fwd->connect_host != NULL &&
3642 		    strcmp(fwd->connect_host, "socks") == 0)
3643 			continue;
3644 		printf("%s", lookup_opcode_name(code));
3645 		if (fwd->listen_port == PORT_STREAMLOCAL)
3646 			printf(" %s", fwd->listen_path);
3647 		else if (fwd->listen_host == NULL)
3648 			printf(" %d", fwd->listen_port);
3649 		else {
3650 			printf(" [%s]:%d",
3651 			    fwd->listen_host, fwd->listen_port);
3652 		}
3653 		if (code != oDynamicForward) {
3654 			if (fwd->connect_port == PORT_STREAMLOCAL)
3655 				printf(" %s", fwd->connect_path);
3656 			else if (fwd->connect_host == NULL)
3657 				printf(" %d", fwd->connect_port);
3658 			else {
3659 				printf(" [%s]:%d",
3660 				    fwd->connect_host, fwd->connect_port);
3661 			}
3662 		}
3663 		printf("\n");
3664 	}
3665 }
3666 
3667 void
3668 dump_client_config(Options *o, const char *host)
3669 {
3670 	int i, r;
3671 	char buf[8], *all_key;
3672 
3673 	/*
3674 	 * Expand HostKeyAlgorithms name lists. This isn't handled in
3675 	 * fill_default_options() like the other algorithm lists because
3676 	 * the host key algorithms are by default dynamically chosen based
3677 	 * on the host's keys found in known_hosts.
3678 	 */
3679 	all_key = sshkey_alg_list(0, 0, 1, ',');
3680 	if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(),
3681 	    all_key)) != 0)
3682 		fatal_fr(r, "expand HostKeyAlgorithms");
3683 	free(all_key);
3684 
3685 	/* Most interesting options first: user, host, port */
3686 	dump_cfg_string(oHost, o->host_arg);
3687 	dump_cfg_string(oUser, o->user);
3688 	dump_cfg_string(oHostname, host);
3689 	dump_cfg_int(oPort, o->port);
3690 
3691 	/* Flag options */
3692 	dump_cfg_fmtint(oAddressFamily, o->address_family);
3693 	dump_cfg_fmtint(oBatchMode, o->batch_mode);
3694 	dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
3695 	dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
3696 	dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
3697 	dump_cfg_fmtint(oCompression, o->compression);
3698 	dump_cfg_fmtint(oControlMaster, o->control_master);
3699 	dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
3700 	dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings);
3701 	dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
3702 	dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
3703 	dump_cfg_fmtint(oForwardX11, o->forward_x11);
3704 	dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
3705 	dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
3706 #ifdef GSSAPI
3707 	dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
3708 	dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
3709 #endif /* GSSAPI */
3710 	dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
3711 	dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
3712 	dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
3713 	dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
3714 	dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
3715 	dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
3716 	dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
3717 	dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
3718 	dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
3719 	dump_cfg_fmtint(oRequestTTY, o->request_tty);
3720 	dump_cfg_fmtint(oSessionType, o->session_type);
3721 	dump_cfg_fmtint(oStdinNull, o->stdin_null);
3722 	dump_cfg_fmtint(oForkAfterAuthentication, o->fork_after_authentication);
3723 	dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
3724 	dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
3725 	dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
3726 	dump_cfg_fmtint(oTunnel, o->tun_open);
3727 	dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
3728 	dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
3729 	dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
3730 	dump_cfg_fmtint(oEnableEscapeCommandline, o->enable_escape_commandline);
3731 
3732 	/* Integer options */
3733 	dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
3734 	dump_cfg_int(oConnectionAttempts, o->connection_attempts);
3735 	dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
3736 	dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
3737 	dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
3738 	dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
3739 	dump_cfg_int(oRequiredRSASize, o->required_rsa_size);
3740 	dump_cfg_int(oObscureKeystrokeTiming,
3741 	    o->obscure_keystroke_timing_interval);
3742 
3743 	/* String options */
3744 	dump_cfg_string(oBindAddress, o->bind_address);
3745 	dump_cfg_string(oBindInterface, o->bind_interface);
3746 	dump_cfg_string(oCiphers, o->ciphers);
3747 	dump_cfg_string(oControlPath, o->control_path);
3748 	dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
3749 	dump_cfg_string(oHostKeyAlias, o->host_key_alias);
3750 	dump_cfg_string(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos);
3751 	dump_cfg_string(oIdentityAgent, o->identity_agent);
3752 	dump_cfg_string(oIgnoreUnknown, o->ignored_unknown);
3753 	dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
3754 	dump_cfg_string(oKexAlgorithms, o->kex_algorithms);
3755 	dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms);
3756 	dump_cfg_string(oLocalCommand, o->local_command);
3757 	dump_cfg_string(oRemoteCommand, o->remote_command);
3758 	dump_cfg_string(oLogLevel, log_level_name(o->log_level));
3759 	dump_cfg_string(oMacs, o->macs);
3760 #ifdef ENABLE_PKCS11
3761 	dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
3762 #endif
3763 	dump_cfg_string(oSecurityKeyProvider, o->sk_provider);
3764 	dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
3765 	dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos);
3766 	dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
3767 	dump_cfg_string(oXAuthLocation, o->xauth_location);
3768 	dump_cfg_string(oKnownHostsCommand, o->known_hosts_command);
3769 	dump_cfg_string(oTag, o->tag);
3770 
3771 	/* Forwards */
3772 	dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
3773 	dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
3774 	dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
3775 
3776 	/* String array options */
3777 	dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
3778 	dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
3779 	dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files);
3780 	dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
3781 	dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
3782 	dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
3783 	dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv);
3784 	dump_cfg_strarray_oneline(oLogVerbose,
3785 	    o->num_log_verbose, o->log_verbose);
3786 	dump_cfg_strarray_oneline(oChannelTimeout,
3787 	    o->num_channel_timeouts, o->channel_timeouts);
3788 
3789 	/* Special cases */
3790 
3791 	/* PermitRemoteOpen */
3792 	if (o->num_permitted_remote_opens == 0)
3793 		printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen));
3794 	else
3795 		dump_cfg_strarray_oneline(oPermitRemoteOpen,
3796 		    o->num_permitted_remote_opens, o->permitted_remote_opens);
3797 
3798 	/* AddKeysToAgent */
3799 	if (o->add_keys_to_agent_lifespan <= 0)
3800 		dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent);
3801 	else {
3802 		printf("addkeystoagent%s %d\n",
3803 		    o->add_keys_to_agent == 3 ? " confirm" : "",
3804 		    o->add_keys_to_agent_lifespan);
3805 	}
3806 
3807 	/* oForwardAgent */
3808 	if (o->forward_agent_sock_path == NULL)
3809 		dump_cfg_fmtint(oForwardAgent, o->forward_agent);
3810 	else
3811 		dump_cfg_string(oForwardAgent, o->forward_agent_sock_path);
3812 
3813 	/* oConnectTimeout */
3814 	if (o->connection_timeout == -1)
3815 		printf("connecttimeout none\n");
3816 	else
3817 		dump_cfg_int(oConnectTimeout, o->connection_timeout);
3818 
3819 	/* oTunnelDevice */
3820 	printf("tunneldevice");
3821 	if (o->tun_local == SSH_TUNID_ANY)
3822 		printf(" any");
3823 	else
3824 		printf(" %d", o->tun_local);
3825 	if (o->tun_remote == SSH_TUNID_ANY)
3826 		printf(":any");
3827 	else
3828 		printf(":%d", o->tun_remote);
3829 	printf("\n");
3830 
3831 	/* oCanonicalizePermittedCNAMEs */
3832 	printf("canonicalizePermittedcnames");
3833 	if (o->num_permitted_cnames == 0)
3834 		printf(" none");
3835 	for (i = 0; i < o->num_permitted_cnames; i++) {
3836 		printf(" %s:%s", o->permitted_cnames[i].source_list,
3837 		    o->permitted_cnames[i].target_list);
3838 	}
3839 	printf("\n");
3840 
3841 	/* oControlPersist */
3842 	if (o->control_persist == 0 || o->control_persist_timeout == 0)
3843 		dump_cfg_fmtint(oControlPersist, o->control_persist);
3844 	else
3845 		dump_cfg_int(oControlPersist, o->control_persist_timeout);
3846 
3847 	/* oEscapeChar */
3848 	if (o->escape_char == SSH_ESCAPECHAR_NONE)
3849 		printf("escapechar none\n");
3850 	else {
3851 		vis(buf, o->escape_char, VIS_WHITE, 0);
3852 		printf("escapechar %s\n", buf);
3853 	}
3854 
3855 	/* oIPQoS */
3856 	printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
3857 	printf("%s\n", iptos2str(o->ip_qos_bulk));
3858 
3859 	/* oRekeyLimit */
3860 	printf("rekeylimit %llu %d\n",
3861 	    (unsigned long long)o->rekey_limit, o->rekey_interval);
3862 
3863 	/* oStreamLocalBindMask */
3864 	printf("streamlocalbindmask 0%o\n",
3865 	    o->fwd_opts.streamlocal_bind_mask);
3866 
3867 	/* oLogFacility */
3868 	printf("syslogfacility %s\n", log_facility_name(o->log_facility));
3869 
3870 	/* oProxyCommand / oProxyJump */
3871 	if (o->jump_host == NULL)
3872 		dump_cfg_string(oProxyCommand, o->proxy_command);
3873 	else {
3874 		/* Check for numeric addresses */
3875 		i = strchr(o->jump_host, ':') != NULL ||
3876 		    strspn(o->jump_host, "1234567890.") == strlen(o->jump_host);
3877 		snprintf(buf, sizeof(buf), "%d", o->jump_port);
3878 		printf("proxyjump %s%s%s%s%s%s%s%s%s\n",
3879 		    /* optional additional jump spec */
3880 		    o->jump_extra == NULL ? "" : o->jump_extra,
3881 		    o->jump_extra == NULL ? "" : ",",
3882 		    /* optional user */
3883 		    o->jump_user == NULL ? "" : o->jump_user,
3884 		    o->jump_user == NULL ? "" : "@",
3885 		    /* opening [ if hostname is numeric */
3886 		    i ? "[" : "",
3887 		    /* mandatory hostname */
3888 		    o->jump_host,
3889 		    /* closing ] if hostname is numeric */
3890 		    i ? "]" : "",
3891 		    /* optional port number */
3892 		    o->jump_port <= 0 ? "" : ":",
3893 		    o->jump_port <= 0 ? "" : buf);
3894 	}
3895 }
3896