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.

Referenced by connectOptions2().

◆ DefaultGSSMode

#define DefaultGSSMode   "disable"

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

Referenced by connectOptions2().

◆ DefaultHost

#define DefaultHost   "localhost"

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

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

◆ DefaultOption

#define DefaultOption   ""

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

◆ DefaultSSLMode

#define DefaultSSLMode   "disable"

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

Referenced by connectOptions2().

◆ 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.

Referenced by PQconnectPoll().

◆ ERRCODE_CANNOT_CONNECT_NOW

#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"

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

Referenced by internal_ping(), PQconnectPoll(), and ProcessStartupPacket().

◆ ERRCODE_INVALID_PASSWORD

#define ERRCODE_INVALID_PASSWORD   "28P01"

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

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

◆ PGPASSFILE

#define PGPASSFILE   ".pgpass"

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

Referenced by connectOptions2().

Typedef Documentation

◆ internalPQconninfoOption

Function Documentation

◆ closePGconn()

static void closePGconn ( PGconn conn)
static

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

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

4193 {
4194  /*
4195  * If possible, send Terminate message to close the connection politely.
4196  */
4197  sendTerminateConn(conn);
4198 
4199  /*
4200  * Must reset the blocking status so a possible reconnect will work.
4201  *
4202  * Don't call PQsetnonblocking() because it will fail if it's unable to
4203  * flush the connection.
4204  */
4205  conn->nonblocking = false;
4206 
4207  /*
4208  * Close the connection, reset all transient state, flush I/O buffers.
4209  * Note that this includes clearing conn->errorMessage; we're no longer
4210  * interested in any failures associated with the old connection, and we
4211  * want a clean slate for any new connection attempt.
4212  */
4213  pqDropConnection(conn, true);
4214  conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
4215  conn->asyncStatus = PGASYNC_IDLE;
4216  conn->xactStatus = PQTRANS_IDLE;
4218  pqClearAsyncResult(conn); /* deallocate result */
4220  release_conn_addrinfo(conn);
4221 
4222  /* Reset all state obtained from server, too */
4223  pqDropServerData(conn);
4224 }
static void release_conn_addrinfo(PGconn *conn)
Definition: fe-connect.c:4150
PGpipelineStatus pipelineStatus
Definition: libpq-int.h:417
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:448
static void sendTerminateConn(PGconn *conn)
Definition: fe-connect.c:4165
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:411
static void pqDropServerData(PGconn *conn)
Definition: fe-connect.c:556
PQExpBufferData errorMessage
Definition: libpq-int.h:571
ConnStatusType status
Definition: libpq-int.h:410
bool nonblocking
Definition: libpq-int.h:415
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:749
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148
PGTransactionStatusType xactStatus
Definition: libpq-int.h:412

◆ connectDBComplete()

static int connectDBComplete ( PGconn conn)
static

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

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

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 */
2130  conn->status = CONNECTION_BAD;
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 */
2181  conn->status = CONNECTION_BAD;
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 */
2191  conn->status = CONNECTION_BAD;
2192  return 0;
2193  }
2194  break;
2195 
2196  default:
2197  /* Just in case we failed to set it in PQconnectPoll */
2198  conn->status = CONNECTION_BAD;
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;
2208  conn->status = CONNECTION_NEEDED;
2209  }
2210 
2211  /*
2212  * Now try to advance the state machine.
2213  */
2214  flag = PQconnectPoll(conn);
2215  }
2216 }
struct addrinfo * addr_cur
Definition: libpq-int.h:462
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
char * connect_timeout
Definition: libpq-int.h:360
char * flag(int b)
Definition: test-ctype.c:33
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
Definition: fe-connect.c:2246
bool try_next_addr
Definition: libpq-int.h:459
ConnStatusType status
Definition: libpq-int.h:410
PostgresPollingStatusType
Definition: libpq-fe.h:82
int whichhost
Definition: libpq-int.h:426

◆ connectDBStart()

static int connectDBStart ( PGconn conn)
static

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

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

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;
2073  conn->status = CONNECTION_NEEDED;
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  */
2086  if (PQconnectPoll(conn) == PGRES_POLLING_WRITING)
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);
2097  conn->status = CONNECTION_BAD;
2098  return 0;
2099 }
int inEnd
Definition: libpq-int.h:483
int inStart
Definition: libpq-int.h:481
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
int outCount
Definition: libpq-int.h:488
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:448
bool try_next_host
Definition: libpq-int.h:460
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
Definition: fe-connect.c:2246
PQExpBufferData errorMessage
Definition: libpq-int.h:571
bool try_next_addr
Definition: libpq-int.h:459
bool options_valid
Definition: libpq-int.h:414
ConnStatusType status
Definition: libpq-int.h:410
int inCursor
Definition: libpq-int.h:482
PGTargetServerType target_server_type
Definition: libpq-int.h:458
int whichhost
Definition: libpq-int.h:426

◆ connectFailureMessage()

static void connectFailureMessage ( PGconn conn,
int  errorno 
)
static

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

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

Referenced by PQconnectPoll().

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 }
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
#define PG_STRERROR_R_BUFLEN
Definition: port.h:234
struct sockaddr_storage addr
Definition: pqcomm.h:64
#define SOCK_STRERROR
Definition: libpq-int.h:855
#define IS_AF_UNIX(fam)
Definition: ip.h:24
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
SockAddr raddr
Definition: libpq-int.h:447
PQExpBufferData errorMessage
Definition: libpq-int.h:571
#define libpq_gettext(x)
Definition: libpq-int.h:841

◆ connectNoDelay()

static int connectNoDelay ( PGconn conn)
static

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

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

Referenced by PQconnectPoll().

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 PG_STRERROR_R_BUFLEN
Definition: port.h:234
#define SOCK_STRERROR
Definition: libpq-int.h:855
#define SOCK_ERRNO
Definition: libpq-int.h:854
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
pgsocket sock
Definition: libpq-int.h:444
PQExpBufferData errorMessage
Definition: libpq-int.h:571
#define libpq_gettext(x)
Definition: libpq-int.h:841

◆ connectOptions1()

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

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

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

