PostgreSQL Source Code  git master
fe-connect.c File Reference
#include "postgres_fe.h"
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>
#include <time.h>
#include <unistd.h>
#include "libpq-fe.h"
#include "libpq-int.h"
#include "fe-auth.h"
#include "pg_config_paths.h"
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include "common/ip.h"
#include "common/link-canary.h"
#include "common/scram-common.h"
#include "common/string.h"
#include "mb/pg_wchar.h"
#include "port/pg_bswap.h"
Include dependency graph for fe-connect.c:

Go to the source code of this file.

Data Structures

struct  _internalPQconninfoOption
 

Macros

#define PGPASSFILE   ".pgpass"
 
#define ERRCODE_APPNAME_UNKNOWN   "42704"
 
#define ERRCODE_INVALID_PASSWORD   "28P01"
 
#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"
 
#define DefaultHost   "localhost"
 
#define DefaultTty   ""
 
#define DefaultOption   ""
 
#define DefaultAuthtype   ""
 
#define DefaultChannelBinding   "disable"
 
#define DefaultTargetSessionAttrs   "any"
 
#define DefaultSSLMode   "disable"
 
#define DefaultGSSMode   "disable"
 
#define MAXBUFSIZE   256
 
#define LINELEN   NAMEDATALEN*5
 

Typedefs

typedef struct _internalPQconninfoOption internalPQconninfoOption
 

Functions

static bool connectOptions1 (PGconn *conn, const char *conninfo)
 
static bool connectOptions2 (PGconn *conn)
 
static int connectDBStart (PGconn *conn)
 
static int connectDBComplete (PGconn *conn)
 
static PGPing internal_ping (PGconn *conn)
 
static PGconnmakeEmptyPGconn (void)
 
static bool fillPGconn (PGconn *conn, PQconninfoOption *connOptions)
 
static void freePGconn (PGconn *conn)
 
static void closePGconn (PGconn *conn)
 
static void release_conn_addrinfo (PGconn *conn)
 
static void sendTerminateConn (PGconn *conn)
 
static PQconninfoOptionconninfo_init (PQExpBuffer errorMessage)
 
static PQconninfoOptionparse_connection_string (const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
 
static int uri_prefix_length (const char *connstr)
 
static bool recognized_connection_string (const char *connstr)
 
static PQconninfoOptionconninfo_parse (const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
 
static PQconninfoOptionconninfo_array_parse (const char *const *keywords, const char *const *values, PQExpBuffer errorMessage, bool use_defaults, int expand_dbname)
 
static bool conninfo_add_defaults (PQconninfoOption *options, PQExpBuffer errorMessage)
 
static PQconninfoOptionconninfo_uri_parse (const char *uri, PQExpBuffer errorMessage, bool use_defaults)
 
static bool conninfo_uri_parse_options (PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage)
 
static bool conninfo_uri_parse_params (char *params, PQconninfoOption *connOptions, PQExpBuffer errorMessage)
 
static char * conninfo_uri_decode (const char *str, PQExpBuffer errorMessage)
 
static bool get_hexdigit (char digit, int *value)
 
static const char * conninfo_getval (PQconninfoOption *connOptions, const char *keyword)
 
static PQconninfoOptionconninfo_storeval (PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode)
 
static PQconninfoOptionconninfo_find (PQconninfoOption *connOptions, const char *keyword)
 
static void defaultNoticeReceiver (void *arg, const PGresult *res)
 
static void defaultNoticeProcessor (void *arg, const char *message)
 
static int parseServiceInfo (PQconninfoOption *options, PQExpBuffer errorMessage)
 
static int parseServiceFile (const char *serviceFile, const char *service, PQconninfoOption *options, PQExpBuffer errorMessage, bool *group_found)
 
static char * pwdfMatchesString (char *buf, const char *token)
 
static char * passwordFromFile (const char *hostname, const char *port, const char *dbname, const char *username, const char *pgpassfile)
 
static void pgpassfileWarning (PGconn *conn)
 
static void default_threadlock (int acquire)
 
void pqDropConnection (PGconn *conn, bool flushInput)
 
static void pqDropServerData (PGconn *conn)
 
PGconnPQconnectdbParams (const char *const *keywords, const char *const *values, int expand_dbname)
 
PGPing PQpingParams (const char *const *keywords, const char *const *values, int expand_dbname)
 
PGconnPQconnectdb (const char *conninfo)
 
PGPing PQping (const char *conninfo)
 
PGconnPQconnectStartParams (const char *const *keywords, const char *const *values, int expand_dbname)
 
PGconnPQconnectStart (const char *conninfo)
 
static int count_comma_separated_elems (const char *input)
 
static char * parse_comma_separated_list (char **startptr, bool *more)
 
PQconninfoOptionPQconndefaults (void)
 
PGconnPQsetdbLogin (const char *pghost, const char *pgport, const char *pgoptions, const char *pgtty, const char *dbName, const char *login, const char *pwd)
 
static int connectNoDelay (PGconn *conn)
 
static void getHostaddr (PGconn *conn, char *host_addr, int host_addr_len)
 
static void connectFailureMessage (PGconn *conn, int errorno)
 
static int useKeepalives (PGconn *conn)
 
static bool parse_int_param (const char *value, int *result, PGconn *conn, const char *context)
 
static int setKeepalivesIdle (PGconn *conn)
 
static int setKeepalivesInterval (PGconn *conn)
 
static int setKeepalivesCount (PGconn *conn)
 
static int setTCPUserTimeout (PGconn *conn)
 
static bool saveErrorMessage (PGconn *conn, PQExpBuffer savedMessage)
 
static void restoreErrorMessage (PGconn *conn, PQExpBuffer savedMessage)
 
PostgresPollingStatusType PQconnectPoll (PGconn *conn)
 
void PQfinish (PGconn *conn)
 
void PQreset (PGconn *conn)
 
int PQresetStart (PGconn *conn)
 
PostgresPollingStatusType PQresetPoll (PGconn *conn)
 
PGcancelPQgetCancel (PGconn *conn)
 
void PQfreeCancel (PGcancel *cancel)
 
static int internal_cancel (SockAddr *raddr, int be_pid, int be_key, char *errbuf, int errbufsize)
 
int PQcancel (PGcancel *cancel, char *errbuf, int errbufsize)
 
int PQrequestCancel (PGconn *conn)
 
int pqPacketSend (PGconn *conn, char pack_type, const void *buf, size_t buf_len)
 
PQconninfoOptionPQconninfoParse (const char *conninfo, char **errmsg)
 
PQconninfoOptionPQconninfo (PGconn *conn)
 
void PQconninfoFree (PQconninfoOption *connOptions)
 
char * PQdb (const PGconn *conn)
 
char * PQuser (const PGconn *conn)
 
char * PQpass (const PGconn *conn)
 
char * PQhost (const PGconn *conn)
 
char * PQhostaddr (const PGconn *conn)
 
char * PQport (const PGconn *conn)
 
char * PQtty (const PGconn *conn)
 
char * PQoptions (const PGconn *conn)
 
ConnStatusType PQstatus (const PGconn *conn)
 
PGTransactionStatusType PQtransactionStatus (const PGconn *conn)
 
const char * PQparameterStatus (const PGconn *conn, const char *paramName)
 
int PQprotocolVersion (const PGconn *conn)
 
int PQserverVersion (const PGconn *conn)
 
char * PQerrorMessage (const PGconn *conn)
 
int PQsocket (const PGconn *conn)
 
int PQbackendPID (const PGconn *conn)
 
int PQconnectionNeedsPassword (const PGconn *conn)
 
int PQconnectionUsedPassword (const PGconn *conn)
 
int PQclientEncoding (const PGconn *conn)
 
int PQsetClientEncoding (PGconn *conn, const char *encoding)
 
PGVerbosity PQsetErrorVerbosity (PGconn *conn, PGVerbosity verbosity)
 
PGContextVisibility PQsetErrorContextVisibility (PGconn *conn, PGContextVisibility show_context)
 
void PQtrace (PGconn *conn, FILE *debug_port)
 
void PQuntrace (PGconn *conn)
 
PQnoticeReceiver PQsetNoticeReceiver (PGconn *conn, PQnoticeReceiver proc, void *arg)
 
PQnoticeProcessor PQsetNoticeProcessor (PGconn *conn, PQnoticeProcessor proc, void *arg)
 
bool pqGetHomeDirectory (char *buf, int bufsize)
 
pgthreadlock_t PQregisterThreadLock (pgthreadlock_t newhandler)
 

Variables

static const internalPQconninfoOption PQconninfoOptions []
 
static const PQEnvironmentOption EnvironmentOptions []
 
static const char uri_designator [] = "postgresql://"
 
static const char short_uri_designator [] = "postgres://"
 
pgthreadlock_t pg_g_threadlock = default_threadlock
 

Macro Definition Documentation

◆ DefaultAuthtype

#define DefaultAuthtype   ""

Definition at line 126 of file fe-connect.c.

◆ DefaultChannelBinding

#define DefaultChannelBinding   "disable"

Definition at line 130 of file fe-connect.c.

Referenced by connectOptions2().

◆ DefaultGSSMode

#define DefaultGSSMode   "disable"

Definition at line 142 of file fe-connect.c.

Referenced by connectOptions2().

◆ DefaultHost

#define DefaultHost   "localhost"

Definition at line 123 of file fe-connect.c.

Referenced by connectOptions2(), passwordFromFile(), and pqPacketSend().

◆ DefaultOption

#define DefaultOption   ""

Definition at line 125 of file fe-connect.c.

◆ DefaultSSLMode

#define DefaultSSLMode   "disable"

Definition at line 136 of file fe-connect.c.

Referenced by connectOptions2().

◆ DefaultTargetSessionAttrs

#define DefaultTargetSessionAttrs   "any"

Definition at line 132 of file fe-connect.c.

◆ DefaultTty

#define DefaultTty   ""

Definition at line 124 of file fe-connect.c.

◆ ERRCODE_APPNAME_UNKNOWN

#define ERRCODE_APPNAME_UNKNOWN   "42704"

Definition at line 93 of file fe-connect.c.

Referenced by PQconnectPoll().

◆ ERRCODE_CANNOT_CONNECT_NOW

#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"

Definition at line 98 of file fe-connect.c.

Referenced by internal_ping(), and ProcessStartupPacket().

◆ ERRCODE_INVALID_PASSWORD

#define ERRCODE_INVALID_PASSWORD   "28P01"

Definition at line 96 of file fe-connect.c.

Referenced by auth_failed(), pgpassfileWarning(), and recv_password_packet().

◆ LINELEN

#define LINELEN   NAMEDATALEN*5

Referenced by passwordFromFile().

◆ MAXBUFSIZE

#define MAXBUFSIZE   256

Definition at line 4938 of file fe-connect.c.

Referenced by parseServiceFile().

◆ PGPASSFILE

#define PGPASSFILE   ".pgpass"

Definition at line 82 of file fe-connect.c.

Referenced by connectOptions2().

Typedef Documentation

◆ internalPQconninfoOption

Function Documentation

◆ closePGconn()

static void closePGconn ( PGconn conn)
static

Definition at line 4063 of file fe-connect.c.

References pg_conn::asyncStatus, CONNECTION_BAD, pg_conn::errorMessage, pg_conn::nonblocking, PGASYNC_IDLE, pqClearAsyncResult(), pqDropConnection(), pqDropServerData(), PQTRANS_IDLE, release_conn_addrinfo(), resetPQExpBuffer(), sendTerminateConn(), pg_conn::status, and pg_conn::xactStatus.

Referenced by PQfinish(), PQreset(), and PQresetStart().

4064 {
4065  /*
4066  * If possible, send Terminate message to close the connection politely.
4067  */
4068  sendTerminateConn(conn);
4069 
4070  /*
4071  * Must reset the blocking status so a possible reconnect will work.
4072  *
4073  * Don't call PQsetnonblocking() because it will fail if it's unable to
4074  * flush the connection.
4075  */
4076  conn->nonblocking = false;
4077 
4078  /*
4079  * Close the connection, reset all transient state, flush I/O buffers.
4080  */
4081  pqDropConnection(conn, true);
4082  conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
4083  conn->asyncStatus = PGASYNC_IDLE;
4084  conn->xactStatus = PQTRANS_IDLE;
4085  pqClearAsyncResult(conn); /* deallocate result */
4087  release_conn_addrinfo(conn);
4088 
4089  /* Reset all state obtained from server, too */
4090  pqDropServerData(conn);
4091 }
static void release_conn_addrinfo(PGconn *conn)
Definition: fe-connect.c:4021
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:455
static void sendTerminateConn(PGconn *conn)
Definition: fe-connect.c:4036
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:386
static void pqDropServerData(PGconn *conn)
Definition: fe-connect.c:529
PQExpBufferData errorMessage
Definition: libpq-int.h:511
ConnStatusType status
Definition: libpq-int.h:385
bool nonblocking
Definition: libpq-int.h:392
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:750
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148
PGTransactionStatusType xactStatus
Definition: libpq-int.h:387

◆ connectDBComplete()

static int connectDBComplete ( PGconn conn)
static

Definition at line 1993 of file fe-connect.c.

References pg_conn::addr_cur, pg_conn::connect_timeout, CONNECTION_BAD, CONNECTION_NEEDED, pg_conn::errorMessage, flag(), parse_int_param(), PGRES_POLLING_OK, PGRES_POLLING_READING, PGRES_POLLING_WRITING, PQconnectPoll(), pqWaitTimed(), resetPQExpBuffer(), pg_conn::status, pg_conn::try_next_addr, and pg_conn::whichhost.

Referenced by internal_ping(), PQconnectdb(), PQconnectdbParams(), PQreset(), and PQsetdbLogin().

1994 {
1996  time_t finish_time = ((time_t) -1);
1997  int timeout = 0;
1998  int last_whichhost = -2; /* certainly different from whichhost */
1999  struct addrinfo *last_addr_cur = NULL;
2000 
2001  if (conn == NULL || conn->status == CONNECTION_BAD)
2002  return 0;
2003 
2004  /*
2005  * Set up a time limit, if connect_timeout isn't zero.
2006  */
2007  if (conn->connect_timeout != NULL)
2008  {
2009  if (!parse_int_param(conn->connect_timeout, &timeout, conn,
2010  "connect_timeout"))
2011  return 0;
2012 
2013  if (timeout > 0)
2014  {
2015  /*
2016  * Rounding could cause connection to fail unexpectedly quickly;
2017  * to prevent possibly waiting hardly-at-all, insist on at least
2018  * two seconds.
2019  */
2020  if (timeout < 2)
2021  timeout = 2;
2022  }
2023  else /* negative means 0 */
2024  timeout = 0;
2025  }
2026 
2027  for (;;)
2028  {
2029  int ret = 0;
2030 
2031  /*
2032  * (Re)start the connect_timeout timer if it's active and we are
2033  * considering a different host than we were last time through. If
2034  * we've already succeeded, though, needn't recalculate.
2035  */
2036  if (flag != PGRES_POLLING_OK &&
2037  timeout > 0 &&
2038  (conn->whichhost != last_whichhost ||
2039  conn->addr_cur != last_addr_cur))
2040  {
2041  finish_time = time(NULL) + timeout;
2042  last_whichhost = conn->whichhost;
2043  last_addr_cur = conn->addr_cur;
2044  }
2045 
2046  /*
2047  * Wait, if necessary. Note that the initial state (just after
2048  * PQconnectStart) is to wait for the socket to select for writing.
2049  */
2050  switch (flag)
2051  {
2052  case PGRES_POLLING_OK:
2053 
2054  /*
2055  * Reset stored error messages since we now have a working
2056  * connection
2057  */
2059  return 1; /* success! */
2060 
2061  case PGRES_POLLING_READING:
2062  ret = pqWaitTimed(1, 0, conn, finish_time);
2063  if (ret == -1)
2064  {
2065  /* hard failure, eg select() problem, aborts everything */
2066  conn->status = CONNECTION_BAD;
2067  return 0;
2068  }
2069  break;
2070 
2071  case PGRES_POLLING_WRITING:
2072  ret = pqWaitTimed(0, 1, conn, finish_time);
2073  if (ret == -1)
2074  {
2075  /* hard failure, eg select() problem, aborts everything */
2076  conn->status = CONNECTION_BAD;
2077  return 0;
2078  }
2079  break;
2080 
2081  default:
2082  /* Just in case we failed to set it in PQconnectPoll */
2083  conn->status = CONNECTION_BAD;
2084  return 0;
2085  }
2086 
2087  if (ret == 1) /* connect_timeout elapsed */
2088  {
2089  /*
2090  * Give up on current server/address, try the next one.
2091  */
2092  conn->try_next_addr = true;
2093  conn->status = CONNECTION_NEEDED;
2094  }
2095 
2096  /*
2097  * Now try to advance the state machine.
2098  */
2099  flag = PQconnectPoll(conn);
2100  }
2101 }
struct addrinfo * addr_cur
Definition: libpq-int.h:424
static bool parse_int_param(const char *value, int *result, PGconn *conn, const char *context)
Definition: fe-connect.c:1693
int pqWaitTimed(int forRead, int forWrite, PGconn *conn, time_t finish_time)
Definition: fe-misc.c:1034
char * connect_timeout
Definition: libpq-int.h:339
char * flag(int b)
Definition: test-ctype.c:33
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
Definition: fe-connect.c:2171
PQExpBufferData errorMessage
Definition: libpq-int.h:511
bool try_next_addr
Definition: libpq-int.h:421
ConnStatusType status
Definition: libpq-int.h:385
PostgresPollingStatusType
Definition: libpq-fe.h:74
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148
int whichhost
Definition: libpq-int.h:402

◆ connectDBStart()

static int connectDBStart ( PGconn conn)
static

Definition at line 1914 of file fe-connect.c.

References CONNECTION_BAD, CONNECTION_NEEDED, pg_conn::errorMessage, pg_conn::gssencmode, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, pg_conn::options_valid, pg_conn::outCount, pg_link_canary_is_frontend(), PGRES_POLLING_WRITING, PQconnectPoll(), pqDropConnection(), printfPQExpBuffer(), resetPQExpBuffer(), pg_conn::status, pg_conn::try_next_addr, pg_conn::try_next_host, and pg_conn::whichhost.

Referenced by PQconnectStart(), PQconnectStartParams(), PQreset(), PQresetStart(), and PQsetdbLogin().

1915 {
1916  if (!conn)
1917  return 0;
1918 
1919  if (!conn->options_valid)
1920  goto connect_errReturn;
1921 
1922  /*
1923  * Check for bad linking to backend-internal versions of src/common
1924  * functions (see comments in link-canary.c for the reason we need this).
1925  * Nobody but developers should see this message, so we don't bother
1926  * translating it.
1927  */
1929  {
1931  "libpq is incorrectly linked to backend functions\n");
1932  goto connect_errReturn;
1933  }
1934 
1935  /* Ensure our buffers are empty */
1936  conn->inStart = conn->inCursor = conn->inEnd = 0;
1937  conn->outCount = 0;
1938 
1939  /*
1940  * Ensure errorMessage is empty, too. PQconnectPoll will append messages
1941  * to it in the process of scanning for a working server. Thus, if we
1942  * fail to connect to multiple hosts, the final error message will include
1943  * details about each failure.
1944  */
1946 
1947 #ifdef ENABLE_GSS
1948  if (conn->gssencmode[0] == 'd') /* "disable" */
1949  conn->try_gss = false;
1950 #endif
1951 
1952  /*
1953  * Set up to try to connect to the first host. (Setting whichhost = -1 is
1954  * a bit of a cheat, but PQconnectPoll will advance it to 0 before
1955  * anything else looks at it.)
1956  */
1957  conn->whichhost = -1;
1958  conn->try_next_addr = false;
1959  conn->try_next_host = true;
1960  conn->status = CONNECTION_NEEDED;
1961 
1962  /*
1963  * The code for processing CONNECTION_NEEDED state is in PQconnectPoll(),
1964  * so that it can easily be re-executed if needed again during the
1965  * asynchronous startup process. However, we must run it once here,
1966  * because callers expect a success return from this routine to mean that
1967  * we are in PGRES_POLLING_WRITING connection state.
1968  */
1969  if (PQconnectPoll(conn) == PGRES_POLLING_WRITING)
1970  return 1;
1971 
1972 connect_errReturn:
1973 
1974  /*
1975  * If we managed to open a socket, close it immediately rather than
1976  * waiting till PQfinish. (The application cannot have gotten the socket
1977  * from PQsocket yet, so this doesn't risk breaking anything.)
1978  */
1979  pqDropConnection(conn, true);
1980  conn->status = CONNECTION_BAD;
1981  return 0;
1982 }
char * gssencmode
Definition: libpq-int.h:487
int inEnd
Definition: libpq-int.h:445
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
int inStart
Definition: libpq-int.h:443
int outCount
Definition: libpq-int.h:450
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:455
bool try_next_host
Definition: libpq-int.h:422
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
Definition: fe-connect.c:2171
PQExpBufferData errorMessage
Definition: libpq-int.h:511
bool try_next_addr
Definition: libpq-int.h:421
bool options_valid
Definition: libpq-int.h:391
ConnStatusType status
Definition: libpq-int.h:385
int inCursor
Definition: libpq-int.h:444
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148
int whichhost
Definition: libpq-int.h:402

◆ connectFailureMessage()

static void connectFailureMessage ( PGconn conn,
int  errorno 
)
static

Definition at line 1600 of file fe-connect.c.

References SockAddr::addr, appendPQExpBuffer(), CHT_HOST_ADDRESS, pg_conn::connhost, pg_conn::errorMessage, getHostaddr(), pg_conn_host::host, pg_conn_host::hostaddr, IS_AF_UNIX, libpq_gettext, NI_MAXHOST, NI_NUMERICSERV, pg_getnameinfo_all(), PG_STRERROR_R_BUFLEN, pg_conn_host::port, pg_conn::raddr, SockAddr::salen, SOCK_STRERROR, pg_conn_host::type, and pg_conn::whichhost.

Referenced by PQconnectPoll().

1601 {
1602  char sebuf[PG_STRERROR_R_BUFLEN];
1603 
1604 #ifdef HAVE_UNIX_SOCKETS
1605  if (IS_AF_UNIX(conn->raddr.addr.ss_family))
1606  {
1607  char service[NI_MAXHOST];
1608 
1609  pg_getnameinfo_all(&conn->raddr.addr, conn->raddr.salen,
1610  NULL, 0,
1611  service, sizeof(service),
1612  NI_NUMERICSERV);
1614  libpq_gettext("could not connect to server: %s\n"
1615  "\tIs the server running locally and accepting\n"
1616  "\tconnections on Unix domain socket \"%s\"?\n"),
1617  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
1618  service);
1619  }
1620  else
1621 #endif /* HAVE_UNIX_SOCKETS */
1622  {
1623  char host_addr[NI_MAXHOST];
1624  const char *displayed_host;
1625  const char *displayed_port;
1626 
1627  /*
1628  * Optionally display the network address with the hostname. This is
1629  * useful to distinguish between IPv4 and IPv6 connections.
1630  */
1631  getHostaddr(conn, host_addr, NI_MAXHOST);
1632 
1633  /* To which host and port were we actually connecting? */
1634  if (conn->connhost[conn->whichhost].type == CHT_HOST_ADDRESS)
1635  displayed_host = conn->connhost[conn->whichhost].hostaddr;
1636  else
1637  displayed_host = conn->connhost[conn->whichhost].host;
1638  displayed_port = conn->connhost[conn->whichhost].port;
1639  if (displayed_port == NULL || displayed_port[0] == '\0')
1640  displayed_port = DEF_PGPORT_STR;
1641 
1642  /*
1643  * If the user did not supply an IP address using 'hostaddr', and
1644  * 'host' was missing or does not match our lookup, display the
1645  * looked-up IP address.
1646  */
1647  if (conn->connhost[conn->whichhost].type != CHT_HOST_ADDRESS &&
1648  strlen(host_addr) > 0 &&
1649  strcmp(displayed_host, host_addr) != 0)
1651  libpq_gettext("could not connect to server: %s\n"
1652  "\tIs the server running on host \"%s\" (%s) and accepting\n"
1653  "\tTCP/IP connections on port %s?\n"),
1654  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
1655  displayed_host, host_addr,
1656  displayed_port);
1657  else
1659  libpq_gettext("could not connect to server: %s\n"
1660  "\tIs the server running on host \"%s\" and accepting\n"
1661  "\tTCP/IP connections on port %s?\n"),
1662  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
1663  displayed_host,
1664  displayed_port);
1665  }
1666 }
#define PG_STRERROR_R_BUFLEN
Definition: port.h:210
char * host
Definition: libpq-int.h:312
struct sockaddr_storage addr
Definition: pqcomm.h:64
pg_conn_host_type type
Definition: libpq-int.h:311
static void getHostaddr(PGconn *conn, char *host_addr, int host_addr_len)
Definition: fe-connect.c:1568
#define SOCK_STRERROR
Definition: libpq-int.h:804
#define NI_MAXHOST
Definition: getaddrinfo.h:88
#define IS_AF_UNIX(fam)
Definition: ip.h:24
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
char * hostaddr
Definition: libpq-int.h:313
pg_conn_host * connhost
Definition: libpq-int.h:403
ACCEPT_TYPE_ARG3 salen
Definition: pqcomm.h:65
SockAddr raddr
Definition: libpq-int.h:410
PQExpBufferData errorMessage
Definition: libpq-int.h:511
#define NI_NUMERICSERV
Definition: getaddrinfo.h:81
int pg_getnameinfo_all(const struct sockaddr_storage *addr, int salen, char *node, int nodelen, char *service, int servicelen, int flags)
Definition: ip.c:122
char * port
Definition: libpq-int.h:314
int whichhost
Definition: libpq-int.h:402
#define libpq_gettext(x)
Definition: libpq-int.h:790

