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

Go to the source code of this file.

Data Structures

struct  _internalPQconninfoOption
 

Macros

#define PGPASSFILE   ".pgpass"
 
#define ERRCODE_APPNAME_UNKNOWN   "42704"
 
#define ERRCODE_INVALID_PASSWORD   "28P01"
 
#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"
 
#define DefaultHost   "localhost"
 
#define DefaultTty   ""
 
#define DefaultOption   ""
 
#define DefaultAuthtype   ""
 
#define DefaultChannelBinding   "disable"
 
#define DefaultTargetSessionAttrs   "any"
 
#define DefaultSSLMode   "disable"
 
#define DefaultGSSMode   "disable"
 

Typedefs

typedef struct _internalPQconninfoOption internalPQconninfoOption
 

Functions

static bool connectOptions1 (PGconn *conn, const char *conninfo)
 
static bool connectOptions2 (PGconn *conn)
 
static int connectDBStart (PGconn *conn)
 
static int connectDBComplete (PGconn *conn)
 
static PGPing internal_ping (PGconn *conn)
 
static PGconnmakeEmptyPGconn (void)
 
static bool fillPGconn (PGconn *conn, PQconninfoOption *connOptions)
 
static void freePGconn (PGconn *conn)
 
static void closePGconn (PGconn *conn)
 
static void release_conn_addrinfo (PGconn *conn)
 
static void sendTerminateConn (PGconn *conn)
 
static PQconninfoOptionconninfo_init (PQExpBuffer errorMessage)
 
