Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  be-secure.c

  Sprache: C
 

/*-------------------------------------------------------------------------
 *
 * be-secure.c
 *   functions related to setting up a secure connection to the frontend.
 *   Secure connections are expected to provide confidentiality,
 *   message integrity and endpoint authentication.
 *
 *
 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
 *   src/backend/libpq/be-secure.c
 *
 *-------------------------------------------------------------------------
 */


#include "postgres.h"

#include <signal.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>

#include "libpq/libpq.h"
#include "miscadmin.h"
#include "tcop/tcopprot.h"
#include "utils/injection_point.h"
#include "utils/wait_event.h"

char    *ssl_library;
char    *ssl_cert_file;
char    *ssl_key_file;
char    *ssl_ca_file;
char    *ssl_crl_file;
char    *ssl_crl_dir;
char    *ssl_dh_params_file;
char    *ssl_passphrase_command;
bool  ssl_passphrase_command_supports_reload;

#ifdef USE_SSL
bool  ssl_loaded_verify_locations = false;
#endif

/* GUC variable controlling SSL cipher list */
char    *SSLCipherSuites = NULL;
char    *SSLCipherList = NULL;

/* GUC variable for default ECHD curve. */
char    *SSLECDHCurve;

/* GUC variable: if false, prefer client ciphers */
bool  SSLPreferServerCiphers;

int   ssl_min_protocol_version = PG_TLS1_2_VERSION;
int   ssl_max_protocol_version = PG_TLS_ANY;

/* ------------------------------------------------------------ */
/*  Procedures common to all secure sessions */
/* ------------------------------------------------------------ */

/*
 * Initialize global context.
 *
 * If isServerStart is true, report any errors as FATAL (so we don't return).
 * Otherwise, log errors at LOG level and return -1 to indicate trouble,
 * preserving the old SSL state if any.  Returns 0 if OK.
 */

int
secure_initialize(bool isServerStart)
{
#ifdef USE_SSL
 return be_tls_init(isServerStart);
#else
 return 0;
#endif
}

/*
 * Destroy global context, if any.
 */

void
secure_destroy(void)
{
#ifdef USE_SSL
 be_tls_destroy();
#endif
}

/*
 * Indicate if we have loaded the root CA store to verify certificates
 */

bool
secure_loaded_verify_locations(void)
{
#ifdef USE_SSL
 return ssl_loaded_verify_locations;
#else
 return false;
#endif
}

/*
 * Attempt to negotiate secure session.
 */

int
secure_open_server(Port *port)
{
#ifdef USE_SSL
 int   r = 0;
 ssize_t  len;

 /* push unencrypted buffered data back through SSL setup */
 len = pq_buffer_remaining_data();
 if (len > 0)
 {
  char    *buf = palloc(len);

  pq_startmsgread();
  if (pq_getbytes(buf, len) == EOF)
   return STATUS_ERROR; /* shouldn't be possible */
  pq_endmsgread();
  port->raw_buf = buf;
  port->raw_buf_remaining = len;
  port->raw_buf_consumed = 0;
 }
 Assert(pq_buffer_remaining_data() == 0);

 INJECTION_POINT("backend-ssl-startup", NULL);

 r = be_tls_open_server(port);

 if (port->raw_buf_remaining > 0)
 {
  /*
   * This shouldn't be possible -- it would mean the client sent
   * encrypted data before we established a session key...
 */

  elog(LOG, "buffered unencrypted data remains after negotiating SSL connection");
  return STATUS_ERROR;
 }
 if (port->raw_buf != NULL)
 {
  pfree(port->raw_buf);
  port->raw_buf = NULL;
 }

 ereport(DEBUG2,
   (errmsg_internal("SSL connection from DN:\"%s\" CN:\"%s\"",
        port->peer_dn ? port->peer_dn : "(anonymous)",
        port->peer_cn ? port->peer_cn : "(anonymous)")));
 return r;
#else
 return 0;
#endif
}

/*
 * Close secure session.
 */

void
secure_close(Port *port)
{
#ifdef USE_SSL
 if (port->ssl_in_use)
  be_tls_close(port);
#endif
}

/*
 * Read data from a secure connection.
 */

