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

4379 {
4382 
4383  return select_next_encryption_method(conn, false);
4384 }
#define Assert(condition)
Definition: c.h:858
static bool select_next_encryption_method(PGconn *conn, bool have_valid_connection)
Definition: fe-connect.c:4393
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:5796
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:6987
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 6184 of file fe-connect.c.

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

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

6926 {
6928 
6929  for (option = connOptions; option->keyword != NULL; option++)
6930  {
6931  if (strcmp(option->keyword, keyword) == 0)
6932  return option;
6933  }
6934 
6935  return NULL;
6936 }

Referenced by conninfo_getval(), and conninfo_storeval().

◆ conninfo_getval()

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

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

6837 {
6839 
6840  option = conninfo_find(connOptions, keyword);
6841 
6842  return option ? option->val : NULL;
6843 }
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:6925

References conninfo_find(), and option::val.

Referenced by fillPGconn(), and parseServiceInfo().

◆ conninfo_init()

static PQconninfoOption * conninfo_init ( PQExpBuffer  errorMessage)
static

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

5758 {
5760  PQconninfoOption *opt_dest;
5761  const internalPQconninfoOption *cur_opt;
5762 
5763  /*
5764  * Get enough memory for all options in PQconninfoOptions, even if some
5765  * end up being filtered out.
5766  */
5768  if (options == NULL)
5769  {
5770  libpq_append_error(errorMessage, "out of memory");
5771  return NULL;
5772  }
5773  opt_dest = options;
5774 
5775  for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++)
5776  {
5777  /* Only copy the public part of the struct, not the full internal */
5778  memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption));
5779  opt_dest++;
5780  }
5781  MemSet(opt_dest, 0, sizeof(PQconninfoOption));
5782 
5783  return options;
5784 }
#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 5850 of file fe-connect.c.

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

6865 {
6867  char *value_copy;
6868 
6869  /*
6870  * For backwards compatibility, requiressl=1 gets translated to
6871  * sslmode=require, and requiressl=0 gets translated to sslmode=prefer
6872  * (which is the default for sslmode).
6873  */
6874  if (strcmp(keyword, "requiressl") == 0)
6875  {
6876  keyword = "sslmode";
6877  if (value[0] == '1')
6878  value = "require";
6879  else
6880  value = "prefer";
6881  }
6882 
6883  option = conninfo_find(connOptions, keyword);
6884  if (option == NULL)
6885  {
6886  if (!ignoreMissing)
6887  libpq_append_error(errorMessage,
6888  "invalid connection option \"%s\"",
6889  keyword);
6890  return NULL;
6891  }
6892 
6893  if (uri_decode)
6894  {
6895  value_copy = conninfo_uri_decode(value, errorMessage);
6896  if (value_copy == NULL)
6897  /* conninfo_uri_decode already set an error message */
6898  return NULL;
6899  }
6900  else
6901  {
6902  value_copy = strdup(value);
6903  if (value_copy == NULL)
6904  {
6905  libpq_append_error(errorMessage, "out of memory");
6906  return NULL;
6907  }
6908  }
6909 
6910  free(option->val);
6911  option->val = value_copy;
6912 
6913  return option;
6914 }
static char * conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
Definition: fe-connect.c:6746
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 6746 of file fe-connect.c.

6747 {
6748  char *buf;
6749  char *p;
6750  const char *q = str;
6751 
6752  buf = malloc(strlen(str) + 1);
6753  if (buf == NULL)
6754  {
6755  libpq_append_error(errorMessage, "out of memory");
6756  return NULL;
6757  }
6758  p = buf;
6759 
6760  for (;;)
6761  {
6762  if (*q != '%')
6763  {
6764  /* copy and check for NUL terminator */
6765  if (!(*(p++) = *(q++)))
6766  break;
6767  }
6768  else
6769  {
6770  int hi;
6771  int lo;
6772  int c;
6773 
6774  ++q; /* skip the percent sign itself */
6775 
6776  /*
6777  * Possible EOL will be caught by the first call to
6778  * get_hexdigit(), so we never dereference an invalid q pointer.
6779  */
6780  if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo)))
6781  {
6782  libpq_append_error(errorMessage,
6783  "invalid percent-encoded token: \"%s\"",
6784  str);
6785  free(buf);
6786  return NULL;
6787  }
6788 
6789  c = (hi << 4) | lo;
6790  if (c == 0)
6791  {
6792  libpq_append_error(errorMessage,
6793  "forbidden value %%00 in percent-encoded value: \"%s\"",
6794  str);
6795  free(buf);
6796  return NULL;
6797  }
6798  *(p++) = c;
6799  }
6800  }
6801 
6802  return buf;
6803 }
static bool get_hexdigit(char digit, int *value)
Definition: fe-connect.c:6814
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 6319 of file fe-connect.c.

