PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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/base64.h"
#include "common/ip.h"
#include "common/link-canary.h"
#include "common/scram-common.h"
#include "common/string.h"
#include "fe-auth.h"
#include "fe-auth-oauth.h"
#include "libpq-fe.h"
#include "libpq-int.h"
#include "mb/pg_wchar.h"
#include "pg_config_paths.h"
#include "port/pg_bswap.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <pwd.h>
#include <pthread.h>
Include dependency graph for fe-connect.c:

Go to the source code of this file.

Data Structures

struct  _internalPQconninfoOption
 

Macros

#define PGPASSFILE   ".pgpass"
 
#define ERRCODE_APPNAME_UNKNOWN   "42704"
 
#define ERRCODE_INVALID_PASSWORD   "28P01"
 
#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"
 
#define DefaultHost   "localhost"
 
#define DefaultOption   ""
 
#define DefaultChannelBinding   "disable"
 
#define DefaultTargetSessionAttrs   "any"
 
#define DefaultLoadBalanceHosts   "disable"
 
#define DefaultSSLMode   "disable"
 
#define DefaultSSLCertMode   "disable"
 
#define DefaultSSLNegotiation   "postgres"
 
#define DefaultGSSMode   "disable"
 
#define SASL_MECHANISM_COUNT   lengthof(supported_sasl_mechs)
 
#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)
 
static bool pqParseProtocolVersion (const char *value, ProtocolVersion *result, PGconn *conn, const char *context)
 
void pqDropConnection (PGconn *conn, bool flushInput)
 
static void pqDropServerData (PGconn *conn)
 
PGconnPQconnectdbParams (const char *const *keywords, const char *const *values, int expand_dbname)
 
PGPing PQpingParams (const char *const *keywords, const char *const *values, int expand_dbname)
 
PGconnPQconnectdb (const char *conninfo)
 
PGPing PQping (const char *conninfo)
 
PGconnPQconnectStartParams (const char *const *keywords, const char *const *values, int expand_dbname)
 
PGconnPQconnectStart (const char *conninfo)
 
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)
 
static void fill_allowed_sasl_mechs (PGconn *conn)
 
static void clear_allowed_sasl_mechs (PGconn *conn)
 
static int index_of_allowed_sasl_mech (PGconn *conn, const pg_fe_sasl_mech *mech)
 
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 * PQservice (const PGconn *conn)
 
char * PQuser (const PGconn *conn)
 
char * PQpass (const PGconn *conn)
 
char * PQhost (const PGconn *conn)
 
char * PQhostaddr (const PGconn *conn)
 
char * PQport (const PGconn *conn)
 
char * PQtty (const PGconn *conn)
 
char * PQoptions (const PGconn *conn)
 
ConnStatusType PQstatus (const PGconn *conn)
 
PGTransactionStatusType PQtransactionStatus (const PGconn *conn)
 
const char * PQparameterStatus (const PGconn *conn, const char *paramName)
 
int PQprotocolVersion (const PGconn *conn)
 
int PQfullProtocolVersion (const PGconn *conn)
 
int PQserverVersion (const PGconn *conn)
 
char * PQerrorMessage (const PGconn *conn)
 
int PQsocket (const PGconn *conn)
 
int PQbackendPID (const PGconn *conn)
 
PGpipelineStatus PQpipelineStatus (const PGconn *conn)
 
int PQconnectionNeedsPassword (const PGconn *conn)
 
int PQconnectionUsedPassword (const PGconn *conn)
 
int PQconnectionUsedGSSAPI (const PGconn *conn)
 
int PQclientEncoding (const PGconn *conn)
 
int PQsetClientEncoding (PGconn *conn, const char *encoding)
 
PGVerbosity PQsetErrorVerbosity (PGconn *conn, PGVerbosity verbosity)
 
PGContextVisibility PQsetErrorContextVisibility (PGconn *conn, PGContextVisibility show_context)
 
PQnoticeReceiver PQsetNoticeReceiver (PGconn *conn, PQnoticeReceiver proc, void *arg)
 
PQnoticeProcessor PQsetNoticeProcessor (PGconn *conn, PQnoticeProcessor proc, void *arg)
 
bool pqGetHomeDirectory (char *buf, int bufsize)
 
bool pqParseIntParam (const char *value, int *result, PGconn *conn, const char *context)
 
pgthreadlock_t PQregisterThreadLock (pgthreadlock_t newhandler)
 

Variables

static const internalPQconninfoOption PQconninfoOptions []
 
static const PQEnvironmentOption EnvironmentOptions []
 
static const pg_fe_sasl_mechsupported_sasl_mechs []
 
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:4783
PGconn * conn
Definition: streamutil.c:52

◆ DefaultChannelBinding

#define DefaultChannelBinding   "disable"

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

◆ DefaultGSSMode

#define DefaultGSSMode   "disable"

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

◆ DefaultHost

#define DefaultHost   "localhost"

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

◆ DefaultLoadBalanceHosts

#define DefaultLoadBalanceHosts   "disable"

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

◆ DefaultOption

#define DefaultOption   ""

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

◆ DefaultSSLCertMode

#define DefaultSSLCertMode   "disable"

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

◆ DefaultSSLMode

#define DefaultSSLMode   "disable"

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

◆ DefaultSSLNegotiation

#define DefaultSSLNegotiation   "postgres"

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

◆ DefaultTargetSessionAttrs

#define DefaultTargetSessionAttrs   "any"

Definition at line 126 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:93
@ PGRES_POLLING_WRITING
Definition: libpq-fe.h:117

◆ ERRCODE_APPNAME_UNKNOWN

#define ERRCODE_APPNAME_UNKNOWN   "42704"

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

◆ ERRCODE_CANNOT_CONNECT_NOW

#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"

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

◆ ERRCODE_INVALID_PASSWORD

#define ERRCODE_INVALID_PASSWORD   "28P01"

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

◆ MAX_ERRLEN

#define MAX_ERRLEN   30000

◆ PGPASSFILE

#define PGPASSFILE   ".pgpass"

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

◆ SASL_MECHANISM_COUNT

#define SASL_MECHANISM_COUNT   lengthof(supported_sasl_mechs)

Definition at line 436 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

◆ clear_allowed_sasl_mechs()

static void clear_allowed_sasl_mechs ( PGconn conn)
inlinestatic

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

1210{
1211 for (int i = 0; i < lengthof(conn->allowed_sasl_mechs); i++)
1212 conn->allowed_sasl_mechs[i] = NULL;
1213}
#define lengthof(array)
Definition: c.h:759
int i
Definition: isn.c:77
const pg_fe_sasl_mech * allowed_sasl_mechs[2]
Definition: libpq-int.h:516

References pg_conn::allowed_sasl_mechs, conn, i, and lengthof.

Referenced by pqConnectOptions2().

◆ connectFailureMessage()

static void connectFailureMessage ( PGconn conn,
int  errorno 
)
static

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

2459{
2460 char sebuf[PG_STRERROR_R_BUFLEN];
2461
2463 "%s\n",
2464 SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
2465
2466 if (conn->raddr.addr.ss_family == AF_UNIX)
2467 libpq_append_conn_error(conn, "\tIs the server running locally and accepting connections on that socket?");
2468 else
2469 libpq_append_conn_error(conn, "\tIs the server running on that host and accepting TCP/IP connections?");
2470}
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition: fe-misc.c:1381
#define SOCK_STRERROR
Definition: libpq-int.h:960
#define PG_STRERROR_R_BUFLEN
Definition: port.h:257
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:671
SockAddr raddr
Definition: libpq-int.h:499

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

4784{
4787
4788 return select_next_encryption_method(conn, false);
4789}
static bool select_next_encryption_method(PGconn *conn, bool have_valid_connection)
Definition: fe-connect.c:4798
Assert(PointerIsAligned(start, uint64))
uint8 failed_enc_methods
Definition: libpq-int.h:604
uint8 current_enc_method
Definition: libpq-int.h:605

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

2344{
2345#ifdef TCP_NODELAY
2346 int on = 1;
2347
2348 if (setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY,
2349 (char *) &on,
2350 sizeof(on)) < 0)
2351 {
2352 char sebuf[PG_STRERROR_R_BUFLEN];
2353
2354 libpq_append_conn_error(conn, "could not set socket to TCP no delay mode: %s",
2355 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2356 return 0;
2357 }
2358#endif
2359
2360 return 1;
2361}
#define SOCK_ERRNO
Definition: libpq-int.h:959
pgsocket sock
Definition: libpq-int.h:496

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

1067{
1068 PQconninfoOption *connOptions;
1069
1070 /*
1071 * Parse the conninfo string
1072 */
1073 connOptions = parse_connection_string(conninfo, &conn->errorMessage, true);
1074 if (connOptions == NULL)
1075 {
1077 /* errorMessage is already set */
1078 return false;
1079 }
1080
1081 /*
1082 * Move option values into conn structure
1083 */
1084 if (!fillPGconn(conn, connOptions))
1085 {
1087 PQconninfoFree(connOptions);
1088 return false;
1089 }
1090
1091 /*
1092 * Free the option info - all is in conn now
1093 */
1094 PQconninfoFree(connOptions);
1095
1096 return true;
1097}
static PQconninfoOption * parse_connection_string(const char *connstr, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:6211
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:7434
static bool fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
Definition: fe-connect.c:987
@ CONNECTION_BAD
Definition: libpq-fe.h:85
ConnStatusType status
Definition: libpq-int.h:459

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

6600{
6602 PQconninfoOption *sslmode_default = NULL,
6603 *sslrootcert = NULL;
6604 char *tmp;
6605
6606 /*
6607 * If there's a service spec, use it to obtain any not-explicitly-given
6608 * parameters. Ignore error if no error message buffer is passed because
6609 * there is no way to pass back the failure message.
6610 */
6611 if (parseServiceInfo(options, errorMessage) != 0 && errorMessage)
6612 return false;
6613
6614 /*
6615 * Get the fallback resources for parameters not specified in the conninfo
6616 * string nor the service.
6617 */
6618 for (option = options; option->keyword != NULL; option++)
6619 {
6620 if (strcmp(option->keyword, "sslrootcert") == 0)
6621 sslrootcert = option; /* save for later */
6622
6623 if (option->val != NULL)
6624 continue; /* Value was in conninfo or service */
6625
6626 /*
6627 * Try to get the environment variable fallback
6628 */
6629 if (option->envvar != NULL)
6630 {
6631 if ((tmp = getenv(option->envvar)) != NULL)
6632 {
6633 option->val = strdup(tmp);
6634 if (!option->val)
6635 {
6636 if (errorMessage)
6637 libpq_append_error(errorMessage, "out of memory");
6638 return false;
6639 }
6640 continue;
6641 }
6642 }
6643
6644 /*
6645 * Interpret the deprecated PGREQUIRESSL environment variable. Per
6646 * tradition, translate values starting with "1" to sslmode=require,
6647 * and ignore other values. Given both PGREQUIRESSL=1 and PGSSLMODE,
6648 * PGSSLMODE takes precedence; the opposite was true before v9.3.
6649 */
6650 if (strcmp(option->keyword, "sslmode") == 0)
6651 {
6652 const char *requiresslenv = getenv("PGREQUIRESSL");
6653
6654 if (requiresslenv != NULL && requiresslenv[0] == '1')
6655 {
6656 option->val = strdup("require");
6657 if (!option->val)
6658 {
6659 if (errorMessage)
6660 libpq_append_error(errorMessage, "out of memory");
6661 return false;
6662 }
6663 continue;
6664 }
6665
6666 /*
6667 * sslmode is not specified. Let it be filled in with the compiled
6668 * default for now, but if sslrootcert=system, we'll override the
6669 * default later before returning.
6670 */
6671 sslmode_default = option;
6672 }
6673
6674 /*
6675 * No environment variable specified or the variable isn't set - try
6676 * compiled-in default
6677 */
6678 if (option->compiled != NULL)
6679 {
6680 option->val = strdup(option->compiled);
6681 if (!option->val)
6682 {
6683 if (errorMessage)
6684 libpq_append_error(errorMessage, "out of memory");
6685 return false;
6686 }
6687 continue;
6688 }
6689
6690 /*
6691 * Special handling for "user" option. Note that if pg_fe_getauthname
6692 * fails, we just leave the value as NULL; there's no need for this to
6693 * be an error condition if the caller provides a user name. The only
6694 * reason we do this now at all is so that callers of PQconndefaults
6695 * will see a correct default (barring error, of course).
6696 */
6697 if (strcmp(option->keyword, "user") == 0)
6698 {
6699 option->val = pg_fe_getauthname(NULL);
6700 continue;
6701 }
6702 }
6703
6704 /*
6705 * Special handling for sslrootcert=system with no sslmode explicitly
6706 * defined. In this case we want to strengthen the default sslmode to
6707 * verify-full.
6708 */
6709 if (sslmode_default && sslrootcert)
6710 {
6711 if (sslrootcert->val && strcmp(sslrootcert->val, "system") == 0)
6712 {
6713 free(sslmode_default->val);
6714
6715 sslmode_default->val = strdup("verify-full");
6716 if (!sslmode_default->val)
6717 {
6718 if (errorMessage)
6719 libpq_append_error(errorMessage, "out of memory");
6720 return false;
6721 }
6722 }
6723 }
6724
6725 return true;
6726}
char * pg_fe_getauthname(PQExpBuffer errorMessage)
Definition: fe-auth.c:1344
static int parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:5904
void libpq_append_error(PQExpBuffer errorMessage, const char *fmt,...)
Definition: fe-misc.c:1352
#define free(a)
Definition: header.h:65
int val
Definition: getopt_long.h:22

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

6444{
6446 PQconninfoOption *dbname_options = NULL;
6448 int i = 0;
6449
6450 /*
6451 * If expand_dbname is non-zero, check keyword "dbname" to see if val is
6452 * actually a recognized connection string.
6453 */
6454 while (expand_dbname && keywords[i])
6455 {
6456 const char *pname = keywords[i];
6457 const char *pvalue = values[i];
6458
6459 /* first find "dbname" if any */
6460 if (strcmp(pname, "dbname") == 0 && pvalue)
6461 {
6462 /*
6463 * If value is a connection string, parse it, but do not use
6464 * defaults here -- those get picked up later. We only want to
6465 * override for those parameters actually passed.
6466 */
6467 if (recognized_connection_string(pvalue))
6468 {
6469 dbname_options = parse_connection_string(pvalue, errorMessage, false);
6470 if (dbname_options == NULL)
6471 return NULL;
6472 }
6473 break;
6474 }
6475 ++i;
6476 }
6477
6478 /* Make a working copy of PQconninfoOptions */
6479 options = conninfo_init(errorMessage);
6480 if (options == NULL)
6481 {
6482 PQconninfoFree(dbname_options);
6483 return NULL;
6484 }
6485
6486 /* Parse the keywords/values arrays */
6487 i = 0;
6488 while (keywords[i])
6489 {
6490 const char *pname = keywords[i];
6491 const char *pvalue = values[i];
6492
6493 if (pvalue != NULL && pvalue[0] != '\0')
6494 {
6495 /* Search for the param record */
6496 for (option = options; option->keyword != NULL; option++)
6497 {
6498 if (strcmp(option->keyword, pname) == 0)
6499 break;
6500 }
6501
6502 /* Check for invalid connection option */
6503 if (option->keyword == NULL)
6504 {
6505 libpq_append_error(errorMessage, "invalid connection option \"%s\"", pname);
6507 PQconninfoFree(dbname_options);
6508 return NULL;
6509 }
6510
6511 /*
6512 * If we are on the first dbname parameter, and we have a parsed
6513 * connection string, copy those parameters across, overriding any
6514 * existing previous settings.
6515 */
6516 if (strcmp(pname, "dbname") == 0 && dbname_options)
6517 {
6518 PQconninfoOption *str_option;
6519
6520 for (str_option = dbname_options; str_option->keyword != NULL; str_option++)
6521 {
6522 if (str_option->val != NULL)
6523 {
6524 int k;
6525
6526 for (k = 0; options[k].keyword; k++)
6527 {
6528 if (strcmp(options[k].keyword, str_option->keyword) == 0)
6529 {
6530 free(options[k].val);
6531 options[k].val = strdup(str_option->val);
6532 if (!options[k].val)
6533 {
6534 libpq_append_error(errorMessage, "out of memory");
6536 PQconninfoFree(dbname_options);
6537 return NULL;
6538 }
6539 break;
6540 }
6541 }
6542 }
6543 }
6544
6545 /*
6546 * Forget the parsed connection string, so that any subsequent
6547 * dbname parameters will not be expanded.
6548 */
6549 PQconninfoFree(dbname_options);
6550 dbname_options = NULL;
6551 }
6552 else
6553 {
6554 /*
6555 * Store the value, overriding previous settings
6556 */
6557 free(option->val);
6558 option->val = strdup(pvalue);
6559 if (!option->val)
6560 {
6561 libpq_append_error(errorMessage, "out of memory");
6563 PQconninfoFree(dbname_options);
6564 return NULL;
6565 }
6566 }
6567 }
6568 ++i;
6569 }
6570 PQconninfoFree(dbname_options);
6571
6572 /*
6573 * Add in defaults if the caller wants that.
6574 */
6575 if (use_defaults)
6576 {
6577 if (!conninfo_add_defaults(options, errorMessage))
6578 {
6580 return NULL;
6581 }
6582 }
6583
6584 return options;
6585}
static Datum values[MAXATTR]
Definition: bootstrap.c:151
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
Definition: fe-connect.c:6172
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
Definition: fe-connect.c:6599
static bool recognized_connection_string(const char *connstr)
Definition: fe-connect.c:6254
long val
Definition: informix.c:689
static const JsonPathKeyword keywords[]
static char ** options

References conninfo_add_defaults(), conninfo_init(), free, i, _PQconninfoOption::keyword, keywords, 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 7372 of file fe-connect.c.

7373{
7375
7376 for (option = connOptions; option->keyword != NULL; option++)
7377 {
7378 if (strcmp(option->keyword, keyword) == 0)
7379 return option;
7380 }
7381
7382 return NULL;
7383}

Referenced by conninfo_getval(), and conninfo_storeval().

◆ conninfo_getval()

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

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

7284{
7286
7287 option = conninfo_find(connOptions, keyword);
7288
7289 return option ? option->val : NULL;
7290}
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:7372

References conninfo_find(), and option::val.

Referenced by fillPGconn(), and parseServiceInfo().

◆ conninfo_init()

static PQconninfoOption * conninfo_init ( PQExpBuffer  errorMessage)
static

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

6173{
6175 PQconninfoOption *opt_dest;
6176 const internalPQconninfoOption *cur_opt;
6177
6178 /*
6179 * Get enough memory for all options in PQconninfoOptions, even if some
6180 * end up being filtered out.
6181 */
6183 if (options == NULL)
6184 {
6185 libpq_append_error(errorMessage, "out of memory");
6186 return NULL;
6187 }
6188 opt_dest = options;
6189
6190 for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++)
6191 {
6192 /* Only copy the public part of the struct, not the full internal */
6193 memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption));
6194 opt_dest++;
6195 }
6196 MemSet(opt_dest, 0, sizeof(PQconninfoOption));
6197
6198 return options;
6199}
#define MemSet(start, val, len)
Definition: c.h:991
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:193
#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 6265 of file fe-connect.c.

6267{
6268 char *pname;
6269 char *pval;
6270 char *buf;
6271 char *cp;
6272 char *cp2;
6274
6275 /* Make a working copy of PQconninfoOptions */
6276 options = conninfo_init(errorMessage);
6277 if (options == NULL)
6278 return NULL;
6279
6280 /* Need a modifiable copy of the input string */
6281 if ((buf = strdup(conninfo)) == NULL)
6282 {
6283 libpq_append_error(errorMessage, "out of memory");
6285 return NULL;
6286 }
6287 cp = buf;
6288
6289 while (*cp)
6290 {
6291 /* Skip blanks before the parameter name */
6292 if (isspace((unsigned char) *cp))
6293 {
6294 cp++;
6295 continue;
6296 }
6297
6298 /* Get the parameter name */
6299 pname = cp;
6300 while (*cp)
6301 {
6302 if (*cp == '=')
6303 break;
6304 if (isspace((unsigned char) *cp))
6305 {
6306 *cp++ = '\0';
6307 while (*cp)
6308 {
6309 if (!isspace((unsigned char) *cp))
6310 break;
6311 cp++;
6312 }
6313 break;
6314 }
6315 cp++;
6316 }
6317
6318 /* Check that there is a following '=' */
6319 if (*cp != '=')
6320 {
6321 libpq_append_error(errorMessage,
6322 "missing \"=\" after \"%s\" in connection info string",
6323 pname);
6325 free(buf);
6326 return NULL;
6327 }
6328 *cp++ = '\0';
6329
6330 /* Skip blanks after the '=' */
6331 while (*cp)
6332 {
6333 if (!isspace((unsigned char) *cp))
6334 break;
6335 cp++;
6336 }
6337
6338 /* Get the parameter value */
6339 pval = cp;
6340
6341 if (*cp != '\'')
6342 {
6343 cp2 = pval;
6344 while (*cp)
6345 {
6346 if (isspace((unsigned char) *cp))
6347 {
6348 *cp++ = '\0';
6349 break;
6350 }
6351 if (*cp == '\\')
6352 {
6353 cp++;
6354 if (*cp != '\0')
6355 *cp2++ = *cp++;
6356 }
6357 else
6358 *cp2++ = *cp++;
6359 }
6360 *cp2 = '\0';
6361 }
6362 else
6363 {
6364 cp2 = pval;
6365 cp++;
6366 for (;;)
6367 {
6368 if (*cp == '\0')
6369 {
6370 libpq_append_error(errorMessage, "unterminated quoted string in connection info string");
6372 free(buf);
6373 return NULL;
6374 }
6375 if (*cp == '\\')
6376 {
6377 cp++;
6378 if (*cp != '\0')
6379 *cp2++ = *cp++;
6380 continue;
6381 }
6382 if (*cp == '\'')
6383 {
6384 *cp2 = '\0';
6385 cp++;
6386 break;
6387 }
6388 *cp2++ = *cp++;
6389 }
6390 }
6391
6392 /*
6393 * Now that we have the name and the value, store the record.
6394 */
6395 if (!conninfo_storeval(options, pname, pval, errorMessage, false, false))
6396 {
6398 free(buf);
6399 return NULL;
6400 }
6401 }
6402
6403 /* Done with the modifiable input string */
6404 free(buf);
6405
6406 /*
6407 * Add in defaults if the caller wants that.
6408 */
6409 if (use_defaults)
6410 {
6411 if (!conninfo_add_defaults(options, errorMessage))
6412 {
6414 return NULL;
6415 }
6416 }
6417
6418 return options;
6419}
static PQconninfoOption * conninfo_storeval(PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode)
Definition: fe-connect.c:7308
static char * buf
Definition: pg_test_fsync.c:72

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

7312{
7314 char *value_copy;
7315
7316 /*
7317 * For backwards compatibility, requiressl=1 gets translated to
7318 * sslmode=require, and requiressl=0 gets translated to sslmode=prefer
7319 * (which is the default for sslmode).
7320 */
7321 if (strcmp(keyword, "requiressl") == 0)
7322 {
7323 keyword = "sslmode";
7324 if (value[0] == '1')
7325 value = "require";
7326 else
7327 value = "prefer";
7328 }
7329
7330 option = conninfo_find(connOptions, keyword);
7331 if (option == NULL)
7332 {
7333 if (!ignoreMissing)
7334 libpq_append_error(errorMessage,
7335 "invalid connection option \"%s\"",
7336 keyword);
7337 return NULL;
7338 }
7339
7340 if (uri_decode)
7341 {
7342 value_copy = conninfo_uri_decode(value, errorMessage);
7343 if (value_copy == NULL)
7344 /* conninfo_uri_decode already set an error message */
7345 return NULL;
7346 }
7347 else
7348 {
7349 value_copy = strdup(value);
7350 if (value_copy == NULL)
7351 {
7352 libpq_append_error(errorMessage, "out of memory");
7353 return NULL;
7354 }
7355 }
7356
7357 free(option->val);
7358 option->val = value_copy;
7359
7360 return option;
7361}
static char * conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
Definition: fe-connect.c:7161
static struct @165 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 7161 of file fe-connect.c.

7162{
7163 char *buf; /* result */
7164 char *p; /* output location */
7165 const char *q = str; /* input location */
7166
7167 buf = malloc(strlen(str) + 1);
7168 if (buf == NULL)
7169 {
7170 libpq_append_error(errorMessage, "out of memory");
7171 return NULL;
7172 }
7173 p = buf;
7174
7175 /* skip leading whitespaces */
7176 for (const char *s = q; *s == ' '; s++)
7177 {
7178 q++;
7179 continue;
7180 }
7181
7182 for (;;)
7183 {
7184 if (*q != '%')
7185 {
7186 /* if found a whitespace or NUL, the string ends */
7187 if (*q == ' ' || *q == '\0')
7188 goto end;
7189
7190 /* copy character */
7191 *(p++) = *(q++);
7192 }
7193 else
7194 {
7195 int hi;
7196 int lo;
7197 int c;
7198
7199 ++q; /* skip the percent sign itself */
7200
7201 /*
7202 * Possible EOL will be caught by the first call to
7203 * get_hexdigit(), so we never dereference an invalid q pointer.
7204 */
7205 if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo)))
7206 {
7207 libpq_append_error(errorMessage,
7208 "invalid percent-encoded token: \"%s\"",
7209 str);
7210 free(buf);
7211 return NULL;
7212 }
7213
7214 c = (hi << 4) | lo;
7215 if (c == 0)
7216 {
7217 libpq_append_error(errorMessage,
7218 "forbidden value %%00 in percent-encoded value: \"%s\"",
7219 str);
7220 free(buf);
7221 return NULL;
7222 }
7223 *(p++) = c;
7224 }
7225 }
7226
7227end:
7228
7229 /* skip trailing whitespaces */
7230 for (const char *s = q; *s == ' '; s++)
7231 {
7232 q++;
7233 continue;
7234 }
7235
7236 /* Not at the end of the string yet? Fail. */
7237 if (*q != '\0')
7238 {
7239 libpq_append_error(errorMessage,
7240 "unexpected spaces found in \"%s\", use percent-encoded spaces (%%20) instead",
7241 str);
7242 free(buf);
7243 return NULL;
7244 }
7245
7246 /* Copy NUL terminator */
7247 *p = '\0';
7248
7249 return buf;
7250}
static bool get_hexdigit(char digit, int *value)
Definition: fe-connect.c:7261
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 6734 of file fe-connect.c.

6736{
6738
6739 /* Make a working copy of PQconninfoOptions */
6740 options = conninfo_init(errorMessage);
6741 if (options == NULL)
6742 return NULL;
6743
6744 if (!conninfo_uri_parse_options(options, uri, errorMessage))
6745 {
6747 return NULL;
6748 }
6749
6750 /*
6751 * Add in defaults if the caller wants that.
6752 */
6753 if (use_defaults)
6754 {
6755 if (!conninfo_add_defaults(options, errorMessage))
6756 {
6758 return NULL;
6759 }
6760 }
6761
6762 return options;
6763}
static bool conninfo_uri_parse_options(PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage)
Definition: fe-connect.c:6787

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

