PostgreSQL Source Code git master
Loading...
Searching...
No Matches
fe-connect.c File Reference
#include "postgres_fe.h"
#include <sys/stat.h>
#include <fcntl.h>
#include <ctype.h>
#include <limits.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 ERRCODE_PROTOCOL_VIOLATION   "08P01"
 
#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 charconninfo_uri_decode (const char *str, PQExpBuffer errorMessage)
 
static bool get_hexdigit (char digit, int *value)
 
static const charconninfo_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 charpwdfMatchesString (char *buf, const char *token)
 
static charpasswordFromFile (const char *hostname, const char *port, const char *dbname, const char *username, const char *pgpassfile, const char **errmsg)
 
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 charparse_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)
 
charPQdb (const PGconn *conn)
 
charPQuser (const PGconn *conn)
 
charPQpass (const PGconn *conn)
 
charPQhost (const PGconn *conn)
 
charPQhostaddr (const PGconn *conn)
 
charPQport (const PGconn *conn)
 
charPQtty (const PGconn *conn)
 
charPQoptions (const PGconn *conn)
 
ConnStatusType PQstatus (const PGconn *conn)
 
PGTransactionStatusType PQtransactionStatus (const PGconn *conn)
 
const charPQparameterStatus (const PGconn *conn, const char *paramName)
 
int PQprotocolVersion (const PGconn *conn)
 
int PQfullProtocolVersion (const PGconn *conn)
 
int PQserverVersion (const PGconn *conn)
 
charPQerrorMessage (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 { \
{ \
goto keep_going; \
} \
} while(0);
static bool connection_failed(PGconn *conn)
static int fb(int x)
PGconn * conn
Definition streamutil.c:52

◆ DefaultChannelBinding

#define DefaultChannelBinding   "disable"

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

◆ DefaultGSSMode

#define DefaultGSSMode   "disable"

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

◆ DefaultHost

#define DefaultHost   "localhost"

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

◆ DefaultLoadBalanceHosts

#define DefaultLoadBalanceHosts   "disable"

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

◆ DefaultOption

#define DefaultOption   ""

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

◆ DefaultSSLCertMode

#define DefaultSSLCertMode   "disable"

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

◆ DefaultSSLMode

#define DefaultSSLMode   "disable"

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

◆ DefaultSSLNegotiation

#define DefaultSSLNegotiation   "postgres"

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

◆ DefaultTargetSessionAttrs

#define DefaultTargetSessionAttrs   "any"

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

◆ ENCRYPTION_NEGOTIATION_FAILED

#define ENCRYPTION_NEGOTIATION_FAILED (   msg)
Value:
do { \
{ \
case 0: \
goto error_return; \
case 1: \
case 2: \
goto keep_going; \
} \
} while(0);
@ CONNECTION_MADE
Definition libpq-fe.h:93
@ PGRES_POLLING_WRITING
Definition libpq-fe.h:117
ConnStatusType status
Definition libpq-int.h:462

◆ ERRCODE_APPNAME_UNKNOWN

#define ERRCODE_APPNAME_UNKNOWN   "42704"

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

◆ ERRCODE_CANNOT_CONNECT_NOW

#define ERRCODE_CANNOT_CONNECT_NOW   "57P03"

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

◆ ERRCODE_INVALID_PASSWORD

#define ERRCODE_INVALID_PASSWORD   "28P01"

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

◆ ERRCODE_PROTOCOL_VIOLATION

#define ERRCODE_PROTOCOL_VIOLATION   "08P01"

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

◆ MAX_ERRLEN

#define MAX_ERRLEN   30000

◆ PGPASSFILE

#define PGPASSFILE   ".pgpass"

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

◆ SASL_MECHANISM_COUNT

#define SASL_MECHANISM_COUNT   lengthof(supported_sasl_mechs)

Definition at line 448 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)
uint8 current_enc_method
Definition libpq-int.h:617

Typedef Documentation

◆ internalPQconninfoOption

Function Documentation

◆ clear_allowed_sasl_mechs()

static void clear_allowed_sasl_mechs ( PGconn conn)
inlinestatic

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

1223{
1224 for (int i = 0; i < lengthof(conn->allowed_sasl_mechs); i++)
1226}
#define lengthof(array)
Definition c.h:815
int i
Definition isn.c:77
const pg_fe_sasl_mech * allowed_sasl_mechs[2]
Definition libpq-int.h:519

References pg_conn::allowed_sasl_mechs, conn, fb(), i, and lengthof.

Referenced by pqConnectOptions2().

◆ connectFailureMessage()

static void connectFailureMessage ( PGconn conn,
int  errorno 
)
static

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

2475{
2477
2479 "%s\n",
2480 SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
2481
2482 if (conn->raddr.addr.ss_family == AF_UNIX)
2483 libpq_append_conn_error(conn, "\tIs the server running locally and accepting connections on that socket?");
2484 else
2485 libpq_append_conn_error(conn, "\tIs the server running on that host and accepting TCP/IP connections?");
2486}
#define SOCK_STRERROR
Definition libpq-int.h:973
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition oauth-utils.c:95
#define PG_STRERROR_R_BUFLEN
Definition port.h:278
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
struct sockaddr_storage addr
Definition pqcomm.h:32
PQExpBufferData errorMessage
Definition libpq-int.h:683
SockAddr raddr
Definition libpq-int.h:502

References SockAddr::addr, appendPQExpBuffer(), conn, pg_conn::errorMessage, fb(), 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 4833 of file fe-connect.c.

4834{
4837
4838 return select_next_encryption_method(conn, false);
4839}
#define Assert(condition)
Definition c.h:885
static bool select_next_encryption_method(PGconn *conn, bool have_valid_connection)
uint8 failed_enc_methods
Definition libpq-int.h:616

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

2360{
2361#ifdef TCP_NODELAY
2362 int on = 1;
2363
2365 (char *) &on,
2366 sizeof(on)) < 0)
2367 {
2369
2370 libpq_append_conn_error(conn, "could not set socket to TCP no delay mode: %s",
2371 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2372 return 0;
2373 }
2374#endif
2375
2376 return 1;
2377}
#define SOCK_ERRNO
pgsocket sock
Definition libpq-int.h:499

References conn, fb(), 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 1079 of file fe-connect.c.

1080{
1082
1083 /*
1084 * Parse the conninfo string
1085 */
1087 if (connOptions == NULL)
1088 {
1090 /* errorMessage is already set */
1091 return false;
1092 }
1093
1094 /*
1095 * Move option values into conn structure
1096 */
1098 {
1101 return false;
1102 }
1103
1104 /*
1105 * Free the option info - all is in conn now
1106 */
1108
1109 return true;
1110}
static PQconninfoOption * parse_connection_string(const char *connstr, PQExpBuffer errorMessage, bool use_defaults)
void PQconninfoFree(PQconninfoOption *connOptions)
static bool fillPGconn(PGconn *conn, PQconninfoOption *connOptions)
@ CONNECTION_BAD
Definition libpq-fe.h:85

References conn, CONNECTION_BAD, pg_conn::errorMessage, fb(), 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 6723 of file fe-connect.c.

6724{
6727 *sslrootcert = NULL;
6728 char *tmp;
6729
6730 /*
6731 * If there's a service spec, use it to obtain any not-explicitly-given
6732 * parameters. Ignore error if no error message buffer is passed because
6733 * there is no way to pass back the failure message.
6734 */
6735 if (parseServiceInfo(options, errorMessage) != 0 && errorMessage)
6736 return false;
6737
6738 /*
6739 * Get the fallback resources for parameters not specified in the conninfo
6740 * string nor the service.
6741 */
6742 for (option = options; option->keyword != NULL; option++)
6743 {
6744 if (strcmp(option->keyword, "sslrootcert") == 0)
6745 sslrootcert = option; /* save for later */
6746
6747 if (option->val != NULL)
6748 continue; /* Value was in conninfo or service */
6749
6750 /*
6751 * Try to get the environment variable fallback
6752 */
6753 if (option->envvar != NULL)
6754 {
6755 if ((tmp = getenv(option->envvar)) != NULL)
6756 {
6757 option->val = strdup(tmp);
6758 if (!option->val)
6759 {
6760 if (errorMessage)
6761 libpq_append_error(errorMessage, "out of memory");
6762 return false;
6763 }
6764 continue;
6765 }
6766 }
6767
6768 /*
6769 * Interpret the deprecated PGREQUIRESSL environment variable. Per
6770 * tradition, translate values starting with "1" to sslmode=require,
6771 * and ignore other values. Given both PGREQUIRESSL=1 and PGSSLMODE,
6772 * PGSSLMODE takes precedence; the opposite was true before v9.3.
6773 */
6774 if (strcmp(option->keyword, "sslmode") == 0)
6775 {
6776 const char *requiresslenv = getenv("PGREQUIRESSL");
6777
6778 if (requiresslenv != NULL && requiresslenv[0] == '1')
6779 {
6780 option->val = strdup("require");
6781 if (!option->val)
6782 {
6783 if (errorMessage)
6784 libpq_append_error(errorMessage, "out of memory");
6785 return false;
6786 }
6787 continue;
6788 }
6789
6790 /*
6791 * sslmode is not specified. Let it be filled in with the compiled
6792 * default for now, but if sslrootcert=system, we'll override the
6793 * default later before returning.
6794 */
6796 }
6797
6798 /*
6799 * No environment variable specified or the variable isn't set - try
6800 * compiled-in default
6801 */
6802 if (option->compiled != NULL)
6803 {
6804 option->val = strdup(option->compiled);
6805 if (!option->val)
6806 {
6807 if (errorMessage)
6808 libpq_append_error(errorMessage, "out of memory");
6809 return false;
6810 }
6811 continue;
6812 }
6813
6814 /*
6815 * Special handling for "user" option. Note that if pg_fe_getauthname
6816 * fails, we just leave the value as NULL; there's no need for this to
6817 * be an error condition if the caller provides a user name. The only
6818 * reason we do this now at all is so that callers of PQconndefaults
6819 * will see a correct default (barring error, of course).
6820 */
6821 if (strcmp(option->keyword, "user") == 0)
6822 {
6824 continue;
6825 }
6826 }
6827
6828 /*
6829 * Special handling for sslrootcert=system with no sslmode explicitly
6830 * defined. In this case we want to strengthen the default sslmode to
6831 * verify-full.
6832 */
6833 if (sslmode_default && sslrootcert)
6834 {
6835 if (sslrootcert->val && strcmp(sslrootcert->val, "system") == 0)
6836 {
6837 free(sslmode_default->val);
6838
6839 sslmode_default->val = strdup("verify-full");
6840 if (!sslmode_default->val)
6841 {
6842 if (errorMessage)
6843 libpq_append_error(errorMessage, "out of memory");
6844 return false;
6845 }
6846 }
6847 }
6848
6849 return true;
6850}
char * pg_fe_getauthname(PQExpBuffer errorMessage)
Definition fe-auth.c:1344
static int parseServiceInfo(PQconninfoOption *options, PQExpBuffer errorMessage)
void libpq_append_error(PQExpBuffer errorMessage, const char *fmt,...)
Definition fe-misc.c:1375
#define free(a)
int val
Definition getopt_long.h:22

References fb(), free, libpq_append_error(), parseServiceInfo(), pg_fe_getauthname(), and option::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 6565 of file fe-connect.c.

6568{
6572 int i = 0;
6573
6574 /*
6575 * If expand_dbname is non-zero, check keyword "dbname" to see if val is
6576 * actually a recognized connection string.
6577 */
6578 while (expand_dbname && keywords[i])
6579 {
6580 const char *pname = keywords[i];
6581 const char *pvalue = values[i];
6582
6583 /* first find "dbname" if any */
6584 if (strcmp(pname, "dbname") == 0 && pvalue)
6585 {
6586 /*
6587 * If value is a connection string, parse it, but do not use
6588 * defaults here -- those get picked up later. We only want to
6589 * override for those parameters actually passed.
6590 */
6592 {
6593 dbname_options = parse_connection_string(pvalue, errorMessage, false);
6594 if (dbname_options == NULL)
6595 return NULL;
6596 }
6597 break;
6598 }
6599 ++i;
6600 }
6601
6602 /* Make a working copy of PQconninfoOptions */
6603 options = conninfo_init(errorMessage);
6604 if (options == NULL)
6605 {
6607 return NULL;
6608 }
6609
6610 /* Parse the keywords/values arrays */
6611 i = 0;
6612 while (keywords[i])
6613 {
6614 const char *pname = keywords[i];
6615 const char *pvalue = values[i];
6616
6617 if (pvalue != NULL && pvalue[0] != '\0')
6618 {
6619 /* Search for the param record */
6620 for (option = options; option->keyword != NULL; option++)
6621 {
6622 if (strcmp(option->keyword, pname) == 0)
6623 break;
6624 }
6625
6626 /* Check for invalid connection option */
6627 if (option->keyword == NULL)
6628 {
6629 libpq_append_error(errorMessage, "invalid connection option \"%s\"", pname);
6632 return NULL;
6633 }
6634
6635 /*
6636 * If we are on the first dbname parameter, and we have a parsed
6637 * connection string, copy those parameters across, overriding any
6638 * existing previous settings.
6639 */
6640 if (strcmp(pname, "dbname") == 0 && dbname_options)
6641 {
6643
6644 for (str_option = dbname_options; str_option->keyword != NULL; str_option++)
6645 {
6646 if (str_option->val != NULL)
6647 {
6648 int k;
6649
6650 for (k = 0; options[k].keyword; k++)
6651 {
6652 if (strcmp(options[k].keyword, str_option->keyword) == 0)
6653 {
6654 free(options[k].val);
6655 options[k].val = strdup(str_option->val);
6656 if (!options[k].val)
6657 {
6658 libpq_append_error(errorMessage, "out of memory");
6661 return NULL;
6662 }
6663 break;
6664 }
6665 }
6666 }
6667 }
6668
6669 /*
6670 * Forget the parsed connection string, so that any subsequent
6671 * dbname parameters will not be expanded.
6672 */
6675 }
6676 else
6677 {
6678 /*
6679 * Store the value, overriding previous settings
6680 */
6681 free(option->val);
6682 option->val = strdup(pvalue);
6683 if (!option->val)
6684 {
6685 libpq_append_error(errorMessage, "out of memory");
6688 return NULL;
6689 }
6690 }
6691 }
6692 ++i;
6693 }
6695
6696 /*
6697 * Add in defaults if the caller wants that.
6698 */
6699 if (use_defaults)
6700 {
6701 if (!conninfo_add_defaults(options, errorMessage))
6702 {
6704 return NULL;
6705 }
6706 }
6707
6708 return options;
6709}
static Datum values[MAXATTR]
Definition bootstrap.c:147
static PQconninfoOption * conninfo_init(PQExpBuffer errorMessage)
static bool conninfo_add_defaults(PQconninfoOption *options, PQExpBuffer errorMessage)
static bool recognized_connection_string(const char *connstr)
long val
Definition informix.c:689
static const JsonPathKeyword keywords[]

References conninfo_add_defaults(), conninfo_init(), fb(), free, i, keywords, libpq_append_error(), parse_connection_string(), PQconninfoFree(), recognized_connection_string(), option::val, val, and values.

Referenced by PQconnectStartParams().

◆ conninfo_find()

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

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

