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