mirror of
https://github.com/postgres/postgres.git
synced 2025-06-30 21:42:05 +03:00
From: todd brandys <brandys@eng3.hep.uiuc.edu>
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:
@ -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()
|
||||
*
|
||||
|
Reference in New Issue
Block a user