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 fae8b0f2c..34b9d304e 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 *);
@@ -326,6 +378,11 @@ static char *authmethods_get(void);
326 378
327Authmethod authmethods[] = { 379Authmethod authmethods[] = {
328#ifdef GSSAPI 380#ifdef GSSAPI
381 {"gssapi-keyex",
382 userauth_gsskeyex,
383 NULL,
384 &options.gss_authentication,
385 NULL},
329 {"gssapi-with-mic", 386 {"gssapi-with-mic",
330 userauth_gssapi, 387 userauth_gssapi,
331 NULL, 388 NULL,
@@ -650,25 +707,40 @@ userauth_gssapi(Authctxt *authctxt)
650 static u_int mech = 0; 707 static u_int mech = 0;
651 OM_uint32 min; 708 OM_uint32 min;
652 int ok = 0; 709 int ok = 0;
710 char *gss_host;
711
712 if (options.gss_server_identity)
713 gss_host = xstrdup(options.gss_server_identity);
714 else if (options.gss_trust_dns)
715 gss_host = remote_hostname(active_state);
716 else
717 gss_host = xstrdup(authctxt->host);
653 718
654 /* Try one GSSAPI method at a time, rather than sending them all at 719 /* Try one GSSAPI method at a time, rather than sending them all at
655 * once. */ 720 * once. */
656 721
657 if (gss_supported == NULL) 722 if (gss_supported == NULL)
658 gss_indicate_mechs(&min, &gss_supported); 723 if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
724 gss_supported = NULL;
725 free(gss_host);
726 return 0;
727 }
659 728
660 /* Check to see if the mechanism is usable before we offer it */ 729 /* Check to see if the mechanism is usable before we offer it */
661 while (mech < gss_supported->count && !ok) { 730 while (mech < gss_supported->count && !ok) {
662 /* My DER encoding requires length<128 */ 731 /* My DER encoding requires length<128 */
663 if (gss_supported->elements[mech].length < 128 && 732 if (gss_supported->elements[mech].length < 128 &&
664 ssh_gssapi_check_mechanism(&gssctxt, 733 ssh_gssapi_check_mechanism(&gssctxt,
665 &gss_supported->elements[mech], authctxt->host)) { 734 &gss_supported->elements[mech], gss_host,
735 options.gss_client_identity)) {
666 ok = 1; /* Mechanism works */ 736 ok = 1; /* Mechanism works */
667 } else { 737 } else {
668 mech++; 738 mech++;
669 } 739 }
670 } 740 }
671 741
742 free(gss_host);
743
672 if (!ok) 744 if (!ok)
673 return 0; 745 return 0;
674 746
@@ -759,8 +831,8 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt)
759{ 831{
760 Authctxt *authctxt = ctxt; 832 Authctxt *authctxt = ctxt;
761 Gssctxt *gssctxt; 833 Gssctxt *gssctxt;
762 int oidlen; 834 u_int oidlen;
763 char *oidv; 835 u_char *oidv;
764 836
765 if (authctxt == NULL) 837 if (authctxt == NULL)
766 fatal("input_gssapi_response: no authentication context"); 838 fatal("input_gssapi_response: no authentication context");
@@ -873,6 +945,48 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt)
873 free(lang); 945 free(lang);
874 return 0; 946 return 0;
875} 947}
948
949int
950userauth_gsskeyex(Authctxt *authctxt)
951{
952 Buffer b;
953 gss_buffer_desc gssbuf;
954 gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
955 OM_uint32 ms;
956
957 static int attempt = 0;
958 if (attempt++ >= 1)
959 return (0);
960
961 if (gss_kex_context == NULL) {
962 debug("No valid Key exchange context");
963 return (0);
964 }
965
966 ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
967 "gssapi-keyex");
968
969 gssbuf.value = buffer_ptr(&b);
970 gssbuf.length = buffer_len(&b);
971
972 if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
973 buffer_free(&b);
974 return (0);
975 }
976
977 packet_start(SSH2_MSG_USERAUTH_REQUEST);
978 packet_put_cstring(authctxt->server_user);
979 packet_put_cstring(authctxt->service);
980 packet_put_cstring(authctxt->method->name);
981 packet_put_string(mic.value, mic.length);
982 packet_send();
983
984 buffer_free(&b);
985 gss_release_buffer(&ms, &mic);
986
987 return (1);
988}
989
876#endif /* GSSAPI */ 990#endif /* GSSAPI */
877 991
878int 992int