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