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:465

◆ 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:620

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 (size_t i = 0; i < lengthof(conn->allowed_sasl_mechs); i++)
1230}
#define lengthof(array)
Definition c.h:932
int i
Definition isn.c:77
const pg_fe_sasl_mech * allowed_sasl_mechs[2]
Definition libpq-int.h:522

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

2484{
2486
2488 "%s\n",
2489 SOCK_STRERROR(errorno, sebuf, sizeof(sebuf)));
2490
2491 if (conn->raddr.addr.ss_family == AF_UNIX)
2492 libpq_append_conn_error(conn, "\tIs the server running locally and accepting connections on that socket?");
2493 else
2494 libpq_append_conn_error(conn, "\tIs the server running on that host and accepting TCP/IP connections?");
2495}
void libpq_append_conn_error(PGconn *conn, const char *fmt,...)
Definition fe-misc.c:1548
#define SOCK_STRERROR
Definition libpq-int.h:983
#define PG_STRERROR_R_BUFLEN
Definition port.h:279
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
struct sockaddr_storage addr
Definition pqcomm.h:32
PQExpBufferData errorMessage
Definition libpq-int.h:686
SockAddr raddr
Definition libpq-int.h:505

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

4843{
4846
4847 return select_next_encryption_method(conn, false);
4848}
#define Assert(condition)
Definition c.h:1002
static bool select_next_encryption_method(PGconn *conn, bool have_valid_connection)
uint8 failed_enc_methods
Definition libpq-int.h:619

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

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

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

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

6590{
6594 int i = 0;
6595
6596 /*
6597 * If expand_dbname is non-zero, check keyword "dbname" to see if val is
6598 * actually a recognized connection string.
6599 */
6600 while (expand_dbname && keywords[i])
6601 {
6602 const char *pname = keywords[i];
6603 const char *pvalue = values[i];
6604
6605 /* first find "dbname" if any */
6606 if (strcmp(pname, "dbname") == 0 && pvalue)
6607 {
6608 /*
6609 * If value is a connection string, parse it, but do not use
6610 * defaults here -- those get picked up later. We only want to
6611 * override for those parameters actually passed.
6612 */
6614 {
6615 dbname_options = parse_connection_string(pvalue, errorMessage, false);
6616 if (dbname_options == NULL)
6617 return NULL;
6618 }
6619 break;
6620 }
6621 ++i;
6622 }
6623
6624 /* Make a working copy of PQconninfoOptions */
6625 options = conninfo_init(errorMessage);
6626 if (options == NULL)
6627 {
6629 return NULL;
6630 }
6631
6632 /* Parse the keywords/values arrays */
6633 i = 0;
6634 while (keywords[i])
6635 {
6636 const char *pname = keywords[i];
6637 const char *pvalue = values[i];
6638
6639 if (pvalue != NULL && pvalue[0] != '\0')
6640 {
6641 /* Search for the param record */
6642 for (option = options; option->keyword != NULL; option++)
6643 {
6644 if (strcmp(option->keyword, pname) == 0)
6645 break;
6646 }
6647
6648 /* Check for invalid connection option */
6649 if (option->keyword == NULL)
6650 {
6651 libpq_append_error(errorMessage, "invalid connection option \"%s\"", pname);
6654 return NULL;
6655 }
6656
6657 /*
6658 * If we are on the first dbname parameter, and we have a parsed
6659 * connection string, copy those parameters across, overriding any
6660 * existing previous settings.
6661 */
6662 if (strcmp(pname, "dbname") == 0 && dbname_options)
6663 {
6665
6666 for (str_option = dbname_options; str_option->keyword != NULL; str_option++)
6667 {
6668 if (str_option->val != NULL)
6669 {
6670 int k;
6671
6672 for (k = 0; options[k].keyword; k++)
6673 {
6674 if (strcmp(options[k].keyword, str_option->keyword) == 0)
6675 {
6676 free(options[k].val);
6677 options[k].val = strdup(str_option->val);
6678 if (!options[k].val)
6679 {
6680 libpq_append_error(errorMessage, "out of memory");
6683 return NULL;
6684 }
6685 break;
6686 }
6687 }
6688 }
6689 }
6690
6691 /*
6692 * Forget the parsed connection string, so that any subsequent
6693 * dbname parameters will not be expanded.
6694 */
6697 }
6698 else
6699 {
6700 /*
6701 * Store the value, overriding previous settings
6702 */
6703 free(option->val);
6704 option->val = strdup(pvalue);
6705 if (!option->val)
6706 {
6707 libpq_append_error(errorMessage, "out of memory");
6710 return NULL;
6711 }
6712 }
6713 }
6714 ++i;
6715 }
6717
6718 /*
6719 * Add in defaults if the caller wants that.
6720 */
6721 if (use_defaults)
6722 {
6723 if (!conninfo_add_defaults(options, errorMessage))
6724 {
6726 return NULL;
6727 }
6728 }
6729
6730 return options;
6731}
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 7518 of file fe-connect.c.

7519{
7521
7522 for (option = connOptions; option->keyword != NULL; option++)
7523 {
7524 if (strcmp(option->keyword, keyword) == 0)
7525 return option;
7526 }
7527
7528 return NULL;
7529}

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

7430{
7432
7433 option = conninfo_find(connOptions, keyword);
7434
7435 return option ? option->val : NULL;
7436}
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 6318 of file fe-connect.c.

6319{
6323
6324 /*
6325 * Get enough memory for all options in PQconninfoOptions, even if some
6326 * end up being filtered out.
6327 */
6329 if (options == NULL)
6330 {
6331 libpq_append_error(errorMessage, "out of memory");
6332 return NULL;
6333 }
6334 opt_dest = options;
6335
6337 {
6338 /* Only copy the public part of the struct, not the full internal */
6340 opt_dest++;
6341 }
6342 MemSet(opt_dest, 0, sizeof(PQconninfoOption));
6343
6344 return options;
6345}
#define MemSet(start, val, len)
Definition c.h:1147
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 6411 of file fe-connect.c.

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

7458{
7460 char *value_copy;
7461
7462 /*
7463 * For backwards compatibility, requiressl=1 gets translated to
7464 * sslmode=require, and requiressl=0 gets translated to sslmode=prefer
7465 * (which is the default for sslmode).
7466 */
7467 if (strcmp(keyword, "requiressl") == 0)
7468 {
7469 keyword = "sslmode";
7470 if (value[0] == '1')
7471 value = "require";
7472 else
7473 value = "prefer";
7474 }
7475
7476 option = conninfo_find(connOptions, keyword);
7477 if (option == NULL)
7478 {
7479 if (!ignoreMissing)
7480 libpq_append_error(errorMessage,
7481 "invalid connection option \"%s\"",
7482 keyword);
7483 return NULL;
7484 }
7485
7486 if (uri_decode)
7487 {
7488 value_copy = conninfo_uri_decode(value, errorMessage);
7489 if (value_copy == NULL)
7490 /* conninfo_uri_decode already set an error message */
7491 return NULL;
7492 }
7493 else
7494 {
7496 if (value_copy == NULL)
7497 {
7498 libpq_append_error(errorMessage, "out of memory");
7499 return NULL;
7500 }
7501 }
7502
7503 free(option->val);
7505
7506 return option;
7507}
static char * conninfo_uri_decode(const char *str, PQExpBuffer errorMessage)
static struct @175 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(), parseServiceInfo(), and PQconninfo().

◆ conninfo_uri_decode()

static char * conninfo_uri_decode ( const char str,
PQExpBuffer  errorMessage 
)
static

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

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

6882{
6884
6885 /* Make a working copy of PQconninfoOptions */
6886 options = conninfo_init(errorMessage);
6887 if (options == NULL)
6888 return NULL;
6889
6890 if (!conninfo_uri_parse_options(options, uri, errorMessage))
6891 {
6893 return NULL;
6894 }
6895
6896 /*
6897 * Add in defaults if the caller wants that.
6898 */
6899 if (use_defaults)
6900 {
6901 if (!conninfo_add_defaults(options, errorMessage))
6902 {
6904 return NULL;
6905 }
6906 }
6907
6908 return options;
6909}
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 6933 of file fe-connect.c.

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

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

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

8412{
8414
8415 if (acquire)
8416 {
8418 Assert(false);
8419 }
8420 else
8421 {
8423 Assert(false);
8424 }
8425}
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 7978 of file fe-connect.c.

