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

Go to the source code of this file.

Data Structures

struct  _internalPQconninfoOption
 

Macros

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

Typedefs

typedef struct _internalPQconninfoOption internalPQconninfoOption
 

Functions

static bool connectOptions1 (PGconn *conn, const char *conninfo)
 
static bool connectOptions2 (PGconn *conn)
 
static int connectDBStart (PGconn *conn)
 
static int connectDBComplete (PGconn *conn)
 
static PGPing internal_ping (PGconn *conn)
 
static PGconnmakeEmptyPGconn (void)
 
static bool fillPGconn (PGconn *conn, PQconninfoOption *connOptions)
 
static void freePGconn (PGconn *conn)
 
static void closePGconn (PGconn *conn)
 
static void release_conn_addrinfo (PGconn *conn)
 
static void sendTerminateConn (PGconn *conn)
 
static PQconninfoOptionconninfo_init (PQExpBuffer errorMessage)
 
static PQconninfoOptionparse_connection_string (const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
 
static int uri_prefix_length (const char *connstr)
 
static bool recognized_connection_string (const char *connstr)
 
static PQconninfoOptionconninfo_parse (const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
 
static PQconninfoOptionconninfo_array_parse (const char *const *keywords, const char *const *values, PQExpBuffer errorMessage, bool use_defaults, int expand_dbname)
 
static bool conninfo_add_defaults (PQconninfoOption *options, PQExpBuffer errorMessage)
 
static PQconninfoOptionconninfo_uri_parse (const char *uri, PQExpBuffer errorMessage, bool use_defaults)
 
static bool conninfo_uri_parse_options (PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage)
 
static bool conninfo_uri_parse_params (char *params, PQconninfoOption *connOptions, PQExpBuffer errorMessage)
 
static char * conninfo_uri_decode (const char *str, PQExpBuffer errorMessage)
 
static bool get_hexdigit (char digit, int *value)
 
static const char * conninfo_getval (PQconninfoOption *connOptions, const char *keyword)
 
static PQconninfoOptionconninfo_storeval (PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode)
 
static PQconninfoOptionconninfo_find (PQconninfoOption *connOptions, const char *keyword)
 
static void defaultNoticeReceiver (void *arg, const PGresult *res)
 
static void defaultNoticeProcessor (void *arg, const char *message)
 
static int parseServiceInfo (PQconninfoOption *options, PQExpBuffer errorMessage)
 
static int parseServiceFile (const char *serviceFile, const char *service, PQconninfoOption *options, PQExpBuffer errorMessage, bool *group_found)
 
static char * pwdfMatchesString (char *buf, const char *token)
 
static char * passwordFromFile (const char *hostname, const char *port, const char *dbname, const char *username, const char *pgpassfile)
 
static void pgpassfileWarning (PGconn *conn)
 
static void default_threadlock (int acquire)
 
static bool sslVerifyProtocolVersion (const char *version)
 
static bool sslVerifyProtocolRange (const char *min, const char *max)
 
void pqDropConnection (PGconn *conn, bool flushInput)
 
static void pqDropServerData (PGconn *conn)
 
PGconnPQconnectdbParams (const char *const *keywords, const char *const *values, int expand_dbname)
 
PGPing PQpingParams (const char *const *keywords, const char *const *values, int expand_dbname)
 
PGconnPQconnectdb (const char *conninfo)
 
PGPing PQping (const char *conninfo)
 
PGconnPQconnectStartParams (const char *const *keywords, const char *const *values, int expand_dbname)
 
PGconnPQconnectStart (const char *conninfo)
 
static int count_comma_separated_elems (const char *input)
 
static char * parse_comma_separated_list (char **startptr, bool *more)
 
PQconninfoOptionPQconndefaults (void)
 
PGconnPQsetdbLogin (const char *pghost, const char *pgport, const char *pgoptions, const char *pgtty, const char *dbName, const char *login, const char *pwd)
 
static int connectNoDelay (PGconn *conn)
 
static void getHostaddr (PGconn *conn, char *host_addr, int host_addr_len)
 
static void 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)
 
static bool saveErrorMessage (PGconn *conn, PQExpBuffer savedMessage)
 
static void restoreErrorMessage (PGconn *conn, PQExpBuffer savedMessage)
 
PostgresPollingStatusType PQconnectPoll (PGconn *conn)
 
void PQfinish (PGconn *conn)
 
void PQreset (PGconn *conn)
 
int PQresetStart (PGconn *conn)
 
PostgresPollingStatusType PQresetPoll (PGconn *conn)
 
PGcancelPQgetCancel (PGconn *conn)
 
void PQfreeCancel (PGcancel *cancel)
 
static int internal_cancel (SockAddr *raddr, int be_pid, int be_key, char *errbuf, int errbufsize)
 
int PQcancel (PGcancel *cancel, char *errbuf, int errbufsize)
 
int PQrequestCancel (PGconn *conn)
 
int pqPacketSend (PGconn *conn, char pack_type, const void *buf, size_t buf_len)
 
PQconninfoOptionPQconninfoParse (const char *conninfo, char **errmsg)
 
PQconninfoOptionPQconninfo (PGconn *conn)
 
void PQconninfoFree (PQconninfoOption *connOptions)
 
char * PQdb (const PGconn *conn)
 
char * PQuser (const PGconn *conn)
 
char * PQpass (const PGconn *conn)
 
char * PQhost (const PGconn *conn)
 
char * PQhostaddr (const PGconn *conn)
 
char * PQport (const PGconn *conn)
 
char * PQtty (const PGconn *conn)
 
char * PQoptions (const PGconn *conn)
 
ConnStatusType PQstatus (const PGconn *conn)
 
PGTransactionStatusType PQtransactionStatus (const PGconn *conn)
 
const char * PQparameterStatus (const PGconn *conn, const char *paramName)
 
int PQprotocolVersion (const PGconn *conn)
 
int PQserverVersion (const PGconn *conn)
 
char * PQerrorMessage (const PGconn *conn)
 
int PQsocket (const PGconn *conn)
 
int PQbackendPID (const PGconn *conn)
 
int PQconnectionNeedsPassword (const PGconn *conn)
 
int PQconnectionUsedPassword (const PGconn *conn)
 
int PQclientEncoding (const PGconn *conn)
 
int PQsetClientEncoding (PGconn *conn, const char *encoding)
 
PGVerbosity PQsetErrorVerbosity (PGconn *conn, PGVerbosity verbosity)
 
PGContextVisibility PQsetErrorContextVisibility (PGconn *conn, PGContextVisibility show_context)
 
void PQtrace (PGconn *conn, FILE *debug_port)
 
void PQuntrace (PGconn *conn)
 
PQnoticeReceiver PQsetNoticeReceiver (PGconn *conn, PQnoticeReceiver proc, void *arg)
 
PQnoticeProcessor PQsetNoticeProcessor (PGconn *conn, PQnoticeProcessor proc, void *arg)
 
bool pqGetHomeDirectory (char *buf, int bufsize)
 
pgthreadlock_t PQregisterThreadLock (pgthreadlock_t newhandler)
 

Variables

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

Macro Definition Documentation

◆ DefaultAuthtype

#define DefaultAuthtype   ""

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

◆ DefaultChannelBinding

#define DefaultChannelBinding   "disable"

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

Referenced by connectOptions2().

◆ DefaultGSSMode

#define DefaultGSSMode   "disable"

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

Referenced by connectOptions2().

◆ DefaultHost

#define DefaultHost   "localhost"

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

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

◆ DefaultOption

#define DefaultOption   ""

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

◆ DefaultSSLMode

#define DefaultSSLMode   "disable"

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

Referenced by connectOptions2().

◆ DefaultTargetSessionAttrs

#define DefaultTargetSessionAttrs   "any"

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

◆ DefaultTty

#define DefaultTty   ""

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

◆ ERRCODE_APPNAME_UNKNOWN

#define ERRCODE_APPNAME_UNKNOWN   "42704"

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

Referenced by PQconnectPoll().

◆ ERRCODE_CANNOT_CONNECT_NOW

#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"

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

Referenced by internal_ping(), and ProcessStartupPacket().

◆ ERRCODE_INVALID_PASSWORD

#define ERRCODE_INVALID_PASSWORD   "28P01"

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

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

◆ LINELEN

#define LINELEN   NAMEDATALEN*5

Referenced by passwordFromFile().

◆ MAXBUFSIZE

#define MAXBUFSIZE   256

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

Referenced by parseServiceFile().

◆ PGPASSFILE

#define PGPASSFILE   ".pgpass"

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

Referenced by connectOptions2().

Typedef Documentation

◆ internalPQconninfoOption

Function Documentation

◆ closePGconn()

static void closePGconn ( PGconn conn)
static

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

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

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

4155 {
4156  /*
4157  * If possible, send Terminate message to close the connection politely.
4158  */
4159  sendTerminateConn(conn);
4160 
4161  /*
4162  * Must reset the blocking status so a possible reconnect will work.
4163  *
4164  * Don't call PQsetnonblocking() because it will fail if it's unable to
4165  * flush the connection.
4166  */
4167  conn->nonblocking = false;
4168 
4169  /*
4170  * Close the connection, reset all transient state, flush I/O buffers.
4171  */
4172  pqDropConnection(conn, true);
4173  conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
4174  conn->asyncStatus = PGASYNC_IDLE;
4175  conn->xactStatus = PQTRANS_IDLE;
4176  pqClearAsyncResult(conn); /* deallocate result */
4178  release_conn_addrinfo(conn);
4179 
4180  /* Reset all state obtained from server, too */
4181  pqDropServerData(conn);
4182 }
static void release_conn_addrinfo(PGconn *conn)
Definition: fe-connect.c:4112
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:458
static void sendTerminateConn(PGconn *conn)
Definition: fe-connect.c:4127
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:389
static void pqDropServerData(PGconn *conn)
Definition: fe-connect.c:547
PQExpBufferData errorMessage
Definition: libpq-int.h:526
ConnStatusType status
Definition: libpq-int.h:388
bool nonblocking
Definition: libpq-int.h:395
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:749
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148
PGTransactionStatusType xactStatus
Definition: libpq-int.h:390

◆ connectDBComplete()

static int connectDBComplete ( PGconn conn)
static

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

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

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

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

◆ connectDBStart()

static int connectDBStart ( PGconn conn)
static

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

References CONNECTION_BAD, CONNECTION_NEEDED, pg_conn::errorMessage, pg_conn::gssencmode, 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(), printfPQExpBuffer(), resetPQExpBuffer(), pg_conn::status, pg_conn::try_next_addr, pg_conn::try_next_host, and pg_conn::whichhost.

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

1998 {
1999  if (!conn)
2000  return 0;
2001 
2002  if (!conn->options_valid)
2003  goto connect_errReturn;
2004 
2005  /*
2006  * Check for bad linking to backend-internal versions of src/common
2007  * functions (see comments in link-canary.c for the reason we need this).
2008  * Nobody but developers should see this message, so we don't bother
2009  * translating it.
2010  */
2012  {
2014  "libpq is incorrectly linked to backend functions\n");
2015  goto connect_errReturn;
2016  }
2017 
2018  /* Ensure our buffers are empty */
2019  conn->inStart = conn->inCursor = conn->inEnd = 0;
2020  conn->outCount = 0;
2021 
2022  /*
2023  * Ensure errorMessage is empty, too. PQconnectPoll will append messages
2024  * to it in the process of scanning for a working server. Thus, if we
2025  * fail to connect to multiple hosts, the final error message will include
2026  * details about each failure.
2027  */
2029 
2030 #ifdef ENABLE_GSS
2031  if (conn->gssencmode[0] == 'd') /* "disable" */
2032  conn->try_gss = false;
2033 #endif
2034 
2035  /*
2036  * Set up to try to connect to the first host. (Setting whichhost = -1 is
2037  * a bit of a cheat, but PQconnectPoll will advance it to 0 before
2038  * anything else looks at it.)
2039  */
2040  conn->whichhost = -1;
2041  conn->try_next_addr = false;
2042  conn->try_next_host = true;
2043  conn->status = CONNECTION_NEEDED;
2044 
2045  /*
2046  * The code for processing CONNECTION_NEEDED state is in PQconnectPoll(),
2047  * so that it can easily be re-executed if needed again during the
2048  * asynchronous startup process. However, we must run it once here,
2049  * because callers expect a success return from this routine to mean that
2050  * we are in PGRES_POLLING_WRITING connection state.
2051  */
2052  if (PQconnectPoll(conn) == PGRES_POLLING_WRITING)
2053  return 1;
2054 
2055 connect_errReturn:
2056 
2057  /*
2058  * If we managed to open a socket, close it immediately rather than
2059  * waiting till PQfinish. (The application cannot have gotten the socket
2060  * from PQsocket yet, so this doesn't risk breaking anything.)
2061  */
2062  pqDropConnection(conn, true);
2063  conn->status = CONNECTION_BAD;
2064  return 0;
2065 }
char * gssencmode
Definition: libpq-int.h:366
int inEnd
Definition: libpq-int.h:448
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
int inStart
Definition: libpq-int.h:446
int outCount
Definition: libpq-int.h:453
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:458
bool try_next_host
Definition: libpq-int.h:425
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
Definition: fe-connect.c:2258
PQExpBufferData errorMessage
Definition: libpq-int.h:526
bool try_next_addr
Definition: libpq-int.h:424
bool options_valid
Definition: libpq-int.h:394
ConnStatusType status
Definition: libpq-int.h:388
int inCursor
Definition: libpq-int.h:447
void resetPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:148
int whichhost
Definition: libpq-int.h:405

