1 /* 2 * 3 * servconf.c 4 * 5 * Author: Tatu Ylonen <ylo@cs.hut.fi> 6 * 7 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 8 * All rights reserved 9 * 10 * Created: Mon Aug 21 15:48:58 1995 ylo 11 * 12 * $FreeBSD$ 13 */ 14 15 #include "includes.h" 16 RCSID("$Id: servconf.c,v 1.41 2000/05/22 18:42:01 markus Exp $"); 17 18 #include "ssh.h" 19 #include "servconf.h" 20 #include "xmalloc.h" 21 #include "compat.h" 22 23 /* add listen address */ 24 void add_listen_addr(ServerOptions *options, char *addr); 25 26 /* Initializes the server options to their default values. */ 27 28 void 29 initialize_server_options(ServerOptions *options) 30 { 31 memset(options, 0, sizeof(*options)); 32 options->num_ports = 0; 33 options->ports_from_cmdline = 0; 34 options->listen_addrs = NULL; 35 options->host_key_file = NULL; 36 options->host_dsa_key_file = NULL; 37 options->pid_file = NULL; 38 options->server_key_bits = -1; 39 options->login_grace_time = -1; 40 options->key_regeneration_time = -1; 41 options->permit_root_login = -1; 42 options->ignore_rhosts = -1; 43 options->ignore_user_known_hosts = -1; 44 options->print_motd = -1; 45 options->check_mail = -1; 46 options->x11_forwarding = -1; 47 options->x11_display_offset = -1; 48 options->strict_modes = -1; 49 options->keepalives = -1; 50 options->log_facility = (SyslogFacility) - 1; 51 options->log_level = (LogLevel) - 1; 52 options->rhosts_authentication = -1; 53 options->rhosts_rsa_authentication = -1; 54 options->rsa_authentication = -1; 55 options->dsa_authentication = -1; 56 #ifdef KRB4 57 options->krb4_authentication = -1; 58 options->krb4_or_local_passwd = -1; 59 options->krb4_ticket_cleanup = -1; 60 #endif 61 #ifdef KRB5 62 options->krb5_authentication = -1; 63 options->krb5_tgt_passing = -1; 64 #endif /* KRB5 */ 65 #ifdef AFS 66 options->krb4_tgt_passing = -1; 67 options->afs_token_passing = -1; 68 #endif 69 options->password_authentication = -1; 70 #ifdef SKEY 71 options->skey_authentication = -1; 72 #endif 73 options->permit_empty_passwd = -1; 74 options->use_login = -1; 75 options->num_allow_users = 0; 76 options->num_deny_users = 0; 77 options->num_allow_groups = 0; 78 options->num_deny_groups = 0; 79 options->ciphers = NULL; 80 options->protocol = SSH_PROTO_UNKNOWN; 81 options->gateway_ports = -1; 82 options->connections_per_period = 0; 83 options->connections_period = 0; 84 } 85 86 void 87 fill_default_server_options(ServerOptions *options) 88 { 89 if (options->num_ports == 0) 90 options->ports[options->num_ports++] = SSH_DEFAULT_PORT; 91 if (options->listen_addrs == NULL) 92 add_listen_addr(options, NULL); 93 if (options->host_key_file == NULL) 94 options->host_key_file = HOST_KEY_FILE; 95 if (options->host_dsa_key_file == NULL) 96 options->host_dsa_key_file = HOST_DSA_KEY_FILE; 97 if (options->pid_file == NULL) 98 options->pid_file = SSH_DAEMON_PID_FILE; 99 if (options->server_key_bits == -1) 100 options->server_key_bits = 768; 101 if (options->login_grace_time == -1) 102 options->login_grace_time = 60; 103 if (options->key_regeneration_time == -1) 104 options->key_regeneration_time = 3600; 105 if (options->permit_root_login == -1) 106 options->permit_root_login = 0; /* no */ 107 if (options->ignore_rhosts == -1) 108 options->ignore_rhosts = 1; 109 if (options->ignore_user_known_hosts == -1) 110 options->ignore_user_known_hosts = 0; 111 if (options->check_mail == -1) 112 options->check_mail = 1; 113 if (options->print_motd == -1) 114 options->print_motd = 1; 115 if (options->x11_forwarding == -1) 116 options->x11_forwarding = 0; 117 if (options->x11_display_offset == -1) 118 options->x11_display_offset = 10; 119 if (options->strict_modes == -1) 120 options->strict_modes = 1; 121 if (options->keepalives == -1) 122 options->keepalives = 1; 123 if (options->log_facility == (SyslogFacility) (-1)) 124 options->log_facility = SYSLOG_FACILITY_AUTH; 125 if (options->log_level == (LogLevel) (-1)) 126 options->log_level = SYSLOG_LEVEL_INFO; 127 if (options->rhosts_authentication == -1) 128 options->rhosts_authentication = 0; 129 if (options->rhosts_rsa_authentication == -1) 130 options->rhosts_rsa_authentication = 0; 131 if (options->rsa_authentication == -1) 132 options->rsa_authentication = 1; 133 if (options->dsa_authentication == -1) 134 options->dsa_authentication = 1; 135 #ifdef KRB4 136 if (options->krb4_authentication == -1) 137 options->krb4_authentication = (access(KEYFILE, R_OK) == 0); 138 if (options->krb4_or_local_passwd == -1) 139 options->krb4_or_local_passwd = 1; 140 if (options->krb4_ticket_cleanup == -1) 141 options->krb4_ticket_cleanup = 1; 142 #endif /* KRB4 */ 143 #ifdef KRB5 144 if (options->krb5_authentication == -1) 145 options->krb5_authentication = 1; 146 if (options->krb5_tgt_passing == -1) 147 options->krb5_tgt_passing = 1; 148 #endif /* KRB5 */ 149 #ifdef AFS 150 if (options->krb4_tgt_passing == -1) 151 options->krb4_tgt_passing = 0; 152 if (options->afs_token_passing == -1) 153 options->afs_token_passing = k_hasafs(); 154 #endif /* AFS */ 155 if (options->password_authentication == -1) 156 options->password_authentication = 1; 157 #ifdef SKEY 158 if (options->skey_authentication == -1) 159 options->skey_authentication = 1; 160 #endif 161 if (options->permit_empty_passwd == -1) 162 options->permit_empty_passwd = 0; 163 if (options->use_login == -1) 164 options->use_login = 0; 165 if (options->protocol == SSH_PROTO_UNKNOWN) 166 options->protocol = SSH_PROTO_1|SSH_PROTO_2; 167 if (options->gateway_ports == -1) 168 options->gateway_ports = 0; 169 } 170 171 #define WHITESPACE " \t\r\n" 172 173 /* Keyword tokens. */ 174 typedef enum { 175 sBadOption, /* == unknown option */ 176 sPort, sHostKeyFile, sServerKeyBits, sLoginGraceTime, sKeyRegenerationTime, 177 sPermitRootLogin, sLogFacility, sLogLevel, 178 sRhostsAuthentication, sRhostsRSAAuthentication, sRSAAuthentication, 179 #ifdef KRB4 180 sKrb4Authentication, sKrb4OrLocalPasswd, sKrb4TicketCleanup, 181 #endif 182 #ifdef KRB5 183 sKrb5Authentication, sKrb5TgtPassing, 184 #endif /* KRB5 */ 185 #ifdef AFS 186 sKrb4TgtPassing, sAFSTokenPassing, 187 #endif 188 #ifdef SKEY 189 sSkeyAuthentication, 190 #endif 191 sPasswordAuthentication, sListenAddress, 192 sPrintMotd, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset, 193 sStrictModes, sEmptyPasswd, sRandomSeedFile, sKeepAlives, sCheckMail, 194 sUseLogin, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, 195 sIgnoreUserKnownHosts, sHostDSAKeyFile, sCiphers, sProtocol, sPidFile, 196 sGatewayPorts, sDSAAuthentication, sConnectionsPerPeriod 197 } ServerOpCodes; 198 199 /* Textual representation of the tokens. */ 200 static struct { 201 const char *name; 202 ServerOpCodes opcode; 203 } keywords[] = { 204 { "port", sPort }, 205 { "hostkey", sHostKeyFile }, 206 { "hostdsakey", sHostDSAKeyFile }, 207 { "pidfile", sPidFile }, 208 { "serverkeybits", sServerKeyBits }, 209 { "logingracetime", sLoginGraceTime }, 210 { "keyregenerationinterval", sKeyRegenerationTime }, 211 { "permitrootlogin", sPermitRootLogin }, 212 { "syslogfacility", sLogFacility }, 213 { "loglevel", sLogLevel }, 214 { "rhostsauthentication", sRhostsAuthentication }, 215 { "rhostsrsaauthentication", sRhostsRSAAuthentication }, 216 { "rsaauthentication", sRSAAuthentication }, 217 { "dsaauthentication", sDSAAuthentication }, 218 #ifdef KRB4 219 { "kerberos4authentication", sKrb4Authentication }, 220 { "kerberos4orlocalpasswd", sKrb4OrLocalPasswd }, 221 { "kerberos4ticketcleanup", sKrb4TicketCleanup }, 222 #endif 223 #ifdef KRB5 224 { "kerberos5authentication", sKrb5Authentication }, 225 { "kerberos5tgtpassing", sKrb5TgtPassing }, 226 #endif /* KRB5 */ 227 #ifdef AFS 228 { "kerberos4tgtpassing", sKrb4TgtPassing }, 229 { "afstokenpassing", sAFSTokenPassing }, 230 #endif 231 { "passwordauthentication", sPasswordAuthentication }, 232 #ifdef SKEY 233 { "skeyauthentication", sSkeyAuthentication }, 234 #endif 235 { "checkmail", sCheckMail }, 236 { "listenaddress", sListenAddress }, 237 { "printmotd", sPrintMotd }, 238 { "ignorerhosts", sIgnoreRhosts }, 239 { "ignoreuserknownhosts", sIgnoreUserKnownHosts }, 240 { "x11forwarding", sX11Forwarding }, 241 { "x11displayoffset", sX11DisplayOffset }, 242 { "strictmodes", sStrictModes }, 243 { "permitemptypasswords", sEmptyPasswd }, 244 { "uselogin", sUseLogin }, 245 { "randomseed", sRandomSeedFile }, 246 { "keepalive", sKeepAlives }, 247 { "allowusers", sAllowUsers }, 248 { "denyusers", sDenyUsers }, 249 { "allowgroups", sAllowGroups }, 250 { "denygroups", sDenyGroups }, 251 { "ciphers", sCiphers }, 252 { "protocol", sProtocol }, 253 { "gatewayports", sGatewayPorts }, 254 { "connectionsperperiod", sConnectionsPerPeriod }, 255 { NULL, 0 } 256 }; 257 258 /* 259 * Returns the number of the token pointed to by cp of length len. Never 260 * returns if the token is not known. 261 */ 262 263 static ServerOpCodes 264 parse_token(const char *cp, const char *filename, 265 int linenum) 266 { 267 unsigned int i; 268 269 for (i = 0; keywords[i].name; i++) 270 if (strcasecmp(cp, keywords[i].name) == 0) 271 return keywords[i].opcode; 272 273 fprintf(stderr, "%s: line %d: Bad configuration option: %s\n", 274 filename, linenum, cp); 275 return sBadOption; 276 } 277 278 /* 279 * add listen address 280 */ 281 void 282 add_listen_addr(ServerOptions *options, char *addr) 283 { 284 extern int IPv4or6; 285 struct addrinfo hints, *ai, *aitop; 286 char strport[NI_MAXSERV]; 287 int gaierr; 288 int i; 289 290 if (options->num_ports == 0) 291 options->ports[options->num_ports++] = SSH_DEFAULT_PORT; 292 for (i = 0; i < options->num_ports; i++) { 293 memset(&hints, 0, sizeof(hints)); 294 hints.ai_family = IPv4or6; 295 hints.ai_socktype = SOCK_STREAM; 296 hints.ai_flags = (addr == NULL) ? AI_PASSIVE : 0; 297 snprintf(strport, sizeof strport, "%d", options->ports[i]); 298 if ((gaierr = getaddrinfo(addr, strport, &hints, &aitop)) != 0) 299 fatal("bad addr or host: %s (%s)\n", 300 addr ? addr : "<NULL>", 301 gai_strerror(gaierr)); 302 for (ai = aitop; ai->ai_next; ai = ai->ai_next) 303 ; 304 ai->ai_next = options->listen_addrs; 305 options->listen_addrs = aitop; 306 } 307 } 308 309 /* Reads the server configuration file. */ 310 311 void 312 read_server_config(ServerOptions *options, const char *filename) 313 { 314 FILE *f; 315 char line[1024]; 316 char *cp, **charptr; 317 int linenum, *intptr, value; 318 int bad_options = 0; 319 ServerOpCodes opcode; 320 321 f = fopen(filename, "r"); 322 if (!f) { 323 perror(filename); 324 exit(1); 325 } 326 linenum = 0; 327 while (fgets(line, sizeof(line), f)) { 328 linenum++; 329 cp = line + strspn(line, WHITESPACE); 330 if (!*cp || *cp == '#') 331 continue; 332 cp = strtok(cp, WHITESPACE); 333 opcode = parse_token(cp, filename, linenum); 334 switch (opcode) { 335 case sBadOption: 336 bad_options++; 337 continue; 338 case sPort: 339 /* ignore ports from configfile if cmdline specifies ports */ 340 if (options->ports_from_cmdline) 341 continue; 342 if (options->listen_addrs != NULL) 343 fatal("%s line %d: ports must be specified before " 344 "ListenAdress.\n", filename, linenum); 345 if (options->num_ports >= MAX_PORTS) 346 fatal("%s line %d: too many ports.\n", 347 filename, linenum); 348 cp = strtok(NULL, WHITESPACE); 349 if (!cp) 350 fatal("%s line %d: missing port number.\n", 351 filename, linenum); 352 options->ports[options->num_ports++] = atoi(cp); 353 break; 354 355 case sServerKeyBits: 356 intptr = &options->server_key_bits; 357 parse_int: 358 cp = strtok(NULL, WHITESPACE); 359 if (!cp) { 360 fprintf(stderr, "%s line %d: missing integer value.\n", 361 filename, linenum); 362 exit(1); 363 } 364 if (sscanf(cp, " %d ", &value) != 1) { 365 fprintf(stderr, "%s line %d: invalid integer value.\n", 366 filename, linenum); 367 exit(1); 368 } 369 if (*intptr == -1) 370 *intptr = value; 371 break; 372 373 case sLoginGraceTime: 374 intptr = &options->login_grace_time; 375 goto parse_int; 376 377 case sKeyRegenerationTime: 378 intptr = &options->key_regeneration_time; 379 goto parse_int; 380 381 case sListenAddress: 382 cp = strtok(NULL, WHITESPACE); 383 if (!cp) 384 fatal("%s line %d: missing inet addr.\n", 385 filename, linenum); 386 add_listen_addr(options, cp); 387 break; 388 389 case sHostKeyFile: 390 case sHostDSAKeyFile: 391 charptr = (opcode == sHostKeyFile ) ? 392 &options->host_key_file : &options->host_dsa_key_file; 393 cp = strtok(NULL, WHITESPACE); 394 if (!cp) { 395 fprintf(stderr, "%s line %d: missing file name.\n", 396 filename, linenum); 397 exit(1); 398 } 399 if (*charptr == NULL) 400 *charptr = tilde_expand_filename(cp, getuid()); 401 break; 402 403 case sPidFile: 404 charptr = &options->pid_file; 405 cp = strtok(NULL, WHITESPACE); 406 if (!cp) { 407 fprintf(stderr, "%s line %d: missing file name.\n", 408 filename, linenum); 409 exit(1); 410 } 411 if (*charptr == NULL) 412 *charptr = tilde_expand_filename(cp, getuid()); 413 break; 414 415 case sRandomSeedFile: 416 fprintf(stderr, "%s line %d: \"randomseed\" option is obsolete.\n", 417 filename, linenum); 418 cp = strtok(NULL, WHITESPACE); 419 break; 420 421 case sPermitRootLogin: 422 intptr = &options->permit_root_login; 423 cp = strtok(NULL, WHITESPACE); 424 if (!cp) { 425 fprintf(stderr, "%s line %d: missing yes/without-password/no argument.\n", 426 filename, linenum); 427 exit(1); 428 } 429 if (strcmp(cp, "without-password") == 0) 430 value = 2; 431 else if (strcmp(cp, "yes") == 0) 432 value = 1; 433 else if (strcmp(cp, "no") == 0) 434 value = 0; 435 else { 436 fprintf(stderr, "%s line %d: Bad yes/without-password/no argument: %s\n", 437 filename, linenum, cp); 438 exit(1); 439 } 440 if (*intptr == -1) 441 *intptr = value; 442 break; 443 444 case sIgnoreRhosts: 445 intptr = &options->ignore_rhosts; 446 parse_flag: 447 cp = strtok(NULL, WHITESPACE); 448 if (!cp) { 449 fprintf(stderr, "%s line %d: missing yes/no argument.\n", 450 filename, linenum); 451 exit(1); 452 } 453 if (strcmp(cp, "yes") == 0) 454 value = 1; 455 else if (strcmp(cp, "no") == 0) 456 value = 0; 457 else { 458 fprintf(stderr, "%s line %d: Bad yes/no argument: %s\n", 459 filename, linenum, cp); 460 exit(1); 461 } 462 if (*intptr == -1) 463 *intptr = value; 464 break; 465 466 case sIgnoreUserKnownHosts: 467 intptr = &options->ignore_user_known_hosts; 468 goto parse_flag; 469 470 case sRhostsAuthentication: 471 intptr = &options->rhosts_authentication; 472 goto parse_flag; 473 474 case sRhostsRSAAuthentication: 475 intptr = &options->rhosts_rsa_authentication; 476 goto parse_flag; 477 478 case sRSAAuthentication: 479 intptr = &options->rsa_authentication; 480 goto parse_flag; 481 482 case sDSAAuthentication: 483 intptr = &options->dsa_authentication; 484 goto parse_flag; 485 486 #ifdef KRB4 487 case sKrb4Authentication: 488 intptr = &options->krb4_authentication; 489 goto parse_flag; 490 491 case sKrb4OrLocalPasswd: 492 intptr = &options->krb4_or_local_passwd; 493 goto parse_flag; 494 495 case sKrb4TicketCleanup: 496 intptr = &options->krb4_ticket_cleanup; 497 goto parse_flag; 498 #endif 499 500 #ifdef KRB5 501 case sKrb5Authentication: 502 intptr = &options->krb5_authentication; 503 goto parse_flag; 504 505 case sKrb5TgtPassing: 506 intptr = &options->krb5_tgt_passing; 507 goto parse_flag; 508 #endif /* KRB5 */ 509 510 #ifdef AFS 511 case sKrb4TgtPassing: 512 intptr = &options->krb4_tgt_passing; 513 goto parse_flag; 514 515 case sAFSTokenPassing: 516 intptr = &options->afs_token_passing; 517 goto parse_flag; 518 #endif 519 520 case sPasswordAuthentication: 521 intptr = &options->password_authentication; 522 goto parse_flag; 523 524 case sCheckMail: 525 intptr = &options->check_mail; 526 goto parse_flag; 527 528 #ifdef SKEY 529 case sSkeyAuthentication: 530 intptr = &options->skey_authentication; 531 goto parse_flag; 532 #endif 533 534 case sPrintMotd: 535 intptr = &options->print_motd; 536 goto parse_flag; 537 538 case sX11Forwarding: 539 intptr = &options->x11_forwarding; 540 goto parse_flag; 541 542 case sX11DisplayOffset: 543 intptr = &options->x11_display_offset; 544 goto parse_int; 545 546 case sStrictModes: 547 intptr = &options->strict_modes; 548 goto parse_flag; 549 550 case sKeepAlives: 551 intptr = &options->keepalives; 552 goto parse_flag; 553 554 case sEmptyPasswd: 555 intptr = &options->permit_empty_passwd; 556 goto parse_flag; 557 558 case sUseLogin: 559 intptr = &options->use_login; 560 goto parse_flag; 561 562 case sGatewayPorts: 563 intptr = &options->gateway_ports; 564 goto parse_flag; 565 566 case sLogFacility: 567 intptr = (int *) &options->log_facility; 568 cp = strtok(NULL, WHITESPACE); 569 value = log_facility_number(cp); 570 if (value == (SyslogFacility) - 1) 571 fatal("%.200s line %d: unsupported log facility '%s'\n", 572 filename, linenum, cp ? cp : "<NONE>"); 573 if (*intptr == -1) 574 *intptr = (SyslogFacility) value; 575 break; 576 577 case sLogLevel: 578 intptr = (int *) &options->log_level; 579 cp = strtok(NULL, WHITESPACE); 580 value = log_level_number(cp); 581 if (value == (LogLevel) - 1) 582 fatal("%.200s line %d: unsupported log level '%s'\n", 583 filename, linenum, cp ? cp : "<NONE>"); 584 if (*intptr == -1) 585 *intptr = (LogLevel) value; 586 break; 587 588 case sAllowUsers: 589 while ((cp = strtok(NULL, WHITESPACE))) { 590 if (options->num_allow_users >= MAX_ALLOW_USERS) 591 fatal("%.200s line %d: too many allow users.\n", 592 filename, linenum); 593 options->allow_users[options->num_allow_users++] = xstrdup(cp); 594 } 595 break; 596 597 case sDenyUsers: 598 while ((cp = strtok(NULL, WHITESPACE))) { 599 if (options->num_deny_users >= MAX_DENY_USERS) 600 fatal("%.200s line %d: too many deny users.\n", 601 filename, linenum); 602 options->deny_users[options->num_deny_users++] = xstrdup(cp); 603 } 604 break; 605 606 case sAllowGroups: 607 while ((cp = strtok(NULL, WHITESPACE))) { 608 if (options->num_allow_groups >= MAX_ALLOW_GROUPS) 609 fatal("%.200s line %d: too many allow groups.\n", 610 filename, linenum); 611 options->allow_groups[options->num_allow_groups++] = xstrdup(cp); 612 } 613 break; 614 615 case sDenyGroups: 616 while ((cp = strtok(NULL, WHITESPACE))) { 617 if (options->num_deny_groups >= MAX_DENY_GROUPS) 618 fatal("%.200s line %d: too many deny groups.\n", 619 filename, linenum); 620 options->deny_groups[options->num_deny_groups++] = xstrdup(cp); 621 } 622 break; 623 624 case sCiphers: 625 cp = strtok(NULL, WHITESPACE); 626 if (!cp) 627 fatal("%s line %d: Missing argument.", filename, linenum); 628 if (!ciphers_valid(cp)) 629 fatal("%s line %d: Bad SSH2 cipher spec '%s'.", 630 filename, linenum, cp ? cp : "<NONE>"); 631 if (options->ciphers == NULL) 632 options->ciphers = xstrdup(cp); 633 break; 634 635 case sProtocol: 636 intptr = &options->protocol; 637 cp = strtok(NULL, WHITESPACE); 638 if (!cp) 639 fatal("%s line %d: Missing argument.", filename, linenum); 640 value = proto_spec(cp); 641 if (value == SSH_PROTO_UNKNOWN) 642 fatal("%s line %d: Bad protocol spec '%s'.", 643 filename, linenum, cp ? cp : "<NONE>"); 644 if (*intptr == SSH_PROTO_UNKNOWN) 645 *intptr = value; 646 break; 647 648 case sConnectionsPerPeriod: 649 cp = strtok(NULL, WHITESPACE); 650 if (cp == NULL) 651 fatal("%.200s line %d: missing (>= 0) number argument.\n", 652 filename, linenum); 653 if (sscanf(cp, " %u/%u ", &options->connections_per_period, 654 &options->connections_period) != 2) 655 fatal("%.200s line %d: invalid numerical argument(s).\n", 656 filename, linenum); 657 if (options->connections_per_period != 0 && 658 options->connections_period == 0) 659 fatal("%.200s line %d: invalid connections period.\n", 660 filename, linenum); 661 break; 662 663 default: 664 fatal("%.200s line %d: Missing handler for opcode %s (%d)\n", 665 filename, linenum, cp, opcode); 666 } 667 if (strtok(NULL, WHITESPACE) != NULL) { 668 fatal("%.200s line %d: garbage at end of line.\n", 669 filename, linenum); 670 } 671 } 672 fclose(f); 673 if (bad_options > 0) { 674 fatal("%.200s: terminating, %d bad configuration options\n", 675 filename, bad_options); 676 } 677 } 678