aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorGrant Pannell <grant@pannell.net.au>2015-04-26 16:12:23 +0200
committerDaniel Stenberg <daniel@haxx.se>2015-04-26 16:12:23 +0200
commit59f3f92ba6150e9a5a57f71b6e781802148916d0 (patch)
tree61f20d9de4e2732a9b73f0feaf4c1938b7cf79ce /lib
parent6a7261359b4c7ebddff0c096468047077e7d06ef (diff)
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
Diffstat (limited to 'lib')
-rw-r--r--lib/curl_sasl.c14
-rw-r--r--lib/curl_sasl.h9
-rw-r--r--lib/curl_sasl_sspi.c74
-rw-r--r--lib/curl_sspi.h4
4 files changed, 95 insertions, 6 deletions
diff --git a/lib/curl_sasl.c b/lib/curl_sasl.c
index d9f63ab0b..68646bc1a 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 0dc73770f..117d60e32 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 0a332e60b..b149530ff 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 7fa308c5a..8655715e2 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);