aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2007-06-26 17:04:57 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-07-10 23:40:37 -0400
commit0df7fb74fbb709591301871a38aac7735a1d6583 (patch)
treea5fc18f5aa581a7e8591551f17e86902b5a7e6b3 /net/sunrpc
parent0285ed1f12298e5304f0f2642e2cf31a5f302e61 (diff)
SUNRPC: Ensure RPCSEC_GSS destroys the security context when freeing a cred
Do so by set the gc_proc field to RPC_GSS_PROC_DESTROY, and then sending a NULL RPC call. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c60
1 files changed, 58 insertions, 2 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 982aba697e4d..17d460f85f0e 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -57,6 +57,7 @@
57static const struct rpc_authops authgss_ops; 57static const struct rpc_authops authgss_ops;
58 58
59static const struct rpc_credops gss_credops; 59static const struct rpc_credops gss_credops;
60static const struct rpc_credops gss_nullops;
60 61
61#ifdef RPC_DEBUG 62#ifdef RPC_DEBUG
62# define RPCDBG_FACILITY RPCDBG_AUTH 63# define RPCDBG_FACILITY RPCDBG_AUTH
@@ -695,7 +696,39 @@ gss_destroy(struct rpc_auth *auth)
695 kref_put(&gss_auth->kref, gss_free_callback); 696 kref_put(&gss_auth->kref, gss_free_callback);
696} 697}
697 698
698/* gss_destroy_cred (and gss_destroy_ctx) are used to clean up after failure 699/*
700 * gss_destroying_context will cause the RPCSEC_GSS to send a NULL RPC call
701 * to the server with the GSS control procedure field set to
702 * RPC_GSS_PROC_DESTROY. This should normally cause the server to release
703 * all RPCSEC_GSS state associated with that context.
704 */
705static int
706gss_destroying_context(struct rpc_cred *cred)
707{
708 struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base);
709 struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth);
710 struct rpc_task *task;
711
712 if (gss_cred->gc_ctx == NULL ||
713 gss_cred->gc_ctx->gc_proc == RPC_GSS_PROC_DESTROY)
714 return 0;
715
716 gss_cred->gc_ctx->gc_proc = RPC_GSS_PROC_DESTROY;
717 cred->cr_ops = &gss_nullops;
718
719 /* Take a reference to ensure the cred will be destroyed either
720 * by the RPC call or by the put_rpccred() below */
721 get_rpccred(cred);
722
723 task = rpc_call_null(gss_auth->client, cred, RPC_TASK_ASYNC);
724 if (!IS_ERR(task))
725 rpc_put_task(task);
726
727 put_rpccred(cred);
728 return 1;
729}
730
731/* gss_destroy_cred (and gss_free_ctx) are used to clean up after failure
699 * to create a new cred or context, so they check that things have been 732 * to create a new cred or context, so they check that things have been
700 * allocated before freeing them. */ 733 * allocated before freeing them. */
701static void 734static void
@@ -744,6 +777,8 @@ gss_destroy_cred(struct rpc_cred *cred)
744 struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth); 777 struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth);
745 struct gss_cl_ctx *ctx = gss_cred->gc_ctx; 778 struct gss_cl_ctx *ctx = gss_cred->gc_ctx;
746 779
780 if (gss_destroying_context(cred))
781 return;
747 rcu_assign_pointer(gss_cred->gc_ctx, NULL); 782 rcu_assign_pointer(gss_cred->gc_ctx, NULL);
748 call_rcu(&cred->cr_rcu, gss_free_cred_callback); 783 call_rcu(&cred->cr_rcu, gss_free_cred_callback);
749 if (ctx) 784 if (ctx)
@@ -892,6 +927,13 @@ gss_refresh(struct rpc_task *task)
892 return 0; 927 return 0;
893} 928}
894 929
930/* Dummy refresh routine: used only when destroying the context */
931static int
932gss_refresh_null(struct rpc_task *task)
933{
934 return -EACCES;
935}
936
895static __be32 * 937static __be32 *
896gss_validate(struct rpc_task *task, __be32 *p) 938gss_validate(struct rpc_task *task, __be32 *p)
897{ 939{
@@ -921,8 +963,11 @@ gss_validate(struct rpc_task *task, __be32 *p)
921 maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic); 963 maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
922 if (maj_stat == GSS_S_CONTEXT_EXPIRED) 964 if (maj_stat == GSS_S_CONTEXT_EXPIRED)
923 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags); 965 clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
924 if (maj_stat) 966 if (maj_stat) {
967 dprintk("RPC: %5u gss_validate: gss_verify_mic returned"
968 "error 0x%08x\n", task->tk_pid, maj_stat);
925 goto out_bad; 969 goto out_bad;
970 }
926 /* We leave it to unwrap to calculate au_rslack. For now we just 971 /* We leave it to unwrap to calculate au_rslack. For now we just
927 * calculate the length of the verifier: */ 972 * calculate the length of the verifier: */
928 cred->cr_auth->au_verfsize = XDR_QUADLEN(len) + 2; 973 cred->cr_auth->au_verfsize = XDR_QUADLEN(len) + 2;
@@ -1260,6 +1305,17 @@ static const struct rpc_credops gss_credops = {
1260 .crunwrap_resp = gss_unwrap_resp, 1305 .crunwrap_resp = gss_unwrap_resp,
1261}; 1306};
1262 1307
1308static const struct rpc_credops gss_nullops = {
1309 .cr_name = "AUTH_GSS",
1310 .crdestroy = gss_destroy_cred,
1311 .crmatch = gss_match,
1312 .crmarshal = gss_marshal,
1313 .crrefresh = gss_refresh_null,
1314 .crvalidate = gss_validate,
1315 .crwrap_req = gss_wrap_req,
1316 .crunwrap_resp = gss_unwrap_resp,
1317};
1318
1263static struct rpc_pipe_ops gss_upcall_ops = { 1319static struct rpc_pipe_ops gss_upcall_ops = {
1264 .upcall = gss_pipe_upcall, 1320 .upcall = gss_pipe_upcall,
1265 .downcall = gss_pipe_downcall, 1321 .downcall = gss_pipe_downcall,