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 "access/xlogrecovery.h"
22 : #include "common/ip.h"
23 : #include "common/string.h"
24 : #include "libpq/libpq.h"
25 : #include "libpq/libpq-be.h"
26 : #include "libpq/pqformat.h"
27 : #include "libpq/pqsignal.h"
28 : #include "miscadmin.h"
29 : #include "postmaster/postmaster.h"
30 : #include "replication/walsender.h"
31 : #include "storage/fd.h"
32 : #include "storage/ipc.h"
33 : #include "storage/procsignal.h"
34 : #include "storage/proc.h"
35 : #include "tcop/backend_startup.h"
36 : #include "tcop/tcopprot.h"
37 : #include "utils/builtins.h"
38 : #include "utils/guc_hooks.h"
39 : #include "utils/injection_point.h"
40 : #include "utils/memutils.h"
41 : #include "utils/ps_status.h"
42 : #include "utils/timeout.h"
43 : #include "utils/varlena.h"
44 :
45 : /* GUCs */
46 : bool Trace_connection_negotiation = false;
47 : uint32 log_connections = 0;
48 : char *log_connections_string = NULL;
49 :
50 : /* Other globals */
51 :
52 : /*
53 : * ConnectionTiming stores timestamps of various points in connection
54 : * establishment and setup.
55 : * ready_for_use is initialized to a special value here so we can check if
56 : * we've already set it before doing so in PostgresMain().
57 : */
58 : ConnectionTiming conn_timing = {.ready_for_use = TIMESTAMP_MINUS_INFINITY};
59 :
60 : static void BackendInitialize(ClientSocket *client_sock, CAC_state cac);
61 : static int ProcessSSLStartup(Port *port);
62 : static int ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done);
63 : static void ProcessCancelRequestPacket(Port *port, void *pkt, int pktlen);
64 : static void SendNegotiateProtocolVersion(List *unrecognized_protocol_options);
65 : static void process_startup_packet_die(SIGNAL_ARGS);
66 : static void StartupPacketTimeoutHandler(void);
67 : static bool validate_log_connections_options(List *elemlist, uint32 *flags);
68 :
69 : /*
70 : * Entry point for a new backend process.
71 : *
72 : * Initialize the connection, read the startup packet, authenticate the
73 : * client, and start the main processing loop.
74 : */
75 : void
76 28026 : BackendMain(const void *startup_data, size_t startup_data_len)
77 : {
78 28026 : 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 */
110 28026 : 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 27640 : 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 : */
122 27634 : MemoryContextSwitchTo(TopMemoryContext);
123 :
124 27634 : PostgresMain(MyProcPort->database_name, MyProcPort->user_name);
125 : }
126 :
127 :
128 : /*
129 : * BackendInitialize -- initialize an interactive (postmaster-child)
130 : * backend process, and collect the client's startup packet.
131 : *
132 : * returns: nothing. Will not return at all if there's any failure.
133 : *
134 : * Note: this code does not depend on having any access to shared memory.
135 : * Indeed, our approach to SIGTERM/timeout handling *requires* that
136 : * shared memory not have been touched yet; see comments within.
137 : * In the EXEC_BACKEND case, we are physically attached to shared memory
138 : * but have not yet set up most of our local pointers to shmem structures.
139 : */
140 : static void
141 28026 : BackendInitialize(ClientSocket *client_sock, CAC_state cac)
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 */
152 28026 : ReserveExternalFD();
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 28026 : if (PreAuthDelay > 0)
162 0 : pg_usleep(PreAuthDelay * 1000000L);
163 :
164 : /* This flag will remain set until InitPostgres finishes authentication */
165 28026 : 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 : */
176 28026 : oldcontext = MemoryContextSwitchTo(TopMemoryContext);
177 28026 : port = MyProcPort = pq_init(client_sock);
178 28026 : MemoryContextSwitchTo(oldcontext);
179 :
180 28026 : 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 28026 : port->remote_host = "";
184 28026 : 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 : */
196 28026 : pqsignal(SIGTERM, process_startup_packet_die);
197 : /* SIGQUIT handler was already set up by InitPostmasterChild */
198 28026 : InitializeTimeouts(); /* establishes SIGALRM handler */
199 28026 : sigprocmask(SIG_SETMASK, &StartupBlockSig, NULL);
200 :
201 : /*
202 : * Get the remote host name and port for logging and status display.
203 : */
204 28026 : remote_host[0] = '\0';
205 28026 : remote_port[0] = '\0';
206 28026 : 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)
210 0 : ereport(WARNING,
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 28026 : port->remote_host = MemoryContextStrdup(TopMemoryContext, remote_host);
219 28026 : port->remote_port = MemoryContextStrdup(TopMemoryContext, remote_port);
220 :
221 : /* And now we can log that the connection was received, if enabled */
222 28026 : if (log_connections & LOG_CONNECTION_RECEIPT)
223 : {
224 1144 : if (remote_port[0])
225 294 : ereport(LOG,
226 : (errmsg("connection received: host=%s port=%s",
227 : remote_host,
228 : remote_port)));
229 : else
230 850 : 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 28026 : INJECTION_POINT("backend-initialize");
238 28024 : 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 : */
245 2 : FrontendProtocol = PG_PROTOCOL(2, 0);
246 2 : 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 28022 : if (log_hostname &&
262 232 : ret == 0 &&
263 232 : strspn(remote_host, "0123456789.") < strlen(remote_host) &&
264 232 : strspn(remote_host, "0123456789ABCDEFabcdef:") < strlen(remote_host))
265 : {
266 232 : 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 : */
284 28022 : RegisterTimeout(STARTUP_PACKET_TIMEOUT, StartupPacketTimeoutHandler);
285 28022 : enable_timeout_after(STARTUP_PACKET_TIMEOUT, AuthenticationTimeout * 1000);
286 :
287 : /* Handle direct SSL handshake */
288 28022 : status = ProcessSSLStartup(port);
289 :
290 : /*
291 : * Receive the startup packet (which might turn out to be a cancel request
292 : * packet).
293 : */
294 28022 : if (status == STATUS_OK)
295 28014 : 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 28020 : if (status == STATUS_OK)
303 : {
304 27912 : switch (cac)
305 : {
306 240 : case CAC_STARTUP:
307 240 : ereport(FATAL,
308 : (errcode(ERRCODE_CANNOT_CONNECT_NOW),
309 : errmsg("the database system is starting up")));
310 : break;
311 12 : case CAC_NOTHOTSTANDBY:
312 12 : if (!EnableHotStandby)
313 0 : ereport(FATAL,
314 : (errcode(ERRCODE_CANNOT_CONNECT_NOW),
315 : errmsg("the database system is not accepting connections"),
316 : errdetail("Hot standby mode is disabled.")));
317 12 : else if (reachedConsistency)
318 0 : ereport(FATAL,
319 : (errcode(ERRCODE_CANNOT_CONNECT_NOW),
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.",
323 : PGPROC_MAX_CACHED_SUBXIDS)));
324 : else
325 12 : ereport(FATAL,
326 : (errcode(ERRCODE_CANNOT_CONNECT_NOW),
327 : errmsg("the database system is not yet accepting connections"),
328 : errdetail("Consistent recovery state has not been yet reached.")));
329 : break;
330 18 : case CAC_SHUTDOWN:
331 18 : ereport(FATAL,
332 : (errcode(ERRCODE_CANNOT_CONNECT_NOW),
333 : errmsg("the database system is shutting down")));
334 : break;
335 0 : case CAC_RECOVERY:
336 0 : ereport(FATAL,
337 : (errcode(ERRCODE_CANNOT_CONNECT_NOW),
338 : errmsg("the database system is in recovery mode")));
339 : break;
340 2 : case CAC_TOOMANY:
341 2 : ereport(FATAL,
342 : (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
343 : errmsg("sorry, too many clients already")));
344 : break;
345 27640 : case CAC_OK:
346 27640 : break;
347 : }
348 108 : }
349 :
350 : /*
351 : * Disable the timeout, and prevent SIGTERM again.
352 : */
353 27748 : disable_timeout(STARTUP_PACKET_TIMEOUT, false);
354 27748 : 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 : */
365 27748 : check_on_shmem_exit_lists_are_empty();
366 :
367 : /*
368 : * Stop here if it was bad or a cancel packet. ProcessStartupPacket
369 : * already did any appropriate error reporting.
370 : */
371 27748 : if (status != STATUS_OK)
372 108 : 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 27640 : initStringInfo(&ps_data);
379 27640 : if (am_walsender)
380 2212 : appendStringInfo(&ps_data, "%s ", GetBackendTypeDesc(B_WAL_SENDER));
381 27640 : appendStringInfo(&ps_data, "%s ", port->user_name);
382 27640 : if (port->database_name[0] != '\0')
383 26730 : appendStringInfo(&ps_data, "%s ", port->database_name);
384 27640 : appendStringInfoString(&ps_data, port->remote_host);
385 27640 : if (port->remote_port[0] != '\0')
386 502 : appendStringInfo(&ps_data, "(%s)", port->remote_port);
387 :
388 27640 : init_ps_display(ps_data.data);
389 27640 : pfree(ps_data.data);
390 :
391 27640 : set_ps_display("initializing");
392 27640 : }
393 :
394 : /*
395 : * Check for a direct SSL connection.
396 : *
397 : * This happens before the startup packet so we are careful not to actually
398 : * read any bytes from the stream if it's not a direct SSL connection.
399 : */
400 : static int
401 28022 : ProcessSSLStartup(Port *port)
402 : {
403 : int firstbyte;
404 :
405 : Assert(!port->ssl_in_use);
406 :
407 28022 : pq_startmsgread();
408 28022 : firstbyte = pq_peekbyte();
409 28022 : pq_endmsgread();
410 28022 : 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 4 : return STATUS_ERROR;
417 : }
418 :
419 28018 : if (firstbyte != 0x16)
420 : {
421 : /* Not an SSL handshake message */
422 28008 : 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 10 : if (!LoadedSSL || port->laddr.addr.ss_family == AF_UNIX)
434 : {
435 : /* SSL not supported */
436 4 : goto reject;
437 : }
438 :
439 6 : if (secure_open_server(port) == -1)
440 : {
441 : /*
442 : * we assume secure_open_server() sent an appropriate TLS alert
443 : * already
444 : */
445 0 : goto reject;
446 : }
447 : Assert(port->ssl_in_use);
448 :
449 6 : if (!port->alpn_used)
450 : {
451 0 : ereport(COMMERROR,
452 : (errcode(ERRCODE_PROTOCOL_VIOLATION),
453 : errmsg("received direct SSL connection request without ALPN protocol negotiation extension")));
454 0 : goto reject;
455 : }
456 :
457 6 : if (Trace_connection_negotiation)
458 6 : ereport(LOG,
459 : (errmsg("direct SSL connection accepted")));
460 6 : return STATUS_OK;
461 : #else
462 : /* SSL not supported by this build */
463 : goto reject;
464 : #endif
465 :
466 4 : reject:
467 4 : if (Trace_connection_negotiation)
468 4 : ereport(LOG,
469 : (errmsg("direct SSL connection rejected")));
470 4 : return STATUS_ERROR;
471 : }
472 :
473 : /*
474 : * Read a client's startup packet and do something according to it.
475 : *
476 : * Returns STATUS_OK or STATUS_ERROR, or might call ereport(FATAL) and
477 : * not return at all.
478 : *
479 : * (Note that ereport(FATAL) stuff is sent to the client, so only use it
480 : * if that's what you want. Return STATUS_ERROR if you don't want to
481 : * send anything to the client, which would typically be appropriate
482 : * if we detect a communications failure.)
483 : *
484 : * Set ssl_done and/or gss_done when negotiation of an encrypted layer
485 : * (currently, TLS or GSSAPI) is completed. A successful negotiation of either
486 : * encryption layer sets both flags, but a rejected negotiation sets only the
487 : * flag for that layer, since the client may wish to try the other one. We
488 : * should make no assumption here about the order in which the client may make
489 : * requests.
490 : */
491 : static int
492 28516 : ProcessStartupPacket(Port *port, bool ssl_done, bool gss_done)
493 : {
494 : int32 len;
495 : char *buf;
496 : ProtocolVersion proto;
497 : MemoryContext oldcontext;
498 :
499 28516 : pq_startmsgread();
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 28516 : 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 30 : return STATUS_ERROR;
520 : }
521 :
522 28486 : if (pq_getbytes(((char *) &len) + 1, 3) == EOF)
523 : {
524 : /* Got a partial length word, so bleat about that */
525 0 : if (!ssl_done && !gss_done)
526 0 : ereport(COMMERROR,
527 : (errcode(ERRCODE_PROTOCOL_VIOLATION),
528 : errmsg("incomplete startup packet")));
529 0 : return STATUS_ERROR;
530 : }
531 :
532 28486 : len = pg_ntoh32(len);
533 28486 : len -= 4;
534 :
535 28486 : if (len < (int32) sizeof(ProtocolVersion) ||
536 28486 : len > MAX_STARTUP_PACKET_LENGTH)
537 : {
538 0 : ereport(COMMERROR,
539 : (errcode(ERRCODE_PROTOCOL_VIOLATION),
540 : errmsg("invalid length of startup packet")));
541 0 : 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 28486 : buf = palloc(len + 1);
550 28486 : buf[len] = '\0';
551 :
552 28486 : if (pq_getbytes(buf, len) == EOF)
553 : {
554 0 : ereport(COMMERROR,
555 : (errcode(ERRCODE_PROTOCOL_VIOLATION),
556 : errmsg("incomplete startup packet")));
557 0 : return STATUS_ERROR;
558 : }
559 28486 : pq_endmsgread();
560 :
561 : /*
562 : * The first field is either a protocol version number or a special
563 : * request code.
564 : */
565 28486 : port->proto = proto = pg_ntoh32(*((ProtocolVersion *) buf));
566 :
567 28486 : if (proto == CANCEL_REQUEST_CODE)
568 : {
569 32 : ProcessCancelRequestPacket(port, buf, len);
570 : /* Not really an error, but we don't want to proceed further */
571 32 : return STATUS_ERROR;
572 : }
573 :
574 28454 : 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 542 : if (!LoadedSSL || port->laddr.addr.ss_family == AF_UNIX || port->ssl_in_use)
586 296 : SSLok = 'N';
587 : else
588 246 : SSLok = 'S'; /* Support for SSL */
589 : #else
590 : SSLok = 'N'; /* No support for SSL */
591 : #endif
592 :
593 542 : if (Trace_connection_negotiation)
594 : {
595 24 : if (SSLok == 'S')
596 16 : ereport(LOG,
597 : (errmsg("SSLRequest accepted")));
598 : else
599 8 : ereport(LOG,
600 : (errmsg("SSLRequest rejected")));
601 : }
602 :
603 542 : while (secure_write(port, &SSLok, 1) != 1)
604 : {
605 0 : if (errno == EINTR)
606 0 : continue; /* if interrupted, just retry */
607 0 : ereport(COMMERROR,
608 : (errcode_for_socket_access(),
609 : errmsg("failed to send SSL negotiation response: %m")));
610 0 : return STATUS_ERROR; /* close the connection */
611 : }
612 :
613 : #ifdef USE_SSL
614 542 : if (SSLok == 'S' && secure_open_server(port) == -1)
615 38 : 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 502 : if (pq_buffer_remaining_data() > 0)
625 0 : ereport(FATAL,
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 502 : return ProcessStartupPacket(port, true, SSLok == 'S');
636 : }
637 27912 : else if (proto == NEGOTIATE_GSS_CODE && !gss_done)
638 : {
639 0 : 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 :
647 0 : if (Trace_connection_negotiation)
648 : {
649 0 : if (GSSok == 'G')
650 0 : ereport(LOG,
651 : (errmsg("GSSENCRequest accepted")));
652 : else
653 0 : ereport(LOG,
654 : (errmsg("GSSENCRequest rejected")));
655 : }
656 :
657 0 : while (secure_write(port, &GSSok, 1) != 1)
658 : {
659 0 : if (errno == EINTR)
660 0 : continue;
661 0 : ereport(COMMERROR,
662 : (errcode_for_socket_access(),
663 : errmsg("failed to send GSSAPI negotiation response: %m")));
664 0 : 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 0 : if (pq_buffer_remaining_data() > 0)
679 0 : ereport(FATAL,
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 0 : 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 : */
702 27912 : FrontendProtocol = Min(proto, PG_PROTOCOL_LATEST);
703 :
704 : /* Check that the major protocol version is in range. */
705 27912 : if (PG_PROTOCOL_MAJOR(proto) < PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST) ||
706 27912 : PG_PROTOCOL_MAJOR(proto) > PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST))
707 0 : ereport(FATAL,
708 : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
709 : errmsg("unsupported frontend protocol %u.%u: server supports %u.0 to %u.%u",
710 : PG_PROTOCOL_MAJOR(proto), PG_PROTOCOL_MINOR(proto),
711 : PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST),
712 : PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST),
713 : PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST))));
714 :
715 : /*
716 : * Now fetch parameters out of startup packet and save them into the Port
717 : * structure.
718 : */
719 27912 : oldcontext = MemoryContextSwitchTo(TopMemoryContext);
720 :
721 : /* Handle protocol version 3 startup packet */
722 : {
723 27912 : int32 offset = sizeof(ProtocolVersion);
724 27912 : 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 27912 : port->guc_options = NIL;
732 :
733 131894 : while (offset < len)
734 : {
735 131894 : char *nameptr = buf + offset;
736 : int32 valoffset;
737 : char *valptr;
738 :
739 131894 : if (*nameptr == '\0')
740 27912 : break; /* found packet terminator */
741 103982 : valoffset = offset + strlen(nameptr) + 1;
742 103982 : if (valoffset >= len)
743 0 : break; /* missing value, will complain below */
744 103982 : valptr = buf + valoffset;
745 :
746 103982 : if (strcmp(nameptr, "database") == 0)
747 27912 : port->database_name = pstrdup(valptr);
748 76070 : else if (strcmp(nameptr, "user") == 0)
749 27912 : port->user_name = pstrdup(valptr);
750 48158 : else if (strcmp(nameptr, "options") == 0)
751 7326 : port->cmdline_options = pstrdup(valptr);
752 40832 : 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 2266 : if (strcmp(valptr, "database") == 0)
762 : {
763 1314 : am_walsender = true;
764 1314 : am_db_walsender = true;
765 : }
766 952 : else if (!parse_bool(valptr, &am_walsender))
767 0 : ereport(FATAL,
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 38566 : 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 0 : lappend(unrecognized_protocol_options, pstrdup(nameptr));
783 : }
784 : else
785 : {
786 : /* Assume it's a generic GUC option */
787 38566 : port->guc_options = lappend(port->guc_options,
788 38566 : pstrdup(nameptr));
789 38566 : port->guc_options = lappend(port->guc_options,
790 38566 : 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 38566 : if (strcmp(nameptr, "application_name") == 0)
799 : {
800 27902 : port->application_name = pg_clean_ascii(valptr, 0);
801 : }
802 : }
803 103982 : 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 27912 : if (offset != len - 1)
811 0 : ereport(FATAL,
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 : */
821 27912 : if (PG_PROTOCOL_MINOR(proto) > PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST) ||
822 : unrecognized_protocol_options != NIL)
823 0 : SendNegotiateProtocolVersion(unrecognized_protocol_options);
824 : }
825 :
826 : /* Check a user name was given. */
827 27912 : if (port->user_name == NULL || port->user_name[0] == '\0')
828 0 : ereport(FATAL,
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 27912 : if (port->database_name == NULL || port->database_name[0] == '\0')
834 0 : 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 27912 : if (strlen(port->database_name) >= NAMEDATALEN)
841 0 : port->database_name[NAMEDATALEN - 1] = '\0';
842 27912 : if (strlen(port->user_name) >= NAMEDATALEN)
843 0 : port->user_name[NAMEDATALEN - 1] = '\0';
844 :
845 27912 : if (am_walsender)
846 2266 : MyBackendType = B_WAL_SENDER;
847 : else
848 25646 : MyBackendType = B_BACKEND;
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 : */
858 27912 : if (am_walsender && !am_db_walsender)
859 952 : port->database_name[0] = '\0';
860 :
861 : /*
862 : * Done filling the Port structure
863 : */
864 27912 : MemoryContextSwitchTo(oldcontext);
865 :
866 27912 : return STATUS_OK;
867 : }
868 :
869 : /*
870 : * The client has sent a cancel request packet, not a normal
871 : * start-a-new-connection packet. Perform the necessary processing. Nothing
872 : * is sent back to the client.
873 : */
874 : static void
875 32 : ProcessCancelRequestPacket(Port *port, void *pkt, int pktlen)
876 : {
877 : CancelRequestPacket *canc;
878 : int len;
879 :
880 32 : if (pktlen < offsetof(CancelRequestPacket, cancelAuthCode))
881 : {
882 0 : ereport(COMMERROR,
883 : (errcode(ERRCODE_PROTOCOL_VIOLATION),
884 : errmsg("invalid length of query cancel packet")));
885 0 : return;
886 : }
887 32 : len = pktlen - offsetof(CancelRequestPacket, cancelAuthCode);
888 32 : if (len == 0 || len > 256)
889 : {
890 0 : ereport(COMMERROR,
891 : (errcode(ERRCODE_PROTOCOL_VIOLATION),
892 : errmsg("invalid length of query cancel key")));
893 0 : return;
894 : }
895 :
896 32 : canc = (CancelRequestPacket *) pkt;
897 32 : SendCancelRequest(pg_ntoh32(canc->backendPID), canc->cancelAuthCode, len);
898 : }
899 :
900 : /*
901 : * Send a NegotiateProtocolVersion to the client. This lets the client know
902 : * that they have either requested a newer minor protocol version than we are
903 : * able to speak, or at least one protocol option that we don't understand, or
904 : * possibly both. FrontendProtocol has already been set to the version
905 : * requested by the client or the highest version we know how to speak,
906 : * whichever is older. If the highest version that we know how to speak is too
907 : * old for the client, it can abandon the connection.
908 : *
909 : * We also include in the response a list of protocol options we didn't
910 : * understand. This allows clients to include optional parameters that might
911 : * be present either in newer protocol versions or third-party protocol
912 : * extensions without fear of having to reconnect if those options are not
913 : * understood, while at the same time making certain that the client is aware
914 : * of which options were actually accepted.
915 : */
916 : static void
917 0 : SendNegotiateProtocolVersion(List *unrecognized_protocol_options)
918 : {
919 : StringInfoData buf;
920 : ListCell *lc;
921 :
922 0 : pq_beginmessage(&buf, PqMsg_NegotiateProtocolVersion);
923 0 : pq_sendint32(&buf, FrontendProtocol);
924 0 : pq_sendint32(&buf, list_length(unrecognized_protocol_options));
925 0 : foreach(lc, unrecognized_protocol_options)
926 0 : pq_sendstring(&buf, lfirst(lc));
927 0 : pq_endmessage(&buf);
928 :
929 : /* no need to flush, some other message will follow */
930 0 : }
931 :
932 :
933 : /*
934 : * SIGTERM while processing startup packet.
935 : *
936 : * Running proc_exit() from a signal handler would be quite unsafe.
937 : * However, since we have not yet touched shared memory, we can just
938 : * pull the plug and exit without running any atexit handlers.
939 : *
940 : * One might be tempted to try to send a message, or log one, indicating
941 : * why we are disconnecting. However, that would be quite unsafe in itself.
942 : * Also, it seems undesirable to provide clues about the database's state
943 : * to a client that has not yet completed authentication, or even sent us
944 : * a startup packet.
945 : */
946 : static void
947 0 : process_startup_packet_die(SIGNAL_ARGS)
948 : {
949 0 : _exit(1);
950 : }
951 :
952 : /*
953 : * Timeout while processing startup packet.
954 : * As for process_startup_packet_die(), we exit via _exit(1).
955 : */
956 : static void
957 0 : StartupPacketTimeoutHandler(void)
958 : {
959 0 : _exit(1);
960 : }
961 :
962 : /*
963 : * Helper for the log_connections GUC check hook.
964 : *
965 : * `elemlist` is a listified version of the string input passed to the
966 : * log_connections GUC check hook, check_log_connections().
967 : * check_log_connections() is responsible for cleaning up `elemlist`.
968 : *
969 : * validate_log_connections_options() returns false if an error was
970 : * encountered and the GUC input could not be validated and true otherwise.
971 : *
972 : * `flags` returns the flags that should be stored in the log_connections GUC
973 : * by its assign hook.
974 : */
975 : static bool
976 2408 : validate_log_connections_options(List *elemlist, uint32 *flags)
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 2408 : *flags = 0;
1001 :
1002 : /* If an empty string was passed, we're done */
1003 2408 : if (list_length(elemlist) == 0)
1004 2176 : 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 232 : item = linitial(elemlist);
1012 :
1013 1402 : for (size_t i = 0; i < lengthof(compat_options); i++)
1014 : {
1015 1352 : struct config_enum_entry option = compat_options[i];
1016 :
1017 1352 : if (pg_strcasecmp(item, option.name) != 0)
1018 1170 : continue;
1019 :
1020 182 : if (list_length(elemlist) > 1)
1021 : {
1022 0 : GUC_check_errdetail("Cannot specify log_connections option \"%s\" in a list with other options.",
1023 : item);
1024 182 : return false;
1025 : }
1026 :
1027 182 : *flags = option.val;
1028 182 : return true;
1029 : }
1030 :
1031 : /* Now check the aspect options. The empty string was already handled */
1032 108 : 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 58 : item = lfirst(l);
1043 262 : for (size_t i = 0; i < lengthof(options); i++)
1044 : {
1045 262 : struct config_enum_entry option = options[i];
1046 :
1047 262 : if (pg_strcasecmp(item, option.name) == 0)
1048 : {
1049 58 : *flags |= option.val;
1050 58 : goto next;
1051 : }
1052 : }
1053 :
1054 0 : GUC_check_errdetail("Invalid option \"%s\".", item);
1055 0 : return false;
1056 :
1057 58 : next: ;
1058 : }
1059 :
1060 50 : return true;
1061 : }
1062 :
1063 :
1064 : /*
1065 : * GUC check hook for log_connections
1066 : */
1067 : bool
1068 2408 : check_log_connections(char **newval, void **extra, GucSource source)
1069 : {
1070 : uint32 flags;
1071 : char *rawstring;
1072 : List *elemlist;
1073 : bool success;
1074 :
1075 : /* Need a modifiable copy of string */
1076 2408 : rawstring = pstrdup(*newval);
1077 :
1078 2408 : if (!SplitIdentifierString(rawstring, ',', &elemlist))
1079 : {
1080 0 : GUC_check_errdetail("Invalid list syntax in parameter \"log_connections\".");
1081 0 : pfree(rawstring);
1082 0 : list_free(elemlist);
1083 0 : return false;
1084 : }
1085 :
1086 : /* Validation logic is all in the helper */
1087 2408 : success = validate_log_connections_options(elemlist, &flags);
1088 :
1089 : /* Time for cleanup */
1090 2408 : pfree(rawstring);
1091 2408 : list_free(elemlist);
1092 :
1093 2408 : if (!success)
1094 0 : return false;
1095 :
1096 : /*
1097 : * We succeeded, so allocate `extra` and save the flags there for use by
1098 : * assign_log_connections().
1099 : */
1100 2408 : *extra = guc_malloc(LOG, sizeof(int));
1101 2408 : if (!*extra)
1102 0 : return false;
1103 2408 : *((int *) *extra) = flags;
1104 :
1105 2408 : return true;
1106 : }
1107 :
1108 : /*
1109 : * GUC assign hook for log_connections
1110 : */
1111 : void
1112 2400 : assign_log_connections(const char *newval, void *extra)
1113 : {
1114 2400 : log_connections = *((int *) extra);
1115 2400 : }
|