]> granicus.if.org Git - curl/commitdiff
ntlm_sspi: fix authentication using Credential Manager
authortoughengineer <paul.skeptic@yandex.ru>
Sat, 8 Jul 2017 00:10:08 +0000 (02:10 +0200)
committerMarcel Raad <Marcel.Raad@teamviewer.com>
Mon, 16 Apr 2018 18:43:21 +0000 (20:43 +0200)
If you pass empty user/pass asking curl to use Windows Credential
Storage (as stated in the docs) and it has valid credentials for the
domain, e.g.
curl -v -u : --ntlm example.com
currently authentication fails.
This change fixes it by providing proper SPN string to the SSPI API
calls.

Fixes https://github.com/curl/curl/issues/1622
Closes https://github.com/curl/curl/pull/1660

lib/curl_sasl.c
lib/http_ntlm.c
lib/urldata.h
lib/vauth/ntlm.c
lib/vauth/ntlm_sspi.c
lib/vauth/vauth.h

index 7052bd91331bba8434fe6c767c333d4d98b3ffd1..e54e4875e2d9202afe5ec93bf51b8a4f8efd885c 100644 (file)
@@ -265,7 +265,7 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
   const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
     conn->host.name;
   const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
-#if defined(USE_KERBEROS5)
+#if defined(USE_KERBEROS5) || defined(USE_NTLM)
   const char *service = data->set.str[STRING_SERVICE_NAME] ?
     data->set.str[STRING_SERVICE_NAME] :
     sasl->params->service;
@@ -333,7 +333,10 @@ CURLcode Curl_sasl_start(struct SASL *sasl, struct connectdata *conn,
       if(force_ir || data->set.sasl_ir)
         result = Curl_auth_create_ntlm_type1_message(data,
                                                      conn->user, conn->passwd,
-                                                     &conn->ntlm, &resp, &len);
+                                                     service,
+                                                     hostname,
+                                                     &conn->ntlm, &resp,
+                                                     &len);
       }
     else
 #endif
@@ -419,13 +422,11 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
   char *chlg = NULL;
   size_t chlglen = 0;
 #endif
-#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5)
+#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
+    defined(USE_NTLM)
   const char *service = data->set.str[STRING_SERVICE_NAME] ?
                         data->set.str[STRING_SERVICE_NAME] :
                         sasl->params->service;
-#endif
-#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
-    defined(USE_NTLM)
   char *serverdata;
 #endif
   size_t len = 0;
@@ -496,6 +497,7 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
     /* Create the type-1 message */
     result = Curl_auth_create_ntlm_type1_message(data,
                                                  conn->user, conn->passwd,
+                                                 service, hostname,
                                                  &conn->ntlm, &resp, &len);
     newstate = SASL_NTLM_TYPE2MSG;
     break;
index 0f1edcf65dc38d1ec94231c65710ea3d8b042224..fd5540b5d06025c35fd4761060f87b0ea2b30d3b 100644 (file)
@@ -121,9 +121,11 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
      server, which is for a plain host or for a HTTP proxy */
   char **allocuserpwd;
 
-  /* point to the name and password for this */
+  /* point to the username, password, service and host */
   const char *userp;
   const char *passwdp;
+  const char *service = NULL;
+  const char *hostname = NULL;
 
   /* point to the correct struct with this */
   struct ntlmdata *ntlm;
@@ -141,6 +143,9 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
     allocuserpwd = &conn->allocptr.proxyuserpwd;
     userp = conn->http_proxy.user;
     passwdp = conn->http_proxy.passwd;
+    service = conn->data->set.str[STRING_PROXY_SERVICE_NAME] ?
+              conn->data->set.str[STRING_PROXY_SERVICE_NAME] : "HTTP";
+    hostname = conn->http_proxy.host.name;
     ntlm = &conn->proxyntlm;
     authp = &conn->data->state.authproxy;
   }
@@ -148,6 +153,9 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
     allocuserpwd = &conn->allocptr.userpwd;
     userp = conn->user;
     passwdp = conn->passwd;
+    service = conn->data->set.str[STRING_SERVICE_NAME] ?
+              conn->data->set.str[STRING_SERVICE_NAME] : "HTTP";
+    hostname = conn->host.name;
     ntlm = &conn->ntlm;
     authp = &conn->data->state.authhost;
   }
@@ -174,7 +182,9 @@ CURLcode Curl_output_ntlm(struct connectdata *conn, bool proxy)
   default: /* for the weird cases we (re)start here */
     /* Create a type-1 message */
     result = Curl_auth_create_ntlm_type1_message(conn->data, userp, passwdp,
-                                                 ntlm, &base64, &len);
+                                                 service, hostname,
+                                                 ntlm, &base64,
+                                                 &len);
     if(result)
       return result;
 
