gss_spkm3_mech.c 6.6 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
/*
 *  linux/net/sunrpc/gss_spkm3_mech.c
 *
 *  Copyright (c) 2003 The Regents of the University of Michigan.
 *  All rights reserved.
 *
 *  Andy Adamson <andros@umich.edu>
 *  J. Bruce Fields <bfields@umich.edu>
 *
 *  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.
 *
 */

37
#include <linux/err.h>
L
Linus Torvalds 已提交
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/sunrpc/auth.h>
#include <linux/in.h>
#include <linux/sunrpc/svcauth_gss.h>
#include <linux/sunrpc/gss_spkm3.h>
#include <linux/sunrpc/xdr.h>
#include <linux/crypto.h>

#ifdef RPC_DEBUG
# define RPCDBG_FACILITY	RPCDBG_AUTH
#endif

static const void *
simple_get_bytes(const void *p, const void *end, void *res, int len)
{
	const void *q = (const void *)((const char *)p + len);
	if (unlikely(q > end || q < p))
		return ERR_PTR(-EFAULT);
	memcpy(res, p, len);
	return q;
}

static const void *
simple_get_netobj(const void *p, const void *end, struct xdr_netobj *res)
{
	const void *q;
	unsigned int len;
	p = simple_get_bytes(p, end, &len, sizeof(len));
	if (IS_ERR(p))
		return p;
	res->len = len;
	if (len == 0) {
		res->data = NULL;
		return p;
	}
	q = (const void *)((const char *)p + len);
	if (unlikely(q > end || q < p))
		return ERR_PTR(-EFAULT);
79
	res->data = kmemdup(p, len, GFP_NOFS);
L
Linus Torvalds 已提交
80 81 82 83 84 85 86
	if (unlikely(res->data == NULL))
		return ERR_PTR(-ENOMEM);
	return q;
}

static int
gss_import_sec_context_spkm3(const void *p, size_t len,
87 88
				struct gss_ctx *ctx_id,
				gfp_t gfp_mask)
L
Linus Torvalds 已提交
89 90 91
{
	const void *end = (const void *)((const char *)p + len);
	struct	spkm3_ctx *ctx;
O
Olga Kornievskaia 已提交
92
	int	version;
L
Linus Torvalds 已提交
93

94
	if (!(ctx = kzalloc(sizeof(*ctx), gfp_mask)))
L
Linus Torvalds 已提交
95 96
		goto out_err;

O
Olga Kornievskaia 已提交
97 98 99 100
	p = simple_get_bytes(p, end, &version, sizeof(version));
	if (IS_ERR(p))
		goto out_err_free_ctx;
	if (version != 1) {
101 102
		dprintk("RPC:       unknown spkm3 token format: "
				"obsolete nfs-utils?\n");
103
		p = ERR_PTR(-EINVAL);
O
Olga Kornievskaia 已提交
104 105 106
		goto out_err_free_ctx;
	}

L
Linus Torvalds 已提交
107 108 109 110
	p = simple_get_netobj(p, end, &ctx->ctx_id);
	if (IS_ERR(p))
		goto out_err_free_ctx;

O
Olga Kornievskaia 已提交
111
	p = simple_get_bytes(p, end, &ctx->endtime, sizeof(ctx->endtime));
L
Linus Torvalds 已提交
112 113 114 115 116
	if (IS_ERR(p))
		goto out_err_free_ctx_id;

	p = simple_get_netobj(p, end, &ctx->mech_used);
	if (IS_ERR(p))
O
Olga Kornievskaia 已提交
117
		goto out_err_free_ctx_id;
L
Linus Torvalds 已提交
118 119 120 121 122

	p = simple_get_bytes(p, end, &ctx->ret_flags, sizeof(ctx->ret_flags));
	if (IS_ERR(p))
		goto out_err_free_mech;

O
Olga Kornievskaia 已提交
123
	p = simple_get_netobj(p, end, &ctx->conf_alg);
L
Linus Torvalds 已提交
124 125 126
	if (IS_ERR(p))
		goto out_err_free_mech;

O
Olga Kornievskaia 已提交
127
	p = simple_get_netobj(p, end, &ctx->derived_conf_key);
L
Linus Torvalds 已提交
128
	if (IS_ERR(p))
O
Olga Kornievskaia 已提交
129
		goto out_err_free_conf_alg;
L
Linus Torvalds 已提交
130

O
Olga Kornievskaia 已提交
131
	p = simple_get_netobj(p, end, &ctx->intg_alg);
L
Linus Torvalds 已提交
132
	if (IS_ERR(p))
O
Olga Kornievskaia 已提交
133
		goto out_err_free_conf_key;
L
Linus Torvalds 已提交
134

O
Olga Kornievskaia 已提交
135
	p = simple_get_netobj(p, end, &ctx->derived_integ_key);
L
Linus Torvalds 已提交
136
	if (IS_ERR(p))
O
Olga Kornievskaia 已提交
137
		goto out_err_free_intg_alg;
L
Linus Torvalds 已提交
138

139 140
	if (p != end) {
		p = ERR_PTR(-EFAULT);
O
Olga Kornievskaia 已提交
141
		goto out_err_free_intg_key;
142
	}
L
Linus Torvalds 已提交
143 144 145

	ctx_id->internal_ctx_id = ctx;

146
	dprintk("RPC:       Successfully imported new spkm context.\n");
L
Linus Torvalds 已提交
147 148
	return 0;

O
Olga Kornievskaia 已提交
149 150 151 152 153 154 155 156
out_err_free_intg_key:
	kfree(ctx->derived_integ_key.data);
out_err_free_intg_alg:
	kfree(ctx->intg_alg.data);
out_err_free_conf_key:
	kfree(ctx->derived_conf_key.data);
out_err_free_conf_alg:
	kfree(ctx->conf_alg.data);
L
Linus Torvalds 已提交
157 158 159 160 161 162 163 164 165 166 167
out_err_free_mech:
	kfree(ctx->mech_used.data);
out_err_free_ctx_id:
	kfree(ctx->ctx_id.data);
out_err_free_ctx:
	kfree(ctx);
out_err:
	return PTR_ERR(p);
}

