Commit 640cdc0b authored by Trond Myklebust's avatar Trond Myklebust

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: default avatarJ. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@fys.uio.no>
parent 06e0fa2f
...@@ -740,7 +740,9 @@ gss_marshal(struct rpc_task *task, u32 *p, int ruid) ...@@ -740,7 +740,9 @@ gss_marshal(struct rpc_task *task, u32 *p, int ruid)
maj_stat = gss_get_mic(ctx->gc_gss_ctx, maj_stat = gss_get_mic(ctx->gc_gss_ctx,
GSS_C_QOP_DEFAULT, GSS_C_QOP_DEFAULT,
&verf_buf, &mic); &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); printk("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat);
goto out_put_ctx; goto out_put_ctx;
} }
...@@ -779,6 +781,7 @@ gss_validate(struct rpc_task *task, u32 *p) ...@@ -779,6 +781,7 @@ gss_validate(struct rpc_task *task, u32 *p)
struct xdr_netobj mic; struct xdr_netobj mic;
u32 flav,len; u32 flav,len;
u32 service; u32 service;
u32 maj_stat;
dprintk("RPC: %4u gss_validate\n", task->tk_pid); dprintk("RPC: %4u gss_validate\n", task->tk_pid);
...@@ -794,8 +797,11 @@ gss_validate(struct rpc_task *task, u32 *p) ...@@ -794,8 +797,11 @@ gss_validate(struct rpc_task *task, u32 *p)
mic.data = (u8 *)p; mic.data = (u8 *)p;
mic.len = len; mic.len = len;
if (gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic, &qop_state)) maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &verf_buf, &mic, &qop_state);
goto out_bad; 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, service = gss_pseudoflavor_to_service(ctx->gc_gss_ctx->mech_type,
gss_cred->gc_flavor); gss_cred->gc_flavor);
switch (service) { switch (service) {
...@@ -821,7 +827,7 @@ gss_validate(struct rpc_task *task, u32 *p) ...@@ -821,7 +827,7 @@ gss_validate(struct rpc_task *task, u32 *p)
} }
static inline int 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) kxdrproc_t encode, void *rqstp, u32 *p, void *obj)
{ {
struct rpc_rqst *req = (struct rpc_rqst *)rqstp; struct rpc_rqst *req = (struct rpc_rqst *)rqstp;
...@@ -858,7 +864,9 @@ gss_wrap_req_integ(struct gss_cl_ctx *ctx, ...@@ -858,7 +864,9 @@ gss_wrap_req_integ(struct gss_cl_ctx *ctx,
maj_stat = gss_get_mic(ctx->gc_gss_ctx, maj_stat = gss_get_mic(ctx->gc_gss_ctx,
GSS_C_QOP_DEFAULT, &integ_buf, &mic); GSS_C_QOP_DEFAULT, &integ_buf, &mic);
status = -EIO; /* XXX? */ 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; return status;
q = xdr_encode_opaque(p, NULL, mic.len); q = xdr_encode_opaque(p, NULL, mic.len);
...@@ -894,7 +902,8 @@ gss_wrap_req(struct rpc_task *task, ...@@ -894,7 +902,8 @@ gss_wrap_req(struct rpc_task *task,
status = encode(rqstp, p, obj); status = encode(rqstp, p, obj);
goto out; goto out;
case RPC_GSS_SVC_INTEGRITY: 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; goto out;
case RPC_GSS_SVC_PRIVACY: case RPC_GSS_SVC_PRIVACY:
default: default:
...@@ -907,7 +916,7 @@ gss_wrap_req(struct rpc_task *task, ...@@ -907,7 +916,7 @@ gss_wrap_req(struct rpc_task *task,
} }
static inline int 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) kxdrproc_t decode, void *rqstp, u32 **p, void *obj)
{ {
struct rpc_rqst *req = (struct rpc_rqst *)rqstp; struct rpc_rqst *req = (struct rpc_rqst *)rqstp;
...@@ -938,6 +947,8 @@ gss_unwrap_resp_integ(struct gss_cl_ctx *ctx, ...@@ -938,6 +947,8 @@ gss_unwrap_resp_integ(struct gss_cl_ctx *ctx,
maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf, maj_stat = gss_verify_mic(ctx->gc_gss_ctx, &integ_buf,
&mic, NULL); &mic, NULL);
if (maj_stat == GSS_S_CONTEXT_EXPIRED)
cred->cr_flags &= ~RPCAUTH_CRED_UPTODATE;
if (maj_stat != GSS_S_COMPLETE) if (maj_stat != GSS_S_COMPLETE)
return status; return status;
return 0; return 0;
...@@ -962,7 +973,7 @@ gss_unwrap_resp(struct rpc_task *task, ...@@ -962,7 +973,7 @@ gss_unwrap_resp(struct rpc_task *task,
case RPC_GSS_SVC_NONE: case RPC_GSS_SVC_NONE:
goto out_decode; goto out_decode;
case RPC_GSS_SVC_INTEGRITY: case RPC_GSS_SVC_INTEGRITY:
status = gss_unwrap_resp_integ(ctx, decode, status = gss_unwrap_resp_integ(cred, ctx, decode,
rqstp, &p, obj); rqstp, &p, obj);
if (status) if (status)
goto out; goto out;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment