Commit 81d4a433 authored by Kevin Coffman's avatar Kevin Coffman Committed by Trond Myklebust

gss_krb5: introduce encryption type framework

Add enctype framework and change functions to use the generic
values from it rather than the values hard-coded for des.
Signed-off-by: default avatarKevin Coffman <kwc@citi.umich.edu>
Signed-off-by: default avatarSteve Dickson <steved@redhat.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent a8cc1cb7
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* Adapted from MIT Kerberos 5-1.2.1 lib/include/krb5.h, * Adapted from MIT Kerberos 5-1.2.1 lib/include/krb5.h,
* lib/gssapi/krb5/gssapiP_krb5.h, and others * lib/gssapi/krb5/gssapiP_krb5.h, and others
* *
* Copyright (c) 2000 The Regents of the University of Michigan. * Copyright (c) 2000-2008 The Regents of the University of Michigan.
* All rights reserved. * All rights reserved.
* *
* Andy Adamson <andros@umich.edu> * Andy Adamson <andros@umich.edu>
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
* *
*/ */
#include <linux/crypto.h>
#include <linux/sunrpc/auth_gss.h> #include <linux/sunrpc/auth_gss.h>
#include <linux/sunrpc/gss_err.h> #include <linux/sunrpc/gss_err.h>
#include <linux/sunrpc/gss_asn1.h> #include <linux/sunrpc/gss_asn1.h>
...@@ -46,9 +47,31 @@ ...@@ -46,9 +47,31 @@
/* Maximum blocksize for the supported crypto algorithms */ /* Maximum blocksize for the supported crypto algorithms */
#define GSS_KRB5_MAX_BLOCKSIZE (16) #define GSS_KRB5_MAX_BLOCKSIZE (16)
struct gss_krb5_enctype {
const u32 etype; /* encryption (key) type */
const u32 ctype; /* checksum type */
const char *name; /* "friendly" name */
const char *encrypt_name; /* crypto encrypt name */
const char *cksum_name; /* crypto checksum name */
const u16 signalg; /* signing algorithm */
const u16 sealalg; /* sealing algorithm */
const u32 blocksize; /* encryption blocksize */
const u32 cksumlength; /* checksum length */
const u32 keyed_cksum; /* is it a keyed cksum? */
const u32 keybytes; /* raw key len, in bytes */
const u32 keylength; /* final key len, in bytes */
u32 (*encrypt) (struct crypto_blkcipher *tfm,
void *iv, void *in, void *out,
int length); /* encryption function */
u32 (*decrypt) (struct crypto_blkcipher *tfm,
void *iv, void *in, void *out,
int length); /* decryption function */
};
struct krb5_ctx { struct krb5_ctx {
int initiate; /* 1 = initiating, 0 = accepting */ int initiate; /* 1 = initiating, 0 = accepting */
u32 enctype; u32 enctype;
const struct gss_krb5_enctype *gk5e; /* enctype-specific info */
struct crypto_blkcipher *enc; struct crypto_blkcipher *enc;
struct crypto_blkcipher *seq; struct crypto_blkcipher *seq;
s32 endtime; s32 endtime;
......
/* /*
* linux/net/sunrpc/gss_krb5_crypto.c * linux/net/sunrpc/gss_krb5_crypto.c
* *
* Copyright (c) 2000 The Regents of the University of Michigan. * Copyright (c) 2000-2008 The Regents of the University of Michigan.
* All rights reserved. * All rights reserved.
* *
* Andy Adamson <andros@umich.edu> * Andy Adamson <andros@umich.edu>
...@@ -58,13 +58,13 @@ krb5_encrypt( ...@@ -58,13 +58,13 @@ krb5_encrypt(
{ {
u32 ret = -EINVAL; u32 ret = -EINVAL;
struct scatterlist sg[1]; struct scatterlist sg[1];
u8 local_iv[16] = {0}; u8 local_iv[GSS_KRB5_MAX_BLOCKSIZE] = {0};
struct blkcipher_desc desc = { .tfm = tfm, .info = local_iv }; struct blkcipher_desc desc = { .tfm = tfm, .info = local_iv };
if (length % crypto_blkcipher_blocksize(tfm) != 0) if (length % crypto_blkcipher_blocksize(tfm) != 0)
goto out; goto out;
if (crypto_blkcipher_ivsize(tfm) > 16) { if (crypto_blkcipher_ivsize(tfm) > GSS_KRB5_MAX_BLOCKSIZE) {
dprintk("RPC: gss_k5encrypt: tfm iv size too large %d\n", dprintk("RPC: gss_k5encrypt: tfm iv size too large %d\n",
crypto_blkcipher_ivsize(tfm)); crypto_blkcipher_ivsize(tfm));
goto out; goto out;
...@@ -92,13 +92,13 @@ krb5_decrypt( ...@@ -92,13 +92,13 @@ krb5_decrypt(
{ {
u32 ret = -EINVAL; u32 ret = -EINVAL;
struct scatterlist sg[1]; struct scatterlist sg[1];
u8 local_iv[16] = {0}; u8 local_iv[GSS_KRB5_MAX_BLOCKSIZE] = {0};
struct blkcipher_desc desc = { .tfm = tfm, .info = local_iv }; struct blkcipher_desc desc = { .tfm = tfm, .info = local_iv };
if (length % crypto_blkcipher_blocksize(tfm) != 0) if (length % crypto_blkcipher_blocksize(tfm) != 0)
goto out; goto out;
if (crypto_blkcipher_ivsize(tfm) > 16) { if (crypto_blkcipher_ivsize(tfm) > GSS_KRB5_MAX_BLOCKSIZE) {
dprintk("RPC: gss_k5decrypt: tfm iv size too large %d\n", dprintk("RPC: gss_k5decrypt: tfm iv size too large %d\n",
crypto_blkcipher_ivsize(tfm)); crypto_blkcipher_ivsize(tfm));
goto out; goto out;
...@@ -157,7 +157,7 @@ make_checksum(char *cksumname, char *header, int hdrlen, struct xdr_buf *body, ...@@ -157,7 +157,7 @@ make_checksum(char *cksumname, char *header, int hdrlen, struct xdr_buf *body,
} }
struct encryptor_desc { struct encryptor_desc {
u8 iv[8]; /* XXX hard-coded blocksize */ u8 iv[GSS_KRB5_MAX_BLOCKSIZE];
struct blkcipher_desc desc; struct blkcipher_desc desc;
int pos; int pos;
struct xdr_buf *outbuf; struct xdr_buf *outbuf;
...@@ -198,7 +198,7 @@ encryptor(struct scatterlist *sg, void *data) ...@@ -198,7 +198,7 @@ encryptor(struct scatterlist *sg, void *data)
desc->fraglen += sg->length; desc->fraglen += sg->length;
desc->pos += sg->length; desc->pos += sg->length;
fraglen = thislen & 7; /* XXX hardcoded blocksize */ fraglen = thislen & (crypto_blkcipher_blocksize(desc->desc.tfm) - 1);
thislen -= fraglen; thislen -= fraglen;
if (thislen == 0) if (thislen == 0)
...@@ -256,7 +256,7 @@ gss_encrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf, ...@@ -256,7 +256,7 @@ gss_encrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf,
} }
struct decryptor_desc { struct decryptor_desc {
u8 iv[8]; /* XXX hard-coded blocksize */ u8 iv[GSS_KRB5_MAX_BLOCKSIZE];
struct blkcipher_desc desc; struct blkcipher_desc desc;
struct scatterlist frags[4]; struct scatterlist frags[4];
int fragno; int fragno;
...@@ -278,7 +278,7 @@ decryptor(struct scatterlist *sg, void *data) ...@@ -278,7 +278,7 @@ decryptor(struct scatterlist *sg, void *data)
desc->fragno++; desc->fragno++;
desc->fraglen += sg->length; desc->fraglen += sg->length;
fraglen = thislen & 7; /* XXX hardcoded blocksize */ fraglen = thislen & (crypto_blkcipher_blocksize(desc->desc.tfm) - 1);
thislen -= fraglen; thislen -= fraglen;
if (thislen == 0) if (thislen == 0)
......
/* /*
* linux/net/sunrpc/gss_krb5_mech.c * linux/net/sunrpc/gss_krb5_mech.c
* *
* Copyright (c) 2001 The Regents of the University of Michigan. * Copyright (c) 2001-2008 The Regents of the University of Michigan.
* All rights reserved. * All rights reserved.
* *
* Andy Adamson <andros@umich.edu> * Andy Adamson <andros@umich.edu>
...@@ -48,6 +48,50 @@ ...@@ -48,6 +48,50 @@
# define RPCDBG_FACILITY RPCDBG_AUTH # define RPCDBG_FACILITY RPCDBG_AUTH
#endif #endif
static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = {
/*
* DES (All DES enctypes are mapped to the same gss functionality)
*/
{
.etype = ENCTYPE_DES_CBC_RAW,
.ctype = CKSUMTYPE_RSA_MD5,
.name = "des-cbc-crc",
.encrypt_name = "cbc(des)",
.cksum_name = "md5",
.encrypt = krb5_encrypt,
.decrypt = krb5_decrypt,
.signalg = SGN_ALG_DES_MAC_MD5,
.sealalg = SEAL_ALG_DES,
.keybytes = 7,
.keylength = 8,
.blocksize = 8,
.cksumlength = 8,
},
};
static const int num_supported_enctypes =
ARRAY_SIZE(supported_gss_krb5_enctypes);
static int
supported_gss_krb5_enctype(int etype)
{
int i;
for (i = 0; i < num_supported_enctypes; i++)
if (supported_gss_krb5_enctypes[i].etype == etype)
return 1;
return 0;
}
static const struct gss_krb5_enctype *
get_gss_krb5_enctype(int etype)
{
int i;
for (i = 0; i < num_supported_enctypes; i++)
if (supported_gss_krb5_enctypes[i].etype == etype)
return &supported_gss_krb5_enctypes[i];
return NULL;
}
static const void * static const void *
simple_get_bytes(const void *p, const void *end, void *res, int len) simple_get_bytes(const void *p, const void *end, void *res, int len)
{ {
...@@ -78,35 +122,45 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res) ...@@ -78,35 +122,45 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res)
} }
static inline const void * static inline const void *
get_key(const void *p, const void *end, struct crypto_blkcipher **res) get_key(const void *p, const void *end,
struct krb5_ctx *ctx, struct crypto_blkcipher **res)
{ {
struct xdr_netobj key; struct xdr_netobj key;
int alg; int alg;
char *alg_name;
p = simple_get_bytes(p, end, &alg, sizeof(alg)); p = simple_get_bytes(p, end, &alg, sizeof(alg));
if (IS_ERR(p)) if (IS_ERR(p))
goto out_err; goto out_err;
switch (alg) {
case ENCTYPE_DES_CBC_CRC:
case ENCTYPE_DES_CBC_MD4:
case ENCTYPE_DES_CBC_MD5:
/* Map all these key types to ENCTYPE_DES_CBC_RAW */
alg = ENCTYPE_DES_CBC_RAW;
break;
}
if (!supported_gss_krb5_enctype(alg)) {
printk(KERN_WARNING "gss_kerberos_mech: unsupported "
"encryption key algorithm %d\n", alg);
goto out_err;
}
p = simple_get_netobj(p, end, &key); p = simple_get_netobj(p, end, &key);
if (IS_ERR(p)) if (IS_ERR(p))
goto out_err; goto out_err;
switch (alg) { *res = crypto_alloc_blkcipher(ctx->gk5e->encrypt_name, 0,
case ENCTYPE_DES_CBC_RAW: CRYPTO_ALG_ASYNC);
alg_name = "cbc(des)";
break;
default:
printk("gss_kerberos_mech: unsupported algorithm %d\n", alg);
goto out_err_free_key;
}
*res = crypto_alloc_blkcipher(alg_name, 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(*res)) { if (IS_ERR(*res)) {
printk("gss_kerberos_mech: unable to initialize crypto algorithm %s\n", alg_name); printk(KERN_WARNING "gss_kerberos_mech: unable to initialize "
"crypto algorithm %s\n", ctx->gk5e->encrypt_name);
*res = NULL; *res = NULL;
goto out_err_free_key; goto out_err_free_key;
} }
if (crypto_blkcipher_setkey(*res, key.data, key.len)) { if (crypto_blkcipher_setkey(*res, key.data, key.len)) {
printk("gss_kerberos_mech: error setting key for crypto algorithm %s\n", alg_name); printk(KERN_WARNING "gss_kerberos_mech: error setting key for "
"crypto algorithm %s\n", ctx->gk5e->encrypt_name);
goto out_err_free_tfm; goto out_err_free_tfm;
} }
...@@ -134,6 +188,10 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx) ...@@ -134,6 +188,10 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx)
/* Old format supports only DES! Any other enctype uses new format */ /* Old format supports only DES! Any other enctype uses new format */
ctx->enctype = ENCTYPE_DES_CBC_RAW; ctx->enctype = ENCTYPE_DES_CBC_RAW;
ctx->gk5e = get_gss_krb5_enctype(ctx->enctype);
if (ctx->gk5e == NULL)
goto out_err;
/* The downcall format was designed before we completely understood /* The downcall format was designed before we completely understood
* the uses of the context fields; so it includes some stuff we * the uses of the context fields; so it includes some stuff we
* just give some minimal sanity-checking, and some we ignore * just give some minimal sanity-checking, and some we ignore
...@@ -164,10 +222,10 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx) ...@@ -164,10 +222,10 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx)
p = simple_get_netobj(p, end, &ctx->mech_used); p = simple_get_netobj(p, end, &ctx->mech_used);
if (IS_ERR(p)) if (IS_ERR(p))
goto out_err; goto out_err;
p = get_key(p, end, &ctx->enc); p = get_key(p, end, ctx, &ctx->enc);
if (IS_ERR(p)) if (IS_ERR(p))
goto out_err_free_mech; goto out_err_free_mech;
p = get_key(p, end, &ctx->seq); p = get_key(p, end, ctx, &ctx->seq);
if (IS_ERR(p)) if (IS_ERR(p))
goto out_err_free_key1; goto out_err_free_key1;
if (p != end) { if (p != end) {
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/krb5/k5seal.c * Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/krb5/k5seal.c
* *
* Copyright (c) 2000 The Regents of the University of Michigan. * Copyright (c) 2000-2008 The Regents of the University of Michigan.
* All rights reserved. * All rights reserved.
* *
* Andy Adamson <andros@umich.edu> * Andy Adamson <andros@umich.edu>
...@@ -70,36 +70,47 @@ ...@@ -70,36 +70,47 @@
DEFINE_SPINLOCK(krb5_seq_lock); DEFINE_SPINLOCK(krb5_seq_lock);
static char *
setup_token(struct krb5_ctx *ctx, struct xdr_netobj *token)
{
__be16 *ptr, *krb5_hdr;
int body_size = GSS_KRB5_TOK_HDR_LEN + ctx->gk5e->cksumlength;
token->len = g_token_size(&ctx->mech_used, body_size);
ptr = (__be16 *)token->data;
g_make_token_header(&ctx->mech_used, body_size, (unsigned char **)&ptr);
/* ptr now at start of header described in rfc 1964, section 1.2.1: */
krb5_hdr = ptr;
*ptr++ = KG_TOK_MIC_MSG;
*ptr++ = cpu_to_le16(ctx->gk5e->signalg);
*ptr++ = SEAL_ALG_NONE;
*ptr++ = 0xffff;
return (char *)krb5_hdr;
}
static u32 static u32
gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text, gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text,
struct xdr_netobj *token) struct xdr_netobj *token)
{ {
char cksumdata[16]; char cksumdata[GSS_KRB5_MAX_CKSUM_LEN];
struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata}; struct xdr_netobj md5cksum = {.len = sizeof(cksumdata),
unsigned char *ptr, *msg_start; .data = cksumdata};
void *ptr;
s32 now; s32 now;
u32 seq_send; u32 seq_send;
dprintk("RPC: gss_krb5_seal\n"); dprintk("RPC: %s\n", __func__);
BUG_ON(ctx == NULL); BUG_ON(ctx == NULL);
now = get_seconds(); now = get_seconds();
token->len = g_token_size(&ctx->mech_used, GSS_KRB5_TOK_HDR_LEN + 8); ptr = setup_token(ctx, token);
ptr = token->data;
g_make_token_header(&ctx->mech_used, GSS_KRB5_TOK_HDR_LEN + 8, &ptr);
/* ptr now at header described in rfc 1964, section 1.2.1: */
ptr[0] = (unsigned char) ((KG_TOK_MIC_MSG >> 8) & 0xff);
ptr[1] = (unsigned char) (KG_TOK_MIC_MSG & 0xff);
msg_start = ptr + GSS_KRB5_TOK_HDR_LEN + 8;
*(__be16 *)(ptr + 2) = htons(SGN_ALG_DES_MAC_MD5);
memset(ptr + 4, 0xff, 4);
if (make_checksum("md5", ptr, 8, text, 0, &md5cksum)) if (make_checksum((char *)ctx->gk5e->cksum_name, ptr, 8,
text, 0, &md5cksum))
return GSS_S_FAILURE; return GSS_S_FAILURE;
if (krb5_encrypt(ctx->seq, NULL, md5cksum.data, if (krb5_encrypt(ctx->seq, NULL, md5cksum.data,
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/krb5/k5unseal.c * Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/krb5/k5unseal.c
* *
* Copyright (c) 2000 The Regents of the University of Michigan. * Copyright (c) 2000-2008 The Regents of the University of Michigan.
* All rights reserved. * All rights reserved.
* *
* Andy Adamson <andros@umich.edu> * Andy Adamson <andros@umich.edu>
...@@ -76,8 +76,9 @@ gss_verify_mic_v1(struct krb5_ctx *ctx, ...@@ -76,8 +76,9 @@ gss_verify_mic_v1(struct krb5_ctx *ctx,
{ {
int signalg; int signalg;
int sealalg; int sealalg;
char cksumdata[16]; char cksumdata[GSS_KRB5_MAX_CKSUM_LEN];
struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata}; struct xdr_netobj md5cksum = {.len = sizeof(cksumdata),
.data = cksumdata};
s32 now; s32 now;
int direction; int direction;
u32 seqnum; u32 seqnum;
...@@ -97,7 +98,7 @@ gss_verify_mic_v1(struct krb5_ctx *ctx, ...@@ -97,7 +98,7 @@ gss_verify_mic_v1(struct krb5_ctx *ctx,
/* XXX sanity-check bodysize?? */ /* XXX sanity-check bodysize?? */
signalg = ptr[2] + (ptr[3] << 8); signalg = ptr[2] + (ptr[3] << 8);
if (signalg != SGN_ALG_DES_MAC_MD5) if (signalg != ctx->gk5e->signalg)
return GSS_S_DEFECTIVE_TOKEN; return GSS_S_DEFECTIVE_TOKEN;
sealalg = ptr[4] + (ptr[5] << 8); sealalg = ptr[4] + (ptr[5] << 8);
...@@ -107,13 +108,15 @@ gss_verify_mic_v1(struct krb5_ctx *ctx, ...@@ -107,13 +108,15 @@ gss_verify_mic_v1(struct krb5_ctx *ctx,
if ((ptr[6] != 0xff) || (ptr[7] != 0xff)) if ((ptr[6] != 0xff) || (ptr[7] != 0xff))
return GSS_S_DEFECTIVE_TOKEN; return GSS_S_DEFECTIVE_TOKEN;
if (make_checksum("md5", ptr, 8, message_buffer, 0, &md5cksum)) if (make_checksum((char *)ctx->gk5e->cksum_name, ptr, 8,
message_buffer, 0, &md5cksum))
return GSS_S_FAILURE; return GSS_S_FAILURE;
if (krb5_encrypt(ctx->seq, NULL, md5cksum.data, md5cksum.data, 16)) if (krb5_encrypt(ctx->seq, NULL, md5cksum.data, md5cksum.data, 16))
return GSS_S_FAILURE; return GSS_S_FAILURE;
if (memcmp(md5cksum.data + 8, ptr + GSS_KRB5_TOK_HDR_LEN, 8)) if (memcmp(md5cksum.data + 8, ptr + GSS_KRB5_TOK_HDR_LEN,
ctx->gk5e->cksumlength))
return GSS_S_BAD_SIG; return GSS_S_BAD_SIG;
/* it got through unscathed. Make sure the context is unexpired */ /* it got through unscathed. Make sure the context is unexpired */
......
/*
* COPYRIGHT (c) 2008
* The Regents of the University of Michigan
* ALL RIGHTS RESERVED
*
* Permission is granted to use, copy, create derivative works
* and redistribute this software and such derivative works
* for any purpose, so long as the name of The University of
* Michigan is not used in any advertising or publicity
* pertaining to the use of distribution of this software
* without specific, written prior authorization. If the
* above copyright notice or any other identification of the
* University of Michigan is included in any copy of any
* portion of this software, then the disclaimer below must
* also be included.
*
* THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
* FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
* PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
* MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
* WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
* REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
* FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
* OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
* IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGES.
*/
#include <linux/types.h> #include <linux/types.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/sunrpc/gss_krb5.h> #include <linux/sunrpc/gss_krb5.h>
...@@ -128,8 +158,9 @@ static u32 ...@@ -128,8 +158,9 @@ static u32
gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
struct xdr_buf *buf, struct page **pages) struct xdr_buf *buf, struct page **pages)
{ {
char cksumdata[16]; char cksumdata[GSS_KRB5_MAX_CKSUM_LEN];
struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata}; struct xdr_netobj md5cksum = {.len = sizeof(cksumdata),
.data = cksumdata};
int blocksize = 0, plainlen; int blocksize = 0, plainlen;
unsigned char *ptr, *msg_start; unsigned char *ptr, *msg_start;
s32 now; s32 now;
...@@ -137,7 +168,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, ...@@ -137,7 +168,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
struct page **tmp_pages; struct page **tmp_pages;
u32 seq_send; u32 seq_send;
dprintk("RPC: gss_wrap_kerberos\n"); dprintk("RPC: %s\n", __func__);
now = get_seconds(); now = get_seconds();
...@@ -146,8 +177,9 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, ...@@ -146,8 +177,9 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
BUG_ON((buf->len - offset) % blocksize); BUG_ON((buf->len - offset) % blocksize);
plainlen = blocksize + buf->len - offset; plainlen = blocksize + buf->len - offset;
headlen = g_token_size(&kctx->mech_used, 24 + plainlen) - headlen = g_token_size(&kctx->mech_used,
(buf->len - offset); GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength + plainlen) -
(buf->len - offset);
ptr = buf->head[0].iov_base + offset; ptr = buf->head[0].iov_base + offset;
/* shift data to make room for header. */ /* shift data to make room for header. */
...@@ -157,25 +189,26 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, ...@@ -157,25 +189,26 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
BUG_ON((buf->len - offset - headlen) % blocksize); BUG_ON((buf->len - offset - headlen) % blocksize);
g_make_token_header(&kctx->mech_used, g_make_token_header(&kctx->mech_used,
GSS_KRB5_TOK_HDR_LEN + 8 + plainlen, &ptr); GSS_KRB5_TOK_HDR_LEN +
kctx->gk5e->cksumlength + plainlen, &ptr);
/* ptr now at header described in rfc 1964, section 1.2.1: */ /* ptr now at header described in rfc 1964, section 1.2.1: */
ptr[0] = (unsigned char) ((KG_TOK_WRAP_MSG >> 8) & 0xff); ptr[0] = (unsigned char) ((KG_TOK_WRAP_MSG >> 8) & 0xff);
ptr[1] = (unsigned char) (KG_TOK_WRAP_MSG & 0xff); ptr[1] = (unsigned char) (KG_TOK_WRAP_MSG & 0xff);
msg_start = ptr + 24; msg_start = ptr + GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength;
*(__be16 *)(ptr + 2) = htons(SGN_ALG_DES_MAC_MD5); *(__be16 *)(ptr + 2) = cpu_to_le16(kctx->gk5e->signalg);
memset(ptr + 4, 0xff, 4); memset(ptr + 4, 0xff, 4);
*(__be16 *)(ptr + 4) = htons(SEAL_ALG_DES); *(__be16 *)(ptr + 4) = cpu_to_le16(kctx->gk5e->sealalg);
make_confounder(msg_start, blocksize); make_confounder(msg_start, blocksize);
/* XXXJBF: UGH!: */ /* XXXJBF: UGH!: */
tmp_pages = buf->pages; tmp_pages = buf->pages;
buf->pages = pages; buf->pages = pages;
if (make_checksum("md5", ptr, 8, buf, if (make_checksum((char *)kctx->gk5e->cksum_name, ptr, 8, buf,
offset + headlen - blocksize, &md5cksum)) offset + headlen - blocksize, &md5cksum))
return GSS_S_FAILURE; return GSS_S_FAILURE;
buf->pages = tmp_pages; buf->pages = tmp_pages;
...@@ -207,8 +240,9 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) ...@@ -207,8 +240,9 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
{ {
int signalg; int signalg;
int sealalg; int sealalg;
char cksumdata[16]; char cksumdata[GSS_KRB5_MAX_CKSUM_LEN];
struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata}; struct xdr_netobj md5cksum = {.len = sizeof(cksumdata),
.data = cksumdata};
s32 now; s32 now;
int direction; int direction;
s32 seqnum; s32 seqnum;
...@@ -217,6 +251,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) ...@@ -217,6 +251,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
void *data_start, *orig_start; void *data_start, *orig_start;
int data_len; int data_len;
int blocksize; int blocksize;
int crypt_offset;
dprintk("RPC: gss_unwrap_kerberos\n"); dprintk("RPC: gss_unwrap_kerberos\n");
...@@ -234,22 +269,27 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) ...@@ -234,22 +269,27 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
/* get the sign and seal algorithms */ /* get the sign and seal algorithms */
signalg = ptr[2] + (ptr[3] << 8); signalg = ptr[2] + (ptr[3] << 8);
if (signalg != SGN_ALG_DES_MAC_MD5) if (signalg != kctx->gk5e->signalg)
return GSS_S_DEFECTIVE_TOKEN; return GSS_S_DEFECTIVE_TOKEN;
sealalg = ptr[4] + (ptr[5] << 8); sealalg = ptr[4] + (ptr[5] << 8);
if (sealalg != SEAL_ALG_DES) if (sealalg != kctx->gk5e->sealalg)
return GSS_S_DEFECTIVE_TOKEN; return GSS_S_DEFECTIVE_TOKEN;
if ((ptr[6] != 0xff) || (ptr[7] != 0xff)) if ((ptr[6] != 0xff) || (ptr[7] != 0xff))
return GSS_S_DEFECTIVE_TOKEN; return GSS_S_DEFECTIVE_TOKEN;
if (gss_decrypt_xdr_buf(kctx->enc, buf, /*
ptr + GSS_KRB5_TOK_HDR_LEN + 8 - (unsigned char *)buf->head[0].iov_base)) * Data starts after token header and checksum. ptr points
* to the beginning of the token header
*/
crypt_offset = ptr + (GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength) -
(unsigned char *)buf->head[0].iov_base;
if (gss_decrypt_xdr_buf(kctx->enc, buf, crypt_offset))
return GSS_S_DEFECTIVE_TOKEN; return GSS_S_DEFECTIVE_TOKEN;
if (make_checksum("md5", ptr, 8, buf, if (make_checksum((char *)kctx->gk5e->cksum_name, ptr, 8, buf,
ptr + GSS_KRB5_TOK_HDR_LEN + 8 - (unsigned char *)buf->head[0].iov_base, &md5cksum)) crypt_offset, &md5cksum))
return GSS_S_FAILURE; return GSS_S_FAILURE;
if (krb5_encrypt(kctx->seq, NULL, md5cksum.data, if (krb5_encrypt(kctx->seq, NULL, md5cksum.data,
...@@ -280,7 +320,8 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) ...@@ -280,7 +320,8 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
* better to copy and encrypt at the same time. */ * better to copy and encrypt at the same time. */
blocksize = crypto_blkcipher_blocksize(kctx->enc); blocksize = crypto_blkcipher_blocksize(kctx->enc);
data_start = ptr + GSS_KRB5_TOK_HDR_LEN + 8 + blocksize; data_start = ptr + (GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength) +
blocksize;
orig_start = buf->head[0].iov_base + offset; orig_start = buf->head[0].iov_base + offset;
data_len = (buf->head[0].iov_base + buf->head[0].iov_len) - data_start; data_len = (buf->head[0].iov_base + buf->head[0].iov_len) - data_start;
memmove(orig_start, data_start, data_len); memmove(orig_start, data_start, data_len);
......
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