summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Lindstrom <mouring@eviladmin.org>2001-03-09 00:12:22 +0000
committerBen Lindstrom <mouring@eviladmin.org>2001-03-09 00:12:22 +0000
commit266dfdfd62d169c62618d73cd72df0391c072be1 (patch)
tree3a51150147ab8fbc365f4d285b3046202bb1a2fc
parent283cb821cda4e05b33a1e87854db276757e9fdf8 (diff)
- markus@cvs.openbsd.org 2001/03/08 21:42:33
[compat.c compat.h readconf.h ssh.c sshconnect1.c sshconnect2.c] implement client side of SSH2_MSG_USERAUTH_PK_OK (test public key -> no need to do enter passphrase or do expensive sign operations if the server does not accept key).
-rw-r--r--ChangeLog7
-rw-r--r--compat.c7
-rw-r--r--compat.h3
-rw-r--r--readconf.h6
-rw-r--r--ssh.c46
-rw-r--r--sshconnect1.c5
-rw-r--r--sshconnect2.c272
7 files changed, 269 insertions, 77 deletions
diff --git a/ChangeLog b/ChangeLog
index e153b899d..f7e526980 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,6 +6,11 @@
6 - stevesk@cvs.openbsd.org 2001/03/08 20:44:48 6 - stevesk@cvs.openbsd.org 2001/03/08 20:44:48
7 [sftp.1] 7 [sftp.1]
8 spelling, cleanup; ok deraadt@ 8 spelling, cleanup; ok deraadt@
9 - markus@cvs.openbsd.org 2001/03/08 21:42:33
10 [compat.c compat.h readconf.h ssh.c sshconnect1.c sshconnect2.c]
11 implement client side of SSH2_MSG_USERAUTH_PK_OK (test public key ->
12 no need to do enter passphrase or do expensive sign operations if the
13 server does not accept key).
9 14
1020010308 1520010308
11 - OpenBSD CVS Sync 16 - OpenBSD CVS Sync
@@ -4452,4 +4457,4 @@
4452 - Wrote replacements for strlcpy and mkdtemp 4457 - Wrote replacements for strlcpy and mkdtemp
4453 - Released 1.0pre1 4458 - Released 1.0pre1
4454 4459
4455$Id: ChangeLog,v 1.929 2001/03/09 00:09:02 mouring Exp $ 4460$Id: ChangeLog,v 1.930 2001/03/09 00:12:22 mouring Exp $
diff --git a/compat.c b/compat.c
index da1f623bc..38fc52605 100644
--- a/compat.c
+++ b/compat.c
@@ -23,7 +23,7 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: compat.c,v 1.36 2001/02/27 11:00:11 markus Exp $"); 26RCSID("$OpenBSD: compat.c,v 1.37 2001/03/08 21:42:31 markus Exp $");
27 27
28#ifdef HAVE_LIBPCRE 28#ifdef HAVE_LIBPCRE
29# include <pcreposix.h> 29# include <pcreposix.h>
@@ -78,11 +78,12 @@ compat_datafellows(const char *version)
78 SSH_OLD_SESSIONID|SSH_BUG_DEBUG }, 78 SSH_OLD_SESSIONID|SSH_BUG_DEBUG },
79 { "^2\\.0\\.1[3-9]", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 79 { "^2\\.0\\.1[3-9]", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
80 SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 80 SSH_OLD_SESSIONID|SSH_BUG_DEBUG|
81 SSH_BUG_PKSERVICE|SSH_BUG_X11FWD }, 81 SSH_BUG_PKSERVICE|SSH_BUG_X11FWD|
82 SSH_BUG_PKOK },
82 { "^2\\.0\\.", SSH_BUG_SIGBLOB|SSH_BUG_HMAC| 83 { "^2\\.0\\.", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
83 SSH_OLD_SESSIONID|SSH_BUG_DEBUG| 84 SSH_OLD_SESSIONID|SSH_BUG_DEBUG|
84 SSH_BUG_PKSERVICE|SSH_BUG_X11FWD| 85 SSH_BUG_PKSERVICE|SSH_BUG_X11FWD|
85 SSH_BUG_PKAUTH }, 86 SSH_BUG_PKAUTH|SSH_BUG_PKOK },
86 { "^2\\.[23]\\.0", SSH_BUG_HMAC}, 87 { "^2\\.[23]\\.0", SSH_BUG_HMAC},
87 { "^2\\.[2-9]\\.", 0 }, 88 { "^2\\.[2-9]\\.", 0 },
88 { "^2\\.4$", SSH_OLD_SESSIONID}, /* Van Dyke */ 89 { "^2\\.4$", SSH_OLD_SESSIONID}, /* Van Dyke */
diff --git a/compat.h b/compat.h
index 2726fafff..9359d4b79 100644
--- a/compat.h
+++ b/compat.h
@@ -21,7 +21,7 @@
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */ 23 */
24/* RCSID("$OpenBSD: compat.h,v 1.15 2001/02/19 09:53:31 markus Exp $"); */ 24/* RCSID("$OpenBSD: compat.h,v 1.16 2001/03/08 21:42:32 markus Exp $"); */
25 25
26#ifndef COMPAT_H 26#ifndef COMPAT_H
27#define COMPAT_H 27#define COMPAT_H
@@ -40,6 +40,7 @@
40#define SSH_BUG_DEBUG 0x0040 40#define SSH_BUG_DEBUG 0x0040
41#define SSH_BUG_BANNER 0x0080 41#define SSH_BUG_BANNER 0x0080
42#define SSH_BUG_IGNOREMSG 0x0100 42#define SSH_BUG_IGNOREMSG 0x0100
43#define SSH_BUG_PKOK 0x0200
43 44
44void enable_compat13(void); 45void enable_compat13(void);
45void enable_compat20(void); 46void enable_compat20(void);
diff --git a/readconf.h b/readconf.h
index 575b2646d..97615620e 100644
--- a/readconf.h
+++ b/readconf.h
@@ -11,11 +11,13 @@
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: readconf.h,v 1.26 2001/02/11 12:59:25 markus Exp $"); */ 14/* RCSID("$OpenBSD: readconf.h,v 1.27 2001/03/08 21:42:32 markus Exp $"); */
15 15
16#ifndef READCONF_H 16#ifndef READCONF_H
17#define READCONF_H 17#define READCONF_H
18 18
19#include "key.h"
20
19/* Data structure for representing a forwarding request. */ 21/* Data structure for representing a forwarding request. */
20 22
21typedef struct { 23typedef struct {
@@ -83,7 +85,7 @@ typedef struct {
83 85
84 int num_identity_files; /* Number of files for RSA/DSA identities. */ 86 int num_identity_files; /* Number of files for RSA/DSA identities. */
85 char *identity_files[SSH_MAX_IDENTITY_FILES]; 87 char *identity_files[SSH_MAX_IDENTITY_FILES];
86 int identity_files_type[SSH_MAX_IDENTITY_FILES]; 88 Key *identity_keys[SSH_MAX_IDENTITY_FILES];
87 89
88 /* Local TCP/IP forward requests. */ 90 /* Local TCP/IP forward requests. */
89 int num_local_forwards; 91 int num_local_forwards;
diff --git a/ssh.c b/ssh.c
index 631900f15..74a2b75ac 100644
--- a/ssh.c
+++ b/ssh.c
@@ -39,7 +39,7 @@
39 */ 39 */
40 40
41#include "includes.h" 41#include "includes.h"
42RCSID("$OpenBSD: ssh.c,v 1.103 2001/03/04 17:42:28 millert Exp $"); 42RCSID("$OpenBSD: ssh.c,v 1.104 2001/03/08 21:42:32 markus Exp $");
43 43
44#include <openssl/evp.h> 44#include <openssl/evp.h>
45#include <openssl/err.h> 45#include <openssl/err.h>
@@ -233,7 +233,7 @@ rsh_connect(char *host, char *user, Buffer * command)
233 233
234int ssh_session(void); 234int ssh_session(void);
235int ssh_session2(void); 235int ssh_session2(void);
236int guess_identity_file_type(const char *filename); 236void load_public_identity_files(void);
237 237
238/* 238/*
239 * Main program for the ssh client. 239 * Main program for the ssh client.
@@ -678,15 +678,11 @@ main(int ac, char **av)
678 } 678 }
679 exit(1); 679 exit(1);
680 } 680 }
681 /* Expand ~ in options.identity_files, known host file names. */ 681 /* load options.identity_files */
682 /* XXX mem-leaks */ 682 load_public_identity_files();
683 for (i = 0; i < options.num_identity_files; i++) { 683
684 options.identity_files[i] = 684 /* Expand ~ in known host file names. */
685 tilde_expand_filename(options.identity_files[i], original_real_uid); 685 /* XXX mem-leaks: */
686 options.identity_files_type[i] = guess_identity_file_type(options.identity_files[i]);
687 debug("identity file %s type %d", options.identity_files[i],
688 options.identity_files_type[i]);
689 }
690 options.system_hostfile = 686 options.system_hostfile =
691 tilde_expand_filename(options.system_hostfile, original_real_uid); 687 tilde_expand_filename(options.system_hostfile, original_real_uid);
692 options.user_hostfile = 688 options.user_hostfile =
@@ -1095,3 +1091,31 @@ guess_identity_file_type(const char *filename)
1095 key_free(public); 1091 key_free(public);
1096 return type; 1092 return type;
1097} 1093}
1094
1095void
1096load_public_identity_files(void)
1097{
1098 char *filename;
1099 Key *public;
1100 int i;
1101
1102 for (i = 0; i < options.num_identity_files; i++) {
1103 filename = tilde_expand_filename(options.identity_files[i],
1104 original_real_uid);
1105 public = key_new(KEY_RSA1);
1106 if (!load_public_key(filename, public, NULL)) {
1107 key_free(public);
1108 public = key_new(KEY_UNSPEC);
1109 if (!try_load_public_key(filename, public, NULL)) {
1110 debug("unknown identity file %s", filename);
1111 key_free(public);
1112 public = NULL;
1113 }
1114 }
1115 debug("identity file %s type %d", filename,
1116 public ? public->type : -1);
1117 xfree(options.identity_files[i]);
1118 options.identity_files[i] = filename;
1119 options.identity_keys[i] = public;
1120 }
1121}
diff --git a/sshconnect1.c b/sshconnect1.c
index c5ff7213a..3d45ac5a2 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.27 2001/02/15 23:19:59 markus Exp $"); 16RCSID("$OpenBSD: sshconnect1.c,v 1.28 2001/03/08 21:42:33 markus Exp $");
17 17
18#include <openssl/bn.h> 18#include <openssl/bn.h>
19#include <openssl/evp.h> 19#include <openssl/evp.h>
@@ -1017,7 +1017,8 @@ ssh_userauth(
1017 1017
1018 /* Try RSA authentication for each identity. */ 1018 /* Try RSA authentication for each identity. */
1019 for (i = 0; i < options.num_identity_files; i++) 1019 for (i = 0; i < options.num_identity_files; i++)
1020 if (options.identity_files_type[i] == KEY_RSA1 && 1020 if (options.identity_keys[i] != NULL &&
1021 options.identity_keys[i]->type == KEY_RSA1 &&
1021 try_rsa_authentication(options.identity_files[i])) 1022 try_rsa_authentication(options.identity_files[i]))
1022 return; 1023 return;
1023 } 1024 }
diff --git a/sshconnect2.c b/sshconnect2.c
index 0baecf0a5..81e1aef93 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -23,7 +23,7 @@
23 */ 23 */
24 24
25#include "includes.h" 25#include "includes.h"
26RCSID("$OpenBSD: sshconnect2.c,v 1.50 2001/03/05 17:17:21 markus Exp $"); 26RCSID("$OpenBSD: sshconnect2.c,v 1.51 2001/03/08 21:42:33 markus Exp $");
27 27
28#include <openssl/bn.h> 28#include <openssl/bn.h>
29#include <openssl/md5.h> 29#include <openssl/md5.h>
@@ -467,6 +467,10 @@ struct Authctxt {
467 AuthenticationConnection *agent; 467 AuthenticationConnection *agent;
468 Authmethod *method; 468 Authmethod *method;
469 int success; 469 int success;
470 char *authlist;
471 Key *last_key;
472 sign_cb_fn *last_key_sign;
473 int last_key_hint;
470}; 474};
471struct Authmethod { 475struct Authmethod {
472 char *name; /* string to compare against server's list */ 476 char *name; /* string to compare against server's list */
@@ -480,12 +484,20 @@ void input_userauth_failure(int type, int plen, void *ctxt);
480void input_userauth_banner(int type, int plen, void *ctxt); 484void input_userauth_banner(int type, int plen, void *ctxt);
481void input_userauth_error(int type, int plen, void *ctxt); 485void input_userauth_error(int type, int plen, void *ctxt);
482void input_userauth_info_req(int type, int plen, void *ctxt); 486void input_userauth_info_req(int type, int plen, void *ctxt);
487void input_userauth_pk_ok(int type, int plen, void *ctxt);
483 488
484int userauth_none(Authctxt *authctxt); 489int userauth_none(Authctxt *authctxt);
485int userauth_pubkey(Authctxt *authctxt); 490int userauth_pubkey(Authctxt *authctxt);
486int userauth_passwd(Authctxt *authctxt); 491int userauth_passwd(Authctxt *authctxt);
487int userauth_kbdint(Authctxt *authctxt); 492int userauth_kbdint(Authctxt *authctxt);
488 493
494void userauth(Authctxt *authctxt, char *authlist);
495
496int
497sign_and_send_pubkey(Authctxt *authctxt, Key *k,
498 sign_cb_fn *sign_callback);
499void clear_auth_state(Authctxt *authctxt);
500
489void authmethod_clear(void); 501void authmethod_clear(void);
490Authmethod *authmethod_get(char *authlist); 502Authmethod *authmethod_get(char *authlist);
491Authmethod *authmethod_lookup(const char *name); 503Authmethod *authmethod_lookup(const char *name);
@@ -546,6 +558,7 @@ ssh_userauth2(const char *server_user, char *host)
546 authctxt.service = "ssh-connection"; /* service name */ 558 authctxt.service = "ssh-connection"; /* service name */
547 authctxt.success = 0; 559 authctxt.success = 0;
548 authctxt.method = authmethod_lookup("none"); 560 authctxt.method = authmethod_lookup("none");
561 authctxt.authlist = NULL;
549 if (authctxt.method == NULL) 562 if (authctxt.method == NULL)
550 fatal("ssh_userauth2: internal error: cannot send userauth none request"); 563 fatal("ssh_userauth2: internal error: cannot send userauth none request");
551 authmethod_clear(); 564 authmethod_clear();
@@ -565,6 +578,30 @@ ssh_userauth2(const char *server_user, char *host)
565 debug("ssh-userauth2 successful: method %s", authctxt.method->name); 578 debug("ssh-userauth2 successful: method %s", authctxt.method->name);
566} 579}
567void 580void
581userauth(Authctxt *authctxt, char *authlist)
582{
583 if (authlist == NULL) {
584 authlist = authctxt->authlist;
585 } else {
586 if (authctxt->authlist)
587 xfree(authctxt->authlist);
588 authctxt->authlist = authlist;
589 }
590 for (;;) {
591 Authmethod *method = authmethod_get(authlist);
592 if (method == NULL)
593 fatal("Permission denied (%s).", authlist);
594 authctxt->method = method;
595 if (method->userauth(authctxt) != 0) {
596 debug2("we sent a %s packet, wait for reply", method->name);
597 break;
598 } else {
599 debug2("we did not send a packet, disable method");
600 method->enabled = NULL;
601 }
602 }
603}
604void
568input_userauth_error(int type, int plen, void *ctxt) 605input_userauth_error(int type, int plen, void *ctxt)
569{ 606{
570 fatal("input_userauth_error: bad message during authentication: " 607 fatal("input_userauth_error: bad message during authentication: "
@@ -587,12 +624,14 @@ input_userauth_success(int type, int plen, void *ctxt)
587 Authctxt *authctxt = ctxt; 624 Authctxt *authctxt = ctxt;
588 if (authctxt == NULL) 625 if (authctxt == NULL)
589 fatal("input_userauth_success: no authentication context"); 626 fatal("input_userauth_success: no authentication context");
627 if (authctxt->authlist)
628 xfree(authctxt->authlist);
629 clear_auth_state(authctxt);
590 authctxt->success = 1; /* break out */ 630 authctxt->success = 1; /* break out */
591} 631}
592void 632void
593input_userauth_failure(int type, int plen, void *ctxt) 633input_userauth_failure(int type, int plen, void *ctxt)
594{ 634{
595 Authmethod *method = NULL;
596 Authctxt *authctxt = ctxt; 635 Authctxt *authctxt = ctxt;
597 char *authlist = NULL; 636 char *authlist = NULL;
598 int partial; 637 int partial;
@@ -608,20 +647,74 @@ input_userauth_failure(int type, int plen, void *ctxt)
608 log("Authenticated with partial success."); 647 log("Authenticated with partial success.");
609 debug("authentications that can continue: %s", authlist); 648 debug("authentications that can continue: %s", authlist);
610 649
611 for (;;) { 650 clear_auth_state(authctxt);
612 method = authmethod_get(authlist); 651 userauth(authctxt, authlist);
613 if (method == NULL) 652}
614 fatal("Permission denied (%s).", authlist); 653void
615 authctxt->method = method; 654input_userauth_pk_ok(int type, int plen, void *ctxt)
616 if (method->userauth(authctxt) != 0) { 655{
617 debug2("we sent a %s packet, wait for reply", method->name); 656 Authctxt *authctxt = ctxt;
657 Key *key = NULL;
658 Buffer b;
659 int alen, blen, pktype, sent = 0;
660 char *pkalg, *pkblob;
661
662 if (authctxt == NULL)
663 fatal("input_userauth_pk_ok: no authentication context");
664 if (datafellows & SSH_BUG_PKOK) {
665 /* this is similar to SSH_BUG_PKAUTH */
666 debug2("input_userauth_pk_ok: SSH_BUG_PKOK");
667 pkblob = packet_get_string(&blen);
668 buffer_init(&b);
669 buffer_append(&b, pkblob, blen);
670 pkalg = buffer_get_string(&b, &alen);
671 buffer_free(&b);
672 } else {
673 pkalg = packet_get_string(&alen);
674 pkblob = packet_get_string(&blen);
675 }
676 packet_done();
677
678 debug("input_userauth_pk_ok: pkalg %s blen %d lastkey %p hint %d",
679 pkalg, blen, authctxt->last_key, authctxt->last_key_hint);
680
681 do {
682 if (authctxt->last_key == NULL ||
683 authctxt->last_key_sign == NULL) {
684 debug("no last key or no sign cb");
618 break; 685 break;
619 } else {
620 debug2("we did not send a packet, disable method");
621 method->enabled = NULL;
622 } 686 }
623 } 687 debug2("last_key %s", key_fingerprint(authctxt->last_key));
624 xfree(authlist); 688 if ((pktype = key_type_from_name(pkalg)) == KEY_UNSPEC) {
689 debug("unknown pkalg %s", pkalg);
690 break;
691 }
692 if ((key = key_from_blob(pkblob, blen)) == NULL) {
693 debug("no key from blob. pkalg %s", pkalg);
694 break;
695 }
696 debug2("input_userauth_pk_ok: fp %s", key_fingerprint(key));
697 if (!key_equal(key, authctxt->last_key)) {
698 debug("key != last_key");
699 break;
700 }
701 sent = sign_and_send_pubkey(authctxt, key,
702 authctxt->last_key_sign);
703 } while(0);
704
705 if (key != NULL)
706 key_free(key);
707 xfree(pkalg);
708 xfree(pkblob);
709
710 /* unregister */
711 clear_auth_state(authctxt);
712 dispatch_set(SSH2_MSG_USERAUTH_PK_OK, NULL);
713
714 /* try another method if we did not send a packet*/
715 if (sent == 0)
716 userauth(authctxt, NULL);
717
625} 718}
626 719
627int 720int
@@ -633,7 +726,6 @@ userauth_none(Authctxt *authctxt)
633 packet_put_cstring(authctxt->service); 726 packet_put_cstring(authctxt->service);
634 packet_put_cstring(authctxt->method->name); 727 packet_put_cstring(authctxt->method->name);
635 packet_send(); 728 packet_send();
636 packet_write_wait();
637 return 1; 729 return 1;
638} 730}
639 731
@@ -663,10 +755,22 @@ userauth_passwd(Authctxt *authctxt)
663 xfree(password); 755 xfree(password);
664 packet_inject_ignore(64); 756 packet_inject_ignore(64);
665 packet_send(); 757 packet_send();
666 packet_write_wait();
667 return 1; 758 return 1;
668} 759}
669 760
761void
762clear_auth_state(Authctxt *authctxt)
763{
764 /* XXX clear authentication state */
765 if (authctxt->last_key != NULL && authctxt->last_key_hint == -1) {
766 debug3("clear_auth_state: key_free %p", authctxt->last_key);
767 key_free(authctxt->last_key);
768 }
769 authctxt->last_key = NULL;
770 authctxt->last_key_hint = -2;
771 authctxt->last_key_sign = NULL;
772}
773
670int 774int
671sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback) 775sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
672{ 776{
@@ -678,6 +782,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
678 int have_sig = 1; 782 int have_sig = 1;
679 783
680 debug3("sign_and_send_pubkey"); 784 debug3("sign_and_send_pubkey");
785
681 if (key_to_blob(k, &blob, &bloblen) == 0) { 786 if (key_to_blob(k, &blob, &bloblen) == 0) {
682 /* we cannot handle this key */ 787 /* we cannot handle this key */
683 debug3("sign_and_send_pubkey: cannot handle key"); 788 debug3("sign_and_send_pubkey: cannot handle key");
@@ -708,7 +813,8 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
708 buffer_put_string(&b, blob, bloblen); 813 buffer_put_string(&b, blob, bloblen);
709 814
710 /* generate signature */ 815 /* generate signature */
711 ret = (*sign_callback)(authctxt, k, &signature, &slen, buffer_ptr(&b), buffer_len(&b)); 816 ret = (*sign_callback)(authctxt, k, &signature, &slen,
817 buffer_ptr(&b), buffer_len(&b));
712 if (ret == -1) { 818 if (ret == -1) {
713 xfree(blob); 819 xfree(blob);
714 buffer_free(&b); 820 buffer_free(&b);
@@ -720,6 +826,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
720 if (datafellows & SSH_BUG_PKSERVICE) { 826 if (datafellows & SSH_BUG_PKSERVICE) {
721 buffer_clear(&b); 827 buffer_clear(&b);
722 buffer_append(&b, session_id2, session_id2_len); 828 buffer_append(&b, session_id2, session_id2_len);
829 skip = session_id2_len;
723 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); 830 buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST);
724 buffer_put_cstring(&b, authctxt->server_user); 831 buffer_put_cstring(&b, authctxt->server_user);
725 buffer_put_cstring(&b, authctxt->service); 832 buffer_put_cstring(&b, authctxt->service);
@@ -730,6 +837,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
730 buffer_put_string(&b, blob, bloblen); 837 buffer_put_string(&b, blob, bloblen);
731 } 838 }
732 xfree(blob); 839 xfree(blob);
840
733 /* append signature */ 841 /* append signature */
734 buffer_put_string(&b, signature, slen); 842 buffer_put_string(&b, signature, slen);
735 xfree(signature); 843 xfree(signature);
@@ -743,76 +851,113 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
743 packet_start(SSH2_MSG_USERAUTH_REQUEST); 851 packet_start(SSH2_MSG_USERAUTH_REQUEST);
744 packet_put_raw(buffer_ptr(&b), buffer_len(&b)); 852 packet_put_raw(buffer_ptr(&b), buffer_len(&b));
745 buffer_free(&b); 853 buffer_free(&b);
746
747 /* send */
748 packet_send(); 854 packet_send();
749 packet_write_wait();
750 855
751 return 1; 856 return 1;
752} 857}
753 858
754/* sign callback */
755int key_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp,
756 u_char *data, int datalen)
757{
758 return key_sign(key, sigp, lenp, data, datalen);
759}
760
761int 859int
762userauth_pubkey_identity(Authctxt *authctxt, char *filename) 860send_pubkey_test(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback,
861 int hint)
763{ 862{
764 Key *k; 863 u_char *blob;
765 int i, ret, try_next, success = 0; 864 int bloblen, have_sig = 0;
766 struct stat st;
767 char *passphrase;
768 char prompt[300];
769 865
770 if (stat(filename, &st) != 0) { 866 debug3("send_pubkey_test");
771 debug("key does not exist: %s", filename); 867
868 if (key_to_blob(k, &blob, &bloblen) == 0) {
869 /* we cannot handle this key */
870 debug3("send_pubkey_test: cannot handle key");
772 return 0; 871 return 0;
773 } 872 }
774 debug("try pubkey: %s", filename); 873 /* register callback for USERAUTH_PK_OK message */
874 authctxt->last_key_sign = sign_callback;
875 authctxt->last_key_hint = hint;
876 authctxt->last_key = k;
877 dispatch_set(SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok);
775 878
776 k = key_new(KEY_UNSPEC); 879 packet_start(SSH2_MSG_USERAUTH_REQUEST);
777 if (!load_private_key(filename, "", k, NULL)) { 880 packet_put_cstring(authctxt->server_user);
881 packet_put_cstring(authctxt->service);
882 packet_put_cstring(authctxt->method->name);
883 packet_put_char(have_sig);
884 if (!(datafellows & SSH_BUG_PKAUTH))
885 packet_put_cstring(key_ssh_name(k));
886 packet_put_string(blob, bloblen);
887 xfree(blob);
888 packet_send();
889 return 1;
890}
891
892Key *
893load_identity_file(char *filename)
894{
895 Key *private;
896 char prompt[300], *passphrase;
897 int success = 0, quit, i;
898
899 private = key_new(KEY_UNSPEC);
900 if (!load_private_key(filename, "", private, NULL)) {
778 if (options.batch_mode) { 901 if (options.batch_mode) {
779 key_free(k); 902 key_free(private);
780 return 0; 903 return NULL;
781 } 904 }
782 snprintf(prompt, sizeof prompt, 905 snprintf(prompt, sizeof prompt,
783 "Enter passphrase for key '%.100s': ", filename); 906 "Enter passphrase for key '%.100s': ", filename);
784 for (i = 0; i < options.number_of_password_prompts; i++) { 907 for (i = 0; i < options.number_of_password_prompts; i++) {
785 passphrase = read_passphrase(prompt, 0); 908 passphrase = read_passphrase(prompt, 0);
786 if (strcmp(passphrase, "") != 0) { 909 if (strcmp(passphrase, "") != 0) {
787 success = load_private_key(filename, passphrase, k, NULL); 910 success = load_private_key(filename,
788 try_next = 0; 911 passphrase, private, NULL);
912 quit = 0;
789 } else { 913 } else {
790 debug2("no passphrase given, try next key"); 914 debug2("no passphrase given, try next key");
791 try_next = 1; 915 quit = 1;
792 } 916 }
793 memset(passphrase, 0, strlen(passphrase)); 917 memset(passphrase, 0, strlen(passphrase));
794 xfree(passphrase); 918 xfree(passphrase);
795 if (success || try_next) 919 if (success || quit)
796 break; 920 break;
797 debug2("bad passphrase given, try again..."); 921 debug2("bad passphrase given, try again...");
798 } 922 }
799 if (!success) { 923 if (!success) {
800 key_free(k); 924 key_free(private);
801 return 0; 925 return NULL;
802 } 926 }
803 } 927 }
804 ret = sign_and_send_pubkey(authctxt, k, key_sign_cb); 928 return private;
805 key_free(k); 929}
930
931int
932identity_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp,
933 u_char *data, int datalen)
934{
935 Key *private;
936 int idx, ret;
937
938 idx = authctxt->last_key_hint;
939 if (idx < 0)
940 return -1;
941 private = load_identity_file(options.identity_files[idx]);
942 if (private == NULL)
943 return -1;
944 ret = key_sign(private, sigp, lenp, data, datalen);
945 key_free(private);
806 return ret; 946 return ret;
807} 947}
808 948
809/* sign callback */
810int agent_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp, 949int agent_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp,
811 u_char *data, int datalen) 950 u_char *data, int datalen)
812{ 951{
813 return ssh_agent_sign(authctxt->agent, key, sigp, lenp, data, datalen); 952 return ssh_agent_sign(authctxt->agent, key, sigp, lenp, data, datalen);
814} 953}
815 954
955int key_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, int *lenp,
956 u_char *data, int datalen)
957{
958 return key_sign(key, sigp, lenp, data, datalen);
959}
960
816int 961int
817userauth_pubkey_agent(Authctxt *authctxt) 962userauth_pubkey_agent(Authctxt *authctxt)
818{ 963{
@@ -830,10 +975,11 @@ userauth_pubkey_agent(Authctxt *authctxt)
830 if (k == NULL) { 975 if (k == NULL) {
831 debug2("userauth_pubkey_agent: no more keys"); 976 debug2("userauth_pubkey_agent: no more keys");
832 } else { 977 } else {
833 debug("userauth_pubkey_agent: trying agent key %s", comment); 978 debug("userauth_pubkey_agent: testing agent key %s", comment);
834 xfree(comment); 979 xfree(comment);
835 ret = sign_and_send_pubkey(authctxt, k, agent_sign_cb); 980 ret = send_pubkey_test(authctxt, k, agent_sign_cb, -1);
836 key_free(k); 981 if (ret == 0)
982 key_free(k);
837 } 983 }
838 if (ret == 0) 984 if (ret == 0)
839 debug2("userauth_pubkey_agent: no message sent"); 985 debug2("userauth_pubkey_agent: no message sent");
@@ -845,6 +991,8 @@ userauth_pubkey(Authctxt *authctxt)
845{ 991{
846 static int idx = 0; 992 static int idx = 0;
847 int sent = 0; 993 int sent = 0;
994 Key *key;
995 char *filename;
848 996
849 if (authctxt->agent != NULL) { 997 if (authctxt->agent != NULL) {
850 do { 998 do {
@@ -852,9 +1000,21 @@ userauth_pubkey(Authctxt *authctxt)
852 } while(!sent && authctxt->agent->howmany > 0); 1000 } while(!sent && authctxt->agent->howmany > 0);
853 } 1001 }
854 while (!sent && idx < options.num_identity_files) { 1002 while (!sent && idx < options.num_identity_files) {
855 if (options.identity_files_type[idx] != KEY_RSA1) 1003 key = options.identity_keys[idx];
856 sent = userauth_pubkey_identity(authctxt, 1004 filename = options.identity_files[idx];
857 options.identity_files[idx]); 1005 if (key == NULL) {
1006 debug("try privkey: %s", filename);
1007 key = load_identity_file(filename);
1008 if (key != NULL) {
1009 sent = sign_and_send_pubkey(authctxt, key,
1010 key_sign_cb);
1011 key_free(key);
1012 }
1013 } else if (key->type != KEY_RSA1) {
1014 debug("try pubkey: %s", filename);
1015 sent = send_pubkey_test(authctxt, key,
1016 identity_sign_cb, idx);
1017 }
858 idx++; 1018 idx++;
859 } 1019 }
860 return sent; 1020 return sent;
@@ -880,7 +1040,6 @@ userauth_kbdint(Authctxt *authctxt)
880 packet_put_cstring(options.kbd_interactive_devices ? 1040 packet_put_cstring(options.kbd_interactive_devices ?
881 options.kbd_interactive_devices : ""); 1041 options.kbd_interactive_devices : "");
882 packet_send(); 1042 packet_send();
883 packet_write_wait();
884 1043
885 dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req); 1044 dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req);
886 return 1; 1045 return 1;
@@ -938,7 +1097,6 @@ input_userauth_info_req(int type, int plen, void *ctxt)
938 1097
939 packet_inject_ignore(64); 1098 packet_inject_ignore(64);
940 packet_send(); 1099 packet_send();
941 packet_write_wait();
942} 1100}
943 1101
944/* find auth method */ 1102/* find auth method */