◆ connectNoDelay()

static int connectNoDelay ( PGconn conn)
static

Definition at line 1541 of file fe-connect.c.

References appendPQExpBuffer(), pg_conn::errorMessage, libpq_gettext, PG_STRERROR_R_BUFLEN, pg_conn::sock, SOCK_ERRNO, and SOCK_STRERROR.

Referenced by PQconnectPoll().

1542 {
1543 #ifdef TCP_NODELAY
1544  int on = 1;
1545 
1546  if (setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY,
1547  (char *) &on,
1548  sizeof(on)) < 0)
1549  {
1550  char sebuf[PG_STRERROR_R_BUFLEN];
1551 
1553  libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
1554  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
1555  return 0;
1556  }
1557 #endif
1558 
1559  return 1;
1560 }
#define PG_STRERROR_R_BUFLEN
Definition: port.h:210
#define SOCK_STRERROR
Definition: libpq-int.h:804
#define SOCK_ERRNO
Definition: libpq-int.h:803
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
pgsocket sock
Definition: libpq-int.h:407
PQExpBufferData errorMessage
Definition: libpq-int.h:511
#define libpq_gettext(x)
Definition: libpq-int.h:790

◆ connectOptions1()

static bool connectOptions1 ( PGconn conn,
const char *  conninfo 
)
static

Definition at line 890 of file fe-connect.c.

References CONNECTION_BAD, pg_conn::errorMessage, fillPGconn(), parse_connection_string(), PQconninfoFree(), and pg_conn::status.

Referenced by PQconnectStart(), and PQsetdbLogin().

891 {
892  PQconninfoOption *connOptions;
893 
894  /*
895  * Parse the conninfo string
896  */
897  connOptions = parse_connection_string(conninfo, &conn->errorMessage, true);
898  if (connOptions == NULL)
899  {
900  conn->status = CONNECTION_BAD;
901  /* errorMessage is already set */
902  return false;
903  }
904 
905  /*
906  * Move option values into conn structure
907  */
908  if (!fillPGconn(conn, connOptions))
909  {
910  conn->status = CONNECTION_BAD;
911  PQconninfoFree(connOptions);
912  return false;
913  }
914 
915  /*
916  * Free the option info - all is in conn now
917  */
918  PQconninfoFree(connOptions);
919 
920  return true;
921 }
static PQconninfoOption * parse_connection_string(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5260
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6428
PQExpBufferData errorMessage
Definition: libpq-int.h:511
static bool fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
Definition: fe-connect.c:848
ConnStatusType status
Definition: libpq-int.h:385

◆ connectOptions2()

static bool connectOptions2 ( PGconn conn)
static

Definition at line 988 of file fe-connect.c.

References Assert, calloc, pg_conn::channel_binding, CHT_HOST_ADDRESS, CHT_HOST_NAME, CHT_UNIX_SOCKET, pg_conn::client_encoding_initial, CONNECTION_BAD, pg_conn::connhost, count_comma_separated_elems(), pg_conn::dbName, DEFAULT_PGSOCKET_DIR, DefaultChannelBinding, DefaultGSSMode, DefaultHost, DefaultSSLMode, pg_conn::errorMessage, free, pg_conn::gssencmode, pg_conn_host::host, pg_conn_host::hostaddr, i, is_absolute_path, libpq_gettext, malloc, MAXPGPATH, pg_conn::nconnhost, pg_conn::options_valid, parse_comma_separated_list(), pg_conn_host::password, passwordFromFile(), pg_encoding_to_char(), pg_fe_getauthname(), pg_get_encoding_from_locale(), pg_conn::pghost, pg_conn::pghostaddr, pg_conn::pgpass, PGPASSFILE, pg_conn::pgpassfile, pg_conn::pgport, pg_conn::pguser, pg_conn_host::port, pqGetHomeDirectory(), printfPQExpBuffer(), snprintf, pg_conn::sslmode, pg_conn::status, pg_conn::target_session_attrs, pg_conn_host::type, and pg_conn::whichhost.

Referenced by PQconnectStart(), PQconnectStartParams(), and PQsetdbLogin().

989 {
990  int i;
991 
992  /*
993  * Allocate memory for details about each host to which we might possibly
994  * try to connect. For that, count the number of elements in the hostaddr
995  * or host options. If neither is given, assume one host.
996  */
997  conn->whichhost = 0;
998  if (conn->pghostaddr && conn->pghostaddr[0] != '\0')
1000  else if (conn->pghost && conn->pghost[0] != '\0')
1002  else
1003  conn->nconnhost = 1;
1004  conn->connhost = (pg_conn_host *)
1005  calloc(conn->nconnhost, sizeof(pg_conn_host));
1006  if (conn->connhost == NULL)
1007  goto oom_error;
1008 
1009  /*
1010  * We now have one pg_conn_host structure per possible host. Fill in the
1011  * host and hostaddr fields for each, by splitting the parameter strings.
1012  */
1013  if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0')
1014  {
1015  char *s = conn->pghostaddr;
1016  bool more = true;
1017 
1018  for (i = 0; i < conn->nconnhost && more; i++)
1019  {
1020  conn->connhost[i].hostaddr = parse_comma_separated_list(&s, &more);
1021  if (conn->connhost[i].hostaddr == NULL)
1022  goto oom_error;
1023  }
1024 
1025  /*
1026  * If hostaddr was given, the array was allocated according to the
1027  * number of elements in the hostaddr list, so it really should be the
1028  * right size.
1029  */
1030  Assert(!more);
1031  Assert(i == conn->nconnhost);
1032  }
1033 
1034  if (conn->pghost != NULL && conn->pghost[0] != '\0')
1035  {
1036  char *s = conn->pghost;
1037  bool more = true;
1038 
1039  for (i = 0; i < conn->nconnhost && more; i++)
1040  {
1041  conn->connhost[i].host = parse_comma_separated_list(&s, &more);
1042  if (conn->connhost[i].host == NULL)
1043  goto oom_error;
1044  }
1045 
1046  /* Check for wrong number of host items. */
1047  if (more || i != conn->nconnhost)
1048  {
1049  conn->status = CONNECTION_BAD;
1051  libpq_gettext("could not match %d host names to %d hostaddr values\n"),
1053  return false;
1054  }
1055  }
1056 
1057  /*
1058  * Now, for each host slot, identify the type of address spec, and fill in
1059  * the default address if nothing was given.
1060  */
1061  for (i = 0; i < conn->nconnhost; i++)
1062  {
1063  pg_conn_host *ch = &conn->connhost[i];
1064 
1065  if (ch->hostaddr != NULL && ch->hostaddr[0] != '\0')
1066  ch->type = CHT_HOST_ADDRESS;
1067  else if (ch->host != NULL && ch->host[0] != '\0')
1068  {
1069  ch->type = CHT_HOST_NAME;
1070 #ifdef HAVE_UNIX_SOCKETS
1071  if (is_absolute_path(ch->host))
1072  ch->type = CHT_UNIX_SOCKET;
1073 #endif
1074  }
1075  else
1076  {
1077  if (ch->host)
1078  free(ch->host);
1079 #ifdef HAVE_UNIX_SOCKETS
1080  ch->host = strdup(DEFAULT_PGSOCKET_DIR);
1081  ch->type = CHT_UNIX_SOCKET;
1082 #else
1083  ch->host = strdup(DefaultHost);
1084  ch->type = CHT_HOST_NAME;
1085 #endif
1086  if (ch->host == NULL)
1087  goto oom_error;
1088  }
1089  }
1090 
1091  /*
1092  * Next, work out the port number corresponding to each host name.
1093  *
1094  * Note: unlike the above for host names, this could leave the port fields
1095  * as null or empty strings. We will substitute DEF_PGPORT whenever we
1096  * read such a port field.
1097  */
1098  if (conn->pgport != NULL && conn->pgport[0] != '\0')
1099  {
1100  char *s = conn->pgport;
1101  bool more = true;
1102 
1103  for (i = 0; i < conn->nconnhost && more; i++)
1104  {
1105  conn->connhost[i].port = parse_comma_separated_list(&s, &more);
1106  if (conn->connhost[i].port == NULL)
1107  goto oom_error;
1108  }
1109 
1110  /*
1111  * If exactly one port was given, use it for every host. Otherwise,
1112  * there must be exactly as many ports as there were hosts.
1113  */
1114  if (i == 1 && !more)
1115  {
1116  for (i = 1; i < conn->nconnhost; i++)
1117  {
1118  conn->connhost[i].port = strdup(conn->connhost[0].port);
1119  if (conn->connhost[i].port == NULL)
1120  goto oom_error;
1121  }
1122  }
1123  else if (more || i != conn->nconnhost)
1124  {
1125  conn->status = CONNECTION_BAD;
1127  libpq_gettext("could not match %d port numbers to %d hosts\n"),
1129  return false;
1130  }
1131  }
1132 
1133  /*
1134  * If user name was not given, fetch it. (Most likely, the fetch will
1135  * fail, since the only way we get here is if pg_fe_getauthname() failed
1136  * during conninfo_add_defaults(). But now we want an error message.)
1137  */
1138  if (conn->pguser == NULL || conn->pguser[0] == '\0')
1139  {
1140  if (conn->pguser)
1141  free(conn->pguser);
1142  conn->pguser = pg_fe_getauthname(&conn->errorMessage);
1143  if (!conn->pguser)
1144  {
1145  conn->status = CONNECTION_BAD;
1146  return false;
1147  }
1148  }
1149 
1150  /*
1151  * If database name was not given, default it to equal user name
1152  */
1153  if (conn->dbName == NULL || conn->dbName[0] == '\0')
1154  {
1155  if (conn->dbName)
1156  free(conn->dbName);
1157  conn->dbName = strdup(conn->pguser);
1158  if (!conn->dbName)
1159  goto oom_error;
1160  }
1161 
1162  /*
1163  * If password was not given, try to look it up in password file. Note
1164  * that the result might be different for each host/port pair.
1165  */
1166  if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
1167  {
1168  /* If password file wasn't specified, use ~/PGPASSFILE */
1169  if (conn->pgpassfile == NULL || conn->pgpassfile[0] == '\0')
1170  {
1171  char homedir[MAXPGPATH];
1172 
1173  if (pqGetHomeDirectory(homedir, sizeof(homedir)))
1174  {
1175  if (conn->pgpassfile)
1176  free(conn->pgpassfile);
1177  conn->pgpassfile = malloc(MAXPGPATH);
1178  if (!conn->pgpassfile)
1179  goto oom_error;
1180  snprintf(conn->pgpassfile, MAXPGPATH, "%s/%s",
1181  homedir, PGPASSFILE);
1182  }
1183  }
1184 
1185  if (conn->pgpassfile != NULL && conn->pgpassfile[0] != '\0')
1186  {
1187  for (i = 0; i < conn->nconnhost; i++)
1188  {
1189  /*
1190  * Try to get a password for this host from file. We use host
1191  * for the hostname search key if given, else hostaddr (at
1192  * least one of them is guaranteed nonempty by now).
1193  */
1194  const char *pwhost = conn->connhost[i].host;
1195 
1196  if (pwhost == NULL || pwhost[0] == '\0')
1197  pwhost = conn->connhost[i].hostaddr;
1198 
1199  conn->connhost[i].password =
1200  passwordFromFile(pwhost,
1201  conn->connhost[i].port,
1202  conn->dbName,
1203  conn->pguser,
1204  conn->pgpassfile);
1205  }
1206  }
1207  }
1208 
1209  /*
1210  * validate channel_binding option
1211  */
1212  if (conn->channel_binding)
1213  {
1214  if (strcmp(conn->channel_binding, "disable") != 0
1215  && strcmp(conn->channel_binding, "prefer") != 0
1216  && strcmp(conn->channel_binding, "require") != 0)
1217  {
1218  conn->status = CONNECTION_BAD;
1220  libpq_gettext("invalid channel_binding value: \"%s\"\n"),
1221  conn->channel_binding);
1222  return false;
1223  }
1224  }
1225  else
1226  {
1227  conn->channel_binding = strdup(DefaultChannelBinding);
1228  if (!conn->channel_binding)
1229  goto oom_error;
1230  }
1231 
1232  /*
1233  * validate sslmode option
1234  */
1235  if (conn->sslmode)
1236  {
1237  if (strcmp(conn->sslmode, "disable") != 0
1238  && strcmp(conn->sslmode, "allow") != 0
1239  && strcmp(conn->sslmode, "prefer") != 0
1240  && strcmp(conn->sslmode, "require") != 0
1241  && strcmp(conn->sslmode, "verify-ca") != 0
1242  && strcmp(conn->sslmode, "verify-full") != 0)
1243  {
1244  conn->status = CONNECTION_BAD;
1246  libpq_gettext("invalid sslmode value: \"%s\"\n"),
1247  conn->sslmode);
1248  return false;
1249  }
1250 
1251 #ifndef USE_SSL
1252  switch (conn->sslmode[0])
1253  {
1254  case 'a': /* "allow" */
1255  case 'p': /* "prefer" */
1256 
1257  /*
1258  * warn user that an SSL connection will never be negotiated
1259  * since SSL was not compiled in?
1260  */
1261  break;
1262 
1263  case 'r': /* "require" */
1264  case 'v': /* "verify-ca" or "verify-full" */
1265  conn->status = CONNECTION_BAD;
1267  libpq_gettext("sslmode value \"%s\" invalid when SSL support is not compiled in\n"),
1268  conn->sslmode);
1269  return false;
1270  }
1271 #endif
1272  }
1273  else
1274  {
1275  conn->sslmode = strdup(DefaultSSLMode);
1276  if (!conn->sslmode)
1277  goto oom_error;
1278  }
1279 
1280  /*
1281  * validate gssencmode option
1282  */
1283  if (conn->gssencmode)
1284  {
1285  if (strcmp(conn->gssencmode, "disable") != 0 &&
1286  strcmp(conn->gssencmode, "prefer") != 0 &&
1287  strcmp(conn->gssencmode, "require") != 0)
1288  {
1289  conn->status = CONNECTION_BAD;
1291  libpq_gettext("invalid gssencmode value: \"%s\"\n"),
1292  conn->gssencmode);
1293  return false;
1294  }
1295 #ifndef ENABLE_GSS
1296  if (strcmp(conn->gssencmode, "require") == 0)
1297  {
1298  conn->status = CONNECTION_BAD;
1300  libpq_gettext("gssencmode value \"%s\" invalid when GSSAPI support is not compiled in\n"),
1301  conn->gssencmode);
1302  return false;
1303  }
1304 #endif
1305  }
1306  else
1307  {
1308  conn->gssencmode = strdup(DefaultGSSMode);
1309  if (!conn->gssencmode)
1310  goto oom_error;
1311  }
1312 
1313  /*
1314  * Resolve special "auto" client_encoding from the locale
1315  */
1316  if (conn->client_encoding_initial &&
1317  strcmp(conn->client_encoding_initial, "auto") == 0)
1318  {
1321  if (!conn->client_encoding_initial)
1322  goto oom_error;
1323  }
1324 
1325  /*
1326  * Validate target_session_attrs option.
1327  */
1328  if (conn->target_session_attrs)
1329  {
1330  if (strcmp(conn->target_session_attrs, "any") != 0
1331  && strcmp(conn->target_session_attrs, "read-write") != 0)
1332  {
1333  conn->status = CONNECTION_BAD;
1335  libpq_gettext("invalid target_session_attrs value: \"%s\"\n"),
1336  conn->target_session_attrs);
1337  return false;
1338  }
1339  }
1340 
1341  /*
1342  * Only if we get this far is it appropriate to try to connect. (We need a
1343  * state flag, rather than just the boolean result of this function, in
1344  * case someone tries to PQreset() the PGconn.)
1345  */
1346  conn->options_valid = true;
1347 
1348  return true;
1349 
1350 oom_error:
1351  conn->status = CONNECTION_BAD;
1353  libpq_gettext("out of memory\n"));
1354  return false;
1355 }
#define calloc(a, b)
Definition: header.h:55
char * gssencmode
Definition: libpq-int.h:487
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
char * pgpassfile
Definition: libpq-int.h:349
char * host
Definition: libpq-int.h:312
char * dbName
Definition: libpq-int.h:345
#define DefaultSSLMode
Definition: fe-connect.c:136
pg_conn_host_type type
Definition: libpq-int.h:311
char * client_encoding_initial
Definition: libpq-int.h:341
#define malloc(a)
Definition: header.h:50
#define PGPASSFILE
Definition: fe-connect.c:82
#define MAXPGPATH
char * hostaddr
Definition: libpq-int.h:313
pg_conn_host * connhost
Definition: libpq-int.h:403
#define is_absolute_path(filename)
Definition: port.h:86
char * channel_binding
Definition: libpq-int.h:350
static int count_comma_separated_elems(const char *input)
Definition: fe-connect.c:927
char * target_session_attrs
Definition: libpq-int.h:371
char * pguser
Definition: libpq-int.h:347
char * sslmode
Definition: libpq-int.h:358
char * pg_fe_getauthname(PQExpBuffer errorMessage)
Definition: fe-auth.c:1074
PQExpBufferData errorMessage
Definition: libpq-int.h:511
static char * passwordFromFile(const char *hostname, const char *port, const char *dbname, const char *username, const char *pgpassfile)
Definition: fe-connect.c:6859
int pg_get_encoding_from_locale(const char *ctype, bool write_message)
Definition: chklocale.c:433
#define free(a)
Definition: header.h:65
const char * pg_encoding_to_char(int encoding)
Definition: encnames.c:607
bool options_valid
Definition: libpq-int.h:391
#define Assert(condition)
Definition: c.h:732
char * pgpass
Definition: libpq-int.h:348
ConnStatusType status
Definition: libpq-int.h:385
static char * parse_comma_separated_list(char **startptr, bool *more)
Definition: fe-connect.c:951
#define DefaultHost
Definition: fe-connect.c:123
char * pghostaddr
Definition: libpq-int.h:331
bool pqGetHomeDirectory(char *buf, int bufsize)
Definition: fe-connect.c:7019
int i
#define DefaultGSSMode
Definition: fe-connect.c:142
char * port
Definition: libpq-int.h:314
char * pgport
Definition: libpq-int.h:335
#define DefaultChannelBinding
Definition: fe-connect.c:130
int nconnhost
Definition: libpq-int.h:401
#define snprintf
Definition: port.h:192
int whichhost
Definition: libpq-int.h:402
#define libpq_gettext(x)
Definition: libpq-int.h:790
char * pghost
Definition: libpq-int.h:327
#define DEFAULT_PGSOCKET_DIR
char * password
Definition: libpq-int.h:315

◆ conninfo_add_defaults()

static bool conninfo_add_defaults ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

Definition at line 5656 of file fe-connect.c.

