cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: [PATCH] SF bug #1302: HTTP Auth Negotiate sends Kerberos token instead of SPNEGO token

From: David Woodhouse <dwmw2_at_infradead.org>
Date: Tue, 15 Jul 2014 14:26:47 +0100

On Tue, 2014-07-15 at 14:53 +0200, Michael Osipov wrote:
> While you are right about "add half of this back again", it not just
> like add that enum and you are done. I you must add the define for the
> CURLAUTH_, add CURL_VERSION_, register both at the appropriate spots,
> add the command line options, etc. That might result in an additional
> series of commits. That's why I have abstained from.

I didn't mean going that far. I meant just this much...

This is tested on Windows and Linux as far as I can — I don't have a
server which offers 'WWW-Authenticate: Kerberos' but I've tested the
non-SPNEGO path in both cases and it works correctly, using *only*
Kerberos and thus failing to authenticate to hosts where NTLM fallback
is required.

From 5109cf90206eb26c69d48d205a4689fbd404e9c2 Mon Sep 17 00:00:00 2001
From: David Woodhouse <David.Woodhouse_at_intel.com>
Date: Tue, 15 Jul 2014 14:23:12 +0100
Subject: [PATCH] Support WWW-Authenticate: Kerberos in place of defunct
 GSS-Negotiate

Based on a patch from Michael Osipov <1983-01-06_at_gmx.net> which just removed
GSS-Negotiate.

---
 lib/http.c                |  2 +-
 lib/http_negotiate.c      | 34 ++++++++++------------------------
 lib/http_negotiate_sspi.c | 39 ++++++++++++---------------------------
 lib/urldata.h             |  2 +-
 4 files changed, 24 insertions(+), 53 deletions(-)
