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

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * be-gssapi-common.c
       4                 :             :  *     Common code for GSSAPI authentication and encryption
       5                 :             :  *
       6                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       7                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :             :  *
       9                 :             :  * IDENTIFICATION
      10                 :             :  *       src/backend/libpq/be-gssapi-common.c
      11                 :             :  *
      12                 :             :  *-------------------------------------------------------------------------
      13                 :             :  */
      14                 :             : 
      15                 :             : #include "postgres.h"
      16                 :             : 
      17                 :             : #include "libpq/be-gssapi-common.h"
      18                 :             : 
      19                 :             : /*
      20                 :             :  * Fetch all errors of a specific type and append to "s" (buffer of size len).
      21                 :             :  * If we obtain more than one string, separate them with spaces.
      22                 :             :  * Call once for GSS_CODE and once for MECH_CODE.
      23                 :             :  */
      24                 :             : static void
      25                 :           0 : pg_GSS_error_int(char *s, size_t len, OM_uint32 stat, int type)
      26                 :             : {
      27                 :           0 :         gss_buffer_desc gmsg;
      28                 :           0 :         size_t          i = 0;
      29                 :           0 :         OM_uint32       lmin_s,
      30                 :           0 :                                 msg_ctx = 0;
      31                 :             : 
      32                 :           0 :         do
      33                 :             :         {
      34                 :           0 :                 if (gss_display_status(&lmin_s, stat, type, GSS_C_NO_OID,
      35         [ #  # ]:           0 :                                                            &msg_ctx, &gmsg) != GSS_S_COMPLETE)
      36                 :           0 :                         break;
      37         [ #  # ]:           0 :                 if (i > 0)
      38                 :             :                 {
      39         [ #  # ]:           0 :                         if (i < len)
      40                 :           0 :                                 s[i] = ' ';
      41                 :           0 :                         i++;
      42                 :           0 :                 }
      43         [ #  # ]:           0 :                 if (i < len)
      44         [ #  # ]:           0 :                         memcpy(s + i, gmsg.value, Min(len - i, gmsg.length));
      45                 :           0 :                 i += gmsg.length;
      46                 :           0 :                 gss_release_buffer(&lmin_s, &gmsg);
      47         [ #  # ]:           0 :         }
      48                 :           0 :         while (msg_ctx);
      49                 :             : 
      50                 :             :         /* add nul termination */
      51         [ #  # ]:           0 :         if (i < len)
      52                 :           0 :                 s[i] = '\0';
      53                 :             :         else
      54                 :             :         {
      55   [ #  #  #  # ]:           0 :                 elog(COMMERROR, "incomplete GSS error report");
      56                 :           0 :                 s[len - 1] = '\0';
      57                 :             :         }
      58                 :           0 : }
      59                 :             : 
      60                 :             : /*
      61                 :             :  * Report the GSSAPI error described by maj_stat/min_stat.
      62                 :             :  *
      63                 :             :  * errmsg should be an already-translated primary error message.
      64                 :             :  * The GSSAPI info is appended as errdetail.
      65                 :             :  *
      66                 :             :  * The error is always reported with elevel COMMERROR; we daren't try to
      67                 :             :  * send it to the client, as that'd likely lead to infinite recursion
      68                 :             :  * when elog.c tries to write to the client.
      69                 :             :  *
      70                 :             :  * To avoid memory allocation, total error size is capped (at 128 bytes for
      71                 :             :  * each of major and minor).  No known mechanisms will produce error messages
      72                 :             :  * beyond this cap.
      73                 :             :  */
      74                 :             : void
      75                 :           0 : pg_GSS_error(const char *errmsg,
      76                 :             :                          OM_uint32 maj_stat, OM_uint32 min_stat)
      77                 :             : {
      78                 :           0 :         char            msg_major[128],
      79                 :             :                                 msg_minor[128];
      80                 :             : 
      81                 :             :         /* Fetch major status message */
      82                 :           0 :         pg_GSS_error_int(msg_major, sizeof(msg_major), maj_stat, GSS_C_GSS_CODE);
      83                 :             : 
      84                 :             :         /* Fetch mechanism minor status message */
      85                 :           0 :         pg_GSS_error_int(msg_minor, sizeof(msg_minor), min_stat, GSS_C_MECH_CODE);
      86                 :             : 
      87                 :             :         /*
      88                 :             :          * errmsg_internal, since translation of the first part must be done
      89                 :             :          * before calling this function anyway.
      90                 :             :          */
      91   [ #  #  #  # ]:           0 :         ereport(COMMERROR,
      92                 :             :                         (errmsg_internal("%s", errmsg),
      93                 :             :                          errdetail_internal("%s: %s", msg_major, msg_minor)));
      94                 :           0 : }
      95                 :             : 
      96                 :             : /*
      97                 :             :  * Store the credentials passed in into the memory cache for later usage.
      98                 :             :  *
      99                 :             :  * This allows credentials to be delegated to us for us to use to connect
     100                 :             :  * to other systems with, using, e.g. postgres_fdw or dblink.
     101                 :             :  */
     102                 :             : #define GSS_MEMORY_CACHE "MEMORY:"
     103                 :             : void
     104                 :           0 : pg_store_delegated_credential(gss_cred_id_t cred)
     105                 :             : {
     106                 :           0 :         OM_uint32       major,
     107                 :             :                                 minor;
     108                 :           0 :         gss_OID_set mech;
     109                 :           0 :         gss_cred_usage_t usage;
     110                 :           0 :         gss_key_value_element_desc cc;
     111                 :           0 :         gss_key_value_set_desc ccset;
     112                 :             : 
     113                 :           0 :         cc.key = "ccache";
     114                 :           0 :         cc.value = GSS_MEMORY_CACHE;
     115                 :           0 :         ccset.count = 1;
     116                 :           0 :         ccset.elements = &cc;
     117                 :             : 
     118                 :             :         /* Make the delegated credential only available to current process */
     119                 :           0 :         major = gss_store_cred_into(&minor,
     120                 :           0 :                                                                 cred,
     121                 :             :                                                                 GSS_C_INITIATE, /* credential only used for
     122                 :             :                                                                                                  * starting libpq connection */
     123                 :             :                                                                 GSS_C_NULL_OID, /* store all */
     124                 :             :                                                                 true,   /* overwrite */
     125                 :             :                                                                 true,   /* make default */
     126                 :             :                                                                 &ccset,
     127                 :             :                                                                 &mech,
     128                 :             :                                                                 &usage);
     129                 :             : 
     130         [ #  # ]:           0 :         if (major != GSS_S_COMPLETE)
     131                 :             :         {
     132                 :           0 :                 pg_GSS_error("gss_store_cred", major, minor);
     133                 :           0 :         }
     134                 :             : 
     135                 :             :         /* Credential stored, so we can release our credential handle. */
     136                 :           0 :         major = gss_release_cred(&minor, &cred);
     137         [ #  # ]:           0 :         if (major != GSS_S_COMPLETE)
     138                 :             :         {
     139                 :           0 :                 pg_GSS_error("gss_release_cred", major, minor);
     140                 :           0 :         }
     141                 :             : 
     142                 :             :         /*
     143                 :             :          * Set KRB5CCNAME for this backend, so that later calls to
     144                 :             :          * gss_acquire_cred will find the delegated credentials we stored.
     145                 :             :          */
     146                 :           0 :         setenv("KRB5CCNAME", GSS_MEMORY_CACHE, 1);
     147                 :           0 : }
        

Generated by: LCOV version 2.3.2-1