◆ connectFailureMessage()

static void connectFailureMessage ( PGconn conn,
int  errorno 
)
static

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

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

Referenced by PQconnectPoll().

1665 {
1666  char sebuf[PG_STRERROR_R_BUFLEN];
1667 
1668 #ifdef HAVE_UNIX_SOCKETS
1669  if (IS_AF_UNIX(conn->raddr.addr.ss_family))
1670  {
1671  char service[NI_MAXHOST];
1672 
1673  pg_getnameinfo_all(&conn->raddr.addr, conn->raddr.salen,
1674  NULL, 0,
1675  service, sizeof(service),
1676  NI_NUMERICSERV);
1678  libpq_gettext("could not connect to server: %s\n"
1679  "\tIs the server running locally and accepting\n"
1680  "\tconnections on Unix domain socket \"%s\"?\n"),
1681  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
1682  service);
1683  }
1684  else
1685 #endif /* HAVE_UNIX_SOCKETS */
1686  {
1687  char host_addr[NI_MAXHOST];
1688  const char *displayed_host;
1689  const char *displayed_port;
1690 
1691  /*
1692  * Optionally display the network address with the hostname. This is
1693  * useful to distinguish between IPv4 and IPv6 connections.
1694  */
1695  getHostaddr(conn, host_addr, NI_MAXHOST);
1696 
1697  /* To which host and port were we actually connecting? */
1698  if (conn->connhost[conn->whichhost].type == CHT_HOST_ADDRESS)
1699  displayed_host = conn->connhost[conn->whichhost].hostaddr;
1700  else
1701  displayed_host = conn->connhost[conn->whichhost].host;
1702  displayed_port = conn->connhost[conn->whichhost].port;
1703  if (displayed_port == NULL || displayed_port[0] == '\0')
1704  displayed_port = DEF_PGPORT_STR;
1705 
1706  /*
1707  * If the user did not supply an IP address using 'hostaddr', and
1708  * 'host' was missing or does not match our lookup, display the
1709  * looked-up IP address.
1710  */
1711  if (conn->connhost[conn->whichhost].type != CHT_HOST_ADDRESS &&
1712  strlen(host_addr) > 0 &&
1713  strcmp(displayed_host, host_addr) != 0)
1715  libpq_gettext("could not connect to server: %s\n"
1716  "\tIs the server running on host \"%s\" (%s) and accepting\n"
1717  "\tTCP/IP connections on port %s?\n"),
1718  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
1719  displayed_host, host_addr,
1720  displayed_port);
1721  else
1723  libpq_gettext("could not connect to server: %s\n"
1724  "\tIs the server running on host \"%s\" and accepting\n"
1725  "\tTCP/IP connections on port %s?\n"),
1726  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)),
1727  displayed_host,
1728  displayed_port);
1729  }
1730 }
#define PG_STRERROR_R_BUFLEN
Definition: port.h:211
char * host
Definition: libpq-int.h:312
struct sockaddr_storage addr
Definition: pqcomm.h:64
pg_conn_host_type type
Definition: libpq-int.h:311
static void getHostaddr(PGconn *conn, char *host_addr, int host_addr_len)
Definition: fe-connect.c:1632
#define SOCK_STRERROR
Definition: libpq-int.h:819
#define NI_MAXHOST
Definition: getaddrinfo.h:88
#define IS_AF_UNIX(fam)
Definition: ip.h:24
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
char * hostaddr
Definition: libpq-int.h:313
pg_conn_host * connhost
Definition: libpq-int.h:406
ACCEPT_TYPE_ARG3 salen
Definition: pqcomm.h:65
SockAddr raddr
Definition: libpq-int.h:413
PQExpBufferData errorMessage
Definition: libpq-int.h:526
#define NI_NUMERICSERV
Definition: getaddrinfo.h:81
int pg_getnameinfo_all(const struct sockaddr_storage *addr, int salen, char *node, int nodelen, char *service, int servicelen, int flags)
Definition: ip.c:122
char * port
Definition: libpq-int.h:314
int whichhost
Definition: libpq-int.h:405
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ connectNoDelay()

static int connectNoDelay ( PGconn conn)
static

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

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

Referenced by PQconnectPoll().

1606 {
1607 #ifdef TCP_NODELAY
1608  int on = 1;
1609 
1610  if (setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY,
1611  (char *) &on,
1612  sizeof(on)) < 0)
1613  {
1614  char sebuf[PG_STRERROR_R_BUFLEN];
1615 
1617  libpq_gettext("could not set socket to TCP no delay mode: %s\n"),
1618  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
1619  return 0;
1620  }
1621 #endif
1622 
1623  return 1;
1624 }
#define PG_STRERROR_R_BUFLEN
Definition: port.h:211
#define SOCK_STRERROR
Definition: libpq-int.h:819
#define SOCK_ERRNO
Definition: libpq-int.h:818
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
pgsocket sock
Definition: libpq-int.h:410
PQExpBufferData errorMessage
Definition: libpq-int.h:526
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ connectOptions1()

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

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

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

Referenced by PQconnectStart(), and PQsetdbLogin().

