1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-30 21:42:05 +03:00
An extension to the code to allow for a pg_password authentication database
that is *seperate* from the system password file
This commit is contained in:
Marc G. Fournier
1997-12-04 00:28:15 +00:00
parent 333323f304
commit 4c04f7724e
19 changed files with 494 additions and 63 deletions

View File

@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.49 1997/12/01 22:02:46 momjian Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.50 1997/12/04 00:28:11 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
@ -36,6 +36,9 @@
#ifndef HAVE_STRDUP
#include "strdup.h"
#endif
#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif
/* use a local version instead of the one found in pqpacket.c */
@ -284,7 +287,7 @@ PQconndefaults(void)
}
/* ----------------
* PQsetdb
* PQsetdbLogin
*
* establishes a connection to a postgres backend through the postmaster
* at the specified host and port.
@ -324,7 +327,7 @@ PQconndefaults(void)
* ----------------
*/
PGconn *
PQsetdb(const char *pghost, const char *pgport, const char *pgoptions, const char *pgtty, const char *dbName)
PQsetdbLogin(const char *pghost, const char *pgport, const char *pgoptions, const char *pgtty, const char *dbName, const char *login, const char *pwd)
{
PGconn *conn;
char *tmp;
@ -386,7 +389,12 @@ PQsetdb(const char *pghost, const char *pgport, const char *pgoptions, const cha
else
conn->pgoptions = strdup(pgoptions);
if ((tmp = getenv("PGUSER")) != NULL)
if (login)
{
error = FALSE;
conn->pguser = strdup(login);
}
else if ((tmp = getenv("PGUSER")) != NULL)
{
error = FALSE;
conn->pguser = strdup(tmp);
@ -407,8 +415,14 @@ PQsetdb(const char *pghost, const char *pgport, const char *pgoptions, const cha
}
}
if ((tmp = getenv("PGPASSWORD")) != NULL)
if (pwd)
{
conn->pgpass = strdup(pwd);
}
else if ((tmp = getenv("PGPASSWORD")) != NULL)
{
conn->pgpass = strdup(tmp);
}
else
conn->pgpass = 0;
@ -479,6 +493,7 @@ connectDB(PGconn *conn)
StartupInfo startup;
PacketBuf pacBuf;
PacketLen pacLen;
int status;
MsgType msgtype;
int laddrlen = sizeof(struct sockaddr);
@ -486,6 +501,8 @@ connectDB(PGconn *conn)
int portno,
family,
len;
bool salted = false;
char* tmp;
/*
* Initialize the startup packet.
@ -592,7 +609,57 @@ connectDB(PGconn *conn)
}
/* by this point, connection has been opened */
msgtype = fe_getauthsvc(conn->errorMessage);
/* This section of code is new as of Nov 19, 1997. It sends just the
* user's login to the backend. This allows the backend to search
* pg_user to see if the user has a password defined. If the user
* does have a password in pg_user, then the backend will send a
* packet back with a randomly generated salt, so the user's password
* can be encrypted.
*/
pacLen = sizeof(pacBuf.len) + sizeof(pacBuf.msgtype) + strlen(startup.user) + 1;
pacBuf.len = htonl(pacLen);
pacBuf.msgtype = htonl(STARTUP_USER_MSG);
strcpy(pacBuf.data, startup.user);
status = packetSend(port, &pacBuf, pacLen, BLOCKING);
if (status == STATUS_ERROR) {
sprintf(conn->errorMessage, "connectDB() -- couldn't send complete packet: errno=%d\n%s\n", errno, strerror(errno));
goto connect_errReturn;
}
/* Check to see if the server sent us a salt back to encrypt the
* password to send for authentication. --TAB
*/
status = packetReceive(port, &pacBuf, BLOCKING);
if (status != STATUS_OK) {
sprintf(conn->errorMessage, "connectDB() -- couldn't receive un/salt packet: errno=%d\n%s\n", errno, strerror(errno));
goto connect_errReturn;
}
pacBuf.msgtype = ntohl(pacBuf.msgtype);
switch (pacBuf.msgtype) {
case STARTUP_SALT_MSG:
salted = true;
if (!conn->pgpass) {
sprintf(conn->errorMessage, "connectDB() -- backend requested a password, but none was given\n");
goto connect_errReturn;
}
tmp = crypt(conn->pgpass, pacBuf.data);
free((void*)conn->pgpass);
conn->pgpass = strdup(tmp);
break;
case STARTUP_UNSALT_MSG:
salted = false;
break;
default:
sprintf(conn->errorMessage, "connectDB() -- backend did not supply a salt packet\n");
goto connect_errReturn;
}
if (salted)
msgtype = STARTUP_CRYPT_MSG;
else
msgtype = fe_getauthsvc(conn->errorMessage);
/* pacBuf = startup2PacketBuf(&startup);*/
startup2PacketBuf(&startup, &pacBuf);
@ -820,6 +887,63 @@ packetSend(Port *port,
return (STATUS_OK);
}
/*
* packetReceive()
*
This is a less stringent PacketReceive(), defined in backend/libpq/pqpacket.c
We define it here to avoid linking in all of libpq.a
* packetReceive -- receive a packet on a port
*
* RETURNS: STATUS_ERROR if the read fails, STATUS_OK otherwise.
* SIDE_EFFECTS: may block.
* NOTES: Non-blocking reads would significantly complicate
* buffer management. For now, we're not going to do it.
*
*/
int
packetReceive(Port *port, PacketBuf *buf, bool nonBlocking) {
PacketLen max_size = sizeof(PacketBuf);
PacketLen cc; /* character count -- recvd */
PacketLen packetLen;
int addrLen = sizeof(struct sockaddr_in);
int hdrLen;
int msgLen;
/* Read the packet length into the PacketBuf
*/
hdrLen = sizeof(PacketLen);
cc = recvfrom(port->sock, (char*)&packetLen, hdrLen, 0, (struct sockaddr*)&port->raddr, &addrLen);
if (cc < 0)
return STATUS_ERROR;
else if (!cc)
return STATUS_INVALID;
else if (cc < hdrLen)
return STATUS_NOT_DONE;
/* convert to local form of integer and check for oversized packet
*/
buf->len = packetLen;
if ((packetLen = ntohl(packetLen)) > max_size) {
port->nBytes = packetLen;
return STATUS_INVALID;
}
/* fetch the rest of the message
*/
msgLen = packetLen - cc;
cc = recvfrom(port->sock, (char*)&buf->msgtype, msgLen, 0, (struct sockaddr*)&port->raddr, &addrLen);
if (cc < 0)
return STATUS_ERROR;
else if (!cc)
return STATUS_INVALID;
else if (cc < msgLen)
return STATUS_NOT_DONE;
return STATUS_OK;
}
/*
* startup2PacketBuf()
*