Referenced by PQconnectStart(), and PQsetdbLogin().

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  {
939  conn->status = CONNECTION_BAD;
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  {
949  conn->status = CONNECTION_BAD;
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 }
static PQconninfoOption * parse_connection_string(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5399
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6572
PQExpBufferData errorMessage
Definition: libpq-int.h:571
static bool fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
Definition: fe-connect.c:887
ConnStatusType status
Definition: libpq-int.h:410

◆ connectOptions2()

static bool connectOptions2 ( PGconn conn)
static

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

References appendPQExpBuffer(), appendPQExpBufferStr(), Assert, calloc, pg_conn::channel_binding, CHT_HOST_ADDRESS, CHT_HOST_NAME, CHT_UNIX_SOCKET, pg_conn::client_encoding_initial, CONNECTION_BAD, pg_conn::connhost, count_comma_separated_elems(), pg_conn::dbName, DEFAULT_PGSOCKET_DIR, DefaultChannelBinding, DefaultGSSMode, DefaultHost, DefaultSSLMode, pg_conn::errorMessage, free, pg_conn::gssencmode, pg_conn_host::host, pg_conn_host::hostaddr, i, is_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().

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  {
1059  conn->connhost[i].hostaddr = parse_comma_separated_list(&s, &more);
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  {
1080  conn->connhost[i].host = parse_comma_separated_list(&s, &more);
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  {
1088  conn->status = CONNECTION_BAD;
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  {
1149  conn->connhost[i].port = parse_comma_separated_list(&s, &more);
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  {
1169  conn->status = CONNECTION_BAD;
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);
1186  conn->pguser = pg_fe_getauthname(&conn->errorMessage);
1187  if (!conn->pguser)
1188  {
1189  conn->status = CONNECTION_BAD;
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);
1221  conn->pgpassfile = malloc(MAXPGPATH);
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  {
1262  conn->status = CONNECTION_BAD;
1264  libpq_gettext("invalid %s value: \"%s\"\n"),
1265  "channel_binding", conn->channel_binding);
1266  return false;
1267  }
1268  }
1269  else
1270  {
1271  conn->channel_binding = strdup(DefaultChannelBinding);
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  {
1288  conn->status = CONNECTION_BAD;
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" */
1309  conn->status = CONNECTION_BAD;
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  {
1330  conn->status = CONNECTION_BAD;
1332  libpq_gettext("invalid %s value: \"%s\"\n"),
1333  "ssl_min_protocol_version",
1334  conn->ssl_min_protocol_version);
1335  return false;
1336  }
1338  {
1339  conn->status = CONNECTION_BAD;
1341  libpq_gettext("invalid %s value: \"%s\"\n"),
1342  "ssl_max_protocol_version",
1343  conn->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  */
1355  conn->ssl_max_protocol_version))
1356  {
1357  conn->status = CONNECTION_BAD;
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  {
1372  conn->status = CONNECTION_BAD;
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  {
1382  conn->status = CONNECTION_BAD;
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  */
1400  if (conn->target_session_attrs)
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  {
1416  conn->status = CONNECTION_BAD;
1418  libpq_gettext("invalid %s value: \"%s\"\n"),
1419  "target_session_attrs",
1420  conn->target_session_attrs);
1421  return false;
1422  }
1423  }
1424  else
1426 
1427  /*
1428  * Resolve special "auto" client_encoding from the locale
1429  */
1430  if (conn->client_encoding_initial &&
1431  strcmp(conn->client_encoding_initial, "auto") == 0)
1432  {
1435  if (!conn->client_encoding_initial)
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:
1449  conn->status = CONNECTION_BAD;
1451  libpq_gettext("out of memory\n"));
1452  return false;
1453 }
#define calloc(a, b)
Definition: header.h:55
char * gssencmode
Definition: libpq-int.h:389
char * pgpassfile
Definition: libpq-int.h:370
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
static bool is_unixsock_path(const char *path)
Definition: pqcomm.h:93
char * host
Definition: libpq-int.h:335
char * dbName
Definition: libpq-int.h:366
static bool sslVerifyProtocolVersion(const char *version)
Definition: fe-connect.c:7163
char * ssl_min_protocol_version
Definition: libpq-int.h:393
#define DefaultSSLMode
Definition: fe-connect.c:132
pg_conn_host_type type
Definition: libpq-int.h:334
char * client_encoding_initial
Definition: libpq-int.h:362
#define malloc(a)
Definition: header.h:50
#define PGPASSFILE
Definition: fe-connect.c:80
#define MAXPGPATH
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
char * hostaddr
Definition: libpq-int.h:336
pg_conn_host * connhost
Definition: libpq-int.h:427
char * channel_binding
Definition: libpq-int.h:371
static int count_comma_separated_elems(const char *input)
Definition: fe-connect.c:966
char * target_session_attrs
Definition: libpq-int.h:395
char * pguser
Definition: libpq-int.h:368
char * sslmode
Definition: libpq-int.h:379
char * pg_fe_getauthname(PQExpBuffer errorMessage)
Definition: fe-auth.c:1101
PQExpBufferData errorMessage
Definition: libpq-int.h:571
static char * passwordFromFile(const char *hostname, const char *port, const char *dbname, const char *username, const char *pgpassfile)
Definition: fe-connect.c:6999
int pg_get_encoding_from_locale(const char *ctype, bool write_message)
Definition: chklocale.c:452
#define free(a)
Definition: header.h:65
const char * pg_encoding_to_char(int encoding)
Definition: encnames.c:588
bool options_valid
Definition: libpq-int.h:414
#define Assert(condition)
Definition: c.h:804
char * pgpass
Definition: libpq-int.h:369
ConnStatusType status
Definition: libpq-int.h:410
static char * parse_comma_separated_list(char **startptr, bool *more)
Definition: fe-connect.c:990
#define DefaultHost
Definition: fe-connect.c:121
char * pghostaddr
Definition: libpq-int.h:354
static bool sslVerifyProtocolRange(const char *min, const char *max)
Definition: fe-connect.c:7189
char * ssl_max_protocol_version
Definition: libpq-int.h:394
bool pqGetHomeDirectory(char *buf, int bufsize)
Definition: fe-connect.c:7242
int i
#define DefaultGSSMode
Definition: fe-connect.c:138
char * port
Definition: libpq-int.h:337
char * pgport
Definition: libpq-int.h:358
#define DefaultChannelBinding
Definition: fe-connect.c:126
PGTargetServerType target_server_type
Definition: libpq-int.h:458
int nconnhost
Definition: libpq-int.h:425
#define snprintf
Definition: port.h:216
int whichhost
Definition: libpq-int.h:426
#define libpq_gettext(x)
Definition: libpq-int.h:841
char * pghost
Definition: libpq-int.h:350
#define DEFAULT_PGSOCKET_DIR
char * password
Definition: libpq-int.h:338

◆ conninfo_add_defaults()

static bool conninfo_add_defaults ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

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

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

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

5796 {
5798  char *tmp;
5799 
5800  /*
5801  * If there's a service spec, use it to obtain any not-explicitly-given
5802  * parameters. Ignore error if no error message buffer is passed because
5803  * there is no way to pass back the failure message.
5804  */
5805  if (parseServiceInfo(options, errorMessage) != 0 && errorMessage)
5806  return false;
5807 
5808  /*
5809  * Get the fallback resources for parameters not specified in the conninfo
5810  * string nor the service.
5811  */
5812  for (option = options; option->keyword != NULL; option++)
5813  {
5814  if (option->val != NULL)
5815  continue; /* Value was in conninfo or service */
5816 
5817  /*
5818  * Try to get the environment variable fallback
5819  */
5820  if (option->envvar != NULL)
5821  {
5822  if ((tmp = getenv(option->envvar)) != NULL)
5823  {
5824  option->val = strdup(tmp);
5825  if (!option->val)
5826  {
5827  if (errorMessage)
5828  appendPQExpBufferStr(errorMessage,
5829  libpq_gettext("out of memory\n"));
5830  return false;
5831  }
5832  continue;
5833  }
5834  }
5835 
5836  /*
5837  * Interpret the deprecated PGREQUIRESSL environment variable. Per
5838  * tradition, translate values starting with "1" to sslmode=require,
5839  * and ignore other values. Given both PGREQUIRESSL=1 and PGSSLMODE,
5840  * PGSSLMODE takes precedence; the opposite was true before v9.3.
5841  */
5842  if (strcmp(option->keyword, "sslmode") == 0)
5843  {
5844  const char *requiresslenv = getenv("PGREQUIRESSL");
5845 
5846  if (requiresslenv != NULL && requiresslenv[0] == '1')
5847  {
5848  option->val = strdup("require");
5849  if (!option->val)
5850  {
5851  if (errorMessage)
5852  appendPQExpBufferStr(errorMessage,
5853  libpq_gettext("out of memory\n"));
5854  return false;
5855  }
5856  continue;
5857  }
5858  }
5859 
5860  /*
5861  * No environment variable specified or the variable isn't set - try
5862  * compiled-in default
5863  */
5864  if (option->compiled != NULL)
5865  {
5866  option->val = strdup(option->compiled);
5867  if (!option->val)
5868  {
5869  if (errorMessage)
5870  appendPQExpBufferStr(errorMessage,
5871  libpq_gettext("out of memory\n"));
5872  return false;
5873  }
5874  continue;
5875  }
5876 
5877  /*
5878  * Special handling for "user" option. Note that if pg_fe_getauthname
5879  * fails, we just leave the value as NULL; there's no need for this to
5880  * be an error condition if the caller provides a user name. The only
5881  * reason we do this now at all is so that callers of PQconndefaults
5882  * will see a correct default (barring error, of course).
5883  */
5884  if (strcmp(option->keyword, "user") == 0)
5885  {
5886  option->val = pg_fe_getauthname(NULL);
5887  continue;
5888  }
5889  }
5890 
5891  return true;
5892 }
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
char * pg_fe_getauthname(PQExpBuffer errorMessage)
Definition: fe-auth.c:1101
static int parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5088
#define libpq_gettext(x)
Definition: libpq-int.h:841

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

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

Referenced by PQconnectStartParams().

5634 {
5636  PQconninfoOption *dbname_options = NULL;
5638  int i = 0;
5639 
5640  /*
5641  * If expand_dbname is non-zero, check keyword "dbname" to see if val is
5642  * actually a recognized connection string.
5643  */
5644  while (expand_dbname && keywords[i])
5645  {
5646  const char *pname = keywords[i];
5647  const char *pvalue = values[i];
5648 
5649  /* first find "dbname" if any */
5650  if (strcmp(pname, "dbname") == 0 && pvalue)
5651  {
5652  /*
5653  * If value is a connection string, parse it, but do not use
5654  * defaults here -- those get picked up later. We only want to
5655  * override for those parameters actually passed.
5656  */
5657  if (recognized_connection_string(pvalue))
5658  {
5659  dbname_options = parse_connection_string(pvalue, errorMessage, false);
5660  if (dbname_options == NULL)
5661  return NULL;
5662  }
5663  break;
5664  }
5665  ++i;
5666  }
5667 
5668  /* Make a working copy of PQconninfoOptions */
5669  options = conninfo_init(errorMessage);
5670  if (options == NULL)
5671  {
5672  PQconninfoFree(dbname_options);
5673  return NULL;
5674  }
5675 
5676  /* Parse the keywords/values arrays */
5677  i = 0;
5678  while (keywords[i])
5679  {
5680  const char *pname = keywords[i];
5681  const char *pvalue = values[i];
5682 
5683  if (pvalue != NULL && pvalue[0] != '\0')
5684  {
5685  /* Search for the param record */
5686  for (option = options; option->keyword != NULL; option++)
5687  {
5688  if (strcmp(option->keyword, pname) == 0)
5689  break;
5690  }
5691 
5692  /* Check for invalid connection option */
5693  if (option->keyword == NULL)
5694  {
5695  appendPQExpBuffer(errorMessage,
5696  libpq_gettext("invalid connection option \"%s\"\n"),
5697  pname);
5698  PQconninfoFree(options);
5699  PQconninfoFree(dbname_options);
5700  return NULL;
5701  }
5702 
5703  /*
5704  * If we are on the first dbname parameter, and we have a parsed
5705  * connection string, copy those parameters across, overriding any
5706  * existing previous settings.
5707  */
5708  if (strcmp(pname, "dbname") == 0 && dbname_options)
5709  {
5710  PQconninfoOption *str_option;
5711 
5712  for (str_option = dbname_options; str_option->keyword != NULL; str_option++)
5713  {
5714  if (str_option->val != NULL)
5715  {
5716  int k;
5717 
5718  for (k = 0; options[k].keyword; k++)
5719  {
5720  if (strcmp(options[k].keyword, str_option->keyword) == 0)
5721  {
5722  if (options[k].val)
5723  free(options[k].val);
5724  options[k].val = strdup(str_option->val);
5725  if (!options[k].val)
5726  {
5727  appendPQExpBufferStr(errorMessage,
5728  libpq_gettext("out of memory\n"));
5729  PQconninfoFree(options);
5730  PQconninfoFree(dbname_options);
5731  return NULL;
5732  }
5733  break;
5734  }
5735  }
5736  }
5737  }
5738 
5739  /*
5740  * Forget the parsed connection string, so that any subsequent
5741  * dbname parameters will not be expanded.
5742  */
5743  PQconninfoFree(dbname_options);
5744  dbname_options = NULL;
5745  }
5746  else
5747  {
5748  /*
5749  * Store the value, overriding previous settings
5750  */
5751  if (option->val)
5752  free(option->val);
5753  option->val = strdup(pvalue);
5754  if (!option->val)
5755  {
5756  appendPQExpBufferStr(errorMessage,
5757  libpq_gettext("out of memory\n"));
5758  PQconninfoFree(options);
5759  PQconninfoFree(dbname_options);
5760  return NULL;
5761  }
5762  }
5763  }
5764  ++i;
5765  }
5766  PQconninfoFree(dbname_options);
5767 
5768  /*
5769  * Add in defaults if the caller wants that.
5770  */
5771  if (use_defaults)
5772  {
5773  if (!conninfo_add_defaults(options, errorMessage))
5774  {
5775  PQconninfoFree(options);
5776  return NULL;
5777  }
5778  }
5779 
5780  return options;
5781 }
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5359
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
static PQconninfoOption * parse_connection_string(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5399
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6572
static char ** options
static bool recognized_connection_string(const char *connstr)
Definition: fe-connect.c:5442
#define free(a)
Definition: header.h:65
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5795
static Datum values[MAXATTR]
Definition: bootstrap.c:156
int i
long val
Definition: informix.c:664
#define libpq_gettext(x)
Definition: libpq-int.h:841

◆ conninfo_find()

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

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

References _PQconninfoOption::keyword.

Referenced by conninfo_getval(), and conninfo_storeval().

6511 {
6513 
6514  for (option = connOptions; option->keyword != NULL; option++)
6515  {
6516  if (strcmp(option->keyword, keyword) == 0)
6517  return option;
6518  }
6519 
6520  return NULL;
6521 }

◆ conninfo_getval()

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

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

References conninfo_find(), and _PQconninfoOption::val.

Referenced by fillPGconn(), and parseServiceInfo().

6421 {
6423 
6424  option = conninfo_find(connOptions, keyword);
6425 
6426  return option ? option->val : NULL;
6427 }
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6510

◆ conninfo_init()

static PQconninfoOption * conninfo_init ( PQExpBuffer  errorMessage)
static

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

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

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

5360 {
5362  PQconninfoOption *opt_dest;
5363  const internalPQconninfoOption *cur_opt;
5364 
5365  /*
5366  * Get enough memory for all options in PQconninfoOptions, even if some
5367  * end up being filtered out.
5368  */
5369  options = (PQconninfoOption *) malloc(sizeof(PQconninfoOption) * sizeof(PQconninfoOptions) / sizeof(PQconninfoOptions[0]));
5370  if (options == NULL)
5371  {
5372  appendPQExpBufferStr(errorMessage,
5373  libpq_gettext("out of memory\n"));
5374  return NULL;
5375  }
5376  opt_dest = options;
5377 
5378  for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++)
5379  {
5380  /* Only copy the public part of the struct, not the full internal */
5381  memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption));
5382  opt_dest++;
5383  }
5384  MemSet(opt_dest, 0, sizeof(PQconninfoOption));
5385 
5386  return options;
5387 }
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
#define MemSet(start, val, len)
Definition: c.h:1008
#define malloc(a)
Definition: header.h:50
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:191
static char ** options
#define libpq_gettext(x)
Definition: libpq-int.h:841

◆ conninfo_parse()

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

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

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

Referenced by parse_connection_string().

5455 {
5456  char *pname;
5457  char *pval;
5458  char *buf;
5459  char *cp;
5460  char *cp2;
5462 
5463  /* Make a working copy of PQconninfoOptions */
5464  options = conninfo_init(errorMessage);
5465  if (options == NULL)
5466  return NULL;
5467 
5468  /* Need a modifiable copy of the input string */
5469  if ((buf = strdup(conninfo)) == NULL)
5470  {
5471  appendPQExpBufferStr(errorMessage,
5472  libpq_gettext("out of memory\n"));
5473  PQconninfoFree(options);
5474  return NULL;
5475  }
5476  cp = buf;
5477 
5478  while (*cp)
5479  {
5480  /* Skip blanks before the parameter name */
5481  if (isspace((unsigned char) *cp))
5482  {
5483  cp++;
5484  continue;
5485  }
5486 
5487  /* Get the parameter name */
5488  pname = cp;
5489  while (*cp)
5490  {
5491  if (*cp == '=')
5492  break;
5493  if (isspace((unsigned char) *cp))
5494  {
5495  *cp++ = '\0';
5496  while (*cp)
5497  {
5498  if (!isspace((unsigned char) *cp))
5499  break;
5500  cp++;
5501  }
5502  break;
5503  }
5504  cp++;
5505  }
5506 
5507  /* Check that there is a following '=' */
5508  if (*cp != '=')
5509  {
5510  appendPQExpBuffer(errorMessage,
5511  libpq_gettext("missing \"=\" after \"%s\" in connection info string\n"),
5512  pname);
5513  PQconninfoFree(options);
5514  free(buf);
5515  return NULL;
5516  }
5517  *cp++ = '\0';
5518 
5519  /* Skip blanks after the '=' */
5520  while (*cp)
5521  {
5522  if (!isspace((unsigned char) *cp))
5523  break;
5524  cp++;
5525  }
5526 
5527  /* Get the parameter value */
5528  pval = cp;
5529 
5530  if (*cp != '\'')
5531  {
5532  cp2 = pval;
5533  while (*cp)
5534  {
5535  if (isspace((unsigned char) *cp))
5536  {
5537  *cp++ = '\0';
5538  break;
5539  }
5540  if (*cp == '\\')
5541  {
5542  cp++;
5543  if (*cp != '\0')
5544  *cp2++ = *cp++;
5545  }
5546  else
5547  *cp2++ = *cp++;
5548  }
5549  *cp2 = '\0';
5550  }
5551  else
5552  {
5553  cp2 = pval;
5554  cp++;
5555  for (;;)
5556  {
5557  if (*cp == '\0')
5558  {
5559  appendPQExpBufferStr(errorMessage,
5560  libpq_gettext("unterminated quoted string in connection info string\n"));
5561  PQconninfoFree(options);
5562  free(buf);
5563  return NULL;
5564  }
5565  if (*cp == '\\')
5566  {
5567  cp++;
5568  if (*cp != '\0')
5569  *cp2++ = *cp++;
5570  continue;
5571  }
5572  if (*cp == '\'')
5573  {
5574  *cp2 = '\0';
5575  cp++;
5576  break;
5577  }
5578  *cp2++ = *cp++;
5579  }
5580  }
5581 
5582  /*
5583  * Now that we have the name and the value, store the record.
5584  */
5585  if (!conninfo_storeval(options, pname, pval, errorMessage, false, false))
5586  {
5587  PQconninfoFree(options);
5588  free(buf);
5589  return NULL;
5590  }
5591  }
5592 
5593  /* Done with the modifiable input string */
5594  free(buf);
5595 
5596  /*
5597  * Add in defaults if the caller wants that.
5598  */
5599  if (use_defaults)
5600  {
5601  if (!conninfo_add_defaults(options, errorMessage))
5602  {
5603  PQconninfoFree(options);
5604  return NULL;
5605  }
5606  }
5607 
5608  return options;
5609 }
static PQconninfoOption * conninfo_storeval(PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode)
Definition: fe-connect.c:6445
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5359
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
static char * buf
Definition: pg_test_fsync.c:68
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6572
static char ** options
#define free(a)
Definition: header.h:65
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5795
#define libpq_gettext(x)
Definition: libpq-int.h:841

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

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

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

6449 {
6451  char *value_copy;
6452 
6453  /*
6454  * For backwards compatibility, requiressl=1 gets translated to
6455  * sslmode=require, and requiressl=0 gets translated to sslmode=prefer
6456  * (which is the default for sslmode).
6457  */
6458  if (strcmp(keyword, "requiressl") == 0)
6459  {
6460  keyword = "sslmode";
6461  if (value[0] == '1')
6462  value = "require";
6463  else
6464  value = "prefer";
6465  }
6466 
6467  option = conninfo_find(connOptions, keyword);
6468  if (option == NULL)
6469  {
6470  if (!ignoreMissing)
6471  appendPQExpBuffer(errorMessage,
6472  libpq_gettext("invalid connection option \"%s\"\n"),
6473  keyword);
6474  return NULL;
6475  }
6476 
6477  if (uri_decode)
6478  {
6479  value_copy = conninfo_uri_decode(value, errorMessage);
6480  if (value_copy == NULL)
6481  /* conninfo_uri_decode already set an error message */
6482  return NULL;
6483  }
6484  else
6485  {
6486  value_copy = strdup(value);
6487  if (value_copy == NULL)
6488  {
6489  appendPQExpBufferStr(errorMessage, libpq_gettext("out of memory\n"));
6490  return NULL;
6491  }
6492  }
6493 
6494  if (option->val)
6495  free(option->val);
6496  option->val = value_copy;
6497 
6498  return option;
6499 }
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6510
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
static char * conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
Definition: fe-connect.c:6330
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
static struct @143 value
#define free(a)
Definition: header.h:65
#define libpq_gettext(x)
Definition: libpq-int.h:841

◆ conninfo_uri_decode()

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

Definition at line 6330 of file fe-connect.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().

6331 {
6332  char *buf;
6333  char *p;
6334  const char *q = str;
6335 
6336  buf = malloc(strlen(str) + 1);
6337  if (buf == NULL)
6338  {
6339  appendPQExpBufferStr(errorMessage, libpq_gettext("out of memory\n"));
6340  return NULL;
6341  }
6342  p = buf;
6343 
6344  for (;;)
6345  {
6346  if (*q != '%')
6347  {
6348  /* copy and check for NUL terminator */
6349  if (!(*(p++) = *(q++)))
6350  break;
6351  }
6352  else
6353  {
6354  int hi;
6355  int lo;
6356  int c;
6357 
6358  ++q; /* skip the percent sign itself */
6359 
6360  /*
6361  * Possible EOL will be caught by the first call to
6362  * get_hexdigit(), so we never dereference an invalid q pointer.
6363  */
6364  if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo)))
6365  {
6366  appendPQExpBuffer(errorMessage,
6367  libpq_gettext("invalid percent-encoded token: \"%s\"\n"),
6368  str);
6369  free(buf);
6370  return NULL;
6371  }
6372 
6373  c = (hi << 4) | lo;
6374  if (c == 0)
6375  {
6376  appendPQExpBuffer(errorMessage,
6377  libpq_gettext("forbidden value %%00 in percent-encoded value: \"%s\"\n"),
6378  str);
6379  free(buf);
6380  return NULL;
6381  }
6382  *(p++) = c;
6383  }
6384  }
6385 
6386  return buf;
6387 }
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
#define malloc(a)
Definition: header.h:50
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
char * c
static char * buf
Definition: pg_test_fsync.c:68
#define free(a)
Definition: header.h:65
static bool get_hexdigit(char digit, int *value)
Definition: fe-connect.c:6398
#define libpq_gettext(x)
Definition: libpq-int.h:841