7497{
7499
7500 for (option = connOptions; option->keyword != NULL; option++)
7501 {
7502 if (strcmp(option->keyword, keyword) == 0)
7503 return option;
7504 }
7505
7506 return NULL;
7507}

References fb().

Referenced by conninfo_getval(), and conninfo_storeval().

◆ conninfo_getval()

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

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

7408{
7410
7411 option = conninfo_find(connOptions, keyword);
7412
7413 return option ? option->val : NULL;
7414}
static PQconninfoOption * conninfo_find(PQconninfoOption *connOptions, const char *keyword)

References conninfo_find(), fb(), and option::val.

Referenced by fillPGconn(), and parseServiceInfo().

◆ conninfo_init()

static PQconninfoOption * conninfo_init ( PQExpBuffer  errorMessage)
static

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

6297{
6301
6302 /*
6303 * Get enough memory for all options in PQconninfoOptions, even if some
6304 * end up being filtered out.
6305 */
6307 if (options == NULL)
6308 {
6309 libpq_append_error(errorMessage, "out of memory");
6310 return NULL;
6311 }
6312 opt_dest = options;
6313
6315 {
6316 /* Only copy the public part of the struct, not the full internal */
6318 opt_dest++;
6319 }
6320 MemSet(opt_dest, 0, sizeof(PQconninfoOption));
6321
6322 return options;
6323}
#define MemSet(start, val, len)
Definition c.h:1035
static const internalPQconninfoOption PQconninfoOptions[]
Definition fe-connect.c:201
#define malloc(a)

References fb(), _internalPQconninfoOption::keyword, libpq_append_error(), malloc, MemSet, 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 6389 of file fe-connect.c.

6391{
6392 char *pname;
6393 char *pval;
6394 char *buf;
6395 char *cp;
6396 char *cp2;
6398
6399 /* Make a working copy of PQconninfoOptions */
6400 options = conninfo_init(errorMessage);
6401 if (options == NULL)
6402 return NULL;
6403
6404 /* Need a modifiable copy of the input string */
6405 if ((buf = strdup(conninfo)) == NULL)
6406 {
6407 libpq_append_error(errorMessage, "out of memory");
6409 return NULL;
6410 }
6411 cp = buf;
6412
6413 while (*cp)
6414 {
6415 /* Skip blanks before the parameter name */
6416 if (isspace((unsigned char) *cp))
6417 {
6418 cp++;
6419 continue;
6420 }
6421
6422 /* Get the parameter name */
6423 pname = cp;
6424 while (*cp)
6425 {
6426 if (*cp == '=')
6427 break;
6428 if (isspace((unsigned char) *cp))
6429 {
6430 *cp++ = '\0';
6431 while (*cp)
6432 {
6433 if (!isspace((unsigned char) *cp))
6434 break;
6435 cp++;
6436 }
6437 break;
6438 }
6439 cp++;
6440 }
6441
6442 /* Check that there is a following '=' */
6443 if (*cp != '=')
6444 {
6445 libpq_append_error(errorMessage,
6446 "missing \"=\" after \"%s\" in connection info string",
6447 pname);
6449 free(buf);
6450 return NULL;
6451 }
6452 *cp++ = '\0';
6453
6454 /* Skip blanks after the '=' */
6455 while (*cp)
6456 {
6457 if (!isspace((unsigned char) *cp))
6458 break;
6459 cp++;
6460 }
6461
6462 /* Get the parameter value */
6463 pval = cp;
6464
6465 if (*cp != '\'')
6466 {
6467 cp2 = pval;
6468 while (*cp)
6469 {
6470 if (isspace((unsigned char) *cp))
6471 {
6472 *cp++ = '\0';
6473 break;
6474 }
6475 if (*cp == '\\')
6476 {
6477 cp++;
6478 if (*cp != '\0')
6479 *cp2++ = *cp++;
6480 }
6481 else
6482 *cp2++ = *cp++;
6483 }
6484 *cp2 = '\0';
6485 }
6486 else
6487 {
6488 cp2 = pval;
6489 cp++;
6490 for (;;)
6491 {
6492 if (*cp == '\0')
6493 {
6494 libpq_append_error(errorMessage, "unterminated quoted string in connection info string");
6496 free(buf);
6497 return NULL;
6498 }
6499 if (*cp == '\\')
6500 {
6501 cp++;
6502 if (*cp != '\0')
6503 *cp2++ = *cp++;
6504 continue;
6505 }
6506 if (*cp == '\'')
6507 {
6508 *cp2 = '\0';
6509 cp++;
6510 break;
6511 }
6512 *cp2++ = *cp++;
6513 }
6514 }
6515
6516 /*
6517 * Now that we have the name and the value, store the record.
6518 */
6519 if (!conninfo_storeval(options, pname, pval, errorMessage, false, false))
6520 {
6522 free(buf);
6523 return NULL;
6524 }
6525 }
6526
6527 /* Done with the modifiable input string */
6528 free(buf);
6529
6530 /*
6531 * Add in defaults if the caller wants that.
6532 */
6533 if (use_defaults)
6534 {
6535 if (!conninfo_add_defaults(options, errorMessage))
6536 {
6538 return NULL;
6539 }
6540 }
6541
6542 return options;
6543}
static PQconninfoOption * conninfo_storeval(PQconninfoOption *connOptions, const char *keyword, const char *value, PQExpBuffer errorMessage, bool ignoreMissing, bool uri_decode)
static char buf[DEFAULT_XLOG_SEG_SIZE]

References buf, conninfo_add_defaults(), conninfo_init(), conninfo_storeval(), fb(), free, libpq_append_error(), 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 7432 of file fe-connect.c.

7436{
7438 char *value_copy;
7439
7440 /*
7441 * For backwards compatibility, requiressl=1 gets translated to
7442 * sslmode=require, and requiressl=0 gets translated to sslmode=prefer
7443 * (which is the default for sslmode).
7444 */
7445 if (strcmp(keyword, "requiressl") == 0)
7446 {
7447 keyword = "sslmode";
7448 if (value[0] == '1')
7449 value = "require";
7450 else
7451 value = "prefer";
7452 }
7453
7454 option = conninfo_find(connOptions, keyword);
7455 if (option == NULL)
7456 {
7457 if (!ignoreMissing)
7458 libpq_append_error(errorMessage,
7459 "invalid connection option \"%s\"",
7460 keyword);
7461 return NULL;
7462 }
7463
7464 if (uri_decode)
7465 {
7466 value_copy = conninfo_uri_decode(value, errorMessage);
7467 if (value_copy == NULL)
7468 /* conninfo_uri_decode already set an error message */
7469 return NULL;
7470 }
7471 else
7472 {
7474 if (value_copy == NULL)
7475 {
7476 libpq_append_error(errorMessage, "out of memory");
7477 return NULL;
7478 }
7479 }
7480
7481 free(option->val);
7483
7484 return option;
7485}
static char * conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
static struct @174 value

References conninfo_find(), conninfo_uri_decode(), fb(), 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 7285 of file fe-connect.c.

7286{
7287 char *buf; /* result */
7288 char *p; /* output location */
7289 const char *q = str; /* input location */
7290
7291 buf = malloc(strlen(str) + 1);
7292 if (buf == NULL)
7293 {
7294 libpq_append_error(errorMessage, "out of memory");
7295 return NULL;
7296 }
7297 p = buf;
7298
7299 /* skip leading whitespaces */
7300 for (const char *s = q; *s == ' '; s++)
7301 {
7302 q++;
7303 continue;
7304 }
7305
7306 for (;;)
7307 {
7308 if (*q != '%')
7309 {
7310 /* if found a whitespace or NUL, the string ends */
7311 if (*q == ' ' || *q == '\0')
7312 goto end;
7313
7314 /* copy character */
7315 *(p++) = *(q++);
7316 }
7317 else
7318 {
7319 int hi;
7320 int lo;
7321 int c;
7322
7323 ++q; /* skip the percent sign itself */
7324
7325 /*
7326 * Possible EOL will be caught by the first call to
7327 * get_hexdigit(), so we never dereference an invalid q pointer.
7328 */
7329 if (!(get_hexdigit(*q++, &hi) && get_hexdigit(*q++, &lo)))
7330 {
7331 libpq_append_error(errorMessage,
7332 "invalid percent-encoded token: \"%s\"",
7333 str);
7334 free(buf);
7335 return NULL;
7336 }
7337
7338 c = (hi << 4) | lo;
7339 if (c == 0)
7340 {
7341 libpq_append_error(errorMessage,
7342 "forbidden value %%00 in percent-encoded value: \"%s\"",
7343 str);
7344 free(buf);
7345 return NULL;
7346 }
7347 *(p++) = c;
7348 }
7349 }
7350
7351end:
7352
7353 /* skip trailing whitespaces */
7354 for (const char *s = q; *s == ' '; s++)
7355 {
7356 q++;
7357 continue;
7358 }
7359
7360 /* Not at the end of the string yet? Fail. */
7361 if (*q != '\0')
7362 {
7363 libpq_append_error(errorMessage,
7364 "unexpected spaces found in \"%s\", use percent-encoded spaces (%%20) instead",
7365 str);
7366 free(buf);
7367 return NULL;
7368 }
7369
7370 /* Copy NUL terminator */
7371 *p = '\0';
7372
7373 return buf;
7374}
static bool get_hexdigit(char digit, int *value)
const char * str
char * c

References buf, fb(), 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 6858 of file fe-connect.c.

6860{
6862
6863 /* Make a working copy of PQconninfoOptions */
6864 options = conninfo_init(errorMessage);
6865 if (options == NULL)
6866 return NULL;
6867
6868 if (!conninfo_uri_parse_options(options, uri, errorMessage))
6869 {
6871 return NULL;
6872 }
6873
6874 /*
6875 * Add in defaults if the caller wants that.
6876 */
6877 if (use_defaults)
6878 {
6879 if (!conninfo_add_defaults(options, errorMessage))
6880 {
6882 return NULL;
6883 }
6884 }
6885
6886 return options;
6887}
static bool conninfo_uri_parse_options(PQconninfoOption *options, const char *uri, PQExpBuffer errorMessage)

References conninfo_add_defaults(), conninfo_init(), conninfo_uri_parse_options(), fb(), 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 6911 of file fe-connect.c.

6913{
6914 int prefix_len;
6915 char *p;
6916 char *buf = NULL;
6917 char *start;
6918 char prevchar = '\0';
6919 char *user = NULL;
6920 char *host = NULL;
6921 bool retval = false;
6924
6928 {
6929 libpq_append_error(errorMessage, "out of memory");
6930 goto cleanup;
6931 }
6932
6933 /* need a modifiable copy of the input URI */
6934 buf = strdup(uri);
6935 if (buf == NULL)
6936 {
6937 libpq_append_error(errorMessage, "out of memory");
6938 goto cleanup;
6939 }
6940 start = buf;
6941
6942 /* Skip the URI prefix */
6944 if (prefix_len == 0)
6945 {
6946 /* Should never happen */
6947 libpq_append_error(errorMessage,
6948 "invalid URI propagated to internal parser routine: \"%s\"",
6949 uri);
6950 goto cleanup;
6951 }
6952 start += prefix_len;
6953 p = start;
6954
6955 /* Look ahead for possible user credentials designator */
6956 while (*p && *p != '@' && *p != '/')
6957 ++p;
6958 if (*p == '@')
6959 {
6960 /*
6961 * Found username/password designator, so URI should be of the form
6962 * "scheme://user[:password]@[netloc]".
6963 */
6964 user = start;
6965
6966 p = user;
6967 while (*p != ':' && *p != '@')
6968 ++p;
6969
6970 /* Save last char and cut off at end of user name */
6971 prevchar = *p;
6972 *p = '\0';
6973
6974 if (*user &&
6975 !conninfo_storeval(options, "user", user,
6976 errorMessage, false, true))
6977 goto cleanup;
6978
6979 if (prevchar == ':')
6980 {
6981 const char *password = p + 1;
6982
6983 while (*p != '@')
6984 ++p;
6985 *p = '\0';
6986
6987 if (*password &&
6988 !conninfo_storeval(options, "password", password,
6989 errorMessage, false, true))
6990 goto cleanup;
6991 }
6992
6993 /* Advance past end of parsed user name or password token */
6994 ++p;
6995 }
6996 else
6997 {
6998 /*
6999 * No username/password designator found. Reset to start of URI.
7000 */
7001 p = start;
7002 }
7003
7004 /*
7005 * There may be multiple netloc[:port] pairs, each separated from the next
7006 * by a comma. When we initially enter this loop, "p" has been
7007 * incremented past optional URI credential information at this point and
7008 * now points at the "netloc" part of the URI. On subsequent loop
7009 * iterations, "p" has been incremented past the comma separator and now
7010 * points at the start of the next "netloc".
7011 */
7012 for (;;)
7013 {
7014 /*
7015 * Look for IPv6 address.
7016 */
7017 if (*p == '[')
7018 {
7019 host = ++p;
7020 while (*p && *p != ']')
7021 ++p;
7022 if (!*p)
7023 {
7024 libpq_append_error(errorMessage,
7025 "end of string reached when looking for matching \"]\" in IPv6 host address in URI: \"%s\"",
7026 uri);
7027 goto cleanup;
7028 }
7029 if (p == host)
7030 {
7031 libpq_append_error(errorMessage,
7032 "IPv6 host address may not be empty in URI: \"%s\"",
7033 uri);
7034 goto cleanup;
7035 }
7036
7037 /* Cut off the bracket and advance */
7038 *(p++) = '\0';
7039
7040 /*
7041 * The address may be followed by a port specifier or a slash or a
7042 * query or a separator comma.
7043 */
7044 if (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',')
7045 {
7046 libpq_append_error(errorMessage,
7047 "unexpected character \"%c\" at position %d in URI (expected \":\" or \"/\"): \"%s\"",
7048 *p, (int) (p - buf + 1), uri);
7049 goto cleanup;
7050 }
7051 }
7052 else
7053 {
7054 /* not an IPv6 address: DNS-named or IPv4 netloc */
7055 host = p;
7056
7057 /*
7058 * Look for port specifier (colon) or end of host specifier
7059 * (slash) or query (question mark) or host separator (comma).
7060 */
7061 while (*p && *p != ':' && *p != '/' && *p != '?' && *p != ',')
7062 ++p;
7063 }
7064
7065 /* Save the hostname terminator before we null it */
7066 prevchar = *p;
7067 *p = '\0';
7068
7070
7071 if (prevchar == ':')
7072 {
7073 const char *port = ++p; /* advance past host terminator */
7074
7075 while (*p && *p != '/' && *p != '?' && *p != ',')
7076 ++p;
7077
7078 prevchar = *p;
7079 *p = '\0';
7080
7082 }
7083
7084 if (prevchar != ',')
7085 break;
7086 ++p; /* advance past comma separator */
7089 }
7090
7091 /* Save final values for host and port. */
7093 goto cleanup;
7094 if (hostbuf.data[0] &&
7095 !conninfo_storeval(options, "host", hostbuf.data,
7096 errorMessage, false, true))
7097 goto cleanup;
7098 if (portbuf.data[0] &&
7099 !conninfo_storeval(options, "port", portbuf.data,
7100 errorMessage, false, true))
7101 goto cleanup;
7102
7103 if (prevchar && prevchar != '?')
7104 {
7105 const char *dbname = ++p; /* advance past host terminator */
7106
7107 /* Look for query parameters */
7108 while (*p && *p != '?')
7109 ++p;
7110
7111 prevchar = *p;
7112 *p = '\0';
7113
7114 /*
7115 * Avoid setting dbname to an empty string, as it forces the default
7116 * value (username) and ignores $PGDATABASE, as opposed to not setting
7117 * it at all.
7118 */
7119 if (*dbname &&
7120 !conninfo_storeval(options, "dbname", dbname,
7121 errorMessage, false, true))
7122 goto cleanup;
7123 }
7124
7125 if (prevchar)
7126 {
7127 ++p; /* advance past terminator */
7128
7129 if (!conninfo_uri_parse_params(p, options, errorMessage))
7130 goto cleanup;
7131 }
7132
7133 /* everything parsed okay */
7134 retval = true;
7135
7136cleanup:
7139 free(buf);
7140 return retval;
7141}
static void cleanup(void)
Definition bootstrap.c:838
static int uri_prefix_length(const char *connstr)
static bool conninfo_uri_parse_params(char *params, PQconninfoOption *connOptions, PQExpBuffer errorMessage)
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)
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
void termPQExpBuffer(PQExpBuffer str)
#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(), dbname, fb(), 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 7152 of file fe-connect.c.

