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