From 5d3cad564729f64d972c5c803ff34f0eb40bfd0c Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Fri, 22 Sep 2017 10:59:46 -0400 Subject: [PATCH] Remove contrib/chkpass The recent addition of a test suite for this module revealed a few problems. It uses a crypt() method that is no longer considered secure and doesn't work anymore on some platforms. Using a volatile input function violates internal sanity check assumptions and leads to failures on the build farm. So this module is neither a usable security tool nor a good example for an extension. No one wanted to argue for keeping or improving it, so remove it. Discussion: https://www.postgresql.org/message-id/5645b0d7-cc40-6ab5-c553-292a91091ee7%402ndquadrant.com --- contrib/Makefile | 1 - contrib/chkpass/.gitignore | 4 - contrib/chkpass/Makefile | 23 --- contrib/chkpass/chkpass--1.0.sql | 70 -------- contrib/chkpass/chkpass--unpackaged--1.0.sql | 13 -- contrib/chkpass/chkpass.c | 175 ------------------- contrib/chkpass/chkpass.control | 5 - contrib/chkpass/expected/chkpass.out | 18 -- contrib/chkpass/sql/chkpass.sql | 7 - doc/src/sgml/chkpass.sgml | 95 ---------- doc/src/sgml/contrib.sgml | 1 - doc/src/sgml/filelist.sgml | 1 - 12 files changed, 413 deletions(-) delete mode 100644 contrib/chkpass/.gitignore delete mode 100644 contrib/chkpass/Makefile delete mode 100644 contrib/chkpass/chkpass--1.0.sql delete mode 100644 contrib/chkpass/chkpass--unpackaged--1.0.sql delete mode 100644 contrib/chkpass/chkpass.c delete mode 100644 contrib/chkpass/chkpass.control delete mode 100644 contrib/chkpass/expected/chkpass.out delete mode 100644 contrib/chkpass/sql/chkpass.sql delete mode 100644 doc/src/sgml/chkpass.sgml diff --git a/contrib/Makefile b/contrib/Makefile index e84eb67008..8046ca4f39 100644 --- a/contrib/Makefile +++ b/contrib/Makefile @@ -12,7 +12,6 @@ SUBDIRS = \ bloom \ btree_gin \ btree_gist \ - chkpass \ citext \ cube \ dblink \ diff --git a/contrib/chkpass/.gitignore b/contrib/chkpass/.gitignore deleted file mode 100644 index 5dcb3ff972..0000000000 --- a/contrib/chkpass/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Generated subdirectories -/log/ -/results/ -/tmp_check/ diff --git a/contrib/chkpass/Makefile b/contrib/chkpass/Makefile deleted file mode 100644 index dbecc3360b..0000000000 --- a/contrib/chkpass/Makefile +++ /dev/null @@ -1,23 +0,0 @@ -# contrib/chkpass/Makefile - -MODULE_big = chkpass -OBJS = chkpass.o $(WIN32RES) - -EXTENSION = chkpass -DATA = chkpass--1.0.sql chkpass--unpackaged--1.0.sql -PGFILEDESC = "chkpass - encrypted password data type" - -SHLIB_LINK = $(filter -lcrypt, $(LIBS)) - -REGRESS = chkpass - -ifdef USE_PGXS -PG_CONFIG = pg_config -PGXS := $(shell $(PG_CONFIG) --pgxs) -include $(PGXS) -else -subdir = contrib/chkpass -top_builddir = ../.. -include $(top_builddir)/src/Makefile.global -include $(top_srcdir)/contrib/contrib-global.mk -endif diff --git a/contrib/chkpass/chkpass--1.0.sql b/contrib/chkpass/chkpass--1.0.sql deleted file mode 100644 index 406a61924c..0000000000 --- a/contrib/chkpass/chkpass--1.0.sql +++ /dev/null @@ -1,70 +0,0 @@ -/* contrib/chkpass/chkpass--1.0.sql */ - --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "CREATE EXTENSION chkpass" to load this file. \quit - --- --- Input and output functions and the type itself: --- - -CREATE FUNCTION chkpass_in(cstring) - RETURNS chkpass - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT VOLATILE; --- Note: chkpass_in actually is volatile, because of its use of random(). --- In hindsight that was a bad idea, but there's no way to change it without --- breaking some usage patterns. - -CREATE FUNCTION chkpass_out(chkpass) - RETURNS cstring - AS 'MODULE_PATHNAME' - LANGUAGE C STRICT IMMUTABLE; - -CREATE TYPE chkpass ( - internallength = 16, - input = chkpass_in, - output = chkpass_out -); - -CREATE FUNCTION raw(chkpass) - RETURNS text - AS 'MODULE_PATHNAME', 'chkpass_rout' - LANGUAGE C STRICT; - --- --- The various boolean tests: --- - -CREATE FUNCTION eq(chkpass, text) - RETURNS bool - AS 'MODULE_PATHNAME', 'chkpass_eq' - LANGUAGE C STRICT; - -CREATE FUNCTION ne(chkpass, text) - RETURNS bool - AS 'MODULE_PATHNAME', 'chkpass_ne' - LANGUAGE C STRICT; - --- --- Now the operators. --- - -CREATE OPERATOR = ( - leftarg = chkpass, - rightarg = text, - negator = <>, - procedure = eq -); - -CREATE OPERATOR <> ( - leftarg = chkpass, - rightarg = text, - negator = =, - procedure = ne -); - -COMMENT ON TYPE chkpass IS 'password type with checks'; - --- --- eof --- diff --git a/contrib/chkpass/chkpass--unpackaged--1.0.sql b/contrib/chkpass/chkpass--unpackaged--1.0.sql deleted file mode 100644 index 8bdecddfa5..0000000000 --- a/contrib/chkpass/chkpass--unpackaged--1.0.sql +++ /dev/null @@ -1,13 +0,0 @@ -/* contrib/chkpass/chkpass--unpackaged--1.0.sql */ - --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "CREATE EXTENSION chkpass FROM unpackaged" to load this file. \quit - -ALTER EXTENSION chkpass ADD type chkpass; -ALTER EXTENSION chkpass ADD function chkpass_in(cstring); -ALTER EXTENSION chkpass ADD function chkpass_out(chkpass); -ALTER EXTENSION chkpass ADD function raw(chkpass); -ALTER EXTENSION chkpass ADD function eq(chkpass,text); -ALTER EXTENSION chkpass ADD function ne(chkpass,text); -ALTER EXTENSION chkpass ADD operator <>(chkpass,text); -ALTER EXTENSION chkpass ADD operator =(chkpass,text); diff --git a/contrib/chkpass/chkpass.c b/contrib/chkpass/chkpass.c deleted file mode 100644 index 3803ccff9a..0000000000 --- a/contrib/chkpass/chkpass.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * PostgreSQL type definitions for chkpass - * Written by D'Arcy J.M. Cain - * darcy@druid.net - * http://www.druid.net/darcy/ - * - * contrib/chkpass/chkpass.c - * best viewed with tabs set to 4 - */ - -#include "postgres.h" - -#include -#include -#ifdef HAVE_CRYPT_H -#include -#endif - -#include "fmgr.h" -#include "utils/backend_random.h" -#include "utils/builtins.h" - -PG_MODULE_MAGIC; - -/* - * 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; - - -/* 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. - */ -PG_FUNCTION_INFO_V1(chkpass_in); -Datum -chkpass_in(PG_FUNCTION_ARGS) -{ - char *str = PG_GETARG_CSTRING(0); - chkpass *result; - char mysalt[4]; - char *crypt_output; - static char salt_chars[] = - "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - - /* special case to let us enter encrypted passwords */ - if (*str == ':') - { - result = (chkpass *) palloc0(sizeof(chkpass)); - strlcpy(result->password, str + 1, 13 + 1); - PG_RETURN_POINTER(result); - } - - if (verify_pass(str) != 0) - ereport(ERROR, - (errcode(ERRCODE_DATA_EXCEPTION), - errmsg("password \"%s\" is weak", str))); - - result = (chkpass *) palloc0(sizeof(chkpass)); - - if (!pg_backend_random(mysalt, 2)) - ereport(ERROR, - (errmsg("could not generate random salt"))); - - mysalt[0] = salt_chars[mysalt[0] & 0x3f]; - mysalt[1] = salt_chars[mysalt[1] & 0x3f]; - mysalt[2] = 0; /* technically the terminator is not necessary - * but I like to play safe */ - - crypt_output = crypt(str, mysalt); - if (crypt_output == NULL) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("crypt() failed"))); - - strlcpy(result->password, crypt_output, sizeof(result->password)); - - PG_RETURN_POINTER(result); -} - -/* - * CHKPASS output function. - * Just like any string but we know it is max 15 (13 plus colon and terminator.) - */ - -PG_FUNCTION_INFO_V1(chkpass_out); -Datum -chkpass_out(PG_FUNCTION_ARGS) -{ - chkpass *password = (chkpass *) PG_GETARG_POINTER(0); - char *result; - - result = (char *) palloc(16); - result[0] = ':'; - strlcpy(result + 1, password->password, 15); - - PG_RETURN_CSTRING(result); -} - - -/* - * special output function that doesn't output the colon - */ - -PG_FUNCTION_INFO_V1(chkpass_rout); -Datum -chkpass_rout(PG_FUNCTION_ARGS) -{ - chkpass *password = (chkpass *) PG_GETARG_POINTER(0); - - PG_RETURN_TEXT_P(cstring_to_text(password->password)); -} - - -/* - * Boolean tests - */ - -PG_FUNCTION_INFO_V1(chkpass_eq); -Datum -chkpass_eq(PG_FUNCTION_ARGS) -{ - chkpass *a1 = (chkpass *) PG_GETARG_POINTER(0); - text *a2 = PG_GETARG_TEXT_PP(1); - char str[9]; - char *crypt_output; - - text_to_cstring_buffer(a2, str, sizeof(str)); - crypt_output = crypt(str, a1->password); - if (crypt_output == NULL) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("crypt() failed"))); - - PG_RETURN_BOOL(strcmp(a1->password, crypt_output) == 0); -} - -PG_FUNCTION_INFO_V1(chkpass_ne); -Datum -chkpass_ne(PG_FUNCTION_ARGS) -{ - chkpass *a1 = (chkpass *) PG_GETARG_POINTER(0); - text *a2 = PG_GETARG_TEXT_PP(1); - char str[9]; - char *crypt_output; - - text_to_cstring_buffer(a2, str, sizeof(str)); - crypt_output = crypt(str, a1->password); - if (crypt_output == NULL) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("crypt() failed"))); - - PG_RETURN_BOOL(strcmp(a1->password, crypt_output) != 0); -} diff --git a/contrib/chkpass/chkpass.control b/contrib/chkpass/chkpass.control deleted file mode 100644 index bd4b3d3d0d..0000000000 --- a/contrib/chkpass/chkpass.control +++ /dev/null @@ -1,5 +0,0 @@ -# chkpass extension -comment = 'data type for auto-encrypted passwords' -default_version = '1.0' -module_pathname = '$libdir/chkpass' -relocatable = true diff --git a/contrib/chkpass/expected/chkpass.out b/contrib/chkpass/expected/chkpass.out deleted file mode 100644 index b53557bf2a..0000000000 --- a/contrib/chkpass/expected/chkpass.out +++ /dev/null @@ -1,18 +0,0 @@ -CREATE EXTENSION chkpass; -WARNING: type input function chkpass_in should not be volatile -CREATE TABLE test (i int, p chkpass); -INSERT INTO test VALUES (1, 'hello'), (2, 'goodbye'); -SELECT i, p = 'hello' AS "hello?" FROM test; - i | hello? ----+-------- - 1 | t - 2 | f -(2 rows) - -SELECT i, p <> 'hello' AS "!hello?" FROM test; - i | !hello? ----+--------- - 1 | f - 2 | t -(2 rows) - diff --git a/contrib/chkpass/sql/chkpass.sql b/contrib/chkpass/sql/chkpass.sql deleted file mode 100644 index 595683e249..0000000000 --- a/contrib/chkpass/sql/chkpass.sql +++ /dev/null @@ -1,7 +0,0 @@ -CREATE EXTENSION chkpass; - -CREATE TABLE test (i int, p chkpass); -INSERT INTO test VALUES (1, 'hello'), (2, 'goodbye'); - -SELECT i, p = 'hello' AS "hello?" FROM test; -SELECT i, p <> 'hello' AS "!hello?" FROM test; diff --git a/doc/src/sgml/chkpass.sgml b/doc/src/sgml/chkpass.sgml deleted file mode 100644 index 9f682d8981..0000000000 --- a/doc/src/sgml/chkpass.sgml +++ /dev/null @@ -1,95 +0,0 @@ - - - - chkpass - - - chkpass - - - - This module implements a data type chkpass that is - designed for storing encrypted passwords. - Each password is automatically converted to encrypted form upon entry, - and is always stored encrypted. To compare, simply compare against a clear - text password and the comparison function will encrypt it before comparing. - - - - There are provisions in the code to report an error if the password is - determined to be easily crackable. However, this is currently just - a stub that does nothing. - - - - If you precede an input string with a colon, it is assumed to be an - already-encrypted password, and is stored without further encryption. - This allows entry of previously-encrypted passwords. - - - - On output, a colon is prepended. This makes it possible to dump and reload - passwords without re-encrypting them. If you want the encrypted password - without the colon then use the raw() function. - This allows you to use the - type with things like Apache's Auth_PostgreSQL module. - - - - The encryption uses the standard Unix function crypt(), - and so it suffers - from all the usual limitations of that function; notably that only the - first eight characters of a password are considered. - - - - Note that the chkpass data type is not indexable. - - - - - Sample usage: - - - -test=# create table test (p chkpass); -CREATE TABLE -test=# insert into test values ('hello'); -INSERT 0 1 -test=# select * from test; - p ----------------- - :dVGkpXdOrE3ko -(1 row) - -test=# select raw(p) from test; - raw ---------------- - dVGkpXdOrE3ko -(1 row) - -test=# select p = 'hello' from test; - ?column? ----------- - t -(1 row) - -test=# select p = 'goodbye' from test; - ?column? ----------- - f -(1 row) - - - - Author - - - D'Arcy J.M. Cain (darcy@druid.net) - - - - diff --git a/doc/src/sgml/contrib.sgml b/doc/src/sgml/contrib.sgml index eaaa36cb87..f32b8a81a2 100644 --- a/doc/src/sgml/contrib.sgml +++ b/doc/src/sgml/contrib.sgml @@ -109,7 +109,6 @@ CREATE EXTENSION module_name FROM unpackaged; &bloom; &btree-gin; &btree-gist; - &chkpass; &citext; &cube; &dblink; diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml index b914086009..bd371fd1d3 100644 --- a/doc/src/sgml/filelist.sgml +++ b/doc/src/sgml/filelist.sgml @@ -110,7 +110,6 @@ -