diff --git a/lib/http.c b/lib/http.c
index 4931dd8..56c0616 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -772,7 +772,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
 
   while(*auth) {
 #ifdef USE_HTTP_NEGOTIATE
-    if(checkprefix("GSS-Negotiate", auth) ||
+    if(checkprefix("Kerberos", auth) ||
        checkprefix("Negotiate", auth)) {
       int neg;
       *availp |= CURLAUTH_GSSNEGOTIATE;
diff --git a/lib/http_negotiate.c b/lib/http_negotiate.c
index bbad0b4..d4ae741 100644
--- a/lib/http_negotiate.c
+++ b/lib/http_negotiate.c
@@ -53,26 +53,12 @@ get_gss_name(struct connectdata *conn, bool proxy, gss_name_t *server)
   OM_uint32 major_status, minor_status;
   gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
   char name[2048];
-  const char* service;
 
-  /* GSSAPI implementation by Globus (known as GSI) requires the name to be
-     of form "<service>/<fqdn>" instead of <service>@<fqdn> (ie. slash instead
-     of at-sign). Also GSI servers are often identified as 'host' not 'khttp'.
-     Change following lines if you want to use GSI */
-
-  /* IIS uses the <service>@<fqdn> form but uses 'http' as the service name */
-
-  if(neg_ctx->gss)
-    service = "KHTTP";
-  else
-    service = "HTTP";
-
-  token.length = strlen(service) + 1 + strlen(proxy ? conn->proxy.name :
-                                              conn->host.name) + 1;
+  token.length = 5 + strlen(proxy ? conn->proxy.name : conn->host.name) + 1;
   if(token.length + 1 > sizeof(name))
     return EMSGSIZE;
 
-  snprintf(name, sizeof(name), "%s@%s", service, proxy ? conn->proxy.name :
+  snprintf(name, sizeof(name), "HTTP@%s", proxy ? conn->proxy.name :
            conn->host.name);
 
   token.value = (void *) name;
@@ -128,29 +114,29 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
   int ret;
   size_t len;
   size_t rawlen = 0;
-  bool gss;
+  bool spnego;
   const char* protocol;
   CURLcode error;
 
-  if(checkprefix("GSS-Negotiate", header)) {
-    protocol = "GSS-Negotiate";
-    gss = TRUE;
+  if(checkprefix("Kerberos", header)) {
+    protocol = "Kerberos";
+    spnego = FALSE;
   }
   else if(checkprefix("Negotiate", header)) {
     protocol = "Negotiate";
-    gss = FALSE;
+    spnego = TRUE;
   }
   else
     return -1;
 
   if(neg_ctx->context) {
-    if(neg_ctx->gss != gss) {
+    if(neg_ctx->spnego != spnego) {
       return -1;
     }
   }
   else {
     neg_ctx->protocol = protocol;
-    neg_ctx->gss = gss;
+    neg_ctx->spnego = spnego;
   }
 
   if(neg_ctx->context && neg_ctx->status == GSS_S_COMPLETE) {
@@ -184,7 +170,7 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
                                            &minor_status,
                                            &neg_ctx->context,
                                            neg_ctx->server_name,
-                                           TRUE,
+                                           spnego,
                                            GSS_C_NO_CHANNEL_BINDINGS,
                                            &input_token,
                                            &output_token,
diff --git a/lib/http_negotiate_sspi.c b/lib/http_negotiate_sspi.c
index 236766b..8bccaea 100644
--- a/lib/http_negotiate_sspi.c
+++ b/lib/http_negotiate_sspi.c
@@ -52,27 +52,12 @@ get_gss_name(struct connectdata *conn, bool proxy,
     /* proxy auth requested but no given proxy name, error out! */
     return -1;
 
-  /* GSSAPI implementation by Globus (known as GSI) requires the name to be
-     of form "<service>/<fqdn>" instead of <service>@<fqdn> (ie. slash instead
-     of at-sign). Also GSI servers are often identified as 'host' not 'khttp'.
-     Change following lines if you want to use GSI */
-
-  /* IIS uses the <service>@<fqdn> form but uses 'http' as the service name,
-     and SSPI then generates an NTLM token. When using <service>/<fqdn> a
-     Kerberos token is generated. */
-
-  if(neg_ctx->gss)
-    service = "KHTTP";
-  else
-    service = "HTTP";
-
-  length = strlen(service) + 1 + strlen(proxy ? conn->proxy.name :
-                                        conn->host.name) + 1;
+  length = 5 + strlen(proxy ? conn->proxy.name : conn->host.name) + 1;
   if(length + 1 > sizeof(neg_ctx->server_name))
     return EMSGSIZE;
 
-  snprintf(neg_ctx->server_name, sizeof(neg_ctx->server_name), "%s/%s",
-           service, proxy ? conn->proxy.name : conn->host.name);
+  snprintf(neg_ctx->server_name, sizeof(neg_ctx->server_name), "HTTP/%s",
+           proxy ? conn->proxy.name : conn->host.name);
 
   return 0;
 }
@@ -94,29 +79,29 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
   TCHAR             *sname;
   int ret;
   size_t len = 0, input_token_len = 0;
-  bool gss = FALSE;
+  bool spnego = FALSE;
   const char* protocol;
   CURLcode error;
 
-  if(checkprefix("GSS-Negotiate", header)) {
-    protocol = "GSS-Negotiate";
-    gss = TRUE;
+  if(checkprefix("Kerberos", header)) {
+    protocol = "Kerberos";
+    spnego = FALSE;
   }
   else if(checkprefix("Negotiate", header)) {
     protocol = "Negotiate";
-    gss = FALSE;
+    spnego = TRUE;
   }
   else
     return -1;
 
   if(neg_ctx->context) {
-    if(neg_ctx->gss != gss) {
+    if(neg_ctx->spnego != spnego) {
       return -1;
     }
   }
   else {
     neg_ctx->protocol = protocol;
-    neg_ctx->gss = gss;
+    neg_ctx->spnego = spnego;
   }
 
   if(neg_ctx->context && neg_ctx->status == SEC_E_OK) {
@@ -135,7 +120,7 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
 
   if(!neg_ctx->output_token) {
     PSecPkgInfo SecurityPackage;
-    ret = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT("Negotiate"),
+    ret = s_pSecFn->QuerySecurityPackageInfo((TCHAR *) TEXT(protocol),
                                              &SecurityPackage);
     if(ret != SEC_E_OK)
       return -1;
@@ -165,7 +150,7 @@ int Curl_input_negotiate(struct connectdata *conn, bool proxy,
 
     neg_ctx->status =
       s_pSecFn->AcquireCredentialsHandle(NULL,
-                                         (TCHAR *) TEXT("Negotiate"),
+                                         (TCHAR *) TEXT(protocol),
                                          SECPKG_CRED_OUTBOUND, NULL, NULL,
                                          NULL, NULL, neg_ctx->credentials,
                                          &lifetime);
diff --git a/lib/urldata.h b/lib/urldata.h
index ebdad80..827cb9d 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -449,7 +449,7 @@ struct negotiatedata {
   /* when doing Negotiate we first need to receive an auth token and then we
      need to send our header */
   enum { GSS_AUTHNONE, GSS_AUTHRECV, GSS_AUTHSENT } state;
-  bool gss; /* Whether we're processing GSS-Negotiate or Negotiate */
+  bool spnego; /* Whether we're processing Kerberos or Negotiate */
   const char* protocol; /* "GSS-Negotiate" or "Negotiate" */
 #ifdef HAVE_GSSAPI
   OM_uint32 status;
-- 
1.9.3
-- 
dwmw2

-------------------------------------------------------------------
List admin: http://cool.haxx.se/list/listinfo/curl-library
Etiquette: http://curl.haxx.se/mail/etiquette.html

  • application/x-pkcs7-signature attachment: smime.p7s
Received on 2014-07-15