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

Go to the source code of this file.

Data Structures

struct  _internalPQconninfoOption
 

Macros

#define PGPASSFILE   ".pgpass"
 
#define ERRCODE_APPNAME_UNKNOWN   "42704"
 
#define ERRCODE_INVALID_PASSWORD   "28P01"
 
#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"
 
#define DefaultHost   "localhost"
 
#define DefaultOption   ""
 
#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 pqFreeCommandQueue (PGcmdQueueEntry *queue)
 
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 emitHostIdentityInfo (PGconn *conn, const char *host_addr)
 
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)
 
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)
 
PGpipelineStatus PQpipelineStatus (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)
 
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

◆ DefaultChannelBinding

#define DefaultChannelBinding   "disable"

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

◆ DefaultGSSMode

#define DefaultGSSMode   "disable"

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

◆ DefaultHost

#define DefaultHost   "localhost"

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

◆ DefaultOption

#define DefaultOption   ""

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

◆ DefaultSSLMode

#define DefaultSSLMode   "disable"

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

◆ DefaultTargetSessionAttrs

#define DefaultTargetSessionAttrs   "any"

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

◆ ERRCODE_APPNAME_UNKNOWN

#define ERRCODE_APPNAME_UNKNOWN   "42704"

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

◆ ERRCODE_CANNOT_CONNECT_NOW

#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"

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

◆ ERRCODE_INVALID_PASSWORD

#define ERRCODE_INVALID_PASSWORD   "28P01"

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

◆ PGPASSFILE

#define PGPASSFILE   ".pgpass"

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

Typedef Documentation

◆ internalPQconninfoOption

Function Documentation

◆ closePGconn()

static void closePGconn ( PGconn conn)
static

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

4219 {
4220  /*
4221  * If possible, send Terminate message to close the connection politely.
4222  */
4224 
4225  /*
4226  * Must reset the blocking status so a possible reconnect will work.
4227  *
4228  * Don't call PQsetnonblocking() because it will fail if it's unable to
4229  * flush the connection.
4230  */
4231  conn->nonblocking = false;
4232 
4233  /*
4234  * Close the connection, reset all transient state, flush I/O buffers.
4235  * Note that this includes clearing conn->errorMessage; we're no longer
4236  * interested in any failures associated with the old connection, and we
4237  * want a clean slate for any new connection attempt.
4238  */
4239  pqDropConnection(conn, true);
4240  conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
4244  pqClearAsyncResult(conn); /* deallocate result */
4247 
4248  /* Reset all state obtained from server, too */
4250 }
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:448
static void sendTerminateConn(PGconn *conn)
Definition: fe-connect.c:4191
static void release_conn_addrinfo(PGconn *conn)
Definition: fe-connect.c:4176
static void pqDropServerData(PGconn *conn)
Definition: fe-connect.c:556
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:749
@ CONNECTION_BAD
Definition: libpq-fe.h:59
@ PQTRANS_IDLE
Definition: libpq-fe.h:116
@ PQ_PIPELINE_OFF
Definition: libpq-fe.h:156
@ PGASYNC_IDLE
Definition: libpq-int.h:219
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148
PGconn * conn
Definition: streamutil.c:54
PGTransactionStatusType xactStatus
Definition: libpq-int.h:412
bool nonblocking
Definition: libpq-int.h:415
PQExpBufferData errorMessage
Definition: libpq-int.h:571
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:411
PGpipelineStatus pipelineStatus
Definition: libpq-int.h:417
ConnStatusType status
Definition: libpq-int.h:410

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

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

◆ connectDBComplete()

static int connectDBComplete ( PGconn conn)
static

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

2111 {
2113  time_t finish_time = ((time_t) -1);
2114  int timeout = 0;
2115  int last_whichhost = -2; /* certainly different from whichhost */
2116  struct addrinfo *last_addr_cur = NULL;
2117 
2118  if (conn == NULL || conn->status == CONNECTION_BAD)
2119  return 0;
2120 
2121  /*
2122  * Set up a time limit, if connect_timeout isn't zero.
2123  */
2124  if (conn->connect_timeout != NULL)
2125  {
2126  if (!parse_int_param(conn->connect_timeout, &timeout, conn,
2127  "connect_timeout"))
2128  {
2129  /* mark the connection as bad to report the parsing failure */
2131  return 0;
2132  }
2133 
2134  if (timeout > 0)
2135  {
2136  /*
2137  * Rounding could cause connection to fail unexpectedly quickly;
2138  * to prevent possibly waiting hardly-at-all, insist on at least
2139  * two seconds.
2140  */
2141  if (timeout < 2)
2142  timeout = 2;
2143  }
2144  else /* negative means 0 */
2145  timeout = 0;
2146  }
2147 
2148  for (;;)
2149  {
2150  int ret = 0;
2151 
2152  /*
2153  * (Re)start the connect_timeout timer if it's active and we are
2154  * considering a different host than we were last time through. If
2155  * we've already succeeded, though, needn't recalculate.
2156  */
2157  if (flag != PGRES_POLLING_OK &&
2158  timeout > 0 &&
2159  (conn->whichhost != last_whichhost ||
2160  conn->addr_cur != last_addr_cur))
2161  {
2162  finish_time = time(NULL) + timeout;
2163  last_whichhost = conn->whichhost;
2164  last_addr_cur = conn->addr_cur;
2165  }
2166 
2167  /*
2168  * Wait, if necessary. Note that the initial state (just after
2169  * PQconnectStart) is to wait for the socket to select for writing.
2170  */
2171  switch (flag)
2172  {
2173  case PGRES_POLLING_OK:
2174  return 1; /* success! */
2175 
2176  case PGRES_POLLING_READING:
2177  ret = pqWaitTimed(1, 0, conn, finish_time);
2178  if (ret == -1)
2179  {
2180  /* hard failure, eg select() problem, aborts everything */
2182  return 0;
2183  }
2184  break;
2185 
2186  case PGRES_POLLING_WRITING:
2187  ret = pqWaitTimed(0, 1, conn, finish_time);
2188  if (ret == -1)
2189  {
2190  /* hard failure, eg select() problem, aborts everything */
2192  return 0;
2193  }
2194  break;
2195 
2196  default:
2197  /* Just in case we failed to set it in PQconnectPoll */
2199  return 0;
2200  }
2201 
2202  if (ret == 1) /* connect_timeout elapsed */
2203  {
2204  /*
2205  * Give up on current server/address, try the next one.
2206  */
2207  conn->try_next_addr = true;
2209  }
2210 
2211  /*
2212  * Now try to advance the state machine.
2213  */
2214  flag = PQconnectPoll(conn);
2215  }
2216 }
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
Definition: fe-connect.c:2246
static bool parse_int_param(const char *value, int *result, PGconn *conn, const char *context)
Definition: fe-connect.c:1795
int pqWaitTimed(int forRead, int forWrite, PGconn *conn, time_t finish_time)
Definition: fe-misc.c:1003
@ CONNECTION_NEEDED
Definition: libpq-fe.h:74
PostgresPollingStatusType
Definition: libpq-fe.h:83
@ PGRES_POLLING_OK
Definition: libpq-fe.h:87
@ PGRES_POLLING_READING
Definition: libpq-fe.h:85
@ PGRES_POLLING_WRITING
Definition: libpq-fe.h:86
struct addrinfo * addr_cur
Definition: libpq-int.h:462
char * connect_timeout
Definition: libpq-int.h:360
bool try_next_addr
Definition: libpq-int.h:459
int whichhost
Definition: libpq-int.h:426
char * flag(int b)
Definition: test-ctype.c:33

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

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

◆ connectDBStart()

static int connectDBStart ( PGconn conn)
static

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

2041 {
2042  if (!conn)
2043  return 0;
2044 
2045  if (!conn->options_valid)
2046  goto connect_errReturn;
2047 
2048  /*
2049  * Check for bad linking to backend-internal versions of src/common
2050  * functions (see comments in link-canary.c for the reason we need this).
2051  * Nobody but developers should see this message, so we don't bother
2052  * translating it.
2053  */
2055  {
2057  "libpq is incorrectly linked to backend functions\n");
2058  goto connect_errReturn;
2059  }
2060 
2061  /* Ensure our buffers are empty */
2062  conn->inStart = conn->inCursor = conn->inEnd = 0;
2063  conn->outCount = 0;
2064 
2065  /*
2066  * Set up to try to connect to the first host. (Setting whichhost = -1 is
2067  * a bit of a cheat, but PQconnectPoll will advance it to 0 before
2068  * anything else looks at it.)
2069  */
2070  conn->whichhost = -1;
2071  conn->try_next_addr = false;
2072  conn->try_next_host = true;
2074 
2075  /* Also reset the target_server_type state if needed */
2078 
2079  /*
2080  * The code for processing CONNECTION_NEEDED state is in PQconnectPoll(),
2081  * so that it can easily be re-executed if needed again during the
2082  * asynchronous startup process. However, we must run it once here,
2083  * because callers expect a success return from this routine to mean that
2084  * we are in PGRES_POLLING_WRITING connection state.
2085  */
2087  return 1;
2088 
2089 connect_errReturn:
2090 
2091  /*
2092  * If we managed to open a socket, close it immediately rather than
2093  * waiting till PQfinish. (The application cannot have gotten the socket
2094  * from PQsocket yet, so this doesn't risk breaking anything.)
2095  */
2096  pqDropConnection(conn, true);
2098  return 0;
2099 }
@ SERVER_TYPE_PREFER_STANDBY_PASS2
Definition: libpq-int.h:240
@ SERVER_TYPE_PREFER_STANDBY
Definition: libpq-int.h:239
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
bool try_next_host
Definition: libpq-int.h:460
int inCursor
Definition: libpq-int.h:482
int inEnd
Definition: libpq-int.h:483
int inStart
Definition: libpq-int.h:481
bool options_valid
Definition: libpq-int.h:414
PGTargetServerType target_server_type
Definition: libpq-int.h:458
int outCount
Definition: libpq-int.h:488

References appendPQExpBufferStr(), conn, 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(), SERVER_TYPE_PREFER_STANDBY, SERVER_TYPE_PREFER_STANDBY_PASS2, pg_conn::status, pg_conn::target_server_type, pg_conn::try_next_addr, pg_conn::try_next_host, and pg_conn::whichhost.

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

◆ connectFailureMessage()

static void connectFailureMessage ( PGconn conn,
int  errorno 
)
static

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

1753 {
1754  char sebuf[PG_STRERROR_R_BUFLEN];
1755 
1757  "%s\n",
1758  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
1759 
1760 #ifdef HAVE_UNIX_SOCKETS
1761  if (IS_AF_UNIX(conn->raddr.addr.ss_family))
1763  libpq_gettext("\tIs the server running locally and accepting connections on that socket?\n"));
1764  else
1765 #endif
1767  libpq_gettext("\tIs the server running on that host and accepting TCP/IP connections?\n"));
1768 }
#define IS_AF_UNIX(fam)
Definition: ip.h:24
#define libpq_gettext(x)
Definition: libpq-int.h:841
#define SOCK_STRERROR
Definition: libpq-int.h:855
#define PG_STRERROR_R_BUFLEN
Definition: port.h:240
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
struct sockaddr_storage addr
Definition: pqcomm.h:64
SockAddr raddr
Definition: libpq-int.h:447

References SockAddr::addr, appendPQExpBuffer(), appendPQExpBufferStr(), conn, pg_conn::errorMessage, IS_AF_UNIX, libpq_gettext, PG_STRERROR_R_BUFLEN, pg_conn::raddr, and SOCK_STRERROR.

Referenced by PQconnectPoll().

◆ connectNoDelay()

static int connectNoDelay ( PGconn conn)
static

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

1633 {
1634 #ifdef TCP_NODELAY
1635  int on = 1;
1636 
1637  if (setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY,
1638  (char *) &on,
1639  sizeof(on)) < 0)
1640  {
1641  char sebuf[PG_STRERROR_R_BUFLEN];
1642 
1644  libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
1645  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
1646  return 0;
1647  }
1648 #endif
1649 
1650  return 1;
1651 }
#define SOCK_ERRNO
Definition: libpq-int.h:854
pgsocket sock
Definition: libpq-int.h:444

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

Referenced by PQconnectPoll().

◆ connectOptions1()

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

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

