]> git.hungrycats.org Git - linux/commitdiff
RPCSEC_GSS: Miscellaneous cleanups of the krb5 code required
authorTrond Myklebust <trond.myklebust@fys.uio.no>
Sat, 7 Feb 2004 15:34:13 +0000 (16:34 +0100)
committerTrond Myklebust <trond.myklebust@fys.uio.no>
Sat, 7 Feb 2004 15:34:13 +0000 (16:34 +0100)
for the integrity checksumming mode.

include/linux/sunrpc/gss_krb5.h
net/sunrpc/auth_gss/gss_krb5_crypto.c
net/sunrpc/auth_gss/gss_krb5_mech.c
net/sunrpc/auth_gss/gss_krb5_seal.c
net/sunrpc/auth_gss/gss_krb5_unseal.c

index 8db6d1e13a697dbf1c14b43370eebb1d54d8a44e..aac2ad4f7d569ffeadea7ea4ce4c49d6b63cdf2b 100644 (file)
@@ -50,7 +50,6 @@ struct krb5_ctx {
        struct crypto_tfm       *seq;
        s32                     endtime;
        u32                     seq_send;
-       u32                     seq_recv;
        struct xdr_netobj       mech_used;
 };
 
@@ -73,7 +72,7 @@ enum seal_alg {
        SEAL_ALG_DES3KD = 0x0002
 };
 
-#define RSA_MD5_CKSUM_LENGTH 16
+#define KRB5_CKSUM_LENGTH 8
 
 #define CKSUMTYPE_CRC32                        0x0001
 #define CKSUMTYPE_RSA_MD4              0x0002