6321 {
6323 
6324  /* Make a working copy of PQconninfoOptions */
6325  options = conninfo_init(errorMessage);
6326  if (options == NULL)
6327  return NULL;
6328 
6329  if (!conninfo_uri_parse_options(options, uri, errorMessage))
6330  {
6332  return NULL;
6333  }
6334 
6335  /*
6336  * Add in defaults if the caller wants that.
6337  */
6338  if (use_defaults)
6339  {
6340  if (!conninfo_add_defaults(options, errorMessage))
6341  {
6343  return NULL;
6344  }
6345  }
6346 
6347  return options;
6348 }
static bool conninfo_uri_parse_options(PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage)
Definition: fe-connect.c:6372

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

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

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

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

7741 {
7742  static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
7743 
7744  if (acquire)
7745  {
7746  if (pthread_mutex_lock(&singlethread_lock))
7747  Assert(false);
7748  }
7749  else
7750  {
7751  if (pthread_mutex_unlock(&singlethread_lock))
7752  Assert(false);
7753  }
7754 }
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 7371 of file fe-connect.c.

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

7357 {
7358  (void) arg; /* not used */
7359  if (res->noticeHooks.noticeProc != NULL)
7362 }
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:6835

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

4632 {
4633  /* let any event procs clean up their state data */
4634  for (int i = 0; i < conn->nEvents; i++)
4635  {
4636  PGEventConnDestroy evt;
4637 
4638  evt.conn = conn;
4639  (void) conn->events[i].proc(PGEVT_CONNDESTROY, &evt,
4640  conn->events[i].passThrough);
4641  free(conn->events[i].name);
4642  }
4643 
4646 
4648  free(conn->events);
4649  free(conn->pghost);
4650  free(conn->pghostaddr);
4651  free(conn->pgport);
4654  free(conn->pgoptions);
4655  free(conn->appname);
4656  free(conn->fbappname);
4657  free(conn->dbName);
4658  free(conn->replication);
4659  free(conn->pguser);
4660  if (conn->pgpass)
4661  {
4662  explicit_bzero(conn->pgpass, strlen(conn->pgpass));
4663  free(conn->pgpass);
4664  }
4665  free(conn->pgpassfile);
4667  free(conn->keepalives);
4671  free(conn->sslmode);
4673  free(conn->sslcert);
4674  free(conn->sslkey);
4675  if (conn->sslpassword)
4676  {
4678  free(conn->sslpassword);
4679  }
4680  free(conn->sslcertmode);
4681  free(conn->sslrootcert);
4682  free(conn->sslcrl);
4683  free(conn->sslcrldir);
4685  free(conn->sslsni);
4686  free(conn->requirepeer);
4690  free(conn->gssencmode);
4691  free(conn->krbsrvname);
4692  free(conn->gsslib);
4694  free(conn->connip);
4695  /* Note that conn->Pfdebug is not ours to close or free */
4697  free(conn->inBuffer);
4698  free(conn->outBuffer);
4699  free(conn->rowBuf);
4704 
4705  free(conn);
4706 }
static void release_conn_addrinfo(PGconn *conn)
Definition: fe-connect.c:4781
void pqReleaseConnHosts(PGconn *conn)
Definition: fe-connect.c:4713
@ 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 6814 of file fe-connect.c.

6815 {
6816  if ('0' <= digit && digit <= '9')
6817  *value = digit - '0';
6818  else if ('A' <= digit && digit <= 'F')
6819  *value = digit - 'A' + 10;
6820  else if ('a' <= digit && digit <= 'f')
6821  *value = digit - 'a' + 10;
6822  else
6823  return false;
6824 
6825  return true;
6826 }

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

