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)
 
pgthreadlock_t PQgetThreadLock (void)
 

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:99
@ PGRES_POLLING_WRITING
Definition libpq-fe.h:123
ConnStatusType status
Definition libpq-int.h:463

◆ 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 452 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:618

Typedef Documentation

◆ internalPQconninfoOption

Function Documentation

◆ clear_allowed_sasl_mechs()

static void clear_allowed_sasl_mechs ( PGconn conn)
inlinestatic

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

1227{
1228 for (int i = 0; i < lengthof(conn->allowed_sasl_mechs); i++)
1230}
#define lengthof(array)
Definition c.h:873
int i
Definition isn.c:77
const pg_fe_sasl_mech * allowed_sasl_mechs[2]
Definition libpq-int.h:520

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

2479{
2481
2483 "%s\n",
2484 SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
2485
2486 if (conn->raddr.addr.ss_family == AF_UNIX)
2487 libpq_append_conn_error(conn, "\tIs the server running locally and accepting connections on that socket?");
2488 else
2489 libpq_append_conn_error(conn, "\tIs the server running on that host and accepting TCP/IP connections?");
2490}
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition fe-misc.c:1404
#define SOCK_STRERROR
Definition libpq-int.h:974
#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:684
SockAddr raddr
Definition libpq-int.h:503

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

4838{
4841
4842 return select_next_encryption_method(conn, false);
4843}
#define Assert(condition)
Definition c.h:943
static bool select_next_encryption_method(PGconn *conn, bool have_valid_connection)
uint8 failed_enc_methods
Definition libpq-int.h:617

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

2364{
2365#ifdef TCP_NODELAY
2366 int on = 1;
2367
2369 (char *) &on,
2370 sizeof(on)) < 0)
2371 {
2373
2374 libpq_append_conn_error(conn, "could not set socket to TCP no delay mode: %s",
2375 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2376 return 0;
2377 }
2378#endif
2379
2380 return 1;
2381}
#define SOCK_ERRNO
Definition oauth-utils.c:86
pgsocket sock
Definition libpq-int.h:500

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

1084{
1086
1087 /*
1088 * Parse the conninfo string
1089 */
1091 if (connOptions == NULL)
1092 {
1094 /* errorMessage is already set */
1095 return false;
1096 }
1097
1098 /*
1099 * Move option values into conn structure
1100 */
1102 {
1105 return false;
1106 }
1107
1108 /*
1109 * Free the option info - all is in conn now
1110 */
1112
1113 return true;
1114}
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:91

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

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

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

7502{
7504
7505 for (option = connOptions; option->keyword != NULL; option++)
7506 {
7507 if (strcmp(option->keyword, keyword) == 0)
7508 return option;
7509 }
7510
7511 return NULL;
7512}

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

7413{
7415
7416 option = conninfo_find(connOptions, keyword);
7417
7418 return option ? option->val : NULL;
7419}
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 6301 of file fe-connect.c.

6302{
6306
6307 /*
6308 * Get enough memory for all options in PQconninfoOptions, even if some
6309 * end up being filtered out.
6310 */
6312 if (options == NULL)
6313 {
6314 libpq_append_error(errorMessage, "out of memory");
6315 return NULL;
6316 }
6317 opt_dest = options;
6318
6320 {
6321 /* Only copy the public part of the struct, not the full internal */
6323 opt_dest++;
6324 }
6325 MemSet(opt_dest, 0, sizeof(PQconninfoOption));
6326
6327 return options;
6328}
#define MemSet(start, val, len)
Definition c.h:1107
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
static const internalPQconninfoOption PQconninfoOptions[]
Definition fe-connect.c:201
#define malloc(a)

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

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

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

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

6865{
6867
6868 /* Make a working copy of PQconninfoOptions */
6869 options = conninfo_init(errorMessage);
6870 if (options == NULL)
6871 return NULL;
6872
6873 if (!conninfo_uri_parse_options(options, uri, errorMessage))
6874 {
6876 return NULL;
6877 }
6878
6879 /*
6880 * Add in defaults if the caller wants that.
6881 */
6882 if (use_defaults)
6883 {
6884 if (!conninfo_add_defaults(options, errorMessage))
6885 {
6887 return NULL;
6888 }
6889 }
6890
6891 return options;
6892}
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 6916 of file fe-connect.c.

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

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

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

1121{
1122 int n;
1123
1124 n = 1;
1125 for (; *input != '\0'; input++)
1126 {
1127 if (*input == ',')
1128 n++;
1129 }
1130
1131 return n;
1132}
FILE * input

References input.

Referenced by pqConnectOptions2().

◆ default_threadlock()

static void default_threadlock ( int  acquire)
static

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

8395{
8397
8398 if (acquire)
8399 {
8401 Assert(false);
8402 }
8403 else
8404 {
8406 Assert(false);
8407 }
8408}
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 7961 of file fe-connect.c.