7155{
7156 while (*params)
7157 {
7158 char *keyword = params;
7159 char *value = NULL;
7160 char *p = params;
7161 bool malloced = false;
7162 int oldmsglen;
7163
7164 /*
7165 * Scan the params string for '=' and '&', marking the end of keyword
7166 * and value respectively.
7167 */
7168 for (;;)
7169 {
7170 if (*p == '=')
7171 {
7172 /* Was there '=' already? */
7173 if (value != NULL)
7174 {
7175 libpq_append_error(errorMessage,
7176 "extra key/value separator \"=\" in URI query parameter: \"%s\"",
7177 keyword);
7178 return false;
7179 }
7180 /* Cut off keyword, advance to value */
7181 *p++ = '\0';
7182 value = p;
7183 }
7184 else if (*p == '&' || *p == '\0')
7185 {
7186 /*
7187 * If not at the end, cut off value and advance; leave p
7188 * pointing to start of the next parameter, if any.
7189 */
7190 if (*p != '\0')
7191 *p++ = '\0';
7192 /* Was there '=' at all? */
7193 if (value == NULL)
7194 {
7195 libpq_append_error(errorMessage,
7196 "missing key/value separator \"=\" in URI query parameter: \"%s\"",
7197 keyword);
7198 return false;
7199 }
7200 /* Got keyword and value, go process them. */
7201 break;
7202 }
7203 else
7204 ++p; /* Advance over all other bytes. */
7205 }
7206
7207 keyword = conninfo_uri_decode(keyword, errorMessage);
7208 if (keyword == NULL)
7209 {
7210 /* conninfo_uri_decode already set an error message */
7211 return false;
7212 }
7213 value = conninfo_uri_decode(value, errorMessage);
7214 if (value == NULL)
7215 {
7216 /* conninfo_uri_decode already set an error message */
7217 free(keyword);
7218 return false;
7219 }
7220 malloced = true;
7221
7222 /*
7223 * Special keyword handling for improved JDBC compatibility.
7224 */
7225 if (strcmp(keyword, "ssl") == 0 &&
7226 strcmp(value, "true") == 0)
7227 {
7228 free(keyword);
7229 free(value);
7230 malloced = false;
7231
7232 keyword = "sslmode";
7233 value = "require";
7234 }
7235
7236 /*
7237 * Store the value if the corresponding option exists; ignore
7238 * otherwise. At this point both keyword and value are not
7239 * URI-encoded.
7240 */
7241 oldmsglen = errorMessage->len;
7242 if (!conninfo_storeval(connOptions, keyword, value,
7243 errorMessage, true, false))
7244 {
7245 /* Insert generic message if conninfo_storeval didn't give one. */
7246 if (errorMessage->len == oldmsglen)
7247 libpq_append_error(errorMessage,
7248 "invalid URI query parameter: \"%s\"",
7249 keyword);
7250 /* And fail. */
7251 if (malloced)
7252 {
7253 free(keyword);
7254 free(value);
7255 }
7256 return false;
7257 }
7258
7259 if (malloced)
7260 {
7261 free(keyword);
7262 free(value);
7263 }
7264
7265 /* Proceed to next key=value pair, if any */
7266 params = p;
7267 }
7268
7269 return true;
7270}

References conninfo_storeval(), conninfo_uri_decode(), fb(), 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 1116 of file fe-connect.c.

1117{
1118 int n;
1119
1120 n = 1;
1121 for (; *input != '\0'; input++)
1122 {
1123 if (*input == ',')
1124 n++;
1125 }
1126
1127 return n;
1128}
FILE * input

References input.

Referenced by pqConnectOptions2().

◆ default_threadlock()

static void default_threadlock ( int  acquire)
static

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

8390{
8392
8393 if (acquire)
8394 {
8396 Assert(false);
8397 }
8398 else
8399 {
8401 Assert(false);
8402 }
8403}
int pthread_mutex_unlock(pthread_mutex_t *mp)
int pthread_mutex_lock(pthread_mutex_t *mp)
#define PTHREAD_MUTEX_INITIALIZER

References Assert, fb(), 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 7956 of file fe-connect.c.

7957{
7958 (void) arg; /* not used */
7959 /* Note: we expect the supplied string to end with a newline already. */
7960 fprintf(stderr, "%s", message);
7961}
#define fprintf(file, fmt, msg)
Definition cubescan.l:21
Datum arg
Definition elog.c:1322

References arg, fb(), and fprintf.

Referenced by pqMakeEmptyPGconn().

◆ defaultNoticeReceiver()

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

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

7942{
7943 (void) arg; /* not used */
7944 if (res->noticeHooks.noticeProc != NULL)
7947}
#define PQresultErrorMessage
void * noticeProcArg
Definition libpq-int.h:152
PQnoticeProcessor noticeProc
Definition libpq-int.h:151
PGNoticeHooks noticeHooks
Definition libpq-int.h:183

References arg, fb(), 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 2418 of file fe-connect.c.

2419{
2420 if (conn->raddr.addr.ss_family == AF_UNIX)
2421 {
2422 char service[NI_MAXHOST];
2423
2425 NULL, 0,
2426 service, sizeof(service),
2429 libpq_gettext("connection to server on socket \"%s\" failed: "),
2430 service);
2431 }
2432 else
2433 {
2434 const char *displayed_host;
2435 const char *displayed_port;
2436
2437 /* To which host and port were we actually connecting? */
2440 else
2443 if (displayed_port == NULL || displayed_port[0] == '\0')
2445
2446 /*
2447 * If the user did not supply an IP address using 'hostaddr', and
2448 * 'host' was missing or does not match our lookup, display the
2449 * looked-up IP address.
2450 */
2452 host_addr[0] &&
2455 libpq_gettext("connection to server at \"%s\" (%s), port %s failed: "),
2458 else
2460 libpq_gettext("connection to server at \"%s\", port %s failed: "),
2463 }
2464}
int pg_getnameinfo_all(const struct sockaddr_storage *addr, int salen, char *node, int nodelen, char *service, int servicelen, int flags)
Definition ip.c:117
@ 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:481
pg_conn_host * connhost
Definition libpq-int.h:482

References SockAddr::addr, appendPQExpBuffer(), CHT_HOST_ADDRESS, conn, pg_conn::connhost, pg_conn::errorMessage, fb(), 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 1198 of file fe-connect.c.

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

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

1001{
1003
1004 for (option = PQconninfoOptions; option->keyword; option++)
1005 {
1006 if (option->connofs >= 0)
1007 {
1008 const char *tmp = conninfo_getval(connOptions, option->keyword);
1009
1010 if (tmp)
1011 {
1012 char **connmember = (char **) ((char *) conn + option->connofs);
1013
1014 free(*connmember);
1015 *connmember = strdup(tmp);
1016 if (*connmember == NULL)
1017 {
1018 libpq_append_conn_error(conn, "out of memory");
1019 return false;
1020 }
1021 }
1022 }
1023 }
1024
1025 return true;
1026}
static const char * conninfo_getval(PQconninfoOption *connOptions, const char *keyword)

References conn, conninfo_getval(), fb(), free, libpq_append_conn_error(), and PQconninfoOptions.

Referenced by connectOptions1(), and PQconnectStartParams().

◆ freePGconn()

static void freePGconn ( PGconn conn)
static

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

5088{
5089 /* let any event procs clean up their state data */
5090 for (int i = 0; i < conn->nEvents; i++)
5091 {
5093
5094 evt.conn = conn;
5097 free(conn->events[i].name);
5098 }
5099
5100 /* free everything not freed in pqClosePGconn */
5101 free(conn->pghost);
5103 free(conn->pgport);
5108 free(conn->appname);
5110 free(conn->dbName);
5114 free(conn->pguser);
5115 if (conn->pgpass)
5116 {
5118 free(conn->pgpass);
5119 }
5126 free(conn->sslmode);
5129 free(conn->sslkey);
5130 free(conn->sslcert);
5131 if (conn->sslpassword)
5132 {
5135 }
5138 free(conn->sslcrl);
5140 free(conn->sslsni);
5144 free(conn->gsslib);
5162 /* Note that conn->Pfdebug is not ours to close or free */
5163 free(conn->events);
5165 free(conn->connip);
5169 /* if this is a cancel connection, be_cancel_key may still be allocated */
5171 free(conn->inBuffer);
5173 free(conn->rowBuf);
5176
5177 free(conn);
5178}
static void release_conn_addrinfo(PGconn *conn)
void pqReleaseConnHosts(PGconn *conn)
@ PGEVT_CONNDESTROY
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:554
char * replication
Definition libpq-int.h:391
uint8 * scram_client_key_binary
Definition libpq-int.h:545
char * sslrootcert
Definition libpq-int.h:413
PGdataValue * rowBuf
Definition libpq-int.h:593
char * sslnegotiation
Definition libpq-int.h:407
char * sslcompression
Definition libpq-int.h:408
char * oauth_discovery_uri
Definition libpq-int.h:441
char * oauth_scope
Definition libpq-int.h:445
char * require_auth
Definition libpq-int.h:428
char * inBuffer
Definition libpq-int.h:576
char * channel_binding
Definition libpq-int.h:398
char * sslcrldir
Definition libpq-int.h:415
char * gssdelegation
Definition libpq-int.h:422
char * pgoptions
Definition libpq-int.h:387
char * sslcrl
Definition libpq-int.h:414
char * pghost
Definition libpq-int.h:374
char * ssl_max_protocol_version
Definition libpq-int.h:426
uint8 * scram_server_key_binary
Definition libpq-int.h:547
char * pgpass
Definition libpq-int.h:396
char * dbName
Definition libpq-int.h:390
char * oauth_client_id
Definition libpq-int.h:443
char * oauth_issuer
Definition libpq-int.h:439
char * fbappname
Definition libpq-int.h:389
char * sslcert
Definition libpq-int.h:410
char * sslcertmode
Definition libpq-int.h:412
char * target_session_attrs
Definition libpq-int.h:427
char * sslpassword
Definition libpq-int.h:411
PQExpBufferData workBuffer
Definition libpq-int.h:687
char * keepalives_idle
Definition libpq-int.h:401
char * connip
Definition libpq-int.h:483
char * pgservicefile
Definition libpq-int.h:393
char * oauth_client_secret
Definition libpq-int.h:444
char * max_protocol_version
Definition libpq-int.h:424
char * load_balance_hosts
Definition libpq-int.h:429
char * pguser
Definition libpq-int.h:395
char * keepalives
Definition libpq-int.h:400
char * min_protocol_version
Definition libpq-int.h:423
char * client_encoding_initial
Definition libpq-int.h:386
char * keepalives_interval
Definition libpq-int.h:402
char * appname
Definition libpq-int.h:388
char * sslmode
Definition libpq-int.h:406
char * pgtcp_user_timeout
Definition libpq-int.h:385
char * ssl_min_protocol_version
Definition libpq-int.h:425
char * oauth_issuer_id
Definition libpq-int.h:440
char * gssencmode
Definition libpq-int.h:418
char * scram_server_key
Definition libpq-int.h:431
int nEvents
Definition libpq-int.h:458
char * pghostaddr
Definition libpq-int.h:378
char * sslkey
Definition libpq-int.h:409
char * scram_client_key
Definition libpq-int.h:430
char * sslkeylogfile
Definition libpq-int.h:432
char * pgpassfile
Definition libpq-int.h:397
char * connect_timeout
Definition libpq-int.h:384
char * krbsrvname
Definition libpq-int.h:419
char * gsslib
Definition libpq-int.h:420
char * pgport
Definition libpq-int.h:382
char * pgservice
Definition libpq-int.h:392
char * keepalives_count
Definition libpq-int.h:404
char * requirepeer
Definition libpq-int.h:417
char * sslsni
Definition libpq-int.h:416
PGEvent * events
Definition libpq-int.h:457
char * outBuffer
Definition libpq-int.h:583

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(), fb(), 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::pgservicefile, 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 7385 of file fe-connect.c.

7386{
7387 if ('0' <= digit && digit <= '9')
7388 *value = digit - '0';
7389 else if ('A' <= digit && digit <= 'F')
7390 *value = digit - 'A' + 10;
7391 else if ('a' <= digit && digit <= 'f')
7392 *value = digit - 'a' + 10;
7393 else
7394 return false;
7395
7396 return true;
7397}

References fb(), and value.

Referenced by conninfo_uri_decode().

◆ getHostaddr()

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

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

