xref: /openbsd/usr.bin/ssh/readconf.c (revision 9e6efb0a)
1 /* $OpenBSD: readconf.c,v 1.387 2024/05/17 02:39:11 jsg 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 static void
871 free_canon_cnames(struct allowed_cname *cnames, u_int n)
872 {
873 	u_int i;
874 
875 	if (cnames == NULL || n == 0)
876 		return;
877 	for (i = 0; i < n; i++) {
878 		free(cnames[i].source_list);
879 		free(cnames[i].target_list);
880 	}
881 	free(cnames);
882 }
883 
884 /* Multistate option parsing */
885 struct multistate {
886 	char *key;
887 	int value;
888 };
889 static const struct multistate multistate_flag[] = {
890 	{ "true",			1 },
891 	{ "false",			0 },
892 	{ "yes",			1 },
893 	{ "no",				0 },
894 	{ NULL, -1 }
895 };
896 static const struct multistate multistate_yesnoask[] = {
897 	{ "true",			1 },
898 	{ "false",			0 },
899 	{ "yes",			1 },
900 	{ "no",				0 },
901 	{ "ask",			2 },
902 	{ NULL, -1 }
903 };
904 static const struct multistate multistate_strict_hostkey[] = {
905 	{ "true",			SSH_STRICT_HOSTKEY_YES },
906 	{ "false",			SSH_STRICT_HOSTKEY_OFF },
907 	{ "yes",			SSH_STRICT_HOSTKEY_YES },
908 	{ "no",				SSH_STRICT_HOSTKEY_OFF },
909 	{ "ask",			SSH_STRICT_HOSTKEY_ASK },
910 	{ "off",			SSH_STRICT_HOSTKEY_OFF },
911 	{ "accept-new",			SSH_STRICT_HOSTKEY_NEW },
912 	{ NULL, -1 }
913 };
914 static const struct multistate multistate_yesnoaskconfirm[] = {
915 	{ "true",			1 },
916 	{ "false",			0 },
917 	{ "yes",			1 },
918 	{ "no",				0 },
919 	{ "ask",			2 },
920 	{ "confirm",			3 },
921 	{ NULL, -1 }
922 };
923 static const struct multistate multistate_addressfamily[] = {
924 	{ "inet",			AF_INET },
925 	{ "inet6",			AF_INET6 },
926 	{ "any",			AF_UNSPEC },
927 	{ NULL, -1 }
928 };
929 static const struct multistate multistate_controlmaster[] = {
930 	{ "true",			SSHCTL_MASTER_YES },
931 	{ "yes",			SSHCTL_MASTER_YES },
932 	{ "false",			SSHCTL_MASTER_NO },
933 	{ "no",				SSHCTL_MASTER_NO },
934 	{ "auto",			SSHCTL_MASTER_AUTO },
935 	{ "ask",			SSHCTL_MASTER_ASK },
936 	{ "autoask",			SSHCTL_MASTER_AUTO_ASK },
937 	{ NULL, -1 }
938 };
939 static const struct multistate multistate_tunnel[] = {
940 	{ "ethernet",			SSH_TUNMODE_ETHERNET },
941 	{ "point-to-point",		SSH_TUNMODE_POINTOPOINT },
942 	{ "true",			SSH_TUNMODE_DEFAULT },
943 	{ "yes",			SSH_TUNMODE_DEFAULT },
944 	{ "false",			SSH_TUNMODE_NO },
945 	{ "no",				SSH_TUNMODE_NO },
946 	{ NULL, -1 }
947 };
948 static const struct multistate multistate_requesttty[] = {
949 	{ "true",			REQUEST_TTY_YES },
950 	{ "yes",			REQUEST_TTY_YES },
951 	{ "false",			REQUEST_TTY_NO },
952 	{ "no",				REQUEST_TTY_NO },
953 	{ "force",			REQUEST_TTY_FORCE },
954 	{ "auto",			REQUEST_TTY_AUTO },
955 	{ NULL, -1 }
956 };
957 static const struct multistate multistate_sessiontype[] = {
958 	{ "none",			SESSION_TYPE_NONE },
959 	{ "subsystem",			SESSION_TYPE_SUBSYSTEM },
960 	{ "default",			SESSION_TYPE_DEFAULT },
961 	{ NULL, -1 }
962 };
963 static const struct multistate multistate_canonicalizehostname[] = {
964 	{ "true",			SSH_CANONICALISE_YES },
965 	{ "false",			SSH_CANONICALISE_NO },
966 	{ "yes",			SSH_CANONICALISE_YES },
967 	{ "no",				SSH_CANONICALISE_NO },
968 	{ "always",			SSH_CANONICALISE_ALWAYS },
969 	{ NULL, -1 }
970 };
971 static const struct multistate multistate_pubkey_auth[] = {
972 	{ "true",			SSH_PUBKEY_AUTH_ALL },
973 	{ "false",			SSH_PUBKEY_AUTH_NO },
974 	{ "yes",			SSH_PUBKEY_AUTH_ALL },
975 	{ "no",				SSH_PUBKEY_AUTH_NO },
976 	{ "unbound",			SSH_PUBKEY_AUTH_UNBOUND },
977 	{ "host-bound",			SSH_PUBKEY_AUTH_HBOUND },
978 	{ NULL, -1 }
979 };
980 static const struct multistate multistate_compression[] = {
981 #ifdef WITH_ZLIB
982 	{ "yes",			COMP_ZLIB },
983 #endif
984 	{ "no",				COMP_NONE },
985 	{ NULL, -1 }
986 };
987 
988 static int
989 parse_multistate_value(const char *arg, const char *filename, int linenum,
990     const struct multistate *multistate_ptr)
991 {
992 	int i;
993 
994 	if (!arg || *arg == '\0') {
995 		error("%s line %d: missing argument.", filename, linenum);
996 		return -1;
997 	}
998 	for (i = 0; multistate_ptr[i].key != NULL; i++) {
999 		if (strcasecmp(arg, multistate_ptr[i].key) == 0)
1000 			return multistate_ptr[i].value;
1001 	}
1002 	return -1;
1003 }
1004 
1005 /*
1006  * Processes a single option line as used in the configuration files. This
1007  * only sets those values that have not already been set.
1008  */
1009 int
1010 process_config_line(Options *options, struct passwd *pw, const char *host,
1011     const char *original_host, char *line, const char *filename,
1012     int linenum, int *activep, int flags)
1013 {
1014 	return process_config_line_depth(options, pw, host, original_host,
1015 	    line, filename, linenum, activep, flags, NULL, 0);
1016 }
1017 
1018 #define WHITESPACE " \t\r\n"
1019 static int
1020 process_config_line_depth(Options *options, struct passwd *pw, const char *host,
1021     const char *original_host, char *line, const char *filename,
1022     int linenum, int *activep, int flags, int *want_final_pass, int depth)
1023 {
1024 	char *str, **charptr, *endofnumber, *keyword, *arg, *arg2, *p;
1025 	char **cpptr, ***cppptr, fwdarg[256];
1026 	u_int i, *uintptr, max_entries = 0;
1027 	int r, oactive, negated, opcode, *intptr, value, value2, cmdline = 0;
1028 	int remotefwd, dynamicfwd, ca_only = 0, found = 0;
1029 	LogLevel *log_level_ptr;
1030 	SyslogFacility *log_facility_ptr;
1031 	long long val64;
1032 	size_t len;
1033 	struct Forward fwd;
1034 	const struct multistate *multistate_ptr;
1035 	glob_t gl;
1036 	const char *errstr;
1037 	char **oav = NULL, **av;
1038 	int oac = 0, ac;
1039 	int ret = -1;
1040 	struct allowed_cname *cnames = NULL;
1041 	u_int ncnames = 0;
1042 	char **strs = NULL; /* string array arguments; freed implicitly */
1043 	u_int nstrs = 0;
1044 
1045 	if (activep == NULL) { /* We are processing a command line directive */
1046 		cmdline = 1;
1047 		activep = &cmdline;
1048 	}
1049 
1050 	/* Strip trailing whitespace. Allow \f (form feed) at EOL only */
1051 	if ((len = strlen(line)) == 0)
1052 		return 0;
1053 	for (len--; len > 0; len--) {
1054 		if (strchr(WHITESPACE "\f", line[len]) == NULL)
1055 			break;
1056 		line[len] = '\0';
1057 	}
1058 
1059 	str = line;
1060 	/* Get the keyword. (Each line is supposed to begin with a keyword). */
1061 	if ((keyword = strdelim(&str)) == NULL)
1062 		return 0;
1063 	/* Ignore leading whitespace. */
1064 	if (*keyword == '\0')
1065 		keyword = strdelim(&str);
1066 	if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
1067 		return 0;
1068 	/* Match lowercase keyword */
1069 	lowercase(keyword);
1070 
1071 	/* Prepare to parse remainder of line */
1072 	if (str != NULL)
1073 		str += strspn(str, WHITESPACE);
1074 	if (str == NULL || *str == '\0') {
1075 		error("%s line %d: no argument after keyword \"%s\"",
1076 		    filename, linenum, keyword);
1077 		return -1;
1078 	}
1079 	opcode = parse_token(keyword, filename, linenum,
1080 	    options->ignored_unknown);
1081 	if (argv_split(str, &oac, &oav, 1) != 0) {
1082 		error("%s line %d: invalid quotes", filename, linenum);
1083 		return -1;
1084 	}
1085 	ac = oac;
1086 	av = oav;
1087 
1088 	switch (opcode) {
1089 	case oBadOption:
1090 		/* don't panic, but count bad options */
1091 		goto out;
1092 	case oIgnore:
1093 		argv_consume(&ac);
1094 		break;
1095 	case oIgnoredUnknownOption:
1096 		debug("%s line %d: Ignored unknown option \"%s\"",
1097 		    filename, linenum, keyword);
1098 		argv_consume(&ac);
1099 		break;
1100 	case oConnectTimeout:
1101 		intptr = &options->connection_timeout;
1102 parse_time:
1103 		arg = argv_next(&ac, &av);
1104 		if (!arg || *arg == '\0') {
1105 			error("%s line %d: missing time value.",
1106 			    filename, linenum);
1107 			goto out;
1108 		}
1109 		if (strcmp(arg, "none") == 0)
1110 			value = -1;
1111 		else if ((value = convtime(arg)) == -1) {
1112 			error("%s line %d: invalid time value.",
1113 			    filename, linenum);
1114 			goto out;
1115 		}
1116 		if (*activep && *intptr == -1)
1117 			*intptr = value;
1118 		break;
1119 
1120 	case oForwardAgent:
1121 		intptr = &options->forward_agent;
1122 
1123 		arg = argv_next(&ac, &av);
1124 		if (!arg || *arg == '\0') {
1125 			error("%s line %d: missing argument.",
1126 			    filename, linenum);
1127 			goto out;
1128 		}
1129 
1130 		value = -1;
1131 		multistate_ptr = multistate_flag;
1132 		for (i = 0; multistate_ptr[i].key != NULL; i++) {
1133 			if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
1134 				value = multistate_ptr[i].value;
1135 				break;
1136 			}
1137 		}
1138 		if (value != -1) {
1139 			if (*activep && *intptr == -1)
1140 				*intptr = value;
1141 			break;
1142 		}
1143 		/* ForwardAgent wasn't 'yes' or 'no', assume a path */
1144 		if (*activep && *intptr == -1)
1145 			*intptr = 1;
1146 
1147 		charptr = &options->forward_agent_sock_path;
1148 		goto parse_agent_path;
1149 
1150 	case oForwardX11:
1151 		intptr = &options->forward_x11;
1152  parse_flag:
1153 		multistate_ptr = multistate_flag;
1154  parse_multistate:
1155 		arg = argv_next(&ac, &av);
1156 		if ((value = parse_multistate_value(arg, filename, linenum,
1157 		    multistate_ptr)) == -1) {
1158 			error("%s line %d: unsupported option \"%s\".",
1159 			    filename, linenum, arg);
1160 			goto out;
1161 		}
1162 		if (*activep && *intptr == -1)
1163 			*intptr = value;
1164 		break;
1165 
1166 	case oForwardX11Trusted:
1167 		intptr = &options->forward_x11_trusted;
1168 		goto parse_flag;
1169 
1170 	case oForwardX11Timeout:
1171 		intptr = &options->forward_x11_timeout;
1172 		goto parse_time;
1173 
1174 	case oGatewayPorts:
1175 		intptr = &options->fwd_opts.gateway_ports;
1176 		goto parse_flag;
1177 
1178 	case oExitOnForwardFailure:
1179 		intptr = &options->exit_on_forward_failure;
1180 		goto parse_flag;
1181 
1182 	case oPasswordAuthentication:
1183 		intptr = &options->password_authentication;
1184 		goto parse_flag;
1185 
1186 	case oKbdInteractiveAuthentication:
1187 		intptr = &options->kbd_interactive_authentication;
1188 		goto parse_flag;
1189 
1190 	case oKbdInteractiveDevices:
1191 		charptr = &options->kbd_interactive_devices;
1192 		goto parse_string;
1193 
1194 	case oPubkeyAuthentication:
1195 		multistate_ptr = multistate_pubkey_auth;
1196 		intptr = &options->pubkey_authentication;
1197 		goto parse_multistate;
1198 
1199 	case oHostbasedAuthentication:
1200 		intptr = &options->hostbased_authentication;
1201 		goto parse_flag;
1202 
1203 	case oGssAuthentication:
1204 		intptr = &options->gss_authentication;
1205 		goto parse_flag;
1206 
1207 	case oGssDelegateCreds:
1208 		intptr = &options->gss_deleg_creds;
1209 		goto parse_flag;
1210 
1211 	case oBatchMode:
1212 		intptr = &options->batch_mode;
1213 		goto parse_flag;
1214 
1215 	case oCheckHostIP:
1216 		intptr = &options->check_host_ip;
1217 		goto parse_flag;
1218 
1219 	case oVerifyHostKeyDNS:
1220 		intptr = &options->verify_host_key_dns;
1221 		multistate_ptr = multistate_yesnoask;
1222 		goto parse_multistate;
1223 
1224 	case oStrictHostKeyChecking:
1225 		intptr = &options->strict_host_key_checking;
1226 		multistate_ptr = multistate_strict_hostkey;
1227 		goto parse_multistate;
1228 
1229 	case oCompression:
1230 		intptr = &options->compression;
1231 		multistate_ptr = multistate_compression;
1232 		goto parse_multistate;
1233 
1234 	case oTCPKeepAlive:
1235 		intptr = &options->tcp_keep_alive;
1236 		goto parse_flag;
1237 
1238 	case oNoHostAuthenticationForLocalhost:
1239 		intptr = &options->no_host_authentication_for_localhost;
1240 		goto parse_flag;
1241 
1242 	case oNumberOfPasswordPrompts:
1243 		intptr = &options->number_of_password_prompts;
1244 		goto parse_int;
1245 
1246 	case oRekeyLimit:
1247 		arg = argv_next(&ac, &av);
1248 		if (!arg || *arg == '\0') {
1249 			error("%.200s line %d: Missing argument.", filename,
1250 			    linenum);
1251 			goto out;
1252 		}
1253 		if (strcmp(arg, "default") == 0) {
1254 			val64 = 0;
1255 		} else {
1256 			if (scan_scaled(arg, &val64) == -1) {
1257 				error("%.200s line %d: Bad number '%s': %s",
1258 				    filename, linenum, arg, strerror(errno));
1259 				goto out;
1260 			}
1261 			if (val64 != 0 && val64 < 16) {
1262 				error("%.200s line %d: RekeyLimit too small",
1263 				    filename, linenum);
1264 				goto out;
1265 			}
1266 		}
1267 		if (*activep && options->rekey_limit == -1)
1268 			options->rekey_limit = val64;
1269 		if (ac != 0) { /* optional rekey interval present */
1270 			if (strcmp(av[0], "none") == 0) {
1271 				(void)argv_next(&ac, &av);	/* discard */
1272 				break;
1273 			}
1274 			intptr = &options->rekey_interval;
1275 			goto parse_time;
1276 		}
1277 		break;
1278 
1279 	case oIdentityFile:
1280 		arg = argv_next(&ac, &av);
1281 		if (!arg || *arg == '\0') {
1282 			error("%.200s line %d: Missing argument.",
1283 			    filename, linenum);
1284 			goto out;
1285 		}
1286 		if (*activep) {
1287 			intptr = &options->num_identity_files;
1288 			if (*intptr >= SSH_MAX_IDENTITY_FILES) {
1289 				error("%.200s line %d: Too many identity files "
1290 				    "specified (max %d).", filename, linenum,
1291 				    SSH_MAX_IDENTITY_FILES);
1292 				goto out;
1293 			}
1294 			add_identity_file(options, NULL,
1295 			    arg, flags & SSHCONF_USERCONF);
1296 		}
1297 		break;
1298 
1299 	case oCertificateFile:
1300 		arg = argv_next(&ac, &av);
1301 		if (!arg || *arg == '\0') {
1302 			error("%.200s line %d: Missing argument.",
1303 			    filename, linenum);
1304 			goto out;
1305 		}
1306 		if (*activep) {
1307 			intptr = &options->num_certificate_files;
1308 			if (*intptr >= SSH_MAX_CERTIFICATE_FILES) {
1309 				error("%.200s line %d: Too many certificate "
1310 				    "files specified (max %d).",
1311 				    filename, linenum,
1312 				    SSH_MAX_CERTIFICATE_FILES);
1313 				goto out;
1314 			}
1315 			add_certificate_file(options, arg,
1316 			    flags & SSHCONF_USERCONF);
1317 		}
1318 		break;
1319 
1320 	case oXAuthLocation:
1321 		charptr=&options->xauth_location;
1322 		goto parse_string;
1323 
1324 	case oUser:
1325 		charptr = &options->user;
1326 parse_string:
1327 		arg = argv_next(&ac, &av);
1328 		if (!arg || *arg == '\0') {
1329 			error("%.200s line %d: Missing argument.",
1330 			    filename, linenum);
1331 			goto out;
1332 		}
1333 		if (*activep && *charptr == NULL)
1334 			*charptr = xstrdup(arg);
1335 		break;
1336 
1337 	case oGlobalKnownHostsFile:
1338 		cpptr = (char **)&options->system_hostfiles;
1339 		uintptr = &options->num_system_hostfiles;
1340 		max_entries = SSH_MAX_HOSTS_FILES;
1341 parse_char_array:
1342 		i = 0;
1343 		value = *uintptr == 0; /* was array empty when we started? */
1344 		while ((arg = argv_next(&ac, &av)) != NULL) {
1345 			if (*arg == '\0') {
1346 				error("%s line %d: keyword %s empty argument",
1347 				    filename, linenum, keyword);
1348 				goto out;
1349 			}
1350 			/* Allow "none" only in first position */
1351 			if (strcasecmp(arg, "none") == 0) {
1352 				if (i > 0 || ac > 0) {
1353 					error("%s line %d: keyword %s \"none\" "
1354 					    "argument must appear alone.",
1355 					    filename, linenum, keyword);
1356 					goto out;
1357 				}
1358 			}
1359 			i++;
1360 			if (*activep && value) {
1361 				if ((*uintptr) >= max_entries) {
1362 					error("%s line %d: too many %s "
1363 					    "entries.", filename, linenum,
1364 					    keyword);
1365 					goto out;
1366 				}
1367 				cpptr[(*uintptr)++] = xstrdup(arg);
1368 			}
1369 		}
1370 		break;
1371 
1372 	case oUserKnownHostsFile:
1373 		cpptr = (char **)&options->user_hostfiles;
1374 		uintptr = &options->num_user_hostfiles;
1375 		max_entries = SSH_MAX_HOSTS_FILES;
1376 		goto parse_char_array;
1377 
1378 	case oHostname:
1379 		charptr = &options->hostname;
1380 		goto parse_string;
1381 
1382 	case oTag:
1383 		charptr = &options->tag;
1384 		goto parse_string;
1385 
1386 	case oHostKeyAlias:
1387 		charptr = &options->host_key_alias;
1388 		goto parse_string;
1389 
1390 	case oPreferredAuthentications:
1391 		charptr = &options->preferred_authentications;
1392 		goto parse_string;
1393 
1394 	case oBindAddress:
1395 		charptr = &options->bind_address;
1396 		goto parse_string;
1397 
1398 	case oBindInterface:
1399 		charptr = &options->bind_interface;
1400 		goto parse_string;
1401 
1402 	case oPKCS11Provider:
1403 		charptr = &options->pkcs11_provider;
1404 		goto parse_string;
1405 
1406 	case oSecurityKeyProvider:
1407 		charptr = &options->sk_provider;
1408 		goto parse_string;
1409 
1410 	case oKnownHostsCommand:
1411 		charptr = &options->known_hosts_command;
1412 		goto parse_command;
1413 
1414 	case oProxyCommand:
1415 		charptr = &options->proxy_command;
1416 		/* Ignore ProxyCommand if ProxyJump already specified */
1417 		if (options->jump_host != NULL)
1418 			charptr = &options->jump_host; /* Skip below */
1419 parse_command:
1420 		if (str == NULL) {
1421 			error("%.200s line %d: Missing argument.",
1422 			    filename, linenum);
1423 			goto out;
1424 		}
1425 		len = strspn(str, WHITESPACE "=");
1426 		if (*activep && *charptr == NULL)
1427 			*charptr = xstrdup(str + len);
1428 		argv_consume(&ac);
1429 		break;
1430 
1431 	case oProxyJump:
1432 		if (str == NULL) {
1433 			error("%.200s line %d: Missing argument.",
1434 			    filename, linenum);
1435 			goto out;
1436 		}
1437 		len = strspn(str, WHITESPACE "=");
1438 		/* XXX use argv? */
1439 		if (parse_jump(str + len, options, *activep) == -1) {
1440 			error("%.200s line %d: Invalid ProxyJump \"%s\"",
1441 			    filename, linenum, str + len);
1442 			goto out;
1443 		}
1444 		argv_consume(&ac);
1445 		break;
1446 
1447 	case oPort:
1448 		arg = argv_next(&ac, &av);
1449 		if (!arg || *arg == '\0') {
1450 			error("%.200s line %d: Missing argument.",
1451 			    filename, linenum);
1452 			goto out;
1453 		}
1454 		value = a2port(arg);
1455 		if (value <= 0) {
1456 			error("%.200s line %d: Bad port '%s'.",
1457 			    filename, linenum, arg);
1458 			goto out;
1459 		}
1460 		if (*activep && options->port == -1)
1461 			options->port = value;
1462 		break;
1463 
1464 	case oConnectionAttempts:
1465 		intptr = &options->connection_attempts;
1466 parse_int:
1467 		arg = argv_next(&ac, &av);
1468 		if ((errstr = atoi_err(arg, &value)) != NULL) {
1469 			error("%s line %d: integer value %s.",
1470 			    filename, linenum, errstr);
1471 			goto out;
1472 		}
1473 		if (*activep && *intptr == -1)
1474 			*intptr = value;
1475 		break;
1476 
1477 	case oCiphers:
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 		    !ciphers_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)){
1486 			error("%.200s line %d: Bad SSH2 cipher spec '%s'.",
1487 			    filename, linenum, arg ? arg : "<NONE>");
1488 			goto out;
1489 		}
1490 		if (*activep && options->ciphers == NULL)
1491 			options->ciphers = xstrdup(arg);
1492 		break;
1493 
1494 	case oMacs:
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 		    !mac_valid(*arg == '+' || *arg == '^' ? arg + 1 : arg)) {
1503 			error("%.200s line %d: Bad SSH2 MAC spec '%s'.",
1504 			    filename, linenum, arg ? arg : "<NONE>");
1505 			goto out;
1506 		}
1507 		if (*activep && options->macs == NULL)
1508 			options->macs = xstrdup(arg);
1509 		break;
1510 
1511 	case oKexAlgorithms:
1512 		arg = argv_next(&ac, &av);
1513 		if (!arg || *arg == '\0') {
1514 			error("%.200s line %d: Missing argument.",
1515 			    filename, linenum);
1516 			goto out;
1517 		}
1518 		if (*arg != '-' &&
1519 		    !kex_names_valid(*arg == '+' || *arg == '^' ?
1520 		    arg + 1 : arg)) {
1521 			error("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
1522 			    filename, linenum, arg ? arg : "<NONE>");
1523 			goto out;
1524 		}
1525 		if (*activep && options->kex_algorithms == NULL)
1526 			options->kex_algorithms = xstrdup(arg);
1527 		break;
1528 
1529 	case oHostKeyAlgorithms:
1530 		charptr = &options->hostkeyalgorithms;
1531 		ca_only = 0;
1532 parse_pubkey_algos:
1533 		arg = argv_next(&ac, &av);
1534 		if (!arg || *arg == '\0') {
1535 			error("%.200s line %d: Missing argument.",
1536 			    filename, linenum);
1537 			goto out;
1538 		}
1539 		if (*arg != '-' &&
1540 		    !sshkey_names_valid2(*arg == '+' || *arg == '^' ?
1541 		    arg + 1 : arg, 1, ca_only)) {
1542 			error("%s line %d: Bad key types '%s'.",
1543 			    filename, linenum, arg ? arg : "<NONE>");
1544 			goto out;
1545 		}
1546 		if (*activep && *charptr == NULL)
1547 			*charptr = xstrdup(arg);
1548 		break;
1549 
1550 	case oCASignatureAlgorithms:
1551 		charptr = &options->ca_sign_algorithms;
1552 		ca_only = 1;
1553 		goto parse_pubkey_algos;
1554 
1555 	case oLogLevel:
1556 		log_level_ptr = &options->log_level;
1557 		arg = argv_next(&ac, &av);
1558 		value = log_level_number(arg);
1559 		if (value == SYSLOG_LEVEL_NOT_SET) {
1560 			error("%.200s line %d: unsupported log level '%s'",
1561 			    filename, linenum, arg ? arg : "<NONE>");
1562 			goto out;
1563 		}
1564 		if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
1565 			*log_level_ptr = (LogLevel) value;
1566 		break;
1567 
1568 	case oLogFacility:
1569 		log_facility_ptr = &options->log_facility;
1570 		arg = argv_next(&ac, &av);
1571 		value = log_facility_number(arg);
1572 		if (value == SYSLOG_FACILITY_NOT_SET) {
1573 			error("%.200s line %d: unsupported log facility '%s'",
1574 			    filename, linenum, arg ? arg : "<NONE>");
1575 			goto out;
1576 		}
1577 		if (*log_facility_ptr == -1)
1578 			*log_facility_ptr = (SyslogFacility) value;
1579 		break;
1580 
1581 	case oLogVerbose:
1582 		cppptr = &options->log_verbose;
1583 		uintptr = &options->num_log_verbose;
1584 		i = 0;
1585 		while ((arg = argv_next(&ac, &av)) != NULL) {
1586 			if (*arg == '\0') {
1587 				error("%s line %d: keyword %s empty argument",
1588 				    filename, linenum, keyword);
1589 				goto out;
1590 			}
1591 			/* Allow "none" only in first position */
1592 			if (strcasecmp(arg, "none") == 0) {
1593 				if (i > 0 || ac > 0) {
1594 					error("%s line %d: keyword %s \"none\" "
1595 					    "argument must appear alone.",
1596 					    filename, linenum, keyword);
1597 					goto out;
1598 				}
1599 			}
1600 			i++;
1601 			if (*activep && *uintptr == 0) {
1602 				*cppptr = xrecallocarray(*cppptr, *uintptr,
1603 				    *uintptr + 1, sizeof(**cppptr));
1604 				(*cppptr)[(*uintptr)++] = xstrdup(arg);
1605 			}
1606 		}
1607 		break;
1608 
1609 	case oLocalForward:
1610 	case oRemoteForward:
1611 	case oDynamicForward:
1612 		arg = argv_next(&ac, &av);
1613 		if (!arg || *arg == '\0') {
1614 			error("%.200s line %d: Missing argument.",
1615 			    filename, linenum);
1616 			goto out;
1617 		}
1618 
1619 		remotefwd = (opcode == oRemoteForward);
1620 		dynamicfwd = (opcode == oDynamicForward);
1621 
1622 		if (!dynamicfwd) {
1623 			arg2 = argv_next(&ac, &av);
1624 			if (arg2 == NULL || *arg2 == '\0') {
1625 				if (remotefwd)
1626 					dynamicfwd = 1;
1627 				else {
1628 					error("%.200s line %d: Missing target "
1629 					    "argument.", filename, linenum);
1630 					goto out;
1631 				}
1632 			} else {
1633 				/* construct a string for parse_forward */
1634 				snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg,
1635 				    arg2);
1636 			}
1637 		}
1638 		if (dynamicfwd)
1639 			strlcpy(fwdarg, arg, sizeof(fwdarg));
1640 
1641 		if (parse_forward(&fwd, fwdarg, dynamicfwd, remotefwd) == 0) {
1642 			error("%.200s line %d: Bad forwarding specification.",
1643 			    filename, linenum);
1644 			goto out;
1645 		}
1646 
1647 		if (*activep) {
1648 			if (remotefwd) {
1649 				add_remote_forward(options, &fwd);
1650 			} else {
1651 				add_local_forward(options, &fwd);
1652 			}
1653 		}
1654 		break;
1655 
1656 	case oPermitRemoteOpen:
1657 		uintptr = &options->num_permitted_remote_opens;
1658 		cppptr = &options->permitted_remote_opens;
1659 		found = *uintptr == 0;
1660 		while ((arg = argv_next(&ac, &av)) != NULL) {
1661 			arg2 = xstrdup(arg);
1662 			/* Allow any/none only in first position */
1663 			if (strcasecmp(arg, "none") == 0 ||
1664 			    strcasecmp(arg, "any") == 0) {
1665 				if (nstrs > 0 || ac > 0) {
1666 					error("%s line %d: keyword %s \"%s\" "
1667 					    "argument must appear alone.",
1668 					    filename, linenum, keyword, arg);
1669 					free(arg2);
1670 					goto out;
1671 				}
1672 			} else {
1673 				p = hpdelim(&arg);
1674 				if (p == NULL) {
1675 					fatal("%s line %d: missing host in %s",
1676 					    filename, linenum,
1677 					    lookup_opcode_name(opcode));
1678 				}
1679 				p = cleanhostname(p);
1680 				/*
1681 				 * don't want to use permitopen_port to avoid
1682 				 * dependency on channels.[ch] here.
1683 				 */
1684 				if (arg == NULL || (strcmp(arg, "*") != 0 &&
1685 				    a2port(arg) <= 0)) {
1686 					fatal("%s line %d: bad port number "
1687 					    "in %s", filename, linenum,
1688 					    lookup_opcode_name(opcode));
1689 				}
1690 			}
1691 			opt_array_append(filename, linenum,
1692 			    lookup_opcode_name(opcode),
1693 			    &strs, &nstrs, arg2);
1694 			free(arg2);
1695 		}
1696 		if (nstrs == 0)
1697 			fatal("%s line %d: missing %s specification",
1698 			    filename, linenum, lookup_opcode_name(opcode));
1699 		if (found && *activep) {
1700 			*cppptr = strs;
1701 			*uintptr = nstrs;
1702 			strs = NULL; /* transferred */
1703 			nstrs = 0;
1704 		}
1705 		break;
1706 
1707 	case oClearAllForwardings:
1708 		intptr = &options->clear_forwardings;
1709 		goto parse_flag;
1710 
1711 	case oHost:
1712 		if (cmdline) {
1713 			error("Host directive not supported as a command-line "
1714 			    "option");
1715 			goto out;
1716 		}
1717 		*activep = 0;
1718 		arg2 = NULL;
1719 		while ((arg = argv_next(&ac, &av)) != NULL) {
1720 			if (*arg == '\0') {
1721 				error("%s line %d: keyword %s empty argument",
1722 				    filename, linenum, keyword);
1723 				goto out;
1724 			}
1725 			if ((flags & SSHCONF_NEVERMATCH) != 0) {
1726 				argv_consume(&ac);
1727 				break;
1728 			}
1729 			negated = *arg == '!';
1730 			if (negated)
1731 				arg++;
1732 			if (match_pattern(host, arg)) {
1733 				if (negated) {
1734 					debug("%.200s line %d: Skipping Host "
1735 					    "block because of negated match "
1736 					    "for %.100s", filename, linenum,
1737 					    arg);
1738 					*activep = 0;
1739 					argv_consume(&ac);
1740 					break;
1741 				}
1742 				if (!*activep)
1743 					arg2 = arg; /* logged below */
1744 				*activep = 1;
1745 			}
1746 		}
1747 		if (*activep)
1748 			debug("%.200s line %d: Applying options for %.100s",
1749 			    filename, linenum, arg2);
1750 		break;
1751 
1752 	case oMatch:
1753 		if (cmdline) {
1754 			error("Host directive not supported as a command-line "
1755 			    "option");
1756 			goto out;
1757 		}
1758 		value = match_cfg_line(options, &str, pw, host, original_host,
1759 		    flags & SSHCONF_FINAL, want_final_pass,
1760 		    filename, linenum);
1761 		if (value < 0) {
1762 			error("%.200s line %d: Bad Match condition", filename,
1763 			    linenum);
1764 			goto out;
1765 		}
1766 		*activep = (flags & SSHCONF_NEVERMATCH) ? 0 : value;
1767 		/*
1768 		 * If match_cfg_line() didn't consume all its arguments then
1769 		 * arrange for the extra arguments check below to fail.
1770 		 */
1771 
1772 		if (str == NULL || *str == '\0')
1773 			argv_consume(&ac);
1774 		break;
1775 
1776 	case oEscapeChar:
1777 		intptr = &options->escape_char;
1778 		arg = argv_next(&ac, &av);
1779 		if (!arg || *arg == '\0') {
1780 			error("%.200s line %d: Missing argument.",
1781 			    filename, linenum);
1782 			goto out;
1783 		}
1784 		if (strcmp(arg, "none") == 0)
1785 			value = SSH_ESCAPECHAR_NONE;
1786 		else if (arg[1] == '\0')
1787 			value = (u_char) arg[0];
1788 		else if (arg[0] == '^' && arg[2] == 0 &&
1789 		    (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
1790 			value = (u_char) arg[1] & 31;
1791 		else {
1792 			error("%.200s line %d: Bad escape character.",
1793 			    filename, linenum);
1794 			goto out;
1795 		}
1796 		if (*activep && *intptr == -1)
1797 			*intptr = value;
1798 		break;
1799 
1800 	case oAddressFamily:
1801 		intptr = &options->address_family;
1802 		multistate_ptr = multistate_addressfamily;
1803 		goto parse_multistate;
1804 
1805 	case oEnableSSHKeysign:
1806 		intptr = &options->enable_ssh_keysign;
1807 		goto parse_flag;
1808 
1809 	case oIdentitiesOnly:
1810 		intptr = &options->identities_only;
1811 		goto parse_flag;
1812 
1813 	case oServerAliveInterval:
1814 		intptr = &options->server_alive_interval;
1815 		goto parse_time;
1816 
1817 	case oServerAliveCountMax:
1818 		intptr = &options->server_alive_count_max;
1819 		goto parse_int;
1820 
1821 	case oSendEnv:
1822 		/* XXX appends to list; doesn't respect first-match-wins */
1823 		while ((arg = argv_next(&ac, &av)) != NULL) {
1824 			if (*arg == '\0' || strchr(arg, '=') != NULL) {
1825 				error("%s line %d: Invalid environment name.",
1826 				    filename, linenum);
1827 				goto out;
1828 			}
1829 			found = 1;
1830 			if (!*activep)
1831 				continue;
1832 			if (*arg == '-') {
1833 				/* Removing an env var */
1834 				rm_env(options, arg, filename, linenum);
1835 				continue;
1836 			}
1837 			opt_array_append(filename, linenum,
1838 			    lookup_opcode_name(opcode),
1839 			    &options->send_env, &options->num_send_env, arg);
1840 		}
1841 		if (!found) {
1842 			fatal("%s line %d: no %s specified",
1843 			    filename, linenum, keyword);
1844 		}
1845 		break;
1846 
1847 	case oSetEnv:
1848 		found = options->num_setenv == 0;
1849 		while ((arg = argv_next(&ac, &av)) != NULL) {
1850 			if (strchr(arg, '=') == NULL) {
1851 				error("%s line %d: Invalid SetEnv.",
1852 				    filename, linenum);
1853 				goto out;
1854 			}
1855 			if (lookup_setenv_in_list(arg, strs, nstrs) != NULL) {
1856 				debug2("%s line %d: ignoring duplicate env "
1857 				    "name \"%.64s\"", filename, linenum, arg);
1858 				continue;
1859 			}
1860 			opt_array_append(filename, linenum,
1861 			    lookup_opcode_name(opcode),
1862 			    &strs, &nstrs, arg);
1863 		}
1864 		if (nstrs == 0) {
1865 			fatal("%s line %d: no %s specified",
1866 			    filename, linenum, keyword);
1867 		}
1868 		if (found && *activep) {
1869 			options->setenv = strs;
1870 			options->num_setenv = nstrs;
1871 			strs = NULL; /* transferred */
1872 			nstrs = 0;
1873 		}
1874 		break;
1875 
1876 	case oControlPath:
1877 		charptr = &options->control_path;
1878 		goto parse_string;
1879 
1880 	case oControlMaster:
1881 		intptr = &options->control_master;
1882 		multistate_ptr = multistate_controlmaster;
1883 		goto parse_multistate;
1884 
1885 	case oControlPersist:
1886 		/* no/false/yes/true, or a time spec */
1887 		intptr = &options->control_persist;
1888 		arg = argv_next(&ac, &av);
1889 		if (!arg || *arg == '\0') {
1890 			error("%.200s line %d: Missing ControlPersist"
1891 			    " argument.", filename, linenum);
1892 			goto out;
1893 		}
1894 		value = 0;
1895 		value2 = 0;	/* timeout */
1896 		if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
1897 			value = 0;
1898 		else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
1899 			value = 1;
1900 		else if ((value2 = convtime(arg)) >= 0)
1901 			value = 1;
1902 		else {
1903 			error("%.200s line %d: Bad ControlPersist argument.",
1904 			    filename, linenum);
1905 			goto out;
1906 		}
1907 		if (*activep && *intptr == -1) {
1908 			*intptr = value;
1909 			options->control_persist_timeout = value2;
1910 		}
1911 		break;
1912 
1913 	case oHashKnownHosts:
1914 		intptr = &options->hash_known_hosts;
1915 		goto parse_flag;
1916 
1917 	case oTunnel:
1918 		intptr = &options->tun_open;
1919 		multistate_ptr = multistate_tunnel;
1920 		goto parse_multistate;
1921 
1922 	case oTunnelDevice:
1923 		arg = argv_next(&ac, &av);
1924 		if (!arg || *arg == '\0') {
1925 			error("%.200s line %d: Missing argument.",
1926 			    filename, linenum);
1927 			goto out;
1928 		}
1929 		value = a2tun(arg, &value2);
1930 		if (value == SSH_TUNID_ERR) {
1931 			error("%.200s line %d: Bad tun device.",
1932 			    filename, linenum);
1933 			goto out;
1934 		}
1935 		if (*activep && options->tun_local == -1) {
1936 			options->tun_local = value;
1937 			options->tun_remote = value2;
1938 		}
1939 		break;
1940 
1941 	case oLocalCommand:
1942 		charptr = &options->local_command;
1943 		goto parse_command;
1944 
1945 	case oPermitLocalCommand:
1946 		intptr = &options->permit_local_command;
1947 		goto parse_flag;
1948 
1949 	case oRemoteCommand:
1950 		charptr = &options->remote_command;
1951 		goto parse_command;
1952 
1953 	case oVisualHostKey:
1954 		intptr = &options->visual_host_key;
1955 		goto parse_flag;
1956 
1957 	case oInclude:
1958 		if (cmdline) {
1959 			error("Include directive not supported as a "
1960 			    "command-line option");
1961 			goto out;
1962 		}
1963 		value = 0;
1964 		while ((arg = argv_next(&ac, &av)) != NULL) {
1965 			if (*arg == '\0') {
1966 				error("%s line %d: keyword %s empty argument",
1967 				    filename, linenum, keyword);
1968 				goto out;
1969 			}
1970 			/*
1971 			 * Ensure all paths are anchored. User configuration
1972 			 * files may begin with '~/' but system configurations
1973 			 * must not. If the path is relative, then treat it
1974 			 * as living in ~/.ssh for user configurations or
1975 			 * /etc/ssh for system ones.
1976 			 */
1977 			if (*arg == '~' && (flags & SSHCONF_USERCONF) == 0) {
1978 				error("%.200s line %d: bad include path %s.",
1979 				    filename, linenum, arg);
1980 				goto out;
1981 			}
1982 			if (!path_absolute(arg) && *arg != '~') {
1983 				xasprintf(&arg2, "%s/%s",
1984 				    (flags & SSHCONF_USERCONF) ?
1985 				    "~/" _PATH_SSH_USER_DIR : SSHDIR, arg);
1986 			} else
1987 				arg2 = xstrdup(arg);
1988 			memset(&gl, 0, sizeof(gl));
1989 			r = glob(arg2, GLOB_TILDE, NULL, &gl);
1990 			if (r == GLOB_NOMATCH) {
1991 				debug("%.200s line %d: include %s matched no "
1992 				    "files",filename, linenum, arg2);
1993 				free(arg2);
1994 				continue;
1995 			} else if (r != 0) {
1996 				error("%.200s line %d: glob failed for %s.",
1997 				    filename, linenum, arg2);
1998 				goto out;
1999 			}
2000 			free(arg2);
2001 			oactive = *activep;
2002 			for (i = 0; i < gl.gl_pathc; i++) {
2003 				debug3("%.200s line %d: Including file %s "
2004 				    "depth %d%s", filename, linenum,
2005 				    gl.gl_pathv[i], depth,
2006 				    oactive ? "" : " (parse only)");
2007 				r = read_config_file_depth(gl.gl_pathv[i],
2008 				    pw, host, original_host, options,
2009 				    flags | SSHCONF_CHECKPERM |
2010 				    (oactive ? 0 : SSHCONF_NEVERMATCH),
2011 				    activep, want_final_pass, depth + 1);
2012 				if (r != 1 && errno != ENOENT) {
2013 					error("Can't open user config file "
2014 					    "%.100s: %.100s", gl.gl_pathv[i],
2015 					    strerror(errno));
2016 					globfree(&gl);
2017 					goto out;
2018 				}
2019 				/*
2020 				 * don't let Match in includes clobber the
2021 				 * containing file's Match state.
2022 				 */
2023 				*activep = oactive;
2024 				if (r != 1)
2025 					value = -1;
2026 			}
2027 			globfree(&gl);
2028 		}
2029 		if (value != 0)
2030 			ret = value;
2031 		break;
2032 
2033 	case oIPQoS:
2034 		arg = argv_next(&ac, &av);
2035 		if ((value = parse_ipqos(arg)) == -1) {
2036 			error("%s line %d: Bad IPQoS value: %s",
2037 			    filename, linenum, arg);
2038 			goto out;
2039 		}
2040 		arg = argv_next(&ac, &av);
2041 		if (arg == NULL)
2042 			value2 = value;
2043 		else if ((value2 = parse_ipqos(arg)) == -1) {
2044 			error("%s line %d: Bad IPQoS value: %s",
2045 			    filename, linenum, arg);
2046 			goto out;
2047 		}
2048 		if (*activep && options->ip_qos_interactive == -1) {
2049 			options->ip_qos_interactive = value;
2050 			options->ip_qos_bulk = value2;
2051 		}
2052 		break;
2053 
2054 	case oRequestTTY:
2055 		intptr = &options->request_tty;
2056 		multistate_ptr = multistate_requesttty;
2057 		goto parse_multistate;
2058 
2059 	case oSessionType:
2060 		intptr = &options->session_type;
2061 		multistate_ptr = multistate_sessiontype;
2062 		goto parse_multistate;
2063 
2064 	case oStdinNull:
2065 		intptr = &options->stdin_null;
2066 		goto parse_flag;
2067 
2068 	case oForkAfterAuthentication:
2069 		intptr = &options->fork_after_authentication;
2070 		goto parse_flag;
2071 
2072 	case oIgnoreUnknown:
2073 		charptr = &options->ignored_unknown;
2074 		goto parse_string;
2075 
2076 	case oProxyUseFdpass:
2077 		intptr = &options->proxy_use_fdpass;
2078 		goto parse_flag;
2079 
2080 	case oCanonicalDomains:
2081 		found = options->num_canonical_domains == 0;
2082 		while ((arg = argv_next(&ac, &av)) != NULL) {
2083 			/* Allow "none" only in first position */
2084 			if (strcasecmp(arg, "none") == 0) {
2085 				if (nstrs > 0 || ac > 0) {
2086 					error("%s line %d: keyword %s \"none\" "
2087 					    "argument must appear alone.",
2088 					    filename, linenum, keyword);
2089 					goto out;
2090 				}
2091 			}
2092 			if (!valid_domain(arg, 1, &errstr)) {
2093 				error("%s line %d: %s", filename, linenum,
2094 				    errstr);
2095 				goto out;
2096 			}
2097 			opt_array_append(filename, linenum, keyword,
2098 			    &strs, &nstrs, arg);
2099 		}
2100 		if (nstrs == 0) {
2101 			fatal("%s line %d: no %s specified",
2102 			    filename, linenum, keyword);
2103 		}
2104 		if (found && *activep) {
2105 			options->canonical_domains = strs;
2106 			options->num_canonical_domains = nstrs;
2107 			strs = NULL; /* transferred */
2108 			nstrs = 0;
2109 		}
2110 		break;
2111 
2112 	case oCanonicalizePermittedCNAMEs:
2113 		found = options->num_permitted_cnames == 0;
2114 		while ((arg = argv_next(&ac, &av)) != NULL) {
2115 			/*
2116 			 * Either 'none' (only in first position), '*' for
2117 			 * everything or 'list:list'
2118 			 */
2119 			if (strcasecmp(arg, "none") == 0) {
2120 				if (ncnames > 0 || ac > 0) {
2121 					error("%s line %d: keyword %s \"none\" "
2122 					    "argument must appear alone.",
2123 					    filename, linenum, keyword);
2124 					goto out;
2125 				}
2126 				arg2 = "";
2127 			} else if (strcmp(arg, "*") == 0) {
2128 				arg2 = arg;
2129 			} else {
2130 				lowercase(arg);
2131 				if ((arg2 = strchr(arg, ':')) == NULL ||
2132 				    arg2[1] == '\0') {
2133 					error("%s line %d: "
2134 					    "Invalid permitted CNAME \"%s\"",
2135 					    filename, linenum, arg);
2136 					goto out;
2137 				}
2138 				*arg2 = '\0';
2139 				arg2++;
2140 			}
2141 			cnames = xrecallocarray(cnames, ncnames, ncnames + 1,
2142 			    sizeof(*cnames));
2143 			cnames[ncnames].source_list = xstrdup(arg);
2144 			cnames[ncnames].target_list = xstrdup(arg2);
2145 			ncnames++;
2146 		}
2147 		if (ncnames == 0) {
2148 			fatal("%s line %d: no %s specified",
2149 			    filename, linenum, keyword);
2150 		}
2151 		if (found && *activep) {
2152 			options->permitted_cnames = cnames;
2153 			options->num_permitted_cnames = ncnames;
2154 			cnames = NULL; /* transferred */
2155 			ncnames = 0;
2156 		}
2157 		/* un-transferred cnames is cleaned up before exit */
2158 		break;
2159 
2160 	case oCanonicalizeHostname:
2161 		intptr = &options->canonicalize_hostname;
2162 		multistate_ptr = multistate_canonicalizehostname;
2163 		goto parse_multistate;
2164 
2165 	case oCanonicalizeMaxDots:
2166 		intptr = &options->canonicalize_max_dots;
2167 		goto parse_int;
2168 
2169 	case oCanonicalizeFallbackLocal:
2170 		intptr = &options->canonicalize_fallback_local;
2171 		goto parse_flag;
2172 
2173 	case oStreamLocalBindMask:
2174 		arg = argv_next(&ac, &av);
2175 		if (!arg || *arg == '\0') {
2176 			error("%.200s line %d: Missing StreamLocalBindMask "
2177 			    "argument.", filename, linenum);
2178 			goto out;
2179 		}
2180 		/* Parse mode in octal format */
2181 		value = strtol(arg, &endofnumber, 8);
2182 		if (arg == endofnumber || value < 0 || value > 0777) {
2183 			error("%.200s line %d: Bad mask.", filename, linenum);
2184 			goto out;
2185 		}
2186 		options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
2187 		break;
2188 
2189 	case oStreamLocalBindUnlink:
2190 		intptr = &options->fwd_opts.streamlocal_bind_unlink;
2191 		goto parse_flag;
2192 
2193 	case oRevokedHostKeys:
2194 		charptr = &options->revoked_host_keys;
2195 		goto parse_string;
2196 
2197 	case oFingerprintHash:
2198 		intptr = &options->fingerprint_hash;
2199 		arg = argv_next(&ac, &av);
2200 		if (!arg || *arg == '\0') {
2201 			error("%.200s line %d: Missing argument.",
2202 			    filename, linenum);
2203 			goto out;
2204 		}
2205 		if ((value = ssh_digest_alg_by_name(arg)) == -1) {
2206 			error("%.200s line %d: Invalid hash algorithm \"%s\".",
2207 			    filename, linenum, arg);
2208 			goto out;
2209 		}
2210 		if (*activep && *intptr == -1)
2211 			*intptr = value;
2212 		break;
2213 
2214 	case oUpdateHostkeys:
2215 		intptr = &options->update_hostkeys;
2216 		multistate_ptr = multistate_yesnoask;
2217 		goto parse_multistate;
2218 
2219 	case oHostbasedAcceptedAlgorithms:
2220 		charptr = &options->hostbased_accepted_algos;
2221 		ca_only = 0;
2222 		goto parse_pubkey_algos;
2223 
2224 	case oPubkeyAcceptedAlgorithms:
2225 		charptr = &options->pubkey_accepted_algos;
2226 		ca_only = 0;
2227 		goto parse_pubkey_algos;
2228 
2229 	case oAddKeysToAgent:
2230 		arg = argv_next(&ac, &av);
2231 		arg2 = argv_next(&ac, &av);
2232 		value = parse_multistate_value(arg, filename, linenum,
2233 		    multistate_yesnoaskconfirm);
2234 		value2 = 0; /* unlimited lifespan by default */
2235 		if (value == 3 && arg2 != NULL) {
2236 			/* allow "AddKeysToAgent confirm 5m" */
2237 			if ((value2 = convtime(arg2)) == -1) {
2238 				error("%s line %d: invalid time value.",
2239 				    filename, linenum);
2240 				goto out;
2241 			}
2242 		} else if (value == -1 && arg2 == NULL) {
2243 			if ((value2 = convtime(arg)) == -1) {
2244 				error("%s line %d: unsupported option",
2245 				    filename, linenum);
2246 				goto out;
2247 			}
2248 			value = 1; /* yes */
2249 		} else if (value == -1 || arg2 != NULL) {
2250 			error("%s line %d: unsupported option",
2251 			    filename, linenum);
2252 			goto out;
2253 		}
2254 		if (*activep && options->add_keys_to_agent == -1) {
2255 			options->add_keys_to_agent = value;
2256 			options->add_keys_to_agent_lifespan = value2;
2257 		}
2258 		break;
2259 
2260 	case oIdentityAgent:
2261 		charptr = &options->identity_agent;
2262 		arg = argv_next(&ac, &av);
2263 		if (!arg || *arg == '\0') {
2264 			error("%.200s line %d: Missing argument.",
2265 			    filename, linenum);
2266 			goto out;
2267 		}
2268   parse_agent_path:
2269 		/* Extra validation if the string represents an env var. */
2270 		if ((arg2 = dollar_expand(&r, arg)) == NULL || r) {
2271 			error("%.200s line %d: Invalid environment expansion "
2272 			    "%s.", filename, linenum, arg);
2273 			goto out;
2274 		}
2275 		free(arg2);
2276 		/* check for legacy environment format */
2277 		if (arg[0] == '$' && arg[1] != '{' &&
2278 		    !valid_env_name(arg + 1)) {
2279 			error("%.200s line %d: Invalid environment name %s.",
2280 			    filename, linenum, arg);
2281 			goto out;
2282 		}
2283 		if (*activep && *charptr == NULL)
2284 			*charptr = xstrdup(arg);
2285 		break;
2286 
2287 	case oEnableEscapeCommandline:
2288 		intptr = &options->enable_escape_commandline;
2289 		goto parse_flag;
2290 
2291 	case oRequiredRSASize:
2292 		intptr = &options->required_rsa_size;
2293 		goto parse_int;
2294 
2295 	case oObscureKeystrokeTiming:
2296 		value = -1;
2297 		while ((arg = argv_next(&ac, &av)) != NULL) {
2298 			if (value != -1) {
2299 				error("%s line %d: invalid arguments",
2300 				    filename, linenum);
2301 				goto out;
2302 			}
2303 			if (strcmp(arg, "yes") == 0 ||
2304 			    strcmp(arg, "true") == 0)
2305 				value = SSH_KEYSTROKE_DEFAULT_INTERVAL_MS;
2306 			else if (strcmp(arg, "no") == 0 ||
2307 			    strcmp(arg, "false") == 0)
2308 				value = 0;
2309 			else if (strncmp(arg, "interval:", 9) == 0) {
2310 				if ((errstr = atoi_err(arg + 9,
2311 				    &value)) != NULL) {
2312 					error("%s line %d: integer value %s.",
2313 					    filename, linenum, errstr);
2314 					goto out;
2315 				}
2316 				if (value <= 0 || value > 1000) {
2317 					error("%s line %d: value out of range.",
2318 					    filename, linenum);
2319 					goto out;
2320 				}
2321 			} else {
2322 				error("%s line %d: unsupported argument \"%s\"",
2323 				    filename, linenum, arg);
2324 				goto out;
2325 			}
2326 		}
2327 		if (value == -1) {
2328 			error("%s line %d: missing argument",
2329 			    filename, linenum);
2330 			goto out;
2331 		}
2332 		intptr = &options->obscure_keystroke_timing_interval;
2333 		if (*activep && *intptr == -1)
2334 			*intptr = value;
2335 		break;
2336 
2337 	case oChannelTimeout:
2338 		found = options->num_channel_timeouts == 0;
2339 		while ((arg = argv_next(&ac, &av)) != NULL) {
2340 			/* Allow "none" only in first position */
2341 			if (strcasecmp(arg, "none") == 0) {
2342 				if (nstrs > 0 || ac > 0) {
2343 					error("%s line %d: keyword %s \"none\" "
2344 					    "argument must appear alone.",
2345 					    filename, linenum, keyword);
2346 					goto out;
2347 				}
2348 			} else if (parse_pattern_interval(arg,
2349 			    NULL, NULL) != 0) {
2350 				fatal("%s line %d: invalid channel timeout %s",
2351 				    filename, linenum, arg);
2352 			}
2353 			opt_array_append(filename, linenum, keyword,
2354 			    &strs, &nstrs, arg);
2355 		}
2356 		if (nstrs == 0) {
2357 			fatal("%s line %d: no %s specified",
2358 			    filename, linenum, keyword);
2359 		}
2360 		if (found && *activep) {
2361 			options->channel_timeouts = strs;
2362 			options->num_channel_timeouts = nstrs;
2363 			strs = NULL; /* transferred */
2364 			nstrs = 0;
2365 		}
2366 		break;
2367 
2368 	case oDeprecated:
2369 		debug("%s line %d: Deprecated option \"%s\"",
2370 		    filename, linenum, keyword);
2371 		argv_consume(&ac);
2372 		break;
2373 
2374 	case oUnsupported:
2375 		error("%s line %d: Unsupported option \"%s\"",
2376 		    filename, linenum, keyword);
2377 		argv_consume(&ac);
2378 		break;
2379 
2380 	default:
2381 		error("%s line %d: Unimplemented opcode %d",
2382 		    filename, linenum, opcode);
2383 		goto out;
2384 	}
2385 
2386 	/* Check that there is no garbage at end of line. */
2387 	if (ac > 0) {
2388 		error("%.200s line %d: keyword %s extra arguments "
2389 		    "at end of line", filename, linenum, keyword);
2390 		goto out;
2391 	}
2392 
2393 	/* success */
2394 	ret = 0;
2395  out:
2396 	free_canon_cnames(cnames, ncnames);
2397 	opt_array_free2(strs, NULL, nstrs);
2398 	argv_free(oav, oac);
2399 	return ret;
2400 }
2401 
2402 /*
2403  * Reads the config file and modifies the options accordingly.  Options
2404  * should already be initialized before this call.  This never returns if
2405  * there is an error.  If the file does not exist, this returns 0.
2406  */
2407 int
2408 read_config_file(const char *filename, struct passwd *pw, const char *host,
2409     const char *original_host, Options *options, int flags,
2410     int *want_final_pass)
2411 {
2412 	int active = 1;
2413 
2414 	return read_config_file_depth(filename, pw, host, original_host,
2415 	    options, flags, &active, want_final_pass, 0);
2416 }
2417 
2418 #define READCONF_MAX_DEPTH	16
2419 static int
2420 read_config_file_depth(const char *filename, struct passwd *pw,
2421     const char *host, const char *original_host, Options *options,
2422     int flags, int *activep, int *want_final_pass, int depth)
2423 {
2424 	FILE *f;
2425 	char *line = NULL;
2426 	size_t linesize = 0;
2427 	int linenum;
2428 	int bad_options = 0;
2429 
2430 	if (depth < 0 || depth > READCONF_MAX_DEPTH)
2431 		fatal("Too many recursive configuration includes");
2432 
2433 	if ((f = fopen(filename, "r")) == NULL)
2434 		return 0;
2435 
2436 	if (flags & SSHCONF_CHECKPERM) {
2437 		struct stat sb;
2438 
2439 		if (fstat(fileno(f), &sb) == -1)
2440 			fatal("fstat %s: %s", filename, strerror(errno));
2441 		if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
2442 		    (sb.st_mode & 022) != 0))
2443 			fatal("Bad owner or permissions on %s", filename);
2444 	}
2445 
2446 	debug("Reading configuration data %.200s", filename);
2447 
2448 	/*
2449 	 * Mark that we are now processing the options.  This flag is turned
2450 	 * on/off by Host specifications.
2451 	 */
2452 	linenum = 0;
2453 	while (getline(&line, &linesize, f) != -1) {
2454 		/* Update line number counter. */
2455 		linenum++;
2456 		/*
2457 		 * Trim out comments and strip whitespace.
2458 		 * NB - preserve newlines, they are needed to reproduce
2459 		 * line numbers later for error messages.
2460 		 */
2461 		if (process_config_line_depth(options, pw, host, original_host,
2462 		    line, filename, linenum, activep, flags, want_final_pass,
2463 		    depth) != 0)
2464 			bad_options++;
2465 	}
2466 	free(line);
2467 	fclose(f);
2468 	if (bad_options > 0)
2469 		fatal("%s: terminating, %d bad configuration options",
2470 		    filename, bad_options);
2471 	return 1;
2472 }
2473 
2474 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
2475 int
2476 option_clear_or_none(const char *o)
2477 {
2478 	return o == NULL || strcasecmp(o, "none") == 0;
2479 }
2480 
2481 /*
2482  * Returns 1 if CanonicalizePermittedCNAMEs have been specified, 0 otherwise.
2483  * Allowed to be called on non-final configuration.
2484  */
2485 int
2486 config_has_permitted_cnames(Options *options)
2487 {
2488 	if (options->num_permitted_cnames == 1 &&
2489 	    strcasecmp(options->permitted_cnames[0].source_list, "none") == 0 &&
2490 	    strcmp(options->permitted_cnames[0].target_list, "") == 0)
2491 		return 0;
2492 	return options->num_permitted_cnames > 0;
2493 }
2494 
2495 /*
2496  * Initializes options to special values that indicate that they have not yet
2497  * been set.  Read_config_file will only set options with this value. Options
2498  * are processed in the following order: command line, user config file,
2499  * system config file.  Last, fill_default_options is called.
2500  */
2501 
2502 void
2503 initialize_options(Options * options)
2504 {
2505 	memset(options, 'X', sizeof(*options));
2506 	options->host_arg = NULL;
2507 	options->forward_agent = -1;
2508 	options->forward_agent_sock_path = NULL;
2509 	options->forward_x11 = -1;
2510 	options->forward_x11_trusted = -1;
2511 	options->forward_x11_timeout = -1;
2512 	options->stdio_forward_host = NULL;
2513 	options->stdio_forward_port = 0;
2514 	options->clear_forwardings = -1;
2515 	options->exit_on_forward_failure = -1;
2516 	options->xauth_location = NULL;
2517 	options->fwd_opts.gateway_ports = -1;
2518 	options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
2519 	options->fwd_opts.streamlocal_bind_unlink = -1;
2520 	options->pubkey_authentication = -1;
2521 	options->gss_authentication = -1;
2522 	options->gss_deleg_creds = -1;
2523 	options->password_authentication = -1;
2524 	options->kbd_interactive_authentication = -1;
2525 	options->kbd_interactive_devices = NULL;
2526 	options->hostbased_authentication = -1;
2527 	options->batch_mode = -1;
2528 	options->check_host_ip = -1;
2529 	options->strict_host_key_checking = -1;
2530 	options->compression = -1;
2531 	options->tcp_keep_alive = -1;
2532 	options->port = -1;
2533 	options->address_family = -1;
2534 	options->connection_attempts = -1;
2535 	options->connection_timeout = -1;
2536 	options->number_of_password_prompts = -1;
2537 	options->ciphers = NULL;
2538 	options->macs = NULL;
2539 	options->kex_algorithms = NULL;
2540 	options->hostkeyalgorithms = NULL;
2541 	options->ca_sign_algorithms = NULL;
2542 	options->num_identity_files = 0;
2543 	memset(options->identity_keys, 0, sizeof(options->identity_keys));
2544 	options->num_certificate_files = 0;
2545 	memset(options->certificates, 0, sizeof(options->certificates));
2546 	options->hostname = NULL;
2547 	options->host_key_alias = NULL;
2548 	options->proxy_command = NULL;
2549 	options->jump_user = NULL;
2550 	options->jump_host = NULL;
2551 	options->jump_port = -1;
2552 	options->jump_extra = NULL;
2553 	options->user = NULL;
2554 	options->escape_char = -1;
2555 	options->num_system_hostfiles = 0;
2556 	options->num_user_hostfiles = 0;
2557 	options->local_forwards = NULL;
2558 	options->num_local_forwards = 0;
2559 	options->remote_forwards = NULL;
2560 	options->num_remote_forwards = 0;
2561 	options->permitted_remote_opens = NULL;
2562 	options->num_permitted_remote_opens = 0;
2563 	options->log_facility = SYSLOG_FACILITY_NOT_SET;
2564 	options->log_level = SYSLOG_LEVEL_NOT_SET;
2565 	options->num_log_verbose = 0;
2566 	options->log_verbose = NULL;
2567 	options->preferred_authentications = NULL;
2568 	options->bind_address = NULL;
2569 	options->bind_interface = NULL;
2570 	options->pkcs11_provider = NULL;
2571 	options->sk_provider = NULL;
2572 	options->enable_ssh_keysign = - 1;
2573 	options->no_host_authentication_for_localhost = - 1;
2574 	options->identities_only = - 1;
2575 	options->rekey_limit = - 1;
2576 	options->rekey_interval = -1;
2577 	options->verify_host_key_dns = -1;
2578 	options->server_alive_interval = -1;
2579 	options->server_alive_count_max = -1;
2580 	options->send_env = NULL;
2581 	options->num_send_env = 0;
2582 	options->setenv = NULL;
2583 	options->num_setenv = 0;
2584 	options->control_path = NULL;
2585 	options->control_master = -1;
2586 	options->control_persist = -1;
2587 	options->control_persist_timeout = 0;
2588 	options->hash_known_hosts = -1;
2589 	options->tun_open = -1;
2590 	options->tun_local = -1;
2591 	options->tun_remote = -1;
2592 	options->local_command = NULL;
2593 	options->permit_local_command = -1;
2594 	options->remote_command = NULL;
2595 	options->add_keys_to_agent = -1;
2596 	options->add_keys_to_agent_lifespan = -1;
2597 	options->identity_agent = NULL;
2598 	options->visual_host_key = -1;
2599 	options->ip_qos_interactive = -1;
2600 	options->ip_qos_bulk = -1;
2601 	options->request_tty = -1;
2602 	options->session_type = -1;
2603 	options->stdin_null = -1;
2604 	options->fork_after_authentication = -1;
2605 	options->proxy_use_fdpass = -1;
2606 	options->ignored_unknown = NULL;
2607 	options->num_canonical_domains = 0;
2608 	options->num_permitted_cnames = 0;
2609 	options->canonicalize_max_dots = -1;
2610 	options->canonicalize_fallback_local = -1;
2611 	options->canonicalize_hostname = -1;
2612 	options->revoked_host_keys = NULL;
2613 	options->fingerprint_hash = -1;
2614 	options->update_hostkeys = -1;
2615 	options->hostbased_accepted_algos = NULL;
2616 	options->pubkey_accepted_algos = NULL;
2617 	options->known_hosts_command = NULL;
2618 	options->required_rsa_size = -1;
2619 	options->enable_escape_commandline = -1;
2620 	options->obscure_keystroke_timing_interval = -1;
2621 	options->tag = NULL;
2622 	options->channel_timeouts = NULL;
2623 	options->num_channel_timeouts = 0;
2624 }
2625 
2626 /*
2627  * A petite version of fill_default_options() that just fills the options
2628  * needed for hostname canonicalization to proceed.
2629  */
2630 void
2631 fill_default_options_for_canonicalization(Options *options)
2632 {
2633 	if (options->canonicalize_max_dots == -1)
2634 		options->canonicalize_max_dots = 1;
2635 	if (options->canonicalize_fallback_local == -1)
2636 		options->canonicalize_fallback_local = 1;
2637 	if (options->canonicalize_hostname == -1)
2638 		options->canonicalize_hostname = SSH_CANONICALISE_NO;
2639 }
2640 
2641 /*
2642  * Called after processing other sources of option data, this fills those
2643  * options for which no value has been specified with their default values.
2644  */
2645 int
2646 fill_default_options(Options * options)
2647 {
2648 	char *all_cipher, *all_mac, *all_kex, *all_key, *all_sig;
2649 	char *def_cipher, *def_mac, *def_kex, *def_key, *def_sig;
2650 	int ret = 0, r;
2651 
2652 	if (options->forward_agent == -1)
2653 		options->forward_agent = 0;
2654 	if (options->forward_x11 == -1)
2655 		options->forward_x11 = 0;
2656 	if (options->forward_x11_trusted == -1)
2657 		options->forward_x11_trusted = 0;
2658 	if (options->forward_x11_timeout == -1)
2659 		options->forward_x11_timeout = 1200;
2660 	/*
2661 	 * stdio forwarding (-W) changes the default for these but we defer
2662 	 * setting the values so they can be overridden.
2663 	 */
2664 	if (options->exit_on_forward_failure == -1)
2665 		options->exit_on_forward_failure =
2666 		    options->stdio_forward_host != NULL ? 1 : 0;
2667 	if (options->clear_forwardings == -1)
2668 		options->clear_forwardings =
2669 		    options->stdio_forward_host != NULL ? 1 : 0;
2670 	if (options->clear_forwardings == 1)
2671 		clear_forwardings(options);
2672 
2673 	if (options->xauth_location == NULL)
2674 		options->xauth_location = xstrdup(_PATH_XAUTH);
2675 	if (options->fwd_opts.gateway_ports == -1)
2676 		options->fwd_opts.gateway_ports = 0;
2677 	if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
2678 		options->fwd_opts.streamlocal_bind_mask = 0177;
2679 	if (options->fwd_opts.streamlocal_bind_unlink == -1)
2680 		options->fwd_opts.streamlocal_bind_unlink = 0;
2681 	if (options->pubkey_authentication == -1)
2682 		options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL;
2683 	if (options->gss_authentication == -1)
2684 		options->gss_authentication = 0;
2685 	if (options->gss_deleg_creds == -1)
2686 		options->gss_deleg_creds = 0;
2687 	if (options->password_authentication == -1)
2688 		options->password_authentication = 1;
2689 	if (options->kbd_interactive_authentication == -1)
2690 		options->kbd_interactive_authentication = 1;
2691 	if (options->hostbased_authentication == -1)
2692 		options->hostbased_authentication = 0;
2693 	if (options->batch_mode == -1)
2694 		options->batch_mode = 0;
2695 	if (options->check_host_ip == -1)
2696 		options->check_host_ip = 0;
2697 	if (options->strict_host_key_checking == -1)
2698 		options->strict_host_key_checking = SSH_STRICT_HOSTKEY_ASK;
2699 	if (options->compression == -1)
2700 		options->compression = 0;
2701 	if (options->tcp_keep_alive == -1)
2702 		options->tcp_keep_alive = 1;
2703 	if (options->port == -1)
2704 		options->port = 0;	/* Filled in ssh_connect. */
2705 	if (options->address_family == -1)
2706 		options->address_family = AF_UNSPEC;
2707 	if (options->connection_attempts == -1)
2708 		options->connection_attempts = 1;
2709 	if (options->number_of_password_prompts == -1)
2710 		options->number_of_password_prompts = 3;
2711 	/* options->hostkeyalgorithms, default set in myproposals.h */
2712 	if (options->add_keys_to_agent == -1) {
2713 		options->add_keys_to_agent = 0;
2714 		options->add_keys_to_agent_lifespan = 0;
2715 	}
2716 	if (options->num_identity_files == 0) {
2717 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_RSA, 0);
2718 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_ECDSA, 0);
2719 		add_identity_file(options, "~/",
2720 		    _PATH_SSH_CLIENT_ID_ECDSA_SK, 0);
2721 		add_identity_file(options, "~/",
2722 		    _PATH_SSH_CLIENT_ID_ED25519, 0);
2723 		add_identity_file(options, "~/",
2724 		    _PATH_SSH_CLIENT_ID_ED25519_SK, 0);
2725 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_XMSS, 0);
2726 #ifdef WITH_DSA
2727 		add_identity_file(options, "~/", _PATH_SSH_CLIENT_ID_DSA, 0);
2728 #endif
2729 	}
2730 	if (options->escape_char == -1)
2731 		options->escape_char = '~';
2732 	if (options->num_system_hostfiles == 0) {
2733 		options->system_hostfiles[options->num_system_hostfiles++] =
2734 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
2735 		options->system_hostfiles[options->num_system_hostfiles++] =
2736 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
2737 	}
2738 	if (options->update_hostkeys == -1) {
2739 		if (options->verify_host_key_dns <= 0 &&
2740 		    (options->num_user_hostfiles == 0 ||
2741 		    (options->num_user_hostfiles == 1 && strcmp(options->
2742 		    user_hostfiles[0], _PATH_SSH_USER_HOSTFILE) == 0)))
2743 			options->update_hostkeys = SSH_UPDATE_HOSTKEYS_YES;
2744 		else
2745 			options->update_hostkeys = SSH_UPDATE_HOSTKEYS_NO;
2746 	}
2747 	if (options->num_user_hostfiles == 0) {
2748 		options->user_hostfiles[options->num_user_hostfiles++] =
2749 		    xstrdup(_PATH_SSH_USER_HOSTFILE);
2750 		options->user_hostfiles[options->num_user_hostfiles++] =
2751 		    xstrdup(_PATH_SSH_USER_HOSTFILE2);
2752 	}
2753 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
2754 		options->log_level = SYSLOG_LEVEL_INFO;
2755 	if (options->log_facility == SYSLOG_FACILITY_NOT_SET)
2756 		options->log_facility = SYSLOG_FACILITY_USER;
2757 	if (options->no_host_authentication_for_localhost == - 1)
2758 		options->no_host_authentication_for_localhost = 0;
2759 	if (options->identities_only == -1)
2760 		options->identities_only = 0;
2761 	if (options->enable_ssh_keysign == -1)
2762 		options->enable_ssh_keysign = 0;
2763 	if (options->rekey_limit == -1)
2764 		options->rekey_limit = 0;
2765 	if (options->rekey_interval == -1)
2766 		options->rekey_interval = 0;
2767 	if (options->verify_host_key_dns == -1)
2768 		options->verify_host_key_dns = 0;
2769 	if (options->server_alive_interval == -1)
2770 		options->server_alive_interval = 0;
2771 	if (options->server_alive_count_max == -1)
2772 		options->server_alive_count_max = 3;
2773 	if (options->control_master == -1)
2774 		options->control_master = 0;
2775 	if (options->control_persist == -1) {
2776 		options->control_persist = 0;
2777 		options->control_persist_timeout = 0;
2778 	}
2779 	if (options->hash_known_hosts == -1)
2780 		options->hash_known_hosts = 0;
2781 	if (options->tun_open == -1)
2782 		options->tun_open = SSH_TUNMODE_NO;
2783 	if (options->tun_local == -1)
2784 		options->tun_local = SSH_TUNID_ANY;
2785 	if (options->tun_remote == -1)
2786 		options->tun_remote = SSH_TUNID_ANY;
2787 	if (options->permit_local_command == -1)
2788 		options->permit_local_command = 0;
2789 	if (options->visual_host_key == -1)
2790 		options->visual_host_key = 0;
2791 	if (options->ip_qos_interactive == -1)
2792 		options->ip_qos_interactive = IPTOS_DSCP_AF21;
2793 	if (options->ip_qos_bulk == -1)
2794 		options->ip_qos_bulk = IPTOS_DSCP_CS1;
2795 	if (options->request_tty == -1)
2796 		options->request_tty = REQUEST_TTY_AUTO;
2797 	if (options->session_type == -1)
2798 		options->session_type = SESSION_TYPE_DEFAULT;
2799 	if (options->stdin_null == -1)
2800 		options->stdin_null = 0;
2801 	if (options->fork_after_authentication == -1)
2802 		options->fork_after_authentication = 0;
2803 	if (options->proxy_use_fdpass == -1)
2804 		options->proxy_use_fdpass = 0;
2805 	if (options->canonicalize_max_dots == -1)
2806 		options->canonicalize_max_dots = 1;
2807 	if (options->canonicalize_fallback_local == -1)
2808 		options->canonicalize_fallback_local = 1;
2809 	if (options->canonicalize_hostname == -1)
2810 		options->canonicalize_hostname = SSH_CANONICALISE_NO;
2811 	if (options->fingerprint_hash == -1)
2812 		options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
2813 	if (options->sk_provider == NULL)
2814 		options->sk_provider = xstrdup("internal");
2815 	if (options->required_rsa_size == -1)
2816 		options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
2817 	if (options->enable_escape_commandline == -1)
2818 		options->enable_escape_commandline = 0;
2819 	if (options->obscure_keystroke_timing_interval == -1) {
2820 		options->obscure_keystroke_timing_interval =
2821 		    SSH_KEYSTROKE_DEFAULT_INTERVAL_MS;
2822 	}
2823 
2824 	/* Expand KEX name lists */
2825 	all_cipher = cipher_alg_list(',', 0);
2826 	all_mac = mac_alg_list(',');
2827 	all_kex = kex_alg_list(',');
2828 	all_key = sshkey_alg_list(0, 0, 1, ',');
2829 	all_sig = sshkey_alg_list(0, 1, 1, ',');
2830 	/* remove unsupported algos from default lists */
2831 	def_cipher = match_filter_allowlist(KEX_CLIENT_ENCRYPT, all_cipher);
2832 	def_mac = match_filter_allowlist(KEX_CLIENT_MAC, all_mac);
2833 	def_kex = match_filter_allowlist(KEX_CLIENT_KEX, all_kex);
2834 	def_key = match_filter_allowlist(KEX_DEFAULT_PK_ALG, all_key);
2835 	def_sig = match_filter_allowlist(SSH_ALLOWED_CA_SIGALGS, all_sig);
2836 #define ASSEMBLE(what, defaults, all) \
2837 	do { \
2838 		if ((r = kex_assemble_names(&options->what, \
2839 		    defaults, all)) != 0) { \
2840 			error_fr(r, "%s", #what); \
2841 			goto fail; \
2842 		} \
2843 	} while (0)
2844 	ASSEMBLE(ciphers, def_cipher, all_cipher);
2845 	ASSEMBLE(macs, def_mac, all_mac);
2846 	ASSEMBLE(kex_algorithms, def_kex, all_kex);
2847 	ASSEMBLE(hostbased_accepted_algos, def_key, all_key);
2848 	ASSEMBLE(pubkey_accepted_algos, def_key, all_key);
2849 	ASSEMBLE(ca_sign_algorithms, def_sig, all_sig);
2850 #undef ASSEMBLE
2851 
2852 #define CLEAR_ON_NONE(v) \
2853 	do { \
2854 		if (option_clear_or_none(v)) { \
2855 			free(v); \
2856 			v = NULL; \
2857 		} \
2858 	} while(0)
2859 #define CLEAR_ON_NONE_ARRAY(v, nv, none) \
2860 	do { \
2861 		if (options->nv == 1 && \
2862 		    strcasecmp(options->v[0], none) == 0) { \
2863 			free(options->v[0]); \
2864 			free(options->v); \
2865 			options->v = NULL; \
2866 			options->nv = 0; \
2867 		} \
2868 	} while (0)
2869 	CLEAR_ON_NONE(options->local_command);
2870 	CLEAR_ON_NONE(options->remote_command);
2871 	CLEAR_ON_NONE(options->proxy_command);
2872 	CLEAR_ON_NONE(options->control_path);
2873 	CLEAR_ON_NONE(options->revoked_host_keys);
2874 	CLEAR_ON_NONE(options->pkcs11_provider);
2875 	CLEAR_ON_NONE(options->sk_provider);
2876 	CLEAR_ON_NONE(options->known_hosts_command);
2877 	CLEAR_ON_NONE_ARRAY(channel_timeouts, num_channel_timeouts, "none");
2878 #undef CLEAR_ON_NONE
2879 #undef CLEAR_ON_NONE_ARRAY
2880 	if (options->jump_host != NULL &&
2881 	    strcmp(options->jump_host, "none") == 0 &&
2882 	    options->jump_port == 0 && options->jump_user == NULL) {
2883 		free(options->jump_host);
2884 		options->jump_host = NULL;
2885 	}
2886 	if (options->num_permitted_cnames == 1 &&
2887 	    !config_has_permitted_cnames(options)) {
2888 		/* clean up CanonicalizePermittedCNAMEs=none */
2889 		free(options->permitted_cnames[0].source_list);
2890 		free(options->permitted_cnames[0].target_list);
2891 		memset(options->permitted_cnames, '\0',
2892 		    sizeof(*options->permitted_cnames));
2893 		options->num_permitted_cnames = 0;
2894 	}
2895 	/* options->identity_agent distinguishes NULL from 'none' */
2896 	/* options->user will be set in the main program if appropriate */
2897 	/* options->hostname will be set in the main program if appropriate */
2898 	/* options->host_key_alias should not be set by default */
2899 	/* options->preferred_authentications will be set in ssh */
2900 
2901 	/* success */
2902 	ret = 0;
2903  fail:
2904 	free(all_cipher);
2905 	free(all_mac);
2906 	free(all_kex);
2907 	free(all_key);
2908 	free(all_sig);
2909 	free(def_cipher);
2910 	free(def_mac);
2911 	free(def_kex);
2912 	free(def_key);
2913 	free(def_sig);
2914 	return ret;
2915 }
2916 
2917 void
2918 free_options(Options *o)
2919 {
2920 	int i;
2921 
2922 	if (o == NULL)
2923 		return;
2924 
2925 #define FREE_ARRAY(type, n, a) \
2926 	do { \
2927 		type _i; \
2928 		for (_i = 0; _i < (n); _i++) \
2929 			free((a)[_i]); \
2930 	} while (0)
2931 
2932 	free(o->forward_agent_sock_path);
2933 	free(o->xauth_location);
2934 	FREE_ARRAY(u_int, o->num_log_verbose, o->log_verbose);
2935 	free(o->log_verbose);
2936 	free(o->ciphers);
2937 	free(o->macs);
2938 	free(o->hostkeyalgorithms);
2939 	free(o->kex_algorithms);
2940 	free(o->ca_sign_algorithms);
2941 	free(o->hostname);
2942 	free(o->host_key_alias);
2943 	free(o->proxy_command);
2944 	free(o->user);
2945 	FREE_ARRAY(u_int, o->num_system_hostfiles, o->system_hostfiles);
2946 	FREE_ARRAY(u_int, o->num_user_hostfiles, o->user_hostfiles);
2947 	free(o->preferred_authentications);
2948 	free(o->bind_address);
2949 	free(o->bind_interface);
2950 	free(o->pkcs11_provider);
2951 	free(o->sk_provider);
2952 	for (i = 0; i < o->num_identity_files; i++) {
2953 		free(o->identity_files[i]);
2954 		sshkey_free(o->identity_keys[i]);
2955 	}
2956 	for (i = 0; i < o->num_certificate_files; i++) {
2957 		free(o->certificate_files[i]);
2958 		sshkey_free(o->certificates[i]);
2959 	}
2960 	free(o->identity_agent);
2961 	for (i = 0; i < o->num_local_forwards; i++) {
2962 		free(o->local_forwards[i].listen_host);
2963 		free(o->local_forwards[i].listen_path);
2964 		free(o->local_forwards[i].connect_host);
2965 		free(o->local_forwards[i].connect_path);
2966 	}
2967 	free(o->local_forwards);
2968 	for (i = 0; i < o->num_remote_forwards; i++) {
2969 		free(o->remote_forwards[i].listen_host);
2970 		free(o->remote_forwards[i].listen_path);
2971 		free(o->remote_forwards[i].connect_host);
2972 		free(o->remote_forwards[i].connect_path);
2973 	}
2974 	free(o->remote_forwards);
2975 	free(o->stdio_forward_host);
2976 	FREE_ARRAY(u_int, o->num_send_env, o->send_env);
2977 	free(o->send_env);
2978 	FREE_ARRAY(u_int, o->num_setenv, o->setenv);
2979 	free(o->setenv);
2980 	free(o->control_path);
2981 	free(o->local_command);
2982 	free(o->remote_command);
2983 	FREE_ARRAY(int, o->num_canonical_domains, o->canonical_domains);
2984 	for (i = 0; i < o->num_permitted_cnames; i++) {
2985 		free(o->permitted_cnames[i].source_list);
2986 		free(o->permitted_cnames[i].target_list);
2987 	}
2988 	free(o->revoked_host_keys);
2989 	free(o->hostbased_accepted_algos);
2990 	free(o->pubkey_accepted_algos);
2991 	free(o->jump_user);
2992 	free(o->jump_host);
2993 	free(o->jump_extra);
2994 	free(o->ignored_unknown);
2995 	explicit_bzero(o, sizeof(*o));
2996 #undef FREE_ARRAY
2997 }
2998 
2999 struct fwdarg {
3000 	char *arg;
3001 	int ispath;
3002 };
3003 
3004 /*
3005  * parse_fwd_field
3006  * parses the next field in a port forwarding specification.
3007  * sets fwd to the parsed field and advances p past the colon
3008  * or sets it to NULL at end of string.
3009  * returns 0 on success, else non-zero.
3010  */
3011 static int
3012 parse_fwd_field(char **p, struct fwdarg *fwd)
3013 {
3014 	char *ep, *cp = *p;
3015 	int ispath = 0;
3016 
3017 	if (*cp == '\0') {
3018 		*p = NULL;
3019 		return -1;	/* end of string */
3020 	}
3021 
3022 	/*
3023 	 * A field escaped with square brackets is used literally.
3024 	 * XXX - allow ']' to be escaped via backslash?
3025 	 */
3026 	if (*cp == '[') {
3027 		/* find matching ']' */
3028 		for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
3029 			if (*ep == '/')
3030 				ispath = 1;
3031 		}
3032 		/* no matching ']' or not at end of field. */
3033 		if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
3034 			return -1;
3035 		/* NUL terminate the field and advance p past the colon */
3036 		*ep++ = '\0';
3037 		if (*ep != '\0')
3038 			*ep++ = '\0';
3039 		fwd->arg = cp + 1;
3040 		fwd->ispath = ispath;
3041 		*p = ep;
3042 		return 0;
3043 	}
3044 
3045 	for (cp = *p; *cp != '\0'; cp++) {
3046 		switch (*cp) {
3047 		case '\\':
3048 			memmove(cp, cp + 1, strlen(cp + 1) + 1);
3049 			if (*cp == '\0')
3050 				return -1;
3051 			break;
3052 		case '/':
3053 			ispath = 1;
3054 			break;
3055 		case ':':
3056 			*cp++ = '\0';
3057 			goto done;
3058 		}
3059 	}
3060 done:
3061 	fwd->arg = *p;
3062 	fwd->ispath = ispath;
3063 	*p = cp;
3064 	return 0;
3065 }
3066 
3067 /*
3068  * parse_forward
3069  * parses a string containing a port forwarding specification of the form:
3070  *   dynamicfwd == 0
3071  *	[listenhost:]listenport|listenpath:connecthost:connectport|connectpath
3072  *	listenpath:connectpath
3073  *   dynamicfwd == 1
3074  *	[listenhost:]listenport
3075  * returns number of arguments parsed or zero on error
3076  */
3077 int
3078 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
3079 {
3080 	struct fwdarg fwdargs[4];
3081 	char *p, *cp;
3082 	int i, err;
3083 
3084 	memset(fwd, 0, sizeof(*fwd));
3085 	memset(fwdargs, 0, sizeof(fwdargs));
3086 
3087 	/*
3088 	 * We expand environment variables before checking if we think they're
3089 	 * paths so that if ${VAR} expands to a fully qualified path it is
3090 	 * treated as a path.
3091 	 */
3092 	cp = p = dollar_expand(&err, fwdspec);
3093 	if (p == NULL || err)
3094 		return 0;
3095 
3096 	/* skip leading spaces */
3097 	while (isspace((u_char)*cp))
3098 		cp++;
3099 
3100 	for (i = 0; i < 4; ++i) {
3101 		if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
3102 			break;
3103 	}
3104 
3105 	/* Check for trailing garbage */
3106 	if (cp != NULL && *cp != '\0') {
3107 		i = 0;	/* failure */
3108 	}
3109 
3110 	switch (i) {
3111 	case 1:
3112 		if (fwdargs[0].ispath) {
3113 			fwd->listen_path = xstrdup(fwdargs[0].arg);
3114 			fwd->listen_port = PORT_STREAMLOCAL;
3115 		} else {
3116 			fwd->listen_host = NULL;
3117 			fwd->listen_port = a2port(fwdargs[0].arg);
3118 		}
3119 		fwd->connect_host = xstrdup("socks");
3120 		break;
3121 
3122 	case 2:
3123 		if (fwdargs[0].ispath && fwdargs[1].ispath) {
3124 			fwd->listen_path = xstrdup(fwdargs[0].arg);
3125 			fwd->listen_port = PORT_STREAMLOCAL;
3126 			fwd->connect_path = xstrdup(fwdargs[1].arg);
3127 			fwd->connect_port = PORT_STREAMLOCAL;
3128 		} else if (fwdargs[1].ispath) {
3129 			fwd->listen_host = NULL;
3130 			fwd->listen_port = a2port(fwdargs[0].arg);
3131 			fwd->connect_path = xstrdup(fwdargs[1].arg);
3132 			fwd->connect_port = PORT_STREAMLOCAL;
3133 		} else {
3134 			fwd->listen_host = xstrdup(fwdargs[0].arg);
3135 			fwd->listen_port = a2port(fwdargs[1].arg);
3136 			fwd->connect_host = xstrdup("socks");
3137 		}
3138 		break;
3139 
3140 	case 3:
3141 		if (fwdargs[0].ispath) {
3142 			fwd->listen_path = xstrdup(fwdargs[0].arg);
3143 			fwd->listen_port = PORT_STREAMLOCAL;
3144 			fwd->connect_host = xstrdup(fwdargs[1].arg);
3145 			fwd->connect_port = a2port(fwdargs[2].arg);
3146 		} else if (fwdargs[2].ispath) {
3147 			fwd->listen_host = xstrdup(fwdargs[0].arg);
3148 			fwd->listen_port = a2port(fwdargs[1].arg);
3149 			fwd->connect_path = xstrdup(fwdargs[2].arg);
3150 			fwd->connect_port = PORT_STREAMLOCAL;
3151 		} else {
3152 			fwd->listen_host = NULL;
3153 			fwd->listen_port = a2port(fwdargs[0].arg);
3154 			fwd->connect_host = xstrdup(fwdargs[1].arg);
3155 			fwd->connect_port = a2port(fwdargs[2].arg);
3156 		}
3157 		break;
3158 
3159 	case 4:
3160 		fwd->listen_host = xstrdup(fwdargs[0].arg);
3161 		fwd->listen_port = a2port(fwdargs[1].arg);
3162 		fwd->connect_host = xstrdup(fwdargs[2].arg);
3163 		fwd->connect_port = a2port(fwdargs[3].arg);
3164 		break;
3165 	default:
3166 		i = 0; /* failure */
3167 	}
3168 
3169 	free(p);
3170 
3171 	if (dynamicfwd) {
3172 		if (!(i == 1 || i == 2))
3173 			goto fail_free;
3174 	} else {
3175 		if (!(i == 3 || i == 4)) {
3176 			if (fwd->connect_path == NULL &&
3177 			    fwd->listen_path == NULL)
3178 				goto fail_free;
3179 		}
3180 		if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
3181 			goto fail_free;
3182 	}
3183 
3184 	if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
3185 	    (!remotefwd && fwd->listen_port == 0))
3186 		goto fail_free;
3187 	if (fwd->connect_host != NULL &&
3188 	    strlen(fwd->connect_host) >= NI_MAXHOST)
3189 		goto fail_free;
3190 	/*
3191 	 * XXX - if connecting to a remote socket, max sun len may not
3192 	 * match this host
3193 	 */
3194 	if (fwd->connect_path != NULL &&
3195 	    strlen(fwd->connect_path) >= PATH_MAX_SUN)
3196 		goto fail_free;
3197 	if (fwd->listen_host != NULL &&
3198 	    strlen(fwd->listen_host) >= NI_MAXHOST)
3199 		goto fail_free;
3200 	if (fwd->listen_path != NULL &&
3201 	    strlen(fwd->listen_path) >= PATH_MAX_SUN)
3202 		goto fail_free;
3203 
3204 	return (i);
3205 
3206  fail_free:
3207 	free(fwd->connect_host);
3208 	fwd->connect_host = NULL;
3209 	free(fwd->connect_path);
3210 	fwd->connect_path = NULL;
3211 	free(fwd->listen_host);
3212 	fwd->listen_host = NULL;
3213 	free(fwd->listen_path);
3214 	fwd->listen_path = NULL;
3215 	return (0);
3216 }
3217 
3218 int
3219 parse_jump(const char *s, Options *o, int active)
3220 {
3221 	char *orig, *sdup, *cp;
3222 	char *host = NULL, *user = NULL;
3223 	int r, ret = -1, port = -1, first;
3224 
3225 	active &= o->proxy_command == NULL && o->jump_host == NULL;
3226 
3227 	orig = sdup = xstrdup(s);
3228 
3229 	/* Remove comment and trailing whitespace */
3230 	if ((cp = strchr(orig, '#')) != NULL)
3231 		*cp = '\0';
3232 	rtrim(orig);
3233 
3234 	first = active;
3235 	do {
3236 		if (strcasecmp(s, "none") == 0)
3237 			break;
3238 		if ((cp = strrchr(sdup, ',')) == NULL)
3239 			cp = sdup; /* last */
3240 		else
3241 			*cp++ = '\0';
3242 
3243 		if (first) {
3244 			/* First argument and configuration is active */
3245 			r = parse_ssh_uri(cp, &user, &host, &port);
3246 			if (r == -1 || (r == 1 &&
3247 			    parse_user_host_port(cp, &user, &host, &port) != 0))
3248 				goto out;
3249 		} else {
3250 			/* Subsequent argument or inactive configuration */
3251 			r = parse_ssh_uri(cp, NULL, NULL, NULL);
3252 			if (r == -1 || (r == 1 &&
3253 			    parse_user_host_port(cp, NULL, NULL, NULL) != 0))
3254 				goto out;
3255 		}
3256 		first = 0; /* only check syntax for subsequent hosts */
3257 	} while (cp != sdup);
3258 	/* success */
3259 	if (active) {
3260 		if (strcasecmp(s, "none") == 0) {
3261 			o->jump_host = xstrdup("none");
3262 			o->jump_port = 0;
3263 		} else {
3264 			o->jump_user = user;
3265 			o->jump_host = host;
3266 			o->jump_port = port;
3267 			o->proxy_command = xstrdup("none");
3268 			user = host = NULL;
3269 			if ((cp = strrchr(s, ',')) != NULL && cp != s) {
3270 				o->jump_extra = xstrdup(s);
3271 				o->jump_extra[cp - s] = '\0';
3272 			}
3273 		}
3274 	}
3275 	ret = 0;
3276  out:
3277 	free(orig);
3278 	free(user);
3279 	free(host);
3280 	return ret;
3281 }
3282 
3283 int
3284 parse_ssh_uri(const char *uri, char **userp, char **hostp, int *portp)
3285 {
3286 	char *user = NULL, *host = NULL, *path = NULL;
3287 	int r, port;
3288 
3289 	r = parse_uri("ssh", uri, &user, &host, &port, &path);
3290 	if (r == 0 && path != NULL)
3291 		r = -1;		/* path not allowed */
3292 	if (r == 0) {
3293 		if (userp != NULL) {
3294 			*userp = user;
3295 			user = NULL;
3296 		}
3297 		if (hostp != NULL) {
3298 			*hostp = host;
3299 			host = NULL;
3300 		}
3301 		if (portp != NULL)
3302 			*portp = port;
3303 	}
3304 	free(user);
3305 	free(host);
3306 	free(path);
3307 	return r;
3308 }
3309 
3310 /* XXX the following is a near-verbatim copy from servconf.c; refactor */
3311 static const char *
3312 fmt_multistate_int(int val, const struct multistate *m)
3313 {
3314 	u_int i;
3315 
3316 	for (i = 0; m[i].key != NULL; i++) {
3317 		if (m[i].value == val)
3318 			return m[i].key;
3319 	}
3320 	return "UNKNOWN";
3321 }
3322 
3323 static const char *
3324 fmt_intarg(OpCodes code, int val)
3325 {
3326 	if (val == -1)
3327 		return "unset";
3328 	switch (code) {
3329 	case oAddressFamily:
3330 		return fmt_multistate_int(val, multistate_addressfamily);
3331 	case oVerifyHostKeyDNS:
3332 	case oUpdateHostkeys:
3333 		return fmt_multistate_int(val, multistate_yesnoask);
3334 	case oStrictHostKeyChecking:
3335 		return fmt_multistate_int(val, multistate_strict_hostkey);
3336 	case oControlMaster:
3337 		return fmt_multistate_int(val, multistate_controlmaster);
3338 	case oTunnel:
3339 		return fmt_multistate_int(val, multistate_tunnel);
3340 	case oRequestTTY:
3341 		return fmt_multistate_int(val, multistate_requesttty);
3342 	case oSessionType:
3343 		return fmt_multistate_int(val, multistate_sessiontype);
3344 	case oCanonicalizeHostname:
3345 		return fmt_multistate_int(val, multistate_canonicalizehostname);
3346 	case oAddKeysToAgent:
3347 		return fmt_multistate_int(val, multistate_yesnoaskconfirm);
3348 	case oPubkeyAuthentication:
3349 		return fmt_multistate_int(val, multistate_pubkey_auth);
3350 	case oFingerprintHash:
3351 		return ssh_digest_alg_name(val);
3352 	default:
3353 		switch (val) {
3354 		case 0:
3355 			return "no";
3356 		case 1:
3357 			return "yes";
3358 		default:
3359 			return "UNKNOWN";
3360 		}
3361 	}
3362 }
3363 
3364 static const char *
3365 lookup_opcode_name(OpCodes code)
3366 {
3367 	u_int i;
3368 
3369 	for (i = 0; keywords[i].name != NULL; i++)
3370 		if (keywords[i].opcode == code)
3371 			return(keywords[i].name);
3372 	return "UNKNOWN";
3373 }
3374 
3375 static void
3376 dump_cfg_int(OpCodes code, int val)
3377 {
3378 	if (code == oObscureKeystrokeTiming) {
3379 		if (val == 0) {
3380 			printf("%s no\n", lookup_opcode_name(code));
3381 			return;
3382 		} else if (val == SSH_KEYSTROKE_DEFAULT_INTERVAL_MS) {
3383 			printf("%s yes\n", lookup_opcode_name(code));
3384 			return;
3385 		}
3386 		/* FALLTHROUGH */
3387 	}
3388 	printf("%s %d\n", lookup_opcode_name(code), val);
3389 }
3390 
3391 static void
3392 dump_cfg_fmtint(OpCodes code, int val)
3393 {
3394 	printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
3395 }
3396 
3397 static void
3398 dump_cfg_string(OpCodes code, const char *val)
3399 {
3400 	if (val == NULL)
3401 		return;
3402 	printf("%s %s\n", lookup_opcode_name(code), val);
3403 }
3404 
3405 static void
3406 dump_cfg_strarray(OpCodes code, u_int count, char **vals)
3407 {
3408 	u_int i;
3409 
3410 	for (i = 0; i < count; i++)
3411 		printf("%s %s\n", lookup_opcode_name(code), vals[i]);
3412 }
3413 
3414 static void
3415 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
3416 {
3417 	u_int i;
3418 
3419 	printf("%s", lookup_opcode_name(code));
3420 	if (count == 0)
3421 		printf(" none");
3422 	for (i = 0; i < count; i++)
3423 		printf(" %s",  vals[i]);
3424 	printf("\n");
3425 }
3426 
3427 static void
3428 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
3429 {
3430 	const struct Forward *fwd;
3431 	u_int i;
3432 
3433 	/* oDynamicForward */
3434 	for (i = 0; i < count; i++) {
3435 		fwd = &fwds[i];
3436 		if (code == oDynamicForward && fwd->connect_host != NULL &&
3437 		    strcmp(fwd->connect_host, "socks") != 0)
3438 			continue;
3439 		if (code == oLocalForward && fwd->connect_host != NULL &&
3440 		    strcmp(fwd->connect_host, "socks") == 0)
3441 			continue;
3442 		printf("%s", lookup_opcode_name(code));
3443 		if (fwd->listen_port == PORT_STREAMLOCAL)
3444 			printf(" %s", fwd->listen_path);
3445 		else if (fwd->listen_host == NULL)
3446 			printf(" %d", fwd->listen_port);
3447 		else {
3448 			printf(" [%s]:%d",
3449 			    fwd->listen_host, fwd->listen_port);
3450 		}
3451 		if (code != oDynamicForward) {
3452 			if (fwd->connect_port == PORT_STREAMLOCAL)
3453 				printf(" %s", fwd->connect_path);
3454 			else if (fwd->connect_host == NULL)
3455 				printf(" %d", fwd->connect_port);
3456 			else {
3457 				printf(" [%s]:%d",
3458 				    fwd->connect_host, fwd->connect_port);
3459 			}
3460 		}
3461 		printf("\n");
3462 	}
3463 }
3464 
3465 void
3466 dump_client_config(Options *o, const char *host)
3467 {
3468 	int i, r;
3469 	char buf[8], *all_key;
3470 
3471 	/*
3472 	 * Expand HostKeyAlgorithms name lists. This isn't handled in
3473 	 * fill_default_options() like the other algorithm lists because
3474 	 * the host key algorithms are by default dynamically chosen based
3475 	 * on the host's keys found in known_hosts.
3476 	 */
3477 	all_key = sshkey_alg_list(0, 0, 1, ',');
3478 	if ((r = kex_assemble_names(&o->hostkeyalgorithms, kex_default_pk_alg(),
3479 	    all_key)) != 0)
3480 		fatal_fr(r, "expand HostKeyAlgorithms");
3481 	free(all_key);
3482 
3483 	/* Most interesting options first: user, host, port */
3484 	dump_cfg_string(oHost, o->host_arg);
3485 	dump_cfg_string(oUser, o->user);
3486 	dump_cfg_string(oHostname, host);
3487 	dump_cfg_int(oPort, o->port);
3488 
3489 	/* Flag options */
3490 	dump_cfg_fmtint(oAddressFamily, o->address_family);
3491 	dump_cfg_fmtint(oBatchMode, o->batch_mode);
3492 	dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
3493 	dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
3494 	dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
3495 	dump_cfg_fmtint(oCompression, o->compression);
3496 	dump_cfg_fmtint(oControlMaster, o->control_master);
3497 	dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
3498 	dump_cfg_fmtint(oClearAllForwardings, o->clear_forwardings);
3499 	dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
3500 	dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
3501 	dump_cfg_fmtint(oForwardX11, o->forward_x11);
3502 	dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
3503 	dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
3504 #ifdef GSSAPI
3505 	dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
3506 	dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
3507 #endif /* GSSAPI */
3508 	dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
3509 	dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
3510 	dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
3511 	dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
3512 	dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
3513 	dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
3514 	dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
3515 	dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
3516 	dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
3517 	dump_cfg_fmtint(oRequestTTY, o->request_tty);
3518 	dump_cfg_fmtint(oSessionType, o->session_type);
3519 	dump_cfg_fmtint(oStdinNull, o->stdin_null);
3520 	dump_cfg_fmtint(oForkAfterAuthentication, o->fork_after_authentication);
3521 	dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
3522 	dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
3523 	dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
3524 	dump_cfg_fmtint(oTunnel, o->tun_open);
3525 	dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
3526 	dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
3527 	dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
3528 	dump_cfg_fmtint(oEnableEscapeCommandline, o->enable_escape_commandline);
3529 
3530 	/* Integer options */
3531 	dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
3532 	dump_cfg_int(oConnectionAttempts, o->connection_attempts);
3533 	dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
3534 	dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
3535 	dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
3536 	dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
3537 	dump_cfg_int(oRequiredRSASize, o->required_rsa_size);
3538 	dump_cfg_int(oObscureKeystrokeTiming,
3539 	    o->obscure_keystroke_timing_interval);
3540 
3541 	/* String options */
3542 	dump_cfg_string(oBindAddress, o->bind_address);
3543 	dump_cfg_string(oBindInterface, o->bind_interface);
3544 	dump_cfg_string(oCiphers, o->ciphers);
3545 	dump_cfg_string(oControlPath, o->control_path);
3546 	dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms);
3547 	dump_cfg_string(oHostKeyAlias, o->host_key_alias);
3548 	dump_cfg_string(oHostbasedAcceptedAlgorithms, o->hostbased_accepted_algos);
3549 	dump_cfg_string(oIdentityAgent, o->identity_agent);
3550 	dump_cfg_string(oIgnoreUnknown, o->ignored_unknown);
3551 	dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
3552 	dump_cfg_string(oKexAlgorithms, o->kex_algorithms);
3553 	dump_cfg_string(oCASignatureAlgorithms, o->ca_sign_algorithms);
3554 	dump_cfg_string(oLocalCommand, o->local_command);
3555 	dump_cfg_string(oRemoteCommand, o->remote_command);
3556 	dump_cfg_string(oLogLevel, log_level_name(o->log_level));
3557 	dump_cfg_string(oMacs, o->macs);
3558 #ifdef ENABLE_PKCS11
3559 	dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
3560 #endif
3561 	dump_cfg_string(oSecurityKeyProvider, o->sk_provider);
3562 	dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
3563 	dump_cfg_string(oPubkeyAcceptedAlgorithms, o->pubkey_accepted_algos);
3564 	dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
3565 	dump_cfg_string(oXAuthLocation, o->xauth_location);
3566 	dump_cfg_string(oKnownHostsCommand, o->known_hosts_command);
3567 	dump_cfg_string(oTag, o->tag);
3568 
3569 	/* Forwards */
3570 	dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
3571 	dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
3572 	dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
3573 
3574 	/* String array options */
3575 	dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
3576 	dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
3577 	dump_cfg_strarray(oCertificateFile, o->num_certificate_files, o->certificate_files);
3578 	dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
3579 	dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
3580 	dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
3581 	dump_cfg_strarray(oSetEnv, o->num_setenv, o->setenv);
3582 	dump_cfg_strarray_oneline(oLogVerbose,
3583 	    o->num_log_verbose, o->log_verbose);
3584 	dump_cfg_strarray_oneline(oChannelTimeout,
3585 	    o->num_channel_timeouts, o->channel_timeouts);
3586 
3587 	/* Special cases */
3588 
3589 	/* PermitRemoteOpen */
3590 	if (o->num_permitted_remote_opens == 0)
3591 		printf("%s any\n", lookup_opcode_name(oPermitRemoteOpen));
3592 	else
3593 		dump_cfg_strarray_oneline(oPermitRemoteOpen,
3594 		    o->num_permitted_remote_opens, o->permitted_remote_opens);
3595 
3596 	/* AddKeysToAgent */
3597 	if (o->add_keys_to_agent_lifespan <= 0)
3598 		dump_cfg_fmtint(oAddKeysToAgent, o->add_keys_to_agent);
3599 	else {
3600 		printf("addkeystoagent%s %d\n",
3601 		    o->add_keys_to_agent == 3 ? " confirm" : "",
3602 		    o->add_keys_to_agent_lifespan);
3603 	}
3604 
3605 	/* oForwardAgent */
3606 	if (o->forward_agent_sock_path == NULL)
3607 		dump_cfg_fmtint(oForwardAgent, o->forward_agent);
3608 	else
3609 		dump_cfg_string(oForwardAgent, o->forward_agent_sock_path);
3610 
3611 	/* oConnectTimeout */
3612 	if (o->connection_timeout == -1)
3613 		printf("connecttimeout none\n");
3614 	else
3615 		dump_cfg_int(oConnectTimeout, o->connection_timeout);
3616 
3617 	/* oTunnelDevice */
3618 	printf("tunneldevice");
3619 	if (o->tun_local == SSH_TUNID_ANY)
3620 		printf(" any");
3621 	else
3622 		printf(" %d", o->tun_local);
3623 	if (o->tun_remote == SSH_TUNID_ANY)
3624 		printf(":any");
3625 	else
3626 		printf(":%d", o->tun_remote);
3627 	printf("\n");
3628 
3629 	/* oCanonicalizePermittedCNAMEs */
3630 	printf("canonicalizePermittedcnames");
3631 	if (o->num_permitted_cnames == 0)
3632 		printf(" none");
3633 	for (i = 0; i < o->num_permitted_cnames; i++) {
3634 		printf(" %s:%s", o->permitted_cnames[i].source_list,
3635 		    o->permitted_cnames[i].target_list);
3636 	}
3637 	printf("\n");
3638 
3639 	/* oControlPersist */
3640 	if (o->control_persist == 0 || o->control_persist_timeout == 0)
3641 		dump_cfg_fmtint(oControlPersist, o->control_persist);
3642 	else
3643 		dump_cfg_int(oControlPersist, o->control_persist_timeout);
3644 
3645 	/* oEscapeChar */
3646 	if (o->escape_char == SSH_ESCAPECHAR_NONE)
3647 		printf("escapechar none\n");
3648 	else {
3649 		vis(buf, o->escape_char, VIS_WHITE, 0);
3650 		printf("escapechar %s\n", buf);
3651 	}
3652 
3653 	/* oIPQoS */
3654 	printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
3655 	printf("%s\n", iptos2str(o->ip_qos_bulk));
3656 
3657 	/* oRekeyLimit */
3658 	printf("rekeylimit %llu %d\n",
3659 	    (unsigned long long)o->rekey_limit, o->rekey_interval);
3660 
3661 	/* oStreamLocalBindMask */
3662 	printf("streamlocalbindmask 0%o\n",
3663 	    o->fwd_opts.streamlocal_bind_mask);
3664 
3665 	/* oLogFacility */
3666 	printf("syslogfacility %s\n", log_facility_name(o->log_facility));
3667 
3668 	/* oProxyCommand / oProxyJump */
3669 	if (o->jump_host == NULL)
3670 		dump_cfg_string(oProxyCommand, o->proxy_command);
3671 	else {
3672 		/* Check for numeric addresses */
3673 		i = strchr(o->jump_host, ':') != NULL ||
3674 		    strspn(o->jump_host, "1234567890.") == strlen(o->jump_host);
3675 		snprintf(buf, sizeof(buf), "%d", o->jump_port);
3676 		printf("proxyjump %s%s%s%s%s%s%s%s%s\n",
3677 		    /* optional additional jump spec */
3678 		    o->jump_extra == NULL ? "" : o->jump_extra,
3679 		    o->jump_extra == NULL ? "" : ",",
3680 		    /* optional user */
3681 		    o->jump_user == NULL ? "" : o->jump_user,
3682 		    o->jump_user == NULL ? "" : "@",
3683 		    /* opening [ if hostname is numeric */
3684 		    i ? "[" : "",
3685 		    /* mandatory hostname */
3686 		    o->jump_host,
3687 		    /* closing ] if hostname is numeric */
3688 		    i ? "]" : "",
3689 		    /* optional port number */
3690 		    o->jump_port <= 0 ? "" : ":",
3691 		    o->jump_port <= 0 ? "" : buf);
3692 	}
3693 }
3694