Age Owner TLA Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * fe-gssapi-common.c
4 : * The front-end (client) GSSAPI common code
5 : *
6 : * Portions Copyright (c) 1996-2023, 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
832 tgl 26 CBC 2 : pg_GSS_error_int(PQExpBuffer str, OM_uint32 stat, int type)
27 : {
28 : OM_uint32 lmin_s;
29 : gss_buffer_desc lmsg;
1467 sfrost 30 2 : OM_uint32 msg_ctx = 0;
31 :
32 : do
33 : {
832 tgl 34 2 : if (gss_display_status(&lmin_s, stat, type, GSS_C_NO_OID,
35 : &msg_ctx, &lmsg) != GSS_S_COMPLETE)
832 tgl 36 UBC 0 : break;
655 tgl 37 CBC 2 : appendPQExpBufferChar(str, ' ');
38 2 : appendBinaryPQExpBuffer(str, lmsg.value, lmsg.length);
1467 sfrost 39 2 : gss_release_buffer(&lmin_s, &lmsg);
40 2 : } while (msg_ctx);
41 2 : }
42 :
43 : /*
44 : * GSSAPI errors contain two parts; put both into conn->errorMessage.
45 : */
46 : void
47 1 : pg_GSS_error(const char *mprefix, PGconn *conn,
48 : OM_uint32 maj_stat, OM_uint32 min_stat)
49 : {
832 tgl 50 1 : appendPQExpBuffer(&conn->errorMessage, "%s:", mprefix);
51 1 : pg_GSS_error_int(&conn->errorMessage, maj_stat, GSS_C_GSS_CODE);
52 1 : appendPQExpBufferChar(&conn->errorMessage, ':');
53 1 : pg_GSS_error_int(&conn->errorMessage, min_stat, GSS_C_MECH_CODE);
54 1 : appendPQExpBufferChar(&conn->errorMessage, '\n');
1467 sfrost 55 1 : }
56 :
57 : /*
58 : * Check if we can acquire credentials at all (and yield them if so).
59 : */
60 : bool
1311 peter 61 193 : pg_GSS_have_cred_cache(gss_cred_id_t *cred_out)
62 : {
63 : OM_uint32 major,
64 : minor;
1467 sfrost 65 193 : gss_cred_id_t cred = GSS_C_NO_CREDENTIAL;
66 :
67 193 : major = gss_acquire_cred(&minor, GSS_C_NO_NAME, 0, GSS_C_NO_OID_SET,
68 : GSS_C_INITIATE, &cred, NULL, NULL);
69 193 : if (major != GSS_S_COMPLETE)
70 : {
71 175 : *cred_out = NULL;
72 175 : return false;
73 : }
74 18 : *cred_out = cred;
75 18 : return true;
76 : }
77 :
78 : /*
79 : * Try to load service name for a connection
80 : */
81 : int
82 42 : pg_GSS_load_servicename(PGconn *conn)
83 : {
84 : OM_uint32 maj_stat,
85 : min_stat;
86 : int maxlen;
87 : gss_buffer_desc temp_gbuf;
88 : char *host;
89 :
90 42 : if (conn->gtarg_nam != NULL)
91 : /* Already taken care of - move along */
92 18 : return STATUS_OK;
93 :
94 24 : host = PQhost(conn);
95 24 : if (!(host && host[0] != '\0'))
96 : {
145 peter 97 UNC 0 : libpq_append_conn_error(conn, "host name must be specified");
1467 sfrost 98 UIC 0 : return STATUS_ERROR;
99 : }
100 :
101 : /*
102 : * Import service principal name so the proper ticket can be acquired by
103 : * the GSSAPI system.
1467 sfrost 104 ECB : */
832 tgl 105 CBC 24 : maxlen = strlen(conn->krbsrvname) + strlen(host) + 2;
1467 sfrost 106 24 : temp_gbuf.value = (char *) malloc(maxlen);
1467 sfrost 107 GIC 24 : if (!temp_gbuf.value)
1467 sfrost 108 EUB : {
145 peter 109 UNC 0 : libpq_append_conn_error(conn, "out of memory");
1467 sfrost 110 LBC 0 : return STATUS_ERROR;
111 : }
1467 sfrost 112 CBC 24 : snprintf(temp_gbuf.value, maxlen, "%s@%s",
113 : conn->krbsrvname, host);
114 24 : temp_gbuf.length = strlen(temp_gbuf.value);
115 :
116 24 : maj_stat = gss_import_name(&min_stat, &temp_gbuf,
117 : GSS_C_NT_HOSTBASED_SERVICE, &conn->gtarg_nam);
118 24 : free(temp_gbuf.value);
119 :
1467 sfrost 120 GBC 24 : if (maj_stat != GSS_S_COMPLETE)
121 : {
1467 sfrost 122 UIC 0 : pg_GSS_error(libpq_gettext("GSSAPI name import error"),
1467 sfrost 123 EUB : conn,
124 : maj_stat, min_stat);
1467 sfrost 125 LBC 0 : return STATUS_ERROR;
126 : }
1467 sfrost 127 GIC 24 : return STATUS_OK;
128 : }
|