Skip to content

Commit 218fc68

Browse files
sbuisson-ddnOleg Drokin
authored andcommitted
LU-12401 gss: fix checksum for Kerberos and SSK
When computing checksum for Kerberos, krb5 wire token header is appended to the plain text. Make sure the actual header is appended in gss_digest_hash(). For interop with older clients, introduce new server side tunable 'sptlrpc.gss.krb5_allow_old_client_csum'. When not set, servers refuse Kerberos connection from older clients. In gss_crypt_generic(), protect against an undefined behavior by switching from memcpy to memmove. When computing checksum for SSK, make sure the actual token is used to store the checksum. Fixes: a21c13d ("LU-8602 gss: Properly port gss to newer crypto api.") Test-Parameters: envdefinitions=SHARED_KEY=true testlist=sanity,recovery-small,sanity-sec Test-Parameters: envdefinitions=SHARED_KEY=true clientbuildno=6308 clientjob=lustre-reviews-patchless testlist=sanity,recovery-small,sanity-sec Signed-off-by: Sebastien Buisson <[email protected]> Change-Id: I0233ada481f132af112bf88c065f5421902c942e Reviewed-on: https://review.whamcloud.com/35099 Reviewed-by: Andreas Dilger <[email protected]> Reviewed-by: Jeremy Filizetti <[email protected]> Tested-by: jenkins <[email protected]> Tested-by: Maloo <[email protected]> Reviewed-by: Oleg Drokin <[email protected]>
1 parent a51d065 commit 218fc68

File tree

12 files changed

+665
-503
lines changed

12 files changed

+665
-503
lines changed

lustre/include/lustre_sec.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,7 @@ struct ptlrpc_bulk_sec_desc {
966966
};
967967

968968
extern struct dentry *sptlrpc_debugfs_dir;
969+
extern struct proc_dir_entry *sptlrpc_lprocfs_dir;
969970

970971
/*
971972
* round size up to next power of 2, for slab allocation.

lustre/ptlrpc/gss/gss_api.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,16 @@
2121

2222
struct gss_api_mech;
2323

24+
typedef int (*digest_hash)(
25+
struct ahash_request *req, rawobj_t *hdr,
26+
int msgcnt, rawobj_t *msgs,
27+
int iovcnt, lnet_kiov_t *iovs);
28+
2429
/* The mechanism-independent gss-api context: */
2530
struct gss_ctx {
26-
struct gss_api_mech *mech_type;
27-
void *internal_ctx_id;
31+
struct gss_api_mech *mech_type;
32+
void *internal_ctx_id;
33+
digest_hash hash_func;
2834
};
2935

3036
#define GSS_C_NO_BUFFER ((rawobj_t) 0)

lustre/ptlrpc/gss/gss_cli_upcall.c

Lines changed: 75 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -59,82 +59,85 @@
5959

