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 775103185..32e9b0df2 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -160,6 +160,11 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
160 struct kex *kex; 160 struct kex *kex;
161 int r; 161 int r;
162 162
163#ifdef GSSAPI
164 char *orig = NULL, *gss = NULL;
165 char *gss_host = NULL;
166#endif
167
163 xxx_host = host; 168 xxx_host = host;
164 xxx_hostaddr = hostaddr; 169 xxx_hostaddr = hostaddr;
165 170
@@ -193,6 +198,33 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
193 order_hostkeyalgs(host, hostaddr, port)); 198 order_hostkeyalgs(host, hostaddr, port));
194 } 199 }
195 200
201#ifdef GSSAPI
202 if (options.gss_keyex) {
203 /* Add the GSSAPI mechanisms currently supported on this
204 * client to the key exchange algorithm proposal */
205 orig = myproposal[PROPOSAL_KEX_ALGS];
206
207 if (options.gss_trust_dns)
208 gss_host = (char *)get_canonical_hostname(1);
209 else
210 gss_host = host;
211
212 gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity);
213 if (gss) {
214 debug("Offering GSSAPI proposal: %s", gss);
215 xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
216 "%s,%s", gss, orig);
217
218 /* If we've got GSSAPI algorithms, then we also
219 * support the 'null' hostkey, as a last resort */
220 orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
221 xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
222 "%s,null", orig);
223 free(gss);
224 }
225 }
226#endif
227
196 if (options.rekey_limit || options.rekey_interval) 228 if (options.rekey_limit || options.rekey_interval)
197 packet_set_rekey_limits((u_int32_t)options.rekey_limit, 229 packet_set_rekey_limits((u_int32_t)options.rekey_limit,
198 (time_t)options.rekey_interval); 230 (time_t)options.rekey_interval);
@@ -211,10 +243,30 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
211# endif 243# endif
212#endif 244#endif
213 kex->kex[KEX_C25519_SHA256] = kexc25519_client; 245 kex->kex[KEX_C25519_SHA256] = kexc25519_client;
246#ifdef GSSAPI
247 if (options.gss_keyex) {
248 kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
249 kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
250 kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
251 }
252#endif
214 kex->client_version_string=client_version_string; 253 kex->client_version_string=client_version_string;
215 kex->server_version_string=server_version_string; 254 kex->server_version_string=server_version_string;
216 kex->verify_host_key=&verify_host_key_callback; 255 kex->verify_host_key=&verify_host_key_callback;
217 256
257#ifdef GSSAPI
258 if (options.gss_keyex) {
259 kex->gss_deleg_creds = options.gss_deleg_creds;
260 kex->gss_trust_dns = options.gss_trust_dns;
261 kex->gss_client = options.gss_client_identity;
262 if (options.gss_server_identity) {
263 kex->gss_host = options.gss_server_identity;
264 } else {
265 kex->gss_host = gss_host;
266 }
267 }
268#endif
269
218 dispatch_run(DISPATCH_BLOCK, &kex->done, active_state); 270 dispatch_run(DISPATCH_BLOCK, &kex->done, active_state);
219 271
220 if (options.use_roaming && !kex->roaming) { 272 if (options.use_roaming && !kex->roaming) {
@@ -306,6 +358,7 @@ int input_gssapi_token(int type, u_int32_t, void *);
306int input_gssapi_hash(int type, u_int32_t, void *); 358int input_gssapi_hash(int type, u_int32_t, void *);
307int input_gssapi_error(int, u_int32_t, void *); 359int input_gssapi_error(int, u_int32_t, void *);
308int input_gssapi_errtok(int, u_int32_t, void *); 360int input_gssapi_errtok(int, u_int32_t, void *);
361int userauth_gsskeyex(Authctxt *authctxt);
309#endif 362#endif
310 363
311void userauth(Authctxt *, char *); 364void userauth(Authctxt *, char *);
@@ -321,6 +374,11 @@ static char *authmethods_get(void);
321 374
322Authmethod authmethods[] = { 375Authmethod authmethods[] = {
323#ifdef GSSAPI 376#ifdef GSSAPI
377 {"gssapi-keyex",
378 userauth_gsskeyex,
379 NULL,
380 &options.gss_authentication,
381 NULL},
324 {"gssapi-with-mic", 382 {"gssapi-with-mic",
325 userauth_gssapi, 383 userauth_gssapi,
326 NULL, 384 NULL,
@@ -627,19 +685,31 @@ userauth_gssapi(Authctxt *authctxt)
627 static u_int mech = 0; 685 static u_int mech = 0;
628 OM_uint32 min; 686 OM_uint32 min;
629 int ok = 0; 687 int ok = 0;
688 const char *gss_host;
689
690 if (options.gss_server_identity)
691 gss_host = options.gss_server_identity;
692 else if (options.gss_trust_dns)
693 gss_host = get_canonical_hostname(1);
694 else
695 gss_host = authctxt->host;
630 696
631 /* Try one GSSAPI method at a time, rather than sending them all at 697 /* Try one GSSAPI method at a time, rather than sending them all at
632 * once. */ 698 * once. */
633 699
634 if (gss_supported == NULL) 700 if (gss_supported == NULL)
635 gss_indicate_mechs(&min, &gss_supported); 701 if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
702 gss_supported = NULL;
703 return 0;
704 }
636 705
637 /* Check to see if the mechanism is usable before we offer it */ 706 /* Check to see if the mechanism is usable before we offer it */
638 while (mech < gss_supported->count && !ok) { 707 while (mech < gss_supported->count && !ok) {
639 /* My DER encoding requires length<128 */ 708 /* My DER encoding requires length<128 */
640 if (gss_supported->elements[mech].length < 128 && 709 if (gss_supported->elements[mech].length < 128 &&
641 ssh_gssapi_check_mechanism(&gssctxt, 710 ssh_gssapi_check_mechanism(&gssctxt,
642 &gss_supported->elements[mech], authctxt->host)) { 711 &gss_supported->elements[mech], gss_host,
712 options.gss_client_identity)) {
643 ok = 1; /* Mechanism works */ 713 ok = 1; /* Mechanism works */
644 } else { 714 } else {
645 mech++; 715 mech++;
@@ -736,8 +806,8 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt)
736{ 806{
737 Authctxt *authctxt = ctxt; 807 Authctxt *authctxt = ctxt;
738 Gssctxt *gssctxt; 808 Gssctxt *gssctxt;
739 int oidlen; 809 u_int oidlen;
740 char *oidv; 810 u_char *oidv;
741 811
742 if (authctxt == NULL) 812 if (authctxt == NULL)
743 fatal("input_gssapi_response: no authentication context"); 813 fatal("input_gssapi_response: no authentication context");
@@ -850,6 +920,48 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt)
850 free(lang); 920 free(lang);
851 return 0; 921 return 0;
852} 922}
923
924int
925userauth_gsskeyex(Authctxt *authctxt)
926{
927 Buffer b;
928 gss_buffer_desc gssbuf;
929 gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
930 OM_uint32 ms;
931
932 static int attempt = 0;
933 if (attempt++ >= 1)
934 return (0);
935
936 if (gss_kex_context == NULL) {
937 debug("No valid Key exchange context");
938 return (0);
939 }
940
941 ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
942 "gssapi-keyex");
943
944 gssbuf.value = buffer_ptr(&b);
945 gssbuf.length = buffer_len(&b);
946
947 if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
948 buffer_free(&b);
949 return (0);
950 }
951
952 packet_start(SSH2_MSG_USERAUTH_REQUEST);
953 packet_put_cstring(authctxt->server_user);
954 packet_put_cstring(authctxt->service);
955 packet_put_cstring(authctxt->method->name);
956 packet_put_string(mic.value, mic.length);
957 packet_send();
958
959 buffer_free(&b);
960 gss_release_buffer(&ms, &mic);
961
962 return (1);
963}
964
853#endif /* GSSAPI */ 965#endif /* GSSAPI */
854 966
855int 967int