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