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