909 {
910  PQconninfoOption *connOptions;
911 
912  /*
913  * Parse the conninfo string
914  */
915  connOptions = parse_connection_string(conninfo, &conn->errorMessage, true);
916  if (connOptions == NULL)
917  {
918  conn->status = CONNECTION_BAD;
919  /* errorMessage is already set */
920  return false;
921  }
922 
923  /*
924  * Move option values into conn structure
925  */
926  if (!fillPGconn(conn, connOptions))
927  {
928  conn->status = CONNECTION_BAD;
929  PQconninfoFree(connOptions);
930  return false;
931  }
932 
933  /*
934  * Free the option info - all is in conn now
935  */
936  PQconninfoFree(connOptions);
937 
938  return true;
939 }
static PQconninfoOption * parse_connection_string(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5355
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6523
PQExpBufferData errorMessage
Definition: libpq-int.h:526
static bool fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
Definition: fe-connect.c:866
ConnStatusType status
Definition: libpq-int.h:388

◆ connectOptions2()

static bool connectOptions2 ( PGconn conn)
static

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

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

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

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

◆ conninfo_add_defaults()

static bool conninfo_add_defaults ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

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

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

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

5752 {
5754  char *tmp;
5755 
5756  /*
5757  * If there's a service spec, use it to obtain any not-explicitly-given
5758  * parameters. Ignore error if no error message buffer is passed because
5759  * there is no way to pass back the failure message.
5760  */
5761  if (parseServiceInfo(options, errorMessage) != 0 && errorMessage)
5762  return false;
5763 
5764  /*
5765  * Get the fallback resources for parameters not specified in the conninfo
5766  * string nor the service.
5767  */
5768  for (option = options; option->keyword != NULL; option++)
5769  {
5770  if (option->val != NULL)
5771  continue; /* Value was in conninfo or service */
5772 
5773  /*
5774  * Try to get the environment variable fallback
5775  */
5776  if (option->envvar != NULL)
5777  {
5778  if ((tmp = getenv(option->envvar)) != NULL)
5779  {
5780  option->val = strdup(tmp);
5781  if (!option->val)
5782  {
5783  if (errorMessage)
5784  printfPQExpBuffer(errorMessage,
5785  libpq_gettext("out of memory\n"));
5786  return false;
5787  }
5788  continue;
5789  }
5790  }
5791 
5792  /*
5793  * Interpret the deprecated PGREQUIRESSL environment variable. Per
5794  * tradition, translate values starting with "1" to sslmode=require,
5795  * and ignore other values. Given both PGREQUIRESSL=1 and PGSSLMODE,
5796  * PGSSLMODE takes precedence; the opposite was true before v9.3.
5797  */
5798  if (strcmp(option->keyword, "sslmode") == 0)
5799  {
5800  const char *requiresslenv = getenv("PGREQUIRESSL");
5801 
5802  if (requiresslenv != NULL && requiresslenv[0] == '1')
5803  {
5804  option->val = strdup("require");
5805  if (!option->val)
5806  {
5807  if (errorMessage)
5808  printfPQExpBuffer(errorMessage,
5809  libpq_gettext("out of memory\n"));
5810  return false;
5811  }
5812  continue;
5813  }
5814  }
5815 
5816  /*
5817  * No environment variable specified or the variable isn't set - try
5818  * compiled-in default
5819  */
5820  if (option->compiled != NULL)
5821  {
5822  option->val = strdup(option->compiled);
5823  if (!option->val)
5824  {
5825  if (errorMessage)
5826  printfPQExpBuffer(errorMessage,
5827  libpq_gettext("out of memory\n"));
5828  return false;
5829  }
5830  continue;
5831  }
5832 
5833  /*
5834  * Special handling for "user" option. Note that if pg_fe_getauthname
5835  * fails, we just leave the value as NULL; there's no need for this to
5836  * be an error condition if the caller provides a user name. The only
5837  * reason we do this now at all is so that callers of PQconndefaults
5838  * will see a correct default (barring error, of course).
5839  */
5840  if (strcmp(option->keyword, "user") == 0)
5841  {
5842  option->val = pg_fe_getauthname(NULL);
5843  continue;
5844  }
5845  }
5846 
5847  return true;
5848 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
char * pg_fe_getauthname(PQExpBuffer errorMessage)
Definition: fe-auth.c:1073
static int parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5046
#define libpq_gettext(x)
Definition: libpq-int.h:805

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

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

Referenced by PQconnectStartParams().

5590 {
5592  PQconninfoOption *dbname_options = NULL;
5594  int i = 0;
5595 
5596  /*
5597  * If expand_dbname is non-zero, check keyword "dbname" to see if val is
5598  * actually a recognized connection string.
5599  */
5600  while (expand_dbname && keywords[i])
5601  {
5602  const char *pname = keywords[i];
5603  const char *pvalue = values[i];
5604 
5605  /* first find "dbname" if any */
5606  if (strcmp(pname, "dbname") == 0 && pvalue)
5607  {
5608  /*
5609  * If value is a connection string, parse it, but do not use
5610  * defaults here -- those get picked up later. We only want to
5611  * override for those parameters actually passed.
5612  */
5613  if (recognized_connection_string(pvalue))
5614  {
5615  dbname_options = parse_connection_string(pvalue, errorMessage, false);
5616  if (dbname_options == NULL)
5617  return NULL;
5618  }
5619  break;
5620  }
5621  ++i;
5622  }
5623 
5624  /* Make a working copy of PQconninfoOptions */
5625  options = conninfo_init(errorMessage);
5626  if (options == NULL)
5627  {
5628  PQconninfoFree(dbname_options);
5629  return NULL;
5630  }
5631 
5632  /* Parse the keywords/values arrays */
5633  i = 0;
5634  while (keywords[i])
5635  {
5636  const char *pname = keywords[i];
5637  const char *pvalue = values[i];
5638 
5639  if (pvalue != NULL && pvalue[0] != '\0')
5640  {
5641  /* Search for the param record */
5642  for (option = options; option->keyword != NULL; option++)
5643  {
5644  if (strcmp(option->keyword, pname) == 0)
5645  break;
5646  }
5647 
5648  /* Check for invalid connection option */
5649  if (option->keyword == NULL)
5650  {
5651  printfPQExpBuffer(errorMessage,
5652  libpq_gettext("invalid connection option \"%s\"\n"),
5653  pname);
5654  PQconninfoFree(options);
5655  PQconninfoFree(dbname_options);
5656  return NULL;
5657  }
5658 
5659  /*
5660  * If we are on the first dbname parameter, and we have a parsed
5661  * connection string, copy those parameters across, overriding any
5662  * existing previous settings.
5663  */
5664  if (strcmp(pname, "dbname") == 0 && dbname_options)
5665  {
5666  PQconninfoOption *str_option;
5667 
5668  for (str_option = dbname_options; str_option->keyword != NULL; str_option++)
5669  {
5670  if (str_option->val != NULL)
5671  {
5672  int k;
5673 
5674  for (k = 0; options[k].keyword; k++)
5675  {
5676  if (strcmp(options[k].keyword, str_option->keyword) == 0)
5677  {
5678  if (options[k].val)
5679  free(options[k].val);
5680  options[k].val = strdup(str_option->val);
5681  if (!options[k].val)
5682  {
5683  printfPQExpBuffer(errorMessage,
5684  libpq_gettext("out of memory\n"));
5685  PQconninfoFree(options);
5686  PQconninfoFree(dbname_options);
5687  return NULL;
5688  }
5689  break;
5690  }
5691  }
5692  }
5693  }
5694 
5695  /*
5696  * Forget the parsed connection string, so that any subsequent
5697  * dbname parameters will not be expanded.
5698  */
5699  PQconninfoFree(dbname_options);
5700  dbname_options = NULL;
5701  }
5702  else
5703  {
5704  /*
5705  * Store the value, overriding previous settings
5706  */
5707  if (option->val)
5708  free(option->val);
5709  option->val = strdup(pvalue);
5710  if (!option->val)
5711  {
5712  printfPQExpBuffer(errorMessage,
5713  libpq_gettext("out of memory\n"));
5714  PQconninfoFree(options);
5715  PQconninfoFree(dbname_options);
5716  return NULL;
5717  }
5718  }
5719  }
5720  ++i;
5721  }
5722  PQconninfoFree(dbname_options);
5723 
5724  /*
5725  * Add in defaults if the caller wants that.
5726  */
5727  if (use_defaults)
5728  {
5729  if (!conninfo_add_defaults(options, errorMessage))
5730  {
5731  PQconninfoFree(options);
5732  return NULL;
5733  }
5734  }
5735 
5736  return options;
5737 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5315
static PQconninfoOption * parse_connection_string(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5355
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6523
static char ** options
static bool recognized_connection_string(const char *connstr)
Definition: fe-connect.c:5398
#define free(a)
Definition: header.h:65
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5751
static Datum values[MAXATTR]
Definition: bootstrap.c:167
int i
long val
Definition: informix.c:664
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ conninfo_find()

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

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

References _PQconninfoOption::keyword.

Referenced by conninfo_getval(), and conninfo_storeval().

6465 {
6467 
6468  for (option = connOptions; option->keyword != NULL; option++)
6469  {
6470  if (strcmp(option->keyword, keyword) == 0)
6471  return option;
6472  }
6473 
6474  return NULL;
6475 }

◆ conninfo_getval()

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

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

References conninfo_find(), and _PQconninfoOption::val.

Referenced by fillPGconn(), and parseServiceInfo().

6375 {
6377 
6378  option = conninfo_find(connOptions, keyword);
6379 
6380  return option ? option->val : NULL;
6381 }
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6464

◆ conninfo_init()

static PQconninfoOption * conninfo_init ( PQExpBuffer  errorMessage)
static

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

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

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

5316 {
5318  PQconninfoOption *opt_dest;
5319  const internalPQconninfoOption *cur_opt;
5320 
5321  /*
5322  * Get enough memory for all options in PQconninfoOptions, even if some
5323  * end up being filtered out.
5324  */
5325  options = (PQconninfoOption *) malloc(sizeof(PQconninfoOption) * sizeof(PQconninfoOptions) / sizeof(PQconninfoOptions[0]));
5326  if (options == NULL)
5327  {
5328  printfPQExpBuffer(errorMessage,
5329  libpq_gettext("out of memory\n"));
5330  return NULL;
5331  }
5332  opt_dest = options;
5333 
5334  for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++)
5335  {
5336  /* Only copy the public part of the struct, not the full internal */
5337  memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption));
5338  opt_dest++;
5339  }
5340  MemSet(opt_dest, 0, sizeof(PQconninfoOption));
5341 
5342  return options;
5343 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
#define MemSet(start, val, len)
Definition: c.h:971
#define malloc(a)
Definition: header.h:50
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:193
static char ** options
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ conninfo_parse()

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

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

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

Referenced by parse_connection_string().

5411 {
5412  char *pname;
5413  char *pval;
5414  char *buf;
5415  char *cp;
5416  char *cp2;
5418 
5419  /* Make a working copy of PQconninfoOptions */
5420  options = conninfo_init(errorMessage);
5421  if (options == NULL)
5422  return NULL;
5423 
5424  /* Need a modifiable copy of the input string */
5425  if ((buf = strdup(conninfo)) == NULL)
5426  {
5427  printfPQExpBuffer(errorMessage,
5428  libpq_gettext("out of memory\n"));
5429  PQconninfoFree(options);
5430  return NULL;
5431  }
5432  cp = buf;
5433 
5434  while (*cp)
5435  {
5436  /* Skip blanks before the parameter name */
5437  if (isspace((unsigned char) *cp))
5438  {
5439  cp++;
5440  continue;
5441  }
5442 
5443  /* Get the parameter name */
5444  pname = cp;
5445  while (*cp)
5446  {
5447  if (*cp == '=')
5448  break;
5449  if (isspace((unsigned char) *cp))
5450  {
5451  *cp++ = '\0';
5452  while (*cp)
5453  {
5454  if (!isspace((unsigned char) *cp))
5455  break;
5456  cp++;
5457  }
5458  break;
5459  }
5460  cp++;
5461  }
5462 
5463  /* Check that there is a following '=' */
5464  if (*cp != '=')
5465  {
5466  printfPQExpBuffer(errorMessage,
5467  libpq_gettext("missing \"=\" after \"%s\" in connection info string\n"),
5468  pname);
5469  PQconninfoFree(options);
5470  free(buf);
5471  return NULL;
5472  }
5473  *cp++ = '\0';
5474 
5475  /* Skip blanks after the '=' */
5476  while (*cp)
5477  {
5478  if (!isspace((unsigned char) *cp))
5479  break;
5480  cp++;
5481  }
5482 
5483  /* Get the parameter value */
5484  pval = cp;
5485 
5486  if (*cp != '\'')
5487  {
5488  cp2 = pval;
5489  while (*cp)
5490  {
5491  if (isspace((unsigned char) *cp))
5492  {
5493  *cp++ = '\0';
5494  break;
5495  }
5496  if (*cp == '\\')
5497  {
5498  cp++;
5499  if (*cp != '\0')
5500  *cp2++ = *cp++;
5501  }
5502  else
5503  *cp2++ = *cp++;
5504  }
5505  *cp2 = '\0';
5506  }
5507  else
5508  {
5509  cp2 = pval;
5510  cp++;
5511  for (;;)
5512  {
5513  if (*cp == '\0')
5514  {
5515  printfPQExpBuffer(errorMessage,
5516  libpq_gettext("unterminated quoted string in connection info string\n"));
5517  PQconninfoFree(options);
5518  free(buf);
5519  return NULL;
5520  }
5521  if (*cp == '\\')
5522  {
5523  cp++;
5524  if (*cp != '\0')
5525  *cp2++ = *cp++;
5526  continue;
5527  }
5528  if (*cp == '\'')
5529  {
5530  *cp2 = '\0';
5531  cp++;
5532  break;
5533  }
5534  *cp2++ = *cp++;
5535  }
5536  }
5537 
5538  /*
5539  * Now that we have the name and the value, store the record.
5540  */
5541  if (!conninfo_storeval(options, pname, pval, errorMessage, false, false))
5542  {
5543  PQconninfoFree(options);
5544  free(buf);
5545  return NULL;
5546  }
5547  }
5548 
5549  /* Done with the modifiable input string */
5550  free(buf);
5551 
5552  /*
5553  * Add in defaults if the caller wants that.
5554  */
5555  if (use_defaults)
5556  {
5557  if (!conninfo_add_defaults(options, errorMessage))
5558  {
5559  PQconninfoFree(options);
5560  return NULL;
5561  }
5562  }
5563 
5564  return options;
5565 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
static PQconninfoOption * conninfo_storeval(PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode)
Definition: fe-connect.c:6399
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5315
static char * buf
Definition: pg_test_fsync.c:67
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6523
static char ** options
#define free(a)
Definition: header.h:65
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5751
#define libpq_gettext(x)
Definition: libpq-int.h:805

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

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

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

6403 {
6405  char *value_copy;
6406 
6407  /*
6408  * For backwards compatibility, requiressl=1 gets translated to
6409  * sslmode=require, and requiressl=0 gets translated to sslmode=prefer
6410  * (which is the default for sslmode).
6411  */
6412  if (strcmp(keyword, "requiressl") == 0)
6413  {
6414  keyword = "sslmode";
6415  if (value[0] == '1')
6416  value = "require";
6417  else
6418  value = "prefer";
6419  }
6420 
6421  option = conninfo_find(connOptions, keyword);
6422  if (option == NULL)
6423  {
6424  if (!ignoreMissing)
6425  printfPQExpBuffer(errorMessage,
6426  libpq_gettext("invalid connection option \"%s\"\n"),
6427  keyword);
6428  return NULL;
6429  }
6430 
6431  if (uri_decode)
6432  {
6433  value_copy = conninfo_uri_decode(value, errorMessage);
6434  if (value_copy == NULL)
6435  /* conninfo_uri_decode already set an error message */
6436  return NULL;
6437  }
6438  else
6439  {
6440  value_copy = strdup(value);
6441  if (value_copy == NULL)
6442  {
6443  printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
6444  return NULL;
6445  }
6446  }
6447 
6448  if (option->val)
6449  free(option->val);
6450  option->val = value_copy;
6451 
6452  return option;
6453 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6464
static char * conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
Definition: fe-connect.c:6284
static struct @143 value
#define free(a)
Definition: header.h:65
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ conninfo_uri_decode()

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

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

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

Referenced by conninfo_storeval(), and conninfo_uri_parse_params().

6285 {
6286  char *buf;
6287  char *p;
6288  const char *q = str;
6289 
6290  buf = malloc(strlen(str) + 1);
6291  if (buf == NULL)
6292  {
6293  printfPQExpBuffer(errorMessage, libpq_gettext("out of memory\n"));
6294  return NULL;
6295  }
6296  p = buf;
6297 
6298  for (;;)
6299  {
6300  if (*q != '%')
6301  {
6302  /* copy and check for NUL terminator */
6303  if (!(*(p++) = *(q++)))
6304  break;
6305  }
6306  else
6307  {
6308  int hi;
6309  int lo;
6310  int c;
6311 
6312  ++q; /* skip the percent sign itself */
6313 
6314  /*
6315  * Possible EOL will be caught by the first call to
6316  * get_hexdigit(), so we never dereference an invalid q pointer.
6317  */
6318  if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo)))
6319  {
6320  printfPQExpBuffer(errorMessage,
6321  libpq_gettext("invalid percent-encoded token: \"%s\"\n"),
6322  str);
6323  free(buf);
6324  return NULL;
6325  }
6326 
6327  c = (hi << 4) | lo;
6328  if (c == 0)
6329  {
6330  printfPQExpBuffer(errorMessage,
6331  libpq_gettext("forbidden value %%00 in percent-encoded value: \"%s\"\n"),
6332  str);
6333  free(buf);
6334  return NULL;
6335  }
6336  *(p++) = c;
6337  }
6338  }
6339 
6340  return buf;
6341 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
#define malloc(a)
Definition: header.h:50
char * c
static char * buf
Definition: pg_test_fsync.c:67
#define free(a)
Definition: header.h:65
static bool get_hexdigit(char digit, int *value)
Definition: fe-connect.c:6352
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ conninfo_uri_parse()

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

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

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

Referenced by parse_connection_string().

5858 {
5860 
5861  /* Make a working copy of PQconninfoOptions */
5862  options = conninfo_init(errorMessage);
5863  if (options == NULL)
5864  return NULL;
5865 
5866  if (!conninfo_uri_parse_options(options, uri, errorMessage))
5867  {
5868  PQconninfoFree(options);
5869  return NULL;
5870  }
5871 
5872  /*
5873  * Add in defaults if the caller wants that.
5874  */
5875  if (use_defaults)
5876  {
5877  if (!conninfo_add_defaults(options, errorMessage))
5878  {
5879  PQconninfoFree(options);
5880  return NULL;
5881  }
5882  }
5883 
5884  return options;
5885 }
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5315
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6523
static bool conninfo_uri_parse_options(PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage)
Definition: fe-connect.c:5909
static char ** options
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5751

◆ conninfo_uri_parse_options()

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

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

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

Referenced by conninfo_uri_parse().

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

◆ conninfo_uri_parse_params()

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

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

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

Referenced by conninfo_uri_parse_options().

6156 {
6157  while (*params)
6158  {
6159  char *keyword = params;
6160  char *value = NULL;
6161  char *p = params;
6162  bool malloced = false;
6163 
6164  /*
6165  * Scan the params string for '=' and '&', marking the end of keyword
6166  * and value respectively.
6167  */
6168  for (;;)
6169  {
6170  if (*p == '=')
6171  {
6172  /* Was there '=' already? */
6173  if (value != NULL)
6174  {
6175  printfPQExpBuffer(errorMessage,
6176  libpq_gettext("extra key/value separator \"=\" in URI query parameter: \"%s\"\n"),
6177  keyword);
6178  return false;
6179  }
6180  /* Cut off keyword, advance to value */
6181  *p++ = '\0';
6182  value = p;
6183  }
6184  else if (*p == '&' || *p == '\0')
6185  {
6186  /*
6187  * If not at the end, cut off value and advance; leave p
6188  * pointing to start of the next parameter, if any.
6189  */
6190  if (*p != '\0')
6191  *p++ = '\0';
6192  /* Was there '=' at all? */
6193  if (value == NULL)
6194  {
6195  printfPQExpBuffer(errorMessage,
6196  libpq_gettext("missing key/value separator \"=\" in URI query parameter: \"%s\"\n"),
6197  keyword);
6198  return false;
6199  }
6200  /* Got keyword and value, go process them. */
6201  break;
6202  }
6203  else
6204  ++p; /* Advance over all other bytes. */
6205  }
6206 
6207  keyword = conninfo_uri_decode(keyword, errorMessage);
6208  if (keyword == NULL)
6209  {
6210  /* conninfo_uri_decode already set an error message */
6211  return false;
6212  }
6213  value = conninfo_uri_decode(value, errorMessage);
6214  if (value == NULL)
6215  {
6216  /* conninfo_uri_decode already set an error message */
6217  free(keyword);
6218  return false;
6219  }
6220  malloced = true;
6221 
6222  /*
6223  * Special keyword handling for improved JDBC compatibility.
6224  */
6225  if (strcmp(keyword, "ssl") == 0 &&
6226  strcmp(value, "true") == 0)
6227  {
6228  free(keyword);
6229  free(value);
6230  malloced = false;
6231 
6232  keyword = "sslmode";
6233  value = "require";
6234  }
6235 
6236  /*
6237  * Store the value if the corresponding option exists; ignore
6238  * otherwise. At this point both keyword and value are not
6239  * URI-encoded.
6240  */
6241  if (!conninfo_storeval(connOptions, keyword, value,
6242  errorMessage, true, false))
6243  {
6244  /* Insert generic message if conninfo_storeval didn't give one. */
6245  if (errorMessage->len == 0)
6246  printfPQExpBuffer(errorMessage,
6247  libpq_gettext("invalid URI query parameter: \"%s\"\n"),
6248  keyword);
6249  /* And fail. */
6250  if (malloced)
6251  {
6252  free(keyword);
6253  free(value);
6254  }
6255  return false;
6256  }
6257 
6258  if (malloced)
6259  {
6260  free(keyword);
6261  free(value);
6262  }
6263 
6264  /* Proceed to next key=value pair, if any */
6265  params = p;
6266  }
6267 
6268  return true;
6269 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
static PQconninfoOption * conninfo_storeval(PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode)
Definition: fe-connect.c:6399
static char * conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
Definition: fe-connect.c:6284
static struct @143 value
#define free(a)
Definition: header.h:65
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ count_comma_separated_elems()

static int count_comma_separated_elems ( const char *  input)
static

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

Referenced by connectOptions2().

946 {
947  int n;
948 
949  n = 1;
950  for (; *input != '\0'; input++)
951  {
952  if (*input == ',')
953  n++;
954  }
955 
956  return n;
957 }

◆ default_threadlock()

static void default_threadlock ( int  acquire)
static

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

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

Referenced by PQregisterThreadLock().

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

◆ defaultNoticeProcessor()

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

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

References fprintf.

Referenced by makeEmptyPGconn().

6906 {
6907  (void) arg; /* not used */
6908  /* Note: we expect the supplied string to end with a newline already. */
6909  fprintf(stderr, "%s", message);
6910 }
#define fprintf
Definition: port.h:197
void * arg

◆ defaultNoticeReceiver()

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

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

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

Referenced by makeEmptyPGconn().

6891 {
6892  (void) arg; /* not used */
6893  if (res->noticeHooks.noticeProc != NULL)
6895  PQresultErrorMessage(res));
6896 }
PGNoticeHooks noticeHooks
Definition: libpq-int.h:186
void * noticeProcArg
Definition: libpq-int.h:155
PQnoticeProcessor noticeProc
Definition: libpq-int.h:154
char * PQresultErrorMessage(const PGresult *res)
Definition: fe-exec.c:2708
void * arg

◆ fillPGconn()

static bool fillPGconn ( PGconn conn,
PQconninfoOption connOptions 
)
static

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

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

Referenced by connectOptions1(), and PQconnectStartParams().

867 {
869 
870  for (option = PQconninfoOptions; option->keyword; option++)
871  {
872  if (option->connofs >= 0)
873  {
874  const char *tmp = conninfo_getval(connOptions, option->keyword);
875 
876  if (tmp)
877  {
878  char **connmember = (char **) ((char *) conn + option->connofs);
879 
880  if (*connmember)
881  free(*connmember);
882  *connmember = strdup(tmp);
883  if (*connmember == NULL)
884  {
886  libpq_gettext("out of memory\n"));
887  return false;
888  }
889  }
890  }
891  }
892 
893  return true;
894 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:193
PQExpBufferData errorMessage
Definition: libpq-int.h:526
#define free(a)
Definition: header.h:65
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6373
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ freePGconn()

static void freePGconn ( PGconn conn)
static

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

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

Referenced by makeEmptyPGconn(), and PQfinish().

3958 {
3959  int i;
3960 
3961  /* let any event procs clean up their state data */
3962  for (i = 0; i < conn->nEvents; i++)
3963  {
3964  PGEventConnDestroy evt;
3965 
3966  evt.conn = conn;
3967  (void) conn->events[i].proc(PGEVT_CONNDESTROY, &evt,
3968  conn->events[i].passThrough);
3969  free(conn->events[i].name);
3970  }
3971 
3972  /* clean up pg_conn_host structures */
3973  if (conn->connhost != NULL)
3974  {
3975  for (i = 0; i < conn->nconnhost; ++i)
3976  {
3977  if (conn->connhost[i].host != NULL)
3978  free(conn->connhost[i].host);
3979  if (conn->connhost[i].hostaddr != NULL)
3980  free(conn->connhost[i].hostaddr);
3981  if (conn->connhost[i].port != NULL)
3982  free(conn->connhost[i].port);
3983  if (conn->connhost[i].password != NULL)
3984  {
3985  explicit_bzero(conn->connhost[i].password, strlen(conn->connhost[i].password));
3986  free(conn->connhost[i].password);
3987  }
3988  }
3989  free(conn->connhost);
3990  }
3991 
3992  if (conn->client_encoding_initial)
3994  if (conn->events)
3995  free(conn->events);
3996  if (conn->pghost)
3997  free(conn->pghost);
3998  if (conn->pghostaddr)
3999  free(conn->pghostaddr);
4000  if (conn->pgport)
4001  free(conn->pgport);
4002  if (conn->pgtty)
4003  free(conn->pgtty);
4004  if (conn->connect_timeout)
4005  free(conn->connect_timeout);
4006  if (conn->pgtcp_user_timeout)
4007  free(conn->pgtcp_user_timeout);
4008  if (conn->pgoptions)
4009  free(conn->pgoptions);
4010  if (conn->appname)
4011  free(conn->appname);
4012  if (conn->fbappname)
4013  free(conn->fbappname);
4014  if (conn->dbName)
4015  free(conn->dbName);
4016  if (conn->replication)
4017  free(conn->replication);
4018  if (conn->pguser)
4019  free(conn->pguser);
4020  if (conn->pgpass)
4021  {
4022  explicit_bzero(conn->pgpass, strlen(conn->pgpass));
4023  free(conn->pgpass);
4024  }
4025  if (conn->pgpassfile)
4026  free(conn->pgpassfile);
4027  if (conn->channel_binding)
4028  free(conn->channel_binding);
4029  if (conn->keepalives)
4030  free(conn->keepalives);
4031  if (conn->keepalives_idle)
4032  free(conn->keepalives_idle);
4033  if (conn->keepalives_interval)
4034  free(conn->keepalives_interval);
4035  if (conn->keepalives_count)
4036  free(conn->keepalives_count);
4037  if (conn->sslmode)
4038  free(conn->sslmode);
4039  if (conn->sslcert)
4040  free(conn->sslcert);
4041  if (conn->sslkey)
4042  free(conn->sslkey);
4043  if (conn->sslpassword)
4044  {
4045  explicit_bzero(conn->sslpassword, strlen(conn->sslpassword));
4046  free(conn->sslpassword);
4047  }
4048  if (conn->sslrootcert)
4049  free(conn->sslrootcert);
4050  if (conn->sslcrl)
4051  free(conn->sslcrl);
4052  if (conn->sslcompression)
4053  free(conn->sslcompression);
4054  if (conn->requirepeer)
4055  free(conn->requirepeer);
4056  if (conn->ssl_min_protocol_version)
4058  if (conn->ssl_max_protocol_version)
4060  if (conn->gssencmode)
4061  free(conn->gssencmode);
4062  if (conn->krbsrvname)
4063  free(conn->krbsrvname);
4064  if (conn->gsslib)
4065  free(conn->gsslib);
4066  if (conn->connip)
4067  free(conn->connip);
4068 #ifdef ENABLE_GSS
4069  if (conn->gcred != GSS_C_NO_CREDENTIAL)
4070  {
4071  OM_uint32 minor;
4072 
4073  gss_release_cred(&minor, &conn->gcred);
4074  conn->gcred = GSS_C_NO_CREDENTIAL;
4075  }
4076  if (conn->gctx)
4077  {
4078  OM_uint32 minor;
4079 
4080  gss_delete_sec_context(&minor, &conn->gctx, GSS_C_NO_BUFFER);
4081  conn->gctx = NULL;
4082  }
4083 #endif
4084  /* Note that conn->Pfdebug is not ours to close or free */
4085  if (conn->last_query)
4086  free(conn->last_query);
4087  if (conn->write_err_msg)
4088  free(conn->write_err_msg);
4089  if (conn->inBuffer)
4090  free(conn->inBuffer);
4091  if (conn->outBuffer)
4092  free(conn->outBuffer);
4093  if (conn->rowBuf)
4094  free(conn->rowBuf);
4095  if (conn->target_session_attrs)
4096  free(conn->target_session_attrs);
4097  termPQExpBuffer(&conn->errorMessage);
4098  termPQExpBuffer(&conn->workBuffer);
4099 
4100  free(conn);
4101 
4102 #ifdef WIN32
4103  WSACleanup();
4104 #endif
4105 }
char * gssencmode
Definition: libpq-int.h:366
PGEvent * events
Definition: libpq-int.h:383
char * replication
Definition: libpq-int.h:346
char * pgpassfile
Definition: libpq-int.h:349
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
PQExpBufferData workBuffer
Definition: libpq-int.h:529
char * requirepeer
Definition: libpq-int.h:365
char * host
Definition: libpq-int.h:312
char * dbName
Definition: libpq-int.h:345
char * ssl_min_protocol_version
Definition: libpq-int.h:370
char * keepalives
Definition: libpq-int.h:352
char * write_err_msg
Definition: libpq-int.h:421
char * keepalives_idle
Definition: libpq-int.h:353
char * client_encoding_initial
Definition: libpq-int.h:341
char * sslkey
Definition: libpq-int.h:360
char * sslcompression
Definition: libpq-int.h:359
PGconn * conn
Definition: streamutil.c:54
char * hostaddr
Definition: libpq-int.h:313
char * connect_timeout
Definition: libpq-int.h:339
pg_conn_host * connhost
Definition: libpq-int.h:406
char * keepalives_interval
Definition: libpq-int.h:354
char * appname
Definition: libpq-int.h:343
char * sslpassword
Definition: libpq-int.h:362
char * krbsrvname
Definition: libpq-int.h:367
char * channel_binding
Definition: libpq-int.h:350
char * target_session_attrs
Definition: libpq-int.h:374
char * last_query
Definition: libpq-int.h:392
PGdataValue * rowBuf
Definition: libpq-int.h:461
char * pguser
Definition: libpq-int.h:347
char * gsslib
Definition: libpq-int.h:368
char * inBuffer
Definition: libpq-int.h:444
char * sslmode
Definition: libpq-int.h:358
PQExpBufferData errorMessage
Definition: libpq-int.h:526
char * sslcert
Definition: libpq-int.h:361
#define free(a)
Definition: header.h:65
char * pgoptions
Definition: libpq-int.h:342
char * connip
Definition: libpq-int.h:407
char * pgpass
Definition: libpq-int.h:348
char * sslrootcert
Definition: libpq-int.h:363
PGEventProc proc
Definition: libpq-int.h:160
char * outBuffer
Definition: libpq-int.h:451
char * pghostaddr
Definition: libpq-int.h:331
void explicit_bzero(void *buf, size_t len)
char * ssl_max_protocol_version
Definition: libpq-int.h:371
int nEvents
Definition: libpq-int.h:384
int i
void * passThrough
Definition: libpq-int.h:162
char * fbappname
Definition: libpq-int.h:344
char * port
Definition: libpq-int.h:314
char * pgport
Definition: libpq-int.h:335
int nconnhost
Definition: libpq-int.h:404
char * name
Definition: libpq-int.h:161
char * pgtcp_user_timeout
Definition: libpq-int.h:340
char * sslcrl
Definition: libpq-int.h:364
char * keepalives_count
Definition: libpq-int.h:356
char * pghost
Definition: libpq-int.h:327
char * pgtty
Definition: libpq-int.h:337
char * password
Definition: libpq-int.h:315

◆ get_hexdigit()

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

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

Referenced by conninfo_uri_decode().

6353 {
6354  if ('0' <= digit && digit <= '9')
6355  *value = digit - '0';
6356  else if ('A' <= digit && digit <= 'F')
6357  *value = digit - 'A' + 10;
6358  else if ('a' <= digit && digit <= 'f')
6359  *value = digit - 'a' + 10;
6360  else
6361  return false;
6362 
6363  return true;
6364 }
static struct @143 value

◆ getHostaddr()

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

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

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

Referenced by connectFailureMessage(), and PQconnectPoll().

1633 {
1634  struct sockaddr_storage *addr = &conn->raddr.addr;
1635 
1636  if (addr->ss_family == AF_INET)
1637  {
1638  if (pg_inet_net_ntop(AF_INET,
1639  &((struct sockaddr_in *) addr)->sin_addr.s_addr,
1640  32,
1641  host_addr, host_addr_len) == NULL)
1642  host_addr[0] = '\0';
1643  }
1644 #ifdef HAVE_IPV6
1645  else if (addr->ss_family == AF_INET6)
1646  {
1647  if (pg_inet_net_ntop(AF_INET6,
1648  &((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr,
1649  128,
1650  host_addr, host_addr_len) == NULL)
1651  host_addr[0] = '\0';
1652  }
1653 #endif
1654  else
1655  host_addr[0] = '\0';
1656 }
struct sockaddr_storage addr
Definition: pqcomm.h:64
char * pg_inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size)
Definition: inet_net_ntop.c:77
SockAddr raddr
Definition: libpq-int.h:413

◆ internal_cancel()

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

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

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

Referenced by PQcancel(), and PQrequestCancel().

4363 {
4364  int save_errno = SOCK_ERRNO;
4365  pgsocket tmpsock = PGINVALID_SOCKET;
4366  char sebuf[PG_STRERROR_R_BUFLEN];
4367  int maxlen;
4368  struct
4369  {
4370  uint32 packetlen;
4372  } crp;
4373 
4374  /*
4375  * We need to open a temporary connection to the postmaster. Do this with
4376  * only kernel calls.
4377  */
4378  if ((tmpsock = socket(raddr->addr.ss_family, SOCK_STREAM, 0)) == PGINVALID_SOCKET)
4379  {
4380  strlcpy(errbuf, "PQcancel() -- socket() failed: ", errbufsize);
4381  goto cancel_errReturn;
4382  }
4383 retry3:
4384  if (connect(tmpsock, (struct sockaddr *) &raddr->addr,
4385  raddr->salen) < 0)
4386  {
4387  if (SOCK_ERRNO == EINTR)
4388  /* Interrupted system call - we'll just try again */
4389  goto retry3;
4390  strlcpy(errbuf, "PQcancel() -- connect() failed: ", errbufsize);
4391  goto cancel_errReturn;
4392  }
4393 
4394  /*
4395  * We needn't set nonblocking I/O or NODELAY options here.
4396  */
4397 
4398  /* Create and send the cancel request packet. */
4399 
4400  crp.packetlen = pg_hton32((uint32) sizeof(crp));
4401  crp.cp.cancelRequestCode = (MsgType) pg_hton32(CANCEL_REQUEST_CODE);
4402  crp.cp.backendPID = pg_hton32(be_pid);
4403  crp.cp.cancelAuthCode = pg_hton32(be_key);
4404 
4405 retry4:
4406  if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp))
4407  {
4408  if (SOCK_ERRNO == EINTR)
4409  /* Interrupted system call - we'll just try again */
4410  goto retry4;
4411  strlcpy(errbuf, "PQcancel() -- send() failed: ", errbufsize);
4412  goto cancel_errReturn;
4413  }
4414 
4415  /*
4416  * Wait for the postmaster to close the connection, which indicates that
4417  * it's processed the request. Without this delay, we might issue another
4418  * command only to find that our cancel zaps that command instead of the
4419  * one we thought we were canceling. Note we don't actually expect this
4420  * read to obtain any data, we are just waiting for EOF to be signaled.
4421  */
4422 retry5:
4423  if (recv(tmpsock, (char *) &crp, 1, 0) < 0)
4424  {
4425  if (SOCK_ERRNO == EINTR)
4426  /* Interrupted system call - we'll just try again */
4427  goto retry5;
4428  /* we ignore other error conditions */
4429  }
4430 
4431  /* All done */
4432  closesocket(tmpsock);
4433  SOCK_ERRNO_SET(save_errno);
4434  return true;
4435 
4436 cancel_errReturn:
4437 
4438  /*
4439  * Make sure we don't overflow the error buffer. Leave space for the \n at
4440  * the end, and for the terminating zero.
4441  */
4442  maxlen = errbufsize - strlen(errbuf) - 2;
4443  if (maxlen >= 0)
4444  {
4445  strncat(errbuf, SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)),
4446  maxlen);
4447  strcat(errbuf, "\n");
4448  }
4449  if (tmpsock != PGINVALID_SOCKET)
4450  closesocket(tmpsock);
4451  SOCK_ERRNO_SET(save_errno);
4452  return false;
4453 }
#define closesocket
Definition: port.h:313
#define PG_STRERROR_R_BUFLEN
Definition: port.h:211
struct sockaddr_storage addr
Definition: pqcomm.h:64
#define connect(s, name, namelen)
Definition: win32_port.h:435
#define recv(s, buf, len, flags)
Definition: win32_port.h:437
#define SOCK_STRERROR
Definition: libpq-int.h:819
#define pg_hton32(x)
Definition: pg_bswap.h:121
#define SOCK_ERRNO
Definition: libpq-int.h:818
unsigned int uint32
Definition: c.h:367
int pgsocket
Definition: port.h:31
ACCEPT_TYPE_ARG3 salen
Definition: pqcomm.h:65
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:820
#define socket(af, type, protocol)
Definition: win32_port.h:431
#define PGINVALID_SOCKET
Definition: port.h:33
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define CANCEL_REQUEST_CODE
Definition: pqcomm.h:190
ProtocolVersion MsgType
Definition: pqcomm.h:115
#define EINTR
Definition: win32_port.h:323
#define send(s, buf, len, flags)
Definition: win32_port.h:438

