xref: /freebsd/crypto/openssh/readconf.c (revision a3cf0ef5a295c885c895fabfd56470c0d1db322d)
1 /* $OpenBSD: readconf.c,v 1.187 2010/07/19 09:15:12 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 
23 #include <netinet/in.h>
24 
25 #include <ctype.h>
26 #include <errno.h>
27 #include <netdb.h>
28 #include <signal.h>
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <unistd.h>
33 
34 #include "xmalloc.h"
35 #include "ssh.h"
36 #include "compat.h"
37 #include "cipher.h"
38 #include "pathnames.h"
39 #include "log.h"
40 #include "key.h"
41 #include "readconf.h"
42 #include "match.h"
43 #include "misc.h"
44 #include "buffer.h"
45 #include "kex.h"
46 #include "mac.h"
47 #include "version.h"
48 
49 /* Format of the configuration file:
50 
51    # Configuration data is parsed as follows:
52    #  1. command line options
53    #  2. user-specific file
54    #  3. system-wide file
55    # Any configuration value is only changed the first time it is set.
56    # Thus, host-specific definitions should be at the beginning of the
57    # configuration file, and defaults at the end.
58 
59    # Host-specific declarations.  These may override anything above.  A single
60    # host may match multiple declarations; these are processed in the order
61    # that they are given in.
62 
63    Host *.ngs.fi ngs.fi
64      User foo
65 
66    Host fake.com
67      HostName another.host.name.real.org
68      User blaah
69      Port 34289
70      ForwardX11 no
71      ForwardAgent no
72 
73    Host books.com
74      RemoteForward 9999 shadows.cs.hut.fi:9999
75      Cipher 3des
76 
77    Host fascist.blob.com
78      Port 23123
79      User tylonen
80      PasswordAuthentication no
81 
82    Host puukko.hut.fi
83      User t35124p
84      ProxyCommand ssh-proxy %h %p
85 
86    Host *.fr
87      PublicKeyAuthentication no
88 
89    Host *.su
90      Cipher none
91      PasswordAuthentication no
92 
93    Host vpn.fake.com
94      Tunnel yes
95      TunnelDevice 3
96 
97    # Defaults for various options
98    Host *
99      ForwardAgent no
100      ForwardX11 no
101      PasswordAuthentication yes
102      RSAAuthentication yes
103      RhostsRSAAuthentication yes
104      StrictHostKeyChecking yes
105      TcpKeepAlive no
106      IdentityFile ~/.ssh/identity
107      Port 22
108      EscapeChar ~
109 
110 */
111 
112 /* Keyword tokens. */
113 
114 typedef enum {
115 	oBadOption,
116 	oForwardAgent, oForwardX11, oForwardX11Trusted, oForwardX11Timeout,
117 	oGatewayPorts, oExitOnForwardFailure,
118 	oPasswordAuthentication, oRSAAuthentication,
119 	oChallengeResponseAuthentication, oXAuthLocation,
120 	oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
121 	oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
122 	oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
123 	oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
124 	oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
125 	oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
126 	oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
127 	oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
128 	oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
129 	oHostKeyAlgorithms, oBindAddress, oPKCS11Provider,
130 	oClearAllForwardings, oNoHostAuthenticationForLocalhost,
131 	oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
132 	oAddressFamily, oGssAuthentication, oGssDelegateCreds,
133 	oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
134 	oSendEnv, oControlPath, oControlMaster, oControlPersist,
135 	oHashKnownHosts,
136 	oTunnel, oTunnelDevice, oLocalCommand, oPermitLocalCommand,
137 	oVisualHostKey, oUseRoaming, oZeroKnowledgePasswordAuthentication,
138 	oVersionAddendum,
139 	oDeprecated, oUnsupported
140 } OpCodes;
141 
142 /* Textual representations of the tokens. */
143 
144 static struct {
145 	const char *name;
146 	OpCodes opcode;
147 } keywords[] = {
148 	{ "forwardagent", oForwardAgent },
149 	{ "forwardx11", oForwardX11 },
150 	{ "forwardx11trusted", oForwardX11Trusted },
151 	{ "forwardx11timeout", oForwardX11Timeout },
152 	{ "exitonforwardfailure", oExitOnForwardFailure },
153 	{ "xauthlocation", oXAuthLocation },
154 	{ "gatewayports", oGatewayPorts },
155 	{ "useprivilegedport", oUsePrivilegedPort },
156 	{ "rhostsauthentication", oDeprecated },
157 	{ "passwordauthentication", oPasswordAuthentication },
158 	{ "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
159 	{ "kbdinteractivedevices", oKbdInteractiveDevices },
160 	{ "rsaauthentication", oRSAAuthentication },
161 	{ "pubkeyauthentication", oPubkeyAuthentication },
162 	{ "dsaauthentication", oPubkeyAuthentication },		    /* alias */
163 	{ "rhostsrsaauthentication", oRhostsRSAAuthentication },
164 	{ "hostbasedauthentication", oHostbasedAuthentication },
165 	{ "challengeresponseauthentication", oChallengeResponseAuthentication },
166 	{ "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
167 	{ "tisauthentication", oChallengeResponseAuthentication },  /* alias */
168 	{ "kerberosauthentication", oUnsupported },
169 	{ "kerberostgtpassing", oUnsupported },
170 	{ "afstokenpassing", oUnsupported },
171 #if defined(GSSAPI)
172 	{ "gssapiauthentication", oGssAuthentication },
173 	{ "gssapidelegatecredentials", oGssDelegateCreds },
174 #else
175 	{ "gssapiauthentication", oUnsupported },
176 	{ "gssapidelegatecredentials", oUnsupported },
177 #endif
178 	{ "fallbacktorsh", oDeprecated },
179 	{ "usersh", oDeprecated },
180 	{ "identityfile", oIdentityFile },
181 	{ "identityfile2", oIdentityFile },			/* obsolete */
182 	{ "identitiesonly", oIdentitiesOnly },
183 	{ "hostname", oHostName },
184 	{ "hostkeyalias", oHostKeyAlias },
185 	{ "proxycommand", oProxyCommand },
186 	{ "port", oPort },
187 	{ "cipher", oCipher },
188 	{ "ciphers", oCiphers },
189 	{ "macs", oMacs },
190 	{ "protocol", oProtocol },
191 	{ "remoteforward", oRemoteForward },
192 	{ "localforward", oLocalForward },
193 	{ "user", oUser },
194 	{ "host", oHost },
195 	{ "escapechar", oEscapeChar },
196 	{ "globalknownhostsfile", oGlobalKnownHostsFile },
197 	{ "globalknownhostsfile2", oGlobalKnownHostsFile2 },	/* obsolete */
198 	{ "userknownhostsfile", oUserKnownHostsFile },
199 	{ "userknownhostsfile2", oUserKnownHostsFile2 },	/* obsolete */
200 	{ "connectionattempts", oConnectionAttempts },
201 	{ "batchmode", oBatchMode },
202 	{ "checkhostip", oCheckHostIP },
203 	{ "stricthostkeychecking", oStrictHostKeyChecking },
204 	{ "compression", oCompression },
205 	{ "compressionlevel", oCompressionLevel },
206 	{ "tcpkeepalive", oTCPKeepAlive },
207 	{ "keepalive", oTCPKeepAlive },				/* obsolete */
208 	{ "numberofpasswordprompts", oNumberOfPasswordPrompts },
209 	{ "loglevel", oLogLevel },
210 	{ "dynamicforward", oDynamicForward },
211 	{ "preferredauthentications", oPreferredAuthentications },
212 	{ "hostkeyalgorithms", oHostKeyAlgorithms },
213 	{ "bindaddress", oBindAddress },
214 #ifdef ENABLE_PKCS11
215 	{ "smartcarddevice", oPKCS11Provider },
216 	{ "pkcs11provider", oPKCS11Provider },
217 #else
218 	{ "smartcarddevice", oUnsupported },
219 	{ "pkcs11provider", oUnsupported },
220 #endif
221 	{ "clearallforwardings", oClearAllForwardings },
222 	{ "enablesshkeysign", oEnableSSHKeysign },
223 	{ "verifyhostkeydns", oVerifyHostKeyDNS },
224 	{ "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
225 	{ "rekeylimit", oRekeyLimit },
226 	{ "connecttimeout", oConnectTimeout },
227 	{ "addressfamily", oAddressFamily },
228 	{ "serveraliveinterval", oServerAliveInterval },
229 	{ "serveralivecountmax", oServerAliveCountMax },
230 	{ "sendenv", oSendEnv },
231 	{ "controlpath", oControlPath },
232 	{ "controlmaster", oControlMaster },
233 	{ "controlpersist", oControlPersist },
234 	{ "hashknownhosts", oHashKnownHosts },
235 	{ "tunnel", oTunnel },
236 	{ "tunneldevice", oTunnelDevice },
237 	{ "localcommand", oLocalCommand },
238 	{ "permitlocalcommand", oPermitLocalCommand },
239 	{ "visualhostkey", oVisualHostKey },
240 	{ "useroaming", oUseRoaming },
241 #ifdef JPAKE
242 	{ "zeroknowledgepasswordauthentication",
243 	    oZeroKnowledgePasswordAuthentication },
244 #else
245 	{ "zeroknowledgepasswordauthentication", oUnsupported },
246 #endif
247 
248 	{ "versionaddendum", oVersionAddendum },
249 	{ NULL, oBadOption }
250 };
251 
252 /*
253  * Adds a local TCP/IP port forward to options.  Never returns if there is an
254  * error.
255  */
256 
257 void
258 add_local_forward(Options *options, const Forward *newfwd)
259 {
260 	Forward *fwd;
261 #ifndef NO_IPPORT_RESERVED_CONCEPT
262 	extern uid_t original_real_uid;
263 	int ipport_reserved;
264 #ifdef __FreeBSD__
265 	size_t len_ipport_reserved = sizeof(ipport_reserved);
266 
267 	if (sysctlbyname("net.inet.ip.portrange.reservedhigh",
268 	    &ipport_reserved, &len_ipport_reserved, NULL, 0) != 0)
269 		ipport_reserved = IPPORT_RESERVED;
270 	else
271 		ipport_reserved++;
272 #else
273 	ipport_reserved = IPPORT_RESERVED;
274 #endif
275 	if (newfwd->listen_port < ipport_reserved && original_real_uid != 0)
276 		fatal("Privileged ports can only be forwarded by root.");
277 #endif
278 	options->local_forwards = xrealloc(options->local_forwards,
279 	    options->num_local_forwards + 1,
280 	    sizeof(*options->local_forwards));
281 	fwd = &options->local_forwards[options->num_local_forwards++];
282 
283 	fwd->listen_host = newfwd->listen_host;
284 	fwd->listen_port = newfwd->listen_port;
285 	fwd->connect_host = newfwd->connect_host;
286 	fwd->connect_port = newfwd->connect_port;
287 }
288 
289 /*
290  * Adds a remote TCP/IP port forward to options.  Never returns if there is
291  * an error.
292  */
293 
294 void
295 add_remote_forward(Options *options, const Forward *newfwd)
296 {
297 	Forward *fwd;
298 
299 	options->remote_forwards = xrealloc(options->remote_forwards,
300 	    options->num_remote_forwards + 1,
301 	    sizeof(*options->remote_forwards));
302 	fwd = &options->remote_forwards[options->num_remote_forwards++];
303 
304 	fwd->listen_host = newfwd->listen_host;
305 	fwd->listen_port = newfwd->listen_port;
306 	fwd->connect_host = newfwd->connect_host;
307 	fwd->connect_port = newfwd->connect_port;
308 	fwd->allocated_port = 0;
309 }
310 
311 static void
312 clear_forwardings(Options *options)
313 {
314 	int i;
315 
316 	for (i = 0; i < options->num_local_forwards; i++) {
317 		if (options->local_forwards[i].listen_host != NULL)
318 			xfree(options->local_forwards[i].listen_host);
319 		xfree(options->local_forwards[i].connect_host);
320 	}
321 	if (options->num_local_forwards > 0) {
322 		xfree(options->local_forwards);
323 		options->local_forwards = NULL;
324 	}
325 	options->num_local_forwards = 0;
326 	for (i = 0; i < options->num_remote_forwards; i++) {
327 		if (options->remote_forwards[i].listen_host != NULL)
328 			xfree(options->remote_forwards[i].listen_host);
329 		xfree(options->remote_forwards[i].connect_host);
330 	}
331 	if (options->num_remote_forwards > 0) {
332 		xfree(options->remote_forwards);
333 		options->remote_forwards = NULL;
334 	}
335 	options->num_remote_forwards = 0;
336 	options->tun_open = SSH_TUNMODE_NO;
337 }
338 
339 /*
340  * Returns the number of the token pointed to by cp or oBadOption.
341  */
342 
343 static OpCodes
344 parse_token(const char *cp, const char *filename, int linenum)
345 {
346 	u_int i;
347 
348 	for (i = 0; keywords[i].name; i++)
349 		if (strcasecmp(cp, keywords[i].name) == 0)
350 			return keywords[i].opcode;
351 
352 	error("%s: line %d: Bad configuration option: %s",
353 	    filename, linenum, cp);
354 	return oBadOption;
355 }
356 
357 /*
358  * Processes a single option line as used in the configuration files. This
359  * only sets those values that have not already been set.
360  */
361 #define WHITESPACE " \t\r\n"
362 
363 int
364 process_config_line(Options *options, const char *host,
365 		    char *line, const char *filename, int linenum,
366 		    int *activep)
367 {
368 	char *s, **charptr, *endofnumber, *keyword, *arg, *arg2, fwdarg[256];
369 	int opcode, *intptr, value, value2, scale;
370 	LogLevel *log_level_ptr;
371 	long long orig, val64;
372 	size_t len;
373 	Forward fwd;
374 
375 	/* Strip trailing whitespace */
376 	for (len = strlen(line) - 1; len > 0; len--) {
377 		if (strchr(WHITESPACE, line[len]) == NULL)
378 			break;
379 		line[len] = '\0';
380 	}
381 
382 	s = line;
383 	/* Get the keyword. (Each line is supposed to begin with a keyword). */
384 	if ((keyword = strdelim(&s)) == NULL)
385 		return 0;
386 	/* Ignore leading whitespace. */
387 	if (*keyword == '\0')
388 		keyword = strdelim(&s);
389 	if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
390 		return 0;
391 
392 	opcode = parse_token(keyword, filename, linenum);
393 
394 	switch (opcode) {
395 	case oBadOption:
396 		/* don't panic, but count bad options */
397 		return -1;
398 		/* NOTREACHED */
399 	case oConnectTimeout:
400 		intptr = &options->connection_timeout;
401 parse_time:
402 		arg = strdelim(&s);
403 		if (!arg || *arg == '\0')
404 			fatal("%s line %d: missing time value.",
405 			    filename, linenum);
406 		if ((value = convtime(arg)) == -1)
407 			fatal("%s line %d: invalid time value.",
408 			    filename, linenum);
409 		if (*activep && *intptr == -1)
410 			*intptr = value;
411 		break;
412 
413 	case oForwardAgent:
414 		intptr = &options->forward_agent;
415 parse_flag:
416 		arg = strdelim(&s);
417 		if (!arg || *arg == '\0')
418 			fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
419 		value = 0;	/* To avoid compiler warning... */
420 		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
421 			value = 1;
422 		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
423 			value = 0;
424 		else
425 			fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
426 		if (*activep && *intptr == -1)
427 			*intptr = value;
428 		break;
429 
430 	case oForwardX11:
431 		intptr = &options->forward_x11;
432 		goto parse_flag;
433 
434 	case oForwardX11Trusted:
435 		intptr = &options->forward_x11_trusted;
436 		goto parse_flag;
437 
438 	case oForwardX11Timeout:
439 		intptr = &options->forward_x11_timeout;
440 		goto parse_time;
441 
442 	case oGatewayPorts:
443 		intptr = &options->gateway_ports;
444 		goto parse_flag;
445 
446 	case oExitOnForwardFailure:
447 		intptr = &options->exit_on_forward_failure;
448 		goto parse_flag;
449 
450 	case oUsePrivilegedPort:
451 		intptr = &options->use_privileged_port;
452 		goto parse_flag;
453 
454 	case oPasswordAuthentication:
455 		intptr = &options->password_authentication;
456 		goto parse_flag;
457 
458 	case oZeroKnowledgePasswordAuthentication:
459 		intptr = &options->zero_knowledge_password_authentication;
460 		goto parse_flag;
461 
462 	case oKbdInteractiveAuthentication:
463 		intptr = &options->kbd_interactive_authentication;
464 		goto parse_flag;
465 
466 	case oKbdInteractiveDevices:
467 		charptr = &options->kbd_interactive_devices;
468 		goto parse_string;
469 
470 	case oPubkeyAuthentication:
471 		intptr = &options->pubkey_authentication;
472 		goto parse_flag;
473 
474 	case oRSAAuthentication:
475 		intptr = &options->rsa_authentication;
476 		goto parse_flag;
477 
478 	case oRhostsRSAAuthentication:
479 		intptr = &options->rhosts_rsa_authentication;
480 		goto parse_flag;
481 
482 	case oHostbasedAuthentication:
483 		intptr = &options->hostbased_authentication;
484 		goto parse_flag;
485 
486 	case oChallengeResponseAuthentication:
487 		intptr = &options->challenge_response_authentication;
488 		goto parse_flag;
489 
490 	case oGssAuthentication:
491 		intptr = &options->gss_authentication;
492 		goto parse_flag;
493 
494 	case oGssDelegateCreds:
495 		intptr = &options->gss_deleg_creds;
496 		goto parse_flag;
497 
498 	case oBatchMode:
499 		intptr = &options->batch_mode;
500 		goto parse_flag;
501 
502 	case oCheckHostIP:
503 		intptr = &options->check_host_ip;
504 		goto parse_flag;
505 
506 	case oVerifyHostKeyDNS:
507 		intptr = &options->verify_host_key_dns;
508 		goto parse_yesnoask;
509 
510 	case oStrictHostKeyChecking:
511 		intptr = &options->strict_host_key_checking;
512 parse_yesnoask:
513 		arg = strdelim(&s);
514 		if (!arg || *arg == '\0')
515 			fatal("%.200s line %d: Missing yes/no/ask argument.",
516 			    filename, linenum);
517 		value = 0;	/* To avoid compiler warning... */
518 		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
519 			value = 1;
520 		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
521 			value = 0;
522 		else if (strcmp(arg, "ask") == 0)
523 			value = 2;
524 		else
525 			fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
526 		if (*activep && *intptr == -1)
527 			*intptr = value;
528 		break;
529 
530 	case oCompression:
531 		intptr = &options->compression;
532 		goto parse_flag;
533 
534 	case oTCPKeepAlive:
535 		intptr = &options->tcp_keep_alive;
536 		goto parse_flag;
537 
538 	case oNoHostAuthenticationForLocalhost:
539 		intptr = &options->no_host_authentication_for_localhost;
540 		goto parse_flag;
541 
542 	case oNumberOfPasswordPrompts:
543 		intptr = &options->number_of_password_prompts;
544 		goto parse_int;
545 
546 	case oCompressionLevel:
547 		intptr = &options->compression_level;
548 		goto parse_int;
549 
550 	case oRekeyLimit:
551 		arg = strdelim(&s);
552 		if (!arg || *arg == '\0')
553 			fatal("%.200s line %d: Missing argument.", filename, linenum);
554 		if (arg[0] < '0' || arg[0] > '9')
555 			fatal("%.200s line %d: Bad number.", filename, linenum);
556 		orig = val64 = strtoll(arg, &endofnumber, 10);
557 		if (arg == endofnumber)
558 			fatal("%.200s line %d: Bad number.", filename, linenum);
559 		switch (toupper(*endofnumber)) {
560 		case '\0':
561 			scale = 1;
562 			break;
563 		case 'K':
564 			scale = 1<<10;
565 			break;
566 		case 'M':
567 			scale = 1<<20;
568 			break;
569 		case 'G':
570 			scale = 1<<30;
571 			break;
572 		default:
573 			fatal("%.200s line %d: Invalid RekeyLimit suffix",
574 			    filename, linenum);
575 		}
576 		val64 *= scale;
577 		/* detect integer wrap and too-large limits */
578 		if ((val64 / scale) != orig || val64 > UINT_MAX)
579 			fatal("%.200s line %d: RekeyLimit too large",
580 			    filename, linenum);
581 		if (val64 < 16)
582 			fatal("%.200s line %d: RekeyLimit too small",
583 			    filename, linenum);
584 		if (*activep && options->rekey_limit == -1)
585 			options->rekey_limit = (u_int32_t)val64;
586 		break;
587 
588 	case oIdentityFile:
589 		arg = strdelim(&s);
590 		if (!arg || *arg == '\0')
591 			fatal("%.200s line %d: Missing argument.", filename, linenum);
592 		if (*activep) {
593 			intptr = &options->num_identity_files;
594 			if (*intptr >= SSH_MAX_IDENTITY_FILES)
595 				fatal("%.200s line %d: Too many identity files specified (max %d).",
596 				    filename, linenum, SSH_MAX_IDENTITY_FILES);
597 			charptr = &options->identity_files[*intptr];
598 			*charptr = xstrdup(arg);
599 			*intptr = *intptr + 1;
600 		}
601 		break;
602 
603 	case oXAuthLocation:
604 		charptr=&options->xauth_location;
605 		goto parse_string;
606 
607 	case oUser:
608 		charptr = &options->user;
609 parse_string:
610 		arg = strdelim(&s);
611 		if (!arg || *arg == '\0')
612 			fatal("%.200s line %d: Missing argument.", filename, linenum);
613 		if (*activep && *charptr == NULL)
614 			*charptr = xstrdup(arg);
615 		break;
616 
617 	case oGlobalKnownHostsFile:
618 		charptr = &options->system_hostfile;
619 		goto parse_string;
620 
621 	case oUserKnownHostsFile:
622 		charptr = &options->user_hostfile;
623 		goto parse_string;
624 
625 	case oGlobalKnownHostsFile2:
626 		charptr = &options->system_hostfile2;
627 		goto parse_string;
628 
629 	case oUserKnownHostsFile2:
630 		charptr = &options->user_hostfile2;
631 		goto parse_string;
632 
633 	case oHostName:
634 		charptr = &options->hostname;
635 		goto parse_string;
636 
637 	case oHostKeyAlias:
638 		charptr = &options->host_key_alias;
639 		goto parse_string;
640 
641 	case oPreferredAuthentications:
642 		charptr = &options->preferred_authentications;
643 		goto parse_string;
644 
645 	case oBindAddress:
646 		charptr = &options->bind_address;
647 		goto parse_string;
648 
649 	case oPKCS11Provider:
650 		charptr = &options->pkcs11_provider;
651 		goto parse_string;
652 
653 	case oProxyCommand:
654 		charptr = &options->proxy_command;
655 parse_command:
656 		if (s == NULL)
657 			fatal("%.200s line %d: Missing argument.", filename, linenum);
658 		len = strspn(s, WHITESPACE "=");
659 		if (*activep && *charptr == NULL)
660 			*charptr = xstrdup(s + len);
661 		return 0;
662 
663 	case oPort:
664 		intptr = &options->port;
665 parse_int:
666 		arg = strdelim(&s);
667 		if (!arg || *arg == '\0')
668 			fatal("%.200s line %d: Missing argument.", filename, linenum);
669 		if (arg[0] < '0' || arg[0] > '9')
670 			fatal("%.200s line %d: Bad number.", filename, linenum);
671 
672 		/* Octal, decimal, or hex format? */
673 		value = strtol(arg, &endofnumber, 0);
674 		if (arg == endofnumber)
675 			fatal("%.200s line %d: Bad number.", filename, linenum);
676 		if (*activep && *intptr == -1)
677 			*intptr = value;
678 		break;
679 
680 	case oConnectionAttempts:
681 		intptr = &options->connection_attempts;
682 		goto parse_int;
683 
684 	case oCipher:
685 		intptr = &options->cipher;
686 		arg = strdelim(&s);
687 		if (!arg || *arg == '\0')
688 			fatal("%.200s line %d: Missing argument.", filename, linenum);
689 		value = cipher_number(arg);
690 		if (value == -1)
691 			fatal("%.200s line %d: Bad cipher '%s'.",
692 			    filename, linenum, arg ? arg : "<NONE>");
693 		if (*activep && *intptr == -1)
694 			*intptr = value;
695 		break;
696 
697 	case oCiphers:
698 		arg = strdelim(&s);
699 		if (!arg || *arg == '\0')
700 			fatal("%.200s line %d: Missing argument.", filename, linenum);
701 		if (!ciphers_valid(arg))
702 			fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
703 			    filename, linenum, arg ? arg : "<NONE>");
704 		if (*activep && options->ciphers == NULL)
705 			options->ciphers = xstrdup(arg);
706 		break;
707 
708 	case oMacs:
709 		arg = strdelim(&s);
710 		if (!arg || *arg == '\0')
711 			fatal("%.200s line %d: Missing argument.", filename, linenum);
712 		if (!mac_valid(arg))
713 			fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
714 			    filename, linenum, arg ? arg : "<NONE>");
715 		if (*activep && options->macs == NULL)
716 			options->macs = xstrdup(arg);
717 		break;
718 
719 	case oHostKeyAlgorithms:
720 		arg = strdelim(&s);
721 		if (!arg || *arg == '\0')
722 			fatal("%.200s line %d: Missing argument.", filename, linenum);
723 		if (!key_names_valid2(arg))
724 			fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
725 			    filename, linenum, arg ? arg : "<NONE>");
726 		if (*activep && options->hostkeyalgorithms == NULL)
727 			options->hostkeyalgorithms = xstrdup(arg);
728 		break;
729 
730 	case oProtocol:
731 		intptr = &options->protocol;
732 		arg = strdelim(&s);
733 		if (!arg || *arg == '\0')
734 			fatal("%.200s line %d: Missing argument.", filename, linenum);
735 		value = proto_spec(arg);
736 		if (value == SSH_PROTO_UNKNOWN)
737 			fatal("%.200s line %d: Bad protocol spec '%s'.",
738 			    filename, linenum, arg ? arg : "<NONE>");
739 		if (*activep && *intptr == SSH_PROTO_UNKNOWN)
740 			*intptr = value;
741 		break;
742 
743 	case oLogLevel:
744 		log_level_ptr = &options->log_level;
745 		arg = strdelim(&s);
746 		value = log_level_number(arg);
747 		if (value == SYSLOG_LEVEL_NOT_SET)
748 			fatal("%.200s line %d: unsupported log level '%s'",
749 			    filename, linenum, arg ? arg : "<NONE>");
750 		if (*activep && *log_level_ptr == SYSLOG_LEVEL_NOT_SET)
751 			*log_level_ptr = (LogLevel) value;
752 		break;
753 
754 	case oLocalForward:
755 	case oRemoteForward:
756 	case oDynamicForward:
757 		arg = strdelim(&s);
758 		if (arg == NULL || *arg == '\0')
759 			fatal("%.200s line %d: Missing port argument.",
760 			    filename, linenum);
761 
762 		if (opcode == oLocalForward ||
763 		    opcode == oRemoteForward) {
764 			arg2 = strdelim(&s);
765 			if (arg2 == NULL || *arg2 == '\0')
766 				fatal("%.200s line %d: Missing target argument.",
767 				    filename, linenum);
768 
769 			/* construct a string for parse_forward */
770 			snprintf(fwdarg, sizeof(fwdarg), "%s:%s", arg, arg2);
771 		} else if (opcode == oDynamicForward) {
772 			strlcpy(fwdarg, arg, sizeof(fwdarg));
773 		}
774 
775 		if (parse_forward(&fwd, fwdarg,
776 		    opcode == oDynamicForward ? 1 : 0,
777 		    opcode == oRemoteForward ? 1 : 0) == 0)
778 			fatal("%.200s line %d: Bad forwarding specification.",
779 			    filename, linenum);
780 
781 		if (*activep) {
782 			if (opcode == oLocalForward ||
783 			    opcode == oDynamicForward)
784 				add_local_forward(options, &fwd);
785 			else if (opcode == oRemoteForward)
786 				add_remote_forward(options, &fwd);
787 		}
788 		break;
789 
790 	case oClearAllForwardings:
791 		intptr = &options->clear_forwardings;
792 		goto parse_flag;
793 
794 	case oHost:
795 		*activep = 0;
796 		while ((arg = strdelim(&s)) != NULL && *arg != '\0')
797 			if (match_pattern(host, arg)) {
798 				debug("Applying options for %.100s", arg);
799 				*activep = 1;
800 				break;
801 			}
802 		/* Avoid garbage check below, as strdelim is done. */
803 		return 0;
804 
805 	case oEscapeChar:
806 		intptr = &options->escape_char;
807 		arg = strdelim(&s);
808 		if (!arg || *arg == '\0')
809 			fatal("%.200s line %d: Missing argument.", filename, linenum);
810 		if (arg[0] == '^' && arg[2] == 0 &&
811 		    (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
812 			value = (u_char) arg[1] & 31;
813 		else if (strlen(arg) == 1)
814 			value = (u_char) arg[0];
815 		else if (strcmp(arg, "none") == 0)
816 			value = SSH_ESCAPECHAR_NONE;
817 		else {
818 			fatal("%.200s line %d: Bad escape character.",
819 			    filename, linenum);
820 			/* NOTREACHED */
821 			value = 0;	/* Avoid compiler warning. */
822 		}
823 		if (*activep && *intptr == -1)
824 			*intptr = value;
825 		break;
826 
827 	case oAddressFamily:
828 		arg = strdelim(&s);
829 		if (!arg || *arg == '\0')
830 			fatal("%s line %d: missing address family.",
831 			    filename, linenum);
832 		intptr = &options->address_family;
833 		if (strcasecmp(arg, "inet") == 0)
834 			value = AF_INET;
835 		else if (strcasecmp(arg, "inet6") == 0)
836 			value = AF_INET6;
837 		else if (strcasecmp(arg, "any") == 0)
838 			value = AF_UNSPEC;
839 		else
840 			fatal("Unsupported AddressFamily \"%s\"", arg);
841 		if (*activep && *intptr == -1)
842 			*intptr = value;
843 		break;
844 
845 	case oEnableSSHKeysign:
846 		intptr = &options->enable_ssh_keysign;
847 		goto parse_flag;
848 
849 	case oIdentitiesOnly:
850 		intptr = &options->identities_only;
851 		goto parse_flag;
852 
853 	case oServerAliveInterval:
854 		intptr = &options->server_alive_interval;
855 		goto parse_time;
856 
857 	case oServerAliveCountMax:
858 		intptr = &options->server_alive_count_max;
859 		goto parse_int;
860 
861 	case oSendEnv:
862 		while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
863 			if (strchr(arg, '=') != NULL)
864 				fatal("%s line %d: Invalid environment name.",
865 				    filename, linenum);
866 			if (!*activep)
867 				continue;
868 			if (options->num_send_env >= MAX_SEND_ENV)
869 				fatal("%s line %d: too many send env.",
870 				    filename, linenum);
871 			options->send_env[options->num_send_env++] =
872 			    xstrdup(arg);
873 		}
874 		break;
875 
876 	case oControlPath:
877 		charptr = &options->control_path;
878 		goto parse_string;
879 
880 	case oControlMaster:
881 		intptr = &options->control_master;
882 		arg = strdelim(&s);
883 		if (!arg || *arg == '\0')
884 			fatal("%.200s line %d: Missing ControlMaster argument.",
885 			    filename, linenum);
886 		value = 0;	/* To avoid compiler warning... */
887 		if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
888 			value = SSHCTL_MASTER_YES;
889 		else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
890 			value = SSHCTL_MASTER_NO;
891 		else if (strcmp(arg, "auto") == 0)
892 			value = SSHCTL_MASTER_AUTO;
893 		else if (strcmp(arg, "ask") == 0)
894 			value = SSHCTL_MASTER_ASK;
895 		else if (strcmp(arg, "autoask") == 0)
896 			value = SSHCTL_MASTER_AUTO_ASK;
897 		else
898 			fatal("%.200s line %d: Bad ControlMaster argument.",
899 			    filename, linenum);
900 		if (*activep && *intptr == -1)
901 			*intptr = value;
902 		break;
903 
904 	case oControlPersist:
905 		/* no/false/yes/true, or a time spec */
906 		intptr = &options->control_persist;
907 		arg = strdelim(&s);
908 		if (!arg || *arg == '\0')
909 			fatal("%.200s line %d: Missing ControlPersist"
910 			    " argument.", filename, linenum);
911 		value = 0;
912 		value2 = 0;	/* timeout */
913 		if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
914 			value = 0;
915 		else if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
916 			value = 1;
917 		else if ((value2 = convtime(arg)) >= 0)
918 			value = 1;
919 		else
920 			fatal("%.200s line %d: Bad ControlPersist argument.",
921 			    filename, linenum);
922 		if (*activep && *intptr == -1) {
923 			*intptr = value;
924 			options->control_persist_timeout = value2;
925 		}
926 		break;
927 
928 	case oHashKnownHosts:
929 		intptr = &options->hash_known_hosts;
930 		goto parse_flag;
931 
932 	case oTunnel:
933 		intptr = &options->tun_open;
934 		arg = strdelim(&s);
935 		if (!arg || *arg == '\0')
936 			fatal("%s line %d: Missing yes/point-to-point/"
937 			    "ethernet/no argument.", filename, linenum);
938 		value = 0;	/* silence compiler */
939 		if (strcasecmp(arg, "ethernet") == 0)
940 			value = SSH_TUNMODE_ETHERNET;
941 		else if (strcasecmp(arg, "point-to-point") == 0)
942 			value = SSH_TUNMODE_POINTOPOINT;
943 		else if (strcasecmp(arg, "yes") == 0)
944 			value = SSH_TUNMODE_DEFAULT;
945 		else if (strcasecmp(arg, "no") == 0)
946 			value = SSH_TUNMODE_NO;
947 		else
948 			fatal("%s line %d: Bad yes/point-to-point/ethernet/"
949 			    "no argument: %s", filename, linenum, arg);
950 		if (*activep)
951 			*intptr = value;
952 		break;
953 
954 	case oTunnelDevice:
955 		arg = strdelim(&s);
956 		if (!arg || *arg == '\0')
957 			fatal("%.200s line %d: Missing argument.", filename, linenum);
958 		value = a2tun(arg, &value2);
959 		if (value == SSH_TUNID_ERR)
960 			fatal("%.200s line %d: Bad tun device.", filename, linenum);
961 		if (*activep) {
962 			options->tun_local = value;
963 			options->tun_remote = value2;
964 		}
965 		break;
966 
967 	case oLocalCommand:
968 		charptr = &options->local_command;
969 		goto parse_command;
970 
971 	case oPermitLocalCommand:
972 		intptr = &options->permit_local_command;
973 		goto parse_flag;
974 
975 	case oVisualHostKey:
976 		intptr = &options->visual_host_key;
977 		goto parse_flag;
978 
979 	case oUseRoaming:
980 		intptr = &options->use_roaming;
981 		goto parse_flag;
982 
983 	case oVersionAddendum:
984 		ssh_version_set_addendum(strtok(s, "\n"));
985 		do {
986 			arg = strdelim(&s);
987 		} while (arg != NULL && *arg != '\0');
988 		break;
989 
990 	case oDeprecated:
991 		debug("%s line %d: Deprecated option \"%s\"",
992 		    filename, linenum, keyword);
993 		return 0;
994 
995 	case oUnsupported:
996 		error("%s line %d: Unsupported option \"%s\"",
997 		    filename, linenum, keyword);
998 		return 0;
999 
1000 	default:
1001 		fatal("process_config_line: Unimplemented opcode %d", opcode);
1002 	}
1003 
1004 	/* Check that there is no garbage at end of line. */
1005 	if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
1006 		fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
1007 		    filename, linenum, arg);
1008 	}
1009 	return 0;
1010 }
1011 
1012 
1013 /*
1014  * Reads the config file and modifies the options accordingly.  Options
1015  * should already be initialized before this call.  This never returns if
1016  * there is an error.  If the file does not exist, this returns 0.
1017  */
1018 
1019 int
1020 read_config_file(const char *filename, const char *host, Options *options,
1021     int checkperm)
1022 {
1023 	FILE *f;
1024 	char line[1024];
1025 	int active, linenum;
1026 	int bad_options = 0;
1027 
1028 	if ((f = fopen(filename, "r")) == NULL)
1029 		return 0;
1030 
1031 	if (checkperm) {
1032 		struct stat sb;
1033 
1034 		if (fstat(fileno(f), &sb) == -1)
1035 			fatal("fstat %s: %s", filename, strerror(errno));
1036 		if (((sb.st_uid != 0 && sb.st_uid != getuid()) ||
1037 		    (sb.st_mode & 022) != 0))
1038 			fatal("Bad owner or permissions on %s", filename);
1039 	}
1040 
1041 	debug("Reading configuration data %.200s", filename);
1042 
1043 	/*
1044 	 * Mark that we are now processing the options.  This flag is turned
1045 	 * on/off by Host specifications.
1046 	 */
1047 	active = 1;
1048 	linenum = 0;
1049 	while (fgets(line, sizeof(line), f)) {
1050 		/* Update line number counter. */
1051 		linenum++;
1052 		if (process_config_line(options, host, line, filename, linenum, &active) != 0)
1053 			bad_options++;
1054 	}
1055 	fclose(f);
1056 	if (bad_options > 0)
1057 		fatal("%s: terminating, %d bad configuration options",
1058 		    filename, bad_options);
1059 	return 1;
1060 }
1061 
1062 /*
1063  * Initializes options to special values that indicate that they have not yet
1064  * been set.  Read_config_file will only set options with this value. Options
1065  * are processed in the following order: command line, user config file,
1066  * system config file.  Last, fill_default_options is called.
1067  */
1068 
1069 void
1070 initialize_options(Options * options)
1071 {
1072 	memset(options, 'X', sizeof(*options));
1073 	options->forward_agent = -1;
1074 	options->forward_x11 = -1;
1075 	options->forward_x11_trusted = -1;
1076 	options->forward_x11_timeout = -1;
1077 	options->exit_on_forward_failure = -1;
1078 	options->xauth_location = NULL;
1079 	options->gateway_ports = -1;
1080 	options->use_privileged_port = -1;
1081 	options->rsa_authentication = -1;
1082 	options->pubkey_authentication = -1;
1083 	options->challenge_response_authentication = -1;
1084 	options->gss_authentication = -1;
1085 	options->gss_deleg_creds = -1;
1086 	options->password_authentication = -1;
1087 	options->kbd_interactive_authentication = -1;
1088 	options->kbd_interactive_devices = NULL;
1089 	options->rhosts_rsa_authentication = -1;
1090 	options->hostbased_authentication = -1;
1091 	options->batch_mode = -1;
1092 	options->check_host_ip = -1;
1093 	options->strict_host_key_checking = -1;
1094 	options->compression = -1;
1095 	options->tcp_keep_alive = -1;
1096 	options->compression_level = -1;
1097 	options->port = -1;
1098 	options->address_family = -1;
1099 	options->connection_attempts = -1;
1100 	options->connection_timeout = -1;
1101 	options->number_of_password_prompts = -1;
1102 	options->cipher = -1;
1103 	options->ciphers = NULL;
1104 	options->macs = NULL;
1105 	options->hostkeyalgorithms = NULL;
1106 	options->protocol = SSH_PROTO_UNKNOWN;
1107 	options->num_identity_files = 0;
1108 	options->hostname = NULL;
1109 	options->host_key_alias = NULL;
1110 	options->proxy_command = NULL;
1111 	options->user = NULL;
1112 	options->escape_char = -1;
1113 	options->system_hostfile = NULL;
1114 	options->user_hostfile = NULL;
1115 	options->system_hostfile2 = NULL;
1116 	options->user_hostfile2 = NULL;
1117 	options->local_forwards = NULL;
1118 	options->num_local_forwards = 0;
1119 	options->remote_forwards = NULL;
1120 	options->num_remote_forwards = 0;
1121 	options->clear_forwardings = -1;
1122 	options->log_level = SYSLOG_LEVEL_NOT_SET;
1123 	options->preferred_authentications = NULL;
1124 	options->bind_address = NULL;
1125 	options->pkcs11_provider = NULL;
1126 	options->enable_ssh_keysign = - 1;
1127 	options->no_host_authentication_for_localhost = - 1;
1128 	options->identities_only = - 1;
1129 	options->rekey_limit = - 1;
1130 	options->verify_host_key_dns = -1;
1131 	options->server_alive_interval = -1;
1132 	options->server_alive_count_max = -1;
1133 	options->num_send_env = 0;
1134 	options->control_path = NULL;
1135 	options->control_master = -1;
1136 	options->control_persist = -1;
1137 	options->control_persist_timeout = 0;
1138 	options->hash_known_hosts = -1;
1139 	options->tun_open = -1;
1140 	options->tun_local = -1;
1141 	options->tun_remote = -1;
1142 	options->local_command = NULL;
1143 	options->permit_local_command = -1;
1144 	options->use_roaming = -1;
1145 	options->visual_host_key = -1;
1146 	options->zero_knowledge_password_authentication = -1;
1147 }
1148 
1149 /*
1150  * Called after processing other sources of option data, this fills those
1151  * options for which no value has been specified with their default values.
1152  */
1153 
1154 void
1155 fill_default_options(Options * options)
1156 {
1157 	int len;
1158 
1159 	if (options->forward_agent == -1)
1160 		options->forward_agent = 0;
1161 	if (options->forward_x11 == -1)
1162 		options->forward_x11 = 0;
1163 	if (options->forward_x11_trusted == -1)
1164 		options->forward_x11_trusted = 0;
1165 	if (options->forward_x11_timeout == -1)
1166 		options->forward_x11_timeout = 1200;
1167 	if (options->exit_on_forward_failure == -1)
1168 		options->exit_on_forward_failure = 0;
1169 	if (options->xauth_location == NULL)
1170 		options->xauth_location = _PATH_XAUTH;
1171 	if (options->gateway_ports == -1)
1172 		options->gateway_ports = 0;
1173 	if (options->use_privileged_port == -1)
1174 		options->use_privileged_port = 0;
1175 	if (options->rsa_authentication == -1)
1176 		options->rsa_authentication = 1;
1177 	if (options->pubkey_authentication == -1)
1178 		options->pubkey_authentication = 1;
1179 	if (options->challenge_response_authentication == -1)
1180 		options->challenge_response_authentication = 1;
1181 	if (options->gss_authentication == -1)
1182 		options->gss_authentication = 0;
1183 	if (options->gss_deleg_creds == -1)
1184 		options->gss_deleg_creds = 0;
1185 	if (options->password_authentication == -1)
1186 		options->password_authentication = 1;
1187 	if (options->kbd_interactive_authentication == -1)
1188 		options->kbd_interactive_authentication = 1;
1189 	if (options->rhosts_rsa_authentication == -1)
1190 		options->rhosts_rsa_authentication = 0;
1191 	if (options->hostbased_authentication == -1)
1192 		options->hostbased_authentication = 0;
1193 	if (options->batch_mode == -1)
1194 		options->batch_mode = 0;
1195 	if (options->check_host_ip == -1)
1196 		options->check_host_ip = 0;
1197 	if (options->strict_host_key_checking == -1)
1198 		options->strict_host_key_checking = 2;	/* 2 is default */
1199 	if (options->compression == -1)
1200 		options->compression = 0;
1201 	if (options->tcp_keep_alive == -1)
1202 		options->tcp_keep_alive = 1;
1203 	if (options->compression_level == -1)
1204 		options->compression_level = 6;
1205 	if (options->port == -1)
1206 		options->port = 0;	/* Filled in ssh_connect. */
1207 	if (options->address_family == -1)
1208 		options->address_family = AF_UNSPEC;
1209 	if (options->connection_attempts == -1)
1210 		options->connection_attempts = 1;
1211 	if (options->number_of_password_prompts == -1)
1212 		options->number_of_password_prompts = 3;
1213 	/* Selected in ssh_login(). */
1214 	if (options->cipher == -1)
1215 		options->cipher = SSH_CIPHER_NOT_SET;
1216 	/* options->ciphers, default set in myproposals.h */
1217 	/* options->macs, default set in myproposals.h */
1218 	/* options->hostkeyalgorithms, default set in myproposals.h */
1219 	if (options->protocol == SSH_PROTO_UNKNOWN)
1220 		options->protocol = SSH_PROTO_2;
1221 	if (options->num_identity_files == 0) {
1222 		if (options->protocol & SSH_PROTO_1) {
1223 			len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
1224 			options->identity_files[options->num_identity_files] =
1225 			    xmalloc(len);
1226 			snprintf(options->identity_files[options->num_identity_files++],
1227 			    len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
1228 		}
1229 		if (options->protocol & SSH_PROTO_2) {
1230 			len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
1231 			options->identity_files[options->num_identity_files] =
1232 			    xmalloc(len);
1233 			snprintf(options->identity_files[options->num_identity_files++],
1234 			    len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
1235 
1236 			len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
1237 			options->identity_files[options->num_identity_files] =
1238 			    xmalloc(len);
1239 			snprintf(options->identity_files[options->num_identity_files++],
1240 			    len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
1241 		}
1242 	}
1243 	if (options->escape_char == -1)
1244 		options->escape_char = '~';
1245 	if (options->system_hostfile == NULL)
1246 		options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE;
1247 	if (options->user_hostfile == NULL)
1248 		options->user_hostfile = _PATH_SSH_USER_HOSTFILE;
1249 	if (options->system_hostfile2 == NULL)
1250 		options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2;
1251 	if (options->user_hostfile2 == NULL)
1252 		options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2;
1253 	if (options->log_level == SYSLOG_LEVEL_NOT_SET)
1254 		options->log_level = SYSLOG_LEVEL_INFO;
1255 	if (options->clear_forwardings == 1)
1256 		clear_forwardings(options);
1257 	if (options->no_host_authentication_for_localhost == - 1)
1258 		options->no_host_authentication_for_localhost = 0;
1259 	if (options->identities_only == -1)
1260 		options->identities_only = 0;
1261 	if (options->enable_ssh_keysign == -1)
1262 		options->enable_ssh_keysign = 0;
1263 	if (options->rekey_limit == -1)
1264 		options->rekey_limit = 0;
1265 	if (options->verify_host_key_dns == -1)
1266 		options->verify_host_key_dns = 0;
1267 	if (options->server_alive_interval == -1)
1268 		options->server_alive_interval = 0;
1269 	if (options->server_alive_count_max == -1)
1270 		options->server_alive_count_max = 3;
1271 	if (options->control_master == -1)
1272 		options->control_master = 0;
1273 	if (options->control_persist == -1) {
1274 		options->control_persist = 0;
1275 		options->control_persist_timeout = 0;
1276 	}
1277 	if (options->hash_known_hosts == -1)
1278 		options->hash_known_hosts = 0;
1279 	if (options->tun_open == -1)
1280 		options->tun_open = SSH_TUNMODE_NO;
1281 	if (options->tun_local == -1)
1282 		options->tun_local = SSH_TUNID_ANY;
1283 	if (options->tun_remote == -1)
1284 		options->tun_remote = SSH_TUNID_ANY;
1285 	if (options->permit_local_command == -1)
1286 		options->permit_local_command = 0;
1287 	if (options->use_roaming == -1)
1288 		options->use_roaming = 1;
1289 	if (options->visual_host_key == -1)
1290 		options->visual_host_key = 0;
1291 	if (options->zero_knowledge_password_authentication == -1)
1292 		options->zero_knowledge_password_authentication = 0;
1293 	/* options->local_command should not be set by default */
1294 	/* options->proxy_command should not be set by default */
1295 	/* options->user will be set in the main program if appropriate */
1296 	/* options->hostname will be set in the main program if appropriate */
1297 	/* options->host_key_alias should not be set by default */
1298 	/* options->preferred_authentications will be set in ssh */
1299 }
1300 
1301 /*
1302  * parse_forward
1303  * parses a string containing a port forwarding specification of the form:
1304  *   dynamicfwd == 0
1305  *	[listenhost:]listenport:connecthost:connectport
1306  *   dynamicfwd == 1
1307  *	[listenhost:]listenport
1308  * returns number of arguments parsed or zero on error
1309  */
1310 int
1311 parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
1312 {
1313 	int i;
1314 	char *p, *cp, *fwdarg[4];
1315 
1316 	memset(fwd, '\0', sizeof(*fwd));
1317 
1318 	cp = p = xstrdup(fwdspec);
1319 
1320 	/* skip leading spaces */
1321 	while (isspace(*cp))
1322 		cp++;
1323 
1324 	for (i = 0; i < 4; ++i)
1325 		if ((fwdarg[i] = hpdelim(&cp)) == NULL)
1326 			break;
1327 
1328 	/* Check for trailing garbage */
1329 	if (cp != NULL)
1330 		i = 0;	/* failure */
1331 
1332 	switch (i) {
1333 	case 1:
1334 		fwd->listen_host = NULL;
1335 		fwd->listen_port = a2port(fwdarg[0]);
1336 		fwd->connect_host = xstrdup("socks");
1337 		break;
1338 
1339 	case 2:
1340 		fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1341 		fwd->listen_port = a2port(fwdarg[1]);
1342 		fwd->connect_host = xstrdup("socks");
1343 		break;
1344 
1345 	case 3:
1346 		fwd->listen_host = NULL;
1347 		fwd->listen_port = a2port(fwdarg[0]);
1348 		fwd->connect_host = xstrdup(cleanhostname(fwdarg[1]));
1349 		fwd->connect_port = a2port(fwdarg[2]);
1350 		break;
1351 
1352 	case 4:
1353 		fwd->listen_host = xstrdup(cleanhostname(fwdarg[0]));
1354 		fwd->listen_port = a2port(fwdarg[1]);
1355 		fwd->connect_host = xstrdup(cleanhostname(fwdarg[2]));
1356 		fwd->connect_port = a2port(fwdarg[3]);
1357 		break;
1358 	default:
1359 		i = 0; /* failure */
1360 	}
1361 
1362 	xfree(p);
1363 
1364 	if (dynamicfwd) {
1365 		if (!(i == 1 || i == 2))
1366 			goto fail_free;
1367 	} else {
1368 		if (!(i == 3 || i == 4))
1369 			goto fail_free;
1370 		if (fwd->connect_port <= 0)
1371 			goto fail_free;
1372 	}
1373 
1374 	if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0))
1375 		goto fail_free;
1376 
1377 	if (fwd->connect_host != NULL &&
1378 	    strlen(fwd->connect_host) >= NI_MAXHOST)
1379 		goto fail_free;
1380 	if (fwd->listen_host != NULL &&
1381 	    strlen(fwd->listen_host) >= NI_MAXHOST)
1382 		goto fail_free;
1383 
1384 
1385 	return (i);
1386 
1387  fail_free:
1388 	if (fwd->connect_host != NULL) {
1389 		xfree(fwd->connect_host);
1390 		fwd->connect_host = NULL;
1391 	}
1392 	if (fwd->listen_host != NULL) {
1393 		xfree(fwd->listen_host);
1394 		fwd->listen_host = NULL;
1395 	}
1396 	return (0);
1397 }
1398