]> andersk Git - openssh.git/blob - readconf.c
- markus@cvs.openbsd.org 2003/12/16 15:49:51
[openssh.git] / readconf.c
1 /*
2  * Author: Tatu Ylonen <ylo@cs.hut.fi>
3  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4  *                    All rights reserved
5  * Functions for reading the configuration files.
6  *
7  * As far as I am concerned, the code I have written for this software
8  * can be used freely for any purpose.  Any derived versions of this
9  * software must be clearly marked as such, and if the derived work is
10  * incompatible with the protocol description in the RFC file, it must be
11  * called by a name other than "ssh" or "Secure Shell".
12  */
13
14 #include "includes.h"
15 RCSID("$OpenBSD: readconf.c,v 1.127 2003/12/16 15:49:51 markus Exp $");
16
17 #include "ssh.h"
18 #include "xmalloc.h"
19 #include "compat.h"
20 #include "cipher.h"
21 #include "pathnames.h"
22 #include "log.h"
23 #include "readconf.h"
24 #include "match.h"
25 #include "misc.h"
26 #include "kex.h"
27 #include "mac.h"
28
29 /* Format of the configuration file:
30
31    # Configuration data is parsed as follows:
32    #  1. command line options
33    #  2. user-specific file
34    #  3. system-wide file
35    # Any configuration value is only changed the first time it is set.
36    # Thus, host-specific definitions should be at the beginning of the
37    # configuration file, and defaults at the end.
38
39    # Host-specific declarations.  These may override anything above.  A single
40    # host may match multiple declarations; these are processed in the order
41    # that they are given in.
42
43    Host *.ngs.fi ngs.fi
44      User foo
45
46    Host fake.com
47      HostName another.host.name.real.org
48      User blaah
49      Port 34289
50      ForwardX11 no
51      ForwardAgent no
52
53    Host books.com
54      RemoteForward 9999 shadows.cs.hut.fi:9999
55      Cipher 3des
56
57    Host fascist.blob.com
58      Port 23123
59      User tylonen
60      PasswordAuthentication no
61
62    Host puukko.hut.fi
63      User t35124p
64      ProxyCommand ssh-proxy %h %p
65
66    Host *.fr
67      PublicKeyAuthentication no
68
69    Host *.su
70      Cipher none
71      PasswordAuthentication no
72
73    # Defaults for various options
74    Host *
75      ForwardAgent no
76      ForwardX11 no
77      PasswordAuthentication yes
78      RSAAuthentication yes
79      RhostsRSAAuthentication yes
80      StrictHostKeyChecking yes
81      TcpKeepAlive no
82      IdentityFile ~/.ssh/identity
83      Port 22
84      EscapeChar ~
85
86 */
87
88 /* Keyword tokens. */
89
90 typedef enum {
91         oBadOption,
92         oForwardAgent, oForwardX11, oForwardX11Trusted, oGatewayPorts,
93         oPasswordAuthentication, oRSAAuthentication,
94         oChallengeResponseAuthentication, oXAuthLocation,
95         oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
96         oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
97         oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
98         oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
99         oCompressionLevel, oTCPKeepAlive, oNumberOfPasswordPrompts,
100         oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
101         oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
102         oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
103         oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
104         oHostKeyAlgorithms, oBindAddress, oSmartcardDevice,
105         oClearAllForwardings, oNoHostAuthenticationForLocalhost,
106         oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
107         oAddressFamily, oGssAuthentication, oGssDelegateCreds,
108         oServerAliveInterval, oServerAliveCountMax,
109         oDeprecated, oUnsupported
110 } OpCodes;
111
112 /* Textual representations of the tokens. */
113
114 static struct {
115         const char *name;
116         OpCodes opcode;
117 } keywords[] = {
118         { "forwardagent", oForwardAgent },
119         { "forwardx11", oForwardX11 },
120         { "forwardx11trusted", oForwardX11Trusted },
121         { "xauthlocation", oXAuthLocation },
122         { "gatewayports", oGatewayPorts },
123         { "useprivilegedport", oUsePrivilegedPort },
124         { "rhostsauthentication", oDeprecated },
125         { "passwordauthentication", oPasswordAuthentication },
126         { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
127         { "kbdinteractivedevices", oKbdInteractiveDevices },
128         { "rsaauthentication", oRSAAuthentication },
129         { "pubkeyauthentication", oPubkeyAuthentication },
130         { "dsaauthentication", oPubkeyAuthentication },             /* alias */
131         { "rhostsrsaauthentication", oRhostsRSAAuthentication },
132         { "hostbasedauthentication", oHostbasedAuthentication },
133         { "challengeresponseauthentication", oChallengeResponseAuthentication },
134         { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
135         { "tisauthentication", oChallengeResponseAuthentication },  /* alias */
136         { "kerberosauthentication", oUnsupported },
137         { "kerberostgtpassing", oUnsupported },
138         { "afstokenpassing", oUnsupported },
139 #if defined(GSSAPI)
140         { "gssapiauthentication", oGssAuthentication },
141         { "gssapidelegatecredentials", oGssDelegateCreds },
142 #else
143         { "gssapiauthentication", oUnsupported },
144         { "gssapidelegatecredentials", oUnsupported },
145 #endif
146         { "fallbacktorsh", oDeprecated },
147         { "usersh", oDeprecated },
148         { "identityfile", oIdentityFile },
149         { "identityfile2", oIdentityFile },                     /* alias */
150         { "hostname", oHostName },
151         { "hostkeyalias", oHostKeyAlias },
152         { "proxycommand", oProxyCommand },
153         { "port", oPort },
154         { "cipher", oCipher },
155         { "ciphers", oCiphers },
156         { "macs", oMacs },
157         { "protocol", oProtocol },
158         { "remoteforward", oRemoteForward },
159         { "localforward", oLocalForward },
160         { "user", oUser },
161         { "host", oHost },
162         { "escapechar", oEscapeChar },
163         { "globalknownhostsfile", oGlobalKnownHostsFile },
164         { "userknownhostsfile", oUserKnownHostsFile },          /* obsolete */
165         { "globalknownhostsfile2", oGlobalKnownHostsFile2 },
166         { "userknownhostsfile2", oUserKnownHostsFile2 },        /* obsolete */
167         { "connectionattempts", oConnectionAttempts },
168         { "batchmode", oBatchMode },
169         { "checkhostip", oCheckHostIP },
170         { "stricthostkeychecking", oStrictHostKeyChecking },
171         { "compression", oCompression },
172         { "compressionlevel", oCompressionLevel },
173         { "tcpkeepalive", oTCPKeepAlive },
174         { "keepalive", oTCPKeepAlive },                         /* obsolete */
175         { "numberofpasswordprompts", oNumberOfPasswordPrompts },
176         { "loglevel", oLogLevel },
177         { "dynamicforward", oDynamicForward },
178         { "preferredauthentications", oPreferredAuthentications },
179         { "hostkeyalgorithms", oHostKeyAlgorithms },
180         { "bindaddress", oBindAddress },
181 #ifdef SMARTCARD
182         { "smartcarddevice", oSmartcardDevice },
183 #else
184         { "smartcarddevice", oUnsupported },
185 #endif
186         { "clearallforwardings", oClearAllForwardings },
187         { "enablesshkeysign", oEnableSSHKeysign },
188         { "verifyhostkeydns", oVerifyHostKeyDNS },
189         { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
190         { "rekeylimit", oRekeyLimit },
191         { "connecttimeout", oConnectTimeout },
192         { "addressfamily", oAddressFamily },
193         { "serveraliveinterval", oServerAliveInterval },
194         { "serveralivecountmax", oServerAliveCountMax },
195         { NULL, oBadOption }
196 };
197
198 /*
199  * Adds a local TCP/IP port forward to options.  Never returns if there is an
200  * error.
201  */
202
203 void
204 add_local_forward(Options *options, u_short port, const char *host,
205                   u_short host_port)
206 {
207         Forward *fwd;
208 #ifndef NO_IPPORT_RESERVED_CONCEPT
209         extern uid_t original_real_uid;
210         if (port < IPPORT_RESERVED && original_real_uid != 0)
211                 fatal("Privileged ports can only be forwarded by root.");
212 #endif
213         if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
214                 fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
215         fwd = &options->local_forwards[options->num_local_forwards++];
216         fwd->port = port;
217         fwd->host = xstrdup(host);
218         fwd->host_port = host_port;
219 }
220
221 /*
222  * Adds a remote TCP/IP port forward to options.  Never returns if there is
223  * an error.
224  */
225
226 void
227 add_remote_forward(Options *options, u_short port, const char *host,
228                    u_short host_port)
229 {
230         Forward *fwd;
231         if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
232                 fatal("Too many remote forwards (max %d).",
233                     SSH_MAX_FORWARDS_PER_DIRECTION);
234         fwd = &options->remote_forwards[options->num_remote_forwards++];
235         fwd->port = port;
236         fwd->host = xstrdup(host);
237         fwd->host_port = host_port;
238 }
239
240 static void
241 clear_forwardings(Options *options)
242 {
243         int i;
244
245         for (i = 0; i < options->num_local_forwards; i++)
246                 xfree(options->local_forwards[i].host);
247         options->num_local_forwards = 0;
248         for (i = 0; i < options->num_remote_forwards; i++)
249                 xfree(options->remote_forwards[i].host);
250         options->num_remote_forwards = 0;
251 }
252
253 /*
254  * Returns the number of the token pointed to by cp or oBadOption.
255  */
256
257 static OpCodes
258 parse_token(const char *cp, const char *filename, int linenum)
259 {
260         u_int i;
261
262         for (i = 0; keywords[i].name; i++)
263                 if (strcasecmp(cp, keywords[i].name) == 0)
264                         return keywords[i].opcode;
265
266         error("%s: line %d: Bad configuration option: %s",
267             filename, linenum, cp);
268         return oBadOption;
269 }
270
271 /*
272  * Processes a single option line as used in the configuration files. This
273  * only sets those values that have not already been set.
274  */
275 #define WHITESPACE " \t\r\n"
276
277 int
278 process_config_line(Options *options, const char *host,
279                     char *line, const char *filename, int linenum,
280                     int *activep)
281 {
282         char buf[256], *s, **charptr, *endofnumber, *keyword, *arg;
283         int opcode, *intptr, value;
284         size_t len;
285         u_short fwd_port, fwd_host_port;
286         char sfwd_host_port[6];
287
288         /* Strip trailing whitespace */
289         for(len = strlen(line) - 1; len > 0; len--) {
290                 if (strchr(WHITESPACE, line[len]) == NULL)
291                         break;
292                 line[len] = '\0';
293         }
294
295         s = line;
296         /* Get the keyword. (Each line is supposed to begin with a keyword). */
297         keyword = strdelim(&s);
298         /* Ignore leading whitespace. */
299         if (*keyword == '\0')
300                 keyword = strdelim(&s);
301         if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
302                 return 0;
303
304         opcode = parse_token(keyword, filename, linenum);
305
306         switch (opcode) {
307         case oBadOption:
308                 /* don't panic, but count bad options */
309                 return -1;
310                 /* NOTREACHED */
311         case oConnectTimeout:
312                 intptr = &options->connection_timeout;
313 parse_time:
314                 arg = strdelim(&s);
315                 if (!arg || *arg == '\0')
316                         fatal("%s line %d: missing time value.",
317                             filename, linenum);
318                 if ((value = convtime(arg)) == -1)
319                         fatal("%s line %d: invalid time value.",
320                             filename, linenum);
321                 if (*intptr == -1)
322                         *intptr = value;
323                 break;
324
325         case oForwardAgent:
326                 intptr = &options->forward_agent;
327 parse_flag:
328                 arg = strdelim(&s);
329                 if (!arg || *arg == '\0')
330                         fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
331                 value = 0;      /* To avoid compiler warning... */
332                 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
333                         value = 1;
334                 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
335                         value = 0;
336                 else
337                         fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
338                 if (*activep && *intptr == -1)
339                         *intptr = value;
340                 break;
341
342         case oForwardX11:
343                 intptr = &options->forward_x11;
344                 goto parse_flag;
345
346         case oForwardX11Trusted:
347                 intptr = &options->forward_x11_trusted;
348                 goto parse_flag;
349
350         case oGatewayPorts:
351                 intptr = &options->gateway_ports;
352                 goto parse_flag;
353
354         case oUsePrivilegedPort:
355                 intptr = &options->use_privileged_port;
356                 goto parse_flag;
357
358         case oPasswordAuthentication:
359                 intptr = &options->password_authentication;
360                 goto parse_flag;
361
362         case oKbdInteractiveAuthentication:
363                 intptr = &options->kbd_interactive_authentication;
364                 goto parse_flag;
365
366         case oKbdInteractiveDevices:
367                 charptr = &options->kbd_interactive_devices;
368                 goto parse_string;
369
370         case oPubkeyAuthentication:
371                 intptr = &options->pubkey_authentication;
372                 goto parse_flag;
373
374         case oRSAAuthentication:
375                 intptr = &options->rsa_authentication;
376                 goto parse_flag;
377
378         case oRhostsRSAAuthentication:
379                 intptr = &options->rhosts_rsa_authentication;
380                 goto parse_flag;
381
382         case oHostbasedAuthentication:
383                 intptr = &options->hostbased_authentication;
384                 goto parse_flag;
385
386         case oChallengeResponseAuthentication:
387                 intptr = &options->challenge_response_authentication;
388                 goto parse_flag;
389
390         case oGssAuthentication:
391                 intptr = &options->gss_authentication;
392                 goto parse_flag;
393
394         case oGssDelegateCreds:
395                 intptr = &options->gss_deleg_creds;
396                 goto parse_flag;
397
398         case oBatchMode:
399                 intptr = &options->batch_mode;
400                 goto parse_flag;
401
402         case oCheckHostIP:
403                 intptr = &options->check_host_ip;
404                 goto parse_flag;
405
406         case oVerifyHostKeyDNS:
407                 intptr = &options->verify_host_key_dns;
408                 goto parse_yesnoask;
409
410         case oStrictHostKeyChecking:
411                 intptr = &options->strict_host_key_checking;
412 parse_yesnoask:
413                 arg = strdelim(&s);
414                 if (!arg || *arg == '\0')
415                         fatal("%.200s line %d: Missing yes/no/ask argument.",
416                             filename, linenum);
417                 value = 0;      /* To avoid compiler warning... */
418                 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
419                         value = 1;
420                 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
421                         value = 0;
422                 else if (strcmp(arg, "ask") == 0)
423                         value = 2;
424                 else
425                         fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
426                 if (*activep && *intptr == -1)
427                         *intptr = value;
428                 break;
429
430         case oCompression:
431                 intptr = &options->compression;
432                 goto parse_flag;
433
434         case oTCPKeepAlive:
435                 intptr = &options->tcp_keep_alive;
436                 goto parse_flag;
437
438         case oNoHostAuthenticationForLocalhost:
439                 intptr = &options->no_host_authentication_for_localhost;
440                 goto parse_flag;
441
442         case oNumberOfPasswordPrompts:
443                 intptr = &options->number_of_password_prompts;
444                 goto parse_int;
445
446         case oCompressionLevel:
447                 intptr = &options->compression_level;
448                 goto parse_int;
449
450         case oRekeyLimit:
451                 intptr = &options->rekey_limit;
452                 arg = strdelim(&s);
453                 if (!arg || *arg == '\0')
454                         fatal("%.200s line %d: Missing argument.", filename, linenum);
455                 if (arg[0] < '0' || arg[0] > '9')
456                         fatal("%.200s line %d: Bad number.", filename, linenum);
457                 value = strtol(arg, &endofnumber, 10);
458                 if (arg == endofnumber)
459                         fatal("%.200s line %d: Bad number.", filename, linenum);
460                 switch (toupper(*endofnumber)) {
461                 case 'K':
462                         value *= 1<<10;
463                         break;
464                 case 'M':
465                         value *= 1<<20;
466                         break;
467                 case 'G':
468                         value *= 1<<30;
469                         break;
470                 }
471                 if (*activep && *intptr == -1)
472                         *intptr = value;
473                 break;
474
475         case oIdentityFile:
476                 arg = strdelim(&s);
477                 if (!arg || *arg == '\0')
478                         fatal("%.200s line %d: Missing argument.", filename, linenum);
479                 if (*activep) {
480                         intptr = &options->num_identity_files;
481                         if (*intptr >= SSH_MAX_IDENTITY_FILES)
482                                 fatal("%.200s line %d: Too many identity files specified (max %d).",
483                                     filename, linenum, SSH_MAX_IDENTITY_FILES);
484                         charptr =  &options->identity_files[*intptr];
485                         *charptr = xstrdup(arg);
486                         *intptr = *intptr + 1;
487                 }
488                 break;
489
490         case oXAuthLocation:
491                 charptr=&options->xauth_location;
492                 goto parse_string;
493
494         case oUser:
495                 charptr = &options->user;
496 parse_string:
497                 arg = strdelim(&s);
498                 if (!arg || *arg == '\0')
499                         fatal("%.200s line %d: Missing argument.", filename, linenum);
500                 if (*activep && *charptr == NULL)
501                         *charptr = xstrdup(arg);
502                 break;
503
504         case oGlobalKnownHostsFile:
505                 charptr = &options->system_hostfile;
506                 goto parse_string;
507
508         case oUserKnownHostsFile:
509                 charptr = &options->user_hostfile;
510                 goto parse_string;
511
512         case oGlobalKnownHostsFile2:
513                 charptr = &options->system_hostfile2;
514                 goto parse_string;
515
516         case oUserKnownHostsFile2:
517                 charptr = &options->user_hostfile2;
518                 goto parse_string;
519
520         case oHostName:
521                 charptr = &options->hostname;
522                 goto parse_string;
523
524         case oHostKeyAlias:
525                 charptr = &options->host_key_alias;
526                 goto parse_string;
527
528         case oPreferredAuthentications:
529                 charptr = &options->preferred_authentications;
530                 goto parse_string;
531
532         case oBindAddress:
533                 charptr = &options->bind_address;
534                 goto parse_string;
535
536         case oSmartcardDevice:
537                 charptr = &options->smartcard_device;
538                 goto parse_string;
539
540         case oProxyCommand:
541                 if (s == NULL)
542                         fatal("%.200s line %d: Missing argument.", filename, linenum);
543                 charptr = &options->proxy_command;
544                 len = strspn(s, WHITESPACE "=");
545                 if (*activep && *charptr == NULL)
546                         *charptr = xstrdup(s + len);
547                 return 0;
548
549         case oPort:
550                 intptr = &options->port;
551 parse_int:
552                 arg = strdelim(&s);
553                 if (!arg || *arg == '\0')
554                         fatal("%.200s line %d: Missing argument.", filename, linenum);
555                 if (arg[0] < '0' || arg[0] > '9')
556                         fatal("%.200s line %d: Bad number.", filename, linenum);
557
558                 /* Octal, decimal, or hex format? */
559                 value = strtol(arg, &endofnumber, 0);
560                 if (arg == endofnumber)
561                         fatal("%.200s line %d: Bad number.", filename, linenum);
562                 if (*activep && *intptr == -1)
563                         *intptr = value;
564                 break;
565
566         case oConnectionAttempts:
567                 intptr = &options->connection_attempts;
568                 goto parse_int;
569
570         case oCipher:
571                 intptr = &options->cipher;
572                 arg = strdelim(&s);
573                 if (!arg || *arg == '\0')
574                         fatal("%.200s line %d: Missing argument.", filename, linenum);
575                 value = cipher_number(arg);
576                 if (value == -1)
577                         fatal("%.200s line %d: Bad cipher '%s'.",
578                             filename, linenum, arg ? arg : "<NONE>");
579                 if (*activep && *intptr == -1)
580                         *intptr = value;
581                 break;
582
583         case oCiphers:
584                 arg = strdelim(&s);
585                 if (!arg || *arg == '\0')
586                         fatal("%.200s line %d: Missing argument.", filename, linenum);
587                 if (!ciphers_valid(arg))
588                         fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
589                             filename, linenum, arg ? arg : "<NONE>");
590                 if (*activep && options->ciphers == NULL)
591                         options->ciphers = xstrdup(arg);
592                 break;
593
594         case oMacs:
595                 arg = strdelim(&s);
596                 if (!arg || *arg == '\0')
597                         fatal("%.200s line %d: Missing argument.", filename, linenum);
598                 if (!mac_valid(arg))
599                         fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
600                             filename, linenum, arg ? arg : "<NONE>");
601                 if (*activep && options->macs == NULL)
602                         options->macs = xstrdup(arg);
603                 break;
604
605         case oHostKeyAlgorithms:
606                 arg = strdelim(&s);
607                 if (!arg || *arg == '\0')
608                         fatal("%.200s line %d: Missing argument.", filename, linenum);
609                 if (!key_names_valid2(arg))
610                         fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
611                             filename, linenum, arg ? arg : "<NONE>");
612                 if (*activep && options->hostkeyalgorithms == NULL)
613                         options->hostkeyalgorithms = xstrdup(arg);
614                 break;
615
616         case oProtocol:
617                 intptr = &options->protocol;
618                 arg = strdelim(&s);
619                 if (!arg || *arg == '\0')
620                         fatal("%.200s line %d: Missing argument.", filename, linenum);
621                 value = proto_spec(arg);
622                 if (value == SSH_PROTO_UNKNOWN)
623                         fatal("%.200s line %d: Bad protocol spec '%s'.",
624                             filename, linenum, arg ? arg : "<NONE>");
625                 if (*activep && *intptr == SSH_PROTO_UNKNOWN)
626                         *intptr = value;
627                 break;
628
629         case oLogLevel:
630                 intptr = (int *) &options->log_level;
631                 arg = strdelim(&s);
632                 value = log_level_number(arg);
633                 if (value == SYSLOG_LEVEL_NOT_SET)
634                         fatal("%.200s line %d: unsupported log level '%s'",
635                             filename, linenum, arg ? arg : "<NONE>");
636                 if (*activep && (LogLevel) *intptr == SYSLOG_LEVEL_NOT_SET)
637                         *intptr = (LogLevel) value;
638                 break;
639
640         case oLocalForward:
641         case oRemoteForward:
642                 arg = strdelim(&s);
643                 if (!arg || *arg == '\0')
644                         fatal("%.200s line %d: Missing port argument.",
645                             filename, linenum);
646                 if ((fwd_port = a2port(arg)) == 0)
647                         fatal("%.200s line %d: Bad listen port.",
648                             filename, linenum);
649                 arg = strdelim(&s);
650                 if (!arg || *arg == '\0')
651                         fatal("%.200s line %d: Missing second argument.",
652                             filename, linenum);
653                 if (sscanf(arg, "%255[^:]:%5[0-9]", buf, sfwd_host_port) != 2 &&
654                     sscanf(arg, "%255[^/]/%5[0-9]", buf, sfwd_host_port) != 2)
655                         fatal("%.200s line %d: Bad forwarding specification.",
656                             filename, linenum);
657                 if ((fwd_host_port = a2port(sfwd_host_port)) == 0)
658                         fatal("%.200s line %d: Bad forwarding port.",
659                             filename, linenum);
660                 if (*activep) {
661                         if (opcode == oLocalForward)
662                                 add_local_forward(options, fwd_port, buf,
663                                     fwd_host_port);
664                         else if (opcode == oRemoteForward)
665                                 add_remote_forward(options, fwd_port, buf,
666                                     fwd_host_port);
667                 }
668                 break;
669
670         case oDynamicForward:
671                 arg = strdelim(&s);
672                 if (!arg || *arg == '\0')
673                         fatal("%.200s line %d: Missing port argument.",
674                             filename, linenum);
675                 fwd_port = a2port(arg);
676                 if (fwd_port == 0)
677                         fatal("%.200s line %d: Badly formatted port number.",
678                             filename, linenum);
679                 if (*activep)
680                         add_local_forward(options, fwd_port, "socks", 0);
681                 break;
682
683         case oClearAllForwardings:
684                 intptr = &options->clear_forwardings;
685                 goto parse_flag;
686
687         case oHost:
688                 *activep = 0;
689                 while ((arg = strdelim(&s)) != NULL && *arg != '\0')
690                         if (match_pattern(host, arg)) {
691                                 debug("Applying options for %.100s", arg);
692                                 *activep = 1;
693                                 break;
694                         }
695                 /* Avoid garbage check below, as strdelim is done. */
696                 return 0;
697
698         case oEscapeChar:
699                 intptr = &options->escape_char;
700                 arg = strdelim(&s);
701                 if (!arg || *arg == '\0')
702                         fatal("%.200s line %d: Missing argument.", filename, linenum);
703                 if (arg[0] == '^' && arg[2] == 0 &&
704                     (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
705                         value = (u_char) arg[1] & 31;
706                 else if (strlen(arg) == 1)
707                         value = (u_char) arg[0];
708                 else if (strcmp(arg, "none") == 0)
709                         value = SSH_ESCAPECHAR_NONE;
710                 else {
711                         fatal("%.200s line %d: Bad escape character.",
712                             filename, linenum);
713                         /* NOTREACHED */
714                         value = 0;      /* Avoid compiler warning. */
715                 }
716                 if (*activep && *intptr == -1)
717                         *intptr = value;
718                 break;
719
720         case oAddressFamily:
721                 arg = strdelim(&s);
722                 intptr = &options->address_family;
723                 if (strcasecmp(arg, "inet") == 0)
724                         value = AF_INET;
725                 else if (strcasecmp(arg, "inet6") == 0)
726                         value = AF_INET6;
727                 else if (strcasecmp(arg, "any") == 0)
728                         value = AF_UNSPEC;
729                 else
730                         fatal("Unsupported AddressFamily \"%s\"", arg);
731                 if (*activep && *intptr == -1)
732                         *intptr = value;
733                 break;
734
735         case oEnableSSHKeysign:
736                 intptr = &options->enable_ssh_keysign;
737                 goto parse_flag;
738
739         case oServerAliveInterval:
740                 intptr = &options->server_alive_interval;
741                 goto parse_time;
742
743         case oServerAliveCountMax:
744                 intptr = &options->server_alive_count_max;
745                 goto parse_int;
746
747         case oDeprecated:
748                 debug("%s line %d: Deprecated option \"%s\"",
749                     filename, linenum, keyword);
750                 return 0;
751
752         case oUnsupported:
753                 error("%s line %d: Unsupported option \"%s\"",
754                     filename, linenum, keyword);
755                 return 0;
756
757         default:
758                 fatal("process_config_line: Unimplemented opcode %d", opcode);
759         }
760
761         /* Check that there is no garbage at end of line. */
762         if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
763                 fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
764                      filename, linenum, arg);
765         }
766         return 0;
767 }
768
769
770 /*
771  * Reads the config file and modifies the options accordingly.  Options
772  * should already be initialized before this call.  This never returns if
773  * there is an error.  If the file does not exist, this returns 0.
774  */
775
776 int
777 read_config_file(const char *filename, const char *host, Options *options)
778 {
779         FILE *f;
780         char line[1024];
781         int active, linenum;
782         int bad_options = 0;
783
784         /* Open the file. */
785         f = fopen(filename, "r");
786         if (!f)
787                 return 0;
788
789         debug("Reading configuration data %.200s", filename);
790
791         /*
792          * Mark that we are now processing the options.  This flag is turned
793          * on/off by Host specifications.
794          */
795         active = 1;
796         linenum = 0;
797         while (fgets(line, sizeof(line), f)) {
798                 /* Update line number counter. */
799                 linenum++;
800                 if (process_config_line(options, host, line, filename, linenum, &active) != 0)
801                         bad_options++;
802         }
803         fclose(f);
804         if (bad_options > 0)
805                 fatal("%s: terminating, %d bad configuration options",
806                     filename, bad_options);
807         return 1;
808 }
809
810 /*
811  * Initializes options to special values that indicate that they have not yet
812  * been set.  Read_config_file will only set options with this value. Options
813  * are processed in the following order: command line, user config file,
814  * system config file.  Last, fill_default_options is called.
815  */
816
817 void
818 initialize_options(Options * options)
819 {
820         memset(options, 'X', sizeof(*options));
821         options->forward_agent = -1;
822         options->forward_x11 = -1;
823         options->forward_x11_trusted = -1;
824         options->xauth_location = NULL;
825         options->gateway_ports = -1;
826         options->use_privileged_port = -1;
827         options->rsa_authentication = -1;
828         options->pubkey_authentication = -1;
829         options->challenge_response_authentication = -1;
830         options->gss_authentication = -1;
831         options->gss_deleg_creds = -1;
832         options->password_authentication = -1;
833         options->kbd_interactive_authentication = -1;
834         options->kbd_interactive_devices = NULL;
835         options->rhosts_rsa_authentication = -1;
836         options->hostbased_authentication = -1;
837         options->batch_mode = -1;
838         options->check_host_ip = -1;
839         options->strict_host_key_checking = -1;
840         options->compression = -1;
841         options->tcp_keep_alive = -1;
842         options->compression_level = -1;
843         options->port = -1;
844         options->address_family = -1;
845         options->connection_attempts = -1;
846         options->connection_timeout = -1;
847         options->number_of_password_prompts = -1;
848         options->cipher = -1;
849         options->ciphers = NULL;
850         options->macs = NULL;
851         options->hostkeyalgorithms = NULL;
852         options->protocol = SSH_PROTO_UNKNOWN;
853         options->num_identity_files = 0;
854         options->hostname = NULL;
855         options->host_key_alias = NULL;
856         options->proxy_command = NULL;
857         options->user = NULL;
858         options->escape_char = -1;
859         options->system_hostfile = NULL;
860         options->user_hostfile = NULL;
861         options->system_hostfile2 = NULL;
862         options->user_hostfile2 = NULL;
863         options->num_local_forwards = 0;
864         options->num_remote_forwards = 0;
865         options->clear_forwardings = -1;
866         options->log_level = SYSLOG_LEVEL_NOT_SET;
867         options->preferred_authentications = NULL;
868         options->bind_address = NULL;
869         options->smartcard_device = NULL;
870         options->enable_ssh_keysign = - 1;
871         options->no_host_authentication_for_localhost = - 1;
872         options->rekey_limit = - 1;
873         options->verify_host_key_dns = -1;
874         options->server_alive_interval = -1;
875         options->server_alive_count_max = -1;
876 }
877
878 /*
879  * Called after processing other sources of option data, this fills those
880  * options for which no value has been specified with their default values.
881  */
882
883 void
884 fill_default_options(Options * options)
885 {
886         int len;
887
888         if (options->forward_agent == -1)
889                 options->forward_agent = 0;
890         if (options->forward_x11 == -1)
891                 options->forward_x11 = 0;
892         if (options->forward_x11_trusted == -1)
893                 options->forward_x11_trusted = 0;
894         if (options->xauth_location == NULL)
895                 options->xauth_location = _PATH_XAUTH;
896         if (options->gateway_ports == -1)
897                 options->gateway_ports = 0;
898         if (options->use_privileged_port == -1)
899                 options->use_privileged_port = 0;
900         if (options->rsa_authentication == -1)
901                 options->rsa_authentication = 1;
902         if (options->pubkey_authentication == -1)
903                 options->pubkey_authentication = 1;
904         if (options->challenge_response_authentication == -1)
905                 options->challenge_response_authentication = 1;
906         if (options->gss_authentication == -1)
907                 options->gss_authentication = 0;
908         if (options->gss_deleg_creds == -1)
909                 options->gss_deleg_creds = 0;
910         if (options->password_authentication == -1)
911                 options->password_authentication = 1;
912         if (options->kbd_interactive_authentication == -1)
913                 options->kbd_interactive_authentication = 1;
914         if (options->rhosts_rsa_authentication == -1)
915                 options->rhosts_rsa_authentication = 0;
916         if (options->hostbased_authentication == -1)
917                 options->hostbased_authentication = 0;
918         if (options->batch_mode == -1)
919                 options->batch_mode = 0;
920         if (options->check_host_ip == -1)
921                 options->check_host_ip = 1;
922         if (options->strict_host_key_checking == -1)
923                 options->strict_host_key_checking = 2;  /* 2 is default */
924         if (options->compression == -1)
925                 options->compression = 0;
926         if (options->tcp_keep_alive == -1)
927                 options->tcp_keep_alive = 1;
928         if (options->compression_level == -1)
929                 options->compression_level = 6;
930         if (options->port == -1)
931                 options->port = 0;      /* Filled in ssh_connect. */
932         if (options->address_family == -1)
933                 options->address_family = AF_UNSPEC;
934         if (options->connection_attempts == -1)
935                 options->connection_attempts = 1;
936         if (options->number_of_password_prompts == -1)
937                 options->number_of_password_prompts = 3;
938         /* Selected in ssh_login(). */
939         if (options->cipher == -1)
940                 options->cipher = SSH_CIPHER_NOT_SET;
941         /* options->ciphers, default set in myproposals.h */
942         /* options->macs, default set in myproposals.h */
943         /* options->hostkeyalgorithms, default set in myproposals.h */
944         if (options->protocol == SSH_PROTO_UNKNOWN)
945                 options->protocol = SSH_PROTO_1|SSH_PROTO_2;
946         if (options->num_identity_files == 0) {
947                 if (options->protocol & SSH_PROTO_1) {
948                         len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
949                         options->identity_files[options->num_identity_files] =
950                             xmalloc(len);
951                         snprintf(options->identity_files[options->num_identity_files++],
952                             len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
953                 }
954                 if (options->protocol & SSH_PROTO_2) {
955                         len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
956                         options->identity_files[options->num_identity_files] =
957                             xmalloc(len);
958                         snprintf(options->identity_files[options->num_identity_files++],
959                             len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
960
961                         len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
962                         options->identity_files[options->num_identity_files] =
963                             xmalloc(len);
964                         snprintf(options->identity_files[options->num_identity_files++],
965                             len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
966                 }
967         }
968         if (options->escape_char == -1)
969                 options->escape_char = '~';
970         if (options->system_hostfile == NULL)
971                 options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE;
972         if (options->user_hostfile == NULL)
973                 options->user_hostfile = _PATH_SSH_USER_HOSTFILE;
974         if (options->system_hostfile2 == NULL)
975                 options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2;
976         if (options->user_hostfile2 == NULL)
977                 options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2;
978         if (options->log_level == SYSLOG_LEVEL_NOT_SET)
979                 options->log_level = SYSLOG_LEVEL_INFO;
980         if (options->clear_forwardings == 1)
981                 clear_forwardings(options);
982         if (options->no_host_authentication_for_localhost == - 1)
983                 options->no_host_authentication_for_localhost = 0;
984         if (options->enable_ssh_keysign == -1)
985                 options->enable_ssh_keysign = 0;
986         if (options->rekey_limit == -1)
987                 options->rekey_limit = 0;
988         if (options->verify_host_key_dns == -1)
989                 options->verify_host_key_dns = 0;
990         if (options->server_alive_interval == -1)
991                 options->server_alive_interval = 0;
992         if (options->server_alive_count_max == -1)
993                 options->server_alive_count_max = 3;
994         /* options->proxy_command should not be set by default */
995         /* options->user will be set in the main program if appropriate */
996         /* options->hostname will be set in the main program if appropriate */
997         /* options->host_key_alias should not be set by default */
998         /* options->preferred_authentications will be set in ssh */
999 }
This page took 0.132431 seconds and 5 git commands to generate.