mirror of https://github.com/postgres/postgres
Initial checkin of a contributed type that handles passwords efficiently.
This commit is contained in:
parent
4ad073cf4c
commit
b95ff0c542
|
@ -0,0 +1,47 @@
|
|||
#
|
||||
# $Header: /cvsroot/pgsql/contrib/chkpass/Makefile,v 1.1 2001/05/03 12:32:13 darcy Exp $
|
||||
#
|
||||
|
||||
subdir = contrib/chkpass
|
||||
top_builddir = ../..
|
||||
include $(top_builddir)/src/Makefile.global
|
||||
|
||||
NAME := chkpass
|
||||
SONAME := $(NAME)$(DLSUFFIX)
|
||||
|
||||
SQLS = $(NAME).sql
|
||||
MODS = $(NAME)$(DLSUFFIX)
|
||||
|
||||
override CPPFLAGS := -I$(srcdir) $(CPPFLAGS)
|
||||
override CFLAGS += $(CFLAGS_SL)
|
||||
|
||||
ifdef REFINT_VERBOSE
|
||||
override CPPFLAGS+= -DREFINT_VERBOSE
|
||||
endif
|
||||
|
||||
all: $(SONAME) $(NAME).sql
|
||||
|
||||
$(NAME).sql: $(NAME).sql.in
|
||||
sed -e 's:MODULE_PATHNAME:$(libdir)/contrib/$(SONAME):g' < $< > $@
|
||||
|
||||
install: all installdirs
|
||||
$(INSTALL_SHLIB) $(SONAME) $(libdir)/contrib
|
||||
$(INSTALL_DATA) README.$(NAME) $(docdir)/contrib
|
||||
sed "s+%%PGDIR%%+$(libdir)+g" < chkpass.sql > $(datadir)/contrib
|
||||
|
||||
installdirs:
|
||||
$(mkinstalldirs) $(libdir)/contrib $(docdir)/contrib $(datadir)/contrib
|
||||
|
||||
uninstall:
|
||||
rm -f $(libdir)/contrib/$(SONAME) $(docdir)/contrib/README.$(NAME) \
|
||||
$(addprefix $(datadir)/contrib/, $(NAME).sql)
|
||||
|
||||
clean distclean maintainer-clean:
|
||||
rm -f $(SONAME) $(NAME).sql
|
||||
|
||||
depend dep:
|
||||
$(CC) -MM -MG $(CFLAGS) *.c > depend
|
||||
|
||||
ifeq (depend,$(wildcard depend))
|
||||
include depend
|
||||
endif
|
|
@ -0,0 +1,22 @@
|
|||
$Header: /cvsroot/pgsql/contrib/chkpass/Attic/README.chkpass,v 1.1 2001/05/03 12:32:13 darcy Exp $
|
||||
|
||||
Chkpass is a password type that is automatically checked and converted upon
|
||||
entry. It is stored encrypted. To compare, simply compare agains a clear
|
||||
text password and the comparison function will encrypt it before comparing.
|
||||
It also returns an error if the code determines that the password is easily
|
||||
crackable. This is currently a stub that does nothing.
|
||||
|
||||
I haven't worried about making this type indexable. I doubt that anyone
|
||||
would ever need to sort a file in order of encrypted password.
|
||||
|
||||
If you precede the string with a colon, the encryption and checking are
|
||||
skipped so that you can enter existing passwords into the field.
|
||||
|
||||
On output, a colon is prepended. This makes it possible to dump and reload
|
||||
passwords without re-encrypting them. If you want the password (encrypted)
|
||||
without the colon then use the raw() function. This allows you to use the
|
||||
type with things like Apache's Auth_PostgreSQL module.
|
||||
|
||||
D'Arcy J.M. Cain
|
||||
darcy@druid.net
|
||||
|
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
* PostgreSQL type definitions for chkpass
|
||||
* Written by D'Arcy J.M. Cain
|
||||
* darcy@druid.net
|
||||
* http://www.druid.net/darcy/
|
||||
*
|
||||
* $Header: /cvsroot/pgsql/contrib/chkpass/chkpass.c,v 1.1 2001/05/03 12:32:13 darcy Exp $
|
||||
* 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);
|
||||
text *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
|
||||
*/
|
||||
|
||||
text *
|
||||
chkpass_rout(chkpass *password)
|
||||
{
|
||||
text *result = NULL;
|
||||
|
||||
if (password == NULL)
|
||||
return (NULL);
|
||||
|
||||
if ((result = (text *) palloc(VARHDRSZ + 16)) != NULL)
|
||||
{
|
||||
VARSIZE(result) = VARHDRSZ + strlen(password->password);
|
||||
memcpy(VARDATA(result), password->password, strlen(password->password));
|
||||
}
|
||||
|
||||
return (result);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Boolean tests
|
||||
*/
|
||||
|
||||
bool
|
||||
chkpass_eq(chkpass * a1, text *a2)
|
||||
{
|
||||
char str[10];
|
||||
int sz = 8;
|
||||
|
||||
if (!a1 || !a2) return 0;
|
||||
if (a2->vl_len < 12) sz = a2->vl_len - 4;
|
||||
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 < 12) sz = a2->vl_len - 4;
|
||||
strncpy(str, a2->vl_dat, sz);
|
||||
str[sz] = 0;
|
||||
return (strcmp(a1->password, crypt(str, a1->password)) != 0);
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
--
|
||||
-- PostgreSQL code for CHKPASS.
|
||||
-- Written by D'Arcy J.M. Cain
|
||||
-- darcy@druid.net
|
||||
-- http://www.druid.net/darcy/
|
||||
--
|
||||
-- $Header: /cvsroot/pgsql/contrib/chkpass/Attic/chkpass.sql,v 1.1 2001/05/03 12:32:13 darcy Exp $
|
||||
-- best viewed with tabs set to 4
|
||||
-- %%PGDIR%% changed to your local directory where modules is
|
||||
--
|
||||
|
||||
load '%%PGDIR%%/modules/chkpass.so';
|
||||
|
||||
--
|
||||
-- Input and output functions and the type itself:
|
||||
--
|
||||
|
||||
create function chkpass_in(opaque)
|
||||
returns opaque
|
||||
as '%%PGDIR%%/modules/chkpass.so'
|
||||
language 'c';
|
||||
|
||||
create function chkpass_out(opaque)
|
||||
returns opaque
|
||||
as '%%PGDIR%%/modules/chkpass.so'
|
||||
language 'c';
|
||||
|
||||
create type chkpass (
|
||||
internallength = 16,
|
||||
externallength = 13,
|
||||
input = chkpass_in,
|
||||
output = chkpass_out
|
||||
);
|
||||
|
||||
create function raw(chkpass)
|
||||
returns text
|
||||
as '%%PGDIR%%/modules/chkpass.so', 'chkpass_rout'
|
||||
language 'c';
|
||||
|
||||
--
|
||||
-- The various boolean tests:
|
||||
--
|
||||
|
||||
create function eq(chkpass, text)
|
||||
returns bool
|
||||
as '%%PGDIR%%/modules/chkpass.so', 'chkpass_eq'
|
||||
language 'c';
|
||||
|
||||
create function ne(chkpass, text)
|
||||
returns bool
|
||||
as '%%PGDIR%%/modules/chkpass.so', 'chkpass_ne'
|
||||
language 'c';
|
||||
|
||||
--
|
||||
-- Now the operators. Note how some of the parameters to some
|
||||
-- of the 'create operator' commands are commented out. This
|
||||
-- is because they reference as yet undefined operators, and
|
||||
-- will be implicitly defined when those are, further down.
|
||||
--
|
||||
|
||||
create operator = (
|
||||
leftarg = chkpass,
|
||||
rightarg = text,
|
||||
commutator = =,
|
||||
-- negator = <>,
|
||||
procedure = eq
|
||||
);
|
||||
|
||||
create operator <> (
|
||||
leftarg = chkpass,
|
||||
rightarg = text,
|
||||
negator = =,
|
||||
procedure = ne
|
||||
);
|
||||
|
||||
INSERT INTO pg_description (objoid, description)
|
||||
SELECT oid, 'password type with checks'
|
||||
FROM pg_type WHERE typname = 'chkpass';
|
||||
|
||||
--
|
||||
-- eof
|
||||
--
|
Loading…
Reference in New Issue