PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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)
 
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
 
charlog_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 1154 of file backend_startup.c.

1155{
1156 log_connections = *((int *) extra);
1157}
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];
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 */
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 */
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),
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", NULL);
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);
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:
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 */
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 */
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
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)
@ CAC_TOOMANY
@ CAC_OK
@ CAC_RECOVERY
@ CAC_NOTHOTSTANDBY
@ CAC_STARTUP
@ CAC_SHUTDOWN
@ LOG_CONNECTION_RECEIPT
#define STATUS_OK
Definition c.h:1258
@ DestRemote
Definition dest.h:89
int errcode(int sqlerrcode)
Definition elog.c:875
#define LOG
Definition elog.h:32
int errhint(const char *fmt,...) pg_attribute_printf(1
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define FATAL
Definition elog.h:42
int int errmsg_internal(const char *fmt,...) pg_attribute_printf(1
#define WARNING
Definition elog.h:37
#define elog(elevel,...)
Definition elog.h:228
#define ereport(elevel,...)
Definition elog.h:152
void ReserveExternalFD(void)
Definition fd.c:1207
#define ERRCODE_CANNOT_CONNECT_NOW
Definition fe-connect.c:95
ProtocolVersion FrontendProtocol
Definition globals.c:30
struct Port * MyProcPort
Definition globals.c:53
#define INJECTION_POINT(name, arg)
#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:117
void check_on_shmem_exit_lists_are_empty(void)
Definition ipc.c:439
void proc_exit(int code)
Definition ipc.c:105
char * MemoryContextStrdup(MemoryContext context, const char *string)
Definition mcxt.c:1897
void pfree(void *pointer)
Definition mcxt.c:1619
MemoryContext TopMemoryContext
Definition mcxt.c:167
@ B_WAL_SENDER
Definition miscadmin.h:359
const char * GetBackendTypeDesc(BackendType backendType)
Definition miscinit.c:264
static char * errmsg
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition palloc.h:138
static int port
Definition pg_regress.c:117
#define pqsignal
Definition port.h:548
CommandDest whereToSendOutput
Definition postgres.c:97
int PreAuthDelay
Definition postmaster.c:241
bool log_hostname
Definition postmaster.c:244
bool ClientAuthInProgress
Definition postmaster.c:374
int AuthenticationTimeout
Definition postmaster.c:242
Port * pq_init(ClientSocket *client_sock)
Definition pqcomm.c:175
#define PG_PROTOCOL(m, n)
Definition pqcomm.h:89
static int fb(int x)
#define PGPROC_MAX_CACHED_SUBXIDS
Definition proc.h:43
void init_ps_display(const char *fixed_part)
Definition ps_status.c:286
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 errcode)
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
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:135
bool EnableHotStandby
Definition xlog.c:128
bool reachedConsistency

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, DestRemote, disable_timeout(), elog, enable_timeout_after(), EnableHotStandby, ereport, errcode(), ERRCODE_CANNOT_CONNECT_NOW, errdetail(), errhint(), errmsg, errmsg_internal(), FATAL, fb(), 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{
79
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 */
110 BackendInitialize(MyClientSocket, bsdata->canAcceptConnections);
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:79
#define Assert(condition)
Definition c.h:943
struct ClientSocket * MyClientSocket
Definition globals.c:52
void PostgresMain(const char *dbname, const char *username)
Definition postgres.c:4274
bool EnableSSL
Definition postmaster.c:239
PGDLLIMPORT bool LoadedSSL
void InitProcess(void)
Definition proc.c:392
char * user_name
Definition libpq-be.h:151
char * database_name
Definition libpq-be.h:150

References Assert, BackendInitialize(), Port::database_name, EnableSSL, ereport, errmsg, fb(), 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 1110 of file backend_startup.c.

1111{
1112 uint32 flags;
1113 char *rawstring;
1114 List *elemlist;
1115 bool success;
1116
1117 /* Need a modifiable copy of string */
1119
1121 {
1122 GUC_check_errdetail("Invalid list syntax in parameter \"%s\".", "log_connections");
1125 return false;
1126 }
1127
1128 /* Validation logic is all in the helper */
1130
1131 /* Time for cleanup */
1134
1135 if (!success)
1136 return false;
1137
1138 /*
1139 * We succeeded, so allocate `extra` and save the flags there for use by
1140 * assign_log_connections().
1141 */
1142 *extra = guc_malloc(LOG, sizeof(int));
1143 if (!*extra)
1144 return false;
1145 *((int *) *extra) = flags;
1146
1147 return true;
1148}
static bool validate_log_connections_options(List *elemlist, uint32 *flags)
uint32_t uint32
Definition c.h:624
void * guc_malloc(int elevel, size_t size)
Definition guc.c:637
#define newval
#define GUC_check_errdetail
Definition guc.h:507
static bool success
Definition initdb.c:188
void list_free(List *list)
Definition list.c:1546
char * pstrdup(const char *in)
Definition mcxt.c:1910
Definition pg_list.h:54
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
Definition varlena.c:2870

References fb(), 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 989 of file backend_startup.c.

990{
991 _exit(1);
992}

References fb().

Referenced by BackendInitialize().

◆ ProcessCancelRequestPacket()

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

Definition at line 917 of file backend_startup.c.

918{
920 int len;
921
922 if (pktlen < offsetof(CancelRequestPacket, cancelAuthCode))
923 {
926 errmsg("invalid length of cancel request packet")));
927 return;
928 }
929 len = pktlen - offsetof(CancelRequestPacket, cancelAuthCode);
930 if (len == 0 || len > 256)
931 {
934 errmsg("invalid length of cancel key in cancel request packet")));
935 return;
936 }
937
939 SendCancelRequest(pg_ntoh32(canc->backendPID), canc->cancelAuthCode, len);
940}
#define COMMERROR
Definition elog.h:34
#define ERRCODE_PROTOCOL_VIOLATION
Definition fe-connect.c:96
#define pg_ntoh32(x)
Definition pg_bswap.h:125
const void size_t len
void SendCancelRequest(int backendPID, const uint8 *cancel_key, int cancel_key_len)
Definition procsignal.c:731

