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 "common/ip.h"
#include "common/link-canary.h"
#include "common/scram-common.h"
#include "common/string.h"
#include "fe-auth.h"
#include "libpq-fe.h"
#include "libpq-int.h"
#include "mb/pg_wchar.h"
#include "pg_config_paths.h"
#include "port/pg_bswap.h"
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.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 124 of file fe-connect.c.

◆ DefaultChannelBinding

#define DefaultChannelBinding   "disable"

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

Referenced by connectOptions2().

◆ DefaultGSSMode

#define DefaultGSSMode   "disable"

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

Referenced by connectOptions2().

◆ DefaultHost

#define DefaultHost   "localhost"

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

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

◆ DefaultOption

#define DefaultOption   ""

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

◆ DefaultSSLMode

#define DefaultSSLMode   "disable"

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

Referenced by connectOptions2().

◆ DefaultTargetSessionAttrs

#define DefaultTargetSessionAttrs   "any"

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

◆ DefaultTty

#define DefaultTty   ""

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

◆ ERRCODE_APPNAME_UNKNOWN

#define ERRCODE_APPNAME_UNKNOWN   "42704"

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

Referenced by PQconnectPoll().

◆ ERRCODE_CANNOT_CONNECT_NOW

#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"

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

Referenced by internal_ping(), and ProcessStartupPacket().

◆ ERRCODE_INVALID_PASSWORD

#define ERRCODE_INVALID_PASSWORD   "28P01"

Definition at line 94 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 4973 of file fe-connect.c.

Referenced by parseServiceFile().

◆ PGPASSFILE

#define PGPASSFILE   ".pgpass"

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

Referenced by connectOptions2().

Typedef Documentation

◆ internalPQconninfoOption

Function Documentation

◆ closePGconn()

static void closePGconn ( PGconn conn)
static

Definition at line 4098 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().

4099 {
4100  /*
4101  * If possible, send Terminate message to close the connection politely.
4102  */
4103  sendTerminateConn(conn);
4104 
4105  /*
4106  * Must reset the blocking status so a possible reconnect will work.
4107  *
4108  * Don't call PQsetnonblocking() because it will fail if it's unable to
4109  * flush the connection.
4110  */
4111  conn->nonblocking = false;
4112 
4113  /*
4114  * Close the connection, reset all transient state, flush I/O buffers.
4115  */
4116  pqDropConnection(conn, true);
4117  conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
4118  conn->asyncStatus = PGASYNC_IDLE;
4119  conn->xactStatus = PQTRANS_IDLE;
4120  pqClearAsyncResult(conn); /* deallocate result */
4122  release_conn_addrinfo(conn);
4123 
4124  /* Reset all state obtained from server, too */
4125  pqDropServerData(conn);
4126 }
static void release_conn_addrinfo(PGconn *conn)
Definition: fe-connect.c:4056
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:448
static void sendTerminateConn(PGconn *conn)
Definition: fe-connect.c:4071
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:387
static void pqDropServerData(PGconn *conn)
Definition: fe-connect.c:537
PQExpBufferData errorMessage
Definition: libpq-int.h:524
ConnStatusType status
Definition: libpq-int.h:386
bool nonblocking
Definition: libpq-int.h:393
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:749
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148
PGTransactionStatusType xactStatus
Definition: libpq-int.h:388

◆ connectDBComplete()

static int connectDBComplete ( PGconn conn)
static

Definition at line 2020 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().

2021 {
2023  time_t finish_time = ((time_t) -1);
2024  int timeout = 0;
2025  int last_whichhost = -2; /* certainly different from whichhost */
2026  struct addrinfo *last_addr_cur = NULL;
2027 
2028  if (conn == NULL || conn->status == CONNECTION_BAD)
2029  return 0;
2030 
2031  /*
2032  * Set up a time limit, if connect_timeout isn't zero.
2033  */
2034  if (conn->connect_timeout != NULL)
2035  {
2036  if (!parse_int_param(conn->connect_timeout, &timeout, conn,
2037  "connect_timeout"))
2038  {
2039  /* mark the connection as bad to report the parsing failure */
2040  conn->status = CONNECTION_BAD;
2041  return 0;
2042  }
2043 
2044  if (timeout > 0)
2045  {
2046  /*
2047  * Rounding could cause connection to fail unexpectedly quickly;
2048  * to prevent possibly waiting hardly-at-all, insist on at least
2049  * two seconds.
2050  */
2051  if (timeout < 2)
2052  timeout = 2;
2053  }
2054  else /* negative means 0 */
2055  timeout = 0;
2056  }
2057 
2058  for (;;)
2059  {
2060  int ret = 0;
2061 
2062  /*
2063  * (Re)start the connect_timeout timer if it's active and we are
2064  * considering a different host than we were last time through. If
2065  * we've already succeeded, though, needn't recalculate.
2066  */
2067  if (flag != PGRES_POLLING_OK &&
2068  timeout > 0 &&
2069  (conn->whichhost != last_whichhost ||
2070  conn->addr_cur != last_addr_cur))
2071  {
2072  finish_time = time(NULL) + timeout;
2073  last_whichhost = conn->whichhost;
2074  last_addr_cur = conn->addr_cur;
2075  }
2076 
2077  /*
2078  * Wait, if necessary. Note that the initial state (just after
2079  * PQconnectStart) is to wait for the socket to select for writing.
2080  */
2081  switch (flag)
2082  {
2083  case PGRES_POLLING_OK:
2084 
2085  /*
2086  * Reset stored error messages since we now have a working
2087  * connection
2088  */
2090  return 1; /* success! */
2091 
2092  case PGRES_POLLING_READING:
2093  ret = pqWaitTimed(1, 0, conn, finish_time);
2094  if (ret == -1)
2095  {
2096  /* hard failure, eg select() problem, aborts everything */
2097  conn->status = CONNECTION_BAD;
2098  return 0;
2099  }
2100  break;
2101 
2102  case PGRES_POLLING_WRITING:
2103  ret = pqWaitTimed(0, 1, conn, finish_time);
2104  if (ret == -1)
2105  {
2106  /* hard failure, eg select() problem, aborts everything */
2107  conn->status = CONNECTION_BAD;
2108  return 0;
2109  }
2110  break;
2111 
2112  default:
2113  /* Just in case we failed to set it in PQconnectPoll */
2114  conn->status = CONNECTION_BAD;
2115  return 0;
2116  }
2117 
2118  if (ret == 1) /* connect_timeout elapsed */
2119  {
2120  /*
2121  * Give up on current server/address, try the next one.
2122  */
2123  conn->try_next_addr = true;
2124  conn->status = CONNECTION_NEEDED;
2125  }
2126 
2127  /*
2128  * Now try to advance the state machine.
2129  */
2130  flag = PQconnectPoll(conn);
2131  }
2132 }
struct addrinfo * addr_cur
Definition: libpq-int.h:425
static bool parse_int_param(const char *value, int *result, PGconn *conn, const char *context)
Definition: fe-connect.c:1701
int pqWaitTimed(int forRead, int forWrite, PGconn *conn, time_t finish_time)
Definition: fe-misc.c:1033
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:2202
PQExpBufferData errorMessage
Definition: libpq-int.h:524
bool try_next_addr
Definition: libpq-int.h:422
ConnStatusType status
Definition: libpq-int.h:386
PostgresPollingStatusType
Definition: libpq-fe.h:74
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148
int whichhost
Definition: libpq-int.h:403

◆ connectDBStart()

static int connectDBStart ( PGconn conn)
static

Definition at line 1941 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().

1942 {
1943  if (!conn)
1944  return 0;
1945 
1946  if (!conn->options_valid)
1947  goto connect_errReturn;
1948 
1949  /*
1950  * Check for bad linking to backend-internal versions of src/common
1951  * functions (see comments in link-canary.c for the reason we need this).
1952  * Nobody but developers should see this message, so we don't bother
1953  * translating it.
1954  */
1956  {
1958  "libpq is incorrectly linked to backend functions\n");
1959  goto connect_errReturn;
1960  }
1961 
1962  /* Ensure our buffers are empty */
1963  conn->inStart = conn->inCursor = conn->inEnd = 0;
1964  conn->outCount = 0;
1965 
1966  /*
1967  * Ensure errorMessage is empty, too. PQconnectPoll will append messages
1968  * to it in the process of scanning for a working server. Thus, if we
1969  * fail to connect to multiple hosts, the final error message will include
1970  * details about each failure.
1971  */
1973 
1974 #ifdef ENABLE_GSS
1975  if (conn->gssencmode[0] == 'd') /* "disable" */
1976  conn->try_gss = false;
1977 #endif
1978 
1979  /*
1980  * Set up to try to connect to the first host. (Setting whichhost = -1 is
1981  * a bit of a cheat, but PQconnectPoll will advance it to 0 before
1982  * anything else looks at it.)
1983  */
1984  conn->whichhost = -1;
1985  conn->try_next_addr = false;
1986  conn->try_next_host = true;
1987  conn->status = CONNECTION_NEEDED;
1988 
1989  /*
1990  * The code for processing CONNECTION_NEEDED state is in PQconnectPoll(),
1991  * so that it can easily be re-executed if needed again during the
1992  * asynchronous startup process. However, we must run it once here,
1993  * because callers expect a success return from this routine to mean that
1994  * we are in PGRES_POLLING_WRITING connection state.
1995  */
1996  if (PQconnectPoll(conn) == PGRES_POLLING_WRITING)
1997  return 1;
1998 
1999 connect_errReturn:
2000 
2001  /*
2002  * If we managed to open a socket, close it immediately rather than
2003  * waiting till PQfinish. (The application cannot have gotten the socket
2004  * from PQsocket yet, so this doesn't risk breaking anything.)
2005  */
2006  pqDropConnection(conn, true);
2007  conn->status = CONNECTION_BAD;
2008  return 0;
2009 }
char * gssencmode
Definition: libpq-int.h:366
int inEnd
Definition: libpq-int.h:446
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
int inStart
Definition: libpq-int.h:444
int outCount
Definition: libpq-int.h:451
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:448
bool try_next_host
Definition: libpq-int.h:423
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
Definition: fe-connect.c:2202
PQExpBufferData errorMessage
Definition: libpq-int.h:524
bool try_next_addr
Definition: libpq-int.h:422
bool options_valid
Definition: libpq-int.h:392
ConnStatusType status
Definition: libpq-int.h:386
int inCursor
Definition: libpq-int.h:445
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148
int whichhost
Definition: libpq-int.h:403

