00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "postgres.h"
00010
00011 #include "px.h"
00012 #include "px-crypt.h"
00013
00014 #define MD5_SIZE 16
00015
00016 static const char _crypt_a64[] =
00017 "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
00018
00019 static void
00020 _crypt_to64(char *s, unsigned long v, int n)
00021 {
00022 while (--n >= 0)
00023 {
00024 *s++ = _crypt_a64[v & 0x3f];
00025 v >>= 6;
00026 }
00027 }
00028
00029
00030
00031
00032
00033 char *
00034 px_crypt_md5(const char *pw, const char *salt, char *passwd, unsigned dstlen)
00035 {
00036 static char *magic = "$1$";
00037
00038
00039 static char *p;
00040 static const char *sp,
00041 *ep;
00042 unsigned char final[MD5_SIZE];
00043 int sl,
00044 pl,
00045 i;
00046 PX_MD *ctx,
00047 *ctx1;
00048 int err;
00049 unsigned long l;
00050
00051 if (!passwd || dstlen < 120)
00052 return NULL;
00053
00054
00055 sp = salt;
00056
00057
00058 if (strncmp(sp, magic, strlen(magic)) == 0)
00059 sp += strlen(magic);
00060
00061
00062 for (ep = sp; *ep && *ep != '$' && ep < (sp + 8); ep++)
00063 continue;
00064
00065
00066 sl = ep - sp;
00067
00068
00069 err = px_find_digest("md5", &ctx);
00070 if (err)
00071 return NULL;
00072 err = px_find_digest("md5", &ctx1);
00073
00074
00075 px_md_update(ctx, (const uint8 *) pw, strlen(pw));
00076
00077
00078 px_md_update(ctx, (uint8 *) magic, strlen(magic));
00079
00080
00081 px_md_update(ctx, (const uint8 *) sp, sl);
00082
00083
00084 px_md_update(ctx1, (const uint8 *) pw, strlen(pw));
00085 px_md_update(ctx1, (const uint8 *) sp, sl);
00086 px_md_update(ctx1, (const uint8 *) pw, strlen(pw));
00087 px_md_finish(ctx1, final);
00088 for (pl = strlen(pw); pl > 0; pl -= MD5_SIZE)
00089 px_md_update(ctx, final, pl > MD5_SIZE ? MD5_SIZE : pl);
00090
00091
00092 memset(final, 0, sizeof final);
00093
00094
00095 for (i = strlen(pw); i; i >>= 1)
00096 if (i & 1)
00097 px_md_update(ctx, final, 1);
00098 else
00099 px_md_update(ctx, (const uint8 *) pw, 1);
00100
00101
00102 strcpy(passwd, magic);
00103 strncat(passwd, sp, sl);
00104 strcat(passwd, "$");
00105
00106 px_md_finish(ctx, final);
00107
00108
00109
00110
00111
00112
00113 for (i = 0; i < 1000; i++)
00114 {
00115 px_md_reset(ctx1);
00116 if (i & 1)
00117 px_md_update(ctx1, (const uint8 *) pw, strlen(pw));
00118 else
00119 px_md_update(ctx1, final, MD5_SIZE);
00120
00121 if (i % 3)
00122 px_md_update(ctx1, (const uint8 *) sp, sl);
00123
00124 if (i % 7)
00125 px_md_update(ctx1, (const uint8 *) pw, strlen(pw));
00126
00127 if (i & 1)
00128 px_md_update(ctx1, final, MD5_SIZE);
00129 else
00130 px_md_update(ctx1, (const uint8 *) pw, strlen(pw));
00131 px_md_finish(ctx1, final);
00132 }
00133
00134 p = passwd + strlen(passwd);
00135
00136 l = (final[0] << 16) | (final[6] << 8) | final[12];
00137 _crypt_to64(p, l, 4);
00138 p += 4;
00139 l = (final[1] << 16) | (final[7] << 8) | final[13];
00140 _crypt_to64(p, l, 4);
00141 p += 4;
00142 l = (final[2] << 16) | (final[8] << 8) | final[14];
00143 _crypt_to64(p, l, 4);
00144 p += 4;
00145 l = (final[3] << 16) | (final[9] << 8) | final[15];
00146 _crypt_to64(p, l, 4);
00147 p += 4;
00148 l = (final[4] << 16) | (final[10] << 8) | final[5];
00149 _crypt_to64(p, l, 4);
00150 p += 4;
00151 l = final[11];
00152 _crypt_to64(p, l, 2);
00153 p += 2;
00154 *p = '\0';
00155
00156
00157 memset(final, 0, sizeof final);
00158
00159 px_md_free(ctx1);
00160 px_md_free(ctx);
00161
00162 return passwd;
00163 }