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