aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/pam_unix/Makefile2
-rw-r--r--modules/pam_unix/md5.c158
-rw-r--r--modules/pam_unix/md5.h7
-rw-r--r--modules/pam_unix/pam_unix.c57
4 files changed, 167 insertions, 57 deletions
diff --git a/modules/pam_unix/Makefile b/modules/pam_unix/Makefile
index 34ed3f0..0b05143 100644
--- a/modules/pam_unix/Makefile
+++ b/modules/pam_unix/Makefile
@@ -17,7 +17,7 @@ MANMODE = 644
PROJ = $(LIBSHARED)
-OBJS = pam_unix.o
+OBJS = pam_unix.o md5.o
all:
case "`uname -s`" in \
diff --git a/modules/pam_unix/md5.c b/modules/pam_unix/md5.c
index a9377f1..94d3dd4 100644
--- a/modules/pam_unix/md5.c
+++ b/modules/pam_unix/md5.c
@@ -17,6 +17,8 @@
#include <sys/types.h>
#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
#include "md5.h"
#define PUT_64BIT_LE(cp, value) do { \
@@ -35,6 +37,10 @@
(cp)[1] = (value) >> 8; \
(cp)[0] = (value); } while (0)
+
+static void to64(char* , long , int );
+
+
static u_int8_t PADDING[MD5_BLOCK_LENGTH] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -244,20 +250,158 @@ MD5Transform(u_int32_t state[4], const u_int8_t block[MD5_BLOCK_LENGTH])
state[2] += c;
state[3] += d;
}
+
+
/*
* MD5String: takes a string as an argument and returns the
* digest for this string.
*/
-char * MD5String(const char * string) {
+char * MD5Hash(const char * string, const char * salt) {
+
+ int i,j,passl,saltl,pl;
+ unsigned long l;
+ MD5_CTX mdContext, mdContext2;
+ unsigned char digest[16];
+ const char *magic = "$1$";
+ const char *sp , *tsp; /*sp: salt pointer / tsp : true salt pointer*/
+ char * md5hash, *passwd;
+
+ md5hash = (char *) malloc (sizeof(char)*120);
+ passwd = md5hash;
+ sp = salt;
+
+ /* skip magic string if it's in salt --
+ * this can't happen here, since we create the
+ * salt without a magic string but someone may use
+ * this for something else one day */
+ if (!strncmp(sp, magic, strlen(magic)))
+ sp += strlen(magic);
+
+ /* stop salt at '$' or after 8 chars */
+ for (tsp = sp; *tsp && *tsp != '$' && tsp < (sp + 8); tsp++)
+ continue;
+ /* Define salt and pass length */
+ saltl = tsp - sp ;
+ passl = strlen(string);
+
+ /* Init the condext */
+ MD5Init(&mdContext);
+ /* Update with the password first */
+ MD5Update(&mdContext, (unsigned const char *)string, passl);
+ /* Then use the magic string */
+ MD5Update(&mdContext, (unsigned const char *)magic, strlen(magic));
+ /* Then use the salt */
+ MD5Update(&mdContext, (unsigned const char *)salt, saltl);
+
+ /* Update original using characters from MD5Hash of pwd,salt,pwd */
+ MD5Init(&mdContext2);
+ MD5Update(&mdContext2, (unsigned const char *)string, passl);
+ MD5Update(&mdContext2, (unsigned const char *)salt, saltl);
+ MD5Update(&mdContext2, (unsigned const char *)string, passl);
+ MD5Final (digest, &mdContext2);
+
+ /* Cool, huh? */
+ for (pl = passl; pl > 0; pl -= 16)
+ MD5Update(&mdContext,(unsigned const char *)digest,pl>16 ? 16 : pl);
+
+ /* Don't leave behind sensitive data */
+ memset(digest, 0, sizeof digest);
+
+ /* Weird stuff... */
+ for (j = 0, i = passl; i; i >>= 1) {
+ if (i & 1)
+ MD5Update(&mdContext,(unsigned const char *)digest+j,1);
+ else
+ MD5Update(&mdContext,(unsigned const char *)string+j,1);
+ }
+
+ /* Update hash with magic + salt + $ */
+ strcpy(passwd, magic);
+ strncat(passwd, salt, saltl);
+ strcat(passwd,"$");
+ passwd += strlen(md5hash);
+
+ MD5Final(digest,&mdContext);
+
+ /* Ensure that it can't go too fast (not sure why we need this) */
+ for (i = 0; i < 1000; i++) {
+ MD5Init(&mdContext2);
+ if (i & 1)
+ MD5Update(&mdContext2,(unsigned const char *)string,passl);
+ else
+ MD5Update(&mdContext2,(unsigned const char *)digest,16);
+ if (i % 3)
+ MD5Update(&mdContext2,(unsigned const char *)salt,saltl);
+
+ if (i % 7)
+ MD5Update(&mdContext2,(unsigned const char *)string,passl);
+
+ if (i & 1)
+ MD5Update(&mdContext2,(unsigned const char *)digest,16);
+ else
+ MD5Update(&mdContext2,(unsigned const char *)string,passl);
+
+ MD5Final(digest,&mdContext2);
+
+ }
+
+ /* Do some binary permutations */
+ l = (digest[0] << 16) | (digest[6] << 8) | digest[12];
+ to64(passwd, l, 4);
+ passwd += 4;
+ l = (digest[1] << 16) | (digest[7] << 8) | digest[13];
+ to64(passwd, l, 4);
+ passwd += 4;
+ l = (digest[2] << 16) | (digest[8] << 8) | digest[14];
+ to64(passwd, l, 4);
+ passwd += 4;
+ l = (digest[3] << 16) | (digest[9] << 8) | digest[15];
+ to64(passwd, l, 4);
+ passwd += 4;
+ l = (digest[4] << 16) | (digest[10] << 8) | digest[5];
+ to64(passwd, l, 4);
+ passwd += 4;
+ l = digest[11];
+ to64(passwd, l, 2);
+ passwd += 2;
+ *passwd = '\0';
+
+ /* Don't leave behind sensitive data */
+ memset(digest, 0, sizeof digest);
+ puts(md5hash);
+ return (md5hash);
+}
- MD5_CTX mdContext;
- unsigned int length = strlen(string);
- MD5Init(&mdContext);
- MD5Update(&mdContext, string, length);
- MD5Final (&mdContext);
- return (mdContext->digest);
+/*
+ * Mostly stolen from freebsd-lib's pam_unix module which was mostly
+ * stolen from passwd(1)'s local_passwd.c
+ *
+ * Good ideas are meant to be reused ;)
+ */
+
+static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+static void to64(char *s, long v, int n) {
+ while (--n >= 0) {
+ *s++ = itoa64[v&0x3f];
+ v >>= 6;
+ }
+}
+/* Salt suitable for traditional DES and MD5 */
+void makesalt(char salt[SALTSIZE]) {
+ int i;
+ /* These are not really random numbers, they are just
+ * numbers that change to thwart construction of a
+ * dictionary. This is exposed to the public.
+ */
+
+ for (i = 0; i < SALTSIZE; i += 4)
+ to64(&salt[i], random(), 4);
+
+ salt[SALTSIZE] = '\0';
}
diff --git a/modules/pam_unix/md5.h b/modules/pam_unix/md5.h
index df431b6..51dcb7b 100644
--- a/modules/pam_unix/md5.h
+++ b/modules/pam_unix/md5.h
@@ -13,8 +13,9 @@
#ifndef _MD5_H_
#define _MD5_H_
+#define SALTSIZE 32
#define MD5_BLOCK_LENGTH 64
-#define MD5_DIGEST_LENGTH 16
+#define MD5_DIGEST_LENGTH 16
#define MD5_DIGEST_STRING_LENGTH (MD5_DIGEST_LENGTH * 2 + 1)
typedef struct MD5Context {
@@ -33,5 +34,7 @@ char *MD5End(MD5_CTX *, char *);
char *MD5File(const char *, char *);
char *MD5FileChunk(const char *, char *, off_t, off_t);
char *MD5Data(const u_int8_t *, size_t, char *);
-char *MD5String(const char *);
+char *MD5Hash(const char *, const char * salt);
+void makesalt(char *);
+
#endif /* _MD5_H_ */
diff --git a/modules/pam_unix/pam_unix.c b/modules/pam_unix/pam_unix.c
index e7c058b..fd5d06d 100644
--- a/modules/pam_unix/pam_unix.c
+++ b/modules/pam_unix/pam_unix.c
@@ -8,20 +8,15 @@
#include <time.h>
#include <string.h>
#include <shadow.h>
-
-#ifndef MAXHOSTNAMELEN
-# define MAXHOSTNAMELEN 256
-#endif
+#include "md5.h"
#define PAM_SM_AUTH
#define PAM_SM_ACCOUNT
#define PAM_SM_PASSWORD
#define PAM_SM_SESSION
-#define PASSWORD_HASH "md5"
#define MAX_RETRIES 3
#define DEFAULT_WARN (2L * 7L * 86400L) /* two weeks */
-#define SALTSIZE 32
#include <security/pam_modules.h>
@@ -164,7 +159,6 @@ pam_sm_acct_mgmt(pam_handle_t *pamh, int flags ,
/* Check for account expiration */
if (pwd->sp_expire > 0) {
- fprintf(stdout, "Account expiration data value is %ld\n", pwd->sp_expire);
if ( (curtime > pwd->sp_expire ) && ( pwd->sp_expire != -1 ) ) {
PAM_ERROR("Account has expired!");
return (PAM_ACCT_EXPIRED);
@@ -218,8 +212,6 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags,
int argc, const char *argv[])
{
- fprintf(stdout, "flags :%d\n" , flags);
- fprintf(stdout, "flags :0x%x\n" , flags);
/*
* NIS support will be left for future implementation.
* This is standard unix passwd changing function.
@@ -341,12 +333,16 @@ pam_sm_chauthtok(pam_handle_t *pamh, int flags,
!openpam_get_option(pamh, PAM_OPT_NULLOK))
return (PAM_PERM_DENIED);
+
+ makesalt(salt);
/* Update shadow/passwd entries for Linux */
- if ( openpam_get_option (pamh, PAM_OPT_MD5) )
- pam_err = update_shadow( pamh ,user, MD5String(new_pass)) ;
- else {
- makesalt(salt);
- pam_err = update_shadow( pamh ,user,crypt(new_pass, salt));
+ if ( openpam_get_option (pamh, PAM_OPT_MD5) ) {
+ pam_err = update_shadow( pamh ,user,
+ MD5Hash(new_pass, salt)) ;
+ } else {
+
+ pam_err = update_shadow( pamh ,user,
+ crypt(new_pass, salt));
}
if ( pam_err != PAM_SUCCESS)
return (pam_err);
@@ -629,37 +625,4 @@ static char * read_shadow(const char * user) {
return (pwd->sp_pwdp);
}
-
-
-/*
- * Mostly stolen from freebsd-lib's pam_unix module which was mostly
- * stolen from passwd(1)'s local_passwd.c
- *
- * Good ideas are meant to be reused ;)
- */
-
-static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
- "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-
-static void to64(char *s, long v, int n) {
- while (--n >= 0) {
- *s++ = itoa64[v&0x3f];
- v >>= 6;
- }
-}
-
-/* Salt suitable for traditional DES and MD5 */
-void
-makesalt(char salt[SALTSIZE]) {
- int i;
- /* These are not really random numbers, they are just
- * numbers that change to thwart construction of a
- * dictionary. This is exposed to the public.
- */
-
- for (i = 0; i < SALTSIZE; i += 4)
- to64(&salt[i], random(), 4);
-
- salt[SALTSIZE] = '\0';
-}
PAM_MODULE_ENTRY("pam_unix")