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