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