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#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
48#define TWRITE_STR(ptr, str, len) \
49 memcpy((ptr), (char *) (str), (len)); \
50 (ptr) += (len);
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
76static int
77der_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
96static void
97der_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
116
117
118static int
119der_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
146
147int
148g_token_size(struct xdr_netobj *mech, unsigned int body_size)
149{
150
151 body_size += 2 + (int) mech->len;
152 return(1 + der_length_size(body_size) + body_size);
153}
154
155EXPORT_SYMBOL_GPL(g_token_size);
156
157
158
159
160void
161g_make_token_header(struct xdr_netobj *mech, int body_size, unsigned char **buf)
162{
163 *(*buf)++ = 0x60;
164 der_write_length(buf, 2 + mech->len + body_size);
165 *(*buf)++ = 0x06;
166 *(*buf)++ = (unsigned char) mech->len;
167 TWRITE_STR(*buf, mech->data, ((int) mech->len));
168}
169
170EXPORT_SYMBOL_GPL(g_make_token_header);
171
172
173
174
175
176
177
178
179
180u32
181g_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
218
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
234EXPORT_SYMBOL_GPL(g_verify_token_header);
235
236