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

Go to the source code of this file.

Data Structures

struct  _internalPQconninfoOption
 

Macros

#define PGPASSFILE   ".pgpass"
 
#define ERRCODE_APPNAME_UNKNOWN   "42704"
 
#define ERRCODE_INVALID_PASSWORD   "28P01"
 
#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"
 
#define DefaultHost   "localhost"
 
#define 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 127 of file fe-connect.c.

Referenced by connectOptions2().

◆ DefaultGSSMode

#define DefaultGSSMode   "disable"

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

Referenced by connectOptions2().

◆ DefaultHost

#define DefaultHost   "localhost"

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

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

◆ DefaultOption

#define DefaultOption   ""

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

◆ DefaultSSLMode

#define DefaultSSLMode   "disable"

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

Referenced by connectOptions2().

◆ DefaultTargetSessionAttrs

#define DefaultTargetSessionAttrs   "any"

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

◆ ERRCODE_APPNAME_UNKNOWN

#define ERRCODE_APPNAME_UNKNOWN   "42704"

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

Referenced by PQconnectPoll().

◆ ERRCODE_CANNOT_CONNECT_NOW

#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"

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

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

◆ ERRCODE_INVALID_PASSWORD

#define ERRCODE_INVALID_PASSWORD   "28P01"

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

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

◆ PGPASSFILE

#define PGPASSFILE   ".pgpass"

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

Referenced by connectOptions2().

Typedef Documentation

◆ internalPQconninfoOption

Function Documentation

◆ closePGconn()

static void closePGconn ( PGconn conn)
static

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

4183 {
4184  /*
4185  * If possible, send Terminate message to close the connection politely.
4186  */
4187  sendTerminateConn(conn);
4188 
4189  /*
4190  * Must reset the blocking status so a possible reconnect will work.
4191  *
4192  * Don't call PQsetnonblocking() because it will fail if it's unable to
4193  * flush the connection.
4194  */
4195  conn->nonblocking = false;
4196 
4197  /*
4198  * Close the connection, reset all transient state, flush I/O buffers.
4199  * Note that this includes clearing conn->errorMessage; we're no longer
4200  * interested in any failures associated with the old connection, and we
4201  * want a clean slate for any new connection attempt.
4202  */
4203  pqDropConnection(conn, true);
4204  conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
4205  conn->asyncStatus = PGASYNC_IDLE;
4206  conn->xactStatus = PQTRANS_IDLE;
4208  pqClearAsyncResult(conn); /* deallocate result */
4210  release_conn_addrinfo(conn);
4211 
4212  /* Reset all state obtained from server, too */
4213  pqDropServerData(conn);
4214 }
static void release_conn_addrinfo(PGconn *conn)
Definition: fe-connect.c:4140
PGpipelineStatus pipelineStatus
Definition: libpq-int.h:416
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:449
static void sendTerminateConn(PGconn *conn)
Definition: fe-connect.c:4155
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:410
static void pqDropServerData(PGconn *conn)
Definition: fe-connect.c:561
PQExpBufferData errorMessage
Definition: libpq-int.h:569
ConnStatusType status
Definition: libpq-int.h:409
bool nonblocking
Definition: libpq-int.h:414
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:735
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148
PGTransactionStatusType xactStatus
Definition: libpq-int.h:411

◆ 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:461
static bool parse_int_param(const char *value, int *result, PGconn *conn, const char *context)
Definition: fe-connect.c:1800
int pqWaitTimed(int forRead, int forWrite, PGconn *conn, time_t finish_time)
Definition: fe-misc.c:1003
char * connect_timeout
Definition: libpq-int.h:359
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:458
ConnStatusType status
Definition: libpq-int.h:409
PostgresPollingStatusType
Definition: libpq-fe.h:73
int whichhost
Definition: libpq-int.h:425

◆ 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:482
int inStart
Definition: libpq-int.h:480
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
int outCount
Definition: libpq-int.h:487
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:449
bool try_next_host
Definition: libpq-int.h:459
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
Definition: fe-connect.c:2246
PQExpBufferData errorMessage
Definition: libpq-int.h:569
bool try_next_addr
Definition: libpq-int.h:458
bool options_valid
Definition: libpq-int.h:413
ConnStatusType status
Definition: libpq-int.h:409
int inCursor
Definition: libpq-int.h:481
PGTargetServerType target_server_type
Definition: libpq-int.h:457
int whichhost
Definition: libpq-int.h:425

◆ connectFailureMessage()

static void connectFailureMessage ( PGconn conn,
int  errorno 
)
static

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

1758 {
1759  char sebuf[PG_STRERROR_R_BUFLEN];
1760 
1762  "%s\n",
1763  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
1764 
1765 #ifdef HAVE_UNIX_SOCKETS
1766  if (IS_AF_UNIX(conn->raddr.addr.ss_family))
1768  libpq_gettext("\tIs the server running locally and accepting connections on that socket?\n"));
1769  else
1770 #endif
1772  libpq_gettext("\tIs the server running on that host and accepting TCP/IP connections?\n"));
1773 }
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:860
#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:446
PQExpBufferData errorMessage
Definition: libpq-int.h:569
#define libpq_gettext(x)
Definition: libpq-int.h:846

◆ connectNoDelay()

static int connectNoDelay ( PGconn conn)
static

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

1638 {
1639 #ifdef TCP_NODELAY
1640  int on = 1;
1641 
1642  if (setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY,
1643  (char *) &on,
1644  sizeof(on)) < 0)
1645  {
1646  char sebuf[PG_STRERROR_R_BUFLEN];
1647 
1649  libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
1650  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
1651  return 0;
1652  }
1653 #endif
1654 
1655  return 1;
1656 }
#define PG_STRERROR_R_BUFLEN
Definition: port.h:234
#define SOCK_STRERROR
Definition: libpq-int.h:860
#define SOCK_ERRNO
Definition: libpq-int.h:859
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
pgsocket sock
Definition: libpq-int.h:443
PQExpBufferData errorMessage
Definition: libpq-int.h:569
#define libpq_gettext(x)
Definition: libpq-int.h:846

◆ connectOptions1()

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

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

935 {
936  PQconninfoOption *connOptions;
937 
938  /*
939  * Parse the conninfo string
940  */
941  connOptions = parse_connection_string(conninfo, &conn->errorMessage, true);
942  if (connOptions == NULL)
943  {
944  conn->status = CONNECTION_BAD;
945  /* errorMessage is already set */
946  return false;
947  }
948 
949  /*
950  * Move option values into conn structure
951  */
952  if (!fillPGconn(conn, connOptions))
953  {
954  conn->status = CONNECTION_BAD;
955  PQconninfoFree(connOptions);
956  return false;
957  }
958 
959  /*
960  * Free the option info - all is in conn now
961  */
962  PQconninfoFree(connOptions);
963 
964  return true;
965 }
static PQconninfoOption * parse_connection_string(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5382
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6555
PQExpBufferData errorMessage
Definition: libpq-int.h:569
static bool fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
Definition: fe-connect.c:892
ConnStatusType status
Definition: libpq-int.h:409

◆ connectOptions2()

static bool connectOptions2 ( PGconn conn)
static

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

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

◆ conninfo_add_defaults()

static bool conninfo_add_defaults ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

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

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

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

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

◆ conninfo_find()

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

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

References _PQconninfoOption::keyword.

Referenced by conninfo_getval(), and conninfo_storeval().

6494 {
6496 
6497  for (option = connOptions; option->keyword != NULL; option++)
6498  {
6499  if (strcmp(option->keyword, keyword) == 0)
6500  return option;
6501  }
6502 
6503  return NULL;
6504 }

◆ conninfo_getval()

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

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

References conninfo_find(), and _PQconninfoOption::val.

Referenced by fillPGconn(), and parseServiceInfo().

6404 {
6406 
6407  option = conninfo_find(connOptions, keyword);
6408 
6409  return option ? option->val : NULL;
6410 }
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6493

◆ conninfo_init()

static PQconninfoOption * conninfo_init ( PQExpBuffer  errorMessage)
static

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

5343 {
5345  PQconninfoOption *opt_dest;
5346  const internalPQconninfoOption *cur_opt;
5347 
5348  /*
5349  * Get enough memory for all options in PQconninfoOptions, even if some
5350  * end up being filtered out.
5351  */
5352  options = (PQconninfoOption *) malloc(sizeof(PQconninfoOption) * sizeof(PQconninfoOptions) / sizeof(PQconninfoOptions[0]));
5353  if (options == NULL)
5354  {
5355  appendPQExpBufferStr(errorMessage,
5356  libpq_gettext("out of memory\n"));
5357  return NULL;
5358  }
5359  opt_dest = options;
5360 
5361  for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++)
5362  {
5363  /* Only copy the public part of the struct, not the full internal */
5364  memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption));
5365  opt_dest++;
5366  }
5367  MemSet(opt_dest, 0, sizeof(PQconninfoOption));
5368 
5369  return options;
5370 }
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:192
static char ** options
#define libpq_gettext(x)
Definition: libpq-int.h:846

