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