summaryrefslogtreecommitdiff
path: root/sshconnect2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshconnect2.c')
-rw-r--r--sshconnect2.c133
1 files changed, 131 insertions, 2 deletions
diff --git a/sshconnect2.c b/sshconnect2.c
index 10e4f0a08..c6a1b1271 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
@@ -194,6 +199,35 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
194 order_hostkeyalgs(host, hostaddr, port)); 199 order_hostkeyalgs(host, hostaddr, port));
195 } 200 }
196 201
202#ifdef GSSAPI
203 if (options.gss_keyex) {
204 /* Add the GSSAPI mechanisms currently supported on this
205 * client to the key exchange algorithm proposal */
206 orig = myproposal[PROPOSAL_KEX_ALGS];
207
208 if (options.gss_server_identity)
209 gss_host = xstrdup(options.gss_server_identity);
210 else if (options.gss_trust_dns)
211 gss_host = remote_hostname(active_state);
212 else
213 gss_host = xstrdup(host);
214
215 gss = ssh_gssapi_client_mechanisms(gss_host,
216 options.gss_client_identity);
217 if (gss) {
218 debug("Offering GSSAPI proposal: %s", gss);
219 xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
220 "%s,%s", gss, orig);
221
222 /* If we've got GSSAPI algorithms, then we also
223 * support the 'null' hostkey, as a last resort */
224 orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
225 xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
226 "%s,null", orig);
227 }
228 }
229#endif
230
197 if (options.rekey_limit || options.rekey_interval) 231 if (options.rekey_limit || options.rekey_interval)
198 packet_set_rekey_limits(options.rekey_limit, 232 packet_set_rekey_limits(options.rekey_limit,
199 options.rekey_interval); 233 options.rekey_interval);
@@ -215,15 +249,41 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
215# endif 249# endif
216#endif 250#endif
217 kex->kex[KEX_C25519_SHA256] = kexc25519_client; 251 kex->kex[KEX_C25519_SHA256] = kexc25519_client;
252#ifdef GSSAPI
253 if (options.gss_keyex) {
254 kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
255 kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
256 kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
257 }
258#endif
218 kex->client_version_string=client_version_string; 259 kex->client_version_string=client_version_string;
219 kex->server_version_string=server_version_string; 260 kex->server_version_string=server_version_string;
220 kex->verify_host_key=&verify_host_key_callback; 261 kex->verify_host_key=&verify_host_key_callback;
221 262
263#ifdef GSSAPI
264 if (options.gss_keyex) {
265 kex->gss_deleg_creds = options.gss_deleg_creds;
266 kex->gss_trust_dns = options.gss_trust_dns;
267 kex->gss_client = options.gss_client_identity;
268 kex->gss_host = gss_host;
269 }
270#endif
271
222 ssh_dispatch_run_fatal(active_state, DISPATCH_BLOCK, &kex->done); 272 ssh_dispatch_run_fatal(active_state, DISPATCH_BLOCK, &kex->done);
223 273
224 /* remove ext-info from the KEX proposals for rekeying */ 274 /* remove ext-info from the KEX proposals for rekeying */
225 myproposal[PROPOSAL_KEX_ALGS] = 275 myproposal[PROPOSAL_KEX_ALGS] =
226 compat_kex_proposal(options.kex_algorithms); 276 compat_kex_proposal(options.kex_algorithms);
277#ifdef GSSAPI
278 /* repair myproposal after it was crumpled by the */
279 /* ext-info removal above */
280 if (gss) {
281 orig = myproposal[PROPOSAL_KEX_ALGS];
282 xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
283 "%s,%s", gss, orig);
284 free(gss);
285 }
286#endif
227 if ((r = kex_prop2buf(kex->my, myproposal)) != 0) 287 if ((r = kex_prop2buf(kex->my, myproposal)) != 0)
228 fatal("kex_prop2buf: %s", ssh_err(r)); 288 fatal("kex_prop2buf: %s", ssh_err(r));
229 289
@@ -314,6 +374,7 @@ int input_gssapi_token(int type, u_int32_t, struct ssh *);
314int input_gssapi_hash(int type, u_int32_t, struct ssh *); 374int input_gssapi_hash(int type, u_int32_t, struct ssh *);
315int input_gssapi_error(int, u_int32_t, struct ssh *); 375int input_gssapi_error(int, u_int32_t, struct ssh *);
316int input_gssapi_errtok(int, u_int32_t, struct ssh *); 376int input_gssapi_errtok(int, u_int32_t, struct ssh *);
377int userauth_gsskeyex(Authctxt *authctxt);
317#endif 378#endif
318 379
319void userauth(Authctxt *, char *); 380void userauth(Authctxt *, char *);
@@ -330,6 +391,11 @@ static char *authmethods_get(void);
330 391
331Authmethod authmethods[] = { 392Authmethod authmethods[] = {
332#ifdef GSSAPI 393#ifdef GSSAPI
394 {"gssapi-keyex",
395 userauth_gsskeyex,
396 NULL,
397 &options.gss_authentication,
398 NULL},
333 {"gssapi-with-mic", 399 {"gssapi-with-mic",
334 userauth_gssapi, 400 userauth_gssapi,
335 NULL, 401 NULL,
@@ -657,25 +723,40 @@ userauth_gssapi(Authctxt *authctxt)
657 static u_int mech = 0; 723 static u_int mech = 0;
658 OM_uint32 min; 724 OM_uint32 min;
659 int r, ok = 0; 725 int r, ok = 0;
726 char *gss_host;
727
728 if (options.gss_server_identity)
729 gss_host = xstrdup(options.gss_server_identity);
730 else if (options.gss_trust_dns)
731 gss_host = remote_hostname(active_state);
732 else
733 gss_host = xstrdup(authctxt->host);
660 734
661 /* Try one GSSAPI method at a time, rather than sending them all at 735 /* Try one GSSAPI method at a time, rather than sending them all at
662 * once. */ 736 * once. */
663 737
664 if (gss_supported == NULL) 738 if (gss_supported == NULL)
665 gss_indicate_mechs(&min, &gss_supported); 739 if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
740 gss_supported = NULL;
741 free(gss_host);
742 return 0;
743 }
666 744
667 /* Check to see if the mechanism is usable before we offer it */ 745 /* Check to see if the mechanism is usable before we offer it */
668 while (mech < gss_supported->count && !ok) { 746 while (mech < gss_supported->count && !ok) {
669 /* My DER encoding requires length<128 */ 747 /* My DER encoding requires length<128 */
670 if (gss_supported->elements[mech].length < 128 && 748 if (gss_supported->elements[mech].length < 128 &&
671 ssh_gssapi_check_mechanism(&gssctxt, 749 ssh_gssapi_check_mechanism(&gssctxt,
672 &gss_supported->elements[mech], authctxt->host)) { 750 &gss_supported->elements[mech], gss_host,
751 options.gss_client_identity)) {
673 ok = 1; /* Mechanism works */ 752 ok = 1; /* Mechanism works */
674 } else { 753 } else {
675 mech++; 754 mech++;
676 } 755 }
677 } 756 }
678 757
758 free(gss_host);
759
679 if (!ok) 760 if (!ok)
680 return 0; 761 return 0;
681 762
@@ -906,6 +987,54 @@ input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh)
906 free(lang); 987 free(lang);
907 return r; 988 return r;
908} 989}
990
991int
992userauth_gsskeyex(Authctxt *authctxt)
993{
994 struct ssh *ssh = active_state; /* XXX */
995 struct sshbuf *b;
996 gss_buffer_desc gssbuf;
997 gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
998 OM_uint32 ms;
999 int r;
1000
1001 static int attempt = 0;
1002 if (attempt++ >= 1)
1003 return (0);
1004
1005 if (gss_kex_context == NULL) {
1006 debug("No valid Key exchange context");
1007 return (0);
1008 }
1009
1010 if ((b = sshbuf_new()) == NULL)
1011 fatal("%s: sshbuf_new failed", __func__);
1012 ssh_gssapi_buildmic(b, authctxt->server_user, authctxt->service,
1013 "gssapi-keyex");
1014
1015 if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL)
1016 fatal("%s: sshbuf_mutable_ptr failed", __func__);
1017 gssbuf.length = sshbuf_len(b);
1018
1019 if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
1020 sshbuf_free(b);
1021 return (0);
1022 }
1023
1024 if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 ||
1025 (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 ||
1026 (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 ||
1027 (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 ||
1028 (r = sshpkt_put_string(ssh, mic.value, mic.length)) != 0 ||
1029 (r = sshpkt_send(ssh)) != 0)
1030 fatal("%s: %s", __func__, ssh_err(r));
1031
1032 sshbuf_free(b);
1033 gss_release_buffer(&ms, &mic);
1034
1035 return (1);
1036}
1037
909#endif /* GSSAPI */ 1038#endif /* GSSAPI */
910 1039
911int 1040int