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