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