summaryrefslogtreecommitdiff
path: root/src/interfaces/libpq/fe-connect.c
diff options
context:
space:
mode:
authorMarc G. Fournier <scrappy@hub.org>1997-12-04 00:28:15 +0000
committerMarc G. Fournier <scrappy@hub.org>1997-12-04 00:28:15 +0000
commit4c04f7724ed4b9aa798810f2cd016b6520a4f2a6 (patch)
treef04eaeed04ad6f4314091828e03e7acafa548510 /src/interfaces/libpq/fe-connect.c
parent333323f304af75ee286367a7f84acc74ed16dd82 (diff)
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
Diffstat (limited to 'src/interfaces/libpq/fe-connect.c')
-rw-r--r--src/interfaces/libpq/fe-connect.c136
1 files changed, 130 insertions, 6 deletions
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index cd5331f7981..84fa1f6742c 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -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);
@@ -821,6 +888,63 @@ packetSend(Port *port,
}
/*
+ * 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()
*
* this is just like StartupInfo2Packet(), defined in backend/libpq/pqpacket.c