Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
PostgreSQL Source Code git master
fe-connect.c File Reference
#include "postgres_fe.h"
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>
#include <netdb.h>
#include <time.h>
#include <unistd.h>
#include "common/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:4785
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 442 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 1215 of file fe-connect.c.

1216{
1217 for (int i = 0; i < lengthof(conn->allowed_sasl_mechs); i++)
1218 conn->allowed_sasl_mechs[i] = NULL;
1219}
#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 2460 of file fe-connect.c.

2461{
2462 char sebuf[PG_STRERROR_R_BUFLEN];
2463
2465 "%s\n",
2466 SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
2467
2468 if (conn->raddr.addr.ss_family == AF_UNIX)
2469 libpq_append_conn_error(conn, "\tIs the server running locally and accepting connections on that socket?");
2470 else
2471 libpq_append_conn_error(conn, "\tIs the server running on that host and accepting TCP/IP connections?");
2472}
#define SOCK_STRERROR
Definition: libpq-int.h:960
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition: oauth-utils.c:95
#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 4785 of file fe-connect.c.

4786{
4789
4790 return select_next_encryption_method(conn, false);
4791}
static bool select_next_encryption_method(PGconn *conn, bool have_valid_connection)
Definition: fe-connect.c:4800
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 2345 of file fe-connect.c.

2346{
2347#ifdef TCP_NODELAY
2348 int on = 1;
2349
2350 if (setsockopt(conn->sock, IPPROTO_TCP, TCP_NODELAY,
2351 (char *) &on,
2352 sizeof(on)) < 0)
2353 {
2354 char sebuf[PG_STRERROR_R_BUFLEN];
2355
2356 libpq_append_conn_error(conn, "could not set socket to TCP no delay mode: %s",
2357 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2358 return 0;
2359 }
2360#endif
2361
2362 return 1;
2363}
#define SOCK_ERRNO
Definition: oauth-utils.c:164
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 1072 of file fe-connect.c.

1073{
1074 PQconninfoOption *connOptions;
1075
1076 /*
1077 * Parse the conninfo string
1078 */
1079 connOptions = parse_connection_string(conninfo, &conn->errorMessage, true);
1080 if (connOptions == NULL)
1081 {
1083 /* errorMessage is already set */
1084 return false;
1085 }
1086
1087 /*
1088 * Move option values into conn structure
1089 */
1090 if (!fillPGconn(conn, connOptions))
1091 {
1093 PQconninfoFree(connOptions);
1094 return false;
1095 }
1096
1097 /*
1098 * Free the option info - all is in conn now
1099 */
1100 PQconninfoFree(connOptions);
1101
1102 return true;
1103}
static PQconninfoOption * parse_connection_string(const char *connstr, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:6221
void PQconninfoFree(PQconninfoOption *connOptions)
Definition: fe-connect.c:7444
static bool fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
Definition: fe-connect.c:993
@ 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 6609 of file fe-connect.c.

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

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

7383{
7385
7386 for (option = connOptions; option->keyword != NULL; option++)
7387 {
7388 if (strcmp(option->keyword, keyword) == 0)
7389 return option;
7390 }
7391
7392 return NULL;
7393}

Referenced by conninfo_getval(), and conninfo_storeval().

◆ conninfo_getval()

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

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

7294{
7296
7297 option = conninfo_find(connOptions, keyword);
7298
7299 return option ? option->val : NULL;
7300}
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)
Definition: fe-connect.c:7382

References conninfo_find(), and option::val.

Referenced by fillPGconn(), and parseServiceInfo().

◆ conninfo_init()

static PQconninfoOption * conninfo_init ( PQExpBuffer  errorMessage)
static

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

6183{
6185 PQconninfoOption *opt_dest;
6186 const internalPQconninfoOption *cur_opt;
6187
6188 /*
6189 * Get enough memory for all options in PQconninfoOptions, even if some
6190 * end up being filtered out.
6191 */
6193 if (options == NULL)
6194 {
6195 libpq_append_error(errorMessage, "out of memory");
6196 return NULL;
6197 }
6198 opt_dest = options;
6199
6200 for (cur_opt = PQconninfoOptions; cur_opt->keyword; cur_opt++)
6201 {
6202 /* Only copy the public part of the struct, not the full internal */
6203 memcpy(opt_dest, cur_opt, sizeof(PQconninfoOption));
6204 opt_dest++;
6205 }
6206 MemSet(opt_dest, 0, sizeof(PQconninfoOption));
6207
6208 return options;
6209}
#define MemSet(start, val, len)
Definition: c.h:991
static const internalPQconninfoOption PQconninfoOptions[]
Definition: fe-connect.c:199
#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 6275 of file fe-connect.c.

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

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

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

6746{
6748
6749 /* Make a working copy of PQconninfoOptions */
6750 options = conninfo_init(errorMessage);
6751 if (options == NULL)
6752 return NULL;
6753
6754 if (!conninfo_uri_parse_options(options, uri, errorMessage))
6755 {
6757 return NULL;
6758 }
6759
6760 /*
6761 * Add in defaults if the caller wants that.
6762 */
6763 if (use_defaults)
6764 {
6765 if (!conninfo_add_defaults(options, errorMessage))
6766 {
6768 return NULL;
6769 }
6770 }
6771
6772 return options;
6773}
static bool conninfo_uri_parse_options(PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage)
Definition: fe-connect.c:6797

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

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

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

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

1110{
1111 int n;
1112
1113 n = 1;
1114 for (; *input != '\0'; input++)
1115 {
1116 if (*input == ',')
1117 n++;
1118 }
1119
1120 return n;
1121}
FILE * input

References input.

Referenced by pqConnectOptions2().

◆ default_threadlock()

static void default_threadlock ( int  acquire)
static

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

8271{
8272 static pthread_mutex_t singlethread_lock = PTHREAD_MUTEX_INITIALIZER;
8273
8274 if (acquire)
8275 {
8276 if (pthread_mutex_lock(&singlethread_lock))
8277 Assert(false);
8278 }
8279 else
8280 {
8281 if (pthread_mutex_unlock(&singlethread_lock))
8282 Assert(false);
8283 }
8284}
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 7848 of file fe-connect.c.

7849{
7850 (void) arg; /* not used */
7851 /* Note: we expect the supplied string to end with a newline already. */
7852 fprintf(stderr, "%s", message);
7853}
#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 7833 of file fe-connect.c.

7834{
7835 (void) arg; /* not used */
7836 if (res->noticeHooks.noticeProc != NULL)
7839}
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 2404 of file fe-connect.c.

2405{
2406 if (conn->raddr.addr.ss_family == AF_UNIX)
2407 {
2408 char service[NI_MAXHOST];
2409
2411 NULL, 0,
2412 service, sizeof(service),
2413 NI_NUMERICSERV);
2415 libpq_gettext("connection to server on socket \"%s\" failed: "),
2416 service);
2417 }
2418 else
2419 {
2420 const char *displayed_host;
2421 const char *displayed_port;
2422
2423 /* To which host and port were we actually connecting? */
2425 displayed_host = conn->connhost[conn->whichhost].hostaddr;
2426 else
2427 displayed_host = conn->connhost[conn->whichhost].host;
2428 displayed_port = conn->connhost[conn->whichhost].port;
2429 if (displayed_port == NULL || displayed_port[0] == '\0')
2430 displayed_port = DEF_PGPORT_STR;
2431
2432 /*
2433 * If the user did not supply an IP address using 'hostaddr', and
2434 * 'host' was missing or does not match our lookup, display the
2435 * looked-up IP address.
2436 */
2438 host_addr[0] &&
2439 strcmp(displayed_host, host_addr) != 0)
2441 libpq_gettext("connection to server at \"%s\" (%s), port %s failed: "),
2442 displayed_host, host_addr,
2443 displayed_port);
2444 else
2446 libpq_gettext("connection to server at \"%s\", port %s failed: "),
2447 displayed_host,
2448 displayed_port);
2449 }
2450}
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
@ CHT_HOST_ADDRESS
Definition: libpq-int.h:310
#define libpq_gettext(x)
Definition: oauth-utils.h:86
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 1191 of file fe-connect.c.

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

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

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

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

