]> git.ipfire.org Git - thirdparty/curl.git/commitdiff
sasl_sspi: Populate domain from the realm in the challenge
authorGrant Pannell <grant@pannell.net.au>
Sun, 26 Apr 2015 14:12:23 +0000 (16:12 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Sun, 26 Apr 2015 14:12:23 +0000 (16:12 +0200)
Without this, SSPI based digest auth was broken.

Bug: https://github.com/bagder/curl/pull/141.patch

lib/curl_sasl.c
lib/curl_sasl.h
lib/curl_sasl_sspi.c
lib/curl_sspi.h

index d9f63ab0b4b747eae09ae44b05403484404c873b..68646bc1a8379cc34d9142885d9e621bc813dd65 100644 (file)
@@ -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,13 +87,16 @@ 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,
-                                const char **endptr)
+int Curl_sasl_digest_get_pair(const char *str, char *value, char *content,
+                              const char **endptr)
 {
   int c;
   bool starts_with_quote = FALSE;
@@ -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)
index 0dc73770fc577284d0c2bf8bbcfe61b7690b8a9c..117d60e32d1c406815f00caca87e8d4d4727f438 100644 (file)
@@ -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
index 0a332e60b7822444d16b8276a053550066e98a56..b149530ffbc4c6b27d388581174d433a350b1190 100644 (file)
@@ -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;
   }
index 7fa308c5a8925e8d5e798e54273e5692107e0c2e..8655715e29e327178078fa10793096e14262e816 100644 (file)
 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);