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