930 {
931  PQconninfoOption *connOptions;
932 
933  /*
934  * Parse the conninfo string
935  */
936  connOptions = parse_connection_string(conninfo, &conn->errorMessage, true);
937  if (connOptions == NULL)
938  {
940  /* errorMessage is already set */
941  return false;
942  }
943 
944  /*
945  * Move option values into conn structure
946  */
947  if (!fillPGconn(conn, connOptions))
948  {
950  PQconninfoFree(connOptions);
951  return false;
952  }
953 
954  /*
955  * Free the option info - all is in conn now
956  */
957  PQconninfoFree(connOptions);
958 
959  return true;
960 }
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6598
static PQconninfoOption * parse_connection_string(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5425
static bool fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
Definition: fe-connect.c:887

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

Referenced by PQconnectStart(), and PQsetdbLogin().

◆ connectOptions2()

static bool connectOptions2 ( PGconn conn)
static

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

1028 {
1029  int i;
1030 
1031  /*
1032  * Allocate memory for details about each host to which we might possibly
1033  * try to connect. For that, count the number of elements in the hostaddr
1034  * or host options. If neither is given, assume one host.
1035  */
1036  conn->whichhost = 0;
1037  if (conn->pghostaddr && conn->pghostaddr[0] != '\0')
1039  else if (conn->pghost && conn->pghost[0] != '\0')
1041  else
1042  conn->nconnhost = 1;
1043  conn->connhost = (pg_conn_host *)
1044  calloc(conn->nconnhost, sizeof(pg_conn_host));
1045  if (conn->connhost == NULL)
1046  goto oom_error;
1047 
1048  /*
1049  * We now have one pg_conn_host structure per possible host. Fill in the
1050  * host and hostaddr fields for each, by splitting the parameter strings.
1051  */
1052  if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0')
1053  {
1054  char *s = conn->pghostaddr;
1055  bool more = true;
1056 
1057  for (i = 0; i < conn->nconnhost && more; i++)
1058  {
1060  if (conn->connhost[i].hostaddr == NULL)
1061  goto oom_error;
1062  }
1063 
1064  /*
1065  * If hostaddr was given, the array was allocated according to the
1066  * number of elements in the hostaddr list, so it really should be the
1067  * right size.
1068  */
1069  Assert(!more);
1070  Assert(i == conn->nconnhost);
1071  }
1072 
1073  if (conn->pghost != NULL && conn->pghost[0] != '\0')
1074  {
1075  char *s = conn->pghost;
1076  bool more = true;
1077 
1078  for (i = 0; i < conn->nconnhost && more; i++)
1079  {
1081  if (conn->connhost[i].host == NULL)
1082  goto oom_error;
1083  }
1084 
1085  /* Check for wrong number of host items. */
1086  if (more || i != conn->nconnhost)
1087  {
1090  libpq_gettext("could not match %d host names to %d hostaddr values\n"),
1092  return false;
1093  }
1094  }
1095 
1096  /*
1097  * Now, for each host slot, identify the type of address spec, and fill in
1098  * the default address if nothing was given.
1099  */
1100  for (i = 0; i < conn->nconnhost; i++)
1101  {
1102  pg_conn_host *ch = &conn->connhost[i];
1103 
1104  if (ch->hostaddr != NULL && ch->hostaddr[0] != '\0')
1105  ch->type = CHT_HOST_ADDRESS;
1106  else if (ch->host != NULL && ch->host[0] != '\0')
1107  {
1108  ch->type = CHT_HOST_NAME;
1109 #ifdef HAVE_UNIX_SOCKETS
1110  if (is_unixsock_path(ch->host))
1111  ch->type = CHT_UNIX_SOCKET;
1112 #endif
1113  }
1114  else
1115  {
1116  if (ch->host)
1117  free(ch->host);
1118 #ifdef HAVE_UNIX_SOCKETS
1119  if (DEFAULT_PGSOCKET_DIR[0])
1120  {
1121  ch->host = strdup(DEFAULT_PGSOCKET_DIR);
1122  ch->type = CHT_UNIX_SOCKET;
1123  }
1124  else
1125 #endif
1126  {
1127  ch->host = strdup(DefaultHost);
1128  ch->type = CHT_HOST_NAME;
1129  }
1130  if (ch->host == NULL)
1131  goto oom_error;
1132  }
1133  }
1134 
1135  /*
1136  * Next, work out the port number corresponding to each host name.
1137  *
1138  * Note: unlike the above for host names, this could leave the port fields
1139  * as null or empty strings. We will substitute DEF_PGPORT whenever we
1140  * read such a port field.
1141  */
1142  if (conn->pgport != NULL && conn->pgport[0] != '\0')
1143  {
1144  char *s = conn->pgport;
1145  bool more = true;
1146 
1147  for (i = 0; i < conn->nconnhost && more; i++)
1148  {
1150  if (conn->connhost[i].port == NULL)
1151  goto oom_error;
1152  }
1153 
1154  /*
1155  * If exactly one port was given, use it for every host. Otherwise,
1156  * there must be exactly as many ports as there were hosts.
1157  */
1158  if (i == 1 && !more)
1159  {
1160  for (i = 1; i < conn->nconnhost; i++)
1161  {
1162  conn->connhost[i].port = strdup(conn->connhost[0].port);
1163  if (conn->connhost[i].port == NULL)
1164  goto oom_error;
1165  }
1166  }
1167  else if (more || i != conn->nconnhost)
1168  {
1171  libpq_gettext("could not match %d port numbers to %d hosts\n"),
1173  return false;
1174  }
1175  }
1176 
1177  /*
1178  * If user name was not given, fetch it. (Most likely, the fetch will
1179  * fail, since the only way we get here is if pg_fe_getauthname() failed
1180  * during conninfo_add_defaults(). But now we want an error message.)
1181  */
1182  if (conn->pguser == NULL || conn->pguser[0] == '\0')
1183  {
1184  if (conn->pguser)
1185  free(conn->pguser);
1187  if (!conn->pguser)
1188  {
1190  return false;
1191  }
1192  }
1193 
1194  /*
1195  * If database name was not given, default it to equal user name
1196  */
1197  if (conn->dbName == NULL || conn->dbName[0] == '\0')
1198  {
1199  if (conn->dbName)
1200  free(conn->dbName);
1201  conn->dbName = strdup(conn->pguser);
1202  if (!conn->dbName)
1203  goto oom_error;
1204  }
1205 
1206  /*
1207  * If password was not given, try to look it up in password file. Note
1208  * that the result might be different for each host/port pair.
1209  */
1210  if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
1211  {
1212  /* If password file wasn't specified, use ~/PGPASSFILE */
1213  if (conn->pgpassfile == NULL || conn->pgpassfile[0] == '\0')
1214  {
1215  char homedir[MAXPGPATH];
1216 
1217  if (pqGetHomeDirectory(homedir, sizeof(homedir)))
1218  {
1219  if (conn->pgpassfile)
1220  free(conn->pgpassfile);
1222  if (!conn->pgpassfile)
1223  goto oom_error;
1224  snprintf(conn->pgpassfile, MAXPGPATH, "%s/%s",
1225  homedir, PGPASSFILE);
1226  }
1227  }
1228 
1229  if (conn->pgpassfile != NULL && conn->pgpassfile[0] != '\0')
1230  {
1231  for (i = 0; i < conn->nconnhost; i++)
1232  {
1233  /*
1234  * Try to get a password for this host from file. We use host
1235  * for the hostname search key if given, else hostaddr (at
1236  * least one of them is guaranteed nonempty by now).
1237  */
1238  const char *pwhost = conn->connhost[i].host;
1239 
1240  if (pwhost == NULL || pwhost[0] == '\0')
1241  pwhost = conn->connhost[i].hostaddr;
1242 
1243  conn->connhost[i].password =
1244  passwordFromFile(pwhost,
1245  conn->connhost[i].port,
1246  conn->dbName,
1247  conn->pguser,
1248  conn->pgpassfile);
1249  }
1250  }
1251  }
1252 
1253  /*
1254  * validate channel_binding option
1255  */
1256  if (conn->channel_binding)
1257  {
1258  if (strcmp(conn->channel_binding, "disable") != 0
1259  && strcmp(conn->channel_binding, "prefer") != 0
1260  && strcmp(conn->channel_binding, "require") != 0)
1261  {
1264  libpq_gettext("invalid %s value: \"%s\"\n"),
1265  "channel_binding", conn->channel_binding);
1266  return false;
1267  }
1268  }
1269  else
1270  {
1272  if (!conn->channel_binding)
1273  goto oom_error;
1274  }
1275 
1276  /*
1277  * validate sslmode option
1278  */
1279  if (conn->sslmode)
1280  {
1281  if (strcmp(conn->sslmode, "disable") != 0
1282  && strcmp(conn->sslmode, "allow") != 0
1283  && strcmp(conn->sslmode, "prefer") != 0
1284  && strcmp(conn->sslmode, "require") != 0
1285  && strcmp(conn->sslmode, "verify-ca") != 0
1286  && strcmp(conn->sslmode, "verify-full") != 0)
1287  {
1290  libpq_gettext("invalid %s value: \"%s\"\n"),
1291  "sslmode", conn->sslmode);
1292  return false;
1293  }
1294 
1295 #ifndef USE_SSL
1296  switch (conn->sslmode[0])
1297  {
1298  case 'a': /* "allow" */
1299  case 'p': /* "prefer" */
1300 
1301  /*
1302  * warn user that an SSL connection will never be negotiated
1303  * since SSL was not compiled in?
1304  */
1305  break;
1306 
1307  case 'r': /* "require" */
1308  case 'v': /* "verify-ca" or "verify-full" */
1311  libpq_gettext("sslmode value \"%s\" invalid when SSL support is not compiled in\n"),
1312  conn->sslmode);
1313  return false;
1314  }
1315 #endif
1316  }
1317  else
1318  {
1319  conn->sslmode = strdup(DefaultSSLMode);
1320  if (!conn->sslmode)
1321  goto oom_error;
1322  }
1323 
1324  /*
1325  * Validate TLS protocol versions for ssl_min_protocol_version and
1326  * ssl_max_protocol_version.
1327  */
1329  {
1332  libpq_gettext("invalid %s value: \"%s\"\n"),
1333  "ssl_min_protocol_version",
1335  return false;
1336  }
1338  {
1341  libpq_gettext("invalid %s value: \"%s\"\n"),
1342  "ssl_max_protocol_version",
1344  return false;
1345  }
1346 
1347  /*
1348  * Check if the range of SSL protocols defined is correct. This is done
1349  * at this early step because this is independent of the SSL
1350  * implementation used, and this avoids unnecessary cycles with an
1351  * already-built SSL context when the connection is being established, as
1352  * it would be doomed anyway.
1353  */
1356  {
1359  libpq_gettext("invalid SSL protocol version range\n"));
1360  return false;
1361  }
1362 
1363  /*
1364  * validate gssencmode option
1365  */
1366  if (conn->gssencmode)
1367  {
1368  if (strcmp(conn->gssencmode, "disable") != 0 &&
1369  strcmp(conn->gssencmode, "prefer") != 0 &&
1370  strcmp(conn->gssencmode, "require") != 0)
1371  {
1374  libpq_gettext("invalid %s value: \"%s\"\n"),
1375  "gssencmode",
1376  conn->gssencmode);
1377  return false;
1378  }
1379 #ifndef ENABLE_GSS
1380  if (strcmp(conn->gssencmode, "require") == 0)
1381  {
1384  libpq_gettext("gssencmode value \"%s\" invalid when GSSAPI support is not compiled in\n"),
1385  conn->gssencmode);
1386  return false;
1387  }
1388 #endif
1389  }
1390  else
1391  {
1392  conn->gssencmode = strdup(DefaultGSSMode);
1393  if (!conn->gssencmode)
1394  goto oom_error;
1395  }
1396 
1397  /*
1398  * validate target_session_attrs option, and set target_server_type
1399  */
1401  {
1402  if (strcmp(conn->target_session_attrs, "any") == 0)
1404  else if (strcmp(conn->target_session_attrs, "read-write") == 0)
1406  else if (strcmp(conn->target_session_attrs, "read-only") == 0)
1408  else if (strcmp(conn->target_session_attrs, "primary") == 0)
1410  else if (strcmp(conn->target_session_attrs, "standby") == 0)
1412  else if (strcmp(conn->target_session_attrs, "prefer-standby") == 0)
1414  else
1415  {
1418  libpq_gettext("invalid %s value: \"%s\"\n"),
1419  "target_session_attrs",
1421  return false;
1422  }
1423  }
1424  else
1426 
1427  /*
1428  * Resolve special "auto" client_encoding from the locale
1429  */
1431  strcmp(conn->client_encoding_initial, "auto") == 0)
1432  {
1436  goto oom_error;
1437  }
1438 
1439  /*
1440  * Only if we get this far is it appropriate to try to connect. (We need a
1441  * state flag, rather than just the boolean result of this function, in
1442  * case someone tries to PQreset() the PGconn.)
1443  */
1444  conn->options_valid = true;
1445 
1446  return true;
1447 
1448 oom_error:
1451  libpq_gettext("out of memory\n"));
1452  return false;
1453 }
const char * pg_encoding_to_char(int encoding)
Definition: encnames.c:588
char * pg_fe_getauthname(PQExpBuffer errorMessage)
Definition: fe-auth.c:1101
#define DefaultHost
Definition: fe-connect.c:121
static char * passwordFromFile(const char *hostname, const char *port, const char *dbname, const char *username, const char *pgpassfile)
Definition: fe-connect.c:7025
static bool sslVerifyProtocolRange(const char *min, const char *max)
Definition: fe-connect.c:7215
bool pqGetHomeDirectory(char *buf, int bufsize)
Definition: fe-connect.c:7268
#define DefaultSSLMode
Definition: fe-connect.c:132
#define DefaultGSSMode
Definition: fe-connect.c:138
static int count_comma_separated_elems(const char *input)
Definition: fe-connect.c:966
#define DefaultChannelBinding
Definition: fe-connect.c:126
static bool sslVerifyProtocolVersion(const char *version)
Definition: fe-connect.c:7189
static char * parse_comma_separated_list(char **startptr, bool *more)
Definition: fe-connect.c:990
#define PGPASSFILE
Definition: fe-connect.c:80
#define calloc(a, b)
Definition: header.h:55
#define free(a)
Definition: header.h:65
#define malloc(a)
Definition: header.h:50
int i
Definition: isn.c:73
@ CHT_UNIX_SOCKET
Definition: libpq-int.h:301
@ CHT_HOST_ADDRESS
Definition: libpq-int.h:300
@ CHT_HOST_NAME
Definition: libpq-int.h:299
@ SERVER_TYPE_STANDBY
Definition: libpq-int.h:238
@ SERVER_TYPE_PRIMARY
Definition: libpq-int.h:237
@ SERVER_TYPE_ANY
Definition: libpq-int.h:234
@ SERVER_TYPE_READ_WRITE
Definition: libpq-int.h:235
@ SERVER_TYPE_READ_ONLY
Definition: libpq-int.h:236
Assert(fmt[strlen(fmt) - 1] !='\n')
#define MAXPGPATH
#define DEFAULT_PGSOCKET_DIR
#define snprintf
Definition: port.h:222
int pg_get_encoding_from_locale(const char *ctype, bool write_message)
Definition: chklocale.c:452
static bool is_unixsock_path(const char *path)
Definition: pqcomm.h:93
char * host
Definition: libpq-int.h:335
char * password
Definition: libpq-int.h:338
char * port
Definition: libpq-int.h:337
char * hostaddr
Definition: libpq-int.h:336
pg_conn_host_type type
Definition: libpq-int.h:334
int nconnhost
Definition: libpq-int.h:425
char * channel_binding
Definition: libpq-int.h:371
char * pghost
Definition: libpq-int.h:350
char * ssl_max_protocol_version
Definition: libpq-int.h:394
char * pgpass
Definition: libpq-int.h:369
char * dbName
Definition: libpq-int.h:366
char * target_session_attrs
Definition: libpq-int.h:395
char * pguser
Definition: libpq-int.h:368
char * client_encoding_initial
Definition: libpq-int.h:362
char * sslmode
Definition: libpq-int.h:379
char * ssl_min_protocol_version
Definition: libpq-int.h:393
char * gssencmode
Definition: libpq-int.h:389
char * pghostaddr
Definition: libpq-int.h:354
char * pgpassfile
Definition: libpq-int.h:370
char * pgport
Definition: libpq-int.h:358
pg_conn_host * connhost
Definition: libpq-int.h:427