7979{
7980 (void) arg; /* not used */
7981 /* Note: we expect the supplied string to end with a newline already. */
7982 fprintf(stderr, "%s", message);
7983}
#define fprintf(file, fmt, msg)
Definition cubescan.l:21
Datum arg
Definition elog.c:1323

References arg, fb(), and fprintf.

Referenced by pqMakeEmptyPGconn().

◆ defaultNoticeReceiver()

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

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

7964{
7965 (void) arg; /* not used */
7966 if (res->noticeHooks.noticeProc != NULL)
7969}
#define PQresultErrorMessage
void * noticeProcArg
Definition libpq-int.h:153
PQnoticeProcessor noticeProc
Definition libpq-int.h:152
PGNoticeHooks noticeHooks
Definition libpq-int.h:184

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

2428{
2429 if (conn->raddr.addr.ss_family == AF_UNIX)
2430 {
2431 char service[NI_MAXHOST];
2432
2434 NULL, 0,
2435 service, sizeof(service),
2438 libpq_gettext("connection to server on socket \"%s\" failed: "),
2439 service);
2440 }
2441 else
2442 {
2443 const char *displayed_host;
2444 const char *displayed_port;
2445
2446 /* To which host and port were we actually connecting? */
2449 else
2452 if (displayed_port == NULL || displayed_port[0] == '\0')
2454
2455 /*
2456 * If the user did not supply an IP address using 'hostaddr', and
2457 * 'host' was missing or does not match our lookup, display the
2458 * looked-up IP address.
2459 */
2461 host_addr[0] &&
2464 libpq_gettext("connection to server at \"%s\" (%s), port %s failed: "),
2467 else
2469 libpq_gettext("connection to server at \"%s\", port %s failed: "),
2472 }
2473}
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:312
#define libpq_gettext(x)
Definition oauth-utils.h:44
socklen_t salen
Definition pqcomm.h:33
char * host
Definition libpq-int.h:360
char * port
Definition libpq-int.h:362
char * hostaddr
Definition libpq-int.h:361
pg_conn_host_type type
Definition libpq-int.h:359
int whichhost
Definition libpq-int.h:484
pg_conn_host * connhost
Definition libpq-int.h:485

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 (size_t i = 0; i < SASL_MECHANISM_COUNT; i++)
1220}
#define StaticAssertDecl(condition, errmessage)
Definition c.h:1067
#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 5096 of file fe-connect.c.

5097{
5098 /* let any event procs clean up their state data */
5099 for (int i = 0; i < conn->nEvents; i++)
5100 {
5102
5103 evt.conn = conn;
5106 free(conn->events[i].name);
5107 }
5108
5109 /* free everything not freed in pqClosePGconn */
5110 free(conn->pghost);
5112 free(conn->pgport);
5117 free(conn->appname);
5119 free(conn->dbName);
5123 free(conn->pguser);
5124 if (conn->pgpass)
5125 {
5127 free(conn->pgpass);
5128 }
5135 free(conn->sslmode);
5138 free(conn->sslkey);
5139 free(conn->sslcert);
5140 if (conn->sslpassword)
5141 {
5144 }
5147 free(conn->sslcrl);
5149 free(conn->sslsni);
5153 free(conn->gsslib);
5172 /* Note that conn->Pfdebug is not ours to close or free */
5173 free(conn->events);
5175 free(conn->connip);
5179 /* if this is a cancel connection, be_cancel_key may still be allocated */
5181 free(conn->inBuffer);
5183 free(conn->rowBuf);
5186
5187 free(conn);
5188}
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:160
char * name
Definition libpq-int.h:159
PGEventProc proc
Definition libpq-int.h:158
uint8 * be_cancel_key
Definition libpq-int.h:557
char * replication
Definition libpq-int.h:393
uint8 * scram_client_key_binary
Definition libpq-int.h:548
char * sslrootcert
Definition libpq-int.h:415
PGdataValue * rowBuf
Definition libpq-int.h:596
char * sslnegotiation
Definition libpq-int.h:409
char * sslcompression
Definition libpq-int.h:410
char * oauth_discovery_uri
Definition libpq-int.h:443
char * oauth_scope
Definition libpq-int.h:447
char * require_auth
Definition libpq-int.h:430
char * inBuffer
Definition libpq-int.h:579
char * channel_binding
Definition libpq-int.h:400
char * sslcrldir
Definition libpq-int.h:417
char * gssdelegation
Definition libpq-int.h:424
char * pgoptions
Definition libpq-int.h:389
char * sslcrl
Definition libpq-int.h:416
char * pghost
Definition libpq-int.h:376
char * ssl_max_protocol_version
Definition libpq-int.h:428
uint8 * scram_server_key_binary
Definition libpq-int.h:550
char * pgpass
Definition libpq-int.h:398
char * dbName
Definition libpq-int.h:392
char * oauth_client_id
Definition libpq-int.h:445
char * oauth_issuer
Definition libpq-int.h:441
char * fbappname
Definition libpq-int.h:391
char * sslcert
Definition libpq-int.h:412
char * sslcertmode
Definition libpq-int.h:414
char * target_session_attrs
Definition libpq-int.h:429
char * sslpassword
Definition libpq-int.h:413
PQExpBufferData workBuffer
Definition libpq-int.h:690
char * keepalives_idle
Definition libpq-int.h:403
char * connip
Definition libpq-int.h:486
char * pgservicefile
Definition libpq-int.h:395
char * oauth_ca_file
Definition libpq-int.h:449
char * oauth_client_secret
Definition libpq-int.h:446
char * max_protocol_version
Definition libpq-int.h:426
char * load_balance_hosts
Definition libpq-int.h:431
char * pguser
Definition libpq-int.h:397
char * keepalives
Definition libpq-int.h:402
char * min_protocol_version
Definition libpq-int.h:425
char * client_encoding_initial
Definition libpq-int.h:388
char * keepalives_interval
Definition libpq-int.h:404
char * appname
Definition libpq-int.h:390
char * sslmode
Definition libpq-int.h:408
char * pgtcp_user_timeout
Definition libpq-int.h:387
char * ssl_min_protocol_version
Definition libpq-int.h:427
char * oauth_issuer_id
Definition libpq-int.h:442
char * gssencmode
Definition libpq-int.h:420
char * scram_server_key
Definition libpq-int.h:433
int nEvents
Definition libpq-int.h:461
char * pghostaddr
Definition libpq-int.h:380
char * sslkey
Definition libpq-int.h:411
char * scram_client_key
Definition libpq-int.h:432
char * sslkeylogfile
Definition libpq-int.h:434
char * pgpassfile
Definition libpq-int.h:399
char * connect_timeout
Definition libpq-int.h:386
char * krbsrvname
Definition libpq-int.h:421
char * gsslib
Definition libpq-int.h:422
char * pgport
Definition libpq-int.h:384
char * pgservice
Definition libpq-int.h:394
char * keepalives_count
Definition libpq-int.h:406
char * requirepeer
Definition libpq-int.h:419
char * sslsni
Definition libpq-int.h:418
PGEvent * events
Definition libpq-int.h:460
char * outBuffer
Definition libpq-int.h:586

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

7408{
7409 if ('0' <= digit && digit <= '9')
7410 *value = digit - '0';
7411 else if ('A' <= digit && digit <= 'F')
7412 *value = digit - 'A' + 10;
7413 else if ('a' <= digit && digit <= 'f')
7414 *value = digit - 'a' + 10;
7415 else
7416 return false;
7417
7418 return true;
7419}

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

