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 <netdb.h>
#include <time.h>
#include <unistd.h>
#include "common/ip.h"
#include "common/link-canary.h"
#include "common/scram-common.h"
#include "common/string.h"
#include "fe-auth.h"
#include "libpq-fe.h"
#include "libpq-int.h"
#include "mb/pg_wchar.h"
#include "pg_config_paths.h"
#include "port/pg_bswap.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
Include dependency graph for fe-connect.c:

Go to the source code of this file.

Data Structures

struct  _internalPQconninfoOption
 

Macros

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

Typedefs

typedef struct _internalPQconninfoOption internalPQconninfoOption
 

Functions

static bool connectOptions1 (PGconn *conn, const char *conninfo)
 
static bool connectOptions2 (PGconn *conn)
 
static int connectDBStart (PGconn *conn)
 
static int connectDBComplete (PGconn *conn)
 
static PGPing internal_ping (PGconn *conn)
 
static PGconnmakeEmptyPGconn (void)
 
static void pqFreeCommandQueue (PGcmdQueueEntry *queue)
 
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 *connstr, 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 emitHostIdentityInfo (PGconn *conn, const char *host_addr)
 
static void connectFailureMessage (PGconn *conn, int errorno)
 
static int useKeepalives (PGconn *conn)
 
static bool parse_int_param (const char *value, int *result, PGconn *conn, const char *context)
 
static int setKeepalivesIdle (PGconn *conn)
 
static int setKeepalivesInterval (PGconn *conn)
 
static int setKeepalivesCount (PGconn *conn)
 
static int setTCPUserTimeout (PGconn *conn)
 
PostgresPollingStatusType PQconnectPoll (PGconn *conn)
 
void PQfinish (PGconn *conn)
 
void PQreset (PGconn *conn)
 
int PQresetStart (PGconn *conn)
 
PostgresPollingStatusType PQresetPoll (PGconn *conn)
 
PGcancelPQgetCancel (PGconn *conn)
 
void PQfreeCancel (PGcancel *cancel)
 
static bool optional_setsockopt (int fd, int protoid, int optid, int value)
 
int PQcancel (PGcancel *cancel, char *errbuf, int errbufsize)
 
int PQrequestCancel (PGconn *conn)
 
int pqPacketSend (PGconn *conn, char pack_type, const void *buf, size_t buf_len)
 
PQconninfoOptionPQconninfoParse (const char *conninfo, char **errmsg)
 
PQconninfoOptionPQconninfo (PGconn *conn)
 
void PQconninfoFree (PQconninfoOption *connOptions)
 
char * PQdb (const PGconn *conn)
 
char * PQuser (const PGconn *conn)
 
char * PQpass (const PGconn *conn)
 
char * PQhost (const PGconn *conn)
 
char * PQhostaddr (const PGconn *conn)
 
char * PQport (const PGconn *conn)
 
char * PQtty (const PGconn *conn)
 
char * PQoptions (const PGconn *conn)
 
ConnStatusType PQstatus (const PGconn *conn)
 
PGTransactionStatusType PQtransactionStatus (const PGconn *conn)
 
const char * PQparameterStatus (const PGconn *conn, const char *paramName)
 
int PQprotocolVersion (const PGconn *conn)
 
int PQserverVersion (const PGconn *conn)
 
char * PQerrorMessage (const PGconn *conn)
 
int PQsocket (const PGconn *conn)
 
int PQbackendPID (const PGconn *conn)
 
PGpipelineStatus PQpipelineStatus (const PGconn *conn)
 
int PQconnectionNeedsPassword (const PGconn *conn)
 
int PQconnectionUsedPassword (const PGconn *conn)
 
int PQclientEncoding (const PGconn *conn)
 
int PQsetClientEncoding (PGconn *conn, const char *encoding)
 
PGVerbosity PQsetErrorVerbosity (PGconn *conn, PGVerbosity verbosity)
 
PGContextVisibility PQsetErrorContextVisibility (PGconn *conn, PGContextVisibility show_context)
 
PQnoticeReceiver PQsetNoticeReceiver (PGconn *conn, PQnoticeReceiver proc, void *arg)
 
PQnoticeProcessor PQsetNoticeProcessor (PGconn *conn, PQnoticeProcessor proc, void *arg)
 
bool pqGetHomeDirectory (char *buf, int bufsize)
 
pgthreadlock_t PQregisterThreadLock (pgthreadlock_t newhandler)
 

Variables

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

Macro Definition Documentation

◆ DefaultChannelBinding

#define DefaultChannelBinding   "disable"

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

◆ DefaultGSSMode

#define DefaultGSSMode   "disable"

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

◆ DefaultHost

#define DefaultHost   "localhost"

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

◆ DefaultOption

#define DefaultOption   ""

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

◆ DefaultSSLMode

#define DefaultSSLMode   "disable"

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

◆ DefaultTargetSessionAttrs

#define DefaultTargetSessionAttrs   "any"

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

◆ ERRCODE_APPNAME_UNKNOWN

#define ERRCODE_APPNAME_UNKNOWN   "42704"

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

◆ ERRCODE_CANNOT_CONNECT_NOW

#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"

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

◆ ERRCODE_INVALID_PASSWORD

#define ERRCODE_INVALID_PASSWORD   "28P01"

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

◆ PGPASSFILE

#define PGPASSFILE   ".pgpass"

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

Typedef Documentation

◆ internalPQconninfoOption

Function Documentation

◆ closePGconn()

static void closePGconn ( PGconn conn)
static

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

4092 {
4093  /*
4094  * If possible, send Terminate message to close the connection politely.
4095  */
4097 
4098  /*
4099  * Must reset the blocking status so a possible reconnect will work.
4100  *
4101  * Don't call PQsetnonblocking() because it will fail if it's unable to
4102  * flush the connection.
4103  */
4104  conn->nonblocking = false;
4105 
4106  /*
4107  * Close the connection, reset all transient state, flush I/O buffers.
4108  * Note that this includes clearing conn's error state; we're no longer
4109  * interested in any failures associated with the old connection, and we
4110  * want a clean slate for any new connection attempt.
4111  */
4112  pqDropConnection(conn, true);
4113  conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
4117  pqClearAsyncResult(conn); /* deallocate result */
4120 
4121  /* Reset all state obtained from server, too */
4123 }
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:446
static void sendTerminateConn(PGconn *conn)
Definition: fe-connect.c:4064
static void release_conn_addrinfo(PGconn *conn)
Definition: fe-connect.c:4049
static void pqDropServerData(PGconn *conn)
Definition: fe-connect.c:559
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:776
@ CONNECTION_BAD
Definition: libpq-fe.h:61
@ PQTRANS_IDLE
Definition: libpq-fe.h:118
@ PQ_PIPELINE_OFF
Definition: libpq-fe.h:158
@ PGASYNC_IDLE
Definition: libpq-int.h:220
#define pqClearConnErrorState(conn)
Definition: libpq-int.h:855
PGconn * conn
Definition: streamutil.c:54
PGTransactionStatusType xactStatus
Definition: libpq-int.h:415
bool nonblocking
Definition: libpq-int.h:418
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:414
PGpipelineStatus pipelineStatus
Definition: libpq-int.h:420
ConnStatusType status
Definition: libpq-int.h:413

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

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

◆ connectDBComplete()

static int connectDBComplete ( PGconn conn)
static

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

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

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

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

◆ connectDBStart()

static int connectDBStart ( PGconn conn)
static

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

