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