diff options
Diffstat (limited to 'sshconnect2.c')
-rw-r--r-- | sshconnect2.c | 124 |
1 files changed, 116 insertions, 8 deletions
diff --git a/sshconnect2.c b/sshconnect2.c index adf967281..7ee71763a 100644 --- a/sshconnect2.c +++ b/sshconnect2.c | |||
@@ -84,9 +84,28 @@ ssh_kex2(char *host, struct sockaddr *hostaddr) | |||
84 | { | 84 | { |
85 | Kex *kex; | 85 | Kex *kex; |
86 | 86 | ||
87 | #ifdef GSSAPI | ||
88 | char *orig, *gss = NULL; | ||
89 | int len; | ||
90 | #endif | ||
91 | |||
87 | xxx_host = host; | 92 | xxx_host = host; |
88 | xxx_hostaddr = hostaddr; | 93 | xxx_hostaddr = hostaddr; |
89 | 94 | ||
95 | #ifdef GSSAPI | ||
96 | if (options.gss_authentication) { | ||
97 | orig = myproposal[PROPOSAL_KEX_ALGS]; | ||
98 | gss = ssh_gssapi_client_mechanisms(get_canonical_hostname(1)); | ||
99 | debug("Offering GSSAPI proposal: %s",gss); | ||
100 | if (gss) { | ||
101 | len = strlen(orig) + strlen(gss) + 2; | ||
102 | myproposal[PROPOSAL_KEX_ALGS] = xmalloc(len); | ||
103 | snprintf(myproposal[PROPOSAL_KEX_ALGS], len, "%s,%s", | ||
104 | gss, orig); | ||
105 | } | ||
106 | } | ||
107 | #endif | ||
108 | |||
90 | if (options.ciphers == (char *)-1) { | 109 | if (options.ciphers == (char *)-1) { |
91 | logit("No valid ciphers for protocol version 2 given, using defaults."); | 110 | logit("No valid ciphers for protocol version 2 given, using defaults."); |
92 | options.ciphers = NULL; | 111 | options.ciphers = NULL; |
@@ -114,6 +133,16 @@ ssh_kex2(char *host, struct sockaddr *hostaddr) | |||
114 | myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = | 133 | myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = |
115 | options.hostkeyalgorithms; | 134 | options.hostkeyalgorithms; |
116 | 135 | ||
136 | #ifdef GSSAPI | ||
137 | if (gss) { | ||
138 | orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; | ||
139 | len = strlen(orig) + sizeof(",null"); | ||
140 | myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = xmalloc(len); | ||
141 | snprintf(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], len, | ||
142 | "%s,null", orig); | ||
143 | } | ||
144 | #endif | ||
145 | |||
117 | if (options.rekey_limit) | 146 | if (options.rekey_limit) |
118 | packet_set_rekey_limit(options.rekey_limit); | 147 | packet_set_rekey_limit(options.rekey_limit); |
119 | 148 | ||
@@ -122,10 +151,18 @@ ssh_kex2(char *host, struct sockaddr *hostaddr) | |||
122 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; | 151 | kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; |
123 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; | 152 | kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; |
124 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; | 153 | kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; |
154 | #ifdef GSSAPI | ||
155 | if (options.gss_authentication) | ||
156 | kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; | ||
157 | #endif | ||
125 | kex->client_version_string=client_version_string; | 158 | kex->client_version_string=client_version_string; |
126 | kex->server_version_string=server_version_string; | 159 | kex->server_version_string=server_version_string; |
127 | kex->verify_host_key=&verify_host_key_callback; | 160 | kex->verify_host_key=&verify_host_key_callback; |
128 | 161 | ||
162 | #ifdef GSSAPI | ||
163 | kex->gss_deleg_creds = options.gss_deleg_creds; | ||
164 | #endif | ||
165 | |||
129 | xxx_kex = kex; | 166 | xxx_kex = kex; |
130 | 167 | ||
131 | dispatch_run(DISPATCH_BLOCK, &kex->done, kex); | 168 | dispatch_run(DISPATCH_BLOCK, &kex->done, kex); |
@@ -208,6 +245,7 @@ void input_gssapi_token(int type, u_int32_t, void *); | |||
208 | void input_gssapi_hash(int type, u_int32_t, void *); | 245 | void input_gssapi_hash(int type, u_int32_t, void *); |
209 | void input_gssapi_error(int, u_int32_t, void *); | 246 | void input_gssapi_error(int, u_int32_t, void *); |
210 | void input_gssapi_errtok(int, u_int32_t, void *); | 247 | void input_gssapi_errtok(int, u_int32_t, void *); |
248 | int userauth_gsskeyx(Authctxt *authctxt); | ||
211 | #endif | 249 | #endif |
212 | 250 | ||
213 | void userauth(Authctxt *, char *); | 251 | void userauth(Authctxt *, char *); |
@@ -223,10 +261,18 @@ static char *authmethods_get(void); | |||
223 | 261 | ||
224 | Authmethod authmethods[] = { | 262 | Authmethod authmethods[] = { |
225 | #ifdef GSSAPI | 263 | #ifdef GSSAPI |
264 | {"gssapi-keyx", | ||
265 | userauth_gsskeyx, | ||
266 | &options.gss_authentication, | ||
267 | NULL}, | ||
226 | {"gssapi-with-mic", | 268 | {"gssapi-with-mic", |
227 | userauth_gssapi, | 269 | userauth_gssapi, |
228 | &options.gss_authentication, | 270 | &options.gss_authentication, |
229 | NULL}, | 271 | NULL}, |
272 | {"gssapi", | ||
273 | userauth_gssapi, | ||
274 | &options.gss_authentication, | ||
275 | NULL}, | ||
230 | #endif | 276 | #endif |
231 | {"hostbased", | 277 | {"hostbased", |
232 | userauth_hostbased, | 278 | userauth_hostbased, |
@@ -485,6 +531,7 @@ userauth_gssapi(Authctxt *authctxt) | |||
485 | static u_int mech = 0; | 531 | static u_int mech = 0; |
486 | OM_uint32 min; | 532 | OM_uint32 min; |
487 | int ok = 0; | 533 | int ok = 0; |
534 | int old_gssapi_method; | ||
488 | 535 | ||
489 | /* Try one GSSAPI method at a time, rather than sending them all at | 536 | /* Try one GSSAPI method at a time, rather than sending them all at |
490 | * once. */ | 537 | * once. */ |
@@ -519,13 +566,25 @@ userauth_gssapi(Authctxt *authctxt) | |||
519 | packet_put_cstring(authctxt->service); | 566 | packet_put_cstring(authctxt->service); |
520 | packet_put_cstring(authctxt->method->name); | 567 | packet_put_cstring(authctxt->method->name); |
521 | 568 | ||
522 | packet_put_int(1); | 569 | old_gssapi_method = !strcmp(authctxt->method->name, "gssapi"); |
570 | |||
571 | /* Versions of Debian ssh-krb5 prior to 3.8.1p1-1 don't expect | ||
572 | * tagged OIDs. As such we include both tagged and untagged oids | ||
573 | * for the old gssapi method. | ||
574 | * We only include tagged oids for the new gssapi-with-mic method. | ||
575 | */ | ||
576 | packet_put_int(old_gssapi_method?2:1); | ||
523 | 577 | ||
524 | packet_put_int((gss_supported->elements[mech].length) + 2); | 578 | packet_put_int((gss_supported->elements[mech].length) + 2); |
525 | packet_put_char(SSH_GSS_OIDTYPE); | 579 | packet_put_char(SSH_GSS_OIDTYPE); |
526 | packet_put_char(gss_supported->elements[mech].length); | 580 | packet_put_char(gss_supported->elements[mech].length); |
527 | packet_put_raw(gss_supported->elements[mech].elements, | 581 | packet_put_raw(gss_supported->elements[mech].elements, |
528 | gss_supported->elements[mech].length); | 582 | gss_supported->elements[mech].length); |
583 | if (old_gssapi_method) { | ||
584 | packet_put_int((gss_supported->elements[mech].length)); | ||
585 | packet_put_raw(gss_supported->elements[mech].elements, | ||
586 | gss_supported->elements[mech].length); | ||
587 | } | ||
529 | 588 | ||
530 | packet_send(); | 589 | packet_send(); |
531 | 590 | ||
@@ -565,8 +624,10 @@ process_gssapi_token(void *ctxt, gss_buffer_t recv_tok) | |||
565 | } | 624 | } |
566 | 625 | ||
567 | if (status == GSS_S_COMPLETE) { | 626 | if (status == GSS_S_COMPLETE) { |
627 | int old_gssapi_method = !strcmp(authctxt->method->name, | ||
628 | "gssapi"); | ||
568 | /* send either complete or MIC, depending on mechanism */ | 629 | /* send either complete or MIC, depending on mechanism */ |
569 | if (!(flags & GSS_C_INTEG_FLAG)) { | 630 | if (old_gssapi_method || !(flags & GSS_C_INTEG_FLAG)) { |
570 | packet_start(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE); | 631 | packet_start(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE); |
571 | packet_send(); | 632 | packet_send(); |
572 | } else { | 633 | } else { |
@@ -599,7 +660,7 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt) | |||
599 | Authctxt *authctxt = ctxt; | 660 | Authctxt *authctxt = ctxt; |
600 | Gssctxt *gssctxt; | 661 | Gssctxt *gssctxt; |
601 | int oidlen; | 662 | int oidlen; |
602 | char *oidv; | 663 | char *oidv, *oidv_free; |
603 | 664 | ||
604 | if (authctxt == NULL) | 665 | if (authctxt == NULL) |
605 | fatal("input_gssapi_response: no authentication context"); | 666 | fatal("input_gssapi_response: no authentication context"); |
@@ -607,22 +668,28 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt) | |||
607 | 668 | ||
608 | /* Setup our OID */ | 669 | /* Setup our OID */ |
609 | oidv = packet_get_string(&oidlen); | 670 | oidv = packet_get_string(&oidlen); |
671 | oidv_free = oidv; | ||
610 | 672 | ||
611 | if (oidlen <= 2 || | 673 | if (oidlen <= 2 || |
612 | oidv[0] != SSH_GSS_OIDTYPE || | 674 | oidv[0] != SSH_GSS_OIDTYPE || |
613 | oidv[1] != oidlen - 2) { | 675 | oidv[1] != oidlen - 2) { |
614 | xfree(oidv); | ||
615 | debug("Badly encoded mechanism OID received"); | 676 | debug("Badly encoded mechanism OID received"); |
616 | userauth(authctxt, NULL); | 677 | if (oidlen < 2) { |
617 | return; | 678 | xfree(oidv_free); |
679 | userauth(authctxt, NULL); | ||
680 | return; | ||
681 | } | ||
682 | } else { | ||
683 | oidlen -= 2; | ||
684 | oidv += 2; | ||
618 | } | 685 | } |
619 | 686 | ||
620 | if (!ssh_gssapi_check_oid(gssctxt, oidv + 2, oidlen - 2)) | 687 | if (!ssh_gssapi_check_oid(gssctxt, oidv, oidlen)) |
621 | fatal("Server returned different OID than expected"); | 688 | fatal("Server returned different OID than expected"); |
622 | 689 | ||
623 | packet_check_eom(); | 690 | packet_check_eom(); |
624 | 691 | ||
625 | xfree(oidv); | 692 | xfree(oidv_free); |
626 | 693 | ||
627 | if (GSS_ERROR(process_gssapi_token(ctxt, GSS_C_NO_BUFFER))) { | 694 | if (GSS_ERROR(process_gssapi_token(ctxt, GSS_C_NO_BUFFER))) { |
628 | /* Start again with next method on list */ | 695 | /* Start again with next method on list */ |
@@ -706,6 +773,47 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt) | |||
706 | xfree(msg); | 773 | xfree(msg); |
707 | xfree(lang); | 774 | xfree(lang); |
708 | } | 775 | } |
776 | |||
777 | int | ||
778 | userauth_gsskeyx(Authctxt *authctxt) | ||
779 | { | ||
780 | Buffer b; | ||
781 | gss_buffer_desc gssbuf, mic; | ||
782 | OM_uint32 ms; | ||
783 | |||
784 | static int attempt = 0; | ||
785 | if (attempt++ >= 1) | ||
786 | return (0); | ||
787 | |||
788 | if (gss_kex_context == NULL) { | ||
789 | debug("No valid Key exchange context"); | ||
790 | return (0); | ||
791 | } | ||
792 | |||
793 | ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service, | ||
794 | "gssapi-keyex"); | ||
795 | |||
796 | gssbuf.value = buffer_ptr(&b); | ||
797 | gssbuf.length = buffer_len(&b); | ||
798 | |||
799 | if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) { | ||
800 | buffer_free(&b); | ||
801 | return (0); | ||
802 | } | ||
803 | |||
804 | packet_start(SSH2_MSG_USERAUTH_REQUEST); | ||
805 | packet_put_cstring(authctxt->server_user); | ||
806 | packet_put_cstring(authctxt->service); | ||
807 | packet_put_cstring(authctxt->method->name); | ||
808 | packet_put_string(mic.value, mic.length); | ||
809 | packet_send(); | ||
810 | |||
811 | buffer_free(&b); | ||
812 | gss_release_buffer(&ms, &mic); | ||
813 | |||
814 | return (1); | ||
815 | } | ||
816 | |||
709 | #endif /* GSSAPI */ | 817 | #endif /* GSSAPI */ |
710 | 818 | ||
711 | int | 819 | int |