diff --git a/lustre/ptlrpc/gss/gss_api.h b/lustre/ptlrpc/gss/gss_api.h index d38e4d20deb4f9071e5a2061bb700ccfa288a6c3..e6f68d359f7ae53fc52916625d0bce10cc01fa0b 100644 --- a/lustre/ptlrpc/gss/gss_api.h +++ b/lustre/ptlrpc/gss/gss_api.h @@ -58,11 +58,13 @@ __u32 lgss_verify_mic( rawobj_t *mic_token); __u32 lgss_wrap( struct gss_ctx *ctx, + rawobj_t *gsshdr, rawobj_t *msg, int msg_buflen, rawobj_t *out_token); __u32 lgss_unwrap( struct gss_ctx *ctx, + rawobj_t *gsshdr, rawobj_t *token, rawobj_t *out_msg); __u32 lgss_plain_encrypt( @@ -120,11 +122,13 @@ struct gss_api_ops { rawobj_t *mic_token); __u32 (*gss_wrap)( struct gss_ctx *ctx, + rawobj_t *gsshdr, rawobj_t *msg, int msg_buflen, rawobj_t *out_token); __u32 (*gss_unwrap)( struct gss_ctx *ctx, + rawobj_t *gsshdr, rawobj_t *token, rawobj_t *out_msg); __u32 (*gss_plain_encrypt)( diff --git a/lustre/ptlrpc/gss/gss_krb5_mech.c b/lustre/ptlrpc/gss/gss_krb5_mech.c index 3b7da5c23a5a90bb0e78bbfe7765ca26ac3ef789..3dc02c74c7307b2cf7498e5475601ca7685ec9d6 100644 --- a/lustre/ptlrpc/gss/gss_krb5_mech.c +++ b/lustre/ptlrpc/gss/gss_krb5_mech.c @@ -902,6 +902,7 @@ int krb5_encrypt_rawobjs(struct ll_crypto_cipher *tfm, static __u32 gss_wrap_kerberos(struct gss_ctx *gctx, + rawobj_t *gsshdr, rawobj_t *msg, int msg_buflen, rawobj_t *token) @@ -912,7 +913,7 @@ __u32 gss_wrap_kerberos(struct gss_ctx *gctx, unsigned char acceptor_flag; int blocksize; rawobj_t cksum = RAWOBJ_EMPTY; - rawobj_t data_desc[3], cipher; + rawobj_t data_desc[4], cipher; __u8 conf[GSS_MAX_CIPHER_BLOCK]; int enc_rc = 0; @@ -922,11 +923,17 @@ __u32 gss_wrap_kerberos(struct gss_ctx *gctx, ke->ke_conf_size >= ll_crypto_blkcipher_blocksize(kctx->kc_keye.kb_tfm)); - acceptor_flag = kctx->kc_initiate ? 0 : FLAG_SENDER_IS_ACCEPTOR; + /* + * final token format: + * --------------------------------------------------- + * | krb5 header | cipher text | checksum (16 bytes) | + * --------------------------------------------------- + */ /* fill krb5 header */ LASSERT(token->len >= sizeof(*khdr)); khdr = (struct krb5_header *) token->data; + acceptor_flag = kctx->kc_initiate ? 0 : FLAG_SENDER_IS_ACCEPTOR; khdr->kh_tok_id = cpu_to_be16(KG_TOK_WRAP_MSG); khdr->kh_flags = acceptor_flag | FLAG_WRAP_CONFIDENTIAL; @@ -956,7 +963,28 @@ __u32 gss_wrap_kerberos(struct gss_ctx *gctx, return GSS_S_FAILURE; /* - * clear text layout, same for both checksum & encryption: + * clear text layout for checksum: + * ------------------------------------------------------ + * | confounder | gss header | clear msgs | krb5 header | + * ------------------------------------------------------ + */ + data_desc[0].data = conf; + data_desc[0].len = ke->ke_conf_size; + data_desc[1].data = gsshdr->data; + data_desc[1].len = gsshdr->len; + data_desc[2].data = msg->data; + data_desc[2].len = msg->len; + data_desc[3].data = (__u8 *) khdr; + data_desc[3].len = sizeof(*khdr); + + /* compute checksum */ + if (krb5_make_checksum(kctx->kc_enctype, &kctx->kc_keyi, + khdr, 4, data_desc, &cksum)) + return GSS_S_FAILURE; + LASSERT(cksum.len >= ke->ke_hash_size); + + /* + * clear text layout for encryption: * ----------------------------------------- * | confounder | clear msgs | krb5 header | * ----------------------------------------- @@ -968,13 +996,7 @@ __u32 gss_wrap_kerberos(struct gss_ctx *gctx, data_desc[2].data = (__u8 *) khdr; data_desc[2].len = sizeof(*khdr); - /* compute checksum */ - if (krb5_make_checksum(kctx->kc_enctype, &kctx->kc_keyi, - khdr, 3, data_desc, &cksum)) - return GSS_S_FAILURE; - LASSERT(cksum.len >= ke->ke_hash_size); - - /* encrypting, cipher text will be directly inplace */ + /* cipher text will be directly inplace */ cipher.data = (__u8 *) (khdr + 1); cipher.len = token->len - sizeof(*khdr); LASSERT(cipher.len >= ke->ke_conf_size + msg->len + sizeof(*khdr)); @@ -1034,6 +1056,7 @@ arc4_out: static __u32 gss_unwrap_kerberos(struct gss_ctx *gctx, + rawobj_t *gsshdr, rawobj_t *token, rawobj_t *msg) { @@ -1045,6 +1068,7 @@ __u32 gss_unwrap_kerberos(struct gss_ctx *gctx, int blocksize, bodysize; rawobj_t cksum = RAWOBJ_EMPTY; rawobj_t cipher_in, plain_out; + rawobj_t hash_objs[3]; __u32 rc = GSS_S_FAILURE, enc_rc = 0; LASSERT(ke); @@ -1174,16 +1198,26 @@ arc4_out: * ----------------------------------------- */ - /* last part must be identical to the krb5 header */ + /* verify krb5 header in token is not modified */ if (memcmp(khdr, plain_out.data + plain_out.len - sizeof(*khdr), sizeof(*khdr))) { - CERROR("decrypted header mismatch\n"); + CERROR("decrypted krb5 header mismatch\n"); goto out_free; } - /* verify checksum */ + /* verify checksum, compose clear text as layout: + * ------------------------------------------------------ + * | confounder | gss header | clear msgs | krb5 header | + * ------------------------------------------------------ + */ + hash_objs[0].len = ke->ke_conf_size; + hash_objs[0].data = plain_out.data; + hash_objs[1].len = gsshdr->len; + hash_objs[1].data = gsshdr->data; + hash_objs[2].len = plain_out.len - ke->ke_conf_size; + hash_objs[2].data = plain_out.data + ke->ke_conf_size; if (krb5_make_checksum(kctx->kc_enctype, &kctx->kc_keyi, - khdr, 1, &plain_out, &cksum)) + khdr, 3, hash_objs, &cksum)) goto out_free; LASSERT(cksum.len >= ke->ke_hash_size); diff --git a/lustre/ptlrpc/gss/gss_mech_switch.c b/lustre/ptlrpc/gss/gss_mech_switch.c index 9b2965d4fef2ad6687d0ad1da768072f430caa30..8118e3e72b9bbd5a366ec7d90a22c59d870a3fff 100644 --- a/lustre/ptlrpc/gss/gss_mech_switch.c +++ b/lustre/ptlrpc/gss/gss_mech_switch.c @@ -245,23 +245,8 @@ __u32 lgss_verify_mic(struct gss_ctx *context_handle, mic_token); } -#if 0 -__u32 lgss_wrap(struct gss_ctx *context_handle, - __u32 qop, - rawobj_buf_t *inbuf, - rawobj_t *outbuf) -{ - LASSERT(context_handle); - LASSERT(context_handle->mech_type); - LASSERT(context_handle->mech_type->gm_ops); - LASSERT(context_handle->mech_type->gm_ops->gss_wrap); - - return context_handle->mech_type->gm_ops - ->gss_wrap(context_handle, qop, inbuf, outbuf); -} -#endif - __u32 lgss_wrap(struct gss_ctx *context_handle, + rawobj_t *gsshdr, rawobj_t *msg, int msg_buflen, rawobj_t *out_token) @@ -272,10 +257,11 @@ __u32 lgss_wrap(struct gss_ctx *context_handle, LASSERT(context_handle->mech_type->gm_ops->gss_wrap); return context_handle->mech_type->gm_ops - ->gss_wrap(context_handle, msg, msg_buflen, out_token); + ->gss_wrap(context_handle, gsshdr, msg, msg_buflen, out_token); } __u32 lgss_unwrap(struct gss_ctx *context_handle, + rawobj_t *gsshdr, rawobj_t *token, rawobj_t *out_msg) { @@ -285,7 +271,7 @@ __u32 lgss_unwrap(struct gss_ctx *context_handle, LASSERT(context_handle->mech_type->gm_ops->gss_unwrap); return context_handle->mech_type->gm_ops - ->gss_unwrap(context_handle, token, out_msg); + ->gss_unwrap(context_handle, gsshdr, token, out_msg); } diff --git a/lustre/ptlrpc/gss/sec_gss.c b/lustre/ptlrpc/gss/sec_gss.c index d4aef70c122b262ad38bed4afc69e0be0986bfeb..a777e9b59abda8ab6df1e1bf5afded0102d390f0 100644 --- a/lustre/ptlrpc/gss/sec_gss.c +++ b/lustre/ptlrpc/gss/sec_gss.c @@ -276,47 +276,39 @@ __u32 gss_unseal_msg(struct gss_ctx *mechctx, struct lustre_msg *msgbuf, int *msg_len, int msgbuf_len) { - rawobj_t clear_obj, micobj, msgobj, token; + rawobj_t clear_obj, hdrobj, token; __u8 *clear_buf; int clear_buflen; __u32 major; ENTRY; - if (msgbuf->lm_bufcount != 3) { + if (msgbuf->lm_bufcount != 2) { CERROR("invalid bufcount %d\n", msgbuf->lm_bufcount); RETURN(GSS_S_FAILURE); } - /* verify gss header */ - msgobj.len = msgbuf->lm_buflens[0]; - msgobj.data = lustre_msg_buf(msgbuf, 0, 0); - micobj.len = msgbuf->lm_buflens[1]; - micobj.data = lustre_msg_buf(msgbuf, 1, 0); - - major = lgss_verify_mic(mechctx, 1, &msgobj, &micobj); - if (major != GSS_S_COMPLETE) { - CERROR("priv: mic verify error: %08x\n", major); - RETURN(major); - } - - /* temporary clear text buffer */ - clear_buflen = msgbuf->lm_buflens[2]; + /* allocate a temporary clear text buffer, same sized as token, + * we assume the final clear text size <= token size */ + clear_buflen = lustre_msg_buflen(msgbuf, 1); OBD_ALLOC(clear_buf, clear_buflen); if (!clear_buf) RETURN(GSS_S_FAILURE); - token.len = msgbuf->lm_buflens[2]; - token.data = lustre_msg_buf(msgbuf, 2, 0); - + /* buffer objects */ + hdrobj.len = lustre_msg_buflen(msgbuf, 0); + hdrobj.data = lustre_msg_buf(msgbuf, 0, 0); + token.len = lustre_msg_buflen(msgbuf, 1); + token.data = lustre_msg_buf(msgbuf, 1, 0); clear_obj.len = clear_buflen; clear_obj.data = clear_buf; - major = lgss_unwrap(mechctx, &token, &clear_obj); + major = lgss_unwrap(mechctx, &hdrobj, &token, &clear_obj); if (major != GSS_S_COMPLETE) { - CERROR("priv: unwrap message error: %08x\n", major); + CERROR("unwrap message error: %08x\n", major); GOTO(out_free, major = GSS_S_FAILURE); } LASSERT(clear_obj.len <= clear_buflen); + LASSERT(clear_obj.len <= msgbuf_len); /* now the decrypted message */ memcpy(msgbuf, clear_obj.data, clear_obj.len); @@ -863,9 +855,9 @@ int gss_cli_ctx_seal(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req) { struct gss_cli_ctx *gctx; - rawobj_t msgobj, cipher_obj, micobj; + rawobj_t hdrobj, msgobj, token; struct gss_header *ghdr; - int buflens[3], wiresize, rc; + int buflens[2], wiresize, rc; __u32 major; ENTRY; @@ -875,15 +867,14 @@ int gss_cli_ctx_seal(struct ptlrpc_cli_ctx *ctx, gctx = container_of(ctx, struct gss_cli_ctx, gc_base); - /* close clear data length */ + /* final clear data length */ req->rq_clrdata_len = lustre_msg_size_v2(req->rq_clrbuf->lm_bufcount, req->rq_clrbuf->lm_buflens); /* calculate wire data length */ buflens[0] = PTLRPC_GSS_HEADER_SIZE; - buflens[1] = gss_cli_payload(&gctx->gc_base, buflens[0], 0); - buflens[2] = gss_cli_payload(&gctx->gc_base, req->rq_clrdata_len, 1); - wiresize = lustre_msg_size_v2(3, buflens); + buflens[1] = gss_cli_payload(&gctx->gc_base, req->rq_clrdata_len, 1); + wiresize = lustre_msg_size_v2(2, buflens); /* allocate wire buffer */ if (req->rq_pool) { @@ -898,7 +889,7 @@ int gss_cli_ctx_seal(struct ptlrpc_cli_ctx *ctx, req->rq_reqbuf_len = wiresize; } - lustre_init_msg_v2(req->rq_reqbuf, 3, buflens, NULL); + lustre_init_msg_v2(req->rq_reqbuf, 2, buflens, NULL); req->rq_reqbuf->lm_secflvr = req->rq_flvr.sf_rpc; /* gss header */ @@ -907,7 +898,6 @@ int gss_cli_ctx_seal(struct ptlrpc_cli_ctx *ctx, ghdr->gh_sp = (__u8) ctx->cc_sec->ps_part; ghdr->gh_flags = 0; ghdr->gh_proc = gctx->gc_proc; - ghdr->gh_seq = atomic_inc_return(&gctx->gc_seq); ghdr->gh_svc = SPTLRPC_SVC_PRIV; ghdr->gh_handle.len = gctx->gc_handle.len; memcpy(ghdr->gh_handle.data, gctx->gc_handle.data, gctx->gc_handle.len); @@ -917,41 +907,27 @@ int gss_cli_ctx_seal(struct ptlrpc_cli_ctx *ctx, ghdr->gh_flags |= LUSTRE_GSS_PACK_USER; redo: - /* header signature */ - msgobj.len = req->rq_reqbuf->lm_buflens[0]; - msgobj.data = lustre_msg_buf(req->rq_reqbuf, 0, 0); - micobj.len = req->rq_reqbuf->lm_buflens[1]; - micobj.data = lustre_msg_buf(req->rq_reqbuf, 1, 0); - - major = lgss_get_mic(gctx->gc_mechctx, 1, &msgobj, &micobj); - if (major != GSS_S_COMPLETE) { - CERROR("priv: sign message error: %08x\n", major); - GOTO(err_free, rc = -EPERM); - } - /* perhaps shrink msg has potential problem in re-packing??? - * ship a little bit more data is fine. - lustre_shrink_msg(req->rq_reqbuf, 1, micobj.len, 0); - */ + ghdr->gh_seq = atomic_inc_return(&gctx->gc_seq); - /* clear text */ + /* buffer objects */ + hdrobj.len = PTLRPC_GSS_HEADER_SIZE; + hdrobj.data = (__u8 *) ghdr; msgobj.len = req->rq_clrdata_len; msgobj.data = (__u8 *) req->rq_clrbuf; + token.len = lustre_msg_buflen(req->rq_reqbuf, 1); + token.data = lustre_msg_buf(req->rq_reqbuf, 1, 0); - /* cipher text */ - cipher_obj.len = req->rq_reqbuf->lm_buflens[2]; - cipher_obj.data = lustre_msg_buf(req->rq_reqbuf, 2, 0); - - major = lgss_wrap(gctx->gc_mechctx, &msgobj, req->rq_clrbuf_len, - &cipher_obj); + major = lgss_wrap(gctx->gc_mechctx, &hdrobj, &msgobj, + req->rq_clrbuf_len, &token); if (major != GSS_S_COMPLETE) { CERROR("priv: wrap message error: %08x\n", major); GOTO(err_free, rc = -EPERM); } - LASSERT(cipher_obj.len <= buflens[2]); + LASSERT(token.len <= buflens[1]); /* see explain in gss_cli_ctx_sign() */ - if (atomic_read(&gctx->gc_seq) - ghdr->gh_seq > - GSS_SEQ_REPACK_THRESHOLD) { + if (unlikely(atomic_read(&gctx->gc_seq) - ghdr->gh_seq > + GSS_SEQ_REPACK_THRESHOLD)) { int behind = atomic_read(&gctx->gc_seq) - ghdr->gh_seq; gss_stat_oos_record_cli(behind); @@ -962,9 +938,7 @@ redo: } /* now set the final wire data length */ - req->rq_reqdata_len = lustre_shrink_msg(req->rq_reqbuf, 2, - cipher_obj.len, 0); - + req->rq_reqdata_len = lustre_shrink_msg(req->rq_reqbuf, 1, token.len,0); RETURN(0); err_free: @@ -1322,7 +1296,7 @@ int gss_alloc_reqbuf_priv(struct ptlrpc_sec *sec, int msgsize) { int ibuflens[3], ibufcnt; - int buflens[3]; + int wbuflens[2]; int clearsize, wiresize; ENTRY; @@ -1334,7 +1308,6 @@ int gss_alloc_reqbuf_priv(struct ptlrpc_sec *sec, * - user descriptor (optional) * - bulk checksum (optional) */ - ibufcnt = 1; ibuflens[0] = msgsize; @@ -1351,14 +1324,11 @@ int gss_alloc_reqbuf_priv(struct ptlrpc_sec *sec, /* Wrapper (wire) buffers * - gss header - * - signature of gss header * - cipher text */ - - buflens[0] = PTLRPC_GSS_HEADER_SIZE; - buflens[1] = gss_cli_payload(req->rq_cli_ctx, buflens[0], 0); - buflens[2] = gss_cli_payload(req->rq_cli_ctx, clearsize, 1); - wiresize = lustre_msg_size_v2(3, buflens); + wbuflens[0] = PTLRPC_GSS_HEADER_SIZE; + wbuflens[1] = gss_cli_payload(req->rq_cli_ctx, clearsize, 1); + wiresize = lustre_msg_size_v2(2, wbuflens); if (req->rq_pool) { /* rq_reqbuf is preallocated */ @@ -1534,38 +1504,26 @@ int gss_alloc_repbuf_priv(struct ptlrpc_sec *sec, int msgsize) { int txtsize; - int buflens[3], bufcnt; + int buflens[2], bufcnt; int alloc_size; - /* Inner (clear) buffers - * - lustre message - * - bulk checksum (optional) - */ - + /* inner buffers */ bufcnt = 1; buflens[0] = msgsize; - if (req->rq_pack_bulk) { + if (req->rq_pack_bulk) buflens[bufcnt++] = bulk_sec_desc_size( req->rq_flvr.sf_bulk_hash, 0, req->rq_bulk_read); - } txtsize = lustre_msg_size_v2(bufcnt, buflens); txtsize += GSS_MAX_CIPHER_BLOCK; - /* Wrapper (wire) buffers - * - gss header - * - signature of gss header - * - cipher text - */ - - bufcnt = 3; + /* wrapper buffers */ + bufcnt = 2; buflens[0] = PTLRPC_GSS_HEADER_SIZE; - buflens[1] = gss_cli_payload(req->rq_cli_ctx, buflens[0], 0); - buflens[2] = gss_cli_payload(req->rq_cli_ctx, txtsize, 1); + buflens[1] = gss_cli_payload(req->rq_cli_ctx, txtsize, 1); alloc_size = lustre_msg_size_v2(bufcnt, buflens); - /* add space for early reply */ alloc_size += gss_at_reply_off_priv; @@ -2353,10 +2311,9 @@ int gss_svc_accept(struct ptlrpc_sec_policy *policy, struct ptlrpc_request *req) /* alloc grctx data */ OBD_ALLOC_PTR(grctx); - if (!grctx) { - CERROR("fail to alloc svc reqctx\n"); + if (!grctx) RETURN(SECSVC_DROP); - } + grctx->src_base.sc_policy = sptlrpc_policy_get(policy); atomic_set(&grctx->src_base.sc_refcount, 1); req->rq_svc_ctx = &grctx->src_base; @@ -2471,7 +2428,7 @@ int gss_svc_alloc_rs(struct ptlrpc_request *req, int msglen) privacy = (svc == SPTLRPC_SVC_PRIV); if (privacy) { - /* Inner buffer */ + /* inner clear buffers */ ibufcnt = 1; ibuflens[0] = msglen; @@ -2488,10 +2445,9 @@ int gss_svc_alloc_rs(struct ptlrpc_request *req, int msglen) txtsize += GSS_MAX_CIPHER_BLOCK; /* wrapper buffer */ - bufcnt = 3; + bufcnt = 2; buflens[0] = PTLRPC_GSS_HEADER_SIZE; - buflens[1] = gss_svc_payload(grctx, early, buflens[0], 0); - buflens[2] = gss_svc_payload(grctx, early, txtsize, 1); + buflens[1] = gss_svc_payload(grctx, early, txtsize, 1); } else { bufcnt = 2; buflens[0] = PTLRPC_GSS_HEADER_SIZE; @@ -2563,48 +2519,61 @@ int gss_svc_alloc_rs(struct ptlrpc_request *req, int msglen) RETURN(0); } -static -int gss_svc_seal(struct ptlrpc_request *req, - struct ptlrpc_reply_state *rs, - struct gss_svc_reqctx *grctx) +static int gss_svc_seal(struct ptlrpc_request *req, + struct ptlrpc_reply_state *rs, + struct gss_svc_reqctx *grctx) { struct gss_svc_ctx *gctx = grctx->src_ctx; - rawobj_t msgobj, cipher_obj, micobj; + rawobj_t hdrobj, msgobj, token; struct gss_header *ghdr; - __u8 *cipher_buf; - int cipher_buflen, buflens[3]; + __u8 *token_buf; + int token_buflen, buflens[2]; int msglen, rc; __u32 major; ENTRY; - /* embedded lustre_msg might have been shrinked */ - if (req->rq_replen != rs->rs_repbuf->lm_buflens[0]) - lustre_shrink_msg(rs->rs_repbuf, 0, req->rq_replen, 1); - - /* clear data length */ - msglen = lustre_msg_size_v2(rs->rs_repbuf->lm_bufcount, - rs->rs_repbuf->lm_buflens); - - /* clear text */ - msgobj.len = msglen; - msgobj.data = (__u8 *) rs->rs_repbuf; + /* get clear data length. note embedded lustre_msg might + * have been shrinked */ + if (req->rq_replen != lustre_msg_buflen(rs->rs_repbuf, 0)) + msglen = lustre_shrink_msg(rs->rs_repbuf, 0, req->rq_replen, 1); + else + msglen = lustre_msg_size_v2(rs->rs_repbuf->lm_bufcount, + rs->rs_repbuf->lm_buflens); + + /* temporarily use tail of buffer to hold gss header data */ + LASSERT(msglen + PTLRPC_GSS_HEADER_SIZE <= rs->rs_repbuf_len); + ghdr = (struct gss_header *) ((char *) rs->rs_repbuf + + rs->rs_repbuf_len - PTLRPC_GSS_HEADER_SIZE); + ghdr->gh_version = PTLRPC_GSS_VERSION; + ghdr->gh_sp = LUSTRE_SP_ANY; + ghdr->gh_flags = 0; + ghdr->gh_proc = PTLRPC_GSS_PROC_DATA; + ghdr->gh_seq = grctx->src_wirectx.gw_seq; + ghdr->gh_svc = SPTLRPC_SVC_PRIV; + ghdr->gh_handle.len = 0; + if (req->rq_pack_bulk) + ghdr->gh_flags |= LUSTRE_GSS_PACK_BULK; /* allocate temporary cipher buffer */ - cipher_buflen = gss_mech_payload(gctx->gsc_mechctx, msglen, 1); - OBD_ALLOC(cipher_buf, cipher_buflen); - if (!cipher_buf) + token_buflen = gss_mech_payload(gctx->gsc_mechctx, msglen, 1); + OBD_ALLOC(token_buf, token_buflen); + if (token_buf == NULL) RETURN(-ENOMEM); - cipher_obj.len = cipher_buflen; - cipher_obj.data = cipher_buf; + hdrobj.len = PTLRPC_GSS_HEADER_SIZE; + hdrobj.data = (__u8 *) ghdr; + msgobj.len = msglen; + msgobj.data = (__u8 *) rs->rs_repbuf; + token.len = token_buflen; + token.data = token_buf; - major = lgss_wrap(gctx->gsc_mechctx, &msgobj, rs->rs_repbuf_len, - &cipher_obj); + major = lgss_wrap(gctx->gsc_mechctx, &hdrobj, &msgobj, + rs->rs_repbuf_len - PTLRPC_GSS_HEADER_SIZE, &token); if (major != GSS_S_COMPLETE) { - CERROR("priv: wrap message error: %08x\n", major); + CERROR("wrap message error: %08x\n", major); GOTO(out_free, rc = -EPERM); } - LASSERT(cipher_obj.len <= cipher_buflen); + LASSERT(token.len <= token_buflen); /* we are about to override data at rs->rs_repbuf, nullify pointers * to which to catch further illegal usage. */ @@ -2613,45 +2582,22 @@ int gss_svc_seal(struct ptlrpc_request *req, grctx->src_repbsd_size = 0; } - /* now the real wire data */ + /* now fill the actual wire data + * - gss header + * - gss token + */ buflens[0] = PTLRPC_GSS_HEADER_SIZE; - buflens[1] = gss_mech_payload(gctx->gsc_mechctx, buflens[0], 0); - buflens[2] = cipher_obj.len; + buflens[1] = token.len; - LASSERT(lustre_msg_size_v2(3, buflens) <= rs->rs_repbuf_len); - lustre_init_msg_v2(rs->rs_repbuf, 3, buflens, NULL); - rs->rs_repbuf->lm_secflvr = req->rq_flvr.sf_rpc; - - /* gss header */ - ghdr = lustre_msg_buf(rs->rs_repbuf, 0, 0); - ghdr->gh_version = PTLRPC_GSS_VERSION; - ghdr->gh_flags = 0; - ghdr->gh_proc = PTLRPC_GSS_PROC_DATA; - ghdr->gh_seq = grctx->src_wirectx.gw_seq; - ghdr->gh_svc = SPTLRPC_SVC_PRIV; - ghdr->gh_handle.len = 0; - if (req->rq_pack_bulk) - ghdr->gh_flags |= LUSTRE_GSS_PACK_BULK; + rs->rs_repdata_len = lustre_msg_size_v2(2, buflens); + LASSERT(rs->rs_repdata_len <= rs->rs_repbuf_len); - /* header signature */ - msgobj.len = rs->rs_repbuf->lm_buflens[0]; - msgobj.data = lustre_msg_buf(rs->rs_repbuf, 0, 0); - micobj.len = rs->rs_repbuf->lm_buflens[1]; - micobj.data = lustre_msg_buf(rs->rs_repbuf, 1, 0); - - major = lgss_get_mic(gctx->gsc_mechctx, 1, &msgobj, &micobj); - if (major != GSS_S_COMPLETE) { - CERROR("priv: sign message error: %08x\n", major); - GOTO(out_free, rc = -EPERM); - } - lustre_shrink_msg(rs->rs_repbuf, 1, micobj.len, 0); - - /* cipher token */ - memcpy(lustre_msg_buf(rs->rs_repbuf, 2, 0), - cipher_obj.data, cipher_obj.len); + lustre_init_msg_v2(rs->rs_repbuf, 2, buflens, NULL); + rs->rs_repbuf->lm_secflvr = req->rq_flvr.sf_rpc; - rs->rs_repdata_len = lustre_shrink_msg(rs->rs_repbuf, 2, - cipher_obj.len, 0); + memcpy(lustre_msg_buf(rs->rs_repbuf, 0, 0), ghdr, + PTLRPC_GSS_HEADER_SIZE); + memcpy(lustre_msg_buf(rs->rs_repbuf, 1, 0), token.data, token.len); /* reply offset */ if (likely(req->rq_packed_final)) @@ -2666,7 +2612,7 @@ int gss_svc_seal(struct ptlrpc_request *req, rc = 0; out_free: - OBD_FREE(cipher_buf, cipher_buflen); + OBD_FREE(token_buf, token_buflen); RETURN(rc); }