7962{
7963 (void) arg; /* not used */
7964 /* Note: we expect the supplied string to end with a newline already. */
7965 fprintf(stderr, "%s", message);
7966}
#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 7946 of file fe-connect.c.

7947{
7948 (void) arg; /* not used */
7949 if (res->noticeHooks.noticeProc != NULL)
7952}
#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 2422 of file fe-connect.c.

2423{
2424 if (conn->raddr.addr.ss_family == AF_UNIX)
2425 {
2426 char service[NI_MAXHOST];
2427
2429 NULL, 0,
2430 service, sizeof(service),
2433 libpq_gettext("connection to server on socket \"%s\" failed: "),
2434 service);
2435 }
2436 else
2437 {
2438 const char *displayed_host;
2439 const char *displayed_port;
2440
2441 /* To which host and port were we actually connecting? */
2444 else
2447 if (displayed_port == NULL || displayed_port[0] == '\0')
2449
2450 /*
2451 * If the user did not supply an IP address using 'hostaddr', and
2452 * 'host' was missing or does not match our lookup, display the
2453 * looked-up IP address.
2454 */
2456 host_addr[0] &&
2459 libpq_gettext("connection to server at \"%s\" (%s), port %s failed: "),
2462 else
2464 libpq_gettext("connection to server at \"%s\", port %s failed: "),
2467 }
2468}
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:44
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:482
pg_conn_host * connhost
Definition libpq-int.h:483

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

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

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

1005{
1007
1008 for (option = PQconninfoOptions; option->keyword; option++)
1009 {
1010 if (option->connofs >= 0)
1011 {
1012 const char *tmp = conninfo_getval(connOptions, option->keyword);
1013
1014 if (tmp)
1015 {
1016 char **connmember = (char **) ((char *) conn + option->connofs);
1017
1018 free(*connmember);
1019 *connmember = strdup(tmp);
1020 if (*connmember == NULL)
1021 {
1022 libpq_append_conn_error(conn, "out of memory");
1023 return false;
1024 }
1025 }
1026 }
1027 }
1028
1029 return true;
1030}
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 5091 of file fe-connect.c.

5092{
5093 /* let any event procs clean up their state data */
5094 for (int i = 0; i < conn->nEvents; i++)
5095 {
5097
5098 evt.conn = conn;
5101 free(conn->events[i].name);
5102 }
5103
5104 /* free everything not freed in pqClosePGconn */
5105 free(conn->pghost);
5107 free(conn->pgport);
5112 free(conn->appname);
5114 free(conn->dbName);
5118 free(conn->pguser);
5119 if (conn->pgpass)
5120 {
5122 free(conn->pgpass);
5123 }
5130 free(conn->sslmode);
5133 free(conn->sslkey);
5134 free(conn->sslcert);
5135 if (conn->sslpassword)
5136 {
5139 }
5142 free(conn->sslcrl);
5144 free(conn->sslsni);
5148 free(conn->gsslib);
5167 /* Note that conn->Pfdebug is not ours to close or free */
5168 free(conn->events);
5170 free(conn->connip);
5174 /* if this is a cancel connection, be_cancel_key may still be allocated */
5176 free(conn->inBuffer);
5178 free(conn->rowBuf);
5181
5182 free(conn);
5183}
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:555
char * replication
Definition libpq-int.h:391
uint8 * scram_client_key_binary
Definition libpq-int.h:546
char * sslrootcert
Definition libpq-int.h:413
PGdataValue * rowBuf
Definition libpq-int.h:594
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:577
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:548
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:688
char * keepalives_idle
Definition libpq-int.h:401
char * connip
Definition libpq-int.h:484
char * pgservicefile
Definition libpq-int.h:393
char * oauth_ca_file
Definition libpq-int.h:447
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:459
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:458
char * outBuffer
Definition libpq-int.h:584

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_ca_file, 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 7390 of file fe-connect.c.

7391{
7392 if ('0' <= digit && digit <= '9')
7393 *value = digit - '0';
7394 else if ('A' <= digit && digit <= 'F')
7395 *value = digit - 'A' + 10;
7396 else if ('a' <= digit && digit <= 'f')
7397 *value = digit - 'a' + 10;
7398 else
7399 return false;
7400
7401 return true;
7402}

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