static PQconninfoOptionparse_connection_string (const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
 
static int uri_prefix_length (const char *connstr)
 
static bool recognized_connection_string (const char *connstr)
 
static PQconninfoOptionconninfo_parse (const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
 
static PQconninfoOptionconninfo_array_parse (const char *const *keywords, const char *const *values, PQExpBuffer errorMessage, bool use_defaults, int expand_dbname)
 
static bool conninfo_add_defaults (PQconninfoOption *options, PQExpBuffer errorMessage)
 
static PQconninfoOptionconninfo_uri_parse (const char *uri, PQExpBuffer errorMessage, bool use_defaults)
 
static bool conninfo_uri_parse_options (PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage)
 
static bool conninfo_uri_parse_params (char *params, PQconninfoOption *connOptions, PQExpBuffer errorMessage)
 
static char * conninfo_uri_decode (const char *str, PQExpBuffer errorMessage)
 
static bool get_hexdigit (char digit, int *value)
 
static const char * conninfo_getval (PQconninfoOption *connOptions, const char *keyword)
 
static PQconninfoOptionconninfo_storeval (PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode)
 
static PQconninfoOptionconninfo_find (PQconninfoOption *connOptions, const char *keyword)
 
static void defaultNoticeReceiver (void *arg, const PGresult *res)
 
static void defaultNoticeProcessor (void *arg, const char *message)
 
static int parseServiceInfo (PQconninfoOption *options, PQExpBuffer errorMessage)
 
static int parseServiceFile (const char *serviceFile, const char *service, PQconninfoOption *options, PQExpBuffer errorMessage, bool *group_found)
 
static char * pwdfMatchesString (char *buf, const char *token)
 
static char * passwordFromFile (const char *hostname, const char *port, const char *dbname, const char *username, const char *pgpassfile)
 
static void pgpassfileWarning (PGconn *conn)
 
static void default_threadlock (int acquire)
 
static bool sslVerifyProtocolVersion (const char *version)
 
static bool sslVerifyProtocolRange (const char *min, const char *max)
 
void pqDropConnection (PGconn *conn, bool flushInput)
 
static void pqDropServerData (PGconn *conn)
 
PGconnPQconnectdbParams (const char *const *keywords, const char *const *values, int expand_dbname)
 
PGPing PQpingParams (const char *const *keywords, const char *const *values, int expand_dbname)
 
PGconnPQconnectdb (const char *conninfo)
 
PGPing PQping (const char *conninfo)
 
PGconnPQconnectStartParams (const char *const *keywords, const char *const *values, int expand_dbname)
 
PGconnPQconnectStart (const char *conninfo)
 
static int count_comma_separated_elems (const char *input)
 
static char * parse_comma_separated_list (char **startptr, bool *more)
 
PQconninfoOptionPQconndefaults (void)
 
PGconnPQsetdbLogin (const char *pghost, const char *pgport, const char *pgoptions, const char *pgtty, const char *dbName, const char *login, const char *pwd)
 
static int connectNoDelay (PGconn *conn)
 
static void getHostaddr (PGconn *conn, char *host_addr, int host_addr_len)
 
static void emitCouldNotConnect (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)
 
int PQconnectionNeedsPassword (const PGconn *conn)
 
int PQconnectionUsedPassword (const PGconn *conn)
 
int PQclientEncoding (const PGconn *conn)
 
int PQsetClientEncoding (PGconn *conn, const char *encoding)
 
PGVerbosity PQsetErrorVerbosity (PGconn *conn, PGVerbosity verbosity)
 
PGContextVisibility PQsetErrorContextVisibility (PGconn *conn, PGContextVisibility show_context)
 
void PQtrace (PGconn *conn, FILE *debug_port)
 
void PQuntrace (PGconn *conn)
 
PQnoticeReceiver PQsetNoticeReceiver (PGconn *conn, PQnoticeReceiver proc, void *arg)
 
PQnoticeProcessor PQsetNoticeProcessor (PGconn *conn, PQnoticeProcessor proc, void *arg)
 
bool pqGetHomeDirectory (char *buf, int bufsize)
 
pgthreadlock_t PQregisterThreadLock (pgthreadlock_t newhandler)
 

Variables

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

Macro Definition Documentation

◆ DefaultAuthtype

#define DefaultAuthtype   ""

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

◆ DefaultChannelBinding

#define DefaultChannelBinding   "disable"

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

Referenced by connectOptions2().

◆ DefaultGSSMode

#define DefaultGSSMode   "disable"

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

Referenced by connectOptions2().

◆ DefaultHost

#define DefaultHost   "localhost"

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

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

◆ DefaultOption

#define DefaultOption   ""

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

◆ DefaultSSLMode

#define DefaultSSLMode   "disable"

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

Referenced by connectOptions2().

◆ DefaultTargetSessionAttrs

#define DefaultTargetSessionAttrs   "any"

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

◆ DefaultTty

#define DefaultTty   ""

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

◆ ERRCODE_APPNAME_UNKNOWN

#define ERRCODE_APPNAME_UNKNOWN   "42704"

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

Referenced by PQconnectPoll().

◆ ERRCODE_CANNOT_CONNECT_NOW

#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"

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

Referenced by internal_ping(), 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 4082 of file fe-connect.c.

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

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

4083 {
4084  /*
4085  * If possible, send Terminate message to close the connection politely.
4086  */
4087  sendTerminateConn(conn);
4088 
4089  /*
4090  * Must reset the blocking status so a possible reconnect will work.
4091  *
4092  * Don't call PQsetnonblocking() because it will fail if it's unable to
4093  * flush the connection.
4094  */
4095  conn->nonblocking = false;
4096 
4097  /*
4098  * Close the connection, reset all transient state, flush I/O buffers.
4099  * Note that this includes clearing conn->errorMessage; we're no longer
4100  * interested in any failures associated with the old connection, and we
4101  * want a clean slate for any new connection attempt.
4102  */
4103  pqDropConnection(conn, true);
4104  conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
4105  conn->asyncStatus = PGASYNC_IDLE;
4106  conn->xactStatus = PQTRANS_IDLE;
4107  pqClearAsyncResult(conn); /* deallocate result */
4109  release_conn_addrinfo(conn);
4110 
4111  /* Reset all state obtained from server, too */
4112  pqDropServerData(conn);
4113 }
static void release_conn_addrinfo(PGconn *conn)
Definition: fe-connect.c:4040
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:459
static void sendTerminateConn(PGconn *conn)
Definition: fe-connect.c:4055
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:389
static void pqDropServerData(PGconn *conn)
Definition: fe-connect.c:554
PQExpBufferData errorMessage
Definition: libpq-int.h:530
ConnStatusType status
Definition: libpq-int.h:388
bool nonblocking
Definition: libpq-int.h:395
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:731
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148
PGTransactionStatusType xactStatus
Definition: libpq-int.h:390

◆ connectDBComplete()

static int connectDBComplete ( PGconn conn)
static

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

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

◆ connectDBStart()

static int connectDBStart ( PGconn conn)
static

Definition at line 2022 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(), pg_conn::status, pg_conn::try_next_addr, pg_conn::try_next_host, and pg_conn::whichhost.

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

2023 {
2024  if (!conn)
2025  return 0;
2026 
2027  if (!conn->options_valid)
2028  goto connect_errReturn;
2029 
2030  /*
2031  * Check for bad linking to backend-internal versions of src/common
2032  * functions (see comments in link-canary.c for the reason we need this).
2033  * Nobody but developers should see this message, so we don't bother
2034  * translating it.
2035  */
2037  {
2039  "libpq is incorrectly linked to backend functions\n");
2040  goto connect_errReturn;
2041  }
2042 
2043  /* Ensure our buffers are empty */
2044  conn->inStart = conn->inCursor = conn->inEnd = 0;
2045  conn->outCount = 0;
2046 
2047  /*
2048  * Set up to try to connect to the first host. (Setting whichhost = -1 is
2049  * a bit of a cheat, but PQconnectPoll will advance it to 0 before
2050  * anything else looks at it.)
2051  */
2052  conn->whichhost = -1;
2053  conn->try_next_addr = false;
2054  conn->try_next_host = true;
2055  conn->status = CONNECTION_NEEDED;
2056 
2057  /*
2058  * The code for processing CONNECTION_NEEDED state is in PQconnectPoll(),
2059  * so that it can easily be re-executed if needed again during the
2060  * asynchronous startup process. However, we must run it once here,
2061  * because callers expect a success return from this routine to mean that
2062  * we are in PGRES_POLLING_WRITING connection state.
2063  */
2064  if (PQconnectPoll(conn) == PGRES_POLLING_WRITING)
2065  return 1;
2066 
2067 connect_errReturn:
2068 
2069  /*
2070  * If we managed to open a socket, close it immediately rather than
2071  * waiting till PQfinish. (The application cannot have gotten the socket
2072  * from PQsocket yet, so this doesn't risk breaking anything.)
2073  */
2074  pqDropConnection(conn, true);
2075  conn->status = CONNECTION_BAD;
2076  return 0;
2077 }
int inEnd
Definition: libpq-int.h:448
int inStart
Definition: libpq-int.h:446
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
int outCount
Definition: libpq-int.h:453
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:459
bool try_next_host
Definition: libpq-int.h:425
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
Definition: fe-connect.c:2224
PQExpBufferData errorMessage
Definition: libpq-int.h:530
bool try_next_addr
Definition: libpq-int.h:424
bool options_valid
Definition: libpq-int.h:394
ConnStatusType status
Definition: libpq-int.h:388
int inCursor
Definition: libpq-int.h:447
int whichhost
Definition: libpq-int.h:405

◆ connectFailureMessage()

static void connectFailureMessage ( PGconn conn,
int  errorno 
)
static

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

1740 {
1741  char sebuf[PG_STRERROR_R_BUFLEN];
1742 
1744  "%s\n",
1745  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
1746 
1747 #ifdef HAVE_UNIX_SOCKETS
1748  if (IS_AF_UNIX(conn->raddr.addr.ss_family))
1750  libpq_gettext("\tIs the server running locally and accepting connections on that socket?\n"));
1751  else
1752 #endif
1754  libpq_gettext("\tIs the server running on that host and accepting TCP/IP connections?\n"));
1755 }
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
#define PG_STRERROR_R_BUFLEN
Definition: port.h:233
struct sockaddr_storage addr
Definition: pqcomm.h:64
#define SOCK_STRERROR
Definition: libpq-int.h:823
#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:413
PQExpBufferData errorMessage
Definition: libpq-int.h:530
#define libpq_gettext(x)
Definition: libpq-int.h:809