2395{
2396 struct sockaddr_storage *addr = &conn->raddr.addr;
2397
2398 if (addr->ss_family == AF_INET)
2399 {
2401 &((struct sockaddr_in *) addr)->sin_addr.s_addr,
2402 32,
2404 host_addr[0] = '\0';
2405 }
2406 else if (addr->ss_family == AF_INET6)
2407 {
2409 &((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr,
2410 128,
2412 host_addr[0] = '\0';
2413 }
2414 else
2415 host_addr[0] = '\0';
2416}
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 (size_t 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 4752 of file fe-connect.c.

4753{
4754 if (conn->raddr.addr.ss_family == AF_UNIX)
4755 {
4756 /* Don't request SSL or GSSAPI over Unix sockets */
4758
4759 /*
4760 * XXX: we probably should not do this. sslmode=require works
4761 * differently
4762 */
4763 if (conn->gssencmode[0] == 'r')
4764 {
4766 "GSSAPI encryption required but it is not supported over a local socket");
4769 return false;
4770 }
4771
4774 return true;
4775 }
4776
4777 /* initialize based on sslmode and gssencmode */
4779
4780#ifdef USE_SSL
4781 /* sslmode anything but 'disable', and GSSAPI not required */
4782 if (conn->sslmode[0] != 'd' && conn->gssencmode[0] != 'r')
4783 {
4785 }
4786#endif
4787
4788#ifdef ENABLE_GSS
4789 if (conn->gssencmode[0] != 'd')
4791#endif
4792
4793 if ((conn->sslmode[0] == 'd' || conn->sslmode[0] == 'p' || conn->sslmode[0] == 'a') &&
4794 (conn->gssencmode[0] == 'd' || conn->gssencmode[0] == 'p'))
4795 {
4797 }
4798
4799 return select_next_encryption_method(conn, false);
4800}
#define ENC_PLAINTEXT
Definition libpq-int.h:231
#define ENC_GSSAPI
Definition libpq-int.h:232
#define ENC_SSL
Definition libpq-int.h:233
#define ENC_ERROR
Definition libpq-int.h:230
uint8 allowed_enc_methods
Definition libpq-int.h:618

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

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

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:684
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:566
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 6357 of file fe-connect.c.

6359{
6360 /* Parse as URI if connection string matches URI prefix */
6361 if (uri_prefix_length(connstr) != 0)
6362 return conninfo_uri_parse(connstr, errorMessage, use_defaults);
6363
6364 /* Parse as default otherwise */
6365 return conninfo_parse(connstr, errorMessage, use_defaults);
6366}
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:82

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

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

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

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

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

8186{
8187 /* If it was 'invalid authorization', add pgpassfile mention */
8188 /* only works with >= 9.0 servers */
8189 if (conn->password_needed &&
8191 conn->result)
8192 {
8193 const char *sqlstate = PQresultErrorField(conn->result,
8195
8196 if (sqlstate && strcmp(sqlstate, ERRCODE_INVALID_PASSWORD) == 0)
8197 libpq_append_conn_error(conn, "password retrieved from file \"%s\"",
8198 conn->pgpassfile);
8199 }
8200}
#define ERRCODE_INVALID_PASSWORD
Definition fe-connect.c:93
#define PQresultErrorField
#define PG_DIAG_SQLSTATE
char * password
Definition libpq-int.h:364
PGresult * result
Definition libpq-int.h:609
bool password_needed
Definition libpq-int.h:511

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

5313{
5314 /*
5315 * If possible, send Terminate message to close the connection politely.
5316 */
5318
5319 /*
5320 * Must reset the blocking status so a possible reconnect will work.
5321 *
5322 * Don't call PQsetnonblocking() because it will fail if it's unable to
5323 * flush the connection.
5324 */
5325 conn->nonblocking = false;
5326
5327 /*
5328 * Close the connection, reset all transient state, flush I/O buffers.
5329 * Note that this includes clearing conn's error state; we're no longer
5330 * interested in any failures associated with the old connection, and we
5331 * want a clean slate for any new connection attempt.
5332 */
5333 pqDropConnection(conn, true);
5334 conn->status = CONNECTION_BAD; /* Well, not really _bad_ - just absent */
5339 pqClearAsyncResult(conn); /* deallocate result */
5341
5342 /*
5343 * Release addrinfo, but since cancel requests never change their addrinfo
5344 * we don't do that. Otherwise we would have to rebuild it during a
5345 * PQcancelReset.
5346 */
5347 if (!conn->cancelRequest)
5349
5350 /* Reset all state obtained from server, too */
5352}
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:216
#define pqClearConnErrorState(conn)
Definition libpq-int.h:933
PGTransactionStatusType xactStatus
Definition libpq-int.h:467
bool cancelRequest
Definition libpq-int.h:436
bool nonblocking
Definition libpq-int.h:470
PGAsyncStatusType asyncStatus
Definition libpq-int.h:466
PGpipelineStatus pipelineStatus
Definition libpq-int.h:472

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

2216{
2219
2220 /* We don't actually report any errors here, but callees want a buffer */
2223 return NULL; /* out of memory already :-( */
2224
2226 if (connOptions != NULL)
2227 {
2228 /* pass NULL errorBuf to ignore errors */
2230 {
2232 connOptions = NULL;
2233 }
2234 }
2235
2237 return connOptions;
2238}

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

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

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

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

7813{
7814 char *password;
7815
7816 if (!conn)
7817 return false;
7818 password = PQpass(conn);
7819 if (conn->password_needed &&
7820 (password == NULL || password[0] == '\0'))
7821 return true;
7822 else
7823 return false;
7824}
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 7838 of file fe-connect.c.

7839{
7840 if (!conn)
7841 return false;
7842 if (conn->gssapi_used)
7843 return true;
7844 else
7845 return false;
7846}
bool gssapi_used
Definition libpq-int.h:512

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

7828{
7829 if (!conn)
7830 return false;
7831 if (conn->password_needed)
7832 return true;
7833 else
7834 return false;
7835}

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 /*
1260 * Allocate memory for details about each host to which we might possibly
1261 * try to connect. For that, count the number of elements in the hostaddr
1262 * or host options. If neither is given, assume one host.
1263 */
1264 conn->whichhost = 0;
1265 if (conn->pghostaddr && conn->pghostaddr[0] != '\0')
1267 else if (conn->pghost && conn->pghost[0] != '\0')
1269 else
1270 conn->nconnhost = 1;
1272 calloc(conn->nconnhost, sizeof(pg_conn_host));
1273 if (conn->connhost == NULL)
1274 goto oom_error;
1275
1276 /*
1277 * We now have one pg_conn_host structure per possible host. Fill in the
1278 * host and hostaddr fields for each, by splitting the parameter strings.
1279 */
1280 if (conn->pghostaddr != NULL && conn->pghostaddr[0] != '\0')
1281 {
1282 int i;
1283 char *s = conn->pghostaddr;
1284 bool more = true;
1285
1286 for (i = 0; i < conn->nconnhost && more; i++)
1287 {
1289 if (conn->connhost[i].hostaddr == NULL)
1290 goto oom_error;
1291 }
1292
1293 /*
1294 * If hostaddr was given, the array was allocated according to the
1295 * number of elements in the hostaddr list, so it really should be the
1296 * right size.
1297 */
1298 Assert(!more);
1299 Assert(i == conn->nconnhost);
1300 }
1301
1302 if (conn->pghost != NULL && conn->pghost[0] != '\0')
1303 {
1304 int i;
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 (int 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 int i;
1374 char *s = conn->pgport;
1375 bool more = true;
1376
1377 for (i = 0; i < conn->nconnhost && more; i++)
1378 {
1380 if (conn->connhost[i].port == NULL)
1381 goto oom_error;
1382 }
1383
1384 /*
1385 * If exactly one port was given, use it for every host. Otherwise,
1386 * there must be exactly as many ports as there were hosts.
1387 */
1388 if (i == 1 && !more)
1389 {
1390 for (i = 1; i < conn->nconnhost; i++)
1391 {
1393 if (conn->connhost[i].port == NULL)
1394 goto oom_error;
1395 }
1396 }
1397 else if (more || i != conn->nconnhost)
1398 {
1400 libpq_append_conn_error(conn, "could not match %d port numbers to %d hosts",
1402 return false;
1403 }
1404 }
1405
1406 /*
1407 * If user name was not given, fetch it. (Most likely, the fetch will
1408 * fail, since the only way we get here is if pg_fe_getauthname() failed
1409 * during conninfo_add_defaults(). But now we want an error message.)
1410 */
1411 if (conn->pguser == NULL || conn->pguser[0] == '\0')
1412 {
1413 free(conn->pguser);
1415 if (!conn->pguser)
1416 {
1418 return false;
1419 }
1420 }
1421
1422 /*
1423 * If database name was not given, default it to equal user name
1424 */
1425 if (conn->dbName == NULL || conn->dbName[0] == '\0')
1426 {
1427 free(conn->dbName);
1429 if (!conn->dbName)
1430 goto oom_error;
1431 }
1432
1433 /*
1434 * If password was not given, try to look it up in password file. Note
1435 * that the result might be different for each host/port pair.
1436 */
1437 if (conn->pgpass == NULL || conn->pgpass[0] == '\0')
1438 {
1439 /* If password file wasn't specified, use ~/PGPASSFILE */
1440 if (conn->pgpassfile == NULL || conn->pgpassfile[0] == '\0')
1441 {
1442 char homedir[MAXPGPATH];
1443
1444 if (pqGetHomeDirectory(homedir, sizeof(homedir)))
1445 {
1448 if (!conn->pgpassfile)
1449 goto oom_error;
1450 snprintf(conn->pgpassfile, MAXPGPATH, "%s/%s",
1452 }
1453 }
1454
1455 if (conn->pgpassfile != NULL && conn->pgpassfile[0] != '\0')
1456 {
1457 for (int i = 0; i < conn->nconnhost; i++)
1458 {
1459 /*
1460 * Try to get a password for this host from file. We use host
1461 * for the hostname search key if given, else hostaddr (at
1462 * least one of them is guaranteed nonempty by now).
1463 */
1464 const char *pwhost = conn->connhost[i].host;
1465 const char *password_errmsg = NULL;
1466
1467 if (pwhost == NULL || pwhost[0] == '\0')
1469
1472 conn->connhost[i].port,
1473 conn->dbName,
1474 conn->pguser,
1477
1478 if (password_errmsg != NULL)
1479 {
1482 return false;
1483 }
1484 }
1485 }
1486 }
1487
1488 /*
1489 * parse and validate require_auth option
1490 */
1491 if (conn->require_auth && conn->require_auth[0])
1492 {
1493 char *s = conn->require_auth;
1494 bool first,
1495 more;
1496 bool negated = false;
1497
1498 /*
1499 * By default, start from an empty set of allowed methods and
1500 * mechanisms, and add to it.
1501 */
1502 conn->auth_required = true;
1505
1506 for (first = true, more = true; more; first = false)
1507 {
1508 char *method,
1509 *part;
1510 uint32 bits = 0;
1511 const pg_fe_sasl_mech *mech = NULL;
1512
1514 if (part == NULL)
1515 goto oom_error;
1516
1517 /*
1518 * Check for negation, e.g. '!password'. If one element is
1519 * negated, they all have to be.
1520 */
1521 method = part;
1522 if (*method == '!')
1523 {
1524 if (first)
1525 {
1526 /*
1527 * Switch to a permissive set of allowed methods and
1528 * mechanisms, and subtract from it.
1529 */
1530 conn->auth_required = false;
1533 }
1534 else if (!negated)
1535 {
1537 libpq_append_conn_error(conn, "negative require_auth method \"%s\" cannot be mixed with non-negative methods",
1538 method);
1539
1540 free(part);
1541 return false;
1542 }
1543
1544 negated = true;
1545 method++;
1546 }
1547 else if (negated)
1548 {
1550 libpq_append_conn_error(conn, "require_auth method \"%s\" cannot be mixed with negative methods",
1551 method);
1552
1553 free(part);
1554 return false;
1555 }
1556
1557 /*
1558 * First group: methods that can be handled solely with the
1559 * authentication request codes.
1560 */
1561 if (strcmp(method, "password") == 0)
1562 {
1563 bits = (1 << AUTH_REQ_PASSWORD);
1564 }
1565 else if (strcmp(method, "md5") == 0)
1566 {
1567 bits = (1 << AUTH_REQ_MD5);
1568 }
1569 else if (strcmp(method, "gss") == 0)
1570 {
1571 bits = (1 << AUTH_REQ_GSS);
1572 bits |= (1 << AUTH_REQ_GSS_CONT);
1573 }
1574 else if (strcmp(method, "sspi") == 0)
1575 {
1576 bits = (1 << AUTH_REQ_SSPI);
1577 bits |= (1 << AUTH_REQ_GSS_CONT);
1578 }
1579
1580 /*
1581 * Next group: SASL mechanisms. All of these use the same request
1582 * codes, so the list of allowed mechanisms is tracked separately.
1583 *
1584 * supported_sasl_mechs must contain all mechanisms handled here.
1585 */
1586 else if (strcmp(method, "scram-sha-256") == 0)
1587 {
1589 }
1590 else if (strcmp(method, "oauth") == 0)
1591 {
1593 }
1594
1595 /*
1596 * Final group: meta-options.
1597 */
1598 else if (strcmp(method, "none") == 0)
1599 {
1600 /*
1601 * Special case: let the user explicitly allow (or disallow)
1602 * connections where the server does not send an explicit
1603 * authentication challenge, such as "trust" and "cert" auth.
1604 */
1605 if (negated) /* "!none" */
1606 {
1607 if (conn->auth_required)
1608 goto duplicate;
1609
1610 conn->auth_required = true;
1611 }
1612 else /* "none" */
1613 {
1614 if (!conn->auth_required)
1615 goto duplicate;
1616
1617 conn->auth_required = false;
1618 }
1619
1620 free(part);
1621 continue; /* avoid the bitmask manipulation below */
1622 }
1623 else
1624 {
1626 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1627 "require_auth", method);
1628
1629 free(part);
1630 return false;
1631 }
1632
1633 if (mech)
1634 {
1635 /*
1636 * Update the mechanism set only. The method bitmask will be
1637 * updated for SASL further down.
1638 */
1639 Assert(!bits);
1640
1641 if (negated)
1642 {
1643 int i;
1644
1645 /* Remove the existing mechanism from the list. */
1647 if (i < 0)
1648 goto duplicate;
1649
1651 }
1652 else
1653 {
1654 int i;
1655
1656 /*
1657 * Find a space to put the new mechanism (after making
1658 * sure it's not already there).
1659 */
1661 if (i >= 0)
1662 goto duplicate;
1663
1665 if (i < 0)
1666 {
1667 /* Should not happen; the pointer list is corrupted. */
1668 Assert(false);
1669
1672 "internal error: no space in allowed_sasl_mechs");
1673 free(part);
1674 return false;
1675 }
1676
1678 }
1679 }
1680 else
1681 {
1682 /* Update the method bitmask. */
1683 Assert(bits);
1684
1685 if (negated)
1686 {
1687 if ((conn->allowed_auth_methods & bits) == 0)
1688 goto duplicate;
1689
1691 }
1692 else
1693 {
1694 if ((conn->allowed_auth_methods & bits) == bits)
1695 goto duplicate;
1696
1697 conn->allowed_auth_methods |= bits;
1698 }
1699 }
1700
1701 free(part);
1702 continue;
1703
1704 duplicate:
1705
1706 /*
1707 * A duplicated method probably indicates a typo in a setting
1708 * where typos are extremely risky.
1709 */
1711 libpq_append_conn_error(conn, "require_auth method \"%s\" is specified more than once",
1712 part);
1713
1714 free(part);
1715 return false;
1716 }
1717
1718 /*
1719 * Finally, allow SASL authentication requests if (and only if) we've
1720 * allowed any mechanisms.
1721 */
1722 {
1723 bool allowed = false;
1724 const uint32 sasl_bits =
1725 (1 << AUTH_REQ_SASL)
1726 | (1 << AUTH_REQ_SASL_CONT)
1727 | (1 << AUTH_REQ_SASL_FIN);
1728
1729 for (size_t i = 0; i < lengthof(conn->allowed_sasl_mechs); i++)
1730 {
1732 {
1733 allowed = true;
1734 break;
1735 }
1736 }
1737
1738 /*
1739 * For the standard case, add the SASL bits to the (default-empty)
1740 * set if needed. For the negated case, remove them.
1741 */
1742 if (!negated && allowed)
1744 else if (negated && !allowed)
1746 }
1747 }
1748
1749 /*
1750 * validate channel_binding option
1751 */
1752 if (conn->channel_binding)
1753 {
1754 if (strcmp(conn->channel_binding, "disable") != 0
1755 && strcmp(conn->channel_binding, "prefer") != 0
1756 && strcmp(conn->channel_binding, "require") != 0)
1757 {
1759 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1760 "channel_binding", conn->channel_binding);
1761 return false;
1762 }
1763 }
1764 else
1765 {
1767 if (!conn->channel_binding)
1768 goto oom_error;
1769 }
1770
1771#ifndef USE_SSL
1772
1773 /*
1774 * sslrootcert=system is not supported. Since setting this changes the
1775 * default sslmode, check this _before_ we validate sslmode, to avoid
1776 * confusing the user with errors for an option they may not have set.
1777 */
1778 if (conn->sslrootcert
1779 && strcmp(conn->sslrootcert, "system") == 0)
1780 {
1782 libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1783 "sslrootcert", conn->sslrootcert);
1784 return false;
1785 }
1786#endif
1787
1788 /*
1789 * validate sslmode option
1790 */
1791 if (conn->sslmode)
1792 {
1793 if (strcmp(conn->sslmode, "disable") != 0
1794 && strcmp(conn->sslmode, "allow") != 0
1795 && strcmp(conn->sslmode, "prefer") != 0
1796 && strcmp(conn->sslmode, "require") != 0
1797 && strcmp(conn->sslmode, "verify-ca") != 0
1798 && strcmp(conn->sslmode, "verify-full") != 0)
1799 {
1801 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1802 "sslmode", conn->sslmode);
1803 return false;
1804 }
1805
1806#ifndef USE_SSL
1807 switch (conn->sslmode[0])
1808 {
1809 case 'a': /* "allow" */
1810 case 'p': /* "prefer" */
1811
1812 /*
1813 * warn user that an SSL connection will never be negotiated
1814 * since SSL was not compiled in?
1815 */
1816 break;
1817
1818 case 'r': /* "require" */
1819 case 'v': /* "verify-ca" or "verify-full" */
1821 libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1822 "sslmode", conn->sslmode);
1823 return false;
1824 }
1825#endif
1826 }
1827 else
1828 {
1830 if (!conn->sslmode)
1831 goto oom_error;
1832 }
1833
1834 /*
1835 * validate sslnegotiation option, default is "postgres" for the postgres
1836 * style negotiated connection with an extra round trip but more options.
1837 */
1838 if (conn->sslnegotiation)
1839 {
1840 if (strcmp(conn->sslnegotiation, "postgres") != 0
1841 && strcmp(conn->sslnegotiation, "direct") != 0)
1842 {
1844 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1845 "sslnegotiation", conn->sslnegotiation);
1846 return false;
1847 }
1848
1849#ifndef USE_SSL
1850 if (conn->sslnegotiation[0] != 'p')
1851 {
1853 libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1854 "sslnegotiation", conn->sslnegotiation);
1855 return false;
1856 }
1857#endif
1858
1859 /*
1860 * Don't allow direct SSL negotiation with sslmode='prefer', because
1861 * that poses a risk of unintentional fallback to plaintext connection
1862 * when connecting to a pre-v17 server that does not support direct
1863 * SSL connections. To keep things simple, don't allow it with
1864 * sslmode='allow' or sslmode='disable' either. If a user goes through
1865 * the trouble of setting sslnegotiation='direct', they probably
1866 * intend to use SSL, and sslmode=disable or allow is probably a user
1867 * mistake anyway.
1868 */
1869 if (conn->sslnegotiation[0] == 'd' &&
1870 conn->sslmode[0] != 'r' && conn->sslmode[0] != 'v')
1871 {
1873 libpq_append_conn_error(conn, "weak sslmode \"%s\" may not be used with sslnegotiation=direct (use \"require\", \"verify-ca\", or \"verify-full\")",
1874 conn->sslmode);
1875 return false;
1876 }
1877 }
1878 else
1879 {
1881 if (!conn->sslnegotiation)
1882 goto oom_error;
1883 }
1884
1885#ifdef USE_SSL
1886
1887 /*
1888 * If sslrootcert=system, make sure our chosen sslmode is compatible.
1889 */
1890 if (conn->sslrootcert
1891 && strcmp(conn->sslrootcert, "system") == 0
1892 && strcmp(conn->sslmode, "verify-full") != 0)
1893 {
1895 libpq_append_conn_error(conn, "weak sslmode \"%s\" may not be used with sslrootcert=system (use \"verify-full\")",
1896 conn->sslmode);
1897 return false;
1898 }
1899#endif
1900
1901 /*
1902 * Validate TLS protocol versions for ssl_min_protocol_version and
1903 * ssl_max_protocol_version.
1904 */
1906 {
1908 libpq_append_conn_error(conn, "invalid \"%s\" value: \"%s\"",
1909 "ssl_min_protocol_version",
1911 return false;
1912 }
1914 {
1916 libpq_append_conn_error(conn, "invalid \"%s\" value: \"%s\"",
1917 "ssl_max_protocol_version",
1919 return false;
1920 }
1921
1922 /*
1923 * Check if the range of SSL protocols defined is correct. This is done
1924 * at this early step because this is independent of the SSL
1925 * implementation used, and this avoids unnecessary cycles with an
1926 * already-built SSL context when the connection is being established, as
1927 * it would be doomed anyway.
1928 */
1931 {
1933 libpq_append_conn_error(conn, "invalid SSL protocol version range");
1934 return false;
1935 }
1936
1937 /*
1938 * validate sslcertmode option
1939 */
1940 if (conn->sslcertmode)
1941 {
1942 if (strcmp(conn->sslcertmode, "disable") != 0 &&
1943 strcmp(conn->sslcertmode, "allow") != 0 &&
1944 strcmp(conn->sslcertmode, "require") != 0)
1945 {
1947 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
1948 "sslcertmode", conn->sslcertmode);
1949 return false;
1950 }
1951#ifndef USE_SSL
1952 if (strcmp(conn->sslcertmode, "require") == 0)
1953 {
1955 libpq_append_conn_error(conn, "%s value \"%s\" invalid when SSL support is not compiled in",
1956 "sslcertmode", conn->sslcertmode);
1957 return false;
1958 }
1959#endif
1960#ifndef HAVE_SSL_CTX_SET_CERT_CB
1961
1962 /*
1963 * Without a certificate callback, the current implementation can't
1964 * figure out if a certificate was actually requested, so "require" is
1965 * useless.
1966 */
1967 if (strcmp(conn->sslcertmode, "require") == 0)
1968 {
1970 libpq_append_conn_error(conn, "%s value \"%s\" is not supported (check OpenSSL version)",
1971 "sslcertmode", conn->sslcertmode);
1972 return false;
1973 }
1974#endif
1975 }
1976 else
1977 {
1979 if (!conn->sslcertmode)
1980 goto oom_error;
1981 }
1982
1983 /*
1984 * validate gssencmode option
1985 */
1986 if (conn->gssencmode)
1987 {
1988 if (strcmp(conn->gssencmode, "disable") != 0 &&
1989 strcmp(conn->gssencmode, "prefer") != 0 &&
1990 strcmp(conn->gssencmode, "require") != 0)
1991 {
1993 libpq_append_conn_error(conn, "invalid %s value: \"%s\"", "gssencmode", conn->gssencmode);
1994 return false;
1995 }
1996#ifndef ENABLE_GSS
1997 if (strcmp(conn->gssencmode, "require") == 0)
1998 {
2000 libpq_append_conn_error(conn, "gssencmode value \"%s\" invalid when GSSAPI support is not compiled in",
2001 conn->gssencmode);
2002 return false;
2003 }
2004#endif
2005 }
2006 else
2007 {
2009 if (!conn->gssencmode)
2010 goto oom_error;
2011 }
2012
2013 /*
2014 * validate target_session_attrs option, and set target_server_type
2015 */
2017 {
2018 if (strcmp(conn->target_session_attrs, "any") == 0)
2020 else if (strcmp(conn->target_session_attrs, "read-write") == 0)
2022 else if (strcmp(conn->target_session_attrs, "read-only") == 0)
2024 else if (strcmp(conn->target_session_attrs, "primary") == 0)
2026 else if (strcmp(conn->target_session_attrs, "standby") == 0)
2028 else if (strcmp(conn->target_session_attrs, "prefer-standby") == 0)
2030 else
2031 {
2033 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
2034 "target_session_attrs",
2036 return false;
2037 }
2038 }
2039 else
2041
2043 {
2044 int len;
2045
2049 goto oom_error;
2052 if (len < 0)
2053 {
2054 libpq_append_conn_error(conn, "invalid SCRAM client key");
2055 return false;
2056 }
2057 if (len != SCRAM_MAX_KEY_LEN)
2058 {
2059 libpq_append_conn_error(conn, "invalid SCRAM client key length: %d", len);
2060 return false;
2061 }
2063 }
2064
2066 {
2067 int len;
2068
2072 goto oom_error;
2075 if (len < 0)
2076 {
2077 libpq_append_conn_error(conn, "invalid SCRAM server key");
2078 return false;
2079 }
2080 if (len != SCRAM_MAX_KEY_LEN)
2081 {
2082 libpq_append_conn_error(conn, "invalid SCRAM server key length: %d", len);
2083 return false;
2084 }
2086 }
2087
2088 /*
2089 * validate load_balance_hosts option, and set load_balance_type
2090 */
2092 {
2093 if (strcmp(conn->load_balance_hosts, "disable") == 0)
2095 else if (strcmp(conn->load_balance_hosts, "random") == 0)
2097 else
2098 {
2100 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
2101 "load_balance_hosts",
2103 return false;
2104 }
2105 }
2106 else
2108
2110 {
2112
2113 /*
2114 * This is the "inside-out" variant of the Fisher-Yates shuffle
2115 * algorithm. Notionally, we append each new value to the array and
2116 * then swap it with a randomly-chosen array element (possibly
2117 * including itself, else we fail to generate permutations with the
2118 * last integer last). The swap step can be optimized by combining it
2119 * with the insertion.
2120 */
2121 for (int i = 1; i < conn->nconnhost; i++)
2122 {
2123 int j = pg_prng_uint64_range(&conn->prng_state, 0, i);
2125
2126 conn->connhost[j] = conn->connhost[i];
2127 conn->connhost[i] = temp;
2128 }
2129 }
2130
2132 {
2133 if (!pqParseProtocolVersion(conn->min_protocol_version, &conn->min_pversion, conn, "min_protocol_version"))
2134 {
2136 return false;
2137 }
2138 }
2139 else
2140 {
2142 }
2143
2145 {
2146 if (!pqParseProtocolVersion(conn->max_protocol_version, &conn->max_pversion, conn, "max_protocol_version"))
2147 {
2149 return false;
2150 }
2151 }
2152 else
2153 {
2154 /*
2155 * Default to PG_PROTOCOL_GREASE, which is larger than all real
2156 * versions, to test negotiation. The server should automatically
2157 * downgrade to a supported version.
2158 *
2159 * This behavior is for 19beta only. It will be reverted before RC1.
2160 */
2162 }
2163
2165 {
2167 libpq_append_conn_error(conn, "\"%s\" is greater than \"%s\"", "min_protocol_version", "max_protocol_version");
2168 return false;
2169 }
2170
2171 /*
2172 * Resolve special "auto" client_encoding from the locale
2173 */
2175 strcmp(conn->client_encoding_initial, "auto") == 0)
2176 {
2180 goto oom_error;
2181 }
2182
2183 /*
2184 * Only if we get this far is it appropriate to try to connect. (We need a
2185 * state flag, rather than just the boolean result of this function, in
2186 * case someone tries to PQreset() the PGconn.)
2187 */
2188 conn->options_valid = true;
2189
2190 return true;
2191
2192oom_error:
2194 libpq_append_conn_error(conn, "out of memory");
2195 return false;
2196}
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:683
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:250
@ LOAD_BALANCE_RANDOM
Definition libpq-int.h:251
@ CHT_UNIX_SOCKET
Definition libpq-int.h:313
@ CHT_HOST_NAME
Definition libpq-int.h:311
@ SERVER_TYPE_STANDBY
Definition libpq-int.h:242
@ SERVER_TYPE_PRIMARY
Definition libpq-int.h:241
@ SERVER_TYPE_ANY
Definition libpq-int.h:238
@ SERVER_TYPE_READ_WRITE
Definition libpq-int.h:239
@ SERVER_TYPE_READ_ONLY
Definition libpq-int.h:240
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:483
size_t scram_client_key_len
Definition libpq-int.h:547
ProtocolVersion min_pversion
Definition libpq-int.h:551
uint32 allowed_auth_methods
Definition libpq-int.h:520
bool auth_required
Definition libpq-int.h:518
ProtocolVersion max_pversion
Definition libpq-int.h:552
PGLoadBalanceType load_balance_type
Definition libpq-int.h:538
size_t scram_server_key_len
Definition libpq-int.h:549

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

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

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_complete(), 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_start(), 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_start(), PQconnectdbParams(), and PQpingParams().