References appendPQExpBuffer(), appendPQExpBufferStr(), Assert(), calloc, pg_conn::channel_binding, CHT_HOST_ADDRESS, CHT_HOST_NAME, CHT_UNIX_SOCKET, pg_conn::client_encoding_initial, conn, 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_unixsock_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(), SERVER_TYPE_ANY, SERVER_TYPE_PREFER_STANDBY, SERVER_TYPE_PRIMARY, SERVER_TYPE_READ_ONLY, SERVER_TYPE_READ_WRITE, SERVER_TYPE_STANDBY, snprintf, pg_conn::ssl_max_protocol_version, pg_conn::ssl_min_protocol_version, pg_conn::sslmode, sslVerifyProtocolRange(), sslVerifyProtocolVersion(), pg_conn::status, pg_conn::target_server_type, pg_conn::target_session_attrs, pg_conn_host::type, and pg_conn::whichhost.

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

◆ conninfo_add_defaults()

static bool conninfo_add_defaults ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

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

5822 {
5824  char *tmp;
5825 
5826  /*
5827  * If there's a service spec, use it to obtain any not-explicitly-given
5828  * parameters. Ignore error if no error message buffer is passed because
5829  * there is no way to pass back the failure message.
5830  */
5831  if (parseServiceInfo(options, errorMessage) != 0 && errorMessage)
5832  return false;
5833 
5834  /*
5835  * Get the fallback resources for parameters not specified in the conninfo
5836  * string nor the service.
5837  */
5838  for (option = options; option->keyword != NULL; option++)
5839  {
5840  if (option->val != NULL)
5841  continue; /* Value was in conninfo or service */
5842 
5843  /*
5844  * Try to get the environment variable fallback
5845  */
5846  if (option->envvar != NULL)
5847  {
5848  if ((tmp = getenv(option->envvar)) != NULL)
5849  {
5850  option->val = strdup(tmp);
5851  if (!option->val)
5852  {
5853  if (errorMessage)
5854  appendPQExpBufferStr(errorMessage,
5855  libpq_gettext("out of memory\n"));
5856  return false;
5857  }
5858  continue;
5859  }
5860  }
5861 
5862  /*
5863  * Interpret the deprecated PGREQUIRESSL environment variable. Per
5864  * tradition, translate values starting with "1" to sslmode=require,
5865  * and ignore other values. Given both PGREQUIRESSL=1 and PGSSLMODE,
5866  * PGSSLMODE takes precedence; the opposite was true before v9.3.
5867  */
5868  if (strcmp(option->keyword, "sslmode") == 0)
5869  {
5870  const char *requiresslenv = getenv("PGREQUIRESSL");
5871 
5872  if (requiresslenv != NULL && requiresslenv[0] == '1')
5873  {
5874  option->val = strdup("require");
5875  if (!option->val)
5876  {
5877  if (errorMessage)
5878  appendPQExpBufferStr(errorMessage,
5879  libpq_gettext("out of memory\n"));
5880  return false;
5881  }
5882  continue;
5883  }
5884  }
5885 
5886  /*
5887  * No environment variable specified or the variable isn't set - try
5888  * compiled-in default
5889  */
5890  if (option->compiled != NULL)
5891  {
5892  option->val = strdup(option->compiled);
5893  if (!option->val)
5894  {
5895  if (errorMessage)
5896  appendPQExpBufferStr(errorMessage,
5897  libpq_gettext("out of memory\n"));
5898  return false;
5899  }
5900  continue;
5901  }
5902 
5903  /*
5904  * Special handling for "user" option. Note that if pg_fe_getauthname
5905  * fails, we just leave the value as NULL; there's no need for this to
5906  * be an error condition if the caller provides a user name. The only
5907  * reason we do this now at all is so that callers of PQconndefaults
5908  * will see a correct default (barring error, of course).
5909  */
5910  if (strcmp(option->keyword, "user") == 0)
5911  {
5912  option->val = pg_fe_getauthname(NULL);
5913  continue;
5914  }
5915  }
5916 
5917  return true;
5918 }
static int parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5114
int val
Definition: getopt_long.h:21

References appendPQExpBufferStr(), libpq_gettext, parseServiceInfo(), pg_fe_getauthname(), and option::val.

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

◆ 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 5657 of file fe-connect.c.

5660 {
5662  PQconninfoOption *dbname_options = NULL;
5664  int i = 0;
5665 
5666  /*
5667  * If expand_dbname is non-zero, check keyword "dbname" to see if val is
5668  * actually a recognized connection string.
5669  */
5670  while (expand_dbname && keywords[i])
5671  {
5672  const char *pname = keywords[i];
5673  const char *pvalue = values[i];
5674 
5675  /* first find "dbname" if any */
5676  if (strcmp(pname, "dbname") == 0 && pvalue)
5677  {
5678  /*
5679  * If value is a connection string, parse it, but do not use
5680  * defaults here -- those get picked up later. We only want to
5681  * override for those parameters actually passed.
5682  */
5683  if (recognized_connection_string(pvalue))
5684  {
5685  dbname_options = parse_connection_string(pvalue, errorMessage, false);
5686  if (dbname_options == NULL)
5687  return NULL;
5688  }
5689  break;
5690  }
5691  ++i;
5692  }
5693 
5694  /* Make a working copy of PQconninfoOptions */
5695  options = conninfo_init(errorMessage);
5696  if (options == NULL)
5697  {
5698  PQconninfoFree(dbname_options);
5699  return NULL;
5700  }
5701 
5702  /* Parse the keywords/values arrays */
5703  i = 0;
5704  while (keywords[i])
5705  {
5706  const char *pname = keywords[i];
5707  const char *pvalue = values[i];
5708 
5709  if (pvalue != NULL && pvalue[0] != '\0')
5710  {
5711  /* Search for the param record */
5712  for (option = options; option->keyword != NULL; option++)
5713  {
5714  if (strcmp(option->keyword, pname) == 0)
5715  break;
5716  }
5717 
5718  /* Check for invalid connection option */
5719  if (option->keyword == NULL)
5720  {
5721  appendPQExpBuffer(errorMessage,
5722  libpq_gettext("invalid connection option \"%s\"\n"),
5723  pname);
5725  PQconninfoFree(dbname_options);
5726  return NULL;
5727  }
5728 
5729  /*
5730  * If we are on the first dbname parameter, and we have a parsed
5731  * connection string, copy those parameters across, overriding any
5732  * existing previous settings.
5733  */
5734  if (strcmp(pname, "dbname") == 0 && dbname_options)
5735  {
5736  PQconninfoOption *str_option;
5737 
5738  for (str_option = dbname_options; str_option->keyword != NULL; str_option++)
5739  {
5740  if (str_option->val != NULL)
5741  {
5742  int k;
5743 
5744  for (k = 0; options[k].keyword; k++)
5745  {
5746  if (strcmp(options[k].keyword, str_option->keyword) == 0)
5747  {
5748  if (options[k].val)
5749  free(options[k].val);
5750  options[k].val = strdup(str_option->val);
5751  if (!options[k].val)
5752  {
5753  appendPQExpBufferStr(errorMessage,
5754  libpq_gettext("out of memory\n"));
5756  PQconninfoFree(dbname_options);
5757  return NULL;
5758  }
5759  break;
5760  }
5761  }
5762  }
5763  }
5764 
5765  /*
5766  * Forget the parsed connection string, so that any subsequent
5767  * dbname parameters will not be expanded.
5768  */
5769  PQconninfoFree(dbname_options);
5770  dbname_options = NULL;
5771  }
5772  else
5773  {
5774  /*
5775  * Store the value, overriding previous settings
5776  */
5777  if (option->val)
5778  free(option->val);
5779  option->val = strdup(pvalue);
5780  if (!option->val)
5781  {
5782  appendPQExpBufferStr(errorMessage,
5783  libpq_gettext("out of memory\n"));
5785  PQconninfoFree(dbname_options);
5786  return NULL;
5787  }
5788  }
5789  }
5790  ++i;
5791  }
5792  PQconninfoFree(dbname_options);
5793 
5794  /*
5795  * Add in defaults if the caller wants that.
5796  */
5797  if (use_defaults)
5798  {
5799  if (!conninfo_add_defaults(options, errorMessage))
5800  {
5802  return NULL;
5803  }
5804  }
5805 
5806  return options;
5807 }
static Datum values[MAXATTR]
Definition: bootstrap.c:156
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5385
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5821
static bool recognized_connection_string(const char *connstr)
Definition: fe-connect.c:5468
long val
Definition: informix.c:664
static char ** options

References appendPQExpBuffer(), appendPQExpBufferStr(), conninfo_add_defaults(), conninfo_init(), free, i, _PQconninfoOption::keyword, libpq_gettext, options, parse_connection_string(), PQconninfoFree(), recognized_connection_string(), option::val, val, _PQconninfoOption::val, and values.

Referenced by PQconnectStartParams().

◆ conninfo_find()

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

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

6537 {
6539 
6540  for (option = connOptions; option->keyword != NULL; option++)
6541  {
6542  if (strcmp(option->keyword, keyword) == 0)
6543  return option;
6544  }
6545 
6546  return NULL;
6547 }

Referenced by conninfo_getval(), and conninfo_storeval().

◆ conninfo_getval()

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

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

6447 {
6449 
6450  option = conninfo_find(connOptions, keyword);
6451 
6452  return option ? option->val : NULL;
6453 }
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6536

References conninfo_find(), and option::val.

Referenced by fillPGconn(), and parseServiceInfo().

◆ conninfo_init()

