aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/curl_sasl.c72
1 files changed, 68 insertions, 4 deletions
diff --git a/lib/curl_sasl.c b/lib/curl_sasl.c
index 8d7a77174..d877eff6f 100644
--- a/lib/curl_sasl.c
+++ b/lib/curl_sasl.c
@@ -40,6 +40,8 @@
#include "curl_sasl.h"
#include "warnless.h"
#include "curl_memory.h"
+#include "strtok.h"
+#include "rawstr.h"
#ifdef USE_NSS
#include "vtls/nssg.h" /* for Curl_nss_force_init() */
@@ -52,6 +54,14 @@
#include "memdebug.h"
#if !defined(CURL_DISABLE_CRYPTO_AUTH) && !defined(USE_WINDOWS_SSPI)
+#define DIGEST_QOP_VALUE_AUTH (1 << 0)
+#define DIGEST_QOP_VALUE_AUTH_INT (1 << 1)
+#define DIGEST_QOP_VALUE_AUTH_CONF (1 << 2)
+
+#define DIGEST_QOP_VALUE_STRING_AUTH "auth"
+#define DIGEST_QOP_VALUE_STRING_AUTH_INT "auth-int"
+#define DIGEST_QOP_VALUE_STRING_AUTH_CONF "auth-conf"
+
/* Retrieves the value for a corresponding key from the challenge string
* returns TRUE if the key could be found, FALSE if it does not exists
*/
@@ -76,6 +86,38 @@ static bool sasl_digest_get_key_value(const char *chlg,
return TRUE;
}
+
+static CURLcode sasl_digest_get_qop_values(const char *options, int *value)
+{
+ char *tmp;
+ char *token;
+ char *tok_buf;
+
+ /* Initialise the output */
+ *value = 0;
+
+ /* Tokenise the list of qop values. Use a temporary clone of the buffer since
+ strtok_r() ruins it. */
+ tmp = strdup(options);
+ if(!tmp)
+ return CURLE_OUT_OF_MEMORY;
+
+ token = strtok_r(tmp, ",", &tok_buf);
+ while(token != NULL) {
+ if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH))
+ *value |= DIGEST_QOP_VALUE_AUTH;
+ else if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH_INT))
+ *value |= DIGEST_QOP_VALUE_AUTH_INT;
+ else if(Curl_raw_equal(token, DIGEST_QOP_VALUE_STRING_AUTH_CONF))
+ *value |= DIGEST_QOP_VALUE_AUTH_CONF;
+
+ token = strtok_r(NULL, ",", &tok_buf);
+ }
+
+ Curl_safefree(tmp);
+
+ return CURLE_OK;
+}
#endif
/*
@@ -279,13 +321,16 @@ CURLcode Curl_sasl_create_cram_md5_message(struct SessionHandle *data,
* rlen [in] - The length of the realm buffer.
* alg [in/out] - The buffer where the algorithm will be stored.
* alen [in] - The length of the algorithm buffer.
+ * qop [in/out] - The buffer where the qop-options will be stored.
+ * qlen [in] - The length of the qop buffer.
*
* Returns CURLE_OK on success.
*/
static CURLcode sasl_decode_digest_md5_message(const char *chlg64,
char *nonce, size_t nlen,
char *realm, size_t rlen,
- char *alg, size_t alen)
+ char *alg, size_t alen,
+ char *qop, size_t qlen)
{
CURLcode result = CURLE_OK;
unsigned char *chlg = NULL;
@@ -321,6 +366,12 @@ static CURLcode sasl_decode_digest_md5_message(const char *chlg64,
return CURLE_BAD_CONTENT_ENCODING;
}
+ /* Retrieve qop-options string from the challenge */
+ if(!sasl_digest_get_key_value((char *)chlg, "qop=\"", qop, qlen, '\"')) {
+ Curl_safefree(chlg);
+ return CURLE_BAD_CONTENT_ENCODING;
+ }
+
Curl_safefree(chlg);
return CURLE_OK;
@@ -367,22 +418,35 @@ CURLcode Curl_sasl_create_digest_md5_message(struct SessionHandle *data,
char nonce[64];
char realm[128];
char algorithm[64];
+ char qop_options[64];
+ int qop_values;
+
char nonceCount[] = "00000001";
char cnonce[] = "12345678"; /* will be changed */
char method[] = "AUTHENTICATE";
- char qop[] = "auth";
+ char qop[] = DIGEST_QOP_VALUE_STRING_AUTH;
char uri[128];
/* Decode the challange message */
result = sasl_decode_digest_md5_message(chlg64, nonce, sizeof(nonce),
realm, sizeof(realm),
- algorithm, sizeof(algorithm));
+ algorithm, sizeof(algorithm),
+ qop_options, sizeof(qop_options));
if(result)
return result;
/* We only support md5 sessions */
if(strcmp(algorithm, "md5-sess") != 0)
- return CURLE_BAD_CONTENT_ENCODING;
+ return CURLE_BAD_CONTENT_ENCODING;
+
+ /* Get the qop-values from the qop-options */
+ result = sasl_digest_get_qop_values(qop_options, &qop_values);
+ if(result)
+ return result;
+
+ /* We only support auth quality-of-protection */
+ if(!(qop_values & DIGEST_QOP_VALUE_AUTH))
+ return CURLE_BAD_CONTENT_ENCODING;
#ifndef DEBUGBUILD
/* Generate 64 bits of random data */