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