]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
Negotiate: fix for HTTP POST with Negotiate
authorDominik Hölzl <dominik.hoelzl@fabasoft.at>
Mon, 10 Sep 2018 07:18:01 +0000 (09:18 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Thu, 14 Mar 2019 08:26:03 +0000 (09:26 +0100)
* Adjusted unit tests 2056, 2057
* do not generally close connections with CURLAUTH_NEGOTIATE after every request
* moved negotiatedata from UrlState to connectdata
* Added stream rewind logic for CURLAUTH_NEGOTIATE
* introduced negotiatedata::GSS_AUTHDONE and negotiatedata::GSS_AUTHSUCC
* Consider authproblem state for CURLAUTH_NEGOTIATE
* Consider reuse_forbid for CURLAUTH_NEGOTIATE
* moved and adjusted negotiate authentication state handling from
  output_auth_headers into Curl_output_negotiate
* Curl_output_negotiate: ensure auth done is always set
* Curl_output_negotiate: Set auth done also if result code is
  GSS_S_CONTINUE_NEEDED/SEC_I_CONTINUE_NEEDED as this result code may
  also indicate the last challenge request (only works with disabled
  Expect: 100-continue and CURLOPT_KEEP_SENDING_ON_ERROR -> 1)
* Consider "Persistent-Auth" header, detect if not present;
  Reset/Cleanup negotiate after authentication if no persistent
  authentication
* apply changes introduced with #2546 for negotiate rewind logic

Fixes #1261
Closes #1975

lib/http.c
lib/http_negotiate.c
lib/http_negotiate.h
lib/multi.c
lib/url.c
lib/urldata.h
lib/vauth/spnego_gssapi.c
lib/vauth/spnego_sspi.c
tests/data/test2056
tests/data/test2057

index 3f41a451b95f7b4f1bbe0eea6f08af43f0810304..a0520b40ec01f7bc613cda3482388508fa71943a 100644 (file)
@@ -481,8 +481,36 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
             (curl_off_t)(expectsend - bytessent));
     }
 #endif
+#if defined(USE_SPNEGO)
+    /* There is still data left to send */
+    if((data->state.authproxy.picked == CURLAUTH_NEGOTIATE) ||
+       (data->state.authhost.picked == CURLAUTH_NEGOTIATE)) {
+      if(((expectsend - bytessent) < 2000) ||
+         (conn->negotiate.state != GSS_AUTHNONE) ||
+         (conn->proxyneg.state != GSS_AUTHNONE)) {
+        /* The NEGOTIATE-negotiation has started *OR*
+        there is just a little (<2K) data left to send, keep on sending. */
+
+        /* rewind data when completely done sending! */
+        if(!conn->bits.authneg && (conn->writesockfd != CURL_SOCKET_BAD)) {
+          conn->bits.rewindaftersend = TRUE;
+          infof(data, "Rewind stream after send\n");
+        }
+
+        return CURLE_OK;
+      }
 
-    /* This is not NTLM or many bytes left to send: close */
+      if(conn->bits.close)
+        /* this is already marked to get closed */
+        return CURLE_OK;
+
+      infof(data, "NEGOTIATE send, close instead of sending %"
+        CURL_FORMAT_CURL_OFF_T " bytes\n",
+        (curl_off_t)(expectsend - bytessent));
+    }
+#endif
+
+    /* This is not NEGOTIATE/NTLM or many bytes left to send: close */
     streamclose(conn, "Mid-auth HTTP and much data left to send");
     data->req.size = 0; /* don't download any more than 0 bytes */
 