◆ connectFailureMessage()

static void connectFailureMessage ( PGconn conn,
int  errorno 
)
static

Definition at line 1608 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().

1609 {
1610  char sebuf[PG_STRERROR_R_BUFLEN];
1611 
1612 #ifdef HAVE_UNIX_SOCKETS
1613  if (IS_AF_UNIX(conn->raddr.addr.ss_family))
1614  {
1615  char service[NI_MAXHOST];
1616 
1617  pg_getnameinfo_all(&conn->raddr.addr, conn->raddr.salen,
1618  NULL, 0,
1619  service, sizeof(service),
1620  NI_NUMERICSERV);
1622  libpq_gettext("could not connect to server: %s\n"
1623  "\tIs the server running locally and accepting\n"
1624  "\tconnections on Unix domain socket \"%s\"?\n"),
1625  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
1626  service);
1627  }
1628  else
1629 #endif /* HAVE_UNIX_SOCKETS */
1630  {
1631  char host_addr[NI_MAXHOST];
1632  const char *displayed_host;
1633  const char *displayed_port;
1634 
1635  /*
1636  * Optionally display the network address with the hostname. This is
1637  * useful to distinguish between IPv4 and IPv6 connections.
1638  */
1639  getHostaddr(conn, host_addr, NI_MAXHOST);
1640 
1641  /* To which host and port were we actually connecting? */
1642  if (conn->connhost[conn->whichhost].type == CHT_HOST_ADDRESS)
1643  displayed_host = conn->connhost[conn->whichhost].hostaddr;
1644  else
1645  displayed_host = conn->connhost[conn->whichhost].host;
1646  displayed_port = conn->connhost[conn->whichhost].port;
1647  if (displayed_port == NULL || displayed_port[0] == '\0')
1648  displayed_port = DEF_PGPORT_STR;
1649 
1650  /*
1651  * If the user did not supply an IP address using 'hostaddr', and
1652  * 'host' was missing or does not match our lookup, display the
1653  * looked-up IP address.
1654  */
1655  if (conn->connhost[conn->whichhost].type != CHT_HOST_ADDRESS &&
1656  strlen(host_addr) > 0 &&
1657  strcmp(displayed_host, host_addr) != 0)
1659  libpq_gettext("could not connect to server: %s\n"
1660  "\tIs the server running on host \"%s\" (%s) and accepting\n"
1661  "\tTCP/IP connections on port %s?\n"),
1662  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
1663  displayed_host, host_addr,
1664  displayed_port);
1665  else
1667  libpq_gettext("could not connect to server: %s\n"
1668  "\tIs the server running on host \"%s\" and accepting\n"
1669  "\tTCP/IP connections on port %s?\n"),
1670  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
1671  displayed_host,
1672  displayed_port);
1673  }
1674 }
#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:1576
#define SOCK_STRERROR
Definition: libpq-int.h:817
#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:404
ACCEPT_TYPE_ARG3 salen
Definition: pqcomm.h:65
SockAddr raddr
Definition: libpq-int.h:411
PQExpBufferData errorMessage
Definition: libpq-int.h:524
#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:403
#define libpq_gettext(x)
Definition: libpq-int.h:803

◆ connectNoDelay()

static int connectNoDelay ( PGconn conn)
static

Definition at line 1549 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().

1550 {
1551 #ifdef TCP_NODELAY
1552  int on = 1;
1553 
1554  if (setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY,
1555  (char *) &on,
1556  sizeof(on)) < 0)
1557  {
1558  char sebuf[PG_STRERROR_R_BUFLEN];
1559 
1561  libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
1562  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
1563  return 0;
1564  }
1565 #endif
1566 
1567  return 1;
1568 }
#define PG_STRERROR_R_BUFLEN
Definition: port.h:210
#define SOCK_STRERROR
Definition: libpq-int.h:817
#define SOCK_ERRNO
Definition: libpq-int.h:816
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
pgsocket sock
Definition: libpq-int.h:408
PQExpBufferData errorMessage
Definition: libpq-int.h:524
#define libpq_gettext(x)
Definition: libpq-int.h:803

◆ connectOptions1()

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

Definition at line 898 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().