2005 {
2006  if (!conn)
2007  return 0;
2008 
2009  if (!conn->options_valid)
2010  goto connect_errReturn;
2011 
2012  /*
2013  * Check for bad linking to backend-internal versions of src/common
2014  * functions (see comments in link-canary.c for the reason we need this).
2015  * Nobody but developers should see this message, so we don't bother
2016  * translating it.
2017  */
2019  {
2021  "libpq is incorrectly linked to backend functions\n");
2022  goto connect_errReturn;
2023  }
2024 
2025  /* Ensure our buffers are empty */
2026  conn->inStart = conn->inCursor = conn->inEnd = 0;
2027  conn->outCount = 0;
2028 
2029  /*
2030  * Set up to try to connect to the first host. (Setting whichhost = -1 is
2031  * a bit of a cheat, but PQconnectPoll will advance it to 0 before
2032  * anything else looks at it.)
2033  */
2034  conn->whichhost = -1;
2035  conn->try_next_addr = false;
2036  conn->try_next_host = true;
2038 
2039  /* Also reset the target_server_type state if needed */
2042 
2043  /*
2044  * The code for processing CONNECTION_NEEDED state is in PQconnectPoll(),
2045  * so that it can easily be re-executed if needed again during the
2046  * asynchronous startup process. However, we must run it once here,
2047  * because callers expect a success return from this routine to mean that
2048  * we are in PGRES_POLLING_WRITING connection state.
2049  */
2051  return 1;
2052 
2053 connect_errReturn:
2054 
2055  /*
2056  * If we managed to open a socket, close it immediately rather than
2057  * waiting till PQfinish. (The application cannot have gotten the socket
2058  * from PQsocket yet, so this doesn't risk breaking anything.)
2059  */
2060  pqDropConnection(conn, true);
2062  return 0;
2063 }
@ SERVER_TYPE_PREFER_STANDBY_PASS2
Definition: libpq-int.h:242
@ SERVER_TYPE_PREFER_STANDBY
Definition: libpq-int.h:241
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:367
bool try_next_host
Definition: libpq-int.h:463
int inCursor
Definition: libpq-int.h:485
int inEnd
Definition: libpq-int.h:486
int inStart
Definition: libpq-int.h:484
PQExpBufferData errorMessage
Definition: libpq-int.h:588
bool options_valid
Definition: libpq-int.h:417
PGTargetServerType target_server_type
Definition: libpq-int.h:461
int outCount
Definition: libpq-int.h:491

References appendPQExpBufferStr(), conn, CONNECTION_BAD, CONNECTION_NEEDED, pg_conn::errorMessage, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, pg_conn::options_valid, pg_conn::outCount, pg_link_canary_is_frontend(), PGRES_POLLING_WRITING, PQconnectPoll(), pqDropConnection(), SERVER_TYPE_PREFER_STANDBY, SERVER_TYPE_PREFER_STANDBY_PASS2, pg_conn::status, pg_conn::target_server_type, pg_conn::try_next_addr, pg_conn::try_next_host, and pg_conn::whichhost.

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

◆ connectFailureMessage()

static void connectFailureMessage ( PGconn conn,
int  errorno 
)
static

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

1716 {
1717  char sebuf[PG_STRERROR_R_BUFLEN];
1718 
1720  "%s\n",
1721  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
1722 
1723  if (conn->raddr.addr.ss_family == AF_UNIX)
1724  libpq_append_conn_error(conn, "\tIs the server running locally and accepting connections on that socket?");
1725  else
1726  libpq_append_conn_error(conn, "\tIs the server running on that host and accepting TCP/IP connections?");
1727 }
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition: fe-misc.c:1312
#define SOCK_STRERROR
Definition: libpq-int.h:904
#define PG_STRERROR_R_BUFLEN
Definition: port.h:256
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:265
struct sockaddr_storage addr
Definition: pqcomm.h:26
SockAddr raddr
Definition: libpq-int.h:450

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

Referenced by PQconnectPoll().

◆ connectNoDelay()

static int connectNoDelay ( PGconn conn)
static

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

1601 {
1602 #ifdef TCP_NODELAY
1603  int on = 1;
1604 
1605  if (setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY,
1606  (char *) &on,
1607  sizeof(on)) < 0)
1608  {
1609  char sebuf[PG_STRERROR_R_BUFLEN];
1610 
1611  libpq_append_conn_error(conn, "could not set socket to TCP no delay mode: %s",
1612  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
1613  return 0;
1614  }
1615 #endif
1616 
1617  return 1;
1618 }
#define SOCK_ERRNO
Definition: libpq-int.h:903
pgsocket sock
Definition: libpq-int.h:447

References conn, libpq_append_conn_error(), PG_STRERROR_R_BUFLEN, pg_conn::sock, SOCK_ERRNO, and SOCK_STRERROR.

Referenced by PQconnectPoll().

◆ connectOptions1()

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

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