◆ PQconninfo()

PQconninfoOption * PQconninfo ( PGconn conn)

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

7537{
7540
7541 if (conn == NULL)
7542 return NULL;
7543
7544 /*
7545 * We don't actually report any errors here, but callees want a buffer,
7546 * and we prefer not to trash the conn's errorMessage.
7547 */
7550 return NULL; /* out of memory already :-( */
7551
7553
7554 if (connOptions != NULL)
7555 {
7557
7558 for (option = PQconninfoOptions; option->keyword; option++)
7559 {
7560 char **connmember;
7561
7562 if (option->connofs < 0)
7563 continue;
7564
7565 connmember = (char **) ((char *) conn + option->connofs);
7566
7567 if (*connmember)
7569 &errorBuf, true, false);
7570 }
7571 }
7572
7574
7575 return connOptions;
7576}

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:398
PGcmdQueueEntry * cmd_queue_recycle
Definition libpq-int.h:499
PGcmdQueueEntry * cmd_queue_tail
Definition libpq-int.h:493
void * sasl_state
Definition libpq-int.h:615
PGcmdQueueEntry * cmd_queue_head
Definition libpq-int.h:492
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_internal().

◆ 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:247
struct pgParameterStatus * next
Definition libpq-int.h:272
char * write_err_msg
Definition libpq-int.h:516
PGnotify * notifyHead
Definition libpq-int.h:479
bool std_strings
Definition libpq-int.h:560
bool write_failed
Definition libpq-int.h:515
bool client_finished_auth
Definition libpq-int.h:524
PGnotify * notifyTail
Definition libpq-int.h:480
pgParameterStatus * pstatus
Definition libpq-int.h:558
int scram_sha_256_iterations
Definition libpq-int.h:616
PGlobjfuncs * lobjfuncs
Definition libpq-int.h:565
int be_cancel_key_len
Definition libpq-int.h:556

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

