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