PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
backend_startup.c File Reference
#include "postgres.h"
#include <unistd.h>
#include "access/xlog.h"
#include "access/xlogrecovery.h"
#include "common/ip.h"
#include "common/string.h"
#include "libpq/libpq.h"
#include "libpq/libpq-be.h"
#include "libpq/pqformat.h"
#include "libpq/pqsignal.h"
#include "miscadmin.h"
#include "postmaster/postmaster.h"
#include "replication/walsender.h"
#include "storage/fd.h"
#include "storage/ipc.h"
#include "storage/procsignal.h"
#include "storage/proc.h"
#include "tcop/backend_startup.h"
#include "tcop/tcopprot.h"
#include "utils/builtins.h"
#include "utils/guc_hooks.h"
#include "utils/injection_point.h"
#include "utils/memutils.h"
#include "utils/ps_status.h"
#include "utils/timeout.h"
#include "utils/varlena.h"
Include dependency graph for backend_startup.c:

Go to the source code of this file.

Functions

static void BackendInitialize (ClientSocket *client_sock, CAC_state cac)
 
static int ProcessSSLStartup (Port *port)
 
static int ProcessStartupPacket (Port *port, bool ssl_done, bool gss_done)
 
static void ProcessCancelRequestPacket (Port *port, void *pkt, int pktlen)
 
static void SendNegotiateProtocolVersion (List *unrecognized_protocol_options)
 
static void process_startup_packet_die (SIGNAL_ARGS)
 
static void StartupPacketTimeoutHandler (void)
 
static bool validate_log_connections_options (List *elemlist, uint32 *flags)
 
void BackendMain (const void *startup_data, size_t startup_data_len)
 
bool check_log_connections (char **newval, void **extra, GucSource source)
 
void assign_log_connections (const char *newval, void *extra)
 

Variables

bool Trace_connection_negotiation = false
 
uint32 log_connections = 0
 
char * log_connections_string = NULL
 
ConnectionTiming conn_timing = {.ready_for_use = TIMESTAMP_MINUS_INFINITY}
 

Function Documentation

◆ assign_log_connections()

void assign_log_connections ( const char *  newval,
void *  extra 
)

Definition at line 1112 of file backend_startup.c.

1113{
1114 log_connections = *((int *) extra);
1115}
uint32 log_connections

References log_connections.

◆ BackendInitialize()

static void BackendInitialize ( ClientSocket client_sock,
CAC_state  cac 
)
static

Definition at line 141 of file backend_startup.c.

142{
143 int status;
144 int ret;
145 Port *port;
146 char remote_host[NI_MAXHOST];
147 char remote_port[NI_MAXSERV];
148 StringInfoData ps_data;
149 MemoryContext oldcontext;
150
151 /* Tell fd.c about the long-lived FD associated with the client_sock */
153
154 /*
155 * PreAuthDelay is a debugging aid for investigating problems in the
156 * authentication cycle: it can be set in postgresql.conf to allow time to
157 * attach to the newly-forked backend with a debugger. (See also
158 * PostAuthDelay, which we allow clients to pass through PGOPTIONS, but it
159 * is not honored until after authentication.)
160 */
161 if (PreAuthDelay > 0)
162 pg_usleep(PreAuthDelay * 1000000L);
163
164 /* This flag will remain set until InitPostgres finishes authentication */
165 ClientAuthInProgress = true; /* limit visibility of log messages */
166
167 /*
168 * Initialize libpq and enable reporting of ereport errors to the client.
169 * Must do this now because authentication uses libpq to send messages.
170 *
171 * The Port structure and all data structures attached to it are allocated
172 * in TopMemoryContext, so that they survive into PostgresMain execution.
173 * We need not worry about leaking this storage on failure, since we
174 * aren't in the postmaster process anymore.
175 */
177 port = MyProcPort = pq_init(client_sock);
178 MemoryContextSwitchTo(oldcontext);
179
180 whereToSendOutput = DestRemote; /* now safe to ereport to client */
181
182 /* set these to empty in case they are needed before we set them up */
183 port->remote_host = "";
184 port->remote_port = "";
185
186 /*
187 * We arrange to do _exit(1) if we receive SIGTERM or timeout while trying
188 * to collect the startup packet; while SIGQUIT results in _exit(2).
189 * Otherwise the postmaster cannot shutdown the database FAST or IMMED
190 * cleanly if a buggy client fails to send the packet promptly.
191 *
192 * Exiting with _exit(1) is only possible because we have not yet touched
193 * shared memory; therefore no outside-the-process state needs to get
194 * cleaned up.
195 */
197 /* SIGQUIT handler was already set up by InitPostmasterChild */
198 InitializeTimeouts(); /* establishes SIGALRM handler */
199 sigprocmask(SIG_SETMASK, &StartupBlockSig, NULL);
200
201 /*
202 * Get the remote host name and port for logging and status display.
203 */
204 remote_host[0] = '\0';
205 remote_port[0] = '\0';
206 if ((ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
207 remote_host, sizeof(remote_host),
208 remote_port, sizeof(remote_port),
209 (log_hostname ? 0 : NI_NUMERICHOST) | NI_NUMERICSERV)) != 0)
211 (errmsg_internal("pg_getnameinfo_all() failed: %s",
212 gai_strerror(ret))));
213
214 /*
215 * Save remote_host and remote_port in port structure (after this, they
216 * will appear in log_line_prefix data for log messages).
217 */
218 port->remote_host = MemoryContextStrdup(TopMemoryContext, remote_host);
219 port->remote_port = MemoryContextStrdup(TopMemoryContext, remote_port);
220
221 /* And now we can log that the connection was received, if enabled */
223 {
224 if (remote_port[0])
225 ereport(LOG,
226 (errmsg("connection received: host=%s port=%s",
227 remote_host,
228 remote_port)));
229 else
230 ereport(LOG,
231 (errmsg("connection received: host=%s",
232 remote_host)));
233 }
234
235 /* For testing client error handling */
236#ifdef USE_INJECTION_POINTS
237 INJECTION_POINT("backend-initialize");
238 if (IS_INJECTION_POINT_ATTACHED("backend-initialize-v2-error"))
239 {
240 /*
241 * This simulates an early error from a pre-v14 server, which used the
242 * version 2 protocol for any errors that occurred before processing
243 * the startup packet.
244 */
246 elog(FATAL, "protocol version 2 error triggered");
247 }
248#endif
249
250 /*
251 * If we did a reverse lookup to name, we might as well save the results
252 * rather than possibly repeating the lookup during authentication.
253 *
254 * Note that we don't want to specify NI_NAMEREQD above, because then we'd
255 * get nothing useful for a client without an rDNS entry. Therefore, we
256 * must check whether we got a numeric IPv4 or IPv6 address, and not save
257 * it into remote_hostname if so. (This test is conservative and might
258 * sometimes classify a hostname as numeric, but an error in that
259 * direction is safe; it only results in a possible extra lookup.)
260 */
261 if (log_hostname &&
262 ret == 0 &&
263 strspn(remote_host, "0123456789.") < strlen(remote_host) &&
264 strspn(remote_host, "0123456789ABCDEFabcdef:") < strlen(remote_host))
265 {
266 port->remote_hostname = MemoryContextStrdup(TopMemoryContext, remote_host);
267 }
268
269 /*
270 * Ready to begin client interaction. We will give up and _exit(1) after
271 * a time delay, so that a broken client can't hog a connection
272 * indefinitely. PreAuthDelay and any DNS interactions above don't count
273 * against the time limit.
274 *
275 * Note: AuthenticationTimeout is applied here while waiting for the
276 * startup packet, and then again in InitPostgres for the duration of any
277 * authentication operations. So a hostile client could tie up the
278 * process for nearly twice AuthenticationTimeout before we kick him off.
279 *
280 * Note: because PostgresMain will call InitializeTimeouts again, the
281 * registration of STARTUP_PACKET_TIMEOUT will be lost. This is okay
282 * since we never use it again after this function.
283 */
286
287 /* Handle direct SSL handshake */
288 status = ProcessSSLStartup(port);
289
290 /*
291 * Receive the startup packet (which might turn out to be a cancel request
292 * packet).
293 */
294 if (status == STATUS_OK)
295 status = ProcessStartupPacket(port, false, false);
296
297 /*
298 * If we're going to reject the connection due to database state, say so
299 * now instead of wasting cycles on an authentication exchange. (This also
300 * allows a pg_ping utility to be written.)
301 */
302 if (status == STATUS_OK)
303 {
304 switch (cac)
305 {
306 case CAC_STARTUP:
309 errmsg("the database system is starting up")));
310 break;
312 if (!EnableHotStandby)
315 errmsg("the database system is not accepting connections"),
316 errdetail("Hot standby mode is disabled.")));
317 else if (reachedConsistency)
320 errmsg("the database system is not yet accepting connections"),
321 errdetail("Recovery snapshot is not yet ready for hot standby."),
322 errhint("To enable hot standby, close write transactions with more than %d subtransactions on the primary server.",
324 else
327 errmsg("the database system is not yet accepting connections"),
328 errdetail("Consistent recovery state has not been yet reached.")));
329 break;
330 case CAC_SHUTDOWN:
333 errmsg("the database system is shutting down")));
334 break;
335 case CAC_RECOVERY:
338 errmsg("the database system is in recovery mode")));
339 break;
340 case CAC_TOOMANY:
342 (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
343 errmsg("sorry, too many clients already")));
344 break;
345 case CAC_OK:
346 break;
347 }
348 }
349
350 /*
351 * Disable the timeout, and prevent SIGTERM again.
352 */
354 sigprocmask(SIG_SETMASK, &BlockSig, NULL);
355
356 /*
357 * As a safety check that nothing in startup has yet performed
358 * shared-memory modifications that would need to be undone if we had
359 * exited through SIGTERM or timeout above, check that no on_shmem_exit
360 * handlers have been registered yet. (This isn't terribly bulletproof,
361 * since someone might misuse an on_proc_exit handler for shmem cleanup,
362 * but it's a cheap and helpful check. We cannot disallow on_proc_exit
363 * handlers unfortunately, since pq_init() already registered one.)
364 */
366
367 /*
368 * Stop here if it was bad or a cancel packet. ProcessStartupPacket
369 * already did any appropriate error reporting.
370 */
371 if (status != STATUS_OK)
372 proc_exit(0);
373
374 /*
375 * Now that we have the user and database name, we can set the process
376 * title for ps. It's good to do this as early as possible in startup.
377 */
378 initStringInfo(&ps_data);
379 if (am_walsender)
381 appendStringInfo(&ps_data, "%s ", port->user_name);
382 if (port->database_name[0] != '\0')
383 appendStringInfo(&ps_data, "%s ", port->database_name);
384 appendStringInfoString(&ps_data, port->remote_host);
385 if (port->remote_port[0] != '\0')
386 appendStringInfo(&ps_data, "(%s)", port->remote_port);
387
388 init_ps_display(ps_data.data);
389 pfree(ps_data.data);
390
391 set_ps_display("initializing");
392}
sigset_t StartupBlockSig
Definition: pqsignal.c:24
sigset_t BlockSig
Definition: pqsignal.c:23
static void process_startup_packet_die(SIGNAL_ARGS)
static void StartupPacketTimeoutHandler(void)
static int ProcessSSLStartup(Port *port)
static int ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
@ CAC_TOOMANY
@ CAC_OK
@ CAC_RECOVERY
@ CAC_NOTHOTSTANDBY
@ CAC_STARTUP
@ CAC_SHUTDOWN
@ LOG_CONNECTION_RECEIPT
#define STATUS_OK
Definition: c.h:1140
@ DestRemote
Definition: dest.h:89
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1158
int errdetail(const char *fmt,...)
Definition: elog.c:1204
int errhint(const char *fmt,...)
Definition: elog.c:1318
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define LOG
Definition: elog.h:31
#define FATAL
Definition: elog.h:41
#define WARNING
Definition: elog.h:36
#define elog(elevel,...)
Definition: elog.h:226
#define ereport(elevel,...)
Definition: elog.h:149
void ReserveExternalFD(void)
Definition: fd.c:1223
#define ERRCODE_CANNOT_CONNECT_NOW
Definition: fe-connect.c:94
ProtocolVersion FrontendProtocol
Definition: globals.c:30
struct Port * MyProcPort
Definition: globals.c:52
#define INJECTION_POINT(name)
#define IS_INJECTION_POINT_ATTACHED(name)
int pg_getnameinfo_all(const struct sockaddr_storage *addr, int salen, char *node, int nodelen, char *service, int servicelen, int flags)
Definition: ip.c:114
void check_on_shmem_exit_lists_are_empty(void)
Definition: ipc.c:432
void proc_exit(int code)
Definition: ipc.c:104
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition: mcxt.c:2312
void pfree(void *pointer)
Definition: mcxt.c:2150
MemoryContext TopMemoryContext
Definition: mcxt.c:165
@ B_WAL_SENDER
Definition: miscadmin.h:347
const char * GetBackendTypeDesc(BackendType backendType)
Definition: miscinit.c:263
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
static int port
Definition: pg_regress.c:115
#define pqsignal
Definition: port.h:531
CommandDest whereToSendOutput
Definition: postgres.c:91
int PreAuthDelay
Definition: postmaster.c:240
bool log_hostname
Definition: postmaster.c:243
bool ClientAuthInProgress
Definition: postmaster.c:372
int AuthenticationTimeout
Definition: postmaster.c:241
Port * pq_init(ClientSocket *client_sock)
Definition: pqcomm.c:174
#define PG_PROTOCOL(m, n)
Definition: pqcomm.h:90
#define PGPROC_MAX_CACHED_SUBXIDS
Definition: proc.h:39
void init_ps_display(const char *fixed_part)
Definition: ps_status.c:269
static void set_ps_display(const char *activity)
Definition: ps_status.h:40
void pg_usleep(long microsec)
Definition: signal.c:53
const char * gai_strerror(int ecode)
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:145
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:230
void initStringInfo(StringInfo str)
Definition: stringinfo.c:97
Definition: libpq-be.h:129
void enable_timeout_after(TimeoutId id, int delay_ms)
Definition: timeout.c:560
void InitializeTimeouts(void)
Definition: timeout.c:470
void disable_timeout(TimeoutId id, bool keep_indicator)
Definition: timeout.c:685
TimeoutId RegisterTimeout(TimeoutId id, timeout_handler_proc handler)
Definition: timeout.c:505
@ STARTUP_PACKET_TIMEOUT
Definition: timeout.h:26
bool am_walsender
Definition: walsender.c:120
bool EnableHotStandby
Definition: xlog.c:121
bool reachedConsistency
Definition: xlogrecovery.c:300

