summaryrefslogtreecommitdiff
path: root/sshconnect2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sshconnect2.c')
-rw-r--r--sshconnect2.c124
1 files changed, 120 insertions, 4 deletions
diff --git a/sshconnect2.c b/sshconnect2.c
index 68f7f4fdd..7b478f16d 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -159,9 +159,34 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
159 char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; 159 char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
160 Kex *kex; 160 Kex *kex;
161 161
162#ifdef GSSAPI
163 char *orig = NULL, *gss = NULL;
164 char *gss_host = NULL;
165#endif
166
162 xxx_host = host; 167 xxx_host = host;
163 xxx_hostaddr = hostaddr; 168 xxx_hostaddr = hostaddr;
164 169
170#ifdef GSSAPI
171 if (options.gss_keyex) {
172 /* Add the GSSAPI mechanisms currently supported on this
173 * client to the key exchange algorithm proposal */
174 orig = myproposal[PROPOSAL_KEX_ALGS];
175
176 if (options.gss_trust_dns)
177 gss_host = (char *)get_canonical_hostname(1);
178 else
179 gss_host = host;
180
181 gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity);
182 if (gss) {
183 debug("Offering GSSAPI proposal: %s", gss);
184 xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
185 "%s,%s", gss, orig);
186 }
187 }
188#endif
189
165 if (options.ciphers == (char *)-1) { 190 if (options.ciphers == (char *)-1) {
166 logit("No valid ciphers for protocol version 2 given, using defaults."); 191 logit("No valid ciphers for protocol version 2 given, using defaults.");
167 options.ciphers = NULL; 192 options.ciphers = NULL;
@@ -199,6 +224,17 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
199 myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal( 224 myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(
200 myproposal[PROPOSAL_KEX_ALGS]); 225 myproposal[PROPOSAL_KEX_ALGS]);
201 226
227#ifdef GSSAPI
228 /* If we've got GSSAPI algorithms, then we also support the
229 * 'null' hostkey, as a last resort */
230 if (options.gss_keyex && gss) {
231 orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
232 xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
233 "%s,null", orig);
234 free(gss);
235 }
236#endif
237
202 if (options.rekey_limit || options.rekey_interval) 238 if (options.rekey_limit || options.rekey_interval)
203 packet_set_rekey_limits((u_int32_t)options.rekey_limit, 239 packet_set_rekey_limits((u_int32_t)options.rekey_limit,
204 (time_t)options.rekey_interval); 240 (time_t)options.rekey_interval);
@@ -213,10 +249,30 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
213 kex->kex[KEX_ECDH_SHA2] = kexecdh_client; 249 kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
214#endif 250#endif
215 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
216 kex->client_version_string=client_version_string; 259 kex->client_version_string=client_version_string;
217 kex->server_version_string=server_version_string; 260 kex->server_version_string=server_version_string;
218 kex->verify_host_key=&verify_host_key_callback; 261 kex->verify_host_key=&verify_host_key_callback;
219 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 if (options.gss_server_identity) {
269 kex->gss_host = options.gss_server_identity;
270 } else {
271 kex->gss_host = gss_host;
272 }
273 }
274#endif
275
220 xxx_kex = kex; 276 xxx_kex = kex;
221 277
222 dispatch_run(DISPATCH_BLOCK, &kex->done, kex); 278 dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
@@ -306,6 +362,7 @@ void input_gssapi_token(int type, u_int32_t, void *);
306void input_gssapi_hash(int type, u_int32_t, void *); 362void input_gssapi_hash(int type, u_int32_t, void *);
307void input_gssapi_error(int, u_int32_t, void *); 363void input_gssapi_error(int, u_int32_t, void *);
308void input_gssapi_errtok(int, u_int32_t, void *); 364void input_gssapi_errtok(int, u_int32_t, void *);
365int userauth_gsskeyex(Authctxt *authctxt);
309#endif 366#endif
310 367
311void userauth(Authctxt *, char *); 368void userauth(Authctxt *, char *);
@@ -321,6 +378,11 @@ static char *authmethods_get(void);
321 378
322Authmethod authmethods[] = { 379Authmethod authmethods[] = {
323#ifdef GSSAPI 380#ifdef GSSAPI
381 {"gssapi-keyex",
382 userauth_gsskeyex,
383 NULL,
384 &options.gss_authentication,
385 NULL},
324 {"gssapi-with-mic", 386 {"gssapi-with-mic",
325 userauth_gssapi, 387 userauth_gssapi,
326 NULL, 388 NULL,
@@ -617,19 +679,31 @@ userauth_gssapi(Authctxt *authctxt)
617 static u_int mech = 0; 679 static u_int mech = 0;
618 OM_uint32 min; 680 OM_uint32 min;
619 int ok = 0; 681 int ok = 0;
682 const char *gss_host;
683
684 if (options.gss_server_identity)
685 gss_host = options.gss_server_identity;
686 else if (options.gss_trust_dns)
687 gss_host = get_canonical_hostname(1);
688 else
689 gss_host = authctxt->host;
620 690
621 /* Try one GSSAPI method at a time, rather than sending them all at 691 /* Try one GSSAPI method at a time, rather than sending them all at
622 * once. */ 692 * once. */
623 693
624 if (gss_supported == NULL) 694 if (gss_supported == NULL)
625 gss_indicate_mechs(&min, &gss_supported); 695 if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
696 gss_supported = NULL;
697 return 0;
698 }
626 699
627 /* Check to see if the mechanism is usable before we offer it */ 700 /* Check to see if the mechanism is usable before we offer it */
628 while (mech < gss_supported->count && !ok) { 701 while (mech < gss_supported->count && !ok) {
629 /* My DER encoding requires length<128 */ 702 /* My DER encoding requires length<128 */
630 if (gss_supported->elements[mech].length < 128 && 703 if (gss_supported->elements[mech].length < 128 &&
631 ssh_gssapi_check_mechanism(&gssctxt, 704 ssh_gssapi_check_mechanism(&gssctxt,
632 &gss_supported->elements[mech], authctxt->host)) { 705 &gss_supported->elements[mech], gss_host,
706 options.gss_client_identity)) {
633 ok = 1; /* Mechanism works */ 707 ok = 1; /* Mechanism works */
634 } else { 708 } else {
635 mech++; 709 mech++;
@@ -726,8 +800,8 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt)
726{ 800{
727 Authctxt *authctxt = ctxt; 801 Authctxt *authctxt = ctxt;
728 Gssctxt *gssctxt; 802 Gssctxt *gssctxt;
729 int oidlen; 803 u_int oidlen;
730 char *oidv; 804 u_char *oidv;
731 805
732 if (authctxt == NULL) 806 if (authctxt == NULL)
733 fatal("input_gssapi_response: no authentication context"); 807 fatal("input_gssapi_response: no authentication context");
@@ -836,6 +910,48 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt)
836 free(msg); 910 free(msg);
837 free(lang); 911 free(lang);
838} 912}
913
914int
915userauth_gsskeyex(Authctxt *authctxt)
916{
917 Buffer b;
918 gss_buffer_desc gssbuf;
919 gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
920 OM_uint32 ms;
921
922 static int attempt = 0;
923 if (attempt++ >= 1)
924 return (0);
925
926 if (gss_kex_context == NULL) {
927 debug("No valid Key exchange context");
928 return (0);
929 }
930
931 ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
932 "gssapi-keyex");
933
934 gssbuf.value = buffer_ptr(&b);
935 gssbuf.length = buffer_len(&b);
936
937 if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
938 buffer_free(&b);
939 return (0);
940 }
941
942 packet_start(SSH2_MSG_USERAUTH_REQUEST);
943 packet_put_cstring(authctxt->server_user);
944 packet_put_cstring(authctxt->service);
945 packet_put_cstring(authctxt->method->name);
946 packet_put_string(mic.value, mic.length);
947 packet_send();
948
949 buffer_free(&b);
950 gss_release_buffer(&ms, &mic);
951
952 return (1);
953}
954
839#endif /* GSSAPI */ 955#endif /* GSSAPI */
840 956
841int 957int