mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-08-31 07:57:31 +02:00
The basic rule we follow here is to always first include 'postgres.h' or 'postgres_fe.h' whichever is applicable, then system header includes and then Postgres header includes. In this, we also follow that all the Postgres header includes are in order based on their ASCII value. We generally follow these rules, but the code has deviated in many places. This commit makes it consistent just for contrib modules. The later commits will enforce similar rules in other parts of code. Author: Vignesh C Reviewed-by: Amit Kapila Discussion: https://postgr.es/m/CALDaNm2Sznv8RR6Ex-iJO6xAdsxgWhCoETkaYX=+9DW3q0QCfA@mail.gmail.com
164 lines
3.6 KiB
C
164 lines
3.6 KiB
C
/*
|
|
* File imported from FreeBSD, original by Poul-Henning Kamp.
|
|
*
|
|
* $FreeBSD: src/lib/libcrypt/crypt-md5.c,v 1.5 1999/12/17 20:21:45 peter Exp $
|
|
*
|
|
* contrib/pgcrypto/crypt-md5.c
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
#include "px-crypt.h"
|
|
#include "px.h"
|
|
|
|
#define MD5_SIZE 16
|
|
|
|
static const char _crypt_a64[] =
|
|
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
|
|
static void
|
|
_crypt_to64(char *s, unsigned long v, int n)
|
|
{
|
|
while (--n >= 0)
|
|
{
|
|
*s++ = _crypt_a64[v & 0x3f];
|
|
v >>= 6;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* UNIX password
|
|
*/
|
|
|
|
char *
|
|
px_crypt_md5(const char *pw, const char *salt, char *passwd, unsigned dstlen)
|
|
{
|
|
static char *magic = "$1$"; /* This string is magic for this algorithm.
|
|
* Having it this way, we can get better later
|
|
* on */
|
|
static char *p;
|
|
static const char *sp,
|
|
*ep;
|
|
unsigned char final[MD5_SIZE];
|
|
int sl,
|
|
pl,
|
|
i;
|
|
PX_MD *ctx,
|
|
*ctx1;
|
|
int err;
|
|
unsigned long l;
|
|
|
|
if (!passwd || dstlen < 120)
|
|
return NULL;
|
|
|
|
/* Refine the Salt first */
|
|
sp = salt;
|
|
|
|
/* If it starts with the magic string, then skip that */
|
|
if (strncmp(sp, magic, strlen(magic)) == 0)
|
|
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;
|
|
|
|
/* */
|
|
err = px_find_digest("md5", &ctx);
|
|
if (err)
|
|
return NULL;
|
|
err = px_find_digest("md5", &ctx1);
|
|
|
|
/* The password first, since that is what is most unknown */
|
|
px_md_update(ctx, (const uint8 *) pw, strlen(pw));
|
|
|
|
/* Then our magic string */
|
|
px_md_update(ctx, (uint8 *) magic, strlen(magic));
|
|
|
|
/* Then the raw salt */
|
|
px_md_update(ctx, (const uint8 *) sp, sl);
|
|
|
|
/* Then just as many characters of the MD5(pw,salt,pw) */
|
|
px_md_update(ctx1, (const uint8 *) pw, strlen(pw));
|
|
px_md_update(ctx1, (const uint8 *) sp, sl);
|
|
px_md_update(ctx1, (const uint8 *) pw, strlen(pw));
|
|
px_md_finish(ctx1, final);
|
|
for (pl = strlen(pw); pl > 0; pl -= MD5_SIZE)
|
|
px_md_update(ctx, final, pl > MD5_SIZE ? MD5_SIZE : pl);
|
|
|
|
/* Don't leave anything around in vm they could use. */
|
|
px_memset(final, 0, sizeof final);
|
|
|
|
/* Then something really weird... */
|
|
for (i = strlen(pw); i; i >>= 1)
|
|
if (i & 1)
|
|
px_md_update(ctx, final, 1);
|
|
else
|
|
px_md_update(ctx, (const uint8 *) pw, 1);
|
|
|
|
/* Now make the output string */
|
|
strcpy(passwd, magic);
|
|
strncat(passwd, sp, sl);
|
|
strcat(passwd, "$");
|
|
|
|
px_md_finish(ctx, final);
|
|
|
|
/*
|
|
* 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++)
|
|
{
|
|
px_md_reset(ctx1);
|
|
if (i & 1)
|
|
px_md_update(ctx1, (const uint8 *) pw, strlen(pw));
|
|
else
|
|
px_md_update(ctx1, final, MD5_SIZE);
|
|
|
|
if (i % 3)
|
|
px_md_update(ctx1, (const uint8 *) sp, sl);
|
|
|
|
if (i % 7)
|
|
px_md_update(ctx1, (const uint8 *) pw, strlen(pw));
|
|
|
|
if (i & 1)
|
|
px_md_update(ctx1, final, MD5_SIZE);
|
|
else
|
|
px_md_update(ctx1, (const uint8 *) pw, strlen(pw));
|
|
px_md_finish(ctx1, final);
|
|
}
|
|
|
|
p = passwd + strlen(passwd);
|
|
|
|
l = (final[0] << 16) | (final[6] << 8) | final[12];
|
|
_crypt_to64(p, l, 4);
|
|
p += 4;
|
|
l = (final[1] << 16) | (final[7] << 8) | final[13];
|
|
_crypt_to64(p, l, 4);
|
|
p += 4;
|
|
l = (final[2] << 16) | (final[8] << 8) | final[14];
|
|
_crypt_to64(p, l, 4);
|
|
p += 4;
|
|
l = (final[3] << 16) | (final[9] << 8) | final[15];
|
|
_crypt_to64(p, l, 4);
|
|
p += 4;
|
|
l = (final[4] << 16) | (final[10] << 8) | final[5];
|
|
_crypt_to64(p, l, 4);
|
|
p += 4;
|
|
l = final[11];
|
|
_crypt_to64(p, l, 2);
|
|
p += 2;
|
|
*p = '\0';
|
|
|
|
/* Don't leave anything around in vm they could use. */
|
|
px_memset(final, 0, sizeof final);
|
|
|
|
px_md_free(ctx1);
|
|
px_md_free(ctx);
|
|
|
|
return passwd;
|
|
}
|