References am_walsender, appendStringInfo(), appendStringInfoString(), AuthenticationTimeout, B_WAL_SENDER, BlockSig, CAC_NOTHOTSTANDBY, CAC_OK, CAC_RECOVERY, CAC_SHUTDOWN, CAC_STARTUP, CAC_TOOMANY, check_on_shmem_exit_lists_are_empty(), ClientAuthInProgress, StringInfoData::data, DestRemote, disable_timeout(), elog, enable_timeout_after(), EnableHotStandby, ereport, errcode(), ERRCODE_CANNOT_CONNECT_NOW, errdetail(), errhint(), errmsg(), errmsg_internal(), FATAL, FrontendProtocol, gai_strerror(), GetBackendTypeDesc(), init_ps_display(), InitializeTimeouts(), initStringInfo(), INJECTION_POINT, IS_INJECTION_POINT_ATTACHED, LOG, LOG_CONNECTION_RECEIPT, log_connections, log_hostname, MemoryContextStrdup(), MemoryContextSwitchTo(), MyProcPort, pfree(), pg_getnameinfo_all(), PG_PROTOCOL, pg_usleep(), PGPROC_MAX_CACHED_SUBXIDS, port, pq_init(), pqsignal, PreAuthDelay, proc_exit(), process_startup_packet_die(), ProcessSSLStartup(), ProcessStartupPacket(), reachedConsistency, RegisterTimeout(), ReserveExternalFD(), set_ps_display(), STARTUP_PACKET_TIMEOUT, StartupBlockSig, StartupPacketTimeoutHandler(), STATUS_OK, TopMemoryContext, WARNING, and whereToSendOutput.

Referenced by BackendMain().

◆ BackendMain()

void BackendMain ( const void *  startup_data,
size_t  startup_data_len 
)

Definition at line 76 of file backend_startup.c.

77{
78 const BackendStartupData *bsdata = startup_data;
79
80 Assert(startup_data_len == sizeof(BackendStartupData));
81 Assert(MyClientSocket != NULL);
82
83#ifdef EXEC_BACKEND
84
85 /*
86 * Need to reinitialize the SSL library in the backend, since the context
87 * structures contain function pointers and cannot be passed through the
88 * parameter file.
89 *
90 * If for some reason reload fails (maybe the user installed broken key
91 * files), soldier on without SSL; that's better than all connections
92 * becoming impossible.
93 *
94 * XXX should we do this in all child processes? For the moment it's
95 * enough to do it in backend children.
96 */
97#ifdef USE_SSL
98 if (EnableSSL)
99 {
100 if (secure_initialize(false) == 0)
101 LoadedSSL = true;
102 else
103 ereport(LOG,
104 (errmsg("SSL configuration could not be loaded in child process")));
105 }
106#endif
107#endif
108
109 /* Perform additional initialization and collect startup packet */
111
112 /*
113 * Create a per-backend PGPROC struct in shared memory. We must do this
114 * before we can use LWLocks or access any shared memory.
115 */
116 InitProcess();
117
118 /*
119 * Make sure we aren't in PostmasterContext anymore. (We can't delete it
120 * just yet, though, because InitPostgres will need the HBA data.)
121 */
123
125}
static void BackendInitialize(ClientSocket *client_sock, CAC_state cac)
int secure_initialize(bool isServerStart)
Definition: be-secure.c:75
struct ClientSocket * MyClientSocket
Definition: globals.c:51
Assert(PointerIsAligned(start, uint64))
void PostgresMain(const char *dbname, const char *username)
Definition: postgres.c:4189
bool EnableSSL
Definition: postmaster.c:238
PGDLLIMPORT bool LoadedSSL
void InitProcess(void)
Definition: proc.c:391
CAC_state canAcceptConnections
char * user_name
Definition: libpq-be.h:151
char * database_name
Definition: libpq-be.h:150

References Assert(), BackendInitialize(), BackendStartupData::canAcceptConnections, Port::database_name, EnableSSL, ereport, errmsg(), InitProcess(), LoadedSSL, LOG, MemoryContextSwitchTo(), MyClientSocket, MyProcPort, PostgresMain(), secure_initialize(), TopMemoryContext, and Port::user_name.

◆ check_log_connections()

bool check_log_connections ( char **  newval,
void **  extra,
GucSource  source 
)

Definition at line 1068 of file backend_startup.c.

1069{
1070 uint32 flags;
1071 char *rawstring;
1072 List *elemlist;
1073 bool success;
1074
1075 /* Need a modifiable copy of string */
1076 rawstring = pstrdup(*newval);
1077
1078 if (!SplitIdentifierString(rawstring, ',', &elemlist))
1079 {
1080 GUC_check_errdetail("Invalid list syntax in parameter \"log_connections\".");
1081 pfree(rawstring);
1082 list_free(elemlist);
1083 return false;
1084 }
1085
1086 /* Validation logic is all in the helper */
1087 success = validate_log_connections_options(elemlist, &flags);
1088
1089 /* Time for cleanup */
1090 pfree(rawstring);
1091 list_free(elemlist);
1092
1093 if (!success)
1094 return false;
1095
1096 /*
1097 * We succeeded, so allocate `extra` and save the flags there for use by
1098 * assign_log_connections().
1099 */
1100 *extra = guc_malloc(LOG, sizeof(int));
1101 if (!*extra)
1102 return false;
1103 *((int *) *extra) = flags;
1104
1105 return true;
1106}
static bool validate_log_connections_options(List *elemlist, uint32 *flags)
uint32_t uint32
Definition: c.h:502
void * guc_malloc(int elevel, size_t size)
Definition: guc.c:638
#define newval
#define GUC_check_errdetail
Definition: guc.h:481
static bool success
Definition: initdb.c:187
void list_free(List *list)
Definition: list.c:1546
char * pstrdup(const char *in)
Definition: mcxt.c:2325
Definition: pg_list.h:54
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition: varlena.c:3525

References GUC_check_errdetail, guc_malloc(), list_free(), LOG, newval, pfree(), pstrdup(), SplitIdentifierString(), success, and validate_log_connections_options().

◆ process_startup_packet_die()

static void process_startup_packet_die ( SIGNAL_ARGS  )
static

Definition at line 947 of file backend_startup.c.

948{
949 _exit(1);
950}

Referenced by BackendInitialize().

◆ ProcessCancelRequestPacket()

static void ProcessCancelRequestPacket ( Port port,
void *  pkt,
int  pktlen 
)
static

Definition at line 875 of file backend_startup.c.

876{
878 int len;
879
880 if (pktlen < offsetof(CancelRequestPacket, cancelAuthCode))
881 {
883 (errcode(ERRCODE_PROTOCOL_VIOLATION),
884 errmsg("invalid length of query cancel packet")));
885 return;
886 }
887 len = pktlen - offsetof(CancelRequestPacket, cancelAuthCode);
888 if (len == 0 || len > 256)
889 {
891 (errcode(ERRCODE_PROTOCOL_VIOLATION),
892 errmsg("invalid length of query cancel key")));
893 return;
894 }
895
896 canc = (CancelRequestPacket *) pkt;
898}
#define COMMERROR
Definition: elog.h:33
#define pg_ntoh32(x)
Definition: pg_bswap.h:125
const void size_t len
void SendCancelRequest(int backendPID, char *cancel_key, int cancel_key_len)
Definition: procsignal.c:731
uint32 backendPID
Definition: pqcomm.h:143
char cancelAuthCode[FLEXIBLE_ARRAY_MEMBER]
Definition: pqcomm.h:144

References CancelRequestPacket::backendPID, CancelRequestPacket::cancelAuthCode, COMMERROR, ereport, errcode(), errmsg(), len, pg_ntoh32, and SendCancelRequest().

Referenced by ProcessStartupPacket().

◆ ProcessSSLStartup()

static int ProcessSSLStartup ( Port port)
static

Definition at line 401 of file backend_startup.c.