4289 {
4290  if (conn->raddr.addr.ss_family == AF_UNIX)
4291  {
4292  /* Don't request SSL or GSSAPI over Unix sockets */
4294 
4295  /*
4296  * XXX: we probably should not do this. sslmode=require works
4297  * differently
4298  */
4299  if (conn->gssencmode[0] == 'r')
4300  {
4302  "GSSAPI encryption required but it is not supported over a local socket");
4305  return false;
4306  }
4307 
4310  return true;
4311  }
4312 
4313  /* initialize based on sslmode and gssencmode */
4315 
4316 #ifdef USE_SSL
4317  /* sslmode anything but 'disable', and GSSAPI not required */
4318  if (conn->sslmode[0] != 'd' && conn->gssencmode[0] != 'r')
4319  {
4321  }
4322 #endif
4323 
4324 #ifdef ENABLE_GSS
4325  if (conn->gssencmode[0] != 'd')
4327 #endif
4328 
4329  if ((conn->sslmode[0] == 'd' || conn->sslmode[0] == 'p' || conn->sslmode[0] == 'a') &&
4330  (conn->gssencmode[0] == 'd' || conn->gssencmode[0] == 'p'))
4331  {
4333  }
4334 
4335  return select_next_encryption_method(conn, false);
4336 }
#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 4468 of file fe-connect.c.

4469 {
4470  /* Say "no attempt" if we never got to PQconnectPoll */
4471  if (!conn || !conn->options_valid)
4472  return PQPING_NO_ATTEMPT;
4473 
4474  /* Attempt to complete the connection */
4475  if (conn->status != CONNECTION_BAD)
4476  (void) pqConnectDBComplete(conn);
4477 
4478  /* Definitely OK if we succeeded */
4479  if (conn->status != CONNECTION_BAD)
4480  return PQPING_OK;
4481 
4482  /*
4483  * Here begins the interesting part of "ping": determine the cause of the
4484  * failure in sufficient detail to decide what to return. We do not want
4485  * to report that the server is not up just because we didn't have a valid
4486  * password, for example. In fact, any sort of authentication request
4487  * implies the server is up. (We need this check since the libpq side of
4488  * things might have pulled the plug on the connection before getting an
4489  * error as such from the postmaster.)
4490  */
4491  if (conn->auth_req_received)
4492  return PQPING_OK;
4493 
4494  /*
4495  * If we failed to get any ERROR response from the postmaster, report
4496  * PQPING_NO_RESPONSE. This result could be somewhat misleading for a
4497  * pre-7.4 server, since it won't send back a SQLSTATE, but those are long
4498  * out of support. Another corner case where the server could return a
4499  * failure without a SQLSTATE is fork failure, but PQPING_NO_RESPONSE
4500  * isn't totally unreasonable for that anyway. We expect that every other
4501  * failure case in a modern server will produce a report with a SQLSTATE.
4502  *
4503  * NOTE: whenever we get around to making libpq generate SQLSTATEs for
4504  * client-side errors, we should either not store those into
4505  * last_sqlstate, or add an extra flag so we can tell client-side errors
4506  * apart from server-side ones.
4507  */
4508  if (strlen(conn->last_sqlstate) != 5)
4509  return PQPING_NO_RESPONSE;
4510 
4511  /*
4512  * Report PQPING_REJECT if server says it's not accepting connections.
4513  */
4514  if (strcmp(conn->last_sqlstate, ERRCODE_CANNOT_CONNECT_NOW) == 0)
4515  return PQPING_REJECT;
4516 
4517  /*
4518  * Any other SQLSTATE can be taken to indicate that the server is up.
4519  * Presumably it didn't like our username, password, or database name; or
4520  * perhaps it had some transient failure, but that should not be taken as
4521  * meaning "it's down".
4522  */
4523  return PQPING_OK;
4524 }
#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 5796 of file fe-connect.c.

