diff options
| author | Marc G. Fournier | 1997-03-12 21:23:16 +0000 |
|---|---|---|
| committer | Marc G. Fournier | 1997-03-12 21:23:16 +0000 |
| commit | 3a7c93e7f32b555defdc2ea0b0554f6dd0a34c41 (patch) | |
| tree | 39e3c59630f15d44aaa3ad7ad0ae4fac7723f68b /src/backend/libpq | |
| parent | 5dde558ce60db1f8747bbf745d56bd9cd5f4c7b7 (diff) | |
From: Dan McGuirk <mcguirk@indirect.com>
Subject: [HACKERS] password authentication
This patch adds support for plaintext password authentication. To use
it, you add a line like
host all 0.0.0.0 0.0.0.0 password pg_pwd.conf
to your pg_hba.conf, where 'pg_pwd.conf' is the name of a file containing
the usernames and password hashes in the format of the first two fields
of a Unix /etc/passwd file. (Of course, you can use a specific database
name or IP instead.)
Then, to connect with a password through libpq, you use the PQconnectdb()
function, specifying the "password=" tag in the connect string and also
adding the tag "authtype=password".
I also added a command-line switch '-u' to psql that tells it to prompt
for a username and password and use password authentication.
Diffstat (limited to 'src/backend/libpq')
| -rw-r--r-- | src/backend/libpq/Makefile | 5 | ||||
| -rw-r--r-- | src/backend/libpq/auth.c | 47 | ||||
| -rw-r--r-- | src/backend/libpq/hba.c | 100 | ||||
| -rw-r--r-- | src/backend/libpq/pqcomm.c | 28 |
4 files changed, 117 insertions, 63 deletions
diff --git a/src/backend/libpq/Makefile b/src/backend/libpq/Makefile index c8a0533a2b9..a7c7f13704e 100644 --- a/src/backend/libpq/Makefile +++ b/src/backend/libpq/Makefile @@ -4,7 +4,7 @@ # Makefile for libpq subsystem (backend half of libpq interface) # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/backend/libpq/Makefile,v 1.4 1996/11/14 10:23:51 bryanh Exp $ +# $Header: /cvsroot/pgsql/src/backend/libpq/Makefile,v 1.5 1997/03/12 21:17:45 scrappy Exp $ # #------------------------------------------------------------------------- @@ -24,7 +24,8 @@ LDADD+= $(KRBLIBS) endif OBJS = be-dumpdata.o be-fsstubs.o be-pqexec.o \ - auth.o hba.o pqcomm.o portal.o util.o portalbuf.o pqpacket.o pqsignal.o + auth.o hba.o pqcomm.o portal.o util.o portalbuf.o pqpacket.o pqsignal.o \ + password.o all: SUBSYS.o diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c index d1cb560f192..333fb6ce7d1 100644 --- a/src/backend/libpq/auth.c +++ b/src/backend/libpq/auth.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.8 1996/11/16 08:09:15 bryanh Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.9 1997/03/12 21:17:48 scrappy Exp $ * *------------------------------------------------------------------------- */ @@ -70,6 +70,7 @@ #include <libpq/libpq.h> #include <libpq/libpq-be.h> #include <libpq/hba.h> +#include <libpq/password.h> /*---------------------------------------------------------------- * common definitions for generic fe/be routines @@ -113,10 +114,11 @@ static struct authsvc authsvcs[] = { { "krb4", STARTUP_KRB4_MSG, 1 }, { "krb5", STARTUP_KRB5_MSG, 1 }, #if defined(KRB5) - { "kerberos", STARTUP_KRB5_MSG, 1 } + { "kerberos", STARTUP_KRB5_MSG, 1 }, #else - { "kerberos", STARTUP_KRB4_MSG, 1 } + { "kerberos", STARTUP_KRB4_MSG, 1 }, #endif + { "password", STARTUP_PASSWORD_MSG, 1 } }; static n_authsvcs = sizeof(authsvcs) / sizeof(struct authsvc); @@ -403,6 +405,26 @@ return(STATUS_ERROR); } #endif /* KRB5 */ +static int +pg_password_recvauth(Port *port, char *database, char *DataDir) +{ + PacketBuf buf; + char *user, *password; + + if(PacketReceive(port, &buf, BLOCKING) != STATUS_OK) { + sprintf(PQerrormsg, + "pg_password_recvauth: failed to receive authentication packet.\n"); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return STATUS_ERROR; + } + + user = buf.data; + password = buf.data + strlen(user) + 1; + + return verify_password(user, password, port, database, DataDir); +} + /* * be_recvauth -- server demux routine for incoming authentication information */ @@ -418,8 +440,8 @@ be_recvauth(MsgType msgtype_arg, Port *port, char *username, StartupInfo* sp) */ if (msgtype_arg == STARTUP_MSG && useHostBasedAuth) msgtype = STARTUP_HBA_MSG; - else - msgtype = STARTUP_UNAUTH_MSG; + else + msgtype = msgtype_arg; if (!username) { (void) sprintf(PQerrormsg, @@ -490,6 +512,21 @@ be_recvauth(MsgType msgtype_arg, Port *port, char *username, StartupInfo* sp) return(STATUS_ERROR); } break; + case STARTUP_PASSWORD_MSG: + if(!be_getauthsvc(msgtype)) { + sprintf(PQerrormsg, + "be_recvauth: " + "plaintext password authentication disallowed\n"); + fputs(PQerrormsg, stderr); + pqdebug("%s", PQerrormsg); + return(STATUS_ERROR); + } + if(pg_password_recvauth(port, sp->database, DataDir) != STATUS_OK) { + /* pg_password_recvauth or lower-level routines have already set */ + /* the error message */ + return(STATUS_ERROR); + } + break; default: (void) sprintf(PQerrormsg, "be_recvauth: unrecognized message type: %d\n", diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c index 4bdf497a759..22d532bf537 100644 --- a/src/backend/libpq/hba.c +++ b/src/backend/libpq/hba.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.15 1997/01/14 01:56:44 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/hba.c,v 1.16 1997/03/12 21:17:53 scrappy Exp $ * *------------------------------------------------------------------------- */ @@ -30,31 +30,6 @@ #include <port/inet_aton.h> /* For inet_aton() */ -#define CONF_FILE "pg_hba.conf" - /* Name of the config file */ - -#define MAP_FILE "pg_ident.conf" - /* Name of the usermap file */ - -#define OLD_CONF_FILE "pg_hba" - /* Name of the config file in prior releases of Postgres. */ - -#define MAX_LINES 255 - /* Maximum number of config lines that can apply to one database */ - -#define MAX_TOKEN 80 -/* Maximum size of one token in the configuration file */ - -#define USERMAP_NAME_SIZE 16 /* Max size of a usermap name */ - -#define IDENT_PORT 113 - /* Standard TCP port number for Ident service. Assigned by IANA */ - -#define IDENT_USERNAME_MAX 512 - /* Max size of username ident server can return */ - -enum Userauth {Trust, Ident}; - /* Some standard C libraries, including GNU, have an isblank() function. Others, including Solaris, do not. So we have our own. */ @@ -108,7 +83,7 @@ read_through_eol(FILE *file) { static void read_hba_entry2(FILE *file, enum Userauth *userauth_p, char usermap_name[], - bool *error_p) { + bool *error_p, bool *matches_p, bool find_password_entries) { /*-------------------------------------------------------------------------- Read from file FILE the rest of a host record, after the mask field, and return the interpretation of it as *userauth_p, usermap_name, and @@ -120,34 +95,47 @@ read_hba_entry2(FILE *file, enum Userauth *userauth_p, char usermap_name[], /* Get authentication type token. */ next_token(file, buf, sizeof(buf)); + userauth_valid = false; if (buf[0] == '\0') { *error_p = true; - read_through_eol(file); } else { - if (strcmp(buf, "trust") == 0) { - userauth_valid = true; + userauth_valid = true; + if(strcmp(buf, "trust") == 0) { *userauth_p = Trust; - } else if (strcmp(buf, "ident") == 0) { - userauth_valid = true; + } else if(strcmp(buf, "ident") == 0) { *userauth_p = Ident; - } else userauth_valid = false; + } else if(strcmp(buf, "password") == 0) { + *userauth_p = Password; + } else { + userauth_valid = false; + } + + if((find_password_entries && strcmp(buf, "password") == 0) || + (!find_password_entries && strcmp(buf, "password") != 0)) { + *matches_p = true; + } else { + *matches_p = false; + } + } + + if(!userauth_valid || !*matches_p || *error_p) { if (!userauth_valid) { *error_p = true; - read_through_eol(file); + } + read_through_eol(file); + } else { + /* Get the map name token, if any */ + next_token(file, buf, sizeof(buf)); + if (buf[0] == '\0') { + *error_p = false; + usermap_name[0] = '\0'; } else { - /* Get the map name token, if any */ + strncpy(usermap_name, buf, USERMAP_NAME_SIZE); next_token(file, buf, sizeof(buf)); - if (buf[0] == '\0') { - *error_p = false; - usermap_name[0] = '\0'; - } else { - strncpy(usermap_name, buf, USERMAP_NAME_SIZE); - next_token(file, buf, sizeof(buf)); - if (buf[0] != '\0') { - *error_p = true; - read_through_eol(file); - } else *error_p = false; - } + if (buf[0] != '\0') { + *error_p = true; + read_through_eol(file); + } else *error_p = false; } } } @@ -158,7 +146,8 @@ static void process_hba_record(FILE *file, const struct in_addr ip_addr, const char database[], bool *matches_p, bool *error_p, - enum Userauth *userauth_p, char usermap_name[] ) { + enum Userauth *userauth_p, char usermap_name[], + bool find_password_entries) { /*--------------------------------------------------------------------------- Process the non-comment record in the config file that is next on the file. See if it applies to a connection to a host with IP address "ip_addr" @@ -221,8 +210,7 @@ process_hba_record(FILE *file, the rest of the info from it. */ read_hba_entry2(file, userauth_p, usermap_name, - error_p); - *matches_p = true; + error_p, matches_p, find_password_entries); if (*error_p) { sprintf(PQerrormsg, "process_hba_record: invalid syntax in " @@ -249,7 +237,7 @@ static void process_open_config_file(FILE *file, const struct in_addr ip_addr, const char database[], bool *host_ok_p, enum Userauth *userauth_p, - char usermap_name[] ) { + char usermap_name[], bool find_password_entries) { /*--------------------------------------------------------------------------- This function does the same thing as find_hba_entry, only with the config file already open on stream descriptor "file". @@ -274,7 +262,8 @@ process_open_config_file(FILE *file, if (c == '#') read_through_eol(file); else { process_hba_record(file, ip_addr, database, - &found_entry, &error, userauth_p, usermap_name); + &found_entry, &error, userauth_p, usermap_name, + find_password_entries); } } } @@ -286,11 +275,11 @@ process_open_config_file(FILE *file, -static void +void find_hba_entry(const char DataDir[], const struct in_addr ip_addr, const char database[], bool *host_ok_p, enum Userauth *userauth_p, - char usermap_name[] ) { + char usermap_name[], bool find_password_entries) { /*-------------------------------------------------------------------------- Read the config file and find an entry that allows connection from host "ip_addr" to database "database". If not found, return @@ -360,7 +349,7 @@ find_hba_entry(const char DataDir[], const struct in_addr ip_addr, pqdebug("%s", PQerrormsg); } else { process_open_config_file(file, ip_addr, database, host_ok_p, userauth_p, - usermap_name); + usermap_name, find_password_entries); fclose(file); } free(conf_file); @@ -731,7 +720,8 @@ hba_recvauth(const Port *port, const char database[], const char user[], find_hba_entry(DataDir, port->raddr.sin_addr, database, - &host_ok, &userauth, usermap_name); + &host_ok, &userauth, usermap_name, + false /* don't find password entries of type 'password' */); if (!host_ok) retvalue = STATUS_ERROR; else { diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c index 928bc281b8d..6b8ecdac28b 100644 --- a/src/backend/libpq/pqcomm.c +++ b/src/backend/libpq/pqcomm.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.11 1997/02/14 04:15:29 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.12 1997/03/12 21:17:58 scrappy Exp $ * *------------------------------------------------------------------------- */ @@ -703,3 +703,29 @@ StreamOpen(char *hostName, short portName, Port *port) return(STATUS_OK); } + +static char *authentication_type_name[] = { + 0, 0, 0, 0, 0, 0, 0, + "the default authentication type", + 0, 0, + "Kerberos v4", + "Kerberos v5", + "host-based authentication", + "unauthenication", + "plaintext password authentication" +}; + +char *name_of_authentication_type(int type) +{ + char *result = 0; + + if(type >= 1 && type <= LAST_AUTHENTICATION_TYPE) { + result = authentication_type_name[type]; + } + + if(result == 0) { + result = "<unknown authentication type>"; + } + + return result; +} |
