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