6789{
6790 int prefix_len;
6791 char *p;
6792 char *buf = NULL;
6793 char *start;
6794 char prevchar = '\0';
6795 char *user = NULL;
6796 char *host = NULL;
6797 bool retval = false;
6798 PQExpBufferData hostbuf;
6799 PQExpBufferData portbuf;
6800
6801 initPQExpBuffer(&hostbuf);
6802 initPQExpBuffer(&portbuf);
6803 if (PQExpBufferDataBroken(hostbuf) || PQExpBufferDataBroken(portbuf))
6804 {
6805 libpq_append_error(errorMessage, "out of memory");
6806 goto cleanup;
6807 }
6808
6809 /* need a modifiable copy of the input URI */
6810 buf = strdup(uri);
6811 if (buf == NULL)
6812 {
6813 libpq_append_error(errorMessage, "out of memory");
6814 goto cleanup;
6815 }
6816 start = buf;
6817
6818 /* Skip the URI prefix */
6819 prefix_len = uri_prefix_length(uri);
6820 if (prefix_len == 0)
6821 {
6822 /* Should never happen */
6823 libpq_append_error(errorMessage,
6824 "invalid URI propagated to internal parser routine: \"%s\"",
6825 uri);
6826 goto cleanup;
6827 }
6828 start += prefix_len;
6829 p = start;
6830
6831 /* Look ahead for possible user credentials designator */
6832 while (*p && *p != '@' && *p != '/')
6833 ++p;
6834 if (*p == '@')
6835 {
6836 /*
6837 * Found username/password designator, so URI should be of the form
6838 * "scheme://user[:password]@[netloc]".
6839 */
6840 user = start;
6841
6842 p = user;
6843 while (*p != ':' && *p != '@')
6844 ++p;
6845
6846 /* Save last char and cut off at end of user name */
6847 prevchar = *p;
6848 *p = '\0';
6849
6850 if (*user &&
6851 !conninfo_storeval(options, "user", user,
6852 errorMessage, false, true))
6853 goto cleanup;
6854
6855 if (prevchar == ':')
6856 {
6857 const char *password = p + 1;
6858
6859 while (*p != '@')
6860 ++p;
6861 *p = '\0';
6862
6863 if (*password &&
6864 !conninfo_storeval(options, "password", password,
6865 errorMessage, false, true))
6866 goto cleanup;
6867 }
6868
6869 /* Advance past end of parsed user name or password token */
6870 ++p;
6871 }
6872 else
6873 {
6874 /*
6875 * No username/password designator found. Reset to start of URI.
6876 */
6877 p = start;
6878 }
6879
6880 /*
6881 * There may be multiple netloc[:port] pairs, each separated from the next
6882 * by a comma. When we initially enter this loop, "p" has been
6883 * incremented past optional URI credential information at this point and
6884 * now points at the "netloc" part of the URI. On subsequent loop
6885 * iterations, "p" has been incremented past the comma separator and now
6886 * points at the start of the next "netloc".
6887 */
6888 for (;;)
6889 {
6890 /*
6891 * Look for IPv6 address.
6892 */
6893 if (*p == '[')
6894 {
6895 host = ++p;
6896 while (*p && *p != ']')
6897 ++p;
6898 if (!*p)
6899 {
6900 libpq_append_error(errorMessage,
6901 "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"",
6902 uri);
6903 goto cleanup;
6904 }
6905 if (p == host)
6906 {
6907 libpq_append_error(errorMessage,
6908 "IPv6 host address may not be empty in URI: \"%s\"",
6909 uri);
6910 goto cleanup;
6911 }
6912
6913 /* Cut off the bracket and advance */
6914 *(p++) = '\0';
6915
6916 /*
6917 * The address may be followed by a port specifier or a slash or a
6918 * query or a separator comma.
6919 */
6920 if (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',')
6921 {
6922 libpq_append_error(errorMessage,
6923 "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"",
6924 *p, (int) (p - buf + 1), uri);
6925 goto cleanup;
6926 }
6927 }
6928 else
6929 {
6930 /* not an IPv6 address: DNS-named or IPv4 netloc */
6931 host = p;
6932
6933 /*
6934 * Look for port specifier (colon) or end of host specifier
6935 * (slash) or query (question mark) or host separator (comma).
6936 */
6937 while (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',')
6938 ++p;
6939 }
6940
6941 /* Save the hostname terminator before we null it */
6942 prevchar = *p;
6943 *p = '\0';
6944
6945 appendPQExpBufferStr(&hostbuf, host);
6946
6947 if (prevchar == ':')
6948 {
6949 const char *port = ++p; /* advance past host terminator */
6950
6951 while (*p && *p != '/' && *p != '?' && *p != ',')
6952 ++p;
6953
6954 prevchar = *p;
6955 *p = '\0';
6956
6957 appendPQExpBufferStr(&portbuf, port);
6958 }
6959
6960 if (prevchar != ',')
6961 break;
6962 ++p; /* advance past comma separator */
6963 appendPQExpBufferChar(&hostbuf, ',');
6964 appendPQExpBufferChar(&portbuf, ',');
6965 }
6966
6967 /* Save final values for host and port. */
6968 if (PQExpBufferDataBroken(hostbuf) || PQExpBufferDataBroken(portbuf))
6969 goto cleanup;
6970 if (hostbuf.data[0] &&
6971 !conninfo_storeval(options, "host", hostbuf.data,
6972 errorMessage, false, true))
6973 goto cleanup;
6974 if (portbuf.data[0] &&
6975 !conninfo_storeval(options, "port", portbuf.data,
6976 errorMessage, false, true))
6977 goto cleanup;
6978
6979 if (prevchar && prevchar != '?')
6980 {
6981 const char *dbname = ++p; /* advance past host terminator */
6982
6983 /* Look for query parameters */
6984 while (*p && *p != '?')
6985 ++p;
6986
6987 prevchar = *p;
6988 *p = '\0';
6989
6990 /*
6991 * Avoid setting dbname to an empty string, as it forces the default
6992 * value (username) and ignores $PGDATABASE, as opposed to not setting
6993 * it at all.
6994 */
6995 if (*dbname &&
6996 !conninfo_storeval(options, "dbname", dbname,
6997 errorMessage, false, true))
6998 goto cleanup;
6999 }
7000
7001 if (prevchar)
7002 {
7003 ++p; /* advance past terminator */
7004
7005 if (!conninfo_uri_parse_params(p, options, errorMessage))
7006 goto cleanup;
7007 }
7008
7009 /* everything parsed okay */
7010 retval = true;
7011
7012cleanup:
7013 termPQExpBuffer(&hostbuf);
7014 termPQExpBuffer(&portbuf);
7015 free(buf);
7016 return retval;
7017}
static void cleanup(void)
Definition: bootstrap.c:713
static int uri_prefix_length(const char *connstr)
Definition: fe-connect.c:6231
static bool conninfo_uri_parse_params(char *params, PQconninfoOption *connOptions, PQExpBuffer errorMessage)
Definition: fe-connect.c:7028
return str start
static char * user
Definition: pg_regress.c:119
static int port
Definition: pg_regress.c:115
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:51
char * dbname
Definition: streamutil.c:49

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

7031{
7032 while (*params)
7033 {
7034 char *keyword = params;
7035 char *value = NULL;
7036 char *p = params;
7037 bool malloced = false;
7038 int oldmsglen;
7039
7040 /*
7041 * Scan the params string for '=' and '&', marking the end of keyword
7042 * and value respectively.
7043 */
7044 for (;;)
7045 {
7046 if (*p == '=')
7047 {
7048 /* Was there '=' already? */
7049 if (value != NULL)
7050 {
7051 libpq_append_error(errorMessage,
7052 "extra key/value separator \"=\" in URI query parameter: \"%s\"",
7053 keyword);
7054 return false;
7055 }
7056 /* Cut off keyword, advance to value */
7057 *p++ = '\0';
7058 value = p;
7059 }
7060 else if (*p == '&' || *p == '\0')
7061 {
7062 /*
7063 * If not at the end, cut off value and advance; leave p
7064 * pointing to start of the next parameter, if any.
7065 */
7066 if (*p != '\0')
7067 *p++ = '\0';
7068 /* Was there '=' at all? */
7069 if (value == NULL)
7070 {
7071 libpq_append_error(errorMessage,
7072 "missing key/value separator \"=\" in URI query parameter: \"%s\"",
7073 keyword);
7074 return false;
7075 }
7076 /* Got keyword and value, go process them. */
7077 break;
7078 }
7079 else
7080 ++p; /* Advance over all other bytes. */
7081 }
7082
7083 keyword = conninfo_uri_decode(keyword, errorMessage);
7084 if (keyword == NULL)
7085 {
7086 /* conninfo_uri_decode already set an error message */
7087 return false;
7088 }
7089 value = conninfo_uri_decode(value, errorMessage);
7090 if (value == NULL)
7091 {
7092 /* conninfo_uri_decode already set an error message */
7093 free(keyword);
7094 return false;
7095 }
7096 malloced = true;
7097
7098 /*
7099 * Special keyword handling for improved JDBC compatibility.
7100 */
7101 if (strcmp(keyword, "ssl") == 0 &&
7102 strcmp(value, "true") == 0)
7103 {
7104 free(keyword);
7105 free(value);
7106 malloced = false;
7107
7108 keyword = "sslmode";
7109 value = "require";
7110 }
7111
7112 /*
7113 * Store the value if the corresponding option exists; ignore
7114 * otherwise. At this point both keyword and value are not
7115 * URI-encoded.
7116 */
7117 oldmsglen = errorMessage->len;
7118 if (!conninfo_storeval(connOptions, keyword, value,
7119 errorMessage, true, false))
7120 {
7121 /* Insert generic message if conninfo_storeval didn't give one. */
7122 if (errorMessage->len == oldmsglen)
7123 libpq_append_error(errorMessage,
7124 "invalid URI query parameter: \"%s\"",
7125 keyword);
7126 /* And fail. */
7127 if (malloced)
7128 {
7129 free(keyword);
7130 free(value);
7131 }
7132 return false;
7133 }
7134
7135 if (malloced)
7136 {
7137 free(keyword);
7138 free(value);
7139 }
7140
7141 /* Proceed to next key=value pair, if any */
7142 params = p;
7143 }
7144
7145 return true;
7146}

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

1104{
1105 int n;
1106
1107 n = 1;
1108 for (; *input != '\0'; input++)
1109 {
1110 if (*input == ',')
1111 n++;
1112 }
1113
1114 return n;
1115}
FILE * input

References input.

Referenced by pqConnectOptions2().

◆ default_threadlock()

static void default_threadlock ( int  acquire)
static

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

8261{
8262 static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
8263
8264 if (acquire)
8265 {
8266 if (pthread_mutex_lock(&singlethread_lock))
8267 Assert(false);
8268 }
8269 else
8270 {
8271 if (pthread_mutex_unlock(&singlethread_lock))
8272 Assert(false);
8273 }
8274}
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 7838 of file fe-connect.c.

7839{
7840 (void) arg; /* not used */
7841 /* Note: we expect the supplied string to end with a newline already. */
7842 fprintf(stderr, "%s", message);
7843}
#define fprintf(file, fmt, msg)
Definition: cubescan.l:21
void * arg

References arg, and fprintf.

Referenced by pqMakeEmptyPGconn().

◆ defaultNoticeReceiver()

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

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

7824{
7825 (void) arg; /* not used */
7826 if (res->noticeHooks.noticeProc != NULL)
7829}
char * PQresultErrorMessage(const PGresult *res)
Definition: fe-exec.c:3427
void * noticeProcArg
Definition: libpq-int.h:152
PQnoticeProcessor noticeProc
Definition: libpq-int.h:151
PGNoticeHooks noticeHooks
Definition: libpq-int.h:183

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

Referenced by pqMakeEmptyPGconn().

◆ emitHostIdentityInfo()

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

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

2403{
2404 if (conn->raddr.addr.ss_family == AF_UNIX)
2405 {
2406 char service[NI_MAXHOST];
2407
2409 NULL, 0,
2410 service, sizeof(service),
2411 NI_NUMERICSERV);
2413 libpq_gettext("connection to server on socket \"%s\" failed: "),
2414 service);
2415 }
2416 else
2417 {
2418 const char *displayed_host;
2419 const char *displayed_port;
2420
2421 /* To which host and port were we actually connecting? */
2423 displayed_host = conn->connhost[conn->whichhost].hostaddr;
2424 else
2425 displayed_host = conn->connhost[conn->whichhost].host;
2426 displayed_port = conn->connhost[conn->whichhost].port;
2427 if (displayed_port == NULL || displayed_port[0] == '\0')
2428 displayed_port = DEF_PGPORT_STR;
2429
2430 /*
2431 * If the user did not supply an IP address using 'hostaddr', and
2432 * 'host' was missing or does not match our lookup, display the
2433 * looked-up IP address.
2434 */
2436 host_addr[0] &&
2437 strcmp(displayed_host, host_addr) != 0)
2439 libpq_gettext("connection to server at \"%s\" (%s), port %s failed: "),
2440 displayed_host, host_addr,
2441 displayed_port);
2442 else
2444 libpq_gettext("connection to server at \"%s\", port %s failed: "),
2445 displayed_host,
2446 displayed_port);
2447 }
2448}
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:938
@ CHT_HOST_ADDRESS
Definition: libpq-int.h:310
socklen_t salen
Definition: pqcomm.h:33
char * host
Definition: libpq-int.h:358
char * port
Definition: libpq-int.h:360
char * hostaddr
Definition: libpq-int.h:359
pg_conn_host_type type
Definition: libpq-int.h:357
int whichhost
Definition: libpq-int.h:478
pg_conn_host * connhost
Definition: libpq-int.h:479

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

◆ fill_allowed_sasl_mechs()

static void fill_allowed_sasl_mechs ( PGconn conn)
inlinestatic

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

1186{
1187 /*---
1188 * We only support two mechanisms at the moment, so rather than deal with a
1189 * linked list, conn->allowed_sasl_mechs is an array of static length. We
1190 * rely on the compile-time assertion here to keep us honest.
1191 *
1192 * To add a new mechanism to require_auth,
1193 * - add it to supported_sasl_mechs,
1194 * - update the length of conn->allowed_sasl_mechs,
1195 * - handle the new mechanism name in the require_auth portion of
1196 * pqConnectOptions2(), below.
1197 */
1199 "conn->allowed_sasl_mechs[] is not sufficiently large for holding all supported SASL mechanisms");
1200
1201 for (int i = 0; i < SASL_MECHANISM_COUNT; i++)
1203}
#define StaticAssertDecl(condition, errmessage)
Definition: c.h:907
#define SASL_MECHANISM_COUNT
Definition: fe-connect.c:436
static const pg_fe_sasl_mech * supported_sasl_mechs[]
Definition: fe-connect.c:431

References pg_conn::allowed_sasl_mechs, conn, i, lengthof, SASL_MECHANISM_COUNT, StaticAssertDecl, and supported_sasl_mechs.

Referenced by pqConnectOptions2().

◆ fillPGconn()

static bool fillPGconn ( PGconn conn,
PQconninfoOption connOptions 
)
static

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

988{
990
991 for (option = PQconninfoOptions; option->keyword; option++)
992 {
993 if (option->connofs >= 0)
994 {
995 const char *tmp = conninfo_getval(connOptions, option->keyword);
996
997 if (tmp)
998 {
999 char **connmember = (char **) ((char *) conn + option->connofs);
1000
1001 free(*connmember);
1002 *connmember = strdup(tmp);
1003 if (*connmember == NULL)
1004 {
1005 libpq_append_conn_error(conn, "out of memory");
1006 return false;
1007 }
1008 }
1009 }
1010 }
1011
1012 return true;
1013}
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:7282

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