◆ conninfo_parse()

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

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

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

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

6432 {
6434  char *value_copy;
6435 
6436  /*
6437  * For backwards compatibility, requiressl=1 gets translated to
6438  * sslmode=require, and requiressl=0 gets translated to sslmode=prefer
6439  * (which is the default for sslmode).
6440  */
6441  if (strcmp(keyword, "requiressl") == 0)
6442  {
6443  keyword = "sslmode";
6444  if (value[0] == '1')
6445  value = "require";
6446  else
6447  value = "prefer";
6448  }
6449 
6450  option = conninfo_find(connOptions, keyword);
6451  if (option == NULL)
6452  {
6453  if (!ignoreMissing)
6454  appendPQExpBuffer(errorMessage,
6455  libpq_gettext("invalid connection option \"%s\"\n"),
6456  keyword);
6457  return NULL;
6458  }
6459 
6460  if (uri_decode)
6461  {
6462  value_copy = conninfo_uri_decode(value, errorMessage);
6463  if (value_copy == NULL)
6464  /* conninfo_uri_decode already set an error message */
6465  return NULL;
6466  }
6467  else
6468  {
6469  value_copy = strdup(value);
6470  if (value_copy == NULL)
6471  {
6472  appendPQExpBufferStr(errorMessage, libpq_gettext("out of memory\n"));
6473  return NULL;
6474  }
6475  }
6476 
6477  if (option->val)
6478  free(option->val);
6479  option->val = value_copy;
6480 
6481  return option;
6482 }
static struct @142 value
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6493
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:6313
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
#define free(a)
Definition: header.h:65
#define libpq_gettext(x)
Definition: libpq-int.h:846

◆ conninfo_uri_decode()

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

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

6314 {
6315  char *buf;
6316  char *p;
6317  const char *q = str;
6318 
6319  buf = malloc(strlen(str) + 1);
6320  if (buf == NULL)
6321  {
6322  appendPQExpBufferStr(errorMessage, libpq_gettext("out of memory\n"));
6323  return NULL;
6324  }
6325  p = buf;
6326 
6327  for (;;)
6328  {
6329  if (*q != '%')
6330  {
6331  /* copy and check for NUL terminator */
6332  if (!(*(p++) = *(q++)))
6333  break;
6334  }
6335  else
6336  {
6337  int hi;
6338  int lo;
6339  int c;
6340 
6341  ++q; /* skip the percent sign itself */
6342 
6343  /*
6344  * Possible EOL will be caught by the first call to
6345  * get_hexdigit(), so we never dereference an invalid q pointer.
6346  */
6347  if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo)))
6348  {
6349  appendPQExpBuffer(errorMessage,
6350  libpq_gettext("invalid percent-encoded token: \"%s\"\n"),
6351  str);
6352  free(buf);
6353  return NULL;
6354  }
6355 
6356  c = (hi << 4) | lo;
6357  if (c == 0)
6358  {
6359  appendPQExpBuffer(errorMessage,
6360  libpq_gettext("forbidden value %%00 in percent-encoded value: \"%s\"\n"),
6361  str);
6362  free(buf);
6363  return NULL;
6364  }
6365  *(p++) = c;
6366  }
6367  }
6368 
6369  return buf;
6370 }
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:6381
#define libpq_gettext(x)
Definition: libpq-int.h:846

◆ conninfo_uri_parse()

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

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

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

Referenced by parse_connection_string().

5885 {
5887 
5888  /* Make a working copy of PQconninfoOptions */
5889  options = conninfo_init(errorMessage);
5890  if (options == NULL)
5891  return NULL;
5892 
5893  if (!conninfo_uri_parse_options(options, uri, errorMessage))
5894  {
5895  PQconninfoFree(options);
5896  return NULL;
5897  }
5898 
5899  /*
5900  * Add in defaults if the caller wants that.
5901  */
5902  if (use_defaults)
5903  {
5904  if (!conninfo_add_defaults(options, errorMessage))
5905  {
5906  PQconninfoFree(options);
5907  return NULL;
5908  }
5909  }
5910 
5911  return options;
5912 }
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5342
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6555
static bool conninfo_uri_parse_options(PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage)
Definition: fe-connect.c:5936
static char ** options
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5778

◆ conninfo_uri_parse_options()

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

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

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

◆ conninfo_uri_parse_params()

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

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

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

◆ count_comma_separated_elems()

static int count_comma_separated_elems ( const char *  input)
static

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

Referenced by connectOptions2().

972 {
973  int n;
974 
975  n = 1;
976  for (; *input != '\0'; input++)
977  {
978  if (*input == ',')
979  n++;
980  }
981 
982  return n;
983 }

◆ default_threadlock()

static void default_threadlock ( int  acquire)
static

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

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

Referenced by PQregisterThreadLock().

7247 {
7248 #ifdef ENABLE_THREAD_SAFETY
7249 #ifndef WIN32
7250  static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
7251 #else
7252  static pthread_mutex_t singlethread_lock = NULL;
7253  static long mutex_initlock = 0;
7254 
7255  if (singlethread_lock == NULL)
7256  {
7257  while (InterlockedExchange(&mutex_initlock, 1) == 1)
7258  /* loop, another thread own the lock */ ;
7259  if (singlethread_lock == NULL)
7260  {
7261  if (pthread_mutex_init(&singlethread_lock, NULL))
7262  PGTHREAD_ERROR("failed to initialize mutex");
7263  }
7264  InterlockedExchange(&mutex_initlock, 0);
7265  }
7266 #endif
7267  if (acquire)
7268  {
7269  if (pthread_mutex_lock(&singlethread_lock))
7270  PGTHREAD_ERROR("failed to lock mutex");
7271  }
7272  else
7273  {
7274  if (pthread_mutex_unlock(&singlethread_lock))
7275  PGTHREAD_ERROR("failed to unlock mutex");
7276  }
7277 #endif
7278 }
CRITICAL_SECTION * pthread_mutex_t
Definition: pthread-win32.h:8
int pthread_mutex_init(pthread_mutex_t *mp, void *attr)
Definition: pthread-win32.c:35
int pthread_mutex_lock(pthread_mutex_t *mp)
Definition: pthread-win32.c:45
int pthread_mutex_unlock(pthread_mutex_t *mp)
Definition: pthread-win32.c:54

◆ defaultNoticeProcessor()

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

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

References fprintf.

Referenced by makeEmptyPGconn().

6926 {
6927  (void) arg; /* not used */
6928  /* Note: we expect the supplied string to end with a newline already. */
6929  fprintf(stderr, "%s", message);
6930 }
#define fprintf
Definition: port.h:220
void * arg