static PQconninfoOption * conninfo_init ( PQExpBuffer  errorMessage)
static

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

5386 {
5388  PQconninfoOption *opt_dest;
5389  const internalPQconninfoOption *cur_opt;
5390 
5391  /*
5392  * Get enough memory for all options in PQconninfoOptions, even if some
5393  * end up being filtered out.
5394  */
5396  if (options == NULL)
5397  {
5398  appendPQExpBufferStr(errorMessage,
5399  libpq_gettext("out of memory\n"));
5400  return NULL;
5401  }
5402  opt_dest = options;
5403 
5404  for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++)
5405  {
5406  /* Only copy the public part of the struct, not the full internal */
5407  memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption));
5408  opt_dest++;
5409  }
5410  MemSet(opt_dest, 0, sizeof(PQconninfoOption));
5411 
5412  return options;
5413 }
#define MemSet(start, val, len)
Definition: c.h:1008
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:191

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

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

◆ conninfo_parse()

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

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

5481 {
5482  char *pname;
5483  char *pval;
5484  char *buf;
5485  char *cp;
5486  char *cp2;
5488 
5489  /* Make a working copy of PQconninfoOptions */
5490  options = conninfo_init(errorMessage);
5491  if (options == NULL)
5492  return NULL;
5493 
5494  /* Need a modifiable copy of the input string */
5495  if ((buf = strdup(conninfo)) == NULL)
5496  {
5497  appendPQExpBufferStr(errorMessage,
5498  libpq_gettext("out of memory\n"));
5500  return NULL;
5501  }
5502  cp = buf;
5503 
5504  while (*cp)
5505  {
5506  /* Skip blanks before the parameter name */
5507  if (isspace((unsigned char) *cp))
5508  {
5509  cp++;
5510  continue;
5511  }
5512 
5513  /* Get the parameter name */
5514  pname = cp;
5515  while (*cp)
5516  {
5517  if (*cp == '=')
5518  break;
5519  if (isspace((unsigned char) *cp))
5520  {
5521  *cp++ = '\0';
5522  while (*cp)
5523  {
5524  if (!isspace((unsigned char) *cp))
5525  break;
5526  cp++;
5527  }
5528  break;
5529  }
5530  cp++;
5531  }
5532 
5533  /* Check that there is a following '=' */
5534  if (*cp != '=')
5535  {
5536  appendPQExpBuffer(errorMessage,
5537  libpq_gettext("missing \"=\" after \"%s\" in connection info string\n"),
5538  pname);
5540  free(buf);
5541  return NULL;
5542  }
5543  *cp++ = '\0';
5544 
5545  /* Skip blanks after the '=' */
5546  while (*cp)
5547  {
5548  if (!isspace((unsigned char) *cp))
5549  break;
5550  cp++;
5551  }
5552 
5553  /* Get the parameter value */
5554  pval = cp;
5555 
5556  if (*cp != '\'')
5557  {
5558  cp2 = pval;
5559  while (*cp)
5560  {
5561  if (isspace((unsigned char) *cp))
5562  {
5563  *cp++ = '\0';
5564  break;
5565  }
5566  if (*cp == '\\')
5567  {
5568  cp++;
5569  if (*cp != '\0')
5570  *cp2++ = *cp++;
5571  }
5572  else
5573  *cp2++ = *cp++;
5574  }
5575  *cp2 = '\0';
5576  }
5577  else
5578  {
5579  cp2 = pval;
5580  cp++;
5581  for (;;)
5582  {
5583  if (*cp == '\0')
5584  {
5585  appendPQExpBufferStr(errorMessage,
5586  libpq_gettext("unterminated quoted string in connection info string\n"));
5588  free(buf);
5589  return NULL;
5590  }
5591  if (*cp == '\\')
5592  {
5593  cp++;
5594  if (*cp != '\0')
5595  *cp2++ = *cp++;
5596  continue;
5597  }
5598  if (*cp == '\'')
5599  {
5600  *cp2 = '\0';
5601  cp++;
5602  break;
5603  }
5604  *cp2++ = *cp++;
5605  }
5606  }
5607 
5608  /*
5609  * Now that we have the name and the value, store the record.
5610  */
5611  if (!conninfo_storeval(options, pname, pval, errorMessage, false, false))
5612  {
5614  free(buf);
5615  return NULL;
5616  }
5617  }
5618 
5619  /* Done with the modifiable input string */
5620  free(buf);
5621 
5622  /*
5623  * Add in defaults if the caller wants that.
5624  */
5625  if (use_defaults)
5626  {
5627  if (!conninfo_add_defaults(options, errorMessage))
5628  {
5630  return NULL;
5631  }
5632  }
5633 
5634  return options;
5635 }
static PQconninfoOption * conninfo_storeval(PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode)
Definition: fe-connect.c:6471
static char * buf
Definition: pg_test_fsync.c:70

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

Referenced by parse_connection_string().

◆ 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 6471 of file fe-connect.c.

6475 {
6477  char *value_copy;
6478 
6479  /*
6480  * For backwards compatibility, requiressl=1 gets translated to
6481  * sslmode=require, and requiressl=0 gets translated to sslmode=prefer
6482  * (which is the default for sslmode).
6483  */
6484  if (strcmp(keyword, "requiressl") == 0)
6485  {
6486  keyword = "sslmode";
6487  if (value[0] == '1')
6488  value = "require";
6489  else
6490  value = "prefer";
6491  }
6492 
6493  option = conninfo_find(connOptions, keyword);
6494  if (option == NULL)
6495  {
6496  if (!ignoreMissing)
6497  appendPQExpBuffer(errorMessage,
6498  libpq_gettext("invalid connection option \"%s\"\n"),
6499  keyword);
6500  return NULL;
6501  }
6502 
6503  if (uri_decode)
6504  {
6505  value_copy = conninfo_uri_decode(value, errorMessage);
6506  if (value_copy == NULL)
6507  /* conninfo_uri_decode already set an error message */
6508  return NULL;
6509  }
6510  else
6511  {
6512  value_copy = strdup(value);
6513  if (value_copy == NULL)
6514  {
6515  appendPQExpBufferStr(errorMessage, libpq_gettext("out of memory\n"));
6516  return NULL;
6517  }
6518  }
6519 
6520  if (option->val)
6521  free(option->val);
6522  option->val = value_copy;
6523 
6524  return option;
6525 }
static char * conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
Definition: fe-connect.c:6356
static struct @142 value

References appendPQExpBuffer(), appendPQExpBufferStr(), conninfo_find(), conninfo_uri_decode(), free, libpq_gettext, option::val, and value.

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

◆ conninfo_uri_decode()

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

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

6357 {
6358  char *buf;
6359  char *p;
6360  const char *q = str;
6361 
6362  buf = malloc(strlen(str) + 1);
6363  if (buf == NULL)
6364  {
6365  appendPQExpBufferStr(errorMessage, libpq_gettext("out of memory\n"));
6366  return NULL;
6367  }
6368  p = buf;
6369 
6370  for (;;)
6371  {
6372  if (*q != '%')
6373  {
6374  /* copy and check for NUL terminator */
6375  if (!(*(p++) = *(q++)))
6376  break;
6377  }
6378  else
6379  {
6380  int hi;
6381  int lo;
6382  int c;
6383 
6384  ++q; /* skip the percent sign itself */
6385 
6386  /*
6387  * Possible EOL will be caught by the first call to
6388  * get_hexdigit(), so we never dereference an invalid q pointer.
6389  */
6390  if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo)))
6391  {
6392  appendPQExpBuffer(errorMessage,
6393  libpq_gettext("invalid percent-encoded token: \"%s\"\n"),
6394  str);
6395  free(buf);
6396  return NULL;
6397  }
6398 
6399  c = (hi << 4) | lo;
6400  if (c == 0)
6401  {
6402  appendPQExpBuffer(errorMessage,
6403  libpq_gettext("forbidden value %%00 in percent-encoded value: \"%s\"\n"),
6404  str);
6405  free(buf);
6406  return NULL;
6407  }
6408  *(p++) = c;
6409  }
6410  }
6411 
6412  return buf;
6413 }
static bool get_hexdigit(char digit, int *value)
Definition: fe-connect.c:6424
char * c

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

Referenced by conninfo_storeval(), and conninfo_uri_parse_params().

◆ conninfo_uri_parse()

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

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

5928 {
5930 
5931  /* Make a working copy of PQconninfoOptions */
5932  options = conninfo_init(errorMessage);
5933  if (options == NULL)
5934  return NULL;
5935 
5936  if (!conninfo_uri_parse_options(options, uri, errorMessage))
5937  {
5939  return NULL;
5940  }
5941 
5942  /*
5943  * Add in defaults if the caller wants that.
5944  */
5945  if (use_defaults)
5946  {
5947  if (!conninfo_add_defaults(options, errorMessage))
5948  {
5950  return NULL;
5951  }
5952  }
5953 
5954  return options;
5955 }
static bool conninfo_uri_parse_options(PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage)
Definition: fe-connect.c:5979

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

Referenced by parse_connection_string().

◆ conninfo_uri_parse_options()

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

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