2386{
2387 struct sockaddr_storage *addr = &conn->raddr.addr;
2388
2389 if (addr->ss_family == AF_INET)
2390 {
2392 &((struct sockaddr_in *) addr)->sin_addr.s_addr,
2393 32,
2395 host_addr[0] = '\0';
2396 }
2397 else if (addr->ss_family == AF_INET6)
2398 {
2400 &((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr,
2401 128,
2403 host_addr[0] = '\0';
2404 }
2405 else
2406 host_addr[0] = '\0';
2407}
char * pg_inet_net_ntop(int af, const void *src, int bits, char *dst, size_t size)

References SockAddr::addr, conn, fb(), 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 1233 of file fe-connect.c.

1234{
1235 for (int i = 0; i < lengthof(conn->allowed_sasl_mechs); i++)
1236 {
1237 if (conn->allowed_sasl_mechs[i] == mech)
1238 return i;
1239 }
1240
1241 return -1;
1242}

References pg_conn::allowed_sasl_mechs, conn, fb(), i, and lengthof.

Referenced by pqConnectOptions2().

◆ init_allowed_encryption_methods()

static bool init_allowed_encryption_methods ( PGconn conn)
static

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

4744{
4745 if (conn->raddr.addr.ss_family == AF_UNIX)
4746 {
4747 /* Don't request SSL or GSSAPI over Unix sockets */
4749
4750 /*
4751 * XXX: we probably should not do this. sslmode=require works
4752 * differently
4753 */
4754 if (conn->gssencmode[0] == 'r')
4755 {
4757 "GSSAPI encryption required but it is not supported over a local socket");
4760 return false;
4761 }
4762
4765 return true;
4766 }
4767
4768 /* initialize based on sslmode and gssencmode */
4770
4771#ifdef USE_SSL
4772 /* sslmode anything but 'disable', and GSSAPI not required */
4773 if (conn->sslmode[0] != 'd' && conn->gssencmode[0] != 'r')
4774 {
4776 }
4777#endif
4778
4779#ifdef ENABLE_GSS
4780 if (conn->gssencmode[0] != 'd')
4782#endif
4783
4784 if ((conn->sslmode[0] == 'd' || conn->sslmode[0] == 'p' || conn->sslmode[0] == 'a') &&
4785 (conn->gssencmode[0] == 'd' || conn->gssencmode[0] == 'p'))
4786 {
4788 }
4789
4790 return select_next_encryption_method(conn, false);
4791}
#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:615

References SockAddr::addr, pg_conn::allowed_enc_methods, conn, pg_conn::current_enc_method, ENC_ERROR, ENC_GSSAPI, ENC_PLAINTEXT, ENC_SSL, fb(), 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 4923 of file fe-connect.c.

4924{
4925 /* Say "no attempt" if we never got to PQconnectPoll */
4926 if (!conn || !conn->options_valid)
4927 return PQPING_NO_ATTEMPT;
4928
4929 /* Attempt to complete the connection */
4930 if (conn->status != CONNECTION_BAD)
4932
4933 /* Definitely OK if we succeeded */
4934 if (conn->status != CONNECTION_BAD)
4935 return PQPING_OK;
4936
4937 /*
4938 * Here begins the interesting part of "ping": determine the cause of the
4939 * failure in sufficient detail to decide what to return. We do not want
4940 * to report that the server is not up just because we didn't have a valid
4941 * password, for example. In fact, any sort of authentication request
4942 * implies the server is up. (We need this check since the libpq side of
4943 * things might have pulled the plug on the connection before getting an
4944 * error as such from the postmaster.)
4945 */
4947 return PQPING_OK;
4948
4949 /*
4950 * If we failed to get any ERROR response from the postmaster, report
4951 * PQPING_NO_RESPONSE. This result could be somewhat misleading for a
4952 * pre-7.4 server, since it won't send back a SQLSTATE, but those are long
4953 * out of support. Another corner case where the server could return a
4954 * failure without a SQLSTATE is fork failure, but PQPING_NO_RESPONSE
4955 * isn't totally unreasonable for that anyway. We expect that every other
4956 * failure case in a modern server will produce a report with a SQLSTATE.
4957 *
4958 * NOTE: whenever we get around to making libpq generate SQLSTATEs for
4959 * client-side errors, we should either not store those into
4960 * last_sqlstate, or add an extra flag so we can tell client-side errors
4961 * apart from server-side ones.
4962 */
4963 if (strlen(conn->last_sqlstate) != 5)
4964 return PQPING_NO_RESPONSE;
4965
4966 /*
4967 * Report PQPING_REJECT if server says it's not accepting connections.
4968 */
4970 return PQPING_REJECT;
4971
4972 /*
4973 * Any other SQLSTATE can be taken to indicate that the server is up.
4974 * Presumably it didn't like our username, password, or database name; or
4975 * perhaps it had some transient failure, but that should not be taken as
4976 * meaning "it's down".
4977 */
4978 return PQPING_OK;
4979}
#define ERRCODE_CANNOT_CONNECT_NOW
Definition fe-connect.c:95
int pqConnectDBComplete(PGconn *conn)
@ 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:507
char last_sqlstate[6]
Definition libpq-int.h:465
bool options_valid
Definition libpq-int.h:466

References pg_conn::auth_req_received, conn, CONNECTION_BAD, ERRCODE_CANNOT_CONNECT_NOW, fb(), 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 1175 of file fe-connect.c.

1176{
1177 uint64 rseed;
1178 struct timeval tval = {0};
1179
1181 return;
1182
1184
1185 rseed = ((uintptr_t) conn) ^
1186 ((uint64) getpid()) ^
1187 ((uint64) tval.tv_usec) ^
1188 ((uint64) tval.tv_sec);
1189
1191}
uint64_t uint64
Definition c.h:559
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:563
int gettimeofday(struct timeval *tp, void *tzp)

References conn, fb(), 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 1140 of file fe-connect.c.

1141{
1142 char *p;
1143 char *s = *startptr;
1144 char *e;
1145 size_t len;
1146
1147 /*
1148 * Search for the end of the current element; a comma or end-of-string
1149 * acts as a terminator.
1150 */
1151 e = s;
1152 while (*e != '\0' && *e != ',')
1153 ++e;
1154 *more = (*e == ',');
1155
1156 len = e - s;
1157 p = (char *) malloc(sizeof(char) * (len + 1));
1158 if (p)
1159 {
1160 memcpy(p, s, len);
1161 p[len] = '\0';
1162 }
1163 *startptr = e + 1;
1164
1165 return p;
1166}
const void size_t len
e

References fb(), 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 6335 of file fe-connect.c.

6337{
6338 /* Parse as URI if connection string matches URI prefix */
6339 if (uri_prefix_length(connstr) != 0)
6340 return conninfo_uri_parse(connstr, errorMessage, use_defaults);
6341
6342 /* Parse as default otherwise */
6343 return conninfo_parse(connstr, errorMessage, use_defaults);
6344}
static PQconninfoOption * conninfo_uri_parse(const char *uri, PQExpBuffer errorMessage, bool use_defaults)
static PQconninfoOption * conninfo_parse(const char *conninfo, PQExpBuffer errorMessage, bool use_defaults)
static const char * connstr
Definition pg_dumpall.c:94

References conninfo_parse(), conninfo_uri_parse(), connstr, fb(), 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 6059 of file fe-connect.c.

6064{
6065 int result = 0,
6066 linenr = 0,
6067 i;
6068 FILE *f;
6069 char *line;
6070 char buf[1024];
6071
6072 *group_found = false;
6073
6074 f = fopen(serviceFile, "r");
6075 if (f == NULL)
6076 {
6077 libpq_append_error(errorMessage, "service file \"%s\" not found", serviceFile);
6078 return 1;
6079 }
6080
6081 while ((line = fgets(buf, sizeof(buf), f)) != NULL)
6082 {
6083 int len;
6084
6085 linenr++;
6086
6087 if (strlen(line) >= sizeof(buf) - 1)
6088 {
6089 libpq_append_error(errorMessage,
6090 "line %d too long in service file \"%s\"",
6091 linenr,
6092 serviceFile);
6093 result = 2;
6094 goto exit;
6095 }
6096
6097 /* ignore whitespace at end of line, especially the newline */
6098 len = strlen(line);
6099 while (len > 0 && isspace((unsigned char) line[len - 1]))
6100 line[--len] = '\0';
6101
6102 /* ignore leading whitespace too */
6103 while (*line && isspace((unsigned char) line[0]))
6104 line++;
6105
6106 /* ignore comments and empty lines */
6107 if (line[0] == '\0' || line[0] == '#')
6108 continue;
6109
6110 /* Check for right groupname */
6111 if (line[0] == '[')
6112 {
6113 if (*group_found)
6114 {
6115 /* end of desired group reached; return success */
6116 goto exit;
6117 }
6118
6119 if (strncmp(line + 1, service, strlen(service)) == 0 &&
6120 line[strlen(service) + 1] == ']')
6121 *group_found = true;
6122 else
6123 *group_found = false;
6124 }
6125 else
6126 {
6127 if (*group_found)
6128 {
6129 /*
6130 * Finally, we are in the right group and can parse the line
6131 */
6132 char *key,
6133 *val;
6134 bool found_keyword;
6135
6136#ifdef USE_LDAP
6137 if (strncmp(line, "ldap", 4) == 0)
6138 {
6139 int rc = ldapServiceLookup(line, options, errorMessage);
6140
6141 /* if rc = 2, go on reading for fallback */
6142 switch (rc)
6143 {
6144 case 0:
6145 goto exit;
6146 case 1:
6147 case 3:
6148 result = 3;
6149 goto exit;
6150 case 2:
6151 continue;
6152 }
6153 }
6154#endif
6155
6156 key = line;
6157 val = strchr(line, '=');
6158 if (val == NULL)
6159 {
6160 libpq_append_error(errorMessage,
6161 "syntax error in service file \"%s\", line %d",
6163 linenr);
6164 result = 3;
6165 goto exit;
6166 }
6167 *val++ = '\0';
6168
6169 if (strcmp(key, "service") == 0)
6170 {
6171 libpq_append_error(errorMessage,
6172 "nested \"service\" specifications not supported in service file \"%s\", line %d",
6174 linenr);
6175 result = 3;
6176 goto exit;
6177 }
6178
6179 if (strcmp(key, "servicefile") == 0)
6180 {
6181 libpq_append_error(errorMessage,
6182 "nested \"servicefile\" specifications not supported in service file \"%s\", line %d",
6184 linenr);
6185 result = 3;
6186 goto exit;
6187 }
6188
6189 /*
6190 * Set the parameter --- but don't override any previous
6191 * explicit setting.
6192 */
6193 found_keyword = false;
6194 for (i = 0; options[i].keyword; i++)
6195 {
6196 if (strcmp(options[i].keyword, key) == 0)
6197 {
6198 if (options[i].val == NULL)
6199 options[i].val = strdup(val);
6200 if (!options[i].val)
6201 {
6202 libpq_append_error(errorMessage, "out of memory");
6203 result = 3;
6204 goto exit;
6205 }
6206 found_keyword = true;
6207 break;
6208 }
6209 }
6210
6211 if (!found_keyword)
6212 {
6213 libpq_append_error(errorMessage,
6214 "syntax error in service file \"%s\", line %d",
6216 linenr);
6217 result = 3;
6218 goto exit;
6219 }
6220 }
6221 }
6222 }
6223
6224exit:
6225
6226 /*
6227 * If a service has been successfully found, set the "servicefile" option
6228 * if not already set. This matters when we use a default service file or
6229 * PGSERVICEFILE, where we want to be able track the value.
6230 */
6231 if (*group_found && result == 0)
6232 {
6233 for (i = 0; options[i].keyword; i++)
6234 {
6235 if (strcmp(options[i].keyword, "servicefile") != 0)
6236 continue;
6237
6238 /* If value is already set, nothing to do */
6239 if (options[i].val != NULL)
6240 break;
6241
6242 options[i].val = strdup(serviceFile);
6243 if (options[i].val == NULL)
6244 {
6245 libpq_append_error(errorMessage, "out of memory");
6246 result = 3;
6247 }
6248 break;
6249 }
6250 }
6251
6252 fclose(f);
6253
6254 return result;
6255}

References buf, fb(), i, len, libpq_append_error(), and val.

Referenced by parseServiceInfo().

◆ parseServiceInfo()

static int parseServiceInfo ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

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

5988{
5989 const char *service = conninfo_getval(options, "service");
5990 const char *service_fname = conninfo_getval(options, "servicefile");
5991 char serviceFile[MAXPGPATH];
5992 char *env;
5993 bool group_found = false;
5994 int status;
5995 struct stat stat_buf;
5996
5997 /*
5998 * We have to special-case the environment variable PGSERVICE here, since
5999 * this is and should be called before inserting environment defaults for
6000 * other connection options.
6001 */
6002 if (service == NULL)
6003 service = getenv("PGSERVICE");
6004
6005 /* If no service name given, nothing to do */
6006 if (service == NULL)
6007 return 0;
6008
6009 /*
6010 * First, try the "servicefile" option in connection string. Then, try
6011 * the PGSERVICEFILE environment variable. Finally, check
6012 * ~/.pg_service.conf (if that exists).
6013 */
6014 if (service_fname != NULL)
6016 else if ((env = getenv("PGSERVICEFILE")) != NULL)
6018 else
6019 {
6020 char homedir[MAXPGPATH];
6021
6022 if (!pqGetHomeDirectory(homedir, sizeof(homedir)))
6023 goto next_file;
6024 snprintf(serviceFile, MAXPGPATH, "%s/%s", homedir, ".pg_service.conf");
6025 if (stat(serviceFile, &stat_buf) != 0)
6026 goto next_file;
6027 }
6028
6029 status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
6030 if (group_found || status != 0)
6031 return status;
6032
6033next_file:
6034
6035 /*
6036 * This could be used by any application so we can't use the binary
6037 * location to find our config files.
6038 */
6039 snprintf(serviceFile, MAXPGPATH, "%s/pg_service.conf",
6040 getenv("PGSYSCONFDIR") ? getenv("PGSYSCONFDIR") : SYSCONFDIR);
6041 if (stat(serviceFile, &stat_buf) != 0)
6042 goto last_file;
6043
6044 status = parseServiceFile(serviceFile, service, options, errorMessage, &group_found);
6045 if (status != 0)
6046 return status;
6047
6048last_file:
6049 if (!group_found)
6050 {
6051 libpq_append_error(errorMessage, "definition of service \"%s\" not found", service);
6052 return 3;
6053 }
6054
6055 return 0;
6056}
static int parseServiceFile(const char *serviceFile, const char *service, PQconninfoOption *options, PQExpBuffer errorMessage, bool *group_found)
bool pqGetHomeDirectory(char *buf, int bufsize)
#define MAXPGPATH
#define snprintf
Definition port.h:260
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition strlcpy.c:45
#define stat
Definition win32_port.h:74

References conninfo_getval(), fb(), 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,
const char **  errmsg 
)
static

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

8013{
8014 FILE *fp;
8015#ifndef WIN32
8016 struct stat stat_buf;
8017#endif
8019
8020 *errmsg = NULL;
8021
8022 if (dbname == NULL || dbname[0] == '\0')
8023 return NULL;
8024
8025 if (username == NULL || username[0] == '\0')
8026 return NULL;
8027
8028 /* 'localhost' matches pghost of '' or the default socket directory */
8029 if (hostname == NULL || hostname[0] == '\0')
8031 else if (is_unixsock_path(hostname))
8032
8033 /*
8034 * We should probably use canonicalize_path(), but then we have to
8035 * bring path.c into libpq, and it doesn't seem worth it.
8036 */
8039
8040 if (port == NULL || port[0] == '\0')
8042
8043 /* If password file cannot be opened, ignore it. */
8044 fp = fopen(pgpassfile, "r");
8045 if (fp == NULL)
8046 return NULL;
8047
8048#ifndef WIN32
8049 if (fstat(fileno(fp), &stat_buf) != 0)
8050 {
8051 fclose(fp);
8052 return NULL;
8053 }
8054
8055 if (!S_ISREG(stat_buf.st_mode))
8056 {
8058 libpq_gettext("WARNING: password file \"%s\" is not a plain file\n"),
8059 pgpassfile);
8060 fclose(fp);
8061 return NULL;
8062 }
8063
8064 /* If password file is insecure, alert the user and ignore it. */
8065 if (stat_buf.st_mode & (S_IRWXG | S_IRWXO))
8066 {
8068 libpq_gettext("WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less\n"),
8069 pgpassfile);
8070 fclose(fp);
8071 return NULL;
8072 }
8073#else
8074
8075 /*
8076 * On Win32, the directory is protected, so we don't have to check the
8077 * file.
8078 */
8079#endif
8080
8081 /* Use an expansible buffer to accommodate any reasonable line length */
8083
8084 while (!feof(fp) && !ferror(fp))
8085 {
8086 /* Make sure there's a reasonable amount of room in the buffer */
8087 if (!enlargePQExpBuffer(&buf, 128))
8088 {
8089 *errmsg = libpq_gettext("out of memory");
8090 break;
8091 }
8092
8093 /* Read some data, appending it to what we already have */
8094 if (fgets(buf.data + buf.len, buf.maxlen - buf.len, fp) == NULL)
8095 break;
8096 buf.len += strlen(buf.data + buf.len);
8097
8098 /* If we don't yet have a whole line, loop around to read more */
8099 if (!(buf.len > 0 && buf.data[buf.len - 1] == '\n') && !feof(fp))
8100 continue;
8101
8102 /* ignore comments */
8103 if (buf.data[0] != '#')
8104 {
8105 char *t = buf.data;
8106 int len;
8107
8108 /* strip trailing newline and carriage return */
8109 len = pg_strip_crlf(t);
8110
8111 if (len > 0 &&
8112 (t = pwdfMatchesString(t, hostname)) != NULL &&
8113 (t = pwdfMatchesString(t, port)) != NULL &&
8114 (t = pwdfMatchesString(t, dbname)) != NULL &&
8115 (t = pwdfMatchesString(t, username)) != NULL)
8116 {
8117 /* Found a match. */
8118 char *ret,
8119 *p1,
8120 *p2;
8121
8122 ret = strdup(t);
8123
8124 fclose(fp);
8125 explicit_bzero(buf.data, buf.maxlen);
8127
8128 if (!ret)
8129 {
8130 *errmsg = libpq_gettext("out of memory");
8131 return NULL;
8132 }
8133
8134 /* De-escape password. */
8135 for (p1 = p2 = ret; *p1 != ':' && *p1 != '\0'; ++p1, ++p2)
8136 {
8137 if (*p1 == '\\' && p1[1] != '\0')
8138 ++p1;
8139 *p2 = *p1;
8140 }
8141 *p2 = '\0';
8142
8143 return ret;
8144 }
8145 }
8146
8147 /* No match, reset buffer to prepare for next line. */
8148 buf.len = 0;
8149 }
8150
8151 fclose(fp);
8152 explicit_bzero(buf.data, buf.maxlen);
8154 return NULL;
8155}
int errmsg(const char *fmt,...)
Definition elog.c:1093
#define DefaultHost
Definition fe-connect.c:121
static char * pwdfMatchesString(char *buf, const char *token)
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:66
int enlargePQExpBuffer(PQExpBuffer str, size_t needed)
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:73
#define S_ISREG(m)
Definition win32_port.h:318

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