◆ defaultNoticeReceiver()

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

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

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

Referenced by makeEmptyPGconn().

6911 {
6912  (void) arg; /* not used */
6913  if (res->noticeHooks.noticeProc != NULL)
6915  PQresultErrorMessage(res));
6916 }
PGNoticeHooks noticeHooks
Definition: libpq-int.h:186
void * noticeProcArg
Definition: libpq-int.h:155
PQnoticeProcessor noticeProc
Definition: libpq-int.h:154
char * PQresultErrorMessage(const PGresult *res)
Definition: fe-exec.c:3113
void * arg

◆ emitHostIdentityInfo()

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

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

1700 {
1701 #ifdef HAVE_UNIX_SOCKETS
1702  if (IS_AF_UNIX(conn->raddr.addr.ss_family))
1703  {
1704  char service[NI_MAXHOST];
1705 
1706  pg_getnameinfo_all(&conn->raddr.addr, conn->raddr.salen,
1707  NULL, 0,
1708  service, sizeof(service),
1709  NI_NUMERICSERV);
1711  libpq_gettext("connection to server on socket \"%s\" failed: "),
1712  service);
1713  }
1714  else
1715 #endif /* HAVE_UNIX_SOCKETS */
1716  {
1717  const char *displayed_host;
1718  const char *displayed_port;
1719 
1720  /* To which host and port were we actually connecting? */
1721  if (conn->connhost[conn->whichhost].type == CHT_HOST_ADDRESS)
1722  displayed_host = conn->connhost[conn->whichhost].hostaddr;
1723  else
1724  displayed_host = conn->connhost[conn->whichhost].host;
1725  displayed_port = conn->connhost[conn->whichhost].port;
1726  if (displayed_port == NULL || displayed_port[0] == '\0')
1727  displayed_port = DEF_PGPORT_STR;
1728 
1729  /*
1730  * If the user did not supply an IP address using 'hostaddr', and
1731  * 'host' was missing or does not match our lookup, display the
1732  * looked-up IP address.
1733  */
1734  if (conn->connhost[conn->whichhost].type != CHT_HOST_ADDRESS &&
1735  host_addr[0] &&
1736  strcmp(displayed_host, host_addr) != 0)
1738  libpq_gettext("connection to server at \"%s\" (%s), port %s failed: "),
1739  displayed_host, host_addr,
1740  displayed_port);
1741  else
1743  libpq_gettext("connection to server at \"%s\", port %s failed: "),
1744  displayed_host,
1745  displayed_port);
1746  }
1747 }
char * host
Definition: libpq-int.h:334
struct sockaddr_storage addr
Definition: pqcomm.h:64
pg_conn_host_type type
Definition: libpq-int.h:333
#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:335
pg_conn_host * connhost
Definition: libpq-int.h:426
ACCEPT_TYPE_ARG3 salen
Definition: pqcomm.h:65
SockAddr raddr
Definition: libpq-int.h:446
PQExpBufferData errorMessage
Definition: libpq-int.h:569
#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:336
int whichhost
Definition: libpq-int.h:425
#define libpq_gettext(x)
Definition: libpq-int.h:846

◆ fillPGconn()

static bool fillPGconn ( PGconn conn,
PQconninfoOption connOptions 
)
static

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

893 {
895 
896  for (option = PQconninfoOptions; option->keyword; option++)
897  {
898  if (option->connofs >= 0)
899  {
900  const char *tmp = conninfo_getval(connOptions, option->keyword);
901 
902  if (tmp)
903  {
904  char **connmember = (char **) ((char *) conn + option->connofs);
905 
906  if (*connmember)
907  free(*connmember);
908  *connmember = strdup(tmp);
909  if (*connmember == NULL)
910  {
912  libpq_gettext("out of memory\n"));
913  return false;
914  }
915  }
916  }
917  }
918 
919  return true;
920 }
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:192
PQExpBufferData errorMessage
Definition: libpq-int.h:569
#define free(a)
Definition: header.h:65
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6402
#define libpq_gettext(x)
Definition: libpq-int.h:846

◆ freePGconn()

static void freePGconn ( PGconn conn)
static

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

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

◆ get_hexdigit()

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

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

Referenced by conninfo_uri_decode().

6382 {
6383  if ('0' <= digit && digit <= '9')
6384  *value = digit - '0';
6385  else if ('A' <= digit && digit <= 'F')
6386  *value = digit - 'A' + 10;
6387  else if ('a' <= digit && digit <= 'f')
6388  *value = digit - 'a' + 10;
6389  else
6390  return false;
6391 
6392  return true;
6393 }
static struct @142 value

◆ getHostaddr()

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

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

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

Referenced by PQconnectPoll().

1665 {
1666  struct sockaddr_storage *addr = &conn->raddr.addr;
1667 
1668  if (addr->ss_family == AF_INET)
1669  {
1670  if (pg_inet_net_ntop(AF_INET,
1671  &((struct sockaddr_in *) addr)->sin_addr.s_addr,
1672  32,
1673  host_addr, host_addr_len) == NULL)
1674  host_addr[0] = '\0';
1675  }
1676 #ifdef HAVE_IPV6
1677  else if (addr->ss_family == AF_INET6)
1678  {
1679  if (pg_inet_net_ntop(AF_INET6,
1680  &((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr,
1681  128,
1682  host_addr, host_addr_len) == NULL)
1683  host_addr[0] = '\0';
1684  }
1685 #endif
1686  else
1687  host_addr[0] = '\0';
1688 }
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:446

◆ internal_cancel()

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

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

4395 {
4396  int save_errno = SOCK_ERRNO;
4397  pgsocket tmpsock = PGINVALID_SOCKET;
4398  char sebuf[PG_STRERROR_R_BUFLEN];
4399  int maxlen;
4400  struct
4401  {
4402  uint32 packetlen;
4404  } crp;
4405 
4406  /*
4407  * We need to open a temporary connection to the postmaster. Do this with
4408  * only kernel calls.
4409  */
4410  if ((tmpsock = socket(raddr->addr.ss_family, SOCK_STREAM, 0)) == PGINVALID_SOCKET)
4411  {
4412  strlcpy(errbuf, "PQcancel() -- socket() failed: ", errbufsize);
4413  goto cancel_errReturn;
4414  }
4415 retry3:
4416  if (connect(tmpsock, (struct sockaddr *) &raddr->addr,
4417  raddr->salen) < 0)
4418  {
4419  if (SOCK_ERRNO == EINTR)
4420  /* Interrupted system call - we'll just try again */
4421  goto retry3;
4422  strlcpy(errbuf, "PQcancel() -- connect() failed: ", errbufsize);
4423  goto cancel_errReturn;
4424  }
4425 
4426  /*
4427  * We needn't set nonblocking I/O or NODELAY options here.
4428  */
4429 
4430  /* Create and send the cancel request packet. */
4431 
4432  crp.packetlen = pg_hton32((uint32) sizeof(crp));
4433  crp.cp.cancelRequestCode = (MsgType) pg_hton32(CANCEL_REQUEST_CODE);
4434  crp.cp.backendPID = pg_hton32(be_pid);
4435  crp.cp.cancelAuthCode = pg_hton32(be_key);
4436 
4437 retry4:
4438  if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp))
4439  {
4440  if (SOCK_ERRNO == EINTR)
4441  /* Interrupted system call - we'll just try again */
4442  goto retry4;
4443  strlcpy(errbuf, "PQcancel() -- send() failed: ", errbufsize);
4444  goto cancel_errReturn;
4445  }
4446 
4447  /*
4448  * Wait for the postmaster to close the connection, which indicates that
4449  * it's processed the request. Without this delay, we might issue another
4450  * command only to find that our cancel zaps that command instead of the
4451  * one we thought we were canceling. Note we don't actually expect this
4452  * read to obtain any data, we are just waiting for EOF to be signaled.
4453  */
4454 retry5:
4455  if (recv(tmpsock, (char *) &crp, 1, 0) < 0)
4456  {
4457  if (SOCK_ERRNO == EINTR)
4458  /* Interrupted system call - we'll just try again */
4459  goto retry5;
4460  /* we ignore other error conditions */
4461  }
4462 
4463  /* All done */
4464  closesocket(tmpsock);
4465  SOCK_ERRNO_SET(save_errno);
4466  return true;
4467 
4468 cancel_errReturn:
4469 
4470  /*
4471  * Make sure we don't overflow the error buffer. Leave space for the \n at
4472  * the end, and for the terminating zero.
4473  */
4474  maxlen = errbufsize - strlen(errbuf) - 2;
4475  if (maxlen >= 0)
4476  {
4477  strncat(errbuf, SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)),
4478  maxlen);
4479  strcat(errbuf, "\n");
4480  }
4481  if (tmpsock != PGINVALID_SOCKET)
4482  closesocket(tmpsock);
4483  SOCK_ERRNO_SET(save_errno);
4484  return false;
4485 }
#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:860
#define pg_hton32(x)
Definition: pg_bswap.h:121
#define SOCK_ERRNO
Definition: libpq-int.h:859
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:861
#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 3842 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().

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

