Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit b95ff0c

Browse files
committed
Initial checkin of a contributed type that handles passwords efficiently.
1 parent 4ad073c commit b95ff0c

File tree

4 files changed

+326
-0
lines changed

4 files changed

+326
-0
lines changed

contrib/chkpass/Makefile

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#
2+
# $Header: /cvsroot/pgsql/contrib/chkpass/Makefile,v 1.1 2001/05/03 12:32:13 darcy Exp $
3+
#
4+
5+
subdir = contrib/chkpass
6+
top_builddir = ../..
7+
include $(top_builddir)/src/Makefile.global
8+
9+
NAME := chkpass
10+
SONAME := $(NAME)$(DLSUFFIX)
11+
12+
SQLS = $(NAME).sql
13+
MODS = $(NAME)$(DLSUFFIX)
14+
15+
override CPPFLAGS := -I$(srcdir) $(CPPFLAGS)
16+
override CFLAGS += $(CFLAGS_SL)
17+
18+
ifdef REFINT_VERBOSE
19+
override CPPFLAGS+= -DREFINT_VERBOSE
20+
endif
21+
22+
all: $(SONAME) $(NAME).sql
23+
24+
$(NAME).sql: $(NAME).sql.in
25+
sed -e 's:MODULE_PATHNAME:$(libdir)/contrib/$(SONAME):g' < $< > $@
26+
27+
install: all installdirs
28+
$(INSTALL_SHLIB) $(SONAME) $(libdir)/contrib
29+
$(INSTALL_DATA) README.$(NAME) $(docdir)/contrib
30+
sed "s+%%PGDIR%%+$(libdir)+g" < chkpass.sql > $(datadir)/contrib
31+
32+
installdirs:
33+
$(mkinstalldirs) $(libdir)/contrib $(docdir)/contrib $(datadir)/contrib
34+
35+
uninstall:
36+
rm -f $(libdir)/contrib/$(SONAME) $(docdir)/contrib/README.$(NAME) \
37+
$(addprefix $(datadir)/contrib/, $(NAME).sql)
38+
39+
clean distclean maintainer-clean:
40+
rm -f $(SONAME) $(NAME).sql
41+
42+
depend dep:
43+
$(CC) -MM -MG $(CFLAGS) *.c > depend
44+
45+
ifeq (depend,$(wildcard depend))
46+
include depend
47+
endif

contrib/chkpass/README.chkpass

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
$Header: /cvsroot/pgsql/contrib/chkpass/Attic/README.chkpass,v 1.1 2001/05/03 12:32:13 darcy Exp $
2+
3+
Chkpass is a password type that is automatically checked and converted upon
4+
entry. It is stored encrypted. To compare, simply compare agains a clear
5+
text password and the comparison function will encrypt it before comparing.
6+
It also returns an error if the code determines that the password is easily
7+
crackable. This is currently a stub that does nothing.
8+
9+
I haven't worried about making this type indexable. I doubt that anyone
10+
would ever need to sort a file in order of encrypted password.
11+
12+
If you precede the string with a colon, the encryption and checking are
13+
skipped so that you can enter existing passwords into the field.
14+
15+
On output, a colon is prepended. This makes it possible to dump and reload
16+
passwords without re-encrypting them. If you want the password (encrypted)
17+
without the colon then use the raw() function. This allows you to use the
18+
type with things like Apache's Auth_PostgreSQL module.
19+
20+
D'Arcy J.M. Cain
21+
darcy@druid.net
22+

contrib/chkpass/chkpass.c