6060
static
6161
int ctx_init_pack_request(struct obd_import *imp,
62-
struct ptlrpc_request *req,
63-
int lustre_srv,
64-
uid_t uid, gid_t gid,
65-
long token_size,
66-
char __user *token)
62+
struct ptlrpc_request *req,
63+
int lustre_srv,
64+
uid_t uid, gid_t gid,
65+
long token_size,
66+
char __user *token)
6767
{
68-
struct lustre_msg *msg = req->rq_reqbuf;
69-
struct gss_sec *gsec;
70-
struct gss_header *ghdr;
71-
struct ptlrpc_user_desc *pud;
72-
__u32 *p, size, offset = 2;
73-
rawobj_t obj;
74-
75-
LASSERT(msg->lm_bufcount <= 4);
76-
LASSERT(req->rq_cli_ctx);
77-
LASSERT(req->rq_cli_ctx->cc_sec);
78-
79-
/* gss hdr */
80-
ghdr = lustre_msg_buf(msg, 0, sizeof(*ghdr));
81-
ghdr->gh_version = PTLRPC_GSS_VERSION;
82-
ghdr->gh_sp = (__u8) imp->imp_sec->ps_part;
83-
ghdr->gh_flags = 0;
84-
ghdr->gh_proc = PTLRPC_GSS_PROC_INIT;
85-
ghdr->gh_seq = 0;
86-
ghdr->gh_svc = SPTLRPC_SVC_NULL;
87-
ghdr->gh_handle.len = 0;
88-
89-
/* fix the user desc */
90-
if (req->rq_pack_udesc) {
91-
ghdr->gh_flags |= LUSTRE_GSS_PACK_USER;
92-
93-
pud = lustre_msg_buf(msg, offset, sizeof(*pud));
94-
LASSERT(pud);
95-
pud->pud_uid = pud->pud_fsuid = uid;
96-
pud->pud_gid = pud->pud_fsgid = gid;
97-
pud->pud_cap = 0;
98-
pud->pud_ngroups = 0;
99-
offset++;
100-
}
68+
struct lustre_msg *msg = req->rq_reqbuf;
69+
struct gss_sec *gsec;
70+
struct gss_header *ghdr;
71+
struct ptlrpc_user_desc *pud;
72+
__u32 *p, size, offset = 2;
73+
rawobj_t obj;
74+
75+
LASSERT(msg->lm_bufcount <= 4);
76+
LASSERT(req->rq_cli_ctx);
77+
LASSERT(req->rq_cli_ctx->cc_sec);
78+
79+
/* gss hdr */
80+
ghdr = lustre_msg_buf(msg, 0, sizeof(*ghdr));
81+
ghdr->gh_version = PTLRPC_GSS_VERSION;
82+
ghdr->gh_sp = (__u8) imp->imp_sec->ps_part;
83+
ghdr->gh_flags = 0;
84+
ghdr->gh_proc = PTLRPC_GSS_PROC_INIT;
85+
ghdr->gh_seq = 0;
86+
ghdr->gh_svc = SPTLRPC_SVC_NULL;
87+
ghdr->gh_handle.len = 0;
88+
89+
/* fix the user desc */
90+
if (req->rq_pack_udesc) {
91+
ghdr->gh_flags |= LUSTRE_GSS_PACK_USER;
92+
93+
pud = lustre_msg_buf(msg, offset, sizeof(*pud));
94+
LASSERT(pud);
95+
pud->pud_uid = pud->pud_fsuid = uid;
96+
pud->pud_gid = pud->pud_fsgid = gid;
97+
pud->pud_cap = 0;
98+
pud->pud_ngroups = 0;
99+
offset++;
100+
}
101101

102-
/* security payload */
103-
p = lustre_msg_buf(msg, offset, 0);
104-
size = msg->lm_buflens[offset];
105-
LASSERT(p);
106-
107-
/* 1. lustre svc type */
108-
LASSERT(size > 4);
109-
*p++ = cpu_to_le32(lustre_srv);
110-
size -= 4;
111-
112-
/* 2. target uuid */
113-
obj.len = strlen(imp->imp_obd->u.cli.cl_target_uuid.uuid) + 1;
114-
obj.data = imp->imp_obd->u.cli.cl_target_uuid.uuid;
115-
if (rawobj_serialize(&obj, &p, &size))
116-
LBUG();
117-
118-
/* 3. reverse context handle. actually only needed by root user,
119-
* but we send it anyway. */
120-
gsec = sec2gsec(req->rq_cli_ctx->cc_sec);
121-
obj.len = sizeof(gsec->gs_rvs_hdl);
122-
obj.data = (__u8 *) &gsec->gs_rvs_hdl;
123-
if (rawobj_serialize(&obj, &p, &size))
124-
LBUG();
125-
126-
/* 4. now the token */
127-
LASSERT(size >= (sizeof(__u32) + token_size));
128-
*p++ = cpu_to_le32(((__u32) token_size));
102+
/* new clients are expected to set KCSUM flag */
103+
ghdr->gh_flags |= LUSTRE_GSS_PACK_KCSUM;
104+
105+
/* security payload */
106+
p = lustre_msg_buf(msg, offset, 0);
107+
size = msg->lm_buflens[offset];
108+
LASSERT(p);
109+
110+
/* 1. lustre svc type */
111+
LASSERT(size > 4);
112+
*p++ = cpu_to_le32(lustre_srv);
113+
size -= 4;
114+
115+
/* 2. target uuid */
116+
obj.len = strlen(imp->imp_obd->u.cli.cl_target_uuid.uuid) + 1;
117+
obj.data = imp->imp_obd->u.cli.cl_target_uuid.uuid;
118+
if (rawobj_serialize(&obj, &p, &size))
119+
LBUG();
120+
121+
/* 3. reverse context handle. actually only needed by root user,
122+
* but we send it anyway. */
123+
gsec = sec2gsec(req->rq_cli_ctx->cc_sec);
124+
obj.len = sizeof(gsec->gs_rvs_hdl);
125+
obj.data = (__u8 *) &gsec->gs_rvs_hdl;
126+
if (rawobj_serialize(&obj, &p, &size))
127+
LBUG();
128+
129+
/* 4. now the token */
130+
LASSERT(size >= (sizeof(__u32) + token_size));
131+
*p++ = cpu_to_le32(((__u32) token_size));
129132
if (copy_from_user(p, token, token_size)) {
130-
CERROR("can't copy token\n");
131-
return -EFAULT;
132-
}
133-
size -= sizeof(__u32) + cfs_size_round4(token_size);
133+
CERROR("can't copy token\n");
134+
return -EFAULT;
135+
}
136+
size -= sizeof(__u32) + cfs_size_round4(token_size);
134137