7760{
7761 if (!conn)
7762 return libpq_gettext("connection pointer is NULL\n");
7763
7764 /*
7765 * The errorMessage buffer might be marked "broken" due to having
7766 * previously failed to allocate enough memory for the message. In that
7767 * case, tell the application we ran out of memory.
7768 */
7770 return libpq_gettext("out of memory\n");
7771
7772 return conn->errorMessage.data;
7773}
#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_exec(), libpqrcv_identify_system(), 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 5359 of file fe-connect.c.

5360{
5361 if (conn)
5362 {
5365 }
5366}
void pqClosePGconn(PGconn *conn)
static void freePGconn(PGconn *conn)

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

Referenced by appendQualifiedRelation(), BaseBackup(), check_for_connection_status(), 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_subscription_info(), get_tablespace_paths(), get_template0_info(), GetConnection(), libpqsrv_connect_complete(), libpqsrv_disconnect(), LogStreamerMain(), main(), main(), PQcancelFinish(), PQping(), PQpingParams(), process_slot(), ReconnectToServer(), reindex_all_databases(), reindex_one_database(), 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:149

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

Referenced by pqDropConnection().

◆ PQfullProtocolVersion()

int PQfullProtocolVersion ( const PGconn conn)

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

7740{
7741 if (!conn)
7742 return 0;
7743 if (conn->status == CONNECTION_BAD)
7744 return 0;
7746}
#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 8287 of file fe-connect.c.