2390{
2391 struct sockaddr_storage *addr = &conn->raddr.addr;
2392
2393 if (addr->ss_family == AF_INET)
2394 {
2396 &((struct sockaddr_in *) addr)->sin_addr.s_addr,
2397 32,
2399 host_addr[0] = '\0';
2400 }
2401 else if (addr->ss_family == AF_INET6)
2402 {
2404 &((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr,
2405 128,
2407 host_addr[0] = '\0';
2408 }
2409 else
2410 host_addr[0] = '\0';
2411}
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 1237 of file fe-connect.c.

1238{
1239 for (int i = 0; i < lengthof(conn->allowed_sasl_mechs); i++)
1240 {
1241 if (conn->allowed_sasl_mechs[i] == mech)
1242 return i;
1243 }
1244
1245 return -1;
1246}

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

4748{
4749 if (conn->raddr.addr.ss_family == AF_UNIX)
4750 {
4751 /* Don't request SSL or GSSAPI over Unix sockets */
4753
4754 /*
4755 * XXX: we probably should not do this. sslmode=require works
4756 * differently
4757 */
4758 if (conn->gssencmode[0] == 'r')
4759 {
4761 "GSSAPI encryption required but it is not supported over a local socket");
4764 return false;
4765 }
4766
4769 return true;
4770 }
4771
4772 /* initialize based on sslmode and gssencmode */
4774
4775#ifdef USE_SSL
4776 /* sslmode anything but 'disable', and GSSAPI not required */
4777 if (conn->sslmode[0] != 'd' && conn->gssencmode[0] != 'r')
4778 {
4780 }
4781#endif
4782
4783#ifdef ENABLE_GSS
4784 if (conn->gssencmode[0] != 'd')
4786#endif
4787
4788 if ((conn->sslmode[0] == 'd' || conn->sslmode[0] == 'p' || conn->sslmode[0] == 'a') &&
4789 (conn->gssencmode[0] == 'd' || conn->gssencmode[0] == 'p'))
4790 {
4792 }
4793
4794 return select_next_encryption_method(conn, false);
4795}
#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:616

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

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

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

1180{
1181 uint64 rseed;
1182 struct timeval tval = {0};
1183
1185 return;
1186
1188
1189 rseed = ((uintptr_t) conn) ^
1190 ((uint64) getpid()) ^
1191 ((uint64) tval.tv_usec) ^
1192 ((uint64) tval.tv_sec);
1193
1195}
uint64_t uint64
Definition c.h:625
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:564
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 1144 of file fe-connect.c.

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

References fb(), len, malloc, and memcpy().

Referenced by pqConnectOptions2().

◆ parse_connection_string()

static PQconninfoOption * parse_connection_string ( const char connstr,
PQExpBuffer  errorMessage,
bool  use_defaults 
)
static

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

6342{
6343 /* Parse as URI if connection string matches URI prefix */
6344 if (uri_prefix_length(connstr) != 0)
6345 return conninfo_uri_parse(connstr, errorMessage, use_defaults);
6346
6347 /* Parse as default otherwise */
6348 return conninfo_parse(connstr, errorMessage, use_defaults);
6349}
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:95

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

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

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

Referenced by parseServiceInfo().

◆ parseServiceInfo()

static int parseServiceInfo ( PQconninfoOption options,
PQExpBuffer  errorMessage 
)
static

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

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

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

8169{
8170 /* If it was 'invalid authorization', add pgpassfile mention */
8171 /* only works with >= 9.0 servers */
8172 if (conn->password_needed &&
8174 conn->result)
8175 {
8176 const char *sqlstate = PQresultErrorField(conn->result,
8178
8179 if (sqlstate && strcmp(sqlstate, ERRCODE_INVALID_PASSWORD) == 0)
8180 libpq_append_conn_error(conn, "password retrieved from file \"%s\"",
8181 conn->pgpassfile);
8182 }
8183}
#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:607
bool password_needed
Definition libpq-int.h:509

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

5308{
5309 /*
5310 * If possible, send Terminate message to close the connection politely.
5311 */
5313
5314 /*
5315 * Must reset the blocking status so a possible reconnect will work.
5316 *
5317 * Don't call PQsetnonblocking() because it will fail if it's unable to
5318 * flush the connection.
5319 */
5320 conn->nonblocking = false;
5321
5322 /*
5323 * Close the connection, reset all transient state, flush I/O buffers.
5324 * Note that this includes clearing conn's error state; we're no longer
5325 * interested in any failures associated with the old connection, and we
5326 * want a clean slate for any new connection attempt.
5327 */
5328 pqDropConnection(conn, true);
5329 conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
5334 pqClearAsyncResult(conn); /* deallocate result */
5336
5337 /*
5338 * Release addrinfo, but since cancel requests never change their addrinfo
5339 * we don't do that. Otherwise we would have to rebuild it during a
5340 * PQcancelReset.
5341 */
5342 if (!conn->cancelRequest)
5344
5345 /* Reset all state obtained from server, too */
5347}
void pqClearOAuthToken(PGconn *conn)
void pqDropConnection(PGconn *conn, bool flushInput)
Definition fe-connect.c:537
static void sendTerminateConn(PGconn *conn)
static void pqDropServerData(PGconn *conn)
Definition fe-connect.c:663
void pqClearAsyncResult(PGconn *conn)
Definition fe-exec.c:785
@ PQTRANS_IDLE
Definition libpq-fe.h:153
@ PQ_PIPELINE_OFF
Definition libpq-fe.h:193
@ PGASYNC_IDLE
Definition libpq-int.h:215
#define pqClearConnErrorState(conn)
Definition libpq-int.h:924
PGTransactionStatusType xactStatus
Definition libpq-int.h:465
bool cancelRequest
Definition libpq-int.h:434
bool nonblocking
Definition libpq-int.h:468
PGAsyncStatusType asyncStatus
Definition libpq-int.h:464
PGpipelineStatus pipelineStatus
Definition libpq-int.h:470

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

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

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

831{
832 PGconn *conn = PQconnectStart(conninfo);
833
834 if (conn && conn->status != CONNECTION_BAD)
836
837 return conn;
838}
PGconn * PQconnectStart(const char *conninfo)
Definition fe-connect.c:958

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

2800{
2803 int timeout = 0;
2804 int last_whichhost = -2; /* certainly different from whichhost */
2805 int last_whichaddr = -2; /* certainly different from whichaddr */
2806
2807 if (conn == NULL || conn->status == CONNECTION_BAD)
2808 return 0;
2809
2810 /*
2811 * Set up a time limit, if connect_timeout is greater than zero.
2812 */
2813 if (conn->connect_timeout != NULL)
2814 {
2816 "connect_timeout"))
2817 {
2818 /* mark the connection as bad to report the parsing failure */
2820 return 0;
2821 }
2822 }
2823
2824 for (;;)
2825 {
2826 int ret = 0;
2827
2828 /*
2829 * (Re)start the connect_timeout timer if it's active and we are
2830 * considering a different host than we were last time through. If
2831 * we've already succeeded, though, needn't recalculate.
2832 */
2833 if (flag != PGRES_POLLING_OK &&
2834 timeout > 0 &&
2837 {
2841 }
2842
2843 /*
2844 * Wait, if necessary. Note that the initial state (just after
2845 * PQconnectStart) is to wait for the socket to select for writing.
2846 */
2847 switch (flag)
2848 {
2849 case PGRES_POLLING_OK:
2850 return 1; /* success! */
2851
2853 ret = pqWaitTimed(1, 0, conn, end_time);
2854 if (ret == -1)
2855 {
2856 /* hard failure, eg select() problem, aborts everything */
2858 return 0;
2859 }
2860 break;
2861
2863 ret = pqWaitTimed(0, 1, conn, end_time);
2864 if (ret == -1)
2865 {
2866 /* hard failure, eg select() problem, aborts everything */
2868 return 0;
2869 }
2870 break;
2871
2872 default:
2873 /* Just in case we failed to set it in PQconnectPoll */
2875 return 0;
2876 }
2877
2878 if (ret == 1) /* connect_timeout elapsed */
2879 {
2880 /*
2881 * Give up on current server/address, try the next one.
2882 */
2883 conn->try_next_addr = true;
2885 }
2886
2887 /*
2888 * Now try to advance the state machine.
2889 */
2890 if (conn->cancelRequest)
2892 else
2894 }
2895}
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:106
int64_t pg_usec_time_t
Definition libpq-fe.h:246
PostgresPollingStatusType
Definition libpq-fe.h:120
@ PGRES_POLLING_OK
Definition libpq-fe.h:124
@ PGRES_POLLING_READING
Definition libpq-fe.h:122
static int64 end_time
Definition pgbench.c:176
int whichaddr
Definition libpq-int.h:541
bool try_next_addr
Definition libpq-int.h:538
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 775 of file fe-connect.c.

778{
780
781 if (conn && conn->status != CONNECTION_BAD)
783
784 return conn;
785}
PGconn * PQconnectStartParams(const char *const *keywords, const char *const *values, int expand_dbname)
Definition fe-connect.c:877

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

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

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

7796{
7797 char *password;
7798
7799 if (!conn)
7800 return false;
7801 password = PQpass(conn);
7802 if (conn->password_needed &&
7803 (password == NULL || password[0] == '\0'))
7804 return true;
7805 else
7806 return false;
7807}
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 7821 of file fe-connect.c.

7822{
7823 if (!conn)
7824 return false;
7825 if (conn->gssapi_used)
7826 return true;
7827 else
7828 return false;
7829}
bool gssapi_used
Definition libpq-int.h:510

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

7811{
7812 if (!conn)
7813 return false;
7814 if (conn->password_needed)
7815 return true;
7816 else
7817 return false;
7818}

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

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

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

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

959{
960 PGconn *conn;
961
962 /*
963 * Allocate memory for the conn structure. Note that we also expect this
964 * to initialize conn->errorMessage to empty. All subsequent steps during
965 * connection initialization will only append to that buffer.
966 */
968 if (conn == NULL)
969 return NULL;
970
971 /*
972 * Parse the conninfo string
973 */
974 if (!connectOptions1(conn, conninfo))
975 return conn;
976
977 /*
978 * Compute derived options
979 */
981 return conn;
982
983 /*
984 * Connect to the database
985 */
987 {
988 /* Just in case we failed to set it in pqConnectDBStart */
990 }
991
992 return conn;
993}
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 877 of file fe-connect.c.

880{
881 PGconn *conn;
883
884 /*
885 * Allocate memory for the conn structure. Note that we also expect this
886 * to initialize conn->errorMessage to empty. All subsequent steps during
887 * connection initialization will only append to that buffer.
888 */
890 if (conn == NULL)
891 return NULL;
892
893 /*
894 * Parse the conninfo arrays
895 */
898 true, expand_dbname);
899 if (connOptions == NULL)
900 {
902 /* errorMessage is already set */
903 return conn;
904 }
905
906 /*
907 * Move option values into conn structure
908 */
910 {
912 return conn;
913 }
914
915 /*
916 * Free the option info - all is in conn now
917 */
919
920 /*
921 * Compute derived options
922 */
924 return conn;
925
926 /*
927 * Connect to the database
928 */
930 {
931 /* Just in case we failed to set it in pqConnectDBStart */
933 }
934
935 return conn;
936}
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 7519 of file fe-connect.c.

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

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(), pg_start_oauthbearer(), and test_protocol_version().

