diff -up cyrus-sasl-2.1.26/plugins/ntlm.c.openssl110 cyrus-sasl-2.1.26/plugins/ntlm.c --- cyrus-sasl-2.1.26/plugins/ntlm.c.openssl110 2012-01-28 00:31:36.000000000 +0100 +++ cyrus-sasl-2.1.26/plugins/ntlm.c 2016-11-07 16:15:57.498259304 +0100 @@ -417,6 +417,29 @@ static unsigned char *P24(unsigned char return P24; } +static HMAC_CTX *_plug_HMAC_CTX_new(const sasl_utils_t *utils) +{ + utils->log(NULL, SASL_LOG_DEBUG, "_plug_HMAC_CTX_new()"); + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + return HMAC_CTX_new(); +#else + return utils->malloc(sizeof(HMAC_CTX)); +#endif +} + +static void _plug_HMAC_CTX_free(HMAC_CTX *ctx, const sasl_utils_t *utils) +{ + utils->log(NULL, SASL_LOG_DEBUG, "_plug_HMAC_CTX_free()"); + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + HMAC_CTX_free(ctx); +#else + HMAC_cleanup(ctx); + utils->free(ctx); +#endif +} + static unsigned char *V2(unsigned char *V2, sasl_secret_t *passwd, const char *authid, const char *target, const unsigned char *challenge, @@ -424,7 +447,7 @@ static unsigned char *V2(unsigned char * const sasl_utils_t *utils, char **buf, unsigned *buflen, int *result) { - HMAC_CTX ctx; + HMAC_CTX *ctx = NULL; unsigned char hash[EVP_MAX_MD_SIZE]; char *upper; unsigned int len; @@ -435,6 +458,10 @@ static unsigned char *V2(unsigned char * SETERROR(utils, "cannot allocate NTLMv2 hash"); *result = SASL_NOMEM; } + else if ((ctx = _plug_HMAC_CTX_new(utils)) == NULL) { + SETERROR(utils, "cannot allocate HMAC CTX"); + *result = SASL_NOMEM; + } else { /* NTLMv2hash = HMAC-MD5(NTLMhash, unicode(ucase(authid + domain))) */ P16_nt(hash, passwd, utils, buf, buflen, result); @@ -449,17 +476,18 @@ static unsigned char *V2(unsigned char * HMAC(EVP_md5(), hash, MD4_DIGEST_LENGTH, *buf, 2 * len, hash, &len); /* V2 = HMAC-MD5(NTLMv2hash, challenge + blob) + blob */ - HMAC_Init(&ctx, hash, len, EVP_md5()); - HMAC_Update(&ctx, challenge, NTLM_NONCE_LENGTH); - HMAC_Update(&ctx, blob, bloblen); - HMAC_Final(&ctx, V2, &len); - HMAC_cleanup(&ctx); + HMAC_Init_ex(ctx, hash, len, EVP_md5(), NULL); + HMAC_Update(ctx, challenge, NTLM_NONCE_LENGTH); + HMAC_Update(ctx, blob, bloblen); + HMAC_Final(ctx, V2, &len); /* the blob is concatenated outside of this function */ *result = SASL_OK; } + if (ctx) _plug_HMAC_CTX_free(ctx, utils); + return V2; } diff -up cyrus-sasl-2.1.26/plugins/otp.c.openssl110 cyrus-sasl-2.1.26/plugins/otp.c --- cyrus-sasl-2.1.26/plugins/otp.c.openssl110 2012-10-12 16:05:48.000000000 +0200 +++ cyrus-sasl-2.1.26/plugins/otp.c 2016-11-07 16:13:54.374327601 +0100 @@ -96,6 +96,28 @@ static algorithm_option_t algorithm_opti {NULL, 0, NULL} }; +static EVP_MD_CTX *_plug_EVP_MD_CTX_new(const sasl_utils_t *utils) +{ + utils->log(NULL, SASL_LOG_DEBUG, "_plug_EVP_MD_CTX_new()"); + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + return EVP_MD_CTX_new(); +#else + return utils->malloc(sizeof(EVP_MD_CTX)); +#endif +} + +static void _plug_EVP_MD_CTX_free(EVP_MD_CTX *ctx, const sasl_utils_t *utils) +{ + utils->log(NULL, SASL_LOG_DEBUG, "_plug_EVP_MD_CTX_free()"); + +#if OPENSSL_VERSION_NUMBER >= 0x10100000L + EVP_MD_CTX_free(ctx); +#else + utils->free(ctx); +#endif +} + /* Convert the binary data into ASCII hex */ void bin2hex(unsigned char *bin, int binlen, char *hex) { @@ -116,17 +138,16 @@ void bin2hex(unsigned char *bin, int bin * swabbing bytes if necessary. */ static void otp_hash(const EVP_MD *md, char *in, size_t inlen, - unsigned char *out, int swab) + unsigned char *out, int swab, EVP_MD_CTX *mdctx) { - EVP_MD_CTX mdctx; - char hash[EVP_MAX_MD_SIZE]; + unsigned char hash[EVP_MAX_MD_SIZE]; unsigned int i; int j; unsigned hashlen; - EVP_DigestInit(&mdctx, md); - EVP_DigestUpdate(&mdctx, in, inlen); - EVP_DigestFinal(&mdctx, hash, &hashlen); + EVP_DigestInit(mdctx, md); + EVP_DigestUpdate(mdctx, in, inlen); + EVP_DigestFinal(mdctx, hash, &hashlen); /* Fold the result into 64 bits */ for (i = OTP_HASH_SIZE; i < hashlen; i++) { @@ -149,7 +170,9 @@ static int generate_otp(const sasl_utils char *secret, char *otp) { const EVP_MD *md; - char *key; + EVP_MD_CTX *mdctx = NULL; + char *key = NULL; + int r = SASL_OK; if (!(md = EVP_get_digestbyname(alg->evp_name))) { utils->seterror(utils->conn, 0, @@ -157,23 +180,32 @@ static int generate_otp(const sasl_utils return SASL_FAIL; } + if ((mdctx = _plug_EVP_MD_CTX_new(utils)) == NULL) { + SETERROR(utils, "cannot allocate MD CTX"); + r = SASL_NOMEM; + goto done; + } + if ((key = utils->malloc(strlen(seed) + strlen(secret) + 1)) == NULL) { SETERROR(utils, "cannot allocate OTP key"); - return SASL_NOMEM; + r = SASL_NOMEM; + goto done; } /* initial step */ strcpy(key, seed); strcat(key, secret); - otp_hash(md, key, strlen(key), otp, alg->swab); + otp_hash(md, key, strlen(key), otp, alg->swab, mdctx); /* computation step */ while (seq-- > 0) - otp_hash(md, otp, OTP_HASH_SIZE, otp, alg->swab); - - utils->free(key); + otp_hash(md, otp, OTP_HASH_SIZE, otp, alg->swab, mdctx); + + done: + if (key) utils->free(key); + if (mdctx) _plug_EVP_MD_CTX_free(mdctx, utils); - return SASL_OK; + return r; } static int parse_challenge(const sasl_utils_t *utils, @@ -693,7 +725,8 @@ static int strptrcasecmp(const void *arg /* Convert the 6 words into binary data */ static int word2bin(const sasl_utils_t *utils, - char *words, unsigned char *bin, const EVP_MD *md) + char *words, unsigned char *bin, const EVP_MD *md, + EVP_MD_CTX *mdctx) { int i, j; char *c, *word, buf[OTP_RESPONSE_MAX+1]; @@ -752,13 +785,12 @@ static int word2bin(const sasl_utils_t * /* alternate dictionary */ if (alt_dict) { - EVP_MD_CTX mdctx; - char hash[EVP_MAX_MD_SIZE]; - int hashlen; + unsigned char hash[EVP_MAX_MD_SIZE]; + unsigned hashlen; - EVP_DigestInit(&mdctx, md); - EVP_DigestUpdate(&mdctx, word, strlen(word)); - EVP_DigestFinal(&mdctx, hash, &hashlen); + EVP_DigestInit(mdctx, md); + EVP_DigestUpdate(mdctx, word, strlen(word)); + EVP_DigestFinal(mdctx, hash, &hashlen); /* use lowest 11 bits */ x = ((hash[hashlen-2] & 0x7) << 8) | hash[hashlen-1]; @@ -802,6 +834,7 @@ static int verify_response(server_contex char *response) { const EVP_MD *md; + EVP_MD_CTX *mdctx = NULL; char *c; int do_init = 0; unsigned char cur_otp[OTP_HASH_SIZE], prev_otp[OTP_HASH_SIZE]; @@ -815,6 +848,11 @@ static int verify_response(server_contex return SASL_FAIL; } + if ((mdctx = _plug_EVP_MD_CTX_new(utils)) == NULL) { + SETERROR(utils, "cannot allocate MD CTX"); + return SASL_NOMEM; + } + /* eat leading whitespace */ c = response; while (isspace((int) *c)) c++; @@ -824,7 +862,7 @@ static int verify_response(server_contex r = hex2bin(c+strlen(OTP_HEX_TYPE), cur_otp, OTP_HASH_SIZE); } else if (!strncasecmp(c, OTP_WORD_TYPE, strlen(OTP_WORD_TYPE))) { - r = word2bin(utils, c+strlen(OTP_WORD_TYPE), cur_otp, md); + r = word2bin(utils, c+strlen(OTP_WORD_TYPE), cur_otp, md, mdctx); } else if (!strncasecmp(c, OTP_INIT_HEX_TYPE, strlen(OTP_INIT_HEX_TYPE))) { @@ -834,7 +872,7 @@ static int verify_response(server_contex else if (!strncasecmp(c, OTP_INIT_WORD_TYPE, strlen(OTP_INIT_WORD_TYPE))) { do_init = 1; - r = word2bin(utils, c+strlen(OTP_INIT_WORD_TYPE), cur_otp, md); + r = word2bin(utils, c+strlen(OTP_INIT_WORD_TYPE), cur_otp, md, mdctx); } else { SETERROR(utils, "unknown OTP extended response type"); @@ -843,14 +881,15 @@ static int verify_response(server_contex } else { /* standard response, try word first, and then hex */ - r = word2bin(utils, c, cur_otp, md); + r = word2bin(utils, c, cur_otp, md, mdctx); if (r != SASL_OK) r = hex2bin(c, cur_otp, OTP_HASH_SIZE); } if (r == SASL_OK) { /* do one more hash (previous otp) and compare to stored otp */ - otp_hash(md, cur_otp, OTP_HASH_SIZE, prev_otp, text->alg->swab); + otp_hash(md, (char *) cur_otp, OTP_HASH_SIZE, + prev_otp, text->alg->swab, mdctx); if (!memcmp(prev_otp, text->otp, OTP_HASH_SIZE)) { /* update the secret with this seq/otp */ @@ -879,23 +918,28 @@ static int verify_response(server_contex *new_resp++ = '\0'; } - if (!(new_chal && new_resp)) - return SASL_BADAUTH; + if (!(new_chal && new_resp)) { + r = SASL_BADAUTH; + goto done; + } if ((r = parse_challenge(utils, new_chal, &alg, &seq, seed, 1)) != SASL_OK) { - return r; + goto done; } - if (seq < 1 || !strcasecmp(seed, text->seed)) - return SASL_BADAUTH; + if (seq < 1 || !strcasecmp(seed, text->seed)) { + r = SASL_BADAUTH; + goto done; + } /* find the MDA */ if (!(md = EVP_get_digestbyname(alg->evp_name))) { utils->seterror(utils->conn, 0, "OTP algorithm %s is not available", alg->evp_name); - return SASL_BADAUTH; + r = SASL_BADAUTH; + goto done; } if (!strncasecmp(c, OTP_INIT_HEX_TYPE, strlen(OTP_INIT_HEX_TYPE))) { @@ -903,7 +947,7 @@ static int verify_response(server_contex } else if (!strncasecmp(c, OTP_INIT_WORD_TYPE, strlen(OTP_INIT_WORD_TYPE))) { - r = word2bin(utils, new_resp, new_otp, md); + r = word2bin(utils, new_resp, new_otp, md, mdctx); } if (r == SASL_OK) { @@ -914,7 +958,10 @@ static int verify_response(server_contex memcpy(text->otp, new_otp, OTP_HASH_SIZE); } } - + + done: + if (mdctx) _plug_EVP_MD_CTX_free(mdctx, utils); + return r; } diff -up cyrus-sasl-2.1.26/saslauthd/lak.c.openssl110 cyrus-sasl-2.1.26/saslauthd/lak.c --- cyrus-sasl-2.1.26/saslauthd/lak.c.openssl110 2016-11-07 16:13:54.347327616 +0100 +++ cyrus-sasl-2.1.26/saslauthd/lak.c 2016-11-07 16:18:42.283167898 +0100 @@ -61,6 +61,35 @@ #include #include "lak.h" +#if OPENSSL_VERSION_NUMBER < 0x10100000L +static EVP_MD_CTX *EVP_MD_CTX_new(void) +{ + return EVP_MD_CTX_create(); +} +static void EVP_MD_CTX_free(EVP_MD_CTX *ctx) +{ + if (ctx == NULL) + return; + + EVP_MD_CTX_destroy(ctx); +} + +static EVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void) +{ + EVP_ENCODE_CTX *ctx = OPENSSL_malloc(sizeof(*ctx)); + + if (ctx != NULL) { + memset(ctx, 0, sizeof(*ctx)); + } + return ctx; +} +static void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx) +{ + OPENSSL_free(ctx); + return; +} +#endif + typedef struct lak_auth_method { int method; int (*check) (LAK *lak, const char *user, const char *service, const char *realm, const char *password) ; @@ -1720,20 +1749,28 @@ static int lak_base64_decode( int rc, i, tlen = 0; char *text; - EVP_ENCODE_CTX EVP_ctx; + EVP_ENCODE_CTX *enc_ctx = EVP_ENCODE_CTX_new(); - text = (char *)malloc(((strlen(src)+3)/4 * 3) + 1); if (text == NULL) return LAK_NOMEM; - EVP_DecodeInit(&EVP_ctx); - rc = EVP_DecodeUpdate(&EVP_ctx, text, &i, (char *)src, strlen(src)); + text = (char *)malloc(((strlen(src)+3)/4 * 3) + 1); + if (text == NULL) { + EVP_ENCODE_CTX_free(enc_ctx); + return LAK_NOMEM; + } + + EVP_DecodeInit(enc_ctx); + rc = EVP_DecodeUpdate(enc_ctx, (unsigned char *) text, &i, (const unsigned char *)src, strlen(src)); if (rc < 0) { + EVP_ENCODE_CTX_free(enc_ctx); free(text); return LAK_FAIL; } tlen += i; - EVP_DecodeFinal(&EVP_ctx, text, &i); + EVP_DecodeFinal(enc_ctx, (unsigned char *) text, &i); + + EVP_ENCODE_CTX_free(enc_ctx); *ret = text; if (rlen != NULL) @@ -1749,7 +1786,7 @@ static int lak_check_hashed( { int rc, clen; LAK_HASH_ROCK *hrock = (LAK_HASH_ROCK *) rock; - EVP_MD_CTX mdctx; + EVP_MD_CTX *mdctx; const EVP_MD *md; unsigned char digest[EVP_MAX_MD_SIZE]; char *cred; @@ -1758,17 +1795,24 @@ static int lak_check_hashed( if (!md) return LAK_FAIL; + mdctx = EVP_MD_CTX_new(); + if (!mdctx) + return LAK_NOMEM; + rc = lak_base64_decode(hash, &cred, &clen); - if (rc != LAK_OK) + if (rc != LAK_OK) { + EVP_MD_CTX_free(mdctx); return rc; + } - EVP_DigestInit(&mdctx, md); - EVP_DigestUpdate(&mdctx, passwd, strlen(passwd)); + EVP_DigestInit(mdctx, md); + EVP_DigestUpdate(mdctx, passwd, strlen(passwd)); if (hrock->salted) { - EVP_DigestUpdate(&mdctx, &cred[EVP_MD_size(md)], + EVP_DigestUpdate(mdctx, &cred[EVP_MD_size(md)], clen - EVP_MD_size(md)); } - EVP_DigestFinal(&mdctx, digest, NULL); + EVP_DigestFinal(mdctx, digest, NULL); + EVP_MD_CTX_free(mdctx); rc = memcmp((char *)cred, (char *)digest, EVP_MD_size(md)); free(cred);