899 {
900  PQconninfoOption *connOptions;
901 
902  /*
903  * Parse the conninfo string
904  */
905  connOptions = parse_connection_string(conninfo, &conn->errorMessage, true);
906  if (connOptions == NULL)
907  {
908  conn->status = CONNECTION_BAD;
909  /* errorMessage is already set */
910  return false;
911  }
912 
913  /*
914  * Move option values into conn structure
915  */
916  if (!fillPGconn(conn, connOptions))
917  {
918  conn->status = CONNECTION_BAD;
919  PQconninfoFree(connOptions);
920  return false;
921  }
922 
923  /*
924  * Free the option info - all is in conn now
925  */
926  PQconninfoFree(connOptions);
927 
928  return true;
929 }
static PQconninfoOption * parse_connection_string(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5295
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6463
PQExpBufferData errorMessage
Definition: libpq-int.h:524
static bool fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
Definition: fe-connect.c:856
ConnStatusType status
Definition: libpq-int.h:386

◆ connectOptions2()

static bool connectOptions2 ( PGconn conn)
static

Definition at line 996 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().

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

5692 {
5694  char *tmp;
5695 
5696  /*
5697  * If there's a service spec, use it to obtain any not-explicitly-given
5698  * parameters. Ignore error if no error message buffer is passed because
5699  * there is no way to pass back the failure message.
5700  */
5701  if (parseServiceInfo(options, errorMessage) != 0 && errorMessage)
5702  return false;
5703 
5704  /*
5705  * Get the fallback resources for parameters not specified in the conninfo
5706  * string nor the service.
5707  */
5708  for (option = options; option->keyword != NULL; option++)
5709  {
5710  if (option->val != NULL)
5711  continue; /* Value was in conninfo or service */
5712 
5713  /*
5714  * Try to get the environment variable fallback
5715  */
5716  if (option->envvar != NULL)
5717  {
5718  if ((tmp = getenv(option->envvar)) != NULL)
5719  {
5720  option->val = strdup(tmp);
5721  if (!option->val)
5722  {
5723  if (errorMessage)
5724  printfPQExpBuffer(errorMessage,
5725  libpq_gettext("out of memory\n"));
5726  return false;
5727  }
5728  continue;
5729  }
5730  }
5731 
5732  /*
5733  * Interpret the deprecated PGREQUIRESSL environment variable. Per
5734  * tradition, translate values starting with "1" to sslmode=require,
5735  * and ignore other values. Given both PGREQUIRESSL=1 and PGSSLMODE,
5736  * PGSSLMODE takes precedence; the opposite was true before v9.3.
5737  */
5738  if (strcmp(option->keyword, "sslmode") == 0)
5739  {
5740  const char *requiresslenv = getenv("PGREQUIRESSL");
5741 
5742  if (requiresslenv != NULL && requiresslenv[0] == '1')
5743  {
5744  option->val = strdup("require");
5745  if (!option->val)
5746  {
5747  if (errorMessage)
5748  printfPQExpBuffer(errorMessage,
5749  libpq_gettext("out of memory\n"));
5750  return false;
5751  }
5752  continue;
5753  }
5754  }
5755 
5756  /*
5757  * No environment variable specified or the variable isn't set - try
5758  * compiled-in default
5759  */
5760  if (option->compiled != NULL)
5761  {
5762  option->val = strdup(option->compiled);
5763  if (!option->val)
5764  {
5765  if (errorMessage)
5766  printfPQExpBuffer(errorMessage,
5767  libpq_gettext("out of memory\n"));
5768  return false;
5769  }
5770  continue;
5771  }
5772 
5773  /*
5774  * Special handling for "user" option. Note that if pg_fe_getauthname
5775  * fails, we just leave the value as NULL; there's no need for this to
5776  * be an error condition if the caller provides a user name. The only
5777  * reason we do this now at all is so that callers of PQconndefaults
5778  * will see a correct default (barring error, of course).
5779  */
5780  if (strcmp(option->keyword, "user") == 0)
5781  {
5782  option->val = pg_fe_getauthname(NULL);
5783  continue;
5784  }
5785  }
5786 
5787  return true;
5788 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
char * pg_fe_getauthname(PQExpBuffer errorMessage)
Definition: fe-auth.c:1073
static int parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:4986
#define libpq_gettext(x)
Definition: libpq-int.h:803

◆ 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 5527 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().

5530 {
5532  PQconninfoOption *dbname_options = NULL;
5534  int i = 0;
5535 
5536  /*
5537  * If expand_dbname is non-zero, check keyword "dbname" to see if val is
5538  * actually a recognized connection string.
5539  */
5540  while (expand_dbname && keywords[i])
5541  {
5542  const char *pname = keywords[i];
5543  const char *pvalue = values[i];
5544 
5545  /* first find "dbname" if any */
5546  if (strcmp(pname, "dbname") == 0 && pvalue)
5547  {
5548  /*
5549  * If value is a connection string, parse it, but do not use
5550  * defaults here -- those get picked up later. We only want to
5551  * override for those parameters actually passed.
5552  */
5553  if (recognized_connection_string(pvalue))
5554  {
5555  dbname_options = parse_connection_string(pvalue, errorMessage, false);
5556  if (dbname_options == NULL)
5557  return NULL;
5558  }
5559  break;
5560  }
5561  ++i;
5562  }
5563 
5564  /* Make a working copy of PQconninfoOptions */
5565  options = conninfo_init(errorMessage);
5566  if (options == NULL)
5567  {
5568  PQconninfoFree(dbname_options);
5569  return NULL;
5570  }
5571 
5572  /* Parse the keywords/values arrays */
5573  i = 0;
5574  while (keywords[i])
5575  {
5576  const char *pname = keywords[i];
5577  const char *pvalue = values[i];
5578 
5579  if (pvalue != NULL && pvalue[0] != '\0')
5580  {
5581  /* Search for the param record */
5582  for (option = options; option->keyword != NULL; option++)
5583  {
5584  if (strcmp(option->keyword, pname) == 0)
5585  break;
5586  }
5587 
5588  /* Check for invalid connection option */
5589  if (option->keyword == NULL)
5590  {
5591  printfPQExpBuffer(errorMessage,
5592  libpq_gettext("invalid connection option \"%s\"\n"),
5593  pname);
5594  PQconninfoFree(options);
5595  PQconninfoFree(dbname_options);
5596  return NULL;
5597  }
5598 
5599  /*
5600  * If we are on the first dbname parameter, and we have a parsed
5601  * connection string, copy those parameters across, overriding any
5602  * existing previous settings.
5603  */
5604  if (strcmp(pname, "dbname") == 0 && dbname_options)
5605  {
5606  PQconninfoOption *str_option;
5607 
5608  for (str_option = dbname_options; str_option->keyword != NULL; str_option++)
5609  {
5610  if (str_option->val != NULL)
5611  {
5612  int k;
5613 
5614  for (k = 0; options[k].keyword; k++)
5615  {
5616  if (strcmp(options[k].keyword, str_option->keyword) == 0)
5617  {
5618  if (options[k].val)
5619  free(options[k].val);
5620  options[k].val = strdup(str_option->val);
5621  if (!options[k].val)
5622  {
5623  printfPQExpBuffer(errorMessage,
5624  libpq_gettext("out of memory\n"));
5625  PQconninfoFree(options);
5626  PQconninfoFree(dbname_options);
5627  return NULL;
5628  }
5629  break;
5630  }
5631  }
5632  }
5633  }
5634 
5635  /*
5636  * Forget the parsed connection string, so that any subsequent
5637  * dbname parameters will not be expanded.
5638  */
5639  PQconninfoFree(dbname_options);
5640  dbname_options = NULL;
5641  }
5642  else
5643  {
5644  /*
5645  * Store the value, overriding previous settings
5646  */
5647  if (option->val)
5648  free(option->val);
5649  option->val = strdup(pvalue);
5650  if (!option->val)
5651  {
5652  printfPQExpBuffer(errorMessage,
5653  libpq_gettext("out of memory\n"));
5654  PQconninfoFree(options);
5655  PQconninfoFree(dbname_options);
5656  return NULL;
5657  }
5658  }
5659  }
5660  ++i;
5661  }
5662  PQconninfoFree(dbname_options);
5663 
5664  /*
5665  * Add in defaults if the caller wants that.
5666  */
5667  if (use_defaults)
5668  {
5669  if (!conninfo_add_defaults(options, errorMessage))
5670  {
5671  PQconninfoFree(options);
5672  return NULL;
5673  }
5674  }
5675 
5676  return options;
5677 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5255
static PQconninfoOption * parse_connection_string(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5295
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6463
static char ** options
static bool recognized_connection_string(const char *connstr)
Definition: fe-connect.c:5338
#define free(a)
Definition: header.h:65
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5691
static Datum values[MAXATTR]
Definition: bootstrap.c:167
int i
long val
Definition: informix.c:664
#define libpq_gettext(x)
Definition: libpq-int.h:803

◆ conninfo_find()

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

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

References _PQconninfoOption::keyword.

Referenced by conninfo_getval(), and conninfo_storeval().

6405 {
6407 
6408  for (option = connOptions; option->keyword != NULL; option++)
6409  {
6410  if (strcmp(option->keyword, keyword) == 0)
6411  return option;
6412  }
6413 
6414  return NULL;
6415 }

◆ conninfo_getval()

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

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

References conninfo_find(), and _PQconninfoOption::val.

Referenced by fillPGconn(), and parseServiceInfo().

6315 {
6317 
6318  option = conninfo_find(connOptions, keyword);
6319 
6320  return option ? option->val : NULL;
6321 }
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6404

◆ conninfo_init()

static PQconninfoOption * conninfo_init ( PQExpBuffer  errorMessage)
static

Definition at line 5255 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().

5256 {
5258  PQconninfoOption *opt_dest;
5259  const internalPQconninfoOption *cur_opt;
5260 
5261  /*
5262  * Get enough memory for all options in PQconninfoOptions, even if some
5263  * end up being filtered out.
5264  */
5265  options = (PQconninfoOption *) malloc(sizeof(PQconninfoOption) * sizeof(PQconninfoOptions) / sizeof(PQconninfoOptions[0]));
5266  if (options == NULL)
5267  {
5268  printfPQExpBuffer(errorMessage,
5269  libpq_gettext("out of memory\n"));
5270  return NULL;
5271  }
5272  opt_dest = options;
5273 
5274  for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++)
5275  {
5276  /* Only copy the public part of the struct, not the full internal */
5277  memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption));
5278  opt_dest++;
5279  }
5280  MemSet(opt_dest, 0, sizeof(PQconninfoOption));
5281 
5282  return options;
5283 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
#define MemSet(start, val, len)
Definition: c.h:962
#define malloc(a)
Definition: header.h:50
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:193
static char ** options
#define libpq_gettext(x)
Definition: libpq-int.h:803

◆ conninfo_parse()

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

Definition at line 5349 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().

5351 {
5352  char *pname;
5353  char *pval;
5354  char *buf;
5355  char *cp;
5356  char *cp2;
5358 
5359  /* Make a working copy of PQconninfoOptions */
5360  options = conninfo_init(errorMessage);
5361  if (options == NULL)
5362  return NULL;
5363 
5364  /* Need a modifiable copy of the input string */
5365  if ((buf = strdup(conninfo)) == NULL)
5366  {
5367  printfPQExpBuffer(errorMessage,
5368  libpq_gettext("out of memory\n"));
5369  PQconninfoFree(options);
5370  return NULL;
5371  }
5372  cp = buf;
5373 
5374  while (*cp)
5375  {
5376  /* Skip blanks before the parameter name */
5377  if (isspace((unsigned char) *cp))
5378  {
5379  cp++;
5380  continue;
5381  }
5382 
5383  /* Get the parameter name */
5384  pname = cp;
5385  while (*cp)
5386  {
5387  if (*cp == '=')
5388  break;
5389  if (isspace((unsigned char) *cp))
5390  {
5391  *cp++ = '\0';
5392  while (*cp)
5393  {
5394  if (!isspace((unsigned char) *cp))
5395  break;
5396  cp++;
5397  }
5398  break;
5399  }
5400  cp++;
5401  }
5402 
5403  /* Check that there is a following '=' */
5404  if (*cp != '=')
5405  {
5406  printfPQExpBuffer(errorMessage,
5407  libpq_gettext("missing \"=\" after \"%s\" in connection info string\n"),
5408  pname);
5409  PQconninfoFree(options);
5410  free(buf);
5411  return NULL;
5412  }
5413  *cp++ = '\0';
5414 
5415  /* Skip blanks after the '=' */
5416  while (*cp)
5417  {
5418  if (!isspace((unsigned char) *cp))
5419  break;
5420  cp++;
5421  }
5422 
5423  /* Get the parameter value */
5424  pval = cp;
5425 
5426  if (*cp != '\'')
5427  {
5428  cp2 = pval;
5429  while (*cp)
5430  {
5431  if (isspace((unsigned char) *cp))
5432  {
5433  *cp++ = '\0';
5434  break;
5435  }
5436  if (*cp == '\\')
5437  {
5438  cp++;
5439  if (*cp != '\0')
5440  *cp2++ = *cp++;
5441  }
5442  else
5443  *cp2++ = *cp++;
5444  }
5445  *cp2 = '\0';
5446  }
5447  else
5448  {
5449  cp2 = pval;
5450  cp++;
5451  for (;;)
5452  {
5453  if (*cp == '\0')
5454  {
5455  printfPQExpBuffer(errorMessage,
5456  libpq_gettext("unterminated quoted string in connection info string\n"));
5457  PQconninfoFree(options);
5458  free(buf);
5459  return NULL;
5460  }
5461  if (*cp == '\\')
5462  {
5463  cp++;
5464  if (*cp != '\0')
5465  *cp2++ = *cp++;
5466  continue;
5467  }
5468  if (*cp == '\'')
5469  {
5470  *cp2 = '\0';
5471  cp++;
5472  break;
5473  }
5474  *cp2++ = *cp++;
5475  }
5476  }
5477 
5478  /*
5479  * Now that we have the name and the value, store the record.
5480  */
5481  if (!conninfo_storeval(options, pname, pval, errorMessage, false, false))
5482  {
5483  PQconninfoFree(options);
5484  free(buf);
5485  return NULL;
5486  }
5487  }
5488 
5489  /* Done with the modifiable input string */
5490  free(buf);
5491 
5492  /*
5493  * Add in defaults if the caller wants that.
5494  */
5495  if (use_defaults)
5496  {
5497  if (!conninfo_add_defaults(options, errorMessage))
5498  {
5499  PQconninfoFree(options);
5500  return NULL;
5501  }
5502  }
5503 
5504  return options;
5505 }
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:6339
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5255
static char * buf
Definition: pg_test_fsync.c:67
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6463
static char ** options
#define free(a)
Definition: header.h:65
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5691
#define libpq_gettext(x)
Definition: libpq-int.h:803

◆ 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 6339 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().

6343 {
6345  char *value_copy;
6346 
6347  /*
6348  * For backwards compatibility, requiressl=1 gets translated to
6349  * sslmode=require, and requiressl=0 gets translated to sslmode=prefer
6350  * (which is the default for sslmode).
6351  */
6352  if (strcmp(keyword, "requiressl") == 0)
6353  {
6354  keyword = "sslmode";
6355  if (value[0] == '1')
6356  value = "require";
6357  else
6358  value = "prefer";
6359  }
6360 
6361  option = conninfo_find(connOptions, keyword);
6362  if (option == NULL)
6363  {
6364  if (!ignoreMissing)
6365  printfPQExpBuffer(errorMessage,
6366  libpq_gettext("invalid connection option \"%s\"\n"),
6367  keyword);
6368  return NULL;
6369  }
6370 
6371  if (uri_decode)
6372  {
6373  value_copy = conninfo_uri_decode(value, errorMessage);
6374  if (value_copy == NULL)
6375  /* conninfo_uri_decode already set an error message */
6376  return NULL;
6377  }
6378  else
6379  {
6380  value_copy = strdup(value);
6381  if (value_copy == NULL)
6382  {
6383  printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
6384  return NULL;
6385  }
6386  }
6387 
6388  if (option->val)
6389  free(option->val);
6390  option->val = value_copy;
6391 
6392  return option;
6393 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6404
static char * conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
Definition: fe-connect.c:6224
static struct @145 value
#define free(a)
Definition: header.h:65
#define libpq_gettext(x)
Definition: libpq-int.h:803

◆ conninfo_uri_decode()

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

Definition at line 6224 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().

6225 {
6226  char *buf;
6227  char *p;
6228  const char *q = str;
6229 
6230  buf = malloc(strlen(str) + 1);
6231  if (buf == NULL)
6232  {
6233  printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
6234  return NULL;
6235  }
6236  p = buf;
6237 
6238  for (;;)
6239  {
6240  if (*q != '%')
6241  {
6242  /* copy and check for NUL terminator */
6243  if (!(*(p++) = *(q++)))
6244  break;
6245  }
6246  else
6247  {
6248  int hi;
6249  int lo;
6250  int c;
6251 
6252  ++q; /* skip the percent sign itself */
6253 
6254  /*
6255  * Possible EOL will be caught by the first call to
6256  * get_hexdigit(), so we never dereference an invalid q pointer.
6257  */
6258  if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo)))
6259  {
6260  printfPQExpBuffer(errorMessage,
6261  libpq_gettext("invalid percent-encoded token: \"%s\"\n"),
6262  str);
6263  free(buf);
6264  return NULL;
6265  }
6266 
6267  c = (hi << 4) | lo;
6268  if (c == 0)
6269  {
6270  printfPQExpBuffer(errorMessage,
6271  libpq_gettext("forbidden value %%00 in percent-encoded value: \"%s\"\n"),
6272  str);
6273  free(buf);
6274  return NULL;
6275  }
6276  *(p++) = c;
6277  }
6278  }
6279 
6280  return buf;
6281 }
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:67
#define free(a)
Definition: header.h:65
static bool get_hexdigit(char digit, int *value)
Definition: fe-connect.c:6292
#define libpq_gettext(x)
Definition: libpq-int.h:803

