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-01-04 15:06:57 +0000
commit48424483cbf2232ba849038e02675b2db1ea3a88 (patch)
treea21f027e0d814ba92e1e918dafdb845654589c1f /sshconnect2.c
parent651211fd4a199b299540c00c54a46e27fadb04be (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-01-04 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 775103185..32e9b0df2 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -160,6 +160,11 @@ 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
@@ -193,6 +198,33 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
193 order_hostkeyalgs(host, hostaddr, port)); 198 order_hostkeyalgs(host, hostaddr, port));
194 } 199 }
195 200
201#ifdef GSSAPI
202 if (options.gss_keyex) {
203 /* Add the GSSAPI mechanisms currently supported on this
204 * client to the key exchange algorithm proposal */
205 orig = myproposal[PROPOSAL_KEX_ALGS];
206
207 if (options.gss_trust_dns)
208 gss_host = (char *)get_canonical_hostname(1);
209 else
210 gss_host = host;
211
212 gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity);
213 if (gss) {
214 debug("Offering GSSAPI proposal: %s", gss);
215 xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
216 "%s,%s", gss, orig);
217
218 /* If we've got GSSAPI algorithms, then we also
219 * support the 'null' hostkey, as a last resort */
220 orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
221 xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
222 "%s,null", orig);
223 free(gss);
224 }
225 }
226#endif
227
196 if (options.rekey_limit || options.rekey_interval) 228 if (options.rekey_limit || options.rekey_interval)
197 packet_set_rekey_limits((u_int32_t)options.rekey_limit, 229 packet_set_rekey_limits((u_int32_t)options.rekey_limit,
198 (time_t)options.rekey_interval); 230 (time_t)options.rekey_interval);
@@ -211,10 +243,30 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
211# endif 243# endif
212#endif 244#endif
213 kex->kex[KEX_C25519_SHA256] = kexc25519_client; 245 kex->kex[KEX_C25519_SHA256] = kexc25519_client;
246#ifdef GSSAPI
247 if (options.gss_keyex) {
248 kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
249 kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
250 kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client;
251 }
252#endif
214 kex->client_version_string=client_version_string; 253 kex->client_version_string=client_version_string;
215 kex->server_version_string=server_version_string; 254 kex->server_version_string=server_version_string;
216 kex->verify_host_key=&verify_host_key_callback; 255 kex->verify_host_key=&verify_host_key_callback;
217 256
257#ifdef GSSAPI
258 if (options.gss_keyex) {
259 kex->gss_deleg_creds = options.gss_deleg_creds;
260 kex->gss_trust_dns = options.gss_trust_dns;
261 kex->gss_client = options.gss_client_identity;
262 if (options.gss_server_identity) {
263 kex->gss_host = options.gss_server_identity;
264 } else {
265 kex->gss_host = gss_host;
266 }
267 }
268#endif
269
218 dispatch_run(DISPATCH_BLOCK, &kex->done, active_state); 270 dispatch_run(DISPATCH_BLOCK, &kex->done, active_state);
219 271
220 if (options.use_roaming && !kex->roaming) { 272 if (options.use_roaming && !kex->roaming) {
@@ -306,6 +358,7 @@ int input_gssapi_token(int type, u_int32_t, void *);
306int input_gssapi_hash(int type, u_int32_t, void *); 358int input_gssapi_hash(int type, u_int32_t, void *);
307int input_gssapi_error(int, u_int32_t, void *); 359int input_gssapi_error(int, u_int32_t, void *);
308int input_gssapi_errtok(int, u_int32_t, void *); 360int input_gssapi_errtok(int, u_int32_t, void *);
361int userauth_gsskeyex(Authctxt *authctxt);
309#endif 362#endif
310 363
311void userauth(Authctxt *, char *); 364void userauth(Authctxt *, char *);
@@ -321,6 +374,11 @@ static char *authmethods_get(void);
321 374
322Authmethod authmethods[] = { 375Authmethod authmethods[] = {
323#ifdef GSSAPI 376#ifdef GSSAPI
377 {"gssapi-keyex",
378 userauth_gsskeyex,
379 NULL,
380 &options.gss_authentication,
381 NULL},
324 {"gssapi-with-mic", 382 {"gssapi-with-mic",
325 userauth_gssapi, 383 userauth_gssapi,
326 NULL, 384 NULL,
@@ -627,19 +685,31 @@ userauth_gssapi(Authctxt *authctxt)
627 static u_int mech = 0; 685 static u_int mech = 0;
628 OM_uint32 min; 686 OM_uint32 min;
629 int ok = 0; 687 int ok = 0;
688 const char *gss_host;
689
690 if (options.gss_server_identity)
691 gss_host = options.gss_server_identity;
692 else if (options.gss_trust_dns)
693 gss_host = get_canonical_hostname(1);
694 else
695 gss_host = authctxt->host;
630 696
631 /* Try one GSSAPI method at a time, rather than sending them all at 697 /* Try one GSSAPI method at a time, rather than sending them all at
632 * once. */ 698 * once. */
633 699
634 if (gss_supported == NULL) 700 if (gss_supported == NULL)
635 gss_indicate_mechs(&min, &gss_supported); 701 if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) {
702 gss_supported = NULL;
703 return 0;
704 }
636 705
637 /* Check to see if the mechanism is usable before we offer it */ 706 /* Check to see if the mechanism is usable before we offer it */
638 while (mech < gss_supported->count && !ok) { 707 while (mech < gss_supported->count && !ok) {
639 /* My DER encoding requires length<128 */ 708 /* My DER encoding requires length<128 */
640 if (gss_supported->elements[mech].length < 128 && 709 if (gss_supported->elements[mech].length < 128 &&
641 ssh_gssapi_check_mechanism(&gssctxt, 710 ssh_gssapi_check_mechanism(&gssctxt,
642 &gss_supported->elements[mech], authctxt->host)) { 711 &gss_supported->elements[mech], gss_host,
712 options.gss_client_identity)) {
643 ok = 1; /* Mechanism works */ 713 ok = 1; /* Mechanism works */
644 } else { 714 } else {
645 mech++; 715 mech++;
@@ -736,8 +806,8 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt)
736{ 806{
737 Authctxt *authctxt = ctxt; 807 Authctxt *authctxt = ctxt;
738 Gssctxt *gssctxt; 808 Gssctxt *gssctxt;
739 int oidlen; 809 u_int oidlen;
740 char *oidv; 810 u_char *oidv;
741 811
742 if (authctxt == NULL) 812 if (authctxt == NULL)
743 fatal("input_gssapi_response: no authentication context"); 813 fatal("input_gssapi_response: no authentication context");
@@ -850,6 +920,48 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt)
850 free(lang); 920 free(lang);
851 return 0; 921 return 0;
852} 922}
923
924int
925userauth_gsskeyex(Authctxt *authctxt)
926{
927 Buffer b;
928 gss_buffer_desc gssbuf;
929 gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
930 OM_uint32 ms;
931
932 static int attempt = 0;
933 if (attempt++ >= 1)
934 return (0);
935
936 if (gss_kex_context == NULL) {
937 debug("No valid Key exchange context");
938 return (0);
939 }
940
941 ssh_gssapi_buildmic(&b, authctxt->server_user, authctxt->service,
942 "gssapi-keyex");
943
944 gssbuf.value = buffer_ptr(&b);
945 gssbuf.length = buffer_len(&b);
946
947 if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) {
948 buffer_free(&b);
949 return (0);
950 }
951
952 packet_start(SSH2_MSG_USERAUTH_REQUEST);
953 packet_put_cstring(authctxt->server_user);
954 packet_put_cstring(authctxt->service);
955 packet_put_cstring(authctxt->method->name);
956 packet_put_string(mic.value, mic.length);
957 packet_send();
958
959 buffer_free(&b);
960 gss_release_buffer(&ms, &mic);
961
962 return (1);
963}
964
853#endif /* GSSAPI */ 965#endif /* GSSAPI */
854 966
855int 967int