Author: J. Bruce Fields SUNRPC,RPCSEC_GSS: fix krb5 sequence numbers. Use a spinlock to ensure unique sequence numbers when creating krb5 gss tokens. Signed-off-by: J. Bruce Fields Signed-off-by: Trond Myklebust --- include/linux/sunrpc/gss_krb5.h | 2 ++ net/sunrpc/auth_gss/gss_krb5_seal.c | 11 ++++++++--- net/sunrpc/auth_gss/gss_krb5_wrap.c | 9 ++++++--- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index 2c3601d..1279280 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -53,6 +53,8 @@ struct krb5_ctx { struct xdr_netobj mech_used; }; +extern spinlock_t krb5_seq_lock; + #define KG_TOK_MIC_MSG 0x0101 #define KG_TOK_WRAP_MSG 0x0201 diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c index 58f9721..f433112 100644 --- a/net/sunrpc/auth_gss/gss_krb5_seal.c +++ b/net/sunrpc/auth_gss/gss_krb5_seal.c @@ -70,6 +70,8 @@ # define RPCDBG_FACILITY RPCDBG_AUTH #endif +spinlock_t krb5_seq_lock = SPIN_LOCK_UNLOCKED; + u32 gss_get_mic_kerberos(struct gss_ctx *gss_ctx, struct xdr_buf *text, struct xdr_netobj *token) @@ -80,6 +82,7 @@ gss_get_mic_kerberos(struct gss_ctx *gss struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata}; unsigned char *ptr, *krb5_hdr, *msg_start; s32 now; + u32 seq_send; dprintk("RPC: gss_krb5_seal\n"); @@ -134,12 +137,14 @@ gss_get_mic_kerberos(struct gss_ctx *gss BUG(); } + spin_lock(&krb5_seq_lock); + seq_send = ctx->seq_send++; + spin_unlock(&krb5_seq_lock); + if ((krb5_make_seq_num(ctx->seq, ctx->initiate ? 0 : 0xff, - ctx->seq_send, krb5_hdr + 16, krb5_hdr + 8))) + seq_send, krb5_hdr + 16, krb5_hdr + 8))) goto out_err; - ctx->seq_send++; - return ((ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE); out_err: return GSS_S_FAILURE; diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index 346133e..89d1f3e 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c @@ -128,6 +128,7 @@ gss_wrap_kerberos(struct gss_ctx *ctx, i s32 now; int headlen; struct page **tmp_pages; + u32 seq_send; dprintk("RPC: gss_wrap_kerberos\n"); @@ -206,18 +207,20 @@ gss_wrap_kerberos(struct gss_ctx *ctx, i BUG(); } + spin_lock(&krb5_seq_lock); + seq_send = kctx->seq_send++; + spin_unlock(&krb5_seq_lock); + /* XXX would probably be more efficient to compute checksum * and encrypt at the same time: */ if ((krb5_make_seq_num(kctx->seq, kctx->initiate ? 0 : 0xff, - kctx->seq_send, krb5_hdr + 16, krb5_hdr + 8))) + seq_send, krb5_hdr + 16, krb5_hdr + 8))) goto out_err; if (gss_encrypt_xdr_buf(kctx->enc, buf, offset + headlen - blocksize, pages)) goto out_err; - kctx->seq_send++; - return ((kctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE); out_err: return GSS_S_FAILURE;