summaryrefslogtreecommitdiff
path: root/sshconnect2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshconnect2.c')
-rw-r--r--sshconnect2.c144
1 files changed, 134 insertions, 10 deletions
diff --git a/sshconnect2.c b/sshconnect2.c
index 208df078c..72d328692 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -99,9 +99,34 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
99{ 99{
100 Kex *kex; 100 Kex *kex;
101 101
102#ifdef GSSAPI
103 char *orig = NULL, *gss = NULL;
104 char *gss_host = NULL;
105#endif
106
102 xxx_host = host; 107 xxx_host = host;
103 xxx_hostaddr = hostaddr; 108 xxx_hostaddr = hostaddr;
104 109
110#ifdef GSSAPI
111 if (options.gss_keyex) {
112 /* Add the GSSAPI mechanisms currently supported on this
113 * client to the key exchange algorithm proposal */
114 orig = myproposal[PROPOSAL_KEX_ALGS];
115
116 if (options.gss_trust_dns)
117 gss_host = (char *)get_canonical_hostname(1);
118 else
119 gss_host = host;
120
121 gss = ssh_gssapi_client_mechanisms(gss_host);
122 if (gss) {
123 debug("Offering GSSAPI proposal: %s", gss);
124 xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
125 "%s,%s", gss, orig);
126 }
127 }
128#endif
129
105 if (options.ciphers == (char *)-1) { 130 if (options.ciphers == (char *)-1) {
106 logit("No valid ciphers for protocol version 2 given, using defaults."); 131 logit("No valid ciphers for protocol version 2 given, using defaults.");
107 options.ciphers = NULL; 132 options.ciphers = NULL;
@@ -129,6 +154,16 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
129 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = 154 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
130 options.hostkeyalgorithms; 155 options.hostkeyalgorithms;
131 156
157#ifdef GSSAPI
158 /* If we've got GSSAPI algorithms, then we also support the
159 * 'null' hostkey, as a last resort */
160 if (options.gss_keyex && gss) {
161 orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
162 xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
163 "%s,null", orig);
164 }
165#endif
166
132 if (options.rekey_limit) 167 if (options.rekey_limit)
133 packet_set_rekey_limit(options.rekey_limit); 168 packet_set_rekey_limit(options.rekey_limit);
134 169
@@ -138,10 +173,21 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
138 kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; 173 kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
139 kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; 174 kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
140 kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; 175 kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
176#ifdef GSSAPI
177 kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
178 kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
179 kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
180#endif
141 kex->client_version_string=client_version_string; 181 kex->client_version_string=client_version_string;
142 kex->server_version_string=server_version_string; 182 kex->server_version_string=server_version_string;
143 kex->verify_host_key=&verify_host_key_callback; 183 kex->verify_host_key=&verify_host_key_callback;
144 184
185#ifdef GSSAPI
186 kex->gss_deleg_creds = options.gss_deleg_creds;
187 kex->gss_trust_dns = options.gss_trust_dns;
188 kex->gss_host = gss_host;
189#endif
190
145 xxx_kex = kex; 191 xxx_kex = kex;
146 192
147 dispatch_run(DISPATCH_BLOCK, &kex->done, kex); 193 dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
@@ -224,6 +270,7 @@ void input_gssapi_token(int type, u_int32_t, void *);
224void input_gssapi_hash(int type, u_int32_t, void *); 270void input_gssapi_hash(int type, u_int32_t, void *);
225void input_gssapi_error(int, u_int32_t, void *); 271void input_gssapi_error(int, u_int32_t, void *);
226void input_gssapi_errtok(int, u_int32_t, void *); 272void input_gssapi_errtok(int, u_int32_t, void *);
273int userauth_gsskeyex(Authctxt *authctxt);
227#endif 274#endif
228 275
229void userauth(Authctxt *, char *); 276void userauth(Authctxt *, char *);
@@ -239,10 +286,18 @@ static char *authmethods_get(void);
239 286
240Authmethod authmethods[] = { 287Authmethod authmethods[] = {
241#ifdef GSSAPI 288#ifdef GSSAPI
289 {"gssapi-keyex",
290 userauth_gsskeyex,
291 &options.gss_authentication,
292 NULL},
242 {"gssapi-with-mic", 293 {"gssapi-with-mic",
243 userauth_gssapi, 294 userauth_gssapi,
244 &options.gss_authentication, 295 &options.gss_authentication,
245 NULL}, 296 NULL},
297 {"gssapi",
298 userauth_gssapi,
299 &options.gss_authentication,
300 NULL},
246#endif 301#endif
247 {"hostbased", 302 {"hostbased",
248 userauth_hostbased, 303 userauth_hostbased,
@@ -501,6 +556,13 @@ userauth_gssapi(Authctxt *authctxt)
501 static u_int mech = 0; 556 static u_int mech = 0;
502 OM_uint32 min; 557 OM_uint32 min;
503 int ok = 0; 558 int ok = 0;
559 char *gss_host = NULL;
560 int old_gssapi_method;
561
562 if (options.gss_trust_dns)
563 gss_host = (char *)get_canonical_hostname(1);
564 else
565 gss_host = (char *)authctxt->host;
504 566
505 /* Try one GSSAPI method at a time, rather than sending them all at 567 /* Try one GSSAPI method at a time, rather than sending them all at
506 * once. */ 568 * once. */
@@ -513,7 +575,7 @@ userauth_gssapi(Authctxt *authctxt)
513 /* My DER encoding requires length<128 */ 575 /* My DER encoding requires length<128 */
514 if (gss_supported->elements[mech].length < 128 && 576 if (gss_supported->elements[mech].length < 128 &&
515 ssh_gssapi_check_mechanism(&gssctxt, 577 ssh_gssapi_check_mechanism(&gssctxt,
516 &gss_supported->elements[mech], authctxt->host)) { 578 &gss_supported->elements[mech], gss_host)) {
517 ok = 1; /* Mechanism works */ 579 ok = 1; /* Mechanism works */
518 } else { 580 } else {
519 mech++; 581 mech++;
@@ -530,13 +592,25 @@ userauth_gssapi(Authctxt *authctxt)
530 packet_put_cstring(authctxt->service); 592 packet_put_cstring(authctxt->service);
531 packet_put_cstring(authctxt->method->name); 593 packet_put_cstring(authctxt->method->name);
532 594
533 packet_put_int(1); 595 old_gssapi_method = !strcmp(authctxt->method->name, "gssapi");
596
597 /* Versions of Debian ssh-krb5 prior to 3.8.1p1-1 don't expect
598 * tagged OIDs. As such we include both tagged and untagged oids
599 * for the old gssapi method.
600 * We only include tagged oids for the new gssapi-with-mic method.
601 */
602 packet_put_int(old_gssapi_method ? 2 : 1);
534 603
535 packet_put_int((gss_supported->elements[mech].length) + 2); 604 packet_put_int((gss_supported->elements[mech].length) + 2);
536 packet_put_char(SSH_GSS_OIDTYPE); 605 packet_put_char(SSH_GSS_OIDTYPE);
537 packet_put_char(gss_supported->elements[mech].length); 606 packet_put_char(gss_supported->elements[mech].length);
538 packet_put_raw(gss_supported->elements[mech].elements, 607 packet_put_raw(gss_supported->elements[mech].elements,
539 gss_supported->elements[mech].length); 608 gss_supported->elements[mech].length);
609 if (old_gssapi_method) {
610 packet_put_int(gss_supported->elements[mech].length);
611 packet_put_raw(gss_supported->elements[mech].elements,
612 gss_supported->elements[mech].length);
613 }
540 614
541 packet_send(); 615 packet_send();
542 616
@@ -576,8 +650,10 @@ process_gssapi_token(void *ctxt, gss_buffer_t recv_tok)
576 } 650 }
577 651
578 if (status == GSS_S_COMPLETE) { 652 if (status == GSS_S_COMPLETE) {
653 int old_gssapi_method = !strcmp(authctxt->method->name,
654 "gssapi");
579 /* send either complete or MIC, depending on mechanism */ 655 /* send either complete or MIC, depending on mechanism */
580 if (!(flags & GSS_C_INTEG_FLAG)) { 656 if (old_gssapi_method || !(flags & GSS_C_INTEG_FLAG)) {
581 packet_start(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE); 657 packet_start(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE);
582 packet_send(); 658 packet_send();
583 } else { 659 } else {
@@ -609,8 +685,8 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt)
609{ 685{
610 Authctxt *authctxt = ctxt; 686 Authctxt *authctxt = ctxt;
611 Gssctxt *gssctxt; 687 Gssctxt *gssctxt;
612 int oidlen; 688 u_int oidlen;
613 char *oidv; 689 u_char *oidv;
614 690
615 if (authctxt == NULL) 691 if (authctxt == NULL)
616 fatal("input_gssapi_response: no authentication context"); 692 fatal("input_gssapi_response: no authentication context");
@@ -618,22 +694,28 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt)
618 694
619 /* Setup our OID */ 695 /* Setup our OID */
620 oidv = packet_get_string(&oidlen); 696 oidv = packet_get_string(&oidlen);
697 oidv_free = oidv;
621 698
622 if (oidlen <= 2 || 699 if (oidlen <= 2 ||
623 oidv[0] != SSH_GSS_OIDTYPE || 700 oidv[0] != SSH_GSS_OIDTYPE ||
624 oidv[1] != oidlen - 2) { 701 oidv[1] != oidlen - 2) {
625 xfree(oidv);
626 debug("Badly encoded mechanism OID received"); 702 debug("Badly encoded mechanism OID received");
627 userauth(authctxt, NULL); 703 if (oidlen < 2) {
628 return; 704 xfree(oidv_free);
705 userauth(authctxt, NULL);
706 return;
707 }
708 } else {
709 oidlen -= 2;
710 oidv += 2;
629 } 711 }
630 712
631 if (!ssh_gssapi_check_oid(gssctxt, oidv + 2, oidlen - 2)) 713 if (!ssh_gssapi_check_oid(gssctxt, oidv, oidlen))
632 fatal("Server returned different OID than expected"); 714 fatal("Server returned different OID than expected");
633 715
634 packet_check_eom(); 716 packet_check_eom();
635 717
636 xfree(oidv); 718 xfree(oidv_free);
637 719
638 if (GSS_ERROR(process_gssapi_token(ctxt, GSS_C_NO_BUFFER))) { 720 if (GSS_ERROR(process_gssapi_token(ctxt, GSS_C_NO_BUFFER))) {
639 /* Start again with next method on list */ 721 /* Start again with next method on list */
@@ -717,6 +799,48 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt)
717 xfree(msg); 799 xfree(msg);
718 xfree(lang); 800 xfree(lang);
719} 801}
802
803int
804userauth_gsskeyex(Authctxt *authctxt)
805{
806 Buffer b;
807 gss_buffer_desc gssbuf;
808 gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
809 OM_uint32 ms;
810
811 static int attempt = 0;
812 if (attempt++ >= 1)
813 return (0);
814
815 if (gss_kex_context == NULL) {
816 debug("No valid Key exchange context");
817 return (0);
818 }
819
820 ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
821 "gssapi-keyex");
822
823 gssbuf.value = buffer_ptr(&b);
824 gssbuf.length = buffer_len(&b);
825
826 if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
827 buffer_free(&b);
828 return (0);
829 }
830
831 packet_start(SSH2_MSG_USERAUTH_REQUEST);
832 packet_put_cstring(authctxt->server_user);
833 packet_put_cstring(authctxt->service);
834 packet_put_cstring(authctxt->method->name);
835 packet_put_string(mic.value, mic.length);
836 packet_send();
837
838 buffer_free(&b);
839 gss_release_buffer(&ms, &mic);
840
841 return (1);
842}
843
720#endif /* GSSAPI */ 844#endif /* GSSAPI */
721 845
722int 846int