Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0
2 : : /*
3 : : * Neil Brown <neilb@cse.unsw.edu.au>
4 : : * J. Bruce Fields <bfields@umich.edu>
5 : : * Andy Adamson <andros@umich.edu>
6 : : * Dug Song <dugsong@monkey.org>
7 : : *
8 : : * RPCSEC_GSS server authentication.
9 : : * This implements RPCSEC_GSS as defined in rfc2203 (rpcsec_gss) and rfc2078
10 : : * (gssapi)
11 : : *
12 : : * The RPCSEC_GSS involves three stages:
13 : : * 1/ context creation
14 : : * 2/ data exchange
15 : : * 3/ context destruction
16 : : *
17 : : * Context creation is handled largely by upcalls to user-space.
18 : : * In particular, GSS_Accept_sec_context is handled by an upcall
19 : : * Data exchange is handled entirely within the kernel
20 : : * In particular, GSS_GetMIC, GSS_VerifyMIC, GSS_Seal, GSS_Unseal are in-kernel.
21 : : * Context destruction is handled in-kernel
22 : : * GSS_Delete_sec_context is in-kernel
23 : : *
24 : : * Context creation is initiated by a RPCSEC_GSS_INIT request arriving.
25 : : * The context handle and gss_token are used as a key into the rpcsec_init cache.
26 : : * The content of this cache includes some of the outputs of GSS_Accept_sec_context,
27 : : * being major_status, minor_status, context_handle, reply_token.
28 : : * These are sent back to the client.
29 : : * Sequence window management is handled by the kernel. The window size if currently
30 : : * a compile time constant.
31 : : *
32 : : * When user-space is happy that a context is established, it places an entry
33 : : * in the rpcsec_context cache. The key for this cache is the context_handle.
34 : : * The content includes:
35 : : * uid/gidlist - for determining access rights
36 : : * mechanism type
37 : : * mechanism specific information, such as a key
38 : : *
39 : : */
40 : :
41 : : #include <linux/slab.h>
42 : : #include <linux/types.h>
43 : : #include <linux/module.h>
44 : : #include <linux/pagemap.h>
45 : : #include <linux/user_namespace.h>
46 : :
47 : : #include <linux/sunrpc/auth_gss.h>
48 : : #include <linux/sunrpc/gss_err.h>
49 : : #include <linux/sunrpc/svcauth.h>
50 : : #include <linux/sunrpc/svcauth_gss.h>
51 : : #include <linux/sunrpc/cache.h>
52 : : #include "gss_rpc_upcall.h"
53 : :
54 : :
55 : : #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
56 : : # define RPCDBG_FACILITY RPCDBG_AUTH
57 : : #endif
58 : :
59 : : /* The rpcsec_init cache is used for mapping RPCSEC_GSS_{,CONT_}INIT requests
60 : : * into replies.
61 : : *
62 : : * Key is context handle (\x if empty) and gss_token.
63 : : * Content is major_status minor_status (integers) context_handle, reply_token.
64 : : *
65 : : */
66 : :
67 : 0 : static int netobj_equal(struct xdr_netobj *a, struct xdr_netobj *b)
68 : : {
69 [ # # # # ]: 0 : return a->len == b->len && 0 == memcmp(a->data, b->data, a->len);
70 : : }
71 : :
72 : : #define RSI_HASHBITS 6
73 : : #define RSI_HASHMAX (1<<RSI_HASHBITS)
74 : :
75 : : struct rsi {
76 : : struct cache_head h;
77 : : struct xdr_netobj in_handle, in_token;
78 : : struct xdr_netobj out_handle, out_token;
79 : : int major_status, minor_status;
80 : : struct rcu_head rcu_head;
81 : : };
82 : :
83 : : static struct rsi *rsi_update(struct cache_detail *cd, struct rsi *new, struct rsi *old);
84 : : static struct rsi *rsi_lookup(struct cache_detail *cd, struct rsi *item);
85 : :
86 : 0 : static void rsi_free(struct rsi *rsii)
87 : : {
88 : 0 : kfree(rsii->in_handle.data);
89 : 0 : kfree(rsii->in_token.data);
90 : 0 : kfree(rsii->out_handle.data);
91 : 0 : kfree(rsii->out_token.data);
92 : 0 : }
93 : :
94 : 0 : static void rsi_free_rcu(struct rcu_head *head)
95 : : {
96 : 0 : struct rsi *rsii = container_of(head, struct rsi, rcu_head);
97 : :
98 : 0 : rsi_free(rsii);
99 : 0 : kfree(rsii);
100 : 0 : }
101 : :
102 : 0 : static void rsi_put(struct kref *ref)
103 : : {
104 : : struct rsi *rsii = container_of(ref, struct rsi, h.ref);
105 : :
106 : 0 : call_rcu(&rsii->rcu_head, rsi_free_rcu);
107 : 0 : }
108 : :
109 : 0 : static inline int rsi_hash(struct rsi *item)
110 : : {
111 : 0 : return hash_mem(item->in_handle.data, item->in_handle.len, RSI_HASHBITS)
112 : 0 : ^ hash_mem(item->in_token.data, item->in_token.len, RSI_HASHBITS);
113 : : }
114 : :
115 : 0 : static int rsi_match(struct cache_head *a, struct cache_head *b)
116 : : {
117 : : struct rsi *item = container_of(a, struct rsi, h);
118 : : struct rsi *tmp = container_of(b, struct rsi, h);
119 [ # # # # ]: 0 : return netobj_equal(&item->in_handle, &tmp->in_handle) &&
120 : 0 : netobj_equal(&item->in_token, &tmp->in_token);
121 : : }
122 : :
123 : 0 : static int dup_to_netobj(struct xdr_netobj *dst, char *src, int len)
124 : : {
125 : 0 : dst->len = len;
126 [ # # ]: 0 : dst->data = (len ? kmemdup(src, len, GFP_KERNEL) : NULL);
127 [ # # # # ]: 0 : if (len && !dst->data)
128 : : return -ENOMEM;
129 : 0 : return 0;
130 : : }
131 : :
132 : : static inline int dup_netobj(struct xdr_netobj *dst, struct xdr_netobj *src)
133 : : {
134 : 0 : return dup_to_netobj(dst, src->data, src->len);
135 : : }
136 : :
137 : 0 : static void rsi_init(struct cache_head *cnew, struct cache_head *citem)
138 : : {
139 : : struct rsi *new = container_of(cnew, struct rsi, h);
140 : : struct rsi *item = container_of(citem, struct rsi, h);
141 : :
142 : 0 : new->out_handle.data = NULL;
143 : 0 : new->out_handle.len = 0;
144 : 0 : new->out_token.data = NULL;
145 : 0 : new->out_token.len = 0;
146 : 0 : new->in_handle.len = item->in_handle.len;
147 : 0 : item->in_handle.len = 0;
148 : 0 : new->in_token.len = item->in_token.len;
149 : 0 : item->in_token.len = 0;
150 : 0 : new->in_handle.data = item->in_handle.data;
151 : 0 : item->in_handle.data = NULL;
152 : 0 : new->in_token.data = item->in_token.data;
153 : 0 : item->in_token.data = NULL;
154 : 0 : }
155 : :
156 : 0 : static void update_rsi(struct cache_head *cnew, struct cache_head *citem)
157 : : {
158 : : struct rsi *new = container_of(cnew, struct rsi, h);
159 : : struct rsi *item = container_of(citem, struct rsi, h);
160 : :
161 [ # # # # ]: 0 : BUG_ON(new->out_handle.data || new->out_token.data);
162 : 0 : new->out_handle.len = item->out_handle.len;
163 : 0 : item->out_handle.len = 0;
164 : 0 : new->out_token.len = item->out_token.len;
165 : 0 : item->out_token.len = 0;
166 : 0 : new->out_handle.data = item->out_handle.data;
167 : 0 : item->out_handle.data = NULL;
168 : 0 : new->out_token.data = item->out_token.data;
169 : 0 : item->out_token.data = NULL;
170 : :
171 : 0 : new->major_status = item->major_status;
172 : 0 : new->minor_status = item->minor_status;
173 : 0 : }
174 : :
175 : 0 : static struct cache_head *rsi_alloc(void)
176 : : {
177 : : struct rsi *rsii = kmalloc(sizeof(*rsii), GFP_KERNEL);
178 [ # # ]: 0 : if (rsii)
179 : 0 : return &rsii->h;
180 : : else
181 : : return NULL;
182 : : }
183 : :
184 : 0 : static void rsi_request(struct cache_detail *cd,
185 : : struct cache_head *h,
186 : : char **bpp, int *blen)
187 : : {
188 : : struct rsi *rsii = container_of(h, struct rsi, h);
189 : :
190 : 0 : qword_addhex(bpp, blen, rsii->in_handle.data, rsii->in_handle.len);
191 : 0 : qword_addhex(bpp, blen, rsii->in_token.data, rsii->in_token.len);
192 : 0 : (*bpp)[-1] = '\n';
193 : 0 : }
194 : :
195 : 0 : static int rsi_parse(struct cache_detail *cd,
196 : : char *mesg, int mlen)
197 : : {
198 : : /* context token expiry major minor context token */
199 : 0 : char *buf = mesg;
200 : : char *ep;
201 : : int len;
202 : : struct rsi rsii, *rsip = NULL;
203 : : time_t expiry;
204 : : int status = -EINVAL;
205 : :
206 : 0 : memset(&rsii, 0, sizeof(rsii));
207 : : /* handle */
208 : 0 : len = qword_get(&mesg, buf, mlen);
209 [ # # ]: 0 : if (len < 0)
210 : : goto out;
211 : : status = -ENOMEM;
212 [ # # ]: 0 : if (dup_to_netobj(&rsii.in_handle, buf, len))
213 : : goto out;
214 : :
215 : : /* token */
216 : 0 : len = qword_get(&mesg, buf, mlen);
217 : : status = -EINVAL;
218 [ # # ]: 0 : if (len < 0)
219 : : goto out;
220 : : status = -ENOMEM;
221 [ # # ]: 0 : if (dup_to_netobj(&rsii.in_token, buf, len))
222 : : goto out;
223 : :
224 : 0 : rsip = rsi_lookup(cd, &rsii);
225 [ # # ]: 0 : if (!rsip)
226 : : goto out;
227 : :
228 : 0 : rsii.h.flags = 0;
229 : : /* expiry */
230 : 0 : expiry = get_expiry(&mesg);
231 : : status = -EINVAL;
232 [ # # ]: 0 : if (expiry == 0)
233 : : goto out;
234 : :
235 : : /* major/minor */
236 : 0 : len = qword_get(&mesg, buf, mlen);
237 [ # # ]: 0 : if (len <= 0)
238 : : goto out;
239 : 0 : rsii.major_status = simple_strtoul(buf, &ep, 10);
240 [ # # ]: 0 : if (*ep)
241 : : goto out;
242 : 0 : len = qword_get(&mesg, buf, mlen);
243 [ # # ]: 0 : if (len <= 0)
244 : : goto out;
245 : 0 : rsii.minor_status = simple_strtoul(buf, &ep, 10);
246 [ # # ]: 0 : if (*ep)
247 : : goto out;
248 : :
249 : : /* out_handle */
250 : 0 : len = qword_get(&mesg, buf, mlen);
251 [ # # ]: 0 : if (len < 0)
252 : : goto out;
253 : : status = -ENOMEM;
254 [ # # ]: 0 : if (dup_to_netobj(&rsii.out_handle, buf, len))
255 : : goto out;
256 : :
257 : : /* out_token */
258 : 0 : len = qword_get(&mesg, buf, mlen);
259 : : status = -EINVAL;
260 [ # # ]: 0 : if (len < 0)
261 : : goto out;
262 : : status = -ENOMEM;
263 [ # # ]: 0 : if (dup_to_netobj(&rsii.out_token, buf, len))
264 : : goto out;
265 : 0 : rsii.h.expiry_time = expiry;
266 : 0 : rsip = rsi_update(cd, &rsii, rsip);
267 : : status = 0;
268 : : out:
269 : 0 : rsi_free(&rsii);
270 [ # # ]: 0 : if (rsip)
271 : 0 : cache_put(&rsip->h, cd);
272 : : else
273 : : status = -ENOMEM;
274 : 0 : return status;
275 : : }
276 : :
277 : : static const struct cache_detail rsi_cache_template = {
278 : : .owner = THIS_MODULE,
279 : : .hash_size = RSI_HASHMAX,
280 : : .name = "auth.rpcsec.init",
281 : : .cache_put = rsi_put,
282 : : .cache_request = rsi_request,
283 : : .cache_parse = rsi_parse,
284 : : .match = rsi_match,
285 : : .init = rsi_init,
286 : : .update = update_rsi,
287 : : .alloc = rsi_alloc,
288 : : };
289 : :
290 : 0 : static struct rsi *rsi_lookup(struct cache_detail *cd, struct rsi *item)
291 : : {
292 : : struct cache_head *ch;
293 : 0 : int hash = rsi_hash(item);
294 : :
295 : 0 : ch = sunrpc_cache_lookup_rcu(cd, &item->h, hash);
296 [ # # ]: 0 : if (ch)
297 : 0 : return container_of(ch, struct rsi, h);
298 : : else
299 : : return NULL;
300 : : }
301 : :
302 : 0 : static struct rsi *rsi_update(struct cache_detail *cd, struct rsi *new, struct rsi *old)
303 : : {
304 : : struct cache_head *ch;
305 : 0 : int hash = rsi_hash(new);
306 : :
307 : 0 : ch = sunrpc_cache_update(cd, &new->h,
308 : : &old->h, hash);
309 [ # # ]: 0 : if (ch)
310 : 0 : return container_of(ch, struct rsi, h);
311 : : else
312 : : return NULL;
313 : : }
314 : :
315 : :
316 : : /*
317 : : * The rpcsec_context cache is used to store a context that is
318 : : * used in data exchange.
319 : : * The key is a context handle. The content is:
320 : : * uid, gidlist, mechanism, service-set, mech-specific-data
321 : : */
322 : :
323 : : #define RSC_HASHBITS 10
324 : : #define RSC_HASHMAX (1<<RSC_HASHBITS)
325 : :
326 : : #define GSS_SEQ_WIN 128
327 : :
328 : : struct gss_svc_seq_data {
329 : : /* highest seq number seen so far: */
330 : : int sd_max;
331 : : /* for i such that sd_max-GSS_SEQ_WIN < i <= sd_max, the i-th bit of
332 : : * sd_win is nonzero iff sequence number i has been seen already: */
333 : : unsigned long sd_win[GSS_SEQ_WIN/BITS_PER_LONG];
334 : : spinlock_t sd_lock;
335 : : };
336 : :
337 : : struct rsc {
338 : : struct cache_head h;
339 : : struct xdr_netobj handle;
340 : : struct svc_cred cred;
341 : : struct gss_svc_seq_data seqdata;
342 : : struct gss_ctx *mechctx;
343 : : struct rcu_head rcu_head;
344 : : };
345 : :
346 : : static struct rsc *rsc_update(struct cache_detail *cd, struct rsc *new, struct rsc *old);
347 : : static struct rsc *rsc_lookup(struct cache_detail *cd, struct rsc *item);
348 : :
349 : 0 : static void rsc_free(struct rsc *rsci)
350 : : {
351 : 0 : kfree(rsci->handle.data);
352 [ # # ]: 0 : if (rsci->mechctx)
353 : 0 : gss_delete_sec_context(&rsci->mechctx);
354 : 0 : free_svc_cred(&rsci->cred);
355 : 0 : }
356 : :
357 : 0 : static void rsc_free_rcu(struct rcu_head *head)
358 : : {
359 : 0 : struct rsc *rsci = container_of(head, struct rsc, rcu_head);
360 : :
361 : 0 : kfree(rsci->handle.data);
362 : 0 : kfree(rsci);
363 : 0 : }
364 : :
365 : 0 : static void rsc_put(struct kref *ref)
366 : : {
367 : : struct rsc *rsci = container_of(ref, struct rsc, h.ref);
368 : :
369 [ # # ]: 0 : if (rsci->mechctx)
370 : 0 : gss_delete_sec_context(&rsci->mechctx);
371 : 0 : free_svc_cred(&rsci->cred);
372 : 0 : call_rcu(&rsci->rcu_head, rsc_free_rcu);
373 : 0 : }
374 : :
375 : : static inline int
376 : : rsc_hash(struct rsc *rsci)
377 : : {
378 : 0 : return hash_mem(rsci->handle.data, rsci->handle.len, RSC_HASHBITS);
379 : : }
380 : :
381 : : static int
382 : 0 : rsc_match(struct cache_head *a, struct cache_head *b)
383 : : {
384 : : struct rsc *new = container_of(a, struct rsc, h);
385 : : struct rsc *tmp = container_of(b, struct rsc, h);
386 : :
387 : 0 : return netobj_equal(&new->handle, &tmp->handle);
388 : : }
389 : :
390 : : static void
391 : 0 : rsc_init(struct cache_head *cnew, struct cache_head *ctmp)
392 : : {
393 : : struct rsc *new = container_of(cnew, struct rsc, h);
394 : : struct rsc *tmp = container_of(ctmp, struct rsc, h);
395 : :
396 : 0 : new->handle.len = tmp->handle.len;
397 : 0 : tmp->handle.len = 0;
398 : 0 : new->handle.data = tmp->handle.data;
399 : 0 : tmp->handle.data = NULL;
400 : 0 : new->mechctx = NULL;
401 : : init_svc_cred(&new->cred);
402 : 0 : }
403 : :
404 : : static void
405 : 0 : update_rsc(struct cache_head *cnew, struct cache_head *ctmp)
406 : : {
407 : : struct rsc *new = container_of(cnew, struct rsc, h);
408 : : struct rsc *tmp = container_of(ctmp, struct rsc, h);
409 : :
410 : 0 : new->mechctx = tmp->mechctx;
411 : 0 : tmp->mechctx = NULL;
412 : 0 : memset(&new->seqdata, 0, sizeof(new->seqdata));
413 : 0 : spin_lock_init(&new->seqdata.sd_lock);
414 : 0 : new->cred = tmp->cred;
415 : : init_svc_cred(&tmp->cred);
416 : 0 : }
417 : :
418 : : static struct cache_head *
419 : 0 : rsc_alloc(void)
420 : : {
421 : : struct rsc *rsci = kmalloc(sizeof(*rsci), GFP_KERNEL);
422 [ # # ]: 0 : if (rsci)
423 : 0 : return &rsci->h;
424 : : else
425 : : return NULL;
426 : : }
427 : :
428 : 0 : static int rsc_parse(struct cache_detail *cd,
429 : : char *mesg, int mlen)
430 : : {
431 : : /* contexthandle expiry [ uid gid N <n gids> mechname ...mechdata... ] */
432 : 0 : char *buf = mesg;
433 : : int id;
434 : : int len, rv;
435 : : struct rsc rsci, *rscp = NULL;
436 : : time_t expiry;
437 : : int status = -EINVAL;
438 : : struct gss_api_mech *gm = NULL;
439 : :
440 : 0 : memset(&rsci, 0, sizeof(rsci));
441 : : /* context handle */
442 : 0 : len = qword_get(&mesg, buf, mlen);
443 [ # # ]: 0 : if (len < 0) goto out;
444 : : status = -ENOMEM;
445 [ # # ]: 0 : if (dup_to_netobj(&rsci.handle, buf, len))
446 : : goto out;
447 : :
448 : 0 : rsci.h.flags = 0;
449 : : /* expiry */
450 : 0 : expiry = get_expiry(&mesg);
451 : : status = -EINVAL;
452 [ # # ]: 0 : if (expiry == 0)
453 : : goto out;
454 : :
455 : 0 : rscp = rsc_lookup(cd, &rsci);
456 [ # # ]: 0 : if (!rscp)
457 : : goto out;
458 : :
459 : : /* uid, or NEGATIVE */
460 : 0 : rv = get_int(&mesg, &id);
461 [ # # ]: 0 : if (rv == -EINVAL)
462 : : goto out;
463 [ # # ]: 0 : if (rv == -ENOENT)
464 : 0 : set_bit(CACHE_NEGATIVE, &rsci.h.flags);
465 : : else {
466 : : int N, i;
467 : :
468 : : /*
469 : : * NOTE: we skip uid_valid()/gid_valid() checks here:
470 : : * instead, * -1 id's are later mapped to the
471 : : * (export-specific) anonymous id by nfsd_setuser.
472 : : *
473 : : * (But supplementary gid's get no such special
474 : : * treatment so are checked for validity here.)
475 : : */
476 : : /* uid */
477 : 0 : rsci.cred.cr_uid = make_kuid(current_user_ns(), id);
478 : :
479 : : /* gid */
480 [ # # ]: 0 : if (get_int(&mesg, &id))
481 : : goto out;
482 : 0 : rsci.cred.cr_gid = make_kgid(current_user_ns(), id);
483 : :
484 : : /* number of additional gid's */
485 [ # # ]: 0 : if (get_int(&mesg, &N))
486 : : goto out;
487 [ # # ]: 0 : if (N < 0 || N > NGROUPS_MAX)
488 : : goto out;
489 : : status = -ENOMEM;
490 : 0 : rsci.cred.cr_group_info = groups_alloc(N);
491 [ # # ]: 0 : if (rsci.cred.cr_group_info == NULL)
492 : : goto out;
493 : :
494 : : /* gid's */
495 : : status = -EINVAL;
496 [ # # ]: 0 : for (i=0; i<N; i++) {
497 : : kgid_t kgid;
498 [ # # ]: 0 : if (get_int(&mesg, &id))
499 : : goto out;
500 : 0 : kgid = make_kgid(current_user_ns(), id);
501 [ # # ]: 0 : if (!gid_valid(kgid))
502 : : goto out;
503 : 0 : rsci.cred.cr_group_info->gid[i] = kgid;
504 : : }
505 : 0 : groups_sort(rsci.cred.cr_group_info);
506 : :
507 : : /* mech name */
508 : 0 : len = qword_get(&mesg, buf, mlen);
509 [ # # ]: 0 : if (len < 0)
510 : : goto out;
511 : 0 : gm = rsci.cred.cr_gss_mech = gss_mech_get_by_name(buf);
512 : : status = -EOPNOTSUPP;
513 [ # # ]: 0 : if (!gm)
514 : : goto out;
515 : :
516 : : status = -EINVAL;
517 : : /* mech-specific data: */
518 : 0 : len = qword_get(&mesg, buf, mlen);
519 [ # # ]: 0 : if (len < 0)
520 : : goto out;
521 : 0 : status = gss_import_sec_context(buf, len, gm, &rsci.mechctx,
522 : : NULL, GFP_KERNEL);
523 [ # # ]: 0 : if (status)
524 : : goto out;
525 : :
526 : : /* get client name */
527 : 0 : len = qword_get(&mesg, buf, mlen);
528 [ # # ]: 0 : if (len > 0) {
529 : 0 : rsci.cred.cr_principal = kstrdup(buf, GFP_KERNEL);
530 [ # # ]: 0 : if (!rsci.cred.cr_principal) {
531 : : status = -ENOMEM;
532 : : goto out;
533 : : }
534 : : }
535 : :
536 : : }
537 : 0 : rsci.h.expiry_time = expiry;
538 : 0 : rscp = rsc_update(cd, &rsci, rscp);
539 : : status = 0;
540 : : out:
541 : 0 : rsc_free(&rsci);
542 [ # # ]: 0 : if (rscp)
543 : 0 : cache_put(&rscp->h, cd);
544 : : else
545 : : status = -ENOMEM;
546 : 0 : return status;
547 : : }
548 : :
549 : : static const struct cache_detail rsc_cache_template = {
550 : : .owner = THIS_MODULE,
551 : : .hash_size = RSC_HASHMAX,
552 : : .name = "auth.rpcsec.context",
553 : : .cache_put = rsc_put,
554 : : .cache_parse = rsc_parse,
555 : : .match = rsc_match,
556 : : .init = rsc_init,
557 : : .update = update_rsc,
558 : : .alloc = rsc_alloc,
559 : : };
560 : :
561 : 0 : static struct rsc *rsc_lookup(struct cache_detail *cd, struct rsc *item)
562 : : {
563 : : struct cache_head *ch;
564 : : int hash = rsc_hash(item);
565 : :
566 : 0 : ch = sunrpc_cache_lookup_rcu(cd, &item->h, hash);
567 [ # # ]: 0 : if (ch)
568 : 0 : return container_of(ch, struct rsc, h);
569 : : else
570 : : return NULL;
571 : : }
572 : :
573 : 0 : static struct rsc *rsc_update(struct cache_detail *cd, struct rsc *new, struct rsc *old)
574 : : {
575 : : struct cache_head *ch;
576 : : int hash = rsc_hash(new);
577 : :
578 : 0 : ch = sunrpc_cache_update(cd, &new->h,
579 : : &old->h, hash);
580 [ # # ]: 0 : if (ch)
581 : 0 : return container_of(ch, struct rsc, h);
582 : : else
583 : : return NULL;
584 : : }
585 : :
586 : :
587 : : static struct rsc *
588 : 0 : gss_svc_searchbyctx(struct cache_detail *cd, struct xdr_netobj *handle)
589 : : {
590 : : struct rsc rsci;
591 : : struct rsc *found;
592 : :
593 : 0 : memset(&rsci, 0, sizeof(rsci));
594 [ # # ]: 0 : if (dup_to_netobj(&rsci.handle, handle->data, handle->len))
595 : : return NULL;
596 : 0 : found = rsc_lookup(cd, &rsci);
597 : 0 : rsc_free(&rsci);
598 [ # # ]: 0 : if (!found)
599 : : return NULL;
600 [ # # ]: 0 : if (cache_check(cd, &found->h, NULL))
601 : : return NULL;
602 : 0 : return found;
603 : : }
604 : :
605 : : /* Implements sequence number algorithm as specified in RFC 2203. */
606 : : static int
607 : 0 : gss_check_seq_num(struct rsc *rsci, int seq_num)
608 : : {
609 : : struct gss_svc_seq_data *sd = &rsci->seqdata;
610 : :
611 : : spin_lock(&sd->sd_lock);
612 [ # # ]: 0 : if (seq_num > sd->sd_max) {
613 [ # # ]: 0 : if (seq_num >= sd->sd_max + GSS_SEQ_WIN) {
614 : 0 : memset(sd->sd_win,0,sizeof(sd->sd_win));
615 : 0 : sd->sd_max = seq_num;
616 [ # # ]: 0 : } else while (sd->sd_max < seq_num) {
617 : 0 : sd->sd_max++;
618 : 0 : __clear_bit(sd->sd_max % GSS_SEQ_WIN, sd->sd_win);
619 : : }
620 : 0 : __set_bit(seq_num % GSS_SEQ_WIN, sd->sd_win);
621 : : goto ok;
622 [ # # ]: 0 : } else if (seq_num <= sd->sd_max - GSS_SEQ_WIN) {
623 : : goto drop;
624 : : }
625 : : /* sd_max - GSS_SEQ_WIN < seq_num <= sd_max */
626 [ # # ]: 0 : if (__test_and_set_bit(seq_num % GSS_SEQ_WIN, sd->sd_win))
627 : : goto drop;
628 : : ok:
629 : : spin_unlock(&sd->sd_lock);
630 : 0 : return 1;
631 : : drop:
632 : : spin_unlock(&sd->sd_lock);
633 : 0 : return 0;
634 : : }
635 : :
636 : : static inline u32 round_up_to_quad(u32 i)
637 : : {
638 : 0 : return (i + 3 ) & ~3;
639 : : }
640 : :
641 : : static inline int
642 : 0 : svc_safe_getnetobj(struct kvec *argv, struct xdr_netobj *o)
643 : : {
644 : : int l;
645 : :
646 [ # # ]: 0 : if (argv->iov_len < 4)
647 : : return -1;
648 : 0 : o->len = svc_getnl(argv);
649 : : l = round_up_to_quad(o->len);
650 [ # # ]: 0 : if (argv->iov_len < l)
651 : : return -1;
652 : 0 : o->data = argv->iov_base;
653 : 0 : argv->iov_base += l;
654 : 0 : argv->iov_len -= l;
655 : 0 : return 0;
656 : : }
657 : :
658 : : static inline int
659 : 0 : svc_safe_putnetobj(struct kvec *resv, struct xdr_netobj *o)
660 : : {
661 : : u8 *p;
662 : :
663 [ # # ]: 0 : if (resv->iov_len + 4 > PAGE_SIZE)
664 : : return -1;
665 : 0 : svc_putnl(resv, o->len);
666 : 0 : p = resv->iov_base + resv->iov_len;
667 : 0 : resv->iov_len += round_up_to_quad(o->len);
668 [ # # ]: 0 : if (resv->iov_len > PAGE_SIZE)
669 : : return -1;
670 : 0 : memcpy(p, o->data, o->len);
671 : 0 : memset(p + o->len, 0, round_up_to_quad(o->len) - o->len);
672 : 0 : return 0;
673 : : }
674 : :
675 : : /*
676 : : * Verify the checksum on the header and return SVC_OK on success.
677 : : * Otherwise, return SVC_DROP (in the case of a bad sequence number)
678 : : * or return SVC_DENIED and indicate error in authp.
679 : : */
680 : : static int
681 : 0 : gss_verify_header(struct svc_rqst *rqstp, struct rsc *rsci,
682 : : __be32 *rpcstart, struct rpc_gss_wire_cred *gc, __be32 *authp)
683 : : {
684 : 0 : struct gss_ctx *ctx_id = rsci->mechctx;
685 : : struct xdr_buf rpchdr;
686 : : struct xdr_netobj checksum;
687 : : u32 flavor = 0;
688 : 0 : struct kvec *argv = &rqstp->rq_arg.head[0];
689 : : struct kvec iov;
690 : :
691 : : /* data to compute the checksum over: */
692 : 0 : iov.iov_base = rpcstart;
693 : 0 : iov.iov_len = (u8 *)argv->iov_base - (u8 *)rpcstart;
694 : 0 : xdr_buf_from_iov(&iov, &rpchdr);
695 : :
696 : 0 : *authp = rpc_autherr_badverf;
697 [ # # ]: 0 : if (argv->iov_len < 4)
698 : : return SVC_DENIED;
699 : : flavor = svc_getnl(argv);
700 [ # # ]: 0 : if (flavor != RPC_AUTH_GSS)
701 : : return SVC_DENIED;
702 [ # # ]: 0 : if (svc_safe_getnetobj(argv, &checksum))
703 : : return SVC_DENIED;
704 : :
705 [ # # ]: 0 : if (rqstp->rq_deferred) /* skip verification of revisited request */
706 : : return SVC_OK;
707 [ # # ]: 0 : if (gss_verify_mic(ctx_id, &rpchdr, &checksum) != GSS_S_COMPLETE) {
708 : 0 : *authp = rpcsec_gsserr_credproblem;
709 : 0 : return SVC_DENIED;
710 : : }
711 : :
712 [ # # ]: 0 : if (gc->gc_seq > MAXSEQ) {
713 : : dprintk("RPC: svcauth_gss: discarding request with "
714 : : "large sequence number %d\n", gc->gc_seq);
715 : 0 : *authp = rpcsec_gsserr_ctxproblem;
716 : 0 : return SVC_DENIED;
717 : : }
718 [ # # ]: 0 : if (!gss_check_seq_num(rsci, gc->gc_seq)) {
719 : : dprintk("RPC: svcauth_gss: discarding request with "
720 : : "old sequence number %d\n", gc->gc_seq);
721 : : return SVC_DROP;
722 : : }
723 : 0 : return SVC_OK;
724 : : }
725 : :
726 : : static int
727 : : gss_write_null_verf(struct svc_rqst *rqstp)
728 : : {
729 : : __be32 *p;
730 : :
731 : : svc_putnl(rqstp->rq_res.head, RPC_AUTH_NULL);
732 : 0 : p = rqstp->rq_res.head->iov_base + rqstp->rq_res.head->iov_len;
733 : : /* don't really need to check if head->iov_len > PAGE_SIZE ... */
734 : 0 : *p++ = 0;
735 [ # # # # ]: 0 : if (!xdr_ressize_check(rqstp, p))
736 : : return -1;
737 : : return 0;
738 : : }
739 : :
740 : : static int
741 : 0 : gss_write_verf(struct svc_rqst *rqstp, struct gss_ctx *ctx_id, u32 seq)
742 : : {
743 : : __be32 *xdr_seq;
744 : : u32 maj_stat;
745 : : struct xdr_buf verf_data;
746 : : struct xdr_netobj mic;
747 : : __be32 *p;
748 : : struct kvec iov;
749 : : int err = -1;
750 : :
751 : : svc_putnl(rqstp->rq_res.head, RPC_AUTH_GSS);
752 : : xdr_seq = kmalloc(4, GFP_KERNEL);
753 [ # # ]: 0 : if (!xdr_seq)
754 : : return -1;
755 : 0 : *xdr_seq = htonl(seq);
756 : :
757 : 0 : iov.iov_base = xdr_seq;
758 : 0 : iov.iov_len = 4;
759 : 0 : xdr_buf_from_iov(&iov, &verf_data);
760 : 0 : p = rqstp->rq_res.head->iov_base + rqstp->rq_res.head->iov_len;
761 : 0 : mic.data = (u8 *)(p + 1);
762 : 0 : maj_stat = gss_get_mic(ctx_id, &verf_data, &mic);
763 [ # # ]: 0 : if (maj_stat != GSS_S_COMPLETE)
764 : : goto out;
765 : 0 : *p++ = htonl(mic.len);
766 : 0 : memset((u8 *)p + mic.len, 0, round_up_to_quad(mic.len) - mic.len);
767 : 0 : p += XDR_QUADLEN(mic.len);
768 [ # # ]: 0 : if (!xdr_ressize_check(rqstp, p))
769 : : goto out;
770 : : err = 0;
771 : : out:
772 : 0 : kfree(xdr_seq);
773 : 0 : return err;
774 : : }
775 : :
776 : : struct gss_domain {
777 : : struct auth_domain h;
778 : : u32 pseudoflavor;
779 : : };
780 : :
781 : : static struct auth_domain *
782 : 0 : find_gss_auth_domain(struct gss_ctx *ctx, u32 svc)
783 : : {
784 : : char *name;
785 : :
786 : 0 : name = gss_service_to_auth_domain_name(ctx->mech_type, svc);
787 [ # # ]: 0 : if (!name)
788 : : return NULL;
789 : 0 : return auth_domain_find(name);
790 : : }
791 : :
792 : : static struct auth_ops svcauthops_gss;
793 : :
794 : 0 : u32 svcauth_gss_flavor(struct auth_domain *dom)
795 : : {
796 : : struct gss_domain *gd = container_of(dom, struct gss_domain, h);
797 : :
798 : 0 : return gd->pseudoflavor;
799 : : }
800 : :
801 : : EXPORT_SYMBOL_GPL(svcauth_gss_flavor);
802 : :
803 : : struct auth_domain *
804 : 0 : svcauth_gss_register_pseudoflavor(u32 pseudoflavor, char * name)
805 : : {
806 : : struct gss_domain *new;
807 : : struct auth_domain *test;
808 : : int stat = -ENOMEM;
809 : :
810 : : new = kmalloc(sizeof(*new), GFP_KERNEL);
811 [ # # ]: 0 : if (!new)
812 : : goto out;
813 : : kref_init(&new->h.ref);
814 : 0 : new->h.name = kstrdup(name, GFP_KERNEL);
815 [ # # ]: 0 : if (!new->h.name)
816 : : goto out_free_dom;
817 : 0 : new->h.flavour = &svcauthops_gss;
818 : 0 : new->pseudoflavor = pseudoflavor;
819 : :
820 : 0 : test = auth_domain_lookup(name, &new->h);
821 [ # # ]: 0 : if (test != &new->h) {
822 : 0 : pr_warn("svc: duplicate registration of gss pseudo flavour %s.\n",
823 : : name);
824 : : stat = -EADDRINUSE;
825 : 0 : auth_domain_put(test);
826 : : goto out_free_name;
827 : : }
828 : : return test;
829 : :
830 : : out_free_name:
831 : 0 : kfree(new->h.name);
832 : : out_free_dom:
833 : 0 : kfree(new);
834 : : out:
835 : 0 : return ERR_PTR(stat);
836 : : }
837 : : EXPORT_SYMBOL_GPL(svcauth_gss_register_pseudoflavor);
838 : :
839 : : static inline int
840 : 0 : read_u32_from_xdr_buf(struct xdr_buf *buf, int base, u32 *obj)
841 : : {
842 : : __be32 raw;
843 : : int status;
844 : :
845 : 0 : status = read_bytes_from_xdr_buf(buf, base, &raw, sizeof(*obj));
846 [ # # ]: 0 : if (status)
847 : : return status;
848 : 0 : *obj = ntohl(raw);
849 : 0 : return 0;
850 : : }
851 : :
852 : : /* It would be nice if this bit of code could be shared with the client.
853 : : * Obstacles:
854 : : * The client shouldn't malloc(), would have to pass in own memory.
855 : : * The server uses base of head iovec as read pointer, while the
856 : : * client uses separate pointer. */
857 : : static int
858 : 0 : unwrap_integ_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct gss_ctx *ctx)
859 : : {
860 : : int stat = -EINVAL;
861 : : u32 integ_len, maj_stat;
862 : : struct xdr_netobj mic;
863 : : struct xdr_buf integ_buf;
864 : :
865 : : /* NFS READ normally uses splice to send data in-place. However
866 : : * the data in cache can change after the reply's MIC is computed
867 : : * but before the RPC reply is sent. To prevent the client from
868 : : * rejecting the server-computed MIC in this somewhat rare case,
869 : : * do not use splice with the GSS integrity service.
870 : : */
871 : 0 : clear_bit(RQ_SPLICE_OK, &rqstp->rq_flags);
872 : :
873 : : /* Did we already verify the signature on the original pass through? */
874 [ # # ]: 0 : if (rqstp->rq_deferred)
875 : : return 0;
876 : :
877 : : integ_len = svc_getnl(&buf->head[0]);
878 [ # # ]: 0 : if (integ_len & 3)
879 : : return stat;
880 [ # # ]: 0 : if (integ_len > buf->len)
881 : : return stat;
882 [ # # ]: 0 : if (xdr_buf_subsegment(buf, &integ_buf, 0, integ_len)) {
883 [ # # ]: 0 : WARN_ON_ONCE(1);
884 : : return stat;
885 : : }
886 : : /* copy out mic... */
887 [ # # ]: 0 : if (read_u32_from_xdr_buf(buf, integ_len, &mic.len))
888 : : return stat;
889 [ # # ]: 0 : if (mic.len > RPC_MAX_AUTH_SIZE)
890 : : return stat;
891 : 0 : mic.data = kmalloc(mic.len, GFP_KERNEL);
892 [ # # ]: 0 : if (!mic.data)
893 : : return stat;
894 [ # # ]: 0 : if (read_bytes_from_xdr_buf(buf, integ_len + 4, mic.data, mic.len))
895 : : goto out;
896 : 0 : maj_stat = gss_verify_mic(ctx, &integ_buf, &mic);
897 [ # # ]: 0 : if (maj_stat != GSS_S_COMPLETE)
898 : : goto out;
899 [ # # ]: 0 : if (svc_getnl(&buf->head[0]) != seq)
900 : : goto out;
901 : : /* trim off the mic and padding at the end before returning */
902 : 0 : xdr_buf_trim(buf, round_up_to_quad(mic.len) + 4);
903 : : stat = 0;
904 : : out:
905 : 0 : kfree(mic.data);
906 : 0 : return stat;
907 : : }
908 : :
909 : : static inline int
910 : : total_buf_len(struct xdr_buf *buf)
911 : : {
912 : 0 : return buf->head[0].iov_len + buf->page_len + buf->tail[0].iov_len;
913 : : }
914 : :
915 : : static void
916 : : fix_priv_head(struct xdr_buf *buf, int pad)
917 : : {
918 [ # # # # ]: 0 : if (buf->page_len == 0) {
919 : : /* We need to adjust head and buf->len in tandem in this
920 : : * case to make svc_defer() work--it finds the original
921 : : * buffer start using buf->len - buf->head[0].iov_len. */
922 : 0 : buf->head[0].iov_len -= pad;
923 : : }
924 : : }
925 : :
926 : : static int
927 : 0 : unwrap_priv_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct gss_ctx *ctx)
928 : : {
929 : : u32 priv_len, maj_stat;
930 : : int pad, remaining_len, offset;
931 : :
932 : 0 : clear_bit(RQ_SPLICE_OK, &rqstp->rq_flags);
933 : :
934 : : priv_len = svc_getnl(&buf->head[0]);
935 [ # # ]: 0 : if (rqstp->rq_deferred) {
936 : : /* Already decrypted last time through! The sequence number
937 : : * check at out_seq is unnecessary but harmless: */
938 : : goto out_seq;
939 : : }
940 : : /* buf->len is the number of bytes from the original start of the
941 : : * request to the end, where head[0].iov_len is just the bytes
942 : : * not yet read from the head, so these two values are different: */
943 : : remaining_len = total_buf_len(buf);
944 [ # # ]: 0 : if (priv_len > remaining_len)
945 : : return -EINVAL;
946 : 0 : pad = remaining_len - priv_len;
947 : 0 : buf->len -= pad;
948 : : fix_priv_head(buf, pad);
949 : :
950 : 0 : maj_stat = gss_unwrap(ctx, 0, priv_len, buf);
951 : 0 : pad = priv_len - buf->len;
952 : : /* The upper layers assume the buffer is aligned on 4-byte boundaries.
953 : : * In the krb5p case, at least, the data ends up offset, so we need to
954 : : * move it around. */
955 : : /* XXX: This is very inefficient. It would be better to either do
956 : : * this while we encrypt, or maybe in the receive code, if we can peak
957 : : * ahead and work out the service and mechanism there. */
958 : 0 : offset = buf->head[0].iov_len % 4;
959 [ # # ]: 0 : if (offset) {
960 : 0 : buf->buflen = RPCSVC_MAXPAYLOAD;
961 : 0 : xdr_shift_buf(buf, offset);
962 : : fix_priv_head(buf, pad);
963 : : }
964 [ # # ]: 0 : if (maj_stat != GSS_S_COMPLETE)
965 : : return -EINVAL;
966 : : out_seq:
967 [ # # ]: 0 : if (svc_getnl(&buf->head[0]) != seq)
968 : : return -EINVAL;
969 : 0 : return 0;
970 : : }
971 : :
972 : : struct gss_svc_data {
973 : : /* decoded gss client cred: */
974 : : struct rpc_gss_wire_cred clcred;
975 : : /* save a pointer to the beginning of the encoded verifier,
976 : : * for use in encryption/checksumming in svcauth_gss_release: */
977 : : __be32 *verf_start;
978 : : struct rsc *rsci;
979 : : };
980 : :
981 : : static int
982 : 0 : svcauth_gss_set_client(struct svc_rqst *rqstp)
983 : : {
984 : 0 : struct gss_svc_data *svcdata = rqstp->rq_auth_data;
985 : 0 : struct rsc *rsci = svcdata->rsci;
986 : : struct rpc_gss_wire_cred *gc = &svcdata->clcred;
987 : : int stat;
988 : :
989 : : /*
990 : : * A gss export can be specified either by:
991 : : * export *(sec=krb5,rw)
992 : : * or by
993 : : * export gss/krb5(rw)
994 : : * The latter is deprecated; but for backwards compatibility reasons
995 : : * the nfsd code will still fall back on trying it if the former
996 : : * doesn't work; so we try to make both available to nfsd, below.
997 : : */
998 : 0 : rqstp->rq_gssclient = find_gss_auth_domain(rsci->mechctx, gc->gc_svc);
999 [ # # ]: 0 : if (rqstp->rq_gssclient == NULL)
1000 : : return SVC_DENIED;
1001 : 0 : stat = svcauth_unix_set_client(rqstp);
1002 [ # # ]: 0 : if (stat == SVC_DROP || stat == SVC_CLOSE)
1003 : 0 : return stat;
1004 : : return SVC_OK;
1005 : : }
1006 : :
1007 : : static inline int
1008 : 0 : gss_write_init_verf(struct cache_detail *cd, struct svc_rqst *rqstp,
1009 : : struct xdr_netobj *out_handle, int *major_status)
1010 : : {
1011 : : struct rsc *rsci;
1012 : : int rc;
1013 : :
1014 [ # # ]: 0 : if (*major_status != GSS_S_COMPLETE)
1015 : 0 : return gss_write_null_verf(rqstp);
1016 : 0 : rsci = gss_svc_searchbyctx(cd, out_handle);
1017 [ # # ]: 0 : if (rsci == NULL) {
1018 : 0 : *major_status = GSS_S_NO_CONTEXT;
1019 : 0 : return gss_write_null_verf(rqstp);
1020 : : }
1021 : 0 : rc = gss_write_verf(rqstp, rsci->mechctx, GSS_SEQ_WIN);
1022 : 0 : cache_put(&rsci->h, cd);
1023 : 0 : return rc;
1024 : : }
1025 : :
1026 : : static inline int
1027 : 0 : gss_read_common_verf(struct rpc_gss_wire_cred *gc,
1028 : : struct kvec *argv, __be32 *authp,
1029 : : struct xdr_netobj *in_handle)
1030 : : {
1031 : : /* Read the verifier; should be NULL: */
1032 : 0 : *authp = rpc_autherr_badverf;
1033 [ # # ]: 0 : if (argv->iov_len < 2 * 4)
1034 : : return SVC_DENIED;
1035 [ # # ]: 0 : if (svc_getnl(argv) != RPC_AUTH_NULL)
1036 : : return SVC_DENIED;
1037 [ # # ]: 0 : if (svc_getnl(argv) != 0)
1038 : : return SVC_DENIED;
1039 : : /* Martial context handle and token for upcall: */
1040 : 0 : *authp = rpc_autherr_badcred;
1041 [ # # # # ]: 0 : if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0)
1042 : : return SVC_DENIED;
1043 [ # # ]: 0 : if (dup_netobj(in_handle, &gc->gc_ctx))
1044 : : return SVC_CLOSE;
1045 : 0 : *authp = rpc_autherr_badverf;
1046 : :
1047 : 0 : return 0;
1048 : : }
1049 : :
1050 : : static inline int
1051 : 0 : gss_read_verf(struct rpc_gss_wire_cred *gc,
1052 : : struct kvec *argv, __be32 *authp,
1053 : : struct xdr_netobj *in_handle,
1054 : : struct xdr_netobj *in_token)
1055 : : {
1056 : : struct xdr_netobj tmpobj;
1057 : : int res;
1058 : :
1059 : 0 : res = gss_read_common_verf(gc, argv, authp, in_handle);
1060 [ # # ]: 0 : if (res)
1061 : : return res;
1062 : :
1063 [ # # ]: 0 : if (svc_safe_getnetobj(argv, &tmpobj)) {
1064 : 0 : kfree(in_handle->data);
1065 : 0 : return SVC_DENIED;
1066 : : }
1067 [ # # ]: 0 : if (dup_netobj(in_token, &tmpobj)) {
1068 : 0 : kfree(in_handle->data);
1069 : 0 : return SVC_CLOSE;
1070 : : }
1071 : :
1072 : : return 0;
1073 : : }
1074 : :
1075 : 0 : static void gss_free_in_token_pages(struct gssp_in_token *in_token)
1076 : : {
1077 : : u32 inlen;
1078 : : int i;
1079 : :
1080 : : i = 0;
1081 : 0 : inlen = in_token->page_len;
1082 [ # # ]: 0 : while (inlen) {
1083 [ # # ]: 0 : if (in_token->pages[i])
1084 : 0 : put_page(in_token->pages[i]);
1085 : 0 : inlen -= inlen > PAGE_SIZE ? PAGE_SIZE : inlen;
1086 : : }
1087 : :
1088 : 0 : kfree(in_token->pages);
1089 : 0 : in_token->pages = NULL;
1090 : 0 : }
1091 : :
1092 : 0 : static int gss_read_proxy_verf(struct svc_rqst *rqstp,
1093 : : struct rpc_gss_wire_cred *gc, __be32 *authp,
1094 : : struct xdr_netobj *in_handle,
1095 : : struct gssp_in_token *in_token)
1096 : : {
1097 : 0 : struct kvec *argv = &rqstp->rq_arg.head[0];
1098 : : unsigned int page_base, length;
1099 : : int pages, i, res;
1100 : : size_t inlen;
1101 : :
1102 : 0 : res = gss_read_common_verf(gc, argv, authp, in_handle);
1103 [ # # ]: 0 : if (res)
1104 : : return res;
1105 : :
1106 : : inlen = svc_getnl(argv);
1107 [ # # ]: 0 : if (inlen > (argv->iov_len + rqstp->rq_arg.page_len))
1108 : : return SVC_DENIED;
1109 : :
1110 : 0 : pages = DIV_ROUND_UP(inlen, PAGE_SIZE);
1111 : 0 : in_token->pages = kcalloc(pages, sizeof(struct page *), GFP_KERNEL);
1112 [ # # ]: 0 : if (!in_token->pages)
1113 : : return SVC_DENIED;
1114 : 0 : in_token->page_base = 0;
1115 : 0 : in_token->page_len = inlen;
1116 [ # # ]: 0 : for (i = 0; i < pages; i++) {
1117 : 0 : in_token->pages[i] = alloc_page(GFP_KERNEL);
1118 [ # # ]: 0 : if (!in_token->pages[i]) {
1119 : 0 : gss_free_in_token_pages(in_token);
1120 : 0 : return SVC_DENIED;
1121 : : }
1122 : : }
1123 : :
1124 : 0 : length = min_t(unsigned int, inlen, argv->iov_len);
1125 : 0 : memcpy(page_address(in_token->pages[0]), argv->iov_base, length);
1126 : 0 : inlen -= length;
1127 : :
1128 : : i = 1;
1129 : 0 : page_base = rqstp->rq_arg.page_base;
1130 [ # # ]: 0 : while (inlen) {
1131 : 0 : length = min_t(unsigned int, inlen, PAGE_SIZE);
1132 : 0 : memcpy(page_address(in_token->pages[i]),
1133 : 0 : page_address(rqstp->rq_arg.pages[i]) + page_base,
1134 : : length);
1135 : :
1136 : 0 : inlen -= length;
1137 : : page_base = 0;
1138 : 0 : i++;
1139 : : }
1140 : : return 0;
1141 : : }
1142 : :
1143 : : static inline int
1144 : 0 : gss_write_resv(struct kvec *resv, size_t size_limit,
1145 : : struct xdr_netobj *out_handle, struct xdr_netobj *out_token,
1146 : : int major_status, int minor_status)
1147 : : {
1148 [ # # ]: 0 : if (resv->iov_len + 4 > size_limit)
1149 : : return -1;
1150 : : svc_putnl(resv, RPC_SUCCESS);
1151 [ # # ]: 0 : if (svc_safe_putnetobj(resv, out_handle))
1152 : : return -1;
1153 [ # # ]: 0 : if (resv->iov_len + 3 * 4 > size_limit)
1154 : : return -1;
1155 : 0 : svc_putnl(resv, major_status);
1156 : 0 : svc_putnl(resv, minor_status);
1157 : : svc_putnl(resv, GSS_SEQ_WIN);
1158 [ # # ]: 0 : if (svc_safe_putnetobj(resv, out_token))
1159 : : return -1;
1160 : 0 : return 0;
1161 : : }
1162 : :
1163 : : /*
1164 : : * Having read the cred already and found we're in the context
1165 : : * initiation case, read the verifier and initiate (or check the results
1166 : : * of) upcalls to userspace for help with context initiation. If
1167 : : * the upcall results are available, write the verifier and result.
1168 : : * Otherwise, drop the request pending an answer to the upcall.
1169 : : */
1170 : 0 : static int svcauth_gss_legacy_init(struct svc_rqst *rqstp,
1171 : : struct rpc_gss_wire_cred *gc, __be32 *authp)
1172 : : {
1173 : 0 : struct kvec *argv = &rqstp->rq_arg.head[0];
1174 : 0 : struct kvec *resv = &rqstp->rq_res.head[0];
1175 : : struct rsi *rsip, rsikey;
1176 : : int ret;
1177 [ # # ]: 0 : struct sunrpc_net *sn = net_generic(SVC_NET(rqstp), sunrpc_net_id);
1178 : :
1179 : 0 : memset(&rsikey, 0, sizeof(rsikey));
1180 : 0 : ret = gss_read_verf(gc, argv, authp,
1181 : : &rsikey.in_handle, &rsikey.in_token);
1182 [ # # ]: 0 : if (ret)
1183 : : return ret;
1184 : :
1185 : : /* Perform upcall, or find upcall result: */
1186 : 0 : rsip = rsi_lookup(sn->rsi_cache, &rsikey);
1187 : 0 : rsi_free(&rsikey);
1188 [ # # ]: 0 : if (!rsip)
1189 : : return SVC_CLOSE;
1190 [ # # ]: 0 : if (cache_check(sn->rsi_cache, &rsip->h, &rqstp->rq_chandle) < 0)
1191 : : /* No upcall result: */
1192 : : return SVC_CLOSE;
1193 : :
1194 : : ret = SVC_CLOSE;
1195 : : /* Got an answer to the upcall; use it: */
1196 [ # # ]: 0 : if (gss_write_init_verf(sn->rsc_cache, rqstp,
1197 : : &rsip->out_handle, &rsip->major_status))
1198 : : goto out;
1199 [ # # ]: 0 : if (gss_write_resv(resv, PAGE_SIZE,
1200 : : &rsip->out_handle, &rsip->out_token,
1201 : : rsip->major_status, rsip->minor_status))
1202 : : goto out;
1203 : :
1204 : : ret = SVC_COMPLETE;
1205 : : out:
1206 : 0 : cache_put(&rsip->h, sn->rsi_cache);
1207 : 0 : return ret;
1208 : : }
1209 : :
1210 : 0 : static int gss_proxy_save_rsc(struct cache_detail *cd,
1211 : : struct gssp_upcall_data *ud,
1212 : : uint64_t *handle)
1213 : : {
1214 : : struct rsc rsci, *rscp = NULL;
1215 : : static atomic64_t ctxhctr;
1216 : : long long ctxh;
1217 : : struct gss_api_mech *gm = NULL;
1218 : : time_t expiry;
1219 : : int status = -EINVAL;
1220 : :
1221 : 0 : memset(&rsci, 0, sizeof(rsci));
1222 : : /* context handle */
1223 : : status = -ENOMEM;
1224 : : /* the handle needs to be just a unique id,
1225 : : * use a static counter */
1226 : 0 : ctxh = atomic64_inc_return(&ctxhctr);
1227 : :
1228 : : /* make a copy for the caller */
1229 : 0 : *handle = ctxh;
1230 : :
1231 : : /* make a copy for the rsc cache */
1232 [ # # ]: 0 : if (dup_to_netobj(&rsci.handle, (char *)handle, sizeof(uint64_t)))
1233 : : goto out;
1234 : 0 : rscp = rsc_lookup(cd, &rsci);
1235 [ # # ]: 0 : if (!rscp)
1236 : : goto out;
1237 : :
1238 : : /* creds */
1239 [ # # ]: 0 : if (!ud->found_creds) {
1240 : : /* userspace seem buggy, we should always get at least a
1241 : : * mapping to nobody */
1242 : : dprintk("RPC: No creds found!\n");
1243 : : goto out;
1244 : : } else {
1245 : : struct timespec64 boot;
1246 : :
1247 : : /* steal creds */
1248 : 0 : rsci.cred = ud->creds;
1249 : 0 : memset(&ud->creds, 0, sizeof(struct svc_cred));
1250 : :
1251 : : status = -EOPNOTSUPP;
1252 : : /* get mech handle from OID */
1253 : 0 : gm = gss_mech_get_by_OID(&ud->mech_oid);
1254 [ # # ]: 0 : if (!gm)
1255 : : goto out;
1256 : 0 : rsci.cred.cr_gss_mech = gm;
1257 : :
1258 : : status = -EINVAL;
1259 : : /* mech-specific data: */
1260 : 0 : status = gss_import_sec_context(ud->out_handle.data,
1261 : : ud->out_handle.len,
1262 : : gm, &rsci.mechctx,
1263 : : &expiry, GFP_KERNEL);
1264 [ # # ]: 0 : if (status)
1265 : : goto out;
1266 : :
1267 : 0 : getboottime64(&boot);
1268 : 0 : expiry -= boot.tv_sec;
1269 : : }
1270 : :
1271 : 0 : rsci.h.expiry_time = expiry;
1272 : 0 : rscp = rsc_update(cd, &rsci, rscp);
1273 : : status = 0;
1274 : : out:
1275 : 0 : rsc_free(&rsci);
1276 [ # # ]: 0 : if (rscp)
1277 : 0 : cache_put(&rscp->h, cd);
1278 : : else
1279 : : status = -ENOMEM;
1280 : 0 : return status;
1281 : : }
1282 : :
1283 : 0 : static int svcauth_gss_proxy_init(struct svc_rqst *rqstp,
1284 : : struct rpc_gss_wire_cred *gc, __be32 *authp)
1285 : : {
1286 : 0 : struct kvec *resv = &rqstp->rq_res.head[0];
1287 : : struct xdr_netobj cli_handle;
1288 : : struct gssp_upcall_data ud;
1289 : : uint64_t handle;
1290 : : int status;
1291 : : int ret;
1292 [ # # ]: 0 : struct net *net = SVC_NET(rqstp);
1293 : 0 : struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1294 : :
1295 : 0 : memset(&ud, 0, sizeof(ud));
1296 : 0 : ret = gss_read_proxy_verf(rqstp, gc, authp,
1297 : : &ud.in_handle, &ud.in_token);
1298 [ # # ]: 0 : if (ret)
1299 : : return ret;
1300 : :
1301 : : ret = SVC_CLOSE;
1302 : :
1303 : : /* Perform synchronous upcall to gss-proxy */
1304 : 0 : status = gssp_accept_sec_context_upcall(net, &ud);
1305 [ # # ]: 0 : if (status)
1306 : : goto out;
1307 : :
1308 : : dprintk("RPC: svcauth_gss: gss major status = %d "
1309 : : "minor status = %d\n",
1310 : : ud.major_status, ud.minor_status);
1311 : :
1312 [ # # # ]: 0 : switch (ud.major_status) {
1313 : : case GSS_S_CONTINUE_NEEDED:
1314 : 0 : cli_handle = ud.out_handle;
1315 : 0 : break;
1316 : : case GSS_S_COMPLETE:
1317 : 0 : status = gss_proxy_save_rsc(sn->rsc_cache, &ud, &handle);
1318 [ # # ]: 0 : if (status) {
1319 : 0 : pr_info("%s: gss_proxy_save_rsc failed (%d)\n",
1320 : : __func__, status);
1321 : 0 : goto out;
1322 : : }
1323 : 0 : cli_handle.data = (u8 *)&handle;
1324 : 0 : cli_handle.len = sizeof(handle);
1325 : 0 : break;
1326 : : default:
1327 : : ret = SVC_CLOSE;
1328 : : goto out;
1329 : : }
1330 : :
1331 : : /* Got an answer to the upcall; use it: */
1332 [ # # ]: 0 : if (gss_write_init_verf(sn->rsc_cache, rqstp,
1333 : : &cli_handle, &ud.major_status)) {
1334 : 0 : pr_info("%s: gss_write_init_verf failed\n", __func__);
1335 : 0 : goto out;
1336 : : }
1337 [ # # ]: 0 : if (gss_write_resv(resv, PAGE_SIZE,
1338 : : &cli_handle, &ud.out_token,
1339 : : ud.major_status, ud.minor_status)) {
1340 : 0 : pr_info("%s: gss_write_resv failed\n", __func__);
1341 : 0 : goto out;
1342 : : }
1343 : :
1344 : : ret = SVC_COMPLETE;
1345 : : out:
1346 : 0 : gss_free_in_token_pages(&ud.in_token);
1347 : 0 : gssp_free_upcall_data(&ud);
1348 : 0 : return ret;
1349 : : }
1350 : :
1351 : : /*
1352 : : * Try to set the sn->use_gss_proxy variable to a new value. We only allow
1353 : : * it to be changed if it's currently undefined (-1). If it's any other value
1354 : : * then return -EBUSY unless the type wouldn't have changed anyway.
1355 : : */
1356 : 0 : static int set_gss_proxy(struct net *net, int type)
1357 : : {
1358 : 0 : struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1359 : : int ret;
1360 : :
1361 [ # # # # ]: 0 : WARN_ON_ONCE(type != 0 && type != 1);
1362 : 0 : ret = cmpxchg(&sn->use_gss_proxy, -1, type);
1363 [ # # ]: 0 : if (ret != -1 && ret != type)
1364 : : return -EBUSY;
1365 : 0 : return 0;
1366 : : }
1367 : :
1368 : 0 : static bool use_gss_proxy(struct net *net)
1369 : : {
1370 : 0 : struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1371 : :
1372 : : /* If use_gss_proxy is still undefined, then try to disable it */
1373 [ # # ]: 0 : if (sn->use_gss_proxy == -1)
1374 : 0 : set_gss_proxy(net, 0);
1375 : 0 : return sn->use_gss_proxy;
1376 : : }
1377 : :
1378 : : #ifdef CONFIG_PROC_FS
1379 : :
1380 : 0 : static ssize_t write_gssp(struct file *file, const char __user *buf,
1381 : : size_t count, loff_t *ppos)
1382 : : {
1383 : 0 : struct net *net = PDE_DATA(file_inode(file));
1384 : : char tbuf[20];
1385 : : unsigned long i;
1386 : : int res;
1387 : :
1388 [ # # # # ]: 0 : if (*ppos || count > sizeof(tbuf)-1)
1389 : : return -EINVAL;
1390 [ # # ]: 0 : if (copy_from_user(tbuf, buf, count))
1391 : : return -EFAULT;
1392 : :
1393 : 0 : tbuf[count] = 0;
1394 : : res = kstrtoul(tbuf, 0, &i);
1395 [ # # ]: 0 : if (res)
1396 : : return res;
1397 [ # # ]: 0 : if (i != 1)
1398 : : return -EINVAL;
1399 : 0 : res = set_gssp_clnt(net);
1400 [ # # ]: 0 : if (res)
1401 : : return res;
1402 : 0 : res = set_gss_proxy(net, 1);
1403 [ # # ]: 0 : if (res)
1404 : : return res;
1405 : 0 : return count;
1406 : : }
1407 : :
1408 : 0 : static ssize_t read_gssp(struct file *file, char __user *buf,
1409 : : size_t count, loff_t *ppos)
1410 : : {
1411 : 0 : struct net *net = PDE_DATA(file_inode(file));
1412 : 0 : struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1413 : 0 : unsigned long p = *ppos;
1414 : : char tbuf[10];
1415 : : size_t len;
1416 : :
1417 : 0 : snprintf(tbuf, sizeof(tbuf), "%d\n", sn->use_gss_proxy);
1418 : 0 : len = strlen(tbuf);
1419 [ # # ]: 0 : if (p >= len)
1420 : : return 0;
1421 : 0 : len -= p;
1422 [ # # ]: 0 : if (len > count)
1423 : : len = count;
1424 [ # # ]: 0 : if (copy_to_user(buf, (void *)(tbuf+p), len))
1425 : : return -EFAULT;
1426 : 0 : *ppos += len;
1427 : 0 : return len;
1428 : : }
1429 : :
1430 : : static const struct file_operations use_gss_proxy_ops = {
1431 : : .open = nonseekable_open,
1432 : : .write = write_gssp,
1433 : : .read = read_gssp,
1434 : : };
1435 : :
1436 : 207 : static int create_use_gss_proxy_proc_entry(struct net *net)
1437 : : {
1438 : 207 : struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1439 : : struct proc_dir_entry **p = &sn->use_gssp_proc;
1440 : :
1441 : 207 : sn->use_gss_proxy = -1;
1442 : 207 : *p = proc_create_data("use-gss-proxy", S_IFREG | 0600,
1443 : : sn->proc_net_rpc,
1444 : : &use_gss_proxy_ops, net);
1445 [ + - ]: 207 : if (!*p)
1446 : : return -ENOMEM;
1447 : 207 : init_gssp_clnt(sn);
1448 : 207 : return 0;
1449 : : }
1450 : :
1451 : 0 : static void destroy_use_gss_proxy_proc_entry(struct net *net)
1452 : : {
1453 : 0 : struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1454 : :
1455 [ # # ]: 0 : if (sn->use_gssp_proc) {
1456 : 0 : remove_proc_entry("use-gss-proxy", sn->proc_net_rpc);
1457 : 0 : clear_gssp_clnt(sn);
1458 : : }
1459 : 0 : }
1460 : : #else /* CONFIG_PROC_FS */
1461 : :
1462 : : static int create_use_gss_proxy_proc_entry(struct net *net)
1463 : : {
1464 : : return 0;
1465 : : }
1466 : :
1467 : : static void destroy_use_gss_proxy_proc_entry(struct net *net) {}
1468 : :
1469 : : #endif /* CONFIG_PROC_FS */
1470 : :
1471 : : /*
1472 : : * Accept an rpcsec packet.
1473 : : * If context establishment, punt to user space
1474 : : * If data exchange, verify/decrypt
1475 : : * If context destruction, handle here
1476 : : * In the context establishment and destruction case we encode
1477 : : * response here and return SVC_COMPLETE.
1478 : : */
1479 : : static int
1480 : 0 : svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp)
1481 : : {
1482 : 0 : struct kvec *argv = &rqstp->rq_arg.head[0];
1483 : : struct kvec *resv = &rqstp->rq_res.head[0];
1484 : : u32 crlen;
1485 : 0 : struct gss_svc_data *svcdata = rqstp->rq_auth_data;
1486 : : struct rpc_gss_wire_cred *gc;
1487 : : struct rsc *rsci = NULL;
1488 : : __be32 *rpcstart;
1489 : 0 : __be32 *reject_stat = resv->iov_base + resv->iov_len;
1490 : : int ret;
1491 [ # # ]: 0 : struct sunrpc_net *sn = net_generic(SVC_NET(rqstp), sunrpc_net_id);
1492 : :
1493 : : dprintk("RPC: svcauth_gss: argv->iov_len = %zd\n",
1494 : : argv->iov_len);
1495 : :
1496 : 0 : *authp = rpc_autherr_badcred;
1497 [ # # ]: 0 : if (!svcdata)
1498 : : svcdata = kmalloc(sizeof(*svcdata), GFP_KERNEL);
1499 [ # # ]: 0 : if (!svcdata)
1500 : : goto auth_err;
1501 : 0 : rqstp->rq_auth_data = svcdata;
1502 : 0 : svcdata->verf_start = NULL;
1503 : 0 : svcdata->rsci = NULL;
1504 : 0 : gc = &svcdata->clcred;
1505 : :
1506 : : /* start of rpc packet is 7 u32's back from here:
1507 : : * xid direction rpcversion prog vers proc flavour
1508 : : */
1509 : 0 : rpcstart = argv->iov_base;
1510 : 0 : rpcstart -= 7;
1511 : :
1512 : : /* credential is:
1513 : : * version(==1), proc(0,1,2,3), seq, service (1,2,3), handle
1514 : : * at least 5 u32s, and is preceded by length, so that makes 6.
1515 : : */
1516 : :
1517 [ # # ]: 0 : if (argv->iov_len < 5 * 4)
1518 : : goto auth_err;
1519 : : crlen = svc_getnl(argv);
1520 [ # # ]: 0 : if (svc_getnl(argv) != RPC_GSS_VERSION)
1521 : : goto auth_err;
1522 : 0 : gc->gc_proc = svc_getnl(argv);
1523 : 0 : gc->gc_seq = svc_getnl(argv);
1524 : 0 : gc->gc_svc = svc_getnl(argv);
1525 [ # # ]: 0 : if (svc_safe_getnetobj(argv, &gc->gc_ctx))
1526 : : goto auth_err;
1527 [ # # ]: 0 : if (crlen != round_up_to_quad(gc->gc_ctx.len) + 5 * 4)
1528 : : goto auth_err;
1529 : :
1530 [ # # # # ]: 0 : if ((gc->gc_proc != RPC_GSS_PROC_DATA) && (rqstp->rq_proc != 0))
1531 : : goto auth_err;
1532 : :
1533 : 0 : *authp = rpc_autherr_badverf;
1534 [ # # # ]: 0 : switch (gc->gc_proc) {
1535 : : case RPC_GSS_PROC_INIT:
1536 : : case RPC_GSS_PROC_CONTINUE_INIT:
1537 [ # # # # ]: 0 : if (use_gss_proxy(SVC_NET(rqstp)))
1538 : 0 : return svcauth_gss_proxy_init(rqstp, gc, authp);
1539 : : else
1540 : 0 : return svcauth_gss_legacy_init(rqstp, gc, authp);
1541 : : case RPC_GSS_PROC_DATA:
1542 : : case RPC_GSS_PROC_DESTROY:
1543 : : /* Look up the context, and check the verifier: */
1544 : 0 : *authp = rpcsec_gsserr_credproblem;
1545 : 0 : rsci = gss_svc_searchbyctx(sn->rsc_cache, &gc->gc_ctx);
1546 [ # # ]: 0 : if (!rsci)
1547 : : goto auth_err;
1548 [ # # # ]: 0 : switch (gss_verify_header(rqstp, rsci, rpcstart, gc, authp)) {
1549 : : case SVC_OK:
1550 : : break;
1551 : : case SVC_DENIED:
1552 : : goto auth_err;
1553 : : case SVC_DROP:
1554 : : goto drop;
1555 : : }
1556 : : break;
1557 : : default:
1558 : 0 : *authp = rpc_autherr_rejectedcred;
1559 : 0 : goto auth_err;
1560 : : }
1561 : :
1562 : : /* now act upon the command: */
1563 [ # # # ]: 0 : switch (gc->gc_proc) {
1564 : : case RPC_GSS_PROC_DESTROY:
1565 [ # # ]: 0 : if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq))
1566 : : goto auth_err;
1567 : : /* Delete the entry from the cache_list and call cache_put */
1568 : 0 : sunrpc_cache_unhash(sn->rsc_cache, &rsci->h);
1569 [ # # ]: 0 : if (resv->iov_len + 4 > PAGE_SIZE)
1570 : : goto drop;
1571 : : svc_putnl(resv, RPC_SUCCESS);
1572 : : goto complete;
1573 : : case RPC_GSS_PROC_DATA:
1574 : 0 : *authp = rpcsec_gsserr_ctxproblem;
1575 : 0 : svcdata->verf_start = resv->iov_base + resv->iov_len;
1576 [ # # ]: 0 : if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq))
1577 : : goto auth_err;
1578 : 0 : rqstp->rq_cred = rsci->cred;
1579 : 0 : get_group_info(rsci->cred.cr_group_info);
1580 : 0 : *authp = rpc_autherr_badcred;
1581 [ # # # # ]: 0 : switch (gc->gc_svc) {
1582 : : case RPC_GSS_SVC_NONE:
1583 : : break;
1584 : : case RPC_GSS_SVC_INTEGRITY:
1585 : : /* placeholders for length and seq. number: */
1586 : : svc_putnl(resv, 0);
1587 : : svc_putnl(resv, 0);
1588 [ # # ]: 0 : if (unwrap_integ_data(rqstp, &rqstp->rq_arg,
1589 : : gc->gc_seq, rsci->mechctx))
1590 : : goto garbage_args;
1591 : 0 : rqstp->rq_auth_slack = RPC_MAX_AUTH_SIZE;
1592 : 0 : break;
1593 : : case RPC_GSS_SVC_PRIVACY:
1594 : : /* placeholders for length and seq. number: */
1595 : : svc_putnl(resv, 0);
1596 : : svc_putnl(resv, 0);
1597 [ # # ]: 0 : if (unwrap_priv_data(rqstp, &rqstp->rq_arg,
1598 : : gc->gc_seq, rsci->mechctx))
1599 : : goto garbage_args;
1600 : 0 : rqstp->rq_auth_slack = RPC_MAX_AUTH_SIZE * 2;
1601 : 0 : break;
1602 : : default:
1603 : : goto auth_err;
1604 : : }
1605 : 0 : svcdata->rsci = rsci;
1606 : : cache_get(&rsci->h);
1607 : 0 : rqstp->rq_cred.cr_flavor = gss_svc_to_pseudoflavor(
1608 : 0 : rsci->mechctx->mech_type,
1609 : : GSS_C_QOP_DEFAULT,
1610 : : gc->gc_svc);
1611 : : ret = SVC_OK;
1612 : 0 : goto out;
1613 : : }
1614 : : garbage_args:
1615 : : ret = SVC_GARBAGE;
1616 : : goto out;
1617 : : auth_err:
1618 : : /* Restore write pointer to its original value: */
1619 : : xdr_ressize_check(rqstp, reject_stat);
1620 : : ret = SVC_DENIED;
1621 : 0 : goto out;
1622 : : complete:
1623 : : ret = SVC_COMPLETE;
1624 : 0 : goto out;
1625 : : drop:
1626 : : ret = SVC_CLOSE;
1627 : : out:
1628 [ # # ]: 0 : if (rsci)
1629 : 0 : cache_put(&rsci->h, sn->rsc_cache);
1630 : 0 : return ret;
1631 : : }
1632 : :
1633 : : static __be32 *
1634 : 0 : svcauth_gss_prepare_to_wrap(struct xdr_buf *resbuf, struct gss_svc_data *gsd)
1635 : : {
1636 : : __be32 *p;
1637 : : u32 verf_len;
1638 : :
1639 : 0 : p = gsd->verf_start;
1640 : 0 : gsd->verf_start = NULL;
1641 : :
1642 : : /* If the reply stat is nonzero, don't wrap: */
1643 [ # # ]: 0 : if (*(p-1) != rpc_success)
1644 : : return NULL;
1645 : : /* Skip the verifier: */
1646 : : p += 1;
1647 : 0 : verf_len = ntohl(*p++);
1648 : 0 : p += XDR_QUADLEN(verf_len);
1649 : : /* move accept_stat to right place: */
1650 : 0 : memcpy(p, p + 2, 4);
1651 : : /* Also don't wrap if the accept stat is nonzero: */
1652 [ # # ]: 0 : if (*p != rpc_success) {
1653 : 0 : resbuf->head[0].iov_len -= 2 * 4;
1654 : 0 : return NULL;
1655 : : }
1656 : 0 : p++;
1657 : 0 : return p;
1658 : : }
1659 : :
1660 : : static inline int
1661 : 0 : svcauth_gss_wrap_resp_integ(struct svc_rqst *rqstp)
1662 : : {
1663 : 0 : struct gss_svc_data *gsd = (struct gss_svc_data *)rqstp->rq_auth_data;
1664 : : struct rpc_gss_wire_cred *gc = &gsd->clcred;
1665 : 0 : struct xdr_buf *resbuf = &rqstp->rq_res;
1666 : : struct xdr_buf integ_buf;
1667 : : struct xdr_netobj mic;
1668 : : struct kvec *resv;
1669 : : __be32 *p;
1670 : : int integ_offset, integ_len;
1671 : : int stat = -EINVAL;
1672 : :
1673 : 0 : p = svcauth_gss_prepare_to_wrap(resbuf, gsd);
1674 [ # # ]: 0 : if (p == NULL)
1675 : : goto out;
1676 : 0 : integ_offset = (u8 *)(p + 1) - (u8 *)resbuf->head[0].iov_base;
1677 : 0 : integ_len = resbuf->len - integ_offset;
1678 [ # # ]: 0 : BUG_ON(integ_len % 4);
1679 : 0 : *p++ = htonl(integ_len);
1680 : 0 : *p++ = htonl(gc->gc_seq);
1681 [ # # ]: 0 : if (xdr_buf_subsegment(resbuf, &integ_buf, integ_offset, integ_len)) {
1682 [ # # ]: 0 : WARN_ON_ONCE(1);
1683 : : goto out_err;
1684 : : }
1685 [ # # ]: 0 : if (resbuf->tail[0].iov_base == NULL) {
1686 [ # # ]: 0 : if (resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE > PAGE_SIZE)
1687 : : goto out_err;
1688 : 0 : resbuf->tail[0].iov_base = resbuf->head[0].iov_base
1689 : 0 : + resbuf->head[0].iov_len;
1690 : 0 : resbuf->tail[0].iov_len = 0;
1691 : : }
1692 : : resv = &resbuf->tail[0];
1693 : 0 : mic.data = (u8 *)resv->iov_base + resv->iov_len + 4;
1694 [ # # ]: 0 : if (gss_get_mic(gsd->rsci->mechctx, &integ_buf, &mic))
1695 : : goto out_err;
1696 : 0 : svc_putnl(resv, mic.len);
1697 : 0 : memset(mic.data + mic.len, 0,
1698 : : round_up_to_quad(mic.len) - mic.len);
1699 : 0 : resv->iov_len += XDR_QUADLEN(mic.len) << 2;
1700 : : /* not strictly required: */
1701 : 0 : resbuf->len += XDR_QUADLEN(mic.len) << 2;
1702 [ # # ]: 0 : BUG_ON(resv->iov_len > PAGE_SIZE);
1703 : : out:
1704 : : stat = 0;
1705 : : out_err:
1706 : 0 : return stat;
1707 : : }
1708 : :
1709 : : static inline int
1710 : 0 : svcauth_gss_wrap_resp_priv(struct svc_rqst *rqstp)
1711 : : {
1712 : 0 : struct gss_svc_data *gsd = (struct gss_svc_data *)rqstp->rq_auth_data;
1713 : : struct rpc_gss_wire_cred *gc = &gsd->clcred;
1714 : 0 : struct xdr_buf *resbuf = &rqstp->rq_res;
1715 : : struct page **inpages = NULL;
1716 : : __be32 *p, *len;
1717 : : int offset;
1718 : : int pad;
1719 : :
1720 : 0 : p = svcauth_gss_prepare_to_wrap(resbuf, gsd);
1721 [ # # ]: 0 : if (p == NULL)
1722 : : return 0;
1723 : 0 : len = p++;
1724 : 0 : offset = (u8 *)p - (u8 *)resbuf->head[0].iov_base;
1725 : 0 : *p++ = htonl(gc->gc_seq);
1726 : 0 : inpages = resbuf->pages;
1727 : : /* XXX: Would be better to write some xdr helper functions for
1728 : : * nfs{2,3,4}xdr.c that place the data right, instead of copying: */
1729 : :
1730 : : /*
1731 : : * If there is currently tail data, make sure there is
1732 : : * room for the head, tail, and 2 * RPC_MAX_AUTH_SIZE in
1733 : : * the page, and move the current tail data such that
1734 : : * there is RPC_MAX_AUTH_SIZE slack space available in
1735 : : * both the head and tail.
1736 : : */
1737 [ # # ]: 0 : if (resbuf->tail[0].iov_base) {
1738 [ # # ]: 0 : BUG_ON(resbuf->tail[0].iov_base >= resbuf->head[0].iov_base
1739 : : + PAGE_SIZE);
1740 [ # # ]: 0 : BUG_ON(resbuf->tail[0].iov_base < resbuf->head[0].iov_base);
1741 [ # # ]: 0 : if (resbuf->tail[0].iov_len + resbuf->head[0].iov_len
1742 : 0 : + 2 * RPC_MAX_AUTH_SIZE > PAGE_SIZE)
1743 : : return -ENOMEM;
1744 : 0 : memmove(resbuf->tail[0].iov_base + RPC_MAX_AUTH_SIZE,
1745 : : resbuf->tail[0].iov_base,
1746 : : resbuf->tail[0].iov_len);
1747 : 0 : resbuf->tail[0].iov_base += RPC_MAX_AUTH_SIZE;
1748 : : }
1749 : : /*
1750 : : * If there is no current tail data, make sure there is
1751 : : * room for the head data, and 2 * RPC_MAX_AUTH_SIZE in the
1752 : : * allotted page, and set up tail information such that there
1753 : : * is RPC_MAX_AUTH_SIZE slack space available in both the
1754 : : * head and tail.
1755 : : */
1756 [ # # ]: 0 : if (resbuf->tail[0].iov_base == NULL) {
1757 [ # # ]: 0 : if (resbuf->head[0].iov_len + 2*RPC_MAX_AUTH_SIZE > PAGE_SIZE)
1758 : : return -ENOMEM;
1759 : 0 : resbuf->tail[0].iov_base = resbuf->head[0].iov_base
1760 : 0 : + resbuf->head[0].iov_len + RPC_MAX_AUTH_SIZE;
1761 : 0 : resbuf->tail[0].iov_len = 0;
1762 : : }
1763 [ # # ]: 0 : if (gss_wrap(gsd->rsci->mechctx, offset, resbuf, inpages))
1764 : : return -ENOMEM;
1765 : 0 : *len = htonl(resbuf->len - offset);
1766 : 0 : pad = 3 - ((resbuf->len - offset - 1)&3);
1767 : 0 : p = (__be32 *)(resbuf->tail[0].iov_base + resbuf->tail[0].iov_len);
1768 : 0 : memset(p, 0, pad);
1769 : 0 : resbuf->tail[0].iov_len += pad;
1770 : 0 : resbuf->len += pad;
1771 : 0 : return 0;
1772 : : }
1773 : :
1774 : : static int
1775 : 0 : svcauth_gss_release(struct svc_rqst *rqstp)
1776 : : {
1777 : 0 : struct gss_svc_data *gsd = (struct gss_svc_data *)rqstp->rq_auth_data;
1778 : : struct rpc_gss_wire_cred *gc = &gsd->clcred;
1779 : : struct xdr_buf *resbuf = &rqstp->rq_res;
1780 : : int stat = -EINVAL;
1781 [ # # ]: 0 : struct sunrpc_net *sn = net_generic(SVC_NET(rqstp), sunrpc_net_id);
1782 : :
1783 [ # # ]: 0 : if (gc->gc_proc != RPC_GSS_PROC_DATA)
1784 : : goto out;
1785 : : /* Release can be called twice, but we only wrap once. */
1786 [ # # ]: 0 : if (gsd->verf_start == NULL)
1787 : : goto out;
1788 : : /* normally not set till svc_send, but we need it here: */
1789 : : /* XXX: what for? Do we mess it up the moment we call svc_putu32
1790 : : * or whatever? */
1791 : 0 : resbuf->len = total_buf_len(resbuf);
1792 [ # # # ]: 0 : switch (gc->gc_svc) {
1793 : : case RPC_GSS_SVC_NONE:
1794 : : break;
1795 : : case RPC_GSS_SVC_INTEGRITY:
1796 : 0 : stat = svcauth_gss_wrap_resp_integ(rqstp);
1797 [ # # ]: 0 : if (stat)
1798 : : goto out_err;
1799 : : break;
1800 : : case RPC_GSS_SVC_PRIVACY:
1801 : 0 : stat = svcauth_gss_wrap_resp_priv(rqstp);
1802 [ # # ]: 0 : if (stat)
1803 : : goto out_err;
1804 : : break;
1805 : : /*
1806 : : * For any other gc_svc value, svcauth_gss_accept() already set
1807 : : * the auth_error appropriately; just fall through:
1808 : : */
1809 : : }
1810 : :
1811 : : out:
1812 : : stat = 0;
1813 : : out_err:
1814 [ # # ]: 0 : if (rqstp->rq_client)
1815 : 0 : auth_domain_put(rqstp->rq_client);
1816 : 0 : rqstp->rq_client = NULL;
1817 [ # # ]: 0 : if (rqstp->rq_gssclient)
1818 : 0 : auth_domain_put(rqstp->rq_gssclient);
1819 : 0 : rqstp->rq_gssclient = NULL;
1820 [ # # ]: 0 : if (rqstp->rq_cred.cr_group_info)
1821 [ # # ]: 0 : put_group_info(rqstp->rq_cred.cr_group_info);
1822 : 0 : rqstp->rq_cred.cr_group_info = NULL;
1823 [ # # ]: 0 : if (gsd->rsci)
1824 : 0 : cache_put(&gsd->rsci->h, sn->rsc_cache);
1825 : 0 : gsd->rsci = NULL;
1826 : :
1827 : 0 : return stat;
1828 : : }
1829 : :
1830 : : static void
1831 : 0 : svcauth_gss_domain_release_rcu(struct rcu_head *head)
1832 : : {
1833 : 0 : struct auth_domain *dom = container_of(head, struct auth_domain, rcu_head);
1834 : : struct gss_domain *gd = container_of(dom, struct gss_domain, h);
1835 : :
1836 : 0 : kfree(dom->name);
1837 : 0 : kfree(gd);
1838 : 0 : }
1839 : :
1840 : : static void
1841 : 0 : svcauth_gss_domain_release(struct auth_domain *dom)
1842 : : {
1843 : 0 : call_rcu(&dom->rcu_head, svcauth_gss_domain_release_rcu);
1844 : 0 : }
1845 : :
1846 : : static struct auth_ops svcauthops_gss = {
1847 : : .name = "rpcsec_gss",
1848 : : .owner = THIS_MODULE,
1849 : : .flavour = RPC_AUTH_GSS,
1850 : : .accept = svcauth_gss_accept,
1851 : : .release = svcauth_gss_release,
1852 : : .domain_release = svcauth_gss_domain_release,
1853 : : .set_client = svcauth_gss_set_client,
1854 : : };
1855 : :
1856 : 207 : static int rsi_cache_create_net(struct net *net)
1857 : : {
1858 : 207 : struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1859 : : struct cache_detail *cd;
1860 : : int err;
1861 : :
1862 : 207 : cd = cache_create_net(&rsi_cache_template, net);
1863 [ - + ]: 207 : if (IS_ERR(cd))
1864 : 0 : return PTR_ERR(cd);
1865 : 207 : err = cache_register_net(cd, net);
1866 [ - + ]: 207 : if (err) {
1867 : 0 : cache_destroy_net(cd, net);
1868 : 0 : return err;
1869 : : }
1870 : 207 : sn->rsi_cache = cd;
1871 : 207 : return 0;
1872 : : }
1873 : :
1874 : 0 : static void rsi_cache_destroy_net(struct net *net)
1875 : : {
1876 : 0 : struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1877 : 0 : struct cache_detail *cd = sn->rsi_cache;
1878 : :
1879 : 0 : sn->rsi_cache = NULL;
1880 : 0 : cache_purge(cd);
1881 : 0 : cache_unregister_net(cd, net);
1882 : 0 : cache_destroy_net(cd, net);
1883 : 0 : }
1884 : :
1885 : 207 : static int rsc_cache_create_net(struct net *net)
1886 : : {
1887 : 207 : struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1888 : : struct cache_detail *cd;
1889 : : int err;
1890 : :
1891 : 207 : cd = cache_create_net(&rsc_cache_template, net);
1892 [ - + ]: 207 : if (IS_ERR(cd))
1893 : 0 : return PTR_ERR(cd);
1894 : 207 : err = cache_register_net(cd, net);
1895 [ - + ]: 207 : if (err) {
1896 : 0 : cache_destroy_net(cd, net);
1897 : 0 : return err;
1898 : : }
1899 : 207 : sn->rsc_cache = cd;
1900 : 207 : return 0;
1901 : : }
1902 : :
1903 : 0 : static void rsc_cache_destroy_net(struct net *net)
1904 : : {
1905 : 0 : struct sunrpc_net *sn = net_generic(net, sunrpc_net_id);
1906 : 0 : struct cache_detail *cd = sn->rsc_cache;
1907 : :
1908 : 0 : sn->rsc_cache = NULL;
1909 : 0 : cache_purge(cd);
1910 : 0 : cache_unregister_net(cd, net);
1911 : 0 : cache_destroy_net(cd, net);
1912 : 0 : }
1913 : :
1914 : : int
1915 : 207 : gss_svc_init_net(struct net *net)
1916 : : {
1917 : : int rv;
1918 : :
1919 : 207 : rv = rsc_cache_create_net(net);
1920 [ + - ]: 207 : if (rv)
1921 : : return rv;
1922 : 207 : rv = rsi_cache_create_net(net);
1923 [ + - ]: 207 : if (rv)
1924 : : goto out1;
1925 : 207 : rv = create_use_gss_proxy_proc_entry(net);
1926 [ - + ]: 207 : if (rv)
1927 : : goto out2;
1928 : : return 0;
1929 : : out2:
1930 : 0 : destroy_use_gss_proxy_proc_entry(net);
1931 : : out1:
1932 : 0 : rsc_cache_destroy_net(net);
1933 : 0 : return rv;
1934 : : }
1935 : :
1936 : : void
1937 : 0 : gss_svc_shutdown_net(struct net *net)
1938 : : {
1939 : 0 : destroy_use_gss_proxy_proc_entry(net);
1940 : 0 : rsi_cache_destroy_net(net);
1941 : 0 : rsc_cache_destroy_net(net);
1942 : 0 : }
1943 : :
1944 : : int
1945 : 207 : gss_svc_init(void)
1946 : : {
1947 : 207 : return svc_auth_register(RPC_AUTH_GSS, &svcauthops_gss);
1948 : : }
1949 : :
1950 : : void
1951 : 0 : gss_svc_shutdown(void)
1952 : : {
1953 : 0 : svc_auth_unregister(RPC_AUTH_GSS);
1954 : 0 : }
|