◆ connectNoDelay()

static int connectNoDelay ( PGconn conn)
static

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

1619 {
1620 #ifdef TCP_NODELAY
1621  int on = 1;
1622 
1623  if (setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY,
1624  (char *) &on,
1625  sizeof(on)) < 0)
1626  {
1627  char sebuf[PG_STRERROR_R_BUFLEN];
1628 
1630  libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
1631  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
1632  return 0;
1633  }
1634 #endif
1635 
1636  return 1;
1637 }
#define PG_STRERROR_R_BUFLEN
Definition: port.h:233
#define SOCK_STRERROR
Definition: libpq-int.h:823
#define SOCK_ERRNO
Definition: libpq-int.h:822
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
pgsocket sock
Definition: libpq-int.h:410
PQExpBufferData errorMessage
Definition: libpq-int.h:530
#define libpq_gettext(x)
Definition: libpq-int.h:809

◆ connectOptions1()

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

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

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

◆ connectOptions2()

static bool connectOptions2 ( PGconn conn)
static

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

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

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

◆ conninfo_add_defaults()

static bool conninfo_add_defaults ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

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

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

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

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

◆ conninfo_find()

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

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

References _PQconninfoOption::keyword.

Referenced by conninfo_getval(), and conninfo_storeval().

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

◆ conninfo_getval()

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

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

References conninfo_find(), and _PQconninfoOption::val.

Referenced by fillPGconn(), and parseServiceInfo().

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

◆ conninfo_init()

static PQconninfoOption * conninfo_init ( PQExpBuffer  errorMessage)
static

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

5245 {
5247  PQconninfoOption *opt_dest;
5248  const internalPQconninfoOption *cur_opt;
5249 
5250  /*
5251  * Get enough memory for all options in PQconninfoOptions, even if some
5252  * end up being filtered out.
5253  */
5254  options = (PQconninfoOption *) malloc(sizeof(PQconninfoOption) * sizeof(PQconninfoOptions) / sizeof(PQconninfoOptions[0]));
5255  if (options == NULL)
5256  {
5257  appendPQExpBufferStr(errorMessage,
5258  libpq_gettext("out of memory\n"));
5259  return NULL;
5260  }
5261  opt_dest = options;
5262 
5263  for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++)
5264  {
5265  /* Only copy the public part of the struct, not the full internal */
5266  memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption));
5267  opt_dest++;
5268  }
5269  MemSet(opt_dest, 0, sizeof(PQconninfoOption));
5270 
5271  return options;
5272 }
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
#define MemSet(start, val, len)
Definition: c.h:996
#define malloc(a)
Definition: header.h:50
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:194
static char ** options
#define libpq_gettext(x)
Definition: libpq-int.h:809

◆ conninfo_parse()

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

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

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

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

6334 {
6336  char *value_copy;
6337 
6338  /*
6339  * For backwards compatibility, requiressl=1 gets translated to
6340  * sslmode=require, and requiressl=0 gets translated to sslmode=prefer
6341  * (which is the default for sslmode).
6342  */
6343  if (strcmp(keyword, "requiressl") == 0)
6344  {
6345  keyword = "sslmode";
6346  if (value[0] == '1')
6347  value = "require";
6348  else
6349  value = "prefer";
6350  }
6351 
6352  option = conninfo_find(connOptions, keyword);
6353  if (option == NULL)
6354  {
6355  if (!ignoreMissing)
6356  appendPQExpBuffer(errorMessage,
6357  libpq_gettext("invalid connection option \"%s\"\n"),
6358  keyword);
6359  return NULL;
6360  }
6361 
6362  if (uri_decode)
6363  {
6364  value_copy = conninfo_uri_decode(value, errorMessage);
6365  if (value_copy == NULL)
6366  /* conninfo_uri_decode already set an error message */
6367  return NULL;
6368  }
6369  else
6370  {
6371  value_copy = strdup(value);
6372  if (value_copy == NULL)
6373  {
6374  appendPQExpBufferStr(errorMessage, libpq_gettext("out of memory\n"));
6375  return NULL;
6376  }
6377  }
6378 
6379  if (option->val)
6380  free(option->val);
6381  option->val = value_copy;
6382 
6383  return option;
6384 }
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6395
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
static struct @144 value
static char * conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
Definition: fe-connect.c:6215
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:809

◆ conninfo_uri_decode()

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

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

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

◆ conninfo_uri_parse()

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

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

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

Referenced by parse_connection_string().

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

◆ conninfo_uri_parse_options()

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

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

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

◆ conninfo_uri_parse_params()

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

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

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

