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