◆ conninfo_uri_parse()

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

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

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

Referenced by parse_connection_string().

5798 {
5800 
5801  /* Make a working copy of PQconninfoOptions */
5802  options = conninfo_init(errorMessage);
5803  if (options == NULL)
5804  return NULL;
5805 
5806  if (!conninfo_uri_parse_options(options, uri, errorMessage))
5807  {
5808  PQconninfoFree(options);
5809  return NULL;
5810  }
5811 
5812  /*
5813  * Add in defaults if the caller wants that.
5814  */
5815  if (use_defaults)
5816  {
5817  if (!conninfo_add_defaults(options, errorMessage))
5818  {
5819  PQconninfoFree(options);
5820  return NULL;
5821  }
5822  }
5823 
5824  return options;
5825 }
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5255
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6463
static bool conninfo_uri_parse_options(PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage)
Definition: fe-connect.c:5849
static char ** options
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5691

◆ conninfo_uri_parse_options()

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

Definition at line 5849 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().

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

◆ conninfo_uri_parse_params()

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

Definition at line 6093 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().

6096 {
6097  while (*params)
6098  {
6099  char *keyword = params;
6100  char *value = NULL;
6101  char *p = params;
6102  bool malloced = false;
6103 
6104  /*
6105  * Scan the params string for '=' and '&', marking the end of keyword
6106  * and value respectively.
6107  */
6108  for (;;)
6109  {
6110  if (*p == '=')
6111  {
6112  /* Was there '=' already? */
6113  if (value != NULL)
6114  {
6115  printfPQExpBuffer(errorMessage,
6116  libpq_gettext("extra key/value separator \"=\" in URI query parameter: \"%s\"\n"),
6117  keyword);
6118  return false;
6119  }
6120  /* Cut off keyword, advance to value */
6121  *p++ = '\0';
6122  value = p;
6123  }
6124  else if (*p == '&' || *p == '\0')
6125  {
6126  /*
6127  * If not at the end, cut off value and advance; leave p
6128  * pointing to start of the next parameter, if any.
6129  */
6130  if (*p != '\0')
6131  *p++ = '\0';
6132  /* Was there '=' at all? */
6133  if (value == NULL)
6134  {
6135  printfPQExpBuffer(errorMessage,
6136  libpq_gettext("missing key/value separator \"=\" in URI query parameter: \"%s\"\n"),
6137  keyword);
6138  return false;
6139  }
6140  /* Got keyword and value, go process them. */
6141  break;
6142  }
6143  else
6144  ++p; /* Advance over all other bytes. */
6145  }
6146 
6147  keyword = conninfo_uri_decode(keyword, errorMessage);
6148  if (keyword == NULL)
6149  {
6150  /* conninfo_uri_decode already set an error message */
6151  return false;
6152  }
6153  value = conninfo_uri_decode(value, errorMessage);
6154  if (value == NULL)
6155  {
6156  /* conninfo_uri_decode already set an error message */
6157  free(keyword);
6158  return false;
6159  }
6160  malloced = true;
6161 
6162  /*
6163  * Special keyword handling for improved JDBC compatibility.
6164  */
6165  if (strcmp(keyword, "ssl") == 0 &&
6166  strcmp(value, "true") == 0)
6167  {
6168  free(keyword);
6169  free(value);
6170  malloced = false;
6171 
6172  keyword = "sslmode";
6173  value = "require";
6174  }
6175 
6176  /*
6177  * Store the value if the corresponding option exists; ignore
6178  * otherwise. At this point both keyword and value are not
6179  * URI-encoded.
6180  */
6181  if (!conninfo_storeval(connOptions, keyword, value,
6182  errorMessage, true, false))
6183  {
6184  /* Insert generic message if conninfo_storeval didn't give one. */
6185  if (errorMessage->len == 0)
6186  printfPQExpBuffer(errorMessage,
6187  libpq_gettext("invalid URI query parameter: \"%s\"\n"),
6188  keyword);
6189  /* And fail. */
6190  if (malloced)
6191  {
6192  free(keyword);
6193  free(value);
6194  }
6195  return false;
6196  }
6197 
6198  if (malloced)
6199  {
6200  free(keyword);
6201  free(value);
6202  }
6203 
6204  /* Proceed to next key=value pair, if any */
6205  params = p;
6206  }
6207 
6208  return true;
6209 }
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:6339
static char * conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
Definition: fe-connect.c:6224
static struct @145 value
#define free(a)
Definition: header.h:65
#define libpq_gettext(x)
Definition: libpq-int.h:803

◆ count_comma_separated_elems()

static int count_comma_separated_elems ( const char *  input)
static

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

Referenced by connectOptions2().

936 {
937  int n;
938 
939  n = 1;
940  for (; *input != '\0'; input++)
941  {
942  if (*input == ',')
943  n++;
944  }
945 
946  return n;
947 }

◆ default_threadlock()

static void default_threadlock ( int  acquire)
static

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

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

Referenced by PQregisterThreadLock().

7084 {
7085 #ifdef ENABLE_THREAD_SAFETY
7086 #ifndef WIN32
7087  static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
7088 #else
7089  static pthread_mutex_t singlethread_lock = NULL;
7090  static long mutex_initlock = 0;
7091 
7092  if (singlethread_lock == NULL)
7093  {
7094  while (InterlockedExchange(&mutex_initlock, 1) == 1)
7095  /* loop, another thread own the lock */ ;
7096  if (singlethread_lock == NULL)
7097  {
7098  if (pthread_mutex_init(&singlethread_lock, NULL))
7099  PGTHREAD_ERROR("failed to initialize mutex");
7100  }
7101  InterlockedExchange(&mutex_initlock, 0);
7102  }
7103 #endif
7104  if (acquire)
7105  {
7106  if (pthread_mutex_lock(&singlethread_lock))
7107  PGTHREAD_ERROR("failed to lock mutex");
7108  }
7109  else
7110  {
7111  if (pthread_mutex_unlock(&singlethread_lock))
7112  PGTHREAD_ERROR("failed to unlock mutex");
7113  }
7114 #endif
7115 }
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 6845 of file fe-connect.c.

References fprintf.

Referenced by makeEmptyPGconn().

6846 {
6847  (void) arg; /* not used */
6848  /* Note: we expect the supplied string to end with a newline already. */
6849  fprintf(stderr, "%s", message);
6850 }
#define fprintf
Definition: port.h:196
void * arg

◆ defaultNoticeReceiver()

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

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

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

Referenced by makeEmptyPGconn().

6831 {
6832  (void) arg; /* not used */
6833  if (res->noticeHooks.noticeProc != NULL)
6835  PQresultErrorMessage(res));
6836 }
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:2708
void * arg

◆ fillPGconn()

static bool fillPGconn ( PGconn conn,
PQconninfoOption connOptions 
)
static

