summaryrefslogtreecommitdiff
path: root/libcrypt
diff options
context:
space:
mode:
authorWilliam Pitcock <nenolod@dereferenced.org>2011-12-19 01:21:33 -0600
committerBernhard Reutner-Fischer <rep.dot.nop@gmail.com>2011-12-22 11:28:05 +0100
commit40c426ae8f032d794d15f4a7fca8dc17cdc9899d (patch)
tree911aa08572259141418ce02bb54217427d1e0343 /libcrypt
parentf69319d5a7d3a3ccb46b28ee2b0fd9053c6415ac (diff)
libcrypt: make crypt() itself more modular
By using a function table, we can more cleanly support new crypt implementations, such as SHA256 ($5$) and SHA512 ($6$). Signed-off-by: William Pitcock <nenolod@dereferenced.org> Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
Diffstat (limited to 'libcrypt')
-rw-r--r--libcrypt/crypt.c30
1 files changed, 24 insertions, 6 deletions
diff --git a/libcrypt/crypt.c b/libcrypt/crypt.c
index 89a26149c..33f98b65a 100644
--- a/libcrypt/crypt.c
+++ b/libcrypt/crypt.c
@@ -8,17 +8,35 @@
#define __FORCE_GLIBC
#include <crypt.h>
#include <unistd.h>
+#include <string.h>
+#include <errno.h>
#include "libcrypt.h"
+typedef char *(*crypt_impl_f)(const unsigned char *pw, const unsigned char *salt);
+
+static const struct {
+ const char *salt_pfx;
+ const crypt_impl_f crypt_impl;
+} crypt_impl_tab[] = {
+ { "$1$", __md5_crypt },
+ { NULL, __des_crypt },
+};
+
char *crypt(const char *key, const char *salt)
{
const unsigned char *ukey = (const unsigned char *)key;
const unsigned char *usalt = (const unsigned char *)salt;
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE(crypt_impl_tab); i++) {
+ if (crypt_impl_tab[i].salt_pfx != NULL &&
+ strncmp(crypt_impl_tab[i].salt_pfx, salt, strlen(crypt_impl_tab[i].salt_pfx)))
+ continue;
+
+ return crypt_impl_tab[i].crypt_impl(ukey, usalt);
+ }
- /* First, check if we are supposed to be using the MD5 replacement
- * instead of DES... */
- if (salt[0]=='$' && salt[1]=='1' && salt[2]=='$')
- return __md5_crypt(ukey, usalt);
- else
- return __des_crypt(ukey, usalt);
+ /* no crypt implementation was found, set errno to ENOSYS and return NULL */
+ __set_errno(ENOSYS);
+ return NULL;
}