8288{
8289#ifndef WIN32
8290 const char *home;
8291
8292 home = getenv("HOME");
8293 if (home && home[0])
8294 {
8296 return true;
8297 }
8298 else
8299 {
8300 struct passwd pwbuf;
8301 struct passwd *pw;
8302 char tmpbuf[1024];
8303 int rc;
8304
8305 rc = getpwuid_r(geteuid(), &pwbuf, tmpbuf, sizeof tmpbuf, &pw);
8306 if (rc != 0 || !pw)
8307 return false;
8308 strlcpy(buf, pw->pw_dir, bufsize);
8309 return true;
8310 }
8311#else
8312 char tmppath[MAX_PATH];
8313
8314 ZeroMemory(tmppath, sizeof(tmppath));
8316 return false;
8317 snprintf(buf, bufsize, "%s/postgresql", tmppath);
8318 return true;
8319#endif
8320}
#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 8441 of file fe-connect.c.

8442{
8444 return pg_g_threadlock;
8445}
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 7626 of file fe-connect.c.

7627{
7628 if (!conn)
7629 return NULL;
7630
7631 if (conn->connhost != NULL)
7632 {
7633 /*
7634 * Return the verbatim host value provided by user, or hostaddr in its
7635 * lack.
7636 */
7637 if (conn->connhost[conn->whichhost].host != NULL &&
7638 conn->connhost[conn->whichhost].host[0] != '\0')
7639 return conn->connhost[conn->whichhost].host;
7640 else if (conn->connhost[conn->whichhost].hostaddr != NULL &&
7641 conn->connhost[conn->whichhost].hostaddr[0] != '\0')
7643 }
7644
7645 return "";
7646}

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

