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-08-07 12:18:35 +0100
commiteecddf8b72fcad83ccca43b1badb03782704f6b7 (patch)
treefd0046825c8d42bd267afa7839d5603b130cf847 /sshconnect2.c
parenta8ed8d256b2e2c05b0c15565a7938028c5192277 (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 fae8b0f2c..34b9d304e 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 *);
@@ -326,6 +378,11 @@ static char *authmethods_get(void);
326 378
327Authmethod authmethods[] = { 379Authmethod authmethods[] = {
328#ifdef GSSAPI 380#ifdef GSSAPI
381 {"gssapi-keyex",
382 userauth_gsskeyex,
383 NULL,
384 &options.gss_authentication,
385 NULL},
329 {"gssapi-with-mic", 386 {"gssapi-with-mic",
330 userauth_gssapi, 387 userauth_gssapi,
331 NULL, 388 NULL,
@@ -650,25 +707,40 @@ userauth_gssapi(Authctxt *authctxt)
650 static u_int mech = 0; 707 static u_int mech = 0;
651 OM_uint32 min; 708 OM_uint32 min;
652 int ok = 0; 709 int ok = 0;
710 char *gss_host;
711
712 if (options.gss_server_identity)
713 gss_host = xstrdup(options.gss_server_identity);
714 else if (options.gss_trust_dns)
715 gss_host = remote_hostname(active_state);
716 else
717 gss_host = xstrdup(authctxt->host);
653 718
654 /* Try one GSSAPI method at a time, rather than sending them all at 719 /* Try one GSSAPI method at a time, rather than sending them all at
655 * once. */ 720 * once. */
656 721
657 if (gss_supported == NULL) 722 if (gss_supported == NULL)
658 gss_indicate_mechs(&min, &gss_supported); 723 if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
724 gss_supported = NULL;
725 free(gss_host);
726 return 0;
727 }
659 728
660 /* Check to see if the mechanism is usable before we offer it */ 729 /* Check to see if the mechanism is usable before we offer it */
661 while (mech < gss_supported->count && !ok) { 730 while (mech < gss_supported->count && !ok) {
662 /* My DER encoding requires length<128 */ 731 /* My DER encoding requires length<128 */
663 if (gss_supported->elements[mech].length < 128 && 732 if (gss_supported->elements[mech].length < 128 &&
664 ssh_gssapi_check_mechanism(&gssctxt, 733 ssh_gssapi_check_mechanism(&gssctxt,
665 &gss_supported->elements[mech], authctxt->host)) { 734 &gss_supported->elements[mech], gss_host,
735 options.gss_client_identity)) {
666 ok = 1; /* Mechanism works */ 736 ok = 1; /* Mechanism works */
667 } else { 737 } else {
668 mech++; 738 mech++;
669 } 739 }
670 } 740 }
671 741
742 free(gss_host);
743
672 if (!ok) 744 if (!ok)
673 return 0; 745 return 0;
674 746
@@ -759,8 +831,8 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt)
759{ 831{
760 Authctxt *authctxt = ctxt; 832 Authctxt *authctxt = ctxt;
761 Gssctxt *gssctxt; 833 Gssctxt *gssctxt;
762 int oidlen; 834 u_int oidlen;
763 char *oidv; 835 u_char *oidv;
764 836
765 if (authctxt == NULL) 837 if (authctxt == NULL)
766 fatal("input_gssapi_response: no authentication context"); 838 fatal("input_gssapi_response: no authentication context");
@@ -873,6 +945,48 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt)
873 free(lang); 945 free(lang);
874 return 0; 946 return 0;
875} 947}
948
949int
950userauth_gsskeyex(Authctxt *authctxt)
951{
952 Buffer b;
953 gss_buffer_desc gssbuf;
954 gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
955 OM_uint32 ms;
956
957 static int attempt = 0;
958 if (attempt++ >= 1)
959 return (0);
960
961 if (gss_kex_context == NULL) {
962 debug("No valid Key exchange context");
963 return (0);
964 }
965
966 ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
967 "gssapi-keyex");
968
969 gssbuf.value = buffer_ptr(&b);
970 gssbuf.length = buffer_len(&b);
971
972 if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
973 buffer_free(&b);
974 return (0);
975 }
976
977 packet_start(SSH2_MSG_USERAUTH_REQUEST);
978 packet_put_cstring(authctxt->server_user);
979 packet_put_cstring(authctxt->service);
980 packet_put_cstring(authctxt->method->name);
981 packet_put_string(mic.value, mic.length);
982 packet_send();
983
984 buffer_free(&b);
985 gss_release_buffer(&ms, &mic);
986
987 return (1);
988}
989
876#endif /* GSSAPI */ 990#endif /* GSSAPI */
877 991
878int 992int