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