index 196aa639501724e6a6c878e1e96a3876495f0155..d439dc3d6cba59298bf8c0c2c4c97aa243d8016f 100644 (file)
@@ -328,6 +328,7 @@ struct ntlmdata {
   BYTE *output_token;
   BYTE *input_token;
   size_t input_token_len;
+  TCHAR *spn;
 #else
   unsigned int flags;
   unsigned char nonce[8];
index 1e0d4792e765fb728c8daef31f451c1b6fc64c1c..ea5e56e37e84d650e25024241dc1d9d59527c5a6 100644 (file)
@@ -355,6 +355,8 @@ static void unicodecpy(unsigned char *dest, const char *src, size_t length)
  * data    [in]     - The session handle.
  * userp   [in]     - The user name in the format User or Domain\User.
  * passdwp [in]     - The user's password.
+ * service [in]     - The service type such as http, smtp, pop or imap.
+ * host    [in]     - The host name.
  * ntlm    [in/out] - The NTLM data struct being used and modified.
  * outptr  [in/out] - The address where a pointer to newly allocated memory
  *                    holding the result will be stored upon completion.
@@ -365,6 +367,8 @@ static void unicodecpy(unsigned char *dest, const char *src, size_t length)
 CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
                                              const char *userp,
                                              const char *passwdp,
+                                             const char *service,
+                                             const char *hostname,
                                              struct ntlmdata *ntlm,
                                              char **outptr, size_t *outlen)
 {
@@ -394,6 +398,8 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
                                          domain are empty */
   (void)userp;
   (void)passwdp;
+  (void)service,
+  (void)hostname,
 
   /* Clean up any former leftovers and initialise to defaults */
   Curl_auth_ntlm_cleanup(ntlm);
index 921524618463a6938526d40d9cc12b95b2c5f05a..089c1a6d4b5e8ddb396a0f93228e35e0ee8e2595 100644 (file)
@@ -70,6 +70,8 @@ bool Curl_auth_is_ntlm_supported(void)
  * data    [in]     - The session handle.
  * userp   [in]     - The user name in the format User or Domain\User.
  * passdwp [in]     - The user's password.
+ * service [in]     - The service type such as http, smtp, pop or imap.
+ * host    [in]     - The host name.
  * ntlm    [in/out] - The NTLM data struct being used and modified.
  * outptr  [in/out] - The address where a pointer to newly allocated memory
  *                    holding the result will be stored upon completion.
@@ -80,6 +82,8 @@ bool Curl_auth_is_ntlm_supported(void)
 CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
                                              const char *userp,
                                              const char *passwdp,
+                                             const char *service,
+                                             const char *host,
                                              struct ntlmdata *ntlm,
                                              char **outptr, size_t *outlen)
 {
@@ -143,6 +147,10 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
   if(!ntlm->context)
     return CURLE_OUT_OF_MEMORY;
 
+  ntlm->spn = Curl_auth_build_spn(service, host, NULL);
+  if(!ntlm->spn)
+    return CURLE_OUT_OF_MEMORY;
+
   /* Setup the type-1 "output" security buffer */
   type_1_desc.ulVersion = SECBUFFER_VERSION;
   type_1_desc.cBuffers  = 1;
@@ -153,7 +161,7 @@ CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
 
   /* Generate our type-1 message */
   status = s_pSecFn->InitializeSecurityContext(ntlm->credentials, NULL,
-                                               (TCHAR *) TEXT(""),
+                                               ntlm->spn,
                                                0, 0, SECURITY_NETWORK_DREP,
                                                NULL, 0,
                                                ntlm->context, &type_1_desc,
@@ -271,7 +279,7 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
   /* Generate our type-3 message */
   status = s_pSecFn->InitializeSecurityContext(ntlm->credentials,
                                                ntlm->context,
-                                               (TCHAR *) TEXT(""),
+                                               ntlm->spn,
                                                0, 0, SECURITY_NETWORK_DREP,
                                                &type_2_desc,
                                                0, ntlm->context,
@@ -329,6 +337,8 @@ void Curl_auth_ntlm_cleanup(struct ntlmdata *ntlm)
 
   /* Reset any variables */
   ntlm->token_max = 0;
+
+  Curl_safefree(ntlm->spn);
 }
 
 #endif /* USE_WINDOWS_SSPI && USE_NTLM */
index dfaf985c60a0421dca1616480fb1bbff6c419d3f..f43064211f49bf84007259febaaa067aa030632e 100644 (file)
@@ -122,6 +122,8 @@ bool Curl_auth_is_ntlm_supported(void);
 CURLcode Curl_auth_create_ntlm_type1_message(struct Curl_easy *data,
                                              const char *userp,
                                              const char *passwdp,
+                                             const char *service,
+                                             const char *host,
                                              struct ntlmdata *ntlm,
                                              char **outptr,
                                              size_t *outlen);