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