diff options
Diffstat (limited to 'sshconnect2.c')
-rw-r--r-- | sshconnect2.c | 882 |
1 files changed, 520 insertions, 362 deletions
diff --git a/sshconnect2.c b/sshconnect2.c index 83562c688..c6a1b1271 100644 --- a/sshconnect2.c +++ b/sshconnect2.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: sshconnect2.c,v 1.270 2018/03/24 19:28:43 markus Exp $ */ | 1 | /* $OpenBSD: sshconnect2.c,v 1.284 2018/08/13 02:41:05 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2000 Markus Friedl. All rights reserved. |
4 | * Copyright (c) 2008 Damien Miller. All rights reserved. | 4 | * Copyright (c) 2008 Damien Miller. All rights reserved. |
@@ -49,11 +49,11 @@ | |||
49 | #include "xmalloc.h" | 49 | #include "xmalloc.h" |
50 | #include "ssh.h" | 50 | #include "ssh.h" |
51 | #include "ssh2.h" | 51 | #include "ssh2.h" |
52 | #include "buffer.h" | 52 | #include "sshbuf.h" |
53 | #include "packet.h" | 53 | #include "packet.h" |
54 | #include "compat.h" | 54 | #include "compat.h" |
55 | #include "cipher.h" | 55 | #include "cipher.h" |
56 | #include "key.h" | 56 | #include "sshkey.h" |
57 | #include "kex.h" | 57 | #include "kex.h" |
58 | #include "myproposal.h" | 58 | #include "myproposal.h" |
59 | #include "sshconnect.h" | 59 | #include "sshconnect.h" |
@@ -158,7 +158,7 @@ void | |||
158 | ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) | 158 | ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) |
159 | { | 159 | { |
160 | char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; | 160 | char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; |
161 | char *s; | 161 | char *s, *all_key; |
162 | struct kex *kex; | 162 | struct kex *kex; |
163 | int r; | 163 | int r; |
164 | 164 | ||
@@ -183,9 +183,11 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) | |||
183 | myproposal[PROPOSAL_MAC_ALGS_CTOS] = | 183 | myproposal[PROPOSAL_MAC_ALGS_CTOS] = |
184 | myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; | 184 | myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; |
185 | if (options.hostkeyalgorithms != NULL) { | 185 | if (options.hostkeyalgorithms != NULL) { |
186 | if (kex_assemble_names(KEX_DEFAULT_PK_ALG, | 186 | all_key = sshkey_alg_list(0, 0, 1, ','); |
187 | &options.hostkeyalgorithms) != 0) | 187 | if (kex_assemble_names(&options.hostkeyalgorithms, |
188 | KEX_DEFAULT_PK_ALG, all_key) != 0) | ||
188 | fatal("%s: kex_assemble_namelist", __func__); | 189 | fatal("%s: kex_assemble_namelist", __func__); |
190 | free(all_key); | ||
189 | myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = | 191 | myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = |
190 | compat_pkalg_proposal(options.hostkeyalgorithms); | 192 | compat_pkalg_proposal(options.hostkeyalgorithms); |
191 | } else { | 193 | } else { |
@@ -290,10 +292,11 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) | |||
290 | 292 | ||
291 | #ifdef DEBUG_KEXDH | 293 | #ifdef DEBUG_KEXDH |
292 | /* send 1st encrypted/maced/compressed message */ | 294 | /* send 1st encrypted/maced/compressed message */ |
293 | packet_start(SSH2_MSG_IGNORE); | 295 | if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 || |
294 | packet_put_cstring("markus"); | 296 | (r = sshpkt_put_cstring(ssh, "markus")) != 0 || |
295 | packet_send(); | 297 | (r = sshpkt_send(ssh)) != 0 || |
296 | packet_write_wait(); | 298 | (r = ssh_packet_write_wait(ssh)) != 0) |
299 | fatal("%s: %s", __func__, ssh_err(r)); | ||
297 | #endif | 300 | #endif |
298 | } | 301 | } |
299 | 302 | ||
@@ -376,7 +379,7 @@ int userauth_gsskeyex(Authctxt *authctxt); | |||
376 | 379 | ||
377 | void userauth(Authctxt *, char *); | 380 | void userauth(Authctxt *, char *); |
378 | 381 | ||
379 | static int sign_and_send_pubkey(Authctxt *, Identity *); | 382 | static int sign_and_send_pubkey(struct ssh *ssh, Authctxt *, Identity *); |
380 | static void pubkey_prepare(Authctxt *); | 383 | static void pubkey_prepare(Authctxt *); |
381 | static void pubkey_cleanup(Authctxt *); | 384 | static void pubkey_cleanup(Authctxt *); |
382 | static void pubkey_reset(Authctxt *); | 385 | static void pubkey_reset(Authctxt *); |
@@ -521,6 +524,8 @@ input_userauth_ext_info(int type, u_int32_t seqnr, struct ssh *ssh) | |||
521 | void | 524 | void |
522 | userauth(Authctxt *authctxt, char *authlist) | 525 | userauth(Authctxt *authctxt, char *authlist) |
523 | { | 526 | { |
527 | struct ssh *ssh = active_state; /* XXX */ | ||
528 | |||
524 | if (authctxt->method != NULL && authctxt->method->cleanup != NULL) | 529 | if (authctxt->method != NULL && authctxt->method->cleanup != NULL) |
525 | authctxt->method->cleanup(authctxt); | 530 | authctxt->method->cleanup(authctxt); |
526 | 531 | ||
@@ -540,7 +545,7 @@ userauth(Authctxt *authctxt, char *authlist) | |||
540 | authctxt->method = method; | 545 | authctxt->method = method; |
541 | 546 | ||
542 | /* reset the per method handler */ | 547 | /* reset the per method handler */ |
543 | dispatch_range(SSH2_MSG_USERAUTH_PER_METHOD_MIN, | 548 | ssh_dispatch_range(ssh, SSH2_MSG_USERAUTH_PER_METHOD_MIN, |
544 | SSH2_MSG_USERAUTH_PER_METHOD_MAX, NULL); | 549 | SSH2_MSG_USERAUTH_PER_METHOD_MAX, NULL); |
545 | 550 | ||
546 | /* and try new method */ | 551 | /* and try new method */ |
@@ -617,14 +622,16 @@ input_userauth_failure(int type, u_int32_t seq, struct ssh *ssh) | |||
617 | { | 622 | { |
618 | Authctxt *authctxt = ssh->authctxt; | 623 | Authctxt *authctxt = ssh->authctxt; |
619 | char *authlist = NULL; | 624 | char *authlist = NULL; |
620 | int partial; | 625 | u_char partial; |
626 | int r; | ||
621 | 627 | ||
622 | if (authctxt == NULL) | 628 | if (authctxt == NULL) |
623 | fatal("input_userauth_failure: no authentication context"); | 629 | fatal("input_userauth_failure: no authentication context"); |
624 | 630 | ||
625 | authlist = packet_get_string(NULL); | 631 | if ((r = sshpkt_get_cstring(ssh, &authlist, NULL)) != 0 || |
626 | partial = packet_get_char(); | 632 | (r = sshpkt_get_u8(ssh, &partial)) != 0 || |
627 | packet_check_eom(); | 633 | (r = sshpkt_get_end(ssh)) != 0) |
634 | goto out; | ||
628 | 635 | ||
629 | if (partial != 0) { | 636 | if (partial != 0) { |
630 | verbose("Authenticated with partial success."); | 637 | verbose("Authenticated with partial success."); |
@@ -634,6 +641,9 @@ input_userauth_failure(int type, u_int32_t seq, struct ssh *ssh) | |||
634 | debug("Authentications that can continue: %s", authlist); | 641 | debug("Authentications that can continue: %s", authlist); |
635 | 642 | ||
636 | userauth(authctxt, authlist); | 643 | userauth(authctxt, authlist); |
644 | authlist = NULL; | ||
645 | out: | ||
646 | free(authlist); | ||
637 | return 0; | 647 | return 0; |
638 | } | 648 | } |
639 | 649 | ||
@@ -645,25 +655,27 @@ input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh) | |||
645 | struct sshkey *key = NULL; | 655 | struct sshkey *key = NULL; |
646 | Identity *id = NULL; | 656 | Identity *id = NULL; |
647 | int pktype, sent = 0; | 657 | int pktype, sent = 0; |
648 | u_int alen, blen; | 658 | size_t blen; |
649 | char *pkalg, *fp; | 659 | char *pkalg = NULL, *fp; |
650 | u_char *pkblob; | 660 | u_char *pkblob = NULL; |
661 | int r; | ||
651 | 662 | ||
652 | if (authctxt == NULL) | 663 | if (authctxt == NULL) |
653 | fatal("input_userauth_pk_ok: no authentication context"); | 664 | fatal("input_userauth_pk_ok: no authentication context"); |
654 | 665 | ||
655 | pkalg = packet_get_string(&alen); | 666 | if ((r = sshpkt_get_cstring(ssh, &pkalg, NULL)) != 0 || |
656 | pkblob = packet_get_string(&blen); | 667 | (r = sshpkt_get_string(ssh, &pkblob, &blen)) != 0 || |
657 | packet_check_eom(); | 668 | (r = sshpkt_get_end(ssh)) != 0) |
669 | goto done; | ||
658 | 670 | ||
659 | debug("Server accepts key: pkalg %s blen %u", pkalg, blen); | 671 | debug("Server accepts key: pkalg %s blen %zu", pkalg, blen); |
660 | 672 | ||
661 | if ((pktype = key_type_from_name(pkalg)) == KEY_UNSPEC) { | 673 | if ((pktype = sshkey_type_from_name(pkalg)) == KEY_UNSPEC) { |
662 | debug("unknown pkalg %s", pkalg); | 674 | debug("unknown pkalg %s", pkalg); |
663 | goto done; | 675 | goto done; |
664 | } | 676 | } |
665 | if ((key = key_from_blob(pkblob, blen)) == NULL) { | 677 | if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { |
666 | debug("no key from blob. pkalg %s", pkalg); | 678 | debug("no key from blob. pkalg %s: %s", pkalg, ssh_err(r)); |
667 | goto done; | 679 | goto done; |
668 | } | 680 | } |
669 | if (key->type != pktype) { | 681 | if (key->type != pktype) { |
@@ -684,31 +696,33 @@ input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh) | |||
684 | * duplicate keys | 696 | * duplicate keys |
685 | */ | 697 | */ |
686 | TAILQ_FOREACH_REVERSE(id, &authctxt->keys, idlist, next) { | 698 | TAILQ_FOREACH_REVERSE(id, &authctxt->keys, idlist, next) { |
687 | if (key_equal(key, id->key)) { | 699 | if (sshkey_equal(key, id->key)) { |
688 | sent = sign_and_send_pubkey(authctxt, id); | 700 | sent = sign_and_send_pubkey(ssh, authctxt, id); |
689 | break; | 701 | break; |
690 | } | 702 | } |
691 | } | 703 | } |
692 | done: | 704 | r = 0; |
693 | key_free(key); | 705 | done: |
706 | sshkey_free(key); | ||
694 | free(pkalg); | 707 | free(pkalg); |
695 | free(pkblob); | 708 | free(pkblob); |
696 | 709 | ||
697 | /* try another method if we did not send a packet */ | 710 | /* try another method if we did not send a packet */ |
698 | if (sent == 0) | 711 | if (r == 0 && sent == 0) |
699 | userauth(authctxt, NULL); | 712 | userauth(authctxt, NULL); |
700 | return 0; | 713 | return r; |
701 | } | 714 | } |
702 | 715 | ||
703 | #ifdef GSSAPI | 716 | #ifdef GSSAPI |
704 | int | 717 | int |
705 | userauth_gssapi(Authctxt *authctxt) | 718 | userauth_gssapi(Authctxt *authctxt) |
706 | { | 719 | { |
720 | struct ssh *ssh = active_state; /* XXX */ | ||
707 | Gssctxt *gssctxt = NULL; | 721 | Gssctxt *gssctxt = NULL; |
708 | static gss_OID_set gss_supported = NULL; | 722 | static gss_OID_set gss_supported = NULL; |
709 | static u_int mech = 0; | 723 | static u_int mech = 0; |
710 | OM_uint32 min; | 724 | OM_uint32 min; |
711 | int ok = 0; | 725 | int r, ok = 0; |
712 | char *gss_host; | 726 | char *gss_host; |
713 | 727 | ||
714 | if (options.gss_server_identity) | 728 | if (options.gss_server_identity) |
@@ -732,8 +746,8 @@ userauth_gssapi(Authctxt *authctxt) | |||
732 | while (mech < gss_supported->count && !ok) { | 746 | while (mech < gss_supported->count && !ok) { |
733 | /* My DER encoding requires length<128 */ | 747 | /* My DER encoding requires length<128 */ |
734 | if (gss_supported->elements[mech].length < 128 && | 748 | if (gss_supported->elements[mech].length < 128 && |
735 | ssh_gssapi_check_mechanism(&gssctxt, | 749 | ssh_gssapi_check_mechanism(&gssctxt, |
736 | &gss_supported->elements[mech], gss_host, | 750 | &gss_supported->elements[mech], gss_host, |
737 | options.gss_client_identity)) { | 751 | options.gss_client_identity)) { |
738 | ok = 1; /* Mechanism works */ | 752 | ok = 1; /* Mechanism works */ |
739 | } else { | 753 | } else { |
@@ -748,25 +762,26 @@ userauth_gssapi(Authctxt *authctxt) | |||
748 | 762 | ||
749 | authctxt->methoddata=(void *)gssctxt; | 763 | authctxt->methoddata=(void *)gssctxt; |
750 | 764 | ||
751 | packet_start(SSH2_MSG_USERAUTH_REQUEST); | 765 | if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || |
752 | packet_put_cstring(authctxt->server_user); | 766 | (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || |
753 | packet_put_cstring(authctxt->service); | 767 | (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || |
754 | packet_put_cstring(authctxt->method->name); | 768 | (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || |
755 | 769 | (r = sshpkt_put_u32(ssh, 1)) != 0 || | |
756 | packet_put_int(1); | 770 | (r = sshpkt_put_u32(ssh, |
757 | 771 | (gss_supported->elements[mech].length) + 2)) != 0 || | |
758 | packet_put_int((gss_supported->elements[mech].length) + 2); | 772 | (r = sshpkt_put_u8(ssh, SSH_GSS_OIDTYPE)) != 0 || |
759 | packet_put_char(SSH_GSS_OIDTYPE); | 773 | (r = sshpkt_put_u8(ssh, |
760 | packet_put_char(gss_supported->elements[mech].length); | 774 | gss_supported->elements[mech].length)) != 0 || |
761 | packet_put_raw(gss_supported->elements[mech].elements, | 775 | (r = sshpkt_put(ssh, |
762 | gss_supported->elements[mech].length); | 776 | gss_supported->elements[mech].elements, |
763 | 777 | gss_supported->elements[mech].length)) != 0 || | |
764 | packet_send(); | 778 | (r = sshpkt_send(ssh)) != 0) |
779 | fatal("%s: %s", __func__, ssh_err(r)); | ||
765 | 780 | ||
766 | dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_RESPONSE, &input_gssapi_response); | 781 | ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_RESPONSE, &input_gssapi_response); |
767 | dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token); | 782 | ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, &input_gssapi_token); |
768 | dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERROR, &input_gssapi_error); | 783 | ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERROR, &input_gssapi_error); |
769 | dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok); | 784 | ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_ERRTOK, &input_gssapi_errtok); |
770 | 785 | ||
771 | mech++; /* Move along to next candidate */ | 786 | mech++; /* Move along to next candidate */ |
772 | 787 | ||
@@ -782,44 +797,56 @@ process_gssapi_token(struct ssh *ssh, gss_buffer_t recv_tok) | |||
782 | gss_buffer_desc mic = GSS_C_EMPTY_BUFFER; | 797 | gss_buffer_desc mic = GSS_C_EMPTY_BUFFER; |
783 | gss_buffer_desc gssbuf; | 798 | gss_buffer_desc gssbuf; |
784 | OM_uint32 status, ms, flags; | 799 | OM_uint32 status, ms, flags; |
785 | Buffer b; | 800 | int r; |
786 | 801 | ||
787 | status = ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds, | 802 | status = ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds, |
788 | recv_tok, &send_tok, &flags); | 803 | recv_tok, &send_tok, &flags); |
789 | 804 | ||
790 | if (send_tok.length > 0) { | 805 | if (send_tok.length > 0) { |
791 | if (GSS_ERROR(status)) | 806 | u_char type = GSS_ERROR(status) ? |
792 | packet_start(SSH2_MSG_USERAUTH_GSSAPI_ERRTOK); | 807 | SSH2_MSG_USERAUTH_GSSAPI_ERRTOK : |
793 | else | 808 | SSH2_MSG_USERAUTH_GSSAPI_TOKEN; |
794 | packet_start(SSH2_MSG_USERAUTH_GSSAPI_TOKEN); | 809 | |
810 | if ((r = sshpkt_start(ssh, type)) != 0 || | ||
811 | (r = sshpkt_put_string(ssh, send_tok.value, | ||
812 | send_tok.length)) != 0 || | ||
813 | (r = sshpkt_send(ssh)) != 0) | ||
814 | fatal("%s: %s", __func__, ssh_err(r)); | ||
795 | 815 | ||
796 | packet_put_string(send_tok.value, send_tok.length); | ||
797 | packet_send(); | ||
798 | gss_release_buffer(&ms, &send_tok); | 816 | gss_release_buffer(&ms, &send_tok); |
799 | } | 817 | } |
800 | 818 | ||
801 | if (status == GSS_S_COMPLETE) { | 819 | if (status == GSS_S_COMPLETE) { |
802 | /* send either complete or MIC, depending on mechanism */ | 820 | /* send either complete or MIC, depending on mechanism */ |
803 | if (!(flags & GSS_C_INTEG_FLAG)) { | 821 | if (!(flags & GSS_C_INTEG_FLAG)) { |
804 | packet_start(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE); | 822 | if ((r = sshpkt_start(ssh, |
805 | packet_send(); | 823 | SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE)) != 0 || |
824 | (r = sshpkt_send(ssh)) != 0) | ||
825 | fatal("%s: %s", __func__, ssh_err(r)); | ||
806 | } else { | 826 | } else { |
807 | ssh_gssapi_buildmic(&b, authctxt->server_user, | 827 | struct sshbuf *b; |
828 | |||
829 | if ((b = sshbuf_new()) == NULL) | ||
830 | fatal("%s: sshbuf_new failed", __func__); | ||
831 | ssh_gssapi_buildmic(b, authctxt->server_user, | ||
808 | authctxt->service, "gssapi-with-mic"); | 832 | authctxt->service, "gssapi-with-mic"); |
809 | 833 | ||
810 | gssbuf.value = buffer_ptr(&b); | 834 | if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL) |
811 | gssbuf.length = buffer_len(&b); | 835 | fatal("%s: sshbuf_mutable_ptr failed", __func__); |
836 | gssbuf.length = sshbuf_len(b); | ||
812 | 837 | ||
813 | status = ssh_gssapi_sign(gssctxt, &gssbuf, &mic); | 838 | status = ssh_gssapi_sign(gssctxt, &gssbuf, &mic); |
814 | 839 | ||
815 | if (!GSS_ERROR(status)) { | 840 | if (!GSS_ERROR(status)) { |
816 | packet_start(SSH2_MSG_USERAUTH_GSSAPI_MIC); | 841 | if ((r = sshpkt_start(ssh, |
817 | packet_put_string(mic.value, mic.length); | 842 | SSH2_MSG_USERAUTH_GSSAPI_MIC)) != 0 || |
818 | 843 | (r = sshpkt_put_string(ssh, mic.value, | |
819 | packet_send(); | 844 | mic.length)) != 0 || |
845 | (r = sshpkt_send(ssh)) != 0) | ||
846 | fatal("%s: %s", __func__, ssh_err(r)); | ||
820 | } | 847 | } |
821 | 848 | ||
822 | buffer_free(&b); | 849 | sshbuf_free(b); |
823 | gss_release_buffer(&ms, &mic); | 850 | gss_release_buffer(&ms, &mic); |
824 | } | 851 | } |
825 | } | 852 | } |
@@ -833,39 +860,43 @@ input_gssapi_response(int type, u_int32_t plen, struct ssh *ssh) | |||
833 | { | 860 | { |
834 | Authctxt *authctxt = ssh->authctxt; | 861 | Authctxt *authctxt = ssh->authctxt; |
835 | Gssctxt *gssctxt; | 862 | Gssctxt *gssctxt; |
836 | u_int oidlen; | 863 | size_t oidlen; |
837 | u_char *oidv; | 864 | u_char *oidv = NULL; |
865 | int r; | ||
838 | 866 | ||
839 | if (authctxt == NULL) | 867 | if (authctxt == NULL) |
840 | fatal("input_gssapi_response: no authentication context"); | 868 | fatal("input_gssapi_response: no authentication context"); |
841 | gssctxt = authctxt->methoddata; | 869 | gssctxt = authctxt->methoddata; |
842 | 870 | ||
843 | /* Setup our OID */ | 871 | /* Setup our OID */ |
844 | oidv = packet_get_string(&oidlen); | 872 | if ((r = sshpkt_get_string(ssh, &oidv, &oidlen)) != 0) |
873 | goto done; | ||
845 | 874 | ||
846 | if (oidlen <= 2 || | 875 | if (oidlen <= 2 || |
847 | oidv[0] != SSH_GSS_OIDTYPE || | 876 | oidv[0] != SSH_GSS_OIDTYPE || |
848 | oidv[1] != oidlen - 2) { | 877 | oidv[1] != oidlen - 2) { |
849 | free(oidv); | ||
850 | debug("Badly encoded mechanism OID received"); | 878 | debug("Badly encoded mechanism OID received"); |
851 | userauth(authctxt, NULL); | 879 | userauth(authctxt, NULL); |
852 | return 0; | 880 | goto ok; |
853 | } | 881 | } |
854 | 882 | ||
855 | if (!ssh_gssapi_check_oid(gssctxt, oidv + 2, oidlen - 2)) | 883 | if (!ssh_gssapi_check_oid(gssctxt, oidv + 2, oidlen - 2)) |
856 | fatal("Server returned different OID than expected"); | 884 | fatal("Server returned different OID than expected"); |
857 | 885 | ||
858 | packet_check_eom(); | 886 | if ((r = sshpkt_get_end(ssh)) != 0) |
859 | 887 | goto done; | |
860 | free(oidv); | ||
861 | 888 | ||
862 | if (GSS_ERROR(process_gssapi_token(ssh, GSS_C_NO_BUFFER))) { | 889 | if (GSS_ERROR(process_gssapi_token(ssh, GSS_C_NO_BUFFER))) { |
863 | /* Start again with next method on list */ | 890 | /* Start again with next method on list */ |
864 | debug("Trying to start again"); | 891 | debug("Trying to start again"); |
865 | userauth(authctxt, NULL); | 892 | userauth(authctxt, NULL); |
866 | return 0; | 893 | goto ok; |
867 | } | 894 | } |
868 | return 0; | 895 | ok: |
896 | r = 0; | ||
897 | done: | ||
898 | free(oidv); | ||
899 | return r; | ||
869 | } | 900 | } |
870 | 901 | ||
871 | /* ARGSUSED */ | 902 | /* ARGSUSED */ |
@@ -874,27 +905,31 @@ input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh) | |||
874 | { | 905 | { |
875 | Authctxt *authctxt = ssh->authctxt; | 906 | Authctxt *authctxt = ssh->authctxt; |
876 | gss_buffer_desc recv_tok; | 907 | gss_buffer_desc recv_tok; |
908 | u_char *p = NULL; | ||
909 | size_t len; | ||
877 | OM_uint32 status; | 910 | OM_uint32 status; |
878 | u_int slen; | 911 | int r; |
879 | 912 | ||
880 | if (authctxt == NULL) | 913 | if (authctxt == NULL) |
881 | fatal("input_gssapi_response: no authentication context"); | 914 | fatal("input_gssapi_response: no authentication context"); |
882 | 915 | ||
883 | recv_tok.value = packet_get_string(&slen); | 916 | if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 || |
884 | recv_tok.length = slen; /* safe typecast */ | 917 | (r = sshpkt_get_end(ssh)) != 0) |
885 | 918 | goto out; | |
886 | packet_check_eom(); | ||
887 | 919 | ||
920 | recv_tok.value = p; | ||
921 | recv_tok.length = len; | ||
888 | status = process_gssapi_token(ssh, &recv_tok); | 922 | status = process_gssapi_token(ssh, &recv_tok); |
889 | 923 | ||
890 | free(recv_tok.value); | 924 | /* Start again with the next method in the list */ |
891 | |||
892 | if (GSS_ERROR(status)) { | 925 | if (GSS_ERROR(status)) { |
893 | /* Start again with the next method in the list */ | ||
894 | userauth(authctxt, NULL); | 926 | userauth(authctxt, NULL); |
895 | return 0; | 927 | /* ok */ |
896 | } | 928 | } |
897 | return 0; | 929 | r = 0; |
930 | out: | ||
931 | free(p); | ||
932 | return r; | ||
898 | } | 933 | } |
899 | 934 | ||
900 | /* ARGSUSED */ | 935 | /* ARGSUSED */ |
@@ -906,22 +941,26 @@ input_gssapi_errtok(int type, u_int32_t plen, struct ssh *ssh) | |||
906 | gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; | 941 | gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; |
907 | gss_buffer_desc recv_tok; | 942 | gss_buffer_desc recv_tok; |
908 | OM_uint32 ms; | 943 | OM_uint32 ms; |
909 | u_int len; | 944 | u_char *p = NULL; |
945 | size_t len; | ||
946 | int r; | ||
910 | 947 | ||
911 | if (authctxt == NULL) | 948 | if (authctxt == NULL) |
912 | fatal("input_gssapi_response: no authentication context"); | 949 | fatal("input_gssapi_response: no authentication context"); |
913 | gssctxt = authctxt->methoddata; | 950 | gssctxt = authctxt->methoddata; |
914 | 951 | ||
915 | recv_tok.value = packet_get_string(&len); | 952 | if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 || |
916 | recv_tok.length = len; | 953 | (r = sshpkt_get_end(ssh)) != 0) { |
917 | 954 | free(p); | |
918 | packet_check_eom(); | 955 | return r; |
956 | } | ||
919 | 957 | ||
920 | /* Stick it into GSSAPI and see what it says */ | 958 | /* Stick it into GSSAPI and see what it says */ |
959 | recv_tok.value = p; | ||
960 | recv_tok.length = len; | ||
921 | (void)ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds, | 961 | (void)ssh_gssapi_init_ctx(gssctxt, options.gss_deleg_creds, |
922 | &recv_tok, &send_tok, NULL); | 962 | &recv_tok, &send_tok, NULL); |
923 | 963 | free(p); | |
924 | free(recv_tok.value); | ||
925 | gss_release_buffer(&ms, &send_tok); | 964 | gss_release_buffer(&ms, &send_tok); |
926 | 965 | ||
927 | /* Server will be returning a failed packet after this one */ | 966 | /* Server will be returning a failed packet after this one */ |
@@ -932,29 +971,32 @@ input_gssapi_errtok(int type, u_int32_t plen, struct ssh *ssh) | |||
932 | int | 971 | int |
933 | input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh) | 972 | input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh) |
934 | { | 973 | { |
935 | char *msg; | 974 | char *msg = NULL; |
936 | char *lang; | 975 | char *lang = NULL; |
937 | 976 | int r; | |
938 | /* maj */(void)packet_get_int(); | ||
939 | /* min */(void)packet_get_int(); | ||
940 | msg=packet_get_string(NULL); | ||
941 | lang=packet_get_string(NULL); | ||
942 | |||
943 | packet_check_eom(); | ||
944 | 977 | ||
978 | if ((r = sshpkt_get_u32(ssh, NULL)) != 0 || /* maj */ | ||
979 | (r = sshpkt_get_u32(ssh, NULL)) != 0 || /* min */ | ||
980 | (r = sshpkt_get_cstring(ssh, &msg, NULL)) != 0 || | ||
981 | (r = sshpkt_get_cstring(ssh, &lang, NULL)) != 0) | ||
982 | goto out; | ||
983 | r = sshpkt_get_end(ssh); | ||
945 | debug("Server GSSAPI Error:\n%s", msg); | 984 | debug("Server GSSAPI Error:\n%s", msg); |
985 | out: | ||
946 | free(msg); | 986 | free(msg); |
947 | free(lang); | 987 | free(lang); |
948 | return 0; | 988 | return r; |
949 | } | 989 | } |
950 | 990 | ||
951 | int | 991 | int |
952 | userauth_gsskeyex(Authctxt *authctxt) | 992 | userauth_gsskeyex(Authctxt *authctxt) |
953 | { | 993 | { |
954 | Buffer b; | 994 | struct ssh *ssh = active_state; /* XXX */ |
995 | struct sshbuf *b; | ||
955 | gss_buffer_desc gssbuf; | 996 | gss_buffer_desc gssbuf; |
956 | gss_buffer_desc mic = GSS_C_EMPTY_BUFFER; | 997 | gss_buffer_desc mic = GSS_C_EMPTY_BUFFER; |
957 | OM_uint32 ms; | 998 | OM_uint32 ms; |
999 | int r; | ||
958 | 1000 | ||
959 | static int attempt = 0; | 1001 | static int attempt = 0; |
960 | if (attempt++ >= 1) | 1002 | if (attempt++ >= 1) |
@@ -965,25 +1007,29 @@ userauth_gsskeyex(Authctxt *authctxt) | |||
965 | return (0); | 1007 | return (0); |
966 | } | 1008 | } |
967 | 1009 | ||
968 | ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service, | 1010 | if ((b = sshbuf_new()) == NULL) |
1011 | fatal("%s: sshbuf_new failed", __func__); | ||
1012 | ssh_gssapi_buildmic(b, authctxt->server_user, authctxt->service, | ||
969 | "gssapi-keyex"); | 1013 | "gssapi-keyex"); |
970 | 1014 | ||
971 | gssbuf.value = buffer_ptr(&b); | 1015 | if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL) |
972 | gssbuf.length = buffer_len(&b); | 1016 | fatal("%s: sshbuf_mutable_ptr failed", __func__); |
1017 | gssbuf.length = sshbuf_len(b); | ||
973 | 1018 | ||
974 | if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) { | 1019 | if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) { |
975 | buffer_free(&b); | 1020 | sshbuf_free(b); |
976 | return (0); | 1021 | return (0); |
977 | } | 1022 | } |
978 | 1023 | ||
979 | packet_start(SSH2_MSG_USERAUTH_REQUEST); | 1024 | if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || |
980 | packet_put_cstring(authctxt->server_user); | 1025 | (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || |
981 | packet_put_cstring(authctxt->service); | 1026 | (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || |
982 | packet_put_cstring(authctxt->method->name); | 1027 | (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || |
983 | packet_put_string(mic.value, mic.length); | 1028 | (r = sshpkt_put_string(ssh, mic.value, mic.length)) != 0 || |
984 | packet_send(); | 1029 | (r = sshpkt_send(ssh)) != 0) |
1030 | fatal("%s: %s", __func__, ssh_err(r)); | ||
985 | 1031 | ||
986 | buffer_free(&b); | 1032 | sshbuf_free(b); |
987 | gss_release_buffer(&ms, &mic); | 1033 | gss_release_buffer(&ms, &mic); |
988 | 1034 | ||
989 | return (1); | 1035 | return (1); |
@@ -994,23 +1040,29 @@ userauth_gsskeyex(Authctxt *authctxt) | |||
994 | int | 1040 | int |
995 | userauth_none(Authctxt *authctxt) | 1041 | userauth_none(Authctxt *authctxt) |
996 | { | 1042 | { |
1043 | struct ssh *ssh = active_state; /* XXX */ | ||
1044 | int r; | ||
1045 | |||
997 | /* initial userauth request */ | 1046 | /* initial userauth request */ |
998 | packet_start(SSH2_MSG_USERAUTH_REQUEST); | 1047 | if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || |
999 | packet_put_cstring(authctxt->server_user); | 1048 | (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || |
1000 | packet_put_cstring(authctxt->service); | 1049 | (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || |
1001 | packet_put_cstring(authctxt->method->name); | 1050 | (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || |
1002 | packet_send(); | 1051 | (r = sshpkt_send(ssh)) != 0) |
1052 | fatal("%s: %s", __func__, ssh_err(r)); | ||
1003 | return 1; | 1053 | return 1; |
1004 | } | 1054 | } |
1005 | 1055 | ||
1006 | int | 1056 | int |
1007 | userauth_passwd(Authctxt *authctxt) | 1057 | userauth_passwd(Authctxt *authctxt) |
1008 | { | 1058 | { |
1059 | struct ssh *ssh = active_state; /* XXX */ | ||
1009 | static int attempt = 0; | 1060 | static int attempt = 0; |
1010 | char prompt[256]; | 1061 | char prompt[256]; |
1011 | char *password; | 1062 | char *password; |
1012 | const char *host = options.host_key_alias ? options.host_key_alias : | 1063 | const char *host = options.host_key_alias ? options.host_key_alias : |
1013 | authctxt->host; | 1064 | authctxt->host; |
1065 | int r; | ||
1014 | 1066 | ||
1015 | if (attempt++ >= options.number_of_password_prompts) | 1067 | if (attempt++ >= options.number_of_password_prompts) |
1016 | return 0; | 1068 | return 0; |
@@ -1021,18 +1073,20 @@ userauth_passwd(Authctxt *authctxt) | |||
1021 | snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ", | 1073 | snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ", |
1022 | authctxt->server_user, host); | 1074 | authctxt->server_user, host); |
1023 | password = read_passphrase(prompt, 0); | 1075 | password = read_passphrase(prompt, 0); |
1024 | packet_start(SSH2_MSG_USERAUTH_REQUEST); | 1076 | if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || |
1025 | packet_put_cstring(authctxt->server_user); | 1077 | (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || |
1026 | packet_put_cstring(authctxt->service); | 1078 | (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || |
1027 | packet_put_cstring(authctxt->method->name); | 1079 | (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || |
1028 | packet_put_char(0); | 1080 | (r = sshpkt_put_u8(ssh, 0)) != 0 || |
1029 | packet_put_cstring(password); | 1081 | (r = sshpkt_put_cstring(ssh, password)) != 0 || |
1030 | explicit_bzero(password, strlen(password)); | 1082 | (r = sshpkt_add_padding(ssh, 64)) != 0 || |
1031 | free(password); | 1083 | (r = sshpkt_send(ssh)) != 0) |
1032 | packet_add_padding(64); | 1084 | fatal("%s: %s", __func__, ssh_err(r)); |
1033 | packet_send(); | 1085 | |
1034 | 1086 | if (password) | |
1035 | dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, | 1087 | freezero(password, strlen(password)); |
1088 | |||
1089 | ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, | ||
1036 | &input_userauth_passwd_changereq); | 1090 | &input_userauth_passwd_changereq); |
1037 | 1091 | ||
1038 | return 1; | 1092 | return 1; |
@@ -1046,9 +1100,10 @@ int | |||
1046 | input_userauth_passwd_changereq(int type, u_int32_t seqnr, struct ssh *ssh) | 1100 | input_userauth_passwd_changereq(int type, u_int32_t seqnr, struct ssh *ssh) |
1047 | { | 1101 | { |
1048 | Authctxt *authctxt = ssh->authctxt; | 1102 | Authctxt *authctxt = ssh->authctxt; |
1049 | char *info, *lang, *password = NULL, *retype = NULL; | 1103 | char *info = NULL, *lang = NULL, *password = NULL, *retype = NULL; |
1050 | char prompt[256]; | 1104 | char prompt[256]; |
1051 | const char *host; | 1105 | const char *host; |
1106 | int r; | ||
1052 | 1107 | ||
1053 | debug2("input_userauth_passwd_changereq"); | 1108 | debug2("input_userauth_passwd_changereq"); |
1054 | 1109 | ||
@@ -1057,24 +1112,26 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, struct ssh *ssh) | |||
1057 | "no authentication context"); | 1112 | "no authentication context"); |
1058 | host = options.host_key_alias ? options.host_key_alias : authctxt->host; | 1113 | host = options.host_key_alias ? options.host_key_alias : authctxt->host; |
1059 | 1114 | ||
1060 | info = packet_get_string(NULL); | 1115 | if ((r = sshpkt_get_cstring(ssh, &info, NULL)) != 0 || |
1061 | lang = packet_get_string(NULL); | 1116 | (r = sshpkt_get_cstring(ssh, &lang, NULL)) != 0) |
1117 | goto out; | ||
1062 | if (strlen(info) > 0) | 1118 | if (strlen(info) > 0) |
1063 | logit("%s", info); | 1119 | logit("%s", info); |
1064 | free(info); | 1120 | if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || |
1065 | free(lang); | 1121 | (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || |
1066 | packet_start(SSH2_MSG_USERAUTH_REQUEST); | 1122 | (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || |
1067 | packet_put_cstring(authctxt->server_user); | 1123 | (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || |
1068 | packet_put_cstring(authctxt->service); | 1124 | (r = sshpkt_put_u8(ssh, 1)) != 0) /* additional info */ |
1069 | packet_put_cstring(authctxt->method->name); | 1125 | goto out; |
1070 | packet_put_char(1); /* additional info */ | 1126 | |
1071 | snprintf(prompt, sizeof(prompt), | 1127 | snprintf(prompt, sizeof(prompt), |
1072 | "Enter %.30s@%.128s's old password: ", | 1128 | "Enter %.30s@%.128s's old password: ", |
1073 | authctxt->server_user, host); | 1129 | authctxt->server_user, host); |
1074 | password = read_passphrase(prompt, 0); | 1130 | password = read_passphrase(prompt, 0); |
1075 | packet_put_cstring(password); | 1131 | if ((r = sshpkt_put_cstring(ssh, password)) != 0) |
1076 | explicit_bzero(password, strlen(password)); | 1132 | goto out; |
1077 | free(password); | 1133 | |
1134 | freezero(password, strlen(password)); | ||
1078 | password = NULL; | 1135 | password = NULL; |
1079 | while (password == NULL) { | 1136 | while (password == NULL) { |
1080 | snprintf(prompt, sizeof(prompt), | 1137 | snprintf(prompt, sizeof(prompt), |
@@ -1083,99 +1140,113 @@ input_userauth_passwd_changereq(int type, u_int32_t seqnr, struct ssh *ssh) | |||
1083 | password = read_passphrase(prompt, RP_ALLOW_EOF); | 1140 | password = read_passphrase(prompt, RP_ALLOW_EOF); |
1084 | if (password == NULL) { | 1141 | if (password == NULL) { |
1085 | /* bail out */ | 1142 | /* bail out */ |
1086 | return 0; | 1143 | r = 0; |
1144 | goto out; | ||
1087 | } | 1145 | } |
1088 | snprintf(prompt, sizeof(prompt), | 1146 | snprintf(prompt, sizeof(prompt), |
1089 | "Retype %.30s@%.128s's new password: ", | 1147 | "Retype %.30s@%.128s's new password: ", |
1090 | authctxt->server_user, host); | 1148 | authctxt->server_user, host); |
1091 | retype = read_passphrase(prompt, 0); | 1149 | retype = read_passphrase(prompt, 0); |
1092 | if (strcmp(password, retype) != 0) { | 1150 | if (strcmp(password, retype) != 0) { |
1093 | explicit_bzero(password, strlen(password)); | 1151 | freezero(password, strlen(password)); |
1094 | free(password); | ||
1095 | logit("Mismatch; try again, EOF to quit."); | 1152 | logit("Mismatch; try again, EOF to quit."); |
1096 | password = NULL; | 1153 | password = NULL; |
1097 | } | 1154 | } |
1098 | explicit_bzero(retype, strlen(retype)); | 1155 | freezero(retype, strlen(retype)); |
1099 | free(retype); | ||
1100 | } | 1156 | } |
1101 | packet_put_cstring(password); | 1157 | if ((r = sshpkt_put_cstring(ssh, password)) != 0 || |
1102 | explicit_bzero(password, strlen(password)); | 1158 | (r = sshpkt_add_padding(ssh, 64)) != 0 || |
1103 | free(password); | 1159 | (r = sshpkt_send(ssh)) != 0) |
1104 | packet_add_padding(64); | 1160 | goto out; |
1105 | packet_send(); | ||
1106 | 1161 | ||
1107 | dispatch_set(SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, | 1162 | ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, |
1108 | &input_userauth_passwd_changereq); | 1163 | &input_userauth_passwd_changereq); |
1109 | return 0; | 1164 | r = 0; |
1110 | } | 1165 | out: |
1111 | 1166 | if (password) | |
1112 | static const char * | 1167 | freezero(password, strlen(password)); |
1113 | key_sign_encode(const struct sshkey *key) | 1168 | free(info); |
1114 | { | 1169 | free(lang); |
1115 | struct ssh *ssh = active_state; | 1170 | return r; |
1116 | |||
1117 | if (key->type == KEY_RSA) { | ||
1118 | switch (ssh->kex->rsa_sha2) { | ||
1119 | case 256: | ||
1120 | return "rsa-sha2-256"; | ||
1121 | case 512: | ||
1122 | return "rsa-sha2-512"; | ||
1123 | } | ||
1124 | } | ||
1125 | return key_ssh_name(key); | ||
1126 | } | 1171 | } |
1127 | 1172 | ||
1128 | /* | 1173 | /* |
1129 | * Some agents will return ssh-rsa signatures when asked to make a | 1174 | * Select an algorithm for publickey signatures. |
1130 | * rsa-sha2-* signature. Check what they actually gave back and warn the | 1175 | * Returns algorithm (caller must free) or NULL if no mutual algorithm found. |
1131 | * user if the agent has returned an unexpected type. | 1176 | * |
1177 | * Call with ssh==NULL to ignore server-sig-algs extension list and | ||
1178 | * only attempt with the key's base signature type. | ||
1132 | */ | 1179 | */ |
1133 | static int | 1180 | static char * |
1134 | check_sigtype(const struct sshkey *key, const u_char *sig, size_t len) | 1181 | key_sig_algorithm(struct ssh *ssh, const struct sshkey *key) |
1135 | { | 1182 | { |
1136 | int r; | 1183 | char *allowed, *oallowed, *cp, *tmp, *alg = NULL; |
1137 | char *sigtype = NULL; | ||
1138 | const char *alg = key_sign_encode(key); | ||
1139 | 1184 | ||
1140 | if (sshkey_is_cert(key)) | 1185 | /* |
1141 | return 0; | 1186 | * The signature algorithm will only differ from the key algorithm |
1142 | if ((r = sshkey_sigtype(sig, len, &sigtype)) != 0) | 1187 | * for RSA keys/certs and when the server advertises support for |
1143 | return r; | 1188 | * newer (SHA2) algorithms. |
1144 | if (strcmp(sigtype, alg) != 0) { | 1189 | */ |
1145 | logit("warning: agent returned different signature type %s " | 1190 | if (ssh == NULL || ssh->kex->server_sig_algs == NULL || |
1146 | "(expected %s)", sigtype, alg); | 1191 | (key->type != KEY_RSA && key->type != KEY_RSA_CERT)) { |
1192 | /* Filter base key signature alg against our configuration */ | ||
1193 | return match_list(sshkey_ssh_name(key), | ||
1194 | options.pubkey_key_types, NULL); | ||
1147 | } | 1195 | } |
1148 | free(sigtype); | 1196 | |
1149 | /* Incorrect signature types aren't an error ... yet */ | 1197 | /* |
1150 | return 0; | 1198 | * For RSA keys/certs, since these might have a different sig type: |
1199 | * find the first entry in PubkeyAcceptedKeyTypes of the right type | ||
1200 | * that also appears in the supported signature algorithms list from | ||
1201 | * the server. | ||
1202 | */ | ||
1203 | oallowed = allowed = xstrdup(options.pubkey_key_types); | ||
1204 | while ((cp = strsep(&allowed, ",")) != NULL) { | ||
1205 | if (sshkey_type_from_name(cp) != key->type) | ||
1206 | continue; | ||
1207 | tmp = match_list(sshkey_sigalg_by_name(cp), ssh->kex->server_sig_algs, NULL); | ||
1208 | if (tmp != NULL) | ||
1209 | alg = xstrdup(cp); | ||
1210 | free(tmp); | ||
1211 | if (alg != NULL) | ||
1212 | break; | ||
1213 | } | ||
1214 | free(oallowed); | ||
1215 | return alg; | ||
1151 | } | 1216 | } |
1152 | 1217 | ||
1153 | static int | 1218 | static int |
1154 | identity_sign(struct identity *id, u_char **sigp, size_t *lenp, | 1219 | identity_sign(struct identity *id, u_char **sigp, size_t *lenp, |
1155 | const u_char *data, size_t datalen, u_int compat) | 1220 | const u_char *data, size_t datalen, u_int compat, const char *alg) |
1156 | { | 1221 | { |
1157 | struct sshkey *prv; | 1222 | struct sshkey *prv; |
1158 | int r; | 1223 | int r; |
1159 | 1224 | ||
1160 | /* the agent supports this key */ | 1225 | /* The agent supports this key. */ |
1161 | if (id->key != NULL && id->agent_fd != -1) { | 1226 | if (id->key != NULL && id->agent_fd != -1) { |
1162 | if ((r = ssh_agent_sign(id->agent_fd, id->key, sigp, lenp, | 1227 | return ssh_agent_sign(id->agent_fd, id->key, sigp, lenp, |
1163 | data, datalen, key_sign_encode(id->key), compat)) != 0 || | 1228 | data, datalen, alg, compat); |
1164 | (r = check_sigtype(id->key, *sigp, *lenp)) != 0) | ||
1165 | return r; | ||
1166 | return 0; | ||
1167 | } | 1229 | } |
1168 | 1230 | ||
1169 | /* | 1231 | /* |
1170 | * we have already loaded the private key or | 1232 | * We have already loaded the private key or the private key is |
1171 | * the private key is stored in external hardware | 1233 | * stored in external hardware. |
1172 | */ | 1234 | */ |
1173 | if (id->key != NULL && | 1235 | if (id->key != NULL && |
1174 | (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT))) | 1236 | (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT))) { |
1175 | return (sshkey_sign(id->key, sigp, lenp, data, datalen, | 1237 | if ((r = sshkey_sign(id->key, sigp, lenp, data, datalen, |
1176 | key_sign_encode(id->key), compat)); | 1238 | alg, compat)) != 0) |
1239 | return r; | ||
1240 | /* | ||
1241 | * PKCS#11 tokens may not support all signature algorithms, | ||
1242 | * so check what we get back. | ||
1243 | */ | ||
1244 | if ((r = sshkey_check_sigtype(*sigp, *lenp, alg)) != 0) | ||
1245 | return r; | ||
1246 | return 0; | ||
1247 | } | ||
1177 | 1248 | ||
1178 | /* load the private key from the file */ | 1249 | /* Load the private key from the file. */ |
1179 | if ((prv = load_identity_file(id)) == NULL) | 1250 | if ((prv = load_identity_file(id)) == NULL) |
1180 | return SSH_ERR_KEY_NOT_FOUND; | 1251 | return SSH_ERR_KEY_NOT_FOUND; |
1181 | if (id->key != NULL && !sshkey_equal_public(prv, id->key)) { | 1252 | if (id->key != NULL && !sshkey_equal_public(prv, id->key)) { |
@@ -1183,8 +1254,7 @@ identity_sign(struct identity *id, u_char **sigp, size_t *lenp, | |||
1183 | __func__, id->filename); | 1254 | __func__, id->filename); |
1184 | return SSH_ERR_KEY_NOT_FOUND; | 1255 | return SSH_ERR_KEY_NOT_FOUND; |
1185 | } | 1256 | } |
1186 | r = sshkey_sign(prv, sigp, lenp, data, datalen, | 1257 | r = sshkey_sign(prv, sigp, lenp, data, datalen, alg, compat); |
1187 | key_sign_encode(prv), compat); | ||
1188 | sshkey_free(prv); | 1258 | sshkey_free(prv); |
1189 | return r; | 1259 | return r; |
1190 | } | 1260 | } |
@@ -1209,57 +1279,35 @@ id_filename_matches(Identity *id, Identity *private_id) | |||
1209 | } | 1279 | } |
1210 | 1280 | ||
1211 | static int | 1281 | static int |
1212 | sign_and_send_pubkey(Authctxt *authctxt, Identity *id) | 1282 | sign_and_send_pubkey(struct ssh *ssh, Authctxt *authctxt, Identity *id) |
1213 | { | 1283 | { |
1214 | Buffer b; | 1284 | struct sshbuf *b = NULL; |
1215 | Identity *private_id; | 1285 | Identity *private_id, *sign_id = NULL; |
1216 | u_char *blob, *signature; | 1286 | u_char *signature = NULL; |
1217 | size_t slen; | 1287 | size_t slen = 0, skip = 0; |
1218 | u_int bloblen, skip = 0; | 1288 | int r, fallback_sigtype, sent = 0; |
1219 | int matched, ret = -1, have_sig = 1; | 1289 | char *alg = NULL, *fp = NULL; |
1220 | char *fp; | 1290 | const char *loc = ""; |
1221 | 1291 | ||
1222 | if ((fp = sshkey_fingerprint(id->key, options.fingerprint_hash, | 1292 | if ((fp = sshkey_fingerprint(id->key, options.fingerprint_hash, |
1223 | SSH_FP_DEFAULT)) == NULL) | 1293 | SSH_FP_DEFAULT)) == NULL) |
1224 | return 0; | 1294 | return 0; |
1225 | debug3("%s: %s %s", __func__, key_type(id->key), fp); | ||
1226 | free(fp); | ||
1227 | 1295 | ||
1228 | if (key_to_blob(id->key, &blob, &bloblen) == 0) { | 1296 | debug3("%s: %s %s", __func__, sshkey_type(id->key), fp); |
1229 | /* we cannot handle this key */ | ||
1230 | debug3("sign_and_send_pubkey: cannot handle key"); | ||
1231 | return 0; | ||
1232 | } | ||
1233 | /* data to be signed */ | ||
1234 | buffer_init(&b); | ||
1235 | if (datafellows & SSH_OLD_SESSIONID) { | ||
1236 | buffer_append(&b, session_id2, session_id2_len); | ||
1237 | skip = session_id2_len; | ||
1238 | } else { | ||
1239 | buffer_put_string(&b, session_id2, session_id2_len); | ||
1240 | skip = buffer_len(&b); | ||
1241 | } | ||
1242 | buffer_put_char(&b, SSH2_MSG_USERAUTH_REQUEST); | ||
1243 | buffer_put_cstring(&b, authctxt->server_user); | ||
1244 | buffer_put_cstring(&b, authctxt->service); | ||
1245 | buffer_put_cstring(&b, authctxt->method->name); | ||
1246 | buffer_put_char(&b, have_sig); | ||
1247 | buffer_put_cstring(&b, key_sign_encode(id->key)); | ||
1248 | buffer_put_string(&b, blob, bloblen); | ||
1249 | 1297 | ||
1250 | /* | 1298 | /* |
1251 | * If the key is an certificate, try to find a matching private key | 1299 | * If the key is an certificate, try to find a matching private key |
1252 | * and use it to complete the signature. | 1300 | * and use it to complete the signature. |
1253 | * If no such private key exists, fall back to trying the certificate | 1301 | * If no such private key exists, fall back to trying the certificate |
1254 | * key itself in case it has a private half already loaded. | 1302 | * key itself in case it has a private half already loaded. |
1303 | * This will try to set sign_id to the private key that will perform | ||
1304 | * the signature. | ||
1255 | */ | 1305 | */ |
1256 | if (key_is_cert(id->key)) { | 1306 | if (sshkey_is_cert(id->key)) { |
1257 | matched = 0; | ||
1258 | TAILQ_FOREACH(private_id, &authctxt->keys, next) { | 1307 | TAILQ_FOREACH(private_id, &authctxt->keys, next) { |
1259 | if (sshkey_equal_public(id->key, private_id->key) && | 1308 | if (sshkey_equal_public(id->key, private_id->key) && |
1260 | id->key->type != private_id->key->type) { | 1309 | id->key->type != private_id->key->type) { |
1261 | id = private_id; | 1310 | sign_id = private_id; |
1262 | matched = 1; | ||
1263 | break; | 1311 | break; |
1264 | } | 1312 | } |
1265 | } | 1313 | } |
@@ -1270,18 +1318,18 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id) | |||
1270 | * of keeping just a private key file and public | 1318 | * of keeping just a private key file and public |
1271 | * certificate on disk. | 1319 | * certificate on disk. |
1272 | */ | 1320 | */ |
1273 | if (!matched && !id->isprivate && id->agent_fd == -1 && | 1321 | if (sign_id == NULL && |
1322 | !id->isprivate && id->agent_fd == -1 && | ||
1274 | (id->key->flags & SSHKEY_FLAG_EXT) == 0) { | 1323 | (id->key->flags & SSHKEY_FLAG_EXT) == 0) { |
1275 | TAILQ_FOREACH(private_id, &authctxt->keys, next) { | 1324 | TAILQ_FOREACH(private_id, &authctxt->keys, next) { |
1276 | if (private_id->key == NULL && | 1325 | if (private_id->key == NULL && |
1277 | id_filename_matches(id, private_id)) { | 1326 | id_filename_matches(id, private_id)) { |
1278 | id = private_id; | 1327 | sign_id = private_id; |
1279 | matched = 1; | ||
1280 | break; | 1328 | break; |
1281 | } | 1329 | } |
1282 | } | 1330 | } |
1283 | } | 1331 | } |
1284 | if (matched) { | 1332 | if (sign_id != NULL) { |
1285 | debug2("%s: using private key \"%s\"%s for " | 1333 | debug2("%s: using private key \"%s\"%s for " |
1286 | "certificate", __func__, id->filename, | 1334 | "certificate", __func__, id->filename, |
1287 | id->agent_fd != -1 ? " from agent" : ""); | 1335 | id->agent_fd != -1 ? " from agent" : ""); |
@@ -1291,65 +1339,141 @@ sign_and_send_pubkey(Authctxt *authctxt, Identity *id) | |||
1291 | } | 1339 | } |
1292 | } | 1340 | } |
1293 | 1341 | ||
1294 | /* generate signature */ | 1342 | /* |
1295 | ret = identity_sign(id, &signature, &slen, | 1343 | * If the above didn't select another identity to do the signing |
1296 | buffer_ptr(&b), buffer_len(&b), datafellows); | 1344 | * then default to the one we started with. |
1297 | if (ret != 0) { | 1345 | */ |
1298 | if (ret != SSH_ERR_KEY_NOT_FOUND) | 1346 | if (sign_id == NULL) |
1299 | error("%s: signing failed: %s", __func__, ssh_err(ret)); | 1347 | sign_id = id; |
1300 | free(blob); | 1348 | |
1301 | buffer_free(&b); | 1349 | /* assemble and sign data */ |
1302 | return 0; | 1350 | for (fallback_sigtype = 0; fallback_sigtype <= 1; fallback_sigtype++) { |
1351 | free(alg); | ||
1352 | slen = 0; | ||
1353 | signature = NULL; | ||
1354 | if ((alg = key_sig_algorithm(fallback_sigtype ? NULL : ssh, | ||
1355 | id->key)) == NULL) { | ||
1356 | error("%s: no mutual signature supported", __func__); | ||
1357 | goto out; | ||
1358 | } | ||
1359 | debug3("%s: signing using %s", __func__, alg); | ||
1360 | |||
1361 | sshbuf_free(b); | ||
1362 | if ((b = sshbuf_new()) == NULL) | ||
1363 | fatal("%s: sshbuf_new failed", __func__); | ||
1364 | if (datafellows & SSH_OLD_SESSIONID) { | ||
1365 | if ((r = sshbuf_put(b, session_id2, | ||
1366 | session_id2_len)) != 0) { | ||
1367 | fatal("%s: sshbuf_put: %s", | ||
1368 | __func__, ssh_err(r)); | ||
1369 | } | ||
1370 | } else { | ||
1371 | if ((r = sshbuf_put_string(b, session_id2, | ||
1372 | session_id2_len)) != 0) { | ||
1373 | fatal("%s: sshbuf_put_string: %s", | ||
1374 | __func__, ssh_err(r)); | ||
1375 | } | ||
1376 | } | ||
1377 | skip = sshbuf_len(b); | ||
1378 | if ((r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 || | ||
1379 | (r = sshbuf_put_cstring(b, authctxt->server_user)) != 0 || | ||
1380 | (r = sshbuf_put_cstring(b, authctxt->service)) != 0 || | ||
1381 | (r = sshbuf_put_cstring(b, authctxt->method->name)) != 0 || | ||
1382 | (r = sshbuf_put_u8(b, 1)) != 0 || | ||
1383 | (r = sshbuf_put_cstring(b, alg)) != 0 || | ||
1384 | (r = sshkey_puts(id->key, b)) != 0) { | ||
1385 | fatal("%s: assemble signed data: %s", | ||
1386 | __func__, ssh_err(r)); | ||
1387 | } | ||
1388 | |||
1389 | /* generate signature */ | ||
1390 | r = identity_sign(sign_id, &signature, &slen, | ||
1391 | sshbuf_ptr(b), sshbuf_len(b), datafellows, alg); | ||
1392 | if (r == 0) | ||
1393 | break; | ||
1394 | else if (r == SSH_ERR_KEY_NOT_FOUND) | ||
1395 | goto out; /* soft failure */ | ||
1396 | else if (r == SSH_ERR_SIGN_ALG_UNSUPPORTED && | ||
1397 | !fallback_sigtype) { | ||
1398 | if (sign_id->agent_fd != -1) | ||
1399 | loc = "agent "; | ||
1400 | else if ((sign_id->key->flags & SSHKEY_FLAG_EXT) != 0) | ||
1401 | loc = "token "; | ||
1402 | logit("%skey %s %s returned incorrect signature type", | ||
1403 | loc, sshkey_type(id->key), fp); | ||
1404 | continue; | ||
1405 | } | ||
1406 | error("%s: signing failed: %s", __func__, ssh_err(r)); | ||
1407 | goto out; | ||
1303 | } | 1408 | } |
1304 | #ifdef DEBUG_PK | 1409 | if (slen == 0 || signature == NULL) /* shouldn't happen */ |
1305 | buffer_dump(&b); | 1410 | fatal("%s: no signature", __func__); |
1306 | #endif | ||
1307 | free(blob); | ||
1308 | 1411 | ||
1309 | /* append signature */ | 1412 | /* append signature */ |
1310 | buffer_put_string(&b, signature, slen); | 1413 | if ((r = sshbuf_put_string(b, signature, slen)) != 0) |
1311 | free(signature); | 1414 | fatal("%s: append signature: %s", __func__, ssh_err(r)); |
1312 | 1415 | ||
1416 | #ifdef DEBUG_PK | ||
1417 | sshbuf_dump(b, stderr); | ||
1418 | #endif | ||
1313 | /* skip session id and packet type */ | 1419 | /* skip session id and packet type */ |
1314 | if (buffer_len(&b) < skip + 1) | 1420 | if ((r = sshbuf_consume(b, skip + 1)) != 0) |
1315 | fatal("userauth_pubkey: internal error"); | 1421 | fatal("%s: consume: %s", __func__, ssh_err(r)); |
1316 | buffer_consume(&b, skip + 1); | ||
1317 | 1422 | ||
1318 | /* put remaining data from buffer into packet */ | 1423 | /* put remaining data from buffer into packet */ |
1319 | packet_start(SSH2_MSG_USERAUTH_REQUEST); | 1424 | if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || |
1320 | packet_put_raw(buffer_ptr(&b), buffer_len(&b)); | 1425 | (r = sshpkt_putb(ssh, b)) != 0 || |
1321 | buffer_free(&b); | 1426 | (r = sshpkt_send(ssh)) != 0) |
1322 | packet_send(); | 1427 | fatal("%s: enqueue request: %s", __func__, ssh_err(r)); |
1323 | 1428 | ||
1324 | return 1; | 1429 | /* success */ |
1430 | sent = 1; | ||
1431 | |||
1432 | out: | ||
1433 | free(fp); | ||
1434 | free(alg); | ||
1435 | sshbuf_free(b); | ||
1436 | freezero(signature, slen); | ||
1437 | return sent; | ||
1325 | } | 1438 | } |
1326 | 1439 | ||
1327 | static int | 1440 | static int |
1328 | send_pubkey_test(Authctxt *authctxt, Identity *id) | 1441 | send_pubkey_test(struct ssh *ssh, Authctxt *authctxt, Identity *id) |
1329 | { | 1442 | { |
1330 | u_char *blob; | 1443 | u_char *blob = NULL; |
1331 | u_int bloblen, have_sig = 0; | 1444 | char *alg = NULL; |
1332 | 1445 | size_t bloblen; | |
1333 | debug3("send_pubkey_test"); | 1446 | u_int have_sig = 0; |
1447 | int sent = 0, r; | ||
1448 | |||
1449 | if ((alg = key_sig_algorithm(ssh, id->key)) == NULL) { | ||
1450 | debug("%s: no mutual signature algorithm", __func__); | ||
1451 | goto out; | ||
1452 | } | ||
1334 | 1453 | ||
1335 | if (key_to_blob(id->key, &blob, &bloblen) == 0) { | 1454 | if ((r = sshkey_to_blob(id->key, &blob, &bloblen)) != 0) { |
1336 | /* we cannot handle this key */ | 1455 | /* we cannot handle this key */ |
1337 | debug3("send_pubkey_test: cannot handle key"); | 1456 | debug3("%s: cannot handle key", __func__); |
1338 | return 0; | 1457 | goto out; |
1339 | } | 1458 | } |
1340 | /* register callback for USERAUTH_PK_OK message */ | 1459 | /* register callback for USERAUTH_PK_OK message */ |
1341 | dispatch_set(SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok); | 1460 | ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_PK_OK, &input_userauth_pk_ok); |
1342 | 1461 | ||
1343 | packet_start(SSH2_MSG_USERAUTH_REQUEST); | 1462 | if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || |
1344 | packet_put_cstring(authctxt->server_user); | 1463 | (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || |
1345 | packet_put_cstring(authctxt->service); | 1464 | (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || |
1346 | packet_put_cstring(authctxt->method->name); | 1465 | (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || |
1347 | packet_put_char(have_sig); | 1466 | (r = sshpkt_put_u8(ssh, have_sig)) != 0 || |
1348 | packet_put_cstring(key_sign_encode(id->key)); | 1467 | (r = sshpkt_put_cstring(ssh, alg)) != 0 || |
1349 | packet_put_string(blob, bloblen); | 1468 | (r = sshpkt_put_string(ssh, blob, bloblen)) != 0 || |
1469 | (r = sshpkt_send(ssh)) != 0) | ||
1470 | fatal("%s: %s", __func__, ssh_err(r)); | ||
1471 | sent = 1; | ||
1472 | |||
1473 | out: | ||
1474 | free(alg); | ||
1350 | free(blob); | 1475 | free(blob); |
1351 | packet_send(); | 1476 | return sent; |
1352 | return 1; | ||
1353 | } | 1477 | } |
1354 | 1478 | ||
1355 | static struct sshkey * | 1479 | static struct sshkey * |
@@ -1407,10 +1531,8 @@ load_identity_file(Identity *id) | |||
1407 | !(id->key && id->isprivate)) | 1531 | !(id->key && id->isprivate)) |
1408 | maybe_add_key_to_agent(id->filename, private, comment, | 1532 | maybe_add_key_to_agent(id->filename, private, comment, |
1409 | passphrase); | 1533 | passphrase); |
1410 | if (i > 0) { | 1534 | if (i > 0) |
1411 | explicit_bzero(passphrase, strlen(passphrase)); | 1535 | freezero(passphrase, strlen(passphrase)); |
1412 | free(passphrase); | ||
1413 | } | ||
1414 | free(comment); | 1536 | free(comment); |
1415 | if (private != NULL || quit) | 1537 | if (private != NULL || quit) |
1416 | break; | 1538 | break; |
@@ -1418,6 +1540,36 @@ load_identity_file(Identity *id) | |||
1418 | return private; | 1540 | return private; |
1419 | } | 1541 | } |
1420 | 1542 | ||
1543 | static int | ||
1544 | key_type_allowed_by_config(struct sshkey *key) | ||
1545 | { | ||
1546 | if (match_pattern_list(sshkey_ssh_name(key), | ||
1547 | options.pubkey_key_types, 0) == 1) | ||
1548 | return 1; | ||
1549 | |||
1550 | /* RSA keys/certs might be allowed by alternate signature types */ | ||
1551 | switch (key->type) { | ||
1552 | case KEY_RSA: | ||
1553 | if (match_pattern_list("rsa-sha2-512", | ||
1554 | options.pubkey_key_types, 0) == 1) | ||
1555 | return 1; | ||
1556 | if (match_pattern_list("rsa-sha2-256", | ||
1557 | options.pubkey_key_types, 0) == 1) | ||
1558 | return 1; | ||
1559 | break; | ||
1560 | case KEY_RSA_CERT: | ||
1561 | if (match_pattern_list("rsa-sha2-512-cert-v01@openssh.com", | ||
1562 | options.pubkey_key_types, 0) == 1) | ||
1563 | return 1; | ||
1564 | if (match_pattern_list("rsa-sha2-256-cert-v01@openssh.com", | ||
1565 | options.pubkey_key_types, 0) == 1) | ||
1566 | return 1; | ||
1567 | break; | ||
1568 | } | ||
1569 | return 0; | ||
1570 | } | ||
1571 | |||
1572 | |||
1421 | /* | 1573 | /* |
1422 | * try keys in the following order: | 1574 | * try keys in the following order: |
1423 | * 1. certificates listed in the config file | 1575 | * 1. certificates listed in the config file |
@@ -1457,7 +1609,7 @@ pubkey_prepare(Authctxt *authctxt) | |||
1457 | /* list of certificates specified by user */ | 1609 | /* list of certificates specified by user */ |
1458 | for (i = 0; i < options.num_certificate_files; i++) { | 1610 | for (i = 0; i < options.num_certificate_files; i++) { |
1459 | key = options.certificates[i]; | 1611 | key = options.certificates[i]; |
1460 | if (!key_is_cert(key) || key->cert == NULL || | 1612 | if (!sshkey_is_cert(key) || key->cert == NULL || |
1461 | key->cert->type != SSH2_CERT_TYPE_USER) | 1613 | key->cert->type != SSH2_CERT_TYPE_USER) |
1462 | continue; | 1614 | continue; |
1463 | id = xcalloc(1, sizeof(*id)); | 1615 | id = xcalloc(1, sizeof(*id)); |
@@ -1531,8 +1683,7 @@ pubkey_prepare(Authctxt *authctxt) | |||
1531 | /* If IdentitiesOnly set and key not found then don't use it */ | 1683 | /* If IdentitiesOnly set and key not found then don't use it */ |
1532 | if (!found && options.identities_only) { | 1684 | if (!found && options.identities_only) { |
1533 | TAILQ_REMOVE(&files, id, next); | 1685 | TAILQ_REMOVE(&files, id, next); |
1534 | explicit_bzero(id, sizeof(*id)); | 1686 | freezero(id, sizeof(*id)); |
1535 | free(id); | ||
1536 | } | 1687 | } |
1537 | } | 1688 | } |
1538 | /* append remaining keys from the config file */ | 1689 | /* append remaining keys from the config file */ |
@@ -1542,9 +1693,7 @@ pubkey_prepare(Authctxt *authctxt) | |||
1542 | } | 1693 | } |
1543 | /* finally, filter by PubkeyAcceptedKeyTypes */ | 1694 | /* finally, filter by PubkeyAcceptedKeyTypes */ |
1544 | TAILQ_FOREACH_SAFE(id, preferred, next, id2) { | 1695 | TAILQ_FOREACH_SAFE(id, preferred, next, id2) { |
1545 | if (id->key != NULL && | 1696 | if (id->key != NULL && !key_type_allowed_by_config(id->key)) { |
1546 | match_pattern_list(sshkey_ssh_name(id->key), | ||
1547 | options.pubkey_key_types, 0) != 1) { | ||
1548 | debug("Skipping %s key %s - " | 1697 | debug("Skipping %s key %s - " |
1549 | "not in PubkeyAcceptedKeyTypes", | 1698 | "not in PubkeyAcceptedKeyTypes", |
1550 | sshkey_ssh_name(id->key), id->filename); | 1699 | sshkey_ssh_name(id->key), id->filename); |
@@ -1590,10 +1739,10 @@ try_identity(Identity *id) | |||
1590 | { | 1739 | { |
1591 | if (!id->key) | 1740 | if (!id->key) |
1592 | return (0); | 1741 | return (0); |
1593 | if (key_type_plain(id->key->type) == KEY_RSA && | 1742 | if (sshkey_type_plain(id->key->type) == KEY_RSA && |
1594 | (datafellows & SSH_BUG_RSASIGMD5) != 0) { | 1743 | (datafellows & SSH_BUG_RSASIGMD5) != 0) { |
1595 | debug("Skipped %s key %s for RSA/MD5 server", | 1744 | debug("Skipped %s key %s for RSA/MD5 server", |
1596 | key_type(id->key), id->filename); | 1745 | sshkey_type(id->key), id->filename); |
1597 | return (0); | 1746 | return (0); |
1598 | } | 1747 | } |
1599 | return 1; | 1748 | return 1; |
@@ -1602,6 +1751,7 @@ try_identity(Identity *id) | |||
1602 | int | 1751 | int |
1603 | userauth_pubkey(Authctxt *authctxt) | 1752 | userauth_pubkey(Authctxt *authctxt) |
1604 | { | 1753 | { |
1754 | struct ssh *ssh = active_state; /* XXX */ | ||
1605 | Identity *id; | 1755 | Identity *id; |
1606 | int sent = 0; | 1756 | int sent = 0; |
1607 | char *fp; | 1757 | char *fp; |
@@ -1629,7 +1779,7 @@ userauth_pubkey(Authctxt *authctxt) | |||
1629 | debug("Offering public key: %s %s %s", | 1779 | debug("Offering public key: %s %s %s", |
1630 | sshkey_type(id->key), fp, id->filename); | 1780 | sshkey_type(id->key), fp, id->filename); |
1631 | free(fp); | 1781 | free(fp); |
1632 | sent = send_pubkey_test(authctxt, id); | 1782 | sent = send_pubkey_test(ssh, authctxt, id); |
1633 | } | 1783 | } |
1634 | } else { | 1784 | } else { |
1635 | debug("Trying private key: %s", id->filename); | 1785 | debug("Trying private key: %s", id->filename); |
@@ -1637,10 +1787,10 @@ userauth_pubkey(Authctxt *authctxt) | |||
1637 | if (id->key != NULL) { | 1787 | if (id->key != NULL) { |
1638 | if (try_identity(id)) { | 1788 | if (try_identity(id)) { |
1639 | id->isprivate = 1; | 1789 | id->isprivate = 1; |
1640 | sent = sign_and_send_pubkey( | 1790 | sent = sign_and_send_pubkey(ssh, |
1641 | authctxt, id); | 1791 | authctxt, id); |
1642 | } | 1792 | } |
1643 | key_free(id->key); | 1793 | sshkey_free(id->key); |
1644 | id->key = NULL; | 1794 | id->key = NULL; |
1645 | id->isprivate = 0; | 1795 | id->isprivate = 0; |
1646 | } | 1796 | } |
@@ -1657,28 +1807,31 @@ userauth_pubkey(Authctxt *authctxt) | |||
1657 | int | 1807 | int |
1658 | userauth_kbdint(Authctxt *authctxt) | 1808 | userauth_kbdint(Authctxt *authctxt) |
1659 | { | 1809 | { |
1810 | struct ssh *ssh = active_state; /* XXX */ | ||
1660 | static int attempt = 0; | 1811 | static int attempt = 0; |
1812 | int r; | ||
1661 | 1813 | ||
1662 | if (attempt++ >= options.number_of_password_prompts) | 1814 | if (attempt++ >= options.number_of_password_prompts) |
1663 | return 0; | 1815 | return 0; |
1664 | /* disable if no SSH2_MSG_USERAUTH_INFO_REQUEST has been seen */ | 1816 | /* disable if no SSH2_MSG_USERAUTH_INFO_REQUEST has been seen */ |
1665 | if (attempt > 1 && !authctxt->info_req_seen) { | 1817 | if (attempt > 1 && !authctxt->info_req_seen) { |
1666 | debug3("userauth_kbdint: disable: no info_req_seen"); | 1818 | debug3("userauth_kbdint: disable: no info_req_seen"); |
1667 | dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, NULL); | 1819 | ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_REQUEST, NULL); |
1668 | return 0; | 1820 | return 0; |
1669 | } | 1821 | } |
1670 | 1822 | ||
1671 | debug2("userauth_kbdint"); | 1823 | debug2("userauth_kbdint"); |
1672 | packet_start(SSH2_MSG_USERAUTH_REQUEST); | 1824 | if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || |
1673 | packet_put_cstring(authctxt->server_user); | 1825 | (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || |
1674 | packet_put_cstring(authctxt->service); | 1826 | (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || |
1675 | packet_put_cstring(authctxt->method->name); | 1827 | (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || |
1676 | packet_put_cstring(""); /* lang */ | 1828 | (r = sshpkt_put_cstring(ssh, "")) != 0 || /* lang */ |
1677 | packet_put_cstring(options.kbd_interactive_devices ? | 1829 | (r = sshpkt_put_cstring(ssh, options.kbd_interactive_devices ? |
1678 | options.kbd_interactive_devices : ""); | 1830 | options.kbd_interactive_devices : "")) != 0 || |
1679 | packet_send(); | 1831 | (r = sshpkt_send(ssh)) != 0) |
1680 | 1832 | fatal("%s: %s", __func__, ssh_err(r)); | |
1681 | dispatch_set(SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req); | 1833 | |
1834 | ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_INFO_REQUEST, &input_userauth_info_req); | ||
1682 | return 1; | 1835 | return 1; |
1683 | } | 1836 | } |
1684 | 1837 | ||
@@ -1689,9 +1842,11 @@ int | |||
1689 | input_userauth_info_req(int type, u_int32_t seq, struct ssh *ssh) | 1842 | input_userauth_info_req(int type, u_int32_t seq, struct ssh *ssh) |
1690 | { | 1843 | { |
1691 | Authctxt *authctxt = ssh->authctxt; | 1844 | Authctxt *authctxt = ssh->authctxt; |
1692 | char *name, *inst, *lang, *prompt, *response; | 1845 | char *name = NULL, *inst = NULL, *lang = NULL, *prompt = NULL; |
1846 | char *response = NULL; | ||
1847 | u_char echo = 0; | ||
1693 | u_int num_prompts, i; | 1848 | u_int num_prompts, i; |
1694 | int echo = 0; | 1849 | int r; |
1695 | 1850 | ||
1696 | debug2("input_userauth_info_req"); | 1851 | debug2("input_userauth_info_req"); |
1697 | 1852 | ||
@@ -1700,44 +1855,52 @@ input_userauth_info_req(int type, u_int32_t seq, struct ssh *ssh) | |||
1700 | 1855 | ||
1701 | authctxt->info_req_seen = 1; | 1856 | authctxt->info_req_seen = 1; |
1702 | 1857 | ||
1703 | name = packet_get_string(NULL); | 1858 | if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0 || |
1704 | inst = packet_get_string(NULL); | 1859 | (r = sshpkt_get_cstring(ssh, &inst, NULL)) != 0 || |
1705 | lang = packet_get_string(NULL); | 1860 | (r = sshpkt_get_cstring(ssh, &lang, NULL)) != 0) |
1861 | goto out; | ||
1706 | if (strlen(name) > 0) | 1862 | if (strlen(name) > 0) |
1707 | logit("%s", name); | 1863 | logit("%s", name); |
1708 | if (strlen(inst) > 0) | 1864 | if (strlen(inst) > 0) |
1709 | logit("%s", inst); | 1865 | logit("%s", inst); |
1710 | free(name); | ||
1711 | free(inst); | ||
1712 | free(lang); | ||
1713 | 1866 | ||
1714 | num_prompts = packet_get_int(); | 1867 | if ((r = sshpkt_get_u32(ssh, &num_prompts)) != 0) |
1868 | goto out; | ||
1715 | /* | 1869 | /* |
1716 | * Begin to build info response packet based on prompts requested. | 1870 | * Begin to build info response packet based on prompts requested. |
1717 | * We commit to providing the correct number of responses, so if | 1871 | * We commit to providing the correct number of responses, so if |
1718 | * further on we run into a problem that prevents this, we have to | 1872 | * further on we run into a problem that prevents this, we have to |
1719 | * be sure and clean this up and send a correct error response. | 1873 | * be sure and clean this up and send a correct error response. |
1720 | */ | 1874 | */ |
1721 | packet_start(SSH2_MSG_USERAUTH_INFO_RESPONSE); | 1875 | if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_INFO_RESPONSE)) != 0 || |
1722 | packet_put_int(num_prompts); | 1876 | (r = sshpkt_put_u32(ssh, num_prompts)) != 0) |
1877 | goto out; | ||
1723 | 1878 | ||
1724 | debug2("input_userauth_info_req: num_prompts %d", num_prompts); | 1879 | debug2("input_userauth_info_req: num_prompts %d", num_prompts); |
1725 | for (i = 0; i < num_prompts; i++) { | 1880 | for (i = 0; i < num_prompts; i++) { |
1726 | prompt = packet_get_string(NULL); | 1881 | if ((r = sshpkt_get_cstring(ssh, &prompt, NULL)) != 0 || |
1727 | echo = packet_get_char(); | 1882 | (r = sshpkt_get_u8(ssh, &echo)) != 0) |
1728 | 1883 | goto out; | |
1729 | response = read_passphrase(prompt, echo ? RP_ECHO : 0); | 1884 | response = read_passphrase(prompt, echo ? RP_ECHO : 0); |
1730 | 1885 | if ((r = sshpkt_put_cstring(ssh, response)) != 0) | |
1731 | packet_put_cstring(response); | 1886 | goto out; |
1732 | explicit_bzero(response, strlen(response)); | 1887 | freezero(response, strlen(response)); |
1733 | free(response); | ||
1734 | free(prompt); | 1888 | free(prompt); |
1889 | response = prompt = NULL; | ||
1735 | } | 1890 | } |
1736 | packet_check_eom(); /* done with parsing incoming message. */ | 1891 | /* done with parsing incoming message. */ |
1737 | 1892 | if ((r = sshpkt_get_end(ssh)) != 0 || | |
1738 | packet_add_padding(64); | 1893 | (r = sshpkt_add_padding(ssh, 64)) != 0) |
1739 | packet_send(); | 1894 | goto out; |
1740 | return 0; | 1895 | r = sshpkt_send(ssh); |
1896 | out: | ||
1897 | if (response) | ||
1898 | freezero(response, strlen(response)); | ||
1899 | free(prompt); | ||
1900 | free(name); | ||
1901 | free(inst); | ||
1902 | free(lang); | ||
1903 | return r; | ||
1741 | } | 1904 | } |
1742 | 1905 | ||
1743 | static int | 1906 | static int |
@@ -1778,7 +1941,6 @@ ssh_keysign(struct sshkey *key, u_char **sigp, size_t *lenp, | |||
1778 | if (pid == 0) { | 1941 | if (pid == 0) { |
1779 | /* keep the socket on exec */ | 1942 | /* keep the socket on exec */ |
1780 | fcntl(sock, F_SETFD, 0); | 1943 | fcntl(sock, F_SETFD, 0); |
1781 | permanently_drop_suid(getuid()); | ||
1782 | close(from[0]); | 1944 | close(from[0]); |
1783 | if (dup2(from[1], STDOUT_FILENO) < 0) | 1945 | if (dup2(from[1], STDOUT_FILENO) < 0) |
1784 | fatal("%s: dup2: %s", __func__, strerror(errno)); | 1946 | fatal("%s: dup2: %s", __func__, strerror(errno)); |
@@ -1858,7 +2020,7 @@ ssh_keysign(struct sshkey *key, u_char **sigp, size_t *lenp, | |||
1858 | int | 2020 | int |
1859 | userauth_hostbased(Authctxt *authctxt) | 2021 | userauth_hostbased(Authctxt *authctxt) |
1860 | { | 2022 | { |
1861 | struct ssh *ssh = active_state; | 2023 | struct ssh *ssh = active_state; /* XXX */ |
1862 | struct sshkey *private = NULL; | 2024 | struct sshkey *private = NULL; |
1863 | struct sshbuf *b = NULL; | 2025 | struct sshbuf *b = NULL; |
1864 | u_char *sig = NULL, *keyblob = NULL; | 2026 | u_char *sig = NULL, *keyblob = NULL; |
@@ -1945,7 +2107,7 @@ userauth_hostbased(Authctxt *authctxt) | |||
1945 | (r = sshbuf_put_cstring(b, authctxt->server_user)) != 0 || | 2107 | (r = sshbuf_put_cstring(b, authctxt->server_user)) != 0 || |
1946 | (r = sshbuf_put_cstring(b, authctxt->service)) != 0 || | 2108 | (r = sshbuf_put_cstring(b, authctxt->service)) != 0 || |
1947 | (r = sshbuf_put_cstring(b, authctxt->method->name)) != 0 || | 2109 | (r = sshbuf_put_cstring(b, authctxt->method->name)) != 0 || |
1948 | (r = sshbuf_put_cstring(b, key_ssh_name(private))) != 0 || | 2110 | (r = sshbuf_put_cstring(b, sshkey_ssh_name(private))) != 0 || |
1949 | (r = sshbuf_put_string(b, keyblob, keylen)) != 0 || | 2111 | (r = sshbuf_put_string(b, keyblob, keylen)) != 0 || |
1950 | (r = sshbuf_put_cstring(b, chost)) != 0 || | 2112 | (r = sshbuf_put_cstring(b, chost)) != 0 || |
1951 | (r = sshbuf_put_cstring(b, authctxt->local_user)) != 0) { | 2113 | (r = sshbuf_put_cstring(b, authctxt->local_user)) != 0) { |
@@ -1956,12 +2118,8 @@ userauth_hostbased(Authctxt *authctxt) | |||
1956 | #ifdef DEBUG_PK | 2118 | #ifdef DEBUG_PK |
1957 | sshbuf_dump(b, stderr); | 2119 | sshbuf_dump(b, stderr); |
1958 | #endif | 2120 | #endif |
1959 | if (authctxt->sensitive->external_keysign) | 2121 | r = ssh_keysign(private, &sig, &siglen, |
1960 | r = ssh_keysign(private, &sig, &siglen, | 2122 | sshbuf_ptr(b), sshbuf_len(b)); |
1961 | sshbuf_ptr(b), sshbuf_len(b)); | ||
1962 | else if ((r = sshkey_sign(private, &sig, &siglen, | ||
1963 | sshbuf_ptr(b), sshbuf_len(b), NULL, datafellows)) != 0) | ||
1964 | debug("%s: sshkey_sign: %s", __func__, ssh_err(r)); | ||
1965 | if (r != 0) { | 2123 | if (r != 0) { |
1966 | error("sign using hostkey %s %s failed", | 2124 | error("sign using hostkey %s %s failed", |
1967 | sshkey_ssh_name(private), fp); | 2125 | sshkey_ssh_name(private), fp); |
@@ -1971,7 +2129,7 @@ userauth_hostbased(Authctxt *authctxt) | |||
1971 | (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || | 2129 | (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || |
1972 | (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || | 2130 | (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || |
1973 | (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || | 2131 | (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || |
1974 | (r = sshpkt_put_cstring(ssh, key_ssh_name(private))) != 0 || | 2132 | (r = sshpkt_put_cstring(ssh, sshkey_ssh_name(private))) != 0 || |
1975 | (r = sshpkt_put_string(ssh, keyblob, keylen)) != 0 || | 2133 | (r = sshpkt_put_string(ssh, keyblob, keylen)) != 0 || |
1976 | (r = sshpkt_put_cstring(ssh, chost)) != 0 || | 2134 | (r = sshpkt_put_cstring(ssh, chost)) != 0 || |
1977 | (r = sshpkt_put_cstring(ssh, authctxt->local_user)) != 0 || | 2135 | (r = sshpkt_put_cstring(ssh, authctxt->local_user)) != 0 || |
@@ -1983,10 +2141,8 @@ userauth_hostbased(Authctxt *authctxt) | |||
1983 | success = 1; | 2141 | success = 1; |
1984 | 2142 | ||
1985 | out: | 2143 | out: |
1986 | if (sig != NULL) { | 2144 | if (sig != NULL) |
1987 | explicit_bzero(sig, siglen); | 2145 | freezero(sig, siglen); |
1988 | free(sig); | ||
1989 | } | ||
1990 | free(keyblob); | 2146 | free(keyblob); |
1991 | free(lname); | 2147 | free(lname); |
1992 | free(fp); | 2148 | free(fp); |
@@ -2083,20 +2239,22 @@ static char * | |||
2083 | authmethods_get(void) | 2239 | authmethods_get(void) |
2084 | { | 2240 | { |
2085 | Authmethod *method = NULL; | 2241 | Authmethod *method = NULL; |
2086 | Buffer b; | 2242 | struct sshbuf *b; |
2087 | char *list; | 2243 | char *list; |
2244 | int r; | ||
2088 | 2245 | ||
2089 | buffer_init(&b); | 2246 | if ((b = sshbuf_new()) == NULL) |
2247 | fatal("%s: sshbuf_new failed", __func__); | ||
2090 | for (method = authmethods; method->name != NULL; method++) { | 2248 | for (method = authmethods; method->name != NULL; method++) { |
2091 | if (authmethod_is_enabled(method)) { | 2249 | if (authmethod_is_enabled(method)) { |
2092 | if (buffer_len(&b) > 0) | 2250 | if ((r = sshbuf_putf(b, "%s%s", |
2093 | buffer_append(&b, ",", 1); | 2251 | sshbuf_len(b) ? "," : "", method->name)) != 0) |
2094 | buffer_append(&b, method->name, strlen(method->name)); | 2252 | fatal("%s: buffer error: %s", |
2253 | __func__, ssh_err(r)); | ||
2095 | } | 2254 | } |
2096 | } | 2255 | } |
2097 | if ((list = sshbuf_dup_string(&b)) == NULL) | 2256 | if ((list = sshbuf_dup_string(b)) == NULL) |
2098 | fatal("%s: sshbuf_dup_string failed", __func__); | 2257 | fatal("%s: sshbuf_dup_string failed", __func__); |
2099 | buffer_free(&b); | 2258 | sshbuf_free(b); |
2100 | return list; | 2259 | return list; |
2101 | } | 2260 | } |
2102 | |||