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

Go to the source code of this file.

Data Structures

struct  _internalPQconninfoOption
 

Macros

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

Typedefs

typedef struct _internalPQconninfoOption internalPQconninfoOption
 

Functions

static bool connectOptions1 (PGconn *conn, const char *conninfo)
 
static bool connectOptions2 (PGconn *conn)
 
static int connectDBStart (PGconn *conn)
 
static int connectDBComplete (PGconn *conn)
 
static PGPing internal_ping (PGconn *conn)
 
static PGconnmakeEmptyPGconn (void)
 
static void pqFreeCommandQueue (PGcmdQueueEntry *queue)
 
static bool fillPGconn (PGconn *conn, PQconninfoOption *connOptions)
 
static void freePGconn (PGconn *conn)
 
static void closePGconn (PGconn *conn)
 
static void release_conn_addrinfo (PGconn *conn)
 
static int store_conn_addrinfo (PGconn *conn, struct addrinfo *addrlist)
 
static void sendTerminateConn (PGconn *conn)
 
static PQconninfoOptionconninfo_init (PQExpBuffer errorMessage)
 
static PQconninfoOptionparse_connection_string (const char *connstr, PQExpBuffer errorMessage, bool use_defaults)
 
static int uri_prefix_length (const char *connstr)
 
static bool recognized_connection_string (const char *connstr)
 
static PQconninfoOptionconninfo_parse (const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
 
static PQconninfoOptionconninfo_array_parse (const char *const *keywords, const char *const *values, PQExpBuffer errorMessage, bool use_defaults, int expand_dbname)
 
static bool conninfo_add_defaults (PQconninfoOption *options, PQExpBuffer errorMessage)
 
static PQconninfoOptionconninfo_uri_parse (const char *uri, PQExpBuffer errorMessage, bool use_defaults)
 
static bool conninfo_uri_parse_options (PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage)
 
static bool conninfo_uri_parse_params (char *params, PQconninfoOption *connOptions, PQExpBuffer errorMessage)
 
static char * conninfo_uri_decode (const char *str, PQExpBuffer errorMessage)
 
static bool get_hexdigit (char digit, int *value)
 
static const char * conninfo_getval (PQconninfoOption *connOptions, const char *keyword)
 
static PQconninfoOptionconninfo_storeval (PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode)
 
static PQconninfoOptionconninfo_find (PQconninfoOption *connOptions, const char *keyword)
 
static void defaultNoticeReceiver (void *arg, const PGresult *res)
 
static void defaultNoticeProcessor (void *arg, const char *message)
 
static int parseServiceInfo (PQconninfoOption *options, PQExpBuffer errorMessage)
 
static int parseServiceFile (const char *serviceFile, const char *service, PQconninfoOption *options, PQExpBuffer errorMessage, bool *group_found)
 
static char * pwdfMatchesString (char *buf, const char *token)
 
static char * passwordFromFile (const char *hostname, const char *port, const char *dbname, const char *username, const char *pgpassfile)
 
static void pgpassfileWarning (PGconn *conn)
 
static void default_threadlock (int acquire)
 
static bool sslVerifyProtocolVersion (const char *version)
 
static bool sslVerifyProtocolRange (const char *min, const char *max)
 
static bool parse_int_param (const char *value, int *result, PGconn *conn, const char *context)
 
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)
 
static void libpq_prng_init (PGconn *conn)
 
PQconninfoOptionPQconndefaults (void)
 
PGconnPQsetdbLogin (const char *pghost, const char *pgport, const char *pgoptions, const char *pgtty, const char *dbName, const char *login, const char *pwd)
 
static int connectNoDelay (PGconn *conn)
 
static void getHostaddr (PGconn *conn, char *host_addr, int host_addr_len)
 
static void emitHostIdentityInfo (PGconn *conn, const char *host_addr)
 
static void connectFailureMessage (PGconn *conn, int errorno)
 
static int useKeepalives (PGconn *conn)
 
static int setKeepalivesIdle (PGconn *conn)
 
static int setKeepalivesInterval (PGconn *conn)
 
static int setKeepalivesCount (PGconn *conn)
 
static int setTCPUserTimeout (PGconn *conn)
 
PostgresPollingStatusType PQconnectPoll (PGconn *conn)
 
void PQfinish (PGconn *conn)
 
void PQreset (PGconn *conn)
 
int PQresetStart (PGconn *conn)
 
PostgresPollingStatusType PQresetPoll (PGconn *conn)
 
PGcancelPQgetCancel (PGconn *conn)
 
void PQfreeCancel (PGcancel *cancel)
 
static bool optional_setsockopt (int fd, int protoid, int optid, int value)
 
int PQcancel (PGcancel *cancel, char *errbuf, int errbufsize)
 
int PQrequestCancel (PGconn *conn)
 
int pqPacketSend (PGconn *conn, char pack_type, const void *buf, size_t buf_len)
 
PQconninfoOptionPQconninfoParse (const char *conninfo, char **errmsg)
 
PQconninfoOptionPQconninfo (PGconn *conn)
 
void PQconninfoFree (PQconninfoOption *connOptions)
 
char * PQdb (const PGconn *conn)
 
char * PQuser (const PGconn *conn)
 
char * PQpass (const PGconn *conn)
 
char * PQhost (const PGconn *conn)
 
char * PQhostaddr (const PGconn *conn)
 
char * PQport (const PGconn *conn)
 
char * PQtty (const PGconn *conn)
 
char * PQoptions (const PGconn *conn)
 
ConnStatusType PQstatus (const PGconn *conn)
 
PGTransactionStatusType PQtransactionStatus (const PGconn *conn)
 
const char * PQparameterStatus (const PGconn *conn, const char *paramName)
 
int PQprotocolVersion (const PGconn *conn)
 
int PQserverVersion (const PGconn *conn)
 
char * PQerrorMessage (const PGconn *conn)
 
int PQsocket (const PGconn *conn)
 
int PQbackendPID (const PGconn *conn)
 
PGpipelineStatus PQpipelineStatus (const PGconn *conn)
 
int PQconnectionNeedsPassword (const PGconn *conn)
 
int PQconnectionUsedPassword (const PGconn *conn)
 
int PQconnectionUsedGSSAPI (const PGconn *conn)
 
int PQclientEncoding (const PGconn *conn)
 
int PQsetClientEncoding (PGconn *conn, const char *encoding)
 
PGVerbosity PQsetErrorVerbosity (PGconn *conn, PGVerbosity verbosity)
 
PGContextVisibility PQsetErrorContextVisibility (PGconn *conn, PGContextVisibility show_context)
 
PQnoticeReceiver PQsetNoticeReceiver (PGconn *conn, PQnoticeReceiver proc, void *arg)
 
PQnoticeProcessor PQsetNoticeProcessor (PGconn *conn, PQnoticeProcessor proc, void *arg)
 
bool pqGetHomeDirectory (char *buf, int bufsize)
 
pgthreadlock_t PQregisterThreadLock (pgthreadlock_t newhandler)
 

Variables

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

Macro Definition Documentation

◆ DefaultChannelBinding

#define DefaultChannelBinding   "disable"

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

◆ DefaultGSSMode

#define DefaultGSSMode   "disable"

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

◆ DefaultHost

#define DefaultHost   "localhost"

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

◆ DefaultLoadBalanceHosts

#define DefaultLoadBalanceHosts   "disable"

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

◆ DefaultOption

#define DefaultOption   ""

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

◆ DefaultSSLCertMode

#define DefaultSSLCertMode   "disable"

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

◆ DefaultSSLMode

#define DefaultSSLMode   "disable"

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

◆ DefaultTargetSessionAttrs

#define DefaultTargetSessionAttrs   "any"

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

◆ ERRCODE_APPNAME_UNKNOWN

#define ERRCODE_APPNAME_UNKNOWN   "42704"

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

◆ ERRCODE_CANNOT_CONNECT_NOW

#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"

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

◆ ERRCODE_INVALID_PASSWORD

#define ERRCODE_INVALID_PASSWORD   "28P01"

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

◆ MAX_ERRLEN

#define MAX_ERRLEN   30000

◆ PGPASSFILE

#define PGPASSFILE   ".pgpass"

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

Typedef Documentation

◆ internalPQconninfoOption

Function Documentation

◆ closePGconn()

static void closePGconn ( PGconn conn)
static

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

4564 {
4565  /*
4566  * If possible, send Terminate message to close the connection politely.
4567  */
4569 
4570  /*
4571  * Must reset the blocking status so a possible reconnect will work.
4572  *
4573  * Don't call PQsetnonblocking() because it will fail if it's unable to
4574  * flush the connection.
4575  */
4576  conn->nonblocking = false;
4577 
4578  /*
4579  * Close the connection, reset all transient state, flush I/O buffers.
4580  * Note that this includes clearing conn's error state; we're no longer
4581  * interested in any failures associated with the old connection, and we
4582  * want a clean slate for any new connection attempt.
4583  */
4584  pqDropConnection(conn, true);
4585  conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
4589  pqClearAsyncResult(conn); /* deallocate result */
4592 
4593  /* Reset all state obtained from server, too */
4595 }
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:467
static void sendTerminateConn(PGconn *conn)
Definition: fe-connect.c:4536
static void release_conn_addrinfo(PGconn *conn)
Definition: fe-connect.c:4522
static void pqDropServerData(PGconn *conn)
Definition: fe-connect.c:580
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:776
@ CONNECTION_BAD
Definition: libpq-fe.h:61
@ PQTRANS_IDLE
Definition: libpq-fe.h:118
@ PQ_PIPELINE_OFF
Definition: libpq-fe.h:158
@ PGASYNC_IDLE
Definition: libpq-int.h:221
#define pqClearConnErrorState(conn)
Definition: libpq-int.h:873
PGconn * conn
Definition: streamutil.c:54
PGTransactionStatusType xactStatus
Definition: libpq-int.h:427
bool nonblocking
Definition: libpq-int.h:430
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:426
PGpipelineStatus pipelineStatus
Definition: libpq-int.h:432
ConnStatusType status
Definition: libpq-int.h:425

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

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

◆ connectDBComplete()

static int connectDBComplete ( PGconn conn)
static

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

2406 {
2408  time_t finish_time = ((time_t) -1);
2409  int timeout = 0;
2410  int last_whichhost = -2; /* certainly different from whichhost */
2411  int last_whichaddr = -2; /* certainly different from whichaddr */
2412 
2413  if (conn == NULL || conn->status == CONNECTION_BAD)
2414  return 0;
2415 
2416  /*
2417  * Set up a time limit, if connect_timeout isn't zero.
2418  */
2419  if (conn->connect_timeout != NULL)
2420  {
2421  if (!parse_int_param(conn->connect_timeout, &timeout, conn,
2422  "connect_timeout"))
2423  {
2424  /* mark the connection as bad to report the parsing failure */
2426  return 0;
2427  }
2428 
2429  if (timeout > 0)
2430  {
2431  /*
2432  * Rounding could cause connection to fail unexpectedly quickly;
2433  * to prevent possibly waiting hardly-at-all, insist on at least
2434  * two seconds.
2435  */
2436  if (timeout < 2)
2437  timeout = 2;
2438  }
2439  else /* negative means 0 */
2440  timeout = 0;
2441  }
2442 
2443  for (;;)
2444  {
2445  int ret = 0;
2446 
2447  /*
2448  * (Re)start the connect_timeout timer if it's active and we are
2449  * considering a different host than we were last time through. If
2450  * we've already succeeded, though, needn't recalculate.
2451  */
2452  if (flag != PGRES_POLLING_OK &&
2453  timeout > 0 &&
2454  (conn->whichhost != last_whichhost ||
2455  conn->whichaddr != last_whichaddr))
2456  {
2457  finish_time = time(NULL) + timeout;
2458  last_whichhost = conn->whichhost;
2459  last_whichaddr = conn->whichaddr;
2460  }
2461 
2462  /*
2463  * Wait, if necessary. Note that the initial state (just after
2464  * PQconnectStart) is to wait for the socket to select for writing.
2465  */
2466  switch (flag)
2467  {
2468  case PGRES_POLLING_OK:
2469  return 1; /* success! */
2470 
2471  case PGRES_POLLING_READING:
2472  ret = pqWaitTimed(1, 0, conn, finish_time);
2473  if (ret == -1)
2474  {
2475  /* hard failure, eg select() problem, aborts everything */
2477  return 0;
2478  }
2479  break;
2480 
2481  case PGRES_POLLING_WRITING:
2482  ret = pqWaitTimed(0, 1, conn, finish_time);
2483  if (ret == -1)
2484  {
2485  /* hard failure, eg select() problem, aborts everything */
2487  return 0;
2488  }
2489  break;
2490 
2491  default:
2492  /* Just in case we failed to set it in PQconnectPoll */
2494  return 0;
2495  }
2496 
2497  if (ret == 1) /* connect_timeout elapsed */
2498  {
2499  /*
2500  * Give up on current server/address, try the next one.
2501  */
2502  conn->try_next_addr = true;
2504  }
2505 
2506  /*
2507  * Now try to advance the state machine.
2508  */
2509  flag = PQconnectPoll(conn);
2510  }
2511 }
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
Definition: fe-connect.c:2541
static bool parse_int_param(const char *value, int *result, PGconn *conn, const char *context)
Definition: fe-connect.c:2085
int pqWaitTimed(int forRead, int forWrite, PGconn *conn, time_t finish_time)
Definition: fe-misc.c:992
@ CONNECTION_NEEDED
Definition: libpq-fe.h:76
PostgresPollingStatusType
Definition: libpq-fe.h:85
@ PGRES_POLLING_OK
Definition: libpq-fe.h:89
@ PGRES_POLLING_READING
Definition: libpq-fe.h:87
@ PGRES_POLLING_WRITING
Definition: libpq-fe.h:88
int whichaddr
Definition: libpq-int.h:488
char * connect_timeout
Definition: libpq-int.h:371
bool try_next_addr
Definition: libpq-int.h:485
int whichhost
Definition: libpq-int.h:441
char * flag(int b)
Definition: test-ctype.c:33

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

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

◆ connectDBStart()

static int connectDBStart ( PGconn conn)
static

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

2336 {
2337  if (!conn)
2338  return 0;
2339 
2340  if (!conn->options_valid)
2341  goto connect_errReturn;
2342 
2343  /*
2344  * Check for bad linking to backend-internal versions of src/common
2345  * functions (see comments in link-canary.c for the reason we need this).
2346  * Nobody but developers should see this message, so we don't bother
2347  * translating it.
2348  */
2350  {
2352  "libpq is incorrectly linked to backend functions\n");
2353  goto connect_errReturn;
2354  }
2355 
2356  /* Ensure our buffers are empty */
2357  conn->inStart = conn->inCursor = conn->inEnd = 0;
2358  conn->outCount = 0;
2359 
2360  /*
2361  * Set up to try to connect to the first host. (Setting whichhost = -1 is
2362  * a bit of a cheat, but PQconnectPoll will advance it to 0 before
2363  * anything else looks at it.)
2364  */
2365  conn->whichhost = -1;
2366  conn->try_next_addr = false;
2367  conn->try_next_host = true;
2369 
2370  /* Also reset the target_server_type state if needed */
2373 
2374  /*
2375  * The code for processing CONNECTION_NEEDED state is in PQconnectPoll(),
2376  * so that it can easily be re-executed if needed again during the
2377  * asynchronous startup process. However, we must run it once here,
2378  * because callers expect a success return from this routine to mean that
2379  * we are in PGRES_POLLING_WRITING connection state.
2380  */
2382  return 1;
2383 
2384 connect_errReturn:
2385 
2386  /*
2387  * If we managed to open a socket, close it immediately rather than
2388  * waiting till PQfinish. (The application cannot have gotten the socket
2389  * from PQsocket yet, so this doesn't risk breaking anything.)
2390  */
2391  pqDropConnection(conn, true);
2393  return 0;
2394 }
@ SERVER_TYPE_PREFER_STANDBY_PASS2
Definition: libpq-int.h:243
@ SERVER_TYPE_PREFER_STANDBY
Definition: libpq-int.h:242
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:367
bool try_next_host
Definition: libpq-int.h:486
int inCursor
Definition: libpq-int.h:511
int inEnd
Definition: libpq-int.h:512
int inStart
Definition: libpq-int.h:510
PQExpBufferData errorMessage
Definition: libpq-int.h:617
bool options_valid
Definition: libpq-int.h:429
PGTargetServerType target_server_type
Definition: libpq-int.h:482
int outCount
Definition: libpq-int.h:517

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

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

◆ connectFailureMessage()

static void connectFailureMessage ( PGconn conn,
int  errorno 
)
static

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

2047 {
2048  char sebuf[PG_STRERROR_R_BUFLEN];
2049 
2051  "%s\n",
2052  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
2053 
2054  if (conn->raddr.addr.ss_family == AF_UNIX)
2055  libpq_append_conn_error(conn, "\tIs the server running locally and accepting connections on that socket?");
2056  else
2057  libpq_append_conn_error(conn, "\tIs the server running on that host and accepting TCP/IP connections?");
2058 }
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition: fe-misc.c:1312
#define SOCK_STRERROR
Definition: libpq-int.h:922
#define PG_STRERROR_R_BUFLEN
Definition: port.h:256
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:265
struct sockaddr_storage addr
Definition: pqcomm.h:32
SockAddr raddr
Definition: libpq-int.h:462

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

Referenced by PQconnectPoll().

◆ connectNoDelay()

static int connectNoDelay ( PGconn conn)
static

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

1932 {
1933 #ifdef TCP_NODELAY
1934  int on = 1;
1935 
1936  if (setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY,
1937  (char *) &on,
1938  sizeof(on)) < 0)
1939  {
1940  char sebuf[PG_STRERROR_R_BUFLEN];
1941 
1942  libpq_append_conn_error(conn, "could not set socket to TCP no delay mode: %s",
1943  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
1944  return 0;
1945  }
1946 #endif
1947 
1948  return 1;
1949 }
#define SOCK_ERRNO
Definition: libpq-int.h:921
pgsocket sock
Definition: libpq-int.h:459

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

Referenced by PQconnectPoll().

◆ connectOptions1()

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

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