◆ internal_ping()

static PGPing internal_ping ( PGconn conn)
static

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

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

Referenced by PQping(), and PQpingParams().

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

◆ makeEmptyPGconn()

static PGconn * makeEmptyPGconn ( void  )
static

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

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

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

3867 {
3868  PGconn *conn;
3869 
3870 #ifdef WIN32
3871 
3872  /*
3873  * Make sure socket support is up and running.
3874  */
3875  WSADATA wsaData;
3876 
3877  if (WSAStartup(MAKEWORD(1, 1), &wsaData))
3878  return NULL;
3879  WSASetLastError(0);
3880 #endif
3881 
3882  conn = (PGconn *) malloc(sizeof(PGconn));
3883  if (conn == NULL)
3884  {
3885 #ifdef WIN32
3886  WSACleanup();
3887 #endif
3888  return conn;
3889  }
3890 
3891  /* Zero all pointers and booleans */
3892  MemSet(conn, 0, sizeof(PGconn));
3893 
3894  /* install default notice hooks */
3897 
3898  conn->status = CONNECTION_BAD;
3899  conn->asyncStatus = PGASYNC_IDLE;
3900  conn->xactStatus = PQTRANS_IDLE;
3901  conn->options_valid = false;
3902  conn->nonblocking = false;
3904  conn->client_encoding = PG_SQL_ASCII;
3905  conn->std_strings = false; /* unless server says differently */
3906  conn->verbosity = PQERRORS_DEFAULT;
3908  conn->sock = PGINVALID_SOCKET;
3909 #ifdef ENABLE_GSS
3910  conn->try_gss = true;
3911 #endif
3912 
3913  /*
3914  * We try to send at least 8K at a time, which is the usual size of pipe
3915  * buffers on Unix systems. That way, when we are sending a large amount
3916  * of data, we avoid incurring extra kernel context swaps for partial
3917  * bufferloads. The output buffer is initially made 16K in size, and we
3918  * try to dump it after accumulating 8K.
3919  *
3920  * With the same goal of minimizing context swaps, the input buffer will
3921  * be enlarged anytime it has less than 8K free, so we initially allocate
3922  * twice that.
3923  */
3924  conn->inBufSize = 16 * 1024;
3925  conn->inBuffer = (char *) malloc(conn->inBufSize);
3926  conn->outBufSize = 16 * 1024;
3927  conn->outBuffer = (char *) malloc(conn->outBufSize);
3928  conn->rowBufLen = 32;
3929  conn->rowBuf = (PGdataValue *) malloc(conn->rowBufLen * sizeof(PGdataValue));
3930  initPQExpBuffer(&conn->errorMessage);
3931  initPQExpBuffer(&conn->workBuffer);
3932 
3933  if (conn->inBuffer == NULL ||
3934  conn->outBuffer == NULL ||
3935  conn->rowBuf == NULL ||
3936  PQExpBufferBroken(&conn->errorMessage) ||
3937  PQExpBufferBroken(&conn->workBuffer))
3938  {
3939  /* out of memory already :-( */
3940  freePGconn(conn);
3941  conn = NULL;
3942  }
3943 
3944  return conn;
3945 }
PGContextVisibility show_context
Definition: libpq-int.h:440
int rowBufLen
Definition: libpq-int.h:462
PQExpBufferData workBuffer
Definition: libpq-int.h:529
#define MemSet(start, val, len)
Definition: c.h:971
#define malloc(a)
Definition: header.h:50
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:389
PGSetenvStatusType setenv_state
Definition: libpq-int.h:429
PGconn * conn
Definition: streamutil.c:54
int inBufSize
Definition: libpq-int.h:445
PGNoticeHooks noticeHooks
Definition: libpq-int.h:380
PGVerbosity verbosity
Definition: libpq-int.h:439
PQnoticeReceiver noticeRec
Definition: libpq-int.h:152
PGdataValue * rowBuf
Definition: libpq-int.h:461
pgsocket sock
Definition: libpq-int.h:410
#define PGINVALID_SOCKET
Definition: port.h:33
char * inBuffer
Definition: libpq-int.h:444
PQnoticeProcessor noticeProc
Definition: libpq-int.h:154
static void freePGconn(PGconn *conn)
Definition: fe-connect.c:3957
PQExpBufferData errorMessage
Definition: libpq-int.h:526
bool std_strings
Definition: libpq-int.h:438
bool options_valid
Definition: libpq-int.h:394
int outBufSize
Definition: libpq-int.h:452
#define PQExpBufferBroken(str)
Definition: pqexpbuffer.h:59
ConnStatusType status
Definition: libpq-int.h:388
char * outBuffer
Definition: libpq-int.h:451
bool nonblocking
Definition: libpq-int.h:395
static void defaultNoticeProcessor(void *arg, const char *message)
Definition: fe-connect.c:6905
int client_encoding
Definition: libpq-int.h:437
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92
static void defaultNoticeReceiver(void *arg, const PGresult *res)
Definition: fe-connect.c:6890
PGTransactionStatusType xactStatus
Definition: libpq-int.h:390

