summaryrefslogtreecommitdiff
path: root/sshconnect1.c
diff options
context:
space:
mode:
authorBen Lindstrom <mouring@eviladmin.org>2001-07-04 04:21:14 +0000
committerBen Lindstrom <mouring@eviladmin.org>2001-07-04 04:21:14 +0000
commitec95ed9b4ca014643a0272f6fa5b24ac9c70d263 (patch)
tree91a5c1b319337e52f7cc80742eda081f6dbfd6c2 /sshconnect1.c
parentb4c774cf8878d9100fde92ff4e938671c3b0301b (diff)
- dugsong@cvs.openbsd.org 2001/06/26 16:15:25
[auth1.c auth.h auth-krb4.c auth-passwd.c readconf.c readconf.h servconf.c servconf.h session.c sshconnect1.c sshd.c] Kerberos v5 support for SSH1, mostly from Assar Westerlund <assar@freebsd.org> and Bjorn Gronvall <bg@sics.se>. markus@ ok
Diffstat (limited to 'sshconnect1.c')
-rw-r--r--sshconnect1.c448
1 files changed, 340 insertions, 108 deletions
diff --git a/sshconnect1.c b/sshconnect1.c
index ec0a5c96c..09203d714 100644
--- a/sshconnect1.c
+++ b/sshconnect1.c
@@ -13,7 +13,7 @@
13 */ 13 */
14 14
15#include "includes.h" 15#include "includes.h"
16RCSID("$OpenBSD: sshconnect1.c,v 1.36 2001/06/23 22:37:46 markus Exp $"); 16RCSID("$OpenBSD: sshconnect1.c,v 1.37 2001/06/26 16:15:24 dugsong Exp $");
17 17
18#include <openssl/bn.h> 18#include <openssl/bn.h>
19#include <openssl/evp.h> 19#include <openssl/evp.h>
@@ -21,6 +21,9 @@ RCSID("$OpenBSD: sshconnect1.c,v 1.36 2001/06/23 22:37:46 markus Exp $");
21#ifdef KRB4 21#ifdef KRB4
22#include <krb.h> 22#include <krb.h>
23#endif 23#endif
24#ifdef KRB5
25#include <krb5.h>
26#endif
24#ifdef AFS 27#ifdef AFS
25#include <kafs.h> 28#include <kafs.h>
26#include "radix.h" 29#include "radix.h"
@@ -43,6 +46,7 @@ RCSID("$OpenBSD: sshconnect1.c,v 1.36 2001/06/23 22:37:46 markus Exp $");
43#include "readpass.h" 46#include "readpass.h"
44#include "cipher.h" 47#include "cipher.h"
45#include "canohost.h" 48#include "canohost.h"
49#include "auth.h"
46 50
47/* Session id for the current session. */ 51/* Session id for the current session. */
48u_char session_id[16]; 52u_char session_id[16];
@@ -379,7 +383,7 @@ try_rhosts_rsa_authentication(const char *local_user, Key * host_key)
379 383
380#ifdef KRB4 384#ifdef KRB4
381static int 385static int
382try_kerberos_authentication(void) 386try_krb4_authentication(void)
383{ 387{
384 KTEXT_ST auth; /* Kerberos data */ 388 KTEXT_ST auth; /* Kerberos data */
385 char *reply; 389 char *reply;
@@ -397,20 +401,21 @@ try_kerberos_authentication(void)
397 /* Don't do anything if we don't have any tickets. */ 401 /* Don't do anything if we don't have any tickets. */
398 if (stat(tkt_string(), &st) < 0) 402 if (stat(tkt_string(), &st) < 0)
399 return 0; 403 return 0;
400 404
401 strncpy(inst, (char *) krb_get_phost(get_canonical_hostname(1)), INST_SZ); 405 strlcpy(inst, (char *)krb_get_phost(get_canonical_hostname(1)),
402 406 INST_SZ);
403 realm = (char *) krb_realmofhost(get_canonical_hostname(1)); 407
408 realm = (char *)krb_realmofhost(get_canonical_hostname(1));
404 if (!realm) { 409 if (!realm) {
405 debug("Kerberos V4: no realm for %s", get_canonical_hostname(1)); 410 debug("Kerberos v4: no realm for %s", get_canonical_hostname(1));
406 return 0; 411 return 0;
407 } 412 }
408 /* This can really be anything. */ 413 /* This can really be anything. */
409 checksum = (u_long) getpid(); 414 checksum = (u_long)getpid();
410 415
411 r = krb_mk_req(&auth, KRB4_SERVICE_NAME, inst, realm, checksum); 416 r = krb_mk_req(&auth, KRB4_SERVICE_NAME, inst, realm, checksum);
412 if (r != KSUCCESS) { 417 if (r != KSUCCESS) {
413 debug("Kerberos V4 krb_mk_req failed: %s", krb_err_txt[r]); 418 debug("Kerberos v4 krb_mk_req failed: %s", krb_err_txt[r]);
414 return 0; 419 return 0;
415 } 420 }
416 /* Get session key to decrypt the server's reply with. */ 421 /* Get session key to decrypt the server's reply with. */
@@ -420,26 +425,26 @@ try_kerberos_authentication(void)
420 return 0; 425 return 0;
421 } 426 }
422 des_key_sched((des_cblock *) cred.session, schedule); 427 des_key_sched((des_cblock *) cred.session, schedule);
423 428
424 /* Send authentication info to server. */ 429 /* Send authentication info to server. */
425 packet_start(SSH_CMSG_AUTH_KERBEROS); 430 packet_start(SSH_CMSG_AUTH_KERBEROS);
426 packet_put_string((char *) auth.dat, auth.length); 431 packet_put_string((char *) auth.dat, auth.length);
427 packet_send(); 432 packet_send();
428 packet_write_wait(); 433 packet_write_wait();
429 434
430 /* Zero the buffer. */ 435 /* Zero the buffer. */
431 (void) memset(auth.dat, 0, MAX_KTXT_LEN); 436 (void) memset(auth.dat, 0, MAX_KTXT_LEN);
432 437
433 slen = sizeof(local); 438 slen = sizeof(local);
434 memset(&local, 0, sizeof(local)); 439 memset(&local, 0, sizeof(local));
435 if (getsockname(packet_get_connection_in(), 440 if (getsockname(packet_get_connection_in(),
436 (struct sockaddr *) & local, &slen) < 0) 441 (struct sockaddr *)&local, &slen) < 0)
437 debug("getsockname failed: %s", strerror(errno)); 442 debug("getsockname failed: %s", strerror(errno));
438 443
439 slen = sizeof(foreign); 444 slen = sizeof(foreign);
440 memset(&foreign, 0, sizeof(foreign)); 445 memset(&foreign, 0, sizeof(foreign));
441 if (getpeername(packet_get_connection_in(), 446 if (getpeername(packet_get_connection_in(),
442 (struct sockaddr *) & foreign, &slen) < 0) { 447 (struct sockaddr *)&foreign, &slen) < 0) {
443 debug("getpeername failed: %s", strerror(errno)); 448 debug("getpeername failed: %s", strerror(errno));
444 fatal_cleanup(); 449 fatal_cleanup();
445 } 450 }
@@ -448,96 +453,288 @@ try_kerberos_authentication(void)
448 switch (type) { 453 switch (type) {
449 case SSH_SMSG_FAILURE: 454 case SSH_SMSG_FAILURE:
450 /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */ 455 /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */
451 debug("Kerberos V4 authentication failed."); 456 debug("Kerberos v4 authentication failed.");
452 return 0; 457 return 0;
453 break; 458 break;
454 459
455 case SSH_SMSG_AUTH_KERBEROS_RESPONSE: 460 case SSH_SMSG_AUTH_KERBEROS_RESPONSE:
456 /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */ 461 /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */
457 debug("Kerberos V4 authentication accepted."); 462 debug("Kerberos v4 authentication accepted.");
458 463
459 /* Get server's response. */ 464 /* Get server's response. */
460 reply = packet_get_string((u_int *) &auth.length); 465 reply = packet_get_string((u_int *) &auth.length);
461 memcpy(auth.dat, reply, auth.length); 466 memcpy(auth.dat, reply, auth.length);
462 xfree(reply); 467 xfree(reply);
463 468
464 packet_integrity_check(plen, 4 + auth.length, type); 469 packet_integrity_check(plen, 4 + auth.length, type);
465 470
466 /* 471 /*
467 * If his response isn't properly encrypted with the session 472 * If his response isn't properly encrypted with the session
468 * key, and the decrypted checksum fails to match, he's 473 * key, and the decrypted checksum fails to match, he's
469 * bogus. Bail out. 474 * bogus. Bail out.
470 */ 475 */
471 r = krb_rd_priv(auth.dat, auth.length, schedule, &cred.session, 476 r = krb_rd_priv(auth.dat, auth.length, schedule, &cred.session,
472 &foreign, &local, &msg_data); 477 &foreign, &local, &msg_data);
473 if (r != KSUCCESS) { 478 if (r != KSUCCESS) {
474 debug("Kerberos V4 krb_rd_priv failed: %s", krb_err_txt[r]); 479 debug("Kerberos v4 krb_rd_priv failed: %s",
475 packet_disconnect("Kerberos V4 challenge failed!"); 480 krb_err_txt[r]);
481 packet_disconnect("Kerberos v4 challenge failed!");
476 } 482 }
477 /* Fetch the (incremented) checksum that we supplied in the request. */ 483 /* Fetch the (incremented) checksum that we supplied in the request. */
478 (void) memcpy((char *) &cksum, (char *) msg_data.app_data, sizeof(cksum)); 484 memcpy((char *)&cksum, (char *)msg_data.app_data,
485 sizeof(cksum));
479 cksum = ntohl(cksum); 486 cksum = ntohl(cksum);
480 487
481 /* If it matches, we're golden. */ 488 /* If it matches, we're golden. */
482 if (cksum == checksum + 1) { 489 if (cksum == checksum + 1) {
483 debug("Kerberos V4 challenge successful."); 490 debug("Kerberos v4 challenge successful.");
484 return 1; 491 return 1;
485 } else 492 } else
486 packet_disconnect("Kerberos V4 challenge failed!"); 493 packet_disconnect("Kerberos v4 challenge failed!");
487 break; 494 break;
488 495
489 default: 496 default:
490 packet_disconnect("Protocol error on Kerberos V4 response: %d", type); 497 packet_disconnect("Protocol error on Kerberos v4 response: %d", type);
491 } 498 }
492 return 0; 499 return 0;
493} 500}
494 501
495#endif /* KRB4 */ 502#endif /* KRB4 */
496 503
497#ifdef AFS 504#ifdef KRB5
498static int 505static int
499send_kerberos_tgt(void) 506try_krb5_authentication(krb5_context *context, krb5_auth_context *auth_context)
507{
508 krb5_error_code problem;
509 const char *tkfile;
510 struct stat buf;
511 krb5_ccache ccache = NULL;
512 const char *remotehost;
513 krb5_data ap;
514 int type, payload_len;
515 krb5_ap_rep_enc_part *reply = NULL;
516 int ret;
517
518 memset(&ap, 0, sizeof(ap));
519
520 problem = krb5_init_context(context);
521 if (problem) {
522 debug("Kerberos v5: krb5_init_context failed");
523 ret = 0;
524 goto out;
525 }
526
527 tkfile = krb5_cc_default_name(*context);
528 if (strncmp(tkfile, "FILE:", 5) == 0)
529 tkfile += 5;
530
531 if (stat(tkfile, &buf) == 0 && getuid() != buf.st_uid) {
532 debug("Kerberos v5: could not get default ccache (permission denied).");
533 ret = 0;
534 goto out;
535 }
536
537 problem = krb5_cc_default(*context, &ccache);
538 if (problem) {
539 debug("Kerberos v5: krb5_cc_default failed: %s",
540 krb5_get_err_text(*context, problem));
541 ret = 0;
542 goto out;
543 }
544
545 remotehost = get_canonical_hostname(1);
546
547 problem = krb5_mk_req(*context, auth_context, AP_OPTS_MUTUAL_REQUIRED,
548 "host", remotehost, NULL, ccache, &ap);
549 if (problem) {
550 debug("Kerberos v5: krb5_mk_req failed: %s",
551 krb5_get_err_text(*context, problem));
552 ret = 0;
553 goto out;
554 }
555
556 packet_start(SSH_CMSG_AUTH_KERBEROS);
557 packet_put_string((char *) ap.data, ap.length);
558 packet_send();
559 packet_write_wait();
560
561 xfree(ap.data);
562 ap.length = 0;
563
564 type = packet_read(&payload_len);
565 switch (type) {
566 case SSH_SMSG_FAILURE:
567 /* Should really be SSH_SMSG_AUTH_KERBEROS_FAILURE */
568 debug("Kerberos v5 authentication failed.");
569 ret = 0;
570 break;
571
572 case SSH_SMSG_AUTH_KERBEROS_RESPONSE:
573 /* SSH_SMSG_AUTH_KERBEROS_SUCCESS */
574 debug("Kerberos v5 authentication accepted.");
575
576 /* Get server's response. */
577 ap.data = packet_get_string((unsigned int *) &ap.length);
578
579 packet_integrity_check(payload_len, 4 + ap.length, type);
580 /* XXX je to dobre? */
581
582 problem = krb5_rd_rep(*context, *auth_context, &ap, &reply);
583 if (problem) {
584 ret = 0;
585 }
586 ret = 1;
587 break;
588
589 default:
590 packet_disconnect("Protocol error on Kerberos v5 response: %d",
591 type);
592 ret = 0;
593 break;
594
595 }
596
597 out:
598 if (ccache != NULL)
599 krb5_cc_close(*context, ccache);
600 if (reply != NULL)
601 krb5_free_ap_rep_enc_part(*context, reply);
602 if (ap.length > 0)
603 krb5_data_free(&ap);
604
605 return (ret);
606}
607
608static void
609send_krb5_tgt(krb5_context context, krb5_auth_context auth_context)
610{
611 int fd, type, payload_len;
612 krb5_error_code problem;
613 krb5_data outbuf;
614 krb5_ccache ccache = NULL;
615 krb5_creds creds;
616 krb5_kdc_flags flags;
617 const char *remotehost;
618
619 memset(&creds, 0, sizeof(creds));
620 memset(&outbuf, 0, sizeof(outbuf));
621
622 fd = packet_get_connection_in();
623
624 problem = krb5_auth_con_setaddrs_from_fd(context, auth_context, &fd);
625 if (problem)
626 goto out;
627
628 problem = krb5_cc_default(context, &ccache);
629 if (problem)
630 goto out;
631
632 problem = krb5_cc_get_principal(context, ccache, &creds.client);
633 if (problem)
634 goto out;
635
636 problem = krb5_build_principal(context, &creds.server,
637 strlen(creds.client->realm), creds.client->realm,
638 "krbtgt", creds.client->realm, NULL);
639 if (problem)
640 goto out;
641
642 creds.times.endtime = 0;
643
644 flags.i = 0;
645 flags.b.forwarded = 1;
646 flags.b.forwardable = krb5_config_get_bool(context, NULL,
647 "libdefaults", "forwardable", NULL);
648
649 remotehost = get_canonical_hostname(1);
650
651 problem = krb5_get_forwarded_creds(context, auth_context,
652 ccache, flags.i, remotehost, &creds, &outbuf);
653 if (problem)
654 goto out;
655
656 packet_start(SSH_CMSG_HAVE_KERBEROS_TGT);
657 packet_put_string((char *)outbuf.data, outbuf.length);
658 packet_send();
659 packet_write_wait();
660
661 type = packet_read(&payload_len);
662
663 if (type == SSH_SMSG_SUCCESS) {
664 char *pname;
665
666 krb5_unparse_name(context, creds.client, &pname);
667 debug("Kerberos v5 TGT forwarded (%s).", pname);
668 xfree(pname);
669 } else
670 debug("Kerberos v5 TGT forwarding failed.");
671
672 return;
673
674 out:
675 if (problem)
676 debug("Kerberos v5 TGT forwarding failed: %s",
677 krb5_get_err_text(context, problem));
678 if (creds.client)
679 krb5_free_principal(context, creds.client);
680 if (creds.server)
681 krb5_free_principal(context, creds.server);
682 if (ccache)
683 krb5_cc_close(context, ccache);
684 if (outbuf.data)
685 xfree(outbuf.data);
686}
687#endif /* KRB5 */
688
689#ifdef AFS
690static void
691send_krb4_tgt(void)
500{ 692{
501 CREDENTIALS *creds; 693 CREDENTIALS *creds;
502 char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
503 int r, type, plen;
504 char buffer[8192];
505 struct stat st; 694 struct stat st;
506 695 char buffer[4096], pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ];
696 int problem, type, len;
697
507 /* Don't do anything if we don't have any tickets. */ 698 /* Don't do anything if we don't have any tickets. */
508 if (stat(tkt_string(), &st) < 0) 699 if (stat(tkt_string(), &st) < 0)
509 return 0; 700 return;
510 701
511 creds = xmalloc(sizeof(*creds)); 702 creds = xmalloc(sizeof(*creds));
512 703
513 if ((r = krb_get_tf_fullname(TKT_FILE, pname, pinst, prealm)) != KSUCCESS) { 704 problem = krb_get_tf_fullname(TKT_FILE, pname, pinst, prealm);
514 debug("Kerberos V4 tf_fullname failed: %s", krb_err_txt[r]); 705 if (problem)
515 return 0; 706 goto out;
516 } 707
517 if ((r = krb_get_cred("krbtgt", prealm, prealm, creds)) != GC_OK) { 708 problem = krb_get_cred("krbtgt", prealm, prealm, creds);
518 debug("Kerberos V4 get_cred failed: %s", krb_err_txt[r]); 709 if (problem)
519 return 0; 710 goto out;
520 } 711
521 if (time(0) > krb_life_to_time(creds->issue_date, creds->lifetime)) { 712 if (time(0) > krb_life_to_time(creds->issue_date, creds->lifetime)) {
522 debug("Kerberos V4 ticket expired: %s", TKT_FILE); 713 problem = RD_AP_EXP;
523 return 0; 714 goto out;
524 } 715 }
525 creds_to_radix(creds, (u_char *)buffer, sizeof buffer); 716 creds_to_radix(creds, (u_char *)buffer, sizeof(buffer));
526 xfree(creds); 717
527
528 packet_start(SSH_CMSG_HAVE_KERBEROS_TGT); 718 packet_start(SSH_CMSG_HAVE_KERBEROS_TGT);
529 packet_put_cstring(buffer); 719 packet_put_cstring(buffer);
530 packet_send(); 720 packet_send();
531 packet_write_wait(); 721 packet_write_wait();
532 722
533 type = packet_read(&plen); 723 type = packet_read(&len);
534 724
535 if (type == SSH_SMSG_FAILURE) 725 if (type == SSH_SMSG_SUCCESS)
536 debug("Kerberos TGT for realm %s rejected.", prealm); 726 debug("Kerberos v4 TGT forwarded (%s%s%s@%s).",
537 else if (type != SSH_SMSG_SUCCESS) 727 creds->pname, creds->pinst[0] ? "." : "",
538 packet_disconnect("Protocol error on Kerberos TGT response: %d", type); 728 creds->pinst, creds->realm);
539 729 else
540 return 1; 730 debug("Kerberos v4 TGT rejected.");
731
732 xfree(creds);
733 return;
734
735 out:
736 debug("Kerberos v4 TGT passing failed: %s", krb_err_txt[problem]);
737 xfree(creds);
541} 738}
542 739
543static void 740static void
@@ -546,10 +743,10 @@ send_afs_tokens(void)
546 CREDENTIALS creds; 743 CREDENTIALS creds;
547 struct ViceIoctl parms; 744 struct ViceIoctl parms;
548 struct ClearToken ct; 745 struct ClearToken ct;
549 int i, type, len, plen; 746 int i, type, len;
550 char buf[2048], *p, *server_cell; 747 char buf[2048], *p, *server_cell;
551 char buffer[8192]; 748 char buffer[8192];
552 749
553 /* Move over ktc_GetToken, here's something leaner. */ 750 /* Move over ktc_GetToken, here's something leaner. */
554 for (i = 0; i < 100; i++) { /* just in case */ 751 for (i = 0; i < 100; i++) { /* just in case */
555 parms.in = (char *) &i; 752 parms.in = (char *) &i;
@@ -559,7 +756,7 @@ send_afs_tokens(void)
559 if (k_pioctl(0, VIOCGETTOK, &parms, 0) != 0) 756 if (k_pioctl(0, VIOCGETTOK, &parms, 0) != 0)
560 break; 757 break;
561 p = buf; 758 p = buf;
562 759
563 /* Get secret token. */ 760 /* Get secret token. */
564 memcpy(&creds.ticket_st.length, p, sizeof(u_int)); 761 memcpy(&creds.ticket_st.length, p, sizeof(u_int));
565 if (creds.ticket_st.length > MAX_KTXT_LEN) 762 if (creds.ticket_st.length > MAX_KTXT_LEN)
@@ -567,7 +764,7 @@ send_afs_tokens(void)
567 p += sizeof(u_int); 764 p += sizeof(u_int);
568 memcpy(creds.ticket_st.dat, p, creds.ticket_st.length); 765 memcpy(creds.ticket_st.dat, p, creds.ticket_st.length);
569 p += creds.ticket_st.length; 766 p += creds.ticket_st.length;
570 767
571 /* Get clear token. */ 768 /* Get clear token. */
572 memcpy(&len, p, sizeof(len)); 769 memcpy(&len, p, sizeof(len));
573 if (len != sizeof(struct ClearToken)) 770 if (len != sizeof(struct ClearToken))
@@ -577,20 +774,22 @@ send_afs_tokens(void)
577 p += len; 774 p += len;
578 p += sizeof(len); /* primary flag */ 775 p += sizeof(len); /* primary flag */
579 server_cell = p; 776 server_cell = p;
580 777
581 /* Flesh out our credentials. */ 778 /* Flesh out our credentials. */
582 strlcpy(creds.service, "afs", sizeof creds.service); 779 strlcpy(creds.service, "afs", sizeof(creds.service));
583 creds.instance[0] = '\0'; 780 creds.instance[0] = '\0';
584 strlcpy(creds.realm, server_cell, REALM_SZ); 781 strlcpy(creds.realm, server_cell, REALM_SZ);
585 memcpy(creds.session, ct.HandShakeKey, DES_KEY_SZ); 782 memcpy(creds.session, ct.HandShakeKey, DES_KEY_SZ);
586 creds.issue_date = ct.BeginTimestamp; 783 creds.issue_date = ct.BeginTimestamp;
587 creds.lifetime = krb_time_to_life(creds.issue_date, ct.EndTimestamp); 784 creds.lifetime = krb_time_to_life(creds.issue_date,
785 ct.EndTimestamp);
588 creds.kvno = ct.AuthHandle; 786 creds.kvno = ct.AuthHandle;
589 snprintf(creds.pname, sizeof(creds.pname), "AFS ID %d", ct.ViceId); 787 snprintf(creds.pname, sizeof(creds.pname), "AFS ID %d", ct.ViceId);
590 creds.pinst[0] = '\0'; 788 creds.pinst[0] = '\0';
591 789
592 /* Encode token, ship it off. */ 790 /* Encode token, ship it off. */
593 if (creds_to_radix(&creds, (u_char *) buffer, sizeof buffer) <= 0) 791 if (creds_to_radix(&creds, (u_char *)buffer,
792 sizeof(buffer)) <= 0)
594 break; 793 break;
595 packet_start(SSH_CMSG_HAVE_AFS_TOKEN); 794 packet_start(SSH_CMSG_HAVE_AFS_TOKEN);
596 packet_put_cstring(buffer); 795 packet_put_cstring(buffer);
@@ -599,8 +798,8 @@ send_afs_tokens(void)
599 798
600 /* Roger, Roger. Clearance, Clarence. What's your vector, 799 /* Roger, Roger. Clearance, Clarence. What's your vector,
601 Victor? */ 800 Victor? */
602 type = packet_read(&plen); 801 type = packet_read(&len);
603 802
604 if (type == SSH_SMSG_FAILURE) 803 if (type == SSH_SMSG_FAILURE)
605 debug("AFS token for cell %s rejected.", server_cell); 804 debug("AFS token for cell %s rejected.", server_cell);
606 else if (type != SSH_SMSG_SUCCESS) 805 else if (type != SSH_SMSG_SUCCESS)
@@ -622,9 +821,9 @@ try_challenge_response_authentication(void)
622 u_int clen; 821 u_int clen;
623 char prompt[1024]; 822 char prompt[1024];
624 char *challenge, *response; 823 char *challenge, *response;
625 824
626 debug("Doing challenge reponse authentication."); 825 debug("Doing challenge reponse authentication.");
627 826
628 for (i = 0; i < options.number_of_password_prompts; i++) { 827 for (i = 0; i < options.number_of_password_prompts; i++) {
629 /* request a challenge */ 828 /* request a challenge */
630 packet_start(SSH_CMSG_AUTH_TIS); 829 packet_start(SSH_CMSG_AUTH_TIS);
@@ -913,9 +1112,13 @@ void
913ssh_userauth1(const char *local_user, const char *server_user, char *host, 1112ssh_userauth1(const char *local_user, const char *server_user, char *host,
914 Key **keys, int nkeys) 1113 Key **keys, int nkeys)
915{ 1114{
1115#ifdef KRB5
1116 krb5_context context = NULL;
1117 krb5_auth_context auth_context = NULL;
1118#endif
916 int i, type; 1119 int i, type;
917 int payload_len; 1120 int payload_len;
918 1121
919 if (supported_authentications == 0) 1122 if (supported_authentications == 0)
920 fatal("ssh_userauth1: server supports no auth methods"); 1123 fatal("ssh_userauth1: server supports no auth methods");
921 1124
@@ -934,43 +1137,40 @@ ssh_userauth1(const char *local_user, const char *server_user, char *host,
934 1137
935 /* check whether the connection was accepted without authentication. */ 1138 /* check whether the connection was accepted without authentication. */
936 if (type == SSH_SMSG_SUCCESS) 1139 if (type == SSH_SMSG_SUCCESS)
937 return; 1140 goto success;
938 if (type != SSH_SMSG_FAILURE) 1141 if (type != SSH_SMSG_FAILURE)
939 packet_disconnect("Protocol error: got %d in response to SSH_CMSG_USER", 1142 packet_disconnect("Protocol error: got %d in response to SSH_CMSG_USER", type);
940 type); 1143
941 1144#ifdef KRB5
942#ifdef AFS 1145 if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) &&
943 /* Try Kerberos tgt passing if the server supports it. */ 1146 options.kerberos_authentication) {
944 if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) && 1147 debug("Trying Kerberos v5 authentication.");
945 options.kerberos_tgt_passing) { 1148
946 if (options.cipher == SSH_CIPHER_NONE) 1149 if (try_krb5_authentication(&context, &auth_context)) {
947 log("WARNING: Encryption is disabled! Ticket will be transmitted in the clear!"); 1150 type = packet_read(&payload_len);
948 (void) send_kerberos_tgt(); 1151 if (type == SSH_SMSG_SUCCESS)
949 } 1152 goto success;
950 /* Try AFS token passing if the server supports it. */ 1153 if (type != SSH_SMSG_FAILURE)
951 if ((supported_authentications & (1 << SSH_PASS_AFS_TOKEN)) && 1154 packet_disconnect("Protocol error: got %d in response to Kerberos v5 auth", type);
952 options.afs_token_passing && k_hasafs()) { 1155 }
953 if (options.cipher == SSH_CIPHER_NONE)
954 log("WARNING: Encryption is disabled! Token will be transmitted in the clear!");
955 send_afs_tokens();
956 } 1156 }
957#endif /* AFS */ 1157#endif /* KRB5 */
958 1158
959#ifdef KRB4 1159#ifdef KRB4
960 if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) && 1160 if ((supported_authentications & (1 << SSH_AUTH_KERBEROS)) &&
961 options.kerberos_authentication) { 1161 options.kerberos_authentication) {
962 debug("Trying Kerberos authentication."); 1162 debug("Trying Kerberos v4 authentication.");
963 if (try_kerberos_authentication()) { 1163
964 /* The server should respond with success or failure. */ 1164 if (try_krb4_authentication()) {
965 type = packet_read(&payload_len); 1165 type = packet_read(&payload_len);
966 if (type == SSH_SMSG_SUCCESS) 1166 if (type == SSH_SMSG_SUCCESS)
967 return; 1167 goto success;
968 if (type != SSH_SMSG_FAILURE) 1168 if (type != SSH_SMSG_FAILURE)
969 packet_disconnect("Protocol error: got %d in response to Kerberos auth", type); 1169 packet_disconnect("Protocol error: got %d in response to Kerberos v4 auth", type);
970 } 1170 }
971 } 1171 }
972#endif /* KRB4 */ 1172#endif /* KRB4 */
973 1173
974 /* 1174 /*
975 * Use rhosts authentication if running in privileged socket and we 1175 * Use rhosts authentication if running in privileged socket and we
976 * do not wish to remain anonymous. 1176 * do not wish to remain anonymous.
@@ -986,7 +1186,7 @@ ssh_userauth1(const char *local_user, const char *server_user, char *host,
986 /* The server should respond with success or failure. */ 1186 /* The server should respond with success or failure. */
987 type = packet_read(&payload_len); 1187 type = packet_read(&payload_len);
988 if (type == SSH_SMSG_SUCCESS) 1188 if (type == SSH_SMSG_SUCCESS)
989 return; 1189 goto success;
990 if (type != SSH_SMSG_FAILURE) 1190 if (type != SSH_SMSG_FAILURE)
991 packet_disconnect("Protocol error: got %d in response to rhosts auth", 1191 packet_disconnect("Protocol error: got %d in response to rhosts auth",
992 type); 1192 type);
@@ -1000,7 +1200,7 @@ ssh_userauth1(const char *local_user, const char *server_user, char *host,
1000 for (i = 0; i < nkeys; i++) { 1200 for (i = 0; i < nkeys; i++) {
1001 if (keys[i] != NULL && keys[i]->type == KEY_RSA1 && 1201 if (keys[i] != NULL && keys[i]->type == KEY_RSA1 &&
1002 try_rhosts_rsa_authentication(local_user, keys[i])) 1202 try_rhosts_rsa_authentication(local_user, keys[i]))
1003 return; 1203 goto success;
1004 } 1204 }
1005 } 1205 }
1006 /* Try RSA authentication if the server supports it. */ 1206 /* Try RSA authentication if the server supports it. */
@@ -1012,20 +1212,20 @@ ssh_userauth1(const char *local_user, const char *server_user, char *host,
1012 * it, whereas identity files may require passphrases. 1212 * it, whereas identity files may require passphrases.
1013 */ 1213 */
1014 if (try_agent_authentication()) 1214 if (try_agent_authentication())
1015 return; 1215 goto success;
1016 1216
1017 /* Try RSA authentication for each identity. */ 1217 /* Try RSA authentication for each identity. */
1018 for (i = 0; i < options.num_identity_files; i++) 1218 for (i = 0; i < options.num_identity_files; i++)
1019 if (options.identity_keys[i] != NULL && 1219 if (options.identity_keys[i] != NULL &&
1020 options.identity_keys[i]->type == KEY_RSA1 && 1220 options.identity_keys[i]->type == KEY_RSA1 &&
1021 try_rsa_authentication(options.identity_files[i])) 1221 try_rsa_authentication(options.identity_files[i]))
1022 return; 1222 goto success;
1023 } 1223 }
1024 /* Try challenge response authentication if the server supports it. */ 1224 /* Try challenge response authentication if the server supports it. */
1025 if ((supported_authentications & (1 << SSH_AUTH_TIS)) && 1225 if ((supported_authentications & (1 << SSH_AUTH_TIS)) &&
1026 options.challenge_response_authentication && !options.batch_mode) { 1226 options.challenge_response_authentication && !options.batch_mode) {
1027 if (try_challenge_response_authentication()) 1227 if (try_challenge_response_authentication())
1028 return; 1228 goto success;
1029 } 1229 }
1030 /* Try password authentication if the server supports it. */ 1230 /* Try password authentication if the server supports it. */
1031 if ((supported_authentications & (1 << SSH_AUTH_PASSWORD)) && 1231 if ((supported_authentications & (1 << SSH_AUTH_PASSWORD)) &&
@@ -1035,9 +1235,41 @@ ssh_userauth1(const char *local_user, const char *server_user, char *host,
1035 snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ", 1235 snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ",
1036 server_user, host); 1236 server_user, host);
1037 if (try_password_authentication(prompt)) 1237 if (try_password_authentication(prompt))
1038 return; 1238 goto success;
1039 } 1239 }
1040 /* All authentication methods have failed. Exit with an error message. */ 1240 /* All authentication methods have failed. Exit with an error message. */
1041 fatal("Permission denied."); 1241 fatal("Permission denied.");
1042 /* NOTREACHED */ 1242 /* NOTREACHED */
1243
1244 success:
1245#ifdef KRB5
1246 /* Try Kerberos v5 TGT passing. */
1247 if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) &&
1248 options.kerberos_tgt_passing && context && auth_context) {
1249 if (options.cipher == SSH_CIPHER_NONE)
1250 log("WARNING: Encryption is disabled! Ticket will be transmitted in the clear!");
1251 send_krb5_tgt(context, auth_context);
1252 }
1253 if (auth_context)
1254 krb5_auth_con_free(context, auth_context);
1255 if (context)
1256 krb5_free_context(context);
1257#endif
1258
1259#ifdef AFS
1260 /* Try Kerberos v4 TGT passing if the server supports it. */
1261 if ((supported_authentications & (1 << SSH_PASS_KERBEROS_TGT)) &&
1262 options.kerberos_tgt_passing) {
1263 if (options.cipher == SSH_CIPHER_NONE)
1264 log("WARNING: Encryption is disabled! Ticket will be transmitted in the clear!");
1265 send_krb4_tgt();
1266 }
1267 /* Try AFS token passing if the server supports it. */
1268 if ((supported_authentications & (1 << SSH_PASS_AFS_TOKEN)) &&
1269 options.afs_token_passing && k_hasafs()) {
1270 if (options.cipher == SSH_CIPHER_NONE)
1271 log("WARNING: Encryption is disabled! Token will be transmitted in the clear!");
1272 send_afs_tokens();
1273 }
1274#endif /* AFS */
1043} 1275}