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 "lib/stringinfo.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"
 

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)
 
static bool sslVerifyProtocolVersion (const char *version)
 
static bool sslVerifyProtocolRange (const char *min, const char *max)
 
void pqDropConnection (PGconn *conn, bool flushInput)
 
static void pqDropServerData (PGconn *conn)
 
PGconnPQconnectdbParams (const char *const *keywords, const char *const *values, int expand_dbname)
 
PGPing PQpingParams (const char *const *keywords, const char *const *values, int expand_dbname)
 
PGconnPQconnectdb (const char *conninfo)
 
PGPing PQping (const char *conninfo)
 
PGconnPQconnectStartParams (const char *const *keywords, const char *const *values, int expand_dbname)
 
PGconnPQconnectStart (const char *conninfo)
 
static int count_comma_separated_elems (const char *input)
 
static char * parse_comma_separated_list (char **startptr, bool *more)
 
PQconninfoOptionPQconndefaults (void)
 
PGconnPQsetdbLogin (const char *pghost, const char *pgport, const char *pgoptions, const char *pgtty, const char *dbName, const char *login, const char *pwd)
 
static int connectNoDelay (PGconn *conn)
 
static void getHostaddr (PGconn *conn, char *host_addr, int host_addr_len)
 
static void connectFailureMessage (PGconn *conn, int errorno)
 
static int useKeepalives (PGconn *conn)
 
static bool parse_int_param (const char *value, int *result, PGconn *conn, const char *context)
 
static int setKeepalivesIdle (PGconn *conn)
 
static int setKeepalivesInterval (PGconn *conn)
 
static int setKeepalivesCount (PGconn *conn)
 
static int setTCPUserTimeout (PGconn *conn)
 
static bool saveErrorMessage (PGconn *conn, PQExpBuffer savedMessage)
 
static void restoreErrorMessage (PGconn *conn, PQExpBuffer savedMessage)
 
PostgresPollingStatusType PQconnectPoll (PGconn *conn)
 
void PQfinish (PGconn *conn)
 
void PQreset (PGconn *conn)
 
int PQresetStart (PGconn *conn)
 
PostgresPollingStatusType PQresetPoll (PGconn *conn)
 
PGcancelPQgetCancel (PGconn *conn)
 
void PQfreeCancel (PGcancel *cancel)
 
static int internal_cancel (SockAddr *raddr, int be_pid, int be_key, char *errbuf, int errbufsize)
 
int PQcancel (PGcancel *cancel, char *errbuf, int errbufsize)
 
int PQrequestCancel (PGconn *conn)
 
int pqPacketSend (PGconn *conn, char pack_type, const void *buf, size_t buf_len)
 
PQconninfoOptionPQconninfoParse (const char *conninfo, char **errmsg)
 
PQconninfoOptionPQconninfo (PGconn *conn)
 
void PQconninfoFree (PQconninfoOption *connOptions)
 
char * PQdb (const PGconn *conn)
 
char * PQuser (const PGconn *conn)
 
char * PQpass (const PGconn *conn)
 
char * PQhost (const PGconn *conn)
 
char * PQhostaddr (const PGconn *conn)
 
char * PQport (const PGconn *conn)
 
char * PQtty (const PGconn *conn)
 
char * PQoptions (const PGconn *conn)
 
ConnStatusType PQstatus (const PGconn *conn)
 
PGTransactionStatusType PQtransactionStatus (const PGconn *conn)
 
const char * PQparameterStatus (const PGconn *conn, const char *paramName)
 
int PQprotocolVersion (const PGconn *conn)
 
int PQserverVersion (const PGconn *conn)
 
char * PQerrorMessage (const PGconn *conn)
 
int PQsocket (const PGconn *conn)
 
int PQbackendPID (const PGconn *conn)
 
int PQconnectionNeedsPassword (const PGconn *conn)
 
int PQconnectionUsedPassword (const PGconn *conn)
 
int PQclientEncoding (const PGconn *conn)
 
int PQsetClientEncoding (PGconn *conn, const char *encoding)
 
PGVerbosity PQsetErrorVerbosity (PGconn *conn, PGVerbosity verbosity)
 
PGContextVisibility PQsetErrorContextVisibility (PGconn *conn, PGContextVisibility show_context)
 
void PQtrace (PGconn *conn, FILE *debug_port)
 
void PQuntrace (PGconn *conn)
 
PQnoticeReceiver PQsetNoticeReceiver (PGconn *conn, PQnoticeReceiver proc, void *arg)
 
PQnoticeProcessor PQsetNoticeProcessor (PGconn *conn, PQnoticeProcessor proc, void *arg)
 
bool pqGetHomeDirectory (char *buf, int bufsize)
 
pgthreadlock_t PQregisterThreadLock (pgthreadlock_t newhandler)
 

Variables

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

Macro Definition Documentation

◆ DefaultAuthtype

#define DefaultAuthtype   ""

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

◆ DefaultChannelBinding

#define DefaultChannelBinding   "disable"

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

Referenced by connectOptions2().

◆ DefaultGSSMode

#define DefaultGSSMode   "disable"

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

Referenced by connectOptions2().

◆ DefaultHost

#define DefaultHost   "localhost"

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

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

◆ DefaultOption

#define DefaultOption   ""

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

◆ DefaultSSLMode

#define DefaultSSLMode   "disable"

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

Referenced by connectOptions2().

◆ DefaultTargetSessionAttrs

#define DefaultTargetSessionAttrs   "any"

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

◆ DefaultTty

#define DefaultTty   ""

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

◆ ERRCODE_APPNAME_UNKNOWN

#define ERRCODE_APPNAME_UNKNOWN   "42704"

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

Referenced by PQconnectPoll().

◆ ERRCODE_CANNOT_CONNECT_NOW

#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"

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

Referenced by internal_ping(), and ProcessStartupPacket().

◆ ERRCODE_INVALID_PASSWORD

#define ERRCODE_INVALID_PASSWORD   "28P01"

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

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

◆ PGPASSFILE

#define PGPASSFILE   ".pgpass"

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

Referenced by connectOptions2().

Typedef Documentation

◆ internalPQconninfoOption

Function Documentation

◆ closePGconn()

static void closePGconn ( PGconn conn)
static

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

4137 {
4138  /*
4139  * If possible, send Terminate message to close the connection politely.
4140  */
4141  sendTerminateConn(conn);
4142 
4143  /*
4144  * Must reset the blocking status so a possible reconnect will work.
4145  *
4146  * Don't call PQsetnonblocking() because it will fail if it's unable to
4147  * flush the connection.
4148  */
4149  conn->nonblocking = false;
4150 
4151  /*
4152  * Close the connection, reset all transient state, flush I/O buffers.
4153  */
4154  pqDropConnection(conn, true);
4155  conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
4156  conn->asyncStatus = PGASYNC_IDLE;
4157  conn->xactStatus = PQTRANS_IDLE;
4158  pqClearAsyncResult(conn); /* deallocate result */
4160  release_conn_addrinfo(conn);
4161 
4162  /* Reset all state obtained from server, too */
4163  pqDropServerData(conn);
4164 }
static void release_conn_addrinfo(PGconn *conn)
Definition: fe-connect.c:4094
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:459
static void sendTerminateConn(PGconn *conn)
Definition: fe-connect.c:4109
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:389
static void pqDropServerData(PGconn *conn)
Definition: fe-connect.c:554
PQExpBufferData errorMessage
Definition: libpq-int.h:526
ConnStatusType status
Definition: libpq-int.h:388
bool nonblocking
Definition: libpq-int.h:395
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:749
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148
PGTransactionStatusType xactStatus
Definition: libpq-int.h:390

◆ connectDBComplete()

static int connectDBComplete ( PGconn conn)
static

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

2079 {
2081  time_t finish_time = ((time_t) -1);
2082  int timeout = 0;
2083  int last_whichhost = -2; /* certainly different from whichhost */
2084  struct addrinfo *last_addr_cur = NULL;
2085 
2086  if (conn == NULL || conn->status == CONNECTION_BAD)
2087  return 0;
2088 
2089  /*
2090  * Set up a time limit, if connect_timeout isn't zero.
2091  */
2092  if (conn->connect_timeout != NULL)
2093  {
2094  if (!parse_int_param(conn->connect_timeout, &timeout, conn,
2095  "connect_timeout"))
2096  {
2097  /* mark the connection as bad to report the parsing failure */
2098  conn->status = CONNECTION_BAD;
2099  return 0;
2100  }
2101 
2102  if (timeout > 0)
2103  {
2104  /*
2105  * Rounding could cause connection to fail unexpectedly quickly;
2106  * to prevent possibly waiting hardly-at-all, insist on at least
2107  * two seconds.
2108  */
2109  if (timeout < 2)
2110  timeout = 2;
2111  }
2112  else /* negative means 0 */
2113  timeout = 0;
2114  }
2115 
2116  for (;;)
2117  {
2118  int ret = 0;
2119 
2120  /*
2121  * (Re)start the connect_timeout timer if it's active and we are
2122  * considering a different host than we were last time through. If
2123  * we've already succeeded, though, needn't recalculate.
2124  */
2125  if (flag != PGRES_POLLING_OK &&
2126  timeout > 0 &&
2127  (conn->whichhost != last_whichhost ||
2128  conn->addr_cur != last_addr_cur))
2129  {
2130  finish_time = time(NULL) + timeout;
2131  last_whichhost = conn->whichhost;
2132  last_addr_cur = conn->addr_cur;
2133  }
2134 
2135  /*
2136  * Wait, if necessary. Note that the initial state (just after
2137  * PQconnectStart) is to wait for the socket to select for writing.
2138  */
2139  switch (flag)
2140  {
2141  case PGRES_POLLING_OK:
2142 
2143  /*
2144  * Reset stored error messages since we now have a working
2145  * connection
2146  */
2148  return 1; /* success! */
2149 
2150  case PGRES_POLLING_READING:
2151  ret = pqWaitTimed(1, 0, conn, finish_time);
2152  if (ret == -1)
2153  {
2154  /* hard failure, eg select() problem, aborts everything */
2155  conn->status = CONNECTION_BAD;
2156  return 0;
2157  }
2158  break;
2159 
2160  case PGRES_POLLING_WRITING:
2161  ret = pqWaitTimed(0, 1, conn, finish_time);
2162  if (ret == -1)
2163  {
2164  /* hard failure, eg select() problem, aborts everything */
2165  conn->status = CONNECTION_BAD;
2166  return 0;
2167  }
2168  break;
2169 
2170  default:
2171  /* Just in case we failed to set it in PQconnectPoll */
2172  conn->status = CONNECTION_BAD;
2173  return 0;
2174  }
2175 
2176  if (ret == 1) /* connect_timeout elapsed */
2177  {
2178  /*
2179  * Give up on current server/address, try the next one.
2180  */
2181  conn->try_next_addr = true;
2182  conn->status = CONNECTION_NEEDED;
2183  }
2184 
2185  /*
2186  * Now try to advance the state machine.
2187  */
2188  flag = PQconnectPoll(conn);
2189  }
2190 }
struct addrinfo * addr_cur
Definition: libpq-int.h:427
static bool parse_int_param(const char *value, int *result, PGconn *conn, const char *context)
Definition: fe-connect.c:1764
int pqWaitTimed(int forRead, int forWrite, PGconn *conn, time_t finish_time)
Definition: fe-misc.c:1038
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:2260
PQExpBufferData errorMessage
Definition: libpq-int.h:526
bool try_next_addr
Definition: libpq-int.h:424
ConnStatusType status
Definition: libpq-int.h:388
PostgresPollingStatusType
Definition: libpq-fe.h:74
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148
int whichhost
Definition: libpq-int.h:405

◆ connectDBStart()

static int connectDBStart ( PGconn conn)
static

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

References CONNECTION_BAD, CONNECTION_NEEDED, pg_conn::errorMessage, 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().

2005 {
2006  if (!conn)
2007  return 0;
2008 
2009  if (!conn->options_valid)
2010  goto connect_errReturn;
2011 
2012  /*
2013  * Check for bad linking to backend-internal versions of src/common
2014  * functions (see comments in link-canary.c for the reason we need this).
2015  * Nobody but developers should see this message, so we don't bother
2016  * translating it.
2017  */
2019  {
2021  "libpq is incorrectly linked to backend functions\n");
2022  goto connect_errReturn;
2023  }
2024 
2025  /* Ensure our buffers are empty */
2026  conn->inStart = conn->inCursor = conn->inEnd = 0;
2027  conn->outCount = 0;
2028 
2029  /*
2030  * Ensure errorMessage is empty, too. PQconnectPoll will append messages
2031  * to it in the process of scanning for a working server. Thus, if we
2032  * fail to connect to multiple hosts, the final error message will include
2033  * details about each failure.
2034  */
2036 
2037  /*
2038  * Set up to try to connect to the first host. (Setting whichhost = -1 is
2039  * a bit of a cheat, but PQconnectPoll will advance it to 0 before
2040  * anything else looks at it.)
2041  */
2042  conn->whichhost = -1;
2043  conn->try_next_addr = false;
2044  conn->try_next_host = true;
2045  conn->status = CONNECTION_NEEDED;
2046 
2047  /*
2048  * The code for processing CONNECTION_NEEDED state is in PQconnectPoll(),
2049  * so that it can easily be re-executed if needed again during the
2050  * asynchronous startup process. However, we must run it once here,
2051  * because callers expect a success return from this routine to mean that
2052  * we are in PGRES_POLLING_WRITING connection state.
2053  */
2054  if (PQconnectPoll(conn) == PGRES_POLLING_WRITING)
2055  return 1;
2056 
2057 connect_errReturn:
2058 
2059  /*
2060  * If we managed to open a socket, close it immediately rather than
2061  * waiting till PQfinish. (The application cannot have gotten the socket
2062  * from PQsocket yet, so this doesn't risk breaking anything.)
2063  */
2064  pqDropConnection(conn, true);
2065  conn->status = CONNECTION_BAD;
2066  return 0;
2067 }
int inEnd
Definition: libpq-int.h:448
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
int inStart
Definition: libpq-int.h:446
int outCount
Definition: libpq-int.h:453
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:459
bool try_next_host
Definition: libpq-int.h:425
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
Definition: fe-connect.c:2260
PQExpBufferData errorMessage
Definition: libpq-int.h:526
bool try_next_addr
Definition: libpq-int.h:424
bool options_valid
Definition: libpq-int.h:394
ConnStatusType status
Definition: libpq-int.h:388
int inCursor
Definition: libpq-int.h:447
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148
int whichhost
Definition: libpq-int.h:405

◆ connectFailureMessage()

static void connectFailureMessage ( PGconn conn,
int  errorno 
)
static

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

1672 {
1673  char sebuf[PG_STRERROR_R_BUFLEN];
1674 
1675 #ifdef HAVE_UNIX_SOCKETS
1676  if (IS_AF_UNIX(conn->raddr.addr.ss_family))
1677  {
1678  char service[NI_MAXHOST];
1679 
1680  pg_getnameinfo_all(&conn->raddr.addr, conn->raddr.salen,
1681  NULL, 0,
1682  service, sizeof(service),
1683  NI_NUMERICSERV);
1685  libpq_gettext("could not connect to server: %s\n"
1686  "\tIs the server running locally and accepting\n"
1687  "\tconnections on Unix domain socket \"%s\"?\n"),
1688  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
1689  service);
1690  }
1691  else
1692 #endif /* HAVE_UNIX_SOCKETS */
1693  {
1694  char host_addr[NI_MAXHOST];
1695  const char *displayed_host;
1696  const char *displayed_port;
1697 
1698  /*
1699  * Optionally display the network address with the hostname. This is
1700  * useful to distinguish between IPv4 and IPv6 connections.
1701  */
1702  getHostaddr(conn, host_addr, NI_MAXHOST);
1703 
1704  /* To which host and port were we actually connecting? */
1705  if (conn->connhost[conn->whichhost].type == CHT_HOST_ADDRESS)
1706  displayed_host = conn->connhost[conn->whichhost].hostaddr;
1707  else
1708  displayed_host = conn->connhost[conn->whichhost].host;
1709  displayed_port = conn->connhost[conn->whichhost].port;
1710  if (displayed_port == NULL || displayed_port[0] == '\0')
1711  displayed_port = DEF_PGPORT_STR;
1712 
1713  /*
1714  * If the user did not supply an IP address using 'hostaddr', and
1715  * 'host' was missing or does not match our lookup, display the
1716  * looked-up IP address.
1717  */
1718  if (conn->connhost[conn->whichhost].type != CHT_HOST_ADDRESS &&
1719  strlen(host_addr) > 0 &&
1720  strcmp(displayed_host, host_addr) != 0)
1722  libpq_gettext("could not connect to server: %s\n"
1723  "\tIs the server running on host \"%s\" (%s) and accepting\n"
1724  "\tTCP/IP connections on port %s?\n"),
1725  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
1726  displayed_host, host_addr,
1727  displayed_port);
1728  else
1730  libpq_gettext("could not connect to server: %s\n"
1731  "\tIs the server running on host \"%s\" and accepting\n"
1732  "\tTCP/IP connections on port %s?\n"),
1733  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
1734  displayed_host,
1735  displayed_port);
1736  }
1737 }
#define PG_STRERROR_R_BUFLEN
Definition: port.h:211
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:1639
#define SOCK_STRERROR
Definition: libpq-int.h:819
#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:406
ACCEPT_TYPE_ARG3 salen
Definition: pqcomm.h:65
SockAddr raddr
Definition: libpq-int.h:413
PQExpBufferData errorMessage
Definition: libpq-int.h:526
#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:405
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ connectNoDelay()

static int connectNoDelay ( PGconn conn)
static

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

1613 {
1614 #ifdef TCP_NODELAY
1615  int on = 1;
1616 
1617  if (setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY,
1618  (char *) &on,
1619  sizeof(on)) < 0)
1620  {
1621  char sebuf[PG_STRERROR_R_BUFLEN];
1622 
1624  libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
1625  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
1626  return 0;
1627  }
1628 #endif
1629 
1630  return 1;
1631 }
#define PG_STRERROR_R_BUFLEN
Definition: port.h:211
#define SOCK_STRERROR
Definition: libpq-int.h:819
#define SOCK_ERRNO
Definition: libpq-int.h:818
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
pgsocket sock
Definition: libpq-int.h:410
PQExpBufferData errorMessage
Definition: libpq-int.h:526
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ connectOptions1()

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

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