5038{
5039 /* let any event procs clean up their state data */
5040 for (int i = 0; i < conn->nEvents; i++)
5041 {
5043
5044 evt.conn = conn;
5045 (void) conn->events[i].proc(PGEVT_CONNDESTROY, &evt,
5047 free(conn->events[i].name);
5048 }
5049
5052
5054 free(conn->events);
5055 free(conn->pghost);
5057 free(conn->pgport);
5061 free(conn->appname);
5063 free(conn->dbName);
5065 free(conn->pguser);
5066 if (conn->pgpass)
5067 {
5068 explicit_bzero(conn->pgpass, strlen(conn->pgpass));
5069 free(conn->pgpass);
5070 }
5077 free(conn->sslmode);
5079 free(conn->sslcert);
5080 free(conn->sslkey);
5081 if (conn->sslpassword)
5082 {
5085 }
5088 free(conn->sslcrl);
5091 free(conn->sslsni);
5098 free(conn->gsslib);
5100 free(conn->connip);
5101 /* Note that conn->Pfdebug is not ours to close or free */
5103 free(conn->inBuffer);
5105 free(conn->rowBuf);
5118
5119 free(conn);
5120}
static void release_conn_addrinfo(PGconn *conn)
Definition: fe-connect.c:5195
void pqReleaseConnHosts(PGconn *conn)
Definition: fe-connect.c:5127
@ PGEVT_CONNDESTROY
Definition: libpq-events.h:31
void explicit_bzero(void *buf, size_t len)
void * passThrough
Definition: libpq-int.h:159
char * name
Definition: libpq-int.h:158
PGEventProc proc
Definition: libpq-int.h:157
char * replication
Definition: libpq-int.h:390
char * write_err_msg
Definition: libpq-int.h:510
char * sslrootcert
Definition: libpq-int.h:410
PGdataValue * rowBuf
Definition: libpq-int.h:581
char * sslnegotiation
Definition: libpq-int.h:404
char * sslcompression
Definition: libpq-int.h:405
char * oauth_discovery_uri
Definition: libpq-int.h:438
char * oauth_scope
Definition: libpq-int.h:442
char * require_auth
Definition: libpq-int.h:425
char * inBuffer
Definition: libpq-int.h:564
char * channel_binding
Definition: libpq-int.h:395
char * sslcrldir
Definition: libpq-int.h:412
char * gssdelegation
Definition: libpq-int.h:419
char * pgoptions
Definition: libpq-int.h:386
char * sslcrl
Definition: libpq-int.h:411
char * pghost
Definition: libpq-int.h:373
char * ssl_max_protocol_version
Definition: libpq-int.h:423
char * pgpass
Definition: libpq-int.h:393
char * dbName
Definition: libpq-int.h:389
char * oauth_client_id
Definition: libpq-int.h:440
char * oauth_issuer
Definition: libpq-int.h:436
char * fbappname
Definition: libpq-int.h:388
char * sslcert
Definition: libpq-int.h:407
char * sslcertmode
Definition: libpq-int.h:409
char * target_session_attrs
Definition: libpq-int.h:424
char * sslpassword
Definition: libpq-int.h:408
PQExpBufferData workBuffer
Definition: libpq-int.h:675
char * keepalives_idle
Definition: libpq-int.h:398
char * connip
Definition: libpq-int.h:480
char * oauth_client_secret
Definition: libpq-int.h:441
char * load_balance_hosts
Definition: libpq-int.h:426
char * pguser
Definition: libpq-int.h:392
char * keepalives
Definition: libpq-int.h:397
char * client_encoding_initial
Definition: libpq-int.h:385
char * keepalives_interval
Definition: libpq-int.h:399
char * appname
Definition: libpq-int.h:387
char * sslmode
Definition: libpq-int.h:403
char * pgtcp_user_timeout
Definition: libpq-int.h:384
char * ssl_min_protocol_version
Definition: libpq-int.h:422
char * oauth_issuer_id
Definition: libpq-int.h:437
char * gssencmode
Definition: libpq-int.h:415
char * scram_server_key
Definition: libpq-int.h:428
int nEvents
Definition: libpq-int.h:455
char * pghostaddr
Definition: libpq-int.h:377
char * sslkey
Definition: libpq-int.h:406
char * scram_client_key
Definition: libpq-int.h:427
char * pgpassfile
Definition: libpq-int.h:394
char * connect_timeout
Definition: libpq-int.h:383
char * krbsrvname
Definition: libpq-int.h:416
char * gsslib
Definition: libpq-int.h:417
char * pgport
Definition: libpq-int.h:381
char * keepalives_count
Definition: libpq-int.h:401
char * requirepeer
Definition: libpq-int.h:414
char * sslsni
Definition: libpq-int.h:413
PGEvent * events
Definition: libpq-int.h:454
char * outBuffer
Definition: libpq-int.h:571

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::oauth_client_id, pg_conn::oauth_client_secret, pg_conn::oauth_discovery_uri, pg_conn::oauth_issuer, pg_conn::oauth_issuer_id, pg_conn::oauth_scope, 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::scram_client_key, pg_conn::scram_server_key, 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 7261 of file fe-connect.c.

7262{
7263 if ('0' <= digit && digit <= '9')
7264 *value = digit - '0';
7265 else if ('A' <= digit && digit <= 'F')
7266 *value = digit - 'A' + 10;
7267 else if ('a' <= digit && digit <= 'f')
7268 *value = digit - 'a' + 10;
7269 else
7270 return false;
7271
7272 return true;
7273}

References value.

Referenced by conninfo_uri_decode().

◆ getHostaddr()

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

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

2370{
2371 struct sockaddr_storage *addr = &conn->raddr.addr;
2372
2373 if (addr->ss_family == AF_INET)
2374 {
2375 if (pg_inet_net_ntop(AF_INET,
2376 &((struct sockaddr_in *) addr)->sin_addr.s_addr,
2377 32,
2378 host_addr, host_addr_len) == NULL)
2379 host_addr[0] = '\0';
2380 }
2381 else if (addr->ss_family == AF_INET6)
2382 {
2383 if (pg_inet_net_ntop(AF_INET6,
2384 &((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr,
2385 128,
2386 host_addr, host_addr_len) == NULL)
2387 host_addr[0] = '\0';
2388 }
2389 else
2390 host_addr[0] = '\0';
2391}
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().

◆ index_of_allowed_sasl_mech()

static int index_of_allowed_sasl_mech ( PGconn conn,
const pg_fe_sasl_mech mech 
)
inlinestatic

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

1221{
1222 for (int i = 0; i < lengthof(conn->allowed_sasl_mechs); i++)
1223 {
1224 if (conn->allowed_sasl_mechs[i] == mech)
1225 return i;
1226 }
1227
1228 return -1;
1229}

References pg_conn::allowed_sasl_mechs, conn, i, and lengthof.

Referenced by pqConnectOptions2().

◆ init_allowed_encryption_methods()

static bool init_allowed_encryption_methods ( PGconn conn)
static

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

4694{
4695 if (conn->raddr.addr.ss_family == AF_UNIX)
4696 {
4697 /* Don't request SSL or GSSAPI over Unix sockets */
4699
4700 /*
4701 * XXX: we probably should not do this. sslmode=require works
4702 * differently
4703 */
4704 if (conn->gssencmode[0] == 'r')
4705 {
4707 "GSSAPI encryption required but it is not supported over a local socket");
4710 return false;
4711 }
4712
4715 return true;
4716 }
4717
4718 /* initialize based on sslmode and gssencmode */
4720
4721#ifdef USE_SSL
4722 /* sslmode anything but 'disable', and GSSAPI not required */
4723 if (conn->sslmode[0] != 'd' && conn->gssencmode[0] != 'r')
4724 {
4726 }
4727#endif
4728
4729#ifdef ENABLE_GSS
4730 if (conn->gssencmode[0] != 'd')
4732#endif
4733
4734 if ((conn->sslmode[0] == 'd' || conn->sslmode[0] == 'p' || conn->sslmode[0] == 'a') &&
4735 (conn->gssencmode[0] == 'd' || conn->gssencmode[0] == 'p'))
4736 {
4738 }
4739
4740 return select_next_encryption_method(conn, false);
4741}
#define ENC_PLAINTEXT
Definition: libpq-int.h:230
#define ENC_GSSAPI
Definition: libpq-int.h:231
#define ENC_SSL
Definition: libpq-int.h:232
#define ENC_ERROR
Definition: libpq-int.h:229
uint8 allowed_enc_methods
Definition: libpq-int.h:603

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

4874{
4875 /* Say "no attempt" if we never got to PQconnectPoll */
4876 if (!conn || !conn->options_valid)
4877 return PQPING_NO_ATTEMPT;
4878
4879 /* Attempt to complete the connection */
4880 if (conn->status != CONNECTION_BAD)
4881 (void) pqConnectDBComplete(conn);
4882
4883 /* Definitely OK if we succeeded */
4884 if (conn->status != CONNECTION_BAD)
4885 return PQPING_OK;
4886
4887 /*
4888 * Here begins the interesting part of "ping": determine the cause of the
4889 * failure in sufficient detail to decide what to return. We do not want
4890 * to report that the server is not up just because we didn't have a valid
4891 * password, for example. In fact, any sort of authentication request
4892 * implies the server is up. (We need this check since the libpq side of
4893 * things might have pulled the plug on the connection before getting an
4894 * error as such from the postmaster.)
4895 */
4897 return PQPING_OK;
4898
4899 /*
4900 * If we failed to get any ERROR response from the postmaster, report
4901 * PQPING_NO_RESPONSE. This result could be somewhat misleading for a
4902 * pre-7.4 server, since it won't send back a SQLSTATE, but those are long
4903 * out of support. Another corner case where the server could return a
4904 * failure without a SQLSTATE is fork failure, but PQPING_NO_RESPONSE
4905 * isn't totally unreasonable for that anyway. We expect that every other
4906 * failure case in a modern server will produce a report with a SQLSTATE.
4907 *
4908 * NOTE: whenever we get around to making libpq generate SQLSTATEs for
4909 * client-side errors, we should either not store those into
4910 * last_sqlstate, or add an extra flag so we can tell client-side errors
4911 * apart from server-side ones.
4912 */
4913 if (strlen(conn->last_sqlstate) != 5)
4914 return PQPING_NO_RESPONSE;
4915
4916 /*
4917 * Report PQPING_REJECT if server says it's not accepting connections.
4918 */
4920 return PQPING_REJECT;
4921
4922 /*
4923 * Any other SQLSTATE can be taken to indicate that the server is up.
4924 * Presumably it didn't like our username, password, or database name; or
4925 * perhaps it had some transient failure, but that should not be taken as
4926 * meaning "it's down".
4927 */
4928 return PQPING_OK;
4929}
#define ERRCODE_CANNOT_CONNECT_NOW
Definition: fe-connect.c:94
int pqConnectDBComplete(PGconn *conn)
Definition: fe-connect.c:2779
@ PQPING_OK
Definition: libpq-fe.h:176
@ PQPING_REJECT
Definition: libpq-fe.h:177
@ PQPING_NO_RESPONSE
Definition: libpq-fe.h:178
@ PQPING_NO_ATTEMPT
Definition: libpq-fe.h:179
bool auth_req_received
Definition: libpq-int.h:504
char last_sqlstate[6]
Definition: libpq-int.h:462
bool options_valid
Definition: libpq-int.h:463

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

1163{
1164 uint64 rseed;
1165 struct timeval tval = {0};
1166
1168 return;
1169
1170 gettimeofday(&tval, NULL);
1171
1172 rseed = ((uintptr_t) conn) ^
1173 ((uint64) getpid()) ^
1174 ((uint64) tval.tv_usec) ^
1175 ((uint64) tval.tv_sec);
1176
1177 pg_prng_seed(&conn->prng_state, rseed);
1178}
uint64_t uint64
Definition: c.h:503
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:560
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 1127 of file fe-connect.c.

1128{
1129 char *p;
1130 char *s = *startptr;
1131 char *e;
1132 int len;
1133
1134 /*
1135 * Search for the end of the current element; a comma or end-of-string
1136 * acts as a terminator.
1137 */
1138 e = s;
1139 while (*e != '\0' && *e != ',')
1140 ++e;
1141 *more = (*e == ',');
1142
1143 len = e - s;
1144 p = (char *) malloc(sizeof(char) * (len + 1));
1145 if (p)
1146 {
1147 memcpy(p, s, len);
1148 p[len] = '\0';
1149 }
1150 *startptr = e + 1;
1151
1152 return p;
1153}
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 6211 of file fe-connect.c.

6213{
6214 /* Parse as URI if connection string matches URI prefix */
6215 if (uri_prefix_length(connstr) != 0)
6216 return conninfo_uri_parse(connstr, errorMessage, use_defaults);
6217
6218 /* Parse as default otherwise */
6219 return conninfo_parse(connstr, errorMessage, use_defaults);
6220}
static PQconninfoOption * conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:6734
static PQconninfoOption * conninfo_parse(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:6265
static const char * connstr
Definition: pg_dumpall.c:84

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

5977{
5978 int result = 0,
5979 linenr = 0,
5980 i;
5981 FILE *f;
5982 char *line;
5983 char buf[1024];
5984
5985 *group_found = false;
5986
5987 f = fopen(serviceFile, "r");
5988 if (f == NULL)
5989 {
5990 libpq_append_error(errorMessage, "service file \"%s\" not found", serviceFile);
5991 return 1;
5992 }
5993
5994 while ((line = fgets(buf, sizeof(buf), f)) != NULL)
5995 {
5996 int len;
5997
5998 linenr++;
5999
6000 if (strlen(line) >= sizeof(buf) - 1)
6001 {
6002 libpq_append_error(errorMessage,
6003 "line %d too long in service file \"%s\"",
6004 linenr,
6005 serviceFile);
6006 result = 2;
6007 goto exit;
6008 }
6009
6010 /* ignore whitespace at end of line, especially the newline */
6011 len = strlen(line);
6012 while (len > 0 && isspace((unsigned char) line[len - 1]))
6013 line[--len] = '\0';
6014
6015 /* ignore leading whitespace too */
6016 while (*line && isspace((unsigned char) line[0]))
6017 line++;
6018
6019 /* ignore comments and empty lines */
6020 if (line[0] == '\0' || line[0] == '#')
6021 continue;
6022
6023 /* Check for right groupname */
6024 if (line[0] == '[')
6025 {
6026 if (*group_found)
6027 {
6028 /* end of desired group reached; return success */
6029 goto exit;
6030 }
6031
6032 if (strncmp(line + 1, service, strlen(service)) == 0 &&
6033 line[strlen(service) + 1] == ']')
6034 *group_found = true;
6035 else
6036 *group_found = false;
6037 }
6038 else
6039 {
6040 if (*group_found)
6041 {
6042 /*
6043 * Finally, we are in the right group and can parse the line
6044 */
6045 char *key,
6046 *val;
6047 bool found_keyword;
6048
6049#ifdef USE_LDAP
6050 if (strncmp(line, "ldap", 4) == 0)
6051 {
6052 int rc = ldapServiceLookup(line, options, errorMessage);
6053
6054 /* if rc = 2, go on reading for fallback */
6055 switch (rc)
6056 {
6057 case 0:
6058 goto exit;
6059 case 1:
6060 case 3:
6061 result = 3;
6062 goto exit;
6063 case 2:
6064 continue;
6065 }
6066 }
6067#endif
6068
6069 key = line;
6070 val = strchr(line, '=');
6071 if (val == NULL)
6072 {
6073 libpq_append_error(errorMessage,
6074 "syntax error in service file \"%s\", line %d",
6075 serviceFile,
6076 linenr);
6077 result = 3;
6078 goto exit;
6079 }
6080 *val++ = '\0';
6081
6082 if (strcmp(key, "service") == 0)
6083 {
6084 libpq_append_error(errorMessage,
6085 "nested service specifications not supported in service file \"%s\", line %d",
6086 serviceFile,
6087 linenr);
6088 result = 3;
6089 goto exit;
6090 }
6091
6092 /*
6093 * Set the parameter --- but don't override any previous
6094 * explicit setting.
6095 */
6096 found_keyword = false;
6097 for (i = 0; options[i].keyword; i++)
6098 {
6099 if (strcmp(options[i].keyword, key) == 0)
6100 {
6101 if (options[i].val == NULL)
6102 options[i].val = strdup(val);
6103 if (!options[i].val)
6104 {
6105 libpq_append_error(errorMessage, "out of memory");
6106 result = 3;
6107 goto exit;
6108 }
6109 found_keyword = true;
6110 break;
6111 }
6112 }
6113
6114 if (!found_keyword)
6115 {
6116 libpq_append_error(errorMessage,
6117 "syntax error in service file \"%s\", line %d",
6118 serviceFile,
6119 linenr);
6120 result = 3;
6121 goto exit;
6122 }
6123 }
6124 }
6125 }
6126
6127exit:
6128 fclose(f);
6129
6130 return result;
6131}

References buf, 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 5904 of file fe-connect.c.

5905{
5906 const char *service = conninfo_getval(options, "service");
5907 char serviceFile[MAXPGPATH];
5908 char *env;
5909 bool group_found = false;
5910 int status;
5911 struct stat stat_buf;
5912
5913 /*
5914 * We have to special-case the environment variable PGSERVICE here, since
5915 * this is and should be called before inserting environment defaults for
5916 * other connection options.
5917 */
5918 if (service == NULL)
5919 service = getenv("PGSERVICE");
5920
5921 /* If no service name given, nothing to do */
5922 if (service == NULL)
5923 return 0;
5924
5925 /*
5926 * Try PGSERVICEFILE if specified, else try ~/.pg_service.conf (if that
5927 * exists).
5928 */
5929 if ((env = getenv("PGSERVICEFILE")) != NULL)
5930 strlcpy(serviceFile, env, sizeof(serviceFile));
5931 else
5932 {
5933 char homedir[MAXPGPATH];
5934
5935 if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
5936 goto next_file;
5937 snprintf(serviceFile, MAXPGPATH, "%s/%s", homedir, ".pg_service.conf");
5938 if (stat(serviceFile, &stat_buf) != 0)
5939 goto next_file;
5940 }
5941
5942 status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
5943 if (group_found || status != 0)
5944 return status;
5945
5946next_file:
5947
5948 /*
5949 * This could be used by any application so we can't use the binary
5950 * location to find our config files.
5951 */
5952 snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf",
5953 getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);
5954 if (stat(serviceFile, &stat_buf) != 0)
5955 goto last_file;
5956
5957 status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
5958 if (status != 0)
5959 return status;
5960
5961last_file:
5962 if (!group_found)
5963 {
5964 libpq_append_error(errorMessage, "definition of service \"%s\" not found", service);
5965 return 3;
5966 }
5967
5968 return 0;
5969}
static int parseServiceFile(const char *serviceFile, const char *service, PQconninfoOption *options, PQExpBuffer errorMessage, bool *group_found)
Definition: fe-connect.c:5972
bool pqGetHomeDirectory(char *buf, int bufsize)
Definition: fe-connect.c:8136
#define MAXPGPATH
#define snprintf
Definition: port.h:239
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
#define stat
Definition: win32_port.h:274

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

7889{
7890 FILE *fp;
7891#ifndef WIN32
7892 struct stat stat_buf;
7893#endif
7895
7896 if (dbname == NULL || dbname[0] == '\0')
7897 return NULL;
7898
7899 if (username == NULL || username[0] == '\0')
7900 return NULL;
7901
7902 /* 'localhost' matches pghost of '' or the default socket directory */
7903 if (hostname == NULL || hostname[0] == '\0')
7905 else if (is_unixsock_path(hostname))
7906
7907 /*
7908 * We should probably use canonicalize_path(), but then we have to
7909 * bring path.c into libpq, and it doesn't seem worth it.
7910 */
7911 if (strcmp(hostname, DEFAULT_PGSOCKET_DIR) == 0)
7913
7914 if (port == NULL || port[0] == '\0')
7915 port = DEF_PGPORT_STR;
7916
7917 /* If password file cannot be opened, ignore it. */
7918 fp = fopen(pgpassfile, "r");
7919 if (fp == NULL)
7920 return NULL;
7921
7922#ifndef WIN32
7923 if (fstat(fileno(fp), &stat_buf) != 0)
7924 {
7925 fclose(fp);
7926 return NULL;
7927 }
7928
7929 if (!S_ISREG(stat_buf.st_mode))
7930 {
7931 fprintf(stderr,
7932 libpq_gettext("WARNING: password file \"%s\" is not a plain file\n"),
7933 pgpassfile);
7934 fclose(fp);
7935 return NULL;
7936 }
7937
7938 /* If password file is insecure, alert the user and ignore it. */
7939 if (stat_buf.st_mode & (S_IRWXG | S_IRWXO))
7940 {
7941 fprintf(stderr,
7942 libpq_gettext("WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
7943 pgpassfile);
7944 fclose(fp);
7945 return NULL;
7946 }
7947#else
7948
7949 /*
7950 * On Win32, the directory is protected, so we don't have to check the
7951 * file.
7952 */
7953#endif
7954
7955 /* Use an expansible buffer to accommodate any reasonable line length */
7957
7958 while (!feof(fp) && !ferror(fp))
7959 {
7960 /* Make sure there's a reasonable amount of room in the buffer */
7961 if (!enlargePQExpBuffer(&buf, 128))
7962 break;
7963
7964 /* Read some data, appending it to what we already have */
7965 if (fgets(buf.data + buf.len, buf.maxlen - buf.len, fp) == NULL)
7966 break;
7967 buf.len += strlen(buf.data + buf.len);
7968
7969 /* If we don't yet have a whole line, loop around to read more */
7970 if (!(buf.len > 0 && buf.data[buf.len - 1] == '\n') && !feof(fp))
7971 continue;
7972
7973 /* ignore comments */
7974 if (buf.data[0] != '#')
7975 {
7976 char *t = buf.data;
7977 int len;
7978
7979 /* strip trailing newline and carriage return */
7980 len = pg_strip_crlf(t);
7981
7982 if (len > 0 &&
7983 (t = pwdfMatchesString(t, hostname)) != NULL &&
7984 (t = pwdfMatchesString(t, port)) != NULL &&
7985 (t = pwdfMatchesString(t, dbname)) != NULL &&
7986 (t = pwdfMatchesString(t, username)) != NULL)
7987 {
7988 /* Found a match. */
7989 char *ret,
7990 *p1,
7991 *p2;
7992
7993 ret = strdup(t);
7994
7995 fclose(fp);
7996 explicit_bzero(buf.data, buf.maxlen);
7998
7999 if (!ret)
8000 {
8001 /* Out of memory. XXX: an error message would be nice. */
8002 return NULL;
8003 }
8004
8005 /* De-escape password. */
8006 for (p1 = p2 = ret; *p1 != ':' && *p1 != '\0'; ++p1, ++p2)
8007 {
8008 if (*p1 == '\\' && p1[1] != '\0')
8009 ++p1;
8010 *p2 = *p1;
8011 }
8012 *p2 = '\0';
8013
8014 return ret;
8015 }
8016 }
8017
8018 /* No match, reset buffer to prepare for next line. */
8019 buf.len = 0;
8020 }
8021
8022 fclose(fp);
8023 explicit_bzero(buf.data, buf.maxlen);
8025 return NULL;
8026}
#define DefaultHost
Definition: fe-connect.c:119
static char * pwdfMatchesString(char *buf, const char *token)
Definition: fe-connect.c:7850
static char * username
Definition: initdb.c:153
#define DEFAULT_PGSOCKET_DIR
static char * hostname
Definition: pg_regress.c:114
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:154
#define S_IRWXG
Definition: win32_port.h:300
#define S_IRWXO
Definition: win32_port.h:312
#define fstat
Definition: win32_port.h:273
#define S_ISREG(m)
Definition: win32_port.h:318

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

Referenced by pqConnectOptions2().

◆ pgpassfileWarning()

static void pgpassfileWarning ( PGconn conn)
static

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

8035{
8036 /* If it was 'invalid authorization', add pgpassfile mention */
8037 /* only works with >= 9.0 servers */
8038 if (conn->password_needed &&
8039 conn->connhost[conn->whichhost].password != NULL &&
8040 conn->result)
8041 {
8042 const char *sqlstate = PQresultErrorField(conn->result,
8044
8045 if (sqlstate && strcmp(sqlstate, ERRCODE_INVALID_PASSWORD) == 0)
8046 libpq_append_conn_error(conn, "password retrieved from file \"%s\"",
8047 conn->pgpassfile);
8048 }
8049}
#define ERRCODE_INVALID_PASSWORD
Definition: fe-connect.c:92
char * PQresultErrorField(const PGresult *res, int fieldcode)
Definition: fe-exec.c:3466
#define PG_DIAG_SQLSTATE
Definition: postgres_ext.h:52
char * password
Definition: libpq-int.h:361
PGresult * result
Definition: libpq-int.h:594
bool password_needed
Definition: libpq-int.h:505

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)

◆ PQclientEncoding()

◆ pqClosePGconn()

void pqClosePGconn ( PGconn conn)

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

5244{
5245 /*
5246 * If possible, send Terminate message to close the connection politely.
5247 */
5249
5250 /*
5251 * Must reset the blocking status so a possible reconnect will work.
5252 *
5253 * Don't call PQsetnonblocking() because it will fail if it's unable to
5254 * flush the connection.
5255 */
5256 conn->nonblocking = false;
5257
5258 /*
5259 * Close the connection, reset all transient state, flush I/O buffers.
5260 * Note that this includes clearing conn's error state; we're no longer
5261 * interested in any failures associated with the old connection, and we
5262 * want a clean slate for any new connection attempt.
5263 */
5264 pqDropConnection(conn, true);
5265 conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
5270 pqClearAsyncResult(conn); /* deallocate result */
5272
5273 /*
5274 * Release addrinfo, but since cancel requests never change their addrinfo
5275 * we don't do that. Otherwise we would have to rebuild it during a
5276 * PQcancelReset.
5277 */
5278 if (!conn->cancelRequest)
5280
5281 /* Reset all state obtained from server, too */
5283}
void pqClearOAuthToken(PGconn *conn)
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:520
static void sendTerminateConn(PGconn *conn)
Definition: fe-connect.c:5209
static void pqDropServerData(PGconn *conn)
Definition: fe-connect.c:646
void pqClearAsyncResult(PGconn *conn)
Definition: fe-exec.c:779
@ PQTRANS_IDLE
Definition: libpq-fe.h:147
@ PQ_PIPELINE_OFF
Definition: libpq-fe.h:187
@ PGASYNC_IDLE
Definition: libpq-int.h:215
#define pqClearConnErrorState(conn)
Definition: libpq-int.h:911
PGTransactionStatusType xactStatus
Definition: libpq-int.h:461
bool cancelRequest
Definition: libpq-int.h:431
bool nonblocking
Definition: libpq-int.h:464
PGAsyncStatusType asyncStatus
Definition: libpq-int.h:460
PGpipelineStatus pipelineStatus
Definition: libpq-int.h:466

References pg_conn::asyncStatus, pg_conn::cancelRequest, conn, CONNECTION_BAD, pg_conn::nonblocking, PGASYNC_IDLE, pg_conn::pipelineStatus, PQ_PIPELINE_OFF, pqClearAsyncResult(), pqClearConnErrorState, pqClearOAuthToken(), 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 2190 of file fe-connect.c.

2191{
2192 PQExpBufferData errorBuf;
2193 PQconninfoOption *connOptions;
2194
2195 /* We don't actually report any errors here, but callees want a buffer */
2196 initPQExpBuffer(&errorBuf);
2197 if (PQExpBufferDataBroken(errorBuf))
2198 return NULL; /* out of memory already :-( */
2199
2200 connOptions = conninfo_init(&errorBuf);
2201 if (connOptions != NULL)
2202 {
2203 /* pass NULL errorBuf to ignore errors */
2204 if (!conninfo_add_defaults(connOptions, NULL))
2205 {
2206 PQconninfoFree(connOptions);
2207 connOptions = NULL;
2208 }
2209 }
2210
2211 termPQExpBuffer(&errorBuf);
2212 return connOptions;
2213}

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

814{
815 PGconn *conn = PQconnectStart(conninfo);
816
817 if (conn && conn->status != CONNECTION_BAD)
819
820 return conn;
821}
PGconn * PQconnectStart(const char *conninfo)
Definition: fe-connect.c:941

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

2780{
2783 int timeout = 0;
2784 int last_whichhost = -2; /* certainly different from whichhost */
2785 int last_whichaddr = -2; /* certainly different from whichaddr */
2786
2787 if (conn == NULL || conn->status == CONNECTION_BAD)
2788 return 0;
2789
2790 /*
2791 * Set up a time limit, if connect_timeout is greater than zero.
2792 */
2793 if (conn->connect_timeout != NULL)
2794 {
2795 if (!pqParseIntParam(conn->connect_timeout, &timeout, conn,
2796 "connect_timeout"))
2797 {
2798 /* mark the connection as bad to report the parsing failure */
2800 return 0;
2801 }
2802 }
2803
2804 for (;;)
2805 {
2806 int ret = 0;
2807
2808 /*
2809 * (Re)start the connect_timeout timer if it's active and we are
2810 * considering a different host than we were last time through. If
2811 * we've already succeeded, though, needn't recalculate.
2812 */
2813 if (flag != PGRES_POLLING_OK &&
2814 timeout > 0 &&
2815 (conn->whichhost != last_whichhost ||
2816 conn->whichaddr != last_whichaddr))
2817 {
2818 end_time = PQgetCurrentTimeUSec() + (pg_usec_time_t) timeout * 1000000;
2819 last_whichhost = conn->whichhost;
2820 last_whichaddr = conn->whichaddr;
2821 }
2822
2823 /*
2824 * Wait, if necessary. Note that the initial state (just after
2825 * PQconnectStart) is to wait for the socket to select for writing.
2826 */
2827 switch (flag)
2828 {
2829 case PGRES_POLLING_OK:
2830 return 1; /* success! */
2831
2833 ret = pqWaitTimed(1, 0, conn, end_time);
2834 if (ret == -1)
2835 {
2836 /* hard failure, eg select() problem, aborts everything */
2838 return 0;
2839 }
2840 break;
2841
2843 ret = pqWaitTimed(0, 1, conn, end_time);
2844 if (ret == -1)
2845 {
2846 /* hard failure, eg select() problem, aborts everything */
2848 return 0;
2849 }
2850 break;
2851
2852 default:
2853 /* Just in case we failed to set it in PQconnectPoll */
2855 return 0;
2856 }
2857
2858 if (ret == 1) /* connect_timeout elapsed */
2859 {
2860 /*
2861 * Give up on current server/address, try the next one.
2862 */
2863 conn->try_next_addr = true;
2865 }
2866
2867 /*
2868 * Now try to advance the state machine.
2869 */
2870 if (conn->cancelRequest)
2872 else
2874 }
2875}
PostgresPollingStatusType PQcancelPoll(PGcancelConn *cancelConn)
Definition: fe-cancel.c:225
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
Definition: fe-connect.c:2905
bool pqParseIntParam(const char *value, int *result, PGconn *conn, const char *context)
Definition: fe-connect.c:8177
pg_usec_time_t PQgetCurrentTimeUSec(void)
Definition: fe-misc.c:1209
int pqWaitTimed(int forRead, int forWrite, PGconn *conn, pg_usec_time_t end_time)
Definition: fe-misc.c:1009
@ CONNECTION_NEEDED
Definition: libpq-fe.h:100
int64_t pg_usec_time_t
Definition: libpq-fe.h:241
PostgresPollingStatusType
Definition: libpq-fe.h:114
@ PGRES_POLLING_OK
Definition: libpq-fe.h:118
@ PGRES_POLLING_READING
Definition: libpq-fe.h:116
static int64 end_time
Definition: pgbench.c:176
int whichaddr
Definition: libpq-int.h:537
bool try_next_addr
Definition: libpq-int.h:534
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 758 of file fe-connect.c.

761{
762 PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname);
763
764 if (conn && conn->status != CONNECTION_BAD)
766
767 return conn;
768}
PGconn * PQconnectStartParams(const char *const *keywords, const char *const *values, int expand_dbname)
Definition: fe-connect.c:860

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

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

◆ pqConnectDBStart()

int pqConnectDBStart ( PGconn conn)

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

2702{
2703 if (!conn)
2704 return 0;
2705
2706 if (!conn->options_valid)
2707 goto connect_errReturn;
2708
2709 /*
2710 * Check for bad linking to backend-internal versions of src/common
2711 * functions (see comments in link-canary.c for the reason we need this).
2712 * Nobody but developers should see this message, so we don't bother
2713 * translating it.
2714 */
2716 {
2718 "libpq is incorrectly linked to backend functions\n");
2719 goto connect_errReturn;
2720 }
2721
2722 /* Ensure our buffers are empty */
2723 conn->inStart = conn->inCursor = conn->inEnd = 0;
2724 conn->outCount = 0;
2725
2726 /*
2727 * Set up to try to connect to the first host. (Setting whichhost = -1 is
2728 * a bit of a cheat, but PQconnectPoll will advance it to 0 before
2729 * anything else looks at it.)
2730 *
2731 * Cancel requests are special though, they should only try one host and
2732 * address, and these fields have already been set up in PQcancelCreate,
2733 * so leave these fields alone for cancel requests.
2734 */
2735 if (!conn->cancelRequest)
2736 {
2737 conn->whichhost = -1;
2738 conn->try_next_host = true;
2739 conn->try_next_addr = false;
2740 }
2741
2743
2744 /* Also reset the target_server_type state if needed */
2747
2748 /*
2749 * The code for processing CONNECTION_NEEDED state is in PQconnectPoll(),
2750 * so that it can easily be re-executed if needed again during the
2751 * asynchronous startup process. However, we must run it once here,
2752 * because callers expect a success return from this routine to mean that
2753 * we are in PGRES_POLLING_WRITING connection state.
2754 */
2756 return 1;
2757
2758connect_errReturn:
2759
2760 /*
2761 * If we managed to open a socket, close it immediately rather than
2762 * waiting till PQfinish. (The application cannot have gotten the socket
2763 * from PQsocket yet, so this doesn't risk breaking anything.)
2764 */
2765 pqDropConnection(conn, true);
2767 return 0;
2768}
@ SERVER_TYPE_PREFER_STANDBY_PASS2
Definition: libpq-int.h:243
@ SERVER_TYPE_PREFER_STANDBY
Definition: libpq-int.h:242
bool try_next_host
Definition: libpq-int.h:535
int inCursor
Definition: libpq-int.h:567
int inEnd
Definition: libpq-int.h:568
int inStart
Definition: libpq-int.h:566
PGTargetServerType target_server_type
Definition: libpq-int.h:531
int outCount
Definition: libpq-int.h:573

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

7673{
7674 char *password;
7675
7676 if (!conn)
7677 return false;
7678 password = PQpass(conn);
7679 if (conn->password_needed &&
7680 (password == NULL || password[0] == '\0'))
7681 return true;
7682 else
7683 return false;
7684}
char * PQpass(const PGconn *conn)
Definition: fe-connect.c:7471

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

7699{
7700 if (!conn)
7701 return false;
7702 if (conn->gssapi_used)
7703 return true;
7704 else
7705 return false;
7706}
bool gssapi_used
Definition: libpq-int.h:506

References conn, and pg_conn::gssapi_used.

Referenced by dblink_security_check(), exec_command_conninfo(), and pgfdw_security_check().

◆ PQconnectionUsedPassword()

int PQconnectionUsedPassword ( const PGconn conn)

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

7688{
7689 if (!conn)
7690 return false;
7691 if (conn->password_needed)
7692 return true;
7693 else
7694 return false;
7695}

References conn, and pg_conn::password_needed.

Referenced by ConnectDatabaseAhx(), dblink_security_check(), exec_command_conninfo(), libpqrcv_connect(), and pgfdw_security_check().

◆ pqConnectOptions2()

bool pqConnectOptions2 ( PGconn conn)

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

1241{
1242 int i;
1243
1244 /*
1245 * Allocate memory for details about each host to which we might possibly
1246 * try to connect. For that, count the number of elements in the hostaddr
1247 * or host options. If neither is given, assume one host.
1248 */
1249 conn->whichhost = 0;
1250 if (conn->pghostaddr && conn->pghostaddr[0] != '\0')
1252 else if (conn->pghost && conn->pghost[0] != '\0')
1254 else
1255 conn->nconnhost = 1;
1257 calloc(conn->nconnhost, sizeof(pg_conn_host));
1258 if (conn->connhost == NULL)
1259 goto oom_error;
1260
1261 /*
1262 * We now have one pg_conn_host structure per possible host. Fill in the
1263 * host and hostaddr fields for each, by splitting the parameter strings.
1264 */
1265 if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0')
1266 {
1267 char *s = conn->pghostaddr;
1268 bool more = true;
1269
1270 for (i = 0; i < conn->nconnhost && more; i++)
1271 {
1273 if (conn->connhost[i].hostaddr == NULL)
1274 goto oom_error;
1275 }
1276
1277 /*
1278 * If hostaddr was given, the array was allocated according to the
1279 * number of elements in the hostaddr list, so it really should be the
1280 * right size.
1281 */
1282 Assert(!more);
1283 Assert(i == conn->nconnhost);
1284 }
1285
1286 if (conn->pghost != NULL && conn->pghost[0] != '\0')
1287 {
1288 char *s = conn->pghost;
1289 bool more = true;
1290
1291 for (i = 0; i < conn->nconnhost && more; i++)
1292 {
1294 if (conn->connhost[i].host == NULL)
1295 goto oom_error;
1296 }
1297
1298 /* Check for wrong number of host items. */
1299 if (more || i != conn->nconnhost)
1300 {
1302 libpq_append_conn_error(conn, "could not match %d host names to %d hostaddr values",
1304 return false;
1305 }
1306 }
1307
1308 /*
1309 * Now, for each host slot, identify the type of address spec, and fill in
1310 * the default address if nothing was given.
1311 */
1312 for (i = 0; i < conn->nconnhost; i++)
1313 {
1314 pg_conn_host *ch = &conn->connhost[i];
1315
1316 if (ch->hostaddr != NULL && ch->hostaddr[0] != '\0')
1317 ch->type = CHT_HOST_ADDRESS;
1318 else if (ch->host != NULL && ch->host[0] != '\0')
1319 {
1320 ch->type = CHT_HOST_NAME;
1321 if (is_unixsock_path(ch->host))
1322 ch->type = CHT_UNIX_SOCKET;
1323 }
1324 else
1325 {
1326 free(ch->host);
1327
1328 /*
1329 * This bit selects the default host location. If you change
1330 * this, see also pg_regress.
1331 */
1332 if (DEFAULT_PGSOCKET_DIR[0])
1333 {
1334 ch->host = strdup(DEFAULT_PGSOCKET_DIR);
1335 ch->type = CHT_UNIX_SOCKET;
1336 }
1337 else
1338 {
1339 ch->host = strdup(DefaultHost);
1340 ch->type = CHT_HOST_NAME;
1341 }
1342 if (ch->host == NULL)
1343 goto oom_error;
1344 }
1345 }
1346
1347 /*
1348 * Next, work out the port number corresponding to each host name.
1349 *
1350 * Note: unlike the above for host names, this could leave the port fields
1351 * as null or empty strings. We will substitute DEF_PGPORT whenever we
1352 * read such a port field.
1353 */
1354 if (conn->pgport != NULL && conn->pgport[0] != '\0')
1355 {
1356 char *s = conn->pgport;
1357 bool more = true;
1358
1359 for (i = 0; i < conn->nconnhost && more; i++)
1360 {
1362 if (conn->connhost[i].port == NULL)
1363 goto oom_error;
1364 }
1365
1366 /*
1367 * If exactly one port was given, use it for every host. Otherwise,
1368 * there must be exactly as many ports as there were hosts.
1369 */
1370 if (i == 1 && !more)
1371 {
1372 for (i = 1; i < conn->nconnhost; i++)
1373 {
1374 conn->connhost[i].port = strdup(conn->connhost[0].port);
1375 if (conn->connhost[i].port == NULL)
1376 goto oom_error;
1377 }
1378 }
1379 else if (more || i != conn->nconnhost)
1380 {
1382 libpq_append_conn_error(conn, "could not match %d port numbers to %d hosts",
1384 return false;
1385 }
1386 }
1387
1388 /*
1389 * If user name was not given, fetch it. (Most likely, the fetch will
1390 * fail, since the only way we get here is if pg_fe_getauthname() failed
1391 * during conninfo_add_defaults(). But now we want an error message.)
1392 */
1393 if (conn->pguser == NULL || conn->pguser[0] == '\0')
1394 {
1395 free(conn->pguser);
1397 if (!conn->pguser)
1398 {
1400 return false;
1401 }
1402 }
1403
1404 /*
1405 * If database name was not given, default it to equal user name
1406 */
1407 if (conn->dbName == NULL || conn->dbName[0] == '\0')
1408 {
1409 free(conn->dbName);
1410 conn->dbName = strdup(conn->pguser);
1411 if (!conn->dbName)
1412 goto oom_error;
1413 }
1414
1415 /*
1416 * If password was not given, try to look it up in password file. Note
1417 * that the result might be different for each host/port pair.
1418 */
1419 if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
1420 {
1421 /* If password file wasn't specified, use ~/PGPASSFILE */
1422 if (conn->pgpassfile == NULL || conn->pgpassfile[0] == '\0')
1423 {
1424 char homedir[MAXPGPATH];
1425
1426 if (pqGetHomeDirectory(homedir, sizeof(homedir)))
1427 {
1430 if (!conn->pgpassfile)
1431 goto oom_error;
1432 snprintf(conn->pgpassfile, MAXPGPATH, "%s/%s",
1433 homedir, PGPASSFILE);
1434 }
1435 }
1436
1437 if (conn->pgpassfile != NULL && conn->pgpassfile[0] != '\0')
1438 {
1439 for (i = 0; i < conn->nconnhost; i++)
1440 {
1441 /*
1442 * Try to get a password for this host from file. We use host
1443 * for the hostname search key if given, else hostaddr (at
1444 * least one of them is guaranteed nonempty by now).
1445 */
1446 const char *pwhost = conn->connhost[i].host;
1447
1448 if (pwhost == NULL || pwhost[0] == '\0')
1449 pwhost = conn->connhost[i].hostaddr;
1450
1452 passwordFromFile(pwhost,
1453 conn->connhost[i].port,
1454 conn->dbName,
1455 conn->pguser,
1456 conn->pgpassfile);
1457 }
1458 }
1459 }
1460
1461 /*
1462 * parse and validate require_auth option
1463 */
1464 if (conn->require_auth && conn->require_auth[0])
1465 {
1466 char *s = conn->require_auth;
1467 bool first,
1468 more;
1469 bool negated = false;
1470
1471 /*
1472 * By default, start from an empty set of allowed methods and
1473 * mechanisms, and add to it.
1474 */
1475 conn->auth_required = true;
1478
1479 for (first = true, more = true; more; first = false)
1480 {
1481 char *method,
1482 *part;
1483 uint32 bits = 0;
1484 const pg_fe_sasl_mech *mech = NULL;
1485
1486 part = parse_comma_separated_list(&s, &more);
1487 if (part == NULL)
1488 goto oom_error;
1489
1490 /*
1491 * Check for negation, e.g. '!password'. If one element is
1492 * negated, they all have to be.
1493 */
1494 method = part;
1495 if (*method == '!')
1496 {
1497 if (first)
1498 {
1499 /*
1500 * Switch to a permissive set of allowed methods and
1501 * mechanisms, and subtract from it.
1502 */
1503 conn->auth_required = false;
1506 }
1507 else if (!negated)
1508 {
1510 libpq_append_conn_error(conn, "negative require_auth method \"%s\" cannot be mixed with non-negative methods",
1511 method);
1512
1513 free(part);
1514 return false;
1515 }
1516
1517 negated = true;
1518 method++;
1519 }
1520 else if (negated)
1521 {
1523 libpq_append_conn_error(conn, "require_auth method \"%s\" cannot be mixed with negative methods",
1524 method);
1525
1526 free(part);
1527 return false;
1528 }
1529
1530 /*
1531 * First group: methods that can be handled solely with the
1532 * authentication request codes.
1533 */
1534 if (strcmp(method, "password") == 0)
1535 {
1536 bits = (1 << AUTH_REQ_PASSWORD);
1537 }
1538 else if (strcmp(method, "md5") == 0)
1539 {
1540 bits = (1 << AUTH_REQ_MD5);
1541 }
1542 else if (strcmp(method, "gss") == 0)
1543 {
1544 bits = (1 << AUTH_REQ_GSS);
1545 bits |= (1 << AUTH_REQ_GSS_CONT);
1546 }
1547 else if (strcmp(method, "sspi") == 0)
1548 {
1549 bits = (1 << AUTH_REQ_SSPI);
1550 bits |= (1 << AUTH_REQ_GSS_CONT);
1551 }
1552
1553 /*
1554 * Next group: SASL mechanisms. All of these use the same request
1555 * codes, so the list of allowed mechanisms is tracked separately.
1556 *
1557 * supported_sasl_mechs must contain all mechanisms handled here.
1558 */
1559 else if (strcmp(method, "scram-sha-256") == 0)
1560 {
1561 mech = &pg_scram_mech;
1562 }
1563 else if (strcmp(method, "oauth") == 0)
1564 {
1565 mech = &pg_oauth_mech;
1566 }
1567
1568 /*
1569 * Final group: meta-options.
1570 */
1571 else if (strcmp(method, "none") == 0)
1572 {
1573 /*
1574 * Special case: let the user explicitly allow (or disallow)
1575 * connections where the server does not send an explicit
1576 * authentication challenge, such as "trust" and "cert" auth.
1577 */
1578 if (negated) /* "!none" */
1579 {
1580 if (conn->auth_required)
1581 goto duplicate;
1582
1583 conn->auth_required = true;
1584 }
1585 else /* "none" */
1586 {
1587 if (!conn->auth_required)
1588 goto duplicate;
1589
1590 conn->auth_required = false;
1591 }
1592
1593 free(part);
1594 continue; /* avoid the bitmask manipulation below */
1595 }
1596 else
1597 {
1599 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1600 "require_auth", method);
1601
1602 free(part);
1603 return false;
1604 }
1605
1606 if (mech)
1607 {
1608 /*
1609 * Update the mechanism set only. The method bitmask will be
1610 * updated for SASL further down.
1611 */
1612 Assert(!bits);
1613
1614 if (negated)
1615 {
1616 /* Remove the existing mechanism from the list. */
1618 if (i < 0)
1619 goto duplicate;
1620
1621 conn->allowed_sasl_mechs[i] = NULL;
1622 }
1623 else
1624 {
1625 /*
1626 * Find a space to put the new mechanism (after making
1627 * sure it's not already there).
1628 */
1630 if (i >= 0)
1631 goto duplicate;
1632
1634 if (i < 0)
1635 {
1636 /* Should not happen; the pointer list is corrupted. */
1637 Assert(false);
1638
1641 "internal error: no space in allowed_sasl_mechs");
1642 free(part);
1643 return false;
1644 }
1645
1646 conn->allowed_sasl_mechs[i] = mech;
1647 }
1648 }
1649 else
1650 {
1651 /* Update the method bitmask. */
1652 Assert(bits);
1653
1654 if (negated)
1655 {
1656 if ((conn->allowed_auth_methods & bits) == 0)
1657 goto duplicate;
1658
1659 conn->allowed_auth_methods &= ~bits;
1660 }
1661 else
1662 {
1663 if ((conn->allowed_auth_methods & bits) == bits)
1664 goto duplicate;
1665
1666 conn->allowed_auth_methods |= bits;
1667 }
1668 }
1669
1670 free(part);
1671 continue;
1672
1673 duplicate:
1674
1675 /*
1676 * A duplicated method probably indicates a typo in a setting
1677 * where typos are extremely risky.
1678 */
1680 libpq_append_conn_error(conn, "require_auth method \"%s\" is specified more than once",
1681 part);
1682
1683 free(part);
1684 return false;
1685 }
1686
1687 /*
1688 * Finally, allow SASL authentication requests if (and only if) we've
1689 * allowed any mechanisms.
1690 */
1691 {
1692 bool allowed = false;
1693 const uint32 sasl_bits =
1694 (1 << AUTH_REQ_SASL)
1695 | (1 << AUTH_REQ_SASL_CONT)
1696 | (1 << AUTH_REQ_SASL_FIN);
1697
1698 for (i = 0; i < lengthof(conn->allowed_sasl_mechs); i++)
1699 {
1701 {
1702 allowed = true;
1703 break;
1704 }
1705 }
1706
1707 /*
1708 * For the standard case, add the SASL bits to the (default-empty)
1709 * set if needed. For the negated case, remove them.
1710 */
1711 if (!negated && allowed)
1712 conn->allowed_auth_methods |= sasl_bits;
1713 else if (negated && !allowed)
1714 conn->allowed_auth_methods &= ~sasl_bits;
1715 }
1716 }
1717
1718 /*
1719 * validate channel_binding option
1720 */
1721 if (conn->channel_binding)
1722 {
1723 if (strcmp(conn->channel_binding, "disable") != 0
1724 && strcmp(conn->channel_binding, "prefer") != 0
1725 && strcmp(conn->channel_binding, "require") != 0)
1726 {
1728 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1729 "channel_binding", conn->channel_binding);
1730 return false;
1731 }
1732 }
1733 else
1734 {
1736 if (!conn->channel_binding)
1737 goto oom_error;
1738 }
1739
1740#ifndef USE_SSL
1741
1742 /*
1743 * sslrootcert=system is not supported. Since setting this changes the
1744 * default sslmode, check this _before_ we validate sslmode, to avoid
1745 * confusing the user with errors for an option they may not have set.
1746 */
1747 if (conn->sslrootcert
1748 && strcmp(conn->sslrootcert, "system") == 0)
1749 {
1751 libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1752 "sslrootcert", conn->sslrootcert);
1753 return false;
1754 }
1755#endif
1756
1757 /*
1758 * validate sslmode option
1759 */
1760 if (conn->sslmode)
1761 {
1762 if (strcmp(conn->sslmode, "disable") != 0
1763 && strcmp(conn->sslmode, "allow") != 0
1764 && strcmp(conn->sslmode, "prefer") != 0
1765 && strcmp(conn->sslmode, "require") != 0
1766 && strcmp(conn->sslmode, "verify-ca") != 0
1767 && strcmp(conn->sslmode, "verify-full") != 0)
1768 {
1770 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1771 "sslmode", conn->sslmode);
1772 return false;
1773 }
1774
1775#ifndef USE_SSL
1776 switch (conn->sslmode[0])
1777 {
1778 case 'a': /* "allow" */
1779 case 'p': /* "prefer" */
1780
1781 /*
1782 * warn user that an SSL connection will never be negotiated
1783 * since SSL was not compiled in?
1784 */
1785 break;
1786
1787 case 'r': /* "require" */
1788 case 'v': /* "verify-ca" or "verify-full" */
1790 libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1791 "sslmode", conn->sslmode);
1792 return false;
1793 }
1794#endif
1795 }
1796 else
1797 {
1798 conn->sslmode = strdup(DefaultSSLMode);
1799 if (!conn->sslmode)
1800 goto oom_error;
1801 }
1802
1803 /*
1804 * validate sslnegotiation option, default is "postgres" for the postgres
1805 * style negotiated connection with an extra round trip but more options.
1806 */
1807 if (conn->sslnegotiation)
1808 {
1809 if (strcmp(conn->sslnegotiation, "postgres") != 0
1810 && strcmp(conn->sslnegotiation, "direct") != 0)
1811 {
1813 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1814 "sslnegotiation", conn->sslnegotiation);
1815 return false;
1816 }
1817
1818#ifndef USE_SSL
1819 if (conn->sslnegotiation[0] != 'p')
1820 {
1822 libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1823 "sslnegotiation", conn->sslnegotiation);
1824 return false;
1825 }
1826#endif
1827
1828 /*
1829 * Don't allow direct SSL negotiation with sslmode='prefer', because
1830 * that poses a risk of unintentional fallback to plaintext connection
1831 * when connecting to a pre-v17 server that does not support direct
1832 * SSL connections. To keep things simple, don't allow it with
1833 * sslmode='allow' or sslmode='disable' either. If a user goes through
1834 * the trouble of setting sslnegotiation='direct', they probably
1835 * intend to use SSL, and sslmode=disable or allow is probably a user
1836 * user mistake anyway.
1837 */
1838 if (conn->sslnegotiation[0] == 'd' &&
1839 conn->sslmode[0] != 'r' && conn->sslmode[0] != 'v')
1840 {
1842 libpq_append_conn_error(conn, "weak sslmode \"%s\" may not be used with sslnegotiation=direct (use \"require\", \"verify-ca\", or \"verify-full\")",
1843 conn->sslmode);
1844 return false;
1845 }
1846 }
1847 else
1848 {
1850 if (!conn->sslnegotiation)
1851 goto oom_error;
1852 }
1853
1854#ifdef USE_SSL
1855
1856 /*
1857 * If sslrootcert=system, make sure our chosen sslmode is compatible.
1858 */
1859 if (conn->sslrootcert
1860 && strcmp(conn->sslrootcert, "system") == 0
1861 && strcmp(conn->sslmode, "verify-full") != 0)
1862 {
1864 libpq_append_conn_error(conn, "weak sslmode \"%s\" may not be used with sslrootcert=system (use \"verify-full\")",
1865 conn->sslmode);
1866 return false;
1867 }
1868#endif
1869
1870 /*
1871 * Validate TLS protocol versions for ssl_min_protocol_version and
1872 * ssl_max_protocol_version.
1873 */
1875 {
1877 libpq_append_conn_error(conn, "invalid \"%s\" value: \"%s\"",
1878 "ssl_min_protocol_version",
1880 return false;
1881 }
1883 {
1885 libpq_append_conn_error(conn, "invalid \"%s\" value: \"%s\"",
1886 "ssl_max_protocol_version",
1888 return false;
1889 }
1890
1891 /*
1892 * Check if the range of SSL protocols defined is correct. This is done
1893 * at this early step because this is independent of the SSL
1894 * implementation used, and this avoids unnecessary cycles with an
1895 * already-built SSL context when the connection is being established, as
1896 * it would be doomed anyway.
1897 */
1900 {
1902 libpq_append_conn_error(conn, "invalid SSL protocol version range");
1903 return false;
1904 }
1905
1906 /*
1907 * validate sslcertmode option
1908 */
1909 if (conn->sslcertmode)
1910 {
1911 if (strcmp(conn->sslcertmode, "disable") != 0 &&
1912 strcmp(conn->sslcertmode, "allow") != 0 &&
1913 strcmp(conn->sslcertmode, "require") != 0)
1914 {
1916 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1917 "sslcertmode", conn->sslcertmode);
1918 return false;
1919 }
1920#ifndef USE_SSL
1921 if (strcmp(conn->sslcertmode, "require") == 0)
1922 {
1924 libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1925 "sslcertmode", conn->sslcertmode);
1926 return false;
1927 }
1928#endif
1929#ifndef HAVE_SSL_CTX_SET_CERT_CB
1930
1931 /*
1932 * Without a certificate callback, the current implementation can't
1933 * figure out if a certificate was actually requested, so "require" is
1934 * useless.
1935 */
1936 if (strcmp(conn->sslcertmode, "require") == 0)
1937 {
1939 libpq_append_conn_error(conn, "%s value \"%s\" is not supported (check OpenSSL version)",
1940 "sslcertmode", conn->sslcertmode);
1941 return false;
1942 }
1943#endif
1944 }
1945 else
1946 {
1948 if (!conn->sslcertmode)
1949 goto oom_error;
1950 }
1951
1952 /*
1953 * validate gssencmode option
1954 */
1955 if (conn->gssencmode)
1956 {
1957 if (strcmp(conn->gssencmode, "disable") != 0 &&
1958 strcmp(conn->gssencmode, "prefer") != 0 &&
1959 strcmp(conn->gssencmode, "require") != 0)
1960 {
1962 libpq_append_conn_error(conn, "invalid %s value: \"%s\"", "gssencmode", conn->gssencmode);
1963 return false;
1964 }
1965#ifndef ENABLE_GSS
1966 if (strcmp(conn->gssencmode, "require") == 0)
1967 {
1969 libpq_append_conn_error(conn, "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in",
1970 conn->gssencmode);
1971 return false;
1972 }
1973#endif
1974 }
1975 else
1976 {
1977 conn->gssencmode = strdup(DefaultGSSMode);
1978 if (!conn->gssencmode)
1979 goto oom_error;
1980 }
1981
1982 /*
1983 * validate target_session_attrs option, and set target_server_type
1984 */
1986 {
1987 if (strcmp(conn->target_session_attrs, "any") == 0)
1989 else if (strcmp(conn->target_session_attrs, "read-write") == 0)
1991 else if (strcmp(conn->target_session_attrs, "read-only") == 0)
1993 else if (strcmp(conn->target_session_attrs, "primary") == 0)
1995 else if (strcmp(conn->target_session_attrs, "standby") == 0)
1997 else if (strcmp(conn->target_session_attrs, "prefer-standby") == 0)
1999 else
2000 {
2002 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
2003 "target_session_attrs",
2005 return false;
2006 }
2007 }
2008 else
2010
2012 {
2013 int len;
2014
2018 goto oom_error;
2021 if (len < 0)
2022 {
2023 libpq_append_conn_error(conn, "invalid SCRAM client key");
2025 return false;
2026 }
2027 if (len != SCRAM_MAX_KEY_LEN)
2028 {
2029 libpq_append_conn_error(conn, "invalid SCRAM client key length: %d", len);
2031 return false;
2032 }
2034 }
2035
2037 {
2038 int len;
2039
2043 goto oom_error;
2046 if (len < 0)
2047 {
2048 libpq_append_conn_error(conn, "invalid SCRAM server key");
2050 return false;
2051 }
2052 if (len != SCRAM_MAX_KEY_LEN)
2053 {
2054 libpq_append_conn_error(conn, "invalid SCRAM server key length: %d", len);
2056 return false;
2057 }
2059 }
2060
2061 /*
2062 * validate load_balance_hosts option, and set load_balance_type
2063 */
2065 {
2066 if (strcmp(conn->load_balance_hosts, "disable") == 0)
2068 else if (strcmp(conn->load_balance_hosts, "random") == 0)
2070 else
2071 {
2073 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
2074 "load_balance_hosts",
2076 return false;
2077 }
2078 }
2079 else
2081
2083 {
2085
2086 /*
2087 * This is the "inside-out" variant of the Fisher-Yates shuffle
2088 * algorithm. Notionally, we append each new value to the array and
2089 * then swap it with a randomly-chosen array element (possibly
2090 * including itself, else we fail to generate permutations with the
2091 * last integer last). The swap step can be optimized by combining it
2092 * with the insertion.
2093 */
2094 for (i = 1; i < conn->nconnhost; i++)
2095 {
2096 int j = pg_prng_uint64_range(&conn->prng_state, 0, i);
2097 pg_conn_host temp = conn->connhost[j];
2098
2099 conn->connhost[j] = conn->connhost[i];
2100 conn->connhost[i] = temp;
2101 }
2102 }
2103
2105 {
2106 if (!pqParseProtocolVersion(conn->min_protocol_version, &conn->min_pversion, conn, "min_protocol_version"))
2107 {
2109 return false;
2110 }
2111 }
2112 else
2113 {
2115 }
2116
2118 {
2119 if (!pqParseProtocolVersion(conn->max_protocol_version, &conn->max_pversion, conn, "max_protocol_version"))
2120 {
2122 return false;
2123 }
2124 }
2125 else
2126 {
2127 /*
2128 * To not break connecting to older servers/poolers that do not yet
2129 * support NegotiateProtocolVersion, default to the 3.0 protocol at
2130 * least for a while longer. Except when min_protocol_version is set
2131 * to something larger, then we might as well default to the latest.
2132 */
2133 if (conn->min_pversion > PG_PROTOCOL(3, 0))
2135 else
2136 conn->max_pversion = PG_PROTOCOL(3, 0);
2137 }
2138
2140 {
2142 libpq_append_conn_error(conn, "min_protocol_version is greater than max_protocol_version");
2143 return false;
2144 }
2145
2146 /*
2147 * Resolve special "auto" client_encoding from the locale
2148 */
2150 strcmp(conn->client_encoding_initial, "auto") == 0)
2151 {
2155 goto oom_error;
2156 }
2157
2158 /*
2159 * Only if we get this far is it appropriate to try to connect. (We need a
2160 * state flag, rather than just the boolean result of this function, in
2161 * case someone tries to PQreset() the PGconn.)
2162 */
2163 conn->options_valid = true;
2164
2165 return true;
2166
2167oom_error:
2169 libpq_append_conn_error(conn, "out of memory");
2170 return false;
2171}
int pg_b64_decode(const char *src, int len, char *dst, int dstlen)
Definition: base64.c:116
int pg_b64_dec_len(int srclen)
Definition: base64.c:239
uint32_t uint32
Definition: c.h:502
const pg_fe_sasl_mech pg_oauth_mech
Definition: fe-auth-oauth.c:35
const pg_fe_sasl_mech pg_scram_mech
Definition: fe-auth-scram.c:33
static bool pqParseProtocolVersion(const char *value, ProtocolVersion *result, PGconn *conn, const char *context)
Definition: fe-connect.c:8222
static char * passwordFromFile(const char *hostname, const char *port, const char *dbname, const char *username, const char *pgpassfile)
Definition: fe-connect.c:7887
static bool sslVerifyProtocolRange(const char *min, const char *max)
Definition: fe-connect.c:8083
static void libpq_prng_init(PGconn *conn)
Definition: fe-connect.c:1162
#define DefaultSSLMode
Definition: fe-connect.c:132
#define DefaultGSSMode
Definition: fe-connect.c:140
static int count_comma_separated_elems(const char *input)
Definition: fe-connect.c:1103
static void clear_allowed_sasl_mechs(PGconn *conn)
Definition: fe-connect.c:1209
static void fill_allowed_sasl_mechs(PGconn *conn)
Definition: fe-connect.c:1185
#define DefaultChannelBinding
Definition: fe-connect.c:124
static int index_of_allowed_sasl_mech(PGconn *conn, const pg_fe_sasl_mech *mech)
Definition: fe-connect.c:1220
static bool sslVerifyProtocolVersion(const char *version)
Definition: fe-connect.c:8057
#define DefaultSSLNegotiation
Definition: fe-connect.c:135
#define PGPASSFILE
Definition: fe-connect.c:78
#define DefaultSSLCertMode
Definition: fe-connect.c:133
static char * parse_comma_separated_list(char **startptr, bool *more)
Definition: fe-connect.c:1127
#define calloc(a, b)
Definition: header.h:55
int j
Definition: isn.c:78
@ LOAD_BALANCE_DISABLE
Definition: libpq-int.h:249
@ LOAD_BALANCE_RANDOM
Definition: libpq-int.h:250
@ CHT_UNIX_SOCKET
Definition: libpq-int.h:311
@ CHT_HOST_NAME
Definition: libpq-int.h:309
@ SERVER_TYPE_STANDBY
Definition: libpq-int.h:241
@ SERVER_TYPE_PRIMARY
Definition: libpq-int.h:240
@ SERVER_TYPE_ANY
Definition: libpq-int.h:237
@ SERVER_TYPE_READ_WRITE
Definition: libpq-int.h:238
@ SERVER_TYPE_READ_ONLY
Definition: libpq-int.h:239
uint64 pg_prng_uint64_range(pg_prng_state *state, uint64 rmin, uint64 rmax)
Definition: pg_prng.c:144
#define pg_encoding_to_char
Definition: pg_wchar.h:630
int pg_get_encoding_from_locale(const char *ctype, bool write_message)
Definition: chklocale.c:301
#define PG_PROTOCOL_EARLIEST
Definition: pqcomm.h:96
#define PG_PROTOCOL_LATEST
Definition: pqcomm.h:97
#define PG_PROTOCOL(m, n)
Definition: pqcomm.h:90
#define AUTH_REQ_SSPI
Definition: protocol.h:83
#define AUTH_REQ_SASL_CONT
Definition: protocol.h:85
#define AUTH_REQ_GSS
Definition: protocol.h:81
#define AUTH_REQ_MD5
Definition: protocol.h:79
#define AUTH_REQ_PASSWORD
Definition: protocol.h:77
#define AUTH_REQ_GSS_CONT
Definition: protocol.h:82
#define AUTH_REQ_SASL
Definition: protocol.h:84
#define AUTH_REQ_SASL_FIN
Definition: protocol.h:86
#define SCRAM_MAX_KEY_LEN
Definition: scram-common.h:30
int nconnhost
Definition: libpq-int.h:477
void * scram_server_key_binary
Definition: libpq-int.h:544
size_t scram_client_key_len
Definition: libpq-int.h:541
ProtocolVersion min_pversion
Definition: libpq-int.h:545
uint32 allowed_auth_methods
Definition: libpq-int.h:514
bool auth_required
Definition: libpq-int.h:512
char * max_protocol_version
Definition: libpq-int.h:421
char * min_protocol_version
Definition: libpq-int.h:420
void * scram_client_key_binary
Definition: libpq-int.h:542
ProtocolVersion max_pversion
Definition: libpq-int.h:546
PGLoadBalanceType load_balance_type
Definition: libpq-int.h:532
size_t scram_server_key_len
Definition: libpq-int.h:543

