Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * backend_startup.c
4 : * Backend startup code
5 : *
6 : * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 : * Portions Copyright (c) 1994, Regents of the University of California
8 : *
9 : *
10 : * IDENTIFICATION
11 : * src/backend/tcop/backend_startup.c
12 : *
13 : *-------------------------------------------------------------------------
14 : */
15 :
16 : #include "postgres.h"
17 :
18 : #include <unistd.h>
19 :
20 : #include "access/xlog.h"
21 : #include "common/ip.h"
22 : #include "common/string.h"
23 : #include "libpq/libpq.h"
24 : #include "libpq/libpq-be.h"
25 : #include "libpq/pqformat.h"
26 : #include "libpq/pqsignal.h"
27 : #include "miscadmin.h"
28 : #include "postmaster/postmaster.h"
29 : #include "replication/walsender.h"
30 : #include "storage/fd.h"
31 : #include "storage/ipc.h"
32 : #include "storage/procsignal.h"
33 : #include "storage/proc.h"
34 : #include "tcop/backend_startup.h"
35 : #include "tcop/tcopprot.h"
36 : #include "utils/builtins.h"
37 : #include "utils/guc_hooks.h"
38 : #include "utils/injection_point.h"
39 : #include "utils/memutils.h"
40 : #include "utils/ps_status.h"
41 : #include "utils/timeout.h"
42 : #include "utils/varlena.h"
43 :
44 : /* GUCs */
45 : bool Trace_connection_negotiation = false;
46 : uint32 log_connections = 0;
47 : char *log_connections_string = NULL;
48 :
49 : /* Other globals */
50 :
51 : /*
52 : * ConnectionTiming stores timestamps of various points in connection
53 : * establishment and setup.
54 : * ready_for_use is initialized to a special value here so we can check if
55 : * we've already set it before doing so in PostgresMain().
56 : */
57 : ConnectionTiming conn_timing = {.ready_for_use = TIMESTAMP_MINUS_INFINITY};
58 :
59 : static void BackendInitialize(ClientSocket *client_sock, CAC_state cac);
60 : static int ProcessSSLStartup(Port *port);
61 : static int ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done);
62 : static void SendNegotiateProtocolVersion(List *unrecognized_protocol_options);
63 : static void process_startup_packet_die(SIGNAL_ARGS);
64 : static void StartupPacketTimeoutHandler(void);
65 : static bool validate_log_connections_options(List *elemlist, uint32 *flags);
66 :
67 : /*
68 : * Entry point for a new backend process.
69 : *
70 : * Initialize the connection, read the startup packet, authenticate the
71 : * client, and start the main processing loop.
72 : */
73 : void
74 27104 : BackendMain(const void *startup_data, size_t startup_data_len)
75 : {
76 27104 : const BackendStartupData *bsdata = startup_data;
77 :
78 : Assert(startup_data_len == sizeof(BackendStartupData));
79 : Assert(MyClientSocket != NULL);
80 :
81 : #ifdef EXEC_BACKEND
82 :
83 : /*
84 : * Need to reinitialize the SSL library in the backend, since the context
85 : * structures contain function pointers and cannot be passed through the
86 : * parameter file.
87 : *
88 : * If for some reason reload fails (maybe the user installed broken key
89 : * files), soldier on without SSL; that's better than all connections
90 : * becoming impossible.
91 : *
92 : * XXX should we do this in all child processes? For the moment it's
93 : * enough to do it in backend children.
94 : */
95 : #ifdef USE_SSL
96 : if (EnableSSL)
97 : {
98 : if (secure_initialize(false) == 0)
99 : LoadedSSL = true;
100 : else
101 : ereport(LOG,
102 : (errmsg("SSL configuration could not be loaded in child process")));
103 : }
104 : #endif
105 : #endif
106 :
107 : /* Perform additional initialization and collect startup packet */
108 27104 : BackendInitialize(MyClientSocket, bsdata->canAcceptConnections);
109 :
110 : /*
111 : * Create a per-backend PGPROC struct in shared memory. We must do this
112 : * before we can use LWLocks or access any shared memory.
113 : */
114 26748 : InitProcess();
115 :
116 : /*
117 : * Make sure we aren't in PostmasterContext anymore. (We can't delete it
118 : * just yet, though, because InitPostgres will need the HBA data.)
119 : */
120 26742 : MemoryContextSwitchTo(TopMemoryContext);
121 :
122 26742 : PostgresMain(MyProcPort->database_name, MyProcPort->user_name);
123 : }
124 :
125 :
126 : /*
127 : * BackendInitialize -- initialize an interactive (postmaster-child)
128 : * backend process, and collect the client's startup packet.
129 : *
130 : * returns: nothing. Will not return at all if there's any failure.
131 : *
132 : * Note: this code does not depend on having any access to shared memory.
133 : * Indeed, our approach to SIGTERM/timeout handling *requires* that
134 : * shared memory not have been touched yet; see comments within.
135 : * In the EXEC_BACKEND case, we are physically attached to shared memory
136 : * but have not yet set up most of our local pointers to shmem structures.
137 : */
138 : static void
139 27104 : BackendInitialize(ClientSocket *client_sock, CAC_state cac)
140 : {
141 : int status;
142 : int ret;
143 : Port *port;
144 : char remote_host[NI_MAXHOST];
145 : char remote_port[NI_MAXSERV];
146 : StringInfoData ps_data;
147 : MemoryContext oldcontext;
148 :
149 : /* Tell fd.c about the long-lived FD associated with the client_sock */
150 27104 : ReserveExternalFD();
151 :
152 : /*
153 : * PreAuthDelay is a debugging aid for investigating problems in the
154 : * authentication cycle: it can be set in postgresql.conf to allow time to
155 : * attach to the newly-forked backend with a debugger. (See also
156 : * PostAuthDelay, which we allow clients to pass through PGOPTIONS, but it
157 : * is not honored until after authentication.)
158 : */
159 27104 : if (PreAuthDelay > 0)
160 0 : pg_usleep(PreAuthDelay * 1000000L);
161 :
162 : /* This flag will remain set until InitPostgres finishes authentication */
163 27104 : ClientAuthInProgress = true; /* limit visibility of log messages */
164 :
165 : /*
166 : * Initialize libpq and enable reporting of ereport errors to the client.
167 : * Must do this now because authentication uses libpq to send messages.
168 : *
169 : * The Port structure and all data structures attached to it are allocated
170 : * in TopMemoryContext, so that they survive into PostgresMain execution.
171 : * We need not worry about leaking this storage on failure, since we
172 : * aren't in the postmaster process anymore.
173 : */
174 27104 : oldcontext = MemoryContextSwitchTo(TopMemoryContext);
175 27104 : port = MyProcPort = pq_init(client_sock);
176 27104 : MemoryContextSwitchTo(oldcontext);
177 :
178 27104 : whereToSendOutput = DestRemote; /* now safe to ereport to client */
179 :
180 : /* set these to empty in case they are needed before we set them up */
181 27104 : port->remote_host = "";
182 27104 : port->remote_port = "";
183 :
184 : /*
185 : * We arrange to do _exit(1) if we receive SIGTERM or timeout while trying
186 : * to collect the startup packet; while SIGQUIT results in _exit(2).
187 : * Otherwise the postmaster cannot shutdown the database FAST or IMMED
188 : * cleanly if a buggy client fails to send the packet promptly.
189 : *
190 : * Exiting with _exit(1) is only possible because we have not yet touched
191 : * shared memory; therefore no outside-the-process state needs to get
192 : * cleaned up.
193 : */
194 27104 : pqsignal(SIGTERM, process_startup_packet_die);
195 : /* SIGQUIT handler was already set up by InitPostmasterChild */
196 27104 : InitializeTimeouts(); /* establishes SIGALRM handler */
197 27104 : sigprocmask(SIG_SETMASK, &StartupBlockSig, NULL);
198 :
199 : /*
200 : * Get the remote host name and port for logging and status display.
201 : */
202 27104 : remote_host[0] = '\0';
203 27104 : remote_port[0] = '\0';
204 27104 : if ((ret = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen,
205 : remote_host, sizeof(remote_host),
206 : remote_port, sizeof(remote_port),
207 : (log_hostname ? 0 : NI_NUMERICHOST) | NI_NUMERICSERV)) != 0)
208 0 : ereport(WARNING,
209 : (errmsg_internal("pg_getnameinfo_all() failed: %s",
210 : gai_strerror(ret))));
211 :
212 : /*
213 : * Save remote_host and remote_port in port structure (after this, they
214 : * will appear in log_line_prefix data for log messages).
215 : */
216 27104 : port->remote_host = MemoryContextStrdup(TopMemoryContext, remote_host);
217 27104 : port->remote_port = MemoryContextStrdup(TopMemoryContext, remote_port);
218 :
219 : /* And now we can log that the connection was received, if enabled */
220 27104 : if (log_connections & LOG_CONNECTION_RECEIPT)
221 : {
222 850 : if (remote_port[0])
223 292 : ereport(LOG,
224 : (errmsg("connection received: host=%s port=%s",
225 : remote_host,
226 : remote_port)));
227 : else
228 558 : ereport(LOG,
229 : (errmsg("connection received: host=%s",
230 : remote_host)));
231 : }
232 :
233 : /* For testing client error handling */
234 : #ifdef USE_INJECTION_POINTS
235 27104 : INJECTION_POINT("backend-initialize");
236 27104 : if (IS_INJECTION_POINT_ATTACHED("backend-initialize-v2-error"))
237 : {
238 : /*
239 : * This simulates an early error from a pre-v14 server, which used the
240 : * version 2 protocol for any errors that occurred before processing
241 : * the startup packet.
242 : */
243 2 : FrontendProtocol = PG_PROTOCOL(2, 0);
244 2 : elog(FATAL, "protocol version 2 error triggered");
245 : }
246 : #endif
247 :
248 : /*
249 : * If we did a reverse lookup to name, we might as well save the results
250 : * rather than possibly repeating the lookup during authentication.
251 : *
252 : * Note that we don't want to specify NI_NAMEREQD above, because then we'd
253 : * get nothing useful for a client without an rDNS entry. Therefore, we
254 : * must check whether we got a numeric IPv4 or IPv6 address, and not save
255 : * it into remote_hostname if so. (This test is conservative and might
256 : * sometimes classify a hostname as numeric, but an error in that
257 : * direction is safe; it only results in a possible extra lookup.)
258 : */
259 27102 : if (log_hostname &&
260 232 : ret == 0 &&
261 232 : strspn(remote_host, "0123456789.") < strlen(remote_host) &&
262 232 : strspn(remote_host, "0123456789ABCDEFabcdef:") < strlen(remote_host))
263 : {
264 232 : port->remote_hostname = MemoryContextStrdup(TopMemoryContext, remote_host);
265 : }
266 :
267 : /*
268 : * Ready to begin client interaction. We will give up and _exit(1) after
269 : * a time delay, so that a broken client can't hog a connection
270 : * indefinitely. PreAuthDelay and any DNS interactions above don't count
271 : * against the time limit.
272 : *
273 : * Note: AuthenticationTimeout is applied here while waiting for the
274 : * startup packet, and then again in InitPostgres for the duration of any
275 : * authentication operations. So a hostile client could tie up the
276 : * process for nearly twice AuthenticationTimeout before we kick him off.
277 : *
278 : * Note: because PostgresMain will call InitializeTimeouts again, the
279 : * registration of STARTUP_PACKET_TIMEOUT will be lost. This is okay
280 : * since we never use it again after this function.
281 : */
282 27102 : RegisterTimeout(STARTUP_PACKET_TIMEOUT, StartupPacketTimeoutHandler);
283 27102 : enable_timeout_after(STARTUP_PACKET_TIMEOUT, AuthenticationTimeout * 1000);
284 :
285 : /* Handle direct SSL handshake */
286 27102 : status = ProcessSSLStartup(port);
287 :
288 : /*
289 : * Receive the startup packet (which might turn out to be a cancel request
290 : * packet).
291 : */
292 27102 : if (status == STATUS_OK)
293 27092 : status = ProcessStartupPacket(port, false, false);
294 :
295 : /*
296 : * If we're going to reject the connection due to database state, say so
297 : * now instead of wasting cycles on an authentication exchange. (This also
298 : * allows a pg_ping utility to be written.)
299 : */
300 27100 : if (status == STATUS_OK)
301 : {
302 26978 : switch (cac)
303 : {
304 204 : case CAC_STARTUP:
305 204 : ereport(FATAL,
306 : (errcode(ERRCODE_CANNOT_CONNECT_NOW),
307 : errmsg("the database system is starting up")));
308 : break;
309 10 : case CAC_NOTCONSISTENT:
310 10 : if (EnableHotStandby)
311 10 : ereport(FATAL,
312 : (errcode(ERRCODE_CANNOT_CONNECT_NOW),
313 : errmsg("the database system is not yet accepting connections"),
314 : errdetail("Consistent recovery state has not been yet reached.")));
315 : else
316 0 : ereport(FATAL,
317 : (errcode(ERRCODE_CANNOT_CONNECT_NOW),
318 : errmsg("the database system is not accepting connections"),
319 : errdetail("Hot standby mode is disabled.")));
320 : break;
321 14 : case CAC_SHUTDOWN:
322 14 : ereport(FATAL,
323 : (errcode(ERRCODE_CANNOT_CONNECT_NOW),
324 : errmsg("the database system is shutting down")));
325 : break;
326 0 : case CAC_RECOVERY:
327 0 : ereport(FATAL,
328 : (errcode(ERRCODE_CANNOT_CONNECT_NOW),
329 : errmsg("the database system is in recovery mode")));
330 : break;
331 2 : case CAC_TOOMANY:
332 2 : ereport(FATAL,
333 : (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
334 : errmsg("sorry, too many clients already")));
335 : break;
336 26748 : case CAC_OK:
337 26748 : break;
338 : }
339 122 : }
340 :
341 : /*
342 : * Disable the timeout, and prevent SIGTERM again.
343 : */
344 26870 : disable_timeout(STARTUP_PACKET_TIMEOUT, false);
345 26870 : sigprocmask(SIG_SETMASK, &BlockSig, NULL);
346 :
347 : /*
348 : * As a safety check that nothing in startup has yet performed
349 : * shared-memory modifications that would need to be undone if we had
350 : * exited through SIGTERM or timeout above, check that no on_shmem_exit
351 : * handlers have been registered yet. (This isn't terribly bulletproof,
352 : * since someone might misuse an on_proc_exit handler for shmem cleanup,
353 : * but it's a cheap and helpful check. We cannot disallow on_proc_exit
354 : * handlers unfortunately, since pq_init() already registered one.)
355 : */
356 26870 : check_on_shmem_exit_lists_are_empty();
357 :
358 : /*
359 : * Stop here if it was bad or a cancel packet. ProcessStartupPacket
360 : * already did any appropriate error reporting.
361 : */
362 26870 : if (status != STATUS_OK)
363 122 : proc_exit(0);
364 :
365 : /*
366 : * Now that we have the user and database name, we can set the process
367 : * title for ps. It's good to do this as early as possible in startup.
368 : */
369 26748 : initStringInfo(&ps_data);
370 26748 : if (am_walsender)
371 2204 : appendStringInfo(&ps_data, "%s ", GetBackendTypeDesc(B_WAL_SENDER));
372 26748 : appendStringInfo(&ps_data, "%s ", port->user_name);
373 26748 : if (port->database_name[0] != '\0')
374 25842 : appendStringInfo(&ps_data, "%s ", port->database_name);
375 26748 : appendStringInfoString(&ps_data, port->remote_host);
376 26748 : if (port->remote_port[0] != '\0')
377 502 : appendStringInfo(&ps_data, "(%s)", port->remote_port);
378 :
379 26748 : init_ps_display(ps_data.data);
380 26748 : pfree(ps_data.data);
381 :
382 26748 : set_ps_display("initializing");
383 26748 : }
384 :
385 : /*
386 : * Check for a direct SSL connection.
387 : *
388 : * This happens before the startup packet so we are careful not to actually
389 : * read any bytes from the stream if it's not a direct SSL connection.
390 : */
391 : static int
392 27102 : ProcessSSLStartup(Port *port)
393 : {
394 : int firstbyte;
395 :
396 : Assert(!port->ssl_in_use);
397 :
398 27102 : pq_startmsgread();
399 27102 : firstbyte = pq_peekbyte();
400 27102 : pq_endmsgread();
401 27102 : if (firstbyte == EOF)
402 : {
403 : /*
404 : * Like in ProcessStartupPacket, if we get no data at all, don't
405 : * clutter the log with a complaint.
406 : */
407 6 : return STATUS_ERROR;
408 : }
409 :
410 27096 : if (firstbyte != 0x16)
411 : {
412 : /* Not an SSL handshake message */
413 27086 : return STATUS_OK;
414 : }
415 :
416 : /*
417 : * First byte indicates standard SSL handshake message
418 : *
419 : * (It can't be a Postgres startup length because in network byte order
420 : * that would be a startup packet hundreds of megabytes long)
421 : */
422 :
423 : #ifdef USE_SSL
424 10 : if (!LoadedSSL || port->laddr.addr.ss_family == AF_UNIX)
425 : {
426 : /* SSL not supported */
427 4 : goto reject;
428 : }
429 :
430 6 : if (secure_open_server(port) == -1)
431 : {
432 : /*
433 : * we assume secure_open_server() sent an appropriate TLS alert
434 : * already
435 : */
436 0 : goto reject;
437 : }
438 : Assert(port->ssl_in_use);
439 :
440 6 : if (!port->alpn_used)
441 : {
442 0 : ereport(COMMERROR,
443 : (errcode(ERRCODE_PROTOCOL_VIOLATION),
444 : errmsg("received direct SSL connection request without ALPN protocol negotiation extension")));
445 0 : goto reject;
446 : }
447 :
448 6 : if (Trace_connection_negotiation)
449 6 : ereport(LOG,
450 : (errmsg("direct SSL connection accepted")));
451 6 : return STATUS_OK;
452 : #else
453 : /* SSL not supported by this build */
454 : goto reject;
455 : #endif
456 :
457 4 : reject:
458 4 : if (Trace_connection_negotiation)
459 4 : ereport(LOG,
460 : (errmsg("direct SSL connection rejected")));
461 4 : return STATUS_ERROR;
462 : }
463 :
464 : /*
465 : * Read a client's startup packet and do something according to it.
466 : *
467 : * Returns STATUS_OK or STATUS_ERROR, or might call ereport(FATAL) and
468 : * not return at all.
469 : *
470 : * (Note that ereport(FATAL) stuff is sent to the client, so only use it
471 : * if that's what you want. Return STATUS_ERROR if you don't want to
472 : * send anything to the client, which would typically be appropriate
473 : * if we detect a communications failure.)
474 : *
475 : * Set ssl_done and/or gss_done when negotiation of an encrypted layer
476 : * (currently, TLS or GSSAPI) is completed. A successful negotiation of either
477 : * encryption layer sets both flags, but a rejected negotiation sets only the
478 : * flag for that layer, since the client may wish to try the other one. We
479 : * should make no assumption here about the order in which the client may make
480 : * requests.
481 : */
482 : static int
483 27618 : ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
484 : {
485 : int32 len;
486 : char *buf;
487 : ProtocolVersion proto;
488 : MemoryContext oldcontext;
489 :
490 27618 : pq_startmsgread();
491 :
492 : /*
493 : * Grab the first byte of the length word separately, so that we can tell
494 : * whether we have no data at all or an incomplete packet. (This might
495 : * sound inefficient, but it's not really, because of buffering in
496 : * pqcomm.c.)
497 : */
498 27618 : if (pq_getbytes(&len, 1) == EOF)
499 : {
500 : /*
501 : * If we get no data at all, don't clutter the log with a complaint;
502 : * such cases often occur for legitimate reasons. An example is that
503 : * we might be here after responding to NEGOTIATE_SSL_CODE, and if the
504 : * client didn't like our response, it'll probably just drop the
505 : * connection. Service-monitoring software also often just opens and
506 : * closes a connection without sending anything. (So do port
507 : * scanners, which may be less benign, but it's not really our job to
508 : * notice those.)
509 : */
510 54 : return STATUS_ERROR;
511 : }
512 :
513 27564 : if (pq_getbytes(((char *) &len) + 1, 3) == EOF)
514 : {
515 : /* Got a partial length word, so bleat about that */
516 0 : if (!ssl_done && !gss_done)
517 0 : ereport(COMMERROR,
518 : (errcode(ERRCODE_PROTOCOL_VIOLATION),
519 : errmsg("incomplete startup packet")));
520 0 : return STATUS_ERROR;
521 : }
522 :
523 27564 : len = pg_ntoh32(len);
524 27564 : len -= 4;
525 :
526 27564 : if (len < (int32) sizeof(ProtocolVersion) ||
527 27564 : len > MAX_STARTUP_PACKET_LENGTH)
528 : {
529 0 : ereport(COMMERROR,
530 : (errcode(ERRCODE_PROTOCOL_VIOLATION),
531 : errmsg("invalid length of startup packet")));
532 0 : return STATUS_ERROR;
533 : }
534 :
535 : /*
536 : * Allocate space to hold the startup packet, plus one extra byte that's
537 : * initialized to be zero. This ensures we will have null termination of
538 : * all strings inside the packet.
539 : */
540 27564 : buf = palloc(len + 1);
541 27564 : buf[len] = '\0';
542 :
543 27564 : if (pq_getbytes(buf, len) == EOF)
544 : {
545 0 : ereport(COMMERROR,
546 : (errcode(ERRCODE_PROTOCOL_VIOLATION),
547 : errmsg("incomplete startup packet")));
548 0 : return STATUS_ERROR;
549 : }
550 27564 : pq_endmsgread();
551 :
552 : /*
553 : * The first field is either a protocol version number or a special
554 : * request code.
555 : */
556 27564 : port->proto = proto = pg_ntoh32(*((ProtocolVersion *) buf));
557 :
558 27564 : if (proto == CANCEL_REQUEST_CODE)
559 : {
560 : /*
561 : * The client has sent a cancel request packet, not a normal
562 : * start-a-new-connection packet. Perform the necessary processing.
563 : * Nothing is sent back to the client.
564 : */
565 : CancelRequestPacket *canc;
566 : int backendPID;
567 : int32 cancelAuthCode;
568 :
569 20 : if (len != sizeof(CancelRequestPacket))
570 : {
571 0 : ereport(COMMERROR,
572 : (errcode(ERRCODE_PROTOCOL_VIOLATION),
573 : errmsg("invalid length of startup packet")));
574 0 : return STATUS_ERROR;
575 : }
576 20 : canc = (CancelRequestPacket *) buf;
577 20 : backendPID = (int) pg_ntoh32(canc->backendPID);
578 20 : cancelAuthCode = (int32) pg_ntoh32(canc->cancelAuthCode);
579 :
580 20 : if (backendPID != 0)
581 20 : SendCancelRequest(backendPID, cancelAuthCode);
582 : /* Not really an error, but we don't want to proceed further */
583 20 : return STATUS_ERROR;
584 : }
585 :
586 27544 : if (proto == NEGOTIATE_SSL_CODE && !ssl_done)
587 : {
588 : char SSLok;
589 :
590 : #ifdef USE_SSL
591 :
592 : /*
593 : * No SSL when disabled or on Unix sockets.
594 : *
595 : * Also no SSL negotiation if we already have a direct SSL connection
596 : */
597 566 : if (!LoadedSSL || port->laddr.addr.ss_family == AF_UNIX || port->ssl_in_use)
598 320 : SSLok = 'N';
599 : else
600 246 : SSLok = 'S'; /* Support for SSL */
601 : #else
602 : SSLok = 'N'; /* No support for SSL */
603 : #endif
604 :
605 566 : if (Trace_connection_negotiation)
606 : {
607 24 : if (SSLok == 'S')
608 16 : ereport(LOG,
609 : (errmsg("SSLRequest accepted")));
610 : else
611 8 : ereport(LOG,
612 : (errmsg("SSLRequest rejected")));
613 : }
614 :
615 566 : while (secure_write(port, &SSLok, 1) != 1)
616 : {
617 0 : if (errno == EINTR)
618 0 : continue; /* if interrupted, just retry */
619 0 : ereport(COMMERROR,
620 : (errcode_for_socket_access(),
621 : errmsg("failed to send SSL negotiation response: %m")));
622 0 : return STATUS_ERROR; /* close the connection */
623 : }
624 :
625 : #ifdef USE_SSL
626 566 : if (SSLok == 'S' && secure_open_server(port) == -1)
627 38 : return STATUS_ERROR;
628 : #endif
629 :
630 : /*
631 : * At this point we should have no data already buffered. If we do,
632 : * it was received before we performed the SSL handshake, so it wasn't
633 : * encrypted and indeed may have been injected by a man-in-the-middle.
634 : * We report this case to the client.
635 : */
636 526 : if (pq_buffer_remaining_data() > 0)
637 0 : ereport(FATAL,
638 : (errcode(ERRCODE_PROTOCOL_VIOLATION),
639 : errmsg("received unencrypted data after SSL request"),
640 : errdetail("This could be either a client-software bug or evidence of an attempted man-in-the-middle attack.")));
641 :
642 : /*
643 : * regular startup packet, cancel, etc packet should follow, but not
644 : * another SSL negotiation request, and a GSS request should only
645 : * follow if SSL was rejected (client may negotiate in either order)
646 : */
647 526 : return ProcessStartupPacket(port, true, SSLok == 'S');
648 : }
649 26978 : else if (proto == NEGOTIATE_GSS_CODE && !gss_done)
650 : {
651 0 : char GSSok = 'N';
652 :
653 : #ifdef ENABLE_GSS
654 : /* No GSSAPI encryption when on Unix socket */
655 : if (port->laddr.addr.ss_family != AF_UNIX)
656 : GSSok = 'G';
657 : #endif
658 :
659 0 : if (Trace_connection_negotiation)
660 : {
661 0 : if (GSSok == 'G')
662 0 : ereport(LOG,
663 : (errmsg("GSSENCRequest accepted")));
664 : else
665 0 : ereport(LOG,
666 : (errmsg("GSSENCRequest rejected")));
667 : }
668 :
669 0 : while (secure_write(port, &GSSok, 1) != 1)
670 : {
671 0 : if (errno == EINTR)
672 0 : continue;
673 0 : ereport(COMMERROR,
674 : (errcode_for_socket_access(),
675 : errmsg("failed to send GSSAPI negotiation response: %m")));
676 0 : return STATUS_ERROR; /* close the connection */
677 : }
678 :
679 : #ifdef ENABLE_GSS
680 : if (GSSok == 'G' && secure_open_gssapi(port) == -1)
681 : return STATUS_ERROR;
682 : #endif
683 :
684 : /*
685 : * At this point we should have no data already buffered. If we do,
686 : * it was received before we performed the GSS handshake, so it wasn't
687 : * encrypted and indeed may have been injected by a man-in-the-middle.
688 : * We report this case to the client.
689 : */
690 0 : if (pq_buffer_remaining_data() > 0)
691 0 : ereport(FATAL,
692 : (errcode(ERRCODE_PROTOCOL_VIOLATION),
693 : errmsg("received unencrypted data after GSSAPI encryption request"),
694 : errdetail("This could be either a client-software bug or evidence of an attempted man-in-the-middle attack.")));
695 :
696 : /*
697 : * regular startup packet, cancel, etc packet should follow, but not
698 : * another GSS negotiation request, and an SSL request should only
699 : * follow if GSS was rejected (client may negotiate in either order)
700 : */
701 0 : return ProcessStartupPacket(port, GSSok == 'G', true);
702 : }
703 :
704 : /* Could add additional special packet types here */
705 :
706 : /*
707 : * Set FrontendProtocol now so that ereport() knows what format to send if
708 : * we fail during startup. We use the protocol version requested by the
709 : * client unless it's higher than the latest version we support. It's
710 : * possible that error message fields might look different in newer
711 : * protocol versions, but that's something those new clients should be
712 : * able to deal with.
713 : */
714 26978 : FrontendProtocol = Min(proto, PG_PROTOCOL_LATEST);
715 :
716 : /* Check that the major protocol version is in range. */
717 26978 : if (PG_PROTOCOL_MAJOR(proto) < PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST) ||
718 26978 : PG_PROTOCOL_MAJOR(proto) > PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST))
719 0 : ereport(FATAL,
720 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
721 : errmsg("unsupported frontend protocol %u.%u: server supports %u.0 to %u.%u",
722 : PG_PROTOCOL_MAJOR(proto), PG_PROTOCOL_MINOR(proto),
723 : PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST),
724 : PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST),
725 : PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST))));
726 :
727 : /*
728 : * Now fetch parameters out of startup packet and save them into the Port
729 : * structure.
730 : */
731 26978 : oldcontext = MemoryContextSwitchTo(TopMemoryContext);
732 :
733 : /* Handle protocol version 3 startup packet */
734 : {
735 26978 : int32 offset = sizeof(ProtocolVersion);
736 26978 : List *unrecognized_protocol_options = NIL;
737 :
738 : /*
739 : * Scan packet body for name/option pairs. We can assume any string
740 : * beginning within the packet body is null-terminated, thanks to
741 : * zeroing extra byte above.
742 : */
743 26978 : port->guc_options = NIL;
744 :
745 127888 : while (offset < len)
746 : {
747 127888 : char *nameptr = buf + offset;
748 : int32 valoffset;
749 : char *valptr;
750 :
751 127888 : if (*nameptr == '\0')
752 26978 : break; /* found packet terminator */
753 100910 : valoffset = offset + strlen(nameptr) + 1;
754 100910 : if (valoffset >= len)
755 0 : break; /* missing value, will complain below */
756 100910 : valptr = buf + valoffset;
757 :
758 100910 : if (strcmp(nameptr, "database") == 0)
759 26978 : port->database_name = pstrdup(valptr);
760 73932 : else if (strcmp(nameptr, "user") == 0)
761 26978 : port->user_name = pstrdup(valptr);
762 46954 : else if (strcmp(nameptr, "options") == 0)
763 7226 : port->cmdline_options = pstrdup(valptr);
764 39728 : else if (strcmp(nameptr, "replication") == 0)
765 : {
766 : /*
767 : * Due to backward compatibility concerns the replication
768 : * parameter is a hybrid beast which allows the value to be
769 : * either boolean or the string 'database'. The latter
770 : * connects to a specific database which is e.g. required for
771 : * logical decoding while.
772 : */
773 2232 : if (strcmp(valptr, "database") == 0)
774 : {
775 1302 : am_walsender = true;
776 1302 : am_db_walsender = true;
777 : }
778 930 : else if (!parse_bool(valptr, &am_walsender))
779 0 : ereport(FATAL,
780 : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
781 : errmsg("invalid value for parameter \"%s\": \"%s\"",
782 : "replication",
783 : valptr),
784 : errhint("Valid values are: \"false\", 0, \"true\", 1, \"database\".")));
785 : }
786 37496 : else if (strncmp(nameptr, "_pq_.", 5) == 0)
787 : {
788 : /*
789 : * Any option beginning with _pq_. is reserved for use as a
790 : * protocol-level option, but at present no such options are
791 : * defined.
792 : */
793 : unrecognized_protocol_options =
794 0 : lappend(unrecognized_protocol_options, pstrdup(nameptr));
795 : }
796 : else
797 : {
798 : /* Assume it's a generic GUC option */
799 37496 : port->guc_options = lappend(port->guc_options,
800 37496 : pstrdup(nameptr));
801 37496 : port->guc_options = lappend(port->guc_options,
802 37496 : pstrdup(valptr));
803 :
804 : /*
805 : * Copy application_name to port if we come across it. This
806 : * is done so we can log the application_name in the
807 : * connection authorization message. Note that the GUC would
808 : * be used but we haven't gone through GUC setup yet.
809 : */
810 37496 : if (strcmp(nameptr, "application_name") == 0)
811 : {
812 26968 : port->application_name = pg_clean_ascii(valptr, 0);
813 : }
814 : }
815 100910 : offset = valoffset + strlen(valptr) + 1;
816 : }
817 :
818 : /*
819 : * If we didn't find a packet terminator exactly at the end of the
820 : * given packet length, complain.
821 : */
822 26978 : if (offset != len - 1)
823 0 : ereport(FATAL,
824 : (errcode(ERRCODE_PROTOCOL_VIOLATION),
825 : errmsg("invalid startup packet layout: expected terminator as last byte")));
826 :
827 : /*
828 : * If the client requested a newer protocol version or if the client
829 : * requested any protocol options we didn't recognize, let them know
830 : * the newest minor protocol version we do support and the names of
831 : * any unrecognized options.
832 : */
833 26978 : if (PG_PROTOCOL_MINOR(proto) > PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST) ||
834 : unrecognized_protocol_options != NIL)
835 0 : SendNegotiateProtocolVersion(unrecognized_protocol_options);
836 : }
837 :
838 : /* Check a user name was given. */
839 26978 : if (port->user_name == NULL || port->user_name[0] == '\0')
840 0 : ereport(FATAL,
841 : (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
842 : errmsg("no PostgreSQL user name specified in startup packet")));
843 :
844 : /* The database defaults to the user name. */
845 26978 : if (port->database_name == NULL || port->database_name[0] == '\0')
846 0 : port->database_name = pstrdup(port->user_name);
847 :
848 : /*
849 : * Truncate given database and user names to length of a Postgres name.
850 : * This avoids lookup failures when overlength names are given.
851 : */
852 26978 : if (strlen(port->database_name) >= NAMEDATALEN)
853 0 : port->database_name[NAMEDATALEN - 1] = '\0';
854 26978 : if (strlen(port->user_name) >= NAMEDATALEN)
855 0 : port->user_name[NAMEDATALEN - 1] = '\0';
856 :
857 26978 : if (am_walsender)
858 2232 : MyBackendType = B_WAL_SENDER;
859 : else
860 24746 : MyBackendType = B_BACKEND;
861 :
862 : /*
863 : * Normal walsender backends, e.g. for streaming replication, are not
864 : * connected to a particular database. But walsenders used for logical
865 : * replication need to connect to a specific database. We allow streaming
866 : * replication commands to be issued even if connected to a database as it
867 : * can make sense to first make a basebackup and then stream changes
868 : * starting from that.
869 : */
870 26978 : if (am_walsender && !am_db_walsender)
871 930 : port->database_name[0] = '\0';
872 :
873 : /*
874 : * Done filling the Port structure
875 : */
876 26978 : MemoryContextSwitchTo(oldcontext);
877 :
878 26978 : return STATUS_OK;
879 : }
880 :
881 : /*
882 : * Send a NegotiateProtocolVersion to the client. This lets the client know
883 : * that they have either requested a newer minor protocol version than we are
884 : * able to speak, or at least one protocol option that we don't understand, or
885 : * possibly both. FrontendProtocol has already been set to the version
886 : * requested by the client or the highest version we know how to speak,
887 : * whichever is older. If the highest version that we know how to speak is too
888 : * old for the client, it can abandon the connection.
889 : *
890 : * We also include in the response a list of protocol options we didn't
891 : * understand. This allows clients to include optional parameters that might
892 : * be present either in newer protocol versions or third-party protocol
893 : * extensions without fear of having to reconnect if those options are not
894 : * understood, while at the same time making certain that the client is aware
895 : * of which options were actually accepted.
896 : */
897 : static void
898 0 : SendNegotiateProtocolVersion(List *unrecognized_protocol_options)
899 : {
900 : StringInfoData buf;
901 : ListCell *lc;
902 :
903 0 : pq_beginmessage(&buf, PqMsg_NegotiateProtocolVersion);
904 0 : pq_sendint32(&buf, FrontendProtocol);
905 0 : pq_sendint32(&buf, list_length(unrecognized_protocol_options));
906 0 : foreach(lc, unrecognized_protocol_options)
907 0 : pq_sendstring(&buf, lfirst(lc));
908 0 : pq_endmessage(&buf);
909 :
910 : /* no need to flush, some other message will follow */
911 0 : }
912 :
913 :
914 : /*
915 : * SIGTERM while processing startup packet.
916 : *
917 : * Running proc_exit() from a signal handler would be quite unsafe.
918 : * However, since we have not yet touched shared memory, we can just
919 : * pull the plug and exit without running any atexit handlers.
920 : *
921 : * One might be tempted to try to send a message, or log one, indicating
922 : * why we are disconnecting. However, that would be quite unsafe in itself.
923 : * Also, it seems undesirable to provide clues about the database's state
924 : * to a client that has not yet completed authentication, or even sent us
925 : * a startup packet.
926 : */
927 : static void
928 0 : process_startup_packet_die(SIGNAL_ARGS)
929 : {
930 0 : _exit(1);
931 : }
932 :
933 : /*
934 : * Timeout while processing startup packet.
935 : * As for process_startup_packet_die(), we exit via _exit(1).
936 : */
937 : static void
938 0 : StartupPacketTimeoutHandler(void)
939 : {
940 0 : _exit(1);
941 : }
942 :
943 : /*
944 : * Helper for the log_connections GUC check hook.
945 : *
946 : * `elemlist` is a listified version of the string input passed to the
947 : * log_connections GUC check hook, check_log_connections().
948 : * check_log_connections() is responsible for cleaning up `elemlist`.
949 : *
950 : * validate_log_connections_options() returns false if an error was
951 : * encountered and the GUC input could not be validated and true otherwise.
952 : *
953 : * `flags` returns the flags that should be stored in the log_connections GUC
954 : * by its assign hook.
955 : */
956 : static bool
957 2336 : validate_log_connections_options(List *elemlist, uint32 *flags)
958 : {
959 : ListCell *l;
960 : char *item;
961 :
962 : /*
963 : * For backwards compatibility, we accept these tokens by themselves.
964 : *
965 : * Prior to PostgreSQL 18, log_connections was a boolean GUC that accepted
966 : * any unambiguous substring of 'true', 'false', 'yes', 'no', 'on', and
967 : * 'off'. Since log_connections became a list of strings in 18, we only
968 : * accept complete option strings.
969 : */
970 : static const struct config_enum_entry compat_options[] = {
971 : {"off", 0},
972 : {"false", 0},
973 : {"no", 0},
974 : {"0", 0},
975 : {"on", LOG_CONNECTION_ON},
976 : {"true", LOG_CONNECTION_ON},
977 : {"yes", LOG_CONNECTION_ON},
978 : {"1", LOG_CONNECTION_ON},
979 : };
980 :
981 2336 : *flags = 0;
982 :
983 : /* If an empty string was passed, we're done */
984 2336 : if (list_length(elemlist) == 0)
985 2106 : return true;
986 :
987 : /*
988 : * Now check for the backwards compatibility options. They must always be
989 : * specified on their own, so we error out if the first option is a
990 : * backwards compatibility option and other options are also specified.
991 : */
992 230 : item = linitial(elemlist);
993 :
994 1392 : for (size_t i = 0; i < lengthof(compat_options); i++)
995 : {
996 1342 : struct config_enum_entry option = compat_options[i];
997 :
998 1342 : if (pg_strcasecmp(item, option.name) != 0)
999 1162 : continue;
1000 :
1001 180 : if (list_length(elemlist) > 1)
1002 : {
1003 0 : GUC_check_errdetail("Cannot specify log_connections option \"%s\" in a list with other options.",
1004 : item);
1005 180 : return false;
1006 : }
1007 :
1008 180 : *flags = option.val;
1009 180 : return true;
1010 : }
1011 :
1012 : /* Now check the aspect options. The empty string was already handled */
1013 108 : foreach(l, elemlist)
1014 : {
1015 : static const struct config_enum_entry options[] = {
1016 : {"receipt", LOG_CONNECTION_RECEIPT},
1017 : {"authentication", LOG_CONNECTION_AUTHENTICATION},
1018 : {"authorization", LOG_CONNECTION_AUTHORIZATION},
1019 : {"setup_durations", LOG_CONNECTION_SETUP_DURATIONS},
1020 : {"all", LOG_CONNECTION_ALL},
1021 : };
1022 :
1023 58 : item = lfirst(l);
1024 262 : for (size_t i = 0; i < lengthof(options); i++)
1025 : {
1026 262 : struct config_enum_entry option = options[i];
1027 :
1028 262 : if (pg_strcasecmp(item, option.name) == 0)
1029 : {
1030 58 : *flags |= option.val;
1031 58 : goto next;
1032 : }
1033 : }
1034 :
1035 0 : GUC_check_errdetail("Invalid option \"%s\".", item);
1036 0 : return false;
1037 :
1038 58 : next: ;
1039 : }
1040 :
1041 50 : return true;
1042 : }
1043 :
1044 :
1045 : /*
1046 : * GUC check hook for log_connections
1047 : */
1048 : bool
1049 2336 : check_log_connections(char **newval, void **extra, GucSource source)
1050 : {
1051 : uint32 flags;
1052 : char *rawstring;
1053 : List *elemlist;
1054 : bool success;
1055 :
1056 : /* Need a modifiable copy of string */
1057 2336 : rawstring = pstrdup(*newval);
1058 :
1059 2336 : if (!SplitIdentifierString(rawstring, ',', &elemlist))
1060 : {
1061 0 : GUC_check_errdetail("Invalid list syntax in parameter \"log_connections\".");
1062 0 : pfree(rawstring);
1063 0 : list_free(elemlist);
1064 0 : return false;
1065 : }
1066 :
1067 : /* Validation logic is all in the helper */
1068 2336 : success = validate_log_connections_options(elemlist, &flags);
1069 :
1070 : /* Time for cleanup */
1071 2336 : pfree(rawstring);
1072 2336 : list_free(elemlist);
1073 :
1074 2336 : if (!success)
1075 0 : return false;
1076 :
1077 : /*
1078 : * We succeeded, so allocate `extra` and save the flags there for use by
1079 : * assign_log_connections().
1080 : */
1081 2336 : *extra = guc_malloc(LOG, sizeof(int));
1082 2336 : if (!*extra)
1083 0 : return false;
1084 2336 : *((int *) *extra) = flags;
1085 :
1086 2336 : return true;
1087 : }
1088 :
1089 : /*
1090 : * GUC assign hook for log_connections
1091 : */
1092 : void
1093 2328 : assign_log_connections(const char *newval, void *extra)
1094 : {
1095 2328 : log_connections = *((int *) extra);
1096 2328 : }
|