@@ -100,16 +99,6 @@ enum seal_alg {
 #define KG_EMPTY_CCACHE                          (39756044L)
 #define KG_NO_CTYPES                             (39756045L)
 
-#define KV5M_PRINCIPAL                           (-1760647423L)
-#define KV5M_KEYBLOCK                            (-1760647421L)
-#define KV5M_CHECKSUM                            (-1760647420L)
-#define KV5M_ADDRESS                             (-1760647390L)
-#define KV5M_AUTHENTICATOR                       (-1760647410L)
-#define KV5M_AUTH_CONTEXT                        (-1760647383L)
-#define KV5M_AUTHDATA                            (-1760647414L)
-#define KV5M_GSS_OID                             (-1760647372L)
-#define KV5M_GSS_QUEUE                           (-1760647371L)
-
 /* per Kerberos v5 protocol spec crypto types from the wire. 
  * these get mapped to linux kernel crypto routines.  
  */
@@ -126,14 +115,13 @@ enum seal_alg {
 #define ENCTYPE_UNKNOWN         0x01ff
 
 s32
-krb5_make_checksum(s32 cksumtype,
-                  struct xdr_netobj *input,
+krb5_make_checksum(s32 cksumtype, char *header, char *body, int body_len,
                   struct xdr_netobj *cksum);
 
 u32
 krb5_make_token(struct krb5_ctx *context_handle, int qop_req,
-       struct xdr_netobj * input_message_buffer,
-       struct xdr_netobj * output_message_buffer, int toktype);
+       struct xdr_netobj *input_message_buffer,
+       struct xdr_netobj *output_message_buffer, int toktype);
 
 u32
 krb5_read_token(struct krb5_ctx *context_handle,
index c3a8f548a4821bbc368dfbc12fda743bbd2d7b7c..9894d83ddf6f612bfa265825a295c5c8619d174f 100644 (file)
@@ -122,14 +122,23 @@ out:
        return(ret);
 }
 
+void
+buf_to_sg(struct scatterlist *sg, char *ptr, int len) {
+       sg->page = virt_to_page(ptr);
+       sg->offset = offset_in_page(ptr);
+       sg->length = len;
+}
+
+/* checksum the plaintext data and the first 8 bytes of the krb5 token header,
+ * as specified by the rfc: */
 s32
-krb5_make_checksum(s32 cksumtype, struct xdr_netobj *input,
+krb5_make_checksum(s32 cksumtype, char *header, char *body, int body_len, 
                   struct xdr_netobj *cksum)
 {
-       s32                     ret = -EINVAL;
-       struct scatterlist      sg[1];
-       char                    *cksumname;
-       struct crypto_tfm       *tfm;
+       char                            *cksumname;
+       struct crypto_tfm               *tfm = NULL; /* XXX add to ctx? */
+       struct scatterlist              sg[2];
+       u32                             code = GSS_S_FAILURE;
 
        switch (cksumtype) {
                case CKSUMTYPE_RSA_MD5:
@@ -143,24 +152,17 @@ krb5_make_checksum(s32 cksumtype, struct xdr_netobj *input,
        if (!(tfm = crypto_alloc_tfm(cksumname, 0)))
                goto out;
        cksum->len = crypto_tfm_alg_digestsize(tfm);
+       if ((cksum->data = kmalloc(cksum->len, GFP_KERNEL)) == NULL)
+               goto out;
 
-       if ((cksum->data = kmalloc(cksum->len, GFP_KERNEL)) == NULL) {
-               ret = -ENOMEM;
-               goto out_free_tfm;
-       }
-       sg[0].page = virt_to_page(input->data);
-       sg[0].offset = offset_in_page(input->data);
-       sg[0].length = input->len;
-
+       buf_to_sg(&sg[0], header, 8);
+       buf_to_sg(&sg[1], body, body_len);
        crypto_digest_init(tfm);
-       crypto_digest_update(tfm, sg, 1);
+       crypto_digest_update(tfm, sg, 2);
        crypto_digest_final(tfm, cksum->data);
-
-       ret = 0;
-
-out_free_tfm:
-       crypto_free_tfm(tfm);
+       code = 0;
 out:
-       dprintk("RPC: gss_k5cksum: returning %d\n", ret);
-       return (ret);
+       if (tfm)
+               crypto_free_tfm(tfm);
+       return code;
 }
index ce31a89684e4a98f8c7edceee1a5fd0a97ac0dc0..61282b4d9c3b9faf9a478734b0c5ee4d6f35f21d 100644 (file)
@@ -98,7 +98,7 @@ get_key(char **p, char *end, struct crypto_tfm **res)
                        alg_mode = CRYPTO_TFM_MODE_CBC;
                        break;
                default:
-                       dprintk("RPC: get_key: unsupported algorithm %d", alg);
+                       dprintk("RPC: get_key: unsupported algorithm %d\n", alg);
                        goto out_err_free_key;
        }
        if (!(*res = crypto_alloc_tfm(alg_name, alg_mode)))
@@ -168,7 +168,7 @@ out_err:
        return GSS_S_FAILURE;
 }
 
-void
+static void
 gss_delete_sec_context_kerberos(void *internal_ctx) {
        struct krb5_ctx *kctx = internal_ctx;
 
@@ -181,16 +181,16 @@ gss_delete_sec_context_kerberos(void *internal_ctx) {
        kfree(kctx);
 }
 
-u32
+static u32
 gss_verify_mic_kerberos(struct gss_ctx         *ctx,
-                       struct xdr_netobj       *signbuf,
-                       struct xdr_netobj       *checksum,
-                       u32             *qstate) {
+                       struct xdr_netobj       *message,
+                       struct xdr_netobj       *mic_token,
+                       u32                     *qstate) {
        u32 maj_stat = 0;
        int qop_state;
        struct krb5_ctx *kctx = ctx->internal_ctx_id;
 
-       maj_stat = krb5_read_token(kctx, checksum, signbuf, &qop_state,
+       maj_stat = krb5_read_token(kctx, mic_token, message, &qop_state,
                                   KG_TOK_MIC_MSG);
        if (!maj_stat && qop_state)
            *qstate = qop_state;
@@ -199,21 +199,17 @@ gss_verify_mic_kerberos(struct gss_ctx            *ctx,
        return maj_stat;
 }
 
-u32
+static u32
 gss_get_mic_kerberos(struct gss_ctx    *ctx,
                     u32                qop,
-                    struct xdr_netobj  *message_buffer,
-                    struct xdr_netobj  *message_token) {
+                    struct xdr_netobj  *message,
+                    struct xdr_netobj  *mic_token) {
        u32 err = 0;
        struct krb5_ctx *kctx = ctx->internal_ctx_id;
 
-       if (!message_buffer->data) return GSS_S_FAILURE;
-
-       dprintk("RPC: gss_get_mic_kerberos:"
-               " message_buffer->len %d\n",message_buffer->len);
+       if (!message->data) return GSS_S_FAILURE;
 
-       err = krb5_make_token(kctx, qop, message_buffer,
-                             message_token, KG_TOK_MIC_MSG);
+       err = krb5_make_token(kctx, qop, message, mic_token, KG_TOK_MIC_MSG);
 
        dprintk("RPC: gss_get_mic_kerberos returning %d\n",err);
 
index 280d82d7c6dc19ca9249d093190140b07c463562..e664d3ea98ce53a6ed5f0f45714ccc463d7becdd 100644 (file)
 #include <linux/jiffies.h>
 #include <linux/sunrpc/gss_krb5.h>
 #include <linux/random.h>
+#include <asm/scatterlist.h>
 #include <linux/crypto.h>
 
 #ifdef RPC_DEBUG
 # define RPCDBG_FACILITY        RPCDBG_AUTH
 #endif
 
-#define CKSUM_SIZE     8
-
 static inline int
 gss_krb5_padding(int blocksize, int length) {
        /* Most of the code is block-size independent but in practice we
@@ -79,29 +78,6 @@ gss_krb5_padding(int blocksize, int length) {
        return 8 - (length & 7);
 }
 
-/* checksum the plaintext data and the first 8 bytes of the krb5 token header,
- * as specified by the rfc: */
-static u32
-compute_checksum(s32 checksum_type, char *header, char *body, int body_len,
-                struct xdr_netobj *md5cksum) {
-       char                    *data_ptr;
-       struct xdr_netobj       plaind;
-       u32                     code = GSS_S_FAILURE;
-
-       if (!(data_ptr = kmalloc(8 + body_len, GFP_KERNEL)))
-               goto out;
-       memcpy(data_ptr, header, 8);
-       memcpy(data_ptr + 8, body, body_len);
-       plaind.len = 8 + body_len;
-       plaind.data = data_ptr;
-       code = krb5_make_checksum(checksum_type, &plaind, md5cksum);
-       kfree(data_ptr);
-       code = 0;
-
-out:
-       return code;
-}
-
 u32
 krb5_make_token(struct krb5_ctx *ctx, int qop_req,
                   struct xdr_netobj * text, struct xdr_netobj * token,
@@ -113,10 +89,12 @@ krb5_make_token(struct krb5_ctx *ctx, int qop_req,
        unsigned char           *ptr, *krb5_hdr, *msg_start;
        s32                     now;
 
-       dprintk("RPC: gss_krb5_seal");
+       dprintk("RPC:     gss_krb5_seal\n");
 
        now = jiffies;
 
+       token->data = NULL;
+
        if (qop_req != 0)
                goto out_err;
 
@@ -167,8 +145,8 @@ krb5_make_token(struct krb5_ctx *ctx, int qop_req,
 
                memset(msg_start + blocksize + text->len, pad, pad);
 
-               if (compute_checksum(checksum_type, krb5_hdr, msg_start,
-                                    tmsglen, &md5cksum))
+               if (krb5_make_checksum(checksum_type, krb5_hdr, msg_start,
+                                      tmsglen, &md5cksum))
                        goto out_err;
 
                if (krb5_encrypt(ctx->enc, NULL, msg_start, msg_start,
@@ -176,8 +154,8 @@ krb5_make_token(struct krb5_ctx *ctx, int qop_req,
                        goto out_err;
 
        } else { /* Sign only.  */
-               if (compute_checksum(checksum_type, krb5_hdr, text->data,
-                                       text->len, &md5cksum))
+               if (krb5_make_checksum(checksum_type, krb5_hdr, text->data,
+                                      text->len, &md5cksum))
                        goto out_err;
        }
 
@@ -187,10 +165,11 @@ krb5_make_token(struct krb5_ctx *ctx, int qop_req,
                                  md5cksum.data, md5cksum.len))
                        goto out_err;
                memcpy(krb5_hdr + 16,
-                      md5cksum.data + md5cksum.len - CKSUM_SIZE, CKSUM_SIZE);
+                      md5cksum.data + md5cksum.len - KRB5_CKSUM_LENGTH,
+                      KRB5_CKSUM_LENGTH);
 
                dprintk("make_seal_token: cksum data: \n");
-               print_hexl((u32 *) (krb5_hdr + 16), CKSUM_SIZE, 0);
+               print_hexl((u32 *) (krb5_hdr + 16), KRB5_CKSUM_LENGTH, 0);
                break;
        default:
                BUG();
index 836c683777f28b5b5c8f7d10ec19287db3d701f3..8b2795d701db112015dfbfd71a0edc627b640ff7 100644 (file)
 #endif
 
 
-/* message_buffer is an input if MIC and an output if WRAP. */
+/* message_buffer is an input if toktype is MIC and an output if it is WRAP:
+ * If toktype is MIC: read_token is a mic token, and message_buffer is the
+ *   data that the mic was supposedly taken over.
+ * If toktype is WRAP: read_token is a wrap token, and message_buffer is used
+ *   to return the decrypted data.
+ */
 
 u32
 krb5_read_token(struct krb5_ctx *ctx,
@@ -76,20 +81,13 @@ krb5_read_token(struct krb5_ctx *ctx,
                struct xdr_netobj *message_buffer,
                int *qop_state, int toktype)
 {
-       s32                     code;
-       int                     tmsglen = 0;
-       int                     conflen = 0;
        int                     signalg;
        int                     sealalg;
        struct xdr_netobj       token = {.len = 0, .data = NULL};
        s32                     checksum_type;
-       struct xdr_netobj       cksum;
        struct xdr_netobj       md5cksum = {.len = 0, .data = NULL};
-       struct xdr_netobj       plaind;
-       char                    *data_ptr;
        s32                     now;
        unsigned char           *plain = NULL;
-       int                     cksum_len = 0;
        int                     plainlen = 0;
        int                     direction;
        s32                     seqnum;
@@ -97,10 +95,9 @@ krb5_read_token(struct krb5_ctx *ctx,
        int                     bodysize;
        u32                     ret = GSS_S_DEFECTIVE_TOKEN;
 
-       dprintk("RPC: krb5_read_token\n");
+       dprintk("RPC:      krb5_read_token\n");
 
-       if (g_verify_token_header((struct xdr_netobj *) &ctx->mech_used,
-                                       &bodysize, &ptr, toktype,
+       if (g_verify_token_header(&ctx->mech_used, &bodysize, &ptr, toktype,
                                        read_token->len))
                goto out;
 
@@ -138,40 +135,22 @@ krb5_read_token(struct krb5_ctx *ctx,
             signalg != SGN_ALG_HMAC_SHA1_DES3_KD))
                goto out;
 
-       /* starting with a single alg */
-       switch (signalg) {
-       case SGN_ALG_DES_MAC_MD5:
-               cksum_len = 8;
-               break;
-       default:
-               goto out;
-       }
-
-       if (toktype == KG_TOK_WRAP_MSG)
-               tmsglen = bodysize - (14 + cksum_len);
-
-       /* get the token parameters */
-
-       /* decode the message, if WRAP */
-
        if (toktype == KG_TOK_WRAP_MSG) {
-               dprintk("RPC: krb5_read_token KG_TOK_WRAP_MSG\n");
+               int conflen = crypto_tfm_alg_blocksize(ctx->enc);
+               int padlen;
 
-               plain = kmalloc(tmsglen, GFP_KERNEL);
-               ret = GSS_S_FAILURE;
-               if (plain ==  NULL)
-                       goto out;
+               plainlen = bodysize - (14 + KRB5_CKSUM_LENGTH);
+               plain = ptr + 14 + KRB5_CKSUM_LENGTH;
 
-               code = krb5_decrypt(ctx->enc, NULL,
-                                  ptr + 14 + cksum_len, plain,
-                                  tmsglen);
-               if (code)
+               ret = krb5_decrypt(ctx->enc, NULL, plain, plain, plainlen);
+               if (ret)
                        goto out;
 
-               plainlen = tmsglen;
-
-               conflen = crypto_tfm_alg_blocksize(ctx->enc);
-               token.len = tmsglen - conflen - plain[tmsglen - 1];
+               ret = GSS_S_FAILURE;
+               padlen = plain[plainlen -1];
+               if ((padlen < 1) || (padlen > 8))
+                       goto out;
+               token.len = plainlen - conflen - padlen;
 
                if (token.len) {
                        token.data = kmalloc(token.len, GFP_KERNEL);
@@ -181,15 +160,13 @@ krb5_read_token(struct krb5_ctx *ctx,
                }
 
        } else if (toktype == KG_TOK_MIC_MSG) {
-               dprintk("RPC: krb5_read_token KG_TOK_MIC_MSG\n");
                token = *message_buffer;
                plain = token.data;
                plainlen = token.len;
        } else {
-               token.len = 0;
-               token.data = NULL;
-               plain = token.data;
-               plainlen = token.len;
+               printk("RPC: bad toktype in krb5_read_token");
+               ret = GSS_S_FAILURE;
+               goto out;
        }
 
        dprintk("RPC krb5_read_token: token.len %d plainlen %d\n", token.len,
@@ -209,67 +186,26 @@ krb5_read_token(struct krb5_ctx *ctx,
 
        switch (signalg) {
        case SGN_ALG_DES_MAC_MD5:
-               dprintk("RPC krb5_read_token SGN_ALG_DES_MAC_MD5\n");
-               /* compute the checksum of the message.
-                * 8 = bytes of token body to be checksummed according to spec 
-                */
-
-               data_ptr = kmalloc(8 + plainlen, GFP_KERNEL);
-               ret = GSS_S_FAILURE;
-               if (!data_ptr)
+               ret = krb5_make_checksum(checksum_type, ptr - 2, plain,
+                                        plainlen, &md5cksum);
+               if (ret)
                        goto out;
 
-               memcpy(data_ptr, ptr - 2, 8);
-               memcpy(data_ptr + 8, plain, plainlen);
-
-               plaind.len = 8 + plainlen;
-               plaind.data = data_ptr;
-
-               code = krb5_make_checksum(checksum_type,
-                                           &plaind, &md5cksum);
-
-               kfree(data_ptr);
-
-               if (code)
+               ret = krb5_encrypt(ctx->seq, NULL, md5cksum.data,
+                                  md5cksum.data, 16);
+               if (ret)
                        goto out;
 
-               code = krb5_encrypt(ctx->seq, NULL, md5cksum.data,
-                                         md5cksum.data, 16);
-               if (code)
+               if (memcmp(md5cksum.data + 8, ptr + 14, 8)) {
+                       ret = GSS_S_BAD_SIG;
                        goto out;
-
-               if (signalg == 0)
-                       cksum.len = 8;
-               else
-                       cksum.len = 16;
-               cksum.data = md5cksum.data + 16 - cksum.len;
-
-               dprintk
-                   ("RPC: krb5_read_token: memcmp digest cksum.len %d:\n",
-                    cksum.len);
-               dprintk("          md5cksum.data\n");
-               print_hexl((u32 *) md5cksum.data, 16, 0);
-               dprintk("          cksum.data:\n");
-               print_hexl((u32 *) cksum.data, cksum.len, 0);
-               {
-                       u32 *p;
-
-                       (u8 *) p = ptr + 14;
-                       dprintk("          ptr+14:\n");
-                       print_hexl(p, cksum.len, 0);
                }
-
-               code = memcmp(cksum.data, ptr + 14, cksum.len);
                break;
        default:
                ret = GSS_S_DEFECTIVE_TOKEN;
                goto out;
        }
 
-       ret = GSS_S_BAD_SIG;
-       if (code)
-               goto out;
-
        /* it got through unscathed.  Make sure the context is unexpired */
 
        if (toktype == KG_TOK_WRAP_MSG)
@@ -287,8 +223,8 @@ krb5_read_token(struct krb5_ctx *ctx,
        /* do sequencing checks */
 
        ret = GSS_S_BAD_SIG;
-       if ((code = krb5_get_seq_num(ctx->seq, ptr + 14, ptr + 6, &direction,
-                                  &seqnum)))
+       if ((ret = krb5_get_seq_num(ctx->seq, ptr + 14, ptr + 6, &direction,
+                                   &seqnum)))
                goto out;
 
        if ((ctx->initiate && direction != 0xff) ||
@@ -298,9 +234,7 @@ krb5_read_token(struct krb5_ctx *ctx,
        ret = GSS_S_COMPLETE;
 out:
        if (md5cksum.data) kfree(md5cksum.data);
-       if (toktype == KG_TOK_WRAP_MSG) {
-               if (plain) kfree(plain);
-               if (ret && token.data) kfree(token.data);
-       }
+       if ((toktype == KG_TOK_WRAP_MSG) && ret && token.data)
+               kfree(token.data);
        return ret;
 }