LCOV - code coverage report
Current view: top level - src/backend/libpq - be-secure-common.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 0.0 % 54 0
Test Date: 2026-01-26 10:56:24 Functions: 0.0 % 2 0
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 0.0 % 110 0

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * be-secure-common.c
       4                 :             :  *
       5                 :             :  * common implementation-independent SSL support code
       6                 :             :  *
       7                 :             :  * While be-secure.c contains the interfaces that the rest of the
       8                 :             :  * communications code calls, this file contains support routines that are
       9                 :             :  * used by the library-specific implementations such as be-secure-openssl.c.
      10                 :             :  *
      11                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
      12                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
      13                 :             :  *
      14                 :             :  * IDENTIFICATION
      15                 :             :  *        src/backend/libpq/be-secure-common.c
      16                 :             :  *
      17                 :             :  *-------------------------------------------------------------------------
      18                 :             :  */
      19                 :             : 
      20                 :             : #include "postgres.h"
      21                 :             : 
      22                 :             : #include <sys/stat.h>
      23                 :             : #include <unistd.h>
      24                 :             : 
      25                 :             : #include "common/percentrepl.h"
      26                 :             : #include "common/string.h"
      27                 :             : #include "libpq/libpq.h"
      28                 :             : #include "storage/fd.h"
      29                 :             : 
      30                 :             : /*
      31                 :             :  * Run ssl_passphrase_command
      32                 :             :  *
      33                 :             :  * prompt will be substituted for %p.  is_server_start determines the loglevel
      34                 :             :  * of error messages.
      35                 :             :  *
      36                 :             :  * The result will be put in buffer buf, which is of size size.  The return
      37                 :             :  * value is the length of the actual result.
      38                 :             :  */
      39                 :             : int
      40                 :           0 : run_ssl_passphrase_command(const char *prompt, bool is_server_start, char *buf, int size)
      41                 :             : {
      42                 :           0 :         int                     loglevel = is_server_start ? ERROR : LOG;
      43                 :           0 :         char       *command;
      44                 :           0 :         FILE       *fh;
      45                 :           0 :         int                     pclose_rc;
      46                 :           0 :         size_t          len = 0;
      47                 :             : 
      48         [ #  # ]:           0 :         Assert(prompt);
      49         [ #  # ]:           0 :         Assert(size > 0);
      50                 :           0 :         buf[0] = '\0';
      51                 :             : 
      52                 :           0 :         command = replace_percent_placeholders(ssl_passphrase_command, "ssl_passphrase_command", "p", prompt);
      53                 :             : 
      54                 :           0 :         fh = OpenPipeStream(command, "r");
      55         [ #  # ]:           0 :         if (fh == NULL)
      56                 :             :         {
      57   [ #  #  #  #  :           0 :                 ereport(loglevel,
          #  #  #  #  #  
                      # ]
      58                 :             :                                 (errcode_for_file_access(),
      59                 :             :                                  errmsg("could not execute command \"%s\": %m",
      60                 :             :                                                 command)));
      61                 :           0 :                 goto error;
      62                 :             :         }
      63                 :             : 
      64         [ #  # ]:           0 :         if (!fgets(buf, size, fh))
      65                 :             :         {
      66         [ #  # ]:           0 :                 if (ferror(fh))
      67                 :             :                 {
      68                 :           0 :                         explicit_bzero(buf, size);
      69   [ #  #  #  #  :           0 :                         ereport(loglevel,
          #  #  #  #  #  
                      # ]
      70                 :             :                                         (errcode_for_file_access(),
      71                 :             :                                          errmsg("could not read from command \"%s\": %m",
      72                 :             :                                                         command)));
      73                 :           0 :                         goto error;
      74                 :             :                 }
      75                 :           0 :         }
      76                 :             : 
      77                 :           0 :         pclose_rc = ClosePipeStream(fh);
      78         [ #  # ]:           0 :         if (pclose_rc == -1)
      79                 :             :         {
      80                 :           0 :                 explicit_bzero(buf, size);
      81   [ #  #  #  #  :           0 :                 ereport(loglevel,
          #  #  #  #  #  
                      # ]
      82                 :             :                                 (errcode_for_file_access(),
      83                 :             :                                  errmsg("could not close pipe to external command: %m")));
      84                 :           0 :                 goto error;
      85                 :             :         }
      86         [ #  # ]:           0 :         else if (pclose_rc != 0)
      87                 :             :         {
      88                 :           0 :                 char       *reason;
      89                 :             : 
      90                 :           0 :                 explicit_bzero(buf, size);
      91                 :           0 :                 reason = wait_result_to_str(pclose_rc);
      92   [ #  #  #  #  :           0 :                 ereport(loglevel,
          #  #  #  #  #  
                      # ]
      93                 :             :                                 (errcode_for_file_access(),
      94                 :             :                                  errmsg("command \"%s\" failed",
      95                 :             :                                                 command),
      96                 :             :                                  errdetail_internal("%s", reason)));
      97                 :           0 :                 pfree(reason);
      98                 :             :                 goto error;
      99         [ #  # ]:           0 :         }
     100                 :             : 
     101                 :             :         /* strip trailing newline and carriage return */
     102                 :           0 :         len = pg_strip_crlf(buf);
     103                 :             : 
     104                 :             : error:
     105                 :           0 :         pfree(command);
     106                 :           0 :         return len;
     107                 :           0 : }
     108                 :             : 
     109                 :             : 
     110                 :             : /*
     111                 :             :  * Check permissions for SSL key files.
     112                 :             :  */
     113                 :             : bool
     114                 :           0 : check_ssl_key_file_permissions(const char *ssl_key_file, bool isServerStart)
     115                 :             : {
     116                 :           0 :         int                     loglevel = isServerStart ? FATAL : LOG;
     117                 :           0 :         struct stat buf;
     118                 :             : 
     119         [ #  # ]:           0 :         if (stat(ssl_key_file, &buf) != 0)
     120                 :             :         {
     121   [ #  #  #  #  :           0 :                 ereport(loglevel,
          #  #  #  #  #  
                      # ]
     122                 :             :                                 (errcode_for_file_access(),
     123                 :             :                                  errmsg("could not access private key file \"%s\": %m",
     124                 :             :                                                 ssl_key_file)));
     125                 :           0 :                 return false;
     126                 :             :         }
     127                 :             : 
     128                 :             :         /* Key file must be a regular file */
     129         [ #  # ]:           0 :         if (!S_ISREG(buf.st_mode))
     130                 :             :         {
     131   [ #  #  #  #  :           0 :                 ereport(loglevel,
          #  #  #  #  #  
                      # ]
     132                 :             :                                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
     133                 :             :                                  errmsg("private key file \"%s\" is not a regular file",
     134                 :             :                                                 ssl_key_file)));
     135                 :           0 :                 return false;
     136                 :             :         }
     137                 :             : 
     138                 :             :         /*
     139                 :             :          * Refuse to load key files owned by users other than us or root, and
     140                 :             :          * require no public access to the key file.  If the file is owned by us,
     141                 :             :          * require mode 0600 or less.  If owned by root, require 0640 or less to
     142                 :             :          * allow read access through either our gid or a supplementary gid that
     143                 :             :          * allows us to read system-wide certificates.
     144                 :             :          *
     145                 :             :          * Note that roughly similar checks are performed in
     146                 :             :          * src/interfaces/libpq/fe-secure-openssl.c so any changes here may need
     147                 :             :          * to be made there as well.  The environment is different though; this
     148                 :             :          * code can assume that we're not running as root.
     149                 :             :          *
     150                 :             :          * Ideally we would do similar permissions checks on Windows, but it is
     151                 :             :          * not clear how that would work since Unix-style permissions may not be
     152                 :             :          * available.
     153                 :             :          */
     154                 :             : #if !defined(WIN32) && !defined(__CYGWIN__)
     155   [ #  #  #  # ]:           0 :         if (buf.st_uid != geteuid() && buf.st_uid != 0)
     156                 :             :         {
     157   [ #  #  #  #  :           0 :                 ereport(loglevel,
          #  #  #  #  #  
                      # ]
     158                 :             :                                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
     159                 :             :                                  errmsg("private key file \"%s\" must be owned by the database user or root",
     160                 :             :                                                 ssl_key_file)));
     161                 :           0 :                 return false;
     162                 :             :         }
     163                 :             : 
     164   [ #  #  #  # ]:           0 :         if ((buf.st_uid == geteuid() && buf.st_mode & (S_IRWXG | S_IRWXO)) ||
     165         [ #  # ]:           0 :                 (buf.st_uid == 0 && buf.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)))
     166                 :             :         {
     167   [ #  #  #  #  :           0 :                 ereport(loglevel,
          #  #  #  #  #  
                      # ]
     168                 :             :                                 (errcode(ERRCODE_CONFIG_FILE_ERROR),
     169                 :             :                                  errmsg("private key file \"%s\" has group or world access",
     170                 :             :                                                 ssl_key_file),
     171                 :             :                                  errdetail("File must have permissions u=rw (0600) or less if owned by the database user, or permissions u=rw,g=r (0640) or less if owned by root.")));
     172                 :           0 :                 return false;
     173                 :             :         }
     174                 :             : #endif
     175                 :             : 
     176                 :           0 :         return true;
     177                 :           0 : }
        

Generated by: LCOV version 2.3.2-1