922 {
923  PQconninfoOption *connOptions;
924 
925  /*
926  * Parse the conninfo string
927  */
928  connOptions = parse_connection_string(conninfo, &conn->errorMessage, true);
929  if (connOptions == NULL)
930  {
932  /* errorMessage is already set */
933  return false;
934  }
935 
936  /*
937  * Move option values into conn structure
938  */
939  if (!fillPGconn(conn, connOptions))
940  {
942  PQconninfoFree(connOptions);
943  return false;
944  }
945 
946  /*
947  * Free the option info - all is in conn now
948  */
949  PQconninfoFree(connOptions);
950 
951  return true;
952 }
static PQconninfoOption * parse_connection_string(const char *connstr, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5418
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6576
static bool fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
Definition: fe-connect.c:881

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

Referenced by PQconnectStart(), and PQsetdbLogin().

◆ connectOptions2()

static bool connectOptions2 ( PGconn conn)
static

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

1020 {
1021  int i;
1022 
1023  /*
1024  * Allocate memory for details about each host to which we might possibly
1025  * try to connect. For that, count the number of elements in the hostaddr
1026  * or host options. If neither is given, assume one host.
1027  */
1028  conn->whichhost = 0;
1029  if (conn->pghostaddr && conn->pghostaddr[0] != '\0')
1031  else if (conn->pghost && conn->pghost[0] != '\0')
1033  else
1034  conn->nconnhost = 1;
1035  conn->connhost = (pg_conn_host *)
1036  calloc(conn->nconnhost, sizeof(pg_conn_host));
1037  if (conn->connhost == NULL)
1038  goto oom_error;
1039 
1040  /*
1041  * We now have one pg_conn_host structure per possible host. Fill in the
1042  * host and hostaddr fields for each, by splitting the parameter strings.
1043  */
1044  if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0')
1045  {
1046  char *s = conn->pghostaddr;
1047  bool more = true;
1048 
1049  for (i = 0; i < conn->nconnhost && more; i++)
1050  {
1052  if (conn->connhost[i].hostaddr == NULL)
1053  goto oom_error;
1054  }
1055 
1056  /*
1057  * If hostaddr was given, the array was allocated according to the
1058  * number of elements in the hostaddr list, so it really should be the
1059  * right size.
1060  */
1061  Assert(!more);
1062  Assert(i == conn->nconnhost);
1063  }
1064 
1065  if (conn->pghost != NULL && conn->pghost[0] != '\0')
1066  {
1067  char *s = conn->pghost;
1068  bool more = true;
1069 
1070  for (i = 0; i < conn->nconnhost && more; i++)
1071  {
1073  if (conn->connhost[i].host == NULL)
1074  goto oom_error;
1075  }
1076 
1077  /* Check for wrong number of host items. */
1078  if (more || i != conn->nconnhost)
1079  {
1081  libpq_append_conn_error(conn, "could not match %d host names to %d hostaddr values",
1083  return false;
1084  }
1085  }
1086 
1087  /*
1088  * Now, for each host slot, identify the type of address spec, and fill in
1089  * the default address if nothing was given.
1090  */
1091  for (i = 0; i < conn->nconnhost; i++)
1092  {
1093  pg_conn_host *ch = &conn->connhost[i];
1094 
1095  if (ch->hostaddr != NULL && ch->hostaddr[0] != '\0')
1096  ch->type = CHT_HOST_ADDRESS;
1097  else if (ch->host != NULL && ch->host[0] != '\0')
1098  {
1099  ch->type = CHT_HOST_NAME;
1100  if (is_unixsock_path(ch->host))
1101  ch->type = CHT_UNIX_SOCKET;
1102  }
1103  else
1104  {
1105  free(ch->host);
1106 
1107  /*
1108  * This bit selects the default host location. If you change
1109  * this, see also pg_regress.
1110  */
1111  if (DEFAULT_PGSOCKET_DIR[0])
1112  {
1113  ch->host = strdup(DEFAULT_PGSOCKET_DIR);
1114  ch->type = CHT_UNIX_SOCKET;
1115  }
1116  else
1117  {
1118  ch->host = strdup(DefaultHost);
1119  ch->type = CHT_HOST_NAME;
1120  }
1121  if (ch->host == NULL)
1122  goto oom_error;
1123  }
1124  }
1125 
1126  /*
1127  * Next, work out the port number corresponding to each host name.
1128  *
1129  * Note: unlike the above for host names, this could leave the port fields
1130  * as null or empty strings. We will substitute DEF_PGPORT whenever we
1131  * read such a port field.
1132  */
1133  if (conn->pgport != NULL && conn->pgport[0] != '\0')
1134  {
1135  char *s = conn->pgport;
1136  bool more = true;
1137 
1138  for (i = 0; i < conn->nconnhost && more; i++)
1139  {
1141  if (conn->connhost[i].port == NULL)
1142  goto oom_error;
1143  }
1144 
1145  /*
1146  * If exactly one port was given, use it for every host. Otherwise,
1147  * there must be exactly as many ports as there were hosts.
1148  */
1149  if (i == 1 && !more)
1150  {
1151  for (i = 1; i < conn->nconnhost; i++)
1152  {
1153  conn->connhost[i].port = strdup(conn->connhost[0].port);
1154  if (conn->connhost[i].port == NULL)
1155  goto oom_error;
1156  }
1157  }
1158  else if (more || i != conn->nconnhost)
1159  {
1161  libpq_append_conn_error(conn, "could not match %d port numbers to %d hosts",
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  free(conn->pguser);
1176  if (!conn->pguser)
1177  {
1179  return false;
1180  }
1181  }
1182 
1183  /*
1184  * If database name was not given, default it to equal user name
1185  */
1186  if (conn->dbName == NULL || conn->dbName[0] == '\0')
1187  {
1188  free(conn->dbName);
1189  conn->dbName = strdup(conn->pguser);
1190  if (!conn->dbName)
1191  goto oom_error;
1192  }
1193 
1194  /*
1195  * If password was not given, try to look it up in password file. Note
1196  * that the result might be different for each host/port pair.
1197  */
1198  if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
1199  {
1200  /* If password file wasn't specified, use ~/PGPASSFILE */
1201  if (conn->pgpassfile == NULL || conn->pgpassfile[0] == '\0')
1202  {
1203  char homedir[MAXPGPATH];
1204 
1205  if (pqGetHomeDirectory(homedir, sizeof(homedir)))
1206  {
1207  free(conn->pgpassfile);
1209  if (!conn->pgpassfile)
1210  goto oom_error;
1211  snprintf(conn->pgpassfile, MAXPGPATH, "%s/%s",
1212  homedir, PGPASSFILE);
1213  }
1214  }
1215 
1216  if (conn->pgpassfile != NULL && conn->pgpassfile[0] != '\0')
1217  {
1218  for (i = 0; i < conn->nconnhost; i++)
1219  {
1220  /*
1221  * Try to get a password for this host from file. We use host
1222  * for the hostname search key if given, else hostaddr (at
1223  * least one of them is guaranteed nonempty by now).
1224  */
1225  const char *pwhost = conn->connhost[i].host;
1226 
1227  if (pwhost == NULL || pwhost[0] == '\0')
1228  pwhost = conn->connhost[i].hostaddr;
1229 
1230  conn->connhost[i].password =
1231  passwordFromFile(pwhost,
1232  conn->connhost[i].port,
1233  conn->dbName,
1234  conn->pguser,
1235  conn->pgpassfile);
1236  }
1237  }
1238  }
1239 
1240  /*
1241  * validate channel_binding option
1242  */
1243  if (conn->channel_binding)
1244  {
1245  if (strcmp(conn->channel_binding, "disable") != 0
1246  && strcmp(conn->channel_binding, "prefer") != 0
1247  && strcmp(conn->channel_binding, "require") != 0)
1248  {
1250  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1251  "channel_binding", conn->channel_binding);
1252  return false;
1253  }
1254  }
1255  else
1256  {
1258  if (!conn->channel_binding)
1259  goto oom_error;
1260  }
1261 
1262  /*
1263  * validate sslmode option
1264  */
1265  if (conn->sslmode)
1266  {
1267  if (strcmp(conn->sslmode, "disable") != 0
1268  && strcmp(conn->sslmode, "allow") != 0
1269  && strcmp(conn->sslmode, "prefer") != 0
1270  && strcmp(conn->sslmode, "require") != 0
1271  && strcmp(conn->sslmode, "verify-ca") != 0
1272  && strcmp(conn->sslmode, "verify-full") != 0)
1273  {
1275  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1276  "sslmode", conn->sslmode);
1277  return false;
1278  }
1279 
1280 #ifndef USE_SSL
1281  switch (conn->sslmode[0])
1282  {
1283  case 'a': /* "allow" */
1284  case 'p': /* "prefer" */
1285 
1286  /*
1287  * warn user that an SSL connection will never be negotiated
1288  * since SSL was not compiled in?
1289  */
1290  break;
1291 
1292  case 'r': /* "require" */
1293  case 'v': /* "verify-ca" or "verify-full" */
1295  libpq_append_conn_error(conn, "sslmode value \"%s\" invalid when SSL support is not compiled in",
1296  conn->sslmode);
1297  return false;
1298  }
1299 #endif
1300  }
1301  else
1302  {
1303  conn->sslmode = strdup(DefaultSSLMode);
1304  if (!conn->sslmode)
1305  goto oom_error;
1306  }
1307 
1308  /*
1309  * Validate TLS protocol versions for ssl_min_protocol_version and
1310  * ssl_max_protocol_version.
1311  */
1313  {
1315  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1316  "ssl_min_protocol_version",
1318  return false;
1319  }
1321  {
1323  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1324  "ssl_max_protocol_version",
1326  return false;
1327  }
1328 
1329  /*
1330  * Check if the range of SSL protocols defined is correct. This is done
1331  * at this early step because this is independent of the SSL
1332  * implementation used, and this avoids unnecessary cycles with an
1333  * already-built SSL context when the connection is being established, as
1334  * it would be doomed anyway.
1335  */
1338  {
1340  libpq_append_conn_error(conn, "invalid SSL protocol version range");
1341  return false;
1342  }
1343 
1344  /*
1345  * validate gssencmode option
1346  */
1347  if (conn->gssencmode)
1348  {
1349  if (strcmp(conn->gssencmode, "disable") != 0 &&
1350  strcmp(conn->gssencmode, "prefer") != 0 &&
1351  strcmp(conn->gssencmode, "require") != 0)
1352  {
1354  libpq_append_conn_error(conn, "invalid %s value: \"%s\"", "gssencmode", conn->gssencmode);
1355  return false;
1356  }
1357 #ifndef ENABLE_GSS
1358  if (strcmp(conn->gssencmode, "require") == 0)
1359  {
1361  libpq_append_conn_error(conn, "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in",
1362  conn->gssencmode);
1363  return false;
1364  }
1365 #endif
1366  }
1367  else
1368  {
1369  conn->gssencmode = strdup(DefaultGSSMode);
1370  if (!conn->gssencmode)
1371  goto oom_error;
1372  }
1373 
1374  /*
1375  * validate target_session_attrs option, and set target_server_type
1376  */
1378  {
1379  if (strcmp(conn->target_session_attrs, "any") == 0)
1381  else if (strcmp(conn->target_session_attrs, "read-write") == 0)
1383  else if (strcmp(conn->target_session_attrs, "read-only") == 0)
1385  else if (strcmp(conn->target_session_attrs, "primary") == 0)
1387  else if (strcmp(conn->target_session_attrs, "standby") == 0)
1389  else if (strcmp(conn->target_session_attrs, "prefer-standby") == 0)
1391  else
1392  {
1394  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1395  "target_session_attrs",
1397  return false;
1398  }
1399  }
1400  else
1402 
1403  /*
1404  * Resolve special "auto" client_encoding from the locale
1405  */
1407  strcmp(conn->client_encoding_initial, "auto") == 0)
1408  {
1412  goto oom_error;
1413  }
1414 
1415  /*
1416  * Only if we get this far is it appropriate to try to connect. (We need a
1417  * state flag, rather than just the boolean result of this function, in
1418  * case someone tries to PQreset() the PGconn.)
1419  */
1420  conn->options_valid = true;
1421 
1422  return true;
1423 
1424 oom_error:
1426  libpq_append_conn_error(conn, "out of memory");
1427  return false;
1428 }
const char * pg_encoding_to_char(int encoding)
Definition: encnames.c:588
char * pg_fe_getauthname(PQExpBuffer errorMessage)
Definition: fe-auth.c:1128
#define DefaultHost
Definition: fe-connect.c:118
static char * passwordFromFile(const char *hostname, const char *port, const char *dbname, const char *username, const char *pgpassfile)
Definition: fe-connect.c:6998
static bool sslVerifyProtocolRange(const char *min, const char *max)
Definition: fe-connect.c:7187
bool pqGetHomeDirectory(char *buf, int bufsize)
Definition: fe-connect.c:7240
#define DefaultSSLMode
Definition: fe-connect.c:129
#define DefaultGSSMode
Definition: fe-connect.c:135
static int count_comma_separated_elems(const char *input)
Definition: fe-connect.c:958
#define DefaultChannelBinding
Definition: fe-connect.c:123
static bool sslVerifyProtocolVersion(const char *version)
Definition: fe-connect.c:7161
static char * parse_comma_separated_list(char **startptr, bool *more)
Definition: fe-connect.c:982
#define PGPASSFILE
Definition: fe-connect.c:77
#define calloc(a, b)
Definition: header.h:55
#define free(a)
Definition: header.h:65
#define malloc(a)
Definition: header.h:50
int i
Definition: isn.c:73
@ CHT_UNIX_SOCKET
Definition: libpq-int.h:303
@ CHT_HOST_ADDRESS
Definition: libpq-int.h:302
@ CHT_HOST_NAME
Definition: libpq-int.h:301
@ SERVER_TYPE_STANDBY
Definition: libpq-int.h:240
@ SERVER_TYPE_PRIMARY
Definition: libpq-int.h:239
@ SERVER_TYPE_ANY
Definition: libpq-int.h:236
@ SERVER_TYPE_READ_WRITE
Definition: libpq-int.h:237
@ SERVER_TYPE_READ_ONLY
Definition: libpq-int.h:238
Assert(fmt[strlen(fmt) - 1] !='\n')
#define MAXPGPATH
#define DEFAULT_PGSOCKET_DIR
#define snprintf
Definition: port.h:238
int pg_get_encoding_from_locale(const char *ctype, bool write_message)
Definition: chklocale.c:428
static bool is_unixsock_path(const char *path)
Definition: pqcomm.h:55
char * host
Definition: libpq-int.h:338
char * password
Definition: libpq-int.h:341
char * port
Definition: libpq-int.h:340
char * hostaddr
Definition: libpq-int.h:339
pg_conn_host_type type
Definition: libpq-int.h:337
int nconnhost
Definition: libpq-int.h:428
char * channel_binding
Definition: libpq-int.h:374
char * pghost
Definition: libpq-int.h:353
char * ssl_max_protocol_version
Definition: libpq-int.h:397
char * pgpass
Definition: libpq-int.h:372
char * dbName
Definition: libpq-int.h:369
char * target_session_attrs
Definition: libpq-int.h:398
char * pguser
Definition: libpq-int.h:371
char * client_encoding_initial
Definition: libpq-int.h:365
char * sslmode
Definition: libpq-int.h:382
char * ssl_min_protocol_version
Definition: libpq-int.h:396
char * gssencmode
Definition: libpq-int.h:392
char * pghostaddr
Definition: libpq-int.h:357
char * pgpassfile
Definition: libpq-int.h:373
char * pgport
Definition: libpq-int.h:361
pg_conn_host * connhost
Definition: libpq-int.h:430

References Assert(), calloc, pg_conn::channel_binding, CHT_HOST_ADDRESS, CHT_HOST_NAME, CHT_UNIX_SOCKET, pg_conn::client_encoding_initial, conn, CONNECTION_BAD, pg_conn::connhost, count_comma_separated_elems(), pg_conn::dbName, DEFAULT_PGSOCKET_DIR, DefaultChannelBinding, DefaultGSSMode, DefaultHost, DefaultSSLMode, pg_conn::errorMessage, free, pg_conn::gssencmode, pg_conn_host::host, pg_conn_host::hostaddr, i, is_unixsock_path(), libpq_append_conn_error(), malloc, MAXPGPATH, pg_conn::nconnhost, pg_conn::options_valid, parse_comma_separated_list(), pg_conn_host::password, passwordFromFile(), pg_encoding_to_char(), pg_fe_getauthname(), pg_get_encoding_from_locale(), pg_conn::pghost, pg_conn::pghostaddr, pg_conn::pgpass, PGPASSFILE, pg_conn::pgpassfile, pg_conn::pgport, pg_conn::pguser, pg_conn_host::port, pqGetHomeDirectory(), SERVER_TYPE_ANY, SERVER_TYPE_PREFER_STANDBY, SERVER_TYPE_PRIMARY, SERVER_TYPE_READ_ONLY, SERVER_TYPE_READ_WRITE, SERVER_TYPE_STANDBY, snprintf, pg_conn::ssl_max_protocol_version, pg_conn::ssl_min_protocol_version, pg_conn::sslmode, sslVerifyProtocolRange(), sslVerifyProtocolVersion(), pg_conn::status, pg_conn::target_server_type, pg_conn::target_session_attrs, pg_conn_host::type, and pg_conn::whichhost.

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

◆ conninfo_add_defaults()

static bool conninfo_add_defaults ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

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

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

References libpq_append_error(), parseServiceInfo(), pg_fe_getauthname(), and option::val.

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

◆ conninfo_array_parse()

static PQconninfoOption * conninfo_array_parse ( const char *const *  keywords,
const char *const *  values,
PQExpBuffer  errorMessage,
bool  use_defaults,
int  expand_dbname 
)
static

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

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

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

Referenced by PQconnectStartParams().

◆ conninfo_find()

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

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

6515 {
6517 
6518  for (option = connOptions; option->keyword != NULL; option++)
6519  {
6520  if (strcmp(option->keyword, keyword) == 0)
6521  return option;
6522  }
6523 
6524  return NULL;
6525 }

Referenced by conninfo_getval(), and conninfo_storeval().

◆ conninfo_getval()

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

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

6426 {
6428 
6429  option = conninfo_find(connOptions, keyword);
6430 
6431  return option ? option->val : NULL;
6432 }
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6514

References conninfo_find(), and option::val.

Referenced by fillPGconn(), and parseServiceInfo().

◆ conninfo_init()

static PQconninfoOption * conninfo_init ( PQExpBuffer  errorMessage)
static

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

5380 {
5382  PQconninfoOption *opt_dest;
5383  const internalPQconninfoOption *cur_opt;
5384 
5385  /*
5386  * Get enough memory for all options in PQconninfoOptions, even if some
5387  * end up being filtered out.
5388  */
5390  if (options == NULL)
5391  {
5392  libpq_append_error(errorMessage, "out of memory");
5393  return NULL;
5394  }
5395  opt_dest = options;
5396 
5397  for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++)
5398  {
5399  /* Only copy the public part of the struct, not the full internal */
5400  memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption));
5401  opt_dest++;
5402  }
5403  MemSet(opt_dest, 0, sizeof(PQconninfoOption));
5404 
5405  return options;
5406 }
#define MemSet(start, val, len)
Definition: c.h:953
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:188

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

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

