summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--server/responder/pam/pam_LOCAL_domain.c18
-rw-r--r--server/responder/pam/pamsrv_cache.c16
-rw-r--r--server/util/nss_sha512crypt.c633
-rw-r--r--server/util/nss_sha512crypt.h5
4 files changed, 334 insertions, 338 deletions
diff --git a/server/responder/pam/pam_LOCAL_domain.c b/server/responder/pam/pam_LOCAL_domain.c
index dc394ab8..1287c7d9 100644
--- a/server/responder/pam/pam_LOCAL_domain.c
+++ b/server/responder/pam/pam_LOCAL_domain.c
@@ -230,14 +230,14 @@ static void do_pam_chauthtok(struct LOCAL_request *lreq)
lreq->error, ret, done);
memset(pd->newauthtok, 0, pd->newauthtok_size);
- salt = gen_salt();
- NULL_CHECK_OR_JUMP(salt, ("Salt generation failed.\n"),
- lreq->error, EFAULT, done);
+ ret = s3crypt_gen_salt(lreq, &salt);
+ NEQ_CHECK_OR_JUMP(ret, EOK, ("Salt generation failed.\n"),
+ lreq->error, ret, done);
DEBUG(4, ("Using salt [%s]\n", salt));
- new_hash = nss_sha512_crypt(newauthtok, salt);
- NULL_CHECK_OR_JUMP(new_hash, ("Hash generation failed.\n"),
- lreq->error, EFAULT, done);
+ ret = s3crypt_sha512(lreq, newauthtok, salt, &new_hash);
+ NEQ_CHECK_OR_JUMP(ret, EOK, ("Hash generation failed.\n"),
+ lreq->error, ret, done);
DEBUG(4, ("New hash [%s]\n", new_hash));
memset(newauthtok, 0, pd->newauthtok_size);
@@ -323,10 +323,10 @@ static void local_handler_callback(void *pvt, int ldb_status,
lreq->error, ret, done);
DEBUG(4, ("user: [%s], password hash: [%s]\n", username, password));
- new_hash = nss_sha512_crypt(authtok, password);
+ ret = s3crypt_sha512(lreq, authtok, password, &new_hash);
memset(authtok, 0, pd->authtok_size);
- NULL_CHECK_OR_JUMP(new_hash, ("nss_sha512_crypt failed.\n"),
- lreq->error, EFAULT, done);
+ NEQ_CHECK_OR_JUMP(ret, EOK, ("nss_sha512_crypt failed.\n"),
+ lreq->error, ret, done);
DEBUG(4, ("user: [%s], new hash: [%s]\n", username, new_hash));
diff --git a/server/responder/pam/pamsrv_cache.c b/server/responder/pam/pamsrv_cache.c
index f98be79b..ed18f6a1 100644
--- a/server/responder/pam/pamsrv_cache.c
+++ b/server/responder/pam/pamsrv_cache.c
@@ -122,17 +122,15 @@ int pam_cache_credentials(struct pam_auth_req *preq)
goto done;
}
- salt = gen_salt();
- if (!salt) {
+ ret = s3crypt_gen_salt(preq, &salt);
+ if (ret) {
DEBUG(4, ("Failed to generate random salt.\n"));
- ret = EFAULT;
goto done;
}
- comphash = nss_sha512_crypt(password, salt);
- if (!comphash) {
+ ret = s3crypt_sha512(preq, password, salt, &comphash);
+ if (ret) {
DEBUG(4, ("Failed to create password hash.\n"));
- ret = EFAULT;
goto done;
}
@@ -181,7 +179,7 @@ static void pam_cache_auth_callback(void *pvt, int ldb_status,
struct pam_auth_req *preq;
struct pam_data *pd;
const char *userhash;
- const char *comphash;
+ char *comphash;
char *password = NULL;
int i, ret;
@@ -226,8 +224,8 @@ static void pam_cache_auth_callback(void *pvt, int ldb_status,
goto done;
}
- comphash = nss_sha512_crypt(password, userhash);
- if (!comphash) {
+ ret = s3crypt_sha512(preq, password, userhash, &comphash);
+ if (ret) {
DEBUG(4, ("Failed to create password hash.\n"));
ret = PAM_SYSTEM_ERR;
goto done;
diff --git a/server/util/nss_sha512crypt.c b/server/util/nss_sha512crypt.c
index cb60610b..f02dbef3 100644
--- a/server/util/nss_sha512crypt.c
+++ b/server/util/nss_sha512crypt.c
@@ -20,400 +20,397 @@
#include <sys/param.h>
#include <sys/types.h>
+#include "util/util.h"
+
#include <prinit.h>
#include <nss.h>
#include <sechash.h>
#include <pk11func.h>
-
static int nspr_nss_init_done = 0;
-/* according to
- * http://www.mozilla.org/projects/security/pki/nss/ref/ssl/sslfnc.html#1234224
- * PR_Init must be called, but at least for the HASH_* calls it seems to work
- * quite well without. */
static int nspr_nss_init(void)
{
- int ret;
- PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
- ret = NSS_NoDB_Init(NULL);
- if (ret != SECSuccess) {
- return ret;
- }
- nspr_nss_init_done = 1;
- return 0;
+ int ret;
+ PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
+ ret = NSS_NoDB_Init(NULL);
+ if (ret != SECSuccess) {
+ return ret;
+ }
+ nspr_nss_init_done = 1;
+ return 0;
}
/* added for completness, so far not used */
static int nspr_nss_cleanup(void)
{
- int ret;
- ret=NSS_Shutdown();
- if (ret != SECSuccess ) {
- return ret;
- }
- PR_Cleanup();
- nspr_nss_init_done = 0;
- return 0;
+ int ret;
+ ret = NSS_Shutdown();
+ if (ret != SECSuccess) {
+ return ret;
+ }
+ PR_Cleanup();
+ nspr_nss_init_done = 0;
+ return 0;
}
-/* Define our magic string to mark salt for SHA512 "encryption"
- replacement. */
-static const char sha512_salt_prefix[] = "$6$";
+/* Define our magic string to mark salt for SHA512 "encryption" replacement. */
+const char sha512_salt_prefix[] = "$6$";
+#define SALT_PREF_SIZE (sizeof(sha512_salt_prefix) - 1)
-/* Prefix for optional rounds specification. */
-static const char sha512_rounds_prefix[] = "rounds=";
+/* Prefix for optional rounds specification. */
+const char sha512_rounds_prefix[] = "rounds=";
+#define ROUNDS_SIZE (sizeof(sha512_rounds_prefix) - 1)
-/* Maximum salt string length. */
#define SALT_LEN_MAX 16
-/* Default number of rounds if not explicitly specified. */
#define ROUNDS_DEFAULT 5000
-/* Minimum number of rounds. */
#define ROUNDS_MIN 1000
-/* Maximum number of rounds. */
#define ROUNDS_MAX 999999999
/* Table with characters for base64 transformation. */
-static const char b64t[64] =
-"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+const char b64t[64] =
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-
-static char *
-sha512_crypt_r (const char *key, const char *salt, char *buffer, int buflen)
+/* base64 conversion function */
+static inline void b64_from_24bit(char **dest, size_t *len, size_t n,
+ uint8_t b2, uint8_t b1, uint8_t b0)
{
- unsigned char alt_result[64]
- __attribute__ ((__aligned__ (__alignof__ (uint64_t))));
- unsigned char temp_result[64]
- __attribute__ ((__aligned__ (__alignof__ (uint64_t))));
- HASHContext *ctx;
- HASHContext *alt_ctx;
- size_t salt_len;
- size_t key_len;
- size_t cnt;
- char *cp;
- char *copied_key = NULL;
- char *copied_salt = NULL;
- char *p_bytes;
- char *s_bytes;
- /* Default number of rounds. */
- size_t rounds = ROUNDS_DEFAULT;
- bool rounds_custom = false;
-
- int ret;
- unsigned int part;
-
- /* Find beginning of salt string. The prefix should normally always
- be present. Just in case it is not. */
- if (strncmp (sha512_salt_prefix, salt, sizeof (sha512_salt_prefix) - 1) == 0)
- /* Skip salt prefix. */
- salt += sizeof (sha512_salt_prefix) - 1;
-
- if (strncmp (salt, sha512_rounds_prefix, sizeof (sha512_rounds_prefix) - 1)
- == 0)
- {
- const char *num = salt + sizeof (sha512_rounds_prefix) - 1;
- char *endp;
- unsigned long int srounds = strtoul (num, &endp, 10);
- if (*endp == '$')
- {
- salt = endp + 1;
- rounds = MAX (ROUNDS_MIN, MIN (srounds, ROUNDS_MAX));
- rounds_custom = true;
- }
+ uint32_t w;
+ size_t i;
+
+ if (*len < n) n = *len;
+
+ w = (b2 << 16) | (b1 << 8) | b0;
+ for (i = 0; i < n; i++) {
+ (*dest)[i] = b64t[w & 0x3f];
+ w >>= 6;
}
- salt_len = MIN (strcspn (salt, "$"), SALT_LEN_MAX);
- key_len = strlen (key);
+ *len -= i;
+ *dest += i;
+}
+
+#define ALIGN64 __alignof__(uint64_t)
- if ((key - (char *) 0) % __alignof__ (uint64_t) != 0)
- {
- char *tmp = (char *) alloca (key_len + __alignof__ (uint64_t));
- key = copied_key =
- memcpy (tmp + __alignof__ (uint64_t)
- - (tmp - (char *) 0) % __alignof__ (uint64_t),
- key, key_len);
+static int sha512_crypt_r(const char *key,
+ const char *salt,
+ char *buffer, size_t buflen)
+{
+ unsigned char temp_result[64] __attribute__((__aligned__(ALIGN64)));
+ unsigned char alt_result[64] __attribute__((__aligned__(ALIGN64)));
+ size_t rounds = ROUNDS_DEFAULT;
+ bool rounds_custom = false;
+ HASHContext *alt_ctx = NULL;
+ HASHContext *ctx = NULL;
+ size_t salt_len;
+ size_t key_len;
+ size_t cnt;
+ char *copied_salt = NULL;
+ char *copied_key = NULL;
+ char *p_bytes = NULL;
+ char *s_bytes = NULL;
+ int p1, p2, p3, pt, n;
+ unsigned int part;
+ char *cp, *tmp;
+ int ret;
+
+ /* Find beginning of salt string. The prefix should normally always be
+ * present. Just in case it is not. */
+ if (strncmp(salt, sha512_salt_prefix, SALT_PREF_SIZE) == 0) {
+ /* Skip salt prefix. */
+ salt += SALT_PREF_SIZE;
}
- if ((salt - (char *) 0) % __alignof__ (uint64_t) != 0)
- {
- char *tmp = (char *) alloca (salt_len + __alignof__ (uint64_t));
- salt = copied_salt =
- memcpy (tmp + __alignof__ (uint64_t)
- - (tmp - (char *) 0) % __alignof__ (uint64_t),
- salt, salt_len);
+ if (strncmp(salt, sha512_rounds_prefix, ROUNDS_SIZE) == 0) {
+ unsigned long int srounds;
+ const char *num;
+ char *endp;
+
+ num = salt + ROUNDS_SIZE;
+ srounds = strtoul(num, &endp, 10);
+ if (*endp == '$') {
+ salt = endp + 1;
+ if (srounds < ROUNDS_MIN) srounds = ROUNDS_MIN;
+ if (srounds > ROUNDS_MAX) srounds = ROUNDS_MAX;
+ rounds = srounds;
+ rounds_custom = true;
+ }
}
+ salt_len = MIN(strcspn(salt, "$"), SALT_LEN_MAX);
+ key_len = strlen(key);
- if (!nspr_nss_init_done) {
- ret = nspr_nss_init();
- if (ret != SECSuccess) return NULL;
- }
+ if ((((uint64_t)key) % ALIGN64) != 0) {
+ tmp = (char *)alloca(key_len + ALIGN64);
+ key = copied_key = memcpy(tmp + ALIGN64 - (((uint64_t)tmp) % ALIGN64), key, key_len);
+ }
- ctx = HASH_Create(HASH_AlgSHA512);
- if ( ctx == NULL ) {
- return NULL;
- }
+ if (((uint64_t)salt) % ALIGN64 != 0) {
+ tmp = (char *)alloca(salt_len + ALIGN64);
+ salt = copied_salt = memcpy(tmp + ALIGN64 - ((uint64_t)tmp) % ALIGN64, salt, salt_len);
+ }
- alt_ctx = HASH_Create(HASH_AlgSHA512);
- if ( alt_ctx == NULL ) {
- return NULL;
- }
+ if (!nspr_nss_init_done) {
+ ret = nspr_nss_init();
+ if (ret != SECSuccess) {
+ ret = EIO;
+ goto done;
+ }
+ }
+ ctx = HASH_Create(HASH_AlgSHA512);
+ if (!ctx) {
+ ret = EIO;
+ goto done;
+ }
- /* Prepare for the real work. */
- HASH_Begin(ctx);
+ alt_ctx = HASH_Create(HASH_AlgSHA512);
+ if (!alt_ctx) {
+ ret = EIO;
+ goto done;
+ }
- /* Add the key string. */
- HASH_Update(ctx, (const unsigned char *)key, key_len);
+ /* Prepare for the real work. */
+ HASH_Begin(ctx);
- /* The last part is the salt string. This must be at most 16
- characters and it ends at the first `$' character (for
- compatibility with existing implementations). */
- HASH_Update(ctx, (const unsigned char *)salt, salt_len);
+ /* Add the key string. */
+ HASH_Update(ctx, (const unsigned char *)key, key_len);
+ /* The last part is the salt string. This must be at most 16
+ * characters and it ends at the first `$' character (for
+ * compatibility with existing implementations). */
+ HASH_Update(ctx, (const unsigned char *)salt, salt_len);
- /* Compute alternate SHA512 sum with input KEY, SALT, and KEY. The
- final result will be added to the first context. */
- HASH_Begin(alt_ctx);
- /* Add key. */
- HASH_Update(alt_ctx, (const unsigned char *)key, key_len);
+ /* Compute alternate SHA512 sum with input KEY, SALT, and KEY.
+ * The final result will be added to the first context. */
+ HASH_Begin(alt_ctx);
- /* Add salt. */
- HASH_Update(alt_ctx, (const unsigned char *)salt, salt_len);
+ /* Add key. */
+ HASH_Update(alt_ctx, (const unsigned char *)key, key_len);
- /* Add key again. */
- HASH_Update(alt_ctx, (const unsigned char *)key, key_len);
+ /* Add salt. */
+ HASH_Update(alt_ctx, (const unsigned char *)salt, salt_len);
- /* Now get result of this (64 bytes) and add it to the other
- context. */
- HASH_End(alt_ctx, alt_result, &part, HASH_ResultLenContext(alt_ctx));
+ /* Add key again. */
+ HASH_Update(alt_ctx, (const unsigned char *)key, key_len);
- /* Add for any character in the key one byte of the alternate sum. */
- for (cnt = key_len; cnt > 64; cnt -= 64) {
- HASH_Update(ctx, alt_result, 64);
- }
- HASH_Update(ctx, alt_result, cnt);
+ /* Now get result of this (64 bytes) and add it to the other context. */
+ HASH_End(alt_ctx, alt_result, &part, HASH_ResultLenContext(alt_ctx));
- /* Take the binary representation of the length of the key and for every
- 1 add the alternate sum, for every 0 the key. */
- for (cnt = key_len; cnt > 0; cnt >>= 1)
- if ((cnt & 1) != 0) {
- HASH_Update(ctx, alt_result, 64);
- } else {
- HASH_Update(ctx, (const unsigned char *)key, key_len);
+ /* Add for any character in the key one byte of the alternate sum. */
+ for (cnt = key_len; cnt > 64; cnt -= 64) {
+ HASH_Update(ctx, alt_result, 64);
+ }
+ HASH_Update(ctx, alt_result, cnt);
+
+ /* Take the binary representation of the length of the key and for every
+ * 1 add the alternate sum, for every 0 the key. */
+ for (cnt = key_len; cnt > 0; cnt >>= 1) {
+ if ((cnt & 1) != 0) {
+ HASH_Update(ctx, alt_result, 64);
+ } else {
+ HASH_Update(ctx, (const unsigned char *)key, key_len);
+ }
}
- /* Create intermediate result. */
- HASH_End(ctx, alt_result, &part, HASH_ResultLenContext(ctx));
-
- /* Start computation of P byte sequence. */
- HASH_Begin(alt_ctx);
-
- /* For every character in the password add the entire password. */
- for (cnt = 0; cnt < key_len; ++cnt) {
- HASH_Update(alt_ctx, (const unsigned char *)key, key_len);
- }
+ /* Create intermediate result. */
+ HASH_End(ctx, alt_result, &part, HASH_ResultLenContext(ctx));
- /* Finish the digest. */
- HASH_End(alt_ctx, temp_result, &part, HASH_ResultLenContext(alt_ctx));
+ /* Start computation of P byte sequence. */
+ HASH_Begin(alt_ctx);
- /* Create byte sequence P. */
- cp = p_bytes = alloca (key_len);
- for (cnt = key_len; cnt >= 64; cnt -= 64)
- cp = mempcpy (cp, temp_result, 64);
- memcpy (cp, temp_result, cnt);
+ /* For every character in the password add the entire password. */
+ for (cnt = 0; cnt < key_len; cnt++) {
+ HASH_Update(alt_ctx, (const unsigned char *)key, key_len);
+ }
- /* Start computation of S byte sequence. */
- HASH_Begin(alt_ctx);
+ /* Finish the digest. */
+ HASH_End(alt_ctx, temp_result, &part, HASH_ResultLenContext(alt_ctx));
- /* For every character in the password add the entire password. */
- for (cnt = 0; cnt < 16 + alt_result[0]; ++cnt) {
- HASH_Update(alt_ctx, (const unsigned char *)salt, salt_len);
- }
-
- /* Finish the digest. */
- HASH_End(alt_ctx, temp_result, &part, HASH_ResultLenContext(alt_ctx));
-
- /* Create byte sequence S. */
- cp = s_bytes = alloca (salt_len);
- for (cnt = salt_len; cnt >= 64; cnt -= 64)
- cp = mempcpy (cp, temp_result, 64);
- memcpy (cp, temp_result, cnt);
-
- /* Repeatedly run the collected hash value through SHA512 to burn
- CPU cycles. */
- for (cnt = 0; cnt < rounds; ++cnt)
- {
- /* New context. */
- HASH_Begin(ctx);
-
- /* Add key or last result. */
- if ((cnt & 1) != 0) {
- HASH_Update(ctx, (const unsigned char *)p_bytes, key_len);
- } else {
- HASH_Update(ctx, alt_result, 64);
- }
+ /* Create byte sequence P. */
+ cp = p_bytes = alloca(key_len);
+ for (cnt = key_len; cnt >= 64; cnt -= 64) {
+ cp = mempcpy(cp, temp_result, 64);
+ }
+ memcpy(cp, temp_result, cnt);
- /* Add salt for numbers not divisible by 3. */
- if (cnt % 3 != 0) {
- HASH_Update(ctx, (const unsigned char *)s_bytes, salt_len);
- }
+ /* Start computation of S byte sequence. */
+ HASH_Begin(alt_ctx);
- /* Add key for numbers not divisible by 7. */
- if (cnt % 7 != 0) {
- HASH_Update(ctx, (const unsigned char *)p_bytes, key_len);
- }
+ /* For every character in the password add the entire salt. */
+ for (cnt = 0; cnt < 16 + alt_result[0]; cnt++) {
+ HASH_Update(alt_ctx, (const unsigned char *)salt, salt_len);
+ }
- /* Add key or last result. */
- if ((cnt & 1) != 0) {
- HASH_Update(ctx, alt_result, 64);
- } else {
- HASH_Update(ctx, (const unsigned char *)p_bytes, key_len);
- }
+ /* Finish the digest. */
+ HASH_End(alt_ctx, temp_result, &part, HASH_ResultLenContext(alt_ctx));
- /* Create intermediate result. */
- HASH_End(ctx, alt_result, &part, HASH_ResultLenContext(ctx));
+ /* Create byte sequence S. */
+ cp = s_bytes = alloca(salt_len);
+ for (cnt = salt_len; cnt >= 64; cnt -= 64) {
+ cp = mempcpy(cp, temp_result, 64);
}
-
- /* Now we can construct the result string. It consists of three
- parts. */
- cp = __stpncpy (buffer, sha512_salt_prefix, MAX (0, buflen));
- buflen -= sizeof (sha512_salt_prefix) - 1;
-
- if (rounds_custom)
- {
- int n = snprintf (cp, MAX (0, buflen), "%s%zu$",
- sha512_rounds_prefix, rounds);
- cp += n;
- buflen -= n;
+ memcpy(cp, temp_result, cnt);
+
+ /* Repeatedly run the collected hash value through SHA512 to burn CPU cycles. */
+ for (cnt = 0; cnt < rounds; cnt++) {
+
+ HASH_Begin(ctx);
+
+ /* Add key or last result. */
+ if ((cnt & 1) != 0) {
+ HASH_Update(ctx, (const unsigned char *)p_bytes, key_len);
+ } else {
+ HASH_Update(ctx, alt_result, 64);
+ }
+
+ /* Add salt for numbers not divisible by 3. */
+ if (cnt % 3 != 0) {
+ HASH_Update(ctx, (const unsigned char *)s_bytes, salt_len);
+ }
+
+ /* Add key for numbers not divisible by 7. */
+ if (cnt % 7 != 0) {
+ HASH_Update(ctx, (const unsigned char *)p_bytes, key_len);
+ }
+
+ /* Add key or last result. */
+ if ((cnt & 1) != 0) {
+ HASH_Update(ctx, alt_result, 64);
+ } else {
+ HASH_Update(ctx, (const unsigned char *)p_bytes, key_len);
+ }
+
+ /* Create intermediate result. */
+ HASH_End(ctx, alt_result, &part, HASH_ResultLenContext(ctx));
}
- cp = __stpncpy (cp, salt, MIN ((size_t) MAX (0, buflen), salt_len));
- buflen -= MIN ((size_t) MAX (0, buflen), salt_len);
+ /* Now we can construct the result string.
+ * It consists of three parts. */
+ if (buflen <= SALT_PREF_SIZE) {
+ ret = ERANGE;
+ goto done;
+ }
- if (buflen > 0)
- {
- *cp++ = '$';
- --buflen;
+ cp = __stpncpy(buffer, sha512_salt_prefix, SALT_PREF_SIZE);
+ buflen -= SALT_PREF_SIZE;
+
+ if (rounds_custom) {
+ n = snprintf(cp, buflen, "%s%zu$",
+ sha512_rounds_prefix, rounds);
+ if (n < 0 || n >= buflen) {
+ ret = ERANGE;
+ goto done;
+ }
+ cp += n;
+ buflen -= n;
}
-#define b64_from_24bit(B2, B1, B0, N) \
- do { \
- unsigned int w = ((B2) << 16) | ((B1) << 8) | (B0); \
- int n = (N); \
- while (n-- > 0 && buflen > 0) \
- { \
- *cp++ = b64t[w & 0x3f]; \
- --buflen; \
- w >>= 6; \
- } \
- } while (0)
-
- b64_from_24bit (alt_result[0], alt_result[21], alt_result[42], 4);
- b64_from_24bit (alt_result[22], alt_result[43], alt_result[1], 4);
- b64_from_24bit (alt_result[44], alt_result[2], alt_result[23], 4);
- b64_from_24bit (alt_result[3], alt_result[24], alt_result[45], 4);
- b64_from_24bit (alt_result[25], alt_result[46], alt_result[4], 4);
- b64_from_24bit (alt_result[47], alt_result[5], alt_result[26], 4);
- b64_from_24bit (alt_result[6], alt_result[27], alt_result[48], 4);
- b64_from_24bit (alt_result[28], alt_result[49], alt_result[7], 4);
- b64_from_24bit (alt_result[50], alt_result[8], alt_result[29], 4);
- b64_from_24bit (alt_result[9], alt_result[30], alt_result[51], 4);
- b64_from_24bit (alt_result[31], alt_result[52], alt_result[10], 4);
- b64_from_24bit (alt_result[53], alt_result[11], alt_result[32], 4);
- b64_from_24bit (alt_result[12], alt_result[33], alt_result[54], 4);
- b64_from_24bit (alt_result[34], alt_result[55], alt_result[13], 4);
- b64_from_24bit (alt_result[56], alt_result[14], alt_result[35], 4);
- b64_from_24bit (alt_result[15], alt_result[36], alt_result[57], 4);
- b64_from_24bit (alt_result[37], alt_result[58], alt_result[16], 4);
- b64_from_24bit (alt_result[59], alt_result[17], alt_result[38], 4);
- b64_from_24bit (alt_result[18], alt_result[39], alt_result[60], 4);
- b64_from_24bit (alt_result[40], alt_result[61], alt_result[19], 4);
- b64_from_24bit (alt_result[62], alt_result[20], alt_result[41], 4);
- b64_from_24bit (0, 0, alt_result[63], 2);
-
- if (buflen <= 0)
- {
- errno = ERANGE;
- buffer = NULL;
+ if (buflen <= salt_len + 1) {
+ ret = ERANGE;
+ goto done;
}
- else
- *cp = '\0'; /* Terminate the string. */
-
- /* Clear the buffer for the intermediate result so that people
- attaching to processes or reading core dumps cannot get any
- information. We do it in this way to clear correct_words[]
- inside the SHA512 implementation as well. */
- HASH_Destroy(ctx);
- HASH_Destroy(alt_ctx);
-
- memset (temp_result, '\0', sizeof (temp_result));
- memset (p_bytes, '\0', key_len);
- memset (s_bytes, '\0', salt_len);
- memset (&ctx, '\0', sizeof (ctx));
- memset (&alt_ctx, '\0', sizeof (alt_ctx));
- if (copied_key != NULL)
- memset (copied_key, '\0', key_len);
- if (copied_salt != NULL)
- memset (copied_salt, '\0', salt_len);
-
- return buffer;
-}
+ cp = __stpncpy(cp, salt, salt_len);
+ *cp++ = '$';
+ buflen -= salt_len + 1;
+
+ /* fuzzyfill the base 64 string */
+ p1 = 0;
+ p2 = 21;
+ p3 = 42;
+ for (n = 0; n < 21; n++) {
+ b64_from_24bit(&cp, &buflen, 4, alt_result[p1], alt_result[p2], alt_result[p3]);
+ if (buflen == 0) {
+ ret = ERANGE;
+ goto done;
+ }
+ pt = p1;
+ p1 = p2 + 1;
+ p2 = p3 + 1;
+ p3 = pt + 1;
+ }
+ /* 64th and last byte */
+ b64_from_24bit(&cp, &buflen, 2, 0, 0, alt_result[p3]);
+ if (buflen == 0) {
+ ret = ERANGE;
+ goto done;
+ }
+
+ *cp = '\0';
+ ret = EOK;
+
+done:
+ /* Clear the buffer for the intermediate result so that people attaching
+ * to processes or reading core dumps cannot get any information. We do it
+ * in this way to clear correct_words[] inside the SHA512 implementation
+ * as well. */
+ if (ctx) HASH_Destroy(ctx);
+ if (alt_ctx) HASH_Destroy(alt_ctx);
+ if (p_bytes) memset(p_bytes, '\0', key_len);
+ if (s_bytes) memset(s_bytes, '\0', salt_len);
+ if (copied_key) memset(copied_key, '\0', key_len);
+ if (copied_salt) memset(copied_salt, '\0', salt_len);
+ memset(temp_result, '\0', sizeof(temp_result));
+ return ret;
+}
-/* This entry point is equivalent to the `crypt' function in Unix
- libcs. */
-char *
-nss_sha512_crypt (const char *key, const char *salt)
+int s3crypt_sha512(TALLOC_CTX *memctx,
+ const char *key, const char *salt, char **_hash)
{
- /* We don't want to have an arbitrary limit in the size of the
- password. We can compute an upper bound for the size of the
- result in advance and so we can prepare the buffer we pass to
- `sha512_crypt_r'. */
- static char *buffer;
- static int buflen;
- int needed = (sizeof (sha512_salt_prefix) - 1
- + sizeof (sha512_rounds_prefix) + 9 + 1
- + strlen (salt) + 1 + 86 + 1);
-
- if (buflen < needed)
- {
- char *new_buffer = (char *) realloc (buffer, needed);
- if (new_buffer == NULL)
- return NULL;
-
- buffer = new_buffer;
- buflen = needed;
- }
+ char *hash;
+ int hlen = (sizeof (sha512_salt_prefix) - 1
+ + sizeof (sha512_rounds_prefix) + 9 + 1
+ + strlen (salt) + 1 + 86 + 1);
+ int ret;
+
+ hash = talloc_size(memctx, hlen);
+ if (!hash) return ENOMEM;
- return sha512_crypt_r (key, salt, buffer, buflen);
+ ret = sha512_crypt_r(key, salt, hash, hlen);
+ if (ret) return ret;
+
+ *_hash = hash;
+ return ret;
}
-char *gen_salt(void)
+#define SALT_RAND_LEN 12
+
+int s3crypt_gen_salt(TALLOC_CTX *memctx, char **_salt)
{
- int ret;
- unsigned char bin_rand[12];
- static char b64_rand[17];
- char *cp;
- int buflen;
+ uint8_t rb[SALT_RAND_LEN];
+ char *salt, *cp;
+ size_t slen;
+ int ret;
+
+ if (!nspr_nss_init_done) {
+ ret = nspr_nss_init();
+ if (ret != SECSuccess) {
+ return EIO;
+ }
+ }
- if (!nspr_nss_init_done) {
- ret = nspr_nss_init();
- if (ret != SECSuccess) return NULL;
- }
+ salt = talloc_size(memctx, SALT_LEN_MAX + 1);
+ if (!salt) {
+ return ENOMEM;
+ }
- ret = PK11_GenerateRandom(bin_rand, sizeof(bin_rand)-1);
- cp = b64_rand;
- buflen = 16;
- b64_from_24bit (bin_rand[0], bin_rand[1], bin_rand[2], 4);
- b64_from_24bit (bin_rand[3], bin_rand[4], bin_rand[5], 4);
- b64_from_24bit (bin_rand[6], bin_rand[7], bin_rand[8], 4);
- b64_from_24bit (bin_rand[9], bin_rand[10], bin_rand[11], 4);
+ ret = PK11_GenerateRandom(rb, SALT_RAND_LEN);
+ if (ret != SECSuccess) {
+ return EIO;
+ }
- *cp++ = '\0';
+ slen = SALT_LEN_MAX;
+ cp = salt;
+ b64_from_24bit(&cp, &slen, 4, rb[0], rb[1], rb[2]);
+ b64_from_24bit(&cp, &slen, 4, rb[3], rb[4], rb[5]);
+ b64_from_24bit(&cp, &slen, 4, rb[6], rb[7], rb[8]);
+ b64_from_24bit(&cp, &slen, 4, rb[9], rb[10], rb[11]);
+ *cp = '\0';
- return b64_rand;
+ *_salt = salt;
+ return EOK;
}
diff --git a/server/util/nss_sha512crypt.h b/server/util/nss_sha512crypt.h
index 0d063217..5512c5d9 100644
--- a/server/util/nss_sha512crypt.h
+++ b/server/util/nss_sha512crypt.h
@@ -1,3 +1,4 @@
-char * nss_sha512_crypt (const char *key, const char *salt);
-char *gen_salt(void);
+int s3crypt_sha512(TALLOC_CTX *mmectx,
+ const char *key, const char *salt, char **_hash);
+int s3crypt_gen_salt(TALLOC_CTX *memctx, char **_salt);