946 {
947  PQconninfoOption *connOptions;
948 
949  /*
950  * Parse the conninfo string
951  */
952  connOptions = parse_connection_string(conninfo, &conn->errorMessage, true);
953  if (connOptions == NULL)
954  {
956  /* errorMessage is already set */
957  return false;
958  }
959 
960  /*
961  * Move option values into conn structure
962  */
963  if (!fillPGconn(conn, connOptions))
964  {
966  PQconninfoFree(connOptions);
967  return false;
968  }
969 
970  /*
971  * Free the option info - all is in conn now
972  */
973  PQconninfoFree(connOptions);
974 
975  return true;
976 }
static PQconninfoOption * parse_connection_string(const char *connstr, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5890
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:7081
static bool fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
Definition: fe-connect.c:905

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

Referenced by PQconnectStart(), and PQsetdbLogin().

◆ connectOptions2()

static bool connectOptions2 ( PGconn conn)
static

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

1069 {
1070  int i;
1071 
1072  /*
1073  * Allocate memory for details about each host to which we might possibly
1074  * try to connect. For that, count the number of elements in the hostaddr
1075  * or host options. If neither is given, assume one host.
1076  */
1077  conn->whichhost = 0;
1078  if (conn->pghostaddr && conn->pghostaddr[0] != '\0')
1080  else if (conn->pghost && conn->pghost[0] != '\0')
1082  else
1083  conn->nconnhost = 1;
1084  conn->connhost = (pg_conn_host *)
1085  calloc(conn->nconnhost, sizeof(pg_conn_host));
1086  if (conn->connhost == NULL)
1087  goto oom_error;
1088 
1089  /*
1090  * We now have one pg_conn_host structure per possible host. Fill in the
1091  * host and hostaddr fields for each, by splitting the parameter strings.
1092  */
1093  if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0')
1094  {
1095  char *s = conn->pghostaddr;
1096  bool more = true;
1097 
1098  for (i = 0; i < conn->nconnhost && more; i++)
1099  {
1101  if (conn->connhost[i].hostaddr == NULL)
1102  goto oom_error;
1103  }
1104 
1105  /*
1106  * If hostaddr was given, the array was allocated according to the
1107  * number of elements in the hostaddr list, so it really should be the
1108  * right size.
1109  */
1110  Assert(!more);
1111  Assert(i == conn->nconnhost);
1112  }
1113 
1114  if (conn->pghost != NULL && conn->pghost[0] != '\0')
1115  {
1116  char *s = conn->pghost;
1117  bool more = true;
1118 
1119  for (i = 0; i < conn->nconnhost && more; i++)
1120  {
1122  if (conn->connhost[i].host == NULL)
1123  goto oom_error;
1124  }
1125 
1126  /* Check for wrong number of host items. */
1127  if (more || i != conn->nconnhost)
1128  {
1130  libpq_append_conn_error(conn, "could not match %d host names to %d hostaddr values",
1132  return false;
1133  }
1134  }
1135 
1136  /*
1137  * Now, for each host slot, identify the type of address spec, and fill in
1138  * the default address if nothing was given.
1139  */
1140  for (i = 0; i < conn->nconnhost; i++)
1141  {
1142  pg_conn_host *ch = &conn->connhost[i];
1143 
1144  if (ch->hostaddr != NULL && ch->hostaddr[0] != '\0')
1145  ch->type = CHT_HOST_ADDRESS;
1146  else if (ch->host != NULL && ch->host[0] != '\0')
1147  {
1148  ch->type = CHT_HOST_NAME;
1149  if (is_unixsock_path(ch->host))
1150  ch->type = CHT_UNIX_SOCKET;
1151  }
1152  else
1153  {
1154  free(ch->host);
1155 
1156  /*
1157  * This bit selects the default host location. If you change
1158  * this, see also pg_regress.
1159  */
1160  if (DEFAULT_PGSOCKET_DIR[0])
1161  {
1162  ch->host = strdup(DEFAULT_PGSOCKET_DIR);
1163  ch->type = CHT_UNIX_SOCKET;
1164  }
1165  else
1166  {
1167  ch->host = strdup(DefaultHost);
1168  ch->type = CHT_HOST_NAME;
1169  }
1170  if (ch->host == NULL)
1171  goto oom_error;
1172  }
1173  }
1174 
1175  /*
1176  * Next, work out the port number corresponding to each host name.
1177  *
1178  * Note: unlike the above for host names, this could leave the port fields
1179  * as null or empty strings. We will substitute DEF_PGPORT whenever we
1180  * read such a port field.
1181  */
1182  if (conn->pgport != NULL && conn->pgport[0] != '\0')
1183  {
1184  char *s = conn->pgport;
1185  bool more = true;
1186 
1187  for (i = 0; i < conn->nconnhost && more; i++)
1188  {
1190  if (conn->connhost[i].port == NULL)
1191  goto oom_error;
1192  }
1193 
1194  /*
1195  * If exactly one port was given, use it for every host. Otherwise,
1196  * there must be exactly as many ports as there were hosts.
1197  */
1198  if (i == 1 && !more)
1199  {
1200  for (i = 1; i < conn->nconnhost; i++)
1201  {
1202  conn->connhost[i].port = strdup(conn->connhost[0].port);
1203  if (conn->connhost[i].port == NULL)
1204  goto oom_error;
1205  }
1206  }
1207  else if (more || i != conn->nconnhost)
1208  {
1210  libpq_append_conn_error(conn, "could not match %d port numbers to %d hosts",
1212  return false;
1213  }
1214  }
1215 
1216  /*
1217  * If user name was not given, fetch it. (Most likely, the fetch will
1218  * fail, since the only way we get here is if pg_fe_getauthname() failed
1219  * during conninfo_add_defaults(). But now we want an error message.)
1220  */
1221  if (conn->pguser == NULL || conn->pguser[0] == '\0')
1222  {
1223  free(conn->pguser);
1225  if (!conn->pguser)
1226  {
1228  return false;
1229  }
1230  }
1231 
1232  /*
1233  * If database name was not given, default it to equal user name
1234  */
1235  if (conn->dbName == NULL || conn->dbName[0] == '\0')
1236  {
1237  free(conn->dbName);
1238  conn->dbName = strdup(conn->pguser);
1239  if (!conn->dbName)
1240  goto oom_error;
1241  }
1242 
1243  /*
1244  * If password was not given, try to look it up in password file. Note
1245  * that the result might be different for each host/port pair.
1246  */
1247  if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
1248  {
1249  /* If password file wasn't specified, use ~/PGPASSFILE */
1250  if (conn->pgpassfile == NULL || conn->pgpassfile[0] == '\0')
1251  {
1252  char homedir[MAXPGPATH];
1253 
1254  if (pqGetHomeDirectory(homedir, sizeof(homedir)))
1255  {
1256  free(conn->pgpassfile);
1258  if (!conn->pgpassfile)
1259  goto oom_error;
1260  snprintf(conn->pgpassfile, MAXPGPATH, "%s/%s",
1261  homedir, PGPASSFILE);
1262  }
1263  }
1264 
1265  if (conn->pgpassfile != NULL && conn->pgpassfile[0] != '\0')
1266  {
1267  for (i = 0; i < conn->nconnhost; i++)
1268  {
1269  /*
1270  * Try to get a password for this host from file. We use host
1271  * for the hostname search key if given, else hostaddr (at
1272  * least one of them is guaranteed nonempty by now).
1273  */
1274  const char *pwhost = conn->connhost[i].host;
1275 
1276  if (pwhost == NULL || pwhost[0] == '\0')
1277  pwhost = conn->connhost[i].hostaddr;
1278 
1279  conn->connhost[i].password =
1280  passwordFromFile(pwhost,
1281  conn->connhost[i].port,
1282  conn->dbName,
1283  conn->pguser,
1284  conn->pgpassfile);
1285  }
1286  }
1287  }
1288 
1289  /*
1290  * parse and validate require_auth option
1291  */
1292  if (conn->require_auth && conn->require_auth[0])
1293  {
1294  char *s = conn->require_auth;
1295  bool first,
1296  more;
1297  bool negated = false;
1298 
1299  /*
1300  * By default, start from an empty set of allowed options and add to
1301  * it.
1302  */
1303  conn->auth_required = true;
1305 
1306  for (first = true, more = true; more; first = false)
1307  {
1308  char *method,
1309  *part;
1310  uint32 bits;
1311 
1312  part = parse_comma_separated_list(&s, &more);
1313  if (part == NULL)
1314  goto oom_error;
1315 
1316  /*
1317  * Check for negation, e.g. '!password'. If one element is
1318  * negated, they all have to be.
1319  */
1320  method = part;
1321  if (*method == '!')
1322  {
1323  if (first)
1324  {
1325  /*
1326  * Switch to a permissive set of allowed options, and
1327  * subtract from it.
1328  */
1329  conn->auth_required = false;
1330  conn->allowed_auth_methods = -1;
1331  }
1332  else if (!negated)
1333  {
1335  libpq_append_conn_error(conn, "negative require_auth method \"%s\" cannot be mixed with non-negative methods",
1336  method);
1337 
1338  free(part);
1339  return false;
1340  }
1341 
1342  negated = true;
1343  method++;
1344  }
1345  else if (negated)
1346  {
1348  libpq_append_conn_error(conn, "require_auth method \"%s\" cannot be mixed with negative methods",
1349  method);
1350 
1351  free(part);
1352  return false;
1353  }
1354 
1355  if (strcmp(method, "password") == 0)
1356  {
1357  bits = (1 << AUTH_REQ_PASSWORD);
1358  }
1359  else if (strcmp(method, "md5") == 0)
1360  {
1361  bits = (1 << AUTH_REQ_MD5);
1362  }
1363  else if (strcmp(method, "gss") == 0)
1364  {
1365  bits = (1 << AUTH_REQ_GSS);
1366  bits |= (1 << AUTH_REQ_GSS_CONT);
1367  }
1368  else if (strcmp(method, "sspi") == 0)
1369  {
1370  bits = (1 << AUTH_REQ_SSPI);
1371  bits |= (1 << AUTH_REQ_GSS_CONT);
1372  }
1373  else if (strcmp(method, "scram-sha-256") == 0)
1374  {
1375  /* This currently assumes that SCRAM is the only SASL method. */
1376  bits = (1 << AUTH_REQ_SASL);
1377  bits |= (1 << AUTH_REQ_SASL_CONT);
1378  bits |= (1 << AUTH_REQ_SASL_FIN);
1379  }
1380  else if (strcmp(method, "none") == 0)
1381  {
1382  /*
1383  * Special case: let the user explicitly allow (or disallow)
1384  * connections where the server does not send an explicit
1385  * authentication challenge, such as "trust" and "cert" auth.
1386  */
1387  if (negated) /* "!none" */
1388  {
1389  if (conn->auth_required)
1390  goto duplicate;
1391 
1392  conn->auth_required = true;
1393  }
1394  else /* "none" */
1395  {
1396  if (!conn->auth_required)
1397  goto duplicate;
1398 
1399  conn->auth_required = false;
1400  }
1401 
1402  free(part);
1403  continue; /* avoid the bitmask manipulation below */
1404  }
1405  else
1406  {
1408  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1409  "require_auth", method);
1410 
1411  free(part);
1412  return false;
1413  }
1414 
1415  /* Update the bitmask. */
1416  if (negated)
1417  {
1418  if ((conn->allowed_auth_methods & bits) == 0)
1419  goto duplicate;
1420 
1421  conn->allowed_auth_methods &= ~bits;
1422  }
1423  else
1424  {
1425  if ((conn->allowed_auth_methods & bits) == bits)
1426  goto duplicate;
1427 
1428  conn->allowed_auth_methods |= bits;
1429  }
1430 
1431  free(part);
1432  continue;
1433 
1434  duplicate:
1435 
1436  /*
1437  * A duplicated method probably indicates a typo in a setting
1438  * where typos are extremely risky.
1439  */
1441  libpq_append_conn_error(conn, "require_auth method \"%s\" is specified more than once",
1442  part);
1443 
1444  free(part);
1445  return false;
1446  }
1447  }
1448 
1449  /*
1450  * validate channel_binding option
1451  */
1452  if (conn->channel_binding)
1453  {
1454  if (strcmp(conn->channel_binding, "disable") != 0
1455  && strcmp(conn->channel_binding, "prefer") != 0
1456  && strcmp(conn->channel_binding, "require") != 0)
1457  {
1459  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1460  "channel_binding", conn->channel_binding);
1461  return false;
1462  }
1463  }
1464  else
1465  {
1467  if (!conn->channel_binding)
1468  goto oom_error;
1469  }
1470 
1471 #ifndef USE_SSL
1472 
1473  /*
1474  * sslrootcert=system is not supported. Since setting this changes the
1475  * default sslmode, check this _before_ we validate sslmode, to avoid
1476  * confusing the user with errors for an option they may not have set.
1477  */
1478  if (conn->sslrootcert
1479  && strcmp(conn->sslrootcert, "system") == 0)
1480  {
1482  libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1483  "sslrootcert", conn->sslrootcert);
1484  return false;
1485  }
1486 #endif
1487 
1488  /*
1489  * validate sslmode option
1490  */
1491  if (conn->sslmode)
1492  {
1493  if (strcmp(conn->sslmode, "disable") != 0
1494  && strcmp(conn->sslmode, "allow") != 0
1495  && strcmp(conn->sslmode, "prefer") != 0
1496  && strcmp(conn->sslmode, "require") != 0
1497  && strcmp(conn->sslmode, "verify-ca") != 0
1498  && strcmp(conn->sslmode, "verify-full") != 0)
1499  {
1501  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1502  "sslmode", conn->sslmode);
1503  return false;
1504  }
1505 
1506 #ifndef USE_SSL
1507  switch (conn->sslmode[0])
1508  {
1509  case 'a': /* "allow" */
1510  case 'p': /* "prefer" */
1511 
1512  /*
1513  * warn user that an SSL connection will never be negotiated
1514  * since SSL was not compiled in?
1515  */
1516  break;
1517 
1518  case 'r': /* "require" */
1519  case 'v': /* "verify-ca" or "verify-full" */
1521  libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1522  "sslmode", conn->sslmode);
1523  return false;
1524  }
1525 #endif
1526  }
1527  else
1528  {
1529  conn->sslmode = strdup(DefaultSSLMode);
1530  if (!conn->sslmode)
1531  goto oom_error;
1532  }
1533 
1534 #ifdef USE_SSL
1535 
1536  /*
1537  * If sslrootcert=system, make sure our chosen sslmode is compatible.
1538  */
1539  if (conn->sslrootcert
1540  && strcmp(conn->sslrootcert, "system") == 0
1541  && strcmp(conn->sslmode, "verify-full") != 0)
1542  {
1544  libpq_append_conn_error(conn, "weak sslmode \"%s\" may not be used with sslrootcert=system (use \"verify-full\")",
1545  conn->sslmode);
1546  return false;
1547  }
1548 #endif
1549 
1550  /*
1551  * Validate TLS protocol versions for ssl_min_protocol_version and
1552  * ssl_max_protocol_version.
1553  */
1555  {
1557  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1558  "ssl_min_protocol_version",
1560  return false;
1561  }
1563  {
1565  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1566  "ssl_max_protocol_version",
1568  return false;
1569  }
1570 
1571  /*
1572  * Check if the range of SSL protocols defined is correct. This is done
1573  * at this early step because this is independent of the SSL
1574  * implementation used, and this avoids unnecessary cycles with an
1575  * already-built SSL context when the connection is being established, as
1576  * it would be doomed anyway.
1577  */
1580  {
1582  libpq_append_conn_error(conn, "invalid SSL protocol version range");
1583  return false;
1584  }
1585 
1586  /*
1587  * validate sslcertmode option
1588  */
1589  if (conn->sslcertmode)
1590  {
1591  if (strcmp(conn->sslcertmode, "disable") != 0 &&
1592  strcmp(conn->sslcertmode, "allow") != 0 &&
1593  strcmp(conn->sslcertmode, "require") != 0)
1594  {
1596  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1597  "sslcertmode", conn->sslcertmode);
1598  return false;
1599  }
1600 #ifndef USE_SSL
1601  if (strcmp(conn->sslcertmode, "require") == 0)
1602  {
1604  libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1605  "sslcertmode", conn->sslcertmode);
1606  return false;
1607  }
1608 #endif
1609 #ifndef HAVE_SSL_CTX_SET_CERT_CB
1610 
1611  /*
1612  * Without a certificate callback, the current implementation can't
1613  * figure out if a certificate was actually requested, so "require" is
1614  * useless.
1615  */
1616  if (strcmp(conn->sslcertmode, "require") == 0)
1617  {
1619  libpq_append_conn_error(conn, "%s value \"%s\" is not supported (check OpenSSL version)",
1620  "sslcertmode", conn->sslcertmode);
1621  return false;
1622  }
1623 #endif
1624  }
1625  else
1626  {
1627  conn->sslcertmode = strdup(DefaultSSLCertMode);
1628  if (!conn->sslcertmode)
1629  goto oom_error;
1630  }
1631 
1632  /*
1633  * validate gssencmode option
1634  */
1635  if (conn->gssencmode)
1636  {
1637  if (strcmp(conn->gssencmode, "disable") != 0 &&
1638  strcmp(conn->gssencmode, "prefer") != 0 &&
1639  strcmp(conn->gssencmode, "require") != 0)
1640  {
1642  libpq_append_conn_error(conn, "invalid %s value: \"%s\"", "gssencmode", conn->gssencmode);
1643  return false;
1644  }
1645 #ifndef ENABLE_GSS
1646  if (strcmp(conn->gssencmode, "require") == 0)
1647  {
1649  libpq_append_conn_error(conn, "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in",
1650  conn->gssencmode);
1651  return false;
1652  }
1653 #endif
1654  }
1655  else
1656  {
1657  conn->gssencmode = strdup(DefaultGSSMode);
1658  if (!conn->gssencmode)
1659  goto oom_error;
1660  }
1661 
1662  /*
1663  * validate target_session_attrs option, and set target_server_type
1664  */
1666  {
1667  if (strcmp(conn->target_session_attrs, "any") == 0)
1669  else if (strcmp(conn->target_session_attrs, "read-write") == 0)
1671  else if (strcmp(conn->target_session_attrs, "read-only") == 0)
1673  else if (strcmp(conn->target_session_attrs, "primary") == 0)
1675  else if (strcmp(conn->target_session_attrs, "standby") == 0)
1677  else if (strcmp(conn->target_session_attrs, "prefer-standby") == 0)
1679  else
1680  {
1682  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1683  "target_session_attrs",
1685  return false;
1686  }
1687  }
1688  else
1690 
1691  /*
1692  * validate load_balance_hosts option, and set load_balance_type
1693  */
1694  if (conn->load_balance_hosts)
1695  {
1696  if (strcmp(conn->load_balance_hosts, "disable") == 0)
1698  else if (strcmp(conn->load_balance_hosts, "random") == 0)
1700  else
1701  {
1703  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1704  "load_balance_hosts",
1706  return false;
1707  }
1708  }
1709  else
1711 
1713  {
1715 
1716  /*
1717  * This is the "inside-out" variant of the Fisher-Yates shuffle
1718  * algorithm. Notionally, we append each new value to the array and
1719  * then swap it with a randomly-chosen array element (possibly
1720  * including itself, else we fail to generate permutations with the
1721  * last integer last). The swap step can be optimized by combining it
1722  * with the insertion.
1723  */
1724  for (i = 1; i < conn->nconnhost; i++)
1725  {
1726  int j = pg_prng_uint64_range(&conn->prng_state, 0, i);
1727  pg_conn_host temp = conn->connhost[j];
1728 
1729  conn->connhost[j] = conn->connhost[i];
1730  conn->connhost[i] = temp;
1731  }
1732  }
1733 
1734  /*
1735  * Resolve special "auto" client_encoding from the locale
1736  */
1738  strcmp(conn->client_encoding_initial, "auto") == 0)
1739  {
1743  goto oom_error;
1744  }
1745 
1746  /*
1747  * Only if we get this far is it appropriate to try to connect. (We need a
1748  * state flag, rather than just the boolean result of this function, in
1749  * case someone tries to PQreset() the PGconn.)
1750  */
1751  conn->options_valid = true;
1752 
1753  return true;
1754 
1755 oom_error:
1757  libpq_append_conn_error(conn, "out of memory");
1758  return false;
1759 }
unsigned int uint32
Definition: c.h:495
const char * pg_encoding_to_char(int encoding)
Definition: encnames.c:588
char * pg_fe_getauthname(PQExpBuffer errorMessage)
Definition: fe-auth.c:1215
#define DefaultHost
Definition: fe-connect.c:116
static char * passwordFromFile(const char *hostname, const char *port, const char *dbname, const char *username, const char *pgpassfile)
Definition: fe-connect.c:7514
static bool sslVerifyProtocolRange(const char *min, const char *max)
Definition: fe-connect.c:7703
static void libpq_prng_init(PGconn *conn)
Definition: fe-connect.c:1041
bool pqGetHomeDirectory(char *buf, int bufsize)
Definition: fe-connect.c:7756
#define DefaultSSLMode
Definition: fe-connect.c:129
#define DefaultGSSMode
Definition: fe-connect.c:136
static int count_comma_separated_elems(const char *input)
Definition: fe-connect.c:982
#define DefaultChannelBinding
Definition: fe-connect.c:121
static bool sslVerifyProtocolVersion(const char *version)
Definition: fe-connect.c:7677
static char * parse_comma_separated_list(char **startptr, bool *more)
Definition: fe-connect.c:1006
#define PGPASSFILE
Definition: fe-connect.c:75
#define DefaultSSLCertMode
Definition: fe-connect.c:130
#define calloc(a, b)
Definition: header.h:55
#define free(a)
Definition: header.h:65
#define malloc(a)
Definition: header.h:50
int j
Definition: isn.c:74
int i
Definition: isn.c:73
@ LOAD_BALANCE_DISABLE
Definition: libpq-int.h:249
@ LOAD_BALANCE_RANDOM
Definition: libpq-int.h:250
@ CHT_UNIX_SOCKET
Definition: libpq-int.h:311
@ CHT_HOST_ADDRESS
Definition: libpq-int.h:310
@ CHT_HOST_NAME
Definition: libpq-int.h:309
@ SERVER_TYPE_STANDBY
Definition: libpq-int.h:241
@ SERVER_TYPE_PRIMARY
Definition: libpq-int.h:240
@ SERVER_TYPE_ANY
Definition: libpq-int.h:237
@ SERVER_TYPE_READ_WRITE
Definition: libpq-int.h:238
@ SERVER_TYPE_READ_ONLY
Definition: libpq-int.h:239
Assert(fmt[strlen(fmt) - 1] !='\n')
#define MAXPGPATH
#define DEFAULT_PGSOCKET_DIR
uint64 pg_prng_uint64_range(pg_prng_state *state, uint64 rmin, uint64 rmax)
Definition: pg_prng.c:144
#define snprintf
Definition: port.h:238
int pg_get_encoding_from_locale(const char *ctype, bool write_message)
Definition: chklocale.c:428
static bool is_unixsock_path(const char *path)
Definition: pqcomm.h:67
#define AUTH_REQ_SSPI
Definition: protocol.h:79
#define AUTH_REQ_SASL_CONT
Definition: protocol.h:81
#define AUTH_REQ_GSS
Definition: protocol.h:77
#define AUTH_REQ_MD5
Definition: protocol.h:75
#define AUTH_REQ_PASSWORD
Definition: protocol.h:73
#define AUTH_REQ_GSS_CONT
Definition: protocol.h:78
#define AUTH_REQ_SASL
Definition: protocol.h:80
#define AUTH_REQ_SASL_FIN
Definition: protocol.h:82
char * host
Definition: libpq-int.h:346
char * password
Definition: libpq-int.h:349
char * port
Definition: libpq-int.h:348
char * hostaddr
Definition: libpq-int.h:347
pg_conn_host_type type
Definition: libpq-int.h:345
char * sslrootcert
Definition: libpq-int.h:396
int nconnhost
Definition: libpq-int.h:440
char * require_auth
Definition: libpq-int.h:409
char * channel_binding
Definition: libpq-int.h:382
char * pghost
Definition: libpq-int.h:361
char * ssl_max_protocol_version
Definition: libpq-int.h:407
char * pgpass
Definition: libpq-int.h:380
char * dbName
Definition: libpq-int.h:377
char * sslcertmode
Definition: libpq-int.h:395
uint32 allowed_auth_methods
Definition: libpq-int.h:475
char * target_session_attrs
Definition: libpq-int.h:408
bool auth_required
Definition: libpq-int.h:473
char * load_balance_hosts
Definition: libpq-int.h:410
char * pguser
Definition: libpq-int.h:379
char * client_encoding_initial
Definition: libpq-int.h:373
char * sslmode
Definition: libpq-int.h:390
pg_prng_state prng_state
Definition: libpq-int.h:504
char * ssl_min_protocol_version
Definition: libpq-int.h:406
char * gssencmode
Definition: libpq-int.h:401
char * pghostaddr
Definition: libpq-int.h:365
char * pgpassfile
Definition: libpq-int.h:381
PGLoadBalanceType load_balance_type
Definition: libpq-int.h:483
char * pgport
Definition: libpq-int.h:369
pg_conn_host * connhost
Definition: libpq-int.h:442