5981 {
5982  int prefix_len;
5983  char *p;
5984  char *buf = NULL;
5985  char *start;
5986  char prevchar = '\0';
5987  char *user = NULL;
5988  char *host = NULL;
5989  bool retval = false;
5990  PQExpBufferData hostbuf;
5991  PQExpBufferData portbuf;
5992 
5993  initPQExpBuffer(&hostbuf);
5994  initPQExpBuffer(&portbuf);
5995  if (PQExpBufferDataBroken(hostbuf) || PQExpBufferDataBroken(portbuf))
5996  {
5997  appendPQExpBufferStr(errorMessage,
5998  libpq_gettext("out of memory\n"));
5999  goto cleanup;
6000  }
6001 
6002  /* need a modifiable copy of the input URI */
6003  buf = strdup(uri);
6004  if (buf == NULL)
6005  {
6006  appendPQExpBufferStr(errorMessage,
6007  libpq_gettext("out of memory\n"));
6008  goto cleanup;
6009  }
6010  start = buf;
6011 
6012  /* Skip the URI prefix */
6013  prefix_len = uri_prefix_length(uri);
6014  if (prefix_len == 0)
6015  {
6016  /* Should never happen */
6017  appendPQExpBuffer(errorMessage,
6018  libpq_gettext("invalid URI propagated to internal parser routine: \"%s\"\n"),
6019  uri);
6020  goto cleanup;
6021  }
6022  start += prefix_len;
6023  p = start;
6024 
6025  /* Look ahead for possible user credentials designator */
6026  while (*p && *p != '@' && *p != '/')
6027  ++p;
6028  if (*p == '@')
6029  {
6030  /*
6031  * Found username/password designator, so URI should be of the form
6032  * "scheme://user[:password]@[netloc]".
6033  */
6034  user = start;
6035 
6036  p = user;
6037  while (*p != ':' && *p != '@')
6038  ++p;
6039 
6040  /* Save last char and cut off at end of user name */
6041  prevchar = *p;
6042  *p = '\0';
6043 
6044  if (*user &&
6045  !conninfo_storeval(options, "user", user,
6046  errorMessage, false, true))
6047  goto cleanup;
6048 
6049  if (prevchar == ':')
6050  {
6051  const char *password = p + 1;
6052 
6053  while (*p != '@')
6054  ++p;
6055  *p = '\0';
6056 
6057  if (*password &&
6058  !conninfo_storeval(options, "password", password,
6059  errorMessage, false, true))
6060  goto cleanup;
6061  }
6062 
6063  /* Advance past end of parsed user name or password token */
6064  ++p;
6065  }
6066  else
6067  {
6068  /*
6069  * No username/password designator found. Reset to start of URI.
6070  */
6071  p = start;
6072  }
6073 
6074  /*
6075  * There may be multiple netloc[:port] pairs, each separated from the next
6076  * by a comma. When we initially enter this loop, "p" has been
6077  * incremented past optional URI credential information at this point and
6078  * now points at the "netloc" part of the URI. On subsequent loop
6079  * iterations, "p" has been incremented past the comma separator and now
6080  * points at the start of the next "netloc".
6081  */
6082  for (;;)
6083  {
6084  /*
6085  * Look for IPv6 address.
6086  */
6087  if (*p == '[')
6088  {
6089  host = ++p;
6090  while (*p && *p != ']')
6091  ++p;
6092  if (!*p)
6093  {
6094  appendPQExpBuffer(errorMessage,
6095  libpq_gettext("end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"\n"),
6096  uri);
6097  goto cleanup;
6098  }
6099  if (p == host)
6100  {
6101  appendPQExpBuffer(errorMessage,
6102  libpq_gettext("IPv6 host address may not be empty in URI: \"%s\"\n"),
6103  uri);
6104  goto cleanup;
6105  }
6106 
6107  /* Cut off the bracket and advance */
6108  *(p++) = '\0';
6109 
6110  /*
6111  * The address may be followed by a port specifier or a slash or a
6112  * query or a separator comma.
6113  */
6114  if (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',')
6115  {
6116  appendPQExpBuffer(errorMessage,
6117  libpq_gettext("unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"\n"),
6118  *p, (int) (p - buf + 1), uri);
6119  goto cleanup;
6120  }
6121  }
6122  else
6123  {
6124  /* not an IPv6 address: DNS-named or IPv4 netloc */
6125  host = p;
6126 
6127  /*
6128  * Look for port specifier (colon) or end of host specifier
6129  * (slash) or query (question mark) or host separator (comma).
6130  */
6131  while (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',')
6132  ++p;
6133  }
6134 
6135  /* Save the hostname terminator before we null it */
6136  prevchar = *p;
6137  *p = '\0';
6138 
6139  appendPQExpBufferStr(&hostbuf, host);
6140 
6141  if (prevchar == ':')
6142  {
6143  const char *port = ++p; /* advance past host terminator */
6144 
6145  while (*p && *p != '/' && *p != '?' && *p != ',')
6146  ++p;
6147 
6148  prevchar = *p;
6149  *p = '\0';
6150 
6151  appendPQExpBufferStr(&portbuf, port);
6152  }
6153 
6154  if (prevchar != ',')
6155  break;
6156  ++p; /* advance past comma separator */
6157  appendPQExpBufferChar(&hostbuf, ',');
6158  appendPQExpBufferChar(&portbuf, ',');
6159  }
6160 
6161  /* Save final values for host and port. */
6162  if (PQExpBufferDataBroken(hostbuf) || PQExpBufferDataBroken(portbuf))
6163  goto cleanup;
6164  if (hostbuf.data[0] &&
6165  !conninfo_storeval(options, "host", hostbuf.data,
6166  errorMessage, false, true))
6167  goto cleanup;
6168  if (portbuf.data[0] &&
6169  !conninfo_storeval(options, "port", portbuf.data,
6170  errorMessage, false, true))
6171  goto cleanup;
6172 
6173  if (prevchar && prevchar != '?')
6174  {
6175  const char *dbname = ++p; /* advance past host terminator */
6176 
6177  /* Look for query parameters */
6178  while (*p && *p != '?')
6179  ++p;
6180 
6181  prevchar = *p;
6182  *p = '\0';
6183 
6184  /*
6185  * Avoid setting dbname to an empty string, as it forces the default
6186  * value (username) and ignores $PGDATABASE, as opposed to not setting
6187  * it at all.
6188  */
6189  if (*dbname &&
6190  !conninfo_storeval(options, "dbname", dbname,
6191  errorMessage, false, true))
6192  goto cleanup;
6193  }
6194 
6195  if (prevchar)
6196  {
6197  ++p; /* advance past terminator */
6198 
6199  if (!conninfo_uri_parse_params(p, options, errorMessage))
6200  goto cleanup;
6201  }
6202 
6203  /* everything parsed okay */
6204  retval = true;
6205 
6206 cleanup:
6207  termPQExpBuffer(&hostbuf);
6208  termPQExpBuffer(&portbuf);
6209  if (buf)
6210  free(buf);
6211  return retval;
6212 }
static void cleanup(void)
Definition: bootstrap.c:697
static int uri_prefix_length(const char *connstr)
Definition: fe-connect.c:5445
static bool conninfo_uri_parse_params(char *params, PQconninfoOption *connOptions, PQExpBuffer errorMessage)
Definition: fe-connect.c:6223
static char * user
Definition: pg_regress.c:95
static int port
Definition: pg_regress.c:92
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:380
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
#define PQExpBufferDataBroken(buf)
Definition: pqexpbuffer.h:67
static char * password
Definition: streamutil.c:53
char * dbname
Definition: streamutil.c:51

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

Referenced by conninfo_uri_parse().

◆ conninfo_uri_parse_params()

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

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

6226 {
6227  while (*params)
6228  {
6229  char *keyword = params;
6230  char *value = NULL;
6231  char *p = params;
6232  bool malloced = false;
6233  int oldmsglen;
6234 
6235  /*
6236  * Scan the params string for '=' and '&', marking the end of keyword
6237  * and value respectively.
6238  */
6239  for (;;)
6240  {
6241  if (*p == '=')
6242  {
6243  /* Was there '=' already? */
6244  if (value != NULL)
6245  {
6246  appendPQExpBuffer(errorMessage,
6247  libpq_gettext("extra key/value separator \"=\" in URI query parameter: \"%s\"\n"),
6248  keyword);
6249  return false;
6250  }
6251  /* Cut off keyword, advance to value */
6252  *p++ = '\0';
6253  value = p;
6254  }
6255  else if (*p == '&' || *p == '\0')
6256  {
6257  /*
6258  * If not at the end, cut off value and advance; leave p
6259  * pointing to start of the next parameter, if any.
6260  */
6261  if (*p != '\0')
6262  *p++ = '\0';
6263  /* Was there '=' at all? */
6264  if (value == NULL)
6265  {
6266  appendPQExpBuffer(errorMessage,
6267  libpq_gettext("missing key/value separator \"=\" in URI query parameter: \"%s\"\n"),
6268  keyword);
6269  return false;
6270  }
6271  /* Got keyword and value, go process them. */
6272  break;
6273  }
6274  else
6275  ++p; /* Advance over all other bytes. */
6276  }
6277 
6278  keyword = conninfo_uri_decode(keyword, errorMessage);
6279  if (keyword == NULL)
6280  {
6281  /* conninfo_uri_decode already set an error message */
6282  return false;
6283  }
6284  value = conninfo_uri_decode(value, errorMessage);
6285  if (value == NULL)
6286  {
6287  /* conninfo_uri_decode already set an error message */
6288  free(keyword);
6289  return false;
6290  }
6291  malloced = true;
6292 
6293  /*
6294  * Special keyword handling for improved JDBC compatibility.
6295  */
6296  if (strcmp(keyword, "ssl") == 0 &&
6297  strcmp(value, "true") == 0)
6298  {
6299  free(keyword);
6300  free(value);
6301  malloced = false;
6302 
6303  keyword = "sslmode";
6304  value = "require";
6305  }
6306 
6307  /*
6308  * Store the value if the corresponding option exists; ignore
6309  * otherwise. At this point both keyword and value are not
6310  * URI-encoded.
6311  */
6312  oldmsglen = errorMessage->len;
6313  if (!conninfo_storeval(connOptions, keyword, value,
6314  errorMessage, true, false))
6315  {
6316  /* Insert generic message if conninfo_storeval didn't give one. */
6317  if (errorMessage->len == oldmsglen)
6318  appendPQExpBuffer(errorMessage,
6319  libpq_gettext("invalid URI query parameter: \"%s\"\n"),
6320  keyword);
6321  /* And fail. */
6322  if (malloced)
6323  {
6324  free(keyword);
6325  free(value);
6326  }
6327  return false;
6328  }
6329 
6330  if (malloced)
6331  {
6332  free(keyword);
6333  free(value);
6334  }
6335 
6336  /* Proceed to next key=value pair, if any */
6337  params = p;
6338  }
6339 
6340  return true;
6341 }

References appendPQExpBuffer(), conninfo_storeval(), conninfo_uri_decode(), free, PQExpBufferData::len, libpq_gettext, and value.

Referenced by conninfo_uri_parse_options().

◆ count_comma_separated_elems()

static int count_comma_separated_elems ( const char *  input)
static

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

967 {
968  int n;
969 
970  n = 1;
971  for (; *input != '\0'; input++)
972  {
973  if (*input == ',')
974  n++;
975  }
976 
977  return n;
978 }

Referenced by connectOptions2().

◆ default_threadlock()

static void default_threadlock ( int  acquire)
static

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

7303 {
7304 #ifdef ENABLE_THREAD_SAFETY
7305 #ifndef WIN32
7306  static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
7307 #else
7308  static pthread_mutex_t singlethread_lock = NULL;
7309  static long mutex_initlock = 0;
7310 
7311  if (singlethread_lock == NULL)
7312  {
7313  while (InterlockedExchange(&mutex_initlock, 1) == 1)
7314  /* loop, another thread own the lock */ ;
7315  if (singlethread_lock == NULL)
7316  {
7317  if (pthread_mutex_init(&singlethread_lock, NULL))
7318  Assert(false);
7319  }
7320  InterlockedExchange(&mutex_initlock, 0);
7321  }
7322 #endif
7323  if (acquire)
7324  {
7325  if (pthread_mutex_lock(&singlethread_lock))
7326  Assert(false);
7327  }
7328  else
7329  {
7330  if (pthread_mutex_unlock(&singlethread_lock))
7331  Assert(false);
7332  }
7333 #endif
7334 }
int pthread_mutex_unlock(pthread_mutex_t *mp)
Definition: pthread-win32.c:54
int pthread_mutex_lock(pthread_mutex_t *mp)
Definition: pthread-win32.c:45
int pthread_mutex_init(pthread_mutex_t *mp, void *attr)
Definition: pthread-win32.c:35
CRITICAL_SECTION * pthread_mutex_t
Definition: pthread-win32.h:8

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

Referenced by PQregisterThreadLock().

◆ defaultNoticeProcessor()

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

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

6977 {
6978  (void) arg; /* not used */
6979  /* Note: we expect the supplied string to end with a newline already. */
6980  fprintf(stderr, "%s", message);
6981 }
void * arg
#define fprintf
Definition: port.h:226

References arg, and fprintf.

Referenced by makeEmptyPGconn().

◆ defaultNoticeReceiver()

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

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

6962 {
6963  (void) arg; /* not used */
6964  if (res->noticeHooks.noticeProc != NULL)
6967 }
char * PQresultErrorMessage(const PGresult *res)
Definition: fe-exec.c:3194
void * noticeProcArg
Definition: libpq-int.h:156
PQnoticeProcessor noticeProc
Definition: libpq-int.h:155
PGNoticeHooks noticeHooks
Definition: libpq-int.h:187

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

Referenced by makeEmptyPGconn().

◆ emitHostIdentityInfo()

static void emitHostIdentityInfo ( PGconn conn,
const char *  host_addr 
)
static

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

1695 {
1696 #ifdef HAVE_UNIX_SOCKETS
1697  if (IS_AF_UNIX(conn->raddr.addr.ss_family))
1698  {
1699  char service[NI_MAXHOST];
1700 
1702  NULL, 0,
1703  service, sizeof(service),
1704  NI_NUMERICSERV);
1706  libpq_gettext("connection to server on socket \"%s\" failed: "),
1707  service);
1708  }
1709  else
1710 #endif /* HAVE_UNIX_SOCKETS */
1711  {
1712  const char *displayed_host;
1713  const char *displayed_port;
1714 
1715  /* To which host and port were we actually connecting? */
1717  displayed_host = conn->connhost[conn->whichhost].hostaddr;
1718  else
1719  displayed_host = conn->connhost[conn->whichhost].host;
1720  displayed_port = conn->connhost[conn->whichhost].port;
1721  if (displayed_port == NULL || displayed_port[0] == '\0')
1722  displayed_port = DEF_PGPORT_STR;
1723 
1724  /*
1725  * If the user did not supply an IP address using 'hostaddr', and
1726  * 'host' was missing or does not match our lookup, display the
1727  * looked-up IP address.
1728  */
1730  host_addr[0] &&
1731  strcmp(displayed_host, host_addr) != 0)
1733  libpq_gettext("connection to server at \"%s\" (%s), port %s failed: "),
1734  displayed_host, host_addr,
1735  displayed_port);
1736  else
1738  libpq_gettext("connection to server at \"%s\", port %s failed: "),
1739  displayed_host,
1740  displayed_port);
1741  }
1742 }
#define NI_MAXHOST
Definition: getaddrinfo.h:88
#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
socklen_t salen
Definition: pqcomm.h:65

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

Referenced by PQconnectPoll().

◆ fillPGconn()

static bool fillPGconn ( PGconn conn,
PQconninfoOption connOptions 
)
static

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

888 {
890 
891  for (option = PQconninfoOptions; option->keyword; option++)
892  {
893  if (option->connofs >= 0)
894  {
895  const char *tmp = conninfo_getval(connOptions, option->keyword);
896 
897  if (tmp)
898  {
899  char **connmember = (char **) ((char *) conn + option->connofs);
900 
901  if (*connmember)
902  free(*connmember);
903  *connmember = strdup(tmp);
904  if (*connmember == NULL)
905  {
907  libpq_gettext("out of memory\n"));
908  return false;
909  }
910  }
911  }
912  }
913 
914  return true;
915 }
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6445

References appendPQExpBufferStr(), conn, conninfo_getval(), pg_conn::errorMessage, free, libpq_gettext, and PQconninfoOptions.

