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