Merge pull request #521 from ennorehling/feature/nocrypt

remove all password hashing code
This commit is contained in:
Enno Rehling 2016-07-13 19:40:20 +02:00 committed by GitHub
commit 4b0463557f
4 changed files with 5 additions and 167 deletions

2
crypto

@ -1 +1 @@
Subproject commit 93dc9200fa4cb6bfa3883b19f6d33fd416ca43da
Subproject commit f0013933852154eccc78536dd813774df5ee7f5d

View File

@ -1,132 +1,18 @@
#include <platform.h>
#include "password.h"
#include <md5.h>
#include <crypt_blowfish.h>
#include <mtrand.h>
#include <drepper.h>
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include <time.h>
#define MAXSALTLEN 32 // maximum length in characters of any salt
#define SALTLEN 8 // length of salts we generate
#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++ = itoa64[w & 0x3f]; \
--buflen; \
w >>= 6; \
} \
} while (0)
char *password_gensalt(char *salt, size_t salt_len) {
size_t buflen = salt_len-1;
char *cp = salt;
while (buflen) {
unsigned long ul = genrand_int32() & (unsigned long)time(0);
b64_from_24bit((char)(ul & 0xFF), (char)((ul >> 8) & 0xff), (char)((ul >> 16) & 0xFF), 4);
}
salt[salt_len-1] = 0;
return salt;
}
bool password_is_implemented(int algo) {
return algo == PASSWORD_PLAINTEXT;// || algo == PASSWORD_BCRYPT || algo == PASSWORD_NOCRYPT || algo == PASSWORD_MD5 || algo == PASSWORD_APACHE_MD5;
}
static const char * password_hash_i(const char * passwd, const char *input, int algo, char *result, size_t len) {
if (algo == PASSWORD_BCRYPT) {
char salt[MAXSALTLEN];
char setting[40];
if (!input) {
input = password_gensalt(salt, MAXSALTLEN);
}
if (_crypt_gensalt_blowfish_rn("$2y$", 5, input, strlen(input), setting, sizeof(setting)) == NULL) {
return NULL;
}
if (_crypt_blowfish_rn(passwd, setting, result, len) == NULL) {
return NULL;
}
return result;
}
else if (algo == PASSWORD_PLAINTEXT) {
_snprintf(result, len, "%s", passwd);
return result;
}
else if (algo == PASSWORD_NOCRYPT) {
_snprintf(result, len, "$0$%s", passwd);
return result;
}
else if (password_is_implemented(algo)) {
char salt[MAXSALTLEN];
assert(passwd);
if (input) {
const char * dol = strchr(input, '$');
size_t salt_len;
if (dol) {
assert(dol > input && dol[0] == '$');
salt_len = dol - input;
}
else {
salt_len = strlen(input);
}
assert(salt_len < MAXSALTLEN);
memcpy(salt, input, salt_len);
salt[salt_len] = 0;
} else {
input = password_gensalt(salt, SALTLEN);
}
if (algo == PASSWORD_MD5) {
return md5_crypt_r(passwd, input, result, len);
}
else if (algo == PASSWORD_APACHE_MD5) {
apr_md5_encode(passwd, input, result, len);
return result;
}
}
return NULL;
return algo == PASSWORD_PLAINTEXT;
}
const char * password_encode(const char * passwd, int algo) {
static char result[64]; // TODO: static result buffers are bad mojo!
if (algo < 0) algo = PASSWORD_DEFAULT;
return password_hash_i(passwd, 0, algo, result, sizeof(result));
return passwd;
}
int password_verify(const char * pwhash, const char * passwd) {
char hash[64];
int algo = PASSWORD_PLAINTEXT;
char *pos;
const char *result;
assert(passwd);
assert(pwhash);
if (pwhash[0] == '$') {
algo = pwhash[1];
}
if (!password_is_implemented(algo)) {
return VERIFY_UNKNOWN;
}
if (algo == PASSWORD_PLAINTEXT) {
return (strcmp(passwd, pwhash) == 0) ? VERIFY_OK : VERIFY_FAIL;
} else if (algo == PASSWORD_BCRYPT) {
char sample[200];
_crypt_blowfish_rn(passwd, pwhash, sample, sizeof(sample));
return (strcmp(sample, pwhash) == 0) ? VERIFY_OK : VERIFY_FAIL;
}
pos = strchr(pwhash+2, '$');
assert(pos && pos[0] == '$');
pos = strchr(pos, '$')+1;
result = password_hash_i(passwd, pos, algo, hash, sizeof(hash));
if (strcmp(pwhash, result) == 0) {
return VERIFY_OK;
}
return VERIFY_FAIL;
return (strcmp(passwd, pwhash) == 0) ? VERIFY_OK : VERIFY_FAIL;
}