References pg_conn::allowed_auth_methods, pg_conn::allowed_sasl_mechs, 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, clear_allowed_sasl_mechs(), 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, fill_allowed_sasl_mechs(), free, pg_conn::gssencmode, pg_conn_host::host, pg_conn_host::hostaddr, i, index_of_allowed_sasl_mech(), is_unixsock_path(), j, len, lengthof, libpq_append_conn_error(), libpq_prng_init(), LOAD_BALANCE_DISABLE, pg_conn::load_balance_hosts, LOAD_BALANCE_RANDOM, pg_conn::load_balance_type, malloc, pg_conn::max_protocol_version, pg_conn::max_pversion, MAXPGPATH, pg_conn::min_protocol_version, pg_conn::min_pversion, pg_conn::nconnhost, pg_conn::options_valid, parse_comma_separated_list(), pg_conn_host::password, passwordFromFile(), pg_b64_dec_len(), pg_b64_decode(), pg_encoding_to_char, pg_fe_getauthname(), pg_get_encoding_from_locale(), pg_oauth_mech, pg_prng_uint64_range(), PG_PROTOCOL, PG_PROTOCOL_EARLIEST, PG_PROTOCOL_LATEST, pg_scram_mech, pg_conn::pghost, pg_conn::pghostaddr, pg_conn::pgpass, PGPASSFILE, pg_conn::pgpassfile, pg_conn::pgport, pg_conn::pguser, pg_conn_host::port, pqGetHomeDirectory(), pqParseProtocolVersion(), pg_conn::prng_state, pg_conn::require_auth, pg_conn::scram_client_key, pg_conn::scram_client_key_binary, pg_conn::scram_client_key_len, SCRAM_MAX_KEY_LEN, pg_conn::scram_server_key, pg_conn::scram_server_key_binary, pg_conn::scram_server_key_len, 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 2905 of file fe-connect.c.

