• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* $OpenBSD: readconf.c,v 1.239 2015/07/30 00:01:34 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 	oPubkeyAcceptedKeyTypes,
161 	oIgnoredUnknownOption, oDeprecated, oUnsupported
162 } OpCodes;
163 
164 /* Textual representations of the tokens. */
165 
166 static struct {
167 	const char *name;
168 	OpCodes opcode;
169 } keywords[] = {
170 	{ "forwardagent", oForwardAgent },
171 	{ "forwardx11", oForwardX11 },
172 	{ "forwardx11trusted", oForwardX11Trusted },
173 	{ "forwardx11timeout", oForwardX11Timeout },
174 	{ "exitonforwardfailure", oExitOnForwardFailure },
175 	{ "xauthlocation", oXAuthLocation },
176 	{ "gatewayports", oGatewayPorts },
177 	{ "useprivilegedport", oUsePrivilegedPort },
178 	{ "rhostsauthentication", oDeprecated },
179 	{ "passwordauthentication", oPasswordAuthentication },
180 	{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
181 	{ "kbdinteractivedevices", oKbdInteractiveDevices },
182 	{ "rsaauthentication", oRSAAuthentication },
183 	{ "pubkeyauthentication", oPubkeyAuthentication },
184 	{ "dsaauthentication", oPubkeyAuthentication },		    /* alias */
185 	{ "rhostsrsaauthentication", oRhostsRSAAuthentication },
186 	{ "hostbasedauthentication", oHostbasedAuthentication },
187 	{ "challengeresponseauthentication", oChallengeResponseAuthentication },
188 	{ "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
189 	{ "tisauthentication", oChallengeResponseAuthentication },  /* alias */
190 	{ "kerberosauthentication", oUnsupported },
191 	{ "kerberostgtpassing", oUnsupported },
192 	{ "afstokenpassing", oUnsupported },
193 #if defined(GSSAPI)
194 	{ "gssapiauthentication", oGssAuthentication },
195 	{ "gssapidelegatecredentials", oGssDelegateCreds },
196 #else
197 	{ "gssapiauthentication", oUnsupported },
198 	{ "gssapidelegatecredentials", oUnsupported },
199 #endif
200 	{ "fallbacktorsh", oDeprecated },
201 	{ "usersh", oDeprecated },
202 	{ "identityfile", oIdentityFile },
203 	{ "identityfile2", oIdentityFile },			/* obsolete */
204 	{ "identitiesonly", oIdentitiesOnly },
205 	{ "hostname", oHostName },
206 	{ "hostkeyalias", oHostKeyAlias },
207 	{ "proxycommand", oProxyCommand },
208 	{ "port", oPort },
209 	{ "cipher", oCipher },
210 	{ "ciphers", oCiphers },
211 	{ "macs", oMacs },
212 	{ "protocol", oProtocol },
213 	{ "remoteforward", oRemoteForward },
214 	{ "localforward", oLocalForward },
215 	{ "user", oUser },
216 	{ "host", oHost },
217 	{ "match", oMatch },
218 	{ "escapechar", oEscapeChar },
219 	{ "globalknownhostsfile", oGlobalKnownHostsFile },
220 	{ "globalknownhostsfile2", oDeprecated },
221 	{ "userknownhostsfile", oUserKnownHostsFile },
222 	{ "userknownhostsfile2", oDeprecated },
223 	{ "connectionattempts", oConnectionAttempts },
224 	{ "batchmode", oBatchMode },
225 	{ "checkhostip", oCheckHostIP },
226 	{ "stricthostkeychecking", oStrictHostKeyChecking },
227 	{ "compression", oCompression },
228 	{ "compressionlevel", oCompressionLevel },
229 	{ "tcpkeepalive", oTCPKeepAlive },
230 	{ "keepalive", oTCPKeepAlive },				/* obsolete */
231 	{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
232 	{ "loglevel", oLogLevel },
233 	{ "dynamicforward", oDynamicForward },
234 	{ "preferredauthentications", oPreferredAuthentications },
235 	{ "hostkeyalgorithms", oHostKeyAlgorithms },
236 	{ "bindaddress", oBindAddress },
237 #ifdef ENABLE_PKCS11
238 	{ "smartcarddevice", oPKCS11Provider },
239 	{ "pkcs11provider", oPKCS11Provider },
240 #else
241 	{ "smartcarddevice", oUnsupported },
242 	{ "pkcs11provider", oUnsupported },
243 #endif
244 	{ "clearallforwardings", oClearAllForwardings },
245 	{ "enablesshkeysign", oEnableSSHKeysign },
246 	{ "verifyhostkeydns", oVerifyHostKeyDNS },
247 	{ "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
248 	{ "rekeylimit", oRekeyLimit },
249 	{ "connecttimeout", oConnectTimeout },
250 	{ "addressfamily", oAddressFamily },
251 	{ "serveraliveinterval", oServerAliveInterval },
252 	{ "serveralivecountmax", oServerAliveCountMax },
253 	{ "sendenv", oSendEnv },
254 	{ "controlpath", oControlPath },
255 	{ "controlmaster", oControlMaster },
256 	{ "controlpersist", oControlPersist },
257 	{ "hashknownhosts", oHashKnownHosts },
258 	{ "tunnel", oTunnel },
259 	{ "tunneldevice", oTunnelDevice },
260 	{ "localcommand", oLocalCommand },
261 	{ "permitlocalcommand", oPermitLocalCommand },
262 	{ "visualhostkey", oVisualHostKey },
263 	{ "useroaming", oUseRoaming },
264 	{ "kexalgorithms", oKexAlgorithms },
265 	{ "ipqos", oIPQoS },
266 	{ "requesttty", oRequestTTY },
267 	{ "proxyusefdpass", oProxyUseFdpass },
268 	{ "canonicaldomains", oCanonicalDomains },
269 	{ "canonicalizefallbacklocal", oCanonicalizeFallbackLocal },
270 	{ "canonicalizehostname", oCanonicalizeHostname },
271 	{ "canonicalizemaxdots", oCanonicalizeMaxDots },
272 	{ "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
273 	{ "streamlocalbindmask", oStreamLocalBindMask },
274 	{ "streamlocalbindunlink", oStreamLocalBindUnlink },
275 	{ "revokedhostkeys", oRevokedHostKeys },
276 	{ "fingerprinthash", oFingerprintHash },
277 	{ "updatehostkeys", oUpdateHostkeys },
278 	{ "hostbasedkeytypes", oHostbasedKeyTypes },
279 	{ "pubkeyacceptedkeytypes", oPubkeyAcceptedKeyTypes },
280 	{ "ignoreunknown", oIgnoreUnknown },
281 
282 	{ NULL, oBadOption }
283 };
284 
285 /*
286  * Adds a local TCP/IP port forward to options.  Never returns if there is an
287  * error.
288  */
289 
290 void
add_local_forward(Options * options,const struct Forward * newfwd)291 add_local_forward(Options *options, const struct Forward *newfwd)
292 {
293 	struct Forward *fwd;
294 #ifndef NO_IPPORT_RESERVED_CONCEPT
295 	extern uid_t original_real_uid;
296 	if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0 &&
297 	    newfwd->listen_path == NULL)
298 		fatal("Privileged ports can only be forwarded by root.");
299 #endif
300 	options->local_forwards = xreallocarray(options->local_forwards,
301 	    options->num_local_forwards + 1,
302 	    sizeof(*options->local_forwards));
303 	fwd = &options->local_forwards[options->num_local_forwards++];
304 
305 	fwd->listen_host = newfwd->listen_host;
306 	fwd->listen_port = newfwd->listen_port;
307 	fwd->listen_path = newfwd->listen_path;
308 	fwd->connect_host = newfwd->connect_host;
309 	fwd->connect_port = newfwd->connect_port;
310 	fwd->connect_path = newfwd->connect_path;
311 }
312 
313 /*
314  * Adds a remote TCP/IP port forward to options.  Never returns if there is
315  * an error.
316  */
317 
318 void
add_remote_forward(Options * options,const struct Forward * newfwd)319 add_remote_forward(Options *options, const struct Forward *newfwd)
320 {
321 	struct Forward *fwd;
322 
323 	options->remote_forwards = xreallocarray(options->remote_forwards,
324 	    options->num_remote_forwards + 1,
325 	    sizeof(*options->remote_forwards));
326 	fwd = &options->remote_forwards[options->num_remote_forwards++];
327 
328 	fwd->listen_host = newfwd->listen_host;
329 	fwd->listen_port = newfwd->listen_port;
330 	fwd->listen_path = newfwd->listen_path;
331 	fwd->connect_host = newfwd->connect_host;
332 	fwd->connect_port = newfwd->connect_port;
333 	fwd->connect_path = newfwd->connect_path;
334 	fwd->handle = newfwd->handle;
335 	fwd->allocated_port = 0;
336 }
337 
338 static void
clear_forwardings(Options * options)339 clear_forwardings(Options *options)
340 {
341 	int i;
342 
343 	for (i = 0; i < options->num_local_forwards; i++) {
344 		free(options->local_forwards[i].listen_host);
345 		free(options->local_forwards[i].listen_path);
346 		free(options->local_forwards[i].connect_host);
347 		free(options->local_forwards[i].connect_path);
348 	}
349 	if (options->num_local_forwards > 0) {
350 		free(options->local_forwards);
351 		options->local_forwards = NULL;
352 	}
353 	options->num_local_forwards = 0;
354 	for (i = 0; i < options->num_remote_forwards; i++) {
355 		free(options->remote_forwards[i].listen_host);
356 		free(options->remote_forwards[i].listen_path);
357 		free(options->remote_forwards[i].connect_host);
358 		free(options->remote_forwards[i].connect_path);
359 	}
360 	if (options->num_remote_forwards > 0) {
361 		free(options->remote_forwards);
362 		options->remote_forwards = NULL;
363 	}
364 	options->num_remote_forwards = 0;
365 	options->tun_open = SSH_TUNMODE_NO;
366 }
367 
368 void
add_identity_file(Options * options,const char * dir,const char * filename,int userprovided)369 add_identity_file(Options *options, const char *dir, const char *filename,
370     int userprovided)
371 {
372 	char *path;
373 	int i;
374 
375 	if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
376 		fatal("Too many identity files specified (max %d)",
377 		    SSH_MAX_IDENTITY_FILES);
378 
379 	if (dir == NULL) /* no dir, filename is absolute */
380 		path = xstrdup(filename);
381 	else
382 		(void)xasprintf(&path, "%.100s%.100s", dir, filename);
383 
384 	/* Avoid registering duplicates */
385 	for (i = 0; i < options->num_identity_files; i++) {
386 		if (options->identity_file_userprovided[i] == userprovided &&
387 		    strcmp(options->identity_files[i], path) == 0) {
388 			debug2("%s: ignoring duplicate key %s", __func__, path);
389 			free(path);
390 			return;
391 		}
392 	}
393 
394 	options->identity_file_userprovided[options->num_identity_files] =
395 	    userprovided;
396 	options->identity_files[options->num_identity_files++] = path;
397 }
398 
399 int
default_ssh_port(void)400 default_ssh_port(void)
401 {
402 	static int port;
403 	struct servent *sp;
404 
405 	if (port == 0) {
406 		sp = getservbyname(SSH_SERVICE_NAME, "tcp");
407 		port = sp ? ntohs(sp->s_port) : SSH_DEFAULT_PORT;
408 	}
409 	return port;
410 }
411 
412 /*
413  * Execute a command in a shell.
414  * Return its exit status or -1 on abnormal exit.
415  */
416 static int
execute_in_shell(const char * cmd)417 execute_in_shell(const char *cmd)
418 {
419 	char *shell, *command_string;
420 	pid_t pid;
421 	int devnull, status;
422 	extern uid_t original_real_uid;
423 
424 	if ((shell = getenv("SHELL")) == NULL)
425 		shell = _PATH_BSHELL;
426 
427 	/*
428 	 * Use "exec" to avoid "sh -c" processes on some platforms
429 	 * (e.g. Solaris)
430 	 */
431 	xasprintf(&command_string, "exec %s", cmd);
432 
433 	/* Need this to redirect subprocess stdin/out */
434 	if ((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1)
435 		fatal("open(/dev/null): %s", strerror(errno));
436 
437 	debug("Executing command: '%.500s'", cmd);
438 
439 	/* Fork and execute the command. */
440 	if ((pid = fork()) == 0) {
441 		char *argv[4];
442 
443 		/* Child.  Permanently give up superuser privileges. */
444 		permanently_drop_suid(original_real_uid);
445 
446 		/* Redirect child stdin and stdout. Leave stderr */
447 		if (dup2(devnull, STDIN_FILENO) == -1)
448 			fatal("dup2: %s", strerror(errno));
449 		if (dup2(devnull, STDOUT_FILENO) == -1)
450 			fatal("dup2: %s", strerror(errno));
451 		if (devnull > STDERR_FILENO)
452 			close(devnull);
453 		closefrom(STDERR_FILENO + 1);
454 
455 		argv[0] = shell;
456 		argv[1] = "-c";
457 		argv[2] = command_string;
458 		argv[3] = NULL;
459 
460 		execv(argv[0], argv);
461 		error("Unable to execute '%.100s': %s", cmd, strerror(errno));
462 		/* Die with signal to make this error apparent to parent. */
463 		signal(SIGTERM, SIG_DFL);
464 		kill(getpid(), SIGTERM);
465 		_exit(1);
466 	}
467 	/* Parent. */
468 	if (pid < 0)
469 		fatal("%s: fork: %.100s", __func__, strerror(errno));
470 
471 	close(devnull);
472 	free(command_string);
473 
474 	while (waitpid(pid, &status, 0) == -1) {
475 		if (errno != EINTR && errno != EAGAIN)
476 			fatal("%s: waitpid: %s", __func__, strerror(errno));
477 	}
478 	if (!WIFEXITED(status)) {
479 		error("command '%.100s' exited abnormally", cmd);
480 		return -1;
481 	}
482 	debug3("command returned status %d", WEXITSTATUS(status));
483 	return WEXITSTATUS(status);
484 }
485 
486 /*
487  * Parse and execute a Match directive.
488  */
489 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)490 match_cfg_line(Options *options, char **condition, struct passwd *pw,
491     const char *host_arg, const char *original_host, int post_canon,
492     const char *filename, int linenum)
493 {
494 	char *arg, *oattrib, *attrib, *cmd, *cp = *condition, *host, *criteria;
495 	const char *ruser;
496 	int r, port, this_result, result = 1, attributes = 0, negate;
497 	char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV];
498 
499 	/*
500 	 * Configuration is likely to be incomplete at this point so we
501 	 * must be prepared to use default values.
502 	 */
503 	port = options->port <= 0 ? default_ssh_port() : options->port;
504 	ruser = options->user == NULL ? pw->pw_name : options->user;
505 	if (options->hostname != NULL) {
506 		/* NB. Please keep in sync with ssh.c:main() */
507 		host = percent_expand(options->hostname,
508 		    "h", host_arg, (char *)NULL);
509 	} else
510 		host = xstrdup(host_arg);
511 
512 	debug2("checking match for '%s' host %s originally %s",
513 	    cp, host, original_host);
514 	while ((oattrib = attrib = strdelim(&cp)) && *attrib != '\0') {
515 		criteria = NULL;
516 		this_result = 1;
517 		if ((negate = attrib[0] == '!'))
518 			attrib++;
519 		/* criteria "all" and "canonical" have no argument */
520 		if (strcasecmp(attrib, "all") == 0) {
521 			if (attributes > 1 ||
522 			    ((arg = strdelim(&cp)) != NULL && *arg != '\0')) {
523 				error("%.200s line %d: '%s' cannot be combined "
524 				    "with other Match attributes",
525 				    filename, linenum, oattrib);
526 				result = -1;
527 				goto out;
528 			}
529 			if (result)
530 				result = negate ? 0 : 1;
531 			goto out;
532 		}
533 		attributes++;
534 		if (strcasecmp(attrib, "canonical") == 0) {
535 			r = !!post_canon;  /* force bitmask member to boolean */
536 			if (r == (negate ? 1 : 0))
537 				this_result = result = 0;
538 			debug3("%.200s line %d: %smatched '%s'",
539 			    filename, linenum,
540 			    this_result ? "" : "not ", oattrib);
541 			continue;
542 		}
543 		/* All other criteria require an argument */
544 		if ((arg = strdelim(&cp)) == NULL || *arg == '\0') {
545 			error("Missing Match criteria for %s", attrib);
546 			result = -1;
547 			goto out;
548 		}
549 		if (strcasecmp(attrib, "host") == 0) {
550 			criteria = xstrdup(host);
551 			r = match_hostname(host, arg) == 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) == 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, 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, 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 &&
669 	    match_pattern_list(cp, 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 	if ((len = strlen(line)) == 0)
767 		return 0;
768 	for (len--; len > 0; len--) {
769 		if (strchr(WHITESPACE, line[len]) == NULL)
770 			break;
771 		line[len] = '\0';
772 	}
773 
774 	s = line;
775 	/* Get the keyword. (Each line is supposed to begin with a keyword). */
776 	if ((keyword = strdelim(&s)) == NULL)
777 		return 0;
778 	/* Ignore leading whitespace. */
779 	if (*keyword == '\0')
780 		keyword = strdelim(&s);
781 	if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
782 		return 0;
783 	/* Match lowercase keyword */
784 	lowercase(keyword);
785 
786 	opcode = parse_token(keyword, filename, linenum,
787 	    options->ignored_unknown);
788 
789 	switch (opcode) {
790 	case oBadOption:
791 		/* don't panic, but count bad options */
792 		return -1;
793 		/* NOTREACHED */
794 	case oIgnoredUnknownOption:
795 		debug("%s line %d: Ignored unknown option \"%s\"",
796 		    filename, linenum, keyword);
797 		return 0;
798 	case oConnectTimeout:
799 		intptr = &options->connection_timeout;
800 parse_time:
801 		arg = strdelim(&s);
802 		if (!arg || *arg == '\0')
803 			fatal("%s line %d: missing time value.",
804 			    filename, linenum);
805 		if (strcmp(arg, "none") == 0)
806 			value = -1;
807 		else if ((value = convtime(arg)) == -1)
808 			fatal("%s line %d: invalid time value.",
809 			    filename, linenum);
810 		if (*activep && *intptr == -1)
811 			*intptr = value;
812 		break;
813 
814 	case oForwardAgent:
815 		intptr = &options->forward_agent;
816  parse_flag:
817 		multistate_ptr = multistate_flag;
818  parse_multistate:
819 		arg = strdelim(&s);
820 		if (!arg || *arg == '\0')
821 			fatal("%s line %d: missing argument.",
822 			    filename, linenum);
823 		value = -1;
824 		for (i = 0; multistate_ptr[i].key != NULL; i++) {
825 			if (strcasecmp(arg, multistate_ptr[i].key) == 0) {
826 				value = multistate_ptr[i].value;
827 				break;
828 			}
829 		}
830 		if (value == -1)
831 			fatal("%s line %d: unsupported option \"%s\".",
832 			    filename, linenum, arg);
833 		if (*activep && *intptr == -1)
834 			*intptr = value;
835 		break;
836 
837 	case oForwardX11:
838 		intptr = &options->forward_x11;
839 		goto parse_flag;
840 
841 	case oForwardX11Trusted:
842 		intptr = &options->forward_x11_trusted;
843 		goto parse_flag;
844 
845 	case oForwardX11Timeout:
846 		intptr = &options->forward_x11_timeout;
847 		goto parse_time;
848 
849 	case oGatewayPorts:
850 		intptr = &options->fwd_opts.gateway_ports;
851 		goto parse_flag;
852 
853 	case oExitOnForwardFailure:
854 		intptr = &options->exit_on_forward_failure;
855 		goto parse_flag;
856 
857 	case oUsePrivilegedPort:
858 		intptr = &options->use_privileged_port;
859 		goto parse_flag;
860 
861 	case oPasswordAuthentication:
862 		intptr = &options->password_authentication;
863 		goto parse_flag;
864 
865 	case oKbdInteractiveAuthentication:
866 		intptr = &options->kbd_interactive_authentication;
867 		goto parse_flag;
868 
869 	case oKbdInteractiveDevices:
870 		charptr = &options->kbd_interactive_devices;
871 		goto parse_string;
872 
873 	case oPubkeyAuthentication:
874 		intptr = &options->pubkey_authentication;
875 		goto parse_flag;
876 
877 	case oRSAAuthentication:
878 		intptr = &options->rsa_authentication;
879 		goto parse_flag;
880 
881 	case oRhostsRSAAuthentication:
882 		intptr = &options->rhosts_rsa_authentication;
883 		goto parse_flag;
884 
885 	case oHostbasedAuthentication:
886 		intptr = &options->hostbased_authentication;
887 		goto parse_flag;
888 
889 	case oChallengeResponseAuthentication:
890 		intptr = &options->challenge_response_authentication;
891 		goto parse_flag;
892 
893 	case oGssAuthentication:
894 		intptr = &options->gss_authentication;
895 		goto parse_flag;
896 
897 	case oGssDelegateCreds:
898 		intptr = &options->gss_deleg_creds;
899 		goto parse_flag;
900 
901 	case oBatchMode:
902 		intptr = &options->batch_mode;
903 		goto parse_flag;
904 
905 	case oCheckHostIP:
906 		intptr = &options->check_host_ip;
907 		goto parse_flag;
908 
909 	case oVerifyHostKeyDNS:
910 		intptr = &options->verify_host_key_dns;
911 		multistate_ptr = multistate_yesnoask;
912 		goto parse_multistate;
913 
914 	case oStrictHostKeyChecking:
915 		intptr = &options->strict_host_key_checking;
916 		multistate_ptr = multistate_yesnoask;
917 		goto parse_multistate;
918 
919 	case oCompression:
920 		intptr = &options->compression;
921 		goto parse_flag;
922 
923 	case oTCPKeepAlive:
924 		intptr = &options->tcp_keep_alive;
925 		goto parse_flag;
926 
927 	case oNoHostAuthenticationForLocalhost:
928 		intptr = &options->no_host_authentication_for_localhost;
929 		goto parse_flag;
930 
931 	case oNumberOfPasswordPrompts:
932 		intptr = &options->number_of_password_prompts;
933 		goto parse_int;
934 
935 	case oCompressionLevel:
936 		intptr = &options->compression_level;
937 		goto parse_int;
938 
939 	case oRekeyLimit:
940 		arg = strdelim(&s);
941 		if (!arg || *arg == '\0')
942 			fatal("%.200s line %d: Missing argument.", filename,
943 			    linenum);
944 		if (strcmp(arg, "default") == 0) {
945 			val64 = 0;
946 		} else {
947 			if (scan_scaled(arg, &val64) == -1)
948 				fatal("%.200s line %d: Bad number '%s': %s",
949 				    filename, linenum, arg, strerror(errno));
950 			/* check for too-large or too-small limits */
951 			if (val64 > UINT_MAX)
952 				fatal("%.200s line %d: RekeyLimit too large",
953 				    filename, linenum);
954 			if (val64 != 0 && val64 < 16)
955 				fatal("%.200s line %d: RekeyLimit too small",
956 				    filename, linenum);
957 		}
958 		if (*activep && options->rekey_limit == -1)
959 			options->rekey_limit = (u_int32_t)val64;
960 		if (s != NULL) { /* optional rekey interval present */
961 			if (strcmp(s, "none") == 0) {
962 				(void)strdelim(&s);	/* discard */
963 				break;
964 			}
965 			intptr = &options->rekey_interval;
966 			goto parse_time;
967 		}
968 		break;
969 
970 	case oIdentityFile:
971 		arg = strdelim(&s);
972 		if (!arg || *arg == '\0')
973 			fatal("%.200s line %d: Missing argument.", filename, linenum);
974 		if (*activep) {
975 			intptr = &options->num_identity_files;
976 			if (*intptr >= SSH_MAX_IDENTITY_FILES)
977 				fatal("%.200s line %d: Too many identity files specified (max %d).",
978 				    filename, linenum, SSH_MAX_IDENTITY_FILES);
979 			add_identity_file(options, NULL,
980 			    arg, flags & SSHCONF_USERCONF);
981 		}
982 		break;
983 
984 	case oXAuthLocation:
985 		charptr=&options->xauth_location;
986 		goto parse_string;
987 
988 	case oUser:
989 		charptr = &options->user;
990 parse_string:
991 		arg = strdelim(&s);
992 		if (!arg || *arg == '\0')
993 			fatal("%.200s line %d: Missing argument.",
994 			    filename, linenum);
995 		if (*activep && *charptr == NULL)
996 			*charptr = xstrdup(arg);
997 		break;
998 
999 	case oGlobalKnownHostsFile:
1000 		cpptr = (char **)&options->system_hostfiles;
1001 		uintptr = &options->num_system_hostfiles;
1002 		max_entries = SSH_MAX_HOSTS_FILES;
1003 parse_char_array:
1004 		if (*activep && *uintptr == 0) {
1005 			while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1006 				if ((*uintptr) >= max_entries)
1007 					fatal("%s line %d: "
1008 					    "too many authorized keys files.",
1009 					    filename, linenum);
1010 				cpptr[(*uintptr)++] = xstrdup(arg);
1011 			}
1012 		}
1013 		return 0;
1014 
1015 	case oUserKnownHostsFile:
1016 		cpptr = (char **)&options->user_hostfiles;
1017 		uintptr = &options->num_user_hostfiles;
1018 		max_entries = SSH_MAX_HOSTS_FILES;
1019 		goto parse_char_array;
1020 
1021 	case oHostName:
1022 		charptr = &options->hostname;
1023 		goto parse_string;
1024 
1025 	case oHostKeyAlias:
1026 		charptr = &options->host_key_alias;
1027 		goto parse_string;
1028 
1029 	case oPreferredAuthentications:
1030 		charptr = &options->preferred_authentications;
1031 		goto parse_string;
1032 
1033 	case oBindAddress:
1034 		charptr = &options->bind_address;
1035 		goto parse_string;
1036 
1037 	case oPKCS11Provider:
1038 		charptr = &options->pkcs11_provider;
1039 		goto parse_string;
1040 
1041 	case oProxyCommand:
1042 		charptr = &options->proxy_command;
1043 parse_command:
1044 		if (s == NULL)
1045 			fatal("%.200s line %d: Missing argument.", filename, linenum);
1046 		len = strspn(s, WHITESPACE "=");
1047 		if (*activep && *charptr == NULL)
1048 			*charptr = xstrdup(s + len);
1049 		return 0;
1050 
1051 	case oPort:
1052 		intptr = &options->port;
1053 parse_int:
1054 		arg = strdelim(&s);
1055 		if (!arg || *arg == '\0')
1056 			fatal("%.200s line %d: Missing argument.", filename, linenum);
1057 		if (arg[0] < '0' || arg[0] > '9')
1058 			fatal("%.200s line %d: Bad number.", filename, linenum);
1059 
1060 		/* Octal, decimal, or hex format? */
1061 		value = strtol(arg, &endofnumber, 0);
1062 		if (arg == endofnumber)
1063 			fatal("%.200s line %d: Bad number.", filename, linenum);
1064 		if (*activep && *intptr == -1)
1065 			*intptr = value;
1066 		break;
1067 
1068 	case oConnectionAttempts:
1069 		intptr = &options->connection_attempts;
1070 		goto parse_int;
1071 
1072 	case oCipher:
1073 		intptr = &options->cipher;
1074 		arg = strdelim(&s);
1075 		if (!arg || *arg == '\0')
1076 			fatal("%.200s line %d: Missing argument.", filename, linenum);
1077 		value = cipher_number(arg);
1078 		if (value == -1)
1079 			fatal("%.200s line %d: Bad cipher '%s'.",
1080 			    filename, linenum, arg ? arg : "<NONE>");
1081 		if (*activep && *intptr == -1)
1082 			*intptr = value;
1083 		break;
1084 
1085 	case oCiphers:
1086 		arg = strdelim(&s);
1087 		if (!arg || *arg == '\0')
1088 			fatal("%.200s line %d: Missing argument.", filename, linenum);
1089 		if (!ciphers_valid(*arg == '+' ? arg + 1 : arg))
1090 			fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
1091 			    filename, linenum, arg ? arg : "<NONE>");
1092 		if (*activep && options->ciphers == NULL)
1093 			options->ciphers = xstrdup(arg);
1094 		break;
1095 
1096 	case oMacs:
1097 		arg = strdelim(&s);
1098 		if (!arg || *arg == '\0')
1099 			fatal("%.200s line %d: Missing argument.", filename, linenum);
1100 		if (!mac_valid(*arg == '+' ? arg + 1 : arg))
1101 			fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
1102 			    filename, linenum, arg ? arg : "<NONE>");
1103 		if (*activep && options->macs == NULL)
1104 			options->macs = xstrdup(arg);
1105 		break;
1106 
1107 	case oKexAlgorithms:
1108 		arg = strdelim(&s);
1109 		if (!arg || *arg == '\0')
1110 			fatal("%.200s line %d: Missing argument.",
1111 			    filename, linenum);
1112 		if (!kex_names_valid(*arg == '+' ? arg + 1 : arg))
1113 			fatal("%.200s line %d: Bad SSH2 KexAlgorithms '%s'.",
1114 			    filename, linenum, arg ? arg : "<NONE>");
1115 		if (*activep && options->kex_algorithms == NULL)
1116 			options->kex_algorithms = xstrdup(arg);
1117 		break;
1118 
1119 	case oHostKeyAlgorithms:
1120 		charptr = &options->hostkeyalgorithms;
1121 parse_keytypes:
1122 		arg = strdelim(&s);
1123 		if (!arg || *arg == '\0')
1124 			fatal("%.200s line %d: Missing argument.",
1125 			    filename, linenum);
1126 		if (!sshkey_names_valid2(*arg == '+' ? arg + 1 : arg, 1))
1127 			fatal("%s line %d: Bad key types '%s'.",
1128 				filename, linenum, arg ? arg : "<NONE>");
1129 		if (*activep && *charptr == NULL)
1130 			*charptr = xstrdup(arg);
1131 		break;
1132 
1133 	case oProtocol:
1134 		intptr = &options->protocol;
1135 		arg = strdelim(&s);
1136 		if (!arg || *arg == '\0')
1137 			fatal("%.200s line %d: Missing argument.", filename, linenum);
1138 		value = proto_spec(arg);
1139 		if (value == SSH_PROTO_UNKNOWN)
1140 			fatal("%.200s line %d: Bad protocol spec '%s'.",
1141 			    filename, linenum, arg ? arg : "<NONE>");
1142 		if (*activep && *intptr == SSH_PROTO_UNKNOWN)
1143 			*intptr = value;
1144 		break;
1145 
1146 	case oLogLevel:
1147 		log_level_ptr = &options->log_level;
1148 		arg = strdelim(&s);
1149 		value = log_level_number(arg);
1150 		if (value == SYSLOG_LEVEL_NOT_SET)
1151 			fatal("%.200s line %d: unsupported log level '%s'",
1152 			    filename, linenum, arg ? arg : "<NONE>");
1153 		if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
1154 			*log_level_ptr = (LogLevel) value;
1155 		break;
1156 
1157 	case oLocalForward:
1158 	case oRemoteForward:
1159 	case oDynamicForward:
1160 		arg = strdelim(&s);
1161 		if (arg == NULL || *arg == '\0')
1162 			fatal("%.200s line %d: Missing port argument.",
1163 			    filename, linenum);
1164 
1165 		if (opcode == oLocalForward ||
1166 		    opcode == oRemoteForward) {
1167 			arg2 = strdelim(&s);
1168 			if (arg2 == NULL || *arg2 == '\0')
1169 				fatal("%.200s line %d: Missing target argument.",
1170 				    filename, linenum);
1171 
1172 			/* construct a string for parse_forward */
1173 			snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
1174 		} else if (opcode == oDynamicForward) {
1175 			strlcpy(fwdarg, arg, sizeof(fwdarg));
1176 		}
1177 
1178 		if (parse_forward(&fwd, fwdarg,
1179 		    opcode == oDynamicForward ? 1 : 0,
1180 		    opcode == oRemoteForward ? 1 : 0) == 0)
1181 			fatal("%.200s line %d: Bad forwarding specification.",
1182 			    filename, linenum);
1183 
1184 		if (*activep) {
1185 			if (opcode == oLocalForward ||
1186 			    opcode == oDynamicForward)
1187 				add_local_forward(options, &fwd);
1188 			else if (opcode == oRemoteForward)
1189 				add_remote_forward(options, &fwd);
1190 		}
1191 		break;
1192 
1193 	case oClearAllForwardings:
1194 		intptr = &options->clear_forwardings;
1195 		goto parse_flag;
1196 
1197 	case oHost:
1198 		if (cmdline)
1199 			fatal("Host directive not supported as a command-line "
1200 			    "option");
1201 		*activep = 0;
1202 		arg2 = NULL;
1203 		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1204 			negated = *arg == '!';
1205 			if (negated)
1206 				arg++;
1207 			if (match_pattern(host, arg)) {
1208 				if (negated) {
1209 					debug("%.200s line %d: Skipping Host "
1210 					    "block because of negated match "
1211 					    "for %.100s", filename, linenum,
1212 					    arg);
1213 					*activep = 0;
1214 					break;
1215 				}
1216 				if (!*activep)
1217 					arg2 = arg; /* logged below */
1218 				*activep = 1;
1219 			}
1220 		}
1221 		if (*activep)
1222 			debug("%.200s line %d: Applying options for %.100s",
1223 			    filename, linenum, arg2);
1224 		/* Avoid garbage check below, as strdelim is done. */
1225 		return 0;
1226 
1227 	case oMatch:
1228 		if (cmdline)
1229 			fatal("Host directive not supported as a command-line "
1230 			    "option");
1231 		value = match_cfg_line(options, &s, pw, host, original_host,
1232 		    flags & SSHCONF_POSTCANON, filename, linenum);
1233 		if (value < 0)
1234 			fatal("%.200s line %d: Bad Match condition", filename,
1235 			    linenum);
1236 		*activep = value;
1237 		break;
1238 
1239 	case oEscapeChar:
1240 		intptr = &options->escape_char;
1241 		arg = strdelim(&s);
1242 		if (!arg || *arg == '\0')
1243 			fatal("%.200s line %d: Missing argument.", filename, linenum);
1244 		if (strcmp(arg, "none") == 0)
1245 			value = SSH_ESCAPECHAR_NONE;
1246 		else if (arg[1] == '\0')
1247 			value = (u_char) arg[0];
1248 		else if (arg[0] == '^' && arg[2] == 0 &&
1249 		    (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
1250 			value = (u_char) arg[1] & 31;
1251 		else {
1252 			fatal("%.200s line %d: Bad escape character.",
1253 			    filename, linenum);
1254 			/* NOTREACHED */
1255 			value = 0;	/* Avoid compiler warning. */
1256 		}
1257 		if (*activep && *intptr == -1)
1258 			*intptr = value;
1259 		break;
1260 
1261 	case oAddressFamily:
1262 		intptr = &options->address_family;
1263 		multistate_ptr = multistate_addressfamily;
1264 		goto parse_multistate;
1265 
1266 	case oEnableSSHKeysign:
1267 		intptr = &options->enable_ssh_keysign;
1268 		goto parse_flag;
1269 
1270 	case oIdentitiesOnly:
1271 		intptr = &options->identities_only;
1272 		goto parse_flag;
1273 
1274 	case oServerAliveInterval:
1275 		intptr = &options->server_alive_interval;
1276 		goto parse_time;
1277 
1278 	case oServerAliveCountMax:
1279 		intptr = &options->server_alive_count_max;
1280 		goto parse_int;
1281 
1282 	case oSendEnv:
1283 		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1284 			if (strchr(arg, '=') != NULL)
1285 				fatal("%s line %d: Invalid environment name.",
1286 				    filename, linenum);
1287 			if (!*activep)
1288 				continue;
1289 			if (options->num_send_env >= MAX_SEND_ENV)
1290 				fatal("%s line %d: too many send env.",
1291 				    filename, linenum);
1292 			options->send_env[options->num_send_env++] =
1293 			    xstrdup(arg);
1294 		}
1295 		break;
1296 
1297 	case oControlPath:
1298 		charptr = &options->control_path;
1299 		goto parse_string;
1300 
1301 	case oControlMaster:
1302 		intptr = &options->control_master;
1303 		multistate_ptr = multistate_controlmaster;
1304 		goto parse_multistate;
1305 
1306 	case oControlPersist:
1307 		/* no/false/yes/true, or a time spec */
1308 		intptr = &options->control_persist;
1309 		arg = strdelim(&s);
1310 		if (!arg || *arg == '\0')
1311 			fatal("%.200s line %d: Missing ControlPersist"
1312 			    " argument.", filename, linenum);
1313 		value = 0;
1314 		value2 = 0;	/* timeout */
1315 		if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
1316 			value = 0;
1317 		else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
1318 			value = 1;
1319 		else if ((value2 = convtime(arg)) >= 0)
1320 			value = 1;
1321 		else
1322 			fatal("%.200s line %d: Bad ControlPersist argument.",
1323 			    filename, linenum);
1324 		if (*activep && *intptr == -1) {
1325 			*intptr = value;
1326 			options->control_persist_timeout = value2;
1327 		}
1328 		break;
1329 
1330 	case oHashKnownHosts:
1331 		intptr = &options->hash_known_hosts;
1332 		goto parse_flag;
1333 
1334 	case oTunnel:
1335 		intptr = &options->tun_open;
1336 		multistate_ptr = multistate_tunnel;
1337 		goto parse_multistate;
1338 
1339 	case oTunnelDevice:
1340 		arg = strdelim(&s);
1341 		if (!arg || *arg == '\0')
1342 			fatal("%.200s line %d: Missing argument.", filename, linenum);
1343 		value = a2tun(arg, &value2);
1344 		if (value == SSH_TUNID_ERR)
1345 			fatal("%.200s line %d: Bad tun device.", filename, linenum);
1346 		if (*activep) {
1347 			options->tun_local = value;
1348 			options->tun_remote = value2;
1349 		}
1350 		break;
1351 
1352 	case oLocalCommand:
1353 		charptr = &options->local_command;
1354 		goto parse_command;
1355 
1356 	case oPermitLocalCommand:
1357 		intptr = &options->permit_local_command;
1358 		goto parse_flag;
1359 
1360 	case oVisualHostKey:
1361 		intptr = &options->visual_host_key;
1362 		goto parse_flag;
1363 
1364 	case oIPQoS:
1365 		arg = strdelim(&s);
1366 		if ((value = parse_ipqos(arg)) == -1)
1367 			fatal("%s line %d: Bad IPQoS value: %s",
1368 			    filename, linenum, arg);
1369 		arg = strdelim(&s);
1370 		if (arg == NULL)
1371 			value2 = value;
1372 		else if ((value2 = parse_ipqos(arg)) == -1)
1373 			fatal("%s line %d: Bad IPQoS value: %s",
1374 			    filename, linenum, arg);
1375 		if (*activep) {
1376 			options->ip_qos_interactive = value;
1377 			options->ip_qos_bulk = value2;
1378 		}
1379 		break;
1380 
1381 	case oUseRoaming:
1382 		intptr = &options->use_roaming;
1383 		goto parse_flag;
1384 
1385 	case oRequestTTY:
1386 		intptr = &options->request_tty;
1387 		multistate_ptr = multistate_requesttty;
1388 		goto parse_multistate;
1389 
1390 	case oIgnoreUnknown:
1391 		charptr = &options->ignored_unknown;
1392 		goto parse_string;
1393 
1394 	case oProxyUseFdpass:
1395 		intptr = &options->proxy_use_fdpass;
1396 		goto parse_flag;
1397 
1398 	case oCanonicalDomains:
1399 		value = options->num_canonical_domains != 0;
1400 		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1401 			valid_domain(arg, filename, linenum);
1402 			if (!*activep || value)
1403 				continue;
1404 			if (options->num_canonical_domains >= MAX_CANON_DOMAINS)
1405 				fatal("%s line %d: too many hostname suffixes.",
1406 				    filename, linenum);
1407 			options->canonical_domains[
1408 			    options->num_canonical_domains++] = xstrdup(arg);
1409 		}
1410 		break;
1411 
1412 	case oCanonicalizePermittedCNAMEs:
1413 		value = options->num_permitted_cnames != 0;
1414 		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1415 			/* Either '*' for everything or 'list:list' */
1416 			if (strcmp(arg, "*") == 0)
1417 				arg2 = arg;
1418 			else {
1419 				lowercase(arg);
1420 				if ((arg2 = strchr(arg, ':')) == NULL ||
1421 				    arg2[1] == '\0') {
1422 					fatal("%s line %d: "
1423 					    "Invalid permitted CNAME \"%s\"",
1424 					    filename, linenum, arg);
1425 				}
1426 				*arg2 = '\0';
1427 				arg2++;
1428 			}
1429 			if (!*activep || value)
1430 				continue;
1431 			if (options->num_permitted_cnames >= MAX_CANON_DOMAINS)
1432 				fatal("%s line %d: too many permitted CNAMEs.",
1433 				    filename, linenum);
1434 			cname = options->permitted_cnames +
1435 			    options->num_permitted_cnames++;
1436 			cname->source_list = xstrdup(arg);
1437 			cname->target_list = xstrdup(arg2);
1438 		}
1439 		break;
1440 
1441 	case oCanonicalizeHostname:
1442 		intptr = &options->canonicalize_hostname;
1443 		multistate_ptr = multistate_canonicalizehostname;
1444 		goto parse_multistate;
1445 
1446 	case oCanonicalizeMaxDots:
1447 		intptr = &options->canonicalize_max_dots;
1448 		goto parse_int;
1449 
1450 	case oCanonicalizeFallbackLocal:
1451 		intptr = &options->canonicalize_fallback_local;
1452 		goto parse_flag;
1453 
1454 	case oStreamLocalBindMask:
1455 		arg = strdelim(&s);
1456 		if (!arg || *arg == '\0')
1457 			fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum);
1458 		/* Parse mode in octal format */
1459 		value = strtol(arg, &endofnumber, 8);
1460 		if (arg == endofnumber || value < 0 || value > 0777)
1461 			fatal("%.200s line %d: Bad mask.", filename, linenum);
1462 		options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
1463 		break;
1464 
1465 	case oStreamLocalBindUnlink:
1466 		intptr = &options->fwd_opts.streamlocal_bind_unlink;
1467 		goto parse_flag;
1468 
1469 	case oRevokedHostKeys:
1470 		charptr = &options->revoked_host_keys;
1471 		goto parse_string;
1472 
1473 	case oFingerprintHash:
1474 		intptr = &options->fingerprint_hash;
1475 		arg = strdelim(&s);
1476 		if (!arg || *arg == '\0')
1477 			fatal("%.200s line %d: Missing argument.",
1478 			    filename, linenum);
1479 		if ((value = ssh_digest_alg_by_name(arg)) == -1)
1480 			fatal("%.200s line %d: Invalid hash algorithm \"%s\".",
1481 			    filename, linenum, arg);
1482 		if (*activep && *intptr == -1)
1483 			*intptr = value;
1484 		break;
1485 
1486 	case oUpdateHostkeys:
1487 		intptr = &options->update_hostkeys;
1488 		multistate_ptr = multistate_yesnoask;
1489 		goto parse_multistate;
1490 
1491 	case oHostbasedKeyTypes:
1492 		charptr = &options->hostbased_key_types;
1493 		goto parse_keytypes;
1494 
1495 	case oPubkeyAcceptedKeyTypes:
1496 		charptr = &options->pubkey_key_types;
1497 		goto parse_keytypes;
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 = 0;
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 	options->pubkey_key_types = NULL;
1680 }
1681 
1682 /*
1683  * A petite version of fill_default_options() that just fills the options
1684  * needed for hostname canonicalization to proceed.
1685  */
1686 void
fill_default_options_for_canonicalization(Options * options)1687 fill_default_options_for_canonicalization(Options *options)
1688 {
1689 	if (options->canonicalize_max_dots == -1)
1690 		options->canonicalize_max_dots = 1;
1691 	if (options->canonicalize_fallback_local == -1)
1692 		options->canonicalize_fallback_local = 1;
1693 	if (options->canonicalize_hostname == -1)
1694 		options->canonicalize_hostname = SSH_CANONICALISE_NO;
1695 }
1696 
1697 /*
1698  * Called after processing other sources of option data, this fills those
1699  * options for which no value has been specified with their default values.
1700  */
1701 void
fill_default_options(Options * options)1702 fill_default_options(Options * options)
1703 {
1704 	if (options->forward_agent == -1)
1705 		options->forward_agent = 0;
1706 	if (options->forward_x11 == -1)
1707 		options->forward_x11 = 0;
1708 	if (options->forward_x11_trusted == -1)
1709 		options->forward_x11_trusted = 0;
1710 	if (options->forward_x11_timeout == -1)
1711 		options->forward_x11_timeout = 1200;
1712 	if (options->exit_on_forward_failure == -1)
1713 		options->exit_on_forward_failure = 0;
1714 	if (options->xauth_location == NULL)
1715 		options->xauth_location = _PATH_XAUTH;
1716 	if (options->fwd_opts.gateway_ports == -1)
1717 		options->fwd_opts.gateway_ports = 0;
1718 	if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
1719 		options->fwd_opts.streamlocal_bind_mask = 0177;
1720 	if (options->fwd_opts.streamlocal_bind_unlink == -1)
1721 		options->fwd_opts.streamlocal_bind_unlink = 0;
1722 	if (options->use_privileged_port == -1)
1723 		options->use_privileged_port = 0;
1724 	if (options->rsa_authentication == -1)
1725 		options->rsa_authentication = 1;
1726 	if (options->pubkey_authentication == -1)
1727 		options->pubkey_authentication = 1;
1728 	if (options->challenge_response_authentication == -1)
1729 		options->challenge_response_authentication = 1;
1730 	if (options->gss_authentication == -1)
1731 		options->gss_authentication = 0;
1732 	if (options->gss_deleg_creds == -1)
1733 		options->gss_deleg_creds = 0;
1734 	if (options->password_authentication == -1)
1735 		options->password_authentication = 1;
1736 	if (options->kbd_interactive_authentication == -1)
1737 		options->kbd_interactive_authentication = 1;
1738 	if (options->rhosts_rsa_authentication == -1)
1739 		options->rhosts_rsa_authentication = 0;
1740 	if (options->hostbased_authentication == -1)
1741 		options->hostbased_authentication = 0;
1742 	if (options->batch_mode == -1)
1743 		options->batch_mode = 0;
1744 	if (options->check_host_ip == -1)
1745 		options->check_host_ip = 1;
1746 	if (options->strict_host_key_checking == -1)
1747 		options->strict_host_key_checking = 2;	/* 2 is default */
1748 	if (options->compression == -1)
1749 		options->compression = 0;
1750 	if (options->tcp_keep_alive == -1)
1751 		options->tcp_keep_alive = 1;
1752 	if (options->compression_level == -1)
1753 		options->compression_level = 6;
1754 	if (options->port == -1)
1755 		options->port = 0;	/* Filled in ssh_connect. */
1756 	if (options->address_family == -1)
1757 		options->address_family = AF_UNSPEC;
1758 	if (options->connection_attempts == -1)
1759 		options->connection_attempts = 1;
1760 	if (options->number_of_password_prompts == -1)
1761 		options->number_of_password_prompts = 3;
1762 	/* Selected in ssh_login(). */
1763 	if (options->cipher == -1)
1764 		options->cipher = SSH_CIPHER_NOT_SET;
1765 	/* options->hostkeyalgorithms, default set in myproposals.h */
1766 	if (options->protocol == SSH_PROTO_UNKNOWN)
1767 		options->protocol = SSH_PROTO_2;
1768 	if (options->num_identity_files == 0) {
1769 		if (options->protocol & SSH_PROTO_1) {
1770 			add_identity_file(options, "~/",
1771 			    _PATH_SSH_CLIENT_IDENTITY, 0);
1772 		}
1773 		if (options->protocol & SSH_PROTO_2) {
1774 			add_identity_file(options, "~/",
1775 			    _PATH_SSH_CLIENT_ID_RSA, 0);
1776 			add_identity_file(options, "~/",
1777 			    _PATH_SSH_CLIENT_ID_DSA, 0);
1778 #ifdef OPENSSL_HAS_ECC
1779 			add_identity_file(options, "~/",
1780 			    _PATH_SSH_CLIENT_ID_ECDSA, 0);
1781 #endif
1782 			add_identity_file(options, "~/",
1783 			    _PATH_SSH_CLIENT_ID_ED25519, 0);
1784 		}
1785 	}
1786 	if (options->escape_char == -1)
1787 		options->escape_char = '~';
1788 	if (options->num_system_hostfiles == 0) {
1789 		options->system_hostfiles[options->num_system_hostfiles++] =
1790 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE);
1791 		options->system_hostfiles[options->num_system_hostfiles++] =
1792 		    xstrdup(_PATH_SSH_SYSTEM_HOSTFILE2);
1793 	}
1794 	if (options->num_user_hostfiles == 0) {
1795 		options->user_hostfiles[options->num_user_hostfiles++] =
1796 		    xstrdup(_PATH_SSH_USER_HOSTFILE);
1797 		options->user_hostfiles[options->num_user_hostfiles++] =
1798 		    xstrdup(_PATH_SSH_USER_HOSTFILE2);
1799 	}
1800 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
1801 		options->log_level = SYSLOG_LEVEL_INFO;
1802 	if (options->clear_forwardings == 1)
1803 		clear_forwardings(options);
1804 	if (options->no_host_authentication_for_localhost == - 1)
1805 		options->no_host_authentication_for_localhost = 0;
1806 	if (options->identities_only == -1)
1807 		options->identities_only = 0;
1808 	if (options->enable_ssh_keysign == -1)
1809 		options->enable_ssh_keysign = 0;
1810 	if (options->rekey_limit == -1)
1811 		options->rekey_limit = 0;
1812 	if (options->rekey_interval == -1)
1813 		options->rekey_interval = 0;
1814 	if (options->verify_host_key_dns == -1)
1815 		options->verify_host_key_dns = 0;
1816 	if (options->server_alive_interval == -1)
1817 		options->server_alive_interval = 0;
1818 	if (options->server_alive_count_max == -1)
1819 		options->server_alive_count_max = 3;
1820 	if (options->control_master == -1)
1821 		options->control_master = 0;
1822 	if (options->control_persist == -1) {
1823 		options->control_persist = 0;
1824 		options->control_persist_timeout = 0;
1825 	}
1826 	if (options->hash_known_hosts == -1)
1827 		options->hash_known_hosts = 0;
1828 	if (options->tun_open == -1)
1829 		options->tun_open = SSH_TUNMODE_NO;
1830 	if (options->tun_local == -1)
1831 		options->tun_local = SSH_TUNID_ANY;
1832 	if (options->tun_remote == -1)
1833 		options->tun_remote = SSH_TUNID_ANY;
1834 	if (options->permit_local_command == -1)
1835 		options->permit_local_command = 0;
1836 	options->use_roaming = 0;
1837 	if (options->visual_host_key == -1)
1838 		options->visual_host_key = 0;
1839 	if (options->ip_qos_interactive == -1)
1840 		options->ip_qos_interactive = IPTOS_LOWDELAY;
1841 	if (options->ip_qos_bulk == -1)
1842 		options->ip_qos_bulk = IPTOS_THROUGHPUT;
1843 	if (options->request_tty == -1)
1844 		options->request_tty = REQUEST_TTY_AUTO;
1845 	if (options->proxy_use_fdpass == -1)
1846 		options->proxy_use_fdpass = 0;
1847 	if (options->canonicalize_max_dots == -1)
1848 		options->canonicalize_max_dots = 1;
1849 	if (options->canonicalize_fallback_local == -1)
1850 		options->canonicalize_fallback_local = 1;
1851 	if (options->canonicalize_hostname == -1)
1852 		options->canonicalize_hostname = SSH_CANONICALISE_NO;
1853 	if (options->fingerprint_hash == -1)
1854 		options->fingerprint_hash = SSH_FP_HASH_DEFAULT;
1855 	if (options->update_hostkeys == -1)
1856 		options->update_hostkeys = 0;
1857 	if (kex_assemble_names(KEX_CLIENT_ENCRYPT, &options->ciphers) != 0 ||
1858 	    kex_assemble_names(KEX_CLIENT_MAC, &options->macs) != 0 ||
1859 	    kex_assemble_names(KEX_CLIENT_KEX, &options->kex_algorithms) != 0 ||
1860 	    kex_assemble_names(KEX_DEFAULT_PK_ALG,
1861 	    &options->hostbased_key_types) != 0 ||
1862 	    kex_assemble_names(KEX_DEFAULT_PK_ALG,
1863 	    &options->pubkey_key_types) != 0)
1864 		fatal("%s: kex_assemble_names failed", __func__);
1865 
1866 #define CLEAR_ON_NONE(v) \
1867 	do { \
1868 		if (option_clear_or_none(v)) { \
1869 			free(v); \
1870 			v = NULL; \
1871 		} \
1872 	} while(0)
1873 	CLEAR_ON_NONE(options->local_command);
1874 	CLEAR_ON_NONE(options->proxy_command);
1875 	CLEAR_ON_NONE(options->control_path);
1876 	CLEAR_ON_NONE(options->revoked_host_keys);
1877 	/* options->user will be set in the main program if appropriate */
1878 	/* options->hostname will be set in the main program if appropriate */
1879 	/* options->host_key_alias should not be set by default */
1880 	/* options->preferred_authentications will be set in ssh */
1881 }
1882 
1883 struct fwdarg {
1884 	char *arg;
1885 	int ispath;
1886 };
1887 
1888 /*
1889  * parse_fwd_field
1890  * parses the next field in a port forwarding specification.
1891  * sets fwd to the parsed field and advances p past the colon
1892  * or sets it to NULL at end of string.
1893  * returns 0 on success, else non-zero.
1894  */
1895 static int
parse_fwd_field(char ** p,struct fwdarg * fwd)1896 parse_fwd_field(char **p, struct fwdarg *fwd)
1897 {
1898 	char *ep, *cp = *p;
1899 	int ispath = 0;
1900 
1901 	if (*cp == '\0') {
1902 		*p = NULL;
1903 		return -1;	/* end of string */
1904 	}
1905 
1906 	/*
1907 	 * A field escaped with square brackets is used literally.
1908 	 * XXX - allow ']' to be escaped via backslash?
1909 	 */
1910 	if (*cp == '[') {
1911 		/* find matching ']' */
1912 		for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
1913 			if (*ep == '/')
1914 				ispath = 1;
1915 		}
1916 		/* no matching ']' or not at end of field. */
1917 		if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
1918 			return -1;
1919 		/* NUL terminate the field and advance p past the colon */
1920 		*ep++ = '\0';
1921 		if (*ep != '\0')
1922 			*ep++ = '\0';
1923 		fwd->arg = cp + 1;
1924 		fwd->ispath = ispath;
1925 		*p = ep;
1926 		return 0;
1927 	}
1928 
1929 	for (cp = *p; *cp != '\0'; cp++) {
1930 		switch (*cp) {
1931 		case '\\':
1932 			memmove(cp, cp + 1, strlen(cp + 1) + 1);
1933 			if (*cp == '\0')
1934 				return -1;
1935 			break;
1936 		case '/':
1937 			ispath = 1;
1938 			break;
1939 		case ':':
1940 			*cp++ = '\0';
1941 			goto done;
1942 		}
1943 	}
1944 done:
1945 	fwd->arg = *p;
1946 	fwd->ispath = ispath;
1947 	*p = cp;
1948 	return 0;
1949 }
1950 
1951 /*
1952  * parse_forward
1953  * parses a string containing a port forwarding specification of the form:
1954  *   dynamicfwd == 0
1955  *	[listenhost:]listenport|listenpath:connecthost:connectport|connectpath
1956  *	listenpath:connectpath
1957  *   dynamicfwd == 1
1958  *	[listenhost:]listenport
1959  * returns number of arguments parsed or zero on error
1960  */
1961 int
parse_forward(struct Forward * fwd,const char * fwdspec,int dynamicfwd,int remotefwd)1962 parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
1963 {
1964 	struct fwdarg fwdargs[4];
1965 	char *p, *cp;
1966 	int i;
1967 
1968 	memset(fwd, 0, sizeof(*fwd));
1969 	memset(fwdargs, 0, sizeof(fwdargs));
1970 
1971 	cp = p = xstrdup(fwdspec);
1972 
1973 	/* skip leading spaces */
1974 	while (isspace((u_char)*cp))
1975 		cp++;
1976 
1977 	for (i = 0; i < 4; ++i) {
1978 		if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
1979 			break;
1980 	}
1981 
1982 	/* Check for trailing garbage */
1983 	if (cp != NULL && *cp != '\0') {
1984 		i = 0;	/* failure */
1985 	}
1986 
1987 	switch (i) {
1988 	case 1:
1989 		if (fwdargs[0].ispath) {
1990 			fwd->listen_path = xstrdup(fwdargs[0].arg);
1991 			fwd->listen_port = PORT_STREAMLOCAL;
1992 		} else {
1993 			fwd->listen_host = NULL;
1994 			fwd->listen_port = a2port(fwdargs[0].arg);
1995 		}
1996 		fwd->connect_host = xstrdup("socks");
1997 		break;
1998 
1999 	case 2:
2000 		if (fwdargs[0].ispath && fwdargs[1].ispath) {
2001 			fwd->listen_path = xstrdup(fwdargs[0].arg);
2002 			fwd->listen_port = PORT_STREAMLOCAL;
2003 			fwd->connect_path = xstrdup(fwdargs[1].arg);
2004 			fwd->connect_port = PORT_STREAMLOCAL;
2005 		} else if (fwdargs[1].ispath) {
2006 			fwd->listen_host = NULL;
2007 			fwd->listen_port = a2port(fwdargs[0].arg);
2008 			fwd->connect_path = xstrdup(fwdargs[1].arg);
2009 			fwd->connect_port = PORT_STREAMLOCAL;
2010 		} else {
2011 			fwd->listen_host = xstrdup(fwdargs[0].arg);
2012 			fwd->listen_port = a2port(fwdargs[1].arg);
2013 			fwd->connect_host = xstrdup("socks");
2014 		}
2015 		break;
2016 
2017 	case 3:
2018 		if (fwdargs[0].ispath) {
2019 			fwd->listen_path = xstrdup(fwdargs[0].arg);
2020 			fwd->listen_port = PORT_STREAMLOCAL;
2021 			fwd->connect_host = xstrdup(fwdargs[1].arg);
2022 			fwd->connect_port = a2port(fwdargs[2].arg);
2023 		} else if (fwdargs[2].ispath) {
2024 			fwd->listen_host = xstrdup(fwdargs[0].arg);
2025 			fwd->listen_port = a2port(fwdargs[1].arg);
2026 			fwd->connect_path = xstrdup(fwdargs[2].arg);
2027 			fwd->connect_port = PORT_STREAMLOCAL;
2028 		} else {
2029 			fwd->listen_host = NULL;
2030 			fwd->listen_port = a2port(fwdargs[0].arg);
2031 			fwd->connect_host = xstrdup(fwdargs[1].arg);
2032 			fwd->connect_port = a2port(fwdargs[2].arg);
2033 		}
2034 		break;
2035 
2036 	case 4:
2037 		fwd->listen_host = xstrdup(fwdargs[0].arg);
2038 		fwd->listen_port = a2port(fwdargs[1].arg);
2039 		fwd->connect_host = xstrdup(fwdargs[2].arg);
2040 		fwd->connect_port = a2port(fwdargs[3].arg);
2041 		break;
2042 	default:
2043 		i = 0; /* failure */
2044 	}
2045 
2046 	free(p);
2047 
2048 	if (dynamicfwd) {
2049 		if (!(i == 1 || i == 2))
2050 			goto fail_free;
2051 	} else {
2052 		if (!(i == 3 || i == 4)) {
2053 			if (fwd->connect_path == NULL &&
2054 			    fwd->listen_path == NULL)
2055 				goto fail_free;
2056 		}
2057 		if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
2058 			goto fail_free;
2059 	}
2060 
2061 	if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
2062 	    (!remotefwd && fwd->listen_port == 0))
2063 		goto fail_free;
2064 	if (fwd->connect_host != NULL &&
2065 	    strlen(fwd->connect_host) >= NI_MAXHOST)
2066 		goto fail_free;
2067 	/* XXX - if connecting to a remote socket, max sun len may not match this host */
2068 	if (fwd->connect_path != NULL &&
2069 	    strlen(fwd->connect_path) >= PATH_MAX_SUN)
2070 		goto fail_free;
2071 	if (fwd->listen_host != NULL &&
2072 	    strlen(fwd->listen_host) >= NI_MAXHOST)
2073 		goto fail_free;
2074 	if (fwd->listen_path != NULL &&
2075 	    strlen(fwd->listen_path) >= PATH_MAX_SUN)
2076 		goto fail_free;
2077 
2078 	return (i);
2079 
2080  fail_free:
2081 	free(fwd->connect_host);
2082 	fwd->connect_host = NULL;
2083 	free(fwd->connect_path);
2084 	fwd->connect_path = NULL;
2085 	free(fwd->listen_host);
2086 	fwd->listen_host = NULL;
2087 	free(fwd->listen_path);
2088 	fwd->listen_path = NULL;
2089 	return (0);
2090 }
2091 
2092 /* XXX the following is a near-vebatim copy from servconf.c; refactor */
2093 static const char *
fmt_multistate_int(int val,const struct multistate * m)2094 fmt_multistate_int(int val, const struct multistate *m)
2095 {
2096 	u_int i;
2097 
2098 	for (i = 0; m[i].key != NULL; i++) {
2099 		if (m[i].value == val)
2100 			return m[i].key;
2101 	}
2102 	return "UNKNOWN";
2103 }
2104 
2105 static const char *
fmt_intarg(OpCodes code,int val)2106 fmt_intarg(OpCodes code, int val)
2107 {
2108 	if (val == -1)
2109 		return "unset";
2110 	switch (code) {
2111 	case oAddressFamily:
2112 		return fmt_multistate_int(val, multistate_addressfamily);
2113 	case oVerifyHostKeyDNS:
2114 	case oStrictHostKeyChecking:
2115 	case oUpdateHostkeys:
2116 		return fmt_multistate_int(val, multistate_yesnoask);
2117 	case oControlMaster:
2118 		return fmt_multistate_int(val, multistate_controlmaster);
2119 	case oTunnel:
2120 		return fmt_multistate_int(val, multistate_tunnel);
2121 	case oRequestTTY:
2122 		return fmt_multistate_int(val, multistate_requesttty);
2123 	case oCanonicalizeHostname:
2124 		return fmt_multistate_int(val, multistate_canonicalizehostname);
2125 	case oFingerprintHash:
2126 		return ssh_digest_alg_name(val);
2127 	case oProtocol:
2128 		switch (val) {
2129 		case SSH_PROTO_1:
2130 			return "1";
2131 		case SSH_PROTO_2:
2132 			return "2";
2133 		case (SSH_PROTO_1|SSH_PROTO_2):
2134 			return "2,1";
2135 		default:
2136 			return "UNKNOWN";
2137 		}
2138 	default:
2139 		switch (val) {
2140 		case 0:
2141 			return "no";
2142 		case 1:
2143 			return "yes";
2144 		default:
2145 			return "UNKNOWN";
2146 		}
2147 	}
2148 }
2149 
2150 static const char *
lookup_opcode_name(OpCodes code)2151 lookup_opcode_name(OpCodes code)
2152 {
2153 	u_int i;
2154 
2155 	for (i = 0; keywords[i].name != NULL; i++)
2156 		if (keywords[i].opcode == code)
2157 			return(keywords[i].name);
2158 	return "UNKNOWN";
2159 }
2160 
2161 static void
dump_cfg_int(OpCodes code,int val)2162 dump_cfg_int(OpCodes code, int val)
2163 {
2164 	printf("%s %d\n", lookup_opcode_name(code), val);
2165 }
2166 
2167 static void
dump_cfg_fmtint(OpCodes code,int val)2168 dump_cfg_fmtint(OpCodes code, int val)
2169 {
2170 	printf("%s %s\n", lookup_opcode_name(code), fmt_intarg(code, val));
2171 }
2172 
2173 static void
dump_cfg_string(OpCodes code,const char * val)2174 dump_cfg_string(OpCodes code, const char *val)
2175 {
2176 	if (val == NULL)
2177 		return;
2178 	printf("%s %s\n", lookup_opcode_name(code), val);
2179 }
2180 
2181 static void
dump_cfg_strarray(OpCodes code,u_int count,char ** vals)2182 dump_cfg_strarray(OpCodes code, u_int count, char **vals)
2183 {
2184 	u_int i;
2185 
2186 	for (i = 0; i < count; i++)
2187 		printf("%s %s\n", lookup_opcode_name(code), vals[i]);
2188 }
2189 
2190 static void
dump_cfg_strarray_oneline(OpCodes code,u_int count,char ** vals)2191 dump_cfg_strarray_oneline(OpCodes code, u_int count, char **vals)
2192 {
2193 	u_int i;
2194 
2195 	printf("%s", lookup_opcode_name(code));
2196 	for (i = 0; i < count; i++)
2197 		printf(" %s",  vals[i]);
2198 	printf("\n");
2199 }
2200 
2201 static void
dump_cfg_forwards(OpCodes code,u_int count,const struct Forward * fwds)2202 dump_cfg_forwards(OpCodes code, u_int count, const struct Forward *fwds)
2203 {
2204 	const struct Forward *fwd;
2205 	u_int i;
2206 
2207 	/* oDynamicForward */
2208 	for (i = 0; i < count; i++) {
2209 		fwd = &fwds[i];
2210 		if (code == oDynamicForward &&
2211 		    strcmp(fwd->connect_host, "socks") != 0)
2212 			continue;
2213 		if (code == oLocalForward &&
2214 		    strcmp(fwd->connect_host, "socks") == 0)
2215 			continue;
2216 		printf("%s", lookup_opcode_name(code));
2217 		if (fwd->listen_port == PORT_STREAMLOCAL)
2218 			printf(" %s", fwd->listen_path);
2219 		else if (fwd->listen_host == NULL)
2220 			printf(" %d", fwd->listen_port);
2221 		else {
2222 			printf(" [%s]:%d",
2223 			    fwd->listen_host, fwd->listen_port);
2224 		}
2225 		if (code != oDynamicForward) {
2226 			if (fwd->connect_port == PORT_STREAMLOCAL)
2227 				printf(" %s", fwd->connect_path);
2228 			else if (fwd->connect_host == NULL)
2229 				printf(" %d", fwd->connect_port);
2230 			else {
2231 				printf(" [%s]:%d",
2232 				    fwd->connect_host, fwd->connect_port);
2233 			}
2234 		}
2235 		printf("\n");
2236 	}
2237 }
2238 
2239 void
dump_client_config(Options * o,const char * host)2240 dump_client_config(Options *o, const char *host)
2241 {
2242 	int i;
2243 	char vbuf[5];
2244 
2245 	/* Most interesting options first: user, host, port */
2246 	dump_cfg_string(oUser, o->user);
2247 	dump_cfg_string(oHostName, host);
2248 	dump_cfg_int(oPort, o->port);
2249 
2250 	/* Flag options */
2251 	dump_cfg_fmtint(oAddressFamily, o->address_family);
2252 	dump_cfg_fmtint(oBatchMode, o->batch_mode);
2253 	dump_cfg_fmtint(oCanonicalizeFallbackLocal, o->canonicalize_fallback_local);
2254 	dump_cfg_fmtint(oCanonicalizeHostname, o->canonicalize_hostname);
2255 	dump_cfg_fmtint(oChallengeResponseAuthentication, o->challenge_response_authentication);
2256 	dump_cfg_fmtint(oCheckHostIP, o->check_host_ip);
2257 	dump_cfg_fmtint(oCompression, o->compression);
2258 	dump_cfg_fmtint(oControlMaster, o->control_master);
2259 	dump_cfg_fmtint(oEnableSSHKeysign, o->enable_ssh_keysign);
2260 	dump_cfg_fmtint(oExitOnForwardFailure, o->exit_on_forward_failure);
2261 	dump_cfg_fmtint(oFingerprintHash, o->fingerprint_hash);
2262 	dump_cfg_fmtint(oForwardAgent, o->forward_agent);
2263 	dump_cfg_fmtint(oForwardX11, o->forward_x11);
2264 	dump_cfg_fmtint(oForwardX11Trusted, o->forward_x11_trusted);
2265 	dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
2266 #ifdef GSSAPI
2267 	dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
2268 	dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
2269 #endif /* GSSAPI */
2270 	dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
2271 	dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
2272 	dump_cfg_fmtint(oIdentitiesOnly, o->identities_only);
2273 	dump_cfg_fmtint(oKbdInteractiveAuthentication, o->kbd_interactive_authentication);
2274 	dump_cfg_fmtint(oNoHostAuthenticationForLocalhost, o->no_host_authentication_for_localhost);
2275 	dump_cfg_fmtint(oPasswordAuthentication, o->password_authentication);
2276 	dump_cfg_fmtint(oPermitLocalCommand, o->permit_local_command);
2277 	dump_cfg_fmtint(oProtocol, o->protocol);
2278 	dump_cfg_fmtint(oProxyUseFdpass, o->proxy_use_fdpass);
2279 	dump_cfg_fmtint(oPubkeyAuthentication, o->pubkey_authentication);
2280 	dump_cfg_fmtint(oRequestTTY, o->request_tty);
2281 	dump_cfg_fmtint(oRhostsRSAAuthentication, o->rhosts_rsa_authentication);
2282 	dump_cfg_fmtint(oRSAAuthentication, o->rsa_authentication);
2283 	dump_cfg_fmtint(oStreamLocalBindUnlink, o->fwd_opts.streamlocal_bind_unlink);
2284 	dump_cfg_fmtint(oStrictHostKeyChecking, o->strict_host_key_checking);
2285 	dump_cfg_fmtint(oTCPKeepAlive, o->tcp_keep_alive);
2286 	dump_cfg_fmtint(oTunnel, o->tun_open);
2287 	dump_cfg_fmtint(oUsePrivilegedPort, o->use_privileged_port);
2288 	dump_cfg_fmtint(oVerifyHostKeyDNS, o->verify_host_key_dns);
2289 	dump_cfg_fmtint(oVisualHostKey, o->visual_host_key);
2290 	dump_cfg_fmtint(oUpdateHostkeys, o->update_hostkeys);
2291 
2292 	/* Integer options */
2293 	dump_cfg_int(oCanonicalizeMaxDots, o->canonicalize_max_dots);
2294 	dump_cfg_int(oCompressionLevel, o->compression_level);
2295 	dump_cfg_int(oConnectionAttempts, o->connection_attempts);
2296 	dump_cfg_int(oForwardX11Timeout, o->forward_x11_timeout);
2297 	dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
2298 	dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
2299 	dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
2300 
2301 	/* String options */
2302 	dump_cfg_string(oBindAddress, o->bind_address);
2303 	dump_cfg_string(oCiphers, o->ciphers ? o->ciphers : KEX_CLIENT_ENCRYPT);
2304 	dump_cfg_string(oControlPath, o->control_path);
2305 	dump_cfg_string(oHostKeyAlgorithms, o->hostkeyalgorithms ? o->hostkeyalgorithms : KEX_DEFAULT_PK_ALG);
2306 	dump_cfg_string(oHostKeyAlias, o->host_key_alias);
2307 	dump_cfg_string(oHostbasedKeyTypes, o->hostbased_key_types);
2308 	dump_cfg_string(oKbdInteractiveDevices, o->kbd_interactive_devices);
2309 	dump_cfg_string(oKexAlgorithms, o->kex_algorithms ? o->kex_algorithms : KEX_CLIENT_KEX);
2310 	dump_cfg_string(oLocalCommand, o->local_command);
2311 	dump_cfg_string(oLogLevel, log_level_name(o->log_level));
2312 	dump_cfg_string(oMacs, o->macs ? o->macs : KEX_CLIENT_MAC);
2313 	dump_cfg_string(oPKCS11Provider, o->pkcs11_provider);
2314 	dump_cfg_string(oPreferredAuthentications, o->preferred_authentications);
2315 	dump_cfg_string(oProxyCommand, o->proxy_command);
2316 	dump_cfg_string(oRevokedHostKeys, o->revoked_host_keys);
2317 	dump_cfg_string(oXAuthLocation, o->xauth_location);
2318 
2319 	/* Forwards */
2320 	dump_cfg_forwards(oDynamicForward, o->num_local_forwards, o->local_forwards);
2321 	dump_cfg_forwards(oLocalForward, o->num_local_forwards, o->local_forwards);
2322 	dump_cfg_forwards(oRemoteForward, o->num_remote_forwards, o->remote_forwards);
2323 
2324 	/* String array options */
2325 	dump_cfg_strarray(oIdentityFile, o->num_identity_files, o->identity_files);
2326 	dump_cfg_strarray_oneline(oCanonicalDomains, o->num_canonical_domains, o->canonical_domains);
2327 	dump_cfg_strarray_oneline(oGlobalKnownHostsFile, o->num_system_hostfiles, o->system_hostfiles);
2328 	dump_cfg_strarray_oneline(oUserKnownHostsFile, o->num_user_hostfiles, o->user_hostfiles);
2329 	dump_cfg_strarray(oSendEnv, o->num_send_env, o->send_env);
2330 
2331 	/* Special cases */
2332 
2333 	/* oConnectTimeout */
2334 	if (o->connection_timeout == -1)
2335 		printf("connecttimeout none\n");
2336 	else
2337 		dump_cfg_int(oConnectTimeout, o->connection_timeout);
2338 
2339 	/* oTunnelDevice */
2340 	printf("tunneldevice");
2341 	if (o->tun_local == SSH_TUNID_ANY)
2342 		printf(" any");
2343 	else
2344 		printf(" %d", o->tun_local);
2345 	if (o->tun_remote == SSH_TUNID_ANY)
2346 		printf(":any");
2347 	else
2348 		printf(":%d", o->tun_remote);
2349 	printf("\n");
2350 
2351 	/* oCanonicalizePermittedCNAMEs */
2352 	if ( o->num_permitted_cnames > 0) {
2353 		printf("canonicalizePermittedcnames");
2354 		for (i = 0; i < o->num_permitted_cnames; i++) {
2355 			printf(" %s:%s", o->permitted_cnames[i].source_list,
2356 			    o->permitted_cnames[i].target_list);
2357 		}
2358 		printf("\n");
2359 	}
2360 
2361 	/* oCipher */
2362 	if (o->cipher != SSH_CIPHER_NOT_SET)
2363 		printf("Cipher %s\n", cipher_name(o->cipher));
2364 
2365 	/* oControlPersist */
2366 	if (o->control_persist == 0 || o->control_persist_timeout == 0)
2367 		dump_cfg_fmtint(oControlPersist, o->control_persist);
2368 	else
2369 		dump_cfg_int(oControlPersist, o->control_persist_timeout);
2370 
2371 	/* oEscapeChar */
2372 	if (o->escape_char == SSH_ESCAPECHAR_NONE)
2373 		printf("escapechar none\n");
2374 	else {
2375 		vis(vbuf, o->escape_char, VIS_WHITE, 0);
2376 		printf("escapechar %s\n", vbuf);
2377 	}
2378 
2379 	/* oIPQoS */
2380 	printf("ipqos %s ", iptos2str(o->ip_qos_interactive));
2381 	printf("%s\n", iptos2str(o->ip_qos_bulk));
2382 
2383 	/* oRekeyLimit */
2384 	printf("rekeylimit %lld %d\n",
2385 	    (long long)o->rekey_limit, o->rekey_interval);
2386 
2387 	/* oStreamLocalBindMask */
2388 	printf("streamlocalbindmask 0%o\n",
2389 	    o->fwd_opts.streamlocal_bind_mask);
2390 }
2391