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 1f4a74cf4..83562c688 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(options.rekey_limit, 230 packet_set_rekey_limits(options.rekey_limit,
197 options.rekey_interval); 231 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 ssh_dispatch_run_fatal(active_state, DISPATCH_BLOCK, &kex->done); 270 ssh_dispatch_run_fatal(active_state, DISPATCH_BLOCK, &kex->done);
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, struct ssh *);
311int input_gssapi_hash(int type, u_int32_t, struct ssh *); 371int input_gssapi_hash(int type, u_int32_t, struct ssh *);
312int input_gssapi_error(int, u_int32_t, struct ssh *); 372int input_gssapi_error(int, u_int32_t, struct ssh *);
313int input_gssapi_errtok(int, u_int32_t, struct ssh *); 373int input_gssapi_errtok(int, u_int32_t, struct ssh *);
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,
@@ -643,25 +709,40 @@ userauth_gssapi(Authctxt *authctxt)
643 static u_int mech = 0; 709 static u_int mech = 0;
644 OM_uint32 min; 710 OM_uint32 min;
645 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);
646 720
647 /* 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
648 * once. */ 722 * once. */
649 723
650 if (gss_supported == NULL) 724 if (gss_supported == NULL)
651 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 }
652 730
653 /* 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 */
654 while (mech < gss_supported->count && !ok) { 732 while (mech < gss_supported->count && !ok) {
655 /* My DER encoding requires length<128 */ 733 /* My DER encoding requires length<128 */
656 if (gss_supported->elements[mech].length < 128 && 734 if (gss_supported->elements[mech].length < 128 &&
657 ssh_gssapi_check_mechanism(&gssctxt, 735 ssh_gssapi_check_mechanism(&gssctxt,
658 &gss_supported->elements[mech], authctxt->host)) { 736 &gss_supported->elements[mech], gss_host,
737 options.gss_client_identity)) {
659 ok = 1; /* Mechanism works */ 738 ok = 1; /* Mechanism works */
660 } else { 739 } else {
661 mech++; 740 mech++;
662 } 741 }
663 } 742 }
664 743
744 free(gss_host);
745
665 if (!ok) 746 if (!ok)
666 return 0; 747 return 0;
667 748
@@ -752,8 +833,8 @@ input_gssapi_response(int type, u_int32_t plen, struct ssh *ssh)
752{ 833{
753 Authctxt *authctxt = ssh->authctxt; 834 Authctxt *authctxt = ssh->authctxt;
754 Gssctxt *gssctxt; 835 Gssctxt *gssctxt;
755 int oidlen; 836 u_int oidlen;
756 char *oidv; 837 u_char *oidv;
757 838
758 if (authctxt == NULL) 839 if (authctxt == NULL)
759 fatal("input_gssapi_response: no authentication context"); 840 fatal("input_gssapi_response: no authentication context");
@@ -866,6 +947,48 @@ input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh)
866 free(lang); 947 free(lang);
867 return 0; 948 return 0;
868} 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
869#endif /* GSSAPI */ 992#endif /* GSSAPI */
870 993
871int 994int