References _PQconninfoOption::compiled, _PQconninfoOption::envvar, _PQconninfoOption::keyword, libpq_gettext, parseServiceInfo(), pg_fe_getauthname(), printfPQExpBuffer(), and _PQconninfoOption::val.

Referenced by conninfo_array_parse(), conninfo_parse(), conninfo_uri_parse(), and PQconndefaults().

5657 {
5659  char *tmp;
5660 
5661  /*
5662  * If there's a service spec, use it to obtain any not-explicitly-given
5663  * parameters. Ignore error if no error message buffer is passed because
5664  * there is no way to pass back the failure message.
5665  */
5666  if (parseServiceInfo(options, errorMessage) != 0 && errorMessage)
5667  return false;
5668 
5669  /*
5670  * Get the fallback resources for parameters not specified in the conninfo
5671  * string nor the service.
5672  */
5673  for (option = options; option->keyword != NULL; option++)
5674  {
5675  if (option->val != NULL)
5676  continue; /* Value was in conninfo or service */
5677 
5678  /*
5679  * Try to get the environment variable fallback
5680  */
5681  if (option->envvar != NULL)
5682  {
5683  if ((tmp = getenv(option->envvar)) != NULL)
5684  {
5685  option->val = strdup(tmp);
5686  if (!option->val)
5687  {
5688  if (errorMessage)
5689  printfPQExpBuffer(errorMessage,
5690  libpq_gettext("out of memory\n"));
5691  return false;
5692  }
5693  continue;
5694  }
5695  }
5696 
5697  /*
5698  * Interpret the deprecated PGREQUIRESSL environment variable. Per
5699  * tradition, translate values starting with "1" to sslmode=require,
5700  * and ignore other values. Given both PGREQUIRESSL=1 and PGSSLMODE,
5701  * PGSSLMODE takes precedence; the opposite was true before v9.3.
5702  */
5703  if (strcmp(option->keyword, "sslmode") == 0)
5704  {
5705  const char *requiresslenv = getenv("PGREQUIRESSL");
5706 
5707  if (requiresslenv != NULL && requiresslenv[0] == '1')
5708  {
5709  option->val = strdup("require");
5710  if (!option->val)
5711  {
5712  if (errorMessage)
5713  printfPQExpBuffer(errorMessage,
5714  libpq_gettext("out of memory\n"));
5715  return false;
5716  }
5717  continue;
5718  }
5719  }
5720 
5721  /*
5722  * No environment variable specified or the variable isn't set - try
5723  * compiled-in default
5724  */
5725  if (option->compiled != NULL)
5726  {
5727  option->val = strdup(option->compiled);
5728  if (!option->val)
5729  {
5730  if (errorMessage)
5731  printfPQExpBuffer(errorMessage,
5732  libpq_gettext("out of memory\n"));
5733  return false;
5734  }
5735  continue;
5736  }
5737 
5738  /*
5739  * Special handling for "user" option. Note that if pg_fe_getauthname
5740  * fails, we just leave the value as NULL; there's no need for this to
5741  * be an error condition if the caller provides a user name. The only
5742  * reason we do this now at all is so that callers of PQconndefaults
5743  * will see a correct default (barring error, of course).
5744  */
5745  if (strcmp(option->keyword, "user") == 0)
5746  {
5747  option->val = pg_fe_getauthname(NULL);
5748  continue;
5749  }
5750  }
5751 
5752  return true;
5753 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
char * pg_fe_getauthname(PQExpBuffer errorMessage)
Definition: fe-auth.c:1074
static int parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:4951
#define libpq_gettext(x)
Definition: libpq-int.h:790

◆ conninfo_array_parse()

static PQconninfoOption * conninfo_array_parse ( const char *const *  keywords,
const char *const *  values,
PQExpBuffer  errorMessage,
bool  use_defaults,
int  expand_dbname 
)
static

Definition at line 5492 of file fe-connect.c.

References conninfo_add_defaults(), conninfo_init(), free, i, _internalPQconninfoOption::keyword, _PQconninfoOption::keyword, libpq_gettext, options, parse_connection_string(), PQconninfoFree(), printfPQExpBuffer(), recognized_connection_string(), _internalPQconninfoOption::val, and _PQconninfoOption::val.

Referenced by PQconnectStartParams().

5495 {
5497  PQconninfoOption *dbname_options = NULL;
5499  int i = 0;
5500 
5501  /*
5502  * If expand_dbname is non-zero, check keyword "dbname" to see if val is
5503  * actually a recognized connection string.
5504  */
5505  while (expand_dbname && keywords[i])
5506  {
5507  const char *pname = keywords[i];
5508  const char *pvalue = values[i];
5509 
5510  /* first find "dbname" if any */
5511  if (strcmp(pname, "dbname") == 0 && pvalue)
5512  {
5513  /*
5514  * If value is a connection string, parse it, but do not use
5515  * defaults here -- those get picked up later. We only want to
5516  * override for those parameters actually passed.
5517  */
5518  if (recognized_connection_string(pvalue))
5519  {
5520  dbname_options = parse_connection_string(pvalue, errorMessage, false);
5521  if (dbname_options == NULL)
5522  return NULL;
5523  }
5524  break;
5525  }
5526  ++i;
5527  }
5528 
5529  /* Make a working copy of PQconninfoOptions */
5530  options = conninfo_init(errorMessage);
5531  if (options == NULL)
5532  {
5533  PQconninfoFree(dbname_options);
5534  return NULL;
5535  }
5536 
5537  /* Parse the keywords/values arrays */
5538  i = 0;
5539  while (keywords[i])
5540  {
5541  const char *pname = keywords[i];
5542  const char *pvalue = values[i];
5543 
5544  if (pvalue != NULL && pvalue[0] != '\0')
5545  {
5546  /* Search for the param record */
5547  for (option = options; option->keyword != NULL; option++)
5548  {
5549  if (strcmp(option->keyword, pname) == 0)
5550  break;
5551  }
5552 
5553  /* Check for invalid connection option */
5554  if (option->keyword == NULL)
5555  {
5556  printfPQExpBuffer(errorMessage,
5557  libpq_gettext("invalid connection option \"%s\"\n"),
5558  pname);
5559  PQconninfoFree(options);
5560  PQconninfoFree(dbname_options);
5561  return NULL;
5562  }
5563 
5564  /*
5565  * If we are on the first dbname parameter, and we have a parsed
5566  * connection string, copy those parameters across, overriding any
5567  * existing previous settings.
5568  */
5569  if (strcmp(pname, "dbname") == 0 && dbname_options)
5570  {
5571  PQconninfoOption *str_option;
5572 
5573  for (str_option = dbname_options; str_option->keyword != NULL; str_option++)
5574  {
5575  if (str_option->val != NULL)
5576  {
5577  int k;
5578 
5579  for (k = 0; options[k].keyword; k++)
5580  {
5581  if (strcmp(options[k].keyword, str_option->keyword) == 0)
5582  {
5583  if (options[k].val)
5584  free(options[k].val);
5585  options[k].val = strdup(str_option->val);
5586  if (!options[k].val)
5587  {
5588  printfPQExpBuffer(errorMessage,
5589  libpq_gettext("out of memory\n"));
5590  PQconninfoFree(options);
5591  PQconninfoFree(dbname_options);
5592  return NULL;
5593  }
5594  break;
5595  }
5596  }
5597  }
5598  }
5599 
5600  /*
5601  * Forget the parsed connection string, so that any subsequent
5602  * dbname parameters will not be expanded.
5603  */
5604  PQconninfoFree(dbname_options);
5605  dbname_options = NULL;
5606  }
5607  else
5608  {
5609  /*
5610  * Store the value, overriding previous settings
5611  */
5612  if (option->val)
5613  free(option->val);
5614  option->val = strdup(pvalue);
5615  if (!option->val)
5616  {
5617  printfPQExpBuffer(errorMessage,
5618  libpq_gettext("out of memory\n"));
5619  PQconninfoFree(options);
5620  PQconninfoFree(dbname_options);
5621  return NULL;
5622  }
5623  }
5624  }
5625  ++i;
5626  }
5627  PQconninfoFree(dbname_options);
5628 
5629  /*
5630  * Add in defaults if the caller wants that.
5631  */
5632  if (use_defaults)
5633  {
5634  if (!conninfo_add_defaults(options, errorMessage))
5635  {
5636  PQconninfoFree(options);
5637  return NULL;
5638  }
5639  }
5640 
5641  return options;
5642 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5220
static PQconninfoOption * parse_connection_string(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5260
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6428
static char ** options
static bool recognized_connection_string(const char *connstr)
Definition: fe-connect.c:5303
#define free(a)
Definition: header.h:65
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5656
static Datum values[MAXATTR]
Definition: bootstrap.c:167
int i
long val
Definition: informix.c:684
#define libpq_gettext(x)
Definition: libpq-int.h:790

◆ conninfo_find()

static PQconninfoOption * conninfo_find ( PQconninfoOption connOptions,
const char *  keyword 
)
static

Definition at line 6369 of file fe-connect.c.

References _PQconninfoOption::keyword.

Referenced by conninfo_getval(), and conninfo_storeval().

6370 {
6372 
6373  for (option = connOptions; option->keyword != NULL; option++)
6374  {
6375  if (strcmp(option->keyword, keyword) == 0)
6376  return option;
6377  }
6378 
6379  return NULL;
6380 }

◆ conninfo_getval()

static const char * conninfo_getval ( PQconninfoOption connOptions,
const char *  keyword 
)
static

Definition at line 6278 of file fe-connect.c.

References conninfo_find(), and _PQconninfoOption::val.

Referenced by fillPGconn(), and parseServiceInfo().

6280 {
6282 
6283  option = conninfo_find(connOptions, keyword);
6284 
6285  return option ? option->val : NULL;
6286 }
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6369

◆ conninfo_init()

static PQconninfoOption * conninfo_init ( PQExpBuffer  errorMessage)
static

Definition at line 5220 of file fe-connect.c.

References _internalPQconninfoOption::keyword, libpq_gettext, malloc, MemSet, options, PQconninfoOptions, and printfPQExpBuffer().

Referenced by conninfo_array_parse(), conninfo_parse(), conninfo_uri_parse(), PQconndefaults(), and PQconninfo().

5221 {
5223  PQconninfoOption *opt_dest;
5224  const internalPQconninfoOption *cur_opt;
5225 
5226  /*
5227  * Get enough memory for all options in PQconninfoOptions, even if some
5228  * end up being filtered out.
5229  */
5230  options = (PQconninfoOption *) malloc(sizeof(PQconninfoOption) * sizeof(PQconninfoOptions) / sizeof(PQconninfoOptions[0]));
5231  if (options == NULL)
5232  {
5233  printfPQExpBuffer(errorMessage,
5234  libpq_gettext("out of memory\n"));
5235  return NULL;
5236  }
5237  opt_dest = options;
5238 
5239  for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++)
5240  {
5241  /* Only copy the public part of the struct, not the full internal */
5242  memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption));
5243  opt_dest++;
5244  }
5245  MemSet(opt_dest, 0, sizeof(PQconninfoOption));
5246 
5247  return options;
5248 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
#define MemSet(start, val, len)
Definition: c.h:955
#define malloc(a)
Definition: header.h:50
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:195
static char ** options
#define libpq_gettext(x)
Definition: libpq-int.h:790

◆ conninfo_parse()

static PQconninfoOption * conninfo_parse ( const char *  conninfo,
PQExpBuffer  errorMessage,
bool  use_defaults 
)
static

Definition at line 5314 of file fe-connect.c.

References buf, conninfo_add_defaults(), conninfo_init(), conninfo_storeval(), free, libpq_gettext, options, PQconninfoFree(), and printfPQExpBuffer().

Referenced by parse_connection_string().

5316 {
5317  char *pname;
5318  char *pval;
5319  char *buf;
5320  char *cp;
5321  char *cp2;
5323 
5324  /* Make a working copy of PQconninfoOptions */
5325  options = conninfo_init(errorMessage);
5326  if (options == NULL)
5327  return NULL;
5328 
5329  /* Need a modifiable copy of the input string */
5330  if ((buf = strdup(conninfo)) == NULL)
5331  {
5332  printfPQExpBuffer(errorMessage,
5333  libpq_gettext("out of memory\n"));
5334  PQconninfoFree(options);
5335  return NULL;
5336  }
5337  cp = buf;
5338 
5339  while (*cp)
5340  {
5341  /* Skip blanks before the parameter name */
5342  if (isspace((unsigned char) *cp))
5343  {
5344  cp++;
5345  continue;
5346  }
5347 
5348  /* Get the parameter name */
5349  pname = cp;
5350  while (*cp)
5351  {
5352  if (*cp == '=')
5353  break;
5354  if (isspace((unsigned char) *cp))
5355  {
5356  *cp++ = '\0';
5357  while (*cp)
5358  {
5359  if (!isspace((unsigned char) *cp))
5360  break;
5361  cp++;
5362  }
5363  break;
5364  }
5365  cp++;
5366  }
5367 
5368  /* Check that there is a following '=' */
5369  if (*cp != '=')
5370  {
5371  printfPQExpBuffer(errorMessage,
5372  libpq_gettext("missing \"=\" after \"%s\" in connection info string\n"),
5373  pname);
5374  PQconninfoFree(options);
5375  free(buf);
5376  return NULL;
5377  }
5378  *cp++ = '\0';
5379 
5380  /* Skip blanks after the '=' */
5381  while (*cp)
5382  {
5383  if (!isspace((unsigned char) *cp))
5384  break;
5385  cp++;
5386  }
5387 
5388  /* Get the parameter value */
5389  pval = cp;
5390 
5391  if (*cp != '\'')
5392  {
5393  cp2 = pval;
5394  while (*cp)
5395  {
5396  if (isspace((unsigned char) *cp))
5397  {
5398  *cp++ = '\0';
5399  break;
5400  }
5401  if (*cp == '\\')
5402  {
5403  cp++;
5404  if (*cp != '\0')
5405  *cp2++ = *cp++;
5406  }
5407  else
5408  *cp2++ = *cp++;
5409  }
5410  *cp2 = '\0';
5411  }
5412  else
5413  {
5414  cp2 = pval;
5415  cp++;
5416  for (;;)
5417  {
5418  if (*cp == '\0')
5419  {
5420  printfPQExpBuffer(errorMessage,
5421  libpq_gettext("unterminated quoted string in connection info string\n"));
5422  PQconninfoFree(options);
5423  free(buf);
5424  return NULL;
5425  }
5426  if (*cp == '\\')
5427  {
5428  cp++;
5429  if (*cp != '\0')
5430  *cp2++ = *cp++;
5431  continue;
5432  }
5433  if (*cp == '\'')
5434  {
5435  *cp2 = '\0';
5436  cp++;
5437  break;
5438  }
5439  *cp2++ = *cp++;
5440  }
5441  }
5442 
5443  /*
5444  * Now that we have the name and the value, store the record.
5445  */
5446  if (!conninfo_storeval(options, pname, pval, errorMessage, false, false))
5447  {
5448  PQconninfoFree(options);
5449  free(buf);
5450  return NULL;
5451  }
5452  }
5453 
5454  /* Done with the modifiable input string */
5455  free(buf);
5456 
5457  /*
5458  * Add in defaults if the caller wants that.
5459  */
5460  if (use_defaults)
5461  {
5462  if (!conninfo_add_defaults(options, errorMessage))
5463  {
5464  PQconninfoFree(options);
5465  return NULL;
5466  }
5467  }
5468 
5469  return options;
5470 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
static PQconninfoOption * conninfo_storeval(PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode)
Definition: fe-connect.c:6304
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5220
static char * buf
Definition: pg_test_fsync.c:68
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6428
static char ** options
#define free(a)
Definition: header.h:65
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5656
#define libpq_gettext(x)
Definition: libpq-int.h:790

◆ conninfo_storeval()

static PQconninfoOption * conninfo_storeval ( PQconninfoOption connOptions,
const char *  keyword,
const char *  value,
PQExpBuffer  errorMessage,
bool  ignoreMissing,
bool  uri_decode 
)
static

Definition at line 6304 of file fe-connect.c.

References conninfo_find(), conninfo_uri_decode(), free, libpq_gettext, printfPQExpBuffer(), and _PQconninfoOption::val.

Referenced by conninfo_parse(), conninfo_uri_parse_options(), conninfo_uri_parse_params(), and PQconninfo().

6308 {
6310  char *value_copy;
6311 
6312  /*
6313  * For backwards compatibility, requiressl=1 gets translated to
6314  * sslmode=require, and requiressl=0 gets translated to sslmode=prefer
6315  * (which is the default for sslmode).
6316  */
6317  if (strcmp(keyword, "requiressl") == 0)
6318  {
6319  keyword = "sslmode";
6320  if (value[0] == '1')
6321  value = "require";
6322  else
6323  value = "prefer";
6324  }
6325 
6326  option = conninfo_find(connOptions, keyword);
6327  if (option == NULL)
6328  {
6329  if (!ignoreMissing)
6330  printfPQExpBuffer(errorMessage,
6331  libpq_gettext("invalid connection option \"%s\"\n"),
6332  keyword);
6333  return NULL;
6334  }
6335 
6336  if (uri_decode)
6337  {
6338  value_copy = conninfo_uri_decode(value, errorMessage);
6339  if (value_copy == NULL)
6340  /* conninfo_uri_decode already set an error message */
6341  return NULL;
6342  }
6343  else
6344  {
6345  value_copy = strdup(value);
6346  if (value_copy == NULL)
6347  {
6348  printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
6349  return NULL;
6350  }
6351  }
6352 
6353  if (option->val)
6354  free(option->val);
6355  option->val = value_copy;
6356 
6357  return option;
6358 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6369
static char * conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
Definition: fe-connect.c:6189
static struct @145 value
#define free(a)
Definition: header.h:65
#define libpq_gettext(x)
Definition: libpq-int.h:790

◆ conninfo_uri_decode()

static char * conninfo_uri_decode ( const char *  str,
PQExpBuffer  errorMessage 
)
static

Definition at line 6189 of file fe-connect.c.

References buf, free, get_hexdigit(), libpq_gettext, malloc, printfPQExpBuffer(), and generate_unaccent_rules::str.

Referenced by conninfo_storeval(), and conninfo_uri_parse_params().

6190 {
6191  char *buf;
6192  char *p;
6193  const char *q = str;
6194 
6195  buf = malloc(strlen(str) + 1);
6196  if (buf == NULL)
6197  {
6198  printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
6199  return NULL;
6200  }
6201  p = buf;
6202 
6203  for (;;)
6204  {
6205  if (*q != '%')
6206  {
6207  /* copy and check for NUL terminator */
6208  if (!(*(p++) = *(q++)))
6209  break;
6210  }
6211  else
6212  {
6213  int hi;
6214  int lo;
6215  int c;
6216 
6217  ++q; /* skip the percent sign itself */
6218 
6219  /*
6220  * Possible EOL will be caught by the first call to
6221  * get_hexdigit(), so we never dereference an invalid q pointer.
6222  */
6223  if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo)))
6224  {
6225  printfPQExpBuffer(errorMessage,
6226  libpq_gettext("invalid percent-encoded token: \"%s\"\n"),
6227  str);
6228  free(buf);
6229  return NULL;
6230  }
6231 
6232  c = (hi << 4) | lo;
6233  if (c == 0)
6234  {
6235  printfPQExpBuffer(errorMessage,
6236  libpq_gettext("forbidden value %%00 in percent-encoded value: \"%s\"\n"),
6237  str);
6238  free(buf);
6239  return NULL;
6240  }
6241  *(p++) = c;
6242  }
6243  }
6244 
6245  return buf;
6246 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
#define malloc(a)
Definition: header.h:50
char * c
static char * buf
Definition: pg_test_fsync.c:68
#define free(a)
Definition: header.h:65
static bool get_hexdigit(char digit, int *value)
Definition: fe-connect.c:6257
#define libpq_gettext(x)
Definition: libpq-int.h:790

◆ conninfo_uri_parse()

static PQconninfoOption * conninfo_uri_parse ( const char *  uri,
PQExpBuffer  errorMessage,
bool  use_defaults 
)
static

Definition at line 5761 of file fe-connect.c.

References conninfo_add_defaults(), conninfo_init(), conninfo_uri_parse_options(), options, and PQconninfoFree().

Referenced by parse_connection_string().

5763 {
5765 
5766  /* Make a working copy of PQconninfoOptions */
5767  options = conninfo_init(errorMessage);
5768  if (options == NULL)
5769  return NULL;
5770 
5771  if (!conninfo_uri_parse_options(options, uri, errorMessage))
5772  {
5773  PQconninfoFree(options);
5774  return NULL;
5775  }
5776 
5777  /*
5778  * Add in defaults if the caller wants that.
5779  */
5780  if (use_defaults)
5781  {
5782  if (!conninfo_add_defaults(options, errorMessage))
5783  {
5784  PQconninfoFree(options);
5785  return NULL;
5786  }
5787  }
5788 
5789  return options;
5790 }
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5220
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6428
static bool conninfo_uri_parse_options(PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage)
Definition: fe-connect.c:5814
static char ** options
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5656

◆ conninfo_uri_parse_options()

static bool conninfo_uri_parse_options ( PQconninfoOption options,
const char *  uri,
PQExpBuffer  errorMessage 
)
static

Definition at line 5814 of file fe-connect.c.

References appendPQExpBufferChar(), appendPQExpBufferStr(), buf, cleanup(), conninfo_storeval(), conninfo_uri_parse_params(), PQExpBufferData::data, dbname, free, initPQExpBuffer(), libpq_gettext, password, port, PQExpBufferDataBroken, printfPQExpBuffer(), termPQExpBuffer(), uri_prefix_length(), and user.

Referenced by conninfo_uri_parse().

5816 {
5817  int prefix_len;
5818  char *p;
5819  char *buf = NULL;
5820  char *start;
5821  char prevchar = '\0';
5822  char *user = NULL;
5823  char *host = NULL;
5824  bool retval = false;
5825  PQExpBufferData hostbuf;
5826  PQExpBufferData portbuf;
5827 
5828  initPQExpBuffer(&hostbuf);
5829  initPQExpBuffer(&portbuf);
5830  if (PQExpBufferDataBroken(hostbuf) || PQExpBufferDataBroken(portbuf))
5831  {
5832  printfPQExpBuffer(errorMessage,
5833  libpq_gettext("out of memory\n"));
5834  goto cleanup;
5835  }
5836 
5837  /* need a modifiable copy of the input URI */
5838  buf = strdup(uri);
5839  if (buf == NULL)
5840  {
5841  printfPQExpBuffer(errorMessage,
5842  libpq_gettext("out of memory\n"));
5843  goto cleanup;
5844  }
5845  start = buf;
5846 
5847  /* Skip the URI prefix */
5848  prefix_len = uri_prefix_length(uri);
5849  if (prefix_len == 0)
5850  {
5851  /* Should never happen */
5852  printfPQExpBuffer(errorMessage,
5853  libpq_gettext("invalid URI propagated to internal parser routine: \"%s\"\n"),
5854  uri);
5855  goto cleanup;
5856  }
5857  start += prefix_len;
5858  p = start;
5859 
5860  /* Look ahead for possible user credentials designator */
5861  while (*p && *p != '@' && *p != '/')
5862  ++p;
5863  if (*p == '@')
5864  {
5865  /*
5866  * Found username/password designator, so URI should be of the form
5867  * "scheme://user[:password]@[netloc]".
5868  */
5869  user = start;
5870 
5871  p = user;
5872  while (*p != ':' && *p != '@')
5873  ++p;
5874 
5875  /* Save last char and cut off at end of user name */
5876  prevchar = *p;
5877  *p = '\0';
5878 
5879  if (*user &&
5880  !conninfo_storeval(options, "user", user,
5881  errorMessage, false, true))
5882  goto cleanup;
5883 
5884  if (prevchar == ':')
5885  {
5886  const char *password = p + 1;
5887 
5888  while (*p != '@')
5889  ++p;
5890  *p = '\0';
5891 
5892  if (*password &&
5893  !conninfo_storeval(options, "password", password,
5894  errorMessage, false, true))
5895  goto cleanup;
5896  }
5897 
5898  /* Advance past end of parsed user name or password token */
5899  ++p;
5900  }
5901  else
5902  {
5903  /*
5904  * No username/password designator found. Reset to start of URI.
5905  */
5906  p = start;
5907  }
5908 
5909  /*
5910  * There may be multiple netloc[:port] pairs, each separated from the next
5911  * by a comma. When we initially enter this loop, "p" has been
5912  * incremented past optional URI credential information at this point and
5913  * now points at the "netloc" part of the URI. On subsequent loop
5914  * iterations, "p" has been incremented past the comma separator and now
5915  * points at the start of the next "netloc".
5916  */
5917  for (;;)
5918  {
5919  /*
5920  * Look for IPv6 address.
5921  */
5922  if (*p == '[')
5923  {
5924  host = ++p;
5925  while (*p && *p != ']')
5926  ++p;
5927  if (!*p)
5928  {
5929  printfPQExpBuffer(errorMessage,
5930  libpq_gettext("end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"\n"),
5931  uri);
5932  goto cleanup;
5933  }
5934  if (p == host)
5935  {
5936  printfPQExpBuffer(errorMessage,
5937  libpq_gettext("IPv6 host address may not be empty in URI: \"%s\"\n"),
5938  uri);
5939  goto cleanup;
5940  }
5941 
5942  /* Cut off the bracket and advance */
5943  *(p++) = '\0';
5944 
5945  /*
5946  * The address may be followed by a port specifier or a slash or a
5947  * query or a separator comma.
5948  */
5949  if (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',')
5950  {
5951  printfPQExpBuffer(errorMessage,
5952  libpq_gettext("unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"\n"),
5953  *p, (int) (p - buf + 1), uri);
5954  goto cleanup;
5955  }
5956  }
5957  else
5958  {
5959  /* not an IPv6 address: DNS-named or IPv4 netloc */
5960  host = p;
5961 
5962  /*
5963  * Look for port specifier (colon) or end of host specifier
5964  * (slash) or query (question mark) or host separator (comma).
5965  */
5966  while (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',')
5967  ++p;
5968  }
5969 
5970  /* Save the hostname terminator before we null it */
5971  prevchar = *p;
5972  *p = '\0';
5973 
5974  appendPQExpBufferStr(&hostbuf, host);
5975 
5976  if (prevchar == ':')
5977  {
5978  const char *port = ++p; /* advance past host terminator */
5979 
5980  while (*p && *p != '/' && *p != '?' && *p != ',')
5981  ++p;
5982 
5983  prevchar = *p;
5984  *p = '\0';
5985 
5986  appendPQExpBufferStr(&portbuf, port);
5987  }
5988 
5989  if (prevchar != ',')
5990  break;
5991  ++p; /* advance past comma separator */
5992  appendPQExpBufferChar(&hostbuf, ',');
5993  appendPQExpBufferChar(&portbuf, ',');
5994  }
5995 
5996  /* Save final values for host and port. */
5997  if (PQExpBufferDataBroken(hostbuf) || PQExpBufferDataBroken(portbuf))
5998  goto cleanup;
5999  if (hostbuf.data[0] &&
6000  !conninfo_storeval(options, "host", hostbuf.data,
6001  errorMessage, false, true))
6002  goto cleanup;
6003  if (portbuf.data[0] &&
6004  !conninfo_storeval(options, "port", portbuf.data,
6005  errorMessage, false, true))
6006  goto cleanup;
6007 
6008  if (prevchar && prevchar != '?')
6009  {
6010  const char *dbname = ++p; /* advance past host terminator */
6011 
6012  /* Look for query parameters */
6013  while (*p && *p != '?')
6014  ++p;
6015 
6016  prevchar = *p;
6017  *p = '\0';
6018 
6019  /*
6020  * Avoid setting dbname to an empty string, as it forces the default
6021  * value (username) and ignores $PGDATABASE, as opposed to not setting
6022  * it at all.
6023  */
6024  if (*dbname &&
6025  !conninfo_storeval(options, "dbname", dbname,
6026  errorMessage, false, true))
6027  goto cleanup;
6028  }
6029 
6030  if (prevchar)
6031  {
6032  ++p; /* advance past terminator */
6033 
6034  if (!conninfo_uri_parse_params(p, options, errorMessage))
6035  goto cleanup;
6036  }
6037 
6038  /* everything parsed okay */
6039  retval = true;
6040 
6041 cleanup:
6042  termPQExpBuffer(&hostbuf);
6043  termPQExpBuffer(&portbuf);
6044  if (buf)
6045  free(buf);
6046  return retval;
6047 }
static char password[100]
Definition: streamutil.c:55
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
static PQconninfoOption * conninfo_storeval(PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode)
Definition: fe-connect.c:6304
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
static char * buf
Definition: pg_test_fsync.c:68
static int port
Definition: pg_regress.c:92
static void cleanup(void)
Definition: bootstrap.c:901
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:380
static bool conninfo_uri_parse_params(char *params, PQconninfoOption *connOptions, PQExpBuffer errorMessage)
Definition: fe-connect.c:6058
#define free(a)
Definition: header.h:65
#define PQExpBufferDataBroken(buf)
Definition: pqexpbuffer.h:67
char * dbname
Definition: streamutil.c:52
static char * user
Definition: pg_regress.c:95
static int uri_prefix_length(const char *connstr)
Definition: fe-connect.c:5280
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
#define libpq_gettext(x)
Definition: libpq-int.h:790

◆ conninfo_uri_parse_params()

static bool conninfo_uri_parse_params ( char *  params,
PQconninfoOption connOptions,
PQExpBuffer  errorMessage 
)
static

Definition at line 6058 of file fe-connect.c.

References conninfo_storeval(), conninfo_uri_decode(), free, _internalPQconninfoOption::keyword, PQExpBufferData::len, libpq_gettext, printfPQExpBuffer(), and value.

Referenced by conninfo_uri_parse_options().

6061 {
6062  while (*params)
6063  {
6064  char *keyword = params;
6065  char *value = NULL;
6066  char *p = params;
6067  bool malloced = false;
6068 
6069  /*
6070  * Scan the params string for '=' and '&', marking the end of keyword
6071  * and value respectively.
6072  */
6073  for (;;)
6074  {
6075  if (*p == '=')
6076  {
6077  /* Was there '=' already? */
6078  if (value != NULL)
6079  {
6080  printfPQExpBuffer(errorMessage,
6081  libpq_gettext("extra key/value separator \"=\" in URI query parameter: \"%s\"\n"),
6082  keyword);
6083  return false;
6084  }
6085  /* Cut off keyword, advance to value */
6086  *p++ = '\0';
6087  value = p;
6088  }
6089  else if (*p == '&' || *p == '\0')
6090  {
6091  /*
6092  * If not at the end, cut off value and advance; leave p
6093  * pointing to start of the next parameter, if any.
6094  */
6095  if (*p != '\0')
6096  *p++ = '\0';
6097  /* Was there '=' at all? */
6098  if (value == NULL)
6099  {
6100  printfPQExpBuffer(errorMessage,
6101  libpq_gettext("missing key/value separator \"=\" in URI query parameter: \"%s\"\n"),
6102  keyword);
6103  return false;
6104  }
6105  /* Got keyword and value, go process them. */
6106  break;
6107  }
6108  else
6109  ++p; /* Advance over all other bytes. */
6110  }
6111 
6112  keyword = conninfo_uri_decode(keyword, errorMessage);
6113  if (keyword == NULL)
6114  {
6115  /* conninfo_uri_decode already set an error message */
6116  return false;
6117  }
6118  value = conninfo_uri_decode(value, errorMessage);
6119  if (value == NULL)
6120  {
6121  /* conninfo_uri_decode already set an error message */
6122  free(keyword);
6123  return false;
6124  }
6125  malloced = true;
6126 
6127  /*
6128  * Special keyword handling for improved JDBC compatibility.
6129  */
6130  if (strcmp(keyword, "ssl") == 0 &&
6131  strcmp(value, "true") == 0)
6132  {
6133  free(keyword);
6134  free(value);
6135  malloced = false;
6136 
6137  keyword = "sslmode";
6138  value = "require";
6139  }
6140 
6141  /*
6142  * Store the value if the corresponding option exists; ignore
6143  * otherwise. At this point both keyword and value are not
6144  * URI-encoded.
6145  */
6146  if (!conninfo_storeval(connOptions, keyword, value,
6147  errorMessage, true, false))
6148  {
6149  /* Insert generic message if conninfo_storeval didn't give one. */
6150  if (errorMessage->len == 0)
6151  printfPQExpBuffer(errorMessage,
6152  libpq_gettext("invalid URI query parameter: \"%s\"\n"),
6153  keyword);
6154  /* And fail. */
6155  if (malloced)
6156  {
6157  free(keyword);
6158  free(value);
6159  }
6160  return false;
6161  }
6162 
6163  if (malloced)
6164  {
6165  free(keyword);
6166  free(value);
6167  }
6168 
6169  /* Proceed to next key=value pair, if any */
6170  params = p;
6171  }
6172 
6173  return true;
6174 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
static PQconninfoOption * conninfo_storeval(PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode)
Definition: fe-connect.c:6304
static char * conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
Definition: fe-connect.c:6189
static struct @145 value
#define free(a)
Definition: header.h:65
#define libpq_gettext(x)
Definition: libpq-int.h:790

◆ count_comma_separated_elems()

static int count_comma_separated_elems ( const char *  input)
static

Definition at line 927 of file fe-connect.c.

Referenced by connectOptions2().

928 {
929  int n;
930 
931  n = 1;
932  for (; *input != '\0'; input++)
933  {
934  if (*input == ',')
935  n++;
936  }
937 
938  return n;
939 }

◆ default_threadlock()

static void default_threadlock ( int  acquire)
static

Definition at line 7048 of file fe-connect.c.

References pthread_mutex_init(), pthread_mutex_lock(), and pthread_mutex_unlock().

Referenced by PQregisterThreadLock().

7049 {
7050 #ifdef ENABLE_THREAD_SAFETY
7051 #ifndef WIN32
7052  static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
7053 #else
7054  static pthread_mutex_t singlethread_lock = NULL;
7055  static long mutex_initlock = 0;
7056 
7057  if (singlethread_lock == NULL)
7058  {
7059  while (InterlockedExchange(&mutex_initlock, 1) == 1)
7060  /* loop, another thread own the lock */ ;
7061  if (singlethread_lock == NULL)
7062  {
7063  if (pthread_mutex_init(&singlethread_lock, NULL))
7064  PGTHREAD_ERROR("failed to initialize mutex");
7065  }
7066  InterlockedExchange(&mutex_initlock, 0);
7067  }
7068 #endif
7069  if (acquire)
7070  {
7071  if (pthread_mutex_lock(&singlethread_lock))
7072  PGTHREAD_ERROR("failed to lock mutex");
7073  }
7074  else
7075  {
7076  if (pthread_mutex_unlock(&singlethread_lock))
7077  PGTHREAD_ERROR("failed to unlock mutex");
7078  }
7079 #endif
7080 }
CRITICAL_SECTION * pthread_mutex_t
Definition: pthread-win32.h:8
int pthread_mutex_init(pthread_mutex_t *mp, void *attr)
Definition: pthread-win32.c:35
int pthread_mutex_lock(pthread_mutex_t *mp)
Definition: pthread-win32.c:45
int pthread_mutex_unlock(pthread_mutex_t *mp)
Definition: pthread-win32.c:54

◆ defaultNoticeProcessor()

static void defaultNoticeProcessor ( void *  arg,
const char *  message 
)
static

Definition at line 6810 of file fe-connect.c.

References fprintf.

Referenced by makeEmptyPGconn().

6811 {
6812  (void) arg; /* not used */
6813  /* Note: we expect the supplied string to end with a newline already. */
6814  fprintf(stderr, "%s", message);
6815 }
#define fprintf
Definition: port.h:196
void * arg

◆ defaultNoticeReceiver()

static void defaultNoticeReceiver ( void *  arg,
const PGresult res 
)
static

Definition at line 6795 of file fe-connect.c.

References pg_result::noticeHooks, PGNoticeHooks::noticeProc, PGNoticeHooks::noticeProcArg, and PQresultErrorMessage().

Referenced by makeEmptyPGconn().

6796 {
6797  (void) arg; /* not used */
6798  if (res->noticeHooks.noticeProc != NULL)
6800  PQresultErrorMessage(res));
6801 }
PGNoticeHooks noticeHooks
Definition: libpq-int.h:186
void * noticeProcArg
Definition: libpq-int.h:155
PQnoticeProcessor noticeProc
Definition: libpq-int.h:154
char * PQresultErrorMessage(const PGresult *res)
Definition: fe-exec.c:2709
void * arg

◆ fillPGconn()

static bool fillPGconn ( PGconn conn,
PQconninfoOption connOptions 
)
static

Definition at line 848 of file fe-connect.c.

References conninfo_getval(), _internalPQconninfoOption::connofs, pg_conn::errorMessage, free, _internalPQconninfoOption::keyword, libpq_gettext, and printfPQExpBuffer().

Referenced by connectOptions1(), and PQconnectStartParams().

849 {
851 
852  for (option = PQconninfoOptions; option->keyword; option++)
853  {
854  if (option->connofs >= 0)
855  {
856  const char *tmp = conninfo_getval(connOptions, option->keyword);
857 
858  if (tmp)
859  {
860  char **connmember = (char **) ((char *) conn + option->connofs);
861 
862  if (*connmember)
863  free(*connmember);
864  *connmember = strdup(tmp);
865  if (*connmember == NULL)
866  {
868  libpq_gettext("out of memory\n"));
869  return false;
870  }
871  }
872  }
873  }
874 
875  return true;
876 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:195
PQExpBufferData errorMessage
Definition: libpq-int.h:511
#define free(a)
Definition: header.h:65
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6278
#define libpq_gettext(x)
Definition: libpq-int.h:790

◆ freePGconn()

static void freePGconn ( PGconn conn)
static

Definition at line 3871 of file fe-connect.c.

References pg_conn::appname, pg_conn::channel_binding, pg_conn::client_encoding_initial, PGEventConnDestroy::conn, conn, pg_conn::connect_timeout, pg_conn::connhost, pg_conn::connip, pg_conn::dbName, pg_conn::errorMessage, pg_conn::events, explicit_bzero(), pg_conn::fbappname, free, pg_conn::gssencmode, pg_conn_host::host, pg_conn_host::hostaddr, i, pg_conn::inBuffer, pg_conn::keepalives, pg_conn::keepalives_count, pg_conn::keepalives_idle, pg_conn::keepalives_interval, pg_conn::last_query, PGEvent::name, pg_conn::nconnhost, pg_conn::nEvents, pg_conn::outBuffer, PGEvent::passThrough, pg_conn_host::password, PGEVT_CONNDESTROY, pg_conn::pghost, pg_conn::pghostaddr, pg_conn::pgoptions, pg_conn::pgpass, pg_conn::pgpassfile, pg_conn::pgport, pg_conn::pgtcp_user_timeout, pg_conn::pgtty, pg_conn::pguser, pg_conn_host::port, PGEvent::proc, pg_conn::replication, pg_conn::requirepeer, pg_conn::rowBuf, pg_conn::sslcert, pg_conn::sslcompression, pg_conn::sslcrl, pg_conn::sslkey, pg_conn::sslmode, pg_conn::sslrootcert, pg_conn::target_session_attrs, termPQExpBuffer(), pg_conn::workBuffer, and pg_conn::write_err_msg.

Referenced by makeEmptyPGconn(), and PQfinish().

3872 {
3873  int i;
3874 
3875  /* let any event procs clean up their state data */
3876  for (i = 0; i < conn->nEvents; i++)
3877  {
3878  PGEventConnDestroy evt;
3879 
3880  evt.conn = conn;
3881  (void) conn->events[i].proc(PGEVT_CONNDESTROY, &evt,
3882  conn->events[i].passThrough);
3883  free(conn->events[i].name);
3884  }
3885 
3886  /* clean up pg_conn_host structures */
3887  if (conn->connhost != NULL)
3888  {
3889  for (i = 0; i < conn->nconnhost; ++i)
3890  {
3891  if (conn->connhost[i].host != NULL)
3892  free(conn->connhost[i].host);
3893  if (conn->connhost[i].hostaddr != NULL)
3894  free(conn->connhost[i].hostaddr);
3895  if (conn->connhost[i].port != NULL)
3896  free(conn->connhost[i].port);
3897  if (conn->connhost[i].password != NULL)
3898  {
3899  explicit_bzero(conn->connhost[i].password, strlen(conn->connhost[i].password));
3900  free(conn->connhost[i].password);
3901  }
3902  }
3903  free(conn->connhost);
3904  }
3905 
3906  if (conn->client_encoding_initial)
3908  if (conn->events)
3909  free(conn->events);
3910  if (conn->pghost)
3911  free(conn->pghost);
3912  if (conn->pghostaddr)
3913  free(conn->pghostaddr);
3914  if (conn->pgport)
3915  free(conn->pgport);
3916  if (conn->pgtty)
3917  free(conn->pgtty);
3918  if (conn->connect_timeout)
3919  free(conn->connect_timeout);
3920  if (conn->pgtcp_user_timeout)
3921  free(conn->pgtcp_user_timeout);
3922  if (conn->pgoptions)
3923  free(conn->pgoptions);
3924  if (conn->appname)
3925  free(conn->appname);
3926  if (conn->fbappname)
3927  free(conn->fbappname);
3928  if (conn->dbName)
3929  free(conn->dbName);
3930  if (conn->replication)
3931  free(conn->replication);
3932  if (conn->pguser)
3933  free(conn->pguser);
3934  if (conn->pgpass)
3935  {
3936  explicit_bzero(conn->pgpass, strlen(conn->pgpass));
3937  free(conn->pgpass);
3938  }
3939  if (conn->pgpassfile)
3940  free(conn->pgpassfile);
3941  if (conn->channel_binding)
3942  free(conn->channel_binding);
3943  if (conn->keepalives)
3944  free(conn->keepalives);
3945  if (conn->keepalives_idle)
3946  free(conn->keepalives_idle);
3947  if (conn->keepalives_interval)
3948  free(conn->keepalives_interval);
3949  if (conn->keepalives_count)
3950  free(conn->keepalives_count);
3951  if (conn->sslmode)
3952  free(conn->sslmode);
3953  if (conn->sslcert)
3954  free(conn->sslcert);
3955  if (conn->sslkey)
3956  free(conn->sslkey);
3957  if (conn->sslrootcert)
3958  free(conn->sslrootcert);
3959  if (conn->sslcrl)
3960  free(conn->sslcrl);
3961  if (conn->sslcompression)
3962  free(conn->sslcompression);
3963  if (conn->requirepeer)
3964  free(conn->requirepeer);
3965  if (conn->connip)
3966  free(conn->connip);
3967  if (conn->gssencmode)
3968  free(conn->gssencmode);
3969 #if defined(ENABLE_GSS) || defined(ENABLE_SSPI)
3970  if (conn->krbsrvname)
3971  free(conn->krbsrvname);
3972 #endif
3973 #ifdef ENABLE_GSS
3974  if (conn->gcred != GSS_C_NO_CREDENTIAL)
3975  {
3976  OM_uint32 minor;
3977 
3978  gss_release_cred(&minor, &conn->gcred);
3979  conn->gcred = GSS_C_NO_CREDENTIAL;
3980  }
3981  if (conn->gctx)
3982  {
3983  OM_uint32 minor;
3984 
3985  gss_delete_sec_context(&minor, &conn->gctx, GSS_C_NO_BUFFER);
3986  conn->gctx = NULL;
3987  }
3988 #endif
3989 #if defined(ENABLE_GSS) && defined(ENABLE_SSPI)
3990  if (conn->gsslib)
3991  free(conn->gsslib);
3992 #endif
3993  /* Note that conn->Pfdebug is not ours to close or free */
3994  if (conn->last_query)
3995  free(conn->last_query);
3996  if (conn->write_err_msg)
3997  free(conn->write_err_msg);
3998  if (conn->inBuffer)
3999  free(conn->inBuffer);
4000  if (conn->outBuffer)
4001  free(conn->outBuffer);
4002  if (conn->rowBuf)
4003  free(conn->rowBuf);
4004  if (conn->target_session_attrs)
4005  free(conn->target_session_attrs);
4006  termPQExpBuffer(&conn->errorMessage);
4007  termPQExpBuffer(&conn->workBuffer);
4008 
4009  free(conn);
4010 
4011 #ifdef WIN32
4012  WSACleanup();
4013 #endif
4014 }
char * gssencmode
Definition: libpq-int.h:487
PGEvent * events
Definition: libpq-int.h:380
char * replication
Definition: libpq-int.h:346
char * pgpassfile
Definition: libpq-int.h:349
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
PQExpBufferData workBuffer
Definition: libpq-int.h:514
char * requirepeer
Definition: libpq-int.h:364
char * host
Definition: libpq-int.h:312
char * dbName
Definition: libpq-int.h:345
char * keepalives
Definition: libpq-int.h:352
char * write_err_msg
Definition: libpq-int.h:418
char * keepalives_idle
Definition: libpq-int.h:353
char * client_encoding_initial
Definition: libpq-int.h:341
char * sslkey
Definition: libpq-int.h:360
char * sslcompression
Definition: libpq-int.h:359
PGconn * conn
Definition: streamutil.c:56
char * hostaddr
Definition: libpq-int.h:313
char * connect_timeout
Definition: libpq-int.h:339
pg_conn_host * connhost
Definition: libpq-int.h:403
char * keepalives_interval
Definition: libpq-int.h:354
char * appname
Definition: libpq-int.h:343
char * channel_binding
Definition: libpq-int.h:350
char * target_session_attrs
Definition: libpq-int.h:371
char * last_query
Definition: libpq-int.h:389
PGdataValue * rowBuf
Definition: libpq-int.h:458
char * pguser
Definition: libpq-int.h:347
char * inBuffer
Definition: libpq-int.h:441
char * sslmode
Definition: libpq-int.h:358
PQExpBufferData errorMessage
Definition: libpq-int.h:511
char * sslcert
Definition: libpq-int.h:361
#define free(a)
Definition: header.h:65
char * pgoptions
Definition: libpq-int.h:342
char * connip
Definition: libpq-int.h:404
char * pgpass
Definition: libpq-int.h:348
char * sslrootcert
Definition: libpq-int.h:362
PGEventProc proc
Definition: libpq-int.h:160
char * outBuffer
Definition: libpq-int.h:448
char * pghostaddr
Definition: libpq-int.h:331
void explicit_bzero(void *buf, size_t len)
int nEvents
Definition: libpq-int.h:381
int i
void * passThrough
Definition: libpq-int.h:162
char * fbappname
Definition: libpq-int.h:344
char * port
Definition: libpq-int.h:314
char * pgport
Definition: libpq-int.h:335
int nconnhost
Definition: libpq-int.h:401
char * name
Definition: libpq-int.h:161
char * pgtcp_user_timeout
Definition: libpq-int.h:340
char * sslcrl
Definition: libpq-int.h:363
char * keepalives_count
Definition: libpq-int.h:356
char * pghost
Definition: libpq-int.h:327
char * pgtty
Definition: libpq-int.h:337
char * password
Definition: libpq-int.h:315

◆ get_hexdigit()

static bool get_hexdigit ( char  digit,
int *  value 
)
static

Definition at line 6257 of file fe-connect.c.

Referenced by conninfo_uri_decode().

6258 {
6259  if ('0' <= digit && digit <= '9')
6260  *value = digit - '0';
6261  else if ('A' <= digit && digit <= 'F')
6262  *value = digit - 'A' + 10;
6263  else if ('a' <= digit && digit <= 'f')
6264  *value = digit - 'a' + 10;
6265  else
6266  return false;
6267 
6268  return true;
6269 }
static struct @145 value

◆ getHostaddr()

static void getHostaddr ( PGconn conn,
char *  host_addr,
int  host_addr_len 
)
static

Definition at line 1568 of file fe-connect.c.

References SockAddr::addr, pg_inet_net_ntop(), and pg_conn::raddr.

Referenced by connectFailureMessage(), and PQconnectPoll().

1569 {
1570  struct sockaddr_storage *addr = &conn->raddr.addr;
1571 
1572  if (addr->ss_family == AF_INET)
1573  {
1574  if (pg_inet_net_ntop(AF_INET,
1575  &((struct sockaddr_in *) addr)->sin_addr.s_addr,
1576  32,
1577  host_addr, host_addr_len) == NULL)
1578  host_addr[0] = '\0';
1579  }
1580 #ifdef HAVE_IPV6
1581  else if (addr->ss_family == AF_INET6)
1582  {
1583  if (pg_inet_net_ntop(AF_INET6,
1584  &((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr,
1585  128,
1586  host_addr, host_addr_len) == NULL)
1587  host_addr[0] = '\0';
1588  }
1589 #endif
1590  else
1591  host_addr[0] = '\0';
1592 }
struct sockaddr_storage addr
Definition: pqcomm.h:64
char * pg_inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size)
Definition: inet_net_ntop.c:77
SockAddr raddr
Definition: libpq-int.h:410

◆ internal_cancel()

static int internal_cancel ( SockAddr raddr,
int  be_pid,
int  be_key,
char *  errbuf,
int  errbufsize 
)
static

Definition at line 4270 of file fe-connect.c.

References SockAddr::addr, CANCEL_REQUEST_CODE, closesocket, connect, EINTR, pg_hton32, PG_STRERROR_R_BUFLEN, PGINVALID_SOCKET, recv, SockAddr::salen, send, SOCK_ERRNO, SOCK_ERRNO_SET, SOCK_STRERROR, socket, and strlcpy().

Referenced by PQcancel(), and PQrequestCancel().

4272 {
4273  int save_errno = SOCK_ERRNO;
4274  pgsocket tmpsock = PGINVALID_SOCKET;
4275  char sebuf[PG_STRERROR_R_BUFLEN];
4276  int maxlen;
4277  struct
4278  {
4279  uint32 packetlen;
4281  } crp;
4282 
4283  /*
4284  * We need to open a temporary connection to the postmaster. Do this with
4285  * only kernel calls.
4286  */
4287  if ((tmpsock = socket(raddr->addr.ss_family, SOCK_STREAM, 0)) == PGINVALID_SOCKET)
4288  {
4289  strlcpy(errbuf, "PQcancel() -- socket() failed: ", errbufsize);
4290  goto cancel_errReturn;
4291  }
4292 retry3:
4293  if (connect(tmpsock, (struct sockaddr *) &raddr->addr,
4294  raddr->salen) < 0)
4295  {
4296  if (SOCK_ERRNO == EINTR)
4297  /* Interrupted system call - we'll just try again */
4298  goto retry3;
4299  strlcpy(errbuf, "PQcancel() -- connect() failed: ", errbufsize);
4300  goto cancel_errReturn;
4301  }
4302 
4303  /*
4304  * We needn't set nonblocking I/O or NODELAY options here.
4305  */
4306 
4307  /* Create and send the cancel request packet. */
4308 
4309  crp.packetlen = pg_hton32((uint32) sizeof(crp));
4310  crp.cp.cancelRequestCode = (MsgType) pg_hton32(CANCEL_REQUEST_CODE);
4311  crp.cp.backendPID = pg_hton32(be_pid);
4312  crp.cp.cancelAuthCode = pg_hton32(be_key);
4313 
4314 retry4:
4315  if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp))
4316  {
4317  if (SOCK_ERRNO == EINTR)
4318  /* Interrupted system call - we'll just try again */
4319  goto retry4;
4320  strlcpy(errbuf, "PQcancel() -- send() failed: ", errbufsize);
4321  goto cancel_errReturn;
4322  }
4323 
4324  /*
4325  * Wait for the postmaster to close the connection, which indicates that
4326  * it's processed the request. Without this delay, we might issue another
4327  * command only to find that our cancel zaps that command instead of the
4328  * one we thought we were canceling. Note we don't actually expect this
4329  * read to obtain any data, we are just waiting for EOF to be signaled.
4330  */
4331 retry5:
4332  if (recv(tmpsock, (char *) &crp, 1, 0) < 0)
4333  {
4334  if (SOCK_ERRNO == EINTR)
4335  /* Interrupted system call - we'll just try again */
4336  goto retry5;
4337  /* we ignore other error conditions */
4338  }
4339 
4340  /* All done */
4341  closesocket(tmpsock);
4342  SOCK_ERRNO_SET(save_errno);
4343  return true;
4344 
4345 cancel_errReturn:
4346 
4347  /*
4348  * Make sure we don't overflow the error buffer. Leave space for the \n at
4349  * the end, and for the terminating zero.
4350  */
4351  maxlen = errbufsize - strlen(errbuf) - 2;
4352  if (maxlen >= 0)
4353  {
4354  strncat(errbuf, SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)),
4355  maxlen);
4356  strcat(errbuf, "\n");
4357  }
4358  if (tmpsock != PGINVALID_SOCKET)
4359  closesocket(tmpsock);
4360  SOCK_ERRNO_SET(save_errno);
4361  return false;
4362 }
#define closesocket
Definition: port.h:312
#define PG_STRERROR_R_BUFLEN
Definition: port.h:210
struct sockaddr_storage addr
Definition: pqcomm.h:64
#define connect(s, name, namelen)
Definition: win32_port.h:435
#define recv(s, buf, len, flags)
Definition: win32_port.h:437
#define SOCK_STRERROR
Definition: libpq-int.h:804
#define pg_hton32(x)
Definition: pg_bswap.h:121
#define SOCK_ERRNO
Definition: libpq-int.h:803
unsigned int uint32
Definition: c.h:358
int pgsocket
Definition: port.h:31
ACCEPT_TYPE_ARG3 salen
Definition: pqcomm.h:65
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:805
#define socket(af, type, protocol)
Definition: win32_port.h:431
#define PGINVALID_SOCKET
Definition: port.h:33
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define CANCEL_REQUEST_CODE
Definition: pqcomm.h:190
ProtocolVersion MsgType
Definition: pqcomm.h:115
#define EINTR
Definition: win32_port.h:323
#define send(s, buf, len, flags)
Definition: win32_port.h:438

