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