402{
403 int firstbyte;
404
405 Assert(!port->ssl_in_use);
406
408 firstbyte = pq_peekbyte();
410 if (firstbyte == EOF)
411 {
412 /*
413 * Like in ProcessStartupPacket, if we get no data at all, don't
414 * clutter the log with a complaint.
415 */
416 return STATUS_ERROR;
417 }
418
419 if (firstbyte != 0x16)
420 {
421 /* Not an SSL handshake message */
422 return STATUS_OK;
423 }
424
425 /*
426 * First byte indicates standard SSL handshake message
427 *
428 * (It can't be a Postgres startup length because in network byte order
429 * that would be a startup packet hundreds of megabytes long)
430 */
431
432#ifdef USE_SSL
433 if (!LoadedSSL || port->laddr.addr.ss_family == AF_UNIX)
434 {
435 /* SSL not supported */
436 goto reject;
437 }
438
439 if (secure_open_server(port) == -1)
440 {
441 /*
442 * we assume secure_open_server() sent an appropriate TLS alert
443 * already
444 */
445 goto reject;
446 }
447 Assert(port->ssl_in_use);
448
449 if (!port->alpn_used)
450 {
452 (errcode(ERRCODE_PROTOCOL_VIOLATION),
453 errmsg("received direct SSL connection request without ALPN protocol negotiation extension")));
454 goto reject;
455 }
456
458 ereport(LOG,
459 (errmsg("direct SSL connection accepted")));
460 return STATUS_OK;
461#else
462 /* SSL not supported by this build */
463 goto reject;
464#endif
465
466reject:
468 ereport(LOG,
469 (errmsg("direct SSL connection rejected")));
470 return STATUS_ERROR;
471}
bool Trace_connection_negotiation
int secure_open_server(Port *port)
Definition: be-secure.c:112
#define STATUS_ERROR
Definition: c.h:1141
int pq_peekbyte(void)
Definition: pqcomm.c:983
void pq_endmsgread(void)
Definition: pqcomm.c:1166
void pq_startmsgread(void)
Definition: pqcomm.c:1142

References Assert(), COMMERROR, ereport, errcode(), errmsg(), LoadedSSL, LOG, port, pq_endmsgread(), pq_peekbyte(), pq_startmsgread(), secure_open_server(), STATUS_ERROR, STATUS_OK, and Trace_connection_negotiation.

Referenced by BackendInitialize().

◆ ProcessStartupPacket()

static int ProcessStartupPacket ( Port port,
bool  ssl_done,
bool  gss_done 
)
static

Definition at line 492 of file backend_startup.c.

493{
494 int32 len;
495 char *buf;
496 ProtocolVersion proto;
497 MemoryContext oldcontext;
498
500
501 /*
502 * Grab the first byte of the length word separately, so that we can tell
503 * whether we have no data at all or an incomplete packet. (This might
504 * sound inefficient, but it's not really, because of buffering in
505 * pqcomm.c.)
506 */
507 if (pq_getbytes(&len, 1) == EOF)
508 {
509 /*
510 * If we get no data at all, don't clutter the log with a complaint;
511 * such cases often occur for legitimate reasons. An example is that
512 * we might be here after responding to NEGOTIATE_SSL_CODE, and if the
513 * client didn't like our response, it'll probably just drop the
514 * connection. Service-monitoring software also often just opens and
515 * closes a connection without sending anything. (So do port
516 * scanners, which may be less benign, but it's not really our job to
517 * notice those.)
518 */
519 return STATUS_ERROR;
520 }
521
522 if (pq_getbytes(((char *) &len) + 1, 3) == EOF)
523 {
524 /* Got a partial length word, so bleat about that */
525 if (!ssl_done && !gss_done)
527 (errcode(ERRCODE_PROTOCOL_VIOLATION),
528 errmsg("incomplete startup packet")));
529 return STATUS_ERROR;
530 }
531
532 len = pg_ntoh32(len);
533 len -= 4;
534
535 if (len < (int32) sizeof(ProtocolVersion) ||
537 {
539 (errcode(ERRCODE_PROTOCOL_VIOLATION),
540 errmsg("invalid length of startup packet")));
541 return STATUS_ERROR;
542 }
543
544 /*
545 * Allocate space to hold the startup packet, plus one extra byte that's
546 * initialized to be zero. This ensures we will have null termination of
547 * all strings inside the packet.
548 */
549 buf = palloc(len + 1);
550 buf[len] = '\0';
551
552 if (pq_getbytes(buf, len) == EOF)
553 {
555 (errcode(ERRCODE_PROTOCOL_VIOLATION),
556 errmsg("incomplete startup packet")));
557 return STATUS_ERROR;
558 }
560
561 /*
562 * The first field is either a protocol version number or a special
563 * request code.
564 */
565 port->proto = proto = pg_ntoh32(*((ProtocolVersion *) buf));
566
567 if (proto == CANCEL_REQUEST_CODE)
568 {
570 /* Not really an error, but we don't want to proceed further */
571 return STATUS_ERROR;
572 }
573
574 if (proto == NEGOTIATE_SSL_CODE && !ssl_done)
575 {
576 char SSLok;
577
578#ifdef USE_SSL
579
580 /*
581 * No SSL when disabled or on Unix sockets.
582 *
583 * Also no SSL negotiation if we already have a direct SSL connection
584 */
585 if (!LoadedSSL || port->laddr.addr.ss_family == AF_UNIX || port->ssl_in_use)
586 SSLok = 'N';
587 else
588 SSLok = 'S'; /* Support for SSL */
589#else
590 SSLok = 'N'; /* No support for SSL */
591#endif
592
594 {
595 if (SSLok == 'S')
596 ereport(LOG,
597 (errmsg("SSLRequest accepted")));
598 else
599 ereport(LOG,
600 (errmsg("SSLRequest rejected")));
601 }
602
603 while (secure_write(port, &SSLok, 1) != 1)
604 {
605 if (errno == EINTR)
606 continue; /* if interrupted, just retry */
609 errmsg("failed to send SSL negotiation response: %m")));
610 return STATUS_ERROR; /* close the connection */
611 }
612
613#ifdef USE_SSL
614 if (SSLok == 'S' && secure_open_server(port) == -1)
615 return STATUS_ERROR;
616#endif
617
618 /*
619 * At this point we should have no data already buffered. If we do,
620 * it was received before we performed the SSL handshake, so it wasn't
621 * encrypted and indeed may have been injected by a man-in-the-middle.
622 * We report this case to the client.
623 */
624 if (pq_buffer_remaining_data() > 0)
626 (errcode(ERRCODE_PROTOCOL_VIOLATION),
627 errmsg("received unencrypted data after SSL request"),
628 errdetail("This could be either a client-software bug or evidence of an attempted man-in-the-middle attack.")));
629
630 /*
631 * regular startup packet, cancel, etc packet should follow, but not
632 * another SSL negotiation request, and a GSS request should only
633 * follow if SSL was rejected (client may negotiate in either order)
634 */
635 return ProcessStartupPacket(port, true, SSLok == 'S');
636 }
637 else if (proto == NEGOTIATE_GSS_CODE && !gss_done)
638 {
639 char GSSok = 'N';
640
641#ifdef ENABLE_GSS
642 /* No GSSAPI encryption when on Unix socket */
643 if (port->laddr.addr.ss_family != AF_UNIX)
644 GSSok = 'G';
645#endif
646
648 {
649 if (GSSok == 'G')
650 ereport(LOG,
651 (errmsg("GSSENCRequest accepted")));
652 else
653 ereport(LOG,
654 (errmsg("GSSENCRequest rejected")));
655 }
656
657 while (secure_write(port, &GSSok, 1) != 1)
658 {
659 if (errno == EINTR)
660 continue;
663 errmsg("failed to send GSSAPI negotiation response: %m")));
664 return STATUS_ERROR; /* close the connection */
665 }
666
667#ifdef ENABLE_GSS
668 if (GSSok == 'G' && secure_open_gssapi(port) == -1)
669 return STATUS_ERROR;
670#endif
671
672 /*
673 * At this point we should have no data already buffered. If we do,
674 * it was received before we performed the GSS handshake, so it wasn't
675 * encrypted and indeed may have been injected by a man-in-the-middle.
676 * We report this case to the client.
677 */
678 if (pq_buffer_remaining_data() > 0)
680 (errcode(ERRCODE_PROTOCOL_VIOLATION),
681 errmsg("received unencrypted data after GSSAPI encryption request"),
682 errdetail("This could be either a client-software bug or evidence of an attempted man-in-the-middle attack.")));
683
684 /*
685 * regular startup packet, cancel, etc packet should follow, but not
686 * another GSS negotiation request, and an SSL request should only
687 * follow if GSS was rejected (client may negotiate in either order)
688 */
689 return ProcessStartupPacket(port, GSSok == 'G', true);
690 }
691
692 /* Could add additional special packet types here */
693
694 /*
695 * Set FrontendProtocol now so that ereport() knows what format to send if
696 * we fail during startup. We use the protocol version requested by the
697 * client unless it's higher than the latest version we support. It's
698 * possible that error message fields might look different in newer
699 * protocol versions, but that's something those new clients should be
700 * able to deal with.
701 */
703
704 /* Check that the major protocol version is in range. */
708 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
709 errmsg("unsupported frontend protocol %u.%u: server supports %u.0 to %u.%u",
714
715 /*
716 * Now fetch parameters out of startup packet and save them into the Port
717 * structure.
718 */
720
721 /* Handle protocol version 3 startup packet */
722 {
723 int32 offset = sizeof(ProtocolVersion);
724 List *unrecognized_protocol_options = NIL;
725
726 /*
727 * Scan packet body for name/option pairs. We can assume any string
728 * beginning within the packet body is null-terminated, thanks to
729 * zeroing extra byte above.
730 */
731 port->guc_options = NIL;
732
733 while (offset < len)
734 {
735 char *nameptr = buf + offset;
736 int32 valoffset;
737 char *valptr;
738
739 if (*nameptr == '\0')
740 break; /* found packet terminator */
741 valoffset = offset + strlen(nameptr) + 1;
742 if (valoffset >= len)
743 break; /* missing value, will complain below */
744 valptr = buf + valoffset;
745
746 if (strcmp(nameptr, "database") == 0)
747 port->database_name = pstrdup(valptr);
748 else if (strcmp(nameptr, "user") == 0)
749 port->user_name = pstrdup(valptr);
750 else if (strcmp(nameptr, "options") == 0)
751 port->cmdline_options = pstrdup(valptr);
752 else if (strcmp(nameptr, "replication") == 0)
753 {
754 /*
755 * Due to backward compatibility concerns the replication
756 * parameter is a hybrid beast which allows the value to be
757 * either boolean or the string 'database'. The latter
758 * connects to a specific database which is e.g. required for
759 * logical decoding while.
760 */
761 if (strcmp(valptr, "database") == 0)
762 {
763 am_walsender = true;
764 am_db_walsender = true;
765 }
766 else if (!parse_bool(valptr, &am_walsender))
768 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
769 errmsg("invalid value for parameter \"%s\": \"%s\"",
770 "replication",
771 valptr),
772 errhint("Valid values are: \"false\", 0, \"true\", 1, \"database\".")));
773 }
774 else if (strncmp(nameptr, "_pq_.", 5) == 0)
775 {
776 /*
777 * Any option beginning with _pq_. is reserved for use as a
778 * protocol-level option, but at present no such options are
779 * defined.
780 */
781 unrecognized_protocol_options =
782 lappend(unrecognized_protocol_options, pstrdup(nameptr));
783 }
784 else
785 {
786 /* Assume it's a generic GUC option */
787 port->guc_options = lappend(port->guc_options,
788 pstrdup(nameptr));
789 port->guc_options = lappend(port->guc_options,
790 pstrdup(valptr));
791
792 /*
793 * Copy application_name to port if we come across it. This
794 * is done so we can log the application_name in the
795 * connection authorization message. Note that the GUC would
796 * be used but we haven't gone through GUC setup yet.
797 */
798 if (strcmp(nameptr, "application_name") == 0)
799 {
800 port->application_name = pg_clean_ascii(valptr, 0);
801 }
802 }
803 offset = valoffset + strlen(valptr) + 1;
804 }
805
806 /*
807 * If we didn't find a packet terminator exactly at the end of the
808 * given packet length, complain.
809 */
810 if (offset != len - 1)
812 (errcode(ERRCODE_PROTOCOL_VIOLATION),
813 errmsg("invalid startup packet layout: expected terminator as last byte")));
814
815 /*
816 * If the client requested a newer protocol version or if the client
817 * requested any protocol options we didn't recognize, let them know
818 * the newest minor protocol version we do support and the names of
819 * any unrecognized options.
820 */
822 unrecognized_protocol_options != NIL)
823 SendNegotiateProtocolVersion(unrecognized_protocol_options);
824 }
825
826 /* Check a user name was given. */
827 if (port->user_name == NULL || port->user_name[0] == '\0')
829 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
830 errmsg("no PostgreSQL user name specified in startup packet")));
831
832 /* The database defaults to the user name. */
833 if (port->database_name == NULL || port->database_name[0] == '\0')
834 port->database_name = pstrdup(port->user_name);
835
836 /*
837 * Truncate given database and user names to length of a Postgres name.
838 * This avoids lookup failures when overlength names are given.
839 */
840 if (strlen(port->database_name) >= NAMEDATALEN)
841 port->database_name[NAMEDATALEN - 1] = '\0';
842 if (strlen(port->user_name) >= NAMEDATALEN)
843 port->user_name[NAMEDATALEN - 1] = '\0';
844
845 if (am_walsender)
847 else
849
850 /*
851 * Normal walsender backends, e.g. for streaming replication, are not
852 * connected to a particular database. But walsenders used for logical
853 * replication need to connect to a specific database. We allow streaming
854 * replication commands to be issued even if connected to a database as it
855 * can make sense to first make a basebackup and then stream changes
856 * starting from that.
857 */
859 port->database_name[0] = '\0';
860
861 /*
862 * Done filling the Port structure
863 */
864 MemoryContextSwitchTo(oldcontext);
865
866 return STATUS_OK;
867}
static void SendNegotiateProtocolVersion(List *unrecognized_protocol_options)
static void ProcessCancelRequestPacket(Port *port, void *pkt, int pktlen)
ssize_t secure_open_gssapi(Port *port)
ssize_t secure_write(Port *port, const void *ptr, size_t len)
Definition: be-secure.c:305
bool parse_bool(const char *value, bool *result)
Definition: bool.c:31
#define Min(x, y)
Definition: c.h:975
int32_t int32
Definition: c.h:498
int errcode_for_socket_access(void)
Definition: elog.c:954
List * lappend(List *list, void *datum)
Definition: list.c:339
void * palloc(Size size)
Definition: mcxt.c:1943
@ B_BACKEND
Definition: miscadmin.h:342
BackendType MyBackendType
Definition: miscinit.c:64
#define NAMEDATALEN
#define NIL
Definition: pg_list.h:68
static char * buf
Definition: pg_test_fsync.c:72
ssize_t pq_buffer_remaining_data(void)
Definition: pqcomm.c:1128
int pq_getbytes(void *b, size_t len)
Definition: pqcomm.c:1063
#define PG_PROTOCOL_MAJOR(v)
Definition: pqcomm.h:87
#define PG_PROTOCOL_EARLIEST
Definition: pqcomm.h:96
#define CANCEL_REQUEST_CODE
Definition: pqcomm.h:137
#define MAX_STARTUP_PACKET_LENGTH
Definition: pqcomm.h:118
#define PG_PROTOCOL_LATEST
Definition: pqcomm.h:97
#define NEGOTIATE_GSS_CODE
Definition: pqcomm.h:173
#define NEGOTIATE_SSL_CODE
Definition: pqcomm.h:172
uint32 ProtocolVersion
Definition: pqcomm.h:99
#define PG_PROTOCOL_MINOR(v)
Definition: pqcomm.h:88
char * pg_clean_ascii(const char *str, int alloc_flags)
Definition: string.c:85
bool am_db_walsender
Definition: walsender.c:123
#define EINTR
Definition: win32_port.h:364

