summaryrefslogtreecommitdiffstats
path: root/lib/libcrypt/crypt.c
diff options
context:
space:
mode:
authormarkm <markm@FreeBSD.org>1999-01-23 08:27:46 +0000
committermarkm <markm@FreeBSD.org>1999-01-23 08:27:46 +0000
commita0f20ba4fc91853c1b11d690f3fc4eccf3a9a8a3 (patch)
tree54e18fd1a40f0d109fa3c2656ca6cb3da498dbe1 /lib/libcrypt/crypt.c
parent41b93516e8ae0af9615f64c660b6568e39d00860 (diff)
downloadFreeBSD-src-a0f20ba4fc91853c1b11d690f3fc4eccf3a9a8a3.zip
FreeBSD-src-a0f20ba4fc91853c1b11d690f3fc4eccf3a9a8a3.tar.gz
The new crypt code broke "make world". Back it out.
Diffstat (limited to 'lib/libcrypt/crypt.c')
-rw-r--r--lib/libcrypt/crypt.c276
1 files changed, 122 insertions, 154 deletions
diff --git a/lib/libcrypt/crypt.c b/lib/libcrypt/crypt.c
index 3d001a4..cdd4bbc 100644
--- a/lib/libcrypt/crypt.c
+++ b/lib/libcrypt/crypt.c
@@ -5,185 +5,153 @@
* can do whatever you want with this stuff. If we meet some day, and you think
* this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
* ----------------------------------------------------------------------------
- */
-
-/*
- * It has since been changed by Brandon Gillespie, the end result is not
- * too clean, but it is clear and modular; there is no need for crypt()
- * to be optimized (and actually a desire for the opposite) so I am not
- * overly concerned.
- */
-
-/*
- * Assumptions made with the format of passwords:
*
- * + Any password beginning with a dollar-sign is assumed to be in
- * the Modular Crypt Format (MCF), namely: $tag$salt$hash. Any
- * algorithms added will also use this format. Other MCF assumptions:
- * + The algorithm tag (field 1) will be less than five characters
- * long (yay, arbitrary limits). Anything longer is ignored.
- * New algorithm names are not allowed to be fully numeric as
- * anything fully numeric is mapped from other OS's not following
- * our standard, and from older versions of this standard (such as
- * $1$ for MD5 passwords, rather than $MD5$).
- * + The salt can be up to 16 characters in length (more arbitrary
- * limits).
- * + An invalid or unrecognized algorithm tag will default to use the
- * 'best' encryption method--whatever that may be at the time.
- * + If the MCF is not specified, use the 'best' method, unless DES
- * is installed--then use DES.
- * + Any password beginning with an underscore '_' is assumed to be
- * the Extended DES Format, which has its own salt requirements,
- * and is not the same as the MCF.
- * + Salt must be limited to the same ascii64 character set the hash
- * is encoded in (namely "./0-9A-Za-z").
+ * $Id$
+ *
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char rcsid[] = "$Header$";
+#endif /* LIBC_SCCS and not lint */
+
#include <unistd.h>
#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
-#include <ctype.h>
-
-#define _CRYPT_C_
-
-#include "crypt.h"
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
+#include <md5.h>
+#include <string.h>
-/*
- * commonly used througout all algorithms
- */
+static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-static unsigned char ascii64[] = /* 0 ... 63 => ascii - 64 */
- "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+static void to64 __P((char *, unsigned long, int));
-void
+static void
to64(s, v, n)
char *s;
unsigned long v;
int n;
{
+static void to64 __P((char *, unsigned long, int));
+
while (--n >= 0) {
- *s++ = ascii64[v&0x3f];
+ *s++ = itoa64[v&0x3f];
v >>= 6;
}
}
-static char * hash_word(password, salt, output)
- const char *password;
- const char *salt;
- char *output;
-{
- unsigned char spbuf[_CRYPT_MAX_SALT_LEN+1],
- pwbuf[_CRYPT_OUTPUT_SIZE+1],
- * ep, * sp, * pw;
- unsigned int sl, pl,
- tag = _CRYPT_DEFAULT_VERSION,
- mcf = FALSE;
-
- memset(spbuf, 0, _CRYPT_MAX_SALT_LEN+1);
- memset(pwbuf, 0, _CRYPT_MAX_SALT_LEN+1);
- strncpy((char *) spbuf, (unsigned char *) salt, _CRYPT_MAX_SALT_LEN);
- strncpy((char *) pwbuf, (unsigned char *) password, _CRYPT_OUTPUT_SIZE);
- sp = &spbuf[0];
- pw = &pwbuf[0];
- pl = strlen((char *) pw);
-
- /* figure out what type of crypt is wanted */
- if (sp && sp[0] == '$') {
- mcf = TRUE;
- sp++;
- if (strncasecmp((char *) sp, "MD5$", 4)==0) {
- tag = _MD5_CRYPT;
- sp += 4;
- } else if (strncasecmp((char *) sp, "1$", 2)==0) {
- tag = _MD5_CRYPT_OLD;
- sp += 2;
- } else if (strncasecmp((char *) sp, "SHA1$", 5)==0) {
- tag = _SHS_CRYPT;
- sp += 5;
- } else {
- tag = _CRYPT_DEFAULT_VERSION;
- while (*sp && *sp != '$')
- sp++;
- if (*sp == '$')
- sp++;
- }
- }
-
- /* Refine the salt. Go to the end, it stops at the first '$' or NULL */
- for (ep=sp; *ep && *ep != '$'; ep++)
- continue;
-
- /* we have to do this so we dont overflow _PASSWORD_LEN */
- if ((ep - sp) > 16) {
- sl = 16;
- sp[16] = (char) NULL;
- } else {
- sl = ep - sp;
- }
-
- switch (tag) {
- case _MD5_CRYPT_OLD:
- return crypt_md5(pw, pl, sp, sl, output, "$1$");
- case _MD5_CRYPT:
- return crypt_md5(pw, pl, sp, sl, output, "$MD5$");
-#ifdef DES_CRYPT
- case _DES_CRYPT:
- return crypt_des(pw, pl, sp, sl, output, "");
-#endif
- /* dropping a DES password through will likely cause problems,
- but at least crypt() will return as it says it will (we cannot
- return an error condition) */
- case _SHS_CRYPT:
- default:
- return crypt_shs(pw, pl, sp, sl, output, "$SHA1$");
- }
-}
-
-char *
-crypt(password, salt)
- const char *password;
- const char *salt;
-{
- static char output[_CRYPT_OUTPUT_SIZE];
-
- return hash_word(password, salt, output);
-}
+/*
+ * UNIX password
+ *
+ * Use MD5 for what it is best at...
+ */
char *
-malloc_crypt(password, salt)
- const char *password;
- const char *salt;
+crypt(pw, salt)
+ register const char *pw;
+ register const char *salt;
{
- char * output;
-
- output = (char *) malloc(sizeof(char) * _CRYPT_OUTPUT_SIZE);
- return hash_word(password, salt, output);
-}
-
-int
-match_crypted(possible, crypted)
- const char * possible,
- * crypted;
-{
- char * pc;
- int match;
+ static char *magic = "$1$"; /*
+ * This string is magic for
+ * this algorithm. Having
+ * it this way, we can get
+ * get better later on
+ */
+ static char passwd[120], *p;
+ static const char *sp,*ep;
+ unsigned char final[16];
+ int sl,pl,i,j;
+ MD5_CTX ctx,ctx1;
+ unsigned long l;
+
+ /* Refine the Salt first */
+ sp = salt;
+
+ /* If it starts with the magic string, then skip that */
+ if(!strncmp(sp,magic,strlen(magic)))
+ sp += strlen(magic);
+
+ /* It stops at the first '$', max 8 chars */
+ for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++)
+ continue;
+
+ /* get the length of the true salt */
+ sl = ep - sp;
+
+ MD5Init(&ctx);
+
+ /* The password first, since that is what is most unknown */
+ MD5Update(&ctx,pw,strlen(pw));
+
+ /* Then our magic string */
+ MD5Update(&ctx,magic,strlen(magic));
+
+ /* Then the raw salt */
+ MD5Update(&ctx,sp,sl);
+
+ /* Then just as many characters of the MD5(pw,salt,pw) */
+ MD5Init(&ctx1);
+ MD5Update(&ctx1,pw,strlen(pw));
+ MD5Update(&ctx1,sp,sl);
+ MD5Update(&ctx1,pw,strlen(pw));
+ MD5Final(final,&ctx1);
+ for(pl = strlen(pw); pl > 0; pl -= 16)
+ MD5Update(&ctx,final,pl>16 ? 16 : pl);
+
+ /* Don't leave anything around in vm they could use. */
+ memset(final,0,sizeof final);
+
+ /* Then something really weird... */
+ for (i = strlen(pw); i ; i >>= 1)
+ if(i&1)
+ MD5Update(&ctx, final, 1);
+ else
+ MD5Update(&ctx, pw, 1);
+
+ /* Now make the output string */
+ strcpy(passwd,magic);
+ strncat(passwd,sp,sl);
+ strcat(passwd,"$");
+
+ MD5Final(final,&ctx);
+
+ /*
+ * and now, just to make sure things don't run too fast
+ * On a 60 Mhz Pentium this takes 34 msec, so you would
+ * need 30 seconds to build a 1000 entry dictionary...
+ */
+ for(i=0;i<1000;i++) {
+ MD5Init(&ctx1);
+ if(i & 1)
+ MD5Update(&ctx1,pw,strlen(pw));
+ else
+ MD5Update(&ctx1,final,16);
+
+ if(i % 3)
+ MD5Update(&ctx1,sp,sl);
+
+ if(i % 7)
+ MD5Update(&ctx1,pw,strlen(pw));
+
+ if(i & 1)
+ MD5Update(&ctx1,final,16);
+ else
+ MD5Update(&ctx1,pw,strlen(pw));
+ MD5Final(final,&ctx1);
+ }
- pc = malloc_crypt(possible, crypted);
+ p = passwd + strlen(passwd);
- match = !strcmp(pc, crypted);
+ l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4;
+ l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4;
+ l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4;
+ l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4;
+ l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4;
+ l = final[11] ; to64(p,l,2); p += 2;
+ *p = '\0';
- free(pc);
+ /* Don't leave anything around in vm they could use. */
+ memset(final,0,sizeof final);
- return match;
+ return passwd;
}
-#undef _CRYPT_C_
OpenPOWER on IntegriCloud