LCOV - differential code coverage report
Current view: top level - src/backend/tcop - backend_startup.c (source / functions) Coverage Total Hit UNC UBC GBC GNC CBC DUB DCB
Current: 380a8b2ea024c33a35e7abc8628e7c4f52f9f9f9 vs db5ed03217b9c238703df8b4b286115d6e940488 Lines: 83.8 % 309 259 5 45 10 20 229 5 7
Current Date: 2026-05-29 21:51:00 -0400 Functions: 81.8 % 11 9 2 1 2 6 1
Baseline: lcov-20260530-034037-baseline Branches: 61.8 % 285 176 1 108 7 5 164
Baseline Date: 2026-05-29 14:39:03 -0700 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(7,30] days: 100.0 % 15 15 6 9
(30,360] days: 70.0 % 20 14 5 1 14
(360..) days: 83.9 % 274 230 44 10 220
Function coverage date bins:
(7,30] days: 100.0 % 1 1 1
(360..) days: 80.0 % 10 8 2 1 1 6
Branch coverage date bins:
(7,30] days: 100.0 % 4 4 4
(30,360] days: 83.3 % 6 5 1 5
(360..) days: 60.7 % 275 167 108 7 160

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * backend_startup.c
                                  4                 :                :  *    Backend startup code
                                  5                 :                :  *
                                  6                 :                :  * Portions Copyright (c) 1996-2026, 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);
                                 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
  463 peter@eisentraut.org       76                 :CBC       15225 : BackendMain(const void *startup_data, size_t startup_data_len)
                                 77                 :                : {
                                 78                 :          15225 :     const BackendStartupData *bsdata = startup_data;
                                 79                 :                : 
  803 heikki.linnakangas@i       80         [ -  + ]:          15225 :     Assert(startup_data_len == sizeof(BackendStartupData));
                                 81         [ -  + ]:          15225 :     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                 :          15225 :     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                 :          14868 :     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                 :          14865 :     MemoryContextSwitchTo(TopMemoryContext);
                                123                 :                : 
                                124                 :          14865 :     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                 :          15225 : 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                 :          15225 :     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         [ -  + ]:          15225 :     if (PreAuthDelay > 0)
  803 heikki.linnakangas@i      162                 :UBC           0 :         pg_usleep(PreAuthDelay * 1000000L);
                                163                 :                : 
                                164                 :                :     /* This flag will remain set until InitPostgres finishes authentication */
  803 heikki.linnakangas@i      165                 :CBC       15225 :     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                 :          15225 :     oldcontext = MemoryContextSwitchTo(TopMemoryContext);
                                177                 :          15225 :     port = MyProcPort = pq_init(client_sock);
                                178                 :          15225 :     MemoryContextSwitchTo(oldcontext);
                                179                 :                : 
                                180                 :          15225 :     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                 :          15225 :     port->remote_host = "";
                                184                 :          15225 :     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                 :          15225 :     pqsignal(SIGTERM, process_startup_packet_die);
                                197                 :                :     /* SIGQUIT handler was already set up by InitPostmasterChild */
                                198                 :          15225 :     InitializeTimeouts();       /* establishes SIGALRM handler */
                                199                 :          15225 :     sigprocmask(SIG_SETMASK, &StartupBlockSig, NULL);
                                200                 :                : 
                                201                 :                :     /*
                                202                 :                :      * Get the remote host name and port for logging and status display.
                                203                 :                :      */
                                204                 :          15225 :     remote_host[0] = '\0';
                                205                 :          15225 :     remote_port[0] = '\0';
                                206   [ +  +  -  + ]:          15225 :     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)
  803 heikki.linnakangas@i      210         [ #  # ]:UBC           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                 :                :      */
  698 tgl@sss.pgh.pa.us         218                 :CBC       15225 :     port->remote_host = MemoryContextStrdup(TopMemoryContext, remote_host);
                                219                 :          15225 :     port->remote_port = MemoryContextStrdup(TopMemoryContext, remote_port);
                                220                 :                : 
                                221                 :                :     /* And now we can log that the connection was received, if enabled */
  444 melanieplageman@gmai      222         [ +  + ]:          15225 :     if (log_connections & LOG_CONNECTION_RECEIPT)
                                223                 :                :     {
  803 heikki.linnakangas@i      224         [ +  + ]:            747 :         if (remote_port[0])
                                225         [ +  - ]:            386 :             ereport(LOG,
                                226                 :                :                     (errmsg("connection received: host=%s port=%s",
                                227                 :                :                             remote_host,
                                228                 :                :                             remote_port)));
                                229                 :                :         else
                                230         [ +  - ]:            361 :             ereport(LOG,
                                231                 :                :                     (errmsg("connection received: host=%s",
                                232                 :                :                             remote_host)));
                                233                 :                :     }
                                234                 :                : 
                                235                 :                :     /* For testing client error handling */
                                236                 :                : #ifdef USE_INJECTION_POINTS
  385 michael@paquier.xyz       237                 :          15225 :     INJECTION_POINT("backend-initialize", NULL);
  673 heikki.linnakangas@i      238         [ -  + ]:          15225 :     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                 :                :          */
  673 heikki.linnakangas@i      245                 :UBC           0 :         FrontendProtocol = PG_PROTOCOL(2, 0);
                                246         [ #  # ]:              0 :         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                 :                :      */
  803 heikki.linnakangas@i      261   [ +  +  +  - ]:CBC       15225 :     if (log_hostname &&
                                262                 :            159 :         ret == 0 &&
                                263         [ +  - ]:            159 :         strspn(remote_host, "0123456789.") < strlen(remote_host) &&
                                264         [ +  - ]:            159 :         strspn(remote_host, "0123456789ABCDEFabcdef:") < strlen(remote_host))
                                265                 :                :     {
  698 tgl@sss.pgh.pa.us         266                 :            159 :         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                 :                :      */
  803 heikki.linnakangas@i      284                 :          15225 :     RegisterTimeout(STARTUP_PACKET_TIMEOUT, StartupPacketTimeoutHandler);
                                285                 :          15225 :     enable_timeout_after(STARTUP_PACKET_TIMEOUT, AuthenticationTimeout * 1000);
                                286                 :                : 
                                287                 :                :     /* Handle direct SSL handshake */
  782                           288                 :          15225 :     status = ProcessSSLStartup(port);
                                289                 :                : 
                                290                 :                :     /*
                                291                 :                :      * Receive the startup packet (which might turn out to be a cancel request
                                292                 :                :      * packet).
                                293                 :                :      */
                                294         [ +  + ]:          15225 :     if (status == STATUS_OK)
   13 michael@paquier.xyz       295                 :GNC       15217 :         status = ProcessStartupPacket(port);
                                296                 :                : 
                                297                 :                :     /*
                                298                 :                :      * If we're going to reject the connection due to database state, say so
                                299                 :                :      * now instead of wasting cycles on an authentication exchange. (This also
                                300                 :                :      * allows a pg_ping utility to be written.)
                                301                 :                :      */
  803 heikki.linnakangas@i      302         [ +  + ]:CBC       15222 :     if (status == STATUS_OK)
                                303                 :                :     {
                                304   [ +  +  +  +  :          15148 :         switch (cac)
                                           +  +  - ]
                                305                 :                :         {
                                306                 :            223 :             case CAC_STARTUP:
                                307         [ +  - ]:            223 :                 ereport(FATAL,
                                308                 :                :                         (errcode(ERRCODE_CANNOT_CONNECT_NOW),
                                309                 :                :                          errmsg("the database system is starting up")));
                                310                 :                :                 break;
  423 fujii@postgresql.org      311                 :              4 :             case CAC_NOTHOTSTANDBY:
                                312         [ -  + ]:              4 :                 if (!EnableHotStandby)
  423 fujii@postgresql.org      313         [ #  # ]:UBC           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.")));
  423 fujii@postgresql.org      317         [ -  + ]:CBC           4 :                 else if (reachedConsistency)
  803 heikki.linnakangas@i      318         [ #  # ]:UBC           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
  803 heikki.linnakangas@i      325         [ +  - ]:CBC           4 :                     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                 :             47 :             case CAC_SHUTDOWN:
                                331         [ +  - ]:             47 :                 ereport(FATAL,
                                332                 :                :                         (errcode(ERRCODE_CANNOT_CONNECT_NOW),
                                333                 :                :                          errmsg("the database system is shutting down")));
                                334                 :                :                 break;
                                335                 :              5 :             case CAC_RECOVERY:
                                336         [ +  - ]:              5 :                 ereport(FATAL,
                                337                 :                :                         (errcode(ERRCODE_CANNOT_CONNECT_NOW),
                                338                 :                :                          errmsg("the database system is in recovery mode")));
                                339                 :                :                 break;
                                340                 :              1 :             case CAC_TOOMANY:
                                341         [ +  - ]:              1 :                 ereport(FATAL,
                                342                 :                :                         (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
                                343                 :                :                          errmsg("sorry, too many clients already")));
                                344                 :                :                 break;
                                345                 :          14868 :             case CAC_OK:
                                346                 :          14868 :                 break;
                                347                 :                :         }
                                348                 :                :     }
                                349                 :                : 
                                350                 :                :     /*
                                351                 :                :      * Disable the timeout, and prevent SIGTERM again.
                                352                 :                :      */
                                353                 :          14942 :     disable_timeout(STARTUP_PACKET_TIMEOUT, false);
                                354                 :          14942 :     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                 :          14942 :     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         [ +  + ]:          14942 :     if (status != STATUS_OK)
                                372                 :             74 :         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                 :          14868 :     initStringInfo(&ps_data);
                                379         [ +  + ]:          14868 :     if (am_walsender)
                                380                 :           1289 :         appendStringInfo(&ps_data, "%s ", GetBackendTypeDesc(B_WAL_SENDER));
                                381                 :          14868 :     appendStringInfo(&ps_data, "%s ", port->user_name);
                                382         [ +  + ]:          14868 :     if (port->database_name[0] != '\0')
                                383                 :          14355 :         appendStringInfo(&ps_data, "%s ", port->database_name);
                                384                 :          14868 :     appendStringInfoString(&ps_data, port->remote_host);
                                385         [ +  + ]:          14868 :     if (port->remote_port[0] != '\0')
                                386                 :            327 :         appendStringInfo(&ps_data, "(%s)", port->remote_port);
                                387                 :                : 
                                388                 :          14868 :     init_ps_display(ps_data.data);
                                389                 :          14868 :     pfree(ps_data.data);
                                390                 :                : 
                                391                 :          14868 :     set_ps_display("initializing");
                                392                 :          14868 : }
                                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
  782                           401                 :          15225 : ProcessSSLStartup(Port *port)
                                402                 :                : {
                                403                 :                :     int         firstbyte;
                                404                 :                : 
                                405         [ -  + ]:          15225 :     Assert(!port->ssl_in_use);
                                406                 :                : 
                                407                 :          15225 :     pq_startmsgread();
                                408                 :          15225 :     firstbyte = pq_peekbyte();
                                409                 :          15225 :     pq_endmsgread();
                                410         [ +  + ]:          15225 :     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                 :              2 :         return STATUS_ERROR;
                                417                 :                :     }
                                418                 :                : 
                                419         [ +  + ]:          15223 :     if (firstbyte != 0x16)
                                420                 :                :     {
                                421                 :                :         /* Not an SSL handshake message */
                                422                 :          15207 :         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   [ +  +  -  + ]:             16 :     if (!LoadedSSL || port->laddr.addr.ss_family == AF_UNIX)
                                434                 :                :     {
                                435                 :                :         /* SSL not supported */
                                436                 :              6 :         goto reject;
                                437                 :                :     }
                                438                 :                : 
                                439         [ -  + ]:             10 :     if (secure_open_server(port) == -1)
                                440                 :                :     {
                                441                 :                :         /*
                                442                 :                :          * we assume secure_open_server() sent an appropriate TLS alert
                                443                 :                :          * already
                                444                 :                :          */
  782 heikki.linnakangas@i      445                 :UBC           0 :         goto reject;
                                446                 :                :     }
  782 heikki.linnakangas@i      447         [ -  + ]:CBC          10 :     Assert(port->ssl_in_use);
                                448                 :                : 
                                449         [ -  + ]:             10 :     if (!port->alpn_used)
                                450                 :                :     {
  782 heikki.linnakangas@i      451         [ #  # ]:UBC           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                 :                : 
  782 heikki.linnakangas@i      457         [ +  - ]:CBC          10 :     if (Trace_connection_negotiation)
                                458         [ +  - ]:             10 :         ereport(LOG,
                                459                 :                :                 (errmsg("direct SSL connection accepted")));
                                460                 :             10 :     return STATUS_OK;
                                461                 :                : #else
                                462                 :                :     /* SSL not supported by this build */
                                463                 :                :     goto reject;
                                464                 :                : #endif
                                465                 :                : 
                                466                 :              6 : reject:
                                467         [ +  - ]:              6 :     if (Trace_connection_negotiation)
                                468         [ +  - ]:              6 :         ereport(LOG,
                                469                 :                :                 (errmsg("direct SSL connection rejected")));
                                470                 :              6 :     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                 :                :  */
                                485                 :                : static int
   13 michael@paquier.xyz       486                 :GNC       15217 : ProcessStartupPacket(Port *port)
                                487                 :                : {
                                488                 :                :     int32       len;
  301 tgl@sss.pgh.pa.us         489                 :          15217 :     char       *buf = NULL;
                                490                 :                :     ProtocolVersion proto;
                                491                 :                :     MemoryContext oldcontext;
                                492                 :                :     bool        gss_done;
                                493                 :                :     bool        ssl_done;
                                494                 :                : 
                                495                 :                :     /*
                                496                 :                :      * Set ssl_done and/or gss_done when negotiation of an encrypted layer
                                497                 :                :      * (currently, TLS or GSSAPI) is completed.  A successful negotiation of
                                498                 :                :      * either encryption layer sets both flags, but a rejected negotiation
                                499                 :                :      * sets only the flag for that layer, since the client may wish to try the
                                500                 :                :      * other one.  We should make no assumption here about the order in which
                                501                 :                :      * the client may make requests.
                                502                 :                :      */
   13 michael@paquier.xyz       503                 :          15217 :     gss_done = false;
                                504                 :          15217 :     ssl_done = false;
                                505                 :                : 
   19 michael@paquier.xyz       506                 :CBC         301 : retry:
  803 heikki.linnakangas@i      507                 :          15518 :     pq_startmsgread();
                                508                 :                : 
                                509                 :                :     /*
                                510                 :                :      * Grab the first byte of the length word separately, so that we can tell
                                511                 :                :      * whether we have no data at all or an incomplete packet.  (This might
                                512                 :                :      * sound inefficient, but it's not really, because of buffering in
                                513                 :                :      * pqcomm.c.)
                                514                 :                :      */
  461 peter@eisentraut.org      515         [ +  + ]:          15518 :     if (pq_getbytes(&len, 1) == EOF)
                                516                 :                :     {
                                517                 :                :         /*
                                518                 :                :          * If we get no data at all, don't clutter the log with a complaint;
                                519                 :                :          * such cases often occur for legitimate reasons.  An example is that
                                520                 :                :          * we might be here after responding to NEGOTIATE_SSL_CODE, and if the
                                521                 :                :          * client didn't like our response, it'll probably just drop the
                                522                 :                :          * connection.  Service-monitoring software also often just opens and
                                523                 :                :          * closes a connection without sending anything.  (So do port
                                524                 :                :          * scanners, which may be less benign, but it's not really our job to
                                525                 :                :          * notice those.)
                                526                 :                :          */
  301 tgl@sss.pgh.pa.us         527                 :GNC          20 :         goto fail;
                                528                 :                :     }
                                529                 :                : 
  803 heikki.linnakangas@i      530         [ -  + ]:CBC       15498 :     if (pq_getbytes(((char *) &len) + 1, 3) == EOF)
                                531                 :                :     {
                                532                 :                :         /* Got a partial length word, so bleat about that */
  803 heikki.linnakangas@i      533   [ #  #  #  # ]:UBC           0 :         if (!ssl_done && !gss_done)
                                534         [ #  # ]:              0 :             ereport(COMMERROR,
                                535                 :                :                     (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                536                 :                :                      errmsg("incomplete startup packet")));
  301 tgl@sss.pgh.pa.us         537                 :UNC           0 :         goto fail;
                                538                 :                :     }
                                539                 :                : 
  803 heikki.linnakangas@i      540                 :CBC       15498 :     len = pg_ntoh32(len);
                                541                 :          15498 :     len -= 4;
                                542                 :                : 
                                543         [ +  - ]:          15498 :     if (len < (int32) sizeof(ProtocolVersion) ||
                                544         [ -  + ]:          15498 :         len > MAX_STARTUP_PACKET_LENGTH)
                                545                 :                :     {
  803 heikki.linnakangas@i      546         [ #  # ]:UBC           0 :         ereport(COMMERROR,
                                547                 :                :                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                548                 :                :                  errmsg("invalid length of startup packet")));
  301 tgl@sss.pgh.pa.us         549                 :UNC           0 :         goto fail;
                                550                 :                :     }
                                551                 :                : 
                                552                 :                :     /*
                                553                 :                :      * Allocate space to hold the startup packet, plus one extra byte that's
                                554                 :                :      * initialized to be zero.  This ensures we will have null termination of
                                555                 :                :      * all strings inside the packet.
                                556                 :                :      */
  803 heikki.linnakangas@i      557                 :CBC       15498 :     buf = palloc(len + 1);
                                558                 :          15498 :     buf[len] = '\0';
                                559                 :                : 
                                560         [ -  + ]:          15498 :     if (pq_getbytes(buf, len) == EOF)
                                561                 :                :     {
  803 heikki.linnakangas@i      562         [ #  # ]:UBC           0 :         ereport(COMMERROR,
                                563                 :                :                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                564                 :                :                  errmsg("incomplete startup packet")));
  301 tgl@sss.pgh.pa.us         565                 :UNC           0 :         goto fail;
                                566                 :                :     }
  803 heikki.linnakangas@i      567                 :CBC       15498 :     pq_endmsgread();
                                568                 :                : 
                                569                 :                :     /*
                                570                 :                :      * The first field is either a protocol version number or a special
                                571                 :                :      * request code.
                                572                 :                :      */
                                573                 :          15498 :     port->proto = proto = pg_ntoh32(*((ProtocolVersion *) buf));
                                574                 :                : 
                                575         [ +  + ]:          15498 :     if (proto == CANCEL_REQUEST_CODE)
                                576                 :                :     {
  423                           577                 :             15 :         ProcessCancelRequestPacket(port, buf, len);
                                578                 :                :         /* Not really an error, but we don't want to proceed further */
  301 tgl@sss.pgh.pa.us         579                 :GNC          15 :         goto fail;
                                580                 :                :     }
                                581                 :                : 
  803 heikki.linnakangas@i      582   [ +  +  +  + ]:CBC       15483 :     if (proto == NEGOTIATE_SSL_CODE && !ssl_done)
                                583                 :                :     {
                                584                 :                :         char        SSLok;
                                585                 :                : 
                                586                 :                : #ifdef USE_SSL
                                587                 :                : 
                                588                 :                :         /*
                                589                 :                :          * No SSL when disabled or on Unix sockets.
                                590                 :                :          *
                                591                 :                :          * Also no SSL negotiation if we already have a direct SSL connection
                                592                 :                :          */
  782                           593   [ +  +  +  -  :            211 :         if (!LoadedSSL || port->laddr.addr.ss_family == AF_UNIX || port->ssl_in_use)
                                              -  + ]
  803                           594                 :             28 :             SSLok = 'N';
                                595                 :                :         else
                                596                 :            183 :             SSLok = 'S';        /* Support for SSL */
                                597                 :                : #else
                                598                 :                :         SSLok = 'N';            /* No support for SSL */
                                599                 :                : #endif
                                600                 :                : 
  782                           601         [ +  + ]:            211 :         if (Trace_connection_negotiation)
                                602                 :                :         {
                                603         [ +  + ]:             39 :             if (SSLok == 'S')
                                604         [ +  - ]:             25 :                 ereport(LOG,
                                605                 :                :                         (errmsg("SSLRequest accepted")));
                                606                 :                :             else
                                607         [ +  - ]:             14 :                 ereport(LOG,
                                608                 :                :                         (errmsg("SSLRequest rejected")));
                                609                 :                :         }
                                610                 :                : 
                                611         [ -  + ]:            211 :         while (secure_write(port, &SSLok, 1) != 1)
                                612                 :                :         {
  803 heikki.linnakangas@i      613         [ #  # ]:UBC           0 :             if (errno == EINTR)
  782                           614                 :              0 :                 continue;       /* if interrupted, just retry */
  803                           615         [ #  # ]:              0 :             ereport(COMMERROR,
                                616                 :                :                     (errcode_for_socket_access(),
                                617                 :                :                      errmsg("failed to send SSL negotiation response: %m")));
  301 tgl@sss.pgh.pa.us         618                 :GNC          31 :             goto fail;          /* close the connection */
                                619                 :                :         }
                                620                 :                : 
                                621                 :                : #ifdef USE_SSL
  803 heikki.linnakangas@i      622   [ +  +  +  + ]:CBC         211 :         if (SSLok == 'S' && secure_open_server(port) == -1)
  301 tgl@sss.pgh.pa.us         623                 :GNC          31 :             goto fail;
                                624                 :                : #endif
                                625                 :                : 
                                626                 :            179 :         pfree(buf);
   19 michael@paquier.xyz       627                 :            179 :         buf = NULL;
                                628                 :                : 
                                629                 :                :         /*
                                630                 :                :          * At this point we should have no data already buffered.  If we do,
                                631                 :                :          * it was received before we performed the SSL handshake, so it wasn't
                                632                 :                :          * encrypted and indeed may have been injected by a man-in-the-middle.
                                633                 :                :          * We report this case to the client.
                                634                 :                :          */
  782 heikki.linnakangas@i      635         [ -  + ]:CBC         179 :         if (pq_buffer_remaining_data() > 0)
  803 heikki.linnakangas@i      636         [ #  # ]:UBC           0 :             ereport(FATAL,
                                637                 :                :                     (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                638                 :                :                      errmsg("received unencrypted data after SSL request"),
                                639                 :                :                      errdetail("This could be either a client-software bug or evidence of an attempted man-in-the-middle attack.")));
                                640                 :                : 
                                641                 :                :         /*
                                642                 :                :          * regular startup packet, cancel, etc packet should follow, but not
                                643                 :                :          * another SSL negotiation request, and a GSS request should only
                                644                 :                :          * follow if SSL was rejected (client may negotiate in either order)
                                645                 :                :          */
   19 michael@paquier.xyz       646                 :CBC         179 :         ssl_done = true;
                                647         [ +  + ]:            179 :         if (SSLok == 'S')
                                648                 :                :         {
                                649                 :                :             /*
                                650                 :                :              * We are done with SSL and negotiated correctly, so consider the
                                651                 :                :              * same for GSS.
                                652                 :                :              */
                                653                 :            151 :             gss_done = true;
                                654                 :                :         }
                                655                 :            179 :         goto retry;
                                656                 :                :     }
  803 heikki.linnakangas@i      657   [ +  +  +  - ]:          15272 :     else if (proto == NEGOTIATE_GSS_CODE && !gss_done)
                                658                 :                :     {
                                659                 :            123 :         char        GSSok = 'N';
                                660                 :                : 
                                661                 :                : #ifdef ENABLE_GSS
                                662                 :                :         /* No GSSAPI encryption when on Unix socket */
                                663         [ +  + ]:            123 :         if (port->laddr.addr.ss_family != AF_UNIX)
                                664                 :            122 :             GSSok = 'G';
                                665                 :                : #endif
                                666                 :                : 
  782                           667         [ +  + ]:            123 :         if (Trace_connection_negotiation)
                                668                 :                :         {
                                669         [ +  + ]:             83 :             if (GSSok == 'G')
                                670         [ +  - ]:             82 :                 ereport(LOG,
                                671                 :                :                         (errmsg("GSSENCRequest accepted")));
                                672                 :                :             else
                                673         [ +  - ]:              1 :                 ereport(LOG,
                                674                 :                :                         (errmsg("GSSENCRequest rejected")));
                                675                 :                :         }
                                676                 :                : 
                                677         [ -  + ]:            123 :         while (secure_write(port, &GSSok, 1) != 1)
                                678                 :                :         {
  803 heikki.linnakangas@i      679         [ #  # ]:UBC           0 :             if (errno == EINTR)
                                680                 :              0 :                 continue;
                                681         [ #  # ]:              0 :             ereport(COMMERROR,
                                682                 :                :                     (errcode_for_socket_access(),
                                683                 :                :                      errmsg("failed to send GSSAPI negotiation response: %m")));
  301 tgl@sss.pgh.pa.us         684                 :UNC           0 :             goto fail;          /* close the connection */
                                685                 :                :         }
                                686                 :                : 
                                687                 :                : #ifdef ENABLE_GSS
  803 heikki.linnakangas@i      688   [ +  +  -  + ]:CBC         123 :         if (GSSok == 'G' && secure_open_gssapi(port) == -1)
  301 tgl@sss.pgh.pa.us         689                 :UNC           0 :             goto fail;
                                690                 :                : #endif
                                691                 :                : 
  301 tgl@sss.pgh.pa.us         692                 :GNC         122 :         pfree(buf);
   19 michael@paquier.xyz       693                 :            122 :         buf = NULL;
                                694                 :                : 
                                695                 :                :         /*
                                696                 :                :          * At this point we should have no data already buffered.  If we do,
                                697                 :                :          * it was received before we performed the GSS handshake, so it wasn't
                                698                 :                :          * encrypted and indeed may have been injected by a man-in-the-middle.
                                699                 :                :          * We report this case to the client.
                                700                 :                :          */
  782 heikki.linnakangas@i      701         [ -  + ]:CBC         122 :         if (pq_buffer_remaining_data() > 0)
  803 heikki.linnakangas@i      702         [ #  # ]:UBC           0 :             ereport(FATAL,
                                703                 :                :                     (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                704                 :                :                      errmsg("received unencrypted data after GSSAPI encryption request"),
                                705                 :                :                      errdetail("This could be either a client-software bug or evidence of an attempted man-in-the-middle attack.")));
                                706                 :                : 
                                707                 :                :         /*
                                708                 :                :          * regular startup packet, cancel, etc packet should follow, but not
                                709                 :                :          * another GSS negotiation request, and an SSL request should only
                                710                 :                :          * follow if GSS was rejected (client may negotiate in either order)
                                711                 :                :          */
   19 michael@paquier.xyz       712                 :CBC         122 :         gss_done = true;
                                713         [ +  + ]:            122 :         if (GSSok == 'G')
                                714                 :                :         {
                                715                 :                :             /*
                                716                 :                :              * We are done with GSS and negotiated correctly, so consider the
                                717                 :                :              * same for SSL.
                                718                 :                :              */
                                719                 :            121 :             ssl_done = true;
                                720                 :                :         }
                                721                 :            122 :         goto retry;
                                722                 :                :     }
                                723                 :                : 
                                724                 :                :     /* Could add additional special packet types here */
                                725                 :                : 
                                726                 :                :     /*
                                727                 :                :      * Set FrontendProtocol now so that ereport() knows what format to send if
                                728                 :                :      * we fail during startup. We use the protocol version requested by the
                                729                 :                :      * client unless it's higher than the latest version we support. It's
                                730                 :                :      * possible that error message fields might look different in newer
                                731                 :                :      * protocol versions, but that's something those new clients should be
                                732                 :                :      * able to deal with.
                                733                 :                :      */
  653 rhaas@postgresql.org      734                 :          15149 :     FrontendProtocol = Min(proto, PG_PROTOCOL_LATEST);
                                735                 :                : 
                                736                 :                :     /* Check that the major protocol version is in range. */
  803 heikki.linnakangas@i      737         [ +  - ]:          15149 :     if (PG_PROTOCOL_MAJOR(proto) < PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST) ||
                                738         [ +  + ]:          15149 :         PG_PROTOCOL_MAJOR(proto) > PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST))
                                739         [ +  - ]:              1 :         ereport(FATAL,
                                740                 :                :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                741                 :                :                  errmsg("unsupported frontend protocol %u.%u: server supports %u.0 to %u.%u",
                                742                 :                :                         PG_PROTOCOL_MAJOR(proto), PG_PROTOCOL_MINOR(proto),
                                743                 :                :                         PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST),
                                744                 :                :                         PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST),
                                745                 :                :                         PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST))));
                                746                 :                : 
                                747                 :                :     /*
                                748                 :                :      * Now fetch parameters out of startup packet and save them into the Port
                                749                 :                :      * structure.
                                750                 :                :      */
                                751                 :          15148 :     oldcontext = MemoryContextSwitchTo(TopMemoryContext);
                                752                 :                : 
                                753                 :                :     /* Handle protocol version 3 startup packet */
                                754                 :                :     {
                                755                 :          15148 :         int32       offset = sizeof(ProtocolVersion);
                                756                 :          15148 :         List       *unrecognized_protocol_options = NIL;
                                757                 :                : 
                                758                 :                :         /*
                                759                 :                :          * Scan packet body for name/option pairs.  We can assume any string
                                760                 :                :          * beginning within the packet body is null-terminated, thanks to
                                761                 :                :          * zeroing extra byte above.
                                762                 :                :          */
                                763                 :          15148 :         port->guc_options = NIL;
                                764                 :                : 
                                765         [ +  - ]:          87808 :         while (offset < len)
                                766                 :                :         {
                                767                 :          87808 :             char       *nameptr = buf + offset;
                                768                 :                :             int32       valoffset;
                                769                 :                :             char       *valptr;
                                770                 :                : 
                                771         [ +  + ]:          87808 :             if (*nameptr == '\0')
                                772                 :          15148 :                 break;          /* found packet terminator */
                                773                 :          72660 :             valoffset = offset + strlen(nameptr) + 1;
                                774         [ -  + ]:          72660 :             if (valoffset >= len)
  803 heikki.linnakangas@i      775                 :UBC           0 :                 break;          /* missing value, will complain below */
  803 heikki.linnakangas@i      776                 :CBC       72660 :             valptr = buf + valoffset;
                                777                 :                : 
                                778         [ +  + ]:          72660 :             if (strcmp(nameptr, "database") == 0)
                                779                 :          15148 :                 port->database_name = pstrdup(valptr);
                                780         [ +  + ]:          57512 :             else if (strcmp(nameptr, "user") == 0)
                                781                 :          15148 :                 port->user_name = pstrdup(valptr);
                                782         [ +  + ]:          42364 :             else if (strcmp(nameptr, "options") == 0)
                                783                 :           4453 :                 port->cmdline_options = pstrdup(valptr);
                                784         [ +  + ]:          37911 :             else if (strcmp(nameptr, "replication") == 0)
                                785                 :                :             {
                                786                 :                :                 /*
                                787                 :                :                  * Due to backward compatibility concerns the replication
                                788                 :                :                  * parameter is a hybrid beast which allows the value to be
                                789                 :                :                  * either boolean or the string 'database'. The latter
                                790                 :                :                  * connects to a specific database which is e.g. required for
                                791                 :                :                  * logical decoding while.
                                792                 :                :                  */
                                793         [ +  + ]:           1342 :                 if (strcmp(valptr, "database") == 0)
                                794                 :                :                 {
                                795                 :            790 :                     am_walsender = true;
                                796                 :            790 :                     am_db_walsender = true;
                                797                 :                :                 }
                                798         [ -  + ]:            552 :                 else if (!parse_bool(valptr, &am_walsender))
  803 heikki.linnakangas@i      799         [ #  # ]:UBC           0 :                     ereport(FATAL,
                                800                 :                :                             (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                801                 :                :                              errmsg("invalid value for parameter \"%s\": \"%s\"",
                                802                 :                :                                     "replication",
                                803                 :                :                                     valptr),
                                804                 :                :                              errhint("Valid values are: \"false\", 0, \"true\", 1, \"database\".")));
                                805                 :                :             }
  803 heikki.linnakangas@i      806         [ +  + ]:CBC       36569 :             else if (strncmp(nameptr, "_pq_.", 5) == 0)
                                807                 :                :             {
                                808                 :                :                 /*
                                809                 :                :                  * Any option beginning with _pq_. is reserved for use as a
                                810                 :                :                  * protocol-level option, but at present no such options are
                                811                 :                :                  * defined.
                                812                 :                :                  */
                                813                 :                :                 unrecognized_protocol_options =
  803 heikki.linnakangas@i      814                 :GBC       15058 :                     lappend(unrecognized_protocol_options, pstrdup(nameptr));
                                815                 :                :             }
                                816                 :                :             else
                                817                 :                :             {
                                818                 :                :                 /* Assume it's a generic GUC option */
  803 heikki.linnakangas@i      819                 :CBC       21511 :                 port->guc_options = lappend(port->guc_options,
                                820                 :          21511 :                                             pstrdup(nameptr));
                                821                 :          21511 :                 port->guc_options = lappend(port->guc_options,
                                822                 :          21511 :                                             pstrdup(valptr));
                                823                 :                : 
                                824                 :                :                 /*
                                825                 :                :                  * Copy application_name to port if we come across it.  This
                                826                 :                :                  * is done so we can log the application_name in the
                                827                 :                :                  * connection authorization message.  Note that the GUC would
                                828                 :                :                  * be used but we haven't gone through GUC setup yet.
                                829                 :                :                  */
                                830         [ +  + ]:          21511 :                 if (strcmp(nameptr, "application_name") == 0)
                                831                 :                :                 {
                                832                 :          15139 :                     port->application_name = pg_clean_ascii(valptr, 0);
                                833                 :                :                 }
                                834                 :                :             }
                                835                 :          72660 :             offset = valoffset + strlen(valptr) + 1;
                                836                 :                :         }
                                837                 :                : 
                                838                 :                :         /*
                                839                 :                :          * If we didn't find a packet terminator exactly at the end of the
                                840                 :                :          * given packet length, complain.
                                841                 :                :          */
                                842         [ -  + ]:          15148 :         if (offset != len - 1)
  803 heikki.linnakangas@i      843         [ #  # ]:UBC           0 :             ereport(FATAL,
                                844                 :                :                     (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                845                 :                :                      errmsg("invalid startup packet layout: expected terminator as last byte")));
                                846                 :                : 
                                847                 :                :         /*
                                848                 :                :          * If the client requested a newer protocol version or if the client
                                849                 :                :          * requested any protocol options we didn't recognize, let them know
                                850                 :                :          * the newest minor protocol version we do support and the names of
                                851                 :                :          * any unrecognized options.
                                852                 :                :          */
  803 heikki.linnakangas@i      853   [ +  +  -  + ]:CBC       15148 :         if (PG_PROTOCOL_MINOR(proto) > PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST) ||
                                854                 :                :             unrecognized_protocol_options != NIL)
  803 heikki.linnakangas@i      855                 :GBC       15058 :             SendNegotiateProtocolVersion(unrecognized_protocol_options);
                                856                 :                : 
   78 heikki.linnakangas@i      857                 :GNC       15148 :         list_free_deep(unrecognized_protocol_options);
                                858                 :                :     }
                                859                 :                : 
                                860                 :                :     /* Check a user name was given. */
  803 heikki.linnakangas@i      861   [ +  -  -  + ]:CBC       15148 :     if (port->user_name == NULL || port->user_name[0] == '\0')
  803 heikki.linnakangas@i      862         [ #  # ]:UBC           0 :         ereport(FATAL,
                                863                 :                :                 (errcode(ERRCODE_INVALID_AUTHORIZATION_SPECIFICATION),
                                864                 :                :                  errmsg("no PostgreSQL user name specified in startup packet")));
                                865                 :                : 
                                866                 :                :     /* The database defaults to the user name. */
  803 heikki.linnakangas@i      867   [ +  -  -  + ]:CBC       15148 :     if (port->database_name == NULL || port->database_name[0] == '\0')
  803 heikki.linnakangas@i      868                 :UBC           0 :         port->database_name = pstrdup(port->user_name);
                                869                 :                : 
                                870                 :                :     /*
                                871                 :                :      * Truncate given database and user names to length of a Postgres name.
                                872                 :                :      * This avoids lookup failures when overlength names are given.
                                873                 :                :      */
  534 nathan@postgresql.or      874         [ -  + ]:CBC       15148 :     if (strlen(port->database_name) >= NAMEDATALEN)
  534 nathan@postgresql.or      875                 :UBC           0 :         port->database_name[NAMEDATALEN - 1] = '\0';
  534 nathan@postgresql.or      876         [ -  + ]:CBC       15148 :     if (strlen(port->user_name) >= NAMEDATALEN)
  534 nathan@postgresql.or      877                 :UBC           0 :         port->user_name[NAMEDATALEN - 1] = '\0';
                                878                 :                : 
  115 alvherre@kurilemu.de      879   [ +  +  -  + ]:GNC       15148 :     Assert(MyBackendType == B_BACKEND || MyBackendType == B_DEAD_END_BACKEND);
  803 heikki.linnakangas@i      880         [ +  + ]:CBC       15148 :     if (am_walsender)
                                881                 :           1342 :         MyBackendType = B_WAL_SENDER;
                                882                 :                : 
                                883                 :                :     /*
                                884                 :                :      * Normal walsender backends, e.g. for streaming replication, are not
                                885                 :                :      * connected to a particular database. But walsenders used for logical
                                886                 :                :      * replication need to connect to a specific database. We allow streaming
                                887                 :                :      * replication commands to be issued even if connected to a database as it
                                888                 :                :      * can make sense to first make a basebackup and then stream changes
                                889                 :                :      * starting from that.
                                890                 :                :      */
                                891   [ +  +  +  + ]:          15148 :     if (am_walsender && !am_db_walsender)
                                892                 :            552 :         port->database_name[0] = '\0';
                                893                 :                : 
                                894                 :                :     /*
                                895                 :                :      * Done filling the Port structure
                                896                 :                :      */
                                897                 :          15148 :     MemoryContextSwitchTo(oldcontext);
                                898                 :                : 
  301 tgl@sss.pgh.pa.us         899                 :GNC       15148 :     pfree(buf);
                                900                 :                : 
  803 heikki.linnakangas@i      901                 :CBC       15148 :     return STATUS_OK;
                                902                 :                : 
  301 tgl@sss.pgh.pa.us         903                 :GNC          66 : fail:
                                904                 :                :     /* be tidy, just to avoid Valgrind complaints */
                                905         [ +  + ]:             66 :     if (buf)
                                906                 :             46 :         pfree(buf);
                                907                 :                : 
                                908                 :             66 :     return STATUS_ERROR;
                                909                 :                : }
                                910                 :                : 
                                911                 :                : /*
                                912                 :                :  * The client has sent a cancel request packet, not a normal
                                913                 :                :  * start-a-new-connection packet.  Perform the necessary processing.  Nothing
                                914                 :                :  * is sent back to the client.
                                915                 :                :  */
                                916                 :                : static void
  423 heikki.linnakangas@i      917                 :CBC          15 : ProcessCancelRequestPacket(Port *port, void *pkt, int pktlen)
                                918                 :                : {
                                919                 :                :     CancelRequestPacket *canc;
                                920                 :                :     int         len;
                                921                 :                : 
                                922         [ -  + ]:             15 :     if (pktlen < offsetof(CancelRequestPacket, cancelAuthCode))
                                923                 :                :     {
  423 heikki.linnakangas@i      924         [ #  # ]:UBC           0 :         ereport(COMMERROR,
                                925                 :                :                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                926                 :                :                  errmsg("invalid length of cancel request packet")));
                                927                 :              0 :         return;
                                928                 :                :     }
  423 heikki.linnakangas@i      929                 :CBC          15 :     len = pktlen - offsetof(CancelRequestPacket, cancelAuthCode);
                                930   [ +  -  -  + ]:             15 :     if (len == 0 || len > 256)
                                931                 :                :     {
  423 heikki.linnakangas@i      932         [ #  # ]:UBC           0 :         ereport(COMMERROR,
                                933                 :                :                 (errcode(ERRCODE_PROTOCOL_VIOLATION),
                                934                 :                :                  errmsg("invalid length of cancel key in cancel request packet")));
                                935                 :              0 :         return;
                                936                 :                :     }
                                937                 :                : 
  423 heikki.linnakangas@i      938                 :CBC          15 :     canc = (CancelRequestPacket *) pkt;
                                939                 :             15 :     SendCancelRequest(pg_ntoh32(canc->backendPID), canc->cancelAuthCode, len);
                                940                 :                : }
                                941                 :                : 
                                942                 :                : /*
                                943                 :                :  * Send a NegotiateProtocolVersion to the client.  This lets the client know
                                944                 :                :  * that they have either requested a newer minor protocol version than we are
                                945                 :                :  * able to speak, or at least one protocol option that we don't understand, or
                                946                 :                :  * possibly both. FrontendProtocol has already been set to the version
                                947                 :                :  * requested by the client or the highest version we know how to speak,
                                948                 :                :  * whichever is older. If the highest version that we know how to speak is too
                                949                 :                :  * old for the client, it can abandon the connection.
                                950                 :                :  *
                                951                 :                :  * We also include in the response a list of protocol options we didn't
                                952                 :                :  * understand.  This allows clients to include optional parameters that might
                                953                 :                :  * be present either in newer protocol versions or third-party protocol
                                954                 :                :  * extensions without fear of having to reconnect if those options are not
                                955                 :                :  * understood, while at the same time making certain that the client is aware
                                956                 :                :  * of which options were actually accepted.
                                957                 :                :  */
                                958                 :                : static void
  803 heikki.linnakangas@i      959                 :GBC       15058 : SendNegotiateProtocolVersion(List *unrecognized_protocol_options)
                                960                 :                : {
                                961                 :                :     StringInfoData buf;
                                962                 :                :     ListCell   *lc;
                                963                 :                : 
                                964                 :          15058 :     pq_beginmessage(&buf, PqMsg_NegotiateProtocolVersion);
  653 rhaas@postgresql.org      965                 :          15058 :     pq_sendint32(&buf, FrontendProtocol);
  803 heikki.linnakangas@i      966                 :          15058 :     pq_sendint32(&buf, list_length(unrecognized_protocol_options));
                                967   [ +  -  +  +  :          30116 :     foreach(lc, unrecognized_protocol_options)
                                              +  + ]
                                968                 :          15058 :         pq_sendstring(&buf, lfirst(lc));
                                969                 :          15058 :     pq_endmessage(&buf);
                                970                 :                : 
                                971                 :                :     /* no need to flush, some other message will follow */
                                972                 :          15058 : }
                                973                 :                : 
                                974                 :                : 
                                975                 :                : /*
                                976                 :                :  * SIGTERM while processing startup packet.
                                977                 :                :  *
                                978                 :                :  * Running proc_exit() from a signal handler would be quite unsafe.
                                979                 :                :  * However, since we have not yet touched shared memory, we can just
                                980                 :                :  * pull the plug and exit without running any atexit handlers.
                                981                 :                :  *
                                982                 :                :  * One might be tempted to try to send a message, or log one, indicating
                                983                 :                :  * why we are disconnecting.  However, that would be quite unsafe in itself.
                                984                 :                :  * Also, it seems undesirable to provide clues about the database's state
                                985                 :                :  * to a client that has not yet completed authentication, or even sent us
                                986                 :                :  * a startup packet.
                                987                 :                :  */
                                988                 :                : static void
  803 heikki.linnakangas@i      989                 :UBC           0 : process_startup_packet_die(SIGNAL_ARGS)
                                990                 :                : {
                                991                 :              0 :     _exit(1);
                                992                 :                : }
                                993                 :                : 
                                994                 :                : /*
                                995                 :                :  * Timeout while processing startup packet.
                                996                 :                :  * As for process_startup_packet_die(), we exit via _exit(1).
                                997                 :                :  */
                                998                 :                : static void
                                999                 :              0 : StartupPacketTimeoutHandler(void)
                               1000                 :                : {
                               1001                 :              0 :     _exit(1);
                               1002                 :                : }
                               1003                 :                : 
                               1004                 :                : /*
                               1005                 :                :  * Helper for the log_connections GUC check hook.
                               1006                 :                :  *
                               1007                 :                :  * `elemlist` is a listified version of the string input passed to the
                               1008                 :                :  * log_connections GUC check hook, check_log_connections().
                               1009                 :                :  * check_log_connections() is responsible for cleaning up `elemlist`.
                               1010                 :                :  *
                               1011                 :                :  * validate_log_connections_options() returns false if an error was
                               1012                 :                :  * encountered and the GUC input could not be validated and true otherwise.
                               1013                 :                :  *
                               1014                 :                :  * `flags` returns the flags that should be stored in the log_connections GUC
                               1015                 :                :  * by its assign hook.
                               1016                 :                :  */
                               1017                 :                : static bool
  444 melanieplageman@gmai     1018                 :CBC        1463 : validate_log_connections_options(List *elemlist, uint32 *flags)
                               1019                 :                : {
                               1020                 :                :     ListCell   *l;
                               1021                 :                :     char       *item;
                               1022                 :                : 
                               1023                 :                :     /*
                               1024                 :                :      * For backwards compatibility, we accept these tokens by themselves.
                               1025                 :                :      *
                               1026                 :                :      * Prior to PostgreSQL 18, log_connections was a boolean GUC that accepted
                               1027                 :                :      * any unambiguous substring of 'true', 'false', 'yes', 'no', 'on', and
                               1028                 :                :      * 'off'. Since log_connections became a list of strings in 18, we only
                               1029                 :                :      * accept complete option strings.
                               1030                 :                :      */
                               1031                 :                :     static const struct config_enum_entry compat_options[] = {
                               1032                 :                :         {"off", 0},
                               1033                 :                :         {"false", 0},
                               1034                 :                :         {"no", 0},
                               1035                 :                :         {"0", 0},
                               1036                 :                :         {"on", LOG_CONNECTION_ON},
                               1037                 :                :         {"true", LOG_CONNECTION_ON},
                               1038                 :                :         {"yes", LOG_CONNECTION_ON},
                               1039                 :                :         {"1", LOG_CONNECTION_ON},
                               1040                 :                :     };
                               1041                 :                : 
                               1042                 :           1463 :     *flags = 0;
                               1043                 :                : 
                               1044                 :                :     /* If an empty string was passed, we're done */
                               1045         [ +  + ]:           1463 :     if (list_length(elemlist) == 0)
                               1046                 :           1298 :         return true;
                               1047                 :                : 
                               1048                 :                :     /*
                               1049                 :                :      * Now check for the backwards compatibility options. They must always be
                               1050                 :                :      * specified on their own, so we error out if the first option is a
                               1051                 :                :      * backwards compatibility option and other options are also specified.
                               1052                 :                :      */
                               1053                 :            165 :     item = linitial(elemlist);
                               1054                 :                : 
                               1055         [ +  + ]:           1481 :     for (size_t i = 0; i < lengthof(compat_options); i++)
                               1056                 :                :     {
                               1057                 :           1317 :         struct config_enum_entry option = compat_options[i];
                               1058                 :                : 
                               1059         [ +  + ]:           1317 :         if (pg_strcasecmp(item, option.name) != 0)
                               1060                 :           1316 :             continue;
                               1061                 :                : 
                               1062         [ -  + ]:              1 :         if (list_length(elemlist) > 1)
                               1063                 :                :         {
  444 melanieplageman@gmai     1064                 :UBC           0 :             GUC_check_errdetail("Cannot specify log_connections option \"%s\" in a list with other options.",
                               1065                 :                :                                 item);
  444 melanieplageman@gmai     1066                 :CBC           1 :             return false;
                               1067                 :                :         }
                               1068                 :                : 
                               1069                 :              1 :         *flags = option.val;
                               1070                 :              1 :         return true;
                               1071                 :                :     }
                               1072                 :                : 
                               1073                 :                :     /* Now check the aspect options. The empty string was already handled */
                               1074   [ +  -  +  +  :            367 :     foreach(l, elemlist)
                                              +  + ]
                               1075                 :                :     {
                               1076                 :                :         static const struct config_enum_entry options[] = {
                               1077                 :                :             {"receipt", LOG_CONNECTION_RECEIPT},
                               1078                 :                :             {"authentication", LOG_CONNECTION_AUTHENTICATION},
                               1079                 :                :             {"authorization", LOG_CONNECTION_AUTHORIZATION},
                               1080                 :                :             {"setup_durations", LOG_CONNECTION_SETUP_DURATIONS},
                               1081                 :                :             {"all", LOG_CONNECTION_ALL},
                               1082                 :                :         };
                               1083                 :                : 
                               1084                 :            203 :         item = lfirst(l);
                               1085         [ +  - ]:            741 :         for (size_t i = 0; i < lengthof(options); i++)
                               1086                 :                :         {
                               1087                 :            741 :             struct config_enum_entry option = options[i];
                               1088                 :                : 
                               1089         [ +  + ]:            741 :             if (pg_strcasecmp(item, option.name) == 0)
                               1090                 :                :             {
                               1091                 :            203 :                 *flags |= option.val;
                               1092                 :            203 :                 goto next;
                               1093                 :                :             }
                               1094                 :                :         }
                               1095                 :                : 
  444 melanieplageman@gmai     1096                 :UBC           0 :         GUC_check_errdetail("Invalid option \"%s\".", item);
                               1097                 :              0 :         return false;
                               1098                 :                : 
  444 melanieplageman@gmai     1099                 :CBC         203 : next:   ;
                               1100                 :                :     }
                               1101                 :                : 
                               1102                 :            164 :     return true;
                               1103                 :                : }
                               1104                 :                : 
                               1105                 :                : 
                               1106                 :                : /*
                               1107                 :                :  * GUC check hook for log_connections
                               1108                 :                :  */
                               1109                 :                : bool
                               1110                 :           1463 : check_log_connections(char **newval, void **extra, GucSource source)
                               1111                 :                : {
                               1112                 :                :     uint32      flags;
                               1113                 :                :     char       *rawstring;
                               1114                 :                :     List       *elemlist;
                               1115                 :                :     bool        success;
                               1116                 :                : 
                               1117                 :                :     /* Need a modifiable copy of string */
                               1118                 :           1463 :     rawstring = pstrdup(*newval);
                               1119                 :                : 
                               1120         [ -  + ]:           1463 :     if (!SplitIdentifierString(rawstring, ',', &elemlist))
                               1121                 :                :     {
  336 peter@eisentraut.org     1122                 :UBC           0 :         GUC_check_errdetail("Invalid list syntax in parameter \"%s\".", "log_connections");
  444 melanieplageman@gmai     1123                 :              0 :         pfree(rawstring);
                               1124                 :              0 :         list_free(elemlist);
                               1125                 :              0 :         return false;
                               1126                 :                :     }
                               1127                 :                : 
                               1128                 :                :     /* Validation logic is all in the helper */
  444 melanieplageman@gmai     1129                 :CBC        1463 :     success = validate_log_connections_options(elemlist, &flags);
                               1130                 :                : 
                               1131                 :                :     /* Time for cleanup */
                               1132                 :           1463 :     pfree(rawstring);
                               1133                 :           1463 :     list_free(elemlist);
                               1134                 :                : 
                               1135         [ -  + ]:           1463 :     if (!success)
  444 melanieplageman@gmai     1136                 :UBC           0 :         return false;
                               1137                 :                : 
                               1138                 :                :     /*
                               1139                 :                :      * We succeeded, so allocate `extra` and save the flags there for use by
                               1140                 :                :      * assign_log_connections().
                               1141                 :                :      */
  429 dgustafsson@postgres     1142                 :CBC        1463 :     *extra = guc_malloc(LOG, sizeof(int));
                               1143         [ -  + ]:           1463 :     if (!*extra)
  429 dgustafsson@postgres     1144                 :UBC           0 :         return false;
  444 melanieplageman@gmai     1145                 :CBC        1463 :     *((int *) *extra) = flags;
                               1146                 :                : 
                               1147                 :           1463 :     return true;
                               1148                 :                : }
                               1149                 :                : 
                               1150                 :                : /*
                               1151                 :                :  * GUC assign hook for log_connections
                               1152                 :                :  */
                               1153                 :                : void
                               1154                 :           1459 : assign_log_connections(const char *newval, void *extra)
                               1155                 :                : {
                               1156                 :           1459 :     log_connections = *((int *) extra);
                               1157                 :           1459 : }
        

Generated by: LCOV version 2.5.0-beta