2906{
2907 bool reset_connection_state_machine = false;
2908 bool need_new_connection = false;
2909 PGresult *res;
2910 char sebuf[PG_STRERROR_R_BUFLEN];
2911 int optval;
2912
2913 if (conn == NULL)
2914 return PGRES_POLLING_FAILED;
2915
2916 /* Get the new data */
2917 switch (conn->status)
2918 {
2919 /*
2920 * We really shouldn't have been polled in these two cases, but we
2921 * can handle it.
2922 */
2923 case CONNECTION_BAD:
2924 return PGRES_POLLING_FAILED;
2925 case CONNECTION_OK:
2926 return PGRES_POLLING_OK;
2927
2928 /* These are reading states */
2930 case CONNECTION_AUTH_OK:
2932 case CONNECTION_CONSUME:
2934 {
2935 /* Load waiting data */
2936 int n = pqReadData(conn);
2937
2938 if (n < 0)
2939 goto error_return;
2940 if (n == 0)
2941 return PGRES_POLLING_READING;
2942
2943 break;
2944 }
2945
2946 /* These are writing states, so we just proceed. */
2947 case CONNECTION_STARTED:
2948 case CONNECTION_MADE:
2949 break;
2950
2951 /* Special cases: proceed without waiting. */
2953 case CONNECTION_NEEDED:
2957 break;
2958
2959 default:
2960 libpq_append_conn_error(conn, "invalid connection state, probably indicative of memory corruption");
2961 goto error_return;
2962 }
2963
2964
2965keep_going: /* We will come back to here until there is
2966 * nothing left to do. */
2967
2968 /* Time to advance to next address, or next host if no more addresses? */
2969 if (conn->try_next_addr)
2970 {
2971 if (conn->whichaddr < conn->naddr)
2972 {
2973 conn->whichaddr++;
2974 reset_connection_state_machine = true;
2975 }
2976 else
2977 conn->try_next_host = true;
2978 conn->try_next_addr = false;
2979 }
2980
2981 /* Time to advance to next connhost[] entry? */
2982 if (conn->try_next_host)
2983 {
2984 pg_conn_host *ch;
2985 struct addrinfo hint;
2986 struct addrinfo *addrlist;
2987 int thisport;
2988 int ret;
2989 char portstr[MAXPGPATH];
2990
2991 if (conn->whichhost + 1 < conn->nconnhost)
2992 conn->whichhost++;
2993 else
2994 {
2995 /*
2996 * Oops, no more hosts.
2997 *
2998 * If we are trying to connect in "prefer-standby" mode, then drop
2999 * the standby requirement and start over. Don't do this for
3000 * cancel requests though, since we are certain the list of
3001 * servers won't change as the target_server_type option is not
3002 * applicable to those connections.
3003 *
3004 * Otherwise, an appropriate error message is already set up, so
3005 * we just need to set the right status.
3006 */
3008 conn->nconnhost > 0 &&
3010 {
3012 conn->whichhost = 0;
3013 }
3014 else
3015 goto error_return;
3016 }
3017
3018 /* Drop any address info for previous host */
3020
3021 /*
3022 * Look up info for the new host. On failure, log the problem in
3023 * conn->errorMessage, then loop around to try the next host. (Note
3024 * we don't clear try_next_host until we've succeeded.)
3025 */
3026 ch = &conn->connhost[conn->whichhost];
3027
3028 /* Initialize hint structure */
3029 MemSet(&hint, 0, sizeof(hint));
3030 hint.ai_socktype = SOCK_STREAM;
3031 hint.ai_family = AF_UNSPEC;
3032
3033 /* Figure out the port number we're going to use. */
3034 if (ch->port == NULL || ch->port[0] == '\0')
3035 thisport = DEF_PGPORT;
3036 else
3037 {
3038 if (!pqParseIntParam(ch->port, &thisport, conn, "port"))
3039 goto error_return;
3040
3041 if (thisport < 1 || thisport > 65535)
3042 {
3043 libpq_append_conn_error(conn, "invalid port number: \"%s\"", ch->port);
3044 goto keep_going;
3045 }
3046 }
3047 snprintf(portstr, sizeof(portstr), "%d", thisport);
3048
3049 /* Use pg_getaddrinfo_all() to resolve the address */
3050 switch (ch->type)
3051 {
3052 case CHT_HOST_NAME:
3053 ret = pg_getaddrinfo_all(ch->host, portstr, &hint,
3054 &addrlist);
3055 if (ret || !addrlist)
3056 {
3057 libpq_append_conn_error(conn, "could not translate host name \"%s\" to address: %s",
3058 ch->host, gai_strerror(ret));
3059 goto keep_going;
3060 }
3061 break;
3062
3063 case CHT_HOST_ADDRESS:
3064 hint.ai_flags = AI_NUMERICHOST;
3065 ret = pg_getaddrinfo_all(ch->hostaddr, portstr, &hint,
3066 &addrlist);
3067 if (ret || !addrlist)
3068 {
3069 libpq_append_conn_error(conn, "could not parse network address \"%s\": %s",
3070 ch->hostaddr, gai_strerror(ret));
3071 goto keep_going;
3072 }
3073 break;
3074
3075 case CHT_UNIX_SOCKET:
3076 hint.ai_family = AF_UNIX;
3077 UNIXSOCK_PATH(portstr, thisport, ch->host);
3078 if (strlen(portstr) >= UNIXSOCK_PATH_BUFLEN)
3079 {
3080 libpq_append_conn_error(conn, "Unix-domain socket path \"%s\" is too long (maximum %d bytes)",
3081 portstr,
3082 (int) (UNIXSOCK_PATH_BUFLEN - 1));
3083 goto keep_going;
3084 }
3085
3086 /*
3087 * NULL hostname tells pg_getaddrinfo_all to parse the service
3088 * name as a Unix-domain socket path.
3089 */
3090 ret = pg_getaddrinfo_all(NULL, portstr, &hint,
3091 &addrlist);
3092 if (ret || !addrlist)
3093 {
3094 libpq_append_conn_error(conn, "could not translate Unix-domain socket path \"%s\" to address: %s",
3095 portstr, gai_strerror(ret));
3096 goto keep_going;
3097 }
3098 break;
3099 }
3100
3101 /*
3102 * Store a copy of the addrlist in private memory so we can perform
3103 * randomization for load balancing.
3104 */
3105 ret = store_conn_addrinfo(conn, addrlist);
3106 pg_freeaddrinfo_all(hint.ai_family, addrlist);
3107 if (ret)
3108 goto error_return; /* message already logged */
3109
3110 /*
3111 * If random load balancing is enabled we shuffle the addresses.
3112 */
3114 {
3115 /*
3116 * This is the "inside-out" variant of the Fisher-Yates shuffle
3117 * algorithm. Notionally, we append each new value to the array
3118 * and then swap it with a randomly-chosen array element (possibly
3119 * including itself, else we fail to generate permutations with
3120 * the last integer last). The swap step can be optimized by
3121 * combining it with the insertion.
3122 *
3123 * We don't need to initialize conn->prng_state here, because that
3124 * already happened in pqConnectOptions2.
3125 */
3126 for (int i = 1; i < conn->naddr; i++)
3127 {
3128 int j = pg_prng_uint64_range(&conn->prng_state, 0, i);
3129 AddrInfo temp = conn->addr[j];
3130
3131 conn->addr[j] = conn->addr[i];
3132 conn->addr[i] = temp;
3133 }
3134 }
3135
3136 reset_connection_state_machine = true;
3137 conn->try_next_host = false;
3138 }
3139
3140 /* Reset connection state machine? */
3141 if (reset_connection_state_machine)
3142 {
3143 /*
3144 * (Re) initialize our connection control variables for a set of
3145 * connection attempts to a single server address. These variables
3146 * must persist across individual connection attempts, but we must
3147 * reset them when we start to consider a new server.
3148 */
3150 conn->send_appname = true;
3154 reset_connection_state_machine = false;
3155 need_new_connection = true;
3156 }
3157
3158 /* Force a new connection (perhaps to the same server as before)? */
3159 if (need_new_connection)
3160 {
3161 /* Drop any existing connection */
3162 pqDropConnection(conn, true);
3163
3164 /* Reset all state obtained from old server */
3166
3167 /* Drop any PGresult we might have, too */
3172
3173 /* Reset conn->status to put the state machine in the right state */
3175
3176 need_new_connection = false;
3177 }
3178
3179 /*
3180 * Decide what to do next, if server rejects SSL or GSS negotiation, but
3181 * the connection is still valid. If there are no options left, error out
3182 * with 'msg'.
3183 */
3184#define ENCRYPTION_NEGOTIATION_FAILED(msg) \
3185 do { \
3186 switch (encryption_negotiation_failed(conn)) \
3187 { \
3188 case 0: \
3189 libpq_append_conn_error(conn, (msg)); \
3190 goto error_return; \
3191 case 1: \
3192 conn->status = CONNECTION_MADE; \
3193 return PGRES_POLLING_WRITING; \
3194 case 2: \
3195 need_new_connection = true; \
3196 goto keep_going; \
3197 } \
3198 } while(0);
3199
3200 /*
3201 * Decide what to do next, if connection fails. If there are no options
3202 * left, return with an error. The error message has already been written
3203 * to the connection's error buffer.
3204 */
3205#define CONNECTION_FAILED() \
3206 do { \
3207 if (connection_failed(conn)) \
3208 { \
3209 need_new_connection = true; \
3210 goto keep_going; \
3211 } \
3212 else \
3213 goto error_return; \
3214 } while(0);
3215
3216 /* Now try to advance the state machine for this connection */
3217 switch (conn->status)
3218 {
3219 case CONNECTION_NEEDED:
3220 {
3221 /*
3222 * Try to initiate a connection to one of the addresses
3223 * returned by pg_getaddrinfo_all(). conn->whichaddr is the
3224 * next one to try.
3225 *
3226 * The extra level of braces here is historical. It's not
3227 * worth reindenting this whole switch case to remove 'em.
3228 */
3229 {
3230 char host_addr[NI_MAXHOST];
3231 int sock_type;
3232 AddrInfo *addr_cur;
3233
3234 /*
3235 * Advance to next possible host, if we've tried all of
3236 * the addresses for the current host.
3237 */
3238 if (conn->whichaddr == conn->naddr)
3239 {
3240 conn->try_next_host = true;
3241 goto keep_going;
3242 }
3243 addr_cur = &conn->addr[conn->whichaddr];
3244
3245 /* Remember current address for possible use later */
3246 memcpy(&conn->raddr, &addr_cur->addr, sizeof(SockAddr));
3247
3248#ifdef ENABLE_GSS
3249
3250 /*
3251 * Before establishing the connection, check if it's
3252 * doomed to fail because gssencmode='require' but GSSAPI
3253 * is not available.
3254 */
3255 if (conn->gssencmode[0] == 'r')
3256 {
3257 if (conn->raddr.addr.ss_family == AF_UNIX)
3258 {
3260 "GSSAPI encryption required but it is not supported over a local socket");
3261 goto error_return;
3262 }
3263 if (conn->gcred == GSS_C_NO_CREDENTIAL)
3264 {
3265 if (!pg_GSS_have_cred_cache(&conn->gcred))
3266 {
3268 "GSSAPI encryption required but no credential cache");
3269 goto error_return;
3270 }
3271 }
3272 }
3273#endif
3274
3275 /*
3276 * Choose the encryption method to try first. Do this
3277 * before establishing the connection, so that if none of
3278 * the modes allowed by the connections options are
3279 * available, we can error out before establishing the
3280 * connection.
3281 */
3283 goto error_return;
3284
3285 /*
3286 * Set connip, too. Note we purposely ignore strdup
3287 * failure; not a big problem if it fails.
3288 */
3289 if (conn->connip != NULL)
3290 {
3291 free(conn->connip);
3292 conn->connip = NULL;
3293 }
3294 getHostaddr(conn, host_addr, NI_MAXHOST);
3295 if (host_addr[0])
3296 conn->connip = strdup(host_addr);
3297
3298 /* Try to create the socket */
3299 sock_type = SOCK_STREAM;
3300#ifdef SOCK_CLOEXEC
3301
3302 /*
3303 * Atomically mark close-on-exec, if possible on this
3304 * platform, so that there isn't a window where a
3305 * subprogram executed by another thread inherits the
3306 * socket. See fallback code below.
3307 */
3308 sock_type |= SOCK_CLOEXEC;
3309#endif
3310#ifdef SOCK_NONBLOCK
3311
3312 /*
3313 * We might as well skip a system call for nonblocking
3314 * mode too, if we can.
3315 */
3316 sock_type |= SOCK_NONBLOCK;
3317#endif
3318 conn->sock = socket(addr_cur->family, sock_type, 0);
3319 if (conn->sock == PGINVALID_SOCKET)
3320 {
3321 int errorno = SOCK_ERRNO;
3322
3323 /*
3324 * Silently ignore socket() failure if we have more
3325 * addresses to try; this reduces useless chatter in
3326 * cases where the address list includes both IPv4 and
3327 * IPv6 but kernel only accepts one family.
3328 */
3329 if (conn->whichaddr < conn->naddr ||
3330 conn->whichhost + 1 < conn->nconnhost)
3331 {
3332 conn->try_next_addr = true;
3333 goto keep_going;
3334 }
3335 emitHostIdentityInfo(conn, host_addr);
3336 libpq_append_conn_error(conn, "could not create socket: %s",
3337 SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
3338 goto error_return;
3339 }
3340
3341 /*
3342 * Once we've identified a target address, all errors
3343 * except the preceding socket()-failure case should be
3344 * prefixed with host-identity information. (If the
3345 * connection succeeds, the contents of conn->errorMessage
3346 * won't matter, so this is harmless.)
3347 */
3348 emitHostIdentityInfo(conn, host_addr);
3349
3350 /*
3351 * Select socket options: no delay of outgoing data for
3352 * TCP sockets, nonblock mode, close-on-exec. Try the
3353 * next address if any of this fails.
3354 */
3355 if (addr_cur->family != AF_UNIX)
3356 {
3357 if (!connectNoDelay(conn))
3358 {
3359 /* error message already created */
3360 conn->try_next_addr = true;
3361 goto keep_going;
3362 }
3363 }
3364#ifndef SOCK_NONBLOCK
3365 if (!pg_set_noblock(conn->sock))
3366 {
3367 libpq_append_conn_error(conn, "could not set socket to nonblocking mode: %s",
3368 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3369 conn->try_next_addr = true;
3370 goto keep_going;
3371 }
3372#endif
3373
3374#ifndef SOCK_CLOEXEC
3375#ifdef F_SETFD
3376 if (fcntl(conn->sock, F_SETFD, FD_CLOEXEC) == -1)
3377 {
3378 libpq_append_conn_error(conn, "could not set socket to close-on-exec mode: %s",
3379 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3380 conn->try_next_addr = true;
3381 goto keep_going;
3382 }
3383#endif /* F_SETFD */
3384#endif
3385
3386 if (addr_cur->family != AF_UNIX)
3387 {
3388#ifndef WIN32
3389 int on = 1;
3390#endif
3391 int usekeepalives = useKeepalives(conn);
3392 int err = 0;
3393
3394 if (usekeepalives < 0)
3395 {
3396 /* error is already reported */
3397 err = 1;
3398 }
3399 else if (usekeepalives == 0)
3400 {
3401 /* Do nothing */
3402 }
3403#ifndef WIN32
3404 else if (setsockopt(conn->sock,
3405 SOL_SOCKET, SO_KEEPALIVE,
3406 (char *) &on, sizeof(on)) < 0)
3407 {
3408 libpq_append_conn_error(conn, "%s(%s) failed: %s",
3409 "setsockopt",
3410 "SO_KEEPALIVE",
3411 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3412 err = 1;
3413 }
3414 else if (!setKeepalivesIdle(conn)
3417 err = 1;
3418#else /* WIN32 */
3419#ifdef SIO_KEEPALIVE_VALS
3420 else if (!prepKeepalivesWin32(conn))
3421 err = 1;
3422#endif /* SIO_KEEPALIVE_VALS */
3423#endif /* WIN32 */
3424 else if (!setTCPUserTimeout(conn))
3425 err = 1;
3426
3427 if (err)
3428 {
3429 conn->try_next_addr = true;
3430 goto keep_going;
3431 }
3432 }
3433
3434 /*----------
3435 * We have three methods of blocking SIGPIPE during
3436 * send() calls to this socket:
3437 *
3438 * - setsockopt(sock, SO_NOSIGPIPE)
3439 * - send(sock, ..., MSG_NOSIGNAL)
3440 * - setting the signal mask to SIG_IGN during send()
3441 *
3442 * The third method requires three syscalls per send,
3443 * so we prefer either of the first two, but they are
3444 * less portable. The state is tracked in the following
3445 * members of PGconn:
3446 *
3447 * conn->sigpipe_so - we have set up SO_NOSIGPIPE
3448 * conn->sigpipe_flag - we're specifying MSG_NOSIGNAL
3449 *
3450 * If we can use SO_NOSIGPIPE, then set sigpipe_so here
3451 * and we're done. Otherwise, set sigpipe_flag so that
3452 * we will try MSG_NOSIGNAL on sends. If we get an error
3453 * with MSG_NOSIGNAL, we'll clear that flag and revert to
3454 * signal masking.
3455 *----------
3456 */
3457 conn->sigpipe_so = false;
3458#ifdef MSG_NOSIGNAL
3459 conn->sigpipe_flag = true;
3460#else
3461 conn->sigpipe_flag = false;
3462#endif /* MSG_NOSIGNAL */
3463
3464#ifdef SO_NOSIGPIPE
3465 optval = 1;
3466 if (setsockopt(conn->sock, SOL_SOCKET, SO_NOSIGPIPE,
3467 (char *) &optval, sizeof(optval)) == 0)
3468 {
3469 conn->sigpipe_so = true;
3470 conn->sigpipe_flag = false;
3471 }
3472#endif /* SO_NOSIGPIPE */
3473
3474 /*
3475 * Start/make connection. This should not block, since we
3476 * are in nonblock mode. If it does, well, too bad.
3477 */
3478 if (connect(conn->sock, (struct sockaddr *) &addr_cur->addr.addr,
3479 addr_cur->addr.salen) < 0)
3480 {
3481 if (SOCK_ERRNO == EINPROGRESS ||
3482#ifdef WIN32
3484#endif
3485 SOCK_ERRNO == EINTR)
3486 {
3487 /*
3488 * This is fine - we're in non-blocking mode, and
3489 * the connection is in progress. Tell caller to
3490 * wait for write-ready on socket.
3491 */
3493 return PGRES_POLLING_WRITING;
3494 }
3495 /* otherwise, trouble */
3496 }
3497 else
3498 {
3499 /*
3500 * Hm, we're connected already --- seems the "nonblock
3501 * connection" wasn't. Advance the state machine and
3502 * go do the next stuff.
3503 */
3505 goto keep_going;
3506 }
3507
3508 /*
3509 * This connection failed. Add the error report to
3510 * conn->errorMessage, then try the next address if any.
3511 */
3513 conn->try_next_addr = true;
3514 goto keep_going;
3515 }
3516 }
3517
3518 case CONNECTION_STARTED:
3519 {
3520 socklen_t optlen = sizeof(optval);
3521
3522 /*
3523 * Write ready, since we've made it here, so the connection
3524 * has been made ... or has failed.
3525 */
3526
3527 /*
3528 * Now check (using getsockopt) that there is not an error
3529 * state waiting for us on the socket.
3530 */
3531
3532 if (getsockopt(conn->sock, SOL_SOCKET, SO_ERROR,
3533 (char *) &optval, &optlen) == -1)
3534 {
3535 libpq_append_conn_error(conn, "could not get socket error status: %s",
3536 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3537 goto error_return;
3538 }
3539 else if (optval != 0)
3540 {
3541 /*
3542 * When using a nonblocking connect, we will typically see
3543 * connect failures at this point, so provide a friendly
3544 * error message.
3545 */
3546 connectFailureMessage(conn, optval);
3547
3548 /*
3549 * Try the next address if any, just as in the case where
3550 * connect() returned failure immediately.
3551 */
3552 conn->try_next_addr = true;
3553 goto keep_going;
3554 }
3555
3556 /* Fill in the client address */
3557 conn->laddr.salen = sizeof(conn->laddr.addr);
3558 if (getsockname(conn->sock,
3559 (struct sockaddr *) &conn->laddr.addr,
3560 &conn->laddr.salen) < 0)
3561 {
3562 libpq_append_conn_error(conn, "could not get client address from socket: %s",
3563 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3564 goto error_return;
3565 }
3566
3567 /*
3568 * Implement requirepeer check, if requested and it's a
3569 * Unix-domain socket.
3570 */
3571 if (conn->requirepeer && conn->requirepeer[0] &&
3572 conn->raddr.addr.ss_family == AF_UNIX)
3573 {
3574#ifndef WIN32
3575 char *remote_username;
3576#endif
3577 uid_t uid;
3578 gid_t gid;
3579
3580 errno = 0;
3581 if (getpeereid(conn->sock, &uid, &gid) != 0)
3582 {
3583 /*
3584 * Provide special error message if getpeereid is a
3585 * stub
3586 */
3587 if (errno == ENOSYS)
3588 libpq_append_conn_error(conn, "requirepeer parameter is not supported on this platform");
3589 else
3590 libpq_append_conn_error(conn, "could not get peer credentials: %s",
3591 strerror_r(errno, sebuf, sizeof(sebuf)));
3592 goto error_return;
3593 }
3594
3595#ifndef WIN32
3596 remote_username = pg_fe_getusername(uid,
3597 &conn->errorMessage);
3598 if (remote_username == NULL)
3599 goto error_return; /* message already logged */
3600
3601 if (strcmp(remote_username, conn->requirepeer) != 0)
3602 {
3603 libpq_append_conn_error(conn, "requirepeer specifies \"%s\", but actual peer user name is \"%s\"",
3604 conn->requirepeer, remote_username);
3605 free(remote_username);
3606 goto error_return;
3607 }
3608 free(remote_username);
3609#else /* WIN32 */
3610 /* should have failed with ENOSYS above */
3611 Assert(false);
3612#endif /* WIN32 */
3613 }
3614
3615 /*
3616 * Make sure we can write before advancing to next step.
3617 */
3619 return PGRES_POLLING_WRITING;
3620 }
3621
3622 case CONNECTION_MADE:
3623 {
3624 char *startpacket;
3625 int packetlen;
3626
3627#ifdef ENABLE_GSS
3628
3629 /*
3630 * If GSSAPI encryption is enabled, send a packet to the
3631 * server asking for GSSAPI Encryption and proceed with GSSAPI
3632 * handshake. We will come back here after GSSAPI encryption
3633 * has been established, with conn->gctx set.
3634 */
3635 if (conn->current_enc_method == ENC_GSSAPI && !conn->gctx)
3636 {
3638
3639 if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
3640 {
3641 libpq_append_conn_error(conn, "could not send GSSAPI negotiation packet: %s",
3642 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3643 goto error_return;
3644 }
3645
3646 /* Ok, wait for response */
3648 return PGRES_POLLING_READING;
3649 }
3650#endif
3651
3652#ifdef USE_SSL
3653
3654 /*
3655 * If SSL is enabled, start the SSL negotiation. We will come
3656 * back here after SSL encryption has been established, with
3657 * ssl_in_use set.
3658 */
3660 {
3661 /*
3662 * If traditional postgres SSL negotiation is used, send
3663 * the SSL request. In direct negotiation, jump straight
3664 * into the SSL handshake.
3665 */
3666 if (conn->sslnegotiation[0] == 'p')
3667 {
3668 ProtocolVersion pv;
3669
3670 /*
3671 * Send the SSL request packet.
3672 *
3673 * Theoretically, this could block, but it really
3674 * shouldn't since we only got here if the socket is
3675 * write-ready.
3676 */
3678 if (pqPacketSend(conn, 0, &pv, sizeof(pv)) != STATUS_OK)
3679 {
3680 libpq_append_conn_error(conn, "could not send SSL negotiation packet: %s",
3681 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3682 goto error_return;
3683 }
3684 /* Ok, wait for response */
3686 return PGRES_POLLING_READING;
3687 }
3688 else
3689 {
3690 Assert(conn->sslnegotiation[0] == 'd');
3692 return PGRES_POLLING_WRITING;
3693 }
3694 }
3695#endif /* USE_SSL */
3696
3697 /*
3698 * For cancel requests this is as far as we need to go in the
3699 * connection establishment. Now we can actually send our
3700 * cancellation request.
3701 */
3702 if (conn->cancelRequest)
3703 {
3705 {
3706 libpq_append_conn_error(conn, "could not send cancel packet: %s",
3707 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3708 goto error_return;
3709 }
3711 return PGRES_POLLING_READING;
3712 }
3713
3714 /*
3715 * We have now established encryption, or we are happy to
3716 * proceed without.
3717 */
3718
3719 /* Build the startup packet. */
3720 startpacket = pqBuildStartupPacket3(conn, &packetlen,
3722 if (!startpacket)
3723 {
3724 libpq_append_conn_error(conn, "out of memory");
3725 goto error_return;
3726 }
3727
3728 /*
3729 * Send the startup packet.
3730 *
3731 * Theoretically, this could block, but it really shouldn't
3732 * since we only got here if the socket is write-ready.
3733 */
3734 if (pqPacketSend(conn, 0, startpacket, packetlen) != STATUS_OK)
3735 {
3736 libpq_append_conn_error(conn, "could not send startup packet: %s",
3737 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
3738 free(startpacket);
3739 goto error_return;
3740 }
3741
3742 free(startpacket);
3743
3745 return PGRES_POLLING_READING;
3746 }
3747
3748 /*
3749 * Handle SSL negotiation: wait for postmaster messages and
3750 * respond as necessary.
3751 */
3753 {
3754#ifdef USE_SSL
3756
3757 /*
3758 * On first time through with traditional SSL negotiation, get
3759 * the postmaster's response to our SSLRequest packet. With
3760 * sslnegotiation='direct', go straight to initiating SSL.
3761 */
3762 if (!conn->ssl_in_use && conn->sslnegotiation[0] == 'p')
3763 {
3764 /*
3765 * We use pqReadData here since it has the logic to
3766 * distinguish no-data-yet from connection closure. Since
3767 * conn->ssl isn't set, a plain recv() will occur.
3768 */
3769 char SSLok;
3770 int rdresult;
3771
3772 rdresult = pqReadData(conn);
3773 if (rdresult < 0)
3774 {
3775 /* errorMessage is already filled in */
3776 goto error_return;
3777 }
3778 if (rdresult == 0)
3779 {
3780 /* caller failed to wait for data */
3781 return PGRES_POLLING_READING;
3782 }
3783 if (pqGetc(&SSLok, conn) < 0)
3784 {
3785 /* should not happen really */
3786 return PGRES_POLLING_READING;
3787 }
3788 if (SSLok == 'S')
3789 {
3790 if (conn->Pfdebug)
3791 pqTraceOutputCharResponse(conn, "SSLResponse",
3792 SSLok);
3793 /* mark byte consumed */
3795 }
3796 else if (SSLok == 'N')
3797 {
3798 if (conn->Pfdebug)
3799 pqTraceOutputCharResponse(conn, "SSLResponse",
3800 SSLok);
3801 /* mark byte consumed */
3803
3804 /*
3805 * The connection is still valid, so if it's OK to
3806 * continue without SSL, we can proceed using this
3807 * connection. Otherwise return with an error.
3808 */
3809 ENCRYPTION_NEGOTIATION_FAILED(libpq_gettext("server does not support SSL, but SSL was required"));
3810 }
3811 else if (SSLok == 'E')
3812 {
3813 /*
3814 * Server failure of some sort, such as failure to
3815 * fork a backend process. Don't bother retrieving
3816 * the error message; we should not trust it as the
3817 * server has not been authenticated yet.
3818 */
3819 libpq_append_conn_error(conn, "server sent an error response during SSL exchange");
3820 goto error_return;
3821 }
3822 else
3823 {
3824 libpq_append_conn_error(conn, "received invalid response to SSL negotiation: %c",
3825 SSLok);
3826 goto error_return;
3827 }
3828 }
3829
3830 /*
3831 * Begin or continue the SSL negotiation process.
3832 */
3833 pollres = pqsecure_open_client(conn);
3834 if (pollres == PGRES_POLLING_OK)
3835 {
3836 /*
3837 * At this point we should have no data already buffered.
3838 * If we do, it was received before we performed the SSL
3839 * handshake, so it wasn't encrypted and indeed may have
3840 * been injected by a man-in-the-middle.
3841 */
3842 if (conn->inCursor != conn->inEnd)
3843 {
3844 libpq_append_conn_error(conn, "received unencrypted data after SSL response");
3845 goto error_return;
3846 }
3847
3848 /* SSL handshake done, ready to send startup packet */
3850 return PGRES_POLLING_WRITING;
3851 }
3852 if (pollres == PGRES_POLLING_FAILED)
3853 {
3854 /*
3855 * SSL handshake failed. We will retry with a plaintext
3856 * connection, if permitted by sslmode.
3857 */
3859 }
3860 /* Else, return POLLING_READING or POLLING_WRITING status */
3861 return pollres;
3862#else /* !USE_SSL */
3863 /* can't get here */
3864 goto error_return;
3865#endif /* USE_SSL */
3866 }
3867
3869 {
3870#ifdef ENABLE_GSS
3872
3873 /*
3874 * If we haven't yet, get the postmaster's response to our
3875 * negotiation packet
3876 */
3877 if (!conn->gctx)
3878 {
3879 char gss_ok;
3880 int rdresult = pqReadData(conn);
3881
3882 if (rdresult < 0)
3883 /* pqReadData fills in error message */
3884 goto error_return;
3885 else if (rdresult == 0)
3886 /* caller failed to wait for data */
3887 return PGRES_POLLING_READING;
3888 if (pqGetc(&gss_ok, conn) < 0)
3889 /* shouldn't happen... */
3890 return PGRES_POLLING_READING;
3891
3892 if (gss_ok == 'E')
3893 {
3894 /*
3895 * Server failure of some sort, possibly protocol
3896 * version support failure. Don't bother retrieving
3897 * the error message; we should not trust it anyway as
3898 * the server has not authenticated yet.
3899 *
3900 * Note that unlike on an error response to
3901 * SSLRequest, we allow falling back to SSL or
3902 * plaintext connection here. GSS support was
3903 * introduced in PostgreSQL version 12, so an error
3904 * response might mean that we are connecting to a
3905 * pre-v12 server.
3906 */
3907 libpq_append_conn_error(conn, "server sent an error response during GSS encryption exchange");
3909 }
3910
3911 /* mark byte consumed */
3913
3914 if (gss_ok == 'N')
3915 {
3916 if (conn->Pfdebug)
3917 pqTraceOutputCharResponse(conn, "GSSENCResponse",
3918 gss_ok);
3919
3920 /*
3921 * The connection is still valid, so if it's OK to
3922 * continue without GSS, we can proceed using this
3923 * connection. Otherwise return with an error.
3924 */
3925 ENCRYPTION_NEGOTIATION_FAILED(libpq_gettext("server doesn't support GSSAPI encryption, but it was required"));
3926 }
3927 else if (gss_ok != 'G')
3928 {
3929 libpq_append_conn_error(conn, "received invalid response to GSSAPI negotiation: %c",
3930 gss_ok);
3931 goto error_return;
3932 }
3933
3934 if (conn->Pfdebug)
3935 pqTraceOutputCharResponse(conn, "GSSENCResponse",
3936 gss_ok);
3937 }
3938
3939 /* Begin or continue GSSAPI negotiation */
3940 pollres = pqsecure_open_gss(conn);
3941 if (pollres == PGRES_POLLING_OK)
3942 {
3943 /*
3944 * At this point we should have no data already buffered.
3945 * If we do, it was received before we performed the GSS
3946 * handshake, so it wasn't encrypted and indeed may have
3947 * been injected by a man-in-the-middle.
3948 */
3949 if (conn->inCursor != conn->inEnd)
3950 {
3951 libpq_append_conn_error(conn, "received unencrypted data after GSSAPI encryption response");
3952 goto error_return;
3953 }
3954
3955 /* All set for startup packet */
3957 return PGRES_POLLING_WRITING;
3958 }
3959 else if (pollres == PGRES_POLLING_FAILED)
3960 {
3961 /*
3962 * GSS handshake failed. We will retry with an SSL or
3963 * plaintext connection, if permitted by the options.
3964 */
3966 }
3967 /* Else, return POLLING_READING or POLLING_WRITING status */
3968 return pollres;
3969#else /* !ENABLE_GSS */
3970 /* unreachable */
3971 goto error_return;
3972#endif /* ENABLE_GSS */
3973 }
3974
3975 /*
3976 * Handle authentication exchange: wait for postmaster messages
3977 * and respond as necessary.
3978 */
3980 {
3981 char beresp;
3982 int msgLength;
3983 int avail;
3984 AuthRequest areq;
3985 int res;
3986 bool async;
3987
3988 /*
3989 * Scan the message from current point (note that if we find
3990 * the message is incomplete, we will return without advancing
3991 * inStart, and resume here next time).
3992 */
3994
3995 /* Read type byte */
3996 if (pqGetc(&beresp, conn))
3997 {
3998 /* We'll come back when there is more data */
3999 return PGRES_POLLING_READING;
4000 }
4001
4002 /*
4003 * Validate message type: we expect only an authentication
4004 * request, NegotiateProtocolVersion, or an error here.
4005 * Anything else probably means it's not Postgres on the other
4006 * end at all.
4007 */
4008 if (beresp != PqMsg_AuthenticationRequest &&
4009 beresp != PqMsg_ErrorResponse &&
4011 {
4012 libpq_append_conn_error(conn, "expected authentication request from server, but received %c",
4013 beresp);
4014 goto error_return;
4015 }
4016
4017 /* Read message length word */
4018 if (pqGetInt(&msgLength, 4, conn))
4019 {
4020 /* We'll come back when there is more data */
4021 return PGRES_POLLING_READING;
4022 }
4023
4024 /*
4025 * Try to validate message length before using it.
4026 *
4027 * Authentication requests can't be very large, although GSS
4028 * auth requests may not be that small. Same for
4029 * NegotiateProtocolVersion.
4030 *
4031 * Errors can be a little larger, but not huge. If we see a
4032 * large apparent length in an error, it means we're really
4033 * talking to a pre-3.0-protocol server; cope. (Before
4034 * version 14, the server also used the old protocol for
4035 * errors that happened before processing the startup packet.)
4036 */
4037 if (beresp == PqMsg_AuthenticationRequest &&
4038 (msgLength < 8 || msgLength > 2000))
4039 {
4040 libpq_append_conn_error(conn, "received invalid authentication request");
4041 goto error_return;
4042 }
4043 if (beresp == PqMsg_NegotiateProtocolVersion &&
4044 (msgLength < 8 || msgLength > 2000))
4045 {
4046 libpq_append_conn_error(conn, "received invalid protocol negotiation message");
4047 goto error_return;
4048 }
4049
4050#define MAX_ERRLEN 30000
4051 if (beresp == PqMsg_ErrorResponse &&
4052 (msgLength < 8 || msgLength > MAX_ERRLEN))
4053 {
4054 /* Handle error from a pre-3.0 server */
4055 conn->inCursor = conn->inStart + 1; /* reread data */
4057 {
4058 /*
4059 * We may not have authenticated the server yet, so
4060 * don't let the buffer grow forever.
4061 */
4062 avail = conn->inEnd - conn->inCursor;
4063 if (avail > MAX_ERRLEN)
4064 {
4065 libpq_append_conn_error(conn, "received invalid error message");
4066 goto error_return;
4067 }
4068
4069 /* We'll come back when there is more data */
4070 return PGRES_POLLING_READING;
4071 }
4072 /* OK, we read the message; mark data consumed */
4074
4075 /*
4076 * Before 7.2, the postmaster didn't always end its
4077 * messages with a newline, so add one if needed to
4078 * conform to libpq conventions.
4079 */
4080 if (conn->errorMessage.len == 0 ||
4081 conn->errorMessage.data[conn->errorMessage.len - 1] != '\n')
4082 {
4084 }
4085
4086 goto error_return;
4087 }
4088#undef MAX_ERRLEN
4089
4090 /*
4091 * Can't process if message body isn't all here yet.
4092 *
4093 * After this check passes, any further EOF during parsing
4094 * implies that the server sent a bad/truncated message.
4095 * Reading more bytes won't help in that case, so don't return
4096 * PGRES_POLLING_READING after this point.
4097 */
4098 msgLength -= 4;
4099 avail = conn->inEnd - conn->inCursor;
4100 if (avail < msgLength)
4101 {
4102 /*
4103 * Before returning, try to enlarge the input buffer if
4104 * needed to hold the whole message; see notes in
4105 * pqParseInput3.
4106 */
4107 if (pqCheckInBufferSpace(conn->inCursor + (size_t) msgLength,
4108 conn))
4109 goto error_return;
4110 /* We'll come back when there is more data */
4111 return PGRES_POLLING_READING;
4112 }
4113
4114 /* Handle errors. */
4115 if (beresp == PqMsg_ErrorResponse)
4116 {
4117 if (pqGetErrorNotice3(conn, true))
4118 {
4119 libpq_append_conn_error(conn, "received invalid error message");
4120 goto error_return;
4121 }
4122 /* OK, we read the message; mark data consumed */
4124
4125 /*
4126 * If error is "cannot connect now", try the next host if
4127 * any (but we don't want to consider additional addresses
4128 * for this host, nor is there much point in changing SSL
4129 * or GSS mode). This is helpful when dealing with
4130 * standby servers that might not be in hot-standby state.
4131 */
4132 if (strcmp(conn->last_sqlstate,
4134 {
4135 conn->try_next_host = true;
4136 goto keep_going;
4137 }
4138
4139 /* Check to see if we should mention pgpassfile */
4141
4143 }
4144 /* Handle NegotiateProtocolVersion */
4145 else if (beresp == PqMsg_NegotiateProtocolVersion)
4146 {
4148 {
4149 libpq_append_conn_error(conn, "received duplicate protocol negotiation message");
4150 goto error_return;
4151 }
4153 {
4154 /* pqGetNegotiateProtocolVersion3 set error already */
4155 goto error_return;
4156 }
4157 conn->pversion_negotiated = true;
4158
4159 /* OK, we read the message; mark data consumed */
4161
4162 goto keep_going;
4163 }
4164
4165 /* It is an authentication request. */
4166 conn->auth_req_received = true;
4167
4168 /* Get the type of request. */
4169 if (pqGetInt((int *) &areq, 4, conn))
4170 {
4171 /* can't happen because we checked the length already */
4172 libpq_append_conn_error(conn, "received invalid authentication request");
4173 goto error_return;
4174 }
4175 msgLength -= 4;
4176
4177 /*
4178 * Process the rest of the authentication request message, and
4179 * respond to it if necessary.
4180 *
4181 * Note that conn->pghost must be non-NULL if we are going to
4182 * avoid the Kerberos code doing a hostname look-up.
4183 */
4184 res = pg_fe_sendauth(areq, msgLength, conn, &async);
4185
4186 if (async && (res == STATUS_OK))
4187 {
4188 /*
4189 * We'll come back later once we're ready to respond.
4190 * Don't consume the request yet.
4191 */
4193 goto keep_going;
4194 }
4195
4196 /*
4197 * OK, we have processed the message; mark data consumed. We
4198 * don't call pqParseDone here because we already traced this
4199 * message inside pg_fe_sendauth.
4200 */
4202
4203 if (res != STATUS_OK)
4204 {
4205 /*
4206 * OAuth connections may perform two-step discovery, where
4207 * the first connection is a dummy.
4208 */
4210 {
4211 need_new_connection = true;
4212 goto keep_going;
4213 }
4214
4215 goto error_return;
4216 }
4217
4218 /*
4219 * Just make sure that any data sent by pg_fe_sendauth is
4220 * flushed out. Although this theoretically could block, it
4221 * really shouldn't since we don't send large auth responses.
4222 */
4223 if (pqFlush(conn))
4224 goto error_return;
4225
4226 if (areq == AUTH_REQ_OK)
4227 {
4228 /* We are done with authentication exchange */
4230
4231 /*
4232 * Set asyncStatus so that PQgetResult will think that
4233 * what comes back next is the result of a query. See
4234 * below.
4235 */
4237 }
4238
4239 /* Look to see if we have more data yet. */
4240 goto keep_going;
4241 }
4242
4244 {
4246
4248 {
4249 /* programmer error; should not happen */
4251 "internal error: async authentication has no handler");
4252 goto error_return;
4253 }
4254
4255 /* Drive some external authentication work. */
4256 status = conn->async_auth(conn);
4257
4258 if (status == PGRES_POLLING_FAILED)
4259 goto error_return;
4260
4261 if (status == PGRES_POLLING_OK)
4262 {
4263 /* Done. Tear down the async implementation. */
4265 conn->cleanup_async_auth = NULL;
4266
4267 /*
4268 * Cleanup must unset altsock, both as an indication that
4269 * it's been released, and to stop pqSocketCheck from
4270 * looking at the wrong socket after async auth is done.
4271 */
4273 {
4274 Assert(false);
4276 "internal error: async cleanup did not release polling socket");
4277 goto error_return;
4278 }
4279
4280 /*
4281 * Reenter the authentication exchange with the server. We
4282 * didn't consume the message that started external
4283 * authentication, so it'll be reprocessed as if we just
4284 * received it.
4285 */
4287
4288 goto keep_going;
4289 }
4290
4291 /*
4292 * Caller needs to poll some more. conn->async_auth() should
4293 * have assigned an altsock to poll on.
4294 */
4296 {
4297 Assert(false);
4299 "internal error: async authentication did not set a socket for polling");
4300 goto error_return;
4301 }
4302
4303 return status;
4304 }
4305
4306 case CONNECTION_AUTH_OK:
4307 {
4308 /*
4309 * Now we expect to hear from the backend. A ReadyForQuery
4310 * message indicates that startup is successful, but we might
4311 * also get an Error message indicating failure. (Notice
4312 * messages indicating nonfatal warnings are also allowed by
4313 * the protocol, as are ParameterStatus and BackendKeyData
4314 * messages.) Easiest way to handle this is to let
4315 * PQgetResult() read the messages. We just have to fake it
4316 * out about the state of the connection, by setting
4317 * asyncStatus = PGASYNC_BUSY (done above).
4318 */
4319
4320 if (PQisBusy(conn))
4321 return PGRES_POLLING_READING;
4322
4323 res = PQgetResult(conn);
4324
4325 /*
4326 * NULL return indicating we have gone to IDLE state is
4327 * expected
4328 */
4329 if (res)
4330 {
4331 if (res->resultStatus != PGRES_FATAL_ERROR)
4332 libpq_append_conn_error(conn, "unexpected message from server during startup");
4333 else if (conn->send_appname &&
4334 (conn->appname || conn->fbappname))
4335 {
4336 /*
4337 * If we tried to send application_name, check to see
4338 * if the error is about that --- pre-9.0 servers will
4339 * reject it at this stage of the process. If so,
4340 * close the connection and retry without sending
4341 * application_name. We could possibly get a false
4342 * SQLSTATE match here and retry uselessly, but there
4343 * seems no great harm in that; we'll just get the
4344 * same error again if it's unrelated.
4345 */
4346 const char *sqlstate;
4347
4348 sqlstate = PQresultErrorField(res, PG_DIAG_SQLSTATE);
4349 if (sqlstate &&
4350 strcmp(sqlstate, ERRCODE_APPNAME_UNKNOWN) == 0)
4351 {
4352 PQclear(res);
4353 conn->send_appname = false;
4354 need_new_connection = true;
4355 goto keep_going;
4356 }
4357 }
4358
4359 /*
4360 * if the resultStatus is FATAL, then conn->errorMessage
4361 * already has a copy of the error; needn't copy it back.
4362 * But add a newline if it's not there already, since
4363 * postmaster error messages may not have one.
4364 */
4365 if (conn->errorMessage.len <= 0 ||
4366 conn->errorMessage.data[conn->errorMessage.len - 1] != '\n')
4368 PQclear(res);
4369 goto error_return;
4370 }
4371
4372 /* Almost there now ... */
4374 goto keep_going;
4375 }
4376
4378 {
4379 /*
4380 * If a read-write, read-only, primary, or standby connection
4381 * is required, see if we have one.
4382 */
4385 {
4386 bool read_only_server;
4387
4388 /*
4389 * If the server didn't report
4390 * "default_transaction_read_only" or "in_hot_standby" at
4391 * startup, we must determine its state by sending the
4392 * query "SHOW transaction_read_only". This GUC exists in
4393 * all server versions that support 3.0 protocol.
4394 */
4397 {
4398 /*
4399 * We use PQsendQueryContinue so that
4400 * conn->errorMessage does not get cleared. We need
4401 * to preserve any error messages related to previous
4402 * hosts we have tried and failed to connect to.
4403 */
4406 "SHOW transaction_read_only"))
4407 goto error_return;
4408 /* We'll return to this state when we have the answer */
4410 return PGRES_POLLING_READING;
4411 }
4412
4413 /* OK, we can make the test */
4414 read_only_server =
4417
4419 read_only_server : !read_only_server)
4420 {
4421 /* Wrong server state, reject and try the next host */
4423 libpq_append_conn_error(conn, "session is read-only");
4424 else
4425 libpq_append_conn_error(conn, "session is not read-only");
4426
4427 /* Close connection politely. */
4430
4431 /*
4432 * Try next host if any, but we don't want to consider
4433 * additional addresses for this host.
4434 */
4435 conn->try_next_host = true;
4436 goto keep_going;
4437 }
4438 }
4442 {
4443 /*
4444 * If the server didn't report "in_hot_standby" at
4445 * startup, we must determine its state by sending the
4446 * query "SELECT pg_catalog.pg_is_in_recovery()". Servers
4447 * before 9.0 don't have that function, but by the same
4448 * token they don't have any standby mode, so we may just
4449 * assume the result.
4450 */
4451 if (conn->sversion < 90000)
4453
4455 {
4456 /*
4457 * We use PQsendQueryContinue so that
4458 * conn->errorMessage does not get cleared. We need
4459 * to preserve any error messages related to previous
4460 * hosts we have tried and failed to connect to.
4461 */
4464 "SELECT pg_catalog.pg_is_in_recovery()"))
4465 goto error_return;
4466 /* We'll return to this state when we have the answer */
4468 return PGRES_POLLING_READING;
4469 }
4470
4471 /* OK, we can make the test */
4475 {
4476 /* Wrong server state, reject and try the next host */
4478 libpq_append_conn_error(conn, "server is in hot standby mode");
4479 else
4480 libpq_append_conn_error(conn, "server is not in hot standby mode");
4481
4482 /* Close connection politely. */
4485
4486 /*
4487 * Try next host if any, but we don't want to consider
4488 * additional addresses for this host.
4489 */
4490 conn->try_next_host = true;
4491 goto keep_going;
4492 }
4493 }
4494
4495 /* Don't hold onto any OAuth tokens longer than necessary. */
4497
4498 /*
4499 * For non cancel requests we can release the address list
4500 * now. For cancel requests we never actually resolve
4501 * addresses and instead the addrinfo exists for the lifetime
4502 * of the connection.
4503 */
4504 if (!conn->cancelRequest)
4506
4507 /*
4508 * Contents of conn->errorMessage are no longer interesting
4509 * (and it seems some clients expect it to be empty after a
4510 * successful connection).
4511 */
4513
4514 /* We are open for business! */
4516 return PGRES_POLLING_OK;
4517 }
4518
4519 case CONNECTION_CONSUME:
4520 {
4521 /*
4522 * This state just makes sure the connection is idle after
4523 * we've obtained the result of a SHOW or SELECT query. Once
4524 * we're clear, return to CONNECTION_CHECK_TARGET state to
4525 * decide what to do next. We must transiently set status =
4526 * CONNECTION_OK in order to use the result-consuming
4527 * subroutines.
4528 */
4530 if (!PQconsumeInput(conn))
4531 goto error_return;
4532
4533 if (PQisBusy(conn))
4534 {
4536 return PGRES_POLLING_READING;
4537 }
4538
4539 /* Call PQgetResult() again until we get a NULL result */
4540 res = PQgetResult(conn);
4541 if (res != NULL)
4542 {
4543 PQclear(res);
4545 return PGRES_POLLING_READING;
4546 }
4547
4549 goto keep_going;
4550 }
4551
4553 {
4554 /*
4555 * Waiting for result of "SHOW transaction_read_only". We
4556 * must transiently set status = CONNECTION_OK in order to use
4557 * the result-consuming subroutines.
4558 */
4560 if (!PQconsumeInput(conn))
4561 goto error_return;
4562
4563 if (PQisBusy(conn))
4564 {
4566 return PGRES_POLLING_READING;
4567 }
4568
4569 res = PQgetResult(conn);
4570 if (res && PQresultStatus(res) == PGRES_TUPLES_OK &&
4571 PQntuples(res) == 1)
4572 {
4573 char *val = PQgetvalue(res, 0, 0);
4574
4575 /*
4576 * "transaction_read_only = on" proves that at least one
4577 * of default_transaction_read_only and in_hot_standby is
4578 * on, but we don't actually know which. We don't care
4579 * though for the purpose of identifying a read-only
4580 * session, so satisfy the CONNECTION_CHECK_TARGET code by
4581 * claiming they are both on. On the other hand, if it's
4582 * a read-write session, they are certainly both off.
4583 */
4584 if (strncmp(val, "on", 2) == 0)
4585 {
4588 }
4589 else
4590 {
4593 }
4594 PQclear(res);
4595
4596 /* Finish reading messages before continuing */
4598 goto keep_going;
4599 }
4600
4601 /* Something went wrong with "SHOW transaction_read_only". */
4602 PQclear(res);
4603
4604 /* Append error report to conn->errorMessage. */
4605 libpq_append_conn_error(conn, "\"%s\" failed",
4606 "SHOW transaction_read_only");
4607
4608 /* Close connection politely. */
4611
4612 /* Try next host. */
4613 conn->try_next_host = true;
4614 goto keep_going;
4615 }
4616
4618 {
4619 /*
4620 * Waiting for result of "SELECT pg_is_in_recovery()". We
4621 * must transiently set status = CONNECTION_OK in order to use
4622 * the result-consuming subroutines.
4623 */
4625 if (!PQconsumeInput(conn))
4626 goto error_return;
4627
4628 if (PQisBusy(conn))
4629 {
4631 return PGRES_POLLING_READING;
4632 }
4633
4634 res = PQgetResult(conn);
4635 if (res && PQresultStatus(res) == PGRES_TUPLES_OK &&
4636 PQntuples(res) == 1)
4637 {
4638 char *val = PQgetvalue(res, 0, 0);
4639
4640 if (strncmp(val, "t", 1) == 0)
4642 else
4644 PQclear(res);
4645
4646 /* Finish reading messages before continuing */
4648 goto keep_going;
4649 }
4650
4651 /* Something went wrong with "SELECT pg_is_in_recovery()". */
4652 PQclear(res);
4653
4654 /* Append error report to conn->errorMessage. */
4655 libpq_append_conn_error(conn, "\"%s\" failed",
4656 "SELECT pg_is_in_recovery()");
4657
4658 /* Close connection politely. */
4661
4662 /* Try next host. */
4663 conn->try_next_host = true;
4664 goto keep_going;
4665 }
4666
4667 default:
4669 "invalid connection state %d, probably indicative of memory corruption",
4670 conn->status);
4671 goto error_return;
4672 }
4673
4674 /* Unreachable */
4675
4676error_return:
4677
4678 /*
4679 * We used to close the socket at this point, but that makes it awkward
4680 * for those above us if they wish to remove this socket from their own
4681 * records (an fd_set for example). We'll just have this socket closed
4682 * when PQfinish is called (which is compulsory even after an error, since
4683 * the connection structure must be freed).
4684 */
4686 return PGRES_POLLING_FAILED;
4687}
#define STATUS_OK
Definition: c.h:1140
void err(int eval, const char *fmt,...)
Definition: err.c:43
int pg_fe_sendauth(AuthRequest areq, int payloadlen, PGconn *conn, bool *async)
Definition: fe-auth.c:1066
char * pg_fe_getusername(uid_t user_id, PQExpBuffer errorMessage)
Definition: fe-auth.c:1286
int PQsendCancelRequest(PGconn *cancelConn)
Definition: fe-cancel.c:454
#define MAX_ERRLEN
static const PQEnvironmentOption EnvironmentOptions[]
Definition: fe-connect.c:413
#define CONNECTION_FAILED()
static int setKeepalivesCount(PGconn *conn)
Definition: fe-connect.c:2565
static int useKeepalives(PGconn *conn)
Definition: fe-connect.c:2478
static int store_conn_addrinfo(PGconn *conn, struct addrinfo *addrlist)
Definition: fe-connect.c:5156
static void connectFailureMessage(PGconn *conn, int errorno)
Definition: fe-connect.c:2458
#define ERRCODE_APPNAME_UNKNOWN
Definition: fe-connect.c:89
static int setKeepalivesInterval(PGconn *conn)
Definition: fe-connect.c:2530
static int setKeepalivesIdle(PGconn *conn)
Definition: fe-connect.c:2496
static void pgpassfileWarning(PGconn *conn)
Definition: fe-connect.c:8034
static void emitHostIdentityInfo(PGconn *conn, const char *host_addr)
Definition: fe-connect.c:2402
static int setTCPUserTimeout(PGconn *conn)
Definition: fe-connect.c:2662
static int connectNoDelay(PGconn *conn)
Definition: fe-connect.c:2343
static void getHostaddr(PGconn *conn, char *host_addr, int host_addr_len)
Definition: fe-connect.c:2369
#define ENCRYPTION_NEGOTIATION_FAILED(msg)
static bool init_allowed_encryption_methods(PGconn *conn)
Definition: fe-connect.c:4693
int pqPacketSend(PGconn *conn, char pack_type, const void *buf, size_t buf_len)
Definition: fe-connect.c:5398
int PQsendQueryContinue(PGconn *conn, const char *query)
Definition: fe-exec.c:1422
char * PQgetvalue(const PGresult *res, int tup_num, int field_num)
Definition: fe-exec.c:3876
PGresult * PQgetResult(PGconn *conn)
Definition: fe-exec.c:2062
ExecStatusType PQresultStatus(const PGresult *res)
Definition: fe-exec.c:3411
void PQclear(PGresult *res)
Definition: fe-exec.c:721
int PQntuples(const PGresult *res)
Definition: fe-exec.c:3481
int PQconsumeInput(PGconn *conn)
Definition: fe-exec.c:1984
int PQisBusy(PGconn *conn)
Definition: fe-exec.c:2031
bool pg_GSS_have_cred_cache(gss_cred_id_t *cred_out)
int pqReadData(PGconn *conn)
Definition: fe-misc.c:580
int pqFlush(PGconn *conn)
Definition: fe-misc.c:968
void pqParseDone(PGconn *conn, int newInStart)
Definition: fe-misc.c:443
int pqGetc(char *result, PGconn *conn)
Definition: fe-misc.c:77
int pqGetInt(int *result, size_t bytes, PGconn *conn)
Definition: fe-misc.c:216
int pqCheckInBufferSpace(size_t bytes_needed, PGconn *conn)
Definition: fe-misc.c:351
int pqGets_append(PQExpBuffer buf, PGconn *conn)
Definition: fe-misc.c:142
char * pqBuildStartupPacket3(PGconn *conn, int *packetlen, const PQEnvironmentOption *options)
int pqGetNegotiateProtocolVersion3(PGconn *conn)
int pqGetErrorNotice3(PGconn *conn, bool isError)
Definition: fe-protocol3.c:878
PostgresPollingStatusType pqsecure_open_gss(PGconn *conn)
PostgresPollingStatusType pqsecure_open_client(PGconn *conn)
Definition: fe-secure.c:138
void pqTraceOutputCharResponse(PGconn *conn, const char *responseType, char response)
Definition: fe-trace.c:915
void pg_freeaddrinfo_all(int hint_ai_family, struct addrinfo *ai)
Definition: ip.c:82
int pg_getaddrinfo_all(const char *hostname, const char *servname, const struct addrinfo *hintp, struct addrinfo **result)
Definition: ip.c:53
@ CONNECTION_CONSUME
Definition: libpq-fe.h:102
@ CONNECTION_AUTHENTICATING
Definition: libpq-fe.h:109
@ CONNECTION_CHECK_STANDBY
Definition: libpq-fe.h:106
@ CONNECTION_STARTED
Definition: libpq-fe.h:92
@ CONNECTION_AWAITING_RESPONSE
Definition: libpq-fe.h:94
@ CONNECTION_CHECK_WRITABLE
Definition: libpq-fe.h:101
@ CONNECTION_GSS_STARTUP
Definition: libpq-fe.h:103
@ CONNECTION_SSL_STARTUP
Definition: libpq-fe.h:99
@ CONNECTION_AUTH_OK
Definition: libpq-fe.h:96
@ CONNECTION_CHECK_TARGET
Definition: libpq-fe.h:104
@ PGRES_FATAL_ERROR
Definition: libpq-fe.h:136
@ PGRES_TUPLES_OK
Definition: libpq-fe.h:128
@ PGRES_POLLING_FAILED
Definition: libpq-fe.h:115
@ PGASYNC_BUSY
Definition: libpq-int.h:216
@ PG_BOOL_YES
Definition: libpq-int.h:257
@ PG_BOOL_NO
Definition: libpq-int.h:258
@ PG_BOOL_UNKNOWN
Definition: libpq-int.h:256
#define pg_hton32(x)
Definition: pg_bswap.h:121
static char portstr[16]
Definition: pg_regress.c:116
bool pg_set_noblock(pgsocket sock)
Definition: noblock.c:25
unsigned int socklen_t
Definition: port.h:40
#define PGINVALID_SOCKET
Definition: port.h:31
#define strerror_r
Definition: port.h:256
int getpeereid(int sock, uid_t *uid, gid_t *gid)
Definition: getpeereid.c:33
#define UNIXSOCK_PATH(path, port, sockdir)
Definition: pqcomm.h:44
#define UNIXSOCK_PATH_BUFLEN
Definition: pqcomm.h:60
#define NEGOTIATE_GSS_CODE
Definition: pqcomm.h:173
#define NEGOTIATE_SSL_CODE
Definition: pqcomm.h:172
uint32 ProtocolVersion
Definition: pqcomm.h:99
uint32 AuthRequest
Definition: pqcomm.h:121
#define AUTH_REQ_OK
Definition: protocol.h:74
#define PqMsg_AuthenticationRequest
Definition: protocol.h:50
#define PqMsg_NegotiateProtocolVersion
Definition: protocol.h:59
#define PqMsg_ErrorResponse
Definition: protocol.h:44
const char * gai_strerror(int ecode)
int family
Definition: pqcomm.h:38
SockAddr addr
Definition: pqcomm.h:39
SockAddr laddr
Definition: libpq-int.h:498
AddrInfo * addr
Definition: libpq-int.h:538
bool sigpipe_flag
Definition: libpq-int.h:508
ProtocolVersion pversion
Definition: libpq-int.h:500
bool send_appname
Definition: libpq-int.h:540
const pg_fe_sasl_mech * sasl
Definition: libpq-int.h:599
PGTernaryBool in_hot_standby
Definition: libpq-int.h:556
void(* cleanup_async_auth)(PGconn *conn)
Definition: libpq-int.h:526
int naddr
Definition: libpq-int.h:536
int sversion
Definition: libpq-int.h:501
bool pversion_negotiated
Definition: libpq-int.h:502
bool oauth_want_retry
Definition: libpq-int.h:444
PGTernaryBool default_transaction_read_only
Definition: libpq-int.h:555
bool sigpipe_so
Definition: libpq-int.h:507
pgsocket altsock
Definition: libpq-int.h:527
PostgresPollingStatusType(* async_auth)(PGconn *conn)
Definition: libpq-int.h:525
FILE * Pfdebug
Definition: libpq-int.h:447
bool ssl_in_use
Definition: libpq-int.h:608
#define EINTR
Definition: win32_port.h:364
#define EWOULDBLOCK
Definition: win32_port.h:370
#define EINPROGRESS
Definition: win32_port.h:376
int gid_t
Definition: win32_port.h:235
#define socket(af, type, protocol)
Definition: win32_port.h:498
#define connect(s, name, namelen)
Definition: win32_port.h:502
int uid_t
Definition: win32_port.h:234

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

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

◆ PQconnectStart()

PGconn * PQconnectStart ( const char *  conninfo)

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

942{
943 PGconn *conn;
944
945 /*
946 * Allocate memory for the conn structure. Note that we also expect this
947 * to initialize conn->errorMessage to empty. All subsequent steps during
948 * connection initialization will only append to that buffer.
949 */
951 if (conn == NULL)
952 return NULL;
953
954 /*
955 * Parse the conninfo string
956 */
957 if (!connectOptions1(conn, conninfo))
958 return conn;
959
960 /*
961 * Compute derived options
962 */
964 return conn;
965
966 /*
967 * Connect to the database
968 */
970 {
971 /* Just in case we failed to set it in pqConnectDBStart */
973 }
974
975 return conn;
976}
static bool connectOptions1(PGconn *conn, const char *conninfo)
Definition: fe-connect.c:1066
bool pqConnectOptions2(PGconn *conn)
Definition: fe-connect.c:1240
PGconn * pqMakeEmptyPGconn(void)
Definition: fe-connect.c:4937
int pqConnectDBStart(PGconn *conn)
Definition: fe-connect.c:2701

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

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

◆ PQconnectStartParams()

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

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

863{
864 PGconn *conn;
865 PQconninfoOption *connOptions;
866
867 /*
868 * Allocate memory for the conn structure. Note that we also expect this
869 * to initialize conn->errorMessage to empty. All subsequent steps during
870 * connection initialization will only append to that buffer.
871 */
873 if (conn == NULL)
874 return NULL;
875
876 /*
877 * Parse the conninfo arrays
878 */
879 connOptions = conninfo_array_parse(keywords, values,
881 true, expand_dbname);
882 if (connOptions == NULL)
883 {
885 /* errorMessage is already set */
886 return conn;
887 }
888
889 /*
890 * Move option values into conn structure
891 */
892 if (!fillPGconn(conn, connOptions))
893 {
894 PQconninfoFree(connOptions);
895 return conn;
896 }
897
898 /*
899 * Free the option info - all is in conn now
900 */
901 PQconninfoFree(connOptions);
902
903 /*
904 * Compute derived options
905 */
907 return conn;
908
909 /*
910 * Connect to the database
911 */
913 {
914 /* Just in case we failed to set it in pqConnectDBStart */
916 }
917
918 return conn;
919}
static PQconninfoOption * conninfo_array_parse(const char *const *keywords, const char *const *values, PQExpBuffer errorMessage, bool use_defaults, int expand_dbname)
Definition: fe-connect.c:6441

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

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

◆ PQconninfo()

PQconninfoOption * PQconninfo ( PGconn conn)

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

7391{
7392 PQExpBufferData errorBuf;
7393 PQconninfoOption *connOptions;
7394
7395 if (conn == NULL)
7396 return NULL;
7397
7398 /*
7399 * We don't actually report any errors here, but callees want a buffer,
7400 * and we prefer not to trash the conn's errorMessage.
7401 */
7402 initPQExpBuffer(&errorBuf);
7403 if (PQExpBufferDataBroken(errorBuf))
7404 return NULL; /* out of memory already :-( */
7405
7406 connOptions = conninfo_init(&errorBuf);
7407
7408 if (connOptions != NULL)
7409 {
7411
7412 for (option = PQconninfoOptions; option->keyword; option++)
7413 {
7414 char **connmember;
7415
7416 if (option->connofs < 0)
7417 continue;
7418
7419 connmember = (char **) ((char *) conn + option->connofs);
7420
7421 if (*connmember)
7422 conninfo_storeval(connOptions, option->keyword, *connmember,
7423 &errorBuf, true, false);
7424 }
7425 }
7426
7427 termPQExpBuffer(&errorBuf);
7428
7429 return connOptions;
7430}

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

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

◆ PQconninfoFree()

◆ PQconninfoParse()

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

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

6151{
6152 PQExpBufferData errorBuf;
6153 PQconninfoOption *connOptions;
6154
6155 if (errmsg)
6156 *errmsg = NULL; /* default */
6157 initPQExpBuffer(&errorBuf);
6158 if (PQExpBufferDataBroken(errorBuf))
6159 return NULL; /* out of memory already :-( */
6160 connOptions = parse_connection_string(conninfo, &errorBuf, false);
6161 if (connOptions == NULL && errmsg)
6162 *errmsg = errorBuf.data;
6163 else
6164 termPQExpBuffer(&errorBuf);
6165 return connOptions;
6166}
int errmsg(const char *fmt,...)
Definition: elog.c:1071

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

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

◆ pqCopyPGconn()

bool pqCopyPGconn ( PGconn srcConn,
PGconn dstConn 
)

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

1026{
1028
1029 /* copy over connection options */
1030 for (option = PQconninfoOptions; option->keyword; option++)
1031 {
1032 if (option->connofs >= 0)
1033 {
1034 const char **tmp = (const char **) ((char *) srcConn + option->connofs);
1035
1036 if (*tmp)
1037 {
1038 char **dstConnmember = (char **) ((char *) dstConn + option->connofs);
1039
1040 if (*dstConnmember)
1041 free(*dstConnmember);
1042 *dstConnmember = strdup(*tmp);
1043 if (*dstConnmember == NULL)
1044 {
1045 libpq_append_conn_error(dstConn, "out of memory");
1046 return false;
1047 }
1048 }
1049 }
1050 }
1051 return true;
1052}

References free, libpq_append_conn_error(), and PQconninfoOptions.

Referenced by PQcancelCreate().

◆ PQdb()

◆ pqDropConnection()

void pqDropConnection ( PGconn conn,
bool  flushInput 
)

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

521{
522 /* Drop any SSL state */
524
525 /* Close the socket itself */
526 if (conn->sock != PGINVALID_SOCKET)
529
530 /* Optionally discard any unread data */
531 if (flushInput)
532 conn->inStart = conn->inCursor = conn->inEnd = 0;
533
534 /* Always discard any unsent data */
535 conn->outCount = 0;
536
537 /* Likewise, discard any pending pipelined commands */
541 conn->cmd_queue_recycle = NULL;
542
543 /* Free authentication/encryption state */
545 {
546 /*
547 * Any in-progress async authentication should be torn down first so
548 * that cleanup_async_auth() can depend on the other authentication
549 * state if necessary.
550 */
552 conn->cleanup_async_auth = NULL;
553 }
554 conn->async_auth = NULL;
555 /* cleanup_async_auth() should have done this, but make sure */
557#ifdef ENABLE_GSS
558 {
559 OM_uint32 min_s;
560
561 if (conn->gcred != GSS_C_NO_CREDENTIAL)
562 {
563 gss_release_cred(&min_s, &conn->gcred);
564 conn->gcred = GSS_C_NO_CREDENTIAL;
565 }
566 if (conn->gctx)
567 gss_delete_sec_context(&min_s, &conn->gctx, GSS_C_NO_BUFFER);
568 if (conn->gtarg_nam)
569 gss_release_name(&min_s, &conn->gtarg_nam);
570 if (conn->gss_SendBuffer)
571 {
572 free(conn->gss_SendBuffer);
573 conn->gss_SendBuffer = NULL;
574 }
575 if (conn->gss_RecvBuffer)
576 {
577 free(conn->gss_RecvBuffer);
578 conn->gss_RecvBuffer = NULL;
579 }
580 if (conn->gss_ResultBuffer)
581 {
582 free(conn->gss_ResultBuffer);
583 conn->gss_ResultBuffer = NULL;
584 }
585 conn->gssenc = false;
586 }
587#endif
588#ifdef ENABLE_SSPI
589 if (conn->sspitarget)
590 {
591 free(conn->sspitarget);
592 conn->sspitarget = NULL;
593 }
594 if (conn->sspicred)
595 {
596 FreeCredentialsHandle(conn->sspicred);
597 free(conn->sspicred);
598 conn->sspicred = NULL;
599 }
600 if (conn->sspictx)
601 {
602 DeleteSecurityContext(conn->sspictx);
603 free(conn->sspictx);
604 conn->sspictx = NULL;
605 }
606 conn->usesspi = 0;
607#endif
608 if (conn->sasl_state)
609 {
611 conn->sasl_state = NULL;
612 }
613}
static void pqFreeCommandQueue(PGcmdQueueEntry *queue)
Definition: fe-connect.c:620
void pqsecure_close(PGconn *conn)
Definition: fe-secure.c:152
#define closesocket
Definition: port.h:377
PGcmdQueueEntry * cmd_queue_recycle
Definition: libpq-int.h:493
PGcmdQueueEntry * cmd_queue_tail
Definition: libpq-int.h:487
void * sasl_state
Definition: libpq-int.h:600
PGcmdQueueEntry * cmd_queue_head
Definition: libpq-int.h:486
void(* free)(void *state)
Definition: fe-auth-sasl.h:149

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

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

◆ pqDropServerData()

static void pqDropServerData ( PGconn conn)
static

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

647{
648 PGnotify *notify;
649 pgParameterStatus *pstatus;
650
651 /* Forget pending notifies */
652 notify = conn->notifyHead;
653 while (notify != NULL)
654 {
655 PGnotify *prev = notify;
656
657 notify = notify->next;
658 free(prev);
659 }
660 conn->notifyHead = conn->notifyTail = NULL;
661
662 /* Reset ParameterStatus data, as well as variables deduced from it */
663 pstatus = conn->pstatus;
664 while (pstatus != NULL)
665 {
666 pgParameterStatus *prev = pstatus;
667
668 pstatus = pstatus->next;
669 free(prev);
670 }
671 conn->pstatus = NULL;
673 conn->std_strings = false;
677 conn->sversion = 0;
678
679 /* Drop large-object lookup data */
681 conn->lobjfuncs = NULL;
682
683 /* Reset assorted other per-connection state */
684 conn->last_sqlstate[0] = '\0';
685 conn->pversion_negotiated = false;
686 conn->auth_req_received = false;
687 conn->client_finished_auth = false;
688 conn->password_needed = false;
689 conn->gssapi_used = false;
690 conn->write_failed = false;
692 conn->write_err_msg = NULL;
693 conn->oauth_want_retry = false;
694
695 /*
696 * Cancel connections need to retain their be_pid and be_cancel_key across
697 * PQcancelReset invocations, otherwise they would not have access to the
698 * secret token of the connection they are supposed to cancel.
699 */
700 if (!conn->cancelRequest)
701 {
702 conn->be_pid = 0;
703 if (conn->be_cancel_key != NULL)
704 {
706 conn->be_cancel_key = NULL;
707 }
709 }
710}
@ PG_SQL_ASCII
Definition: pg_wchar.h:226
#define SCRAM_SHA_256_DEFAULT_ITERATIONS
Definition: scram-common.h:50
struct pgNotify * next
Definition: libpq-fe.h:234
struct pgParameterStatus * next
Definition: libpq-int.h:271
PGnotify * notifyHead
Definition: libpq-int.h:473
char * be_cancel_key
Definition: libpq-int.h:550
bool std_strings
Definition: libpq-int.h:554
bool write_failed
Definition: libpq-int.h:509
bool client_finished_auth
Definition: libpq-int.h:518
PGnotify * notifyTail
Definition: libpq-int.h:474
pgParameterStatus * pstatus
Definition: libpq-int.h:552
int scram_sha_256_iterations
Definition: libpq-int.h:601
PGlobjfuncs * lobjfuncs
Definition: libpq-int.h:559
uint16 be_cancel_key_len
Definition: libpq-int.h:551

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

Referenced by pqClosePGconn(), and PQconnectPoll().

◆ PQerrorMessage()

char * PQerrorMessage ( const PGconn conn)

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

7620{
7621 if (!conn)
7622 return libpq_gettext("connection pointer is NULL\n");
7623
7624 /*
7625 * The errorMessage buffer might be marked "broken" due to having
7626 * previously failed to allocate enough memory for the message. In that
7627 * case, tell the application we ran out of memory.
7628 */
7630 return libpq_gettext("out of memory\n");
7631
7632 return conn->errorMessage.data;
7633}
#define PQExpBufferBroken(str)
Definition: pqexpbuffer.h:59

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

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

◆ PQfinish()

void PQfinish ( PGconn conn)

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

5291{
5292 if (conn)
5293 {
5296 }
5297}
void pqClosePGconn(PGconn *conn)
Definition: fe-connect.c:5243
static void freePGconn(PGconn *conn)
Definition: fe-connect.c:5037

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

Referenced by appendQualifiedRelation(), BaseBackup(), check_for_connection_status(), check_for_pg_role_prefix(), check_for_prepared_transactions(), check_is_install_user(), check_loadable_libraries(), check_new_cluster_logical_replication_slots(), check_new_cluster_subscription_configuration(), check_old_cluster_subscription_state(), CheckConnection(), cluster_all_databases(), cluster_one_database(), connect_database(), ConnectDatabase(), connectDatabase(), connectToServer(), create_logical_replication_slots(), create_new_objects(), disconnect_atexit(), disconnect_database(), DisconnectDatabase(), disconnectDatabase(), do_connect(), doConnect(), dumpRoleGUCPrivs(), dumpRoleMembership(), dumpTablespaces(), ecpg_finish(), executeCommand(), executeQuery(), executeQueryOrDie(), exit_nicely(), expand_dbname_patterns(), finishCon(), get_db_infos(), get_dbnames_list_to_restore(), get_subscription_count(), get_tablespace_paths(), get_template0_info(), GetConnection(), libpqsrv_connect_internal(), libpqsrv_disconnect(), LogStreamerMain(), main(), old_9_6_invalidate_hash_indexes(), PQcancelFinish(), PQping(), PQpingParams(), process_slot(), ReconnectToServer(), reindex_all_databases(), reindex_one_database(), restore_all_databases(), runInitSteps(), set_frozenxids(), set_locale_and_encoding(), sql_conn(), sql_exec(), start_postmaster(), StreamLog(), StreamLogicalLog(), test_protocol_version(), unicode_version_changed(), vacuum_all_databases(), vacuum_one_database(), and vacuumlo().

◆ pqFreeCommandQueue()

static void pqFreeCommandQueue ( PGcmdQueueEntry queue)
static

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

621{
622 while (queue != NULL)
623 {
624 PGcmdQueueEntry *cur = queue;
625
626 queue = cur->next;
627 free(cur->query);
628 free(cur);
629 }
630}
struct cursor * cur
Definition: ecpg.c:29
struct cursor * next
Definition: type.h:148

References cur, free, and cursor::next.

Referenced by pqDropConnection().

◆ PQfullProtocolVersion()

int PQfullProtocolVersion ( const PGconn conn)

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

7600{
7601 if (!conn)
7602 return 0;
7603 if (conn->status == CONNECTION_BAD)
7604 return 0;
7606}
#define PG_PROTOCOL_FULL(v)
Definition: pqcomm.h:89

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

Referenced by test_protocol_version().

◆ pqGetHomeDirectory()

bool pqGetHomeDirectory ( char *  buf,
int  bufsize 
)

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

8137{
8138#ifndef WIN32
8139 const char *home;
8140
8141 home = getenv("HOME");
8142 if (home && home[0])
8143 {
8144 strlcpy(buf, home, bufsize);
8145 return true;
8146 }
8147 else
8148 {
8149 struct passwd pwbuf;
8150 struct passwd *pw;
8151 char tmpbuf[1024];
8152 int rc;
8153
8154 rc = getpwuid_r(geteuid(), &pwbuf, tmpbuf, sizeof tmpbuf, &pw);
8155 if (rc != 0 || !pw)
8156 return false;
8157 strlcpy(buf, pw->pw_dir, bufsize);
8158 return true;
8159 }
8160#else
8161 char tmppath[MAX_PATH];
8162
8163 ZeroMemory(tmppath, sizeof(tmppath));
8164 if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, tmppath) != S_OK)
8165 return false;
8166 snprintf(buf, bufsize, "%s/postgresql", tmppath);
8167 return true;
8168#endif
8169}
#define bufsize
Definition: indent_globs.h:36
static StringInfoData tmpbuf
Definition: walsender.c:175

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

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

◆ PQhost()

char * PQhost ( const PGconn conn)

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

7489{
7490 if (!conn)
7491 return NULL;
7492
7493 if (conn->connhost != NULL)
7494 {
7495 /*
7496 * Return the verbatim host value provided by user, or hostaddr in its
7497 * lack.
7498 */
7499 if (conn->connhost[conn->whichhost].host != NULL &&
7500 conn->connhost[conn->whichhost].host[0] != '\0')
7501 return conn->connhost[conn->whichhost].host;
7502 else if (conn->connhost[conn->whichhost].hostaddr != NULL &&
7503 conn->connhost[conn->whichhost].hostaddr[0] != '\0')
7505 }
7506
7507 return "";
7508}

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

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

◆ PQhostaddr()

char * PQhostaddr ( const PGconn conn)

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

7512{
7513 if (!conn)
7514 return NULL;
7515
7516 /* Return the parsed IP address */
7517 if (conn->connhost != NULL && conn->connip != NULL)
7518 return conn->connip;
7519
7520 return "";
7521}

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

Referenced by do_connect(), and exec_command_conninfo().

◆ pqMakeEmptyPGconn()

PGconn * pqMakeEmptyPGconn ( void  )

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

4938{
4939 PGconn *conn;
4940
4941#ifdef WIN32
4942
4943 /*
4944 * Make sure socket support is up and running in this process.
4945 *
4946 * Note: the Windows documentation says that we should eventually do a
4947 * matching WSACleanup() call, but experience suggests that that is at
4948 * least as likely to cause problems as fix them. So we don't.
4949 */
4950 static bool wsastartup_done = false;
4951
4952 if (!wsastartup_done)
4953 {
4954 WSADATA wsaData;
4955
4956 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
4957 return NULL;
4958 wsastartup_done = true;
4959 }
4960
4961 /* Forget any earlier error */
4962 WSASetLastError(0);
4963#endif /* WIN32 */
4964
4965 conn = (PGconn *) malloc(sizeof(PGconn));
4966 if (conn == NULL)
4967 return conn;
4968
4969 /* Zero all pointers and booleans */
4970 MemSet(conn, 0, sizeof(PGconn));
4971
4972 /* install default notice hooks */
4975
4980 conn->options_valid = false;
4981 conn->nonblocking = false;
4983 conn->std_strings = false; /* unless server says differently */
4991 conn->Pfdebug = NULL;
4992
4993 /*
4994 * We try to send at least 8K at a time, which is the usual size of pipe
4995 * buffers on Unix systems. That way, when we are sending a large amount
4996 * of data, we avoid incurring extra kernel context swaps for partial
4997 * bufferloads. The output buffer is initially made 16K in size, and we
4998 * try to dump it after accumulating 8K.
4999 *
5000 * With the same goal of minimizing context swaps, the input buffer will
5001 * be enlarged anytime it has less than 8K free, so we initially allocate
5002 * twice that.
5003 */
5004 conn->inBufSize = 16 * 1024;
5005 conn->inBuffer = (char *) malloc(conn->inBufSize);
5006 conn->outBufSize = 16 * 1024;
5007 conn->outBuffer = (char *) malloc(conn->outBufSize);
5008 conn->rowBufLen = 32;
5012
5013 if (conn->inBuffer == NULL ||
5014 conn->outBuffer == NULL ||
5015 conn->rowBuf == NULL ||
5018 {
5019 /* out of memory already :-( */
5021 conn = NULL;
5022 }
5023
5024 return conn;
5025}
static void defaultNoticeReceiver(void *arg, const PGresult *res)
Definition: fe-connect.c:7823
static void defaultNoticeProcessor(void *arg, const char *message)
Definition: fe-connect.c:7838
@ PQSHOW_CONTEXT_ERRORS
Definition: libpq-fe.h:165
@ PQERRORS_DEFAULT
Definition: libpq-fe.h:157
PQnoticeReceiver noticeRec
Definition: libpq-int.h:149
int inBufSize
Definition: libpq-int.h:565
PGVerbosity verbosity
Definition: libpq-int.h:557
int rowBufLen
Definition: libpq-int.h:582
int outBufSize
Definition: libpq-int.h:572
PGNoticeHooks noticeHooks
Definition: libpq-int.h:451
PGContextVisibility show_context
Definition: libpq-int.h:558

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

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

◆ PQoptions()

char * PQoptions ( const PGconn conn)

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

7549{
7550 if (!conn)
7551 return NULL;
7552 return conn->pgoptions;
7553}

References conn, and pg_conn::pgoptions.

Referenced by exec_command_conninfo().

◆ pqPacketSend()

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

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

5400{
5401 /* Start the message. */
5402 if (pqPutMsgStart(pack_type, conn))
5403 return STATUS_ERROR;
5404
5405 /* Send the message body. */
5406 if (pqPutnchar(buf, buf_len, conn))
5407 return STATUS_ERROR;
5408
5409 /* Finish the message. */
5410 if (pqPutMsgEnd(conn))
5411 return STATUS_ERROR;
5412
5413 /* Flush to ensure backend gets it. */
5414 if (pqFlush(conn))
5415 return STATUS_ERROR;
5416
5417 return STATUS_OK;
5418}
#define STATUS_ERROR
Definition: c.h:1141
int pqPutMsgStart(char msg_type, PGconn *conn)
Definition: fe-misc.c:473
int pqPutnchar(const char *s, size_t len, PGconn *conn)
Definition: fe-misc.c:202
int pqPutMsgEnd(PGconn *conn)
Definition: fe-misc.c:532

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

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

◆ PQparameterStatus()

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

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

7575{
7576 const pgParameterStatus *pstatus;
7577
7578 if (!conn || !paramName)
7579 return NULL;
7580 for (pstatus = conn->pstatus; pstatus != NULL; pstatus = pstatus->next)
7581 {
7582 if (strcmp(pstatus->name, paramName) == 0)
7583 return pstatus->value;
7584 }
7585 return NULL;
7586}

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

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

◆ pqParseIntParam()

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

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

8179{
8180 char *end;
8181 long numval;
8182
8183 Assert(value != NULL);
8184
8185 *result = 0;
8186
8187 /* strtol(3) skips leading whitespaces */
8188 errno = 0;
8189 numval = strtol(value, &end, 10);
8190
8191 /*
8192 * If no progress was done during the parsing or an error happened, fail.
8193 * This tests properly for overflows of the result.
8194 */
8195 if (value == end || errno != 0 || numval != (int) numval)
8196 goto error;
8197
8198 /*
8199 * Skip any trailing whitespace; if anything but whitespace remains before
8200 * the terminating character, fail
8201 */
8202 while (*end != '\0' && isspace((unsigned char) *end))
8203 end++;
8204
8205 if (*end != '\0')
8206 goto error;
8207
8208 *result = numval;
8209 return true;
8210
8211error:
8212 libpq_append_conn_error(conn, "invalid integer value \"%s\" for connection option \"%s\"",
8213 value, context);
8214 return false;
8215}
static void error(void)
Definition: sql-dyntest.c:147

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

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

◆ pqParseProtocolVersion()

static bool pqParseProtocolVersion ( const char *  value,
ProtocolVersion result,
PGconn conn,
const char *  context 
)
static

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

8224{
8225 if (strcmp(value, "latest") == 0)
8226 {
8227 *result = PG_PROTOCOL_LATEST;
8228 return true;
8229 }
8230 if (strcmp(value, "3.0") == 0)
8231 {
8232 *result = PG_PROTOCOL(3, 0);
8233 return true;
8234 }
8235
8236 /* 3.1 never existed, we went straight from 3.0 to 3.2 */
8237
8238 if (strcmp(value, "3.2") == 0)
8239 {
8240 *result = PG_PROTOCOL(3, 2);
8241 return true;
8242 }
8243
8244 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
8245 context, value);
8246 return false;
8247}

References conn, libpq_append_conn_error(), PG_PROTOCOL, PG_PROTOCOL_LATEST, and value.

Referenced by pqConnectOptions2().

◆ PQpass()

char * PQpass ( const PGconn conn)

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

7472{
7473 char *password = NULL;
7474
7475 if (!conn)
7476 return NULL;
7477 if (conn->connhost != NULL)
7479 if (password == NULL)
7480 password = conn->pgpass;
7481 /* Historically we've returned "" not NULL for no password specified */
7482 if (password == NULL)
7483 password = "";
7484 return password;
7485}

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

Referenced by ConnectDatabaseAhx(), and PQconnectionNeedsPassword().

◆ PQping()

PGPing PQping ( const char *  conninfo)

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

830{
831 PGconn *conn = PQconnectStart(conninfo);
832 PGPing ret;
833
834 ret = internal_ping(conn);
835 PQfinish(conn);
836
837 return ret;
838}
static PGPing internal_ping(PGconn *conn)
Definition: fe-connect.c:4873
void PQfinish(PGconn *conn)
Definition: fe-connect.c:5290
PGPing
Definition: libpq-fe.h:175

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

◆ PQpingParams()

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

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

779{
780 PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname);
781 PGPing ret;
782
783 ret = internal_ping(conn);
784 PQfinish(conn);
785
786 return ret;
787}

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

Referenced by main(), and regression_main().

◆ PQpipelineStatus()

◆ PQport()

char * PQport ( const PGconn conn)

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

7525{
7526 if (!conn)
7527 return NULL;
7528
7529 if (conn->connhost != NULL)
7530 return conn->connhost[conn->whichhost].port;
7531
7532 return "";
7533}

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

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

◆ PQprotocolVersion()

int PQprotocolVersion ( const PGconn conn)

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

7590{
7591 if (!conn)
7592 return 0;
7593 if (conn->status == CONNECTION_BAD)
7594 return 0;
7596}
#define PG_PROTOCOL_MAJOR(v)
Definition: pqcomm.h:87

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

Referenced by exec_command_conninfo(), and handleCopyIn().

◆ PQregisterThreadLock()

pgthreadlock_t PQregisterThreadLock ( pgthreadlock_t  newhandler)

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

8278{
8280
8281 if (newhandler)
8282 pg_g_threadlock = newhandler;
8283 else
8285
8286 return prev;
8287}
static void default_threadlock(int acquire)
Definition: fe-connect.c:8260
pgthreadlock_t pg_g_threadlock
Definition: fe-connect.c:504
void(* pgthreadlock_t)(int acquire)
Definition: libpq-fe.h:472

References default_threadlock(), and pg_g_threadlock.

◆ pqReleaseConnHosts()

void pqReleaseConnHosts ( PGconn conn)

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

5128{
5129 if (conn->connhost)
5130 {
5131 for (int i = 0; i < conn->nconnhost; ++i)
5132 {
5133 free(conn->connhost[i].host);
5135 free(conn->connhost[i].port);
5136 if (conn->connhost[i].password != NULL)
5137 {
5139 strlen(conn->connhost[i].password));
5141 }
5142 }
5143 free(conn->connhost);
5144 }
5145}

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