5798 {
5799  /* Parse as URI if connection string matches URI prefix */
5800  if (uri_prefix_length(connstr) != 0)
5801  return conninfo_uri_parse(connstr, errorMessage, use_defaults);
5802 
5803  /* Parse as default otherwise */
5804  return conninfo_parse(connstr, errorMessage, use_defaults);
5805 }
static PQconninfoOption * conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:6319
static PQconninfoOption * conninfo_parse(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:5850
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 5557 of file fe-connect.c.

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

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

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

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

Referenced by pqConnectOptions2().

◆ pgpassfileWarning()

static void pgpassfileWarning ( PGconn conn)
static

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

7561 {
7562  /* If it was 'invalid authorization', add pgpassfile mention */
7563  /* only works with >= 9.0 servers */
7564  if (conn->password_needed &&
7565  conn->connhost[conn->whichhost].password != NULL &&
7566  conn->result)
7567  {
7568  const char *sqlstate = PQresultErrorField(conn->result,
7570 
7571  if (sqlstate && strcmp(sqlstate, ERRCODE_INVALID_PASSWORD) == 0)
7572  libpq_append_conn_error(conn, "password retrieved from file \"%s\"",
7573  conn->pgpassfile);
7574  }
7575 }
#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 7188 of file fe-connect.c.

7189 {
7190  if (!conn || conn->status != CONNECTION_OK)
7191  return 0;
7192  return conn->be_pid;
7193 }
@ 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 4829 of file fe-connect.c.

4830 {
4831  /*
4832  * If possible, send Terminate message to close the connection politely.
4833  */
4835 
4836  /*
4837  * Must reset the blocking status so a possible reconnect will work.
4838  *
4839  * Don't call PQsetnonblocking() because it will fail if it's unable to
4840  * flush the connection.
4841  */
4842  conn->nonblocking = false;
4843 
4844  /*
4845  * Close the connection, reset all transient state, flush I/O buffers.
4846  * Note that this includes clearing conn's error state; we're no longer
4847  * interested in any failures associated with the old connection, and we
4848  * want a clean slate for any new connection attempt.
4849  */
4850  pqDropConnection(conn, true);
4851  conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
4855  pqClearAsyncResult(conn); /* deallocate result */
4857 
4858  /*
4859  * Release addrinfo, but since cancel requests never change their addrinfo
4860  * we don't do that. Otherwise we would have to rebuild it during a
4861  * PQcancelReset.
4862  */
4863  if (!conn->cancelRequest)
4865 
4866  /* Reset all state obtained from server, too */
4868 }
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:471
static void sendTerminateConn(PGconn *conn)
Definition: fe-connect.c:4795
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:7689
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
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 7205 of file fe-connect.c.

7206 {
7207  char *password;
7208 
7209  if (!conn)
7210  return false;
7211  password = PQpass(conn);
7212  if (conn->password_needed &&
7213  (password == NULL || password[0] == '\0'))
7214  return true;
7215  else
7216  return false;
7217 }
char * PQpass(const PGconn *conn)
Definition: fe-connect.c:7016

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

7232 {
7233  if (!conn)
7234  return false;
7235  if (conn->gssapi_used)
7236  return true;
7237  else
7238  return false;
7239 }
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 7220 of file fe-connect.c.

7221 {
7222  if (!conn)
7223  return false;
7224  if (conn->password_needed)
7225  return true;
7226  else
7227  return false;
7228 }

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:7420
static bool sslVerifyProtocolRange(const char *min, const char *max)
Definition: fe-connect.c:7609
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:7583
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:79
#define AUTH_REQ_SASL_CONT
Definition: protocol.h:81
#define AUTH_REQ_GSS
Definition: protocol.h:77
#define AUTH_REQ_MD5
Definition: protocol.h:75
#define AUTH_REQ_PASSWORD
Definition: protocol.h:73
#define AUTH_REQ_GSS_CONT
Definition: protocol.h:78
#define AUTH_REQ_SASL
Definition: protocol.h:80
#define AUTH_REQ_SASL_FIN
Definition: protocol.h:82
int nconnhost
Definition: libpq-int.h: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  goto keep_going;
3525  }
3526  else
3527  {
3528  libpq_append_conn_error(conn, "received invalid response to SSL negotiation: %c",
3529  SSLok);
3530  goto error_return;
3531  }
3532  }
3533 
3534  /*
3535  * Set up global SSL state if required. The crypto state has
3536  * already been set if libpq took care of doing that, so there
3537  * is no need to make that happen again.
3538  */
3539  if (pqsecure_initialize(conn, true, false) != 0)
3540  goto error_return;
3541 
3542  /*
3543  * Begin or continue the SSL negotiation process.
3544  */
3545  pollres = pqsecure_open_client(conn);
3546  if (pollres == PGRES_POLLING_OK)
3547  {
3548  /*
3549  * At this point we should have no data already buffered.
3550  * If we do, it was received before we performed the SSL
3551  * handshake, so it wasn't encrypted and indeed may have
3552  * been injected by a man-in-the-middle.
3553  */
3554  if (conn->inCursor != conn->inEnd)
3555  {
3556  libpq_append_conn_error(conn, "received unencrypted data after SSL response");
3557  goto error_return;
3558  }
3559 
3560  /* SSL handshake done, ready to send startup packet */
3562  return PGRES_POLLING_WRITING;
3563  }
3564  if (pollres == PGRES_POLLING_FAILED)
3565  {
3566  /*
3567  * Failed direct ssl connection, possibly try a new
3568  * connection with postgres negotiation
3569  */
3571  }
3572  /* Else, return POLLING_READING or POLLING_WRITING status */
3573  return pollres;
3574 #else /* !USE_SSL */
3575  /* can't get here */
3576  goto error_return;
3577 #endif /* USE_SSL */
3578  }
3579 
3581  {
3582 #ifdef ENABLE_GSS
3583  PostgresPollingStatusType pollres;
3584 
3585  /*
3586  * If we haven't yet, get the postmaster's response to our
3587  * negotiation packet
3588  */
3589  if (!conn->gctx)
3590  {
3591  char gss_ok;
3592  int rdresult = pqReadData(conn);
3593 
3594  if (rdresult < 0)
3595  /* pqReadData fills in error message */
3596  goto error_return;
3597  else if (rdresult == 0)
3598  /* caller failed to wait for data */
3599  return PGRES_POLLING_READING;
3600  if (pqGetc(&gss_ok, conn) < 0)
3601  /* shouldn't happen... */
3602  return PGRES_POLLING_READING;
3603 
3604  if (gss_ok == 'E')
3605  {
3606  /*
3607  * Server failure of some sort, possibly protocol
3608  * version support failure. We need to process and
3609  * report the error message, which might be formatted
3610  * according to either protocol 2 or protocol 3.
3611  * Rather than duplicate the code for that, we flip
3612  * into AWAITING_RESPONSE state and let the code there
3613  * deal with it. Note we have *not* consumed the "E"
3614  * byte here.
3615  */
3617  goto keep_going;
3618  }
3619 
3620  /* mark byte consumed */
3621  conn->inStart = conn->inCursor;
3622 
3623  if (gss_ok == 'N')
3624  {
3625  /*
3626  * The connection is still valid, so if it's OK to
3627  * continue without GSS, we can proceed using this
3628  * connection. Otherwise return with an error.
3629  */
3630  ENCRYPTION_NEGOTIATION_FAILED(libpq_gettext("server doesn't support GSSAPI encryption, but it was required"));
3631  }
3632  else if (gss_ok != 'G')
3633  {
3634  libpq_append_conn_error(conn, "received invalid response to GSSAPI negotiation: %c",
3635  gss_ok);
3636  goto error_return;
3637  }
3638  }
3639 
3640  /* Begin or continue GSSAPI negotiation */
3641  pollres = pqsecure_open_gss(conn);
3642  if (pollres == PGRES_POLLING_OK)
3643  {
3644  /*
3645  * At this point we should have no data already buffered.
3646  * If we do, it was received before we performed the GSS
3647  * handshake, so it wasn't encrypted and indeed may have
3648  * been injected by a man-in-the-middle.
3649  */
3650  if (conn->inCursor != conn->inEnd)
3651  {
3652  libpq_append_conn_error(conn, "received unencrypted data after GSSAPI encryption response");
3653  goto error_return;
3654  }
3655 
3656  /* All set for startup packet */
3658  return PGRES_POLLING_WRITING;
3659  }
3660  else if (pollres == PGRES_POLLING_FAILED)
3661  {
3663  }
3664  /* Else, return POLLING_READING or POLLING_WRITING status */
3665  return pollres;
3666 #else /* !ENABLE_GSS */
3667  /* unreachable */
3668  goto error_return;
3669 #endif /* ENABLE_GSS */
3670  }
3671 
3672  /*
3673  * Handle authentication exchange: wait for postmaster messages
3674  * and respond as necessary.
3675  */
3677  {
3678  char beresp;
3679  int msgLength;
3680  int avail;
3681  AuthRequest areq;
3682  int res;
3683 
3684  /*
3685  * Scan the message from current point (note that if we find
3686  * the message is incomplete, we will return without advancing
3687  * inStart, and resume here next time).
3688  */
3689  conn->inCursor = conn->inStart;
3690 
3691  /* Read type byte */
3692  if (pqGetc(&beresp, conn))
3693  {
3694  /* We'll come back when there is more data */
3695  return PGRES_POLLING_READING;
3696  }
3697 
3698  /*
3699  * Validate message type: we expect only an authentication
3700  * request, NegotiateProtocolVersion, or an error here.
3701  * Anything else probably means it's not Postgres on the other
3702  * end at all.
3703  */
3704  if (beresp != PqMsg_AuthenticationRequest &&
3705  beresp != PqMsg_ErrorResponse &&
3707  {
3708  libpq_append_conn_error(conn, "expected authentication request from server, but received %c",
3709  beresp);
3710  goto error_return;
3711  }
3712 
3713  /* Read message length word */
3714  if (pqGetInt(&msgLength, 4, conn))
3715  {
3716  /* We'll come back when there is more data */
3717  return PGRES_POLLING_READING;
3718  }
3719 
3720  /*
3721  * Try to validate message length before using it.
3722  *
3723  * Authentication requests can't be very large, although GSS
3724  * auth requests may not be that small. Same for
3725  * NegotiateProtocolVersion.
3726  *
3727  * Errors can be a little larger, but not huge. If we see a
3728  * large apparent length in an error, it means we're really
3729  * talking to a pre-3.0-protocol server; cope. (Before
3730  * version 14, the server also used the old protocol for
3731  * errors that happened before processing the startup packet.)
3732  */
3733  if (beresp == PqMsg_AuthenticationRequest &&
3734  (msgLength < 8 || msgLength > 2000))
3735  {
3736  libpq_append_conn_error(conn, "received invalid authentication request");
3737  goto error_return;
3738  }
3739  if (beresp == PqMsg_NegotiateProtocolVersion &&
3740  (msgLength < 8 || msgLength > 2000))
3741  {
3742  libpq_append_conn_error(conn, "received invalid protocol negotiation message");
3743  goto error_return;
3744  }
3745 
3746 #define MAX_ERRLEN 30000
3747  if (beresp == PqMsg_ErrorResponse &&
3748  (msgLength < 8 || msgLength > MAX_ERRLEN))
3749  {
3750  /* Handle error from a pre-3.0 server */
3751  conn->inCursor = conn->inStart + 1; /* reread data */
3753  {
3754  /*
3755  * We may not have authenticated the server yet, so
3756  * don't let the buffer grow forever.
3757  */
3758  avail = conn->inEnd - conn->inCursor;
3759  if (avail > MAX_ERRLEN)
3760  {
3761  libpq_append_conn_error(conn, "received invalid error message");
3762  goto error_return;
3763  }
3764 
3765  /* We'll come back when there is more data */
3766  return PGRES_POLLING_READING;
3767  }
3768  /* OK, we read the message; mark data consumed */
3769  conn->inStart = conn->inCursor;
3770 
3771  /*
3772  * Before 7.2, the postmaster didn't always end its
3773  * messages with a newline, so add one if needed to
3774  * conform to libpq conventions.
3775  */
3776  if (conn->errorMessage.len == 0 ||
3777  conn->errorMessage.data[conn->errorMessage.len - 1] != '\n')
3778  {
3779