◆ makeEmptyPGconn()

static PGconn * makeEmptyPGconn ( void  )
static

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

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

◆ parse_comma_separated_list()

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

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

References malloc, and startptr.

Referenced by connectOptions2().

996 {
997  char *p;
998  char *s = *startptr;
999  char *e;
1000  int len;
1001 
1002  /*
1003  * Search for the end of the current element; a comma or end-of-string
1004  * acts as a terminator.
1005  */
1006  e = s;
1007  while (*e != '\0' && *e != ',')
1008  ++e;
1009  *more = (*e == ',');
1010 
1011  len = e - s;
1012  p = (char *) malloc(sizeof(char) * (len + 1));
1013  if (p)
1014  {
1015  memcpy(p, s, len);
1016  p[len] = '\0';
1017  }
1018  *startptr = e + 1;
1019 
1020  return p;
1021 }
#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 5382 of file fe-connect.c.

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

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

5384 {
5385  /* Parse as URI if connection string matches URI prefix */
5386  if (uri_prefix_length(connstr) != 0)
5387  return conninfo_uri_parse(connstr, errorMessage, use_defaults);
5388 
5389  /* Parse as default otherwise */
5390  return conninfo_parse(connstr, errorMessage, use_defaults);
5391 }
static PQconninfoOption * conninfo_parse(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5436
static int uri_prefix_length(const char *connstr)
Definition: fe-connect.c:5402
static PQconninfoOption * conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5883
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 1800 of file fe-connect.c.

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

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

1802 {
1803  char *end;
1804  long numval;
1805 
1806  Assert(value != NULL);
1807 
1808  *result = 0;
1809 
1810  /* strtol(3) skips leading whitespaces */
1811  errno = 0;
1812  numval = strtol(value, &end, 10);
1813 
1814  /*
1815  * If no progress was done during the parsing or an error happened, fail.
1816  * This tests properly for overflows of the result.
1817  */
1818  if (value == end || errno != 0 || numval != (int) numval)
1819  goto error;
1820 
1821  /*
1822  * Skip any trailing whitespace; if anything but whitespace remains before
1823  * the terminating character, fail
1824  */
1825  while (*end != '\0' && isspace((unsigned char) *end))
1826  end++;
1827 
1828  if (*end != '\0')
1829  goto error;
1830 
1831  *result = numval;
1832  return true;
1833 
1834 error:
1836  libpq_gettext("invalid integer value \"%s\" for connection option \"%s\"\n"),
1837  value, context);
1838  return false;
1839 }
static struct @142 value
static void error(void)
Definition: sql-dyntest.c:147
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
PQExpBufferData errorMessage
Definition: libpq-int.h:569
#define Assert(condition)
Definition: c.h:804
#define libpq_gettext(x)
Definition: libpq-int.h:846

◆ parseServiceFile()

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

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

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

Referenced by parseServiceInfo().

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

◆ parseServiceInfo()

static int parseServiceInfo ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

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

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

Referenced by conninfo_add_defaults().

5079 {
5080  const char *service = conninfo_getval(options, "service");
5081  char serviceFile[MAXPGPATH];
5082  char *env;
5083  bool group_found = false;
5084  int status;
5085  struct stat stat_buf;
5086 
5087  /*
5088  * We have to special-case the environment variable PGSERVICE here, since
5089  * this is and should be called before inserting environment defaults for
5090  * other connection options.
5091  */
5092  if (service == NULL)
5093  service = getenv("PGSERVICE");
5094 
5095  /* If no service name given, nothing to do */
5096  if (service == NULL)
5097  return 0;
5098 
5099  /*
5100  * Try PGSERVICEFILE if specified, else try ~/.pg_service.conf (if that
5101  * exists).
5102  */
5103  if ((env = getenv("PGSERVICEFILE")) != NULL)
5104  strlcpy(serviceFile, env, sizeof(serviceFile));
5105  else
5106  {
5107  char homedir[MAXPGPATH];
5108 
5109  if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
5110  goto next_file;
5111  snprintf(serviceFile, MAXPGPATH, "%s/%s", homedir, ".pg_service.conf");
5112  if (stat(serviceFile, &stat_buf) != 0)
5113  goto next_file;
5114  }
5115 
5116  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
5117  if (group_found || status != 0)
5118  return status;
5119 
5120 next_file:
5121 
5122  /*
5123  * This could be used by any application so we can't use the binary
5124  * location to find our config files.
5125  */
5126  snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf",
5127  getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);
5128  if (stat(serviceFile, &stat_buf) != 0)
5129  goto last_file;
5130 
5131  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
5132  if (status != 0)
5133  return status;
5134 
5135 last_file:
5136  if (!group_found)
5137  {
5138  appendPQExpBuffer(errorMessage,
5139  libpq_gettext("definition of service \"%s\" not found\n"), service);
5140  return 3;
5141  }
5142 
5143  return 0;
5144 }
#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:5147
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6402
bool pqGetHomeDirectory(char *buf, int bufsize)
Definition: fe-connect.c:7217
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:846
#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 6974 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().