References COMMERROR, ereport, errcode(), ERRCODE_PROTOCOL_VIOLATION, errmsg, fb(), 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
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 {
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:116
#define STATUS_ERROR
Definition c.h:1259
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(), ERRCODE_PROTOCOL_VIOLATION, errmsg, fb(), 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)
static

Definition at line 486 of file backend_startup.c.

487{
488 int32 len;
489 char *buf = NULL;
490 ProtocolVersion proto;
491 MemoryContext oldcontext;
492 bool gss_done;
493 bool ssl_done;
494
495 /*
496 * Set ssl_done and/or gss_done when negotiation of an encrypted layer
497 * (currently, TLS or GSSAPI) is completed. A successful negotiation of
498 * either encryption layer sets both flags, but a rejected negotiation
499 * sets only the flag for that layer, since the client may wish to try the
500 * other one. We should make no assumption here about the order in which
501 * the client may make requests.
502 */
503 gss_done = false;
504 ssl_done = false;
505
506retry:
508
509 /*
510 * Grab the first byte of the length word separately, so that we can tell
511 * whether we have no data at all or an incomplete packet. (This might
512 * sound inefficient, but it's not really, because of buffering in
513 * pqcomm.c.)
514 */
515 if (pq_getbytes(&len, 1) == EOF)
516 {
517 /*
518 * If we get no data at all, don't clutter the log with a complaint;
519 * such cases often occur for legitimate reasons. An example is that
520 * we might be here after responding to NEGOTIATE_SSL_CODE, and if the
521 * client didn't like our response, it'll probably just drop the
522 * connection. Service-monitoring software also often just opens and
523 * closes a connection without sending anything. (So do port
524 * scanners, which may be less benign, but it's not really our job to
525 * notice those.)
526 */
527 goto fail;
528 }
529
530 if (pq_getbytes(((char *) &len) + 1, 3) == EOF)
531 {
532 /* Got a partial length word, so bleat about that */
533 if (!ssl_done && !gss_done)
536 errmsg("incomplete startup packet")));
537 goto fail;
538 }
539
540 len = pg_ntoh32(len);
541 len -= 4;
542
543 if (len < (int32) sizeof(ProtocolVersion) ||
545 {
548 errmsg("invalid length of startup packet")));
549 goto fail;
550 }
551
552 /*
553 * Allocate space to hold the startup packet, plus one extra byte that's
554 * initialized to be zero. This ensures we will have null termination of
555 * all strings inside the packet.
556 */
557 buf = palloc(len + 1);
558 buf[len] = '\0';
559
560 if (pq_getbytes(buf, len) == EOF)
561 {
564 errmsg("incomplete startup packet")));
565 goto fail;
566 }
568
569 /*
570 * The first field is either a protocol version number or a special
571 * request code.
572 */
573 port->proto = proto = pg_ntoh32(*((ProtocolVersion *) buf));
574
575 if (proto == CANCEL_REQUEST_CODE)
576 {
578 /* Not really an error, but we don't want to proceed further */
579 goto fail;
580 }
581
582 if (proto == NEGOTIATE_SSL_CODE && !ssl_done)
583 {
584 char SSLok;
585
586#ifdef USE_SSL
587
588 /*
589 * No SSL when disabled or on Unix sockets.
590 *
591 * Also no SSL negotiation if we already have a direct SSL connection
592 */
593 if (!LoadedSSL || port->laddr.addr.ss_family == AF_UNIX || port->ssl_in_use)
594 SSLok = 'N';
595 else
596 SSLok = 'S'; /* Support for SSL */
597#else
598 SSLok = 'N'; /* No support for SSL */
599#endif
600
602 {
603 if (SSLok == 'S')
604 ereport(LOG,
605 (errmsg("SSLRequest accepted")));
606 else
607 ereport(LOG,
608 (errmsg("SSLRequest rejected")));
609 }
610
611 while (secure_write(port, &SSLok, 1) != 1)
612 {
613 if (errno == EINTR)
614 continue; /* if interrupted, just retry */
617 errmsg("failed to send SSL negotiation response: %m")));
618 goto fail; /* close the connection */
619 }
620
621#ifdef USE_SSL
622 if (SSLok == 'S' && secure_open_server(port) == -1)
623 goto fail;
624#endif
625
626 pfree(buf);
627 buf = NULL;
628
629 /*
630 * At this point we should have no data already buffered. If we do,
631 * it was received before we performed the SSL handshake, so it wasn't
632 * encrypted and indeed may have been injected by a man-in-the-middle.
633 * We report this case to the client.
634 */
635 if (pq_buffer_remaining_data() > 0)
638 errmsg("received unencrypted data after SSL request"),
639 errdetail("This could be either a client-software bug or evidence of an attempted man-in-the-middle attack.")));
640
641 /*
642 * regular startup packet, cancel, etc packet should follow, but not
643 * another SSL negotiation request, and a GSS request should only
644 * follow if SSL was rejected (client may negotiate in either order)
645 */
646 ssl_done = true;
647 if (SSLok == 'S')
648 {
649 /*
650 * We are done with SSL and negotiated correctly, so consider the
651 * same for GSS.
652 */
653 gss_done = true;
654 }
655 goto retry;
656 }
657 else if (proto == NEGOTIATE_GSS_CODE && !gss_done)
658 {
659 char GSSok = 'N';
660
661#ifdef ENABLE_GSS
662 /* No GSSAPI encryption when on Unix socket */
663 if (port->laddr.addr.ss_family != AF_UNIX)
664 GSSok = 'G';
665#endif
666
668 {
669 if (GSSok == 'G')
670 ereport(LOG,
671 (errmsg("GSSENCRequest accepted")));
672 else
673 ereport(LOG,
674 (errmsg("GSSENCRequest rejected")));
675 }
676
677 while (secure_write(port, &GSSok, 1) != 1)
678 {
679 if (errno == EINTR)
680 continue;
683 errmsg("failed to send GSSAPI negotiation response: %m")));
684 goto fail; /* close the connection */
685 }
686
687#ifdef ENABLE_GSS
688 if (GSSok == 'G' && secure_open_gssapi(port) == -1)
689 goto fail;
690#endif
691
692 pfree(buf);
693 buf = NULL;
694
695 /*
696 * At this point we should have no data already buffered. If we do,
697 * it was received before we performed the GSS handshake, so it wasn't
698 * encrypted and indeed may have been injected by a man-in-the-middle.
699 * We report this case to the client.
700 */
701 if (pq_buffer_remaining_data() > 0)
704 errmsg("received unencrypted data after GSSAPI encryption request"),
705 errdetail("This could be either a client-software bug or evidence of an attempted man-in-the-middle attack.")));
706
707 /*
708 * regular startup packet, cancel, etc packet should follow, but not
709 * another GSS negotiation request, and an SSL request should only
710 * follow if GSS was rejected (client may negotiate in either order)
711 */
712 gss_done = true;
713 if (GSSok == 'G')
714 {
715 /*
716 * We are done with GSS and negotiated correctly, so consider the
717 * same for SSL.
718 */
719 ssl_done = true;
720 }
721 goto retry;
722 }
723
724 /* Could add additional special packet types here */
725
726 /*
727 * Set FrontendProtocol now so that ereport() knows what format to send if
728 * we fail during startup. We use the protocol version requested by the
729 * client unless it's higher than the latest version we support. It's
730 * possible that error message fields might look different in newer
731 * protocol versions, but that's something those new clients should be
732 * able to deal with.
733 */
735
736 /* Check that the major protocol version is in range. */
741 errmsg("unsupported frontend protocol %u.%u: server supports %u.0 to %u.%u",
746
747 /*
748 * Now fetch parameters out of startup packet and save them into the Port
749 * structure.
750 */
752
753 /* Handle protocol version 3 startup packet */
754 {
755 int32 offset = sizeof(ProtocolVersion);
757
758 /*
759 * Scan packet body for name/option pairs. We can assume any string
760 * beginning within the packet body is null-terminated, thanks to
761 * zeroing extra byte above.
762 */
763 port->guc_options = NIL;
764
765 while (offset < len)
766 {
767 char *nameptr = buf + offset;
769 char *valptr;
770
771 if (*nameptr == '\0')
772 break; /* found packet terminator */
773 valoffset = offset + strlen(nameptr) + 1;
774 if (valoffset >= len)
775 break; /* missing value, will complain below */
776 valptr = buf + valoffset;
777
778 if (strcmp(nameptr, "database") == 0)
779 port->database_name = pstrdup(valptr);
780 else if (strcmp(nameptr, "user") == 0)
781 port->user_name = pstrdup(valptr);
782 else if (strcmp(nameptr, "options") == 0)
783 port->cmdline_options = pstrdup(valptr);
784 else if (strcmp(nameptr, "replication") == 0)
785 {
786 /*
787 * Due to backward compatibility concerns the replication
788 * parameter is a hybrid beast which allows the value to be
789 * either boolean or the string 'database'. The latter
790 * connects to a specific database which is e.g. required for
791 * logical decoding while.
792 */
793 if (strcmp(valptr, "database") == 0)
794 {
795 am_walsender = true;
796 am_db_walsender = true;
797 }
798 else if (!parse_bool(valptr, &am_walsender))
801 errmsg("invalid value for parameter \"%s\": \"%s\"",
802 "replication",
803 valptr),
804 errhint("Valid values are: \"false\", 0, \"true\", 1, \"database\".")));
805 }
806 else if (strncmp(nameptr, "_pq_.", 5) == 0)
807 {
808 /*
809 * Any option beginning with _pq_. is reserved for use as a
810 * protocol-level option, but at present no such options are
811 * defined.
812 */
815 }
816 else
817 {
818 /* Assume it's a generic GUC option */
819 port->guc_options = lappend(port->guc_options,
821 port->guc_options = lappend(port->guc_options,
822 pstrdup(valptr));
823
824 /*
825 * Copy application_name to port if we come across it. This
826 * is done so we can log the application_name in the
827 * connection authorization message. Note that the GUC would
828 * be used but we haven't gone through GUC setup yet.
829 */
830 if (strcmp(nameptr, "application_name") == 0)
831 {
832 port->application_name = pg_clean_ascii(valptr, 0);
833 }
834 }
835 offset = valoffset + strlen(valptr) + 1;
836 }
837
838 /*
839 * If we didn't find a packet terminator exactly at the end of the
840 * given packet length, complain.
841 */
842 if (offset != len - 1)
845 errmsg("invalid startup packet layout: expected terminator as last byte")));
846
847 /*
848 * If the client requested a newer protocol version or if the client
849 * requested any protocol options we didn't recognize, let them know
850 * the newest minor protocol version we do support and the names of
851 * any unrecognized options.
852 */
856
858 }
859
860 /* Check a user name was given. */
861 if (port->user_name == NULL || port->user_name[0] == '\0')
864 errmsg("no PostgreSQL user name specified in startup packet")));
865
866 /* The database defaults to the user name. */
867 if (port->database_name == NULL || port->database_name[0] == '\0')
868 port->database_name = pstrdup(port->user_name);
869
870 /*
871 * Truncate given database and user names to length of a Postgres name.
872 * This avoids lookup failures when overlength names are given.
873 */
874 if (strlen(port->database_name) >= NAMEDATALEN)
875 port->database_name[NAMEDATALEN - 1] = '\0';
876 if (strlen(port->user_name) >= NAMEDATALEN)
877 port->user_name[NAMEDATALEN - 1] = '\0';
878
880 if (am_walsender)
882
883 /*
884 * Normal walsender backends, e.g. for streaming replication, are not
885 * connected to a particular database. But walsenders used for logical
886 * replication need to connect to a specific database. We allow streaming
887 * replication commands to be issued even if connected to a database as it
888 * can make sense to first make a basebackup and then stream changes
889 * starting from that.
890 */
892 port->database_name[0] = '\0';
893
894 /*
895 * Done filling the Port structure
896 */
897 MemoryContextSwitchTo(oldcontext);
898
899 pfree(buf);
900
901 return STATUS_OK;
902
903fail:
904 /* be tidy, just to avoid Valgrind complaints */
905 if (buf)
906 pfree(buf);
907
908 return STATUS_ERROR;
909}
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:309
bool parse_bool(const char *value, bool *result)
Definition bool.c:31
#define Min(x, y)
Definition c.h:1091
int32_t int32
Definition c.h:620
int errcode_for_socket_access(void)
Definition elog.c:977
List * lappend(List *list, void *datum)
Definition list.c:339
void list_free_deep(List *list)
Definition list.c:1560
void * palloc(Size size)
Definition mcxt.c:1390
@ B_BACKEND
Definition miscadmin.h:354
@ B_DEAD_END_BACKEND
Definition miscadmin.h:355
BackendType MyBackendType
Definition miscinit.c:65
#define NAMEDATALEN
#define NIL
Definition pg_list.h:68
static char buf[DEFAULT_XLOG_SEG_SIZE]
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:86
#define PG_PROTOCOL_EARLIEST
Definition pqcomm.h:94
#define CANCEL_REQUEST_CODE
Definition pqcomm.h:122
#define MAX_STARTUP_PACKET_LENGTH
Definition pqcomm.h:148
#define PG_PROTOCOL_LATEST
Definition pqcomm.h:95
#define NEGOTIATE_GSS_CODE
Definition pqcomm.h:129
#define NEGOTIATE_SSL_CODE
Definition pqcomm.h:128
uint32 ProtocolVersion
Definition pqcomm.h:132
#define PG_PROTOCOL_MINOR(v)
Definition pqcomm.h:87
char * pg_clean_ascii(const char *str, int alloc_flags)
Definition string.c:85
bool am_db_walsender
Definition walsender.c:138
#define EINTR
Definition win32_port.h:361