Definition at line 856 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().

857 {
859 
860  for (option = PQconninfoOptions; option->keyword; option++)
861  {
862  if (option->connofs >= 0)
863  {
864  const char *tmp = conninfo_getval(connOptions, option->keyword);
865 
866  if (tmp)
867  {
868  char **connmember = (char **) ((char *) conn + option->connofs);
869 
870  if (*connmember)
871  free(*connmember);
872  *connmember = strdup(tmp);
873  if (*connmember == NULL)
874  {
876  libpq_gettext("out of memory\n"));
877  return false;
878  }
879  }
880  }
881  }
882 
883  return true;
884 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:193
PQExpBufferData errorMessage
Definition: libpq-int.h:524
#define free(a)
Definition: header.h:65
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6313
#define libpq_gettext(x)
Definition: libpq-int.h:803

◆ freePGconn()

static void freePGconn ( PGconn conn)
static

Definition at line 3908 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::gsslib, 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::krbsrvname, 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::sslpassword, pg_conn::sslrootcert, pg_conn::target_session_attrs, termPQExpBuffer(), pg_conn::workBuffer, and pg_conn::write_err_msg.

Referenced by makeEmptyPGconn(), and PQfinish().

3909 {
3910  int i;
3911 
3912  /* let any event procs clean up their state data */
3913  for (i = 0; i < conn->nEvents; i++)
3914  {
3915  PGEventConnDestroy evt;
3916 
3917  evt.conn = conn;
3918  (void) conn->events[i].proc(PGEVT_CONNDESTROY, &evt,
3919  conn->events[i].passThrough);
3920  free(conn->events[i].name);
3921  }
3922 
3923  /* clean up pg_conn_host structures */
3924  if (conn->connhost != NULL)
3925  {
3926  for (i = 0; i < conn->nconnhost; ++i)
3927  {
3928  if (conn->connhost[i].host != NULL)
3929  free(conn->connhost[i].host);
3930  if (conn->connhost[i].hostaddr != NULL)
3931  free(conn->connhost[i].hostaddr);
3932  if (conn->connhost[i].port != NULL)
3933  free(conn->connhost[i].port);
3934  if (conn->connhost[i].password != NULL)
3935  {
3936  explicit_bzero(conn->connhost[i].password, strlen(conn->connhost[i].password));
3937  free(conn->connhost[i].password);
3938  }
3939  }
3940  free(conn->connhost);
3941  }
3942 
3943  if (conn->client_encoding_initial)
3945  if (conn->events)
3946  free(conn->events);
3947  if (conn->pghost)
3948  free(conn->pghost);
3949  if (conn->pghostaddr)
3950  free(conn->pghostaddr);
3951  if (conn->pgport)
3952  free(conn->pgport);
3953  if (conn->pgtty)
3954  free(conn->pgtty);
3955  if (conn->connect_timeout)
3956  free(conn->connect_timeout);
3957  if (conn->pgtcp_user_timeout)
3958  free(conn->pgtcp_user_timeout);
3959  if (conn->pgoptions)
3960  free(conn->pgoptions);
3961  if (conn->appname)
3962  free(conn->appname);
3963  if (conn->fbappname)
3964  free(conn->fbappname);
3965  if (conn->dbName)
3966  free(conn->dbName);
3967  if (conn->replication)
3968  free(conn->replication);
3969  if (conn->pguser)
3970  free(conn->pguser);
3971  if (conn->pgpass)
3972  {
3973  explicit_bzero(conn->pgpass, strlen(conn->pgpass));
3974  free(conn->pgpass);
3975  }
3976  if (conn->pgpassfile)
3977  free(conn->pgpassfile);
3978  if (conn->channel_binding)
3979  free(conn->channel_binding);
3980  if (conn->keepalives)
3981  free(conn->keepalives);
3982  if (conn->keepalives_idle)
3983  free(conn->keepalives_idle);
3984  if (conn->keepalives_interval)
3985  free(conn->keepalives_interval);
3986  if (conn->keepalives_count)
3987  free(conn->keepalives_count);
3988  if (conn->sslmode)
3989  free(conn->sslmode);
3990  if (conn->sslcert)
3991  free(conn->sslcert);
3992  if (conn->sslkey)
3993  free(conn->sslkey);
3994  if (conn->sslpassword)
3995  free(conn->sslpassword);
3996  if (conn->sslrootcert)
3997  free(conn->sslrootcert);
3998  if (conn->sslcrl)
3999  free(conn->sslcrl);
4000  if (conn->sslcompression)
4001  free(conn->sslcompression);
4002  if (conn->requirepeer)
4003  free(conn->requirepeer);
4004  if (conn->gssencmode)
4005  free(conn->gssencmode);
4006  if (conn->krbsrvname)
4007  free(conn->krbsrvname);
4008  if (conn->gsslib)
4009  free(conn->gsslib);
4010  if (conn->connip)
4011  free(conn->connip);
4012 #ifdef ENABLE_GSS
4013  if (conn->gcred != GSS_C_NO_CREDENTIAL)
4014  {
4015  OM_uint32 minor;
4016 
4017  gss_release_cred(&minor, &conn->gcred);
4018  conn->gcred = GSS_C_NO_CREDENTIAL;
4019  }
4020  if (conn->gctx)
4021  {
4022  OM_uint32 minor;
4023 
4024  gss_delete_sec_context(&minor, &conn->gctx, GSS_C_NO_BUFFER);
4025  conn->gctx = NULL;
4026  }
4027 #endif
4028  /* Note that conn->Pfdebug is not ours to close or free */
4029  if (conn->last_query)
4030  free(conn->last_query);
4031  if (conn->write_err_msg)
4032  free(conn->write_err_msg);
4033  if (conn->inBuffer)
4034  free(conn->inBuffer);
4035  if (conn->outBuffer)
4036  free(conn->outBuffer);
4037  if (conn->rowBuf)
4038  free(conn->rowBuf);
4039  if (conn->target_session_attrs)
4040  free(conn->target_session_attrs);
4041  termPQExpBuffer(&conn->errorMessage);
4042  termPQExpBuffer(&conn->workBuffer);
4043 
4044  free(conn);
4045 
4046 #ifdef WIN32
4047  WSACleanup();
4048 #endif
4049 }
char * gssencmode
Definition: libpq-int.h:366
PGEvent * events
Definition: libpq-int.h:381
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:527
char * requirepeer
Definition: libpq-int.h:365
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:419
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:54
char * hostaddr
Definition: libpq-int.h:313
char * connect_timeout
Definition: libpq-int.h:339
pg_conn_host * connhost
Definition: libpq-int.h:404
char * keepalives_interval
Definition: libpq-int.h:354
char * appname
Definition: libpq-int.h:343
char * sslpassword
Definition: libpq-int.h:362
char * krbsrvname
Definition: libpq-int.h:367
char * channel_binding
Definition: libpq-int.h:350
char * target_session_attrs
Definition: libpq-int.h:372
char * last_query
Definition: libpq-int.h:390
PGdataValue * rowBuf
Definition: libpq-int.h:459
char * pguser
Definition: libpq-int.h:347
char * gsslib
Definition: libpq-int.h:368
char * inBuffer
Definition: libpq-int.h:442
char * sslmode
Definition: libpq-int.h:358
PQExpBufferData errorMessage
Definition: libpq-int.h:524
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:405
char * pgpass
Definition: libpq-int.h:348
char * sslrootcert
Definition: libpq-int.h:363
PGEventProc proc
Definition: libpq-int.h:160
char * outBuffer
Definition: libpq-int.h:449
char * pghostaddr
Definition: libpq-int.h:331
void explicit_bzero(void *buf, size_t len)
int nEvents
Definition: libpq-int.h:382
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:402
char * name
Definition: libpq-int.h:161
char * pgtcp_user_timeout
Definition: libpq-int.h:340
char * sslcrl
Definition: libpq-int.h:364
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 6292 of file fe-connect.c.

Referenced by conninfo_uri_decode().

6293 {
6294  if ('0' <= digit && digit <= '9')
6295  *value = digit - '0';
6296  else if ('A' <= digit && digit <= 'F')
6297  *value = digit - 'A' + 10;
6298  else if ('a' <= digit && digit <= 'f')
6299  *value = digit - 'a' + 10;
6300  else
6301  return false;
6302 
6303  return true;
6304 }
static struct @145 value

◆ getHostaddr()

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

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

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

Referenced by connectFailureMessage(), and PQconnectPoll().