◆ PQconninfoFree()

◆ PQconninfoParse()

◆ pqCopyPGconn()

bool pqCopyPGconn ( PGconn srcConn,
PGconn dstConn 
)

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

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

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

Referenced by PQcancelCreate().

◆ PQdb()

◆ pqDropConnection()

void pqDropConnection ( PGconn conn,
bool  flushInput 
)

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

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

664{
666 pgParameterStatus *pstatus;
667
668 /* Forget pending notifies */
670 while (notify != NULL)
671 {
672 PGnotify *prev = notify;
673
674 notify = notify->next;
675 free(prev);
676 }
678
679 /* Reset ParameterStatus data, as well as variables deduced from it */
680 pstatus = conn->pstatus;
681 while (pstatus != NULL)
682 {
683 pgParameterStatus *prev = pstatus;
684
685 pstatus = pstatus->next;
686 free(prev);
687 }
688 conn->pstatus = NULL;
690 conn->std_strings = false;
694 conn->sversion = 0;
695
696 /* Drop large-object lookup data */
699
700 /* Reset assorted other per-connection state */
701 conn->last_sqlstate[0] = '\0';
702 conn->pversion_negotiated = false;
703 conn->auth_req_received = false;
704 conn->client_finished_auth = false;
705 conn->password_needed = false;
706 conn->gssapi_used = false;
707 conn->write_failed = false;
710 conn->oauth_want_retry = false;
711
712 /*
713 * Cancel connections need to retain their be_pid and be_cancel_key across
714 * PQcancelReset invocations, otherwise they would not have access to the
715 * secret token of the connection they are supposed to cancel.
716 */
717 if (!conn->cancelRequest)
718 {
719 conn->be_pid = 0;
720 if (conn->be_cancel_key != NULL)
721 {
724 }
726 }
727}
@ PG_SQL_ASCII
Definition pg_wchar.h:76
#define SCRAM_SHA_256_DEFAULT_ITERATIONS
struct pgNotify * next
Definition libpq-fe.h:242
struct pgParameterStatus * next
Definition libpq-int.h:271
char * write_err_msg
Definition libpq-int.h:514
PGnotify * notifyHead
Definition libpq-int.h:477
bool std_strings
Definition libpq-int.h:558
bool write_failed
Definition libpq-int.h:513
bool client_finished_auth
Definition libpq-int.h:522
PGnotify * notifyTail
Definition libpq-int.h:478
pgParameterStatus * pstatus
Definition libpq-int.h:556
int scram_sha_256_iterations
Definition libpq-int.h:614
PGlobjfuncs * lobjfuncs
Definition libpq-int.h:563
int be_cancel_key_len
Definition libpq-int.h:554

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

