]> git.8kb.co.uk Git - pgpool-ii/pgpool-ii_2.2.5/blob - md5.c
Attempt to send a proper failure message to frontend when authentication
[pgpool-ii/pgpool-ii_2.2.5] / md5.c
1 /*
2  *      md5.c
3  *
4  *      Implements      the  MD5 Message-Digest Algorithm as specified in
5  *      RFC  1321.      This  implementation  is a simple one, in that it
6  *      needs  every  input  byte  to  be  buffered  before doing any
7  *      calculations.  I  do  not  expect  this  file  to be used for
8  *      general  purpose  MD5'ing  of large amounts of data, only for
9  *      generating hashed passwords from limited input.
10  *
11  *      Sverre H. Huseby <sverrehu@online.no>
12  *
13  *      Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
14  *      Portions Copyright (c) 1994, Regents of the University of California
15  *
16  *  This file is imported from PostgreSQL 8.1.3., and modified by
17  *  Taiki Yamaguchi <yamaguchi@sraoss.co.jp>
18  *
19  * IDENTIFICATION
20  *      $Header: /cvsroot/pgpool/pgpool-II/md5.c,v 1.1.1.1.6.1 2009/08/22 04:19:49 t-ishii Exp $
21  */
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27
28 #include "md5.h"
29
30 typedef unsigned char uint8;    /* == 8 bits */
31 typedef unsigned int uint32;    /* == 32 bits */
32
33 #define S11 7
34 #define S12 12
35 #define S13 17
36 #define S14 22
37 #define S21 5
38 #define S22 9
39 #define S23 14
40 #define S24 20
41 #define S31 4
42 #define S32 11
43 #define S33 16
44 #define S34 23
45 #define S41 6
46 #define S42 10
47 #define S43 15
48 #define S44 21
49
50 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
51 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
52 #define H(x, y, z) ((x) ^ (y) ^ (z))
53 #define I(x, y, z) ((y) ^ ((x) | (~z)))
54
55 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
56
57 #define FF(a, b, c, d, x, s, ac) { \
58 (a) += F((b), (c), (d)) + (x) + (uint32)(ac); \
59 (a) = ROTATE_LEFT((a), (s)); \
60 (a) += (b); \
61 }
62
63 #define GG(a, b, c, d, x, s, ac) { \
64 (a) += G((b), (c), (d)) + (x) + (uint32)(ac); \
65 (a) = ROTATE_LEFT((a), (s)); \
66 (a) += (b); \
67 }
68
69 #define HH(a, b, c, d, x, s, ac) { \
70 (a) += H((b), (c), (d)) + (x) + (uint32)(ac); \
71 (a) = ROTATE_LEFT((a), (s)); \
72 (a) += (b); \
73 }
74
75 #define II(a, b, c, d, x, s, ac) { \
76 (a) += I((b), (c), (d)) + (x) + (uint32)(ac); \
77 (a) = ROTATE_LEFT((a), (s)); \
78 (a) += (b); \
79 }
80
81 const uint32 T[64] =
82 {
83         0xd76aa478,     0xe8c7b756,     0x242070db,     0xc1bdceee,     0xf57c0faf,     0x4787c62a,     0xa8304613,     0xfd469501,
84         0x698098d8,     0x8b44f7af,     0xffff5bb1,     0x895cd7be,     0x6b901122,     0xfd987193,     0xa679438e,     0x49b40821,
85
86         0xf61e2562,     0xc040b340,     0x265e5a51,     0xe9b6c7aa,     0xd62f105d,     0x02441453,     0xd8a1e681,     0xe7d3fbc8,
87         0x21e1cde6,     0xc33707d6,     0xf4d50d87,     0x455a14ed,     0xa9e3e905,     0xfcefa3f8,     0x676f02d9,     0x8d2a4c8a,
88
89         0xfffa3942,     0x8771f681,     0x6d9d6122,     0xfde5380c,     0xa4beea44,     0x4bdecfa9,     0xf6bb4b60,     0xbebfbc70,
90         0x289b7ec6,     0xeaa127fa,     0xd4ef3085,     0x04881d05,     0xd9d4d039,     0xe6db99e5,     0x1fa27cf8,     0xc4ac5665,
91
92         0xf4292244,     0x432aff97,     0xab9423a7,     0xfc93a039,     0x655b59c3,     0x8f0ccc92,     0xffeff47d,     0x85845dd1,
93         0x6fa87e4f,     0xfe2ce6e0,     0xa3014314,     0x4e0811a1,     0xf7537e82,     0xbd3af235,     0x2ad7d2bb,     0xeb86d391
94 };
95
96
97 /*
98  *      PRIVATE FUNCTIONS
99  */
100
101
102 /*
103  *      The returned array is allocated using malloc.  the caller should free it
104  *      when it is no longer needed.
105  */
106 static uint8 *
107 createPaddedCopyWithLength(uint8 *b, uint32 *l)
108 {
109         /*
110          * uint8 *b  - message to be digested
111          * uint32 *l - length of b
112          */
113         uint8      *ret;
114         uint32          q;
115         uint32          len,
116                                 newLen448;
117         uint32          len_high,
118                                 len_low;                /* 64-bit value split into 32-bit sections */
119
120         len = ((b == NULL) ? 0 : *l);
121         newLen448 = len + 64 - (len % 64) - 8;
122         if (newLen448 <= len)
123                 newLen448 += 64;
124
125         *l = newLen448 + 8;
126         if ((ret = (uint8 *) malloc(sizeof(uint8) * *l)) == NULL)
127                 return NULL;
128
129         if (b != NULL)
130                 memcpy(ret, b, sizeof(uint8) * len);
131
132         /* pad */
133         ret[len] = 0x80;
134         for (q = len + 1; q < newLen448; q++)
135                 ret[q] = 0x00;
136
137         /* append length as a 64 bit bitcount */
138         len_low = len;
139         /* split into two 32-bit values */
140         /* we only look at the bottom 32-bits */
141         len_high = len >> 29;
142         len_low <<= 3;
143         q = newLen448;
144         ret[q++] = (len_low & 0xff);
145         len_low >>= 8;
146         ret[q++] = (len_low & 0xff);
147         len_low >>= 8;
148         ret[q++] = (len_low & 0xff);
149         len_low >>= 8;
150         ret[q++] = (len_low & 0xff);
151         ret[q++] = (len_high & 0xff);
152         len_high >>= 8;
153         ret[q++] = (len_high & 0xff);
154         len_high >>= 8;
155         ret[q++] = (len_high & 0xff);
156         len_high >>= 8;
157         ret[q] = (len_high & 0xff);
158
159         return ret;
160 }
161
162 static void
163 doTheRounds(uint32 X[16], uint32 state[4])
164 {
165         uint32          a,
166                                 b,
167                                 c,
168                                 d;
169
170         a = state[0];
171         b = state[1];
172         c = state[2];
173         d = state[3];
174
175         /* round 1 */
176         FF(a, b, c, d, X[ 0], S11, T[ 0]);
177         FF(d, a, b, c, X[ 1], S12, T[ 1]);
178         FF(c, d, a, b, X[ 2], S13, T[ 2]);
179         FF(b, c, d, a, X[ 3], S14, T[ 3]);
180         FF(a, b, c, d, X[ 4], S11, T[ 4]);
181         FF(d, a, b, c, X[ 5], S12, T[ 5]);
182         FF(c, d, a, b, X[ 6], S13, T[ 6]);
183         FF(b, c, d, a, X[ 7], S14, T[ 7]);
184         FF(a, b, c, d, X[ 8], S11, T[ 8]);
185         FF(d, a, b, c, X[ 9], S12, T[ 9]);
186         FF(c, d, a, b, X[10], S13, T[10]);
187         FF(b, c, d, a, X[11], S14, T[11]);
188         FF(a, b, c, d, X[12], S11, T[12]);
189         FF(d, a, b, c, X[13], S12, T[13]);
190         FF(c, d, a, b, X[14], S13, T[14]);
191         FF(b, c, d, a, X[15], S14, T[15]);
192
193         GG(a, b, c, d, X[ 1], S21, T[16]);
194         GG(d, a, b, c, X[ 6], S22, T[17]);
195         GG(c, d, a, b, X[11], S23, T[18]);
196         GG(b, c, d, a, X[ 0], S24, T[19]);
197         GG(a, b, c, d, X[ 5], S21, T[20]);
198         GG(d, a, b, c, X[10], S22, T[21]);
199         GG(c, d, a, b, X[15], S23, T[22]);
200         GG(b, c, d, a, X[ 4], S24, T[23]);
201         GG(a, b, c, d, X[ 9], S21, T[24]);
202         GG(d, a, b, c, X[14], S22, T[25]);
203         GG(c, d, a, b, X[ 3], S23, T[26]);
204         GG(b, c, d, a, X[ 8], S24, T[27]);
205         GG(a, b, c, d, X[13], S21, T[28]);
206         GG(d, a, b, c, X[ 2], S22, T[29]);
207         GG(c, d, a, b, X[ 7], S23, T[30]);
208         GG(b, c, d, a, X[12], S24, T[31]);
209
210         HH(a, b, c, d, X[ 5], S31, T[32]);
211         HH(d, a, b, c, X[ 8], S32, T[33]);
212         HH(c, d, a, b, X[11], S33, T[34]);
213         HH(b, c, d, a, X[14], S34, T[35]);
214         HH(a, b, c, d, X[ 1], S31, T[36]);
215         HH(d, a, b, c, X[ 4], S32, T[37]);
216         HH(c, d, a, b, X[ 7], S33, T[38]);
217         HH(b, c, d, a, X[10], S34, T[39]);
218         HH(a, b, c, d, X[13], S31, T[40]);
219         HH(d, a, b, c, X[ 0], S32, T[41]);
220         HH(c, d, a, b, X[ 3], S33, T[42]);
221         HH(b, c, d, a, X[ 6], S34, T[43]);
222         HH(a, b, c, d, X[ 9], S31, T[44]);
223         HH(d, a, b, c, X[12], S32, T[45]);
224         HH(c, d, a, b, X[15], S33, T[46]);
225         HH(b, c, d, a, X[ 2], S34, T[47]);
226
227         II(a, b, c, d, X[ 0], S41, T[48]);
228         II(d, a, b, c, X[ 7], S42, T[49]);
229         II(c, d, a, b, X[14], S43, T[50]);
230         II(b, c, d, a, X[ 5], S44, T[51]);
231         II(a, b, c, d, X[12], S41, T[52]);
232         II(d, a, b, c, X[ 3], S42, T[53]);
233         II(c, d, a, b, X[10], S43, T[54]);
234         II(b, c, d, a, X[ 1], S44, T[55]);
235         II(a, b, c, d, X[ 8], S41, T[56]);
236         II(d, a, b, c, X[15], S42, T[57]);
237         II(c, d, a, b, X[ 6], S43, T[58]);
238         II(b, c, d, a, X[13], S44, T[59]);
239         II(a, b, c, d, X[ 4], S41, T[60]);
240         II(d, a, b, c, X[11], S42, T[61]);
241         II(c, d, a, b, X[ 2], S43, T[62]);
242         II(b, c, d, a, X[ 9], S44, T[63]);
243
244         state[0] += a;
245         state[1] += b;
246         state[2] += c;
247         state[3] += d;
248 }
249
250 static int
251 calculateDigestFromBuffer(uint8 *b, uint32 len, uint8 sum[16])
252 {
253         /*
254          * uint8 *b      - message to be digested
255          * uint32 len    - length of b
256          * uint8 sum[16] - md5 digest calculated from b
257          */
258
259         register uint32 i,
260                                 j,
261                                 k,
262                                 newI;
263         uint32          l;
264         uint8      *input;
265         register uint32 *wbp;
266         uint32          workBuff[16],
267                                 state[4];
268
269         l = len;
270
271         state[0] = 0x67452301;
272         state[1] = 0xEFCDAB89;
273         state[2] = 0x98BADCFE;
274         state[3] = 0x10325476;
275
276         if ((input = createPaddedCopyWithLength(b, &l)) == NULL)
277                 return 0;
278
279         for (i = 0;;)
280         {
281                 if ((newI = i + 16 * 4) > l)
282                         break;
283                 k = i + 3;
284                 for (j = 0; j < 16; j++)
285                 {
286                         wbp = (workBuff + j);
287                         *wbp = input[k--];
288                         *wbp <<= 8;
289                         *wbp |= input[k--];
290                         *wbp <<= 8;
291                         *wbp |= input[k--];
292                         *wbp <<= 8;
293                         *wbp |= input[k];
294                         k += 7;
295                 }
296                 doTheRounds(workBuff, state);
297                 i = newI;
298         }
299         free(input);
300
301         j = 0;
302         for (i = 0; i < 4; i++)
303         {
304                 k = state[i];
305                 sum[j++] = (k & 0xff);
306                 k >>= 8;
307                 sum[j++] = (k & 0xff);
308                 k >>= 8;
309                 sum[j++] = (k & 0xff);
310                 k >>= 8;
311                 sum[j++] = (k & 0xff);
312         }
313         return 1;
314 }
315
316 static void
317 bytesToHex(uint8 b[16], char *s)
318 {
319         static const char *hex = "0123456789abcdef";
320         int                     q,
321                                 w;
322
323         for (q = 0, w = 0; q < 16; q++)
324         {
325                 s[w++] = hex[(b[q] >> 4) & 0x0F];
326                 s[w++] = hex[b[q] & 0x0F];
327         }
328         s[w] = '\0';
329 }
330
331 /*
332  *      PUBLIC FUNCTIONS
333  */
334
335 /*
336  *      pool_md5_hash
337  *
338  *      Calculates the MD5 sum of the bytes in a buffer.
339  *
340  *      SYNOPSIS          int pool_md5_hash(const void *buff, size_t len, char *hexsum)
341  *
342  *      INPUT             buff    the buffer containing the bytes that you want
343  *                                                the MD5 sum of.
344  *                                len     number of bytes in the buffer.
345  *
346  *      OUTPUT            hexsum  the MD5 sum as a '\0'-terminated string of
347  *                                                hexadecimal digits.  an MD5 sum is 16 bytes long.
348  *                                                each byte is represented by two heaxadecimal
349  *                                                characters.  you thus need to provide an array
350  *                                                of 33 characters, including the trailing '\0'.
351  *
352  *      RETURNS           false on failure (out of memory for internal buffers) or
353  *                                true on success.
354  *
355  *      STANDARDS         MD5 is described in RFC 1321.
356  *
357  *      AUTHOR            Sverre H. Huseby <sverrehu@online.no>
358  *  MODIFIED by   Taiki Yamaguchi <yamaguchi@sraoss.co.jp>
359  *
360  */
361 int
362 pool_md5_hash(const void *buff, size_t len, char *hexsum)
363 {
364         uint8           sum[16];
365
366         if (!calculateDigestFromBuffer((uint8 *) buff, len, sum))
367                 return 0;                               /* failed */
368
369         bytesToHex(sum, hexsum);
370         return 1;                                       /* success */
371 }
372
373 /*
374  * Computes MD5 checksum of "passwd" (a null-terminated string) followed
375  * by "salt" (which need not be null-terminated).
376  *
377  * Output format is a 32-hex-digit MD5 checksum.
378  * Hence, the output buffer "buf" must be at least 33 bytes long.
379  *
380  * Returns 1 if okay, 0 on error (out of memory).
381  */
382 int
383 pool_md5_encrypt(const char *passwd, const char *salt, size_t salt_len,
384                            char *buf)
385 {
386         size_t passwd_len = strlen(passwd);
387         char *crypt_buf = malloc(passwd_len + salt_len);
388         int ret;
389
390         if (!crypt_buf)
391                 return 0;                               /* failed */
392
393         /*
394          * Place salt at the end because it may be known by users trying to crack
395          * the MD5 output.
396          */
397         strcpy(crypt_buf, passwd);
398         memcpy(crypt_buf + passwd_len, salt, salt_len);
399
400         ret = pool_md5_hash(crypt_buf, passwd_len + salt_len, buf);
401
402         free(crypt_buf);
403
404         return ret;
405 }