◆ conninfo_parse()

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

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

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

References buf, conninfo_add_defaults(), conninfo_init(), conninfo_storeval(), free, libpq_append_error(), options, and PQconninfoFree().

Referenced by parse_connection_string().

◆ conninfo_storeval()

static PQconninfoOption * conninfo_storeval ( PQconninfoOption connOptions,
const char *  keyword,
const char *  value,
PQExpBuffer  errorMessage,
bool  ignoreMissing,
bool  uri_decode 
)
static

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

6454 {
6456  char *value_copy;
6457 
6458  /*
6459  * For backwards compatibility, requiressl=1 gets translated to
6460  * sslmode=require, and requiressl=0 gets translated to sslmode=prefer
6461  * (which is the default for sslmode).
6462  */
6463  if (strcmp(keyword, "requiressl") == 0)
6464  {
6465  keyword = "sslmode";
6466  if (value[0] == '1')
6467  value = "require";
6468  else
6469  value = "prefer";
6470  }
6471 
6472  option = conninfo_find(connOptions, keyword);
6473  if (option == NULL)
6474  {
6475  if (!ignoreMissing)
6476  libpq_append_error(errorMessage,
6477  "invalid connection option \"%s\"",
6478  keyword);
6479  return NULL;
6480  }
6481 
6482  if (uri_decode)
6483  {
6484  value_copy = conninfo_uri_decode(value, errorMessage);
6485  if (value_copy == NULL)
6486  /* conninfo_uri_decode already set an error message */
6487  return NULL;
6488  }
6489  else
6490  {
6491  value_copy = strdup(value);
6492  if (value_copy == NULL)
6493  {
6494  libpq_append_error(errorMessage, "out of memory");
6495  return NULL;
6496  }
6497  }
6498 
6499  free(option->val);
6500  option->val = value_copy;
6501 
6502  return option;
6503 }
static char * conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
Definition: fe-connect.c:6335
static struct @143 value

