postgresql/src/backend/libpq/crypt.c

158 lines
3.6 KiB
C
Raw Normal View History

/*-------------------------------------------------------------------------
*
* crypt.c
2001-11-01 19:10:48 +01:00
* Look into the password file and check the encrypted password with
* the one passed in from the frontend.
*
2001-11-01 19:10:48 +01:00
* Original coding by Todd A. Brandys
*
2002-06-20 22:29:54 +02:00
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
2001-11-01 19:10:48 +01:00
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Header: /cvsroot/pgsql/src/backend/libpq/crypt.c,v 1.50 2002/12/05 18:39:43 momjian Exp $
*
*-------------------------------------------------------------------------
*/
2001-11-01 19:10:48 +01:00
#include "postgres.h"
#include <unistd.h>
#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif
1999-07-16 07:00:38 +02:00
#include "libpq/crypt.h"
2001-08-17 04:59:20 +02:00
#include "libpq/libpq.h"
1997-12-12 17:26:36 +01:00
#include "miscadmin.h"
#include "storage/fd.h"
#include "nodes/pg_list.h"
1999-07-16 07:00:38 +02:00
#include "utils/nabstime.h"
int
md5_crypt_verify(const Port *port, const char *user, char *pgpass)
{
char *passwd = NULL,
*valuntil = NULL,
1999-05-25 18:15:34 +02:00
*crypt_pwd;
int retval = STATUS_ERROR;
2002-09-04 22:31:48 +02:00
List **line;
List *token;
char *crypt_pgpass = pgpass;
2002-09-04 22:31:48 +02:00
if ((line = get_user_line(user)) == NULL)
return STATUS_ERROR;
/* Skip over line number and username */
token = lnext(lnext(*line));
if (token)
{
passwd = lfirst(token);
token = lnext(token);
if (token)
valuntil = lfirst(token);
}
2002-09-04 22:31:48 +02:00
if (passwd == NULL || *passwd == '\0')
return STATUS_ERROR;
/* We can't do crypt with pg_shadow MD5 passwords */
if (isMD5(passwd) && port->auth_method == uaCrypt)
2001-08-17 04:59:20 +02:00
{
elog(LOG, "Password is stored MD5 encrypted. "
"'crypt' auth method cannot be used.");
2001-08-17 04:59:20 +02:00
return STATUS_ERROR;
}
/*
* Compare with the encrypted or plain password depending on the
* authentication method being used for this connection.
*/
2001-08-17 04:59:20 +02:00
switch (port->auth_method)
{
case uaMD5:
crypt_pwd = palloc(MD5_PASSWD_LEN + 1);
if (isMD5(passwd))
{
/* pg_shadow already encrypted, only do salt */
if (!EncryptMD5(passwd + strlen("md5"),
(char *) port->md5Salt,
2001-08-17 04:59:20 +02:00
sizeof(port->md5Salt), crypt_pwd))
{
pfree(crypt_pwd);
return STATUS_ERROR;
}
}
else
{
/* pg_shadow plain, double-encrypt */
char *crypt_pwd2 = palloc(MD5_PASSWD_LEN + 1);
2001-08-17 04:59:20 +02:00
if (!EncryptMD5(passwd, port->user, strlen(port->user),
crypt_pwd2))
{
pfree(crypt_pwd);
pfree(crypt_pwd2);
return STATUS_ERROR;
}
2001-08-17 04:59:20 +02:00
if (!EncryptMD5(crypt_pwd2 + strlen("md5"), port->md5Salt,
sizeof(port->md5Salt), crypt_pwd))
{
pfree(crypt_pwd);
pfree(crypt_pwd2);
return STATUS_ERROR;
}
pfree(crypt_pwd2);
}
break;
case uaCrypt:
{
char salt[3];
StrNCpy(salt, port->cryptSalt, 3);
crypt_pwd = crypt(passwd, salt);
break;
}
default:
if (isMD5(passwd))
{
/* Encrypt user-supplied password to match MD5 in pg_shadow */
crypt_pgpass = palloc(MD5_PASSWD_LEN + 1);
if (!EncryptMD5(pgpass, port->user, strlen(port->user),
crypt_pgpass))
{
pfree(crypt_pgpass);
return STATUS_ERROR;
}
}
crypt_pwd = passwd;
break;
}
if (strcmp(crypt_pgpass, crypt_pwd) == 0)
{
/*
2001-11-01 19:10:48 +01:00
* Password OK, now check to be sure we are not past valuntil
*/
2001-11-01 19:10:48 +01:00
AbsoluteTime vuntil,
current;
if (!valuntil)
vuntil = INVALID_ABSTIME;
else
vuntil = DatumGetAbsoluteTime(DirectFunctionCall1(nabstimein,
2001-03-22 05:01:46 +01:00
CStringGetDatum(valuntil)));
current = GetCurrentAbsoluteTime();
if (vuntil != INVALID_ABSTIME && vuntil < current)
retval = STATUS_ERROR;
else
retval = STATUS_OK;
}
if (port->auth_method == uaMD5)
pfree(crypt_pwd);
if (crypt_pgpass != pgpass)
pfree(crypt_pgpass);
return retval;
}