Referenced by pqConnectOptions2().

◆ pgpassfileWarning()

static void pgpassfileWarning ( PGconn conn)
static

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

8164{
8165 /* If it was 'invalid authorization', add pgpassfile mention */
8166 /* only works with >= 9.0 servers */
8167 if (conn->password_needed &&
8169 conn->result)
8170 {
8171 const char *sqlstate = PQresultErrorField(conn->result,
8173
8174 if (sqlstate && strcmp(sqlstate, ERRCODE_INVALID_PASSWORD) == 0)
8175 libpq_append_conn_error(conn, "password retrieved from file \"%s\"",
8176 conn->pgpassfile);
8177 }
8178}
#define ERRCODE_INVALID_PASSWORD
Definition fe-connect.c:93
#define PQresultErrorField
#define PG_DIAG_SQLSTATE
char * password
Definition libpq-int.h:362
PGresult * result
Definition libpq-int.h:606
bool password_needed
Definition libpq-int.h:508

References conn, pg_conn::connhost, ERRCODE_INVALID_PASSWORD, fb(), 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 5302 of file fe-connect.c.

5303{
5304 /*
5305 * If possible, send Terminate message to close the connection politely.
5306 */
5308
5309 /*
5310 * Must reset the blocking status so a possible reconnect will work.
5311 *
5312 * Don't call PQsetnonblocking() because it will fail if it's unable to
5313 * flush the connection.
5314 */
5315 conn->nonblocking = false;
5316
5317 /*
5318 * Close the connection, reset all transient state, flush I/O buffers.
5319 * Note that this includes clearing conn's error state; we're no longer
5320 * interested in any failures associated with the old connection, and we
5321 * want a clean slate for any new connection attempt.
5322 */
5323 pqDropConnection(conn, true);
5324 conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
5329 pqClearAsyncResult(conn); /* deallocate result */
5331
5332 /*
5333 * Release addrinfo, but since cancel requests never change their addrinfo
5334 * we don't do that. Otherwise we would have to rebuild it during a
5335 * PQcancelReset.
5336 */
5337 if (!conn->cancelRequest)
5339
5340 /* Reset all state obtained from server, too */
5342}
void pqClearOAuthToken(PGconn *conn)
void pqDropConnection(PGconn *conn, bool flushInput)
Definition fe-connect.c:533
static void sendTerminateConn(PGconn *conn)
static void pqDropServerData(PGconn *conn)
Definition fe-connect.c:659
void pqClearAsyncResult(PGconn *conn)
Definition fe-exec.c:785
@ 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:923
PGTransactionStatusType xactStatus
Definition libpq-int.h:464
bool cancelRequest
Definition libpq-int.h:434
bool nonblocking
Definition libpq-int.h:467
PGAsyncStatusType asyncStatus
Definition libpq-int.h:463
PGpipelineStatus pipelineStatus
Definition libpq-int.h:469

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

2207{
2210
2211 /* We don't actually report any errors here, but callees want a buffer */
2214 return NULL; /* out of memory already :-( */
2215
2217 if (connOptions != NULL)
2218 {
2219 /* pass NULL errorBuf to ignore errors */
2221 {
2223 connOptions = NULL;
2224 }
2225 }
2226
2228 return connOptions;
2229}

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

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

◆ PQconnectdb()

PGconn * PQconnectdb ( const char conninfo)

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

827{
828 PGconn *conn = PQconnectStart(conninfo);
829
830 if (conn && conn->status != CONNECTION_BAD)
832
833 return conn;
834}
PGconn * PQconnectStart(const char *conninfo)
Definition fe-connect.c:954

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

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

◆ pqConnectDBComplete()

int pqConnectDBComplete ( PGconn conn)

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

2796{
2799 int timeout = 0;
2800 int last_whichhost = -2; /* certainly different from whichhost */
2801 int last_whichaddr = -2; /* certainly different from whichaddr */
2802
2803 if (conn == NULL || conn->status == CONNECTION_BAD)
2804 return 0;
2805
2806 /*
2807 * Set up a time limit, if connect_timeout is greater than zero.
2808 */
2809 if (conn->connect_timeout != NULL)
2810 {
2812 "connect_timeout"))
2813 {
2814 /* mark the connection as bad to report the parsing failure */
2816 return 0;
2817 }
2818 }
2819
2820 for (;;)
2821 {
2822 int ret = 0;
2823
2824 /*
2825 * (Re)start the connect_timeout timer if it's active and we are
2826 * considering a different host than we were last time through. If
2827 * we've already succeeded, though, needn't recalculate.
2828 */
2829 if (flag != PGRES_POLLING_OK &&
2830 timeout > 0 &&
2833 {
2837 }
2838
2839 /*
2840 * Wait, if necessary. Note that the initial state (just after
2841 * PQconnectStart) is to wait for the socket to select for writing.
2842 */
2843 switch (flag)
2844 {
2845 case PGRES_POLLING_OK:
2846 return 1; /* success! */
2847
2849 ret = pqWaitTimed(1, 0, conn, end_time);
2850 if (ret == -1)
2851 {
2852 /* hard failure, eg select() problem, aborts everything */
2854 return 0;
2855 }
2856 break;
2857
2859 ret = pqWaitTimed(0, 1, conn, end_time);
2860 if (ret == -1)
2861 {
2862 /* hard failure, eg select() problem, aborts everything */
2864 return 0;
2865 }
2866 break;
2867
2868 default:
2869 /* Just in case we failed to set it in PQconnectPoll */
2871 return 0;
2872 }
2873
2874 if (ret == 1) /* connect_timeout elapsed */
2875 {
2876 /*
2877 * Give up on current server/address, try the next one.
2878 */
2879 conn->try_next_addr = true;
2881 }
2882
2883 /*
2884 * Now try to advance the state machine.
2885 */
2886 if (conn->cancelRequest)
2888 else
2890 }
2891}
PostgresPollingStatusType PQcancelPoll(PGcancelConn *cancelConn)
Definition fe-cancel.c:226
PostgresPollingStatusType PQconnectPoll(PGconn *conn)
bool pqParseIntParam(const char *value, int *result, PGconn *conn, const char *context)
pg_usec_time_t PQgetCurrentTimeUSec(void)
Definition fe-misc.c:1235
int pqWaitTimed(int forRead, int forWrite, PGconn *conn, pg_usec_time_t end_time)
Definition fe-misc.c:1035
@ CONNECTION_NEEDED
Definition libpq-fe.h:100
int64_t pg_usec_time_t
Definition libpq-fe.h:238
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:540
bool try_next_addr
Definition libpq-int.h:537
char * flag(int b)
Definition test-ctype.c:33

References pg_conn::cancelRequest, conn, pg_conn::connect_timeout, CONNECTION_BAD, CONNECTION_NEEDED, end_time, fb(), 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 771 of file fe-connect.c.

774{
776
777 if (conn && conn->status != CONNECTION_BAD)
779
780 return conn;
781}
PGconn * PQconnectStartParams(const char *const *keywords, const char *const *values, int expand_dbname)
Definition fe-connect.c:873

References conn, CONNECTION_BAD, fb(), 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 2717 of file fe-connect.c.

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

References appendPQExpBufferStr(), pg_conn::cancelRequest, conn, CONNECTION_BAD, CONNECTION_NEEDED, pg_conn::errorMessage, fb(), 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 7790 of file fe-connect.c.

7791{
7792 char *password;
7793
7794 if (!conn)
7795 return false;
7796 password = PQpass(conn);
7797 if (conn->password_needed &&
7798 (password == NULL || password[0] == '\0'))
7799 return true;
7800 else
7801 return false;
7802}
char * PQpass(const PGconn *conn)

References conn, fb(), 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 7816 of file fe-connect.c.

7817{
7818 if (!conn)
7819 return false;
7820 if (conn->gssapi_used)
7821 return true;
7822 else
7823 return false;
7824}
bool gssapi_used
Definition libpq-int.h:509

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

7806{
7807 if (!conn)
7808 return false;
7809 if (conn->password_needed)
7810 return true;
7811 else
7812 return false;
7813}

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

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

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, fb(), 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_EARLIEST, PG_PROTOCOL_GREASE, 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 2921 of file fe-connect.c.

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

References SockAddr::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, ERRCODE_PROTOCOL_VIOLATION, pg_conn::errorMessage, EWOULDBLOCK, pg_conn::failed_enc_methods, fb(), pg_conn::fbappname, free, gai_strerror(), getHostaddr(), getpeereid(), pg_conn::gssencmode, 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_append_grease_info(), 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_PROTOCOL_GREASE, 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, 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_conn::result, 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, 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 954 of file fe-connect.c.

955{
956 PGconn *conn;
957
958 /*
959 * Allocate memory for the conn structure. Note that we also expect this
960 * to initialize conn->errorMessage to empty. All subsequent steps during
961 * connection initialization will only append to that buffer.
962 */
964 if (conn == NULL)
965 return NULL;
966
967 /*
968 * Parse the conninfo string
969 */
970 if (!connectOptions1(conn, conninfo))
971 return conn;
972
973 /*
974 * Compute derived options
975 */
977 return conn;
978
979 /*
980 * Connect to the database
981 */
983 {
984 /* Just in case we failed to set it in pqConnectDBStart */
986 }
987
988 return conn;
989}
static bool connectOptions1(PGconn *conn, const char *conninfo)
bool pqConnectOptions2(PGconn *conn)
PGconn * pqMakeEmptyPGconn(void)
int pqConnectDBStart(PGconn *conn)

References conn, CONNECTION_BAD, connectOptions1(), fb(), 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 873 of file fe-connect.c.

876{
877 PGconn *conn;
879
880 /*
881 * Allocate memory for the conn structure. Note that we also expect this
882 * to initialize conn->errorMessage to empty. All subsequent steps during
883 * connection initialization will only append to that buffer.
884 */
886 if (conn == NULL)
887 return NULL;
888
889 /*
890 * Parse the conninfo arrays
891 */
894 true, expand_dbname);
895 if (connOptions == NULL)
896 {
898 /* errorMessage is already set */
899 return conn;
900 }
901
902 /*
903 * Move option values into conn structure
904 */
906 {
908 return conn;
909 }
910
911 /*
912 * Free the option info - all is in conn now
913 */
915
916 /*
917 * Compute derived options
918 */
920 return conn;
921
922 /*
923 * Connect to the database
924 */
926 {
927 /* Just in case we failed to set it in pqConnectDBStart */
929 }
930
931 return conn;
932}
static PQconninfoOption * conninfo_array_parse(const char *const *keywords, const char *const *values, PQExpBuffer errorMessage, bool use_defaults, int expand_dbname)

References conn, CONNECTION_BAD, conninfo_array_parse(), pg_conn::errorMessage, fb(), 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 7514 of file fe-connect.c.

7515{
7518
7519 if (conn == NULL)
7520 return NULL;
7521
7522 /*
7523 * We don't actually report any errors here, but callees want a buffer,
7524 * and we prefer not to trash the conn's errorMessage.
7525 */
7528 return NULL; /* out of memory already :-( */
7529
7531
7532 if (connOptions != NULL)
7533 {
7535
7536 for (option = PQconninfoOptions; option->keyword; option++)
7537 {
7538 char **connmember;
7539
7540 if (option->connofs < 0)
7541 continue;
7542
7543 connmember = (char **) ((char *) conn + option->connofs);
7544
7545 if (*connmember)
7547 &errorBuf, true, false);
7548 }
7549 }
7550
7552
7553 return connOptions;
7554}

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

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

◆ PQconninfoFree()

◆ PQconninfoParse()

◆ pqCopyPGconn()

bool pqCopyPGconn ( PGconn srcConn,
PGconn dstConn 
)

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

1039{
1041
1042 /* copy over connection options */
1043 for (option = PQconninfoOptions; option->keyword; option++)
1044 {
1045 if (option->connofs >= 0)
1046 {
1047 const char **tmp = (const char **) ((char *) srcConn + option->connofs);
1048
1049 if (*tmp)
1050 {
1051 char **dstConnmember = (char **) ((char *) dstConn + option->connofs);
1052
1053 if (*dstConnmember)
1055 *dstConnmember = strdup(*tmp);
1056 if (*dstConnmember == NULL)
1057 {
1058 libpq_append_conn_error(dstConn, "out of memory");
1059 return false;
1060 }
1061 }
1062 }
1063 }
1064 return true;
1065}

References fb(), free, libpq_append_conn_error(), and PQconninfoOptions.

Referenced by PQcancelCreate().

◆ PQdb()

◆ pqDropConnection()

void pqDropConnection ( PGconn conn,
bool  flushInput 
)

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

