#include <netinet/in.h>
#include <gssapi/gssapi.h>
-static void authgss_nextverf();
-static bool_t authgss_marshal();
-static bool_t authgss_refresh();
-static bool_t authgss_validate();
-static void authgss_destroy();
-static void authgss_destroy_context();
-static bool_t authgss_wrap();
-static bool_t authgss_unwrap();
+#include "debug.h"
+
+static void authgss_nextverf(AUTH *);
+static bool_t authgss_marshal(AUTH *, XDR *);
+static bool_t authgss_refresh(AUTH *, void *);
+static bool_t authgss_validate(AUTH *, struct opaque_auth *);
+static void authgss_destroy(AUTH *);
+static void authgss_destroy_context(AUTH *);
+static bool_t authgss_wrap(AUTH *, XDR *, xdrproc_t, caddr_t);
+static bool_t authgss_unwrap(AUTH *, XDR *, xdrproc_t, caddr_t);
/*
authgss_unwrap
};
-#ifdef DEBUG
/* useful as i add more mechanisms */
void
int i;
char *p;
- log_debug("rpc_gss_sec:");
+ if (libtirpc_debug_level < 4 || log_stderr == 0)
+ return;
+
+ gss_log_debug("rpc_gss_sec:");
if(ptr->mech == NULL)
- log_debug("NULL gss_OID mech");
+ gss_log_debug("NULL gss_OID mech");
else {
fprintf(stderr, " mechanism_OID: {");
p = (char *)ptr->mech->elements;
fprintf(stderr, " service: %d\n", ptr->svc);
fprintf(stderr, " cred: %p\n", ptr->cred);
}
-#endif /*DEBUG*/
struct rpc_gss_data {
bool_t established; /* context established */
struct rpc_gss_data *gd;
OM_uint32 min_stat = 0;
- log_debug("in authgss_create()");
+ gss_log_debug("in authgss_create()");
memset(&rpc_createerr, 0, sizeof(rpc_createerr));
free(auth);
return (NULL);
}
-#ifdef DEBUG
- fprintf(stderr, "authgss_create: name is %p\n", name);
-#endif
+ LIBTIRPC_DEBUG(3, ("authgss_create: name is %p", name));
if (name != GSS_C_NO_NAME) {
if (gss_duplicate_name(&min_stat, name, &gd->name)
!= GSS_S_COMPLETE) {
else
gd->name = name;
-#ifdef DEBUG
- fprintf(stderr, "authgss_create: gd->name is %p\n", gd->name);
-#endif
+ LIBTIRPC_DEBUG(3, ("authgss_create: gd->name is %p", gd->name));
gd->clnt = clnt;
gd->ctx = GSS_C_NO_CONTEXT;
gd->sec = *sec;
save_auth = clnt->cl_auth;
clnt->cl_auth = auth;
- if (!authgss_refresh(auth))
+ if (!authgss_refresh(auth, NULL))
auth = NULL;
+ else
+ auth_get(auth); /* Reference for caller */
clnt->cl_auth = save_auth;
gss_buffer_desc sname;
gss_name_t name = GSS_C_NO_NAME;
- log_debug("in authgss_create_default()");
+ gss_log_debug("in authgss_create_default()");
sname.value = service;
&name);
if (maj_stat != GSS_S_COMPLETE) {
- log_status("gss_import_name", maj_stat, min_stat);
+ gss_log_status("authgss_create_default: gss_import_name",
+ maj_stat, min_stat);
rpc_createerr.cf_stat = RPC_AUTHERROR;
return (NULL);
}
auth = authgss_create(clnt, name, sec);
if (name != GSS_C_NO_NAME) {
-#ifdef DEBUG
- fprintf(stderr, "authgss_create_default: freeing name %p\n", name);
-#endif
+ LIBTIRPC_DEBUG(3, ("authgss_create_default: freeing name %p", name));
gss_release_name(&min_stat, &name);
}
{
struct rpc_gss_data *gd;
- log_debug("in authgss_get_private_data()");
+ gss_log_debug("in authgss_get_private_data()");
if (!auth || !pd)
return (FALSE);
pd->pd_ctx = gd->ctx;
pd->pd_ctx_hndl = gd->gc.gc_ctx;
pd->pd_seq_win = gd->win;
+ /*
+ * We've given this away -- don't try to use it ourself any more
+ * Caller should call authgss_free_private_data to free data.
+ * This also ensures that authgss_destroy_context() won't try to
+ * send an RPCSEC_GSS_DESTROY request which might inappropriately
+ * destroy the context.
+ */
+ gd->ctx = GSS_C_NO_CONTEXT;
+ gd->gc.gc_ctx.length = 0;
+ gd->gc.gc_ctx.value = NULL;
+
+ return (TRUE);
+}
+
+bool_t
+authgss_free_private_data(struct authgss_private_data *pd)
+{
+ OM_uint32 min_stat;
+ gss_log_debug("in authgss_free_private_data()");
+
+ if (!pd)
+ return (FALSE);
+
+ if (pd->pd_ctx != GSS_C_NO_CONTEXT)
+ gss_delete_sec_context(&min_stat, &pd->pd_ctx, NULL);
+ gss_release_buffer(&min_stat, &pd->pd_ctx_hndl);
+ memset(&pd->pd_ctx_hndl, 0, sizeof(pd->pd_ctx_hndl));
+ pd->pd_seq_win = 0;
return (TRUE);
}
static void
authgss_nextverf(AUTH *auth)
{
- log_debug("in authgss_nextverf()");
+ gss_log_debug("in authgss_nextverf()");
/* no action necessary */
}
OM_uint32 maj_stat, min_stat;
bool_t xdr_stat;
- log_debug("in authgss_marshal()");
+ gss_log_debug("in authgss_marshal()");
gd = AUTH_PRIVATE(auth);
&rpcbuf, &checksum);
if (maj_stat != GSS_S_COMPLETE) {
- log_status("gss_get_mic", maj_stat, min_stat);
+ gss_log_status("authgss_marshal: gss_get_mic",
+ maj_stat, min_stat);
if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
gd->established = FALSE;
authgss_destroy_context(auth);
gss_buffer_desc signbuf, checksum;
OM_uint32 maj_stat, min_stat;
- log_debug("in authgss_validate()");
+ gss_log_debug("in authgss_validate()");
gd = AUTH_PRIVATE(auth);
maj_stat = gss_verify_mic(&min_stat, gd->ctx, &signbuf,
&checksum, &qop_state);
+
if (maj_stat != GSS_S_COMPLETE || qop_state != gd->sec.qop) {
- log_status("gss_verify_mic", maj_stat, min_stat);
+ gss_log_status("authgss_validate: gss_verify_mic",
+ maj_stat, min_stat);
if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
gd->established = FALSE;
authgss_destroy_context(auth);
}
static bool_t
-authgss_refresh(AUTH *auth)
+authgss_refresh(AUTH *auth, void *dummy)
{
struct rpc_gss_data *gd;
struct rpc_gss_init_res gr;
gss_buffer_desc *recv_tokenp, send_token;
OM_uint32 maj_stat, min_stat, call_stat, ret_flags;
- log_debug("in authgss_refresh()");
+ gss_log_debug("in authgss_refresh()");
gd = AUTH_PRIVATE(auth);
memset(&gr, 0, sizeof(gr));
recv_tokenp = GSS_C_NO_BUFFER;
-#ifdef DEBUG
print_rpc_gss_sec(&gd->sec);
-#endif /*DEBUG*/
for (;;) {
-#ifdef DEBUG
/* print the token we just received */
if (recv_tokenp != GSS_C_NO_BUFFER) {
- log_debug("The token we just received (length %d):",
+ gss_log_debug("The token we just received (length %d):",
recv_tokenp->length);
- log_hexdump(recv_tokenp->value, recv_tokenp->length, 0);
+ gss_log_hexdump(recv_tokenp->value, recv_tokenp->length, 0);
}
-#endif
maj_stat = gss_init_sec_context(&min_stat,
gd->sec.cred,
&gd->ctx,
}
if (maj_stat != GSS_S_COMPLETE &&
maj_stat != GSS_S_CONTINUE_NEEDED) {
- log_status("gss_init_sec_context", maj_stat, min_stat);
+ gss_log_status("authgss_refresh: gss_init_sec_context",
+ maj_stat, min_stat);
break;
}
if (send_token.length != 0) {
memset(&gr, 0, sizeof(gr));
-#ifdef DEBUG
/* print the token we are about to send */
- log_debug("The token being sent (length %d):",
+ gss_log_debug("The token being sent (length %d):",
send_token.length);
- log_hexdump(send_token.value, send_token.length, 0);
-#endif
+ gss_log_hexdump(send_token.value, send_token.length, 0);
call_stat = clnt_call(gd->clnt, NULLPROC,
(xdrproc_t)xdr_rpc_gss_init_args,
if (maj_stat != GSS_S_COMPLETE
|| qop_state != gd->sec.qop) {
- log_status("gss_verify_mic", maj_stat, min_stat);
+ gss_log_status("authgss_refresh: gss_verify_mic",
+ maj_stat, min_stat);
if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
gd->established = FALSE;
authgss_destroy_context(auth);
{
struct rpc_gss_data *gd;
- log_debug("in authgss_service()");
+ gss_log_debug("in authgss_service()");
if (!auth)
return(FALSE);
struct rpc_gss_data *gd;
OM_uint32 min_stat;
- log_debug("in authgss_destroy_context()");
+ gss_log_debug("in authgss_destroy_context()");
gd = AUTH_PRIVATE(auth);
if (gd->gc.gc_ctx.length != 0) {
if (gd->established) {
+ AUTH *save_auth = NULL;
+
+ /* Make sure we use the right auth_ops */
+ if (gd->clnt->cl_auth != auth) {
+ save_auth = gd->clnt->cl_auth;
+ gd->clnt->cl_auth = auth;
+ }
+
gd->gc.gc_proc = RPCSEC_GSS_DESTROY;
clnt_call(gd->clnt, NULLPROC, (xdrproc_t)xdr_void, NULL,
(xdrproc_t)xdr_void, NULL, AUTH_TIMEOUT);
+
+ if (save_auth != NULL)
+ gd->clnt->cl_auth = save_auth;
}
gss_release_buffer(&min_stat, &gd->gc.gc_ctx);
/* XXX ANDROS check size of context - should be 8 */
struct rpc_gss_data *gd;
OM_uint32 min_stat;
- log_debug("in authgss_destroy()");
+ gss_log_debug("in authgss_destroy()");
gd = AUTH_PRIVATE(auth);
authgss_destroy_context(auth);
-#ifdef DEBUG
- fprintf(stderr, "authgss_destroy: freeing name %p\n", gd->name);
-#endif
+ LIBTIRPC_DEBUG(3, ("authgss_destroy: freeing name %p", gd->name));
if (gd->name != GSS_C_NO_NAME)
gss_release_name(&min_stat, &gd->name);
free(auth);
}
-bool_t
+static bool_t
authgss_wrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr)
{
struct rpc_gss_data *gd;
- log_debug("in authgss_wrap()");
+ gss_log_debug("in authgss_wrap()");
gd = AUTH_PRIVATE(auth);
gd->sec.svc, gd->gc.gc_seq));
}
-bool_t
+static bool_t
authgss_unwrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr)
{
struct rpc_gss_data *gd;
- log_debug("in authgss_unwrap()");
+ gss_log_debug("in authgss_unwrap()");
gd = AUTH_PRIVATE(auth);