aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/auth_gss/gss_krb5_wrap.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc/auth_gss/gss_krb5_wrap.c')
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_wrap.c61
1 files changed, 45 insertions, 16 deletions
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
index 38f388c39dce..107c4528654f 100644
--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
+++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
@@ -381,21 +381,53 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
381} 381}
382 382
383/* 383/*
384 * We cannot currently handle tokens with rotated data. We need a 384 * We can shift data by up to LOCAL_BUF_LEN bytes in a pass. If we need
385 * generalized routine to rotate the data in place. It is anticipated 385 * to do more than that, we shift repeatedly. Kevin Coffman reports
386 * that we won't encounter rotated data in the general case. 386 * seeing 28 bytes as the value used by Microsoft clients and servers
387 * with AES, so this constant is chosen to allow handling 28 in one pass
388 * without using too much stack space.
389 *
390 * If that proves to a problem perhaps we could use a more clever
391 * algorithm.
387 */ 392 */
388static u32 393#define LOCAL_BUF_LEN 32u
389rotate_left(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf, u16 rrc) 394
395static void rotate_buf_a_little(struct xdr_buf *buf, unsigned int shift)
390{ 396{
391 unsigned int realrrc = rrc % (buf->len - offset - GSS_KRB5_TOK_HDR_LEN); 397 char head[LOCAL_BUF_LEN];
398 char tmp[LOCAL_BUF_LEN];
399 unsigned int this_len, i;
400
401 BUG_ON(shift > LOCAL_BUF_LEN);
392 402
393 if (realrrc == 0) 403 read_bytes_from_xdr_buf(buf, 0, head, shift);
394 return 0; 404 for (i = 0; i + shift < buf->len; i += LOCAL_BUF_LEN) {
405 this_len = min(LOCAL_BUF_LEN, buf->len - (i + shift));
406 read_bytes_from_xdr_buf(buf, i+shift, tmp, this_len);
407 write_bytes_to_xdr_buf(buf, i, tmp, this_len);
408 }
409 write_bytes_to_xdr_buf(buf, buf->len - shift, head, shift);
410}
395 411
396 dprintk("%s: cannot process token with rotated data: " 412static void _rotate_left(struct xdr_buf *buf, unsigned int shift)
397 "rrc %u, realrrc %u\n", __func__, rrc, realrrc); 413{
398 return 1; 414 int shifted = 0;
415 int this_shift;
416
417 shift %= buf->len;
418 while (shifted < shift) {
419 this_shift = min(shift - shifted, LOCAL_BUF_LEN);
420 rotate_buf_a_little(buf, this_shift);
421 shifted += this_shift;
422 }
423}
424
425static void rotate_left(u32 base, struct xdr_buf *buf, unsigned int shift)
426{
427 struct xdr_buf subbuf;
428
429 xdr_buf_subsegment(buf, &subbuf, base, buf->len - base);
430 _rotate_left(&subbuf, shift);
399} 431}
400 432
401static u32 433static u32
@@ -495,11 +527,8 @@ gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
495 527
496 seqnum = be64_to_cpup((__be64 *)(ptr + 8)); 528 seqnum = be64_to_cpup((__be64 *)(ptr + 8));
497 529
498 if (rrc != 0) { 530 if (rrc != 0)
499 err = rotate_left(kctx, offset, buf, rrc); 531 rotate_left(offset + 16, buf, rrc);
500 if (err)
501 return GSS_S_FAILURE;
502 }
503 532
504 err = (*kctx->gk5e->decrypt_v2)(kctx, offset, buf, 533 err = (*kctx->gk5e->decrypt_v2)(kctx, offset, buf,
505 &headskip, &tailskip); 534 &headskip, &tailskip);