References am_db_walsender, am_walsender, B_BACKEND, B_WAL_SENDER, buf, CANCEL_REQUEST_CODE, COMMERROR, EINTR, ereport, errcode(), errcode_for_socket_access(), errdetail(), errhint(), errmsg(), FATAL, FrontendProtocol, lappend(), len, LoadedSSL, LOG, MAX_STARTUP_PACKET_LENGTH, MemoryContextSwitchTo(), Min, MyBackendType, NAMEDATALEN, NEGOTIATE_GSS_CODE, NEGOTIATE_SSL_CODE, NIL, palloc(), parse_bool(), pg_clean_ascii(), pg_ntoh32, PG_PROTOCOL_EARLIEST, PG_PROTOCOL_LATEST, PG_PROTOCOL_MAJOR, PG_PROTOCOL_MINOR, port, pq_buffer_remaining_data(), pq_endmsgread(), pq_getbytes(), pq_startmsgread(), ProcessCancelRequestPacket(), ProcessStartupPacket(), pstrdup(), secure_open_gssapi(), secure_open_server(), secure_write(), SendNegotiateProtocolVersion(), STATUS_ERROR, STATUS_OK, TopMemoryContext, and Trace_connection_negotiation.

Referenced by BackendInitialize(), and ProcessStartupPacket().