7743{
7744 if (!conn)
7745 return libpq_gettext("connection pointer is NULL\n");
7746
7747 /*
7748 * The errorMessage buffer might be marked "broken" due to having
7749 * previously failed to allocate enough memory for the message. In that
7750 * case, tell the application we ran out of memory.
7751 */
7753 return libpq_gettext("out of memory\n");
7754
7755 return conn->errorMessage.data;
7756}
#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 5354 of file fe-connect.c.

5355{
5356 if (conn)
5357 {
5360 }
5361}
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_for_unsupported_encodings(), 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 637 of file fe-connect.c.

638{
639 while (queue != NULL)
640 {
641 PGcmdQueueEntry *cur = queue;
642
643 queue = cur->next;
644 free(cur->query);
645 free(cur);
646 }
647}
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 7722 of file fe-connect.c.

7723{
7724 if (!conn)
7725 return 0;
7726 if (conn->status == CONNECTION_BAD)
7727 return 0;
7729}
#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 8270 of file fe-connect.c.

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

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

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

◆ PQgetThreadLock()

pgthreadlock_t PQgetThreadLock ( void  )

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

8425{
8427 return pg_g_threadlock;
8428}
pgthreadlock_t pg_g_threadlock
Definition fe-connect.c:521

References Assert, and pg_g_threadlock.