916 {
917  PQconninfoOption *connOptions;
918 
919  /*
920  * Parse the conninfo string
921  */
922  connOptions = parse_connection_string(conninfo, &conn->errorMessage, true);
923  if (connOptions == NULL)
924  {
925  conn->status = CONNECTION_BAD;
926  /* errorMessage is already set */
927  return false;
928  }
929 
930  /*
931  * Move option values into conn structure
932  */
933  if (!fillPGconn(conn, connOptions))
934  {
935  conn->status = CONNECTION_BAD;
936  PQconninfoFree(connOptions);
937  return false;
938  }
939 
940  /*
941  * Free the option info - all is in conn now
942  */
943  PQconninfoFree(connOptions);
944 
945  return true;
946 }
static PQconninfoOption * parse_connection_string(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5330
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6498
PQExpBufferData errorMessage
Definition: libpq-int.h:526
static bool fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
Definition: fe-connect.c:873
ConnStatusType status
Definition: libpq-int.h:388

◆ connectOptions2()

static bool connectOptions2 ( PGconn conn)
static

Definition at line 1013 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::ssl_max_protocol_version, pg_conn::ssl_min_protocol_version, pg_conn::sslmode, sslVerifyProtocolRange(), sslVerifyProtocolVersion(), pg_conn::status, pg_conn::target_session_attrs, pg_conn_host::type, and pg_conn::whichhost.

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

1014 {
1015  int i;
1016 
1017  /*
1018  * Allocate memory for details about each host to which we might possibly
1019  * try to connect. For that, count the number of elements in the hostaddr
1020  * or host options. If neither is given, assume one host.
1021  */
1022  conn->whichhost = 0;
1023  if (conn->pghostaddr && conn->pghostaddr[0] != '\0')
1025  else if (conn->pghost && conn->pghost[0] != '\0')
1027  else
1028  conn->nconnhost = 1;
1029  conn->connhost = (pg_conn_host *)
1030  calloc(conn->nconnhost, sizeof(pg_conn_host));
1031  if (conn->connhost == NULL)
1032  goto oom_error;
1033 
1034  /*
1035  * We now have one pg_conn_host structure per possible host. Fill in the
1036  * host and hostaddr fields for each, by splitting the parameter strings.
1037  */
1038  if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0')
1039  {
1040  char *s = conn->pghostaddr;
1041  bool more = true;
1042 
1043  for (i = 0; i < conn->nconnhost && more; i++)
1044  {
1045  conn->connhost[i].hostaddr = parse_comma_separated_list(&s, &more);
1046  if (conn->connhost[i].hostaddr == NULL)
1047  goto oom_error;
1048  }
1049 
1050  /*
1051  * If hostaddr was given, the array was allocated according to the
1052  * number of elements in the hostaddr list, so it really should be the
1053  * right size.
1054  */
1055  Assert(!more);
1056  Assert(i == conn->nconnhost);
1057  }
1058 
1059  if (conn->pghost != NULL && conn->pghost[0] != '\0')
1060  {
1061  char *s = conn->pghost;
1062  bool more = true;
1063 
1064  for (i = 0; i < conn->nconnhost && more; i++)
1065  {
1066  conn->connhost[i].host = parse_comma_separated_list(&s, &more);
1067  if (conn->connhost[i].host == NULL)
1068  goto oom_error;
1069  }
1070 
1071  /* Check for wrong number of host items. */
1072  if (more || i != conn->nconnhost)
1073  {
1074  conn->status = CONNECTION_BAD;
1076  libpq_gettext("could not match %d host names to %d hostaddr values\n"),
1078  return false;
1079  }
1080  }
1081 
1082  /*
1083  * Now, for each host slot, identify the type of address spec, and fill in
1084  * the default address if nothing was given.
1085  */
1086  for (i = 0; i < conn->nconnhost; i++)
1087  {
1088  pg_conn_host *ch = &conn->connhost[i];
1089 
1090  if (ch->hostaddr != NULL && ch->hostaddr[0] != '\0')
1091  ch->type = CHT_HOST_ADDRESS;
1092  else if (ch->host != NULL && ch->host[0] != '\0')
1093  {
1094  ch->type = CHT_HOST_NAME;
1095 #ifdef HAVE_UNIX_SOCKETS
1096  if (is_absolute_path(ch->host))
1097  ch->type = CHT_UNIX_SOCKET;
1098 #endif
1099  }
1100  else
1101  {
1102  if (ch->host)
1103  free(ch->host);
1104 #ifdef HAVE_UNIX_SOCKETS
1105  if (DEFAULT_PGSOCKET_DIR[0])
1106  {
1107  ch->host = strdup(DEFAULT_PGSOCKET_DIR);
1108  ch->type = CHT_UNIX_SOCKET;
1109  }
1110  else
1111 #endif
1112  {
1113  ch->host = strdup(DefaultHost);
1114  ch->type = CHT_HOST_NAME;
1115  }
1116  if (ch->host == NULL)
1117  goto oom_error;
1118  }
1119  }
1120 
1121  /*
1122  * Next, work out the port number corresponding to each host name.
1123  *
1124  * Note: unlike the above for host names, this could leave the port fields
1125  * as null or empty strings. We will substitute DEF_PGPORT whenever we
1126  * read such a port field.
1127  */
1128  if (conn->pgport != NULL && conn->pgport[0] != '\0')
1129  {
1130  char *s = conn->pgport;
1131  bool more = true;
1132 
1133  for (i = 0; i < conn->nconnhost && more; i++)
1134  {
1135  conn->connhost[i].port = parse_comma_separated_list(&s, &more);
1136  if (conn->connhost[i].port == NULL)
1137  goto oom_error;
1138  }
1139 
1140  /*
1141  * If exactly one port was given, use it for every host. Otherwise,
1142  * there must be exactly as many ports as there were hosts.
1143  */
1144  if (i == 1 && !more)
1145  {
1146  for (i = 1; i < conn->nconnhost; i++)
1147  {
1148  conn->connhost[i].port = strdup(conn->connhost[0].port);
1149  if (conn->connhost[i].port == NULL)
1150  goto oom_error;
1151  }
1152  }
1153  else if (more || i != conn->nconnhost)
1154  {
1155  conn->status = CONNECTION_BAD;
1157  libpq_gettext("could not match %d port numbers to %d hosts\n"),
1159  return false;
1160  }
1161  }
1162 
1163  /*
1164  * If user name was not given, fetch it. (Most likely, the fetch will
1165  * fail, since the only way we get here is if pg_fe_getauthname() failed
1166  * during conninfo_add_defaults(). But now we want an error message.)
1167  */
1168  if (conn->pguser == NULL || conn->pguser[0] == '\0')
1169  {
1170  if (conn->pguser)
1171  free(conn->pguser);
1172  conn->pguser = pg_fe_getauthname(&conn->errorMessage);
1173  if (!conn->pguser)
1174  {
1175  conn->status = CONNECTION_BAD;
1176  return false;
1177  }
1178  }
1179 
1180  /*
1181  * If database name was not given, default it to equal user name
1182  */
1183  if (conn->dbName == NULL || conn->dbName[0] == '\0')
1184  {
1185  if (conn->dbName)
1186  free(conn->dbName);
1187  conn->dbName = strdup(conn->pguser);
1188  if (!conn->dbName)
1189  goto oom_error;
1190  }
1191 
1192  /*
1193  * If password was not given, try to look it up in password file. Note
1194  * that the result might be different for each host/port pair.
1195  */
1196  if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
1197  {
1198  /* If password file wasn't specified, use ~/PGPASSFILE */
1199  if (conn->pgpassfile == NULL || conn->pgpassfile[0] == '\0')
1200  {
1201  char homedir[MAXPGPATH];
1202 
1203  if (pqGetHomeDirectory(homedir, sizeof(homedir)))
1204  {
1205  if (conn->pgpassfile)
1206  free(conn->pgpassfile);
1207  conn->pgpassfile = malloc(MAXPGPATH);
1208  if (!conn->pgpassfile)
1209  goto oom_error;
1210  snprintf(conn->pgpassfile, MAXPGPATH, "%s/%s",
1211  homedir, PGPASSFILE);
1212  }
1213  }
1214 
1215  if (conn->pgpassfile != NULL && conn->pgpassfile[0] != '\0')
1216  {
1217  for (i = 0; i < conn->nconnhost; i++)
1218  {
1219  /*
1220  * Try to get a password for this host from file. We use host
1221  * for the hostname search key if given, else hostaddr (at
1222  * least one of them is guaranteed nonempty by now).
1223  */
1224  const char *pwhost = conn->connhost[i].host;
1225 
1226  if (pwhost == NULL || pwhost[0] == '\0')
1227  pwhost = conn->connhost[i].hostaddr;
1228 
1229  conn->connhost[i].password =
1230  passwordFromFile(pwhost,
1231  conn->connhost[i].port,
1232  conn->dbName,
1233  conn->pguser,
1234  conn->pgpassfile);
1235  }
1236  }
1237  }
1238 
1239  /*
1240  * validate channel_binding option
1241  */
1242  if (conn->channel_binding)
1243  {
1244  if (strcmp(conn->channel_binding, "disable") != 0
1245  && strcmp(conn->channel_binding, "prefer") != 0
1246  && strcmp(conn->channel_binding, "require") != 0)
1247  {
1248  conn->status = CONNECTION_BAD;
1250  libpq_gettext("invalid %s value: \"%s\"\n"),
1251  "channel_binding", conn->channel_binding);
1252  return false;
1253  }
1254  }
1255  else
1256  {
1257  conn->channel_binding = strdup(DefaultChannelBinding);
1258  if (!conn->channel_binding)
1259  goto oom_error;
1260  }
1261 
1262  /*
1263  * validate sslmode option
1264  */
1265  if (conn->sslmode)
1266  {
1267  if (strcmp(conn->sslmode, "disable") != 0
1268  && strcmp(conn->sslmode, "allow") != 0
1269  && strcmp(conn->sslmode, "prefer") != 0
1270  && strcmp(conn->sslmode, "require") != 0
1271  && strcmp(conn->sslmode, "verify-ca") != 0
1272  && strcmp(conn->sslmode, "verify-full") != 0)
1273  {
1274  conn->status = CONNECTION_BAD;
1276  libpq_gettext("invalid %s value: \"%s\"\n"),
1277  "sslmode", conn->sslmode);
1278  return false;
1279  }
1280 
1281 #ifndef USE_SSL
1282  switch (conn->sslmode[0])
1283  {
1284  case 'a': /* "allow" */
1285  case 'p': /* "prefer" */
1286 
1287  /*
1288  * warn user that an SSL connection will never be negotiated
1289  * since SSL was not compiled in?
1290  */
1291  break;
1292 
1293  case 'r': /* "require" */
1294  case 'v': /* "verify-ca" or "verify-full" */
1295  conn->status = CONNECTION_BAD;
1297  libpq_gettext("sslmode value \"%s\" invalid when SSL support is not compiled in\n"),
1298  conn->sslmode);
1299  return false;
1300  }
1301 #endif
1302  }
1303  else
1304  {
1305  conn->sslmode = strdup(DefaultSSLMode);
1306  if (!conn->sslmode)
1307  goto oom_error;
1308  }
1309 
1310  /*
1311  * Validate TLS protocol versions for ssl_min_protocol_version and
1312  * ssl_max_protocol_version.
1313  */
1315  {
1316  conn->status = CONNECTION_BAD;
1318  libpq_gettext("invalid %s value: \"%s\"\n"),
1319  "ssl_min_protocol_version",
1320  conn->ssl_min_protocol_version);
1321  return false;
1322  }
1324  {
1325  conn->status = CONNECTION_BAD;
1327  libpq_gettext("invalid %s value: \"%s\"\n"),
1328  "ssl_max_protocol_version",
1329  conn->ssl_max_protocol_version);
1330  return false;
1331  }
1332 
1333  /*
1334  * Check if the range of SSL protocols defined is correct. This is done
1335  * at this early step because this is independent of the SSL
1336  * implementation used, and this avoids unnecessary cycles with an
1337  * already-built SSL context when the connection is being established, as
1338  * it would be doomed anyway.
1339  */
1341  conn->ssl_max_protocol_version))
1342  {
1343  conn->status = CONNECTION_BAD;
1345  libpq_gettext("invalid SSL protocol version range\n"));
1346  return false;
1347  }
1348 
1349  /*
1350  * validate gssencmode option
1351  */
1352  if (conn->gssencmode)
1353  {
1354  if (strcmp(conn->gssencmode, "disable") != 0 &&
1355  strcmp(conn->gssencmode, "prefer") != 0 &&
1356  strcmp(conn->gssencmode, "require") != 0)
1357  {
1358  conn->status = CONNECTION_BAD;
1360  libpq_gettext("invalid %s value: \"%s\"\n"),
1361  "gssencmode",
1362  conn->gssencmode);
1363  return false;
1364  }
1365 #ifndef ENABLE_GSS
1366  if (strcmp(conn->gssencmode, "require") == 0)
1367  {
1368  conn->status = CONNECTION_BAD;
1370  libpq_gettext("gssencmode value \"%s\" invalid when GSSAPI support is not compiled in\n"),
1371  conn->gssencmode);
1372  return false;
1373  }
1374 #endif
1375  }
1376  else
1377  {
1378  conn->gssencmode = strdup(DefaultGSSMode);
1379  if (!conn->gssencmode)
1380  goto oom_error;
1381  }
1382 
1383  /*
1384  * Resolve special "auto" client_encoding from the locale
1385  */
1386  if (conn->client_encoding_initial &&
1387  strcmp(conn->client_encoding_initial, "auto") == 0)
1388  {
1391  if (!conn->client_encoding_initial)
1392  goto oom_error;
1393  }
1394 
1395  /*
1396  * Validate target_session_attrs option.
1397  */
1398  if (conn->target_session_attrs)
1399  {
1400  if (strcmp(conn->target_session_attrs, "any") != 0
1401  && strcmp(conn->target_session_attrs, "read-write") != 0)
1402  {
1403  conn->status = CONNECTION_BAD;
1405  libpq_gettext("invalid %s value: \"%s\"\n"),
1406  "target_settion_attrs",
1407  conn->target_session_attrs);
1408  return false;
1409  }
1410  }
1411 
1412  /*
1413  * Only if we get this far is it appropriate to try to connect. (We need a
1414  * state flag, rather than just the boolean result of this function, in
1415  * case someone tries to PQreset() the PGconn.)
1416  */
1417  conn->options_valid = true;
1418 
1419  return true;
1420 
1421 oom_error:
1422  conn->status = CONNECTION_BAD;
1424  libpq_gettext("out of memory\n"));
1425  return false;
1426 }
#define calloc(a, b)
Definition: header.h:55
char * gssencmode
Definition: libpq-int.h:366
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
char * pgpassfile
Definition: libpq-int.h:349
char * host
Definition: libpq-int.h:312
char * dbName
Definition: libpq-int.h:345
static bool sslVerifyProtocolVersion(const char *version)
Definition: fe-connect.c:7093
char * ssl_min_protocol_version
Definition: libpq-int.h:370
#define DefaultSSLMode
Definition: fe-connect.c:135
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:81
#define MAXPGPATH
char * hostaddr
Definition: libpq-int.h:313
pg_conn_host * connhost
Definition: libpq-int.h:406
#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:952
char * target_session_attrs
Definition: libpq-int.h:374
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:526
static char * passwordFromFile(const char *hostname, const char *port, const char *dbname, const char *username, const char *pgpassfile)
Definition: fe-connect.c:6929
int pg_get_encoding_from_locale(const char *ctype, bool write_message)
Definition: chklocale.c:452
#define free(a)
Definition: header.h:65
const char * pg_encoding_to_char(int encoding)
Definition: encnames.c:588
bool options_valid
Definition: libpq-int.h:394
#define Assert(condition)
Definition: c.h:745
char * pgpass
Definition: libpq-int.h:348
ConnStatusType status
Definition: libpq-int.h:388
static char * parse_comma_separated_list(char **startptr, bool *more)
Definition: fe-connect.c:976
#define DefaultHost
Definition: fe-connect.c:122
char * pghostaddr
Definition: libpq-int.h:331
static bool sslVerifyProtocolRange(const char *min, const char *max)
Definition: fe-connect.c:7119
char * ssl_max_protocol_version
Definition: libpq-int.h:371
bool pqGetHomeDirectory(char *buf, int bufsize)
Definition: fe-connect.c:7172
int i
#define DefaultGSSMode
Definition: fe-connect.c:141
char * port
Definition: libpq-int.h:314
char * pgport
Definition: libpq-int.h:335
#define DefaultChannelBinding
Definition: fe-connect.c:129
int nconnhost
Definition: libpq-int.h:404
#define snprintf
Definition: port.h:193
int whichhost
Definition: libpq-int.h:405
#define libpq_gettext(x)
Definition: libpq-int.h:805
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 5726 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().

5727 {
5729  char *tmp;
5730 
5731  /*
5732  * If there's a service spec, use it to obtain any not-explicitly-given
5733  * parameters. Ignore error if no error message buffer is passed because
5734  * there is no way to pass back the failure message.
5735  */
5736  if (parseServiceInfo(options, errorMessage) != 0 && errorMessage)
5737  return false;
5738 
5739  /*
5740  * Get the fallback resources for parameters not specified in the conninfo
5741  * string nor the service.
5742  */
5743  for (option = options; option->keyword != NULL; option++)
5744  {
5745  if (option->val != NULL)
5746  continue; /* Value was in conninfo or service */
5747 
5748  /*
5749  * Try to get the environment variable fallback
5750  */
5751  if (option->envvar != NULL)
5752  {
5753  if ((tmp = getenv(option->envvar)) != NULL)
5754  {
5755  option->val = strdup(tmp);
5756  if (!option->val)
5757  {
5758  if (errorMessage)
5759  printfPQExpBuffer(errorMessage,
5760  libpq_gettext("out of memory\n"));
5761  return false;
5762  }
5763  continue;
5764  }
5765  }
5766 
5767  /*
5768  * Interpret the deprecated PGREQUIRESSL environment variable. Per
5769  * tradition, translate values starting with "1" to sslmode=require,
5770  * and ignore other values. Given both PGREQUIRESSL=1 and PGSSLMODE,
5771  * PGSSLMODE takes precedence; the opposite was true before v9.3.
5772  */
5773  if (strcmp(option->keyword, "sslmode") == 0)
5774  {
5775  const char *requiresslenv = getenv("PGREQUIRESSL");
5776 
5777  if (requiresslenv != NULL && requiresslenv[0] == '1')
5778  {
5779  option->val = strdup("require");
5780  if (!option->val)
5781  {
5782  if (errorMessage)
5783  printfPQExpBuffer(errorMessage,
5784  libpq_gettext("out of memory\n"));
5785  return false;
5786  }
5787  continue;
5788  }
5789  }
5790 
5791  /*
5792  * No environment variable specified or the variable isn't set - try
5793  * compiled-in default
5794  */
5795  if (option->compiled != NULL)
5796  {
5797  option->val = strdup(option->compiled);
5798  if (!option->val)
5799  {
5800  if (errorMessage)
5801  printfPQExpBuffer(errorMessage,
5802  libpq_gettext("out of memory\n"));
5803  return false;
5804  }
5805  continue;
5806  }
5807 
5808  /*
5809  * Special handling for "user" option. Note that if pg_fe_getauthname
5810  * fails, we just leave the value as NULL; there's no need for this to
5811  * be an error condition if the caller provides a user name. The only
5812  * reason we do this now at all is so that callers of PQconndefaults
5813  * will see a correct default (barring error, of course).
5814  */
5815  if (strcmp(option->keyword, "user") == 0)
5816  {
5817  option->val = pg_fe_getauthname(NULL);
5818  continue;
5819  }
5820  }
5821 
5822  return true;
5823 }
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:5026
#define libpq_gettext(x)
Definition: libpq-int.h:805

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

