You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
354 lines
10 KiB
354 lines
10 KiB
diff --git a/plugins/ntlm.c b/plugins/ntlm.c
|
|
index 79ea47c..554a00d 100644
|
|
--- a/plugins/ntlm.c
|
|
+++ b/plugins/ntlm.c
|
|
@@ -417,6 +417,29 @@ static unsigned char *P24(unsigned char *P24, unsigned char *P21,
|
|
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(EVP_MD_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 *V2, sasl_secret_t *passwd,
|
|
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 *V2, sasl_secret_t *passwd,
|
|
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 *V2, sasl_secret_t *passwd,
|
|
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 --git a/plugins/otp.c b/plugins/otp.c
|
|
index dd73065..d1e9bf4 100644
|
|
--- a/plugins/otp.c
|
|
+++ b/plugins/otp.c
|
|
@@ -96,6 +96,28 @@ static algorithm_option_t algorithm_options[] = {
|
|
{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 binlen, char *hex)
|
|
* 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 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_t *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_t *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);
|
|
+ otp_hash(md, otp, OTP_HASH_SIZE, otp, alg->swab, mdctx);
|
|
|
|
- utils->free(key);
|
|
+ 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 *arg1, const void *arg2)
|
|
|
|
/* 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 *utils,
|
|
|
|
/* alternate dictionary */
|
|
if (alt_dict) {
|
|
- EVP_MD_CTX mdctx;
|
|
char hash[EVP_MAX_MD_SIZE];
|
|
int 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_context_t *text, const sasl_utils_t *utils,
|
|
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_context_t *text, const sasl_utils_t *utils,
|
|
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_context_t *text, const sasl_utils_t *utils,
|
|
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_context_t *text, const sasl_utils_t *utils,
|
|
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,14 @@ static int verify_response(server_context_t *text, const sasl_utils_t *utils,
|
|
}
|
|
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, 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 +917,28 @@ static int verify_response(server_context_t *text, const sasl_utils_t *utils,
|
|
*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 +946,7 @@ static int verify_response(server_context_t *text, const sasl_utils_t *utils,
|
|
}
|
|
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 +957,10 @@ static int verify_response(server_context_t *text, const sasl_utils_t *utils,
|
|
memcpy(text->otp, new_otp, OTP_HASH_SIZE);
|
|
}
|
|
}
|
|
-
|
|
+
|
|
+ done:
|
|
+ if (mdctx) _plug_EVP_MD_CTX_free(mdctx, utils);
|
|
+
|
|
return r;
|
|
}
|
|
|
|
@@ -1443,8 +1489,10 @@ int otp_server_plug_init(const sasl_utils_t *utils,
|
|
*pluglist = otp_server_plugins;
|
|
*plugcount = 1;
|
|
|
|
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
|
/* Add all digests */
|
|
OpenSSL_add_all_digests();
|
|
+#endif
|
|
|
|
return SASL_OK;
|
|
}
|
|
@@ -1844,8 +1892,10 @@ int otp_client_plug_init(sasl_utils_t *utils,
|
|
*pluglist = otp_client_plugins;
|
|
*plugcount = 1;
|
|
|
|
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
|
/* Add all digests */
|
|
OpenSSL_add_all_digests();
|
|
+#endif
|
|
|
|
return SASL_OK;
|
|
}
|
|
--- a/saslauthd/lak.c
|
|
+++ b/saslauthd/lak.c
|
|
@@ -729,7 +729,7 @@ int lak_init(
|
|
return rc;
|
|
}
|
|
|
|
-#ifdef HAVE_OPENSSL
|
|
+#if defined(HAVE_OPENSSL) && OPENSSL_VERSION_NUMBER < 0x10100000L
|
|
OpenSSL_add_all_digests();
|
|
#endif
|
|
|