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