◆ count_comma_separated_elems()

static int count_comma_separated_elems ( const char *  input)
static

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

Referenced by connectOptions2().

957 {
958  int n;
959 
960  n = 1;
961  for (; *input != '\0'; input++)
962  {
963  if (*input == ',')
964  n++;
965  }
966 
967  return n;
968 }

◆ default_threadlock()

static void default_threadlock ( int  acquire)
static

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

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

Referenced by PQregisterThreadLock().

7161 {
7162 #ifdef ENABLE_THREAD_SAFETY
7163 #ifndef WIN32
7164  static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
7165 #else
7166  static pthread_mutex_t singlethread_lock = NULL;
7167  static long mutex_initlock = 0;
7168 
7169  if (singlethread_lock == NULL)
7170  {
7171  while (InterlockedExchange(&mutex_initlock, 1) == 1)
7172  /* loop, another thread own the lock */ ;
7173  if (singlethread_lock == NULL)
7174  {
7175  if (pthread_mutex_init(&singlethread_lock, NULL))
7176  PGTHREAD_ERROR("failed to initialize mutex");
7177  }
7178  InterlockedExchange(&mutex_initlock, 0);
7179  }
7180 #endif
7181  if (acquire)
7182  {
7183  if (pthread_mutex_lock(&singlethread_lock))
7184  PGTHREAD_ERROR("failed to lock mutex");
7185  }
7186  else
7187  {
7188  if (pthread_mutex_unlock(&singlethread_lock))
7189  PGTHREAD_ERROR("failed to unlock mutex");
7190  }
7191 #endif
7192 }
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 6839 of file fe-connect.c.

References fprintf.

Referenced by makeEmptyPGconn().

6840 {
6841  (void) arg; /* not used */
6842  /* Note: we expect the supplied string to end with a newline already. */
6843  fprintf(stderr, "%s", message);
6844 }
#define fprintf
Definition: port.h:219
void * arg

◆ defaultNoticeReceiver()

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

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

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

Referenced by makeEmptyPGconn().

6825 {
6826  (void) arg; /* not used */
6827  if (res->noticeHooks.noticeProc != NULL)
6829  PQresultErrorMessage(res));
6830 }
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:2667
void * arg

◆ emitCouldNotConnect()

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

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

1682 {
1683 #ifdef HAVE_UNIX_SOCKETS
1684  if (IS_AF_UNIX(conn->raddr.addr.ss_family))
1685  {
1686  char service[NI_MAXHOST];
1687 
1688  pg_getnameinfo_all(&conn->raddr.addr, conn->raddr.salen,
1689  NULL, 0,
1690  service, sizeof(service),
1691  NI_NUMERICSERV);
1693  libpq_gettext("could not connect to socket \"%s\": "),
1694  service);
1695  }
1696  else
1697 #endif /* HAVE_UNIX_SOCKETS */
1698  {
1699  const char *displayed_host;
1700  const char *displayed_port;
1701 
1702  /* To which host and port were we actually connecting? */
1703  if (conn->connhost[conn->whichhost].type == CHT_HOST_ADDRESS)
1704  displayed_host = conn->connhost[conn->whichhost].hostaddr;
1705  else
1706  displayed_host = conn->connhost[conn->whichhost].host;
1707  displayed_port = conn->connhost[conn->whichhost].port;
1708  if (displayed_port == NULL || displayed_port[0] == '\0')
1709  displayed_port = DEF_PGPORT_STR;
1710 
1711  /*
1712  * If the user did not supply an IP address using 'hostaddr', and
1713  * 'host' was missing or does not match our lookup, display the
1714  * looked-up IP address.
1715  */
1716  if (conn->connhost[conn->whichhost].type != CHT_HOST_ADDRESS &&
1717  host_addr[0] &&
1718  strcmp(displayed_host, host_addr) != 0)
1720  libpq_gettext("could not connect to host \"%s\" (%s), port %s: "),
1721  displayed_host, host_addr,
1722  displayed_port);
1723  else
1725  libpq_gettext("could not connect to host \"%s\", port %s: "),
1726  displayed_host,
1727  displayed_port);
1728  }
1729 }
char * host
Definition: libpq-int.h:312
struct sockaddr_storage addr
Definition: pqcomm.h:64
pg_conn_host_type type
Definition: libpq-int.h:311
#define NI_MAXHOST
Definition: getaddrinfo.h:88
#define IS_AF_UNIX(fam)
Definition: ip.h:24
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
char * hostaddr
Definition: libpq-int.h:313
pg_conn_host * connhost
Definition: libpq-int.h:406
ACCEPT_TYPE_ARG3 salen
Definition: pqcomm.h:65
SockAddr raddr
Definition: libpq-int.h:413
PQExpBufferData errorMessage
Definition: libpq-int.h:530
#define NI_NUMERICSERV
Definition: getaddrinfo.h:81
int pg_getnameinfo_all(const struct sockaddr_storage *addr, int salen, char *node, int nodelen, char *service, int servicelen, int flags)
Definition: ip.c:122
char * port
Definition: libpq-int.h:314
int whichhost
Definition: libpq-int.h:405
#define libpq_gettext(x)
Definition: libpq-int.h:809

◆ fillPGconn()

static bool fillPGconn ( PGconn conn,
PQconninfoOption connOptions 
)
static

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