5040{
5041 /* let any event procs clean up their state data */
5042 for (int i = 0; i < conn->nEvents; i++)
5043 {
5045
5046 evt.conn = conn;
5047 (void) conn->events[i].proc(PGEVT_CONNDESTROY, &evt,
5049 free(conn->events[i].name);
5050 }
5051
5052 /* free everything not freed in pqClosePGconn */
5053 free(conn->pghost);
5055 free(conn->pgport);
5060 free(conn->appname);
5062 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);
5080 free(conn->sslkey);
5081 free(conn->sslcert);
5082 if (conn->sslpassword)
5083 {
5086 }
5089 free(conn->sslcrl);
5091 free(conn->sslsni);
5095 free(conn->gsslib);
5113 /* Note that conn->Pfdebug is not ours to close or free */
5114 free(conn->events);
5116 free(conn->connip);
5120 /* if this is a cancel connection, be_cancel_key may still be allocated */
5122 free(conn->inBuffer);
5124 free(conn->rowBuf);
5127
5128 free(conn);
5129}
static void release_conn_addrinfo(PGconn *conn)
Definition: fe-connect.c:5205
void pqReleaseConnHosts(PGconn *conn)
Definition: fe-connect.c:5136
@ 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
uint8 * be_cancel_key
Definition: libpq-int.h:551
char * replication
Definition: libpq-int.h:390
uint8 * scram_client_key_binary
Definition: libpq-int.h:542
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
uint8 * scram_server_key_binary
Definition: libpq-int.h:544
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 * max_protocol_version
Definition: libpq-int.h:421
char * load_balance_hosts
Definition: libpq-int.h:426
char * pguser
Definition: libpq-int.h:392
char * keepalives
Definition: libpq-int.h:397
char * min_protocol_version
Definition: libpq-int.h:420
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 * sslkeylogfile
Definition: libpq-int.h:429
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 * pgservice
Definition: libpq-int.h:391
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::be_cancel_key, 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, pg_conn::max_protocol_version, pg_conn::min_protocol_version, 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::pgservice, 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_client_key_binary, pg_conn::scram_server_key, pg_conn::scram_server_key_binary, 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::sslkeylogfile, pg_conn::sslmode, pg_conn::sslnegotiation, pg_conn::sslpassword, pg_conn::sslrootcert, pg_conn::sslsni, pg_conn::target_session_attrs, termPQExpBuffer(), and pg_conn::workBuffer.