6976 {
6977  FILE *fp;
6978  struct stat stat_buf;
6980 
6981  if (dbname == NULL || dbname[0] == '\0')
6982  return NULL;
6983 
6984  if (username == NULL || username[0] == '\0')
6985  return NULL;
6986 
6987  /* 'localhost' matches pghost of '' or the default socket directory */
6988  if (hostname == NULL || hostname[0] == '\0')
6990  else if (is_unixsock_path(hostname))
6991 
6992  /*
6993  * We should probably use canonicalize_path(), but then we have to
6994  * bring path.c into libpq, and it doesn't seem worth it.
6995  */
6996  if (strcmp(hostname, DEFAULT_PGSOCKET_DIR) == 0)
6998 
6999  if (port == NULL || port[0] == '\0')
7000  port = DEF_PGPORT_STR;
7001 
7002  /* If password file cannot be opened, ignore it. */
7003  if (stat(pgpassfile, &stat_buf) != 0)
7004  return NULL;
7005 
7006 #ifndef WIN32
7007  if (!S_ISREG(stat_buf.st_mode))
7008  {
7009  fprintf(stderr,
7010  libpq_gettext("WARNING: password file \"%s\" is not a plain file\n"),
7011  pgpassfile);
7012  return NULL;
7013  }
7014 
7015  /* If password file is insecure, alert the user and ignore it. */
7016  if (stat_buf.st_mode & (S_IRWXG | S_IRWXO))
7017  {
7018  fprintf(stderr,
7019  libpq_gettext("WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
7020  pgpassfile);
7021  return NULL;
7022  }
7023 #else
7024 
7025  /*
7026  * On Win32, the directory is protected, so we don't have to check the
7027  * file.
7028  */
7029 #endif
7030 
7031  fp = fopen(pgpassfile, "r");
7032  if (fp == NULL)
7033  return NULL;
7034 
7035  /* Use an expansible buffer to accommodate any reasonable line length */
7036  initPQExpBuffer(&buf);
7037 
7038  while (!feof(fp) && !ferror(fp))
7039  {
7040  /* Make sure there's a reasonable amount of room in the buffer */
7041  if (!enlargePQExpBuffer(&buf, 128))
7042  break;
7043 
7044  /* Read some data, appending it to what we already have */
7045  if (fgets(buf.data + buf.len, buf.maxlen - buf.len, fp) == NULL)
7046  break;
7047  buf.len += strlen(buf.data + buf.len);
7048 
7049  /* If we don't yet have a whole line, loop around to read more */
7050  if (!(buf.len > 0 && buf.data[buf.len - 1] == '\n') && !feof(fp))
7051  continue;
7052 
7053  /* ignore comments */
7054  if (buf.data[0] != '#')
7055  {
7056  char *t = buf.data;
7057  int len;
7058 
7059  /* strip trailing newline and carriage return */
7060  len = pg_strip_crlf(t);
7061 
7062  if (len > 0 &&
7063  (t = pwdfMatchesString(t, hostname)) != NULL &&
7064  (t = pwdfMatchesString(t, port)) != NULL &&
7065  (t = pwdfMatchesString(t, dbname)) != NULL &&
7066  (t = pwdfMatchesString(t, username)) != NULL)
7067  {
7068  /* Found a match. */
7069  char *ret,
7070  *p1,
7071  *p2;
7072 
7073  ret = strdup(t);
7074 
7075  fclose(fp);
7076  explicit_bzero(buf.data, buf.maxlen);
7077  termPQExpBuffer(&buf);
7078 
7079  if (!ret)
7080  {
7081  /* Out of memory. XXX: an error message would be nice. */
7082  return NULL;
7083  }
7084 
7085  /* De-escape password. */
7086  for (p1 = p2 = ret; *p1 != ':' && *p1 != '\0'; ++p1, ++p2)
7087  {
7088  if (*p1 == '\\' && p1[1] != '\0')
7089  ++p1;
7090  *p2 = *p1;
7091  }
7092  *p2 = '\0';
7093 
7094  return ret;
7095  }
7096  }
7097 
7098  /* No match, reset buffer to prepare for next line. */
7099  buf.len = 0;
7100  }
7101 
7102  fclose(fp);
7103  explicit_bzero(buf.data, buf.maxlen);
7104  termPQExpBuffer(&buf);
7105  return NULL;
7106 }
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:280
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:122
static char * pwdfMatchesString(char *buf, const char *token)
Definition: fe-connect.c:6937
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:846
#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 7114 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().

7115 {
7116  /* If it was 'invalid authorization', add pgpassfile mention */
7117  /* only works with >= 9.0 servers */
7118  if (conn->password_needed &&
7119  conn->connhost[conn->whichhost].password != NULL &&
7120  conn->result)
7121  {
7122  const char *sqlstate = PQresultErrorField(conn->result,
7124 
7125  if (sqlstate && strcmp(sqlstate, ERRCODE_INVALID_PASSWORD) == 0)
7127  libpq_gettext("password retrieved from file \"%s\"\n"),
7128  conn->pgpassfile);
7129  }
7130 }
char * pgpassfile
Definition: libpq-int.h:369
bool password_needed
Definition: libpq-int.h:450
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
PGresult * result
Definition: libpq-int.h:499
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
pg_conn_host * connhost
Definition: libpq-int.h:426
PQExpBufferData errorMessage
Definition: libpq-int.h:569
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:3152
#define ERRCODE_INVALID_PASSWORD
Definition: fe-connect.c:95
int whichhost
Definition: libpq-int.h:425
#define libpq_gettext(x)
Definition: libpq-int.h:846
char * password
Definition: libpq-int.h:337

◆ PQbackendPID()

int PQbackendPID ( const PGconn conn)

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

6754 {
6755  if (!conn || conn->status != CONNECTION_OK)
6756  return 0;
6757  return conn->be_pid;
6758 }
ConnStatusType status
Definition: libpq-int.h:409
int be_pid
Definition: libpq-int.h:466

◆ PQcancel()

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

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

4498 {
4499  if (!cancel)
4500  {
4501  strlcpy(errbuf, "PQcancel() -- no cancel object supplied", errbufsize);
4502  return false;
4503  }
4504 
4505  return internal_cancel(&cancel->raddr, cancel->be_pid, cancel->be_key,
4506  errbuf, errbufsize);
4507 }
static int internal_cancel(SockAddr *raddr, int be_pid, int be_key, char *errbuf, int errbufsize)
Definition: fe-connect.c:4393
int be_pid
Definition: libpq-int.h:582
int be_key
Definition: libpq-int.h:583
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
SockAddr raddr
Definition: libpq-int.h:581

◆ PQclientEncoding()

int PQclientEncoding ( const PGconn conn)

◆ PQconndefaults()

PQconninfoOption* PQconndefaults ( void  )

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

1478 {
1479  PQExpBufferData errorBuf;
1480  PQconninfoOption *connOptions;
1481 
1482  /* We don't actually report any errors here, but callees want a buffer */
1483  initPQExpBuffer(&errorBuf);
1484  if (PQExpBufferDataBroken(errorBuf))
1485  return NULL; /* out of memory already :-( */
1486 
1487  connOptions = conninfo_init(&errorBuf);
1488  if (connOptions != NULL)
1489  {
1490  /* pass NULL errorBuf to ignore errors */
1491  if (!conninfo_add_defaults(connOptions, NULL))
1492  {
1493  PQconninfoFree(connOptions);
1494  connOptions = NULL;
1495  }
1496  }
1497 
1498  termPQExpBuffer(&errorBuf);
1499  return connOptions;
1500 }
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5342
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6555
#define PQExpBufferDataBroken(buf)
Definition: pqexpbuffer.h:67
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5778
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92

◆ PQconnectdb()

PGconn* PQconnectdb ( const char *  conninfo)

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

719 {
720  PGconn *conn = PQconnectStart(conninfo);
721 
722  if (conn && conn->status != CONNECTION_BAD)
723  (void) connectDBComplete(conn);
724 
725  return conn;
726 }
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:846
ConnStatusType status
Definition: libpq-int.h:409

◆ PQconnectdbParams()

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

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

665 {
666  PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname);
667 
668  if (conn && conn->status != CONNECTION_BAD)
669  (void) connectDBComplete(conn);
670 
671  return conn;
672 
673 }
PGconn * conn
Definition: streamutil.c:54
static int connectDBComplete(PGconn *conn)
Definition: fe-connect.c:2110
ConnStatusType status
Definition: libpq-int.h:409
static Datum values[MAXATTR]
Definition: bootstrap.c:166
PGconn * PQconnectStartParams(const char *const *keywords, const char *const *values, int expand_dbname)
Definition: fe-connect.c:765

◆ PQconnectionNeedsPassword()

int PQconnectionNeedsPassword ( const PGconn conn)

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

6771 {
6772  char *password;
6773 
6774  if (!conn)
6775  return false;
6776  password = PQpass(conn);
6777  if (conn->password_needed &&
6778  (password == NULL || password[0] == '\0'))
6779  return true;
6780  else
6781  return false;
6782 }
bool password_needed
Definition: libpq-int.h:450
char * PQpass(const PGconn *conn)
Definition: fe-connect.c:6589
static char * password
Definition: streamutil.c:53

◆ PQconnectionUsedPassword()

int PQconnectionUsedPassword ( const PGconn conn)

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