1577 {
1578  struct sockaddr_storage *addr = &conn->raddr.addr;
1579 
1580  if (addr->ss_family == AF_INET)
1581  {
1582  if (pg_inet_net_ntop(AF_INET,
1583  &((struct sockaddr_in *) addr)->sin_addr.s_addr,
1584  32,
1585  host_addr, host_addr_len) == NULL)
1586  host_addr[0] = '\0';
1587  }
1588 #ifdef HAVE_IPV6
1589  else if (addr->ss_family == AF_INET6)
1590  {
1591  if (pg_inet_net_ntop(AF_INET6,
1592  &((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr,
1593  128,
1594  host_addr, host_addr_len) == NULL)
1595  host_addr[0] = '\0';
1596  }
1597 #endif
1598  else
1599  host_addr[0] = '\0';
1600 }
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:411

◆ internal_cancel()

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

Definition at line 4305 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().

4307 {
4308  int save_errno = SOCK_ERRNO;
4309  pgsocket tmpsock = PGINVALID_SOCKET;
4310  char sebuf[PG_STRERROR_R_BUFLEN];
4311  int maxlen;
4312  struct
4313  {
4314  uint32 packetlen;
4316  } crp;
4317 
4318  /*
4319  * We need to open a temporary connection to the postmaster. Do this with
4320  * only kernel calls.
4321  */
4322  if ((tmpsock = socket(raddr->addr.ss_family, SOCK_STREAM, 0)) == PGINVALID_SOCKET)
4323  {
4324  strlcpy(errbuf, "PQcancel() -- socket() failed: ", errbufsize);
4325  goto cancel_errReturn;
4326  }
4327 retry3:
4328  if (connect(tmpsock, (struct sockaddr *) &raddr->addr,
4329  raddr->salen) < 0)
4330  {
4331  if (SOCK_ERRNO == EINTR)
4332  /* Interrupted system call - we'll just try again */
4333  goto retry3;
4334  strlcpy(errbuf, "PQcancel() -- connect() failed: ", errbufsize);
4335  goto cancel_errReturn;
4336  }
4337 
4338  /*
4339  * We needn't set nonblocking I/O or NODELAY options here.
4340  */
4341 
4342  /* Create and send the cancel request packet. */
4343 
4344  crp.packetlen = pg_hton32((uint32) sizeof(crp));
4345  crp.cp.cancelRequestCode = (MsgType) pg_hton32(CANCEL_REQUEST_CODE);
4346  crp.cp.backendPID = pg_hton32(be_pid);
4347  crp.cp.cancelAuthCode = pg_hton32(be_key);
4348 
4349 retry4:
4350  if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp))
4351  {
4352  if (SOCK_ERRNO == EINTR)
4353  /* Interrupted system call - we'll just try again */
4354  goto retry4;
4355  strlcpy(errbuf, "PQcancel() -- send() failed: ", errbufsize);
4356  goto cancel_errReturn;
4357  }
4358 
4359  /*
4360  * Wait for the postmaster to close the connection, which indicates that
4361  * it's processed the request. Without this delay, we might issue another
4362  * command only to find that our cancel zaps that command instead of the
4363  * one we thought we were canceling. Note we don't actually expect this
4364  * read to obtain any data, we are just waiting for EOF to be signaled.
4365  */
4366 retry5:
4367  if (recv(tmpsock, (char *) &crp, 1, 0) < 0)
4368  {
4369  if (SOCK_ERRNO == EINTR)
4370  /* Interrupted system call - we'll just try again */
4371  goto retry5;
4372  /* we ignore other error conditions */
4373  }
4374 
4375  /* All done */
4376  closesocket(tmpsock);
4377  SOCK_ERRNO_SET(save_errno);
4378  return true;
4379 
4380 cancel_errReturn:
4381 
4382  /*
4383  * Make sure we don't overflow the error buffer. Leave space for the \n at
4384  * the end, and for the terminating zero.
4385  */
4386  maxlen = errbufsize - strlen(errbuf) - 2;
4387  if (maxlen >= 0)
4388  {
4389  strncat(errbuf, SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)),
4390  maxlen);
4391  strcat(errbuf, "\n");
4392  }
4393  if (tmpsock != PGINVALID_SOCKET)
4394  closesocket(tmpsock);
4395  SOCK_ERRNO_SET(save_errno);
4396  return false;
4397 }
#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:817
#define pg_hton32(x)
Definition: pg_bswap.h:121
#define SOCK_ERRNO
Definition: libpq-int.h:816
unsigned int uint32
Definition: c.h:359
int pgsocket
Definition: port.h:31
ACCEPT_TYPE_ARG3 salen
Definition: pqcomm.h:65
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:818
#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 3752 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().

3753 {
3754  /* Say "no attempt" if we never got to PQconnectPoll */
3755  if (!conn || !conn->options_valid)
3756  return PQPING_NO_ATTEMPT;
3757 
3758  /* Attempt to complete the connection */
3759  if (conn->status != CONNECTION_BAD)
3760  (void) connectDBComplete(conn);
3761 
3762  /* Definitely OK if we succeeded */
3763  if (conn->status != CONNECTION_BAD)
3764  return PQPING_OK;
3765 
3766  /*
3767  * Here begins the interesting part of "ping": determine the cause of the
3768  * failure in sufficient detail to decide what to return. We do not want
3769  * to report that the server is not up just because we didn't have a valid
3770  * password, for example. In fact, any sort of authentication request
3771  * implies the server is up. (We need this check since the libpq side of
3772  * things might have pulled the plug on the connection before getting an
3773  * error as such from the postmaster.)
3774  */
3775  if (conn->auth_req_received)
3776  return PQPING_OK;
3777 
3778  /*
3779  * If we failed to get any ERROR response from the postmaster, report
3780  * PQPING_NO_RESPONSE. This result could be somewhat misleading for a
3781  * pre-7.4 server, since it won't send back a SQLSTATE, but those are long
3782  * out of support. Another corner case where the server could return a
3783  * failure without a SQLSTATE is fork failure, but PQPING_NO_RESPONSE
3784  * isn't totally unreasonable for that anyway. We expect that every other
3785  * failure case in a modern server will produce a report with a SQLSTATE.
3786  *
3787  * NOTE: whenever we get around to making libpq generate SQLSTATEs for
3788  * client-side errors, we should either not store those into
3789  * last_sqlstate, or add an extra flag so we can tell client-side errors
3790  * apart from server-side ones.
3791  */
3792  if (strlen(conn->last_sqlstate) != 5)
3793  return PQPING_NO_RESPONSE;
3794 
3795  /*
3796  * Report PQPING_REJECT if server says it's not accepting connections. (We
3797  * distinguish this case mainly for the convenience of pg_ctl.)
3798  */
3799  if (strcmp(conn->last_sqlstate, ERRCODE_CANNOT_CONNECT_NOW) == 0)
3800  return PQPING_REJECT;
3801 
3802  /*
3803  * Any other SQLSTATE can be taken to indicate that the server is up.
3804  * Presumably it didn't like our username, password, or database name; or
3805  * perhaps it had some transient failure, but that should not be taken as
3806  * meaning "it's down".
3807  */
3808  return PQPING_OK;
3809 }
static int connectDBComplete(PGconn *conn)
Definition: fe-connect.c:2020
bool options_valid
Definition: libpq-int.h:392
#define ERRCODE_CANNOT_CONNECT_NOW
Definition: fe-connect.c:96
ConnStatusType status
Definition: libpq-int.h:386
bool auth_req_received
Definition: libpq-int.h:414
char last_sqlstate[6]
Definition: libpq-int.h:391

◆ makeEmptyPGconn()

static PGconn * makeEmptyPGconn ( void  )
static

Definition at line 3817 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().

3818 {
3819  PGconn *conn;
3820 
3821 #ifdef WIN32
3822 
3823  /*
3824  * Make sure socket support is up and running.
3825  */
3826  WSADATA wsaData;
3827 
3828  if (WSAStartup(MAKEWORD(1, 1), &wsaData))
3829  return NULL;
3830  WSASetLastError(0);
3831 #endif
3832 
3833  conn = (PGconn *) malloc(sizeof(PGconn));
3834  if (conn == NULL)
3835  {
3836 #ifdef WIN32
3837  WSACleanup();
3838 #endif
3839  return conn;
3840  }
3841 
3842  /* Zero all pointers and booleans */
3843  MemSet(conn, 0, sizeof(PGconn));
3844 
3845  /* install default notice hooks */
3848 
3849  conn->status = CONNECTION_BAD;
3850  conn->asyncStatus = PGASYNC_IDLE;
3851  conn->xactStatus = PQTRANS_IDLE;
3852  conn->options_valid = false;
3853  conn->nonblocking = false;
3855  conn->client_encoding = PG_SQL_ASCII;
3856  conn->std_strings = false; /* unless server says differently */
3857  conn->verbosity = PQERRORS_DEFAULT;
3859  conn->sock = PGINVALID_SOCKET;
3860 #ifdef ENABLE_GSS
3861  conn->try_gss = true;
3862 #endif
3863 
3864  /*
3865  * We try to send at least 8K at a time, which is the usual size of pipe
3866  * buffers on Unix systems. That way, when we are sending a large amount
3867  * of data, we avoid incurring extra kernel context swaps for partial
3868  * bufferloads. The output buffer is initially made 16K in size, and we
3869  * try to dump it after accumulating 8K.
3870  *
3871  * With the same goal of minimizing context swaps, the input buffer will
3872  * be enlarged anytime it has less than 8K free, so we initially allocate
3873  * twice that.
3874  */
3875  conn->inBufSize = 16 * 1024;
3876  conn->inBuffer = (char *) malloc(conn->inBufSize);
3877  conn->outBufSize = 16 * 1024;
3878  conn->outBuffer = (char *) malloc(conn->outBufSize);
3879  conn->rowBufLen = 32;
3880  conn->rowBuf = (PGdataValue *) malloc(conn->rowBufLen * sizeof(PGdataValue));
3881  initPQExpBuffer(&conn->errorMessage);
3882  initPQExpBuffer(&conn->workBuffer);
3883 
3884  if (conn->inBuffer == NULL ||
3885  conn->outBuffer == NULL ||
3886  conn->rowBuf == NULL ||
3887  PQExpBufferBroken(&conn->errorMessage) ||
3888  PQExpBufferBroken(&conn->workBuffer))
3889  {
3890  /* out of memory already :-( */
3891  freePGconn(conn);
3892  conn = NULL;
3893  }
3894 
3895  return conn;
3896 }
PGContextVisibility show_context
Definition: libpq-int.h:438
int rowBufLen
Definition: libpq-int.h:460
PQExpBufferData workBuffer
Definition: libpq-int.h:527
#define MemSet(start, val, len)
Definition: c.h:962
#define malloc(a)
Definition: header.h:50
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:387
PGSetenvStatusType setenv_state
Definition: libpq-int.h:427
PGconn * conn
Definition: streamutil.c:54
int inBufSize
Definition: libpq-int.h:443
PGNoticeHooks noticeHooks
Definition: libpq-int.h:378
PGVerbosity verbosity
Definition: libpq-int.h:437
PQnoticeReceiver noticeRec
Definition: libpq-int.h:152
PGdataValue * rowBuf
Definition: libpq-int.h:459
pgsocket sock
Definition: libpq-int.h:408
#define PGINVALID_SOCKET
Definition: port.h:33
char * inBuffer
Definition: libpq-int.h:442
PQnoticeProcessor noticeProc
Definition: libpq-int.h:154
static void freePGconn(PGconn *conn)
Definition: fe-connect.c:3908
PQExpBufferData errorMessage
Definition: libpq-int.h:524
bool std_strings
Definition: libpq-int.h:436
bool options_valid
Definition: libpq-int.h:392
int outBufSize
Definition: libpq-int.h:450
#define PQExpBufferBroken(str)
Definition: pqexpbuffer.h:59
ConnStatusType status
Definition: libpq-int.h:386
char * outBuffer
Definition: libpq-int.h:449
bool nonblocking
Definition: libpq-int.h:393
static void defaultNoticeProcessor(void *arg, const char *message)
Definition: fe-connect.c:6845
int client_encoding
Definition: libpq-int.h:435
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
static void defaultNoticeReceiver(void *arg, const PGresult *res)
Definition: fe-connect.c:6830
PGTransactionStatusType xactStatus
Definition: libpq-int.h:388

