summaryrefslogtreecommitdiff
path: root/sshconnect2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshconnect2.c')
-rw-r--r--sshconnect2.c122
1 files changed, 118 insertions, 4 deletions
diff --git a/sshconnect2.c b/sshconnect2.c
index 103a2b36a..d534e6190 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -162,6 +162,11 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
162 struct kex *kex; 162 struct kex *kex;
163 int r; 163 int r;
164 164
165#ifdef GSSAPI
166 char *orig = NULL, *gss = NULL;
167 char *gss_host = NULL;
168#endif
169
165 xxx_host = host; 170 xxx_host = host;
166 xxx_hostaddr = hostaddr; 171 xxx_hostaddr = hostaddr;
167 172
@@ -192,6 +197,36 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
192 order_hostkeyalgs(host, hostaddr, port)); 197 order_hostkeyalgs(host, hostaddr, port));
193 } 198 }
194 199
200#ifdef GSSAPI
201 if (options.gss_keyex) {
202 /* Add the GSSAPI mechanisms currently supported on this
203 * client to the key exchange algorithm proposal */
204 orig = myproposal[PROPOSAL_KEX_ALGS];
205
206 if (options.gss_server_identity)
207 gss_host = xstrdup(options.gss_server_identity);
208 else if (options.gss_trust_dns)
209 gss_host = remote_hostname(active_state);
210 else
211 gss_host = xstrdup(host);
212
213 gss = ssh_gssapi_client_mechanisms(gss_host,
214 options.gss_client_identity);
215 if (gss) {
216 debug("Offering GSSAPI proposal: %s", gss);
217 xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
218 "%s,%s", gss, orig);
219
220 /* If we've got GSSAPI algorithms, then we also
221 * support the 'null' hostkey, as a last resort */
222 orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
223 xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
224 "%s,null", orig);
225 free(gss);
226 }
227 }
228#endif
229
195 if (options.rekey_limit || options.rekey_interval) 230 if (options.rekey_limit || options.rekey_interval)
196 packet_set_rekey_limits((u_int32_t)options.rekey_limit, 231 packet_set_rekey_limits((u_int32_t)options.rekey_limit,
197 (time_t)options.rekey_interval); 232 (time_t)options.rekey_interval);
@@ -213,10 +248,26 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
213# endif 248# endif
214#endif 249#endif
215 kex->kex[KEX_C25519_SHA256] = kexc25519_client; 250 kex->kex[KEX_C25519_SHA256] = kexc25519_client;
251#ifdef GSSAPI
252 if (options.gss_keyex) {
253 kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
254 kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
255 kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
256 }
257#endif
216 kex->client_version_string=client_version_string; 258 kex->client_version_string=client_version_string;
217 kex->server_version_string=server_version_string; 259 kex->server_version_string=server_version_string;
218 kex->verify_host_key=&verify_host_key_callback; 260 kex->verify_host_key=&verify_host_key_callback;
219 261
262#ifdef GSSAPI
263 if (options.gss_keyex) {
264 kex->gss_deleg_creds = options.gss_deleg_creds;
265 kex->gss_trust_dns = options.gss_trust_dns;
266 kex->gss_client = options.gss_client_identity;
267 kex->gss_host = gss_host;
268 }
269#endif
270
220 dispatch_run(DISPATCH_BLOCK, &kex->done, active_state); 271 dispatch_run(DISPATCH_BLOCK, &kex->done, active_state);
221 272
222 /* remove ext-info from the KEX proposals for rekeying */ 273 /* remove ext-info from the KEX proposals for rekeying */
@@ -311,6 +362,7 @@ int input_gssapi_token(int type, u_int32_t, void *);
311int input_gssapi_hash(int type, u_int32_t, void *); 362int input_gssapi_hash(int type, u_int32_t, void *);
312int input_gssapi_error(int, u_int32_t, void *); 363int input_gssapi_error(int, u_int32_t, void *);
313int input_gssapi_errtok(int, u_int32_t, void *); 364int input_gssapi_errtok(int, u_int32_t, void *);
365int userauth_gsskeyex(Authctxt *authctxt);
314#endif 366#endif
315 367
316void userauth(Authctxt *, char *); 368void userauth(Authctxt *, char *);
@@ -327,6 +379,11 @@ static char *authmethods_get(void);
327 379
328Authmethod authmethods[] = { 380Authmethod authmethods[] = {
329#ifdef GSSAPI 381#ifdef GSSAPI
382 {"gssapi-keyex",
383 userauth_gsskeyex,
384 NULL,
385 &options.gss_authentication,
386 NULL},
330 {"gssapi-with-mic", 387 {"gssapi-with-mic",
331 userauth_gssapi, 388 userauth_gssapi,
332 NULL, 389 NULL,
@@ -652,25 +709,40 @@ userauth_gssapi(Authctxt *authctxt)
652 static u_int mech = 0; 709 static u_int mech = 0;
653 OM_uint32 min; 710 OM_uint32 min;
654 int ok = 0; 711 int ok = 0;
712 char *gss_host;
713
714 if (options.gss_server_identity)
715 gss_host = xstrdup(options.gss_server_identity);
716 else if (options.gss_trust_dns)
717 gss_host = remote_hostname(active_state);
718 else
719 gss_host = xstrdup(authctxt->host);
655 720
656 /* Try one GSSAPI method at a time, rather than sending them all at 721 /* Try one GSSAPI method at a time, rather than sending them all at
657 * once. */ 722 * once. */
658 723
659 if (gss_supported == NULL) 724 if (gss_supported == NULL)
660 gss_indicate_mechs(&min, &gss_supported); 725 if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
726 gss_supported = NULL;
727 free(gss_host);
728 return 0;
729 }
661 730
662 /* Check to see if the mechanism is usable before we offer it */ 731 /* Check to see if the mechanism is usable before we offer it */
663 while (mech < gss_supported->count && !ok) { 732 while (mech < gss_supported->count && !ok) {
664 /* My DER encoding requires length<128 */ 733 /* My DER encoding requires length<128 */
665 if (gss_supported->elements[mech].length < 128 && 734 if (gss_supported->elements[mech].length < 128 &&
666 ssh_gssapi_check_mechanism(&gssctxt, 735 ssh_gssapi_check_mechanism(&gssctxt,
667 &gss_supported->elements[mech], authctxt->host)) { 736 &gss_supported->elements[mech], gss_host,
737 options.gss_client_identity)) {
668 ok = 1; /* Mechanism works */ 738 ok = 1; /* Mechanism works */
669 } else { 739 } else {
670 mech++; 740 mech++;
671 } 741 }
672 } 742 }
673 743
744 free(gss_host);
745
674 if (!ok) 746 if (!ok)
675 return 0; 747 return 0;
676 748
@@ -761,8 +833,8 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt)
761{ 833{
762 Authctxt *authctxt = ctxt; 834 Authctxt *authctxt = ctxt;
763 Gssctxt *gssctxt; 835 Gssctxt *gssctxt;
764 int oidlen; 836 u_int oidlen;
765 char *oidv; 837 u_char *oidv;
766 838
767 if (authctxt == NULL) 839 if (authctxt == NULL)
768 fatal("input_gssapi_response: no authentication context"); 840 fatal("input_gssapi_response: no authentication context");
@@ -875,6 +947,48 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt)
875 free(lang); 947 free(lang);
876 return 0; 948 return 0;
877} 949}
950
951int
952userauth_gsskeyex(Authctxt *authctxt)
953{
954 Buffer b;
955 gss_buffer_desc gssbuf;
956 gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
957 OM_uint32 ms;
958
959 static int attempt = 0;
960 if (attempt++ >= 1)
961 return (0);
962
963 if (gss_kex_context == NULL) {
964 debug("No valid Key exchange context");
965 return (0);
966 }
967
968 ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
969 "gssapi-keyex");
970
971 gssbuf.value = buffer_ptr(&b);
972 gssbuf.length = buffer_len(&b);
973
974 if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
975 buffer_free(&b);
976 return (0);
977 }
978
979 packet_start(SSH2_MSG_USERAUTH_REQUEST);
980 packet_put_cstring(authctxt->server_user);
981 packet_put_cstring(authctxt->service);
982 packet_put_cstring(authctxt->method->name);
983 packet_put_string(mic.value, mic.length);
984 packet_send();
985
986 buffer_free(&b);
987 gss_release_buffer(&ms, &mic);
988
989 return (1);
990}
991
878#endif /* GSSAPI */ 992#endif /* GSSAPI */
879 993
880int 994int