diff options
Diffstat (limited to 'sshconnect1.c')
-rw-r--r-- | sshconnect1.c | 589 |
1 files changed, 580 insertions, 9 deletions
diff --git a/sshconnect1.c b/sshconnect1.c index 2f89964ec..2fc9a981a 100644 --- a/sshconnect1.c +++ b/sshconnect1.c | |||
@@ -13,11 +13,25 @@ | |||
13 | */ | 13 | */ |
14 | 14 | ||
15 | #include "includes.h" | 15 | #include "includes.h" |
16 | RCSID("$OpenBSD: sshconnect1.c,v 1.56 2003/08/28 12:54:34 markus Exp $"); | 16 | RCSID("$OpenBSD: sshconnect1.c,v 1.52 2002/08/08 13:50:23 aaron Exp $"); |
17 | 17 | ||
18 | #include <openssl/bn.h> | 18 | #include <openssl/bn.h> |
19 | #include <openssl/md5.h> | 19 | #include <openssl/md5.h> |
20 | 20 | ||
21 | #ifdef KRB4 | ||
22 | #include <krb.h> | ||
23 | #endif | ||
24 | #ifdef KRB5 | ||
25 | #include <krb5.h> | ||
26 | #ifndef HEIMDAL | ||
27 | #define krb5_get_err_text(context,code) error_message(code) | ||
28 | #endif /* !HEIMDAL */ | ||
29 | #endif | ||
30 | #ifdef AFS | ||
31 | #include <kafs.h> | ||
32 | #include "radix.h" | ||
33 | #endif | ||
34 | |||
21 | #include "ssh.h" | 35 | #include "ssh.h" |
22 | #include "ssh1.h" | 36 | #include "ssh1.h" |
23 | #include "xmalloc.h" | 37 | #include "xmalloc.h" |
@@ -108,7 +122,7 @@ try_agent_authentication(void) | |||
108 | * although it advertised it supports this. Just | 122 | * although it advertised it supports this. Just |
109 | * return a wrong value. | 123 | * return a wrong value. |
110 | */ | 124 | */ |
111 | logit("Authentication agent failed to decrypt challenge."); | 125 | log("Authentication agent failed to decrypt challenge."); |
112 | memset(response, 0, sizeof(response)); | 126 | memset(response, 0, sizeof(response)); |
113 | } | 127 | } |
114 | key_free(key); | 128 | key_free(key); |
@@ -366,6 +380,478 @@ try_rhosts_rsa_authentication(const char *local_user, Key * host_key) | |||
366 | return 0; | 380 | return 0; |
367 | } | 381 | } |
368 | 382 | ||
383 | #ifdef KRB4 | ||
384 | static int | ||
385 | try_krb4_authentication(void) | ||
386 | { | ||
387 | KTEXT_ST auth; /* Kerberos data */ | ||
388 | char *reply; | ||
389 | char inst[INST_SZ]; | ||
390 | char *realm; | ||
391 | CREDENTIALS cred; | ||
392 | int r, type; | ||
393 | socklen_t slen; | ||
394 | Key_schedule schedule; | ||
395 | u_long checksum, cksum; | ||
396 | MSG_DAT msg_data; | ||
397 | struct sockaddr_in local, foreign; | ||
398 | struct stat st; | ||
399 | |||
400 | /* Don't do anything if we don't have any tickets. */ | ||
401 | if (stat(tkt_string(), &st) < 0) | ||
402 | return 0; | ||
403 | |||
404 | strlcpy(inst, (char *)krb_get_phost(get_canonical_hostname(1)), | ||
405 | INST_SZ); | ||
406 | |||
407 | realm = (char *)krb_realmofhost(get_canonical_hostname(1)); | ||
408 | if (!realm) { | ||
409 | debug("Kerberos v4: no realm for %s", get_canonical_hostname(1)); | ||
410 | return 0; | ||
411 | } | ||
412 | /* This can really be anything. */ | ||
413 | checksum = (u_long)getpid(); | ||
414 | |||
415 | r = krb_mk_req(&auth, KRB4_SERVICE_NAME, inst, realm, checksum); | ||
416 | if (r != KSUCCESS) { | ||
417 | debug("Kerberos v4 krb_mk_req failed: %s", krb_err_txt[r]); | ||
418 | return 0; | ||
419 | } | ||
420 | /* Get session key to decrypt the server's reply with. */ | ||
421 | r = krb_get_cred(KRB4_SERVICE_NAME, inst, realm, &cred); | ||
422 | if (r != KSUCCESS) { | ||
423 | debug("get_cred failed: %s", krb_err_txt[r]); | ||
424 | return 0; | ||
425 | } | ||
426 | des_key_sched((des_cblock *) cred.session, schedule); | ||
427 | |||
428 | /* Send authentication info to server. */ | ||
429 | packet_start(SSH_CMSG_AUTH_KERBEROS); | ||
430 | packet_put_string((char *) auth.dat, auth.length); | ||
431 | packet_send(); | ||
432 | packet_write_wait(); | ||
433 | |||
434 | /* Zero the buffer. */ | ||
435 | (void) memset(auth.dat, 0, MAX_KTXT_LEN); | ||
436 | |||
437 | slen = sizeof(local); | ||
438 | memset(&local, 0, sizeof(local)); | ||
439 | if (getsockname(packet_get_connection_in(), | ||
440 | (struct sockaddr *)&local, &slen) < 0) | ||
441 | debug("getsockname failed: %s", strerror(errno)); | ||
442 | |||
443 | slen = sizeof(foreign); | ||
444 | memset(&foreign, 0, sizeof(foreign)); | ||
445 | if (getpeername(packet_get_connection_in(), | ||
446 | (struct sockaddr *)&foreign, &slen) < 0) { | ||
447 | debug("getpeername failed: %s", strerror(errno)); | ||
448 | fatal_cleanup(); | ||
449 | } | ||
450 | /* Get server reply. */ | ||
451 | type = packet_read(); | ||
452 | switch (type) { | ||
453 | case SSH_SMSG_FAILURE: | ||
454 | /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */ | ||
455 | debug("Kerberos v4 authentication failed."); | ||
456 | return 0; | ||
457 | break; | ||
458 | |||
459 | case SSH_SMSG_AUTH_KERBEROS_RESPONSE: | ||
460 | /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */ | ||
461 | debug("Kerberos v4 authentication accepted."); | ||
462 | |||
463 | /* Get server's response. */ | ||
464 | reply = packet_get_string((u_int *) &auth.length); | ||
465 | if (auth.length >= MAX_KTXT_LEN) | ||
466 | fatal("Kerberos v4: Malformed response from server"); | ||
467 | memcpy(auth.dat, reply, auth.length); | ||
468 | xfree(reply); | ||
469 | |||
470 | packet_check_eom(); | ||
471 | |||
472 | /* | ||
473 | * If his response isn't properly encrypted with the session | ||
474 | * key, and the decrypted checksum fails to match, he's | ||
475 | * bogus. Bail out. | ||
476 | */ | ||
477 | r = krb_rd_priv(auth.dat, auth.length, schedule, &cred.session, | ||
478 | &foreign, &local, &msg_data); | ||
479 | if (r != KSUCCESS) { | ||
480 | debug("Kerberos v4 krb_rd_priv failed: %s", | ||
481 | krb_err_txt[r]); | ||
482 | packet_disconnect("Kerberos v4 challenge failed!"); | ||
483 | } | ||
484 | /* Fetch the (incremented) checksum that we supplied in the request. */ | ||
485 | memcpy((char *)&cksum, (char *)msg_data.app_data, | ||
486 | sizeof(cksum)); | ||
487 | cksum = ntohl(cksum); | ||
488 | |||
489 | /* If it matches, we're golden. */ | ||
490 | if (cksum == checksum + 1) { | ||
491 | debug("Kerberos v4 challenge successful."); | ||
492 | return 1; | ||
493 | } else | ||
494 | packet_disconnect("Kerberos v4 challenge failed!"); | ||
495 | break; | ||
496 | |||
497 | default: | ||
498 | packet_disconnect("Protocol error on Kerberos v4 response: %d", type); | ||
499 | } | ||
500 | return 0; | ||
501 | } | ||
502 | |||
503 | #endif /* KRB4 */ | ||
504 | |||
505 | #ifdef KRB5 | ||
506 | static int | ||
507 | try_krb5_authentication(krb5_context *context, krb5_auth_context *auth_context) | ||
508 | { | ||
509 | krb5_error_code problem; | ||
510 | const char *tkfile; | ||
511 | struct stat buf; | ||
512 | krb5_ccache ccache = NULL; | ||
513 | const char *remotehost; | ||
514 | krb5_data ap; | ||
515 | int type; | ||
516 | krb5_ap_rep_enc_part *reply = NULL; | ||
517 | int ret; | ||
518 | |||
519 | memset(&ap, 0, sizeof(ap)); | ||
520 | |||
521 | problem = krb5_init_context(context); | ||
522 | if (problem) { | ||
523 | debug("Kerberos v5: krb5_init_context failed"); | ||
524 | ret = 0; | ||
525 | goto out; | ||
526 | } | ||
527 | |||
528 | problem = krb5_auth_con_init(*context, auth_context); | ||
529 | if (problem) { | ||
530 | debug("Kerberos v5: krb5_auth_con_init failed"); | ||
531 | ret = 0; | ||
532 | goto out; | ||
533 | } | ||
534 | |||
535 | #ifndef HEIMDAL | ||
536 | problem = krb5_auth_con_setflags(*context, *auth_context, | ||
537 | KRB5_AUTH_CONTEXT_RET_TIME); | ||
538 | if (problem) { | ||
539 | debug("Keberos v5: krb5_auth_con_setflags failed"); | ||
540 | ret = 0; | ||
541 | goto out; | ||
542 | } | ||
543 | #endif | ||
544 | |||
545 | tkfile = krb5_cc_default_name(*context); | ||
546 | if (strncmp(tkfile, "FILE:", 5) == 0) | ||
547 | tkfile += 5; | ||
548 | |||
549 | if (stat(tkfile, &buf) == 0 && getuid() != buf.st_uid) { | ||
550 | debug("Kerberos v5: could not get default ccache (permission denied)."); | ||
551 | ret = 0; | ||
552 | goto out; | ||
553 | } | ||
554 | |||
555 | problem = krb5_cc_default(*context, &ccache); | ||
556 | if (problem) { | ||
557 | debug("Kerberos v5: krb5_cc_default failed: %s", | ||
558 | krb5_get_err_text(*context, problem)); | ||
559 | ret = 0; | ||
560 | goto out; | ||
561 | } | ||
562 | |||
563 | remotehost = get_canonical_hostname(1); | ||
564 | |||
565 | problem = krb5_mk_req(*context, auth_context, AP_OPTS_MUTUAL_REQUIRED, | ||
566 | "host", remotehost, NULL, ccache, &ap); | ||
567 | if (problem) { | ||
568 | debug("Kerberos v5: krb5_mk_req failed: %s", | ||
569 | krb5_get_err_text(*context, problem)); | ||
570 | ret = 0; | ||
571 | goto out; | ||
572 | } | ||
573 | |||
574 | packet_start(SSH_CMSG_AUTH_KERBEROS); | ||
575 | packet_put_string((char *) ap.data, ap.length); | ||
576 | packet_send(); | ||
577 | packet_write_wait(); | ||
578 | |||
579 | xfree(ap.data); | ||
580 | ap.length = 0; | ||
581 | |||
582 | type = packet_read(); | ||
583 | switch (type) { | ||
584 | case SSH_SMSG_FAILURE: | ||
585 | /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */ | ||
586 | debug("Kerberos v5 authentication failed."); | ||
587 | ret = 0; | ||
588 | break; | ||
589 | |||
590 | case SSH_SMSG_AUTH_KERBEROS_RESPONSE: | ||
591 | /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */ | ||
592 | debug("Kerberos v5 authentication accepted."); | ||
593 | |||
594 | /* Get server's response. */ | ||
595 | ap.data = packet_get_string((unsigned int *) &ap.length); | ||
596 | packet_check_eom(); | ||
597 | /* XXX je to dobre? */ | ||
598 | |||
599 | problem = krb5_rd_rep(*context, *auth_context, &ap, &reply); | ||
600 | if (problem) { | ||
601 | ret = 0; | ||
602 | } | ||
603 | ret = 1; | ||
604 | break; | ||
605 | |||
606 | default: | ||
607 | packet_disconnect("Protocol error on Kerberos v5 response: %d", | ||
608 | type); | ||
609 | ret = 0; | ||
610 | break; | ||
611 | |||
612 | } | ||
613 | |||
614 | out: | ||
615 | if (ccache != NULL) | ||
616 | krb5_cc_close(*context, ccache); | ||
617 | if (reply != NULL) | ||
618 | krb5_free_ap_rep_enc_part(*context, reply); | ||
619 | if (ap.length > 0) | ||
620 | #ifdef HEIMDAL | ||
621 | krb5_data_free(&ap); | ||
622 | #else | ||
623 | krb5_free_data_contents(*context, &ap); | ||
624 | #endif | ||
625 | |||
626 | return (ret); | ||
627 | } | ||
628 | |||
629 | static void | ||
630 | send_krb5_tgt(krb5_context context, krb5_auth_context auth_context) | ||
631 | { | ||
632 | int fd, type; | ||
633 | krb5_error_code problem; | ||
634 | krb5_data outbuf; | ||
635 | krb5_ccache ccache = NULL; | ||
636 | krb5_creds creds; | ||
637 | #ifdef HEIMDAL | ||
638 | krb5_kdc_flags flags; | ||
639 | #else | ||
640 | int forwardable; | ||
641 | #endif | ||
642 | const char *remotehost; | ||
643 | |||
644 | memset(&creds, 0, sizeof(creds)); | ||
645 | memset(&outbuf, 0, sizeof(outbuf)); | ||
646 | |||
647 | fd = packet_get_connection_in(); | ||
648 | |||
649 | #ifdef HEIMDAL | ||
650 | problem = krb5_auth_con_setaddrs_from_fd(context, auth_context, &fd); | ||
651 | #else | ||
652 | problem = krb5_auth_con_genaddrs(context, auth_context, fd, | ||
653 | KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR | | ||
654 | KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR); | ||
655 | #endif | ||
656 | if (problem) | ||
657 | goto out; | ||
658 | |||
659 | problem = krb5_cc_default(context, &ccache); | ||
660 | if (problem) | ||
661 | goto out; | ||
662 | |||
663 | problem = krb5_cc_get_principal(context, ccache, &creds.client); | ||
664 | if (problem) | ||
665 | goto out; | ||
666 | |||
667 | remotehost = get_canonical_hostname(1); | ||
668 | |||
669 | #ifdef HEIMDAL | ||
670 | problem = krb5_build_principal(context, &creds.server, | ||
671 | strlen(creds.client->realm), creds.client->realm, | ||
672 | "krbtgt", creds.client->realm, NULL); | ||
673 | #else | ||
674 | problem = krb5_build_principal(context, &creds.server, | ||
675 | creds.client->realm.length, creds.client->realm.data, | ||
676 | "host", remotehost, NULL); | ||
677 | #endif | ||
678 | if (problem) | ||
679 | goto out; | ||
680 | |||
681 | creds.times.endtime = 0; | ||
682 | |||
683 | #ifdef HEIMDAL | ||
684 | flags.i = 0; | ||
685 | flags.b.forwarded = 1; | ||
686 | flags.b.forwardable = krb5_config_get_bool(context, NULL, | ||
687 | "libdefaults", "forwardable", NULL); | ||
688 | problem = krb5_get_forwarded_creds(context, auth_context, | ||
689 | ccache, flags.i, remotehost, &creds, &outbuf); | ||
690 | #else | ||
691 | forwardable = 1; | ||
692 | problem = krb5_fwd_tgt_creds(context, auth_context, remotehost, | ||
693 | creds.client, creds.server, ccache, forwardable, &outbuf); | ||
694 | #endif | ||
695 | |||
696 | if (problem) | ||
697 | goto out; | ||
698 | |||
699 | packet_start(SSH_CMSG_HAVE_KERBEROS_TGT); | ||
700 | packet_put_string((char *)outbuf.data, outbuf.length); | ||
701 | packet_send(); | ||
702 | packet_write_wait(); | ||
703 | |||
704 | type = packet_read(); | ||
705 | |||
706 | if (type == SSH_SMSG_SUCCESS) { | ||
707 | char *pname; | ||
708 | |||
709 | krb5_unparse_name(context, creds.client, &pname); | ||
710 | debug("Kerberos v5 TGT forwarded (%s).", pname); | ||
711 | xfree(pname); | ||
712 | } else | ||
713 | debug("Kerberos v5 TGT forwarding failed."); | ||
714 | |||
715 | return; | ||
716 | |||
717 | out: | ||
718 | if (problem) | ||
719 | debug("Kerberos v5 TGT forwarding failed: %s", | ||
720 | krb5_get_err_text(context, problem)); | ||
721 | if (creds.client) | ||
722 | krb5_free_principal(context, creds.client); | ||
723 | if (creds.server) | ||
724 | krb5_free_principal(context, creds.server); | ||
725 | if (ccache) | ||
726 | krb5_cc_close(context, ccache); | ||
727 | if (outbuf.data) | ||
728 | xfree(outbuf.data); | ||
729 | } | ||
730 | #endif /* KRB5 */ | ||
731 | |||
732 | #ifdef AFS | ||
733 | static void | ||
734 | send_krb4_tgt(void) | ||
735 | { | ||
736 | CREDENTIALS *creds; | ||
737 | struct stat st; | ||
738 | char buffer[4096], pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ]; | ||
739 | int problem, type; | ||
740 | |||
741 | /* Don't do anything if we don't have any tickets. */ | ||
742 | if (stat(tkt_string(), &st) < 0) | ||
743 | return; | ||
744 | |||
745 | creds = xmalloc(sizeof(*creds)); | ||
746 | |||
747 | problem = krb_get_tf_fullname(TKT_FILE, pname, pinst, prealm); | ||
748 | if (problem) | ||
749 | goto out; | ||
750 | |||
751 | problem = krb_get_cred("krbtgt", prealm, prealm, creds); | ||
752 | if (problem) | ||
753 | goto out; | ||
754 | |||
755 | if (time(0) > krb_life_to_time(creds->issue_date, creds->lifetime)) { | ||
756 | problem = RD_AP_EXP; | ||
757 | goto out; | ||
758 | } | ||
759 | creds_to_radix(creds, (u_char *)buffer, sizeof(buffer)); | ||
760 | |||
761 | packet_start(SSH_CMSG_HAVE_KERBEROS_TGT); | ||
762 | packet_put_cstring(buffer); | ||
763 | packet_send(); | ||
764 | packet_write_wait(); | ||
765 | |||
766 | type = packet_read(); | ||
767 | |||
768 | if (type == SSH_SMSG_SUCCESS) | ||
769 | debug("Kerberos v4 TGT forwarded (%s%s%s@%s).", | ||
770 | creds->pname, creds->pinst[0] ? "." : "", | ||
771 | creds->pinst, creds->realm); | ||
772 | else | ||
773 | debug("Kerberos v4 TGT rejected."); | ||
774 | |||
775 | xfree(creds); | ||
776 | return; | ||
777 | |||
778 | out: | ||
779 | debug("Kerberos v4 TGT passing failed: %s", krb_err_txt[problem]); | ||
780 | xfree(creds); | ||
781 | } | ||
782 | |||
783 | static void | ||
784 | send_afs_tokens(void) | ||
785 | { | ||
786 | CREDENTIALS creds; | ||
787 | struct ViceIoctl parms; | ||
788 | struct ClearToken ct; | ||
789 | int i, type, len; | ||
790 | char buf[2048], *p, *server_cell; | ||
791 | char buffer[8192]; | ||
792 | |||
793 | /* Move over ktc_GetToken, here's something leaner. */ | ||
794 | for (i = 0; i < 100; i++) { /* just in case */ | ||
795 | parms.in = (char *) &i; | ||
796 | parms.in_size = sizeof(i); | ||
797 | parms.out = buf; | ||
798 | parms.out_size = sizeof(buf); | ||
799 | if (k_pioctl(0, VIOCGETTOK, &parms, 0) != 0) | ||
800 | break; | ||
801 | p = buf; | ||
802 | |||
803 | /* Get secret token. */ | ||
804 | memcpy(&creds.ticket_st.length, p, sizeof(u_int)); | ||
805 | if (creds.ticket_st.length > MAX_KTXT_LEN) | ||
806 | break; | ||
807 | p += sizeof(u_int); | ||
808 | memcpy(creds.ticket_st.dat, p, creds.ticket_st.length); | ||
809 | p += creds.ticket_st.length; | ||
810 | |||
811 | /* Get clear token. */ | ||
812 | memcpy(&len, p, sizeof(len)); | ||
813 | if (len != sizeof(struct ClearToken)) | ||
814 | break; | ||
815 | p += sizeof(len); | ||
816 | memcpy(&ct, p, len); | ||
817 | p += len; | ||
818 | p += sizeof(len); /* primary flag */ | ||
819 | server_cell = p; | ||
820 | |||
821 | /* Flesh out our credentials. */ | ||
822 | strlcpy(creds.service, "afs", sizeof(creds.service)); | ||
823 | creds.instance[0] = '\0'; | ||
824 | strlcpy(creds.realm, server_cell, REALM_SZ); | ||
825 | memcpy(creds.session, ct.HandShakeKey, DES_KEY_SZ); | ||
826 | creds.issue_date = ct.BeginTimestamp; | ||
827 | creds.lifetime = krb_time_to_life(creds.issue_date, | ||
828 | ct.EndTimestamp); | ||
829 | creds.kvno = ct.AuthHandle; | ||
830 | snprintf(creds.pname, sizeof(creds.pname), "AFS ID %d", ct.ViceId); | ||
831 | creds.pinst[0] = '\0'; | ||
832 | |||
833 | /* Encode token, ship it off. */ | ||
834 | if (creds_to_radix(&creds, (u_char *)buffer, | ||
835 | sizeof(buffer)) <= 0) | ||
836 | break; | ||
837 | packet_start(SSH_CMSG_HAVE_AFS_TOKEN); | ||
838 | packet_put_cstring(buffer); | ||
839 | packet_send(); | ||
840 | packet_write_wait(); | ||
841 | |||
842 | /* Roger, Roger. Clearance, Clarence. What's your vector, | ||
843 | Victor? */ | ||
844 | type = packet_read(); | ||
845 | |||
846 | if (type == SSH_SMSG_FAILURE) | ||
847 | debug("AFS token for cell %s rejected.", server_cell); | ||
848 | else if (type != SSH_SMSG_SUCCESS) | ||
849 | packet_disconnect("Protocol error on AFS token response: %d", type); | ||
850 | } | ||
851 | } | ||
852 | |||
853 | #endif /* AFS */ | ||
854 | |||
369 | /* | 855 | /* |
370 | * Tries to authenticate with any string-based challenge/response system. | 856 | * Tries to authenticate with any string-based challenge/response system. |
371 | * Note that the client code is not tied to s/key or TIS. | 857 | * Note that the client code is not tied to s/key or TIS. |
@@ -404,7 +890,7 @@ try_challenge_response_authentication(void) | |||
404 | if (i != 0) | 890 | if (i != 0) |
405 | error("Permission denied, please try again."); | 891 | error("Permission denied, please try again."); |
406 | if (options.cipher == SSH_CIPHER_NONE) | 892 | if (options.cipher == SSH_CIPHER_NONE) |
407 | logit("WARNING: Encryption is disabled! " | 893 | log("WARNING: Encryption is disabled! " |
408 | "Response will be transmitted in clear text."); | 894 | "Response will be transmitted in clear text."); |
409 | response = read_passphrase(prompt, 0); | 895 | response = read_passphrase(prompt, 0); |
410 | if (strcmp(response, "") == 0) { | 896 | if (strcmp(response, "") == 0) { |
@@ -439,7 +925,7 @@ try_password_authentication(char *prompt) | |||
439 | 925 | ||
440 | debug("Doing password authentication."); | 926 | debug("Doing password authentication."); |
441 | if (options.cipher == SSH_CIPHER_NONE) | 927 | if (options.cipher == SSH_CIPHER_NONE) |
442 | logit("WARNING: Encryption is disabled! Password will be transmitted in clear text."); | 928 | log("WARNING: Encryption is disabled! Password will be transmitted in clear text."); |
443 | for (i = 0; i < options.number_of_password_prompts; i++) { | 929 | for (i = 0; i < options.number_of_password_prompts; i++) { |
444 | if (i != 0) | 930 | if (i != 0) |
445 | error("Permission denied, please try again."); | 931 | error("Permission denied, please try again."); |
@@ -495,9 +981,9 @@ ssh_kex(char *host, struct sockaddr *hostaddr) | |||
495 | 981 | ||
496 | rbits = BN_num_bits(server_key->rsa->n); | 982 | rbits = BN_num_bits(server_key->rsa->n); |
497 | if (bits != rbits) { | 983 | if (bits != rbits) { |
498 | logit("Warning: Server lies about size of server public key: " | 984 | log("Warning: Server lies about size of server public key: " |
499 | "actual size is %d bits vs. announced %d.", rbits, bits); | 985 | "actual size is %d bits vs. announced %d.", rbits, bits); |
500 | logit("Warning: This may be due to an old implementation of ssh."); | 986 | log("Warning: This may be due to an old implementation of ssh."); |
501 | } | 987 | } |
502 | /* Get the host key. */ | 988 | /* Get the host key. */ |
503 | host_key = key_new(KEY_RSA1); | 989 | host_key = key_new(KEY_RSA1); |
@@ -507,9 +993,9 @@ ssh_kex(char *host, struct sockaddr *hostaddr) | |||
507 | 993 | ||
508 | rbits = BN_num_bits(host_key->rsa->n); | 994 | rbits = BN_num_bits(host_key->rsa->n); |
509 | if (bits != rbits) { | 995 | if (bits != rbits) { |
510 | logit("Warning: Server lies about size of server host key: " | 996 | log("Warning: Server lies about size of server host key: " |
511 | "actual size is %d bits vs. announced %d.", rbits, bits); | 997 | "actual size is %d bits vs. announced %d.", rbits, bits); |
512 | logit("Warning: This may be due to an old implementation of ssh."); | 998 | log("Warning: This may be due to an old implementation of ssh."); |
513 | } | 999 | } |
514 | 1000 | ||
515 | /* Get protocol flags. */ | 1001 | /* Get protocol flags. */ |
@@ -600,7 +1086,7 @@ ssh_kex(char *host, struct sockaddr *hostaddr) | |||
600 | options.cipher = ssh_cipher_default; | 1086 | options.cipher = ssh_cipher_default; |
601 | } else if (options.cipher == SSH_CIPHER_ILLEGAL || | 1087 | } else if (options.cipher == SSH_CIPHER_ILLEGAL || |
602 | !(cipher_mask_ssh1(1) & (1 << options.cipher))) { | 1088 | !(cipher_mask_ssh1(1) & (1 << options.cipher))) { |
603 | logit("No valid SSH1 cipher, using %.100s instead.", | 1089 | log("No valid SSH1 cipher, using %.100s instead.", |
604 | cipher_name(ssh_cipher_default)); | 1090 | cipher_name(ssh_cipher_default)); |
605 | options.cipher = ssh_cipher_default; | 1091 | options.cipher = ssh_cipher_default; |
606 | } | 1092 | } |
@@ -654,6 +1140,10 @@ void | |||
654 | ssh_userauth1(const char *local_user, const char *server_user, char *host, | 1140 | ssh_userauth1(const char *local_user, const char *server_user, char *host, |
655 | Sensitive *sensitive) | 1141 | Sensitive *sensitive) |
656 | { | 1142 | { |
1143 | #ifdef KRB5 | ||
1144 | krb5_context context = NULL; | ||
1145 | krb5_auth_context auth_context = NULL; | ||
1146 | #endif | ||
657 | int i, type; | 1147 | int i, type; |
658 | 1148 | ||
659 | if (supported_authentications == 0) | 1149 | if (supported_authentications == 0) |
@@ -678,6 +1168,56 @@ ssh_userauth1(const char *local_user, const char *server_user, char *host, | |||
678 | if (type != SSH_SMSG_FAILURE) | 1168 | if (type != SSH_SMSG_FAILURE) |
679 | packet_disconnect("Protocol error: got %d in response to SSH_CMSG_USER", type); | 1169 | packet_disconnect("Protocol error: got %d in response to SSH_CMSG_USER", type); |
680 | 1170 | ||
1171 | #ifdef KRB5 | ||
1172 | if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) && | ||
1173 | options.kerberos_authentication) { | ||
1174 | debug("Trying Kerberos v5 authentication."); | ||
1175 | |||
1176 | if (try_krb5_authentication(&context, &auth_context)) { | ||
1177 | type = packet_read(); | ||
1178 | if (type == SSH_SMSG_SUCCESS) | ||
1179 | goto success; | ||
1180 | if (type != SSH_SMSG_FAILURE) | ||
1181 | packet_disconnect("Protocol error: got %d in response to Kerberos v5 auth", type); | ||
1182 | } | ||
1183 | } | ||
1184 | #endif /* KRB5 */ | ||
1185 | |||
1186 | #ifdef KRB4 | ||
1187 | if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) && | ||
1188 | options.kerberos_authentication) { | ||
1189 | debug("Trying Kerberos v4 authentication."); | ||
1190 | |||
1191 | if (try_krb4_authentication()) { | ||
1192 | type = packet_read(); | ||
1193 | if (type == SSH_SMSG_SUCCESS) | ||
1194 | goto success; | ||
1195 | if (type != SSH_SMSG_FAILURE) | ||
1196 | packet_disconnect("Protocol error: got %d in response to Kerberos v4 auth", type); | ||
1197 | } | ||
1198 | } | ||
1199 | #endif /* KRB4 */ | ||
1200 | |||
1201 | /* | ||
1202 | * Use rhosts authentication if running in privileged socket and we | ||
1203 | * do not wish to remain anonymous. | ||
1204 | */ | ||
1205 | if ((supported_authentications & (1 << SSH_AUTH_RHOSTS)) && | ||
1206 | options.rhosts_authentication) { | ||
1207 | debug("Trying rhosts authentication."); | ||
1208 | packet_start(SSH_CMSG_AUTH_RHOSTS); | ||
1209 | packet_put_cstring(local_user); | ||
1210 | packet_send(); | ||
1211 | packet_write_wait(); | ||
1212 | |||
1213 | /* The server should respond with success or failure. */ | ||
1214 | type = packet_read(); | ||
1215 | if (type == SSH_SMSG_SUCCESS) | ||
1216 | goto success; | ||
1217 | if (type != SSH_SMSG_FAILURE) | ||
1218 | packet_disconnect("Protocol error: got %d in response to rhosts auth", | ||
1219 | type); | ||
1220 | } | ||
681 | /* | 1221 | /* |
682 | * Try .rhosts or /etc/hosts.equiv authentication with RSA host | 1222 | * Try .rhosts or /etc/hosts.equiv authentication with RSA host |
683 | * authentication. | 1223 | * authentication. |
@@ -731,5 +1271,36 @@ ssh_userauth1(const char *local_user, const char *server_user, char *host, | |||
731 | /* NOTREACHED */ | 1271 | /* NOTREACHED */ |
732 | 1272 | ||
733 | success: | 1273 | success: |
1274 | #ifdef KRB5 | ||
1275 | /* Try Kerberos v5 TGT passing. */ | ||
1276 | if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) && | ||
1277 | options.kerberos_tgt_passing && context && auth_context) { | ||
1278 | if (options.cipher == SSH_CIPHER_NONE) | ||
1279 | log("WARNING: Encryption is disabled! Ticket will be transmitted in the clear!"); | ||
1280 | send_krb5_tgt(context, auth_context); | ||
1281 | } | ||
1282 | if (auth_context) | ||
1283 | krb5_auth_con_free(context, auth_context); | ||
1284 | if (context) | ||
1285 | krb5_free_context(context); | ||
1286 | #endif | ||
1287 | |||
1288 | #ifdef AFS | ||
1289 | /* Try Kerberos v4 TGT passing if the server supports it. */ | ||
1290 | if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) && | ||
1291 | options.kerberos_tgt_passing) { | ||
1292 | if (options.cipher == SSH_CIPHER_NONE) | ||
1293 | log("WARNING: Encryption is disabled! Ticket will be transmitted in the clear!"); | ||
1294 | send_krb4_tgt(); | ||
1295 | } | ||
1296 | /* Try AFS token passing if the server supports it. */ | ||
1297 | if ((supported_authentications & (1 << SSH_PASS_AFS_TOKEN)) && | ||
1298 | options.afs_token_passing && k_hasafs()) { | ||
1299 | if (options.cipher == SSH_CIPHER_NONE) | ||
1300 | log("WARNING: Encryption is disabled! Token will be transmitted in the clear!"); | ||
1301 | send_afs_tokens(); | ||
1302 | } | ||
1303 | #endif /* AFS */ | ||
1304 | |||
734 | return; /* need statement after label */ | 1305 | return; /* need statement after label */ |
735 | } | 1306 | } |