References conninfo_find(), conninfo_uri_decode(), free, libpq_append_error(), option::val, and value.

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

◆ conninfo_uri_decode()

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

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

6336 {
6337  char *buf;
6338  char *p;
6339  const char *q = str;
6340 
6341  buf = malloc(strlen(str) + 1);
6342  if (buf == NULL)
6343  {
6344  libpq_append_error(errorMessage, "out of memory");
6345  return NULL;
6346  }
6347  p = buf;
6348 
6349  for (;;)
6350  {
6351  if (*q != '%')
6352  {
6353  /* copy and check for NUL terminator */
6354  if (!(*(p++) = *(q++)))
6355  break;
6356  }
6357  else
6358  {
6359  int hi;
6360  int lo;
6361  int c;
6362 
6363  ++q; /* skip the percent sign itself */
6364 
6365  /*
6366  * Possible EOL will be caught by the first call to
6367  * get_hexdigit(), so we never dereference an invalid q pointer.
6368  */
6369  if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo)))
6370  {
6371  libpq_append_error(errorMessage,
6372  "invalid percent-encoded token: \"%s\"",
6373  str);
6374  free(buf);
6375  return NULL;
6376  }
6377 
6378  c = (hi << 4) | lo;
6379  if (c == 0)
6380  {
6381  libpq_append_error(errorMessage,
6382  "forbidden value %%00 in percent-encoded value: \"%s\"",
6383  str);
6384  free(buf);
6385  return NULL;
6386  }
6387  *(p++) = c;
6388  }
6389  }
6390 
6391  return buf;
6392 }
static bool get_hexdigit(char digit, int *value)
Definition: fe-connect.c:6403
char * c

References buf, free, get_hexdigit(), libpq_append_error(), malloc, and generate_unaccent_rules::str.

Referenced by conninfo_storeval(), and conninfo_uri_parse_params().

◆ conninfo_uri_parse()

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

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

5910 {
5912 
5913  /* Make a working copy of PQconninfoOptions */
5914  options = conninfo_init(errorMessage);
5915  if (options == NULL)
5916  return NULL;
5917 
5918  if (!conninfo_uri_parse_options(options, uri, errorMessage))
5919  {
5921  return NULL;
5922  }
5923 
5924  /*
5925  * Add in defaults if the caller wants that.
5926  */
5927  if (use_defaults)
5928  {
5929  if (!conninfo_add_defaults(options, errorMessage))
5930  {
5932  return NULL;
5933  }
5934  }
5935 
5936  return options;
5937 }
static bool conninfo_uri_parse_options(PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage)
Definition: fe-connect.c:5961

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

Referenced by parse_connection_string().

◆ conninfo_uri_parse_options()

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

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

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

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

Referenced by conninfo_uri_parse().

◆ conninfo_uri_parse_params()

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

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

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

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

Referenced by conninfo_uri_parse_options().

◆ count_comma_separated_elems()

static int count_comma_separated_elems ( const char *  input)
static

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

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

Referenced by connectOptions2().

◆ default_threadlock()

static void default_threadlock ( int  acquire)
static

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

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

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

Referenced by PQregisterThreadLock().

◆ defaultNoticeProcessor()

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

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

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

References arg, and fprintf.

Referenced by makeEmptyPGconn().

◆ defaultNoticeReceiver()

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

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

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

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

Referenced by makeEmptyPGconn().

◆ emitHostIdentityInfo()

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

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

1660 {
1661  if (conn->raddr.addr.ss_family == AF_UNIX)
1662  {
1663  char service[NI_MAXHOST];
1664 
1666  NULL, 0,
1667  service, sizeof(service),
1668  NI_NUMERICSERV);
1670  libpq_gettext("connection to server on socket \"%s\" failed: "),
1671  service);
1672  }
1673  else
1674  {
1675  const char *displayed_host;
1676  const char *displayed_port;
1677 
1678  /* To which host and port were we actually connecting? */
1680  displayed_host = conn->connhost[conn->whichhost].hostaddr;
1681  else
1682  displayed_host = conn->connhost[conn->whichhost].host;
1683  displayed_port = conn->connhost[conn->whichhost].port;
1684  if (displayed_port == NULL || displayed_port[0] == '\0')
1685  displayed_port = DEF_PGPORT_STR;
1686 
1687  /*
1688  * If the user did not supply an IP address using 'hostaddr', and
1689  * 'host' was missing or does not match our lookup, display the
1690  * looked-up IP address.
1691  */
1693  host_addr[0] &&
1694  strcmp(displayed_host, host_addr) != 0)
1696  libpq_gettext("connection to server at \"%s\" (%s), port %s failed: "),
1697  displayed_host, host_addr,
1698  displayed_port);
1699  else
1701  libpq_gettext("connection to server at \"%s\", port %s failed: "),
1702  displayed_host,
1703  displayed_port);
1704  }
1705 }
int pg_getnameinfo_all(const struct sockaddr_storage *addr, int salen, char *node, int nodelen, char *service, int servicelen, int flags)
Definition: ip.c:114
#define libpq_gettext(x)
Definition: libpq-int.h:882
socklen_t salen
Definition: pqcomm.h:27

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

Referenced by PQconnectPoll().

◆ fillPGconn()

static bool fillPGconn ( PGconn conn,
PQconninfoOption connOptions 
)
static

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

882 {
884 
885  for (option = PQconninfoOptions; option->keyword; option++)
886  {
887  if (option->connofs >= 0)
888  {
889  const char *tmp = conninfo_getval(connOptions, option->keyword);
890 
891  if (tmp)
892  {
893  char **connmember = (char **) ((char *) conn + option->connofs);
894 
895  free(*connmember);
896  *connmember = strdup(tmp);
897  if (*connmember == NULL)
898  {
899  libpq_append_conn_error(conn, "out of memory");
900  return false;
901  }
902  }
903  }
904  }
905 
906  return true;
907 }
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6424

References conn, conninfo_getval(), free, libpq_append_conn_error(), and PQconninfoOptions.

Referenced by connectOptions1(), and PQconnectStartParams().

◆ freePGconn()

static void freePGconn ( PGconn conn)
static

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