◆ parse_comma_separated_list()

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

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

References malloc, and startptr.

Referenced by connectOptions2().

970 {
971  char *p;
972  char *s = *startptr;
973  char *e;
974  int len;
975 
976  /*
977  * Search for the end of the current element; a comma or end-of-string
978  * acts as a terminator.
979  */
980  e = s;
981  while (*e != '\0' && *e != ',')
982  ++e;
983  *more = (*e == ',');
984 
985  len = e - s;
986  p = (char *) malloc(sizeof(char) * (len + 1));
987  if (p)
988  {
989  memcpy(p, s, len);
990  p[len] = '\0';
991  }
992  *startptr = e + 1;
993 
994  return p;
995 }
#define malloc(a)
Definition: header.h:50
e
Definition: preproc-init.c:82
static XLogRecPtr startptr
Definition: basebackup.c:116

◆ parse_connection_string()

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

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

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

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

5357 {
5358  /* Parse as URI if connection string matches URI prefix */
5359  if (uri_prefix_length(connstr) != 0)
5360  return conninfo_uri_parse(connstr, errorMessage, use_defaults);
5361 
5362  /* Parse as default otherwise */
5363  return conninfo_parse(connstr, errorMessage, use_defaults);
5364 }
static PQconninfoOption * conninfo_parse(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5409
static int uri_prefix_length(const char *connstr)
Definition: fe-connect.c:5375
static PQconninfoOption * conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5856
static char * connstr
Definition: pg_dumpall.c:61

◆ parse_int_param()

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

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

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

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

1759 {
1760  char *end;
1761  long numval;
1762 
1763  Assert(value != NULL);
1764 
1765  *result = 0;
1766 
1767  /* strtol(3) skips leading whitespaces */
1768  errno = 0;
1769  numval = strtol(value, &end, 10);
1770 
1771  /*
1772  * If no progress was done during the parsing or an error happened, fail.
1773  * This tests properly for overflows of the result.
1774  */
1775  if (value == end || errno != 0 || numval != (int) numval)
1776  goto error;
1777 
1778  /*
1779  * Skip any trailing whitespace; if anything but whitespace remains before
1780  * the terminating character, fail
1781  */
1782  while (*end != '\0' && isspace((unsigned char) *end))
1783  end++;
1784 
1785  if (*end != '\0')
1786  goto error;
1787 
1788  *result = numval;
1789  return true;
1790 
1791 error:
1793  libpq_gettext("invalid integer value \"%s\" for connection option \"%s\"\n"),
1794  value, context);
1795  return false;
1796 }
static void error(void)
Definition: sql-dyntest.c:147
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
PQExpBufferData errorMessage
Definition: libpq-int.h:526
static struct @143 value
#define Assert(condition)
Definition: c.h:738
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ parseServiceFile()

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

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

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

