xref: /openbsd/usr.bin/ssh/readconf.c (revision 4bdff4be)
1 /* $OpenBSD: readconf.c,v 1.384 2024/01/11 01:45:36 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 #ifdef WITH_DSA
2690 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0);
2691 #endif
2692 	}
2693 	if (options->escape_char == -1)
2694 		options->escape_char = '~';
2695 	if (options->num_system_hostfiles == 0) {
2696 		options->system_hostfiles[options->num_system_hostfiles++] =
2697 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
2698 		options->system_hostfiles[options->num_system_hostfiles++] =
2699 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
2700 	}
2701 	if (options->update_hostkeys == -1) {
2702 		if (options->verify_host_key_dns <= 0 &&
2703 		    (options->num_user_hostfiles == 0 ||
2704 		    (options->num_user_hostfiles == 1 && strcmp(options->
2705 		    user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0)))
2706 			options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES;
2707 		else
2708 			options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO;
2709 	}
2710 	if (options->num_user_hostfiles == 0) {
2711 		options->user_hostfiles[options->num_user_hostfiles++] =
2712 		    xstrdup(_PATH_SSH_USER_HOSTFILE);
2713 		options->user_hostfiles[options->num_user_hostfiles++] =
2714 		    xstrdup(_PATH_SSH_USER_HOSTFILE2);
2715 	}
2716 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
2717 		options->log_level = SYSLOG_LEVEL_INFO;
2718 	if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
2719 		options->log_facility = SYSLOG_FACILITY_USER;
2720 	if (options->no_host_authentication_for_localhost == - 1)
2721 		options->no_host_authentication_for_localhost = 0;
2722 	if (options->identities_only == -1)
2723 		options->identities_only = 0;
2724 	if (options->enable_ssh_keysign == -1)
2725 		options->enable_ssh_keysign = 0;
2726 	if (options->rekey_limit == -1)
2727 		options->rekey_limit = 0;
2728 	if (options->rekey_interval == -1)
2729 		options->rekey_interval = 0;
2730 	if (options->verify_host_key_dns == -1)
2731 		options->verify_host_key_dns = 0;
2732 	if (options->server_alive_interval == -1)
2733 		options->server_alive_interval = 0;
2734 	if (options->server_alive_count_max == -1)
2735 		options->server_alive_count_max = 3;
2736 	if (options->control_master == -1)
2737 		options->control_master = 0;
2738 	if (options->control_persist == -1) {
2739 		options->control_persist = 0;
2740 		options->control_persist_timeout = 0;
2741 	}
2742 	if (options->hash_known_hosts == -1)
2743 		options->hash_known_hosts = 0;
2744 	if (options->tun_open == -1)
2745 		options->tun_open = SSH_TUNMODE_NO;
2746 	if (options->tun_local == -1)
2747 		options->tun_local = SSH_TUNID_ANY;
2748 	if (options->tun_remote == -1)
2749 		options->tun_remote = SSH_TUNID_ANY;
2750 	if (options->permit_local_command == -1)
2751 		options->permit_local_command = 0;
2752 	if (options->visual_host_key == -1)
2753 		options->visual_host_key = 0;
2754 	if (options->ip_qos_interactive == -1)
2755 		options->ip_qos_interactive = IPTOS_DSCP_AF21;
2756 	if (options->ip_qos_bulk == -1)
2757 		options->ip_qos_bulk = IPTOS_DSCP_CS1;
2758 	if (options->request_tty == -1)
2759 		options->request_tty = REQUEST_TTY_AUTO;
2760 	if (options->session_type == -1)
2761 		options->session_type = SESSION_TYPE_DEFAULT;
2762 	if (options->stdin_null == -1)
2763 		options->stdin_null = 0;
2764 	if (options->fork_after_authentication == -1)
2765 		options->fork_after_authentication = 0;
2766 	if (options->proxy_use_fdpass == -1)
2767 		options->proxy_use_fdpass = 0;
2768 	if (options->canonicalize_max_dots == -1)
2769 		options->canonicalize_max_dots = 1;
2770 	if (options->canonicalize_fallback_local == -1)
2771 		options->canonicalize_fallback_local = 1;
2772 	if (options->canonicalize_hostname == -1)
2773 		options->canonicalize_hostname = SSH_CANONICALISE_NO;
2774 	if (options->fingerprint_hash == -1)
2775 		options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
2776 	if (options->sk_provider == NULL)
2777 		options->sk_provider = xstrdup("internal");
2778 	if (options->required_rsa_size == -1)
2779 		options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
2780 	if (options->enable_escape_commandline == -1)
2781 		options->enable_escape_commandline = 0;
2782 	if (options->obscure_keystroke_timing_interval == -1) {
2783 		options->obscure_keystroke_timing_interval =
2784 		    SSH_KEYSTROKE_DEFAULT_INTERVAL_MS;
2785 	}
2786 
2787 	/* Expand KEX name lists */
2788 	all_cipher = cipher_alg_list(',', 0);
2789 	all_mac = mac_alg_list(',');
2790 	all_kex = kex_alg_list(',');
2791 	all_key = sshkey_alg_list(0, 0, 1, ',');
2792 	all_sig = sshkey_alg_list(0, 1, 1, ',');
2793 	/* remove unsupported algos from default lists */
2794 	def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher);
2795 	def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac);
2796 	def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex);
2797 	def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
2798 	def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
2799 #define ASSEMBLE(what, defaults, all) \
2800 	do { \
2801 		if ((r = kex_assemble_names(&options->what, \
2802 		    defaults, all)) != 0) { \
2803 			error_fr(r, "%s", #what); \
2804 			goto fail; \
2805 		} \
2806 	} while (0)
2807 	ASSEMBLE(ciphers, def_cipher, all_cipher);
2808 	ASSEMBLE(macs, def_mac, all_mac);
2809 	ASSEMBLE(kex_algorithms, def_kex, all_kex);
2810 	ASSEMBLE(hostbased_accepted_algos, def_key, all_key);
2811 	ASSEMBLE(pubkey_accepted_algos, def_key, all_key);
2812 	ASSEMBLE(ca_sign_algorithms, def_sig, all_sig);
2813 #undef ASSEMBLE
2814 
2815 #define CLEAR_ON_NONE(v) \
2816 	do { \
2817 		if (option_clear_or_none(v)) { \
2818 			free(v); \
2819 			v = NULL; \
2820 		} \
2821 	} while(0)
2822 #define CLEAR_ON_NONE_ARRAY(v, nv, none) \
2823 	do { \
2824 		if (options->nv == 1 && \
2825 		    strcasecmp(options->v[0], none) == 0) { \
2826 			free(options->v[0]); \
2827 			free(options->v); \
2828 			options->v = NULL; \
2829 			options->nv = 0; \
2830 		} \
2831 	} while (0)
2832 	CLEAR_ON_NONE(options->local_command);
2833 	CLEAR_ON_NONE(options->remote_command);
2834 	CLEAR_ON_NONE(options->proxy_command);
2835 	CLEAR_ON_NONE(options->control_path);
2836 	CLEAR_ON_NONE(options->revoked_host_keys);
2837 	CLEAR_ON_NONE(options->pkcs11_provider);
2838 	CLEAR_ON_NONE(options->sk_provider);
2839 	CLEAR_ON_NONE(options->known_hosts_command);
2840 	CLEAR_ON_NONE_ARRAY(channel_timeouts, num_channel_timeouts, "none");
2841 #undef CLEAR_ON_NONE
2842 #undef CLEAR_ON_NONE_ARRAY
2843 	if (options->jump_host != NULL &&
2844 	    strcmp(options->jump_host, "none") == 0 &&
2845 	    options->jump_port == 0 && options->jump_user == NULL) {
2846 		free(options->jump_host);
2847 		options->jump_host = NULL;
2848 	}
2849 	if (options->num_permitted_cnames == 1 &&
2850 	    !config_has_permitted_cnames(options)) {
2851 		/* clean up CanonicalizePermittedCNAMEs=none */
2852 		free(options->permitted_cnames[0].source_list);
2853 		free(options->permitted_cnames[0].target_list);
2854 		memset(options->permitted_cnames, '\0',
2855 		    sizeof(*options->permitted_cnames));
2856 		options->num_permitted_cnames = 0;
2857 	}
2858 	/* options->identity_agent distinguishes NULL from 'none' */
2859 	/* options->user will be set in the main program if appropriate */
2860 	/* options->hostname will be set in the main program if appropriate */
2861 	/* options->host_key_alias should not be set by default */
2862 	/* options->preferred_authentications will be set in ssh */
2863 
2864 	/* success */
2865 	ret = 0;
2866  fail:
2867 	free(all_cipher);
2868 	free(all_mac);
2869 	free(all_kex);
2870 	free(all_key);
2871 	free(all_sig);
2872 	free(def_cipher);
2873 	free(def_mac);
2874 	free(def_kex);
2875 	free(def_key);
2876 	free(def_sig);
2877 	return ret;
2878 }
2879 
2880 void
2881 free_options(Options *o)
2882 {
2883 	int i;
2884 
2885 	if (o == NULL)
2886 		return;
2887 
2888 #define FREE_ARRAY(type, n, a) \
2889 	do { \
2890 		type _i; \
2891 		for (_i = 0; _i < (n); _i++) \
2892 			free((a)[_i]); \
2893 	} while (0)
2894 
2895 	free(o->forward_agent_sock_path);
2896 	free(o->xauth_location);
2897 	FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose);
2898 	free(o->log_verbose);
2899 	free(o->ciphers);
2900 	free(o->macs);
2901 	free(o->hostkeyalgorithms);
2902 	free(o->kex_algorithms);
2903 	free(o->ca_sign_algorithms);
2904 	free(o->hostname);
2905 	free(o->host_key_alias);
2906 	free(o->proxy_command);
2907 	free(o->user);
2908 	FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles);
2909 	FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles);
2910 	free(o->preferred_authentications);
2911 	free(o->bind_address);
2912 	free(o->bind_interface);
2913 	free(o->pkcs11_provider);
2914 	free(o->sk_provider);
2915 	for (i = 0; i < o->num_identity_files; i++) {
2916 		free(o->identity_files[i]);
2917 		sshkey_free(o->identity_keys[i]);
2918 	}
2919 	for (i = 0; i < o->num_certificate_files; i++) {
2920 		free(o->certificate_files[i]);
2921 		sshkey_free(o->certificates[i]);
2922 	}
2923 	free(o->identity_agent);
2924 	for (i = 0; i < o->num_local_forwards; i++) {
2925 		free(o->local_forwards[i].listen_host);
2926 		free(o->local_forwards[i].listen_path);
2927 		free(o->local_forwards[i].connect_host);
2928 		free(o->local_forwards[i].connect_path);
2929 	}
2930 	free(o->local_forwards);
2931 	for (i = 0; i < o->num_remote_forwards; i++) {
2932 		free(o->remote_forwards[i].listen_host);
2933 		free(o->remote_forwards[i].listen_path);
2934 		free(o->remote_forwards[i].connect_host);
2935 		free(o->remote_forwards[i].connect_path);
2936 	}
2937 	free(o->remote_forwards);
2938 	free(o->stdio_forward_host);
2939 	FREE_ARRAY(u_int, o->num_send_env, o->send_env);
2940 	free(o->send_env);
2941 	FREE_ARRAY(u_int, o->num_setenv, o->setenv);
2942 	free(o->setenv);
2943 	free(o->control_path);
2944 	free(o->local_command);
2945 	free(o->remote_command);
2946 	FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains);
2947 	for (i = 0; i < o->num_permitted_cnames; i++) {
2948 		free(o->permitted_cnames[i].source_list);
2949 		free(o->permitted_cnames[i].target_list);
2950 	}
2951 	free(o->revoked_host_keys);
2952 	free(o->hostbased_accepted_algos);
2953 	free(o->pubkey_accepted_algos);
2954 	free(o->jump_user);
2955 	free(o->jump_host);
2956 	free(o->jump_extra);
2957 	free(o->ignored_unknown);
2958 	explicit_bzero(o, sizeof(*o));
2959 #undef FREE_ARRAY
2960 }
2961 
2962 struct fwdarg {
2963 	char *arg;
2964 	int ispath;
2965 };
2966 
2967 /*
2968  * parse_fwd_field
2969  * parses the next field in a port forwarding specification.
2970  * sets fwd to the parsed field and advances p past the colon
2971  * or sets it to NULL at end of string.
2972  * returns 0 on success, else non-zero.
2973  */
2974 static int
2975 parse_fwd_field(char **p, struct fwdarg *fwd)
2976 {
2977 	char *ep, *cp = *p;
2978 	int ispath = 0;
2979 
2980 	if (*cp == '\0') {
2981 		*p = NULL;
2982 		return -1;	/* end of string */
2983 	}
2984 
2985 	/*
2986 	 * A field escaped with square brackets is used literally.
2987 	 * XXX - allow ']' to be escaped via backslash?
2988 	 */
2989 	if (*cp == '[') {
2990 		/* find matching ']' */
2991 		for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
2992 			if (*ep == '/')
2993 				ispath = 1;
2994 		}
2995 		/* no matching ']' or not at end of field. */
2996 		if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
2997 			return -1;
2998 		/* NUL terminate the field and advance p past the colon */
2999 		*ep++ = '\0';
3000 		if (*ep != '\0')
3001 			*ep++ = '\0';
3002 		fwd->arg = cp + 1;
3003 		fwd->ispath = ispath;
3004 		*p = ep;
3005 		return 0;
3006 	}
3007 
3008 	for (cp = *p; *cp != '\0'; cp++) {
3009 		switch (*cp) {
3010 		case '\\':
3011 			memmove(cp, cp + 1, strlen(cp + 1) + 1);
3012 			if (*cp == '\0')
3013 				return -1;
3014 			break;
3015 		case '/':
3016 			ispath = 1;
3017 			break;
3018 		case ':':
3019 			*cp++ = '\0';
3020 			goto done;
3021 		}
3022 	}
3023 done:
3024 	fwd->arg = *p;
3025 	fwd->ispath = ispath;
3026 	*p = cp;
3027 	return 0;
3028 }
3029 
3030 /*
3031  * parse_forward
3032  * parses a string containing a port forwarding specification of the form:
3033  *   dynamicfwd == 0
3034  *	[listenhost:]listenport|listenpath:connecthost:connectport|connectpath
3035  *	listenpath:connectpath
3036  *   dynamicfwd == 1
3037  *	[listenhost:]listenport
3038  * returns number of arguments parsed or zero on error
3039  */
3040 int
3041 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
3042 {
3043 	struct fwdarg fwdargs[4];
3044 	char *p, *cp;
3045 	int i, err;
3046 
3047 	memset(fwd, 0, sizeof(*fwd));
3048 	memset(fwdargs, 0, sizeof(fwdargs));
3049 
3050 	/*
3051 	 * We expand environment variables before checking if we think they're
3052 	 * paths so that if ${VAR} expands to a fully qualified path it is
3053 	 * treated as a path.
3054 	 */
3055 	cp = p = dollar_expand(&err, fwdspec);
3056 	if (p == NULL || err)
3057 		return 0;
3058 
3059 	/* skip leading spaces */
3060 	while (isspace((u_char)*cp))
3061 		cp++;
3062 
3063 	for (i = 0; i < 4; ++i) {
3064 		if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
3065 			break;
3066 	}
3067 
3068 	/* Check for trailing garbage */
3069 	if (cp != NULL && *cp != '\0') {
3070 		i = 0;	/* failure */
3071 	}
3072 
3073 	switch (i) {
3074 	case 1:
3075 		if (fwdargs[0].ispath) {
3076 			fwd->listen_path = xstrdup(fwdargs[0].arg);
3077 			fwd->listen_port = PORT_STREAMLOCAL;
3078 		} else {
3079 			fwd->listen_host = NULL;
3080 			fwd->listen_port = a2port(fwdargs[0].arg);
3081 		}
3082 		fwd->connect_host = xstrdup("socks");
3083 		break;
3084 
3085 	case 2:
3086 		if (fwdargs[0].ispath && fwdargs[1].ispath) {
3087 			fwd->listen_path = xstrdup(fwdargs[0].arg);
3088 			fwd->listen_port = PORT_STREAMLOCAL;
3089 			fwd->connect_path = xstrdup(fwdargs[1].arg);
3090 			fwd->connect_port = PORT_STREAMLOCAL;
3091 		} else if (fwdargs[1].ispath) {
3092 			fwd->listen_host = NULL;
3093 			fwd->listen_port = a2port(fwdargs[0].arg);
3094 			fwd->connect_path = xstrdup(fwdargs[1].arg);
3095 			fwd->connect_port = PORT_STREAMLOCAL;
3096 		} else {
3097 			fwd->listen_host = xstrdup(fwdargs[0].arg);
3098 			fwd->listen_port = a2port(fwdargs[1].arg);
3099 			fwd->connect_host = xstrdup("socks");
3100 		}
3101 		break;
3102 
3103 	case 3:
3104 		if (fwdargs[0].ispath) {
3105 			fwd->listen_path = xstrdup(fwdargs[0].arg);
3106 			fwd->listen_port = PORT_STREAMLOCAL;
3107 			fwd->connect_host = xstrdup(fwdargs[1].arg);
3108 			fwd->connect_port = a2port(fwdargs[2].arg);
3109 		} else if (fwdargs[2].ispath) {
3110 			fwd->listen_host = xstrdup(fwdargs[0].arg);
3111 			fwd->listen_port = a2port(fwdargs[1].arg);
3112 			fwd->connect_path = xstrdup(fwdargs[2].arg);
3113 			fwd->connect_port = PORT_STREAMLOCAL;
3114 		} else {
3115 			fwd->listen_host = NULL;
3116 			fwd->listen_port = a2port(fwdargs[0].arg);
3117 			fwd->connect_host = xstrdup(fwdargs[1].arg);
3118 			fwd->connect_port = a2port(fwdargs[2].arg);
3119 		}
3120 		break;
3121 
3122 	case 4:
3123 		fwd->listen_host = xstrdup(fwdargs[0].arg);
3124 		fwd->listen_port = a2port(fwdargs[1].arg);
3125 		fwd->connect_host = xstrdup(fwdargs[2].arg);
3126 		fwd->connect_port = a2port(fwdargs[3].arg);
3127 		break;
3128 	default:
3129 		i = 0; /* failure */
3130 	}
3131 
3132 	free(p);
3133 
3134 	if (dynamicfwd) {
3135 		if (!(i == 1 || i == 2))
3136 			goto fail_free;
3137 	} else {
3138 		if (!(i == 3 || i == 4)) {
3139 			if (fwd->connect_path == NULL &&
3140 			    fwd->listen_path == NULL)
3141 				goto fail_free;
3142 		}
3143 		if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
3144 			goto fail_free;
3145 	}
3146 
3147 	if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
3148 	    (!remotefwd && fwd->listen_port == 0))
3149 		goto fail_free;
3150 	if (fwd->connect_host != NULL &&
3151 	    strlen(fwd->connect_host) >= NI_MAXHOST)
3152 		goto fail_free;
3153 	/*
3154 	 * XXX - if connecting to a remote socket, max sun len may not
3155 	 * match this host
3156 	 */
3157 	if (fwd->connect_path != NULL &&
3158 	    strlen(fwd->connect_path) >= PATH_MAX_SUN)
3159 		goto fail_free;
3160 	if (fwd->listen_host != NULL &&
3161 	    strlen(fwd->listen_host) >= NI_MAXHOST)
3162 		goto fail_free;
3163 	if (fwd->listen_path != NULL &&
3164 	    strlen(fwd->listen_path) >= PATH_MAX_SUN)
3165 		goto fail_free;
3166 
3167 	return (i);
3168 
3169  fail_free:
3170 	free(fwd->connect_host);
3171 	fwd->connect_host = NULL;
3172 	free(fwd->connect_path);
3173 	fwd->connect_path = NULL;
3174 	free(fwd->listen_host);
3175 	fwd->listen_host = NULL;
3176 	free(fwd->listen_path);
3177 	fwd->listen_path = NULL;
3178 	return (0);
3179 }
3180 
3181 int
3182 parse_jump(const char *s, Options *o, int active)
3183 {
3184 	char *orig, *sdup, *cp;
3185 	char *host = NULL, *user = NULL;
3186 	int r, ret = -1, port = -1, first;
3187 
3188 	active &= o->proxy_command == NULL && o->jump_host == NULL;
3189 
3190 	orig = sdup = xstrdup(s);
3191 
3192 	/* Remove comment and trailing whitespace */
3193 	if ((cp = strchr(orig, '#')) != NULL)
3194 		*cp = '\0';
3195 	rtrim(orig);
3196 
3197 	first = active;
3198 	do {
3199 		if (strcasecmp(s, "none") == 0)
3200 			break;
3201 		if ((cp = strrchr(sdup, ',')) == NULL)
3202 			cp = sdup; /* last */
3203 		else
3204 			*cp++ = '\0';
3205 
3206 		if (first) {
3207 			/* First argument and configuration is active */
3208 			r = parse_ssh_uri(cp, &user, &host, &port);
3209 			if (r == -1 || (r == 1 &&
3210 			    parse_user_host_port(cp, &user, &host, &port) != 0))
3211 				goto out;
3212 		} else {
3213 			/* Subsequent argument or inactive configuration */
3214 			r = parse_ssh_uri(cp, NULL, NULL, NULL);
3215 			if (r == -1 || (r == 1 &&
3216 			    parse_user_host_port(cp, NULL, NULL, NULL) != 0))
3217 				goto out;
3218 		}
3219 		first = 0; /* only check syntax for subsequent hosts */
3220 	} while (cp != sdup);
3221 	/* success */
3222 	if (active) {
3223 		if (strcasecmp(s, "none") == 0) {
3224 			o->jump_host = xstrdup("none");
3225 			o->jump_port = 0;
3226 		} else {
3227 			o->jump_user = user;
3228 			o->jump_host = host;
3229 			o->jump_port = port;
3230 			o->proxy_command = xstrdup("none");
3231 			user = host = NULL;
3232 			if ((cp = strrchr(s, ',')) != NULL && cp != s) {
3233 				o->jump_extra = xstrdup(s);
3234 				o->jump_extra[cp - s] = '\0';
3235 			}
3236 		}
3237 	}
3238 	ret = 0;
3239  out:
3240 	free(orig);
3241 	free(user);
3242 	free(host);
3243 	return ret;
3244 }
3245 
3246 int
3247 parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp)
3248 {
3249 	char *user = NULL, *host = NULL, *path = NULL;
3250 	int r, port;
3251 
3252 	r = parse_uri("ssh", uri, &user, &host, &port, &path);
3253 	if (r == 0 && path != NULL)
3254 		r = -1;		/* path not allowed */
3255 	if (r == 0) {
3256 		if (userp != NULL) {
3257 			*userp = user;
3258 			user = NULL;
3259 		}
3260 		if (hostp != NULL) {
3261 			*hostp = host;
3262 			host = NULL;
3263 		}
3264 		if (portp != NULL)
3265 			*portp = port;
3266 	}
3267 	free(user);
3268 	free(host);
3269 	free(path);
3270 	return r;
3271 }
3272 
3273 /* XXX the following is a near-vebatim copy from servconf.c; refactor */
3274 static const char *
3275 fmt_multistate_int(int val, const struct multistate *m)
3276 {
3277 	u_int i;
3278 
3279 	for (i = 0; m[i].key != NULL; i++) {
3280 		if (m[i].value == val)
3281 			return m[i].key;
3282 	}
3283 	return "UNKNOWN";
3284 }
3285 
3286 static const char *
3287 fmt_intarg(OpCodes code, int val)
3288 {
3289 	if (val == -1)
3290 		return "unset";
3291 	switch (code) {
3292 	case oAddressFamily:
3293 		return fmt_multistate_int(val, multistate_addressfamily);
3294 	case oVerifyHostKeyDNS:
3295 	case oUpdateHostkeys:
3296 		return fmt_multistate_int(val, multistate_yesnoask);
3297 	case oStrictHostKeyChecking:
3298 		return fmt_multistate_int(val, multistate_strict_hostkey);
3299 	case oControlMaster:
3300 		return fmt_multistate_int(val, multistate_controlmaster);
3301 	case oTunnel:
3302 		return fmt_multistate_int(val, multistate_tunnel);
3303 	case oRequestTTY:
3304 		return fmt_multistate_int(val, multistate_requesttty);
3305 	case oSessionType:
3306 		return fmt_multistate_int(val, multistate_sessiontype);
3307 	case oCanonicalizeHostname:
3308 		return fmt_multistate_int(val, multistate_canonicalizehostname);
3309 	case oAddKeysToAgent:
3310 		return fmt_multistate_int(val, multistate_yesnoaskconfirm);
3311 	case oPubkeyAuthentication:
3312 		return fmt_multistate_int(val, multistate_pubkey_auth);
3313 	case oFingerprintHash:
3314 		return ssh_digest_alg_name(val);
3315 	default:
3316 		switch (val) {
3317 		case 0:
3318 			return "no";
3319 		case 1:
3320 			return "yes";
3321 		default:
3322 			return "UNKNOWN";
3323 		}
3324 	}
3325 }
3326 
3327 static const char *
3328 lookup_opcode_name(OpCodes code)
3329 {
3330 	u_int i;
3331 
3332 	for (i = 0; keywords[i].name != NULL; i++)
3333 		if (keywords[i].opcode == code)
3334 			return(keywords[i].name);
3335 	return "UNKNOWN";
3336 }
3337 
3338 static void
3339 dump_cfg_int(OpCodes code, int val)
3340 {
3341 	if (code == oObscureKeystrokeTiming) {
3342 		if (val == 0) {
3343 			printf("%s no\n", lookup_opcode_name(code));
3344 			return;
3345 		} else if (val == SSH_KEYSTROKE_DEFAULT_INTERVAL_MS) {
3346 			printf("%s yes\n", lookup_opcode_name(code));
3347 			return;
3348 		}
3349 		/* FALLTHROUGH */
3350 	}
3351 	printf("%s %d\n", lookup_opcode_name(code), val);
3352 }
3353 
3354 static void
3355 dump_cfg_fmtint(OpCodes code, int val)
3356 {
3357 	printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
3358 }
3359 
3360 static void
3361 dump_cfg_string(OpCodes code, const char *val)
3362 {
3363 	if (val == NULL)
3364 		return;
3365 	printf("%s %s\n", lookup_opcode_name(code), val);
3366 }
3367 
3368 static void
3369 dump_cfg_strarray(OpCodes code, u_int count, char **vals)
3370 {
3371 	u_int i;
3372 
3373 	for (i = 0; i < count; i++)
3374 		printf("%s %s\n", lookup_opcode_name(code), vals[i]);
3375 }
3376 
3377 static void
3378 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
3379 {
3380 	u_int i;
3381 
3382 	printf("%s", lookup_opcode_name(code));
3383 	if (count == 0)
3384 		printf(" none");
3385 	for (i = 0; i < count; i++)
3386 		printf(" %s",  vals[i]);
3387 	printf("\n");
3388 }
3389 
3390 static void
3391 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
3392 {
3393 	const struct Forward *fwd;
3394 	u_int i;
3395 
3396 	/* oDynamicForward */
3397 	for (i = 0; i < count; i++) {
3398 		fwd = &fwds[i];
3399 		if (code == oDynamicForward && fwd->connect_host != NULL &&
3400 		    strcmp(fwd->connect_host, "socks") != 0)
3401 			continue;
3402 		if (code == oLocalForward && fwd->connect_host != NULL &&
3403 		    strcmp(fwd->connect_host, "socks") == 0)
3404 			continue;
3405 		printf("%s", lookup_opcode_name(code));
3406 		if (fwd->listen_port == PORT_STREAMLOCAL)
3407 			printf(" %s", fwd->listen_path);
3408 		else if (fwd->listen_host == NULL)
3409 			printf(" %d", fwd->listen_port);
3410 		else {
3411 			printf(" [%s]:%d",
3412 			    fwd->listen_host, fwd->listen_port);
3413 		}
3414 		if (code != oDynamicForward) {
3415 			if (fwd->connect_port == PORT_STREAMLOCAL)
3416 				printf(" %s", fwd->connect_path);
3417 			else if (fwd->connect_host == NULL)
3418 				printf(" %d", fwd->connect_port);
3419 			else {
3420 				printf(" [%s]:%d",
3421 				    fwd->connect_host, fwd->connect_port);
3422 			}
3423 		}
3424 		printf("\n");
3425 	}
3426 }
3427 
3428 void
3429 dump_client_config(Options *o, const char *host)
3430 {
3431 	int i, r;
3432 	char buf[8], *all_key;
3433 
3434 	/*
3435 	 * Expand HostKeyAlgorithms name lists. This isn't handled in
3436 	 * fill_default_options() like the other algorithm lists because
3437 	 * the host key algorithms are by default dynamically chosen based
3438 	 * on the host's keys found in known_hosts.
3439 	 */
3440 	all_key = sshkey_alg_list(0, 0, 1, ',');
3441 	if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(),
3442 	    all_key)) != 0)
3443 		fatal_fr(r, "expand HostKeyAlgorithms");
3444 	free(all_key);
3445 
3446 	/* Most interesting options first: user, host, port */
3447 	dump_cfg_string(oHost, o->host_arg);
3448 	dump_cfg_string(oUser, o->user);
3449 	dump_cfg_string(oHostname, host);
3450 	dump_cfg_int(oPort, o->port);
3451 
3452 	/* Flag options */
3453 	dump_cfg_fmtint(oAddressFamily, o->address_family);
3454 	dump_cfg_fmtint(oBatchMode, o->batch_mode);
3455 	dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
3456 	dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
3457 	dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
3458 	dump_cfg_fmtint(oCompression, o->compression);
3459 	dump_cfg_fmtint(oControlMaster, o->control_master);
3460 	dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
3461 	dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings);
3462 	dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
3463 	dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
3464 	dump_cfg_fmtint(oForwardX11, o->forward_x11);
3465 	dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
3466 	dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
3467 #ifdef GSSAPI
3468 	dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
3469 	dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
3470 #endif /* GSSAPI */
3471 	dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
3472 	dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
3473 	dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
3474 	dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
3475 	dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
3476 	dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
3477 	dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
3478 	dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
3479 	dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
3480 	dump_cfg_fmtint(oRequestTTY, o->request_tty);
3481 	dump_cfg_fmtint(oSessionType, o->session_type);
3482 	dump_cfg_fmtint(oStdinNull, o->stdin_null);
3483 	dump_cfg_fmtint(oForkAfterAuthentication, o->fork_after_authentication);
3484 	dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
3485 	dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
3486 	dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
3487 	dump_cfg_fmtint(oTunnel, o->tun_open);
3488 	dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
3489 	dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
3490 	dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
3491 	dump_cfg_fmtint(oEnableEscapeCommandline, o->enable_escape_commandline);
3492 
3493 	/* Integer options */
3494 	dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
3495 	dump_cfg_int(oConnectionAttempts, o->connection_attempts);
3496 	dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
3497 	dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
3498 	dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
3499 	dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
3500 	dump_cfg_int(oRequiredRSASize, o->required_rsa_size);
3501 	dump_cfg_int(oObscureKeystrokeTiming,
3502 	    o->obscure_keystroke_timing_interval);
3503 
3504 	/* String options */
3505 	dump_cfg_string(oBindAddress, o->bind_address);
3506 	dump_cfg_string(oBindInterface, o->bind_interface);
3507 	dump_cfg_string(oCiphers, o->ciphers);
3508 	dump_cfg_string(oControlPath, o->control_path);
3509 	dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
3510 	dump_cfg_string(oHostKeyAlias, o->host_key_alias);
3511 	dump_cfg_string(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos);
3512 	dump_cfg_string(oIdentityAgent, o->identity_agent);
3513 	dump_cfg_string(oIgnoreUnknown, o->ignored_unknown);
3514 	dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
3515 	dump_cfg_string(oKexAlgorithms, o->kex_algorithms);
3516 	dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms);
3517 	dump_cfg_string(oLocalCommand, o->local_command);
3518 	dump_cfg_string(oRemoteCommand, o->remote_command);
3519 	dump_cfg_string(oLogLevel, log_level_name(o->log_level));
3520 	dump_cfg_string(oMacs, o->macs);
3521 #ifdef ENABLE_PKCS11
3522 	dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
3523 #endif
3524 	dump_cfg_string(oSecurityKeyProvider, o->sk_provider);
3525 	dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
3526 	dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos);
3527 	dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
3528 	dump_cfg_string(oXAuthLocation, o->xauth_location);
3529 	dump_cfg_string(oKnownHostsCommand, o->known_hosts_command);
3530 	dump_cfg_string(oTag, o->tag);
3531 
3532 	/* Forwards */
3533 	dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
3534 	dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
3535 	dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
3536 
3537 	/* String array options */
3538 	dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
3539 	dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
3540 	dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files);
3541 	dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
3542 	dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
3543 	dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
3544 	dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv);
3545 	dump_cfg_strarray_oneline(oLogVerbose,
3546 	    o->num_log_verbose, o->log_verbose);
3547 	dump_cfg_strarray_oneline(oChannelTimeout,
3548 	    o->num_channel_timeouts, o->channel_timeouts);
3549 
3550 	/* Special cases */
3551 
3552 	/* PermitRemoteOpen */
3553 	if (o->num_permitted_remote_opens == 0)
3554 		printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen));
3555 	else
3556 		dump_cfg_strarray_oneline(oPermitRemoteOpen,
3557 		    o->num_permitted_remote_opens, o->permitted_remote_opens);
3558 
3559 	/* AddKeysToAgent */
3560 	if (o->add_keys_to_agent_lifespan <= 0)
3561 		dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent);
3562 	else {
3563 		printf("addkeystoagent%s %d\n",
3564 		    o->add_keys_to_agent == 3 ? " confirm" : "",
3565 		    o->add_keys_to_agent_lifespan);
3566 	}
3567 
3568 	/* oForwardAgent */
3569 	if (o->forward_agent_sock_path == NULL)
3570 		dump_cfg_fmtint(oForwardAgent, o->forward_agent);
3571 	else
3572 		dump_cfg_string(oForwardAgent, o->forward_agent_sock_path);
3573 
3574 	/* oConnectTimeout */
3575 	if (o->connection_timeout == -1)
3576 		printf("connecttimeout none\n");
3577 	else
3578 		dump_cfg_int(oConnectTimeout, o->connection_timeout);
3579 
3580 	/* oTunnelDevice */
3581 	printf("tunneldevice");
3582 	if (o->tun_local == SSH_TUNID_ANY)
3583 		printf(" any");
3584 	else
3585 		printf(" %d", o->tun_local);
3586 	if (o->tun_remote == SSH_TUNID_ANY)
3587 		printf(":any");
3588 	else
3589 		printf(":%d", o->tun_remote);
3590 	printf("\n");
3591 
3592 	/* oCanonicalizePermittedCNAMEs */
3593 	printf("canonicalizePermittedcnames");
3594 	if (o->num_permitted_cnames == 0)
3595 		printf(" none");
3596 	for (i = 0; i < o->num_permitted_cnames; i++) {
3597 		printf(" %s:%s", o->permitted_cnames[i].source_list,
3598 		    o->permitted_cnames[i].target_list);
3599 	}
3600 	printf("\n");
3601 
3602 	/* oControlPersist */
3603 	if (o->control_persist == 0 || o->control_persist_timeout == 0)
3604 		dump_cfg_fmtint(oControlPersist, o->control_persist);
3605 	else
3606 		dump_cfg_int(oControlPersist, o->control_persist_timeout);
3607 
3608 	/* oEscapeChar */
3609 	if (o->escape_char == SSH_ESCAPECHAR_NONE)
3610 		printf("escapechar none\n");
3611 	else {
3612 		vis(buf, o->escape_char, VIS_WHITE, 0);
3613 		printf("escapechar %s\n", buf);
3614 	}
3615 
3616 	/* oIPQoS */
3617 	printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
3618 	printf("%s\n", iptos2str(o->ip_qos_bulk));
3619 
3620 	/* oRekeyLimit */
3621 	printf("rekeylimit %llu %d\n",
3622 	    (unsigned long long)o->rekey_limit, o->rekey_interval);
3623 
3624 	/* oStreamLocalBindMask */
3625 	printf("streamlocalbindmask 0%o\n",
3626 	    o->fwd_opts.streamlocal_bind_mask);
3627 
3628 	/* oLogFacility */
3629 	printf("syslogfacility %s\n", log_facility_name(o->log_facility));
3630 
3631 	/* oProxyCommand / oProxyJump */
3632 	if (o->jump_host == NULL)
3633 		dump_cfg_string(oProxyCommand, o->proxy_command);
3634 	else {
3635 		/* Check for numeric addresses */
3636 		i = strchr(o->jump_host, ':') != NULL ||
3637 		    strspn(o->jump_host, "1234567890.") == strlen(o->jump_host);
3638 		snprintf(buf, sizeof(buf), "%d", o->jump_port);
3639 		printf("proxyjump %s%s%s%s%s%s%s%s%s\n",
3640 		    /* optional additional jump spec */
3641 		    o->jump_extra == NULL ? "" : o->jump_extra,
3642 		    o->jump_extra == NULL ? "" : ",",
3643 		    /* optional user */
3644 		    o->jump_user == NULL ? "" : o->jump_user,
3645 		    o->jump_user == NULL ? "" : "@",
3646 		    /* opening [ if hostname is numeric */
3647 		    i ? "[" : "",
3648 		    /* mandatory hostname */
3649 		    o->jump_host,
3650 		    /* closing ] if hostname is numeric */
3651 		    i ? "]" : "",
3652 		    /* optional port number */
3653 		    o->jump_port <= 0 ? "" : ":",
3654 		    o->jump_port <= 0 ? "" : buf);
3655 	}
3656 }
3657