1 /*************************************************************************** 2 * _ _ ____ _ 3 * Project ___| | | | _ \| | 4 * / __| | | | |_) | | 5 * | (__| |_| | _ <| |___ 6 * \___|\___/|_| \_\_____| 7 * 8 * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel (at) haxx.se>, et al. 9 * 10 * This software is licensed as described in the file COPYING, which 11 * you should have received as part of this distribution. The terms 12 * are also available at https://curl.haxx.se/docs/copyright.html. 13 * 14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell 15 * copies of the Software, and permit persons to whom the Software is 16 * furnished to do so, under the terms of the COPYING file. 17 * 18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 19 * KIND, either express or implied. 20 * 21 * RFC2195 CRAM-MD5 authentication 22 * 23 ***************************************************************************/ 24 25 #include "curl_setup.h" 26 27 #if !defined(CURL_DISABLE_CRYPTO_AUTH) 28 29 #include <curl/curl.h> 30 #include "urldata.h" 31 32 #include "vauth/vauth.h" 33 #include "curl_base64.h" 34 #include "curl_hmac.h" 35 #include "curl_md5.h" 36 #include "warnless.h" 37 #include "curl_printf.h" 38 39 /* The last #include files should be: */ 40 #include "curl_memory.h" 41 #include "memdebug.h" 42 43 /* 44 * Curl_auth_decode_cram_md5_message() 45 * 46 * This is used to decode an already encoded CRAM-MD5 challenge message. 47 * 48 * Parameters: 49 * 50 * chlg64 [in] - The base64 encoded challenge message. 51 * outptr [in/out] - The address where a pointer to newly allocated memory 52 * holding the result will be stored upon completion. 53 * outlen [out] - The length of the output message. 54 * 55 * Returns CURLE_OK on success. 56 */ 57 CURLcode Curl_auth_decode_cram_md5_message(const char *chlg64, char **outptr, 58 size_t *outlen) 59 { 60 CURLcode result = CURLE_OK; 61 size_t chlg64len = strlen(chlg64); 62 63 *outptr = NULL; 64 *outlen = 0; 65 66 /* Decode the challenge if necessary */ 67 if(chlg64len && *chlg64 != '=') 68 result = Curl_base64_decode(chlg64, (unsigned char **) outptr, outlen); 69 70 return result; 71 } 72 73 /* 74 * Curl_auth_create_cram_md5_message() 75 * 76 * This is used to generate an already encoded CRAM-MD5 response message ready 77 * for sending to the recipient. 78 * 79 * Parameters: 80 * 81 * data [in] - The session handle. 82 * chlg [in] - The challenge. 83 * userp [in] - The user name. 84 * passdwp [in] - The user's password. 85 * outptr [in/out] - The address where a pointer to newly allocated memory 86 * holding the result will be stored upon completion. 87 * outlen [out] - The length of the output message. 88 * 89 * Returns CURLE_OK on success. 90 */ 91 CURLcode Curl_auth_create_cram_md5_message(struct Curl_easy *data, 92 const char *chlg, 93 const char *userp, 94 const char *passwdp, 95 char **outptr, size_t *outlen) 96 { 97 CURLcode result = CURLE_OK; 98 size_t chlglen = 0; 99 HMAC_context *ctxt; 100 unsigned char digest[MD5_DIGEST_LEN]; 101 char *response; 102 103 if(chlg) 104 chlglen = strlen(chlg); 105 106 /* Compute the digest using the password as the key */ 107 ctxt = Curl_HMAC_init(Curl_HMAC_MD5, 108 (const unsigned char *) passwdp, 109 curlx_uztoui(strlen(passwdp))); 110 if(!ctxt) 111 return CURLE_OUT_OF_MEMORY; 112 113 /* Update the digest with the given challenge */ 114 if(chlglen > 0) 115 Curl_HMAC_update(ctxt, (const unsigned char *) chlg, 116 curlx_uztoui(chlglen)); 117 118 /* Finalise the digest */ 119 Curl_HMAC_final(ctxt, digest); 120 121 /* Generate the response */ 122 response = aprintf( 123 "%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", 124 userp, digest[0], digest[1], digest[2], digest[3], digest[4], 125 digest[5], digest[6], digest[7], digest[8], digest[9], digest[10], 126 digest[11], digest[12], digest[13], digest[14], digest[15]); 127 if(!response) 128 return CURLE_OUT_OF_MEMORY; 129 130 /* Base64 encode the response */ 131 result = Curl_base64_encode(data, response, 0, outptr, outlen); 132 133 free(response); 134 135 return result; 136 } 137 138 #endif /* !CURL_DISABLE_CRYPTO_AUTH */ 139