7650{
7651 if (!conn)
7652 return NULL;
7653
7654 /* Return the parsed IP address */
7655 if (conn->connhost != NULL && conn->connip != NULL)
7656 return conn->connip;
7657
7658 return "";
7659}

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

4997{
4998 PGconn *conn;
4999
5000#ifdef WIN32
5001
5002 /*
5003 * Make sure socket support is up and running in this process.
5004 *
5005 * Note: the Windows documentation says that we should eventually do a
5006 * matching WSACleanup() call, but experience suggests that that is at
5007 * least as likely to cause problems as fix them. So we don't.
5008 */
5009 static bool wsastartup_done = false;
5010
5011 if (!wsastartup_done)
5012 {
5014
5015 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
5016 return NULL;
5017 wsastartup_done = true;
5018 }
5019
5020 /* Forget any earlier error */
5021 WSASetLastError(0);
5022#endif /* WIN32 */
5023
5024 conn = (PGconn *) malloc(sizeof(PGconn));
5025 if (conn == NULL)
5026 return conn;
5027
5028 /* Zero all pointers and booleans */
5029 MemSet(conn, 0, sizeof(PGconn));
5030
5031 /* install default notice hooks */
5034
5039 conn->options_valid = false;
5040 conn->nonblocking = false;
5042 conn->std_strings = false; /* unless server says differently */
5050 conn->Pfdebug = NULL;
5051
5052 /*
5053 * We try to send at least 8K at a time, which is the usual size of pipe
5054 * buffers on Unix systems. That way, when we are sending a large amount
5055 * of data, we avoid incurring extra kernel context swaps for partial
5056 * bufferloads. The output buffer is initially made 16K in size, and we
5057 * try to dump it after accumulating 8K.
5058 *
5059 * With the same goal of minimizing context swaps, the input buffer will
5060 * be enlarged anytime it has less than 8K free, so we initially allocate
5061 * twice that.
5062 */
5063 conn->inBufSize = 16 * 1024;
5064 conn->inBuffer = (char *) malloc(conn->inBufSize);
5065 conn->outBufSize = 16 * 1024;
5066 conn->outBuffer = (char *) malloc(conn->outBufSize);
5067 conn->rowBufLen = 32;
5071
5072 if (conn->inBuffer == NULL ||
5073 conn->outBuffer == NULL ||
5074 conn->rowBuf == NULL ||
5077 {
5078 /* out of memory already :-( */
5080 conn = NULL;
5081 }
5082
5083 return conn;
5084}
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:150
int inBufSize
Definition libpq-int.h:580
PGVerbosity verbosity
Definition libpq-int.h:563
int rowBufLen
Definition libpq-int.h:597
int outBufSize
Definition libpq-int.h:587
PGNoticeHooks noticeHooks
Definition libpq-int.h:457
PGContextVisibility show_context
Definition libpq-int.h:564

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

7689{
7690 if (!conn)
7691 return NULL;
7692 return conn->pgoptions;
7693}

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

5469{
5470 /* Start the message. */
5472 return STATUS_ERROR;
5473
5474 /* Send the message body. */
5475 if (pqPutnchar(buf, buf_len, conn))
5476 return STATUS_ERROR;
5477
5478 /* Finish the message. */
5479 if (pqPutMsgEnd(conn))
5480 return STATUS_ERROR;
5481
5482 /* Flush to ensure backend gets it. */
5483 if (pqFlush(conn))
5484 return STATUS_ERROR;
5485
5486 return STATUS_OK;
5487}
#define STATUS_ERROR
Definition c.h:1299
int pqPutMsgStart(char msg_type, PGconn *conn)
Definition fe-misc.c:475
int pqPutnchar(const void *s, size_t len, PGconn *conn)
Definition fe-misc.c:204
int pqPutMsgEnd(PGconn *conn)
Definition fe-misc.c:534

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

8330{
8331 char *end;
8332 long numval;
8333
8334 Assert(value != NULL);
8335
8336 *result = 0;
8337
8338 /* strtol(3) skips leading whitespaces */
8339 errno = 0;
8340 numval = strtol(value, &end, 10);
8341
8342 /*
8343 * If no progress was done during the parsing or an error happened, fail.
8344 * This tests properly for overflows of the result.
8345 */
8346 if (value == end || errno != 0 || numval != (int) numval)
8347 goto error;
8348
8349 /*
8350 * Skip any trailing whitespace; if anything but whitespace remains before
8351 * the terminating character, fail
8352 */
8353 while (*end != '\0' && isspace((unsigned char) *end))
8354 end++;
8355
8356 if (*end != '\0')
8357 goto error;
8358
8359 *result = numval;
8360 return true;
8361
8362error:
8363 libpq_append_conn_error(conn, "invalid integer value \"%s\" for connection option \"%s\"",
8364 value, context);
8365 return false;
8366}
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 8373 of file fe-connect.c.

8375{
8376 if (strcmp(value, "latest") == 0)
8377 {
8379 return true;
8380 }
8381 if (strcmp(value, "3.0") == 0)
8382 {
8383 *result = PG_PROTOCOL(3, 0);
8384 return true;
8385 }
8386
8387 /* 3.1 never existed, we went straight from 3.0 to 3.2 */
8388
8389 if (strcmp(value, "3.2") == 0)
8390 {
8391 *result = PG_PROTOCOL(3, 2);
8392 return true;
8393 }
8394
8395 libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
8396 context, value);
8397 return false;
8398}
#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 7609 of file fe-connect.c.

7610{
7611 char *password = NULL;
7612
7613 if (!conn)
7614 return NULL;
7615 if (conn->connhost != NULL)
7617 if (password == NULL)
7618 password = conn->pgpass;
7619 /* Historically we've returned "" not NULL for no password specified */
7620 if (password == NULL)
7621 password = "";
7622 return password;
7623}

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

7663{
7664 if (!conn)
7665 return NULL;
7666
7667 if (conn->connhost != NULL &&
7669 conn->connhost[conn->whichhost].port[0] != '\0')
7670 return conn->connhost[conn->whichhost].port;
7671
7672 return DEF_PGPORT_STR;
7673}

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

7730{
7731 if (!conn)
7732 return 0;
7733 if (conn->status == CONNECTION_BAD)
7734 return 0;
7736}
#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 8428 of file fe-connect.c.

8429{
8431
8432 if (newhandler)
8434 else
8436
8437 return prev;
8438}
static void default_threadlock(int acquire)
void(* pgthreadlock_t)(int acquire)
Definition libpq-fe.h:484

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

◆ pqReleaseConnHosts()

void pqReleaseConnHosts ( PGconn conn)

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

5196{
5197 if (conn->connhost)
5198 {
5199 for (int i = 0; i < conn->nconnhost; ++i)
5200 {
5201 free(conn->connhost[i].host);
5203 free(conn->connhost[i].port);
5204 if (conn->connhost[i].password != NULL)
5205 {
5209 }
5210 }
5211 free(conn->connhost);
5212 conn->connhost = NULL;
5213 }
5214}

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

5374{
5375 if (conn)
5376 {
5378
5380 {
5381 /*
5382 * Notify event procs of successful reset.
5383 */
5384 int i;
5385
5386 for (i = 0; i < conn->nEvents; i++)
5387 {
5389
5390 evt.conn = conn;
5393 }
5394 }
5395 }
5396}
@ 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 5425 of file fe-connect.c.

5426{
5427 if (conn)
5428 {
5430
5431 if (status == PGRES_POLLING_OK)
5432 {
5433 /*
5434 * Notify event procs of successful reset.
5435 */
5436 int i;
5437
5438 for (i = 0; i < conn->nEvents; i++)
5439 {
5441
5442 evt.conn = conn;
5445 }
5446 }
5447
5448 return status;
5449 }
5450
5451 return PGRES_POLLING_FAILED;
5452}

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

