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