Referenced by PQfinish(), and pqMakeEmptyPGconn().

◆ get_hexdigit()

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

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

7272{
7273 if ('0' <= digit && digit <= '9')
7274 *value = digit - '0';
7275 else if ('A' <= digit && digit <= 'F')
7276 *value = digit - 'A' + 10;
7277 else if ('a' <= digit && digit <= 'f')
7278 *value = digit - 'a' + 10;
7279 else
7280 return false;
7281
7282 return true;
7283}

References value.

Referenced by conninfo_uri_decode().

◆ getHostaddr()

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

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

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

1227{
1228 for (int i = 0; i < lengthof(conn->allowed_sasl_mechs); i++)
1229 {
1230 if (conn->allowed_sasl_mechs[i] == mech)
1231 return i;
1232 }
1233
1234 return -1;
1235}

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

4696{
4697 if (conn->raddr.addr.ss_family == AF_UNIX)
4698 {
4699 /* Don't request SSL or GSSAPI over Unix sockets */
4701
4702 /*
4703 * XXX: we probably should not do this. sslmode=require works
4704 * differently
4705 */
4706 if (conn->gssencmode[0] == 'r')
4707 {
4709 "GSSAPI encryption required but it is not supported over a local socket");
4712 return false;
4713 }
4714
4717 return true;
4718 }
4719
4720 /* initialize based on sslmode and gssencmode */
4722
4723#ifdef USE_SSL
4724 /* sslmode anything but 'disable', and GSSAPI not required */
4725 if (conn->sslmode[0] != 'd' && conn->gssencmode[0] != 'r')
4726 {
4728 }
4729#endif
4730
4731#ifdef ENABLE_GSS
4732 if (conn->gssencmode[0] != 'd')
4734#endif
4735
4736 if ((conn->sslmode[0] == 'd' || conn->sslmode[0] == 'p' || conn->sslmode[0] == 'a') &&
4737 (conn->gssencmode[0] == 'd' || conn->gssencmode[0] == 'p'))
4738 {
4740 }
4741
4742 return select_next_encryption_method(conn, false);
4743}
#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 4875 of file fe-connect.c.

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

1169{
1170 uint64 rseed;
1171 struct timeval tval = {0};
1172
1174 return;
1175
1176 gettimeofday(&tval, NULL);
1177
1178 rseed = ((uintptr_t) conn) ^
1179 ((uint64) getpid()) ^
1180 ((uint64) tval.tv_usec) ^
1181 ((uint64) tval.tv_sec);
1182
1183 pg_prng_seed(&conn->prng_state, rseed);
1184}
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 1133 of file fe-connect.c.

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

