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 * PQsslpassword (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 4965 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 4090 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().

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

◆ connectDBComplete()

static int connectDBComplete ( PGconn conn)
static

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

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

◆ connectDBStart()

static int connectDBStart ( PGconn conn)
static

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

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

◆ connectFailureMessage()

static void connectFailureMessage ( PGconn conn,
int  errorno 
)
static

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

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

◆ connectNoDelay()

static int connectNoDelay ( PGconn conn)
static

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

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

◆ connectOptions1()

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

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

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

◆ connectOptions2()

static bool connectOptions2 ( PGconn conn)
static

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

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

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

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

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

◆ conninfo_find()

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

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

References _PQconninfoOption::keyword.

Referenced by conninfo_getval(), and conninfo_storeval().

6397 {
6399 
6400  for (option = connOptions; option->keyword != NULL; option++)
6401  {
6402  if (strcmp(option->keyword, keyword) == 0)
6403  return option;
6404  }
6405 
6406  return NULL;
6407 }

◆ conninfo_getval()

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

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

References conninfo_find(), and _PQconninfoOption::val.

Referenced by fillPGconn(), and parseServiceInfo().

6307 {
6309 
6310  option = conninfo_find(connOptions, keyword);
6311 
6312  return option ? option->val : NULL;
6313 }
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6396

◆ conninfo_init()

static PQconninfoOption * conninfo_init ( PQExpBuffer  errorMessage)
static

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

5248 {
5250  PQconninfoOption *opt_dest;
5251  const internalPQconninfoOption *cur_opt;
5252 
5253  /*
5254  * Get enough memory for all options in PQconninfoOptions, even if some
5255  * end up being filtered out.
5256  */
5257  options = (PQconninfoOption *) malloc(sizeof(PQconninfoOption) * sizeof(PQconninfoOptions) / sizeof(PQconninfoOptions[0]));
5258  if (options == NULL)
5259  {
5260  printfPQExpBuffer(errorMessage,
5261  libpq_gettext("out of memory\n"));
5262  return NULL;
5263  }
5264  opt_dest = options;
5265 
5266  for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++)
5267  {
5268  /* Only copy the public part of the struct, not the full internal */
5269  memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption));
5270  opt_dest++;
5271  }
5272  MemSet(opt_dest, 0, sizeof(PQconninfoOption));
5273 
5274  return options;
5275 }
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:792

◆ conninfo_parse()

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

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

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

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

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

◆ conninfo_uri_decode()

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

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

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

◆ conninfo_uri_parse()

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

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

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

Referenced by parse_connection_string().

5790 {
5792 
5793  /* Make a working copy of PQconninfoOptions */
5794  options = conninfo_init(errorMessage);
5795  if (options == NULL)
5796  return NULL;
5797 
5798  if (!conninfo_uri_parse_options(options, uri, errorMessage))
5799  {
5800  PQconninfoFree(options);
5801  return NULL;
5802  }
5803 
5804  /*
5805  * Add in defaults if the caller wants that.
5806  */
5807  if (use_defaults)
5808  {
5809  if (!conninfo_add_defaults(options, errorMessage))
5810  {
5811  PQconninfoFree(options);
5812  return NULL;
5813  }
5814  }
5815 
5816  return options;
5817 }
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5247
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6455
static bool conninfo_uri_parse_options(PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage)
Definition: fe-connect.c:5841
static char ** options
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5683

◆ conninfo_uri_parse_options()

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

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

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

◆ conninfo_uri_parse_params()

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

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

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

◆ count_comma_separated_elems()

static int count_comma_separated_elems ( const char *  input)
static

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

Referenced by connectOptions2().

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

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

851 {
853 
854  for (option = PQconninfoOptions; option->keyword; option++)
855  {
856  if (option->connofs >= 0)
857  {
858  const char *tmp = conninfo_getval(connOptions, option->keyword);
859 
860  if (tmp)
861  {
862  char **connmember = (char **) ((char *) conn + option->connofs);
863 
864  if (*connmember)
865  free(*connmember);
866  *connmember = strdup(tmp);
867  if (*connmember == NULL)
868  {
870  libpq_gettext("out of memory\n"));
871  return false;
872  }
873  }
874  }
875  }
876 
877  return true;
878 }
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:511
#define free(a)
Definition: header.h:65
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6305
#define libpq_gettext(x)
Definition: libpq-int.h:792

◆ freePGconn()

static void freePGconn ( PGconn conn)
static

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

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

Referenced by makeEmptyPGconn(), and PQfinish().

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