References pg_conn::allowed_auth_methods, Assert(), AUTH_REQ_GSS, AUTH_REQ_GSS_CONT, AUTH_REQ_MD5, AUTH_REQ_PASSWORD, AUTH_REQ_SASL, AUTH_REQ_SASL_CONT, AUTH_REQ_SASL_FIN, AUTH_REQ_SSPI, pg_conn::auth_required, calloc, pg_conn::channel_binding, CHT_HOST_ADDRESS, CHT_HOST_NAME, CHT_UNIX_SOCKET, pg_conn::client_encoding_initial, conn, CONNECTION_BAD, pg_conn::connhost, count_comma_separated_elems(), pg_conn::dbName, DEFAULT_PGSOCKET_DIR, DefaultChannelBinding, DefaultGSSMode, DefaultHost, DefaultSSLCertMode, DefaultSSLMode, pg_conn::errorMessage, free, pg_conn::gssencmode, pg_conn_host::host, pg_conn_host::hostaddr, i, is_unixsock_path(), j, libpq_append_conn_error(), libpq_prng_init(), LOAD_BALANCE_DISABLE, pg_conn::load_balance_hosts, LOAD_BALANCE_RANDOM, pg_conn::load_balance_type, 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_prng_uint64_range(), pg_conn::pghost, pg_conn::pghostaddr, pg_conn::pgpass, PGPASSFILE, pg_conn::pgpassfile, pg_conn::pgport, pg_conn::pguser, pg_conn_host::port, pqGetHomeDirectory(), pg_conn::prng_state, pg_conn::require_auth, SERVER_TYPE_ANY, SERVER_TYPE_PREFER_STANDBY, SERVER_TYPE_PRIMARY, SERVER_TYPE_READ_ONLY, SERVER_TYPE_READ_WRITE, SERVER_TYPE_STANDBY, snprintf, pg_conn::ssl_max_protocol_version, pg_conn::ssl_min_protocol_version, pg_conn::sslcertmode, pg_conn::sslmode, pg_conn::sslrootcert, sslVerifyProtocolRange(), sslVerifyProtocolVersion(), pg_conn::status, pg_conn::target_server_type, pg_conn::target_session_attrs, pg_conn_host::type, and pg_conn::whichhost.

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

◆ conninfo_add_defaults()

static bool conninfo_add_defaults ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

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

6279 {
6281  PQconninfoOption *sslmode_default = NULL,
6282  *sslrootcert = NULL;
6283  char *tmp;
6284 
6285  /*
6286  * If there's a service spec, use it to obtain any not-explicitly-given
6287  * parameters. Ignore error if no error message buffer is passed because
6288  * there is no way to pass back the failure message.
6289  */
6290  if (parseServiceInfo(options, errorMessage) != 0 && errorMessage)
6291  return false;
6292 
6293  /*
6294  * Get the fallback resources for parameters not specified in the conninfo
6295  * string nor the service.
6296  */
6297  for (option = options; option->keyword != NULL; option++)
6298  {
6299  if (strcmp(option->keyword, "sslrootcert") == 0)
6300  sslrootcert = option; /* save for later */
6301 
6302  if (option->val != NULL)
6303  continue; /* Value was in conninfo or service */
6304 
6305  /*
6306  * Try to get the environment variable fallback
6307  */
6308  if (option->envvar != NULL)
6309  {
6310  if ((tmp = getenv(option->envvar)) != NULL)
6311  {
6312  option->val = strdup(tmp);
6313  if (!option->val)
6314  {
6315  if (errorMessage)
6316  libpq_append_error(errorMessage, "out of memory");
6317  return false;
6318  }
6319  continue;
6320  }
6321  }
6322 
6323  /*
6324  * Interpret the deprecated PGREQUIRESSL environment variable. Per
6325  * tradition, translate values starting with "1" to sslmode=require,
6326  * and ignore other values. Given both PGREQUIRESSL=1 and PGSSLMODE,
6327  * PGSSLMODE takes precedence; the opposite was true before v9.3.
6328  */
6329  if (strcmp(option->keyword, "sslmode") == 0)
6330  {
6331  const char *requiresslenv = getenv("PGREQUIRESSL");
6332 
6333  if (requiresslenv != NULL && requiresslenv[0] == '1')
6334  {
6335  option->val = strdup("require");
6336  if (!option->val)
6337  {
6338  if (errorMessage)
6339  libpq_append_error(errorMessage, "out of memory");
6340  return false;
6341  }
6342  continue;
6343  }
6344 
6345  /*
6346  * sslmode is not specified. Let it be filled in with the compiled
6347  * default for now, but if sslrootcert=system, we'll override the
6348  * default later before returning.
6349  */
6350  sslmode_default = option;
6351  }
6352 
6353  /*
6354  * No environment variable specified or the variable isn't set - try
6355  * compiled-in default
6356  */
6357  if (option->compiled != NULL)
6358  {
6359  option->val = strdup(option->compiled);
6360  if (!option->val)
6361  {
6362  if (errorMessage)
6363  libpq_append_error(errorMessage, "out of memory");
6364  return false;
6365  }
6366  continue;
6367  }
6368 
6369  /*
6370  * Special handling for "user" option. Note that if pg_fe_getauthname
6371  * fails, we just leave the value as NULL; there's no need for this to
6372  * be an error condition if the caller provides a user name. The only
6373  * reason we do this now at all is so that callers of PQconndefaults
6374  * will see a correct default (barring error, of course).
6375  */
6376  if (strcmp(option->keyword, "user") == 0)
6377  {
6378  option->val = pg_fe_getauthname(NULL);
6379  continue;
6380  }
6381  }
6382 
6383  /*
6384  * Special handling for sslrootcert=system with no sslmode explicitly
6385  * defined. In this case we want to strengthen the default sslmode to
6386  * verify-full.
6387  */
6388  if (sslmode_default && sslrootcert)
6389  {
6390  if (sslrootcert->val && strcmp(sslrootcert->val, "system") == 0)
6391  {
6392  free(sslmode_default->val);
6393 
6394  sslmode_default->val = strdup("verify-full");
6395  if (!sslmode_default->val)
6396  {
6397  if (errorMessage)
6398  libpq_append_error(errorMessage, "out of memory");
6399  return false;
6400  }
6401  }
6402  }
6403 
6404  return true;
6405 }
static int parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5583
void libpq_append_error(PQExpBuffer errorMessage, const char *fmt,...)
Definition: fe-misc.c:1283
int val
Definition: getopt_long.h:21

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

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

◆ conninfo_array_parse()

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

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

6123 {
6125  PQconninfoOption *dbname_options = NULL;
6127  int i = 0;
6128 
6129  /*
6130  * If expand_dbname is non-zero, check keyword "dbname" to see if val is
6131  * actually a recognized connection string.
6132  */
6133  while (expand_dbname && keywords[i])
6134  {
6135  const char *pname = keywords[i];
6136  const char *pvalue = values[i];
6137 
6138  /* first find "dbname" if any */
6139  if (strcmp(pname, "dbname") == 0 && pvalue)
6140  {
6141  /*
6142  * If value is a connection string, parse it, but do not use
6143  * defaults here -- those get picked up later. We only want to
6144  * override for those parameters actually passed.
6145  */
6146  if (recognized_connection_string(pvalue))
6147  {
6148  dbname_options = parse_connection_string(pvalue, errorMessage, false);
6149  if (dbname_options == NULL)
6150  return NULL;
6151  }
6152  break;
6153  }
6154  ++i;
6155  }
6156 
6157  /* Make a working copy of PQconninfoOptions */
6158  options = conninfo_init(errorMessage);
6159  if (options == NULL)
6160  {
6161  PQconninfoFree(dbname_options);
6162  return NULL;
6163  }
6164 
6165  /* Parse the keywords/values arrays */
6166  i = 0;
6167  while (keywords[i])
6168  {
6169  const char *pname = keywords[i];
6170  const char *pvalue = values[i];
6171 
6172  if (pvalue != NULL && pvalue[0] != '\0')
6173  {
6174  /* Search for the param record */
6175  for (option = options; option->keyword != NULL; option++)
6176  {
6177  if (strcmp(option->keyword, pname) == 0)
6178  break;
6179  }
6180 
6181  /* Check for invalid connection option */
6182  if (option->keyword == NULL)
6183  {
6184  libpq_append_error(errorMessage, "invalid connection option \"%s\"", pname);
6186  PQconninfoFree(dbname_options);
6187  return NULL;
6188  }
6189 
6190  /*
6191  * If we are on the first dbname parameter, and we have a parsed
6192  * connection string, copy those parameters across, overriding any
6193  * existing previous settings.
6194  */
6195  if (strcmp(pname, "dbname") == 0 && dbname_options)
6196  {
6197  PQconninfoOption *str_option;
6198 
6199  for (str_option = dbname_options; str_option->keyword != NULL; str_option++)
6200  {
6201  if (str_option->val != NULL)
6202  {
6203  int k;
6204 
6205  for (k = 0; options[k].keyword; k++)
6206  {
6207  if (strcmp(options[k].keyword, str_option->keyword) == 0)
6208  {
6209  free(options[k].val);
6210  options[k].val = strdup(str_option->val);
6211  if (!options[k].val)
6212  {
6213  libpq_append_error(errorMessage, "out of memory");
6215  PQconninfoFree(dbname_options);
6216  return NULL;
6217  }
6218  break;
6219  }
6220  }
6221  }
6222  }
6223 
6224  /*
6225  * Forget the parsed connection string, so that any subsequent
6226  * dbname parameters will not be expanded.
6227  */
6228  PQconninfoFree(dbname_options);
6229  dbname_options = NULL;
6230  }
6231  else
6232  {
6233  /*
6234  * Store the value, overriding previous settings
6235  */
6236  free(option->val);
6237  option->val = strdup(pvalue);
6238  if (!option->val)
6239  {
6240  libpq_append_error(errorMessage, "out of memory");
6242  PQconninfoFree(dbname_options);
6243  return NULL;
6244  }
6245  }
6246  }
6247  ++i;
6248  }
6249  PQconninfoFree(dbname_options);
6250 
6251  /*
6252  * Add in defaults if the caller wants that.
6253  */
6254  if (use_defaults)
6255  {
6256  if (!conninfo_add_defaults(options, errorMessage))
6257  {
6259  return NULL;
6260  }
6261  }
6262 
6263  return options;
6264 }
static Datum values[MAXATTR]
Definition: bootstrap.c:156
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5851
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:6278
static bool recognized_connection_string(const char *connstr)
Definition: fe-connect.c:5933
long val
Definition: informix.c:664
static char ** options

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

Referenced by PQconnectStartParams().

◆ conninfo_find()

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

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

7020 {
7022 
7023  for (option = connOptions; option->keyword != NULL; option++)
7024  {
7025  if (strcmp(option->keyword, keyword) == 0)
7026  return option;
7027  }
7028 
7029  return NULL;
7030 }

Referenced by conninfo_getval(), and conninfo_storeval().

◆ conninfo_getval()

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

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

6931 {
6933 
6934  option = conninfo_find(connOptions, keyword);
6935 
6936  return option ? option->val : NULL;
6937 }
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:7019

References conninfo_find(), and option::val.

Referenced by fillPGconn(), and parseServiceInfo().

◆ conninfo_init()

static PQconninfoOption * conninfo_init ( PQExpBuffer  errorMessage)
static

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

5852 {
5854  PQconninfoOption *opt_dest;
5855  const internalPQconninfoOption *cur_opt;
5856 
5857  /*
5858  * Get enough memory for all options in PQconninfoOptions, even if some
5859  * end up being filtered out.
5860  */
5862  if (options == NULL)
5863  {
5864  libpq_append_error(errorMessage, "out of memory");
5865  return NULL;
5866  }
5867  opt_dest = options;
5868 
5869  for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++)
5870  {
5871  /* Only copy the public part of the struct, not the full internal */
5872  memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption));
5873  opt_dest++;
5874  }
5875  MemSet(opt_dest, 0, sizeof(PQconninfoOption));
5876 
5877  return options;
5878 }
#define MemSet(start, val, len)
Definition: c.h:1009
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:189

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

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

◆ conninfo_parse()

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

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