Referenced by freePGconn(), and PQcancelCreate().

◆ PQreset()

void PQreset ( PGconn conn)

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

5305{
5306 if (conn)
5307 {
5309
5311 {
5312 /*
5313 * Notify event procs of successful reset.
5314 */
5315 int i;
5316
5317 for (i = 0; i < conn->nEvents; i++)
5318 {
5319 PGEventConnReset evt;
5320
5321 evt.conn = conn;
5322 (void) conn->events[i].proc(PGEVT_CONNRESET, &evt,
5324 }
5325 }
5326 }
5327}
@ PGEVT_CONNRESET
Definition: libpq-events.h:30

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

Referenced by CheckConnection().

◆ PQresetPoll()

PostgresPollingStatusType PQresetPoll ( PGconn conn)

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

5357{
5358 if (conn)
5359 {
5361
5362 if (status == PGRES_POLLING_OK)
5363 {
5364 /*
5365 * Notify event procs of successful reset.
5366 */
5367 int i;
5368
5369 for (i = 0; i < conn->nEvents; i++)
5370 {
5371 PGEventConnReset evt;
5372
5373 evt.conn = conn;
5374 (void) conn->events[i].proc(PGEVT_CONNRESET, &evt,
5376 }
5377 }
5378
5379 return status;
5380 }
5381
5382 return PGRES_POLLING_FAILED;
5383}

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

◆ PQresetStart()

int PQresetStart ( PGconn conn)

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

5338{
5339 if (conn)
5340 {
5342
5343 return pqConnectDBStart(conn);
5344 }
5345
5346 return 0;
5347}

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

◆ PQserverVersion()

◆ PQservice()

char * PQservice ( const PGconn conn)

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

7456{
7457 if (!conn)
7458 return NULL;
7459 return conn->pgservice;
7460}
char * pgservice
Definition: libpq-int.h:391

References conn, and pg_conn::pgservice.

Referenced by get_prompt(), and SyncVariables().

◆ PQsetClientEncoding()

int PQsetClientEncoding ( PGconn conn,
const char *  encoding 
)

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

7718{
7719 char qbuf[128];
7720 static const char query[] = "set client_encoding to '%s'";
7721 PGresult *res;
7722 int status;
7723
7724 if (!conn || conn->status != CONNECTION_OK)
7725 return -1;
7726
7727 if (!encoding)
7728 return -1;
7729
7730 /* Resolve special "auto" value from the locale */
7731 if (strcmp(encoding, "auto") == 0)
7733
7734 /* check query buffer overflow */
7735 if (sizeof(qbuf) < (sizeof(query) + strlen(encoding)))
7736 return -1;
7737
7738 /* ok, now send a query */
7739 sprintf(qbuf, query, encoding);
7740 res = PQexec(conn, qbuf);
7741
7742 if (res == NULL)
7743 return -1;
7744 if (res->resultStatus != PGRES_COMMAND_OK)
7745 status = -1;
7746 else
7747 {
7748 /*
7749 * We rely on the backend to report the parameter value, and we'll
7750 * change state at that time.
7751 */
7752 status = 0; /* everything is ok */
7753 }
7754 PQclear(res);
7755 return status;
7756}
PGresult * PQexec(PGconn *conn, const char *query)
Definition: fe-exec.c:2262
@ PGRES_COMMAND_OK
Definition: libpq-fe.h:125
int32 encoding
Definition: pg_database.h:41
#define sprintf
Definition: port.h:241
ExecStatusType resultStatus
Definition: libpq-int.h:174

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

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

◆ PQsetdbLogin()

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

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

2231{
2232 PGconn *conn;
2233
2234 /*
2235 * Allocate memory for the conn structure. Note that we also expect this
2236 * to initialize conn->errorMessage to empty. All subsequent steps during
2237 * connection initialization will only append to that buffer.
2238 */
2240 if (conn == NULL)
2241 return NULL;
2242
2243 /*
2244 * If the dbName parameter contains what looks like a connection string,
2245 * parse it into conn struct using connectOptions1.
2246 */
2248 {
2250 return conn;
2251 }
2252 else
2253 {
2254 /*
2255 * Old-style path: first, parse an empty conninfo string in order to
2256 * set up the same defaults that PQconnectdb() would use.
2257 */
2258 if (!connectOptions1(conn, ""))
2259 return conn;
2260
2261 /* Insert dbName parameter value into struct */
2262 if (dbName && dbName[0] != '\0')
2263 {
2264 free(conn->dbName);
2265 conn->dbName = strdup(dbName);
2266 if (!conn->dbName)
2267 goto oom_error;
2268 }
2269 }
2270
2271 /*
2272 * Insert remaining parameters into struct, overriding defaults (as well
2273 * as any conflicting data from dbName taken as a conninfo).
2274 */
2275 if (pghost && pghost[0] != '\0')
2276 {
2277 free(conn->pghost);
2278 conn->pghost = strdup(pghost);
2279 if (!conn->pghost)
2280 goto oom_error;
2281 }
2282
2283 if (pgport && pgport[0] != '\0')
2284 {
2285 free(conn->pgport);
2286 conn->pgport = strdup(pgport);
2287 if (!conn->pgport)
2288 goto oom_error;
2289 }
2290
2291 if (pgoptions && pgoptions[0] != '\0')
2292 {
2294 conn->pgoptions = strdup(pgoptions);
2295 if (!conn->pgoptions)
2296 goto oom_error;
2297 }
2298
2299 if (login && login[0] != '\0')
2300 {
2301 free(conn->pguser);
2302 conn->pguser = strdup(login);
2303 if (!conn->pguser)
2304 goto oom_error;
2305 }
2306
2307 if (pwd && pwd[0] != '\0')
2308 {
2309 free(conn->pgpass);
2310 conn->pgpass = strdup(pwd);
2311 if (!conn->pgpass)
2312 goto oom_error;
2313 }
2314
2315 /*
2316 * Compute derived options
2317 */
2318 if (!pqConnectOptions2(conn))
2319 return conn;
2320
2321 /*
2322 * Connect to the database
2323 */
2325 (void) pqConnectDBComplete(conn);
2326
2327 return conn;
2328
2329oom_error:
2331 libpq_append_conn_error(conn, "out of memory");
2332 return conn;
2333}
static const char * pghost
Definition: pgbench.c:295
static const char * pgport
Definition: pgbench.c:296
static const char * dbName
Definition: pgbench.c:298

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

◆ PQsetErrorContextVisibility()

PGContextVisibility PQsetErrorContextVisibility ( PGconn conn,
PGContextVisibility  show_context 
)

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

7772{
7774
7775 if (!conn)
7776 return PQSHOW_CONTEXT_ERRORS;
7777 old = conn->show_context;
7778 conn->show_context = show_context;
7779 return old;
7780}
PGContextVisibility
Definition: libpq-fe.h:163

References conn, PQSHOW_CONTEXT_ERRORS, and pg_conn::show_context.

Referenced by show_context_hook(), and SyncVariables().

◆ PQsetErrorVerbosity()

PGVerbosity PQsetErrorVerbosity ( PGconn conn,
PGVerbosity  verbosity 
)

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

7760{
7761 PGVerbosity old;
7762
7763 if (!conn)
7764 return PQERRORS_DEFAULT;
7765 old = conn->verbosity;
7766 conn->verbosity = verbosity;
7767 return old;
7768}
PGVerbosity
Definition: libpq-fe.h:155

References conn, PQERRORS_DEFAULT, and pg_conn::verbosity.

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

◆ PQsetNoticeProcessor()

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

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

7801{
7803
7804 if (conn == NULL)
7805 return NULL;
7806
7808 if (proc)
7809 {
7810 conn->noticeHooks.noticeProc = proc;
7812 }
7813 return old;
7814}
void(* PQnoticeProcessor)(void *arg, const char *message)
Definition: libpq-fe.h:245

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

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

◆ PQsetNoticeReceiver()

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

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

7784{
7785 PQnoticeReceiver old;
7786
7787 if (conn == NULL)
7788 return NULL;
7789
7790 old = conn->noticeHooks.noticeRec;
7791 if (proc)
7792 {
7793 conn->noticeHooks.noticeRec = proc;
7795 }
7796 return old;
7797}
void(* PQnoticeReceiver)(void *arg, const PGresult *res)
Definition: libpq-fe.h:244
void * noticeRecArg
Definition: libpq-int.h:150

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

Referenced by ECPGconnect().

◆ PQsocket()

◆ PQstatus()

◆ PQtransactionStatus()

◆ PQtty()

char * PQtty ( const PGconn conn)

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

7541{
7542 if (!conn)
7543 return NULL;
7544 return "";
7545}

References conn.

◆ PQuser()

char * PQuser ( const PGconn conn)

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

7464{
7465 if (!conn)
7466 return NULL;
7467 return conn->pguser;
7468}

References conn, and pg_conn::pguser.

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

◆ pwdfMatchesString()

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

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

7851{
7852 char *tbuf;
7853 const char *ttok;
7854 bool bslash = false;
7855
7856 if (buf == NULL || token == NULL)
7857 return NULL;
7858 tbuf = buf;
7859 ttok = token;
7860 if (tbuf[0] == '*' && tbuf[1] == ':')
7861 return tbuf + 2;
7862 while (*tbuf != 0)
7863 {
7864 if (*tbuf == '\\' && !bslash)
7865 {
7866 tbuf++;
7867 bslash = true;
7868 }
7869 if (*tbuf == ':' && *ttok == 0 && !bslash)
7870 return tbuf + 1;
7871 bslash = false;
7872 if (*ttok == 0)
7873 return NULL;
7874 if (*tbuf == *ttok)
7875 {
7876 tbuf++;
7877 ttok++;
7878 }
7879 else
7880 return NULL;
7881 }
7882 return NULL;
7883}
#define token
Definition: indent_globs.h:126

References buf, and token.

Referenced by passwordFromFile().

◆ recognized_connection_string()

static bool recognized_connection_string ( const char *  connstr)
static

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

6255{
6256 return uri_prefix_length(connstr) != 0 || strchr(connstr, '=') != NULL;
6257}

References connstr, and uri_prefix_length().

Referenced by conninfo_array_parse(), and PQsetdbLogin().

◆ release_conn_addrinfo()

static void release_conn_addrinfo ( PGconn conn)
static

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

5196{
5197 if (conn->addr)
5198 {
5199 free(conn->addr);
5200 conn->addr = NULL;
5201 }
5202}

References pg_conn::addr, conn, and free.

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

◆ select_next_encryption_method()

static bool select_next_encryption_method ( PGconn conn,
bool  have_valid_connection 
)
static

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

4799{
4800 int remaining_methods;
4801
4802#define SELECT_NEXT_METHOD(method) \
4803 do { \
4804 if ((remaining_methods & method) != 0) \
4805 { \
4806 conn->current_enc_method = method; \
4807 return true; \
4808 } \
4809 } while (false)
4810
4811 remaining_methods = conn->allowed_enc_methods & ~conn->failed_enc_methods;
4812
4813 /*
4814 * Try GSSAPI before SSL
4815 */
4816#ifdef ENABLE_GSS
4817 if ((remaining_methods & ENC_GSSAPI) != 0)
4818 {
4819 /*
4820 * If GSSAPI encryption is enabled, then call pg_GSS_have_cred_cache()
4821 * which will return true if we can acquire credentials (and give us a
4822 * handle to use in conn->gcred), and then send a packet to the server
4823 * asking for GSSAPI Encryption (and skip past SSL negotiation and
4824 * regular startup below).
4825 */
4826 if (!conn->gctx)
4827 {
4828 if (!pg_GSS_have_cred_cache(&conn->gcred))
4829 {
4830 conn->allowed_enc_methods &= ~ENC_GSSAPI;
4831 remaining_methods &= ~ENC_GSSAPI;
4832
4833 if (conn->gssencmode[0] == 'r')
4834 {
4836 "GSSAPI encryption required but no credential cache");
4837 }
4838 }
4839 }
4840 }
4841
4843#endif
4844
4845 /*
4846 * The order between SSL encryption and plaintext depends on sslmode. With
4847 * sslmode=allow, try plaintext connection before SSL. With
4848 * sslmode=prefer, it's the other way round. With other modes, we only try
4849 * plaintext or SSL connections so the order they're listed here doesn't
4850 * matter.
4851 */
4852 if (conn->sslmode[0] == 'a')
4854
4856
4857 if (conn->sslmode[0] != 'a')
4859
4860 /* No more options */
4862 return false;
4863#undef SELECT_NEXT_METHOD
4864}
#define SELECT_NEXT_METHOD(method)

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

Referenced by connection_failed(), and init_allowed_encryption_methods().

◆ sendTerminateConn()

static void sendTerminateConn ( PGconn conn)
static

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

5210{
5211 /*
5212 * The Postgres cancellation protocol does not have a notion of a
5213 * Terminate message, so don't send one.
5214 */
5215 if (conn->cancelRequest)
5216 return;
5217
5218 /*
5219 * Note that the protocol doesn't allow us to send Terminate messages
5220 * during the startup phase.
5221 */
5223 {
5224 /*
5225 * Try to send "close connection" message to backend. Ignore any
5226 * error.
5227 */
5230 (void) pqFlush(conn);
5231 }
5232}
#define PqMsg_Terminate
Definition: protocol.h:28

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

Referenced by pqClosePGconn(), and PQconnectPoll().

◆ setKeepalivesCount()

static int setKeepalivesCount ( PGconn conn)
static

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

2566{
2567 int count;
2568
2569 if (conn->keepalives_count == NULL)
2570 return 1;
2571
2573 "keepalives_count"))
2574 return 0;
2575 if (count < 0)
2576 count = 0;
2577
2578#ifdef TCP_KEEPCNT
2579 if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPCNT,
2580 (char *) &count, sizeof(count)) < 0)
2581 {
2582 char sebuf[PG_STRERROR_R_BUFLEN];
2583
2584 libpq_append_conn_error(conn, "%s(%s) failed: %s",
2585 "setsockopt",
2586 "TCP_KEEPCNT",
2587 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2588 return 0;
2589 }
2590#endif
2591
2592 return 1;
2593}

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

