diff options
Diffstat (limited to 'src/include/libpq')
-rw-r--r-- | src/include/libpq/auth.h | 31 | ||||
-rw-r--r-- | src/include/libpq/be-fsstubs.h | 32 | ||||
-rw-r--r-- | src/include/libpq/be-gssapi-common.h | 30 | ||||
-rw-r--r-- | src/include/libpq/crypt.h | 47 | ||||
-rw-r--r-- | src/include/libpq/hba.h | 179 | ||||
-rw-r--r-- | src/include/libpq/ifaddr.h | 30 | ||||
-rw-r--r-- | src/include/libpq/libpq-be.h | 343 | ||||
-rw-r--r-- | src/include/libpq/libpq-fs.h | 24 | ||||
-rw-r--r-- | src/include/libpq/libpq.h | 144 | ||||
-rw-r--r-- | src/include/libpq/pqcomm.h | 194 | ||||
-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/sasl.h | 136 | ||||
-rw-r--r-- | src/include/libpq/scram.h | 30 |
15 files changed, 1496 insertions, 0 deletions
diff --git a/src/include/libpq/auth.h b/src/include/libpq/auth.h new file mode 100644 index 0000000..d3c189e --- /dev/null +++ b/src/include/libpq/auth.h @@ -0,0 +1,31 @@ +/*------------------------------------------------------------------------- + * + * auth.h + * Definitions for network authentication routines + * + * + * Portions Copyright (c) 1996-2022, 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 PGDLLIMPORT char *pg_krb_server_keyfile; +extern PGDLLIMPORT bool pg_krb_caseins_users; +extern PGDLLIMPORT char *pg_krb_realm; + +extern void ClientAuthentication(Port *port); +extern void sendAuthRequest(Port *port, AuthRequest areq, const char *extradata, + int extralen); + +/* 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..130bc30 --- /dev/null +++ b/src/include/libpq/be-fsstubs.h @@ -0,0 +1,32 @@ +/*------------------------------------------------------------------------- + * + * be-fsstubs.h + * + * + * + * Portions Copyright (c) 1996-2022, 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..ae84112 --- /dev/null +++ b/src/include/libpq/be-gssapi-common.h @@ -0,0 +1,30 @@ +/*------------------------------------------------------------------------- + * + * be-gssapi-common.h + * Definitions for GSSAPI authentication and encryption handling + * + * Portions Copyright (c) 1996-2022, 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 + +#ifdef ENABLE_GSS + +#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 /* ENABLE_GSS */ + +#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..3238cf6 --- /dev/null +++ b/src/include/libpq/crypt.h @@ -0,0 +1,47 @@ +/*------------------------------------------------------------------------- + * + * crypt.h + * Interface to libpq/crypt.c + * + * Portions Copyright (c) 1996-2022, 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, const 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, const char **logdetail); +extern int plain_crypt_verify(const char *role, const char *shadow_pass, + const char *client_pass, + const char **logdetail); + +#endif diff --git a/src/include/libpq/hba.h b/src/include/libpq/hba.h new file mode 100644 index 0000000..d06da81 --- /dev/null +++ b/src/include/libpq/hba.h @@ -0,0 +1,179 @@ +/*------------------------------------------------------------------------- + * + * 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 enum ClientCertName +{ + clientCertCN, + clientCertDN +} ClientCertName; + +typedef struct HbaLine +{ + int linenumber; + char *rawline; + ConnType conntype; + List *databases; + List *roles; + struct sockaddr_storage addr; + int addrlen; /* zero if we don't have a valid addr */ + struct sockaddr_storage mask; + int masklen; /* zero if we don't have a valid 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; + ClientCertName clientcertname; + 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; +} HbaLine; + +typedef struct IdentLine +{ + int linenumber; + + char *usermap; + char *ident_user; + char *pg_role; + regex_t re; +} IdentLine; + +/* + * A single string token lexed from an authentication configuration file + * (pg_ident.conf or pg_hba.conf), together with whether the token has + * been quoted. + */ +typedef struct AuthToken +{ + char *string; + bool quoted; +} AuthToken; + +/* + * TokenizedAuthLine represents one line lexed from an authentication + * configuration file. Each item in the "fields" list is a sub-list of + * AuthTokens. We don't emit a TokenizedAuthLine for empty or all-comment + * lines, so "fields" is never NIL (nor are any of its sub-lists). + * + * Exception: if an error occurs during tokenization, we might have + * fields == NIL, in which case err_msg != NULL. + */ +typedef struct TokenizedAuthLine +{ + List *fields; /* List of lists of AuthTokens */ + int line_num; /* Line number */ + char *raw_line; /* Raw line text */ + char *err_msg; /* Error message if any */ +} TokenizedAuthLine; + +/* kluge to avoid including libpq/libpq-be.h here */ +typedef struct Port hbaPort; + +extern bool load_hba(void); +extern bool load_ident(void); +extern const char *hba_authname(UserAuth auth_method); +extern void hba_getauthmethod(hbaPort *port); +extern int check_usermap(const char *usermap_name, + const char *pg_role, const char *auth_user, + bool case_insensitive); +extern HbaLine *parse_hba_line(TokenizedAuthLine *tok_line, int elevel); +extern IdentLine *parse_ident_line(TokenizedAuthLine *tok_line, int elevel); +extern bool pg_isblank(const char c); +extern MemoryContext tokenize_auth_file(const char *filename, FILE *file, + List **tok_lines, int elevel); + +#endif /* HBA_H */ diff --git a/src/include/libpq/ifaddr.h b/src/include/libpq/ifaddr.h new file mode 100644 index 0000000..b04d093 --- /dev/null +++ b/src/include/libpq/ifaddr.h @@ -0,0 +1,30 @@ +/*------------------------------------------------------------------------- + * + * ifaddr.h + * IP netmask calculations, and enumerating network interfaces. + * + * Copyright (c) 2003-2022, 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..351b4f4 --- /dev/null +++ b/src/include/libpq/libpq-be.h @@ -0,0 +1,343 @@ +/*------------------------------------------------------------------------- + * + * 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-2022, 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_NOTCONSISTENT, + CAC_TOOMANY +} 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; + + /* + * Authenticated identity. The meaning of this identifier is dependent on + * hba->auth_method; it is the identity (if any) that the user presented + * during the authentication cycle, before they were assigned a database + * role. (It is effectively the "SYSTEM-USERNAME" of a pg_ident usermap + * -- though the exact string in use may be different, depending on pg_hba + * options.) + * + * authn_id is NULL if the user has not actually been authenticated, for + * example if the "trust" auth method is in use. + */ + const char *authn_id; + + /* + * 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; + char *peer_dn; + 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 SSL enabled.) + */ +#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 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) || defined(HAVE_X509_GET_SIGNATURE_INFO)) +#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 PGDLLIMPORT 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..7fa02d2 --- /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-2022, 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..2de7d9b --- /dev/null +++ b/src/include/libpq/libpq.h @@ -0,0 +1,144 @@ +/*------------------------------------------------------------------------- + * + * libpq.h + * POSTGRES LIBPQ buffer structure definitions. + * + * + * Portions Copyright (c) 1996-2022, 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" + + +/* + * Callers of pq_getmessage() must supply a maximum expected message size. + * By convention, if there's not any specific reason to use another value, + * use PQ_SMALL_MESSAGE_LIMIT for messages that shouldn't be too long, and + * PQ_LARGE_MESSAGE_LIMIT for messages that can be long. + */ +#define PQ_SMALL_MESSAGE_LIMIT 10000 +#define PQ_LARGE_MESSAGE_LIMIT (MaxAllocSize - 1) + +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); +} 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)) + +/* + * External functions. + */ + +/* + * prototypes for functions in pqcomm.c + */ +extern PGDLLIMPORT WaitEventSet *FeBeWaitSet; + +#define FeBeWaitSetSocketPos 0 +#define FeBeWaitSetLatchPos 1 +#define FeBeWaitSetNEvents 3 + +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 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 bool pq_buffer_has_data(void); +extern int pq_putmessage_v2(char msgtype, const char *s, size_t len); +extern bool pq_check_connection(void); + +/* + * prototypes for functions in be-secure.c + */ +extern PGDLLIMPORT char *ssl_library; +extern PGDLLIMPORT char *ssl_cert_file; +extern PGDLLIMPORT char *ssl_key_file; +extern PGDLLIMPORT char *ssl_ca_file; +extern PGDLLIMPORT char *ssl_crl_file; +extern PGDLLIMPORT char *ssl_crl_dir; +extern PGDLLIMPORT char *ssl_dh_params_file; +extern PGDLLIMPORT char *ssl_passphrase_command; +extern PGDLLIMPORT bool ssl_passphrase_command_supports_reload; +#ifdef USE_SSL +extern PGDLLIMPORT 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 PGDLLIMPORT char *SSLCipherSuites; +extern PGDLLIMPORT char *SSLECDHCurve; +extern PGDLLIMPORT bool SSLPreferServerCiphers; +extern PGDLLIMPORT int ssl_min_protocol_version; +extern PGDLLIMPORT 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..b418283 --- /dev/null +++ b/src/include/libpq/pqcomm.h @@ -0,0 +1,194 @@ +/*------------------------------------------------------------------------- + * + * 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-2022, 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; + socklen_t 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) + +/* + * A host that looks either like an absolute path or starts with @ is + * interpreted as a Unix-domain socket address. + */ +static inline bool +is_unixsock_path(const char *path) +{ + return is_absolute_path(path) || path[0] == '@'; +} + +/* + * 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. + * (Only protocol version 3 is currently supported) + */ + +#define PG_PROTOCOL_EARLIEST PG_PROTOCOL(3,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; + +extern PGDLLIMPORT 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..cd83482 --- /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-2022, 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..6687c8f --- /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-2022, 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_leader(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..41227a3 --- /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-2022, 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 PGDLLIMPORT sigset_t UnBlockSig; +extern PGDLLIMPORT sigset_t BlockSig; +extern PGDLLIMPORT sigset_t 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/sasl.h b/src/include/libpq/sasl.h new file mode 100644 index 0000000..39ccf8f --- /dev/null +++ b/src/include/libpq/sasl.h @@ -0,0 +1,136 @@ +/*------------------------------------------------------------------------- + * + * sasl.h + * Defines the SASL mechanism interface for the backend. + * + * Each SASL mechanism defines a frontend and a backend callback structure. + * + * See src/interfaces/libpq/fe-auth-sasl.h for the frontend counterpart. + * + * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/libpq/sasl.h + * + *------------------------------------------------------------------------- + */ + +#ifndef PG_SASL_H +#define PG_SASL_H + +#include "lib/stringinfo.h" +#include "libpq/libpq-be.h" + +/* Status codes for message exchange */ +#define PG_SASL_EXCHANGE_CONTINUE 0 +#define PG_SASL_EXCHANGE_SUCCESS 1 +#define PG_SASL_EXCHANGE_FAILURE 2 + +/* + * Backend SASL mechanism callbacks. + * + * To implement a backend mechanism, declare a pg_be_sasl_mech struct with + * appropriate callback implementations. Then pass the mechanism to + * CheckSASLAuth() during ClientAuthentication(), once the server has decided + * which authentication method to use. + */ +typedef struct pg_be_sasl_mech +{ + /*--------- + * get_mechanisms() + * + * Retrieves the list of SASL mechanism names supported by this + * implementation. + * + * Input parameters: + * + * port: The client Port + * + * Output parameters: + * + * buf: A StringInfo buffer that the callback should populate with + * supported mechanism names. The names are appended into this + * StringInfo, each one ending with '\0' bytes. + *--------- + */ + void (*get_mechanisms) (Port *port, StringInfo buf); + + /*--------- + * init() + * + * Initializes mechanism-specific state for a connection. This callback + * must return a pointer to its allocated state, which will be passed + * as-is as the first argument to the other callbacks. + * + * Input parameters: + * + * port: The client Port. + * + * mech: The actual mechanism name in use by the client. + * + * shadow_pass: The stored secret for the role being authenticated, or + * NULL if one does not exist. Mechanisms that do not use + * shadow entries may ignore this parameter. If a + * mechanism uses shadow entries but shadow_pass is NULL, + * the implementation must continue the exchange as if the + * user existed and the password did not match, to avoid + * disclosing valid user names. + *--------- + */ + void *(*init) (Port *port, const char *mech, const char *shadow_pass); + + /*--------- + * exchange() + * + * Produces a server challenge to be sent to the client. The callback + * must return one of the PG_SASL_EXCHANGE_* values, depending on + * whether the exchange continues, has finished successfully, or has + * failed. + * + * Input parameters: + * + * state: The opaque mechanism state returned by init() + * + * input: The response data sent by the client, or NULL if the + * mechanism is client-first but the client did not send an + * initial response. (This can only happen during the first + * message from the client.) This is guaranteed to be + * null-terminated for safety, but SASL allows embedded + * nulls in responses, so mechanisms must be careful to + * check inputlen. + * + * inputlen: The length of the challenge data sent by the server, or + * -1 if the client did not send an initial response + * + * Output parameters, to be set by the callback function: + * + * output: A palloc'd buffer containing either the server's next + * challenge (if PG_SASL_EXCHANGE_CONTINUE is returned) or + * the server's outcome data (if PG_SASL_EXCHANGE_SUCCESS is + * returned and the mechanism requires data to be sent during + * a successful outcome). The callback should set this to + * NULL if the exchange is over and no output should be sent, + * which should correspond to either PG_SASL_EXCHANGE_FAILURE + * or a PG_SASL_EXCHANGE_SUCCESS with no outcome data. + * + * outputlen: The length of the challenge data. Ignored if *output is + * NULL. + * + * logdetail: Set to an optional DETAIL message to be printed to the + * server log, to disambiguate failure modes. (The client + * will only ever see the same generic authentication + * failure message.) Ignored if the exchange is completed + * with PG_SASL_EXCHANGE_SUCCESS. + *--------- + */ + int (*exchange) (void *state, + const char *input, int inputlen, + char **output, int *outputlen, + const char **logdetail); +} pg_be_sasl_mech; + +/* Common implementation for auth.c */ +extern int CheckSASLAuth(const pg_be_sasl_mech *mech, Port *port, + char *shadow_pass, const char **logdetail); + +#endif /* PG_SASL_H */ diff --git a/src/include/libpq/scram.h b/src/include/libpq/scram.h new file mode 100644 index 0000000..c51e848 --- /dev/null +++ b/src/include/libpq/scram.h @@ -0,0 +1,30 @@ +/*------------------------------------------------------------------------- + * + * scram.h + * Interface to libpq/scram.c + * + * Portions Copyright (c) 1996-2022, 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" +#include "libpq/sasl.h" + +/* SASL implementation callbacks */ +extern PGDLLIMPORT const pg_be_sasl_mech pg_be_scram_mech; + +/* 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 */ |