mirror of
https://github.com/postgres/postgres.git
synced 2025-04-24 10:47:04 +03:00
The term "ccache" is overloaded. Let's be more clear, in case someone other than a Kerberos wizard has to read this code.
131 lines
3.0 KiB
C
131 lines
3.0 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* fe-gssapi-common.c
|
|
* The front-end (client) GSSAPI common code
|
|
*
|
|
* Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
* IDENTIFICATION
|
|
* src/interfaces/libpq/fe-gssapi-common.c
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include "postgres_fe.h"
|
|
|
|
#include "fe-gssapi-common.h"
|
|
|
|
#include "libpq-int.h"
|
|
#include "pqexpbuffer.h"
|
|
|
|
/*
|
|
* Fetch all errors of a specific type and append to "str".
|
|
*/
|
|
static void
|
|
pg_GSS_error_int(PQExpBuffer str, const char *mprefix,
|
|
OM_uint32 stat, int type)
|
|
{
|
|
OM_uint32 lmin_s;
|
|
gss_buffer_desc lmsg;
|
|
OM_uint32 msg_ctx = 0;
|
|
|
|
do
|
|
{
|
|
gss_display_status(&lmin_s, stat, type,
|
|
GSS_C_NO_OID, &msg_ctx, &lmsg);
|
|
appendPQExpBuffer(str, "%s: %s\n", mprefix, (char *) lmsg.value);
|
|
gss_release_buffer(&lmin_s, &lmsg);
|
|
} while (msg_ctx);
|
|
}
|
|
|
|
/*
|
|
* GSSAPI errors contain two parts; put both into conn->errorMessage.
|
|
*/
|
|
void
|
|
pg_GSS_error(const char *mprefix, PGconn *conn,
|
|
OM_uint32 maj_stat, OM_uint32 min_stat)
|
|
{
|
|
resetPQExpBuffer(&conn->errorMessage);
|
|
|
|
/* Fetch major error codes */
|
|
pg_GSS_error_int(&conn->errorMessage, mprefix, maj_stat, GSS_C_GSS_CODE);
|
|
|
|
/* Add the minor codes as well */
|
|
pg_GSS_error_int(&conn->errorMessage, mprefix, min_stat, GSS_C_MECH_CODE);
|
|
}
|
|
|
|
/*
|
|
* Check if we can acquire credentials at all (and yield them if so).
|
|
*/
|
|
bool
|
|
pg_GSS_have_cred_cache(gss_cred_id_t *cred_out)
|
|
{
|
|
OM_uint32 major,
|
|
minor;
|
|
gss_cred_id_t cred = GSS_C_NO_CREDENTIAL;
|
|
|
|
major = gss_acquire_cred(&minor, GSS_C_NO_NAME, 0, GSS_C_NO_OID_SET,
|
|
GSS_C_INITIATE, &cred, NULL, NULL);
|
|
if (major != GSS_S_COMPLETE)
|
|
{
|
|
*cred_out = NULL;
|
|
return false;
|
|
}
|
|
*cred_out = cred;
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Try to load service name for a connection
|
|
*/
|
|
int
|
|
pg_GSS_load_servicename(PGconn *conn)
|
|
{
|
|
OM_uint32 maj_stat,
|
|
min_stat;
|
|
int maxlen;
|
|
gss_buffer_desc temp_gbuf;
|
|
char *host;
|
|
|
|
if (conn->gtarg_nam != NULL)
|
|
/* Already taken care of - move along */
|
|
return STATUS_OK;
|
|
|
|
host = PQhost(conn);
|
|
if (!(host && host[0] != '\0'))
|
|
{
|
|
printfPQExpBuffer(&conn->errorMessage,
|
|
libpq_gettext("host name must be specified\n"));
|
|
return STATUS_ERROR;
|
|
}
|
|
|
|
/*
|
|
* Import service principal name so the proper ticket can be acquired by
|
|
* the GSSAPI system.
|
|
*/
|
|
maxlen = NI_MAXHOST + strlen(conn->krbsrvname) + 2;
|
|
temp_gbuf.value = (char *) malloc(maxlen);
|
|
if (!temp_gbuf.value)
|
|
{
|
|
printfPQExpBuffer(&conn->errorMessage,
|
|
libpq_gettext("out of memory\n"));
|
|
return STATUS_ERROR;
|
|
}
|
|
snprintf(temp_gbuf.value, maxlen, "%s@%s",
|
|
conn->krbsrvname, host);
|
|
temp_gbuf.length = strlen(temp_gbuf.value);
|
|
|
|
maj_stat = gss_import_name(&min_stat, &temp_gbuf,
|
|
GSS_C_NT_HOSTBASED_SERVICE, &conn->gtarg_nam);
|
|
free(temp_gbuf.value);
|
|
|
|
if (maj_stat != GSS_S_COMPLETE)
|
|
{
|
|
pg_GSS_error(libpq_gettext("GSSAPI name import error"),
|
|
conn,
|
|
maj_stat, min_stat);
|
|
return STATUS_ERROR;
|
|
}
|
|
return STATUS_OK;
|
|
}
|