summaryrefslogtreecommitdiff
path: root/sshconnect.c
diff options
context:
space:
mode:
authorBen Lindstrom <mouring@eviladmin.org>2001-06-25 04:37:41 +0000
committerBen Lindstrom <mouring@eviladmin.org>2001-06-25 04:37:41 +0000
commitd6481ea49ab5999e00cc2a2fd7b6a1d779f4c598 (patch)
treec89fd81312f3b95fe22bcaad56cdb1b2a2dd822a /sshconnect.c
parentb710f788f173a80a9a24fa041558087b56bb7fac (diff)
- markus@cvs.openbsd.org 2001/06/23 02:34:33
[kexdh.c kexgex.c kex.h pathnames.h readconf.c servconf.h ssh.1 sshconnect1.c sshconnect2.c sshconnect.c sshconnect.h sshd.8] get rid of known_hosts2, use it for hostkey lookup, but do not modify.
Diffstat (limited to 'sshconnect.c')
-rw-r--r--sshconnect.c147
1 files changed, 105 insertions, 42 deletions
diff --git a/sshconnect.c b/sshconnect.c
index bafdec95a..1766de0c3 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -13,7 +13,7 @@
13 */ 13 */
14 14
15#include "includes.h" 15#include "includes.h"
16RCSID("$OpenBSD: sshconnect.c,v 1.107 2001/06/07 20:23:05 markus Exp $"); 16RCSID("$OpenBSD: sshconnect.c,v 1.108 2001/06/23 02:34:31 markus Exp $");
17 17
18#include <openssl/bn.h> 18#include <openssl/bn.h>
19 19
@@ -467,7 +467,10 @@ read_yes_or_no(const char *prompt, int defval)
467 while (1) { 467 while (1) {
468 fprintf(stderr, "%s", prompt); 468 fprintf(stderr, "%s", prompt);
469 if (fgets(buf, sizeof(buf), f) == NULL) { 469 if (fgets(buf, sizeof(buf), f) == NULL) {
470 /* Print a newline (the prompt probably didn\'t have one). */ 470 /*
471 * Print a newline (the prompt probably didn\'t have
472 * one).
473 */
471 fprintf(stderr, "\n"); 474 fprintf(stderr, "\n");
472 strlcpy(buf, "no", sizeof buf); 475 strlcpy(buf, "no", sizeof buf);
473 } 476 }
@@ -493,12 +496,13 @@ read_yes_or_no(const char *prompt, int defval)
493} 496}
494 497
495/* 498/*
496 * check whether the supplied host key is valid, return only if ok. 499 * check whether the supplied host key is valid, return -1 if the key
500 * is not valid. the user_hostfile will not be updated if 'readonly' is true.
497 */ 501 */
498 502
499void 503int
500check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key, 504check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
501 const char *user_hostfile, const char *system_hostfile) 505 int readonly, const char *user_hostfile, const char *system_hostfile)
502{ 506{
503 Key *file_key; 507 Key *file_key;
504 char *type = key_type(host_key); 508 char *type = key_type(host_key);
@@ -523,11 +527,13 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
523 /** hostaddr == 0! */ 527 /** hostaddr == 0! */
524 switch (hostaddr->sa_family) { 528 switch (hostaddr->sa_family) {
525 case AF_INET: 529 case AF_INET:
526 local = (ntohl(((struct sockaddr_in *)hostaddr)->sin_addr.s_addr) >> 24) == IN_LOOPBACKNET; 530 local = (ntohl(((struct sockaddr_in *)hostaddr)->
531 sin_addr.s_addr) >> 24) == IN_LOOPBACKNET;
527 salen = sizeof(struct sockaddr_in); 532 salen = sizeof(struct sockaddr_in);
528 break; 533 break;
529 case AF_INET6: 534 case AF_INET6:
530 local = IN6_IS_ADDR_LOOPBACK(&(((struct sockaddr_in6 *)hostaddr)->sin6_addr)); 535 local = IN6_IS_ADDR_LOOPBACK(
536 &(((struct sockaddr_in6 *)hostaddr)->sin6_addr));
531 salen = sizeof(struct sockaddr_in6); 537 salen = sizeof(struct sockaddr_in6);
532 break; 538 break;
533 default: 539 default:
@@ -538,7 +544,7 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
538 if (local && options.host_key_alias == NULL) { 544 if (local && options.host_key_alias == NULL) {
539 debug("Forcing accepting of host key for " 545 debug("Forcing accepting of host key for "
540 "loopback/localhost."); 546 "loopback/localhost.");
541 return; 547 return 0;
542 } 548 }
543 549
544 /* 550 /*
@@ -582,10 +588,12 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
582 * hosts or in the systemwide list. 588 * hosts or in the systemwide list.
583 */ 589 */
584 host_file = user_hostfile; 590 host_file = user_hostfile;
585 host_status = check_host_in_hostfile(host_file, host, host_key, file_key, &host_line); 591 host_status = check_host_in_hostfile(host_file, host, host_key,
592 file_key, &host_line);
586 if (host_status == HOST_NEW) { 593 if (host_status == HOST_NEW) {
587 host_file = system_hostfile; 594 host_file = system_hostfile;
588 host_status = check_host_in_hostfile(host_file, host, host_key, file_key, &host_line); 595 host_status = check_host_in_hostfile(host_file, host, host_key,
596 file_key, &host_line);
589 } 597 }
590 /* 598 /*
591 * Also perform check for the ip address, skip the check if we are 599 * Also perform check for the ip address, skip the check if we are
@@ -595,10 +603,12 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
595 Key *ip_key = key_new(host_key->type); 603 Key *ip_key = key_new(host_key->type);
596 604
597 ip_file = user_hostfile; 605 ip_file = user_hostfile;
598 ip_status = check_host_in_hostfile(ip_file, ip, host_key, ip_key, &ip_line); 606 ip_status = check_host_in_hostfile(ip_file, ip, host_key,
607 ip_key, &ip_line);
599 if (ip_status == HOST_NEW) { 608 if (ip_status == HOST_NEW) {
600 ip_file = system_hostfile; 609 ip_file = system_hostfile;
601 ip_status = check_host_in_hostfile(ip_file, ip, host_key, ip_key, &ip_line); 610 ip_status = check_host_in_hostfile(ip_file, ip,
611 host_key, ip_key, &ip_line);
602 } 612 }
603 if (host_status == HOST_CHANGED && 613 if (host_status == HOST_CHANGED &&
604 (ip_status != HOST_CHANGED || !key_equal(ip_key, file_key))) 614 (ip_status != HOST_CHANGED || !key_equal(ip_key, file_key)))
@@ -617,32 +627,49 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
617 host, type); 627 host, type);
618 debug("Found key in %s:%d", host_file, host_line); 628 debug("Found key in %s:%d", host_file, host_line);
619 if (options.check_host_ip && ip_status == HOST_NEW) { 629 if (options.check_host_ip && ip_status == HOST_NEW) {
620 if (!add_host_to_hostfile(user_hostfile, ip, host_key)) 630 if (readonly)
621 log("Failed to add the %s host key for IP address '%.128s' to the list of known hosts (%.30s).", 631 log("%s host key for IP address "
622 type, ip, user_hostfile); 632 "'%.128s' not in list of known hosts.",
623 else
624 log("Warning: Permanently added the %s host key for IP address '%.128s' to the list of known hosts.",
625 type, ip); 633 type, ip);
634 else if (!add_host_to_hostfile(user_hostfile, ip,
635 host_key))
636 log("Failed to add the %s host key for IP "
637 "address '%.128s' to the list of known "
638 "hosts (%.30s).", type, ip, user_hostfile);
639 else
640 log("Warning: Permanently added the %s host "
641 "key for IP address '%.128s' to the list "
642 "of known hosts.", type, ip);
626 } 643 }
627 break; 644 break;
628 case HOST_NEW: 645 case HOST_NEW:
646 if (readonly)
647 goto fail;
629 /* The host is new. */ 648 /* The host is new. */
630 if (options.strict_host_key_checking == 1) { 649 if (options.strict_host_key_checking == 1) {
631 /* User has requested strict host key checking. We will not add the host key 650 /*
632 automatically. The only alternative left is to abort. */ 651 * User has requested strict host key checking. We
633 fatal("No %s host key is known for %.200s and you have requested strict checking.", type, host); 652 * will not add the host key automatically. The only
653 * alternative left is to abort.
654 */
655 error("No %s host key is known for %.200s and you "
656 "have requested strict checking.", type, host);
657 goto fail;
634 } else if (options.strict_host_key_checking == 2) { 658 } else if (options.strict_host_key_checking == 2) {
635 /* The default */ 659 /* The default */
636 char prompt[1024]; 660 char prompt[1024];
637 fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX); 661 fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
638 snprintf(prompt, sizeof(prompt), 662 snprintf(prompt, sizeof(prompt),
639 "The authenticity of host '%.200s (%s)' can't be established.\n" 663 "The authenticity of host '%.200s (%s)' can't be "
664 "established.\n"
640 "%s key fingerprint is %s.\n" 665 "%s key fingerprint is %s.\n"
641 "Are you sure you want to continue connecting (yes/no)? ", 666 "Are you sure you want to continue connecting "
642 host, ip, type, fp); 667 "(yes/no)? ", host, ip, type, fp);
643 xfree(fp); 668 xfree(fp);
644 if (!read_yes_or_no(prompt, -1)) 669 if (!read_yes_or_no(prompt, -1)) {
645 fatal("Aborted by user!"); 670 log("Aborted by user!");
671 goto fail;
672 }
646 } 673 }
647 if (options.check_host_ip && ip_status == HOST_NEW) { 674 if (options.check_host_ip && ip_status == HOST_NEW) {
648 snprintf(hostline, sizeof(hostline), "%s,%s", host, ip); 675 snprintf(hostline, sizeof(hostline), "%s,%s", host, ip);
@@ -650,13 +677,16 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
650 } else 677 } else
651 hostp = host; 678 hostp = host;
652 679
653 /* If not in strict mode, add the key automatically to the local known_hosts file. */ 680 /*
681 * If not in strict mode, add the key automatically to the
682 * local known_hosts file.
683 */
654 if (!add_host_to_hostfile(user_hostfile, hostp, host_key)) 684 if (!add_host_to_hostfile(user_hostfile, hostp, host_key))
655 log("Failed to add the host to the list of known hosts (%.500s).", 685 log("Failed to add the host to the list of known "
656 user_hostfile); 686 "hosts (%.500s).", user_hostfile);
657 else 687 else
658 log("Warning: Permanently added '%.200s' (%s) to the list of known hosts.", 688 log("Warning: Permanently added '%.200s' (%s) to the "
659 hostp, type); 689 "list of known hosts.", hostp, type);
660 break; 690 break;
661 case HOST_CHANGED: 691 case HOST_CHANGED:
662 if (options.check_host_ip && host_ip_differ) { 692 if (options.check_host_ip && host_ip_differ) {
@@ -698,8 +728,11 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
698 * If strict host key checking is in use, the user will have 728 * If strict host key checking is in use, the user will have
699 * to edit the key manually and we can only abort. 729 * to edit the key manually and we can only abort.
700 */ 730 */
701 if (options.strict_host_key_checking) 731 if (options.strict_host_key_checking) {
702 fatal("%s host key for %.200s has changed and you have requested strict checking.", type, host); 732 error("%s host key for %.200s has changed and you have "
733 "requested strict checking.", type, host);
734 goto fail;
735 }
703 736
704 /* 737 /*
705 * If strict host key checking has not been requested, allow 738 * If strict host key checking has not been requested, allow
@@ -707,20 +740,26 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
707 * agent forwarding. 740 * agent forwarding.
708 */ 741 */
709 if (options.password_authentication) { 742 if (options.password_authentication) {
710 error("Password authentication is disabled to avoid trojan horses."); 743 error("Password authentication is disabled to avoid "
744 "man-in-the-middle attacks.");
711 options.password_authentication = 0; 745 options.password_authentication = 0;
712 } 746 }
713 if (options.forward_agent) { 747 if (options.forward_agent) {
714 error("Agent forwarding is disabled to avoid trojan horses."); 748 error("Agent forwarding is disabled to avoid "
749 "man-in-the-middle attacks.");
715 options.forward_agent = 0; 750 options.forward_agent = 0;
716 } 751 }
717 if (options.forward_x11) { 752 if (options.forward_x11) {
718 error("X11 forwarding is disabled to avoid trojan horses."); 753 error("X11 forwarding is disabled to avoid "
754 "man-in-the-middle attacks.");
719 options.forward_x11 = 0; 755 options.forward_x11 = 0;
720 } 756 }
721 if (options.num_local_forwards > 0 || options.num_remote_forwards > 0) { 757 if (options.num_local_forwards > 0 ||
722 error("Port forwarding is disabled to avoid trojan horses."); 758 options.num_remote_forwards > 0) {
723 options.num_local_forwards = options.num_remote_forwards = 0; 759 error("Port forwarding is disabled to avoid "
760 "man-in-the-middle attacks.");
761 options.num_local_forwards =
762 options.num_remote_forwards = 0;
724 } 763 }
725 /* 764 /*
726 * XXX Should permit the user to change to use the new id. 765 * XXX Should permit the user to change to use the new id.
@@ -741,15 +780,39 @@ check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,
741 log("Matching host key in %s:%d", host_file, host_line); 780 log("Matching host key in %s:%d", host_file, host_line);
742 log("Offending key for IP in %s:%d", ip_file, ip_line); 781 log("Offending key for IP in %s:%d", ip_file, ip_line);
743 if (options.strict_host_key_checking == 1) { 782 if (options.strict_host_key_checking == 1) {
744 fatal("Exiting, you have requested strict checking."); 783 error("Exiting, you have requested strict checking.");
784 goto fail;
745 } else if (options.strict_host_key_checking == 2) { 785 } else if (options.strict_host_key_checking == 2) {
746 if (!read_yes_or_no("Are you sure you want " \ 786 if (!read_yes_or_no("Are you sure you want "
747 "to continue connecting (yes/no)? ", -1)) 787 "to continue connecting (yes/no)? ", -1)) {
748 fatal("Aborted by user!"); 788 log("Aborted by user!");
789 goto fail;
790 }
749 } 791 }
750 } 792 }
751 793
752 xfree(ip); 794 xfree(ip);
795 return 0;
796
797fail:
798 xfree(ip);
799 return -1;
800}
801
802int
803verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
804{
805 struct stat st;
806
807 /* return ok if the key can be found in an old keyfile */
808 if (stat(options.system_hostfile2, &st) == 0 ||
809 stat(options.user_hostfile2, &st) == 0) {
810 if (check_host_key(host, hostaddr, host_key, /*readonly*/ 1,
811 options.user_hostfile2, options.system_hostfile2) == 0)
812 return 0;
813 }
814 return check_host_key(host, hostaddr, host_key, /*readonly*/ 0,
815 options.user_hostfile, options.system_hostfile);
753} 816}
754 817
755/* 818/*