diff options
author | Kevin Coffman <kwc@citi.umich.edu> | 2010-03-17 13:02:46 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-05-14 15:09:15 -0400 |
commit | 725f2865d4df31ac0768b13ae763beadc4bb8ce9 (patch) | |
tree | 20b2da47713e7f38a61d37cbb2c95ad52c88609f | |
parent | 4fc4c3ce0dc1096cbd0daa3fe8f6905cbec2b87e (diff) |
gss_krb5: Introduce encryption type framework
Make the client and server code consistent regarding the extra buffer
space made available for the auth code when wrapping data.
Add some comments/documentation about the available buffer space
in the xdr_buf head and tail when gss_wrap is called.
Add a compile-time check to make sure we are not exceeding the available
buffer space.
Add a central function to shift head data.
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>
-rw-r--r-- | include/linux/sunrpc/gss_krb5.h | 25 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 2 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_crypto.c | 38 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/gss_krb5_wrap.c | 6 |
4 files changed, 66 insertions, 5 deletions
diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index e7bbdba474d5..31bb8a538bf1 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h | |||
@@ -40,6 +40,12 @@ | |||
40 | #include <linux/sunrpc/gss_err.h> | 40 | #include <linux/sunrpc/gss_err.h> |
41 | #include <linux/sunrpc/gss_asn1.h> | 41 | #include <linux/sunrpc/gss_asn1.h> |
42 | 42 | ||
43 | /* Maximum checksum function output for the supported crypto algorithms */ | ||
44 | #define GSS_KRB5_MAX_CKSUM_LEN (20) | ||
45 | |||
46 | /* Maximum blocksize for the supported crypto algorithms */ | ||
47 | #define GSS_KRB5_MAX_BLOCKSIZE (16) | ||
48 | |||
43 | struct krb5_ctx { | 49 | struct krb5_ctx { |
44 | int initiate; /* 1 = initiating, 0 = accepting */ | 50 | int initiate; /* 1 = initiating, 0 = accepting */ |
45 | struct crypto_blkcipher *enc; | 51 | struct crypto_blkcipher *enc; |
@@ -113,6 +119,22 @@ enum seal_alg { | |||
113 | #define ENCTYPE_DES3_CBC_SHA1 0x0010 | 119 | #define ENCTYPE_DES3_CBC_SHA1 0x0010 |
114 | #define ENCTYPE_UNKNOWN 0x01ff | 120 | #define ENCTYPE_UNKNOWN 0x01ff |
115 | 121 | ||
122 | /* | ||
123 | * This compile-time check verifies that we will not exceed the | ||
124 | * slack space allotted by the client and server auth_gss code | ||
125 | * before they call gss_wrap(). | ||
126 | */ | ||
127 | #define GSS_KRB5_MAX_SLACK_NEEDED \ | ||
128 | (GSS_KRB5_TOK_HDR_LEN /* gss token header */ \ | ||
129 | + GSS_KRB5_MAX_CKSUM_LEN /* gss token checksum */ \ | ||
130 | + GSS_KRB5_MAX_BLOCKSIZE /* confounder */ \ | ||
131 | + GSS_KRB5_MAX_BLOCKSIZE /* possible padding */ \ | ||
132 | + GSS_KRB5_TOK_HDR_LEN /* encrypted hdr in v2 token */\ | ||
133 | + GSS_KRB5_MAX_CKSUM_LEN /* encryption hmac */ \ | ||
134 | + 4 + 4 /* RPC verifier */ \ | ||
135 | + GSS_KRB5_TOK_HDR_LEN \ | ||
136 | + GSS_KRB5_MAX_CKSUM_LEN) | ||
137 | |||
116 | s32 | 138 | s32 |
117 | make_checksum(char *, char *header, int hdrlen, struct xdr_buf *body, | 139 | make_checksum(char *, char *header, int hdrlen, struct xdr_buf *body, |
118 | int body_offset, struct xdr_netobj *cksum); | 140 | int body_offset, struct xdr_netobj *cksum); |
@@ -157,3 +179,6 @@ s32 | |||
157 | krb5_get_seq_num(struct crypto_blkcipher *key, | 179 | krb5_get_seq_num(struct crypto_blkcipher *key, |
158 | unsigned char *cksum, | 180 | unsigned char *cksum, |
159 | unsigned char *buf, int *direction, u32 *seqnum); | 181 | unsigned char *buf, int *direction, u32 *seqnum); |
182 | |||
183 | int | ||
184 | xdr_extend_head(struct xdr_buf *buf, unsigned int base, unsigned int shiftlen); | ||
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index c389ccf6437d..75602ece58eb 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -61,7 +61,7 @@ static const struct rpc_credops gss_nullops; | |||
61 | # define RPCDBG_FACILITY RPCDBG_AUTH | 61 | # define RPCDBG_FACILITY RPCDBG_AUTH |
62 | #endif | 62 | #endif |
63 | 63 | ||
64 | #define GSS_CRED_SLACK 1024 | 64 | #define GSS_CRED_SLACK (RPC_MAX_AUTH_SIZE * 2) |
65 | /* length of a krb5 verifier (48), plus data added before arguments when | 65 | /* length of a krb5 verifier (48), plus data added before arguments when |
66 | * using integrity (two 4-byte integers): */ | 66 | * using integrity (two 4-byte integers): */ |
67 | #define GSS_VERF_SLACK 100 | 67 | #define GSS_VERF_SLACK 100 |
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index e9b636176687..746b3e139aed 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c | |||
@@ -325,3 +325,41 @@ gss_decrypt_xdr_buf(struct crypto_blkcipher *tfm, struct xdr_buf *buf, | |||
325 | 325 | ||
326 | return xdr_process_buf(buf, offset, buf->len - offset, decryptor, &desc); | 326 | return xdr_process_buf(buf, offset, buf->len - offset, decryptor, &desc); |
327 | } | 327 | } |
328 | |||
329 | /* | ||
330 | * This function makes the assumption that it was ultimately called | ||
331 | * from gss_wrap(). | ||
332 | * | ||
333 | * The client auth_gss code moves any existing tail data into a | ||
334 | * separate page before calling gss_wrap. | ||
335 | * The server svcauth_gss code ensures that both the head and the | ||
336 | * tail have slack space of RPC_MAX_AUTH_SIZE before calling gss_wrap. | ||
337 | * | ||
338 | * Even with that guarantee, this function may be called more than | ||
339 | * once in the processing of gss_wrap(). The best we can do is | ||
340 | * verify at compile-time (see GSS_KRB5_SLACK_CHECK) that the | ||
341 | * largest expected shift will fit within RPC_MAX_AUTH_SIZE. | ||
342 | * At run-time we can verify that a single invocation of this | ||
343 | * function doesn't attempt to use more the RPC_MAX_AUTH_SIZE. | ||
344 | */ | ||
345 | |||
346 | int | ||
347 | xdr_extend_head(struct xdr_buf *buf, unsigned int base, unsigned int shiftlen) | ||
348 | { | ||
349 | u8 *p; | ||
350 | |||
351 | if (shiftlen == 0) | ||
352 | return 0; | ||
353 | |||
354 | BUILD_BUG_ON(GSS_KRB5_MAX_SLACK_NEEDED > RPC_MAX_AUTH_SIZE); | ||
355 | BUG_ON(shiftlen > RPC_MAX_AUTH_SIZE); | ||
356 | |||
357 | p = buf->head[0].iov_base + base; | ||
358 | |||
359 | memmove(p + shiftlen, p, buf->head[0].iov_len - base); | ||
360 | |||
361 | buf->head[0].iov_len += shiftlen; | ||
362 | buf->len += shiftlen; | ||
363 | |||
364 | return 0; | ||
365 | } | ||
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index a6e905637e03..496281fabb91 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c | |||
@@ -155,11 +155,9 @@ gss_wrap_kerberos(struct gss_ctx *ctx, int offset, | |||
155 | 155 | ||
156 | ptr = buf->head[0].iov_base + offset; | 156 | ptr = buf->head[0].iov_base + offset; |
157 | /* shift data to make room for header. */ | 157 | /* shift data to make room for header. */ |
158 | xdr_extend_head(buf, offset, headlen); | ||
159 | |||
158 | /* XXX Would be cleverer to encrypt while copying. */ | 160 | /* XXX Would be cleverer to encrypt while copying. */ |
159 | /* XXX bounds checking, slack, etc. */ | ||
160 | memmove(ptr + headlen, ptr, buf->head[0].iov_len - offset); | ||
161 | buf->head[0].iov_len += headlen; | ||
162 | buf->len += headlen; | ||
163 | BUG_ON((buf->len - offset - headlen) % blocksize); | 161 | BUG_ON((buf->len - offset - headlen) % blocksize); |
164 | 162 | ||
165 | g_make_token_header(&kctx->mech_used, | 163 | g_make_token_header(&kctx->mech_used, |