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 PGPing internal_ping (PGconn *conn)
 
static void pqFreeCommandQueue (PGcmdQueueEntry *queue)
 
static bool fillPGconn (PGconn *conn, PQconninfoOption *connOptions)
 
static void freePGconn (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)
 
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)
 
bool pqConnectOptions2 (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)
 
int pqConnectDBStart (PGconn *conn)
 
int pqConnectDBComplete (PGconn *conn)
 
PostgresPollingStatusType PQconnectPoll (PGconn *conn)
 
PGconnpqMakeEmptyPGconn (void)
 
void pqReleaseConnHosts (PGconn *conn)
 
void pqClosePGconn (PGconn *conn)
 
void PQfinish (PGconn *conn)
 
void PQreset (PGconn *conn)
 
int PQresetStart (PGconn *conn)
 
PostgresPollingStatusType PQresetPoll (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)
 
bool pqParseIntParam (const char *value, int *result, PGconn *conn, const char *context)
 
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

◆ connectFailureMessage()

static void connectFailureMessage ( PGconn conn,
int  errorno 
)
static

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

2040 {
2041  char sebuf[PG_STRERROR_R_BUFLEN];
2042 
2044  "%s\n",
2045  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
2046 
2047  if (conn->raddr.addr.ss_family == AF_UNIX)
2048  libpq_append_conn_error(conn, "\tIs the server running locally and accepting connections on that socket?");
2049  else
2050  libpq_append_conn_error(conn, "\tIs the server running on that host and accepting TCP/IP connections?");
2051 }
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition: fe-misc.c:1325
#define SOCK_STRERROR
Definition: libpq-int.h:934
#define PG_STRERROR_R_BUFLEN
Definition: port.h:256
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:265
PGconn * conn
Definition: streamutil.c:54
struct sockaddr_storage addr
Definition: pqcomm.h:32
PQExpBufferData errorMessage
Definition: libpq-int.h:617
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 1924 of file fe-connect.c.

1925 {
1926 #ifdef TCP_NODELAY
1927  int on = 1;
1928 
1929  if (setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY,
1930  (char *) &on,
1931  sizeof(on)) < 0)
1932  {
1933  char sebuf[PG_STRERROR_R_BUFLEN];
1934 
1935  libpq_append_conn_error(conn, "could not set socket to TCP no delay mode: %s",
1936  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
1937  return 0;
1938  }
1939 #endif
1940 
1941  return 1;
1942 }
#define SOCK_ERRNO
Definition: libpq-int.h:933
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 938 of file fe-connect.c.

939 {
940  PQconninfoOption *connOptions;
941 
942  /*
943  * Parse the conninfo string
944  */
945  connOptions = parse_connection_string(conninfo, &conn->errorMessage, true);
946  if (connOptions == NULL)
947  {
949  /* errorMessage is already set */
950  return false;
951  }
952 
953  /*
954  * Move option values into conn structure
955  */
956  if (!fillPGconn(conn, connOptions))
957  {
959  PQconninfoFree(connOptions);
960  return false;
961  }
962 
963  /*
964  * Free the option info - all is in conn now
965  */
966  PQconninfoFree(connOptions);
967 
968  return true;
969 }
static PQconninfoOption * parse_connection_string(const char *connstr, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5483
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6674
static bool fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
Definition: fe-connect.c:898
@ CONNECTION_BAD
Definition: libpq-fe.h:61
ConnStatusType status
Definition: libpq-int.h:425

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

Referenced by PQconnectStart(), and PQsetdbLogin().

◆ conninfo_add_defaults()

static bool conninfo_add_defaults ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

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

5872 {
5874  PQconninfoOption *sslmode_default = NULL,
5875  *sslrootcert = NULL;
5876  char *tmp;
5877 
5878  /*
5879  * If there's a service spec, use it to obtain any not-explicitly-given
5880  * parameters. Ignore error if no error message buffer is passed because
5881  * there is no way to pass back the failure message.
5882  */
5883  if (parseServiceInfo(options, errorMessage) != 0 && errorMessage)
5884  return false;
5885 
5886  /*
5887  * Get the fallback resources for parameters not specified in the conninfo
5888  * string nor the service.
5889  */
5890  for (option = options; option->keyword != NULL; option++)
5891  {
5892  if (strcmp(option->keyword, "sslrootcert") == 0)
5893  sslrootcert = option; /* save for later */
5894 
5895  if (option->val != NULL)
5896  continue; /* Value was in conninfo or service */
5897 
5898  /*
5899  * Try to get the environment variable fallback
5900  */
5901  if (option->envvar != NULL)
5902  {
5903  if ((tmp = getenv(option->envvar)) != NULL)
5904  {
5905  option->val = strdup(tmp);
5906  if (!option->val)
5907  {
5908  if (errorMessage)
5909  libpq_append_error(errorMessage, "out of memory");
5910  return false;
5911  }
5912  continue;
5913  }
5914  }
5915 
5916  /*
5917  * Interpret the deprecated PGREQUIRESSL environment variable. Per
5918  * tradition, translate values starting with "1" to sslmode=require,
5919  * and ignore other values. Given both PGREQUIRESSL=1 and PGSSLMODE,
5920  * PGSSLMODE takes precedence; the opposite was true before v9.3.
5921  */
5922  if (strcmp(option->keyword, "sslmode") == 0)
5923  {
5924  const char *requiresslenv = getenv("PGREQUIRESSL");
5925 
5926  if (requiresslenv != NULL && requiresslenv[0] == '1')
5927  {
5928  option->val = strdup("require");
5929  if (!option->val)
5930  {
5931  if (errorMessage)
5932  libpq_append_error(errorMessage, "out of memory");
5933  return false;
5934  }
5935  continue;
5936  }
5937 
5938  /*
5939  * sslmode is not specified. Let it be filled in with the compiled
5940  * default for now, but if sslrootcert=system, we'll override the
5941  * default later before returning.
5942  */
5943  sslmode_default = option;
5944  }
5945 
5946  /*
5947  * No environment variable specified or the variable isn't set - try
5948  * compiled-in default
5949  */
5950  if (option->compiled != NULL)
5951  {
5952  option->val = strdup(option->compiled);
5953  if (!option->val)
5954  {
5955  if (errorMessage)
5956  libpq_append_error(errorMessage, "out of memory");
5957  return false;
5958  }
5959  continue;
5960  }
5961 
5962  /*
5963  * Special handling for "user" option. Note that if pg_fe_getauthname
5964  * fails, we just leave the value as NULL; there's no need for this to
5965  * be an error condition if the caller provides a user name. The only
5966  * reason we do this now at all is so that callers of PQconndefaults
5967  * will see a correct default (barring error, of course).
5968  */
5969  if (strcmp(option->keyword, "user") == 0)
5970  {
5971  option->val = pg_fe_getauthname(NULL);
5972  continue;
5973  }
5974  }
5975 
5976  /*
5977  * Special handling for sslrootcert=system with no sslmode explicitly
5978  * defined. In this case we want to strengthen the default sslmode to
5979  * verify-full.
5980  */
5981  if (sslmode_default && sslrootcert)
5982  {
5983  if (sslrootcert->val && strcmp(sslrootcert->val, "system") == 0)
5984  {
5985  free(sslmode_default->val);
5986 
5987  sslmode_default->val = strdup("verify-full");
5988  if (!sslmode_default->val)
5989  {
5990  if (errorMessage)
5991  libpq_append_error(errorMessage, "out of memory");
5992  return false;
5993  }
5994  }
5995  }
5996 
5997  return true;
5998 }
char * pg_fe_getauthname(PQExpBuffer errorMessage)
Definition: fe-auth.c:1215
static int parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5176
void libpq_append_error(PQExpBuffer errorMessage, const char *fmt,...)
Definition: fe-misc.c:1296
#define free(a)
Definition: header.h:65
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 5713 of file fe-connect.c.

5716 {
5718  PQconninfoOption *dbname_options = NULL;
5720  int i = 0;
5721 
5722  /*
5723  * If expand_dbname is non-zero, check keyword "dbname" to see if val is
5724  * actually a recognized connection string.
5725  */
5726  while (expand_dbname && keywords[i])
5727  {
5728  const char *pname = keywords[i];
5729  const char *pvalue = values[i];
5730 
5731  /* first find "dbname" if any */
5732  if (strcmp(pname, "dbname") == 0 && pvalue)
5733  {
5734  /*
5735  * If value is a connection string, parse it, but do not use
5736  * defaults here -- those get picked up later. We only want to
5737  * override for those parameters actually passed.
5738  */
5739  if (recognized_connection_string(pvalue))
5740  {
5741  dbname_options = parse_connection_string(pvalue, errorMessage, false);
5742  if (dbname_options == NULL)
5743  return NULL;
5744  }
5745  break;
5746  }
5747  ++i;
5748  }
5749 
5750  /* Make a working copy of PQconninfoOptions */
5751  options = conninfo_init(errorMessage);
5752  if (options == NULL)
5753  {
5754  PQconninfoFree(dbname_options);
5755  return NULL;
5756  }
5757 
5758  /* Parse the keywords/values arrays */
5759  i = 0;
5760  while (keywords[i])
5761  {
5762  const char *pname = keywords[i];
5763  const char *pvalue = values[i];
5764 
5765  if (pvalue != NULL && pvalue[0] != '\0')
5766  {
5767  /* Search for the param record */
5768  for (option = options; option->keyword != NULL; option++)
5769  {
5770  if (strcmp(option->keyword, pname) == 0)
5771  break;
5772  }
5773 
5774  /* Check for invalid connection option */
5775  if (option->keyword == NULL)
5776  {
5777  libpq_append_error(errorMessage, "invalid connection option \"%s\"", pname);
5779  PQconninfoFree(dbname_options);
5780  return NULL;
5781  }
5782 
5783  /*
5784  * If we are on the first dbname parameter, and we have a parsed
5785  * connection string, copy those parameters across, overriding any
5786  * existing previous settings.
5787  */
5788  if (strcmp(pname, "dbname") == 0 && dbname_options)
5789  {
5790  PQconninfoOption *str_option;
5791 
5792  for (str_option = dbname_options; str_option->keyword != NULL; str_option++)
5793  {
5794  if (str_option->val != NULL)
5795  {
5796  int k;
5797 
5798  for (k = 0; options[k].keyword; k++)
5799  {
5800  if (strcmp(options[k].keyword, str_option->keyword) == 0)
5801  {
5802  free(options[k].val);
5803  options[k].val = strdup(str_option->val);
5804  if (!options[k].val)
5805  {
5806  libpq_append_error(errorMessage, "out of memory");
5808  PQconninfoFree(dbname_options);
5809  return NULL;
5810  }
5811  break;
5812  }
5813  }
5814  }
5815  }
5816 
5817  /*
5818  * Forget the parsed connection string, so that any subsequent
5819  * dbname parameters will not be expanded.
5820  */
5821  PQconninfoFree(dbname_options);
5822  dbname_options = NULL;
5823  }
5824  else
5825  {
5826  /*
5827  * Store the value, overriding previous settings
5828  */
5829  free(option->val);
5830  option->val = strdup(pvalue);
5831  if (!option->val)
5832  {
5833  libpq_append_error(errorMessage, "out of memory");
5835  PQconninfoFree(dbname_options);
5836  return NULL;
5837  }
5838  }
5839  }
5840  ++i;
5841  }
5842  PQconninfoFree(dbname_options);
5843 
5844  /*
5845  * Add in defaults if the caller wants that.
5846  */
5847  if (use_defaults)
5848  {
5849  if (!conninfo_add_defaults(options, errorMessage))
5850  {
5852  return NULL;
5853  }
5854  }
5855 
5856  return options;
5857 }
static Datum values[MAXATTR]
Definition: bootstrap.c:156
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5444
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5871
static bool recognized_connection_string(const char *connstr)
Definition: fe-connect.c:5526
long val
Definition: informix.c:664
int i
Definition: isn.c:73
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 6612 of file fe-connect.c.

6613 {
6615 
6616  for (option = connOptions; option->keyword != NULL; option++)
6617  {
6618  if (strcmp(option->keyword, keyword) == 0)
6619  return option;
6620  }
6621 
6622  return NULL;
6623 }

Referenced by conninfo_getval(), and conninfo_storeval().

◆ conninfo_getval()

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

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

6524 {
6526 
6527  option = conninfo_find(connOptions, keyword);
6528 
6529  return option ? option->val : NULL;
6530 }
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6612

References conninfo_find(), and option::val.

Referenced by fillPGconn(), and parseServiceInfo().

◆ conninfo_init()

static PQconninfoOption * conninfo_init ( PQExpBuffer  errorMessage)
static

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

5445 {
5447  PQconninfoOption *opt_dest;
5448  const internalPQconninfoOption *cur_opt;
5449 
5450  /*
5451  * Get enough memory for all options in PQconninfoOptions, even if some
5452  * end up being filtered out.
5453  */
5455  if (options == NULL)
5456  {
5457  libpq_append_error(errorMessage, "out of memory");
5458  return NULL;
5459  }
5460  opt_dest = options;
5461 
5462  for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++)
5463  {
5464  /* Only copy the public part of the struct, not the full internal */
5465  memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption));
5466  opt_dest++;
5467  }
5468  MemSet(opt_dest, 0, sizeof(PQconninfoOption));
5469 
5470  return options;
5471 }
#define MemSet(start, val, len)
Definition: c.h:1009
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:189
#define malloc(a)
Definition: header.h:50

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

5539 {
5540  char *pname;
5541  char *pval;
5542  char *buf;
5543  char *cp;
5544  char *cp2;
5546 
5547  /* Make a working copy of PQconninfoOptions */
5548  options = conninfo_init(errorMessage);
5549  if (options == NULL)
5550  return NULL;
5551 
5552  /* Need a modifiable copy of the input string */
5553  if ((buf = strdup(conninfo)) == NULL)
5554  {
5555  libpq_append_error(errorMessage, "out of memory");
5557  return NULL;
5558  }
5559  cp = buf;
5560 
5561  while (*cp)
5562  {
5563  /* Skip blanks before the parameter name */
5564  if (isspace((unsigned char) *cp))
5565  {
5566  cp++;
5567  continue;
5568  }
5569 
5570  /* Get the parameter name */
5571  pname = cp;
5572  while (*cp)
5573  {
5574  if (*cp == '=')
5575  break;
5576  if (isspace((unsigned char) *cp))
5577  {
5578  *cp++ = '\0';
5579  while (*cp)
5580  {
5581  if (!isspace((unsigned char) *cp))
5582  break;
5583  cp++;
5584  }
5585  break;
5586  }
5587  cp++;
5588  }
5589 
5590  /* Check that there is a following '=' */
5591  if (*cp != '=')
5592  {
5593  libpq_append_error(errorMessage,
5594  "missing \"=\" after \"%s\" in connection info string",
5595  pname);
5597  free(buf);
5598  return NULL;
5599  }
5600  *cp++ = '\0';
5601 
5602  /* Skip blanks after the '=' */
5603  while (*cp)
5604  {
5605  if (!isspace((unsigned char) *cp))
5606  break;
5607  cp++;
5608  }
5609 
5610  /* Get the parameter value */
5611  pval = cp;
5612 
5613  if (*cp != '\'')
5614  {
5615  cp2 = pval;
5616  while (*cp)
5617  {
5618  if (isspace((unsigned char) *cp))
5619  {
5620  *cp++ = '\0';
5621  break;
5622  }
5623  if (*cp == '\\')
5624  {
5625  cp++;
5626  if (*cp != '\0')
5627  *cp2++ = *cp++;
5628  }
5629  else
5630  *cp2++ = *cp++;
5631  }
5632  *cp2 = '\0';
5633  }
5634  else
5635  {
5636  cp2 = pval;
5637  cp++;
5638  for (;;)
5639  {
5640  if (*cp == '\0')
5641  {
5642  libpq_append_error(errorMessage, "unterminated quoted string in connection info string");
5644  free(buf);
5645  return NULL;
5646  }
5647  if (*cp == '\\')
5648  {
5649  cp++;
5650  if (*cp != '\0')
5651  *cp2++ = *cp++;
5652  continue;
5653  }
5654  if (*cp == '\'')
5655  {
5656  *cp2 = '\0';
5657  cp++;
5658  break;
5659  }
5660  *cp2++ = *cp++;
5661  }
5662  }
5663 
5664  /*
5665  * Now that we have the name and the value, store the record.
5666  */
5667  if (!conninfo_storeval(options, pname, pval, errorMessage, false, false))
5668  {
5670  free(buf);
5671  return NULL;
5672  }
5673  }
5674 
5675  /* Done with the modifiable input string */
5676  free(buf);
5677 
5678  /*
5679  * Add in defaults if the caller wants that.
5680  */
5681  if (use_defaults)
5682  {
5683  if (!conninfo_add_defaults(options, errorMessage))
5684  {
5686  return NULL;
5687  }
5688  }
5689 
5690  return options;
5691 }
static PQconninfoOption * conninfo_storeval(PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode)
Definition: fe-connect.c:6548
static char * buf
Definition: pg_test_fsync.c:73

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

6552 {
6554  char *value_copy;
6555 
6556  /*
6557  * For backwards compatibility, requiressl=1 gets translated to
6558  * sslmode=require, and requiressl=0 gets translated to sslmode=prefer
6559  * (which is the default for sslmode).
6560  */
6561  if (strcmp(keyword, "requiressl") == 0)
6562  {
6563  keyword = "sslmode";
6564  if (value[0] == '1')
6565  value = "require";
6566  else
6567  value = "prefer";
6568  }
6569 
6570  option = conninfo_find(connOptions, keyword);
6571  if (option == NULL)
6572  {
6573  if (!ignoreMissing)
6574  libpq_append_error(errorMessage,
6575  "invalid connection option \"%s\"",
6576  keyword);
6577  return NULL;
6578  }
6579 
6580  if (uri_decode)
6581  {
6582  value_copy = conninfo_uri_decode(value, errorMessage);
6583  if (value_copy == NULL)
6584  /* conninfo_uri_decode already set an error message */
6585  return NULL;
6586  }
6587  else
6588  {
6589  value_copy = strdup(value);
6590  if (value_copy == NULL)
6591  {
6592  libpq_append_error(errorMessage, "out of memory");
6593  return NULL;
6594  }
6595  }
6596 
6597  free(option->val);
6598  option->val = value_copy;
6599 
6600  return option;
6601 }
static char * conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
Definition: fe-connect.c:6433
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 6433 of file fe-connect.c.

6434 {
6435  char *buf;
6436  char *p;
6437  const char *q = str;
6438 
6439  buf = malloc(strlen(str) + 1);
6440  if (buf == NULL)
6441  {
6442  libpq_append_error(errorMessage, "out of memory");
6443  return NULL;
6444  }
6445  p = buf;
6446 
6447  for (;;)
6448  {
6449  if (*q != '%')
6450  {
6451  /* copy and check for NUL terminator */
6452  if (!(*(p++) = *(q++)))
6453  break;
6454  }
6455  else
6456  {
6457  int hi;
6458  int lo;
6459  int c;
6460 
6461  ++q; /* skip the percent sign itself */
6462 
6463  /*
6464  * Possible EOL will be caught by the first call to
6465  * get_hexdigit(), so we never dereference an invalid q pointer.
6466  */
6467  if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo)))
6468  {
6469  libpq_append_error(errorMessage,
6470  "invalid percent-encoded token: \"%s\"",
6471  str);
6472  free(buf);
6473  return NULL;
6474  }
6475 
6476  c = (hi << 4) | lo;
6477  if (c == 0)
6478  {
6479  libpq_append_error(errorMessage,
6480  "forbidden value %%00 in percent-encoded value: \"%s\"",
6481  str);
6482  free(buf);
6483  return NULL;
6484  }
6485  *(p++) = c;
6486  }
6487  }
6488 
6489  return buf;
6490 }
static bool get_hexdigit(char digit, int *value)
Definition: fe-connect.c:6501
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 6006 of file fe-connect.c.

6008 {
6010 
6011  /* Make a working copy of PQconninfoOptions */
6012  options = conninfo_init(errorMessage);
6013  if (options == NULL)
6014  return NULL;
6015 
6016  if (!conninfo_uri_parse_options(options, uri, errorMessage))
6017  {
6019  return NULL;
6020  }
6021 
6022  /*
6023  * Add in defaults if the caller wants that.
6024  */
6025  if (use_defaults)
6026  {
6027  if (!conninfo_add_defaults(options, errorMessage))
6028  {
6030  return NULL;
6031  }
6032  }
6033 
6034  return options;
6035 }
static bool conninfo_uri_parse_options(PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage)
Definition: fe-connect.c:6059

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

6061 {
6062  int prefix_len;
6063  char *p;
6064  char *buf = NULL;
6065  char *start;
6066  char prevchar = '\0';
6067  char *user = NULL;
6068  char *host = NULL;
6069  bool retval = false;
6070  PQExpBufferData hostbuf;
6071  PQExpBufferData portbuf;
6072 
6073  initPQExpBuffer(&hostbuf);
6074  initPQExpBuffer(&portbuf);
6075  if (PQExpBufferDataBroken(hostbuf) || PQExpBufferDataBroken(portbuf))
6076  {
6077  libpq_append_error(errorMessage, "out of memory");
6078  goto cleanup;
6079  }
6080 
6081  /* need a modifiable copy of the input URI */
6082  buf = strdup(uri);
6083  if (buf == NULL)
6084  {
6085  libpq_append_error(errorMessage, "out of memory");
6086  goto cleanup;
6087  }
6088  start = buf;
6089 
6090  /* Skip the URI prefix */
6091  prefix_len = uri_prefix_length(uri);
6092  if (prefix_len == 0)
6093  {
6094  /* Should never happen */
6095  libpq_append_error(errorMessage,
6096  "invalid URI propagated to internal parser routine: \"%s\"",
6097  uri);
6098  goto cleanup;
6099  }
6100  start += prefix_len;
6101  p = start;
6102 
6103  /* Look ahead for possible user credentials designator */
6104  while (*p && *p != '@' && *p != '/')
6105  ++p;
6106  if (*p == '@')
6107  {
6108  /*
6109  * Found username/password designator, so URI should be of the form
6110  * "scheme://user[:password]@[netloc]".
6111  */
6112  user = start;
6113 
6114  p = user;
6115  while (*p != ':' && *p != '@')
6116  ++p;
6117 
6118  /* Save last char and cut off at end of user name */
6119  prevchar = *p;
6120  *p = '\0';
6121 
6122  if (*user &&
6123  !conninfo_storeval(options, "user", user,
6124  errorMessage, false, true))
6125  goto cleanup;
6126 
6127  if (prevchar == ':')
6128  {
6129  const char *password = p + 1;
6130 
6131  while (*p != '@')
6132  ++p;
6133  *p = '\0';
6134 
6135  if (*password &&
6136  !conninfo_storeval(options, "password", password,
6137  errorMessage, false, true))
6138  goto cleanup;
6139  }
6140 
6141  /* Advance past end of parsed user name or password token */
6142  ++p;
6143  }
6144  else
6145  {
6146  /*
6147  * No username/password designator found. Reset to start of URI.
6148  */
6149  p = start;
6150  }
6151 
6152  /*
6153  * There may be multiple netloc[:port] pairs, each separated from the next
6154  * by a comma. When we initially enter this loop, "p" has been
6155  * incremented past optional URI credential information at this point and
6156  * now points at the "netloc" part of the URI. On subsequent loop
6157  * iterations, "p" has been incremented past the comma separator and now
6158  * points at the start of the next "netloc".
6159  */
6160  for (;;)
6161  {
6162  /*
6163  * Look for IPv6 address.
6164  */
6165  if (*p == '[')
6166  {
6167  host = ++p;
6168  while (*p && *p != ']')
6169  ++p;
6170  if (!*p)
6171  {
6172  libpq_append_error(errorMessage,
6173  "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"",
6174  uri);
6175  goto cleanup;
6176  }
6177  if (p == host)
6178  {
6179  libpq_append_error(errorMessage,
6180  "IPv6 host address may not be empty in URI: \"%s\"",
6181  uri);
6182  goto cleanup;
6183  }
6184 
6185  /* Cut off the bracket and advance */
6186  *(p++) = '\0';
6187 
6188  /*
6189  * The address may be followed by a port specifier or a slash or a
6190  * query or a separator comma.
6191  */
6192  if (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',')
6193  {
6194  libpq_append_error(errorMessage,
6195  "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"",
6196  *p, (int) (p - buf + 1), uri);
6197  goto cleanup;
6198  }
6199  }
6200  else
6201  {
6202  /* not an IPv6 address: DNS-named or IPv4 netloc */
6203  host = p;
6204 
6205  /*
6206  * Look for port specifier (colon) or end of host specifier
6207  * (slash) or query (question mark) or host separator (comma).
6208  */
6209  while (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',')
6210  ++p;
6211  }
6212 
6213  /* Save the hostname terminator before we null it */
6214  prevchar = *p;
6215  *p = '\0';
6216 
6217  appendPQExpBufferStr(&hostbuf, host);
6218 
6219  if (prevchar == ':')
6220  {
6221  const char *port = ++p; /* advance past host terminator */
6222 
6223  while (*p && *p != '/' && *p != '?' && *p != ',')
6224  ++p;
6225 
6226  prevchar = *p;
6227  *p = '\0';
6228 
6229  appendPQExpBufferStr(&portbuf, port);
6230  }
6231 
6232  if (prevchar != ',')
6233  break;
6234  ++p; /* advance past comma separator */
6235  appendPQExpBufferChar(&hostbuf, ',');
6236  appendPQExpBufferChar(&portbuf, ',');
6237  }
6238 
6239  /* Save final values for host and port. */
6240  if (PQExpBufferDataBroken(hostbuf) || PQExpBufferDataBroken(portbuf))
6241  goto cleanup;
6242  if (hostbuf.data[0] &&
6243  !conninfo_storeval(options, "host", hostbuf.data,
6244  errorMessage, false, true))
6245  goto cleanup;
6246  if (portbuf.data[0] &&
6247  !conninfo_storeval(options, "port", portbuf.data,
6248  errorMessage, false, true))
6249  goto cleanup;
6250 
6251  if (prevchar && prevchar != '?')
6252  {
6253  const char *dbname = ++p; /* advance past host terminator */
6254 
6255  /* Look for query parameters */
6256  while (*p && *p != '?')
6257  ++p;
6258 
6259  prevchar = *p;
6260  *p = '\0';
6261 
6262  /*
6263  * Avoid setting dbname to an empty string, as it forces the default
6264  * value (username) and ignores $PGDATABASE, as opposed to not setting
6265  * it at all.
6266  */
6267  if (*dbname &&
6268  !conninfo_storeval(options, "dbname", dbname,
6269  errorMessage, false, true))
6270  goto cleanup;
6271  }
6272 
6273  if (prevchar)
6274  {
6275  ++p; /* advance past terminator */
6276 
6277  if (!conninfo_uri_parse_params(p, options, errorMessage))
6278  goto cleanup;
6279  }
6280 
6281  /* everything parsed okay */
6282  retval = true;
6283 
6284 cleanup:
6285  termPQExpBuffer(&hostbuf);
6286  termPQExpBuffer(&portbuf);
6287  free(buf);
6288  return retval;
6289 }
static void cleanup(void)
Definition: bootstrap.c:686
static int uri_prefix_length(const char *connstr)
Definition: fe-connect.c:5503
static bool conninfo_uri_parse_params(char *params, PQconninfoOption *connOptions, PQExpBuffer errorMessage)
Definition: fe-connect.c:6300
static char * user
Definition: pg_regress.c:120
static int port
Definition: pg_regress.c:116
void initPQExpBuffer(PQExpBuffer str)
Definition: pqexpbuffer.c:90
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:378
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:367
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 6300 of file fe-connect.c.

6303 {
6304  while (*params)
6305  {
6306  char *keyword = params;
6307  char *value = NULL;
6308  char *p = params;
6309  bool malloced = false;
6310  int oldmsglen;
6311 
6312  /*
6313  * Scan the params string for '=' and '&', marking the end of keyword
6314  * and value respectively.
6315  */
6316  for (;;)
6317  {
6318  if (*p == '=')
6319  {
6320  /* Was there '=' already? */
6321  if (value != NULL)
6322  {
6323  libpq_append_error(errorMessage,
6324  "extra key/value separator \"=\" in URI query parameter: \"%s\"",
6325  keyword);
6326  return false;
6327  }
6328  /* Cut off keyword, advance to value */
6329  *p++ = '\0';
6330  value = p;
6331  }
6332  else if (*p == '&' || *p == '\0')
6333  {
6334  /*
6335  * If not at the end, cut off value and advance; leave p
6336  * pointing to start of the next parameter, if any.
6337  */
6338  if (*p != '\0')
6339  *p++ = '\0';
6340  /* Was there '=' at all? */
6341  if (value == NULL)
6342  {
6343  libpq_append_error(errorMessage,
6344  "missing key/value separator \"=\" in URI query parameter: \"%s\"",
6345  keyword);
6346  return false;
6347  }
6348  /* Got keyword and value, go process them. */
6349  break;
6350  }
6351  else
6352  ++p; /* Advance over all other bytes. */
6353  }
6354 
6355  keyword = conninfo_uri_decode(keyword, errorMessage);
6356  if (keyword == NULL)
6357  {
6358  /* conninfo_uri_decode already set an error message */
6359  return false;
6360  }
6361  value = conninfo_uri_decode(value, errorMessage);
6362  if (value == NULL)
6363  {
6364  /* conninfo_uri_decode already set an error message */
6365  free(keyword);
6366  return false;
6367  }
6368  malloced = true;
6369 
6370  /*
6371  * Special keyword handling for improved JDBC compatibility.
6372  */
6373  if (strcmp(keyword, "ssl") == 0 &&
6374  strcmp(value, "true") == 0)
6375  {
6376  free(keyword);
6377  free(value);
6378  malloced = false;
6379 
6380  keyword = "sslmode";
6381  value = "require";
6382  }
6383 
6384  /*
6385  * Store the value if the corresponding option exists; ignore
6386  * otherwise. At this point both keyword and value are not
6387  * URI-encoded.
6388  */
6389  oldmsglen = errorMessage->len;
6390  if (!conninfo_storeval(connOptions, keyword, value,
6391  errorMessage, true, false))
6392  {
6393  /* Insert generic message if conninfo_storeval didn't give one. */
6394  if (errorMessage->len == oldmsglen)
6395  libpq_append_error(errorMessage,
6396  "invalid URI query parameter: \"%s\"",
6397  keyword);
6398  /* And fail. */
6399  if (malloced)
6400  {
6401  free(keyword);
6402  free(value);
6403  }
6404  return false;
6405  }
6406 
6407  if (malloced)
6408  {
6409  free(keyword);
6410  free(value);
6411  }
6412 
6413  /* Proceed to next key=value pair, if any */
6414  params = p;
6415  }
6416 
6417  return true;
6418 }

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

976 {
977  int n;
978 
979  n = 1;
980  for (; *input != '\0'; input++)
981  {
982  if (*input == ',')
983  n++;
984  }
985 
986  return n;
987 }
FILE * input

References input.

Referenced by pqConnectOptions2().

◆ default_threadlock()

static void default_threadlock ( int  acquire)
static

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

7428 {
7429  static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
7430 
7431  if (acquire)
7432  {
7433  if (pthread_mutex_lock(&singlethread_lock))
7434  Assert(false);
7435  }
7436  else
7437  {
7438  if (pthread_mutex_unlock(&singlethread_lock))
7439  Assert(false);
7440  }
7441 }
Assert(fmt[strlen(fmt) - 1] !='\n')
int pthread_mutex_unlock(pthread_mutex_t *mp)
Definition: pthread-win32.c:60
int pthread_mutex_lock(pthread_mutex_t *mp)
Definition: pthread-win32.c:42
#define PTHREAD_MUTEX_INITIALIZER
Definition: pthread-win32.h:16

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

Referenced by PQregisterThreadLock().

◆ defaultNoticeProcessor()

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

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

7059 {
7060  (void) arg; /* not used */
7061  /* Note: we expect the supplied string to end with a newline already. */
7062  fprintf(stderr, "%s", message);
7063 }
void * arg
#define fprintf
Definition: port.h:242

References arg, and fprintf.

Referenced by pqMakeEmptyPGconn().

◆ defaultNoticeReceiver()

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

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

7044 {
7045  (void) arg; /* not used */
7046  if (res->noticeHooks.noticeProc != NULL)
7049 }
char * PQresultErrorMessage(const PGresult *res)
Definition: fe-exec.c:3387
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 pqMakeEmptyPGconn().

◆ emitHostIdentityInfo()

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

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

1984 {
1985  if (conn->raddr.addr.ss_family == AF_UNIX)
1986  {
1987  char service[NI_MAXHOST];
1988 
1990  NULL, 0,
1991  service, sizeof(service),
1992  NI_NUMERICSERV);
1994  libpq_gettext("connection to server on socket \"%s\" failed: "),
1995  service);
1996  }
1997  else
1998  {
1999  const char *displayed_host;
2000  const char *displayed_port;
2001 
2002  /* To which host and port were we actually connecting? */
2004  displayed_host = conn->connhost[conn->whichhost].hostaddr;
2005  else
2006  displayed_host = conn->connhost[conn->whichhost].host;
2007  displayed_port = conn->connhost[conn->whichhost].port;
2008  if (displayed_port == NULL || displayed_port[0] == '\0')
2009  displayed_port = DEF_PGPORT_STR;
2010 
2011  /*
2012  * If the user did not supply an IP address using 'hostaddr', and
2013  * 'host' was missing or does not match our lookup, display the
2014  * looked-up IP address.
2015  */
2017  host_addr[0] &&
2018  strcmp(displayed_host, host_addr) != 0)
2020  libpq_gettext("connection to server at \"%s\" (%s), port %s failed: "),
2021  displayed_host, host_addr,
2022  displayed_port);
2023  else
2025  libpq_gettext("connection to server at \"%s\", port %s failed: "),
2026  displayed_host,
2027  displayed_port);
2028  }
2029 }
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:912
@ CHT_HOST_ADDRESS
Definition: libpq-int.h:310
socklen_t salen
Definition: pqcomm.h:33
char * host
Definition: libpq-int.h:346
char * port
Definition: libpq-int.h:348
char * hostaddr
Definition: libpq-int.h:347
pg_conn_host_type type
Definition: libpq-int.h:345
int whichhost
Definition: libpq-int.h:441
pg_conn_host * connhost
Definition: libpq-int.h:442

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

899 {
901 
902  for (option = PQconninfoOptions; option->keyword; option++)
903  {
904  if (option->connofs >= 0)
905  {
906  const char *tmp = conninfo_getval(connOptions, option->keyword);
907 
908  if (tmp)
909  {
910  char **connmember = (char **) ((char *) conn + option->connofs);
911 
912  free(*connmember);
913  *connmember = strdup(tmp);
914  if (*connmember == NULL)
915  {
916  libpq_append_conn_error(conn, "out of memory");
917  return false;
918  }
919  }
920  }
921  }
922 
923  return true;
924 }
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6522

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

4335 {
4336  /* let any event procs clean up their state data */
4337  for (int i = 0; i < conn->nEvents; i++)
4338  {
4339  PGEventConnDestroy evt;
4340 
4341  evt.conn = conn;
4342  (void) conn->events[i].proc(PGEVT_CONNDESTROY, &evt,
4343  conn->events[i].passThrough);
4344  free(conn->events[i].name);
4345  }
4346 
4348 
4350  free(conn->events);
4351  free(conn->pghost);
4352  free(conn->pghostaddr);
4353  free(conn->pgport);
4356  free(conn->pgoptions);
4357  free(conn->appname);
4358  free(conn->fbappname);
4359  free(conn->dbName);
4360  free(conn->replication);
4361  free(conn->pguser);
4362  if (conn->pgpass)
4363  {
4364  explicit_bzero(conn->pgpass, strlen(conn->pgpass));
4365  free(conn->pgpass);
4366  }
4367  free(conn->pgpassfile);
4369  free(conn->keepalives);
4373  free(conn->sslmode);
4374  free(conn->sslcert);
4375  free(conn->sslkey);
4376  if (conn->sslpassword)
4377  {
4379  free(conn->sslpassword);
4380  }
4381  free(conn->sslcertmode);
4382  free(conn->sslrootcert);
4383  free(conn->sslcrl);
4384  free(conn->sslcrldir);
4386  free(conn->sslsni);
4387  free(conn->requirepeer);
4391  free(conn->gssencmode);
4392  free(conn->krbsrvname);
4393  free(conn->gsslib);
4395  free(conn->connip);
4396  /* Note that conn->Pfdebug is not ours to close or free */
4398  free(conn->inBuffer);
4399  free(conn->outBuffer);
4400  free(conn->rowBuf);
4405 
4406  free(conn);
4407 }
void pqReleaseConnHosts(PGconn *conn)
Definition: fe-connect.c:4414
@ 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
char * sslrootcert
Definition: libpq-int.h:396
PGdataValue * rowBuf
Definition: libpq-int.h:525
char * sslcompression
Definition: libpq-int.h:391
char * require_auth
Definition: libpq-int.h:409
char * inBuffer
Definition: libpq-int.h:508
char * channel_binding
Definition: libpq-int.h:382
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 * 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 * fbappname
Definition: libpq-int.h:376
char * sslcert
Definition: libpq-int.h:393
char * sslcertmode
Definition: libpq-int.h:395
char * target_session_attrs
Definition: libpq-int.h:408
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 * load_balance_hosts
Definition: libpq-int.h:410
char * pguser
Definition: libpq-int.h:379
char * keepalives
Definition: libpq-int.h:384
char * client_encoding_initial
Definition: libpq-int.h:373
char * keepalives_interval
Definition: libpq-int.h:386
char * appname
Definition: libpq-int.h:375
char * sslmode
Definition: libpq-int.h:390
char * pgtcp_user_timeout
Definition: libpq-int.h:372
char * ssl_min_protocol_version
Definition: libpq-int.h:406
char * gssencmode
Definition: libpq-int.h:401
int nEvents
Definition: libpq-int.h:421
char * pghostaddr
Definition: libpq-int.h:365
char * sslkey
Definition: libpq-int.h:392
char * pgpassfile
Definition: libpq-int.h:381
char * connect_timeout
Definition: libpq-int.h:371
char * krbsrvname
Definition: libpq-int.h:402
char * gsslib
Definition: libpq-int.h:403
char * pgport
Definition: libpq-int.h:369
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::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, 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::nEvents, pg_conn::outBuffer, PGEvent::passThrough, 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, pqReleaseConnHosts(), 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 PQfinish(), and pqMakeEmptyPGconn().

◆ get_hexdigit()

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

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

6502 {
6503  if ('0' <= digit && digit <= '9')
6504  *value = digit - '0';
6505  else if ('A' <= digit && digit <= 'F')
6506  *value = digit - 'A' + 10;
6507  else if ('a' <= digit && digit <= 'f')
6508  *value = digit - 'a' + 10;
6509  else
6510  return false;
6511 
6512  return true;
6513 }

References value.

Referenced by conninfo_uri_decode().

◆ getHostaddr()

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

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

1951 {
1952  struct sockaddr_storage *addr = &conn->raddr.addr;
1953 
1954  if (addr->ss_family == AF_INET)
1955  {
1956  if (pg_inet_net_ntop(AF_INET,
1957  &((struct sockaddr_in *) addr)->sin_addr.s_addr,
1958  32,
1959  host_addr, host_addr_len) == NULL)
1960  host_addr[0] = '\0';
1961  }
1962  else if (addr->ss_family == AF_INET6)
1963  {
1964  if (pg_inet_net_ntop(AF_INET6,
1965  &((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr,
1966  128,
1967  host_addr, host_addr_len) == NULL)
1968  host_addr[0] = '\0';
1969  }
1970  else
1971  host_addr[0] = '\0';
1972 }
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 4171 of file fe-connect.c.

4172 {
4173  /* Say "no attempt" if we never got to PQconnectPoll */
4174  if (!conn || !conn->options_valid)
4175  return PQPING_NO_ATTEMPT;
4176 
4177  /* Attempt to complete the connection */
4178  if (conn->status != CONNECTION_BAD)
4179  (void) pqConnectDBComplete(conn);
4180 
4181  /* Definitely OK if we succeeded */
4182  if (conn->status != CONNECTION_BAD)
4183  return PQPING_OK;
4184 
4185  /*
4186  * Here begins the interesting part of "ping": determine the cause of the
4187  * failure in sufficient detail to decide what to return. We do not want
4188  * to report that the server is not up just because we didn't have a valid
4189  * password, for example. In fact, any sort of authentication request
4190  * implies the server is up. (We need this check since the libpq side of
4191  * things might have pulled the plug on the connection before getting an
4192  * error as such from the postmaster.)
4193  */
4194  if (conn->auth_req_received)
4195  return PQPING_OK;
4196 
4197  /*
4198  * If we failed to get any ERROR response from the postmaster, report
4199  * PQPING_NO_RESPONSE. This result could be somewhat misleading for a
4200  * pre-7.4 server, since it won't send back a SQLSTATE, but those are long
4201  * out of support. Another corner case where the server could return a
4202  * failure without a SQLSTATE is fork failure, but PQPING_NO_RESPONSE
4203  * isn't totally unreasonable for that anyway. We expect that every other
4204  * failure case in a modern server will produce a report with a SQLSTATE.
4205  *
4206  * NOTE: whenever we get around to making libpq generate SQLSTATEs for
4207  * client-side errors, we should either not store those into
4208  * last_sqlstate, or add an extra flag so we can tell client-side errors
4209  * apart from server-side ones.
4210  */
4211  if (strlen(conn->last_sqlstate) != 5)
4212  return PQPING_NO_RESPONSE;
4213 
4214  /*
4215  * Report PQPING_REJECT if server says it's not accepting connections.
4216  */
4217  if (strcmp(conn->last_sqlstate, ERRCODE_CANNOT_CONNECT_NOW) == 0)
4218  return PQPING_REJECT;
4219 
4220  /*
4221  * Any other SQLSTATE can be taken to indicate that the server is up.
4222  * Presumably it didn't like our username, password, or database name; or
4223  * perhaps it had some transient failure, but that should not be taken as
4224  * meaning "it's down".
4225  */
4226  return PQPING_OK;
4227 }
#define ERRCODE_CANNOT_CONNECT_NOW
Definition: fe-connect.c:91
int pqConnectDBComplete(PGconn *conn)
Definition: fe-connect.c:2352
@ 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
bool options_valid
Definition: libpq-int.h:429

References pg_conn::auth_req_received, conn, CONNECTION_BAD, ERRCODE_CANNOT_CONNECT_NOW, pg_conn::last_sqlstate, pg_conn::options_valid, pqConnectDBComplete(), 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 1034 of file fe-connect.c.

1035 {
1036  uint64 rseed;
1037  struct timeval tval = {0};
1038 
1040  return;
1041 
1042  gettimeofday(&tval, NULL);
1043 
1044  rseed = ((uintptr_t) conn) ^
1045  ((uint64) getpid()) ^
1046  ((uint64) tval.tv_usec) ^
1047  ((uint64) tval.tv_sec);
1048 
1049  pg_prng_seed(&conn->prng_state, rseed);
1050 }
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
pg_prng_state prng_state
Definition: libpq-int.h:504
int gettimeofday(struct timeval *tp, void *tzp)

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

Referenced by pqConnectOptions2().

◆ parse_comma_separated_list()

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

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

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

References len, and malloc.

Referenced by pqConnectOptions2().

◆ parse_connection_string()

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

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

5485 {
5486  /* Parse as URI if connection string matches URI prefix */
5487  if (uri_prefix_length(connstr) != 0)
5488  return conninfo_uri_parse(connstr, errorMessage, use_defaults);
5489 
5490  /* Parse as default otherwise */
5491  return conninfo_parse(connstr, errorMessage, use_defaults);
5492 }
static PQconninfoOption * conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:6006
static PQconninfoOption * conninfo_parse(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5537
static char * connstr
Definition: pg_dumpall.c:90

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

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

◆ parseServiceFile()

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

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

5249 {
5250  int result = 0,
5251  linenr = 0,
5252  i;
5253  FILE *f;
5254  char *line;
5255  char buf[1024];
5256 
5257  *group_found = false;
5258 
5259  f = fopen(serviceFile, "r");
5260  if (f == NULL)
5261  {
5262  libpq_append_error(errorMessage, "service file \"%s\" not found", serviceFile);
5263  return 1;
5264  }
5265 
5266  while ((line = fgets(buf, sizeof(buf), f)) != NULL)
5267  {
5268  int len;
5269 
5270  linenr++;
5271 
5272  if (strlen(line) >= sizeof(buf) - 1)
5273  {
5274  libpq_append_error(errorMessage,
5275  "line %d too long in service file \"%s\"",
5276  linenr,
5277  serviceFile);
5278  result = 2;
5279  goto exit;
5280  }
5281 
5282  /* ignore whitespace at end of line, especially the newline */
5283  len = strlen(line);
5284  while (len > 0 && isspace((unsigned char) line[len - 1]))
5285  line[--len] = '\0';
5286 
5287  /* ignore leading whitespace too */
5288  while (*line && isspace((unsigned char) line[0]))
5289  line++;
5290 
5291  /* ignore comments and empty lines */
5292  if (line[0] == '\0' || line[0] == '#')
5293  continue;
5294 
5295  /* Check for right groupname */
5296  if (line[0] == '[')
5297  {
5298  if (*group_found)
5299  {
5300  /* end of desired group reached; return success */
5301  goto exit;
5302  }
5303 
5304  if (strncmp(line + 1, service, strlen(service)) == 0 &&
5305  line[strlen(service) + 1] == ']')
5306  *group_found = true;
5307  else
5308  *group_found = false;
5309  }
5310  else
5311  {
5312  if (*group_found)
5313  {
5314  /*
5315  * Finally, we are in the right group and can parse the line
5316  */
5317  char *key,
5318  *val;
5319  bool found_keyword;
5320 
5321 #ifdef USE_LDAP
5322  if (strncmp(line, "ldap", 4) == 0)
5323  {
5324  int rc = ldapServiceLookup(line, options, errorMessage);
5325 
5326  /* if rc = 2, go on reading for fallback */
5327  switch (rc)
5328  {
5329  case 0:
5330  goto exit;
5331  case 1:
5332  case 3:
5333  result = 3;
5334  goto exit;
5335  case 2:
5336  continue;
5337  }
5338  }
5339 #endif
5340 
5341  key = line;
5342  val = strchr(line, '=');
5343  if (val == NULL)
5344  {
5345  libpq_append_error(errorMessage,
5346  "syntax error in service file \"%s\", line %d",
5347  serviceFile,
5348  linenr);
5349  result = 3;
5350  goto exit;
5351  }
5352  *val++ = '\0';
5353 
5354  if (strcmp(key, "service") == 0)
5355  {
5356  libpq_append_error(errorMessage,
5357  "nested service specifications not supported in service file \"%s\", line %d",
5358  serviceFile,
5359  linenr);
5360  result = 3;
5361  goto exit;
5362  }
5363 
5364  /*
5365  * Set the parameter --- but don't override any previous
5366  * explicit setting.
5367  */
5368  found_keyword = false;
5369  for (i = 0; options[i].keyword; i++)
5370  {
5371  if (strcmp(options[i].keyword, key) == 0)
5372  {
5373  if (options[i].val == NULL)
5374  options[i].val = strdup(val);
5375  if (!options[i].val)
5376  {
5377  libpq_append_error(errorMessage, "out of memory");
5378  result = 3;
5379  goto exit;
5380  }
5381  found_keyword = true;
5382  break;
5383  }
5384  }
5385 
5386  if (!found_keyword)
5387  {
5388  libpq_append_error(errorMessage,
5389  "syntax error in service file \"%s\", line %d",
5390  serviceFile,
5391  linenr);
5392  result = 3;
5393  goto exit;
5394  }
5395  }
5396  }
5397  }
5398 
5399 exit:
5400  fclose(f);
5401 
5402  return result;
5403 }
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 5176 of file fe-connect.c.

5177 {
5178  const char *service = conninfo_getval(options, "service");
5179  char serviceFile[MAXPGPATH];
5180  char *env;
5181  bool group_found = false;
5182  int status;
5183  struct stat stat_buf;
5184 
5185  /*
5186  * We have to special-case the environment variable PGSERVICE here, since
5187  * this is and should be called before inserting environment defaults for
5188  * other connection options.
5189  */
5190  if (service == NULL)
5191  service = getenv("PGSERVICE");
5192 
5193  /* If no service name given, nothing to do */
5194  if (service == NULL)
5195  return 0;
5196 
5197  /*
5198  * Try PGSERVICEFILE if specified, else try ~/.pg_service.conf (if that
5199  * exists).
5200  */
5201  if ((env = getenv("PGSERVICEFILE")) != NULL)
5202  strlcpy(serviceFile, env, sizeof(serviceFile));
5203  else
5204  {
5205  char homedir[MAXPGPATH];
5206 
5207  if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
5208  goto next_file;
5209  snprintf(serviceFile, MAXPGPATH, "%s/%s", homedir, ".pg_service.conf");
5210  if (stat(serviceFile, &stat_buf) != 0)
5211  goto next_file;
5212  }
5213 
5214  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
5215  if (group_found || status != 0)
5216  return status;
5217 
5218 next_file:
5219 
5220  /*
5221  * This could be used by any application so we can't use the binary
5222  * location to find our config files.
5223  */
5224  snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf",
5225  getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);
5226  if (stat(serviceFile, &stat_buf) != 0)
5227  goto last_file;
5228 
5229  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
5230  if (status != 0)
5231  return status;
5232 
5233 last_file:
5234  if (!group_found)
5235  {
5236  libpq_append_error(errorMessage, "definition of service \"%s\" not found", service);
5237  return 3;
5238  }
5239 
5240  return 0;
5241 }
static int parseServiceFile(const char *serviceFile, const char *service, PQconninfoOption *options, PQExpBuffer errorMessage, bool *group_found)
Definition: fe-connect.c:5244
bool pqGetHomeDirectory(char *buf, int bufsize)
Definition: fe-connect.c:7349
#define MAXPGPATH
#define snprintf
Definition: port.h:238
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 7107 of file fe-connect.c.

7109 {
7110  FILE *fp;
7111  struct stat stat_buf;
7113 
7114  if (dbname == NULL || dbname[0] == '\0')
7115  return NULL;
7116 
7117  if (username == NULL || username[0] == '\0')
7118  return NULL;
7119 
7120  /* 'localhost' matches pghost of '' or the default socket directory */
7121  if (hostname == NULL || hostname[0] == '\0')
7123  else if (is_unixsock_path(hostname))
7124 
7125  /*
7126  * We should probably use canonicalize_path(), but then we have to
7127  * bring path.c into libpq, and it doesn't seem worth it.
7128  */
7129  if (strcmp(hostname, DEFAULT_PGSOCKET_DIR) == 0)
7131 
7132  if (port == NULL || port[0] == '\0')
7133  port = DEF_PGPORT_STR;
7134 
7135  /* If password file cannot be opened, ignore it. */
7136  if (stat(pgpassfile, &stat_buf) != 0)
7137  return NULL;
7138 
7139 #ifndef WIN32
7140  if (!S_ISREG(stat_buf.st_mode))
7141  {
7142  fprintf(stderr,
7143  libpq_gettext("WARNING: password file \"%s\" is not a plain file\n"),
7144  pgpassfile);
7145  return NULL;
7146  }
7147 
7148  /* If password file is insecure, alert the user and ignore it. */
7149  if (stat_buf.st_mode & (S_IRWXG | S_IRWXO))
7150  {
7151  fprintf(stderr,
7152  libpq_gettext("WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
7153  pgpassfile);
7154  return NULL;
7155  }
7156 #else
7157 
7158  /*
7159  * On Win32, the directory is protected, so we don't have to check the
7160  * file.
7161  */
7162 #endif
7163 
7164  fp = fopen(pgpassfile, "r");
7165  if (fp == NULL)
7166  return NULL;
7167 
7168  /* Use an expansible buffer to accommodate any reasonable line length */
7169  initPQExpBuffer(&buf);
7170 
7171  while (!feof(fp) && !ferror(fp))
7172  {
7173  /* Make sure there's a reasonable amount of room in the buffer */
7174  if (!enlargePQExpBuffer(&buf, 128))
7175  break;
7176 
7177  /* Read some data, appending it to what we already have */
7178  if (fgets(buf.data + buf.len, buf.maxlen - buf.len, fp) == NULL)
7179  break;
7180  buf.len += strlen(buf.data + buf.len);
7181 
7182  /* If we don't yet have a whole line, loop around to read more */
7183  if (!(buf.len > 0 && buf.data[buf.len - 1] == '\n') && !feof(fp))
7184  continue;
7185 
7186  /* ignore comments */
7187  if (buf.data[0] != '#')
7188  {
7189  char *t = buf.data;
7190  int len;
7191 
7192  /* strip trailing newline and carriage return */
7193  len = pg_strip_crlf(t);
7194 
7195  if (len > 0 &&
7196  (t = pwdfMatchesString(t, hostname)) != NULL &&
7197  (t = pwdfMatchesString(t, port)) != NULL &&
7198  (t = pwdfMatchesString(t, dbname)) != NULL &&
7199  (t = pwdfMatchesString(t, username)) != NULL)
7200  {
7201  /* Found a match. */
7202  char *ret,
7203  *p1,
7204  *p2;
7205 
7206  ret = strdup(t);
7207 
7208  fclose(fp);
7209  explicit_bzero(buf.data, buf.maxlen);
7210  termPQExpBuffer(&buf);
7211 
7212  if (!ret)
7213  {
7214  /* Out of memory. XXX: an error message would be nice. */
7215  return NULL;
7216  }
7217 
7218  /* De-escape password. */
7219  for (p1 = p2 = ret; *p1 != ':' && *p1 != '\0'; ++p1, ++p2)
7220  {
7221  if (*p1 == '\\' && p1[1] != '\0')
7222  ++p1;
7223  *p2 = *p1;
7224  }
7225  *p2 = '\0';
7226 
7227  return ret;
7228  }
7229  }
7230 
7231  /* No match, reset buffer to prepare for next line. */
7232  buf.len = 0;
7233  }
7234 
7235  fclose(fp);
7236  explicit_bzero(buf.data, buf.maxlen);
7237  termPQExpBuffer(&buf);
7238  return NULL;
7239 }
#define DefaultHost
Definition: fe-connect.c:116
static char * pwdfMatchesString(char *buf, const char *token)
Definition: fe-connect.c:7070
#define DEFAULT_PGSOCKET_DIR
static char * hostname
Definition: pg_regress.c:115
const char * username
Definition: pgbench.c:296
static bool is_unixsock_path(const char *path)
Definition: pqcomm.h:67
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 pqConnectOptions2().

◆ pgpassfileWarning()

static void pgpassfileWarning ( PGconn conn)
static

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

7248 {
7249  /* If it was 'invalid authorization', add pgpassfile mention */
7250  /* only works with >= 9.0 servers */
7251  if (conn->password_needed &&
7252  conn->connhost[conn->whichhost].password != NULL &&
7253  conn->result)
7254  {
7255  const char *sqlstate = PQresultErrorField(conn->result,
7257 
7258  if (sqlstate && strcmp(sqlstate, ERRCODE_INVALID_PASSWORD) == 0)
7259  libpq_append_conn_error(conn, "password retrieved from file \"%s\"",
7260  conn->pgpassfile);
7261  }
7262 }
#define ERRCODE_INVALID_PASSWORD
Definition: fe-connect.c:89
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:3426
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:56
char * password
Definition: libpq-int.h:349
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 6875 of file fe-connect.c.

6876 {
6877  if (!conn || conn->status != CONNECTION_OK)
6878  return 0;
6879  return conn->be_pid;
6880 }
@ 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().

◆ PQclientEncoding()

int PQclientEncoding ( const PGconn conn)

◆ pqClosePGconn()

void pqClosePGconn ( PGconn conn)

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

4524 {
4525  /*
4526  * If possible, send Terminate message to close the connection politely.
4527  */
4529 
4530  /*
4531  * Must reset the blocking status so a possible reconnect will work.
4532  *
4533  * Don't call PQsetnonblocking() because it will fail if it's unable to
4534  * flush the connection.
4535  */
4536  conn->nonblocking = false;
4537 
4538  /*
4539  * Close the connection, reset all transient state, flush I/O buffers.
4540  * Note that this includes clearing conn's error state; we're no longer
4541  * interested in any failures associated with the old connection, and we
4542  * want a clean slate for any new connection attempt.
4543  */
4544  pqDropConnection(conn, true);
4545  conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
4549  pqClearAsyncResult(conn); /* deallocate result */
4552 
4553  /* Reset all state obtained from server, too */
4555 }
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:460
static void sendTerminateConn(PGconn *conn)
Definition: fe-connect.c:4496
static void release_conn_addrinfo(PGconn *conn)
Definition: fe-connect.c:4482
static void pqDropServerData(PGconn *conn)
Definition: fe-connect.c:573
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:777
@ 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:885
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

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

◆ PQconndefaults()

PQconninfoOption* PQconndefaults ( void  )

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

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

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

725 {
726  PGconn *conn = PQconnectStart(conninfo);
727 
728  if (conn && conn->status != CONNECTION_BAD)
729  (void) pqConnectDBComplete(conn);
730 
731  return conn;
732 }
PGconn * PQconnectStart(const char *conninfo)
Definition: fe-connect.c:852

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

Referenced by get_db_conn(), and main().

◆ pqConnectDBComplete()

int pqConnectDBComplete ( PGconn conn)

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

2353 {
2355  time_t finish_time = ((time_t) -1);
2356  int timeout = 0;
2357  int last_whichhost = -2; /* certainly different from whichhost */
2358  int last_whichaddr = -2; /* certainly different from whichaddr */
2359 
2360  if (conn == NULL || conn->status == CONNECTION_BAD)
2361  return 0;
2362 
2363  /*
2364  * Set up a time limit, if connect_timeout isn't zero.
2365  */
2366  if (conn->connect_timeout != NULL)
2367  {
2368  if (!pqParseIntParam(conn->connect_timeout, &timeout, conn,
2369  "connect_timeout"))
2370  {
2371  /* mark the connection as bad to report the parsing failure */
2373  return 0;
2374  }
2375 
2376  if (timeout > 0)
2377  {
2378  /*
2379  * Rounding could cause connection to fail unexpectedly quickly;
2380  * to prevent possibly waiting hardly-at-all, insist on at least
2381  * two seconds.
2382  */
2383  if (timeout < 2)
2384  timeout = 2;
2385  }
2386  else /* negative means 0 */
2387  timeout = 0;
2388  }
2389 
2390  for (;;)
2391  {
2392  int ret = 0;
2393 
2394  /*
2395  * (Re)start the connect_timeout timer if it's active and we are
2396  * considering a different host than we were last time through. If
2397  * we've already succeeded, though, needn't recalculate.
2398  */
2399  if (flag != PGRES_POLLING_OK &&
2400  timeout > 0 &&
2401  (conn->whichhost != last_whichhost ||
2402  conn->whichaddr != last_whichaddr))
2403  {
2404  finish_time = time(NULL) + timeout;
2405  last_whichhost = conn->whichhost;
2406  last_whichaddr = conn->whichaddr;
2407  }
2408 
2409  /*
2410  * Wait, if necessary. Note that the initial state (just after
2411  * PQconnectStart) is to wait for the socket to select for writing.
2412  */
2413  switch (flag)
2414  {
2415  case PGRES_POLLING_OK:
2416  return 1; /* success! */
2417 
2418  case PGRES_POLLING_READING:
2419  ret = pqWaitTimed(1, 0, conn, finish_time);
2420  if (ret == -1)
2421  {
2422  /* hard failure, eg select() problem, aborts everything */
2424  return 0;
2425  }
2426  break;
2427 
2428  case PGRES_POLLING_WRITING:
2429  ret = pqWaitTimed(0, 1, conn, finish_time);
2430  if (ret == -1)
2431  {
2432  /* hard failure, eg select() problem, aborts everything */
2434  return 0;
2435  }
2436  break;
2437 
2438  default:
2439  /* Just in case we failed to set it in PQconnectPoll */
2441  return 0;
2442  }
2443 
2444  if (ret == 1) /* connect_timeout elapsed */
2445  {
2446  /*
2447  * Give up on current server/address, try the next one.
2448  */
2449  conn->try_next_addr = true;
2451  }
2452 
2453  /*
2454  * Now try to advance the state machine.
2455  */
2456  flag = PQconnectPoll(conn);
2457  }
2458 }
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
Definition: fe-connect.c:2488
bool pqParseIntParam(const char *value, int *result, PGconn *conn, const char *context)
Definition: fe-connect.c:7376
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
bool try_next_addr
Definition: libpq-int.h:485
char * flag(int b)
Definition: test-ctype.c:33

References conn, pg_conn::connect_timeout, CONNECTION_BAD, CONNECTION_NEEDED, flag(), PGRES_POLLING_OK, PGRES_POLLING_READING, PGRES_POLLING_WRITING, PQconnectPoll(), pqParseIntParam(), 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().

◆ PQconnectdbParams()

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

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

672 {
673  PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname);
674 
675  if (conn && conn->status != CONNECTION_BAD)
676  (void) pqConnectDBComplete(conn);
677 
678  return conn;
679 }
PGconn * PQconnectStartParams(const char *const *keywords, const char *const *values, int expand_dbname)
Definition: fe-connect.c:771

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

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

◆ pqConnectDBStart()

int pqConnectDBStart ( PGconn conn)

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

2283 {
2284  if (!conn)
2285  return 0;
2286 
2287  if (!conn->options_valid)
2288  goto connect_errReturn;
2289 
2290  /*
2291  * Check for bad linking to backend-internal versions of src/common
2292  * functions (see comments in link-canary.c for the reason we need this).
2293  * Nobody but developers should see this message, so we don't bother
2294  * translating it.
2295  */
2297  {
2299  "libpq is incorrectly linked to backend functions\n");
2300  goto connect_errReturn;
2301  }
2302 
2303  /* Ensure our buffers are empty */
2304  conn->inStart = conn->inCursor = conn->inEnd = 0;
2305  conn->outCount = 0;
2306 
2307  /*
2308  * Set up to try to connect to the first host. (Setting whichhost = -1 is
2309  * a bit of a cheat, but PQconnectPoll will advance it to 0 before
2310  * anything else looks at it.)
2311  */
2312  conn->whichhost = -1;
2313  conn->try_next_addr = false;
2314  conn->try_next_host = true;
2316 
2317  /* Also reset the target_server_type state if needed */
2320 
2321  /*
2322  * The code for processing CONNECTION_NEEDED state is in PQconnectPoll(),
2323  * so that it can easily be re-executed if needed again during the
2324  * asynchronous startup process. However, we must run it once here,
2325  * because callers expect a success return from this routine to mean that
2326  * we are in PGRES_POLLING_WRITING connection state.
2327  */
2329  return 1;
2330 
2331 connect_errReturn:
2332 
2333  /*
2334  * If we managed to open a socket, close it immediately rather than
2335  * waiting till PQfinish. (The application cannot have gotten the socket
2336  * from PQsocket yet, so this doesn't risk breaking anything.)
2337  */
2338  pqDropConnection(conn, true);
2340  return 0;
2341 }
@ SERVER_TYPE_PREFER_STANDBY_PASS2
Definition: libpq-int.h:243
@ SERVER_TYPE_PREFER_STANDBY
Definition: libpq-int.h:242
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
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().

◆ PQconnectionNeedsPassword()

int PQconnectionNeedsPassword ( const PGconn conn)

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

6893 {
6894  char *password;
6895 
6896  if (!conn)
6897  return false;
6898  password = PQpass(conn);
6899  if (conn->password_needed &&
6900  (password == NULL || password[0] == '\0'))
6901  return true;
6902  else
6903  return false;
6904 }
char * PQpass(const PGconn *conn)
Definition: fe-connect.c:6703

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

6919 {
6920  if (!conn)
6921  return false;
6922  if (conn->gssapi_used)
6923  return true;
6924  else
6925  return false;
6926 }
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 6907 of file fe-connect.c.

6908 {
6909  if (!conn)
6910  return false;
6911  if (conn->password_needed)
6912  return true;
6913  else
6914  return false;
6915 }

References conn, and pg_conn::password_needed.

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

◆ pqConnectOptions2()

bool pqConnectOptions2 ( PGconn conn)

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

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

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

◆ PQconnectPoll()

PostgresPollingStatusType PQconnectPoll ( PGconn conn)

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

2489 {
2490  bool reset_connection_state_machine = false;
2491  bool need_new_connection = false;
2492  PGresult *res;
2493  char sebuf[PG_STRERROR_R_BUFLEN];
2494  int optval;
2495 
2496  if (conn == NULL)
2497  return PGRES_POLLING_FAILED;
2498 
2499  /* Get the new data */
2500  switch (conn->status)
2501  {
2502  /*
2503  * We really shouldn't have been polled in these two cases, but we
2504  * can handle it.
2505  */
2506  case CONNECTION_BAD:
2507  return PGRES_POLLING_FAILED;
2508  case CONNECTION_OK:
2509  return PGRES_POLLING_OK;
2510 
2511  /* These are reading states */
2513  case CONNECTION_AUTH_OK:
2515  case CONNECTION_CONSUME:
2517  {
2518  /* Load waiting data */
2519  int n = pqReadData(conn);
2520 
2521  if (n < 0)
2522  goto error_return;
2523  if (n == 0)
2524  return PGRES_POLLING_READING;
2525 
2526  break;
2527  }
2528 
2529  /* These are writing states, so we just proceed. */
2530  case CONNECTION_STARTED:
2531  case CONNECTION_MADE:
2532  break;
2533 
2534  /* Special cases: proceed without waiting. */
2536  case CONNECTION_NEEDED:
2539  break;
2540 
2541  default:
2542  libpq_append_conn_error(conn, "invalid connection state, probably indicative of memory corruption");
2543  goto error_return;
2544  }
2545 
2546 
2547 keep_going: /* We will come back to here until there is
2548  * nothing left to do. */
2549 
2550  /* Time to advance to next address, or next host if no more addresses? */
2551  if (conn->try_next_addr)
2552  {
2553  if (conn->whichaddr < conn->naddr)
2554  {
2555  conn->whichaddr++;
2556  reset_connection_state_machine = true;
2557  }
2558  else
2559  conn->try_next_host = true;
2560  conn->try_next_addr = false;
2561  }
2562 
2563  /* Time to advance to next connhost[] entry? */
2564  if (conn->try_next_host)
2565  {
2566  pg_conn_host *ch;
2567  struct addrinfo hint;
2568  struct addrinfo *addrlist;
2569  int thisport;
2570  int ret;
2571  char portstr[MAXPGPATH];
2572 
2573  if (conn->whichhost + 1 < conn->nconnhost)
2574  conn->whichhost++;
2575  else
2576  {
2577  /*
2578  * Oops, no more hosts.
2579  *
2580  * If we are trying to connect in "prefer-standby" mode, then drop
2581  * the standby requirement and start over.
2582  *
2583  * Otherwise, an appropriate error message is already set up, so
2584  * we just need to set the right status.
2585  */
2587  conn->nconnhost > 0)
2588  {
2590  conn->whichhost = 0;
2591  }
2592  else
2593  goto error_return;
2594  }
2595 
2596  /* Drop any address info for previous host */
2598 
2599  /*
2600  * Look up info for the new host. On failure, log the problem in
2601  * conn->errorMessage, then loop around to try the next host. (Note
2602  * we don't clear try_next_host until we've succeeded.)
2603  */
2604  ch = &conn->connhost[conn->whichhost];
2605 
2606  /* Initialize hint structure */
2607  MemSet(&hint, 0, sizeof(hint));
2608  hint.ai_socktype = SOCK_STREAM;
2609  hint.ai_family = AF_UNSPEC;
2610 
2611  /* Figure out the port number we're going to use. */
2612  if (ch->port == NULL || ch->port[0] == '\0')
2613  thisport = DEF_PGPORT;
2614  else
2615  {
2616  if (!pqParseIntParam(ch->port, &thisport, conn, "port"))
2617  goto error_return;
2618 
2619  if (thisport < 1 || thisport > 65535)
2620  {
2621  libpq_append_conn_error(conn, "invalid port number: \"%s\"", ch->port);
2622  goto keep_going;
2623  }
2624  }
2625  snprintf(portstr, sizeof(portstr), "%d", thisport);
2626 
2627  /* Use pg_getaddrinfo_all() to resolve the address */
2628  switch (ch->type)
2629  {
2630  case CHT_HOST_NAME:
2631  ret = pg_getaddrinfo_all(ch->host, portstr, &hint,
2632  &addrlist);
2633  if (ret || !addrlist)
2634  {
2635  libpq_append_conn_error(conn, "could not translate host name \"%s\" to address: %s",
2636  ch->host, gai_strerror(ret));
2637  goto keep_going;
2638  }
2639  break;
2640 
2641  case CHT_HOST_ADDRESS:
2642  hint.ai_flags = AI_NUMERICHOST;
2643  ret = pg_getaddrinfo_all(ch->hostaddr, portstr, &hint,
2644  &addrlist);
2645  if (ret || !addrlist)
2646  {
2647  libpq_append_conn_error(conn, "could not parse network address \"%s\": %s",
2648  ch->hostaddr, gai_strerror(ret));
2649  goto keep_going;
2650  }
2651  break;
2652 
2653  case CHT_UNIX_SOCKET:
2654  hint.ai_family = AF_UNIX;
2655  UNIXSOCK_PATH(portstr, thisport, ch->host);
2656  if (strlen(portstr) >= UNIXSOCK_PATH_BUFLEN)
2657  {
2658  libpq_append_conn_error(conn, "Unix-domain socket path \"%s\" is too long (maximum %d bytes)",
2659  portstr,
2660  (int) (UNIXSOCK_PATH_BUFLEN - 1));
2661  goto keep_going;
2662  }
2663 
2664  /*
2665  * NULL hostname tells pg_getaddrinfo_all to parse the service
2666  * name as a Unix-domain socket path.
2667  */
2668  ret = pg_getaddrinfo_all(NULL, portstr, &hint,
2669  &addrlist);
2670  if (ret || !addrlist)
2671  {
2672  libpq_append_conn_error(conn, "could not translate Unix-domain socket path \"%s\" to address: %s",
2673  portstr, gai_strerror(ret));
2674  goto keep_going;
2675  }
2676  break;
2677  }
2678 
2679  /*
2680  * Store a copy of the addrlist in private memory so we can perform
2681  * randomization for load balancing.
2682  */
2683  ret = store_conn_addrinfo(conn, addrlist);
2684  pg_freeaddrinfo_all(hint.ai_family, addrlist);
2685  if (ret)
2686  goto error_return; /* message already logged */
2687 
2688  /*
2689  * If random load balancing is enabled we shuffle the addresses.
2690  */
2692  {
2693  /*
2694  * This is the "inside-out" variant of the Fisher-Yates shuffle
2695  * algorithm. Notionally, we append each new value to the array
2696  * and then swap it with a randomly-chosen array element (possibly
2697  * including itself, else we fail to generate permutations with
2698  * the last integer last). The swap step can be optimized by
2699  * combining it with the insertion.
2700  *
2701  * We don't need to initialize conn->prng_state here, because that
2702  * already happened in pqConnectOptions2.
2703  */
2704  for (int i = 1; i < conn->naddr; i++)
2705  {
2706  int j = pg_prng_uint64_range(&conn->prng_state, 0, i);
2707  AddrInfo temp = conn->addr[j];
2708 
2709  conn->addr[j] = conn->addr[i];
2710  conn->addr[i] = temp;
2711  }
2712  }
2713 
2714  reset_connection_state_machine = true;
2715  conn->try_next_host = false;
2716  }
2717 
2718  /* Reset connection state machine? */
2719  if (reset_connection_state_machine)
2720  {
2721  /*
2722  * (Re) initialize our connection control variables for a set of
2723  * connection attempts to a single server address. These variables
2724  * must persist across individual connection attempts, but we must
2725  * reset them when we start to consider a new server.
2726  */
2727  conn->pversion = PG_PROTOCOL(3, 0);
2728  conn->send_appname = true;
2729 #ifdef USE_SSL
2730  /* initialize these values based on SSL mode */
2731  conn->allow_ssl_try = (conn->sslmode[0] != 'd'); /* "disable" */
2732  conn->wait_ssl_try = (conn->sslmode[0] == 'a'); /* "allow" */
2733 #endif
2734 #ifdef ENABLE_GSS
2735  conn->try_gss = (conn->gssencmode[0] != 'd'); /* "disable" */
2736 #endif
2737 
2738  reset_connection_state_machine = false;
2739  need_new_connection = true;
2740  }
2741 
2742  /* Force a new connection (perhaps to the same server as before)? */
2743  if (need_new_connection)
2744  {
2745  /* Drop any existing connection */
2746  pqDropConnection(conn, true);
2747 
2748  /* Reset all state obtained from old server */
2750 
2751  /* Drop any PGresult we might have, too */
2756 
2757  /* Reset conn->status to put the state machine in the right state */
2759 
2760  need_new_connection = false;
2761  }
2762 
2763  /* Now try to advance the state machine for this connection */
2764  switch (conn->status)
2765  {
2766  case CONNECTION_NEEDED:
2767  {
2768  /*
2769  * Try to initiate a connection to one of the addresses
2770  * returned by pg_getaddrinfo_all(). conn->whichaddr is the
2771  * next one to try.
2772  *
2773  * The extra level of braces here is historical. It's not
2774  * worth reindenting this whole switch case to remove 'em.
2775  */
2776  {
2777  char host_addr[NI_MAXHOST];
2778  int sock_type;
2779  AddrInfo *addr_cur;
2780 
2781  /*
2782  * Advance to next possible host, if we've tried all of
2783  * the addresses for the current host.
2784  */
2785  if (conn->whichaddr == conn->naddr)
2786  {
2787  conn->try_next_host = true;
2788  goto keep_going;
2789  }
2790  addr_cur = &conn->addr[conn->whichaddr];
2791 
2792  /* Remember current address for possible use later */
2793  memcpy(&conn->raddr, &addr_cur->addr, sizeof(SockAddr));
2794 
2795  /*
2796  * Set connip, too. Note we purposely ignore strdup
2797  * failure; not a big problem if it fails.
2798  */
2799  if (conn->connip != NULL)
2800  {
2801  free(conn->connip);
2802  conn->connip = NULL;
2803  }
2804  getHostaddr(conn, host_addr, NI_MAXHOST);
2805  if (host_addr[0])
2806  conn->connip = strdup(host_addr);
2807 
2808  /* Try to create the socket */
2809  sock_type = SOCK_STREAM;
2810 #ifdef SOCK_CLOEXEC
2811 
2812  /*
2813  * Atomically mark close-on-exec, if possible on this
2814  * platform, so that there isn't a window where a
2815  * subprogram executed by another thread inherits the
2816  * socket. See fallback code below.
2817  */
2818  sock_type |= SOCK_CLOEXEC;
2819 #endif
2820 #ifdef SOCK_NONBLOCK
2821 
2822  /*
2823  * We might as well skip a system call for nonblocking
2824  * mode too, if we can.
2825  */
2826  sock_type |= SOCK_NONBLOCK;
2827 #endif
2828  conn->sock = socket(addr_cur->family, sock_type, 0);
2829  if (conn->sock == PGINVALID_SOCKET)
2830  {
2831  int errorno = SOCK_ERRNO;
2832 
2833  /*
2834  * Silently ignore socket() failure if we have more
2835  * addresses to try; this reduces useless chatter in
2836  * cases where the address list includes both IPv4 and
2837  * IPv6 but kernel only accepts one family.
2838  */
2839  if (conn->whichaddr < conn->naddr ||
2840  conn->whichhost + 1 < conn->nconnhost)
2841  {
2842  conn->try_next_addr = true;
2843  goto keep_going;
2844  }
2845  emitHostIdentityInfo(conn, host_addr);
2846  libpq_append_conn_error(conn, "could not create socket: %s",
2847  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
2848  goto error_return;
2849  }
2850 
2851  /*
2852  * Once we've identified a target address, all errors
2853  * except the preceding socket()-failure case should be
2854  * prefixed with host-identity information. (If the
2855  * connection succeeds, the contents of conn->errorMessage
2856  * won't matter, so this is harmless.)
2857  */
2858  emitHostIdentityInfo(conn, host_addr);
2859 
2860  /*
2861  * Select socket options: no delay of outgoing data for
2862  * TCP sockets, nonblock mode, close-on-exec. Try the
2863  * next address if any of this fails.
2864  */
2865  if (addr_cur->family != AF_UNIX)
2866  {
2867  if (!connectNoDelay(conn))
2868  {
2869  /* error message already created */
2870  conn->try_next_addr = true;
2871  goto keep_going;
2872  }
2873  }
2874 #ifndef SOCK_NONBLOCK
2875  if (!pg_set_noblock(conn->sock))
2876  {
2877  libpq_append_conn_error(conn, "could not set socket to nonblocking mode: %s",
2878  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2879  conn->try_next_addr = true;
2880  goto keep_going;
2881  }
2882 #endif
2883 
2884 #ifndef SOCK_CLOEXEC
2885 #ifdef F_SETFD
2886  if (fcntl(conn->sock, F_SETFD, FD_CLOEXEC) == -1)
2887  {
2888  libpq_append_conn_error(conn, "could not set socket to close-on-exec mode: %s",
2889  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2890  conn->try_next_addr = true;
2891  goto keep_going;
2892  }
2893 #endif /* F_SETFD */
2894 #endif
2895 
2896  if (addr_cur->family != AF_UNIX)
2897  {
2898 #ifndef WIN32
2899  int on = 1;
2900 #endif
2901  int usekeepalives = useKeepalives(conn);
2902  int err = 0;
2903 
2904  if (usekeepalives < 0)
2905  {
2906  libpq_append_conn_error(conn, "keepalives parameter must be an integer");
2907  err = 1;
2908  }
2909  else if (usekeepalives == 0)
2910  {
2911  /* Do nothing */
2912  }
2913 #ifndef WIN32
2914  else if (setsockopt(conn->sock,
2915  SOL_SOCKET, SO_KEEPALIVE,
2916  (char *) &on, sizeof(on)) < 0)
2917  {
2918  libpq_append_conn_error(conn, "%s(%s) failed: %s",
2919  "setsockopt",
2920  "SO_KEEPALIVE",
2921  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2922  err = 1;
2923  }
2924  else if (!setKeepalivesIdle(conn)
2926  || !setKeepalivesCount(conn))
2927  err = 1;
2928 #else /* WIN32 */
2929 #ifdef SIO_KEEPALIVE_VALS
2930  else if (!prepKeepalivesWin32(conn))
2931  err = 1;
2932 #endif /* SIO_KEEPALIVE_VALS */
2933 #endif /* WIN32 */
2934  else if (!setTCPUserTimeout(conn))
2935  err = 1;
2936 
2937  if (err)
2938  {
2939  conn->try_next_addr = true;
2940  goto keep_going;
2941  }
2942  }
2943 
2944  /*----------
2945  * We have three methods of blocking SIGPIPE during
2946  * send() calls to this socket:
2947  *
2948  * - setsockopt(sock, SO_NOSIGPIPE)
2949  * - send(sock, ..., MSG_NOSIGNAL)
2950  * - setting the signal mask to SIG_IGN during send()
2951  *
2952  * The third method requires three syscalls per send,
2953  * so we prefer either of the first two, but they are
2954  * less portable. The state is tracked in the following
2955  * members of PGconn:
2956  *
2957  * conn->sigpipe_so - we have set up SO_NOSIGPIPE
2958  * conn->sigpipe_flag - we're specifying MSG_NOSIGNAL
2959  *
2960  * If we can use SO_NOSIGPIPE, then set sigpipe_so here
2961  * and we're done. Otherwise, set sigpipe_flag so that
2962  * we will try MSG_NOSIGNAL on sends. If we get an error
2963  * with MSG_NOSIGNAL, we'll clear that flag and revert to
2964  * signal masking.
2965  *----------
2966  */
2967  conn->sigpipe_so = false;
2968 #ifdef MSG_NOSIGNAL
2969  conn->sigpipe_flag = true;
2970 #else
2971  conn->sigpipe_flag = false;
2972 #endif /* MSG_NOSIGNAL */
2973 
2974 #ifdef SO_NOSIGPIPE
2975  optval = 1;
2976  if (setsockopt(conn->sock, SOL_SOCKET, SO_NOSIGPIPE,
2977  (char *) &optval, sizeof(optval)) == 0)
2978  {
2979  conn->sigpipe_so = true;
2980  conn->sigpipe_flag = false;
2981  }
2982 #endif /* SO_NOSIGPIPE */
2983 
2984  /*
2985  * Start/make connection. This should not block, since we
2986  * are in nonblock mode. If it does, well, too bad.
2987  */
2988  if (connect(conn->sock, (struct sockaddr *) &addr_cur->addr.addr,
2989  addr_cur->addr.salen) < 0)
2990  {
2991  if (SOCK_ERRNO == EINPROGRESS ||
2992 #ifdef WIN32
2993  SOCK_ERRNO == EWOULDBLOCK ||
2994 #endif
2995  SOCK_ERRNO == EINTR)
2996  {
2997  /*
2998  * This is fine - we're in non-blocking mode, and
2999  * the connection is in progress. Tell caller to
3000  * wait for write-ready on socket.
3001  */
3003  return PGRES_POLLING_WRITING;
3004  }
3005  /* otherwise, trouble */
3006  }
3007  else
3008  {
3009  /*
3010  * Hm, we're connected already --- seems the "nonblock
3011  * connection" wasn't. Advance the state machine and
3012  * go do the next stuff.
3013  */
3015  goto keep_going;
3016  }
3017 
3018  /*
3019  * This connection failed. Add the error report to
3020  * conn->errorMessage, then try the next address if any.
3021  */
3023  conn->try_next_addr = true;
3024  goto keep_going;
3025  }
3026  }
3027 
3028  case CONNECTION_STARTED:
3029  {
3030  socklen_t optlen = sizeof(optval);
3031 
3032  /*
3033  * Write ready, since we've made it here, so the connection
3034  * has been made ... or has failed.
3035  */
3036 
3037  /*
3038  * Now check (using getsockopt) that there is not an error
3039  * state waiting for us on the socket.
3040  */
3041 
3042  if (getsockopt(conn->sock, SOL_SOCKET, SO_ERROR,
3043  (char *) &optval, &optlen) == -1)
3044  {
3045  libpq_append_conn_error(conn, "could not get socket error status: %s",
3046  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3047  goto error_return;
3048  }
3049  else if (optval != 0)
3050  {
3051  /*
3052  * When using a nonblocking connect, we will typically see
3053  * connect failures at this point, so provide a friendly
3054  * error message.
3055  */
3056  connectFailureMessage(conn, optval);
3057 
3058  /*
3059  * Try the next address if any, just as in the case where
3060  * connect() returned failure immediately.
3061  */
3062  conn->try_next_addr = true;
3063  goto keep_going;
3064  }
3065 
3066  /* Fill in the client address */
3067  conn->laddr.salen = sizeof(conn->laddr.addr);
3068  if (getsockname(conn->sock,
3069  (struct sockaddr *) &conn->laddr.addr,
3070  &conn->laddr.salen) < 0)
3071  {
3072  libpq_append_conn_error(conn, "could not get client address from socket: %s",
3073  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3074  goto error_return;
3075  }
3076 
3077  /*
3078  * Make sure we can write before advancing to next step.
3079  */
3081  return PGRES_POLLING_WRITING;
3082  }
3083 
3084  case CONNECTION_MADE:
3085  {
3086  char *startpacket;
3087  int packetlen;
3088 
3089  /*
3090  * Implement requirepeer check, if requested and it's a
3091  * Unix-domain socket.
3092  */
3093  if (conn->requirepeer && conn->requirepeer[0] &&
3094  conn->raddr.addr.ss_family == AF_UNIX)
3095  {
3096 #ifndef WIN32
3097  char *remote_username;
3098 #endif
3099  uid_t uid;
3100  gid_t gid;
3101 
3102  errno = 0;
3103  if (getpeereid(conn->sock, &uid, &gid) != 0)
3104  {
3105  /*
3106  * Provide special error message if getpeereid is a
3107  * stub
3108  */
3109  if (errno == ENOSYS)
3110  libpq_append_conn_error(conn, "requirepeer parameter is not supported on this platform");
3111  else
3112  libpq_append_conn_error(conn, "could not get peer credentials: %s",
3113  strerror_r(errno, sebuf, sizeof(sebuf)));
3114  goto error_return;
3115  }
3116 
3117 #ifndef WIN32
3118  remote_username = pg_fe_getusername(uid,
3119  &conn->errorMessage);
3120  if (remote_username == NULL)
3121  goto error_return; /* message already logged */
3122 
3123  if (strcmp(remote_username, conn->requirepeer) != 0)
3124  {
3125  libpq_append_conn_error(conn, "requirepeer specifies \"%s\", but actual peer user name is \"%s\"",
3126  conn->requirepeer, remote_username);
3127  free(remote_username);
3128  goto error_return;
3129  }
3130  free(remote_username);
3131 #else /* WIN32 */
3132  /* should have failed with ENOSYS above */
3133  Assert(false);
3134 #endif /* WIN32 */
3135  }
3136 
3137  if (conn->raddr.addr.ss_family == AF_UNIX)
3138  {
3139  /* Don't request SSL or GSSAPI over Unix sockets */
3140 #ifdef USE_SSL
3141  conn->allow_ssl_try = false;
3142 #endif
3143 #ifdef ENABLE_GSS
3144  conn->try_gss = false;
3145 #endif
3146  }
3147 
3148 #ifdef ENABLE_GSS
3149 
3150  /*
3151  * If GSSAPI encryption is enabled, then call
3152  * pg_GSS_have_cred_cache() which will return true if we can
3153  * acquire credentials (and give us a handle to use in
3154  * conn->gcred), and then send a packet to the server asking
3155  * for GSSAPI Encryption (and skip past SSL negotiation and
3156  * regular startup below).
3157  */
3158  if (conn->try_gss && !conn->gctx)
3159  conn->try_gss = pg_GSS_have_cred_cache(&conn->gcred);
3160  if (conn->try_gss && !conn->gctx)
3161  {
3163 
3164  if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
3165  {
3166  libpq_append_conn_error(conn, "could not send GSSAPI negotiation packet: %s",
3167  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3168  goto error_return;
3169  }
3170 
3171  /* Ok, wait for response */
3173  return PGRES_POLLING_READING;
3174  }
3175  else if (!conn->gctx && conn->gssencmode[0] == 'r')
3176  {
3178  "GSSAPI encryption required but was impossible (possibly no credential cache, no server support, or using a local socket)");
3179  goto error_return;
3180  }
3181 #endif
3182 
3183 #ifdef USE_SSL
3184 
3185  /*
3186  * Enable the libcrypto callbacks before checking if SSL needs
3187  * to be done. This is done before sending the startup packet
3188  * as depending on the type of authentication done, like MD5
3189  * or SCRAM that use cryptohashes, the callbacks would be
3190  * required even without a SSL connection
3191  */
3192  if (pqsecure_initialize(conn, false, true) < 0)
3193  goto error_return;
3194 
3195  /*
3196  * If SSL is enabled and we haven't already got encryption of
3197  * some sort running, request SSL instead of sending the
3198  * startup message.
3199  */
3200  if (conn->allow_ssl_try && !conn->wait_ssl_try &&
3201  !conn->ssl_in_use
3202 #ifdef ENABLE_GSS
3203  && !conn->gssenc
3204 #endif
3205  )
3206  {
3207  ProtocolVersion pv;
3208 
3209  /*
3210  * Send the SSL request packet.
3211  *
3212  * Theoretically, this could block, but it really
3213  * shouldn't since we only got here if the socket is
3214  * write-ready.
3215  */
3217  if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
3218  {
3219  libpq_append_conn_error(conn, "could not send SSL negotiation packet: %s",
3220  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3221  goto error_return;
3222  }
3223  /* Ok, wait for response */
3225  return PGRES_POLLING_READING;
3226  }
3227 #endif /* USE_SSL */
3228 
3229  /*
3230  * Build the startup packet.
3231  */
3232  startpacket = pqBuildStartupPacket3(conn, &packetlen,
3234  if (!startpacket)
3235  {
3236  libpq_append_conn_error(conn, "out of memory");
3237  goto error_return;
3238  }
3239 
3240  /*
3241  * Send the startup packet.
3242  *
3243  * Theoretically, this could block, but it really shouldn't
3244  * since we only got here if the socket is write-ready.
3245  */
3246  if (pqPacketSend(conn, 0, startpacket, packetlen) != STATUS_OK)
3247  {
3248  libpq_append_conn_error(conn, "could not send startup packet: %s",
3249  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3250  free(startpacket);
3251  goto error_return;
3252  }
3253 
3254  free(startpacket);
3255 
3257  return PGRES_POLLING_READING;
3258  }
3259 
3260  /*
3261  * Handle SSL negotiation: wait for postmaster messages and
3262  * respond as necessary.
3263  */
3265  {
3266 #ifdef USE_SSL
3267  PostgresPollingStatusType pollres;
3268 
3269  /*
3270  * On first time through, get the postmaster's response to our
3271  * SSL negotiation packet.
3272  */
3273  if (!conn->ssl_in_use)
3274  {
3275  /*
3276  * We use pqReadData here since it has the logic to
3277  * distinguish no-data-yet from connection closure. Since
3278  * conn->ssl isn't set, a plain recv() will occur.
3279  */
3280  char SSLok;
3281  int rdresult;
3282 
3283  rdresult = pqReadData(conn);
3284  if (rdresult < 0)
3285  {
3286  /* errorMessage is already filled in */
3287  goto error_return;
3288  }
3289  if (rdresult == 0)
3290  {
3291  /* caller failed to wait for data */
3292  return PGRES_POLLING_READING;
3293  }
3294  if (pqGetc(&SSLok, conn) < 0)
3295  {
3296  /* should not happen really */
3297  return PGRES_POLLING_READING;
3298  }
3299  if (SSLok == 'S')
3300  {
3301  /* mark byte consumed */
3302  conn->inStart = conn->inCursor;
3303 
3304  /*
3305  * Set up global SSL state if required. The crypto
3306  * state has already been set if libpq took care of
3307  * doing that, so there is no need to make that happen
3308  * again.
3309  */
3310  if (pqsecure_initialize(conn, true, false) != 0)
3311  goto error_return;
3312  }
3313  else if (SSLok == 'N')
3314  {
3315  /* mark byte consumed */
3316  conn->inStart = conn->inCursor;
3317  /* OK to do without SSL? */
3318  if (conn->sslmode[0] == 'r' || /* "require" */
3319  conn->sslmode[0] == 'v') /* "verify-ca" or
3320  * "verify-full" */
3321  {
3322  /* Require SSL, but server does not want it */
3323  libpq_append_conn_error(conn, "server does not support SSL, but SSL was required");
3324  goto error_return;
3325  }
3326  /* Otherwise, proceed with normal startup */
3327  conn->allow_ssl_try = false;
3328  /* We can proceed using this connection */
3330  return PGRES_POLLING_WRITING;
3331  }
3332  else if (SSLok == 'E')
3333  {
3334  /*
3335  * Server failure of some sort, such as failure to
3336  * fork a backend process. We need to process and
3337  * report the error message, which might be formatted
3338  * according to either protocol 2 or protocol 3.
3339  * Rather than duplicate the code for that, we flip
3340  * into AWAITING_RESPONSE state and let the code there
3341  * deal with it. Note we have *not* consumed the "E"
3342  * byte here.
3343  */
3345  goto keep_going;
3346  }
3347  else
3348  {
3349  libpq_append_conn_error(conn, "received invalid response to SSL negotiation: %c",
3350  SSLok);
3351  goto error_return;
3352  }
3353  }
3354 
3355  /*
3356  * Begin or continue the SSL negotiation process.
3357  */
3358  pollres = pqsecure_open_client(conn);
3359  if (pollres == PGRES_POLLING_OK)
3360  {
3361  /*
3362  * At this point we should have no data already buffered.
3363  * If we do, it was received before we performed the SSL
3364  * handshake, so it wasn't encrypted and indeed may have
3365  * been injected by a man-in-the-middle.
3366  */
3367  if (conn->inCursor != conn->inEnd)
3368  {
3369  libpq_append_conn_error(conn, "received unencrypted data after SSL response");
3370  goto error_return;
3371  }
3372 
3373  /* SSL handshake done, ready to send startup packet */
3375  return PGRES_POLLING_WRITING;
3376  }
3377  if (pollres == PGRES_POLLING_FAILED)
3378  {
3379  /*
3380  * Failed ... if sslmode is "prefer" then do a non-SSL
3381  * retry
3382  */
3383  if (conn->sslmode[0] == 'p' /* "prefer" */
3384  && conn->allow_ssl_try /* redundant? */
3385  && !conn->wait_ssl_try) /* redundant? */
3386  {
3387  /* only retry once */
3388  conn->allow_ssl_try = false;
3389  need_new_connection = true;
3390  goto keep_going;
3391  }
3392  /* Else it's a hard failure */
3393  goto error_return;
3394  }
3395  /* Else, return POLLING_READING or POLLING_WRITING status */
3396  return pollres;
3397 #else /* !USE_SSL */
3398  /* can't get here */
3399  goto error_return;
3400 #endif /* USE_SSL */
3401  }
3402 
3404  {
3405 #ifdef ENABLE_GSS
3406  PostgresPollingStatusType pollres;
3407 
3408  /*
3409  * If we haven't yet, get the postmaster's response to our
3410  * negotiation packet
3411  */
3412  if (conn->try_gss && !conn->gctx)
3413  {
3414  char gss_ok;
3415  int rdresult = pqReadData(conn);
3416 
3417  if (rdresult < 0)
3418  /* pqReadData fills in error message */
3419  goto error_return;
3420  else if (rdresult == 0)
3421  /* caller failed to wait for data */
3422  return PGRES_POLLING_READING;
3423  if (pqGetc(&gss_ok, conn) < 0)
3424  /* shouldn't happen... */
3425  return PGRES_POLLING_READING;
3426 
3427  if (gss_ok == 'E')
3428  {
3429  /*
3430  * Server failure of some sort. Assume it's a
3431  * protocol version support failure, and let's see if
3432  * we can't recover (if it's not, we'll get a better
3433  * error message on retry). Server gets fussy if we
3434  * don't hang up the socket, though.
3435  */
3436  conn->try_gss = false;
3437  need_new_connection = true;
3438  goto keep_going;
3439  }
3440 
3441  /* mark byte consumed */
3442  conn->inStart = conn->inCursor;
3443 
3444  if (gss_ok == 'N')
3445  {
3446  /* Server doesn't want GSSAPI; fall back if we can */
3447  if (conn->gssencmode[0] == 'r')
3448  {
3449  libpq_append_conn_error(conn, "server doesn't support GSSAPI encryption, but it was required");
3450  goto error_return;
3451  }
3452 
3453  conn->try_gss = false;
3454  /* We can proceed using this connection */
3456  return PGRES_POLLING_WRITING;
3457  }
3458  else if (gss_ok != 'G')
3459  {
3460  libpq_append_conn_error(conn, "received invalid response to GSSAPI negotiation: %c",
3461  gss_ok);
3462  goto error_return;
3463  }
3464  }
3465 
3466  /* Begin or continue GSSAPI negotiation */
3467  pollres = pqsecure_open_gss(conn);
3468  if (pollres == PGRES_POLLING_OK)
3469  {
3470  /*
3471  * At this point we should have no data already buffered.
3472  * If we do, it was received before we performed the GSS
3473  * handshake, so it wasn't encrypted and indeed may have
3474  * been injected by a man-in-the-middle.
3475  */
3476  if (conn->inCursor != conn->inEnd)
3477  {
3478  libpq_append_conn_error(conn, "received unencrypted data after GSSAPI encryption response");
3479  goto error_return;
3480  }
3481 
3482  /* All set for startup packet */
3484  return PGRES_POLLING_WRITING;
3485  }
3486  else if (pollres == PGRES_POLLING_FAILED)
3487  {
3488  if (conn->gssencmode[0] == 'p')
3489  {
3490  /*
3491  * We failed, but we can retry on "prefer". Have to
3492  * drop the current connection to do so, though.
3493  */
3494  conn->try_gss = false;
3495  need_new_connection = true;
3496  goto keep_going;
3497  }
3498  /* Else it's a hard failure */
3499  goto error_return;
3500  }
3501  /* Else, return POLLING_READING or POLLING_WRITING status */
3502  return pollres;
3503 #else /* !ENABLE_GSS */
3504  /* unreachable */
3505  goto error_return;
3506 #endif /* ENABLE_GSS */
3507  }
3508 
3509  /*
3510  * Handle authentication exchange: wait for postmaster messages
3511  * and respond as necessary.
3512  */
3514  {
3515  char beresp;
3516  int msgLength;
3517  int avail;
3518  AuthRequest areq;
3519  int res;
3520 
3521  /*
3522  * Scan the message from current point (note that if we find
3523  * the message is incomplete, we will return without advancing
3524  * inStart, and resume here next time).
3525  */
3526  conn->inCursor = conn->inStart;
3527 
3528  /* Read type byte */
3529  if (pqGetc(&beresp, conn))
3530  {
3531  /* We'll come back when there is more data */
3532  return PGRES_POLLING_READING;
3533  }
3534 
3535  /*
3536  * Validate message type: we expect only an authentication
3537  * request, NegotiateProtocolVersion, or an error here.
3538  * Anything else probably means it's not Postgres on the other
3539  * end at all.
3540  */
3541  if (beresp != PqMsg_AuthenticationRequest &&
3542  beresp != PqMsg_ErrorResponse &&
3544  {
3545  libpq_append_conn_error(conn, "expected authentication request from server, but received %c",
3546  beresp);
3547  goto error_return;
3548  }
3549 
3550  /* Read message length word */
3551  if (pqGetInt(&msgLength, 4, conn))
3552  {
3553  /* We'll come back when there is more data */
3554  return PGRES_POLLING_READING;
3555  }
3556 
3557  /*
3558  * Try to validate message length before using it.
3559  *
3560  * Authentication requests can't be very large, although GSS
3561  * auth requests may not be that small. Same for
3562  * NegotiateProtocolVersion.
3563  *
3564  * Errors can be a little larger, but not huge. If we see a
3565  * large apparent length in an error, it means we're really
3566  * talking to a pre-3.0-protocol server; cope. (Before
3567  * version 14, the server also used the old protocol for
3568  * errors that happened before processing the startup packet.)
3569  */
3570  if (beresp == PqMsg_AuthenticationRequest &&
3571  (msgLength < 8 || msgLength > 2000))
3572  {
3573  libpq_append_conn_error(conn, "received invalid authentication request");
3574  goto error_return;
3575  }
3576  if (beresp == PqMsg_NegotiateProtocolVersion &&
3577  (msgLength < 8 || msgLength > 2000))
3578  {
3579  libpq_append_conn_error(conn, "received invalid protocol negotiation message");
3580  goto error_return;
3581  }
3582 
3583 #define MAX_ERRLEN 30000
3584  if (beresp == PqMsg_ErrorResponse &&
3585  (msgLength < 8 || msgLength > MAX_ERRLEN))
3586  {
3587  /* Handle error from a pre-3.0 server */
3588  conn->inCursor = conn->inStart + 1; /* reread data */
3590  {
3591  /*
3592  * We may not have authenticated the server yet, so
3593  * don't let the buffer grow forever.
3594  */
3595  avail = conn->inEnd - conn->inCursor;
3596  if (avail > MAX_ERRLEN)
3597  {
3598  libpq_append_conn_error(conn, "received invalid error message");
3599  goto error_return;
3600  }
3601 
3602  /* We'll come back when there is more data */
3603  return PGRES_POLLING_READING;
3604  }
3605  /* OK, we read the message; mark data consumed */
3606  conn->inStart = conn->inCursor;
3607 
3608  /*
3609  * Before 7.2, the postmaster didn't always end its
3610  * messages with a newline, so add one if needed to
3611  * conform to libpq conventions.
3612  */
3613  if (conn->errorMessage.len == 0 ||
3614  conn->errorMessage.data[conn->errorMessage.len - 1] != '\n')
3615  {
3617  }
3618 
3619  goto error_return;
3620  }
3621 #undef MAX_ERRLEN
3622 
3623  /*
3624  * Can't process if message body isn't all here yet.
3625  *
3626  * After this check passes, any further EOF during parsing
3627  * implies that the server sent a bad/truncated message.
3628  * Reading more bytes won't help in that case, so don't return
3629  * PGRES_POLLING_READING after this point.
3630  */
3631  msgLength -= 4;
3632  avail = conn->inEnd - conn->inCursor;
3633  if (avail < msgLength)
3634  {
3635  /*
3636  * Before returning, try to enlarge the input buffer if
3637  * needed to hold the whole message; see notes in
3638  * pqParseInput3.
3639  */
3640  if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
3641  conn))
3642  goto error_return;
3643  /* We'll come back when there is more data */
3644  return PGRES_POLLING_READING;
3645  }
3646 
3647  /* Handle errors. */
3648  if (beresp == PqMsg_ErrorResponse)
3649  {
3650  if (pqGetErrorNotice3(conn, true))
3651  {
3652  libpq_append_conn_error(conn, "received invalid error message");
3653  goto error_return;
3654  }
3655  /* OK, we read the message; mark data consumed */
3656  conn->inStart = conn->inCursor;
3657 
3658  /*
3659  * If error is "cannot connect now", try the next host if
3660  * any (but we don't want to consider additional addresses
3661  * for this host, nor is there much point in changing SSL
3662  * or GSS mode). This is helpful when dealing with
3663  * standby servers that might not be in hot-standby state.
3664  */
3665  if (strcmp(conn->last_sqlstate,
3667  {
3668  conn->try_next_host = true;
3669  goto keep_going;
3670  }
3671 
3672  /* Check to see if we should mention pgpassfile */
3674 
3675 #ifdef ENABLE_GSS
3676 
3677  /*
3678  * If gssencmode is "prefer" and we're using GSSAPI, retry
3679  * without it.
3680  */
3681  if (conn->gssenc && conn->gssencmode[0] == 'p')
3682  {
3683  /* only retry once */
3684  conn->try_gss = false;
3685  need_new_connection = true;
3686  goto keep_going;
3687  }
3688 #endif
3689 
3690 #ifdef USE_SSL
3691 
3692  /*
3693  * if sslmode is "allow" and we haven't tried an SSL
3694  * connection already, then retry with an SSL connection
3695  */
3696  if (conn->sslmode[0] == 'a' /* "allow" */
3697  && !conn->ssl_in_use
3698  && conn->allow_ssl_try
3699  && conn->wait_ssl_try)
3700  {
3701  /* only retry once */
3702  conn->wait_ssl_try = false;
3703  need_new_connection = true;
3704  goto keep_going;
3705  }
3706 
3707  /*
3708  * if sslmode is "prefer" and we're in an SSL connection,
3709  * then do a non-SSL retry
3710  */
3711  if (conn->sslmode[0] == 'p' /* "prefer" */
3712  && conn->ssl_in_use
3713  && conn->allow_ssl_try /* redundant? */
3714  && !conn->wait_ssl_try) /* redundant? */
3715  {
3716  /* only retry once */
3717  conn->allow_ssl_try = false;
3718  need_new_connection = true;
3719  goto keep_going;
3720  }
3721 #endif
3722 
3723  goto error_return;
3724  }
3725  else if (beresp == PqMsg_NegotiateProtocolVersion)
3726  {
3728  {
3729  libpq_append_conn_error(conn, "received invalid protocol negotiation message");
3730  goto error_return;
3731  }
3732  /* OK, we read the message; mark data consumed */
3733  conn->inStart = conn->inCursor;
3734  goto error_return;
3735  }
3736 
3737  /* It is an authentication request. */
3738  conn->auth_req_received = true;
3739 
3740  /* Get the type of request. */
3741  if (pqGetInt((int *) &areq, 4, conn))
3742  {
3743  /* can't happen because we checked the length already */
3744  libpq_append_conn_error(conn, "received invalid authentication request");
3745  goto error_return;
3746  }
3747  msgLength -= 4;
3748 
3749  /*
3750  * Process the rest of the authentication request message, and
3751  * respond to it if necessary.
3752  *
3753  * Note that conn->pghost must be non-NULL if we are going to
3754  * avoid the Kerberos code doing a hostname look-up.
3755  */
3756  res = pg_fe_sendauth(areq, msgLength, conn);
3757 
3758  /* OK, we have processed the message; mark data consumed */
3759  conn->inStart = conn->inCursor;
3760 
3761  if (res != STATUS_OK)
3762  goto error_return;
3763 
3764  /*
3765  * Just make sure that any data sent by pg_fe_sendauth is
3766  * flushed out. Although this theoretically could block, it
3767  * really shouldn't since we don't send large auth responses.
3768  */
3769  if (pqFlush(conn))
3770  goto error_return;
3771 
3772  if (areq == AUTH_REQ_OK)
3773  {
3774  /* We are done with authentication exchange */
3776 
3777  /*
3778  * Set asyncStatus so that PQgetResult will think that
3779  * what comes back next is the result of a query. See
3780  * below.
3781  */
3783  }
3784 
3785  /* Look to see if we have more data yet. */
3786  goto keep_going;
3787  }
3788 
3789  case CONNECTION_AUTH_OK:
3790  {
3791  /*
3792  * Now we expect to hear from the backend. A ReadyForQuery
3793  * message indicates that startup is successful, but we might
3794  * also get an Error message indicating failure. (Notice
3795  * messages indicating nonfatal warnings are also allowed by
3796  * the protocol, as are ParameterStatus and BackendKeyData
3797  * messages.) Easiest way to handle this is to let
3798  * PQgetResult() read the messages. We just have to fake it
3799  * out about the state of the connection, by setting
3800  * asyncStatus = PGASYNC_BUSY (done above).
3801  */
3802 
3803  if (PQisBusy(conn))
3804  return PGRES_POLLING_READING;
3805 
3806  res = PQgetResult(conn);
3807 
3808  /*
3809  * NULL return indicating we have gone to IDLE state is
3810  * expected
3811  */
3812  if (res)
3813  {
3815  libpq_append_conn_error(conn, "unexpected message from server during startup");
3816  else if (conn->send_appname &&
3817  (conn->appname || conn->fbappname))
3818  {
3819  /*
3820  * If we tried to send application_name, check to see
3821  * if the error is about that --- pre-9.0 servers will
3822  * reject it at this stage of the process. If so,
3823  * close the connection and retry without sending
3824  * application_name. We could possibly get a false
3825  * SQLSTATE match here and retry uselessly, but there
3826  * seems no great harm in that; we'll just get the
3827  * same error again if it's unrelated.
3828  */
3829  const char *sqlstate;
3830 
3832  if (sqlstate &&
3833  strcmp(sqlstate, ERRCODE_APPNAME_UNKNOWN) == 0)
3834  {
3835  PQclear(res);
3836  conn->send_appname = false;
3837  need_new_connection = true;
3838  goto keep_going;
3839  }
3840  }
3841 
3842  /*
3843  * if the resultStatus is FATAL, then conn->errorMessage
3844  * already has a copy of the error; needn't copy it back.
3845  * But add a newline if it's not there already, since
3846  * postmaster error messages may not have one.
3847  */
3848  if (conn->errorMessage.len <= 0 ||
3849  conn->errorMessage.data[conn->errorMessage.len - 1] != '\n')
3851  PQclear(res);
3852  goto error_return;
3853  }
3854 
3855  /* Almost there now ... */
3857  goto keep_going;
3858  }
3859 
3861  {
3862  /*
3863  * If a read-write, read-only, primary, or standby connection
3864  * is required, see if we have one.
3865  */
3868  {
3869  bool read_only_server;
3870 
3871  /*
3872  * If the server didn't report
3873  * "default_transaction_read_only" or "in_hot_standby" at
3874  * startup, we must determine its state by sending the
3875  * query "SHOW transaction_read_only". This GUC exists in
3876  * all server versions that support 3.0 protocol.
3877  */
3880  {
3881  /*
3882  * We use PQsendQueryContinue so that
3883  * conn->errorMessage does not get cleared. We need
3884  * to preserve any error messages related to previous
3885  * hosts we have tried and failed to connect to.
3886  */
3889  "SHOW transaction_read_only"))
3890  goto error_return;
3891  /* We'll return to this state when we have the answer */
3893  return PGRES_POLLING_READING;
3894  }
3895 
3896  /* OK, we can make the test */
3897  read_only_server =
3900 
3902  read_only_server : !read_only_server)
3903  {
3904  /* Wrong server state, reject and try the next host */