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 <pwd.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 DefaultSSLNegotiation   "postgres"
 
#define DefaultGSSMode   "disable"
 
#define ENCRYPTION_NEGOTIATION_FAILED(msg)
 
#define CONNECTION_FAILED()
 
#define MAX_ERRLEN   30000
 
#define SELECT_NEXT_METHOD(method)
 

Typedefs

typedef struct _internalPQconninfoOption internalPQconninfoOption
 

Functions

static bool connectOptions1 (PGconn *conn, const char *conninfo)
 
static bool init_allowed_encryption_methods (PGconn *conn)
 
static bool connection_failed (PGconn *conn)
 
static bool select_next_encryption_method (PGconn *conn, bool have_valid_connection)
 
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)
 
bool pqCopyPGconn (PGconn *srcConn, PGconn *dstConn)
 
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 PQfullProtocolVersion (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

◆ CONNECTION_FAILED

#define CONNECTION_FAILED ( )
Value:
do { \
{ \
need_new_connection = true; \
goto keep_going; \
} \
else \
goto error_return; \
} while(0);
static bool connection_failed(PGconn *conn)
Definition: fe-connect.c:4396
PGconn * conn
Definition: streamutil.c:55

◆ DefaultChannelBinding

#define DefaultChannelBinding   "disable"

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

◆ DefaultGSSMode

#define DefaultGSSMode   "disable"

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

◆ DefaultHost

#define DefaultHost   "localhost"

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

◆ DefaultLoadBalanceHosts

#define DefaultLoadBalanceHosts   "disable"

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

◆ DefaultOption

#define DefaultOption   ""

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

◆ DefaultSSLCertMode

#define DefaultSSLCertMode   "disable"

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

◆ DefaultSSLMode

#define DefaultSSLMode   "disable"

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

◆ DefaultSSLNegotiation

#define DefaultSSLNegotiation   "postgres"

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

◆ DefaultTargetSessionAttrs

#define DefaultTargetSessionAttrs   "any"

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

◆ ENCRYPTION_NEGOTIATION_FAILED

#define ENCRYPTION_NEGOTIATION_FAILED (   msg)
Value:
do { \
switch (encryption_negotiation_failed(conn)) \
{ \
case 0: \
libpq_append_conn_error(conn, (msg)); \
goto error_return; \
case 1: \
conn->status = CONNECTION_MADE; \
case 2: \
need_new_connection = true; \
goto keep_going; \
} \
} while(0);
@ CONNECTION_MADE
Definition: libpq-fe.h:90
@ PGRES_POLLING_WRITING
Definition: libpq-fe.h:112

◆ ERRCODE_APPNAME_UNKNOWN

#define ERRCODE_APPNAME_UNKNOWN   "42704"

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

◆ ERRCODE_CANNOT_CONNECT_NOW

#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"

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

◆ ERRCODE_INVALID_PASSWORD

#define ERRCODE_INVALID_PASSWORD   "28P01"

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

◆ MAX_ERRLEN

#define MAX_ERRLEN   30000

◆ PGPASSFILE

#define PGPASSFILE   ".pgpass"

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

◆ SELECT_NEXT_METHOD

#define SELECT_NEXT_METHOD (   method)
Value:
do { \
if ((remaining_methods & method) != 0) \
{ \
conn->current_enc_method = method; \
return true; \
} \
} while (false)

Typedef Documentation

◆ internalPQconninfoOption

Function Documentation

◆ connectFailureMessage()

static void connectFailureMessage ( PGconn conn,
int  errorno 
)
static

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

2151 {
2152  char sebuf[PG_STRERROR_R_BUFLEN];
2153 
2155  "%s\n",
2156  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
2157 
2158  if (conn->raddr.addr.ss_family == AF_UNIX)
2159  libpq_append_conn_error(conn, "\tIs the server running locally and accepting connections on that socket?");
2160  else
2161  libpq_append_conn_error(conn, "\tIs the server running on that host and accepting TCP/IP connections?");
2162 }
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition: fe-misc.c:1372
#define SOCK_STRERROR
Definition: libpq-int.h:927
#define PG_STRERROR_R_BUFLEN
Definition: port.h:256
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:265
struct sockaddr_storage addr
Definition: pqcomm.h:32
PQExpBufferData errorMessage
Definition: libpq-int.h:642
SockAddr raddr
Definition: libpq-int.h:488

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

◆ connection_failed()

static bool connection_failed ( PGconn conn)
static

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

4397 {
4400 
4401  return select_next_encryption_method(conn, false);
4402 }
#define Assert(condition)
Definition: c.h:858
static bool select_next_encryption_method(PGconn *conn, bool have_valid_connection)
Definition: fe-connect.c:4411
uint8 failed_enc_methods
Definition: libpq-int.h:576
uint8 current_enc_method
Definition: libpq-int.h:577

References Assert, conn, pg_conn::current_enc_method, pg_conn::failed_enc_methods, and select_next_encryption_method().

◆ connectNoDelay()

static int connectNoDelay ( PGconn conn)
static

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

2036 {
2037 #ifdef TCP_NODELAY
2038  int on = 1;
2039 
2040  if (setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY,
2041  (char *) &on,
2042  sizeof(on)) < 0)
2043  {
2044  char sebuf[PG_STRERROR_R_BUFLEN];
2045 
2046  libpq_append_conn_error(conn, "could not set socket to TCP no delay mode: %s",
2047  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2048  return 0;
2049  }
2050 #endif
2051 
2052  return 1;
2053 }
#define SOCK_ERRNO
Definition: libpq-int.h:926
pgsocket sock
Definition: libpq-int.h:485

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

999 {
1000  PQconninfoOption *connOptions;
1001 
1002  /*
1003  * Parse the conninfo string
1004  */
1005  connOptions = parse_connection_string(conninfo, &conn->errorMessage, true);
1006  if (connOptions == NULL)
1007  {
1009  /* errorMessage is already set */
1010  return false;
1011  }
1012 
1013  /*
1014  * Move option values into conn structure
1015  */
1016  if (!fillPGconn(conn, connOptions))
1017  {
1019  PQconninfoFree(connOptions);
1020  return false;
1021  }
1022 
1023  /*
1024  * Free the option info - all is in conn now
1025  */
1026  PQconninfoFree(connOptions);
1027 
1028  return true;
1029 }
static PQconninfoOption * parse_connection_string(const char *connstr, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5814
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:7005
static bool fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
Definition: fe-connect.c:919
@ CONNECTION_BAD
Definition: libpq-fe.h:82
ConnStatusType status
Definition: libpq-int.h:448

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

6203 {
6205  PQconninfoOption *sslmode_default = NULL,
6206  *sslrootcert = NULL;
6207  char *tmp;
6208 
6209  /*
6210  * If there's a service spec, use it to obtain any not-explicitly-given
6211  * parameters. Ignore error if no error message buffer is passed because
6212  * there is no way to pass back the failure message.
6213  */
6214  if (parseServiceInfo(options, errorMessage) != 0 && errorMessage)
6215  return false;
6216 
6217  /*
6218  * Get the fallback resources for parameters not specified in the conninfo
6219  * string nor the service.
6220  */
6221  for (option = options; option->keyword != NULL; option++)
6222  {
6223  if (strcmp(option->keyword, "sslrootcert") == 0)
6224  sslrootcert = option; /* save for later */
6225 
6226  if (option->val != NULL)
6227  continue; /* Value was in conninfo or service */
6228 
6229  /*
6230  * Try to get the environment variable fallback
6231  */
6232  if (option->envvar != NULL)
6233  {
6234  if ((tmp = getenv(option->envvar)) != NULL)
6235  {
6236  option->val = strdup(tmp);
6237  if (!option->val)
6238  {
6239  if (errorMessage)
6240  libpq_append_error(errorMessage, "out of memory");
6241  return false;
6242  }
6243  continue;
6244  }
6245  }
6246 
6247  /*
6248  * Interpret the deprecated PGREQUIRESSL environment variable. Per
6249  * tradition, translate values starting with "1" to sslmode=require,
6250  * and ignore other values. Given both PGREQUIRESSL=1 and PGSSLMODE,
6251  * PGSSLMODE takes precedence; the opposite was true before v9.3.
6252  */
6253  if (strcmp(option->keyword, "sslmode") == 0)
6254  {
6255  const char *requiresslenv = getenv("PGREQUIRESSL");
6256 
6257  if (requiresslenv != NULL && requiresslenv[0] == '1')
6258  {
6259  option->val = strdup("require");
6260  if (!option->val)
6261  {
6262  if (errorMessage)
6263  libpq_append_error(errorMessage, "out of memory");
6264  return false;
6265  }
6266  continue;
6267  }
6268 
6269  /*
6270  * sslmode is not specified. Let it be filled in with the compiled
6271  * default for now, but if sslrootcert=system, we'll override the
6272  * default later before returning.
6273  */
6274  sslmode_default = option;
6275  }
6276 
6277  /*
6278  * No environment variable specified or the variable isn't set - try
6279  * compiled-in default
6280  */
6281  if (option->compiled != NULL)
6282  {
6283  option->val = strdup(option->compiled);
6284  if (!option->val)
6285  {
6286  if (errorMessage)
6287  libpq_append_error(errorMessage, "out of memory");
6288  return false;
6289  }
6290  continue;
6291  }
6292 
6293  /*
6294  * Special handling for "user" option. Note that if pg_fe_getauthname
6295  * fails, we just leave the value as NULL; there's no need for this to
6296  * be an error condition if the caller provides a user name. The only
6297  * reason we do this now at all is so that callers of PQconndefaults
6298  * will see a correct default (barring error, of course).
6299  */
6300  if (strcmp(option->keyword, "user") == 0)
6301  {
6302  option->val = pg_fe_getauthname(NULL);
6303  continue;
6304  }
6305  }
6306 
6307  /*
6308  * Special handling for sslrootcert=system with no sslmode explicitly
6309  * defined. In this case we want to strengthen the default sslmode to
6310  * verify-full.
6311  */
6312  if (sslmode_default && sslrootcert)
6313  {
6314  if (sslrootcert->val && strcmp(sslrootcert->val, "system") == 0)
6315  {
6316  free(sslmode_default->val);
6317 
6318  sslmode_default->val = strdup("verify-full");
6319  if (!sslmode_default->val)
6320  {
6321  if (errorMessage)
6322  libpq_append_error(errorMessage, "out of memory");
6323  return false;
6324  }
6325  }
6326  }
6327 
6328  return true;
6329 }
char * pg_fe_getauthname(PQExpBuffer errorMessage)
Definition: fe-auth.c:1255
static int parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5507
void libpq_append_error(PQExpBuffer errorMessage, const char *fmt,...)
Definition: fe-misc.c:1343
#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 6044 of file fe-connect.c.

6047 {
6049  PQconninfoOption *dbname_options = NULL;
6051  int i = 0;
6052 
6053  /*
6054  * If expand_dbname is non-zero, check keyword "dbname" to see if val is
6055  * actually a recognized connection string.
6056  */
6057  while (expand_dbname && keywords[i])
6058  {
6059  const char *pname = keywords[i];
6060  const char *pvalue = values[i];
6061 
6062  /* first find "dbname" if any */
6063  if (strcmp(pname, "dbname") == 0 && pvalue)
6064  {
6065  /*
6066  * If value is a connection string, parse it, but do not use
6067  * defaults here -- those get picked up later. We only want to
6068  * override for those parameters actually passed.
6069  */
6070  if (recognized_connection_string(pvalue))
6071  {
6072  dbname_options = parse_connection_string(pvalue, errorMessage, false);
6073  if (dbname_options == NULL)
6074  return NULL;
6075  }
6076  break;
6077  }
6078  ++i;
6079  }
6080 
6081  /* Make a working copy of PQconninfoOptions */
6082  options = conninfo_init(errorMessage);
6083  if (options == NULL)
6084  {
6085  PQconninfoFree(dbname_options);
6086  return NULL;
6087  }
6088 
6089  /* Parse the keywords/values arrays */
6090  i = 0;
6091  while (keywords[i])
6092  {
6093  const char *pname = keywords[i];
6094  const char *pvalue = values[i];
6095 
6096  if (pvalue != NULL && pvalue[0] != '\0')
6097  {
6098  /* Search for the param record */
6099  for (option = options; option->keyword != NULL; option++)
6100  {
6101  if (strcmp(option->keyword, pname) == 0)
6102  break;
6103  }
6104 
6105  /* Check for invalid connection option */
6106  if (option->keyword == NULL)
6107  {
6108  libpq_append_error(errorMessage, "invalid connection option \"%s\"", pname);
6110  PQconninfoFree(dbname_options);
6111  return NULL;
6112  }
6113 
6114  /*
6115  * If we are on the first dbname parameter, and we have a parsed
6116  * connection string, copy those parameters across, overriding any
6117  * existing previous settings.
6118  */
6119  if (strcmp(pname, "dbname") == 0 && dbname_options)
6120  {
6121  PQconninfoOption *str_option;
6122 
6123  for (str_option = dbname_options; str_option->keyword != NULL; str_option++)
6124  {
6125  if (str_option->val != NULL)
6126  {
6127  int k;
6128 
6129  for (k = 0; options[k].keyword; k++)
6130  {
6131  if (strcmp(options[k].keyword, str_option->keyword) == 0)
6132  {
6133  free(options[k].val);
6134  options[k].val = strdup(str_option->val);
6135  if (!options[k].val)
6136  {
6137  libpq_append_error(errorMessage, "out of memory");
6139  PQconninfoFree(dbname_options);
6140  return NULL;
6141  }
6142  break;
6143  }
6144  }
6145  }
6146  }
6147 
6148  /*
6149  * Forget the parsed connection string, so that any subsequent
6150  * dbname parameters will not be expanded.
6151  */
6152  PQconninfoFree(dbname_options);
6153  dbname_options = NULL;
6154  }
6155  else
6156  {
6157  /*
6158  * Store the value, overriding previous settings
6159  */
6160  free(option->val);
6161  option->val = strdup(pvalue);
6162  if (!option->val)
6163  {
6164  libpq_append_error(errorMessage, "out of memory");
6166  PQconninfoFree(dbname_options);
6167  return NULL;
6168  }
6169  }
6170  }
6171  ++i;
6172  }
6173  PQconninfoFree(dbname_options);
6174 
6175  /*
6176  * Add in defaults if the caller wants that.
6177  */
6178  if (use_defaults)
6179  {
6180  if (!conninfo_add_defaults(options, errorMessage))
6181  {
6183  return NULL;
6184  }
6185  }
6186 
6187  return options;
6188 }
static Datum values[MAXATTR]
Definition: bootstrap.c:150
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:5775
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:6202
static bool recognized_connection_string(const char *connstr)
Definition: fe-connect.c:5857
long val
Definition: informix.c:689
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 6943 of file fe-connect.c.

6944 {
6946 
6947  for (option = connOptions; option->keyword != NULL; option++)
6948  {
6949  if (strcmp(option->keyword, keyword) == 0)
6950  return option;
6951  }
6952 
6953  return NULL;
6954 }

Referenced by conninfo_getval(), and conninfo_storeval().

◆ conninfo_getval()

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

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

6855 {
6857 
6858  option = conninfo_find(connOptions, keyword);
6859 
6860  return option ? option->val : NULL;
6861 }
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6943

References conninfo_find(), and option::val.

Referenced by fillPGconn(), and parseServiceInfo().

◆ conninfo_init()

static PQconninfoOption * conninfo_init ( PQExpBuffer  errorMessage)
static

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

5776 {
5778  PQconninfoOption *opt_dest;
5779  const internalPQconninfoOption *cur_opt;
5780 
5781  /*
5782  * Get enough memory for all options in PQconninfoOptions, even if some
5783  * end up being filtered out.
5784  */
5786  if (options == NULL)
5787  {
5788  libpq_append_error(errorMessage, "out of memory");
5789  return NULL;
5790  }
5791  opt_dest = options;
5792 
5793  for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++)
5794  {
5795  /* Only copy the public part of the struct, not the full internal */
5796  memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption));
5797  opt_dest++;
5798  }
5799  MemSet(opt_dest, 0, sizeof(PQconninfoOption));
5800 
5801  return options;
5802 }
#define MemSet(start, val, len)
Definition: c.h:1020
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:191
#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 5868 of file fe-connect.c.

5870 {
5871  char *pname;
5872  char *pval;
5873  char *buf;
5874  char *cp;
5875  char *cp2;
5877 
5878  /* Make a working copy of PQconninfoOptions */
5879  options = conninfo_init(errorMessage);
5880  if (options == NULL)
5881  return NULL;
5882 
5883  /* Need a modifiable copy of the input string */
5884  if ((buf = strdup(conninfo)) == NULL)
5885  {
5886  libpq_append_error(errorMessage, "out of memory");
5888  return NULL;
5889  }
5890  cp = buf;
5891 
5892  while (*cp)
5893  {
5894  /* Skip blanks before the parameter name */
5895  if (isspace((unsigned char) *cp))
5896  {
5897  cp++;
5898  continue;
5899  }
5900 
5901  /* Get the parameter name */
5902  pname = cp;
5903  while (*cp)
5904  {
5905  if (*cp == '=')
5906  break;
5907  if (isspace((unsigned char) *cp))
5908  {
5909  *cp++ = '\0';
5910  while (*cp)
5911  {
5912  if (!isspace((unsigned char) *cp))
5913  break;
5914  cp++;
5915  }
5916  break;
5917  }
5918  cp++;
5919  }
5920 
5921  /* Check that there is a following '=' */
5922  if (*cp != '=')
5923  {
5924  libpq_append_error(errorMessage,
5925  "missing \"=\" after \"%s\" in connection info string",
5926  pname);
5928  free(buf);
5929  return NULL;
5930  }
5931  *cp++ = '\0';
5932 
5933  /* Skip blanks after the '=' */
5934  while (*cp)
5935  {
5936  if (!isspace((unsigned char) *cp))
5937  break;
5938  cp++;
5939  }
5940 
5941  /* Get the parameter value */
5942  pval = cp;
5943 
5944  if (*cp != '\'')
5945  {
5946  cp2 = pval;
5947  while (*cp)
5948  {
5949  if (isspace((unsigned char) *cp))
5950  {
5951  *cp++ = '\0';
5952  break;
5953  }
5954  if (*cp == '\\')
5955  {
5956  cp++;
5957  if (*cp != '\0')
5958  *cp2++ = *cp++;
5959  }
5960  else
5961  *cp2++ = *cp++;
5962  }
5963  *cp2 = '\0';
5964  }
5965  else
5966  {
5967  cp2 = pval;
5968  cp++;
5969  for (;;)
5970  {
5971  if (*cp == '\0')
5972  {
5973  libpq_append_error(errorMessage, "unterminated quoted string in connection info string");
5975  free(buf);
5976  return NULL;
5977  }
5978  if (*cp == '\\')
5979  {
5980  cp++;
5981  if (*cp != '\0')
5982  *cp2++ = *cp++;
5983  continue;
5984  }
5985  if (*cp == '\'')
5986  {
5987  *cp2 = '\0';
5988  cp++;
5989  break;
5990  }
5991  *cp2++ = *cp++;
5992  }
5993  }
5994 
5995  /*
5996  * Now that we have the name and the value, store the record.
5997  */
5998  if (!conninfo_storeval(options, pname, pval, errorMessage, false, false))
5999  {
6001  free(buf);
6002  return NULL;
6003  }
6004  }
6005 
6006  /* Done with the modifiable input string */
6007  free(buf);
6008 
6009  /*
6010  * Add in defaults if the caller wants that.
6011  */
6012  if (use_defaults)
6013  {
6014  if (!conninfo_add_defaults(options, errorMessage))
6015  {
6017  return NULL;
6018  }
6019  }
6020 
6021  return options;
6022 }
static PQconninfoOption * conninfo_storeval(PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode)
Definition: fe-connect.c:6879
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 6879 of file fe-connect.c.

6883 {
6885  char *value_copy;
6886 
6887  /*
6888  * For backwards compatibility, requiressl=1 gets translated to
6889  * sslmode=require, and requiressl=0 gets translated to sslmode=prefer
6890  * (which is the default for sslmode).
6891  */
6892  if (strcmp(keyword, "requiressl") == 0)
6893  {
6894  keyword = "sslmode";
6895  if (value[0] == '1')
6896  value = "require";
6897  else
6898  value = "prefer";
6899  }
6900 
6901  option = conninfo_find(connOptions, keyword);
6902  if (option == NULL)
6903  {
6904  if (!ignoreMissing)
6905  libpq_append_error(errorMessage,
6906  "invalid connection option \"%s\"",
6907  keyword);
6908  return NULL;
6909  }
6910 
6911  if (uri_decode)
6912  {
6913  value_copy = conninfo_uri_decode(value, errorMessage);
6914  if (value_copy == NULL)
6915  /* conninfo_uri_decode already set an error message */
6916  return NULL;
6917  }
6918  else
6919  {
6920  value_copy = strdup(value);
6921  if (value_copy == NULL)
6922  {
6923  libpq_append_error(errorMessage, "out of memory");
6924  return NULL;
6925  }
6926  }
6927 
6928  free(option->val);
6929  option->val = value_copy;
6930 
6931  return option;
6932 }
static char * conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
Definition: fe-connect.c:6764
static struct @157 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 6764 of file fe-connect.c.

6765 {
6766  char *buf;
6767  char *p;
6768  const char *q = str;
6769 
6770  buf = malloc(strlen(str) + 1);
6771  if (buf == NULL)
6772  {
6773  libpq_append_error(errorMessage, "out of memory");
6774  return NULL;
6775  }
6776  p = buf;
6777 
6778  for (;;)
6779  {
6780  if (*q != '%')
6781  {
6782  /* copy and check for NUL terminator */
6783  if (!(*(p++) = *(q++)))
6784  break;
6785  }
6786  else
6787  {
6788  int hi;
6789  int lo;
6790  int c;
6791 
6792  ++q; /* skip the percent sign itself */
6793 
6794  /*
6795  * Possible EOL will be caught by the first call to
6796  * get_hexdigit(), so we never dereference an invalid q pointer.
6797  */
6798  if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo)))
6799  {
6800  libpq_append_error(errorMessage,
6801  "invalid percent-encoded token: \"%s\"",
6802  str);
6803  free(buf);
6804  return NULL;
6805  }
6806 
6807  c = (hi << 4) | lo;
6808  if (c == 0)
6809  {
6810  libpq_append_error(errorMessage,
6811  "forbidden value %%00 in percent-encoded value: \"%s\"",
6812  str);
6813  free(buf);
6814  return NULL;
6815  }
6816  *(p++) = c;
6817  }
6818  }
6819 
6820  return buf;
6821 }
static bool get_hexdigit(char digit, int *value)
Definition: fe-connect.c:6832
const char * str
char * c

References buf, free, get_hexdigit(), libpq_append_error(), malloc, and 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 6337 of file fe-connect.c.

6339 {
6341 
6342  /* Make a working copy of PQconninfoOptions */
6343  options = conninfo_init(errorMessage);
6344  if (options == NULL)
6345  return NULL;
6346 
6347  if (!conninfo_uri_parse_options(options, uri, errorMessage))
6348  {
6350  return NULL;
6351  }
6352 
6353  /*
6354  * Add in defaults if the caller wants that.
6355  */
6356  if (use_defaults)
6357  {
6358  if (!conninfo_add_defaults(options, errorMessage))
6359  {
6361  return NULL;
6362  }
6363  }
6364 
6365  return options;
6366 }
static bool conninfo_uri_parse_options(PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage)
Definition: fe-connect.c:6390

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

6392 {
6393  int prefix_len;
6394  char *p;
6395  char *buf = NULL;
6396  char *start;
6397  char prevchar = '\0';
6398  char *user = NULL;
6399  char *host = NULL;
6400  bool retval = false;
6401  PQExpBufferData hostbuf;
6402  PQExpBufferData portbuf;
6403 
6404  initPQExpBuffer(&hostbuf);
6405  initPQExpBuffer(&portbuf);
6406  if (PQExpBufferDataBroken(hostbuf) || PQExpBufferDataBroken(portbuf))
6407  {
6408  libpq_append_error(errorMessage, "out of memory");
6409  goto cleanup;
6410  }
6411 
6412  /* need a modifiable copy of the input URI */
6413  buf = strdup(uri);
6414  if (buf == NULL)
6415  {
6416  libpq_append_error(errorMessage, "out of memory");
6417  goto cleanup;
6418  }
6419  start = buf;
6420 
6421  /* Skip the URI prefix */
6422  prefix_len = uri_prefix_length(uri);
6423  if (prefix_len == 0)
6424  {
6425  /* Should never happen */
6426  libpq_append_error(errorMessage,
6427  "invalid URI propagated to internal parser routine: \"%s\"",
6428  uri);
6429  goto cleanup;
6430  }
6431  start += prefix_len;
6432  p = start;
6433 
6434  /* Look ahead for possible user credentials designator */
6435  while (*p && *p != '@' && *p != '/')
6436  ++p;
6437  if (*p == '@')
6438  {
6439  /*
6440  * Found username/password designator, so URI should be of the form
6441  * "scheme://user[:password]@[netloc]".
6442  */
6443  user = start;
6444 
6445  p = user;
6446  while (*p != ':' && *p != '@')
6447  ++p;
6448 
6449  /* Save last char and cut off at end of user name */
6450  prevchar = *p;
6451  *p = '\0';
6452 
6453  if (*user &&
6454  !conninfo_storeval(options, "user", user,
6455  errorMessage, false, true))
6456  goto cleanup;
6457 
6458  if (prevchar == ':')
6459  {
6460  const char *password = p + 1;
6461 
6462  while (*p != '@')
6463  ++p;
6464  *p = '\0';
6465 
6466  if (*password &&
6467  !conninfo_storeval(options, "password", password,
6468  errorMessage, false, true))
6469  goto cleanup;
6470  }
6471 
6472  /* Advance past end of parsed user name or password token */
6473  ++p;
6474  }
6475  else
6476  {
6477  /*
6478  * No username/password designator found. Reset to start of URI.
6479  */
6480  p = start;
6481  }
6482 
6483  /*
6484  * There may be multiple netloc[:port] pairs, each separated from the next
6485  * by a comma. When we initially enter this loop, "p" has been
6486  * incremented past optional URI credential information at this point and
6487  * now points at the "netloc" part of the URI. On subsequent loop
6488  * iterations, "p" has been incremented past the comma separator and now
6489  * points at the start of the next "netloc".
6490  */
6491  for (;;)
6492  {
6493  /*
6494  * Look for IPv6 address.
6495  */
6496  if (*p == '[')
6497  {
6498  host = ++p;
6499  while (*p && *p != ']')
6500  ++p;
6501  if (!*p)
6502  {
6503  libpq_append_error(errorMessage,
6504  "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"",
6505  uri);
6506  goto cleanup;
6507  }
6508  if (p == host)
6509  {
6510  libpq_append_error(errorMessage,
6511  "IPv6 host address may not be empty in URI: \"%s\"",
6512  uri);
6513  goto cleanup;
6514  }
6515 
6516  /* Cut off the bracket and advance */
6517  *(p++) = '\0';
6518 
6519  /*
6520  * The address may be followed by a port specifier or a slash or a
6521  * query or a separator comma.
6522  */
6523  if (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',')
6524  {
6525  libpq_append_error(errorMessage,
6526  "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"",
6527  *p, (int) (p - buf + 1), uri);
6528  goto cleanup;
6529  }
6530  }
6531  else
6532  {
6533  /* not an IPv6 address: DNS-named or IPv4 netloc */
6534  host = p;
6535 
6536  /*
6537  * Look for port specifier (colon) or end of host specifier
6538  * (slash) or query (question mark) or host separator (comma).
6539  */
6540  while (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',')
6541  ++p;
6542  }
6543 
6544  /* Save the hostname terminator before we null it */
6545  prevchar = *p;
6546  *p = '\0';
6547 
6548  appendPQExpBufferStr(&hostbuf, host);
6549 
6550  if (prevchar == ':')
6551  {
6552  const char *port = ++p; /* advance past host terminator */
6553 
6554  while (*p && *p != '/' && *p != '?' && *p != ',')
6555  ++p;
6556 
6557  prevchar = *p;
6558  *p = '\0';
6559 
6560  appendPQExpBufferStr(&portbuf, port);
6561  }
6562 
6563  if (prevchar != ',')
6564  break;
6565  ++p; /* advance past comma separator */
6566  appendPQExpBufferChar(&hostbuf, ',');
6567  appendPQExpBufferChar(&portbuf, ',');
6568  }
6569 
6570  /* Save final values for host and port. */
6571  if (PQExpBufferDataBroken(hostbuf) || PQExpBufferDataBroken(portbuf))
6572  goto cleanup;
6573  if (hostbuf.data[0] &&
6574  !conninfo_storeval(options, "host", hostbuf.data,
6575  errorMessage, false, true))
6576  goto cleanup;
6577  if (portbuf.data[0] &&
6578  !conninfo_storeval(options, "port", portbuf.data,
6579  errorMessage, false, true))
6580  goto cleanup;
6581 
6582  if (prevchar && prevchar != '?')
6583  {
6584  const char *dbname = ++p; /* advance past host terminator */
6585 
6586  /* Look for query parameters */
6587  while (*p && *p != '?')
6588  ++p;
6589 
6590  prevchar = *p;
6591  *p = '\0';
6592 
6593  /*
6594  * Avoid setting dbname to an empty string, as it forces the default
6595  * value (username) and ignores $PGDATABASE, as opposed to not setting
6596  * it at all.
6597  */
6598  if (*dbname &&
6599  !conninfo_storeval(options, "dbname", dbname,
6600  errorMessage, false, true))
6601  goto cleanup;
6602  }
6603 
6604  if (prevchar)
6605  {
6606  ++p; /* advance past terminator */
6607 
6608  if (!conninfo_uri_parse_params(p, options, errorMessage))
6609  goto cleanup;
6610  }
6611 
6612  /* everything parsed okay */
6613  retval = true;
6614 
6615 cleanup:
6616  termPQExpBuffer(&hostbuf);
6617  termPQExpBuffer(&portbuf);
6618  free(buf);
6619  return retval;
6620 }
static void cleanup(void)
Definition: bootstrap.c:681
static int uri_prefix_length(const char *connstr)
Definition: fe-connect.c:5834
static bool conninfo_uri_parse_params(char *params, PQconninfoOption *connOptions, PQExpBuffer errorMessage)
Definition: fe-connect.c:6631
return str start
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:54
char * dbname
Definition: streamutil.c:52

References appendPQExpBufferChar(), appendPQExpBufferStr(), buf, cleanup(), conninfo_storeval(), conninfo_uri_parse_params(), PQExpBufferData::data, dbname, free, initPQExpBuffer(), libpq_append_error(), password, port, PQExpBufferDataBroken, start, 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 6631 of file fe-connect.c.

6634 {
6635  while (*params)
6636  {
6637  char *keyword = params;
6638  char *value = NULL;
6639  char *p = params;
6640  bool malloced = false;
6641  int oldmsglen;
6642 
6643  /*
6644  * Scan the params string for '=' and '&', marking the end of keyword
6645  * and value respectively.
6646  */
6647  for (;;)
6648  {
6649  if (*p == '=')
6650  {
6651  /* Was there '=' already? */
6652  if (value != NULL)
6653  {
6654  libpq_append_error(errorMessage,
6655  "extra key/value separator \"=\" in URI query parameter: \"%s\"",
6656  keyword);
6657  return false;
6658  }
6659  /* Cut off keyword, advance to value */
6660  *p++ = '\0';
6661  value = p;
6662  }
6663  else if (*p == '&' || *p == '\0')
6664  {
6665  /*
6666  * If not at the end, cut off value and advance; leave p
6667  * pointing to start of the next parameter, if any.
6668  */
6669  if (*p != '\0')
6670  *p++ = '\0';
6671  /* Was there '=' at all? */
6672  if (value == NULL)
6673  {
6674  libpq_append_error(errorMessage,
6675  "missing key/value separator \"=\" in URI query parameter: \"%s\"",
6676  keyword);
6677  return false;
6678  }
6679  /* Got keyword and value, go process them. */
6680  break;
6681  }
6682  else
6683  ++p; /* Advance over all other bytes. */
6684  }
6685 
6686  keyword = conninfo_uri_decode(keyword, errorMessage);
6687  if (keyword == NULL)
6688  {
6689  /* conninfo_uri_decode already set an error message */
6690  return false;
6691  }
6692  value = conninfo_uri_decode(value, errorMessage);
6693  if (value == NULL)
6694  {
6695  /* conninfo_uri_decode already set an error message */
6696  free(keyword);
6697  return false;
6698  }
6699  malloced = true;
6700 
6701  /*
6702  * Special keyword handling for improved JDBC compatibility.
6703  */
6704  if (strcmp(keyword, "ssl") == 0 &&
6705  strcmp(value, "true") == 0)
6706  {
6707  free(keyword);
6708  free(value);
6709  malloced = false;
6710 
6711  keyword = "sslmode";
6712  value = "require";
6713  }
6714 
6715  /*
6716  * Store the value if the corresponding option exists; ignore
6717  * otherwise. At this point both keyword and value are not
6718  * URI-encoded.
6719  */
6720  oldmsglen = errorMessage->len;
6721  if (!conninfo_storeval(connOptions, keyword, value,
6722  errorMessage, true, false))
6723  {
6724  /* Insert generic message if conninfo_storeval didn't give one. */
6725  if (errorMessage->len == oldmsglen)
6726  libpq_append_error(errorMessage,
6727  "invalid URI query parameter: \"%s\"",
6728  keyword);
6729  /* And fail. */
6730  if (malloced)
6731  {
6732  free(keyword);
6733  free(value);
6734  }
6735  return false;
6736  }
6737 
6738  if (malloced)
6739  {
6740  free(keyword);
6741  free(value);
6742  }
6743 
6744  /* Proceed to next key=value pair, if any */
6745  params = p;
6746  }
6747 
6748  return true;
6749 }

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

1036 {
1037  int n;
1038 
1039  n = 1;
1040  for (; *input != '\0'; input++)
1041  {
1042  if (*input == ',')
1043  n++;
1044  }
1045 
1046  return n;
1047 }
FILE * input

References input.

Referenced by pqConnectOptions2().

◆ default_threadlock()

static void default_threadlock ( int  acquire)
static

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

7785 {
7786  static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
7787 
7788  if (acquire)
7789  {
7790  if (pthread_mutex_lock(&singlethread_lock))
7791  Assert(false);
7792  }
7793  else
7794  {
7795  if (pthread_mutex_unlock(&singlethread_lock))
7796  Assert(false);
7797  }
7798 }
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 7399 of file fe-connect.c.

7400 {
7401  (void) arg; /* not used */
7402  /* Note: we expect the supplied string to end with a newline already. */
7403  fprintf(stderr, "%s", message);
7404 }
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 7384 of file fe-connect.c.

7385 {
7386  (void) arg; /* not used */
7387  if (res->noticeHooks.noticeProc != NULL)
7390 }
char * PQresultErrorMessage(const PGresult *res)
Definition: fe-exec.c:3427
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 2094 of file fe-connect.c.

2095 {
2096  if (conn->raddr.addr.ss_family == AF_UNIX)
2097  {
2098  char service[NI_MAXHOST];
2099 
2101  NULL, 0,
2102  service, sizeof(service),
2103  NI_NUMERICSERV);
2105  libpq_gettext("connection to server on socket \"%s\" failed: "),
2106  service);
2107  }
2108  else
2109  {
2110  const char *displayed_host;
2111  const char *displayed_port;
2112 
2113  /* To which host and port were we actually connecting? */
2115  displayed_host = conn->connhost[conn->whichhost].hostaddr;
2116  else
2117  displayed_host = conn->connhost[conn->whichhost].host;
2118  displayed_port = conn->connhost[conn->whichhost].port;
2119  if (displayed_port == NULL || displayed_port[0] == '\0')
2120  displayed_port = DEF_PGPORT_STR;
2121 
2122  /*
2123  * If the user did not supply an IP address using 'hostaddr', and
2124  * 'host' was missing or does not match our lookup, display the
2125  * looked-up IP address.
2126  */
2128  host_addr[0] &&
2129  strcmp(displayed_host, host_addr) != 0)
2131  libpq_gettext("connection to server at \"%s\" (%s), port %s failed: "),
2132  displayed_host, host_addr,
2133  displayed_port);
2134  else
2136  libpq_gettext("connection to server at \"%s\", port %s failed: "),
2137  displayed_host,
2138  displayed_port);
2139  }
2140 }
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:905
@ CHT_HOST_ADDRESS
Definition: libpq-int.h:316
socklen_t salen
Definition: pqcomm.h:33
char * host
Definition: libpq-int.h:364
char * port
Definition: libpq-int.h:366
char * hostaddr
Definition: libpq-int.h:365
pg_conn_host_type type
Definition: libpq-int.h:363
int whichhost
Definition: libpq-int.h:467
pg_conn_host * connhost
Definition: libpq-int.h:468

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

920 {
922 
923  for (option = PQconninfoOptions; option->keyword; option++)
924  {
925  if (option->connofs >= 0)
926  {
927  const char *tmp = conninfo_getval(connOptions, option->keyword);
928 
929  if (tmp)
930  {
931  char **connmember = (char **) ((char *) conn + option->connofs);
932 
933  free(*connmember);
934  *connmember = strdup(tmp);
935  if (*connmember == NULL)
936  {
937  libpq_append_conn_error(conn, "out of memory");
938  return false;
939  }
940  }
941  }
942  }
943 
944  return true;
945 }
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6853

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

4650 {
4651  /* let any event procs clean up their state data */
4652  for (int i = 0; i < conn->nEvents; i++)
4653  {
4654  PGEventConnDestroy evt;
4655 
4656  evt.conn = conn;
4657  (void) conn->events[i].proc(PGEVT_CONNDESTROY, &evt,
4658  conn->events[i].passThrough);
4659  free(conn->events[i].name);
4660  }
4661 
4664 
4666  free(conn->events);
4667  free(conn->pghost);
4668  free(conn->pghostaddr);
4669  free(conn->pgport);
4672  free(conn->pgoptions);
4673  free(conn->appname);
4674  free(conn->fbappname);
4675  free(conn->dbName);
4676  free(conn->replication);
4677  free(conn->pguser);
4678  if (conn->pgpass)
4679  {
4680  explicit_bzero(conn->pgpass, strlen(conn->pgpass));
4681  free(conn->pgpass);
4682  }
4683  free(conn->pgpassfile);
4685  free(conn->keepalives);
4689  free(conn->sslmode);
4691  free(conn->sslcert);
4692  free(conn->sslkey);
4693  if (conn->sslpassword)
4694  {
4696  free(conn->sslpassword);
4697  }
4698  free(conn->sslcertmode);
4699  free(conn->sslrootcert);
4700  free(conn->sslcrl);
4701  free(conn->sslcrldir);
4703  free(conn->sslsni);
4704  free(conn->requirepeer);
4708  free(conn->gssencmode);
4709  free(conn->krbsrvname);
4710  free(conn->gsslib);
4712  free(conn->connip);
4713  /* Note that conn->Pfdebug is not ours to close or free */
4715  free(conn->inBuffer);
4716  free(conn->outBuffer);
4717  free(conn->rowBuf);
4722 
4723  free(conn);
4724 }
static void release_conn_addrinfo(PGconn *conn)
Definition: fe-connect.c:4799
void pqReleaseConnHosts(PGconn *conn)
Definition: fe-connect.c:4731
@ 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:396
char * write_err_msg
Definition: libpq-int.h:497
char * sslrootcert
Definition: libpq-int.h:415
PGdataValue * rowBuf
Definition: libpq-int.h:553
char * sslnegotiation
Definition: libpq-int.h:409
char * sslcompression
Definition: libpq-int.h:410
char * require_auth
Definition: libpq-int.h:428
char * inBuffer
Definition: libpq-int.h:536
char * channel_binding
Definition: libpq-int.h:400
char * sslcrldir
Definition: libpq-int.h:417
char * gssdelegation
Definition: libpq-int.h:424
char * pgoptions
Definition: libpq-int.h:392
char * sslcrl
Definition: libpq-int.h:416
char * pghost
Definition: libpq-int.h:379
char * ssl_max_protocol_version
Definition: libpq-int.h:426
char * pgpass
Definition: libpq-int.h:398
char * dbName
Definition: libpq-int.h:395
char * fbappname
Definition: libpq-int.h:394
char * sslcert
Definition: libpq-int.h:412
char * sslcertmode
Definition: libpq-int.h:414
char * target_session_attrs
Definition: libpq-int.h:427
char * sslpassword
Definition: libpq-int.h:413
PQExpBufferData workBuffer
Definition: libpq-int.h:646
char * keepalives_idle
Definition: libpq-int.h:403
char * connip
Definition: libpq-int.h:469
char * load_balance_hosts
Definition: libpq-int.h:429
char * pguser
Definition: libpq-int.h:397
char * keepalives
Definition: libpq-int.h:402
char * client_encoding_initial
Definition: libpq-int.h:391
char * keepalives_interval
Definition: libpq-int.h:404
char * appname
Definition: libpq-int.h:393
char * sslmode
Definition: libpq-int.h:408
char * pgtcp_user_timeout
Definition: libpq-int.h:390
char * ssl_min_protocol_version
Definition: libpq-int.h:425
char * gssencmode
Definition: libpq-int.h:420
int nEvents
Definition: libpq-int.h:444
char * pghostaddr
Definition: libpq-int.h:383
char * sslkey
Definition: libpq-int.h:411
char * pgpassfile
Definition: libpq-int.h:399
char * connect_timeout
Definition: libpq-int.h:389
char * krbsrvname
Definition: libpq-int.h:421
char * gsslib
Definition: libpq-int.h:422
char * pgport
Definition: libpq-int.h:387
char * keepalives_count
Definition: libpq-int.h:406
char * requirepeer
Definition: libpq-int.h:419
char * sslsni
Definition: libpq-int.h:418
PGEvent * events
Definition: libpq-int.h:443
char * outBuffer
Definition: libpq-int.h:543

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, release_conn_addrinfo(), 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::sslnegotiation, 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 6832 of file fe-connect.c.

6833 {
6834  if ('0' <= digit && digit <= '9')
6835  *value = digit - '0';
6836  else if ('A' <= digit && digit <= 'F')
6837  *value = digit - 'A' + 10;
6838  else if ('a' <= digit && digit <= 'f')
6839  *value = digit - 'a' + 10;
6840  else
6841  return false;
6842 
6843  return true;
6844 }

References value.

Referenced by conninfo_uri_decode().

◆ getHostaddr()

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

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

2062 {
2063  struct sockaddr_storage *addr = &conn->raddr.addr;
2064 
2065  if (addr->ss_family == AF_INET)
2066  {
2067  if (pg_inet_net_ntop(AF_INET,
2068  &((struct sockaddr_in *) addr)->sin_addr.s_addr,
2069  32,
2070  host_addr, host_addr_len) == NULL)
2071  host_addr[0] = '\0';
2072  }
2073  else if (addr->ss_family == AF_INET6)
2074  {
2075  if (pg_inet_net_ntop(AF_INET6,
2076  &((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr,
2077  128,
2078  host_addr, host_addr_len) == NULL)
2079  host_addr[0] = '\0';
2080  }
2081  else
2082  host_addr[0] = '\0';
2083 }
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().

◆ init_allowed_encryption_methods()

static bool init_allowed_encryption_methods ( PGconn conn)
static

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

4307 {
4308  if (conn->raddr.addr.ss_family == AF_UNIX)
4309  {
4310  /* Don't request SSL or GSSAPI over Unix sockets */
4312 
4313  /*
4314  * XXX: we probably should not do this. sslmode=require works
4315  * differently
4316  */
4317  if (conn->gssencmode[0] == 'r')
4318  {
4320  "GSSAPI encryption required but it is not supported over a local socket");
4323  return false;
4324  }
4325 
4328  return true;
4329  }
4330 
4331  /* initialize based on sslmode and gssencmode */
4333 
4334 #ifdef USE_SSL
4335  /* sslmode anything but 'disable', and GSSAPI not required */
4336  if (conn->sslmode[0] != 'd' && conn->gssencmode[0] != 'r')
4337  {
4339  }
4340 #endif
4341 
4342 #ifdef ENABLE_GSS
4343  if (conn->gssencmode[0] != 'd')
4345 #endif
4346 
4347  if ((conn->sslmode[0] == 'd' || conn->sslmode[0] == 'p' || conn->sslmode[0] == 'a') &&
4348  (conn->gssencmode[0] == 'd' || conn->gssencmode[0] == 'p'))
4349  {
4351  }
4352 
4353  return select_next_encryption_method(conn, false);
4354 }
#define ENC_PLAINTEXT
Definition: libpq-int.h:236
#define ENC_GSSAPI
Definition: libpq-int.h:237
#define ENC_SSL
Definition: libpq-int.h:238
#define ENC_ERROR
Definition: libpq-int.h:235
uint8 allowed_enc_methods
Definition: libpq-int.h:575

References SockAddr::addr, pg_conn::allowed_enc_methods, conn, pg_conn::current_enc_method, ENC_ERROR, ENC_GSSAPI, ENC_PLAINTEXT, ENC_SSL, pg_conn::gssencmode, libpq_append_conn_error(), pg_conn::raddr, select_next_encryption_method(), and pg_conn::sslmode.

Referenced by PQconnectPoll().

◆ internal_ping()

static PGPing internal_ping ( PGconn conn)
static

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

4487 {
4488  /* Say "no attempt" if we never got to PQconnectPoll */
4489  if (!conn || !conn->options_valid)
4490  return PQPING_NO_ATTEMPT;
4491 
4492  /* Attempt to complete the connection */
4493  if (conn->status != CONNECTION_BAD)
4494  (void) pqConnectDBComplete(conn);
4495 
4496  /* Definitely OK if we succeeded */
4497  if (conn->status != CONNECTION_BAD)
4498  return PQPING_OK;
4499 
4500  /*
4501  * Here begins the interesting part of "ping": determine the cause of the
4502  * failure in sufficient detail to decide what to return. We do not want
4503  * to report that the server is not up just because we didn't have a valid
4504  * password, for example. In fact, any sort of authentication request
4505  * implies the server is up. (We need this check since the libpq side of
4506  * things might have pulled the plug on the connection before getting an
4507  * error as such from the postmaster.)
4508  */
4509  if (conn->auth_req_received)
4510  return PQPING_OK;
4511 
4512  /*
4513  * If we failed to get any ERROR response from the postmaster, report
4514  * PQPING_NO_RESPONSE. This result could be somewhat misleading for a
4515  * pre-7.4 server, since it won't send back a SQLSTATE, but those are long
4516  * out of support. Another corner case where the server could return a
4517  * failure without a SQLSTATE is fork failure, but PQPING_NO_RESPONSE
4518  * isn't totally unreasonable for that anyway. We expect that every other
4519  * failure case in a modern server will produce a report with a SQLSTATE.
4520  *
4521  * NOTE: whenever we get around to making libpq generate SQLSTATEs for
4522  * client-side errors, we should either not store those into
4523  * last_sqlstate, or add an extra flag so we can tell client-side errors
4524  * apart from server-side ones.
4525  */
4526  if (strlen(conn->last_sqlstate) != 5)
4527  return PQPING_NO_RESPONSE;
4528 
4529  /*
4530  * Report PQPING_REJECT if server says it's not accepting connections.
4531  */
4532  if (strcmp(conn->last_sqlstate, ERRCODE_CANNOT_CONNECT_NOW) == 0)
4533  return PQPING_REJECT;
4534 
4535  /*
4536  * Any other SQLSTATE can be taken to indicate that the server is up.
4537  * Presumably it didn't like our username, password, or database name; or
4538  * perhaps it had some transient failure, but that should not be taken as
4539  * meaning "it's down".
4540  */
4541  return PQPING_OK;
4542 }
#define ERRCODE_CANNOT_CONNECT_NOW
Definition: fe-connect.c:92
int pqConnectDBComplete(PGconn *conn)
Definition: fe-connect.c:2471
@ PQPING_OK
Definition: libpq-fe.h:171
@ PQPING_REJECT
Definition: libpq-fe.h:172
@ PQPING_NO_RESPONSE
Definition: libpq-fe.h:173
@ PQPING_NO_ATTEMPT
Definition: libpq-fe.h:174
bool auth_req_received
Definition: libpq-int.h:491
char last_sqlstate[6]
Definition: libpq-int.h:451
bool options_valid
Definition: libpq-int.h:452

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

1095 {
1096  uint64 rseed;
1097  struct timeval tval = {0};
1098 
1100  return;
1101 
1102  gettimeofday(&tval, NULL);
1103 
1104  rseed = ((uintptr_t) conn) ^
1105  ((uint64) getpid()) ^
1106  ((uint64) tval.tv_usec) ^
1107  ((uint64) tval.tv_sec);
1108 
1109  pg_prng_seed(&conn->prng_state, rseed);
1110 }
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:532
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 1059 of file fe-connect.c.

1060 {
1061  char *p;
1062  char *s = *startptr;
1063  char *e;
1064  int len;
1065 
1066  /*
1067  * Search for the end of the current element; a comma or end-of-string
1068  * acts as a terminator.
1069  */
1070  e = s;
1071  while (*e != '\0' && *e != ',')
1072  ++e;
1073  *more = (*e == ',');
1074 
1075  len = e - s;
1076  p = (char *) malloc(sizeof(char) * (len + 1));
1077  if (p)
1078  {
1079  memcpy(p, s, len);
1080  p[len] = '\0';
1081  }
1082  *startptr = e + 1;
1083 
1084  return p;
1085 }
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 5814 of file fe-connect.c.

5816 {
5817  /* Parse as URI if connection string matches URI prefix */
5818  if (uri_prefix_length(connstr) != 0)
5819  return conninfo_uri_parse(connstr, errorMessage, use_defaults);
5820 
5821  /* Parse as default otherwise */
5822  return conninfo_parse(connstr, errorMessage, use_defaults);
5823 }
static PQconninfoOption * conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:6337
static PQconninfoOption * conninfo_parse(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5868
static char * connstr
Definition: pg_dumpall.c:88

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

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

◆ parseServiceFile()

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

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

5580 {
5581  int result = 0,
5582  linenr = 0,
5583  i;
5584  FILE *f;
5585  char *line;
5586  char buf[1024];
5587 
5588  *group_found = false;
5589 
5590  f = fopen(serviceFile, "r");
5591  if (f == NULL)
5592  {
5593  libpq_append_error(errorMessage, "service file \"%s\" not found", serviceFile);
5594  return 1;
5595  }
5596 
5597  while ((line = fgets(buf, sizeof(buf), f)) != NULL)
5598  {
5599  int len;
5600 
5601  linenr++;
5602 
5603  if (strlen(line) >= sizeof(buf) - 1)
5604  {
5605  libpq_append_error(errorMessage,
5606  "line %d too long in service file \"%s\"",
5607  linenr,
5608  serviceFile);
5609  result = 2;
5610  goto exit;
5611  }
5612 
5613  /* ignore whitespace at end of line, especially the newline */
5614  len = strlen(line);
5615  while (len > 0 && isspace((unsigned char) line[len - 1]))
5616  line[--len] = '\0';
5617 
5618  /* ignore leading whitespace too */
5619  while (*line && isspace((unsigned char) line[0]))
5620  line++;
5621 
5622  /* ignore comments and empty lines */
5623  if (line[0] == '\0' || line[0] == '#')
5624  continue;
5625 
5626  /* Check for right groupname */
5627  if (line[0] == '[')
5628  {
5629  if (*group_found)
5630  {
5631  /* end of desired group reached; return success */
5632  goto exit;
5633  }
5634 
5635  if (strncmp(line + 1, service, strlen(service)) == 0 &&
5636  line[strlen(service) + 1] == ']')
5637  *group_found = true;
5638  else
5639  *group_found = false;
5640  }
5641  else
5642  {
5643  if (*group_found)
5644  {
5645  /*
5646  * Finally, we are in the right group and can parse the line
5647  */
5648  char *key,
5649  *val;
5650  bool found_keyword;
5651 
5652 #ifdef USE_LDAP
5653  if (strncmp(line, "ldap", 4) == 0)
5654  {
5655  int rc = ldapServiceLookup(line, options, errorMessage);
5656 
5657  /* if rc = 2, go on reading for fallback */
5658  switch (rc)
5659  {
5660  case 0:
5661  goto exit;
5662  case 1:
5663  case 3:
5664  result = 3;
5665  goto exit;
5666  case 2:
5667  continue;
5668  }
5669  }
5670 #endif
5671 
5672  key = line;
5673  val = strchr(line, '=');
5674  if (val == NULL)
5675  {
5676  libpq_append_error(errorMessage,
5677  "syntax error in service file \"%s\", line %d",
5678  serviceFile,
5679  linenr);
5680  result = 3;
5681  goto exit;
5682  }
5683  *val++ = '\0';
5684 
5685  if (strcmp(key, "service") == 0)
5686  {
5687  libpq_append_error(errorMessage,
5688  "nested service specifications not supported in service file \"%s\", line %d",
5689  serviceFile,
5690  linenr);
5691  result = 3;
5692  goto exit;
5693  }
5694 
5695  /*
5696  * Set the parameter --- but don't override any previous
5697  * explicit setting.
5698  */
5699  found_keyword = false;
5700  for (i = 0; options[i].keyword; i++)
5701  {
5702  if (strcmp(options[i].keyword, key) == 0)
5703  {
5704  if (options[i].val == NULL)
5705  options[i].val = strdup(val);
5706  if (!options[i].val)
5707  {
5708  libpq_append_error(errorMessage, "out of memory");
5709  result = 3;
5710  goto exit;
5711  }
5712  found_keyword = true;
5713  break;
5714  }
5715  }
5716 
5717  if (!found_keyword)
5718  {
5719  libpq_append_error(errorMessage,
5720  "syntax error in service file \"%s\", line %d",
5721  serviceFile,
5722  linenr);
5723  result = 3;
5724  goto exit;
5725  }
5726  }
5727  }
5728  }
5729 
5730 exit:
5731  fclose(f);
5732 
5733  return result;
5734 }
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 5507 of file fe-connect.c.

5508 {
5509  const char *service = conninfo_getval(options, "service");
5510  char serviceFile[MAXPGPATH];
5511  char *env;
5512  bool group_found = false;
5513  int status;
5514  struct stat stat_buf;
5515 
5516  /*
5517  * We have to special-case the environment variable PGSERVICE here, since
5518  * this is and should be called before inserting environment defaults for
5519  * other connection options.
5520  */
5521  if (service == NULL)
5522  service = getenv("PGSERVICE");
5523 
5524  /* If no service name given, nothing to do */
5525  if (service == NULL)
5526  return 0;
5527 
5528  /*
5529  * Try PGSERVICEFILE if specified, else try ~/.pg_service.conf (if that
5530  * exists).
5531  */
5532  if ((env = getenv("PGSERVICEFILE")) != NULL)
5533  strlcpy(serviceFile, env, sizeof(serviceFile));
5534  else
5535  {
5536  char homedir[MAXPGPATH];
5537 
5538  if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
5539  goto next_file;
5540  snprintf(serviceFile, MAXPGPATH, "%s/%s", homedir, ".pg_service.conf");
5541  if (stat(serviceFile, &stat_buf) != 0)
5542  goto next_file;
5543  }
5544 
5545  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
5546  if (group_found || status != 0)
5547  return status;
5548 
5549 next_file:
5550 
5551  /*
5552  * This could be used by any application so we can't use the binary
5553  * location to find our config files.
5554  */
5555  snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf",
5556  getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);
5557  if (stat(serviceFile, &stat_buf) != 0)
5558  goto last_file;
5559 
5560  status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
5561  if (status != 0)
5562  return status;
5563 
5564 last_file:
5565  if (!group_found)
5566  {
5567  libpq_append_error(errorMessage, "definition of service \"%s\" not found", service);
5568  return 3;
5569  }
5570 
5571  return 0;
5572 }
static int parseServiceFile(const char *serviceFile, const char *service, PQconninfoOption *options, PQExpBuffer errorMessage, bool *group_found)
Definition: fe-connect.c:5575
bool pqGetHomeDirectory(char *buf, int bufsize)
Definition: fe-connect.c:7692
#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 7448 of file fe-connect.c.

7450 {
7451  FILE *fp;
7452 #ifndef WIN32
7453  struct stat stat_buf;
7454 #endif
7456 
7457  if (dbname == NULL || dbname[0] == '\0')
7458  return NULL;
7459 
7460  if (username == NULL || username[0] == '\0')
7461  return NULL;
7462 
7463  /* 'localhost' matches pghost of '' or the default socket directory */
7464  if (hostname == NULL || hostname[0] == '\0')
7466  else if (is_unixsock_path(hostname))
7467 
7468  /*
7469  * We should probably use canonicalize_path(), but then we have to
7470  * bring path.c into libpq, and it doesn't seem worth it.
7471  */
7472  if (strcmp(hostname, DEFAULT_PGSOCKET_DIR) == 0)
7474 
7475  if (port == NULL || port[0] == '\0')
7476  port = DEF_PGPORT_STR;
7477 
7478  /* If password file cannot be opened, ignore it. */
7479  fp = fopen(pgpassfile, "r");
7480  if (fp == NULL)
7481  return NULL;
7482 
7483 #ifndef WIN32
7484  if (fstat(fileno(fp), &stat_buf) != 0)
7485  return NULL;
7486 
7487  if (!S_ISREG(stat_buf.st_mode))
7488  {
7489  fprintf(stderr,
7490  libpq_gettext("WARNING: password file \"%s\" is not a plain file\n"),
7491  pgpassfile);
7492  return NULL;
7493  }
7494 
7495  /* If password file is insecure, alert the user and ignore it. */
7496  if (stat_buf.st_mode & (S_IRWXG | S_IRWXO))
7497  {
7498  fprintf(stderr,
7499  libpq_gettext("WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
7500  pgpassfile);
7501  return NULL;
7502  }
7503 #else
7504 
7505  /*
7506  * On Win32, the directory is protected, so we don't have to check the
7507  * file.
7508  */
7509 #endif
7510 
7511  /* Use an expansible buffer to accommodate any reasonable line length */
7512  initPQExpBuffer(&buf);
7513 
7514  while (!feof(fp) && !ferror(fp))
7515  {
7516  /* Make sure there's a reasonable amount of room in the buffer */
7517  if (!enlargePQExpBuffer(&buf, 128))
7518  break;
7519 
7520  /* Read some data, appending it to what we already have */
7521  if (fgets(buf.data + buf.len, buf.maxlen - buf.len, fp) == NULL)
7522  break;
7523  buf.len += strlen(buf.data + buf.len);
7524 
7525  /* If we don't yet have a whole line, loop around to read more */
7526  if (!(buf.len > 0 && buf.data[buf.len - 1] == '\n') && !feof(fp))
7527  continue;
7528 
7529  /* ignore comments */
7530  if (buf.data[0] != '#')
7531  {
7532  char *t = buf.data;
7533  int len;
7534 
7535  /* strip trailing newline and carriage return */
7536  len = pg_strip_crlf(t);
7537 
7538  if (len > 0 &&
7539  (t = pwdfMatchesString(t, hostname)) != NULL &&
7540  (t = pwdfMatchesString(t, port)) != NULL &&
7541  (t = pwdfMatchesString(t, dbname)) != NULL &&
7542  (t = pwdfMatchesString(t, username)) != NULL)
7543  {
7544  /* Found a match. */
7545  char *ret,
7546  *p1,
7547  *p2;
7548 
7549  ret = strdup(t);
7550 
7551  fclose(fp);
7552  explicit_bzero(buf.data, buf.maxlen);
7553  termPQExpBuffer(&buf);
7554 
7555  if (!ret)
7556  {
7557  /* Out of memory. XXX: an error message would be nice. */
7558  return NULL;
7559  }
7560 
7561  /* De-escape password. */
7562  for (p1 = p2 = ret; *p1 != ':' && *p1 != '\0'; ++p1, ++p2)
7563  {
7564  if (*p1 == '\\' && p1[1] != '\0')
7565  ++p1;
7566  *p2 = *p1;
7567  }
7568  *p2 = '\0';
7569 
7570  return ret;
7571  }
7572  }
7573 
7574  /* No match, reset buffer to prepare for next line. */
7575  buf.len = 0;
7576  }
7577 
7578  fclose(fp);
7579  explicit_bzero(buf.data, buf.maxlen);
7580  termPQExpBuffer(&buf);
7581  return NULL;
7582 }
#define DefaultHost
Definition: fe-connect.c:117
static char * pwdfMatchesString(char *buf, const char *token)
Definition: fe-connect.c:7411
static char * username
Definition: initdb.c:153
#define DEFAULT_PGSOCKET_DIR
static char * hostname
Definition: pg_regress.c:115
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 fstat
Definition: win32_port.h:283
#define S_ISREG(m)
Definition: win32_port.h:328

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

Referenced by pqConnectOptions2().

◆ pgpassfileWarning()

static void pgpassfileWarning ( PGconn conn)
static

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

7591 {
7592  /* If it was 'invalid authorization', add pgpassfile mention */
7593  /* only works with >= 9.0 servers */
7594  if (conn->password_needed &&
7595  conn->connhost[conn->whichhost].password != NULL &&
7596  conn->result)
7597  {
7598  const char *sqlstate = PQresultErrorField(conn->result,
7600 
7601  if (sqlstate && strcmp(sqlstate, ERRCODE_INVALID_PASSWORD) == 0)
7602  libpq_append_conn_error(conn, "password retrieved from file \"%s\"",
7603  conn->pgpassfile);
7604  }
7605 }
#define ERRCODE_INVALID_PASSWORD
Definition: fe-connect.c:90
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:3466
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:56
char * password
Definition: libpq-int.h:367
PGresult * result
Definition: libpq-int.h:566
bool password_needed
Definition: libpq-int.h:492

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

7217 {
7218  if (!conn || conn->status != CONNECTION_OK)
7219  return 0;
7220  return conn->be_pid;
7221 }
@ CONNECTION_OK
Definition: libpq-fe.h:81
int be_pid
Definition: libpq-int.h:522

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

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

◆ PQclientEncoding()

int PQclientEncoding ( const PGconn conn)

◆ pqClosePGconn()

void pqClosePGconn ( PGconn conn)

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

4848 {
4849  /*
4850  * If possible, send Terminate message to close the connection politely.
4851  */
4853 
4854  /*
4855  * Must reset the blocking status so a possible reconnect will work.
4856  *
4857  * Don't call PQsetnonblocking() because it will fail if it's unable to
4858  * flush the connection.
4859  */
4860  conn->nonblocking = false;
4861 
4862  /*
4863  * Close the connection, reset all transient state, flush I/O buffers.
4864  * Note that this includes clearing conn's error state; we're no longer
4865  * interested in any failures associated with the old connection, and we
4866  * want a clean slate for any new connection attempt.
4867  */
4868  pqDropConnection(conn, true);
4869  conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
4873  pqClearAsyncResult(conn); /* deallocate result */
4875 
4876  /*
4877  * Release addrinfo, but since cancel requests never change their addrinfo
4878  * we don't do that. Otherwise we would have to rebuild it during a
4879  * PQcancelReset.
4880  */
4881  if (!conn->cancelRequest)
4883 
4884  /* Reset all state obtained from server, too */
4886 }
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:472
static void sendTerminateConn(PGconn *conn)
Definition: fe-connect.c:4813
static void pqDropServerData(PGconn *conn)
Definition: fe-connect.c:585
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:779
@ PQTRANS_IDLE
Definition: libpq-fe.h:142
@ PQ_PIPELINE_OFF
Definition: libpq-fe.h:182
@ PGASYNC_IDLE
Definition: libpq-int.h:221
#define pqClearConnErrorState(conn)
Definition: libpq-int.h:878
PGTransactionStatusType xactStatus
Definition: libpq-int.h:450
bool cancelRequest
Definition: libpq-int.h:431
bool nonblocking
Definition: libpq-int.h:453
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:449
PGpipelineStatus pipelineStatus
Definition: libpq-int.h:455

References pg_conn::asyncStatus, pg_conn::cancelRequest, 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 PQcancelReset(), PQfinish(), PQreset(), and PQresetStart().

◆ PQconndefaults()

PQconninfoOption* PQconndefaults ( void  )

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

1883 {
1884  PQExpBufferData errorBuf;
1885  PQconninfoOption *connOptions;
1886 
1887  /* We don't actually report any errors here, but callees want a buffer */
1888  initPQExpBuffer(&errorBuf);
1889  if (PQExpBufferDataBroken(errorBuf))
1890  return NULL; /* out of memory already :-( */
1891 
1892  connOptions = conninfo_init(&errorBuf);
1893  if (connOptions != NULL)
1894  {
1895  /* pass NULL errorBuf to ignore errors */
1896  if (!conninfo_add_defaults(connOptions, NULL))
1897  {
1898  PQconninfoFree(connOptions);
1899  connOptions = NULL;
1900  }
1901  }
1902 
1903  termPQExpBuffer(&errorBuf);
1904  return connOptions;
1905 }

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

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

◆ PQconnectdb()

PGconn* PQconnectdb ( const char *  conninfo)

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

746 {
747  PGconn *conn = PQconnectStart(conninfo);
748 
749  if (conn && conn->status != CONNECTION_BAD)
750  (void) pqConnectDBComplete(conn);
751 
752  return conn;
753 }
PGconn * PQconnectStart(const char *conninfo)
Definition: fe-connect.c:873

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

Referenced by connect_database(), get_db_conn(), and main().

◆ pqConnectDBComplete()

int pqConnectDBComplete ( PGconn conn)

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

2472 {
2474  pg_usec_time_t end_time = -1;
2475  int timeout = 0;
2476  int last_whichhost = -2; /* certainly different from whichhost */
2477  int last_whichaddr = -2; /* certainly different from whichaddr */
2478 
2479  if (conn == NULL || conn->status == CONNECTION_BAD)
2480  return 0;
2481 
2482  /*
2483  * Set up a time limit, if connect_timeout is greater than zero.
2484  */
2485  if (conn->connect_timeout != NULL)
2486  {
2487  if (!pqParseIntParam(conn->connect_timeout, &timeout, conn,
2488  "connect_timeout"))
2489  {
2490  /* mark the connection as bad to report the parsing failure */
2492  return 0;
2493  }
2494  }
2495 
2496  for (;;)
2497  {
2498  int ret = 0;
2499 
2500  /*
2501  * (Re)start the connect_timeout timer if it's active and we are
2502  * considering a different host than we were last time through. If
2503  * we've already succeeded, though, needn't recalculate.
2504  */
2505  if (flag != PGRES_POLLING_OK &&
2506  timeout > 0 &&
2507  (conn->whichhost != last_whichhost ||
2508  conn->whichaddr != last_whichaddr))
2509  {
2510  end_time = PQgetCurrentTimeUSec() + (pg_usec_time_t) timeout * 1000000;
2511  last_whichhost = conn->whichhost;
2512  last_whichaddr = conn->whichaddr;
2513  }
2514 
2515  /*
2516  * Wait, if necessary. Note that the initial state (just after
2517  * PQconnectStart) is to wait for the socket to select for writing.
2518  */
2519  switch (flag)
2520  {
2521  case PGRES_POLLING_OK:
2522  return 1; /* success! */
2523 
2524  case PGRES_POLLING_READING:
2525  ret = pqWaitTimed(1, 0, conn, end_time);
2526  if (ret == -1)
2527  {
2528  /* hard failure, eg select() problem, aborts everything */
2530  return 0;
2531  }
2532  break;
2533 
2534  case PGRES_POLLING_WRITING:
2535  ret = pqWaitTimed(0, 1, conn, end_time);
2536  if (ret == -1)
2537  {
2538  /* hard failure, eg select() problem, aborts everything */
2540  return 0;
2541  }
2542  break;
2543 
2544  default:
2545  /* Just in case we failed to set it in PQconnectPoll */
2547  return 0;
2548  }
2549 
2550  if (ret == 1) /* connect_timeout elapsed */
2551  {
2552  /*
2553  * Give up on current server/address, try the next one.
2554  */
2555  conn->try_next_addr = true;
2557  }
2558 
2559  /*
2560  * Now try to advance the state machine.
2561  */
2562  if (conn->cancelRequest)
2564  else
2565  flag = PQconnectPoll(conn);
2566  }
2567 }
PostgresPollingStatusType PQcancelPoll(PGcancelConn *cancelConn)
Definition: fe-cancel.c:207
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
Definition: fe-connect.c:2597
bool pqParseIntParam(const char *value, int *result, PGconn *conn, const char *context)
Definition: fe-connect.c:7733
pg_usec_time_t PQgetCurrentTimeUSec(void)
Definition: fe-misc.c:1200
int pqWaitTimed(int forRead, int forWrite, PGconn *conn, pg_usec_time_t end_time)
Definition: fe-misc.c:1009
@ CONNECTION_NEEDED
Definition: libpq-fe.h:97
PostgresPollingStatusType
Definition: libpq-fe.h:109
@ PGRES_POLLING_OK
Definition: libpq-fe.h:113
@ PGRES_POLLING_READING
Definition: libpq-fe.h:111
pg_int64 pg_usec_time_t
Definition: libpq-fe.h:226
static int64 end_time
Definition: pgbench.c:175
int whichaddr
Definition: libpq-int.h:516
bool try_next_addr
Definition: libpq-int.h:513
char * flag(int b)
Definition: test-ctype.c:33

References pg_conn::cancelRequest, conn, pg_conn::connect_timeout, CONNECTION_BAD, CONNECTION_NEEDED, end_time, flag(), PGRES_POLLING_OK, PGRES_POLLING_READING, PGRES_POLLING_WRITING, PQcancelPoll(), PQconnectPoll(), PQgetCurrentTimeUSec(), pqParseIntParam(), pqWaitTimed(), pg_conn::status, pg_conn::try_next_addr, pg_conn::whichaddr, and pg_conn::whichhost.

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

◆ PQconnectdbParams()

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

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

693 {
694  PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname);
695 
696  if (conn && conn->status != CONNECTION_BAD)
697  (void) pqConnectDBComplete(conn);
698 
699  return conn;
700 }
PGconn * PQconnectStartParams(const char *const *keywords, const char *const *values, int expand_dbname)
Definition: fe-connect.c:792

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

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

◆ pqConnectDBStart()

int pqConnectDBStart ( PGconn conn)

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

2394 {
2395  if (!conn)
2396  return 0;
2397 
2398  if (!conn->options_valid)
2399  goto connect_errReturn;
2400 
2401  /*
2402  * Check for bad linking to backend-internal versions of src/common
2403  * functions (see comments in link-canary.c for the reason we need this).
2404  * Nobody but developers should see this message, so we don't bother
2405  * translating it.
2406  */
2408  {
2410  "libpq is incorrectly linked to backend functions\n");
2411  goto connect_errReturn;
2412  }
2413 
2414  /* Ensure our buffers are empty */
2415  conn->inStart = conn->inCursor = conn->inEnd = 0;
2416  conn->outCount = 0;
2417 
2418  /*
2419  * Set up to try to connect to the first host. (Setting whichhost = -1 is
2420  * a bit of a cheat, but PQconnectPoll will advance it to 0 before
2421  * anything else looks at it.)
2422  *
2423  * Cancel requests are special though, they should only try one host and
2424  * address, and these fields have already been set up in PQcancelCreate,
2425  * so leave these fields alone for cancel requests.
2426  */
2427  if (!conn->cancelRequest)
2428  {
2429  conn->whichhost = -1;
2430  conn->try_next_host = true;
2431  conn->try_next_addr = false;
2432  }
2433 
2435 
2436  /* Also reset the target_server_type state if needed */
2439 
2440  /*
2441  * The code for processing CONNECTION_NEEDED state is in PQconnectPoll(),
2442  * so that it can easily be re-executed if needed again during the
2443  * asynchronous startup process. However, we must run it once here,
2444  * because callers expect a success return from this routine to mean that
2445  * we are in PGRES_POLLING_WRITING connection state.
2446  */
2448  return 1;
2449 
2450 connect_errReturn:
2451 
2452  /*
2453  * If we managed to open a socket, close it immediately rather than
2454  * waiting till PQfinish. (The application cannot have gotten the socket
2455  * from PQsocket yet, so this doesn't risk breaking anything.)
2456  */
2457  pqDropConnection(conn, true);
2459  return 0;
2460 }
@ SERVER_TYPE_PREFER_STANDBY_PASS2
Definition: libpq-int.h:249
@ SERVER_TYPE_PREFER_STANDBY
Definition: libpq-int.h:248
bool try_next_host
Definition: libpq-int.h:514
int inCursor
Definition: libpq-int.h:539
int inEnd
Definition: libpq-int.h:540
int inStart
Definition: libpq-int.h:538
PGTargetServerType target_server_type
Definition: libpq-int.h:510
int outCount
Definition: libpq-int.h:545

References appendPQExpBufferStr(), pg_conn::cancelRequest, 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 PQcancelStart(), PQconnectStart(), PQconnectStartParams(), PQreset(), PQresetStart(), and PQsetdbLogin().

◆ PQconnectionNeedsPassword()

int PQconnectionNeedsPassword ( const PGconn conn)

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

7234 {
7235  char *password;
7236 
7237  if (!conn)
7238  return false;
7239  password = PQpass(conn);
7240  if (conn->password_needed &&
7241  (password == NULL || password[0] == '\0'))
7242  return true;
7243  else
7244  return false;
7245 }
char * PQpass(const PGconn *conn)
Definition: fe-connect.c:7034

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

7260 {
7261  if (!conn)
7262  return false;
7263  if (conn->gssapi_used)
7264  return true;
7265  else
7266  return false;
7267 }
bool gssapi_used
Definition: libpq-int.h:493

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

7249 {
7250  if (!conn)
7251  return false;
7252  if (conn->password_needed)
7253  return true;
7254  else
7255  return false;
7256 }

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

1122 {
1123  int i;
1124 
1125  /*
1126  * Allocate memory for details about each host to which we might possibly
1127  * try to connect. For that, count the number of elements in the hostaddr
1128  * or host options. If neither is given, assume one host.
1129  */
1130  conn->whichhost = 0;
1131  if (conn->pghostaddr && conn->pghostaddr[0] != '\0')
1133  else if (conn->pghost && conn->pghost[0] != '\0')
1135  else
1136  conn->nconnhost = 1;
1137  conn->connhost = (pg_conn_host *)
1138  calloc(conn->nconnhost, sizeof(pg_conn_host));
1139  if (conn->connhost == NULL)
1140  goto oom_error;
1141 
1142  /*
1143  * We now have one pg_conn_host structure per possible host. Fill in the
1144  * host and hostaddr fields for each, by splitting the parameter strings.
1145  */
1146  if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0')
1147  {
1148  char *s = conn->pghostaddr;
1149  bool more = true;
1150 
1151  for (i = 0; i < conn->nconnhost && more; i++)
1152  {
1154  if (conn->connhost[i].hostaddr == NULL)
1155  goto oom_error;
1156  }
1157 
1158  /*
1159  * If hostaddr was given, the array was allocated according to the
1160  * number of elements in the hostaddr list, so it really should be the
1161  * right size.
1162  */
1163  Assert(!more);
1164  Assert(i == conn->nconnhost);
1165  }
1166 
1167  if (conn->pghost != NULL && conn->pghost[0] != '\0')
1168  {
1169  char *s = conn->pghost;
1170  bool more = true;
1171 
1172  for (i = 0; i < conn->nconnhost && more; i++)
1173  {
1175  if (conn->connhost[i].host == NULL)
1176  goto oom_error;
1177  }
1178 
1179  /* Check for wrong number of host items. */
1180  if (more || i != conn->nconnhost)
1181  {
1183  libpq_append_conn_error(conn, "could not match %d host names to %d hostaddr values",
1185  return false;
1186  }
1187  }
1188 
1189  /*
1190  * Now, for each host slot, identify the type of address spec, and fill in
1191  * the default address if nothing was given.
1192  */
1193  for (i = 0; i < conn->nconnhost; i++)
1194  {
1195  pg_conn_host *ch = &conn->connhost[i];
1196 
1197  if (ch->hostaddr != NULL && ch->hostaddr[0] != '\0')
1198  ch->type = CHT_HOST_ADDRESS;
1199  else if (ch->host != NULL && ch->host[0] != '\0')
1200  {
1201  ch->type = CHT_HOST_NAME;
1202  if (is_unixsock_path(ch->host))
1203  ch->type = CHT_UNIX_SOCKET;
1204  }
1205  else
1206  {
1207  free(ch->host);
1208 
1209  /*
1210  * This bit selects the default host location. If you change
1211  * this, see also pg_regress.
1212  */
1213  if (DEFAULT_PGSOCKET_DIR[0])
1214  {
1215  ch->host = strdup(DEFAULT_PGSOCKET_DIR);
1216  ch->type = CHT_UNIX_SOCKET;
1217  }
1218  else
1219  {
1220  ch->host = strdup(DefaultHost);
1221  ch->type = CHT_HOST_NAME;
1222  }
1223  if (ch->host == NULL)
1224  goto oom_error;
1225  }
1226  }
1227 
1228  /*
1229  * Next, work out the port number corresponding to each host name.
1230  *
1231  * Note: unlike the above for host names, this could leave the port fields
1232  * as null or empty strings. We will substitute DEF_PGPORT whenever we
1233  * read such a port field.
1234  */
1235  if (conn->pgport != NULL && conn->pgport[0] != '\0')
1236  {
1237  char *s = conn->pgport;
1238  bool more = true;
1239 
1240  for (i = 0; i < conn->nconnhost && more; i++)
1241  {
1243  if (conn->connhost[i].port == NULL)
1244  goto oom_error;
1245  }
1246 
1247  /*
1248  * If exactly one port was given, use it for every host. Otherwise,
1249  * there must be exactly as many ports as there were hosts.
1250  */
1251  if (i == 1 && !more)
1252  {
1253  for (i = 1; i < conn->nconnhost; i++)
1254  {
1255  conn->connhost[i].port = strdup(conn->connhost[0].port);
1256  if (conn->connhost[i].port == NULL)
1257  goto oom_error;
1258  }
1259  }
1260  else if (more || i != conn->nconnhost)
1261  {
1263  libpq_append_conn_error(conn, "could not match %d port numbers to %d hosts",
1265  return false;
1266  }
1267  }
1268 
1269  /*
1270  * If user name was not given, fetch it. (Most likely, the fetch will
1271  * fail, since the only way we get here is if pg_fe_getauthname() failed
1272  * during conninfo_add_defaults(). But now we want an error message.)
1273  */
1274  if (conn->pguser == NULL || conn->pguser[0] == '\0')
1275  {
1276  free(conn->pguser);
1278  if (!conn->pguser)
1279  {
1281  return false;
1282  }
1283  }
1284 
1285  /*
1286  * If database name was not given, default it to equal user name
1287  */
1288  if (conn->dbName == NULL || conn->dbName[0] == '\0')
1289  {
1290  free(conn->dbName);
1291  conn->dbName = strdup(conn->pguser);
1292  if (!conn->dbName)
1293  goto oom_error;
1294  }
1295 
1296  /*
1297  * If password was not given, try to look it up in password file. Note
1298  * that the result might be different for each host/port pair.
1299  */
1300  if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
1301  {
1302  /* If password file wasn't specified, use ~/PGPASSFILE */
1303  if (conn->pgpassfile == NULL || conn->pgpassfile[0] == '\0')
1304  {
1305  char homedir[MAXPGPATH];
1306 
1307  if (pqGetHomeDirectory(homedir, sizeof(homedir)))
1308  {
1309  free(conn->pgpassfile);
1311  if (!conn->pgpassfile)
1312  goto oom_error;
1313  snprintf(conn->pgpassfile, MAXPGPATH, "%s/%s",
1314  homedir, PGPASSFILE);
1315  }
1316  }
1317 
1318  if (conn->pgpassfile != NULL && conn->pgpassfile[0] != '\0')
1319  {
1320  for (i = 0; i < conn->nconnhost; i++)
1321  {
1322  /*
1323  * Try to get a password for this host from file. We use host
1324  * for the hostname search key if given, else hostaddr (at
1325  * least one of them is guaranteed nonempty by now).
1326  */
1327  const char *pwhost = conn->connhost[i].host;
1328 
1329  if (pwhost == NULL || pwhost[0] == '\0')
1330  pwhost = conn->connhost[i].hostaddr;
1331 
1332  conn->connhost[i].password =
1333  passwordFromFile(pwhost,
1334  conn->connhost[i].port,
1335  conn->dbName,
1336  conn->pguser,
1337  conn->pgpassfile);
1338  }
1339  }
1340  }
1341 
1342  /*
1343  * parse and validate require_auth option
1344  */
1345  if (conn->require_auth && conn->require_auth[0])
1346  {
1347  char *s = conn->require_auth;
1348  bool first,
1349  more;
1350  bool negated = false;
1351 
1352  /*
1353  * By default, start from an empty set of allowed options and add to
1354  * it.
1355  */
1356  conn->auth_required = true;
1358 
1359  for (first = true, more = true; more; first = false)
1360  {
1361  char *method,
1362  *part;
1363  uint32 bits;
1364 
1365  part = parse_comma_separated_list(&s, &more);
1366  if (part == NULL)
1367  goto oom_error;
1368 
1369  /*
1370  * Check for negation, e.g. '!password'. If one element is
1371  * negated, they all have to be.
1372  */
1373  method = part;
1374  if (*method == '!')
1375  {
1376  if (first)
1377  {
1378  /*
1379  * Switch to a permissive set of allowed options, and
1380  * subtract from it.
1381  */
1382  conn->auth_required = false;
1383  conn->allowed_auth_methods = -1;
1384  }
1385  else if (!negated)
1386  {
1388  libpq_append_conn_error(conn, "negative require_auth method \"%s\" cannot be mixed with non-negative methods",
1389  method);
1390 
1391  free(part);
1392  return false;
1393  }
1394 
1395  negated = true;
1396  method++;
1397  }
1398  else if (negated)
1399  {
1401  libpq_append_conn_error(conn, "require_auth method \"%s\" cannot be mixed with negative methods",
1402  method);
1403 
1404  free(part);
1405  return false;
1406  }
1407 
1408  if (strcmp(method, "password") == 0)
1409  {
1410  bits = (1 << AUTH_REQ_PASSWORD);
1411  }
1412  else if (strcmp(method, "md5") == 0)
1413  {
1414  bits = (1 << AUTH_REQ_MD5);
1415  }
1416  else if (strcmp(method, "gss") == 0)
1417  {
1418  bits = (1 << AUTH_REQ_GSS);
1419  bits |= (1 << AUTH_REQ_GSS_CONT);
1420  }
1421  else if (strcmp(method, "sspi") == 0)
1422  {
1423  bits = (1 << AUTH_REQ_SSPI);
1424  bits |= (1 << AUTH_REQ_GSS_CONT);
1425  }
1426  else if (strcmp(method, "scram-sha-256") == 0)
1427  {
1428  /* This currently assumes that SCRAM is the only SASL method. */
1429  bits = (1 << AUTH_REQ_SASL);
1430  bits |= (1 << AUTH_REQ_SASL_CONT);
1431  bits |= (1 << AUTH_REQ_SASL_FIN);
1432  }
1433  else if (strcmp(method, "none") == 0)
1434  {
1435  /*
1436  * Special case: let the user explicitly allow (or disallow)
1437  * connections where the server does not send an explicit
1438  * authentication challenge, such as "trust" and "cert" auth.
1439  */
1440  if (negated) /* "!none" */
1441  {
1442  if (conn->auth_required)
1443  goto duplicate;
1444 
1445  conn->auth_required = true;
1446  }
1447  else /* "none" */
1448  {
1449  if (!conn->auth_required)
1450  goto duplicate;
1451 
1452  conn->auth_required = false;
1453  }
1454 
1455  free(part);
1456  continue; /* avoid the bitmask manipulation below */
1457  }
1458  else
1459  {
1461  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1462  "require_auth", method);
1463 
1464  free(part);
1465  return false;
1466  }
1467 
1468  /* Update the bitmask. */
1469  if (negated)
1470  {
1471  if ((conn->allowed_auth_methods & bits) == 0)
1472  goto duplicate;
1473 
1474  conn->allowed_auth_methods &= ~bits;
1475  }
1476  else
1477  {
1478  if ((conn->allowed_auth_methods & bits) == bits)
1479  goto duplicate;
1480 
1481  conn->allowed_auth_methods |= bits;
1482  }
1483 
1484  free(part);
1485  continue;
1486 
1487  duplicate:
1488 
1489  /*
1490  * A duplicated method probably indicates a typo in a setting
1491  * where typos are extremely risky.
1492  */
1494  libpq_append_conn_error(conn, "require_auth method \"%s\" is specified more than once",
1495  part);
1496 
1497  free(part);
1498  return false;
1499  }
1500  }
1501 
1502  /*
1503  * validate channel_binding option
1504  */
1505  if (conn->channel_binding)
1506  {
1507  if (strcmp(conn->channel_binding, "disable") != 0
1508  && strcmp(conn->channel_binding, "prefer") != 0
1509  && strcmp(conn->channel_binding, "require") != 0)
1510  {
1512  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1513  "channel_binding", conn->channel_binding);
1514  return false;
1515  }
1516  }
1517  else
1518  {
1520  if (!conn->channel_binding)
1521  goto oom_error;
1522  }
1523 
1524 #ifndef USE_SSL
1525 
1526  /*
1527  * sslrootcert=system is not supported. Since setting this changes the
1528  * default sslmode, check this _before_ we validate sslmode, to avoid
1529  * confusing the user with errors for an option they may not have set.
1530  */
1531  if (conn->sslrootcert
1532  && strcmp(conn->sslrootcert, "system") == 0)
1533  {
1535  libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1536  "sslrootcert", conn->sslrootcert);
1537  return false;
1538  }
1539 #endif
1540 
1541  /*
1542  * validate sslmode option
1543  */
1544  if (conn->sslmode)
1545  {
1546  if (strcmp(conn->sslmode, "disable") != 0
1547  && strcmp(conn->sslmode, "allow") != 0
1548  && strcmp(conn->sslmode, "prefer") != 0
1549  && strcmp(conn->sslmode, "require") != 0
1550  && strcmp(conn->sslmode, "verify-ca") != 0
1551  && strcmp(conn->sslmode, "verify-full") != 0)
1552  {
1554  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1555  "sslmode", conn->sslmode);
1556  return false;
1557  }
1558 
1559 #ifndef USE_SSL
1560  switch (conn->sslmode[0])
1561  {
1562  case 'a': /* "allow" */
1563  case 'p': /* "prefer" */
1564 
1565  /*
1566  * warn user that an SSL connection will never be negotiated
1567  * since SSL was not compiled in?
1568  */
1569  break;
1570 
1571  case 'r': /* "require" */
1572  case 'v': /* "verify-ca" or "verify-full" */
1574  libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1575  "sslmode", conn->sslmode);
1576  return false;
1577  }
1578 #endif
1579  }
1580  else
1581  {
1582  conn->sslmode = strdup(DefaultSSLMode);
1583  if (!conn->sslmode)
1584  goto oom_error;
1585  }
1586 
1587  /*
1588  * validate sslnegotiation option, default is "postgres" for the postgres
1589  * style negotiated connection with an extra round trip but more options.
1590  */
1591  if (conn->sslnegotiation)
1592  {
1593  if (strcmp(conn->sslnegotiation, "postgres") != 0
1594  && strcmp(conn->sslnegotiation, "direct") != 0)
1595  {
1597  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1598  "sslnegotiation", conn->sslnegotiation);
1599  return false;
1600  }
1601 
1602 #ifndef USE_SSL
1603  if (conn->sslnegotiation[0] != 'p')
1604  {
1606  libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1607  "sslnegotiation", conn->sslnegotiation);
1608  return false;
1609  }
1610 #endif
1611 
1612  /*
1613  * Don't allow direct SSL negotiation with sslmode='prefer', because
1614  * that poses a risk of unintentional fallback to plaintext connection
1615  * when connecting to a pre-v17 server that does not support direct
1616  * SSL connections. To keep things simple, don't allow it with
1617  * sslmode='allow' or sslmode='disable' either. If a user goes through
1618  * the trouble of setting sslnegotiation='direct', they probably
1619  * intend to use SSL, and sslmode=disable or allow is probably a user
1620  * user mistake anyway.
1621  */
1622  if (conn->sslnegotiation[0] == 'd' &&
1623  conn->sslmode[0] != 'r' && conn->sslmode[0] != 'v')
1624  {
1626  libpq_append_conn_error(conn, "weak sslmode \"%s\" may not be used with sslnegotiation=direct (use \"require\", \"verify-ca\", or \"verify-full\")",
1627  conn->sslmode);
1628  return false;
1629  }
1630  }
1631  else
1632  {
1634  if (!conn->sslnegotiation)
1635  goto oom_error;
1636  }
1637 
1638 #ifdef USE_SSL
1639 
1640  /*
1641  * If sslrootcert=system, make sure our chosen sslmode is compatible.
1642  */
1643  if (conn->sslrootcert
1644  && strcmp(conn->sslrootcert, "system") == 0
1645  && strcmp(conn->sslmode, "verify-full") != 0)
1646  {
1648  libpq_append_conn_error(conn, "weak sslmode \"%s\" may not be used with sslrootcert=system (use \"verify-full\")",
1649  conn->sslmode);
1650  return false;
1651  }
1652 #endif
1653 
1654  /*
1655  * Validate TLS protocol versions for ssl_min_protocol_version and
1656  * ssl_max_protocol_version.
1657  */
1659  {
1661  libpq_append_conn_error(conn, "invalid \"%s\" value: \"%s\"",
1662  "ssl_min_protocol_version",
1664  return false;
1665  }
1667  {
1669  libpq_append_conn_error(conn, "invalid \"%s\" value: \"%s\"",
1670  "ssl_max_protocol_version",
1672  return false;
1673  }
1674 
1675  /*
1676  * Check if the range of SSL protocols defined is correct. This is done
1677  * at this early step because this is independent of the SSL
1678  * implementation used, and this avoids unnecessary cycles with an
1679  * already-built SSL context when the connection is being established, as
1680  * it would be doomed anyway.
1681  */
1684  {
1686  libpq_append_conn_error(conn, "invalid SSL protocol version range");
1687  return false;
1688  }
1689 
1690  /*
1691  * validate sslcertmode option
1692  */
1693  if (conn->sslcertmode)
1694  {
1695  if (strcmp(conn->sslcertmode, "disable") != 0 &&
1696  strcmp(conn->sslcertmode, "allow") != 0 &&
1697  strcmp(conn->sslcertmode, "require") != 0)
1698  {
1700  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1701  "sslcertmode", conn->sslcertmode);
1702  return false;
1703  }
1704 #ifndef USE_SSL
1705  if (strcmp(conn->sslcertmode, "require") == 0)
1706  {
1708  libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1709  "sslcertmode", conn->sslcertmode);
1710  return false;
1711  }
1712 #endif
1713 #ifndef HAVE_SSL_CTX_SET_CERT_CB
1714 
1715  /*
1716  * Without a certificate callback, the current implementation can't
1717  * figure out if a certificate was actually requested, so "require" is
1718  * useless.
1719  */
1720  if (strcmp(conn->sslcertmode, "require") == 0)
1721  {
1723  libpq_append_conn_error(conn, "%s value \"%s\" is not supported (check OpenSSL version)",
1724  "sslcertmode", conn->sslcertmode);
1725  return false;
1726  }
1727 #endif
1728  }
1729  else
1730  {
1731  conn->sslcertmode = strdup(DefaultSSLCertMode);
1732  if (!conn->sslcertmode)
1733  goto oom_error;
1734  }
1735 
1736  /*
1737  * validate gssencmode option
1738  */
1739  if (conn->gssencmode)
1740  {
1741  if (strcmp(conn->gssencmode, "disable") != 0 &&
1742  strcmp(conn->gssencmode, "prefer") != 0 &&
1743  strcmp(conn->gssencmode, "require") != 0)
1744  {
1746  libpq_append_conn_error(conn, "invalid %s value: \"%s\"", "gssencmode", conn->gssencmode);
1747  return false;
1748  }
1749 #ifndef ENABLE_GSS
1750  if (strcmp(conn->gssencmode, "require") == 0)
1751  {
1753  libpq_append_conn_error(conn, "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in",
1754  conn->gssencmode);
1755  return false;
1756  }
1757 #endif
1758  }
1759  else
1760  {
1761  conn->gssencmode = strdup(DefaultGSSMode);
1762  if (!conn->gssencmode)
1763  goto oom_error;
1764  }
1765 
1766  /*
1767  * validate target_session_attrs option, and set target_server_type
1768  */
1770  {
1771  if (strcmp(conn->target_session_attrs, "any") == 0)
1773  else if (strcmp(conn->target_session_attrs, "read-write") == 0)
1775  else if (strcmp(conn->target_session_attrs, "read-only") == 0)
1777  else if (strcmp(conn->target_session_attrs, "primary") == 0)
1779  else if (strcmp(conn->target_session_attrs, "standby") == 0)
1781  else if (strcmp(conn->target_session_attrs, "prefer-standby") == 0)
1783  else
1784  {
1786  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1787  "target_session_attrs",
1789  return false;
1790  }
1791  }
1792  else
1794 
1795  /*
1796  * validate load_balance_hosts option, and set load_balance_type
1797  */
1798  if (conn->load_balance_hosts)
1799  {
1800  if (strcmp(conn->load_balance_hosts, "disable") == 0)
1802  else if (strcmp(conn->load_balance_hosts, "random") == 0)
1804  else
1805  {
1807  libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1808  "load_balance_hosts",
1810  return false;
1811  }
1812  }
1813  else
1815 
1817  {
1819 
1820  /*
1821  * This is the "inside-out" variant of the Fisher-Yates shuffle
1822  * algorithm. Notionally, we append each new value to the array and
1823  * then swap it with a randomly-chosen array element (possibly
1824  * including itself, else we fail to generate permutations with the
1825  * last integer last). The swap step can be optimized by combining it
1826  * with the insertion.
1827  */
1828  for (i = 1; i < conn->nconnhost; i++)
1829  {
1830  int j = pg_prng_uint64_range(&conn->prng_state, 0, i);
1831  pg_conn_host temp = conn->connhost[j];
1832 
1833  conn->connhost[j] = conn->connhost[i];
1834  conn->connhost[i] = temp;
1835  }
1836  }
1837 
1838  /*
1839  * Resolve special "auto" client_encoding from the locale
1840  */
1842  strcmp(conn->client_encoding_initial, "auto") == 0)
1843  {
1847  goto oom_error;
1848  }
1849 
1850  /*
1851  * Only if we get this far is it appropriate to try to connect. (We need a
1852  * state flag, rather than just the boolean result of this function, in
1853  * case someone tries to PQreset() the PGconn.)
1854  */
1855  conn->options_valid = true;
1856 
1857  return true;
1858 
1859 oom_error:
1861  libpq_append_conn_error(conn, "out of memory");
1862  return false;
1863 }
unsigned int uint32
Definition: c.h:506
static char * passwordFromFile(const char *hostname, const char *port, const char *dbname, const char *username, const char *pgpassfile)
Definition: fe-connect.c:7448
static bool sslVerifyProtocolRange(const char *min, const char *max)
Definition: fe-connect.c:7639
static void libpq_prng_init(PGconn *conn)
Definition: fe-connect.c:1094
#define DefaultSSLMode
Definition: fe-connect.c:130
#define DefaultGSSMode
Definition: fe-connect.c:138
static int count_comma_separated_elems(const char *input)
Definition: fe-connect.c:1035
#define DefaultChannelBinding
Definition: fe-connect.c:122
static bool sslVerifyProtocolVersion(const char *version)
Definition: fe-connect.c:7613
static char * parse_comma_separated_list(char **startptr, bool *more)
Definition: fe-connect.c:1059
#define DefaultSSLNegotiation
Definition: fe-connect.c:133
#define PGPASSFILE
Definition: fe-connect.c:76
#define DefaultSSLCertMode
Definition: fe-connect.c:131
#define calloc(a, b)
Definition: header.h:55
int j
Definition: isn.c:74
@ LOAD_BALANCE_DISABLE
Definition: libpq-int.h:255
@ LOAD_BALANCE_RANDOM
Definition: libpq-int.h:256
@ CHT_UNIX_SOCKET
Definition: libpq-int.h:317
@ CHT_HOST_NAME
Definition: libpq-int.h:315
@ SERVER_TYPE_STANDBY
Definition: libpq-int.h:247
@ SERVER_TYPE_PRIMARY
Definition: libpq-int.h:246
@ SERVER_TYPE_ANY
Definition: libpq-int.h:243
@ SERVER_TYPE_READ_WRITE
Definition: libpq-int.h:244
@ SERVER_TYPE_READ_ONLY
Definition: libpq-int.h:245
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:630
int pg_get_encoding_from_locale(const char *ctype, bool write_message)
Definition: chklocale.c:305
#define AUTH_REQ_SSPI
Definition: protocol.h:83
#define AUTH_REQ_SASL_CONT
Definition: protocol.h:85
#define AUTH_REQ_GSS
Definition: protocol.h:81
#define AUTH_REQ_MD5
Definition: protocol.h:79
#define AUTH_REQ_PASSWORD
Definition: protocol.h:77
#define AUTH_REQ_GSS_CONT
Definition: protocol.h:82
#define AUTH_REQ_SASL
Definition: protocol.h:84
#define AUTH_REQ_SASL_FIN
Definition: protocol.h:86
int nconnhost
Definition: libpq-int.h:466
uint32 allowed_auth_methods
Definition: libpq-int.h:501
bool auth_required
Definition: libpq-int.h:499
PGLoadBalanceType load_balance_type
Definition: libpq-int.h:511

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, DefaultSSLNegotiation, 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::sslnegotiation, 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 PQcancelCreate(), PQconnectStart(), PQconnectStartParams(), and PQsetdbLogin().

◆ PQconnectPoll()

PostgresPollingStatusType PQconnectPoll ( PGconn conn)

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

2598 {
2599  bool reset_connection_state_machine = false;
2600  bool need_new_connection = false;
2601  PGresult *res;
2602  char sebuf[PG_STRERROR_R_BUFLEN];
2603  int optval;
2604 
2605  if (conn == NULL)
2606  return PGRES_POLLING_FAILED;
2607 
2608  /* Get the new data */
2609  switch (conn->status)
2610  {
2611  /*
2612  * We really shouldn't have been polled in these two cases, but we
2613  * can handle it.
2614  */
2615  case CONNECTION_BAD:
2616  return PGRES_POLLING_FAILED;
2617  case CONNECTION_OK:
2618  return PGRES_POLLING_OK;
2619 
2620  /* These are reading states */
2622  case CONNECTION_AUTH_OK:
2624  case CONNECTION_CONSUME:
2626  {
2627  /* Load waiting data */
2628  int n = pqReadData(conn);
2629 
2630  if (n < 0)
2631  goto error_return;
2632  if (n == 0)
2633  return PGRES_POLLING_READING;
2634 
2635  break;
2636  }
2637 
2638  /* These are writing states, so we just proceed. */
2639  case CONNECTION_STARTED:
2640  case CONNECTION_MADE:
2641  break;
2642 
2643  /* Special cases: proceed without waiting. */
2645  case CONNECTION_NEEDED:
2648  break;
2649 
2650  default:
2651  libpq_append_conn_error(conn, "invalid connection state, probably indicative of memory corruption");
2652  goto error_return;
2653  }
2654 
2655 
2656 keep_going: /* We will come back to here until there is
2657  * nothing left to do. */
2658 
2659  /* Time to advance to next address, or next host if no more addresses? */
2660  if (conn->try_next_addr)
2661  {
2662  if (conn->whichaddr < conn->naddr)
2663  {
2664  conn->whichaddr++;
2665  reset_connection_state_machine = true;
2666  }
2667  else
2668  conn->try_next_host = true;
2669  conn->try_next_addr = false;
2670  }
2671 
2672  /* Time to advance to next connhost[] entry? */
2673  if (conn->try_next_host)
2674  {
2675  pg_conn_host *ch;
2676  struct addrinfo hint;
2677  struct addrinfo *addrlist;
2678  int thisport;
2679  int ret;
2680  char portstr[MAXPGPATH];
2681 
2682  if (conn->whichhost + 1 < conn->nconnhost)
2683  conn->whichhost++;
2684  else
2685  {
2686  /*
2687  * Oops, no more hosts.
2688  *
2689  * If we are trying to connect in "prefer-standby" mode, then drop
2690  * the standby requirement and start over. Don't do this for
2691  * cancel requests though, since we are certain the list of
2692  * servers won't change as the target_server_type option is not
2693  * applicable to those connections.
2694  *
2695  * Otherwise, an appropriate error message is already set up, so
2696  * we just need to set the right status.
2697  */
2699  conn->nconnhost > 0 &&
2700  !conn->cancelRequest)
2701  {
2703  conn->whichhost = 0;
2704  }
2705  else
2706  goto error_return;
2707  }
2708 
2709  /* Drop any address info for previous host */
2711 
2712  /*
2713  * Look up info for the new host. On failure, log the problem in
2714  * conn->errorMessage, then loop around to try the next host. (Note
2715  * we don't clear try_next_host until we've succeeded.)
2716  */
2717  ch = &conn->connhost[conn->whichhost];
2718 
2719  /* Initialize hint structure */
2720  MemSet(&hint, 0, sizeof(hint));
2721  hint.ai_socktype = SOCK_STREAM;
2722  hint.ai_family = AF_UNSPEC;
2723 
2724  /* Figure out the port number we're going to use. */
2725  if (ch->port == NULL || ch->port[0] == '\0')
2726  thisport = DEF_PGPORT;
2727  else
2728  {
2729  if (!pqParseIntParam(ch->port, &thisport, conn, "port"))
2730  goto error_return;
2731 
2732  if (thisport < 1 || thisport > 65535)
2733  {
2734  libpq_append_conn_error(conn, "invalid port number: \"%s\"", ch->port);
2735  goto keep_going;
2736  }
2737  }
2738  snprintf(portstr, sizeof(portstr), "%d", thisport);
2739 
2740  /* Use pg_getaddrinfo_all() to resolve the address */
2741  switch (ch->type)
2742  {
2743  case CHT_HOST_NAME:
2744  ret = pg_getaddrinfo_all(ch->host, portstr, &hint,
2745  &addrlist);
2746  if (ret || !addrlist)
2747  {
2748  libpq_append_conn_error(conn, "could not translate host name \"%s\" to address: %s",
2749  ch->host, gai_strerror(ret));
2750  goto keep_going;
2751  }
2752  break;
2753 
2754  case CHT_HOST_ADDRESS:
2755  hint.ai_flags = AI_NUMERICHOST;
2756  ret = pg_getaddrinfo_all(ch->hostaddr, portstr, &hint,
2757  &addrlist);
2758  if (ret || !addrlist)
2759  {
2760  libpq_append_conn_error(conn, "could not parse network address \"%s\": %s",
2761  ch->hostaddr, gai_strerror(ret));
2762  goto keep_going;
2763  }
2764  break;
2765 
2766  case CHT_UNIX_SOCKET:
2767  hint.ai_family = AF_UNIX;
2768  UNIXSOCK_PATH(portstr, thisport, ch->host);
2769  if (strlen(portstr) >= UNIXSOCK_PATH_BUFLEN)
2770  {
2771  libpq_append_conn_error(conn, "Unix-domain socket path \"%s\" is too long (maximum %d bytes)",
2772  portstr,
2773  (int) (UNIXSOCK_PATH_BUFLEN - 1));
2774  goto keep_going;
2775  }
2776 
2777  /*
2778  * NULL hostname tells pg_getaddrinfo_all to parse the service
2779  * name as a Unix-domain socket path.
2780  */
2781  ret = pg_getaddrinfo_all(NULL, portstr, &hint,
2782  &addrlist);
2783  if (ret || !addrlist)
2784  {
2785  libpq_append_conn_error(conn, "could not translate Unix-domain socket path \"%s\" to address: %s",
2786  portstr, gai_strerror(ret));
2787  goto keep_going;
2788  }
2789  break;
2790  }
2791 
2792  /*
2793  * Store a copy of the addrlist in private memory so we can perform
2794  * randomization for load balancing.
2795  */
2796  ret = store_conn_addrinfo(conn, addrlist);
2797  pg_freeaddrinfo_all(hint.ai_family, addrlist);
2798  if (ret)
2799  goto error_return; /* message already logged */
2800 
2801  /*
2802  * If random load balancing is enabled we shuffle the addresses.
2803  */
2805  {
2806  /*
2807  * This is the "inside-out" variant of the Fisher-Yates shuffle
2808  * algorithm. Notionally, we append each new value to the array
2809  * and then swap it with a randomly-chosen array element (possibly
2810  * including itself, else we fail to generate permutations with
2811  * the last integer last). The swap step can be optimized by
2812  * combining it with the insertion.
2813  *
2814  * We don't need to initialize conn->prng_state here, because that
2815  * already happened in pqConnectOptions2.
2816  */
2817  for (int i = 1; i < conn->naddr; i++)
2818  {
2819  int j = pg_prng_uint64_range(&conn->prng_state, 0, i);
2820  AddrInfo temp = conn->addr[j];
2821 
2822  conn->addr[j] = conn->addr[i];
2823  conn->addr[i] = temp;
2824  }
2825  }
2826 
2827  reset_connection_state_machine = true;
2828  conn->try_next_host = false;
2829  }
2830 
2831  /* Reset connection state machine? */
2832  if (reset_connection_state_machine)
2833  {
2834  /*
2835  * (Re) initialize our connection control variables for a set of
2836  * connection attempts to a single server address. These variables
2837  * must persist across individual connection attempts, but we must
2838  * reset them when we start to consider a new server.
2839  */
2840  conn->pversion = PG_PROTOCOL(3, 0);
2841  conn->send_appname = true;
2842  conn->failed_enc_methods = 0;
2843  conn->current_enc_method = 0;
2845  reset_connection_state_machine = false;
2846  need_new_connection = true;
2847  }
2848 
2849  /* Force a new connection (perhaps to the same server as before)? */
2850  if (need_new_connection)
2851  {
2852  /* Drop any existing connection */
2853  pqDropConnection(conn, true);
2854 
2855  /* Reset all state obtained from old server */
2857 
2858  /* Drop any PGresult we might have, too */
2863 
2864  /* Reset conn->status to put the state machine in the right state */
2866 
2867  need_new_connection = false;
2868  }
2869 
2870  /*
2871  * Decide what to do next, if server rejects SSL or GSS negotiation, but
2872  * the connection is still valid. If there are no options left, error out
2873  * with 'msg'.
2874  */
2875 #define ENCRYPTION_NEGOTIATION_FAILED(msg) \
2876  do { \
2877  switch (encryption_negotiation_failed(conn)) \
2878  { \
2879  case 0: \
2880  libpq_append_conn_error(conn, (msg)); \
2881  goto error_return; \
2882  case 1: \
2883  conn->status = CONNECTION_MADE; \
2884  return PGRES_POLLING_WRITING; \
2885  case 2: \
2886  need_new_connection = true; \
2887  goto keep_going; \
2888  } \
2889  } while(0);
2890 
2891  /*
2892  * Decide what to do next, if connection fails. If there are no options
2893  * left, return with an error. The error message has already been written
2894  * to the connection's error buffer.
2895  */
2896 #define CONNECTION_FAILED() \
2897  do { \
2898  if (connection_failed(conn)) \
2899  { \
2900  need_new_connection = true; \
2901  goto keep_going; \
2902  } \
2903  else \
2904  goto error_return; \
2905  } while(0);
2906 
2907  /* Now try to advance the state machine for this connection */
2908  switch (conn->status)
2909  {
2910  case CONNECTION_NEEDED:
2911  {
2912  /*
2913  * Try to initiate a connection to one of the addresses
2914  * returned by pg_getaddrinfo_all(). conn->whichaddr is the
2915  * next one to try.
2916  *
2917  * The extra level of braces here is historical. It's not
2918  * worth reindenting this whole switch case to remove 'em.
2919  */
2920  {
2921  char host_addr[NI_MAXHOST];
2922  int sock_type;
2923  AddrInfo *addr_cur;
2924 
2925  /*
2926  * Advance to next possible host, if we've tried all of
2927  * the addresses for the current host.
2928  */
2929  if (conn->whichaddr == conn->naddr)
2930  {
2931  conn->try_next_host = true;
2932  goto keep_going;
2933  }
2934  addr_cur = &conn->addr[conn->whichaddr];
2935 
2936  /* Remember current address for possible use later */
2937  memcpy(&conn->raddr, &addr_cur->addr, sizeof(SockAddr));
2938 
2939 #ifdef ENABLE_GSS
2940 
2941  /*
2942  * Before establishing the connection, check if it's
2943  * doomed to fail because gssencmode='require' but GSSAPI
2944  * is not available.
2945  */
2946  if (conn->gssencmode[0] == 'r')
2947  {
2948  if (conn->raddr.addr.ss_family == AF_UNIX)
2949  {
2951  "GSSAPI encryption required but it is not supported over a local socket");
2952  goto error_return;
2953  }
2954  if (conn->gcred == GSS_C_NO_CREDENTIAL)
2955  {
2956  if (!pg_GSS_have_cred_cache(&conn->gcred))
2957  {
2959  "GSSAPI encryption required but no credential cache");
2960  goto error_return;
2961  }
2962  }
2963  }
2964 #endif
2965 
2966  /*
2967  * Choose the encryption method to try first. Do this
2968  * before establishing the connection, so that if none of
2969  * the modes allowed by the connections options are
2970  * available, we can error out before establishing the
2971  * connection.
2972  */
2974  goto error_return;
2975 
2976  /*
2977  * Set connip, too. Note we purposely ignore strdup
2978  * failure; not a big problem if it fails.
2979  */
2980  if (conn->connip != NULL)
2981  {
2982  free(conn->connip);
2983  conn->connip = NULL;
2984  }
2985  getHostaddr(conn, host_addr, NI_MAXHOST);
2986  if (host_addr[0])
2987  conn->connip = strdup(host_addr);
2988 
2989  /* Try to create the socket */
2990  sock_type = SOCK_STREAM;
2991 #ifdef SOCK_CLOEXEC
2992 
2993  /*
2994  * Atomically mark close-on-exec, if possible on this
2995  * platform, so that there isn't a window where a
2996  * subprogram executed by another thread inherits the
2997  * socket. See fallback code below.
2998  */
2999  sock_type |= SOCK_CLOEXEC;
3000 #endif
3001 #ifdef SOCK_NONBLOCK
3002 
3003  /*
3004  * We might as well skip a system call for nonblocking
3005  * mode too, if we can.
3006  */
3007  sock_type |= SOCK_NONBLOCK;
3008 #endif
3009  conn->sock = socket(addr_cur->family, sock_type, 0);
3010  if (conn->sock == PGINVALID_SOCKET)
3011  {
3012  int errorno = SOCK_ERRNO;
3013 
3014  /*
3015  * Silently ignore socket() failure if we have more
3016  * addresses to try; this reduces useless chatter in
3017  * cases where the address list includes both IPv4 and
3018  * IPv6 but kernel only accepts one family.
3019  */
3020  if (conn->whichaddr < conn->naddr ||
3021  conn->whichhost + 1 < conn->nconnhost)
3022  {
3023  conn->try_next_addr = true;
3024  goto keep_going;
3025  }
3026  emitHostIdentityInfo(conn, host_addr);
3027  libpq_append_conn_error(conn, "could not create socket: %s",
3028  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
3029  goto error_return;
3030  }
3031 
3032  /*
3033  * Once we've identified a target address, all errors
3034  * except the preceding socket()-failure case should be
3035  * prefixed with host-identity information. (If the
3036  * connection succeeds, the contents of conn->errorMessage
3037  * won't matter, so this is harmless.)
3038  */
3039  emitHostIdentityInfo(conn, host_addr);
3040 
3041  /*
3042  * Select socket options: no delay of outgoing data for
3043  * TCP sockets, nonblock mode, close-on-exec. Try the
3044  * next address if any of this fails.
3045  */
3046  if (addr_cur->family != AF_UNIX)
3047  {
3048  if (!connectNoDelay(conn))
3049  {
3050  /* error message already created */
3051  conn->try_next_addr = true;
3052  goto keep_going;
3053  }
3054  }
3055 #ifndef SOCK_NONBLOCK
3056  if (!pg_set_noblock(conn->sock))
3057  {
3058  libpq_append_conn_error(conn, "could not set socket to nonblocking mode: %s",
3059  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3060  conn->try_next_addr = true;
3061  goto keep_going;
3062  }
3063 #endif
3064 
3065 #ifndef SOCK_CLOEXEC
3066 #ifdef F_SETFD
3067  if (fcntl(conn->sock, F_SETFD, FD_CLOEXEC) == -1)
3068  {
3069  libpq_append_conn_error(conn, "could not set socket to close-on-exec mode: %s",
3070  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3071  conn->try_next_addr = true;
3072  goto keep_going;
3073  }
3074 #endif /* F_SETFD */
3075 #endif
3076 
3077  if (addr_cur->family != AF_UNIX)
3078  {
3079 #ifndef WIN32
3080  int on = 1;
3081 #endif
3082  int usekeepalives = useKeepalives(conn);
3083  int err = 0;
3084 
3085  if (usekeepalives < 0)
3086  {
3087  libpq_append_conn_error(conn, "keepalives parameter must be an integer");
3088  err = 1;
3089  }
3090  else if (usekeepalives == 0)
3091  {
3092  /* Do nothing */
3093  }
3094 #ifndef WIN32
3095  else if (setsockopt(conn->sock,
3096  SOL_SOCKET, SO_KEEPALIVE,
3097  (char *) &on, sizeof(on)) < 0)
3098  {
3099  libpq_append_conn_error(conn, "%s(%s) failed: %s",
3100  "setsockopt",
3101  "SO_KEEPALIVE",
3102  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3103  err = 1;
3104  }
3105  else if (!setKeepalivesIdle(conn)
3107  || !setKeepalivesCount(conn))
3108  err = 1;
3109 #else /* WIN32 */
3110 #ifdef SIO_KEEPALIVE_VALS
3111  else if (!prepKeepalivesWin32(conn))
3112  err = 1;
3113 #endif /* SIO_KEEPALIVE_VALS */
3114 #endif /* WIN32 */
3115  else if (!setTCPUserTimeout(conn))
3116  err = 1;
3117 
3118  if (err)
3119  {
3120  conn->try_next_addr = true;
3121  goto keep_going;
3122  }
3123  }
3124 
3125  /*----------
3126  * We have three methods of blocking SIGPIPE during
3127  * send() calls to this socket:
3128  *
3129  * - setsockopt(sock, SO_NOSIGPIPE)
3130  * - send(sock, ..., MSG_NOSIGNAL)
3131  * - setting the signal mask to SIG_IGN during send()
3132  *
3133  * The third method requires three syscalls per send,
3134  * so we prefer either of the first two, but they are
3135  * less portable. The state is tracked in the following
3136  * members of PGconn:
3137  *
3138  * conn->sigpipe_so - we have set up SO_NOSIGPIPE
3139  * conn->sigpipe_flag - we're specifying MSG_NOSIGNAL
3140  *
3141  * If we can use SO_NOSIGPIPE, then set sigpipe_so here
3142  * and we're done. Otherwise, set sigpipe_flag so that
3143  * we will try MSG_NOSIGNAL on sends. If we get an error
3144  * with MSG_NOSIGNAL, we'll clear that flag and revert to
3145  * signal masking.
3146  *----------
3147  */
3148  conn->sigpipe_so = false;
3149 #ifdef MSG_NOSIGNAL
3150  conn->sigpipe_flag = true;
3151 #else
3152  conn->sigpipe_flag = false;
3153 #endif /* MSG_NOSIGNAL */
3154 
3155 #ifdef SO_NOSIGPIPE
3156  optval = 1;
3157  if (setsockopt(conn->sock, SOL_SOCKET, SO_NOSIGPIPE,
3158  (char *) &optval, sizeof(optval)) == 0)
3159  {
3160  conn->sigpipe_so = true;
3161  conn->sigpipe_flag = false;
3162  }
3163 #endif /* SO_NOSIGPIPE */
3164 
3165  /*
3166  * Start/make connection. This should not block, since we
3167  * are in nonblock mode. If it does, well, too bad.
3168  */
3169  if (connect(conn->sock, (struct sockaddr *) &addr_cur->addr.addr,
3170  addr_cur->addr.salen) < 0)
3171  {
3172  if (SOCK_ERRNO == EINPROGRESS ||
3173 #ifdef WIN32
3174  SOCK_ERRNO == EWOULDBLOCK ||
3175 #endif
3176  SOCK_ERRNO == EINTR)
3177  {
3178  /*
3179  * This is fine - we're in non-blocking mode, and
3180  * the connection is in progress. Tell caller to
3181  * wait for write-ready on socket.
3182  */
3184  return PGRES_POLLING_WRITING;
3185  }
3186  /* otherwise, trouble */
3187  }
3188  else
3189  {
3190  /*
3191  * Hm, we're connected already --- seems the "nonblock
3192  * connection" wasn't. Advance the state machine and
3193  * go do the next stuff.
3194  */
3196  goto keep_going;
3197  }
3198 
3199  /*
3200  * This connection failed. Add the error report to
3201  * conn->errorMessage, then try the next address if any.
3202  */
3204  conn->try_next_addr = true;
3205  goto keep_going;
3206  }
3207  }
3208 
3209  case CONNECTION_STARTED:
3210  {
3211  socklen_t optlen = sizeof(optval);
3212 
3213  /*
3214  * Write ready, since we've made it here, so the connection
3215  * has been made ... or has failed.
3216  */
3217 
3218  /*
3219  * Now check (using getsockopt) that there is not an error
3220  * state waiting for us on the socket.
3221  */
3222 
3223  if (getsockopt(conn->sock, SOL_SOCKET, SO_ERROR,
3224  (char *) &optval, &optlen) == -1)
3225  {
3226  libpq_append_conn_error(conn, "could not get socket error status: %s",
3227  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3228  goto error_return;
3229  }
3230  else if (optval != 0)
3231  {
3232  /*
3233  * When using a nonblocking connect, we will typically see
3234  * connect failures at this point, so provide a friendly
3235  * error message.
3236  */
3237  connectFailureMessage(conn, optval);
3238 
3239  /*
3240  * Try the next address if any, just as in the case where
3241  * connect() returned failure immediately.
3242  */
3243  conn->try_next_addr = true;
3244  goto keep_going;
3245  }
3246 
3247  /* Fill in the client address */
3248  conn->laddr.salen = sizeof(conn->laddr.addr);
3249  if (getsockname(conn->sock,
3250  (struct sockaddr *) &conn->laddr.addr,
3251  &conn->laddr.salen) < 0)
3252  {
3253  libpq_append_conn_error(conn, "could not get client address from socket: %s",
3254  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3255  goto error_return;
3256  }
3257 
3258  /*
3259  * Implement requirepeer check, if requested and it's a
3260  * Unix-domain socket.
3261  */
3262  if (conn->requirepeer && conn->requirepeer[0] &&
3263  conn->raddr.addr.ss_family == AF_UNIX)
3264  {
3265 #ifndef WIN32
3266  char *remote_username;
3267 #endif
3268  uid_t uid;
3269  gid_t gid;
3270 
3271  errno = 0;
3272  if (getpeereid(conn->sock, &uid, &gid) != 0)
3273  {
3274  /*
3275  * Provide special error message if getpeereid is a
3276  * stub
3277  */
3278  if (errno == ENOSYS)
3279  libpq_append_conn_error(conn, "requirepeer parameter is not supported on this platform");
3280  else
3281  libpq_append_conn_error(conn, "could not get peer credentials: %s",
3282  strerror_r(errno, sebuf, sizeof(sebuf)));
3283  goto error_return;
3284  }
3285 
3286 #ifndef WIN32
3287  remote_username = pg_fe_getusername(uid,
3288  &conn->errorMessage);
3289  if (remote_username == NULL)
3290  goto error_return; /* message already logged */
3291 
3292  if (strcmp(remote_username, conn->requirepeer) != 0)
3293  {
3294  libpq_append_conn_error(conn, "requirepeer specifies \"%s\", but actual peer user name is \"%s\"",
3295  conn->requirepeer, remote_username);
3296  free(remote_username);
3297  goto error_return;
3298  }
3299  free(remote_username);
3300 #else /* WIN32 */
3301  /* should have failed with ENOSYS above */
3302  Assert(false);
3303 #endif /* WIN32 */
3304  }
3305 
3306  /*
3307  * Make sure we can write before advancing to next step.
3308  */
3310  return PGRES_POLLING_WRITING;
3311  }
3312 
3313  case CONNECTION_MADE:
3314  {
3315  char *startpacket;
3316  int packetlen;
3317 
3318 #ifdef ENABLE_GSS
3319 
3320  /*
3321  * If GSSAPI encryption is enabled, send a packet to the
3322  * server asking for GSSAPI Encryption and proceed with GSSAPI
3323  * handshake. We will come back here after GSSAPI encryption
3324  * has been established, with conn->gctx set.
3325  */
3326  if (conn->current_enc_method == ENC_GSSAPI && !conn->gctx)
3327  {
3329 
3330  if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
3331  {
3332  libpq_append_conn_error(conn, "could not send GSSAPI negotiation packet: %s",
3333  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3334  goto error_return;
3335  }
3336 
3337  /* Ok, wait for response */
3339  return PGRES_POLLING_READING;
3340  }
3341 #endif
3342 
3343 #ifdef USE_SSL
3344 
3345  /*
3346  * If SSL is enabled, start the SSL negotiation. We will come
3347  * back here after SSL encryption has been established, with
3348  * ssl_in_use set.
3349  */
3351  {
3352  /*
3353  * If traditional postgres SSL negotiation is used, send
3354  * the SSL request. In direct negotiation, jump straight
3355  * into the SSL handshake.
3356  */
3357  if (conn->sslnegotiation[0] == 'p')
3358  {
3359  ProtocolVersion pv;
3360 
3361  /*
3362  * Send the SSL request packet.
3363  *
3364  * Theoretically, this could block, but it really
3365  * shouldn't since we only got here if the socket is
3366  * write-ready.
3367  */
3369  if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
3370  {
3371  libpq_append_conn_error(conn, "could not send SSL negotiation packet: %s",
3372  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3373  goto error_return;
3374  }
3375  /* Ok, wait for response */
3377  return PGRES_POLLING_READING;
3378  }
3379  else
3380  {
3381  Assert(conn->sslnegotiation[0] == 'd');
3383  return PGRES_POLLING_WRITING;
3384  }
3385  }
3386 #endif /* USE_SSL */
3387 
3388  /*
3389  * For cancel requests this is as far as we need to go in the
3390  * connection establishment. Now we can actually send our
3391  * cancellation request.
3392  */
3393  if (conn->cancelRequest)
3394  {
3395  CancelRequestPacket cancelpacket;
3396 
3397  packetlen = sizeof(cancelpacket);
3399  cancelpacket.backendPID = pg_hton32(conn->be_pid);
3400  cancelpacket.cancelAuthCode = pg_hton32(conn->be_key);
3401  if (pqPacketSend(conn, 0, &cancelpacket, packetlen) != STATUS_OK)
3402  {
3403  libpq_append_conn_error(conn, "could not send cancel packet: %s",
3404  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3405  goto error_return;
3406  }
3408  return PGRES_POLLING_READING;
3409  }
3410 
3411  /*
3412  * We have now established encryption, or we are happy to
3413  * proceed without.
3414  */
3415 
3416  /* Build the startup packet. */
3417  startpacket = pqBuildStartupPacket3(conn, &packetlen,
3419  if (!startpacket)
3420  {
3421  libpq_append_conn_error(conn, "out of memory");
3422  goto error_return;
3423  }
3424 
3425  /*
3426  * Send the startup packet.
3427  *
3428  * Theoretically, this could block, but it really shouldn't
3429  * since we only got here if the socket is write-ready.
3430  */
3431  if (pqPacketSend(conn, 0, startpacket, packetlen) != STATUS_OK)
3432  {
3433  libpq_append_conn_error(conn, "could not send startup packet: %s",
3434  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3435  free(startpacket);
3436  goto error_return;
3437  }
3438 
3439  free(startpacket);
3440 
3442  return PGRES_POLLING_READING;
3443  }
3444 
3445  /*
3446  * Handle SSL negotiation: wait for postmaster messages and
3447  * respond as necessary.
3448  */
3450  {
3451 #ifdef USE_SSL
3452  PostgresPollingStatusType pollres;
3453 
3454  /*
3455  * On first time through with traditional SSL negotiation, get
3456  * the postmaster's response to our SSLRequest packet. With
3457  * sslnegotiation='direct', go straight to initiating SSL.
3458  */
3459  if (!conn->ssl_in_use && conn->sslnegotiation[0] == 'p')
3460  {
3461  /*
3462  * We use pqReadData here since it has the logic to
3463  * distinguish no-data-yet from connection closure. Since
3464  * conn->ssl isn't set, a plain recv() will occur.
3465  */
3466  char SSLok;
3467  int rdresult;
3468 
3469  rdresult = pqReadData(conn);
3470  if (rdresult < 0)
3471  {
3472  /* errorMessage is already filled in */
3473  goto error_return;
3474  }
3475  if (rdresult == 0)
3476  {
3477  /* caller failed to wait for data */
3478  return PGRES_POLLING_READING;
3479  }
3480  if (pqGetc(&SSLok, conn) < 0)
3481  {
3482  /* should not happen really */
3483  return PGRES_POLLING_READING;
3484  }
3485  if (SSLok == 'S')
3486  {
3487  if (conn->Pfdebug)
3488  pqTraceOutputCharResponse(conn, "SSLResponse",
3489  SSLok);
3490  /* mark byte consumed */
3491  conn->inStart = conn->inCursor;
3492  }
3493  else if (SSLok == 'N')
3494  {
3495  if (conn->Pfdebug)
3496  pqTraceOutputCharResponse(conn, "SSLResponse",
3497  SSLok);
3498  /* mark byte consumed */
3499  conn->inStart = conn->inCursor;
3500 
3501  /*
3502  * The connection is still valid, so if it's OK to
3503  * continue without SSL, we can proceed using this
3504  * connection. Otherwise return with an error.
3505  */
3506  ENCRYPTION_NEGOTIATION_FAILED(libpq_gettext("server does not support SSL, but SSL was required"));
3507  }
3508  else if (SSLok == 'E')
3509  {
3510  /*
3511  * Server failure of some sort, such as failure to
3512  * fork a backend process. We need to process and
3513  * report the error message, which might be formatted
3514  * according to either protocol 2 or protocol 3.
3515  * Rather than duplicate the code for that, we flip
3516  * into AWAITING_RESPONSE state and let the code there
3517  * deal with it. Note we have *not* consumed the "E"
3518  * byte here.
3519  */
3521 
3522  /*
3523  * Don't fall back to a plaintext connection after
3524  * reading the error.
3525  */
3527  goto keep_going;
3528  }
3529  else
3530  {
3531  libpq_append_conn_error(conn, "received invalid response to SSL negotiation: %c",
3532  SSLok);
3533  goto error_return;
3534  }
3535  }
3536 
3537  /*
3538  * Begin or continue the SSL negotiation process.
3539  */
3540  pollres = pqsecure_open_client(conn);
3541  if (pollres == PGRES_POLLING_OK)
3542  {
3543  /*
3544  * At this point we should have no data already buffered.
3545  * If we do, it was received before we performed the SSL
3546  * handshake, so it wasn't encrypted and indeed may have
3547  * been injected by a man-in-the-middle.
3548  */
3549  if (conn->inCursor != conn->inEnd)
3550  {
3551  libpq_append_conn_error(conn, "received unencrypted data after SSL response");
3552  goto error_return;
3553  }
3554 
3555  /* SSL handshake done, ready to send startup packet */
3557  return PGRES_POLLING_WRITING;
3558  }
3559  if (pollres == PGRES_POLLING_FAILED)
3560  {
3561  /*
3562  * SSL handshake failed. We will retry with a plaintext
3563  * connection, if permitted by sslmode.
3564  */
3566  }
3567  /* Else, return POLLING_READING or POLLING_WRITING status */
3568  return pollres;
3569 #else /* !USE_SSL */
3570  /* can't get here */
3571  goto error_return;
3572 #endif /* USE_SSL */
3573  }
3574 
3576  {
3577 #ifdef ENABLE_GSS
3578  PostgresPollingStatusType pollres;
3579 
3580  /*
3581  * If we haven't yet, get the postmaster's response to our
3582  * negotiation packet
3583  */
3584  if (!conn->gctx)
3585  {
3586  char gss_ok;
3587  int rdresult = pqReadData(conn);
3588 
3589  if (rdresult < 0)
3590  /* pqReadData fills in error message */
3591  goto error_return;
3592  else if (rdresult == 0)
3593  /* caller failed to wait for data */
3594  return PGRES_POLLING_READING;
3595  if (pqGetc(&gss_ok, conn) < 0)
3596  /* shouldn't happen... */
3597  return PGRES_POLLING_READING;
3598 
3599  if (gss_ok == 'E')
3600  {
3601  /*
3602  * Server failure of some sort, possibly protocol
3603  * version support failure. We need to process and
3604  * report the error message, which might be formatted
3605  * according to either protocol 2 or protocol 3.
3606  * Rather than duplicate the code for that, we flip
3607  * into AWAITING_RESPONSE state and let the code there
3608  * deal with it. Note we have *not* consumed the "E"
3609  * byte here.
3610  *
3611  * Note that unlike on an error response to
3612  * SSLRequest, we allow falling back to SSL or
3613  * plaintext connection here. GSS support was
3614  * introduced in PostgreSQL version 12, so an error
3615  * response might mean that we are connecting to a
3616  * pre-v12 server.
3617  */
3619  goto keep_going;
3620  }
3621 
3622  /* mark byte consumed */
3623  conn->inStart = conn->inCursor;
3624 
3625  if (gss_ok == 'N')
3626  {
3627  if (conn->Pfdebug)
3628  pqTraceOutputCharResponse(conn, "GSSENCResponse",
3629  gss_ok);
3630 
3631  /*
3632  * The connection is still valid, so if it's OK to
3633  * continue without GSS, we can proceed using this
3634  * connection. Otherwise return with an error.
3635  */
3636  ENCRYPTION_NEGOTIATION_FAILED(libpq_gettext("server doesn't support GSSAPI encryption, but it was required"));
3637  }
3638  else if (gss_ok != 'G')
3639  {
3640  libpq_append_conn_error(conn, "received invalid response to GSSAPI negotiation: %c",
3641  gss_ok);
3642  goto error_return;
3643  }
3644 
3645  if (conn->Pfdebug)
3646  pqTraceOutputCharResponse(conn, "GSSENCResponse",
3647  gss_ok);
3648  }
3649 
3650  /* Begin or continue GSSAPI negotiation */
3651  pollres = pqsecure_open_gss(conn);
3652  if (pollres == PGRES_POLLING_OK)
3653  {
3654  /*
3655  * At this point we should have no data already buffered.
3656  * If we do, it was received before we performed the GSS
3657  * handshake, so it wasn't encrypted and indeed may have
3658  * been injected by a man-in-the-middle.
3659  */
3660  if (conn->inCursor != conn->inEnd)
3661  {
3662  libpq_append_conn_error(conn, "received unencrypted data after GSSAPI encryption response");
3663  goto error_return;
3664  }
3665 
3666  /* All set for startup packet */
3668  return PGRES_POLLING_WRITING;
3669  }
3670  else if (pollres == PGRES_POLLING_FAILED)
3671  {
3672  /*
3673  * GSS handshake failed. We will retry with an SSL or
3674  * plaintext connection, if permitted by the options.
3675  */
3677  }
3678  /* Else, return POLLING_READING or POLLING_WRITING status */
3679  return pollres;
3680 #else /* !ENABLE_GSS */
3681  /* unreachable */
3682  goto error_return;
3683 #endif /* ENABLE_GSS */
3684  }
3685 
3686  /*
3687  * Handle authentication exchange: wait for postmaster messages
3688  * and respond as necessary.
3689  */
3691  {
3692  char beresp;
3693  int msgLength;
3694  int avail;
3695  AuthRequest areq;
3696  int res;
3697 
3698  /*
3699  * Scan the message from current point (note that if we find
3700  * the message is incomplete, we will return without advancing
3701  * inStart, and resume here next time).
3702  */
3703  conn->inCursor = conn->inStart;
3704 
3705  /* Read type byte */
3706  if (pqGetc(&beresp, conn))
3707  {
3708  /* We'll come back when there is more data */
3709  return PGRES_POLLING_READING;
3710  }
3711 
3712  /*
3713  * Validate message type: we expect only an authentication
3714  * request, NegotiateProtocolVersion, or an error here.
3715  * Anything else probably means it's not Postgres on the other
3716  * end at all.
3717  */
3718  if (beresp != PqMsg_AuthenticationRequest &&
3719  beresp != PqMsg_ErrorResponse &&
3721  {
3722  libpq_append_conn_error(conn, "expected authentication request from server, but received %c",
3723  beresp);
3724  goto error_return;
3725  }
3726 
3727  /* Read message length word */
3728  if (pqGetInt(&msgLength, 4, conn))
3729  {
3730  /* We'll come back when there is more data */
3731  return PGRES_POLLING_READING;
3732  }
3733 
3734  /*
3735  * Try to validate message length before using it.
3736  *
3737  * Authentication requests can't be very large, although GSS
3738  * auth requests may not be that small. Same for
3739  * NegotiateProtocolVersion.
3740  *
3741  * Errors can be a little larger, but not huge. If we see a
3742  * large apparent length in an error, it means we're really
3743  * talking to a pre-3.0-protocol server; cope. (Before
3744  * version 14, the server also used the old protocol for
3745  * errors that happened before processing the startup packet.)
3746  */
3747  if (beresp == PqMsg_AuthenticationRequest &&
3748  (msgLength < 8 || msgLength > 2000))
3749  {
3750  libpq_append_conn_error(conn, "received invalid authentication request");
3751  goto error_return;
3752  }
3753  if (beresp == PqMsg_NegotiateProtocolVersion &&
3754  (msgLength < 8 || msgLength > 2000))
3755  {
3756  libpq_append_conn_error(conn, "received invalid protocol negotiation message");
3757  goto error_return;
3758  }
3759 
3760 #define MAX_ERRLEN 30000
3761  if (beresp == PqMsg_ErrorResponse &&
3762  (msgLength < 8 || msgLength > MAX_ERRLEN))
3763  {
3764  /* Handle error from a pre-3.0 server */
3765  conn->inCursor = conn->inStart + 1; /* reread data */
3767  {
3768  /*
3769  * We may not have authenticated the server yet, so
3770  * don't let the buffer grow forever.
3771  */
3772  avail = conn->