• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/net/sunrpc/auth_gss/
1/*
2 *  linux/net/sunrpc/gss_generic_token.c
3 *
4 *  Adapted from MIT Kerberos 5-1.2.1 lib/gssapi/generic/util_token.c
5 *
6 *  Copyright (c) 2000 The Regents of the University of Michigan.
7 *  All rights reserved.
8 *
9 *  Andy Adamson   <andros@umich.edu>
10 */
11
12/*
13 * Copyright 1993 by OpenVision Technologies, Inc.
14 *
15 * Permission to use, copy, modify, distribute, and sell this software
16 * and its documentation for any purpose is hereby granted without fee,
17 * provided that the above copyright notice appears in all copies and
18 * that both that copyright notice and this permission notice appear in
19 * supporting documentation, and that the name of OpenVision not be used
20 * in advertising or publicity pertaining to distribution of the software
21 * without specific, written prior permission. OpenVision makes no
22 * representations about the suitability of this software for any
23 * purpose.  It is provided "as is" without express or implied warranty.
24 *
25 * OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
26 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
27 * EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
28 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
29 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
30 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
31 * PERFORMANCE OF THIS SOFTWARE.
32 */
33
34#include <linux/types.h>
35#include <linux/module.h>
36#include <linux/string.h>
37#include <linux/sunrpc/sched.h>
38#include <linux/sunrpc/gss_asn1.h>
39
40
41#ifdef RPC_DEBUG
42# define RPCDBG_FACILITY        RPCDBG_AUTH
43#endif
44
45
46/* TWRITE_STR from gssapiP_generic.h */
47#define TWRITE_STR(ptr, str, len) \
48	memcpy((ptr), (char *) (str), (len)); \
49	(ptr) += (len);
50
51
52/* Each token looks like this:
53
540x60				tag for APPLICATION 0, SEQUENCE
55					(constructed, definite-length)
56	<length>		possible multiple bytes, need to parse/generate
57	0x06			tag for OBJECT IDENTIFIER
58		<moid_length>	compile-time constant string (assume 1 byte)
59		<moid_bytes>	compile-time constant string
60	<inner_bytes>		the ANY containing the application token
61					bytes 0,1 are the token type
62					bytes 2,n are the token data
63
64For the purposes of this abstraction, the token "header" consists of
65the sequence tag and length octets, the mech OID DER encoding, and the
66first two inner bytes, which indicate the token type.  The token
67"body" consists of everything else.
68
69*/
70
71static int
72der_length_size( int length)
73{
74	if (length < (1<<7))
75		return(1);
76	else if (length < (1<<8))
77		return(2);
78#if (SIZEOF_INT == 2)
79	else
80		return(3);
81#else
82	else if (length < (1<<16))
83		return(3);
84	else if (length < (1<<24))
85		return(4);
86	else
87		return(5);
88#endif
89}
90
91static void
92der_write_length(unsigned char **buf, int length)
93{
94	if (length < (1<<7)) {
95		*(*buf)++ = (unsigned char) length;
96	} else {
97		*(*buf)++ = (unsigned char) (der_length_size(length)+127);
98#if (SIZEOF_INT > 2)
99		if (length >= (1<<24))
100			*(*buf)++ = (unsigned char) (length>>24);
101		if (length >= (1<<16))
102			*(*buf)++ = (unsigned char) ((length>>16)&0xff);
103#endif
104		if (length >= (1<<8))
105			*(*buf)++ = (unsigned char) ((length>>8)&0xff);
106		*(*buf)++ = (unsigned char) (length&0xff);
107	}
108}
109
110/* returns decoded length, or < 0 on failure.  Advances buf and
111   decrements bufsize */
112
113static int
114der_read_length(unsigned char **buf, int *bufsize)
115{
116	unsigned char sf;
117	int ret;
118
119	if (*bufsize < 1)
120		return(-1);
121	sf = *(*buf)++;
122	(*bufsize)--;
123	if (sf & 0x80) {
124		if ((sf &= 0x7f) > ((*bufsize)-1))
125			return(-1);
126		if (sf > SIZEOF_INT)
127			return (-1);
128		ret = 0;
129		for (; sf; sf--) {
130			ret = (ret<<8) + (*(*buf)++);
131			(*bufsize)--;
132		}
133	} else {
134		ret = sf;
135	}
136
137	return(ret);
138}
139
140/* returns the length of a token, given the mech oid and the body size */
141
142int
143g_token_size(struct xdr_netobj *mech, unsigned int body_size)
144{
145	/* set body_size to sequence contents size */
146	body_size += 2 + (int) mech->len;         /* NEED overflow check */
147	return(1 + der_length_size(body_size) + body_size);
148}
149
150EXPORT_SYMBOL_GPL(g_token_size);
151
152/* fills in a buffer with the token header.  The buffer is assumed to
153   be the right size.  buf is advanced past the token header */
154
155void
156g_make_token_header(struct xdr_netobj *mech, int body_size, unsigned char **buf)
157{
158	*(*buf)++ = 0x60;
159	der_write_length(buf, 2 + mech->len + body_size);
160	*(*buf)++ = 0x06;
161	*(*buf)++ = (unsigned char) mech->len;
162	TWRITE_STR(*buf, mech->data, ((int) mech->len));
163}
164
165EXPORT_SYMBOL_GPL(g_make_token_header);
166
167/*
168 * Given a buffer containing a token, reads and verifies the token,
169 * leaving buf advanced past the token header, and setting body_size
170 * to the number of remaining bytes.  Returns 0 on success,
171 * G_BAD_TOK_HEADER for a variety of errors, and G_WRONG_MECH if the
172 * mechanism in the token does not match the mech argument.  buf and
173 * *body_size are left unmodified on error.
174 */
175u32
176g_verify_token_header(struct xdr_netobj *mech, int *body_size,
177		      unsigned char **buf_in, int toksize)
178{
179	unsigned char *buf = *buf_in;
180	int seqsize;
181	struct xdr_netobj toid;
182	int ret = 0;
183
184	if ((toksize-=1) < 0)
185		return(G_BAD_TOK_HEADER);
186	if (*buf++ != 0x60)
187		return(G_BAD_TOK_HEADER);
188
189	if ((seqsize = der_read_length(&buf, &toksize)) < 0)
190		return(G_BAD_TOK_HEADER);
191
192	if (seqsize != toksize)
193		return(G_BAD_TOK_HEADER);
194
195	if ((toksize-=1) < 0)
196		return(G_BAD_TOK_HEADER);
197	if (*buf++ != 0x06)
198		return(G_BAD_TOK_HEADER);
199
200	if ((toksize-=1) < 0)
201		return(G_BAD_TOK_HEADER);
202	toid.len = *buf++;
203
204	if ((toksize-=toid.len) < 0)
205		return(G_BAD_TOK_HEADER);
206	toid.data = buf;
207	buf+=toid.len;
208
209	if (! g_OID_equal(&toid, mech))
210		ret = G_WRONG_MECH;
211
212   /* G_WRONG_MECH is not returned immediately because it's more important
213      to return G_BAD_TOK_HEADER if the token header is in fact bad */
214
215	if ((toksize-=2) < 0)
216		return(G_BAD_TOK_HEADER);
217
218	if (ret)
219		return(ret);
220
221	if (!ret) {
222		*buf_in = buf;
223		*body_size = toksize;
224	}
225
226	return(ret);
227}
228
229EXPORT_SYMBOL_GPL(g_verify_token_header);
230