◆ internal_ping()

static PGPing internal_ping ( PGconn conn)
static

Definition at line 3715 of file fe-connect.c.

References pg_conn::auth_req_received, connectDBComplete(), CONNECTION_BAD, ERRCODE_CANNOT_CONNECT_NOW, pg_conn::last_sqlstate, pg_conn::options_valid, PQPING_NO_ATTEMPT, PQPING_NO_RESPONSE, PQPING_OK, PQPING_REJECT, and pg_conn::status.

Referenced by PQping(), and PQpingParams().

3716 {
3717  /* Say "no attempt" if we never got to PQconnectPoll */
3718  if (!conn || !conn->options_valid)
3719  return PQPING_NO_ATTEMPT;
3720 
3721  /* Attempt to complete the connection */
3722  if (conn->status != CONNECTION_BAD)
3723  (void) connectDBComplete(conn);
3724 
3725  /* Definitely OK if we succeeded */
3726  if (conn->status != CONNECTION_BAD)
3727  return PQPING_OK;
3728 
3729  /*
3730  * Here begins the interesting part of "ping": determine the cause of the
3731  * failure in sufficient detail to decide what to return. We do not want
3732  * to report that the server is not up just because we didn't have a valid
3733  * password, for example. In fact, any sort of authentication request
3734  * implies the server is up. (We need this check since the libpq side of
3735  * things might have pulled the plug on the connection before getting an
3736  * error as such from the postmaster.)
3737  */
3738  if (conn->auth_req_received)
3739  return PQPING_OK;
3740 
3741  /*
3742  * If we failed to get any ERROR response from the postmaster, report
3743  * PQPING_NO_RESPONSE. This result could be somewhat misleading for a
3744  * pre-7.4 server, since it won't send back a SQLSTATE, but those are long
3745  * out of support. Another corner case where the server could return a
3746  * failure without a SQLSTATE is fork failure, but PQPING_NO_RESPONSE
3747  * isn't totally unreasonable for that anyway. We expect that every other
3748  * failure case in a modern server will produce a report with a SQLSTATE.
3749  *
3750  * NOTE: whenever we get around to making libpq generate SQLSTATEs for
3751  * client-side errors, we should either not store those into
3752  * last_sqlstate, or add an extra flag so we can tell client-side errors
3753  * apart from server-side ones.
3754  */
3755  if (strlen(conn->last_sqlstate) != 5)
3756  return PQPING_NO_RESPONSE;
3757 
3758  /*
3759  * Report PQPING_REJECT if server says it's not accepting connections. (We
3760  * distinguish this case mainly for the convenience of pg_ctl.)
3761  */
3762  if (strcmp(conn->last_sqlstate, ERRCODE_CANNOT_CONNECT_NOW) == 0)
3763  return PQPING_REJECT;
3764 
3765  /*
3766  * Any other SQLSTATE can be taken to indicate that the server is up.
3767  * Presumably it didn't like our username, password, or database name; or
3768  * perhaps it had some transient failure, but that should not be taken as
3769  * meaning "it's down".
3770  */
3771  return PQPING_OK;
3772 }
static int connectDBComplete(PGconn *conn)
Definition: fe-connect.c:1993
bool options_valid
Definition: libpq-int.h:391
#define ERRCODE_CANNOT_CONNECT_NOW
Definition: fe-connect.c:98
ConnStatusType status
Definition: libpq-int.h:385
bool auth_req_received
Definition: libpq-int.h:413
char last_sqlstate[6]
Definition: libpq-int.h:390