534{
535 /* Drop any SSL state */
537
538 /* Close the socket itself */
539 if (conn->sock != PGINVALID_SOCKET)
542
543 /* Optionally discard any unread data */
544 if (flushInput)
545 conn->inStart = conn->inCursor = conn->inEnd = 0;
546
547 /* Always discard any unsent data */
548 conn->outCount = 0;
549
550 /* Likewise, discard any pending pipelined commands */
555
556 /* Free authentication/encryption state */
558 {
559 /*
560 * Any in-progress async authentication should be torn down first so
561 * that cleanup_async_auth() can depend on the other authentication
562 * state if necessary.
563 */
566 }
568 /* cleanup_async_auth() should have done this, but make sure */
570#ifdef ENABLE_GSS
571 {
573
574 if (conn->gcred != GSS_C_NO_CREDENTIAL)
575 {
576 gss_release_cred(&min_s, &conn->gcred);
577 conn->gcred = GSS_C_NO_CREDENTIAL;
578 }
579 if (conn->gctx)
581 if (conn->gtarg_nam)
582 gss_release_name(&min_s, &conn->gtarg_nam);
583 if (conn->gss_SendBuffer)
584 {
585 free(conn->gss_SendBuffer);
586 conn->gss_SendBuffer = NULL;
587 }
588 if (conn->gss_RecvBuffer)
589 {
590 free(conn->gss_RecvBuffer);
591 conn->gss_RecvBuffer = NULL;
592 }
593 if (conn->gss_ResultBuffer)
594 {
595 free(conn->gss_ResultBuffer);
596 conn->gss_ResultBuffer = NULL;
597 }
598 conn->gssenc = false;
599 }
600#endif
601#ifdef ENABLE_SSPI
602 if (conn->sspitarget)
603 {
604 free(conn->sspitarget);
605 conn->sspitarget = NULL;
606 }
607 if (conn->sspicred)
608 {
609 FreeCredentialsHandle(conn->sspicred);
610 free(conn->sspicred);
611 conn->sspicred = NULL;
612 }
613 if (conn->sspictx)
614 {
615 DeleteSecurityContext(conn->sspictx);
616 free(conn->sspictx);
617 conn->sspictx = NULL;
618 }
619 conn->usesspi = 0;
620#endif
621 if (conn->sasl_state)
622 {
625 }
626}
static void pqFreeCommandQueue(PGcmdQueueEntry *queue)
Definition fe-connect.c:633
void pqsecure_close(PGconn *conn)
Definition fe-secure.c:152
#define closesocket
Definition port.h:397
PGcmdQueueEntry * cmd_queue_recycle
Definition libpq-int.h:496
PGcmdQueueEntry * cmd_queue_tail
Definition libpq-int.h:490
void * sasl_state
Definition libpq-int.h:612
PGcmdQueueEntry * cmd_queue_head
Definition libpq-int.h:489
void(* free)(void *state)

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, fb(), 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 handleFatalError(), pqClosePGconn(), pqConnectDBStart(), PQconnectPoll(), and pqReadData().

◆ pqDropServerData()

static void pqDropServerData ( PGconn conn)
static

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

660{
662 pgParameterStatus *pstatus;
663
664 /* Forget pending notifies */
666 while (notify != NULL)
667 {
668 PGnotify *prev = notify;
669
670 notify = notify->next;
671 free(prev);
672 }
674
675 /* Reset ParameterStatus data, as well as variables deduced from it */
676 pstatus = conn->pstatus;
677 while (pstatus != NULL)
678 {
679 pgParameterStatus *prev = pstatus;
680
681 pstatus = pstatus->next;
682 free(prev);
683 }
684 conn->pstatus = NULL;
686 conn->std_strings = false;
690 conn->sversion = 0;
691
692 /* Drop large-object lookup data */
695
696 /* Reset assorted other per-connection state */
697 conn->last_sqlstate[0] = '\0';
698 conn->pversion_negotiated = false;
699 conn->auth_req_received = false;
700 conn->client_finished_auth = false;
701 conn->password_needed = false;
702 conn->gssapi_used = false;
703 conn->write_failed = false;
706 conn->oauth_want_retry = false;
707
708 /*
709 * Cancel connections need to retain their be_pid and be_cancel_key across
710 * PQcancelReset invocations, otherwise they would not have access to the
711 * secret token of the connection they are supposed to cancel.
712 */
713 if (!conn->cancelRequest)
714 {
715 conn->be_pid = 0;
716 if (conn->be_cancel_key != NULL)
717 {
720 }
722 }
723}
@ PG_SQL_ASCII
Definition pg_wchar.h:226
#define SCRAM_SHA_256_DEFAULT_ITERATIONS
struct pgNotify * next
Definition libpq-fe.h:234
struct pgParameterStatus * next
Definition libpq-int.h:271
char * write_err_msg
Definition libpq-int.h:513
PGnotify * notifyHead
Definition libpq-int.h:476
bool std_strings
Definition libpq-int.h:557
bool write_failed
Definition libpq-int.h:512
bool client_finished_auth
Definition libpq-int.h:521
PGnotify * notifyTail
Definition libpq-int.h:477
pgParameterStatus * pstatus
Definition libpq-int.h:555
int scram_sha_256_iterations
Definition libpq-int.h:613
PGlobjfuncs * lobjfuncs
Definition libpq-int.h:562
int be_cancel_key_len
Definition libpq-int.h:553

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, fb(), 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 7737 of file fe-connect.c.

7738{
7739 if (!conn)
7740 return libpq_gettext("connection pointer is NULL\n");
7741
7742 /*
7743 * The errorMessage buffer might be marked "broken" due to having
7744 * previously failed to allocate enough memory for the message. In that
7745 * case, tell the application we ran out of memory.
7746 */
7748 return libpq_gettext("out of memory\n");
7749
7750 return conn->errorMessage.data;
7751}
#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_result_status_impl(), connect_database(), connect_pg_server(), ConnectDatabase(), connectDatabase(), connectToServer(), consume_null_result_impl(), consume_query_cancel_impl(), 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(), executeCommand(), executeQuery(), executeQuery(), executeQueryOrDie(), ExecuteSqlCommand(), ExecuteSqlCommandBuf(), executeStatement(), find_publication(), get_table_relkind(), GetConnection(), 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(), main(), my_truncate(), overwrite(), pgfdw_cancel_query_end(), pgfdw_report_internal(), pickout(), PQcancelErrorMessage(), prepareCommand(), process_query_result(), process_queued_fetch_requests(), process_result(), process_slot(), ProcessWALDataMsg(), psql_get_variable(), ReceiveCopyData(), RetrieveDataDirCreatePerm(), RetrieveWalSegSize(), run_command(), run_permutation(), run_reindex_command(), run_vacuum_command(), RunIdentifySystem(), send_cancellable_query_impl(), sendFeedback(), 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 5349 of file fe-connect.c.

5350{
5351 if (conn)
5352 {
5355 }
5356}
void pqClosePGconn(PGconn *conn)
static void freePGconn(PGconn *conn)

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_replication_slots(), check_new_cluster_subscription_configuration(), check_old_cluster_global_names(), check_old_cluster_subscription_state(), CheckConnection(), cluster_all_databases(), cluster_one_database(), connect_database(), ConnectDatabase(), connectDatabase(), connectToServer(), create_conflict_detection_slot(), create_logical_replication_slots(), create_new_objects(), disconnect_atexit(), disconnect_atexit(), disconnect_atexit(), disconnect_atexit(), disconnect_atexit(), disconnect_database(), DisconnectDatabase(), disconnectDatabase(), do_connect(), doConnect(), dumpRoleGUCPrivs(), dumpRoleMembership(), dumpTablespaces(), ecpg_finish(), executeCommand(), executeCommand(), executeQuery(), executeQuery(), executeQueryOrDie(), exit_nicely(), exit_nicely(), exit_nicely(), exit_nicely(), exit_nicely(), exit_nicely(), exit_nicely(), expand_dbname_patterns(), finishCon(), get_db_infos(), get_dbnames_list_to_restore(), get_subscription_info(), get_tablespace_paths(), get_template0_info(), GetConnection(), libpqsrv_connect_internal(), libpqsrv_disconnect(), LogStreamerMain(), main(), 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_cancel(), test_protocol_version(), unicode_version_changed(), vacuum_all_databases(), vacuum_one_database(), and vacuumlo().

◆ pqFreeCommandQueue()

static void pqFreeCommandQueue ( PGcmdQueueEntry queue)
static

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

634{
635 while (queue != NULL)
636 {
637 PGcmdQueueEntry *cur = queue;
638
639 queue = cur->next;
640 free(cur->query);
641 free(cur);
642 }
643}
struct cursor * cur
Definition ecpg.c:29
struct cursor * next
Definition type.h:148

References cur, fb(), free, and cursor::next.

Referenced by pqDropConnection().

◆ PQfullProtocolVersion()

int PQfullProtocolVersion ( const PGconn conn)

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

7718{
7719 if (!conn)
7720 return 0;
7721 if (conn->status == CONNECTION_BAD)
7722 return 0;
7724}
#define PG_PROTOCOL_FULL(v)
Definition pqcomm.h:88

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

Referenced by exec_command_conninfo(), and test_protocol_version().

◆ pqGetHomeDirectory()

bool pqGetHomeDirectory ( char buf,
int  bufsize 
)

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

8266{
8267#ifndef WIN32
8268 const char *home;
8269
8270 home = getenv("HOME");
8271 if (home && home[0])
8272 {
8274 return true;
8275 }
8276 else
8277 {
8278 struct passwd pwbuf;
8279 struct passwd *pw;
8280 char tmpbuf[1024];
8281 int rc;
8282
8283 rc = getpwuid_r(geteuid(), &pwbuf, tmpbuf, sizeof tmpbuf, &pw);
8284 if (rc != 0 || !pw)
8285 return false;
8286 strlcpy(buf, pw->pw_dir, bufsize);
8287 return true;
8288 }
8289#else
8290 char tmppath[MAX_PATH];
8291
8292 ZeroMemory(tmppath, sizeof(tmppath));
8294 return false;
8295 snprintf(buf, bufsize, "%s/postgresql", tmppath);
8296 return true;
8297#endif
8298}
#define bufsize
static StringInfoData tmpbuf
Definition walsender.c:178

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

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

◆ PQhost()

char * PQhost ( const PGconn conn)

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

7605{
7606 if (!conn)
7607 return NULL;
7608
7609 if (conn->connhost != NULL)
7610 {
7611 /*
7612 * Return the verbatim host value provided by user, or hostaddr in its
7613 * lack.
7614 */
7615 if (conn->connhost[conn->whichhost].host != NULL &&
7616 conn->connhost[conn->whichhost].host[0] != '\0')
7617 return conn->connhost[conn->whichhost].host;
7618 else if (conn->connhost[conn->whichhost].hostaddr != NULL &&
7619 conn->connhost[conn->whichhost].hostaddr[0] != '\0')
7621 }
7622
7623 return "";
7624}

References conn, pg_conn::connhost, fb(), 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 7627 of file fe-connect.c.

7628{
7629 if (!conn)
7630 return NULL;
7631
7632 /* Return the parsed IP address */
7633 if (conn->connhost != NULL && conn->connip != NULL)
7634 return conn->connip;
7635
7636 return "";
7637}

References conn, pg_conn::connhost, pg_conn::connip, and fb().

Referenced by do_connect(), and exec_command_conninfo().

◆ pqMakeEmptyPGconn()

PGconn * pqMakeEmptyPGconn ( void  )

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

4988{
4989 PGconn *conn;
4990
4991#ifdef WIN32
4992
4993 /*
4994 * Make sure socket support is up and running in this process.
4995 *
4996 * Note: the Windows documentation says that we should eventually do a
4997 * matching WSACleanup() call, but experience suggests that that is at
4998 * least as likely to cause problems as fix them. So we don't.
4999 */
5000 static bool wsastartup_done = false;
5001
5002 if (!wsastartup_done)
5003 {
5005
5006 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
5007 return NULL;
5008 wsastartup_done = true;
5009 }
5010
5011 /* Forget any earlier error */
5012 WSASetLastError(0);
5013#endif /* WIN32 */
5014
5015 conn = (PGconn *) malloc(sizeof(PGconn));
5016 if (conn == NULL)
5017 return conn;
5018
5019 /* Zero all pointers and booleans */
5020 MemSet(conn, 0, sizeof(PGconn));
5021
5022 /* install default notice hooks */
5025
5030 conn->options_valid = false;
5031 conn->nonblocking = false;
5033 conn->std_strings = false; /* unless server says differently */
5041 conn->Pfdebug = NULL;
5042
5043 /*
5044 * We try to send at least 8K at a time, which is the usual size of pipe
5045 * buffers on Unix systems. That way, when we are sending a large amount
5046 * of data, we avoid incurring extra kernel context swaps for partial
5047 * bufferloads. The output buffer is initially made 16K in size, and we
5048 * try to dump it after accumulating 8K.
5049 *
5050 * With the same goal of minimizing context swaps, the input buffer will
5051 * be enlarged anytime it has less than 8K free, so we initially allocate
5052 * twice that.
5053 */
5054 conn->inBufSize = 16 * 1024;
5055 conn->inBuffer = (char *) malloc(conn->inBufSize);
5056 conn->outBufSize = 16 * 1024;
5057 conn->outBuffer = (char *) malloc(conn->outBufSize);
5058 conn->rowBufLen = 32;
5062
5063 if (conn->inBuffer == NULL ||
5064 conn->outBuffer == NULL ||
5065 conn->rowBuf == NULL ||
5068 {
5069 /* out of memory already :-( */
5071 conn = NULL;
5072 }
5073
5074 return conn;
5075}
static void defaultNoticeReceiver(void *arg, const PGresult *res)
static void defaultNoticeProcessor(void *arg, const char *message)
@ 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:577
PGVerbosity verbosity
Definition libpq-int.h:560
int rowBufLen
Definition libpq-int.h:594
int outBufSize
Definition libpq-int.h:584
PGNoticeHooks noticeHooks
Definition libpq-int.h:454
PGContextVisibility show_context
Definition libpq-int.h:561

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, fb(), 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 7666 of file fe-connect.c.

7667{
7668 if (!conn)
7669 return NULL;
7670 return conn->pgoptions;
7671}

References conn, fb(), 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 5457 of file fe-connect.c.

5459{
5460 /* Start the message. */
5462 return STATUS_ERROR;
5463
5464 /* Send the message body. */
5465 if (pqPutnchar(buf, buf_len, conn))
5466 return STATUS_ERROR;
5467
5468 /* Finish the message. */
5469 if (pqPutMsgEnd(conn))
5470 return STATUS_ERROR;
5471
5472 /* Flush to ensure backend gets it. */
5473 if (pqFlush(conn))
5474 return STATUS_ERROR;
5475
5476 return STATUS_OK;
5477}
#define STATUS_ERROR
Definition c.h:1187
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, fb(), 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 
)

◆ pqParseIntParam()

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

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

8308{
8309 char *end;
8310 long numval;
8311
8312 Assert(value != NULL);
8313
8314 *result = 0;
8315
8316 /* strtol(3) skips leading whitespaces */
8317 errno = 0;
8318 numval = strtol(value, &end, 10);
8319
8320 /*
8321 * If no progress was done during the parsing or an error happened, fail.
8322 * This tests properly for overflows of the result.
8323 */
8324 if (value == end || errno != 0 || numval != (int) numval)
8325 goto error;
8326
8327 /*
8328 * Skip any trailing whitespace; if anything but whitespace remains before
8329 * the terminating character, fail
8330 */
8331 while (*end != '\0' && isspace((unsigned char) *end))
8332 end++;
8333
8334 if (*end != '\0')
8335 goto error;
8336
8337 *result = numval;
8338 return true;
8339
8340error:
8341 libpq_append_conn_error(conn, "invalid integer value \"%s\" for connection option \"%s\"",
8342 value, context);
8343 return false;
8344}
static void error(void)

References Assert, conn, error(), fb(), 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 8351 of file fe-connect.c.

