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