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