LCOV - code coverage report
Current view: top level - src/backend/tcop - backend_startup.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 173 228 75.9 %
Date: 2024-11-21 08:14:44 Functions: 4 7 57.1 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14