aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@fys.uio.no>2005-01-04 21:39:01 +0100
committerTrond Myklebust <trond.myklebust@fys.uio.no>2005-01-04 21:39:01 +0100
commit640cdc0b740e07b2cb9acfc216fbd979c330a59e (patch)
tree0ba2d39edb533049dcd69361ce74b286178aeb37 /net
parent06e0fa2f3ec4d93abdf36e59063e77ac8de676c0 (diff)
downloadhistory-640cdc0b740e07b2cb9acfc216fbd979c330a59e.tar.gz
RPCSEC_GSS: When the gss code notices that a cred has expired, mark
the cred containing the context non-uptodate, triggering creation of a new context. Note that on the send-side operations (get_mic, wrap), we mark the cred as not uptodate, but continue trying to use it; the server can complain if it wants to, and the next time through we'll refresh it. Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> Signed-off-by: Trond Myklebust <trond.myklebust@fys.uio.no>
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index a6260098e836e3..629bb0ecb7e288 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -740,7 +740,9 @@ gss_marshal(struct rpc_task *task, u32 *p, int ruid)
maj_stat = gss_get_mic(ctx->gc_gss_ctx,
GSS_C_QOP_DEFAULT,
&verf_buf, &mic);
- if(maj_stat != 0){
+ if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
+ cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+ } else if (maj_stat != 0) {
printk("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat);
goto out_put_ctx;
}
@@ -779,6 +781,7 @@ gss_validate(struct rpc_task *task, u32 *p)
struct xdr_netobj mic;
u32 flav,len;
u32 service;
+ u32 maj_stat;
dprintk("RPC: %4u gss_validate\n", task->tk_pid);
@@ -794,8 +797,11 @@ gss_validate(struct rpc_task *task, u32 *p)
mic.data = (u8 *)p;
mic.len = len;
- if (gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic, &qop_state))
- goto out_bad;
+ maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic, &qop_state);
+ if (maj_stat == GSS_S_CONTEXT_EXPIRED)
+ cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+ if (maj_stat)
+ goto out_bad;
service = gss_pseudoflavor_to_service(ctx->gc_gss_ctx->mech_type,
gss_cred->gc_flavor);
switch (service) {
@@ -821,7 +827,7 @@ out_bad:
}
static inline int
-gss_wrap_req_integ(struct gss_cl_ctx *ctx,
+gss_wrap_req_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
kxdrproc_t encode, void *rqstp, u32 *p, void *obj)
{
struct rpc_rqst *req = (struct rpc_rqst *)rqstp;
@@ -858,7 +864,9 @@ gss_wrap_req_integ(struct gss_cl_ctx *ctx,
maj_stat = gss_get_mic(ctx->gc_gss_ctx,
GSS_C_QOP_DEFAULT, &integ_buf, &mic);
status = -EIO; /* XXX? */
- if (maj_stat)
+ if (maj_stat == GSS_S_CONTEXT_EXPIRED)
+ cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
+ else if (maj_stat)
return status;
q = xdr_encode_opaque(p, NULL, mic.len);
@@ -894,7 +902,8 @@ gss_wrap_req(struct rpc_task *task,
status = encode(rqstp, p, obj);
goto out;
case RPC_GSS_SVC_INTEGRITY:
- status = gss_wrap_req_integ(ctx, encode, rqstp, p, obj);
+ status = gss_wrap_req_integ(cred, ctx, encode,
+ rqstp, p, obj);
goto out;
case RPC_GSS_SVC_PRIVACY:
default:
@@ -907,7 +916,7 @@ out:
}
static inline int
-gss_unwrap_resp_integ(struct gss_cl_ctx *ctx,
+gss_unwrap_resp_integ(struct rpc_cred *cred, struct gss_cl_ctx *ctx,
kxdrproc_t decode, void *rqstp, u32 **p, void *obj)
{
struct rpc_rqst *req = (struct rpc_rqst *)rqstp;
@@ -938,6 +947,8 @@ gss_unwrap_resp_integ(struct gss_cl_ctx *ctx,
maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf,
&mic, NULL);
+ if (maj_stat == GSS_S_CONTEXT_EXPIRED)
+ cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
if (maj_stat != GSS_S_COMPLETE)
return status;
return 0;
@@ -962,7 +973,7 @@ gss_unwrap_resp(struct rpc_task *task,
case RPC_GSS_SVC_NONE:
goto out_decode;
case RPC_GSS_SVC_INTEGRITY:
- status = gss_unwrap_resp_integ(ctx, decode,
+ status = gss_unwrap_resp_integ(cred, ctx, decode,
rqstp, &p, obj);
if (status)
goto out;