]> andersk Git - openssh.git/blob - readconf.c
e5f2620a719c30f85d83e6a4ff97eb36aad6ba5e
[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.123 2003/10/11 08:24:07 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      KeepAlives 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, oKeepAlives, 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         oDeprecated, oUnsupported
109 } OpCodes;
110
111 /* Textual representations of the tokens. */
112
113 static struct {
114         const char *name;
115         OpCodes opcode;
116 } keywords[] = {
117         { "forwardagent", oForwardAgent },
118         { "forwardx11", oForwardX11 },
119         { "forwardx11trusted", oForwardX11Trusted },
120         { "xauthlocation", oXAuthLocation },
121         { "gatewayports", oGatewayPorts },
122         { "useprivilegedport", oUsePrivilegedPort },
123         { "rhostsauthentication", oDeprecated },
124         { "passwordauthentication", oPasswordAuthentication },
125         { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
126         { "kbdinteractivedevices", oKbdInteractiveDevices },
127         { "rsaauthentication", oRSAAuthentication },
128         { "pubkeyauthentication", oPubkeyAuthentication },
129         { "dsaauthentication", oPubkeyAuthentication },             /* alias */
130         { "rhostsrsaauthentication", oRhostsRSAAuthentication },
131         { "hostbasedauthentication", oHostbasedAuthentication },
132         { "challengeresponseauthentication", oChallengeResponseAuthentication },
133         { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
134         { "tisauthentication", oChallengeResponseAuthentication },  /* alias */
135         { "kerberosauthentication", oUnsupported },
136         { "kerberostgtpassing", oUnsupported },
137         { "afstokenpassing", oUnsupported },
138 #if defined(GSSAPI)
139         { "gssapiauthentication", oGssAuthentication },
140         { "gssapidelegatecredentials", oGssDelegateCreds },
141 #else
142         { "gssapiauthentication", oUnsupported },
143         { "gssapidelegatecredentials", oUnsupported },
144 #endif
145         { "fallbacktorsh", oDeprecated },
146         { "usersh", oDeprecated },
147         { "identityfile", oIdentityFile },
148         { "identityfile2", oIdentityFile },                     /* alias */
149         { "hostname", oHostName },
150         { "hostkeyalias", oHostKeyAlias },
151         { "proxycommand", oProxyCommand },
152         { "port", oPort },
153         { "cipher", oCipher },
154         { "ciphers", oCiphers },
155         { "macs", oMacs },
156         { "protocol", oProtocol },
157         { "remoteforward", oRemoteForward },
158         { "localforward", oLocalForward },
159         { "user", oUser },
160         { "host", oHost },
161         { "escapechar", oEscapeChar },
162         { "globalknownhostsfile", oGlobalKnownHostsFile },
163         { "userknownhostsfile", oUserKnownHostsFile },          /* obsolete */
164         { "globalknownhostsfile2", oGlobalKnownHostsFile2 },
165         { "userknownhostsfile2", oUserKnownHostsFile2 },        /* obsolete */
166         { "connectionattempts", oConnectionAttempts },
167         { "batchmode", oBatchMode },
168         { "checkhostip", oCheckHostIP },
169         { "stricthostkeychecking", oStrictHostKeyChecking },
170         { "compression", oCompression },
171         { "compressionlevel", oCompressionLevel },
172         { "keepalive", oKeepAlives },
173         { "numberofpasswordprompts", oNumberOfPasswordPrompts },
174         { "loglevel", oLogLevel },
175         { "dynamicforward", oDynamicForward },
176         { "preferredauthentications", oPreferredAuthentications },
177         { "hostkeyalgorithms", oHostKeyAlgorithms },
178         { "bindaddress", oBindAddress },
179 #ifdef SMARTCARD
180         { "smartcarddevice", oSmartcardDevice },
181 #else
182         { "smartcarddevice", oUnsupported },
183 #endif
184         { "clearallforwardings", oClearAllForwardings },
185         { "enablesshkeysign", oEnableSSHKeysign },
186 #ifdef DNS
187         { "verifyhostkeydns", oVerifyHostKeyDNS },
188 #else
189         { "verifyhostkeydns", oUnsupported },
190 #endif
191         { "nohostauthenticationforlocalhost", oNoHostAuthenticationForLocalhost },
192         { "rekeylimit", oRekeyLimit },
193         { "connecttimeout", oConnectTimeout },
194         { "addressfamily", oAddressFamily },
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_flag;
409
410         case oStrictHostKeyChecking:
411                 intptr = &options->strict_host_key_checking;
412                 arg = strdelim(&s);
413                 if (!arg || *arg == '\0')
414                         fatal("%.200s line %d: Missing yes/no/ask argument.",
415                             filename, linenum);
416                 value = 0;      /* To avoid compiler warning... */
417                 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
418                         value = 1;
419                 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
420                         value = 0;
421                 else if (strcmp(arg, "ask") == 0)
422                         value = 2;
423                 else
424                         fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
425                 if (*activep && *intptr == -1)
426                         *intptr = value;
427                 break;
428
429         case oCompression:
430                 intptr = &options->compression;
431                 goto parse_flag;
432
433         case oKeepAlives:
434                 intptr = &options->keepalives;
435                 goto parse_flag;
436
437         case oNoHostAuthenticationForLocalhost:
438                 intptr = &options->no_host_authentication_for_localhost;
439                 goto parse_flag;
440
441         case oNumberOfPasswordPrompts:
442                 intptr = &options->number_of_password_prompts;
443                 goto parse_int;
444
445         case oCompressionLevel:
446                 intptr = &options->compression_level;
447                 goto parse_int;
448
449         case oRekeyLimit:
450                 intptr = &options->rekey_limit;
451                 arg = strdelim(&s);
452                 if (!arg || *arg == '\0')
453                         fatal("%.200s line %d: Missing argument.", filename, linenum);
454                 if (arg[0] < '0' || arg[0] > '9')
455                         fatal("%.200s line %d: Bad number.", filename, linenum);
456                 value = strtol(arg, &endofnumber, 10);
457                 if (arg == endofnumber)
458                         fatal("%.200s line %d: Bad number.", filename, linenum);
459                 switch (toupper(*endofnumber)) {
460                 case 'K':
461                         value *= 1<<10;
462                         break;
463                 case 'M':
464                         value *= 1<<20;
465                         break;
466                 case 'G':
467                         value *= 1<<30;
468                         break;
469                 }
470                 if (*activep && *intptr == -1)
471                         *intptr = value;
472                 break;
473
474         case oIdentityFile:
475                 arg = strdelim(&s);
476                 if (!arg || *arg == '\0')
477                         fatal("%.200s line %d: Missing argument.", filename, linenum);
478                 if (*activep) {
479                         intptr = &options->num_identity_files;
480                         if (*intptr >= SSH_MAX_IDENTITY_FILES)
481                                 fatal("%.200s line %d: Too many identity files specified (max %d).",
482                                     filename, linenum, SSH_MAX_IDENTITY_FILES);
483                         charptr =  &options->identity_files[*intptr];
484                         *charptr = xstrdup(arg);
485                         *intptr = *intptr + 1;
486                 }
487                 break;
488
489         case oXAuthLocation:
490                 charptr=&options->xauth_location;
491                 goto parse_string;
492
493         case oUser:
494                 charptr = &options->user;
495 parse_string:
496                 arg = strdelim(&s);
497                 if (!arg || *arg == '\0')
498                         fatal("%.200s line %d: Missing argument.", filename, linenum);
499                 if (*activep && *charptr == NULL)
500                         *charptr = xstrdup(arg);
501                 break;
502
503         case oGlobalKnownHostsFile:
504                 charptr = &options->system_hostfile;
505                 goto parse_string;
506
507         case oUserKnownHostsFile:
508                 charptr = &options->user_hostfile;
509                 goto parse_string;
510
511         case oGlobalKnownHostsFile2:
512                 charptr = &options->system_hostfile2;
513                 goto parse_string;
514
515         case oUserKnownHostsFile2:
516                 charptr = &options->user_hostfile2;
517                 goto parse_string;
518
519         case oHostName:
520                 charptr = &options->hostname;
521                 goto parse_string;
522
523         case oHostKeyAlias:
524                 charptr = &options->host_key_alias;
525                 goto parse_string;
526
527         case oPreferredAuthentications:
528                 charptr = &options->preferred_authentications;
529                 goto parse_string;
530
531         case oBindAddress:
532                 charptr = &options->bind_address;
533                 goto parse_string;
534
535         case oSmartcardDevice:
536                 charptr = &options->smartcard_device;
537                 goto parse_string;
538
539         case oProxyCommand:
540                 if (s == NULL)
541                         fatal("%.200s line %d: Missing argument.", filename, linenum);
542                 charptr = &options->proxy_command;
543                 len = strspn(s, WHITESPACE "=");
544                 if (*activep && *charptr == NULL)
545                         *charptr = xstrdup(s + len);
546                 return 0;
547
548         case oPort:
549                 intptr = &options->port;
550 parse_int:
551                 arg = strdelim(&s);
552                 if (!arg || *arg == '\0')
553                         fatal("%.200s line %d: Missing argument.", filename, linenum);
554                 if (arg[0] < '0' || arg[0] > '9')
555                         fatal("%.200s line %d: Bad number.", filename, linenum);
556
557                 /* Octal, decimal, or hex format? */
558                 value = strtol(arg, &endofnumber, 0);
559                 if (arg == endofnumber)
560                         fatal("%.200s line %d: Bad number.", filename, linenum);
561                 if (*activep && *intptr == -1)
562                         *intptr = value;
563                 break;
564
565         case oConnectionAttempts:
566                 intptr = &options->connection_attempts;
567                 goto parse_int;
568
569         case oCipher:
570                 intptr = &options->cipher;
571                 arg = strdelim(&s);
572                 if (!arg || *arg == '\0')
573                         fatal("%.200s line %d: Missing argument.", filename, linenum);
574                 value = cipher_number(arg);
575                 if (value == -1)
576                         fatal("%.200s line %d: Bad cipher '%s'.",
577                             filename, linenum, arg ? arg : "<NONE>");
578                 if (*activep && *intptr == -1)
579                         *intptr = value;
580                 break;
581
582         case oCiphers:
583                 arg = strdelim(&s);
584                 if (!arg || *arg == '\0')
585                         fatal("%.200s line %d: Missing argument.", filename, linenum);
586                 if (!ciphers_valid(arg))
587                         fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
588                             filename, linenum, arg ? arg : "<NONE>");
589                 if (*activep && options->ciphers == NULL)
590                         options->ciphers = xstrdup(arg);
591                 break;
592
593         case oMacs:
594                 arg = strdelim(&s);
595                 if (!arg || *arg == '\0')
596                         fatal("%.200s line %d: Missing argument.", filename, linenum);
597                 if (!mac_valid(arg))
598                         fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
599                             filename, linenum, arg ? arg : "<NONE>");
600                 if (*activep && options->macs == NULL)
601                         options->macs = xstrdup(arg);
602                 break;
603
604         case oHostKeyAlgorithms:
605                 arg = strdelim(&s);
606                 if (!arg || *arg == '\0')
607                         fatal("%.200s line %d: Missing argument.", filename, linenum);
608                 if (!key_names_valid2(arg))
609                         fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
610                             filename, linenum, arg ? arg : "<NONE>");
611                 if (*activep && options->hostkeyalgorithms == NULL)
612                         options->hostkeyalgorithms = xstrdup(arg);
613                 break;
614
615         case oProtocol:
616                 intptr = &options->protocol;
617                 arg = strdelim(&s);
618                 if (!arg || *arg == '\0')
619                         fatal("%.200s line %d: Missing argument.", filename, linenum);
620                 value = proto_spec(arg);
621                 if (value == SSH_PROTO_UNKNOWN)
622                         fatal("%.200s line %d: Bad protocol spec '%s'.",
623                             filename, linenum, arg ? arg : "<NONE>");
624                 if (*activep && *intptr == SSH_PROTO_UNKNOWN)
625                         *intptr = value;
626                 break;
627
628         case oLogLevel:
629                 intptr = (int *) &options->log_level;
630                 arg = strdelim(&s);
631                 value = log_level_number(arg);
632                 if (value == SYSLOG_LEVEL_NOT_SET)
633                         fatal("%.200s line %d: unsupported log level '%s'",
634                             filename, linenum, arg ? arg : "<NONE>");
635                 if (*activep && (LogLevel) *intptr == SYSLOG_LEVEL_NOT_SET)
636                         *intptr = (LogLevel) value;
637                 break;
638
639         case oLocalForward:
640         case oRemoteForward:
641                 arg = strdelim(&s);
642                 if (!arg || *arg == '\0')
643                         fatal("%.200s line %d: Missing port argument.",
644                             filename, linenum);
645                 if ((fwd_port = a2port(arg)) == 0)
646                         fatal("%.200s line %d: Bad listen port.",
647                             filename, linenum);
648                 arg = strdelim(&s);
649                 if (!arg || *arg == '\0')
650                         fatal("%.200s line %d: Missing second argument.",
651                             filename, linenum);
652                 if (sscanf(arg, "%255[^:]:%5[0-9]", buf, sfwd_host_port) != 2 &&
653                     sscanf(arg, "%255[^/]/%5[0-9]", buf, sfwd_host_port) != 2)
654                         fatal("%.200s line %d: Bad forwarding specification.",
655                             filename, linenum);
656                 if ((fwd_host_port = a2port(sfwd_host_port)) == 0)
657                         fatal("%.200s line %d: Bad forwarding port.",
658                             filename, linenum);
659                 if (*activep) {
660                         if (opcode == oLocalForward)
661                                 add_local_forward(options, fwd_port, buf,
662                                     fwd_host_port);
663                         else if (opcode == oRemoteForward)
664                                 add_remote_forward(options, fwd_port, buf,
665                                     fwd_host_port);
666                 }
667                 break;
668
669         case oDynamicForward:
670                 arg = strdelim(&s);
671                 if (!arg || *arg == '\0')
672                         fatal("%.200s line %d: Missing port argument.",
673                             filename, linenum);
674                 fwd_port = a2port(arg);
675                 if (fwd_port == 0)
676                         fatal("%.200s line %d: Badly formatted port number.",
677                             filename, linenum);
678                 if (*activep)
679                         add_local_forward(options, fwd_port, "socks", 0);
680                 break;
681
682         case oClearAllForwardings:
683                 intptr = &options->clear_forwardings;
684                 goto parse_flag;
685
686         case oHost:
687                 *activep = 0;
688                 while ((arg = strdelim(&s)) != NULL && *arg != '\0')
689                         if (match_pattern(host, arg)) {
690                                 debug("Applying options for %.100s", arg);
691                                 *activep = 1;
692                                 break;
693                         }
694                 /* Avoid garbage check below, as strdelim is done. */
695                 return 0;
696
697         case oEscapeChar:
698                 intptr = &options->escape_char;
699                 arg = strdelim(&s);
700                 if (!arg || *arg == '\0')
701                         fatal("%.200s line %d: Missing argument.", filename, linenum);
702                 if (arg[0] == '^' && arg[2] == 0 &&
703                     (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
704                         value = (u_char) arg[1] & 31;
705                 else if (strlen(arg) == 1)
706                         value = (u_char) arg[0];
707                 else if (strcmp(arg, "none") == 0)
708                         value = SSH_ESCAPECHAR_NONE;
709                 else {
710                         fatal("%.200s line %d: Bad escape character.",
711                             filename, linenum);
712                         /* NOTREACHED */
713                         value = 0;      /* Avoid compiler warning. */
714                 }
715                 if (*activep && *intptr == -1)
716                         *intptr = value;
717                 break;
718
719         case oAddressFamily:
720                 arg = strdelim(&s);
721                 intptr = &options->address_family;
722                 if (strcasecmp(arg, "inet") == 0)
723                         value = AF_INET;
724                 else if (strcasecmp(arg, "inet6") == 0)
725                         value = AF_INET6;
726                 else if (strcasecmp(arg, "any") == 0)
727                         value = AF_UNSPEC;
728                 else
729                         fatal("Unsupported AddressFamily \"%s\"", arg);
730                 if (*activep && *intptr == -1)
731                         *intptr = value;
732                 break;
733
734         case oEnableSSHKeysign:
735                 intptr = &options->enable_ssh_keysign;
736                 goto parse_flag;
737
738         case oDeprecated:
739                 debug("%s line %d: Deprecated option \"%s\"",
740                     filename, linenum, keyword);
741                 return 0;
742
743         case oUnsupported:
744                 error("%s line %d: Unsupported option \"%s\"",
745                     filename, linenum, keyword);
746                 return 0;
747
748         default:
749                 fatal("process_config_line: Unimplemented opcode %d", opcode);
750         }
751
752         /* Check that there is no garbage at end of line. */
753         if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
754                 fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
755                      filename, linenum, arg);
756         }
757         return 0;
758 }
759
760
761 /*
762  * Reads the config file and modifies the options accordingly.  Options
763  * should already be initialized before this call.  This never returns if
764  * there is an error.  If the file does not exist, this returns 0.
765  */
766
767 int
768 read_config_file(const char *filename, const char *host, Options *options)
769 {
770         FILE *f;
771         char line[1024];
772         int active, linenum;
773         int bad_options = 0;
774
775         /* Open the file. */
776         f = fopen(filename, "r");
777         if (!f)
778                 return 0;
779
780         debug("Reading configuration data %.200s", filename);
781
782         /*
783          * Mark that we are now processing the options.  This flag is turned
784          * on/off by Host specifications.
785          */
786         active = 1;
787         linenum = 0;
788         while (fgets(line, sizeof(line), f)) {
789                 /* Update line number counter. */
790                 linenum++;
791                 if (process_config_line(options, host, line, filename, linenum, &active) != 0)
792                         bad_options++;
793         }
794         fclose(f);
795         if (bad_options > 0)
796                 fatal("%s: terminating, %d bad configuration options",
797                     filename, bad_options);
798         return 1;
799 }
800
801 /*
802  * Initializes options to special values that indicate that they have not yet
803  * been set.  Read_config_file will only set options with this value. Options
804  * are processed in the following order: command line, user config file,
805  * system config file.  Last, fill_default_options is called.
806  */
807
808 void
809 initialize_options(Options * options)
810 {
811         memset(options, 'X', sizeof(*options));
812         options->forward_agent = -1;
813         options->forward_x11 = -1;
814         options->forward_x11_trusted = -1;
815         options->xauth_location = NULL;
816         options->gateway_ports = -1;
817         options->use_privileged_port = -1;
818         options->rsa_authentication = -1;
819         options->pubkey_authentication = -1;
820         options->challenge_response_authentication = -1;
821         options->gss_authentication = -1;
822         options->gss_deleg_creds = -1;
823         options->password_authentication = -1;
824         options->kbd_interactive_authentication = -1;
825         options->kbd_interactive_devices = NULL;
826         options->rhosts_rsa_authentication = -1;
827         options->hostbased_authentication = -1;
828         options->batch_mode = -1;
829         options->check_host_ip = -1;
830         options->strict_host_key_checking = -1;
831         options->compression = -1;
832         options->keepalives = -1;
833         options->compression_level = -1;
834         options->port = -1;
835         options->address_family = -1;
836         options->connection_attempts = -1;
837         options->connection_timeout = -1;
838         options->number_of_password_prompts = -1;
839         options->cipher = -1;
840         options->ciphers = NULL;
841         options->macs = NULL;
842         options->hostkeyalgorithms = NULL;
843         options->protocol = SSH_PROTO_UNKNOWN;
844         options->num_identity_files = 0;
845         options->hostname = NULL;
846         options->host_key_alias = NULL;
847         options->proxy_command = NULL;
848         options->user = NULL;
849         options->escape_char = -1;
850         options->system_hostfile = NULL;
851         options->user_hostfile = NULL;
852         options->system_hostfile2 = NULL;
853         options->user_hostfile2 = NULL;
854         options->num_local_forwards = 0;
855         options->num_remote_forwards = 0;
856         options->clear_forwardings = -1;
857         options->log_level = SYSLOG_LEVEL_NOT_SET;
858         options->preferred_authentications = NULL;
859         options->bind_address = NULL;
860         options->smartcard_device = NULL;
861         options->enable_ssh_keysign = - 1;
862         options->no_host_authentication_for_localhost = - 1;
863         options->rekey_limit = - 1;
864         options->verify_host_key_dns = -1;
865 }
866
867 /*
868  * Called after processing other sources of option data, this fills those
869  * options for which no value has been specified with their default values.
870  */
871
872 void
873 fill_default_options(Options * options)
874 {
875         int len;
876
877         if (options->forward_agent == -1)
878                 options->forward_agent = 0;
879         if (options->forward_x11 == -1)
880                 options->forward_x11 = 0;
881         if (options->forward_x11_trusted == -1)
882                 options->forward_x11_trusted = 0;
883         if (options->xauth_location == NULL)
884                 options->xauth_location = _PATH_XAUTH;
885         if (options->gateway_ports == -1)
886                 options->gateway_ports = 0;
887         if (options->use_privileged_port == -1)
888                 options->use_privileged_port = 0;
889         if (options->rsa_authentication == -1)
890                 options->rsa_authentication = 1;
891         if (options->pubkey_authentication == -1)
892                 options->pubkey_authentication = 1;
893         if (options->challenge_response_authentication == -1)
894                 options->challenge_response_authentication = 1;
895         if (options->gss_authentication == -1)
896                 options->gss_authentication = 0;
897         if (options->gss_deleg_creds == -1)
898                 options->gss_deleg_creds = 0;
899         if (options->password_authentication == -1)
900                 options->password_authentication = 1;
901         if (options->kbd_interactive_authentication == -1)
902                 options->kbd_interactive_authentication = 1;
903         if (options->rhosts_rsa_authentication == -1)
904                 options->rhosts_rsa_authentication = 0;
905         if (options->hostbased_authentication == -1)
906                 options->hostbased_authentication = 0;
907         if (options->batch_mode == -1)
908                 options->batch_mode = 0;
909         if (options->check_host_ip == -1)
910                 options->check_host_ip = 1;
911         if (options->strict_host_key_checking == -1)
912                 options->strict_host_key_checking = 2;  /* 2 is default */
913         if (options->compression == -1)
914                 options->compression = 0;
915         if (options->keepalives == -1)
916                 options->keepalives = 1;
917         if (options->compression_level == -1)
918                 options->compression_level = 6;
919         if (options->port == -1)
920                 options->port = 0;      /* Filled in ssh_connect. */
921         if (options->address_family == -1)
922                 options->address_family = AF_UNSPEC;
923         if (options->connection_attempts == -1)
924                 options->connection_attempts = 1;
925         if (options->number_of_password_prompts == -1)
926                 options->number_of_password_prompts = 3;
927         /* Selected in ssh_login(). */
928         if (options->cipher == -1)
929                 options->cipher = SSH_CIPHER_NOT_SET;
930         /* options->ciphers, default set in myproposals.h */
931         /* options->macs, default set in myproposals.h */
932         /* options->hostkeyalgorithms, default set in myproposals.h */
933         if (options->protocol == SSH_PROTO_UNKNOWN)
934                 options->protocol = SSH_PROTO_1|SSH_PROTO_2;
935         if (options->num_identity_files == 0) {
936                 if (options->protocol & SSH_PROTO_1) {
937                         len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
938                         options->identity_files[options->num_identity_files] =
939                             xmalloc(len);
940                         snprintf(options->identity_files[options->num_identity_files++],
941                             len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
942                 }
943                 if (options->protocol & SSH_PROTO_2) {
944                         len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
945                         options->identity_files[options->num_identity_files] =
946                             xmalloc(len);
947                         snprintf(options->identity_files[options->num_identity_files++],
948                             len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
949
950                         len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
951                         options->identity_files[options->num_identity_files] =
952                             xmalloc(len);
953                         snprintf(options->identity_files[options->num_identity_files++],
954                             len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
955                 }
956         }
957         if (options->escape_char == -1)
958                 options->escape_char = '~';
959         if (options->system_hostfile == NULL)
960                 options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE;
961         if (options->user_hostfile == NULL)
962                 options->user_hostfile = _PATH_SSH_USER_HOSTFILE;
963         if (options->system_hostfile2 == NULL)
964                 options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2;
965         if (options->user_hostfile2 == NULL)
966                 options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2;
967         if (options->log_level == SYSLOG_LEVEL_NOT_SET)
968                 options->log_level = SYSLOG_LEVEL_INFO;
969         if (options->clear_forwardings == 1)
970                 clear_forwardings(options);
971         if (options->no_host_authentication_for_localhost == - 1)
972                 options->no_host_authentication_for_localhost = 0;
973         if (options->enable_ssh_keysign == -1)
974                 options->enable_ssh_keysign = 0;
975         if (options->rekey_limit == -1)
976                 options->rekey_limit = 0;
977         if (options->verify_host_key_dns == -1)
978                 options->verify_host_key_dns = 0;
979         /* options->proxy_command should not be set by default */
980         /* options->user will be set in the main program if appropriate */
981         /* options->hostname will be set in the main program if appropriate */
982         /* options->host_key_alias should not be set by default */
983         /* options->preferred_authentications will be set in ssh */
984 }
This page took 2.033856 seconds and 3 git commands to generate.