Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0+
2 : : /*
3 : : * GSS Proxy upcall module
4 : : *
5 : : * Copyright (C) 2012 Simo Sorce <simo@redhat.com>
6 : : */
7 : :
8 : : #include <linux/sunrpc/svcauth.h>
9 : : #include "gss_rpc_xdr.h"
10 : :
11 : 0 : static int gssx_enc_bool(struct xdr_stream *xdr, int v)
12 : : {
13 : 0 : __be32 *p;
14 : :
15 : 0 : p = xdr_reserve_space(xdr, 4);
16 [ # # # # : 0 : if (unlikely(p == NULL))
# # # # #
# # # # #
# # ]
17 : : return -ENOSPC;
18 [ # # # # : 0 : *p = v ? xdr_one : xdr_zero;
# # # # #
# ]
19 : 0 : return 0;
20 : : }
21 : :
22 : 0 : static int gssx_dec_bool(struct xdr_stream *xdr, u32 *v)
23 : : {
24 : 0 : __be32 *p;
25 : :
26 : 0 : p = xdr_inline_decode(xdr, 4);
27 [ # # # # : 0 : if (unlikely(p == NULL))
# # # # #
# # # ]
28 : : return -ENOSPC;
29 : 0 : *v = be32_to_cpu(*p);
30 : 0 : return 0;
31 : : }
32 : :
33 : : static int gssx_enc_buffer(struct xdr_stream *xdr,
34 : : const gssx_buffer *buf)
35 : : {
36 : : __be32 *p;
37 : :
38 : : p = xdr_reserve_space(xdr, sizeof(u32) + buf->len);
39 : : if (!p)
40 : : return -ENOSPC;
41 : : xdr_encode_opaque(p, buf->data, buf->len);
42 : : return 0;
43 : : }
44 : :
45 : 0 : static int gssx_enc_in_token(struct xdr_stream *xdr,
46 : : const struct gssp_in_token *in)
47 : : {
48 : 0 : __be32 *p;
49 : :
50 : 0 : p = xdr_reserve_space(xdr, 4);
51 [ # # ]: 0 : if (!p)
52 : : return -ENOSPC;
53 : 0 : *p = cpu_to_be32(in->page_len);
54 : :
55 : : /* all we need to do is to write pages */
56 : 0 : xdr_write_pages(xdr, in->pages, in->page_base, in->page_len);
57 : :
58 : 0 : return 0;
59 : : }
60 : :
61 : :
62 : : static int gssx_dec_buffer(struct xdr_stream *xdr,
63 : : gssx_buffer *buf)
64 : : {
65 : : u32 length;
66 : : __be32 *p;
67 : :
68 : : p = xdr_inline_decode(xdr, 4);
69 : : if (unlikely(p == NULL))
70 : : return -ENOSPC;
71 : :
72 : : length = be32_to_cpup(p);
73 : : p = xdr_inline_decode(xdr, length);
74 : : if (unlikely(p == NULL))
75 : : return -ENOSPC;
76 : :
77 : : if (buf->len == 0) {
78 : : /* we intentionally are not interested in this buffer */
79 : : return 0;
80 : : }
81 : : if (length > buf->len)
82 : : return -ENOSPC;
83 : :
84 : : if (!buf->data) {
85 : : buf->data = kmemdup(p, length, GFP_KERNEL);
86 : : if (!buf->data)
87 : : return -ENOMEM;
88 : : } else {
89 : : memcpy(buf->data, p, length);
90 : : }
91 : : buf->len = length;
92 : : return 0;
93 : : }
94 : :
95 : 0 : static int gssx_enc_option(struct xdr_stream *xdr,
96 : : struct gssx_option *opt)
97 : : {
98 : 0 : int err;
99 : :
100 : 0 : err = gssx_enc_buffer(xdr, &opt->option);
101 [ # # ]: 0 : if (err)
102 : : return err;
103 : 0 : err = gssx_enc_buffer(xdr, &opt->value);
104 : 0 : return err;
105 : : }
106 : :
107 : 0 : static int gssx_dec_option(struct xdr_stream *xdr,
108 : : struct gssx_option *opt)
109 : : {
110 : 0 : int err;
111 : :
112 : 0 : err = gssx_dec_buffer(xdr, &opt->option);
113 [ # # ]: 0 : if (err)
114 : : return err;
115 : 0 : err = gssx_dec_buffer(xdr, &opt->value);
116 : 0 : return err;
117 : : }
118 : :
119 : 0 : static int dummy_enc_opt_array(struct xdr_stream *xdr,
120 : : const struct gssx_option_array *oa)
121 : : {
122 : 0 : __be32 *p;
123 : :
124 : 0 : if (oa->count != 0)
125 : : return -EINVAL;
126 : :
127 : 0 : p = xdr_reserve_space(xdr, 4);
128 [ # # # # : 0 : if (!p)
# # ]
129 : : return -ENOSPC;
130 : 0 : *p = 0;
131 : :
132 : 0 : return 0;
133 : : }
134 : :
135 : : static int dummy_dec_opt_array(struct xdr_stream *xdr,
136 : : struct gssx_option_array *oa)
137 : : {
138 : : struct gssx_option dummy;
139 : : u32 count, i;
140 : : __be32 *p;
141 : :
142 : : p = xdr_inline_decode(xdr, 4);
143 : : if (unlikely(p == NULL))
144 : : return -ENOSPC;
145 : : count = be32_to_cpup(p++);
146 : : memset(&dummy, 0, sizeof(dummy));
147 : : for (i = 0; i < count; i++) {
148 : : gssx_dec_option(xdr, &dummy);
149 : : }
150 : :
151 : : oa->count = 0;
152 : : oa->data = NULL;
153 : : return 0;
154 : : }
155 : :
156 : 0 : static int get_host_u32(struct xdr_stream *xdr, u32 *res)
157 : : {
158 : 0 : __be32 *p;
159 : :
160 : 0 : p = xdr_inline_decode(xdr, 4);
161 [ # # # # : 0 : if (!p)
# # # # ]
162 : : return -EINVAL;
163 : : /* Contents of linux creds are all host-endian: */
164 : 0 : memcpy(res, p, sizeof(u32));
165 : 0 : return 0;
166 : : }
167 : :
168 : 0 : static int gssx_dec_linux_creds(struct xdr_stream *xdr,
169 : : struct svc_cred *creds)
170 : : {
171 : 0 : u32 length;
172 : 0 : __be32 *p;
173 : 0 : u32 tmp;
174 : 0 : u32 N;
175 : 0 : int i, err;
176 : :
177 : 0 : p = xdr_inline_decode(xdr, 4);
178 [ # # ]: 0 : if (unlikely(p == NULL))
179 : : return -ENOSPC;
180 : :
181 [ # # ]: 0 : length = be32_to_cpup(p);
182 : :
183 [ # # ]: 0 : if (length > (3 + NGROUPS_MAX) * sizeof(u32))
184 : : return -ENOSPC;
185 : :
186 : : /* uid */
187 : 0 : err = get_host_u32(xdr, &tmp);
188 : 0 : if (err)
189 : : return err;
190 : 0 : creds->cr_uid = make_kuid(&init_user_ns, tmp);
191 : :
192 : : /* gid */
193 : 0 : err = get_host_u32(xdr, &tmp);
194 : 0 : if (err)
195 : : return err;
196 : 0 : creds->cr_gid = make_kgid(&init_user_ns, tmp);
197 : :
198 : : /* number of additional gid's */
199 : 0 : err = get_host_u32(xdr, &tmp);
200 : 0 : if (err)
201 : : return err;
202 : 0 : N = tmp;
203 [ # # ]: 0 : if ((3 + N) * sizeof(u32) != length)
204 : : return -EINVAL;
205 : 0 : creds->cr_group_info = groups_alloc(N);
206 [ # # ]: 0 : if (creds->cr_group_info == NULL)
207 : : return -ENOMEM;
208 : :
209 : : /* gid's */
210 [ # # ]: 0 : for (i = 0; i < N; i++) {
211 : 0 : kgid_t kgid;
212 : 0 : err = get_host_u32(xdr, &tmp);
213 : 0 : if (err)
214 : 0 : goto out_free_groups;
215 : 0 : err = -EINVAL;
216 [ # # ]: 0 : kgid = make_kgid(&init_user_ns, tmp);
217 [ # # ]: 0 : if (!gid_valid(kgid))
218 : 0 : goto out_free_groups;
219 : 0 : creds->cr_group_info->gid[i] = kgid;
220 : : }
221 : 0 : groups_sort(creds->cr_group_info);
222 : :
223 : 0 : return 0;
224 : : out_free_groups:
225 : 0 : groups_free(creds->cr_group_info);
226 : 0 : return err;
227 : : }
228 : :
229 : : static int gssx_dec_option_array(struct xdr_stream *xdr,
230 : : struct gssx_option_array *oa)
231 : : {
232 : : struct svc_cred *creds;
233 : : u32 count, i;
234 : : __be32 *p;
235 : : int err;
236 : :
237 : : p = xdr_inline_decode(xdr, 4);
238 : : if (unlikely(p == NULL))
239 : : return -ENOSPC;
240 : : count = be32_to_cpup(p++);
241 : : if (!count)
242 : : return 0;
243 : :
244 : : /* we recognize only 1 currently: CREDS_VALUE */
245 : : oa->count = 1;
246 : :
247 : : oa->data = kmalloc(sizeof(struct gssx_option), GFP_KERNEL);
248 : : if (!oa->data)
249 : : return -ENOMEM;
250 : :
251 : : creds = kzalloc(sizeof(struct svc_cred), GFP_KERNEL);
252 : : if (!creds) {
253 : : kfree(oa->data);
254 : : return -ENOMEM;
255 : : }
256 : :
257 : : oa->data[0].option.data = CREDS_VALUE;
258 : : oa->data[0].option.len = sizeof(CREDS_VALUE);
259 : : oa->data[0].value.data = (void *)creds;
260 : : oa->data[0].value.len = 0;
261 : :
262 : : for (i = 0; i < count; i++) {
263 : : gssx_buffer dummy = { 0, NULL };
264 : : u32 length;
265 : :
266 : : /* option buffer */
267 : : p = xdr_inline_decode(xdr, 4);
268 : : if (unlikely(p == NULL))
269 : : return -ENOSPC;
270 : :
271 : : length = be32_to_cpup(p);
272 : : p = xdr_inline_decode(xdr, length);
273 : : if (unlikely(p == NULL))
274 : : return -ENOSPC;
275 : :
276 : : if (length == sizeof(CREDS_VALUE) &&
277 : : memcmp(p, CREDS_VALUE, sizeof(CREDS_VALUE)) == 0) {
278 : : /* We have creds here. parse them */
279 : : err = gssx_dec_linux_creds(xdr, creds);
280 : : if (err)
281 : : return err;
282 : : oa->data[0].value.len = 1; /* presence */
283 : : } else {
284 : : /* consume uninteresting buffer */
285 : : err = gssx_dec_buffer(xdr, &dummy);
286 : : if (err)
287 : : return err;
288 : : }
289 : : }
290 : : return 0;
291 : : }
292 : :
293 : 0 : static int gssx_dec_status(struct xdr_stream *xdr,
294 : : struct gssx_status *status)
295 : : {
296 : 0 : __be32 *p;
297 : 0 : int err;
298 : :
299 : : /* status->major_status */
300 : 0 : p = xdr_inline_decode(xdr, 8);
301 [ # # ]: 0 : if (unlikely(p == NULL))
302 : : return -ENOSPC;
303 : 0 : p = xdr_decode_hyper(p, &status->major_status);
304 : :
305 : : /* status->mech */
306 : 0 : err = gssx_dec_buffer(xdr, &status->mech);
307 [ # # ]: 0 : if (err)
308 : : return err;
309 : :
310 : : /* status->minor_status */
311 : 0 : p = xdr_inline_decode(xdr, 8);
312 [ # # ]: 0 : if (unlikely(p == NULL))
313 : : return -ENOSPC;
314 : 0 : p = xdr_decode_hyper(p, &status->minor_status);
315 : :
316 : : /* status->major_status_string */
317 : 0 : err = gssx_dec_buffer(xdr, &status->major_status_string);
318 [ # # ]: 0 : if (err)
319 : : return err;
320 : :
321 : : /* status->minor_status_string */
322 : 0 : err = gssx_dec_buffer(xdr, &status->minor_status_string);
323 [ # # ]: 0 : if (err)
324 : : return err;
325 : :
326 : : /* status->server_ctx */
327 : 0 : err = gssx_dec_buffer(xdr, &status->server_ctx);
328 [ # # ]: 0 : if (err)
329 : : return err;
330 : :
331 : : /* we assume we have no options for now, so simply consume them */
332 : : /* status->options */
333 : 0 : err = dummy_dec_opt_array(xdr, &status->options);
334 : :
335 : 0 : return err;
336 : : }
337 : :
338 : 0 : static int gssx_enc_call_ctx(struct xdr_stream *xdr,
339 : : const struct gssx_call_ctx *ctx)
340 : : {
341 : 0 : struct gssx_option opt;
342 : 0 : __be32 *p;
343 : 0 : int err;
344 : :
345 : : /* ctx->locale */
346 : 0 : err = gssx_enc_buffer(xdr, &ctx->locale);
347 [ # # ]: 0 : if (err)
348 : : return err;
349 : :
350 : : /* ctx->server_ctx */
351 : 0 : err = gssx_enc_buffer(xdr, &ctx->server_ctx);
352 [ # # ]: 0 : if (err)
353 : : return err;
354 : :
355 : : /* we always want to ask for lucid contexts */
356 : : /* ctx->options */
357 : 0 : p = xdr_reserve_space(xdr, 4);
358 : 0 : *p = cpu_to_be32(2);
359 : :
360 : : /* we want a lucid_v1 context */
361 : 0 : opt.option.data = LUCID_OPTION;
362 : 0 : opt.option.len = sizeof(LUCID_OPTION);
363 : 0 : opt.value.data = LUCID_VALUE;
364 : 0 : opt.value.len = sizeof(LUCID_VALUE);
365 : 0 : err = gssx_enc_option(xdr, &opt);
366 : :
367 : : /* ..and user creds */
368 : 0 : opt.option.data = CREDS_OPTION;
369 : 0 : opt.option.len = sizeof(CREDS_OPTION);
370 : 0 : opt.value.data = CREDS_VALUE;
371 : 0 : opt.value.len = sizeof(CREDS_VALUE);
372 : 0 : err = gssx_enc_option(xdr, &opt);
373 : :
374 : 0 : return err;
375 : : }
376 : :
377 : 0 : static int gssx_dec_name_attr(struct xdr_stream *xdr,
378 : : struct gssx_name_attr *attr)
379 : : {
380 : 0 : int err;
381 : :
382 : : /* attr->attr */
383 : 0 : err = gssx_dec_buffer(xdr, &attr->attr);
384 [ # # ]: 0 : if (err)
385 : : return err;
386 : :
387 : : /* attr->value */
388 : 0 : err = gssx_dec_buffer(xdr, &attr->value);
389 [ # # ]: 0 : if (err)
390 : : return err;
391 : :
392 : : /* attr->extensions */
393 : 0 : err = dummy_dec_opt_array(xdr, &attr->extensions);
394 : :
395 : 0 : return err;
396 : : }
397 : :
398 : 0 : static int dummy_enc_nameattr_array(struct xdr_stream *xdr,
399 : : struct gssx_name_attr_array *naa)
400 : : {
401 : 0 : __be32 *p;
402 : :
403 : 0 : if (naa->count != 0)
404 : : return -EINVAL;
405 : :
406 : 0 : p = xdr_reserve_space(xdr, 4);
407 [ # # ]: 0 : if (!p)
408 : : return -ENOSPC;
409 : 0 : *p = 0;
410 : :
411 : 0 : return 0;
412 : : }
413 : :
414 : : static int dummy_dec_nameattr_array(struct xdr_stream *xdr,
415 : : struct gssx_name_attr_array *naa)
416 : : {
417 : : struct gssx_name_attr dummy = { .attr = {.len = 0} };
418 : : u32 count, i;
419 : : __be32 *p;
420 : :
421 : : p = xdr_inline_decode(xdr, 4);
422 : : if (unlikely(p == NULL))
423 : : return -ENOSPC;
424 : : count = be32_to_cpup(p++);
425 : : for (i = 0; i < count; i++) {
426 : : gssx_dec_name_attr(xdr, &dummy);
427 : : }
428 : :
429 : : naa->count = 0;
430 : : naa->data = NULL;
431 : : return 0;
432 : : }
433 : :
434 : : static struct xdr_netobj zero_netobj = {};
435 : :
436 : : static struct gssx_name_attr_array zero_name_attr_array = {};
437 : :
438 : : static struct gssx_option_array zero_option_array = {};
439 : :
440 : 0 : static int gssx_enc_name(struct xdr_stream *xdr,
441 : : struct gssx_name *name)
442 : : {
443 : 0 : int err;
444 : :
445 : : /* name->display_name */
446 : 0 : err = gssx_enc_buffer(xdr, &name->display_name);
447 [ # # ]: 0 : if (err)
448 : : return err;
449 : :
450 : : /* name->name_type */
451 : 0 : err = gssx_enc_buffer(xdr, &zero_netobj);
452 [ # # ]: 0 : if (err)
453 : : return err;
454 : :
455 : : /* name->exported_name */
456 : 0 : err = gssx_enc_buffer(xdr, &zero_netobj);
457 [ # # ]: 0 : if (err)
458 : : return err;
459 : :
460 : : /* name->exported_composite_name */
461 : 0 : err = gssx_enc_buffer(xdr, &zero_netobj);
462 [ # # ]: 0 : if (err)
463 : : return err;
464 : :
465 : : /* leave name_attributes empty for now, will add once we have any
466 : : * to pass up at all */
467 : : /* name->name_attributes */
468 [ # # ]: 0 : err = dummy_enc_nameattr_array(xdr, &zero_name_attr_array);
469 : 0 : if (err)
470 : 0 : return err;
471 : :
472 : : /* leave options empty for now, will add once we have any options
473 : : * to pass up at all */
474 : : /* name->extensions */
475 [ # # ]: 0 : err = dummy_enc_opt_array(xdr, &zero_option_array);
476 : :
477 : : return err;
478 : : }
479 : :
480 : :
481 : 0 : static int gssx_dec_name(struct xdr_stream *xdr,
482 : : struct gssx_name *name)
483 : : {
484 : 0 : struct xdr_netobj dummy_netobj = { .len = 0 };
485 : 0 : struct gssx_name_attr_array dummy_name_attr_array = { .count = 0 };
486 : 0 : struct gssx_option_array dummy_option_array = { .count = 0 };
487 : 0 : int err;
488 : :
489 : : /* name->display_name */
490 : 0 : err = gssx_dec_buffer(xdr, &name->display_name);
491 [ # # ]: 0 : if (err)
492 : : return err;
493 : :
494 : : /* name->name_type */
495 : 0 : err = gssx_dec_buffer(xdr, &dummy_netobj);
496 [ # # ]: 0 : if (err)
497 : : return err;
498 : :
499 : : /* name->exported_name */
500 : 0 : err = gssx_dec_buffer(xdr, &dummy_netobj);
501 [ # # ]: 0 : if (err)
502 : : return err;
503 : :
504 : : /* name->exported_composite_name */
505 : 0 : err = gssx_dec_buffer(xdr, &dummy_netobj);
506 [ # # ]: 0 : if (err)
507 : : return err;
508 : :
509 : : /* we assume we have no attributes for now, so simply consume them */
510 : : /* name->name_attributes */
511 : 0 : err = dummy_dec_nameattr_array(xdr, &dummy_name_attr_array);
512 [ # # ]: 0 : if (err)
513 : : return err;
514 : :
515 : : /* we assume we have no options for now, so simply consume them */
516 : : /* name->extensions */
517 : 0 : err = dummy_dec_opt_array(xdr, &dummy_option_array);
518 : :
519 : 0 : return err;
520 : : }
521 : :
522 : 0 : static int dummy_enc_credel_array(struct xdr_stream *xdr,
523 : : struct gssx_cred_element_array *cea)
524 : : {
525 : 0 : __be32 *p;
526 : :
527 : 0 : if (cea->count != 0)
528 : : return -EINVAL;
529 : :
530 : 0 : p = xdr_reserve_space(xdr, 4);
531 [ # # ]: 0 : if (!p)
532 : : return -ENOSPC;
533 : 0 : *p = 0;
534 : :
535 : 0 : return 0;
536 : : }
537 : :
538 : 0 : static int gssx_enc_cred(struct xdr_stream *xdr,
539 : : struct gssx_cred *cred)
540 : : {
541 : 0 : int err;
542 : :
543 : : /* cred->desired_name */
544 : 0 : err = gssx_enc_name(xdr, &cred->desired_name);
545 [ # # ]: 0 : if (err)
546 : : return err;
547 : :
548 : : /* cred->elements */
549 [ # # ]: 0 : err = dummy_enc_credel_array(xdr, &cred->elements);
550 : 0 : if (err)
551 : 0 : return err;
552 : :
553 : : /* cred->cred_handle_reference */
554 : 0 : err = gssx_enc_buffer(xdr, &cred->cred_handle_reference);
555 [ # # ]: 0 : if (err)
556 : : return err;
557 : :
558 : : /* cred->needs_release */
559 : 0 : err = gssx_enc_bool(xdr, cred->needs_release);
560 : :
561 : : return err;
562 : : }
563 : :
564 : 0 : static int gssx_enc_ctx(struct xdr_stream *xdr,
565 : : struct gssx_ctx *ctx)
566 : : {
567 : 0 : __be32 *p;
568 : 0 : int err;
569 : :
570 : : /* ctx->exported_context_token */
571 : 0 : err = gssx_enc_buffer(xdr, &ctx->exported_context_token);
572 [ # # ]: 0 : if (err)
573 : : return err;
574 : :
575 : : /* ctx->state */
576 : 0 : err = gssx_enc_buffer(xdr, &ctx->state);
577 [ # # ]: 0 : if (err)
578 : : return err;
579 : :
580 : : /* ctx->need_release */
581 : 0 : err = gssx_enc_bool(xdr, ctx->need_release);
582 : 0 : if (err)
583 : : return err;
584 : :
585 : : /* ctx->mech */
586 : 0 : err = gssx_enc_buffer(xdr, &ctx->mech);
587 [ # # ]: 0 : if (err)
588 : : return err;
589 : :
590 : : /* ctx->src_name */
591 : 0 : err = gssx_enc_name(xdr, &ctx->src_name);
592 [ # # ]: 0 : if (err)
593 : : return err;
594 : :
595 : : /* ctx->targ_name */
596 : 0 : err = gssx_enc_name(xdr, &ctx->targ_name);
597 [ # # ]: 0 : if (err)
598 : : return err;
599 : :
600 : : /* ctx->lifetime */
601 : 0 : p = xdr_reserve_space(xdr, 8+8);
602 [ # # ]: 0 : if (!p)
603 : : return -ENOSPC;
604 : 0 : p = xdr_encode_hyper(p, ctx->lifetime);
605 : :
606 : : /* ctx->ctx_flags */
607 : 0 : p = xdr_encode_hyper(p, ctx->ctx_flags);
608 : :
609 : : /* ctx->locally_initiated */
610 : 0 : err = gssx_enc_bool(xdr, ctx->locally_initiated);
611 : 0 : if (err)
612 : : return err;
613 : :
614 : : /* ctx->open */
615 : 0 : err = gssx_enc_bool(xdr, ctx->open);
616 : 0 : if (err)
617 : : return err;
618 : :
619 : : /* leave options empty for now, will add once we have any options
620 : : * to pass up at all */
621 : : /* ctx->options */
622 [ # # ]: 0 : err = dummy_enc_opt_array(xdr, &ctx->options);
623 : :
624 : : return err;
625 : : }
626 : :
627 : 0 : static int gssx_dec_ctx(struct xdr_stream *xdr,
628 : : struct gssx_ctx *ctx)
629 : : {
630 : 0 : __be32 *p;
631 : 0 : int err;
632 : :
633 : : /* ctx->exported_context_token */
634 : 0 : err = gssx_dec_buffer(xdr, &ctx->exported_context_token);
635 [ # # ]: 0 : if (err)
636 : : return err;
637 : :
638 : : /* ctx->state */
639 : 0 : err = gssx_dec_buffer(xdr, &ctx->state);
640 [ # # ]: 0 : if (err)
641 : : return err;
642 : :
643 : : /* ctx->need_release */
644 : 0 : err = gssx_dec_bool(xdr, &ctx->need_release);
645 : 0 : if (err)
646 : : return err;
647 : :
648 : : /* ctx->mech */
649 : 0 : err = gssx_dec_buffer(xdr, &ctx->mech);
650 [ # # ]: 0 : if (err)
651 : : return err;
652 : :
653 : : /* ctx->src_name */
654 : 0 : err = gssx_dec_name(xdr, &ctx->src_name);
655 [ # # ]: 0 : if (err)
656 : : return err;
657 : :
658 : : /* ctx->targ_name */
659 : 0 : err = gssx_dec_name(xdr, &ctx->targ_name);
660 [ # # ]: 0 : if (err)
661 : : return err;
662 : :
663 : : /* ctx->lifetime */
664 : 0 : p = xdr_inline_decode(xdr, 8+8);
665 [ # # ]: 0 : if (unlikely(p == NULL))
666 : : return -ENOSPC;
667 : 0 : p = xdr_decode_hyper(p, &ctx->lifetime);
668 : :
669 : : /* ctx->ctx_flags */
670 : 0 : p = xdr_decode_hyper(p, &ctx->ctx_flags);
671 : :
672 : : /* ctx->locally_initiated */
673 : 0 : err = gssx_dec_bool(xdr, &ctx->locally_initiated);
674 : 0 : if (err)
675 : : return err;
676 : :
677 : : /* ctx->open */
678 : 0 : err = gssx_dec_bool(xdr, &ctx->open);
679 : 0 : if (err)
680 : : return err;
681 : :
682 : : /* we assume we have no options for now, so simply consume them */
683 : : /* ctx->options */
684 : 0 : err = dummy_dec_opt_array(xdr, &ctx->options);
685 : :
686 : 0 : return err;
687 : : }
688 : :
689 : 0 : static int gssx_enc_cb(struct xdr_stream *xdr, struct gssx_cb *cb)
690 : : {
691 : 0 : __be32 *p;
692 : 0 : int err;
693 : :
694 : : /* cb->initiator_addrtype */
695 : 0 : p = xdr_reserve_space(xdr, 8);
696 [ # # ]: 0 : if (!p)
697 : : return -ENOSPC;
698 : 0 : p = xdr_encode_hyper(p, cb->initiator_addrtype);
699 : :
700 : : /* cb->initiator_address */
701 : 0 : err = gssx_enc_buffer(xdr, &cb->initiator_address);
702 [ # # ]: 0 : if (err)
703 : : return err;
704 : :
705 : : /* cb->acceptor_addrtype */
706 : 0 : p = xdr_reserve_space(xdr, 8);
707 [ # # ]: 0 : if (!p)
708 : : return -ENOSPC;
709 : 0 : p = xdr_encode_hyper(p, cb->acceptor_addrtype);
710 : :
711 : : /* cb->acceptor_address */
712 : 0 : err = gssx_enc_buffer(xdr, &cb->acceptor_address);
713 [ # # ]: 0 : if (err)
714 : : return err;
715 : :
716 : : /* cb->application_data */
717 : 0 : err = gssx_enc_buffer(xdr, &cb->application_data);
718 : :
719 : 0 : return err;
720 : : }
721 : :
722 : 0 : void gssx_enc_accept_sec_context(struct rpc_rqst *req,
723 : : struct xdr_stream *xdr,
724 : : const void *data)
725 : : {
726 : 0 : const struct gssx_arg_accept_sec_context *arg = data;
727 : 0 : int err;
728 : :
729 : 0 : err = gssx_enc_call_ctx(xdr, &arg->call_ctx);
730 [ # # ]: 0 : if (err)
731 : 0 : goto done;
732 : :
733 : : /* arg->context_handle */
734 [ # # ]: 0 : if (arg->context_handle)
735 : 0 : err = gssx_enc_ctx(xdr, arg->context_handle);
736 : : else
737 : 0 : err = gssx_enc_bool(xdr, 0);
738 [ # # ]: 0 : if (err)
739 : 0 : goto done;
740 : :
741 : : /* arg->cred_handle */
742 [ # # ]: 0 : if (arg->cred_handle)
743 : 0 : err = gssx_enc_cred(xdr, arg->cred_handle);
744 : : else
745 : 0 : err = gssx_enc_bool(xdr, 0);
746 [ # # ]: 0 : if (err)
747 : 0 : goto done;
748 : :
749 : : /* arg->input_token */
750 : 0 : err = gssx_enc_in_token(xdr, &arg->input_token);
751 [ # # ]: 0 : if (err)
752 : 0 : goto done;
753 : :
754 : : /* arg->input_cb */
755 [ # # ]: 0 : if (arg->input_cb)
756 : 0 : err = gssx_enc_cb(xdr, arg->input_cb);
757 : : else
758 : 0 : err = gssx_enc_bool(xdr, 0);
759 [ # # ]: 0 : if (err)
760 : 0 : goto done;
761 : :
762 : 0 : err = gssx_enc_bool(xdr, arg->ret_deleg_cred);
763 : 0 : if (err)
764 : 0 : goto done;
765 : :
766 : : /* leave options empty for now, will add once we have any options
767 : : * to pass up at all */
768 : : /* arg->options */
769 [ # # ]: 0 : err = dummy_enc_opt_array(xdr, &arg->options);
770 : :
771 : 0 : xdr_inline_pages(&req->rq_rcv_buf,
772 : : PAGE_SIZE/2 /* pretty arbitrary */,
773 : 0 : arg->pages, 0 /* page base */, arg->npages * PAGE_SIZE);
774 : 0 : req->rq_rcv_buf.flags |= XDRBUF_SPARSE_PAGES;
775 : 0 : done:
776 : 0 : if (err)
777 : 0 : dprintk("RPC: gssx_enc_accept_sec_context: %d\n", err);
778 : 0 : }
779 : :
780 : 0 : int gssx_dec_accept_sec_context(struct rpc_rqst *rqstp,
781 : : struct xdr_stream *xdr,
782 : : void *data)
783 : : {
784 : 0 : struct gssx_res_accept_sec_context *res = data;
785 : 0 : u32 value_follows;
786 : 0 : int err;
787 : 0 : struct page *scratch;
788 : :
789 : 0 : scratch = alloc_page(GFP_KERNEL);
790 [ # # ]: 0 : if (!scratch)
791 : : return -ENOMEM;
792 : 0 : xdr_set_scratch_buffer(xdr, page_address(scratch), PAGE_SIZE);
793 : :
794 : : /* res->status */
795 : 0 : err = gssx_dec_status(xdr, &res->status);
796 [ # # ]: 0 : if (err)
797 : 0 : goto out_free;
798 : :
799 : : /* res->context_handle */
800 : 0 : err = gssx_dec_bool(xdr, &value_follows);
801 : 0 : if (err)
802 : 0 : goto out_free;
803 [ # # ]: 0 : if (value_follows) {
804 : 0 : err = gssx_dec_ctx(xdr, res->context_handle);
805 [ # # ]: 0 : if (err)
806 : 0 : goto out_free;
807 : : } else {
808 : 0 : res->context_handle = NULL;
809 : : }
810 : :
811 : : /* res->output_token */
812 : 0 : err = gssx_dec_bool(xdr, &value_follows);
813 : 0 : if (err)
814 : 0 : goto out_free;
815 [ # # ]: 0 : if (value_follows) {
816 : 0 : err = gssx_dec_buffer(xdr, res->output_token);
817 [ # # ]: 0 : if (err)
818 : 0 : goto out_free;
819 : : } else {
820 : 0 : res->output_token = NULL;
821 : : }
822 : :
823 : : /* res->delegated_cred_handle */
824 : 0 : err = gssx_dec_bool(xdr, &value_follows);
825 : 0 : if (err)
826 : 0 : goto out_free;
827 [ # # ]: 0 : if (value_follows) {
828 : : /* we do not support upcall servers sending this data. */
829 : 0 : err = -EINVAL;
830 : 0 : goto out_free;
831 : : }
832 : :
833 : : /* res->options */
834 : 0 : err = gssx_dec_option_array(xdr, &res->options);
835 : :
836 : 0 : out_free:
837 : 0 : __free_page(scratch);
838 : 0 : return err;
839 : : }
|