diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:19:15 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 12:19:15 +0000 |
commit | 6eb9c5a5657d1fe77b55cc261450f3538d35a94d (patch) | |
tree | 657d8194422a5daccecfd42d654b8a245ef7b4c8 /src/include/libpq | |
parent | Initial commit. (diff) | |
download | postgresql-13-upstream.tar.xz postgresql-13-upstream.zip |
Adding upstream version 13.4.upstream/13.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/include/libpq')
-rw-r--r-- | src/include/libpq/auth.h | 29 | ||||
-rw-r--r-- | src/include/libpq/be-fsstubs.h | 32 | ||||
-rw-r--r-- | src/include/libpq/be-gssapi-common.h | 26 | ||||
-rw-r--r-- | src/include/libpq/crypt.h | 46 | ||||
-rw-r--r-- | src/include/libpq/hba.h | 140 | ||||
-rw-r--r-- | src/include/libpq/ifaddr.h | 30 | ||||
-rw-r--r-- | src/include/libpq/libpq-be.h | 326 | ||||
-rw-r--r-- | src/include/libpq/libpq-fs.h | 24 | ||||
-rw-r--r-- | src/include/libpq/libpq.h | 133 | ||||
-rw-r--r-- | src/include/libpq/pqcomm.h | 208 | ||||
-rw-r--r-- | src/include/libpq/pqformat.h | 210 | ||||
-rw-r--r-- | src/include/libpq/pqmq.h | 24 | ||||
-rw-r--r-- | src/include/libpq/pqsignal.h | 42 | ||||
-rw-r--r-- | src/include/libpq/scram.h | 37 |
14 files changed, 1307 insertions, 0 deletions
diff --git a/src/include/libpq/auth.h b/src/include/libpq/auth.h new file mode 100644 index 0000000..81202e6 --- /dev/null +++ b/src/include/libpq/auth.h @@ -0,0 +1,29 @@ +/*------------------------------------------------------------------------- + * + * auth.h + * Definitions for network authentication routines + * + * + * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/libpq/auth.h + * + *------------------------------------------------------------------------- + */ +#ifndef AUTH_H +#define AUTH_H + +#include "libpq/libpq-be.h" + +extern char *pg_krb_server_keyfile; +extern bool pg_krb_caseins_users; +extern char *pg_krb_realm; + +extern void ClientAuthentication(Port *port); + +/* Hook for plugins to get control in ClientAuthentication() */ +typedef void (*ClientAuthentication_hook_type) (Port *, int); +extern PGDLLIMPORT ClientAuthentication_hook_type ClientAuthentication_hook; + +#endif /* AUTH_H */ diff --git a/src/include/libpq/be-fsstubs.h b/src/include/libpq/be-fsstubs.h new file mode 100644 index 0000000..4fbd7cc --- /dev/null +++ b/src/include/libpq/be-fsstubs.h @@ -0,0 +1,32 @@ +/*------------------------------------------------------------------------- + * + * be-fsstubs.h + * + * + * + * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/libpq/be-fsstubs.h + * + *------------------------------------------------------------------------- + */ +#ifndef BE_FSSTUBS_H +#define BE_FSSTUBS_H + +/* + * These are not fmgr-callable, but are available to C code. + * Probably these should have had the underscore-free names, + * but too late now... + */ +extern int lo_read(int fd, char *buf, int len); +extern int lo_write(int fd, const char *buf, int len); + +/* + * Cleanup LOs at xact commit/abort + */ +extern void AtEOXact_LargeObject(bool isCommit); +extern void AtEOSubXact_LargeObject(bool isCommit, SubTransactionId mySubid, + SubTransactionId parentSubid); + +#endif /* BE_FSSTUBS_H */ diff --git a/src/include/libpq/be-gssapi-common.h b/src/include/libpq/be-gssapi-common.h new file mode 100644 index 0000000..e1c23ac --- /dev/null +++ b/src/include/libpq/be-gssapi-common.h @@ -0,0 +1,26 @@ +/*------------------------------------------------------------------------- + * + * be-gssapi-common.h + * Definitions for GSSAPI authentication and encryption handling + * + * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/libpq/be-gssapi-common.h + * + *------------------------------------------------------------------------- + */ + +#ifndef BE_GSSAPI_COMMON_H +#define BE_GSSAPI_COMMON_H + +#if defined(HAVE_GSSAPI_H) +#include <gssapi.h> +#else +#include <gssapi/gssapi.h> +#endif + +extern void pg_GSS_error(const char *errmsg, + OM_uint32 maj_stat, OM_uint32 min_stat); + +#endif /* BE_GSSAPI_COMMON_H */ diff --git a/src/include/libpq/crypt.h b/src/include/libpq/crypt.h new file mode 100644 index 0000000..0c99e6c --- /dev/null +++ b/src/include/libpq/crypt.h @@ -0,0 +1,46 @@ +/*------------------------------------------------------------------------- + * + * crypt.h + * Interface to libpq/crypt.c + * + * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/libpq/crypt.h + * + *------------------------------------------------------------------------- + */ +#ifndef PG_CRYPT_H +#define PG_CRYPT_H + +#include "datatype/timestamp.h" + +/* + * Types of password hashes or secrets. + * + * Plaintext passwords can be passed in by the user, in a CREATE/ALTER USER + * command. They will be encrypted to MD5 or SCRAM-SHA-256 format, before + * storing on-disk, so only MD5 and SCRAM-SHA-256 passwords should appear + * in pg_authid.rolpassword. They are also the allowed values for the + * password_encryption GUC. + */ +typedef enum PasswordType +{ + PASSWORD_TYPE_PLAINTEXT = 0, + PASSWORD_TYPE_MD5, + PASSWORD_TYPE_SCRAM_SHA_256 +} PasswordType; + +extern PasswordType get_password_type(const char *shadow_pass); +extern char *encrypt_password(PasswordType target_type, const char *role, + const char *password); + +extern char *get_role_password(const char *role, char **logdetail); + +extern int md5_crypt_verify(const char *role, const char *shadow_pass, + const char *client_pass, const char *md5_salt, + int md5_salt_len, char **logdetail); +extern int plain_crypt_verify(const char *role, const char *shadow_pass, + const char *client_pass, char **logdetail); + +#endif diff --git a/src/include/libpq/hba.h b/src/include/libpq/hba.h new file mode 100644 index 0000000..c194d74 --- /dev/null +++ b/src/include/libpq/hba.h @@ -0,0 +1,140 @@ +/*------------------------------------------------------------------------- + * + * hba.h + * Interface to hba.c + * + * + * src/include/libpq/hba.h + * + *------------------------------------------------------------------------- + */ +#ifndef HBA_H +#define HBA_H + +#include "libpq/pqcomm.h" /* pgrminclude ignore */ /* needed for NetBSD */ +#include "nodes/pg_list.h" +#include "regex/regex.h" + + +/* + * The following enum represents the authentication methods that + * are supported by PostgreSQL. + * + * Note: keep this in sync with the UserAuthName array in hba.c. + */ +typedef enum UserAuth +{ + uaReject, + uaImplicitReject, /* Not a user-visible option */ + uaTrust, + uaIdent, + uaPassword, + uaMD5, + uaSCRAM, + uaGSS, + uaSSPI, + uaPAM, + uaBSD, + uaLDAP, + uaCert, + uaRADIUS, + uaPeer +#define USER_AUTH_LAST uaPeer /* Must be last value of this enum */ +} UserAuth; + +/* + * Data structures representing pg_hba.conf entries + */ + +typedef enum IPCompareMethod +{ + ipCmpMask, + ipCmpSameHost, + ipCmpSameNet, + ipCmpAll +} IPCompareMethod; + +typedef enum ConnType +{ + ctLocal, + ctHost, + ctHostSSL, + ctHostNoSSL, + ctHostGSS, + ctHostNoGSS, +} ConnType; + +typedef enum ClientCertMode +{ + clientCertOff, + clientCertCA, + clientCertFull +} ClientCertMode; + +typedef struct HbaLine +{ + int linenumber; + char *rawline; + ConnType conntype; + List *databases; + List *roles; + struct sockaddr_storage addr; + struct sockaddr_storage mask; + IPCompareMethod ip_cmp_method; + char *hostname; + UserAuth auth_method; + + char *usermap; + char *pamservice; + bool pam_use_hostname; + bool ldaptls; + char *ldapscheme; + char *ldapserver; + int ldapport; + char *ldapbinddn; + char *ldapbindpasswd; + char *ldapsearchattribute; + char *ldapsearchfilter; + char *ldapbasedn; + int ldapscope; + char *ldapprefix; + char *ldapsuffix; + ClientCertMode clientcert; + char *krb_realm; + bool include_realm; + bool compat_realm; + bool upn_username; + List *radiusservers; + char *radiusservers_s; + List *radiussecrets; + char *radiussecrets_s; + List *radiusidentifiers; + char *radiusidentifiers_s; + List *radiusports; + char *radiusports_s; + int addrlen; /* zero if we don't have a valid addr */ + int masklen; /* zero if we don't have a valid mask */ +} HbaLine; + +typedef struct IdentLine +{ + int linenumber; + + char *usermap; + char *ident_user; + char *pg_role; + regex_t re; +} IdentLine; + +/* kluge to avoid including libpq/libpq-be.h here */ +typedef struct Port hbaPort; + +extern bool load_hba(void); +extern bool load_ident(void); +extern void hba_getauthmethod(hbaPort *port); +extern int check_usermap(const char *usermap_name, + const char *pg_role, const char *auth_user, + bool case_sensitive); +extern bool pg_isblank(const char c); + +#endif /* HBA_H */ diff --git a/src/include/libpq/ifaddr.h b/src/include/libpq/ifaddr.h new file mode 100644 index 0000000..4b61518 --- /dev/null +++ b/src/include/libpq/ifaddr.h @@ -0,0 +1,30 @@ +/*------------------------------------------------------------------------- + * + * ifaddr.h + * IP netmask calculations, and enumerating network interfaces. + * + * Copyright (c) 2003-2020, PostgreSQL Global Development Group + * + * src/include/libpq/ifaddr.h + * + *------------------------------------------------------------------------- + */ +#ifndef IFADDR_H +#define IFADDR_H + +#include "libpq/pqcomm.h" /* pgrminclude ignore */ + +typedef void (*PgIfAddrCallback) (struct sockaddr *addr, + struct sockaddr *netmask, + void *cb_data); + +extern int pg_range_sockaddr(const struct sockaddr_storage *addr, + const struct sockaddr_storage *netaddr, + const struct sockaddr_storage *netmask); + +extern int pg_sockaddr_cidr_mask(struct sockaddr_storage *mask, + char *numbits, int family); + +extern int pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data); + +#endif /* IFADDR_H */ diff --git a/src/include/libpq/libpq-be.h b/src/include/libpq/libpq-be.h new file mode 100644 index 0000000..fa778e1 --- /dev/null +++ b/src/include/libpq/libpq-be.h @@ -0,0 +1,326 @@ +/*------------------------------------------------------------------------- + * + * libpq-be.h + * This file contains definitions for structures and externs used + * by the postmaster during client authentication. + * + * Note that this is backend-internal and is NOT exported to clients. + * Structs that need to be client-visible are in pqcomm.h. + * + * + * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/libpq/libpq-be.h + * + *------------------------------------------------------------------------- + */ +#ifndef LIBPQ_BE_H +#define LIBPQ_BE_H + +#include <sys/time.h> +#ifdef USE_OPENSSL +#include <openssl/ssl.h> +#include <openssl/err.h> +#endif +#ifdef HAVE_NETINET_TCP_H +#include <netinet/tcp.h> +#endif + +#ifdef ENABLE_GSS +#if defined(HAVE_GSSAPI_H) +#include <gssapi.h> +#else +#include <gssapi/gssapi.h> +#endif /* HAVE_GSSAPI_H */ +/* + * GSSAPI brings in headers that set a lot of things in the global namespace on win32, + * that doesn't match the msvc build. It gives a bunch of compiler warnings that we ignore, + * but also defines a symbol that simply does not exist. Undefine it again. + */ +#ifdef _MSC_VER +#undef HAVE_GETADDRINFO +#endif +#endif /* ENABLE_GSS */ + +#ifdef ENABLE_SSPI +#define SECURITY_WIN32 +#if defined(WIN32) && !defined(_MSC_VER) +#include <ntsecapi.h> +#endif +#include <security.h> +#undef SECURITY_WIN32 + +#ifndef ENABLE_GSS +/* + * Define a fake structure compatible with GSSAPI on Unix. + */ +typedef struct +{ + void *value; + int length; +} gss_buffer_desc; +#endif +#endif /* ENABLE_SSPI */ + +#include "datatype/timestamp.h" +#include "libpq/hba.h" +#include "libpq/pqcomm.h" + + +typedef enum CAC_state +{ + CAC_OK, CAC_STARTUP, CAC_SHUTDOWN, CAC_RECOVERY, CAC_TOOMANY, + CAC_SUPERUSER +} CAC_state; + + +/* + * GSSAPI specific state information + */ +#if defined(ENABLE_GSS) | defined(ENABLE_SSPI) +typedef struct +{ + gss_buffer_desc outbuf; /* GSSAPI output token buffer */ +#ifdef ENABLE_GSS + gss_cred_id_t cred; /* GSSAPI connection cred's */ + gss_ctx_id_t ctx; /* GSSAPI connection context */ + gss_name_t name; /* GSSAPI client name */ + char *princ; /* GSSAPI Principal used for auth, NULL if + * GSSAPI auth was not used */ + bool auth; /* GSSAPI Authentication used */ + bool enc; /* GSSAPI encryption in use */ +#endif +} pg_gssinfo; +#endif + +/* + * This is used by the postmaster in its communication with frontends. It + * contains all state information needed during this communication before the + * backend is run. The Port structure is kept in malloc'd memory and is + * still available when a backend is running (see MyProcPort). The data + * it points to must also be malloc'd, or else palloc'd in TopMemoryContext, + * so that it survives into PostgresMain execution! + * + * remote_hostname is set if we did a successful reverse lookup of the + * client's IP address during connection setup. + * remote_hostname_resolv tracks the state of hostname verification: + * +1 = remote_hostname is known to resolve to client's IP address + * -1 = remote_hostname is known NOT to resolve to client's IP address + * 0 = we have not done the forward DNS lookup yet + * -2 = there was an error in name resolution + * If reverse lookup of the client IP address fails, remote_hostname will be + * left NULL while remote_hostname_resolv is set to -2. If reverse lookup + * succeeds but forward lookup fails, remote_hostname_resolv is also set to -2 + * (the case is distinguishable because remote_hostname isn't NULL). In + * either of the -2 cases, remote_hostname_errcode saves the lookup return + * code for possible later use with gai_strerror. + */ + +typedef struct Port +{ + pgsocket sock; /* File descriptor */ + bool noblock; /* is the socket in non-blocking mode? */ + ProtocolVersion proto; /* FE/BE protocol version */ + SockAddr laddr; /* local addr (postmaster) */ + SockAddr raddr; /* remote addr (client) */ + char *remote_host; /* name (or ip addr) of remote host */ + char *remote_hostname; /* name (not ip addr) of remote host, if + * available */ + int remote_hostname_resolv; /* see above */ + int remote_hostname_errcode; /* see above */ + char *remote_port; /* text rep of remote port */ + CAC_state canAcceptConnections; /* postmaster connection status */ + + /* + * Information that needs to be saved from the startup packet and passed + * into backend execution. "char *" fields are NULL if not set. + * guc_options points to a List of alternating option names and values. + */ + char *database_name; + char *user_name; + char *cmdline_options; + List *guc_options; + + /* + * The startup packet application name, only used here for the "connection + * authorized" log message. We shouldn't use this post-startup, instead + * the GUC should be used as application can change it afterward. + */ + char *application_name; + + /* + * Information that needs to be held during the authentication cycle. + */ + HbaLine *hba; + + /* + * TCP keepalive and user timeout settings. + * + * default values are 0 if AF_UNIX or not yet known; current values are 0 + * if AF_UNIX or using the default. Also, -1 in a default value means we + * were unable to find out the default (getsockopt failed). + */ + int default_keepalives_idle; + int default_keepalives_interval; + int default_keepalives_count; + int default_tcp_user_timeout; + int keepalives_idle; + int keepalives_interval; + int keepalives_count; + int tcp_user_timeout; + + /* + * GSSAPI structures. + */ +#if defined(ENABLE_GSS) || defined(ENABLE_SSPI) + + /* + * If GSSAPI is supported and used on this connection, store GSSAPI + * information. Even when GSSAPI is not compiled in, store a NULL pointer + * to keep struct offsets the same (for extension ABI compatibility). + */ + pg_gssinfo *gss; +#else + void *gss; +#endif + + /* + * SSL structures. + */ + bool ssl_in_use; + char *peer_cn; + bool peer_cert_valid; + + /* + * OpenSSL structures. (Keep these last so that the locations of other + * fields are the same whether or not you build with OpenSSL.) + */ +#ifdef USE_OPENSSL + SSL *ssl; + X509 *peer; +#endif +} Port; + +#ifdef USE_SSL +/* + * Hardcoded DH parameters, used in ephemeral DH keying. (See also + * README.SSL for more details on EDH.) + * + * This is the 2048-bit DH parameter from RFC 3526. The generation of the + * prime is specified in RFC 2412 Appendix E, which also discusses the + * design choice of the generator. Note that when loaded with OpenSSL + * this causes DH_check() to fail on DH_NOT_SUITABLE_GENERATOR, where + * leaking a bit is preferred. + */ +#define FILE_DH2048 \ +"-----BEGIN DH PARAMETERS-----\n\ +MIIBCAKCAQEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxOb\n\ +IlFKCHmONATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjft\n\ +awv/XLb0Brft7jhr+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXT\n\ +mmkWP6j9JM9fg2VdI9yjrZYcYvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhgh\n\ +fDKQXkYuNs474553LBgOhgObJ4Oi7Aeij7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq\n\ +5RXSJhiY+gUQFXKOWoqsqmj//////////wIBAg==\n\ +-----END DH PARAMETERS-----\n" + +/* + * These functions are implemented by the glue code specific to each + * SSL implementation (e.g. be-secure-openssl.c) + */ + +/* + * Initialize global SSL context. + * + * If isServerStart is true, report any errors as FATAL (so we don't return). + * Otherwise, log errors at LOG level and return -1 to indicate trouble, + * preserving the old SSL state if any. Returns 0 if OK. + */ +extern int be_tls_init(bool isServerStart); + +/* + * Destroy global SSL context, if any. + */ +extern void be_tls_destroy(void); + +/* + * Attempt to negotiate SSL connection. + */ +extern int be_tls_open_server(Port *port); + +/* + * Close SSL connection. + */ +extern void be_tls_close(Port *port); + +/* + * Read data from a secure connection. + */ +extern ssize_t be_tls_read(Port *port, void *ptr, size_t len, int *waitfor); + +/* + * Write data to a secure connection. + */ +extern ssize_t be_tls_write(Port *port, void *ptr, size_t len, int *waitfor); + +/* + * Return information about the SSL connection. + */ +extern int be_tls_get_cipher_bits(Port *port); +extern bool be_tls_get_compression(Port *port); +extern const char *be_tls_get_version(Port *port); +extern const char *be_tls_get_cipher(Port *port); +extern void be_tls_get_peer_subject_name(Port *port, char *ptr, size_t len); +extern void be_tls_get_peer_issuer_name(Port *port, char *ptr, size_t len); +extern void be_tls_get_peer_serial(Port *port, char *ptr, size_t len); + +/* + * Get the server certificate hash for SCRAM channel binding type + * tls-server-end-point. + * + * The result is a palloc'd hash of the server certificate with its + * size, and NULL if there is no certificate available. + * + * This is not supported with old versions of OpenSSL that don't have + * the X509_get_signature_nid() function. + */ +#if defined(USE_OPENSSL) && defined(HAVE_X509_GET_SIGNATURE_NID) +#define HAVE_BE_TLS_GET_CERTIFICATE_HASH +extern char *be_tls_get_certificate_hash(Port *port, size_t *len); +#endif + +/* init hook for SSL, the default sets the password callback if appropriate */ +#ifdef USE_OPENSSL +typedef void (*openssl_tls_init_hook_typ) (SSL_CTX *context, bool isServerStart); +extern PGDLLIMPORT openssl_tls_init_hook_typ openssl_tls_init_hook; +#endif + +#endif /* USE_SSL */ + +#ifdef ENABLE_GSS +/* + * Return information about the GSSAPI authenticated connection + */ +extern bool be_gssapi_get_auth(Port *port); +extern bool be_gssapi_get_enc(Port *port); +extern const char *be_gssapi_get_princ(Port *port); + +/* Read and write to a GSSAPI-encrypted connection. */ +extern ssize_t be_gssapi_read(Port *port, void *ptr, size_t len); +extern ssize_t be_gssapi_write(Port *port, void *ptr, size_t len); +#endif /* ENABLE_GSS */ + +extern ProtocolVersion FrontendProtocol; + +/* TCP keepalives configuration. These are no-ops on an AF_UNIX socket. */ + +extern int pq_getkeepalivesidle(Port *port); +extern int pq_getkeepalivesinterval(Port *port); +extern int pq_getkeepalivescount(Port *port); +extern int pq_gettcpusertimeout(Port *port); + +extern int pq_setkeepalivesidle(int idle, Port *port); +extern int pq_setkeepalivesinterval(int interval, Port *port); +extern int pq_setkeepalivescount(int count, Port *port); +extern int pq_settcpusertimeout(int timeout, Port *port); + +#endif /* LIBPQ_BE_H */ diff --git a/src/include/libpq/libpq-fs.h b/src/include/libpq/libpq-fs.h new file mode 100644 index 0000000..a3c2cd9 --- /dev/null +++ b/src/include/libpq/libpq-fs.h @@ -0,0 +1,24 @@ +/*------------------------------------------------------------------------- + * + * libpq-fs.h + * definitions for using Inversion file system routines (ie, large objects) + * + * + * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/libpq/libpq-fs.h + * + *------------------------------------------------------------------------- + */ +#ifndef LIBPQ_FS_H +#define LIBPQ_FS_H + +/* + * Read/write mode flags for inversion (large object) calls + */ + +#define INV_WRITE 0x00020000 +#define INV_READ 0x00040000 + +#endif /* LIBPQ_FS_H */ diff --git a/src/include/libpq/libpq.h b/src/include/libpq/libpq.h new file mode 100644 index 0000000..b115247 --- /dev/null +++ b/src/include/libpq/libpq.h @@ -0,0 +1,133 @@ +/*------------------------------------------------------------------------- + * + * libpq.h + * POSTGRES LIBPQ buffer structure definitions. + * + * + * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/libpq/libpq.h + * + *------------------------------------------------------------------------- + */ +#ifndef LIBPQ_H +#define LIBPQ_H + +#include <netinet/in.h> + +#include "lib/stringinfo.h" +#include "libpq/libpq-be.h" +#include "storage/latch.h" + + +typedef struct +{ + void (*comm_reset) (void); + int (*flush) (void); + int (*flush_if_writable) (void); + bool (*is_send_pending) (void); + int (*putmessage) (char msgtype, const char *s, size_t len); + void (*putmessage_noblock) (char msgtype, const char *s, size_t len); + void (*startcopyout) (void); + void (*endcopyout) (bool errorAbort); +} PQcommMethods; + +extern const PGDLLIMPORT PQcommMethods *PqCommMethods; + +#define pq_comm_reset() (PqCommMethods->comm_reset()) +#define pq_flush() (PqCommMethods->flush()) +#define pq_flush_if_writable() (PqCommMethods->flush_if_writable()) +#define pq_is_send_pending() (PqCommMethods->is_send_pending()) +#define pq_putmessage(msgtype, s, len) \ + (PqCommMethods->putmessage(msgtype, s, len)) +#define pq_putmessage_noblock(msgtype, s, len) \ + (PqCommMethods->putmessage_noblock(msgtype, s, len)) +#define pq_startcopyout() (PqCommMethods->startcopyout()) +#define pq_endcopyout(errorAbort) (PqCommMethods->endcopyout(errorAbort)) + +/* + * External functions. + */ + +/* + * prototypes for functions in pqcomm.c + */ +extern WaitEventSet *FeBeWaitSet; + +extern int StreamServerPort(int family, const char *hostName, + unsigned short portNumber, const char *unixSocketDir, + pgsocket ListenSocket[], int MaxListen); +extern int StreamConnection(pgsocket server_fd, Port *port); +extern void StreamClose(pgsocket sock); +extern void TouchSocketFiles(void); +extern void RemoveSocketFiles(void); +extern void pq_init(void); +extern int pq_getbytes(char *s, size_t len); +extern int pq_getstring(StringInfo s); +extern void pq_startmsgread(void); +extern void pq_endmsgread(void); +extern bool pq_is_reading_msg(void); +extern int pq_getmessage(StringInfo s, int maxlen); +extern int pq_getbyte(void); +extern int pq_peekbyte(void); +extern int pq_getbyte_if_available(unsigned char *c); +extern int pq_putbytes(const char *s, size_t len); + +/* + * prototypes for functions in be-secure.c + */ +extern char *ssl_library; +extern char *ssl_cert_file; +extern char *ssl_key_file; +extern char *ssl_ca_file; +extern char *ssl_crl_file; +extern char *ssl_dh_params_file; +extern PGDLLIMPORT char *ssl_passphrase_command; +extern PGDLLIMPORT bool ssl_passphrase_command_supports_reload; +#ifdef USE_SSL +extern bool ssl_loaded_verify_locations; +#endif + +extern int secure_initialize(bool isServerStart); +extern bool secure_loaded_verify_locations(void); +extern void secure_destroy(void); +extern int secure_open_server(Port *port); +extern void secure_close(Port *port); +extern ssize_t secure_read(Port *port, void *ptr, size_t len); +extern ssize_t secure_write(Port *port, void *ptr, size_t len); +extern ssize_t secure_raw_read(Port *port, void *ptr, size_t len); +extern ssize_t secure_raw_write(Port *port, const void *ptr, size_t len); + +/* + * prototypes for functions in be-secure-gssapi.c + */ +#ifdef ENABLE_GSS +extern ssize_t secure_open_gssapi(Port *port); +#endif + +/* GUCs */ +extern char *SSLCipherSuites; +extern char *SSLECDHCurve; +extern bool SSLPreferServerCiphers; +extern int ssl_min_protocol_version; +extern int ssl_max_protocol_version; + +enum ssl_protocol_versions +{ + PG_TLS_ANY = 0, + PG_TLS1_VERSION, + PG_TLS1_1_VERSION, + PG_TLS1_2_VERSION, + PG_TLS1_3_VERSION, +}; + +/* + * prototypes for functions in be-secure-common.c + */ +extern int run_ssl_passphrase_command(const char *prompt, bool is_server_start, + char *buf, int size); +extern bool check_ssl_key_file_permissions(const char *ssl_key_file, + bool isServerStart); + +#endif /* LIBPQ_H */ diff --git a/src/include/libpq/pqcomm.h b/src/include/libpq/pqcomm.h new file mode 100644 index 0000000..781d86c --- /dev/null +++ b/src/include/libpq/pqcomm.h @@ -0,0 +1,208 @@ +/*------------------------------------------------------------------------- + * + * pqcomm.h + * Definitions common to frontends and backends. + * + * NOTE: for historical reasons, this does not correspond to pqcomm.c. + * pqcomm.c's routines are declared in libpq.h. + * + * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/libpq/pqcomm.h + * + *------------------------------------------------------------------------- + */ +#ifndef PQCOMM_H +#define PQCOMM_H + +#include <sys/socket.h> +#include <netdb.h> +#ifdef HAVE_SYS_UN_H +#include <sys/un.h> +#endif +#include <netinet/in.h> + +#ifdef HAVE_STRUCT_SOCKADDR_STORAGE + +#ifndef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY +#ifdef HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY +#define ss_family __ss_family +#else +#error struct sockaddr_storage does not provide an ss_family member +#endif +#endif + +#ifdef HAVE_STRUCT_SOCKADDR_STORAGE___SS_LEN +#define ss_len __ss_len +#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN 1 +#endif +#else /* !HAVE_STRUCT_SOCKADDR_STORAGE */ + +/* Define a struct sockaddr_storage if we don't have one. */ + +struct sockaddr_storage +{ + union + { + struct sockaddr sa; /* get the system-dependent fields */ + int64 ss_align; /* ensures struct is properly aligned */ + char ss_pad[128]; /* ensures struct has desired size */ + } ss_stuff; +}; + +#define ss_family ss_stuff.sa.sa_family +/* It should have an ss_len field if sockaddr has sa_len. */ +#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN +#define ss_len ss_stuff.sa.sa_len +#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN 1 +#endif +#endif /* HAVE_STRUCT_SOCKADDR_STORAGE */ + +typedef struct +{ + struct sockaddr_storage addr; + ACCEPT_TYPE_ARG3 salen; +} SockAddr; + +/* Configure the UNIX socket location for the well known port. */ + +#define UNIXSOCK_PATH(path, port, sockdir) \ + (AssertMacro(sockdir), \ + AssertMacro(*(sockdir) != '\0'), \ + snprintf(path, sizeof(path), "%s/.s.PGSQL.%d", \ + (sockdir), (port))) + +/* + * The maximum workable length of a socket path is what will fit into + * struct sockaddr_un. This is usually only 100 or so bytes :-(. + * + * For consistency, always pass a MAXPGPATH-sized buffer to UNIXSOCK_PATH(), + * then complain if the resulting string is >= UNIXSOCK_PATH_BUFLEN bytes. + * (Because the standard API for getaddrinfo doesn't allow it to complain in + * a useful way when the socket pathname is too long, we have to test for + * this explicitly, instead of just letting the subroutine return an error.) + */ +#define UNIXSOCK_PATH_BUFLEN sizeof(((struct sockaddr_un *) NULL)->sun_path) + + +/* + * These manipulate the frontend/backend protocol version number. + * + * The major number should be incremented for incompatible changes. The minor + * number should be incremented for compatible changes (eg. additional + * functionality). + * + * If a backend supports version m.n of the protocol it must actually support + * versions m.[0..n]. Backend support for version m-1 can be dropped after a + * `reasonable' length of time. + * + * A frontend isn't required to support anything other than the current + * version. + */ + +#define PG_PROTOCOL_MAJOR(v) ((v) >> 16) +#define PG_PROTOCOL_MINOR(v) ((v) & 0x0000ffff) +#define PG_PROTOCOL(m,n) (((m) << 16) | (n)) + +/* The earliest and latest frontend/backend protocol version supported. */ + +#define PG_PROTOCOL_EARLIEST PG_PROTOCOL(2,0) +#define PG_PROTOCOL_LATEST PG_PROTOCOL(3,0) + +typedef uint32 ProtocolVersion; /* FE/BE protocol version number */ + +typedef ProtocolVersion MsgType; + + +/* + * Packet lengths are 4 bytes in network byte order. + * + * The initial length is omitted from the packet layouts appearing below. + */ + +typedef uint32 PacketLen; + + +/* + * Old-style startup packet layout with fixed-width fields. This is used in + * protocol 1.0 and 2.0, but not in later versions. Note that the fields + * in this layout are '\0' terminated only if there is room. + */ + +#define SM_DATABASE 64 +#define SM_USER 32 +/* We append database name if db_user_namespace true. */ +#define SM_DATABASE_USER (SM_DATABASE+SM_USER+1) /* +1 for @ */ +#define SM_OPTIONS 64 +#define SM_UNUSED 64 +#define SM_TTY 64 + +typedef struct StartupPacket +{ + ProtocolVersion protoVersion; /* Protocol version */ + char database[SM_DATABASE]; /* Database name */ + /* Db_user_namespace appends dbname */ + char user[SM_USER]; /* User name */ + char options[SM_OPTIONS]; /* Optional additional args */ + char unused[SM_UNUSED]; /* Unused */ + char tty[SM_TTY]; /* Tty for debug output */ +} StartupPacket; + +extern bool Db_user_namespace; + +/* + * In protocol 3.0 and later, the startup packet length is not fixed, but + * we set an arbitrary limit on it anyway. This is just to prevent simple + * denial-of-service attacks via sending enough data to run the server + * out of memory. + */ +#define MAX_STARTUP_PACKET_LENGTH 10000 + + +/* These are the authentication request codes sent by the backend. */ + +#define AUTH_REQ_OK 0 /* User is authenticated */ +#define AUTH_REQ_KRB4 1 /* Kerberos V4. Not supported any more. */ +#define AUTH_REQ_KRB5 2 /* Kerberos V5. Not supported any more. */ +#define AUTH_REQ_PASSWORD 3 /* Password */ +#define AUTH_REQ_CRYPT 4 /* crypt password. Not supported any more. */ +#define AUTH_REQ_MD5 5 /* md5 password */ +#define AUTH_REQ_SCM_CREDS 6 /* transfer SCM credentials */ +#define AUTH_REQ_GSS 7 /* GSSAPI without wrap() */ +#define AUTH_REQ_GSS_CONT 8 /* Continue GSS exchanges */ +#define AUTH_REQ_SSPI 9 /* SSPI negotiate without wrap() */ +#define AUTH_REQ_SASL 10 /* Begin SASL authentication */ +#define AUTH_REQ_SASL_CONT 11 /* Continue SASL authentication */ +#define AUTH_REQ_SASL_FIN 12 /* Final SASL message */ + +typedef uint32 AuthRequest; + + +/* + * A client can also send a cancel-current-operation request to the postmaster. + * This is uglier than sending it directly to the client's backend, but it + * avoids depending on out-of-band communication facilities. + * + * The cancel request code must not match any protocol version number + * we're ever likely to use. This random choice should do. + */ +#define CANCEL_REQUEST_CODE PG_PROTOCOL(1234,5678) + +typedef struct CancelRequestPacket +{ + /* Note that each field is stored in network byte order! */ + MsgType cancelRequestCode; /* code to identify a cancel request */ + uint32 backendPID; /* PID of client's backend */ + uint32 cancelAuthCode; /* secret key to authorize cancel */ +} CancelRequestPacket; + + +/* + * A client can also start by sending a SSL or GSSAPI negotiation request to + * get a secure channel. + */ +#define NEGOTIATE_SSL_CODE PG_PROTOCOL(1234,5679) +#define NEGOTIATE_GSS_CODE PG_PROTOCOL(1234,5680) + +#endif /* PQCOMM_H */ diff --git a/src/include/libpq/pqformat.h b/src/include/libpq/pqformat.h new file mode 100644 index 0000000..af31e9c --- /dev/null +++ b/src/include/libpq/pqformat.h @@ -0,0 +1,210 @@ +/*------------------------------------------------------------------------- + * + * pqformat.h + * Definitions for formatting and parsing frontend/backend messages + * + * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/libpq/pqformat.h + * + *------------------------------------------------------------------------- + */ +#ifndef PQFORMAT_H +#define PQFORMAT_H + +#include "lib/stringinfo.h" +#include "mb/pg_wchar.h" +#include "port/pg_bswap.h" + +extern void pq_beginmessage(StringInfo buf, char msgtype); +extern void pq_beginmessage_reuse(StringInfo buf, char msgtype); +extern void pq_endmessage(StringInfo buf); +extern void pq_endmessage_reuse(StringInfo buf); + +extern void pq_sendbytes(StringInfo buf, const char *data, int datalen); +extern void pq_sendcountedtext(StringInfo buf, const char *str, int slen, + bool countincludesself); +extern void pq_sendtext(StringInfo buf, const char *str, int slen); +extern void pq_sendstring(StringInfo buf, const char *str); +extern void pq_send_ascii_string(StringInfo buf, const char *str); +extern void pq_sendfloat4(StringInfo buf, float4 f); +extern void pq_sendfloat8(StringInfo buf, float8 f); + +/* + * Append a [u]int8 to a StringInfo buffer, which already has enough space + * preallocated. + * + * The use of pg_restrict allows the compiler to optimize the code based on + * the assumption that buf, buf->len, buf->data and *buf->data don't + * overlap. Without the annotation buf->len etc cannot be kept in a register + * over subsequent pq_writeintN calls. + * + * The use of StringInfoData * rather than StringInfo is due to MSVC being + * overly picky and demanding a * before a restrict. + */ +static inline void +pq_writeint8(StringInfoData *pg_restrict buf, uint8 i) +{ + uint8 ni = i; + + Assert(buf->len + (int) sizeof(uint8) <= buf->maxlen); + memcpy((char *pg_restrict) (buf->data + buf->len), &ni, sizeof(uint8)); + buf->len += sizeof(uint8); +} + +/* + * Append a [u]int16 to a StringInfo buffer, which already has enough space + * preallocated. + */ +static inline void +pq_writeint16(StringInfoData *pg_restrict buf, uint16 i) +{ + uint16 ni = pg_hton16(i); + + Assert(buf->len + (int) sizeof(uint16) <= buf->maxlen); + memcpy((char *pg_restrict) (buf->data + buf->len), &ni, sizeof(uint16)); + buf->len += sizeof(uint16); +} + +/* + * Append a [u]int32 to a StringInfo buffer, which already has enough space + * preallocated. + */ +static inline void +pq_writeint32(StringInfoData *pg_restrict buf, uint32 i) +{ + uint32 ni = pg_hton32(i); + + Assert(buf->len + (int) sizeof(uint32) <= buf->maxlen); + memcpy((char *pg_restrict) (buf->data + buf->len), &ni, sizeof(uint32)); + buf->len += sizeof(uint32); +} + +/* + * Append a [u]int64 to a StringInfo buffer, which already has enough space + * preallocated. + */ +static inline void +pq_writeint64(StringInfoData *pg_restrict buf, uint64 i) +{ + uint64 ni = pg_hton64(i); + + Assert(buf->len + (int) sizeof(uint64) <= buf->maxlen); + memcpy((char *pg_restrict) (buf->data + buf->len), &ni, sizeof(uint64)); + buf->len += sizeof(uint64); +} + +/* + * Append a null-terminated text string (with conversion) to a buffer with + * preallocated space. + * + * NB: The pre-allocated space needs to be sufficient for the string after + * converting to client encoding. + * + * NB: passed text string must be null-terminated, and so is the data + * sent to the frontend. + */ +static inline void +pq_writestring(StringInfoData *pg_restrict buf, const char *pg_restrict str) +{ + int slen = strlen(str); + char *p; + + p = pg_server_to_client(str, slen); + if (p != str) /* actual conversion has been done? */ + slen = strlen(p); + + Assert(buf->len + slen + 1 <= buf->maxlen); + + memcpy(((char *pg_restrict) buf->data + buf->len), p, slen + 1); + buf->len += slen + 1; + + if (p != str) + pfree(p); +} + +/* append a binary [u]int8 to a StringInfo buffer */ +static inline void +pq_sendint8(StringInfo buf, uint8 i) +{ + enlargeStringInfo(buf, sizeof(uint8)); + pq_writeint8(buf, i); +} + +/* append a binary [u]int16 to a StringInfo buffer */ +static inline void +pq_sendint16(StringInfo buf, uint16 i) +{ + enlargeStringInfo(buf, sizeof(uint16)); + pq_writeint16(buf, i); +} + +/* append a binary [u]int32 to a StringInfo buffer */ +static inline void +pq_sendint32(StringInfo buf, uint32 i) +{ + enlargeStringInfo(buf, sizeof(uint32)); + pq_writeint32(buf, i); +} + +/* append a binary [u]int64 to a StringInfo buffer */ +static inline void +pq_sendint64(StringInfo buf, uint64 i) +{ + enlargeStringInfo(buf, sizeof(uint64)); + pq_writeint64(buf, i); +} + +/* append a binary byte to a StringInfo buffer */ +static inline void +pq_sendbyte(StringInfo buf, uint8 byt) +{ + pq_sendint8(buf, byt); +} + +/* + * Append a binary integer to a StringInfo buffer + * + * This function is deprecated; prefer use of the functions above. + */ +static inline void +pq_sendint(StringInfo buf, uint32 i, int b) +{ + switch (b) + { + case 1: + pq_sendint8(buf, (uint8) i); + break; + case 2: + pq_sendint16(buf, (uint16) i); + break; + case 4: + pq_sendint32(buf, (uint32) i); + break; + default: + elog(ERROR, "unsupported integer size %d", b); + break; + } +} + + +extern void pq_begintypsend(StringInfo buf); +extern bytea *pq_endtypsend(StringInfo buf); + +extern void pq_puttextmessage(char msgtype, const char *str); +extern void pq_putemptymessage(char msgtype); + +extern int pq_getmsgbyte(StringInfo msg); +extern unsigned int pq_getmsgint(StringInfo msg, int b); +extern int64 pq_getmsgint64(StringInfo msg); +extern float4 pq_getmsgfloat4(StringInfo msg); +extern float8 pq_getmsgfloat8(StringInfo msg); +extern const char *pq_getmsgbytes(StringInfo msg, int datalen); +extern void pq_copymsgbytes(StringInfo msg, char *buf, int datalen); +extern char *pq_getmsgtext(StringInfo msg, int rawbytes, int *nbytes); +extern const char *pq_getmsgstring(StringInfo msg); +extern const char *pq_getmsgrawstring(StringInfo msg); +extern void pq_getmsgend(StringInfo msg); + +#endif /* PQFORMAT_H */ diff --git a/src/include/libpq/pqmq.h b/src/include/libpq/pqmq.h new file mode 100644 index 0000000..6a3ccba --- /dev/null +++ b/src/include/libpq/pqmq.h @@ -0,0 +1,24 @@ +/*------------------------------------------------------------------------- + * + * pqmq.h + * Use the frontend/backend protocol for communication over a shm_mq + * + * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/libpq/pqmq.h + * + *------------------------------------------------------------------------- + */ +#ifndef PQMQ_H +#define PQMQ_H + +#include "lib/stringinfo.h" +#include "storage/shm_mq.h" + +extern void pq_redirect_to_shm_mq(dsm_segment *seg, shm_mq_handle *mqh); +extern void pq_set_parallel_master(pid_t pid, BackendId backend_id); + +extern void pq_parse_errornotice(StringInfo str, ErrorData *edata); + +#endif /* PQMQ_H */ diff --git a/src/include/libpq/pqsignal.h b/src/include/libpq/pqsignal.h new file mode 100644 index 0000000..695c4dc --- /dev/null +++ b/src/include/libpq/pqsignal.h @@ -0,0 +1,42 @@ +/*------------------------------------------------------------------------- + * + * pqsignal.h + * Backend signal(2) support (see also src/port/pqsignal.c) + * + * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/libpq/pqsignal.h + * + *------------------------------------------------------------------------- + */ +#ifndef PQSIGNAL_H +#define PQSIGNAL_H + +#include <signal.h> + +#ifndef WIN32 +#define PG_SETMASK(mask) sigprocmask(SIG_SETMASK, mask, NULL) +#else +/* Emulate POSIX sigset_t APIs on Windows */ +typedef int sigset_t; + +extern int pqsigsetmask(int mask); + +#define PG_SETMASK(mask) pqsigsetmask(*(mask)) +#define sigemptyset(set) (*(set) = 0) +#define sigfillset(set) (*(set) = ~0) +#define sigaddset(set, signum) (*(set) |= (sigmask(signum))) +#define sigdelset(set, signum) (*(set) &= ~(sigmask(signum))) +#endif /* WIN32 */ + +extern sigset_t UnBlockSig, + BlockSig, + StartupBlockSig; + +extern void pqinitmask(void); + +/* pqsigfunc is declared in src/include/port.h */ +extern pqsigfunc pqsignal_pm(int signo, pqsigfunc func); + +#endif /* PQSIGNAL_H */ diff --git a/src/include/libpq/scram.h b/src/include/libpq/scram.h new file mode 100644 index 0000000..83f1bbc --- /dev/null +++ b/src/include/libpq/scram.h @@ -0,0 +1,37 @@ +/*------------------------------------------------------------------------- + * + * scram.h + * Interface to libpq/scram.c + * + * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/libpq/scram.h + * + *------------------------------------------------------------------------- + */ +#ifndef PG_SCRAM_H +#define PG_SCRAM_H + +#include "lib/stringinfo.h" +#include "libpq/libpq-be.h" + +/* Status codes for message exchange */ +#define SASL_EXCHANGE_CONTINUE 0 +#define SASL_EXCHANGE_SUCCESS 1 +#define SASL_EXCHANGE_FAILURE 2 + +/* Routines dedicated to authentication */ +extern void pg_be_scram_get_mechanisms(Port *port, StringInfo buf); +extern void *pg_be_scram_init(Port *port, const char *selected_mech, const char *shadow_pass); +extern int pg_be_scram_exchange(void *opaq, const char *input, int inputlen, + char **output, int *outputlen, char **logdetail); + +/* Routines to handle and check SCRAM-SHA-256 secret */ +extern char *pg_be_scram_build_secret(const char *password); +extern bool parse_scram_secret(const char *secret, int *iterations, char **salt, + uint8 *stored_key, uint8 *server_key); +extern bool scram_verify_plain_password(const char *username, + const char *password, const char *secret); + +#endif /* PG_SCRAM_H */ |