5946 {
5947  char *pname;
5948  char *pval;
5949  char *buf;
5950  char *cp;
5951  char *cp2;
5953 
5954  /* Make a working copy of PQconninfoOptions */
5955  options = conninfo_init(errorMessage);
5956  if (options == NULL)
5957  return NULL;
5958 
5959  /* Need a modifiable copy of the input string */
5960  if ((buf = strdup(conninfo)) == NULL)
5961  {
5962  libpq_append_error(errorMessage, "out of memory");
5964  return NULL;
5965  }
5966  cp = buf;
5967 
5968  while (*cp)
5969  {
5970  /* Skip blanks before the parameter name */
5971  if (isspace((unsigned char) *cp))
5972  {
5973  cp++;
5974  continue;
5975  }
5976 
5977  /* Get the parameter name */
5978  pname = cp;
5979  while (*cp)
5980  {
5981  if (*cp == '=')
5982  break;
5983  if (isspace((unsigned char) *cp))
5984  {
5985  *cp++ = '\0';
5986  while (*cp)
5987  {
5988  if (!isspace((unsigned char) *cp))
5989  break;
5990  cp++;
5991  }
5992  break;
5993  }
5994  cp++;
5995  }
5996 
5997  /* Check that there is a following '=' */
5998  if (*cp != '=')
5999  {
6000  libpq_append_error(errorMessage,
6001  "missing \"=\" after \"%s\" in connection info string",
6002  pname);
6004  free(buf);
6005  return NULL;
6006  }
6007  *cp++ = '\0';
6008 
6009  /* Skip blanks after the '=' */
6010  while (*cp)
6011  {
6012  if (!isspace((unsigned char) *cp))
6013  break;
6014  cp++;
6015  }
6016 
6017  /* Get the parameter value */
6018  pval = cp;
6019 
6020  if (*cp != '\'')
6021  {
6022  cp2 = pval;
6023  while (*cp)
6024  {
6025  if (isspace((unsigned char) *cp))
6026  {
6027  *cp++ = '\0';
6028  break;
6029  }
6030  if (*cp == '\\')
6031  {
6032  cp++;
6033  if (*cp != '\0')
6034  *cp2++ = *cp++;
6035  }
6036  else
6037  *cp2++ = *cp++;
6038  }
6039  *cp2 = '\0';
6040  }
6041  else
6042  {
6043  cp2 = pval;
6044  cp++;
6045  for (;;)
6046  {
6047  if (*cp == '\0')
6048  {
6049  libpq_append_error(errorMessage, "unterminated quoted string in connection info string");
6051  free(buf);
6052  return NULL;
6053  }
6054  if (*cp == '\\')
6055  {
6056  cp++;
6057  if (*cp != '\0')
6058  *cp2++ = *cp++;
6059  continue;
6060  }
6061  if (*cp == '\'')
6062  {
6063  *cp2 = '\0';
6064  cp++;
6065  break;
6066  }
6067  *cp2++ = *cp++;
6068  }
6069  }
6070 
6071  /*
6072  * Now that we have the name and the value, store the record.
6073  */
6074  if (!conninfo_storeval(options, pname, pval, errorMessage, false, false))
6075  {
6077  free(buf);
6078  return NULL;
6079  }
6080  }
6081 
6082  /* Done with the modifiable input string */
6083  free(buf);
6084 
6085  /*
6086  * Add in defaults if the caller wants that.
6087  */
6088  if (use_defaults)
6089  {
6090  if (!conninfo_add_defaults(options, errorMessage))
6091  {
6093  return NULL;
6094  }
6095  }
6096 
6097  return options;
6098 }
static PQconninfoOption * conninfo_storeval(PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode)
Definition: fe-connect.c:6955
static char * buf
Definition: pg_test_fsync.c:67

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

Referenced by parse_connection_string().

◆ conninfo_storeval()

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

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

6959 {
6961  char *value_copy;
6962 
6963  /*
6964  * For backwards compatibility, requiressl=1 gets translated to
6965  * sslmode=require, and requiressl=0 gets translated to sslmode=prefer
6966  * (which is the default for sslmode).
6967  */
6968  if (strcmp(keyword, "requiressl") == 0)
6969  {
6970  keyword = "sslmode";
6971  if (value[0] == '1')
6972  value = "require";
6973  else
6974  value = "prefer";
6975  }
6976 
6977  option = conninfo_find(connOptions, keyword);
6978  if (option == NULL)
6979  {
6980  if (!ignoreMissing)
6981  libpq_append_error(errorMessage,
6982  "invalid connection option \"%s\"",
6983  keyword);
6984  return NULL;
6985  }
6986 
6987  if (uri_decode)
6988  {
6989  value_copy = conninfo_uri_decode(value, errorMessage);
6990  if (value_copy == NULL)
6991  /* conninfo_uri_decode already set an error message */
6992  return NULL;
6993  }
6994  else
6995  {
6996  value_copy = strdup(value);
6997  if (value_copy == NULL)
6998  {
6999  libpq_append_error(errorMessage, "out of memory");
7000  return NULL;
7001  }
7002  }
7003 
7004  free(option->val);
7005  option->val = value_copy;
7006 
7007  return option;
7008 }
static char * conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
Definition: fe-connect.c:6840
static struct @148 value

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

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

◆ conninfo_uri_decode()

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

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

6841 {
6842  char *buf;
6843  char *p;
6844  const char *q = str;
6845 
6846  buf = malloc(strlen(str) + 1);
6847  if (buf == NULL)
6848  {
6849  libpq_append_error(errorMessage, "out of memory");
6850  return NULL;
6851  }
6852  p = buf;
6853 
6854  for (;;)
6855  {
6856  if (*q != '%')
6857  {
6858  /* copy and check for NUL terminator */
6859  if (!(*(p++) = *(q++)))
6860  break;
6861  }
6862  else
6863  {
6864  int hi;
6865  int lo;
6866  int c;
6867 
6868  ++q; /* skip the percent sign itself */
6869 
6870  /*
6871  * Possible EOL will be caught by the first call to
6872  * get_hexdigit(), so we never dereference an invalid q pointer.
6873  */
6874  if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo)))
6875  {
6876  libpq_append_error(errorMessage,
6877  "invalid percent-encoded token: \"%s\"",
6878  str);
6879  free(buf);
6880  return NULL;
6881  }
6882 
6883  c = (hi << 4) | lo;
6884  if (c == 0)
6885  {
6886  libpq_append_error(errorMessage,
6887  "forbidden value %%00 in percent-encoded value: \"%s\"",
6888  str);
6889  free(buf);
6890  return NULL;
6891  }
6892  *(p++) = c;
6893  }
6894  }
6895 
6896  return buf;
6897 }
static bool get_hexdigit(char digit, int *value)
Definition: fe-connect.c:6908
char * c

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

Referenced by conninfo_storeval(), and conninfo_uri_parse_params().

◆ conninfo_uri_parse()

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

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

6415 {
6417 
6418  /* Make a working copy of PQconninfoOptions */
6419  options = conninfo_init(errorMessage);
6420  if (options == NULL)
6421  return NULL;
6422 
6423  if (!conninfo_uri_parse_options(options, uri, errorMessage))
6424  {
6426  return NULL;
6427  }
6428 
6429  /*
6430  * Add in defaults if the caller wants that.
6431  */
6432  if (use_defaults)
6433  {
6434  if (!conninfo_add_defaults(options, errorMessage))
6435  {
6437  return NULL;
6438  }
6439  }
6440 
6441  return options;
6442 }
static bool conninfo_uri_parse_options(PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage)
Definition: fe-connect.c:6466

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

Referenced by parse_connection_string().

◆ conninfo_uri_parse_options()

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

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

6468 {
6469  int prefix_len;
6470  char *p;
6471  char *buf = NULL;
6472  char *start;
6473  char prevchar = '\0';
6474  char *user = NULL;
6475  char *host = NULL;
6476  bool retval = false;
6477  PQExpBufferData hostbuf;
6478  PQExpBufferData portbuf;
6479 
6480  initPQExpBuffer(&hostbuf);
6481  initPQExpBuffer(&portbuf);
6482  if (PQExpBufferDataBroken(hostbuf) || PQExpBufferDataBroken(portbuf))
6483  {
6484  libpq_append_error(errorMessage, "out of memory");
6485  goto cleanup;
6486  }
6487 
6488  /* need a modifiable copy of the input URI */
6489  buf = strdup(uri);
6490  if (buf == NULL)
6491  {
6492  libpq_append_error(errorMessage, "out of memory");
6493  goto cleanup;
6494  }
6495  start = buf;
6496 
6497  /* Skip the URI prefix */
6498  prefix_len = uri_prefix_length(uri);
6499  if (prefix_len == 0)
6500  {
6501  /* Should never happen */
6502  libpq_append_error(errorMessage,
6503  "invalid URI propagated to internal parser routine: \"%s\"",
6504  uri);
6505  goto cleanup;
6506  }
6507  start += prefix_len;
6508  p = start;
6509 
6510  /* Look ahead for possible user credentials designator */
6511  while (*p && *p != '@' && *p != '/')
6512  ++p;
6513  if (*p == '@')
6514  {
6515  /*
6516  * Found username/password designator, so URI should be of the form
6517  * "scheme://user[:password]@[netloc]".
6518  */
6519  user = start;
6520 
6521  p = user;
6522  while (*p != ':' && *p != '@')
6523  ++p;
6524 
6525  /* Save last char and cut off at end of user name */
6526  prevchar = *p;
6527  *p = '\0';
6528 
6529  if (*user &&
6530  !conninfo_storeval(options, "user", user,
6531  errorMessage, false, true))
6532  goto cleanup;
6533 
6534  if (prevchar == ':')
6535  {
6536  const char *password = p + 1;
6537 
6538  while (*p != '@')
6539  ++p;
6540  *p = '\0';
6541 
6542  if (*password &&
6543  !conninfo_storeval(options, "password", password,
6544  errorMessage, false, true))
6545  goto cleanup;
6546  }
6547 
6548  /* Advance past end of parsed user name or password token */
6549  ++p;
6550  }
6551  else
6552  {
6553  /*
6554  * No username/password designator found. Reset to start of URI.
6555  */
6556  p = start;
6557  }
6558 
6559  /*
6560  * There may be multiple netloc[:port] pairs, each separated from the next
6561  * by a comma. When we initially enter this loop, "p" has been
6562  * incremented past optional URI credential information at this point and
6563  * now points at the "netloc" part of the URI. On subsequent loop
6564  * iterations, "p" has been incremented past the comma separator and now
6565  * points at the start of the next "netloc".
6566  */
6567  for (;;)
6568  {
6569  /*
6570  * Look for IPv6 address.
6571  */
6572  if (*p == '[')
6573  {
6574  host = ++p;
6575  while (*p && *p != ']')
6576  ++p;
6577  if (!*p)
6578  {
6579  libpq_append_error(errorMessage,
6580  "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"",
6581  uri);
6582  goto cleanup;
6583  }
6584  if (p == host)
6585  {
6586  libpq_append_error(errorMessage,
6587  "IPv6 host address may not be empty in URI: \"%s\"",
6588  uri);
6589  goto cleanup;
6590  }
6591 
6592  /* Cut off the bracket and advance */
6593  *(p++) = '\0';
6594 
6595  /*
6596  * The address may be followed by a port specifier or a slash or a
6597  * query or a separator comma.
6598  */
6599  if (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',')
6600  {
6601  libpq_append_error(errorMessage,
6602  "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"",
6603  *p, (int) (p - buf + 1), uri);
6604  goto cleanup;
6605  }
6606  }
6607  else
6608  {
6609  /* not an IPv6 address: DNS-named or IPv4 netloc */
6610  host = p;
6611 
6612  /*
6613  * Look for port specifier (colon) or end of host specifier
6614  * (slash) or query (question mark) or host separator (comma).
6615  */
6616  while (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',')
6617  ++p;
6618  }
6619 
6620  /* Save the hostname terminator before we null it */
6621  prevchar = *p;
6622  *p = '\0';
6623 
6624  appendPQExpBufferStr(&hostbuf, host);
6625 
6626  if (prevchar == ':')
6627  {
6628  const char *port = ++p; /* advance past host terminator */
6629 
6630  while (*p && *p != '/' && *p != '?' && *p != ',')
6631  ++p;
6632 
6633  prevchar = *p;
6634  *p = '\0';
6635 
6636  appendPQExpBufferStr(&portbuf, port);
6637  }
6638 
6639  if (prevchar != ',')
6640  break;
6641  ++p; /* advance past comma separator */
6642  appendPQExpBufferChar(&hostbuf, ',');
6643  appendPQExpBufferChar(&portbuf, ',');
6644  }
6645 
6646  /* Save final values for host and port. */
6647  if (PQExpBufferDataBroken(hostbuf) || PQExpBufferDataBroken(portbuf))
6648  goto cleanup;
6649  if (hostbuf.data[0] &&
6650  !conninfo_storeval(options, "host", hostbuf.data,
6651  errorMessage, false, true))
6652  goto cleanup;
6653  if (portbuf.data[0] &&
6654  !conninfo_storeval(options, "port", portbuf.data,
6655  errorMessage, false, true))
6656  goto cleanup;
6657 
6658  if (prevchar && prevchar != '?')
6659  {
6660  const char *dbname = ++p; /* advance past host terminator */
6661 
6662  /* Look for query parameters */
6663  while (*p && *p != '?')
6664  ++p;
6665 
6666  prevchar = *p;
6667  *p = '\0';
6668 
6669  /*
6670  * Avoid setting dbname to an empty string, as it forces the default
6671  * value (username) and ignores $PGDATABASE, as opposed to not setting
6672  * it at all.
6673  */
6674  if (*dbname &&
6675  !conninfo_storeval(options, "dbname", dbname,
6676  errorMessage, false, true))
6677  goto cleanup;
6678  }
6679 
6680  if (prevchar)
6681  {
6682  ++p; /* advance past terminator */
6683 
6684  if (!conninfo_uri_parse_params(p, options, errorMessage))
6685  goto cleanup;
6686  }
6687 
6688  /* everything parsed okay */
6689  retval = true;
6690 
6691 cleanup:
6692  termPQExpBuffer(&hostbuf);
6693  termPQExpBuffer(&portbuf);
6694  free(buf);
6695  return retval;
6696 }
static void cleanup(void)
Definition: bootstrap.c:687
static int uri_prefix_length(const char *connstr)
Definition: fe-connect.c:5910
static bool conninfo_uri_parse_params(char *params, PQconninfoOption *connOptions, PQExpBuffer errorMessage)
Definition: fe-connect.c:6707
static char * user
Definition: pg_regress.c:112
static int port
Definition: pg_regress.c:109
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:90
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:378
void termPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:129
#define PQExpBufferDataBroken(buf)
Definition: pqexpbuffer.h:67
static char * password
Definition: streamutil.c:53
char * dbname
Definition: streamutil.c:51

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

Referenced by conninfo_uri_parse().

◆ conninfo_uri_parse_params()

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

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

6710 {
6711  while (*params)
6712  {
6713  char *keyword = params;
6714  char *value = NULL;
6715  char *p = params;
6716  bool malloced = false;
6717  int oldmsglen;
6718 
6719  /*
6720  * Scan the params string for '=' and '&', marking the end of keyword
6721  * and value respectively.
6722  */
6723  for (;;)
6724  {
6725  if (*p == '=')
6726  {
6727  /* Was there '=' already? */
6728  if (value != NULL)
6729  {
6730  libpq_append_error(errorMessage,
6731  "extra key/value separator \"=\" in URI query parameter: \"%s\"",
6732  keyword);
6733  return false;
6734  }
6735  /* Cut off keyword, advance to value */
6736  *p++ = '\0';
6737  value = p;
6738  }
6739  else if (*p == '&' || *p == '\0')
6740  {
6741  /*
6742  * If not at the end, cut off value and advance; leave p
6743  * pointing to start of the next parameter, if any.
6744  */
6745  if (*p != '\0')
6746  *p++ = '\0';
6747  /* Was there '=' at all? */
6748  if (value == NULL)
6749  {
6750  libpq_append_error(errorMessage,
6751  "missing key/value separator \"=\" in URI query parameter: \"%s\"",
6752  keyword);
6753  return false;
6754  }
6755  /* Got keyword and value, go process them. */
6756  break;
6757  }
6758  else
6759  ++p; /* Advance over all other bytes. */
6760  }
6761 
6762  keyword = conninfo_uri_decode(keyword, errorMessage);
6763  if (keyword == NULL)
6764  {
6765  /* conninfo_uri_decode already set an error message */
6766  return false;
6767  }
6768  value = conninfo_uri_decode(value, errorMessage);
6769  if (value == NULL)
6770  {
6771  /* conninfo_uri_decode already set an error message */
6772  free(keyword);
6773  return false;
6774  }
6775  malloced = true;
6776 
6777  /*
6778  * Special keyword handling for improved JDBC compatibility.
6779  */
6780  if (strcmp(keyword, "ssl") == 0 &&
6781  strcmp(value, "true") == 0)
6782  {
6783  free(keyword);
6784  free(value);
6785  malloced = false;
6786 
6787  keyword = "sslmode";
6788  value = "require";
6789  }
6790 
6791  /*
6792  * Store the value if the corresponding option exists; ignore
6793  * otherwise. At this point both keyword and value are not
6794  * URI-encoded.
6795  */
6796  oldmsglen = errorMessage->len;
6797  if (!conninfo_storeval(connOptions, keyword, value,
6798  errorMessage, true, false))
6799  {
6800  /* Insert generic message if conninfo_storeval didn't give one. */
6801  if (errorMessage->len == oldmsglen)
6802  libpq_append_error(errorMessage,
6803  "invalid URI query parameter: \"%s\"",
6804  keyword);
6805  /* And fail. */
6806  if (malloced)
6807  {
6808  free(keyword);
6809  free(value);
6810  }
6811  return false;
6812  }
6813 
6814  if (malloced)
6815  {
6816  free(keyword);
6817  free(value);
6818  }
6819 
6820  /* Proceed to next key=value pair, if any */
6821  params = p;
6822  }
6823 
6824  return true;
6825 }

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

Referenced by conninfo_uri_parse_options().

◆ count_comma_separated_elems()

static int count_comma_separated_elems ( const char *  input)
static

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

983 {
984  int n;
985 
986  n = 1;
987  for (; *input != '\0'; input++)
988  {
989  if (*input == ',')
990  n++;
991  }
992 
993  return n;
994 }
FILE * input

References input.

Referenced by connectOptions2().

◆ default_threadlock()

static void default_threadlock ( int  acquire)
static

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

7789 {
7790 #ifndef WIN32
7791  static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
7792 #else
7793  static pthread_mutex_t singlethread_lock = NULL;
7794  static long mutex_initlock = 0;
7795 
7796  if (singlethread_lock == NULL)
7797  {
7798  while (InterlockedExchange(&mutex_initlock, 1) == 1)
7799  /* loop, another thread own the lock */ ;
7800  if (singlethread_lock == NULL)
7801  {
7802  if (pthread_mutex_init(&singlethread_lock, NULL))
7803  Assert(false);
7804  }
7805  InterlockedExchange(&mutex_initlock, 0);
7806  }
7807 #endif
7808  if (acquire)
7809  {
7810  if (pthread_mutex_lock(&singlethread_lock))
7811  Assert(false);
7812  }
7813  else
7814  {
7815  if (pthread_mutex_unlock(&singlethread_lock))
7816  Assert(false);
7817  }
7818 }
int pthread_mutex_unlock(pthread_mutex_t *mp)
Definition: pthread-win32.c:54
int pthread_mutex_lock(pthread_mutex_t *mp)
Definition: pthread-win32.c:45
int pthread_mutex_init(pthread_mutex_t *mp, void *attr)
Definition: pthread-win32.c:35
CRITICAL_SECTION * pthread_mutex_t
Definition: pthread-win32.h:8

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

Referenced by PQregisterThreadLock().

◆ defaultNoticeProcessor()

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

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

7466 {
7467  (void) arg; /* not used */
7468  /* Note: we expect the supplied string to end with a newline already. */
7469  fprintf(stderr, "%s", message);
7470 }
void * arg
#define fprintf
Definition: port.h:242

References arg, and fprintf.

Referenced by makeEmptyPGconn().

◆ defaultNoticeReceiver()

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

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

7451 {
7452  (void) arg; /* not used */
7453  if (res->noticeHooks.noticeProc != NULL)
7456 }
char * PQresultErrorMessage(const PGresult *res)
Definition: fe-exec.c:3341
void * noticeProcArg
Definition: libpq-int.h:158
PQnoticeProcessor noticeProc
Definition: libpq-int.h:157
PGNoticeHooks noticeHooks
Definition: libpq-int.h:189

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

Referenced by makeEmptyPGconn().

◆ emitHostIdentityInfo()

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

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

1991 {
1992  if (conn->raddr.addr.ss_family == AF_UNIX)
1993  {
1994  char service[NI_MAXHOST];
1995 
1997  NULL, 0,
1998  service, sizeof(service),
1999  NI_NUMERICSERV);
2001  libpq_gettext("connection to server on socket \"%s\" failed: "),
2002  service);
2003  }
2004  else
2005  {
2006  const char *displayed_host;
2007  const char *displayed_port;
2008 
2009  /* To which host and port were we actually connecting? */
2011  displayed_host = conn->connhost[conn->whichhost].hostaddr;
2012  else
2013  displayed_host = conn->connhost[conn->whichhost].host;
2014  displayed_port = conn->connhost[conn->whichhost].port;
2015  if (displayed_port == NULL || displayed_port[0] == '\0')
2016  displayed_port = DEF_PGPORT_STR;
2017 
2018  /*
2019  * If the user did not supply an IP address using 'hostaddr', and
2020  * 'host' was missing or does not match our lookup, display the
2021  * looked-up IP address.
2022  */
2024  host_addr[0] &&
2025  strcmp(displayed_host, host_addr) != 0)
2027  libpq_gettext("connection to server at \"%s\" (%s), port %s failed: "),
2028  displayed_host, host_addr,
2029  displayed_port);
2030  else
2032  libpq_gettext("connection to server at \"%s\", port %s failed: "),
2033  displayed_host,
2034  displayed_port);
2035  }
2036 }
int pg_getnameinfo_all(const struct sockaddr_storage *addr, int salen, char *node, int nodelen, char *service, int servicelen, int flags)
Definition: ip.c:114
#define libpq_gettext(x)
Definition: libpq-int.h:900
socklen_t salen
Definition: pqcomm.h:33

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

Referenced by PQconnectPoll().

◆ fillPGconn()

static bool fillPGconn ( PGconn conn,
PQconninfoOption connOptions 
)
static

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

906 {
908 
909  for (option = PQconninfoOptions; option->keyword; option++)
910  {
911  if (option->connofs >= 0)
912  {
913  const char *tmp = conninfo_getval(connOptions, option->keyword);
914 
915  if (tmp)
916  {
917  char **connmember = (char **) ((char *) conn + option->connofs);
918 
919  free(*connmember);
920  *connmember = strdup(tmp);
921  if (*connmember == NULL)
922  {
923  libpq_append_conn_error(conn, "out of memory");
924  return false;
925  }
926  }
927  }
928  }
929 
930  return true;
931 }
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6929

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

Referenced by connectOptions1(), and PQconnectStartParams().

◆ freePGconn()

static void freePGconn ( PGconn conn)
static

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

4388 {
4389  /* let any event procs clean up their state data */
4390  for (int i = 0; i < conn->nEvents; i++)
4391  {
4392  PGEventConnDestroy evt;
4393 
4394  evt.conn = conn;
4395  (void) conn->events[i].proc(PGEVT_CONNDESTROY, &evt,
4396  conn->events[i].passThrough);
4397  free(conn->events[i].name);
4398  }
4399 
4400  /* clean up pg_conn_host structures */
4401  for (int i = 0; i < conn->nconnhost; ++i)
4402  {
4403  free(conn->connhost[i].host);
4405  free(conn->connhost[i].port);
4406  if (conn->connhost[i].password != NULL)
4407  {
4410  }
4411  }
4412  free(conn->connhost);
4413 
4415  free(conn->events);
4416  free(conn->pghost);
4417  free(conn->pghostaddr);
4418  free(conn->pgport);
4421  free(conn->pgoptions);
4422  free(conn->appname);
4423  free(conn->fbappname);
4424  free(conn->dbName);
4425  free(conn->replication);
4426  free(conn->pguser);
4427  if (conn->pgpass)
4428  {
4429  explicit_bzero(conn->pgpass, strlen(conn->pgpass));
4430  free(conn->pgpass);
4431  }
4432  free(conn->pgpassfile);
4434  free(conn->keepalives);
4438  free(conn->sslmode);
4439  free(conn->sslcert);
4440  free(conn->sslkey);
4441  if (conn->sslpassword)
4442  {
4444  free(conn->sslpassword);
4445  }
4446  free(conn->sslcertmode);
4447  free(conn->sslrootcert);
4448  free(conn->sslcrl);
4449  free(conn->sslcrldir);
4451  free(conn->sslsni);
4452  free(conn->requirepeer);
4456  free(conn->gssencmode);
4457  free(conn->krbsrvname);
4458  free(conn->gsslib);
4460  free(conn->connip);
4461  /* Note that conn->Pfdebug is not ours to close or free */
4463  free(conn->inBuffer);
4464  free(conn->outBuffer);
4465  free(conn->rowBuf);
4470 
4471  free(conn);
4472 }
@ PGEVT_CONNDESTROY
Definition: libpq-events.h:31
void explicit_bzero(void *buf, size_t len)
void * passThrough
Definition: libpq-int.h:165
char * name
Definition: libpq-int.h:164
PGEventProc proc
Definition: libpq-int.h:163
char * replication
Definition: libpq-int.h:378
char * write_err_msg
Definition: libpq-int.h:471
PGdataValue * rowBuf
Definition: libpq-int.h:525
char * sslcompression
Definition: libpq-int.h:391
char * inBuffer
Definition: libpq-int.h:508
char * sslcrldir
Definition: libpq-int.h:398
char * gssdelegation
Definition: libpq-int.h:405
char * pgoptions
Definition: libpq-int.h:374
char * sslcrl
Definition: libpq-int.h:397
char * fbappname
Definition: libpq-int.h:376
char * sslcert
Definition: libpq-int.h:393
char * sslpassword
Definition: libpq-int.h:394
PQExpBufferData workBuffer
Definition: libpq-int.h:621
char * keepalives_idle
Definition: libpq-int.h:385
char * connip
Definition: libpq-int.h:443
char * keepalives
Definition: libpq-int.h:384
char * keepalives_interval
Definition: libpq-int.h:386
char * appname
Definition: libpq-int.h:375
char * pgtcp_user_timeout
Definition: libpq-int.h:372
int nEvents
Definition: libpq-int.h:421
char * sslkey
Definition: libpq-int.h:392
char * krbsrvname
Definition: libpq-int.h:402
char * gsslib
Definition: libpq-int.h:403
char * keepalives_count
Definition: libpq-int.h:388
char * requirepeer
Definition: libpq-int.h:400
char * sslsni
Definition: libpq-int.h:399
PGEvent * events
Definition: libpq-int.h:420
char * outBuffer
Definition: libpq-int.h:515

References pg_conn::appname, pg_conn::channel_binding, pg_conn::client_encoding_initial, conn, PGEventConnDestroy::conn, pg_conn::connect_timeout, pg_conn::connhost, pg_conn::connip, pg_conn::dbName, pg_conn::errorMessage, pg_conn::events, explicit_bzero(), pg_conn::fbappname, free, pg_conn::gssdelegation, 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::load_balance_hosts, PGEvent::name, pg_conn::nconnhost, pg_conn::nEvents, pg_conn::outBuffer, PGEvent::passThrough, pg_conn_host::password, PGEVT_CONNDESTROY, pg_conn::pghost, pg_conn::pghostaddr, pg_conn::pgoptions, pg_conn::pgpass, pg_conn::pgpassfile, pg_conn::pgport, pg_conn::pgtcp_user_timeout, pg_conn::pguser, pg_conn_host::port, PGEvent::proc, pg_conn::replication, pg_conn::require_auth, pg_conn::requirepeer, pg_conn::rowBuf, pg_conn::ssl_max_protocol_version, pg_conn::ssl_min_protocol_version, pg_conn::sslcert, pg_conn::sslcertmode, pg_conn::sslcompression, pg_conn::sslcrl, pg_conn::sslcrldir, pg_conn::sslkey, pg_conn::sslmode, pg_conn::sslpassword, pg_conn::sslrootcert, pg_conn::sslsni, pg_conn::target_session_attrs, termPQExpBuffer(), pg_conn::workBuffer, and pg_conn::write_err_msg.

Referenced by makeEmptyPGconn(), and PQfinish().

◆ get_hexdigit()

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

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

6909 {
6910  if ('0' <= digit && digit <= '9')
6911  *value = digit - '0';
6912  else if ('A' <= digit && digit <= 'F')
6913  *value = digit - 'A' + 10;
6914  else if ('a' <= digit && digit <= 'f')
6915  *value = digit - 'a' + 10;
6916  else
6917  return false;
6918 
6919  return true;
6920 }

References value.

Referenced by conninfo_uri_decode().

◆ getHostaddr()

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

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

1958 {
1959  struct sockaddr_storage *addr = &conn->raddr.addr;
1960 
1961  if (addr->ss_family == AF_INET)
1962  {
1963  if (pg_inet_net_ntop(AF_INET,
1964  &((struct sockaddr_in *) addr)->sin_addr.s_addr,
1965  32,
1966  host_addr, host_addr_len) == NULL)
1967  host_addr[0] = '\0';
1968  }
1969  else if (addr->ss_family == AF_INET6)
1970  {
1971  if (pg_inet_net_ntop(AF_INET6,
1972  &((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr,
1973  128,
1974  host_addr, host_addr_len) == NULL)
1975  host_addr[0] = '\0';
1976  }
1977  else
1978  host_addr[0] = '\0';
1979 }
char * pg_inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size)
Definition: inet_net_ntop.c:77

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

Referenced by PQconnectPoll().

◆ internal_ping()

static PGPing internal_ping ( PGconn conn)
static

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

4225 {
4226  /* Say "no attempt" if we never got to PQconnectPoll */
4227  if (!conn || !conn->options_valid)
4228  return PQPING_NO_ATTEMPT;
4229 
4230  /* Attempt to complete the connection */
4231  if (conn->status != CONNECTION_BAD)
4232  (void) connectDBComplete(conn);
4233 
4234  /* Definitely OK if we succeeded */
4235  if (conn->status != CONNECTION_BAD)
4236  return PQPING_OK;
4237 
4238  /*
4239  * Here begins the interesting part of "ping": determine the cause of the
4240  * failure in sufficient detail to decide what to return. We do not want
4241  * to report that the server is not up just because we didn't have a valid
4242  * password, for example. In fact, any sort of authentication request
4243  * implies the server is up. (We need this check since the libpq side of
4244  * things might have pulled the plug on the connection before getting an
4245  * error as such from the postmaster.)
4246  */
4247  if (conn->auth_req_received)
4248  return PQPING_OK;
4249 
4250  /*
4251  * If we failed to get any ERROR response from the postmaster, report
4252  * PQPING_NO_RESPONSE. This result could be somewhat misleading for a
4253  * pre-7.4 server, since it won't send back a SQLSTATE, but those are long
4254  * out of support. Another corner case where the server could return a
4255  * failure without a SQLSTATE is fork failure, but PQPING_NO_RESPONSE
4256  * isn't totally unreasonable for that anyway. We expect that every other
4257  * failure case in a modern server will produce a report with a SQLSTATE.
4258  *
4259  * NOTE: whenever we get around to making libpq generate SQLSTATEs for
4260  * client-side errors, we should either not store those into
4261  * last_sqlstate, or add an extra flag so we can tell client-side errors
4262  * apart from server-side ones.
4263  */
4264  if (strlen(conn->last_sqlstate) != 5)
4265  return PQPING_NO_RESPONSE;
4266 
4267  /*
4268  * Report PQPING_REJECT if server says it's not accepting connections.
4269  */
4270  if (strcmp(conn->last_sqlstate, ERRCODE_CANNOT_CONNECT_NOW) == 0)
4271  return PQPING_REJECT;
4272 
4273  /*
4274  * Any other SQLSTATE can be taken to indicate that the server is up.
4275  * Presumably it didn't like our username, password, or database name; or
4276  * perhaps it had some transient failure, but that should not be taken as
4277  * meaning "it's down".
4278  */
4279  return PQPING_OK;
4280 }
static int connectDBComplete(PGconn *conn)
Definition: fe-connect.c:2405
#define ERRCODE_CANNOT_CONNECT_NOW
Definition: fe-connect.c:91
@ PQPING_OK
Definition: libpq-fe.h:147
@ PQPING_REJECT
Definition: libpq-fe.h:148
@ PQPING_NO_RESPONSE
Definition: libpq-fe.h:149
@ PQPING_NO_ATTEMPT
Definition: libpq-fe.h:150
bool auth_req_received
Definition: libpq-int.h:465
char last_sqlstate[6]
Definition: libpq-int.h:428

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

Referenced by PQping(), and PQpingParams().

◆ libpq_prng_init()

static void libpq_prng_init ( PGconn conn)
static

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

1042 {
1043  uint64 rseed;
1044  struct timeval tval = {0};
1045 
1047  return;
1048 
1049  gettimeofday(&tval, NULL);
1050 
1051  rseed = ((uintptr_t) conn) ^
1052  ((uint64) getpid()) ^
1053  ((uint64) tval.tv_usec) ^
1054  ((uint64) tval.tv_sec);
1055 
1056  pg_prng_seed(&conn->prng_state, rseed);
1057 }
void pg_prng_seed(pg_prng_state *state, uint64 seed)
Definition: pg_prng.c:89
#define pg_prng_strong_seed(state)
Definition: pg_prng.h:46
int gettimeofday(struct timeval *tp, void *tzp)

References conn, gettimeofday(), pg_prng_seed(), pg_prng_strong_seed, and pg_conn::prng_state.

Referenced by connectOptions2().

◆ makeEmptyPGconn()

static PGconn * makeEmptyPGconn ( void  )
static

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

4289 {
4290  PGconn *conn;
4291 
4292 #ifdef WIN32
4293 
4294  /*
4295  * Make sure socket support is up and running in this process.
4296  *
4297  * Note: the Windows documentation says that we should eventually do a
4298  * matching WSACleanup() call, but experience suggests that that is at
4299  * least as likely to cause problems as fix them. So we don't.
4300  */
4301  static bool wsastartup_done = false;
4302 
4303  if (!wsastartup_done)
4304  {
4305  WSADATA wsaData;
4306 
4307  if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
4308  return NULL;
4309  wsastartup_done = true;
4310  }
4311 
4312  /* Forget any earlier error */
4313  WSASetLastError(0);
4314 #endif /* WIN32 */
4315 
4316  conn = (PGconn *) malloc(sizeof(PGconn));
4317  if (conn == NULL)
4318  return conn;
4319 
4320  /* Zero all pointers and booleans */
4321  MemSet(conn, 0, sizeof(PGconn));
4322 
4323  /* install default notice hooks */
4326 
4331  conn->options_valid = false;
4332  conn->nonblocking = false;
4334  conn->std_strings = false; /* unless server says differently */
4341  conn->Pfdebug = NULL;
4342 
4343  /*
4344  * We try to send at least 8K at a time, which is the usual size of pipe
4345  * buffers on Unix systems. That way, when we are sending a large amount
4346  * of data, we avoid incurring extra kernel context swaps for partial
4347  * bufferloads. The output buffer is initially made 16K in size, and we
4348  * try to dump it after accumulating 8K.
4349  *
4350  * With the same goal of minimizing context swaps, the input buffer will
4351  * be enlarged anytime it has less than 8K free, so we initially allocate
4352  * twice that.
4353  */
4354  conn->inBufSize = 16 * 1024;
4355  conn->inBuffer = (char *) malloc(conn->inBufSize);
4356  conn->outBufSize = 16 * 1024;
4357  conn->outBuffer = (char *) malloc(conn->outBufSize);
4358  conn->rowBufLen = 32;
4359  conn->rowBuf = (PGdataValue *) malloc(conn->rowBufLen * sizeof(PGdataValue));
4362 
4363  if (conn->inBuffer == NULL ||
4364  conn->outBuffer == NULL ||
4365  conn->rowBuf == NULL ||
4368  {
4369  /* out of memory already :-( */
4370  freePGconn(conn);
4371  conn = NULL;
4372  }
4373 
4374  return conn;
4375 }
static void defaultNoticeReceiver(void *arg, const PGresult *res)
Definition: fe-connect.c:7450
static void defaultNoticeProcessor(void *arg, const char *message)
Definition: fe-connect.c:7465
static void freePGconn(PGconn *conn)
Definition: fe-connect.c:4387
@ PQSHOW_CONTEXT_ERRORS
Definition: libpq-fe.h:136
@ PQERRORS_DEFAULT
Definition: libpq-fe.h:128
@ PG_BOOL_UNKNOWN
Definition: libpq-int.h:256
@ PG_SQL_ASCII
Definition: pg_wchar.h:226
#define PGINVALID_SOCKET
Definition: port.h:31
#define PQExpBufferBroken(str)
Definition: pqexpbuffer.h:59
#define SCRAM_SHA_256_DEFAULT_ITERATIONS
Definition: scram-common.h:50
PQnoticeReceiver noticeRec
Definition: libpq-int.h:155
bool std_strings
Definition: libpq-int.h:498
PGTernaryBool in_hot_standby
Definition: libpq-int.h:500
int inBufSize
Definition: libpq-int.h:509
int client_encoding
Definition: libpq-int.h:497
PGTernaryBool default_transaction_read_only
Definition: libpq-int.h:499
PGVerbosity verbosity
Definition: libpq-int.h:501
int rowBufLen
Definition: libpq-int.h:526
int scram_sha_256_iterations
Definition: libpq-int.h:544
int outBufSize
Definition: libpq-int.h:516
PGNoticeHooks noticeHooks
Definition: libpq-int.h:417
FILE * Pfdebug
Definition: libpq-int.h:413
PGContextVisibility show_context
Definition: libpq-int.h:502

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

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

◆ optional_setsockopt()

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

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

4790 {
4791  if (value < 0)
4792  return true;
4793  if (setsockopt(fd, protoid, optid, (char *) &value, sizeof(value)) < 0)
4794  return false;
4795  return true;
4796 }
static int fd(const char *x, int i)
Definition: preproc-init.c:105

References fd(), and value.

Referenced by PQcancel().

◆ parse_comma_separated_list()

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

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

1007 {
1008  char *p;
1009  char *s = *startptr;
1010  char *e;
1011  int len;
1012 
1013  /*
1014  * Search for the end of the current element; a comma or end-of-string
1015  * acts as a terminator.
1016  */
1017  e = s;
1018  while (*e != '\0' && *e != ',')
1019  ++e;
1020  *more = (*e == ',');
1021 
1022  len = e - s;
1023  p = (char *) malloc(sizeof(char) * (len + 1));
1024  if (p)
1025  {
1026  memcpy(p, s, len);
1027  p[len] = '\0';
1028  }
1029  *startptr = e + 1;
1030 
1031  return p;
1032 }
const void size_t len
e
Definition: preproc-init.c:82

References len, and malloc.

Referenced by connectOptions2().

◆ parse_connection_string()

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

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

5892 {
5893  /* Parse as URI if connection string matches URI prefix */
5894  if (uri_prefix_length(connstr) != 0)
5895  return conninfo_uri_parse(connstr, errorMessage, use_defaults);
5896 
5897  /* Parse as default otherwise */
5898  return conninfo_parse(connstr, errorMessage, use_defaults);
5899 }
static PQconninfoOption * conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:6413
static PQconninfoOption * conninfo_parse(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5944
static char * connstr
Definition: pg_dumpall.c:88

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

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

◆ parse_int_param()

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

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

2087 {
2088  char *end;
2089  long numval;
2090 
2091  Assert(value != NULL);
2092 
2093  *result = 0;
2094 
2095  /* strtol(3) skips leading whitespaces */
2096  errno = 0;
2097  numval = strtol(value, &end, 10);
2098 
2099  /*
2100  * If no progress was done during the parsing or an error happened, fail.
2101  * This tests properly for overflows of the result.
2102  */
2103  if (value == end || errno != 0 || numval != (int) numval)
2104  goto error;
2105 
2106  /*
2107  * Skip any trailing whitespace; if anything but whitespace remains before
2108  * the terminating character, fail
2109  */
2110  while (*end != '\0' && isspace((unsigned char) *end))
2111  end++;
2112 
2113  if (*end != '\0')
2114  goto error;
2115 
2116  *result = numval;
2117  return true;
2118 
2119 error:
2120  libpq_append_conn_error(conn, "invalid integer value \"%s\" for connection option \"%s\"",
2121  value, context);
2122  return false;
2123 }
static void error(void)
Definition: sql-dyntest.c:147

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

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

◆ parseServiceFile()

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

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

5656 {
5657  int result = 0,
5658  linenr = 0,
5659  i;
5660  FILE *f;
5661  char *line;
5662  char buf[1024];
5663 
5664  *group_found = false;
5665 
5666  f = fopen(serviceFile, "r");
5667  if (f == NULL)
5668  {
5669  libpq_append_error(errorMessage, "service file \"%s\" not found", serviceFile);
5670  return 1;
5671  }
5672 
5673  while ((line = fgets(buf, sizeof(buf), f)) != NULL)
5674  {
5675  int len;
5676 
5677  linenr++;
5678 
5679  if (strlen(line) >= sizeof(buf) - 1)
5680  {
5681  libpq_append_error(errorMessage,
5682  "line %d too long in service file \"%s\"",
5683  linenr,
5684  serviceFile);
5685  result = 2;
5686  goto exit;
5687  }
5688 
5689  /* ignore whitespace at end of line, especially the newline */
5690  len = strlen(line);
5691  while (len > 0 && isspace((unsigned char) line[len - 1]))
5692  line[--len] = '\0';
5693 
5694  /* ignore leading whitespace too */
5695  while (*line && isspace((unsigned char) line[0]))
5696  line++;
5697 
5698  /* ignore comments and empty lines */
5699  if (line[0] == '\0' || line[0] == '#')
5700  continue;
5701 
5702  /* Check for right groupname */
5703  if (line[0] == '[')
5704  {
5705  if (*group_found)
5706  {
5707  /* end of desired group reached; return success */
5708  goto exit;
5709  }
5710 
5711  if (strncmp(line + 1, service, strlen(service)) == 0 &&
5712  line[strlen(service) + 1] == ']')
5713  *group_found = true;
5714  else
5715  *group_found = false;
5716  }
5717  else
5718  {
5719  if (*group_found)
5720  {
5721  /*
5722  * Finally, we are in the right group and can parse the line
5723  */
5724  char *key,
5725  *val;
5726  bool found_keyword;
5727 
5728 #ifdef USE_LDAP
5729  if (strncmp(line, "ldap", 4) == 0)
5730  {
5731  int rc = ldapServiceLookup(line, options, errorMessage);
5732 
5733  /* if rc = 2, go on reading for fallback */
5734  switch (rc)
5735  {
5736  case 0:
5737  goto exit;
5738  case 1:
5739  case 3:
5740  result = 3;
5741  goto exit;
5742  case 2:
5743  continue;
5744  }
5745  }
5746 #endif
5747 
5748  key = line;
5749  val = strchr(line, '=');
5750  if (val == NULL)
5751  {
5752  libpq_append_error(errorMessage,
5753  "syntax error in service file \"%s\", line %d",
5754  serviceFile,
5755  linenr);
5756  result = 3;
5757  goto exit;
5758  }
5759  *val++ = '\0';
5760 
5761  if (strcmp(key, "service") == 0)
5762  {
5763  libpq_append_error(errorMessage,
5764  "nested service specifications not supported in service file \"%s\", line %d",
5765  serviceFile,
5766  linenr);
5767  result = 3;
5768  goto exit;
5769  }
5770 
5771  /*
5772  * Set the parameter --- but don't override any previous
5773  * explicit setting.
5774  */
5775  found_keyword = false;
5776  for (i = 0; options[i].keyword; i++)
5777  {
5778  if (strcmp(options[i].keyword, key) == 0)
5779  {
5780  if (options[i].val == NULL)
5781  options[i].val = strdup(val);
5782  if (!options[i].val)
5783  {
5784  libpq_append_error(errorMessage, "out of memory");
5785  result = 3;
5786  goto exit;
5787  }
5788  found_keyword = true;
5789  break;
5790  }
5791  }
5792 
5793  if (!found_keyword)
5794  {
5795  libpq_append_error(errorMessage,
5796  "syntax error in service file \"%s\", line %d",
5797  serviceFile,
5798  linenr);
5799  result = 3;
5800  goto exit;
5801  }
5802  }
5803  }
5804  }
5805 
5806 exit:
5807  fclose(f);
5808 
5809  return result;
5810 }
exit(1)

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

Referenced by parseServiceInfo().

◆ parseServiceInfo()

static int parseServiceInfo ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

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

5584 {
5585  const char *service = conninfo_getval(options, "service");
5586  char serviceFile[MAXPGPATH];
5587  char *env;
5588  bool group_found = false;
5589  int status;
5590  struct stat stat_buf;
5591 
5592  /*
5593  * We have to special-case the environment variable PGSERVICE here, since
5594  * this is and should be called before inserting environment defaults for
5595  * other connection options.
5596  */
5597  if (service == NULL)
5598  service = getenv("PGSERVICE");
5599 
5600  /* If no service name given, nothing to do */
5601  if (service == NULL)
5602  return 0;
5603 
5604  /*
5605  * Try PGSERVICEFILE if specified, else try ~/.pg_service.conf (if that
5606  * exists).
5607  */
5608  if ((env = getenv("PGSERVICEFILE")) != NULL)
5609  strlcpy(serviceFile, env, sizeof(serviceFile));
5610  else
5611  {
5612  char homedir[MAXPGPATH];
5613 
5614  if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
5615  goto next_file;
5616  snprintf(serviceFile, MAXPGPATH, "%s/%s", homedir, ".pg_service.conf");
5617  if (stat(serviceFile, &stat_buf) != 0)
5618  goto next_file;
5619  }
5620 
5621  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
5622  if (group_found || status != 0)
5623  return status;
5624 
5625 next_file:
5626 
5627  /*
5628  * This could be used by any application so we can't use the binary
5629  * location to find our config files.
5630  */
5631  snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf",
5632  getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);
5633  if (stat(serviceFile, &stat_buf) != 0)
5634  goto last_file;
5635 
5636  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
5637  if (status != 0)
5638  return status;
5639 
5640 last_file:
5641  if (!group_found)
5642  {
5643  libpq_append_error(errorMessage, "definition of service \"%s\" not found", service);
5644  return 3;
5645  }
5646 
5647  return 0;
5648 }
static int parseServiceFile(const char *serviceFile, const char *service, PQconninfoOption *options, PQExpBuffer errorMessage, bool *group_found)
Definition: fe-connect.c:5651
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define stat
Definition: win32_port.h:284

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

Referenced by conninfo_add_defaults().

◆ passwordFromFile()

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

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

7516 {
7517  FILE *fp;
7518  struct stat stat_buf;
7520 
7521  if (dbname == NULL || dbname[0] == '\0')
7522  return NULL;
7523 
7524  if (username == NULL || username[0] == '\0')
7525  return NULL;
7526 
7527  /* 'localhost' matches pghost of '' or the default socket directory */
7528  if (hostname == NULL || hostname[0] == '\0')
7530  else if (is_unixsock_path(hostname))
7531 
7532  /*
7533  * We should probably use canonicalize_path(), but then we have to
7534  * bring path.c into libpq, and it doesn't seem worth it.
7535  */
7536  if (strcmp(hostname, DEFAULT_PGSOCKET_DIR) == 0)
7538 
7539  if (port == NULL || port[0] == '\0')
7540  port = DEF_PGPORT_STR;
7541 
7542  /* If password file cannot be opened, ignore it. */
7543  if (stat(pgpassfile, &stat_buf) != 0)
7544  return NULL;
7545 
7546 #ifndef WIN32
7547  if (!S_ISREG(stat_buf.st_mode))
7548  {
7549  fprintf(stderr,
7550  libpq_gettext("WARNING: password file \"%s\" is not a plain file\n"),
7551  pgpassfile);
7552  return NULL;
7553  }
7554 
7555  /* If password file is insecure, alert the user and ignore it. */
7556  if (stat_buf.st_mode & (S_IRWXG | S_IRWXO))
7557  {
7558  fprintf(stderr,
7559  libpq_gettext("WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
7560  pgpassfile);
7561  return NULL;
7562  }
7563 #else
7564 
7565  /*
7566  * On Win32, the directory is protected, so we don't have to check the
7567  * file.
7568  */
7569 #endif
7570 
7571  fp = fopen(pgpassfile, "r");
7572  if (fp == NULL)
7573  return NULL;
7574 
7575  /* Use an expansible buffer to accommodate any reasonable line length */
7576  initPQExpBuffer(&buf);
7577 
7578  while (!feof(fp) && !ferror(fp))
7579  {
7580  /* Make sure there's a reasonable amount of room in the buffer */
7581  if (!enlargePQExpBuffer(&buf, 128))
7582  break;
7583 
7584  /* Read some data, appending it to what we already have */
7585  if (fgets(buf.data + buf.len, buf.maxlen - buf.len, fp) == NULL)
7586  break;
7587  buf.len += strlen(buf.data + buf.len);
7588 
7589  /* If we don't yet have a whole line, loop around to read more */
7590  if (!(buf.len > 0 && buf.data[buf.len - 1] == '\n') && !feof(fp))
7591  continue;
7592 
7593  /* ignore comments */
7594  if (buf.data[0] != '#')
7595  {
7596  char *t = buf.data;
7597  int len;
7598 
7599  /* strip trailing newline and carriage return */
7600  len = pg_strip_crlf(t);
7601 
7602  if (len > 0 &&
7603  (t = pwdfMatchesString(t, hostname)) != NULL &&
7604  (t = pwdfMatchesString(t, port)) != NULL &&
7605  (t = pwdfMatchesString(t, dbname)) != NULL &&
7606  (t = pwdfMatchesString(t, username)) != NULL)
7607  {
7608  /* Found a match. */
7609  char *ret,
7610  *p1,
7611  *p2;
7612 
7613  ret = strdup(t);
7614 
7615  fclose(fp);
7616  explicit_bzero(buf.data, buf.maxlen);
7617  termPQExpBuffer(&buf);
7618 
7619  if (!ret)
7620  {
7621  /* Out of memory. XXX: an error message would be nice. */
7622  return NULL;
7623  }
7624 
7625  /* De-escape password. */
7626  for (p1 = p2 = ret; *p1 != ':' && *p1 != '\0'; ++p1, ++p2)
7627  {
7628  if (*p1 == '\\' && p1[1] != '\0')
7629  ++p1;
7630  *p2 = *p1;
7631  }
7632  *p2 = '\0';
7633 
7634  return ret;
7635  }
7636  }
7637 
7638  /* No match, reset buffer to prepare for next line. */
7639  buf.len = 0;
7640  }
7641 
7642  fclose(fp);
7643  explicit_bzero(buf.data, buf.maxlen);
7644  termPQExpBuffer(&buf);
7645  return NULL;
7646 }
static char * pwdfMatchesString(char *buf, const char *token)
Definition: fe-connect.c:7477
static char * hostname
Definition: pg_regress.c:108
const char * username
Definition: pgbench.c:296
int enlargePQExpBuffer(PQExpBuffer str, size_t needed)
Definition: pqexpbuffer.c:172
int pg_strip_crlf(char *str)
Definition: string.c:155
#define S_IRWXG
Definition: win32_port.h:310
#define S_IRWXO
Definition: win32_port.h:322
#define S_ISREG(m)
Definition: win32_port.h:328

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

Referenced by connectOptions2().

◆ pgpassfileWarning()

static void pgpassfileWarning ( PGconn conn)
static

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

7655 {
7656  /* If it was 'invalid authorization', add pgpassfile mention */
7657  /* only works with >= 9.0 servers */
7658  if (conn->password_needed &&
7659  conn->connhost[conn->whichhost].password != NULL &&
7660  conn->result)
7661  {
7662  const char *sqlstate = PQresultErrorField(conn->result,
7664 
7665  if (sqlstate && strcmp(sqlstate, ERRCODE_INVALID_PASSWORD) == 0)
7666  libpq_append_conn_error(conn, "password retrieved from file \"%s\"",
7667  conn->pgpassfile);
7668  }
7669 }
#define ERRCODE_INVALID_PASSWORD
Definition: fe-connect.c:89
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:3380
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:56
PGresult * result
Definition: libpq-int.h:537
bool password_needed
Definition: libpq-int.h:466

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

Referenced by PQconnectPoll().

◆ PQbackendPID()

int PQbackendPID ( const PGconn conn)

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

7283 {
7284  if (!conn || conn->status != CONNECTION_OK)
7285  return 0;
7286  return conn->be_pid;
7287 }
@ CONNECTION_OK
Definition: libpq-fe.h:60
int be_pid
Definition: libpq-int.h:494

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

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

◆ PQcancel()

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

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

4822 {
4823  int save_errno = SOCK_ERRNO;
4824  pgsocket tmpsock = PGINVALID_SOCKET;
4825  int maxlen;
4826  struct
4827  {
4828  uint32 packetlen;
4830  } crp;
4831 
4832  if (!cancel)
4833  {
4834  strlcpy(errbuf, "PQcancel() -- no cancel object supplied", errbufsize);
4835  /* strlcpy probably doesn't change errno, but be paranoid */
4836  SOCK_ERRNO_SET(save_errno);
4837  return false;
4838  }
4839 
4840  /*
4841  * We need to open a temporary connection to the postmaster. Do this with
4842  * only kernel calls.
4843  */
4844  if ((tmpsock = socket(cancel->raddr.addr.ss_family, SOCK_STREAM, 0)) == PGINVALID_SOCKET)
4845  {
4846  strlcpy(errbuf, "PQcancel() -- socket() failed: ", errbufsize);
4847  goto cancel_errReturn;
4848  }
4849 
4850  /*
4851  * Since this connection will only be used to send a single packet of
4852  * data, we don't need NODELAY. We also don't set the socket to
4853  * nonblocking mode, because the API definition of PQcancel requires the
4854  * cancel to be sent in a blocking way.
4855  *
4856  * We do set socket options related to keepalives and other TCP timeouts.
4857  * This ensures that this function does not block indefinitely when
4858  * reasonable keepalive and timeout settings have been provided.
4859  */
4860  if (cancel->raddr.addr.ss_family != AF_UNIX &&
4861  cancel->keepalives != 0)
4862  {
4863 #ifndef WIN32
4864  if (!optional_setsockopt(tmpsock, SOL_SOCKET, SO_KEEPALIVE, 1))
4865  {
4866  strlcpy(errbuf, "PQcancel() -- setsockopt(SO_KEEPALIVE) failed: ", errbufsize);
4867  goto cancel_errReturn;
4868  }
4869 
4870 #ifdef PG_TCP_KEEPALIVE_IDLE
4871  if (!optional_setsockopt(tmpsock, IPPROTO_TCP, PG_TCP_KEEPALIVE_IDLE,
4872  cancel->keepalives_idle))
4873  {
4874  strlcpy(errbuf, "PQcancel() -- setsockopt(" PG_TCP_KEEPALIVE_IDLE_STR ") failed: ", errbufsize);
4875  goto cancel_errReturn;
4876  }
4877 #endif
4878 
4879 #ifdef TCP_KEEPINTVL
4880  if (!optional_setsockopt(tmpsock, IPPROTO_TCP, TCP_KEEPINTVL,
4881  cancel->keepalives_interval))
4882  {
4883  strlcpy(errbuf, "PQcancel() -- setsockopt(TCP_KEEPINTVL) failed: ", errbufsize);
4884  goto cancel_errReturn;
4885  }
4886 #endif
4887 
4888 #ifdef TCP_KEEPCNT
4889  if (!optional_setsockopt(tmpsock, IPPROTO_TCP, TCP_KEEPCNT,
4890  cancel->keepalives_count))
4891  {
4892  strlcpy(errbuf, "PQcancel() -- setsockopt(TCP_KEEPCNT) failed: ", errbufsize);
4893  goto cancel_errReturn;
4894  }
4895 #endif
4896 
4897 #else /* WIN32 */
4898 
4899 #ifdef SIO_KEEPALIVE_VALS
4900  if (!setKeepalivesWin32(tmpsock,
4901  cancel->keepalives_idle,
4902  cancel->keepalives_interval))
4903  {
4904  strlcpy(errbuf, "PQcancel() -- WSAIoctl(SIO_KEEPALIVE_VALS) failed: ", errbufsize);
4905  goto cancel_errReturn;
4906  }
4907 #endif /* SIO_KEEPALIVE_VALS */
4908 #endif /* WIN32 */
4909 
4910  /* TCP_USER_TIMEOUT works the same way on Unix and Windows */
4911 #ifdef TCP_USER_TIMEOUT
4912  if (!optional_setsockopt(tmpsock, IPPROTO_TCP, TCP_USER_TIMEOUT,
4913  cancel->pgtcp_user_timeout))
4914  {
4915  strlcpy(errbuf, "PQcancel() -- setsockopt(TCP_USER_TIMEOUT) failed: ", errbufsize);
4916  goto cancel_errReturn;
4917  }
4918 #endif
4919  }
4920 
4921 retry3:
4922  if (connect(tmpsock, (struct sockaddr *) &cancel->raddr.addr,
4923  cancel->raddr.salen) < 0)
4924  {
4925  if (SOCK_ERRNO == EINTR)
4926  /* Interrupted system call - we'll just try again */
4927  goto retry3;
4928  strlcpy(errbuf, "PQcancel() -- connect() failed: ", errbufsize);
4929  goto cancel_errReturn;
4930  }
4931 
4932  /* Create and send the cancel request packet. */
4933 
4934  crp.packetlen = pg_hton32((uint32) sizeof(crp));
4935  crp.cp.cancelRequestCode = (MsgType) pg_hton32(CANCEL_REQUEST_CODE);
4936  crp.cp.backendPID = pg_hton32(cancel->be_pid);
4937  crp.cp.cancelAuthCode = pg_hton32(cancel->be_key);
4938 
4939 retry4:
4940  if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp))
4941  {
4942  if (SOCK_ERRNO == EINTR)
4943  /* Interrupted system call - we'll just try again */
4944  goto retry4;
4945  strlcpy(errbuf, "PQcancel() -- send() failed: ", errbufsize);
4946  goto cancel_errReturn;
4947  }
4948 
4949  /*
4950  * Wait for the postmaster to close the connection, which indicates that
4951  * it's processed the request. Without this delay, we might issue another
4952  * command only to find that our cancel zaps that command instead of the
4953  * one we thought we were canceling. Note we don't actually expect this
4954  * read to obtain any data, we are just waiting for EOF to be signaled.
4955  */
4956 retry5:
4957  if (recv(tmpsock, (char *) &crp, 1, 0) < 0)
4958  {
4959  if (SOCK_ERRNO == EINTR)
4960  /* Interrupted system call - we'll just try again */
4961  goto retry5;
4962  /* we ignore other error conditions */
4963  }
4964 
4965  /* All done */
4966  closesocket(tmpsock);
4967  SOCK_ERRNO_SET(save_errno);
4968  return true;
4969 
4970 cancel_errReturn:
4971 
4972  /*
4973  * Make sure we don't overflow the error buffer. Leave space for the \n at
4974  * the end, and for the terminating zero.
4975  */
4976  maxlen = errbufsize - strlen(errbuf) - 2;
4977  if (maxlen >= 0)
4978  {
4979  /*
4980  * We can't invoke strerror here, since it's not signal-safe. Settle
4981  * for printing the decimal value of errno. Even that has to be done
4982  * the hard way.
4983  */
4984  int val = SOCK_ERRNO;
4985  char buf[32];
4986  char *bufp;
4987 
4988  bufp = buf + sizeof(buf) - 1;
4989  *bufp = '\0';
4990  do
4991  {
4992  *(--bufp) = (val % 10) + '0';
4993  val /= 10;
4994  } while (val > 0);
4995  bufp -= 6;
4996  memcpy(bufp, "error ", 6);
4997  strncat(errbuf, bufp, maxlen);
4998  strcat(errbuf, "\n");
4999  }
5000  if (tmpsock != PGINVALID_SOCKET)
5001  closesocket(tmpsock);
5002  SOCK_ERRNO_SET(save_errno);
5003  return false;
5004 }
static bool optional_setsockopt(int fd, int protoid, int optid, int value)
Definition: fe-connect.c:4789
#define SOCK_ERRNO_SET(e)
Definition: libpq-int.h:923
#define pg_hton32(x)
Definition: pg_bswap.h:121
int pgsocket
Definition: port.h:29
#define closesocket
Definition: port.h:349
#define CANCEL_REQUEST_CODE
Definition: pqcomm.h:132
ProtocolVersion MsgType
Definition: pqcomm.h:101
int pgtcp_user_timeout
Definition: libpq-int.h:633
int keepalives_interval
Definition: libpq-int.h:636
int keepalives_idle
Definition: libpq-int.h:635
int keepalives_count
Definition: libpq-int.h:638
SockAddr raddr
Definition: libpq-int.h:630
int be_pid
Definition: libpq-int.h:631
int keepalives
Definition: libpq-int.h:634
int be_key
Definition: libpq-int.h:632
#define EINTR
Definition: win32_port.h:374
#define recv(s, buf, len, flags)
Definition: win32_port.h:496
#define send(s, buf, len, flags)
Definition: win32_port.h:497
#define socket(af, type, protocol)
Definition: win32_port.h:490
#define connect(s, name, namelen)
Definition: win32_port.h:494

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

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

◆ PQclientEncoding()

◆ PQconndefaults()

PQconninfoOption* PQconndefaults ( void  )

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

1779 {
1780  PQExpBufferData errorBuf;
1781  PQconninfoOption *connOptions;
1782 
1783  /* We don't actually report any errors here, but callees want a buffer */
1784  initPQExpBuffer(&errorBuf);
1785  if (PQExpBufferDataBroken(errorBuf))
1786  return NULL; /* out of memory already :-( */
1787 
1788  connOptions = conninfo_init(&errorBuf);
1789  if (connOptions != NULL)
1790  {
1791  /* pass NULL errorBuf to ignore errors */
1792  if (!conninfo_add_defaults(connOptions, NULL))
1793  {
1794  PQconninfoFree(connOptions);
1795  connOptions = NULL;
1796  }
1797  }
1798 
1799  termPQExpBuffer(&errorBuf);
1800  return connOptions;
1801 }

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

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

◆ PQconnectdb()

PGconn* PQconnectdb ( const char *  conninfo)

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

732 {
733  PGconn *conn = PQconnectStart(conninfo);
734 
735  if (conn && conn->status != CONNECTION_BAD)
736  (void) connectDBComplete(conn);
737 
738  return conn;
739 }
PGconn * PQconnectStart(const char *conninfo)
Definition: fe-connect.c:859

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

Referenced by get_db_conn(), and main().

◆ PQconnectdbParams()

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

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

679 {
680  PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname);
681 
682  if (conn && conn->status != CONNECTION_BAD)
683  (void) connectDBComplete(conn);
684 
685  return conn;
686 }
PGconn * PQconnectStartParams(const char *const *keywords, const char *const *values, int expand_dbname)
Definition: fe-connect.c:778

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

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

◆ PQconnectionNeedsPassword()

int PQconnectionNeedsPassword ( const PGconn conn)

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

7300 {
7301  char *password;
7302 
7303  if (!conn)
7304  return false;
7305  password = PQpass(conn);
7306  if (conn->password_needed &&
7307  (password == NULL || password[0] == '\0'))
7308  return true;
7309  else
7310  return false;
7311 }
char * PQpass(const PGconn *conn)
Definition: fe-connect.c:7110

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

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

◆ PQconnectionUsedGSSAPI()

int PQconnectionUsedGSSAPI ( const PGconn conn)

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

7326 {
7327  if (!conn)
7328  return false;
7329  if (conn->gssapi_used)
7330  return true;
7331  else
7332  return false;
7333 }
bool gssapi_used
Definition: libpq-int.h:467

References conn, and pg_conn::gssapi_used.

Referenced by dblink_security_check(), and pgfdw_security_check().

◆ PQconnectionUsedPassword()

int PQconnectionUsedPassword ( const PGconn conn)

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

7315 {
7316  if (!conn)
7317  return false;
7318  if (conn->password_needed)
7319  return true;
7320  else
7321  return false;
7322 }

References conn, and pg_conn::password_needed.

Referenced by ConnectDatabase(), dblink_security_check(), libpqrcv_connect(), and pgfdw_security_check().

◆ PQconnectPoll()

PostgresPollingStatusType PQconnectPoll ( PGconn conn)

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

2542 {
2543  bool reset_connection_state_machine = false;
2544  bool need_new_connection = false;
2545  PGresult *res;
2546  char sebuf[PG_STRERROR_R_BUFLEN];
2547  int optval;
2548 
2549  if (conn == NULL)
2550  return PGRES_POLLING_FAILED;
2551 
2552  /* Get the new data */
2553  switch (conn->status)
2554  {
2555  /*
2556  * We really shouldn't have been polled in these two cases, but we
2557  * can handle it.
2558  */
2559  case CONNECTION_BAD:
2560  return PGRES_POLLING_FAILED;
2561  case CONNECTION_OK:
2562  return PGRES_POLLING_OK;
2563 
2564  /* These are reading states */
2566  case CONNECTION_AUTH_OK:
2568  case CONNECTION_CONSUME:
2570  {
2571  /* Load waiting data */
2572  int n = pqReadData(conn);
2573 
2574  if (n < 0)
2575  goto error_return;
2576  if (n == 0)
2577  return PGRES_POLLING_READING;
2578 
2579  break;
2580  }
2581 
2582  /* These are writing states, so we just proceed. */
2583  case CONNECTION_STARTED:
2584  case CONNECTION_MADE:
2585  break;
2586 
2587  /* Special cases: proceed without waiting. */
2589  case CONNECTION_NEEDED:
2592  break;
2593 
2594  default:
2595  libpq_append_conn_error(conn, "invalid connection state, probably indicative of memory corruption");
2596  goto error_return;
2597  }
2598 
2599 
2600 keep_going: /* We will come back to here until there is
2601  * nothing left to do. */
2602 
2603  /* Time to advance to next address, or next host if no more addresses? */
2604  if (conn->try_next_addr)
2605  {
2606  if (conn->whichaddr < conn->naddr)
2607  {
2608  conn->whichaddr++;
2609  reset_connection_state_machine = true;
2610  }
2611  else
2612  conn->try_next_host = true;
2613  conn->try_next_addr = false;
2614  }
2615 
2616  /* Time to advance to next connhost[] entry? */
2617  if (conn->try_next_host)
2618  {
2619  pg_conn_host *ch;
2620  struct addrinfo hint;
2621  struct addrinfo *addrlist;
2622  int thisport;
2623  int ret;
2624  char portstr[MAXPGPATH];
2625 
2626  if (conn->whichhost + 1 < conn->nconnhost)
2627  conn->whichhost++;
2628  else
2629  {
2630  /*
2631  * Oops, no more hosts.
2632  *
2633  * If we are trying to connect in "prefer-standby" mode, then drop
2634  * the standby requirement and start over.
2635  *
2636  * Otherwise, an appropriate error message is already set up, so
2637  * we just need to set the right status.
2638  */
2640  conn->nconnhost > 0)
2641  {
2643  conn->whichhost = 0;
2644  }
2645  else
2646  goto error_return;
2647  }
2648 
2649  /* Drop any address info for previous host */
2651 
2652  /*
2653  * Look up info for the new host. On failure, log the problem in
2654  * conn->errorMessage, then loop around to try the next host. (Note
2655  * we don't clear try_next_host until we've succeeded.)
2656  */
2657  ch = &conn->connhost[conn->whichhost];
2658 
2659  /* Initialize hint structure */
2660  MemSet(&hint, 0, sizeof(hint));
2661  hint.ai_socktype = SOCK_STREAM;
2662  hint.ai_family = AF_UNSPEC;
2663 
2664  /* Figure out the port number we're going to use. */
2665  if (ch->port == NULL || ch->port[0] == '\0')
2666  thisport = DEF_PGPORT;
2667  else
2668  {
2669  if (!parse_int_param(ch->port, &thisport, conn, "port"))
2670  goto error_return;
2671 
2672  if (thisport < 1 || thisport > 65535)
2673  {
2674  libpq_append_conn_error(conn, "invalid port number: \"%s\"", ch->port);
2675  goto keep_going;
2676  }
2677  }
2678  snprintf(portstr, sizeof(portstr), "%d", thisport);
2679 
2680  /* Use pg_getaddrinfo_all() to resolve the address */
2681  switch (ch->type)
2682  {
2683  case CHT_HOST_NAME:
2684  ret = pg_getaddrinfo_all(ch->host, portstr, &hint,
2685  &addrlist);
2686  if (ret || !addrlist)
2687  {
2688  libpq_append_conn_error(conn, "could not translate host name \"%s\" to address: %s",
2689  ch->host, gai_strerror(ret));
2690  goto keep_going;
2691  }
2692  break;
2693 
2694  case CHT_HOST_ADDRESS:
2695  hint.ai_flags = AI_NUMERICHOST;
2696  ret = pg_getaddrinfo_all(ch->hostaddr, portstr, &hint,
2697  &addrlist);
2698  if (ret || !addrlist)
2699  {
2700  libpq_append_conn_error(conn, "could not parse network address \"%s\": %s",
2701  ch->hostaddr, gai_strerror(ret));
2702  goto keep_going;
2703  }
2704  break;
2705 
2706  case CHT_UNIX_SOCKET:
2707  hint.ai_family = AF_UNIX;
2708  UNIXSOCK_PATH(portstr, thisport, ch->host);
2709  if (strlen(portstr) >= UNIXSOCK_PATH_BUFLEN)
2710  {
2711  libpq_append_conn_error(conn, "Unix-domain socket path \"%s\" is too long (maximum %d bytes)",
2712  portstr,
2713  (int) (UNIXSOCK_PATH_BUFLEN - 1));
2714  goto keep_going;
2715  }
2716 
2717  /*
2718  * NULL hostname tells pg_getaddrinfo_all to parse the service
2719  * name as a Unix-domain socket path.
2720  */
2721  ret = pg_getaddrinfo_all(NULL, portstr, &hint,
2722  &addrlist);
2723  if (ret || !addrlist)
2724  {
2725  libpq_append_conn_error(conn, "could not translate Unix-domain socket path \"%s\" to address: %s",
2726  portstr, gai_strerror(ret));
2727  goto keep_going;
2728  }
2729  break;
2730  }
2731 
2732  /*
2733  * Store a copy of the addrlist in private memory so we can perform
2734  * randomization for load balancing.
2735  */
2736  ret = store_conn_addrinfo(conn, addrlist);
2737  pg_freeaddrinfo_all(hint.ai_family, addrlist);
2738  if (ret)
2739  goto error_return; /* message already logged */
2740 
2741  /*
2742  * If random load balancing is enabled we shuffle the addresses.
2743  */
2745  {
2746  /*
2747  * This is the "inside-out" variant of the Fisher-Yates shuffle
2748  * algorithm. Notionally, we append each new value to the array
2749  * and then swap it with a randomly-chosen array element (possibly
2750  * including itself, else we fail to generate permutations with
2751  * the last integer last). The swap step can be optimized by
2752  * combining it with the insertion.
2753  *
2754  * We don't need to initialize conn->prng_state here, because that
2755  * already happened in connectOptions2.
2756  */
2757  for (int i = 1; i < conn->naddr; i++)
2758  {
2759  int j = pg_prng_uint64_range(&conn->prng_state, 0, i);
2760  AddrInfo temp = conn->addr[j];
2761 
2762  conn->addr[j] = conn->addr[i];
2763  conn->addr[i] = temp;
2764  }
2765  }
2766 
2767  reset_connection_state_machine = true;
2768  conn->try_next_host = false;
2769  }
2770 
2771  /* Reset connection state machine? */
2772  if (reset_connection_state_machine)
2773  {
2774  /*
2775  * (Re) initialize our connection control variables for a set of
2776  * connection attempts to a single server address. These variables
2777  * must persist across individual connection attempts, but we must
2778  * reset them when we start to consider a new server.
2779  */
2780  conn->pversion = PG_PROTOCOL(3, 0);
2781  conn->send_appname = true;
2782 #ifdef USE_SSL
2783  /* initialize these values based on SSL mode */
2784  conn->allow_ssl_try = (conn->sslmode[0] != 'd'); /* "disable" */
2785  conn->wait_ssl_try = (conn->sslmode[0] == 'a'); /* "allow" */
2786 #endif
2787 #ifdef ENABLE_GSS
2788  conn->try_gss = (conn->gssencmode[0] != 'd'); /* "disable" */
2789 #endif
2790 
2791  reset_connection_state_machine = false;
2792  need_new_connection = true;
2793  }
2794 
2795  /* Force a new connection (perhaps to the same server as before)? */
2796  if (need_new_connection)
2797  {
2798  /* Drop any existing connection */
2799  pqDropConnection(conn, true);
2800 
2801  /* Reset all state obtained from old server */
2803 
2804  /* Drop any PGresult we might have, too */
2809 
2810  /* Reset conn->status to put the state machine in the right state */
2812 
2813  need_new_connection = false;
2814  }
2815 
2816  /* Now try to advance the state machine for this connection */
2817  switch (conn->status)
2818  {
2819  case CONNECTION_NEEDED:
2820  {
2821  /*
2822  * Try to initiate a connection to one of the addresses
2823  * returned by pg_getaddrinfo_all(). conn->whichaddr is the
2824  * next one to try.
2825  *
2826  * The extra level of braces here is historical. It's not
2827  * worth reindenting this whole switch case to remove 'em.
2828  */
2829  {
2830  char host_addr[NI_MAXHOST];
2831  int sock_type;
2832  AddrInfo *addr_cur;
2833 
2834  /*
2835  * Advance to next possible host, if we've tried all of
2836  * the addresses for the current host.
2837  */
2838  if (conn->whichaddr == conn->naddr)
2839  {
2840  conn->try_next_host = true;
2841  goto keep_going;
2842  }
2843  addr_cur = &conn->addr[conn->whichaddr];
2844 
2845  /* Remember current address for possible use later */
2846  memcpy(&conn->raddr, &addr_cur->addr, sizeof(SockAddr));
2847 
2848  /*
2849  * Set connip, too. Note we purposely ignore strdup
2850  * failure; not a big problem if it fails.
2851  */
2852  if (conn->connip != NULL)
2853  {
2854  free(conn->connip);
2855  conn->connip = NULL;
2856  }
2857  getHostaddr(conn, host_addr, NI_MAXHOST);
2858  if (host_addr[0])
2859  conn->connip = strdup(host_addr);
2860 
2861  /* Try to create the socket */
2862  sock_type = SOCK_STREAM;
2863 #ifdef SOCK_CLOEXEC
2864 
2865  /*
2866  * Atomically mark close-on-exec, if possible on this
2867  * platform, so that there isn't a window where a
2868  * subprogram executed by another thread inherits the
2869  * socket. See fallback code below.
2870  */
2871  sock_type |= SOCK_CLOEXEC;
2872 #endif
2873 #ifdef SOCK_NONBLOCK
2874 
2875  /*
2876  * We might as well skip a system call for nonblocking
2877  * mode too, if we can.
2878  */
2879  sock_type |= SOCK_NONBLOCK;
2880 #endif
2881  conn->sock = socket(addr_cur->family, sock_type, 0);
2882  if (conn->sock == PGINVALID_SOCKET)
2883  {
2884  int errorno = SOCK_ERRNO;
2885 
2886  /*
2887  * Silently ignore socket() failure if we have more
2888  * addresses to try; this reduces useless chatter in
2889  * cases where the address list includes both IPv4 and
2890  * IPv6 but kernel only accepts one family.
2891  */
2892  if (conn->whichaddr < conn->naddr ||
2893  conn->whichhost + 1 < conn->nconnhost)
2894  {
2895  conn->try_next_addr = true;
2896  goto keep_going;
2897  }
2898  emitHostIdentityInfo(conn, host_addr);
2899  libpq_append_conn_error(conn, "could not create socket: %s",
2900  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
2901  goto error_return;
2902  }
2903 
2904  /*
2905  * Once we've identified a target address, all errors
2906  * except the preceding socket()-failure case should be
2907  * prefixed with host-identity information. (If the
2908  * connection succeeds, the contents of conn->errorMessage
2909  * won't matter, so this is harmless.)
2910  */
2911  emitHostIdentityInfo(conn, host_addr);
2912 
2913  /*
2914  * Select socket options: no delay of outgoing data for
2915  * TCP sockets, nonblock mode, close-on-exec. Try the
2916  * next address if any of this fails.
2917  */
2918  if (addr_cur->family != AF_UNIX)
2919  {
2920  if (!connectNoDelay(conn))
2921  {
2922  /* error message already created */
2923  conn->try_next_addr = true;
2924  goto keep_going;
2925  }
2926  }
2927 #ifndef SOCK_NONBLOCK
2928  if (!pg_set_noblock(conn->sock))
2929  {
2930  libpq_append_conn_error(conn, "could not set socket to nonblocking mode: %s",
2931  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2932  conn->try_next_addr = true;
2933  goto keep_going;
2934  }
2935 #endif
2936 
2937 #ifndef SOCK_CLOEXEC
2938 #ifdef F_SETFD
2939  if (fcntl(conn->sock, F_SETFD, FD_CLOEXEC) == -1)
2940  {
2941  libpq_append_conn_error(conn, "could not set socket to close-on-exec mode: %s",
2942  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2943  conn->try_next_addr = true;
2944  goto keep_going;
2945  }
2946 #endif /* F_SETFD */
2947 #endif
2948 
2949  if (addr_cur->family != AF_UNIX)
2950  {
2951 #ifndef WIN32
2952  int on = 1;
2953 #endif
2954  int usekeepalives = useKeepalives(conn);
2955  int err = 0;
2956 
2957  if (usekeepalives < 0)
2958  {
2959  libpq_append_conn_error(conn, "keepalives parameter must be an integer");
2960  err = 1;
2961  }
2962  else if (usekeepalives == 0)
2963  {
2964  /* Do nothing */
2965  }
2966 #ifndef WIN32
2967  else if (setsockopt(conn->sock,
2968  SOL_SOCKET, SO_KEEPALIVE,
2969  (char *) &on, sizeof(on)) < 0)
2970  {
2971  libpq_append_conn_error(conn, "%s(%s) failed: %s",
2972  "setsockopt",
2973  "SO_KEEPALIVE",
2974  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2975  err = 1;
2976  }
2977  else if (!setKeepalivesIdle(conn)
2979  || !setKeepalivesCount(conn))
2980  err = 1;
2981 #else /* WIN32 */
2982 #ifdef SIO_KEEPALIVE_VALS
2983  else if (!prepKeepalivesWin32(conn))
2984  err = 1;
2985 #endif /* SIO_KEEPALIVE_VALS */
2986 #endif /* WIN32 */
2987  else if (!setTCPUserTimeout(conn))
2988  err = 1;
2989 
2990  if (err)
2991  {
2992  conn->try_next_addr = true;
2993  goto keep_going;
2994  }
2995  }
2996 
2997  /*----------
2998  * We have three methods of blocking SIGPIPE during
2999  * send() calls to this socket:
3000  *
3001  * - setsockopt(sock, SO_NOSIGPIPE)
3002  * - send(sock, ..., MSG_NOSIGNAL)
3003  * - setting the signal mask to SIG_IGN during send()
3004  *
3005  * The third method requires three syscalls per send,
3006  * so we prefer either of the first two, but they are
3007  * less portable. The state is tracked in the following
3008  * members of PGconn:
3009  *
3010  * conn->sigpipe_so - we have set up SO_NOSIGPIPE
3011  * conn->sigpipe_flag - we're specifying MSG_NOSIGNAL
3012  *
3013  * If we can use SO_NOSIGPIPE, then set sigpipe_so here
3014  * and we're done. Otherwise, set sigpipe_flag so that
3015  * we will try MSG_NOSIGNAL on sends. If we get an error
3016  * with MSG_NOSIGNAL, we'll clear that flag and revert to
3017  * signal masking.
3018  *----------
3019  */
3020  conn->sigpipe_so = false;
3021 #ifdef MSG_NOSIGNAL
3022  conn->sigpipe_flag = true;
3023 #else
3024  conn->sigpipe_flag = false;
3025 #endif /* MSG_NOSIGNAL */
3026 
3027 #ifdef SO_NOSIGPIPE
3028  optval = 1;
3029  if (setsockopt(conn->sock, SOL_SOCKET, SO_NOSIGPIPE,
3030  (char *) &optval, sizeof(optval)) == 0)
3031  {
3032  conn->sigpipe_so = true;
3033  conn->sigpipe_flag = false;
3034  }
3035 #endif /* SO_NOSIGPIPE */
3036 
3037  /*
3038  * Start/make connection. This should not block, since we
3039  * are in nonblock mode. If it does, well, too bad.
3040  */
3041  if (connect(conn->sock, (struct sockaddr *) &addr_cur->addr.addr,
3042  addr_cur->addr.salen) < 0)
3043  {
3044  if (SOCK_ERRNO == EINPROGRESS ||
3045 #ifdef WIN32
3046  SOCK_ERRNO == EWOULDBLOCK ||
3047 #endif
3048  SOCK_ERRNO == EINTR)
3049  {
3050  /*
3051  * This is fine - we're in non-blocking mode, and
3052  * the connection is in progress. Tell caller to
3053  * wait for write-ready on socket.
3054  */
3056  return PGRES_POLLING_WRITING;
3057  }
3058  /* otherwise, trouble */
3059  }
3060  else
3061  {
3062  /*
3063  * Hm, we're connected already --- seems the "nonblock
3064  * connection" wasn't. Advance the state machine and
3065  * go do the next stuff.
3066  */
3068  goto keep_going;
3069  }
3070 
3071  /*
3072  * This connection failed. Add the error report to
3073  * conn->errorMessage, then try the next address if any.
3074  */
3076  conn->try_next_addr = true;
3077  goto keep_going;
3078  }
3079  }
3080 
3081  case CONNECTION_STARTED:
3082  {
3083  socklen_t optlen = sizeof(optval);
3084 
3085  /*
3086  * Write ready, since we've made it here, so the connection
3087  * has been made ... or has failed.
3088  */
3089 
3090  /*
3091  * Now check (using getsockopt) that there is not an error
3092  * state waiting for us on the socket.
3093  */
3094 
3095  if (getsockopt(conn->sock, SOL_SOCKET, SO_ERROR,
3096  (char *) &optval, &optlen) == -1)
3097  {
3098  libpq_append_conn_error(conn, "could not get socket error status: %s",
3099  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3100  goto error_return;
3101  }
3102  else if (optval != 0)
3103  {
3104  /*
3105  * When using a nonblocking connect, we will typically see
3106  * connect failures at this point, so provide a friendly
3107  * error message.
3108  */
3109  connectFailureMessage(conn, optval);
3110 
3111  /*
3112  * Try the next address if any, just as in the case where
3113  * connect() returned failure immediately.
3114  */
3115  conn->try_next_addr = true;
3116  goto keep_going;
3117  }
3118 
3119  /* Fill in the client address */
3120  conn->laddr.salen = sizeof(conn->laddr.addr);
3121  if (getsockname(conn->sock,
3122  (struct sockaddr *) &conn->laddr.addr,
3123  &conn->laddr.salen) < 0)
3124  {
3125  libpq_append_conn_error(conn, "could not get client address from socket: %s",
3126  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3127  goto error_return;
3128  }
3129 
3130  /*
3131  * Make sure we can write before advancing to next step.
3132  */
3134  return PGRES_POLLING_WRITING;
3135  }
3136 
3137  case CONNECTION_MADE:
3138  {
3139  char *startpacket;
3140  int packetlen;
3141 
3142  /*
3143  * Implement requirepeer check, if requested and it's a
3144  * Unix-domain socket.
3145  */
3146  if (conn->requirepeer && conn->requirepeer[0] &&
3147  conn->raddr.addr.ss_family == AF_UNIX)
3148  {
3149 #ifndef WIN32
3150  char *remote_username;
3151 #endif
3152  uid_t uid;
3153  gid_t gid;
3154 
3155  errno = 0;
3156  if (getpeereid(conn->sock, &uid, &gid) != 0)
3157  {
3158  /*
3159  * Provide special error message if getpeereid is a
3160  * stub
3161  */
3162  if (errno == ENOSYS)
3163  libpq_append_conn_error(conn, "requirepeer parameter is not supported on this platform");
3164  else
3165  libpq_append_conn_error(conn, "could not get peer credentials: %s",
3166  strerror_r(errno, sebuf, sizeof(sebuf)));
3167  goto error_return;
3168  }
3169 
3170 #ifndef WIN32
3171  remote_username = pg_fe_getusername(uid,
3172  &conn->errorMessage);
3173  if (remote_username == NULL)
3174  goto error_return; /* message already logged */
3175 
3176  if (strcmp(remote_username, conn->requirepeer) != 0)
3177  {
3178  libpq_append_conn_error(conn, "requirepeer specifies \"%s\", but actual peer user name is \"%s\"",
3179  conn->requirepeer, remote_username);
3180  free(remote_username);
3181  goto error_return;
3182  }
3183  free(remote_username);
3184 #else /* WIN32 */
3185  /* should have failed with ENOSYS above */
3186  Assert(false);
3187 #endif /* WIN32 */
3188  }
3189 
3190  if (conn->raddr.addr.ss_family == AF_UNIX)
3191  {
3192  /* Don't request SSL or GSSAPI over Unix sockets */
3193 #ifdef USE_SSL
3194  conn->allow_ssl_try = false;
3195 #endif
3196 #ifdef ENABLE_GSS
3197  conn->try_gss = false;
3198 #endif
3199  }
3200 
3201 #ifdef ENABLE_GSS
3202 
3203  /*
3204  * If GSSAPI encryption is enabled, then call
3205  * pg_GSS_have_cred_cache() which will return true if we can
3206  * acquire credentials (and give us a handle to use in
3207  * conn->gcred), and then send a packet to the server asking
3208  * for GSSAPI Encryption (and skip past SSL negotiation and
3209  * regular startup below).
3210  */
3211  if (conn->try_gss && !conn->gctx)
3212  conn->try_gss = pg_GSS_have_cred_cache(&conn->gcred);
3213  if (conn->try_gss && !conn->gctx)
3214  {
3216 
3217  if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
3218  {
3219  libpq_append_conn_error(conn, "could not send GSSAPI negotiation packet: %s",
3220  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3221  goto error_return;
3222  }
3223 
3224  /* Ok, wait for response */
3226  return PGRES_POLLING_READING;
3227  }
3228  else if (!conn->gctx && conn->gssencmode[0] == 'r')
3229  {
3231  "GSSAPI encryption required but was impossible (possibly no credential cache, no server support, or using a local socket)");
3232  goto error_return;
3233  }
3234 #endif
3235 
3236 #ifdef USE_SSL
3237 
3238  /*
3239  * Enable the libcrypto callbacks before checking if SSL needs
3240  * to be done. This is done before sending the startup packet
3241  * as depending on the type of authentication done, like MD5
3242  * or SCRAM that use cryptohashes, the callbacks would be
3243  * required even without a SSL connection
3244  */
3245  if (pqsecure_initialize(conn, false, true) < 0)
3246  goto error_return;
3247 
3248  /*
3249  * If SSL is enabled and we haven't already got encryption of
3250  * some sort running, request SSL instead of sending the
3251  * startup message.
3252  */
3253  if (conn->allow_ssl_try && !conn->wait_ssl_try &&
3254  !conn->ssl_in_use
3255 #ifdef ENABLE_GSS
3256  && !conn->gssenc
3257 #endif
3258  )
3259  {
3260  ProtocolVersion pv;
3261 
3262  /*
3263  * Send the SSL request packet.
3264  *
3265  * Theoretically, this could block, but it really
3266  * shouldn't since we only got here if the socket is
3267  * write-ready.
3268  */
3270  if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
3271  {
3272  libpq_append_conn_error(conn, "could not send SSL negotiation packet: %s",
3273  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3274  goto error_return;
3275  }
3276  /* Ok, wait for response */
3278  return PGRES_POLLING_READING;
3279  }
3280 #endif /* USE_SSL */
3281 
3282  /*
3283  * Build the startup packet.
3284  */
3285  startpacket = pqBuildStartupPacket3(conn, &packetlen,
3287  if (!startpacket)
3288  {
3289  libpq_append_conn_error(conn, "out of memory");
3290  goto error_return;
3291  }
3292 
3293  /*
3294  * Send the startup packet.
3295  *
3296  * Theoretically, this could block, but it really shouldn't
3297  * since we only got here if the socket is write-ready.
3298  */
3299  if (pqPacketSend(conn, 0, startpacket, packetlen) != STATUS_OK)
3300  {
3301  libpq_append_conn_error(conn, "could not send startup packet: %s",
3302  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3303  free(startpacket);
3304  goto error_return;
3305  }
3306 
3307  free(startpacket);
3308 
3310  return PGRES_POLLING_READING;
3311  }
3312 
3313  /*
3314  * Handle SSL negotiation: wait for postmaster messages and
3315  * respond as necessary.
3316  */
3318  {
3319 #ifdef USE_SSL
3320  PostgresPollingStatusType pollres;
3321 
3322  /*
3323  * On first time through, get the postmaster's response to our
3324  * SSL negotiation packet.
3325  */
3326  if (!conn->ssl_in_use)
3327  {
3328  /*
3329  * We use pqReadData here since it has the logic to
3330  * distinguish no-data-yet from connection closure. Since
3331  * conn->ssl isn't set, a plain recv() will occur.
3332  */
3333  char SSLok;
3334  int rdresult;
3335 
3336  rdresult = pqReadData(conn);
3337  if (rdresult < 0)
3338  {
3339  /* errorMessage is already filled in */
3340  goto error_return;
3341  }
3342  if (rdresult == 0)
3343  {
3344  /* caller failed to wait for data */
3345  return PGRES_POLLING_READING;
3346  }
3347  if (pqGetc(&SSLok, conn) < 0)
3348  {
3349  /* should not happen really */
3350  return PGRES_POLLING_READING;
3351  }
3352  if (SSLok == 'S')
3353  {
3354  /* mark byte consumed */
3355  conn->inStart = conn->inCursor;
3356 
3357  /*
3358  * Set up global SSL state if required. The crypto
3359  * state has already been set if libpq took care of
3360  * doing that, so there is no need to make that happen
3361  * again.
3362  */
3363  if (pqsecure_initialize(conn, true, false) != 0)
3364  goto error_return;
3365  }
3366  else if (SSLok == 'N')
3367  {
3368  /* mark byte consumed */
3369  conn->inStart = conn->inCursor;
3370  /* OK to do without SSL? */
3371  if (conn->sslmode[0] == 'r' || /* "require" */
3372  conn->sslmode[0] == 'v') /* "verify-ca" or
3373  * "verify-full" */
3374  {
3375  /* Require SSL, but server does not want it */
3376  libpq_append_conn_error(conn, "server does not support SSL, but SSL was required");
3377  goto error_return;
3378  }
3379  /* Otherwise, proceed with normal startup */
3380  conn->allow_ssl_try = false;
3381  /* We can proceed using this connection */
3383  return PGRES_POLLING_WRITING;
3384  }
3385  else if (SSLok == 'E')
3386  {
3387  /*
3388  * Server failure of some sort, such as failure to
3389  * fork a backend process. We need to process and
3390  * report the error message, which might be formatted
3391  * according to either protocol 2 or protocol 3.
3392  * Rather than duplicate the code for that, we flip
3393  * into AWAITING_RESPONSE state and let the code there
3394  * deal with it. Note we have *not* consumed the "E"
3395  * byte here.
3396  */
3398  goto keep_going;
3399  }
3400  else
3401  {
3402  libpq_append_conn_error(conn, "received invalid response to SSL negotiation: %c",
3403  SSLok);
3404  goto error_return;
3405  }
3406  }
3407 
3408  /*
3409  * Begin or continue the SSL negotiation process.
3410  */
3411  pollres = pqsecure_open_client(conn);
3412  if (pollres == PGRES_POLLING_OK)
3413  {
3414  /*
3415  * At this point we should have no data already buffered.
3416  * If we do, it was received before we performed the SSL
3417  * handshake, so it wasn't encrypted and indeed may have
3418  * been injected by a man-in-the-middle.
3419  */
3420  if (conn->inCursor != conn->inEnd)
3421  {
3422  libpq_append_conn_error(conn, "received unencrypted data after SSL response");
3423  goto error_return;
3424  }
3425 
3426  /* SSL handshake done, ready to send startup packet */
3428  return PGRES_POLLING_WRITING;
3429  }
3430  if (pollres == PGRES_POLLING_FAILED)
3431  {
3432  /*
3433  * Failed ... if sslmode is "prefer" then do a non-SSL
3434  * retry
3435  */
3436  if (conn->sslmode[0] == 'p' /* "prefer" */
3437  && conn->allow_ssl_try /* redundant? */
3438  && !conn->wait_ssl_try) /* redundant? */
3439  {
3440  /* only retry once */
3441  conn->allow_ssl_try = false;
3442  need_new_connection = true;
3443  goto keep_going;
3444  }
3445  /* Else it's a hard failure */
3446  goto error_return;
3447  }
3448  /* Else, return POLLING_READING or POLLING_WRITING status */
3449  return pollres;
3450 #else /* !USE_SSL */
3451  /* can't get here */
3452  goto error_return;
3453 #endif /* USE_SSL */
3454  }
3455