3962 {
3963  /* let any event procs clean up their state data */
3964  for (int i = 0; i < conn->nEvents; i++)
3965  {
3966  PGEventConnDestroy evt;
3967 
3968  evt.conn = conn;
3969  (void) conn->events[i].proc(PGEVT_CONNDESTROY, &evt,
3970  conn->events[i].passThrough);
3971  free(conn->events[i].name);
3972  }
3973 
3974  /* clean up pg_conn_host structures */
3975  for (int i = 0; i < conn->nconnhost; ++i)
3976  {
3977  free(conn->connhost[i].host);
3979  free(conn->connhost[i].port);
3980  if (conn->connhost[i].password != NULL)
3981  {
3984  }
3985  }
3986  free(conn->connhost);
3987 
3989  free(conn->events);
3990  free(conn->pghost);
3991  free(conn->pghostaddr);
3992  free(conn->pgport);
3995  free(conn->pgoptions);
3996  free(conn->appname);
3997  free(conn->fbappname);
3998  free(conn->dbName);
3999  free(conn->replication);
4000  free(conn->pguser);
4001  if (conn->pgpass)
4002  {
4003  explicit_bzero(conn->pgpass, strlen(conn->pgpass));
4004  free(conn->pgpass);
4005  }
4006  free(conn->pgpassfile);
4008  free(conn->keepalives);
4012  free(conn->sslmode);
4013  free(conn->sslcert);
4014  free(conn->sslkey);
4015  if (conn->sslpassword)
4016  {
4018  free(conn->sslpassword);
4019  }
4020  free(conn->sslrootcert);
4021  free(conn->sslcrl);
4022  free(conn->sslcrldir);
4024  free(conn->sslsni);
4025  free(conn->requirepeer);
4028  free(conn->gssencmode);
4029  free(conn->krbsrvname);
4030  free(conn->gsslib);
4031  free(conn->connip);
4032  /* Note that conn->Pfdebug is not ours to close or free */
4034  free(conn->inBuffer);
4035  free(conn->outBuffer);
4036  free(conn->rowBuf);
4040 
4041  free(conn);
4042 }
@ PGEVT_CONNDESTROY
Definition: libpq-events.h:31
void explicit_bzero(void *buf, size_t len)
void * passThrough
Definition: libpq-int.h:164
char * name
Definition: libpq-int.h:163
PGEventProc proc
Definition: libpq-int.h:162
char * replication
Definition: libpq-int.h:370
char * write_err_msg
Definition: libpq-int.h:458
char * sslrootcert
Definition: libpq-int.h:387
PGdataValue * rowBuf
Definition: libpq-int.h:499
char * sslcompression
Definition: libpq-int.h:383
char * inBuffer
Definition: libpq-int.h:482
char * sslcrldir
Definition: libpq-int.h:389
char * pgoptions
Definition: libpq-int.h:366
char * sslcrl
Definition: libpq-int.h:388
char * fbappname
Definition: libpq-int.h:368
char * sslcert
Definition: libpq-int.h:385
char * sslpassword
Definition: libpq-int.h:386
PQExpBufferData workBuffer
Definition: libpq-int.h:592
char * keepalives_idle
Definition: libpq-int.h:377
char * connip
Definition: libpq-int.h:431
char * keepalives
Definition: libpq-int.h:376
char * keepalives_interval
Definition: libpq-int.h:378
char * appname
Definition: libpq-int.h:367
char * pgtcp_user_timeout
Definition: libpq-int.h:364
int nEvents
Definition: libpq-int.h:409
char * sslkey
Definition: libpq-int.h:384
char * krbsrvname
Definition: libpq-int.h:393
char * gsslib
Definition: libpq-int.h:394
char * keepalives_count
Definition: libpq-int.h:380
char * requirepeer
Definition: libpq-int.h:391
char * sslsni
Definition: libpq-int.h:390
PGEvent * events
Definition: libpq-int.h:408
char * outBuffer
Definition: libpq-int.h:489

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

Referenced by makeEmptyPGconn(), and PQfinish().

◆ get_hexdigit()

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

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

6404 {
6405  if ('0' <= digit && digit <= '9')
6406  *value = digit - '0';
6407  else if ('A' <= digit && digit <= 'F')
6408  *value = digit - 'A' + 10;
6409  else if ('a' <= digit && digit <= 'f')
6410  *value = digit - 'a' + 10;
6411  else
6412  return false;
6413 
6414  return true;
6415 }

References value.

Referenced by conninfo_uri_decode().

◆ getHostaddr()

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

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

