summaryrefslogtreecommitdiff
path: root/sshconnect2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshconnect2.c')
-rw-r--r--sshconnect2.c148
1 files changed, 137 insertions, 11 deletions
diff --git a/sshconnect2.c b/sshconnect2.c
index 389bec9e4..18cbbd9f9 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -102,9 +102,34 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
102{ 102{
103 Kex *kex; 103 Kex *kex;
104 104
105#ifdef GSSAPI
106 char *orig = NULL, *gss = NULL;
107 char *gss_host = NULL;
108#endif
109
105 xxx_host = host; 110 xxx_host = host;
106 xxx_hostaddr = hostaddr; 111 xxx_hostaddr = hostaddr;
107 112
113#ifdef GSSAPI
114 if (options.gss_keyex) {
115 /* Add the GSSAPI mechanisms currently supported on this
116 * client to the key exchange algorithm proposal */
117 orig = myproposal[PROPOSAL_KEX_ALGS];
118
119 if (options.gss_trust_dns)
120 gss_host = (char *)get_canonical_hostname(1);
121 else
122 gss_host = host;
123
124 gss = ssh_gssapi_client_mechanisms(gss_host);
125 if (gss) {
126 debug("Offering GSSAPI proposal: %s", gss);
127 xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
128 "%s,%s", gss, orig);
129 }
130 }
131#endif
132
108 if (options.ciphers == (char *)-1) { 133 if (options.ciphers == (char *)-1) {
109 logit("No valid ciphers for protocol version 2 given, using defaults."); 134 logit("No valid ciphers for protocol version 2 given, using defaults.");
110 options.ciphers = NULL; 135 options.ciphers = NULL;
@@ -132,6 +157,16 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
132 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = 157 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] =
133 options.hostkeyalgorithms; 158 options.hostkeyalgorithms;
134 159
160#ifdef GSSAPI
161 /* If we've got GSSAPI algorithms, then we also support the
162 * 'null' hostkey, as a last resort */
163 if (options.gss_keyex && gss) {
164 orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
165 xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
166 "%s,null", orig);
167 }
168#endif
169
135 if (options.rekey_limit) 170 if (options.rekey_limit)
136 packet_set_rekey_limit((u_int32_t)options.rekey_limit); 171 packet_set_rekey_limit((u_int32_t)options.rekey_limit);
137 172
@@ -141,10 +176,21 @@ ssh_kex2(char *host, struct sockaddr *hostaddr)
141 kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; 176 kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
142 kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; 177 kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
143 kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; 178 kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
179#ifdef GSSAPI
180 kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
181 kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
182 kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
183#endif
144 kex->client_version_string=client_version_string; 184 kex->client_version_string=client_version_string;
145 kex->server_version_string=server_version_string; 185 kex->server_version_string=server_version_string;
146 kex->verify_host_key=&verify_host_key_callback; 186 kex->verify_host_key=&verify_host_key_callback;
147 187
188#ifdef GSSAPI
189 kex->gss_deleg_creds = options.gss_deleg_creds;
190 kex->gss_trust_dns = options.gss_trust_dns;
191 kex->gss_host = gss_host;
192#endif
193
148 xxx_kex = kex; 194 xxx_kex = kex;
149 195
150 dispatch_run(DISPATCH_BLOCK, &kex->done, kex); 196 dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
@@ -227,6 +273,7 @@ void input_gssapi_token(int type, u_int32_t, void *);
227void input_gssapi_hash(int type, u_int32_t, void *); 273void input_gssapi_hash(int type, u_int32_t, void *);
228void input_gssapi_error(int, u_int32_t, void *); 274void input_gssapi_error(int, u_int32_t, void *);
229void input_gssapi_errtok(int, u_int32_t, void *); 275void input_gssapi_errtok(int, u_int32_t, void *);
276int userauth_gsskeyex(Authctxt *authctxt);
230#endif 277#endif
231 278
232void userauth(Authctxt *, char *); 279void userauth(Authctxt *, char *);
@@ -242,10 +289,18 @@ static char *authmethods_get(void);
242 289
243Authmethod authmethods[] = { 290Authmethod authmethods[] = {
244#ifdef GSSAPI 291#ifdef GSSAPI
292 {"gssapi-keyex",
293 userauth_gsskeyex,
294 &options.gss_authentication,
295 NULL},
245 {"gssapi-with-mic", 296 {"gssapi-with-mic",
246 userauth_gssapi, 297 userauth_gssapi,
247 &options.gss_authentication, 298 &options.gss_authentication,
248 NULL}, 299 NULL},
300 {"gssapi",
301 userauth_gssapi,
302 &options.gss_authentication,
303 NULL},
249#endif 304#endif
250 {"hostbased", 305 {"hostbased",
251 userauth_hostbased, 306 userauth_hostbased,
@@ -511,6 +566,13 @@ userauth_gssapi(Authctxt *authctxt)
511 static u_int mech = 0; 566 static u_int mech = 0;
512 OM_uint32 min; 567 OM_uint32 min;
513 int ok = 0; 568 int ok = 0;
569 char *gss_host = NULL;
570 int old_gssapi_method;
571
572 if (options.gss_trust_dns)
573 gss_host = (char *)get_canonical_hostname(1);
574 else
575 gss_host = (char *)authctxt->host;
514 576
515 /* Try one GSSAPI method at a time, rather than sending them all at 577 /* Try one GSSAPI method at a time, rather than sending them all at
516 * once. */ 578 * once. */
@@ -523,7 +585,7 @@ userauth_gssapi(Authctxt *authctxt)
523 /* My DER encoding requires length<128 */ 585 /* My DER encoding requires length<128 */
524 if (gss_supported->elements[mech].length < 128 && 586 if (gss_supported->elements[mech].length < 128 &&
525 ssh_gssapi_check_mechanism(&gssctxt, 587 ssh_gssapi_check_mechanism(&gssctxt,
526 &gss_supported->elements[mech], authctxt->host)) { 588 &gss_supported->elements[mech], gss_host)) {
527 ok = 1; /* Mechanism works */ 589 ok = 1; /* Mechanism works */
528 } else { 590 } else {
529 mech++; 591 mech++;
@@ -540,13 +602,25 @@ userauth_gssapi(Authctxt *authctxt)
540 packet_put_cstring(authctxt->service); 602 packet_put_cstring(authctxt->service);
541 packet_put_cstring(authctxt->method->name); 603 packet_put_cstring(authctxt->method->name);
542 604
543 packet_put_int(1); 605 old_gssapi_method = !strcmp(authctxt->method->name, "gssapi");
606
607 /* Versions of Debian ssh-krb5 prior to 3.8.1p1-1 don't expect
608 * tagged OIDs. As such we include both tagged and untagged oids
609 * for the old gssapi method.
610 * We only include tagged oids for the new gssapi-with-mic method.
611 */
612 packet_put_int(old_gssapi_method ? 2 : 1);
544 613
545 packet_put_int((gss_supported->elements[mech].length) + 2); 614 packet_put_int((gss_supported->elements[mech].length) + 2);
546 packet_put_char(SSH_GSS_OIDTYPE); 615 packet_put_char(SSH_GSS_OIDTYPE);
547 packet_put_char(gss_supported->elements[mech].length); 616 packet_put_char(gss_supported->elements[mech].length);
548 packet_put_raw(gss_supported->elements[mech].elements, 617 packet_put_raw(gss_supported->elements[mech].elements,
549 gss_supported->elements[mech].length); 618 gss_supported->elements[mech].length);
619 if (old_gssapi_method) {
620 packet_put_int(gss_supported->elements[mech].length);
621 packet_put_raw(gss_supported->elements[mech].elements,
622 gss_supported->elements[mech].length);
623 }
550 624
551 packet_send(); 625 packet_send();
552 626
@@ -586,8 +660,10 @@ process_gssapi_token(void *ctxt, gss_buffer_t recv_tok)
586 } 660 }
587 661
588 if (status == GSS_S_COMPLETE) { 662 if (status == GSS_S_COMPLETE) {
663 int old_gssapi_method = !strcmp(authctxt->method->name,
664 "gssapi");
589 /* send either complete or MIC, depending on mechanism */ 665 /* send either complete or MIC, depending on mechanism */
590 if (!(flags & GSS_C_INTEG_FLAG)) { 666 if (old_gssapi_method || !(flags & GSS_C_INTEG_FLAG)) {
591 packet_start(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE); 667 packet_start(SSH2_MSG_USERAUTH_GSSAPI_EXCHANGE_COMPLETE);
592 packet_send(); 668 packet_send();
593 } else { 669 } else {
@@ -619,8 +695,8 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt)
619{ 695{
620 Authctxt *authctxt = ctxt; 696 Authctxt *authctxt = ctxt;
621 Gssctxt *gssctxt; 697 Gssctxt *gssctxt;
622 int oidlen; 698 u_int oidlen;
623 char *oidv; 699 u_char *oidv, *oidv_free;
624 700
625 if (authctxt == NULL) 701 if (authctxt == NULL)
626 fatal("input_gssapi_response: no authentication context"); 702 fatal("input_gssapi_response: no authentication context");
@@ -628,22 +704,28 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt)
628 704
629 /* Setup our OID */ 705 /* Setup our OID */
630 oidv = packet_get_string(&oidlen); 706 oidv = packet_get_string(&oidlen);
707 oidv_free = oidv;
631 708
632 if (oidlen <= 2 || 709 if (oidlen <= 2 ||
633 oidv[0] != SSH_GSS_OIDTYPE || 710 oidv[0] != SSH_GSS_OIDTYPE ||
634 oidv[1] != oidlen - 2) { 711 oidv[1] != oidlen - 2) {
635 xfree(oidv);
636 debug("Badly encoded mechanism OID received"); 712 debug("Badly encoded mechanism OID received");
637 userauth(authctxt, NULL); 713 if (oidlen < 2) {
638 return; 714 xfree(oidv_free);
715 userauth(authctxt, NULL);
716 return;
717 }
718 } else {
719 oidlen -= 2;
720 oidv += 2;
639 } 721 }
640 722
641 if (!ssh_gssapi_check_oid(gssctxt, oidv + 2, oidlen - 2)) 723 if (!ssh_gssapi_check_oid(gssctxt, oidv, oidlen))
642 fatal("Server returned different OID than expected"); 724 fatal("Server returned different OID than expected");
643 725
644 packet_check_eom(); 726 packet_check_eom();
645 727
646 xfree(oidv); 728 xfree(oidv_free);
647 729
648 if (GSS_ERROR(process_gssapi_token(ctxt, GSS_C_NO_BUFFER))) { 730 if (GSS_ERROR(process_gssapi_token(ctxt, GSS_C_NO_BUFFER))) {
649 /* Start again with next method on list */ 731 /* Start again with next method on list */
@@ -727,6 +809,48 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt)
727 xfree(msg); 809 xfree(msg);
728 xfree(lang); 810 xfree(lang);
729} 811}
812
813int
814userauth_gsskeyex(Authctxt *authctxt)
815{
816 Buffer b;
817 gss_buffer_desc gssbuf;
818 gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
819 OM_uint32 ms;
820
821 static int attempt = 0;
822 if (attempt++ >= 1)
823 return (0);
824
825 if (gss_kex_context == NULL) {
826 debug("No valid Key exchange context");
827 return (0);
828 }
829
830 ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
831 "gssapi-keyex");
832
833 gssbuf.value = buffer_ptr(&b);
834 gssbuf.length = buffer_len(&b);
835
836 if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
837 buffer_free(&b);
838 return (0);
839 }
840
841 packet_start(SSH2_MSG_USERAUTH_REQUEST);
842 packet_put_cstring(authctxt->server_user);
843 packet_put_cstring(authctxt->service);
844 packet_put_cstring(authctxt->method->name);
845 packet_put_string(mic.value, mic.length);
846 packet_send();
847
848 buffer_free(&b);
849 gss_release_buffer(&ms, &mic);
850
851 return (1);
852}
853
730#endif /* GSSAPI */ 854#endif /* GSSAPI */
731 855
732int 856int
@@ -1042,6 +1166,8 @@ pubkey_prepare(Authctxt *authctxt)
1042 1166
1043 /* list of keys stored in the filesystem */ 1167 /* list of keys stored in the filesystem */
1044 for (i = 0; i < options.num_identity_files; i++) { 1168 for (i = 0; i < options.num_identity_files; i++) {
1169 if (options.identity_files[i] == NULL)
1170 continue;
1045 key = options.identity_keys[i]; 1171 key = options.identity_keys[i];
1046 if (key && key->type == KEY_RSA1) 1172 if (key && key->type == KEY_RSA1)
1047 continue; 1173 continue;
@@ -1132,7 +1258,7 @@ userauth_pubkey(Authctxt *authctxt)
1132 if (id->key && id->key->type != KEY_RSA1) { 1258 if (id->key && id->key->type != KEY_RSA1) {
1133 debug("Offering public key: %s", id->filename); 1259 debug("Offering public key: %s", id->filename);
1134 sent = send_pubkey_test(authctxt, id); 1260 sent = send_pubkey_test(authctxt, id);
1135 } else if (id->key == NULL) { 1261 } else if (id->key == NULL && id->filename) {
1136 debug("Trying private key: %s", id->filename); 1262 debug("Trying private key: %s", id->filename);
1137 id->key = load_identity_file(id->filename); 1263 id->key = load_identity_file(id->filename);
1138 if (id->key != NULL) { 1264 if (id->key != NULL) {