◆ get_hexdigit()

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

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

Referenced by conninfo_uri_decode().

6285 {
6286  if ('0' <= digit && digit <= '9')
6287  *value = digit - '0';
6288  else if ('A' <= digit && digit <= 'F')
6289  *value = digit - 'A' + 10;
6290  else if ('a' <= digit && digit <= 'f')
6291  *value = digit - 'a' + 10;
6292  else
6293  return false;
6294 
6295  return true;
6296 }
static struct @145 value

◆ getHostaddr()

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

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

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

Referenced by connectFailureMessage(), and PQconnectPoll().

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

◆ internal_cancel()

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

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

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

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

◆ makeEmptyPGconn()

static PGconn * makeEmptyPGconn ( void  )
static

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

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

◆ parse_comma_separated_list()

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

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

References malloc, and startptr.

Referenced by connectOptions2().

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

◆ parse_connection_string()

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

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

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

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

5289 {
5290  /* Parse as URI if connection string matches URI prefix */
5291  if (uri_prefix_length(connstr) != 0)
5292  return conninfo_uri_parse(connstr, errorMessage, use_defaults);
5293 
5294  /* Parse as default otherwise */
5295  return conninfo_parse(connstr, errorMessage, use_defaults);
5296 }
static PQconninfoOption * conninfo_parse(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5341
static int uri_prefix_length(const char *connstr)
Definition: fe-connect.c:5307
static PQconninfoOption * conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5788
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 1695 of file fe-connect.c.

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

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

1697 {
1698  char *end;
1699  long numval;
1700 
1701  Assert(value != NULL);
1702 
1703  *result = 0;
1704 
1705  /* strtol(3) skips leading whitespaces */
1706  errno = 0;
1707  numval = strtol(value, &end, 10);
1708 
1709  /*
1710  * If no progress was done during the parsing or an error happened, fail.
1711  * This tests properly for overflows of the result.
1712  */
1713  if (value == end || errno != 0 || numval != (int) numval)
1714  goto error;
1715 
1716  /*
1717  * Skip any trailing whitespace; if anything but whitespace remains before
1718  * the terminating character, fail
1719  */
1720  while (*end != '\0' && isspace((unsigned char) *end))
1721  end++;
1722 
1723  if (*end != '\0')
1724  goto error;
1725 
1726  *result = numval;
1727  return true;
1728 
1729 error:
1731  libpq_gettext("invalid integer value \"%s\" for connection option \"%s\"\n"),
1732  value, context);
1733  return false;
1734 }
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:511
#define Assert(condition)
Definition: c.h:739
#define libpq_gettext(x)
Definition: libpq-int.h:792

◆ parseServiceFile()

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

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

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

◆ parseServiceInfo()

static int parseServiceInfo ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

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

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

Referenced by conninfo_add_defaults().

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

◆ 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:792
#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:414
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
PGresult * result
Definition: libpq-int.h:462
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
pg_conn_host * connhost
Definition: libpq-int.h:403
PQExpBufferData errorMessage
Definition: libpq-int.h:511
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:2754
#define ERRCODE_INVALID_PASSWORD
Definition: fe-connect.c:94
int whichhost
Definition: libpq-int.h:402
#define libpq_gettext(x)
Definition: libpq-int.h:792
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(), 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:385
int be_pid
Definition: libpq-int.h:431

◆ PQcancel()

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

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

4402 {
4403  if (!cancel)
4404  {
4405  strlcpy(errbuf, "PQcancel() -- no cancel object supplied", errbufsize);
4406  return false;
4407  }
4408 
4409  return internal_cancel(&cancel->raddr, cancel->be_pid, cancel->be_key,
4410  errbuf, errbufsize);
4411 }
static int internal_cancel(SockAddr *raddr, int be_pid, int be_key, char *errbuf, int errbufsize)
Definition: fe-connect.c:4297
int be_pid
Definition: libpq-int.h:526
int be_key
Definition: libpq-int.h:527
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
SockAddr raddr
Definition: libpq-int.h:525

◆ PQclientEncoding()

int PQclientEncoding ( const PGconn conn)

◆ PQconndefaults()

PQconninfoOption* PQconndefaults ( void  )

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

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

◆ PQconnectdb()

PGconn* PQconnectdb ( const char *  conninfo)

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

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

◆ PQconnectdbParams()

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

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

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

◆ 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:414
char * PQpass(const PGconn *conn)
Definition: fe-connect.c:6489

◆ 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:414

◆ PQconnectPoll()

PostgresPollingStatusType PQconnectPoll ( PGconn conn)

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

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