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