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 be9397e48..c22477f59 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,
@@ -654,25 +720,40 @@ userauth_gssapi(Authctxt *authctxt)
654 static u_int mech = 0; 720 static u_int mech = 0;
655 OM_uint32 min; 721 OM_uint32 min;
656 int ok = 0; 722 int ok = 0;
723 char *gss_host;
724
725 if (options.gss_server_identity)
726 gss_host = xstrdup(options.gss_server_identity);
727 else if (options.gss_trust_dns)
728 gss_host = remote_hostname(active_state);
729 else
730 gss_host = xstrdup(authctxt->host);
657 731
658 /* Try one GSSAPI method at a time, rather than sending them all at 732 /* Try one GSSAPI method at a time, rather than sending them all at
659 * once. */ 733 * once. */
660 734
661 if (gss_supported == NULL) 735 if (gss_supported == NULL)
662 gss_indicate_mechs(&min, &gss_supported); 736 if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
737 gss_supported = NULL;
738 free(gss_host);
739 return 0;
740 }
663 741
664 /* Check to see if the mechanism is usable before we offer it */ 742 /* Check to see if the mechanism is usable before we offer it */
665 while (mech < gss_supported->count && !ok) { 743 while (mech < gss_supported->count && !ok) {
666 /* My DER encoding requires length<128 */ 744 /* My DER encoding requires length<128 */
667 if (gss_supported->elements[mech].length < 128 && 745 if (gss_supported->elements[mech].length < 128 &&
668 ssh_gssapi_check_mechanism(&gssctxt, 746 ssh_gssapi_check_mechanism(&gssctxt,
669 &gss_supported->elements[mech], authctxt->host)) { 747 &gss_supported->elements[mech], gss_host,
748 options.gss_client_identity)) {
670 ok = 1; /* Mechanism works */ 749 ok = 1; /* Mechanism works */
671 } else { 750 } else {
672 mech++; 751 mech++;
673 } 752 }
674 } 753 }
675 754
755 free(gss_host);
756
676 if (!ok) 757 if (!ok)
677 return 0; 758 return 0;
678 759
@@ -763,8 +844,8 @@ input_gssapi_response(int type, u_int32_t plen, struct ssh *ssh)
763{ 844{
764 Authctxt *authctxt = ssh->authctxt; 845 Authctxt *authctxt = ssh->authctxt;
765 Gssctxt *gssctxt; 846 Gssctxt *gssctxt;
766 int oidlen; 847 u_int oidlen;
767 char *oidv; 848 u_char *oidv;
768 849
769 if (authctxt == NULL) 850 if (authctxt == NULL)
770 fatal("input_gssapi_response: no authentication context"); 851 fatal("input_gssapi_response: no authentication context");
@@ -877,6 +958,48 @@ input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh)
877 free(lang); 958 free(lang);
878 return 0; 959 return 0;
879} 960}
961
962int
963userauth_gsskeyex(Authctxt *authctxt)
964{
965 Buffer b;
966 gss_buffer_desc gssbuf;
967 gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
968 OM_uint32 ms;
969
970 static int attempt = 0;
971 if (attempt++ >= 1)
972 return (0);
973
974 if (gss_kex_context == NULL) {
975 debug("No valid Key exchange context");
976 return (0);
977 }
978
979 ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
980 "gssapi-keyex");
981
982 gssbuf.value = buffer_ptr(&b);
983 gssbuf.length = buffer_len(&b);
984
985 if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
986 buffer_free(&b);
987 return (0);
988 }
989
990 packet_start(SSH2_MSG_USERAUTH_REQUEST);
991 packet_put_cstring(authctxt->server_user);
992 packet_put_cstring(authctxt->service);
993 packet_put_cstring(authctxt->method->name);
994 packet_put_string(mic.value, mic.length);
995 packet_send();
996
997 buffer_free(&b);
998 gss_release_buffer(&ms, &mic);
999
1000 return (1);
1001}
1002
880#endif /* GSSAPI */ 1003#endif /* GSSAPI */
881 1004
882int 1005int