| 1 | /*------------------------------------------------------------------------- |
| 2 | * |
| 3 | * libpq-be.h |
| 4 | * This file contains definitions for structures and externs used |
| 5 | * by the postmaster during client authentication. |
| 6 | * |
| 7 | * Note that this is backend-internal and is NOT exported to clients. |
| 8 | * Structs that need to be client-visible are in pqcomm.h. |
| 9 | * |
| 10 | * |
| 11 | * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group |
| 12 | * Portions Copyright (c) 1994, Regents of the University of California |
| 13 | * |
| 14 | * src/include/libpq/libpq-be.h |
| 15 | * |
| 16 | *------------------------------------------------------------------------- |
| 17 | */ |
| 18 | #ifndef LIBPQ_BE_H |
| 19 | #define LIBPQ_BE_H |
| 20 | |
| 21 | #include <sys/time.h> |
| 22 | #ifdef USE_OPENSSL |
| 23 | #include <openssl/ssl.h> |
| 24 | #include <openssl/err.h> |
| 25 | #endif |
| 26 | #ifdef HAVE_NETINET_TCP_H |
| 27 | #include <netinet/tcp.h> |
| 28 | #endif |
| 29 | |
| 30 | #ifdef ENABLE_GSS |
| 31 | #if defined(HAVE_GSSAPI_H) |
| 32 | #include <gssapi.h> |
| 33 | #else |
| 34 | #include <gssapi/gssapi.h> |
| 35 | #endif /* HAVE_GSSAPI_H */ |
| 36 | /* |
| 37 | * GSSAPI brings in headers that set a lot of things in the global namespace on win32, |
| 38 | * that doesn't match the msvc build. It gives a bunch of compiler warnings that we ignore, |
| 39 | * but also defines a symbol that simply does not exist. Undefine it again. |
| 40 | */ |
| 41 | #ifdef _MSC_VER |
| 42 | #undef HAVE_GETADDRINFO |
| 43 | #endif |
| 44 | #endif /* ENABLE_GSS */ |
| 45 | |
| 46 | #ifdef ENABLE_SSPI |
| 47 | #define SECURITY_WIN32 |
| 48 | #if defined(WIN32) && !defined(_MSC_VER) |
| 49 | #include <ntsecapi.h> |
| 50 | #endif |
| 51 | #include <security.h> |
| 52 | #undef SECURITY_WIN32 |
| 53 | |
| 54 | #ifndef ENABLE_GSS |
| 55 | /* |
| 56 | * Define a fake structure compatible with GSSAPI on Unix. |
| 57 | */ |
| 58 | typedef struct |
| 59 | { |
| 60 | void *value; |
| 61 | int length; |
| 62 | } gss_buffer_desc; |
| 63 | #endif |
| 64 | #endif /* ENABLE_SSPI */ |
| 65 | |
| 66 | #include "datatype/timestamp.h" |
| 67 | #include "libpq/hba.h" |
| 68 | #include "libpq/pqcomm.h" |
| 69 | |
| 70 | |
| 71 | typedef enum CAC_state |
| 72 | { |
| 73 | CAC_OK, CAC_STARTUP, CAC_SHUTDOWN, CAC_RECOVERY, CAC_TOOMANY, |
| 74 | CAC_WAITBACKUP |
| 75 | } CAC_state; |
| 76 | |
| 77 | |
| 78 | /* |
| 79 | * GSSAPI specific state information |
| 80 | */ |
| 81 | #if defined(ENABLE_GSS) | defined(ENABLE_SSPI) |
| 82 | typedef struct |
| 83 | { |
| 84 | gss_buffer_desc outbuf; /* GSSAPI output token buffer */ |
| 85 | #ifdef ENABLE_GSS |
| 86 | gss_cred_id_t cred; /* GSSAPI connection cred's */ |
| 87 | gss_ctx_id_t ctx; /* GSSAPI connection context */ |
| 88 | gss_name_t name; /* GSSAPI client name */ |
| 89 | char *princ; /* GSSAPI Principal used for auth, NULL if |
| 90 | * GSSAPI auth was not used */ |
| 91 | bool auth; /* GSSAPI Authentication used */ |
| 92 | bool enc; /* GSSAPI encryption in use */ |
| 93 | #endif |
| 94 | } pg_gssinfo; |
| 95 | #endif |
| 96 | |
| 97 | /* |
| 98 | * This is used by the postmaster in its communication with frontends. It |
| 99 | * contains all state information needed during this communication before the |
| 100 | * backend is run. The Port structure is kept in malloc'd memory and is |
| 101 | * still available when a backend is running (see MyProcPort). The data |
| 102 | * it points to must also be malloc'd, or else palloc'd in TopMemoryContext, |
| 103 | * so that it survives into PostgresMain execution! |
| 104 | * |
| 105 | * remote_hostname is set if we did a successful reverse lookup of the |
| 106 | * client's IP address during connection setup. |
| 107 | * remote_hostname_resolv tracks the state of hostname verification: |
| 108 | * +1 = remote_hostname is known to resolve to client's IP address |
| 109 | * -1 = remote_hostname is known NOT to resolve to client's IP address |
| 110 | * 0 = we have not done the forward DNS lookup yet |
| 111 | * -2 = there was an error in name resolution |
| 112 | * If reverse lookup of the client IP address fails, remote_hostname will be |
| 113 | * left NULL while remote_hostname_resolv is set to -2. If reverse lookup |
| 114 | * succeeds but forward lookup fails, remote_hostname_resolv is also set to -2 |
| 115 | * (the case is distinguishable because remote_hostname isn't NULL). In |
| 116 | * either of the -2 cases, remote_hostname_errcode saves the lookup return |
| 117 | * code for possible later use with gai_strerror. |
| 118 | */ |
| 119 | |
| 120 | typedef struct Port |
| 121 | { |
| 122 | pgsocket sock; /* File descriptor */ |
| 123 | bool noblock; /* is the socket in non-blocking mode? */ |
| 124 | ProtocolVersion proto; /* FE/BE protocol version */ |
| 125 | SockAddr laddr; /* local addr (postmaster) */ |
| 126 | SockAddr raddr; /* remote addr (client) */ |
| 127 | char *remote_host; /* name (or ip addr) of remote host */ |
| 128 | char *remote_hostname; /* name (not ip addr) of remote host, if |
| 129 | * available */ |
| 130 | int remote_hostname_resolv; /* see above */ |
| 131 | int remote_hostname_errcode; /* see above */ |
| 132 | char *remote_port; /* text rep of remote port */ |
| 133 | CAC_state canAcceptConnections; /* postmaster connection status */ |
| 134 | |
| 135 | /* |
| 136 | * Information that needs to be saved from the startup packet and passed |
| 137 | * into backend execution. "char *" fields are NULL if not set. |
| 138 | * guc_options points to a List of alternating option names and values. |
| 139 | */ |
| 140 | char *database_name; |
| 141 | char *user_name; |
| 142 | char *cmdline_options; |
| 143 | List *guc_options; |
| 144 | |
| 145 | /* |
| 146 | * The startup packet application name, only used here for the "connection |
| 147 | * authorized" log message. We shouldn't use this post-startup, instead |
| 148 | * the GUC should be used as application can change it afterward. |
| 149 | */ |
| 150 | char *application_name; |
| 151 | |
| 152 | /* |
| 153 | * Information that needs to be held during the authentication cycle. |
| 154 | */ |
| 155 | HbaLine *hba; |
| 156 | |
| 157 | /* |
| 158 | * TCP keepalive and user timeout settings. |
| 159 | * |
| 160 | * default values are 0 if AF_UNIX or not yet known; current values are 0 |
| 161 | * if AF_UNIX or using the default. Also, -1 in a default value means we |
| 162 | * were unable to find out the default (getsockopt failed). |
| 163 | */ |
| 164 | int default_keepalives_idle; |
| 165 | int default_keepalives_interval; |
| 166 | int default_keepalives_count; |
| 167 | int default_tcp_user_timeout; |
| 168 | int keepalives_idle; |
| 169 | int keepalives_interval; |
| 170 | int keepalives_count; |
| 171 | int tcp_user_timeout; |
| 172 | |
| 173 | /* |
| 174 | * GSSAPI structures. |
| 175 | */ |
| 176 | #if defined(ENABLE_GSS) || defined(ENABLE_SSPI) |
| 177 | |
| 178 | /* |
| 179 | * If GSSAPI is supported, store GSSAPI information. Otherwise, store a |
| 180 | * NULL pointer to make sure offsets in the struct remain the same. |
| 181 | */ |
| 182 | pg_gssinfo *gss; |
| 183 | #else |
| 184 | void *gss; |
| 185 | #endif |
| 186 | |
| 187 | /* |
| 188 | * SSL structures. |
| 189 | */ |
| 190 | bool ssl_in_use; |
| 191 | char *peer_cn; |
| 192 | bool peer_cert_valid; |
| 193 | |
| 194 | /* |
| 195 | * OpenSSL structures. (Keep these last so that the locations of other |
| 196 | * fields are the same whether or not you build with OpenSSL.) |
| 197 | */ |
| 198 | #ifdef USE_OPENSSL |
| 199 | SSL *ssl; |
| 200 | X509 *peer; |
| 201 | #endif |
| 202 | } Port; |
| 203 | |
| 204 | #ifdef USE_SSL |
| 205 | /* |
| 206 | * Hardcoded DH parameters, used in ephemeral DH keying. (See also |
| 207 | * README.SSL for more details on EDH.) |
| 208 | * |
| 209 | * If you want to create your own hardcoded DH parameters |
| 210 | * for fun and profit, review "Assigned Number for SKIP |
| 211 | * Protocols" (http://www.skip-vpn.org/spec/numbers.html) |
| 212 | * for suggestions. |
| 213 | */ |
| 214 | #define FILE_DH2048 \ |
| 215 | "-----BEGIN DH PARAMETERS-----\n\ |
| 216 | MIIBCAKCAQEA9kJXtwh/CBdyorrWqULzBej5UxE5T7bxbrlLOCDaAadWoxTpj0BV\n\ |
| 217 | 89AHxstDqZSt90xkhkn4DIO9ZekX1KHTUPj1WV/cdlJPPT2N286Z4VeSWc39uK50\n\ |
| 218 | T8X8dryDxUcwYc58yWb/Ffm7/ZFexwGq01uejaClcjrUGvC/RgBYK+X0iP1YTknb\n\ |
| 219 | zSC0neSRBzZrM2w4DUUdD3yIsxx8Wy2O9vPJI8BD8KVbGI2Ou1WMuF040zT9fBdX\n\ |
| 220 | Q6MdGGzeMyEstSr/POGxKUAYEY18hKcKctaGxAMZyAcpesqVDNmWn6vQClCbAkbT\n\ |
| 221 | CD1mpF1Bn5x8vYlLIhkmuquiXsNV6TILOwIBAg==\n\ |
| 222 | -----END DH PARAMETERS-----\n" |
| 223 | |
| 224 | /* |
| 225 | * These functions are implemented by the glue code specific to each |
| 226 | * SSL implementation (e.g. be-secure-openssl.c) |
| 227 | */ |
| 228 | |
| 229 | /* |
| 230 | * Initialize global SSL context. |
| 231 | * |
| 232 | * If isServerStart is true, report any errors as FATAL (so we don't return). |
| 233 | * Otherwise, log errors at LOG level and return -1 to indicate trouble, |
| 234 | * preserving the old SSL state if any. Returns 0 if OK. |
| 235 | */ |
| 236 | extern int be_tls_init(bool isServerStart); |
| 237 | |
| 238 | /* |
| 239 | * Destroy global SSL context, if any. |
| 240 | */ |
| 241 | extern void be_tls_destroy(void); |
| 242 | |
| 243 | /* |
| 244 | * Attempt to negotiate SSL connection. |
| 245 | */ |
| 246 | extern int be_tls_open_server(Port *port); |
| 247 | |
| 248 | /* |
| 249 | * Close SSL connection. |
| 250 | */ |
| 251 | extern void be_tls_close(Port *port); |
| 252 | |
| 253 | /* |
| 254 | * Read data from a secure connection. |
| 255 | */ |
| 256 | extern ssize_t be_tls_read(Port *port, void *ptr, size_t len, int *waitfor); |
| 257 | |
| 258 | /* |
| 259 | * Write data to a secure connection. |
| 260 | */ |
| 261 | extern ssize_t be_tls_write(Port *port, void *ptr, size_t len, int *waitfor); |
| 262 | |
| 263 | /* |
| 264 | * Return information about the SSL connection. |
| 265 | */ |
| 266 | extern int be_tls_get_cipher_bits(Port *port); |
| 267 | extern bool be_tls_get_compression(Port *port); |
| 268 | extern const char *be_tls_get_version(Port *port); |
| 269 | extern const char *be_tls_get_cipher(Port *port); |
| 270 | extern void be_tls_get_peer_subject_name(Port *port, char *ptr, size_t len); |
| 271 | extern void be_tls_get_peer_issuer_name(Port *port, char *ptr, size_t len); |
| 272 | extern void be_tls_get_peer_serial(Port *port, char *ptr, size_t len); |
| 273 | |
| 274 | /* |
| 275 | * Get the server certificate hash for SCRAM channel binding type |
| 276 | * tls-server-end-point. |
| 277 | * |
| 278 | * The result is a palloc'd hash of the server certificate with its |
| 279 | * size, and NULL if there is no certificate available. |
| 280 | * |
| 281 | * This is not supported with old versions of OpenSSL that don't have |
| 282 | * the X509_get_signature_nid() function. |
| 283 | */ |
| 284 | #if defined(USE_OPENSSL) && defined(HAVE_X509_GET_SIGNATURE_NID) |
| 285 | #define HAVE_BE_TLS_GET_CERTIFICATE_HASH |
| 286 | extern char *be_tls_get_certificate_hash(Port *port, size_t *len); |
| 287 | #endif |
| 288 | |
| 289 | #endif /* USE_SSL */ |
| 290 | |
| 291 | #ifdef ENABLE_GSS |
| 292 | /* |
| 293 | * Return information about the GSSAPI authenticated connection |
| 294 | */ |
| 295 | extern bool be_gssapi_get_auth(Port *port); |
| 296 | extern bool be_gssapi_get_enc(Port *port); |
| 297 | extern const char *be_gssapi_get_princ(Port *port); |
| 298 | |
| 299 | /* Read and write to a GSSAPI-encrypted connection. */ |
| 300 | extern ssize_t be_gssapi_read(Port *port, void *ptr, size_t len); |
| 301 | extern ssize_t be_gssapi_write(Port *port, void *ptr, size_t len); |
| 302 | #endif /* ENABLE_GSS */ |
| 303 | |
| 304 | extern ProtocolVersion FrontendProtocol; |
| 305 | |
| 306 | /* TCP keepalives configuration. These are no-ops on an AF_UNIX socket. */ |
| 307 | |
| 308 | extern int pq_getkeepalivesidle(Port *port); |
| 309 | extern int pq_getkeepalivesinterval(Port *port); |
| 310 | extern int pq_getkeepalivescount(Port *port); |
| 311 | extern int pq_gettcpusertimeout(Port *port); |
| 312 | |
| 313 | extern int pq_setkeepalivesidle(int idle, Port *port); |
| 314 | extern int pq_setkeepalivesinterval(int interval, Port *port); |
| 315 | extern int pq_setkeepalivescount(int count, Port *port); |
| 316 | extern int pq_settcpusertimeout(int timeout, Port *port); |
| 317 | |
| 318 | #endif /* LIBPQ_BE_H */ |
| 319 | |