5565 {
5567  PQconninfoOption *dbname_options = NULL;
5569  int i = 0;
5570 
5571  /*
5572  * If expand_dbname is non-zero, check keyword "dbname" to see if val is
5573  * actually a recognized connection string.
5574  */
5575  while (expand_dbname && keywords[i])
5576  {
5577  const char *pname = keywords[i];
5578  const char *pvalue = values[i];
5579 
5580  /* first find "dbname" if any */
5581  if (strcmp(pname, "dbname") == 0 && pvalue)
5582  {
5583  /*
5584  * If value is a connection string, parse it, but do not use
5585  * defaults here -- those get picked up later. We only want to
5586  * override for those parameters actually passed.
5587  */
5588  if (recognized_connection_string(pvalue))
5589  {
5590  dbname_options = parse_connection_string(pvalue, errorMessage, false);
5591  if (dbname_options == NULL)
5592  return NULL;
5593  }
5594  break;
5595  }
5596  ++i;
5597  }
5598 
5599  /* Make a working copy of PQconninfoOptions */
5600  options = conninfo_init(errorMessage);
5601  if (options == NULL)
5602  {
5603  PQconninfoFree(dbname_options);
5604  return NULL;
5605  }
5606 
5607  /* Parse the keywords/values arrays */
5608  i = 0;
5609  while (keywords[i])
5610  {
5611  const char *pname = keywords[i];
5612  const char *pvalue = values[i];
5613 
5614  if (pvalue != NULL && pvalue[0] != '\0')
5615  {
5616  /* Search for the param record */
5617  for (option = options; option->keyword != NULL; option++)
5618  {
5619  if (strcmp(option->keyword, pname) == 0)
5620  break;
5621  }
5622 
5623  /* Check for invalid connection option */
5624  if (option->keyword == NULL)
5625  {
5626  printfPQExpBuffer(errorMessage,
5627  libpq_gettext("invalid connection option \"%s\"\n"),
5628  pname);
5629  PQconninfoFree(options);
5630  PQconninfoFree(dbname_options);
5631  return NULL;
5632  }
5633 
5634  /*
5635  * If we are on the first dbname parameter, and we have a parsed
5636  * connection string, copy those parameters across, overriding any
5637  * existing previous settings.
5638  */
5639  if (strcmp(pname, "dbname") == 0 && dbname_options)
5640  {
5641  PQconninfoOption *str_option;
5642 
5643  for (str_option = dbname_options; str_option->keyword != NULL; str_option++)
5644  {
5645  if (str_option->val != NULL)
5646  {
5647  int k;
5648 
5649  for (k = 0; options[k].keyword; k++)
5650  {
5651  if (strcmp(options[k].keyword, str_option->keyword) == 0)
5652  {
5653  if (options[k].val)
5654  free(options[k].val);
5655  options[k].val = strdup(str_option->val);
5656  if (!options[k].val)
5657  {
5658  printfPQExpBuffer(errorMessage,
5659  libpq_gettext("out of memory\n"));
5660  PQconninfoFree(options);
5661  PQconninfoFree(dbname_options);
5662  return NULL;
5663  }
5664  break;
5665  }
5666  }
5667  }
5668  }
5669 
5670  /*
5671  * Forget the parsed connection string, so that any subsequent
5672  * dbname parameters will not be expanded.
5673  */
5674  PQconninfoFree(dbname_options);
5675  dbname_options = NULL;
5676  }
5677  else
5678  {
5679  /*
5680  * Store the value, overriding previous settings
5681  */
5682  if (option->val)
5683  free(option->val);
5684  option->val = strdup(pvalue);
5685  if (!option->val)
5686  {
5687  printfPQExpBuffer(errorMessage,
5688  libpq_gettext("out of memory\n"));
5689  PQconninfoFree(options);
5690  PQconninfoFree(dbname_options);
5691  return NULL;
5692  }
5693  }
5694  }
5695  ++i;
5696  }
5697  PQconninfoFree(dbname_options);
5698 
5699  /*
5700  * Add in defaults if the caller wants that.
5701  */
5702  if (use_defaults)
5703  {
5704  if (!conninfo_add_defaults(options, errorMessage))
5705  {
5706  PQconninfoFree(options);
5707  return NULL;
5708  }
5709  }
5710 
5711  return options;
5712 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5290
static PQconninfoOption * parse_connection_string(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5330
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6498
static char ** options
static bool recognized_connection_string(const char *connstr)
Definition: fe-connect.c:5373
#define free(a)
Definition: header.h:65
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5726
static Datum values[MAXATTR]
Definition: bootstrap.c:165
int i
long val
Definition: informix.c:664
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ conninfo_find()

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

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

References _PQconninfoOption::keyword.

Referenced by conninfo_getval(), and conninfo_storeval().

6440 {
6442 
6443  for (option = connOptions; option->keyword != NULL; option++)
6444  {
6445  if (strcmp(option->keyword, keyword) == 0)
6446  return option;
6447  }
6448 
6449  return NULL;
6450 }

◆ conninfo_getval()

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

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

References conninfo_find(), and _PQconninfoOption::val.

Referenced by fillPGconn(), and parseServiceInfo().

6350 {
6352 
6353  option = conninfo_find(connOptions, keyword);
6354 
6355  return option ? option->val : NULL;
6356 }
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6439

◆ conninfo_init()

static PQconninfoOption * conninfo_init ( PQExpBuffer  errorMessage)
static

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

5291 {
5293  PQconninfoOption *opt_dest;
5294  const internalPQconninfoOption *cur_opt;
5295 
5296  /*
5297  * Get enough memory for all options in PQconninfoOptions, even if some
5298  * end up being filtered out.
5299  */
5300  options = (PQconninfoOption *) malloc(sizeof(PQconninfoOption) * sizeof(PQconninfoOptions) / sizeof(PQconninfoOptions[0]));
5301  if (options == NULL)
5302  {
5303  printfPQExpBuffer(errorMessage,
5304  libpq_gettext("out of memory\n"));
5305  return NULL;
5306  }
5307  opt_dest = options;
5308 
5309  for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++)
5310  {
5311  /* Only copy the public part of the struct, not the full internal */
5312  memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption));
5313  opt_dest++;
5314  }
5315  MemSet(opt_dest, 0, sizeof(PQconninfoOption));
5316 
5317  return options;
5318 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
#define MemSet(start, val, len)
Definition: c.h:949
#define malloc(a)
Definition: header.h:50
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:194
static char ** options
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ conninfo_parse()

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

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

5386 {
5387  char *pname;
5388  char *pval;
5389  char *buf;
5390  char *cp;
5391  char *cp2;
5393 
5394  /* Make a working copy of PQconninfoOptions */
5395  options = conninfo_init(errorMessage);
5396  if (options == NULL)
5397  return NULL;
5398 
5399  /* Need a modifiable copy of the input string */
5400  if ((buf = strdup(conninfo)) == NULL)
5401  {
5402  printfPQExpBuffer(errorMessage,
5403  libpq_gettext("out of memory\n"));
5404  PQconninfoFree(options);
5405  return NULL;
5406  }
5407  cp = buf;
5408 
5409  while (*cp)
5410  {
5411  /* Skip blanks before the parameter name */
5412  if (isspace((unsigned char) *cp))
5413  {
5414  cp++;
5415  continue;
5416  }
5417 
5418  /* Get the parameter name */
5419  pname = cp;
5420  while (*cp)
5421  {
5422  if (*cp == '=')
5423  break;
5424  if (isspace((unsigned char) *cp))
5425  {
5426  *cp++ = '\0';
5427  while (*cp)
5428  {
5429  if (!isspace((unsigned char) *cp))
5430  break;
5431  cp++;
5432  }
5433  break;
5434  }
5435  cp++;
5436  }
5437 
5438  /* Check that there is a following '=' */
5439  if (*cp != '=')
5440  {
5441  printfPQExpBuffer(errorMessage,
5442  libpq_gettext("missing \"=\" after \"%s\" in connection info string\n"),
5443  pname);
5444  PQconninfoFree(options);
5445  free(buf);
5446  return NULL;
5447  }
5448  *cp++ = '\0';
5449 
5450  /* Skip blanks after the '=' */
5451  while (*cp)
5452  {
5453  if (!isspace((unsigned char) *cp))
5454  break;
5455  cp++;
5456  }
5457 
5458  /* Get the parameter value */
5459  pval = cp;
5460 
5461  if (*cp != '\'')
5462  {
5463  cp2 = pval;
5464  while (*cp)
5465  {
5466  if (isspace((unsigned char) *cp))
5467  {
5468  *cp++ = '\0';
5469  break;
5470  }
5471  if (*cp == '\\')
5472  {
5473  cp++;
5474  if (*cp != '\0')
5475  *cp2++ = *cp++;
5476  }
5477  else
5478  *cp2++ = *cp++;
5479  }
5480  *cp2 = '\0';
5481  }
5482  else
5483  {
5484  cp2 = pval;
5485  cp++;
5486  for (;;)
5487  {
5488  if (*cp == '\0')
5489  {
5490  printfPQExpBuffer(errorMessage,
5491  libpq_gettext("unterminated quoted string in connection info string\n"));
5492  PQconninfoFree(options);
5493  free(buf);
5494  return NULL;
5495  }
5496  if (*cp == '\\')
5497  {
5498  cp++;
5499  if (*cp != '\0')
5500  *cp2++ = *cp++;
5501  continue;
5502  }
5503  if (*cp == '\'')
5504  {
5505  *cp2 = '\0';
5506  cp++;
5507  break;
5508  }
5509  *cp2++ = *cp++;
5510  }
5511  }
5512 
5513  /*
5514  * Now that we have the name and the value, store the record.
5515  */
5516  if (!conninfo_storeval(options, pname, pval, errorMessage, false, false))
5517  {
5518  PQconninfoFree(options);
5519  free(buf);
5520  return NULL;
5521  }
5522  }
5523 
5524  /* Done with the modifiable input string */
5525  free(buf);
5526 
5527  /*
5528  * Add in defaults if the caller wants that.
5529  */
5530  if (use_defaults)
5531  {
5532  if (!conninfo_add_defaults(options, errorMessage))
5533  {
5534  PQconninfoFree(options);
5535  return NULL;
5536  }
5537  }
5538 
5539  return options;
5540 }
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:6374
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5290
static char * buf
Definition: pg_test_fsync.c:68
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6498
static char ** options
#define free(a)
Definition: header.h:65
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5726
#define libpq_gettext(x)
Definition: libpq-int.h:805

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

6378 {
6380  char *value_copy;
6381 
6382  /*
6383  * For backwards compatibility, requiressl=1 gets translated to
6384  * sslmode=require, and requiressl=0 gets translated to sslmode=prefer
6385  * (which is the default for sslmode).
6386  */
6387  if (strcmp(keyword, "requiressl") == 0)
6388  {
6389  keyword = "sslmode";
6390  if (value[0] == '1')
6391  value = "require";
6392  else
6393  value = "prefer";
6394  }
6395 
6396  option = conninfo_find(connOptions, keyword);
6397  if (option == NULL)
6398  {
6399  if (!ignoreMissing)
6400  printfPQExpBuffer(errorMessage,
6401  libpq_gettext("invalid connection option \"%s\"\n"),
6402  keyword);
6403  return NULL;
6404  }
6405 
6406  if (uri_decode)
6407  {
6408  value_copy = conninfo_uri_decode(value, errorMessage);
6409  if (value_copy == NULL)
6410  /* conninfo_uri_decode already set an error message */
6411  return NULL;
6412  }
6413  else
6414  {
6415  value_copy = strdup(value);
6416  if (value_copy == NULL)
6417  {
6418  printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
6419  return NULL;
6420  }
6421  }
6422 
6423  if (option->val)
6424  free(option->val);
6425  option->val = value_copy;
6426 
6427  return option;
6428 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
static struct @142 value
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6439
static char * conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
Definition: fe-connect.c:6259
#define free(a)
Definition: header.h:65
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ conninfo_uri_decode()

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

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

6260 {
6261  char *buf;
6262  char *p;
6263  const char *q = str;
6264 
6265  buf = malloc(strlen(str) + 1);
6266  if (buf == NULL)
6267  {
6268  printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
6269  return NULL;
6270  }
6271  p = buf;
6272 
6273  for (;;)
6274  {
6275  if (*q != '%')
6276  {
6277  /* copy and check for NUL terminator */
6278  if (!(*(p++) = *(q++)))
6279  break;
6280  }
6281  else
6282  {
6283  int hi;
6284  int lo;
6285  int c;
6286 
6287  ++q; /* skip the percent sign itself */
6288 
6289  /*
6290  * Possible EOL will be caught by the first call to
6291  * get_hexdigit(), so we never dereference an invalid q pointer.
6292  */
6293  if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo)))
6294  {
6295  printfPQExpBuffer(errorMessage,
6296  libpq_gettext("invalid percent-encoded token: \"%s\"\n"),
6297  str);
6298  free(buf);
6299  return NULL;
6300  }
6301 
6302  c = (hi << 4) | lo;
6303  if (c == 0)
6304  {
6305  printfPQExpBuffer(errorMessage,
6306  libpq_gettext("forbidden value %%00 in percent-encoded value: \"%s\"\n"),
6307  str);
6308  free(buf);
6309  return NULL;
6310  }
6311  *(p++) = c;
6312  }
6313  }
6314 
6315  return buf;
6316 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
#define malloc(a)
Definition: header.h:50
char * c
static char * buf
Definition: pg_test_fsync.c:68
#define free(a)
Definition: header.h:65
static bool get_hexdigit(char digit, int *value)
Definition: fe-connect.c:6327
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ conninfo_uri_parse()

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

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

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

Referenced by parse_connection_string().

5833 {
5835 
5836  /* Make a working copy of PQconninfoOptions */
5837  options = conninfo_init(errorMessage);
5838  if (options == NULL)
5839  return NULL;
5840 
5841  if (!conninfo_uri_parse_options(options, uri, errorMessage))
5842  {
5843  PQconninfoFree(options);
5844  return NULL;
5845  }
5846 
5847  /*
5848  * Add in defaults if the caller wants that.
5849  */
5850  if (use_defaults)
5851  {
5852  if (!conninfo_add_defaults(options, errorMessage))
5853  {
5854  PQconninfoFree(options);
5855  return NULL;
5856  }
5857  }
5858 
5859  return options;
5860 }
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5290
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6498
static bool conninfo_uri_parse_options(PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage)
Definition: fe-connect.c:5884
static char ** options
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5726

◆ conninfo_uri_parse_options()

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

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

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

◆ conninfo_uri_parse_params()

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

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

6131 {
6132  while (*params)
6133  {
6134  char *keyword = params;
6135  char *value = NULL;
6136  char *p = params;
6137  bool malloced = false;
6138 
6139  /*
6140  * Scan the params string for '=' and '&', marking the end of keyword
6141  * and value respectively.
6142  */
6143  for (;;)
6144  {
6145  if (*p == '=')
6146  {
6147  /* Was there '=' already? */
6148  if (value != NULL)
6149  {
6150  printfPQExpBuffer(errorMessage,
6151  libpq_gettext("extra key/value separator \"=\" in URI query parameter: \"%s\"\n"),
6152  keyword);
6153  return false;
6154  }
6155  /* Cut off keyword, advance to value */
6156  *p++ = '\0';
6157  value = p;
6158  }
6159  else if (*p == '&' || *p == '\0')
6160  {
6161  /*
6162  * If not at the end, cut off value and advance; leave p
6163  * pointing to start of the next parameter, if any.
6164  */
6165  if (*p != '\0')
6166  *p++ = '\0';
6167  /* Was there '=' at all? */
6168  if (value == NULL)
6169  {
6170  printfPQExpBuffer(errorMessage,
6171  libpq_gettext("missing key/value separator \"=\" in URI query parameter: \"%s\"\n"),
6172  keyword);
6173  return false;
6174  }
6175  /* Got keyword and value, go process them. */
6176  break;
6177  }
6178  else
6179  ++p; /* Advance over all other bytes. */
6180  }
6181 
6182  keyword = conninfo_uri_decode(keyword, errorMessage);
6183  if (keyword == NULL)
6184  {
6185  /* conninfo_uri_decode already set an error message */
6186  return false;
6187  }
6188  value = conninfo_uri_decode(value, errorMessage);
6189  if (value == NULL)
6190  {
6191  /* conninfo_uri_decode already set an error message */
6192  free(keyword);
6193  return false;
6194  }
6195  malloced = true;
6196 
6197  /*
6198  * Special keyword handling for improved JDBC compatibility.
6199  */
6200  if (strcmp(keyword, "ssl") == 0 &&
6201  strcmp(value, "true") == 0)
6202  {
6203  free(keyword);
6204  free(value);
6205  malloced = false;
6206 
6207  keyword = "sslmode";
6208  value = "require";
6209  }
6210 
6211  /*
6212  * Store the value if the corresponding option exists; ignore
6213  * otherwise. At this point both keyword and value are not
6214  * URI-encoded.
6215  */
6216  if (!conninfo_storeval(connOptions, keyword, value,
6217  errorMessage, true, false))
6218  {
6219  /* Insert generic message if conninfo_storeval didn't give one. */
6220  if (errorMessage->len == 0)
6221  printfPQExpBuffer(errorMessage,
6222  libpq_gettext("invalid URI query parameter: \"%s\"\n"),
6223  keyword);
6224  /* And fail. */
6225  if (malloced)
6226  {
6227  free(keyword);
6228  free(value);
6229  }
6230  return false;
6231  }
6232 
6233  if (malloced)
6234  {
6235  free(keyword);
6236  free(value);
6237  }
6238 
6239  /* Proceed to next key=value pair, if any */
6240  params = p;
6241  }
6242 
6243  return true;
6244 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
static struct @142 value
static PQconninfoOption * conninfo_storeval(PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode)
Definition: fe-connect.c:6374
static char * conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
Definition: fe-connect.c:6259
#define free(a)
Definition: header.h:65
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ count_comma_separated_elems()

static int count_comma_separated_elems ( const char *  input)
static

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

Referenced by connectOptions2().

953 {
954  int n;
955 
956  n = 1;
957  for (; *input != '\0'; input++)
958  {
959  if (*input == ',')
960  n++;
961  }
962 
963  return n;
964 }

◆ default_threadlock()

static void default_threadlock ( int  acquire)
static

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

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

Referenced by PQregisterThreadLock().

7202 {
7203 #ifdef ENABLE_THREAD_SAFETY
7204 #ifndef WIN32
7205  static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
7206 #else
7207  static pthread_mutex_t singlethread_lock = NULL;
7208  static long mutex_initlock = 0;
7209 
7210  if (singlethread_lock == NULL)
7211  {
7212  while (InterlockedExchange(&mutex_initlock, 1) == 1)
7213  /* loop, another thread own the lock */ ;
7214  if (singlethread_lock == NULL)
7215  {
7216  if (pthread_mutex_init(&singlethread_lock, NULL))
7217  PGTHREAD_ERROR("failed to initialize mutex");
7218  }
7219  InterlockedExchange(&mutex_initlock, 0);
7220  }
7221 #endif
7222  if (acquire)
7223  {
7224  if (pthread_mutex_lock(&singlethread_lock))
7225  PGTHREAD_ERROR("failed to lock mutex");
7226  }
7227  else
7228  {
7229  if (pthread_mutex_unlock(&singlethread_lock))
7230  PGTHREAD_ERROR("failed to unlock mutex");
7231  }
7232 #endif
7233 }
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 6880 of file fe-connect.c.

References fprintf.

Referenced by makeEmptyPGconn().

6881 {
6882  (void) arg; /* not used */
6883  /* Note: we expect the supplied string to end with a newline already. */
6884  fprintf(stderr, "%s", message);
6885 }
#define fprintf
Definition: port.h:197
void * arg

◆ defaultNoticeReceiver()

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

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

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

Referenced by makeEmptyPGconn().

6866 {
6867  (void) arg; /* not used */
6868  if (res->noticeHooks.noticeProc != NULL)
6870  PQresultErrorMessage(res));
6871 }
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 873 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().

874 {
876 
877  for (option = PQconninfoOptions; option->keyword; option++)
878  {
879  if (option->connofs >= 0)
880  {
881  const char *tmp = conninfo_getval(connOptions, option->keyword);
882 
883  if (tmp)
884  {
885  char **connmember = (char **) ((char *) conn + option->connofs);
886 
887  if (*connmember)
888  free(*connmember);
889  *connmember = strdup(tmp);
890  if (*connmember == NULL)
891  {
893  libpq_gettext("out of memory\n"));
894  return false;
895  }
896  }
897  }
898  }
899 
900  return true;
901 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:194
PQExpBufferData errorMessage
Definition: libpq-int.h:526
#define free(a)
Definition: header.h:65
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6348
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ freePGconn()

static void freePGconn ( PGconn conn)
static

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

References pg_conn::appname, pg_conn::channel_binding, pg_conn::client_encoding_initial, PGEventConnDestroy::conn, conn, pg_conn::connect_timeout, pg_conn::connhost, pg_conn::connip, pg_conn::dbName, pg_conn::errorMessage, pg_conn::events, explicit_bzero(), pg_conn::fbappname, free, pg_conn::gssencmode, pg_conn::gsslib, pg_conn_host::host, pg_conn_host::hostaddr, i, pg_conn::inBuffer, pg_conn::keepalives, pg_conn::keepalives_count, pg_conn::keepalives_idle, pg_conn::keepalives_interval, pg_conn::krbsrvname, pg_conn::last_query, PGEvent::name, pg_conn::nconnhost, pg_conn::nEvents, pg_conn::outBuffer, PGEvent::passThrough, pg_conn_host::password, PGEVT_CONNDESTROY, pg_conn::pghost, pg_conn::pghostaddr, pg_conn::pgoptions, pg_conn::pgpass, pg_conn::pgpassfile, pg_conn::pgport, pg_conn::pgtcp_user_timeout, pg_conn::pgtty, pg_conn::pguser, pg_conn_host::port, PGEvent::proc, pg_conn::replication, pg_conn::requirepeer, pg_conn::rowBuf, pg_conn::ssl_max_protocol_version, pg_conn::ssl_min_protocol_version, 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().