Referenced by parseServiceInfo().

5120 {
5121  int linenr = 0,
5122  i;
5123  FILE *f;
5124  char buf[MAXBUFSIZE],
5125  *line;
5126 
5127  f = fopen(serviceFile, "r");
5128  if (f == NULL)
5129  {
5130  printfPQExpBuffer(errorMessage, libpq_gettext("service file \"%s\" not found\n"),
5131  serviceFile);
5132  return 1;
5133  }
5134 
5135  while ((line = fgets(buf, sizeof(buf), f)) != NULL)
5136  {
5137  int len;
5138 
5139  linenr++;
5140 
5141  if (strlen(line) >= sizeof(buf) - 1)
5142  {
5143  fclose(f);
5144  printfPQExpBuffer(errorMessage,
5145  libpq_gettext("line %d too long in service file \"%s\"\n"),
5146  linenr,
5147  serviceFile);
5148  return 2;
5149  }
5150 
5151  /* ignore whitespace at end of line, especially the newline */
5152  len = strlen(line);
5153  while (len > 0 && isspace((unsigned char) line[len - 1]))
5154  line[--len] = '\0';
5155 
5156  /* ignore leading whitespace too */
5157  while (*line && isspace((unsigned char) line[0]))
5158  line++;
5159 
5160  /* ignore comments and empty lines */
5161  if (line[0] == '\0' || line[0] == '#')
5162  continue;
5163 
5164  /* Check for right groupname */
5165  if (line[0] == '[')
5166  {
5167  if (*group_found)
5168  {
5169  /* group info already read */
5170  fclose(f);
5171  return 0;
5172  }
5173 
5174  if (strncmp(line + 1, service, strlen(service)) == 0 &&
5175  line[strlen(service) + 1] == ']')
5176  *group_found = true;
5177  else
5178  *group_found = false;
5179  }
5180  else
5181  {
5182  if (*group_found)
5183  {
5184  /*
5185  * Finally, we are in the right group and can parse the line
5186  */
5187  char *key,
5188  *val;
5189  bool found_keyword;
5190 
5191 #ifdef USE_LDAP
5192  if (strncmp(line, "ldap", 4) == 0)
5193  {
5194  int rc = ldapServiceLookup(line, options, errorMessage);
5195 
5196  /* if rc = 2, go on reading for fallback */
5197  switch (rc)
5198  {
5199  case 0:
5200  fclose(f);
5201  return 0;
5202  case 1:
5203  case 3:
5204  fclose(f);
5205  return 3;
5206  case 2:
5207  continue;
5208  }
5209  }
5210 #endif
5211 
5212  key = line;
5213  val = strchr(line, '=');
5214  if (val == NULL)
5215  {
5216  printfPQExpBuffer(errorMessage,
5217  libpq_gettext("syntax error in service file \"%s\", line %d\n"),
5218  serviceFile,
5219  linenr);
5220  fclose(f);
5221  return 3;
5222  }
5223  *val++ = '\0';
5224 
5225  if (strcmp(key, "service") == 0)
5226  {
5227  printfPQExpBuffer(errorMessage,
5228  libpq_gettext("nested service specifications not supported in service file \"%s\", line %d\n"),
5229  serviceFile,
5230  linenr);
5231  fclose(f);
5232  return 3;
5233  }
5234 
5235  /*
5236  * Set the parameter --- but don't override any previous
5237  * explicit setting.
5238  */
5239  found_keyword = false;
5240  for (i = 0; options[i].keyword; i++)
5241  {
5242  if (strcmp(options[i].keyword, key) == 0)
5243  {
5244  if (options[i].val == NULL)
5245  options[i].val = strdup(val);
5246  if (!options[i].val)
5247  {
5248  printfPQExpBuffer(errorMessage,
5249  libpq_gettext("out of memory\n"));
5250  fclose(f);
5251  return 3;
5252  }
5253  found_keyword = true;
5254  break;
5255  }
5256  }
5257 
5258  if (!found_keyword)
5259  {
5260  printfPQExpBuffer(errorMessage,
5261  libpq_gettext("syntax error in service file \"%s\", line %d\n"),
5262  serviceFile,
5263  linenr);
5264  fclose(f);
5265  return 3;
5266  }
5267  }
5268  }
5269  }
5270 
5271  fclose(f);
5272 
5273  return 0;
5274 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
#define MAXBUFSIZE
Definition: fe-connect.c:5033
static char * buf
Definition: pg_test_fsync.c:67
int i
long val
Definition: informix.c:664
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ parseServiceInfo()

static int parseServiceInfo ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

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

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

Referenced by conninfo_add_defaults().

5047 {
5048  const char *service = conninfo_getval(options, "service");
5049  char serviceFile[MAXPGPATH];
5050  char *env;
5051  bool group_found = false;
5052  int status;
5053  struct stat stat_buf;
5054 
5055  /*
5056  * We have to special-case the environment variable PGSERVICE here, since
5057  * this is and should be called before inserting environment defaults for
5058  * other connection options.
5059  */
5060  if (service == NULL)
5061  service = getenv("PGSERVICE");
5062 
5063  /* If no service name given, nothing to do */
5064  if (service == NULL)
5065  return 0;
5066 
5067  /*
5068  * Try PGSERVICEFILE if specified, else try ~/.pg_service.conf (if that
5069  * exists).
5070  */
5071  if ((env = getenv("PGSERVICEFILE")) != NULL)
5072  strlcpy(serviceFile, env, sizeof(serviceFile));
5073  else
5074  {
5075  char homedir[MAXPGPATH];
5076 
5077  if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
5078  goto next_file;
5079  snprintf(serviceFile, MAXPGPATH, "%s/%s", homedir, ".pg_service.conf");
5080  if (stat(serviceFile, &stat_buf) != 0)
5081  goto next_file;
5082  }
5083 
5084  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
5085  if (group_found || status != 0)
5086  return status;
5087 
5088 next_file:
5089 
5090  /*
5091  * This could be used by any application so we can't use the binary
5092  * location to find our config files.
5093  */
5094  snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf",
5095  getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);
5096  if (stat(serviceFile, &stat_buf) != 0)
5097  goto last_file;
5098 
5099  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
5100  if (status != 0)
5101  return status;
5102 
5103 last_file:
5104  if (!group_found)
5105  {
5106  printfPQExpBuffer(errorMessage,
5107  libpq_gettext("definition of service \"%s\" not found\n"), service);
5108  return 3;
5109  }
5110 
5111  return 0;
5112 }
void printfPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:237
struct stat stat_buf
Definition: pg_standby.c:100
#define MAXPGPATH
#define stat(a, b)
Definition: win32_port.h:255
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
static int parseServiceFile(const char *serviceFile, const char *service, PQconninfoOption *options, PQExpBuffer errorMessage, bool *group_found)
Definition: fe-connect.c:5115
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6373
bool pqGetHomeDirectory(char *buf, int bufsize)
Definition: fe-connect.c:7212
static void static void status(const char *fmt,...) pg_attribute_printf(1
Definition: pg_regress.c:225
#define snprintf
Definition: port.h:193
#define libpq_gettext(x)
Definition: libpq-int.h:805

◆ passwordFromFile()

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

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

References buf, DEFAULT_PGSOCKET_DIR, DefaultHost, explicit_bzero(), fprintf, is_absolute_path, libpq_gettext, LINELEN, pg_strip_crlf(), pwdfMatchesString(), S_IRWXG, S_IRWXO, S_ISREG, and stat.

Referenced by connectOptions2().

6956 {
6957  FILE *fp;
6958  struct stat stat_buf;
6959  int line_number = 0;
6960 
6961 #define LINELEN NAMEDATALEN*5
6962  char buf[LINELEN];
6963 
6964  if (dbname == NULL || dbname[0] == '\0')
6965  return NULL;
6966 
6967  if (username == NULL || username[0] == '\0')
6968  return NULL;
6969 
6970  /* 'localhost' matches pghost of '' or the default socket directory */
6971  if (hostname == NULL || hostname[0] == '\0')
6973  else if (is_absolute_path(hostname))
6974 
6975  /*
6976  * We should probably use canonicalize_path(), but then we have to
6977  * bring path.c into libpq, and it doesn't seem worth it.
6978  */
6979  if (strcmp(hostname, DEFAULT_PGSOCKET_DIR) == 0)
6981 
6982  if (port == NULL || port[0] == '\0')
6983  port = DEF_PGPORT_STR;
6984 
6985  /* If password file cannot be opened, ignore it. */
6986  if (stat(pgpassfile, &stat_buf) != 0)
6987  return NULL;
6988 
6989 #ifndef WIN32
6990  if (!S_ISREG(stat_buf.st_mode))
6991  {
6992  fprintf(stderr,
6993  libpq_gettext("WARNING: password file \"%s\" is not a plain file\n"),
6994  pgpassfile);
6995  return NULL;
6996  }
6997 
6998  /* If password file is insecure, alert the user and ignore it. */
6999  if (stat_buf.st_mode & (S_IRWXG | S_IRWXO))
7000  {
7001  fprintf(stderr,
7002  libpq_gettext("WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
7003  pgpassfile);
7004  return NULL;
7005  }
7006 #else
7007 
7008  /*
7009  * On Win32, the directory is protected, so we don't have to check the
7010  * file.
7011  */
7012 #endif
7013 
7014  fp = fopen(pgpassfile, "r");
7015  if (fp == NULL)
7016  return NULL;
7017 
7018  while (!feof(fp) && !ferror(fp))
7019  {
7020  char *t = buf,
7021  *ret,
7022  *p1,
7023  *p2;
7024  int len;
7025  int buflen;
7026 
7027  if (fgets(buf, sizeof(buf), fp) == NULL)
7028  break;
7029 
7030  line_number++;
7031  buflen = strlen(buf);
7032  if (buflen >= sizeof(buf) - 1 && buf[buflen - 1] != '\n')
7033  {
7034  char rest[LINELEN];
7035  int restlen;
7036 
7037  /*
7038  * Warn if this password setting line is too long, because it's
7039  * unexpectedly truncated.
7040  */
7041  if (buf[0] != '#')
7042  fprintf(stderr,
7043  libpq_gettext("WARNING: line %d too long in password file \"%s\"\n"),
7044  line_number, pgpassfile);
7045 
7046  /* eat rest of the line */
7047  while (!feof(fp) && !ferror(fp))
7048  {
7049  if (fgets(rest, sizeof(rest), fp) == NULL)
7050  break;
7051  restlen = strlen(rest);
7052  if (restlen < sizeof(rest) - 1 || rest[restlen - 1] == '\n')
7053  break;
7054  }
7055  }
7056 
7057  /* ignore comments */
7058  if (buf[0] == '#')
7059  continue;
7060 
7061  /* strip trailing newline and carriage return */
7062  len = pg_strip_crlf(buf);
7063 
7064  if (len == 0)
7065  continue;
7066 
7067  if ((t = pwdfMatchesString(t, hostname)) == NULL ||
7068  (t = pwdfMatchesString(t, port)) == NULL ||
7069  (t = pwdfMatchesString(t, dbname)) == NULL ||
7070  (t = pwdfMatchesString(t, username)) == NULL)
7071  continue;
7072 
7073  /* Found a match. */
7074  ret = strdup(t);
7075  fclose(fp);
7076 
7077  if (!ret)
7078  {
7079  /* Out of memory. XXX: an error message would be nice. */
7080  explicit_bzero(buf, sizeof(buf));
7081  return NULL;
7082  }
7083 
7084  /* De-escape password. */
7085  for (p1 = p2 = ret; *p1 != ':' && *p1 != '\0'; ++p1, ++p2)
7086  {
7087  if (*p1 == '\\' && p1[1] != '\0')
7088  ++p1;
7089  *p2 = *p1;
7090  }
7091  *p2 = '\0';
7092 
7093  return ret;
7094  }
7095 
7096  fclose(fp);
7097  explicit_bzero(buf, sizeof(buf));
7098  return NULL;
7099 
7100 #undef LINELEN
7101 }
int pg_strip_crlf(char *str)
Definition: string.c:105
#define LINELEN
#define fprintf
Definition: port.h:197
struct stat stat_buf
Definition: pg_standby.c:100
static char * buf
Definition: pg_test_fsync.c:67
#define S_IRWXG
Definition: win32_port.h:281
#define is_absolute_path(filename)
Definition: port.h:86
static int port
Definition: pg_regress.c:90
#define S_ISREG(m)
Definition: win32_port.h:299
#define stat(a, b)
Definition: win32_port.h:255
static char * username
Definition: initdb.c:133
char * dbname
Definition: streamutil.c:50
#define DefaultHost
Definition: fe-connect.c:121
static char * pwdfMatchesString(char *buf, const char *token)
Definition: fe-connect.c:6917
void explicit_bzero(void *buf, size_t len)
static char * hostname
Definition: pg_regress.c:89
#define S_IRWXO
Definition: win32_port.h:293
#define libpq_gettext(x)
Definition: libpq-int.h:805
#define DEFAULT_PGSOCKET_DIR

◆ pgpassfileWarning()

static void pgpassfileWarning ( PGconn conn)
static

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

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

Referenced by PQconnectPoll().

7110 {
7111  /* If it was 'invalid authorization', add pgpassfile mention */
7112  /* only works with >= 9.0 servers */
7113  if (conn->password_needed &&
7114  conn->connhost[conn->whichhost].password != NULL &&
7115  conn->result)
7116  {
7117  const char *sqlstate = PQresultErrorField(conn->result,
7119 
7120  if (sqlstate && strcmp(sqlstate, ERRCODE_INVALID_PASSWORD) == 0)
7122  libpq_gettext("password retrieved from file \"%s\"\n"),
7123  conn->pgpassfile);
7124  }
7125 }
char * pgpassfile
Definition: libpq-int.h:349
bool password_needed
Definition: libpq-int.h:417
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:57
PGresult * result
Definition: libpq-int.h:465
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
pg_conn_host * connhost
Definition: libpq-int.h:406
PQExpBufferData errorMessage
Definition: libpq-int.h:526
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:2754
#define ERRCODE_INVALID_PASSWORD
Definition: fe-connect.c:94
int whichhost
Definition: libpq-int.h:405
#define libpq_gettext(x)
Definition: libpq-int.h:805
char * password
Definition: libpq-int.h:315

◆ PQbackendPID()

int PQbackendPID ( const PGconn conn)

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

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

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

6718 {
6719  if (!conn || conn->status != CONNECTION_OK)
6720  return 0;
6721  return conn->be_pid;
6722 }
ConnStatusType status
Definition: libpq-int.h:388
int be_pid
Definition: libpq-int.h:434

◆ PQcancel()

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

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

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

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

4466 {
4467  if (!cancel)
4468  {
4469  strlcpy(errbuf, "PQcancel() -- no cancel object supplied", errbufsize);
4470  return false;
4471  }
4472 
4473  return internal_cancel(&cancel->raddr, cancel->be_pid, cancel->be_key,
4474  errbuf, errbufsize);
4475 }
static int internal_cancel(SockAddr *raddr, int be_pid, int be_key, char *errbuf, int errbufsize)
Definition: fe-connect.c:4361
int be_pid
Definition: libpq-int.h:539
int be_key
Definition: libpq-int.h:540
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
SockAddr raddr
Definition: libpq-int.h:538

◆ PQclientEncoding()

int PQclientEncoding ( const PGconn conn)

◆ PQconndefaults()

PQconninfoOption* PQconndefaults ( void  )

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

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

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

1439 {
1440  PQExpBufferData errorBuf;
1441  PQconninfoOption *connOptions;
1442 
1443  /* We don't actually report any errors here, but callees want a buffer */
1444  initPQExpBuffer(&errorBuf);
1445  if (PQExpBufferDataBroken(errorBuf))
1446  return NULL; /* out of memory already :-( */
1447 
1448  connOptions = conninfo_init(&errorBuf);
1449  if (connOptions != NULL)
1450  {
1451  /* pass NULL errorBuf to ignore errors */
1452  if (!conninfo_add_defaults(connOptions, NULL))
1453  {
1454  PQconninfoFree(connOptions);
1455  connOptions = NULL;
1456  }
1457  }
1458 
1459  termPQExpBuffer(&errorBuf);
1460  return connOptions;
1461 }
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:131
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5315
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6523
#define PQExpBufferDataBroken(buf)
Definition: pqexpbuffer.h:67
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5751
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:92

◆ PQconnectdb()

PGconn* PQconnectdb ( const char *  conninfo)

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

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

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

697 {
698  PGconn *conn = PQconnectStart(conninfo);
699 
700  if (conn && conn->status != CONNECTION_BAD)
701  (void) connectDBComplete(conn);
702 
703  return conn;
704 }
PGconn * conn
Definition: streamutil.c:54
static int connectDBComplete(PGconn *conn)
Definition: fe-connect.c:2076
PGconn * PQconnectStart(const char *conninfo)
Definition: fe-connect.c:822
ConnStatusType status
Definition: libpq-int.h:388

◆ PQconnectdbParams()

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

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

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

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

643 {
644  PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname);
645 
646  if (conn && conn->status != CONNECTION_BAD)
647  (void) connectDBComplete(conn);
648 
649  return conn;
650 
651 }
PGconn * conn
Definition: streamutil.c:54
static int connectDBComplete(PGconn *conn)
Definition: fe-connect.c:2076
ConnStatusType status
Definition: libpq-int.h:388
static Datum values[MAXATTR]
Definition: bootstrap.c:167
PGconn * PQconnectStartParams(const char *const *keywords, const char *const *values, int expand_dbname)
Definition: fe-connect.c:743

◆ PQconnectionNeedsPassword()

int PQconnectionNeedsPassword ( const PGconn conn)

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

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

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

6726 {
6727  char *password;
6728 
6729  if (!conn)
6730  return false;
6731  password = PQpass(conn);
6732  if (conn->password_needed &&
6733  (password == NULL || password[0] == '\0'))
6734  return true;
6735  else
6736  return false;
6737 }
static char password[100]
Definition: streamutil.c:53
bool password_needed
Definition: libpq-int.h:417
char * PQpass(const PGconn *conn)
Definition: fe-connect.c:6557

◆ PQconnectionUsedPassword()

int PQconnectionUsedPassword ( const PGconn conn)

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

References pg_conn::password_needed.

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

6741 {
6742  if (!conn)
6743  return false;
6744  if (conn->password_needed)
6745  return true;
6746  else
6747  return false;
6748 }
bool password_needed
Definition: libpq-int.h:417

◆ PQconnectPoll()

PostgresPollingStatusType PQconnectPoll ( PGconn conn)

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

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

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

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