◆ conninfo_uri_parse()

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

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

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

Referenced by parse_connection_string().

5902 {
5904 
5905  /* Make a working copy of PQconninfoOptions */
5906  options = conninfo_init(errorMessage);
5907  if (options == NULL)
5908  return NULL;
5909 
5910  if (!conninfo_uri_parse_options(options, uri, errorMessage))
5911  {
5912  PQconninfoFree(options);
5913  return NULL;
5914  }
5915 
5916  /*
5917  * Add in defaults if the caller wants that.
5918  */
5919  if (use_defaults)
5920  {
5921  if (!conninfo_add_defaults(options, errorMessage))
5922  {
5923  PQconninfoFree(options);
5924  return NULL;
5925  }
5926  }
5927 
5928  return options;
5929 }
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5359
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6572
static bool conninfo_uri_parse_options(PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage)
Definition: fe-connect.c:5953
static char ** options
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5795

◆ conninfo_uri_parse_options()

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

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

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

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

◆ conninfo_uri_parse_params()

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

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

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

Referenced by conninfo_uri_parse_options().

6200 {
6201  while (*params)
6202  {
6203  char *keyword = params;
6204  char *value = NULL;
6205  char *p = params;
6206  bool malloced = false;
6207  int oldmsglen;
6208 
6209  /*
6210  * Scan the params string for '=' and '&', marking the end of keyword
6211  * and value respectively.
6212  */
6213  for (;;)
6214  {
6215  if (*p == '=')
6216  {
6217  /* Was there '=' already? */
6218  if (value != NULL)
6219  {
6220  appendPQExpBuffer(errorMessage,
6221  libpq_gettext("extra key/value separator \"=\" in URI query parameter: \"%s\"\n"),
6222  keyword);
6223  return false;
6224  }
6225  /* Cut off keyword, advance to value */
6226  *p++ = '\0';
6227  value = p;
6228  }
6229  else if (*p == '&' || *p == '\0')
6230  {
6231  /*
6232  * If not at the end, cut off value and advance; leave p
6233  * pointing to start of the next parameter, if any.
6234  */
6235  if (*p != '\0')
6236  *p++ = '\0';
6237  /* Was there '=' at all? */
6238  if (value == NULL)
6239  {
6240  appendPQExpBuffer(errorMessage,
6241  libpq_gettext("missing key/value separator \"=\" in URI query parameter: \"%s\"\n"),
6242  keyword);
6243  return false;
6244  }
6245  /* Got keyword and value, go process them. */
6246  break;
6247  }
6248  else
6249  ++p; /* Advance over all other bytes. */
6250  }
6251 
6252  keyword = conninfo_uri_decode(keyword, errorMessage);
6253  if (keyword == NULL)
6254  {
6255  /* conninfo_uri_decode already set an error message */
6256  return false;
6257  }
6258  value = conninfo_uri_decode(value, errorMessage);
6259  if (value == NULL)
6260  {
6261  /* conninfo_uri_decode already set an error message */
6262  free(keyword);
6263  return false;
6264  }
6265  malloced = true;
6266 
6267  /*
6268  * Special keyword handling for improved JDBC compatibility.
6269  */
6270  if (strcmp(keyword, "ssl") == 0 &&
6271  strcmp(value, "true") == 0)
6272  {
6273  free(keyword);
6274  free(value);
6275  malloced = false;
6276 
6277  keyword = "sslmode";
6278  value = "require";
6279  }
6280 
6281  /*
6282  * Store the value if the corresponding option exists; ignore
6283  * otherwise. At this point both keyword and value are not
6284  * URI-encoded.
6285  */
6286  oldmsglen = errorMessage->len;
6287  if (!conninfo_storeval(connOptions, keyword, value,
6288  errorMessage, true, false))
6289  {
6290  /* Insert generic message if conninfo_storeval didn't give one. */
6291  if (errorMessage->len == oldmsglen)
6292  appendPQExpBuffer(errorMessage,
6293  libpq_gettext("invalid URI query parameter: \"%s\"\n"),
6294  keyword);
6295  /* And fail. */
6296  if (malloced)
6297  {
6298  free(keyword);
6299  free(value);
6300  }
6301  return false;
6302  }
6303 
6304  if (malloced)
6305  {
6306  free(keyword);
6307  free(value);
6308  }
6309 
6310  /* Proceed to next key=value pair, if any */
6311  params = p;
6312  }
6313 
6314  return true;
6315 }
static PQconninfoOption * conninfo_storeval(PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode)
Definition: fe-connect.c:6445
static char * conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
Definition: fe-connect.c:6330
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
static struct @143 value
#define free(a)
Definition: header.h:65
#define libpq_gettext(x)
Definition: libpq-int.h:841

