mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-12-27 08:39:28 +08:00
220db7ccd8
strings. This patch introduces four support functions cstring_to_text, cstring_to_text_with_len, text_to_cstring, and text_to_cstring_buffer, and two macros CStringGetTextDatum and TextDatumGetCString. A number of existing macros that provided variants on these themes were removed. Most of the places that need to make such conversions now require just one function or macro call, in place of the multiple notational layers that used to be needed. There are no longer any direct calls of textout or textin, and we got most of the places that were using handmade conversions via memcpy (there may be a few still lurking, though). This commit doesn't make any serious effort to eliminate transient memory leaks caused by detoasting toasted text objects before they reach text_to_cstring. We changed PG_GETARG_TEXT_P to PG_GETARG_TEXT_PP in a few places where it was easy, but much more could be done. Brendan Jurd and Tom Lane
160 lines
3.4 KiB
C
160 lines
3.4 KiB
C
/*
|
|
* PostgreSQL type definitions for chkpass
|
|
* Written by D'Arcy J.M. Cain
|
|
* darcy@druid.net
|
|
* http://www.druid.net/darcy/
|
|
*
|
|
* $PostgreSQL: pgsql/contrib/chkpass/chkpass.c,v 1.20 2008/03/25 22:42:41 tgl Exp $
|
|
* 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/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;
|
|
|
|
/*
|
|
* Various forward declarations:
|
|
*/
|
|
|
|
Datum chkpass_in(PG_FUNCTION_ARGS);
|
|
Datum chkpass_out(PG_FUNCTION_ARGS);
|
|
Datum chkpass_rout(PG_FUNCTION_ARGS);
|
|
|
|
/* Only equal or not equal make sense */
|
|
Datum chkpass_eq(PG_FUNCTION_ARGS);
|
|
Datum chkpass_ne(PG_FUNCTION_ARGS);
|
|
|
|
|
|
/* 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];
|
|
static char salt_chars[] =
|
|
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
|
|
/* special case to let us enter encrypted passwords */
|
|
if (*str == ':')
|
|
{
|
|
result = (chkpass *) palloc(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 *) palloc(sizeof(chkpass));
|
|
|
|
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));
|
|
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] = ':';
|
|
strcpy(result + 1, password->password);
|
|
|
|
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];
|
|
|
|
text_to_cstring_buffer(a2, str, sizeof(str));
|
|
PG_RETURN_BOOL(strcmp(a1->password, crypt(str, a1->password)) == 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];
|
|
|
|
text_to_cstring_buffer(a2, str, sizeof(str));
|
|
PG_RETURN_BOOL(strcmp(a1->password, crypt(str, a1->password)) != 0);
|
|
}
|