◆ parse_comma_separated_list()

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

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

References malloc, and startptr.

Referenced by connectOptions2().

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

◆ parse_connection_string()

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

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

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

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

5297 {
5298  /* Parse as URI if connection string matches URI prefix */
5299  if (uri_prefix_length(connstr) != 0)
5300  return conninfo_uri_parse(connstr, errorMessage, use_defaults);
5301 
5302  /* Parse as default otherwise */
5303  return conninfo_parse(connstr, errorMessage, use_defaults);
5304 }
static PQconninfoOption * conninfo_parse(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5349
static int uri_prefix_length(const char *connstr)
Definition: fe-connect.c:5315
static PQconninfoOption * conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5796
static char * connstr
Definition: pg_dumpall.c:61

◆ parse_int_param()

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

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

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

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

1703 {
1704  char *end;
1705  long numval;
1706 
1707  Assert(value != NULL);
1708 
1709  *result = 0;
1710 
1711  /* strtol(3) skips leading whitespaces */
1712  errno = 0;
1713  numval = strtol(value, &end, 10);
1714 
1715  /*
1716  * If no progress was done during the parsing or an error happened, fail.
1717  * This tests properly for overflows of the result.
1718  */
1719  if (value == end || errno != 0 || numval != (int) numval)
1720  goto error;
1721 
1722  /*
1723  * Skip any trailing whitespace; if anything but whitespace remains before
1724  * the terminating character, fail
1725  */
1726  while (*end != '\0' && isspace((unsigned char) *end))
1727  end++;
1728 
1729  if (*end != '\0')
1730  goto error;
1731 
1732  *result = numval;
1733  return true;
1734 
1735 error:
1737  libpq_gettext("invalid integer value \"%s\" for connection option \"%s\"\n"),
1738  value, context);
1739  return false;
1740 }
static void error(void)
Definition: sql-dyntest.c:147
static struct @145 value
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
PQExpBufferData errorMessage
Definition: libpq-int.h:524
#define Assert(condition)
Definition: c.h:739
#define libpq_gettext(x)
Definition: libpq-int.h:803

◆ parseServiceFile()

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

Definition at line 5055 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().

