cram.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. /***************************************************************************
  2. * _ _ ____ _
  3. * Project ___| | | | _ \| |
  4. * / __| | | | |_) | |
  5. * | (__| |_| | _ <| |___
  6. * \___|\___/|_| \_\_____|
  7. *
  8. * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@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.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. #include "curl_setup.h"
  25. #if !defined(CURL_DISABLE_CRYPTO_AUTH)
  26. #include <curl/curl.h>
  27. #include "urldata.h"
  28. #include "vauth/vauth.h"
  29. #include "curl_base64.h"
  30. #include "curl_hmac.h"
  31. #include "curl_md5.h"
  32. #include "warnless.h"
  33. #include "curl_printf.h"
  34. /* The last #include files should be: */
  35. #include "curl_memory.h"
  36. #include "memdebug.h"
  37. /*
  38. * Curl_auth_decode_cram_md5_message()
  39. *
  40. * This is used to decode an already encoded CRAM-MD5 challenge message.
  41. *
  42. * Parameters:
  43. *
  44. * chlg64 [in] - The base64 encoded challenge message.
  45. * outptr [in/out] - The address where a pointer to newly allocated memory
  46. * holding the result will be stored upon completion.
  47. * outlen [out] - The length of the output message.
  48. *
  49. * Returns CURLE_OK on success.
  50. */
  51. CURLcode Curl_auth_decode_cram_md5_message(const char *chlg64, char **outptr,
  52. size_t *outlen)
  53. {
  54. CURLcode result = CURLE_OK;
  55. size_t chlg64len = strlen(chlg64);
  56. *outptr = NULL;
  57. *outlen = 0;
  58. /* Decode the challenge if necessary */
  59. if(chlg64len && *chlg64 != '=')
  60. result = Curl_base64_decode(chlg64, (unsigned char **) outptr, outlen);
  61. return result;
  62. }
  63. /*
  64. * Curl_auth_create_cram_md5_message()
  65. *
  66. * This is used to generate an already encoded CRAM-MD5 response message ready
  67. * for sending to the recipient.
  68. *
  69. * Parameters:
  70. *
  71. * data [in] - The session handle.
  72. * chlg [in] - The challenge.
  73. * userp [in] - The user name.
  74. * passwdp [in] - The user's password.
  75. * outptr [in/out] - The address where a pointer to newly allocated memory
  76. * holding the result will be stored upon completion.
  77. * outlen [out] - The length of the output message.
  78. *
  79. * Returns CURLE_OK on success.
  80. */
  81. CURLcode Curl_auth_create_cram_md5_message(struct Curl_easy *data,
  82. const char *chlg,
  83. const char *userp,
  84. const char *passwdp,
  85. char **outptr, size_t *outlen)
  86. {
  87. CURLcode result = CURLE_OK;
  88. size_t chlglen = 0;
  89. struct HMAC_context *ctxt;
  90. unsigned char digest[MD5_DIGEST_LEN];
  91. char *response;
  92. if(chlg)
  93. chlglen = strlen(chlg);
  94. /* Compute the digest using the password as the key */
  95. ctxt = Curl_HMAC_init(Curl_HMAC_MD5,
  96. (const unsigned char *) passwdp,
  97. curlx_uztoui(strlen(passwdp)));
  98. if(!ctxt)
  99. return CURLE_OUT_OF_MEMORY;
  100. /* Update the digest with the given challenge */
  101. if(chlglen > 0)
  102. Curl_HMAC_update(ctxt, (const unsigned char *) chlg,
  103. curlx_uztoui(chlglen));
  104. /* Finalise the digest */
  105. Curl_HMAC_final(ctxt, digest);
  106. /* Generate the response */
  107. response = aprintf(
  108. "%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
  109. userp, digest[0], digest[1], digest[2], digest[3], digest[4],
  110. digest[5], digest[6], digest[7], digest[8], digest[9], digest[10],
  111. digest[11], digest[12], digest[13], digest[14], digest[15]);
  112. if(!response)
  113. return CURLE_OUT_OF_MEMORY;
  114. /* Base64 encode the response */
  115. result = Curl_base64_encode(data, response, 0, outptr, outlen);
  116. free(response);
  117. return result;
  118. }
  119. #endif /* !CURL_DISABLE_CRYPTO_AUTH */