summaryrefslogtreecommitdiff
path: root/sshconnect2.c
diff options
context:
space:
mode:
authorSimon Wilkinson <simon@sxw.org.uk>2014-02-09 16:09:48 +0000
committerColin Watson <cjwatson@debian.org>2016-12-23 11:24:59 +0000
commit9f717de15a8e113f7c6a3db52d75ce0172885f95 (patch)
tree75236e36100f74ec69d8e8d38543224237ceacf1 /sshconnect2.c
parent971a7653746a6972b907dfe0ce139c06e4a6f482 (diff)
GSSAPI key exchange support
This patch has been rejected upstream: "None of the OpenSSH developers are in favour of adding this, and this situation has not changed for several years. This is not a slight on Simon's patch, which is of fine quality, but just that a) we don't trust GSSAPI implementations that much and b) we don't like adding new KEX since they are pre-auth attack surface. This one is particularly scary, since it requires hooks out to typically root-owned system resources." However, quite a lot of people rely on this in Debian, and it's better to have it merged into the main openssh package rather than having separate -krb5 packages (as we used to have). It seems to have a generally good security history. Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1242 Last-Updated: 2016-08-07 Patch-Name: gssapi.patch
Diffstat (limited to 'sshconnect2.c')
-rw-r--r--sshconnect2.c122
1 files changed, 118 insertions, 4 deletions
diff --git a/sshconnect2.c b/sshconnect2.c
index 103a2b36a..d534e6190 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,36 @@ 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 free(gss);
226 }
227 }
228#endif
229
195 if (options.rekey_limit || options.rekey_interval) 230 if (options.rekey_limit || options.rekey_interval)
196 packet_set_rekey_limits((u_int32_t)options.rekey_limit, 231 packet_set_rekey_limits((u_int32_t)options.rekey_limit,
197 (time_t)options.rekey_interval); 232 (time_t)options.rekey_interval);
@@ -213,10 +248,26 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
213# endif 248# endif
214#endif 249#endif
215 kex->kex[KEX_C25519_SHA256] = kexc25519_client; 250 kex->kex[KEX_C25519_SHA256] = kexc25519_client;
251#ifdef GSSAPI
252 if (options.gss_keyex) {
253 kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
254 kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
255 kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
256 }
257#endif
216 kex->client_version_string=client_version_string; 258 kex->client_version_string=client_version_string;
217 kex->server_version_string=server_version_string; 259 kex->server_version_string=server_version_string;
218 kex->verify_host_key=&verify_host_key_callback; 260 kex->verify_host_key=&verify_host_key_callback;
219 261
262#ifdef GSSAPI
263 if (options.gss_keyex) {
264 kex->gss_deleg_creds = options.gss_deleg_creds;
265 kex->gss_trust_dns = options.gss_trust_dns;
266 kex->gss_client = options.gss_client_identity;
267 kex->gss_host = gss_host;
268 }
269#endif
270
220 dispatch_run(DISPATCH_BLOCK, &kex->done, active_state); 271 dispatch_run(DISPATCH_BLOCK, &kex->done, active_state);
221 272
222 /* remove ext-info from the KEX proposals for rekeying */ 273 /* remove ext-info from the KEX proposals for rekeying */
@@ -311,6 +362,7 @@ int input_gssapi_token(int type, u_int32_t, void *);
311int input_gssapi_hash(int type, u_int32_t, void *); 362int input_gssapi_hash(int type, u_int32_t, void *);
312int input_gssapi_error(int, u_int32_t, void *); 363int input_gssapi_error(int, u_int32_t, void *);
313int input_gssapi_errtok(int, u_int32_t, void *); 364int input_gssapi_errtok(int, u_int32_t, void *);
365int userauth_gsskeyex(Authctxt *authctxt);
314#endif 366#endif
315 367
316void userauth(Authctxt *, char *); 368void userauth(Authctxt *, char *);
@@ -327,6 +379,11 @@ static char *authmethods_get(void);
327 379
328Authmethod authmethods[] = { 380Authmethod authmethods[] = {
329#ifdef GSSAPI 381#ifdef GSSAPI
382 {"gssapi-keyex",
383 userauth_gsskeyex,
384 NULL,
385 &options.gss_authentication,
386 NULL},
330 {"gssapi-with-mic", 387 {"gssapi-with-mic",
331 userauth_gssapi, 388 userauth_gssapi,
332 NULL, 389 NULL,
@@ -652,25 +709,40 @@ userauth_gssapi(Authctxt *authctxt)
652 static u_int mech = 0; 709 static u_int mech = 0;
653 OM_uint32 min; 710 OM_uint32 min;
654 int ok = 0; 711 int ok = 0;
712 char *gss_host;
713
714 if (options.gss_server_identity)
715 gss_host = xstrdup(options.gss_server_identity);
716 else if (options.gss_trust_dns)
717 gss_host = remote_hostname(active_state);
718 else
719 gss_host = xstrdup(authctxt->host);
655 720
656 /* Try one GSSAPI method at a time, rather than sending them all at 721 /* Try one GSSAPI method at a time, rather than sending them all at
657 * once. */ 722 * once. */
658 723
659 if (gss_supported == NULL) 724 if (gss_supported == NULL)
660 gss_indicate_mechs(&min, &gss_supported); 725 if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
726 gss_supported = NULL;
727 free(gss_host);
728 return 0;
729 }
661 730
662 /* Check to see if the mechanism is usable before we offer it */ 731 /* Check to see if the mechanism is usable before we offer it */
663 while (mech < gss_supported->count && !ok) { 732 while (mech < gss_supported->count && !ok) {
664 /* My DER encoding requires length<128 */ 733 /* My DER encoding requires length<128 */
665 if (gss_supported->elements[mech].length < 128 && 734 if (gss_supported->elements[mech].length < 128 &&
666 ssh_gssapi_check_mechanism(&gssctxt, 735 ssh_gssapi_check_mechanism(&gssctxt,
667 &gss_supported->elements[mech], authctxt->host)) { 736 &gss_supported->elements[mech], gss_host,
737 options.gss_client_identity)) {
668 ok = 1; /* Mechanism works */ 738 ok = 1; /* Mechanism works */
669 } else { 739 } else {
670 mech++; 740 mech++;
671 } 741 }
672 } 742 }
673 743
744 free(gss_host);
745
674 if (!ok) 746 if (!ok)
675 return 0; 747 return 0;
676 748
@@ -761,8 +833,8 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt)
761{ 833{
762 Authctxt *authctxt = ctxt; 834 Authctxt *authctxt = ctxt;
763 Gssctxt *gssctxt; 835 Gssctxt *gssctxt;
764 int oidlen; 836 u_int oidlen;
765 char *oidv; 837 u_char *oidv;
766 838
767 if (authctxt == NULL) 839 if (authctxt == NULL)
768 fatal("input_gssapi_response: no authentication context"); 840 fatal("input_gssapi_response: no authentication context");
@@ -875,6 +947,48 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt)
875 free(lang); 947 free(lang);
876 return 0; 948 return 0;
877} 949}
950
951int
952userauth_gsskeyex(Authctxt *authctxt)
953{
954 Buffer b;
955 gss_buffer_desc gssbuf;
956 gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
957 OM_uint32 ms;
958
959 static int attempt = 0;
960 if (attempt++ >= 1)
961 return (0);
962
963 if (gss_kex_context == NULL) {
964 debug("No valid Key exchange context");
965 return (0);
966 }
967
968 ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
969 "gssapi-keyex");
970
971 gssbuf.value = buffer_ptr(&b);
972 gssbuf.length = buffer_len(&b);
973
974 if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
975 buffer_free(&b);
976 return (0);
977 }
978
979 packet_start(SSH2_MSG_USERAUTH_REQUEST);
980 packet_put_cstring(authctxt->server_user);
981 packet_put_cstring(authctxt->service);
982 packet_put_cstring(authctxt->method->name);
983 packet_put_string(mic.value, mic.length);
984 packet_send();
985
986 buffer_free(&b);
987 gss_release_buffer(&ms, &mic);
988
989 return (1);
990}
991
878#endif /* GSSAPI */ 992#endif /* GSSAPI */
879 993
880int 994int