1627 {
1628  struct sockaddr_storage *addr = &conn->raddr.addr;
1629 
1630  if (addr->ss_family == AF_INET)
1631  {
1632  if (pg_inet_net_ntop(AF_INET,
1633  &((struct sockaddr_in *) addr)->sin_addr.s_addr,
1634  32,
1635  host_addr, host_addr_len) == NULL)
1636  host_addr[0] = '\0';
1637  }
1638  else if (addr->ss_family == AF_INET6)
1639  {
1640  if (pg_inet_net_ntop(AF_INET6,
1641  &((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr,
1642  128,
1643  host_addr, host_addr_len) == NULL)
1644  host_addr[0] = '\0';
1645  }
1646  else
1647  host_addr[0] = '\0';
1648 }
char * pg_inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size)
Definition: inet_net_ntop.c:77

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

Referenced by PQconnectPoll().

◆ internal_ping()

static PGPing internal_ping ( PGconn conn)
static

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

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

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

Referenced by PQping(), and PQpingParams().

◆ makeEmptyPGconn()

static PGconn * makeEmptyPGconn ( void  )
static

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

3864 {
3865  PGconn *conn;
3866 
3867 #ifdef WIN32
3868 
3869  /*
3870  * Make sure socket support is up and running in this process.
3871  *
3872  * Note: the Windows documentation says that we should eventually do a
3873  * matching WSACleanup() call, but experience suggests that that is at
3874  * least as likely to cause problems as fix them. So we don't.
3875  */
3876  static bool wsastartup_done = false;
3877 
3878  if (!wsastartup_done)
3879  {
3880  WSADATA wsaData;
3881 
3882  if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
3883  return NULL;
3884  wsastartup_done = true;
3885  }
3886 
3887  /* Forget any earlier error */
3888  WSASetLastError(0);
3889 #endif /* WIN32 */
3890 
3891  conn = (PGconn *) malloc(sizeof(PGconn));
3892  if (conn == NULL)
3893  return conn;
3894 
3895  /* Zero all pointers and booleans */
3896  MemSet(conn, 0, sizeof(PGconn));
3897 
3898  /* install default notice hooks */
3901 
3906  conn->options_valid = false;
3907  conn->nonblocking = false;
3909  conn->std_strings = false; /* unless server says differently */
3915  conn->Pfdebug = NULL;
3916 
3917  /*
3918  * We try to send at least 8K at a time, which is the usual size of pipe
3919  * buffers on Unix systems. That way, when we are sending a large amount
3920  * of data, we avoid incurring extra kernel context swaps for partial
3921  * bufferloads. The output buffer is initially made 16K in size, and we
3922  * try to dump it after accumulating 8K.
3923  *
3924  * With the same goal of minimizing context swaps, the input buffer will
3925  * be enlarged anytime it has less than 8K free, so we initially allocate
3926  * twice that.
3927  */
3928  conn->inBufSize = 16 * 1024;
3929  conn->inBuffer = (char *) malloc(conn->inBufSize);
3930  conn->outBufSize = 16 * 1024;
3931  conn->outBuffer = (char *) malloc(conn->outBufSize);
3932  conn->rowBufLen = 32;
3933  conn->rowBuf = (PGdataValue *) malloc(conn->rowBufLen * sizeof(PGdataValue));
3936 
3937  if (conn->inBuffer == NULL ||
3938  conn->outBuffer == NULL ||
3939  conn->rowBuf == NULL ||
3942  {
3943  /* out of memory already :-( */
3944  freePGconn(conn);
3945  conn = NULL;
3946  }
3947 
3948  return conn;
3949 }
static void defaultNoticeReceiver(void *arg, const PGresult *res)
Definition: fe-connect.c:6934
static void defaultNoticeProcessor(void *arg, const char *message)
Definition: fe-connect.c:6949
static void freePGconn(PGconn *conn)
Definition: fe-connect.c:3961
@ PQSHOW_CONTEXT_ERRORS
Definition: libpq-fe.h:136
@ PQERRORS_DEFAULT
Definition: libpq-fe.h:128
@ PG_BOOL_UNKNOWN
Definition: libpq-int.h:248
@ PG_SQL_ASCII
Definition: pg_wchar.h:226
#define PGINVALID_SOCKET
Definition: port.h:31
#define PQExpBufferBroken(str)
Definition: pqexpbuffer.h:59
PQnoticeReceiver noticeRec
Definition: libpq-int.h:154
bool std_strings
Definition: libpq-int.h:474
PGTernaryBool in_hot_standby
Definition: libpq-int.h:476
int inBufSize
Definition: libpq-int.h:483
int client_encoding
Definition: libpq-int.h:473
PGTernaryBool default_transaction_read_only
Definition: libpq-int.h:475
PGVerbosity verbosity
Definition: libpq-int.h:477
int rowBufLen
Definition: libpq-int.h:500
int outBufSize
Definition: libpq-int.h:490
PGNoticeHooks noticeHooks
Definition: libpq-int.h:405
FILE * Pfdebug
Definition: libpq-int.h:401
PGContextVisibility show_context
Definition: libpq-int.h:478

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

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

◆ optional_setsockopt()

static bool optional_setsockopt ( int  fd,
int  protoid,
int  optid,
int  value 
)
static

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

4318 {
4319  if (value < 0)
4320  return true;
4321  if (setsockopt(fd, protoid, optid, (char *) &value, sizeof(value)) < 0)
4322  return false;
4323  return true;
4324 }
static int fd(const char *x, int i)
Definition: preproc-init.c:105

References fd(), and value.

Referenced by PQcancel().

◆ parse_comma_separated_list()

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

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

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

References len, and malloc.

Referenced by connectOptions2().

◆ parse_connection_string()

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

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

5420 {
5421  /* Parse as URI if connection string matches URI prefix */
5422  if (uri_prefix_length(connstr) != 0)
5423  return conninfo_uri_parse(connstr, errorMessage, use_defaults);
5424 
5425  /* Parse as default otherwise */
5426  return conninfo_parse(connstr, errorMessage, use_defaults);
5427 }
static PQconninfoOption * conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5908
static PQconninfoOption * conninfo_parse(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5472
static char * connstr
Definition: pg_dumpall.c:88

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

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

◆ parse_int_param()

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

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

1756 {
1757  char *end;
1758  long numval;
1759 
1760  Assert(value != NULL);
1761 
1762  *result = 0;
1763 
1764  /* strtol(3) skips leading whitespaces */
1765  errno = 0;
1766  numval = strtol(value, &end, 10);
1767 
1768  /*
1769  * If no progress was done during the parsing or an error happened, fail.
1770  * This tests properly for overflows of the result.
1771  */
1772  if (value == end || errno != 0 || numval != (int) numval)
1773  goto error;
1774 
1775  /*
1776  * Skip any trailing whitespace; if anything but whitespace remains before
1777  * the terminating character, fail
1778  */
1779  while (*end != '\0' && isspace((unsigned char) *end))
1780  end++;
1781 
1782  if (*end != '\0')
1783  goto error;
1784 
1785  *result = numval;
1786  return true;
1787 
1788 error:
1789  libpq_append_conn_error(conn, "invalid integer value \"%s\" for connection option \"%s\"",
1790  value, context);
1791  return false;
1792 }
static void error(void)
Definition: sql-dyntest.c:147

References Assert(), conn, error(), libpq_append_conn_error(), and value.

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

◆ parseServiceFile()

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

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

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

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

Referenced by parseServiceInfo().

◆ parseServiceInfo()

static int parseServiceInfo ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

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

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

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

Referenced by conninfo_add_defaults().

◆ passwordFromFile()

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

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

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

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

Referenced by connectOptions2().

◆ pgpassfileWarning()

static void pgpassfileWarning ( PGconn conn)
static

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

7139 {
7140  /* If it was 'invalid authorization', add pgpassfile mention */
7141  /* only works with >= 9.0 servers */
7142  if (conn->password_needed &&
7143  conn->connhost[conn->whichhost].password != NULL &&
7144  conn->result)
7145  {
7146  const char *sqlstate = PQresultErrorField(conn->result,
7148 
7149  if (sqlstate && strcmp(sqlstate, ERRCODE_INVALID_PASSWORD) == 0)
7150  libpq_append_conn_error(conn, "password retrieved from file \"%s\"",
7151  conn->pgpassfile);
7152  }
7153 }
#define ERRCODE_INVALID_PASSWORD
Definition: fe-connect.c:91
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:3295
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:56
PGresult * result
Definition: libpq-int.h:511
bool password_needed
Definition: libpq-int.h:454

References conn, pg_conn::connhost, ERRCODE_INVALID_PASSWORD, libpq_append_conn_error(), pg_conn_host::password, pg_conn::password_needed, PG_DIAG_SQLSTATE, pg_conn::pgpassfile, PQresultErrorField(), pg_conn::result, and pg_conn::whichhost.

Referenced by PQconnectPoll().

◆ PQbackendPID()

int PQbackendPID ( const PGconn conn)

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

6778 {
6779  if (!conn || conn->status != CONNECTION_OK)
6780  return 0;
6781  return conn->be_pid;
6782 }
@ CONNECTION_OK
Definition: libpq-fe.h:60
int be_pid
Definition: libpq-int.h:470

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

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

◆ PQcancel()

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

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

4350 {
4351  int save_errno = SOCK_ERRNO;
4352  pgsocket tmpsock = PGINVALID_SOCKET;
4353  int maxlen;
4354  struct
4355  {
4356  uint32 packetlen;
4358  } crp;
4359 
4360  if (!cancel)
4361  {
4362  strlcpy(errbuf, "PQcancel() -- no cancel object supplied", errbufsize);
4363  /* strlcpy probably doesn't change errno, but be paranoid */
4364  SOCK_ERRNO_SET(save_errno);
4365  return false;
4366  }
4367 
4368  /*
4369  * We need to open a temporary connection to the postmaster. Do this with
4370  * only kernel calls.
4371  */
4372  if ((tmpsock = socket(cancel->raddr.addr.ss_family, SOCK_STREAM, 0)) == PGINVALID_SOCKET)
4373  {
4374  strlcpy(errbuf, "PQcancel() -- socket() failed: ", errbufsize);
4375  goto cancel_errReturn;
4376  }
4377 
4378  /*
4379  * Since this connection will only be used to send a single packet of
4380  * data, we don't need NODELAY. We also don't set the socket to
4381  * nonblocking mode, because the API definition of PQcancel requires the
4382  * cancel to be sent in a blocking way.
4383  *
4384  * We do set socket options related to keepalives and other TCP timeouts.
4385  * This ensures that this function does not block indefinitely when
4386  * reasonable keepalive and timeout settings have been provided.
4387  */
4388  if (cancel->raddr.addr.ss_family != AF_UNIX &&
4389  cancel->keepalives != 0)
4390  {
4391 #ifndef WIN32
4392  if (!optional_setsockopt(tmpsock, SOL_SOCKET, SO_KEEPALIVE, 1))
4393  {
4394  strlcpy(errbuf, "PQcancel() -- setsockopt(SO_KEEPALIVE) failed: ", errbufsize);
4395  goto cancel_errReturn;
4396  }
4397 
4398 #ifdef PG_TCP_KEEPALIVE_IDLE
4399  if (!optional_setsockopt(tmpsock, IPPROTO_TCP, PG_TCP_KEEPALIVE_IDLE,
4400  cancel->keepalives_idle))
4401  {
4402  strlcpy(errbuf, "PQcancel() -- setsockopt(" PG_TCP_KEEPALIVE_IDLE_STR ") failed: ", errbufsize);
4403  goto cancel_errReturn;
4404  }
4405 #endif
4406 
4407 #ifdef TCP_KEEPINTVL
4408  if (!optional_setsockopt(tmpsock, IPPROTO_TCP, TCP_KEEPINTVL,
4409  cancel->keepalives_interval))
4410  {
4411  strlcpy(errbuf, "PQcancel() -- setsockopt(TCP_KEEPINTVL) failed: ", errbufsize);
4412  goto cancel_errReturn;
4413  }
4414 #endif
4415 
4416 #ifdef TCP_KEEPCNT
4417  if (!optional_setsockopt(tmpsock, IPPROTO_TCP, TCP_KEEPCNT,
4418  cancel->keepalives_count))
4419  {
4420  strlcpy(errbuf, "PQcancel() -- setsockopt(TCP_KEEPCNT) failed: ", errbufsize);
4421  goto cancel_errReturn;
4422  }
4423 #endif
4424 
4425 #else /* WIN32 */
4426 
4427 #ifdef SIO_KEEPALIVE_VALS
4428  if (!setKeepalivesWin32(tmpsock,
4429  cancel->keepalives_idle,
4430  cancel->keepalives_interval))
4431  {
4432  strlcpy(errbuf, "PQcancel() -- WSAIoctl(SIO_KEEPALIVE_VALS) failed: ", errbufsize);
4433  goto cancel_errReturn;
4434  }
4435 #endif /* SIO_KEEPALIVE_VALS */
4436 #endif /* WIN32 */
4437 
4438  /* TCP_USER_TIMEOUT works the same way on Unix and Windows */
4439 #ifdef TCP_USER_TIMEOUT
4440  if (!optional_setsockopt(tmpsock, IPPROTO_TCP, TCP_USER_TIMEOUT,
4441  cancel->pgtcp_user_timeout))
4442  {
4443  strlcpy(errbuf, "PQcancel() -- setsockopt(TCP_USER_TIMEOUT) failed: ", errbufsize);
4444  goto cancel_errReturn;
4445  }
4446 #endif
4447  }
4448 
4449 retry3:
4450  if (connect(tmpsock, (struct sockaddr *) &cancel->raddr.addr,
4451  cancel->raddr.salen) < 0)
4452  {
4453  if (SOCK_ERRNO == EINTR)
4454  /* Interrupted system call - we'll just try again */
4455  goto retry3;
4456  strlcpy(errbuf, "PQcancel() -- connect() failed: ", errbufsize);
4457  goto cancel_errReturn;
4458  }
4459 
4460  /* Create and send the cancel request packet. */
4461 
4462  crp.packetlen = pg_hton32((uint32) sizeof(crp));
4463  crp.cp.cancelRequestCode = (MsgType) pg_hton32(CANCEL_REQUEST_CODE);
4464  crp.cp.backendPID = pg_hton32(cancel->be_pid);
4465  crp.cp.cancelAuthCode = pg_hton32(cancel->be_key);
4466 
4467 retry4:
4468  if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp))
4469  {
4470  if (SOCK_ERRNO == EINTR)
4471  /* Interrupted system call - we'll just try again */
4472  goto retry4;
4473  strlcpy(errbuf, "PQcancel() -- send() failed: ", errbufsize);
4474  goto cancel_errReturn;
4475  }
4476 
4477  /*
4478  * Wait for the postmaster to close the connection, which indicates that
4479  * it's processed the request. Without this delay, we might issue another
4480  * command only to find that our cancel zaps that command instead of the
4481  * one we thought we were canceling. Note we don't actually expect this
4482  * read to obtain any data, we are just waiting for EOF to be signaled.
4483  */
4484 retry5:
4485  if (recv(tmpsock, (char *) &crp, 1, 0) < 0)
4486  {
4487  if (SOCK_ERRNO == EINTR)
4488  /* Interrupted system call - we'll just try again */
4489  goto retry5;
4490  /* we ignore other error conditions */
4491  }
4492 
4493  /* All done */
4494  closesocket(tmpsock);
4495  SOCK_ERRNO_SET(save_errno);
4496  return true;
4497 
4498 cancel_errReturn:
4499 
4500  /*
4501  * Make sure we don't overflow the error buffer. Leave space for the \n at
4502  * the end, and for the terminating zero.
4503  */
4504  maxlen = errbufsize - strlen(errbuf) - 2;
4505  if (maxlen >= 0)
4506  {
4507  /*
4508  * We can't invoke strerror here, since it's not signal-safe. Settle
4509  * for printing the decimal value of errno. Even that has to be done
4510  * the hard way.
4511  */
4512  int val = SOCK_ERRNO;
4513  char buf[32];
4514  char *bufp;
4515 
4516  bufp = buf + sizeof(buf) - 1;
4517  *bufp = '\0';
4518  do
4519  {
4520  *(--bufp) = (val % 10) + '0';
4521  val /= 10;
4522  } while (val > 0);
4523  bufp -= 6;
4524  memcpy(bufp, "error ", 6);
4525  strncat(errbuf, bufp, maxlen);
4526  strcat(errbuf, "\n");
4527  }
4528  if (tmpsock != PGINVALID_SOCKET)
4529  closesocket(tmpsock);
4530  SOCK_ERRNO_SET(save_errno);
4531  return false;
4532 }
unsigned int uint32
Definition: c.h:442
static bool optional_setsockopt(int fd, int protoid, int optid, int value)
Definition: fe-connect.c:4317
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:905
#define pg_hton32(x)
Definition: pg_bswap.h:121
int pgsocket
Definition: port.h:29
#define closesocket
Definition: port.h:349
#define CANCEL_REQUEST_CODE
Definition: pqcomm.h:138
ProtocolVersion MsgType
Definition: pqcomm.h:89
int pgtcp_user_timeout
Definition: libpq-int.h:604
int keepalives_interval
Definition: libpq-int.h:607
int keepalives_idle
Definition: libpq-int.h:606
int keepalives_count
Definition: libpq-int.h:609
SockAddr raddr
Definition: libpq-int.h:601
int be_pid
Definition: libpq-int.h:602
int keepalives
Definition: libpq-int.h:605
int be_key
Definition: libpq-int.h:603
#define EINTR
Definition: win32_port.h:369
#define recv(s, buf, len, flags)
Definition: win32_port.h:493
#define send(s, buf, len, flags)
Definition: win32_port.h:494
#define socket(af, type, protocol)
Definition: win32_port.h:487
#define connect(s, name, namelen)
Definition: win32_port.h:491

References SockAddr::addr, pg_cancel::be_key, pg_cancel::be_pid, buf, CANCEL_REQUEST_CODE, closesocket, connect, EINTR, pg_cancel::keepalives, pg_cancel::keepalives_count, pg_cancel::keepalives_idle, pg_cancel::keepalives_interval, optional_setsockopt(), pg_hton32, PGINVALID_SOCKET, pg_cancel::pgtcp_user_timeout, pg_cancel::raddr, recv, SockAddr::salen, send, SOCK_ERRNO, SOCK_ERRNO_SET, socket, strlcpy(), and val.

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

◆ PQclientEncoding()

◆ PQconndefaults()

PQconninfoOption* PQconndefaults ( void  )

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

1448 {
1449  PQExpBufferData errorBuf;
1450  PQconninfoOption *connOptions;
1451 
1452  /* We don't actually report any errors here, but callees want a buffer */
1453  initPQExpBuffer(&errorBuf);
1454  if (PQExpBufferDataBroken(errorBuf))
1455  return NULL; /* out of memory already :-( */
1456 
1457  connOptions = conninfo_init(&errorBuf);
1458  if (connOptions != NULL)
1459  {
1460  /* pass NULL errorBuf to ignore errors */
1461  if (!conninfo_add_defaults(connOptions, NULL))
1462  {
1463  PQconninfoFree(connOptions);
1464  connOptions = NULL;
1465  }
1466  }
1467 
1468  termPQExpBuffer(&errorBuf);
1469  return connOptions;
1470 }

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

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

◆ PQconnectdb()

PGconn* PQconnectdb ( const char *  conninfo)

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

708 {
709  PGconn *conn = PQconnectStart(conninfo);
710 
711  if (conn && conn->status != CONNECTION_BAD)
712  (void) connectDBComplete(conn);
713 
714  return conn;
715 }
PGconn * PQconnectStart(const char *conninfo)
Definition: fe-connect.c:835

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

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

◆ PQconnectdbParams()

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

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

655 {
656  PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname);
657 
658  if (conn && conn->status != CONNECTION_BAD)
659  (void) connectDBComplete(conn);
660 
661  return conn;
662 }
PGconn * PQconnectStartParams(const char *const *keywords, const char *const *values, int expand_dbname)
Definition: fe-connect.c:754

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

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

◆ PQconnectionNeedsPassword()

int PQconnectionNeedsPassword ( const PGconn conn)

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

6795 {
6796  char *password;
6797 
6798  if (!conn)
6799  return false;
6800  password = PQpass(conn);
6801  if (conn->password_needed &&
6802  (password == NULL || password[0] == '\0'))
6803  return true;
6804  else
6805  return false;
6806 }
char * PQpass(const PGconn *conn)
Definition: fe-connect.c:6605

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

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

◆ PQconnectionUsedPassword()

int PQconnectionUsedPassword ( const PGconn conn)

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

6810 {
6811  if (!conn)
6812  return false;
6813  if (conn->password_needed)
6814  return true;
6815  else
6816  return false;
6817 }

References conn, and pg_conn::password_needed.

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

◆ PQconnectPoll()

PostgresPollingStatusType PQconnectPoll ( PGconn conn)

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

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