6223{
6224 /* Parse as URI if connection string matches URI prefix */
6225 if (uri_prefix_length(connstr) != 0)
6226 return conninfo_uri_parse(connstr, errorMessage, use_defaults);
6227
6228 /* Parse as default otherwise */
6229 return conninfo_parse(connstr, errorMessage, use_defaults);
6230}
static PQconninfoOption * conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:6744
static PQconninfoOption * conninfo_parse(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
Definition: fe-connect.c:6275
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 5982 of file fe-connect.c.

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

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

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

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

8045{
8046 /* If it was 'invalid authorization', add pgpassfile mention */
8047 /* only works with >= 9.0 servers */
8048 if (conn->password_needed &&
8049 conn->connhost[conn->whichhost].password != NULL &&
8050 conn->result)
8051 {
8052 const char *sqlstate = PQresultErrorField(conn->result,
8054
8055 if (sqlstate && strcmp(sqlstate, ERRCODE_INVALID_PASSWORD) == 0)
8056 libpq_append_conn_error(conn, "password retrieved from file \"%s\"",
8057 conn->pgpassfile);
8058 }
8059}
#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 5253 of file fe-connect.c.

5254{
5255 /*
5256 * If possible, send Terminate message to close the connection politely.
5257 */
5259
5260 /*
5261 * Must reset the blocking status so a possible reconnect will work.
5262 *
5263 * Don't call PQsetnonblocking() because it will fail if it's unable to
5264 * flush the connection.
5265 */
5266 conn->nonblocking = false;
5267
5268 /*
5269 * Close the connection, reset all transient state, flush I/O buffers.
5270 * Note that this includes clearing conn's error state; we're no longer
5271 * interested in any failures associated with the old connection, and we
5272 * want a clean slate for any new connection attempt.
5273 */
5274 pqDropConnection(conn, true);
5275 conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
5280 pqClearAsyncResult(conn); /* deallocate result */
5282
5283 /*
5284 * Release addrinfo, but since cancel requests never change their addrinfo
5285 * we don't do that. Otherwise we would have to rebuild it during a
5286 * PQcancelReset.
5287 */
5288 if (!conn->cancelRequest)
5290
5291 /* Reset all state obtained from server, too */
5293}
void pqClearOAuthToken(PGconn *conn)
void pqDropConnection(PGconn *conn, bool flushInput)
Definition: fe-connect.c:526
static void sendTerminateConn(PGconn *conn)
Definition: fe-connect.c:5219
static void pqDropServerData(PGconn *conn)
Definition: fe-connect.c:652
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 2192 of file fe-connect.c.

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

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

820{
821 PGconn *conn = PQconnectStart(conninfo);
822
823 if (conn && conn->status != CONNECTION_BAD)
825
826 return conn;
827}
PGconn * PQconnectStart(const char *conninfo)
Definition: fe-connect.c:947

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

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

767{
768 PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname);
769
770 if (conn && conn->status != CONNECTION_BAD)
772
773 return conn;
774}
PGconn * PQconnectStartParams(const char *const *keywords, const char *const *values, int expand_dbname)
Definition: fe-connect.c:866

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

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

7683{
7684 char *password;
7685
7686 if (!conn)
7687 return false;
7688 password = PQpass(conn);
7689 if (conn->password_needed &&
7690 (password == NULL || password[0] == '\0'))
7691 return true;
7692 else
7693 return false;
7694}
char * PQpass(const PGconn *conn)
Definition: fe-connect.c:7481

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

7709{
7710 if (!conn)
7711 return false;
7712 if (conn->gssapi_used)
7713 return true;
7714 else
7715 return false;
7716}
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 7697 of file fe-connect.c.

7698{
7699 if (!conn)
7700 return false;
7701 if (conn->password_needed)
7702 return true;
7703 else
7704 return false;
7705}

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

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

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

948{
949 PGconn *conn;
950
951 /*
952 * Allocate memory for the conn structure. Note that we also expect this
953 * to initialize conn->errorMessage to empty. All subsequent steps during
954 * connection initialization will only append to that buffer.
955 */
957 if (conn == NULL)
958 return NULL;
959
960 /*
961 * Parse the conninfo string
962 */
963 if (!connectOptions1(conn, conninfo))
964 return conn;
965
966 /*
967 * Compute derived options
968 */
970 return conn;
971
972 /*
973 * Connect to the database
974 */
976 {
977 /* Just in case we failed to set it in pqConnectDBStart */
979 }
980
981 return conn;
982}
static bool connectOptions1(PGconn *conn, const char *conninfo)
Definition: fe-connect.c:1072
bool pqConnectOptions2(PGconn *conn)
Definition: fe-connect.c:1246
PGconn * pqMakeEmptyPGconn(void)
Definition: fe-connect.c:4939
int pqConnectDBStart(PGconn *conn)
Definition: fe-connect.c:2703

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

869{
870 PGconn *conn;
871 PQconninfoOption *connOptions;
872
873 /*
874 * Allocate memory for the conn structure. Note that we also expect this
875 * to initialize conn->errorMessage to empty. All subsequent steps during
876 * connection initialization will only append to that buffer.
877 */
879 if (conn == NULL)
880 return NULL;
881
882 /*
883 * Parse the conninfo arrays
884 */
885 connOptions = conninfo_array_parse(keywords, values,
887 true, expand_dbname);
888 if (connOptions == NULL)
889 {
891 /* errorMessage is already set */
892 return conn;
893 }
894
895 /*
896 * Move option values into conn structure
897 */
898 if (!fillPGconn(conn, connOptions))
899 {
900 PQconninfoFree(connOptions);
901 return conn;
902 }
903
904 /*
905 * Free the option info - all is in conn now
906 */
907 PQconninfoFree(connOptions);
908
909 /*
910 * Compute derived options
911 */
913 return conn;
914
915 /*
916 * Connect to the database
917 */
919 {
920 /* Just in case we failed to set it in pqConnectDBStart */
922 }
923
924 return conn;
925}
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:6451

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

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

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

6161{
6162 PQExpBufferData errorBuf;
6163 PQconninfoOption *connOptions;
6164
6165 if (errmsg)
6166 *errmsg = NULL; /* default */
6167 initPQExpBuffer(&errorBuf);
6168 if (PQExpBufferDataBroken(errorBuf))
6169 return NULL; /* out of memory already :-( */
6170 connOptions = parse_connection_string(conninfo, &errorBuf, false);
6171 if (connOptions == NULL && errmsg)
6172 *errmsg = errorBuf.data;
6173 else
6174 termPQExpBuffer(&errorBuf);
6175 return connOptions;
6176}
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 1031 of file fe-connect.c.

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

References free, libpq_append_conn_error(), and PQconninfoOptions.

Referenced by PQcancelCreate().

◆ PQdb()

◆ pqDropConnection()

void pqDropConnection ( PGconn conn,
bool  flushInput 
)

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

527{
528 /* Drop any SSL state */
530
531 /* Close the socket itself */
532 if (conn->sock != PGINVALID_SOCKET)
535
536 /* Optionally discard any unread data */
537 if (flushInput)
538 conn->inStart = conn->inCursor = conn->inEnd = 0;
539
540 /* Always discard any unsent data */
541 conn->outCount = 0;
542
543 /* Likewise, discard any pending pipelined commands */
547 conn->cmd_queue_recycle = NULL;
548
549 /* Free authentication/encryption state */
551 {
552 /*
553 * Any in-progress async authentication should be torn down first so
554 * that cleanup_async_auth() can depend on the other authentication
555 * state if necessary.
556 */
558 conn->cleanup_async_auth = NULL;
559 }
560 conn->async_auth = NULL;
561 /* cleanup_async_auth() should have done this, but make sure */
563#ifdef ENABLE_GSS
564 {
565 OM_uint32 min_s;
566
567 if (conn->gcred != GSS_C_NO_CREDENTIAL)
568 {
569 gss_release_cred(&min_s, &conn->gcred);
570 conn->gcred = GSS_C_NO_CREDENTIAL;
571 }
572 if (conn->gctx)
573 gss_delete_sec_context(&min_s, &conn->gctx, GSS_C_NO_BUFFER);
574 if (conn->gtarg_nam)
575 gss_release_name(&min_s, &conn->gtarg_nam);
576 if (conn->gss_SendBuffer)
577 {
578 free(conn->gss_SendBuffer);
579 conn->gss_SendBuffer = NULL;
580 }
581 if (conn->gss_RecvBuffer)
582 {
583 free(conn->gss_RecvBuffer);
584 conn->gss_RecvBuffer = NULL;
585 }
586 if (conn->gss_ResultBuffer)
587 {
588 free(conn->gss_ResultBuffer);
589 conn->gss_ResultBuffer = NULL;
590 }
591 conn->gssenc = false;
592 }
593#endif
594#ifdef ENABLE_SSPI
595 if (conn->sspitarget)
596 {
597 free(conn->sspitarget);
598 conn->sspitarget = NULL;
599 }
600 if (conn->sspicred)
601 {
602 FreeCredentialsHandle(conn->sspicred);
603 free(conn->sspicred);
604 conn->sspicred = NULL;
605 }
606 if (conn->sspictx)
607 {
608 DeleteSecurityContext(conn->sspictx);
609 free(conn->sspictx);
610 conn->sspictx = NULL;
611 }
612 conn->usesspi = 0;
613#endif
614 if (conn->sasl_state)
615 {
617 conn->sasl_state = NULL;
618 }
619}
static void pqFreeCommandQueue(PGcmdQueueEntry *queue)
Definition: fe-connect.c:626
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 652 of file fe-connect.c.

653{
654 PGnotify *notify;
655 pgParameterStatus *pstatus;
656
657 /* Forget pending notifies */
658 notify = conn->notifyHead;
659 while (notify != NULL)
660 {
661 PGnotify *prev = notify;
662
663 notify = notify->next;
664 free(prev);
665 }
666 conn->notifyHead = conn->notifyTail = NULL;
667
668 /* Reset ParameterStatus data, as well as variables deduced from it */
669 pstatus = conn->pstatus;
670 while (pstatus != NULL)
671 {
672 pgParameterStatus *prev = pstatus;
673
674 pstatus = pstatus->next;
675 free(prev);
676 }
677 conn->pstatus = NULL;
679 conn->std_strings = false;
683 conn->sversion = 0;
684
685 /* Drop large-object lookup data */
687 conn->lobjfuncs = NULL;
688
689 /* Reset assorted other per-connection state */
690 conn->last_sqlstate[0] = '\0';
691 conn->pversion_negotiated = false;
692 conn->auth_req_received = false;
693 conn->client_finished_auth = false;
694 conn->password_needed = false;
695 conn->gssapi_used = false;
696 conn->write_failed = false;
698 conn->write_err_msg = NULL;
699 conn->oauth_want_retry = false;
700
701 /*
702 * Cancel connections need to retain their be_pid and be_cancel_key across
703 * PQcancelReset invocations, otherwise they would not have access to the
704 * secret token of the connection they are supposed to cancel.
705 */
706 if (!conn->cancelRequest)
707 {
708 conn->be_pid = 0;
709 if (conn->be_cancel_key != NULL)
710 {
712 conn->be_cancel_key = NULL;
713 }
715 }
716}
@ 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
char * write_err_msg
Definition: libpq-int.h:510
PGnotify * notifyHead
Definition: libpq-int.h:473
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
int be_cancel_key_len
Definition: libpq-int.h:550

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

7630{
7631 if (!conn)
7632 return libpq_gettext("connection pointer is NULL\n");
7633
7634 /*
7635 * The errorMessage buffer might be marked "broken" due to having
7636 * previously failed to allocate enough memory for the message. In that
7637 * case, tell the application we ran out of memory.
7638 */
7640 return libpq_gettext("out of memory\n");
7641
7642 return conn->errorMessage.data;
7643}
#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 5300 of file fe-connect.c.

5301{
5302 if (conn)
5303 {
5306 }
5307}
void pqClosePGconn(PGconn *conn)
Definition: fe-connect.c:5253
static void freePGconn(PGconn *conn)
Definition: fe-connect.c:5039

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

627{
628 while (queue != NULL)
629 {
630 PGcmdQueueEntry *cur = queue;
631
632 queue = cur->next;
633 free(cur->query);
634 free(cur);
635 }
636}
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 7609 of file fe-connect.c.

7610{
7611 if (!conn)
7612 return 0;
7613 if (conn->status == CONNECTION_BAD)
7614 return 0;
7616}
#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 8146 of file fe-connect.c.

8147{
8148#ifndef WIN32
8149 const char *home;
8150
8151 home = getenv("HOME");
8152 if (home && home[0])
8153 {
8154 strlcpy(buf, home, bufsize);
8155 return true;
8156 }
8157 else
8158 {
8159 struct passwd pwbuf;
8160 struct passwd *pw;
8161 char tmpbuf[1024];
8162 int rc;
8163
8164 rc = getpwuid_r(geteuid(), &pwbuf, tmpbuf, sizeof tmpbuf, &pw);
8165 if (rc != 0 || !pw)
8166 return false;
8167 strlcpy(buf, pw->pw_dir, bufsize);
8168 return true;
8169 }
8170#else
8171 char tmppath[MAX_PATH];
8172
8173 ZeroMemory(tmppath, sizeof(tmppath));
8174 if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, tmppath) != S_OK)
8175 return false;
8176 snprintf(buf, bufsize, "%s/postgresql", tmppath);
8177 return true;
8178#endif
8179}
#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 7498 of file fe-connect.c.

