aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2009-09-13 21:17:46 -0400
committerDavid S. Miller <davem@davemloft.net>2009-09-15 05:44:33 -0400
commit99455153d0670ba110e6a3b855b8369bcbd11120 (patch)
tree166ba6e3046654f7d1cd5f0debdcae1aa8938080
parented6dd18b5aceb322da9840f01a68d648e91c8a72 (diff)
RxRPC: Parse security index 5 keys (Kerberos 5)
Parse RxRPC security index 5 type keys (Kerberos 5 tokens). Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/keys/rxrpc-type.h52
-rw-r--r--net/rxrpc/ar-key.c577
2 files changed, 589 insertions, 40 deletions
diff --git a/include/keys/rxrpc-type.h b/include/keys/rxrpc-type.h
index c0d91218fdd3..5eb23571b425 100644
--- a/include/keys/rxrpc-type.h
+++ b/include/keys/rxrpc-type.h
@@ -36,6 +36,54 @@ struct rxkad_key {
36}; 36};
37 37
38/* 38/*
39 * Kerberos 5 principal
40 * name/name/name@realm
41 */
42struct krb5_principal {
43 u8 n_name_parts; /* N of parts of the name part of the principal */
44 char **name_parts; /* parts of the name part of the principal */
45 char *realm; /* parts of the realm part of the principal */
46};
47
48/*
49 * Kerberos 5 tagged data
50 */
51struct krb5_tagged_data {
52 /* for tag value, see /usr/include/krb5/krb5.h
53 * - KRB5_AUTHDATA_* for auth data
54 * -
55 */
56 int32_t tag;
57 uint32_t data_len;
58 u8 *data;
59};
60
61/*
62 * RxRPC key for Kerberos V (type-5 security)
63 */
64struct rxk5_key {
65 uint64_t authtime; /* time at which auth token generated */
66 uint64_t starttime; /* time at which auth token starts */
67 uint64_t endtime; /* time at which auth token expired */
68 uint64_t renew_till; /* time to which auth token can be renewed */
69 int32_t is_skey; /* T if ticket is encrypted in another ticket's
70 * skey */
71 int32_t flags; /* mask of TKT_FLG_* bits (krb5/krb5.h) */
72 struct krb5_principal client; /* client principal name */
73 struct krb5_principal server; /* server principal name */
74 uint16_t ticket_len; /* length of ticket */
75 uint16_t ticket2_len; /* length of second ticket */
76 u8 n_authdata; /* number of authorisation data elements */
77 u8 n_addresses; /* number of addresses */
78 struct krb5_tagged_data session; /* session data; tag is enctype */
79 struct krb5_tagged_data *addresses; /* addresses */
80 u8 *ticket; /* krb5 ticket */
81 u8 *ticket2; /* second krb5 ticket, if related to ticket (via
82 * DUPLICATE-SKEY or ENC-TKT-IN-SKEY) */
83 struct krb5_tagged_data *authdata; /* authorisation data */
84};
85
86/*
39 * list of tokens attached to an rxrpc key 87 * list of tokens attached to an rxrpc key
40 */ 88 */
41struct rxrpc_key_token { 89struct rxrpc_key_token {
@@ -43,6 +91,7 @@ struct rxrpc_key_token {
43 struct rxrpc_key_token *next; /* the next token in the list */ 91 struct rxrpc_key_token *next; /* the next token in the list */
44 union { 92 union {
45 struct rxkad_key *kad; 93 struct rxkad_key *kad;
94 struct rxk5_key *k5;
46 }; 95 };
47}; 96};
48 97
@@ -64,8 +113,11 @@ struct rxrpc_key_data_v1 {
64 * - based on openafs-1.4.10/src/auth/afs_token.xg 113 * - based on openafs-1.4.10/src/auth/afs_token.xg
65 */ 114 */
66#define AFSTOKEN_LENGTH_MAX 16384 /* max payload size */ 115#define AFSTOKEN_LENGTH_MAX 16384 /* max payload size */
116#define AFSTOKEN_STRING_MAX 256 /* max small string length */
117#define AFSTOKEN_DATA_MAX 64 /* max small data length */
67#define AFSTOKEN_CELL_MAX 64 /* max cellname length */ 118#define AFSTOKEN_CELL_MAX 64 /* max cellname length */
68#define AFSTOKEN_MAX 8 /* max tokens per payload */ 119#define AFSTOKEN_MAX 8 /* max tokens per payload */
120#define AFSTOKEN_BDATALN_MAX 16384 /* max big data length */
69#define AFSTOKEN_RK_TIX_MAX 12000 /* max RxKAD ticket size */ 121#define AFSTOKEN_RK_TIX_MAX 12000 /* max RxKAD ticket size */
70#define AFSTOKEN_GK_KEY_MAX 64 /* max GSSAPI key size */ 122#define AFSTOKEN_GK_KEY_MAX 64 /* max GSSAPI key size */
71#define AFSTOKEN_GK_TOKEN_MAX 16384 /* max GSSAPI token size */ 123#define AFSTOKEN_GK_TOKEN_MAX 16384 /* max GSSAPI token size */
diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c
index bf4d623ee1ce..44836f6c9643 100644
--- a/net/rxrpc/ar-key.c
+++ b/net/rxrpc/ar-key.c
@@ -64,7 +64,7 @@ struct key_type key_type_rxrpc_s = {
64static int rxrpc_instantiate_xdr_rxkad(struct key *key, const __be32 *xdr, 64static int rxrpc_instantiate_xdr_rxkad(struct key *key, const __be32 *xdr,
65 unsigned toklen) 65 unsigned toklen)
66{ 66{
67 struct rxrpc_key_token *token; 67 struct rxrpc_key_token *token, **pptoken;
68 size_t plen; 68 size_t plen;
69 u32 tktlen; 69 u32 tktlen;
70 int ret; 70 int ret;
@@ -129,13 +129,398 @@ static int rxrpc_instantiate_xdr_rxkad(struct key *key, const __be32 *xdr,
129 key->type_data.x[0]++; 129 key->type_data.x[0]++;
130 130
131 /* attach the data */ 131 /* attach the data */
132 token->next = key->payload.data; 132 for (pptoken = (struct rxrpc_key_token **)&key->payload.data;
133 key->payload.data = token; 133 *pptoken;
134 pptoken = &(*pptoken)->next)
135 continue;
136 *pptoken = token;
137 if (token->kad->expiry < key->expiry)
138 key->expiry = token->kad->expiry;
139
140 _leave(" = 0");
141 return 0;
142}
143
144static void rxrpc_free_krb5_principal(struct krb5_principal *princ)
145{
146 int loop;
147
148 if (princ->name_parts) {
149 for (loop = princ->n_name_parts - 1; loop >= 0; loop--)
150 kfree(princ->name_parts[loop]);
151 kfree(princ->name_parts);
152 }
153 kfree(princ->realm);
154}
155
156static void rxrpc_free_krb5_tagged(struct krb5_tagged_data *td)
157{
158 kfree(td->data);
159}
160
161/*
162 * free up an RxK5 token
163 */
164static void rxrpc_rxk5_free(struct rxk5_key *rxk5)
165{
166 int loop;
167
168 rxrpc_free_krb5_principal(&rxk5->client);
169 rxrpc_free_krb5_principal(&rxk5->server);
170 rxrpc_free_krb5_tagged(&rxk5->session);
171
172 if (rxk5->addresses) {
173 for (loop = rxk5->n_addresses - 1; loop >= 0; loop--)
174 rxrpc_free_krb5_tagged(&rxk5->addresses[loop]);
175 kfree(rxk5->addresses);
176 }
177 if (rxk5->authdata) {
178 for (loop = rxk5->n_authdata - 1; loop >= 0; loop--)
179 rxrpc_free_krb5_tagged(&rxk5->authdata[loop]);
180 kfree(rxk5->authdata);
181 }
182
183 kfree(rxk5->ticket);
184 kfree(rxk5->ticket2);
185 kfree(rxk5);
186}
187
188/*
189 * extract a krb5 principal
190 */
191static int rxrpc_krb5_decode_principal(struct krb5_principal *princ,
192 const __be32 **_xdr,
193 unsigned *_toklen)
194{
195 const __be32 *xdr = *_xdr;
196 unsigned toklen = *_toklen, n_parts, loop, tmp;
197
198 /* there must be at least one name, and at least #names+1 length
199 * words */
200 if (toklen <= 12)
201 return -EINVAL;
202
203 _enter(",{%x,%x,%x},%u",
204 ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), toklen);
205
206 n_parts = ntohl(*xdr++);
207 toklen -= 4;
208 if (n_parts <= 0 || n_parts > AFSTOKEN_K5_COMPONENTS_MAX)
209 return -EINVAL;
210 princ->n_name_parts = n_parts;
211
212 if (toklen <= (n_parts + 1) * 4)
213 return -EINVAL;
214
215 princ->name_parts = kcalloc(sizeof(char *), n_parts, GFP_KERNEL);
216 if (!princ->name_parts)
217 return -ENOMEM;
218
219 for (loop = 0; loop < n_parts; loop++) {
220 if (toklen < 4)
221 return -EINVAL;
222 tmp = ntohl(*xdr++);
223 toklen -= 4;
224 if (tmp <= 0 || tmp > AFSTOKEN_STRING_MAX)
225 return -EINVAL;
226 if (tmp > toklen)
227 return -EINVAL;
228 princ->name_parts[loop] = kmalloc(tmp + 1, GFP_KERNEL);
229 if (!princ->name_parts[loop])
230 return -ENOMEM;
231 memcpy(princ->name_parts[loop], xdr, tmp);
232 princ->name_parts[loop][tmp] = 0;
233 tmp = (tmp + 3) & ~3;
234 toklen -= tmp;
235 xdr += tmp >> 2;
236 }
237
238 if (toklen < 4)
239 return -EINVAL;
240 tmp = ntohl(*xdr++);
241 toklen -= 4;
242 if (tmp <= 0 || tmp > AFSTOKEN_K5_REALM_MAX)
243 return -EINVAL;
244 if (tmp > toklen)
245 return -EINVAL;
246 princ->realm = kmalloc(tmp + 1, GFP_KERNEL);
247 if (!princ->realm)
248 return -ENOMEM;
249 memcpy(princ->realm, xdr, tmp);
250 princ->realm[tmp] = 0;
251 tmp = (tmp + 3) & ~3;
252 toklen -= tmp;
253 xdr += tmp >> 2;
254
255 _debug("%s/...@%s", princ->name_parts[0], princ->realm);
256
257 *_xdr = xdr;
258 *_toklen = toklen;
259 _leave(" = 0 [toklen=%u]", toklen);
260 return 0;
261}
262
263/*
264 * extract a piece of krb5 tagged data
265 */
266static int rxrpc_krb5_decode_tagged_data(struct krb5_tagged_data *td,
267 size_t max_data_size,
268 const __be32 **_xdr,
269 unsigned *_toklen)
270{
271 const __be32 *xdr = *_xdr;
272 unsigned toklen = *_toklen, len;
273
274 /* there must be at least one tag and one length word */
275 if (toklen <= 8)
276 return -EINVAL;
277
278 _enter(",%zu,{%x,%x},%u",
279 max_data_size, ntohl(xdr[0]), ntohl(xdr[1]), toklen);
280
281 td->tag = ntohl(*xdr++);
282 len = ntohl(*xdr++);
283 toklen -= 8;
284 if (len > max_data_size)
285 return -EINVAL;
286 td->data_len = len;
287
288 if (len > 0) {
289 td->data = kmalloc(len, GFP_KERNEL);
290 if (!td->data)
291 return -ENOMEM;
292 memcpy(td->data, xdr, len);
293 len = (len + 3) & ~3;
294 toklen -= len;
295 xdr += len >> 2;
296 }
297
298 _debug("tag %x len %x", td->tag, td->data_len);
299
300 *_xdr = xdr;
301 *_toklen = toklen;
302 _leave(" = 0 [toklen=%u]", toklen);
303 return 0;
304}
305
306/*
307 * extract an array of tagged data
308 */
309static int rxrpc_krb5_decode_tagged_array(struct krb5_tagged_data **_td,
310 u8 *_n_elem,
311 u8 max_n_elem,
312 size_t max_elem_size,
313 const __be32 **_xdr,
314 unsigned *_toklen)
315{
316 struct krb5_tagged_data *td;
317 const __be32 *xdr = *_xdr;
318 unsigned toklen = *_toklen, n_elem, loop;
319 int ret;
320
321 /* there must be at least one count */
322 if (toklen < 4)
323 return -EINVAL;
324
325 _enter(",,%u,%zu,{%x},%u",
326 max_n_elem, max_elem_size, ntohl(xdr[0]), toklen);
327
328 n_elem = ntohl(*xdr++);
329 toklen -= 4;
330 if (n_elem < 0 || n_elem > max_n_elem)
331 return -EINVAL;
332 *_n_elem = n_elem;
333 if (n_elem > 0) {
334 if (toklen <= (n_elem + 1) * 4)
335 return -EINVAL;
336
337 _debug("n_elem %d", n_elem);
338
339 td = kcalloc(sizeof(struct krb5_tagged_data), n_elem,
340 GFP_KERNEL);
341 if (!td)
342 return -ENOMEM;
343 *_td = td;
344
345 for (loop = 0; loop < n_elem; loop++) {
346 ret = rxrpc_krb5_decode_tagged_data(&td[loop],
347 max_elem_size,
348 &xdr, &toklen);
349 if (ret < 0)
350 return ret;
351 }
352 }
353
354 *_xdr = xdr;
355 *_toklen = toklen;
356 _leave(" = 0 [toklen=%u]", toklen);
357 return 0;
358}
359
360/*
361 * extract a krb5 ticket
362 */
363static int rxrpc_krb5_decode_ticket(u8 **_ticket, uint16_t *_tktlen,
364 const __be32 **_xdr, unsigned *_toklen)
365{
366 const __be32 *xdr = *_xdr;
367 unsigned toklen = *_toklen, len;
368
369 /* there must be at least one length word */
370 if (toklen <= 4)
371 return -EINVAL;
372
373 _enter(",{%x},%u", ntohl(xdr[0]), toklen);
374
375 len = ntohl(*xdr++);
376 toklen -= 4;
377 if (len > AFSTOKEN_K5_TIX_MAX)
378 return -EINVAL;
379 *_tktlen = len;
380
381 _debug("ticket len %u", len);
382
383 if (len > 0) {
384 *_ticket = kmalloc(len, GFP_KERNEL);
385 if (!*_ticket)
386 return -ENOMEM;
387 memcpy(*_ticket, xdr, len);
388 len = (len + 3) & ~3;
389 toklen -= len;
390 xdr += len >> 2;
391 }
392
393 *_xdr = xdr;
394 *_toklen = toklen;
395 _leave(" = 0 [toklen=%u]", toklen);
396 return 0;
397}
398
399/*
400 * parse an RxK5 type XDR format token
401 * - the caller guarantees we have at least 4 words
402 */
403static int rxrpc_instantiate_xdr_rxk5(struct key *key, const __be32 *xdr,
404 unsigned toklen)
405{
406 struct rxrpc_key_token *token, **pptoken;
407 struct rxk5_key *rxk5;
408 const __be32 *end_xdr = xdr + (toklen >> 2);
409 int ret;
410
411 _enter(",{%x,%x,%x,%x},%u",
412 ntohl(xdr[0]), ntohl(xdr[1]), ntohl(xdr[2]), ntohl(xdr[3]),
413 toklen);
414
415 /* reserve some payload space for this subkey - the length of the token
416 * is a reasonable approximation */
417 ret = key_payload_reserve(key, key->datalen + toklen);
418 if (ret < 0)
419 return ret;
420
421 token = kzalloc(sizeof(*token), GFP_KERNEL);
422 if (!token)
423 return -ENOMEM;
424
425 rxk5 = kzalloc(sizeof(*rxk5), GFP_KERNEL);
426 if (!rxk5) {
427 kfree(token);
428 return -ENOMEM;
429 }
430
431 token->security_index = RXRPC_SECURITY_RXK5;
432 token->k5 = rxk5;
433
434 /* extract the principals */
435 ret = rxrpc_krb5_decode_principal(&rxk5->client, &xdr, &toklen);
436 if (ret < 0)
437 goto error;
438 ret = rxrpc_krb5_decode_principal(&rxk5->server, &xdr, &toklen);
439 if (ret < 0)
440 goto error;
441
442 /* extract the session key and the encoding type (the tag field ->
443 * ENCTYPE_xxx) */
444 ret = rxrpc_krb5_decode_tagged_data(&rxk5->session, AFSTOKEN_DATA_MAX,
445 &xdr, &toklen);
446 if (ret < 0)
447 goto error;
448
449 if (toklen < 4 * 8 + 2 * 4)
450 goto inval;
451 rxk5->authtime = be64_to_cpup((const __be64 *) xdr);
452 xdr += 2;
453 rxk5->starttime = be64_to_cpup((const __be64 *) xdr);
454 xdr += 2;
455 rxk5->endtime = be64_to_cpup((const __be64 *) xdr);
456 xdr += 2;
457 rxk5->renew_till = be64_to_cpup((const __be64 *) xdr);
458 xdr += 2;
459 rxk5->is_skey = ntohl(*xdr++);
460 rxk5->flags = ntohl(*xdr++);
461 toklen -= 4 * 8 + 2 * 4;
462
463 _debug("times: a=%llx s=%llx e=%llx rt=%llx",
464 rxk5->authtime, rxk5->starttime, rxk5->endtime,
465 rxk5->renew_till);
466 _debug("is_skey=%x flags=%x", rxk5->is_skey, rxk5->flags);
467
468 /* extract the permitted client addresses */
469 ret = rxrpc_krb5_decode_tagged_array(&rxk5->addresses,
470 &rxk5->n_addresses,
471 AFSTOKEN_K5_ADDRESSES_MAX,
472 AFSTOKEN_DATA_MAX,
473 &xdr, &toklen);
474 if (ret < 0)
475 goto error;
476
477 ASSERTCMP((end_xdr - xdr) << 2, ==, toklen);
478
479 /* extract the tickets */
480 ret = rxrpc_krb5_decode_ticket(&rxk5->ticket, &rxk5->ticket_len,
481 &xdr, &toklen);
482 if (ret < 0)
483 goto error;
484 ret = rxrpc_krb5_decode_ticket(&rxk5->ticket2, &rxk5->ticket2_len,
485 &xdr, &toklen);
486 if (ret < 0)
487 goto error;
488
489 ASSERTCMP((end_xdr - xdr) << 2, ==, toklen);
490
491 /* extract the typed auth data */
492 ret = rxrpc_krb5_decode_tagged_array(&rxk5->authdata,
493 &rxk5->n_authdata,
494 AFSTOKEN_K5_AUTHDATA_MAX,
495 AFSTOKEN_BDATALN_MAX,
496 &xdr, &toklen);
497 if (ret < 0)
498 goto error;
499
500 ASSERTCMP((end_xdr - xdr) << 2, ==, toklen);
501
502 if (toklen != 0)
503 goto inval;
504
505 /* attach the payload to the key */
506 for (pptoken = (struct rxrpc_key_token **)&key->payload.data;
507 *pptoken;
508 pptoken = &(*pptoken)->next)
509 continue;
510 *pptoken = token;
134 if (token->kad->expiry < key->expiry) 511 if (token->kad->expiry < key->expiry)
135 key->expiry = token->kad->expiry; 512 key->expiry = token->kad->expiry;
136 513
137 _leave(" = 0"); 514 _leave(" = 0");
138 return 0; 515 return 0;
516
517inval:
518 ret = -EINVAL;
519error:
520 rxrpc_rxk5_free(rxk5);
521 kfree(token);
522 _leave(" = %d", ret);
523 return ret;
139} 524}
140 525
141/* 526/*
@@ -228,6 +613,8 @@ static int rxrpc_instantiate_xdr(struct key *key, const void *data, size_t datal
228 sec_ix = ntohl(*xdr++); 613 sec_ix = ntohl(*xdr++);
229 toklen -= 4; 614 toklen -= 4;
230 615
616 _debug("TOKEN type=%u [%p-%p]", sec_ix, xdr, token);
617
231 switch (sec_ix) { 618 switch (sec_ix) {
232 case RXRPC_SECURITY_RXKAD: 619 case RXRPC_SECURITY_RXKAD:
233 ret = rxrpc_instantiate_xdr_rxkad(key, xdr, toklen); 620 ret = rxrpc_instantiate_xdr_rxkad(key, xdr, toklen);
@@ -235,6 +622,12 @@ static int rxrpc_instantiate_xdr(struct key *key, const void *data, size_t datal
235 goto error; 622 goto error;
236 break; 623 break;
237 624
625 case RXRPC_SECURITY_RXK5:
626 ret = rxrpc_instantiate_xdr_rxk5(key, xdr, toklen);
627 if (ret != 0)
628 goto error;
629 break;
630
238 default: 631 default:
239 ret = -EPROTONOSUPPORT; 632 ret = -EPROTONOSUPPORT;
240 goto error; 633 goto error;
@@ -412,6 +805,10 @@ static void rxrpc_destroy(struct key *key)
412 case RXRPC_SECURITY_RXKAD: 805 case RXRPC_SECURITY_RXKAD:
413 kfree(token->kad); 806 kfree(token->kad);
414 break; 807 break;
808 case RXRPC_SECURITY_RXK5:
809 if (token->k5)
810 rxrpc_rxk5_free(token->k5);
811 break;
415 default: 812 default:
416 printk(KERN_ERR "Unknown token type %x on rxrpc key\n", 813 printk(KERN_ERR "Unknown token type %x on rxrpc key\n",
417 token->security_index); 814 token->security_index);
@@ -602,10 +999,13 @@ EXPORT_SYMBOL(rxrpc_get_null_key);
602static long rxrpc_read(const struct key *key, 999static long rxrpc_read(const struct key *key,
603 char __user *buffer, size_t buflen) 1000 char __user *buffer, size_t buflen)
604{ 1001{
605 struct rxrpc_key_token *token; 1002 const struct rxrpc_key_token *token;
606 size_t size, toksize; 1003 const struct krb5_principal *princ;
607 __be32 __user *xdr; 1004 size_t size;
608 u32 cnlen, tktlen, ntoks, zero; 1005 __be32 __user *xdr, *oldxdr;
1006 u32 cnlen, toksize, ntoks, tok, zero;
1007 u16 toksizes[AFSTOKEN_MAX];
1008 int loop;
609 1009
610 _enter(""); 1010 _enter("");
611 1011
@@ -614,28 +1014,68 @@ static long rxrpc_read(const struct key *key,
614 return -EOPNOTSUPP; 1014 return -EOPNOTSUPP;
615 cnlen = strlen(key->description + 4); 1015 cnlen = strlen(key->description + 4);
616 1016
1017#define RND(X) (((X) + 3) & ~3)
1018
617 /* AFS keys we return in XDR form, so we need to work out the size of 1019 /* AFS keys we return in XDR form, so we need to work out the size of
618 * the XDR */ 1020 * the XDR */
619 size = 2 * 4; /* flags, cellname len */ 1021 size = 2 * 4; /* flags, cellname len */
620 size += (cnlen + 3) & ~3; /* cellname */ 1022 size += RND(cnlen); /* cellname */
621 size += 1 * 4; /* token count */ 1023 size += 1 * 4; /* token count */
622 1024
623 ntoks = 0; 1025 ntoks = 0;
624 for (token = key->payload.data; token; token = token->next) { 1026 for (token = key->payload.data; token; token = token->next) {
1027 toksize = 4; /* sec index */
1028
625 switch (token->security_index) { 1029 switch (token->security_index) {
626 case RXRPC_SECURITY_RXKAD: 1030 case RXRPC_SECURITY_RXKAD:
627 size += 2 * 4; /* length, security index (switch ID) */ 1031 toksize += 8 * 4; /* viceid, kvno, key*2, begin,
628 size += 8 * 4; /* viceid, kvno, key*2, begin, end, 1032 * end, primary, tktlen */
629 * primary, tktlen */ 1033 toksize += RND(token->kad->ticket_len);
630 size += (token->kad->ticket_len + 3) & ~3; /* ticket */
631 ntoks++;
632 break; 1034 break;
633 1035
634 default: /* can't encode */ 1036 case RXRPC_SECURITY_RXK5:
1037 princ = &token->k5->client;
1038 toksize += 4 + princ->n_name_parts * 4;
1039 for (loop = 0; loop < princ->n_name_parts; loop++)
1040 toksize += RND(strlen(princ->name_parts[loop]));
1041 toksize += 4 + RND(strlen(princ->realm));
1042
1043 princ = &token->k5->server;
1044 toksize += 4 + princ->n_name_parts * 4;
1045 for (loop = 0; loop < princ->n_name_parts; loop++)
1046 toksize += RND(strlen(princ->name_parts[loop]));
1047 toksize += 4 + RND(strlen(princ->realm));
1048
1049 toksize += 8 + RND(token->k5->session.data_len);
1050
1051 toksize += 4 * 8 + 2 * 4;
1052
1053 toksize += 4 + token->k5->n_addresses * 8;
1054 for (loop = 0; loop < token->k5->n_addresses; loop++)
1055 toksize += RND(token->k5->addresses[loop].data_len);
1056
1057 toksize += 4 + RND(token->k5->ticket_len);
1058 toksize += 4 + RND(token->k5->ticket2_len);
1059
1060 toksize += 4 + token->k5->n_authdata * 8;
1061 for (loop = 0; loop < token->k5->n_authdata; loop++)
1062 toksize += RND(token->k5->authdata[loop].data_len);
635 break; 1063 break;
1064
1065 default: /* we have a ticket we can't encode */
1066 BUG();
1067 continue;
636 } 1068 }
1069
1070 _debug("token[%u]: toksize=%u", ntoks, toksize);
1071 ASSERTCMP(toksize, <=, AFSTOKEN_LENGTH_MAX);
1072
1073 toksizes[ntoks++] = toksize;
1074 size += toksize + 4; /* each token has a length word */
637 } 1075 }
638 1076
1077#undef RND
1078
639 if (!buffer || buflen < size) 1079 if (!buffer || buflen < size)
640 return size; 1080 return size;
641 1081
@@ -647,52 +1087,109 @@ static long rxrpc_read(const struct key *key,
647 if (put_user(y, xdr++) < 0) \ 1087 if (put_user(y, xdr++) < 0) \
648 goto fault; \ 1088 goto fault; \
649 } while(0) 1089 } while(0)
1090#define ENCODE_DATA(l, s) \
1091 do { \
1092 u32 _l = (l); \
1093 ENCODE(l); \
1094 if (copy_to_user(xdr, (s), _l) != 0) \
1095 goto fault; \
1096 if (_l & 3 && \
1097 copy_to_user((u8 *)xdr + _l, &zero, 4 - (_l & 3)) != 0) \
1098 goto fault; \
1099 xdr += (_l + 3) >> 2; \
1100 } while(0)
1101#define ENCODE64(x) \
1102 do { \
1103 __be64 y = cpu_to_be64(x); \
1104 if (copy_to_user(xdr, &y, 8) != 0) \
1105 goto fault; \
1106 xdr += 8 >> 2; \
1107 } while(0)
1108#define ENCODE_STR(s) \
1109 do { \
1110 const char *_s = (s); \
1111 ENCODE_DATA(strlen(_s), _s); \
1112 } while(0)
650 1113
651 ENCODE(0); /* flags */ 1114 ENCODE(0); /* flags */
652 ENCODE(cnlen); /* cellname length */ 1115 ENCODE_DATA(cnlen, key->description + 4); /* cellname */
653 if (copy_to_user(xdr, key->description + 4, cnlen) != 0) 1116 ENCODE(ntoks);
654 goto fault;
655 if (cnlen & 3 &&
656 copy_to_user((u8 *)xdr + cnlen, &zero, 4 - (cnlen & 3)) != 0)
657 goto fault;
658 xdr += (cnlen + 3) >> 2;
659 ENCODE(ntoks); /* token count */
660 1117
1118 tok = 0;
661 for (token = key->payload.data; token; token = token->next) { 1119 for (token = key->payload.data; token; token = token->next) {
662 toksize = 1 * 4; /* sec index */ 1120 toksize = toksizes[tok++];
1121 ENCODE(toksize);
1122 oldxdr = xdr;
1123 ENCODE(token->security_index);
663 1124
664 switch (token->security_index) { 1125 switch (token->security_index) {
665 case RXRPC_SECURITY_RXKAD: 1126 case RXRPC_SECURITY_RXKAD:
666 toksize += 8 * 4;
667 toksize += (token->kad->ticket_len + 3) & ~3;
668 ENCODE(toksize);
669 ENCODE(token->security_index);
670 ENCODE(token->kad->vice_id); 1127 ENCODE(token->kad->vice_id);
671 ENCODE(token->kad->kvno); 1128 ENCODE(token->kad->kvno);
672 if (copy_to_user(xdr, token->kad->session_key, 8) != 0) 1129 ENCODE_DATA(8, token->kad->session_key);
673 goto fault;
674 xdr += 8 >> 2;
675 ENCODE(token->kad->start); 1130 ENCODE(token->kad->start);
676 ENCODE(token->kad->expiry); 1131 ENCODE(token->kad->expiry);
677 ENCODE(token->kad->primary_flag); 1132 ENCODE(token->kad->primary_flag);
678 tktlen = token->kad->ticket_len; 1133 ENCODE_DATA(token->kad->ticket_len, token->kad->ticket);
679 ENCODE(tktlen); 1134 break;
680 if (copy_to_user(xdr, token->kad->ticket, tktlen) != 0) 1135
681 goto fault; 1136 case RXRPC_SECURITY_RXK5:
682 if (tktlen & 3 && 1137 princ = &token->k5->client;
683 copy_to_user((u8 *)xdr + tktlen, &zero, 1138 ENCODE(princ->n_name_parts);
684 4 - (tktlen & 3)) != 0) 1139 for (loop = 0; loop < princ->n_name_parts; loop++)
685 goto fault; 1140 ENCODE_STR(princ->name_parts[loop]);
686 xdr += (tktlen + 3) >> 2; 1141 ENCODE_STR(princ->realm);
1142
1143 princ = &token->k5->server;
1144 ENCODE(princ->n_name_parts);
1145 for (loop = 0; loop < princ->n_name_parts; loop++)
1146 ENCODE_STR(princ->name_parts[loop]);
1147 ENCODE_STR(princ->realm);
1148
1149 ENCODE(token->k5->session.tag);
1150 ENCODE_DATA(token->k5->session.data_len,
1151 token->k5->session.data);
1152
1153 ENCODE64(token->k5->authtime);
1154 ENCODE64(token->k5->starttime);
1155 ENCODE64(token->k5->endtime);
1156 ENCODE64(token->k5->renew_till);
1157 ENCODE(token->k5->is_skey);
1158 ENCODE(token->k5->flags);
1159
1160 ENCODE(token->k5->n_addresses);
1161 for (loop = 0; loop < token->k5->n_addresses; loop++) {
1162 ENCODE(token->k5->addresses[loop].tag);
1163 ENCODE_DATA(token->k5->addresses[loop].data_len,
1164 token->k5->addresses[loop].data);
1165 }
1166
1167 ENCODE_DATA(token->k5->ticket_len, token->k5->ticket);
1168 ENCODE_DATA(token->k5->ticket2_len, token->k5->ticket2);
1169
1170 ENCODE(token->k5->n_authdata);
1171 for (loop = 0; loop < token->k5->n_authdata; loop++) {
1172 ENCODE(token->k5->authdata[loop].tag);
1173 ENCODE_DATA(token->k5->authdata[loop].data_len,
1174 token->k5->authdata[loop].data);
1175 }
687 break; 1176 break;
688 1177
689 default: 1178 default:
1179 BUG();
690 break; 1180 break;
691 } 1181 }
1182
1183 ASSERTCMP((unsigned long)xdr - (unsigned long)oldxdr, ==,
1184 toksize);
692 } 1185 }
693 1186
1187#undef ENCODE_STR
1188#undef ENCODE_DATA
1189#undef ENCODE64
694#undef ENCODE 1190#undef ENCODE
695 1191
1192 ASSERTCMP(tok, ==, ntoks);
696 ASSERTCMP((char __user *) xdr - buffer, ==, size); 1193 ASSERTCMP((char __user *) xdr - buffer, ==, size);
697 _leave(" = %zu", size); 1194 _leave(" = %zu", size);
698 return size; 1195 return size;