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