From bb6d420f543eb93904809b00916f467b4972c3ba Mon Sep 17 00:00:00 2001 From: Orgad Shaneh Date: Tue, 5 May 2015 15:08:59 +0300 Subject: [PATCH] curl: Fix digest authentication cherry-picked from upstream commit 59f3f92ba6150e9a5a57f71b6e781802148916d0 --- ...te-domain-from-the-realm-in-the-chal.patch | 211 ++++++++++++++++++ mingw-w64-curl/PKGBUILD | 9 +- 2 files changed, 217 insertions(+), 3 deletions(-) create mode 100644 mingw-w64-curl/0004-sasl_sspi-Populate-domain-from-the-realm-in-the-chal.patch diff --git a/mingw-w64-curl/0004-sasl_sspi-Populate-domain-from-the-realm-in-the-chal.patch b/mingw-w64-curl/0004-sasl_sspi-Populate-domain-from-the-realm-in-the-chal.patch new file mode 100644 index 0000000000..fba529492e --- /dev/null +++ b/mingw-w64-curl/0004-sasl_sspi-Populate-domain-from-the-realm-in-the-chal.patch @@ -0,0 +1,211 @@ +From 59f3f92ba6150e9a5a57f71b6e781802148916d0 Mon Sep 17 00:00:00 2001 +From: Grant Pannell +Date: Sun, 26 Apr 2015 16:12:23 +0200 +Subject: [PATCH] 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 +--- + lib/curl_sasl.c | 14 +++++----- + lib/curl_sasl.h | 9 +++++++ + lib/curl_sasl_sspi.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + lib/curl_sspi.h | 4 +++ + 4 files changed, 95 insertions(+), 6 deletions(-) + +diff --git a/lib/curl_sasl.c b/lib/curl_sasl.c +index d9f63ab..68646bc 100644 +--- a/lib/curl_sasl.c ++++ b/lib/curl_sasl.c +@@ -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) +diff --git a/lib/curl_sasl.h b/lib/curl_sasl.h +index 0dc7377..117d60e 100644 +--- a/lib/curl_sasl.h ++++ b/lib/curl_sasl.h +@@ -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 +diff --git a/lib/curl_sasl_sspi.c b/lib/curl_sasl_sspi.c +index 0a332e6..b149530 100644 +--- a/lib/curl_sasl_sspi.c ++++ b/lib/curl_sasl_sspi.c +@@ -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" +@@ -274,6 +275,74 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data, + } + + /* ++* 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() + * + * This is used to decode a HTTP DIGEST challenge message into the seperate +@@ -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; + } +diff --git a/lib/curl_sspi.h b/lib/curl_sspi.h +index 7fa308c..8655715 100644 +--- a/lib/curl_sspi.h ++++ b/lib/curl_sspi.h +@@ -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); +-- +2.3.7.windows.1 + diff --git a/mingw-w64-curl/PKGBUILD b/mingw-w64-curl/PKGBUILD index 013d471165..0a225f855e 100644 --- a/mingw-w64-curl/PKGBUILD +++ b/mingw-w64-curl/PKGBUILD @@ -6,7 +6,7 @@ _variant=-openssl _realname=curl pkgname="${MINGW_PACKAGE_PREFIX}-${_realname}" pkgver=7.42.1 -pkgrel=2 +pkgrel=3 pkgdesc="An URL retrival utility and library. (mingw-w64)" arch=('any') url="http://curl.haxx.se" @@ -29,12 +29,14 @@ options=('staticlibs') source=("$url/download/${_realname}-$pkgver.tar.bz2"{,.asc} "0001-curl-relocation.patch" "0002-curl-mingw-enable-static.patch" - "0003-curl-mingw-text-mode-for-netrc.patch") + "0003-curl-mingw-text-mode-for-netrc.patch" + "0004-sasl_sspi-Populate-domain-from-the-realm-in-the-chal.patch") md5sums=('296945012ce647b94083ed427c1877a8' 'SKIP' '58520051c4ed77781d233c3fa40a5435' 'eac9e212e619490966ae47004bec547b' - 'c35c31a1c8ed28c75be93e5bf95c8c9e') + 'c35c31a1c8ed28c75be93e5bf95c8c9e' + '8d16dedc48b53f9406ab103a74889681') validpgpkeys=('914C533DF9B2ADA2204F586D78E11C6B279D5C91') # Daniel Stenberg prepare() { @@ -43,6 +45,7 @@ prepare() { patch -p1 -i "${srcdir}/0001-curl-relocation.patch" patch -p1 -i "${srcdir}/0002-curl-mingw-enable-static.patch" patch -p1 -i "${srcdir}/0003-curl-mingw-text-mode-for-netrc.patch" + patch -p1 -i "${srcdir}/0004-sasl_sspi-Populate-domain-from-the-realm-in-the-chal.patch" autoreconf -vfi }