summaryrefslogtreecommitdiff
path: root/sshconnect2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshconnect2.c')
-rw-r--r--sshconnect2.c124
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 *);
208void input_gssapi_hash(int type, u_int32_t, void *); 245void input_gssapi_hash(int type, u_int32_t, void *);
209void input_gssapi_error(int, u_int32_t, void *); 246void input_gssapi_error(int, u_int32_t, void *);
210void input_gssapi_errtok(int, u_int32_t, void *); 247void input_gssapi_errtok(int, u_int32_t, void *);
248int userauth_gsskeyx(Authctxt *authctxt);
211#endif 249#endif
212 250
213void userauth(Authctxt *, char *); 251void userauth(Authctxt *, char *);
@@ -223,10 +261,18 @@ static char *authmethods_get(void);
223 261
224Authmethod authmethods[] = { 262Authmethod 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
777int
778userauth_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
711int 819int