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