Referenced by libpq_oauth_init().

◆ PQhost()

char * PQhost ( const PGconn conn)

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

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

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

7633{
7634 if (!conn)
7635 return NULL;
7636
7637 /* Return the parsed IP address */
7638 if (conn->connhost != NULL && conn->connip != NULL)
7639 return conn->connip;
7640
7641 return "";
7642}

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

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

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

7672{
7673 if (!conn)
7674 return NULL;
7675 return conn->pgoptions;
7676}

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

5464{
5465 /* Start the message. */
5467 return STATUS_ERROR;
5468
5469 /* Send the message body. */
5470 if (pqPutnchar(buf, buf_len, conn))
5471 return STATUS_ERROR;
5472
5473 /* Finish the message. */
5474 if (pqPutMsgEnd(conn))
5475 return STATUS_ERROR;
5476
5477 /* Flush to ensure backend gets it. */
5478 if (pqFlush(conn))
5479 return STATUS_ERROR;
5480
5481 return STATUS_OK;
5482}
#define STATUS_ERROR
Definition c.h:1259
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 8311 of file fe-connect.c.

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

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

8358{
8359 if (strcmp(value, "latest") == 0)
8360 {
8362 return true;
8363 }
8364 if (strcmp(value, "3.0") == 0)
8365 {
8366 *result = PG_PROTOCOL(3, 0);
8367 return true;
8368 }
8369
8370 /* 3.1 never existed, we went straight from 3.0 to 3.2 */
8371
8372 if (strcmp(value, "3.2") == 0)
8373 {
8374 *result = PG_PROTOCOL(3, 2);
8375 return true;
8376 }
8377
8378 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
8379 context, value);
8380 return false;
8381}
#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, result, and value.

Referenced by pqConnectOptions2().

◆ PQpass()

char * PQpass ( const PGconn conn)

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

7593{
7594 char *password = NULL;
7595
7596 if (!conn)
7597 return NULL;
7598 if (conn->connhost != NULL)
7600 if (password == NULL)
7601 password = conn->pgpass;
7602 /* Historically we've returned "" not NULL for no password specified */
7603 if (password == NULL)
7604 password = "";
7605 return password;
7606}

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

847{
848 PGconn *conn = PQconnectStart(conninfo);
849 PGPing ret;
850
851 ret = internal_ping(conn);
852 PQfinish(conn);
853
854 return ret;
855}
static PGPing internal_ping(PGconn *conn)
void PQfinish(PGconn *conn)
PGPing
Definition libpq-fe.h:181

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

◆ PQpingParams()

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

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

796{
798 PGPing ret;
799
800 ret = internal_ping(conn);
801 PQfinish(conn);
802
803 return ret;
804}

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

7646{
7647 if (!conn)
7648 return NULL;
7649
7650 if (conn->connhost != NULL &&
7652 conn->connhost[conn->whichhost].port[0] != '\0')
7653 return conn->connhost[conn->whichhost].port;
7654
7655 return DEF_PGPORT_STR;
7656}

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

7713{
7714 if (!conn)
7715 return 0;
7716 if (conn->status == CONNECTION_BAD)
7717 return 0;
7719}
#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 8411 of file fe-connect.c.

8412{
8414
8415 if (newhandler)
8417 else
8419
8420 return prev;
8421}
static void default_threadlock(int acquire)
void(* pgthreadlock_t)(int acquire)
Definition libpq-fe.h:477

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

◆ pqReleaseConnHosts()

void pqReleaseConnHosts ( PGconn conn)

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

5191{
5192 if (conn->connhost)
5193 {
5194 for (int i = 0; i < conn->nconnhost; ++i)
5195 {
5196 free(conn->connhost[i].host);
5198 free(conn->connhost[i].port);
5199 if (conn->connhost[i].password != NULL)
5200 {
5204 }
5205 }
5206 free(conn->connhost);
5207 conn->connhost = NULL;
5208 }
5209}

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

5369{
5370 if (conn)
5371 {
5373
5375 {
5376 /*
5377 * Notify event procs of successful reset.
5378 */
5379 int i;
5380
5381 for (i = 0; i < conn->nEvents; i++)
5382 {
5384
5385 evt.conn = conn;
5388 }
5389 }
5390 }
5391}
@ 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 5420 of file fe-connect.c.

5421{
5422 if (conn)
5423 {
5425
5426 if (status == PGRES_POLLING_OK)
5427 {
5428 /*
5429 * Notify event procs of successful reset.
5430 */
5431 int i;
5432
5433 for (i = 0; i < conn->nEvents; i++)
5434 {
5436
5437 evt.conn = conn;
5440 }
5441 }
5442
5443 return status;
5444 }
5445
5446 return PGRES_POLLING_FAILED;
5447}

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

5402{
5403 if (conn)
5404 {
5406
5407 return pqConnectDBStart(conn);
5408 }
5409
5410 return 0;
5411}

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

