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