3956 {
3957  int i;
3958 
3959  /* let any event procs clean up their state data */
3960  for (i = 0; i < conn->nEvents; i++)
3961  {
3962  PGEventConnDestroy evt;
3963 
3964  evt.conn = conn;
3965  (void) conn->events[i].proc(PGEVT_CONNDESTROY, &evt,
3966  conn->events[i].passThrough);
3967  free(conn->events[i].name);
3968  }
3969 
3970  /* clean up pg_conn_host structures */
3971  if (conn->connhost != NULL)
3972  {
3973  for (i = 0; i < conn->nconnhost; ++i)
3974  {
3975  if (conn->connhost[i].host != NULL)
3976  free(conn->connhost[i].host);
3977  if (conn->connhost[i].hostaddr != NULL)
3978  free(conn->connhost[i].hostaddr);
3979  if (conn->connhost[i].port != NULL)
3980  free(conn->connhost[i].port);
3981  if (conn->connhost[i].password != NULL)
3982  {
3983  explicit_bzero(conn->connhost[i].password, strlen(conn->connhost[i].password));
3984  free(conn->connhost[i].password);
3985  }
3986  }
3987  free(conn->connhost);
3988  }
3989 
3990  if (conn->client_encoding_initial)
3992  if (conn->events)
3993  free(conn->events);
3994  if (conn->pghost)
3995  free(conn->pghost);
3996  if (conn->pghostaddr)
3997  free(conn->pghostaddr);
3998  if (conn->pgport)
3999  free(conn->pgport);
4000  if (conn->pgtty)
4001  free(conn->pgtty);
4002  if (conn->connect_timeout)
4003  free(conn->connect_timeout);
4004  if (conn->pgtcp_user_timeout)
4005  free(conn->pgtcp_user_timeout);
4006  if (conn->pgoptions)
4007  free(conn->pgoptions);
4008  if (conn->appname)
4009  free(conn->appname);
4010  if (conn->fbappname)
4011  free(conn->fbappname);
4012  if (conn->dbName)
4013  free(conn->dbName);
4014  if (conn->replication)
4015  free(conn->replication);
4016  if (conn->pguser)
4017  free(conn->pguser);
4018  if (conn->pgpass)
4019  {
4020  explicit_bzero(conn->pgpass, strlen(conn->pgpass));
4021  free(conn->pgpass);
4022  }
4023  if (conn->pgpassfile)
4024  free(conn->pgpassfile);
4025  if (conn->channel_binding)
4026  free(conn->channel_binding);
4027  if (conn->keepalives)
4028  free(conn->keepalives);
4029  if (conn->keepalives_idle)
4030  free(conn->keepalives_idle);
4031  if (conn->keepalives_interval)
4032  free(conn->keepalives_interval);
4033  if (conn->keepalives_count)
4034  free(conn->keepalives_count);
4035  if (conn->sslmode)
4036  free(conn->sslmode);
4037  if (conn->sslcert)
4038  free(conn->sslcert);
4039  if (conn->sslkey)
4040  free(conn->sslkey);
4041  if (conn->sslpassword)
4042  {
4043  explicit_bzero(conn->sslpassword, strlen(conn->sslpassword));
4044  free(conn->sslpassword);
4045  }
4046  if (conn->sslrootcert)
4047  free(conn->sslrootcert);
4048  if (conn->sslcrl)
4049  free(conn->sslcrl);
4050  if (conn->sslcompression)
4051  free(conn->sslcompression);
4052  if (conn->requirepeer)
4053  free(conn->requirepeer);
4054  if (conn->ssl_min_protocol_version)
4056  if (conn->ssl_max_protocol_version)
4058  if (conn->gssencmode)
4059  free(conn->gssencmode);
4060  if (conn->krbsrvname)
4061  free(conn->krbsrvname);
4062  if (conn->gsslib)
4063  free(conn->gsslib);
4064  if (conn->connip)
4065  free(conn->connip);
4066  /* Note that conn->Pfdebug is not ours to close or free */
4067  if (conn->last_query)
4068  free(conn->last_query);
4069  if (conn->write_err_msg)
4070  free(conn->write_err_msg);
4071  if (conn->inBuffer)
4072  free(conn->inBuffer);
4073  if (conn->outBuffer)
4074  free(conn->outBuffer);
4075  if (conn->rowBuf)
4076  free(conn->rowBuf);
4077  if (conn->target_session_attrs)
4078  free(conn->target_session_attrs);
4079  termPQExpBuffer(&conn->errorMessage);
4080  termPQExpBuffer(&conn->workBuffer);
4081 
4082  free(conn);
4083 
4084 #ifdef WIN32
4085  WSACleanup();
4086 #endif
4087 }
char * gssencmode
Definition: libpq-int.h:366
PGEvent * events
Definition: libpq-int.h:383
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:529
char * requirepeer
Definition: libpq-int.h:365
char * host
Definition: libpq-int.h:312
char * dbName
Definition: libpq-int.h:345
char * ssl_min_protocol_version
Definition: libpq-int.h:370
char * keepalives
Definition: libpq-int.h:352
char * write_err_msg
Definition: libpq-int.h:421
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:406
char * keepalives_interval
Definition: libpq-int.h:354
char * appname
Definition: libpq-int.h:343
char * sslpassword
Definition: libpq-int.h:362
char * krbsrvname
Definition: libpq-int.h:367
char * channel_binding
Definition: libpq-int.h:350
char * target_session_attrs
Definition: libpq-int.h:374
char * last_query
Definition: libpq-int.h:392
PGdataValue * rowBuf
Definition: libpq-int.h:461
char * pguser
Definition: libpq-int.h:347
char * gsslib
Definition: libpq-int.h:368
char * inBuffer
Definition: libpq-int.h:444
char * sslmode
Definition: libpq-int.h:358
PQExpBufferData errorMessage
Definition: libpq-int.h:526
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:407
char * pgpass
Definition: libpq-int.h:348
char * sslrootcert
Definition: libpq-int.h:363
PGEventProc proc
Definition: libpq-int.h:160
char * outBuffer
Definition: libpq-int.h:451
char * pghostaddr
Definition: libpq-int.h:331
void explicit_bzero(void *buf, size_t len)
char * ssl_max_protocol_version
Definition: libpq-int.h:371
int nEvents
Definition: libpq-int.h:384
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:404
char * name
Definition: libpq-int.h:161
char * pgtcp_user_timeout
Definition: libpq-int.h:340
char * sslcrl
Definition: libpq-int.h:364
char * keepalives_count
Definition: libpq-int.h:356
char * pghost
Definition: libpq-int.h:327
char * pgtty
Definition: libpq-int.h:337
char * password
Definition: libpq-int.h:315

◆ get_hexdigit()

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

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

Referenced by conninfo_uri_decode().

6328 {
6329  if ('0' <= digit && digit <= '9')
6330  *value = digit - '0';
6331  else if ('A' <= digit && digit <= 'F')
6332  *value = digit - 'A' + 10;
6333  else if ('a' <= digit && digit <= 'f')
6334  *value = digit - 'a' + 10;
6335  else
6336  return false;
6337 
6338  return true;
6339 }
static struct @142 value

◆ getHostaddr()

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

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

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

Referenced by connectFailureMessage(), and PQconnectPoll().

1640 {
1641  struct sockaddr_storage *addr = &conn->raddr.addr;
1642 
1643  if (addr->ss_family == AF_INET)
1644  {
1645  if (pg_inet_net_ntop(AF_INET,
1646  &((struct sockaddr_in *) addr)->sin_addr.s_addr,
1647  32,
1648  host_addr, host_addr_len) == NULL)
1649  host_addr[0] = '\0';
1650  }
1651 #ifdef HAVE_IPV6
1652  else if (addr->ss_family == AF_INET6)
1653  {
1654  if (pg_inet_net_ntop(AF_INET6,
1655  &((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr,
1656  128,
1657  host_addr, host_addr_len) == NULL)
1658  host_addr[0] = '\0';
1659  }
1660 #endif
1661  else
1662  host_addr[0] = '\0';
1663 }
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:413

◆ internal_cancel()

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

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

4345 {
4346  int save_errno = SOCK_ERRNO;
4347  pgsocket tmpsock = PGINVALID_SOCKET;
4348  char sebuf[PG_STRERROR_R_BUFLEN];
4349  int maxlen;
4350  struct
4351  {
4352  uint32 packetlen;
4354  } crp;
4355 
4356  /*
4357  * We need to open a temporary connection to the postmaster. Do this with
4358  * only kernel calls.
4359  */
4360  if ((tmpsock = socket(raddr->addr.ss_family, SOCK_STREAM, 0)) == PGINVALID_SOCKET)
4361  {
4362  strlcpy(errbuf, "PQcancel() -- socket() failed: ", errbufsize);
4363  goto cancel_errReturn;
4364  }
4365 retry3:
4366  if (connect(tmpsock, (struct sockaddr *) &raddr->addr,
4367  raddr->salen) < 0)
4368  {
4369  if (SOCK_ERRNO == EINTR)
4370  /* Interrupted system call - we'll just try again */
4371  goto retry3;
4372  strlcpy(errbuf, "PQcancel() -- connect() failed: ", errbufsize);
4373  goto cancel_errReturn;
4374  }
4375 
4376  /*
4377  * We needn't set nonblocking I/O or NODELAY options here.
4378  */
4379 
4380  /* Create and send the cancel request packet. */
4381 
4382  crp.packetlen = pg_hton32((uint32) sizeof(crp));
4383  crp.cp.cancelRequestCode = (MsgType) pg_hton32(CANCEL_REQUEST_CODE);
4384  crp.cp.backendPID = pg_hton32(be_pid);
4385  crp.cp.cancelAuthCode = pg_hton32(be_key);
4386 
4387 retry4:
4388  if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp))
4389  {
4390  if (SOCK_ERRNO == EINTR)
4391  /* Interrupted system call - we'll just try again */
4392  goto retry4;
4393  strlcpy(errbuf, "PQcancel() -- send() failed: ", errbufsize);
4394  goto cancel_errReturn;
4395  }
4396 
4397  /*
4398  * Wait for the postmaster to close the connection, which indicates that
4399  * it's processed the request. Without this delay, we might issue another
4400  * command only to find that our cancel zaps that command instead of the
4401  * one we thought we were canceling. Note we don't actually expect this
4402  * read to obtain any data, we are just waiting for EOF to be signaled.
4403  */
4404 retry5:
4405  if (recv(tmpsock, (char *) &crp, 1, 0) < 0)
4406  {
4407  if (SOCK_ERRNO == EINTR)
4408  /* Interrupted system call - we'll just try again */
4409  goto retry5;
4410  /* we ignore other error conditions */
4411  }
4412 
4413  /* All done */
4414  closesocket(tmpsock);
4415  SOCK_ERRNO_SET(save_errno);
4416  return true;
4417 
4418 cancel_errReturn:
4419 
4420  /*
4421  * Make sure we don't overflow the error buffer. Leave space for the \n at
4422  * the end, and for the terminating zero.
4423  */
4424  maxlen = errbufsize - strlen(errbuf) - 2;
4425  if (maxlen >= 0)
4426  {
4427  strncat(errbuf, SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)),
4428  maxlen);
4429  strcat(errbuf, "\n");
4430  }
4431  if (tmpsock != PGINVALID_SOCKET)
4432  closesocket(tmpsock);
4433  SOCK_ERRNO_SET(save_errno);
4434  return false;
4435 }
#define closesocket
Definition: port.h:309
#define PG_STRERROR_R_BUFLEN
Definition: port.h:211
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:819
#define pg_hton32(x)
Definition: pg_bswap.h:121
#define SOCK_ERRNO
Definition: libpq-int.h:818
unsigned int uint32
Definition: c.h:374
int pgsocket
Definition: port.h:31
ACCEPT_TYPE_ARG3 salen
Definition: pqcomm.h:65
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:820
#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 3802 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().

3803 {
3804  /* Say "no attempt" if we never got to PQconnectPoll */
3805  if (!conn || !conn->options_valid)
3806  return PQPING_NO_ATTEMPT;
3807 
3808  /* Attempt to complete the connection */
3809  if (conn->status != CONNECTION_BAD)
3810  (void) connectDBComplete(conn);
3811 
3812  /* Definitely OK if we succeeded */
3813  if (conn->status != CONNECTION_BAD)
3814  return PQPING_OK;
3815 
3816  /*
3817  * Here begins the interesting part of "ping": determine the cause of the
3818  * failure in sufficient detail to decide what to return. We do not want
3819  * to report that the server is not up just because we didn't have a valid
3820  * password, for example. In fact, any sort of authentication request
3821  * implies the server is up. (We need this check since the libpq side of
3822  * things might have pulled the plug on the connection before getting an
3823  * error as such from the postmaster.)
3824  */
3825  if (conn->auth_req_received)
3826  return PQPING_OK;
3827 
3828  /*
3829  * If we failed to get any ERROR response from the postmaster, report
3830  * PQPING_NO_RESPONSE. This result could be somewhat misleading for a
3831  * pre-7.4 server, since it won't send back a SQLSTATE, but those are long
3832  * out of support. Another corner case where the server could return a
3833  * failure without a SQLSTATE is fork failure, but PQPING_NO_RESPONSE
3834  * isn't totally unreasonable for that anyway. We expect that every other
3835  * failure case in a modern server will produce a report with a SQLSTATE.
3836  *
3837  * NOTE: whenever we get around to making libpq generate SQLSTATEs for
3838  * client-side errors, we should either not store those into
3839  * last_sqlstate, or add an extra flag so we can tell client-side errors
3840  * apart from server-side ones.
3841  */
3842  if (strlen(conn->last_sqlstate) != 5)
3843  return PQPING_NO_RESPONSE;
3844 
3845  /*
3846  * Report PQPING_REJECT if server says it's not accepting connections. (We
3847  * distinguish this case mainly for the convenience of pg_ctl.)
3848  */
3849  if (strcmp(conn->last_sqlstate, ERRCODE_CANNOT_CONNECT_NOW) == 0)
3850  return PQPING_REJECT;
3851 
3852  /*
3853  * Any other SQLSTATE can be taken to indicate that the server is up.
3854  * Presumably it didn't like our username, password, or database name; or
3855  * perhaps it had some transient failure, but that should not be taken as
3856  * meaning "it's down".
3857  */
3858  return PQPING_OK;
3859 }
static int connectDBComplete(PGconn *conn)
Definition: fe-connect.c:2078
bool options_valid
Definition: libpq-int.h:394
#define ERRCODE_CANNOT_CONNECT_NOW
Definition: fe-connect.c:97
ConnStatusType status
Definition: libpq-int.h:388
bool auth_req_received
Definition: libpq-int.h:416
char last_sqlstate[6]
Definition: libpq-int.h:393

◆ makeEmptyPGconn()

