Commit d5bbe2ac authored by Marc G. Fournier's avatar Marc G. Fournier

From: Phil Thompson <phil@river-bank.demon.co.uk>

I've completed the patch to fix the protocol and authentication issues I
was discussing a couple of weeks ago.  The particular changes are:

- the protocol has a version number
- network byte order is used throughout
- the pg_hba.conf file is used to specify what method is used to
  authenticate a frontend (either password, ident, trust, reject, krb4
  or krb5)
- support for multiplexed backends is removed
- appropriate changes to man pages
- the -a switch to many programs to specify an authentication service
  no longer has any effect
- the libpq.so version number has changed to 1.1

The new backend still supports the old protocol so old interfaces won't
break.
parent 91d983aa
This diff is collapsed.
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/libpq/Attic/be-dumpdata.c,v 1.9 1997/09/12 04:07:50 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/libpq/Attic/be-dumpdata.c,v 1.10 1998/01/26 01:41:05 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -34,7 +34,7 @@
#include <postgres.h>
#include <lib/dllist.h>
#include <libpq/libpq-be.h>
#include <libpq/libpq.h>
#include <access/heapam.h>
#include <access/htup.h>
#include <storage/buf.h>
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/libpq/Attic/be-pqexec.c,v 1.13 1998/01/07 21:03:16 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/libpq/Attic/be-pqexec.c,v 1.14 1998/01/26 01:41:06 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -27,7 +27,7 @@
#include <tcop/fastpath.h>
#include <tcop/tcopprot.h>
#include <lib/dllist.h>
#include <libpq/libpq-be.h>
#include <libpq/libpq.h>
#include <fmgr.h>
#include <utils/exc.h>
#include <utils/builtins.h>
......
......@@ -17,9 +17,6 @@
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif
#include "postgres.h"
#include "miscadmin.h"
......@@ -27,6 +24,10 @@
#include "storage/fd.h"
#include "libpq/crypt.h"
#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif
char** pwd_cache = NULL;
int pwd_cache_count = 0;
......@@ -219,6 +220,7 @@ int crypt_getloginfo(const char* user, char** passwd, char** valuntil) {
/*-------------------------------------------------------------------------*/
#ifdef 0
MsgType crypt_salt(const char* user) {
char* passwd;
......@@ -237,6 +239,7 @@ MsgType crypt_salt(const char* user) {
if (valuntil) free((void*)valuntil);
return STARTUP_SALT_MSG;
}
#endif
/*-------------------------------------------------------------------------*/
......@@ -258,7 +261,13 @@ int crypt_verify(Port* port, const char* user, const char* pgpass) {
return STATUS_ERROR;
}
crypt_pwd = crypt(passwd, port->salt);
/*
* Compare with the encrypted or plain password depending on the
* authentication method being used for this connection.
*/
crypt_pwd = (port->auth_method == uaCrypt ? crypt(passwd, port->salt) : passwd);
if (!strcmp(pgpass, crypt_pwd)) {
/* check here to be sure we are not past valuntil
*/
......
This diff is collapsed.
#include <postgres.h>
#include <miscadmin.h>
#include <libpq/password.h>
#include <libpq/hba.h>
#include <libpq/libpq.h>
#include <storage/fd.h>
#include <string.h>
......@@ -10,56 +10,15 @@
#endif
int
verify_password(char *user, char *password, Port *port,
char *database, char *DataDir)
verify_password(char *auth_arg, char *user, char *password)
{
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;
find_hba_entry(DataDir, port->raddr.in.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 *) palloc(strlen(DataDir) + strlen(pw_file_name) + 2);
pw_file_fullname = (char *) palloc(strlen(DataDir) + strlen(auth_arg) + 2);
strcpy(pw_file_fullname, DataDir);
strcat(pw_file_fullname, "/");
strcat(pw_file_fullname, pw_file_name);
strcat(pw_file_fullname, auth_arg);
pw_file = AllocateFile(pw_file_fullname, "r");
if (!pw_file)
......@@ -69,12 +28,17 @@ verify_password(char *user, char *password, Port *port,
pw_file_fullname);
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
pfree(pw_file_fullname);
return STATUS_ERROR;
}
while (!feof(pw_file))
{
fgets(pw_file_line, 255, pw_file);
char pw_file_line[255], *p, *test_user, *test_pw;
fgets(pw_file_line, sizeof (pw_file_line), pw_file);
p = pw_file_line;
test_user = strtok(p, ":");
......@@ -97,6 +61,9 @@ verify_password(char *user, char *password, Port *port,
if (strcmp(crypt(password, test_pw), test_pw) == 0)
{
/* it matched. */
pfree(pw_file_fullname);
return STATUS_OK;
}
......@@ -105,6 +72,9 @@ verify_password(char *user, char *password, Port *port,
user);
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
pfree(pw_file_fullname);
return STATUS_ERROR;
}
}
......@@ -114,5 +84,8 @@ verify_password(char *user, char *password, Port *port,
user);
fputs(PQerrormsg, stderr);
pqdebug("%s", PQerrormsg);
pfree(pw_file_fullname);
return STATUS_ERROR;
}
......@@ -4,6 +4,7 @@
#
# This file controls what hosts are allowed to connect to what databases
# and specifies some options on how users on a particular host are identified.
# It is read each time a host tries to make a connection to a database.
#
# Each line (terminated by a newline character) is a record. A record cannot
# be continued across two lines.
......@@ -29,13 +30,14 @@
# Record type "host"
# ------------------
#
# This record identifies a set of hosts that are permitted to connect to
# databases. No hosts are permitted to connect except as specified by a
# "host" record.
# This record identifies a set of network hosts that are permitted to connect
# to databases. No network hosts are permitted to connect except as specified
# by a "host" record. See the record type "local" to specify permitted
# connections using UNIX sockets.
#
# Format:
#
# host DBNAME IP_ADDRESS ADDRESS_MASK USERAUTH [MAP]
# host DBNAME IP_ADDRESS ADDRESS_MASK USERAUTH [AUTH_ARGUMENT]
#
# DBNAME is the name of a Postgres database, or "all" to indicate all
# databases.
......@@ -49,33 +51,54 @@
# under the Postgres username he supplies in his connection parameters.
#
# ident: Authentication is done by the ident server on the remote
# host, via the ident (RFC 1413) protocol.
# host, via the ident (RFC 1413) protocol. AUTH_ARGUMENT, if
# specified, is a map name to be found in the pg_ident.conf file.
# That table maps from ident usernames to Postgres usernames. The
# special map name "sameuser" indicates an implied map (not found
# in pg_ident.conf) that maps every ident username to the identical
# Postgres username.
#
# trust: No authentication is done. Trust that the user has the
# authority to user whatever username he says he does.
# Before Postgres Version 6, all authentication was this way.
#
# MAP is the name of a map that matches an authenticated principal with
# a Postgres username. If USERNAME is "trust", this value is ignored and
# may be absent.
# reject: Reject the connection.
#
# In the case of USERAUTH=ident, this is a map name to be found in the
# pg_ident.conf file. That table maps from ident usernames to Postgres
# usernames. The special map name "sameuser" indicates an implied map
# (not found in pg_ident.conf) that maps every ident username to the identical
# Postgres username.
# password: Authentication is done by matching a password supplied in clear
# by the host. If AUTH_ARGUMENT is specified then the password is
# compared with the user's entry in that file (in the $PGDATA
# directory). See pg_passwd(1). If it is omitted then the
# password is compared with the user's entry in the pg_user table.
#
# crypt: Authentication is done by matching an encrypted password supplied
# by the host with that held for the user in the pg_user table.
#
# krb4: Kerberos V4 authentication is used.
#
# krb5: Kerberos V5 authentication is used.
# Record type "local"
# ------------------
#
# This record identifies the authentication to use when connecting to a
# particular database via a local UNIX socket.
#
# Format:
#
# local DBNAME USERAUTH [AUTH_ARGUMENT]
#
# The format is the same as that of the "host" record type except that the
# IP_ADDRESS and ADDRESS_MASK are omitted and the "ident", "krb4" and "krb5"
# values of USERAUTH are no allowed.
# For backwards compatibility, PostgreSQL also accepts pre-Version 6 records,
# which look like:
#
# all 127.0.0.1 0.0.0.0
#
#
# TYPE DATABASE IP_ADDRESS MASK USERAUTH MAP
host all 127.0.0.1 255.255.255.255 trust
#host all 127.0.0.1 255.255.255.255 trust
# The above allows any user on the local system to connect to any database
# under any username.
......@@ -86,10 +109,11 @@ host all 127.0.0.1 255.255.255.255 trust
# connect to database template1 as the same username that ident on that host
# identifies him as (typically his Unix username).
#host all 192.168.0.1 255.255.255.255 reject
#host all 0.0.0.0 0.0.0.0 trust
# The above would allow anyone anywhere to connect to any database under
# any username.
# The above would allow anyone anywhere except from 192.168.0.1 to connect to
# any database under any username.
#host all 192.168.0.0 255.255.255.0 ident omicron
#
......
......@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.34 1998/01/25 05:13:18 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.35 1998/01/26 01:41:11 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -43,6 +43,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
......@@ -269,28 +270,6 @@ int
pq_getnchar(char *s, int off, int maxlen)
{
return pqGetNBytes(s + off, maxlen, Pfin);
#if 0
int c = '\0';
if (Pfin == (FILE *) NULL)
{
/* elog(DEBUG, "Input descriptor is null"); */
return (EOF);
}
s += off;
while (maxlen-- && (c = pq_getc(Pfin)) != EOF)
*s++ = c;
/* -----------------
* If EOF reached let caller know
* -----------------
*/
if (c == EOF)
return (EOF);
return (!EOF);
#endif
}
/* --------------------------------
......@@ -591,11 +570,7 @@ do_unlink()
int
StreamServerPort(char *hostName, short portName, int *fdP)
{
union
{
struct sockaddr_in in;
struct sockaddr_un un;
} saddr;
SockAddr saddr;
int fd,
err,
family;
......@@ -624,20 +599,19 @@ StreamServerPort(char *hostName, short portName, int *fdP)
return (STATUS_ERROR);
}
bzero(&saddr, sizeof(saddr));
saddr.sa.sa_family = family;
if (family == AF_UNIX)
{
saddr.un.sun_family = family;
len = UNIXSOCK_PATH(saddr.un, portName);
strcpy(sock_path, saddr.un.sun_path);
}
else
{
saddr.in.sin_family = family;
saddr.in.sin_addr.s_addr = htonl(INADDR_ANY);
saddr.in.sin_port = htons(portName);
len = sizeof saddr.in;
len = sizeof (struct sockaddr_in);
}
err = bind(fd, (struct sockaddr *) & saddr, len);
err = bind(fd, &saddr.sa, len);
if (err < 0)
{
sprintf(PQerrormsg,
......@@ -685,7 +659,7 @@ StreamConnection(int server_fd, Port *port)
{
int len,
addrlen;
int family = port->raddr.in.sin_family;
int family = port->raddr.sa.sa_family;
/* accept connection (and fill in the client (remote) address) */
len = family == AF_INET ?
......@@ -726,8 +700,6 @@ StreamConnection(int server_fd, Port *port)
}
}
port->mask = 1 << port->sock;
/* reset to non-blocking */
fcntl(port->sock, F_SETFL, 1);
......@@ -788,7 +760,7 @@ StreamOpen(char *hostName, short portName, Port *port)
len = UNIXSOCK_PATH(port->raddr.un, portName);
}
/* connect to the server */
if ((port->sock = socket(port->raddr.in.sin_family, SOCK_STREAM, 0)) < 0)
if ((port->sock = socket(port->raddr.sa.sa_family, SOCK_STREAM, 0)) < 0)
{
sprintf(PQerrormsg,
"FATAL: StreamOpen: socket() failed: errno=%d\n",
......@@ -797,7 +769,7 @@ StreamOpen(char *hostName, short portName, Port *port)
pqdebug("%s", PQerrormsg);
return (STATUS_ERROR);
}
err = connect(port->sock, (struct sockaddr *) & port->raddr, len);
err = connect(port->sock, &port->raddr.sa, len);
if (err < 0)
{
sprintf(PQerrormsg,
......@@ -809,8 +781,7 @@ StreamOpen(char *hostName, short portName, Port *port)
}
/* fill in the client address */
if (getsockname(port->sock, (struct sockaddr *) & port->laddr,
&len) < 0)
if (getsockname(port->sock, &port->laddr.sa, &len) < 0)
{
sprintf(PQerrormsg,
"FATAL: StreamOpen: getsockname() failed: errno=%d\n",
......@@ -822,32 +793,3 @@ 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;
}
#include <stdlib.h>
#include <stdio.h>
#include <netinet/in.h>
#include "postgres.h"
#include "libpq/pqcomm.h"
/*
* The backend supports the old little endian byte order and the current
* network byte order.
*/
#ifndef FRONTEND
#include "libpq/libpq-be.h"
#ifdef HAVE_ENDIAN_H
#include <endian.h>
#endif
/* --------------------------------------------------------------------- */
/* These definitions for ntoh/hton are the other way around from the
* default system definitions, so we roll our own here.
*/
#ifndef BYTE_ORDER
#error BYTE_ORDER must be defined as LITTLE_ENDIAN, BIG_ENDIAN or PDP_ENDIAN
#endif
#if BYTE_ORDER == LITTLE_ENDIAN
#define ntoh_s(n) n
#define ntoh_l(n) n
#define hton_s(n) n
#define hton_l(n) n
#else /* BYTE_ORDER != LITTLE_ENDIAN */
#else
#if BYTE_ORDER == BIG_ENDIAN
#define ntoh_s(n) (u_short)(((u_char *)&n)[1] << 8 \
#define ntoh_s(n) (uint16)(((u_char *)&n)[1] << 8 \
| ((u_char *)&n)[0])
#define ntoh_l(n) (uint32) (((u_char *)&n)[3] << 24 \
#define ntoh_l(n) (uint32)(((u_char *)&n)[3] << 24 \
| ((u_char *)&n)[2] << 16 \
| ((u_char *)&n)[1] << 8 \
| ((u_char *)&n)[0])
#define hton_s(n) (ntoh_s(n))
#define hton_l(n) (ntoh_l(n))
#else
/* BYTE_ORDER != BIG_ENDIAN */
#if BYTE_ORDER == PDP_ENDIAN
#error PDP_ENDIAN macros not written yet
#else
/* BYTE_ORDER != anything known */
#error BYTE_ORDER not defined as anything understood
#endif /* BYTE_ORDER == PDP_ENDIAN */
#endif /* BYTE_ORDER == BIG_ENDIAN */
#endif /* BYTE_ORDER == LITTLE_ENDIAN */
#endif
#endif
#endif
#endif
/* --------------------------------------------------------------------- */
int
pqPutShort(int integer, FILE *f)
{
int retval = 0;
u_short n,
s;
uint16 n;
s = integer;
n = hton_s(s);
if (fwrite(&n, sizeof(u_short), 1, f) != 1)
retval = EOF;
#ifdef FRONTEND
n = htons((uint16)integer);
#else
n = ((PG_PROTOCOL_MAJOR(FrontendProtocol) == 0) ? hton_s(integer) : htons((uint16)integer));
#endif
return retval;
if (fwrite(&n, 2, 1, f) != 1)
return EOF;
return 0;
}
/* --------------------------------------------------------------------- */
int
pqPutLong(int integer, FILE *f)
{
int retval = 0;
uint32 n;
n = hton_l(integer);
if (fwrite(&n, sizeof(uint32), 1, f) != 1)
retval = EOF;
#ifdef FRONTEND
n = htonl((uint32)integer);
#else
n = ((PG_PROTOCOL_MAJOR(FrontendProtocol) == 0) ? hton_l(integer) : htonl((uint32)integer));
#endif
return retval;
if (fwrite(&n, 4, 1, f) != 1)
return EOF;
return 0;
}
/* --------------------------------------------------------------------- */
int
pqGetShort(int *result, FILE *f)
{
int retval = 0;
u_short n;
uint16 n;
if (fread(&n, sizeof(u_short), 1, f) != 1)
retval = EOF;
if (fread(&n, 2, 1, f) != 1)
return EOF;
#ifdef FRONTEND
*result = (int)ntohs(n);
#else
*result = (int)((PG_PROTOCOL_MAJOR(FrontendProtocol) == 0) ? ntoh_s(n) : ntohs(n));
#endif
*result = ntoh_s(n);
return retval;
return 0;
}
/* --------------------------------------------------------------------- */
int
pqGetLong(int *result, FILE *f)
{
int retval = 0;
uint32 n;
if (fread(&n, sizeof(uint32), 1, f) != 1)
retval = EOF;
if (fread(&n, 4, 1, f) != 1)
return EOF;
#ifdef FRONTEND
*result = (int)ntohl(n);
#else
*result = (int)((PG_PROTOCOL_MAJOR(FrontendProtocol) == 0) ? ntoh_l(n) : ntohl(n));
#endif
*result = ntoh_l(n);
return retval;
return 0;
}
/* --------------------------------------------------------------------- */
/* pqGetNBytes: Read a chunk of exactly len bytes in buffer s.
/* pqGetNBytes: Read a chunk of exactly len bytes in buffer s (which must be 1
byte longer) and terminate it with a '\0'.
Return 0 if ok.
*/
int
......@@ -116,7 +145,6 @@ pqGetNBytes(char *s, size_t len, FILE *f)
cnt = fread(s, 1, len, f);
s[cnt] = '\0';
/* mjl: actually needs up to len+1 bytes, is this okay? XXX */
return (cnt == len) ? 0 : EOF;
}
......@@ -126,7 +154,7 @@ int
pqPutNBytes(const char *s, size_t len, FILE *f)
{
if (f == NULL)
return 0;
return EOF;
if (fwrite(s, 1, len, f) != len)
return EOF;
......@@ -143,10 +171,22 @@ pqGetString(char *s, size_t len, FILE *f)
if (f == NULL)
return EOF;
while (len-- && (c = getc(f)) != EOF && c)
/*
* Keep on reading until we get the terminating '\0' and discard those
* bytes we don't have room for.
*/
while ((c = getc(f)) != EOF && c != '\0')
if (len > 1)
{
*s++ = c;
len--;
}
*s = '\0';
/* mjl: actually needs up to len+1 bytes, is this okay? XXX */
if (c == EOF)
return EOF;
return 0;
}
......@@ -183,5 +223,3 @@ pqPutByte(int c, FILE *f)
return (putc(c, f) == c) ? 0 : EOF;
}
/* --------------------------------------------------------------------- */
......@@ -8,36 +8,14 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/libpq/Attic/pqpacket.c,v 1.12 1997/12/09 03:10:51 scrappy Exp $
* $Header: /cvsroot/pgsql/src/backend/libpq/Attic/pqpacket.c,v 1.13 1998/01/26 01:41:12 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
/* NOTES
* This is the module that understands the lowest-level part
* of the communication protocol. All of the trickiness in
* this module is for making sure that non-blocking I/O in
* the Postmaster works correctly. Check the notes in PacketRecv
* on non-blocking I/O.
*
* Data Structures:
* Port has two important functions. (1) It records the
* sock/addr used in communication. (2) It holds partially
* read in messages. This is especially important when
* we haven't seen enough to construct a complete packet
* header.
*
* PacketBuf -- None of the clients of this module should know
* what goes into a packet hdr (although they know how big
* it is). This routine is in charge of host to net order
* conversion for headers. Data conversion is someone elses
* responsibility.
*
* IMPORTANT: these routines are called by backends, clients, and
* the Postmaster.
*
*/
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
......@@ -50,260 +28,158 @@
#include <storage/ipc.h>
#include <libpq/libpq.h>
/*
* PacketReceive -- receive a packet on a port.
*
* RETURNS: connection id of the packet sender, if one
* is available.
*
* Set up a packet read for the postmaster event loop.
*/
int
PacketReceive(Port *port, /* receive port */
PacketBuf *buf, /* MAX_PACKET_SIZE-worth of buffer space */
bool nonBlocking) /* NON_BLOCKING or BLOCKING i/o */
void PacketReceiveSetup(Packet *pkt, void (*iodone)(), char *arg)
{
PacketLen max_size = sizeof(PacketBuf);
PacketLen cc; /* character count -- bytes recvd */
PacketLen packetLen; /* remaining packet chars to read */
Addr tmp; /* curr recv buf pointer */
int hdrLen;
int flag;
int decr;
pkt->nrtodo = sizeof (pkt->len);
pkt->ptr = (char *)&pkt->len;
pkt->iodone = iodone;
pkt->arg = arg;
pkt->state = ReadingPacketLength;
}
hdrLen = sizeof(buf->len);
if (nonBlocking == NON_BLOCKING)
{
flag = MSG_PEEK;
decr = 0;
}
else
{
flag = 0;
decr = hdrLen;
}
/*
* Assume port->nBytes is zero unless we were interrupted during
* non-blocking I/O. This first recv() is to get the hdr information
* so we know how many bytes to read. Life would be very complicated
* if we read too much data (buffering).
/*
* Read a packet fragment. Return STATUS_OK if the connection should stay
* open.
*/
tmp = ((Addr) buf) + port->nBytes;
if (port->nBytes >= hdrLen)
{
packetLen = ntohl(buf->len) - port->nBytes;
}
else
{
/* peeking into the incoming message */
cc = recv(port->sock, (char *) &(buf->len), hdrLen, flag);
if (cc < hdrLen)
{
/* if cc is negative, the system call failed */
if (cc < 0)
{
return (STATUS_ERROR);
}
int PacketReceiveFragment(Packet *pkt, int sock)
{
int got;
/*
* cc == 0 means the connection was broken at the other end.
*/
else if (!cc)
if ((got = read(sock,pkt->ptr,pkt->nrtodo)) > 0)
{
return (STATUS_INVALID);
pkt->nrtodo -= got;
pkt->ptr += got;
}
else
{
/* See if we have got what we need for the packet length. */
/*
* Worst case. We didn't even read in enough data to get
* the header length. since we are using a data stream,
* this happens only if the client is mallicious.
*
* Don't save the number of bytes we've read so far. Since we
* only peeked at the incoming message, the kernel is
* going to keep it for us.
*/
return (STATUS_NOT_DONE);
}
}
else
if (pkt->nrtodo == 0 && pkt->state == ReadingPacketLength)
{
pkt->len = ntohl(pkt->len);
/*
* This is an attempt to shield the Postmaster from mallicious
* attacks by placing tighter restrictions on the reported
* packet length.
*
* Check for negative packet length
*/
if ((buf->len) <= 0)
if (pkt->len < sizeof (pkt->len) ||
pkt->len > sizeof (pkt->len) + sizeof (pkt->pkt))
{
return (STATUS_INVALID);
PacketSendError(pkt,"Invalid packet length");
return STATUS_OK;
}
/*
* Check for oversize packet
*/
if ((ntohl(buf->len)) > max_size)
{
return (STATUS_INVALID);
/* Set up for the rest of the packet. */
pkt->nrtodo = pkt->len - sizeof (pkt->len);
pkt->ptr = (char *)&pkt->pkt;
pkt->state = ReadingPacket;
}
/*
* great. got the header. now get the true length (including
* header size).
*/
packetLen = ntohl(buf->len);
/* See if we have got what we need for the packet. */
/*
* if someone is sending us junk, close the connection
*/
if (packetLen > max_size)
if (pkt->nrtodo == 0 && pkt->state == ReadingPacket)
{
port->nBytes = packetLen;
return (STATUS_BAD_PACKET);
}
packetLen -= decr;
tmp += decr - port->nBytes;
pkt->state = Idle;
/* Special case to close the connection. */
if (pkt->iodone == NULL)
return STATUS_ERROR;
(*pkt->iodone)(pkt->arg, pkt->len - sizeof (pkt->len),
(char *)&pkt->pkt);
}
return STATUS_OK;
}
/*
* Now that we know how big it is, read the packet. We read the
* entire packet, since the last call was just a peek.
*/
while (packetLen)
{
cc = read(port->sock, tmp, packetLen);
if (cc < 0)
return (STATUS_ERROR);
if (got == 0)
return STATUS_ERROR;
if (errno == EINTR)
return STATUS_OK;
fprintf(stderr, "read() system call failed\n");
return STATUS_ERROR;
}
/*
* cc == 0 means the connection was broken at the other end.
*/
else if (!cc)
return (STATUS_INVALID);
/*
fprintf(stderr,"expected packet of %d bytes, got %d bytes\n",
packetLen, cc);
*/
tmp += cc;
packetLen -= cc;
/* if non-blocking, we're done. */
if (nonBlocking && packetLen)
{
port->nBytes += cc;
return (STATUS_NOT_DONE);
}
}
* Set up a packet write for the postmaster event loop.
*/
port->nBytes = 0;
return (STATUS_OK);
void PacketSendSetup(Packet *pkt, int nbytes, void (*iodone)(), char *arg)
{
pkt->nrtodo = nbytes;
pkt->ptr = (char *)&pkt->pkt;
pkt->iodone = iodone;
pkt->arg = arg;
pkt->state = WritingPacket;
}
/*
* PacketSend -- send a single-packet message.
*
* RETURNS: STATUS_ERROR if the write fails, STATUS_OK otherwise.
* SIDE_EFFECTS: may block.
* NOTES: Non-blocking writes would significantly complicate
* buffer management. For now, we're not going to do it.
*
* Write a packet fragment. Return STATUS_OK if the connection should stay
* open.
*/
int
PacketSend(Port *port,
PacketBuf *buf,
PacketLen len,
bool nonBlocking)
int PacketSendFragment(Packet *pkt, int sock)
{
PacketLen doneLen;
int done;
if ((done = write(sock,pkt->ptr,pkt->nrtodo)) > 0)
{
pkt->nrtodo -= done;
pkt->ptr += done;
Assert(!nonBlocking);
Assert(buf);
/* See if we have written the whole packet. */
doneLen = write(port->sock, buf, len);
if (doneLen < len)
if (pkt->nrtodo == 0)
{
sprintf(PQerrormsg,
"FATAL: PacketSend: couldn't send complete packet: errno=%d\n",
errno);
fputs(PQerrormsg, stderr);
return (STATUS_ERROR);
pkt->state = Idle;
/* Special case to close the connection. */
if (pkt->iodone == NULL)
return STATUS_ERROR;
(*pkt->iodone)(pkt->arg);
}
return (STATUS_OK);
return STATUS_OK;
}
if (done == 0)
return STATUS_ERROR;
if (errno == EINTR)
return STATUS_OK;
fprintf(stderr, "write() system call failed\n");
return STATUS_ERROR;
}
/*
* StartupInfo2PacketBuf -
* convert the fields of the StartupInfo to a PacketBuf
*
* Send an error message from the postmaster to the frontend.
*/
/* moved to src/libpq/fe-connect.c */
/*
PacketBuf*
StartupInfo2PacketBuf(StartupInfo* s)
void PacketSendError(Packet *pkt, char *errormsg)
{
PacketBuf* res;
char* tmp;
res = (PacketBuf*)palloc(sizeof(PacketBuf));
res->len = htonl(sizeof(PacketBuf));
res->data[0] = '\0';
tmp= res->data;
strncpy(tmp, s->database, sizeof(s->database));
tmp += sizeof(s->database);
strncpy(tmp, s->user, sizeof(s->user));
tmp += sizeof(s->user);
strncpy(tmp, s->options, sizeof(s->options));
tmp += sizeof(s->options);
strncpy(tmp, s->execFile, sizeof(s->execFile));
tmp += sizeof(s->execFile);
strncpy(tmp, s->tty, sizeof(s->execFile));
return res;
}
*/
fprintf(stderr, "%s\n", errormsg);
/*
* PacketBuf2StartupInfo -
* convert the fields of the StartupInfo to a PacketBuf
*
pkt->pkt.em.data[0] = 'E';
StrNCpy(&pkt->pkt.em.data[1], errormsg, sizeof (pkt->pkt.em.data) - 2);
/*
* The NULL i/o callback will cause the connection to be broken when
* the error message has been sent.
*/
/* moved to postmaster.c
StartupInfo*
PacketBuf2StartupInfo(PacketBuf* p)
{
StartupInfo* res;
char* tmp;
res = (StartupInfo*)palloc(sizeof(StartupInfo));
res->database[0]='\0';
res->user[0]='\0';
res->options[0]='\0';
res->execFile[0]='\0';
res->tty[0]='\0';
tmp= p->data;
strncpy(res->database,tmp,sizeof(res->database));
tmp += sizeof(res->database);
strncpy(res->user,tmp, sizeof(res->user));
tmp += sizeof(res->user);
strncpy(res->options,tmp, sizeof(res->options));
tmp += sizeof(res->options);
strncpy(res->execFile,tmp, sizeof(res->execFile));
tmp += sizeof(res->execFile);
strncpy(res->tty,tmp, sizeof(res->tty));
return res;
PacketSendSetup(pkt, strlen(pkt->pkt.em.data) + 1, NULL, NULL);
}
*/
This diff is collapsed.
......@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/dest.c,v 1.15 1997/12/06 22:57:02 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/tcop/dest.c,v 1.16 1998/01/26 01:41:23 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -29,7 +29,7 @@
#include "postgres.h"
#include "access/htup.h"
#include "libpq/libpq-be.h"
#include "libpq/libpq.h"
#include "access/printtup.h"
#include "utils/portal.h"
#include "utils/palloc.h"
......
......@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/fastpath.c,v 1.11 1998/01/11 21:16:01 scrappy Exp $
* $Header: /cvsroot/pgsql/src/backend/tcop/fastpath.c,v 1.12 1998/01/26 01:41:28 scrappy Exp $
*
* NOTES
* This cruft is the server side of PQfn.
......@@ -336,7 +336,7 @@ HandleFunctionRequest()
else
{ /* ... fixed */
/* XXX cross our fingers and trust "argsize" */
if (!(p = palloc(argsize)))
if (!(p = palloc(argsize + 1)))
{
elog(ERROR, "HandleFunctionRequest: palloc failed");
}
......
This diff is collapsed.
......@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.18 1998/01/25 05:14:42 momjian Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.19 1998/01/26 01:41:42 scrappy Exp $
*
* NOTES
* Globals used all over the place should be declared here and not
......@@ -32,9 +32,10 @@
#include "storage/sinvaladt.h"
#include "storage/lmgr.h"
#include "utils/elog.h"
#include "libpq/pqcomm.h"
#include "catalog/catname.h"
ProtocolVersion FrontendProtocol = PG_PROTOCOL_LATEST;
int Portfd = -1;
int Noversion = 0;
int Quiet = 1;
......
......@@ -7,7 +7,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: c.h,v 1.28 1998/01/24 22:47:43 momjian Exp $
* $Id: c.h,v 1.29 1998/01/26 01:41:49 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -204,21 +204,23 @@ typedef char *Pointer;
/*
* intN --
* Signed integer, AT LEAST N BITS IN SIZE,
* used for numerical computations.
* Signed integer, EXACTLY N BITS IN SIZE,
* used for numerical computations and the
* frontend/backend protocol.
*/
typedef signed char int8; /* >= 8 bits */
typedef signed short int16; /* >= 16 bits */
typedef signed int int32; /* >= 32 bits */
typedef signed char int8; /* == 8 bits */
typedef signed short int16; /* == 16 bits */
typedef signed int int32; /* == 32 bits */
/*
* uintN --
* Unsigned integer, AT LEAST N BITS IN SIZE,
* used for numerical computations.
* Unsigned integer, EXACTLY N BITS IN SIZE,
* used for numerical computations and the
* frontend/backend protocol.
*/
typedef unsigned char uint8; /* >= 8 bits */
typedef unsigned short uint16; /* >= 16 bits */
typedef unsigned int uint32; /* >= 32 bits */
typedef unsigned char uint8; /* == 8 bits */
typedef unsigned short uint16; /* == 16 bits */
typedef unsigned int uint32; /* == 32 bits */
/*
* floatN --
......
......@@ -6,40 +6,22 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: auth.h,v 1.7 1997/09/08 21:52:28 momjian Exp $
* $Id: auth.h,v 1.8 1998/01/26 01:42:05 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef AUTH_H
#define AUTH_H
#include <libpq/pqcomm.h>
#include "libpq/libpq-be.h"
/*----------------------------------------------------------------
* Common routines and definitions
*----------------------------------------------------------------
*/
/* what we call "no authentication system" */
#define UNAUTHNAME "unauth"
/* what a frontend uses by default */
#if !defined(KRB4) && !defined(KRB5)
#define DEFAULT_CLIENT_AUTHSVC UNAUTHNAME
#else /* KRB4 || KRB5 */
#define DEFAULT_CLIENT_AUTHSVC "kerberos"
#endif /* KRB4 || KRB5 */
extern int fe_sendauth(MsgType msgtype, Port *port, char *hostname);
extern void fe_setauthsvc(char *name);
extern MsgType fe_getauthsvc();
extern char *fe_getauthname(void);
extern int be_recvauth(MsgType msgtype, Port *port, char *username, StartupInfo *sp);
extern void be_setauthsvc(char *name);
/* the value that matches any dbName value when doing
host based authentication*/
#define ALL_DBNAME "*"
void be_recvauth(Port *port);
void auth_failed(Port *port);
#define PG_KRB4_VERSION "PGVER4.1" /* at most KRB_SENDAUTH_VLEN chars */
#define PG_KRB5_VERSION "PGVER5.1"
......
......@@ -9,7 +9,7 @@
#ifndef PG_CRYPT_H
#define PG_CRYPT_H
#include <libpq/pqcomm.h>
#include <libpq/libpq-be.h>
#define CRYPT_PWD_FILE "pg_pwd"
#define CRYPT_PWD_FILE_SEPCHAR "'\\t'"
......@@ -21,7 +21,9 @@ extern int pwd_cache_count;
extern char* crypt_getpwdfilename(void);
extern char* crypt_getpwdreloadfilename(void);
#ifdef 0
extern MsgType crypt_salt(const char* user);
#endif
extern int crypt_verify(Port* port, const char* user, const char* pgpass);
#endif
......@@ -4,14 +4,17 @@
* Interface to hba.c
*
*
* $Id: hba.h,v 1.6 1998/01/24 22:49:15 momjian Exp $
* $Id: hba.h,v 1.7 1998/01/26 01:42:15 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef HBA_H
#define HBA_H
#include <libpq/pqcomm.h>
#include <netinet/in.h>
#include "libpq/libpq-be.h"
#define CONF_FILE "pg_hba.conf"
/* Name of the config file */
......@@ -28,7 +31,7 @@
#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 MAX_AUTH_ARG 80 /* Max size of an authentication arg */
#define IDENT_PORT 113
/* Standard TCP port number for Ident service. Assigned by IANA */
......@@ -36,18 +39,19 @@
#define IDENT_USERNAME_MAX 512
/* Max size of username ident server can return */
enum Userauth
{
Trust, Ident,
Password
};
extern int hba_recvauth(const Port *port, const char database[], const char user[],
const char DataDir[]);
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[], bool find_password_entries);
typedef enum UserAuth {
uaReject,
uaKrb4,
uaKrb5,
uaTrust,
uaIdent,
uaPassword,
uaCrypt
} UserAuth;
int hba_getauthmethod(SockAddr *raddr, char *database, char *auth_arg,
UserAuth *auth_method);
int authident(struct sockaddr_in *raddr, struct sockaddr_in *laddr,
const char postgres_username[], const char auth_arg[]);
#endif
......@@ -7,45 +7,126 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: libpq-be.h,v 1.8 1998/01/24 22:49:18 momjian Exp $
* $Id: libpq-be.h,v 1.9 1998/01/26 01:42:17 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef LIBPQ_BE_H
#define LIBPQ_BE_H
#include <access/htup.h>
#include <access/tupdesc.h>
#include <libpq/libpq.h>
#include <stdio.h>
#include <sys/types.h>
/* ----------------
* include stuff common to fe and be
* ----------------
#include "libpq/pqcomm.h"
#include "libpq/hba.h"
/* Protocol v0 password packet. */
typedef struct PasswordPacketV0 {
uint32 unused;
char data[288]; /* User and password as strings. */
} PasswordPacketV0;
/*
* Password packet. The length of the password can be changed without
* affecting anything.
*/
typedef struct PasswordPacket {
char passwd[100]; /* The password. */
} PasswordPacket;
/* Error message packet. */
typedef struct ErrorMessagePacket {
char data[1 + 100]; /* 'E' + the message. */
} ErrorMessagePacket;
/* Authentication request packet. */
typedef struct AuthRequestPacket {
char data[1 + sizeof (AuthRequest) + 2]; /* 'R' + the request + optional salt. */
} AuthRequestPacket;
/* These are used by the packet handling routines. */
typedef enum {
Idle,
ReadingPacketLength,
ReadingPacket,
WritingPacket
} PacketState;
typedef struct Packet {
PacketState state; /* What's in progress. */
PacketLen len; /* Actual length */
int nrtodo; /* Bytes still to transfer */
char *ptr; /* Buffer pointer */
void (*iodone)(); /* I/O complete callback */
char *arg; /* Argument to callback */
/* ----------------
* declarations for backend libpq support routines
* ----------------
/* A union of all the different packets. */
union {
/* These are outgoing so have no packet length prepended. */
ErrorMessagePacket em;
AuthRequestPacket ar;
/* These are incoming and have a packet length prepended. */
StartupPacket si;
PasswordPacketV0 pwv0;
PasswordPacket pw;
} pkt;
} Packet;
/*
* This is used by the postmaster in its communication with frontends. It is
* contains all state information needed during this communication before the
* backend is run.
*/
typedef struct Port {
int sock; /* File descriptor */
Packet pktInfo; /* For the packet handlers */
SockAddr laddr; /* local addr (us) */
SockAddr raddr; /* remote addr (them) */
char salt[2]; /* Password salt */
/*
* Information that needs to be held during the fe/be authentication
* handshake.
*/
/* in be-dumpdata.c */
extern void be_portalinit(void);
extern void be_portalpush(PortalEntry *entry);
extern PortalEntry *be_portalpop(void);
extern PortalEntry *be_currentportal(void);
extern PortalEntry *be_newportal(void);
extern void be_typeinit(PortalEntry *entry, TupleDesc attrs,
int natts);
extern void be_printtup(HeapTuple tuple, TupleDesc typeinfo);
/* in be-pqexec.c */
extern char * PQfn(int fnid, int *result_buf, int result_len, int result_is_int,
PQArgBlock *args, int nargs);
extern char *PQexec(char *query);
extern int pqtest_PQexec(char *q);
extern int pqtest_PQfn(char *q);
extern int32 pqtest(struct varlena * vlena);
ProtocolVersion proto;
char database[SM_DATABASE + 1];
char user[SM_USER + 1];
char options[SM_OPTIONS + 1];
char tty[SM_TTY + 1];
char auth_arg[MAX_AUTH_ARG];
UserAuth auth_method;
} Port;
extern FILE *Pfout, *Pfin;
extern int PQAsyncNotifyWaiting;
extern ProtocolVersion FrontendProtocol;
/*
* prototypes for functions in pqpacket.c
*/
void PacketReceiveSetup(Packet *pkt, void (*iodone)(), char *arg);
int PacketReceiveFragment(Packet *pkt, int sock);
void PacketSendSetup(Packet *pkt, int nbytes, void (*iodone)(), char *arg);
int PacketSendFragment(Packet *pkt, int sock);
void PacketSendError(Packet *pkt, char *errormsg);
#endif /* LIBPQ_BE_H */
......@@ -6,20 +6,19 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: libpq.h,v 1.9 1998/01/24 22:49:21 momjian Exp $
*
* NOTES
* This file contains definitions for structures and
* externs for functions used by both frontend applications
* and the POSTGRES backend. See the files libpq-fe.h and
* libpq-be.h for frontend/backend specific information
* $Id: libpq.h,v 1.10 1998/01/26 01:42:18 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef LIBPQ_H
#define LIBPQ_H
#include <libpq/pqcomm.h>
#include <netinet/in.h>
#include "libpq/libpq-be.h"
#include "access/htup.h"
#include "access/tupdesc.h"
/* ----------------
* PQArgBlock --
......@@ -228,6 +227,27 @@ extern int pbuf_findFnumber(GroupBuffer *group, char *field_name);
extern void pbuf_checkFnumber(GroupBuffer *group, int field_number);
extern char *pbuf_findFname(GroupBuffer *group, int field_number);
/* in be-dumpdata.c */
extern void be_portalinit(void);
extern void be_portalpush(PortalEntry *entry);
extern PortalEntry *be_portalpop(void);
extern PortalEntry *be_currentportal(void);
extern PortalEntry *be_newportal(void);
extern void
be_typeinit(PortalEntry *entry, TupleDesc attrs,
int natts);
extern void be_printtup(HeapTuple tuple, TupleDesc typeinfo);
/* in be-pqexec.c */
extern char *
PQfn(int fnid, int *result_buf, int result_len, int result_is_int,
PQArgBlock *args, int nargs);
extern char *PQexec(char *query);
extern int pqtest_PQexec(char *q);
extern int pqtest_PQfn(char *q);
extern int32 pqtest(struct varlena * vlena);
/*
* prototypes for functions in pqcomm.c
*/
......
#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);
int verify_password(char *auth_arg, char *user, char *password);
#endif
/*-------------------------------------------------------------------------
*
* pqcomm.h--
* Parameters for the communication module
* Definitions common to frontends and backends.
*
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: pqcomm.h,v 1.18 1998/01/24 22:49:23 momjian Exp $
*
* NOTES
* Some of this should move to libpq.h
* $Id: pqcomm.h,v 1.19 1998/01/26 01:42:21 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -18,134 +15,105 @@
#include <stdio.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include "c.h"
/*
* startup msg parameters: path length, argument string length
*/
#define PATH_SIZE 64
#define ARGV_SIZE 64
/* Define a generic socket address type. */
typedef union SockAddr {
struct sockaddr sa;
struct sockaddr_in in;
struct sockaddr_un un;
} SockAddr;
/* Configure the UNIX socket address for the well known port. */
#define UNIXSOCK_PATH(sun,port) \
sprintf(sun.sun_path,"/tmp/.s.PGSQL.%d",port) + sizeof(sun.sun_family) + 1;
/* The various kinds of startup messages are for the various kinds of
user authentication systems. In the beginning, there was only
STARTUP_MSG and all connections were unauthenticated. Now, there are
several choices of authentication method (the client picks one, but
the server needn't necessarily accept it). So now, the STARTUP_MSG
message means to start either an unauthenticated or a host-based
authenticated connection, depending on what the server prefers. This
is possible because the protocol between server and client is the same
in both cases (basically, no negotiation is required at all).
(sprintf((sun).sun_path, "/tmp/.s.PGSQL.%d", (port)) + \
sizeof ((sun).sun_family))
/*
* These manipulate the frontend/backend protocol version number.
*
* The major number should be incremented for incompatible changes. The minor
* number should be incremented for compatible changes (eg. additional
* functionality).
*
* If a backend supports version m.n of the protocol it must actually support
* versions m.0..n]. Backend support for version m-1 can be dropped after a
* `reasonable' length of time.
*
* A frontend isn't required to support anything other than the current
* version.
*/
typedef enum _MsgType
{
ACK_MSG = 0, /* acknowledge a message */
ERROR_MSG = 1, /* error response to client from server */
RESET_MSG = 2, /* client must reset connection */
PRINT_MSG = 3, /* tuples for client from server */
NET_ERROR = 4, /* error in net system call */
FUNCTION_MSG = 5, /* fastpath call (unused) */
QUERY_MSG = 6, /* client query to server */
STARTUP_MSG = 7, /* initialize a connection with a backend */
DUPLICATE_MSG = 8, /* duplicate msg arrived (errors msg only) */
INVALID_MSG = 9, /* for some control functions */
STARTUP_KRB4_MSG = 10, /* krb4 session follows startup packet */
STARTUP_KRB5_MSG = 11, /* krb5 session follows startup packet */
STARTUP_HBA_MSG = 12, /* use host-based authentication */
STARTUP_UNAUTH_MSG = 13, /* use unauthenticated connection */
STARTUP_PASSWORD_MSG = 14, /* use plaintext password authentication */
/* The following three are not really a named authentication method
* since the front end has no choice in choosing the method. The
* backend sends the SALT/UNSALT messages back to the frontend after
* the USER login has been given to the backend.
#define PG_PROTOCOL_MAJOR(v) ((v) >> 16)
#define PG_PROTOCOL_MINOR(v) ((v) & 0x0000ffff)
#define PG_PROTOCOL(m,n) (((m) << 16) | (n))
/* The earliest and latest frontend/backend protocol version supported. */
#define PG_PROTOCOL_EARLIEST PG_PROTOCOL(0,0)
#define PG_PROTOCOL_LATEST PG_PROTOCOL(1,0)
/*
* All packets sent to the postmaster start with the length. This is omitted
* from the different packet definitions specified below.
*/
STARTUP_CRYPT_MSG = 15, /* use crypt()'ed password authentication */
STARTUP_USER_MSG = 16, /* send user name to check pg_user for password */
STARTUP_SALT_MSG = 17, /* frontend should crypt the password it sends */
STARTUP_UNSALT_MSG = 18 /* frontend should NOT crypt the password it sends */
/* insert new values here -- DO NOT REORDER OR DELETE ENTRIES */
/* also change LAST_AUTHENTICATION_TYPE below and add to the */
/* authentication_type_name[] array in pqcomm.c */
} MsgType;
#define LAST_AUTHENTICATION_TYPE 14
typedef char *Addr;
typedef int PacketLen; /* packet length */
typedef struct StartupInfo
{
/* PacketHdr hdr; */
char database[PATH_SIZE]; /* database name */
char user[NAMEDATALEN]; /* user name */
char options[ARGV_SIZE]; /* possible additional args */
char execFile[ARGV_SIZE]; /* possible backend to use */
char tty[PATH_SIZE]; /* possible tty for debug output */
} StartupInfo;
/* amount of available data in a packet buffer */
#define MESSAGE_SIZE sizeof(StartupInfo)
/* I/O can be blocking or non-blocking */
#define BLOCKING (FALSE)
#define NON_BLOCKING (TRUE)
/* a PacketBuf gets shipped from client to server so be careful
of differences in representation.
Be sure to use htonl() and ntohl() on the len and msgtype fields! */
typedef struct PacketBuf
{
int len;
MsgType msgtype;
char data[MESSAGE_SIZE];
} PacketBuf;
/* update the conversion routines
StartupInfo2PacketBuf() and PacketBuf2StartupInfo() (decl. below)
if StartupInfo or PacketBuf structs ever change */
typedef uint32 PacketLen;
/*
* socket descriptor port
* we need addresses of both sides to do authentication calls
* Startup message parameters sizes. These must not be changed without changing
* the protcol version. These are all strings that are '\0' terminated only if
* there is room.
*/
typedef struct Port
{
int sock; /* file descriptor */
int mask; /* select mask */
int nBytes; /* nBytes read in so far */
/* local addr (us) */
union { struct sockaddr_in in; struct sockaddr_un un; } laddr;
/* remote addr (them) */
union { struct sockaddr_in in; struct sockaddr_un un; } raddr;
/*
* PacketBufId id;
*//* id of packet buf currently in use */
PacketBuf buf; /* stream implementation (curr pack buf) */
char salt[2];
} Port;
/* invalid socket descriptor */
#define INVALID_SOCK (-1)
#define INVALID_ID (-1)
#define MAX_CONNECTIONS 10
#define N_PACK_BUFS 20
/* no multi-packet messages yet */
#define MAX_PACKET_BACKLOG 1
#define DEFAULT_STRING ""
extern FILE *Pfout,
*Pfin;
extern int PQAsyncNotifyWaiting;
#define SM_DATABASE 64
#define SM_USER 32
#define SM_OPTIONS 64
#define SM_UNUSED 64
#define SM_TTY 64
typedef uint32 ProtocolVersion; /* Fe/Be protocol version nr. */
typedef struct StartupPacket {
ProtocolVersion protoVersion; /* Protocol version */
char database[SM_DATABASE]; /* Database name */
char user[SM_USER]; /* User name */
char options[SM_OPTIONS]; /* Optional additional args */
char unused[SM_UNUSED]; /* Unused */
char tty[SM_TTY]; /* Tty for debug output */
} StartupPacket;
/* These are the authentication requests sent by the backend. */
#define AUTH_REQ_OK 0 /* User is authenticated */
#define AUTH_REQ_KRB4 1 /* Kerberos V4 */
#define AUTH_REQ_KRB5 2 /* Kerberos V5 */
#define AUTH_REQ_PASSWORD 3 /* Password */
#define AUTH_REQ_CRYPT 4 /* Encrypted password */
typedef uint32 AuthRequest;
/* This next section is to maintain compatibility with protocol v0.0. */
#define STARTUP_MSG 7 /* Initialise a connection */
#define STARTUP_KRB4_MSG 10 /* krb4 session follows */
#define STARTUP_KRB5_MSG 11 /* krb5 session follows */
#define STARTUP_PASSWORD_MSG 14 /* Password follows */
typedef ProtocolVersion MsgType;
/* in pqcompriv.c */
int pqGetShort(int *, FILE *);
......@@ -160,15 +128,4 @@ int pqPutNBytes(const char *, size_t, FILE *);
int pqPutString(const char *, FILE *);
int pqPutByte(int, FILE *);
/*
* prototypes for functions in pqpacket.c
*/
extern int PacketReceive(Port *port, PacketBuf *buf, char nonBlocking);
extern int PacketSend(Port *port, PacketBuf *buf,
PacketLen len, char nonBlocking);
/* extern PacketBuf* StartupInfo2PacketBuf(StartupInfo*); */
/* extern StartupInfo* PacketBuf2StartupInfo(PacketBuf*); */
extern char *name_of_authentication_type(int type);
#endif /* PQCOMM_H */
......@@ -7,10 +7,13 @@
#
#
# IDENTIFICATION
# $Header: /cvsroot/pgsql/src/interfaces/libpq/Attic/Makefile.in,v 1.4 1998/01/17 23:39:11 scrappy Exp $
# $Header: /cvsroot/pgsql/src/interfaces/libpq/Attic/Makefile.in,v 1.5 1998/01/26 01:42:24 scrappy Exp $
#
#-------------------------------------------------------------------------
SO_MAJOR_VERSION=1
SO_MINOR_VERSION=1
SRCDIR= ../..
include $(SRCDIR)/Makefile.global
......@@ -19,7 +22,7 @@ INCLUDE_OPT= -I$(SRCDIR)/include -I$(SRCDIR)/backend
PORTNAME=@PORTNAME@
CFLAGS+= $(INCLUDE_OPT)
CFLAGS+= $(INCLUDE_OPT) -DFRONTEND
ifdef KRBVERS
CFLAGS+= $(KRBFLAGS)
......@@ -34,20 +37,20 @@ install-shlib-dep :=
ifeq ($(PORTNAME), linux)
ifdef LINUX_ELF
install-shlib-dep := install-shlib
shlib := libpq.so.1
shlib := libpq.so.$(SO_MAJOR_VERSION).$(SO_MINOR_VERSION)
LDFLAGS_SL = -shared
CFLAGS += $(CFLAGS_SL)
endif
endif
ifeq ($(PORTNAME), bsd)
install-shlib-dep := install-shlib
shlib := libpq.so.1.0
shlib := libpq.so.$(SO_MAJOR_VERSION).$(SO_MINOR_VERSION)
LDFLAGS_SL = -x -Bshareable -Bforcearchive
CFLAGS += $(CFLAGS_SL)
endif
ifeq ($(PORTNAME), i386_solaris)
install-shlib-dep := install-shlib
shlib := libpq.so.1
shlib := libpq.so.$(SO_MAJOR_VERSION).$(SO_MINOR_VERSION)
LDFLAGS_SL = -G -z text
CFLAGS += $(CFLAGS_SL)
endif
......
......@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.12 1997/12/04 00:28:08 scrappy Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-auth.c,v 1.13 1998/01/26 01:42:25 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -42,6 +42,11 @@
#include "fe-auth.h"
#include "fe-connect.h"
#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif
/*----------------------------------------------------------------
* common definitions for generic fe/be routines
*----------------------------------------------------------------
......@@ -457,49 +462,49 @@ pg_krb5_sendauth(const char *PQerrormsg, int sock,
#endif /* KRB5 */
static int
pg_password_sendauth(Port *port, const char *user, const char *password)
pg_password_sendauth(PGconn *conn, const char *password, AuthRequest areq)
{
PacketBuf buf;
char *tmp;
/* Encrypt the password if needed. */
buf.len = htonl(sizeof(PacketBuf));
buf.msgtype = STARTUP_PASSWORD_MSG;
buf.data[0] = '\0';
if (areq == AUTH_REQ_CRYPT)
password = crypt(password, conn->salt);
tmp = buf.data;
strncpy(tmp, user, strlen(user) + 1);
tmp += strlen(user) + 1;
strncpy(tmp, password, strlen(password) + 1);
return packetSend(port, &buf, sizeof(PacketBuf), BLOCKING);
return packetSend(conn, password, strlen(password) + 1);
}
/*
* fe_sendauth -- client demux routine for outgoing authentication information
*/
int
fe_sendauth(MsgType msgtype, Port *port, const char *hostname,
const char *user, const char *password, const char *PQerrormsg)
fe_sendauth(AuthRequest areq, PGconn *conn, const char *hostname,
const char *password, const char *PQerrormsg)
{
switch (msgtype)
switch (areq)
{
case AUTH_REQ_OK:
break;
case AUTH_REQ_KRB4:
#ifdef KRB4
case STARTUP_KRB4_MSG:
if (pg_krb4_sendauth(PQerrormsg, port->sock, &port->laddr,
&port->raddr,
if (pg_krb4_sendauth(PQerrormsg, conn->sock, &conn->laddr.in,
&conn->raddr.in,
hostname) != STATUS_OK)
{
(void) sprintf(PQerrormsg,
"fe_sendauth: krb4 authentication failed\n");
/* fputs(PQerrormsg, stderr); */
return (STATUS_ERROR);
}
break;
#else
(void)sprintf(PQerrormsg,
"fe_sendauth: krb4 authentication not supported\n");
return (STATUS_ERROR);
#endif
case AUTH_REQ_KRB5:
#ifdef KRB5
case STARTUP_KRB5_MSG:
if (pg_krb5_sendauth(PQerrormsg, port->sock, &port->laddr,
&port->raddr,
if (pg_krb5_sendauth(PQerrormsg, conn->sock, &conn->laddr.in,
&conn->raddr.in,
hostname) != STATUS_OK)
{
(void) sprintf(PQerrormsg,
......@@ -507,15 +512,29 @@ fe_sendauth(MsgType msgtype, Port *port, const char *hostname,
return (STATUS_ERROR);
}
break;
#else
(void)sprintf(PQerrormsg,
"fe_sendauth: krb5 authentication not supported\n");
return (STATUS_ERROR);
#endif
case STARTUP_MSG:
case AUTH_REQ_PASSWORD:
case AUTH_REQ_CRYPT:
if (pg_password_sendauth(conn, password, areq) != STATUS_OK)
{
(void)sprintf(PQerrormsg,
"fe_sendauth: error sending password authentication\n");
return (STATUS_ERROR);
}
break;
case STARTUP_PASSWORD_MSG:
case STARTUP_CRYPT_MSG:
pg_password_sendauth(port, user, password);
default:
break;
(void)sprintf(PQerrormsg,
"fe_sendauth: authentication type %u not supported\n",areq);
return (STATUS_ERROR);
}
return (STATUS_OK);
}
......
......@@ -6,13 +6,16 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: fe-auth.h,v 1.6 1997/09/08 21:55:35 momjian Exp $
* $Id: fe-auth.h,v 1.7 1998/01/26 01:42:26 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef FE_AUTH_H
#define FE_AUTH_H
#include "libpq-fe.h"
/*----------------------------------------------------------------
* Common routines and definitions
*----------------------------------------------------------------
......@@ -29,9 +32,8 @@
#endif /* KRB4 || KRB5 */
extern int
fe_sendauth(MsgType msgtype, Port *port, const char *hostname,
const char *user, const char *password,
const char *PQerromsg);
fe_sendauth(AuthRequest areq, PGconn *conn, const char *hostname,
const char *password, const char *PQerromsg);
extern void fe_setauthsvc(const char *name, char *PQerrormsg);
#define PG_KRB4_VERSION "PGVER4.1" /* at most KRB_SENDAUTH_VLEN chars */
......
This diff is collapsed.
This diff is collapsed.
......@@ -7,7 +7,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.45 1997/12/23 20:00:06 thomas Exp $
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-exec.c,v 1.46 1998/01/26 01:42:35 scrappy Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -168,7 +168,7 @@ getTuple(PGconn *conn, PGresult *result, int binary)
if ((nfields % BYTELEN) > 0)
nbytes++;
if (pqGetnchar(bitmap, nbytes, pfin, pfdebug) == 1)
if (nbytes >= MAX_FIELDS || pqGetnchar(bitmap, nbytes, pfin, pfdebug) == 1)
{
sprintf(conn->errorMessage,
"Error reading null-values bitmap from row data stream\n");
......@@ -189,10 +189,10 @@ getTuple(PGconn *conn, PGresult *result, int binary)
else
{
/* get the value length (the first four bytes are for length) */
pqGetInt(&vlen, VARHDRSZ, pfin, pfdebug);
pqGetInt(&vlen, 4, pfin, pfdebug);
if (binary == 0)
{
vlen = vlen - VARHDRSZ;
vlen = vlen - 4;
}
if (vlen < 0)
vlen = 0;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment