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

Go to the source code of this file.

Data Structures

struct  _internalPQconninfoOption
 

Macros

#define PGPASSFILE   ".pgpass"
 
#define ERRCODE_APPNAME_UNKNOWN   "42704"
 
#define ERRCODE_INVALID_PASSWORD   "28P01"
 
#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"
 
#define DefaultHost   "localhost"
 
#define DefaultOption   ""
 
#define DefaultChannelBinding   "disable"
 
#define DefaultTargetSessionAttrs   "any"
 
#define DefaultLoadBalanceHosts   "disable"
 
#define DefaultSSLMode   "disable"
 
#define DefaultSSLCertMode   "disable"
 
#define 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 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:4395
PGconn * conn
Definition: streamutil.c:55

◆ DefaultChannelBinding

#define DefaultChannelBinding   "disable"

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

◆ DefaultGSSMode

#define DefaultGSSMode   "disable"

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

◆ DefaultHost

#define DefaultHost   "localhost"

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

◆ DefaultLoadBalanceHosts

#define DefaultLoadBalanceHosts   "disable"

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

◆ DefaultOption

#define DefaultOption   ""

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

◆ DefaultSSLCertMode

#define DefaultSSLCertMode   "disable"

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

◆ DefaultSSLMode

#define DefaultSSLMode   "disable"

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

◆ DefaultSSLNegotiation

#define DefaultSSLNegotiation   "postgres"

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

◆ DefaultTargetSessionAttrs

#define DefaultTargetSessionAttrs   "any"

Definition at line 123 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:69
@ PGRES_POLLING_WRITING
Definition: libpq-fe.h:91

◆ ERRCODE_APPNAME_UNKNOWN

#define ERRCODE_APPNAME_UNKNOWN   "42704"

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

◆ ERRCODE_CANNOT_CONNECT_NOW

#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"

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

◆ ERRCODE_INVALID_PASSWORD

#define ERRCODE_INVALID_PASSWORD   "28P01"

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

◆ MAX_ERRLEN

#define MAX_ERRLEN   30000

◆ PGPASSFILE

#define PGPASSFILE   ".pgpass"

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

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

2150 {
2151  char sebuf[PG_STRERROR_R_BUFLEN];
2152 
2154  "%s\n",
2155  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
2156 
2157  if (conn->raddr.addr.ss_family == AF_UNIX)
2158  libpq_append_conn_error(conn, "\tIs the server running locally and accepting connections on that socket?");
2159  else
2160  libpq_append_conn_error(conn, "\tIs the server running on that host and accepting TCP/IP connections?");
2161 }
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition: fe-misc.c:1357
#define SOCK_STRERROR
Definition: libpq-int.h:933
#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:633
SockAddr raddr
Definition: libpq-int.h:476

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

4396 {
4399 
4400  return select_next_encryption_method(conn, false);
4401 }
#define Assert(condition)
Definition: c.h:858
static bool select_next_encryption_method(PGconn *conn, bool have_valid_connection)
Definition: fe-connect.c:4410
uint8 failed_enc_methods
Definition: libpq-int.h:562
uint8 current_enc_method
Definition: libpq-int.h:563

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

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

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

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

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

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

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

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

Referenced by conninfo_getval(), and conninfo_storeval().

◆ conninfo_getval()

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

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

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

References conninfo_find(), and option::val.

Referenced by fillPGconn(), and parseServiceInfo().

◆ conninfo_init()

static PQconninfoOption * conninfo_init ( PQExpBuffer  errorMessage)
static

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

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

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

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

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

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

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

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

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

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

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

References input.

Referenced by pqConnectOptions2().

◆ default_threadlock()

static void default_threadlock ( int  acquire)
static

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

7758 {
7759  static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
7760 
7761  if (acquire)
7762  {
7763  if (pthread_mutex_lock(&singlethread_lock))
7764  Assert(false);
7765  }
7766  else
7767  {
7768  if (pthread_mutex_unlock(&singlethread_lock))
7769  Assert(false);
7770  }
7771 }
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 7388 of file fe-connect.c.

7389 {
7390  (void) arg; /* not used */
7391  /* Note: we expect the supplied string to end with a newline already. */
7392  fprintf(stderr, "%s", message);
7393 }
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 7373 of file fe-connect.c.

7374 {
7375  (void) arg; /* not used */
7376  if (res->noticeHooks.noticeProc != NULL)
7379 }
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 2093 of file fe-connect.c.

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

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

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

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

4649 {
4650  /* let any event procs clean up their state data */
4651  for (int i = 0; i < conn->nEvents; i++)
4652  {
4653  PGEventConnDestroy evt;
4654 
4655  evt.conn = conn;
4656  (void) conn->events[i].proc(PGEVT_CONNDESTROY, &evt,
4657  conn->events[i].passThrough);
4658  free(conn->events[i].name);
4659  }
4660 
4663 
4665  free(conn->events);
4666  free(conn->pghost);
4667  free(conn->pghostaddr);
4668  free(conn->pgport);
4671  free(conn->pgoptions);
4672  free(conn->appname);
4673  free(conn->fbappname);
4674  free(conn->dbName);
4675  free(conn->replication);
4676  free(conn->pguser);
4677  if (conn->pgpass)
4678  {
4679  explicit_bzero(conn->pgpass, strlen(conn->pgpass));
4680  free(conn->pgpass);
4681  }
4682  free(conn->pgpassfile);
4684  free(conn->keepalives);
4688  free(conn->sslmode);
4690  free(conn->sslcert);
4691  free(conn->sslkey);
4692  if (conn->sslpassword)
4693  {
4695  free(conn->sslpassword);
4696  }
4697  free(conn->sslcertmode);
4698  free(conn->sslrootcert);
4699  free(conn->sslcrl);
4700  free(conn->sslcrldir);
4702  free(conn->sslsni);
4703  free(conn->requirepeer);
4707  free(conn->gssencmode);
4708  free(conn->krbsrvname);
4709  free(conn->gsslib);
4711  free(conn->connip);
4712  /* Note that conn->Pfdebug is not ours to close or free */
4714  free(conn->inBuffer);
4715  free(conn->outBuffer);
4716  free(conn->rowBuf);
4721 
4722  free(conn);
4723 }
static void release_conn_addrinfo(PGconn *conn)
Definition: fe-connect.c:4798
void pqReleaseConnHosts(PGconn *conn)
Definition: fe-connect.c:4730
@ 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:384
char * write_err_msg
Definition: libpq-int.h:485
char * sslrootcert
Definition: libpq-int.h:403
PGdataValue * rowBuf
Definition: libpq-int.h:539
char * sslnegotiation
Definition: libpq-int.h:397
char * sslcompression
Definition: libpq-int.h:398
char * require_auth
Definition: libpq-int.h:416
char * inBuffer
Definition: libpq-int.h:522
char * channel_binding
Definition: libpq-int.h:388
char * sslcrldir
Definition: libpq-int.h:405
char * gssdelegation
Definition: libpq-int.h:412
char * pgoptions
Definition: libpq-int.h:380
char * sslcrl
Definition: libpq-int.h:404
char * pghost
Definition: libpq-int.h:367
char * ssl_max_protocol_version
Definition: libpq-int.h:414
char * pgpass
Definition: libpq-int.h:386
char * dbName
Definition: libpq-int.h:383
char * fbappname
Definition: libpq-int.h:382
char * sslcert
Definition: libpq-int.h:400
char * sslcertmode
Definition: libpq-int.h:402
char * target_session_attrs
Definition: libpq-int.h:415
char * sslpassword
Definition: libpq-int.h:401
PQExpBufferData workBuffer
Definition: libpq-int.h:637
char * keepalives_idle
Definition: libpq-int.h:391
char * connip
Definition: libpq-int.h:457
char * load_balance_hosts
Definition: libpq-int.h:417
char * pguser
Definition: libpq-int.h:385
char * keepalives
Definition: libpq-int.h:390
char * client_encoding_initial
Definition: libpq-int.h:379
char * keepalives_interval
Definition: libpq-int.h:392
char * appname
Definition: libpq-int.h:381
char * sslmode
Definition: libpq-int.h:396
char * pgtcp_user_timeout
Definition: libpq-int.h:378
char * ssl_min_protocol_version
Definition: libpq-int.h:413
char * gssencmode
Definition: libpq-int.h:408
int nEvents
Definition: libpq-int.h:432
char * pghostaddr
Definition: libpq-int.h:371
char * sslkey
Definition: libpq-int.h:399
char * pgpassfile
Definition: libpq-int.h:387
char * connect_timeout
Definition: libpq-int.h:377
char * krbsrvname
Definition: libpq-int.h:409
char * gsslib
Definition: libpq-int.h:410
char * pgport
Definition: libpq-int.h:375
char * keepalives_count
Definition: libpq-int.h:394
char * requirepeer
Definition: libpq-int.h:407
char * sslsni
Definition: libpq-int.h:406
PGEvent * events
Definition: libpq-int.h:431
char * outBuffer
Definition: libpq-int.h:529

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

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

References value.

Referenced by conninfo_uri_decode().

◆ getHostaddr()

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

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

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

4306 {
4307  if (conn->raddr.addr.ss_family == AF_UNIX)
4308  {
4309  /* Don't request SSL or GSSAPI over Unix sockets */
4311 
4312  /*
4313  * XXX: we probably should not do this. sslmode=require works
4314  * differently
4315  */
4316  if (conn->gssencmode[0] == 'r')
4317  {
4319  "GSSAPI encryption required but it is not supported over a local socket");
4322  return false;
4323  }
4324 
4327  return true;
4328  }
4329 
4330  /* initialize based on sslmode and gssencmode */
4332 
4333 #ifdef USE_SSL
4334  /* sslmode anything but 'disable', and GSSAPI not required */
4335  if (conn->sslmode[0] != 'd' && conn->gssencmode[0] != 'r')
4336  {
4338  }
4339 #endif
4340 
4341 #ifdef ENABLE_GSS
4342  if (conn->gssencmode[0] != 'd')
4344 #endif
4345 
4346  if ((conn->sslmode[0] == 'd' || conn->sslmode[0] == 'p' || conn->sslmode[0] == 'a') &&
4347  (conn->gssencmode[0] == 'd' || conn->gssencmode[0] == 'p'))
4348  {
4350  }
4351 
4352  return select_next_encryption_method(conn, false);
4353 }
#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:561

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

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

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

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

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

5815 {
5816  /* Parse as URI if connection string matches URI prefix */
5817  if (uri_prefix_length(connstr) != 0)
5818  return conninfo_uri_parse(connstr, errorMessage, use_defaults);
5819 
5820  /* Parse as default otherwise */
5821  return conninfo_parse(connstr, errorMessage, use_defaults);
5822 }
static PQconninfoOption * conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:6336
static PQconninfoOption * conninfo_parse(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5867
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 5574 of file fe-connect.c.

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

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

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

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

Referenced by pqConnectOptions2().

◆ pgpassfileWarning()

static void pgpassfileWarning ( PGconn conn)
static

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

7578 {
7579  /* If it was 'invalid authorization', add pgpassfile mention */
7580  /* only works with >= 9.0 servers */
7581  if (conn->password_needed &&
7582  conn->connhost[conn->whichhost].password != NULL &&
7583  conn->result)
7584  {
7585  const char *sqlstate = PQresultErrorField(conn->result,
7587 
7588  if (sqlstate && strcmp(sqlstate, ERRCODE_INVALID_PASSWORD) == 0)
7589  libpq_append_conn_error(conn, "password retrieved from file \"%s\"",
7590  conn->pgpassfile);
7591  }
7592 }
#define ERRCODE_INVALID_PASSWORD
Definition: fe-connect.c:89
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:355
PGresult * result
Definition: libpq-int.h:552
bool password_needed
Definition: libpq-int.h:480

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

7206 {
7207  if (!conn || conn->status != CONNECTION_OK)
7208  return 0;
7209  return conn->be_pid;
7210 }
@ CONNECTION_OK
Definition: libpq-fe.h:60
int be_pid
Definition: libpq-int.h:508

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

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

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

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

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

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

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

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

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

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

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

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

7223 {
7224  char *password;
7225 
7226  if (!conn)
7227  return false;
7228  password = PQpass(conn);
7229  if (conn->password_needed &&
7230  (password == NULL || password[0] == '\0'))
7231  return true;
7232  else
7233  return false;
7234 }
char * PQpass(const PGconn *conn)
Definition: fe-connect.c:7033

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

7249 {
7250  if (!conn)
7251  return false;
7252  if (conn->gssapi_used)
7253  return true;
7254  else
7255  return false;
7256 }
bool gssapi_used
Definition: libpq-int.h:481

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

7238 {
7239  if (!conn)
7240  return false;
7241  if (conn->password_needed)
7242  return true;
7243  else
7244  return false;
7245 }

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

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

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

2597 {
2598  bool reset_connection_state_machine = false;
2599  bool need_new_connection = false;
2600  PGresult *res;
2601  char sebuf[PG_STRERROR_R_BUFLEN];
2602  int optval;
2603 
2604  if (conn == NULL)
2605  return PGRES_POLLING_FAILED;
2606 
2607  /* Get the new data */
2608  switch (conn->status)
2609  {
2610  /*
2611  * We really shouldn't have been polled in these two cases, but we
2612  * can handle it.
2613  */
2614  case CONNECTION_BAD:
2615  return PGRES_POLLING_FAILED;
2616  case CONNECTION_OK:
2617  return PGRES_POLLING_OK;
2618 
2619  /* These are reading states */
2621  case CONNECTION_AUTH_OK:
2623  case CONNECTION_CONSUME:
2625  {
2626  /* Load waiting data */
2627  int n = pqReadData(conn);
2628 
2629  if (n < 0)
2630  goto error_return;
2631  if (n == 0)
2632  return PGRES_POLLING_READING;
2633 
2634  break;
2635  }
2636 
2637  /* These are writing states, so we just proceed. */
2638  case CONNECTION_STARTED:
2639  case CONNECTION_MADE:
2640  break;
2641 
2642  /* Special cases: proceed without waiting. */
2644  case CONNECTION_NEEDED:
2647  break;
2648 
2649  default:
2650  libpq_append_conn_error(conn, "invalid connection state, probably indicative of memory corruption");
2651  goto error_return;
2652  }
2653 
2654 
2655 keep_going: /* We will come back to here until there is
2656  * nothing left to do. */
2657 
2658  /* Time to advance to next address, or next host if no more addresses? */
2659  if (conn->try_next_addr)
2660  {
2661  if (conn->whichaddr < conn->naddr)
2662  {
2663  conn->whichaddr++;
2664  reset_connection_state_machine = true;
2665  }
2666  else
2667  conn->try_next_host = true;
2668  conn->try_next_addr = false;
2669  }
2670 
2671  /* Time to advance to next connhost[] entry? */
2672  if (conn->try_next_host)
2673  {
2674  pg_conn_host *ch;
2675  struct addrinfo hint;
2676  struct addrinfo *addrlist;
2677  int thisport;
2678  int ret;
2679  char portstr[MAXPGPATH];
2680 
2681  if (conn->whichhost + 1 < conn->nconnhost)
2682  conn->whichhost++;
2683  else
2684  {
2685  /*
2686  * Oops, no more hosts.
2687  *
2688  * If we are trying to connect in "prefer-standby" mode, then drop
2689  * the standby requirement and start over. Don't do this for
2690  * cancel requests though, since we are certain the list of
2691  * servers won't change as the target_server_type option is not
2692  * applicable to those connections.
2693  *
2694  * Otherwise, an appropriate error message is already set up, so
2695  * we just need to set the right status.
2696  */
2698  conn->nconnhost > 0 &&
2699  !conn->cancelRequest)
2700  {
2702  conn->whichhost = 0;
2703  }
2704  else
2705  goto error_return;
2706  }
2707 
2708  /* Drop any address info for previous host */
2710 
2711  /*
2712  * Look up info for the new host. On failure, log the problem in
2713  * conn->errorMessage, then loop around to try the next host. (Note
2714  * we don't clear try_next_host until we've succeeded.)
2715  */
2716  ch = &conn->connhost[conn->whichhost];
2717 
2718  /* Initialize hint structure */
2719  MemSet(&hint, 0, sizeof(hint));
2720  hint.ai_socktype = SOCK_STREAM;
2721  hint.ai_family = AF_UNSPEC;
2722 
2723  /* Figure out the port number we're going to use. */
2724  if (ch->port == NULL || ch->port[0] == '\0')
2725  thisport = DEF_PGPORT;
2726  else
2727  {
2728  if (!pqParseIntParam(ch->port, &thisport, conn, "port"))
2729  goto error_return;
2730 
2731  if (thisport < 1 || thisport > 65535)
2732  {
2733  libpq_append_conn_error(conn, "invalid port number: \"%s\"", ch->port);
2734  goto keep_going;
2735  }
2736  }
2737  snprintf(portstr, sizeof(portstr), "%d", thisport);
2738 
2739  /* Use pg_getaddrinfo_all() to resolve the address */
2740  switch (ch->type)
2741  {
2742  case CHT_HOST_NAME:
2743  ret = pg_getaddrinfo_all(ch->host, portstr, &hint,
2744  &addrlist);
2745  if (ret || !addrlist)
2746  {
2747  libpq_append_conn_error(conn, "could not translate host name \"%s\" to address: %s",
2748  ch->host, gai_strerror(ret));
2749  goto keep_going;
2750  }
2751  break;
2752 
2753  case CHT_HOST_ADDRESS:
2754  hint.ai_flags = AI_NUMERICHOST;
2755  ret = pg_getaddrinfo_all(ch->hostaddr, portstr, &hint,
2756  &addrlist);
2757  if (ret || !addrlist)
2758  {
2759  libpq_append_conn_error(conn, "could not parse network address \"%s\": %s",
2760  ch->hostaddr, gai_strerror(ret));
2761  goto keep_going;
2762  }
2763  break;
2764 
2765  case CHT_UNIX_SOCKET:
2766  hint.ai_family = AF_UNIX;
2767  UNIXSOCK_PATH(portstr, thisport, ch->host);
2768  if (strlen(portstr) >= UNIXSOCK_PATH_BUFLEN)
2769  {
2770  libpq_append_conn_error(conn, "Unix-domain socket path \"%s\" is too long (maximum %d bytes)",
2771  portstr,
2772  (int) (UNIXSOCK_PATH_BUFLEN - 1));
2773  goto keep_going;
2774  }
2775 
2776  /*
2777  * NULL hostname tells pg_getaddrinfo_all to parse the service
2778  * name as a Unix-domain socket path.
2779  */
2780  ret = pg_getaddrinfo_all(NULL, portstr, &hint,
2781  &addrlist);
2782  if (ret || !addrlist)
2783  {
2784  libpq_append_conn_error(conn, "could not translate Unix-domain socket path \"%s\" to address: %s",
2785  portstr, gai_strerror(ret));
2786  goto keep_going;
2787  }
2788  break;
2789  }
2790 
2791  /*
2792  * Store a copy of the addrlist in private memory so we can perform
2793  * randomization for load balancing.
2794  */
2795  ret = store_conn_addrinfo(conn, addrlist);
2796  pg_freeaddrinfo_all(hint.ai_family, addrlist);
2797  if (ret)
2798  goto error_return; /* message already logged */
2799 
2800  /*
2801  * If random load balancing is enabled we shuffle the addresses.
2802  */
2804  {
2805  /*
2806  * This is the "inside-out" variant of the Fisher-Yates shuffle
2807  * algorithm. Notionally, we append each new value to the array
2808  * and then swap it with a randomly-chosen array element (possibly
2809  * including itself, else we fail to generate permutations with
2810  * the last integer last). The swap step can be optimized by
2811  * combining it with the insertion.
2812  *
2813  * We don't need to initialize conn->prng_state here, because that
2814  * already happened in pqConnectOptions2.
2815  */
2816  for (int i = 1; i < conn->naddr; i++)
2817  {
2818  int j = pg_prng_uint64_range(&conn->prng_state, 0, i);
2819  AddrInfo temp = conn->addr[j];
2820 
2821  conn->addr[j] = conn->addr[i];
2822  conn->addr[i] = temp;
2823  }
2824  }
2825 
2826  reset_connection_state_machine = true;
2827  conn->try_next_host = false;
2828  }
2829 
2830  /* Reset connection state machine? */
2831  if (reset_connection_state_machine)
2832  {
2833  /*
2834  * (Re) initialize our connection control variables for a set of
2835  * connection attempts to a single server address. These variables
2836  * must persist across individual connection attempts, but we must
2837  * reset them when we start to consider a new server.
2838  */
2839  conn->pversion = PG_PROTOCOL(3, 0);
2840  conn->send_appname = true;
2841  conn->failed_enc_methods = 0;
2842  conn->current_enc_method = 0;
2844  reset_connection_state_machine = false;
2845  need_new_connection = true;
2846  }
2847 
2848  /* Force a new connection (perhaps to the same server as before)? */
2849  if (need_new_connection)
2850  {
2851  /* Drop any existing connection */
2852  pqDropConnection(conn, true);
2853 
2854  /* Reset all state obtained from old server */
2856 
2857  /* Drop any PGresult we might have, too */
2862 
2863  /* Reset conn->status to put the state machine in the right state */
2865 
2866  need_new_connection = false;
2867  }
2868 
2869  /*
2870  * Decide what to do next, if server rejects SSL or GSS negotiation, but
2871  * the connection is still valid. If there are no options left, error out
2872  * with 'msg'.
2873  */
2874 #define ENCRYPTION_NEGOTIATION_FAILED(msg) \
2875  do { \
2876  switch (encryption_negotiation_failed(conn)) \
2877  { \
2878  case 0: \
2879  libpq_append_conn_error(conn, (msg)); \
2880  goto error_return; \
2881  case 1: \
2882  conn->status = CONNECTION_MADE; \
2883  return PGRES_POLLING_WRITING; \
2884  case 2: \
2885  need_new_connection = true; \
2886  goto keep_going; \
2887  } \
2888  } while(0);
2889 
2890  /*
2891  * Decide what to do next, if connection fails. If there are no options
2892  * left, return with an error. The error message has already been written
2893  * to the connection's error buffer.
2894  */
2895 #define CONNECTION_FAILED() \
2896  do { \
2897  if (connection_failed(conn)) \
2898  { \
2899  need_new_connection = true; \
2900  goto keep_going; \
2901  } \
2902  else \
2903  goto error_return; \
2904  } while(0);
2905 
2906  /* Now try to advance the state machine for this connection */
2907  switch (conn->status)
2908  {
2909  case CONNECTION_NEEDED:
2910  {
2911  /*
2912  * Try to initiate a connection to one of the addresses
2913  * returned by pg_getaddrinfo_all(). conn->whichaddr is the
2914  * next one to try.
2915  *
2916  * The extra level of braces here is historical. It's not
2917  * worth reindenting this whole switch case to remove 'em.
2918  */
2919  {
2920  char host_addr[NI_MAXHOST];
2921  int sock_type;
2922  AddrInfo *addr_cur;
2923 
2924  /*
2925  * Advance to next possible host, if we've tried all of
2926  * the addresses for the current host.
2927  */
2928  if (conn->whichaddr == conn->naddr)
2929  {
2930  conn->try_next_host = true;
2931  goto keep_going;
2932  }
2933  addr_cur = &conn->addr[conn->whichaddr];
2934 
2935  /* Remember current address for possible use later */
2936  memcpy(&conn->raddr, &addr_cur->addr, sizeof(SockAddr));
2937 
2938 #ifdef ENABLE_GSS
2939 
2940  /*
2941  * Before establishing the connection, check if it's
2942  * doomed to fail because gssencmode='require' but GSSAPI
2943  * is not available.
2944  */
2945  if (conn->gssencmode[0] == 'r')
2946  {
2947  if (conn->raddr.addr.ss_family == AF_UNIX)
2948  {
2950  "GSSAPI encryption required but it is not supported over a local socket");
2951  goto error_return;
2952  }
2953  if (conn->gcred == GSS_C_NO_CREDENTIAL)
2954  {
2955  if (!pg_GSS_have_cred_cache(&conn->gcred))
2956  {
2958  "GSSAPI encryption required but no credential cache");
2959  goto error_return;
2960  }
2961  }
2962  }
2963 #endif
2964 
2965  /*
2966  * Choose the encryption method to try first. Do this
2967  * before establishing the connection, so that if none of
2968  * the modes allowed by the connections options are
2969  * available, we can error out before establishing the
2970  * connection.
2971  */
2973  goto error_return;
2974 
2975  /*
2976  * Set connip, too. Note we purposely ignore strdup
2977  * failure; not a big problem if it fails.
2978  */
2979  if (conn->connip != NULL)
2980  {
2981  free(conn->connip);
2982  conn->connip = NULL;
2983  }
2984  getHostaddr(conn, host_addr, NI_MAXHOST);
2985  if (host_addr[0])
2986  conn->connip = strdup(host_addr);
2987 
2988  /* Try to create the socket */
2989  sock_type = SOCK_STREAM;
2990 #ifdef SOCK_CLOEXEC
2991 
2992  /*
2993  * Atomically mark close-on-exec, if possible on this
2994  * platform, so that there isn't a window where a
2995  * subprogram executed by another thread inherits the
2996  * socket. See fallback code below.
2997  */
2998  sock_type |= SOCK_CLOEXEC;
2999 #endif
3000 #ifdef SOCK_NONBLOCK
3001 
3002  /*
3003  * We might as well skip a system call for nonblocking
3004  * mode too, if we can.
3005  */
3006  sock_type |= SOCK_NONBLOCK;
3007 #endif
3008  conn->sock = socket(addr_cur->family, sock_type, 0);
3009  if (conn->sock == PGINVALID_SOCKET)
3010  {
3011  int errorno = SOCK_ERRNO;
3012 
3013  /*
3014  * Silently ignore socket() failure if we have more
3015  * addresses to try; this reduces useless chatter in
3016  * cases where the address list includes both IPv4 and
3017  * IPv6 but kernel only accepts one family.
3018  */
3019  if (conn->whichaddr < conn->naddr ||
3020  conn->whichhost + 1 < conn->nconnhost)
3021  {
3022  conn->try_next_addr = true;
3023  goto keep_going;
3024  }
3025  emitHostIdentityInfo(conn, host_addr);
3026  libpq_append_conn_error(conn, "could not create socket: %s",
3027  SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
3028  goto error_return;
3029  }
3030 
3031  /*
3032  * Once we've identified a target address, all errors
3033  * except the preceding socket()-failure case should be
3034  * prefixed with host-identity information. (If the
3035  * connection succeeds, the contents of conn->errorMessage
3036  * won't matter, so this is harmless.)
3037  */
3038  emitHostIdentityInfo(conn, host_addr);
3039 
3040  /*
3041  * Select socket options: no delay of outgoing data for
3042  * TCP sockets, nonblock mode, close-on-exec. Try the
3043  * next address if any of this fails.
3044  */
3045  if (addr_cur->family != AF_UNIX)
3046  {
3047  if (!connectNoDelay(conn))
3048  {
3049  /* error message already created */
3050  conn->try_next_addr = true;
3051  goto keep_going;
3052  }
3053  }
3054 #ifndef SOCK_NONBLOCK
3055  if (!pg_set_noblock(conn->sock))
3056  {
3057  libpq_append_conn_error(conn, "could not set socket to nonblocking mode: %s",
3058  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3059  conn->try_next_addr = true;
3060  goto keep_going;
3061  }
3062 #endif
3063 
3064 #ifndef SOCK_CLOEXEC
3065 #ifdef F_SETFD
3066  if (fcntl(conn->sock, F_SETFD, FD_CLOEXEC) == -1)
3067  {
3068  libpq_append_conn_error(conn, "could not set socket to close-on-exec mode: %s",
3069  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3070  conn->try_next_addr = true;
3071  goto keep_going;
3072  }
3073 #endif /* F_SETFD */
3074 #endif
3075 
3076  if (addr_cur->family != AF_UNIX)
3077  {
3078 #ifndef WIN32
3079  int on = 1;
3080 #endif
3081  int usekeepalives = useKeepalives(conn);
3082  int err = 0;
3083 
3084  if (usekeepalives < 0)
3085  {
3086  libpq_append_conn_error(conn, "keepalives parameter must be an integer");
3087  err = 1;
3088  }
3089  else if (usekeepalives == 0)
3090  {
3091  /* Do nothing */
3092  }
3093 #ifndef WIN32
3094  else if (setsockopt(conn->sock,
3095  SOL_SOCKET, SO_KEEPALIVE,
3096  (char *) &on, sizeof(on)) < 0)
3097  {
3098  libpq_append_conn_error(conn, "%s(%s) failed: %s",
3099  "setsockopt",
3100  "SO_KEEPALIVE",
3101  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3102  err = 1;
3103  }
3104  else if (!setKeepalivesIdle(conn)
3106  || !setKeepalivesCount(conn))
3107  err = 1;
3108 #else /* WIN32 */
3109 #ifdef SIO_KEEPALIVE_VALS
3110  else if (!prepKeepalivesWin32(conn))
3111  err = 1;
3112 #endif /* SIO_KEEPALIVE_VALS */
3113 #endif /* WIN32 */
3114  else if (!setTCPUserTimeout(conn))
3115  err = 1;
3116 
3117  if (err)
3118  {
3119  conn->try_next_addr = true;
3120  goto keep_going;
3121  }
3122  }
3123 
3124  /*----------
3125  * We have three methods of blocking SIGPIPE during
3126  * send() calls to this socket:
3127  *
3128  * - setsockopt(sock, SO_NOSIGPIPE)
3129  * - send(sock, ..., MSG_NOSIGNAL)
3130  * - setting the signal mask to SIG_IGN during send()
3131  *
3132  * The third method requires three syscalls per send,
3133  * so we prefer either of the first two, but they are
3134  * less portable. The state is tracked in the following
3135  * members of PGconn:
3136  *
3137  * conn->sigpipe_so - we have set up SO_NOSIGPIPE
3138  * conn->sigpipe_flag - we're specifying MSG_NOSIGNAL
3139  *
3140  * If we can use SO_NOSIGPIPE, then set sigpipe_so here
3141  * and we're done. Otherwise, set sigpipe_flag so that
3142  * we will try MSG_NOSIGNAL on sends. If we get an error
3143  * with MSG_NOSIGNAL, we'll clear that flag and revert to
3144  * signal masking.
3145  *----------
3146  */
3147  conn->sigpipe_so = false;
3148 #ifdef MSG_NOSIGNAL
3149  conn->sigpipe_flag = true;
3150 #else
3151  conn->sigpipe_flag = false;
3152 #endif /* MSG_NOSIGNAL */
3153 
3154 #ifdef SO_NOSIGPIPE
3155  optval = 1;
3156  if (setsockopt(conn->sock, SOL_SOCKET, SO_NOSIGPIPE,
3157  (char *) &optval, sizeof(optval)) == 0)
3158  {
3159  conn->sigpipe_so = true;
3160  conn->sigpipe_flag = false;
3161  }
3162 #endif /* SO_NOSIGPIPE */
3163 
3164  /*
3165  * Start/make connection. This should not block, since we
3166  * are in nonblock mode. If it does, well, too bad.
3167  */
3168  if (connect(conn->sock, (struct sockaddr *) &addr_cur->addr.addr,
3169  addr_cur->addr.salen) < 0)
3170  {
3171  if (SOCK_ERRNO == EINPROGRESS ||
3172 #ifdef WIN32
3173  SOCK_ERRNO == EWOULDBLOCK ||
3174 #endif
3175  SOCK_ERRNO == EINTR)
3176  {
3177  /*
3178  * This is fine - we're in non-blocking mode, and
3179  * the connection is in progress. Tell caller to
3180  * wait for write-ready on socket.
3181  */
3183  return PGRES_POLLING_WRITING;
3184  }
3185  /* otherwise, trouble */
3186  }
3187  else
3188  {
3189  /*
3190  * Hm, we're connected already --- seems the "nonblock
3191  * connection" wasn't. Advance the state machine and
3192  * go do the next stuff.
3193  */
3195  goto keep_going;
3196  }
3197 
3198  /*
3199  * This connection failed. Add the error report to
3200  * conn->errorMessage, then try the next address if any.
3201  */
3203  conn->try_next_addr = true;
3204  goto keep_going;
3205  }
3206  }
3207 
3208  case CONNECTION_STARTED:
3209  {
3210  socklen_t optlen = sizeof(optval);
3211 
3212  /*
3213  * Write ready, since we've made it here, so the connection
3214  * has been made ... or has failed.
3215  */
3216 
3217  /*
3218  * Now check (using getsockopt) that there is not an error
3219  * state waiting for us on the socket.
3220  */
3221 
3222  if (getsockopt(conn->sock, SOL_SOCKET, SO_ERROR,
3223  (char *) &optval, &optlen) == -1)
3224  {
3225  libpq_append_conn_error(conn, "could not get socket error status: %s",
3226  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3227  goto error_return;
3228  }
3229  else if (optval != 0)
3230  {
3231  /*
3232  * When using a nonblocking connect, we will typically see
3233  * connect failures at this point, so provide a friendly
3234  * error message.
3235  */
3236  connectFailureMessage(conn, optval);
3237 
3238  /*
3239  * Try the next address if any, just as in the case where
3240  * connect() returned failure immediately.
3241  */
3242  conn->try_next_addr = true;
3243  goto keep_going;
3244  }
3245 
3246  /* Fill in the client address */
3247  conn->laddr.salen = sizeof(conn->laddr.addr);
3248  if (getsockname(conn->sock,
3249  (struct sockaddr *) &conn->laddr.addr,
3250  &conn->laddr.salen) < 0)
3251  {
3252  libpq_append_conn_error(conn, "could not get client address from socket: %s",
3253  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3254  goto error_return;
3255  }
3256 
3257  /*
3258  * Implement requirepeer check, if requested and it's a
3259  * Unix-domain socket.
3260  */
3261  if (conn->requirepeer && conn->requirepeer[0] &&
3262  conn->raddr.addr.ss_family == AF_UNIX)
3263  {
3264 #ifndef WIN32
3265  char *remote_username;
3266 #endif
3267  uid_t uid;
3268  gid_t gid;
3269 
3270  errno = 0;
3271  if (getpeereid(conn->sock, &uid, &gid) != 0)
3272  {
3273  /*
3274  * Provide special error message if getpeereid is a
3275  * stub
3276  */
3277  if (errno == ENOSYS)
3278  libpq_append_conn_error(conn, "requirepeer parameter is not supported on this platform");
3279  else
3280  libpq_append_conn_error(conn, "could not get peer credentials: %s",
3281  strerror_r(errno, sebuf, sizeof(sebuf)));
3282  goto error_return;
3283  }
3284 
3285 #ifndef WIN32
3286  remote_username = pg_fe_getusername(uid,
3287  &conn->errorMessage);
3288  if (remote_username == NULL)
3289  goto error_return; /* message already logged */
3290 
3291  if (strcmp(remote_username, conn->requirepeer) != 0)
3292  {
3293  libpq_append_conn_error(conn, "requirepeer specifies \"%s\", but actual peer user name is \"%s\"",
3294  conn->requirepeer, remote_username);
3295  free(remote_username);
3296  goto error_return;
3297  }
3298  free(remote_username);
3299 #else /* WIN32 */
3300  /* should have failed with ENOSYS above */
3301  Assert(false);
3302 #endif /* WIN32 */
3303  }
3304 
3305  /*
3306  * Make sure we can write before advancing to next step.
3307  */
3309  return PGRES_POLLING_WRITING;
3310  }
3311 
3312  case CONNECTION_MADE:
3313  {
3314  char *startpacket;
3315  int packetlen;
3316 
3317 #ifdef ENABLE_GSS
3318 
3319  /*
3320  * If GSSAPI encryption is enabled, send a packet to the
3321  * server asking for GSSAPI Encryption and proceed with GSSAPI
3322  * handshake. We will come back here after GSSAPI encryption
3323  * has been established, with conn->gctx set.
3324  */
3325  if (conn->current_enc_method == ENC_GSSAPI && !conn->gctx)
3326  {
3328 
3329  if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
3330  {
3331  libpq_append_conn_error(conn, "could not send GSSAPI negotiation packet: %s",
3332  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3333  goto error_return;
3334  }
3335 
3336  /* Ok, wait for response */
3338  return PGRES_POLLING_READING;
3339  }
3340 #endif
3341 
3342 #ifdef USE_SSL
3343 
3344  /*
3345  * Enable the libcrypto callbacks before checking if SSL needs
3346  * to be done. This is done before sending the startup packet
3347  * as depending on the type of authentication done, like MD5
3348  * or SCRAM that use cryptohashes, the callbacks would be
3349  * required even without a SSL connection
3350  */
3351  if (pqsecure_initialize(conn, false, true) < 0)
3352  goto error_return;
3353 
3354  /*
3355  * If SSL is enabled, start the SSL negotiation. We will come
3356  * back here after SSL encryption has been established, with
3357  * ssl_in_use set.
3358  */
3360  {
3361  /*
3362  * If traditional postgres SSL negotiation is used, send
3363  * the SSL request. In direct negotiation, jump straight
3364  * into the SSL handshake.
3365  */
3366  if (conn->sslnegotiation[0] == 'p')
3367  {
3368  ProtocolVersion pv;
3369 
3370  /*
3371  * Send the SSL request packet.
3372  *
3373  * Theoretically, this could block, but it really
3374  * shouldn't since we only got here if the socket is
3375  * write-ready.
3376  */
3378  if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
3379  {
3380  libpq_append_conn_error(conn, "could not send SSL negotiation packet: %s",
3381  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3382  goto error_return;
3383  }
3384  /* Ok, wait for response */
3386  return PGRES_POLLING_READING;
3387  }
3388  else
3389  {
3390  Assert(conn->sslnegotiation[0] == 'd');
3392  return PGRES_POLLING_WRITING;
3393  }
3394  }
3395 #endif /* USE_SSL */
3396 
3397  /*
3398  * For cancel requests this is as far as we need to go in the
3399  * connection establishment. Now we can actually send our
3400  * cancellation request.
3401  */
3402  if (conn->cancelRequest)
3403  {
3404  CancelRequestPacket cancelpacket;
3405 
3406  packetlen = sizeof(cancelpacket);
3408  cancelpacket.backendPID = pg_hton32(conn->be_pid);
3409  cancelpacket.cancelAuthCode = pg_hton32(conn->be_key);
3410  if (pqPacketSend(conn, 0, &cancelpacket, packetlen) != STATUS_OK)
3411  {
3412  libpq_append_conn_error(conn, "could not send cancel packet: %s",
3413  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3414  goto error_return;
3415  }
3417  return PGRES_POLLING_READING;
3418  }
3419 
3420  /*
3421  * We have now established encryption, or we are happy to
3422  * proceed without.
3423  */
3424 
3425  /* Build the startup packet. */
3426  startpacket = pqBuildStartupPacket3(conn, &packetlen,
3428  if (!startpacket)
3429  {
3430  libpq_append_conn_error(conn, "out of memory");
3431  goto error_return;
3432  }
3433 
3434  /*
3435  * Send the startup packet.
3436  *
3437  * Theoretically, this could block, but it really shouldn't
3438  * since we only got here if the socket is write-ready.
3439  */
3440  if (pqPacketSend(conn, 0, startpacket, packetlen) != STATUS_OK)
3441  {
3442  libpq_append_conn_error(conn, "could not send startup packet: %s",
3443  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3444  free(startpacket);
3445  goto error_return;
3446  }
3447 
3448  free(startpacket);
3449 
3451  return PGRES_POLLING_READING;
3452  }
3453 
3454  /*
3455  * Handle SSL negotiation: wait for postmaster messages and
3456  * respond as necessary.
3457  */
3459  {
3460 #ifdef USE_SSL
3461  PostgresPollingStatusType pollres;
3462 
3463  /*
3464  * On first time through with traditional SSL negotiation, get
3465  * the postmaster's response to our SSLRequest packet. With
3466  * sslnegotiation='direct', go straight to initiating SSL.
3467  */
3468  if (!conn->ssl_in_use && conn->sslnegotiation[0] == 'p')
3469  {
3470  /*
3471  * We use pqReadData here since it has the logic to
3472  * distinguish no-data-yet from connection closure. Since
3473  * conn->ssl isn't set, a plain recv() will occur.
3474  */
3475  char SSLok;
3476  int rdresult;
3477 
3478  rdresult = pqReadData(conn);
3479  if (rdresult < 0)
3480  {
3481  /* errorMessage is already filled in */
3482  goto error_return;
3483  }
3484  if (rdresult == 0)
3485  {
3486  /* caller failed to wait for data */
3487  return PGRES_POLLING_READING;
3488  }
3489  if (pqGetc(&SSLok, conn) < 0)
3490  {
3491  /* should not happen really */
3492  return PGRES_POLLING_READING;
3493  }
3494  if (SSLok == 'S')
3495  {
3496  /* mark byte consumed */
3497  conn->inStart = conn->inCursor;
3498  }
3499  else if (SSLok == 'N')
3500  {
3501  /* mark byte consumed */
3502  conn->inStart = conn->inCursor;
3503 
3504  /*
3505  * The connection is still valid, so if it's OK to
3506  * continue without SSL, we can proceed using this
3507  * connection. Otherwise return with an error.
3508  */
3509  ENCRYPTION_NEGOTIATION_FAILED(libpq_gettext("server does not support SSL, but SSL was required"));
3510  }
3511  else if (SSLok == 'E')
3512  {
3513  /*
3514  * Server failure of some sort, such as failure to
3515  * fork a backend process. We need to process and
3516  * report the error message, which might be formatted
3517  * according to either protocol 2 or protocol 3.
3518  * Rather than duplicate the code for that, we flip
3519  * into AWAITING_RESPONSE state and let the code there
3520  * deal with it. Note we have *not* consumed the "E"
3521  * byte here.
3522  */
3524 
3525  /*
3526  * Don't fall back to a plaintext connection after
3527  * reading the error.
3528  */
3530  goto keep_going;
3531  }
3532  else
3533  {
3534  libpq_append_conn_error(conn, "received invalid response to SSL negotiation: %c",
3535  SSLok);
3536  goto error_return;
3537  }
3538  }
3539 
3540  /*
3541  * Set up global SSL state if required. The crypto state has
3542  * already been set if libpq took care of doing that, so there
3543  * is no need to make that happen again.
3544  */
3545  if (pqsecure_initialize(conn, true, false) != 0)
3546  goto error_return;
3547 
3548  /*
3549  * Begin or continue the SSL negotiation process.
3550  */
3551  pollres = pqsecure_open_client(conn);
3552  if (pollres == PGRES_POLLING_OK)
3553  {
3554  /*
3555  * At this point we should have no data already buffered.
3556  * If we do, it was received before we performed the SSL
3557  * handshake, so it wasn't encrypted and indeed may have
3558  * been injected by a man-in-the-middle.
3559  */
3560  if (conn->inCursor != conn->inEnd)
3561  {
3562  libpq_append_conn_error(conn, "received unencrypted data after SSL response");
3563  goto error_return;
3564  }
3565 
3566  /* SSL handshake done, ready to send startup packet */
3568  return PGRES_POLLING_WRITING;
3569  }
3570  if (pollres == PGRES_POLLING_FAILED)
3571  {
3572  /*
3573  * SSL handshake failed. We will retry with a plaintext
3574  * connection, if permitted by sslmode.
3575  */
3577  }
3578  /* Else, return POLLING_READING or POLLING_WRITING status */
3579  return pollres;
3580 #else /* !USE_SSL */
3581  /* can't get here */
3582  goto error_return;
3583 #endif /* USE_SSL */
3584  }
3585 
3587  {
3588 #ifdef ENABLE_GSS
3589  PostgresPollingStatusType pollres;
3590 
3591  /*
3592  * If we haven't yet, get the postmaster's response to our
3593  * negotiation packet
3594  */
3595  if (!conn->gctx)
3596  {
3597  char gss_ok;
3598  int rdresult = pqReadData(conn);
3599 
3600  if (rdresult < 0)
3601  /* pqReadData fills in error message */
3602  goto error_return;
3603  else if (rdresult == 0)
3604  /* caller failed to wait for data */
3605  return PGRES_POLLING_READING;
3606  if (pqGetc(&gss_ok, conn) < 0)
3607  /* shouldn't happen... */
3608  return PGRES_POLLING_READING;
3609 
3610  if (gss_ok == 'E')
3611  {
3612  /*
3613  * Server failure of some sort, possibly protocol
3614  * version support failure. We need to process and
3615  * report the error message, which might be formatted
3616  * according to either protocol 2 or protocol 3.
3617  * Rather than duplicate the code for that, we flip
3618  * into AWAITING_RESPONSE state and let the code there
3619  * deal with it. Note we have *not* consumed the "E"
3620  * byte here.
3621  *
3622  * Note that unlike on an error response to
3623  * SSLRequest, we allow falling back to SSL or
3624  * plaintext connection here. GSS support was
3625  * introduced in PostgreSQL version 12, so an error
3626  * response might mean that we are connecting to a
3627  * pre-v12 server.
3628  */
3630  goto keep_going;
3631  }
3632 
3633  /* mark byte consumed */
3634  conn->inStart = conn->inCursor;
3635 
3636  if (gss_ok == 'N')
3637  {
3638  /*
3639  * The connection is still valid, so if it's OK to
3640  * continue without GSS, we can proceed using this
3641  * connection. Otherwise return with an error.
3642  */
3643  ENCRYPTION_NEGOTIATION_FAILED(libpq_gettext("server doesn't support GSSAPI encryption, but it was required"));
3644  }
3645  else if (gss_ok != 'G')
3646  {
3647  libpq_append_conn_error(conn, "received invalid response to GSSAPI negotiation: %c",
3648  gss_ok);
3649  goto error_return;
3650  }
3651  }
3652 
3653  /* Begin or continue GSSAPI negotiation */
3654  pollres = pqsecure_open_gss(conn);
3655  if (pollres == PGRES_POLLING_OK)
3656  {
3657  /*
3658  * At this point we should have no data already buffered.
3659  * If we do, it was received before we performed the GSS
3660  * handshake, so it wasn't encrypted and indeed may have
3661  * been injected by a man-in-the-middle.
3662  */
3663  if (conn->inCursor != conn->inEnd)
3664  {
3665  libpq_append_conn_error(conn, "received unencrypted data after GSSAPI encryption response");
3666  goto error_return;
3667  }
3668 
3669  /* All set for startup packet */
3671  return PGRES_POLLING_WRITING;
3672  }
3673  else if (pollres == PGRES_POLLING_FAILED)
3674  {
3675  /*
3676  * GSS handshake failed. We will retry with an SSL or
3677  * plaintext connection, if permitted by the options.
3678  */
3680  }
3681  /* Else, return POLLING_READING or POLLING_WRITING status */
3682  return pollres;
3683 #else /* !ENABLE_GSS */
3684  /* unreachable */
3685  goto error_return;
3686 #endif /* ENABLE_GSS */
3687  }
3688 
3689  /*
3690  * Handle authentication exchange: wait for postmaster messages
3691  * and respond as necessary.
3692  */
3694  {
3695  char beresp;
3696  int msgLength;
3697  int avail;
3698  AuthRequest areq;
3699  int res;
3700 
3701  /*
3702  * Scan the message from current point (note that if we find
3703  * the message is incomplete, we will return without advancing
3704  * inStart, and resume here next time).
3705  */
3706  conn->inCursor = conn->inStart;
3707 
3708  /* Read type byte */
3709  if (pqGetc(&beresp, conn))
3710  {
3711  /* We'll come back when there is more data */
3712  return PGRES_POLLING_READING;
3713  }
3714 
3715  /*
3716  * Validate message type: we expect only an authentication
3717  * request, NegotiateProtocolVersion, or an error here.
3718  * Anything else probably means it's not Postgres on the other
3719  * end at all.
3720  */
3721  if (beresp != PqMsg_AuthenticationRequest &&
3722  beresp != PqMsg_ErrorResponse &&
3724  {
3725  libpq_append_conn_error(conn, "expected authentication request from server, but received %c",
3726  beresp);
3727  goto error_return;
3728  }
3729 
3730  /* Read message length word */
3731  if (pqGetInt(&msgLength, 4, conn))
3732  {
3733  /* We'll come back when there is more data */
3734  return PGRES_POLLING_READING;
3735  }
3736 
3737  /*
3738  * Try to validate message length before using it.
3739  *
3740  * Authentication requests can't be very large, although GSS
3741  * auth requests may not be that small. Same for
3742  * NegotiateProtocolVersion.
3743  *
3744  * Errors can be a little larger, but not huge. If we see a
3745  * large apparent length in an error, it means we're really
3746  * talking to a pre-3.0-protocol server; cope. (Before
3747  * version 14, the server also used the old protocol for
3748  * errors that happened before processing the startup packet.)
3749  */
3750  if (beresp == PqMsg_AuthenticationRequest &&
3751  (msgLength < 8 || msgLength > 2000))
3752  {
3753  libpq_append_conn_error(conn, "received invalid authentication request");
3754  goto error_return;
3755  }
3756  if (beresp == PqMsg_NegotiateProtocolVersion &&
3757  (msgLength < 8 || msgLength > 2000))
3758  {
3759  libpq_append_conn_error(conn, "received invalid protocol negotiation message");
3760  goto error_return;
3761  }
3762 
3763 #define MAX_ERRLEN 30000
3764  if (beresp == PqMsg_ErrorResponse &&
3765  (msgLength < 8 || msgLength > MAX_ERRLEN))
3766  {
3767  /* Handle error from a pre-3.0 server */
3768  conn->inCursor = conn->inStart + 1; /* reread data */
3770  {
3771  /*
3772  * We may not have authenticated the server yet, so
3773  * don't let the buffer grow forever.
3774  */
3775  avail = conn->inEnd - conn->inCursor;
3776  if (avail > MAX_ERRLEN)
3777  {
3778  libpq_append_conn_error(conn, "received invalid error message");
3779  goto error_return;
3780  }
3781 
3782  /* We'll come back when there is more data */
3783  return PGRES_POLLING_READING;
3784  }
3785  /* OK, we read the message; mark data consumed */
3786  conn->inStart = conn->inCursor;
3787 
3788  /*
3789  * Before 7.2, the postmaster didn't always end its
3790  * messages with a newline, so add one if needed to
3791  * conform to libpq conventions.
3792  */
3793  if (conn->errorMessage.len == 0 ||
3794  conn->errorMessage.data[conn->errorMessage.len - 1] != '\n')
3795  {
3797  }
3798 
3799  goto error_return;
3800  }
3801 #undef MAX_ERRLEN
3802 
3803  /*
3804  * Can't process if message body isn't all here yet.
3805  *
3806  * After this check passes, any further EOF during parsing
3807  * implies that the server sent a bad/truncated message.
3808  * Reading more bytes won't help in that case, so don't return
3809  * PGRES_POLLING_READING after this point.
3810  */
3811  msgLength -= 4;
3812  avail = conn->inEnd - conn->inCursor;
3813  if (avail < msgLength)
3814  {
3815  /*
3816  * Before returning, try to enlarge the input buffer if
3817  * needed to hold the whole message; see notes in
3818  * pqParseInput3.
3819  */
3820  if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
3821  conn))
3822  goto error_return;
3823  /* We'll come back when there is more data */
3824  return PGRES_POLLING_READING;
3825  }
3826 
3827  /* Handle errors. */
3828  if (beresp == PqMsg_ErrorResponse)
3829  {
3830  if (pqGetErrorNotice3(conn, true))
3831  {
3832  libpq_append_conn_error(conn, "received invalid error message");
3833  goto error_return;
3834  }
3835  /* OK, we read the message; mark data consumed */
3836  conn->inStart = conn->inCursor;
3837 
3838  /*
3839  * If error is "cannot connect now", try the next host if
3840  * any (but we don't want to consider additional addresses
3841  * for this host, nor is there much point in changing SSL
3842  * or GSS mode). This is helpful when dealing with
3843  * standby servers that might not be in hot-standby state.
3844  */
3845  if (strcmp(conn->last_sqlstate,
3847  {
3848  conn->try_next_host = true;
3849  goto keep_going;
3850  }
3851 
3852  /* Check to see if we should mention pgpassfile */
3854 
3856  }
3857  else if (beresp == PqMsg_NegotiateProtocolVersion)
3858  {
3860  {
3861  libpq_append_conn_error(conn, "received invalid protocol negotiation message");
3862  goto error_return;
3863  }
3864  /* OK, we read the message; mark data consumed */
3865  conn->inStart = conn->inCursor;
3866  goto error_return;
3867  }
3868 
3869  /* It is an authentication request. */
3870  conn->auth_req_received = true;
3871 
3872  /* Get the type of request. */
3873  if (pqGetInt((int *) &areq, 4, conn))
3874  {
3875  /* can't happen because we checked the length already */
3876  libpq_append_conn_error(conn, "received invalid authentication request");
3877  goto error_return;
3878  }
3879  msgLength -= 4;
3880 
3881  /*
3882  * Process the rest of the authentication request message, and
3883  * respond to it if necessary.
3884  *
3885  * Note that conn->pghost must be non-NULL if we are going to
3886  * avoid the Kerberos code doing a hostname look-up.
3887  */
3888  res = pg_fe_sendauth(areq, msgLength, conn);
3889 
3890  /* OK, we have processed the message; mark data consumed */
3891  conn->inStart = conn->inCursor;
3892 
3893  if (res != STATUS_OK)
3894  goto error_return;
3895 
3896  /*
3897  * Just make sure that any data sent by pg_fe_sendauth is
3898  * flushed out. Although this theoretically could block, it
3899  * really shouldn't since we don't send large auth responses.
3900  */
3901  if (pqFlush(conn))
3902  goto error_return;
3903 
3904  if (areq == AUTH_REQ_OK)
3905  {
3906  /* We are done with authentication exchange */
3908 
3909  /*
3910  * Set asyncStatus so that PQgetResult will think that
3911  * what comes back next is the result of a query. See
3912  * below.
3913  */
3915  }
3916 
3917  /* Look to see if we have more data yet. */
3918  goto keep_going;
3919  }
3920 
3921  case CONNECTION_AUTH_OK:
3922  {
3923  /*
3924  * Now we expect to hear from the backend. A ReadyForQuery
3925  * message indicates that startup is successful, but we might
3926  * also get an Error message indicating failure. (Notice
3927  * messages indicating nonfatal warnings are also allowed by
3928  * the protocol, as are ParameterStatus and BackendKeyData
3929  * messages.) Easiest way to handle this is to let
3930  * PQgetResult() read the messages. We just have to fake it
3931  * out about the state of the connection, by setting
3932  * asyncStatus = PGASYNC_BUSY (done above).
3933  */
3934 
3935  if (PQisBusy(conn))
3936  return PGRES_POLLING_READING;
3937 
3938  res = PQgetResult(conn);
3939 
3940  /*
3941  * NULL return indicating we have gone to IDLE state is
3942  * expected
3943  */
3944  if (res)
3945  {
3947  libpq_append_conn_error(conn, "unexpected message from server during startup");
3948  else if (conn->send_appname &&
3949  (conn->appname || conn->fbappname))
3950  {
3951  /*
3952  * If we tried to send application_name, check to see
3953  * if the error is about that --- pre-9.0 servers will
3954  * reject it at this stage of the process. If so,
3955  * close the connection and retry without sending
3956  * application_name. We could possibly get a false
3957  * SQLSTATE match here and retry uselessly, but there
3958  * seems no great harm in that; we'll just get the
3959  * same error again if it's unrelated.
3960  */
3961  const char *sqlstate;
3962 
3964  if (sqlstate &&
3965  strcmp(sqlstate, ERRCODE_APPNAME_UNKNOWN) == 0)
3966  {
3967  PQclear(res);
3968  conn->send_appname = false;
3969  need_new_connection = true;
3970  goto keep_going;
3971  }
3972  }
3973 
3974  /*
3975  * if the resultStatus is FATAL, then conn->errorMessage
3976  * already has a copy of the error; needn't copy it back.
3977  * But add a newline if it's not there already, since
3978  * postmaster error messages may not have one.
3979  */
3980  if (conn->errorMessage.len <= 0 ||
3981  conn->errorMessage.data[conn->errorMessage.len - 1] != '\n')
3983  PQclear(res);
3984  goto error_return;
3985  }
3986 
3987  /* Almost there now ... */
3989  goto keep_going;
3990  }
3991 
3993  {
3994  /*
3995  * If a read-write, read-only, primary, or standby connection
3996  * is required, see if we have one.
3997  */
4000  {
4001  bool read_only_server;
4002 
4003  /*
4004  * If the server didn't report
4005  * "default_transaction_read_only" or "in_hot_standby" at
4006  * startup, we must determine its state by sending the
4007  * query "SHOW transaction_read_only". This GUC exists in
4008  * all server versions that support 3.0 protocol.
4009  */
4012  {
4013  /*
4014  * We use PQsendQueryContinue so that
4015  * conn->errorMessage does not get cleared. We need
4016  * to preserve any error messages related to previous
4017  * hosts we have tried and failed to connect to.
4018  */
4021  "SHOW transaction_read_only"))
4022  goto error_return;
4023  /* We'll return to this state when we have the answer */
4025  return PGRES_POLLING_READING;
4026  }
4027 
4028  /* OK, we can make the test */
4029  read_only_server =
4032 
4034  read_only_server : !read_only_server)
4035  {
4036  /* Wrong server state, reject and try the next host */
4038  libpq_append_conn_error(conn, "session is read-only");
4039  else
4040  libpq_append_conn_error(conn, "session is not read-only");
4041 
4042  /* Close connection politely. */
4045 
4046  /*
4047  * Try next host if any, but we don't want to consider
4048  * additional addresses for this host.
4049  */
4050  conn->try_next_host = true;
4051  goto keep_going;
4052  }
4053  }
4057  {
4058  /*
4059  * If the server didn't report "in_hot_standby" at
4060  * startup, we must determine its state by sending the
4061  * query "SELECT pg_catalog.pg_is_in_recovery()". Servers
4062  * before 9.0 don't have that function, but by the same
4063  * token they don't have any standby mode, so we may just
4064  * assume the result.
4065  */
4066  if (conn->sversion < 90000)
4068 
4070  {
4071  /*
4072  * We use PQsendQueryContinue so that
4073  * conn->errorMessage does not get cleared. We need
4074  * to preserve any error messages related to previous
4075  * hosts we have tried and failed to connect to.
4076  */
4079  "SELECT pg_catalog.pg_is_in_recovery()"))
4080  goto error_return;
4081  /* We'll return to this state when we have the answer */
4083  return PGRES_POLLING_READING;
4084  }
4085 
4086  /* OK, we can make the test */
4090  {
4091  /* Wrong server state, reject and try the next host */
4093  libpq_append_conn_error(conn, "server is in hot standby mode");
4094  else
4095  libpq_append_conn_error(conn, "server is not in hot standby mode");
4096 
4097  /* Close connection politely. */
4100 
4101  /*
4102  * Try next host if any, but we don't want to consider
4103  * additional addresses for this host.
4104  */
4105  conn->try_next_host = true;
4106  goto keep_going;
4107  }
4108  }
4109 
4110  /*
4111  * For non cancel requests we can release the address list
4112  * now. For cancel requests we never actually resolve
4113  * addresses and instead the addrinfo exists for the lifetime
4114  * of the connection.
4115  */
4116  if (!conn->cancelRequest)
4118 
4119  /*
4120  * Contents of conn->errorMessage are no longer interesting
4121  * (and it seems some clients expect it to be empty after a
4122  * successful connection).
4123  */
4125 
4126  /* We are open for business! */
4128  return PGRES_POLLING_OK;
4129  }
4130 
4131  case CONNECTION_CONSUME:
4132  {
4133  /*
4134  * This state just makes sure the connection is idle after
4135  * we've obtained the result of a SHOW or SELECT query. Once
4136  * we're clear, return to CONNECTION_CHECK_TARGET state to
4137  * decide what to do next. We must transiently set status =
4138  * CONNECTION_OK in order to use the result-consuming
4139  * subroutines.
4140  */
4142  if (!PQconsumeInput(conn))
4143  goto error_return;
4144 
4145  if (PQisBusy(conn))
4146  {
4148  return PGRES_POLLING_READING;
4149  }
4150 
4151  /* Call PQgetResult() again until we get a NULL result */
4152  res = PQgetResult(conn);
4153  if (res != NULL)
4154  {
4155  PQclear(res);
4157  return PGRES_POLLING_READING;
4158  }
4159 
4161  goto keep_going;
4162  }
4163 
4165  {
4166  /*
4167  * Waiting for result of "SHOW transaction_read_only". We
4168  * must transiently set status = CONNECTION_OK in order to use
4169  * the result-consuming subroutines.
4170  */
4172  if (!PQconsumeInput(conn))
4173  goto error_return;
4174 
4175  if (PQisBusy(conn))
4176  {
4178  return PGRES_POLLING_READING;
4179  }
4180 
4181  res = PQgetResult(conn);
4182  if (res && PQresultStatus(res) == PGRES_TUPLES_OK &&
4183  PQntuples(res) == 1)
4184  {
4185  char *val = PQgetvalue(res, 0, 0);
4186 
4187  /*
4188  * "transaction_read_only = on" proves that at least one
4189  * of default_transaction_read_only and in_hot_standby is
4190  * on, but we don't actually know which. We don't care
4191  * though for the purpose of identifying a read-only
4192  * session, so satisfy the CONNECTION_CHECK_TARGET code by
4193  * claiming they are both on. On the other hand, if it's
4194  * a read-write session, they are certainly both off.
4195  */
4196  if (strncmp(val, "on", 2) == 0)
4197  {
4200  }
4201  else
4202  {
4205  }
4206  PQclear(res);
4207 
4208  /* Finish reading messages before continuing */
4210  goto keep_going;
4211  }
4212 
4213  /* Something went wrong with "SHOW transaction_read_only". */
4214  PQclear(res);
4215 
4216  /* Append error report to conn->errorMessage. */
4217  libpq_append_conn_error(conn, "\"%s\" failed",
4218  "SHOW transaction_read_only");
4219 
4220  /* Close connection politely. */
4223 
4224  /* Try next host. */
4225  conn->try_next_host = true;
4226  goto keep_going;
4227  }
4228 
4230  {
4231  /*
4232  * Waiting for result of "SELECT pg_is_in_recovery()". We
4233  * must transiently set status = CONNECTION_OK in order to use
4234  * the result-consuming subroutines.
4235  */
4237  if (!PQconsumeInput(conn))
4238  goto error_return;
4239 
4240  if (PQisBusy(conn))
4241  {
4243  return PGRES_POLLING_READING;
4244  }
4245 
4246  res = PQgetResult(conn);
4247  if (res && PQresultStatus(res) == PGRES_TUPLES_OK &&
4248  PQntuples(res) == 1)
4249  {
4250  char *val = PQgetvalue(res, 0, 0);
4251 
4252  if (strncmp(val, "t", 1) == 0)
4254  else
4256  PQclear(res);
4257 
4258  /* Finish reading messages before continuing */
4260  goto keep_going;
4261  }
4262 
4263  /* Something went wrong with "SELECT pg_is_in_recovery()". */
4264  PQclear(res);
4265 
4266  /* Append error report to conn->errorMessage. */
4267  libpq_append_conn_error(conn, "\"%s\" failed",
4268  "SELECT pg_is_in_recovery()");
4269 
4270  /* Close connection politely. */
4273 
4274  /* Try next host. */
4275  conn->try_next_host = true;
4276  goto keep_going;
4277  }
4278 
4279  default:
4281  "invalid connection state %d, probably indicative of memory corruption",
4282  conn->status);
4283  goto error_return;
4284  }
4285 
4286  /* Unreachable */
4287 
4288 error_return:
4289 
4290  /*
4291  * We used to close the socket at this point, but that makes it awkward
4292  * for those above us if they wish to remove this socket from their own
4293  * records (an fd_set for example). We'll just have this socket closed
4294  * when PQfinish is called (which is compulsory even after an error, since
4295  * the connection structure must be freed).
4296  */
4298  return PGRES_POLLING_FAILED;
4299 }
#define STATUS_OK
Definition: c.h:1169
void err(int eval, const char *fmt,...)
Definition: err.c:43
int pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn)
Definition: fe-auth.c:961
char * pg_fe_getusername(uid_t user_id, PQExpBuffer errorMessage)
Definition: fe-auth.c:1169
#define MAX_ERRLEN
static const PQEnvironmentOption EnvironmentOptions[]
Definition: fe-connect.c:372
#define CONNECTION_FAILED()
static int setKeepalivesCount(PGconn *conn)
Definition: fe-connect.c:2256
static int useKeepalives(PGconn *conn)
Definition: fe-connect.c:2169
static int store_conn_addrinfo(PGconn *conn, struct addrinfo *addrlist)
Definition: fe-connect.c:4759
static void connectFailureMessage(PGconn *conn, int errorno)
Definition: fe-connect.c:2149
#define ERRCODE_APPNAME_UNKNOWN
Definition: fe-connect.c:86
static int setKeepalivesInterval(PGconn *conn)
Definition: fe-connect.c:2221
static int setKeepalivesIdle(PGconn *conn)
Definition: fe-connect.c:2187
static void pgpassfileWarning(PGconn *conn)
Definition: fe-connect.c:7577
static void emitHostIdentityInfo(PGconn *conn, const char *host_addr)
Definition: fe-connect.c:2093
static int setTCPUserTimeout(PGconn *conn)
Definition: fe-connect.c:2353
static int connectNoDelay(PGconn *conn)
Definition: fe-connect.c:2034
static void getHostaddr(PGconn *conn, char *host_addr, int host_addr_len)
Definition: fe-connect.c:2060
#define ENCRYPTION_NEGOTIATION_FAILED(msg)
static bool init_allowed_encryption_methods(PGconn *conn)
Definition: fe-connect.c:4305
int pqPacketSend(PGconn *conn, char pack_type, const void *buf, size_t buf_len)
Definition: fe-connect.c:5000
int PQsendQueryContinue(PGconn *conn, const char *query)
Definition: fe-exec.c:1422
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:3411
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3481
int PQconsumeInput(PGconn *conn)
Definition: fe-exec.c:1984
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3876
int PQisBusy(PGconn *conn)
Definition: fe-exec.c:2031
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:2062
bool pg_GSS_have_cred_cache(gss_cred_id_t *cred_out)
int pqReadData(PGconn *conn)
Definition: fe-misc.c:565
int pqFlush(PGconn *conn)
Definition: fe-misc.c:953
int pqGetc(char *result, PGconn *conn)
Definition: fe-misc.c:77
int pqGetInt(int *result, size_t bytes, PGconn *conn)
Definition: fe-misc.c:216
int pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn)
Definition: fe-misc.c:351
int pqGets_append(PQExpBuffer buf, PGconn *conn)
Definition: fe-misc.c:142
int pqGetNegotiateProtocolVersion3(PGconn *conn)
int pqGetErrorNotice3(PGconn *conn, bool isError)
Definition: fe-protocol3.c:882
char * pqBuildStartupPacket3(PGconn *conn, int *packetlen, const PQEnvironmentOption *options)
PostgresPollingStatusType pqsecure_open_gss(PGconn *conn)
PostgresPollingStatusType pqsecure_open_client(PGconn *conn)
Definition: fe-secure.c:153
int pqsecure_initialize(PGconn *conn, bool do_ssl, bool do_crypto)
Definition: fe-secure.c:138
void pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo *ai)
Definition: ip.c:82
int pg_getaddrinfo_all(const char *hostname, const char *servname, const struct addrinfo *hintp, struct addrinfo **result)
Definition: ip.c:53
@ CONNECTION_CONSUME
Definition: libpq-fe.h:78
@ CONNECTION_CHECK_STANDBY
Definition: libpq-fe.h:82
@ CONNECTION_STARTED
Definition: libpq-fe.h:68
@ CONNECTION_AWAITING_RESPONSE
Definition: libpq-fe.h:70
@ CONNECTION_CHECK_WRITABLE
Definition: libpq-fe.h:77
@ CONNECTION_GSS_STARTUP
Definition: libpq-fe.h:79
@ CONNECTION_SSL_STARTUP
Definition: libpq-fe.h:75
@ CONNECTION_AUTH_OK
Definition: libpq-fe.h:72
@ CONNECTION_CHECK_TARGET
Definition: libpq-fe.h:80
@ PGRES_FATAL_ERROR
Definition: libpq-fe.h:110
@ PGRES_TUPLES_OK
Definition: libpq-fe.h:102
@ PGRES_POLLING_FAILED
Definition: libpq-fe.h:89
@ PGASYNC_BUSY
Definition: libpq-int.h:222
@ PG_BOOL_YES
Definition: libpq-int.h:263
@ PG_BOOL_NO
Definition: libpq-int.h:264
@ PG_BOOL_UNKNOWN
Definition: libpq-int.h:262
#define pg_hton32(x)
Definition: pg_bswap.h:121
static char portstr[16]
Definition: pg_regress.c:117
bool pg_set_noblock(pgsocket sock)
Definition: noblock.c:25
unsigned int socklen_t
Definition: port.h:40
#define PGINVALID_SOCKET
Definition: port.h:31
#define strerror_r
Definition: port.h:255
int getpeereid(int sock, uid_t *uid, gid_t *gid)
Definition: getpeereid.c:33
#define CANCEL_REQUEST_CODE
Definition: pqcomm.h:132
#define UNIXSOCK_PATH(path, port, sockdir)
Definition: pqcomm.h:44
#define UNIXSOCK_PATH_BUFLEN
Definition: pqcomm.h:60
#define NEGOTIATE_GSS_CODE
Definition: pqcomm.h:167
#define NEGOTIATE_SSL_CODE
Definition: pqcomm.h:166
uint32 ProtocolVersion
Definition: pqcomm.h:99
uint32 AuthRequest
Definition: pqcomm.h:121
ProtocolVersion MsgType
Definition: pqcomm.h:101
#define PG_PROTOCOL(m, n)
Definition: pqcomm.h:89
#define AUTH_REQ_OK
Definition: protocol.h:74
#define PqMsg_AuthenticationRequest
Definition: protocol.h:50
#define PqMsg_NegotiateProtocolVersion
Definition: protocol.h:59
#define PqMsg_ErrorResponse
Definition: protocol.h:44
const char * gai_strerror(int ecode)
int family
Definition: pqcomm.h:38
SockAddr addr
Definition: pqcomm.h:39
MsgType cancelRequestCode
Definition: pqcomm.h:137
uint32 backendPID
Definition: pqcomm.h:138
uint32 cancelAuthCode
Definition: pqcomm.h:139
SockAddr laddr
Definition: libpq-int.h:475
AddrInfo * addr
Definition: libpq-int.h:503
bool sigpipe_flag
Definition: libpq-int.h:483
ProtocolVersion pversion
Definition: libpq-int.h:477
bool send_appname
Definition: libpq-int.h:505
PGTernaryBool in_hot_standby
Definition: libpq-int.h:514
int be_key
Definition: libpq-int.h:509
int naddr
Definition: libpq-int.h:501
int sversion
Definition: libpq-int.h:478
PGTernaryBool default_transaction_read_only
Definition: libpq-int.h:513
bool sigpipe_so
Definition: libpq-int.h:482
bool ssl_in_use
Definition: libpq-int.h:566
ExecStatusType resultStatus
Definition: libpq-int.h:180
#define EINTR
Definition: win32_port.h:374
#define EWOULDBLOCK
Definition: win32_port.h:380
#define EINPROGRESS
Definition: win32_port.h:386
int gid_t
Definition: win32_port.h:245
#define socket(af, type, protocol)
Definition: win32_port.h:495
#define connect(s, name, namelen)
Definition: win32_port.h:499
int uid_t
Definition: win32_port.h:244

References AddrInfo::addr, SockAddr::addr, pg_conn::addr, pg_conn::allowed_enc_methods, appendPQExpBufferChar(), pg_conn::appname, Assert, pg_conn::asyncStatus, AUTH_REQ_OK, pg_conn::auth_req_received, CancelRequestPacket::backendPID, pg_conn::be_key, pg_conn::be_pid, CANCEL_REQUEST_CODE, CancelRequestPacket::cancelAuthCode, pg_conn::cancelRequest, CancelRequestPacket::cancelRequestCode, CHT_HOST_ADDRESS, CHT_HOST_NAME, CHT_UNIX_SOCKET, conn, connect, connectFailureMessage(), CONNECTION_AUTH_OK, CONNECTION_AWAITING_RESPONSE, CONNECTION_BAD, CONNECTION_CHECK_STANDBY, CONNECTION_CHECK_TARGET, CONNECTION_CHECK_WRITABLE, CONNECTION_CONSUME, CONNECTION_FAILED, CONNECTION_GSS_STARTUP, CONNECTION_MADE, CONNECTION_NEEDED, CONNECTION_OK, CONNECTION_SSL_STARTUP, CONNECTION_STARTED, connectNoDelay(), pg_conn::connhost, pg_conn::connip, pg_conn::current_enc_method, PQExpBufferData::data, pg_conn::default_transaction_read_only, EINPROGRESS, EINTR, emitHostIdentityInfo(), ENC_GSSAPI, ENC_SSL, ENCRYPTION_NEGOTIATION_FAILED, EnvironmentOptions, err(), ERRCODE_APPNAME_UNKNOWN, ERRCODE_CANNOT_CONNECT_NOW, pg_conn::errorMessage, EWOULDBLOCK, pg_conn::failed_enc_methods, AddrInfo::family, pg_conn::fbappname, free, gai_strerror(), getHostaddr(), getpeereid(), pg_conn::gssencmode, pg_conn_host::host, pg_conn_host::hostaddr, i, pg_conn::in_hot_standby, pg_conn::inCursor, pg_conn::inEnd, init_allowed_encryption_methods(), pg_conn::inStart, j, pg_conn::laddr, pg_conn::last_sqlstate, PQExpBufferData::len, libpq_append_conn_error(), libpq_gettext, LOAD_BALANCE_RANDOM, pg_conn::load_balance_type, MAX_ERRLEN, MAXPGPATH, MemSet, pg_conn::naddr, pg_conn::nconnhost, NEGOTIATE_GSS_CODE, NEGOTIATE_SSL_CODE, PG_BOOL_NO, PG_BOOL_UNKNOWN, PG_BOOL_YES, PG_DIAG_SQLSTATE, pg_fe_getusername(), pg_fe_sendauth(), pg_freeaddrinfo_all(), pg_getaddrinfo_all(), pg_GSS_have_cred_cache(), pg_hton32, pg_prng_uint64_range(), PG_PROTOCOL, pg_set_noblock(), PG_STRERROR_R_BUFLEN, PGASYNC_BUSY, PGASYNC_IDLE, PGINVALID_SOCKET, pgpassfileWarning(), PGRES_FATAL_ERROR, PGRES_POLLING_FAILED, PGRES_POLLING_OK, PGRES_POLLING_READING, PGRES_POLLING_WRITING, PGRES_TUPLES_OK, pg_conn::pipelineStatus, pg_conn_host::port, portstr, PQ_PIPELINE_OFF, pqBuildStartupPacket3(), pqCheckInBufferSpace(), PQclear(), pqClearAsyncResult(), pqClearConnErrorState, PQconsumeInput(), pqDropConnection(), pqDropServerData(), pqFlush(), pqGetc(), pqGetErrorNotice3(), pqGetInt(), pqGetNegotiateProtocolVersion3(), PQgetResult(), pqGets_append(), PQgetvalue(), PQisBusy(), PqMsg_AuthenticationRequest, PqMsg_ErrorResponse, PqMsg_NegotiateProtocolVersion, PQntuples(), pqPacketSend(), pqParseIntParam(), pqReadData(), PQresultErrorField(), PQresultStatus(), pqsecure_initialize(), pqsecure_open_client(), pqsecure_open_gss(), PQsendQueryContinue(), PQTRANS_IDLE, pg_conn::prng_state, pg_conn::pversion, pg_conn::raddr, release_conn_addrinfo(), pg_conn::requirepeer, res, pg_result::resultStatus, SockAddr::salen, pg_conn::send_appname, sendTerminateConn(), SERVER_TYPE_PREFER_STANDBY, SERVER_TYPE_PREFER_STANDBY_PASS2, SERVER_TYPE_PRIMARY, SERVER_TYPE_READ_ONLY, SERVER_TYPE_READ_WRITE, SERVER_TYPE_STANDBY, setKeepalivesCount(), setKeepalivesIdle(), setKeepalivesInterval(), setTCPUserTimeout(), pg_conn::sigpipe_flag, pg_conn::sigpipe_so, snprintf, pg_conn::sock, SOCK_ERRNO, SOCK_STRERROR, socket, pg_conn::ssl_in_use, pg_conn::sslnegotiation, pg_conn::status, STATUS_OK, store_conn_addrinfo(), strerror_r, pg_conn::sversion, pg_conn::target_server_type, pg_conn::try_next_addr, pg_conn::try_next_host, pg_conn_host::type, UNIXSOCK_PATH, UNIXSOCK_PATH_BUFLEN, useKeepalives(), val, pg_conn::whichaddr, pg_conn::whichhost, and pg_conn::xactStatus.

Referenced by libpqrcv_connect(), libpqsrv_connect_internal(), PQcancelPoll(), pqConnectDBComplete(), pqConnectDBStart(), PQresetPoll(), and wait_until_connected().

◆ PQconnectStart()

PGconn* PQconnectStart ( const char *  conninfo)

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

873 {
874  PGconn *conn;
875 
876  /*
877  * Allocate memory for the conn structure. Note that we also expect this
878  * to initialize conn->errorMessage to empty. All subsequent steps during
879  * connection initialization will only append to that buffer.
880  */
882  if (conn == NULL)
883  return NULL;
884 
885  /*
886  * Parse the conninfo string
887  */
888  if (!connectOptions1(conn, conninfo))
889  return conn;
890 
891  /*
892  * Compute derived options
893  */
894  if (!pqConnectOptions2(conn))
895  return conn;
896 
897  /*
898  * Connect to the database
899  */
900  if (!pqConnectDBStart(conn))
901  {
902  /* Just in case we failed to set it in pqConnectDBStart */
904  }
905 
906  return conn;
907 }
static bool connectOptions1(PGconn *conn, const char *conninfo)
Definition: fe-connect.c:997
bool pqConnectOptions2(PGconn *conn)
Definition: fe-connect.c:1120
PGconn * pqMakeEmptyPGconn(void)
Definition: fe-connect.c:4549
int pqConnectDBStart(PGconn *conn)
Definition: fe-connect.c:2392

References conn, CONNECTION_BAD, connectOptions1(), pqConnectDBStart(), pqConnectOptions2(), pqMakeEmptyPGconn(), and pg_conn::status.

Referenced by libpqsrv_connect(), PQconnectdb(), and PQping().

◆ PQconnectStartParams()

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

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

794 {
795  PGconn *conn;
796  PQconninfoOption *connOptions;
797 
798  /*
799  * Allocate memory for the conn structure. Note that we also expect this
800  * to initialize conn->errorMessage to empty. All subsequent steps during
801  * connection initialization will only append to that buffer.
802  */
804  if (conn == NULL)
805  return NULL;
806 
807  /*
808  * Parse the conninfo arrays
809  */
810  connOptions = conninfo_array_parse(keywords, values,
811  &conn->errorMessage,
812  true, expand_dbname);
813  if (connOptions == NULL)
814  {
816  /* errorMessage is already set */
817  return conn;
818  }
819 
820  /*
821  * Move option values into conn structure
822  */
823  if (!fillPGconn(conn, connOptions))
824  {
825  PQconninfoFree(connOptions);
826  return conn;
827  }
828 
829  /*
830  * Free the option info - all is in conn now
831  */
832  PQconninfoFree(connOptions);
833 
834  /*
835  * Compute derived options
836  */
837  if (!pqConnectOptions2(conn))
838  return conn;
839 
840  /*
841  * Connect to the database
842  */
843  if (!pqConnectDBStart(conn))
844  {
845  /* Just in case we failed to set it in pqConnectDBStart */
847  }
848 
849  return conn;
850 }
static PQconninfoOption * conninfo_array_parse(const char *const *keywords, const char *const *values, PQExpBuffer errorMessage, bool use_defaults, int expand_dbname)
Definition: fe-connect.c:6043

References conn, CONNECTION_BAD, conninfo_array_parse(), pg_conn::errorMessage, fillPGconn(), pqConnectDBStart(), pqConnectOptions2(), PQconninfoFree(), pqMakeEmptyPGconn(), pg_conn::status, and values.

Referenced by do_connect(), libpqrcv_connect(), libpqsrv_connect_params(), PQconnectdbParams(), and PQpingParams().

◆ PQconninfo()

PQconninfoOption* PQconninfo ( PGconn conn)

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

6961 {
6962  PQExpBufferData errorBuf;
6963  PQconninfoOption *connOptions;
6964 
6965  if (conn == NULL)
6966  return NULL;
6967 
6968  /*
6969  * We don't actually report any errors here, but callees want a buffer,
6970  * and we prefer not to trash the conn's errorMessage.
6971  */
6972  initPQExpBuffer(&errorBuf);
6973  if (PQExpBufferDataBroken(errorBuf))
6974  return NULL; /* out of memory already :-( */
6975 
6976  connOptions = conninfo_init(&errorBuf);
6977 
6978  if (connOptions != NULL)
6979  {
6981 
6982  for (option = PQconninfoOptions; option->keyword; option++)
6983  {
6984  char **connmember;
6985 
6986  if (option->connofs < 0)
6987  continue;
6988 
6989  connmember = (char **) ((char *) conn + option->connofs);
6990 
6991  if (*connmember)
6992  conninfo_storeval(connOptions, option->keyword, *connmember,
6993  &errorBuf, true, false);
6994  }
6995  }
6996 
6997  termPQExpBuffer(&errorBuf);
6998 
6999  return connOptions;
7000 }

References conn, conninfo_init(), conninfo_storeval(), initPQExpBuffer(), PQconninfoOptions, PQExpBufferDataBroken, and termPQExpBuffer().

Referenced by copy_connection(), do_connect(), GenerateRecoveryConfig(), and libpqrcv_get_conninfo().

◆ PQconninfoFree()

◆ PQconninfoParse()

PQconninfoOption* PQconninfoParse ( const char *  conninfo,
char **  errmsg 
)

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

5753 {
5754  PQExpBufferData errorBuf;
5755  PQconninfoOption *connOptions;
5756 
5757  if (errmsg)
5758  *errmsg = NULL; /* default */
5759  initPQExpBuffer(&errorBuf);
5760  if (PQExpBufferDataBroken(errorBuf))
5761  return NULL; /* out of memory already :-( */
5762  connOptions = parse_connection_string(conninfo, &errorBuf, false);
5763  if (connOptions == NULL && errmsg)
5764  *errmsg = errorBuf.data;
5765  else
5766  termPQExpBuffer(&errorBuf);
5767  return connOptions;
5768 }
int errmsg(const char *fmt,...)
Definition: elog.c:1070

References PQExpBufferData::data, errmsg(), initPQExpBuffer(), parse_connection_string(), PQExpBufferDataBroken, and termPQExpBuffer().

Referenced by connectDatabase(), dblink_connstr_has_pw(), do_connect(), get_base_conninfo(), GetConnection(), GetDbnameFromConnectionOptions(), libpqrcv_check_conninfo(), libpqrcv_get_dbname_from_conninfo(), and main().

◆ pqCopyPGconn()

bool pqCopyPGconn ( PGconn srcConn,
PGconn dstConn 
)

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

957 {
959 
960  /* copy over connection options */
961  for (option = PQconninfoOptions; option->keyword; option++)
962  {
963  if (option->connofs >= 0)
964  {
965  const char **tmp = (const char **) ((char *) srcConn + option->connofs);
966 
967  if (*tmp)
968  {
969  char **dstConnmember = (char **) ((char *) dstConn + option->connofs);
970 
971  if (*dstConnmember)
972  free(*dstConnmember);
973  *dstConnmember = strdup(*tmp);
974  if (*dstConnmember == NULL)
975  {
976  libpq_append_conn_error(dstConn, "out of memory");
977  return false;
978  }
979  }
980  }
981  }
982  return true;
983 }

References free, libpq_append_conn_error(), and PQconninfoOptions.

Referenced by PQcancelCreate().

◆ PQdb()

◆ pqDropConnection()

void pqDropConnection ( PGconn conn,
bool  flushInput 
)

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

472 {
473  /* Drop any SSL state */
475 
476  /* Close the socket itself */
477  if (conn->sock != PGINVALID_SOCKET)
480 
481  /* Optionally discard any unread data */
482  if (flushInput)
483  conn->inStart = conn->inCursor = conn->inEnd = 0;
484 
485  /* Always discard any unsent data */
486  conn->outCount = 0;
487 
488  /* Likewise, discard any pending pipelined commands */
492  conn->cmd_queue_recycle = NULL;
493 
494  /* Free authentication/encryption state */
495 #ifdef ENABLE_GSS
496  {
497  OM_uint32 min_s;
498 
499  if (conn->gcred != GSS_C_NO_CREDENTIAL)
500  {
501  gss_release_cred(&min_s, &conn->gcred);
502  conn->gcred = GSS_C_NO_CREDENTIAL;
503  }
504  if (conn->gctx)
505  gss_delete_sec_context(&min_s, &conn->gctx, GSS_C_NO_BUFFER);
506  if (conn->gtarg_nam)
507  gss_release_name(&min_s, &conn->gtarg_nam);
508  if (conn->gss_SendBuffer)
509  {
510  free(conn->gss_SendBuffer);
511  conn->gss_SendBuffer = NULL;
512  }
513  if (conn->gss_RecvBuffer)
514  {
515  free(conn->gss_RecvBuffer);
516  conn->gss_RecvBuffer = NULL;
517  }
518  if (conn->gss_ResultBuffer)
519  {
520  free(conn->gss_ResultBuffer);
521  conn->gss_ResultBuffer = NULL;
522  }
523  conn->gssenc = false;
524  }
525 #endif
526 #ifdef ENABLE_SSPI
527  if (conn->sspitarget)
528  {
529  free(conn->sspitarget);
530  conn->sspitarget = NULL;
531  }
532  if (conn->sspicred)
533  {
534  FreeCredentialsHandle(conn->sspicred);
535  free(conn->sspicred);
536  conn->sspicred = NULL;
537  }
538  if (conn->sspictx)
539  {
540  DeleteSecurityContext(conn->sspictx);
541  free(conn->sspictx);
542  conn->sspictx = NULL;
543  }
544  conn->usesspi = 0;
545 #endif
546  if (conn->sasl_state)
547  {
549  conn->sasl_state = NULL;
550  }
551 }
static void pqFreeCommandQueue(PGcmdQueueEntry *queue)
Definition: fe-connect.c:558
void pqsecure_close(PGconn *conn)
Definition: fe-secure.c:167
#define closesocket
Definition: port.h:349
const pg_fe_sasl_mech * sasl
Definition: libpq-int.h:557
PGcmdQueueEntry * cmd_queue_recycle
Definition: libpq-int.h:470
PGcmdQueueEntry * cmd_queue_tail
Definition: libpq-int.h:464
void * sasl_state
Definition: libpq-int.h:558
PGcmdQueueEntry * cmd_queue_head
Definition: libpq-int.h:463
void(* free)(void *state)
Definition: fe-auth-sasl.h:140

References closesocket, pg_conn::cmd_queue_head, pg_conn::cmd_queue_recycle, pg_conn::cmd_queue_tail, conn, free, pg_fe_sasl_mech::free, pg_conn::inCursor, pg_conn::inEnd, pg_conn::inStart, pg_conn::outCount, PGINVALID_SOCKET, pqFreeCommandQueue(), pqsecure_close(), pg_conn::sasl, pg_conn::sasl_state, and pg_conn::sock.

Referenced by handleSyncLoss(), pqClosePGconn(), pqConnectDBStart(), PQconnectPoll(), and pqReadData().

◆ pqDropServerData()

static void pqDropServerData ( PGconn conn)
static

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

585 {
586  PGnotify *notify;
587  pgParameterStatus *pstatus;
588 
589  /* Forget pending notifies */
590  notify = conn->notifyHead;
591  while (notify != NULL)
592  {
593  PGnotify *prev = notify;
594 
595  notify = notify->next;
596  free(prev);
597  }
598  conn->notifyHead = conn->notifyTail = NULL;
599 
600  /* Reset ParameterStatus data, as well as variables deduced from it */
601  pstatus = conn->pstatus;
602  while (pstatus != NULL)
603  {
604  pgParameterStatus *prev = pstatus;
605 
606  pstatus = pstatus->next;
607  free(prev);
608  }
609  conn->pstatus = NULL;
611  conn->std_strings = false;
615  conn->sversion = 0;
616 
617  /* Drop large-object lookup data */
618  free(conn->lobjfuncs);
619  conn->lobjfuncs = NULL;
620 
621  /* Reset assorted other per-connection state */
622  conn->last_sqlstate[0] = '\0';
623  conn->auth_req_received = false;
624  conn->client_finished_auth = false;
625  conn->password_needed = false;
626  conn->gssapi_used = false;
627  conn->write_failed = false;
629  conn->write_err_msg = NULL;
630 
631  /*
632  * Cancel connections need to retain their be_pid and be_key across
633  * PQcancelReset invocations, otherwise they would not have access to the
634  * secret token of the connection they are supposed to cancel.
635  */
636  if (!conn->cancelRequest)
637  {
638  conn->be_pid = 0;
639  conn->be_key = 0;
640  }
641 }
@ PG_SQL_ASCII
Definition: pg_wchar.h:226
#define SCRAM_SHA_256_DEFAULT_ITERATIONS
Definition: scram-common.h:50
struct pgNotify * next
Definition: libpq-fe.h:201
struct pgParameterStatus * next
Definition: libpq-int.h:277
PGnotify * notifyHead
Definition: libpq-int.h:450
bool std_strings
Definition: libpq-int.h:512
bool write_failed
Definition: libpq-int.h:484
bool client_finished_auth
Definition: libpq-int.h:491
PGnotify * notifyTail
Definition: libpq-int.h:451
pgParameterStatus * pstatus
Definition: libpq-int.h:510
int scram_sha_256_iterations
Definition: libpq-int.h:559
PGlobjfuncs * lobjfuncs
Definition: libpq-int.h:517

References pg_conn::auth_req_received, pg_conn::be_key, pg_conn::be_pid, pg_conn::cancelRequest, pg_conn::client_encoding, pg_conn::client_finished_auth, conn, pg_conn::default_transaction_read_only, free, pg_conn::gssapi_used, pg_conn::in_hot_standby, pg_conn::last_sqlstate, pg_conn::lobjfuncs, pgNotify::next, pgParameterStatus::next, pg_conn::notifyHead, pg_conn::notifyTail, pg_conn::password_needed, PG_BOOL_UNKNOWN, PG_SQL_ASCII, pg_conn::pstatus, SCRAM_SHA_256_DEFAULT_ITERATIONS, pg_conn::scram_sha_256_iterations, pg_conn::std_strings, pg_conn::sversion, pg_conn::write_err_msg, and pg_conn::write_failed.

Referenced by pqClosePGconn(), and PQconnectPoll().

◆ PQerrorMessage()

char* PQerrorMessage ( const PGconn conn)

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

7172 {
7173  if (!conn)
7174  return libpq_gettext("connection pointer is NULL\n");
7175 
7176  /*
7177  * The errorMessage buffer might be marked "broken" due to having
7178  * previously failed to allocate enough memory for the message. In that
7179  * case, tell the application we ran out of memory.
7180  */
7182  return libpq_gettext("out of memory\n");
7183 
7184  return conn->errorMessage.data;
7185 }
#define PQExpBufferBroken(str)
Definition: pqexpbuffer.h:59

References conn, PQExpBufferData::data, pg_conn::errorMessage, libpq_gettext, and PQExpBufferBroken.

Referenced by _doSetSessionAuth(), _printTableAccessMethodNoStorage(), _selectOutputSchema(), _selectTableAccessMethod(), _selectTablespace(), AcceptResult(), advanceConnectionState(), BaseBackup(), check_loadable_libraries(), check_prepare_conn(), CheckCopyStreamStop(), cluster_one_database(), compile_database_list(), compile_relation_list_one_db(), confirm_query_canceled_impl(), connect_database(), connect_pg_server(), ConnectDatabase(), connectDatabase(), connectToServer(), copy_connection(), CopyStreamPoll(), CopyStreamReceive(), CreateReplicationSlot(), dblink_connect(), dblink_error_message(), dblink_get_conn(), dblink_res_error(), dblink_send_query(), DescribeQuery(), die_on_query_failure(), do_connect(), do_lo_export(), do_lo_import(), do_lo_unlink(), doConnect(), DropReplicationSlot(), dump_lo_buf(), dumpLOs(), dumpTableData_copy(), ecpg_check_PQresult(), ecpg_raise_backend(), ECPGconnect(), EndDBCopyMode(), exec_command_password(), ExecQueryAndProcessResults(), executeCommand(), executeQuery(), executeQueryOrDie(), ExecuteSqlCommand(), ExecuteSqlCommandBuf(), executeStatement(), GetConnection(), GetSlotInformation(), GetTableInfo(), handleCopyIn(), handleCopyOut(), HandleEndOfCopyStream(), initPopulateTable(), libpqrcv_alter_slot(), libpqrcv_connect(), libpqrcv_create_slot(), libpqrcv_endstreaming(), libpqrcv_exec(), libpqrcv_identify_system(), libpqrcv_readtimelinehistoryfile(), libpqrcv_receive(), libpqrcv_send(), libpqrcv_startstreaming(), main(), my_truncate(), overwrite(), pgfdw_cancel_query_end(), pgfdw_report_error(), pickout(), PQcancelErrorMessage(), prepareCommand(), process_queued_fetch_requests(), process_result(), ProcessXLogDataMsg(), psql_get_variable(), readCommandResponse(), ReceiveCopyData(), RetrieveDataDirCreatePerm(), RetrieveWalSegSize(), run_command(), run_permutation(), run_reindex_command(), run_vacuum_command(), RunIdentifySystem(), send_cancellable_query_impl(), sendFeedback(), SendQuery(), sql_conn(), sql_exec(), start_postmaster(), StartRestoreLO(), storeQueryResult(), StreamLogicalLog(), TableCommandResultHandler(), test_cancel(), test_disallowed_in_pipeline(), test_multi_pipelines(), test_nosync(), test_pipeline_abort(), test_pipeline_idle(), test_pipelined_insert(), test_prepared(), test_simple_pipeline(), test_singlerowmode(), test_transaction(), test_uniqviol(), threadRun(), try_complete_step(), tryExecuteStatement(), vacuumlo(), verify_btree_slot_handler(), verify_heap_slot_handler(), and wait_for_connection_state().

◆ PQfinish()

void PQfinish ( PGconn conn)

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

4893 {
4894  if (conn)
4895  {
4897  freePGconn(conn);
4898  }
4899 }
void pqClosePGconn(PGconn *conn)
Definition: fe-connect.c:4846
static void freePGconn(PGconn *conn)
Definition: fe-connect.c:4648

References conn, freePGconn(), and pqClosePGconn().

Referenced by appendQualifiedRelation(), BaseBackup(), check_for_data_types_usage(), check_for_incompatible_polymorphics(), check_for_isn_and_int8_passing_mismatch(), check_for_pg_role_prefix(), check_for_prepared_transactions(), check_for_tables_with_oids(), check_for_user_defined_encoding_conversions(), check_for_user_defined_postfix_ops(), check_is_install_user(), check_loadable_libraries(), check_new_cluster_logical_replication_slots(), check_new_cluster_subscription_configuration(), check_old_cluster_subscription_state(), check_proper_datallowconn(), CheckConnection(), cluster_all_databases(), cluster_one_database(), connect_database(), ConnectDatabase(), connectDatabase(), connectToServer(), create_logical_replication_slots(), create_new_objects(), disconnect_atexit(), disconnect_database(), DisconnectDatabase(), disconnectDatabase(), do_connect(), doConnect(), dumpRoleGUCPrivs(), dumpRoleMembership(), dumpTablespaces(), ecpg_finish(), executeCommand(), executeQuery(), executeQueryOrDie(), exit_nicely(), expand_dbname_patterns(), finishCon(), get_db_infos(), get_loadable_libraries(), get_old_cluster_logical_slot_infos(), get_parallel_object_list(), get_rel_infos(), get_subscription_count(), get_tablespace_paths(), get_template0_info(), GetConnection(), libpqrcv_connect(), libpqrcv_disconnect(), libpqsrv_connect_internal(), libpqsrv_disconnect(), LogStreamerMain(), main(), old_9_6_invalidate_hash_indexes(), PQcancelFinish(), PQping(), PQpingParams(), ReconnectToServer(), reindex_all_databases(), reindex_one_database(), report_extension_updates(), run_reindex_command(), runInitSteps(), set_frozenxids(), set_locale_and_encoding(), sql_conn(), sql_exec(), start_postmaster(), StreamLog(), StreamLogicalLog(), vacuum_all_databases(), vacuum_one_database(), and vacuumlo().

◆ pqFreeCommandQueue()

static void pqFreeCommandQueue ( PGcmdQueueEntry queue)
static

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

559 {
560  while (queue != NULL)
561  {
562  PGcmdQueueEntry *cur = queue;
563 
564  queue = cur->next;
565  free(cur->query);
566  free(cur);
567  }
568 }
struct cursor * cur
Definition: ecpg.c:28
struct cursor * next
Definition: type.h:147

References cur, free, and cursor::next.

Referenced by pqDropConnection().

◆ pqGetHomeDirectory()

bool pqGetHomeDirectory ( char *  buf,
int  bufsize 
)

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

7680 {
7681 #ifndef WIN32
7682  const char *home;
7683 
7684  home = getenv("HOME");
7685  if (home == NULL || home[0] == '\0')
7686  return pg_get_user_home_dir(geteuid(), buf, bufsize);
7687  strlcpy(buf, home, bufsize);
7688  return true;
7689 #else
7690  char tmppath[MAX_PATH];
7691 
7692  ZeroMemory(tmppath, sizeof(tmppath));
7693  if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, tmppath) != S_OK)
7694  return false;
7695  snprintf(buf, bufsize, "%s/postgresql", tmppath);
7696  return true;
7697 #endif
7698 }
#define bufsize
Definition: indent_globs.h:36
bool pg_get_user_home_dir(uid_t user_id, char *buffer, size_t buflen)
Definition: user.c:64

References buf, bufsize, pg_get_user_home_dir(), snprintf, and strlcpy().

Referenced by initialize_SSL(), parseServiceInfo(), and pqConnectOptions2().

◆ PQhost()

char* PQhost ( const PGconn conn)

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

7051 {
7052  if (!conn)
7053  return NULL;
7054 
7055  if (conn->connhost != NULL)
7056  {
7057  /*
7058  * Return the verbatim host value provided by user, or hostaddr in its
7059  * lack.
7060  */
7061  if (conn->connhost[conn->whichhost].host != NULL &&
7062  conn->connhost[conn->whichhost].host[0] != '\0')
7063  return conn->connhost[conn->whichhost].host;
7064  else if (conn->connhost[conn->whichhost].hostaddr != NULL &&
7065  conn->connhost[conn->whichhost].hostaddr[0] != '\0')
7066  return conn->connhost[conn->whichhost].hostaddr;
7067  }
7068 
7069  return "";
7070 }

References conn, pg_conn::connhost, pg_conn_host::host, pg_conn_host::hostaddr, and pg_conn::whichhost.

Referenced by do_connect(), exec_command_conninfo(), get_prompt(), libpqrcv_get_senderinfo(), main(), pg_GSS_load_servicename(), and SyncVariables().

◆ PQhostaddr()

char* PQhostaddr ( const PGconn conn)

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

7074 {
7075  if (!conn)
7076  return NULL;
7077 
7078  /* Return the parsed IP address */
7079  if (conn->connhost != NULL && conn->connip != NULL)
7080  return conn->connip;
7081 
7082  return "";
7083 }

References conn, pg_conn::connhost, and pg_conn::connip.

Referenced by do_connect(), and exec_command_conninfo().

◆ pqMakeEmptyPGconn()

PGconn* pqMakeEmptyPGconn ( void  )

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

4550 {
4551  PGconn *conn;
4552 
4553 #ifdef WIN32
4554 
4555  /*
4556  * Make sure socket support is up and running in this process.
4557  *
4558  * Note: the Windows documentation says that we should eventually do a
4559  * matching WSACleanup() call, but experience suggests that that is at
4560  * least as likely to cause problems as fix them. So we don't.
4561  */
4562  static bool wsastartup_done = false;
4563 
4564  if (!wsastartup_done)
4565  {
4566  WSADATA wsaData;
4567 
4568  if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
4569  return NULL;
4570  wsastartup_done = true;
4571  }
4572 
4573  /* Forget any earlier error */
4574  WSASetLastError(0);
4575 #endif /* WIN32 */
4576 
4577  conn = (PGconn *) malloc(sizeof(PGconn));
4578  if (conn == NULL)
4579  return conn;
4580 
4581  /* Zero all pointers and booleans */
4582  MemSet(conn, 0, sizeof(PGconn));
4583 
4584  /* install default notice hooks */
4587 
4592  conn->options_valid = false;
4593  conn->nonblocking = false;
4595  conn->std_strings = false; /* unless server says differently */
4602  conn->Pfdebug = NULL;
4603 
4604  /*
4605  * We try to send at least 8K at a time, which is the usual size of pipe
4606  * buffers on Unix systems. That way, when we are sending a large amount
4607  * of data, we avoid incurring extra kernel context swaps for partial
4608  * bufferloads. The output buffer is initially made 16K in size, and we
4609  * try to dump it after accumulating 8K.
4610  *
4611  * With the same goal of minimizing context swaps, the input buffer will
4612  * be enlarged anytime it has less than 8K free, so we initially allocate
4613  * twice that.
4614  */
4615  conn->inBufSize = 16 * 1024;
4616  conn->inBuffer = (char *) malloc(conn->inBufSize);
4617  conn->outBufSize = 16 * 1024;
4618  conn->outBuffer = (char *) malloc(conn->outBufSize);
4619  conn->rowBufLen = 32;
4620  conn->rowBuf = (PGdataValue *) malloc(conn->rowBufLen * sizeof(PGdataValue));
4623 
4624  if (conn->inBuffer == NULL ||
4625  conn->outBuffer == NULL ||
4626  conn->rowBuf == NULL ||
4629  {
4630  /* out of memory already :-( */
4631  freePGconn(conn);
4632  conn = NULL;
4633  }
4634 
4635  return conn;
4636 }
static void defaultNoticeReceiver(void *arg, const PGresult *res)
Definition: fe-connect.c:7373
static void defaultNoticeProcessor(void *arg, const char *message)
Definition: fe-connect.c:7388
@ PQSHOW_CONTEXT_ERRORS
Definition: libpq-fe.h:139
@ PQERRORS_DEFAULT
Definition: libpq-fe.h:131
PQnoticeReceiver noticeRec
Definition: libpq-int.h:155
int inBufSize
Definition: libpq-int.h:523
PGVerbosity verbosity
Definition: libpq-int.h:515
int rowBufLen
Definition: libpq-int.h:540
int outBufSize
Definition: libpq-int.h:530
PGNoticeHooks noticeHooks
Definition: libpq-int.h:428
FILE * Pfdebug
Definition: libpq-int.h:424
PGContextVisibility show_context
Definition: libpq-int.h:516

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

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

◆ PQoptions()

char* PQoptions ( const PGconn conn)

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

7111 {
7112  if (!conn)
7113  return NULL;
7114  return conn->pgoptions;
7115 }

References conn, and pg_conn::pgoptions.

◆ pqPacketSend()

int pqPacketSend ( PGconn conn,
char  pack_type,
const void *  buf,
size_t  buf_len 
)

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

5002 {
5003  /* Start the message. */
5004  if (pqPutMsgStart(pack_type, conn))
5005  return STATUS_ERROR;
5006 
5007  /* Send the message body. */
5008  if (pqPutnchar(buf, buf_len, conn))
5009  return STATUS_ERROR;
5010 
5011  /* Finish the message. */
5012  if (pqPutMsgEnd(conn))
5013  return STATUS_ERROR;
5014 
5015  /* Flush to ensure backend gets it. */
5016  if (pqFlush(conn))
5017  return STATUS_ERROR;
5018 
5019  return STATUS_OK;
5020 }
#define STATUS_ERROR
Definition: c.h:1170
int pqPutMsgStart(char msg_type, PGconn *conn)
Definition: fe-misc.c:458
int pqPutnchar(const char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:202
int pqPutMsgEnd(PGconn *conn)
Definition: fe-misc.c:517

References buf, conn, pqFlush(), pqPutMsgEnd(), pqPutMsgStart(), pqPutnchar(), STATUS_ERROR, and STATUS_OK.

Referenced by pg_password_sendauth(), pg_SASL_continue(), and PQconnectPoll().

◆ PQparameterStatus()

const char* PQparameterStatus ( const PGconn conn,
const char *  paramName 
)

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

7137 {
7138  const pgParameterStatus *pstatus;
7139 
7140  if (!conn || !paramName)
7141  return NULL;
7142  for (pstatus = conn->pstatus; pstatus != NULL; pstatus = pstatus->next)
7143  {
7144  if (strcmp(pstatus->name, paramName) == 0)
7145  return pstatus->value;
7146  }
7147  return NULL;
7148 }

References conn, pgParameterStatus::name, pgParameterStatus::next, pg_conn::pstatus, and pgParameterStatus::value.

Referenced by _check_database_version(), applyRemoteGucs(), BaseBackup(), CheckServerVersionForStreaming(), connectDatabase(), connection_warnings(), ecpg_build_params(), GetConnection(), is_superuser(), main(), printVersion(), session_username(), setup_connection(), standard_strings(), and SyncVariables().

◆ pqParseIntParam()

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

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

7708 {
7709  char *end;
7710  long numval;
7711 
7712  Assert(value != NULL);
7713 
7714  *result = 0;
7715 
7716  /* strtol(3) skips leading whitespaces */
7717  errno = 0;
7718  numval = strtol(value, &end, 10);
7719 
7720  /*
7721  * If no progress was done during the parsing or an error happened, fail.
7722  * This tests properly for overflows of the result.
7723  */
7724  if (value == end || errno != 0 || numval != (int) numval)
7725  goto error;
7726 
7727  /*
7728  * Skip any trailing whitespace; if anything but whitespace remains before
7729  * the terminating character, fail
7730  */
7731  while (*end != '\0' && isspace((unsigned char) *end))
7732  end++;
7733 
7734  if (*end != '\0')
7735  goto error;
7736 
7737  *result = numval;
7738  return true;
7739 
7740 error:
7741  libpq_append_conn_error(conn, "invalid integer value \"%s\" for connection option \"%s\"",
7742  value, context);
7743  return false;
7744 }
tree context
Definition: radixtree.h:1835
static void error(void)
Definition: sql-dyntest.c:147

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

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

◆ PQpass()

char* PQpass ( const PGconn conn)

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

7034 {
7035  char *password = NULL;
7036 
7037  if (!conn)
7038  return NULL;
7039  if (conn->connhost != NULL)
7041  if (password == NULL)
7042  password = conn->pgpass;
7043  /* Historically we've returned "" not NULL for no password specified */
7044  if (password == NULL)
7045  password = "";
7046  return password;
7047 }

References conn, pg_conn::connhost, password, pg_conn_host::password, pg_conn::pgpass, and pg_conn::whichhost.

Referenced by ConnectDatabase(), and PQconnectionNeedsPassword().

◆ PQping()

PGPing PQping ( const char *  conninfo)

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

761 {
762  PGconn *conn = PQconnectStart(conninfo);
763  PGPing ret;
764 
765  ret = internal_ping(conn);
766  PQfinish(conn);
767 
768  return ret;
769 }
static PGPing internal_ping(PGconn *conn)
Definition: fe-connect.c:4485
void PQfinish(PGconn *conn)
Definition: fe-connect.c:4892
PGPing
Definition: libpq-fe.h:149

References conn, internal_ping(), PQconnectStart(), and PQfinish().

◆ PQpingParams()

PGPing PQpingParams ( const char *const *  keywords,
const char *const *  values,
int  expand_dbname 
)

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

710 {
711  PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname);
712  PGPing ret;
713 
714  ret = internal_ping(conn);
715  PQfinish(conn);
716 
717  return ret;
718 }

References conn, internal_ping(), PQconnectStartParams(), PQfinish(), and values.

Referenced by main(), and regression_main().

◆ PQpipelineStatus()

PGpipelineStatus PQpipelineStatus ( const PGconn conn)

◆ PQport()

char* PQport ( const PGconn conn)

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

7087 {
7088  if (!conn)
7089  return NULL;
7090 
7091  if (conn->connhost != NULL)
7092  return conn->connhost[conn->whichhost].port;
7093 
7094  return "";
7095 }

References conn, pg_conn::connhost, pg_conn_host::port, and pg_conn::whichhost.

Referenced by do_connect(), exec_command_conninfo(), get_prompt(), libpqrcv_get_senderinfo(), main(), and SyncVariables().

◆ PQprotocolVersion()

int PQprotocolVersion ( const PGconn conn)

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

7152 {
7153  if (!conn)
7154  return 0;
7155  if (conn->status == CONNECTION_BAD)
7156  return 0;
7157  return PG_PROTOCOL_MAJOR(conn->pversion);
7158 }
#define PG_PROTOCOL_MAJOR(v)
Definition: pqcomm.h:87

References conn, CONNECTION_BAD, PG_PROTOCOL_MAJOR, pg_conn::pversion, and pg_conn::status.

Referenced by handleCopyIn().

◆ PQregisterThreadLock()

pgthreadlock_t PQregisterThreadLock ( pgthreadlock_t  newhandler)

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

7775 {
7777 
7778  if (newhandler)
7779  pg_g_threadlock = newhandler;
7780  else
7782 
7783  return prev;
7784 }
static void default_threadlock(int acquire)
Definition: fe-connect.c:7757
pgthreadlock_t pg_g_threadlock
Definition: fe-connect.c:455
void(* pgthreadlock_t)(int acquire)
Definition: libpq-fe.h:434

References default_threadlock(), and pg_g_threadlock.

◆ pqReleaseConnHosts()

void pqReleaseConnHosts ( PGconn conn)

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

4731 {
4732  if (conn->connhost)
4733  {
4734  for (int i = 0; i < conn->nconnhost; ++i)
4735  {
4736  free(conn->connhost[i].host);
4738  free(conn->connhost[i].port);
4739  if (conn->connhost[i].password != NULL)
4740  {
4742  strlen(conn->connhost[i].password));
4744  }
4745  }
4746  free(conn->connhost);
4747  }
4748 }

References conn, pg_conn::connhost, explicit_bzero(), free, pg_conn_host::host, pg_conn_host::hostaddr, i, pg_conn::nconnhost, pg_conn_host::password, and pg_conn_host::port.

Referenced by freePGconn(), and PQcancelCreate().

◆ PQreset()

void PQreset ( PGconn conn)

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

4907 {
4908  if (conn)
4909  {
4911 
4913  {
4914  /*
4915  * Notify event procs of successful reset.
4916  */
4917  int i;
4918 
4919  for (i = 0; i < conn->nEvents; i++)
4920  {
4921  PGEventConnReset evt;
4922 
4923  evt.conn = conn;
4924  (void) conn->events[i].proc(PGEVT_CONNRESET, &evt,
4925  conn->events[i].passThrough);
4926  }
4927  }
4928  }
4929 }
@ PGEVT_CONNRESET
Definition: libpq-events.h:30

References conn, PGEventConnReset::conn, pg_conn::events, i, pg_conn::nEvents, PGEvent::passThrough, PGEVT_CONNRESET, pqClosePGconn(), pqConnectDBComplete(), pqConnectDBStart(), and PGEvent::proc.

Referenced by CheckConnection().

◆ PQresetPoll()

PostgresPollingStatusType PQresetPoll ( PGconn conn)

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

4959 {
4960  if (conn)
4961  {
4963 
4964  if (status == PGRES_POLLING_OK)
4965  {
4966  /*
4967  * Notify event procs of successful reset.
4968  */
4969  int i;
4970 
4971  for (i = 0; i < conn->nEvents; i++)
4972  {
4973  PGEventConnReset evt;
4974 
4975  evt.conn = conn;
4976  (void) conn->events[i].proc(PGEVT_CONNRESET, &evt,
4977  conn->events[i].passThrough);
4978  }
4979  }
4980 
4981  return status;
4982  }
4983 
4984  return PGRES_POLLING_FAILED;
4985 }

References conn, PGEventConnReset::conn, pg_conn::events, i, pg_conn::nEvents, PGEvent::passThrough, PGEVT_CONNRESET, PGRES_POLLING_FAILED, PGRES_POLLING_OK, PQconnectPoll(), and PGEvent::proc.

◆ PQresetStart()

int PQresetStart ( PGconn conn)

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

4940 {
4941  if (conn)
4942  {
4944 
4945  return pqConnectDBStart(conn);
4946  }
4947 
4948  return 0;
4949 }

References conn, pqClosePGconn(), and pqConnectDBStart().

◆ PQserverVersion()

◆ PQsetClientEncoding()

int PQsetClientEncoding ( PGconn conn,
const char *  encoding 
)

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

