postgresql/src/backend/libpq/crypt.c

183 lines
4.1 KiB
C
Raw Normal View History

/*-------------------------------------------------------------------------
*
* crypt.c--
* Look into pg_user and check the encrypted password with the one
* passed in from the frontend.
*
*
*-------------------------------------------------------------------------
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif
#include "postgres.h"
1997-12-12 17:26:36 +01:00
#include "miscadmin.h"
#include "libpq/crypt.h"
#include "utils/nabstime.h"
#include "utils/palloc.h"
#include "storage/fd.h"
char* crypt_getpwdfilename() {
static char* filename = NULL;
if (!filename) {
1997-12-11 18:03:52 +01:00
filename = (char*)palloc(strlen(DataDir) + strlen(CRYPT_PWD_FILE) + 2);
sprintf(filename, "%s/%s", DataDir, CRYPT_PWD_FILE);
}
return filename;
}
/*-------------------------------------------------------------------------*/
static
FILE* crypt_openpwdfile() {
char* filename;
filename = crypt_getpwdfilename();
return (AllocateFile(filename, "r"));
}
/*-------------------------------------------------------------------------*/
static
void crypt_parsepwdfile(FILE* datafile, char** login, char** pwd, char** valdate) {
char buffer[256];
char* parse;
int count,
i;
fgets(buffer, 256, datafile);
parse = buffer;
/* store a copy of user login to return
*/
count = strcspn(parse, "#");
*login = (char*)palloc(count + 1);
strncpy(*login, parse, count);
(*login)[count] = '\0';
parse += (count + 1);
/* skip to the password field
*/
for (i = 0; i < 5; i++)
parse += (strcspn(parse, "#") + 1);
/* store a copy of user password to return
*/
count = strcspn(parse, "#");
*pwd = (char*)palloc(count + 1);
strncpy(*pwd, parse, count);
(*pwd)[count] = '\0';
parse += (count + 1);
/* store a copy of date login becomes invalid
*/
count = strcspn(parse, "#");
*valdate = (char*)palloc(count + 1);
strncpy(*valdate, parse, count);
(*valdate)[count] = '\0';
parse += (count + 1);
}
/*-------------------------------------------------------------------------*/
static
void crypt_getloginfo(const char* user, char** passwd, char** valuntil) {
FILE* datafile;
char* login;
char* pwd;
char* valdate;
*passwd = NULL;
*valuntil = NULL;
if (!(datafile = crypt_openpwdfile()))
return;
while (!feof(datafile)) {
crypt_parsepwdfile(datafile, &login, &pwd, &valdate);
if (!strcmp(login, user)) {
pfree((void*)login);
*passwd = pwd;
*valuntil = valdate;
fclose(datafile);
return;
}
pfree((void*)login);
pfree((void*)pwd);
pfree((void*)valdate);
}
fclose(datafile);
}
/*-------------------------------------------------------------------------*/
MsgType crypt_salt(const char* user) {
char* passwd;
char* valuntil;
crypt_getloginfo(user, &passwd, &valuntil);
1997-12-12 17:26:36 +01:00
if (passwd == NULL || *passwd == '\0' || !strcmp(passwd, "\\N")) {
if (passwd) pfree((void*)passwd);
if (valuntil) pfree((void*)valuntil);
return STARTUP_UNSALT_MSG;
}
pfree((void*)passwd);
if (valuntil) pfree((void*)valuntil);
return STARTUP_SALT_MSG;
}
/*-------------------------------------------------------------------------*/
int crypt_verify(Port* port, const char* user, const char* pgpass) {
char* passwd;
char* valuntil;
char* crypt_pwd;
int retval = STATUS_ERROR;
AbsoluteTime vuntil,
current;
crypt_getloginfo(user, &passwd, &valuntil);
if (passwd == NULL || *passwd == '\0') {
if (passwd) pfree((void*)passwd);
if (valuntil) pfree((void*)valuntil);
return STATUS_ERROR;
}
crypt_pwd = crypt(passwd, port->salt);
if (!strcmp(pgpass, crypt_pwd)) {
/* check here to be sure we are not past valuntil
*/
if (!valuntil)
vuntil = INVALID_ABSTIME;
else
vuntil = nabstimein(valuntil);
current = GetCurrentAbsoluteTime();
if (vuntil != INVALID_ABSTIME && vuntil < current)
retval = STATUS_ERROR;
else
retval = STATUS_OK;
}
pfree((void*)passwd);
if (valuntil) pfree((void*)valuntil);
return retval;
}