summaryrefslogtreecommitdiff
path: root/sshconnect2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshconnect2.c')
-rw-r--r--sshconnect2.c131
1 files changed, 127 insertions, 4 deletions
diff --git a/sshconnect2.c b/sshconnect2.c
index 103a2b36a..c35a0bd50 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,35 @@ 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 }
226 }
227#endif
228
195 if (options.rekey_limit || options.rekey_interval) 229 if (options.rekey_limit || options.rekey_interval)
196 packet_set_rekey_limits((u_int32_t)options.rekey_limit, 230 packet_set_rekey_limits((u_int32_t)options.rekey_limit,
197 (time_t)options.rekey_interval); 231 (time_t)options.rekey_interval);
@@ -213,15 +247,41 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
213# endif 247# endif
214#endif 248#endif
215 kex->kex[KEX_C25519_SHA256] = kexc25519_client; 249 kex->kex[KEX_C25519_SHA256] = kexc25519_client;
250#ifdef GSSAPI
251 if (options.gss_keyex) {
252 kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
253 kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
254 kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
255 }
256#endif
216 kex->client_version_string=client_version_string; 257 kex->client_version_string=client_version_string;
217 kex->server_version_string=server_version_string; 258 kex->server_version_string=server_version_string;
218 kex->verify_host_key=&verify_host_key_callback; 259 kex->verify_host_key=&verify_host_key_callback;
219 260
261#ifdef GSSAPI
262 if (options.gss_keyex) {
263 kex->gss_deleg_creds = options.gss_deleg_creds;
264 kex->gss_trust_dns = options.gss_trust_dns;
265 kex->gss_client = options.gss_client_identity;
266 kex->gss_host = gss_host;
267 }
268#endif
269
220 dispatch_run(DISPATCH_BLOCK, &kex->done, active_state); 270 dispatch_run(DISPATCH_BLOCK, &kex->done, active_state);
221 271
222 /* remove ext-info from the KEX proposals for rekeying */ 272 /* remove ext-info from the KEX proposals for rekeying */
223 myproposal[PROPOSAL_KEX_ALGS] = 273 myproposal[PROPOSAL_KEX_ALGS] =
224 compat_kex_proposal(options.kex_algorithms); 274 compat_kex_proposal(options.kex_algorithms);
275#ifdef GSSAPI
276 /* repair myproposal after it was crumpled by the */
277 /* ext-info removal above */
278 if (gss) {
279 orig = myproposal[PROPOSAL_KEX_ALGS];
280 xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
281 "%s,%s", gss, orig);
282 free(gss);
283 }
284#endif
225 if ((r = kex_prop2buf(kex->my, myproposal)) != 0) 285 if ((r = kex_prop2buf(kex->my, myproposal)) != 0)
226 fatal("kex_prop2buf: %s", ssh_err(r)); 286 fatal("kex_prop2buf: %s", ssh_err(r));
227 287
@@ -311,6 +371,7 @@ int input_gssapi_token(int type, u_int32_t, void *);
311int input_gssapi_hash(int type, u_int32_t, void *); 371int input_gssapi_hash(int type, u_int32_t, void *);
312int input_gssapi_error(int, u_int32_t, void *); 372int input_gssapi_error(int, u_int32_t, void *);
313int input_gssapi_errtok(int, u_int32_t, void *); 373int input_gssapi_errtok(int, u_int32_t, void *);
374int userauth_gsskeyex(Authctxt *authctxt);
314#endif 375#endif
315 376
316void userauth(Authctxt *, char *); 377void userauth(Authctxt *, char *);
@@ -327,6 +388,11 @@ static char *authmethods_get(void);
327 388
328Authmethod authmethods[] = { 389Authmethod authmethods[] = {
329#ifdef GSSAPI 390#ifdef GSSAPI
391 {"gssapi-keyex",
392 userauth_gsskeyex,
393 NULL,
394 &options.gss_authentication,
395 NULL},
330 {"gssapi-with-mic", 396 {"gssapi-with-mic",
331 userauth_gssapi, 397 userauth_gssapi,
332 NULL, 398 NULL,
@@ -652,25 +718,40 @@ userauth_gssapi(Authctxt *authctxt)
652 static u_int mech = 0; 718 static u_int mech = 0;
653 OM_uint32 min; 719 OM_uint32 min;
654 int ok = 0; 720 int ok = 0;
721 char *gss_host;
722
723 if (options.gss_server_identity)
724 gss_host = xstrdup(options.gss_server_identity);
725 else if (options.gss_trust_dns)
726 gss_host = remote_hostname(active_state);
727 else
728 gss_host = xstrdup(authctxt->host);
655 729
656 /* Try one GSSAPI method at a time, rather than sending them all at 730 /* Try one GSSAPI method at a time, rather than sending them all at
657 * once. */ 731 * once. */
658 732
659 if (gss_supported == NULL) 733 if (gss_supported == NULL)
660 gss_indicate_mechs(&min, &gss_supported); 734 if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
735 gss_supported = NULL;
736 free(gss_host);
737 return 0;
738 }
661 739
662 /* Check to see if the mechanism is usable before we offer it */ 740 /* Check to see if the mechanism is usable before we offer it */
663 while (mech < gss_supported->count && !ok) { 741 while (mech < gss_supported->count && !ok) {
664 /* My DER encoding requires length<128 */ 742 /* My DER encoding requires length<128 */
665 if (gss_supported->elements[mech].length < 128 && 743 if (gss_supported->elements[mech].length < 128 &&
666 ssh_gssapi_check_mechanism(&gssctxt, 744 ssh_gssapi_check_mechanism(&gssctxt,
667 &gss_supported->elements[mech], authctxt->host)) { 745 &gss_supported->elements[mech], gss_host,
746 options.gss_client_identity)) {
668 ok = 1; /* Mechanism works */ 747 ok = 1; /* Mechanism works */
669 } else { 748 } else {
670 mech++; 749 mech++;
671 } 750 }
672 } 751 }
673 752
753 free(gss_host);
754
674 if (!ok) 755 if (!ok)
675 return 0; 756 return 0;
676 757
@@ -761,8 +842,8 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt)
761{ 842{
762 Authctxt *authctxt = ctxt; 843 Authctxt *authctxt = ctxt;
763 Gssctxt *gssctxt; 844 Gssctxt *gssctxt;
764 int oidlen; 845 u_int oidlen;
765 char *oidv; 846 u_char *oidv;
766 847
767 if (authctxt == NULL) 848 if (authctxt == NULL)
768 fatal("input_gssapi_response: no authentication context"); 849 fatal("input_gssapi_response: no authentication context");
@@ -875,6 +956,48 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt)
875 free(lang); 956 free(lang);
876 return 0; 957 return 0;
877} 958}
959
960int
961userauth_gsskeyex(Authctxt *authctxt)
962{
963 Buffer b;
964 gss_buffer_desc gssbuf;
965 gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
966 OM_uint32 ms;
967
968 static int attempt = 0;
969 if (attempt++ >= 1)
970 return (0);
971
972 if (gss_kex_context == NULL) {
973 debug("No valid Key exchange context");
974 return (0);
975 }
976
977 ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
978 "gssapi-keyex");
979
980 gssbuf.value = buffer_ptr(&b);
981 gssbuf.length = buffer_len(&b);
982
983 if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
984 buffer_free(&b);
985 return (0);
986 }
987
988 packet_start(SSH2_MSG_USERAUTH_REQUEST);
989 packet_put_cstring(authctxt->server_user);
990 packet_put_cstring(authctxt->service);
991 packet_put_cstring(authctxt->method->name);
992 packet_put_string(mic.value, mic.length);
993 packet_send();
994
995 buffer_free(&b);
996 gss_release_buffer(&ms, &mic);
997
998 return (1);
999}
1000
878#endif /* GSSAPI */ 1001#endif /* GSSAPI */
879 1002
880int 1003int