878 {
880 
881  for (option = PQconninfoOptions; option->keyword; option++)
882  {
883  if (option->connofs >= 0)
884  {
885  const char *tmp = conninfo_getval(connOptions, option->keyword);
886 
887  if (tmp)
888  {
889  char **connmember = (char **) ((char *) conn + option->connofs);
890 
891  if (*connmember)
892  free(*connmember);
893  *connmember = strdup(tmp);
894  if (*connmember == NULL)
895  {
897  libpq_gettext("out of memory\n"));
898  return false;
899  }
900  }
901  }
902  }
903 
904  return true;
905 }
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:194
PQExpBufferData errorMessage
Definition: libpq-int.h:530
#define free(a)
Definition: header.h:65
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6304
#define libpq_gettext(x)
Definition: libpq-int.h:809

◆ freePGconn()

static void freePGconn ( PGconn conn)
static

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

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

Referenced by makeEmptyPGconn(), and PQfinish().

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

◆ get_hexdigit()

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

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

Referenced by conninfo_uri_decode().

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

◆ getHostaddr()

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

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

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

Referenced by PQconnectPoll().

1646 {
1647  struct sockaddr_storage *addr = &conn->raddr.addr;
1648 
1649  if (addr->ss_family == AF_INET)
1650  {
1651  if (pg_inet_net_ntop(AF_INET,
1652  &((struct sockaddr_in *) addr)->sin_addr.s_addr,
1653  32,
1654  host_addr, host_addr_len) == NULL)
1655  host_addr[0] = '\0';
1656  }
1657 #ifdef HAVE_IPV6
1658  else if (addr->ss_family == AF_INET6)
1659  {
1660  if (pg_inet_net_ntop(AF_INET6,
1661  &((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr,
1662  128,
1663  host_addr, host_addr_len) == NULL)
1664  host_addr[0] = '\0';
1665  }
1666 #endif
1667  else
1668  host_addr[0] = '\0';
1669 }
struct sockaddr_storage addr
Definition: pqcomm.h:64
char * pg_inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size)
Definition: inet_net_ntop.c:77
SockAddr raddr
Definition: libpq-int.h:413

◆ internal_cancel()

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

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

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

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

◆ makeEmptyPGconn()

static PGconn * makeEmptyPGconn ( void  )
static

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

References pg_conn::asyncStatus, pg_conn::client_encoding, conn, CONNECTION_BAD, defaultNoticeProcessor(), defaultNoticeReceiver(), pg_conn::errorMessage, freePGconn(), pg_conn::inBuffer, pg_conn::inBufSize, initPQExpBuffer(), malloc, MemSet, pg_conn::nonblocking, pg_conn::noticeHooks, PGNoticeHooks::noticeProc, PGNoticeHooks::noticeRec, pg_conn::options_valid, pg_conn::outBuffer, pg_conn::outBufSize, PG_SQL_ASCII, PGASYNC_IDLE, PGINVALID_SOCKET, PQERRORS_DEFAULT, PQExpBufferBroken, PQSHOW_CONTEXT_ERRORS, PQTRANS_IDLE, pg_conn::rowBuf, pg_conn::rowBufLen, pg_conn::setenv_state, SETENV_STATE_IDLE, pg_conn::show_context, pg_conn::sock, pg_conn::status, pg_conn::std_strings, pg_conn::verbosity, pg_conn::workBuffer, and pg_conn::xactStatus.

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

3811 {
3812  PGconn *conn;
3813 
3814 #ifdef WIN32
3815 
3816  /*
3817  * Make sure socket support is up and running in this process.
3818  *
3819  * Note: the Windows documentation says that we should eventually do a
3820  * matching WSACleanup() call, but experience suggests that that is at
3821  * least as likely to cause problems as fix them. So we don't.
3822  */
3823  static bool wsastartup_done = false;
3824 
3825  if (!wsastartup_done)
3826  {
3827  WSADATA wsaData;
3828 
3829  if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
3830  return NULL;
3831  wsastartup_done = true;
3832  }
3833 
3834  /* Forget any earlier error */
3835  WSASetLastError(0);
3836 #endif /* WIN32 */
3837 
3838  conn = (PGconn *) malloc(sizeof(PGconn));
3839  if (conn == NULL)
3840  return conn;
3841 
3842  /* Zero all pointers and booleans */
3843  MemSet(conn, 0, sizeof(PGconn));
3844 
3845  /* install default notice hooks */
3848 
3849  conn->status = CONNECTION_BAD;
3850  conn->asyncStatus = PGASYNC_IDLE;
3851  conn->xactStatus = PQTRANS_IDLE;
3852  conn->options_valid = false;
3853  conn->nonblocking = false;
3855  conn->client_encoding = PG_SQL_ASCII;
3856  conn->std_strings = false; /* unless server says differently */
3857  conn->verbosity = PQERRORS_DEFAULT;
3859  conn->sock = PGINVALID_SOCKET;
3860 
3861  /*
3862  * We try to send at least 8K at a time, which is the usual size of pipe
3863  * buffers on Unix systems. That way, when we are sending a large amount
3864  * of data, we avoid incurring extra kernel context swaps for partial
3865  * bufferloads. The output buffer is initially made 16K in size, and we
3866  * try to dump it after accumulating 8K.
3867  *
3868  * With the same goal of minimizing context swaps, the input buffer will
3869  * be enlarged anytime it has less than 8K free, so we initially allocate
3870  * twice that.
3871  */
3872  conn->inBufSize = 16 * 1024;
3873  conn->inBuffer = (char *) malloc(conn->inBufSize);
3874  conn->outBufSize = 16 * 1024;
3875  conn->outBuffer = (char *) malloc(conn->outBufSize);
3876  conn->rowBufLen = 32;
3877  conn->rowBuf = (PGdataValue *) malloc(conn->rowBufLen * sizeof(PGdataValue));
3878  initPQExpBuffer(&conn->errorMessage);
3879  initPQExpBuffer(&conn->workBuffer);
3880 
3881  if (conn->inBuffer == NULL ||
3882  conn->outBuffer == NULL ||
3883  conn->rowBuf == NULL ||
3884  PQExpBufferBroken(&conn->errorMessage) ||
3885  PQExpBufferBroken(&conn->workBuffer))
3886  {
3887  /* out of memory already :-( */
3888  freePGconn(conn);
3889  conn = NULL;
3890  }
3891 
3892  return conn;
3893 }
PGContextVisibility show_context
Definition: libpq-int.h:440
int rowBufLen
Definition: libpq-int.h:462
PQExpBufferData workBuffer
Definition: libpq-int.h:533
#define MemSet(start, val, len)
Definition: c.h:996
#define malloc(a)
Definition: header.h:50
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:389
PGSetenvStatusType setenv_state
Definition: libpq-int.h:429
PGconn * conn
Definition: streamutil.c:54
int inBufSize
Definition: libpq-int.h:445
PGNoticeHooks noticeHooks
Definition: libpq-int.h:380
PGVerbosity verbosity
Definition: libpq-int.h:439
PQnoticeReceiver noticeRec
Definition: libpq-int.h:152
PGdataValue * rowBuf
Definition: libpq-int.h:461
pgsocket sock
Definition: libpq-int.h:410
#define PGINVALID_SOCKET
Definition: port.h:33
char * inBuffer
Definition: libpq-int.h:444
PQnoticeProcessor noticeProc
Definition: libpq-int.h:154
static void freePGconn(PGconn *conn)
Definition: fe-connect.c:3905
PQExpBufferData errorMessage
Definition: libpq-int.h:530
bool std_strings
Definition: libpq-int.h:438
bool options_valid
Definition: libpq-int.h:394
int outBufSize
Definition: libpq-int.h:452
#define PQExpBufferBroken(str)
Definition: pqexpbuffer.h:59
ConnStatusType status
Definition: libpq-int.h:388
char * outBuffer
Definition: libpq-int.h:451
bool nonblocking
Definition: libpq-int.h:395
static void defaultNoticeProcessor(void *arg, const char *message)
Definition: fe-connect.c:6839
int client_encoding
Definition: libpq-int.h:437
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
static void defaultNoticeReceiver(void *arg, const PGresult *res)
Definition: fe-connect.c:6824
PGTransactionStatusType xactStatus
Definition: libpq-int.h:390

◆ parse_comma_separated_list()

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

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

References malloc, and startptr.

Referenced by connectOptions2().

981 {
982  char *p;
983  char *s = *startptr;
984  char *e;
985  int len;
986 
987  /*
988  * Search for the end of the current element; a comma or end-of-string
989  * acts as a terminator.
990  */
991  e = s;
992  while (*e != '\0' && *e != ',')
993  ++e;
994  *more = (*e == ',');
995 
996  len = e - s;
997  p = (char *) malloc(sizeof(char) * (len + 1));
998  if (p)
999  {
1000  memcpy(p, s, len);
1001  p[len] = '\0';
1002  }
1003  *startptr = e + 1;
1004 
1005  return p;
1006 }
#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 5284 of file fe-connect.c.

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

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

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

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

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

1784 {
1785  char *end;
1786  long numval;
1787 
1788  Assert(value != NULL);
1789 
1790  *result = 0;
1791 
1792  /* strtol(3) skips leading whitespaces */
1793  errno = 0;
1794  numval = strtol(value, &end, 10);
1795 
1796  /*
1797  * If no progress was done during the parsing or an error happened, fail.
1798  * This tests properly for overflows of the result.
1799  */
1800  if (value == end || errno != 0 || numval != (int) numval)
1801  goto error;
1802 
1803  /*
1804  * Skip any trailing whitespace; if anything but whitespace remains before
1805  * the terminating character, fail
1806  */
1807  while (*end != '\0' && isspace((unsigned char) *end))
1808  end++;
1809 
1810  if (*end != '\0')
1811  goto error;
1812 
1813  *result = numval;
1814  return true;
1815 
1816 error:
1818  libpq_gettext("invalid integer value \"%s\" for connection option \"%s\"\n"),
1819  value, context);
1820  return false;
1821 }
static void error(void)
Definition: sql-dyntest.c:147
static struct @144 value
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
PQExpBufferData errorMessage
Definition: libpq-int.h:530
#define Assert(condition)
Definition: c.h:792
#define libpq_gettext(x)
Definition: libpq-int.h:809

