]> granicus.if.org Git - curl/commitdiff
spnego_sspi: add support for channel binding
authorgeorgeok <giorgos.n.oikonomou@gmail.com>
Tue, 29 Jan 2019 17:26:31 +0000 (18:26 +0100)
committerMarcel Raad <Marcel.Raad@teamviewer.com>
Fri, 1 Feb 2019 08:56:27 +0000 (09:56 +0100)
Attempt to add support for Secure Channel binding when negotiate
authentication is used. The problem to solve is that by default IIS
accepts channel binding and curl doesn't utilise them. The result was a
401 response. Scope affects only the Schannel(winssl)-SSPI combination.

Fixes https://github.com/curl/curl/issues/3503
Closes https://github.com/curl/curl/pull/3509

lib/http_negotiate.c
lib/http_ntlm.c
lib/urldata.h
lib/vauth/spnego_sspi.c
lib/vtls/schannel.c

index 4713d1bd5ca3de3e44f260b53e442c139d7911bc..2a97707ebaba472ac1661f0a761ba639187adcc9 100644 (file)
@@ -89,6 +89,11 @@ CURLcode Curl_input_negotiate(struct connectdata *conn, bool proxy,
     }
   }
 
+  /* Supports SSL channel binding for Windows ISS extended protection */
+#if defined(USE_WINDOWS_SSPI) && defined(SECPKG_ATTR_ENDPOINT_BINDINGS)
+  neg_ctx->sslContext = conn->sslContext;
+#endif
+
   /* Initialize the security context and decode our challenge */
   result = Curl_auth_decode_spnego_message(data, userp, passwdp, service,
                                            host, header, neg_ctx);
index a9b33f98e45cb3047ae01031a6ced33af4a9ba91..aaf8a3deb120505f1e8298a3154a7b3870d79961 100644 (file)
@@ -175,6 +175,9 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
     if(s_hSecDll == NULL)
       return err;
   }
+#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS
+  ntlm->sslContext = conn->sslContext;
+#endif
 #endif
 
   switch(ntlm->state) {
index b71a843b43b5ca919e689a1b73d26a822ad1497c..ff3cc9a655e8e5646cb3120b8b43efa6adc1f516 100644 (file)
@@ -364,6 +364,9 @@ struct negotiatedata {
   gss_buffer_desc output_token;
 #else
 #ifdef USE_WINDOWS_SSPI
+#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS
+  CtxtHandle *sslContext;
+#endif
   DWORD status;
   CredHandle *credentials;
   CtxtHandle *context;
@@ -980,6 +983,9 @@ struct connectdata {
   void *seek_client;            /* pointer to pass to the seek() above */
 
   /*************** Request - specific items ************/
+#if defined(USE_WINDOWS_SSPI) && defined(SECPKG_ATTR_ENDPOINT_BINDINGS)
+  CtxtHandle *sslContext;
+#endif
 
 #if defined(USE_NTLM)
   struct ntlmdata ntlm;     /* NTLM differs from other authentication schemes
index d3cb5cb0f63f196f4d3072852f7441e548834f32..00d8404652ac8203511a391154c6fd7bd52840a7 100644 (file)
@@ -92,7 +92,7 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
   size_t chlglen = 0;
   unsigned char *chlg = NULL;
   PSecPkgInfo SecurityPackage;
-  SecBuffer chlg_buf;
+  SecBuffer chlg_buf[2];
   SecBuffer resp_buf;
   SecBufferDesc chlg_desc;
   SecBufferDesc resp_desc;
@@ -189,12 +189,39 @@ CURLcode Curl_auth_decode_spnego_message(struct Curl_easy *data,
     }
 
     /* Setup the challenge "input" security buffer */
-    chlg_desc.ulVersion = SECBUFFER_VERSION;
-    chlg_desc.cBuffers  = 1;
-    chlg_desc.pBuffers  = &chlg_buf;
-    chlg_buf.BufferType = SECBUFFER_TOKEN;
-    chlg_buf.pvBuffer   = chlg;
-    chlg_buf.cbBuffer   = curlx_uztoul(chlglen);
+    chlg_desc.ulVersion    = SECBUFFER_VERSION;
+    chlg_desc.cBuffers     = 1;
+    chlg_desc.pBuffers     = &chlg_buf[0];
+    chlg_buf[0].BufferType = SECBUFFER_TOKEN;
+    chlg_buf[0].pvBuffer   = chlg;
+    chlg_buf[0].cbBuffer   = curlx_uztoul(chlglen);
+
+#ifdef SECPKG_ATTR_ENDPOINT_BINDINGS
+    /* ssl context comes from Schannel.
+    * When extended protection is used in IIS server,
+    * we have to pass a second SecBuffer to the SecBufferDesc
+    * otherwise IIS will not pass the authentication (401 response).
+    * Minimum supported version is Windows 7.
+    * https://docs.microsoft.com/en-us/security-updates
+    * /SecurityAdvisories/2009/973811
+    */
+    if(nego->sslContext) {
+      SEC_CHANNEL_BINDINGS channelBindings;
+      SecPkgContext_Bindings pkgBindings;
+      pkgBindings.Bindings = &channelBindings;
+      nego->status = s_pSecFn->QueryContextAttributes(
+          nego->sslContext,
+          SECPKG_ATTR_ENDPOINT_BINDINGS,
+          &pkgBindings
+      );
+      if(nego->status == SEC_E_OK) {
+        chlg_desc.cBuffers++;
+        chlg_buf[1].BufferType = SECBUFFER_CHANNEL_BINDINGS;
+        chlg_buf[1].cbBuffer   = pkgBindings.BindingsLength;
+        chlg_buf[1].pvBuffer   = pkgBindings.Bindings;
+      }
+    }
+#endif
   }
 
   /* Setup the response "output" security buffer */
index 4c816fddaa7fc44333ddb45e9ffdafa582218b20..c8574f56c1589ff802b84401f75ae680540c261b 100644 (file)
@@ -1428,7 +1428,7 @@ schannel_connect_common(struct connectdata *conn, int sockindex,
      * binding to pass the IIS extended protection checks.
      * Available on Windows 7 or later.
      */
-    conn->ntlm.sslContext = &BACKEND->ctxt->ctxt_handle;
+    conn->sslContext = &BACKEND->ctxt->ctxt_handle;
 #endif
 
     *done = TRUE;