View File

@ -1,12 +1,6 @@
#pragma once
#define PASSWORD_PLAINTEXT 0
#define PASSWORD_NOCRYPT '0'
#define PASSWORD_MD5 '1'
#define PASSWORD_BCRYPT '2' // not implemented
#define PASSWORD_APACHE_MD5 'a'
#define PASSWORD_SHA256 '5' // not implemented
#define PASSWORD_SHA512 '6' // not implemented
#define PASSWORD_DEFAULT PASSWORD_PLAINTEXT
#define VERIFY_OK 0 // password matches hash

View File

@ -5,26 +5,7 @@
static void test_passwords(CuTest *tc) {
const char *hash, *expect;
expect = "$apr1$FqQLkl8g$.icQqaDJpim4BVy.Ho5660";
if (password_is_implemented(PASSWORD_APACHE_MD5)) {
CuAssertIntEquals(tc, VERIFY_OK, password_verify(expect, "Hodor"));
hash = password_encode("Hodor", PASSWORD_APACHE_MD5);
CuAssertPtrNotNull(tc, hash);
CuAssertIntEquals(tc, 0, strncmp(hash, expect, 6));
} else {
CuAssertIntEquals(tc, VERIFY_UNKNOWN, password_verify(expect, "Hodor"));
}
expect = "$1$ZouUn04i$yNnT1Oy8azJ5V.UM9ppP5/";
if (password_is_implemented(PASSWORD_MD5)) {
CuAssertIntEquals(tc, VERIFY_OK, password_verify(expect, "jollygood"));
hash = password_encode("jollygood", PASSWORD_MD5);
CuAssertPtrNotNull(tc, hash);
CuAssertIntEquals(tc, 0, strncmp(hash, expect, 3));
} else {
CuAssertIntEquals(tc, VERIFY_UNKNOWN, password_verify(expect, "jollygood"));
}
expect = "password";
if (password_is_implemented(PASSWORD_PLAINTEXT)) {
hash = password_encode("password", PASSWORD_PLAINTEXT);
@ -35,29 +16,6 @@ static void test_passwords(CuTest *tc) {
} else {
CuAssertIntEquals(tc, VERIFY_UNKNOWN, password_verify(expect, "password"));
}
expect = "$0$password";
if (password_is_implemented(PASSWORD_NOCRYPT)) {
hash = password_encode("password", PASSWORD_NOCRYPT);
CuAssertPtrNotNull(tc, hash);
CuAssertStrEquals(tc, hash, expect);
CuAssertIntEquals(tc, VERIFY_OK, password_verify(expect, "password"));
CuAssertIntEquals(tc, VERIFY_FAIL, password_verify(expect, "arseword"));
} else {
CuAssertIntEquals(tc, VERIFY_UNKNOWN, password_verify(expect, "password"));
}
expect = "$2y$05$RJ8qAhu.foXyJLdc2eHTLOaK4MDYn3/v4HtOVCq0Plv2yxcrEB7Wm";
if (password_is_implemented(PASSWORD_BCRYPT)) {
CuAssertIntEquals(tc, VERIFY_OK, password_verify(expect, "Hodor"));
hash = password_encode("Hodor", PASSWORD_BCRYPT);
CuAssertPtrNotNull(tc, hash);
CuAssertIntEquals(tc, 0, strncmp(hash, expect, 7));
} else {
CuAssertIntEquals(tc, VERIFY_UNKNOWN, password_verify(expect, "Hodor"));
}
CuAssertIntEquals(tc, VERIFY_UNKNOWN, password_verify("$9$saltyfish$password", "password"));
}
CuSuite *get_password_suite(void) {