1 /*
2 * From crypt implementation 1.7 by Poul-Henning Kamp
3 * ----------------------------------------------------------------------------
4 * "THE BEER-WARE LICENSE" (Revision 42):
5 * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
6 * can do whatever you want with this stuff. If we meet some day, and you think
7 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
8 * ----------------------------------------------------------------------------
9 *
10 * Sub-licensed with modifications under AGPL:
11 *
12 * This program is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Affero General Public License version 3.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU Affero General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 *
23 * In addition, as a special exception, the copyright holders give
24 * permission to link the code of portions of this program with the
25 * OpenSSL library under certain conditions as described in each
26 * individual source file, and distribute linked combinations
27 * including the two.
28 *
29 * You must obey the GNU Affero General Public License in all respects
30 * for all of the code used other than OpenSSL.
31 */
32
33 #include "config.h"
34
35 #ifdef HAVE_UNISTD_H
36 #include <unistd.h>
37 #endif
38
39 #ifdef HAVE_STDIO_H
40 #include <stdio.h>
41 #endif
42
43 #ifdef HAVE_STRING_H
44 #include <string.h>
45 #endif
46
47 #include "md5.h"
48 #include "md5_crypt.h"
49
50
51 /* 0 ... 63 => ascii - 64 */
52 static unsigned char itoa64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
53
to64(char * s,unsigned long v,int n)54 static void to64(char *s, unsigned long v, int n) {
55 while (--n >= 0) {
56 *s++ = itoa64[v & 0x3f];
57 v >>= 6;
58 }
59 }
60
61
62 /*
63 * UNIX password MD5
64 */
md5_crypt(const char * pw,const char * id,const char * salt,char * buf,int buflen)65 char *md5_crypt(const char *pw, const char *id, const char *salt, char *buf, int buflen) {
66 char *p;
67 const md5_byte_t *sp, *ep;
68 unsigned char final[16];
69 int sl, pl, pwl = (int)strlen(pw);
70 unsigned long l;
71 md5_context_t ctx, ctx1;
72
73 /* Refine the Salt first */
74 sp = (const md5_byte_t *)salt;
75
76 /* If it starts with the id string, then skip that */
77 if (! strncmp(salt, id, strlen(id)))
78 sp += strlen(id);
79
80 /* It stops at the first '$', max 8 chars */
81 for (ep = sp; *ep && *ep != '$' && ep < (sp + 8); ep++)
82 continue;
83
84 /* get the length of the true salt */
85 sl = (int)(ep - sp);
86
87 md5_init(&ctx);
88
89 /* The password first, since that is what is most unknown */
90 md5_append(&ctx, (const md5_byte_t *)pw, pwl);
91
92 /* Then our id string */
93 md5_append(&ctx, (const md5_byte_t *)id, (int)strlen(id));
94
95 /* Then the raw salt */
96 md5_append(&ctx, sp, sl);
97
98 /* Then just as many characters of the MD5(pw, salt, pw) */
99 md5_init(&ctx1);
100 md5_append(&ctx1, (const md5_byte_t *)pw, pwl);
101 md5_append(&ctx1, sp, sl);
102 md5_append(&ctx1, (const md5_byte_t *)pw, pwl);
103 md5_finish(&ctx1, final);
104 for (pl = pwl; pl > 0; pl -= 16)
105 md5_append(&ctx, final, pl > 16 ? 16 : pl);
106
107 /* Don't leave anything around in vm they could use. */
108 memset(final, 0, sizeof(final));
109
110 /* Then something really weird... */
111 for (int i = pwl; i; i >>= 1) {
112 if (i & 1)
113 md5_append(&ctx, final, 1);
114 else
115 md5_append(&ctx, (const md5_byte_t *)pw, 1);
116 }
117
118 /* Now make the output string */
119 strncpy(buf, id, buflen);
120 strncat(buf, (const char *)sp, sl);
121 strcat(buf, "$");
122
123 md5_finish(&ctx, final);
124
125 /*
126 * and now, just to make sure things don't run too fast
127 * On a 60 Mhz Pentium this takes 34 msec, so you would
128 * need 30 seconds to build a 1000 entry dictionary...
129 */
130 for (int i = 0; i < 1000; i++) {
131 md5_init(&ctx1);
132 if (i & 1)
133 md5_append(&ctx1, (const md5_byte_t *)pw, pwl);
134 else
135 md5_append(&ctx1, final, 16);
136
137 if (i % 3)
138 md5_append(&ctx1, sp, sl);
139
140 if (i % 7)
141 md5_append(&ctx1, (const md5_byte_t *)pw, pwl);
142
143 if (i & 1)
144 md5_append(&ctx1, final, 16);
145 else
146 md5_append(&ctx1, (const md5_byte_t *)pw, pwl);
147 md5_finish(&ctx1, final);
148 }
149
150 p = buf + strlen(buf);
151
152 l = (final[ 0] << 16) | (final[ 6] << 8) | final[12]; to64(p, l, 4); p += 4;
153 l = (final[ 1] << 16) | (final[ 7] << 8) | final[13]; to64(p, l, 4); p += 4;
154 l = (final[ 2] << 16) | (final[ 8] << 8) | final[14]; to64(p, l, 4); p += 4;
155 l = (final[ 3] << 16) | (final[ 9] << 8) | final[15]; to64(p, l, 4); p += 4;
156 l = (final[ 4] << 16) | (final[10] << 8) | final[ 5]; to64(p, l, 4); p += 4;
157 l = final[11] ; to64(p, l, 2); p += 2;
158 *p = '\0';
159
160 /* Don't leave anything around in vm they could use. */
161 memset(final, 0, sizeof(final));
162
163 return buf;
164 }
165
166