References pg_conn::password_needed.

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

6786 {
6787  if (!conn)
6788  return false;
6789  if (conn->password_needed)
6790  return true;
6791  else
6792  return false;
6793 }
bool password_needed
Definition: libpq-int.h:450

◆ 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, 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("setsockopt(%s) failed: %s\n"),
2636  "SO_KEEPALIVE",
2637  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2638  err = 1;
2639  }
2640  else if (!setKeepalivesIdle(conn)
2641  || !setKeepalivesInterval(conn)
2642  || !setKeepalivesCount(conn))
2643  err = 1;
2644 #else /* WIN32 */
2645 #ifdef SIO_KEEPALIVE_VALS
2646  else if (!setKeepalivesWin32(conn))
2647  err = 1;
2648 #endif /* SIO_KEEPALIVE_VALS */
2649 #endif /* WIN32 */
2650  else if (!setTCPUserTimeout(conn))
2651  err = 1;
2652 
2653  if (err)
2654  {
2655  conn->try_next_addr = true;
2656  goto keep_going;
2657  }
2658  }
2659 
2660  /*----------
2661  * We have three methods of blocking SIGPIPE during
2662  * send() calls to this socket:
2663  *
2664  * - setsockopt(sock, SO_NOSIGPIPE)
2665  * - send(sock, ..., MSG_NOSIGNAL)
2666  * - setting the signal mask to SIG_IGN during send()
2667  *
2668  * The third method requires three syscalls per send,
2669  * so we prefer either of the first two, but they are
2670  * less portable. The state is tracked in the following
2671  * members of PGconn:
2672  *
2673  * conn->sigpipe_so - we have set up SO_NOSIGPIPE
2674  * conn->sigpipe_flag - we're specifying MSG_NOSIGNAL
2675  *
2676  * If we can use SO_NOSIGPIPE, then set sigpipe_so here
2677  * and we're done. Otherwise, set sigpipe_flag so that
2678  * we will try MSG_NOSIGNAL on sends. If we get an error
2679  * with MSG_NOSIGNAL, we'll clear that flag and revert to
2680  * signal masking.
2681  *----------
2682  */
2683  conn->sigpipe_so = false;
2684 #ifdef MSG_NOSIGNAL
2685  conn->sigpipe_flag = true;
2686 #else
2687  conn->sigpipe_flag = false;
2688 #endif /* MSG_NOSIGNAL */
2689 
2690 #ifdef SO_NOSIGPIPE
2691  optval = 1;
2692  if (setsockopt(conn->sock, SOL_SOCKET, SO_NOSIGPIPE,
2693  (char *) &optval, sizeof(optval)) == 0)
2694  {
2695  conn->sigpipe_so = true;
2696  conn->sigpipe_flag = false;
2697  }
2698 #endif /* SO_NOSIGPIPE */
2699 
2700  /*
2701  * Start/make connection. This should not block, since we
2702  * are in nonblock mode. If it does, well, too bad.
2703  */
2704  if (connect(conn->sock, addr_cur->ai_addr,
2705  addr_cur->ai_addrlen) < 0)
2706  {
2707  if (SOCK_ERRNO == EINPROGRESS ||
2708 #ifdef WIN32
2709  SOCK_ERRNO == EWOULDBLOCK ||
2710 #endif
2711  SOCK_ERRNO == EINTR)
2712  {
2713  /*
2714  * This is fine - we're in non-blocking mode, and
2715  * the connection is in progress. Tell caller to
2716  * wait for write-ready on socket.
2717  */
2718  conn->status = CONNECTION_STARTED;
2719  return PGRES_POLLING_WRITING;
2720  }
2721  /* otherwise, trouble */
2722  }
2723  else
2724  {
2725  /*
2726  * Hm, we're connected already --- seems the "nonblock
2727  * connection" wasn't. Advance the state machine and
2728  * go do the next stuff.
2729  */
2730  conn->status = CONNECTION_STARTED;
2731  goto keep_going;
2732  }
2733 
2734  /*
2735  * This connection failed. Add the error report to
2736  * conn->errorMessage, then try the next address if any.
2737  */
2739  conn->try_next_addr = true;
2740  goto keep_going;
2741  }
2742  }
2743 
2744  case CONNECTION_STARTED:
2745  {
2746  ACCEPT_TYPE_ARG3 optlen = sizeof(optval);
2747 
2748  /*
2749  * Write ready, since we've made it here, so the connection
2750  * has been made ... or has failed.
2751  */
2752 
2753  /*
2754  * Now check (using getsockopt) that there is not an error
2755  * state waiting for us on the socket.
2756  */
2757 
2758  if (getsockopt(conn->sock, SOL_SOCKET, SO_ERROR,
2759  (char *) &optval, &optlen) == -1)
2760  {
2762  libpq_gettext("could not get socket error status: %s\n"),
2763  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2764  goto error_return;
2765  }
2766  else if (optval != 0)
2767  {
2768  /*
2769  * When using a nonblocking connect, we will typically see
2770  * connect failures at this point, so provide a friendly
2771  * error message.
2772  */
2773  connectFailureMessage(conn, optval);
2774 
2775  /*
2776  * Try the next address if any, just as in the case where
2777  * connect() returned failure immediately.
2778  */
2779  conn->try_next_addr = true;
2780  goto keep_going;
2781  }
2782 
2783  /* Fill in the client address */
2784  conn->laddr.salen = sizeof(conn->laddr.addr);
2785  if (getsockname(conn->sock,
2786  (struct sockaddr *) &conn->laddr.addr,
2787  &conn->laddr.salen) < 0)
2788  {
2790  libpq_gettext("could not get client address from socket: %s\n"),
2791  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2792  goto error_return;
2793  }
2794 
2795  /*
2796  * Make sure we can write before advancing to next step.
2797  */
2798  conn->status = CONNECTION_MADE;
2799  return PGRES_POLLING_WRITING;
2800  }
2801 
2802  case CONNECTION_MADE:
2803  {
2804  char *startpacket;
2805  int packetlen;
2806 
2807  /*
2808  * Implement requirepeer check, if requested and it's a
2809  * Unix-domain socket.
2810  */
2811  if (conn->requirepeer && conn->requirepeer[0] &&
2812  IS_AF_UNIX(conn->raddr.addr.ss_family))
2813  {
2814 #ifndef WIN32
2815  char pwdbuf[BUFSIZ];
2816  struct passwd pass_buf;
2817  struct passwd *pass;
2818  int passerr;
2819 #endif
2820  uid_t uid;
2821  gid_t gid;
2822 
2823  errno = 0;
2824  if (getpeereid(conn->sock, &uid, &gid) != 0)
2825  {
2826  /*
2827  * Provide special error message if getpeereid is a
2828  * stub
2829  */
2830  if (errno == ENOSYS)
2832  libpq_gettext("requirepeer parameter is not supported on this platform\n"));
2833  else
2835  libpq_gettext("could not get peer credentials: %s\n"),
2836  strerror_r(errno, sebuf, sizeof(sebuf)));
2837  goto error_return;
2838  }
2839 
2840 #ifndef WIN32
2841  passerr = pqGetpwuid(uid, &pass_buf, pwdbuf, sizeof(pwdbuf), &pass);
2842  if (pass == NULL)
2843  {
2844  if (passerr != 0)
2846  libpq_gettext("could not look up local user ID %d: %s\n"),
2847  (int) uid,
2848  strerror_r(passerr, sebuf, sizeof(sebuf)));
2849  else
2851  libpq_gettext("local user with ID %d does not exist\n"),
2852  (int) uid);
2853  goto error_return;
2854  }
2855 
2856  if (strcmp(pass->pw_name, conn->requirepeer) != 0)
2857  {
2859  libpq_gettext("requirepeer specifies \"%s\", but actual peer user name is \"%s\"\n"),
2860  conn->requirepeer, pass->pw_name);
2861  goto error_return;
2862  }
2863 #else /* WIN32 */
2864  /* should have failed with ENOSYS above */
2865  Assert(false);
2866 #endif /* WIN32 */
2867  }
2868 
2869  if (IS_AF_UNIX(conn->raddr.addr.ss_family))
2870  {
2871  /* Don't request SSL or GSSAPI over Unix sockets */
2872 #ifdef USE_SSL
2873  conn->allow_ssl_try = false;
2874 #endif
2875 #ifdef ENABLE_GSS
2876  conn->try_gss = false;
2877 #endif
2878  }
2879 
2880 #ifdef ENABLE_GSS
2881 
2882  /*
2883  * If GSSAPI encryption is enabled, then call
2884  * pg_GSS_have_cred_cache() which will return true if we can
2885  * acquire credentials (and give us a handle to use in
2886  * conn->gcred), and then send a packet to the server asking
2887  * for GSSAPI Encryption (and skip past SSL negotiation and
2888  * regular startup below).
2889  */
2890  if (conn->try_gss && !conn->gctx)
2891  conn->try_gss = pg_GSS_have_cred_cache(&conn->gcred);
2892  if (conn->try_gss && !conn->gctx)
2893  {
2895 
2896  if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
2897  {
2899  libpq_gettext("could not send GSSAPI negotiation packet: %s\n"),
2900  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2901  goto error_return;
2902  }
2903 
2904  /* Ok, wait for response */
2906  return PGRES_POLLING_READING;
2907  }
2908  else if (!conn->gctx && conn->gssencmode[0] == 'r')
2909  {
2911  libpq_gettext("GSSAPI encryption required but was impossible (possibly no credential cache, no server support, or using a local socket)\n"));
2912  goto error_return;
2913  }
2914 #endif
2915 
2916 #ifdef USE_SSL
2917 
2918  /*
2919  * Enable the libcrypto callbacks before checking if SSL needs
2920  * to be done. This is done before sending the startup packet
2921  * as depending on the type of authentication done, like MD5
2922  * or SCRAM that use cryptohashes, the callbacks would be
2923  * required even without a SSL connection
2924  */
2925  if (pqsecure_initialize(conn, false, true) < 0)
2926  goto error_return;
2927 
2928  /*
2929  * If SSL is enabled and we haven't already got encryption of
2930  * some sort running, request SSL instead of sending the
2931  * startup message.
2932  */
2933  if (conn->allow_ssl_try && !conn->wait_ssl_try &&
2934  !conn->ssl_in_use
2935 #ifdef ENABLE_GSS
2936  && !conn->gssenc
2937 #endif
2938  )
2939  {
2940  ProtocolVersion pv;
2941 
2942  /*
2943  * Send the SSL request packet.
2944  *
2945  * Theoretically, this could block, but it really
2946  * shouldn't since we only got here if the socket is
2947  * write-ready.
2948  */
2950  if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
2951  {
2953  libpq_gettext("could not send SSL negotiation packet: %s\n"),
2954  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2955  goto error_return;
2956  }
2957  /* Ok, wait for response */
2959  return PGRES_POLLING_READING;
2960  }
2961 #endif /* USE_SSL */
2962 
2963  /*
2964  * Build the startup packet.
2965  */
2966  startpacket = pqBuildStartupPacket3(conn, &packetlen,
2968  if (!startpacket)
2969  {
2971  libpq_gettext("out of memory\n"));
2972  goto error_return;
2973  }
2974 
2975  /*
2976  * Send the startup packet.
2977  *
2978  * Theoretically, this could block, but it really shouldn't
2979  * since we only got here if the socket is write-ready.
2980  */
2981  if (pqPacketSend(conn, 0, startpacket, packetlen) != STATUS_OK)
2982  {
2984  libpq_gettext("could not send startup packet: %s\n"),
2985  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2986  free(startpacket);
2987  goto error_return;
2988  }
2989 
2990  free(startpacket);
2991 
2993  return PGRES_POLLING_READING;
2994  }
2995 
2996  /*
2997  * Handle SSL negotiation: wait for postmaster messages and
2998  * respond as necessary.
2999  */
3001  {
3002 #ifdef USE_SSL
3003  PostgresPollingStatusType pollres;
3004 
3005  /*
3006  * On first time through, get the postmaster's response to our
3007  * SSL negotiation packet.
3008  */
3009  if (!conn->ssl_in_use)
3010  {
3011  /*
3012  * We use pqReadData here since it has the logic to
3013  * distinguish no-data-yet from connection closure. Since
3014  * conn->ssl isn't set, a plain recv() will occur.
3015  */
3016  char SSLok;
3017  int rdresult;
3018 
3019  rdresult = pqReadData(conn);
3020  if (rdresult < 0)
3021  {
3022  /* errorMessage is already filled in */
3023  goto error_return;
3024  }
3025  if (rdresult == 0)
3026  {
3027  /* caller failed to wait for data */
3028  return PGRES_POLLING_READING;
3029  }
3030  if (pqGetc(&SSLok, conn) < 0)
3031  {
3032  /* should not happen really */
3033  return PGRES_POLLING_READING;
3034  }
3035  if (SSLok == 'S')
3036  {
3037  /* mark byte consumed */
3038  conn->inStart = conn->inCursor;
3039 
3040  /*
3041  * Set up global SSL state if required. The crypto
3042  * state has already been set if libpq took care of
3043  * doing that, so there is no need to make that happen
3044  * again.
3045  */
3046  if (pqsecure_initialize(conn, true, false) != 0)
3047  goto error_return;
3048  }
3049  else if (SSLok == 'N')
3050  {
3051  /* mark byte consumed */
3052  conn->inStart = conn->inCursor;
3053  /* OK to do without SSL? */
3054  if (conn->sslmode[0] == 'r' || /* "require" */
3055  conn->sslmode[0] == 'v') /* "verify-ca" or
3056  * "verify-full" */
3057  {
3058  /* Require SSL, but server does not want it */
3060  libpq_gettext("server does not support SSL, but SSL was required\n"));
3061  goto error_return;
3062  }
3063  /* Otherwise, proceed with normal startup */
3064  conn->allow_ssl_try = false;
3065  /* We can proceed using this connection */
3066  conn->status = CONNECTION_MADE;
3067  return PGRES_POLLING_WRITING;
3068  }
3069  else if (SSLok == 'E')
3070  {
3071  /*
3072  * Server failure of some sort, such as failure to
3073  * fork a backend process. We need to process and
3074  * report the error message, which might be formatted
3075  * according to either protocol 2 or protocol 3.
3076  * Rather than duplicate the code for that, we flip
3077  * into AWAITING_RESPONSE state and let the code there
3078  * deal with it. Note we have *not* consumed the "E"
3079  * byte here.
3080  */
3082  goto keep_going;
3083  }
3084  else
3085  {
3087  libpq_gettext("received invalid response to SSL negotiation: %c\n"),
3088  SSLok);
3089  goto error_return;
3090  }
3091  }
3092 
3093  /*
3094  * Begin or continue the SSL negotiation process.
3095  */
3096  pollres = pqsecure_open_client(conn);
3097  if (pollres == PGRES_POLLING_OK)
3098  {
3099  /* SSL handshake done, ready to send startup packet */
3100  conn->status = CONNECTION_MADE;
3101  return PGRES_POLLING_WRITING;
3102  }
3103  if (pollres == PGRES_POLLING_FAILED)
3104  {
3105  /*
3106  * Failed ... if sslmode is "prefer" then do a non-SSL
3107  * retry
3108  */
3109  if (conn->sslmode[0] == 'p' /* "prefer" */
3110  && conn->allow_ssl_try /* redundant? */
3111  && !conn->wait_ssl_try) /* redundant? */
3112  {
3113  /* only retry once */
3114  conn->allow_ssl_try = false;
3115  need_new_connection = true;
3116  goto keep_going;
3117  }
3118  /* Else it's a hard failure */
3119  goto error_return;
3120  }
3121  /* Else, return POLLING_READING or POLLING_WRITING status */
3122  return pollres;
3123 #else /* !USE_SSL */
3124  /* can't get here */
3125  goto error_return;
3126 #endif /* USE_SSL */
3127  }
3128 
3130  {
3131 #ifdef ENABLE_GSS
3132  PostgresPollingStatusType pollres;
3133 
3134  /*
3135  * If we haven't yet, get the postmaster's response to our
3136  * negotiation packet
3137  */
3138  if (conn->try_gss && !conn->gctx)
3139  {
3140  char gss_ok;
3141  int rdresult = pqReadData(conn);
3142 
3143  if (rdresult < 0)
3144  /* pqReadData fills in error message */
3145  goto error_return;
3146  else if (rdresult == 0)
3147  /* caller failed to wait for data */
3148  return PGRES_POLLING_READING;
3149  if (pqGetc(&gss_ok, conn) < 0)
3150  /* shouldn't happen... */
3151  return PGRES_POLLING_READING;
3152 
3153  if (gss_ok == 'E')
3154  {
3155  /*
3156  * Server failure of some sort. Assume it's a
3157  * protocol version support failure, and let's see if
3158  * we can't recover (if it's not, we'll get a better
3159  * error message on retry). Server gets fussy if we
3160  * don't hang up the socket, though.
3161  */
3162  conn->try_gss = false;
3163  need_new_connection = true;
3164  goto keep_going;
3165  }
3166 
3167  /* mark byte consumed */
3168  conn->inStart = conn->inCursor;
3169 
3170  if (gss_ok == 'N')
3171  {
3172  /* Server doesn't want GSSAPI; fall back if we can */
3173  if (conn->gssencmode[0] == 'r')
3174  {
3176  libpq_gettext("server doesn't support GSSAPI encryption, but it was required\n"));
3177  goto error_return;
3178  }
3179 
3180  conn->try_gss = false;
3181  /* We can proceed using this connection */
3182  conn->status = CONNECTION_MADE;
3183  return PGRES_POLLING_WRITING;
3184  }
3185  else if (gss_ok != 'G')
3186  {
3188  libpq_gettext("received invalid response to GSSAPI negotiation: %c\n"),
3189  gss_ok);
3190  goto error_return;
3191  }
3192  }
3193 
3194  /* Begin or continue GSSAPI negotiation */
3195  pollres = pqsecure_open_gss(conn);
3196  if (pollres == PGRES_POLLING_OK)
3197  {
3198  /* All set for startup packet */
3199  conn->status = CONNECTION_MADE;
3200  return PGRES_POLLING_WRITING;
3201  }
3202  else if (pollres == PGRES_POLLING_FAILED &&
3203  conn->gssencmode[0] == 'p')
3204  {
3205  /*
3206  * We failed, but we can retry on "prefer". Have to drop
3207  * the current connection to do so, though.
3208  */
3209  conn->try_gss = false;
3210  need_new_connection = true;
3211  goto keep_going;
3212  }
3213  return pollres;
3214 #else /* !ENABLE_GSS */
3215  /* unreachable */
3216  goto error_return;
3217 #endif /* ENABLE_GSS */
3218  }
3219 
3220  /*
3221  * Handle authentication exchange: wait for postmaster messages
3222  * and respond as necessary.
3223  */
3225  {
3226  char beresp;
3227  int msgLength;
3228  int avail;
3229  AuthRequest areq;
3230  int res;
3231 
3232  /*
3233  * Scan the message from current point (note that if we find
3234  * the message is incomplete, we will return without advancing
3235  * inStart, and resume here next time).
3236  */
3237  conn->inCursor = conn->inStart;
3238 
3239  /* Read type byte */
3240  if (pqGetc(&beresp, conn))
3241  {
3242  /* We'll come back when there is more data */
3243  return PGRES_POLLING_READING;
3244  }
3245 
3246  /*
3247  * Validate message type: we expect only an authentication
3248  * request or an error here. Anything else probably means
3249  * it's not Postgres on the other end at all.
3250  */
3251  if (!(beresp == 'R' || beresp == 'E'))
3252  {
3254  libpq_gettext("expected authentication request from server, but received %c\n"),
3255  beresp);
3256  goto error_return;
3257  }
3258 
3259  /* Read message length word */
3260  if (pqGetInt(&msgLength, 4, conn))
3261  {
3262  /* We'll come back when there is more data */
3263  return PGRES_POLLING_READING;
3264  }
3265 
3266  /*
3267  * Try to validate message length before using it.
3268  * Authentication requests can't be very large, although GSS
3269  * auth requests may not be that small. Errors can be a
3270  * little larger, but not huge. If we see a large apparent
3271  * length in an error, it means we're really talking to a
3272  * pre-3.0-protocol server; cope. (Before version 14, the
3273  * server also used the old protocol for errors that happened
3274  * before processing the startup packet.)
3275  */
3276  if (beresp == 'R' && (msgLength < 8 || msgLength > 2000))
3277  {
3279  libpq_gettext("expected authentication request from server, but received %c\n"),
3280  beresp);
3281  goto error_return;
3282  }
3283 
3284  if (beresp == 'E' && (msgLength < 8 || msgLength > 30000))
3285  {
3286  /* Handle error from a pre-3.0 server */
3287  conn->inCursor = conn->inStart + 1; /* reread data */
3288  if (pqGets_append(&conn->errorMessage, conn))
3289  {
3290  /* We'll come back when there is more data */
3291  return PGRES_POLLING_READING;
3292  }
3293  /* OK, we read the message; mark data consumed */
3294  conn->inStart = conn->inCursor;
3295 
3296  /*
3297  * Before 7.2, the postmaster didn't always end its
3298  * messages with a newline, so add one if needed to
3299  * conform to libpq conventions.
3300  */
3301  if (conn->errorMessage.len == 0 ||
3302  conn->errorMessage.data[conn->errorMessage.len - 1] != '\n')
3303  {
3304  appendPQExpBufferChar(&conn->errorMessage, '\n');
3305  }
3306 
3307  goto error_return;
3308  }
3309 
3310  /*
3311  * Can't process if message body isn't all here yet.
3312  */
3313  msgLength -= 4;
3314  avail = conn->inEnd - conn->inCursor;
3315  if (avail < msgLength)
3316  {
3317  /*
3318  * Before returning, try to enlarge the input buffer if
3319  * needed to hold the whole message; see notes in
3320  * pqParseInput3.
3321  */
3322  if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
3323  conn))
3324  goto error_return;
3325  /* We'll come back when there is more data */
3326  return PGRES_POLLING_READING;
3327  }
3328 
3329  /* Handle errors. */
3330  if (beresp == 'E')
3331  {
3332  if (pqGetErrorNotice3(conn, true))
3333  {
3334  /* We'll come back when there is more data */
3335  return PGRES_POLLING_READING;
3336  }
3337  /* OK, we read the message; mark data consumed */
3338  conn->inStart = conn->inCursor;
3339 
3340  /*
3341  * If error is "cannot connect now", try the next host if
3342  * any (but we don't want to consider additional addresses
3343  * for this host, nor is there much point in changing SSL
3344  * or GSS mode). This is helpful when dealing with
3345  * standby servers that might not be in hot-standby state.
3346  */
3347  if (strcmp(conn->last_sqlstate,
3349  {
3350  conn->try_next_host = true;
3351  goto keep_going;
3352  }
3353 
3354  /* Check to see if we should mention pgpassfile */
3355  pgpassfileWarning(conn);
3356 
3357 #ifdef ENABLE_GSS
3358 
3359  /*
3360  * If gssencmode is "prefer" and we're using GSSAPI, retry
3361  * without it.
3362  */
<