Referenced by connectOptions1(), and PQconnectStartParams().

◆ freePGconn()

static void freePGconn ( PGconn conn)
static

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

4042 {
4043  int i;
4044 
4045  /* let any event procs clean up their state data */
4046  for (i = 0; i < conn->nEvents; i++)
4047  {
4048  PGEventConnDestroy evt;
4049 
4050  evt.conn = conn;
4051  (void) conn->events[i].proc(PGEVT_CONNDESTROY, &evt,
4052  conn->events[i].passThrough);
4053  free(conn->events[i].name);
4054  }
4055 
4056  /* clean up pg_conn_host structures */
4057  if (conn->connhost != NULL)
4058  {
4059  for (i = 0; i < conn->nconnhost; ++i)
4060  {
4061  if (conn->connhost[i].host != NULL)
4062  free(conn->connhost[i].host);
4063  if (conn->connhost[i].hostaddr != NULL)
4065  if (conn->connhost[i].port != NULL)
4066  free(conn->connhost[i].port);
4067  if (conn->connhost[i].password != NULL)
4068  {
4071  }
4072  }
4073  free(conn->connhost);
4074  }
4075 
4078  if (conn->events)
4079  free(conn->events);
4080  if (conn->pghost)
4081  free(conn->pghost);
4082  if (conn->pghostaddr)
4083  free(conn->pghostaddr);
4084  if (conn->pgport)
4085  free(conn->pgport);
4086  if (conn->connect_timeout)
4088  if (conn->pgtcp_user_timeout)
4090  if (conn->pgoptions)
4091  free(conn->pgoptions);
4092  if (conn->appname)
4093  free(conn->appname);
4094  if (conn->fbappname)
4095  free(conn->fbappname);
4096  if (conn->dbName)
4097  free(conn->dbName);
4098  if (conn->replication)
4099  free(conn->replication);
4100  if (conn->pguser)
4101  free(conn->pguser);
4102  if (conn->pgpass)
4103  {
4104  explicit_bzero(conn->pgpass, strlen(conn->pgpass));
4105  free(conn->pgpass);
4106  }
4107  if (conn->pgpassfile)
4108  free(conn->pgpassfile);
4109  if (conn->channel_binding)
4111  if (conn->keepalives)
4112  free(conn->keepalives);
4113  if (conn->keepalives_idle)
4117  if (conn->keepalives_count)
4119  if (conn->sslmode)
4120  free(conn->sslmode);
4121  if (conn->sslcert)
4122  free(conn->sslcert);
4123  if (conn->sslkey)
4124  free(conn->sslkey);
4125  if (conn->sslpassword)
4126  {
4128  free(conn->sslpassword);
4129  }
4130  if (conn->sslrootcert)
4131  free(conn->sslrootcert);
4132  if (conn->sslcrl)
4133  free(conn->sslcrl);
4134  if (conn->sslcrldir)
4135  free(conn->sslcrldir);
4136  if (conn->sslcompression)
4138  if (conn->sslsni)
4139  free(conn->sslsni);
4140  if (conn->requirepeer)
4141  free(conn->requirepeer);
4146  if (conn->gssencmode)
4147  free(conn->gssencmode);
4148  if (conn->krbsrvname)
4149  free(conn->krbsrvname);
4150  if (conn->gsslib)
4151  free(conn->gsslib);
4152  if (conn->connip)
4153  free(conn->connip);
4154  /* Note that conn->Pfdebug is not ours to close or free */
4155  if (conn->write_err_msg)
4157  if (conn->inBuffer)
4158  free(conn->inBuffer);
4159  if (conn->outBuffer)
4160  free(conn->outBuffer);
4161  if (conn->rowBuf)
4162  free(conn->rowBuf);
4167 
4168  free(conn);
4169 }
@ PGEVT_CONNDESTROY
Definition: libpq-events.h:31
void explicit_bzero(void *buf, size_t len)
void * passThrough
Definition: libpq-int.h:163
char * name
Definition: libpq-int.h:162
PGEventProc proc
Definition: libpq-int.h:161
char * replication
Definition: libpq-int.h:367
char * write_err_msg
Definition: libpq-int.h:455
char * sslrootcert
Definition: libpq-int.h:384
PGdataValue * rowBuf
Definition: libpq-int.h:496
char * sslcompression
Definition: libpq-int.h:380
char * inBuffer
Definition: libpq-int.h:479
char * sslcrldir
Definition: libpq-int.h:386
char * pgoptions
Definition: libpq-int.h:363
char * sslcrl
Definition: libpq-int.h:385
char * fbappname
Definition: libpq-int.h:365
char * sslcert
Definition: libpq-int.h:382
char * sslpassword
Definition: libpq-int.h:383
PQExpBufferData workBuffer
Definition: libpq-int.h:574
char * keepalives_idle
Definition: libpq-int.h:374
char * connip
Definition: libpq-int.h:428
char * keepalives
Definition: libpq-int.h:373
char * keepalives_interval
Definition: libpq-int.h:375
char * appname
Definition: libpq-int.h:364
char * pgtcp_user_timeout
Definition: libpq-int.h:361
int nEvents
Definition: libpq-int.h:406
char * sslkey
Definition: libpq-int.h:381
char * krbsrvname
Definition: libpq-int.h:390
char * gsslib
Definition: libpq-int.h:391
char * keepalives_count
Definition: libpq-int.h:377
char * requirepeer
Definition: libpq-int.h:388
char * sslsni
Definition: libpq-int.h:387
PGEvent * events
Definition: libpq-int.h:405
char * outBuffer
Definition: libpq-int.h:486

References pg_conn::appname, pg_conn::channel_binding, pg_conn::client_encoding_initial, conn, PGEventConnDestroy::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, 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::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::sslcrldir, pg_conn::sslkey, pg_conn::sslmode, pg_conn::sslpassword, pg_conn::sslrootcert, pg_conn::sslsni, pg_conn::target_session_attrs, termPQExpBuffer(), pg_conn::workBuffer, and pg_conn::write_err_msg.

Referenced by makeEmptyPGconn(), and PQfinish().

◆ get_hexdigit()

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

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

6425 {
6426  if ('0' <= digit && digit <= '9')
6427  *value = digit - '0';
6428  else if ('A' <= digit && digit <= 'F')
6429  *value = digit - 'A' + 10;
6430  else if ('a' <= digit && digit <= 'f')
6431  *value = digit - 'a' + 10;
6432  else
6433  return false;
6434 
6435  return true;
6436 }

References value.

Referenced by conninfo_uri_decode().

◆ getHostaddr()

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

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

1660 {
1661  struct sockaddr_storage *addr = &conn->raddr.addr;
1662 
1663  if (addr->ss_family == AF_INET)
1664  {
1665  if (pg_inet_net_ntop(AF_INET,
1666  &((struct sockaddr_in *) addr)->sin_addr.s_addr,
1667  32,
1668  host_addr, host_addr_len) == NULL)
1669  host_addr[0] = '\0';
1670  }
1671 #ifdef HAVE_IPV6
1672  else if (addr->ss_family == AF_INET6)
1673  {
1674  if (pg_inet_net_ntop(AF_INET6,
1675  &((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr,
1676  128,
1677  host_addr, host_addr_len) == NULL)
1678  host_addr[0] = '\0';
1679  }
1680 #endif
1681  else
1682  host_addr[0] = '\0';
1683 }
char * pg_inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size)
Definition: inet_net_ntop.c:77

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

Referenced by PQconnectPoll().

◆ internal_cancel()

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

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

4431 {
4432  int save_errno = SOCK_ERRNO;
4433  pgsocket tmpsock = PGINVALID_SOCKET;
4434  char sebuf[PG_STRERROR_R_BUFLEN];
4435  int maxlen;
4436  struct
4437  {
4438  uint32 packetlen;
4440  } crp;
4441 
4442  /*
4443  * We need to open a temporary connection to the postmaster. Do this with
4444  * only kernel calls.
4445  */
4446  if ((tmpsock = socket(raddr->addr.ss_family, SOCK_STREAM, 0)) == PGINVALID_SOCKET)
4447  {
4448  strlcpy(errbuf, "PQcancel() -- socket() failed: ", errbufsize);
4449  goto cancel_errReturn;
4450  }
4451 retry3:
4452  if (connect(tmpsock, (struct sockaddr *) &raddr->addr,
4453  raddr->salen) < 0)
4454  {
4455  if (SOCK_ERRNO == EINTR)
4456  /* Interrupted system call - we'll just try again */
4457  goto retry3;
4458  strlcpy(errbuf, "PQcancel() -- connect() failed: ", errbufsize);
4459  goto cancel_errReturn;
4460  }
4461 
4462  /*
4463  * We needn't set nonblocking I/O or NODELAY options here.
4464  */
4465 
4466  /* Create and send the cancel request packet. */
4467 
4468  crp.packetlen = pg_hton32((uint32) sizeof(crp));
4469  crp.cp.cancelRequestCode = (MsgType) pg_hton32(CANCEL_REQUEST_CODE);
4470  crp.cp.backendPID = pg_hton32(be_pid);
4471  crp.cp.cancelAuthCode = pg_hton32(be_key);
4472 
4473 retry4:
4474  if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp))
4475  {
4476  if (SOCK_ERRNO == EINTR)
4477  /* Interrupted system call - we'll just try again */
4478  goto retry4;
4479  strlcpy(errbuf, "PQcancel() -- send() failed: ", errbufsize);
4480  goto cancel_errReturn;
4481  }
4482 
4483  /*
4484  * Wait for the postmaster to close the connection, which indicates that
4485  * it's processed the request. Without this delay, we might issue another
4486  * command only to find that our cancel zaps that command instead of the
4487  * one we thought we were canceling. Note we don't actually expect this
4488  * read to obtain any data, we are just waiting for EOF to be signaled.
4489  */
4490 retry5:
4491  if (recv(tmpsock, (char *) &crp, 1, 0) < 0)
4492  {
4493  if (SOCK_ERRNO == EINTR)
4494  /* Interrupted system call - we'll just try again */
4495  goto retry5;
4496  /* we ignore other error conditions */
4497  }
4498 
4499  /* All done */
4500  closesocket(tmpsock);
4501  SOCK_ERRNO_SET(save_errno);
4502  return true;
4503 
4504 cancel_errReturn:
4505 
4506  /*
4507  * Make sure we don't overflow the error buffer. Leave space for the \n at
4508  * the end, and for the terminating zero.
4509  */
4510  maxlen = errbufsize - strlen(errbuf) - 2;
4511  if (maxlen >= 0)
4512  {
4513  strncat(errbuf, SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)),
4514  maxlen);
4515  strcat(errbuf, "\n");
4516  }
4517  if (tmpsock != PGINVALID_SOCKET)
4518  closesocket(tmpsock);
4519  SOCK_ERRNO_SET(save_errno);
4520  return false;
4521 }
unsigned int uint32
Definition: c.h:441
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:856
#define pg_hton32(x)
Definition: pg_bswap.h:121
int pgsocket
Definition: port.h:31
#define PGINVALID_SOCKET
Definition: port.h:33
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define closesocket
Definition: port.h:338
#define CANCEL_REQUEST_CODE
Definition: pqcomm.h:176
ProtocolVersion MsgType
Definition: pqcomm.h:127
#define EINTR
Definition: win32_port.h:351
#define recv(s, buf, len, flags)
Definition: win32_port.h:475
#define send(s, buf, len, flags)
Definition: win32_port.h:476
#define socket(af, type, protocol)
Definition: win32_port.h:469
#define connect(s, name, namelen)
Definition: win32_port.h:473

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

◆ internal_ping()

static PGPing internal_ping ( PGconn conn)
static

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