7268 {
7269  char qbuf[128];
7270  static const char query[] = "set client_encoding to '%s'";
7271  PGresult *res;
7272  int status;
7273 
7274  if (!conn || conn->status != CONNECTION_OK)
7275  return -1;
7276 
7277  if (!encoding)
7278  return -1;
7279 
7280  /* Resolve special "auto" value from the locale */
7281  if (strcmp(encoding, "auto") == 0)
7283 
7284  /* check query buffer overflow */
7285  if (sizeof(qbuf) < (sizeof(query) + strlen(encoding)))
7286  return -1;
7287 
7288  /* ok, now send a query */
7289  sprintf(qbuf, query, encoding);
7290  res = PQexec(conn, qbuf);
7291 
7292  if (res == NULL)
7293  return -1;
7295  status = -1;
7296  else
7297  {
7298  /*
7299  * We rely on the backend to report the parameter value, and we'll
7300  * change state at that time.
7301  */
7302  status = 0; /* everything is ok */
7303  }
7304  PQclear(res);
7305  return status;
7306 }
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:2262
@ PGRES_COMMAND_OK
Definition: libpq-fe.h:99
int32 encoding
Definition: pg_database.h:41
#define sprintf
Definition: port.h:240

References conn, CONNECTION_OK, encoding, pg_encoding_to_char, pg_get_encoding_from_locale(), PGRES_COMMAND_OK, PQclear(), PQexec(), res, pg_result::resultStatus, sprintf, and pg_conn::status.

Referenced by dblink_connect(), dblink_get_conn(), exec_command_encoding(), main(), and setup_connection().

◆ PQsetdbLogin()

PGconn* PQsetdbLogin ( const char *  pghost,
const char *  pgport,
const char *  pgoptions,
const char *  pgtty,
const char *  dbName,
const char *  login,
const char *  pwd 
)

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

1922 {
1923  PGconn *conn;
1924 
1925  /*
1926  * Allocate memory for the conn structure. Note that we also expect this
1927  * to initialize conn->errorMessage to empty. All subsequent steps during
1928  * connection initialization will only append to that buffer.
1929  */
1930  conn = pqMakeEmptyPGconn();
1931  if (conn == NULL)
1932  return NULL;
1933 
1934  /*
1935  * If the dbName parameter contains what looks like a connection string,
1936  * parse it into conn struct using connectOptions1.
1937  */
1939  {
1940  if (!connectOptions1(conn, dbName))
1941  return conn;
1942  }
1943  else
1944  {
1945  /*
1946  * Old-style path: first, parse an empty conninfo string in order to
1947  * set up the same defaults that PQconnectdb() would use.
1948  */
1949  if (!connectOptions1(conn, ""))
1950  return conn;
1951 
1952  /* Insert dbName parameter value into struct */
1953  if (dbName && dbName[0] != '\0')
1954  {
1955  free(conn->dbName);
1956  conn->dbName = strdup(dbName);
1957  if (!conn->dbName)
1958  goto oom_error;
1959  }
1960  }
1961 
1962  /*
1963  * Insert remaining parameters into struct, overriding defaults (as well
1964  * as any conflicting data from dbName taken as a conninfo).
1965  */
1966  if (pghost && pghost[0] != '\0')
1967  {
1968  free(conn->pghost);
1969  conn->pghost = strdup(pghost);
1970  if (!conn->pghost)
1971  goto oom_error;
1972  }
1973 
1974  if (pgport && pgport[0] != '\0')
1975  {
1976  free(conn->pgport);
1977  conn->pgport = strdup(pgport);
1978  if (!conn->pgport)
1979  goto oom_error;
1980  }
1981 
1982  if (pgoptions && pgoptions[0] != '\0')
1983  {
1984  free(conn->pgoptions);
1985  conn->pgoptions = strdup(pgoptions);
1986  if (!conn->pgoptions)
1987  goto oom_error;
1988  }
1989 
1990  if (login && login[0] != '\0')
1991  {
1992  free(conn->pguser);
1993  conn->pguser = strdup(login);
1994  if (!conn->pguser)
1995  goto oom_error;
1996  }
1997 
1998  if (pwd && pwd[0] != '\0')
1999  {
2000  free(conn->pgpass);
2001  conn->pgpass = strdup(pwd);
2002  if (!conn->pgpass)
2003  goto oom_error;
2004  }
2005 
2006  /*
2007  * Compute derived options
2008  */
2009  if (!pqConnectOptions2(conn))
2010  return conn;
2011 
2012  /*
2013  * Connect to the database
2014  */
2015  if (pqConnectDBStart(conn))
2016  (void) pqConnectDBComplete(conn);
2017 
2018  return conn;
2019 
2020 oom_error:
2022  libpq_append_conn_error(conn, "out of memory");
2023  return conn;
2024 }
static const char * pghost
Definition: pgbench.c:294
static const char * pgport
Definition: pgbench.c:295
static const char * dbName
Definition: pgbench.c:297

References conn, CONNECTION_BAD, connectOptions1(), dbName, pg_conn::dbName, free, libpq_append_conn_error(), pghost, pg_conn::pghost, pg_conn::pgoptions, pg_conn::pgpass, pgport, pg_conn::pgport, pg_conn::pguser, pqConnectDBComplete(), pqConnectDBStart(), pqConnectOptions2(), pqMakeEmptyPGconn(), recognized_connection_string(), and pg_conn::status.

◆ PQsetErrorContextVisibility()

PGContextVisibility PQsetErrorContextVisibility ( PGconn conn,
PGContextVisibility  show_context 
)

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

7322 {
7323  PGContextVisibility old;
7324 
7325  if (!conn)
7326  return PQSHOW_CONTEXT_ERRORS;
7327  old = conn->show_context;
7328  conn->show_context = show_context;
7329  return old;
7330 }
PGContextVisibility
Definition: libpq-fe.h:137

References conn, PQSHOW_CONTEXT_ERRORS, and pg_conn::show_context.

Referenced by show_context_hook(), and SyncVariables().

◆ PQsetErrorVerbosity()

PGVerbosity PQsetErrorVerbosity ( PGconn conn,
PGVerbosity  verbosity 
)

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

7310 {
7311  PGVerbosity old;
7312 
7313  if (!conn)
7314  return PQERRORS_DEFAULT;
7315  old = conn->verbosity;
7316  conn->verbosity = verbosity;
7317  return old;
7318 }
PGVerbosity
Definition: libpq-fe.h:129

References conn, PQERRORS_DEFAULT, and pg_conn::verbosity.

Referenced by main(), SyncVariables(), and verbosity_hook().

◆ PQsetNoticeProcessor()

PQnoticeProcessor PQsetNoticeProcessor ( PGconn conn,
PQnoticeProcessor  proc,
void *  arg 
)

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

7351 {
7352  PQnoticeProcessor old;
7353 
7354  if (conn == NULL)
7355  return NULL;
7356 
7357  old = conn->noticeHooks.noticeProc;
7358  if (proc)
7359  {
7360  conn->noticeHooks.noticeProc = proc;
7362  }
7363  return old;
7364 }
void(* PQnoticeProcessor)(void *arg, const char *message)
Definition: libpq-fe.h:209

References arg, conn, pg_conn::noticeHooks, PGNoticeHooks::noticeProc, and PGNoticeHooks::noticeProcArg.

Referenced by ConnectDatabase(), do_connect(), main(), and test_pipeline_idle().

◆ PQsetNoticeReceiver()

PQnoticeReceiver PQsetNoticeReceiver ( PGconn conn,
PQnoticeReceiver  proc,
void *  arg 
)

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

7334 {
7335  PQnoticeReceiver old;
7336 
7337  if (conn == NULL)
7338  return NULL;
7339 
7340  old = conn->noticeHooks.noticeRec;
7341  if (proc)
7342  {
7343  conn->noticeHooks.noticeRec = proc;
7345  }
7346  return old;
7347 }
void(* PQnoticeReceiver)(void *arg, const PGresult *res)
Definition: libpq-fe.h:208
void * noticeRecArg
Definition: libpq-int.h:156

References arg, conn, pg_conn::noticeHooks, PGNoticeHooks::noticeRec, and PGNoticeHooks::noticeRecArg.

Referenced by ECPGconnect().

◆ PQsocket()

◆ PQstatus()

◆ PQtransactionStatus()

◆ PQtty()

char* PQtty ( const PGconn conn)

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

7103 {
7104  if (!conn)
7105  return NULL;
7106  return "";
7107 }

References conn.

◆ PQuser()

char* PQuser ( const PGconn conn)

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

7026 {
7027  if (!conn)
7028  return NULL;
7029  return conn->pguser;
7030 }

References conn, and pg_conn::pguser.

Referenced by do_connect(), exec_command_conninfo(), get_prompt(), main(), session_username(), and SyncVariables().

◆ pwdfMatchesString()

static char * pwdfMatchesString ( char *  buf,
const char *  token 
)
static

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

7401 {
7402  char *tbuf;
7403  const char *ttok;
7404  bool bslash = false;
7405 
7406  if (buf == NULL || token == NULL)
7407  return NULL;
7408  tbuf = buf;
7409  ttok = token;
7410  if (tbuf[0] == '*' && tbuf[1] == ':')
7411  return tbuf + 2;
7412  while (*tbuf != 0)
7413  {
7414  if (*tbuf == '\\' && !bslash)
7415  {
7416  tbuf++;
7417  bslash = true;
7418  }
7419  if (*tbuf == ':' && *ttok == 0 && !bslash)
7420  return tbuf + 1;
7421  bslash = false;
7422  if (*ttok == 0)
7423  return NULL;
7424  if (*tbuf == *ttok)
7425  {
7426  tbuf++;
7427  ttok++;
7428  }
7429  else
7430  return NULL;
7431  }
7432  return NULL;
7433 }
#define token
Definition: indent_globs.h:126

References buf, and token.

Referenced by passwordFromFile().

◆ recognized_connection_string()

static bool recognized_connection_string ( const char *  connstr)
static

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

5857 {
5858  return uri_prefix_length(connstr) != 0 || strchr(connstr, '=') != NULL;
5859 }

References connstr, and uri_prefix_length().

Referenced by conninfo_array_parse(), and PQsetdbLogin().

◆ release_conn_addrinfo()

static void release_conn_addrinfo ( PGconn conn)
static

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

4799 {
4800  if (conn->addr)
4801  {
4802  free(conn->addr);
4803  conn->addr = NULL;
4804  }
4805 }

References pg_conn::addr, conn, and free.

Referenced by freePGconn(), pqClosePGconn(), and PQconnectPoll().

◆ select_next_encryption_method()

static bool select_next_encryption_method ( PGconn conn,
bool  have_valid_connection 
)
static

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

4411 {
4412  int remaining_methods;
4413 
4414 #define SELECT_NEXT_METHOD(method) \
4415  do { \
4416  if ((remaining_methods & method) != 0) \
4417  { \
4418  conn->current_enc_method = method; \
4419  return true; \
4420  } \
4421  } while (false)
4422 
4423  remaining_methods = conn->allowed_enc_methods & ~conn->failed_enc_methods;
4424 
4425  /*
4426  * Try GSSAPI before SSL
4427  */
4428 #ifdef ENABLE_GSS
4429  if ((remaining_methods & ENC_GSSAPI) != 0)
4430  {
4431  /*
4432  * If GSSAPI encryption is enabled, then call pg_GSS_have_cred_cache()
4433  * which will return true if we can acquire credentials (and give us a
4434  * handle to use in conn->gcred), and then send a packet to the server
4435  * asking for GSSAPI Encryption (and skip past SSL negotiation and
4436  * regular startup below).
4437  */
4438  if (!conn->gctx)
4439  {
4440  if (!pg_GSS_have_cred_cache(&conn->gcred))
4441  {
4443  remaining_methods &= ~ENC_GSSAPI;
4444 
4445  if (conn->gssencmode[0] == 'r')
4446  {
4448  "GSSAPI encryption required but no credential cache");
4449  }
4450  }
4451  }
4452  }
4453 
4455 #endif
4456 
4457  /*
4458  * The order between SSL encryption and plaintext depends on sslmode. With
4459  * sslmode=allow, try plaintext connection before SSL. With
4460  * sslmode=prefer, it's the other way round. With other modes, we only try
4461  * plaintext or SSL connections so the order they're listed here doesn't
4462  * matter.
4463  */
4464  if (conn->sslmode[0] == 'a')
4466 
4468 
4469  if (conn->sslmode[0] != 'a')
4471 
4472  /* No more options */
4474  return false;
4475 #undef SELECT_NEXT_METHOD
4476 }
#define SELECT_NEXT_METHOD(method)

References pg_conn::allowed_enc_methods, conn, pg_conn::current_enc_method, ENC_ERROR, ENC_GSSAPI, ENC_PLAINTEXT, ENC_SSL, pg_conn::failed_enc_methods, pg_conn::gssencmode, libpq_append_conn_error(), pg_GSS_have_cred_cache(), SELECT_NEXT_METHOD, and pg_conn::sslmode.

Referenced by connection_failed(), and init_allowed_encryption_methods().

◆ sendTerminateConn()

static void sendTerminateConn ( PGconn conn)
static

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

4813 {
4814  /*
4815  * The Postgres cancellation protocol does not have a notion of a
4816  * Terminate message, so don't send one.
4817  */
4818  if (conn->cancelRequest)
4819  return;
4820 
4821  /*
4822  * Note that the protocol doesn't allow us to send Terminate messages
4823  * during the startup phase.
4824  */
4826  {
4827  /*
4828  * Try to send "close connection" message to backend. Ignore any
4829  * error.
4830  */
4832  pqPutMsgEnd(conn);
4833  (void) pqFlush(conn);
4834  }
4835 }
#define PqMsg_Terminate
Definition: protocol.h:28

References pg_conn::cancelRequest, conn, CONNECTION_OK, PGINVALID_SOCKET, pqFlush(), PqMsg_Terminate, pqPutMsgEnd(), pqPutMsgStart(), pg_conn::sock, and pg_conn::status.

Referenced by pqClosePGconn(), and PQconnectPoll().

◆ setKeepalivesCount()

static int setKeepalivesCount ( PGconn conn)
static

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

2257 {
2258  int count;
2259 
2260  if (conn->keepalives_count == NULL)
2261  return 1;
2262 
2263  if (!pqParseIntParam(conn->keepalives_count, &count, conn,
2264  "keepalives_count"))
2265  return 0;
2266  if (count < 0)
2267  count = 0;
2268 
2269 #ifdef TCP_KEEPCNT
2270  if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPCNT,
2271  (char *) &count, sizeof(count)) < 0)
2272  {
2273  char sebuf[PG_STRERROR_R_BUFLEN];
2274 
2275  libpq_append_conn_error(conn, "%s(%s) failed: %s",
2276  "setsockopt",
2277  "TCP_KEEPCNT",
2278  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2279  return 0;
2280  }
2281 #endif
2282 
2283  return 1;
2284 }

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

Referenced by PQconnectPoll().

◆ setKeepalivesIdle()

static int setKeepalivesIdle ( PGconn conn)
static

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

2188 {
2189  int idle;
2190 
2191  if (conn->keepalives_idle == NULL)
2192  return 1;
2193 
2194  if (!pqParseIntParam(conn->keepalives_idle, &idle, conn,
2195  "keepalives_idle"))
2196  return 0;
2197  if (idle < 0)
2198  idle = 0;
2199 
2200 #ifdef PG_TCP_KEEPALIVE_IDLE
2201  if (setsockopt(conn->sock, IPPROTO_TCP, PG_TCP_KEEPALIVE_IDLE,
2202  (char *) &idle, sizeof(idle)) < 0)
2203  {
2204  char sebuf[PG_STRERROR_R_BUFLEN];
2205 
2206  libpq_append_conn_error(conn, "%s(%s) failed: %s",
2207  "setsockopt",
2208  PG_TCP_KEEPALIVE_IDLE_STR,
2209  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2210  return 0;
2211  }
2212 #endif
2213 
2214  return 1;
2215 }

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

Referenced by PQconnectPoll().

◆ setKeepalivesInterval()

static int setKeepalivesInterval ( PGconn conn)
static

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

2222 {
2223  int interval;
2224 
2225  if (conn->keepalives_interval == NULL)
2226  return 1;
2227 
2229  "keepalives_interval"))
2230  return 0;
2231  if (interval < 0)
2232  interval = 0;
2233 
2234 #ifdef TCP_KEEPINTVL
2235  if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPINTVL,
2236  (char *) &interval, sizeof(interval)) < 0)
2237  {
2238  char sebuf[PG_STRERROR_R_BUFLEN];
2239 
2240  libpq_append_conn_error(conn, "%s(%s) failed: %s",
2241  "setsockopt",
2242  "TCP_KEEPINTVL",
2243  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2244  return 0;
2245  }
2246 #endif
2247 
2248  return 1;
2249 }

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

Referenced by PQconnectPoll().

◆ setTCPUserTimeout()

static int setTCPUserTimeout ( PGconn conn)
static

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

2354 {
2355  int timeout;
2356 
2357  if (conn->pgtcp_user_timeout == NULL)
2358  return 1;
2359 
2360  if (!pqParseIntParam(conn->pgtcp_user_timeout, &timeout, conn,
2361  "tcp_user_timeout"))
2362  return 0;
2363 
2364  if (timeout < 0)
2365  timeout = 0;
2366 
2367 #ifdef TCP_USER_TIMEOUT
2368  if (setsockopt(conn->sock, IPPROTO_TCP, TCP_USER_TIMEOUT,
2369  (char *) &timeout, sizeof(timeout)) < 0)
2370  {
2371  char sebuf[256];
2372 
2373  libpq_append_conn_error(conn, "%s(%s) failed: %s",
2374  "setsockopt",
2375  "TCP_USER_TIMEOUT",
2376  SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2377  return 0;
2378  }
2379 #endif
2380 
2381  return 1;
2382 }

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

Referenced by PQconnectPoll().

◆ sslVerifyProtocolRange()

static bool sslVerifyProtocolRange ( const char *  min,
const char *  max 
)
static

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

7627 {
7630 
7631  /* If at least one of the bounds is not set, the range is valid */
7632  if (min == NULL || max == NULL || strlen(min) == 0 || strlen(max) == 0)
7633  return true;
7634 
7635  /*
7636  * If the minimum version is the lowest one we accept, then all options
7637  * for the maximum are valid.
7638  */
7639  if (pg_strcasecmp(min, "TLSv1") == 0)
7640  return true;
7641 
7642  /*
7643  * The minimum bound is valid, and cannot be TLSv1, so using TLSv1 for the
7644  * maximum is incorrect.
7645  */
7646  if (pg_strcasecmp(max, "TLSv1") == 0)
7647  return false;
7648 
7649  /*
7650  * At this point we know that we have a mix of TLSv1.1 through 1.3
7651  * versions.
7652  */
7653  if (pg_strcasecmp(min, max) > 0)
7654  return false;
7655 
7656  return true;
7657 }
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36

References Assert, pg_strcasecmp(), and sslVerifyProtocolVersion().

Referenced by pqConnectOptions2().

◆ sslVerifyProtocolVersion()

static bool sslVerifyProtocolVersion ( const char *  version)
static

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

7601 {
7602  /*
7603  * An empty string and a NULL value are considered valid as it is
7604  * equivalent to ignoring the parameter.
7605  */
7606  if (!version || strlen(version) == 0)
7607  return true;
7608 
7609  if (pg_strcasecmp(version, "TLSv1") == 0 ||
7610  pg_strcasecmp(version, "TLSv1.1") == 0 ||
7611  pg_strcasecmp(version, "TLSv1.2") == 0 ||
7612  pg_strcasecmp(version, "TLSv1.3") == 0)
7613  return true;
7614 
7615  /* anything else is wrong */
7616  return false;
7617 }

References pg_strcasecmp().

Referenced by pqConnectOptions2(), and sslVerifyProtocolRange().

◆ store_conn_addrinfo()

static int store_conn_addrinfo ( PGconn conn,
struct addrinfo *  addrlist 
)
static

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

4760 {
4761  struct addrinfo *ai = addrlist;
4762 
4763  conn->whichaddr = 0;
4764 
4765  conn->naddr = 0;
4766  while (ai)
4767  {
4768  ai = ai->ai_next;
4769  conn->naddr++;
4770  }
4771 
4772  conn->addr = calloc(conn->naddr, sizeof(AddrInfo));
4773  if (conn->addr == NULL)
4774  {
4775  libpq_append_conn_error(conn, "out of memory");
4776  return 1;
4777  }
4778 
4779  ai = addrlist;
4780  for (int i = 0; i < conn->naddr; i++)
4781  {
4782  conn->addr[i].family = ai->ai_family;
4783 
4784  memcpy(&conn->addr[i].addr.addr, ai->ai_addr,
4785  ai->ai_addrlen);
4786  conn->addr[i].addr.salen = ai->ai_addrlen;
4787  ai = ai->ai_next;
4788  }
4789 
4790  return 0;
4791 }

References AddrInfo::addr, SockAddr::addr, pg_conn::addr, calloc, conn, AddrInfo::family, i, libpq_append_conn_error(), pg_conn::naddr, SockAddr::salen, and pg_conn::whichaddr.

Referenced by PQconnectPoll().

◆ uri_prefix_length()

static int uri_prefix_length ( const char *  connstr)
static

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

5834 {
5835  if (strncmp(connstr, uri_designator,
5836  sizeof(uri_designator) - 1) == 0)
5837  return sizeof(uri_designator) - 1;
5838 
5839  if (strncmp(connstr, short_uri_designator,
5840  sizeof(short_uri_designator) - 1) == 0)
5841  return sizeof(short_uri_designator) - 1;
5842 
5843  return 0;
5844 }
static const char short_uri_designator[]
Definition: fe-connect.c:392
static const char uri_designator[]
Definition: fe-connect.c:391

References connstr, short_uri_designator, and uri_designator.

Referenced by conninfo_uri_parse_options(), parse_connection_string(), and recognized_connection_string().

◆ useKeepalives()

static int useKeepalives ( PGconn conn)
static

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

2170 {
2171  char *ep;
2172  int val;
2173 
2174  if (conn->keepalives == NULL)
2175  return 1;
2176  val = strtol(conn->keepalives, &ep, 10);
2177  if (*ep)
2178  return -1;
2179  return val != 0 ? 1 : 0;
2180 }

References conn, pg_conn::keepalives, and val.

Referenced by PQconnectPoll().

Variable Documentation

◆ EnvironmentOptions

const PQEnvironmentOption EnvironmentOptions[]
static
Initial value:
=
{
{
"PGDATESTYLE", "datestyle"
},
{
"PGTZ", "timezone"
},
{
"PGGEQO", "geqo"
},
{
NULL, NULL
}
}

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

Referenced by PQconnectPoll().

◆ pg_g_threadlock

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

Referenced by PQregisterThreadLock().

◆ PQconninfoOptions

const internalPQconninfoOption PQconninfoOptions[]
static

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

Referenced by conninfo_init(), fillPGconn(), PQconninfo(), and pqCopyPGconn().

◆ short_uri_designator

const char short_uri_designator[] = "postgres://"
static

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

Referenced by uri_prefix_length().

◆ uri_designator

const char uri_designator[] = "postgresql://"
static

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

Referenced by uri_prefix_length().