◆ count_comma_separated_elems()

static int count_comma_separated_elems ( const char *  input)
static

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

Referenced by connectOptions2().

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 }

◆ default_threadlock()

static void default_threadlock ( int  acquire)
static

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

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

Referenced by PQregisterThreadLock().

7277 {
7278 #ifdef ENABLE_THREAD_SAFETY
7279 #ifndef WIN32
7280  static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
7281 #else
7282  static pthread_mutex_t singlethread_lock = NULL;
7283  static long mutex_initlock = 0;
7284 
7285  if (singlethread_lock == NULL)
7286  {
7287  while (InterlockedExchange(&mutex_initlock, 1) == 1)
7288  /* loop, another thread own the lock */ ;
7289  if (singlethread_lock == NULL)
7290  {
7291  if (pthread_mutex_init(&singlethread_lock, NULL))
7292  Assert(false);
7293  }
7294  InterlockedExchange(&mutex_initlock, 0);
7295  }
7296 #endif
7297  if (acquire)
7298  {
7299  if (pthread_mutex_lock(&singlethread_lock))
7300  Assert(false);
7301  }
7302  else
7303  {
7304  if (pthread_mutex_unlock(&singlethread_lock))
7305  Assert(false);
7306  }
7307 #endif
7308 }
CRITICAL_SECTION * pthread_mutex_t
Definition: pthread-win32.h:8
int pthread_mutex_init(pthread_mutex_t *mp, void *attr)
Definition: pthread-win32.c:35
int pthread_mutex_lock(pthread_mutex_t *mp)
Definition: pthread-win32.c:45
int pthread_mutex_unlock(pthread_mutex_t *mp)
Definition: pthread-win32.c:54
#define Assert(condition)
Definition: c.h:804

◆ defaultNoticeProcessor()

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

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

References fprintf.

Referenced by makeEmptyPGconn().

6951 {
6952  (void) arg; /* not used */
6953  /* Note: we expect the supplied string to end with a newline already. */
6954  fprintf(stderr, "%s", message);
6955 }
#define fprintf
Definition: port.h:220
void * arg

◆ defaultNoticeReceiver()

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

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

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

Referenced by makeEmptyPGconn().

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

◆ emitHostIdentityInfo()

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

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

References SockAddr::addr, appendPQExpBuffer(), CHT_HOST_ADDRESS, 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().