8353{
8354 if (strcmp(value, "latest") == 0)
8355 {
8356 *result = PG_PROTOCOL_LATEST;
8357 return true;
8358 }
8359 if (strcmp(value, "3.0") == 0)
8360 {
8361 *result = PG_PROTOCOL(3, 0);
8362 return true;
8363 }
8364
8365 /* 3.1 never existed, we went straight from 3.0 to 3.2 */
8366
8367 if (strcmp(value, "3.2") == 0)
8368 {
8369 *result = PG_PROTOCOL(3, 2);
8370 return true;
8371 }
8372
8373 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
8374 context, value);
8375 return false;
8376}
#define PG_PROTOCOL_LATEST
Definition pqcomm.h:95
#define PG_PROTOCOL(m, n)
Definition pqcomm.h:89

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

Referenced by pqConnectOptions2().

◆ PQpass()

char * PQpass ( const PGconn conn)

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

7588{
7589 char *password = NULL;
7590
7591 if (!conn)
7592 return NULL;
7593 if (conn->connhost != NULL)
7595 if (password == NULL)
7596 password = conn->pgpass;
7597 /* Historically we've returned "" not NULL for no password specified */
7598 if (password == NULL)
7599 password = "";
7600 return password;
7601}

References conn, pg_conn::connhost, fb(), 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 842 of file fe-connect.c.

843{
844 PGconn *conn = PQconnectStart(conninfo);
845 PGPing ret;
846
847 ret = internal_ping(conn);
848 PQfinish(conn);
849
850 return ret;
851}
static PGPing internal_ping(PGconn *conn)
void PQfinish(PGconn *conn)
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 789 of file fe-connect.c.

792{
794 PGPing ret;
795
796 ret = internal_ping(conn);
797 PQfinish(conn);
798
799 return ret;
800}

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

Referenced by main(), and regression_main().

◆ PQpipelineStatus()

◆ PQport()

char * PQport ( const PGconn conn)

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

7641{
7642 if (!conn)
7643 return NULL;
7644
7645 if (conn->connhost != NULL &&
7647 conn->connhost[conn->whichhost].port[0] != '\0')
7648 return conn->connhost[conn->whichhost].port;
7649
7650 return DEF_PGPORT_STR;
7651}

References conn, pg_conn::connhost, fb(), 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 7707 of file fe-connect.c.

7708{
7709 if (!conn)
7710 return 0;
7711 if (conn->status == CONNECTION_BAD)
7712 return 0;
7714}
#define PG_PROTOCOL_MAJOR(v)
Definition pqcomm.h:86

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

Referenced by handleCopyIn().

◆ PQregisterThreadLock()

pgthreadlock_t PQregisterThreadLock ( pgthreadlock_t  newhandler)

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

8407{
8409
8410 if (newhandler)
8412 else
8414
8415 return prev;
8416}
static void default_threadlock(int acquire)
pgthreadlock_t pg_g_threadlock
Definition fe-connect.c:517
void(* pgthreadlock_t)(int acquire)
Definition libpq-fe.h:468

References default_threadlock(), fb(), and pg_g_threadlock.

◆ pqReleaseConnHosts()

void pqReleaseConnHosts ( PGconn conn)

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

5186{
5187 if (conn->connhost)
5188 {
5189 for (int i = 0; i < conn->nconnhost; ++i)
5190 {
5191 free(conn->connhost[i].host);
5193 free(conn->connhost[i].port);
5194 if (conn->connhost[i].password != NULL)
5195 {
5199 }
5200 }
5201 free(conn->connhost);
5202 conn->connhost = NULL;
5203 }
5204}

References conn, pg_conn::connhost, explicit_bzero(), fb(), 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 5363 of file fe-connect.c.

5364{
5365 if (conn)
5366 {
5368
5370 {
5371 /*
5372 * Notify event procs of successful reset.
5373 */
5374 int i;
5375
5376 for (i = 0; i < conn->nEvents; i++)
5377 {
5379
5380 evt.conn = conn;
5383 }
5384 }
5385 }
5386}
@ PGEVT_CONNRESET

References conn, PGEventConnReset::conn, pg_conn::events, fb(), 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 5415 of file fe-connect.c.

5416{
5417 if (conn)
5418 {
5420
5421 if (status == PGRES_POLLING_OK)
5422 {
5423 /*
5424 * Notify event procs of successful reset.
5425 */
5426 int i;
5427
5428 for (i = 0; i < conn->nEvents; i++)
5429 {
5431
5432 evt.conn = conn;
5435 }
5436 }
5437
5438 return status;
5439 }
5440
5441 return PGRES_POLLING_FAILED;
5442}

References conn, PGEventConnReset::conn, pg_conn::events, fb(), 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 5396 of file fe-connect.c.

5397{
5398 if (conn)
5399 {
5401
5402 return pqConnectDBStart(conn);
5403 }
5404
5405 return 0;
5406}

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

◆ PQserverVersion()

◆ PQsetClientEncoding()

int PQsetClientEncoding ( PGconn conn,
const char encoding 
)

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

7836{
7837 char qbuf[128];
7838 static const char query[] = "set client_encoding to '%s'";
7839 PGresult *res;
7840 int status;
7841
7842 if (!conn || conn->status != CONNECTION_OK)
7843 return -1;
7844
7845 if (!encoding)
7846 return -1;
7847
7848 /* Resolve special "auto" value from the locale */
7849 if (strcmp(encoding, "auto") == 0)
7851
7852 /* check query buffer overflow */
7853 if (sizeof(qbuf) < (sizeof(query) + strlen(encoding)))
7854 return -1;
7855
7856 /* ok, now send a query */
7857 sprintf(qbuf, query, encoding);
7858 res = PQexec(conn, qbuf);
7859
7860 if (res == NULL)
7861 return -1;
7862 if (res->resultStatus != PGRES_COMMAND_OK)
7863 status = -1;
7864 else
7865 {
7866 /*
7867 * We rely on the backend to report the parameter value, and we'll
7868 * change state at that time.
7869 */
7870 status = 0; /* everything is ok */
7871 }
7872 PQclear(res);
7873 return status;
7874}
PGresult * PQexec(PGconn *conn, const char *query)
Definition fe-exec.c:2279
static char * encoding
Definition initdb.c:139
@ PGRES_COMMAND_OK
Definition libpq-fe.h:125
#define sprintf
Definition port.h:262
ExecStatusType resultStatus
Definition libpq-int.h:174

References conn, CONNECTION_OK, encoding, fb(), 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 2244 of file fe-connect.c.

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

7890{
7892
7893 if (!conn)
7894 return PQSHOW_CONTEXT_ERRORS;
7896 conn->show_context = show_context;
7897 return old;
7898}
PGContextVisibility
Definition libpq-fe.h:163

References conn, fb(), 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 7877 of file fe-connect.c.

7878{
7880
7881 if (!conn)
7882 return PQERRORS_DEFAULT;
7883 old = conn->verbosity;
7884 conn->verbosity = verbosity;
7885 return old;
7886}
PGVerbosity
Definition libpq-fe.h:155

References conn, fb(), 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 7918 of file fe-connect.c.

7919{
7921
7922 if (conn == NULL)
7923 return NULL;
7924
7926 if (proc)
7927 {
7928 conn->noticeHooks.noticeProc = proc;
7930 }
7931 return old;
7932}
void(* PQnoticeProcessor)(void *arg, const char *message)
Definition libpq-fe.h:242

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

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

◆ PQsetNoticeReceiver()

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

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

7902{
7904
7905 if (conn == NULL)
7906 return NULL;
7907
7909 if (proc)
7910 {
7911 conn->noticeHooks.noticeRec = proc;
7913 }
7914 return old;
7915}
void(* PQnoticeReceiver)(void *arg, const PGresult *res)
Definition libpq-fe.h:241
void * noticeRecArg
Definition libpq-int.h:150

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

Referenced by connect_pg_server(), dblink_connect(), dblink_get_conn(), ECPGconnect(), and libpqrcv_connect().

◆ PQsocket()

◆ PQstatus()

◆ PQtransactionStatus()

◆ PQtty()

char * PQtty ( const PGconn conn)

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

7659{
7660 if (!conn)
7661 return NULL;
7662 return "";
7663}

References conn, and fb().

◆ PQuser()

char * PQuser ( const PGconn conn)

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

7580{
7581 if (!conn)
7582 return NULL;
7583 return conn->pguser;
7584}

References conn, fb(), and pg_conn::pguser.

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

◆ pwdfMatchesString()

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

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

7969{
7970 char *tbuf;
7971 const char *ttok;
7972 bool bslash = false;
7973
7974 if (buf == NULL || token == NULL)
7975 return NULL;
7976 tbuf = buf;
7977 ttok = token;
7978 if (tbuf[0] == '*' && tbuf[1] == ':')
7979 return tbuf + 2;
7980 while (*tbuf != 0)
7981 {
7982 if (*tbuf == '\\' && !bslash)
7983 {
7984 tbuf++;
7985 bslash = true;
7986 }
7987 if (*tbuf == ':' && *ttok == 0 && !bslash)
7988 return tbuf + 1;
7989 bslash = false;
7990 if (*ttok == 0)
7991 return NULL;
7992 if (*tbuf == *ttok)
7993 {
7994 tbuf++;
7995 ttok++;
7996 }
7997 else
7998 return NULL;
7999 }
8000 return NULL;
8001}
#define token

References buf, fb(), and token.

Referenced by passwordFromFile().

◆ recognized_connection_string()

static bool recognized_connection_string ( const char connstr)
static

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

6379{
6380 return uri_prefix_length(connstr) != 0 || strchr(connstr, '=') != NULL;
6381}

References connstr, fb(), 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 5254 of file fe-connect.c.

5255{
5256 if (conn->addr)
5257 {
5258 free(conn->addr);
5259 conn->addr = NULL;
5260 }
5261}

References pg_conn::addr, conn, fb(), 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 4848 of file fe-connect.c.

4849{
4851
4852#define SELECT_NEXT_METHOD(method) \
4853 do { \
4854 if ((remaining_methods & method) != 0) \
4855 { \
4856 conn->current_enc_method = method; \
4857 return true; \
4858 } \
4859 } while (false)
4860
4861 remaining_methods = conn->allowed_enc_methods & ~conn->failed_enc_methods;
4862
4863 /*
4864 * Try GSSAPI before SSL
4865 */
4866#ifdef ENABLE_GSS
4867 if ((remaining_methods & ENC_GSSAPI) != 0)
4868 {
4869 /*
4870 * If GSSAPI encryption is enabled, then call pg_GSS_have_cred_cache()
4871 * which will return true if we can acquire credentials (and give us a
4872 * handle to use in conn->gcred), and then send a packet to the server
4873 * asking for GSSAPI Encryption (and skip past SSL negotiation and
4874 * regular startup below).
4875 */
4876 if (!conn->gctx)
4877 {
4878 if (!pg_GSS_have_cred_cache(&conn->gcred))
4879 {
4882
4883 if (conn->gssencmode[0] == 'r')
4884 {
4886 "GSSAPI encryption required but no credential cache");
4887 }
4888 }
4889 }
4890 }
4891
4893#endif
4894
4895 /*
4896 * The order between SSL encryption and plaintext depends on sslmode. With
4897 * sslmode=allow, try plaintext connection before SSL. With
4898 * sslmode=prefer, it's the other way round. With other modes, we only try
4899 * plaintext or SSL connections so the order they're listed here doesn't
4900 * matter.
4901 */
4902 if (conn->sslmode[0] == 'a')
4904
4906
4907 if (conn->sslmode[0] != 'a')
4909
4910 /* No more options */
4912 return false;
4913#undef SELECT_NEXT_METHOD
4914}
#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, fb(), 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 5268 of file fe-connect.c.

5269{
5270 /*
5271 * The Postgres cancellation protocol does not have a notion of a
5272 * Terminate message, so don't send one.
5273 */
5274 if (conn->cancelRequest)
5275 return;
5276
5277 /*
5278 * Note that the protocol doesn't allow us to send Terminate messages
5279 * during the startup phase.
5280 */
5282 {
5283 /*
5284 * Try to send "close connection" message to backend. Ignore any
5285 * error.
5286 */
5289 (void) pqFlush(conn);
5290 }
5291}
#define PqMsg_Terminate
Definition protocol.h:28

References pg_conn::cancelRequest, conn, CONNECTION_OK, fb(), 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 2581 of file fe-connect.c.

2582{
2583 int count;
2584
2585 if (conn->keepalives_count == NULL)
2586 return 1;
2587
2589 "keepalives_count"))
2590 return 0;
2591 if (count < 0)
2592 count = 0;
2593
2594#ifdef TCP_KEEPCNT
2596 (char *) &count, sizeof(count)) < 0)
2597 {
2599
2600 libpq_append_conn_error(conn, "%s(%s) failed: %s",
2601 "setsockopt",
2602 "TCP_KEEPCNT",
2603 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2604 return 0;
2605 }
2606#endif
2607
2608 return 1;
2609}

References conn, fb(), 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 2512 of file fe-connect.c.

2513{
2514 int idle;
2515
2516 if (conn->keepalives_idle == NULL)
2517 return 1;
2518
2520 "keepalives_idle"))
2521 return 0;
2522 if (idle < 0)
2523 idle = 0;
2524
2525#ifdef PG_TCP_KEEPALIVE_IDLE
2527 (char *) &idle, sizeof(idle)) < 0)
2528 {
2530
2531 libpq_append_conn_error(conn, "%s(%s) failed: %s",
2532 "setsockopt",
2534 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2535 return 0;
2536 }
2537#endif
2538
2539 return 1;
2540}

References conn, fb(), 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 2546 of file fe-connect.c.

2547{
2548 int interval;
2549
2551 return 1;
2552
2554 "keepalives_interval"))
2555 return 0;
2556 if (interval < 0)
2557 interval = 0;
2558
2559#ifdef TCP_KEEPINTVL
2561 (char *) &interval, sizeof(interval)) < 0)
2562 {
2564
2565 libpq_append_conn_error(conn, "%s(%s) failed: %s",
2566 "setsockopt",
2567 "TCP_KEEPINTVL",
2568 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2569 return 0;
2570 }
2571#endif
2572
2573 return 1;
2574}

References conn, fb(), 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 2678 of file fe-connect.c.

2679{
2680 int timeout;
2681
2683 return 1;
2684
2686 "tcp_user_timeout"))
2687 return 0;
2688
2689 if (timeout < 0)
2690 timeout = 0;
2691
2692#ifdef TCP_USER_TIMEOUT
2694 (char *) &timeout, sizeof(timeout)) < 0)
2695 {
2696 char sebuf[256];
2697
2698 libpq_append_conn_error(conn, "%s(%s) failed: %s",
2699 "setsockopt",
2700 "TCP_USER_TIMEOUT",
2701 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2702 return 0;
2703 }
2704#endif
2705
2706 return 1;
2707}

References conn, fb(), 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 8212 of file fe-connect.c.