135-
req->rq_reqdata_len = lustre_shrink_msg(req->rq_reqbuf, offset,
136-
msg->lm_buflens[offset] - size, 0);
137-
return 0;
138+
req->rq_reqdata_len = lustre_shrink_msg(req->rq_reqbuf, offset,
139+
msg->lm_buflens[offset] - size, 0);
140+
return 0;
138141
}
139142

140143
static

lustre/ptlrpc/gss/gss_crypto.c

Lines changed: 57 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,8 @@ int gss_crypt_generic(struct crypto_blkcipher *tfm, int decrypt, const void *iv,
254254
if (iv)
255255
memcpy(local_iv, iv, crypto_blkcipher_ivsize(tfm));
256256

257-
memcpy(out, in, length);
257+
if (in != out)
258+
memmove(out, in, length);
258259

259260
ret = gss_setup_sgtable(&sg_out, &sg, out, length);
260261
if (ret != 0)
@@ -272,8 +273,7 @@ int gss_crypt_generic(struct crypto_blkcipher *tfm, int decrypt, const void *iv,
272273

273274
int gss_digest_hash(struct ahash_request *req,
274275
rawobj_t *hdr, int msgcnt, rawobj_t *msgs,
275-
int iovcnt, lnet_kiov_t *iovs,
276-
rawobj_t *cksum)
276+
int iovcnt, lnet_kiov_t *iovs)
277277
{
278278
struct scatterlist sg[1];
279279
struct sg_table sgt;
@@ -310,7 +310,7 @@ int gss_digest_hash(struct ahash_request *req,
310310
}
311311

312312
if (hdr) {
313-
rc = gss_setup_sgtable(&sgt, sg, hdr, sizeof(*hdr));
313+
rc = gss_setup_sgtable(&sgt, sg, hdr->data, hdr->len);
314314
if (rc)
315315
return rc;
316316

@@ -324,6 +324,59 @@ int gss_digest_hash(struct ahash_request *req,
324324
return rc;
325325
}
326326

327+
int gss_digest_hash_compat(struct ahash_request *req,
328+
rawobj_t *hdr, int msgcnt, rawobj_t *msgs,
329+
int iovcnt, lnet_kiov_t *iovs)
330+
{
331+
struct scatterlist sg[1];
332+
struct sg_table sgt;
333+
int rc = 0;
334+
int i;
335+
336+
for (i = 0; i < msgcnt; i++) {
337+
if (msgs[i].len == 0)
338+
continue;
339+
340+
rc = gss_setup_sgtable(&sgt, sg, msgs[i].data, msgs[i].len);
341+
if (rc)
342+
return rc;
343+
344+
ahash_request_set_crypt(req, sg, NULL, msgs[i].len);
345+
rc = crypto_ahash_update(req);
346+
gss_teardown_sgtable(&sgt);
347+
if (rc)
348+
return rc;
349+
}
350+
351+
for (i = 0; i < iovcnt; i++) {
352+
if (iovs[i].kiov_len == 0)
353+
continue;
354+
355+
sg_init_table(sg, 1);
356+
sg_set_page(&sg[0], iovs[i].kiov_page, iovs[i].kiov_len,
357+
iovs[i].kiov_offset);
358+
359+
ahash_request_set_crypt(req, sg, NULL, iovs[i].kiov_len);
360+
rc = crypto_ahash_update(req);
361+
if (rc)
362+
return rc;
363+
}
364+
365+
if (hdr) {
366+
rc = gss_setup_sgtable(&sgt, sg, &(hdr->len), sizeof(hdr->len));
367+
if (rc)
368+
return rc;
369+
370+
ahash_request_set_crypt(req, sg, NULL, sizeof(hdr->len));
371+
rc = crypto_ahash_update(req);
372+
gss_teardown_sgtable(&sgt);
373+
if (rc)
374+
return rc;
375+
}
376+
377+
return rc;
378+
}
379+
327380
int gss_add_padding(rawobj_t *msg, int msg_buflen, int blocksize)
328381
{
329382
int padding;

lustre/ptlrpc/gss/gss_crypto.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,10 @@ void gss_teardown_sgtable(struct sg_table *sgt);
2424
int gss_crypt_generic(struct crypto_blkcipher *tfm, int decrypt, const void *iv,
2525
const void *in, void *out, size_t length);
2626
int gss_digest_hash(struct ahash_request *req, rawobj_t *hdr,
27-
int msgcnt, rawobj_t *msgs, int iovcnt, lnet_kiov_t *iovs,
28-
rawobj_t *cksum);
27+
int msgcnt, rawobj_t *msgs, int iovcnt, lnet_kiov_t *iovs);
28+
int gss_digest_hash_compat(struct ahash_request *req,
29+
rawobj_t *hdr, int msgcnt, rawobj_t *msgs,
30+
int iovcnt, lnet_kiov_t *iovs);
2931
int gss_add_padding(rawobj_t *msg, int msg_buflen, int blocksize);
3032
int gss_crypt_rawobjs(struct crypto_blkcipher *tfm, __u8 *iv,
3133
int inobj_cnt, rawobj_t *inobjs, rawobj_t *outobj,

lustre/ptlrpc/gss/gss_internal.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,9 @@ enum ptlrpc_gss_tgt {
117117
};
118118

119119
enum ptlrpc_gss_header_flags {
120-
LUSTRE_GSS_PACK_BULK = 1,
121-
LUSTRE_GSS_PACK_USER = 2,
120+
LUSTRE_GSS_PACK_BULK = 1,
121+
LUSTRE_GSS_PACK_USER = 2,
122+
LUSTRE_GSS_PACK_KCSUM = 4,
122123
};
123124

124125
static inline
@@ -509,6 +510,7 @@ void gss_svc_upcall_destroy_ctx(struct gss_svc_ctx *ctx);
509510

510511
int __init gss_init_svc_upcall(void);
511512
void gss_exit_svc_upcall(void);
513+
extern unsigned int krb5_allow_old_client_csum;
512514

513515
/* lproc_gss.c */
514516
void gss_stat_oos_record_cli(int behind);

0 commit comments

Comments
 (0)