ssize_t
secure_read(Port *port, void *ptr, size_t len)
{
 ssize_t  n;
 int   waitfor;

 /* Deal with any already-pending interrupt condition. */
 ProcessClientReadInterrupt(false);

retry:
#ifdef USE_SSL
 waitfor = 0;
 if (port->ssl_in_use)
 {
  n = be_tls_read(port, ptr, len, &waitfor);
 }
 else
#endif
#ifdef ENABLE_GSS
 if (port->gss && port->gss->enc)
 {
  n = be_gssapi_read(port, ptr, len);
  waitfor = WL_SOCKET_READABLE;
 }
 else
#endif
 {
  n = secure_raw_read(port, ptr, len);
  waitfor = WL_SOCKET_READABLE;
 }

 /* In blocking mode, wait until the socket is ready */
 if (n < 0 && !port->noblock && (errno == EWOULDBLOCK || errno == EAGAIN))
 {
  WaitEvent event;

  Assert(waitfor);

  ModifyWaitEvent(FeBeWaitSet, FeBeWaitSetSocketPos, waitfor, NULL);

  WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1,
       WAIT_EVENT_CLIENT_READ);

  /*
   * If the postmaster has died, it's not safe to continue running,
   * because it is the postmaster's job to kill us if some other backend
   * exits uncleanly.  Moreover, we won't run very well in this state;
   * helper processes like walwriter and the bgwriter will exit, so
   * performance may be poor.  Finally, if we don't exit, pg_ctl will be
   * unable to restart the postmaster without manual intervention, so no
   * new connections can be accepted.  Exiting clears the deck for a
   * postmaster restart.
   *
   * (Note that we only make this check when we would otherwise sleep on
   * our latch.  We might still continue running for a while if the
   * postmaster is killed in mid-query, or even through multiple queries
   * if we never have to wait for read.  We don't want to burn too many
   * cycles checking for this very rare condition, and this should cause
   * us to exit quickly in most cases.)
 */

  if (event.events & WL_POSTMASTER_DEATH)
   ereport(FATAL,
     (errcode(ERRCODE_ADMIN_SHUTDOWN),
      errmsg("terminating connection due to unexpected postmaster exit")));

  /* Handle interrupt. */
  if (event.events & WL_LATCH_SET)
  {
   ResetLatch(MyLatch);
   ProcessClientReadInterrupt(true);

   /*
    * We'll retry the read. Most likely it will return immediately
    * because there's still no data available, and we'll wait for the
    * socket to become ready again.
 */

  }
  goto retry;
 }

 /*
  * Process interrupts that happened during a successful (or non-blocking,
  * or hard-failed) read.
 */

 ProcessClientReadInterrupt(false);

 return n;
}

ssize_t
secure_raw_read(Port *port, void *ptr, size_t len)
{
 ssize_t  n;

 /* Read from the "unread" buffered data first. c.f. libpq-be.h */
 if (port->raw_buf_remaining > 0)
 {
  /* consume up to len bytes from the raw_buf */
  if (len > port->raw_buf_remaining)
   len = port->raw_buf_remaining;
  Assert(port->raw_buf);
  memcpy(ptr, port->raw_buf + port->raw_buf_consumed, len);
  port->raw_buf_consumed += len;
  port->raw_buf_remaining -= len;
  return len;
 }

 /*
  * Try to read from the socket without blocking. If it succeeds we're
  * done, otherwise we'll wait for the socket using the latch mechanism.
 */

#ifdef WIN32
 pgwin32_noblock = true;
#endif
 n = recv(port->sock, ptr, len, 0);
#ifdef WIN32
 pgwin32_noblock = false;
#endif

 return n;
}


/*
 * Write data to a secure connection.
 */

ssize_t
secure_write(Port *port, const void *ptr, size_t len)
{
 ssize_t  n;
 int   waitfor;

 /* Deal with any already-pending interrupt condition. */
 ProcessClientWriteInterrupt(false);

retry:
 waitfor = 0;
#ifdef USE_SSL
 if (port->ssl_in_use)
 {
  n = be_tls_write(port, ptr, len, &waitfor);
 }
 else
#endif
#ifdef ENABLE_GSS
 if (port->gss && port->gss->enc)
 {
  n = be_gssapi_write(port, ptr, len);
  waitfor = WL_SOCKET_WRITEABLE;
 }
 else
#endif
 {
  n = secure_raw_write(port, ptr, len);
  waitfor = WL_SOCKET_WRITEABLE;
 }

 if (n < 0 && !port->noblock && (errno == EWOULDBLOCK || errno == EAGAIN))
 {
  WaitEvent event;

  Assert(waitfor);

  ModifyWaitEvent(FeBeWaitSet, FeBeWaitSetSocketPos, waitfor, NULL);

  WaitEventSetWait(FeBeWaitSet, -1 /* no timeout */ , &event, 1,
       WAIT_EVENT_CLIENT_WRITE);

  /* See comments in secure_read. */
  if (event.events & WL_POSTMASTER_DEATH)
   ereport(FATAL,
     (errcode(ERRCODE_ADMIN_SHUTDOWN),
      errmsg("terminating connection due to unexpected postmaster exit")));

  /* Handle interrupt. */
  if (event.events & WL_LATCH_SET)
  {
   ResetLatch(MyLatch);
   ProcessClientWriteInterrupt(true);

   /*
    * We'll retry the write. Most likely it will return immediately
    * because there's still no buffer space available, and we'll wait
    * for the socket to become ready again.
 */

  }
  goto retry;
 }

 /*
  * Process interrupts that happened during a successful (or non-blocking,
  * or hard-failed) write.
 */

 ProcessClientWriteInterrupt(false);

 return n;
}

ssize_t
secure_raw_write(Port *port, const void *ptr, size_t len)
{
 ssize_t  n;

#ifdef WIN32
 pgwin32_noblock = true;
#endif
 n = send(port->sock, ptr, len, 0);
#ifdef WIN32
 pgwin32_noblock = false;
#endif

 return n;
}

Messung V0.5 in Prozent
C=92 H=97 G=94

¤ Dauer der Verarbeitung: 0.18 Sekunden  (vorverarbeitet am  2026-08-08) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=141584
#Domains=738142