Referenced by PQconnectPoll().

◆ setKeepalivesIdle()

static int setKeepalivesIdle ( PGconn conn)
static

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

2497{
2498 int idle;
2499
2500 if (conn->keepalives_idle == NULL)
2501 return 1;
2502
2504 "keepalives_idle"))
2505 return 0;
2506 if (idle < 0)
2507 idle = 0;
2508
2509#ifdef PG_TCP_KEEPALIVE_IDLE
2510 if (setsockopt(conn->sock, IPPROTO_TCP, PG_TCP_KEEPALIVE_IDLE,
2511 (char *) &idle, sizeof(idle)) < 0)
2512 {
2513 char sebuf[PG_STRERROR_R_BUFLEN];
2514
2515 libpq_append_conn_error(conn, "%s(%s) failed: %s",
2516 "setsockopt",
2517 PG_TCP_KEEPALIVE_IDLE_STR,
2518 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2519 return 0;
2520 }
2521#endif
2522
2523 return 1;
2524}

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

Referenced by PQconnectPoll().

◆ setKeepalivesInterval()

static int setKeepalivesInterval ( PGconn conn)
static

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

2531{
2532 int interval;
2533
2534 if (conn->keepalives_interval == NULL)
2535 return 1;
2536
2538 "keepalives_interval"))
2539 return 0;
2540 if (interval < 0)
2541 interval = 0;
2542
2543#ifdef TCP_KEEPINTVL
2544 if (setsockopt(conn->sock, IPPROTO_TCP, TCP_KEEPINTVL,
2545 (char *) &interval, sizeof(interval)) < 0)
2546 {
2547 char sebuf[PG_STRERROR_R_BUFLEN];
2548
2549 libpq_append_conn_error(conn, "%s(%s) failed: %s",
2550 "setsockopt",
2551 "TCP_KEEPINTVL",
2552 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2553 return 0;
2554 }
2555#endif
2556
2557 return 1;
2558}

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