◆ SendNegotiateProtocolVersion()

static void SendNegotiateProtocolVersion ( List unrecognized_protocol_options)
static

Definition at line 917 of file backend_startup.c.

918{
920 ListCell *lc;
921
924 pq_sendint32(&buf, list_length(unrecognized_protocol_options));
925 foreach(lc, unrecognized_protocol_options)
926 pq_sendstring(&buf, lfirst(lc));
928
929 /* no need to flush, some other message will follow */
930}
#define lfirst(lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:152
void pq_sendstring(StringInfo buf, const char *str)
Definition: pqformat.c:195
void pq_endmessage(StringInfo buf)
Definition: pqformat.c:296
void pq_beginmessage(StringInfo buf, char msgtype)
Definition: pqformat.c:88
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:144
#define PqMsg_NegotiateProtocolVersion
Definition: protocol.h:59

References buf, FrontendProtocol, lfirst, list_length(), pq_beginmessage(), pq_endmessage(), pq_sendint32(), pq_sendstring(), and PqMsg_NegotiateProtocolVersion.

Referenced by ProcessStartupPacket().

◆ StartupPacketTimeoutHandler()

static void StartupPacketTimeoutHandler ( void  )
static

Definition at line 957 of file backend_startup.c.

958{
959 _exit(1);
960}

Referenced by BackendInitialize().

◆ validate_log_connections_options()

static bool validate_log_connections_options ( List elemlist,
uint32 flags 
)
static

Definition at line 976 of file backend_startup.c.

977{
978 ListCell *l;
979 char *item;
980
981 /*
982 * For backwards compatibility, we accept these tokens by themselves.
983 *
984 * Prior to PostgreSQL 18, log_connections was a boolean GUC that accepted
985 * any unambiguous substring of 'true', 'false', 'yes', 'no', 'on', and
986 * 'off'. Since log_connections became a list of strings in 18, we only
987 * accept complete option strings.
988 */
989 static const struct config_enum_entry compat_options[] = {
990 {"off", 0},
991 {"false", 0},
992 {"no", 0},
993 {"0", 0},
994 {"on", LOG_CONNECTION_ON},
995 {"true", LOG_CONNECTION_ON},
996 {"yes", LOG_CONNECTION_ON},
997 {"1", LOG_CONNECTION_ON},
998 };
999
1000 *flags = 0;
1001
1002 /* If an empty string was passed, we're done */
1003 if (list_length(elemlist) == 0)
1004 return true;
1005
1006 /*
1007 * Now check for the backwards compatibility options. They must always be
1008 * specified on their own, so we error out if the first option is a
1009 * backwards compatibility option and other options are also specified.
1010 */
1011 item = linitial(elemlist);
1012
1013 for (size_t i = 0; i < lengthof(compat_options); i++)
1014 {
1015 struct config_enum_entry option = compat_options[i];
1016
1017 if (pg_strcasecmp(item, option.name) != 0)
1018 continue;
1019
1020 if (list_length(elemlist) > 1)
1021 {
1022 GUC_check_errdetail("Cannot specify log_connections option \"%s\" in a list with other options.",
1023 item);
1024 return false;
1025 }
1026
1027 *flags = option.val;
1028 return true;
1029 }
1030
1031 /* Now check the aspect options. The empty string was already handled */
1032 foreach(l, elemlist)
1033 {
1034 static const struct config_enum_entry options[] = {
1035 {"receipt", LOG_CONNECTION_RECEIPT},
1036 {"authentication", LOG_CONNECTION_AUTHENTICATION},
1037 {"authorization", LOG_CONNECTION_AUTHORIZATION},
1038 {"setup_durations", LOG_CONNECTION_SETUP_DURATIONS},
1039 {"all", LOG_CONNECTION_ALL},
1040 };
1041
1042 item = lfirst(l);
1043 for (size_t i = 0; i < lengthof(options); i++)
1044 {
1046
1047 if (pg_strcasecmp(item, option.name) == 0)
1048 {
1049 *flags |= option.val;
1050 goto next;
1051 }
1052 }
1053
1054 GUC_check_errdetail("Invalid option \"%s\".", item);
1055 return false;
1056
1057next: ;
1058 }
1059
1060 return true;
1061}
@ LOG_CONNECTION_AUTHORIZATION
@ LOG_CONNECTION_ON
@ LOG_CONNECTION_SETUP_DURATIONS
@ LOG_CONNECTION_ALL
@ LOG_CONNECTION_AUTHENTICATION
static int32 next
Definition: blutils.c:224
#define lengthof(array)
Definition: c.h:759
int i
Definition: isn.c:77
#define linitial(l)
Definition: pg_list.h:178
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
Definition: guc.h:174
int val
Definition: getopt_long.h:22
const char * name
Definition: getopt_long.h:19

References GUC_check_errdetail, i, lengthof, lfirst, linitial, list_length(), LOG_CONNECTION_ALL, LOG_CONNECTION_AUTHENTICATION, LOG_CONNECTION_AUTHORIZATION, LOG_CONNECTION_ON, LOG_CONNECTION_RECEIPT, LOG_CONNECTION_SETUP_DURATIONS, option::name, next, pg_strcasecmp(), and option::val.

Referenced by check_log_connections().

Variable Documentation

◆ conn_timing

ConnectionTiming conn_timing = {.ready_for_use = TIMESTAMP_MINUS_INFINITY}

Definition at line 58 of file backend_startup.c.

Referenced by PerformAuthentication(), PostgresMain(), and postmaster_child_launch().

◆ log_connections

◆ log_connections_string

char* log_connections_string = NULL

Definition at line 48 of file backend_startup.c.

◆ Trace_connection_negotiation

bool Trace_connection_negotiation = false

Definition at line 46 of file backend_startup.c.

Referenced by ProcessSSLStartup(), and ProcessStartupPacket().