Deleted Added
full compact
crypt.c (22993) crypt.c (42981)
1/*
2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
7 * ----------------------------------------------------------------------------
1/*
2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
7 * ----------------------------------------------------------------------------
8 *
9 * $Id$
10 *
11 */
12
8 */
9
13#if defined(LIBC_SCCS) && !defined(lint)
14static char rcsid[] = "$Header: /home/ncvs/src/lib/libcrypt/crypt.c,v 1.6 1997/01/14 06:09:00 jkh Exp $";
15#endif /* LIBC_SCCS and not lint */
10/*
11 * It has since been changed by Brandon Gillespie, the end result is not
12 * too clean, but it is clear and modular; there is no need for crypt()
13 * to be optimized (and actually a desire for the opposite) so I am not
14 * overly concerned.
15 */
16
16
17/*
18 * Assumptions made with the format of passwords:
19 *
20 * + Any password beginning with a dollar-sign is assumed to be in
21 * the Modular Crypt Format (MCF), namely: $tag$salt$hash. Any
22 * algorithms added will also use this format. Other MCF assumptions:
23 * + The algorithm tag (field 1) will be less than five characters
24 * long (yay, arbitrary limits). Anything longer is ignored.
25 * New algorithm names are not allowed to be fully numeric as
26 * anything fully numeric is mapped from other OS's not following
27 * our standard, and from older versions of this standard (such as
28 * $1$ for MD5 passwords, rather than $MD5$).
29 * + The salt can be up to 16 characters in length (more arbitrary
30 * limits).
31 * + An invalid or unrecognized algorithm tag will default to use the
32 * 'best' encryption method--whatever that may be at the time.
33 * + If the MCF is not specified, use the 'best' method, unless DES
34 * is installed--then use DES.
35 * + Any password beginning with an underscore '_' is assumed to be
36 * the Extended DES Format, which has its own salt requirements,
37 * and is not the same as the MCF.
38 * + Salt must be limited to the same ascii64 character set the hash
39 * is encoded in (namely "./0-9A-Za-z").
40 */
41
17#include <unistd.h>
18#include <stdio.h>
42#include <unistd.h>
43#include <stdio.h>
44#include <stdlib.h>
19#include <string.h>
45#include <string.h>
20#include <md5.h>
21#include <string.h>
46#include <ctype.h>
22
47
23static unsigned char itoa64[] = /* 0 ... 63 => ascii - 64 */
24 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
48#define _CRYPT_C_
25
49
26static void to64 __P((char *, unsigned long, int));
50#include "crypt.h"
27
51
28static void
52#ifndef TRUE
53#define TRUE 1
54#endif
55
56#ifndef FALSE
57#define FALSE 0
58#endif
59
60/*
61 * commonly used througout all algorithms
62 */
63
64static unsigned char ascii64[] = /* 0 ... 63 => ascii - 64 */
65 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
66
67void
29to64(s, v, n)
30 char *s;
31 unsigned long v;
32 int n;
33{
68to64(s, v, n)
69 char *s;
70 unsigned long v;
71 int n;
72{
34static void to64 __P((char *, unsigned long, int));
35
36 while (--n >= 0) {
73 while (--n >= 0) {
37 *s++ = itoa64[v&0x3f];
74 *s++ = ascii64[v&0x3f];
38 v >>= 6;
39 }
40}
41
75 v >>= 6;
76 }
77}
78
42/*
43 * UNIX password
44 *
45 * Use MD5 for what it is best at...
46 */
47
48char *
49crypt(pw, salt)
50 register const char *pw;
51 register const char *salt;
79static char * hash_word(password, salt, output)
80 const char *password;
81 const char *salt;
82 char *output;
52{
83{
53 static char *magic = "$1$"; /*
54 * This string is magic for
55 * this algorithm. Having
56 * it this way, we can get
57 * get better later on
58 */
59 static char passwd[120], *p;
60 static const char *sp,*ep;
61 unsigned char final[16];
62 int sl,pl,i,j;
63 MD5_CTX ctx,ctx1;
64 unsigned long l;
84 unsigned char spbuf[_CRYPT_MAX_SALT_LEN+1],
85 pwbuf[_CRYPT_OUTPUT_SIZE+1],
86 * ep, * sp, * pw;
87 unsigned int sl, pl,
88 tag = _CRYPT_DEFAULT_VERSION,
89 mcf = FALSE;
65
90
66 /* Refine the Salt first */
67 sp = salt;
91 memset(spbuf, 0, _CRYPT_MAX_SALT_LEN+1);
92 memset(pwbuf, 0, _CRYPT_MAX_SALT_LEN+1);
93 strncpy((char *) spbuf, (unsigned char *) salt, _CRYPT_MAX_SALT_LEN);
94 strncpy((char *) pwbuf, (unsigned char *) password, _CRYPT_OUTPUT_SIZE);
95 sp = &spbuf[0];
96 pw = &pwbuf[0];
97 pl = strlen((char *) pw);
68
98
69 /* If it starts with the magic string, then skip that */
70 if(!strncmp(sp,magic,strlen(magic)))
71 sp += strlen(magic);
99 /* figure out what type of crypt is wanted */
100 if (sp && sp[0] == '$') {
101 mcf = TRUE;
102 sp++;
103 if (strncasecmp((char *) sp, "MD5$", 4)==0) {
104 tag = _MD5_CRYPT;
105 sp += 4;
106 } else if (strncasecmp((char *) sp, "1$", 2)==0) {
107 tag = _MD5_CRYPT_OLD;
108 sp += 2;
109 } else if (strncasecmp((char *) sp, "SHA1$", 5)==0) {
110 tag = _SHS_CRYPT;
111 sp += 5;
112 } else {
113 tag = _CRYPT_DEFAULT_VERSION;
114 while (*sp && *sp != '$')
115 sp++;
116 if (*sp == '$')
117 sp++;
118 }
119 }
72
120
73 /* It stops at the first '$', max 8 chars */
74 for(ep=sp;*ep && *ep != '$' && ep < (sp+8);ep++)
75 continue;
121 /* Refine the salt. Go to the end, it stops at the first '$' or NULL */
122 for (ep=sp; *ep && *ep != '$'; ep++)
123 continue;
76
124
77 /* get the length of the true salt */
78 sl = ep - sp;
125 /* we have to do this so we dont overflow _PASSWORD_LEN */
126 if ((ep - sp) > 16) {
127 sl = 16;
128 sp[16] = (char) NULL;
129 } else {
130 sl = ep - sp;
131 }
79
132
80 MD5Init(&ctx);
133 switch (tag) {
134 case _MD5_CRYPT_OLD:
135 return crypt_md5(pw, pl, sp, sl, output, "$1$");
136 case _MD5_CRYPT:
137 return crypt_md5(pw, pl, sp, sl, output, "$MD5$");
138#ifdef DES_CRYPT
139 case _DES_CRYPT:
140 return crypt_des(pw, pl, sp, sl, output, "");
141#endif
142 /* dropping a DES password through will likely cause problems,
143 but at least crypt() will return as it says it will (we cannot
144 return an error condition) */
145 case _SHS_CRYPT:
146 default:
147 return crypt_shs(pw, pl, sp, sl, output, "$SHA1$");
148 }
149}
81
150
82 /* The password first, since that is what is most unknown */
83 MD5Update(&ctx,pw,strlen(pw));
151char *
152crypt(password, salt)
153 const char *password;
154 const char *salt;
155{
156 static char output[_CRYPT_OUTPUT_SIZE];
84
157
85 /* Then our magic string */
86 MD5Update(&ctx,magic,strlen(magic));
158 return hash_word(password, salt, output);
159}
87
160
88 /* Then the raw salt */
89 MD5Update(&ctx,sp,sl);
161char *
162malloc_crypt(password, salt)
163 const char *password;
164 const char *salt;
165{
166 char * output;
90
167
91 /* Then just as many characters of the MD5(pw,salt,pw) */
92 MD5Init(&ctx1);
93 MD5Update(&ctx1,pw,strlen(pw));
94 MD5Update(&ctx1,sp,sl);
95 MD5Update(&ctx1,pw,strlen(pw));
96 MD5Final(final,&ctx1);
97 for(pl = strlen(pw); pl > 0; pl -= 16)
98 MD5Update(&ctx,final,pl>16 ? 16 : pl);
168 output = (char *) malloc(sizeof(char) * _CRYPT_OUTPUT_SIZE);
169 return hash_word(password, salt, output);
170}
99
171
100 /* Don't leave anything around in vm they could use. */
101 memset(final,0,sizeof final);
172int
173match_crypted(possible, crypted)
174 const char * possible,
175 * crypted;
176{
177 char * pc;
178 int match;
102
179
103 /* Then something really weird... */
104 for (i = strlen(pw); i ; i >>= 1)
105 if(i&1)
106 MD5Update(&ctx, final, 1);
107 else
108 MD5Update(&ctx, pw, 1);
180 pc = malloc_crypt(possible, crypted);
109
181
110 /* Now make the output string */
111 strcpy(passwd,magic);
112 strncat(passwd,sp,sl);
113 strcat(passwd,"$");
182 match = !strcmp(pc, crypted);
114
183
115 MD5Final(final,&ctx);
184 free(pc);
116
185
117 /*
118 * and now, just to make sure things don't run too fast
119 * On a 60 Mhz Pentium this takes 34 msec, so you would
120 * need 30 seconds to build a 1000 entry dictionary...
121 */
122 for(i=0;i<1000;i++) {
123 MD5Init(&ctx1);
124 if(i & 1)
125 MD5Update(&ctx1,pw,strlen(pw));
126 else
127 MD5Update(&ctx1,final,16);
128
129 if(i % 3)
130 MD5Update(&ctx1,sp,sl);
131
132 if(i % 7)
133 MD5Update(&ctx1,pw,strlen(pw));
134
135 if(i & 1)
136 MD5Update(&ctx1,final,16);
137 else
138 MD5Update(&ctx1,pw,strlen(pw));
139 MD5Final(final,&ctx1);
140 }
141
142 p = passwd + strlen(passwd);
143
144 l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p,l,4); p += 4;
145 l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p,l,4); p += 4;
146 l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p,l,4); p += 4;
147 l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p,l,4); p += 4;
148 l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p,l,4); p += 4;
149 l = final[11] ; to64(p,l,2); p += 2;
150 *p = '\0';
151
152 /* Don't leave anything around in vm they could use. */
153 memset(final,0,sizeof final);
154
155 return passwd;
186 return match;
156}
157
187}
188
189#undef _CRYPT_C_