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 ba56f6433..faa8ec589 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -160,9 +160,34 @@ 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
171#ifdef GSSAPI
172 if (options.gss_keyex) {
173 /* Add the GSSAPI mechanisms currently supported on this
174 * client to the key exchange algorithm proposal */
175 orig = myproposal[PROPOSAL_KEX_ALGS];
176
177 if (options.gss_trust_dns)
178 gss_host = (char *)get_canonical_hostname(1);
179 else
180 gss_host = host;
181
182 gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity);
183 if (gss) {
184 debug("Offering GSSAPI proposal: %s", gss);
185 xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
186 "%s,%s", gss, orig);
187 }
188 }
189#endif
190
166 if (options.ciphers == (char *)-1) { 191 if (options.ciphers == (char *)-1) {
167 logit("No valid ciphers for protocol version 2 given, using defaults."); 192 logit("No valid ciphers for protocol version 2 given, using defaults.");
168 options.ciphers = NULL; 193 options.ciphers = NULL;
@@ -200,6 +225,17 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
200 myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal( 225 myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(
201 myproposal[PROPOSAL_KEX_ALGS]); 226 myproposal[PROPOSAL_KEX_ALGS]);
202 227
228#ifdef GSSAPI
229 /* If we've got GSSAPI algorithms, then we also support the
230 * 'null' hostkey, as a last resort */
231 if (options.gss_keyex && gss) {
232 orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
233 xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
234 "%s,null", orig);
235 free(gss);
236 }
237#endif
238
203 if (options.rekey_limit || options.rekey_interval) 239 if (options.rekey_limit || options.rekey_interval)
204 packet_set_rekey_limits((u_int32_t)options.rekey_limit, 240 packet_set_rekey_limits((u_int32_t)options.rekey_limit,
205 (time_t)options.rekey_interval); 241 (time_t)options.rekey_interval);
@@ -218,10 +254,30 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
218# endif 254# endif
219#endif 255#endif
220 kex->kex[KEX_C25519_SHA256] = kexc25519_client; 256 kex->kex[KEX_C25519_SHA256] = kexc25519_client;
257#ifdef GSSAPI
258 if (options.gss_keyex) {
259 kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
260 kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
261 kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
262 }
263#endif
221 kex->client_version_string=client_version_string; 264 kex->client_version_string=client_version_string;
222 kex->server_version_string=server_version_string; 265 kex->server_version_string=server_version_string;
223 kex->verify_host_key=&verify_host_key_callback; 266 kex->verify_host_key=&verify_host_key_callback;
224 267
268#ifdef GSSAPI
269 if (options.gss_keyex) {
270 kex->gss_deleg_creds = options.gss_deleg_creds;
271 kex->gss_trust_dns = options.gss_trust_dns;
272 kex->gss_client = options.gss_client_identity;
273 if (options.gss_server_identity) {
274 kex->gss_host = options.gss_server_identity;
275 } else {
276 kex->gss_host = gss_host;
277 }
278 }
279#endif
280
225 dispatch_run(DISPATCH_BLOCK, &kex->done, active_state); 281 dispatch_run(DISPATCH_BLOCK, &kex->done, active_state);
226 282
227 if (options.use_roaming && !kex->roaming) { 283 if (options.use_roaming && !kex->roaming) {
@@ -313,6 +369,7 @@ int input_gssapi_token(int type, u_int32_t, void *);
313int input_gssapi_hash(int type, u_int32_t, void *); 369int input_gssapi_hash(int type, u_int32_t, void *);
314int input_gssapi_error(int, u_int32_t, void *); 370int input_gssapi_error(int, u_int32_t, void *);
315int input_gssapi_errtok(int, u_int32_t, void *); 371int input_gssapi_errtok(int, u_int32_t, void *);
372int userauth_gsskeyex(Authctxt *authctxt);
316#endif 373#endif
317 374
318void userauth(Authctxt *, char *); 375void userauth(Authctxt *, char *);
@@ -328,6 +385,11 @@ static char *authmethods_get(void);
328 385
329Authmethod authmethods[] = { 386Authmethod authmethods[] = {
330#ifdef GSSAPI 387#ifdef GSSAPI
388 {"gssapi-keyex",
389 userauth_gsskeyex,
390 NULL,
391 &options.gss_authentication,
392 NULL},
331 {"gssapi-with-mic", 393 {"gssapi-with-mic",
332 userauth_gssapi, 394 userauth_gssapi,
333 NULL, 395 NULL,
@@ -634,19 +696,31 @@ userauth_gssapi(Authctxt *authctxt)
634 static u_int mech = 0; 696 static u_int mech = 0;
635 OM_uint32 min; 697 OM_uint32 min;
636 int ok = 0; 698 int ok = 0;
699 const char *gss_host;
700
701 if (options.gss_server_identity)
702 gss_host = options.gss_server_identity;
703 else if (options.gss_trust_dns)
704 gss_host = get_canonical_hostname(1);
705 else
706 gss_host = authctxt->host;
637 707
638 /* Try one GSSAPI method at a time, rather than sending them all at 708 /* Try one GSSAPI method at a time, rather than sending them all at
639 * once. */ 709 * once. */
640 710
641 if (gss_supported == NULL) 711 if (gss_supported == NULL)
642 gss_indicate_mechs(&min, &gss_supported); 712 if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
713 gss_supported = NULL;
714 return 0;
715 }
643 716
644 /* Check to see if the mechanism is usable before we offer it */ 717 /* Check to see if the mechanism is usable before we offer it */
645 while (mech < gss_supported->count && !ok) { 718 while (mech < gss_supported->count && !ok) {
646 /* My DER encoding requires length<128 */ 719 /* My DER encoding requires length<128 */
647 if (gss_supported->elements[mech].length < 128 && 720 if (gss_supported->elements[mech].length < 128 &&
648 ssh_gssapi_check_mechanism(&gssctxt, 721 ssh_gssapi_check_mechanism(&gssctxt,
649 &gss_supported->elements[mech], authctxt->host)) { 722 &gss_supported->elements[mech], gss_host,
723 options.gss_client_identity)) {
650 ok = 1; /* Mechanism works */ 724 ok = 1; /* Mechanism works */
651 } else { 725 } else {
652 mech++; 726 mech++;
@@ -743,8 +817,8 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt)
743{ 817{
744 Authctxt *authctxt = ctxt; 818 Authctxt *authctxt = ctxt;
745 Gssctxt *gssctxt; 819 Gssctxt *gssctxt;
746 int oidlen; 820 u_int oidlen;
747 char *oidv; 821 u_char *oidv;
748 822
749 if (authctxt == NULL) 823 if (authctxt == NULL)
750 fatal("input_gssapi_response: no authentication context"); 824 fatal("input_gssapi_response: no authentication context");
@@ -857,6 +931,48 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt)
857 free(lang); 931 free(lang);
858 return 0; 932 return 0;
859} 933}
934
935int
936userauth_gsskeyex(Authctxt *authctxt)
937{
938 Buffer b;
939 gss_buffer_desc gssbuf;
940 gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
941 OM_uint32 ms;
942
943 static int attempt = 0;
944 if (attempt++ >= 1)
945 return (0);
946
947 if (gss_kex_context == NULL) {
948 debug("No valid Key exchange context");
949 return (0);
950 }
951
952 ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
953 "gssapi-keyex");
954
955 gssbuf.value = buffer_ptr(&b);
956 gssbuf.length = buffer_len(&b);
957
958 if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
959 buffer_free(&b);
960 return (0);
961 }
962
963 packet_start(SSH2_MSG_USERAUTH_REQUEST);
964 packet_put_cstring(authctxt->server_user);
965 packet_put_cstring(authctxt->service);
966 packet_put_cstring(authctxt->method->name);
967 packet_put_string(mic.value, mic.length);
968 packet_send();
969
970 buffer_free(&b);
971 gss_release_buffer(&ms, &mic);
972
973 return (1);
974}
975
860#endif /* GSSAPI */ 976#endif /* GSSAPI */
861 977
862int 978int