linux/net/sunrpc/auth_gss/gss_spkm3_mech.c
<<
>>
Prefs
   1/*
   2 *  linux/net/sunrpc/gss_spkm3_mech.c
   3 *
   4 *  Copyright (c) 2003 The Regents of the University of Michigan.
   5 *  All rights reserved.
   6 *
   7 *  Andy Adamson <andros@umich.edu>
   8 *  J. Bruce Fields <bfields@umich.edu>
   9 *
  10 *  Redistribution and use in source and binary forms, with or without
  11 *  modification, are permitted provided that the following conditions
  12 *  are met:
  13 *
  14 *  1. Redistributions of source code must retain the above copyright
  15 *     notice, this list of conditions and the following disclaimer.
  16 *  2. Redistributions in binary form must reproduce the above copyright
  17 *     notice, this list of conditions and the following disclaimer in the
  18 *     documentation and/or other materials provided with the distribution.
  19 *  3. Neither the name of the University nor the names of its
  20 *     contributors may be used to endorse or promote products derived
  21 *     from this software without specific prior written permission.
  22 *
  23 *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  24 *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  25 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  26 *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  27 *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  28 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  29 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  30 *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  31 *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  32 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  33 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  34 *
  35 */
  36
  37#include <linux/err.h>
  38#include <linux/module.h>
  39#include <linux/init.h>
  40#include <linux/types.h>
  41#include <linux/slab.h>
  42#include <linux/sunrpc/auth.h>
  43#include <linux/in.h>
  44#include <linux/sunrpc/svcauth_gss.h>
  45#include <linux/sunrpc/gss_spkm3.h>
  46#include <linux/sunrpc/xdr.h>
  47#include <linux/crypto.h>
  48
  49#ifdef RPC_DEBUG
  50# define RPCDBG_FACILITY        RPCDBG_AUTH
  51#endif
  52
  53static const void *
  54simple_get_bytes(const void *p, const void *end, void *res, int len)
  55{
  56        const void *q = (const void *)((const char *)p + len);
  57        if (unlikely(q > end || q < p))
  58                return ERR_PTR(-EFAULT);
  59        memcpy(res, p, len);
  60        return q;
  61}
  62
  63static const void *
  64simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res)
  65{
  66        const void *q;
  67        unsigned int len;
  68        p = simple_get_bytes(p, end, &len, sizeof(len));
  69        if (IS_ERR(p))
  70                return p;
  71        res->len = len;
  72        if (len == 0) {
  73                res->data = NULL;
  74                return p;
  75        }
  76        q = (const void *)((const char *)p + len);
  77        if (unlikely(q > end || q < p))
  78                return ERR_PTR(-EFAULT);
  79        res->data = kmemdup(p, len, GFP_NOFS);
  80        if (unlikely(res->data == NULL))
  81                return ERR_PTR(-ENOMEM);
  82        return q;
  83}
  84
  85static int
  86gss_import_sec_context_spkm3(const void *p, size_t len,
  87                                struct gss_ctx *ctx_id)
  88{
  89        const void *end = (const void *)((const char *)p + len);
  90        struct  spkm3_ctx *ctx;
  91        int     version;
  92
  93        if (!(ctx = kzalloc(sizeof(*ctx), GFP_NOFS)))
  94                goto out_err;
  95
  96        p = simple_get_bytes(p, end, &version, sizeof(version));
  97        if (IS_ERR(p))
  98                goto out_err_free_ctx;
  99        if (version != 1) {
 100                dprintk("RPC:       unknown spkm3 token format: "
 101                                "obsolete nfs-utils?\n");
 102                goto out_err_free_ctx;
 103        }
 104
 105        p = simple_get_netobj(p, end, &ctx->ctx_id);
 106        if (IS_ERR(p))
 107                goto out_err_free_ctx;
 108
 109        p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime));
 110        if (IS_ERR(p))
 111                goto out_err_free_ctx_id;
 112
 113        p = simple_get_netobj(p, end, &ctx->mech_used);
 114        if (IS_ERR(p))
 115                goto out_err_free_ctx_id;
 116
 117        p = simple_get_bytes(p, end, &ctx->ret_flags, sizeof(ctx->ret_flags));
 118        if (IS_ERR(p))
 119                goto out_err_free_mech;
 120
 121        p = simple_get_netobj(p, end, &ctx->conf_alg);
 122        if (IS_ERR(p))
 123                goto out_err_free_mech;
 124
 125        p = simple_get_netobj(p, end, &ctx->derived_conf_key);
 126        if (IS_ERR(p))
 127                goto out_err_free_conf_alg;
 128
 129        p = simple_get_netobj(p, end, &ctx->intg_alg);
 130        if (IS_ERR(p))
 131                goto out_err_free_conf_key;
 132
 133        p = simple_get_netobj(p, end, &ctx->derived_integ_key);
 134        if (IS_ERR(p))
 135                goto out_err_free_intg_alg;
 136
 137        if (p != end)
 138                goto out_err_free_intg_key;
 139
 140        ctx_id->internal_ctx_id = ctx;
 141
 142        dprintk("RPC:       Successfully imported new spkm context.\n");
 143        return 0;
 144
 145out_err_free_intg_key:
 146        kfree(ctx->derived_integ_key.data);
 147out_err_free_intg_alg:
 148        kfree(ctx->intg_alg.data);
 149out_err_free_conf_key:
 150        kfree(ctx->derived_conf_key.data);
 151out_err_free_conf_alg:
 152        kfree(ctx->conf_alg.data);
 153out_err_free_mech:
 154        kfree(ctx->mech_used.data);
 155out_err_free_ctx_id:
 156        kfree(ctx->ctx_id.data);
 157out_err_free_ctx:
 158        kfree(ctx);
 159out_err:
 160        return PTR_ERR(p);
 161}
 162
 163static void
 164gss_delete_sec_context_spkm3(void *internal_ctx)
 165{
 166        struct spkm3_ctx *sctx = internal_ctx;
 167
 168        kfree(sctx->derived_integ_key.data);
 169        kfree(sctx->intg_alg.data);
 170        kfree(sctx->derived_conf_key.data);
 171        kfree(sctx->conf_alg.data);
 172        kfree(sctx->mech_used.data);
 173        kfree(sctx->ctx_id.data);
 174        kfree(sctx);
 175}
 176
 177static u32
 178gss_verify_mic_spkm3(struct gss_ctx             *ctx,
 179                        struct xdr_buf          *signbuf,
 180                        struct xdr_netobj       *checksum)
 181{
 182        u32 maj_stat = 0;
 183        struct spkm3_ctx *sctx = ctx->internal_ctx_id;
 184
 185        maj_stat = spkm3_read_token(sctx, checksum, signbuf, SPKM_MIC_TOK);
 186
 187        dprintk("RPC:       gss_verify_mic_spkm3 returning %d\n", maj_stat);
 188        return maj_stat;
 189}
 190
 191static u32
 192gss_get_mic_spkm3(struct gss_ctx        *ctx,
 193                     struct xdr_buf     *message_buffer,
 194                     struct xdr_netobj  *message_token)
 195{
 196        u32 err = 0;
 197        struct spkm3_ctx *sctx = ctx->internal_ctx_id;
 198
 199        err = spkm3_make_token(sctx, message_buffer,
 200                                message_token, SPKM_MIC_TOK);
 201        dprintk("RPC:       gss_get_mic_spkm3 returning %d\n", err);
 202        return err;
 203}
 204
 205static const struct gss_api_ops gss_spkm3_ops = {
 206        .gss_import_sec_context = gss_import_sec_context_spkm3,
 207        .gss_get_mic            = gss_get_mic_spkm3,
 208        .gss_verify_mic         = gss_verify_mic_spkm3,
 209        .gss_delete_sec_context = gss_delete_sec_context_spkm3,
 210};
 211
 212static struct pf_desc gss_spkm3_pfs[] = {
 213        {RPC_AUTH_GSS_SPKM, RPC_GSS_SVC_NONE, "spkm3"},
 214        {RPC_AUTH_GSS_SPKMI, RPC_GSS_SVC_INTEGRITY, "spkm3i"},
 215};
 216
 217static struct gss_api_mech gss_spkm3_mech = {
 218        .gm_name        = "spkm3",
 219        .gm_owner       = THIS_MODULE,
 220        .gm_oid         = {7, "\053\006\001\005\005\001\003"},
 221        .gm_ops         = &gss_spkm3_ops,
 222        .gm_pf_num      = ARRAY_SIZE(gss_spkm3_pfs),
 223        .gm_pfs         = gss_spkm3_pfs,
 224};
 225
 226static int __init init_spkm3_module(void)
 227{
 228        int status;
 229
 230        status = gss_mech_register(&gss_spkm3_mech);
 231        if (status)
 232                printk("Failed to register spkm3 gss mechanism!\n");
 233        return status;
 234}
 235
 236static void __exit cleanup_spkm3_module(void)
 237{
 238        gss_mech_unregister(&gss_spkm3_mech);
 239}
 240
 241MODULE_LICENSE("GPL");
 242module_init(init_spkm3_module);
 243module_exit(cleanup_spkm3_module);
 244