Thus spake Tom Lane
> [EMAIL PROTECTED] (D'Arcy J.M. Cain) writes:
> > Any ideas?
> 
> Not with that much info.  Sooner or later you're going to have to
> show us your C code...

Oh, sure.  I was going to submit it to contrib when it was finished and
as I said, the fprintf test I added pretty much assures me that it isn't
in the code but just in case I am wrong, here it is.


/*
 * PostgreSQL type definitions for chkpass
 * Written by D'Arcy J.M. Cain
 * [EMAIL PROTECTED]
 * http://www.druid.net/darcy/
 *
 * $Id$
 * best viewed with tabs set to 4
 */

#include <stdio.h>
#include <string.h>
#include <time.h>
#include <unistd.h>

#include <postgres.h>
#include <utils/palloc.h>

/*
 * This type encrypts it's input unless the first character is a colon.
 * The output is the encrypted form with a leading colon.  The output
 * format is designed to allow dump and reload operations to work as
 * expected without doing special tricks.
 */


/*
 * This is the internal storage format for CHKPASSs.
 * 15 is all I need but add a little buffer
 */

typedef struct chkpass
{
        char    password[16];
}                       chkpass;

/*
 * Various forward declarations:
 */

chkpass    *chkpass_in(char *str);
char       *chkpass_out(chkpass * addr);
char       *chkpass_rout(chkpass * addr);

/* Only equal or not equal make sense */
bool            chkpass_eq(chkpass * a1, text * a2);
bool            chkpass_ne(chkpass * a1, text * a2);

/* This function checks that the password is a good one
 * It's just a placeholder for now */
static int
verify_pass(const char *str)
{
        return 0;
}

/*
 * CHKPASS reader.
 */
chkpass *
chkpass_in(char *str)
{
        chkpass    *result;
        char            mysalt[4];
        static bool     random_initialized = false;
        static char salt_chars[] =
                "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

        /* special case to let us enter encrypted passwords */
        if (*str == ':')
        {
                result = (chkpass *) palloc(sizeof(chkpass));
                strncpy(result->password, str + 1, 13);
                result->password[13] = 0;
                return (result);
        }

        if (verify_pass(str) != 0)
        {
                elog(ERROR, "chkpass_in: purported CHKPASS \"%s\" is a weak password",
                     str);
                return NULL;
        }

        result = (chkpass *) palloc(sizeof(chkpass));

        if (!random_initialized)
        {
                srandom((unsigned int) time(NULL));
                random_initialized = true;
        }

        mysalt[0] = salt_chars[random() & 0x3f];
        mysalt[1] = salt_chars[random() & 0x3f];
        mysalt[2] = 0;                          /* technically the terminator is not
                                                                 * necessary but I 
like to play safe */
        strcpy(result->password, crypt(str, mysalt));
        return (result);
}

/*
 * CHKPASS output function.
 * Just like any string but we know it is max 15 (13 plus colon and terminator.)
 */

char *
chkpass_out(chkpass * password)
{
        char       *result;

        if (password == NULL)
                return (NULL);

        if ((result = (char *) palloc(16)) != NULL)
        {
                result[0] = ':';
                strcpy(result + 1, password->password);
        }

        return (result);
}


/*
 * special output function that doesn't output the colon
 */

char *
chkpass_rout(chkpass *password)
{
        char       *result;

        if (password == NULL)
                return (NULL);

        if ((result = (char *) palloc(16)) != NULL)
                strcpy(result, password->password);

        return (result);
}


/*
 * Boolean tests
 */

bool
chkpass_eq(chkpass * a1, text *a2)
{
        char    str[10];
        int             sz = 8;

        if (a2->vl_len < 8) sz = a2->vl_len;
        if (!a1 || !a2) return 0;
        strncpy(str, a2->vl_dat, sz);
        str[sz] = 0;
        return (strcmp(a1->password, crypt(str, a1->password)) == 0);
}

bool
chkpass_ne(chkpass * a1, text *a2)
{
        char    str[10];
        int             sz = 8;

        if (!a1 || !a2) return 0;
        if (a2->vl_len < 8) sz = a2->vl_len;
        strncpy(str, a2->vl_dat, sz);
        str[sz] = 0;
        return (strcmp(a1->password, crypt(str, a1->password)) != 0);
}


-- 
D'Arcy J.M. Cain <darcy@{druid|vex}.net>   |  Democracy is three wolves
http://www.druid.net/darcy/                |  and a sheep voting on
+1 416 425 1212     (DoD#0082)    (eNTP)   |  what's for dinner.

Reply via email to