/*------------------------------------------------------------------------- * * crypt.c-- * Look into pg_user and check the encrypted password with the one * passed in from the frontend. * * *------------------------------------------------------------------------- */ #include #include #include #include #ifdef HAVE_CRYPT_H #include #endif #include "postgres.h" #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) { 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); 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; }