◆ makeEmptyPGconn()

static PGconn * makeEmptyPGconn ( void  )
static

Definition at line 3780 of file fe-connect.c.

References pg_conn::asyncStatus, pg_conn::client_encoding, conn, CONNECTION_BAD, defaultNoticeProcessor(), defaultNoticeReceiver(), pg_conn::errorMessage, freePGconn(), pg_conn::inBuffer, pg_conn::inBufSize, initPQExpBuffer(), malloc, MemSet, pg_conn::nonblocking, pg_conn::noticeHooks, PGNoticeHooks::noticeProc, PGNoticeHooks::noticeRec, pg_conn::options_valid, pg_conn::outBuffer, pg_conn::outBufSize, PG_SQL_ASCII, PGASYNC_IDLE, PGINVALID_SOCKET, PQERRORS_DEFAULT, PQExpBufferBroken, PQSHOW_CONTEXT_ERRORS, PQTRANS_IDLE, pg_conn::rowBuf, pg_conn::rowBufLen, pg_conn::setenv_state, SETENV_STATE_IDLE, pg_conn::show_context, pg_conn::sock, pg_conn::status, pg_conn::std_strings, pg_conn::verbosity, pg_conn::workBuffer, and pg_conn::xactStatus.

Referenced by PQconnectStart(), PQconnectStartParams(), and PQsetdbLogin().

3781 {
3782  PGconn *conn;
3783 
3784 #ifdef WIN32
3785 
3786  /*
3787  * Make sure socket support is up and running.
3788  */
3789  WSADATA wsaData;
3790 
3791  if (WSAStartup(MAKEWORD(1, 1), &wsaData))
3792  return NULL;
3793  WSASetLastError(0);
3794 #endif
3795 
3796  conn = (PGconn *) malloc(sizeof(PGconn));
3797  if (conn == NULL)
3798  {
3799 #ifdef WIN32
3800  WSACleanup();
3801 #endif
3802  return conn;
3803  }
3804 
3805  /* Zero all pointers and booleans */
3806  MemSet(conn, 0, sizeof(PGconn));
3807 
3808  /* install default notice hooks */
3811 
3812  conn->status = CONNECTION_BAD;
3813  conn->asyncStatus = PGASYNC_IDLE;
3814  conn->xactStatus = PQTRANS_IDLE;
3815  conn->options_valid = false;
3816  conn->nonblocking = false;
3818  conn->client_encoding = PG_SQL_ASCII;
3819  conn->std_strings = false; /* unless server says differently */
3820  conn->verbosity = PQERRORS_DEFAULT;
3822  conn->sock = PGINVALID_SOCKET;
3823 #ifdef ENABLE_GSS
3824  conn->try_gss = true;
3825 #endif
3826 
3827  /*
3828  * We try to send at least 8K at a time, which is the usual size of pipe
3829  * buffers on Unix systems. That way, when we are sending a large amount
3830  * of data, we avoid incurring extra kernel context swaps for partial
3831  * bufferloads. The output buffer is initially made 16K in size, and we
3832  * try to dump it after accumulating 8K.
3833  *
3834  * With the same goal of minimizing context swaps, the input buffer will
3835  * be enlarged anytime it has less than 8K free, so we initially allocate
3836  * twice that.
3837  */
3838  conn->inBufSize = 16 * 1024;
3839  conn->inBuffer = (char *) malloc(conn->inBufSize);
3840  conn->outBufSize = 16 * 1024;
3841  conn->outBuffer = (char *) malloc(conn->outBufSize);
3842  conn->rowBufLen = 32;
3843  conn->rowBuf = (PGdataValue *) malloc(conn->rowBufLen * sizeof(PGdataValue));
3844  initPQExpBuffer(&conn->errorMessage);
3845  initPQExpBuffer(&conn->workBuffer);
3846 
3847  if (conn->inBuffer == NULL ||
3848  conn->outBuffer == NULL ||
3849  conn->rowBuf == NULL ||
3850  PQExpBufferBroken(&conn->errorMessage) ||
3851  PQExpBufferBroken(&conn->workBuffer))
3852  {
3853  /* out of memory already :-( */
3854  freePGconn(conn);
3855  conn = NULL;
3856  }
3857 
3858  return conn;
3859 }
PGContextVisibility show_context
Definition: libpq-int.h:437
int rowBufLen
Definition: libpq-int.h:459
PQExpBufferData workBuffer
Definition: libpq-int.h:514
#define MemSet(start, val, len)
Definition: c.h:955
#define malloc(a)
Definition: header.h:50
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:386
PGSetenvStatusType setenv_state
Definition: libpq-int.h:426
PGconn * conn
Definition: streamutil.c:56
int inBufSize
Definition: libpq-int.h:442
PGNoticeHooks noticeHooks
Definition: libpq-int.h:377
PGVerbosity verbosity
Definition: libpq-int.h:436
PQnoticeReceiver noticeRec
Definition: libpq-int.h:152
PGdataValue * rowBuf
Definition: libpq-int.h:458
pgsocket sock
Definition: libpq-int.h:407
#define PGINVALID_SOCKET
Definition: port.h:33
char * inBuffer
Definition: libpq-int.h:441
PQnoticeProcessor noticeProc
Definition: libpq-int.h:154
static void freePGconn(PGconn *conn)
Definition: fe-connect.c:3871
PQExpBufferData errorMessage
Definition: libpq-int.h:511
bool std_strings
Definition: libpq-int.h:435
bool options_valid
Definition: libpq-int.h:391
int outBufSize
Definition: libpq-int.h:449
#define PQExpBufferBroken(str)
Definition: pqexpbuffer.h:59
ConnStatusType status
Definition: libpq-int.h:385
char * outBuffer
Definition: libpq-int.h:448
bool nonblocking
Definition: libpq-int.h:392
static void defaultNoticeProcessor(void *arg, const char *message)
Definition: fe-connect.c:6810
int client_encoding
Definition: libpq-int.h:434
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
static void defaultNoticeReceiver(void *arg, const PGresult *res)
Definition: fe-connect.c:6795
PGTransactionStatusType xactStatus
Definition: libpq-int.h:387

◆ parse_comma_separated_list()

static char* parse_comma_separated_list ( char **  startptr,
bool more 
)
static

Definition at line 951 of file fe-connect.c.

References malloc, and startptr.

Referenced by connectOptions2().

952 {
953  char *p;
954  char *s = *startptr;
955  char *e;
956  int len;
957 
958  /*
959  * Search for the end of the current element; a comma or end-of-string
960  * acts as a terminator.
961  */
962  e = s;
963  while (*e != '\0' && *e != ',')
964  ++e;
965  *more = (*e == ',');
966 
967  len = e - s;
968  p = (char *) malloc(sizeof(char) * (len + 1));
969  if (p)
970  {
971  memcpy(p, s, len);
972  p[len] = '\0';
973  }
974  *startptr = e + 1;
975 
976  return p;
977 }
#define malloc(a)
Definition: header.h:50
e
Definition: preproc-init.c:82
static XLogRecPtr startptr
Definition: basebackup.c:118

◆ parse_connection_string()

static PQconninfoOption * parse_connection_string ( const char *  conninfo,
PQExpBuffer  errorMessage,
bool  use_defaults 
)
static

Definition at line 5260 of file fe-connect.c.

References conninfo_parse(), conninfo_uri_parse(), and uri_prefix_length().

Referenced by connectOptions1(), conninfo_array_parse(), and PQconninfoParse().

5262 {
5263  /* Parse as URI if connection string matches URI prefix */
5264  if (uri_prefix_length(connstr) != 0)
5265  return conninfo_uri_parse(connstr, errorMessage, use_defaults);
5266 
5267  /* Parse as default otherwise */
5268  return conninfo_parse(connstr, errorMessage, use_defaults);
5269 }
static PQconninfoOption * conninfo_parse(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5314
static int uri_prefix_length(const char *connstr)
Definition: fe-connect.c:5280
static PQconninfoOption * conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5761
static char * connstr
Definition: pg_dumpall.c:62

◆ parse_int_param()

static bool parse_int_param ( const char *  value,
int *  result,
PGconn conn,
const char *  context 
)
static

Definition at line 1693 of file fe-connect.c.

References appendPQExpBuffer(), pg_conn::errorMessage, and libpq_gettext.

Referenced by connectDBComplete(), PQconnectPoll(), setKeepalivesCount(), setKeepalivesIdle(), setKeepalivesInterval(), and setTCPUserTimeout().

1695 {
1696  char *end;
1697  long numval;
1698 
1699  *result = 0;
1700 
1701  errno = 0;
1702  numval = strtol(value, &end, 10);
1703  if (errno == 0 && *end == '\0' && numval == (int) numval)
1704  {
1705  *result = numval;
1706  return true;
1707  }
1708 
1710  libpq_gettext("invalid integer value \"%s\" for connection option \"%s\"\n"),
1711  value, context);
1712  return false;
1713 }
static struct @145 value
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
PQExpBufferData errorMessage
Definition: libpq-int.h:511
#define libpq_gettext(x)
Definition: libpq-int.h:790

◆ parseServiceFile()

static int parseServiceFile ( const char *  serviceFile,
const char *  service,
PQconninfoOption options,
PQExpBuffer  errorMessage,
bool group_found 
)
static