1695 {
1696 #ifdef HAVE_UNIX_SOCKETS
1697  if (IS_AF_UNIX(conn->raddr.addr.ss_family))
1698  {
1699  char service[NI_MAXHOST];
1700 
1701  pg_getnameinfo_all(&conn->raddr.addr, conn->raddr.salen,
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? */
1716  if (conn->connhost[conn->whichhost].type == CHT_HOST_ADDRESS)
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  */
1729  if (conn->connhost[conn->whichhost].type != CHT_HOST_ADDRESS &&
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 }
char * host
Definition: libpq-int.h:335
struct sockaddr_storage addr
Definition: pqcomm.h:64
pg_conn_host_type type
Definition: libpq-int.h:334
#define NI_MAXHOST
Definition: getaddrinfo.h:88
#define IS_AF_UNIX(fam)
Definition: ip.h:24
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
char * hostaddr
Definition: libpq-int.h:336
pg_conn_host * connhost
Definition: libpq-int.h:427
ACCEPT_TYPE_ARG3 salen
Definition: pqcomm.h:65
SockAddr raddr
Definition: libpq-int.h:447
PQExpBufferData errorMessage
Definition: libpq-int.h:571
#define NI_NUMERICSERV
Definition: getaddrinfo.h:81
int pg_getnameinfo_all(const struct sockaddr_storage *addr, int salen, char *node, int nodelen, char *service, int servicelen, int flags)
Definition: ip.c:122
char * port
Definition: libpq-int.h:337
int whichhost
Definition: libpq-int.h:426
#define libpq_gettext(x)
Definition: libpq-int.h:841

◆ fillPGconn()

static bool fillPGconn ( PGconn conn,
PQconninfoOption connOptions 
)
static

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

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

Referenced by connectOptions1(), and PQconnectStartParams().

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 }
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:191
PQExpBufferData errorMessage
Definition: libpq-int.h:571
#define free(a)
Definition: header.h:65
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6419
#define libpq_gettext(x)
Definition: libpq-int.h:841

◆ freePGconn()

static void freePGconn ( PGconn conn)
static

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

References pg_conn::appname, pg_conn::channel_binding, pg_conn::client_encoding_initial, PGEventConnDestroy::conn, conn, pg_conn::connect_timeout, pg_conn::connhost, pg_conn::connip, pg_conn::dbName, pg_conn::errorMessage, pg_conn::events, explicit_bzero(), pg_conn::fbappname, free, pg_conn::gssencmode, pg_conn::gsslib, pg_conn_host::host, pg_conn_host::hostaddr, i, pg_conn::inBuffer, pg_conn::keepalives, pg_conn::keepalives_count, pg_conn::keepalives_idle, pg_conn::keepalives_interval, pg_conn::krbsrvname, 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().

4016 {
4017  int i;
4018 
4019  /* let any event procs clean up their state data */
4020  for (i = 0; i < conn->nEvents; i++)
4021  {
4022  PGEventConnDestroy evt;
4023 
4024  evt.conn = conn;
4025  (void) conn->events[i].proc(PGEVT_CONNDESTROY, &evt,
4026  conn->events[i].passThrough);
4027  free(conn->events[i].name);
4028  }
4029 
4030  /* clean up pg_conn_host structures */
4031  if (conn->connhost != NULL)
4032  {
4033  for (i = 0; i < conn->nconnhost; ++i)
4034  {
4035  if (conn->connhost[i].host != NULL)
4036  free(conn->connhost[i].host);
4037  if (conn->connhost[i].hostaddr != NULL)
4038  free(conn->connhost[i].hostaddr);
4039  if (conn->connhost[i].port != NULL)
4040  free(conn->connhost[i].port);
4041  if (conn->connhost[i].password != NULL)
4042  {
4043  explicit_bzero(conn->connhost[i].password, strlen(conn->connhost[i].password));
4044  free(conn->connhost[i].password);
4045  }
4046  }
4047  free(conn->connhost);
4048  }
4049 
4050  if (conn->client_encoding_initial)
4052  if (conn->events)
4053  free(conn->events);
4054  if (conn->pghost)
4055  free(conn->pghost);
4056  if (conn->pghostaddr)
4057  free(conn->pghostaddr);
4058  if (conn->pgport)
4059  free(conn->pgport);
4060  if (conn->connect_timeout)
4061  free(conn->connect_timeout);
4062  if (conn->pgtcp_user_timeout)
4063  free(conn->pgtcp_user_timeout);
4064  if (conn->pgoptions)
4065  free(conn->pgoptions);
4066  if (conn->appname)
4067  free(conn->appname);
4068  if (conn->fbappname)
4069  free(conn->fbappname);
4070  if (conn->dbName)
4071  free(conn->dbName);
4072  if (conn->replication)
4073  free(conn->replication);
4074  if (conn->pguser)
4075  free(conn->pguser);
4076  if (conn->pgpass)
4077  {
4078  explicit_bzero(conn->pgpass, strlen(conn->pgpass));
4079  free(conn->pgpass);
4080  }
4081  if (conn->pgpassfile)
4082  free(conn->pgpassfile);
4083  if (conn->channel_binding)
4084  free(conn->channel_binding);
4085  if (conn->keepalives)
4086  free(conn->keepalives);
4087  if (conn->keepalives_idle)
4088  free(conn->keepalives_idle);
4089  if (conn->keepalives_interval)
4090  free(conn->keepalives_interval);
4091  if (conn->keepalives_count)
4092  free(conn->keepalives_count);
4093  if (conn->sslmode)
4094  free(conn->sslmode);
4095  if (conn->sslcert)
4096  free(conn->sslcert);
4097  if (conn->sslkey)
4098  free(conn->sslkey);
4099  if (conn->sslpassword)
4100  {
4101  explicit_bzero(conn->sslpassword, strlen(conn->sslpassword));
4102  free(conn->sslpassword);
4103  }
4104  if (conn->sslrootcert)
4105  free(conn->sslrootcert);
4106  if (conn->sslcrl)
4107  free(conn->sslcrl);
4108  if (conn->sslcrldir)
4109  free(conn->sslcrldir);
4110  if (conn->sslcompression)
4111  free(conn->sslcompression);
4112  if (conn->sslsni)
4113  free(conn->sslsni);
4114  if (conn->requirepeer)
4115  free(conn->requirepeer);
4116  if (conn->ssl_min_protocol_version)
4118  if (conn->ssl_max_protocol_version)
4120  if (conn->gssencmode)
4121  free(conn->gssencmode);
4122  if (conn->krbsrvname)
4123  free(conn->krbsrvname);
4124  if (conn->gsslib)
4125  free(conn->gsslib);
4126  if (conn->connip)
4127  free(conn->connip);
4128  /* Note that conn->Pfdebug is not ours to close or free */
4129  if (conn->write_err_msg)
4130  free(conn->write_err_msg);
4131  if (conn->inBuffer)
4132  free(conn->inBuffer);
4133  if (conn->outBuffer)
4134  free(conn->outBuffer);
4135  if (conn->rowBuf)
4136  free(conn->rowBuf);
4137  if (conn->target_session_attrs)
4138  free(conn->target_session_attrs);
4139  termPQExpBuffer(&conn->errorMessage);
4140  termPQExpBuffer(&conn->workBuffer);
4141 
4142  free(conn);
4143 }
char * gssencmode
Definition: libpq-int.h:389
PGEvent * events
Definition: libpq-int.h:405
char * replication
Definition: libpq-int.h:367
char * pgpassfile
Definition: libpq-int.h:370
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
PQExpBufferData workBuffer
Definition: libpq-int.h:574
char * requirepeer
Definition: libpq-int.h:388
char * host
Definition: libpq-int.h:335
char * dbName
Definition: libpq-int.h:366
char * sslsni
Definition: libpq-int.h:387
char * ssl_min_protocol_version
Definition: libpq-int.h:393
char * keepalives
Definition: libpq-int.h:373
char * write_err_msg
Definition: libpq-int.h:455
char * keepalives_idle
Definition: libpq-int.h:374
char * client_encoding_initial
Definition: libpq-int.h:362
char * sslkey
Definition: libpq-int.h:381
char * sslcompression
Definition: libpq-int.h:380
PGconn * conn
Definition: streamutil.c:54
char * hostaddr
Definition: libpq-int.h:336
char * connect_timeout
Definition: libpq-int.h:360
pg_conn_host * connhost
Definition: libpq-int.h:427
char * keepalives_interval
Definition: libpq-int.h:375
char * appname
Definition: libpq-int.h:364
char * sslpassword
Definition: libpq-int.h:383
char * krbsrvname
Definition: libpq-int.h:390
char * channel_binding
Definition: libpq-int.h:371
char * target_session_attrs
Definition: libpq-int.h:395
PGdataValue * rowBuf
Definition: libpq-int.h:496
char * pguser
Definition: libpq-int.h:368
char * gsslib
Definition: libpq-int.h:391
char * inBuffer
Definition: libpq-int.h:479
char * sslmode
Definition: libpq-int.h:379
PQExpBufferData errorMessage
Definition: libpq-int.h:571
char * sslcert
Definition: libpq-int.h:382
#define free(a)
Definition: header.h:65
char * pgoptions
Definition: libpq-int.h:363
char * connip
Definition: libpq-int.h:428
char * pgpass
Definition: libpq-int.h:369
char * sslrootcert
Definition: libpq-int.h:384
PGEventProc proc
Definition: libpq-int.h:161
char * outBuffer
Definition: libpq-int.h:486
char * pghostaddr
Definition: libpq-int.h:354
void explicit_bzero(void *buf, size_t len)
char * ssl_max_protocol_version
Definition: libpq-int.h:394
int nEvents
Definition: libpq-int.h:406
int i
char * sslcrldir
Definition: libpq-int.h:386
void * passThrough
Definition: libpq-int.h:163
char * fbappname
Definition: libpq-int.h:365
char * port
Definition: libpq-int.h:337
char * pgport
Definition: libpq-int.h:358
int nconnhost
Definition: libpq-int.h:425
char * name
Definition: libpq-int.h:162
char * pgtcp_user_timeout
Definition: libpq-int.h:361
char * sslcrl
Definition: libpq-int.h:385
char * keepalives_count
Definition: libpq-int.h:377
char * pghost
Definition: libpq-int.h:350
char * password
Definition: libpq-int.h:338

◆ get_hexdigit()

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

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

Referenced by conninfo_uri_decode().

6399 {
6400  if ('0' <= digit && digit <= '9')
6401  *value = digit - '0';
6402  else if ('A' <= digit && digit <= 'F')
6403  *value = digit - 'A' + 10;
6404  else if ('a' <= digit && digit <= 'f')
6405  *value = digit - 'a' + 10;
6406  else
6407  return false;
6408 
6409  return true;
6410 }
static struct @143 value

◆ getHostaddr()

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

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

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

Referenced by PQconnectPoll().

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 }
struct sockaddr_storage addr
Definition: pqcomm.h:64
char * pg_inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size)
Definition: inet_net_ntop.c:77
SockAddr raddr
Definition: libpq-int.h:447

◆ internal_cancel()

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

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

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

Referenced by PQcancel(), and PQrequestCancel().

