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