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