4405 {
4406  int save_errno = SOCK_ERRNO;
4407  pgsocket tmpsock = PGINVALID_SOCKET;
4408  char sebuf[PG_STRERROR_R_BUFLEN];
4409  int maxlen;
4410  struct
4411  {
4412  uint32 packetlen;
4414  } crp;
4415 
4416  /*
4417  * We need to open a temporary connection to the postmaster. Do this with
4418  * only kernel calls.
4419  */
4420  if ((tmpsock = socket(raddr->addr.ss_family, SOCK_STREAM, 0)) == PGINVALID_SOCKET)
4421  {
4422  strlcpy(errbuf, "PQcancel() -- socket() failed: ", errbufsize);
4423  goto cancel_errReturn;
4424  }
4425 retry3:
4426  if (connect(tmpsock, (struct sockaddr *) &raddr->addr,
4427  raddr->salen) < 0)
4428  {
4429  if (SOCK_ERRNO == EINTR)
4430  /* Interrupted system call - we'll just try again */
4431  goto retry3;
4432  strlcpy(errbuf, "PQcancel() -- connect() failed: ", errbufsize);
4433  goto cancel_errReturn;
4434  }
4435 
4436  /*
4437  * We needn't set nonblocking I/O or NODELAY options here.
4438  */
4439 
4440  /* Create and send the cancel request packet. */
4441 
4442  crp.packetlen = pg_hton32((uint32) sizeof(crp));
4443  crp.cp.cancelRequestCode = (MsgType) pg_hton32(CANCEL_REQUEST_CODE);
4444  crp.cp.backendPID = pg_hton32(be_pid);
4445  crp.cp.cancelAuthCode = pg_hton32(be_key);
4446 
4447 retry4:
4448  if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp))
4449  {
4450  if (SOCK_ERRNO == EINTR)
4451  /* Interrupted system call - we'll just try again */
4452  goto retry4;
4453  strlcpy(errbuf, "PQcancel() -- send() failed: ", errbufsize);
4454  goto cancel_errReturn;
4455  }
4456 
4457  /*
4458  * Wait for the postmaster to close the connection, which indicates that
4459  * it's processed the request. Without this delay, we might issue another
4460  * command only to find that our cancel zaps that command instead of the
4461  * one we thought we were canceling. Note we don't actually expect this
4462  * read to obtain any data, we are just waiting for EOF to be signaled.
4463  */
4464 retry5:
4465  if (recv(tmpsock, (char *) &crp, 1, 0) < 0)
4466  {
4467  if (SOCK_ERRNO == EINTR)
4468  /* Interrupted system call - we'll just try again */
4469  goto retry5;
4470  /* we ignore other error conditions */
4471  }
4472 
4473  /* All done */
4474  closesocket(tmpsock);
4475  SOCK_ERRNO_SET(save_errno);
4476  return true;
4477 
4478 cancel_errReturn:
4479 
4480  /*
4481  * Make sure we don't overflow the error buffer. Leave space for the \n at
4482  * the end, and for the terminating zero.
4483  */
4484  maxlen = errbufsize - strlen(errbuf) - 2;
4485  if (maxlen >= 0)
4486  {
4487  strncat(errbuf, SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)),
4488  maxlen);
4489  strcat(errbuf, "\n");
4490  }
4491  if (tmpsock != PGINVALID_SOCKET)
4492  closesocket(tmpsock);
4493  SOCK_ERRNO_SET(save_errno);
4494  return false;
4495 }
#define closesocket
Definition: port.h:332
#define PG_STRERROR_R_BUFLEN
Definition: port.h:234
struct sockaddr_storage addr
Definition: pqcomm.h:64
#define connect(s, name, namelen)
Definition: win32_port.h:463
#define recv(s, buf, len, flags)
Definition: win32_port.h:465
#define SOCK_STRERROR
Definition: libpq-int.h:855
#define pg_hton32(x)
Definition: pg_bswap.h:121
#define SOCK_ERRNO
Definition: libpq-int.h:854
unsigned int uint32
Definition: c.h:441
int pgsocket
Definition: port.h:31
ACCEPT_TYPE_ARG3 salen
Definition: pqcomm.h:65
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:856
#define socket(af, type, protocol)
Definition: win32_port.h:459
#define PGINVALID_SOCKET
Definition: port.h:33
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define CANCEL_REQUEST_CODE
Definition: pqcomm.h:176
ProtocolVersion MsgType
Definition: pqcomm.h:127
#define EINTR
Definition: win32_port.h:343
#define send(s, buf, len, flags)
Definition: win32_port.h:466

◆ internal_ping()

static PGPing internal_ping ( PGconn conn)
static

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

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

Referenced by PQping(), and PQpingParams().

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

◆ makeEmptyPGconn()

static PGconn * makeEmptyPGconn ( void  )
static

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

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

3918 {
3919  PGconn *conn;
3920 
3921 #ifdef WIN32
3922 
3923  /*
3924  * Make sure socket support is up and running in this process.
3925  *
3926  * Note: the Windows documentation says that we should eventually do a
3927  * matching WSACleanup() call, but experience suggests that that is at
3928  * least as likely to cause problems as fix them. So we don't.
3929  */
3930  static bool wsastartup_done = false;
3931 
3932  if (!wsastartup_done)
3933  {
3934  WSADATA wsaData;
3935 
3936  if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
3937  return NULL;
3938  wsastartup_done = true;
3939  }
3940 
3941  /* Forget any earlier error */
3942  WSASetLastError(0);
3943 #endif /* WIN32 */
3944 
3945  conn = (PGconn *) malloc(sizeof(PGconn));
3946  if (conn == NULL)
3947  return conn;
3948 
3949  /* Zero all pointers and booleans */
3950  MemSet(conn, 0, sizeof(PGconn));
3951 
3952  /* install default notice hooks */
3955 
3956  conn->status = CONNECTION_BAD;
3957  conn->asyncStatus = PGASYNC_IDLE;
3959  conn->xactStatus = PQTRANS_IDLE;
3960  conn->options_valid = false;
3961  conn->nonblocking = false;
3962  conn->client_encoding = PG_SQL_ASCII;
3963  conn->std_strings = false; /* unless server says differently */
3966  conn->verbosity = PQERRORS_DEFAULT;
3968  conn->sock = PGINVALID_SOCKET;
3969  conn->Pfdebug = NULL;
3970 
3971  /*
3972  * We try to send at least 8K at a time, which is the usual size of pipe
3973  * buffers on Unix systems. That way, when we are sending a large amount
3974  * of data, we avoid incurring extra kernel context swaps for partial
3975  * bufferloads. The output buffer is initially made 16K in size, and we
3976  * try to dump it after accumulating 8K.
3977  *
3978  * With the same goal of minimizing context swaps, the input buffer will
3979  * be enlarged anytime it has less than 8K free, so we initially allocate
3980  * twice that.
3981  */
3982  conn->inBufSize = 16 * 1024;
3983  conn->inBuffer = (char *) malloc(conn->inBufSize);
3984  conn->outBufSize = 16 * 1024;
3985  conn->outBuffer = (char *) malloc(conn->outBufSize);
3986  conn->rowBufLen = 32;
3987  conn->rowBuf = (PGdataValue *) malloc(conn->rowBufLen * sizeof(PGdataValue));
3988  initPQExpBuffer(&conn->errorMessage);
3989  initPQExpBuffer(&conn->workBuffer);
3990 
3991  if (conn->inBuffer == NULL ||
3992  conn->outBuffer == NULL ||
3993  conn->rowBuf == NULL ||
3994  PQExpBufferBroken(&conn->errorMessage) ||
3995  PQExpBufferBroken(&conn->workBuffer))
3996  {
3997  /* out of memory already :-( */
3998  freePGconn(conn);
3999  conn = NULL;
4000  }
4001 
4002  return conn;
4003 }
PGContextVisibility show_context
Definition: libpq-int.h:475
int rowBufLen
Definition: libpq-int.h:497
PQExpBufferData workBuffer
Definition: libpq-int.h:574
PGpipelineStatus pipelineStatus
Definition: libpq-int.h:417
#define MemSet(start, val, len)
Definition: c.h:1008
FILE * Pfdebug
Definition: libpq-int.h:398
#define malloc(a)
Definition: header.h:50
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:411
PGTernaryBool default_transaction_read_only
Definition: libpq-int.h:472
PGconn * conn
Definition: streamutil.c:54
int inBufSize
Definition: libpq-int.h:480
PGNoticeHooks noticeHooks
Definition: libpq-int.h:402
PGVerbosity verbosity
Definition: libpq-int.h:474
PQnoticeReceiver noticeRec
Definition: libpq-int.h:153
PGdataValue * rowBuf
Definition: libpq-int.h:496
pgsocket sock
Definition: libpq-int.h:444
PGTernaryBool in_hot_standby
Definition: libpq-int.h:473
#define PGINVALID_SOCKET
Definition: port.h:33
char * inBuffer
Definition: libpq-int.h:479
PQnoticeProcessor noticeProc
Definition: libpq-int.h:155
static void freePGconn(PGconn *conn)
Definition: fe-connect.c:4015
PQExpBufferData errorMessage
Definition: libpq-int.h:571
bool std_strings
Definition: libpq-int.h:471
bool options_valid
Definition: libpq-int.h:414
int outBufSize
Definition: libpq-int.h:487
#define PQExpBufferBroken(str)
Definition: pqexpbuffer.h:59
ConnStatusType status
Definition: libpq-int.h:410
char * outBuffer
Definition: libpq-int.h:486
bool nonblocking
Definition: libpq-int.h:415
static void defaultNoticeProcessor(void *arg, const char *message)
Definition: fe-connect.c:6950
int client_encoding
Definition: libpq-int.h:470
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
static void defaultNoticeReceiver(void *arg, const PGresult *res)
Definition: fe-connect.c:6935
PGTransactionStatusType xactStatus
Definition: libpq-int.h:412

◆ parse_comma_separated_list()

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

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

References malloc, and startptr.

Referenced by connectOptions2().

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 }
#define malloc(a)
Definition: header.h:50
e
Definition: preproc-init.c:82
static XLogRecPtr startptr
Definition: basebackup.c:116

◆ parse_connection_string()

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

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

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

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