static void
O
Olga Kornievskaia 已提交
168 169
gss_delete_sec_context_spkm3(void *internal_ctx)
{
L
Linus Torvalds 已提交
170 171
	struct spkm3_ctx *sctx = internal_ctx;

O
Olga Kornievskaia 已提交
172 173 174 175
	kfree(sctx->derived_integ_key.data);
	kfree(sctx->intg_alg.data);
	kfree(sctx->derived_conf_key.data);
	kfree(sctx->conf_alg.data);
176
	kfree(sctx->mech_used.data);
O
Olga Kornievskaia 已提交
177
	kfree(sctx->ctx_id.data);
L
Linus Torvalds 已提交
178 179 180 181 182 183
	kfree(sctx);
}

static u32
gss_verify_mic_spkm3(struct gss_ctx		*ctx,
			struct xdr_buf		*signbuf,
184 185
			struct xdr_netobj	*checksum)
{
L
Linus Torvalds 已提交
186 187 188
	u32 maj_stat = 0;
	struct spkm3_ctx *sctx = ctx->internal_ctx_id;

189
	maj_stat = spkm3_read_token(sctx, checksum, signbuf, SPKM_MIC_TOK);
L
Linus Torvalds 已提交
190

191
	dprintk("RPC:       gss_verify_mic_spkm3 returning %d\n", maj_stat);
L
Linus Torvalds 已提交
192 193 194 195 196 197
	return maj_stat;
}

static u32
gss_get_mic_spkm3(struct gss_ctx	*ctx,
		     struct xdr_buf	*message_buffer,
198 199
		     struct xdr_netobj	*message_token)
{
L
Linus Torvalds 已提交
200 201 202
	u32 err = 0;
	struct spkm3_ctx *sctx = ctx->internal_ctx_id;

203
	err = spkm3_make_token(sctx, message_buffer,
O
Olga Kornievskaia 已提交
204
				message_token, SPKM_MIC_TOK);
205
	dprintk("RPC:       gss_get_mic_spkm3 returning %d\n", err);
L
Linus Torvalds 已提交
206 207 208
	return err;
}

209
static const struct gss_api_ops gss_spkm3_ops = {
L
Linus Torvalds 已提交
210 211 212 213 214 215 216
	.gss_import_sec_context	= gss_import_sec_context_spkm3,
	.gss_get_mic		= gss_get_mic_spkm3,
	.gss_verify_mic		= gss_verify_mic_spkm3,
	.gss_delete_sec_context	= gss_delete_sec_context_spkm3,
};

static struct pf_desc gss_spkm3_pfs[] = {
217 218
	{RPC_AUTH_GSS_SPKM, RPC_GSS_SVC_NONE, "spkm3"},
	{RPC_AUTH_GSS_SPKMI, RPC_GSS_SVC_INTEGRITY, "spkm3i"},
L
Linus Torvalds 已提交
219 220 221 222 223
};

static struct gss_api_mech gss_spkm3_mech = {
	.gm_name	= "spkm3",
	.gm_owner	= THIS_MODULE,
224
	.gm_oid		= {7, "\053\006\001\005\005\001\003"},
L
Linus Torvalds 已提交
225 226 227 228 229 230 231 232 233 234 235 236
	.gm_ops		= &gss_spkm3_ops,
	.gm_pf_num	= ARRAY_SIZE(gss_spkm3_pfs),
	.gm_pfs		= gss_spkm3_pfs,
};

static int __init init_spkm3_module(void)
{
	int status;

	status = gss_mech_register(&gss_spkm3_mech);
	if (status)
		printk("Failed to register spkm3 gss mechanism!\n");
237
	return status;
L
Linus Torvalds 已提交
238 239 240 241 242 243 244 245 246 247
}

static void __exit cleanup_spkm3_module(void)
{
	gss_mech_unregister(&gss_spkm3_mech);
}

MODULE_LICENSE("GPL");
module_init(init_spkm3_module);
module_exit(cleanup_spkm3_module);