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
This commit is contained in:
Peter Eisentraut 2017-09-22 10:59:46 -04:00
parent ed87e19807
commit 5d3cad5647
12 changed files with 0 additions and 413 deletions

View File

@ -12,7 +12,6 @@ SUBDIRS = \
bloom \
btree_gin \
btree_gist \
chkpass \
citext \
cube \
dblink \

View File

@ -1,4 +0,0 @@
# Generated subdirectories
/log/
/results/
/tmp_check/

View File

@ -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

View File

@ -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
--

View File

@ -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);

View File

@ -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 <time.h>
#include <unistd.h>
#ifdef HAVE_CRYPT_H
#include <crypt.h>
#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);
}

View File

@ -1,5 +0,0 @@
# chkpass extension
comment = 'data type for auto-encrypted passwords'
default_version = '1.0'
module_pathname = '$libdir/chkpass'
relocatable = true

View File

@ -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)

View File

@ -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;

View File

@ -1,95 +0,0 @@
<!-- doc/src/sgml/chkpass.sgml -->
<sect1 id="chkpass" xreflabel="chkpass">
<title>chkpass</title>
<indexterm zone="chkpass">
<primary>chkpass</primary>
</indexterm>
<para>
This module implements a data type <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.
</para>
<para>
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.
</para>
<para>
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.
</para>
<para>
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 <function>raw()</> function.
This allows you to use the
type with things like Apache's <literal>Auth_PostgreSQL</> module.
</para>
<para>
The encryption uses the standard Unix function <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.
</para>
<para>
Note that the <type>chkpass</type> data type is not indexable.
<!--
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.
-->
</para>
<para>
Sample usage:
</para>
<programlisting>
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)
</programlisting>
<sect2>
<title>Author</title>
<para>
D'Arcy J.M. Cain (<email>darcy@druid.net</email>)
</para>
</sect2>
</sect1>

View File

@ -109,7 +109,6 @@ CREATE EXTENSION <replaceable>module_name</> FROM unpackaged;
&bloom;
&btree-gin;
&btree-gist;
&chkpass;
&citext;
&cube;
&dblink;

View File

@ -110,7 +110,6 @@
<!ENTITY bloom SYSTEM "bloom.sgml">
<!ENTITY btree-gin SYSTEM "btree-gin.sgml">
<!ENTITY btree-gist SYSTEM "btree-gist.sgml">
<!ENTITY chkpass SYSTEM "chkpass.sgml">
<!ENTITY citext SYSTEM "citext.sgml">
<!ENTITY cube SYSTEM "cube.sgml">
<!ENTITY dblink SYSTEM "dblink.sgml">