]> granicus.if.org Git - postgresql/commitdiff
Initial checkin of a contributed type that handles passwords efficiently.
authorD'Arcy J.M. Cain <darcy@druid.net>
Thu, 3 May 2001 12:32:13 +0000 (12:32 +0000)
committerD'Arcy J.M. Cain <darcy@druid.net>
Thu, 3 May 2001 12:32:13 +0000 (12:32 +0000)
contrib/chkpass/Makefile [new file with mode: 0644]
contrib/chkpass/README.chkpass [new file with mode: 0644]
contrib/chkpass/chkpass.c [new file with mode: 0644]
contrib/chkpass/chkpass.sql [new file with mode: 0644]

diff --git a/contrib/chkpass/Makefile b/contrib/chkpass/Makefile
new file mode 100644 (file)
index 0000000..a84a6a6
--- /dev/null
@@ -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
diff --git a/contrib/chkpass/README.chkpass b/contrib/chkpass/README.chkpass
new file mode 100644 (file)
index 0000000..41b0dea
--- /dev/null
@@ -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
+
diff --git a/contrib/chkpass/chkpass.c b/contrib/chkpass/chkpass.c
new file mode 100644 (file)
index 0000000..46080cc
--- /dev/null
@@ -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);
+}
+
diff --git a/contrib/chkpass/chkpass.sql b/contrib/chkpass/chkpass.sql
new file mode 100644 (file)
index 0000000..f8fce41
--- /dev/null
@@ -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
+--