5401 {
5402  /* Parse as URI if connection string matches URI prefix */
5403  if (uri_prefix_length(connstr) != 0)
5404  return conninfo_uri_parse(connstr, errorMessage, use_defaults);
5405 
5406  /* Parse as default otherwise */
5407  return conninfo_parse(connstr, errorMessage, use_defaults);
5408 }
static PQconninfoOption * conninfo_parse(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5453
static int uri_prefix_length(const char *connstr)
Definition: fe-connect.c:5419
static PQconninfoOption * conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5900
static char * connstr
Definition: pg_dumpall.c:62

◆ parse_int_param()

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

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

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

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

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
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
PQExpBufferData errorMessage
Definition: libpq-int.h:571
static struct @143 value
#define Assert(condition)
Definition: c.h:804
#define libpq_gettext(x)
Definition: libpq-int.h:841

◆ parseServiceFile()

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

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

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

Referenced by parseServiceInfo().

5162 {
5163  int result = 0,
5164  linenr = 0,
5165  i;
5166  FILE *f;
5167  char *line;
5168  char buf[1024];
5169 
5170  *group_found = false;
5171 
5172  f = fopen(serviceFile, "r");
5173  if (f == NULL)
5174  {
5175  appendPQExpBuffer(errorMessage, libpq_gettext("service file \"%s\" not found\n"),
5176  serviceFile);
5177  return 1;
5178  }
5179 
5180  while ((line = fgets(buf, sizeof(buf), f)) != NULL)
5181  {
5182  int len;
5183 
5184  linenr++;
5185 
5186  if (strlen(line) >= sizeof(buf) - 1)
5187  {
5188  appendPQExpBuffer(errorMessage,
5189  libpq_gettext("line %d too long in service file \"%s\"\n"),
5190  linenr,
5191  serviceFile);
5192  result = 2;
5193  goto exit;
5194  }
5195 
5196  /* ignore whitespace at end of line, especially the newline */
5197  len = strlen(line);
5198  while (len > 0 && isspace((unsigned char) line[len - 1]))
5199  line[--len] = '\0';
5200 
5201  /* ignore leading whitespace too */
5202  while (*line && isspace((unsigned char) line[0]))
5203  line++;
5204 
5205  /* ignore comments and empty lines */
5206  if (line[0] == '\0' || line[0] == '#')
5207  continue;
5208 
5209  /* Check for right groupname */
5210  if (line[0] == '[')
5211  {
5212  if (*group_found)
5213  {
5214  /* end of desired group reached; return success */
5215  goto exit;
5216  }
5217 
5218  if (strncmp(line + 1, service, strlen(service)) == 0 &&
5219  line[strlen(service) + 1] == ']')
5220  *group_found = true;
5221  else
5222  *group_found = false;
5223  }
5224  else
5225  {
5226  if (*group_found)
5227  {
5228  /*
5229  * Finally, we are in the right group and can parse the line
5230  */
5231  char *key,
5232  *val;
5233  bool found_keyword;
5234 
5235 #ifdef USE_LDAP
5236  if (strncmp(line, "ldap", 4) == 0)
5237  {
5238  int rc = ldapServiceLookup(line, options, errorMessage);
5239 
5240  /* if rc = 2, go on reading for fallback */
5241  switch (rc)
5242  {
5243  case 0:
5244  goto exit;
5245  case 1:
5246  case 3:
5247  result = 3;
5248  goto exit;
5249  case 2:
5250  continue;
5251  }
5252  }
5253 #endif
5254 
5255  key = line;
5256  val = strchr(line, '=');
5257  if (val == NULL)
5258  {
5259  appendPQExpBuffer(errorMessage,
5260  libpq_gettext("syntax error in service file \"%s\", line %d\n"),
5261  serviceFile,
5262  linenr);
5263  result = 3;
5264  goto exit;
5265  }
5266  *val++ = '\0';
5267 
5268  if (strcmp(key, "service") == 0)
5269  {
5270  appendPQExpBuffer(errorMessage,
5271  libpq_gettext("nested service specifications not supported in service file \"%s\", line %d\n"),
5272  serviceFile,
5273  linenr);
5274  result = 3;
5275  goto exit;
5276  }
5277 
5278  /*
5279  * Set the parameter --- but don't override any previous
5280  * explicit setting.
5281  */
5282  found_keyword = false;
5283  for (i = 0; options[i].keyword; i++)
5284  {
5285  if (strcmp(options[i].keyword, key) == 0)
5286  {
5287  if (options[i].val == NULL)
5288  options[i].val = strdup(val);
5289  if (!options[i].val)
5290  {
5291  appendPQExpBufferStr(errorMessage,
5292  libpq_gettext("out of memory\n"));
5293  result = 3;
5294  goto exit;
5295  }
5296  found_keyword = true;
5297  break;
5298  }
5299  }
5300 
5301  if (!found_keyword)
5302  {
5303  appendPQExpBuffer(errorMessage,
5304  libpq_gettext("syntax error in service file \"%s\", line %d\n"),
5305  serviceFile,
5306  linenr);
5307  result = 3;
5308  goto exit;
5309  }
5310  }
5311  }
5312  }
5313 
5314 exit:
5315  fclose(f);
5316 
5317  return result;
5318 }
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
static char * buf
Definition: pg_test_fsync.c:68
int i
long val
Definition: informix.c:664
#define libpq_gettext(x)
Definition: libpq-int.h:841

◆ parseServiceInfo()

static int parseServiceInfo ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

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

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

Referenced by conninfo_add_defaults().

5089 {
5090  const char *service = conninfo_getval(options, "service");
5091  char serviceFile[MAXPGPATH];
5092  char *env;
5093  bool group_found = false;
5094  int status;
5095  struct stat stat_buf;
5096 
5097  /*
5098  * We have to special-case the environment variable PGSERVICE here, since
5099  * this is and should be called before inserting environment defaults for
5100  * other connection options.
5101  */
5102  if (service == NULL)
5103  service = getenv("PGSERVICE");
5104 
5105  /* If no service name given, nothing to do */
5106  if (service == NULL)
5107  return 0;
5108 
5109  /*
5110  * Try PGSERVICEFILE if specified, else try ~/.pg_service.conf (if that
5111  * exists).
5112  */
5113  if ((env = getenv("PGSERVICEFILE")) != NULL)
5114  strlcpy(serviceFile, env, sizeof(serviceFile));
5115  else
5116  {
5117  char homedir[MAXPGPATH];
5118 
5119  if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
5120  goto next_file;
5121  snprintf(serviceFile, MAXPGPATH, "%s/%s", homedir, ".pg_service.conf");
5122  if (stat(serviceFile, &stat_buf) != 0)
5123  goto next_file;
5124  }
5125 
5126  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
5127  if (group_found || status != 0)
5128  return status;
5129 
5130 next_file:
5131 
5132  /*
5133  * This could be used by any application so we can't use the binary
5134  * location to find our config files.
5135  */
5136  snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf",
5137  getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);
5138  if (stat(serviceFile, &stat_buf) != 0)
5139  goto last_file;
5140 
5141  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
5142  if (status != 0)
5143  return status;
5144 
5145 last_file:
5146  if (!group_found)
5147  {
5148  appendPQExpBuffer(errorMessage,
5149  libpq_gettext("definition of service \"%s\" not found\n"), service);
5150  return 3;
5151  }
5152 
5153  return 0;
5154 }
#define MAXPGPATH
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
static int parseServiceFile(const char *serviceFile, const char *service, PQconninfoOption *options, PQExpBuffer errorMessage, bool *group_found)
Definition: fe-connect.c:5157
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6419
bool pqGetHomeDirectory(char *buf, int bufsize)
Definition: fe-connect.c:7242
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:227
#define snprintf
Definition: port.h:216
#define libpq_gettext(x)
Definition: libpq-int.h:841
#define stat
Definition: win32_port.h:275

◆ passwordFromFile()

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

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

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

Referenced by connectOptions2().

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

◆ pgpassfileWarning()

static void pgpassfileWarning ( PGconn conn)
static

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

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

Referenced by PQconnectPoll().

7140 {
7141  /* If it was 'invalid authorization', add pgpassfile mention */
7142  /* only works with >= 9.0 servers */
7143  if (conn->password_needed &&
7144  conn->connhost[conn->whichhost].password != NULL &&
7145  conn->result)
7146  {
7147  const char *sqlstate = PQresultErrorField(conn->result,
7149 
7150  if (sqlstate && strcmp(sqlstate, ERRCODE_INVALID_PASSWORD) == 0)
7152  libpq_gettext("password retrieved from file \"%s\"\n"),
7153  conn->pgpassfile);
7154  }
7155 }
char * pgpassfile
Definition: libpq-int.h:370
bool password_needed
Definition: libpq-int.h:451
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
PGresult * result
Definition: libpq-int.h:500
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
pg_conn_host * connhost
Definition: libpq-int.h:427
PQExpBufferData errorMessage
Definition: libpq-int.h:571
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:3233
#define ERRCODE_INVALID_PASSWORD
Definition: fe-connect.c:94
int whichhost
Definition: libpq-int.h:426
#define libpq_gettext(x)
Definition: libpq-int.h:841
char * password
Definition: libpq-int.h:338

◆ PQbackendPID()

int PQbackendPID ( const PGconn conn)

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

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

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

6779 {
6780  if (!conn || conn->status != CONNECTION_OK)
6781  return 0;
6782  return conn->be_pid;
6783 }
ConnStatusType status
Definition: libpq-int.h:410
int be_pid
Definition: libpq-int.h:467

◆ PQcancel()

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

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

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

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

4508 {
4509  if (!cancel)
4510  {
4511  strlcpy(errbuf, "PQcancel() -- no cancel object supplied", errbufsize);
4512  return false;
4513  }
4514 
4515  return internal_cancel(&cancel->raddr, cancel->be_pid, cancel->be_key,
4516  errbuf, errbufsize);
4517 }
static int internal_cancel(SockAddr *raddr, int be_pid, int be_key, char *errbuf, int errbufsize)
Definition: fe-connect.c:4403
int be_pid
Definition: libpq-int.h:584
int be_key
Definition: libpq-int.h:585
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
SockAddr raddr
Definition: libpq-int.h:583

◆ PQclientEncoding()

int PQclientEncoding ( const PGconn conn)

◆ PQconndefaults()

PQconninfoOption* PQconndefaults ( void  )

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

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

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 }
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5359
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6572
#define PQExpBufferDataBroken(buf)
Definition: pqexpbuffer.h:67
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5795
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92

◆ PQconnectdb()

PGconn* PQconnectdb ( const char *  conninfo)

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

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

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

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

◆ PQconnectdbParams()

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

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

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

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

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 * conn
Definition: streamutil.c:54
static int connectDBComplete(PGconn *conn)
Definition: fe-connect.c:2110
ConnStatusType status
Definition: libpq-int.h:410
static Datum values[MAXATTR]
Definition: bootstrap.c:156
PGconn * PQconnectStartParams(const char *const *keywords, const char *const *values, int expand_dbname)
Definition: fe-connect.c:760

◆ PQconnectionNeedsPassword()

int PQconnectionNeedsPassword ( const PGconn conn)

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

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

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

6796 {
6797  char *password;
6798 
6799  if (!conn)
6800  return false;
6801  password = PQpass(conn);
6802  if (conn->password_needed &&
6803  (password == NULL || password[0] == '\0'))
6804  return true;
6805  else
6806  return false;
6807 }
bool password_needed
Definition: libpq-int.h:451
char * PQpass(const PGconn *conn)
Definition: fe-connect.c:6606
static char * password
Definition: streamutil.c:53