7499{
7500 if (!conn)
7501 return NULL;
7502
7503 if (conn->connhost != NULL)
7504 {
7505 /*
7506 * Return the verbatim host value provided by user, or hostaddr in its
7507 * lack.
7508 */
7509 if (conn->connhost[conn->whichhost].host != NULL &&
7510 conn->connhost[conn->whichhost].host[0] != '\0')
7511 return conn->connhost[conn->whichhost].host;
7512 else if (conn->connhost[conn->whichhost].hostaddr != NULL &&
7513 conn->connhost[conn->whichhost].hostaddr[0] != '\0')
7515 }
7516
7517 return "";
7518}

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

7522{
7523 if (!conn)
7524 return NULL;
7525
7526 /* Return the parsed IP address */
7527 if (conn->connhost != NULL && conn->connip != NULL)
7528 return conn->connip;
7529
7530 return "";
7531}

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

Referenced by do_connect(), and exec_command_conninfo().

◆ pqMakeEmptyPGconn()

PGconn * pqMakeEmptyPGconn ( void  )

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

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

7559{
7560 if (!conn)
7561 return NULL;
7562 return conn->pgoptions;
7563}

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

5410{
5411 /* Start the message. */
5412 if (pqPutMsgStart(pack_type, conn))
5413 return STATUS_ERROR;
5414
5415 /* Send the message body. */
5416 if (pqPutnchar(buf, buf_len, conn))
5417 return STATUS_ERROR;
5418
5419 /* Finish the message. */
5420 if (pqPutMsgEnd(conn))
5421 return STATUS_ERROR;
5422
5423 /* Flush to ensure backend gets it. */
5424 if (pqFlush(conn))
5425 return STATUS_ERROR;
5426
5427 return STATUS_OK;
5428}
#define STATUS_ERROR
Definition: c.h:1141
int pqPutMsgStart(char msg_type, PGconn *conn)
Definition: fe-misc.c:473
int pqPutnchar(const void *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 7584 of file fe-connect.c.

7585{
7586 const pgParameterStatus *pstatus;
7587
7588 if (!conn || !paramName)
7589 return NULL;
7590 for (pstatus = conn->pstatus; pstatus != NULL; pstatus = pstatus->next)
7591 {
7592 if (strcmp(pstatus->name, paramName) == 0)
7593 return pstatus->value;
7594 }
7595 return NULL;
7596}

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

8189{
8190 char *end;
8191 long numval;
8192
8193 Assert(value != NULL);
8194
8195 *result = 0;
8196
8197 /* strtol(3) skips leading whitespaces */
8198 errno = 0;
8199 numval = strtol(value, &end, 10);
8200
8201 /*
8202 * If no progress was done during the parsing or an error happened, fail.
8203 * This tests properly for overflows of the result.
8204 */
8205 if (value == end || errno != 0 || numval != (int) numval)
8206 goto error;
8207
8208 /*
8209 * Skip any trailing whitespace; if anything but whitespace remains before
8210 * the terminating character, fail
8211 */
8212 while (*end != '\0' && isspace((unsigned char) *end))
8213 end++;
8214
8215 if (*end != '\0')
8216 goto error;
8217
8218 *result = numval;
8219 return true;
8220
8221error:
8222 libpq_append_conn_error(conn, "invalid integer value \"%s\" for connection option \"%s\"",
8223 value, context);
8224 return false;
8225}
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 8232 of file fe-connect.c.

8234{
8235 if (strcmp(value, "latest") == 0)
8236 {
8237 *result = PG_PROTOCOL_LATEST;
8238 return true;
8239 }
8240 if (strcmp(value, "3.0") == 0)
8241 {
8242 *result = PG_PROTOCOL(3, 0);
8243 return true;
8244 }
8245
8246 /* 3.1 never existed, we went straight from 3.0 to 3.2 */
8247
8248 if (strcmp(value, "3.2") == 0)
8249 {
8250 *result = PG_PROTOCOL(3, 2);
8251 return true;
8252 }
8253
8254 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
8255 context, value);
8256 return false;
8257}

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