◆ parseServiceFile()

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

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

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

◆ parseServiceInfo()

static int parseServiceInfo ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

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

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

Referenced by conninfo_add_defaults().

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

6890 {
6891  FILE *fp;
6892  struct stat stat_buf;
6894 
6895  if (dbname == NULL || dbname[0] == '\0')
6896  return NULL;
6897 
6898  if (username == NULL || username[0] == '\0')
6899  return NULL;
6900 
6901  /* 'localhost' matches pghost of '' or the default socket directory */
6902  if (hostname == NULL || hostname[0] == '\0')
6904  else if (is_unixsock_path(hostname))
6905 
6906  /*
6907  * We should probably use canonicalize_path(), but then we have to
6908  * bring path.c into libpq, and it doesn't seem worth it.
6909  */
6910  if (strcmp(hostname, DEFAULT_PGSOCKET_DIR) == 0)
6912 
6913  if (port == NULL || port[0] == '\0')
6914  port = DEF_PGPORT_STR;
6915 
6916  /* If password file cannot be opened, ignore it. */
6917  if (stat(pgpassfile, &stat_buf) != 0)
6918  return NULL;
6919 
6920 #ifndef WIN32
6921  if (!S_ISREG(stat_buf.st_mode))
6922  {
6923  fprintf(stderr,
6924  libpq_gettext("WARNING: password file \"%s\" is not a plain file\n"),
6925  pgpassfile);
6926  return NULL;
6927  }
6928 
6929  /* If password file is insecure, alert the user and ignore it. */
6930  if (stat_buf.st_mode & (S_IRWXG | S_IRWXO))
6931  {
6932  fprintf(stderr,
6933  libpq_gettext("WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
6934  pgpassfile);
6935  return NULL;
6936  }
6937 #else
6938 
6939  /*
6940  * On Win32, the directory is protected, so we don't have to check the
6941  * file.
6942  */
6943 #endif
6944 
6945  fp = fopen(pgpassfile, "r");
6946  if (fp == NULL)
6947  return NULL;
6948 
6949  /* Use an expansible buffer to accommodate any reasonable line length */
6950  initPQExpBuffer(&buf);
6951 
6952  while (!feof(fp) && !ferror(fp))
6953  {
6954  /* Make sure there's a reasonable amount of room in the buffer */
6955  if (!enlargePQExpBuffer(&buf, 128))
6956  break;
6957 
6958  /* Read some data, appending it to what we already have */
6959  if (fgets(buf.data + buf.len, buf.maxlen - buf.len, fp) == NULL)
6960  break;
6961  buf.len += strlen(buf.data + buf.len);
6962 
6963  /* If we don't yet have a whole line, loop around to read more */
6964  if (!(buf.len > 0 && buf.data[buf.len - 1] == '\n') && !feof(fp))
6965  continue;
6966 
6967  /* ignore comments */
6968  if (buf.data[0] != '#')
6969  {
6970  char *t = buf.data;
6971  int len;
6972 
6973  /* strip trailing newline and carriage return */
6974  len = pg_strip_crlf(t);
6975 
6976  if (len > 0 &&
6977  (t = pwdfMatchesString(t, hostname)) != NULL &&
6978  (t = pwdfMatchesString(t, port)) != NULL &&
6979  (t = pwdfMatchesString(t, dbname)) != NULL &&
6980  (t = pwdfMatchesString(t, username)) != NULL)
6981  {
6982  /* Found a match. */
6983  char *ret,
6984  *p1,
6985  *p2;
6986 
6987  ret = strdup(t);
6988 
6989  fclose(fp);
6990  explicit_bzero(buf.data, buf.maxlen);
6991  termPQExpBuffer(&buf);
6992 
6993  if (!ret)
6994  {
6995  /* Out of memory. XXX: an error message would be nice. */
6996  return NULL;
6997  }
6998 
6999  /* De-escape password. */
7000  for (p1 = p2 = ret; *p1 != ':' && *p1 != '\0'; ++p1, ++p2)
7001  {
7002  if (*p1 == '\\' && p1[1] != '\0')
7003  ++p1;
7004  *p2 = *p1;
7005  }
7006  *p2 = '\0';
7007 
7008  return ret;
7009  }
7010  }
7011 
7012  /* No match, reset buffer to prepare for next line. */
7013  buf.len = 0;
7014  }
7015 
7016  fclose(fp);
7017  explicit_bzero(buf.data, buf.maxlen);
7018  termPQExpBuffer(&buf);
7019  return NULL;
7020 }
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:219
struct stat stat_buf
Definition: pg_standby.c:100
static char * buf
Definition: pg_test_fsync.c:68
#define S_IRWXG
Definition: win32_port.h:301
static int port
Definition: pg_regress.c:92
#define S_ISREG(m)
Definition: win32_port.h:319
unsigned short st_mode
Definition: win32_port.h:260
static char * username
Definition: initdb.c:134
char * dbname
Definition: streamutil.c:51
#define DefaultHost
Definition: fe-connect.c:122
static char * pwdfMatchesString(char *buf, const char *token)
Definition: fe-connect.c:6851
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:809
#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 7028 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().

7029 {
7030  /* If it was 'invalid authorization', add pgpassfile mention */
7031  /* only works with >= 9.0 servers */
7032  if (conn->password_needed &&
7033  conn->connhost[conn->whichhost].password != NULL &&
7034  conn->result)
7035  {
7036  const char *sqlstate = PQresultErrorField(conn->result,
7038 
7039  if (sqlstate && strcmp(sqlstate, ERRCODE_INVALID_PASSWORD) == 0)
7041  libpq_gettext("password retrieved from file \"%s\"\n"),
7042  conn->pgpassfile);
7043  }
7044 }
char * pgpassfile
Definition: libpq-int.h:349
bool password_needed
Definition: libpq-int.h:417
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
PGresult * result
Definition: libpq-int.h:465
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
pg_conn_host * connhost
Definition: libpq-int.h:406
PQExpBufferData errorMessage
Definition: libpq-int.h:530
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:2713
#define ERRCODE_INVALID_PASSWORD
Definition: fe-connect.c:95
int whichhost
Definition: libpq-int.h:405
#define libpq_gettext(x)
Definition: libpq-int.h:809
char * password
Definition: libpq-int.h:315

◆ PQbackendPID()

int PQbackendPID ( const PGconn conn)

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

6652 {
6653  if (!conn || conn->status != CONNECTION_OK)
6654  return 0;
6655  return conn->be_pid;
6656 }
ConnStatusType status
Definition: libpq-int.h:388
int be_pid
Definition: libpq-int.h:434

◆ PQcancel()

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

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

4397 {
4398  if (!cancel)
4399  {
4400  strlcpy(errbuf, "PQcancel() -- no cancel object supplied", errbufsize);
4401  return false;
4402  }
4403 
4404  return internal_cancel(&cancel->raddr, cancel->be_pid, cancel->be_key,
4405  errbuf, errbufsize);
4406 }
static int internal_cancel(SockAddr *raddr, int be_pid, int be_key, char *errbuf, int errbufsize)
Definition: fe-connect.c:4292
int be_pid
Definition: libpq-int.h:543
int be_key
Definition: libpq-int.h:544
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
SockAddr raddr
Definition: libpq-int.h:542

◆ PQclientEncoding()

int PQclientEncoding ( const PGconn conn)

◆ PQconndefaults()

PQconninfoOption* PQconndefaults ( void  )

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

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

◆ PQconnectdb()

PGconn* PQconnectdb ( const char *  conninfo)

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

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

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

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

◆ PQconnectdbParams()

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

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

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

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

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

◆ PQconnectionNeedsPassword()

int PQconnectionNeedsPassword ( const PGconn conn)

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

6660 {
6661  char *password;
6662 
6663  if (!conn)
6664  return false;
6665  password = PQpass(conn);
6666  if (conn->password_needed &&
6667  (password == NULL || password[0] == '\0'))
6668  return true;
6669  else
6670  return false;
6671 }
bool password_needed
Definition: libpq-int.h:417
char * PQpass(const PGconn *conn)
Definition: fe-connect.c:6491
static char * password
Definition: streamutil.c:53

◆ PQconnectionUsedPassword()

int PQconnectionUsedPassword ( const PGconn conn)

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

References pg_conn::password_needed.

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

6675 {
6676  if (!conn)
6677  return false;
6678  if (conn->password_needed)
6679  return true;
6680  else
6681  return false;
6682 }
bool password_needed
Definition: libpq-int.h:417

◆ PQconnectPoll()

PostgresPollingStatusType PQconnectPoll ( PGconn conn)

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

References SockAddr::addr, pg_conn::addr_cur, pg_conn::addrlist, pg_conn::addrlist_family, addrinfo::ai_addr, addrinfo::ai_addrlen, addrinfo::ai_family, addrinfo::ai_flags, addrinfo::ai_next, AI_NUMERICHOST, addrinfo::ai_socktype, appendPQExpBuffer(), appendPQExpBufferChar(), appendPQExpBufferStr(), pg_conn::appname, Assert, pg_conn::asyncStatus, AUTH_REQ_MD5, AUTH_REQ_OK, pg_conn::auth_req_received, CHT_HOST_ADDRESS, CHT_HOST_NAME, CHT_UNIX_SOCKET, connect, connectFailureMessage(), CONNECTION_AUTH_OK, CONNECTION_AWAITING_RESPONSE, CONNECTION_BAD, CONNECTION_CHECK_TARGET, CONNECTION_CHECK_WRITABLE, CONNECTION_CONSUME, CONNECTION_GSS_STARTUP, CONNECTION_MADE, CONNECTION_NEEDED, CONNECTION_OK, CONNECTION_SETENV, CONNECTION_SSL_STARTUP, CONNECTION_STARTED, connectNoDelay(), pg_conn::connhost, pg_conn::connip, PQExpBufferData::data, EINPROGRESS, EINTR, emitCouldNotConnect(), EnvironmentOptions, 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::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, pg_conn::next_eo, NI_MAXHOST, parse_int_param(), PG_DIAG_SQLSTATE, pg_fe_sendauth(), pg_getaddrinfo_all(), pg_GSS_have_cred_cache(), pg_hton32, PG_PROTOCOL, PG_PROTOCOL_MAJOR, pg_set_noblock(), PG_STRERROR_R_BUFLEN, PGASYNC_BUSY, PGASYNC_IDLE, PGINVALID_SOCKET, pgpassfileWarning(), PGRES_FATAL_ERROR, PGRES_POLLING_FAILED, PGRES_POLLING_OK, PGRES_POLLING_READING, PGRES_POLLING_WRITING, PGRES_TUPLES_OK, pg_conn_host::port, pqBuildStartupPacket2(), pqBuildStartupPacket3(), pqCheckInBufferSpace(), PQclear(), pqClearAsyncResult(), PQconsumeInput(), pqDropConnection(), pqDropServerData(), pqFlush(), pqGetc(), pqGetErrorNotice3(), pqGetInt(), pqGetpwuid(), PQgetResult(), pqGets_append(), PQgetvalue(), PQisBusy(), PQntuples(), pqPacketSend(), pqReadData(), PQresultErrorField(), PQresultStatus(), pqsecure_initialize(), pqsecure_open_client(), pqsecure_open_gss(), PQsendQueryContinue(), pqSetenvPoll(), PQTRANS_IDLE, pg_conn::pversion, pg_conn::raddr, release_conn_addrinfo(), pg_conn::requirepeer, pg_result::resultStatus, SockAddr::salen, pg_conn::send_appname, sendTerminateConn(), pg_conn::setenv_state, SETENV_STATE_CLIENT_ENCODING_SEND, setKeepalivesCount(), setKeepalivesIdle(), setKeepalivesInterval(), setTCPUserTimeout(), pg_conn::sigpipe_flag, pg_conn::sigpipe_so, snprintf, pg_conn::sock, SOCK_ERRNO, SOCK_STRERROR, socket, pg_conn::ssl_in_use, pg_conn::sslmode, pg_conn::status, STATUS_OK, strerror_r, pg_conn::sversion, pg_conn::target_session_attrs, 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().

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