8213{
8216
8217 /* If at least one of the bounds is not set, the range is valid */
8218 if (min == NULL || max == NULL || strlen(min) == 0 || strlen(max) == 0)
8219 return true;
8220
8221 /*
8222 * If the minimum version is the lowest one we accept, then all options
8223 * for the maximum are valid.
8224 */
8225 if (pg_strcasecmp(min, "TLSv1") == 0)
8226 return true;
8227
8228 /*
8229 * The minimum bound is valid, and cannot be TLSv1, so using TLSv1 for the
8230 * maximum is incorrect.
8231 */
8232 if (pg_strcasecmp(max, "TLSv1") == 0)
8233 return false;
8234
8235 /*
8236 * At this point we know that we have a mix of TLSv1.1 through 1.3
8237 * versions.
8238 */
8239 if (pg_strcasecmp(min, max) > 0)
8240 return false;
8241
8242 return true;
8243}
int pg_strcasecmp(const char *s1, const char *s2)

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

Referenced by pqConnectOptions2().

◆ sslVerifyProtocolVersion()

static bool sslVerifyProtocolVersion ( const char version)
static

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

8187{
8188 /*
8189 * An empty string and a NULL value are considered valid as it is
8190 * equivalent to ignoring the parameter.
8191 */
8192 if (!version || strlen(version) == 0)
8193 return true;
8194
8195 if (pg_strcasecmp(version, "TLSv1") == 0 ||
8196 pg_strcasecmp(version, "TLSv1.1") == 0 ||
8197 pg_strcasecmp(version, "TLSv1.2") == 0 ||
8198 pg_strcasecmp(version, "TLSv1.3") == 0)
8199 return true;
8200
8201 /* anything else is wrong */
8202 return false;
8203}

References fb(), and pg_strcasecmp().

Referenced by pqConnectOptions2(), and sslVerifyProtocolRange().

◆ store_conn_addrinfo()

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

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

5216{
5217 struct addrinfo *ai = addrlist;
5218
5219 conn->whichaddr = 0;
5220
5221 conn->naddr = 0;
5222 while (ai)
5223 {
5224 ai = ai->ai_next;
5225 conn->naddr++;
5226 }
5227
5228 conn->addr = calloc(conn->naddr, sizeof(AddrInfo));
5229 if (conn->addr == NULL)
5230 {
5231 libpq_append_conn_error(conn, "out of memory");
5232 return 1;
5233 }
5234
5235 ai = addrlist;
5236 for (int i = 0; i < conn->naddr; i++)
5237 {
5238 conn->addr[i].family = ai->ai_family;
5239
5240 memcpy(&conn->addr[i].addr.addr, ai->ai_addr,
5241 ai->ai_addrlen);
5242 conn->addr[i].addr.salen = ai->ai_addrlen;
5243 ai = ai->ai_next;
5244 }
5245
5246 return 0;
5247}
int family
Definition pqcomm.h:38
SockAddr addr
Definition pqcomm.h:39

References SockAddr::addr, AddrInfo::addr, pg_conn::addr, calloc, conn, AddrInfo::family, fb(), 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 6355 of file fe-connect.c.

6356{
6358 sizeof(uri_designator) - 1) == 0)
6359 return sizeof(uri_designator) - 1;
6360
6362 sizeof(short_uri_designator) - 1) == 0)
6363 return sizeof(short_uri_designator) - 1;
6364
6365 return 0;
6366}
static const char short_uri_designator[]
Definition fe-connect.c:452
static const char uri_designator[]
Definition fe-connect.c:451

References connstr, fb(), 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 2494 of file fe-connect.c.

2495{
2496 int val;
2497
2498 if (conn->keepalives == NULL)
2499 return 1;
2500
2501 if (!pqParseIntParam(conn->keepalives, &val, conn, "keepalives"))
2502 return -1;
2503
2504 return val != 0 ? 1 : 0;
2505}

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

Referenced by PQconnectPoll().

Variable Documentation

◆ EnvironmentOptions

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

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

426{
427 /* common user-interface settings */
428 {
429 "PGDATESTYLE", "datestyle"
430 },
431 {
432 "PGTZ", "timezone"
433 },
434 /* internal performance-related settings */
435 {
436 "PGGEQO", "geqo"
437 },
438 {
439 NULL, NULL
440 }
441};

Referenced by PQconnectPoll().

◆ pg_g_threadlock

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

Referenced by PQregisterThreadLock().

◆ PQconninfoOptions

const internalPQconninfoOption PQconninfoOptions[]
static

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

201 {
202 {"service", "PGSERVICE", NULL, NULL,
203 "Database-Service", "", 20,
204 offsetof(struct pg_conn, pgservice)},
205
206 {"servicefile", "PGSERVICEFILE", NULL, NULL,
207 "Database-Service-File", "", 64,
208 offsetof(struct pg_conn, pgservicefile)},
209
210 {"user", "PGUSER", NULL, NULL,
211 "Database-User", "", 20,
212 offsetof(struct pg_conn, pguser)},
213
214 {"password", "PGPASSWORD", NULL, NULL,
215 "Database-Password", "*", 20,
216 offsetof(struct pg_conn, pgpass)},
217
218 {"passfile", "PGPASSFILE", NULL, NULL,
219 "Database-Password-File", "", 64,
220 offsetof(struct pg_conn, pgpassfile)},
221
222 {"channel_binding", "PGCHANNELBINDING", DefaultChannelBinding, NULL,
223 "Channel-Binding", "", 8, /* sizeof("require") == 8 */
224 offsetof(struct pg_conn, channel_binding)},
225
226 {"connect_timeout", "PGCONNECT_TIMEOUT", NULL, NULL,
227 "Connect-timeout", "", 10, /* strlen(INT32_MAX) == 10 */
228 offsetof(struct pg_conn, connect_timeout)},
229
230 {"dbname", "PGDATABASE", NULL, NULL,
231 "Database-Name", "", 20,
232 offsetof(struct pg_conn, dbName)},
233
234 {"host", "PGHOST", NULL, NULL,
235 "Database-Host", "", 40,
236 offsetof(struct pg_conn, pghost)},
237
238 {"hostaddr", "PGHOSTADDR", NULL, NULL,
239 "Database-Host-IP-Address", "", 45,
240 offsetof(struct pg_conn, pghostaddr)},
241
242 {"port", "PGPORT", DEF_PGPORT_STR, NULL,
243 "Database-Port", "", 6,
244 offsetof(struct pg_conn, pgport)},
245
246 {"client_encoding", "PGCLIENTENCODING", NULL, NULL,
247 "Client-Encoding", "", 10,
248 offsetof(struct pg_conn, client_encoding_initial)},
249
250 {"options", "PGOPTIONS", DefaultOption, NULL,
251 "Backend-Options", "", 40,
252 offsetof(struct pg_conn, pgoptions)},
253
254 {"application_name", "PGAPPNAME", NULL, NULL,
255 "Application-Name", "", 64,
256 offsetof(struct pg_conn, appname)},
257
258 {"fallback_application_name", NULL, NULL, NULL,
259 "Fallback-Application-Name", "", 64,
260 offsetof(struct pg_conn, fbappname)},
261
262 {"keepalives", NULL, NULL, NULL,
263 "TCP-Keepalives", "", 1, /* should be just '0' or '1' */
264 offsetof(struct pg_conn, keepalives)},
265
266 {"keepalives_idle", NULL, NULL, NULL,
267 "TCP-Keepalives-Idle", "", 10, /* strlen(INT32_MAX) == 10 */
268 offsetof(struct pg_conn, keepalives_idle)},
269
270 {"keepalives_interval", NULL, NULL, NULL,
271 "TCP-Keepalives-Interval", "", 10, /* strlen(INT32_MAX) == 10 */
272 offsetof(struct pg_conn, keepalives_interval)},
273
274 {"keepalives_count", NULL, NULL, NULL,
275 "TCP-Keepalives-Count", "", 10, /* strlen(INT32_MAX) == 10 */
276 offsetof(struct pg_conn, keepalives_count)},
277
278 {"tcp_user_timeout", NULL, NULL, NULL,
279 "TCP-User-Timeout", "", 10, /* strlen(INT32_MAX) == 10 */
280 offsetof(struct pg_conn, pgtcp_user_timeout)},
281
282 /*
283 * ssl options are allowed even without client SSL support because the
284 * client can still handle SSL modes "disable" and "allow". Other
285 * parameters have no effect on non-SSL connections, so there is no reason
286 * to exclude them since none of them are mandatory.
287 */
288 {"sslmode", "PGSSLMODE", DefaultSSLMode, NULL,
289 "SSL-Mode", "", 12, /* sizeof("verify-full") == 12 */
290 offsetof(struct pg_conn, sslmode)},
291
292 {"sslnegotiation", "PGSSLNEGOTIATION", DefaultSSLNegotiation, NULL,
293 "SSL-Negotiation", "", 9, /* sizeof("postgres") == 9 */
294 offsetof(struct pg_conn, sslnegotiation)},
295
296 {"sslcompression", "PGSSLCOMPRESSION", "0", NULL,
297 "SSL-Compression", "", 1,
298 offsetof(struct pg_conn, sslcompression)},
299
300 {"sslcert", "PGSSLCERT", NULL, NULL,
301 "SSL-Client-Cert", "", 64,
302 offsetof(struct pg_conn, sslcert)},
303
304 {"sslkey", "PGSSLKEY", NULL, NULL,
305 "SSL-Client-Key", "", 64,
306 offsetof(struct pg_conn, sslkey)},
307
308 {"sslcertmode", "PGSSLCERTMODE", NULL, NULL,
309 "SSL-Client-Cert-Mode", "", 8, /* sizeof("disable") == 8 */
310 offsetof(struct pg_conn, sslcertmode)},
311
312 {"sslpassword", NULL, NULL, NULL,
313 "SSL-Client-Key-Password", "*", 20,
314 offsetof(struct pg_conn, sslpassword)},
315
316 {"sslrootcert", "PGSSLROOTCERT", NULL, NULL,
317 "SSL-Root-Certificate", "", 64,
318 offsetof(struct pg_conn, sslrootcert)},
319
320 {"sslcrl", "PGSSLCRL", NULL, NULL,
321 "SSL-Revocation-List", "", 64,
322 offsetof(struct pg_conn, sslcrl)},
323
324 {"sslcrldir", "PGSSLCRLDIR", NULL, NULL,
325 "SSL-Revocation-List-Dir", "", 64,
326 offsetof(struct pg_conn, sslcrldir)},
327
328 {"sslsni", "PGSSLSNI", "1", NULL,
329 "SSL-SNI", "", 1,
330 offsetof(struct pg_conn, sslsni)},
331
332 {"requirepeer", "PGREQUIREPEER", NULL, NULL,
333 "Require-Peer", "", 10,
334 offsetof(struct pg_conn, requirepeer)},
335
336 {"require_auth", "PGREQUIREAUTH", NULL, NULL,
337 "Require-Auth", "", 14, /* sizeof("scram-sha-256") == 14 */
338 offsetof(struct pg_conn, require_auth)},
339
340 {"min_protocol_version", "PGMINPROTOCOLVERSION",
341 NULL, NULL,
342 "Min-Protocol-Version", "", 6, /* sizeof("latest") = 6 */
343 offsetof(struct pg_conn, min_protocol_version)},
344
345 {"max_protocol_version", "PGMAXPROTOCOLVERSION",
346 NULL, NULL,
347 "Max-Protocol-Version", "", 6, /* sizeof("latest") = 6 */
348 offsetof(struct pg_conn, max_protocol_version)},
349
350 {"ssl_min_protocol_version", "PGSSLMINPROTOCOLVERSION", "TLSv1.2", NULL,
351 "SSL-Minimum-Protocol-Version", "", 8, /* sizeof("TLSv1.x") == 8 */
353
354 {"ssl_max_protocol_version", "PGSSLMAXPROTOCOLVERSION", NULL, NULL,
355 "SSL-Maximum-Protocol-Version", "", 8, /* sizeof("TLSv1.x") == 8 */
357
358 /*
359 * As with SSL, all GSS options are exposed even in builds that don't have
360 * support.
361 */
362 {"gssencmode", "PGGSSENCMODE", DefaultGSSMode, NULL,
363 "GSSENC-Mode", "", 8, /* sizeof("disable") == 8 */
364 offsetof(struct pg_conn, gssencmode)},
365
366 /* Kerberos and GSSAPI authentication support specifying the service name */
367 {"krbsrvname", "PGKRBSRVNAME", PG_KRB_SRVNAM, NULL,
368 "Kerberos-service-name", "", 20,
369 offsetof(struct pg_conn, krbsrvname)},
370
371 {"gsslib", "PGGSSLIB", NULL, NULL,
372 "GSS-library", "", 7, /* sizeof("gssapi") == 7 */
373 offsetof(struct pg_conn, gsslib)},
374
375 {"gssdelegation", "PGGSSDELEGATION", "0", NULL,
376 "GSS-delegation", "", 1,
377 offsetof(struct pg_conn, gssdelegation)},
378
379 {"replication", NULL, NULL, NULL,
380 "Replication", "D", 5,
381 offsetof(struct pg_conn, replication)},
382
383 {"target_session_attrs", "PGTARGETSESSIONATTRS",
385 "Target-Session-Attrs", "", 15, /* sizeof("prefer-standby") = 15 */
386 offsetof(struct pg_conn, target_session_attrs)},
387
388 {"load_balance_hosts", "PGLOADBALANCEHOSTS",
390 "Load-Balance-Hosts", "", 8, /* sizeof("disable") = 8 */
391 offsetof(struct pg_conn, load_balance_hosts)},
392
393 {"scram_client_key", NULL, NULL, NULL, "SCRAM-Client-Key", "D", SCRAM_MAX_KEY_LEN * 2,
394 offsetof(struct pg_conn, scram_client_key)},
395
396 {"scram_server_key", NULL, NULL, NULL, "SCRAM-Server-Key", "D", SCRAM_MAX_KEY_LEN * 2,
397 offsetof(struct pg_conn, scram_server_key)},
398
399 /* OAuth v2 */
400 {"oauth_issuer", NULL, NULL, NULL,
401 "OAuth-Issuer", "", 40,
402 offsetof(struct pg_conn, oauth_issuer)},
403
404 {"oauth_client_id", NULL, NULL, NULL,
405 "OAuth-Client-ID", "", 40,
406 offsetof(struct pg_conn, oauth_client_id)},
407
408 {"oauth_client_secret", NULL, NULL, NULL,
409 "OAuth-Client-Secret", "*", 40,
410 offsetof(struct pg_conn, oauth_client_secret)},
411
412 {"oauth_scope", NULL, NULL, NULL,
413 "OAuth-Scope", "", 15,
414 offsetof(struct pg_conn, oauth_scope)},
415
416 {"sslkeylogfile", NULL, NULL, NULL,
417 "SSL-Key-Log-File", "D", 64,
418 offsetof(struct pg_conn, sslkeylogfile)},
419
420 /* Terminating entry --- MUST BE LAST */
421 {NULL, NULL, NULL, NULL,
422 NULL, NULL, 0}
423};
int ssl_min_protocol_version
Definition be-secure.c:61
int ssl_max_protocol_version
Definition be-secure.c:62
#define DefaultOption
Definition fe-connect.c:122
#define DefaultLoadBalanceHosts
Definition fe-connect.c:129
#define DefaultTargetSessionAttrs
Definition fe-connect.c:128

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

◆ short_uri_designator

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

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

Referenced by uri_prefix_length(), and uri_prefix_length().

◆ supported_sasl_mechs

const pg_fe_sasl_mech* supported_sasl_mechs[]
static
Initial value:

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

444{
447};

Referenced by fill_allowed_sasl_mechs().

◆ uri_designator

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

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

Referenced by uri_prefix_length(), and uri_prefix_length().