@@ -600,10 +628,6 @@ output_auth_headers(struct connectdata *conn,
 #if !defined(CURL_DISABLE_VERBOSE_STRINGS) || defined(USE_SPNEGO)
   struct Curl_easy *data = conn->data;
 #endif
-#ifdef USE_SPNEGO
-  struct negotiatedata *negdata = proxy ?
-    &data->state.proxyneg : &data->state.negotiate;
-#endif
 
 #ifdef CURL_DISABLE_CRYPTO_AUTH
   (void)request;
@@ -611,15 +635,11 @@ output_auth_headers(struct connectdata *conn,
 #endif
 
 #ifdef USE_SPNEGO
-  negdata->state = GSS_AUTHNONE;
-  if((authstatus->picked == CURLAUTH_NEGOTIATE) &&
-     negdata->context && !GSS_ERROR(negdata->status)) {
+  if((authstatus->picked == CURLAUTH_NEGOTIATE)) {
     auth = "Negotiate";
     result = Curl_output_negotiate(conn, proxy);
     if(result)
       return result;
-    authstatus->done = TRUE;
-    negdata->state = GSS_AUTHSENT;
   }
   else
 #endif
@@ -796,7 +816,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
 
 #ifdef USE_SPNEGO
   struct negotiatedata *negdata = proxy?
-    &data->state.proxyneg:&data->state.negotiate;
+    &conn->proxyneg:&conn->negotiate;
 #endif
   unsigned long *availp;
   struct auth *authp;
@@ -835,21 +855,18 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
         authp->avail |= CURLAUTH_NEGOTIATE;
 
         if(authp->picked == CURLAUTH_NEGOTIATE) {
-          if(negdata->state == GSS_AUTHSENT ||
-             negdata->state == GSS_AUTHNONE) {
-            CURLcode result = Curl_input_negotiate(conn, proxy, auth);
-            if(!result) {
-              DEBUGASSERT(!data->req.newurl);
-              data->req.newurl = strdup(data->change.url);
-              if(!data->req.newurl)
-                return CURLE_OUT_OF_MEMORY;
-              data->state.authproblem = FALSE;
-              /* we received a GSS auth token and we dealt with it fine */
-              negdata->state = GSS_AUTHRECV;
-            }
-            else
-              data->state.authproblem = TRUE;
+          CURLcode result = Curl_input_negotiate(conn, proxy, auth);
+          if(!result) {
+            DEBUGASSERT(!data->req.newurl);
+            data->req.newurl = strdup(data->change.url);
+            if(!data->req.newurl)
+              return CURLE_OUT_OF_MEMORY;
+            data->state.authproblem = FALSE;
+            /* we received a GSS auth token and we dealt with it fine */
+            negdata->state = GSS_AUTHRECV;
           }
+          else
+            data->state.authproblem = TRUE;
         }
       }
     }
@@ -1555,20 +1572,6 @@ CURLcode Curl_http_done(struct connectdata *conn,
 
   Curl_unencode_cleanup(conn);
 
-#ifdef USE_SPNEGO
-  if(data->state.proxyneg.state == GSS_AUTHSENT ||
-     data->state.negotiate.state == GSS_AUTHSENT) {
-    /* add forbid re-use if http-code != 401/407 as a WA only needed for
-     * 401/407 that signal auth failure (empty) otherwise state will be RECV
-     * with current code.
-     * Do not close CONNECT_ONLY connections. */
-    if((data->req.httpcode != 401) && (data->req.httpcode != 407) &&
-       !data->set.connect_only)
-      streamclose(conn, "Negotiate transfer completed");
-    Curl_cleanup_negotiate(data);
-  }
-#endif
-
   /* set the proper values (possibly modified on POST) */
   conn->seek_func = data->set.seek_func; /* restore */
   conn->seek_client = data->set.seek_client; /* restore */
@@ -3376,7 +3379,24 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
         data->state.authproblem = TRUE;
       }
 #endif
-
+#if defined(USE_SPNEGO)
+      if(conn->bits.close &&
+        (((data->req.httpcode == 401) &&
+          (conn->negotiate.state == GSS_AUTHRECV)) ||
+         ((data->req.httpcode == 407) &&
+          (conn->proxyneg.state == GSS_AUTHRECV)))) {
+        infof(data, "Connection closure while negotiating auth (HTTP 1.0?)\n");
+        data->state.authproblem = TRUE;
+      }
+      if((conn->negotiate.state == GSS_AUTHDONE) &&
+         (data->req.httpcode != 401)) {
+        conn->negotiate.state = GSS_AUTHSUCC;
+      }
+      if((conn->proxyneg.state == GSS_AUTHDONE) &&
+         (data->req.httpcode != 407)) {
+        conn->proxyneg.state = GSS_AUTHSUCC;
+      }
+#endif
       /*
        * When all the headers have been parsed, see if we should give
        * up and return an error.
@@ -3953,6 +3973,22 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
       if(result)
         return result;
     }
+  #ifdef USE_SPNEGO
+    else if(checkprefix("Persistent-Auth", k->p)) {
+      struct negotiatedata *negdata = &conn->negotiate;
+      struct auth *authp = &data->state.authhost;
+      if(authp->picked == CURLAUTH_NEGOTIATE) {
+        char *persistentauth = Curl_copy_header_value(k->p);
+        if(!persistentauth)
+          return CURLE_OUT_OF_MEMORY;
+        negdata->noauthpersist = checkprefix("false", persistentauth);
+        negdata->havenoauthpersist = TRUE;
+        infof(data, "Negotiate: noauthpersist -> %d, header part: %s",
+          negdata->noauthpersist, persistentauth);
+        free(persistentauth);
+      }
+    }
+  #endif
     else if((k->httpcode >= 300 && k->httpcode < 400) &&
             checkprefix("Location:", k->p) &&
             !data->req.location) {
index 2a97707ebaba472ac1661f0a761ba639187adcc9..9415236fb1e457468cbbcaae242c484f4bbe3e5c 100644 (file)
@@ -56,7 +56,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
     service = data->set.str[STRING_PROXY_SERVICE_NAME] ?
               data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
     host = conn->http_proxy.host.name;
-    neg_ctx = &data->state.proxyneg;
+    neg_ctx = &conn->proxyneg;
   }
   else {
     userp = conn->user;
@@ -64,7 +64,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
     service = data->set.str[STRING_SERVICE_NAME] ?
               data->set.str[STRING_SERVICE_NAME] : "HTTP";
     host = conn->host.name;
-    neg_ctx = &data->state.negotiate;
+    neg_ctx = &conn->negotiate;
   }
 
   /* Not set means empty */
@@ -80,11 +80,16 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
     header++;
 
   len = strlen(header);
+  neg_ctx->havenegdata = len != 0;
   if(!len) {
-    /* Is this the first call in a new negotiation? */
-    if(neg_ctx->context) {
-      /* The server rejected our authentication and hasn't suppled any more
+    if(neg_ctx->state == GSS_AUTHSUCC) {
+      infof(conn->data, "Negotiate auth restarted\n");
+      Curl_cleanup_negotiate(conn);
+    }
+    else if(neg_ctx->state != GSS_AUTHNONE) {
+      /* The server rejected our authentication and hasn't supplied any more
       negotiation mechanisms */
+      Curl_cleanup_negotiate(conn);
       return CURLE_LOGIN_DENIED;
     }
   }
@@ -106,38 +111,96 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
 
 CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy)
 {
-  struct negotiatedata *neg_ctx = proxy ? &conn->data->state.proxyneg :
-    &conn->data->state.negotiate;
+  struct negotiatedata *neg_ctx = proxy ? &conn->proxyneg :
+    &conn->negotiate;
+  struct auth *authp = proxy ? &conn->data->state.authproxy :
+    &conn->data->state.authhost;
   char *base64 = NULL;
   size_t len = 0;
   char *userp;
   CURLcode result;
 
-  result = Curl_auth_create_spnego_message(conn->data, neg_ctx, &base64, &len);
-  if(result)
-    return result;
+  authp->done = FALSE;
+
+  if(neg_ctx->state == GSS_AUTHRECV) {
+    if(neg_ctx->havenegdata) {
+      neg_ctx->havemultiplerequests = TRUE;
+    }
+  }
+  else if(neg_ctx->state == GSS_AUTHSUCC) {
+    if(!neg_ctx->havenoauthpersist) {
+      neg_ctx->noauthpersist = !neg_ctx->havemultiplerequests;
+    }
+  }
 
-  userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "",
-                  base64);
+  if(neg_ctx->noauthpersist ||
+    (neg_ctx->state != GSS_AUTHDONE && neg_ctx->state != GSS_AUTHSUCC)) {
 
-  if(proxy) {
-    Curl_safefree(conn->allocptr.proxyuserpwd);
-    conn->allocptr.proxyuserpwd = userp;
+    if(neg_ctx->noauthpersist && neg_ctx->state == GSS_AUTHSUCC) {
+      infof(conn->data, "Curl_output_negotiate, "
+       "no persistent authentication: cleanup existing context");
+      Curl_auth_spnego_cleanup(neg_ctx);
+    }
+    if(!neg_ctx->context) {
+      result = Curl_input_negotiate(conn, proxy, "Negotiate");
+      if(result)
+        return result;
+    }
+
+    result = Curl_auth_create_spnego_message(conn->data,
+      neg_ctx, &base64, &len);
+    if(result)
+      return result;
+
+    userp = aprintf("%sAuthorization: Negotiate %s\r\n", proxy ? "Proxy-" : "",
+      base64);
+
+    if(proxy) {
+      Curl_safefree(conn->allocptr.proxyuserpwd);
+      conn->allocptr.proxyuserpwd = userp;
+    }
+    else {
+      Curl_safefree(conn->allocptr.userpwd);
+      conn->allocptr.userpwd = userp;
+    }
+
+    free(base64);
+
+    if(userp == NULL) {
+      return CURLE_OUT_OF_MEMORY;
+    }
+
+    neg_ctx->state = GSS_AUTHSENT;
+  #ifdef HAVE_GSSAPI
+    if(neg_ctx->status == GSS_S_COMPLETE ||
+       neg_ctx->status == GSS_S_CONTINUE_NEEDED) {
+      neg_ctx->state = GSS_AUTHDONE;
+    }
+  #else
+  #ifdef USE_WINDOWS_SSPI
+    if(neg_ctx->status == SEC_E_OK ||
+       neg_ctx->status == SEC_I_CONTINUE_NEEDED) {
+      neg_ctx->state = GSS_AUTHDONE;
+    }
+  #endif
+  #endif
   }
-  else {
-    Curl_safefree(conn->allocptr.userpwd);
-    conn->allocptr.userpwd = userp;
+
+  if(neg_ctx->state == GSS_AUTHDONE || neg_ctx->state == GSS_AUTHSUCC) {
+    /* connection is already authenticated,
+     * don't send a header in future requests */
+    authp->done = TRUE;
   }
 
-  free(base64);
+  neg_ctx->havenegdata = FALSE;
 
-  return (userp == NULL) ? CURLE_OUT_OF_MEMORY : CURLE_OK;
+  return CURLE_OK;
 }
 
-void Curl_cleanup_negotiate(struct Curl_easy *data)
+void Curl_cleanup_negotiate(struct connectdata *conn)
 {
-  Curl_auth_spnego_cleanup(&data->state.negotiate);
-  Curl_auth_spnego_cleanup(&data->state.proxyneg);
+  Curl_auth_spnego_cleanup(&conn->negotiate);
+  Curl_auth_spnego_cleanup(&conn->proxyneg);
 }
 
 #endif /* !CURL_DISABLE_HTTP && USE_SPNEGO */
index c64e54825189c9a34afe473c8c460eecc08e41e0..d4a7f09e095d871a722f44bc3f008d9f21a1e1c0 100644 (file)
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -31,7 +31,7 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
 /* this is for creating Negotiate header output */
 CURLcode Curl_output_negotiate(struct connectdata *conn, bool proxy);
 
-void Curl_cleanup_negotiate(struct Curl_easy *data);
+void Curl_cleanup_negotiate(struct connectdata *conn);
 
 #endif /* USE_SPNEGO */
 
index 1029aea9908e52d4c8c10504e8e326358e3a6088..cc16924a3ca1690432fc28455e8e7670e36f3c93 100644 (file)
@@ -600,7 +600,7 @@ static CURLcode multi_done(struct Curl_easy *data,
 
   /* if data->set.reuse_forbid is TRUE, it means the libcurl client has
      forced us to close this connection. This is ignored for requests taking
-     place in a NTLM authentication handshake
+     place in a NTLM/NEGOTIATE authentication handshake
 
      if conn->bits.close is TRUE, it means that the connection should be
      closed in spite of all our efforts to be nice, due to protocol
@@ -617,6 +617,10 @@ static CURLcode multi_done(struct Curl_easy *data,
 #if defined(USE_NTLM)
       && !(conn->ntlm.state == NTLMSTATE_TYPE2 ||
            conn->proxyntlm.state == NTLMSTATE_TYPE2)
+#endif
+#if defined(USE_SPNEGO)
+      && !(conn->negotiate.state == GSS_AUTHRECV ||
+           conn->proxyneg.state == GSS_AUTHRECV)
 #endif
      ) || conn->bits.close
        || (premature && !(conn->handler->flags & PROTOPT_STREAM))) {
index 76e912231a6e64ca307170faab056e6552c9ccbd..e67def5fc581d963d37d5ea40fa7ce2f7df71ad9 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -806,6 +806,10 @@ CURLcode Curl_disconnect(struct Curl_easy *data,
   /* Cleanup NTLM connection-related data */
   Curl_http_ntlm_cleanup(conn);
 #endif
+#if !defined(CURL_DISABLE_HTTP) && defined(USE_SPNEGO)
+  /* Cleanup NEGOTIATE connection-related data */
+  Curl_cleanup_negotiate(conn);
+#endif
 
   /* the protocol specific disconnect handler and conn_shutdown need a transfer
      for the connection! */
index e5596b87f0947d64dc7e1834955daee74058d275..24187a4c487d6a3a802b80904adbbad6fb0513b3 100644 (file)
@@ -358,7 +358,9 @@ struct ntlmdata {
 struct negotiatedata {
   /* When doing Negotiate (SPNEGO) auth, we first need to send a token
      and then validate the received one. */
-  enum { GSS_AUTHNONE, GSS_AUTHRECV, GSS_AUTHSENT } state;
+  enum {
+    GSS_AUTHNONE, GSS_AUTHRECV, GSS_AUTHSENT, GSS_AUTHDONE, GSS_AUTHSUCC
+  } state;
 #ifdef HAVE_GSSAPI
   OM_uint32 status;
   gss_ctx_id_t context;
@@ -380,6 +382,10 @@ struct negotiatedata {
   size_t output_token_length;
 #endif
 #endif
+  bool noauthpersist;
+  bool havenoauthpersist;
+  bool havenegdata;
+  bool havemultiplerequests;
 };
 #endif
 
@@ -977,6 +983,11 @@ struct connectdata {
 #endif
 #endif
 
+#ifdef USE_SPNEGO
+  struct negotiatedata negotiate; /* state data for host Negotiate auth */
+  struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */
+#endif
+
   /* data used for the asynch name resolve callback */
   struct Curl_async async;
 
@@ -1274,11 +1285,6 @@ struct UrlState {
   struct digestdata digest;      /* state data for host Digest auth */
   struct digestdata proxydigest; /* state data for proxy Digest auth */
 
-#ifdef USE_SPNEGO
-  struct negotiatedata negotiate; /* state data for host Negotiate auth */
-  struct negotiatedata proxyneg; /* state data for proxy Negotiate auth */
-#endif
-
   struct auth authhost;  /* auth details for host */
   struct auth authproxy; /* auth details for proxy */
 
index 4a48bdd2088880859e107459827b27133649863d..7c4bd4b5952d37d32992afc36933c803a10b58ac 100644 (file)
@@ -5,7 +5,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -273,6 +273,11 @@ void Curl_auth_spnego_cleanup(struct negotiatedata *nego)
 
   /* Reset any variables */
   nego->status = 0;
+  nego->state = GSS_AUTHNONE;
+  nego->noauthpersist = FALSE;
+  nego->havenoauthpersist = FALSE;
+  nego->havenegdata = FALSE;
+  nego->havemultiplerequests = FALSE;
 }
 
 #endif /* HAVE_GSSAPI && USE_SPNEGO */
index 98c471e581642d913fc0e883f944cde3b49b0309..0171ec52b5bbaa5772e66efee8cdf6c07343af8f 100644 (file)
@@ -343,6 +343,11 @@ void Curl_auth_spnego_cleanup(struct negotiatedata *nego)
   /* Reset any variables */
   nego->status = 0;
   nego->token_max = 0;
+  nego->state = GSS_AUTHNONE;
+  nego->noauthpersist = FALSE;
+  nego->havenoauthpersist = FALSE;
+  nego->havenegdata = FALSE;
+  nego->havemultiplerequests = FALSE;
 }
 
 #endif /* USE_WINDOWS_SSPI && USE_SPNEGO */
index f00e21204b82f9cac14bb598588008cb6bf367c0..5d2584eec03e298aaed6b5f4c67bfb17432502e9 100644 (file)
@@ -8,17 +8,7 @@ HTTP Negotiate auth (stub krb5)
 </info>
 # Server-side
 <reply>
-<!-- First request, expect 401 Negotiate -->
-<data>
-HTTP/1.1 401 Authorization Required
-Server: Microsoft-IIS/7.0
-Content-Type: text/html; charset=iso-8859-1
-WWW-Authenticate: Negotiate
-Content-Length: 13
-
-Not yet sir!
-</data>
-<!-- Second request, expect success in one shot -->
+<!-- First request, expect success in one shot -->
 <data1>
 HTTP/1.1 200 Things are fine in server land
 Server: Microsoft-IIS/7.0
@@ -29,12 +19,6 @@ Content-Length: 15
 Nice auth sir!
 </data1>
 <datacheck>
-HTTP/1.1 401 Authorization Required
-Server: Microsoft-IIS/7.0
-Content-Type: text/html; charset=iso-8859-1
-WWW-Authenticate: Negotiate
-Content-Length: 13
-
 HTTP/1.1 200 Things are fine in server land
 Server: Microsoft-IIS/7.0
 Content-Type: text/html; charset=iso-8859-1
@@ -73,10 +57,6 @@ CURL_STUB_GSS_CREDS="KRB5_Alice"
 ^User-Agent:.*
 </strip>
 <protocol>
-GET /2056 HTTP/1.1\r
-Host: %HOSTIP:%HTTPPORT\r
-Accept: */*\r
-\r
 GET /2056 HTTP/1.1\r
 Host: %HOSTIP:%HTTPPORT\r
 Authorization: Negotiate IktSQjVfQWxpY2UiOkhUVFBAMTI3LjAuMC4xOjE6QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==\r
index 5625051685e52b9ecd5865069b674a1873e0efb3..92d7824c17c0a793bb937e7b802d2a0b6b1b87a7 100644 (file)
@@ -8,17 +8,7 @@ HTTP Negotiate auth (stub ntlm)
 </info>
 # Server-side
 <reply>
-<!-- First request, expect 401 Negotiate -->
-<data>
-HTTP/1.1 401 Authorization Required
-Server: Microsoft-IIS/7.0
-Content-Type: text/html; charset=iso-8859-1
-WWW-Authenticate: Negotiate
-Content-Length: 13
-
-Not yet sir!
-</data>
-<!-- Second request, expect 401 (ntlm challenge) -->
+<!-- First request, expect 401 (ntlm challenge) -->
 <data1>
 HTTP/1.1 401 Authorization Required
 Server: Microsoft-IIS/7.0
@@ -28,7 +18,7 @@ Content-Length: 19
 
 Still not yet sir!
 </data1>
-<!-- Third request, expect success  -->
+<!-- Second request, expect success  -->
 <data2>
 HTTP/1.1 200 Things are fine in server land
 Server: Microsoft-IIS/7.0
@@ -39,12 +29,6 @@ Content-Length: 15
 Nice auth sir!
 </data2>
 <datacheck>
-HTTP/1.1 401 Authorization Required
-Server: Microsoft-IIS/7.0
-Content-Type: text/html; charset=iso-8859-1
-WWW-Authenticate: Negotiate
-Content-Length: 13
-
 HTTP/1.1 401 Authorization Required
 Server: Microsoft-IIS/7.0
 Content-Type: text/html; charset=iso-8859-1
@@ -89,10 +73,6 @@ CURL_STUB_GSS_CREDS="NTLM_Alice"
 ^User-Agent:.*
 </strip>
 <protocol>
-GET /2057 HTTP/1.1\r
-Host: %HOSTIP:%HTTPPORT\r
-Accept: */*\r
-\r
 GET /2057 HTTP/1.1\r
 Host: %HOSTIP:%HTTPPORT\r
 Authorization: Negotiate Ik5UTE1fQWxpY2UiOkhUVFBAMTI3LjAuMC4xOjI6QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ==\r