Definition at line 5020 of file fe-connect.c.

References buf, i, sort-test::key, _internalPQconninfoOption::keyword, _PQconninfoOption::keyword, libpq_gettext, MAXBUFSIZE, printfPQExpBuffer(), _internalPQconninfoOption::val, and _PQconninfoOption::val.

Referenced by parseServiceInfo().

5025 {
5026  int linenr = 0,
5027  i;
5028  FILE *f;
5029  char buf[MAXBUFSIZE],
5030  *line;
5031 
5032  f = fopen(serviceFile, "r");
5033  if (f == NULL)
5034  {
5035  printfPQExpBuffer(errorMessage, libpq_gettext("service file \"%s\" not found\n"),
5036  serviceFile);
5037  return 1;
5038  }
5039 
5040  while ((line = fgets(buf, sizeof(buf), f)) != NULL)
5041  {
5042  int len;
5043 
5044  linenr++;
5045 
5046  if (strlen(line) >= sizeof(buf) - 1)
5047  {
5048  fclose(f);
5049  printfPQExpBuffer(errorMessage,
5050  libpq_gettext("line %d too long in service file \"%s\"\n"),
5051  linenr,
5052  serviceFile);
5053  return 2;
5054  }
5055 
5056  /* ignore whitespace at end of line, especially the newline */
5057  len = strlen(line);
5058  while (len > 0 && isspace((unsigned char) line[len - 1]))
5059  line[--len] = '\0';
5060 
5061  /* ignore leading whitespace too */
5062  while (*line && isspace((unsigned char) line[0]))
5063  line++;
5064 
5065  /* ignore comments and empty lines */
5066  if (line[0] == '\0' || line[0] == '#')
5067  continue;
5068 
5069  /* Check for right groupname */
5070  if (line[0] == '[')
5071  {
5072  if (*group_found)
5073  {
5074  /* group info already read */
5075  fclose(f);
5076  return 0;
5077  }
5078 
5079  if (strncmp(line + 1, service, strlen(service)) == 0 &&
5080  line[strlen(service) + 1] == ']')
5081  *group_found = true;
5082  else
5083  *group_found = false;
5084  }
5085  else
5086  {
5087  if (*group_found)
5088  {
5089  /*
5090  * Finally, we are in the right group and can parse the line
5091  */
5092  char *key,
5093  *val;
5094  bool found_keyword;
5095 
5096 #ifdef USE_LDAP
5097  if (strncmp(line, "ldap", 4) == 0)
5098  {
5099  int rc = ldapServiceLookup(line, options, errorMessage);
5100 
5101  /* if rc = 2, go on reading for fallback */
5102  switch (rc)
5103  {
5104  case 0:
5105  fclose(f);
5106  return 0;
5107  case 1:
5108  case 3:
5109  fclose(f);
5110  return 3;
5111  case 2:
5112  continue;
5113  }
5114  }
5115 #endif
5116 
5117  key = line;
5118  val = strchr(line, '=');
5119  if (val == NULL)
5120  {
5121  printfPQExpBuffer(errorMessage,
5122  libpq_gettext("syntax error in service file \"%s\", line %d\n"),
5123  serviceFile,
5124  linenr);
5125  fclose(f);
5126  return 3;
5127  }
5128  *val++ = '\0';
5129 
5130  if (strcmp(key, "service") == 0)
5131  {
5132  printfPQExpBuffer(errorMessage,
5133  libpq_gettext("nested service specifications not supported in service file \"%s\", line %d\n"),
5134  serviceFile,
5135  linenr);
5136  fclose(f);
5137  return 3;
5138  }
5139 
5140  /*
5141  * Set the parameter --- but don't override any previous
5142  * explicit setting.
5143  */
5144  found_keyword = false;
5145  for (i = 0; options[i].keyword; i++)
5146  {
5147  if (strcmp(options[i].keyword, key) == 0)
5148  {
5149  if (options[i].val == NULL)
5150  options[i].val = strdup(val);
5151  if (!options[i].val)
5152  {
5153  printfPQExpBuffer(errorMessage,
5154  libpq_gettext("out of memory\n"));
5155  fclose(f);
5156  return 3;
5157  }
5158  found_keyword = true;
5159  break;
5160  }
5161  }
5162 
5163  if (!found_keyword)
5164  {
5165  printfPQExpBuffer(errorMessage,
5166  libpq_gettext("syntax error in service file \"%s\", line %d\n"),
5167  serviceFile,
5168  linenr);
5169  fclose(f);
5170  return 3;
5171  }
5172  }
5173  }
5174  }
5175 
5176  fclose(f);
5177 
5178  return 0;
5179 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
#define MAXBUFSIZE
Definition: fe-connect.c:4938
static char * buf
Definition: pg_test_fsync.c:68
int i
long val
Definition: informix.c:684
#define libpq_gettext(x)
Definition: libpq-int.h:790

◆ parseServiceInfo()

static int parseServiceInfo ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

Definition at line 4951 of file fe-connect.c.

References conninfo_getval(), libpq_gettext, MAXPGPATH, parseServiceFile(), pqGetHomeDirectory(), printfPQExpBuffer(), snprintf, stat, status(), and strlcpy().

Referenced by conninfo_add_defaults().

4952 {
4953  const char *service = conninfo_getval(options, "service");
4954  char serviceFile[MAXPGPATH];
4955  char *env;
4956  bool group_found = false;
4957  int status;
4958  struct stat stat_buf;
4959 
4960  /*
4961  * We have to special-case the environment variable PGSERVICE here, since
4962  * this is and should be called before inserting environment defaults for
4963  * other connection options.
4964  */
4965  if (service == NULL)
4966  service = getenv("PGSERVICE");
4967 
4968  /* If no service name given, nothing to do */
4969  if (service == NULL)
4970  return 0;
4971 
4972  /*
4973  * Try PGSERVICEFILE if specified, else try ~/.pg_service.conf (if that
4974  * exists).
4975  */
4976  if ((env = getenv("PGSERVICEFILE")) != NULL)
4977  strlcpy(serviceFile, env, sizeof(serviceFile));
4978  else
4979  {
4980  char homedir[MAXPGPATH];
4981 
4982  if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
4983  goto next_file;
4984  snprintf(serviceFile, MAXPGPATH, "%s/%s", homedir, ".pg_service.conf");
4985  if (stat(serviceFile, &stat_buf) != 0)
4986  goto next_file;
4987  }
4988 
4989  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
4990  if (group_found || status != 0)
4991  return status;
4992 
4993 next_file:
4994 
4995  /*
4996  * This could be used by any application so we can't use the binary
4997  * location to find our config files.
4998  */
4999  snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf",
5000  getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);
5001  if (stat(serviceFile, &stat_buf) != 0)
5002  goto last_file;
5003 
5004  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
5005  if (status != 0)
5006  return status;
5007 
5008 last_file:
5009  if (!group_found)
5010  {
5011  printfPQExpBuffer(errorMessage,
5012  libpq_gettext("definition of service \"%s\" not found\n"), service);
5013  return 3;
5014  }
5015 
5016  return 0;
5017 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
struct stat stat_buf
Definition: pg_standby.c:101
#define MAXPGPATH
#define stat(a, b)
Definition: win32_port.h:255
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
static int parseServiceFile(const char *serviceFile, const char *service, PQconninfoOption *options, PQExpBuffer errorMessage, bool *group_found)
Definition: fe-connect.c:5020
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6278
bool pqGetHomeDirectory(char *buf, int bufsize)
Definition: fe-connect.c:7019
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
#define snprintf
Definition: port.h:192
#define libpq_gettext(x)
Definition: libpq-int.h:790

◆ passwordFromFile()

static char * passwordFromFile ( const char *  hostname,
const char *  port,
const char *  dbname,
const char *  username,
const char *  pgpassfile 
)
static

Definition at line 6859 of file fe-connect.c.

References buf, DEFAULT_PGSOCKET_DIR, DefaultHost, explicit_bzero(), fprintf, is_absolute_path, libpq_gettext, LINELEN, pg_strip_crlf(), pwdfMatchesString(), S_IRWXG, S_IRWXO, S_ISREG, and stat.

Referenced by connectOptions2().

6861 {
6862  FILE *fp;
6863  struct stat stat_buf;
6864 
6865 #define LINELEN NAMEDATALEN*5
6866  char buf[LINELEN];
6867 
6868  if (dbname == NULL || dbname[0] == '\0')
6869  return NULL;
6870 
6871  if (username == NULL || username[0] == '\0')
6872  return NULL;
6873 
6874  /* 'localhost' matches pghost of '' or the default socket directory */
6875  if (hostname == NULL || hostname[0] == '\0')
6877  else if (is_absolute_path(hostname))
6878 
6879  /*
6880  * We should probably use canonicalize_path(), but then we have to
6881  * bring path.c into libpq, and it doesn't seem worth it.
6882  */
6883  if (strcmp(hostname, DEFAULT_PGSOCKET_DIR) == 0)
6885 
6886  if (port == NULL || port[0] == '\0')
6887  port = DEF_PGPORT_STR;
6888 
6889  /* If password file cannot be opened, ignore it. */
6890  if (stat(pgpassfile, &stat_buf) != 0)
6891  return NULL;
6892 
6893 #ifndef WIN32
6894  if (!S_ISREG(stat_buf.st_mode))
6895  {
6896  fprintf(stderr,
6897  libpq_gettext("WARNING: password file \"%s\" is not a plain file\n"),
6898  pgpassfile);
6899  return NULL;
6900  }
6901 
6902  /* If password file is insecure, alert the user and ignore it. */
6903  if (stat_buf.st_mode & (S_IRWXG | S_IRWXO))
6904  {
6905  fprintf(stderr,
6906  libpq_gettext("WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
6907  pgpassfile);
6908  return NULL;
6909  }
6910 #else
6911 
6912  /*
6913  * On Win32, the directory is protected, so we don't have to check the
6914  * file.
6915  */
6916 #endif
6917 
6918  fp = fopen(pgpassfile, "r");
6919  if (fp == NULL)
6920  return NULL;
6921 
6922  while (!feof(fp) && !ferror(fp))
6923  {
6924  char *t = buf,
6925  *ret,
6926  *p1,
6927  *p2;
6928  int len;
6929 
6930  if (fgets(buf, sizeof(buf), fp) == NULL)
6931  break;
6932 
6933  /* strip trailing newline and carriage return */
6934  len = pg_strip_crlf(buf);
6935 
6936  if (len == 0)
6937  continue;
6938 
6939  if ((t = pwdfMatchesString(t, hostname)) == NULL ||
6940  (t = pwdfMatchesString(t, port)) == NULL ||
6941  (t = pwdfMatchesString(t, dbname)) == NULL ||
6942  (t = pwdfMatchesString(t, username)) == NULL)
6943  continue;
6944 
6945  /* Found a match. */
6946  ret = strdup(t);
6947  fclose(fp);
6948 
6949  if (!ret)
6950  {
6951  /* Out of memory. XXX: an error message would be nice. */
6952  explicit_bzero(buf, sizeof(buf));
6953  return NULL;
6954  }
6955 
6956  /* De-escape password. */
6957  for (p1 = p2 = ret; *p1 != ':' && *p1 != '\0'; ++p1, ++p2)
6958  {
6959  if (*p1 == '\\' && p1[1] != '\0')
6960  ++p1;
6961  *p2 = *p1;
6962  }
6963  *p2 = '\0';
6964 
6965  return ret;
6966  }
6967 
6968  fclose(fp);
6969  explicit_bzero(buf, sizeof(buf));
6970  return NULL;
6971 
6972 #undef LINELEN
6973 }
int pg_strip_crlf(char *str)
Definition: string.c:105
#define LINELEN
#define fprintf
Definition: port.h:196
struct stat stat_buf
Definition: pg_standby.c:101
static char * buf
Definition: pg_test_fsync.c:68
#define S_IRWXG
Definition: win32_port.h:281
#define is_absolute_path(filename)
Definition: port.h:86
static int port
Definition: pg_regress.c:92
#define S_ISREG(m)
Definition: win32_port.h:299
#define stat(a, b)
Definition: win32_port.h:255
static char * username
Definition: initdb.c:133
char * dbname
Definition: streamutil.c:52
#define DefaultHost
Definition: fe-connect.c:123
static char * pwdfMatchesString(char *buf, const char *token)
Definition: fe-connect.c:6822
void explicit_bzero(void *buf, size_t len)
static char * hostname
Definition: pg_regress.c:91
#define S_IRWXO
Definition: win32_port.h:293
#define libpq_gettext(x)
Definition: libpq-int.h:790
#define DEFAULT_PGSOCKET_DIR

◆ pgpassfileWarning()

static void pgpassfileWarning ( PGconn conn)
static

Definition at line 6981 of file fe-connect.c.

References appendPQExpBuffer(), pg_conn::connhost, ERRCODE_INVALID_PASSWORD, pg_conn::errorMessage, libpq_gettext, pg_conn_host::password, pg_conn::password_needed, PG_DIAG_SQLSTATE, pg_conn::pgpassfile, PQresultErrorField(), pg_conn::result, and pg_conn::whichhost.

Referenced by PQconnectPoll().

6982 {
6983  /* If it was 'invalid authorization', add pgpassfile mention */
6984  /* only works with >= 9.0 servers */
6985  if (conn->password_needed &&
6986  conn->connhost[conn->whichhost].password != NULL &&
6987  conn->result)
6988  {
6989  const char *sqlstate = PQresultErrorField(conn->result,
6991 
6992  if (sqlstate && strcmp(sqlstate, ERRCODE_INVALID_PASSWORD) == 0)
6994  libpq_gettext("password retrieved from file \"%s\"\n"),
6995  conn->pgpassfile);
6996  }
6997 }
char * pgpassfile
Definition: libpq-int.h:349
bool password_needed
Definition: libpq-int.h:414
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
PGresult * result
Definition: libpq-int.h:462
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
pg_conn_host * connhost
Definition: libpq-int.h:403
PQExpBufferData errorMessage
Definition: libpq-int.h:511
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:2755
#define ERRCODE_INVALID_PASSWORD
Definition: fe-connect.c:96
int whichhost
Definition: libpq-int.h:402
#define libpq_gettext(x)
Definition: libpq-int.h:790
char * password
Definition: libpq-int.h:315

◆ PQbackendPID()

int PQbackendPID ( const PGconn conn)

Definition at line 6622 of file fe-connect.c.

References pg_conn::be_pid, CONNECTION_OK, and pg_conn::status.

Referenced by get_prompt(), main(), and StartLogStreamer().

6623 {
6624  if (!conn || conn->status != CONNECTION_OK)
6625  return 0;
6626  return conn->be_pid;
6627 }
ConnStatusType status
Definition: libpq-int.h:385
int be_pid
Definition: libpq-int.h:431

◆ PQcancel()

int PQcancel ( PGcancel cancel,
char *  errbuf,
int  errbufsize 
)

Definition at line 4374 of file fe-connect.c.

References pg_cancel::be_key, pg_cancel::be_pid, internal_cancel(), pg_cancel::raddr, and strlcpy().

Referenced by dblink_cancel_query(), disconnectDatabase(), DisconnectDatabase(), handle_sigint(), pgfdw_cancel_query(), setup_cancel_handler(), ShutdownWorkersHard(), sigTermHandler(), and try_complete_step().

4375 {
4376  if (!cancel)
4377  {
4378  strlcpy(errbuf, "PQcancel() -- no cancel object supplied", errbufsize);
4379  return false;
4380  }
4381 
4382  return internal_cancel(&cancel->raddr, cancel->be_pid, cancel->be_key,
4383  errbuf, errbufsize);
4384 }
static int internal_cancel(SockAddr *raddr, int be_pid, int be_key, char *errbuf, int errbufsize)
Definition: fe-connect.c:4270
int be_pid
Definition: libpq-int.h:524
int be_key
Definition: libpq-int.h:525
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
SockAddr raddr
Definition: libpq-int.h:523

◆ PQclientEncoding()

int PQclientEncoding ( const PGconn conn)

◆ PQconndefaults()

PQconninfoOption* PQconndefaults ( void  )

Definition at line 1374 of file fe-connect.c.

References conninfo_add_defaults(), conninfo_init(), initPQExpBuffer(), PQconninfoFree(), PQExpBufferDataBroken, and termPQExpBuffer().

Referenced by check_pghost_envvar(), dblink_fdw_validator(), get_connect_string(), InitPgFdwOptions(), and main().

1375 {
1376  PQExpBufferData errorBuf;
1377  PQconninfoOption *connOptions;
1378 
1379  /* We don't actually report any errors here, but callees want a buffer */
1380  initPQExpBuffer(&errorBuf);
1381  if (PQExpBufferDataBroken(errorBuf))
1382  return NULL; /* out of memory already :-( */
1383 
1384  connOptions = conninfo_init(&errorBuf);
1385  if (connOptions != NULL)
1386  {
1387  /* pass NULL errorBuf to ignore errors */
1388  if (!conninfo_add_defaults(connOptions, NULL))
1389  {
1390  PQconninfoFree(connOptions);
1391  connOptions = NULL;
1392  }
1393  }
1394 
1395  termPQExpBuffer(&errorBuf);
1396  return connOptions;
1397 }
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5220
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6428
#define PQExpBufferDataBroken(buf)
Definition: pqexpbuffer.h:67
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5656
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92

◆ PQconnectdb()

PGconn* PQconnectdb ( const char *  conninfo)

Definition at line 678 of file fe-connect.c.

References conn, connectDBComplete(), CONNECTION_BAD, PQconnectStart(), and pg_conn::status.

Referenced by dblink_connect(), dblink_get_conn(), get_db_conn(), libpqConnect(), and main().

679 {
680  PGconn *conn = PQconnectStart(conninfo);
681 
682  if (conn && conn->status != CONNECTION_BAD)
683  (void) connectDBComplete(conn);
684 
685  return conn;
686 }
PGconn * conn
Definition: streamutil.c:56
static int connectDBComplete(PGconn *conn)
Definition: fe-connect.c:1993
PGconn * PQconnectStart(const char *conninfo)
Definition: fe-connect.c:804
ConnStatusType status
Definition: libpq-int.h:385

◆ PQconnectdbParams()

PGconn* PQconnectdbParams ( const char *const *  keywords,
const char *const *  values,
int  expand_dbname 
)

Definition at line 622 of file fe-connect.c.

References conn, connectDBComplete(), CONNECTION_BAD, PQconnectStartParams(), and pg_conn::status.

Referenced by _connectDB(), connect_pg_server(), connectDatabase(), ConnectDatabase(), do_connect(), doConnect(), ECPGconnect(), GetConnection(), main(), sql_conn(), and vacuumlo().

625 {
626  PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname);
627 
628  if (conn && conn->status != CONNECTION_BAD)
629  (void) connectDBComplete(conn);
630 
631  return conn;
632 
633 }
PGconn * conn
Definition: streamutil.c:56
static int connectDBComplete(PGconn *conn)
Definition: fe-connect.c:1993
ConnStatusType status
Definition: libpq-int.h:385
static Datum values[MAXATTR]
Definition: bootstrap.c:167
PGconn * PQconnectStartParams(const char *const *keywords, const char *const *values, int expand_dbname)
Definition: fe-connect.c:725

◆ PQconnectionNeedsPassword()

int PQconnectionNeedsPassword ( const PGconn conn)

Definition at line 6630 of file fe-connect.c.

References password, pg_conn::password_needed, and PQpass().

Referenced by _connectDB(), connectDatabase(), ConnectDatabase(), do_connect(), doConnect(), GetConnection(), main(), sql_conn(), and vacuumlo().

6631 {
6632  char *password;
6633 
6634  if (!conn)
6635  return false;
6636  password = PQpass(conn);
6637  if (conn->password_needed &&
6638  (password == NULL || password[0] == '\0'))
6639  return true;
6640  else
6641  return false;
6642 }
static char password[100]
Definition: streamutil.c:55
bool password_needed
Definition: libpq-int.h:414
char * PQpass(const PGconn *conn)
Definition: fe-connect.c:6462

◆ PQconnectionUsedPassword()

int PQconnectionUsedPassword ( const PGconn conn)

Definition at line 6645 of file fe-connect.c.

References pg_conn::password_needed.

Referenced by _connectDB(), connect_pg_server(), ConnectDatabase(), and dblink_security_check().

6646 {
6647  if (!conn)
6648  return false;
6649  if (conn->password_needed)
6650  return true;
6651  else
6652  return false;
6653 }
bool password_needed
Definition: libpq-int.h:414

◆ PQconnectPoll()

PostgresPollingStatusType PQconnectPoll ( PGconn conn)

Definition at line 2171 of file fe-connect.c.

References SockAddr::addr, pg_conn::addr_cur, pg_conn::addrlist, pg_conn::addrlist_family, addrinfo::ai_addr, addrinfo::ai_addrlen, addrinfo::ai_family, addrinfo::ai_flags, addrinfo::ai_next, AI_NUMERICHOST, addrinfo::ai_socktype, appendPQExpBuffer(), appendPQExpBufferChar(), appendPQExpBufferStr(), pg_conn::appname, Assert, pg_conn::asyncStatus, AUTH_REQ_MD5, AUTH_REQ_OK, pg_conn::auth_req_received, CHT_HOST_ADDRESS, CHT_HOST_NAME, CHT_UNIX_SOCKET, connect, connectFailureMessage(), CONNECTION_AUTH_OK, CONNECTION_AWAITING_RESPONSE, CONNECTION_BAD, CONNECTION_CHECK_TARGET, CONNECTION_CHECK_WRITABLE, CONNECTION_CONSUME, CONNECTION_GSS_STARTUP, CONNECTION_MADE, CONNECTION_NEEDED, CONNECTION_OK, CONNECTION_SETENV, CONNECTION_SSL_STARTUP, CONNECTION_STARTED, connectNoDelay(), pg_conn::connhost, pg_conn::connip, PQExpBufferData::data, EINPROGRESS, EINTR, EnvironmentOptions, ERRCODE_APPNAME_UNKNOWN, pg_conn::errorMessage, EWOULDBLOCK, pg_conn::fbappname, free, gai_strerror, getHostaddr(), getpeereid(), pg_conn::gssencmode, pg_conn_host::host, pg_conn_host::hostaddr, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, IS_AF_UNIX, pg_conn::laddr, PQExpBufferData::len, libpq_gettext, MAXPGPATH, MemSet, pg_conn::nconnhost, NEGOTIATE_GSS_CODE, NEGOTIATE_SSL_CODE, pg_conn::next_eo, NI_MAXHOST, parse_int_param(), PG_DIAG_SQLSTATE, pg_fe_sendauth(), pg_getaddrinfo_all(), pg_GSS_have_cred_cache(), pg_hton32, PG_PROTOCOL, PG_PROTOCOL_MAJOR, pg_set_noblock(), PG_STRERROR_R_BUFLEN, PGASYNC_BUSY, PGASYNC_IDLE, PGINVALID_SOCKET, pgpassfileWarning(), PGRES_FATAL_ERROR, PGRES_POLLING_FAILED, PGRES_POLLING_OK, PGRES_POLLING_READING, PGRES_POLLING_WRITING, PGRES_TUPLES_OK, pg_conn_host::port, pqBuildStartupPacket2(), pqBuildStartupPacket3(), pqCheckInBufferSpace(), PQclear(), pqClearAsyncResult(), PQconsumeInput(), pqDropConnection(), pqDropServerData(), pqFlush(), pqGetc(), pqGetErrorNotice3(), pqGetInt(), pqGetpwuid(), PQgetResult(), pqGets_append(), PQgetvalue(), PQisBusy(), PQntuples(), pqPacketSend(), pqReadData(), PQresultErrorField(), PQresultStatus(), pqsecure_initialize(), pqsecure_open_client(), pqsecure_open_gss(), PQsendQuery(), pqSetenvPoll(), PQTRANS_IDLE, printfPQExpBuffer(), pg_conn::pversion, pg_conn::raddr, release_conn_addrinfo(), pg_conn::requirepeer, restoreErrorMessage(), pg_result::resultStatus, SockAddr::salen, saveErrorMessage(), pg_conn::send_appname, sendTerminateConn(), pg_conn::setenv_state, SETENV_STATE_CLIENT_ENCODING_SEND, setKeepalivesCount(), setKeepalivesIdle(), setKeepalivesInterval(), setTCPUserTimeout(), pg_conn::sigpipe_flag, pg_conn::sigpipe_so, snprintf, pg_conn::sock, SOCK_ERRNO, SOCK_STRERROR, socket, pg_conn::ssl_in_use, pg_conn::sslmode, pg_conn::status, STATUS_OK, strerror_r, pg_conn::sversion, pg_conn::target_session_attrs, termPQExpBuffer(), pg_conn::try_next_addr, pg_conn::try_next_host, pg_conn_host::type, UNIXSOCK_PATH, UNIXSOCK_PATH_BUFLEN, useKeepalives(), _internalPQconninfoOption::val, pg_conn::whichhost, and pg_conn::xactStatus.

Referenced by connectDBComplete(), connectDBStart(), libpqrcv_connect(), and PQresetPoll().

2172 {
2173  bool reset_connection_state_machine = false;
2174  bool need_new_connection = false;
2175  PGresult *res;
2176  char sebuf[PG_STRERROR_R_BUFLEN];
2177  int optval;
2178  PQExpBufferData savedMessage;
2179 
2180  if (conn == NULL)
2181  return PGRES_POLLING_FAILED;
2182 
2183  /* Get the new data */
2184  switch (conn->status)
2185  {
2186  /*
2187  * We really shouldn't have been polled in these two cases, but we
2188  * can handle it.
2189  */
2190  case CONNECTION_BAD:
2191  return PGRES_POLLING_FAILED;
2192  case CONNECTION_OK:
2193  return PGRES_POLLING_OK;
2194 
2195  /* These are reading states */
2197  case CONNECTION_AUTH_OK:
2198  {
2199  /* Load waiting data */
2200  int n = pqReadData(conn);
2201 
2202  if (n < 0)
2203  goto error_return;
2204  if (n == 0)
2205  return PGRES_POLLING_READING;
2206 
2207  break;
2208  }
2209 
2210  /* These are writing states, so we just proceed. */
2211  case CONNECTION_STARTED:
2212  case CONNECTION_MADE:
2213  break;
2214 
2215  /* We allow pqSetenvPoll to decide whether to proceed. */
2216  case CONNECTION_SETENV:
2217  break;
2218 
2219  /* Special cases: proceed without waiting. */
2221  case CONNECTION_NEEDED:
2223  case CONNECTION_CONSUME:
2225  break;
2226 
2227  default:
2229  libpq_gettext(
2230  "invalid connection state, "
2231  "probably indicative of memory corruption\n"
2232  ));
2233  goto error_return;
2234  }
2235 
2236 
2237 keep_going: /* We will come back to here until there is
2238  * nothing left to do. */
2239 
2240  /* Time to advance to next address, or next host if no more addresses? */
2241  if (conn->try_next_addr)
2242  {
2243  if (conn->addr_cur && conn->addr_cur->ai_next)
2244  {
2245  conn->addr_cur = conn->addr_cur->ai_next;
2246  reset_connection_state_machine = true;
2247  }
2248  else
2249  conn->try_next_host = true;
2250  conn->try_next_addr = false;
2251  }
2252 
2253  /* Time to advance to next connhost[] entry? */
2254  if (conn->try_next_host)
2255  {
2256  pg_conn_host *ch;
2257  struct addrinfo hint;
2258  int thisport;
2259  int ret;
2260  char portstr[MAXPGPATH];
2261 
2262  if (conn->whichhost + 1 >= conn->nconnhost)
2263  {
2264  /*
2265  * Oops, no more hosts. An appropriate error message is already
2266  * set up, so just set the right status.
2267  */
2268  goto error_return;
2269  }
2270  conn->whichhost++;
2271 
2272  /* Drop any address info for previous host */
2273  release_conn_addrinfo(conn);
2274 
2275  /*
2276  * Look up info for the new host. On failure, log the problem in
2277  * conn->errorMessage, then loop around to try the next host. (Note
2278  * we don't clear try_next_host until we've succeeded.)
2279  */
2280  ch = &conn->connhost[conn->whichhost];
2281 
2282  /* Initialize hint structure */
2283  MemSet(&hint, 0, sizeof(hint));
2284  hint.ai_socktype = SOCK_STREAM;
2285  conn->addrlist_family = hint.ai_family = AF_UNSPEC;
2286 
2287  /* Figure out the port number we're going to use. */
2288  if (ch->port == NULL || ch->port[0] == '\0')
2289  thisport = DEF_PGPORT;
2290  else
2291  {
2292  if (!parse_int_param(ch->port, &thisport, conn, "port"))
2293  goto error_return;
2294 
2295  if (thisport < 1 || thisport > 65535)
2296  {
2298  libpq_gettext("invalid port number: \"%s\"\n"),
2299  ch->port);
2300  goto keep_going;
2301  }
2302  }
2303  snprintf(portstr, sizeof(portstr), "%d", thisport);
2304 
2305  /* Use pg_getaddrinfo_all() to resolve the address */
2306  switch (ch->type)
2307  {
2308  case CHT_HOST_NAME:
2309  ret = pg_getaddrinfo_all(ch->host, portstr, &hint,
2310  &conn->addrlist);
2311  if (ret || !conn->addrlist)
2312  {
2314  libpq_gettext("could not translate host name \"%s\" to address: %s\n"),
2315  ch->host, gai_strerror(ret));
2316  goto keep_going;
2317  }
2318  break;
2319 
2320  case CHT_HOST_ADDRESS:
2321  hint.ai_flags = AI_NUMERICHOST;
2322  ret = pg_getaddrinfo_all(ch->hostaddr, portstr, &hint,
2323  &conn->addrlist);
2324  if (ret || !conn->addrlist)
2325  {
2327  libpq_gettext("could not parse network address \"%s\": %s\n"),
2328  ch->hostaddr, gai_strerror(ret));
2329  goto keep_going;
2330  }
2331  break;
2332 
2333  case CHT_UNIX_SOCKET:
2334 #ifdef HAVE_UNIX_SOCKETS
2335  conn->addrlist_family = hint.ai_family = AF_UNIX;
2336  UNIXSOCK_PATH(portstr, thisport, ch->host);
2337  if (strlen(portstr) >= UNIXSOCK_PATH_BUFLEN)
2338  {
2340  libpq_gettext("Unix-domain socket path \"%s\" is too long (maximum %d bytes)\n"),
2341  portstr,
2342  (int) (UNIXSOCK_PATH_BUFLEN - 1));
2343  goto keep_going;
2344  }
2345 
2346  /*
2347  * NULL hostname tells pg_getaddrinfo_all to parse the service
2348  * name as a Unix-domain socket path.
2349  */
2350  ret = pg_getaddrinfo_all(NULL, portstr, &hint,
2351  &conn->addrlist);
2352  if (ret || !conn->addrlist)
2353  {
2355  libpq_gettext("could not translate Unix-domain socket path \"%s\" to address: %s\n"),
2356  portstr, gai_strerror(ret));
2357  goto keep_going;
2358  }
2359 #else
2360  Assert(false);
2361 #endif
2362  break;
2363  }
2364 
2365  /* OK, scan this addrlist for a working server address */
2366  conn->addr_cur = conn->addrlist;
2367  reset_connection_state_machine = true;
2368  conn->try_next_host = false;
2369  }
2370 
2371  /* Reset connection state machine? */
2372  if (reset_connection_state_machine)
2373  {
2374  /*
2375  * (Re) initialize our connection control variables for a set of
2376  * connection attempts to a single server address. These variables
2377  * must persist across individual connection attempts, but we must
2378  * reset them when we start to consider a new server.
2379  */
2380  conn->pversion = PG_PROTOCOL(3, 0);
2381  conn->send_appname = true;
2382 #ifdef USE_SSL
2383  /* initialize these values based on SSL mode */
2384  conn->allow_ssl_try = (conn->sslmode[0] != 'd'); /* "disable" */
2385  conn->wait_ssl_try = (conn->sslmode[0] == 'a'); /* "allow" */
2386 #endif
2387 
2388  reset_connection_state_machine = false;
2389  need_new_connection = true;
2390  }
2391 
2392  /* Force a new connection (perhaps to the same server as before)? */
2393  if (need_new_connection)
2394  {
2395  /* Drop any existing connection */
2396  pqDropConnection(conn, true);
2397 
2398  /* Reset all state obtained from old server */
2399  pqDropServerData(conn);
2400 
2401  /* Drop any PGresult we might have, too */
2402  conn->asyncStatus = PGASYNC_IDLE;
2403  conn->xactStatus = PQTRANS_IDLE;
2404  pqClearAsyncResult(conn);
2405 
2406  /* Reset conn->status to put the state machine in the right state */
2407  conn->status = CONNECTION_NEEDED;
2408 
2409  need_new_connection = false;
2410  }
2411 
2412  /* Now try to advance the state machine for this connection */
2413  switch (conn->status)
2414  {
2415  case CONNECTION_NEEDED:
2416  {
2417  /*
2418  * Try to initiate a connection to one of the addresses
2419  * returned by pg_getaddrinfo_all(). conn->addr_cur is the
2420  * next one to try.
2421  *
2422  * The extra level of braces here is historical. It's not
2423  * worth reindenting this whole switch case to remove 'em.
2424  */
2425  {
2426  struct addrinfo *addr_cur = conn->addr_cur;
2427  char host_addr[NI_MAXHOST];
2428 
2429  /*
2430  * Advance to next possible host, if we've tried all of
2431  * the addresses for the current host.
2432  */
2433  if (addr_cur == NULL)
2434  {
2435  conn->try_next_host = true;
2436  goto keep_going;
2437  }
2438 
2439  /* Remember current address for possible error msg */
2440  memcpy(&conn->raddr.addr, addr_cur->ai_addr,
2441  addr_cur->ai_addrlen);
2442  conn->raddr.salen = addr_cur->ai_addrlen;
2443 
2444  /* set connip */
2445  if (conn->connip != NULL)
2446  {
2447  free(conn->connip);
2448  conn->connip = NULL;
2449  }
2450 
2451  getHostaddr(conn, host_addr, NI_MAXHOST);
2452  if (strlen(host_addr) > 0)
2453  conn->connip = strdup(host_addr);
2454 
2455  /*
2456  * purposely ignore strdup failure; not a big problem if
2457  * it fails anyway.
2458  */
2459 
2460  conn->sock = socket(addr_cur->ai_family, SOCK_STREAM, 0);
2461  if (conn->sock == PGINVALID_SOCKET)
2462  {
2463  /*
2464  * Silently ignore socket() failure if we have more
2465  * addresses to try; this reduces useless chatter in
2466  * cases where the address list includes both IPv4 and
2467  * IPv6 but kernel only accepts one family.
2468  */
2469  if (addr_cur->ai_next != NULL ||
2470  conn->whichhost + 1 < conn->nconnhost)
2471  {
2472  conn->try_next_addr = true;
2473  goto keep_going;
2474  }
2476  libpq_gettext("could not create socket: %s\n"),
2477  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2478  goto error_return;
2479  }
2480 
2481  /*
2482  * Select socket options: no delay of outgoing data for
2483  * TCP sockets, nonblock mode, close-on-exec. Try the
2484  * next address if any of this fails.
2485  */
2486  if (!IS_AF_UNIX(addr_cur->ai_family))
2487  {
2488  if (!connectNoDelay(conn))
2489  {
2490  /* error message already created */
2491  conn->try_next_addr = true;
2492  goto keep_going;
2493  }
2494  }
2495  if (!pg_set_noblock(conn->sock))
2496  {
2498  libpq_gettext("could not set socket to nonblocking mode: %s\n"),
2499  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2500  conn->try_next_addr = true;
2501  goto keep_going;
2502  }
2503 
2504 #ifdef F_SETFD
2505  if (fcntl(conn->sock, F_SETFD, FD_CLOEXEC) == -1)
2506  {
2508  libpq_gettext("could not set socket to close-on-exec mode: %s\n"),
2509  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2510  conn->try_next_addr = true;
2511  goto keep_going;
2512  }
2513 #endif /* F_SETFD */
2514 
2515  if (!IS_AF_UNIX(addr_cur->ai_family))
2516  {
2517 #ifndef WIN32
2518  int on = 1;
2519 #endif
2520  int usekeepalives = useKeepalives(conn);
2521  int err = 0;
2522 
2523  if (usekeepalives < 0)
2524  {
2526  libpq_gettext("keepalives parameter must be an integer\n"));
2527  err = 1;
2528  }
2529  else if (usekeepalives == 0)
2530  {
2531  /* Do nothing */
2532  }
2533 #ifndef WIN32
2534  else if (setsockopt(conn->sock,
2535  SOL_SOCKET, SO_KEEPALIVE,
2536  (char *) &on, sizeof(on)) < 0)
2537  {
2539  libpq_gettext("setsockopt(%s) failed: %s\n"),
2540  "SO_KEEPALIVE",
2541  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2542  err = 1;
2543  }
2544  else if (!setKeepalivesIdle(conn)
2545  || !setKeepalivesInterval(conn)
2546  || !setKeepalivesCount(conn))
2547  err = 1;
2548 #else /* WIN32 */
2549 #ifdef SIO_KEEPALIVE_VALS
2550  else if (!setKeepalivesWin32(conn))
2551  err = 1;
2552 #endif /* SIO_KEEPALIVE_VALS */
2553 #endif /* WIN32 */
2554  else if (!setTCPUserTimeout(conn))
2555  err = 1;
2556 
2557  if (err)
2558  {
2559  conn->try_next_addr = true;
2560  goto keep_going;
2561  }
2562  }
2563 
2564  /*----------
2565  * We have three methods of blocking SIGPIPE during
2566  * send() calls to this socket:
2567  *
2568  * - setsockopt(sock, SO_NOSIGPIPE)
2569  * - send(sock, ..., MSG_NOSIGNAL)
2570  * - setting the signal mask to SIG_IGN during send()
2571  *
2572  * The third method requires three syscalls per send,
2573  * so we prefer either of the first two, but they are
2574  * less portable. The state is tracked in the following
2575  * members of PGconn:
2576  *
2577  * conn->sigpipe_so - we have set up SO_NOSIGPIPE
2578  * conn->sigpipe_flag - we're specifying MSG_NOSIGNAL
2579  *
2580  * If we can use SO_NOSIGPIPE, then set sigpipe_so here
2581  * and we're done. Otherwise, set sigpipe_flag so that
2582  * we will try MSG_NOSIGNAL on sends. If we get an error
2583  * with MSG_NOSIGNAL, we'll clear that flag and revert to
2584  * signal masking.
2585  *----------
2586  */
2587  conn->sigpipe_so = false;
2588 #ifdef MSG_NOSIGNAL
2589  conn->sigpipe_flag = true;
2590 #else
2591  conn->sigpipe_flag = false;
2592 #endif /* MSG_NOSIGNAL */
2593 
2594 #ifdef SO_NOSIGPIPE
2595  optval = 1;
2596  if (setsockopt(conn->sock, SOL_SOCKET, SO_NOSIGPIPE,
2597  (char *) &optval, sizeof(optval)) == 0)
2598  {
2599  conn->sigpipe_so = true;
2600  conn->sigpipe_flag = false;
2601  }
2602 #endif /* SO_NOSIGPIPE */
2603 
2604  /*
2605  * Start/make connection. This should not block, since we
2606  * are in nonblock mode. If it does, well, too bad.
2607  */
2608  if (connect(conn->sock, addr_cur->ai_addr,
2609  addr_cur->ai_addrlen) < 0)
2610  {
2611  if (SOCK_ERRNO == EINPROGRESS ||
2612 #ifdef WIN32
2613  SOCK_ERRNO == EWOULDBLOCK ||
2614 #endif
2615  SOCK_ERRNO == EINTR)
2616  {
2617  /*
2618  * This is fine - we're in non-blocking mode, and
2619  * the connection is in progress. Tell caller to
2620  * wait for write-ready on socket.
2621  */
2622  conn->status = CONNECTION_STARTED;
2623  return PGRES_POLLING_WRITING;
2624  }
2625  /* otherwise, trouble */
2626  }
2627  else
2628  {
2629  /*
2630  * Hm, we're connected already --- seems the "nonblock
2631  * connection" wasn't. Advance the state machine and
2632  * go do the next stuff.
2633  */
2634  conn->status = CONNECTION_STARTED;
2635  goto keep_going;
2636  }
2637 
2638  /*
2639  * This connection failed. Add the error report to
2640  * conn->errorMessage, then try the next address if any.
2641  */
2643  conn->try_next_addr = true;
2644  goto keep_going;
2645  }
2646  }
2647 
2648  case CONNECTION_STARTED:
2649  {
2650  ACCEPT_TYPE_ARG3 optlen = sizeof(optval);
2651 
2652  /*
2653  * Write ready, since we've made it here, so the connection
2654  * has been made ... or has failed.
2655  */
2656 
2657  /*
2658  * Now check (using getsockopt) that there is not an error
2659  * state waiting for us on the socket.
2660  */
2661 
2662  if (getsockopt(conn->sock, SOL_SOCKET, SO_ERROR,
2663  (char *) &optval, &optlen) == -1)
2664  {
2666  libpq_gettext("could not get socket error status: %s\n"),
2667  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2668  goto error_return;
2669  }
2670  else if (optval != 0)
2671  {
2672  /*
2673  * When using a nonblocking connect, we will typically see
2674  * connect failures at this point, so provide a friendly
2675  * error message.
2676  */
2677  connectFailureMessage(conn, optval);
2678 
2679  /*
2680  * Try the next address if any, just as in the case where
2681  * connect() returned failure immediately.
2682  */
2683  conn->try_next_addr = true;
2684  goto keep_going;
2685  }
2686 
2687  /* Fill in the client address */
2688  conn->laddr.salen = sizeof(conn->laddr.addr);
2689  if (getsockname(conn->sock,
2690  (struct sockaddr *) &conn->laddr.addr,
2691  &conn->laddr.salen) < 0)
2692  {
2694  libpq_gettext("could not get client address from socket: %s\n"),
2695  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2696  goto error_return;
2697  }
2698 
2699  /*
2700  * Make sure we can write before advancing to next step.
2701  */
2702  conn->status = CONNECTION_MADE;
2703  return PGRES_POLLING_WRITING;
2704  }
2705 
2706  case CONNECTION_MADE:
2707  {
2708  char *startpacket;
2709  int packetlen;
2710 
2711 #ifdef HAVE_UNIX_SOCKETS
2712 
2713  /*
2714  * Implement requirepeer check, if requested and it's a
2715  * Unix-domain socket.
2716  */
2717  if (conn->requirepeer && conn->requirepeer[0] &&
2718  IS_AF_UNIX(conn->raddr.addr.ss_family))
2719  {
2720  char pwdbuf[BUFSIZ];
2721  struct passwd pass_buf;
2722  struct passwd *pass;
2723  int passerr;
2724  uid_t uid;
2725  gid_t gid;
2726 
2727  errno = 0;
2728  if (getpeereid(conn->sock, &uid, &gid) != 0)
2729  {
2730  /*
2731  * Provide special error message if getpeereid is a
2732  * stub
2733  */
2734  if (errno == ENOSYS)
2736  libpq_gettext("requirepeer parameter is not supported on this platform\n"));
2737  else
2739  libpq_gettext("could not get peer credentials: %s\n"),
2740  strerror_r(errno, sebuf, sizeof(sebuf)));
2741  goto error_return;
2742  }
2743 
2744  passerr = pqGetpwuid(uid, &pass_buf, pwdbuf, sizeof(pwdbuf), &pass);
2745  if (pass == NULL)
2746  {
2747  if (passerr != 0)
2749  libpq_gettext("could not look up local user ID %d: %s\n"),
2750  (int) uid,
2751  strerror_r(passerr, sebuf, sizeof(sebuf)));
2752  else
2754  libpq_gettext("local user with ID %d does not exist\n"),
2755  (int) uid);
2756  goto error_return;
2757  }
2758 
2759  if (strcmp(pass->pw_name, conn->requirepeer) != 0)
2760  {
2762  libpq_gettext("requirepeer specifies \"%s\", but actual peer user name is \"%s\"\n"),
2763  conn->requirepeer, pass->pw_name);
2764  goto error_return;
2765  }
2766  }
2767 #endif /* HAVE_UNIX_SOCKETS */
2768 
2769  if (IS_AF_UNIX(conn->raddr.addr.ss_family))
2770  {
2771  /* Don't request SSL or GSSAPI over Unix sockets */
2772 #ifdef USE_SSL
2773  conn->allow_ssl_try = false;
2774 #endif
2775 #ifdef ENABLE_GSS
2776  conn->try_gss = false;
2777 #endif
2778  }
2779 
2780 #ifdef ENABLE_GSS
2781 
2782  /*
2783  * If GSSAPI is enabled and we have a credential cache, try to
2784  * set it up before sending startup messages. If it's already
2785  * operating, don't try SSL and instead just build the startup
2786  * packet.
2787  */
2788  if (conn->try_gss && !conn->gctx)
2789  conn->try_gss = pg_GSS_have_cred_cache(&conn->gcred);
2790  if (conn->try_gss && !conn->gctx)
2791  {
2793 
2794  if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
2795  {
2797  libpq_gettext("could not send GSSAPI negotiation packet: %s\n"),
2798  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2799  goto error_return;
2800  }
2801 
2802  /* Ok, wait for response */
2804  return PGRES_POLLING_READING;
2805  }
2806  else if (!conn->gctx && conn->gssencmode[0] == 'r')
2807  {
2809  libpq_gettext("GSSAPI encryption required but was impossible (possibly no credential cache, no server support, or using a local socket)\n"));
2810  goto error_return;
2811  }
2812 #endif
2813 
2814 #ifdef USE_SSL
2815 
2816  /*
2817  * If SSL is enabled and we haven't already got it running,
2818  * request it instead of sending the startup message.
2819  */
2820  if (conn->allow_ssl_try && !conn->wait_ssl_try &&
2821  !conn->ssl_in_use)
2822  {
2823  ProtocolVersion pv;
2824 
2825  /*
2826  * Send the SSL request packet.
2827  *
2828  * Theoretically, this could block, but it really
2829  * shouldn't since we only got here if the socket is
2830  * write-ready.
2831  */
2833  if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
2834  {
2836  libpq_gettext("could not send SSL negotiation packet: %s\n"),
2837  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2838  goto error_return;
2839  }
2840  /* Ok, wait for response */
2842  return PGRES_POLLING_READING;
2843  }
2844 #endif /* USE_SSL */
2845 
2846  /*
2847  * Build the startup packet.
2848  */
2849  if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
2850  startpacket = pqBuildStartupPacket3(conn, &packetlen,
2852  else
2853  startpacket = pqBuildStartupPacket2(conn, &packetlen,
2855  if (!startpacket)
2856  {
2857  /*
2858  * will not appendbuffer here, since it's likely to also
2859  * run out of memory
2860  */
2862  libpq_gettext("out of memory\n"));
2863  goto error_return;
2864  }
2865 
2866  /*
2867  * Send the startup packet.
2868  *
2869  * Theoretically, this could block, but it really shouldn't
2870  * since we only got here if the socket is write-ready.
2871  */
2872  if (pqPacketSend(conn, 0, startpacket, packetlen) != STATUS_OK)
2873  {
2875  libpq_gettext("could not send startup packet: %s\n"),
2876  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2877  free(startpacket);
2878  goto error_return;
2879  }
2880 
2881  free(startpacket);
2882 
2884  return PGRES_POLLING_READING;
2885  }
2886 
2887  /*
2888  * Handle SSL negotiation: wait for postmaster messages and
2889  * respond as necessary.
2890  */
2892  {
2893 #ifdef USE_SSL
2894  PostgresPollingStatusType pollres;
2895 
2896  /*
2897  * On first time through, get the postmaster's response to our
2898  * SSL negotiation packet.
2899  */
2900  if (!conn->ssl_in_use)
2901  {
2902  /*
2903  * We use pqReadData here since it has the logic to
2904  * distinguish no-data-yet from connection closure. Since
2905  * conn->ssl isn't set, a plain recv() will occur.
2906  */
2907  char SSLok;
2908  int rdresult;
2909 
2910  rdresult = pqReadData(conn);
2911  if (rdresult < 0)
2912  {
2913  /* errorMessage is already filled in */
2914  goto error_return;
2915  }
2916  if (rdresult == 0)
2917  {
2918  /* caller failed to wait for data */
2919  return PGRES_POLLING_READING;
2920  }
2921  if (pqGetc(&SSLok, conn) < 0)
2922  {
2923  /* should not happen really */
2924  return PGRES_POLLING_READING;
2925  }
2926  if (SSLok == 'S')
2927  {
2928  /* mark byte consumed */
2929  conn->inStart = conn->inCursor;
2930  /* Set up global SSL state if required */
2931  if (pqsecure_initialize(conn) != 0)
2932  goto error_return;
2933  }
2934  else if (SSLok == 'N')
2935  {
2936  /* mark byte consumed */
2937  conn->inStart = conn->inCursor;
2938  /* OK to do without SSL? */
2939  if (conn->sslmode[0] == 'r' || /* "require" */
2940  conn->sslmode[0] == 'v') /* "verify-ca" or
2941  * "verify-full" */
2942  {
2943  /* Require SSL, but server does not want it */
2945  libpq_gettext("server does not support SSL, but SSL was required\n"));
2946  goto error_return;
2947  }
2948  /* Otherwise, proceed with normal startup */
2949  conn->allow_ssl_try = false;
2950  conn->status = CONNECTION_MADE;
2951  return PGRES_POLLING_WRITING;
2952  }
2953  else if (SSLok == 'E')
2954  {
2955  /*
2956  * Server failure of some sort, such as failure to
2957  * fork a backend process. We need to process and
2958  * report the error message, which might be formatted
2959  * according to either protocol 2 or protocol 3.
2960  * Rather than duplicate the code for that, we flip
2961  * into AWAITING_RESPONSE state and let the code there
2962  * deal with it. Note we have *not* consumed the "E"
2963  * byte here.
2964  */
2966  goto keep_going;
2967  }
2968  else
2969  {
2971  libpq_gettext("received invalid response to SSL negotiation: %c\n"),
2972  SSLok);
2973  goto error_return;
2974  }
2975  }
2976 
2977  /*
2978  * Begin or continue the SSL negotiation process.
2979  */
2980  pollres = pqsecure_open_client(conn);
2981  if (pollres == PGRES_POLLING_OK)
2982  {
2983  /* SSL handshake done, ready to send startup packet */
2984  conn->status = CONNECTION_MADE;
2985  return PGRES_POLLING_WRITING;
2986  }
2987  if (pollres == PGRES_POLLING_FAILED)
2988  {
2989  /*
2990  * Failed ... if sslmode is "prefer" then do a non-SSL
2991  * retry
2992  */
2993  if (conn->sslmode[0] == 'p' /* "prefer" */
2994  && conn->allow_ssl_try /* redundant? */
2995  && !conn->wait_ssl_try) /* redundant? */
2996  {
2997  /* only retry once */
2998  conn->allow_ssl_try = false;
2999  need_new_connection = true;
3000  goto keep_going;
3001  }
3002  /* Else it's a hard failure */
3003  goto error_return;
3004  }
3005  /* Else, return POLLING_READING or POLLING_WRITING status */
3006  return pollres;
3007 #else /* !USE_SSL */
3008  /* can't get here */
3009  goto error_return;
3010 #endif /* USE_SSL */
3011  }
3012 
3014  {
3015 #ifdef ENABLE_GSS
3016  PostgresPollingStatusType pollres;
3017 
3018  /*
3019  * If we haven't yet, get the postmaster's response to our
3020  * negotiation packet
3021  */
3022  if (conn->try_gss && !conn->gctx)
3023  {
3024  char gss_ok;
3025  int rdresult = pqReadData(conn);
3026 
3027  if (rdresult < 0)
3028  /* pqReadData fills in error message */
3029  goto error_return;
3030  else if (rdresult == 0)
3031  /* caller failed to wait for data */
3032  return PGRES_POLLING_READING;
3033  if (pqGetc(&gss_ok, conn) < 0)
3034  /* shouldn't happen... */
3035  return PGRES_POLLING_READING;
3036 
3037  if (gss_ok == 'E')
3038  {
3039  /*
3040  * Server failure of some sort. Assume it's a
3041  * protocol version support failure, and let's see if
3042  * we can't recover (if it's not, we'll get a better
3043  * error message on retry). Server gets fussy if we
3044  * don't hang up the socket, though.
3045  */
3046  conn->try_gss = false;
3047  pqDropConnection(conn, true);
3048  conn->status = CONNECTION_NEEDED;
3049  goto keep_going;
3050  }
3051 
3052  /* mark byte consumed */
3053  conn->inStart = conn->inCursor;
3054 
3055  if (gss_ok == 'N')
3056  {
3057  /* Server doesn't want GSSAPI; fall back if we can */
3058  if (conn->gssencmode[0] == 'r')
3059  {
3061  libpq_gettext("server doesn't support GSSAPI encryption, but it was required\n"));
3062  goto error_return;
3063  }
3064 
3065  conn->try_gss = false;
3066  conn->status = CONNECTION_MADE;
3067  return PGRES_POLLING_WRITING;
3068  }
3069  else if (gss_ok != 'G')
3070  {
3072  libpq_gettext("received invalid response to GSSAPI negotiation: %c\n"),
3073  gss_ok);
3074  goto error_return;
3075  }
3076  }
3077 
3078  /* Begin or continue GSSAPI negotiation */
3079  pollres = pqsecure_open_gss(conn);
3080  if (pollres == PGRES_POLLING_OK)
3081  {
3082  /* All set for startup packet */
3083  conn->status = CONNECTION_MADE;
3084  return PGRES_POLLING_WRITING;
3085  }
3086  else if (pollres == PGRES_POLLING_FAILED &&
3087  conn->gssencmode[0] == 'p')
3088  {
3089  /*
3090  * We failed, but we can retry on "prefer". Have to drop
3091  * the current connection to do so, though.
3092  */
3093  conn->try_gss = false;
3094  pqDropConnection(conn, true);
3095  conn->status = CONNECTION_NEEDED;
3096  goto keep_going;
3097  }
3098  return pollres;
3099 #else /* !ENABLE_GSS */
3100  /* unreachable */
3101  goto error_return;
3102 #endif /* ENABLE_GSS */
3103  }
3104 
3105  /*
3106  * Handle authentication exchange: wait for postmaster messages
3107  * and respond as necessary.
3108  */
3110  {
3111  char beresp;
3112  int msgLength;
3113  int avail;
3114  AuthRequest areq;
3115  int res;
3116 
3117  /*
3118  * Scan the message from current point (note that if we find
3119  * the message is incomplete, we will return without advancing
3120  * inStart, and resume here next time).
3121  */
3122  conn->inCursor = conn->inStart;
3123 
3124  /* Read type byte */
3125  if (pqGetc(&beresp, conn))
3126  {
3127  /* We'll come back when there is more data */
3128  return PGRES_POLLING_READING;
3129  }
3130 
3131  /*
3132  * Validate message type: we expect only an authentication
3133  * request or an error here. Anything else probably means
3134  * it's not Postgres on the other end at all.
3135  */
3136  if (!(beresp == 'R' || beresp == 'E'))
3137  {
3139  libpq_gettext(
3140  "expected authentication request from "
3141  "server, but received %c\n"),
3142  beresp);
3143  goto error_return;
3144  }
3145 
3146  if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
3147  {
3148  /* Read message length word */
3149  if (pqGetInt(&msgLength, 4, conn))
3150  {
3151  /* We'll come back when there is more data */
3152  return PGRES_POLLING_READING;
3153  }
3154  }
3155  else
3156  {
3157  /* Set phony message length to disable checks below */
3158  msgLength = 8;
3159  }
3160 
3161  /*
3162  * Try to validate message length before using it.
3163  * Authentication requests can't be very large, although GSS
3164  * auth requests may not be that small. Errors can be a
3165  * little larger, but not huge. If we see a large apparent
3166  * length in an error, it means we're really talking to a
3167  * pre-3.0-protocol server; cope.
3168  */
3169  if (beresp == 'R' && (msgLength < 8 || msgLength > 2000))
3170  {
3172  libpq_gettext(
3173  "expected authentication request from "
3174  "server, but received %c\n"),
3175  beresp);
3176  goto error_return;
3177  }
3178 
3179  if (beresp == 'E' && (msgLength < 8 || msgLength > 30000))
3180  {
3181  /* Handle error from a pre-3.0 server */
3182  conn->inCursor = conn->inStart + 1; /* reread data */
3183  if (pqGets_append(&conn->errorMessage, conn))
3184  {
3185  /* We'll come back when there is more data */
3186  return PGRES_POLLING_READING;
3187  }
3188  /* OK, we read the message; mark data consumed */
3189  conn->inStart = conn->inCursor;
3190 
3191  /*
3192  * The postmaster typically won't end its message with a
3193  * newline, so add one to conform to libpq conventions.
3194  */
3195  appendPQExpBufferChar(&conn->errorMessage, '\n');
3196 
3197  /*
3198  * If we tried to open the connection in 3.0 protocol,
3199  * fall back to 2.0 protocol.
3200  */
3201  if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
3202  {
3203  conn->pversion = PG_PROTOCOL(2, 0);
3204  need_new_connection = true;
3205  goto keep_going;
3206  }
3207 
3208  goto error_return;
3209  }
3210 
3211  /*
3212  * Can't process if message body isn't all here yet.
3213  *
3214  * (In protocol 2.0 case, we are assuming messages carry at
3215  * least 4 bytes of data.)
3216  */
3217  msgLength -= 4;
3218  avail = conn->inEnd - conn->inCursor;
3219  if (avail < msgLength)
3220  {
3221  /*
3222  * Before returning, try to enlarge the input buffer if
3223  * needed to hold the whole message; see notes in
3224  * pqParseInput3.
3225  */
3226  if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
3227  conn))
3228  goto error_return;
3229  /* We'll come back when there is more data */
3230  return PGRES_POLLING_READING;
3231  }
3232 
3233  /* Handle errors. */
3234  if (beresp == 'E')
3235  {
3236  if (PG_PROTOCOL_MAJOR(conn->pversion) >= 3)
3237  {
3238  if (pqGetErrorNotice3(conn, true))
3239  {
3240  /* We'll come back when there is more data */
3241  return PGRES_POLLING_READING;
3242  }
3243  }
3244  else
3245  {
3246  if (pqGets_append(&conn->errorMessage, conn))
3247  {
3248  /* We'll come back when there is more data */
3249  return PGRES_POLLING_READING;
3250  }
3251  }
3252  /* OK, we read the message; mark data consumed */
3253  conn->inStart = conn->inCursor;
3254 
3255  /* Check to see if we should mention pgpassfile */
3256  pgpassfileWarning(conn);
3257 
3258 #ifdef ENABLE_GSS
3259 
3260  /*
3261  * If gssencmode is "prefer" and we're using GSSAPI, retry
3262  * without it.
3263  */
3264  if (conn->gssenc && conn->gssencmode[0] == 'p')
3265  {
3266  OM_uint32 minor;
3267 
3268  /* postmaster expects us to drop the connection */
3269  conn->try_gss = false;
3270  conn->gssenc = false;
3271  gss_delete_sec_context(&minor, &conn->gctx, NULL);
3272  pqDropConnection(conn, true);
3273  conn->status = CONNECTION_NEEDED;
3274  goto keep_going;
3275  }
3276 #endif
3277 
3278 #ifdef USE_SSL
3279 
3280  /*
3281  * if sslmode is "allow" and we haven't tried an SSL
3282  * connection already, then retry with an SSL connection
3283  */
3284  if (conn->sslmode[0] == 'a' /* "allow" */
3285  && !conn->ssl_in_use
3286  && conn->allow_ssl_try
3287  && conn->wait_ssl_try)
3288  {
3289  /* only retry once */
3290  conn->wait_ssl_try = false;
3291  need_new_connection = true;
3292  goto keep_going;
3293  }
3294 
3295  /*
3296  * if sslmode is "prefer" and we're in an SSL connection,
3297  * then do a non-SSL retry
3298  */
3299  if (conn->sslmode[0] == 'p' /* "prefer" */
3300  && conn->ssl_in_use
3301  && conn->allow_ssl_try /* redundant? */
3302  && !conn->wait_ssl_try) /* redundant? */
3303  {
3304  /* only retry once */
3305  conn->allow_ssl_try = false;
3306  need_new_connection = true;
3307  goto keep_going;
3308  }
3309 #endif
3310 
3311  goto error_return;
3312  }
3313 
3314  /* It is an authentication request. */
3315  conn->auth_req_received = true;
3316 
3317  /* Get the type of request. */
3318  if (pqGetInt((int *) &areq, 4, conn))
3319  {
3320  /* We'll come back when there are more data */
3321  return PGRES_POLLING_READING;
3322  }
3323  msgLength -= 4;
3324 
3325  /*
3326  * Ensure the password salt is in the input buffer, if it's an
3327  * MD5 request. All the other authentication methods that
3328  * contain extra data in the authentication request are only
3329  * supported in protocol version 3, in which case we already
3330  * read the whole message above.
3331  */
3332  if (areq == AUTH_REQ_MD5 && PG_PROTOCOL_MAJOR(conn->pversion) < 3)
3333  {
3334  msgLength += 4;
3335 
3336  avail = conn->inEnd - conn->inCursor;
3337  if (avail < 4)
3338  {
3339  /*
3340  * Before returning, try to enlarge the input buffer
3341  * if needed to hold the whole message; see notes in
3342  * pqParseInput3.
3343  */
3344  if (pqCheckInBufferSpace(conn->inCursor + (size_t) 4,
3345  conn))
3346  goto error_return;
3347  /* We'll come back when there is more data */
3348  return PGRES_POLLING_READING;
3349  }
3350  }
3351 
3352  /*
3353  * Process the rest of the authentication request message, and
3354  * respond to it if necessary.
3355  *
3356  * Note that conn->pghost must be non-NULL if we are going to
3357  * avoid the Kerberos code doing a hostname look-up.
3358  */
3359  res = pg_fe_sendauth(areq, msgLength, conn);
3360  conn->errorMessage.len = strlen(conn->errorMessage.data);
3361 
3362  /* OK, we have processed the message; mark data consumed */
3363  conn->inStart = conn->inCursor;
3364 
3365  if (res != STATUS_OK)
3366  goto error_return;
3367 
3368  /*
3369  * Just make sure that any data sent by pg_fe_sendauth is
3370  * flushed out. Although this theoretically could block, it
3371  * really shouldn't since we don't send large auth responses.
3372  */
3373  if (pqFlush(conn))
3374  goto error_return;
3375 
3376  if (areq == AUTH_REQ_OK)
3377  {
3378  /* We are done with authentication exchange */
3379  conn->status = CONNECTION_AUTH_OK;
3380 
3381  /*
3382  * Set asyncStatus so that PQgetResult will think that
3383  * what comes back next is the result of a query. See
3384  * below.
3385  */
3386  conn->asyncStatus = PGASYNC_BUSY;
3387  }
3388 
3389  /* Look to see if we have more data yet. */
3390  goto keep_going;
3391  }
3392 
3393  case CONNECTION_AUTH_OK:
3394  {
3395  /*
3396  * Now we expect to hear from the backend. A ReadyForQuery
3397  * message indicates that startup is successful, but we might
3398  * also get an Error message indicating failure. (Notice
3399  * messages indicating nonfatal warnings are also allowed by
3400  * the protocol, as are ParameterStatus and BackendKeyData
3401  * messages.) Easiest way to handle this is to let
3402  * PQgetResult() read the messages. We just have to fake it
3403  * out about the state of the connection, by setting
3404  * asyncStatus = PGASYNC_BUSY (done above).
3405  */
3406 
3407  if (PQisBusy(conn))
3408  return PGRES_POLLING_READING;
3409 
3410  res = PQgetResult(conn);
3411 
3412  /*
3413  * NULL return indicating we have gone to IDLE state is
3414  * expected
3415  */
3416  if (res)
3417  {
3418  if (res->resultStatus != PGRES_FATAL_ERROR)
3420  libpq_gettext("unexpected message from server during startup\n"));
3421  else if (conn->send_appname &&
3422  (conn->appname || conn->fbappname))
3423  {
3424  /*
3425  * If we tried to send application_name, check to see
3426  * if the error is about that --- pre-9.0 servers will
3427  * reject it at this stage of the process. If so,
3428  * close the connection and retry without sending
3429  * application_name. We could possibly get a false
3430  * SQLSTATE match here and retry uselessly, but there
3431  * seems no great harm in that; we'll just get the
3432  * same error again if it's unrelated.
3433  */
3434  const char *sqlstate;
3435 
3436  sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
3437  if (sqlstate &&
3438  strcmp(sqlstate, ERRCODE_APPNAME_UNKNOWN) == 0)
3439  {
3440  PQclear(res);
3441  conn->send_appname = false;
3442  need_new_connection = true;
3443  goto keep_going;
3444  }
3445  }
3446 
3447  /*
3448  * if the resultStatus is FATAL, then conn->errorMessage
3449  * already has a copy of the error; needn't copy it back.
3450  * But add a newline if it's not there already, since
3451  * postmaster error messages may not have one.
3452  */
3453  if (conn->errorMessage.len <= 0 ||
3454  conn->errorMessage.data[conn->errorMessage.len - 1] != '\n')
3455  appendPQExpBufferChar(&conn->errorMessage, '\n');
3456  PQclear(res);
3457  goto error_return;
3458  }
3459 
3460  /* Fire up post-connection housekeeping if needed */
3461  if (PG_PROTOCOL_MAJOR(conn->pversion) < 3)
3462  {
3463  conn->status = CONNECTION_SETENV;
3465  conn->next_eo = EnvironmentOptions;
3466  return PGRES_POLLING_WRITING;
3467  }
3468 
3469  /* Almost there now ... */
3471  goto keep_going;
3472  }
3473 
3475  {
3476  /*
3477  * If a read-write connection is required, see if we have one.
3478  *
3479  * Servers before 7.4 lack the transaction_read_only GUC, but
3480  * by the same token they don't have any read-only mode, so we
3481  * may just skip the test in that case.
3482  */
3483  if (conn->sversion >= 70400 &&
3484  conn->target_session_attrs != NULL &&
3485  strcmp(conn->target_session_attrs, "read-write") == 0)
3486  {
3487  /*
3488  * Save existing error messages across the PQsendQuery