References am_db_walsender, am_walsender, Assert, B_BACKEND, B_DEAD_END_BACKEND, B_WAL_SENDER, buf, CANCEL_REQUEST_CODE, COMMERROR, EINTR, ereport, errcode(), errcode_for_socket_access(), ERRCODE_PROTOCOL_VIOLATION, errdetail(), errhint(), errmsg, FATAL, fb(), FrontendProtocol, lappend(), len, list_free_deep(), LoadedSSL, LOG, MAX_STARTUP_PACKET_LENGTH, MemoryContextSwitchTo(), Min, MyBackendType, NAMEDATALEN, NEGOTIATE_GSS_CODE, NEGOTIATE_SSL_CODE, NIL, palloc(), parse_bool(), pfree(), 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(), pstrdup(), secure_open_gssapi(), secure_open_server(), secure_write(), SendNegotiateProtocolVersion(), STATUS_ERROR, STATUS_OK, TopMemoryContext, and Trace_connection_negotiation.

Referenced by BackendInitialize().

◆ SendNegotiateProtocolVersion()

static void SendNegotiateProtocolVersion ( List unrecognized_protocol_options)
static

Definition at line 959 of file backend_startup.c.

960{
962 ListCell *lc;
963
970
971 /* no need to flush, some other message will follow */
972}
#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, fb(), 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 999 of file backend_startup.c.

