Unverified Commit bc4b8c97 authored by toughengineer's avatar toughengineer Committed by Marcel Raad
Browse files

ntlm_sspi: fix authentication using Credential Manager

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
parent 2d4c2152
Loading
Loading
Loading
Loading
+8 −6
Original line number Diff line number Diff line
@@ -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;
+12 −2
Original line number Diff line number Diff line
@@ -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;

+1 −0
Original line number Diff line number Diff line
@@ -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];
+6 −0
Original line number Diff line number Diff line
@@ -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);
+12 −2
Original line number Diff line number Diff line
@@ -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 */
Loading