+175
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/*
2+
* PostgreSQL type definitions for chkpass
3+
* Written by D'Arcy J.M. Cain
4+
* darcy@druid.net
5+
* http://www.druid.net/darcy/
6+
*
7+
* $Header: /cvsroot/pgsql/contrib/chkpass/chkpass.c,v 1.1 2001/05/03 12:32:13 darcy Exp $
8+
* best viewed with tabs set to 4
9+
*/
10+
11+
#include <stdio.h>
12+
#include <string.h>
13+
#include <time.h>
14+
#include <unistd.h>
15+
16+
#include <postgres.h>
17+
#include <utils/palloc.h>
18+
19+
/*
20+
* This type encrypts it's input unless the first character is a colon.
21+
* The output is the encrypted form with a leading colon. The output
22+
* format is designed to allow dump and reload operations to work as
23+
* expected without doing special tricks.
24+
*/
25+
26+
27+
/*
28+
* This is the internal storage format for CHKPASSs.
29+
* 15 is all I need but add a little buffer
30+
*/
31+
32+
typedef struct chkpass
33+
{
34+
char password[16];
35+
} chkpass;
36+
37+
/*
38+
* Various forward declarations:
39+
*/
40+
41+
chkpass *chkpass_in(char *str);
42+
char *chkpass_out(chkpass * addr);
43+
text *chkpass_rout(chkpass * addr);
44+
45+
/* Only equal or not equal make sense */
46+
bool chkpass_eq(chkpass * a1, text * a2);
47+
bool chkpass_ne(chkpass * a1, text * a2);
48+
49+
/* This function checks that the password is a good one
50+
* It's just a placeholder for now */
51+
static int
52+
verify_pass(const char *str)
53+
{
54+
return 0;
55+
}
56+
57+
/*
58+
* CHKPASS reader.
59+
*/
60+
chkpass *
61+
chkpass_in(char *str)
62+
{
63+
chkpass *result;
64+
char mysalt[4];
65+
static bool random_initialized = false;
66+
static char salt_chars[] =
67+
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
68+
69+
/* special case to let us enter encrypted passwords */
70+
if (*str == ':')
71+
{
72+
result = (chkpass *) palloc(sizeof(chkpass));
73+
strncpy(result->password, str + 1, 13);
74+
result->password[13] = 0;
75+
return (result);
76+
}
77+
78+
if (verify_pass(str) != 0)
79+
{
80+
elog(ERROR, "chkpass_in: purported CHKPASS \"%s\" is a weak password",
81+
str);
82+
return NULL;
83+
}
84+
85+
result = (chkpass *) palloc(sizeof(chkpass));
86+
87+
if (!random_initialized)
88+
{
89+
srandom((unsigned int) time(NULL));
90+
random_initialized = true;
91+
}
92+
93+
mysalt[0] = salt_chars[random() & 0x3f];
94+
mysalt[1] = salt_chars[random() & 0x3f];
95+
mysalt[2] = 0; /* technically the terminator is not
96+
* necessary but I like to play safe */
97+
strcpy(result->password, crypt(str, mysalt));
98+
return (result);
99+
}
100+
101+
/*
102+
* CHKPASS output function.
103+
* Just like any string but we know it is max 15 (13 plus colon and terminator.)
104+
*/
105+
106+
char *
107+
chkpass_out(chkpass * password)
108+
{
109+
char *result;
110+
111+
if (password == NULL)
112+
return (NULL);
113+
114+
if ((result = (char *) palloc(16)) != NULL)
115+
{
116+
result[0] = ':';
117+
strcpy(result + 1, password->password);
118+
}
119+
120+
return (result);
121+
}
122+
123+
124+
/*
125+
* special output function that doesn't output the colon
126+
*/
127+
128+
text *
129+
chkpass_rout(chkpass *password)
130+
{
131+
text *result = NULL;
132+
133+
if (password == NULL)
134+
return (NULL);
135+
136+
if ((result = (text *) palloc(VARHDRSZ + 16)) != NULL)
137+
{
138+
VARSIZE(result) = VARHDRSZ + strlen(password->password);
139+
memcpy(VARDATA(result), password->password, strlen(password->password));
140+
}
141+
142+
return (result);
143+
}
144+
145+
146+
/*
147+
* Boolean tests
148+
*/
149+
150+
bool
151+
chkpass_eq(chkpass * a1, text *a2)
152+
{
153+
char str[10];
154+
int sz = 8;
155+
156+
if (!a1 || !a2) return 0;
157+
if (a2->vl_len < 12) sz = a2->vl_len - 4;
158+
strncpy(str, a2->vl_dat, sz);
159+
str[sz] = 0;
160+
return (strcmp(a1->password, crypt(str, a1->password)) == 0);
161+
}
162+
163+
bool
164+
chkpass_ne(chkpass * a1, text *a2)
165+
{
166+
char str[10];
167+
int sz = 8;
168+
169+
if (!a1 || !a2) return 0;
170+
if (a2->vl_len < 12) sz = a2->vl_len - 4;
171+
strncpy(str, a2->vl_dat, sz);
172+
str[sz] = 0;
173+
return (strcmp(a1->password, crypt(str, a1->password)) != 0);
174+
}
175+

contrib/chkpass/chkpass.sql

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
--
2+
-- PostgreSQL code for CHKPASS.
3+
-- Written by D'Arcy J.M. Cain
4+
-- darcy@druid.net
5+
-- http://www.druid.net/darcy/
6+
--
7+
-- $Header: /cvsroot/pgsql/contrib/chkpass/Attic/chkpass.sql,v 1.1 2001/05/03 12:32:13 darcy Exp $
8+
-- best viewed with tabs set to 4
9+
-- %%PGDIR%% changed to your local directory where modules is
10+
--
11+
12+
load '%%PGDIR%%/modules/chkpass.so';
13+
14+
--
15+
-- Input and output functions and the type itself:
16+
--
17+
18+
create function chkpass_in(opaque)
19+
returns opaque
20+
as '%%PGDIR%%/modules/chkpass.so'
21+
language 'c';
22+
23+
create function chkpass_out(opaque)
24+
returns opaque
25+
as '%%PGDIR%%/modules/chkpass.so'
26+
language 'c';
27+
28+
create type chkpass (
29+
internallength = 16,
30+
externallength = 13,
31+
input = chkpass_in,
32+
output = chkpass_out
33+
);
34+
35+
create function raw(chkpass)
36+
returns text
37+
as '%%PGDIR%%/modules/chkpass.so', 'chkpass_rout'
38+
language 'c';
39+
40+
--
41+
-- The various boolean tests:
42+
--
43+
44+
create function eq(chkpass, text)
45+
returns bool
46+
as '%%PGDIR%%/modules/chkpass.so', 'chkpass_eq'
47+
language 'c';
48+
49+
create function ne(chkpass, text)
50+
returns bool
51+
as '%%PGDIR%%/modules/chkpass.so', 'chkpass_ne'
52+
language 'c';
53+
54+
--
55+
-- Now the operators. Note how some of the parameters to some
56+
-- of the 'create operator' commands are commented out. This
57+
-- is because they reference as yet undefined operators, and
58+
-- will be implicitly defined when those are, further down.
59+
--
60+
61+
create operator = (
62+
leftarg = chkpass,
63+
rightarg = text,
64+
commutator = =,
65+
-- negator = <>,
66+
procedure = eq
67+
);
68+
69+
create operator <> (
70+
leftarg = chkpass,
71+
rightarg = text,
72+
negator = =,
73+
procedure = ne
74+
);
75+
76+
INSERT INTO pg_description (objoid, description)
77+
SELECT oid, 'password type with checks'
78+
FROM pg_type WHERE typname = 'chkpass';
79+
80+
--
81+
-- eof
82+
--

0 commit comments

Comments
 (0)