1000{
1001 _exit(1);
1002}

References fb().

Referenced by BackendInitialize().

◆ validate_log_connections_options()

static bool validate_log_connections_options ( List elemlist,
uint32 flags 
)
static

Definition at line 1018 of file backend_startup.c.

1019{
1020 ListCell *l;
1021 char *item;
1022
1023 /*
1024 * For backwards compatibility, we accept these tokens by themselves.
1025 *
1026 * Prior to PostgreSQL 18, log_connections was a boolean GUC that accepted
1027 * any unambiguous substring of 'true', 'false', 'yes', 'no', 'on', and
1028 * 'off'. Since log_connections became a list of strings in 18, we only
1029 * accept complete option strings.
1030 */
1031 static const struct config_enum_entry compat_options[] = {
1032 {"off", 0},
1033 {"false", 0},
1034 {"no", 0},
1035 {"0", 0},
1036 {"on", LOG_CONNECTION_ON},
1037 {"true", LOG_CONNECTION_ON},
1038 {"yes", LOG_CONNECTION_ON},
1039 {"1", LOG_CONNECTION_ON},
1040 };
1041
1042 *flags = 0;
1043
1044 /* If an empty string was passed, we're done */
1045 if (list_length(elemlist) == 0)
1046 return true;
1047
1048 /*
1049 * Now check for the backwards compatibility options. They must always be
1050 * specified on their own, so we error out if the first option is a
1051 * backwards compatibility option and other options are also specified.
1052 */
1053 item = linitial(elemlist);
1054
1055 for (size_t i = 0; i < lengthof(compat_options); i++)
1056 {
1058
1059 if (pg_strcasecmp(item, option.name) != 0)
1060 continue;
1061
1062 if (list_length(elemlist) > 1)
1063 {
1064 GUC_check_errdetail("Cannot specify log_connections option \"%s\" in a list with other options.",
1065 item);
1066 return false;
1067 }
1068
1069 *flags = option.val;
1070 return true;
1071 }
1072
1073 /* Now check the aspect options. The empty string was already handled */
1074 foreach(l, elemlist)
1075 {
1076 static const struct config_enum_entry options[] = {
1077 {"receipt", LOG_CONNECTION_RECEIPT},
1078 {"authentication", LOG_CONNECTION_AUTHENTICATION},
1079 {"authorization", LOG_CONNECTION_AUTHORIZATION},
1080 {"setup_durations", LOG_CONNECTION_SETUP_DURATIONS},
1081 {"all", LOG_CONNECTION_ALL},
1082 };
1083
1084 item = lfirst(l);
1085 for (size_t i = 0; i < lengthof(options); i++)
1086 {
1088
1089 if (pg_strcasecmp(item, option.name) == 0)
1090 {
1091 *flags |= option.val;
1092 goto next;
1093 }
1094 }
1095
1096 GUC_check_errdetail("Invalid option \"%s\".", item);
1097 return false;
1098
1099next: ;
1100 }
1101
1102 return true;
1103}
@ LOG_CONNECTION_AUTHORIZATION
@ LOG_CONNECTION_ON
@ LOG_CONNECTION_SETUP_DURATIONS
@ LOG_CONNECTION_ALL
@ LOG_CONNECTION_AUTHENTICATION
static int32 next
Definition blutils.c:225
#define lengthof(array)
Definition c.h:873
int i
Definition isn.c:77
#define linitial(l)
Definition pg_list.h:178
int pg_strcasecmp(const char *s1, const char *s2)
Definition guc.h:174
int val
Definition getopt_long.h:22
const char * name
Definition getopt_long.h:19

References fb(), 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.

58{.ready_for_use = TIMESTAMP_MINUS_INFINITY};
#define TIMESTAMP_MINUS_INFINITY
Definition timestamp.h:150

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