7482{
7483 char *password = NULL;
7484
7485 if (!conn)
7486 return NULL;
7487 if (conn->connhost != NULL)
7489 if (password == NULL)
7490 password = conn->pgpass;
7491 /* Historically we've returned "" not NULL for no password specified */
7492 if (password == NULL)
7493 password = "";
7494 return password;
7495}

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

836{
837 PGconn *conn = PQconnectStart(conninfo);
838 PGPing ret;
839
840 ret = internal_ping(conn);
841 PQfinish(conn);
842
843 return ret;
844}
static PGPing internal_ping(PGconn *conn)
Definition: fe-connect.c:4875
void PQfinish(PGconn *conn)
Definition: fe-connect.c:5300
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 782 of file fe-connect.c.

785{
786 PGconn *conn = PQconnectStartParams(keywords, values, expand_dbname);
787 PGPing ret;
788
789 ret = internal_ping(conn);
790 PQfinish(conn);
791
792 return ret;
793}

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

7535{
7536 if (!conn)
7537 return NULL;
7538
7539 if (conn->connhost != NULL)
7540 return conn->connhost[conn->whichhost].port;
7541
7542 return "";
7543}

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

8288{
8290
8291 if (newhandler)
8292 pg_g_threadlock = newhandler;
8293 else
8295
8296 return prev;
8297}
static void default_threadlock(int acquire)
Definition: fe-connect.c:8270
pgthreadlock_t pg_g_threadlock
Definition: fe-connect.c:510
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 5136 of file fe-connect.c.

5137{
5138 if (conn->connhost)
5139 {
5140 for (int i = 0; i < conn->nconnhost; ++i)
5141 {
5142 free(conn->connhost[i].host);
5144 free(conn->connhost[i].port);
5145 if (conn->connhost[i].password != NULL)
5146 {
5148 strlen(conn->connhost[i].password));
5150 }
5151 }
5152 free(conn->connhost);
5153 conn->connhost = NULL;
5154 }
5155}

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

5315{
5316 if (conn)
5317 {
5319
5321 {
5322 /*
5323 * Notify event procs of successful reset.
5324 */
5325 int i;
5326
5327 for (i = 0; i < conn->nEvents; i++)
5328 {
5329 PGEventConnReset evt;
5330
5331 evt.conn = conn;
5332 (void) conn->events[i].proc(PGEVT_CONNRESET, &evt,
5334 }
5335 }
5336 }
5337}
@ 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 5366 of file fe-connect.c.

5367{
5368 if (conn)
5369 {
5371
5372 if (status == PGRES_POLLING_OK)
5373 {
5374 /*
5375 * Notify event procs of successful reset.
5376 */
5377 int i;
5378
5379 for (i = 0; i < conn->nEvents; i++)
5380 {
5381 PGEventConnReset evt;
5382
5383 evt.conn = conn;
5384 (void) conn->events[i].proc(PGEVT_CONNRESET, &evt,
5386 }
5387 }
5388
5389 return status;
5390 }
5391
5392 return PGRES_POLLING_FAILED;
5393}

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

5348{
5349 if (conn)
5350 {
5352
5353 return pqConnectDBStart(conn);
5354 }
5355
5356 return 0;
5357}

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

◆ PQserverVersion()

◆ PQservice()

char * PQservice ( const PGconn conn)

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

7466{
7467 if (!conn)
7468 return NULL;
7469 return conn->pgservice;
7470}

References conn, and pg_conn::pgservice.

Referenced by get_prompt(), and SyncVariables().

◆ PQsetClientEncoding()

int PQsetClientEncoding ( PGconn conn,
const char *  encoding 
)

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

7728{
7729 char qbuf[128];
7730 static const char query[] = "set client_encoding to '%s'";
7731 PGresult *res;
7732 int status;
7733
7734 if (!conn || conn->status != CONNECTION_OK)
7735 return -1;
7736
7737 if (!encoding)
7738 return -1;
7739
7740 /* Resolve special "auto" value from the locale */
7741 if (strcmp(encoding, "auto") == 0)
7743
7744 /* check query buffer overflow */
7745 if (sizeof(qbuf) < (sizeof(query) + strlen(encoding)))
7746 return -1;
7747
7748 /* ok, now send a query */
7749 sprintf(qbuf, query, encoding);
7750 res = PQexec(conn, qbuf);
7751
7752 if (res == NULL)
7753 return -1;
7754 if (res->resultStatus != PGRES_COMMAND_OK)
7755 status = -1;
7756 else
7757 {
7758 /*
7759 * We rely on the backend to report the parameter value, and we'll
7760 * change state at that time.
7761 */
7762 status = 0; /* everything is ok */
7763 }
7764 PQclear(res);
7765 return status;
7766}
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(), test_gb18030_page_multiple(), 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 2230 of file fe-connect.c.

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

7782{
7784
7785 if (!conn)
7786 return PQSHOW_CONTEXT_ERRORS;
7787 old = conn->show_context;
7788 conn->show_context = show_context;
7789 return old;
7790}
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 7769 of file fe-connect.c.

7770{
7771 PGVerbosity old;
7772
7773 if (!conn)
7774 return PQERRORS_DEFAULT;
7775 old = conn->verbosity;
7776 conn->verbosity = verbosity;
7777 return old;
7778}
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 7810 of file fe-connect.c.

7811{
7813
7814 if (conn == NULL)
7815 return NULL;
7816
7818 if (proc)
7819 {
7820 conn->noticeHooks.noticeProc = proc;
7822 }
7823 return old;
7824}
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 7793 of file fe-connect.c.

7794{
7795 PQnoticeReceiver old;
7796
7797 if (conn == NULL)
7798 return NULL;
7799
7800 old = conn->noticeHooks.noticeRec;
7801 if (proc)
7802 {
7803 conn->noticeHooks.noticeRec = proc;
7805 }
7806 return old;
7807}
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 7550 of file fe-connect.c.

7551{
7552 if (!conn)
7553 return NULL;
7554 return "";
7555}

References conn.

◆ PQuser()

char * PQuser ( const PGconn conn)

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

7474{
7475 if (!conn)
7476 return NULL;
7477 return conn->pguser;
7478}

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

7861{
7862 char *tbuf;
7863 const char *ttok;
7864 bool bslash = false;
7865
7866 if (buf == NULL || token == NULL)
7867 return NULL;
7868 tbuf = buf;
7869 ttok = token;
7870 if (tbuf[0] == '*' && tbuf[1] == ':')
7871 return tbuf + 2;
7872 while (*tbuf != 0)
7873 {
7874 if (*tbuf == '\\' && !bslash)
7875 {
7876 tbuf++;
7877 bslash = true;
7878 }
7879 if (*tbuf == ':' && *ttok == 0 && !bslash)
7880 return tbuf + 1;
7881 bslash = false;
7882 if (*ttok == 0)
7883 return NULL;
7884 if (*tbuf == *ttok)
7885 {
7886 tbuf++;
7887 ttok++;
7888 }
7889 else
7890 return NULL;
7891 }
7892 return NULL;
7893}
#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 6264 of file fe-connect.c.

6265{
6266 return uri_prefix_length(connstr) != 0 || strchr(connstr, '=') != NULL;
6267}

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

5206{
5207 if (conn->addr)
5208 {
5209 free(conn->addr);
5210 conn->addr = NULL;
5211 }
5212}

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

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

5220{
5221 /*
5222 * The Postgres cancellation protocol does not have a notion of a
5223 * Terminate message, so don't send one.
5224 */
5225 if (conn->cancelRequest)
5226 return;
5227
5228 /*
5229 * Note that the protocol doesn't allow us to send Terminate messages
5230 * during the startup phase.
5231 */
5233 {
5234 /*
5235 * Try to send "close connection" message to backend. Ignore any
5236 * error.
5237 */
5240 (void) pqFlush(conn);
5241 }
5242}
#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 2567 of file fe-connect.c.

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

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

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

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

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

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

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

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

8094{
8097
8098 /* If at least one of the bounds is not set, the range is valid */
8099 if (min == NULL || max == NULL || strlen(min) == 0 || strlen(max) == 0)
8100 return true;
8101
8102 /*
8103 * If the minimum version is the lowest one we accept, then all options
8104 * for the maximum are valid.
8105 */
8106 if (pg_strcasecmp(min, "TLSv1") == 0)
8107 return true;
8108
8109 /*
8110 * The minimum bound is valid, and cannot be TLSv1, so using TLSv1 for the
8111 * maximum is incorrect.
8112 */
8113 if (pg_strcasecmp(max, "TLSv1") == 0)
8114 return false;
8115
8116 /*
8117 * At this point we know that we have a mix of TLSv1.1 through 1.3
8118 * versions.
8119 */
8120 if (pg_strcasecmp(min, max) > 0)
8121 return false;
8122
8123 return true;
8124}
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 8067 of file fe-connect.c.

8068{
8069 /*
8070 * An empty string and a NULL value are considered valid as it is
8071 * equivalent to ignoring the parameter.
8072 */
8073 if (!version || strlen(version) == 0)
8074 return true;
8075
8076 if (pg_strcasecmp(version, "TLSv1") == 0 ||
8077 pg_strcasecmp(version, "TLSv1.1") == 0 ||
8078 pg_strcasecmp(version, "TLSv1.2") == 0 ||
8079 pg_strcasecmp(version, "TLSv1.3") == 0)
8080 return true;
8081
8082 /* anything else is wrong */
8083 return false;
8084}

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

5167{
5168 struct addrinfo *ai = addrlist;
5169
5170 conn->whichaddr = 0;
5171
5172 conn->naddr = 0;
5173 while (ai)
5174 {
5175 ai = ai->ai_next;
5176 conn->naddr++;
5177 }
5178
5179 conn->addr = calloc(conn->naddr, sizeof(AddrInfo));
5180 if (conn->addr == NULL)
5181 {
5182 libpq_append_conn_error(conn, "out of memory");
5183 return 1;
5184 }
5185
5186 ai = addrlist;
5187 for (int i = 0; i < conn->naddr; i++)
5188 {
5189 conn->addr[i].family = ai->ai_family;
5190
5191 memcpy(&conn->addr[i].addr.addr, ai->ai_addr,
5192 ai->ai_addrlen);
5193 conn->addr[i].addr.salen = ai->ai_addrlen;
5194 ai = ai->ai_next;
5195 }
5196
5197 return 0;
5198}

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

6242{
6243 if (strncmp(connstr, uri_designator,
6244 sizeof(uri_designator) - 1) == 0)
6245 return sizeof(uri_designator) - 1;
6246
6247 if (strncmp(connstr, short_uri_designator,
6248 sizeof(short_uri_designator) - 1) == 0)
6249 return sizeof(short_uri_designator) - 1;
6250
6251 return 0;
6252}
static const char short_uri_designator[]
Definition: fe-connect.c:446
static const char uri_designator[]
Definition: fe-connect.c:445

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

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

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

Referenced by PQconnectPoll().

◆ pg_g_threadlock

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

Referenced by PQregisterThreadLock().

◆ PQconninfoOptions

const internalPQconninfoOption PQconninfoOptions[]
static

Definition at line 199 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 446 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 437 of file fe-connect.c.

Referenced by fill_allowed_sasl_mechs().

◆ uri_designator

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

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

Referenced by uri_prefix_length().