static PGconn * makeEmptyPGconn ( void  )
static

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

3868 {
3869  PGconn *conn;
3870 
3871 #ifdef WIN32
3872 
3873  /*
3874  * Make sure socket support is up and running.
3875  */
3876  WSADATA wsaData;
3877 
3878  if (WSAStartup(MAKEWORD(1, 1), &wsaData))
3879  return NULL;
3880  WSASetLastError(0);
3881 #endif
3882 
3883  conn = (PGconn *) malloc(sizeof(PGconn));
3884  if (conn == NULL)
3885  {
3886 #ifdef WIN32
3887  WSACleanup();
3888 #endif
3889  return conn;
3890  }
3891 
3892  /* Zero all pointers and booleans */
3893  MemSet(conn, 0, sizeof(PGconn));
3894 
3895  /* install default notice hooks */
3898 
3899  conn->status = CONNECTION_BAD;
3900  conn->asyncStatus = PGASYNC_IDLE;
3901  conn->xactStatus = PQTRANS_IDLE;
3902  conn->options_valid = false;
3903  conn->nonblocking = false;
3905  conn->client_encoding = PG_SQL_ASCII;
3906  conn->std_strings = false; /* unless server says differently */
3907  conn->verbosity = PQERRORS_DEFAULT;
3909  conn->sock = PGINVALID_SOCKET;
3910 
3911  /*
3912  * We try to send at least 8K at a time, which is the usual size of pipe
3913  * buffers on Unix systems. That way, when we are sending a large amount
3914  * of data, we avoid incurring extra kernel context swaps for partial
3915  * bufferloads. The output buffer is initially made 16K in size, and we
3916  * try to dump it after accumulating 8K.
3917  *
3918  * With the same goal of minimizing context swaps, the input buffer will
3919  * be enlarged anytime it has less than 8K free, so we initially allocate
3920  * twice that.
3921  */
3922  conn->inBufSize = 16 * 1024;
3923  conn->inBuffer = (char *) malloc(conn->inBufSize);
3924  conn->outBufSize = 16 * 1024;
3925  conn->outBuffer = (char *) malloc(conn->outBufSize);
3926  conn->rowBufLen = 32;
3927  conn->rowBuf = (PGdataValue *) malloc(conn->rowBufLen * sizeof(PGdataValue));
3928  initPQExpBuffer(&conn->errorMessage);
3929  initPQExpBuffer(&conn->workBuffer);
3930 
3931  if (conn->inBuffer == NULL ||
3932  conn->outBuffer == NULL ||
3933  conn->rowBuf == NULL ||
3934  PQExpBufferBroken(&conn->errorMessage) ||
3935  PQExpBufferBroken(&conn->workBuffer))
3936  {
3937  /* out of memory already :-( */
3938  freePGconn(conn);
3939  conn = NULL;
3940  }
3941 
3942  return conn;
3943 }
PGContextVisibility show_context
Definition: libpq-int.h:440
int rowBufLen
Definition: libpq-int.h:462
PQExpBufferData workBuffer
Definition: libpq-int.h:529
#define MemSet(start, val, len)
Definition: c.h:949
#define malloc(a)
Definition: header.h:50
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:389
PGSetenvStatusType setenv_state
Definition: libpq-int.h:429
PGconn * conn
Definition: streamutil.c:54
int inBufSize
Definition: libpq-int.h:445
PGNoticeHooks noticeHooks
Definition: libpq-int.h:380
PGVerbosity verbosity
Definition: libpq-int.h:439
PQnoticeReceiver noticeRec
Definition: libpq-int.h:152
PGdataValue * rowBuf
Definition: libpq-int.h:461
pgsocket sock
Definition: libpq-int.h:410
#define PGINVALID_SOCKET
Definition: port.h:33
char * inBuffer
Definition: libpq-int.h:444
PQnoticeProcessor noticeProc
Definition: libpq-int.h:154
static void freePGconn(PGconn *conn)
Definition: fe-connect.c:3955
PQExpBufferData errorMessage
Definition: libpq-int.h:526
bool std_strings
Definition: libpq-int.h:438
bool options_valid
Definition: libpq-int.h:394
int outBufSize
Definition: libpq-int.h:452
#define PQExpBufferBroken(str)
Definition: pqexpbuffer.h:59
ConnStatusType status
Definition: libpq-int.h:388
char * outBuffer
Definition: libpq-int.h:451
bool nonblocking
Definition: libpq-int.h:395
static void defaultNoticeProcessor(void *arg, const char *message)
Definition: fe-connect.c:6880
int client_encoding
Definition: libpq-int.h:437
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
static void defaultNoticeReceiver(void *arg, const PGresult *res)
Definition: fe-connect.c:6865
PGTransactionStatusType xactStatus
Definition: libpq-int.h:390

◆ parse_comma_separated_list()

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

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

References malloc, and startptr.

Referenced by connectOptions2().

977 {
978  char *p;
979  char *s = *startptr;
980  char *e;
981  int len;
982 
983  /*
984  * Search for the end of the current element; a comma or end-of-string
985  * acts as a terminator.
986  */
987  e = s;
988  while (*e != '\0' && *e != ',')
989  ++e;
990  *more = (*e == ',');
991 
992  len = e - s;
993  p = (char *) malloc(sizeof(char) * (len + 1));
994  if (p)
995  {
996  memcpy(p, s, len);
997  p[len] = '\0';
998  }
999  *startptr = e + 1;
1000 
1001  return p;
1002 }
#define malloc(a)
Definition: header.h:50
e
Definition: preproc-init.c:82
static XLogRecPtr startptr
Definition: basebackup.c:116

◆ parse_connection_string()

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

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

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

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

5332 {
5333  /* Parse as URI if connection string matches URI prefix */
5334  if (uri_prefix_length(connstr) != 0)
5335  return conninfo_uri_parse(connstr, errorMessage, use_defaults);
5336 
5337  /* Parse as default otherwise */
5338  return conninfo_parse(connstr, errorMessage, use_defaults);
5339 }
static PQconninfoOption * conninfo_parse(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5384
static int uri_prefix_length(const char *connstr)
Definition: fe-connect.c:5350
static PQconninfoOption * conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5831
static char * connstr
Definition: pg_dumpall.c:62

◆ parse_int_param()

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

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

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

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

1766 {
1767  char *end;
1768  long numval;
1769 
1770  Assert(value != NULL);
1771 
1772  *result = 0;
1773 
1774  /* strtol(3) skips leading whitespaces */
1775  errno = 0;
1776  numval = strtol(value, &end, 10);
1777 
1778  /*
1779  * If no progress was done during the parsing or an error happened, fail.
1780  * This tests properly for overflows of the result.
1781  */
1782  if (value == end || errno != 0 || numval != (int) numval)
1783  goto error;
1784 
1785  /*
1786  * Skip any trailing whitespace; if anything but whitespace remains before
1787  * the terminating character, fail
1788  */
1789  while (*end != '\0' && isspace((unsigned char) *end))
1790  end++;
1791 
1792  if (*end != '\0')
1793  goto error;
1794 
1795  *result = numval;
1796  return true;
1797 
1798 error:
1800  libpq_gettext("invalid integer value \"%s\" for connection option \"%s\"\n"),
1801  value, context);
1802  return false;
1803 }
static struct @142 value
static void error(void)
Definition: sql-dyntest.c:147
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
PQExpBufferData errorMessage
Definition: libpq-int.h:526
#define Assert(condition)
Definition: c.h:745
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ parseServiceFile()

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

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

References StringInfoData::data, i, initStringInfo(), sort-test::key, _internalPQconninfoOption::keyword, _PQconninfoOption::keyword, StringInfoData::len, libpq_gettext, pfree(), pg_get_line_buf(), printfPQExpBuffer(), _internalPQconninfoOption::val, and _PQconninfoOption::val.

Referenced by parseServiceInfo().

5100 {
5101  int result = 0,
5102  linenr = 0,
5103  i;
5104  FILE *f;
5105  char *line;
5106  StringInfoData linebuf;
5107 
5108  *group_found = false;
5109 
5110  f = fopen(serviceFile, "r");
5111  if (f == NULL)
5112  {
5113  printfPQExpBuffer(errorMessage, libpq_gettext("service file \"%s\" not found\n"),
5114  serviceFile);
5115  return 1;
5116  }
5117 
5118  initStringInfo(&linebuf);
5119 
5120  while (pg_get_line_buf(f, &linebuf))
5121  {
5122  linenr++;
5123 
5124  /* ignore whitespace at end of line, especially the newline */
5125  while (linebuf.len > 0 &&
5126  isspace((unsigned char) linebuf.data[linebuf.len - 1]))
5127  linebuf.data[--linebuf.len] = '\0';
5128 
5129  line = linebuf.data;
5130 
5131  /* ignore leading whitespace too */
5132  while (*line && isspace((unsigned char) line[0]))
5133  line++;
5134 
5135  /* ignore comments and empty lines */
5136  if (line[0] == '\0' || line[0] == '#')
5137  continue;
5138 
5139  /* Check for right groupname */
5140  if (line[0] == '[')
5141  {
5142  if (*group_found)
5143  {
5144  /* end of desired group reached; return success */
5145  goto exit;
5146  }
5147 
5148  if (strncmp(line + 1, service, strlen(service)) == 0 &&
5149  line[strlen(service) + 1] == ']')
5150  *group_found = true;
5151  else
5152  *group_found = false;
5153  }
5154  else
5155  {
5156  if (*group_found)
5157  {
5158  /*
5159  * Finally, we are in the right group and can parse the line
5160  */
5161  char *key,
5162  *val;
5163  bool found_keyword;
5164 
5165 #ifdef USE_LDAP
5166  if (strncmp(line, "ldap", 4) == 0)
5167  {
5168  int rc = ldapServiceLookup(line, options, errorMessage);
5169 
5170  /* if rc = 2, go on reading for fallback */
5171  switch (rc)
5172  {
5173  case 0:
5174  goto exit;
5175  case 1:
5176  case 3:
5177  result = 3;
5178  goto exit;
5179  case 2:
5180  continue;
5181  }
5182  }
5183 #endif
5184 
5185  key = line;
5186  val = strchr(line, '=');
5187  if (val == NULL)
5188  {
5189  printfPQExpBuffer(errorMessage,
5190  libpq_gettext("syntax error in service file \"%s\", line %d\n"),
5191  serviceFile,
5192  linenr);
5193  result = 3;
5194  goto exit;
5195  }
5196  *val++ = '\0';
5197 
5198  if (strcmp(key, "service") == 0)
5199  {
5200  printfPQExpBuffer(errorMessage,
5201  libpq_gettext("nested service specifications not supported in service file \"%s\", line %d\n"),
5202  serviceFile,
5203  linenr);
5204  result = 3;
5205  goto exit;
5206  }
5207 
5208  /*
5209  * Set the parameter --- but don't override any previous
5210  * explicit setting.
5211  */
5212  found_keyword = false;
5213  for (i = 0; options[i].keyword; i++)
5214  {
5215  if (strcmp(options[i].keyword, key) == 0)
5216  {
5217  if (options[i].val == NULL)
5218  options[i].val = strdup(val);
5219  if (!options[i].val)
5220  {
5221  printfPQExpBuffer(errorMessage,
5222  libpq_gettext("out of memory\n"));
5223  result = 3;
5224  goto exit;
5225  }
5226  found_keyword = true;
5227  break;
5228  }
5229  }
5230 
5231  if (!found_keyword)
5232  {
5233  printfPQExpBuffer(errorMessage,
5234  libpq_gettext("syntax error in service file \"%s\", line %d\n"),
5235  serviceFile,
5236  linenr);
5237  result = 3;
5238  goto exit;
5239  }
5240  }
5241  }
5242  }
5243 
5244 exit:
5245  fclose(f);
5246  pfree(linebuf.data);
5247 
5248  return result;
5249 }
bool pg_get_line_buf(FILE *stream, StringInfo buf)
Definition: pg_get_line.c:88
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
void pfree(void *pointer)
Definition: mcxt.c:1057
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
int i
long val
Definition: informix.c:664
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ parseServiceInfo()

static int parseServiceInfo ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

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

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

Referenced by conninfo_add_defaults().

