]> andersk Git - openssh.git/blob - readconf.c
- markus@cvs.openbsd.org 2001/07/22 22:04:19
[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.83 2001/07/22 22:04:19 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      FallBackToRsh no
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      RhostsAuthentication no
61      PasswordAuthentication no
62
63    Host puukko.hut.fi
64      User t35124p
65      ProxyCommand ssh-proxy %h %p
66
67    Host *.fr
68      UseRsh yes
69
70    Host *.su
71      Cipher none
72      PasswordAuthentication no
73
74    # Defaults for various options
75    Host *
76      ForwardAgent no
77      ForwardX11 no
78      RhostsAuthentication yes
79      PasswordAuthentication yes
80      RSAAuthentication yes
81      RhostsRSAAuthentication yes
82      FallBackToRsh no
83      UseRsh no
84      StrictHostKeyChecking yes
85      KeepAlives no
86      IdentityFile ~/.ssh/identity
87      Port 22
88      EscapeChar ~
89
90 */
91
92 /* Keyword tokens. */
93
94 typedef enum {
95         oBadOption,
96         oForwardAgent, oForwardX11, oGatewayPorts, oRhostsAuthentication,
97         oPasswordAuthentication, oRSAAuthentication, oFallBackToRsh, oUseRsh,
98         oChallengeResponseAuthentication, oXAuthLocation,
99 #if defined(KRB4) || defined(KRB5)
100         oKerberosAuthentication,
101 #endif
102 #if defined(AFS) || defined(KRB5)
103         oKerberosTgtPassing,
104 #endif
105 #ifdef AFS
106         oAFSTokenPassing,
107 #endif
108         oIdentityFile, oHostName, oPort, oCipher, oRemoteForward, oLocalForward,
109         oUser, oHost, oEscapeChar, oRhostsRSAAuthentication, oProxyCommand,
110         oGlobalKnownHostsFile, oUserKnownHostsFile, oConnectionAttempts,
111         oBatchMode, oCheckHostIP, oStrictHostKeyChecking, oCompression,
112         oCompressionLevel, oKeepAlives, oNumberOfPasswordPrompts,
113         oUsePrivilegedPort, oLogLevel, oCiphers, oProtocol, oMacs,
114         oGlobalKnownHostsFile2, oUserKnownHostsFile2, oPubkeyAuthentication,
115         oKbdInteractiveAuthentication, oKbdInteractiveDevices, oHostKeyAlias,
116         oDynamicForward, oPreferredAuthentications, oHostbasedAuthentication,
117         oHostKeyAlgorithms, oBindAddress
118 } OpCodes;
119
120 /* Textual representations of the tokens. */
121
122 static struct {
123         const char *name;
124         OpCodes opcode;
125 } keywords[] = {
126         { "forwardagent", oForwardAgent },
127         { "forwardx11", oForwardX11 },
128         { "xauthlocation", oXAuthLocation },
129         { "gatewayports", oGatewayPorts },
130         { "useprivilegedport", oUsePrivilegedPort },
131         { "rhostsauthentication", oRhostsAuthentication },
132         { "passwordauthentication", oPasswordAuthentication },
133         { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
134         { "kbdinteractivedevices", oKbdInteractiveDevices },
135         { "rsaauthentication", oRSAAuthentication },
136         { "pubkeyauthentication", oPubkeyAuthentication },
137         { "dsaauthentication", oPubkeyAuthentication },             /* alias */
138         { "rhostsrsaauthentication", oRhostsRSAAuthentication },
139         { "hostbasedauthentication", oHostbasedAuthentication },
140         { "challengeresponseauthentication", oChallengeResponseAuthentication },
141         { "skeyauthentication", oChallengeResponseAuthentication }, /* alias */
142         { "tisauthentication", oChallengeResponseAuthentication },  /* alias */
143 #if defined(KRB4) || defined(KRB5)
144         { "kerberosauthentication", oKerberosAuthentication },
145 #endif
146 #if defined(AFS) || defined(KRB5)
147         { "kerberostgtpassing", oKerberosTgtPassing },
148 #endif
149 #ifdef AFS
150         { "afstokenpassing", oAFSTokenPassing },
151 #endif
152         { "fallbacktorsh", oFallBackToRsh },
153         { "usersh", oUseRsh },
154         { "identityfile", oIdentityFile },
155         { "identityfile2", oIdentityFile },                     /* alias */
156         { "hostname", oHostName },
157         { "hostkeyalias", oHostKeyAlias },
158         { "proxycommand", oProxyCommand },
159         { "port", oPort },
160         { "cipher", oCipher },
161         { "ciphers", oCiphers },
162         { "macs", oMacs },
163         { "protocol", oProtocol },
164         { "remoteforward", oRemoteForward },
165         { "localforward", oLocalForward },
166         { "user", oUser },
167         { "host", oHost },
168         { "escapechar", oEscapeChar },
169         { "globalknownhostsfile", oGlobalKnownHostsFile },
170         { "userknownhostsfile", oUserKnownHostsFile },          /* obsolete */
171         { "globalknownhostsfile2", oGlobalKnownHostsFile2 },
172         { "userknownhostsfile2", oUserKnownHostsFile2 },        /* obsolete */
173         { "connectionattempts", oConnectionAttempts },
174         { "batchmode", oBatchMode },
175         { "checkhostip", oCheckHostIP },
176         { "stricthostkeychecking", oStrictHostKeyChecking },
177         { "compression", oCompression },
178         { "compressionlevel", oCompressionLevel },
179         { "keepalive", oKeepAlives },
180         { "numberofpasswordprompts", oNumberOfPasswordPrompts },
181         { "loglevel", oLogLevel },
182         { "dynamicforward", oDynamicForward },
183         { "preferredauthentications", oPreferredAuthentications },
184         { "hostkeyalgorithms", oHostKeyAlgorithms },
185         { "bindaddress", oBindAddress },
186         { NULL, 0 }
187 };
188
189 /*
190  * Adds a local TCP/IP port forward to options.  Never returns if there is an
191  * error.
192  */
193
194 void
195 add_local_forward(Options *options, u_short port, const char *host,
196                   u_short host_port)
197 {
198         Forward *fwd;
199 #ifndef HAVE_CYGWIN
200         extern uid_t original_real_uid;
201         if (port < IPPORT_RESERVED && original_real_uid != 0)
202                 fatal("Privileged ports can only be forwarded by root.");
203 #endif
204         if (options->num_local_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
205                 fatal("Too many local forwards (max %d).", SSH_MAX_FORWARDS_PER_DIRECTION);
206         fwd = &options->local_forwards[options->num_local_forwards++];
207         fwd->port = port;
208         fwd->host = xstrdup(host);
209         fwd->host_port = host_port;
210 }
211
212 /*
213  * Adds a remote TCP/IP port forward to options.  Never returns if there is
214  * an error.
215  */
216
217 void
218 add_remote_forward(Options *options, u_short port, const char *host,
219                    u_short host_port)
220 {
221         Forward *fwd;
222         if (options->num_remote_forwards >= SSH_MAX_FORWARDS_PER_DIRECTION)
223                 fatal("Too many remote forwards (max %d).",
224                       SSH_MAX_FORWARDS_PER_DIRECTION);
225         fwd = &options->remote_forwards[options->num_remote_forwards++];
226         fwd->port = port;
227         fwd->host = xstrdup(host);
228         fwd->host_port = host_port;
229 }
230
231 /*
232  * Returns the number of the token pointed to by cp or oBadOption.
233  */
234
235 static OpCodes
236 parse_token(const char *cp, const char *filename, int linenum)
237 {
238         u_int i;
239
240         for (i = 0; keywords[i].name; i++)
241                 if (strcasecmp(cp, keywords[i].name) == 0)
242                         return keywords[i].opcode;
243
244         error("%s: line %d: Bad configuration option: %s",
245             filename, linenum, cp);
246         return oBadOption;
247 }
248
249 /*
250  * Processes a single option line as used in the configuration files. This
251  * only sets those values that have not already been set.
252  */
253
254 int
255 process_config_line(Options *options, const char *host,
256                     char *line, const char *filename, int linenum,
257                     int *activep)
258 {
259         char buf[256], *s, *string = NULL, **charptr, *endofnumber, *keyword, 
260             *arg;
261         int opcode, *intptr, value;
262         u_short fwd_port, fwd_host_port;
263
264         s = line;
265         /* Get the keyword. (Each line is supposed to begin with a keyword). */
266         keyword = strdelim(&s);
267         /* Ignore leading whitespace. */
268         if (*keyword == '\0')
269                 keyword = strdelim(&s);
270         if (keyword == NULL || !*keyword || *keyword == '\n' || *keyword == '#')
271                 return 0;
272
273         opcode = parse_token(keyword, filename, linenum);
274
275         switch (opcode) {
276         case oBadOption:
277                 /* don't panic, but count bad options */
278                 return -1;
279                 /* NOTREACHED */
280         case oForwardAgent:
281                 intptr = &options->forward_agent;
282 parse_flag:
283                 arg = strdelim(&s);
284                 if (!arg || *arg == '\0')
285                         fatal("%.200s line %d: Missing yes/no argument.", filename, linenum);
286                 value = 0;      /* To avoid compiler warning... */
287                 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
288                         value = 1;
289                 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
290                         value = 0;
291                 else
292                         fatal("%.200s line %d: Bad yes/no argument.", filename, linenum);
293                 if (*activep && *intptr == -1)
294                         *intptr = value;
295                 break;
296
297         case oForwardX11:
298                 intptr = &options->forward_x11;
299                 goto parse_flag;
300
301         case oGatewayPorts:
302                 intptr = &options->gateway_ports;
303                 goto parse_flag;
304
305         case oUsePrivilegedPort:
306                 intptr = &options->use_privileged_port;
307                 goto parse_flag;
308
309         case oRhostsAuthentication:
310                 intptr = &options->rhosts_authentication;
311                 goto parse_flag;
312
313         case oPasswordAuthentication:
314                 intptr = &options->password_authentication;
315                 goto parse_flag;
316
317         case oKbdInteractiveAuthentication:
318                 intptr = &options->kbd_interactive_authentication;
319                 goto parse_flag;
320
321         case oKbdInteractiveDevices:
322                 charptr = &options->kbd_interactive_devices;
323                 goto parse_string;
324
325         case oPubkeyAuthentication:
326                 intptr = &options->pubkey_authentication;
327                 goto parse_flag;
328
329         case oRSAAuthentication:
330                 intptr = &options->rsa_authentication;
331                 goto parse_flag;
332
333         case oRhostsRSAAuthentication:
334                 intptr = &options->rhosts_rsa_authentication;
335                 goto parse_flag;
336
337         case oHostbasedAuthentication:
338                 intptr = &options->hostbased_authentication;
339                 goto parse_flag;
340
341         case oChallengeResponseAuthentication:
342                 intptr = &options->challenge_response_authentication;
343                 goto parse_flag;
344 #if defined(KRB4) || defined(KRB5)
345         case oKerberosAuthentication:
346                 intptr = &options->kerberos_authentication;
347                 goto parse_flag;
348 #endif
349 #if defined(AFS) || defined(KRB5)
350         case oKerberosTgtPassing:
351                 intptr = &options->kerberos_tgt_passing;
352                 goto parse_flag;
353 #endif
354 #ifdef AFS
355         case oAFSTokenPassing:
356                 intptr = &options->afs_token_passing;
357                 goto parse_flag;
358 #endif
359         case oFallBackToRsh:
360                 intptr = &options->fallback_to_rsh;
361                 goto parse_flag;
362
363         case oUseRsh:
364                 intptr = &options->use_rsh;
365                 goto parse_flag;
366
367         case oBatchMode:
368                 intptr = &options->batch_mode;
369                 goto parse_flag;
370
371         case oCheckHostIP:
372                 intptr = &options->check_host_ip;
373                 goto parse_flag;
374
375         case oStrictHostKeyChecking:
376                 intptr = &options->strict_host_key_checking;
377                 arg = strdelim(&s);
378                 if (!arg || *arg == '\0')
379                         fatal("%.200s line %d: Missing yes/no/ask argument.",
380                               filename, linenum);
381                 value = 0;      /* To avoid compiler warning... */
382                 if (strcmp(arg, "yes") == 0 || strcmp(arg, "true") == 0)
383                         value = 1;
384                 else if (strcmp(arg, "no") == 0 || strcmp(arg, "false") == 0)
385                         value = 0;
386                 else if (strcmp(arg, "ask") == 0)
387                         value = 2;
388                 else
389                         fatal("%.200s line %d: Bad yes/no/ask argument.", filename, linenum);
390                 if (*activep && *intptr == -1)
391                         *intptr = value;
392                 break;
393
394         case oCompression:
395                 intptr = &options->compression;
396                 goto parse_flag;
397
398         case oKeepAlives:
399                 intptr = &options->keepalives;
400                 goto parse_flag;
401
402         case oNumberOfPasswordPrompts:
403                 intptr = &options->number_of_password_prompts;
404                 goto parse_int;
405
406         case oCompressionLevel:
407                 intptr = &options->compression_level;
408                 goto parse_int;
409
410         case oIdentityFile:
411                 arg = strdelim(&s);
412                 if (!arg || *arg == '\0')
413                         fatal("%.200s line %d: Missing argument.", filename, linenum);
414                 if (*activep) {
415                         intptr = &options->num_identity_files;
416                         if (*intptr >= SSH_MAX_IDENTITY_FILES)
417                                 fatal("%.200s line %d: Too many identity files specified (max %d).",
418                                       filename, linenum, SSH_MAX_IDENTITY_FILES);
419                         charptr =  &options->identity_files[*intptr];
420                         *charptr = xstrdup(arg);
421                         *intptr = *intptr + 1;
422                 }
423                 break;
424
425         case oXAuthLocation:
426                 charptr=&options->xauth_location;
427                 goto parse_string;
428
429         case oUser:
430                 charptr = &options->user;
431 parse_string:
432                 arg = strdelim(&s);
433                 if (!arg || *arg == '\0')
434                         fatal("%.200s line %d: Missing argument.", filename, linenum);
435                 if (*activep && *charptr == NULL)
436                         *charptr = xstrdup(arg);
437                 break;
438
439         case oGlobalKnownHostsFile:
440                 charptr = &options->system_hostfile;
441                 goto parse_string;
442
443         case oUserKnownHostsFile:
444                 charptr = &options->user_hostfile;
445                 goto parse_string;
446
447         case oGlobalKnownHostsFile2:
448                 charptr = &options->system_hostfile2;
449                 goto parse_string;
450
451         case oUserKnownHostsFile2:
452                 charptr = &options->user_hostfile2;
453                 goto parse_string;
454
455         case oHostName:
456                 charptr = &options->hostname;
457                 goto parse_string;
458
459         case oHostKeyAlias:
460                 charptr = &options->host_key_alias;
461                 goto parse_string;
462
463         case oPreferredAuthentications:
464                 charptr = &options->preferred_authentications;
465                 goto parse_string;
466
467         case oBindAddress:
468                 charptr = &options->bind_address;
469                 goto parse_string;
470
471         case oProxyCommand:
472                 charptr = &options->proxy_command;
473                 while ((arg = strdelim(&s)) != NULL && *arg != '\0') {
474                         string = xrealloc(string, strlen(string) + strlen(arg) + 2);
475                         strcat(string, " ");
476                         strcat(string, arg);
477                 }
478                 if (*activep && *charptr == NULL)
479                         *charptr = string;
480                 else
481                         xfree(string);
482                 return 0;
483
484         case oPort:
485                 intptr = &options->port;
486 parse_int:
487                 arg = strdelim(&s);
488                 if (!arg || *arg == '\0')
489                         fatal("%.200s line %d: Missing argument.", filename, linenum);
490                 if (arg[0] < '0' || arg[0] > '9')
491                         fatal("%.200s line %d: Bad number.", filename, linenum);
492
493                 /* Octal, decimal, or hex format? */
494                 value = strtol(arg, &endofnumber, 0);
495                 if (arg == endofnumber)
496                         fatal("%.200s line %d: Bad number.", filename, linenum);
497                 if (*activep && *intptr == -1)
498                         *intptr = value;
499                 break;
500
501         case oConnectionAttempts:
502                 intptr = &options->connection_attempts;
503                 goto parse_int;
504
505         case oCipher:
506                 intptr = &options->cipher;
507                 arg = strdelim(&s);
508                 if (!arg || *arg == '\0')
509                         fatal("%.200s line %d: Missing argument.", filename, linenum);
510                 value = cipher_number(arg);
511                 if (value == -1)
512                         fatal("%.200s line %d: Bad cipher '%s'.",
513                               filename, linenum, arg ? arg : "<NONE>");
514                 if (*activep && *intptr == -1)
515                         *intptr = value;
516                 break;
517
518         case oCiphers:
519                 arg = strdelim(&s);
520                 if (!arg || *arg == '\0')
521                         fatal("%.200s line %d: Missing argument.", filename, linenum);
522                 if (!ciphers_valid(arg))
523                         fatal("%.200s line %d: Bad SSH2 cipher spec '%s'.",
524                               filename, linenum, arg ? arg : "<NONE>");
525                 if (*activep && options->ciphers == NULL)
526                         options->ciphers = xstrdup(arg);
527                 break;
528
529         case oMacs:
530                 arg = strdelim(&s);
531                 if (!arg || *arg == '\0')
532                         fatal("%.200s line %d: Missing argument.", filename, linenum);
533                 if (!mac_valid(arg))
534                         fatal("%.200s line %d: Bad SSH2 Mac spec '%s'.",
535                               filename, linenum, arg ? arg : "<NONE>");
536                 if (*activep && options->macs == NULL)
537                         options->macs = xstrdup(arg);
538                 break;
539
540         case oHostKeyAlgorithms:
541                 arg = strdelim(&s);
542                 if (!arg || *arg == '\0')
543                         fatal("%.200s line %d: Missing argument.", filename, linenum);
544                 if (!key_names_valid2(arg))
545                         fatal("%.200s line %d: Bad protocol 2 host key algorithms '%s'.",
546                               filename, linenum, arg ? arg : "<NONE>");
547                 if (*activep && options->hostkeyalgorithms == NULL)
548                         options->hostkeyalgorithms = xstrdup(arg);
549                 break;
550
551         case oProtocol:
552                 intptr = &options->protocol;
553                 arg = strdelim(&s);
554                 if (!arg || *arg == '\0')
555                         fatal("%.200s line %d: Missing argument.", filename, linenum);
556                 value = proto_spec(arg);
557                 if (value == SSH_PROTO_UNKNOWN)
558                         fatal("%.200s line %d: Bad protocol spec '%s'.",
559                               filename, linenum, arg ? arg : "<NONE>");
560                 if (*activep && *intptr == SSH_PROTO_UNKNOWN)
561                         *intptr = value;
562                 break;
563
564         case oLogLevel:
565                 intptr = (int *) &options->log_level;
566                 arg = strdelim(&s);
567                 value = log_level_number(arg);
568                 if (value == (LogLevel) - 1)
569                         fatal("%.200s line %d: unsupported log level '%s'",
570                               filename, linenum, arg ? arg : "<NONE>");
571                 if (*activep && (LogLevel) * intptr == -1)
572                         *intptr = (LogLevel) value;
573                 break;
574
575         case oRemoteForward:
576                 arg = strdelim(&s);
577                 if (!arg || *arg == '\0')
578                         fatal("%.200s line %d: Missing argument.", filename, linenum);
579                 fwd_port = a2port(arg);
580                 if (fwd_port == 0)
581                         fatal("%.200s line %d: Badly formatted port number.",
582                               filename, linenum);
583                 arg = strdelim(&s);
584                 if (!arg || *arg == '\0')
585                         fatal("%.200s line %d: Missing second argument.",
586                               filename, linenum);
587                 if (sscanf(arg, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
588                         fatal("%.200s line %d: Badly formatted host:port.",
589                               filename, linenum);
590                 if (*activep)
591                         add_remote_forward(options, fwd_port, buf, fwd_host_port);
592                 break;
593
594         case oLocalForward:
595                 arg = strdelim(&s);
596                 if (!arg || *arg == '\0')
597                         fatal("%.200s line %d: Missing argument.", filename, linenum);
598                 fwd_port = a2port(arg);
599                 if (fwd_port == 0)
600                         fatal("%.200s line %d: Badly formatted port number.",
601                               filename, linenum);
602                 arg = strdelim(&s);
603                 if (!arg || *arg == '\0')
604                         fatal("%.200s line %d: Missing second argument.",
605                               filename, linenum);
606                 if (sscanf(arg, "%255[^:]:%hu", buf, &fwd_host_port) != 2)
607                         fatal("%.200s line %d: Badly formatted host:port.",
608                               filename, linenum);
609                 if (*activep)
610                         add_local_forward(options, fwd_port, buf, fwd_host_port);
611                 break;
612
613         case oDynamicForward:
614                 arg = strdelim(&s);
615                 if (!arg || *arg == '\0')
616                         fatal("%.200s line %d: Missing port argument.",
617                             filename, linenum);
618                 fwd_port = a2port(arg);
619                 if (fwd_port == 0)
620                         fatal("%.200s line %d: Badly formatted port number.",
621                             filename, linenum);
622                 add_local_forward(options, fwd_port, "socks4", 0);
623                 break;
624
625         case oHost:
626                 *activep = 0;
627                 while ((arg = strdelim(&s)) != NULL && *arg != '\0')
628                         if (match_pattern(host, arg)) {
629                                 debug("Applying options for %.100s", arg);
630                                 *activep = 1;
631                                 break;
632                         }
633                 /* Avoid garbage check below, as strdelim is done. */
634                 return 0;
635
636         case oEscapeChar:
637                 intptr = &options->escape_char;
638                 arg = strdelim(&s);
639                 if (!arg || *arg == '\0')
640                         fatal("%.200s line %d: Missing argument.", filename, linenum);
641                 if (arg[0] == '^' && arg[2] == 0 &&
642                     (u_char) arg[1] >= 64 && (u_char) arg[1] < 128)
643                         value = (u_char) arg[1] & 31;
644                 else if (strlen(arg) == 1)
645                         value = (u_char) arg[0];
646                 else if (strcmp(arg, "none") == 0)
647                         value = SSH_ESCAPECHAR_NONE;
648                 else {
649                         fatal("%.200s line %d: Bad escape character.",
650                               filename, linenum);
651                         /* NOTREACHED */
652                         value = 0;      /* Avoid compiler warning. */
653                 }
654                 if (*activep && *intptr == -1)
655                         *intptr = value;
656                 break;
657
658         default:
659                 fatal("process_config_line: Unimplemented opcode %d", opcode);
660         }
661
662         /* Check that there is no garbage at end of line. */
663         if ((arg = strdelim(&s)) != NULL && *arg != '\0') {
664                 fatal("%.200s line %d: garbage at end of line; \"%.200s\".",
665                       filename, linenum, arg);
666         }
667         return 0;
668 }
669
670
671 /*
672  * Reads the config file and modifies the options accordingly.  Options
673  * should already be initialized before this call.  This never returns if
674  * there is an error.  If the file does not exist, this returns immediately.
675  */
676
677 void
678 read_config_file(const char *filename, const char *host, Options *options)
679 {
680         FILE *f;
681         char line[1024];
682         int active, linenum;
683         int bad_options = 0;
684
685         /* Open the file. */
686         f = fopen(filename, "r");
687         if (!f)
688                 return;
689
690         debug("Reading configuration data %.200s", filename);
691
692         /*
693          * Mark that we are now processing the options.  This flag is turned
694          * on/off by Host specifications.
695          */
696         active = 1;
697         linenum = 0;
698         while (fgets(line, sizeof(line), f)) {
699                 /* Update line number counter. */
700                 linenum++;
701                 if (process_config_line(options, host, line, filename, linenum, &active) != 0)
702                         bad_options++;
703         }
704         fclose(f);
705         if (bad_options > 0)
706                 fatal("%s: terminating, %d bad configuration options",
707                       filename, bad_options);
708 }
709
710 /*
711  * Initializes options to special values that indicate that they have not yet
712  * been set.  Read_config_file will only set options with this value. Options
713  * are processed in the following order: command line, user config file,
714  * system config file.  Last, fill_default_options is called.
715  */
716
717 void
718 initialize_options(Options * options)
719 {
720         memset(options, 'X', sizeof(*options));
721         options->forward_agent = -1;
722         options->forward_x11 = -1;
723         options->xauth_location = NULL;
724         options->gateway_ports = -1;
725         options->use_privileged_port = -1;
726         options->rhosts_authentication = -1;
727         options->rsa_authentication = -1;
728         options->pubkey_authentication = -1;
729         options->challenge_response_authentication = -1;
730 #if defined(KRB4) || defined(KRB5)
731         options->kerberos_authentication = -1;
732 #endif
733 #if defined(AFS) || defined(KRB5)
734         options->kerberos_tgt_passing = -1;
735 #endif
736 #ifdef AFS
737         options->afs_token_passing = -1;
738 #endif
739         options->password_authentication = -1;
740         options->kbd_interactive_authentication = -1;
741         options->kbd_interactive_devices = NULL;
742         options->rhosts_rsa_authentication = -1;
743         options->hostbased_authentication = -1;
744         options->fallback_to_rsh = -1;
745         options->use_rsh = -1;
746         options->batch_mode = -1;
747         options->check_host_ip = -1;
748         options->strict_host_key_checking = -1;
749         options->compression = -1;
750         options->keepalives = -1;
751         options->compression_level = -1;
752         options->port = -1;
753         options->connection_attempts = -1;
754         options->number_of_password_prompts = -1;
755         options->cipher = -1;
756         options->ciphers = NULL;
757         options->macs = NULL;
758         options->hostkeyalgorithms = NULL;
759         options->protocol = SSH_PROTO_UNKNOWN;
760         options->num_identity_files = 0;
761         options->hostname = NULL;
762         options->host_key_alias = NULL;
763         options->proxy_command = NULL;
764         options->user = NULL;
765         options->escape_char = -1;
766         options->system_hostfile = NULL;
767         options->user_hostfile = NULL;
768         options->system_hostfile2 = NULL;
769         options->user_hostfile2 = NULL;
770         options->num_local_forwards = 0;
771         options->num_remote_forwards = 0;
772         options->log_level = (LogLevel) - 1;
773         options->preferred_authentications = NULL;
774         options->bind_address = NULL;
775 }
776
777 /*
778  * Called after processing other sources of option data, this fills those
779  * options for which no value has been specified with their default values.
780  */
781
782 void
783 fill_default_options(Options * options)
784 {
785         int len;
786
787         if (options->forward_agent == -1)
788                 options->forward_agent = 0;
789         if (options->forward_x11 == -1)
790                 options->forward_x11 = 0;
791 #ifdef _PATH_XAUTH
792         if (options->xauth_location == NULL)
793                 options->xauth_location = _PATH_XAUTH;
794 #endif
795         if (options->gateway_ports == -1)
796                 options->gateway_ports = 0;
797         if (options->use_privileged_port == -1)
798                 options->use_privileged_port = 0;
799         if (options->rhosts_authentication == -1)
800                 options->rhosts_authentication = 1;
801         if (options->rsa_authentication == -1)
802                 options->rsa_authentication = 1;
803         if (options->pubkey_authentication == -1)
804                 options->pubkey_authentication = 1;
805         if (options->challenge_response_authentication == -1)
806                 options->challenge_response_authentication = 1;
807 #if defined(KRB4) || defined(KRB5)
808         if (options->kerberos_authentication == -1)
809                 options->kerberos_authentication = 1;
810 #endif
811 #if defined(AFS) || defined(KRB5)
812         if (options->kerberos_tgt_passing == -1)
813                 options->kerberos_tgt_passing = 1;
814 #endif
815 #ifdef AFS
816         if (options->afs_token_passing == -1)
817                 options->afs_token_passing = 1;
818 #endif
819         if (options->password_authentication == -1)
820                 options->password_authentication = 1;
821         if (options->kbd_interactive_authentication == -1)
822                 options->kbd_interactive_authentication = 1;
823         if (options->rhosts_rsa_authentication == -1)
824                 options->rhosts_rsa_authentication = 1;
825         if (options->hostbased_authentication == -1)
826                 options->hostbased_authentication = 0;
827         if (options->fallback_to_rsh == -1)
828                 options->fallback_to_rsh = 0;
829         if (options->use_rsh == -1)
830                 options->use_rsh = 0;
831         if (options->batch_mode == -1)
832                 options->batch_mode = 0;
833         if (options->check_host_ip == -1)
834                 options->check_host_ip = 1;
835         if (options->strict_host_key_checking == -1)
836                 options->strict_host_key_checking = 2;  /* 2 is default */
837         if (options->compression == -1)
838                 options->compression = 0;
839         if (options->keepalives == -1)
840                 options->keepalives = 1;
841         if (options->compression_level == -1)
842                 options->compression_level = 6;
843         if (options->port == -1)
844                 options->port = 0;      /* Filled in ssh_connect. */
845         if (options->connection_attempts == -1)
846                 options->connection_attempts = 4;
847         if (options->number_of_password_prompts == -1)
848                 options->number_of_password_prompts = 3;
849         /* Selected in ssh_login(). */
850         if (options->cipher == -1)
851                 options->cipher = SSH_CIPHER_NOT_SET;
852         /* options->ciphers, default set in myproposals.h */
853         /* options->macs, default set in myproposals.h */
854         /* options->hostkeyalgorithms, default set in myproposals.h */
855         if (options->protocol == SSH_PROTO_UNKNOWN)
856                 options->protocol = SSH_PROTO_1|SSH_PROTO_2;
857         if (options->num_identity_files == 0) {
858                 if (options->protocol & SSH_PROTO_1) {
859                         len = 2 + strlen(_PATH_SSH_CLIENT_IDENTITY) + 1;
860                         options->identity_files[options->num_identity_files] =
861                             xmalloc(len);
862                         snprintf(options->identity_files[options->num_identity_files++],
863                             len, "~/%.100s", _PATH_SSH_CLIENT_IDENTITY);
864                 }
865                 if (options->protocol & SSH_PROTO_2) {
866                         len = 2 + strlen(_PATH_SSH_CLIENT_ID_RSA) + 1;
867                         options->identity_files[options->num_identity_files] =
868                             xmalloc(len);
869                         snprintf(options->identity_files[options->num_identity_files++],
870                             len, "~/%.100s", _PATH_SSH_CLIENT_ID_RSA);
871
872                         len = 2 + strlen(_PATH_SSH_CLIENT_ID_DSA) + 1;
873                         options->identity_files[options->num_identity_files] =
874                             xmalloc(len);
875                         snprintf(options->identity_files[options->num_identity_files++],
876                             len, "~/%.100s", _PATH_SSH_CLIENT_ID_DSA);
877                 }
878         }
879         if (options->escape_char == -1)
880                 options->escape_char = '~';
881         if (options->system_hostfile == NULL)
882                 options->system_hostfile = _PATH_SSH_SYSTEM_HOSTFILE;
883         if (options->user_hostfile == NULL)
884                 options->user_hostfile = _PATH_SSH_USER_HOSTFILE;
885         if (options->system_hostfile2 == NULL)
886                 options->system_hostfile2 = _PATH_SSH_SYSTEM_HOSTFILE2;
887         if (options->user_hostfile2 == NULL)
888                 options->user_hostfile2 = _PATH_SSH_USER_HOSTFILE2;
889         if (options->log_level == (LogLevel) - 1)
890                 options->log_level = SYSLOG_LEVEL_INFO;
891         /* options->proxy_command should not be set by default */
892         /* options->user will be set in the main program if appropriate */
893         /* options->hostname will be set in the main program if appropriate */
894         /* options->host_key_alias should not be set by default */
895         /* options->preferred_authentications will be set in ssh */
896 }
This page took 0.138609 seconds and 5 git commands to generate.