5060 {
5061  int linenr = 0,
5062  i;
5063  FILE *f;
5064  char buf[MAXBUFSIZE],
5065  *line;
5066 
5067  f = fopen(serviceFile, "r");
5068  if (f == NULL)
5069  {
5070  printfPQExpBuffer(errorMessage, libpq_gettext("service file \"%s\" not found\n"),
5071  serviceFile);
5072  return 1;
5073  }
5074 
5075  while ((line = fgets(buf, sizeof(buf), f)) != NULL)
5076  {
5077  int len;
5078 
5079  linenr++;
5080 
5081  if (strlen(line) >= sizeof(buf) - 1)
5082  {
5083  fclose(f);
5084  printfPQExpBuffer(errorMessage,
5085  libpq_gettext("line %d too long in service file \"%s\"\n"),
5086  linenr,
5087  serviceFile);
5088  return 2;
5089  }
5090 
5091  /* ignore whitespace at end of line, especially the newline */
5092  len = strlen(line);
5093  while (len > 0 && isspace((unsigned char) line[len - 1]))
5094  line[--len] = '\0';
5095 
5096  /* ignore leading whitespace too */
5097  while (*line && isspace((unsigned char) line[0]))
5098  line++;
5099 
5100  /* ignore comments and empty lines */
5101  if (line[0] == '\0' || line[0] == '#')
5102  continue;
5103 
5104  /* Check for right groupname */
5105  if (line[0] == '[')
5106  {
5107  if (*group_found)
5108  {
5109  /* group info already read */
5110  fclose(f);
5111  return 0;
5112  }
5113 
5114  if (strncmp(line + 1, service, strlen(service)) == 0 &&
5115  line[strlen(service) + 1] == ']')
5116  *group_found = true;
5117  else
5118  *group_found = false;
5119  }
5120  else
5121  {
5122  if (*group_found)
5123  {
5124  /*
5125  * Finally, we are in the right group and can parse the line
5126  */
5127  char *key,
5128  *val;
5129  bool found_keyword;
5130 
5131 #ifdef USE_LDAP
5132  if (strncmp(line, "ldap", 4) == 0)
5133  {
5134  int rc = ldapServiceLookup(line, options, errorMessage);
5135 
5136  /* if rc = 2, go on reading for fallback */
5137  switch (rc)
5138  {
5139  case 0:
5140  fclose(f);
5141  return 0;
5142  case 1:
5143  case 3:
5144  fclose(f);
5145  return 3;
5146  case 2:
5147  continue;
5148  }
5149  }
5150 #endif
5151 
5152  key = line;
5153  val = strchr(line, '=');
5154  if (val == NULL)
5155  {
5156  printfPQExpBuffer(errorMessage,
5157  libpq_gettext("syntax error in service file \"%s\", line %d\n"),
5158  serviceFile,
5159  linenr);
5160  fclose(f);
5161  return 3;
5162  }
5163  *val++ = '\0';
5164 
5165  if (strcmp(key, "service") == 0)
5166  {
5167  printfPQExpBuffer(errorMessage,
5168  libpq_gettext("nested service specifications not supported in service file \"%s\", line %d\n"),
5169  serviceFile,
5170  linenr);
5171  fclose(f);
5172  return 3;
5173  }
5174 
5175  /*
5176  * Set the parameter --- but don't override any previous
5177  * explicit setting.
5178  */
5179  found_keyword = false;
5180  for (i = 0; options[i].keyword; i++)
5181  {
5182  if (strcmp(options[i].keyword, key) == 0)
5183  {
5184  if (options[i].val == NULL)
5185  options[i].val = strdup(val);
5186  if (!options[i].val)
5187  {
5188  printfPQExpBuffer(errorMessage,
5189  libpq_gettext("out of memory\n"));
5190  fclose(f);
5191  return 3;
5192  }
5193  found_keyword = true;
5194  break;
5195  }
5196  }
5197 
5198  if (!found_keyword)
5199  {
5200  printfPQExpBuffer(errorMessage,
5201  libpq_gettext("syntax error in service file \"%s\", line %d\n"),
5202  serviceFile,
5203  linenr);
5204  fclose(f);
5205  return 3;
5206  }
5207  }
5208  }
5209  }
5210 
5211  fclose(f);
5212 
5213  return 0;
5214 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
#define MAXBUFSIZE
Definition: fe-connect.c:4973
static char * buf
Definition: pg_test_fsync.c:67
int i
long val
Definition: informix.c:664
#define libpq_gettext(x)
Definition: libpq-int.h:803

◆ parseServiceInfo()

static int parseServiceInfo ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

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

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

Referenced by conninfo_add_defaults().

4987 {
4988  const char *service = conninfo_getval(options, "service");
4989  char serviceFile[MAXPGPATH];
4990  char *env;
4991  bool group_found = false;
4992  int status;
4993  struct stat stat_buf;
4994 
4995  /*
4996  * We have to special-case the environment variable PGSERVICE here, since
4997  * this is and should be called before inserting environment defaults for
4998  * other connection options.
4999  */
5000  if (service == NULL)
5001  service = getenv("PGSERVICE");
5002 
5003  /* If no service name given, nothing to do */
5004  if (service == NULL)
5005  return 0;
5006 
5007  /*
5008  * Try PGSERVICEFILE if specified, else try ~/.pg_service.conf (if that
5009  * exists).
5010  */
5011  if ((env = getenv("PGSERVICEFILE")) != NULL)
5012  strlcpy(serviceFile, env, sizeof(serviceFile));
5013  else
5014  {
5015  char homedir[MAXPGPATH];
5016 
5017  if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
5018  goto next_file;
5019  snprintf(serviceFile, MAXPGPATH, "%s/%s", homedir, ".pg_service.conf");
5020  if (stat(serviceFile, &stat_buf) != 0)
5021  goto next_file;
5022  }
5023 
5024  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
5025  if (group_found || status != 0)
5026  return status;
5027 
5028 next_file:
5029 
5030  /*
5031  * This could be used by any application so we can't use the binary
5032  * location to find our config files.
5033  */
5034  snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf",
5035  getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);
5036  if (stat(serviceFile, &stat_buf) != 0)
5037  goto last_file;
5038 
5039  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
5040  if (status != 0)
5041  return status;
5042 
5043 last_file:
5044  if (!group_found)
5045  {
5046  printfPQExpBuffer(errorMessage,
5047  libpq_gettext("definition of service \"%s\" not found\n"), service);
5048  return 3;
5049  }
5050 
5051  return 0;
5052 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
struct stat stat_buf
Definition: pg_standby.c:100
#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:5055
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6313
bool pqGetHomeDirectory(char *buf, int bufsize)
Definition: fe-connect.c:7054
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:226
#define snprintf
Definition: port.h:192
#define libpq_gettext(x)
Definition: libpq-int.h:803

◆ passwordFromFile()

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

Definition at line 6894 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().

6896 {
6897  FILE *fp;
6898  struct stat stat_buf;
6899 
6900 #define LINELEN NAMEDATALEN*5
6901  char buf[LINELEN];
6902 
6903  if (dbname == NULL || dbname[0] == '\0')
6904  return NULL;
6905 
6906  if (username == NULL || username[0] == '\0')
6907  return NULL;
6908 
6909  /* 'localhost' matches pghost of '' or the default socket directory */
6910  if (hostname == NULL || hostname[0] == '\0')
6912  else if (is_absolute_path(hostname))
6913 
6914  /*
6915  * We should probably use canonicalize_path(), but then we have to
6916  * bring path.c into libpq, and it doesn't seem worth it.
6917  */
6918  if (strcmp(hostname, DEFAULT_PGSOCKET_DIR) == 0)
6920 
6921  if (port == NULL || port[0] == '\0')
6922  port = DEF_PGPORT_STR;
6923 
6924  /* If password file cannot be opened, ignore it. */
6925  if (stat(pgpassfile, &stat_buf) != 0)
6926  return NULL;
6927 
6928 #ifndef WIN32
6929  if (!S_ISREG(stat_buf.st_mode))
6930  {
6931  fprintf(stderr,
6932  libpq_gettext("WARNING: password file \"%s\" is not a plain file\n"),
6933  pgpassfile);
6934  return NULL;
6935  }
6936 
6937  /* If password file is insecure, alert the user and ignore it. */
6938  if (stat_buf.st_mode & (S_IRWXG | S_IRWXO))
6939  {
6940  fprintf(stderr,
6941  libpq_gettext("WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
6942  pgpassfile);
6943  return NULL;
6944  }
6945 #else
6946 
6947  /*
6948  * On Win32, the directory is protected, so we don't have to check the
6949  * file.
6950  */
6951 #endif
6952 
6953  fp = fopen(pgpassfile, "r");
6954  if (fp == NULL)
6955  return NULL;
6956 
6957  while (!feof(fp) && !ferror(fp))
6958  {
6959  char *t = buf,
6960  *ret,
6961  *p1,
6962  *p2;
6963  int len;
6964 
6965  if (fgets(buf, sizeof(buf), fp) == NULL)
6966  break;
6967 
6968  /* strip trailing newline and carriage return */
6969  len = pg_strip_crlf(buf);
6970 
6971  if (len == 0)
6972  continue;
6973 
6974  if ((t = pwdfMatchesString(t, hostname)) == NULL ||
6975  (t = pwdfMatchesString(t, port)) == NULL ||
6976  (t = pwdfMatchesString(t, dbname)) == NULL ||
6977  (t = pwdfMatchesString(t, username)) == NULL)
6978  continue;
6979 
6980  /* Found a match. */
6981  ret = strdup(t);
6982  fclose(fp);
6983 
6984  if (!ret)
6985  {
6986  /* Out of memory. XXX: an error message would be nice. */
6987  explicit_bzero(buf, sizeof(buf));
6988  return NULL;
6989  }
6990 
6991  /* De-escape password. */
6992  for (p1 = p2 = ret; *p1 != ':' && *p1 != '\0'; ++p1, ++p2)
6993  {
6994  if (*p1 == '\\' && p1[1] != '\0')
6995  ++p1;
6996  *p2 = *p1;
6997  }
6998  *p2 = '\0';
6999 
7000  return ret;
7001  }
7002 
7003  fclose(fp);
7004  explicit_bzero(buf, sizeof(buf));
7005  return NULL;
7006 
7007 #undef LINELEN
7008 }
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:100
static char * buf
Definition: pg_test_fsync.c:67
#define S_IRWXG
Definition: win32_port.h:281
#define is_absolute_path(filename)
Definition: port.h:86
static int port
Definition: pg_regress.c:91
#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:50
#define DefaultHost
Definition: fe-connect.c:121
static char * pwdfMatchesString(char *buf, const char *token)
Definition: fe-connect.c:6857
void explicit_bzero(void *buf, size_t len)
static char * hostname
Definition: pg_regress.c:90
#define S_IRWXO
Definition: win32_port.h:293
#define libpq_gettext(x)
Definition: libpq-int.h:803
#define DEFAULT_PGSOCKET_DIR

◆ pgpassfileWarning()

static void pgpassfileWarning ( PGconn conn)
static

Definition at line 7016 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().

7017 {
7018  /* If it was 'invalid authorization', add pgpassfile mention */
7019  /* only works with >= 9.0 servers */
7020  if (conn->password_needed &&
7021  conn->connhost[conn->whichhost].password != NULL &&
7022  conn->result)
7023  {
7024  const char *sqlstate = PQresultErrorField(conn->result,
7026 
7027  if (sqlstate && strcmp(sqlstate, ERRCODE_INVALID_PASSWORD) == 0)
7029  libpq_gettext("password retrieved from file \"%s\"\n"),
7030  conn->pgpassfile);
7031  }
7032 }
char * pgpassfile
Definition: libpq-int.h:349
bool password_needed
Definition: libpq-int.h:415
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
PGresult * result
Definition: libpq-int.h:463
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
pg_conn_host * connhost
Definition: libpq-int.h:404
PQExpBufferData errorMessage
Definition: libpq-int.h:524
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:2754
#define ERRCODE_INVALID_PASSWORD
Definition: fe-connect.c:94
int whichhost
Definition: libpq-int.h:403
#define libpq_gettext(x)
Definition: libpq-int.h:803
char * password
Definition: libpq-int.h:315

◆ PQbackendPID()

int PQbackendPID ( const PGconn conn)

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

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

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

6658 {
6659  if (!conn || conn->status != CONNECTION_OK)
6660  return 0;
6661  return conn->be_pid;
6662 }
ConnStatusType status
Definition: libpq-int.h:386
int be_pid
Definition: libpq-int.h:432

◆ PQcancel()

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

Definition at line 4409 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().

4410 {
4411  if (!cancel)
4412  {
4413  strlcpy(errbuf, "PQcancel() -- no cancel object supplied", errbufsize);
4414  return false;
4415  }
4416 
4417  return internal_cancel(&cancel->raddr, cancel->be_pid, cancel->be_key,
4418  errbuf, errbufsize);
4419 }
static int internal_cancel(SockAddr *raddr, int be_pid, int be_key, char *errbuf, int errbufsize)
Definition: fe-connect.c:4305
int be_pid
Definition: libpq-int.h:537
int be_key
Definition: libpq-int.h:538
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
SockAddr raddr
Definition: libpq-int.h:536

◆ PQclientEncoding()

int PQclientEncoding ( const PGconn conn)

◆ PQconndefaults()

PQconninfoOption* PQconndefaults ( void  )

Definition at line 1382 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().

1383 {
1384  PQExpBufferData errorBuf;
1385  PQconninfoOption *connOptions;
1386 
1387  /* We don't actually report any errors here, but callees want a buffer */
1388  initPQExpBuffer(&errorBuf);
1389  if (PQExpBufferDataBroken(errorBuf))
1390  return NULL; /* out of memory already :-( */
1391 
1392  connOptions = conninfo_init(&errorBuf);
1393  if (connOptions != NULL)
1394  {
1395  /* pass NULL errorBuf to ignore errors */
1396  if (!conninfo_add_defaults(connOptions, NULL))
1397  {
1398  PQconninfoFree(connOptions);
1399  connOptions = NULL;
1400  }
1401  }
1402 
1403  termPQExpBuffer(&errorBuf);
1404  return connOptions;
1405 }
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5255
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6463
#define PQExpBufferDataBroken(buf)
Definition: pqexpbuffer.h:67
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5691
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92

◆ PQconnectdb()

PGconn* PQconnectdb ( const char *  conninfo)

Definition at line 686 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().

687 {
688  PGconn *conn = PQconnectStart(conninfo);
689 
690  if (conn && conn->status != CONNECTION_BAD)
691  (void) connectDBComplete(conn);
692 
693  return conn;
694 }
PGconn * conn
Definition: streamutil.c:54
static int connectDBComplete(PGconn *conn)
Definition: fe-connect.c:2020
PGconn * PQconnectStart(const char *conninfo)
Definition: fe-connect.c:812
ConnStatusType status
Definition: libpq-int.h:386

◆ PQconnectdbParams()

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

Definition at line 630 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().

633 {
634  PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname);
635 
636  if (conn && conn->status != CONNECTION_BAD)
637  (void) connectDBComplete(conn);
638 
639  return conn;
640 
641 }
PGconn * conn
Definition: streamutil.c:54
static int connectDBComplete(PGconn *conn)
Definition: fe-connect.c:2020
ConnStatusType status
Definition: libpq-int.h:386
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:733

◆ PQconnectionNeedsPassword()

int PQconnectionNeedsPassword ( const PGconn conn)

Definition at line 6665 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().

6666 {
6667  char *password;
6668 
6669  if (!conn)
6670  return false;
6671  password = PQpass(conn);
6672  if (conn->password_needed &&
6673  (password == NULL || password[0] == '\0'))
6674  return true;
6675  else
6676  return false;
6677 }
static char password[100]
Definition: streamutil.c:53
bool password_needed
Definition: libpq-int.h:415
char * PQpass(const PGconn *conn)
Definition: fe-connect.c:6497

◆ PQconnectionUsedPassword()

int PQconnectionUsedPassword ( const PGconn conn)

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

References pg_conn::password_needed.

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

6681 {
6682  if (!conn)
6683  return false;
6684  if (conn->password_needed)
6685  return true;
6686  else
6687  return false;
6688 }
bool password_needed
Definition: libpq-int.h:415

◆ PQconnectPoll()

PostgresPollingStatusType PQconnectPoll ( PGconn conn)

Definition at line 2202 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().

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