◆ PQconnectionUsedPassword()

int PQconnectionUsedPassword ( const PGconn conn)

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

References pg_conn::password_needed.

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

6811 {
6812  if (!conn)
6813  return false;
6814  if (conn->password_needed)
6815  return true;
6816  else
6817  return false;
6818 }
bool password_needed
Definition: libpq-int.h:451

◆ PQconnectPoll()

PostgresPollingStatusType PQconnectPoll ( PGconn conn)

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

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

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

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  {
2314  conn->addr_cur = conn->addr_cur->ai_next;
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 */
2355  release_conn_addrinfo(conn);
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 */
2484  pqDropServerData(conn);
2485 
2486  /* Drop any PGresult we might have, too */
2487  conn->asyncStatus = PGASYNC_IDLE;
2488  conn->xactStatus = PQTRANS_IDLE;
2490  pqClearAsyncResult(conn);
2491 
2492  /* Reset conn->status to put the state machine in the right state */
2493  conn->status = CONNECTION_NEEDED;
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)
2642  || !setKeepalivesInterval(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  */
2719  conn->status = CONNECTION_STARTED;
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  */
2731  conn->status = CONNECTION_STARTED;
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  ACCEPT_TYPE_ARG3 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  */
2799  conn->status = CONNECTION_MADE;
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 */
3067  conn->status = CONNECTION_MADE;
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  /* SSL handshake done, ready to send startup packet */
3101  conn->status = CONNECTION_MADE;
3102  return PGRES_POLLING_WRITING;
3103  }
3104  if (pollres == PGRES_POLLING_FAILED)
3105  {
3106  /*
3107  * Failed ... if sslmode is "prefer" then do a non-SSL
3108  * retry
3109  */
3110  if (conn->sslmode[0] == 'p' /* "prefer" */
3111  && conn->allow_ssl_try /* redundant? */
3112  && !conn->wait_ssl_try) /* redundant? */
3113  {
3114  /* only retry once */
3115  conn->allow_ssl_try = false;
3116  need_new_connection = true;
3117  goto keep_going;
3118  }
3119  /* Else it's a hard failure */
3120  goto error_return;
3121  }
3122  /* Else, return POLLING_READING or POLLING_WRITING status */
3123  return pollres;
3124 #else /* !USE_SSL */
3125  /* can't get here */
3126  goto error_return;
3127 #endif /* USE_SSL */
3128  }
3129 
3131  {
3132 #ifdef ENABLE_GSS
3133  PostgresPollingStatusType pollres;
3134 
3135  /*
3136  * If we haven't yet, get the postmaster's response to our
3137  * negotiation packet
3138  */
3139  if (conn->try_gss && !conn->gctx)
3140  {
3141  char gss_ok;
3142  int rdresult = pqReadData(conn);
3143 
3144  if (rdresult < 0)
3145  /* pqReadData fills in error message */
3146  goto error_return;
3147  else if (rdresult == 0)
3148  /* caller failed to wait for data */
3149  return PGRES_POLLING_READING;
3150  if (pqGetc(&gss_ok, conn) < 0)
3151  /* shouldn't happen... */
3152  return PGRES_POLLING_READING;
3153 
3154  if (gss_ok == 'E')
3155  {
3156  /*
3157  * Server failure of some sort. Assume it's a
3158  * protocol version support failure, and let's see if
3159  * we can't recover (if it's not, we'll get a better
3160  * error message on retry). Server gets fussy if we
3161  * don't hang up the socket, though.
3162  */
3163  conn->try_gss = false;
3164  need_new_connection = true;
3165  goto keep_going;
3166  }
3167 
3168  /* mark byte consumed */
3169  conn->inStart = conn->inCursor;
3170 
3171  if (gss_ok == 'N')
3172  {
3173  /* Server doesn't want GSSAPI; fall back if we can */
3174  if (conn->gssencmode[0] == 'r')
3175  {
3177  libpq_gettext("server doesn't support GSSAPI encryption, but it was required\n"));
3178  goto error_return;
3179  }
3180 
3181  conn->try_gss = false;
3182  /* We can proceed using this connection */
3183  conn->status = CONNECTION_MADE;
3184  return PGRES_POLLING_WRITING;
3185  }
3186  else if (gss_ok != 'G')
3187  {
3189  libpq_gettext("received invalid response to GSSAPI negotiation: %c\n"),
3190  gss_ok);
3191  goto error_return;
3192  }
3193  }
3194 
3195  /* Begin or continue GSSAPI negotiation */
3196  pollres = pqsecure_open_gss(conn);
3197  if (pollres == PGRES_POLLING_OK)
3198  {
3199  /* All set for startup packet */
3200  conn->status = CONNECTION_MADE;
3201  return PGRES_POLLING_WRITING;
3202  }
3203  else if (pollres == PGRES_POLLING_FAILED &&
3204  conn->gssencmode[0] == 'p')
3205  {
3206  /*
3207  * We failed, but we can retry on "prefer". Have to drop
3208  * the current connection to do so, though.
3209  */
3210  conn->try_gss = false;
3211  need_new_connection = true;
3212  goto keep_going;
3213  }
3214  return pollres;
3215 #else /* !ENABLE_GSS */
3216  /* unreachable */
3217  goto error_return;
3218 #endif /* ENABLE_GSS */
3219  }
3220 
3221  /*
3222  * Handle authentication exchange: wait for postmaster messages
3223  * and respond as necessary.
3224  */
3226  {
3227  char beresp;
3228  int msgLength;
3229  int avail;
3230  AuthRequest areq;
3231  int res;
3232 
3233  /*
3234  * Scan the message from current point (note that if we find
3235  * the message is incomplete, we will return without advancing
3236  * inStart, and resume here next time).
3237  */
3238  conn->inCursor = conn->inStart;
3239 
3240  /* Read type byte */
3241  if (pqGetc(&beresp, conn))
3242  {
3243  /* We'll come back when there is more data */
3244  return PGRES_POLLING_READING;
3245  }
3246 
3247  /*
3248  * Validate message type: we expect only an authentication
3249  * request or an error here. Anything else probably means
3250  * it's not Postgres on the other end at all.
3251  */
3252  if (!(beresp == 'R' || beresp == 'E'))
3253  {
3255  libpq_gettext("expected authentication request from server, but received %c\n"),
3256  beresp);
3257  goto error_return;
3258  }
3259 
3260  /* Read message length word */
3261  if (pqGetInt(&msgLength, 4, conn))
3262  {
3263  /* We'll come back when there is more data */
3264  return PGRES_POLLING_READING;
3265  }
3266 
3267  /*
3268  * Try to validate message length before using it.
3269  * Authentication requests can't be very large, although GSS
3270  * auth requests may not be that small. Errors can be a
3271  * little larger, but not huge. If we see a large apparent
3272  * length in an error, it means we're really talking to a
3273  * pre-3.0-protocol server; cope. (Before version 14, the
3274  * server also used the old protocol for errors that happened
3275  * before processing the startup packet.)
3276  */
3277  if (beresp == 'R' && (msgLength < 8 || msgLength > 2000))
3278  {
3280  libpq_gettext("expected authentication request from server, but received %c\n"),
3281  beresp);
3282  goto error_return;
3283  }
3284 
3285  if (beresp == 'E' && (msgLength < 8 || msgLength > 30000))
3286  {
3287  /* Handle error from a pre-3.0 server */
3288  conn->inCursor = conn->inStart + 1; /* reread data */
3289  if (pqGets_append(&conn->errorMessage, conn))
3290  {
3291  /* We'll come back when there is more data */
3292  return PGRES_POLLING_READING;
3293  }
3294  /* OK, we read the message; mark data consumed */
3295  conn->inStart = conn->inCursor;
3296 
3297  /*
3298  * Before 7.2, the postmaster didn't always end its
3299  * messages with a newline, so add one if needed to
3300  * conform to libpq conventions.
3301  */
3302  if (conn->errorMessage.len == 0 ||
3303  conn->errorMessage.data[conn->errorMessage.len - 1] != '\n')
3304  {
3305  appendPQExpBufferChar(&conn->errorMessage, '\n');
3306  }
3307 
3308  goto error_return;
3309  }
3310 
3311  /*
3312  * Can't process if message body isn't all here yet.
3313  */
3314  msgLength -= 4;
3315  avail = conn->inEnd - conn->inCursor;
3316  if (avail < msgLength)
3317  {
3318  /*
3319  * Before returning, try to enlarge the input buffer if
3320  * needed to hold the whole message; see notes in
3321  * pqParseInput3.
3322  */
3323  if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
3324  conn))
3325  goto error_return;
3326  /* We'll come back when there is more data */
3327  return PGRES_POLLING_READING;
3328  }
3329 
3330  /* Handle errors. */
3331  if (beresp == 'E')
3332  {
3333  if (pqGetErrorNotice3(conn, true))
3334  {
3335  /* We'll come back when there is more data */
3336  return PGRES_POLLING_READING;
3337  }
3338  /* OK, we read the message; mark data consumed */
3339  conn->inStart = conn->inCursor;
3340 
3341  /*
3342  * If error is "cannot connect now", try the next host if
3343  * any (but we don't want to consider additional addresses
3344  * for this host, nor is there much point in changing SSL
3345  * or GSS mode). This is helpful when dealing with
3346  * standby servers that might not be in hot-standby state.
3347  */
3348  if (strcmp(conn->last_sqlstate,
3350  {
3351  conn->try_next_host = true;
3352  goto keep_going;
3353  }
3354 
3355  /* Check to see if we should mention pgpassfile */
3356  pgpassfileWarning(conn);
3357 
3358 #ifdef ENABLE_GSS
3359 
3360  /*
3361  * If gssencmode is "prefer" and we're using GSSAPI, retry
3362  * without it.
3363  */
3364  if (conn->gssenc && conn->gssencmode[0] == 'p')
3365  {
3366  /* only retry once */
3367  conn->try_gss = false;
3368  need_new_connection = true;