5027 {
5028  const char *service = conninfo_getval(options, "service");
5029  char serviceFile[MAXPGPATH];
5030  char *env;
5031  bool group_found = false;
5032  int status;
5033  struct stat stat_buf;
5034 
5035  /*
5036  * We have to special-case the environment variable PGSERVICE here, since
5037  * this is and should be called before inserting environment defaults for
5038  * other connection options.
5039  */
5040  if (service == NULL)
5041  service = getenv("PGSERVICE");
5042 
5043  /* If no service name given, nothing to do */
5044  if (service == NULL)
5045  return 0;
5046 
5047  /*
5048  * Try PGSERVICEFILE if specified, else try ~/.pg_service.conf (if that
5049  * exists).
5050  */
5051  if ((env = getenv("PGSERVICEFILE")) != NULL)
5052  strlcpy(serviceFile, env, sizeof(serviceFile));
5053  else
5054  {
5055  char homedir[MAXPGPATH];
5056 
5057  if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
5058  goto next_file;
5059  snprintf(serviceFile, MAXPGPATH, "%s/%s", homedir, ".pg_service.conf");
5060  if (stat(serviceFile, &stat_buf) != 0)
5061  goto next_file;
5062  }
5063 
5064  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
5065  if (group_found || status != 0)
5066  return status;
5067 
5068 next_file:
5069 
5070  /*
5071  * This could be used by any application so we can't use the binary
5072  * location to find our config files.
5073  */
5074  snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf",
5075  getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);
5076  if (stat(serviceFile, &stat_buf) != 0)
5077  goto last_file;
5078 
5079  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
5080  if (status != 0)
5081  return status;
5082 
5083 last_file:
5084  if (!group_found)
5085  {
5086  printfPQExpBuffer(errorMessage,
5087  libpq_gettext("definition of service \"%s\" not found\n"), service);
5088  return 3;
5089  }
5090 
5091  return 0;
5092 }
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:5095
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6348
bool pqGetHomeDirectory(char *buf, int bufsize)
Definition: fe-connect.c:7172
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
#define snprintf
Definition: port.h:193
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ passwordFromFile()

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

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

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

Referenced by connectOptions2().

6931 {
6932  FILE *fp;
6933  struct stat stat_buf;
6935 
6936  if (dbname == NULL || dbname[0] == '\0')
6937  return NULL;
6938 
6939  if (username == NULL || username[0] == '\0')
6940  return NULL;
6941 
6942  /* 'localhost' matches pghost of '' or the default socket directory */
6943  if (hostname == NULL || hostname[0] == '\0')
6945  else if (is_absolute_path(hostname))
6946 
6947  /*
6948  * We should probably use canonicalize_path(), but then we have to
6949  * bring path.c into libpq, and it doesn't seem worth it.
6950  */
6951  if (strcmp(hostname, DEFAULT_PGSOCKET_DIR) == 0)
6953 
6954  if (port == NULL || port[0] == '\0')
6955  port = DEF_PGPORT_STR;
6956 
6957  /* If password file cannot be opened, ignore it. */
6958  if (stat(pgpassfile, &stat_buf) != 0)
6959  return NULL;
6960 
6961 #ifndef WIN32
6962  if (!S_ISREG(stat_buf.st_mode))
6963  {
6964  fprintf(stderr,
6965  libpq_gettext("WARNING: password file \"%s\" is not a plain file\n"),
6966  pgpassfile);
6967  return NULL;
6968  }
6969 
6970  /* If password file is insecure, alert the user and ignore it. */
6971  if (stat_buf.st_mode & (S_IRWXG | S_IRWXO))
6972  {
6973  fprintf(stderr,
6974  libpq_gettext("WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
6975  pgpassfile);
6976  return NULL;
6977  }
6978 #else
6979 
6980  /*
6981  * On Win32, the directory is protected, so we don't have to check the
6982  * file.
6983  */
6984 #endif
6985 
6986  fp = fopen(pgpassfile, "r");
6987  if (fp == NULL)
6988  return NULL;
6989 
6990  /* Use an expansible buffer to accommodate any reasonable line length */
6991  initPQExpBuffer(&buf);
6992 
6993  while (!feof(fp) && !ferror(fp))
6994  {
6995  /* Make sure there's a reasonable amount of room in the buffer */
6996  if (!enlargePQExpBuffer(&buf, 128))
6997  break;
6998 
6999  /* Read some data, appending it to what we already have */
7000  if (fgets(buf.data + buf.len, buf.maxlen - buf.len, fp) == NULL)
7001  break;
7002  buf.len += strlen(buf.data + buf.len);
7003 
7004  /* If we don't yet have a whole line, loop around to read more */
7005  if (!(buf.len > 0 && buf.data[buf.len - 1] == '\n') && !feof(fp))
7006  continue;
7007 
7008  /* ignore comments */
7009  if (buf.data[0] != '#')
7010  {
7011  char *t = buf.data;
7012  int len;
7013 
7014  /* strip trailing newline and carriage return */
7015  len = pg_strip_crlf(t);
7016 
7017  if (len > 0 &&
7018  (t = pwdfMatchesString(t, hostname)) != NULL &&
7019  (t = pwdfMatchesString(t, port)) != NULL &&
7020  (t = pwdfMatchesString(t, dbname)) != NULL &&
7021  (t = pwdfMatchesString(t, username)) != NULL)
7022  {
7023  /* Found a match. */
7024  char *ret,
7025  *p1,
7026  *p2;
7027 
7028  ret = strdup(t);
7029 
7030  fclose(fp);
7031  explicit_bzero(buf.data, buf.maxlen);
7032  termPQExpBuffer(&buf);
7033 
7034  if (!ret)
7035  {
7036  /* Out of memory. XXX: an error message would be nice. */
7037  return NULL;
7038  }
7039 
7040  /* De-escape password. */
7041  for (p1 = p2 = ret; *p1 != ':' && *p1 != '\0'; ++p1, ++p2)
7042  {
7043  if (*p1 == '\\' && p1[1] != '\0')
7044  ++p1;
7045  *p2 = *p1;
7046  }
7047  *p2 = '\0';
7048 
7049  return ret;
7050  }
7051  }
7052 
7053  /* No match, reset buffer to prepare for next line. */
7054  buf.len = 0;
7055  }
7056 
7057  fclose(fp);
7058  explicit_bzero(buf.data, buf.maxlen);
7059  termPQExpBuffer(&buf);
7060  return NULL;
7061 }
int pg_strip_crlf(char *str)
Definition: string.c:105
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
#define fprintf
Definition: port.h:197
struct stat stat_buf
Definition: pg_standby.c:100
static char * buf
Definition: pg_test_fsync.c:68
#define S_IRWXG
Definition: win32_port.h:281
#define is_absolute_path(filename)
Definition: port.h:86
static int port
Definition: pg_regress.c:92
#define S_ISREG(m)
Definition: win32_port.h:299
#define stat(a, b)
Definition: win32_port.h:255
static char * username
Definition: initdb.c:134
char * dbname
Definition: streamutil.c:51
#define DefaultHost
Definition: fe-connect.c:122
static char * pwdfMatchesString(char *buf, const char *token)
Definition: fe-connect.c:6892
void explicit_bzero(void *buf, size_t len)
static char * hostname
Definition: pg_regress.c:91
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
#define S_IRWXO
Definition: win32_port.h:293
#define libpq_gettext(x)
Definition: libpq-int.h:805
#define DEFAULT_PGSOCKET_DIR
int enlargePQExpBuffer(PQExpBuffer str, size_t needed)
Definition: pqexpbuffer.c:174

◆ pgpassfileWarning()

static void pgpassfileWarning ( PGconn conn)
static

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

7070 {
7071  /* If it was 'invalid authorization', add pgpassfile mention */
7072  /* only works with >= 9.0 servers */
7073  if (conn->password_needed &&
7074  conn->connhost[conn->whichhost].password != NULL &&
7075  conn->result)
7076  {
7077  const char *sqlstate = PQresultErrorField(conn->result,
7079 
7080  if (sqlstate && strcmp(sqlstate, ERRCODE_INVALID_PASSWORD) == 0)
7082  libpq_gettext("password retrieved from file \"%s\"\n"),
7083  conn->pgpassfile);
7084  }
7085 }
char * pgpassfile
Definition: libpq-int.h:349
bool password_needed
Definition: libpq-int.h:417
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
PGresult * result
Definition: libpq-int.h:465
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
pg_conn_host * connhost
Definition: libpq-int.h:406
PQExpBufferData errorMessage
Definition: libpq-int.h:526
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:2754
#define ERRCODE_INVALID_PASSWORD
Definition: fe-connect.c:95
int whichhost
Definition: libpq-int.h:405
#define libpq_gettext(x)
Definition: libpq-int.h:805
char * password
Definition: libpq-int.h:315

◆ PQbackendPID()

int PQbackendPID ( const PGconn conn)

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

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

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

6693 {
6694  if (!conn || conn->status != CONNECTION_OK)
6695  return 0;
6696  return conn->be_pid;
6697 }
ConnStatusType status
Definition: libpq-int.h:388
int be_pid
Definition: libpq-int.h:434

◆ PQcancel()

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

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

4448 {
4449  if (!cancel)
4450  {
4451  strlcpy(errbuf, "PQcancel() -- no cancel object supplied", errbufsize);
4452  return false;
4453  }
4454 
4455  return internal_cancel(&cancel->raddr, cancel->be_pid, cancel->be_key,
4456  errbuf, errbufsize);
4457 }
static int internal_cancel(SockAddr *raddr, int be_pid, int be_key, char *errbuf, int errbufsize)
Definition: fe-connect.c:4343
int be_pid
Definition: libpq-int.h:539
int be_key
Definition: libpq-int.h:540
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
SockAddr raddr
Definition: libpq-int.h:538

◆ PQclientEncoding()

int PQclientEncoding ( const PGconn conn)

◆ PQconndefaults()

PQconninfoOption* PQconndefaults ( void  )

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

1446 {
1447  PQExpBufferData errorBuf;
1448  PQconninfoOption *connOptions;
1449 
1450  /* We don't actually report any errors here, but callees want a buffer */
1451  initPQExpBuffer(&errorBuf);
1452  if (PQExpBufferDataBroken(errorBuf))
1453  return NULL; /* out of memory already :-( */
1454 
1455  connOptions = conninfo_init(&errorBuf);
1456  if (connOptions != NULL)
1457  {
1458  /* pass NULL errorBuf to ignore errors */
1459  if (!conninfo_add_defaults(connOptions, NULL))
1460  {
1461  PQconninfoFree(connOptions);
1462  connOptions = NULL;
1463  }
1464  }
1465 
1466  termPQExpBuffer(&errorBuf);
1467  return connOptions;
1468 }
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5290
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6498
#define PQExpBufferDataBroken(buf)
Definition: pqexpbuffer.h:67
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5726
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92

◆ PQconnectdb()

PGconn* PQconnectdb ( const char *  conninfo)

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

704 {
705  PGconn *conn = PQconnectStart(conninfo);
706 
707  if (conn && conn->status != CONNECTION_BAD)
708  (void) connectDBComplete(conn);
709 
710  return conn;
711 }
PGconn * conn
Definition: streamutil.c:54
static int connectDBComplete(PGconn *conn)
Definition: fe-connect.c:2078
PGconn * PQconnectStart(const char *conninfo)
Definition: fe-connect.c:829
ConnStatusType status
Definition: libpq-int.h:388

◆ PQconnectdbParams()

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

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

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

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

650 {
651  PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname);
652 
653  if (conn && conn->status != CONNECTION_BAD)
654  (void) connectDBComplete(conn);
655 
656  return conn;
657 
658 }
PGconn * conn
Definition: streamutil.c:54
static int connectDBComplete(PGconn *conn)
Definition: fe-connect.c:2078
ConnStatusType status
Definition: libpq-int.h:388
static Datum values[MAXATTR]
Definition: bootstrap.c:165
PGconn * PQconnectStartParams(const char *const *keywords, const char *const *values, int expand_dbname)
Definition: fe-connect.c:750

◆ PQconnectionNeedsPassword()

int PQconnectionNeedsPassword ( const PGconn conn)

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

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

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

6701 {
6702  char *password;
6703 
6704  if (!conn)
6705  return false;
6706  password = PQpass(conn);
6707  if (conn->password_needed &&
6708  (password == NULL || password[0] == '\0'))
6709  return true;
6710  else
6711  return false;
6712 }
bool password_needed
Definition: libpq-int.h:417
char * PQpass(const PGconn *conn)
Definition: fe-connect.c:6532
static char * password
Definition: streamutil.c:53

◆ PQconnectionUsedPassword()

int PQconnectionUsedPassword ( const PGconn conn)

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

References pg_conn::password_needed.

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

6716 {
6717  if (!conn)
6718  return false;
6719  if (conn->password_needed)
6720  return true;
6721  else
6722  return false;
6723 }
bool password_needed
Definition: libpq-int.h:417

◆ PQconnectPoll()

PostgresPollingStatusType PQconnectPoll ( PGconn conn)

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

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