5407{
5408 if (conn)
5409 {
5411
5412 return pqConnectDBStart(conn);
5413 }
5414
5415 return 0;
5416}

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

◆ PQserverVersion()

◆ PQsetClientEncoding()

int PQsetClientEncoding ( PGconn conn,
const char encoding 
)

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

7858{
7859 char qbuf[128];
7860 static const char query[] = "set client_encoding to '%s'";
7861 PGresult *res;
7862 int status;
7863
7864 if (!conn || conn->status != CONNECTION_OK)
7865 return -1;
7866
7867 if (!encoding)
7868 return -1;
7869
7870 /* Resolve special "auto" value from the locale */
7871 if (strcmp(encoding, "auto") == 0)
7873
7874 /* check query buffer overflow */
7875 if (sizeof(qbuf) < (sizeof(query) + strlen(encoding)))
7876 return -1;
7877
7878 /* ok, now send a query */
7879 sprintf(qbuf, query, encoding);
7880 res = PQexec(conn, qbuf);
7881
7882 if (res == NULL)
7883 return -1;
7884 if (res->resultStatus != PGRES_COMMAND_OK)
7885 status = -1;
7886 else
7887 {
7888 /*
7889 * We rely on the backend to report the parameter value, and we'll
7890 * change state at that time.
7891 */
7892 status = 0; /* everything is ok */
7893 }
7894 PQclear(res);
7895 return status;
7896}
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:263
ExecStatusType resultStatus
Definition libpq-int.h:175

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

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

7912{
7914
7915 if (!conn)
7916 return PQSHOW_CONTEXT_ERRORS;
7918 conn->show_context = show_context;
7919 return old;
7920}
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 7899 of file fe-connect.c.

7900{
7902
7903 if (!conn)
7904 return PQERRORS_DEFAULT;
7905 old = conn->verbosity;
7906 conn->verbosity = verbosity;
7907 return old;
7908}
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 7940 of file fe-connect.c.

7941{
7943
7944 if (conn == NULL)
7945 return NULL;
7946
7948 if (proc)
7949 {
7950 conn->noticeHooks.noticeProc = proc;
7952 }
7953 return old;
7954}
void(* PQnoticeProcessor)(void *arg, const char *message)
Definition libpq-fe.h:255

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

7924{
7926
7927 if (conn == NULL)
7928 return NULL;
7929
7931 if (proc)
7932 {
7933 conn->noticeHooks.noticeRec = proc;
7935 }
7936 return old;
7937}
void(* PQnoticeReceiver)(void *arg, const PGresult *res)
Definition libpq-fe.h:254
void * noticeRecArg
Definition libpq-int.h:151

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

7681{
7682 if (!conn)
7683 return NULL;
7684 return "";
7685}

References conn, and fb().

◆ PQuser()

char * PQuser ( const PGconn conn)

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

7602{
7603 if (!conn)
7604 return NULL;
7605 return conn->pguser;
7606}

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

7991{
7992 char *tbuf;
7993 const char *ttok;
7994 bool bslash = false;
7995
7996 if (buf == NULL || token == NULL)
7997 return NULL;
7998 tbuf = buf;
7999 ttok = token;
8000 if (tbuf[0] == '*' && tbuf[1] == ':')
8001 return tbuf + 2;
8002 while (*tbuf != 0)
8003 {
8004 if (*tbuf == '\\' && !bslash)
8005 {
8006 tbuf++;
8007 bslash = true;
8008 }
8009 if (*tbuf == ':' && *ttok == 0 && !bslash)
8010 return tbuf + 1;
8011 bslash = false;
8012 if (*ttok == 0)
8013 return NULL;
8014 if (*tbuf == *ttok)
8015 {
8016 tbuf++;
8017 ttok++;
8018 }
8019 else
8020 return NULL;
8021 }
8022 return NULL;
8023}
#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 6400 of file fe-connect.c.

6401{
6402 return uri_prefix_length(connstr) != 0 || strchr(connstr, '=') != NULL;
6403}

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

5265{
5266 if (conn->addr)
5267 {
5268 free(conn->addr);
5269 conn->addr = NULL;
5270 }
5271}

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

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

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

2591{
2592 int count;
2593
2594 if (conn->keepalives_count == NULL)
2595 return 1;
2596
2598 "keepalives_count"))
2599 return 0;
2600 if (count < 0)
2601 count = 0;
2602
2603#ifdef TCP_KEEPCNT
2605 (char *) &count, sizeof(count)) < 0)
2606 {
2608
2609 libpq_append_conn_error(conn, "%s(%s) failed: %s",
2610 "setsockopt",
2611 "TCP_KEEPCNT",
2612 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2613 return 0;
2614 }
2615#endif
2616
2617 return 1;
2618}

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

2522{
2523 int idle;
2524
2525 if (conn->keepalives_idle == NULL)
2526 return 1;
2527
2529 "keepalives_idle"))
2530 return 0;
2531 if (idle < 0)
2532 idle = 0;
2533
2534#ifdef PG_TCP_KEEPALIVE_IDLE
2536 (char *) &idle, sizeof(idle)) < 0)
2537 {
2539
2540 libpq_append_conn_error(conn, "%s(%s) failed: %s",
2541 "setsockopt",
2543 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2544 return 0;
2545 }
2546#endif
2547
2548 return 1;
2549}

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

2556{
2557 int interval;
2558
2560 return 1;
2561
2563 "keepalives_interval"))
2564 return 0;
2565 if (interval < 0)
2566 interval = 0;
2567
2568#ifdef TCP_KEEPINTVL
2570 (char *) &interval, sizeof(interval)) < 0)
2571 {
2573
2574 libpq_append_conn_error(conn, "%s(%s) failed: %s",
2575 "setsockopt",
2576 "TCP_KEEPINTVL",
2577 SOCK_STRERROR(SOCK_ERRNO, sebuf, sizeof(sebuf)));
2578 return 0;
2579 }
2580#endif
2581
2582 return 1;
2583}

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

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

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

8235{
8238
8239 /* If at least one of the bounds is not set, the range is valid */
8240 if (min == NULL || max == NULL || strlen(min) == 0 || strlen(max) == 0)
8241 return true;
8242
8243 /*
8244 * If the minimum version is the lowest one we accept, then all options
8245 * for the maximum are valid.
8246 */
8247 if (pg_strcasecmp(min, "TLSv1") == 0)
8248 return true;
8249
8250 /*
8251 * The minimum bound is valid, and cannot be TLSv1, so using TLSv1 for the
8252 * maximum is incorrect.
8253 */
8254 if (pg_strcasecmp(max, "TLSv1") == 0)
8255 return false;
8256
8257 /*
8258 * At this point we know that we have a mix of TLSv1.1 through 1.3
8259 * versions.
8260 */
8261 if (pg_strcasecmp(min, max) > 0)
8262 return false;
8263
8264 return true;
8265}
int pg_strcasecmp(const char *s1, const char *s2)
#define min(a, b)
Definition private.h:155
#define max(a, b)
Definition private.h:154

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

Referenced by pqConnectOptions2().

◆ sslVerifyProtocolVersion()

static bool sslVerifyProtocolVersion ( const char version)
static

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

8209{
8210 /*
8211 * An empty string and a NULL value are considered valid as it is
8212 * equivalent to ignoring the parameter.
8213 */
8214 if (!version || strlen(version) == 0)
8215 return true;
8216
8217 if (pg_strcasecmp(version, "TLSv1") == 0 ||
8218 pg_strcasecmp(version, "TLSv1.1") == 0 ||
8219 pg_strcasecmp(version, "TLSv1.2") == 0 ||
8220 pg_strcasecmp(version, "TLSv1.3") == 0)
8221 return true;
8222
8223 /* anything else is wrong */
8224 return false;
8225}

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

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

6378{
6380 sizeof(uri_designator) - 1) == 0)
6381 return sizeof(uri_designator) - 1;
6382
6384 sizeof(short_uri_designator) - 1) == 0)
6385 return sizeof(short_uri_designator) - 1;
6386
6387 return 0;
6388}
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 2503 of file fe-connect.c.

2504{
2505 int val;
2506
2507 if (conn->keepalives == NULL)
2508 return 1;
2509
2510 if (!pqParseIntParam(conn->keepalives, &val, conn, "keepalives"))
2511 return -1;
2512
2513 return val != 0 ? 1 : 0;
2514}

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