◆ PQserverVersion()

◆ PQsetClientEncoding()

int PQsetClientEncoding ( PGconn conn,
const char encoding 
)

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

7841{
7842 char qbuf[128];
7843 static const char query[] = "set client_encoding to '%s'";
7844 PGresult *res;
7845 int status;
7846
7847 if (!conn || conn->status != CONNECTION_OK)
7848 return -1;
7849
7850 if (!encoding)
7851 return -1;
7852
7853 /* Resolve special "auto" value from the locale */
7854 if (strcmp(encoding, "auto") == 0)
7856
7857 /* check query buffer overflow */
7858 if (sizeof(qbuf) < (sizeof(query) + strlen(encoding)))
7859 return -1;
7860
7861 /* ok, now send a query */
7862 sprintf(qbuf, query, encoding);
7863 res = PQexec(conn, qbuf);
7864
7865 if (res == NULL)
7866 return -1;
7867 if (res->resultStatus != PGRES_COMMAND_OK)
7868 status = -1;
7869 else
7870 {
7871 /*
7872 * We rely on the backend to report the parameter value, and we'll
7873 * change state at that time.
7874 */
7875 status = 0; /* everything is ok */
7876 }
7877 PQclear(res);
7878 return status;
7879}
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:131
#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 2248 of file fe-connect.c.

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

7895{
7897
7898 if (!conn)
7899 return PQSHOW_CONTEXT_ERRORS;
7901 conn->show_context = show_context;
7902 return old;
7903}
PGContextVisibility
Definition libpq-fe.h:169

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

7883{
7885
7886 if (!conn)
7887 return PQERRORS_DEFAULT;
7888 old = conn->verbosity;
7889 conn->verbosity = verbosity;
7890 return old;
7891}
PGVerbosity
Definition libpq-fe.h:161

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

7924{
7926
7927 if (conn == NULL)
7928 return NULL;
7929
7931 if (proc)
7932 {
7933 conn->noticeHooks.noticeProc = proc;
7935 }
7936 return old;
7937}
void(* PQnoticeProcessor)(void *arg, const char *message)
Definition libpq-fe.h:250

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

7907{
7909
7910 if (conn == NULL)
7911 return NULL;
7912
7914 if (proc)
7915 {
7916 conn->noticeHooks.noticeRec = proc;
7918 }
7919 return old;
7920}
void(* PQnoticeReceiver)(void *arg, const PGresult *res)
Definition libpq-fe.h:249
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 7663 of file fe-connect.c.

7664{
7665 if (!conn)
7666 return NULL;
7667 return "";
7668}

References conn, and fb().

◆ PQuser()

char * PQuser ( const PGconn conn)

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

7585{
7586 if (!conn)
7587 return NULL;
7588 return conn->pguser;
7589}

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

7974{
7975 char *tbuf;
7976 const char *ttok;
7977 bool bslash = false;
7978
7979 if (buf == NULL || token == NULL)
7980 return NULL;
7981 tbuf = buf;
7982 ttok = token;
7983 if (tbuf[0] == '*' && tbuf[1] == ':')
7984 return tbuf + 2;
7985 while (*tbuf != 0)
7986 {
7987 if (*tbuf == '\\' && !bslash)
7988 {
7989 tbuf++;
7990 bslash = true;
7991 }
7992 if (*tbuf == ':' && *ttok == 0 && !bslash)
7993 return tbuf + 1;
7994 bslash = false;
7995 if (*ttok == 0)
7996 return NULL;
7997 if (*tbuf == *ttok)
7998 {
7999 tbuf++;
8000 ttok++;
8001 }
8002 else
8003 return NULL;
8004 }
8005 return NULL;
8006}
#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 6383 of file fe-connect.c.

6384{
6385 return uri_prefix_length(connstr) != 0 || strchr(connstr, '=') != NULL;
6386}

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

5260{
5261 if (conn->addr)
5262 {
5263 free(conn->addr);
5264 conn->addr = NULL;
5265 }
5266}

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

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

5274{
5275 /*
5276 * The Postgres cancellation protocol does not have a notion of a
5277 * Terminate message, so don't send one.
5278 */
5279 if (conn->cancelRequest)
5280 return;
5281
5282 /*
5283 * Note that the protocol doesn't allow us to send Terminate messages
5284 * during the startup phase.
5285 */
5287 {
5288 /*
5289 * Try to send "close connection" message to backend. Ignore any
5290 * error.
5291 */
5294 (void) pqFlush(conn);
5295 }
5296}
#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 2585 of file fe-connect.c.

2586{
2587 int count;
2588
2589 if (conn->keepalives_count == NULL)
2590 return 1;
2591
2593 "keepalives_count"))
2594 return 0;
2595 if (count < 0)
2596 count = 0;
2597
2598#ifdef TCP_KEEPCNT
2600 (char *) &count, sizeof(count)) < 0)
2601 {
2603
2604 libpq_append_conn_error(conn, "%s(%s) failed: %s",
2605 "setsockopt",
2606 "TCP_KEEPCNT",
2607 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2608 return 0;
2609 }
2610#endif
2611
2612 return 1;
2613}

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

