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