Referenced by PQconnectPoll().

◆ setTCPUserTimeout()

static int setTCPUserTimeout ( PGconn conn)
static

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

2663{
2664 int timeout;
2665
2666 if (conn->pgtcp_user_timeout == NULL)
2667 return 1;
2668
2670 "tcp_user_timeout"))
2671 return 0;
2672
2673 if (timeout < 0)
2674 timeout = 0;
2675
2676#ifdef TCP_USER_TIMEOUT
2677 if (setsockopt(conn->sock, IPPROTO_TCP, TCP_USER_TIMEOUT,
2678 (char *) &timeout, sizeof(timeout)) < 0)
2679 {
2680 char sebuf[256];
2681
2682 libpq_append_conn_error(conn, "%s(%s) failed: %s",
2683 "setsockopt",
2684 "TCP_USER_TIMEOUT",
2685 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2686 return 0;
2687 }
2688#endif
2689
2690 return 1;
2691}

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

Referenced by PQconnectPoll().

◆ sslVerifyProtocolRange()

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

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

8084{
8087
8088 /* If at least one of the bounds is not set, the range is valid */
8089 if (min == NULL || max == NULL || strlen(min) == 0 || strlen(max) == 0)
8090 return true;
8091
8092 /*
8093 * If the minimum version is the lowest one we accept, then all options
8094 * for the maximum are valid.
8095 */
8096 if (pg_strcasecmp(min, "TLSv1") == 0)
8097 return true;
8098
8099 /*
8100 * The minimum bound is valid, and cannot be TLSv1, so using TLSv1 for the
8101 * maximum is incorrect.
8102 */
8103 if (pg_strcasecmp(max, "TLSv1") == 0)
8104 return false;
8105
8106 /*
8107 * At this point we know that we have a mix of TLSv1.1 through 1.3
8108 * versions.
8109 */
8110 if (pg_strcasecmp(min, max) > 0)
8111 return false;
8112
8113 return true;
8114}
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36

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

Referenced by pqConnectOptions2().

◆ sslVerifyProtocolVersion()

static bool sslVerifyProtocolVersion ( const char *  version)
static

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

8058{
8059 /*
8060 * An empty string and a NULL value are considered valid as it is
8061 * equivalent to ignoring the parameter.
8062 */
8063 if (!version || strlen(version) == 0)
8064 return true;
8065
8066 if (pg_strcasecmp(version, "TLSv1") == 0 ||
8067 pg_strcasecmp(version, "TLSv1.1") == 0 ||
8068 pg_strcasecmp(version, "TLSv1.2") == 0 ||
8069 pg_strcasecmp(version, "TLSv1.3") == 0)
8070 return true;
8071
8072 /* anything else is wrong */
8073 return false;
8074}

References pg_strcasecmp().

Referenced by pqConnectOptions2(), and sslVerifyProtocolRange().

◆ store_conn_addrinfo()

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

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

5157{
5158 struct addrinfo *ai = addrlist;
5159
5160 conn->whichaddr = 0;
5161
5162 conn->naddr = 0;
5163 while (ai)
5164 {
5165 ai = ai->ai_next;
5166 conn->naddr++;
5167 }
5168
5169 conn->addr = calloc(conn->naddr, sizeof(AddrInfo));
5170 if (conn->addr == NULL)
5171 {
5172 libpq_append_conn_error(conn, "out of memory");
5173 return 1;
5174 }
5175
5176 ai = addrlist;
5177 for (int i = 0; i < conn->naddr; i++)
5178 {
5179 conn->addr[i].family = ai->ai_family;
5180
5181 memcpy(&conn->addr[i].addr.addr, ai->ai_addr,
5182 ai->ai_addrlen);
5183 conn->addr[i].addr.salen = ai->ai_addrlen;
5184 ai = ai->ai_next;
5185 }
5186
5187 return 0;
5188}

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

Referenced by PQconnectPoll().

◆ uri_prefix_length()

static int uri_prefix_length ( const char *  connstr)
static

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

6232{
6233 if (strncmp(connstr, uri_designator,
6234 sizeof(uri_designator) - 1) == 0)
6235 return sizeof(uri_designator) - 1;
6236
6237 if (strncmp(connstr, short_uri_designator,
6238 sizeof(short_uri_designator) - 1) == 0)
6239 return sizeof(short_uri_designator) - 1;
6240
6241 return 0;
6242}
static const char short_uri_designator[]
Definition: fe-connect.c:440
static const char uri_designator[]
Definition: fe-connect.c:439

References connstr, short_uri_designator, and uri_designator.

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

◆ useKeepalives()

static int useKeepalives ( PGconn conn)
static

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

2479{
2480 int val;
2481
2482 if (conn->keepalives == NULL)
2483 return 1;
2484
2485 if (!pqParseIntParam(conn->keepalives, &val, conn, "keepalives"))
2486 return -1;
2487
2488 return val != 0 ? 1 : 0;
2489}

References conn, pg_conn::keepalives, pqParseIntParam(), and val.

Referenced by PQconnectPoll().

Variable Documentation

◆ EnvironmentOptions

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

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

Referenced by PQconnectPoll().

◆ pg_g_threadlock

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

Referenced by PQregisterThreadLock().

◆ PQconninfoOptions

const internalPQconninfoOption PQconninfoOptions[]
static

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

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

◆ short_uri_designator

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

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

Referenced by uri_prefix_length().

◆ supported_sasl_mechs

const pg_fe_sasl_mech* supported_sasl_mechs[]
static
Initial value:

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

Referenced by fill_allowed_sasl_mechs().

◆ uri_designator

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

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

Referenced by uri_prefix_length().