Commit 59f3f92b authored by Grant Pannell's avatar Grant Pannell Committed by Daniel Stenberg
Browse files

sasl_sspi: Populate domain from the realm in the challenge

Without this, SSPI based digest auth was broken.

Bug: https://github.com/bagder/curl/pull/141.patch
parent 6a726135
Loading
Loading
Loading
Loading
+8 −6
Original line number Diff line number Diff line
@@ -76,9 +76,6 @@ const struct {
#define DIGEST_QOP_VALUE_STRING_AUTH_INT  "auth-int"
#define DIGEST_QOP_VALUE_STRING_AUTH_CONF "auth-conf"

#define DIGEST_MAX_VALUE_LENGTH           256
#define DIGEST_MAX_CONTENT_LENGTH         1024

/* The CURL_OUTPUT_DIGEST_CONV macro below is for non-ASCII machines.
   It converts digest text to ASCII so the MD5 will be correct for
   what ultimately goes over the network.
@@ -90,12 +87,15 @@ const struct {
    return result; \
  }

#endif

#if !defined(CURL_DISABLE_CRYPTO_AUTH)
/*
 * Returns 0 on success and then the buffers are filled in fine.
 *
 * Non-zero means failure to parse.
 */
static int sasl_digest_get_pair(const char *str, char *value, char *content,
int Curl_sasl_digest_get_pair(const char *str, char *value, char *content,
                              const char **endptr)
{
  int c;
@@ -157,7 +157,9 @@ static int sasl_digest_get_pair(const char *str, char *value, char *content,

  return 0; /* all is fine! */
}
#endif

#if !defined(CURL_DISABLE_CRYPTO_AUTH) && !defined(USE_WINDOWS_SSPI)
/* Convert md5 chunk to RFC2617 (section 3.1.3) -suitable ascii string*/
static void sasl_digest_md5_to_ascii(unsigned char *source, /* 16 bytes */
                                     unsigned char *dest) /* 33 bytes */
@@ -776,7 +778,7 @@ CURLcode Curl_sasl_decode_digest_http_message(const char *chlg,
      chlg++;

    /* Extract a value=content pair */
    if(!sasl_digest_get_pair(chlg, value, content, &chlg)) {
    if(!Curl_sasl_digest_get_pair(chlg, value, content, &chlg)) {
      if(Curl_raw_equal(value, "nonce")) {
        digest->nonce = strdup(content);
        if(!digest->nonce)
+9 −0
Original line number Diff line number Diff line
@@ -65,6 +65,11 @@ struct kerberos5data;
#define SASL_MECH_STRING_NTLM       "NTLM"
#define SASL_MECH_STRING_XOAUTH2    "XOAUTH2"

#if !defined(CURL_DISABLE_CRYPTO_AUTH)
#define DIGEST_MAX_VALUE_LENGTH           256
#define DIGEST_MAX_CONTENT_LENGTH         1024
#endif

enum {
  CURLDIGESTALGO_MD5,
  CURLDIGESTALGO_MD5SESS
@@ -136,6 +141,10 @@ char *Curl_sasl_build_spn(const char *service, const char *instance);
TCHAR *Curl_sasl_build_spn(const char *service, const char *instance);
#endif

/* This is used to extract the realm from a challenge message */
int Curl_sasl_digest_get_pair(const char *str, char *value, char *content,
                              const char **endptr);

#if defined(HAVE_GSSAPI)
char *Curl_sasl_build_gssapi_spn(const char *service, const char *host);
#endif
+74 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
#include "sendf.h"
#include "strdup.h"
#include "curl_printf.h"
#include "rawstr.h"

/* The last #include files should be: */
#include "curl_memory.h"
@@ -273,6 +274,74 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
  return result;
}

/*
* Curl_override_sspi_http_realm()
*
* This is used to populate the domain in a SSPI identity structure
* The realm is extracted from the challenge message and used as the
* domain if it is not already explicitly set.
*
* Parameters:
*
* chlg     [in]     - The challenge message.
* identity [in/out] - The identity structure.
*
* Returns CURLE_OK on success.
*/
CURLcode Curl_override_sspi_http_realm(const char *chlg,
                                       SEC_WINNT_AUTH_IDENTITY *identity)
{
  xcharp_u domain, dup_domain;

  /* If domain is blank or unset, check challenge message for realm */
  if(!identity->Domain || !identity->DomainLength) {
    for(;;) {
      char value[DIGEST_MAX_VALUE_LENGTH];
      char content[DIGEST_MAX_CONTENT_LENGTH];

      /* Pass all additional spaces here */
      while(*chlg && ISSPACE(*chlg))
        chlg++;

      /* Extract a value=content pair */
      if(!Curl_sasl_digest_get_pair(chlg, value, content, &chlg)) {
        if(Curl_raw_equal(value, "realm")) {

          /* Setup identity's domain and length */
          domain.tchar_ptr = Curl_convert_UTF8_to_tchar((char *)content);
          if(!domain.tchar_ptr)
            return CURLE_OUT_OF_MEMORY;
          dup_domain.tchar_ptr = _tcsdup(domain.tchar_ptr);
          if(!dup_domain.tchar_ptr) {
            Curl_unicodefree(domain.tchar_ptr);
            return CURLE_OUT_OF_MEMORY;
          }
          identity->Domain = dup_domain.tbyte_ptr;
          identity->DomainLength = curlx_uztoul(_tcslen(dup_domain.tchar_ptr));
          dup_domain.tchar_ptr = NULL;

          Curl_unicodefree(domain.tchar_ptr);
        }
        else {
          /* unknown specifier, ignore it! */
        }
      }
      else
        break; /* we're done here */

      /* Pass all additional spaces here */
      while(*chlg && ISSPACE(*chlg))
        chlg++;

      /* Allow the list to be comma-separated */
      if(',' == *chlg)
        chlg++;
    }
  }

  return CURLE_OK;
}

/*
 * Curl_sasl_decode_digest_http_message()
 *
@@ -374,6 +443,11 @@ CURLcode Curl_sasl_create_digest_http_message(struct SessionHandle *data,
    if(Curl_create_sspi_identity(userp, passwdp, &identity))
      return CURLE_OUT_OF_MEMORY;

    /* Populate our identity domain */
    if(Curl_override_sspi_http_realm((const char*)digest->input_token,
                                     &identity))
      return CURLE_OUT_OF_MEMORY;

    /* Allow proper cleanup of the identity structure */
    p_identity = &identity;
  }
+4 −0
Original line number Diff line number Diff line
@@ -43,6 +43,10 @@
CURLcode Curl_sspi_global_init(void);
void Curl_sspi_global_cleanup(void);

/* This is used to populate the domain in a SSPI identity structure */
CURLcode Curl_override_sspi_http_realm(const char *chlg,
                                       SEC_WINNT_AUTH_IDENTITY *identity);

/* This is used to generate an SSPI identity structure */
CURLcode Curl_create_sspi_identity(const char *userp, const char *passwdp,
                                   SEC_WINNT_AUTH_IDENTITY *identity);