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