From 59431c242bf1d93980756fa2db2d08744bfa79d3 Mon Sep 17 00:00:00 2001
From: David Woodhouse <David.Woodhouse@intel.com>
Date: Fri, 11 Jul 2014 10:55:07 +0100
Subject: [PATCH] Use SPNEGO for HTTP Negotiate

This is the correct way to do SPNEGO. Just ask for it

Now I correctly see it trying NTLMSSP authentication when a Kerberos ticket
isn't available. Of course, we bail out when the server responds with the
challenge packet, since we don't expect that. But I'll fix that bug next...
---
 lib/curl_gssapi.c    | 9 ++++++++-
 lib/curl_gssapi.h    | 1 +
 lib/http_negotiate.c | 1 +
 lib/krb5.c           | 1 +
 lib/socks_gssapi.c   | 1 +
 5 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/lib/curl_gssapi.c b/lib/curl_gssapi.c
index fabbe35985..af1813b03f 100644
--- a/lib/curl_gssapi.c
+++ b/lib/curl_gssapi.c
@@ -27,11 +27,18 @@
 #include "curl_gssapi.h"
 #include "sendf.h"
 
+static const char spnego_OID[] = "\x2b\x06\x01\x05\x05\x02";
+static const gss_OID_desc gss_mech_spnego = {
+  6,
+  &spnego_OID
+};
+
 OM_uint32 Curl_gss_init_sec_context(
     struct SessionHandle *data,
     OM_uint32 * minor_status,
     gss_ctx_id_t * context,
     gss_name_t target_name,
+    bool use_spnego,
     gss_channel_bindings_t input_chan_bindings,
     gss_buffer_t input_token,
     gss_buffer_t output_token,
@@ -55,7 +62,7 @@ OM_uint32 Curl_gss_init_sec_context(
                               GSS_C_NO_CREDENTIAL, /* cred_handle */
                               context,
                               target_name,
-                              GSS_C_NO_OID, /* mech_type */
+                              use_spnego ? (gss_OID)&gss_mech_spnego : GSS_C_NO_OID,
                               req_flags,
                               0, /* time_req */
                               input_chan_bindings,
diff --git a/lib/curl_gssapi.h b/lib/curl_gssapi.h
index ed33b51a2d..5af7a0261b 100644
--- a/lib/curl_gssapi.h
+++ b/lib/curl_gssapi.h
@@ -47,6 +47,7 @@ OM_uint32 Curl_gss_init_sec_context(
     OM_uint32 * minor_status,
     gss_ctx_id_t * context,
     gss_name_t target_name,
+    bool use_spnego,
     gss_channel_bindings_t input_chan_bindings,
     gss_buffer_t input_token,
     gss_buffer_t output_token,
diff --git a/lib/http_negotiate.c b/lib/http_negotiate.c
index ccd005bbb6..9b01e0a563 100644
--- a/lib/http_negotiate.c
+++ b/lib/http_negotiate.c
@@ -184,6 +184,7 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
                                            &minor_status,
                                            &neg_ctx->context,
                                            neg_ctx->server_name,
+                                           TRUE,
                                            GSS_C_NO_CHANNEL_BINDINGS,
                                            &input_token,
                                            &output_token,
diff --git a/lib/krb5.c b/lib/krb5.c
index 1643f11a6a..9a36af1dbe 100644
--- a/lib/krb5.c
+++ b/lib/krb5.c
@@ -236,6 +236,7 @@ krb5_auth(void *app_data, struct connectdata *conn)
                                       &min,
                                       context,
                                       gssname,
+                                      FALSE,
                                       &chan,
                                       gssresp,
                                       &output_buffer,
diff --git a/lib/socks_gssapi.c b/lib/socks_gssapi.c
index 1f840bd4e0..0a35dfa09b 100644
--- a/lib/socks_gssapi.c
+++ b/lib/socks_gssapi.c
@@ -181,6 +181,7 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(int sockindex,
                                                  &gss_minor_status,
                                                  &gss_context,
                                                  server,
+                                                 FALSE,
                                                  NULL,
                                                  gss_token,
                                                  &gss_send_token,
-- 
GitLab