summaryrefslogtreecommitdiff
path: root/sshconnect2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshconnect2.c')
-rw-r--r--sshconnect2.c336
1 files changed, 190 insertions, 146 deletions
diff --git a/sshconnect2.c b/sshconnect2.c
index d32960447..74d699ff2 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.116 2003/04/08 20:21:29 itojun Exp $"); 26RCSID("$OpenBSD: sshconnect2.c,v 1.117 2003/05/12 16:55:37 markus Exp $");
27 27
28#include "ssh.h" 28#include "ssh.h"
29#include "ssh2.h" 29#include "ssh2.h"
@@ -141,10 +141,18 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
141 141
142typedef struct Authctxt Authctxt; 142typedef struct Authctxt Authctxt;
143typedef struct Authmethod Authmethod; 143typedef struct Authmethod Authmethod;
144 144typedef struct identity Identity;
145typedef int sign_cb_fn( 145typedef struct idlist Idlist;
146 Authctxt *authctxt, Key *key, 146
147 u_char **sigp, u_int *lenp, u_char *data, u_int datalen); 147struct identity {
148 TAILQ_ENTRY(identity) next;
149 AuthenticationConnection *ac; /* set if agent supports key */
150 Key *key; /* public/private key */
151 char *filename; /* comment for agent-only keys */
152 int tried;
153 int isprivate; /* key points to the private key */
154};
155TAILQ_HEAD(idlist, identity);
148 156
149struct Authctxt { 157struct Authctxt {
150 const char *server_user; 158 const char *server_user;
@@ -155,9 +163,7 @@ struct Authctxt {
155 int success; 163 int success;
156 char *authlist; 164 char *authlist;
157 /* pubkey */ 165 /* pubkey */
158 Key *last_key; 166 Idlist keys;
159 sign_cb_fn *last_key_sign;
160 int last_key_hint;
161 AuthenticationConnection *agent; 167 AuthenticationConnection *agent;
162 /* hostbased */ 168 /* hostbased */
163 Sensitive *sensitive; 169 Sensitive *sensitive;
@@ -187,8 +193,11 @@ int userauth_hostbased(Authctxt *);
187 193
188void userauth(Authctxt *, char *); 194void userauth(Authctxt *, char *);
189 195
190static int sign_and_send_pubkey(Authctxt *, Key *, sign_cb_fn *); 196static int sign_and_send_pubkey(Authctxt *, Identity *);
191static void clear_auth_state(Authctxt *); 197static void clear_auth_state(Authctxt *);
198static void pubkey_prepare(Authctxt *);
199static void pubkey_cleanup(Authctxt *);
200static Key *load_identity_file(char *);
192 201
193static Authmethod *authmethod_get(char *authlist); 202static Authmethod *authmethod_get(char *authlist);
194static Authmethod *authmethod_lookup(const char *name); 203static Authmethod *authmethod_lookup(const char *name);
@@ -251,7 +260,7 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host,
251 260
252 /* setup authentication context */ 261 /* setup authentication context */
253 memset(&authctxt, 0, sizeof(authctxt)); 262 memset(&authctxt, 0, sizeof(authctxt));
254 authctxt.agent = ssh_get_authentication_connection(); 263 pubkey_prepare(&authctxt);
255 authctxt.server_user = server_user; 264 authctxt.server_user = server_user;
256 authctxt.local_user = local_user; 265 authctxt.local_user = local_user;
257 authctxt.host = host; 266 authctxt.host = host;
@@ -273,9 +282,7 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host,
273 dispatch_set(SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner); 282 dispatch_set(SSH2_MSG_USERAUTH_BANNER, &input_userauth_banner);
274 dispatch_run(DISPATCH_BLOCK, &authctxt.success, &authctxt); /* loop until success */ 283 dispatch_run(DISPATCH_BLOCK, &authctxt.success, &authctxt); /* loop until success */
275 284
276 if (authctxt.agent != NULL) 285 pubkey_cleanup(&authctxt);
277 ssh_close_authentication_connection(authctxt.agent);
278
279 debug("Authentication succeeded (%s).", authctxt.method->name); 286 debug("Authentication succeeded (%s).", authctxt.method->name);
280} 287}
281void 288void
@@ -360,6 +367,7 @@ input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt)
360{ 367{
361 Authctxt *authctxt = ctxt; 368 Authctxt *authctxt = ctxt;
362 Key *key = NULL; 369 Key *key = NULL;
370 Identity *id = NULL;
363 Buffer b; 371 Buffer b;
364 int pktype, sent = 0; 372 int pktype, sent = 0;
365 u_int alen, blen; 373 u_int alen, blen;
@@ -382,40 +390,33 @@ input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt)
382 } 390 }
383 packet_check_eom(); 391 packet_check_eom();
384 392
385 debug("Server accepts key: pkalg %s blen %u lastkey %p hint %d", 393 debug("Server accepts key: pkalg %s blen %u", pkalg, blen);
386 pkalg, blen, authctxt->last_key, authctxt->last_key_hint);
387 394
388 do { 395 if ((pktype = key_type_from_name(pkalg)) == KEY_UNSPEC) {
389 if (authctxt->last_key == NULL || 396 debug("unknown pkalg %s", pkalg);
390 authctxt->last_key_sign == NULL) { 397 goto done;
391 debug("no last key or no sign cb"); 398 }
392 break; 399 if ((key = key_from_blob(pkblob, blen)) == NULL) {
393 } 400 debug("no key from blob. pkalg %s", pkalg);
394 if ((pktype = key_type_from_name(pkalg)) == KEY_UNSPEC) { 401 goto done;
395 debug("unknown pkalg %s", pkalg); 402 }
396 break; 403 if (key->type != pktype) {
397 } 404 error("input_userauth_pk_ok: type mismatch "
398 if ((key = key_from_blob(pkblob, blen)) == NULL) { 405 "for decoded key (received %d, expected %d)",
399 debug("no key from blob. pkalg %s", pkalg); 406 key->type, pktype);
400 break; 407 goto done;
401 } 408 }
402 if (key->type != pktype) { 409 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
403 error("input_userauth_pk_ok: type mismatch " 410 debug2("input_userauth_pk_ok: fp %s", fp);
404 "for decoded key (received %d, expected %d)", 411 xfree(fp);
405 key->type, pktype); 412
406 break; 413 TAILQ_FOREACH(id, &authctxt->keys, next) {
407 } 414 if (key_equal(key, id->key)) {
408 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX); 415 sent = sign_and_send_pubkey(authctxt, id);
409 debug2("input_userauth_pk_ok: fp %s", fp);
410 xfree(fp);
411 if (!key_equal(key, authctxt->last_key)) {
412 debug("key != last_key");
413 break; 416 break;
414 } 417 }
415 sent = sign_and_send_pubkey(authctxt, key, 418 }
416 authctxt->last_key_sign); 419done:
417 } while (0);
418
419 if (key != NULL) 420 if (key != NULL)
420 key_free(key); 421 key_free(key);
421 xfree(pkalg); 422 xfree(pkalg);
@@ -428,7 +429,6 @@ input_userauth_pk_ok(int type, u_int32_t seq, void *ctxt)
428 /* try another method if we did not send a packet */ 429 /* try another method if we did not send a packet */
429 if (sent == 0) 430 if (sent == 0)
430 userauth(authctxt, NULL); 431 userauth(authctxt, NULL);
431
432} 432}
433 433
434int 434int
@@ -547,18 +547,35 @@ clear_auth_state(Authctxt *authctxt)
547{ 547{
548 /* XXX clear authentication state */ 548 /* XXX clear authentication state */
549 dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, NULL); 549 dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, NULL);
550}
550 551
551 if (authctxt->last_key != NULL && authctxt->last_key_hint == -1) { 552static int
552 debug3("clear_auth_state: key_free %p", authctxt->last_key); 553identity_sign(Identity *id, u_char **sigp, u_int *lenp,
553 key_free(authctxt->last_key); 554 u_char *data, u_int datalen)
554 } 555{
555 authctxt->last_key = NULL; 556 Key *prv;
556 authctxt->last_key_hint = -2; 557 int ret;
557 authctxt->last_key_sign = NULL; 558
559 /* the agent supports this key */
560 if (id->ac)
561 return (ssh_agent_sign(id->ac, id->key, sigp, lenp,
562 data, datalen));
563 /*
564 * we have already loaded the private key or
565 * the private key is stored in external hardware
566 */
567 if (id->isprivate || (id->key->flags & KEY_FLAG_EXT))
568 return (key_sign(id->key, sigp, lenp, data, datalen));
569 /* load the private key from the file */
570 if ((prv = load_identity_file(id->filename)) == NULL)
571 return (-1);
572 ret = key_sign(prv, sigp, lenp, data, datalen);
573 key_free(prv);
574 return (ret);
558} 575}
559 576
560static int 577static int
561sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback) 578sign_and_send_pubkey(Authctxt *authctxt, Identity *id)
562{ 579{
563 Buffer b; 580 Buffer b;
564 u_char *blob, *signature; 581 u_char *blob, *signature;
@@ -569,7 +586,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
569 586
570 debug3("sign_and_send_pubkey"); 587 debug3("sign_and_send_pubkey");
571 588
572 if (key_to_blob(k, &blob, &bloblen) == 0) { 589 if (key_to_blob(id->key, &blob, &bloblen) == 0) {
573 /* we cannot handle this key */ 590 /* we cannot handle this key */
574 debug3("sign_and_send_pubkey: cannot handle key"); 591 debug3("sign_and_send_pubkey: cannot handle key");
575 return 0; 592 return 0;
@@ -594,12 +611,12 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
594 } else { 611 } else {
595 buffer_put_cstring(&b, authctxt->method->name); 612 buffer_put_cstring(&b, authctxt->method->name);
596 buffer_put_char(&b, have_sig); 613 buffer_put_char(&b, have_sig);
597 buffer_put_cstring(&b, key_ssh_name(k)); 614 buffer_put_cstring(&b, key_ssh_name(id->key));
598 } 615 }
599 buffer_put_string(&b, blob, bloblen); 616 buffer_put_string(&b, blob, bloblen);
600 617
601 /* generate signature */ 618 /* generate signature */
602 ret = (*sign_callback)(authctxt, k, &signature, &slen, 619 ret = identity_sign(id, &signature, &slen,
603 buffer_ptr(&b), buffer_len(&b)); 620 buffer_ptr(&b), buffer_len(&b));
604 if (ret == -1) { 621 if (ret == -1) {
605 xfree(blob); 622 xfree(blob);
@@ -619,7 +636,7 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
619 buffer_put_cstring(&b, authctxt->method->name); 636 buffer_put_cstring(&b, authctxt->method->name);
620 buffer_put_char(&b, have_sig); 637 buffer_put_char(&b, have_sig);
621 if (!(datafellows & SSH_BUG_PKAUTH)) 638 if (!(datafellows & SSH_BUG_PKAUTH))
622 buffer_put_cstring(&b, key_ssh_name(k)); 639 buffer_put_cstring(&b, key_ssh_name(id->key));
623 buffer_put_string(&b, blob, bloblen); 640 buffer_put_string(&b, blob, bloblen);
624 } 641 }
625 xfree(blob); 642 xfree(blob);
@@ -643,23 +660,19 @@ sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback)
643} 660}
644 661
645static int 662static int
646send_pubkey_test(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback, 663send_pubkey_test(Authctxt *authctxt, Identity *id)
647 int hint)
648{ 664{
649 u_char *blob; 665 u_char *blob;
650 u_int bloblen, have_sig = 0; 666 u_int bloblen, have_sig = 0;
651 667
652 debug3("send_pubkey_test"); 668 debug3("send_pubkey_test");
653 669
654 if (key_to_blob(k, &blob, &bloblen) == 0) { 670 if (key_to_blob(id->key, &blob, &bloblen) == 0) {
655 /* we cannot handle this key */ 671 /* we cannot handle this key */
656 debug3("send_pubkey_test: cannot handle key"); 672 debug3("send_pubkey_test: cannot handle key");
657 return 0; 673 return 0;
658 } 674 }
659 /* register callback for USERAUTH_PK_OK message */ 675 /* register callback for USERAUTH_PK_OK message */
660 authctxt->last_key_sign = sign_callback;
661 authctxt->last_key_hint = hint;
662 authctxt->last_key = k;
663 dispatch_set(SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok); 676 dispatch_set(SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok);
664 677
665 packet_start(SSH2_MSG_USERAUTH_REQUEST); 678 packet_start(SSH2_MSG_USERAUTH_REQUEST);
@@ -668,7 +681,7 @@ send_pubkey_test(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback,
668 packet_put_cstring(authctxt->method->name); 681 packet_put_cstring(authctxt->method->name);
669 packet_put_char(have_sig); 682 packet_put_char(have_sig);
670 if (!(datafellows & SSH_BUG_PKAUTH)) 683 if (!(datafellows & SSH_BUG_PKAUTH))
671 packet_put_cstring(key_ssh_name(k)); 684 packet_put_cstring(key_ssh_name(id->key));
672 packet_put_string(blob, bloblen); 685 packet_put_string(blob, bloblen);
673 xfree(blob); 686 xfree(blob);
674 packet_send(); 687 packet_send();
@@ -713,103 +726,134 @@ load_identity_file(char *filename)
713 return private; 726 return private;
714} 727}
715 728
716static int 729/*
717identity_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, u_int *lenp, 730 * try keys in the following order:
718 u_char *data, u_int datalen) 731 * 1. agent keys that are found in the config file
719{ 732 * 2. other agent keys
720 Key *private; 733 * 3. keys that are only listed in the config file
721 int idx, ret; 734 */
722 735static void
723 idx = authctxt->last_key_hint; 736pubkey_prepare(Authctxt *authctxt)
724 if (idx < 0)
725 return -1;
726
727 /* private key is stored in external hardware */
728 if (options.identity_keys[idx]->flags & KEY_FLAG_EXT)
729 return key_sign(options.identity_keys[idx], sigp, lenp, data, datalen);
730
731 private = load_identity_file(options.identity_files[idx]);
732 if (private == NULL)
733 return -1;
734 ret = key_sign(private, sigp, lenp, data, datalen);
735 key_free(private);
736 return ret;
737}
738
739static int
740agent_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, u_int *lenp,
741 u_char *data, u_int datalen)
742{
743 return ssh_agent_sign(authctxt->agent, key, sigp, lenp, data, datalen);
744}
745
746static int
747key_sign_cb(Authctxt *authctxt, Key *key, u_char **sigp, u_int *lenp,
748 u_char *data, u_int datalen)
749{ 737{
750 return key_sign(key, sigp, lenp, data, datalen); 738 Identity *id;
739 Idlist agent, files, *preferred;
740 Key *key;
741 AuthenticationConnection *ac;
742 char *comment;
743 int i, found;
744
745 TAILQ_INIT(&agent); /* keys from the agent */
746 TAILQ_INIT(&files); /* keys from the config file */
747 preferred = &authctxt->keys;
748 TAILQ_INIT(preferred); /* preferred order of keys */
749
750 /* list of keys stored in the filesystem */
751 for (i = 0; i < options.num_identity_files; i++) {
752 key = options.identity_keys[i];
753 if (key && key->type == KEY_RSA1)
754 continue;
755 options.identity_keys[i] = NULL;
756 id = xmalloc(sizeof(*id));
757 memset(id, 0, sizeof(*id));
758 id->key = key;
759 id->filename = xstrdup(options.identity_files[i]);
760 TAILQ_INSERT_TAIL(&files, id, next);
761 }
762 /* list of keys supported by the agent */
763 if ((ac = ssh_get_authentication_connection())) {
764 for (key = ssh_get_first_identity(ac, &comment, 2);
765 key != NULL;
766 key = ssh_get_next_identity(ac, &comment, 2)) {
767 found = 0;
768 TAILQ_FOREACH(id, &files, next) {
769 /* agent keys from the config file are preferred */
770 if (key_equal(key, id->key)) {
771 key_free(key);
772 xfree(comment);
773 TAILQ_REMOVE(&files, id, next);
774 TAILQ_INSERT_TAIL(preferred, id, next);
775 id->ac = ac;
776 found = 1;
777 break;
778 }
779 }
780 if (!found) {
781 id = xmalloc(sizeof(*id));
782 memset(id, 0, sizeof(*id));
783 id->key = key;
784 id->filename = comment;
785 id->ac = ac;
786 TAILQ_INSERT_TAIL(&agent, id, next);
787 }
788 }
789 /* append remaining agent keys */
790 for (id = TAILQ_FIRST(&agent); id; id = TAILQ_FIRST(&agent)) {
791 TAILQ_REMOVE(&agent, id, next);
792 TAILQ_INSERT_TAIL(preferred, id, next);
793 }
794 authctxt->agent = ac;
795 }
796 /* append remaining keys from the config file */
797 for (id = TAILQ_FIRST(&files); id; id = TAILQ_FIRST(&files)) {
798 TAILQ_REMOVE(&files, id, next);
799 TAILQ_INSERT_TAIL(preferred, id, next);
800 }
801 TAILQ_FOREACH(id, preferred, next) {
802 debug2("key: %s (%p)", id->filename, id->key);
803 }
751} 804}
752 805
753static int 806static void
754userauth_pubkey_agent(Authctxt *authctxt) 807pubkey_cleanup(Authctxt *authctxt)
755{ 808{
756 static int called = 0; 809 Identity *id;
757 int ret = 0; 810
758 char *comment; 811 if (authctxt->agent != NULL)
759 Key *k; 812 ssh_close_authentication_connection(authctxt->agent);
760 813 for (id = TAILQ_FIRST(&authctxt->keys); id;
761 if (called == 0) { 814 id = TAILQ_FIRST(&authctxt->keys)) {
762 if (ssh_get_num_identities(authctxt->agent, 2) == 0) 815 TAILQ_REMOVE(&authctxt->keys, id, next);
763 debug2("userauth_pubkey_agent: no keys at all"); 816 if (id->key)
764 called = 1; 817 key_free(id->key);
818 if (id->filename)
819 xfree(id->filename);
820 xfree(id);
765 } 821 }
766 k = ssh_get_next_identity(authctxt->agent, &comment, 2);
767 if (k == NULL) {
768 debug2("userauth_pubkey_agent: no more keys");
769 } else {
770 debug("Offering agent key: %s", comment);
771 xfree(comment);
772 ret = send_pubkey_test(authctxt, k, agent_sign_cb, -1);
773 if (ret == 0)
774 key_free(k);
775 }
776 if (ret == 0)
777 debug2("userauth_pubkey_agent: no message sent");
778 return ret;
779} 822}
780 823
781int 824int
782userauth_pubkey(Authctxt *authctxt) 825userauth_pubkey(Authctxt *authctxt)
783{ 826{
784 static int idx = 0; 827 Identity *id;
785 int sent = 0; 828 int sent = 0;
786 Key *key;
787 char *filename;
788 829
789 if (authctxt->agent != NULL) { 830 while ((id = TAILQ_FIRST(&authctxt->keys))) {
790 do { 831 if (id->tried++)
791 sent = userauth_pubkey_agent(authctxt); 832 return (0);
792 } while (!sent && authctxt->agent->howmany > 0); 833 TAILQ_REMOVE(&authctxt->keys, id, next);
793 } 834 TAILQ_INSERT_TAIL(&authctxt->keys, id, next);
794 while (!sent && idx < options.num_identity_files) { 835 /*
795 key = options.identity_keys[idx]; 836 * send a test message if we have the public key. for
796 filename = options.identity_files[idx]; 837 * encrypted keys we cannot do this and have to load the
797 if (key == NULL) { 838 * private key instead
798 debug("Trying private key: %s", filename); 839 */
799 key = load_identity_file(filename); 840 if (id->key && id->key->type != KEY_RSA1) {
800 if (key != NULL) { 841 debug("Offering public key: %s", id->filename);
801 sent = sign_and_send_pubkey(authctxt, key, 842 sent = send_pubkey_test(authctxt, id);
802 key_sign_cb); 843 } else if (id->key == NULL) {
803 key_free(key); 844 debug("Trying private key: %s", id->filename);
845 id->key = load_identity_file(id->filename);
846 if (id->key != NULL) {
847 id->isprivate = 1;
848 sent = sign_and_send_pubkey(authctxt, id);
849 key_free(id->key);
850 id->key = NULL;
804 } 851 }
805 } else if (key->type != KEY_RSA1) {
806 debug("Offering public key: %s", filename);
807 sent = send_pubkey_test(authctxt, key,
808 identity_sign_cb, idx);
809 } 852 }
810 idx++; 853 if (sent)
854 return (sent);
811 } 855 }
812 return sent; 856 return (0);
813} 857}
814 858
815/* 859/*