summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--servconf.c888
-rw-r--r--servconf.h4
-rw-r--r--sshd.87
-rw-r--r--sshd.c55
5 files changed, 497 insertions, 463 deletions
diff --git a/ChangeLog b/ChangeLog
index f4f1f790e..61efb3700 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -68,6 +68,10 @@
68 - markus@cvs.openbsd.org 2001/12/05 16:54:51 68 - markus@cvs.openbsd.org 2001/12/05 16:54:51
69 [compat.c match.c match.h] 69 [compat.c match.c match.h]
70 make theo and djm happy: bye bye regexp 70 make theo and djm happy: bye bye regexp
71 - markus@cvs.openbsd.org 2001/12/06 13:30:06
72 [servconf.c servconf.h sshd.8 sshd.c]
73 add -o to sshd, too. ok deraadt@
74 - (bal) Minor white space fix up in servconf.c
71 75
7220011126 7620011126
73 - (tim) [contrib/cygwin/README, openbsd-compat/bsd-cygwin_util.c, 77 - (tim) [contrib/cygwin/README, openbsd-compat/bsd-cygwin_util.c,
@@ -6990,4 +6994,4 @@
6990 - Wrote replacements for strlcpy and mkdtemp 6994 - Wrote replacements for strlcpy and mkdtemp
6991 - Released 1.0pre1 6995 - Released 1.0pre1
6992 6996
6993$Id: ChangeLog,v 1.1686 2001/12/06 18:06:05 mouring Exp $ 6997$Id: ChangeLog,v 1.1687 2001/12/06 18:22:17 mouring Exp $
diff --git a/servconf.c b/servconf.c
index bd5588609..0f0a7396b 100644
--- a/servconf.c
+++ b/servconf.c
@@ -10,7 +10,7 @@
10 */ 10 */
11 11
12#include "includes.h" 12#include "includes.h"
13RCSID("$OpenBSD: servconf.c,v 1.93 2001/12/05 10:06:12 deraadt Exp $"); 13RCSID("$OpenBSD: servconf.c,v 1.94 2001/12/06 13:30:05 markus Exp $");
14 14
15#if defined(KRB4) || defined(KRB5) 15#if defined(KRB4) || defined(KRB5)
16#include <krb.h> 16#include <krb.h>
@@ -261,7 +261,7 @@ typedef enum {
261 sBanner, sReverseMappingCheck, sHostbasedAuthentication, 261 sBanner, sReverseMappingCheck, sHostbasedAuthentication,
262 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, 262 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
263 sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2, 263 sClientAliveCountMax, sAuthorizedKeysFile, sAuthorizedKeysFile2,
264 sDeprecated 264 sDeprecated
265} ServerOpCodes; 265} ServerOpCodes;
266 266
267/* Textual representation of the tokens. */ 267/* Textual representation of the tokens. */
@@ -392,487 +392,497 @@ add_one_listen_addr(ServerOptions *options, char *addr, u_short port)
392 options->listen_addrs = aitop; 392 options->listen_addrs = aitop;
393} 393}
394 394
395/* Reads the server configuration file. */ 395int
396 396process_server_config_line(ServerOptions *options, char *line,
397void 397 const char *filename, int linenum)
398read_server_config(ServerOptions *options, const char *filename)
399{ 398{
400 FILE *f;
401 char line[1024];
402 char *cp, **charptr, *arg, *p; 399 char *cp, **charptr, *arg, *p;
403 int linenum, *intptr, value; 400 int *intptr, value;
404 int bad_options = 0;
405 ServerOpCodes opcode; 401 ServerOpCodes opcode;
406 int i, n; 402 int i, n;
407 403
408 f = fopen(filename, "r"); 404 cp = line;
409 if (!f) { 405 arg = strdelim(&cp);
410 perror(filename); 406 /* Ignore leading whitespace */
411 exit(1); 407 if (*arg == '\0')
412 }
413 linenum = 0;
414 while (fgets(line, sizeof(line), f)) {
415 linenum++;
416 cp = line;
417 arg = strdelim(&cp); 408 arg = strdelim(&cp);
418 /* Ignore leading whitespace */ 409 if (!arg || !*arg || *arg == '#')
419 if (*arg == '\0') 410 return 0;
420 arg = strdelim(&cp); 411 intptr = NULL;
421 if (!arg || !*arg || *arg == '#') 412 charptr = NULL;
422 continue; 413 opcode = parse_token(arg, filename, linenum);
423 intptr = NULL; 414 switch (opcode) {
424 charptr = NULL; 415 /* Portable-specific options */
425 opcode = parse_token(arg, filename, linenum); 416 case sPAMAuthenticationViaKbdInt:
426 switch (opcode) { 417 intptr = &options->pam_authentication_via_kbd_int;
427 case sBadOption: 418 goto parse_flag;
428 bad_options++;
429 continue;
430
431 /* Portable-specific options */
432 case sPAMAuthenticationViaKbdInt:
433 intptr = &options->pam_authentication_via_kbd_int;
434 goto parse_flag;
435
436 /* Standard Options */
437 case sPort:
438 /* ignore ports from configfile if cmdline specifies ports */
439 if (options->ports_from_cmdline)
440 continue;
441 if (options->listen_addrs != NULL)
442 fatal("%s line %d: ports must be specified before "
443 "ListenAdress.", filename, linenum);
444 if (options->num_ports >= MAX_PORTS)
445 fatal("%s line %d: too many ports.",
446 filename, linenum);
447 arg = strdelim(&cp);
448 if (!arg || *arg == '\0')
449 fatal("%s line %d: missing port number.",
450 filename, linenum);
451 options->ports[options->num_ports++] = a2port(arg);
452 if (options->ports[options->num_ports-1] == 0)
453 fatal("%s line %d: Badly formatted port number.",
454 filename, linenum);
455 break;
456 419
457 case sServerKeyBits: 420 /* Standard Options */
458 intptr = &options->server_key_bits; 421 case sBadOption:
422 return -1;
423 case sPort:
424 /* ignore ports from configfile if cmdline specifies ports */
425 if (options->ports_from_cmdline)
426 return 0;
427 if (options->listen_addrs != NULL)
428 fatal("%s line %d: ports must be specified before "
429 "ListenAdress.", filename, linenum);
430 if (options->num_ports >= MAX_PORTS)
431 fatal("%s line %d: too many ports.",
432 filename, linenum);
433 arg = strdelim(&cp);
434 if (!arg || *arg == '\0')
435 fatal("%s line %d: missing port number.",
436 filename, linenum);
437 options->ports[options->num_ports++] = a2port(arg);
438 if (options->ports[options->num_ports-1] == 0)
439 fatal("%s line %d: Badly formatted port number.",
440 filename, linenum);
441 break;
442
443 case sServerKeyBits:
444 intptr = &options->server_key_bits;
459parse_int: 445parse_int:
460 arg = strdelim(&cp); 446 arg = strdelim(&cp);
461 if (!arg || *arg == '\0') 447 if (!arg || *arg == '\0')
462 fatal("%s line %d: missing integer value.", 448 fatal("%s line %d: missing integer value.",
463 filename, linenum); 449 filename, linenum);
464 value = atoi(arg); 450 value = atoi(arg);
465 if (*intptr == -1) 451 if (*intptr == -1)
466 *intptr = value; 452 *intptr = value;
467 break; 453 break;
468 454
469 case sLoginGraceTime: 455 case sLoginGraceTime:
470 intptr = &options->login_grace_time; 456 intptr = &options->login_grace_time;
471parse_time: 457parse_time:
472 arg = strdelim(&cp); 458 arg = strdelim(&cp);
473 if (!arg || *arg == '\0') 459 if (!arg || *arg == '\0')
474 fatal("%s line %d: missing time value.", 460 fatal("%s line %d: missing time value.",
475 filename, linenum); 461 filename, linenum);
476 if ((value = convtime(arg)) == -1) 462 if ((value = convtime(arg)) == -1)
477 fatal("%s line %d: invalid time value.", 463 fatal("%s line %d: invalid time value.",
464 filename, linenum);
465 if (*intptr == -1)
466 *intptr = value;
467 break;
468
469 case sKeyRegenerationTime:
470 intptr = &options->key_regeneration_time;
471 goto parse_time;
472
473 case sListenAddress:
474 arg = strdelim(&cp);
475 if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0)
476 fatal("%s line %d: missing inet addr.",
477 filename, linenum);
478 if (*arg == '[') {
479 if ((p = strchr(arg, ']')) == NULL)
480 fatal("%s line %d: bad ipv6 inet addr usage.",
478 filename, linenum); 481 filename, linenum);
479 if (*intptr == -1) 482 arg++;
480 *intptr = value; 483 memmove(p, p+1, strlen(p+1)+1);
484 } else if (((p = strchr(arg, ':')) == NULL) ||
485 (strchr(p+1, ':') != NULL)) {
486 add_listen_addr(options, arg, 0);
481 break; 487 break;
488 }
489 if (*p == ':') {
490 u_short port;
482 491
483 case sKeyRegenerationTime: 492 p++;
484 intptr = &options->key_regeneration_time; 493 if (*p == '\0')
485 goto parse_time; 494 fatal("%s line %d: bad inet addr:port usage.",
486
487 case sListenAddress:
488 arg = strdelim(&cp);
489 if (!arg || *arg == '\0' || strncmp(arg, "[]", 2) == 0)
490 fatal("%s line %d: missing inet addr.",
491 filename, linenum); 495 filename, linenum);
492 if (*arg == '[') { 496 else {
493 if ((p = strchr(arg, ']')) == NULL) 497 *(p-1) = '\0';
494 fatal("%s line %d: bad ipv6 inet addr usage.", 498 if ((port = a2port(p)) == 0)
499 fatal("%s line %d: bad port number.",
495 filename, linenum); 500 filename, linenum);
496 arg++; 501 add_listen_addr(options, arg, port);
497 memmove(p, p+1, strlen(p+1)+1);
498 } else if (((p = strchr(arg, ':')) == NULL) ||
499 (strchr(p+1, ':') != NULL)) {
500 add_listen_addr(options, arg, 0);
501 break;
502 } 502 }
503 if (*p == ':') { 503 } else if (*p == '\0')
504 u_short port; 504 add_listen_addr(options, arg, 0);
505 505 else
506 p++; 506 fatal("%s line %d: bad inet addr usage.",
507 if (*p == '\0') 507 filename, linenum);
508 fatal("%s line %d: bad inet addr:port usage.", 508 break;
509 filename, linenum); 509
510 else { 510 case sHostKeyFile:
511 *(p-1) = '\0'; 511 intptr = &options->num_host_key_files;
512 if ((port = a2port(p)) == 0) 512 if (*intptr >= MAX_HOSTKEYS)
513 fatal("%s line %d: bad port number.", 513 fatal("%s line %d: too many host keys specified (max %d).",
514 filename, linenum); 514 filename, linenum, MAX_HOSTKEYS);
515 add_listen_addr(options, arg, port); 515 charptr = &options->host_key_files[*intptr];
516 }
517 } else if (*p == '\0')
518 add_listen_addr(options, arg, 0);
519 else
520 fatal("%s line %d: bad inet addr usage.",
521 filename, linenum);
522 break;
523
524 case sHostKeyFile:
525 intptr = &options->num_host_key_files;
526 if (*intptr >= MAX_HOSTKEYS)
527 fatal("%s line %d: too many host keys specified (max %d).",
528 filename, linenum, MAX_HOSTKEYS);
529 charptr = &options->host_key_files[*intptr];
530parse_filename: 516parse_filename:
531 arg = strdelim(&cp); 517 arg = strdelim(&cp);
532 if (!arg || *arg == '\0') 518 if (!arg || *arg == '\0')
533 fatal("%s line %d: missing file name.", 519 fatal("%s line %d: missing file name.",
534 filename, linenum); 520 filename, linenum);
535 if (*charptr == NULL) { 521 if (*charptr == NULL) {
536 *charptr = tilde_expand_filename(arg, getuid()); 522 *charptr = tilde_expand_filename(arg, getuid());
537 /* increase optional counter */ 523 /* increase optional counter */
538 if (intptr != NULL) 524 if (intptr != NULL)
539 *intptr = *intptr + 1; 525 *intptr = *intptr + 1;
540 } 526 }
541 break; 527 break;
542 528
543 case sPidFile: 529 case sPidFile:
544 charptr = &options->pid_file; 530 charptr = &options->pid_file;
545 goto parse_filename; 531 goto parse_filename;
546
547 case sPermitRootLogin:
548 intptr = &options->permit_root_login;
549 arg = strdelim(&cp);
550 if (!arg || *arg == '\0')
551 fatal("%s line %d: missing yes/"
552 "without-password/forced-commands-only/no "
553 "argument.", filename, linenum);
554 value = 0; /* silence compiler */
555 if (strcmp(arg, "without-password") == 0)
556 value = PERMIT_NO_PASSWD;
557 else if (strcmp(arg, "forced-commands-only") == 0)
558 value = PERMIT_FORCED_ONLY;
559 else if (strcmp(arg, "yes") == 0)
560 value = PERMIT_YES;
561 else if (strcmp(arg, "no") == 0)
562 value = PERMIT_NO;
563 else
564 fatal("%s line %d: Bad yes/"
565 "without-password/forced-commands-only/no "
566 "argument: %s", filename, linenum, arg);
567 if (*intptr == -1)
568 *intptr = value;
569 break;
570 532
571 case sIgnoreRhosts: 533 case sPermitRootLogin:
572 intptr = &options->ignore_rhosts; 534 intptr = &options->permit_root_login;
535 arg = strdelim(&cp);
536 if (!arg || *arg == '\0')
537 fatal("%s line %d: missing yes/"
538 "without-password/forced-commands-only/no "
539 "argument.", filename, linenum);
540 value = 0; /* silence compiler */
541 if (strcmp(arg, "without-password") == 0)
542 value = PERMIT_NO_PASSWD;
543 else if (strcmp(arg, "forced-commands-only") == 0)
544 value = PERMIT_FORCED_ONLY;
545 else if (strcmp(arg, "yes") == 0)
546 value = PERMIT_YES;
547 else if (strcmp(arg, "no") == 0)
548 value = PERMIT_NO;
549 else
550 fatal("%s line %d: Bad yes/"
551 "without-password/forced-commands-only/no "
552 "argument: %s", filename, linenum, arg);
553 if (*intptr == -1)
554 *intptr = value;
555 break;
556
557 case sIgnoreRhosts:
558 intptr = &options->ignore_rhosts;
573parse_flag: 559parse_flag:
574 arg = strdelim(&cp); 560 arg = strdelim(&cp);
575 if (!arg || *arg == '\0') 561 if (!arg || *arg == '\0')
576 fatal("%s line %d: missing yes/no argument.", 562 fatal("%s line %d: missing yes/no argument.",
577 filename, linenum); 563 filename, linenum);
578 value = 0; /* silence compiler */ 564 value = 0; /* silence compiler */
579 if (strcmp(arg, "yes") == 0) 565 if (strcmp(arg, "yes") == 0)
580 value = 1; 566 value = 1;
581 else if (strcmp(arg, "no") == 0) 567 else if (strcmp(arg, "no") == 0)
582 value = 0; 568 value = 0;
583 else 569 else
584 fatal("%s line %d: Bad yes/no argument: %s", 570 fatal("%s line %d: Bad yes/no argument: %s",
585 filename, linenum, arg); 571 filename, linenum, arg);
586 if (*intptr == -1) 572 if (*intptr == -1)
587 *intptr = value; 573 *intptr = value;
588 break; 574 break;
575
576 case sIgnoreUserKnownHosts:
577 intptr = &options->ignore_user_known_hosts;
578 goto parse_flag;
579
580 case sRhostsAuthentication:
581 intptr = &options->rhosts_authentication;
582 goto parse_flag;
583
584 case sRhostsRSAAuthentication:
585 intptr = &options->rhosts_rsa_authentication;
586 goto parse_flag;
587
588 case sHostbasedAuthentication:
589 intptr = &options->hostbased_authentication;
590 goto parse_flag;
591
592 case sHostbasedUsesNameFromPacketOnly:
593 intptr = &options->hostbased_uses_name_from_packet_only;
594 goto parse_flag;
595
596 case sRSAAuthentication:
597 intptr = &options->rsa_authentication;
598 goto parse_flag;
599
600 case sPubkeyAuthentication:
601 intptr = &options->pubkey_authentication;
602 goto parse_flag;
603#if defined(KRB4) || defined(KRB5)
604 case sKerberosAuthentication:
605 intptr = &options->kerberos_authentication;
606 goto parse_flag;
589 607
590 case sIgnoreUserKnownHosts: 608 case sKerberosOrLocalPasswd:
591 intptr = &options->ignore_user_known_hosts; 609 intptr = &options->kerberos_or_local_passwd;
592 goto parse_flag; 610 goto parse_flag;
593 611
594 case sRhostsAuthentication: 612 case sKerberosTicketCleanup:
595 intptr = &options->rhosts_authentication; 613 intptr = &options->kerberos_ticket_cleanup;
596 goto parse_flag; 614 goto parse_flag;
615#endif
616#if defined(AFS) || defined(KRB5)
617 case sKerberosTgtPassing:
618 intptr = &options->kerberos_tgt_passing;
619 goto parse_flag;
620#endif
621#ifdef AFS
622 case sAFSTokenPassing:
623 intptr = &options->afs_token_passing;
624 goto parse_flag;
625#endif
597 626
598 case sRhostsRSAAuthentication: 627 case sPasswordAuthentication:
599 intptr = &options->rhosts_rsa_authentication; 628 intptr = &options->password_authentication;
600 goto parse_flag; 629 goto parse_flag;
601 630
602 case sHostbasedAuthentication: 631 case sKbdInteractiveAuthentication:
603 intptr = &options->hostbased_authentication; 632 intptr = &options->kbd_interactive_authentication;
604 goto parse_flag; 633 goto parse_flag;
605 634
606 case sHostbasedUsesNameFromPacketOnly: 635 case sChallengeResponseAuthentication:
607 intptr = &options->hostbased_uses_name_from_packet_only; 636 intptr = &options->challenge_response_authentication;
608 goto parse_flag; 637 goto parse_flag;
609 638
610 case sRSAAuthentication: 639 case sPrintMotd:
611 intptr = &options->rsa_authentication; 640 intptr = &options->print_motd;
612 goto parse_flag; 641 goto parse_flag;
613 642
614 case sPubkeyAuthentication: 643 case sPrintLastLog:
615 intptr = &options->pubkey_authentication; 644 intptr = &options->print_lastlog;
616 goto parse_flag; 645 goto parse_flag;
617#if defined(KRB4) || defined(KRB5)
618 case sKerberosAuthentication:
619 intptr = &options->kerberos_authentication;
620 goto parse_flag;
621 646
622 case sKerberosOrLocalPasswd: 647 case sX11Forwarding:
623 intptr = &options->kerberos_or_local_passwd; 648 intptr = &options->x11_forwarding;
624 goto parse_flag; 649 goto parse_flag;
625 650
626 case sKerberosTicketCleanup: 651 case sX11DisplayOffset:
627 intptr = &options->kerberos_ticket_cleanup; 652 intptr = &options->x11_display_offset;
628 goto parse_flag; 653 goto parse_int;
629#endif
630#if defined(AFS) || defined(KRB5)
631 case sKerberosTgtPassing:
632 intptr = &options->kerberos_tgt_passing;
633 goto parse_flag;
634#endif
635#ifdef AFS
636 case sAFSTokenPassing:
637 intptr = &options->afs_token_passing;
638 goto parse_flag;
639#endif
640 654
641 case sPasswordAuthentication: 655 case sXAuthLocation:
642 intptr = &options->password_authentication; 656 charptr = &options->xauth_location;
643 goto parse_flag; 657 goto parse_filename;
644
645 case sKbdInteractiveAuthentication:
646 intptr = &options->kbd_interactive_authentication;
647 goto parse_flag;
648
649 case sChallengeResponseAuthentication:
650 intptr = &options->challenge_response_authentication;
651 goto parse_flag;
652
653 case sPrintMotd:
654 intptr = &options->print_motd;
655 goto parse_flag;
656
657 case sPrintLastLog:
658 intptr = &options->print_lastlog;
659 goto parse_flag;
660
661 case sX11Forwarding:
662 intptr = &options->x11_forwarding;
663 goto parse_flag;
664
665 case sX11DisplayOffset:
666 intptr = &options->x11_display_offset;
667 goto parse_int;
668
669 case sXAuthLocation:
670 charptr = &options->xauth_location;
671 goto parse_filename;
672
673 case sStrictModes:
674 intptr = &options->strict_modes;
675 goto parse_flag;
676
677 case sKeepAlives:
678 intptr = &options->keepalives;
679 goto parse_flag;
680
681 case sEmptyPasswd:
682 intptr = &options->permit_empty_passwd;
683 goto parse_flag;
684
685 case sUseLogin:
686 intptr = &options->use_login;
687 goto parse_flag;
688
689 case sGatewayPorts:
690 intptr = &options->gateway_ports;
691 goto parse_flag;
692
693 case sReverseMappingCheck:
694 intptr = &options->reverse_mapping_check;
695 goto parse_flag;
696
697 case sLogFacility:
698 intptr = (int *) &options->log_facility;
699 arg = strdelim(&cp);
700 value = log_facility_number(arg);
701 if (value == (SyslogFacility) - 1)
702 fatal("%.200s line %d: unsupported log facility '%s'",
703 filename, linenum, arg ? arg : "<NONE>");
704 if (*intptr == -1)
705 *intptr = (SyslogFacility) value;
706 break;
707 658
708 case sLogLevel: 659 case sStrictModes:
709 intptr = (int *) &options->log_level; 660 intptr = &options->strict_modes;
710 arg = strdelim(&cp); 661 goto parse_flag;
711 value = log_level_number(arg);
712 if (value == (LogLevel) - 1)
713 fatal("%.200s line %d: unsupported log level '%s'",
714 filename, linenum, arg ? arg : "<NONE>");
715 if (*intptr == -1)
716 *intptr = (LogLevel) value;
717 break;
718 662
719 case sAllowTcpForwarding: 663 case sKeepAlives:
720 intptr = &options->allow_tcp_forwarding; 664 intptr = &options->keepalives;
721 goto parse_flag; 665 goto parse_flag;
722 666
723 case sAllowUsers: 667 case sEmptyPasswd:
724 while ((arg = strdelim(&cp)) && *arg != '\0') { 668 intptr = &options->permit_empty_passwd;
725 if (options->num_allow_users >= MAX_ALLOW_USERS) 669 goto parse_flag;
726 fatal("%s line %d: too many allow users.",
727 filename, linenum);
728 options->allow_users[options->num_allow_users++] = xstrdup(arg);
729 }
730 break;
731 670
732 case sDenyUsers: 671 case sUseLogin:
733 while ((arg = strdelim(&cp)) && *arg != '\0') { 672 intptr = &options->use_login;
734 if (options->num_deny_users >= MAX_DENY_USERS) 673 goto parse_flag;
735 fatal( "%s line %d: too many deny users.",
736 filename, linenum);
737 options->deny_users[options->num_deny_users++] = xstrdup(arg);
738 }
739 break;
740 674
741 case sAllowGroups: 675 case sGatewayPorts:
742 while ((arg = strdelim(&cp)) && *arg != '\0') { 676 intptr = &options->gateway_ports;
743 if (options->num_allow_groups >= MAX_ALLOW_GROUPS) 677 goto parse_flag;
744 fatal("%s line %d: too many allow groups.",
745 filename, linenum);
746 options->allow_groups[options->num_allow_groups++] = xstrdup(arg);
747 }
748 break;
749 678
750 case sDenyGroups: 679 case sReverseMappingCheck:
751 while ((arg = strdelim(&cp)) && *arg != '\0') { 680 intptr = &options->reverse_mapping_check;
752 if (options->num_deny_groups >= MAX_DENY_GROUPS) 681 goto parse_flag;
753 fatal("%s line %d: too many deny groups.",
754 filename, linenum);
755 options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
756 }
757 break;
758 682
759 case sCiphers: 683 case sLogFacility:
760 arg = strdelim(&cp); 684 intptr = (int *) &options->log_facility;
761 if (!arg || *arg == '\0') 685 arg = strdelim(&cp);
762 fatal("%s line %d: Missing argument.", filename, linenum); 686 value = log_facility_number(arg);
763 if (!ciphers_valid(arg)) 687 if (value == (SyslogFacility) - 1)
764 fatal("%s line %d: Bad SSH2 cipher spec '%s'.", 688 fatal("%.200s line %d: unsupported log facility '%s'",
765 filename, linenum, arg ? arg : "<NONE>"); 689 filename, linenum, arg ? arg : "<NONE>");
766 if (options->ciphers == NULL) 690 if (*intptr == -1)
767 options->ciphers = xstrdup(arg); 691 *intptr = (SyslogFacility) value;
768 break; 692 break;
693
694 case sLogLevel:
695 intptr = (int *) &options->log_level;
696 arg = strdelim(&cp);
697 value = log_level_number(arg);
698 if (value == (LogLevel) - 1)
699 fatal("%.200s line %d: unsupported log level '%s'",
700 filename, linenum, arg ? arg : "<NONE>");
701 if (*intptr == -1)
702 *intptr = (LogLevel) value;
703 break;
704
705 case sAllowTcpForwarding:
706 intptr = &options->allow_tcp_forwarding;
707 goto parse_flag;
708
709 case sAllowUsers:
710 while ((arg = strdelim(&cp)) && *arg != '\0') {
711 if (options->num_allow_users >= MAX_ALLOW_USERS)
712 fatal("%s line %d: too many allow users.",
713 filename, linenum);
714 options->allow_users[options->num_allow_users++] = xstrdup(arg);
715 }
716 break;
769 717
770 case sMacs: 718 case sDenyUsers:
771 arg = strdelim(&cp); 719 while ((arg = strdelim(&cp)) && *arg != '\0') {
772 if (!arg || *arg == '\0') 720 if (options->num_deny_users >= MAX_DENY_USERS)
773 fatal("%s line %d: Missing argument.", filename, linenum); 721 fatal( "%s line %d: too many deny users.",
774 if (!mac_valid(arg)) 722 filename, linenum);
775 fatal("%s line %d: Bad SSH2 mac spec '%s'.", 723 options->deny_users[options->num_deny_users++] = xstrdup(arg);
776 filename, linenum, arg ? arg : "<NONE>"); 724 }
777 if (options->macs == NULL) 725 break;
778 options->macs = xstrdup(arg);
779 break;
780 726
781 case sProtocol: 727 case sAllowGroups:
782 intptr = &options->protocol; 728 while ((arg = strdelim(&cp)) && *arg != '\0') {
783 arg = strdelim(&cp); 729 if (options->num_allow_groups >= MAX_ALLOW_GROUPS)
784 if (!arg || *arg == '\0') 730 fatal("%s line %d: too many allow groups.",
785 fatal("%s line %d: Missing argument.", filename, linenum); 731 filename, linenum);
786 value = proto_spec(arg); 732 options->allow_groups[options->num_allow_groups++] = xstrdup(arg);
787 if (value == SSH_PROTO_UNKNOWN) 733 }
788 fatal("%s line %d: Bad protocol spec '%s'.", 734 break;
789 filename, linenum, arg ? arg : "<NONE>");
790 if (*intptr == SSH_PROTO_UNKNOWN)
791 *intptr = value;
792 break;
793 735
794 case sSubsystem: 736 case sDenyGroups:
795 if (options->num_subsystems >= MAX_SUBSYSTEMS) { 737 while ((arg = strdelim(&cp)) && *arg != '\0') {
796 fatal("%s line %d: too many subsystems defined.", 738 if (options->num_deny_groups >= MAX_DENY_GROUPS)
797 filename, linenum); 739 fatal("%s line %d: too many deny groups.",
798 } 740 filename, linenum);
799 arg = strdelim(&cp); 741 options->deny_groups[options->num_deny_groups++] = xstrdup(arg);
800 if (!arg || *arg == '\0') 742 }
801 fatal("%s line %d: Missing subsystem name.", 743 break;
802 filename, linenum);
803 for (i = 0; i < options->num_subsystems; i++)
804 if (strcmp(arg, options->subsystem_name[i]) == 0)
805 fatal("%s line %d: Subsystem '%s' already defined.",
806 filename, linenum, arg);
807 options->subsystem_name[options->num_subsystems] = xstrdup(arg);
808 arg = strdelim(&cp);
809 if (!arg || *arg == '\0')
810 fatal("%s line %d: Missing subsystem command.",
811 filename, linenum);
812 options->subsystem_command[options->num_subsystems] = xstrdup(arg);
813 options->num_subsystems++;
814 break;
815 744
816 case sMaxStartups: 745 case sCiphers:
817 arg = strdelim(&cp); 746 arg = strdelim(&cp);
818 if (!arg || *arg == '\0') 747 if (!arg || *arg == '\0')
819 fatal("%s line %d: Missing MaxStartups spec.", 748 fatal("%s line %d: Missing argument.", filename, linenum);
820 filename, linenum); 749 if (!ciphers_valid(arg))
821 if ((n = sscanf(arg, "%d:%d:%d", 750 fatal("%s line %d: Bad SSH2 cipher spec '%s'.",
822 &options->max_startups_begin, 751 filename, linenum, arg ? arg : "<NONE>");
823 &options->max_startups_rate, 752 if (options->ciphers == NULL)
824 &options->max_startups)) == 3) { 753 options->ciphers = xstrdup(arg);
825 if (options->max_startups_begin > 754 break;
826 options->max_startups || 755
827 options->max_startups_rate > 100 || 756 case sMacs:
828 options->max_startups_rate < 1) 757 arg = strdelim(&cp);
829 fatal("%s line %d: Illegal MaxStartups spec.", 758 if (!arg || *arg == '\0')
830 filename, linenum); 759 fatal("%s line %d: Missing argument.", filename, linenum);
831 } else if (n != 1) 760 if (!mac_valid(arg))
761 fatal("%s line %d: Bad SSH2 mac spec '%s'.",
762 filename, linenum, arg ? arg : "<NONE>");
763 if (options->macs == NULL)
764 options->macs = xstrdup(arg);
765 break;
766
767 case sProtocol:
768 intptr = &options->protocol;
769 arg = strdelim(&cp);
770 if (!arg || *arg == '\0')
771 fatal("%s line %d: Missing argument.", filename, linenum);
772 value = proto_spec(arg);
773 if (value == SSH_PROTO_UNKNOWN)
774 fatal("%s line %d: Bad protocol spec '%s'.",
775 filename, linenum, arg ? arg : "<NONE>");
776 if (*intptr == SSH_PROTO_UNKNOWN)
777 *intptr = value;
778 break;
779
780 case sSubsystem:
781 if (options->num_subsystems >= MAX_SUBSYSTEMS) {
782 fatal("%s line %d: too many subsystems defined.",
783 filename, linenum);
784 }
785 arg = strdelim(&cp);
786 if (!arg || *arg == '\0')
787 fatal("%s line %d: Missing subsystem name.",
788 filename, linenum);
789 for (i = 0; i < options->num_subsystems; i++)
790 if (strcmp(arg, options->subsystem_name[i]) == 0)
791 fatal("%s line %d: Subsystem '%s' already defined.",
792 filename, linenum, arg);
793 options->subsystem_name[options->num_subsystems] = xstrdup(arg);
794 arg = strdelim(&cp);
795 if (!arg || *arg == '\0')
796 fatal("%s line %d: Missing subsystem command.",
797 filename, linenum);
798 options->subsystem_command[options->num_subsystems] = xstrdup(arg);
799 options->num_subsystems++;
800 break;
801
802 case sMaxStartups:
803 arg = strdelim(&cp);
804 if (!arg || *arg == '\0')
805 fatal("%s line %d: Missing MaxStartups spec.",
806 filename, linenum);
807 if ((n = sscanf(arg, "%d:%d:%d",
808 &options->max_startups_begin,
809 &options->max_startups_rate,
810 &options->max_startups)) == 3) {
811 if (options->max_startups_begin >
812 options->max_startups ||
813 options->max_startups_rate > 100 ||
814 options->max_startups_rate < 1)
832 fatal("%s line %d: Illegal MaxStartups spec.", 815 fatal("%s line %d: Illegal MaxStartups spec.",
833 filename, linenum); 816 filename, linenum);
834 else 817 } else if (n != 1)
835 options->max_startups = options->max_startups_begin; 818 fatal("%s line %d: Illegal MaxStartups spec.",
836 break; 819 filename, linenum);
820 else
821 options->max_startups = options->max_startups_begin;
822 break;
823
824 case sBanner:
825 charptr = &options->banner;
826 goto parse_filename;
827 /*
828 * These options can contain %X options expanded at
829 * connect time, so that you can specify paths like:
830 *
831 * AuthorizedKeysFile /etc/ssh_keys/%u
832 */
833 case sAuthorizedKeysFile:
834 case sAuthorizedKeysFile2:
835 charptr = (opcode == sAuthorizedKeysFile ) ?
836 &options->authorized_keys_file :
837 &options->authorized_keys_file2;
838 goto parse_filename;
839
840 case sClientAliveInterval:
841 intptr = &options->client_alive_interval;
842 goto parse_time;
843
844 case sClientAliveCountMax:
845 intptr = &options->client_alive_count_max;
846 goto parse_int;
847
848 case sDeprecated:
849 log("%s line %d: Deprecated option %s",
850 filename, linenum, arg);
851 while (arg)
852 arg = strdelim(&cp);
853 break;
854
855 default:
856 fatal("%s line %d: Missing handler for opcode %s (%d)",
857 filename, linenum, arg, opcode);
858 }
859 if ((arg = strdelim(&cp)) != NULL && *arg != '\0')
860 fatal("%s line %d: garbage at end of line; \"%.200s\".",
861 filename, linenum, arg);
862 return 0;
863}
837 864
838 case sBanner: 865/* Reads the server configuration file. */
839 charptr = &options->banner;
840 goto parse_filename;
841 /*
842 * These options can contain %X options expanded at
843 * connect time, so that you can specify paths like:
844 *
845 * AuthorizedKeysFile /etc/ssh_keys/%u
846 */
847 case sAuthorizedKeysFile:
848 case sAuthorizedKeysFile2:
849 charptr = (opcode == sAuthorizedKeysFile ) ?
850 &options->authorized_keys_file :
851 &options->authorized_keys_file2;
852 goto parse_filename;
853
854 case sClientAliveInterval:
855 intptr = &options->client_alive_interval;
856 goto parse_time;
857
858 case sClientAliveCountMax:
859 intptr = &options->client_alive_count_max;
860 goto parse_int;
861
862 case sDeprecated:
863 log("%s line %d: Deprecated option %s",
864 filename, linenum, arg);
865 while (arg)
866 arg = strdelim(&cp);
867 break;
868 866
869 default: 867void
870 fatal("%s line %d: Missing handler for opcode %s (%d)", 868read_server_config(ServerOptions *options, const char *filename)
871 filename, linenum, arg, opcode); 869{
872 } 870 FILE *f;
873 if ((arg = strdelim(&cp)) != NULL && *arg != '\0') 871 char line[1024];
874 fatal("%s line %d: garbage at end of line; \"%.200s\".", 872 int linenum;
875 filename, linenum, arg); 873 int bad_options = 0;
874
875 f = fopen(filename, "r");
876 if (!f) {
877 perror(filename);
878 exit(1);
879 }
880 linenum = 0;
881 while (fgets(line, sizeof(line), f)) {
882 /* Update line number counter. */
883 linenum++;
884 if (process_server_config_line(options, line, filename, linenum) != 0)
885 bad_options++;
876 } 886 }
877 fclose(f); 887 fclose(f);
878 if (bad_options > 0) 888 if (bad_options > 0)
diff --git a/servconf.h b/servconf.h
index 2e10b1c33..90ecbc70e 100644
--- a/servconf.h
+++ b/servconf.h
@@ -11,7 +11,7 @@
11 * called by a name other than "ssh" or "Secure Shell". 11 * called by a name other than "ssh" or "Secure Shell".
12 */ 12 */
13 13
14/* RCSID("$OpenBSD: servconf.h,v 1.49 2001/08/17 18:59:47 stevesk Exp $"); */ 14/* RCSID("$OpenBSD: servconf.h,v 1.50 2001/12/06 13:30:05 markus Exp $"); */
15 15
16#ifndef SERVCONF_H 16#ifndef SERVCONF_H
17#define SERVCONF_H 17#define SERVCONF_H
@@ -135,5 +135,7 @@ typedef struct {
135void initialize_server_options(ServerOptions *); 135void initialize_server_options(ServerOptions *);
136void read_server_config(ServerOptions *, const char *); 136void read_server_config(ServerOptions *, const char *);
137void fill_default_server_options(ServerOptions *); 137void fill_default_server_options(ServerOptions *);
138int process_server_config_line(ServerOptions *, char *, const char *, int);
139
138 140
139#endif /* SERVCONF_H */ 141#endif /* SERVCONF_H */
diff --git a/sshd.8 b/sshd.8
index a3826fa80..91da9adef 100644
--- a/sshd.8
+++ b/sshd.8
@@ -34,7 +34,7 @@
34.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36.\" 36.\"
37.\" $OpenBSD: sshd.8,v 1.155 2001/12/01 21:41:48 markus Exp $ 37.\" $OpenBSD: sshd.8,v 1.156 2001/12/06 13:30:06 markus Exp $
38.Dd September 25, 1999 38.Dd September 25, 1999
39.Dt SSHD 8 39.Dt SSHD 8
40.Os 40.Os
@@ -49,6 +49,7 @@
49.Op Fl g Ar login_grace_time 49.Op Fl g Ar login_grace_time
50.Op Fl h Ar host_key_file 50.Op Fl h Ar host_key_file
51.Op Fl k Ar key_gen_time 51.Op Fl k Ar key_gen_time
52.Op Fl o Ar option
52.Op Fl p Ar port 53.Op Fl p Ar port
53.Op Fl u Ar len 54.Op Fl u Ar len
54.Sh DESCRIPTION 55.Sh DESCRIPTION
@@ -237,6 +238,10 @@ it becomes impossible to recover the key for decrypting intercepted
237communications even if the machine is cracked into or physically 238communications even if the machine is cracked into or physically
238seized. 239seized.
239A value of zero indicates that the key will never be regenerated. 240A value of zero indicates that the key will never be regenerated.
241.It Fl o Ar option
242Can be used to give options in the format used in the configuration file.
243This is useful for specifying options for which there is no separate
244command-line flag.
240.It Fl p Ar port 245.It Fl p Ar port
241Specifies the port on which the server listens for connections 246Specifies the port on which the server listens for connections
242(default 22). 247(default 22).
diff --git a/sshd.c b/sshd.c
index 74175a6fc..f105b8b06 100644
--- a/sshd.c
+++ b/sshd.c
@@ -40,7 +40,7 @@
40 */ 40 */
41 41
42#include "includes.h" 42#include "includes.h"
43RCSID("$OpenBSD: sshd.c,v 1.214 2001/12/05 10:06:13 deraadt Exp $"); 43RCSID("$OpenBSD: sshd.c,v 1.215 2001/12/06 13:30:06 markus Exp $");
44 44
45#include <openssl/dh.h> 45#include <openssl/dh.h>
46#include <openssl/bn.h> 46#include <openssl/bn.h>
@@ -543,6 +543,31 @@ drop_connection(int startups)
543 return (r < p) ? 1 : 0; 543 return (r < p) ? 1 : 0;
544} 544}
545 545
546static void
547usage(void)
548{
549 fprintf(stderr, "sshd version %s\n", SSH_VERSION);
550 fprintf(stderr, "Usage: %s [options]\n", __progname);
551 fprintf(stderr, "Options:\n");
552 fprintf(stderr, " -f file Configuration file (default %s)\n", _PATH_SERVER_CONFIG_FILE);
553 fprintf(stderr, " -d Debugging mode (multiple -d means more debugging)\n");
554 fprintf(stderr, " -i Started from inetd\n");
555 fprintf(stderr, " -D Do not fork into daemon mode\n");
556 fprintf(stderr, " -t Only test configuration file and keys\n");
557 fprintf(stderr, " -q Quiet (no logging)\n");
558 fprintf(stderr, " -p port Listen on the specified port (default: 22)\n");
559 fprintf(stderr, " -k seconds Regenerate server key every this many seconds (default: 3600)\n");
560 fprintf(stderr, " -g seconds Grace period for authentication (default: 600)\n");
561 fprintf(stderr, " -b bits Size of server RSA key (default: 768 bits)\n");
562 fprintf(stderr, " -h file File from which to read host key (default: %s)\n",
563 _PATH_HOST_KEY_FILE);
564 fprintf(stderr, " -u len Maximum hostname length for utmp recording\n");
565 fprintf(stderr, " -4 Use IPv4 only\n");
566 fprintf(stderr, " -6 Use IPv6 only\n");
567 fprintf(stderr, " -o option Process the option as if it was read from a configuration file.\n");
568 exit(1);
569}
570
546/* 571/*
547 * Main program for the daemon. 572 * Main program for the daemon.
548 */ 573 */
@@ -579,7 +604,7 @@ main(int ac, char **av)
579 initialize_server_options(&options); 604 initialize_server_options(&options);
580 605
581 /* Parse command-line arguments. */ 606 /* Parse command-line arguments. */
582 while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:u:dDeiqtQ46")) != -1) { 607 while ((opt = getopt(ac, av, "f:p:b:k:h:g:V:u:o:dDeiqtQ46")) != -1) {
583 switch (opt) { 608 switch (opt) {
584 case '4': 609 case '4':
585 IPv4or6 = AF_INET; 610 IPv4or6 = AF_INET;
@@ -661,27 +686,15 @@ main(int ac, char **av)
661 case 'u': 686 case 'u':
662 utmp_len = atoi(optarg); 687 utmp_len = atoi(optarg);
663 break; 688 break;
689 case 'o':
690 if (process_server_config_line(&options, optarg,
691 "command-line", 0) != 0)
692 exit(1);
693 break;
664 case '?': 694 case '?':
665 default: 695 default:
666 fprintf(stderr, "sshd version %s\n", SSH_VERSION); 696 usage();
667 fprintf(stderr, "Usage: %s [options]\n", __progname); 697 break;
668 fprintf(stderr, "Options:\n");
669 fprintf(stderr, " -f file Configuration file (default %s)\n", _PATH_SERVER_CONFIG_FILE);
670 fprintf(stderr, " -d Debugging mode (multiple -d means more debugging)\n");
671 fprintf(stderr, " -i Started from inetd\n");
672 fprintf(stderr, " -D Do not fork into daemon mode\n");
673 fprintf(stderr, " -t Only test configuration file and keys\n");
674 fprintf(stderr, " -q Quiet (no logging)\n");
675 fprintf(stderr, " -p port Listen on the specified port (default: 22)\n");
676 fprintf(stderr, " -k seconds Regenerate server key every this many seconds (default: 3600)\n");
677 fprintf(stderr, " -g seconds Grace period for authentication (default: 600)\n");
678 fprintf(stderr, " -b bits Size of server RSA key (default: 768 bits)\n");
679 fprintf(stderr, " -h file File from which to read host key (default: %s)\n",
680 _PATH_HOST_KEY_FILE);
681 fprintf(stderr, " -u len Maximum hostname length for utmp recording\n");
682 fprintf(stderr, " -4 Use IPv4 only\n");
683 fprintf(stderr, " -6 Use IPv6 only\n");
684 exit(1);
685 } 698 }
686 } 699 }
687 SSLeay_add_all_algorithms(); 700 SSLeay_add_all_algorithms();