diff options
author | Kevin Coffman <kwc@citi.umich.edu> | 2010-03-17 13:02:51 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-05-14 15:09:16 -0400 |
commit | 81d4a4333a1dfd6070f046265d928bb4c79aff88 (patch) | |
tree | 652fce6cd75be7388f0cd5c45aec653814710791 /net/sunrpc | |
parent | a8cc1cb7d7a12b0e2855832d10cfbfaffebfad6c (diff) |
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: Kevin Coffman <kwc@citi.umich.edu>
Signed-off-by: Steve Dickson <steved@redhat.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_crypto.c | 18 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_mech.c | 90 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_seal.c | 49 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_unseal.c | 15 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_wrap.c | 79 |
5 files changed, 182 insertions, 69 deletions
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index 746b3e139aed..ccd5236953f7 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * linux/net/sunrpc/gss_krb5_crypto.c | 2 | * linux/net/sunrpc/gss_krb5_crypto.c |
3 | * | 3 | * |
4 | * Copyright (c) 2000 The Regents of the University of Michigan. | 4 | * Copyright (c) 2000-2008 The Regents of the University of Michigan. |
5 | * All rights reserved. | 5 | * All rights reserved. |
6 | * | 6 | * |
7 | * Andy Adamson <andros@umich.edu> | 7 | * Andy Adamson <andros@umich.edu> |
@@ -58,13 +58,13 @@ krb5_encrypt( | |||
58 | { | 58 | { |
59 | u32 ret = -EINVAL; | 59 | u32 ret = -EINVAL; |
60 | struct scatterlist sg[1]; | 60 | struct scatterlist sg[1]; |
61 | u8 local_iv[16] = {0}; | 61 | u8 local_iv[GSS_KRB5_MAX_BLOCKSIZE] = {0}; |
62 | struct blkcipher_desc desc = { .tfm = tfm, .info = local_iv }; | 62 | struct blkcipher_desc desc = { .tfm = tfm, .info = local_iv }; |
63 | 63 | ||
64 | if (length % crypto_blkcipher_blocksize(tfm) != 0) | 64 | if (length % crypto_blkcipher_blocksize(tfm) != 0) |
65 | goto out; | 65 | goto out; |
66 | 66 | ||
67 | if (crypto_blkcipher_ivsize(tfm) > 16) { | 67 | if (crypto_blkcipher_ivsize(tfm) > GSS_KRB5_MAX_BLOCKSIZE) { |
68 | dprintk("RPC: gss_k5encrypt: tfm iv size too large %d\n", | 68 | dprintk("RPC: gss_k5encrypt: tfm iv size too large %d\n", |
69 | crypto_blkcipher_ivsize(tfm)); | 69 | crypto_blkcipher_ivsize(tfm)); |
70 | goto out; | 70 | goto out; |
@@ -92,13 +92,13 @@ krb5_decrypt( | |||
92 | { | 92 | { |
93 | u32 ret = -EINVAL; | 93 | u32 ret = -EINVAL; |
94 | struct scatterlist sg[1]; | 94 | struct scatterlist sg[1]; |
95 | u8 local_iv[16] = {0}; | 95 | u8 local_iv[GSS_KRB5_MAX_BLOCKSIZE] = {0}; |
96 | struct blkcipher_desc desc = { .tfm = tfm, .info = local_iv }; | 96 | struct blkcipher_desc desc = { .tfm = tfm, .info = local_iv }; |
97 | 97 | ||
98 | if (length % crypto_blkcipher_blocksize(tfm) != 0) | 98 | if (length % crypto_blkcipher_blocksize(tfm) != 0) |
99 | goto out; | 99 | goto out; |
100 | 100 | ||
101 | if (crypto_blkcipher_ivsize(tfm) > 16) { | 101 | if (crypto_blkcipher_ivsize(tfm) > GSS_KRB5_MAX_BLOCKSIZE) { |
102 | dprintk("RPC: gss_k5decrypt: tfm iv size too large %d\n", | 102 | dprintk("RPC: gss_k5decrypt: tfm iv size too large %d\n", |
103 | crypto_blkcipher_ivsize(tfm)); | 103 | crypto_blkcipher_ivsize(tfm)); |
104 | goto out; | 104 | goto out; |
@@ -157,7 +157,7 @@ out: | |||
157 | } | 157 | } |
158 | 158 | ||
159 | struct encryptor_desc { | 159 | struct encryptor_desc { |
160 | u8 iv[8]; /* XXX hard-coded blocksize */ | 160 | u8 iv[GSS_KRB5_MAX_BLOCKSIZE]; |
161 | struct blkcipher_desc desc; | 161 | struct blkcipher_desc desc; |
162 | int pos; | 162 | int pos; |
163 | struct xdr_buf *outbuf; | 163 | struct xdr_buf *outbuf; |
@@ -198,7 +198,7 @@ encryptor(struct scatterlist *sg, void *data) | |||
198 | desc->fraglen += sg->length; | 198 | desc->fraglen += sg->length; |
199 | desc->pos += sg->length; | 199 | desc->pos += sg->length; |
200 | 200 | ||
201 | fraglen = thislen & 7; /* XXX hardcoded blocksize */ | 201 | fraglen = thislen & (crypto_blkcipher_blocksize(desc->desc.tfm) - 1); |
202 | thislen -= fraglen; | 202 | thislen -= fraglen; |
203 | 203 | ||
204 | if (thislen == 0) | 204 | if (thislen == 0) |
@@ -256,7 +256,7 @@ gss_encrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf, | |||
256 | } | 256 | } |
257 | 257 | ||
258 | struct decryptor_desc { | 258 | struct decryptor_desc { |
259 | u8 iv[8]; /* XXX hard-coded blocksize */ | 259 | u8 iv[GSS_KRB5_MAX_BLOCKSIZE]; |
260 | struct blkcipher_desc desc; | 260 | struct blkcipher_desc desc; |
261 | struct scatterlist frags[4]; | 261 | struct scatterlist frags[4]; |
262 | int fragno; | 262 | int fragno; |
@@ -278,7 +278,7 @@ decryptor(struct scatterlist *sg, void *data) | |||
278 | desc->fragno++; | 278 | desc->fragno++; |
279 | desc->fraglen += sg->length; | 279 | desc->fraglen += sg->length; |
280 | 280 | ||
281 | fraglen = thislen & 7; /* XXX hardcoded blocksize */ | 281 | fraglen = thislen & (crypto_blkcipher_blocksize(desc->desc.tfm) - 1); |
282 | thislen -= fraglen; | 282 | thislen -= fraglen; |
283 | 283 | ||
284 | if (thislen == 0) | 284 | if (thislen == 0) |
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index afe09108e1b0..a66eb706aeb7 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * linux/net/sunrpc/gss_krb5_mech.c | 2 | * linux/net/sunrpc/gss_krb5_mech.c |
3 | * | 3 | * |
4 | * Copyright (c) 2001 The Regents of the University of Michigan. | 4 | * Copyright (c) 2001-2008 The Regents of the University of Michigan. |
5 | * All rights reserved. | 5 | * All rights reserved. |
6 | * | 6 | * |
7 | * Andy Adamson <andros@umich.edu> | 7 | * Andy Adamson <andros@umich.edu> |
@@ -48,6 +48,50 @@ | |||
48 | # define RPCDBG_FACILITY RPCDBG_AUTH | 48 | # define RPCDBG_FACILITY RPCDBG_AUTH |
49 | #endif | 49 | #endif |
50 | 50 | ||
51 | static const struct gss_krb5_enctype supported_gss_krb5_enctypes[] = { | ||
52 | /* | ||
53 | * DES (All DES enctypes are mapped to the same gss functionality) | ||
54 | */ | ||
55 | { | ||
56 | .etype = ENCTYPE_DES_CBC_RAW, | ||
57 | .ctype = CKSUMTYPE_RSA_MD5, | ||
58 | .name = "des-cbc-crc", | ||
59 | .encrypt_name = "cbc(des)", | ||
60 | .cksum_name = "md5", | ||
61 | .encrypt = krb5_encrypt, | ||
62 | .decrypt = krb5_decrypt, | ||
63 | .signalg = SGN_ALG_DES_MAC_MD5, | ||
64 | .sealalg = SEAL_ALG_DES, | ||
65 | .keybytes = 7, | ||
66 | .keylength = 8, | ||
67 | .blocksize = 8, | ||
68 | .cksumlength = 8, | ||
69 | }, | ||
70 | }; | ||
71 | |||
72 | static const int num_supported_enctypes = | ||
73 | ARRAY_SIZE(supported_gss_krb5_enctypes); | ||
74 | |||
75 | static int | ||
76 | supported_gss_krb5_enctype(int etype) | ||
77 | { | ||
78 | int i; | ||
79 | for (i = 0; i < num_supported_enctypes; i++) | ||
80 | if (supported_gss_krb5_enctypes[i].etype == etype) | ||
81 | return 1; | ||
82 | return 0; | ||
83 | } | ||
84 | |||
85 | static const struct gss_krb5_enctype * | ||
86 | get_gss_krb5_enctype(int etype) | ||
87 | { | ||
88 | int i; | ||
89 | for (i = 0; i < num_supported_enctypes; i++) | ||
90 | if (supported_gss_krb5_enctypes[i].etype == etype) | ||
91 | return &supported_gss_krb5_enctypes[i]; | ||
92 | return NULL; | ||
93 | } | ||
94 | |||
51 | static const void * | 95 | static const void * |
52 | simple_get_bytes(const void *p, const void *end, void *res, int len) | 96 | simple_get_bytes(const void *p, const void *end, void *res, int len) |
53 | { | 97 | { |
@@ -78,35 +122,45 @@ simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res) | |||
78 | } | 122 | } |
79 | 123 | ||
80 | static inline const void * | 124 | static inline const void * |
81 | get_key(const void *p, const void *end, struct crypto_blkcipher **res) | 125 | get_key(const void *p, const void *end, |
126 | struct krb5_ctx *ctx, struct crypto_blkcipher **res) | ||
82 | { | 127 | { |
83 | struct xdr_netobj key; | 128 | struct xdr_netobj key; |
84 | int alg; | 129 | int alg; |
85 | char *alg_name; | ||
86 | 130 | ||
87 | p = simple_get_bytes(p, end, &alg, sizeof(alg)); | 131 | p = simple_get_bytes(p, end, &alg, sizeof(alg)); |
88 | if (IS_ERR(p)) | 132 | if (IS_ERR(p)) |
89 | goto out_err; | 133 | goto out_err; |
134 | |||
135 | switch (alg) { | ||
136 | case ENCTYPE_DES_CBC_CRC: | ||
137 | case ENCTYPE_DES_CBC_MD4: | ||
138 | case ENCTYPE_DES_CBC_MD5: | ||
139 | /* Map all these key types to ENCTYPE_DES_CBC_RAW */ | ||
140 | alg = ENCTYPE_DES_CBC_RAW; | ||
141 | break; | ||
142 | } | ||
143 | |||
144 | if (!supported_gss_krb5_enctype(alg)) { | ||
145 | printk(KERN_WARNING "gss_kerberos_mech: unsupported " | ||
146 | "encryption key algorithm %d\n", alg); | ||
147 | goto out_err; | ||
148 | } | ||
90 | p = simple_get_netobj(p, end, &key); | 149 | p = simple_get_netobj(p, end, &key); |
91 | if (IS_ERR(p)) | 150 | if (IS_ERR(p)) |
92 | goto out_err; | 151 | goto out_err; |
93 | 152 | ||
94 | switch (alg) { | 153 | *res = crypto_alloc_blkcipher(ctx->gk5e->encrypt_name, 0, |
95 | case ENCTYPE_DES_CBC_RAW: | 154 | CRYPTO_ALG_ASYNC); |
96 | alg_name = "cbc(des)"; | ||
97 | break; | ||
98 | default: | ||
99 | printk("gss_kerberos_mech: unsupported algorithm %d\n", alg); | ||
100 | goto out_err_free_key; | ||
101 | } | ||
102 | *res = crypto_alloc_blkcipher(alg_name, 0, CRYPTO_ALG_ASYNC); | ||
103 | if (IS_ERR(*res)) { | 155 | if (IS_ERR(*res)) { |
104 | printk("gss_kerberos_mech: unable to initialize crypto algorithm %s\n", alg_name); | 156 | printk(KERN_WARNING "gss_kerberos_mech: unable to initialize " |
157 | "crypto algorithm %s\n", ctx->gk5e->encrypt_name); | ||
105 | *res = NULL; | 158 | *res = NULL; |
106 | goto out_err_free_key; | 159 | goto out_err_free_key; |
107 | } | 160 | } |
108 | if (crypto_blkcipher_setkey(*res, key.data, key.len)) { | 161 | if (crypto_blkcipher_setkey(*res, key.data, key.len)) { |
109 | printk("gss_kerberos_mech: error setting key for crypto algorithm %s\n", alg_name); | 162 | printk(KERN_WARNING "gss_kerberos_mech: error setting key for " |
163 | "crypto algorithm %s\n", ctx->gk5e->encrypt_name); | ||
110 | goto out_err_free_tfm; | 164 | goto out_err_free_tfm; |
111 | } | 165 | } |
112 | 166 | ||
@@ -134,6 +188,10 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx) | |||
134 | /* Old format supports only DES! Any other enctype uses new format */ | 188 | /* Old format supports only DES! Any other enctype uses new format */ |
135 | ctx->enctype = ENCTYPE_DES_CBC_RAW; | 189 | ctx->enctype = ENCTYPE_DES_CBC_RAW; |
136 | 190 | ||
191 | ctx->gk5e = get_gss_krb5_enctype(ctx->enctype); | ||
192 | if (ctx->gk5e == NULL) | ||
193 | goto out_err; | ||
194 | |||
137 | /* The downcall format was designed before we completely understood | 195 | /* The downcall format was designed before we completely understood |
138 | * the uses of the context fields; so it includes some stuff we | 196 | * the uses of the context fields; so it includes some stuff we |
139 | * just give some minimal sanity-checking, and some we ignore | 197 | * 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 | p = simple_get_netobj(p, end, &ctx->mech_used); | 222 | p = simple_get_netobj(p, end, &ctx->mech_used); |
165 | if (IS_ERR(p)) | 223 | if (IS_ERR(p)) |
166 | goto out_err; | 224 | goto out_err; |
167 | p = get_key(p, end, &ctx->enc); | 225 | p = get_key(p, end, ctx, &ctx->enc); |
168 | if (IS_ERR(p)) | 226 | if (IS_ERR(p)) |
169 | goto out_err_free_mech; | 227 | goto out_err_free_mech; |
170 | p = get_key(p, end, &ctx->seq); | 228 | p = get_key(p, end, ctx, &ctx->seq); |
171 | if (IS_ERR(p)) | 229 | if (IS_ERR(p)) |
172 | goto out_err_free_key1; | 230 | goto out_err_free_key1; |
173 | if (p != end) { | 231 | if (p != end) { |
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c index 71c2014e7ebf..46c6f44e5c3f 100644 --- a/net/sunrpc/auth_gss/gss_krb5_seal.c +++ b/net/sunrpc/auth_gss/gss_krb5_seal.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/krb5/k5seal.c | 4 | * Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/krb5/k5seal.c |
5 | * | 5 | * |
6 | * Copyright (c) 2000 The Regents of the University of Michigan. | 6 | * Copyright (c) 2000-2008 The Regents of the University of Michigan. |
7 | * All rights reserved. | 7 | * All rights reserved. |
8 | * | 8 | * |
9 | * Andy Adamson <andros@umich.edu> | 9 | * Andy Adamson <andros@umich.edu> |
@@ -70,36 +70,47 @@ | |||
70 | 70 | ||
71 | DEFINE_SPINLOCK(krb5_seq_lock); | 71 | DEFINE_SPINLOCK(krb5_seq_lock); |
72 | 72 | ||
73 | static char * | ||
74 | setup_token(struct krb5_ctx *ctx, struct xdr_netobj *token) | ||
75 | { | ||
76 | __be16 *ptr, *krb5_hdr; | ||
77 | int body_size = GSS_KRB5_TOK_HDR_LEN + ctx->gk5e->cksumlength; | ||
78 | |||
79 | token->len = g_token_size(&ctx->mech_used, body_size); | ||
80 | |||
81 | ptr = (__be16 *)token->data; | ||
82 | g_make_token_header(&ctx->mech_used, body_size, (unsigned char **)&ptr); | ||
83 | |||
84 | /* ptr now at start of header described in rfc 1964, section 1.2.1: */ | ||
85 | krb5_hdr = ptr; | ||
86 | *ptr++ = KG_TOK_MIC_MSG; | ||
87 | *ptr++ = cpu_to_le16(ctx->gk5e->signalg); | ||
88 | *ptr++ = SEAL_ALG_NONE; | ||
89 | *ptr++ = 0xffff; | ||
90 | |||
91 | return (char *)krb5_hdr; | ||
92 | } | ||
93 | |||
73 | static u32 | 94 | static u32 |
74 | gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text, | 95 | gss_get_mic_v1(struct krb5_ctx *ctx, struct xdr_buf *text, |
75 | struct xdr_netobj *token) | 96 | struct xdr_netobj *token) |
76 | { | 97 | { |
77 | char cksumdata[16]; | 98 | char cksumdata[GSS_KRB5_MAX_CKSUM_LEN]; |
78 | struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata}; | 99 | struct xdr_netobj md5cksum = {.len = sizeof(cksumdata), |
79 | unsigned char *ptr, *msg_start; | 100 | .data = cksumdata}; |
101 | void *ptr; | ||
80 | s32 now; | 102 | s32 now; |
81 | u32 seq_send; | 103 | u32 seq_send; |
82 | 104 | ||
83 | dprintk("RPC: gss_krb5_seal\n"); | 105 | dprintk("RPC: %s\n", __func__); |
84 | BUG_ON(ctx == NULL); | 106 | BUG_ON(ctx == NULL); |
85 | 107 | ||
86 | now = get_seconds(); | 108 | now = get_seconds(); |
87 | 109 | ||
88 | token->len = g_token_size(&ctx->mech_used, GSS_KRB5_TOK_HDR_LEN + 8); | 110 | ptr = setup_token(ctx, token); |
89 | |||
90 | ptr = token->data; | ||
91 | g_make_token_header(&ctx->mech_used, GSS_KRB5_TOK_HDR_LEN + 8, &ptr); | ||
92 | |||
93 | /* ptr now at header described in rfc 1964, section 1.2.1: */ | ||
94 | ptr[0] = (unsigned char) ((KG_TOK_MIC_MSG >> 8) & 0xff); | ||
95 | ptr[1] = (unsigned char) (KG_TOK_MIC_MSG & 0xff); | ||
96 | |||
97 | msg_start = ptr + GSS_KRB5_TOK_HDR_LEN + 8; | ||
98 | |||
99 | *(__be16 *)(ptr + 2) = htons(SGN_ALG_DES_MAC_MD5); | ||
100 | memset(ptr + 4, 0xff, 4); | ||
101 | 111 | ||
102 | if (make_checksum("md5", ptr, 8, text, 0, &md5cksum)) | 112 | if (make_checksum((char *)ctx->gk5e->cksum_name, ptr, 8, |
113 | text, 0, &md5cksum)) | ||
103 | return GSS_S_FAILURE; | 114 | return GSS_S_FAILURE; |
104 | 115 | ||
105 | if (krb5_encrypt(ctx->seq, NULL, md5cksum.data, | 116 | if (krb5_encrypt(ctx->seq, NULL, md5cksum.data, |
diff --git a/net/sunrpc/auth_gss/gss_krb5_unseal.c b/net/sunrpc/auth_gss/gss_krb5_unseal.c index 069d4b59807a..10ee641a39d0 100644 --- a/net/sunrpc/auth_gss/gss_krb5_unseal.c +++ b/net/sunrpc/auth_gss/gss_krb5_unseal.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/krb5/k5unseal.c | 4 | * Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/krb5/k5unseal.c |
5 | * | 5 | * |
6 | * Copyright (c) 2000 The Regents of the University of Michigan. | 6 | * Copyright (c) 2000-2008 The Regents of the University of Michigan. |
7 | * All rights reserved. | 7 | * All rights reserved. |
8 | * | 8 | * |
9 | * Andy Adamson <andros@umich.edu> | 9 | * Andy Adamson <andros@umich.edu> |
@@ -76,8 +76,9 @@ gss_verify_mic_v1(struct krb5_ctx *ctx, | |||
76 | { | 76 | { |
77 | int signalg; | 77 | int signalg; |
78 | int sealalg; | 78 | int sealalg; |
79 | char cksumdata[16]; | 79 | char cksumdata[GSS_KRB5_MAX_CKSUM_LEN]; |
80 | struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata}; | 80 | struct xdr_netobj md5cksum = {.len = sizeof(cksumdata), |
81 | .data = cksumdata}; | ||
81 | s32 now; | 82 | s32 now; |
82 | int direction; | 83 | int direction; |
83 | u32 seqnum; | 84 | u32 seqnum; |
@@ -97,7 +98,7 @@ gss_verify_mic_v1(struct krb5_ctx *ctx, | |||
97 | /* XXX sanity-check bodysize?? */ | 98 | /* XXX sanity-check bodysize?? */ |
98 | 99 | ||
99 | signalg = ptr[2] + (ptr[3] << 8); | 100 | signalg = ptr[2] + (ptr[3] << 8); |
100 | if (signalg != SGN_ALG_DES_MAC_MD5) | 101 | if (signalg != ctx->gk5e->signalg) |
101 | return GSS_S_DEFECTIVE_TOKEN; | 102 | return GSS_S_DEFECTIVE_TOKEN; |
102 | 103 | ||
103 | sealalg = ptr[4] + (ptr[5] << 8); | 104 | sealalg = ptr[4] + (ptr[5] << 8); |
@@ -107,13 +108,15 @@ gss_verify_mic_v1(struct krb5_ctx *ctx, | |||
107 | if ((ptr[6] != 0xff) || (ptr[7] != 0xff)) | 108 | if ((ptr[6] != 0xff) || (ptr[7] != 0xff)) |
108 | return GSS_S_DEFECTIVE_TOKEN; | 109 | return GSS_S_DEFECTIVE_TOKEN; |
109 | 110 | ||
110 | if (make_checksum("md5", ptr, 8, message_buffer, 0, &md5cksum)) | 111 | if (make_checksum((char *)ctx->gk5e->cksum_name, ptr, 8, |
112 | message_buffer, 0, &md5cksum)) | ||
111 | return GSS_S_FAILURE; | 113 | return GSS_S_FAILURE; |
112 | 114 | ||
113 | if (krb5_encrypt(ctx->seq, NULL, md5cksum.data, md5cksum.data, 16)) | 115 | if (krb5_encrypt(ctx->seq, NULL, md5cksum.data, md5cksum.data, 16)) |
114 | return GSS_S_FAILURE; | 116 | return GSS_S_FAILURE; |
115 | 117 | ||
116 | if (memcmp(md5cksum.data + 8, ptr + GSS_KRB5_TOK_HDR_LEN, 8)) | 118 | if (memcmp(md5cksum.data + 8, ptr + GSS_KRB5_TOK_HDR_LEN, |
119 | ctx->gk5e->cksumlength)) | ||
117 | return GSS_S_BAD_SIG; | 120 | return GSS_S_BAD_SIG; |
118 | 121 | ||
119 | /* it got through unscathed. Make sure the context is unexpired */ | 122 | /* it got through unscathed. Make sure the context is unexpired */ |
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index b45b59b17ae1..7188891bcc33 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c | |||
@@ -1,3 +1,33 @@ | |||
1 | /* | ||
2 | * COPYRIGHT (c) 2008 | ||
3 | * The Regents of the University of Michigan | ||
4 | * ALL RIGHTS RESERVED | ||
5 | * | ||
6 | * Permission is granted to use, copy, create derivative works | ||
7 | * and redistribute this software and such derivative works | ||
8 | * for any purpose, so long as the name of The University of | ||
9 | * Michigan is not used in any advertising or publicity | ||
10 | * pertaining to the use of distribution of this software | ||
11 | * without specific, written prior authorization. If the | ||
12 | * above copyright notice or any other identification of the | ||
13 | * University of Michigan is included in any copy of any | ||
14 | * portion of this software, then the disclaimer below must | ||
15 | * also be included. | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION | ||
18 | * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY | ||
19 | * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF | ||
20 | * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING | ||
21 | * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF | ||
22 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE | ||
23 | * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE | ||
24 | * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR | ||
25 | * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING | ||
26 | * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN | ||
27 | * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF | ||
28 | * SUCH DAMAGES. | ||
29 | */ | ||
30 | |||
1 | #include <linux/types.h> | 31 | #include <linux/types.h> |
2 | #include <linux/jiffies.h> | 32 | #include <linux/jiffies.h> |
3 | #include <linux/sunrpc/gss_krb5.h> | 33 | #include <linux/sunrpc/gss_krb5.h> |
@@ -128,8 +158,9 @@ static u32 | |||
128 | gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, | 158 | gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, |
129 | struct xdr_buf *buf, struct page **pages) | 159 | struct xdr_buf *buf, struct page **pages) |
130 | { | 160 | { |
131 | char cksumdata[16]; | 161 | char cksumdata[GSS_KRB5_MAX_CKSUM_LEN]; |
132 | struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata}; | 162 | struct xdr_netobj md5cksum = {.len = sizeof(cksumdata), |
163 | .data = cksumdata}; | ||
133 | int blocksize = 0, plainlen; | 164 | int blocksize = 0, plainlen; |
134 | unsigned char *ptr, *msg_start; | 165 | unsigned char *ptr, *msg_start; |
135 | s32 now; | 166 | s32 now; |
@@ -137,7 +168,7 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, | |||
137 | struct page **tmp_pages; | 168 | struct page **tmp_pages; |
138 | u32 seq_send; | 169 | u32 seq_send; |
139 | 170 | ||
140 | dprintk("RPC: gss_wrap_kerberos\n"); | 171 | dprintk("RPC: %s\n", __func__); |
141 | 172 | ||
142 | now = get_seconds(); | 173 | now = get_seconds(); |
143 | 174 | ||
@@ -146,8 +177,9 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, | |||
146 | BUG_ON((buf->len - offset) % blocksize); | 177 | BUG_ON((buf->len - offset) % blocksize); |
147 | plainlen = blocksize + buf->len - offset; | 178 | plainlen = blocksize + buf->len - offset; |
148 | 179 | ||
149 | headlen = g_token_size(&kctx->mech_used, 24 + plainlen) - | 180 | headlen = g_token_size(&kctx->mech_used, |
150 | (buf->len - offset); | 181 | GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength + plainlen) - |
182 | (buf->len - offset); | ||
151 | 183 | ||
152 | ptr = buf->head[0].iov_base + offset; | 184 | ptr = buf->head[0].iov_base + offset; |
153 | /* shift data to make room for header. */ | 185 | /* shift data to make room for header. */ |
@@ -157,25 +189,26 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, | |||
157 | BUG_ON((buf->len - offset - headlen) % blocksize); | 189 | BUG_ON((buf->len - offset - headlen) % blocksize); |
158 | 190 | ||
159 | g_make_token_header(&kctx->mech_used, | 191 | g_make_token_header(&kctx->mech_used, |
160 | GSS_KRB5_TOK_HDR_LEN + 8 + plainlen, &ptr); | 192 | GSS_KRB5_TOK_HDR_LEN + |
193 | kctx->gk5e->cksumlength + plainlen, &ptr); | ||
161 | 194 | ||
162 | 195 | ||
163 | /* ptr now at header described in rfc 1964, section 1.2.1: */ | 196 | /* ptr now at header described in rfc 1964, section 1.2.1: */ |
164 | ptr[0] = (unsigned char) ((KG_TOK_WRAP_MSG >> 8) & 0xff); | 197 | ptr[0] = (unsigned char) ((KG_TOK_WRAP_MSG >> 8) & 0xff); |
165 | ptr[1] = (unsigned char) (KG_TOK_WRAP_MSG & 0xff); | 198 | ptr[1] = (unsigned char) (KG_TOK_WRAP_MSG & 0xff); |
166 | 199 | ||
167 | msg_start = ptr + 24; | 200 | msg_start = ptr + GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength; |
168 | 201 | ||
169 | *(__be16 *)(ptr + 2) = htons(SGN_ALG_DES_MAC_MD5); | 202 | *(__be16 *)(ptr + 2) = cpu_to_le16(kctx->gk5e->signalg); |
170 | memset(ptr + 4, 0xff, 4); | 203 | memset(ptr + 4, 0xff, 4); |
171 | *(__be16 *)(ptr + 4) = htons(SEAL_ALG_DES); | 204 | *(__be16 *)(ptr + 4) = cpu_to_le16(kctx->gk5e->sealalg); |
172 | 205 | ||
173 | make_confounder(msg_start, blocksize); | 206 | make_confounder(msg_start, blocksize); |
174 | 207 | ||
175 | /* XXXJBF: UGH!: */ | 208 | /* XXXJBF: UGH!: */ |
176 | tmp_pages = buf->pages; | 209 | tmp_pages = buf->pages; |
177 | buf->pages = pages; | 210 | buf->pages = pages; |
178 | if (make_checksum("md5", ptr, 8, buf, | 211 | if (make_checksum((char *)kctx->gk5e->cksum_name, ptr, 8, buf, |
179 | offset + headlen - blocksize, &md5cksum)) | 212 | offset + headlen - blocksize, &md5cksum)) |
180 | return GSS_S_FAILURE; | 213 | return GSS_S_FAILURE; |
181 | buf->pages = tmp_pages; | 214 | buf->pages = tmp_pages; |
@@ -207,8 +240,9 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) | |||
207 | { | 240 | { |
208 | int signalg; | 241 | int signalg; |
209 | int sealalg; | 242 | int sealalg; |
210 | char cksumdata[16]; | 243 | char cksumdata[GSS_KRB5_MAX_CKSUM_LEN]; |
211 | struct xdr_netobj md5cksum = {.len = 0, .data = cksumdata}; | 244 | struct xdr_netobj md5cksum = {.len = sizeof(cksumdata), |
245 | .data = cksumdata}; | ||
212 | s32 now; | 246 | s32 now; |
213 | int direction; | 247 | int direction; |
214 | s32 seqnum; | 248 | s32 seqnum; |
@@ -217,6 +251,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) | |||
217 | void *data_start, *orig_start; | 251 | void *data_start, *orig_start; |
218 | int data_len; | 252 | int data_len; |
219 | int blocksize; | 253 | int blocksize; |
254 | int crypt_offset; | ||
220 | 255 | ||
221 | dprintk("RPC: gss_unwrap_kerberos\n"); | 256 | dprintk("RPC: gss_unwrap_kerberos\n"); |
222 | 257 | ||
@@ -234,22 +269,27 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf) | |||
234 | /* get the sign and seal algorithms */ | 269 | /* get the sign and seal algorithms */ |
235 | 270 | ||
236 | signalg = ptr[2] + (ptr[3] << 8); | 271 | signalg = ptr[2] + (ptr[3] << 8); |
237 | if (signalg != SGN_ALG_DES_MAC_MD5) | 272 | if (signalg != kctx->gk5e->signalg) |
238 | return GSS_S_DEFECTIVE_TOKEN; | 273 | return GSS_S_DEFECTIVE_TOKEN; |
239 | 274 | ||
240 | sealalg = ptr[4] + (ptr[5] << 8); | 275 | sealalg = ptr[4] + (ptr[5] << 8); |
241 | if (sealalg != SEAL_ALG_DES) | 276 | if (sealalg != kctx->gk5e->sealalg) |
242 | return GSS_S_DEFECTIVE_TOKEN; | 277 | return GSS_S_DEFECTIVE_TOKEN; |
243 | 278 | ||
244 | if ((ptr[6] != 0xff) || (ptr[7] != 0xff)) | 279 | if ((ptr[6] != 0xff) || (ptr[7] != 0xff)) |
245 | return GSS_S_DEFECTIVE_TOKEN; | 280 | return GSS_S_DEFECTIVE_TOKEN; |
246 | 281 | ||
247 | if (gss_decrypt_xdr_buf(kctx->enc, buf, | 282 | /* |
248 | ptr + GSS_KRB5_TOK_HDR_LEN + 8 - (unsigned char *)buf->head[0].iov_base)) | 283 | * Data starts after token header and checksum. ptr points |
284 | * to the beginning of the token header | ||
285 | */ | ||
286 | crypt_offset = ptr + (GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength) - | ||
287 | (unsigned char *)buf->head[0].iov_base; | ||
288 | if (gss_decrypt_xdr_buf(kctx->enc, buf, crypt_offset)) | ||
249 | return GSS_S_DEFECTIVE_TOKEN; | 289 | return GSS_S_DEFECTIVE_TOKEN; |
250 | 290 | ||
251 | if (make_checksum("md5", ptr, 8, buf, | 291 | if (make_checksum((char *)kctx->gk5e->cksum_name, ptr, 8, buf, |
252 | ptr + GSS_KRB5_TOK_HDR_LEN + 8 - (unsigned char *)buf->head[0].iov_base, &md5cksum)) | 292 | crypt_offset, &md5cksum)) |
253 | return GSS_S_FAILURE; | 293 | return GSS_S_FAILURE; |
254 | 294 | ||
255 | if (krb5_encrypt(kctx->seq, NULL, md5cksum.data, | 295 | 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 | * better to copy and encrypt at the same time. */ | 320 | * better to copy and encrypt at the same time. */ |
281 | 321 | ||
282 | blocksize = crypto_blkcipher_blocksize(kctx->enc); | 322 | blocksize = crypto_blkcipher_blocksize(kctx->enc); |
283 | data_start = ptr + GSS_KRB5_TOK_HDR_LEN + 8 + blocksize; | 323 | data_start = ptr + (GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength) + |
324 | blocksize; | ||
284 | orig_start = buf->head[0].iov_base + offset; | 325 | orig_start = buf->head[0].iov_base + offset; |
285 | data_len = (buf->head[0].iov_base + buf->head[0].iov_len) - data_start; | 326 | data_len = (buf->head[0].iov_base + buf->head[0].iov_len) - data_start; |
286 | memmove(orig_start, data_start, data_len); | 327 | memmove(orig_start, data_start, data_len); |