struct svc_rpc_gss_data {
bool_t established; /* context established */
+ gss_cred_id_t cred; /* credential */
gss_ctx_id_t ctx; /* context id */
struct rpc_gss_sec sec; /* security triple */
gss_buffer_desc cname; /* GSS client name */
}
static bool_t
-svcauth_gss_acquire_cred(void)
+svcauth_gss_acquire_cred(struct svc_rpc_gss_data *gd)
{
OM_uint32 maj_stat, min_stat;
log_debug("in svcauth_gss_acquire_cred()");
+ /* We don't need to acquire a credential if using the default name. */
+ if (svcauth_gss_name == GSS_C_NO_NAME)
+ return (TRUE);
+
+ /* Only acquire a credential once per authentication. */
+ if (gd->cred != GSS_C_NO_CREDENTIAL)
+ return (TRUE);
+
maj_stat = gss_acquire_cred(&min_stat, svcauth_gss_name, 0,
GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
- &svcauth_gss_creds, NULL, NULL);
+ &gd->cred, NULL, NULL);
if (maj_stat != GSS_S_COMPLETE) {
log_status("gss_acquire_cred", maj_stat, min_stat);
return (TRUE);
}
-static bool_t
-svcauth_gss_release_cred(void)
-{
- OM_uint32 maj_stat, min_stat;
-
- log_debug("in svcauth_gss_release_cred()");
-
- maj_stat = gss_release_cred(&min_stat, &svcauth_gss_creds);
-
- if (maj_stat != GSS_S_COMPLETE) {
- log_status("gss_release_cred", maj_stat, min_stat);
- return (FALSE);
- }
-
- svcauth_gss_creds = NULL;
-
- return (TRUE);
-}
-
/* Invoke log_badauth callbacks for an authentication failure. */
static void
badauth(OM_uint32 maj, OM_uint32 minor, SVCXPRT *xprt)
gr->gr_major = gss_accept_sec_context(&gr->gr_minor,
&gd->ctx,
- svcauth_gss_creds,
+ gd->cred,
&recv_tok,
GSS_C_NO_CHANNEL_BINDINGS,
&gd->client_name,
if (rqst->rq_proc != NULLPROC)
ret_freegc (AUTH_FAILED); /* XXX ? */
- if (!svcauth_gss_acquire_cred())
+ if (!svcauth_gss_acquire_cred(gd))
ret_freegc (AUTH_FAILED);
if (!svcauth_gss_accept_sec_context(rqst, &gr))
log_debug("sendreply in destroy: %d", call_stat);
- if (!svcauth_gss_release_cred())
- ret_freegc (AUTH_FAILED);
-
SVCAUTH_DESTROY(rqst->rq_xprt->xp_auth);
rqst->rq_xprt->xp_auth = &svc_auth_none;
gd = SVCAUTH_PRIVATE(auth);
gss_delete_sec_context(&min_stat, &gd->ctx, GSS_C_NO_BUFFER);
+ gss_release_cred(&min_stat, &gd->cred);
gss_release_buffer(&min_stat, &gd->cname);
gss_release_buffer(&min_stat, &gd->checksum);