diff --git a/src/backend/libpq/password.c b/src/backend/libpq/password.c new file mode 100644 index 0000000000000000000000000000000000000000..b9ec4d55cc6812afe572c5d8218096c16a6e1796 --- /dev/null +++ b/src/backend/libpq/password.c @@ -0,0 +1,107 @@ +#include <postgres.h> +#include <libpq/password.h> +#include <libpq/hba.h> +#include <libpq/libpq.h> +#include <string.h> +#include <unistd.h> + +int +verify_password(char *user, char *password, Port *port, + char *database, char *DataDir) +{ + bool host_ok; + enum Userauth userauth; + char pw_file_name[PWFILE_NAME_SIZE+1]; + + char *pw_file_fullname; + FILE *pw_file; + + char pw_file_line[255]; + char *p, *test_user, *test_pw; + char salt[3]; + + find_hba_entry(DataDir, port->raddr.sin_addr, database, + &host_ok, &userauth, pw_file_name, true); + + if(!host_ok) { + sprintf(PQerrormsg, + "verify_password: couldn't find entry for connecting host\n"); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return STATUS_ERROR; + } + + if(userauth != Password) { + sprintf(PQerrormsg, + "verify_password: couldn't find entry of type 'password' " + "for this host\n"); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return STATUS_ERROR; + } + + if(!pw_file_name || pw_file_name[0] == '\0') { + sprintf(PQerrormsg, + "verify_password: no password file specified\n"); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return STATUS_ERROR; + } + + pw_file_fullname = (char *)malloc(strlen(DataDir) + strlen(pw_file_name) + 2); + strcpy(pw_file_fullname, DataDir); + strcat(pw_file_fullname, "/"); + strcat(pw_file_fullname, pw_file_name); + + pw_file = fopen(pw_file_fullname, "r"); + if(!pw_file) { + sprintf(PQerrormsg, + "verify_password: couldn't open password file '%s'\n", + pw_file_fullname); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return STATUS_ERROR; + } + + while(!feof(pw_file)) { + fgets(pw_file_line, 255, pw_file); + p = pw_file_line; + + test_user = strsep(&p, ":"); + test_pw = p; + if(!test_user || !test_pw || + test_user[0] == '\0' || test_pw[0] == '\0') { + continue; + } + + /* kill the newline */ + test_pw[strlen(test_pw)-1] = '\0'; + + strncpy(salt, test_pw, 2); + salt[2] = '\0'; + + if(strcmp(user, test_user) == 0) { + /* we're outta here one way or the other. */ + fclose(pw_file); + + if(strcmp(crypt(password, salt), test_pw) == 0) { + /* it matched. */ + return STATUS_OK; + } + + sprintf(PQerrormsg, + "verify_password: password mismatch for '%s'.\n", + user); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return STATUS_ERROR; + } + } + + sprintf(PQerrormsg, + "verify_password: user '%s' not found in password file.\n", + user); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return STATUS_ERROR; +} diff --git a/src/include/libpq/password.h b/src/include/libpq/password.h new file mode 100644 index 0000000000000000000000000000000000000000..f6b6214095077d586f6cd1667904a02fe25ea4e2 --- /dev/null +++ b/src/include/libpq/password.h @@ -0,0 +1,12 @@ +#ifndef PASSWORD_H +#define PASSWORD_H + +#include <libpq/hba.h> +#include <libpq/pqcomm.h> + +#define PWFILE_NAME_SIZE USERMAP_NAME_SIZE + +int verify_password(char *user, char *password, Port *port, + char *database, char *DataDir); + +#endif