diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /net/sunrpc/auth_gss/gss_generic_token.c |
Linux-2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'net/sunrpc/auth_gss/gss_generic_token.c')
-rw-r--r-- | net/sunrpc/auth_gss/gss_generic_token.c | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/net/sunrpc/auth_gss/gss_generic_token.c b/net/sunrpc/auth_gss/gss_generic_token.c new file mode 100644 index 000000000000..826df44e7fca --- /dev/null +++ b/net/sunrpc/auth_gss/gss_generic_token.c | |||
@@ -0,0 +1,235 @@ | |||
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/slab.h> | ||
37 | #include <linux/string.h> | ||
38 | #include <linux/sunrpc/sched.h> | ||
39 | #include <linux/sunrpc/gss_asn1.h> | ||
40 | |||
41 | |||
42 | #ifdef RPC_DEBUG | ||
43 | # define RPCDBG_FACILITY RPCDBG_AUTH | ||
44 | #endif | ||
45 | |||
46 | |||
47 | /* TWRITE_STR from gssapiP_generic.h */ | ||
48 | #define TWRITE_STR(ptr, str, len) \ | ||
49 | memcpy((ptr), (char *) (str), (len)); \ | ||
50 | (ptr) += (len); | ||
51 | |||
52 | /* XXXX this code currently makes the assumption that a mech oid will | ||
53 | never be longer than 127 bytes. This assumption is not inherent in | ||
54 | the interfaces, so the code can be fixed if the OSI namespace | ||
55 | balloons unexpectedly. */ | ||
56 | |||
57 | /* Each token looks like this: | ||
58 | |||
59 | 0x60 tag for APPLICATION 0, SEQUENCE | ||
60 | (constructed, definite-length) | ||
61 | <length> possible multiple bytes, need to parse/generate | ||
62 | 0x06 tag for OBJECT IDENTIFIER | ||
63 | <moid_length> compile-time constant string (assume 1 byte) | ||
64 | <moid_bytes> compile-time constant string | ||
65 | <inner_bytes> the ANY containing the application token | ||
66 | bytes 0,1 are the token type | ||
67 | bytes 2,n are the token data | ||
68 | |||
69 | For the purposes of this abstraction, the token "header" consists of | ||
70 | the sequence tag and length octets, the mech OID DER encoding, and the | ||
71 | first two inner bytes, which indicate the token type. The token | ||
72 | "body" consists of everything else. | ||
73 | |||
74 | */ | ||
75 | |||
76 | static int | ||
77 | der_length_size( int length) | ||
78 | { | ||
79 | if (length < (1<<7)) | ||
80 | return(1); | ||
81 | else if (length < (1<<8)) | ||
82 | return(2); | ||
83 | #if (SIZEOF_INT == 2) | ||
84 | else | ||
85 | return(3); | ||
86 | #else | ||
87 | else if (length < (1<<16)) | ||
88 | return(3); | ||
89 | else if (length < (1<<24)) | ||
90 | return(4); | ||
91 | else | ||
92 | return(5); | ||
93 | #endif | ||
94 | } | ||
95 | |||
96 | static void | ||
97 | der_write_length(unsigned char **buf, int length) | ||
98 | { | ||
99 | if (length < (1<<7)) { | ||
100 | *(*buf)++ = (unsigned char) length; | ||
101 | } else { | ||
102 | *(*buf)++ = (unsigned char) (der_length_size(length)+127); | ||
103 | #if (SIZEOF_INT > 2) | ||
104 | if (length >= (1<<24)) | ||
105 | *(*buf)++ = (unsigned char) (length>>24); | ||
106 | if (length >= (1<<16)) | ||
107 | *(*buf)++ = (unsigned char) ((length>>16)&0xff); | ||
108 | #endif | ||
109 | if (length >= (1<<8)) | ||
110 | *(*buf)++ = (unsigned char) ((length>>8)&0xff); | ||
111 | *(*buf)++ = (unsigned char) (length&0xff); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | /* returns decoded length, or < 0 on failure. Advances buf and | ||
116 | decrements bufsize */ | ||
117 | |||
118 | static int | ||
119 | der_read_length(unsigned char **buf, int *bufsize) | ||
120 | { | ||
121 | unsigned char sf; | ||
122 | int ret; | ||
123 | |||
124 | if (*bufsize < 1) | ||
125 | return(-1); | ||
126 | sf = *(*buf)++; | ||
127 | (*bufsize)--; | ||
128 | if (sf & 0x80) { | ||
129 | if ((sf &= 0x7f) > ((*bufsize)-1)) | ||
130 | return(-1); | ||
131 | if (sf > SIZEOF_INT) | ||
132 | return (-1); | ||
133 | ret = 0; | ||
134 | for (; sf; sf--) { | ||
135 | ret = (ret<<8) + (*(*buf)++); | ||
136 | (*bufsize)--; | ||
137 | } | ||
138 | } else { | ||
139 | ret = sf; | ||
140 | } | ||
141 | |||
142 | return(ret); | ||
143 | } | ||
144 | |||
145 | /* returns the length of a token, given the mech oid and the body size */ | ||
146 | |||
147 | int | ||
148 | g_token_size(struct xdr_netobj *mech, unsigned int body_size) | ||
149 | { | ||
150 | /* set body_size to sequence contents size */ | ||
151 | body_size += 4 + (int) mech->len; /* NEED overflow check */ | ||
152 | return(1 + der_length_size(body_size) + body_size); | ||
153 | } | ||
154 | |||
155 | EXPORT_SYMBOL(g_token_size); | ||
156 | |||
157 | /* fills in a buffer with the token header. The buffer is assumed to | ||
158 | be the right size. buf is advanced past the token header */ | ||
159 | |||
160 | void | ||
161 | g_make_token_header(struct xdr_netobj *mech, int body_size, unsigned char **buf) | ||
162 | { | ||
163 | *(*buf)++ = 0x60; | ||
164 | der_write_length(buf, 4 + mech->len + body_size); | ||
165 | *(*buf)++ = 0x06; | ||
166 | *(*buf)++ = (unsigned char) mech->len; | ||
167 | TWRITE_STR(*buf, mech->data, ((int) mech->len)); | ||
168 | } | ||
169 | |||
170 | EXPORT_SYMBOL(g_make_token_header); | ||
171 | |||
172 | /* | ||
173 | * Given a buffer containing a token, reads and verifies the token, | ||
174 | * leaving buf advanced past the token header, and setting body_size | ||
175 | * to the number of remaining bytes. Returns 0 on success, | ||
176 | * G_BAD_TOK_HEADER for a variety of errors, and G_WRONG_MECH if the | ||
177 | * mechanism in the token does not match the mech argument. buf and | ||
178 | * *body_size are left unmodified on error. | ||
179 | */ | ||
180 | u32 | ||
181 | g_verify_token_header(struct xdr_netobj *mech, int *body_size, | ||
182 | unsigned char **buf_in, int toksize) | ||
183 | { | ||
184 | unsigned char *buf = *buf_in; | ||
185 | int seqsize; | ||
186 | struct xdr_netobj toid; | ||
187 | int ret = 0; | ||
188 | |||
189 | if ((toksize-=1) < 0) | ||
190 | return(G_BAD_TOK_HEADER); | ||
191 | if (*buf++ != 0x60) | ||
192 | return(G_BAD_TOK_HEADER); | ||
193 | |||
194 | if ((seqsize = der_read_length(&buf, &toksize)) < 0) | ||
195 | return(G_BAD_TOK_HEADER); | ||
196 | |||
197 | if (seqsize != toksize) | ||
198 | return(G_BAD_TOK_HEADER); | ||
199 | |||
200 | if ((toksize-=1) < 0) | ||
201 | return(G_BAD_TOK_HEADER); | ||
202 | if (*buf++ != 0x06) | ||
203 | return(G_BAD_TOK_HEADER); | ||
204 | |||
205 | if ((toksize-=1) < 0) | ||
206 | return(G_BAD_TOK_HEADER); | ||
207 | toid.len = *buf++; | ||
208 | |||
209 | if ((toksize-=toid.len) < 0) | ||
210 | return(G_BAD_TOK_HEADER); | ||
211 | toid.data = buf; | ||
212 | buf+=toid.len; | ||
213 | |||
214 | if (! g_OID_equal(&toid, mech)) | ||
215 | ret = G_WRONG_MECH; | ||
216 | |||
217 | /* G_WRONG_MECH is not returned immediately because it's more important | ||
218 | to return G_BAD_TOK_HEADER if the token header is in fact bad */ | ||
219 | |||
220 | if ((toksize-=2) < 0) | ||
221 | return(G_BAD_TOK_HEADER); | ||
222 | |||
223 | if (ret) | ||
224 | return(ret); | ||
225 | |||
226 | if (!ret) { | ||
227 | *buf_in = buf; | ||
228 | *body_size = toksize; | ||
229 | } | ||
230 | |||
231 | return(ret); | ||
232 | } | ||
233 | |||
234 | EXPORT_SYMBOL(g_verify_token_header); | ||
235 | |||