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