xref: /freebsd/crypto/openssh/readconf.c (revision dda5b39711dab90ae1c5624bdd6ff7453177df31)
1 /* $OpenBSD: readconf.c,v 1.215 2013/12/06 13:39:49 markus Exp $ */
2 /* $FreeBSD$ */
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$");
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 
127 typedef 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 
165 static 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 
297 void
298 add_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 
334 void
335 add_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 
352 static void
353 clear_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 
378 void
379 add_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 
398 int
399 default_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  */
415 static int
416 execute_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  */
488 static int
489 match_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 */
605 static void
606 valid_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  */
635 static OpCodes
636 parse_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 */
653 struct multistate {
654 	char *key;
655 	int value;
656 };
657 static const struct multistate multistate_flag[] = {
658 	{ "true",			1 },
659 	{ "false",			0 },
660 	{ "yes",			1 },
661 	{ "no",				0 },
662 	{ NULL, -1 }
663 };
664 static const struct multistate multistate_yesnoask[] = {
665 	{ "true",			1 },
666 	{ "false",			0 },
667 	{ "yes",			1 },
668 	{ "no",				0 },
669 	{ "ask",			2 },
670 	{ NULL, -1 }
671 };
672 static const struct multistate multistate_addressfamily[] = {
673 	{ "inet",			AF_INET },
674 	{ "inet6",			AF_INET6 },
675 	{ "any",			AF_UNSPEC },
676 	{ NULL, -1 }
677 };
678 static 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 };
688 static 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 };
697 static 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 };
706 static 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"
720 int
721 process_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;
773 parse_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;
964 parse_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;
977 parse_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;
1017 parse_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;
1027 parse_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 
1511 int
1512 read_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 
1562 void
1563 initialize_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 
1666 void
1667 fill_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  */
1883 int
1884 parse_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