diff -u -r -N linux-2.5.47-07-auth_upcall2/fs/Kconfig linux-2.5.47-08-krb5/fs/Kconfig --- linux-2.5.47-07-auth_upcall2/fs/Kconfig 2002-11-13 13:11:59.000000000 -0500 +++ linux-2.5.47-08-krb5/fs/Kconfig 2002-11-13 13:32:19.000000000 -0500 @@ -1342,8 +1342,15 @@ depends on SUNRPC && EXPERIMENTAL help Provides cryptographic authentication for NFS rpc requests. To - make this useful, you also need support for a gss-api mechanism - (such as Kerberos). + make this useful, you must also select an rpcsec_gss mechanism + below. + +config RPCSEC_GSS_KRB5 + tristate "Kerberos mechanism for RPCSEC_GSS (EXPERIMENTAL)" + depends on SUNRPC_GSS + help + Provides a gss-api mechanism based on Kerberos 5. Requires a + userspace daemon; see http://www.citi.umich.edu/projects/nfsv4/. config LOCKD tristate diff -u -r -N linux-2.5.47-07-auth_upcall2/include/linux/sunrpc/gss_krb5_types.h linux-2.5.47-08-krb5/include/linux/sunrpc/gss_krb5_types.h --- linux-2.5.47-07-auth_upcall2/include/linux/sunrpc/gss_krb5_types.h 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.5.47-08-krb5/include/linux/sunrpc/gss_krb5_types.h 2002-11-15 18:23:15.000000000 -0500 @@ -0,0 +1,166 @@ +/* + * linux/include/linux/sunrpc/gss_krb5_types.h + * + * krb5 types mapped to linux kernel types + * + * Adapted from MIT Kerberos 5-1.2.1 lib/include/krb5.h, + * lib/gssapi/krb5/gssapiP_krb5.h, and others + * + * Copyright (c) 2000 The Regents of the University of Michigan. + * All rights reserved. + * + * Andy Adamson + */ + +/* + * Copyright 1995 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + */ + +#include +#include +#include + +/* the krb5 gss context that is stored in userland */ +typedef struct _krb5_gss_ctx_id_rec { + int initiate; /* 1 = initiating, 0 = accepting */ + int seed_init; + unsigned char seed[16]; + int signalg; + int cksum_size; + int sealalg; + struct crypto_tfm *enc; + struct crypto_tfm *seq; + s32 endtime; + u32 seq_send; + u32 seq_recv; + int big_endian; + struct xdr_netobj mech_used; +} krb5_gss_ctx_id_rec, *krb5_gss_ctx_id_t; + +#define KG_TOK_MIC_MSG 0x0101 +#define KG_TOK_WRAP_MSG 0x0201 + +enum sgn_alg { + SGN_ALG_DES_MAC_MD5 = 0x0000, + SGN_ALG_MD2_5 = 0x0001, + SGN_ALG_DES_MAC = 0x0002, + SGN_ALG_3 = 0x0003, /* not published */ + SGN_ALG_HMAC_MD5 = 0x0011, /* microsoft w2k; no support */ + SGN_ALG_HMAC_SHA1_DES3_KD = 0x0004 +}; +enum seal_alg { + SEAL_ALG_NONE = 0xffff, + SEAL_ALG_DES = 0x0000, + SEAL_ALG_1 = 0x0001, /* not published */ + SEAL_ALG_MICROSOFT_RC4 = 0x0010,/* microsoft w2k; no support */ + SEAL_ALG_DES3KD = 0x0002 +}; + +#define RSA_MD5_CKSUM_LENGTH 16 + +#define CKSUMTYPE_CRC32 0x0001 +#define CKSUMTYPE_RSA_MD4 0x0002 +#define CKSUMTYPE_RSA_MD4_DES 0x0003 +#define CKSUMTYPE_DESCBC 0x0004 +#define CKSUMTYPE_RSA_MD5 0x0007 +#define CKSUMTYPE_RSA_MD5_DES 0x0008 +#define CKSUMTYPE_NIST_SHA 0x0009 +#define CKSUMTYPE_HMAC_SHA1_DES3 0x000c + +/* from gssapi_err_krb5.h */ +#define KG_CCACHE_NOMATCH (39756032L) +#define KG_KEYTAB_NOMATCH (39756033L) +#define KG_TGT_MISSING (39756034L) +#define KG_NO_SUBKEY (39756035L) +#define KG_CONTEXT_ESTABLISHED (39756036L) +#define KG_BAD_SIGN_TYPE (39756037L) +#define KG_BAD_LENGTH (39756038L) +#define KG_CTX_INCOMPLETE (39756039L) +#define KG_CONTEXT (39756040L) +#define KG_CRED (39756041L) +#define KG_ENC_DESC (39756042L) +#define KG_BAD_SEQ (39756043L) +#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. + */ +#define ENCTYPE_NULL 0x0000 +#define ENCTYPE_DES_CBC_CRC 0x0001 /* DES cbc mode with CRC-32 */ +#define ENCTYPE_DES_CBC_MD4 0x0002 /* DES cbc mode with RSA-MD4 */ +#define ENCTYPE_DES_CBC_MD5 0x0003 /* DES cbc mode with RSA-MD5 */ +#define ENCTYPE_DES_CBC_RAW 0x0004 /* DES cbc mode raw */ +/* XXX deprecated? */ +#define ENCTYPE_DES3_CBC_SHA 0x0005 /* DES-3 cbc mode with NIST-SHA */ +#define ENCTYPE_DES3_CBC_RAW 0x0006 /* DES-3 cbc mode raw */ +#define ENCTYPE_DES_HMAC_SHA1 0x0008 +#define ENCTYPE_DES3_CBC_SHA1 0x0010 +#define ENCTYPE_UNKNOWN 0x01ff + +s32 +krb5_make_checksum(s32 cksumtype, + struct xdr_netobj *input, + struct xdr_netobj *cksum); + +u32 +kg_seal(GSS_CTX_ID_T context_handle, + int qop_req, + struct xdr_netobj * input_message_buffer, + int *conf_state, + struct xdr_netobj * output_message_buffer, int toktype); + +u32 +kg_unseal(GSS_CTX_ID_T context_handle, + struct xdr_netobj * input_token_buffer, + struct xdr_netobj * message_buffer, + int *conf_state, int *qop_state, int toktype); + +u32 +gss_k5encrypt(struct crypto_tfm * key, + void *iv, void *in, void *out, int length); + +u32 +gss_k5decrypt(struct crypto_tfm * key, + void *iv, void *in, void *out, int length); + +s32 +kg_make_seq_num(struct crypto_tfm * key, + int direction, + s32 seqnum, unsigned char *cksum, unsigned char *buf); + +s32 +kg_get_seq_num(struct crypto_tfm * key, + unsigned char *cksum, + unsigned char *buf, int *direction, s32 * seqnum); diff -u -r -N linux-2.5.47-07-auth_upcall2/net/sunrpc/Makefile linux-2.5.47-08-krb5/net/sunrpc/Makefile --- linux-2.5.47-07-auth_upcall2/net/sunrpc/Makefile 2002-11-13 13:12:02.000000000 -0500 +++ linux-2.5.47-08-krb5/net/sunrpc/Makefile 2002-11-15 16:04:44.000000000 -0500 @@ -17,6 +17,11 @@ obj-$(CONFIG_SUNRPC_GSS) += auth_rpcgss.o auth_rpcgss-objs := auth_gss.o gss_pseudoflavors.o gss_generic_token.o \ - sunrpcgss_syms.o gss_mech_switch.o + sunrpcgss_syms.o gss_mech_switch.o + +rpcsec_gss_krb5-objs := gss_krb5_mech.o gss_krb5_seal.o gss_krb5_unseal.o \ + gss_krb5_crypto.o gss_krb5_seqnum.o + +obj-$(CONFIG_RPCSEC_GSS_KRB5) += rpcsec_gss_krb5.o include $(TOPDIR)/Rules.make diff -u -r -N linux-2.5.47-07-auth_upcall2/net/sunrpc/gss_krb5_crypto.c linux-2.5.47-08-krb5/net/sunrpc/gss_krb5_crypto.c --- linux-2.5.47-07-auth_upcall2/net/sunrpc/gss_krb5_crypto.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.5.47-08-krb5/net/sunrpc/gss_krb5_crypto.c 2002-11-15 17:30:29.000000000 -0500 @@ -0,0 +1,168 @@ +/* + * linux/net/sunrpc/gss_krb5_crypto.c + * + * Copyright (c) 2000 The Regents of the University of Michigan. + * All rights reserved. + * + * Andy Adamson + * Bruce Fields + */ + +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include +#include +#include +#include +#include +#include + +#ifdef RPC_DEBUG +# define RPCDBG_FACILITY RPCDBG_AUTH +#endif + +u32 +gss_k5encrypt( + struct crypto_tfm *tfm, + void * iv, + void * in, + void * out, + int length) +{ + u32 ret = -EINVAL; + struct scatterlist sg[1]; + u8 local_iv[16] = {0}; + + dprintk("RPC: gss_k5encrypt: TOP in %p out %p\nin data:\n", out, in); + print_hexl((u32 *)in, length, 0); + + if (length % crypto_tfm_alg_blocksize(tfm) != 0) + goto out; + + if (crypto_tfm_alg_ivsize(tfm) > 16) { + dprintk("RPC: gss_k5encrypt: tfm iv size to large %d\n", + crypto_tfm_alg_ivsize(tfm)); + goto out; + } + + if (iv) + memcpy(local_iv, iv, crypto_tfm_alg_ivsize(tfm)); + crypto_cipher_set_iv(tfm, local_iv, crypto_tfm_alg_ivsize(tfm)); + + memcpy(out, in, length); + sg[0].page = virt_to_page(out); + sg[0].offset = ((long)out & ~PAGE_MASK); + sg[0].length = length; + + ret = crypto_cipher_encrypt(tfm, sg, 1); + +out: + dprintk("gss_k5encrypt returns %d\n",ret); + return(ret); +} + +u32 +gss_k5decrypt( + struct crypto_tfm *tfm, + void * iv, + void * in, + void * out, + int length) +{ + u32 ret = -EINVAL; + struct scatterlist sg[1]; + u8 local_iv[16] = {0}; + + dprintk("RPC: gss_k5decrypt: TOP in %p out %p\nin data:\n", in, out); + print_hexl((u32 *)in,length,0); + + if (length % crypto_tfm_alg_blocksize(tfm) != 0) + goto out; + + if (crypto_tfm_alg_ivsize(tfm) > 16) { + dprintk("RPC: gss_k5decrypt: tfm iv size to large %d\n", + crypto_tfm_alg_ivsize(tfm)); + goto out; + } + if (iv) + memcpy(local_iv,iv, crypto_tfm_alg_ivsize(tfm)); + crypto_cipher_set_iv(tfm, local_iv, crypto_tfm_alg_blocksize(tfm)); + + memcpy(out, in, length); + sg[0].page = virt_to_page(out); + sg[0].offset = ((long)out & ~PAGE_MASK); + sg[0].length = length; + + ret = crypto_cipher_decrypt(tfm, sg, 1); + +out: + dprintk("gss_k5decrypt returns %d\n",ret); + return(ret); +} + +s32 +krb5_make_checksum(s32 cksumtype, struct xdr_netobj *input, + struct xdr_netobj *cksum) +{ + s32 ret = -EINVAL; + struct scatterlist sg[1]; + char *cksumname; + struct crypto_tfm *tfm; + + switch (cksumtype) { + case CKSUMTYPE_RSA_MD5: + cksumname = "md5"; + break; + default: + dprintk("RPC: krb5_make_checksum:" + " unsupported checksum %d", cksumtype); + goto out; + } + 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) { + ret = -ENOMEM; + goto out_free_tfm; + } + sg[0].page = virt_to_page(input->data); + sg[0].offset = ((long)input->data & ~PAGE_MASK); + sg[0].length = input->len; + + crypto_digest_init(tfm); + crypto_digest_update(tfm, sg, 1); + crypto_digest_final(tfm, cksum->data); + + ret = 0; + +out_free_tfm: + crypto_free_tfm(tfm); +out: + dprintk("RPC: gss_k5cksum: returning %d\n", ret); + return (ret); +} diff -u -r -N linux-2.5.47-07-auth_upcall2/net/sunrpc/gss_krb5_mech.c linux-2.5.47-08-krb5/net/sunrpc/gss_krb5_mech.c --- linux-2.5.47-07-auth_upcall2/net/sunrpc/gss_krb5_mech.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.5.47-08-krb5/net/sunrpc/gss_krb5_mech.c 2002-11-15 18:24:15.000000000 -0500 @@ -0,0 +1,282 @@ +/* + * linux/net/sunrpc/gss_krb5_mech.c + * + * Copyright (c) 2001 The Regents of the University of Michigan. + * All rights reserved. + * + * Andy Adamson + * J. Bruce Fields + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef RPC_DEBUG +# define RPCDBG_FACILITY RPCDBG_AUTH +#endif + +struct xdr_netobj gss_mech_krb5_oid = + {9, "\052\206\110\206\367\022\001\002\002"}; + +void +print_krb5_gss_ctx_id_rec(krb5_gss_ctx_id_t k5_ctx) +{ + dprintk("some of krb5_gss_ctx_id_rec: \n"); + if (!k5_ctx) return; + dprintk(" initiate: %d\n",k5_ctx->initiate); + dprintk(" seed_init: %d\n",k5_ctx->seed_init); + dprintk(" signalg: %d\n",k5_ctx->signalg); + dprintk(" cksum_size: %d\n",k5_ctx->cksum_size); + dprintk(" sealalg: %d\n",k5_ctx->sealalg); + dprintk(" big_endian: %d\n", k5_ctx->big_endian); +} + +static inline int +get_bytes(char **ptr, const char *end, void *res, int len) +{ + char *p, *q; + p = *ptr; + q = p + len; + if (q > end || q < p) + return -1; + memcpy(res, p, len); + *ptr = q; + return 0; +} + +static inline int +get_netobj(char **ptr, const char *end, struct xdr_netobj *res) +{ + char *p, *q; + p = *ptr; + if (get_bytes(&p, end, &res->len, sizeof(res->len))) + return -1; + q = p + res->len; + if (q > end || q < p) + return -1; + if (!(res->data = kmalloc(res->len, GFP_KERNEL))) + return -1; + memcpy(res->data, p, res->len); + *ptr = q; + return 0; +} + +static inline int +get_key(char **p, char *end, struct crypto_tfm **res) +{ + struct xdr_netobj key; + int alg, alg_mode; + char *alg_name; + + if (get_bytes(p, end, &alg, sizeof(alg))) + goto out_err; + if ((get_netobj(p, end, &key))) + goto out_err; + + switch (alg) { + case ENCTYPE_DES_CBC_RAW: + alg_name = "des"; + alg_mode = CRYPTO_TFM_MODE_CBC; + break; + default: + dprintk("RPC: get_key: unsupported algorithm %d", alg); + goto out_err_free_key; + } + if (!(*res = crypto_alloc_tfm(alg_name, alg_mode))) + goto out_err_free_key; + if (crypto_cipher_setkey(*res, key.data, key.len)) + goto out_err_free_tfm; + + kfree(key.data); + return 0; + +out_err_free_tfm: + crypto_free_tfm(*res); +out_err_free_key: + kfree(key.data); +out_err: + return -1; +} + +static u32 +gss_import_sec_context_kerberos(struct xdr_netobj *inbuf, GSS_CTX_ID_T ctx_id) +{ + char *p = inbuf->data; + char *end = inbuf->data + inbuf->len; + struct _krb5_gss_ctx_id_rec *ctx; + + if (!(ctx = kmalloc(sizeof(*ctx), GFP_KERNEL))) + goto out_err; + memset(ctx, 0, sizeof(*ctx)); + + if (get_bytes(&p, end, &ctx->initiate, sizeof(ctx->initiate))) + goto out_err_free_ctx; + if (get_bytes(&p, end, &ctx->seed_init, sizeof(ctx->seed_init))) + goto out_err_free_ctx; + if (get_bytes(&p, end, ctx->seed, sizeof(ctx->seed))) + goto out_err_free_ctx; + if (get_bytes(&p, end, &ctx->signalg, sizeof(ctx->signalg))) + goto out_err_free_ctx; + if (get_bytes(&p, end, &ctx->cksum_size, sizeof(ctx->cksum_size))) + goto out_err_free_ctx; + if (get_bytes(&p, end, &ctx->sealalg, sizeof(ctx->sealalg))) + goto out_err_free_ctx; + if (get_bytes(&p, end, &ctx->endtime, sizeof(ctx->endtime))) + goto out_err_free_ctx; + if (get_bytes(&p, end, &ctx->seq_send, sizeof(ctx->seq_send))) + goto out_err_free_ctx; + if (get_bytes(&p, end, &ctx->big_endian, sizeof(ctx->big_endian))) + goto out_err_free_ctx; + if (get_netobj(&p, end, &ctx->mech_used)) + goto out_err_free_ctx; + if (get_key(&p, end, &ctx->enc)) + goto out_err_free_mech; + if (get_key(&p, end, &ctx->seq)) + goto out_err_free_key1; + if (p != end) + goto out_err_free_key2; + + ctx_id->internal_ctx_id = ctx; + dprintk("Succesfully imported new context.\n"); + print_krb5_gss_ctx_id_rec(ctx); + return 0; + +out_err_free_key2: + crypto_free_tfm(ctx->seq); +out_err_free_key1: + crypto_free_tfm(ctx->enc); +out_err_free_mech: + kfree(ctx->mech_used.data); +out_err_free_ctx: + kfree(ctx); +out_err: + return GSS_S_FAILURE; +} + +void +gss_delete_sec_context_kerberos(void *internal_ctx) { + struct _krb5_gss_ctx_id_rec *kctx = internal_ctx; + + if (kctx->seq) + crypto_free_tfm(kctx->seq); + if (kctx->enc) + crypto_free_tfm(kctx->enc); + if (kctx->mech_used.data) + kfree(kctx->mech_used.data); + kfree(kctx); +} + +u32 +gss_verify_mic_kerberos( GSS_CTX_ID_T contextid, + struct xdr_netobj *signbuf, + struct xdr_netobj *checksum, + u32 *qstate) { + u32 maj_stat = 0; + int qop_state; + + dprintk("GSS_VERIFY_MIC\n"); + + print_krb5_gss_ctx_id_rec(contextid->internal_ctx_id); + + dprintk("VERIFY MIC calling kg_unseal\n"); + + maj_stat = kg_unseal(contextid, checksum,signbuf, + NULL, &qop_state, KG_TOK_MIC_MSG); + if (!maj_stat && qop_state) + *qstate = qop_state; + + dprintk("VERIFY MIC returning err %d\n", maj_stat); + return maj_stat; +} + +u32 +gss_get_mic_kerberos(GSS_CTX_ID_T contextid, + u32 qop, + struct xdr_netobj *message_buffer, + struct xdr_netobj *message_token) { + u32 err = 0,i; + unsigned char *pp; + + dprintk("GSS_GETMIC\n"); + + print_krb5_gss_ctx_id_rec(contextid->internal_ctx_id); + + if (!message_buffer->data) return -EINVAL; + + dprintk("GSS_GETMIC: message_buffer->len %d\n",message_buffer->len); + pp = message_buffer->data; + for(i=0;ilen;i++) + dprintk("%02x",*pp++); + dprintk("\n"); + + dprintk("GETMIC calling kg_seal\n"); + err = kg_seal(contextid, qop, message_buffer, NULL, + message_token, KG_TOK_MIC_MSG); + + dprintk("GETMIC kg_seal return: %d \n",err); + + return err; +} + +static struct gss_api_ops gss_kerberos_ops = { + .name = "krb5", + NULL, + .gss_import_sec_context = gss_import_sec_context_kerberos, + .gss_get_mic = gss_get_mic_kerberos, + .gss_verify_mic = gss_verify_mic_kerberos, + .gss_delete_sec_context = gss_delete_sec_context_kerberos, +}; + +/* XXX error checking? reference counting? */ +static int __init init_kerberos_module(void) +{ + struct gss_api_mech *gm; + + if (gss_mech_register(&gss_mech_krb5_oid, &gss_kerberos_ops)) + printk("Failed to register kerberos gss mechanism!\n"); + gm = gss_mech_get_by_OID(&gss_mech_krb5_oid); + gss_register_triple(RPC_AUTH_GSS_KRB5 , gm, 0, RPC_GSS_SVC_NONE); + gss_mech_put(gm); + return 0; +} + +static void __exit cleanup_kerberos_module(void) +{ + gss_unregister_triple(RPC_AUTH_GSS_KRB5); +} + +MODULE_LICENSE("GPL"); +module_init(init_kerberos_module); +module_exit(cleanup_kerberos_module); diff -u -r -N linux-2.5.47-07-auth_upcall2/net/sunrpc/gss_krb5_seal.c linux-2.5.47-08-krb5/net/sunrpc/gss_krb5_seal.c --- linux-2.5.47-07-auth_upcall2/net/sunrpc/gss_krb5_seal.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.5.47-08-krb5/net/sunrpc/gss_krb5_seal.c 2002-11-15 20:43:52.000000000 -0500 @@ -0,0 +1,283 @@ +/* + * linux/net/sunrpc/gss_krb5_seal.c + * + * Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/krb5/k5seal.c + * + * Copyright (c) 2000 The Regents of the University of Michigan. + * All rights reserved. + * + * Andy Adamson + */ + +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include +#include +#include +#include +#include +#include + +#ifdef RPC_DEBUG +# define RPCDBG_FACILITY RPCDBG_AUTH +#endif + +static s32 +make_seal_token_v1(struct crypto_tfm *enc, + struct crypto_tfm *seq, + s32 * seqnum, + int direction, + struct xdr_netobj * text, + struct xdr_netobj * token, + int signalg, + int cksum_size, + int sealalg, + int toktype, + struct xdr_netobj * oid) +{ + s32 checksum_type; + s32 code = 0; + char *data_ptr; + struct xdr_netobj plaind; + struct xdr_netobj md5cksum; + struct xdr_netobj cksum; + int conflen = 0, tmsglen, tlen; + unsigned char *t, *ptr; + + dprintk("RPC: gss_krb5_seal"); + switch (signalg) { + case SGN_ALG_DES_MAC_MD5: + checksum_type = CKSUMTYPE_RSA_MD5; + break; + default: + dprintk("RPC: gss_krb5_seal: signalg %d not" + " supported\n", signalg); + return KG_BAD_SIGN_TYPE; + } + if (sealalg != SEAL_ALG_NONE && sealalg != SEAL_ALG_DES) { + dprintk("RPC: gss_krb5_seal: sealalg %d not supported\n", + sealalg); + return KG_BAD_SIGN_TYPE; + } + + /* create the token buffer */ + + if (toktype == KG_TOK_WRAP_MSG) { + conflen = crypto_tfm_alg_blocksize(enc); + /* XXX knows that des block size is 8 */ + tmsglen = (conflen + text->len + 8) & (~7); + } else { + tmsglen = 0; + } + + tlen = g_token_size(oid, 14 + cksum_size + tmsglen); + + if ((t = kmalloc(tlen, GFP_KERNEL)) == NULL) + return GSS_S_FAILURE; + + /* fill in the token */ + + ptr = t; + + g_make_token_header(oid, 14 + cksum_size + tmsglen, &ptr, toktype); + + /* ptr now at byte 2 of header described in rfc 1964, section 1.2.1: */ + ptr[0] = signalg & 0xff; + ptr[1] = (signalg >> 8) & 0xff; + + if (toktype == KG_TOK_WRAP_MSG) { + ptr[2] = sealalg & 0xff; + ptr[3] = (sealalg >> 8) & 0xff; + } else { + /* No seal */ + ptr[2] = 0xff; + ptr[3] = 0xff; + } + + ptr[4] = 0xff; + ptr[5] = 0xff; + + md5cksum.len = RSA_MD5_CKSUM_LENGTH; + + if (toktype == KG_TOK_WRAP_MSG) { + unsigned char *plain; + unsigned char pad; + + if ((plain = kmalloc(tmsglen, GFP_KERNEL)) == NULL) { + kfree(t); + return GSS_S_FAILURE; + } + get_random_bytes(plain, conflen); /* "confounder" */ + memcpy(plain + conflen, text->data, text->len); + + /* XXX 8 is DES cblock size */ + pad = 8 - (text->len % 8); + + memset(plain + conflen + text->len, pad, pad); + + if ((code = gss_k5encrypt(enc, NULL, plain, + ptr + cksum_size + 14, + tmsglen))) { + if (plain) + kfree(plain); + kfree(t); + return code; + } + + /* compute the checksum */ + + /* 8 = head of token body as specified by mech spec */ + if (!(data_ptr = kmalloc(8 + tmsglen, GFP_KERNEL))) { + if (plain) + kfree(plain); + kfree(t); + return GSS_S_FAILURE; + } + memcpy(data_ptr, ptr - 2, 8); + memcpy(data_ptr + 8, plain, tmsglen); + plaind.len = 8 + tmsglen; + plaind.data = data_ptr; + code = krb5_make_checksum(checksum_type, &plaind, + &md5cksum); + kfree(data_ptr); + + if (code) { + if (plain) + kfree(plain); + kfree(t); + return code; + } + + if (plain) + kfree(plain); + } else { /* Sign only. */ + /* compute the checksum */ + + if (!(data_ptr = kmalloc(8 + text->len, GFP_KERNEL))) { + kfree(t); + return GSS_S_FAILURE; + } + memcpy(data_ptr, ptr - 2, 8); + memcpy(data_ptr + 8, text->data, text->len); + plaind.len = 8 + text->len; + plaind.data = data_ptr; + code = krb5_make_checksum(checksum_type, &plaind, + &md5cksum); + kfree(data_ptr); + if (code) { + kfree(t); + return code; + } + } + + switch (signalg) { + case SGN_ALG_DES_MAC_MD5: + if ((code = gss_k5encrypt(seq, NULL, md5cksum.data, + md5cksum.data, 16))) { + kfree(md5cksum.data); + kfree(t); + return code; + } + + cksum.len = cksum_size; + cksum.data = md5cksum.data + 16 - cksum.len; + memcpy(ptr + 14, cksum.data, cksum.len); + + dprintk("make_seal_token: ptr with cksum data: \n"); + print_hexl((u32 *) ptr + 14, 8, 0); + break; + default: + return KG_BAD_SIGN_TYPE; + } + + kfree(md5cksum.data); + + if ((code = kg_make_seq_num(seq, direction ? 0 : 0xff, *seqnum, + ptr + 14, ptr + 6))) { + kfree(t); + return code; + } + + (*seqnum)++; + token->len = tlen; + token->data = (void *) t; + + return GSS_S_COMPLETE; +} + +u32 +kg_seal(GSS_CTX_ID_T context_handle, + int qop_req, + struct xdr_netobj * input_message_buffer, + int *conf_state, struct xdr_netobj * output_message_buffer, int toktype) +{ + krb5_gss_ctx_id_rec *ctx = context_handle->internal_ctx_id; + s32 code; + s32 now; + + output_message_buffer->len = 0; + output_message_buffer->data = NULL; + + if (qop_req != 0) + return GSS_S_FAILURE; + + now = jiffies; + + code = make_seal_token_v1(ctx->enc, ctx->seq, + &ctx->seq_send, ctx->initiate, + input_message_buffer, + output_message_buffer, ctx->signalg, + ctx->cksum_size, ctx->sealalg, + toktype, &ctx->mech_used); + + if (code) + return (GSS_S_FAILURE); + + return ((ctx->endtime < now) ? GSS_S_CONTEXT_EXPIRED : GSS_S_COMPLETE); +} diff -u -r -N linux-2.5.47-07-auth_upcall2/net/sunrpc/gss_krb5_seqnum.c linux-2.5.47-08-krb5/net/sunrpc/gss_krb5_seqnum.c --- linux-2.5.47-07-auth_upcall2/net/sunrpc/gss_krb5_seqnum.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.5.47-08-krb5/net/sunrpc/gss_krb5_seqnum.c 2002-11-15 20:39:45.000000000 -0500 @@ -0,0 +1,88 @@ +/* + * linux/net/sunrpc/gss_krb5_seqnum.c + * + * Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/krb5/util_seqnum.c + * + * Copyright (c) 2000 The Regents of the University of Michigan. + * All rights reserved. + * + * Andy Adamson + */ + +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include + +#ifdef RPC_DEBUG +# define RPCDBG_FACILITY RPCDBG_AUTH +#endif + +s32 +kg_make_seq_num(struct crypto_tfm *key, + int direction, + s32 seqnum, + unsigned char *cksum, unsigned char *buf) +{ + unsigned char plain[8]; + + plain[0] = (unsigned char) (seqnum & 0xff); + plain[1] = (unsigned char) ((seqnum >> 8) & 0xff); + plain[2] = (unsigned char) ((seqnum >> 16) & 0xff); + plain[3] = (unsigned char) ((seqnum >> 24) & 0xff); + + plain[4] = direction; + plain[5] = direction; + plain[6] = direction; + plain[7] = direction; + + return gss_k5encrypt(key, cksum, plain, buf, 8); +} + +s32 +kg_get_seq_num(struct crypto_tfm *key, + unsigned char *cksum, + unsigned char *buf, + int *direction, s32 * seqnum) +{ + s32 code; + unsigned char plain[8]; + + dprintk("kg_get_seq_num: \n"); + + if ((code = gss_k5decrypt(key, cksum, buf, plain, 8))) + return code; + + if ((plain[4] != plain[5]) || (plain[4] != plain[6]) + || (plain[4] != plain[7])) + return (s32)KG_BAD_SEQ; + + *direction = plain[4]; + + *seqnum = ((plain[0]) | + (plain[1] << 8) | (plain[2] << 16) | (plain[3] << 24)); + + return (0); +} diff -u -r -N linux-2.5.47-07-auth_upcall2/net/sunrpc/gss_krb5_unseal.c linux-2.5.47-08-krb5/net/sunrpc/gss_krb5_unseal.c --- linux-2.5.47-07-auth_upcall2/net/sunrpc/gss_krb5_unseal.c 1969-12-31 19:00:00.000000000 -0500 +++ linux-2.5.47-08-krb5/net/sunrpc/gss_krb5_unseal.c 2002-11-15 17:30:29.000000000 -0500 @@ -0,0 +1,367 @@ +/* + * linux/net/sunrpc/gss_krb5_unseal.c + * + * Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/krb5/k5unseal.c + * + * Copyright (c) 2000 The Regents of the University of Michigan. + * All rights reserved. + * + * Andy Adamson + */ + +/* + * Copyright 1993 by OpenVision Technologies, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appears in all copies and + * that both that copyright notice and this permission notice appear in + * supporting documentation, and that the name of OpenVision not be used + * in advertising or publicity pertaining to distribution of the software + * without specific, written prior permission. OpenVision makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF + * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR + * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Copyright (C) 1998 by the FundsXpress, INC. + * + * All rights reserved. + * + * Export of this software from the United States of America may require + * a specific license from the United States Government. It is the + * responsibility of any person or organization contemplating export to + * obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of FundsXpress. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. FundsXpress makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#include +#include +#include +#include +#include + +#ifdef RPC_DEBUG +# define RPCDBG_FACILITY RPCDBG_AUTH +#endif + + +/* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX + conf_state is only valid if SEAL. */ + +u32 +kg_unseal_v1(krb5_gss_ctx_id_rec * ctx, + unsigned char *ptr, + int bodysize, + struct xdr_netobj * message_buffer, + int *conf_state, int *qop_state, int toktype) +{ + s32 code; + int tmsglen = 0; + int conflen = 0; + int signalg; + int sealalg; + struct xdr_netobj token; + s32 checksum_type; + struct xdr_netobj cksum; + struct xdr_netobj md5cksum; + struct xdr_netobj plaind; + char *data_ptr; + s32 now; + unsigned char *plain = NULL; + int cksum_len = 0; + int plainlen = 0; + int direction; + s32 seqnum; + + dprintk("RPC: kg_unseal_v1\n"); + if (toktype == KG_TOK_WRAP_MSG) { + message_buffer->len = 0; + message_buffer->data = NULL; + } + + /* get the sign and seal algorithms */ + + signalg = ptr[0] + (ptr[1] << 8); + sealalg = ptr[2] + (ptr[3] << 8); + + /* Sanity checks */ + + if ((ptr[4] != 0xff) || (ptr[5] != 0xff)) + return GSS_S_DEFECTIVE_TOKEN; + + if ((toktype != KG_TOK_WRAP_MSG) && (sealalg != 0xffff)) + return GSS_S_DEFECTIVE_TOKEN; + + /* in the current spec, there is only one valid seal algorithm per + key type, so a simple comparison is ok */ + + if ((toktype == KG_TOK_WRAP_MSG) && + !((sealalg == 0xffff) || (sealalg == ctx->sealalg))) + return GSS_S_DEFECTIVE_TOKEN; + /* there are several mappings of seal algorithms to sign algorithms, + but few enough that we can try them all. */ + + if ((ctx->sealalg == SEAL_ALG_NONE && signalg > 1) || + (ctx->sealalg == SEAL_ALG_1 && signalg != SGN_ALG_3) || + (ctx->sealalg == SEAL_ALG_DES3KD && + signalg != SGN_ALG_HMAC_SHA1_DES3_KD)) + return GSS_S_DEFECTIVE_TOKEN; + + /* starting with a single alg */ + switch (signalg) { + case SGN_ALG_DES_MAC_MD5: + cksum_len = 8; + break; + default: + return GSS_S_DEFECTIVE_TOKEN; + } + + if (toktype == KG_TOK_WRAP_MSG) + tmsglen = bodysize - (14 + cksum_len); + + /* get the token parameters */ + + /* decode the message, if SEAL */ + + if (toktype == KG_TOK_WRAP_MSG) { + dprintk("RPC: kg_unseal_v1 KG_TOK_WRAP_MSG\n"); + + + if (sealalg != 0xffff) { + plain = kmalloc(tmsglen, GFP_KERNEL); + if (plain == NULL) + return (GSS_S_FAILURE); + + code = gss_k5decrypt(ctx->enc, NULL, + ptr + 14 + cksum_len, plain, + tmsglen); + if (code) { + kfree(plain); + return (GSS_S_FAILURE); + } + } else { + plain = ptr + 14 + cksum_len; + } + + plainlen = tmsglen; + + if ((sealalg == 0xffff) && ctx->big_endian) { + token.len = tmsglen; + } else { + conflen = crypto_tfm_alg_blocksize(ctx->enc); + token.len = tmsglen - conflen - plain[tmsglen - 1]; + } + + if (token.len) { + token.data = kmalloc(token.len, GFP_KERNEL); + if (token.data == NULL) { + if (sealalg != 0xffff) + kfree(plain); + return (GSS_S_FAILURE); + } + memcpy(token.data, plain + conflen, token.len); + } + + } else if (toktype == KG_TOK_MIC_MSG) { + dprintk("RPC: kg_unseal_v1 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; + } + + dprintk("RPC kg_unseal_v1: token.len %d plainlen %d\n", token.len, + plainlen); + + /* compute the checksum of the message */ + + /* initialize the the cksum */ + switch (signalg) { + case SGN_ALG_DES_MAC_MD5: + checksum_type = CKSUMTYPE_RSA_MD5; + break; + default: + return (GSS_S_DEFECTIVE_TOKEN); + } + + md5cksum.len = RSA_MD5_CKSUM_LENGTH; + + switch (signalg) { + case SGN_ALG_DES_MAC_MD5: + dprintk("RPC kg_unseal_v1 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 + (ctx->big_endian ? token.len : plainlen), + GFP_KERNEL); + if (!data_ptr) { + if (sealalg != 0xffff) + kfree(plain); + if (toktype == KG_TOK_WRAP_MSG) + kfree(token.data); + return (GSS_S_FAILURE); + } + + memcpy(data_ptr, ptr - 2, 8); + if (ctx->big_endian) + memcpy(data_ptr + 8, token.data, token.len); + else + memcpy(data_ptr + 8, plain, plainlen); + + plaind.len = 8 + (ctx->big_endian ? token.len : plainlen); + plaind.data = data_ptr; + + dprintk + ("RPC:kg_unseal calling make_checksum with PLAIN TEXT\n"); + print_hexl((u32 *) plaind.data, plaind.len, 0); + + code = krb5_make_checksum(checksum_type, + &plaind, &md5cksum); + + kfree(data_ptr); + + if (code) { + if (toktype == KG_TOK_WRAP_MSG) + kfree(token.data); + return (GSS_S_FAILURE); + } + + code = gss_k5encrypt(ctx->seq, NULL, md5cksum.data, + md5cksum.data, 16); + if (code) { + kfree(md5cksum.data); + if (toktype == KG_TOK_WRAP_MSG) + kfree(token.data); + return GSS_S_FAILURE; + } + + + if (signalg == 0) + cksum.len = 8; + else + cksum.len = 16; + cksum.data = md5cksum.data + 16 - cksum.len; + + dprintk + ("RPC: kg_unseal_v1: 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: + return (GSS_S_DEFECTIVE_TOKEN); + } + + kfree(md5cksum.data); + if (sealalg != 0xffff) + kfree(plain); + + /* compare the computed checksum against the transmitted checksum */ + + if (code) { + if (toktype == KG_TOK_WRAP_MSG) + kfree(token.data); + return (GSS_S_BAD_SIG); + } + + /* it got through unscathed. Make sure the context is unexpired */ + + if (toktype == KG_TOK_WRAP_MSG) + *message_buffer = token; + + if (conf_state) + *conf_state = (sealalg != 0xffff); + + if (qop_state) + *qop_state = GSS_C_QOP_DEFAULT; + + now = jiffies; + + if (now > ctx->endtime) { + return (GSS_S_CONTEXT_EXPIRED); + } + + /* do sequencing checks */ + + if ((code = kg_get_seq_num(ctx->seq, ptr + 14, ptr + 6, &direction, + &seqnum))) { + if (toktype == KG_TOK_WRAP_MSG) + kfree(token.data); + return (GSS_S_BAD_SIG); + } + + if ((ctx->initiate && direction != 0xff) || + (!ctx->initiate && direction != 0)) { + if (toktype == KG_TOK_WRAP_MSG) + kfree(token.data); + return (GSS_S_BAD_SIG); + } + + return (GSS_S_COMPLETE); +} + +/* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX + conf_state is only valid if SEAL. */ + +u32 +kg_unseal(GSS_CTX_ID_T context_handle, + struct xdr_netobj * input_token_buffer, + struct xdr_netobj * message_buffer, + int *conf_state, int *qop_state, int toktype) +{ + krb5_gss_ctx_id_rec *ctx = context_handle->internal_ctx_id; + unsigned char *ptr; + int bodysize; + int err; + + ptr = (unsigned char *) input_token_buffer->data; + + /* parse the token, leave the data in message_buffer, setting conf_state */ + if ((err = g_verify_token_header((struct xdr_netobj *) &ctx->mech_used, + &bodysize, &ptr, toktype, + input_token_buffer->len)) != 0) + return (GSS_S_DEFECTIVE_TOKEN); + err = kg_unseal_v1(ctx, ptr, bodysize, + message_buffer, conf_state, qop_state, toktype); + dprintk("kg_unseal_v1 returned %d\n", err); + return (err); +}