@@ -82,9 +82,6 @@
#include " url.h"
#include " rawstr.h"
#include " strtoofft.h"
#include " curl_base64.h"
#include " curl_rand.h"
#include " curl_md5.h"
#include " curl_gethostname.h"
#include " curl_sasl.h"
#include " warnless.h"
@@ -279,33 +276,6 @@ static int smtp_endofresp(struct pingpong *pp, int *resp)
return result;
}
#ifndef CURL_DISABLE_CRYPTO_AUTH
/* 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
*/
static bool smtp_digest_get_key_value (const unsigned char *chlg,
const char *key,
char *value,
size_t max_val_len,
char end_char)
{
char *find_pos;
size_t i;
find_pos = strstr ((const char *) chlg, key);
if (!find_pos)
return FALSE ;
find_pos += strlen (key);
for (i = 0 ; *find_pos && *find_pos != end_char && i < max_val_len - 1 ; ++i)
value[i] = *find_pos++;
value[i] = ' \0 ' ;
return TRUE ;
}
#endif
/* This is the ONLY way to change SMTP state! */
static void state (struct connectdata *conn, smtpstate newstate)
{
@@ -764,31 +734,11 @@ static CURLcode smtp_state_authdigest_resp(struct connectdata *conn,
int smtpcode,
smtpstate instate)
{
static const char table16[] = " 0123456789abcdef" ;
CURLcode result = CURLE_OK;
struct SessionHandle *data = conn->data ;
char *chlg64 = data->state .buffer ;
unsigned char *chlg;
size_t chlglen;
size_t len = 0 ;
size_t i;
char *rplyb64 = NULL ;
MD5_context *ctxt;
unsigned char digest[MD5_DIGEST_LEN];
char HA1_hex[2 * MD5_DIGEST_LEN + 1 ];
char HA2_hex[2 * MD5_DIGEST_LEN + 1 ];
char resp_hash_hex[2 * MD5_DIGEST_LEN + 1 ];
char nonce[64 ];
char realm[128 ];
char alg[64 ];
char nonceCount[] = " 00000001" ;
char cnonce[] = " 12345678" ; /* will be changed */
char method[] = " AUTHENTICATE" ;
char qop[] = " auth" ;
char uri[128 ] = " smtp/" ;
char response[512 ];
(void )instate; /* no use for this yet */
@@ -801,138 +751,8 @@ static CURLcode smtp_state_authdigest_resp(struct connectdata *conn,
for (chlg64 += 4 ; *chlg64 == ' ' || *chlg64 == ' \t ' ; chlg64++)
;
chlg = (unsigned char *) NULL ;
chlglen = 0 ;
result = Curl_base64_decode (chlg64, &chlg, &chlglen);
if (result)
return result;
/* Retrieve nonce string from the challenge */
if (!smtp_digest_get_key_value (chlg, " nonce=\" " , nonce,
sizeof (nonce), ' \" ' )) {
Curl_safefree (chlg);
return CURLE_LOGIN_DENIED;
}
/* Retrieve realm string from the challenge */
if (!smtp_digest_get_key_value (chlg, " realm=\" " , realm,
sizeof (realm), ' \" ' )) {
/* Challenge does not have a realm, set empty string [RFC2831] page 6 */
strcpy (realm, " " );
}
/* Retrieve algorithm string from the challenge */
if (!smtp_digest_get_key_value (chlg, " algorithm=" , alg, sizeof (alg), ' ,' )) {
Curl_safefree (chlg);
return CURLE_LOGIN_DENIED;
}
Curl_safefree (chlg);
/* We do not support other algorithms */
if (strcmp (alg, " md5-sess" ) != 0 )
return CURLE_LOGIN_DENIED;
/* Generate 64 bits of random data */
for (i = 0 ; i < 8 ; i++)
cnonce[i] = table16[Curl_rand ()%16 ];
/* So far so good, now calculate A1 and H(A1) according to RFC 2831 */
ctxt = Curl_MD5_init (Curl_DIGEST_MD5);
if (!ctxt)
return CURLE_OUT_OF_MEMORY;
Curl_MD5_update (ctxt, (const unsigned char *) conn->user ,
curlx_uztoui (strlen (conn->user )));
Curl_MD5_update (ctxt, (const unsigned char *) " :" , 1 );
Curl_MD5_update (ctxt, (const unsigned char *) realm,
curlx_uztoui (strlen (realm)));
Curl_MD5_update (ctxt, (const unsigned char *) " :" , 1 );
Curl_MD5_update (ctxt, (const unsigned char *) conn->passwd ,
curlx_uztoui (strlen (conn->passwd )));
Curl_MD5_final (ctxt, digest);
ctxt = Curl_MD5_init (Curl_DIGEST_MD5);
if (!ctxt)
return CURLE_OUT_OF_MEMORY;
Curl_MD5_update (ctxt, (const unsigned char *) digest, MD5_DIGEST_LEN);
Curl_MD5_update (ctxt, (const unsigned char *) " :" , 1 );
Curl_MD5_update (ctxt, (const unsigned char *) nonce,
curlx_uztoui (strlen (nonce)));
Curl_MD5_update (ctxt, (const unsigned char *) " :" , 1 );
Curl_MD5_update (ctxt, (const unsigned char *) cnonce,
curlx_uztoui (strlen (cnonce)));
Curl_MD5_final (ctxt, digest);
/* Convert calculated 16 octet hex into 32 bytes string */
for (i = 0 ; i < MD5_DIGEST_LEN; i++)
snprintf (&HA1_hex[2 * i], 3 , " %02x " , digest[i]);
/* Orepare URL string, append realm to the protocol */
strcat (uri, realm);
/* Calculate H(A2) */
ctxt = Curl_MD5_init (Curl_DIGEST_MD5);
if (!ctxt)
return CURLE_OUT_OF_MEMORY;
Curl_MD5_update (ctxt, (const unsigned char *) method,
curlx_uztoui (strlen (method)));
Curl_MD5_update (ctxt, (const unsigned char *) " :" , 1 );
Curl_MD5_update (ctxt, (const unsigned char *) uri,
curlx_uztoui (strlen (uri)));
Curl_MD5_final (ctxt, digest);
for (i = 0 ; i < MD5_DIGEST_LEN; i++)
snprintf (&HA2_hex[2 * i], 3 , " %02x " , digest[i]);
/* Now calculate the response hash */
ctxt = Curl_MD5_init (Curl_DIGEST_MD5);
if (!ctxt)
return CURLE_OUT_OF_MEMORY;
Curl_MD5_update (ctxt, (const unsigned char *) HA1_hex, 2 * MD5_DIGEST_LEN);
Curl_MD5_update (ctxt, (const unsigned char *) " :" , 1 );
Curl_MD5_update (ctxt, (const unsigned char *) nonce,
curlx_uztoui (strlen (nonce)));
Curl_MD5_update (ctxt, (const unsigned char *) " :" , 1 );
Curl_MD5_update (ctxt, (const unsigned char *) nonceCount,
curlx_uztoui (strlen (nonceCount)));
Curl_MD5_update (ctxt, (const unsigned char *) " :" , 1 );
Curl_MD5_update (ctxt, (const unsigned char *) cnonce,
curlx_uztoui (strlen (cnonce)));
Curl_MD5_update (ctxt, (const unsigned char *) " :" , 1 );
Curl_MD5_update (ctxt, (const unsigned char *) qop,
curlx_uztoui (strlen (qop)));
Curl_MD5_update (ctxt, (const unsigned char *) " :" , 1 );
Curl_MD5_update (ctxt, (const unsigned char *) HA2_hex, 2 * MD5_DIGEST_LEN);
Curl_MD5_final (ctxt, digest);
for (i = 0 ; i < MD5_DIGEST_LEN; i++)
snprintf (&resp_hash_hex[2 * i], 3 , " %02x " , digest[i]);
strcpy (response, " username=\" " );
strcat (response, conn->user );
strcat (response, " \" ,realm=\" " );
strcat (response, realm);
strcat (response, " \" ,nonce=\" " );
strcat (response, nonce);
strcat (response, " \" ,cnonce=\" " );
strcat (response, cnonce);
strcat (response, " \" ,nc=" );
strcat (response, nonceCount);
strcat (response, " ,digest-uri=\" " );
strcat (response, uri);
strcat (response, " \" ,response=" );
strcat (response, resp_hash_hex);
/* Encode it to base64 and send it */
result = Curl_base64_encode (data, response, 0 , &rplyb64, &len);
result = Curl_sasl_create_digest_md5_message (data, chlg64, conn->user ,
conn->passwd , &rplyb64, &len);
if (!result) {
if (rplyb64) {