mirror of
https://github.com/postgres/postgres.git
synced 2025-04-24 10:47:04 +03:00
Lots of patches coming in from me today :-)
When drawing up a very simple "text-drawing" of how the negotiation is done, I realised I had done this last part (fallback) in a very stupid way. Patch #4 fixes this, and does it in a much better way. Included is also the simple text-drawing of how the negotiation is done. //Magnus
This commit is contained in:
parent
3114f92122
commit
e0e7daef6d
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.40 1999/07/17 20:17:00 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.41 1999/09/27 03:12:58 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -452,8 +452,7 @@ be_recvauth(Port *port)
|
||||
* an error message into the postmaster logfile if it failed.
|
||||
*/
|
||||
|
||||
if (hba_getauthmethod(&port->raddr, port->user, port->database,
|
||||
port->auth_arg, &port->auth_method) != STATUS_OK)
|
||||
if (hba_getauthmethod(port) != STATUS_OK)
|
||||
PacketSendError(&port->pktInfo,
|
||||
"Missing or erroneous pg_hba.conf file, see postmaster log for details");
|
||||
|
||||
@ -470,7 +469,6 @@ be_recvauth(Port *port)
|
||||
|
||||
AuthRequest areq = AUTH_REQ_OK;
|
||||
PacketDoneProc auth_handler = NULL;
|
||||
|
||||
switch (port->auth_method)
|
||||
{
|
||||
case uaReject:
|
||||
|
@ -5,7 +5,7 @@
|
||||
* wherein you authenticate a user by seeing what IP address the system
|
||||
* says he comes from and possibly using ident).
|
||||
*
|
||||
* $Id: hba.c,v 1.47 1999/07/17 20:17:02 momjian Exp $
|
||||
* $Id: hba.c,v 1.48 1999/09/27 03:12:59 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -146,9 +146,7 @@ read_hba_entry2(FILE *file, UserAuth *userauth_p, char *auth_arg,
|
||||
|
||||
|
||||
static void
|
||||
process_hba_record(FILE *file, SockAddr *raddr, const char *user,
|
||||
const char *database, bool *matches_p, bool *error_p,
|
||||
UserAuth *userauth_p, char *auth_arg)
|
||||
process_hba_record(FILE *file, hbaPort *port, bool *matches_p, bool *error_p)
|
||||
{
|
||||
/*---------------------------------------------------------------------------
|
||||
Process the non-comment record in the config file that is next on the file.
|
||||
@ -182,16 +180,16 @@ process_hba_record(FILE *file, SockAddr *raddr, const char *user,
|
||||
|
||||
/* Read the rest of the line. */
|
||||
|
||||
read_hba_entry2(file, userauth_p, auth_arg, error_p);
|
||||
read_hba_entry2(file, &port->auth_method, port->auth_arg, error_p);
|
||||
|
||||
/*
|
||||
* For now, disallow methods that need AF_INET sockets to work.
|
||||
*/
|
||||
|
||||
if (!*error_p &&
|
||||
(*userauth_p == uaIdent ||
|
||||
*userauth_p == uaKrb4 ||
|
||||
*userauth_p == uaKrb5))
|
||||
(port->auth_method == uaIdent ||
|
||||
port->auth_method == uaKrb4 ||
|
||||
port->auth_method == uaKrb5))
|
||||
*error_p = true;
|
||||
|
||||
if (*error_p)
|
||||
@ -202,15 +200,33 @@ process_hba_record(FILE *file, SockAddr *raddr, const char *user,
|
||||
* sort of connection, ignore it.
|
||||
*/
|
||||
|
||||
if ((strcmp(db, database) != 0 && strcmp(db, "all") != 0 &&
|
||||
(strcmp(db, "sameuser") != 0 || strcmp(database, user) != 0)) ||
|
||||
raddr->sa.sa_family != AF_UNIX)
|
||||
if ((strcmp(db, port->database) != 0 && strcmp(db, "all") != 0 &&
|
||||
(strcmp(db, "sameuser") != 0 || strcmp(port->database, port->user) != 0)) ||
|
||||
port->raddr.sa.sa_family != AF_UNIX)
|
||||
return;
|
||||
}
|
||||
else if (strcmp(buf, "host") == 0)
|
||||
else if (strcmp(buf, "host") == 0 || strcmp(buf, "hostssl") == 0)
|
||||
{
|
||||
struct in_addr file_ip_addr,
|
||||
mask;
|
||||
bool discard = 0; /* Discard this entry */
|
||||
|
||||
#ifdef USE_SSL
|
||||
/* If SSL, then check that we are on SSL */
|
||||
if (strcmp(buf, "hostssl") == 0) {
|
||||
if (!port->ssl)
|
||||
discard = 1;
|
||||
|
||||
/* Placeholder to require specific SSL level, perhaps? */
|
||||
/* Or a client certificate */
|
||||
|
||||
/* Since we were on SSL, proceed as with normal 'host' mode */
|
||||
}
|
||||
#else
|
||||
/* If not SSL, we don't support this */
|
||||
if (strcmp(buf,"hostssl") == 0)
|
||||
goto syntax;
|
||||
#endif
|
||||
|
||||
/* Get the database. */
|
||||
|
||||
@ -252,20 +268,27 @@ process_hba_record(FILE *file, SockAddr *raddr, const char *user,
|
||||
* info from it.
|
||||
*/
|
||||
|
||||
read_hba_entry2(file, userauth_p, auth_arg, error_p);
|
||||
read_hba_entry2(file, &port->auth_method, port->auth_arg, error_p);
|
||||
|
||||
if (*error_p)
|
||||
goto syntax;
|
||||
|
||||
/*
|
||||
* If told to discard earlier. Moved down here so we don't get
|
||||
* "out of sync" with the file.
|
||||
*/
|
||||
if (discard)
|
||||
return;
|
||||
|
||||
/*
|
||||
* If this record isn't for our database, or this is the wrong
|
||||
* sort of connection, ignore it.
|
||||
*/
|
||||
|
||||
if ((strcmp(db, database) != 0 && strcmp(db, "all") != 0 &&
|
||||
(strcmp(db, "sameuser") != 0 || strcmp(database, user) != 0)) ||
|
||||
raddr->sa.sa_family != AF_INET ||
|
||||
((file_ip_addr.s_addr ^ raddr->in.sin_addr.s_addr) & mask.s_addr) != 0x0000)
|
||||
if ((strcmp(db, port->database) != 0 && strcmp(db, "all") != 0 &&
|
||||
(strcmp(db, "sameuser") != 0 || strcmp(port->database, port->user) != 0)) ||
|
||||
port->raddr.sa.sa_family != AF_INET ||
|
||||
((file_ip_addr.s_addr ^ port->raddr.in.sin_addr.s_addr) & mask.s_addr) != 0x0000)
|
||||
return;
|
||||
}
|
||||
else
|
||||
@ -291,9 +314,7 @@ syntax:
|
||||
|
||||
|
||||
static void
|
||||
process_open_config_file(FILE *file, SockAddr *raddr, const char *user,
|
||||
const char *database, bool *hba_ok_p,
|
||||
UserAuth *userauth_p, char *auth_arg)
|
||||
process_open_config_file(FILE *file, hbaPort *port, bool *hba_ok_p)
|
||||
{
|
||||
/*---------------------------------------------------------------------------
|
||||
This function does the same thing as find_hba_entry, only with
|
||||
@ -316,8 +337,7 @@ process_open_config_file(FILE *file, SockAddr *raddr, const char *user,
|
||||
if (c == '#')
|
||||
read_through_eol(file);
|
||||
else
|
||||
process_hba_record(file, raddr, user, database,
|
||||
&found_entry, &error, userauth_p, auth_arg);
|
||||
process_hba_record(file, port, &found_entry, &error);
|
||||
}
|
||||
}
|
||||
|
||||
@ -326,7 +346,7 @@ process_open_config_file(FILE *file, SockAddr *raddr, const char *user,
|
||||
/* If no matching entry was found, synthesize 'reject' entry. */
|
||||
|
||||
if (!found_entry)
|
||||
*userauth_p = uaReject;
|
||||
port->auth_method = uaReject;
|
||||
|
||||
*hba_ok_p = true;
|
||||
}
|
||||
@ -335,8 +355,7 @@ process_open_config_file(FILE *file, SockAddr *raddr, const char *user,
|
||||
|
||||
|
||||
static void
|
||||
find_hba_entry(SockAddr *raddr, const char *user, const char *database,
|
||||
bool *hba_ok_p, UserAuth *userauth_p, char *auth_arg)
|
||||
find_hba_entry(hbaPort *port, bool *hba_ok_p)
|
||||
{
|
||||
/*
|
||||
* Read the config file and find an entry that allows connection from
|
||||
@ -412,8 +431,7 @@ find_hba_entry(SockAddr *raddr, const char *user, const char *database,
|
||||
}
|
||||
else
|
||||
{
|
||||
process_open_config_file(file, raddr, user, database, hba_ok_p,
|
||||
userauth_p, auth_arg);
|
||||
process_open_config_file(file, port, hba_ok_p);
|
||||
FreeFile(file);
|
||||
}
|
||||
pfree(conf_file);
|
||||
@ -1057,8 +1075,7 @@ GetCharSetByHost(char *TableName, int host, const char *DataDir)
|
||||
#endif
|
||||
|
||||
int
|
||||
hba_getauthmethod(SockAddr *raddr, char *user, char *database,
|
||||
char *auth_arg, UserAuth *auth_method)
|
||||
hba_getauthmethod(hbaPort *port)
|
||||
{
|
||||
/*---------------------------------------------------------------------------
|
||||
Determine what authentication method should be used when accessing database
|
||||
@ -1070,7 +1087,7 @@ hba_getauthmethod(SockAddr *raddr, char *user, char *database,
|
||||
----------------------------------------------------------------------------*/
|
||||
bool hba_ok = false;
|
||||
|
||||
find_hba_entry(raddr, user, database, &hba_ok, auth_method, auth_arg);
|
||||
find_hba_entry(port, &hba_ok);
|
||||
|
||||
return hba_ok ? STATUS_OK : STATUS_ERROR;
|
||||
}
|
||||
|
@ -79,6 +79,18 @@
|
||||
#
|
||||
# krb5: Kerberos V5 authentication is used.
|
||||
|
||||
# Record type "hostssl"
|
||||
# ---------------------
|
||||
#
|
||||
# This record identifies the authentication to use when connecting to a
|
||||
# particular database via TCP/IP sockets over SSL. Note that normal
|
||||
# "host" records are also matched - "hostssl" records can be used to
|
||||
# require a SSL connection.
|
||||
# This keyword is only available if the server is compiled with SSL support
|
||||
# enabled.
|
||||
#
|
||||
# The format of this record is identical to that of "host".
|
||||
|
||||
# Record type "local"
|
||||
# ------------------
|
||||
#
|
||||
|
@ -28,7 +28,7 @@
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: pqcomm.c,v 1.83 1999/09/08 22:57:12 tgl Exp $
|
||||
* $Id: pqcomm.c,v 1.84 1999/09/27 03:12:59 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -436,8 +436,16 @@ pq_recvbuf(void)
|
||||
/* Can fill buffer from PqRecvLength and upwards */
|
||||
for (;;)
|
||||
{
|
||||
int r = recv(MyProcPort->sock, PqRecvBuffer + PqRecvLength,
|
||||
PQ_BUFFER_SIZE - PqRecvLength, 0);
|
||||
int r;
|
||||
|
||||
#ifdef USE_SSL
|
||||
if (MyProcPort->ssl)
|
||||
r = SSL_read(MyProcPort->ssl, PqRecvBuffer + PqRecvLength,
|
||||
PQ_BUFFER_SIZE - PqRecvLength);
|
||||
else
|
||||
#endif
|
||||
r = recv(MyProcPort->sock, PqRecvBuffer + PqRecvLength,
|
||||
PQ_BUFFER_SIZE - PqRecvLength, 0);
|
||||
|
||||
if (r < 0)
|
||||
{
|
||||
@ -604,7 +612,13 @@ pq_flush(void)
|
||||
|
||||
while (bufptr < bufend)
|
||||
{
|
||||
int r = send(MyProcPort->sock, bufptr, bufend - bufptr, 0);
|
||||
int r;
|
||||
#ifdef USE_SSL
|
||||
if (MyProcPort->ssl)
|
||||
r = SSL_write(MyProcPort->ssl, bufptr, bufend - bufptr);
|
||||
else
|
||||
#endif
|
||||
r = send(MyProcPort->sock, bufptr, bufend - bufptr, 0);
|
||||
|
||||
if (r <= 0)
|
||||
{
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/libpq/Attic/pqpacket.c,v 1.22 1999/07/17 20:17:03 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/libpq/Attic/pqpacket.c,v 1.23 1999/09/27 03:12:59 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -50,13 +50,20 @@ PacketReceiveSetup(Packet *pkt, PacketDoneProc iodone, void *arg)
|
||||
*/
|
||||
|
||||
int
|
||||
PacketReceiveFragment(Packet *pkt, int sock)
|
||||
PacketReceiveFragment(Port *port)
|
||||
{
|
||||
int got;
|
||||
Packet *pkt = &port->pktInfo;
|
||||
|
||||
if ((got = read(sock, pkt->ptr, pkt->nrtodo)) > 0)
|
||||
#ifdef USE_SSL
|
||||
if (port->ssl)
|
||||
got = SSL_read(port->ssl, pkt->ptr, pkt->nrtodo);
|
||||
else
|
||||
#endif
|
||||
got = read(port->sock, pkt->ptr, pkt->nrtodo);
|
||||
if (got > 0)
|
||||
{
|
||||
pkt->nrtodo -= got;
|
||||
pkt->nrtodo -= got;
|
||||
pkt->ptr += got;
|
||||
|
||||
/* See if we have got what we need for the packet length. */
|
||||
@ -132,11 +139,19 @@ PacketSendSetup(Packet *pkt, int nbytes, PacketDoneProc iodone, void *arg)
|
||||
*/
|
||||
|
||||
int
|
||||
PacketSendFragment(Packet *pkt, int sock)
|
||||
PacketSendFragment(Port *port)
|
||||
{
|
||||
int done;
|
||||
Packet *pkt = &port->pktInfo;
|
||||
|
||||
if ((done = write(sock, pkt->ptr, pkt->nrtodo)) > 0)
|
||||
#ifdef USE_SSL
|
||||
if (port->ssl)
|
||||
done = SSL_write(port->ssl, pkt->ptr, pkt->nrtodo);
|
||||
else
|
||||
#endif
|
||||
done = write(port->sock, pkt->ptr, pkt->nrtodo);
|
||||
|
||||
if (done > 0)
|
||||
{
|
||||
pkt->nrtodo -= done;
|
||||
pkt->ptr += done;
|
||||
|
@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.116 1999/09/21 20:58:19 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.117 1999/09/27 03:13:05 momjian Exp $
|
||||
*
|
||||
* NOTES
|
||||
*
|
||||
@ -183,6 +183,10 @@ static int ServerSock_UNIX = INVALID_SOCK; /* stream socket server */
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_SSL
|
||||
static SSL_CTX *SSL_context = NULL; /* Global SSL context */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set by the -o option
|
||||
*/
|
||||
@ -200,6 +204,8 @@ static int SendStop = false;
|
||||
|
||||
static bool NetServer = false; /* if not zero, postmaster listen for
|
||||
* non-local connections */
|
||||
static bool SecureNetServer = false; /* if not zero, postmaster listens for only SSL
|
||||
* non-local connections */
|
||||
|
||||
|
||||
/*
|
||||
@ -233,6 +239,7 @@ extern int optind,
|
||||
*/
|
||||
static void pmdaemonize(void);
|
||||
static Port *ConnCreate(int serverFd);
|
||||
static void ConnFree(Port *port);
|
||||
static void reset_shared(unsigned short port);
|
||||
static void pmdie(SIGNAL_ARGS);
|
||||
static void reaper(SIGNAL_ARGS);
|
||||
@ -250,6 +257,9 @@ static long PostmasterRandom(void);
|
||||
static void RandomSalt(char *salt);
|
||||
static void SignalChildren(SIGNAL_ARGS);
|
||||
static int CountChildren(void);
|
||||
#ifdef USE_SSL
|
||||
static void InitSSL(void);
|
||||
#endif
|
||||
|
||||
#ifdef CYR_RECODE
|
||||
void GetCharSetByHost(char *, int, char *);
|
||||
@ -393,7 +403,7 @@ PostmasterMain(int argc, char *argv[])
|
||||
DataDir = getenv("PGDATA"); /* default value */
|
||||
|
||||
opterr = 0;
|
||||
while ((opt = getopt(nonblank_argc, argv, "A:a:B:b:D:dim:MN:no:p:Ss")) != EOF)
|
||||
while ((opt = getopt(nonblank_argc, argv, "A:a:B:b:D:i::dm:MN:no:p:Ss")) != EOF)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
@ -456,6 +466,10 @@ PostmasterMain(int argc, char *argv[])
|
||||
break;
|
||||
case 'i':
|
||||
NetServer = true;
|
||||
#ifdef USE_SSL
|
||||
if (optarg && !strcasecmp(optarg,"s"))
|
||||
SecureNetServer = true;
|
||||
#endif
|
||||
break;
|
||||
case 'm':
|
||||
/* Multiplexed backends no longer supported. */
|
||||
@ -557,16 +571,21 @@ PostmasterMain(int argc, char *argv[])
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef USE_SSL
|
||||
InitSSL();
|
||||
#endif
|
||||
|
||||
if (NetServer)
|
||||
{
|
||||
status = StreamServerPort(hostName, PostPortName, &ServerSock_INET);
|
||||
if (status != STATUS_OK)
|
||||
{
|
||||
fprintf(stderr, "%s: cannot create INET stream port\n",
|
||||
progname);
|
||||
exit(1);
|
||||
}
|
||||
status = StreamServerPort(hostName, PostPortName, &ServerSock_INET);
|
||||
if (status != STATUS_OK)
|
||||
{
|
||||
fprintf(stderr, "%s: cannot create INET stream port\n",
|
||||
progname);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef __CYGWIN32__
|
||||
status = StreamServerPort(NULL, PostPortName, &ServerSock_UNIX);
|
||||
if (status != STATUS_OK)
|
||||
@ -655,6 +674,9 @@ usage(const char *progname)
|
||||
fprintf(stderr, "\t-b backend\tuse a specific backend server executable\n");
|
||||
fprintf(stderr, "\t-d [1|2|3]\tset debugging level\n");
|
||||
fprintf(stderr, "\t-i \t\tlisten on TCP/IP sockets as well as Unix domain socket\n");
|
||||
#ifdef USE_SSL
|
||||
fprintf(stderr," \t-is\t\tlisten on TCP/IP sockets as above, but only SSL connections\n");
|
||||
#endif
|
||||
fprintf(stderr, "\t-N nprocs\tset max number of backends (1..%d, default %d)\n",
|
||||
MAXBACKENDS, DEF_MAXBACKENDS);
|
||||
fprintf(stderr, "\t-n \t\tdon't reinitialize shared memory after abnormal exit\n");
|
||||
@ -690,6 +712,9 @@ ServerLoop(void)
|
||||
Port *port;
|
||||
fd_set rmask,
|
||||
wmask;
|
||||
#ifdef USE_SSL
|
||||
int no_select = 0;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SIGPROCMASK
|
||||
sigprocmask(SIG_SETMASK, &oldsigmask, 0);
|
||||
@ -699,6 +724,18 @@ ServerLoop(void)
|
||||
|
||||
memmove((char *) &rmask, (char *) &readmask, sizeof(fd_set));
|
||||
memmove((char *) &wmask, (char *) &writemask, sizeof(fd_set));
|
||||
|
||||
#ifdef USE_SSL
|
||||
for (curr = DLGetHead(PortList); curr; curr = DLGetSucc(curr))
|
||||
if (((Port *)DLE_VAL(curr))->ssl &&
|
||||
SSL_pending(((Port *)DLE_VAL(curr))->ssl) > 0) {
|
||||
no_select = 1;
|
||||
break;
|
||||
}
|
||||
if (no_select)
|
||||
FD_ZERO(&rmask); /* So we don't accept() anything below */
|
||||
else
|
||||
#endif
|
||||
if (select(nSockets, &rmask, &wmask, (fd_set *) NULL,
|
||||
(struct timeval *) NULL) < 0)
|
||||
{
|
||||
@ -743,18 +780,20 @@ ServerLoop(void)
|
||||
#ifndef __CYGWIN32__
|
||||
if (ServerSock_UNIX != INVALID_SOCK &&
|
||||
FD_ISSET(ServerSock_UNIX, &rmask) &&
|
||||
(port = ConnCreate(ServerSock_UNIX)) != NULL)
|
||||
PacketReceiveSetup(&port->pktInfo,
|
||||
(port = ConnCreate(ServerSock_UNIX)) != NULL) {
|
||||
PacketReceiveSetup(&port->pktInfo,
|
||||
readStartupPacket,
|
||||
(void *) port);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ServerSock_INET != INVALID_SOCK &&
|
||||
FD_ISSET(ServerSock_INET, &rmask) &&
|
||||
(port = ConnCreate(ServerSock_INET)) != NULL)
|
||||
FD_ISSET(ServerSock_INET, &rmask) &&
|
||||
(port = ConnCreate(ServerSock_INET)) != NULL) {
|
||||
PacketReceiveSetup(&port->pktInfo,
|
||||
readStartupPacket,
|
||||
(void *) port);
|
||||
}
|
||||
|
||||
/* Build up new masks for select(). */
|
||||
|
||||
@ -767,14 +806,26 @@ ServerLoop(void)
|
||||
Port *port = (Port *) DLE_VAL(curr);
|
||||
int status = STATUS_OK;
|
||||
Dlelem *next;
|
||||
int readyread = 0;
|
||||
|
||||
if (FD_ISSET(port->sock, &rmask))
|
||||
#ifdef USE_SSL
|
||||
if (port->ssl) {
|
||||
if (SSL_pending(port->ssl) ||
|
||||
FD_ISSET(port->sock, &rmask))
|
||||
readyread = 1;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (FD_ISSET(port->sock, &rmask))
|
||||
readyread = 1;
|
||||
|
||||
if (readyread)
|
||||
{
|
||||
if (DebugLvl > 1)
|
||||
fprintf(stderr, "%s: ServerLoop:\t\thandling reading %d\n",
|
||||
progname, port->sock);
|
||||
|
||||
if (PacketReceiveFragment(&port->pktInfo, port->sock) != STATUS_OK)
|
||||
if (PacketReceiveFragment(port) != STATUS_OK)
|
||||
status = STATUS_ERROR;
|
||||
}
|
||||
|
||||
@ -784,7 +835,7 @@ ServerLoop(void)
|
||||
fprintf(stderr, "%s: ServerLoop:\t\thandling writing %d\n",
|
||||
progname, port->sock);
|
||||
|
||||
if (PacketSendFragment(&port->pktInfo, port->sock) != STATUS_OK)
|
||||
if (PacketSendFragment(port) != STATUS_OK)
|
||||
status = STATUS_ERROR;
|
||||
}
|
||||
|
||||
@ -827,7 +878,7 @@ ServerLoop(void)
|
||||
{
|
||||
StreamClose(port->sock);
|
||||
DLRemove(curr);
|
||||
free(port);
|
||||
ConnFree(port);
|
||||
DLFreeElem(curr);
|
||||
}
|
||||
else
|
||||
@ -896,7 +947,7 @@ readStartupPacket(void *arg, PacketLen len, void *pkt)
|
||||
|
||||
port = (Port *) arg;
|
||||
si = (StartupPacket *) pkt;
|
||||
|
||||
|
||||
/*
|
||||
* The first field is either a protocol version number or a special
|
||||
* request code.
|
||||
@ -907,8 +958,45 @@ readStartupPacket(void *arg, PacketLen len, void *pkt)
|
||||
if (port->proto == CANCEL_REQUEST_CODE)
|
||||
return processCancelRequest(port, len, pkt);
|
||||
|
||||
if (port->proto == NEGOTIATE_SSL_CODE) {
|
||||
char SSLok;
|
||||
|
||||
#ifdef USE_SSL
|
||||
SSLok = 'S'; /* Support for SSL */
|
||||
#else
|
||||
SSLok = 'N'; /* No support for SSL */
|
||||
#endif
|
||||
if (send(port->sock, &SSLok, 1, 0) != 1) {
|
||||
perror("Failed to send SSL negotiation response");
|
||||
return STATUS_ERROR; /* Close connection */
|
||||
}
|
||||
|
||||
#ifdef USE_SSL
|
||||
if (!(port->ssl = SSL_new(SSL_context)) ||
|
||||
!SSL_set_fd(port->ssl, port->sock) ||
|
||||
SSL_accept(port->ssl) <= 0)
|
||||
{
|
||||
fprintf(stderr,"Failed to initialize SSL connection: %s, errno: %d (%s)\n",
|
||||
ERR_reason_error_string(ERR_get_error()), errno, strerror(errno));
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
#endif
|
||||
/* ready for the normal startup packet */
|
||||
PacketReceiveSetup(&port->pktInfo,
|
||||
readStartupPacket,
|
||||
(void *)port);
|
||||
return STATUS_OK; /* Do not close connection */
|
||||
}
|
||||
|
||||
/* Could add additional special packet types here */
|
||||
|
||||
/* Any SSL negotiation must have taken place here, so drop the connection
|
||||
* ASAP if we require SSL */
|
||||
if (SecureNetServer && !port->ssl) {
|
||||
PacketSendError(&port->pktInfo, "Backend requires secure connection.");
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
/* Check we can handle the protocol the frontend is using. */
|
||||
|
||||
if (PG_PROTOCOL_MAJOR(port->proto) < PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST) ||
|
||||
@ -952,7 +1040,6 @@ readStartupPacket(void *arg, PacketLen len, void *pkt)
|
||||
return STATUS_OK; /* don't close the connection yet */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The client has sent a cancel request packet, not a normal
|
||||
* start-a-new-backend packet. Perform the necessary processing.
|
||||
@ -1039,6 +1126,20 @@ ConnCreate(int serverFd)
|
||||
return port;
|
||||
}
|
||||
|
||||
/*
|
||||
* ConnFree -- cree a local connection data structure
|
||||
*/
|
||||
void
|
||||
ConnFree(Port *conn)
|
||||
{
|
||||
#ifdef USE_SSL
|
||||
if (conn->ssl) {
|
||||
SSL_free(conn->ssl);
|
||||
}
|
||||
#endif
|
||||
free(conn);
|
||||
}
|
||||
|
||||
/*
|
||||
* reset_shared -- reset shared memory and semaphores
|
||||
*/
|
||||
@ -1502,7 +1603,7 @@ DoBackend(Port *port)
|
||||
sigprocmask(SIG_SETMASK, &oldsigmask, 0);
|
||||
|
||||
/* Close the postmaster sockets */
|
||||
if (NetServer)
|
||||
if (NetServer)
|
||||
StreamClose(ServerSock_INET);
|
||||
#ifndef __CYGWIN32__
|
||||
StreamClose(ServerSock_UNIX);
|
||||
@ -1729,3 +1830,33 @@ CountChildren(void)
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Initialize SSL library and structures
|
||||
*/
|
||||
static void InitSSL(void) {
|
||||
char fnbuf[2048];
|
||||
|
||||
SSL_load_error_strings();
|
||||
SSL_library_init();
|
||||
SSL_context = SSL_CTX_new(SSLv23_method());
|
||||
if (!SSL_context) {
|
||||
fprintf(stderr, "Failed to create SSL context: %s\n",ERR_reason_error_string(ERR_get_error()));
|
||||
exit(1);
|
||||
}
|
||||
snprintf(fnbuf,sizeof(fnbuf),"%s/server.crt", DataDir);
|
||||
if (!SSL_CTX_use_certificate_file(SSL_context, fnbuf, SSL_FILETYPE_PEM)) {
|
||||
fprintf(stderr, "Failed to load server certificate (%s): %s\n",fnbuf,ERR_reason_error_string(ERR_get_error()));
|
||||
exit(1);
|
||||
}
|
||||
snprintf(fnbuf,sizeof(fnbuf),"%s/server.key", DataDir);
|
||||
if (!SSL_CTX_use_PrivateKey_file(SSL_context, fnbuf, SSL_FILETYPE_PEM)) {
|
||||
fprintf(stderr, "Failed to load private key file (%s): %s\n",fnbuf,ERR_reason_error_string(ERR_get_error()));
|
||||
exit(1);
|
||||
}
|
||||
if (!SSL_CTX_check_private_key(SSL_context)) {
|
||||
fprintf(stderr, "Check of private key failed: %s\n",ERR_reason_error_string(ERR_get_error()));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
* Interface to hba.c
|
||||
*
|
||||
*
|
||||
* $Id: hba.h,v 1.14 1999/07/14 01:20:17 momjian Exp $
|
||||
* $Id: hba.h,v 1.15 1999/09/27 03:13:10 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -49,8 +49,9 @@ typedef enum UserAuth
|
||||
uaCrypt
|
||||
} UserAuth;
|
||||
|
||||
int hba_getauthmethod(SockAddr *raddr, char *user, char *database,
|
||||
char *auth_arg, UserAuth *auth_method);
|
||||
typedef struct Port hbaPort;
|
||||
|
||||
int hba_getauthmethod(hbaPort *port);
|
||||
int authident(struct sockaddr_in * raddr, struct sockaddr_in * laddr,
|
||||
const char *postgres_username, const char *auth_arg);
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: libpq-be.h,v 1.16 1999/07/17 20:18:28 momjian Exp $
|
||||
* $Id: libpq-be.h,v 1.17 1999/09/27 03:13:11 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -18,6 +18,11 @@
|
||||
|
||||
#include "libpq/hba.h"
|
||||
|
||||
#ifdef USE_SSL
|
||||
#include <openssl/ssl.h>
|
||||
#include <openssl/err.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* Protocol v0 password packet. */
|
||||
|
||||
@ -126,6 +131,13 @@ typedef struct Port
|
||||
char tty[SM_TTY + 1];
|
||||
char auth_arg[MAX_AUTH_ARG];
|
||||
UserAuth auth_method;
|
||||
|
||||
/*
|
||||
* SSL structures
|
||||
*/
|
||||
#ifdef USE_SSL
|
||||
SSL *ssl;
|
||||
#endif
|
||||
} Port;
|
||||
|
||||
|
||||
@ -136,9 +148,9 @@ extern ProtocolVersion FrontendProtocol;
|
||||
* prototypes for functions in pqpacket.c
|
||||
*/
|
||||
void PacketReceiveSetup(Packet *pkt, PacketDoneProc iodone, void *arg);
|
||||
int PacketReceiveFragment(Packet *pkt, int sock);
|
||||
int PacketReceiveFragment(Port *port);
|
||||
void PacketSendSetup(Packet *pkt, int nbytes, PacketDoneProc iodone, void *arg);
|
||||
int PacketSendFragment(Packet *pkt, int sock);
|
||||
int PacketSendFragment(Port *port);
|
||||
void PacketSendError(Packet *pkt, char *errormsg);
|
||||
|
||||
#endif /* LIBPQ_BE_H */
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: pqcomm.h,v 1.39 1999/08/31 04:26:33 tgl Exp $
|
||||
* $Id: pqcomm.h,v 1.40 1999/09/27 03:13:11 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -152,4 +152,11 @@ typedef struct CancelRequestPacket
|
||||
uint32 cancelAuthCode; /* secret key to authorize cancel */
|
||||
} CancelRequestPacket;
|
||||
|
||||
|
||||
/*
|
||||
* A client can also start by sending a SSL negotiation request, to get a
|
||||
* secure channel.
|
||||
*/
|
||||
#define NEGOTIATE_SSL_CODE PG_PROTOCOL(1234,5679)
|
||||
|
||||
#endif /* PQCOMM_H */
|
||||
|
@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.102 1999/08/31 01:37:36 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.103 1999/09/27 03:13:16 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -40,6 +40,10 @@
|
||||
#include "mb/pg_wchar.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_SSL
|
||||
static SSL_CTX *SSL_context = NULL;
|
||||
#endif
|
||||
|
||||
static ConnStatusType connectDB(PGconn *conn);
|
||||
static PGconn *makeEmptyPGconn(void);
|
||||
static void freePGconn(PGconn *conn);
|
||||
@ -508,6 +512,12 @@ connectDB(PGconn *conn)
|
||||
family;
|
||||
char beresp;
|
||||
int on = 1;
|
||||
#ifdef USE_SSL
|
||||
StartupPacket np; /* Used to negotiate SSL connection */
|
||||
char SSLok;
|
||||
static int allow_ssl_try = 1; /* Allowed to do SSL negotiation */
|
||||
int tried_ssl = 0; /* Set if SSL negotiation was tried */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* parse dbName to get all additional info in it, if any
|
||||
@ -591,6 +601,70 @@ connectDB(PGconn *conn)
|
||||
goto connect_errReturn;
|
||||
}
|
||||
|
||||
/* This needs to be done before we set into nonblocking, since SSL negotiation
|
||||
* does not like that mode */
|
||||
|
||||
#ifdef USE_SSL
|
||||
/* Attempt to negotiate SSL usage */
|
||||
if (allow_ssl_try) {
|
||||
tried_ssl = 1;
|
||||
memset((char *)&np, 0, sizeof(np));
|
||||
np.protoVersion = htonl(NEGOTIATE_SSL_CODE);
|
||||
if (pqPacketSend(conn, (char *) &np, sizeof(StartupPacket)) != STATUS_OK)
|
||||
{
|
||||
sprintf(conn->errorMessage,
|
||||
"connectDB() -- couldn't send SSL negotiation packet: errno=%d\n%s\n",
|
||||
errno, strerror(errno));
|
||||
goto connect_errReturn;
|
||||
}
|
||||
/* Now receive the backends response */
|
||||
if (recv(conn->sock, &SSLok, 1, 0) != 1) {
|
||||
sprintf(conn->errorMessage, "PQconnectDB() -- couldn't read backend response: errno=%d\n%s\n",
|
||||
errno, strerror(errno));
|
||||
goto connect_errReturn;
|
||||
}
|
||||
if (SSLok == 'S') {
|
||||
if (!SSL_context)
|
||||
{
|
||||
SSL_load_error_strings();
|
||||
SSL_library_init();
|
||||
SSL_context = SSL_CTX_new(SSLv23_method());
|
||||
if (!SSL_context) {
|
||||
sprintf(conn->errorMessage,
|
||||
"connectDB() -- couldn't create SSL context: %s\n",
|
||||
ERR_reason_error_string(ERR_get_error()));
|
||||
goto connect_errReturn;
|
||||
}
|
||||
}
|
||||
if (!(conn->ssl = SSL_new(SSL_context)) ||
|
||||
!SSL_set_fd(conn->ssl, conn->sock) ||
|
||||
SSL_connect(conn->ssl) <= 0)
|
||||
{
|
||||
sprintf(conn->errorMessage,
|
||||
"connectDB() -- couldn't establish SSL connection: %s\n",
|
||||
ERR_reason_error_string(ERR_get_error()));
|
||||
goto connect_errReturn;
|
||||
}
|
||||
/* SSL connection finished. Continue to send startup packet */
|
||||
}
|
||||
else if (SSLok == 'E') {
|
||||
/* Received error - probably protocol mismatch */
|
||||
if (conn->Pfdebug)
|
||||
fprintf(conn->Pfdebug, "Backend reports error, attempting fallback to pre-6.6.\n");
|
||||
close(conn->sock);
|
||||
allow_ssl_try = 0;
|
||||
return connectDB(conn);
|
||||
}
|
||||
else if (SSLok != 'N') {
|
||||
strcpy(conn->errorMessage,
|
||||
"Received invalid negotiation response.\n");
|
||||
goto connect_errReturn;
|
||||
}
|
||||
}
|
||||
else
|
||||
allow_ssl_try = 1; /* We'll allow an attempt to use SSL next time */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Set the right options. We need nonblocking I/O, and we don't want
|
||||
* delay of outgoing data.
|
||||
@ -896,6 +970,10 @@ freePGconn(PGconn *conn)
|
||||
if (!conn)
|
||||
return;
|
||||
pqClearAsyncResult(conn); /* deallocate result and curTuple */
|
||||
#ifdef USE_SSL
|
||||
if (conn->ssl)
|
||||
SSL_free(conn->ssl);
|
||||
#endif
|
||||
if (conn->sock >= 0)
|
||||
#ifdef WIN32
|
||||
closesocket(conn->sock);
|
||||
|
@ -24,7 +24,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.30 1999/09/13 03:00:19 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.31 1999/09/27 03:13:16 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -351,7 +351,13 @@ pqReadData(PGconn *conn)
|
||||
|
||||
/* OK, try to read some data */
|
||||
tryAgain:
|
||||
nread = recv(conn->sock, conn->inBuffer + conn->inEnd,
|
||||
#ifdef USE_SSL
|
||||
if (conn->ssl)
|
||||
nread = SSL_read(conn->ssl, conn->inBuffer + conn->inEnd,
|
||||
conn->inBufSize - conn->inEnd);
|
||||
else
|
||||
#endif
|
||||
nread = recv(conn->sock, conn->inBuffer + conn->inEnd,
|
||||
conn->inBufSize - conn->inEnd, 0);
|
||||
if (nread < 0)
|
||||
{
|
||||
@ -420,7 +426,13 @@ tryAgain:
|
||||
* arrived.
|
||||
*/
|
||||
tryAgain2:
|
||||
nread = recv(conn->sock, conn->inBuffer + conn->inEnd,
|
||||
#ifdef USE_SSL
|
||||
if (conn->ssl)
|
||||
nread = SSL_read(conn->ssl, conn->inBuffer + conn->inEnd,
|
||||
conn->inBufSize - conn->inEnd);
|
||||
else
|
||||
#endif
|
||||
nread = recv(conn->sock, conn->inBuffer + conn->inEnd,
|
||||
conn->inBufSize - conn->inEnd, 0);
|
||||
if (nread < 0)
|
||||
{
|
||||
@ -494,7 +506,13 @@ pqFlush(PGconn *conn)
|
||||
pqsigfunc oldsighandler = pqsignal(SIGPIPE, SIG_IGN);
|
||||
#endif
|
||||
|
||||
int sent = send(conn->sock, ptr, len, 0);
|
||||
int sent;
|
||||
#ifdef USE_SSL
|
||||
if (conn->ssl)
|
||||
sent = SSL_write(conn->ssl, ptr, len);
|
||||
else
|
||||
#endif
|
||||
sent = send(conn->sock, ptr, len, 0);
|
||||
|
||||
#ifndef WIN32
|
||||
pqsignal(SIGPIPE, oldsighandler);
|
||||
|
@ -11,7 +11,7 @@
|
||||
*
|
||||
* Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $Id: libpq-int.h,v 1.11 1999/08/31 01:37:37 tgl Exp $
|
||||
* $Id: libpq-int.h,v 1.12 1999/09/27 03:13:16 momjian Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -28,6 +28,11 @@
|
||||
#include "pqexpbuffer.h"
|
||||
|
||||
|
||||
#ifdef USE_SSL
|
||||
#include "openssl/ssl.h"
|
||||
#include "openssl/err.h"
|
||||
#endif
|
||||
|
||||
/* libpq supports this version of the frontend/backend protocol.
|
||||
*
|
||||
* NB: we used to use PG_PROTOCOL_LATEST from the backend pqcomm.h file,
|
||||
@ -215,6 +220,10 @@ struct pg_conn
|
||||
PGresult *result; /* result being constructed */
|
||||
PGresAttValue *curTuple; /* tuple currently being read */
|
||||
|
||||
#ifdef USE_SSL
|
||||
SSL *ssl;
|
||||
#endif
|
||||
|
||||
/* Buffer for current error message */
|
||||
PQExpBufferData errorMessage; /* expansible string */
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user