diff options
Diffstat (limited to 'sshconnect2.c')
-rw-r--r-- | sshconnect2.c | 336 |
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" |
26 | RCSID("$OpenBSD: sshconnect2.c,v 1.116 2003/04/08 20:21:29 itojun Exp $"); | 26 | RCSID("$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 | ||
142 | typedef struct Authctxt Authctxt; | 142 | typedef struct Authctxt Authctxt; |
143 | typedef struct Authmethod Authmethod; | 143 | typedef struct Authmethod Authmethod; |
144 | 144 | typedef struct identity Identity; | |
145 | typedef int sign_cb_fn( | 145 | typedef struct idlist Idlist; |
146 | Authctxt *authctxt, Key *key, | 146 | |
147 | u_char **sigp, u_int *lenp, u_char *data, u_int datalen); | 147 | struct 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 | }; | ||
155 | TAILQ_HEAD(idlist, identity); | ||
148 | 156 | ||
149 | struct Authctxt { | 157 | struct 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 | ||
188 | void userauth(Authctxt *, char *); | 194 | void userauth(Authctxt *, char *); |
189 | 195 | ||
190 | static int sign_and_send_pubkey(Authctxt *, Key *, sign_cb_fn *); | 196 | static int sign_and_send_pubkey(Authctxt *, Identity *); |
191 | static void clear_auth_state(Authctxt *); | 197 | static void clear_auth_state(Authctxt *); |
198 | static void pubkey_prepare(Authctxt *); | ||
199 | static void pubkey_cleanup(Authctxt *); | ||
200 | static Key *load_identity_file(char *); | ||
192 | 201 | ||
193 | static Authmethod *authmethod_get(char *authlist); | 202 | static Authmethod *authmethod_get(char *authlist); |
194 | static Authmethod *authmethod_lookup(const char *name); | 203 | static 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 | } |
281 | void | 288 | void |
@@ -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); | 419 | done: |
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 | ||
434 | int | 434 | int |
@@ -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) { | 552 | static int |
552 | debug3("clear_auth_state: key_free %p", authctxt->last_key); | 553 | identity_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 | ||
560 | static int | 577 | static int |
561 | sign_and_send_pubkey(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback) | 578 | sign_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 | ||
645 | static int | 662 | static int |
646 | send_pubkey_test(Authctxt *authctxt, Key *k, sign_cb_fn *sign_callback, | 663 | send_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 | ||
716 | static int | 729 | /* |
717 | identity_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 | 735 | static void | |
723 | idx = authctxt->last_key_hint; | 736 | pubkey_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 | |||
739 | static int | ||
740 | agent_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 | |||
746 | static int | ||
747 | key_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 | ||
753 | static int | 806 | static void |
754 | userauth_pubkey_agent(Authctxt *authctxt) | 807 | pubkey_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 | ||
781 | int | 824 | int |
782 | userauth_pubkey(Authctxt *authctxt) | 825 | userauth_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 | /* |