3879 {
3880  /* Say "no attempt" if we never got to PQconnectPoll */
3881  if (!conn || !conn->options_valid)
3882  return PQPING_NO_ATTEMPT;
3883 
3884  /* Attempt to complete the connection */
3885  if (conn->status != CONNECTION_BAD)
3886  (void) connectDBComplete(conn);
3887 
3888  /* Definitely OK if we succeeded */
3889  if (conn->status != CONNECTION_BAD)
3890  return PQPING_OK;
3891 
3892  /*
3893  * Here begins the interesting part of "ping": determine the cause of the
3894  * failure in sufficient detail to decide what to return. We do not want
3895  * to report that the server is not up just because we didn't have a valid
3896  * password, for example. In fact, any sort of authentication request
3897  * implies the server is up. (We need this check since the libpq side of
3898  * things might have pulled the plug on the connection before getting an
3899  * error as such from the postmaster.)
3900  */
3901  if (conn->auth_req_received)
3902  return PQPING_OK;
3903 
3904  /*
3905  * If we failed to get any ERROR response from the postmaster, report
3906  * PQPING_NO_RESPONSE. This result could be somewhat misleading for a
3907  * pre-7.4 server, since it won't send back a SQLSTATE, but those are long
3908  * out of support. Another corner case where the server could return a
3909  * failure without a SQLSTATE is fork failure, but PQPING_NO_RESPONSE
3910  * isn't totally unreasonable for that anyway. We expect that every other
3911  * failure case in a modern server will produce a report with a SQLSTATE.
3912  *
3913  * NOTE: whenever we get around to making libpq generate SQLSTATEs for
3914  * client-side errors, we should either not store those into
3915  * last_sqlstate, or add an extra flag so we can tell client-side errors
3916  * apart from server-side ones.
3917  */
3918  if (strlen(conn->last_sqlstate) != 5)
3919  return PQPING_NO_RESPONSE;
3920 
3921  /*
3922  * Report PQPING_REJECT if server says it's not accepting connections. (We
3923  * distinguish this case mainly for the convenience of pg_ctl.)
3924  */
3925  if (strcmp(conn->last_sqlstate, ERRCODE_CANNOT_CONNECT_NOW) == 0)
3926  return PQPING_REJECT;
3927 
3928  /*
3929  * Any other SQLSTATE can be taken to indicate that the server is up.
3930  * Presumably it didn't like our username, password, or database name; or
3931  * perhaps it had some transient failure, but that should not be taken as
3932  * meaning "it's down".
3933  */
3934  return PQPING_OK;
3935 }
static int connectDBComplete(PGconn *conn)
Definition: fe-connect.c:2110
#define ERRCODE_CANNOT_CONNECT_NOW
Definition: fe-connect.c:96
@ PQPING_OK
Definition: libpq-fe.h:145
@ PQPING_REJECT
Definition: libpq-fe.h:146
@ PQPING_NO_RESPONSE
Definition: libpq-fe.h:147
@ PQPING_NO_ATTEMPT
Definition: libpq-fe.h:148
bool auth_req_received
Definition: libpq-int.h:450
char last_sqlstate[6]
Definition: libpq-int.h:413

References pg_conn::auth_req_received, conn, 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().

◆ makeEmptyPGconn()

static PGconn * makeEmptyPGconn ( void  )
static

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

3944 {
3945  PGconn *conn;
3946 
3947 #ifdef WIN32
3948 
3949  /*
3950  * Make sure socket support is up and running in this process.
3951  *
3952  * Note: the Windows documentation says that we should eventually do a
3953  * matching WSACleanup() call, but experience suggests that that is at
3954  * least as likely to cause problems as fix them. So we don't.
3955  */
3956  static bool wsastartup_done = false;
3957 
3958  if (!wsastartup_done)
3959  {
3960  WSADATA wsaData;
3961 
3962  if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
3963  return NULL;
3964  wsastartup_done = true;
3965  }
3966 
3967  /* Forget any earlier error */
3968  WSASetLastError(0);
3969 #endif /* WIN32 */
3970 
3971  conn = (PGconn *) malloc(sizeof(PGconn));
3972  if (conn == NULL)
3973  return conn;
3974 
3975  /* Zero all pointers and booleans */
3976  MemSet(conn, 0, sizeof(PGconn));
3977 
3978  /* install default notice hooks */
3981 
3986  conn->options_valid = false;
3987  conn->nonblocking = false;
3989  conn->std_strings = false; /* unless server says differently */
3995  conn->Pfdebug = NULL;
3996 
3997  /*
3998  * We try to send at least 8K at a time, which is the usual size of pipe
3999  * buffers on Unix systems. That way, when we are sending a large amount
4000  * of data, we avoid incurring extra kernel context swaps for partial
4001  * bufferloads. The output buffer is initially made 16K in size, and we
4002  * try to dump it after accumulating 8K.
4003  *
4004  * With the same goal of minimizing context swaps, the input buffer will
4005  * be enlarged anytime it has less than 8K free, so we initially allocate
4006  * twice that.
4007  */
4008  conn->inBufSize = 16 * 1024;
4009  conn->inBuffer = (char *) malloc(conn->inBufSize);
4010  conn->outBufSize = 16 * 1024;
4011  conn->outBuffer = (char *) malloc(conn->outBufSize);
4012  conn->rowBufLen = 32;
4013  conn->rowBuf = (PGdataValue *) malloc(conn->rowBufLen * sizeof(PGdataValue));
4016 
4017  if (conn->inBuffer == NULL ||
4018  conn->outBuffer == NULL ||
4019  conn->rowBuf == NULL ||
4022  {
4023  /* out of memory already :-( */
4024  freePGconn(conn);
4025  conn = NULL;
4026  }
4027 
4028  return conn;
4029 }
static void defaultNoticeReceiver(void *arg, const PGresult *res)
Definition: fe-connect.c:6961
static void defaultNoticeProcessor(void *arg, const char *message)
Definition: fe-connect.c:6976
static void freePGconn(PGconn *conn)
Definition: fe-connect.c:4041
@ PQSHOW_CONTEXT_ERRORS
Definition: libpq-fe.h:134
@ PQERRORS_DEFAULT
Definition: libpq-fe.h:126
@ PG_BOOL_UNKNOWN
Definition: libpq-int.h:246
@ PG_SQL_ASCII
Definition: pg_wchar.h:224
#define PQExpBufferBroken(str)
Definition: pqexpbuffer.h:59
PQnoticeReceiver noticeRec
Definition: libpq-int.h:153
bool std_strings
Definition: libpq-int.h:471
PGTernaryBool in_hot_standby
Definition: libpq-int.h:473
int inBufSize
Definition: libpq-int.h:480
int client_encoding
Definition: libpq-int.h:470
PGTernaryBool default_transaction_read_only
Definition: libpq-int.h:472
PGVerbosity verbosity
Definition: libpq-int.h:474
int rowBufLen
Definition: libpq-int.h:497
int outBufSize
Definition: libpq-int.h:487
PGNoticeHooks noticeHooks
Definition: libpq-int.h:402
FILE * Pfdebug
Definition: libpq-int.h:398
PGContextVisibility show_context
Definition: libpq-int.h:475

References pg_conn::asyncStatus, pg_conn::client_encoding, conn, CONNECTION_BAD, pg_conn::default_transaction_read_only, defaultNoticeProcessor(), defaultNoticeReceiver(), pg_conn::errorMessage, freePGconn(), pg_conn::in_hot_standby, 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_conn::Pfdebug, PG_BOOL_UNKNOWN, PG_SQL_ASCII, PGASYNC_IDLE, PGINVALID_SOCKET, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, PQERRORS_DEFAULT, PQExpBufferBroken, PQSHOW_CONTEXT_ERRORS, PQTRANS_IDLE, pg_conn::rowBuf, pg_conn::rowBufLen, 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().

◆ parse_comma_separated_list()

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

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

991 {
992  char *p;
993  char *s = *startptr;
994  char *e;
995  int len;
996 
997  /*
998  * Search for the end of the current element; a comma or end-of-string
999  * acts as a terminator.
1000  */
1001  e = s;
1002  while (*e != '\0' && *e != ',')
1003  ++e;
1004  *more = (*e == ',');
1005 
1006  len = e - s;
1007  p = (char *) malloc(sizeof(char) * (len + 1));
1008  if (p)
1009  {
1010  memcpy(p, s, len);
1011  p[len] = '\0';
1012  }
1013  *startptr = e + 1;
1014 
1015  return p;
1016 }
const void size_t len
e
Definition: preproc-init.c:82

References len, and malloc.

Referenced by connectOptions2().

◆ parse_connection_string()

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

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

5427 {
5428  /* Parse as URI if connection string matches URI prefix */
5429  if (uri_prefix_length(connstr) != 0)
5430  return conninfo_uri_parse(connstr, errorMessage, use_defaults);
5431 
5432  /* Parse as default otherwise */
5433  return conninfo_parse(connstr, errorMessage, use_defaults);
5434 }
static PQconninfoOption * conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5926
static PQconninfoOption * conninfo_parse(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5479
static char * connstr
Definition: pg_dumpall.c:62

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

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

◆ parse_int_param()

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

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

1797 {
1798  char *end;
1799  long numval;
1800 
1801  Assert(value != NULL);
1802 
1803  *result = 0;
1804 
1805  /* strtol(3) skips leading whitespaces */
1806  errno = 0;
1807  numval = strtol(value, &end, 10);
1808 
1809  /*
1810  * If no progress was done during the parsing or an error happened, fail.
1811  * This tests properly for overflows of the result.
1812  */
1813  if (value == end || errno != 0 || numval != (int) numval)
1814  goto error;
1815 
1816  /*
1817  * Skip any trailing whitespace; if anything but whitespace remains before
1818  * the terminating character, fail
1819  */
1820  while (*end != '\0' && isspace((unsigned char) *end))
1821  end++;
1822 
1823  if (*end != '\0')
1824  goto error;
1825 
1826  *result = numval;
1827  return true;
1828 
1829 error:
1831  libpq_gettext("invalid integer value \"%s\" for connection option \"%s\"\n"),
1832  value, context);
1833  return false;
1834 }
static void error(void)
Definition: sql-dyntest.c:147

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

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

◆ parseServiceFile()

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

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

5188 {
5189  int result = 0,
5190  linenr = 0,
5191  i;
5192  FILE *f;
5193  char *line;
5194  char buf[1024];
5195 
5196  *group_found = false;
5197 
5198  f = fopen(serviceFile, "r");
5199  if (f == NULL)
5200  {
5201  appendPQExpBuffer(errorMessage, libpq_gettext("service file \"%s\" not found\n"),
5202  serviceFile);
5203  return 1;
5204  }
5205 
5206  while ((line = fgets(buf, sizeof(buf), f)) != NULL)
5207  {
5208  int len;
5209 
5210  linenr++;
5211 
5212  if (strlen(line) >= sizeof(buf) - 1)
5213  {
5214  appendPQExpBuffer(errorMessage,
5215  libpq_gettext("line %d too long in service file \"%s\"\n"),
5216  linenr,
5217  serviceFile);
5218  result = 2;
5219  goto exit;
5220  }
5221 
5222  /* ignore whitespace at end of line, especially the newline */
5223  len = strlen(line);
5224  while (len > 0 && isspace((unsigned char) line[len - 1]))
5225  line[--len] = '\0';
5226 
5227  /* ignore leading whitespace too */
5228  while (*line && isspace((unsigned char) line[0]))
5229  line++;
5230 
5231  /* ignore comments and empty lines */
5232  if (line[0] == '\0' || line[0] == '#')
5233  continue;
5234 
5235  /* Check for right groupname */
5236  if (line[0] == '[')
5237  {
5238  if (*group_found)
5239  {
5240  /* end of desired group reached; return success */
5241  goto exit;
5242  }
5243 
5244  if (strncmp(line + 1, service, strlen(service)) == 0 &&
5245  line[strlen(service) + 1] == ']')
5246  *group_found = true;
5247  else
5248  *group_found = false;
5249  }
5250  else
5251  {
5252  if (*group_found)
5253  {
5254  /*
5255  * Finally, we are in the right group and can parse the line
5256  */
5257  char *key,
5258  *val;
5259  bool found_keyword;
5260 
5261 #ifdef USE_LDAP
5262  if (strncmp(line, "ldap", 4) == 0)
5263  {
5264  int rc = ldapServiceLookup(line, options, errorMessage);
5265 
5266  /* if rc = 2, go on reading for fallback */
5267  switch (rc)
5268  {
5269  case 0:
5270  goto exit;
5271  case 1:
5272  case 3:
5273  result = 3;
5274  goto exit;
5275  case 2:
5276  continue;
5277  }
5278  }
5279 #endif
5280 
5281  key = line;
5282  val = strchr(line, '=');
5283  if (val == NULL)
5284  {
5285  appendPQExpBuffer(errorMessage,
5286  libpq_gettext("syntax error in service file \"%s\", line %d\n"),
5287  serviceFile,
5288  linenr);
5289  result = 3;
5290  goto exit;
5291  }
5292  *val++ = '\0';
5293 
5294  if (strcmp(key, "service") == 0)
5295  {
5296  appendPQExpBuffer(errorMessage,
5297  libpq_gettext("nested service specifications not supported in service file \"%s\", line %d\n"),
5298  serviceFile,
5299  linenr);
5300  result = 3;
5301  goto exit;
5302  }
5303 
5304  /*
5305  * Set the parameter --- but don't override any previous
5306  * explicit setting.
5307  */
5308  found_keyword = false;
5309  for (i = 0; options[i].keyword; i++)
5310  {
5311  if (strcmp(options[i].keyword, key) == 0)
5312  {
5313  if (options[i].val == NULL)
5314  options[i].val = strdup(val);
5315  if (!options[i].val)
5316  {
5317  appendPQExpBufferStr(errorMessage,
5318  libpq_gettext("out of memory\n"));
5319  result = 3;
5320  goto exit;
5321  }
5322  found_keyword = true;
5323  break;
5324  }
5325  }
5326 
5327  if (!found_keyword)
5328  {
5329  appendPQExpBuffer(errorMessage,
5330  libpq_gettext("syntax error in service file \"%s\", line %d\n"),
5331  serviceFile,
5332  linenr);
5333  result = 3;
5334  goto exit;
5335  }
5336  }
5337  }
5338  }
5339 
5340 exit:
5341  fclose(f);
5342 
5343  return result;
5344 }
exit(1)

References appendPQExpBuffer(), appendPQExpBufferStr(), buf, exit(), i, sort-test::key, len, libpq_gettext, and val.

Referenced by parseServiceInfo().

◆ parseServiceInfo()

static int parseServiceInfo ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

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

5115 {
5116  const char *service = conninfo_getval(options, "service");
5117  char serviceFile[MAXPGPATH];
5118  char *env;
5119  bool group_found = false;
5120  int status;
5121  struct stat stat_buf;
5122 
5123  /*
5124  * We have to special-case the environment variable PGSERVICE here, since
5125  * this is and should be called before inserting environment defaults for
5126  * other connection options.
5127  */
5128  if (service == NULL)
5129  service = getenv("PGSERVICE");
5130 
5131  /* If no service name given, nothing to do */
5132  if (service == NULL)
5133  return 0;
5134 
5135  /*
5136  * Try PGSERVICEFILE if specified, else try ~/.pg_service.conf (if that
5137  * exists).
5138  */
5139  if ((env = getenv("PGSERVICEFILE")) != NULL)
5140  strlcpy(serviceFile, env, sizeof(serviceFile));
5141  else
5142  {
5143  char homedir[MAXPGPATH];
5144 
5145  if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
5146  goto next_file;
5147  snprintf(serviceFile, MAXPGPATH, "%s/%s", homedir, ".pg_service.conf");
5148  if (stat(serviceFile, &stat_buf) != 0)
5149  goto next_file;
5150  }
5151 
5152  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
5153  if (group_found || status != 0)
5154  return status;
5155 
5156 next_file:
5157 
5158  /*
5159  * This could be used by any application so we can't use the binary
5160  * location to find our config files.
5161  */
5162  snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf",
5163  getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);
5164  if (stat(serviceFile, &stat_buf) != 0)
5165  goto last_file;
5166 
5167  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
5168  if (status != 0)
5169  return status;
5170 
5171 last_file:
5172  if (!group_found)
5173  {
5174  appendPQExpBuffer(errorMessage,
5175  libpq_gettext("definition of service \"%s\" not found\n"), service);
5176  return 3;
5177  }
5178 
5179  return 0;
5180 }
static int parseServiceFile(const char *serviceFile, const char *service, PQconninfoOption *options, PQExpBuffer errorMessage, bool *group_found)
Definition: fe-connect.c:5183
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:229
#define stat
Definition: win32_port.h:283

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

