PostgreSQL Source Code  git master
fe-gssapi-common.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * fe-gssapi-common.c
4  * The front-end (client) GSSAPI common code
5  *
6  * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * IDENTIFICATION
10  * src/interfaces/libpq/fe-gssapi-common.c
11  *-------------------------------------------------------------------------
12  */
13 
14 #include "postgres_fe.h"
15 
16 #include "fe-gssapi-common.h"
17 
18 #include "libpq-int.h"
19 #include "pqexpbuffer.h"
20 
21 /*
22  * Fetch all errors of a specific type and append to "str".
23  * Each error string is preceded by a space.
24  */
25 static void
27 {
28  OM_uint32 lmin_s;
29  gss_buffer_desc lmsg;
30  OM_uint32 msg_ctx = 0;
31 
32  do
33  {
34  if (gss_display_status(&lmin_s, stat, type, GSS_C_NO_OID,
35  &msg_ctx, &lmsg) != GSS_S_COMPLETE)
36  break;
37  appendPQExpBuffer(str, " %s", (char *) lmsg.value);
38  gss_release_buffer(&lmin_s, &lmsg);
39  } while (msg_ctx);
40 }
41 
42 /*
43  * GSSAPI errors contain two parts; put both into conn->errorMessage.
44  */
45 void
46 pg_GSS_error(const char *mprefix, PGconn *conn,
47  OM_uint32 maj_stat, OM_uint32 min_stat)
48 {
49  appendPQExpBuffer(&conn->errorMessage, "%s:", mprefix);
50  pg_GSS_error_int(&conn->errorMessage, maj_stat, GSS_C_GSS_CODE);
52  pg_GSS_error_int(&conn->errorMessage, min_stat, GSS_C_MECH_CODE);
53  appendPQExpBufferChar(&conn->errorMessage, '\n');
54 }
55 
56 /*
57  * Check if we can acquire credentials at all (and yield them if so).
58  */
59 bool
60 pg_GSS_have_cred_cache(gss_cred_id_t *cred_out)
61 {
62  OM_uint32 major,
63  minor;
64  gss_cred_id_t cred = GSS_C_NO_CREDENTIAL;
65 
66  major = gss_acquire_cred(&minor, GSS_C_NO_NAME, 0, GSS_C_NO_OID_SET,
67  GSS_C_INITIATE, &cred, NULL, NULL);
68  if (major != GSS_S_COMPLETE)
69  {
70  *cred_out = NULL;
71  return false;
72  }
73  *cred_out = cred;
74  return true;
75 }
76 
77 /*
78  * Try to load service name for a connection
79  */
80 int
82 {
83  OM_uint32 maj_stat,
84  min_stat;
85  int maxlen;
86  gss_buffer_desc temp_gbuf;
87  char *host;
88 
89  if (conn->gtarg_nam != NULL)
90  /* Already taken care of - move along */
91  return STATUS_OK;
92 
93  host = PQhost(conn);
94  if (!(host && host[0] != '\0'))
95  {
97  libpq_gettext("host name must be specified\n"));
98  return STATUS_ERROR;
99  }
100 
101  /*
102  * Import service principal name so the proper ticket can be acquired by
103  * the GSSAPI system.
104  */
105  maxlen = strlen(conn->krbsrvname) + strlen(host) + 2;
106  temp_gbuf.value = (char *) malloc(maxlen);
107  if (!temp_gbuf.value)
108  {
110  libpq_gettext("out of memory\n"));
111  return STATUS_ERROR;
112  }
113  snprintf(temp_gbuf.value, maxlen, "%s@%s",
114  conn->krbsrvname, host);
115  temp_gbuf.length = strlen(temp_gbuf.value);
116 
117  maj_stat = gss_import_name(&min_stat, &temp_gbuf,
118  GSS_C_NT_HOSTBASED_SERVICE, &conn->gtarg_nam);
119  free(temp_gbuf.value);
120 
121  if (maj_stat != GSS_S_COMPLETE)
122  {
123  pg_GSS_error(libpq_gettext("GSSAPI name import error"),
124  conn,
125  maj_stat, min_stat);
126  return STATUS_ERROR;
127  }
128  return STATUS_OK;
129 }
void appendPQExpBufferStr(PQExpBuffer str, const char *data)
Definition: pqexpbuffer.c:369
#define STATUS_ERROR
Definition: c.h:1171
#define malloc(a)
Definition: header.h:50
PGconn * conn
Definition: streamutil.c:54
void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)
Definition: pqexpbuffer.c:267
char * krbsrvname
Definition: libpq-int.h:389
#define STATUS_OK
Definition: c.h:1170
void appendPQExpBufferChar(PQExpBuffer str, char ch)
Definition: pqexpbuffer.c:380
PQExpBufferData errorMessage
Definition: libpq-int.h:569
char * PQhost(const PGconn *conn)
Definition: fe-connect.c:6614
#define free(a)
Definition: header.h:65
int pg_GSS_load_servicename(PGconn *conn)
void pg_GSS_error(const char *mprefix, PGconn *conn, OM_uint32 maj_stat, OM_uint32 min_stat)
bool pg_GSS_have_cred_cache(gss_cred_id_t *cred_out)
static void pg_GSS_error_int(PQExpBuffer str, OM_uint32 stat, int type)
#define snprintf
Definition: port.h:216
#define libpq_gettext(x)
Definition: libpq-int.h:846