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