Referenced by conninfo_add_defaults().

◆ passwordFromFile()

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

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

7027 {
7028  FILE *fp;
7029  struct stat stat_buf;
7031 
7032  if (dbname == NULL || dbname[0] == '\0')
7033  return NULL;
7034 
7035  if (username == NULL || username[0] == '\0')
7036  return NULL;
7037 
7038  /* 'localhost' matches pghost of '' or the default socket directory */
7039  if (hostname == NULL || hostname[0] == '\0')
7041  else if (is_unixsock_path(hostname))
7042 
7043  /*
7044  * We should probably use canonicalize_path(), but then we have to
7045  * bring path.c into libpq, and it doesn't seem worth it.
7046  */
7047  if (strcmp(hostname, DEFAULT_PGSOCKET_DIR) == 0)
7049 
7050  if (port == NULL || port[0] == '\0')
7051  port = DEF_PGPORT_STR;
7052 
7053  /* If password file cannot be opened, ignore it. */
7054  if (stat(pgpassfile, &stat_buf) != 0)
7055  return NULL;
7056 
7057 #ifndef WIN32
7058  if (!S_ISREG(stat_buf.st_mode))
7059  {
7060  fprintf(stderr,
7061  libpq_gettext("WARNING: password file \"%s\" is not a plain file\n"),
7062  pgpassfile);
7063  return NULL;
7064  }
7065 
7066  /* If password file is insecure, alert the user and ignore it. */
7067  if (stat_buf.st_mode & (S_IRWXG | S_IRWXO))
7068  {
7069  fprintf(stderr,
7070  libpq_gettext("WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
7071  pgpassfile);
7072  return NULL;
7073  }
7074 #else
7075 
7076  /*
7077  * On Win32, the directory is protected, so we don't have to check the
7078  * file.
7079  */
7080 #endif
7081 
7082  fp = fopen(pgpassfile, "r");
7083  if (fp == NULL)
7084  return NULL;
7085 
7086  /* Use an expansible buffer to accommodate any reasonable line length */
7087  initPQExpBuffer(&buf);
7088 
7089  while (!feof(fp) && !ferror(fp))
7090  {
7091  /* Make sure there's a reasonable amount of room in the buffer */
7092  if (!enlargePQExpBuffer(&buf, 128))
7093  break;
7094 
7095  /* Read some data, appending it to what we already have */
7096  if (fgets(buf.data + buf.len, buf.maxlen - buf.len, fp) == NULL)
7097  break;
7098  buf.len += strlen(buf.data + buf.len);
7099 
7100  /* If we don't yet have a whole line, loop around to read more */
7101  if (!(buf.len > 0 && buf.data[buf.len - 1] == '\n') && !feof(fp))
7102  continue;
7103 
7104  /* ignore comments */
7105  if (buf.data[0] != '#')
7106  {
7107  char *t = buf.data;
7108  int len;
7109 
7110  /* strip trailing newline and carriage return */
7111  len = pg_strip_crlf(t);
7112 
7113  if (len > 0 &&
7114  (t = pwdfMatchesString(t, hostname)) != NULL &&
7115  (t = pwdfMatchesString(t, port)) != NULL &&
7116  (t = pwdfMatchesString(t, dbname)) != NULL &&
7117  (t = pwdfMatchesString(t, username)) != NULL)
7118  {
7119  /* Found a match. */
7120  char *ret,
7121  *p1,
7122  *p2;
7123 
7124  ret = strdup(t);
7125 
7126  fclose(fp);
7127  explicit_bzero(buf.data, buf.maxlen);
7128  termPQExpBuffer(&buf);
7129 
7130  if (!ret)
7131  {
7132  /* Out of memory. XXX: an error message would be nice. */
7133  return NULL;
7134  }
7135 
7136  /* De-escape password. */
7137  for (p1 = p2 = ret; *p1 != ':' && *p1 != '\0'; ++p1, ++p2)
7138  {
7139  if (*p1 == '\\' && p1[1] != '\0')
7140  ++p1;
7141  *p2 = *p1;
7142  }
7143  *p2 = '\0';
7144 
7145  return ret;
7146  }
7147  }
7148 
7149  /* No match, reset buffer to prepare for next line. */
7150  buf.len = 0;
7151  }
7152 
7153  fclose(fp);
7154  explicit_bzero(buf.data, buf.maxlen);
7155  termPQExpBuffer(&buf);
7156  return NULL;
7157 }
static char * pwdfMatchesString(char *buf, const char *token)
Definition: fe-connect.c:6988
static char * hostname
Definition: pg_regress.c:91
const char * username
Definition: pgbench.c:282
int enlargePQExpBuffer(PQExpBuffer str, size_t needed)
Definition: pqexpbuffer.c:174
int pg_strip_crlf(char *str)
Definition: string.c:121
#define S_IRWXG
Definition: win32_port.h:309
#define S_IRWXO
Definition: win32_port.h:321
#define S_ISREG(m)
Definition: win32_port.h:327

References buf, dbname, DEFAULT_PGSOCKET_DIR, DefaultHost, enlargePQExpBuffer(), explicit_bzero(), fprintf, hostname, initPQExpBuffer(), is_unixsock_path(), len, libpq_gettext, p2, pg_strip_crlf(), port, pwdfMatchesString(), S_IRWXG, S_IRWXO, S_ISREG, stat::st_mode, stat, termPQExpBuffer(), and username.

Referenced by connectOptions2().

◆ pgpassfileWarning()

static void pgpassfileWarning ( PGconn conn)
static

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

7166 {
7167  /* If it was 'invalid authorization', add pgpassfile mention */
7168  /* only works with >= 9.0 servers */
7169  if (conn->password_needed &&
7170  conn->connhost[conn->whichhost].password != NULL &&
7171  conn->result)
7172  {
7173  const char *sqlstate = PQresultErrorField(conn->result,
7175 
7176  if (sqlstate && strcmp(sqlstate, ERRCODE_INVALID_PASSWORD) == 0)
7178  libpq_gettext("password retrieved from file \"%s\"\n"),
7179  conn->pgpassfile);
7180  }
7181 }
#define ERRCODE_INVALID_PASSWORD
Definition: fe-connect.c:94
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:3233
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
PGresult * result
Definition: libpq-int.h:500
bool password_needed
Definition: libpq-int.h:451

References appendPQExpBuffer(), conn, 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().

◆ PQbackendPID()

int PQbackendPID ( const PGconn conn)

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

6805 {
6806  if (!conn || conn->status != CONNECTION_OK)
6807  return 0;
6808  return conn->be_pid;
6809 }
@ CONNECTION_OK
Definition: libpq-fe.h:58
int be_pid
Definition: libpq-int.h:467

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

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

◆ PQcancel()

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

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

4534 {
4535  if (!cancel)
4536  {
4537  strlcpy(errbuf, "PQcancel() -- no cancel object supplied", errbufsize);
4538  return false;
4539  }
4540 
4541  return internal_cancel(&cancel->raddr, cancel->be_pid, cancel->be_key,
4542  errbuf, errbufsize);
4543 }
static int internal_cancel(SockAddr *raddr, int be_pid, int be_key, char *errbuf, int errbufsize)
Definition: fe-connect.c:4429
SockAddr raddr
Definition: libpq-int.h:583
int be_pid
Definition: libpq-int.h:584
int be_key
Definition: libpq-int.h:585

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(), ShutdownWorkersHard(), sigTermHandler(), and try_complete_step().

◆ PQclientEncoding()

◆ PQconndefaults()

PQconninfoOption* PQconndefaults ( void  )

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

1473 {
1474  PQExpBufferData errorBuf;
1475  PQconninfoOption *connOptions;
1476 
1477  /* We don't actually report any errors here, but callees want a buffer */
1478  initPQExpBuffer(&errorBuf);
1479  if (PQExpBufferDataBroken(errorBuf))
1480  return NULL; /* out of memory already :-( */
1481 
1482  connOptions = conninfo_init(&errorBuf);
1483  if (connOptions != NULL)
1484  {
1485  /* pass NULL errorBuf to ignore errors */
1486  if (!conninfo_add_defaults(connOptions, NULL))
1487  {
1488  PQconninfoFree(connOptions);
1489  connOptions = NULL;
1490  }
1491  }
1492 
1493  termPQExpBuffer(&errorBuf);
1494  return connOptions;
1495 }

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

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

◆ PQconnectdb()

PGconn* PQconnectdb ( const char *  conninfo)

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

714 {
715  PGconn *conn = PQconnectStart(conninfo);
716 
717  if (conn && conn->status != CONNECTION_BAD)
718  (void) connectDBComplete(conn);
719 
720  return conn;
721 }
PGconn * PQconnectStart(const char *conninfo)
Definition: fe-connect.c:841

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

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

◆ PQconnectdbParams()

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

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

660 {
661  PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname);
662 
663  if (conn && conn->status != CONNECTION_BAD)
664  (void) connectDBComplete(conn);
665 
666  return conn;
667 
668 }
PGconn * PQconnectStartParams(const char *const *keywords, const char *const *values, int expand_dbname)
Definition: fe-connect.c:760

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

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

◆ PQconnectionNeedsPassword()

int PQconnectionNeedsPassword ( const PGconn conn)

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

6822 {
6823  char *password;
6824 
6825  if (!conn)
6826  return false;
6827  password = PQpass(conn);
6828  if (conn->password_needed &&
6829  (password == NULL || password[0] == '\0'))
6830  return true;
6831  else
6832  return false;
6833 }
char * PQpass(const PGconn *conn)
Definition: fe-connect.c:6632

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

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

◆ PQconnectionUsedPassword()

int PQconnectionUsedPassword ( const PGconn conn)

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

6837 {
6838  if (!conn)
6839  return false;
6840  if (conn->password_needed)
6841  return true;
6842  else
6843  return false;
6844 }

References conn, and pg_conn::password_needed.

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

◆ PQconnectPoll()

PostgresPollingStatusType PQconnectPoll ( PGconn conn)

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

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