2517{
2518 int idle;
2519
2520 if (conn->keepalives_idle == NULL)
2521 return 1;
2522
2524 "keepalives_idle"))
2525 return 0;
2526 if (idle < 0)
2527 idle = 0;
2528
2529#ifdef PG_TCP_KEEPALIVE_IDLE
2531 (char *) &idle, sizeof(idle)) < 0)
2532 {
2534
2535 libpq_append_conn_error(conn, "%s(%s) failed: %s",
2536 "setsockopt",
2538 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2539 return 0;
2540 }
2541#endif
2542
2543 return 1;
2544}

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

2551{
2552 int interval;
2553
2555 return 1;
2556
2558 "keepalives_interval"))
2559 return 0;
2560 if (interval < 0)
2561 interval = 0;
2562
2563#ifdef TCP_KEEPINTVL
2565 (char *) &interval, sizeof(interval)) < 0)
2566 {
2568
2569 libpq_append_conn_error(conn, "%s(%s) failed: %s",
2570 "setsockopt",
2571 "TCP_KEEPINTVL",
2572 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2573 return 0;
2574 }
2575#endif
2576
2577 return 1;
2578}

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

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

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

8218{
8221
8222 /* If at least one of the bounds is not set, the range is valid */
8223 if (min == NULL || max == NULL || strlen(min) == 0 || strlen(max) == 0)
8224 return true;
8225
8226 /*
8227 * If the minimum version is the lowest one we accept, then all options
8228 * for the maximum are valid.
8229 */
8230 if (pg_strcasecmp(min, "TLSv1") == 0)
8231 return true;
8232
8233 /*
8234 * The minimum bound is valid, and cannot be TLSv1, so using TLSv1 for the
8235 * maximum is incorrect.
8236 */
8237 if (pg_strcasecmp(max, "TLSv1") == 0)
8238 return false;
8239
8240 /*
8241 * At this point we know that we have a mix of TLSv1.1 through 1.3
8242 * versions.
8243 */
8244 if (pg_strcasecmp(min, max) > 0)
8245 return false;
8246
8247 return true;
8248}
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 8191 of file fe-connect.c.

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

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

5221{
5222 struct addrinfo *ai = addrlist;
5223
5224 conn->whichaddr = 0;
5225
5226 conn->naddr = 0;
5227 while (ai)
5228 {
5229 ai = ai->ai_next;
5230 conn->naddr++;
5231 }
5232
5233 conn->addr = calloc(conn->naddr, sizeof(AddrInfo));
5234 if (conn->addr == NULL)
5235 {
5236 libpq_append_conn_error(conn, "out of memory");
5237 return 1;
5238 }
5239
5240 ai = addrlist;
5241 for (int i = 0; i < conn->naddr; i++)
5242 {
5243 conn->addr[i].family = ai->ai_family;
5244
5245 memcpy(&conn->addr[i].addr.addr, ai->ai_addr,
5246 ai->ai_addrlen);
5247 conn->addr[i].addr.salen = ai->ai_addrlen;
5248 ai = ai->ai_next;
5249 }
5250
5251 return 0;
5252}
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(), memcpy(), 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 6360 of file fe-connect.c.

6361{
6363 sizeof(uri_designator) - 1) == 0)
6364 return sizeof(uri_designator) - 1;
6365
6367 sizeof(short_uri_designator) - 1) == 0)
6368 return sizeof(short_uri_designator) - 1;
6369
6370 return 0;
6371}
static const char short_uri_designator[]
Definition fe-connect.c:456
static const char uri_designator[]
Definition fe-connect.c:455

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

2499{
2500 int val;
2501
2502 if (conn->keepalives == NULL)
2503 return 1;
2504
2505 if (!pqParseIntParam(conn->keepalives, &val, conn, "keepalives"))
2506 return -1;
2507
2508 return val != 0 ? 1 : 0;
2509}

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

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

Referenced by PQconnectPoll().

◆ pg_g_threadlock

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

Referenced by PQgetThreadLock(), and 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 {"oauth_ca_file", "PGOAUTHCAFILE", NULL, NULL,
417 "OAuth-CA-File", "", 64,
418 offsetof(struct pg_conn, oauth_ca_file)},
419
420 {"sslkeylogfile", NULL, NULL, NULL,
421 "SSL-Key-Log-File", "D", 64,
422 offsetof(struct pg_conn, sslkeylogfile)},
423
424 /* Terminating entry --- MUST BE LAST */
425 {NULL, NULL, NULL, NULL,
426 NULL, NULL, 0}
427};
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 456 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 447 of file fe-connect.c.

448{
451};

Referenced by fill_allowed_sasl_mechs().

◆ uri_designator

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

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

Referenced by uri_prefix_length(), and uri_prefix_length().