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-03-21 12:06:07 +0000
commit8c27af53099b50387dda97c0aae36194197186f6 (patch)
treec2722bd6f5463d8bdbfe42159d0094074329e438 /sshconnect2.c
parentf0329aac23c61e1a5197d6d57349a63f459bccb0 (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-03-21 Patch-Name: gssapi.patch
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 f79c96beb..b452eae24 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -161,6 +161,11 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
161 struct kex *kex; 161 struct kex *kex;
162 int r; 162 int r;
163 163
164#ifdef GSSAPI
165 char *orig = NULL, *gss = NULL;
166 char *gss_host = NULL;
167#endif
168
164 xxx_host = host; 169 xxx_host = host;
165 xxx_hostaddr = hostaddr; 170 xxx_hostaddr = hostaddr;
166 171
@@ -195,6 +200,33 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
195 order_hostkeyalgs(host, hostaddr, port)); 200 order_hostkeyalgs(host, hostaddr, port));
196 } 201 }
197 202
203#ifdef GSSAPI
204 if (options.gss_keyex) {
205 /* Add the GSSAPI mechanisms currently supported on this
206 * client to the key exchange algorithm proposal */
207 orig = myproposal[PROPOSAL_KEX_ALGS];
208
209 if (options.gss_trust_dns)
210 gss_host = (char *)get_canonical_hostname(1);
211 else
212 gss_host = host;
213
214 gss = ssh_gssapi_client_mechanisms(gss_host, 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
198 if (options.rekey_limit || options.rekey_interval) 230 if (options.rekey_limit || options.rekey_interval)
199 packet_set_rekey_limits((u_int32_t)options.rekey_limit, 231 packet_set_rekey_limits((u_int32_t)options.rekey_limit,
200 (time_t)options.rekey_interval); 232 (time_t)options.rekey_interval);
@@ -213,10 +245,30 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
213# endif 245# endif
214#endif 246#endif
215 kex->kex[KEX_C25519_SHA256] = kexc25519_client; 247 kex->kex[KEX_C25519_SHA256] = kexc25519_client;
248#ifdef GSSAPI
249 if (options.gss_keyex) {
250 kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
251 kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
252 kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
253 }
254#endif
216 kex->client_version_string=client_version_string; 255 kex->client_version_string=client_version_string;
217 kex->server_version_string=server_version_string; 256 kex->server_version_string=server_version_string;
218 kex->verify_host_key=&verify_host_key_callback; 257 kex->verify_host_key=&verify_host_key_callback;
219 258
259#ifdef GSSAPI
260 if (options.gss_keyex) {
261 kex->gss_deleg_creds = options.gss_deleg_creds;
262 kex->gss_trust_dns = options.gss_trust_dns;
263 kex->gss_client = options.gss_client_identity;
264 if (options.gss_server_identity) {
265 kex->gss_host = options.gss_server_identity;
266 } else {
267 kex->gss_host = gss_host;
268 }
269 }
270#endif
271
220 dispatch_run(DISPATCH_BLOCK, &kex->done, active_state); 272 dispatch_run(DISPATCH_BLOCK, &kex->done, active_state);
221 273
222 /* remove ext-info from the KEX proposals for rekeying */ 274 /* remove ext-info from the KEX proposals for rekeying */
@@ -311,6 +363,7 @@ int input_gssapi_token(int type, u_int32_t, void *);
311int input_gssapi_hash(int type, u_int32_t, void *); 363int input_gssapi_hash(int type, u_int32_t, void *);
312int input_gssapi_error(int, u_int32_t, void *); 364int input_gssapi_error(int, u_int32_t, void *);
313int input_gssapi_errtok(int, u_int32_t, void *); 365int input_gssapi_errtok(int, u_int32_t, void *);
366int userauth_gsskeyex(Authctxt *authctxt);
314#endif 367#endif
315 368
316void userauth(Authctxt *, char *); 369void userauth(Authctxt *, char *);
@@ -326,6 +379,11 @@ static char *authmethods_get(void);
326 379
327Authmethod authmethods[] = { 380Authmethod authmethods[] = {
328#ifdef GSSAPI 381#ifdef GSSAPI
382 {"gssapi-keyex",
383 userauth_gsskeyex,
384 NULL,
385 &options.gss_authentication,
386 NULL},
329 {"gssapi-with-mic", 387 {"gssapi-with-mic",
330 userauth_gssapi, 388 userauth_gssapi,
331 NULL, 389 NULL,
@@ -656,19 +714,31 @@ userauth_gssapi(Authctxt *authctxt)
656 static u_int mech = 0; 714 static u_int mech = 0;
657 OM_uint32 min; 715 OM_uint32 min;
658 int ok = 0; 716 int ok = 0;
717 const char *gss_host;
718
719 if (options.gss_server_identity)
720 gss_host = options.gss_server_identity;
721 else if (options.gss_trust_dns)
722 gss_host = get_canonical_hostname(1);
723 else
724 gss_host = authctxt->host;
659 725
660 /* Try one GSSAPI method at a time, rather than sending them all at 726 /* Try one GSSAPI method at a time, rather than sending them all at
661 * once. */ 727 * once. */
662 728
663 if (gss_supported == NULL) 729 if (gss_supported == NULL)
664 gss_indicate_mechs(&min, &gss_supported); 730 if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
731 gss_supported = NULL;
732 return 0;
733 }
665 734
666 /* Check to see if the mechanism is usable before we offer it */ 735 /* Check to see if the mechanism is usable before we offer it */
667 while (mech < gss_supported->count && !ok) { 736 while (mech < gss_supported->count && !ok) {
668 /* My DER encoding requires length<128 */ 737 /* My DER encoding requires length<128 */
669 if (gss_supported->elements[mech].length < 128 && 738 if (gss_supported->elements[mech].length < 128 &&
670 ssh_gssapi_check_mechanism(&gssctxt, 739 ssh_gssapi_check_mechanism(&gssctxt,
671 &gss_supported->elements[mech], authctxt->host)) { 740 &gss_supported->elements[mech], gss_host,
741 options.gss_client_identity)) {
672 ok = 1; /* Mechanism works */ 742 ok = 1; /* Mechanism works */
673 } else { 743 } else {
674 mech++; 744 mech++;
@@ -765,8 +835,8 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt)
765{ 835{
766 Authctxt *authctxt = ctxt; 836 Authctxt *authctxt = ctxt;
767 Gssctxt *gssctxt; 837 Gssctxt *gssctxt;
768 int oidlen; 838 u_int oidlen;
769 char *oidv; 839 u_char *oidv;
770 840
771 if (authctxt == NULL) 841 if (authctxt == NULL)
772 fatal("input_gssapi_response: no authentication context"); 842 fatal("input_gssapi_response: no authentication context");
@@ -879,6 +949,48 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt)
879 free(lang); 949 free(lang);
880 return 0; 950 return 0;
881} 951}
952
953int
954userauth_gsskeyex(Authctxt *authctxt)
955{
956 Buffer b;
957 gss_buffer_desc gssbuf;
958 gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
959 OM_uint32 ms;
960
961 static int attempt = 0;
962 if (attempt++ >= 1)
963 return (0);
964
965 if (gss_kex_context == NULL) {
966 debug("No valid Key exchange context");
967 return (0);
968 }
969
970 ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
971 "gssapi-keyex");
972
973 gssbuf.value = buffer_ptr(&b);
974 gssbuf.length = buffer_len(&b);
975
976 if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
977 buffer_free(&b);
978 return (0);
979 }
980
981 packet_start(SSH2_MSG_USERAUTH_REQUEST);
982 packet_put_cstring(authctxt->server_user);
983 packet_put_cstring(authctxt->service);
984 packet_put_cstring(authctxt->method->name);
985 packet_put_string(mic.value, mic.length);
986 packet_send();
987
988 buffer_free(&b);
989 gss_release_buffer(&ms, &mic);
990
991 return (1);
992}
993
882#endif /* GSSAPI */ 994#endif /* GSSAPI */
883 995
884int 996int