Whamcloud - gitweb
7e6d21aecaaa68b981fd02b413d233efc02292be
[fs/lustre-release.git] / lustre / ptlrpc / gss / gss_svc_upcall.c
1 /*
2  * Modifications for Lustre
3  *
4  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
5  *
6  * Copyright (c) 2012, Intel Corporation.
7  *
8  * Author: Eric Mei <ericm@clusterfs.com>
9  */
10
11 /*
12  * Neil Brown <neilb@cse.unsw.edu.au>
13  * J. Bruce Fields <bfields@umich.edu>
14  * Andy Adamson <andros@umich.edu>
15  * Dug Song <dugsong@monkey.org>
16  *
17  * RPCSEC_GSS server authentication.
18  * This implements RPCSEC_GSS as defined in rfc2203 (rpcsec_gss) and rfc2078
19  * (gssapi)
20  *
21  * The RPCSEC_GSS involves three stages:
22  *  1/ context creation
23  *  2/ data exchange
24  *  3/ context destruction
25  *
26  * Context creation is handled largely by upcalls to user-space.
27  *  In particular, GSS_Accept_sec_context is handled by an upcall
28  * Data exchange is handled entirely within the kernel
29  *  In particular, GSS_GetMIC, GSS_VerifyMIC, GSS_Seal, GSS_Unseal are in-kernel.
30  * Context destruction is handled in-kernel
31  *  GSS_Delete_sec_context is in-kernel
32  *
33  * Context creation is initiated by a RPCSEC_GSS_INIT request arriving.
34  * The context handle and gss_token are used as a key into the rpcsec_init cache.
35  * The content of this cache includes some of the outputs of GSS_Accept_sec_context,
36  * being major_status, minor_status, context_handle, reply_token.
37  * These are sent back to the client.
38  * Sequence window management is handled by the kernel.  The window size if currently
39  * a compile time constant.
40  *
41  * When user-space is happy that a context is established, it places an entry
42  * in the rpcsec_context cache. The key for this cache is the context_handle.
43  * The content includes:
44  *   uid/gidlist - for determining access rights
45  *   mechanism type
46  *   mechanism specific information, such as a key
47  *
48  */
49
50 #define DEBUG_SUBSYSTEM S_SEC
51 #ifdef __KERNEL__
52 #include <linux/types.h>
53 #include <linux/init.h>
54 #include <linux/module.h>
55 #include <linux/slab.h>
56 #include <linux/hash.h>
57 #include <linux/mutex.h>
58 #include <linux/sunrpc/cache.h>
59 #else
60 #include <liblustre.h>
61 #endif
62
63 #include <obd.h>
64 #include <obd_class.h>
65 #include <obd_support.h>
66 #include <lustre/lustre_idl.h>
67 #include <lustre_net.h>
68 #include <lustre_import.h>
69 #include <lustre_sec.h>
70
71 #include "gss_err.h"
72 #include "gss_internal.h"
73 #include "gss_api.h"
74
75 #define GSS_SVC_UPCALL_TIMEOUT  (20)
76
77 static spinlock_t __ctx_index_lock;
78 static __u64 __ctx_index;
79
80 __u64 gss_get_next_ctx_index(void)
81 {
82         __u64 idx;
83
84         spin_lock(&__ctx_index_lock);
85         idx = __ctx_index++;
86         spin_unlock(&__ctx_index_lock);
87
88         return idx;
89 }
90
91 static inline unsigned long hash_mem(char *buf, int length, int bits)
92 {
93         unsigned long hash = 0;
94         unsigned long l = 0;
95         int len = 0;
96         unsigned char c;
97
98         do {
99                 if (len == length) {
100                         c = (char) len;
101                         len = -1;
102                 } else
103                         c = *buf++;
104
105                 l = (l << 8) | c;
106                 len++;
107
108                 if ((len & (BITS_PER_LONG/8-1)) == 0)
109                         hash = cfs_hash_long(hash^l, BITS_PER_LONG);
110         } while (len);
111
112         return hash >> (BITS_PER_LONG - bits);
113 }
114
115 /* This compatibility can be removed once kernel 3.3 is used,
116  * since cache_register_net/cache_unregister_net are exported.
117  * Note that since kernel 3.4 cache_register and cache_unregister
118  * are removed.
119 */
120 static inline int _cache_register_net(struct cache_detail *cd, struct net *net)
121 {
122 #ifdef HAVE_CACHE_REGISTER
123         return cache_register(cd);
124 #else
125         return cache_register_net(cd, net);
126 #endif
127 }
128 static inline void _cache_unregister_net(struct cache_detail *cd,
129                                          struct net *net)
130 {
131 #ifdef HAVE_CACHE_REGISTER
132         cache_unregister(cd);
133 #else
134         cache_unregister_net(cd, net);
135 #endif
136 }
137 /****************************************
138  * rsi cache                            *
139  ****************************************/
140
141 #define RSI_HASHBITS    (6)
142 #define RSI_HASHMAX     (1 << RSI_HASHBITS)
143 #define RSI_HASHMASK    (RSI_HASHMAX - 1)
144
145 struct rsi {
146         struct cache_head       h;
147         __u32                   lustre_svc;
148         __u64                   nid;
149         wait_queue_head_t       waitq;
150         rawobj_t                in_handle, in_token;
151         rawobj_t                out_handle, out_token;
152         int                     major_status, minor_status;
153 };
154
155 static struct cache_head *rsi_table[RSI_HASHMAX];
156 static struct cache_detail rsi_cache;
157 static struct rsi *rsi_update(struct rsi *new, struct rsi *old);
158 static struct rsi *rsi_lookup(struct rsi *item);
159
160 static inline int rsi_hash(struct rsi *item)
161 {
162         return hash_mem((char *)item->in_handle.data, item->in_handle.len,
163                         RSI_HASHBITS) ^
164                hash_mem((char *)item->in_token.data, item->in_token.len,
165                         RSI_HASHBITS);
166 }
167
168 static inline int __rsi_match(struct rsi *item, struct rsi *tmp)
169 {
170         return (rawobj_equal(&item->in_handle, &tmp->in_handle) &&
171                 rawobj_equal(&item->in_token, &tmp->in_token));
172 }
173
174 static void rsi_free(struct rsi *rsi)
175 {
176         rawobj_free(&rsi->in_handle);
177         rawobj_free(&rsi->in_token);
178         rawobj_free(&rsi->out_handle);
179         rawobj_free(&rsi->out_token);
180 }
181
182 static void rsi_request(struct cache_detail *cd,
183                         struct cache_head *h,
184                         char **bpp, int *blen)
185 {
186         struct rsi *rsi = container_of(h, struct rsi, h);
187         __u64 index = 0;
188
189         /* if in_handle is null, provide kernel suggestion */
190         if (rsi->in_handle.len == 0)
191                 index = gss_get_next_ctx_index();
192
193         qword_addhex(bpp, blen, (char *) &rsi->lustre_svc,
194                         sizeof(rsi->lustre_svc));
195         qword_addhex(bpp, blen, (char *) &rsi->nid, sizeof(rsi->nid));
196         qword_addhex(bpp, blen, (char *) &index, sizeof(index));
197         qword_addhex(bpp, blen, rsi->in_handle.data, rsi->in_handle.len);
198         qword_addhex(bpp, blen, rsi->in_token.data, rsi->in_token.len);
199         (*bpp)[-1] = '\n';
200 }
201
202 #ifdef HAVE_SUNRPC_UPCALL_HAS_3ARGS
203 static int rsi_upcall(struct cache_detail *cd, struct cache_head *h)
204 {
205         return sunrpc_cache_pipe_upcall(cd, h, rsi_request);
206 }
207 #else
208
209 static int rsi_upcall(struct cache_detail *cd, struct cache_head *h)
210 {
211         return sunrpc_cache_pipe_upcall(cd, h);
212 }
213 #endif
214
215 static inline void __rsi_init(struct rsi *new, struct rsi *item)
216 {
217         new->out_handle = RAWOBJ_EMPTY;
218         new->out_token = RAWOBJ_EMPTY;
219
220         new->in_handle = item->in_handle;
221         item->in_handle = RAWOBJ_EMPTY;
222         new->in_token = item->in_token;
223         item->in_token = RAWOBJ_EMPTY;
224
225         new->lustre_svc = item->lustre_svc;
226         new->nid = item->nid;
227         init_waitqueue_head(&new->waitq);
228 }
229
230 static inline void __rsi_update(struct rsi *new, struct rsi *item)
231 {
232         LASSERT(new->out_handle.len == 0);
233         LASSERT(new->out_token.len == 0);
234
235         new->out_handle = item->out_handle;
236         item->out_handle = RAWOBJ_EMPTY;
237         new->out_token = item->out_token;
238         item->out_token = RAWOBJ_EMPTY;
239
240         new->major_status = item->major_status;
241         new->minor_status = item->minor_status;
242 }
243
244 static void rsi_put(struct kref *ref)
245 {
246         struct rsi *rsi = container_of(ref, struct rsi, h.ref);
247
248         LASSERT(rsi->h.next == NULL);
249         rsi_free(rsi);
250         OBD_FREE_PTR(rsi);
251 }
252
253 static int rsi_match(struct cache_head *a, struct cache_head *b)
254 {
255         struct rsi *item = container_of(a, struct rsi, h);
256         struct rsi *tmp = container_of(b, struct rsi, h);
257
258         return __rsi_match(item, tmp);
259 }
260
261 static void rsi_init(struct cache_head *cnew, struct cache_head *citem)
262 {
263         struct rsi *new = container_of(cnew, struct rsi, h);
264         struct rsi *item = container_of(citem, struct rsi, h);
265
266         __rsi_init(new, item);
267 }
268
269 static void update_rsi(struct cache_head *cnew, struct cache_head *citem)
270 {
271         struct rsi *new = container_of(cnew, struct rsi, h);
272         struct rsi *item = container_of(citem, struct rsi, h);
273
274         __rsi_update(new, item);
275 }
276
277 static struct cache_head *rsi_alloc(void)
278 {
279         struct rsi *rsi;
280
281         OBD_ALLOC_PTR(rsi);
282         if (rsi) 
283                 return &rsi->h;
284         else
285                 return NULL;
286 }
287
288 static int rsi_parse(struct cache_detail *cd, char *mesg, int mlen)
289 {
290         char           *buf = mesg;
291         char           *ep;
292         int             len;
293         struct rsi      rsii, *rsip = NULL;
294         time_t          expiry;
295         int             status = -EINVAL;
296         ENTRY;
297
298
299         memset(&rsii, 0, sizeof(rsii));
300
301         /* handle */
302         len = qword_get(&mesg, buf, mlen);
303         if (len < 0)
304                 goto out;
305         if (rawobj_alloc(&rsii.in_handle, buf, len)) {
306                 status = -ENOMEM;
307                 goto out;
308         }
309
310         /* token */
311         len = qword_get(&mesg, buf, mlen);
312         if (len < 0)
313                 goto out;
314         if (rawobj_alloc(&rsii.in_token, buf, len)) {
315                 status = -ENOMEM;
316                 goto out;
317         }
318
319         rsip = rsi_lookup(&rsii);
320         if (!rsip)
321                 goto out;
322
323         rsii.h.flags = 0;
324         /* expiry */
325         expiry = get_expiry(&mesg);
326         if (expiry == 0)
327                 goto out;
328
329         len = qword_get(&mesg, buf, mlen);
330         if (len <= 0)
331                 goto out;
332
333         /* major */
334         rsii.major_status = simple_strtol(buf, &ep, 10);
335         if (*ep)
336                 goto out;
337
338         /* minor */
339         len = qword_get(&mesg, buf, mlen);
340         if (len <= 0)
341                 goto out;
342         rsii.minor_status = simple_strtol(buf, &ep, 10);
343         if (*ep)
344                 goto out;
345
346         /* out_handle */
347         len = qword_get(&mesg, buf, mlen);
348         if (len < 0)
349                 goto out;
350         if (rawobj_alloc(&rsii.out_handle, buf, len)) {
351                 status = -ENOMEM;
352                 goto out;
353         }
354
355         /* out_token */
356         len = qword_get(&mesg, buf, mlen);
357         if (len < 0)
358                 goto out;
359         if (rawobj_alloc(&rsii.out_token, buf, len)) {
360                 status = -ENOMEM;
361                 goto out;
362         }
363
364         rsii.h.expiry_time = expiry;
365         rsip = rsi_update(&rsii, rsip);
366         status = 0;
367 out:
368         rsi_free(&rsii);
369         if (rsip) {
370                 wake_up_all(&rsip->waitq);
371                 cache_put(&rsip->h, &rsi_cache);
372         } else {
373                 status = -ENOMEM;
374         }
375
376         if (status)
377                 CERROR("rsi parse error %d\n", status);
378         RETURN(status);
379 }
380
381 static struct cache_detail rsi_cache = {
382         .hash_size      = RSI_HASHMAX,
383         .hash_table     = rsi_table,
384         .name           = "auth.sptlrpc.init",
385         .cache_put      = rsi_put,
386 #ifndef HAVE_SUNRPC_UPCALL_HAS_3ARGS
387         .cache_request  = rsi_request,
388 #endif
389         .cache_upcall   = rsi_upcall,
390         .cache_parse    = rsi_parse,
391         .match          = rsi_match,
392         .init           = rsi_init,
393         .update         = update_rsi,
394         .alloc          = rsi_alloc,
395 };
396
397 static struct rsi *rsi_lookup(struct rsi *item)
398 {
399         struct cache_head *ch;
400         int hash = rsi_hash(item);
401
402         ch = sunrpc_cache_lookup(&rsi_cache, &item->h, hash);
403         if (ch)
404                 return container_of(ch, struct rsi, h);
405         else
406                 return NULL;
407 }
408
409 static struct rsi *rsi_update(struct rsi *new, struct rsi *old)
410 {
411         struct cache_head *ch;
412         int hash = rsi_hash(new);
413
414         ch = sunrpc_cache_update(&rsi_cache, &new->h, &old->h, hash);
415         if (ch)
416                 return container_of(ch, struct rsi, h);
417         else
418                 return NULL;
419 }
420
421 /****************************************
422  * rsc cache                            *
423  ****************************************/
424
425 #define RSC_HASHBITS    (10)
426 #define RSC_HASHMAX     (1 << RSC_HASHBITS)
427 #define RSC_HASHMASK    (RSC_HASHMAX - 1)
428
429 struct rsc {
430         struct cache_head       h;
431         struct obd_device      *target;
432         rawobj_t                handle;
433         struct gss_svc_ctx      ctx;
434 };
435
436 static struct cache_head *rsc_table[RSC_HASHMAX];
437 static struct cache_detail rsc_cache;
438 static struct rsc *rsc_update(struct rsc *new, struct rsc *old);
439 static struct rsc *rsc_lookup(struct rsc *item);
440
441 static void rsc_free(struct rsc *rsci)
442 {
443         rawobj_free(&rsci->handle);
444         rawobj_free(&rsci->ctx.gsc_rvs_hdl);
445         lgss_delete_sec_context(&rsci->ctx.gsc_mechctx);
446 }
447
448 static inline int rsc_hash(struct rsc *rsci)
449 {
450         return hash_mem((char *)rsci->handle.data,
451                         rsci->handle.len, RSC_HASHBITS);
452 }
453
454 static inline int __rsc_match(struct rsc *new, struct rsc *tmp)
455 {
456         return rawobj_equal(&new->handle, &tmp->handle);
457 }
458
459 static inline void __rsc_init(struct rsc *new, struct rsc *tmp)
460 {
461         new->handle = tmp->handle;
462         tmp->handle = RAWOBJ_EMPTY;
463
464         new->target = NULL;
465         memset(&new->ctx, 0, sizeof(new->ctx));
466         new->ctx.gsc_rvs_hdl = RAWOBJ_EMPTY;
467 }
468
469 static inline void __rsc_update(struct rsc *new, struct rsc *tmp)
470 {
471         new->ctx = tmp->ctx;
472         tmp->ctx.gsc_rvs_hdl = RAWOBJ_EMPTY;
473         tmp->ctx.gsc_mechctx = NULL;
474
475         memset(&new->ctx.gsc_seqdata, 0, sizeof(new->ctx.gsc_seqdata));
476         spin_lock_init(&new->ctx.gsc_seqdata.ssd_lock);
477 }
478
479 static void rsc_put(struct kref *ref)
480 {
481         struct rsc *rsci = container_of(ref, struct rsc, h.ref);
482
483         LASSERT(rsci->h.next == NULL);
484         rsc_free(rsci);
485         OBD_FREE_PTR(rsci);
486 }
487
488 static int rsc_match(struct cache_head *a, struct cache_head *b)
489 {
490         struct rsc *new = container_of(a, struct rsc, h);
491         struct rsc *tmp = container_of(b, struct rsc, h);
492
493         return __rsc_match(new, tmp);
494 }
495
496 static void rsc_init(struct cache_head *cnew, struct cache_head *ctmp)
497 {
498         struct rsc *new = container_of(cnew, struct rsc, h);
499         struct rsc *tmp = container_of(ctmp, struct rsc, h);
500
501         __rsc_init(new, tmp);
502 }
503
504 static void update_rsc(struct cache_head *cnew, struct cache_head *ctmp)
505 {
506         struct rsc *new = container_of(cnew, struct rsc, h);
507         struct rsc *tmp = container_of(ctmp, struct rsc, h);
508
509         __rsc_update(new, tmp);
510 }
511
512 static struct cache_head * rsc_alloc(void)
513 {
514         struct rsc *rsc;
515
516         OBD_ALLOC_PTR(rsc);
517         if (rsc)
518                 return &rsc->h;
519         else
520                 return NULL;
521 }
522
523 static int rsc_parse(struct cache_detail *cd, char *mesg, int mlen)
524 {
525         char                *buf = mesg;
526         int                  len, rv, tmp_int;
527         struct rsc           rsci, *rscp = NULL;
528         time_t               expiry;
529         int                  status = -EINVAL;
530         struct gss_api_mech *gm = NULL;
531
532         memset(&rsci, 0, sizeof(rsci));
533
534         /* context handle */
535         len = qword_get(&mesg, buf, mlen);
536         if (len < 0) goto out;
537         status = -ENOMEM;
538         if (rawobj_alloc(&rsci.handle, buf, len))
539                 goto out;
540
541         rsci.h.flags = 0;
542         /* expiry */
543         expiry = get_expiry(&mesg);
544         status = -EINVAL;
545         if (expiry == 0)
546                 goto out;
547
548         /* remote flag */
549         rv = get_int(&mesg, &tmp_int);
550         if (rv) {
551                 CERROR("fail to get remote flag\n");
552                 goto out;
553         }
554         rsci.ctx.gsc_remote = (tmp_int != 0);
555
556         /* root user flag */
557         rv = get_int(&mesg, &tmp_int);
558         if (rv) {
559                 CERROR("fail to get oss user flag\n");
560                 goto out;
561         }
562         rsci.ctx.gsc_usr_root = (tmp_int != 0);
563
564         /* mds user flag */
565         rv = get_int(&mesg, &tmp_int);
566         if (rv) {
567                 CERROR("fail to get mds user flag\n");
568                 goto out;
569         }
570         rsci.ctx.gsc_usr_mds = (tmp_int != 0);
571
572         /* oss user flag */
573         rv = get_int(&mesg, &tmp_int);
574         if (rv) {
575                 CERROR("fail to get oss user flag\n");
576                 goto out;
577         }
578         rsci.ctx.gsc_usr_oss = (tmp_int != 0);
579
580         /* mapped uid */
581         rv = get_int(&mesg, (int *) &rsci.ctx.gsc_mapped_uid);
582         if (rv) {
583                 CERROR("fail to get mapped uid\n");
584                 goto out;
585         }
586
587         rscp = rsc_lookup(&rsci);
588         if (!rscp)
589                 goto out;
590
591         /* uid, or NEGATIVE */
592         rv = get_int(&mesg, (int *) &rsci.ctx.gsc_uid);
593         if (rv == -EINVAL)
594                 goto out;
595         if (rv == -ENOENT) {
596                 CERROR("NOENT? set rsc entry negative\n");
597                 set_bit(CACHE_NEGATIVE, &rsci.h.flags);
598         } else {
599                 rawobj_t tmp_buf;
600                 unsigned long ctx_expiry;
601
602                 /* gid */
603                 if (get_int(&mesg, (int *) &rsci.ctx.gsc_gid))
604                         goto out;
605
606                 /* mech name */
607                 len = qword_get(&mesg, buf, mlen);
608                 if (len < 0)
609                         goto out;
610                 gm = lgss_name_to_mech(buf);
611                 status = -EOPNOTSUPP;
612                 if (!gm)
613                         goto out;
614
615                 status = -EINVAL;
616                 /* mech-specific data: */
617                 len = qword_get(&mesg, buf, mlen);
618                 if (len < 0)
619                         goto out;
620
621                 tmp_buf.len = len;
622                 tmp_buf.data = (unsigned char *)buf;
623                 if (lgss_import_sec_context(&tmp_buf, gm,
624                                             &rsci.ctx.gsc_mechctx))
625                         goto out;
626
627                 /* currently the expiry time passed down from user-space
628                  * is invalid, here we retrive it from mech. */
629                 if (lgss_inquire_context(rsci.ctx.gsc_mechctx, &ctx_expiry)) {
630                         CERROR("unable to get expire time, drop it\n");
631                         goto out;
632                 }
633                 expiry = (time_t) ctx_expiry;
634         }
635
636         rsci.h.expiry_time = expiry;
637         rscp = rsc_update(&rsci, rscp);
638         status = 0;
639 out:
640         if (gm)
641                 lgss_mech_put(gm);
642         rsc_free(&rsci);
643         if (rscp)
644                 cache_put(&rscp->h, &rsc_cache);
645         else
646                 status = -ENOMEM;
647
648         if (status)
649                 CERROR("parse rsc error %d\n", status);
650         return status;
651 }
652
653 static struct cache_detail rsc_cache = {
654         .hash_size      = RSC_HASHMAX,
655         .hash_table     = rsc_table,
656         .name           = "auth.sptlrpc.context",
657         .cache_put      = rsc_put,
658         .cache_parse    = rsc_parse,
659         .match          = rsc_match,
660         .init           = rsc_init,
661         .update         = update_rsc,
662         .alloc          = rsc_alloc,
663 };
664
665 static struct rsc *rsc_lookup(struct rsc *item)
666 {
667         struct cache_head *ch;
668         int                hash = rsc_hash(item);
669
670         ch = sunrpc_cache_lookup(&rsc_cache, &item->h, hash);
671         if (ch)
672                 return container_of(ch, struct rsc, h);
673         else
674                 return NULL;
675 }
676
677 static struct rsc *rsc_update(struct rsc *new, struct rsc *old)
678 {
679         struct cache_head *ch;
680         int                hash = rsc_hash(new);
681
682         ch = sunrpc_cache_update(&rsc_cache, &new->h, &old->h, hash);
683         if (ch)
684                 return container_of(ch, struct rsc, h);
685         else
686                 return NULL;
687 }
688
689 #define COMPAT_RSC_PUT(item, cd)        cache_put((item), (cd))
690
691 /****************************************
692  * rsc cache flush                      *
693  ****************************************/
694
695 typedef int rsc_entry_match(struct rsc *rscp, long data);
696
697 static void rsc_flush(rsc_entry_match *match, long data)
698 {
699         struct cache_head **ch;
700         struct rsc *rscp;
701         int n;
702         ENTRY;
703
704         write_lock(&rsc_cache.hash_lock);
705         for (n = 0; n < RSC_HASHMAX; n++) {
706                 for (ch = &rsc_cache.hash_table[n]; *ch;) {
707                         rscp = container_of(*ch, struct rsc, h);
708
709                         if (!match(rscp, data)) {
710                                 ch = &((*ch)->next);
711                                 continue;
712                         }
713
714                         /* it seems simply set NEGATIVE doesn't work */
715                         *ch = (*ch)->next;
716                         rscp->h.next = NULL;
717                         cache_get(&rscp->h);
718                         set_bit(CACHE_NEGATIVE, &rscp->h.flags);
719                         COMPAT_RSC_PUT(&rscp->h, &rsc_cache);
720                         rsc_cache.entries--;
721                 }
722         }
723         write_unlock(&rsc_cache.hash_lock);
724         EXIT;
725 }
726
727 static int match_uid(struct rsc *rscp, long uid)
728 {
729         if ((int) uid == -1)
730                 return 1;
731         return ((int) rscp->ctx.gsc_uid == (int) uid);
732 }
733
734 static int match_target(struct rsc *rscp, long target)
735 {
736         return (rscp->target == (struct obd_device *) target);
737 }
738
739 static inline void rsc_flush_uid(int uid)
740 {
741         if (uid == -1)
742                 CWARN("flush all gss contexts...\n");
743
744         rsc_flush(match_uid, (long) uid);
745 }
746
747 static inline void rsc_flush_target(struct obd_device *target)
748 {
749         rsc_flush(match_target, (long) target);
750 }
751
752 void gss_secsvc_flush(struct obd_device *target)
753 {
754         rsc_flush_target(target);
755 }
756 EXPORT_SYMBOL(gss_secsvc_flush);
757
758 static struct rsc *gss_svc_searchbyctx(rawobj_t *handle)
759 {
760         struct rsc  rsci;
761         struct rsc *found;
762
763         memset(&rsci, 0, sizeof(rsci));
764         if (rawobj_dup(&rsci.handle, handle))
765                 return NULL;
766
767         found = rsc_lookup(&rsci);
768         rsc_free(&rsci);
769         if (!found)
770                 return NULL;
771         if (cache_check(&rsc_cache, &found->h, NULL))
772                 return NULL;
773         return found;
774 }
775
776 int gss_svc_upcall_install_rvs_ctx(struct obd_import *imp,
777                                    struct gss_sec *gsec,
778                                    struct gss_cli_ctx *gctx)
779 {
780         struct rsc      rsci, *rscp = NULL;
781         unsigned long   ctx_expiry;
782         __u32           major;
783         int             rc;
784         ENTRY;
785
786         memset(&rsci, 0, sizeof(rsci));
787
788         if (rawobj_alloc(&rsci.handle, (char *) &gsec->gs_rvs_hdl,
789                          sizeof(gsec->gs_rvs_hdl)))
790                 GOTO(out, rc = -ENOMEM);
791
792         rscp = rsc_lookup(&rsci);
793         if (rscp == NULL)
794                 GOTO(out, rc = -ENOMEM);
795
796         major = lgss_copy_reverse_context(gctx->gc_mechctx,
797                                           &rsci.ctx.gsc_mechctx);
798         if (major != GSS_S_COMPLETE)
799                 GOTO(out, rc = -ENOMEM);
800
801         if (lgss_inquire_context(rsci.ctx.gsc_mechctx, &ctx_expiry)) {
802                 CERROR("unable to get expire time, drop it\n");
803                 GOTO(out, rc = -EINVAL);
804         }
805         rsci.h.expiry_time = (time_t) ctx_expiry;
806
807         if (strcmp(imp->imp_obd->obd_type->typ_name, LUSTRE_MDC_NAME) == 0)
808                 rsci.ctx.gsc_usr_mds = 1;
809         else if (strcmp(imp->imp_obd->obd_type->typ_name, LUSTRE_OSC_NAME) == 0)
810                 rsci.ctx.gsc_usr_oss = 1;
811         else
812                 rsci.ctx.gsc_usr_root = 1;
813
814         rscp = rsc_update(&rsci, rscp);
815         if (rscp == NULL)
816                 GOTO(out, rc = -ENOMEM);
817
818         rscp->target = imp->imp_obd;
819         rawobj_dup(&gctx->gc_svc_handle, &rscp->handle);
820
821         CWARN("create reverse svc ctx %p to %s: idx "LPX64"\n",
822               &rscp->ctx, obd2cli_tgt(imp->imp_obd), gsec->gs_rvs_hdl);
823         rc = 0;
824 out:
825         if (rscp)
826                 cache_put(&rscp->h, &rsc_cache);
827         rsc_free(&rsci);
828
829         if (rc)
830                 CERROR("create reverse svc ctx: idx "LPX64", rc %d\n",
831                        gsec->gs_rvs_hdl, rc);
832         RETURN(rc);
833 }
834
835 int gss_svc_upcall_expire_rvs_ctx(rawobj_t *handle)
836 {
837         const cfs_time_t        expire = 20;
838         struct rsc             *rscp;
839
840         rscp = gss_svc_searchbyctx(handle);
841         if (rscp) {
842                 CDEBUG(D_SEC, "reverse svcctx %p (rsc %p) expire soon\n",
843                        &rscp->ctx, rscp);
844
845                 rscp->h.expiry_time = cfs_time_current_sec() + expire;
846                 COMPAT_RSC_PUT(&rscp->h, &rsc_cache);
847         }
848         return 0;
849 }
850
851 int gss_svc_upcall_dup_handle(rawobj_t *handle, struct gss_svc_ctx *ctx)
852 {
853         struct rsc *rscp = container_of(ctx, struct rsc, ctx);
854
855         return rawobj_dup(handle, &rscp->handle);
856 }
857
858 int gss_svc_upcall_update_sequence(rawobj_t *handle, __u32 seq)
859 {
860         struct rsc             *rscp;
861
862         rscp = gss_svc_searchbyctx(handle);
863         if (rscp) {
864                 CDEBUG(D_SEC, "reverse svcctx %p (rsc %p) update seq to %u\n",
865                        &rscp->ctx, rscp, seq + 1);
866
867                 rscp->ctx.gsc_rvs_seq = seq + 1;
868                 COMPAT_RSC_PUT(&rscp->h, &rsc_cache);
869         }
870         return 0;
871 }
872
873 static struct cache_deferred_req* cache_upcall_defer(struct cache_req *req)
874 {
875         return NULL;
876 }
877 static struct cache_req cache_upcall_chandle = { cache_upcall_defer };
878
879 int gss_svc_upcall_handle_init(struct ptlrpc_request *req,
880                                struct gss_svc_reqctx *grctx,
881                                struct gss_wire_ctx *gw,
882                                struct obd_device *target,
883                                __u32 lustre_svc,
884                                rawobj_t *rvs_hdl,
885                                rawobj_t *in_token)
886 {
887         struct ptlrpc_reply_state *rs;
888         struct rsc                *rsci = NULL;
889         struct rsi                *rsip = NULL, rsikey;
890         wait_queue_t             wait;
891         int                        replen = sizeof(struct ptlrpc_body);
892         struct gss_rep_header     *rephdr;
893         int                        first_check = 1;
894         int                        rc = SECSVC_DROP;
895         ENTRY;
896
897         memset(&rsikey, 0, sizeof(rsikey));
898         rsikey.lustre_svc = lustre_svc;
899         rsikey.nid = (__u64) req->rq_peer.nid;
900
901         /* duplicate context handle. for INIT it always 0 */
902         if (rawobj_dup(&rsikey.in_handle, &gw->gw_handle)) {
903                 CERROR("fail to dup context handle\n");
904                 GOTO(out, rc);
905         }
906
907         if (rawobj_dup(&rsikey.in_token, in_token)) {
908                 CERROR("can't duplicate token\n");
909                 rawobj_free(&rsikey.in_handle);
910                 GOTO(out, rc);
911         }
912
913         rsip = rsi_lookup(&rsikey);
914         rsi_free(&rsikey);
915         if (!rsip) {
916                 CERROR("error in rsi_lookup.\n");
917
918                 if (!gss_pack_err_notify(req, GSS_S_FAILURE, 0))
919                         rc = SECSVC_COMPLETE;
920
921                 GOTO(out, rc);
922         }
923
924         cache_get(&rsip->h); /* take an extra ref */
925         init_waitqueue_head(&rsip->waitq);
926         init_waitqueue_entry_current(&wait);
927         add_wait_queue(&rsip->waitq, &wait);
928
929 cache_check:
930         /* Note each time cache_check() will drop a reference if return
931          * non-zero. We hold an extra reference on initial rsip, but must
932          * take care of following calls. */
933         rc = cache_check(&rsi_cache, &rsip->h, &cache_upcall_chandle);
934         switch (rc) {
935         case -ETIMEDOUT:
936         case -EAGAIN: {
937                 int valid;
938
939                 if (first_check) {
940                         first_check = 0;
941
942                         read_lock(&rsi_cache.hash_lock);
943                         valid = test_bit(CACHE_VALID, &rsip->h.flags);
944                         if (valid == 0)
945                                 set_current_state(TASK_INTERRUPTIBLE);
946                         read_unlock(&rsi_cache.hash_lock);
947
948                         if (valid == 0)
949                                 schedule_timeout(GSS_SVC_UPCALL_TIMEOUT *
950                                                      HZ);
951
952                         cache_get(&rsip->h);
953                         goto cache_check;
954                 }
955                 CWARN("waited %ds timeout, drop\n", GSS_SVC_UPCALL_TIMEOUT);
956                 break;
957         }
958         case -ENOENT:
959                 CWARN("cache_check return ENOENT, drop\n");
960                 break;
961         case 0:
962                 /* if not the first check, we have to release the extra
963                  * reference we just added on it. */
964                 if (!first_check)
965                         cache_put(&rsip->h, &rsi_cache);
966                 CDEBUG(D_SEC, "cache_check is good\n");
967                 break;
968         }
969
970         remove_wait_queue(&rsip->waitq, &wait);
971         cache_put(&rsip->h, &rsi_cache);
972
973         if (rc)
974                 GOTO(out, rc = SECSVC_DROP);
975
976         rc = SECSVC_DROP;
977         rsci = gss_svc_searchbyctx(&rsip->out_handle);
978         if (!rsci) {
979                 CERROR("authentication failed\n");
980
981                 if (!gss_pack_err_notify(req, GSS_S_FAILURE, 0))
982                         rc = SECSVC_COMPLETE;
983
984                 GOTO(out, rc);
985         } else {
986                 cache_get(&rsci->h);
987                 grctx->src_ctx = &rsci->ctx;
988         }
989
990         if (rawobj_dup(&rsci->ctx.gsc_rvs_hdl, rvs_hdl)) {
991                 CERROR("failed duplicate reverse handle\n");
992                 GOTO(out, rc);
993         }
994
995         rsci->target = target;
996
997         CDEBUG(D_SEC, "server create rsc %p(%u->%s)\n",
998                rsci, rsci->ctx.gsc_uid, libcfs_nid2str(req->rq_peer.nid));
999
1000         if (rsip->out_handle.len > PTLRPC_GSS_MAX_HANDLE_SIZE) {
1001                 CERROR("handle size %u too large\n", rsip->out_handle.len);
1002                 GOTO(out, rc = SECSVC_DROP);
1003         }
1004
1005         grctx->src_init = 1;
1006         grctx->src_reserve_len = cfs_size_round4(rsip->out_token.len);
1007
1008         rc = lustre_pack_reply_v2(req, 1, &replen, NULL, 0);
1009         if (rc) {
1010                 CERROR("failed to pack reply: %d\n", rc);
1011                 GOTO(out, rc = SECSVC_DROP);
1012         }
1013
1014         rs = req->rq_reply_state;
1015         LASSERT(rs->rs_repbuf->lm_bufcount == 3);
1016         LASSERT(rs->rs_repbuf->lm_buflens[0] >=
1017                 sizeof(*rephdr) + rsip->out_handle.len);
1018         LASSERT(rs->rs_repbuf->lm_buflens[2] >= rsip->out_token.len);
1019
1020         rephdr = lustre_msg_buf(rs->rs_repbuf, 0, 0);
1021         rephdr->gh_version = PTLRPC_GSS_VERSION;
1022         rephdr->gh_flags = 0;
1023         rephdr->gh_proc = PTLRPC_GSS_PROC_ERR;
1024         rephdr->gh_major = rsip->major_status;
1025         rephdr->gh_minor = rsip->minor_status;
1026         rephdr->gh_seqwin = GSS_SEQ_WIN;
1027         rephdr->gh_handle.len = rsip->out_handle.len;
1028         memcpy(rephdr->gh_handle.data, rsip->out_handle.data,
1029                rsip->out_handle.len);
1030
1031         memcpy(lustre_msg_buf(rs->rs_repbuf, 2, 0), rsip->out_token.data,
1032                rsip->out_token.len);
1033
1034         rs->rs_repdata_len = lustre_shrink_msg(rs->rs_repbuf, 2,
1035                                                rsip->out_token.len, 0);
1036
1037         rc = SECSVC_OK;
1038
1039 out:
1040         /* it looks like here we should put rsip also, but this mess up
1041          * with NFS cache mgmt code... FIXME */
1042 #if 0
1043         if (rsip)
1044                 rsi_put(&rsip->h, &rsi_cache);
1045 #endif
1046
1047         if (rsci) {
1048                 /* if anything went wrong, we don't keep the context too */
1049                 if (rc != SECSVC_OK)
1050                         set_bit(CACHE_NEGATIVE, &rsci->h.flags);
1051                 else
1052                         CDEBUG(D_SEC, "create rsc with idx "LPX64"\n",
1053                                gss_handle_to_u64(&rsci->handle));
1054
1055                 COMPAT_RSC_PUT(&rsci->h, &rsc_cache);
1056         }
1057         RETURN(rc);
1058 }
1059
1060 struct gss_svc_ctx *gss_svc_upcall_get_ctx(struct ptlrpc_request *req,
1061                                            struct gss_wire_ctx *gw)
1062 {
1063         struct rsc *rsc;
1064
1065         rsc = gss_svc_searchbyctx(&gw->gw_handle);
1066         if (!rsc) {
1067                 CWARN("Invalid gss ctx idx "LPX64" from %s\n",
1068                       gss_handle_to_u64(&gw->gw_handle),
1069                       libcfs_nid2str(req->rq_peer.nid));
1070                 return NULL;
1071         }
1072
1073         return &rsc->ctx;
1074 }
1075
1076 void gss_svc_upcall_put_ctx(struct gss_svc_ctx *ctx)
1077 {
1078         struct rsc *rsc = container_of(ctx, struct rsc, ctx);
1079
1080         COMPAT_RSC_PUT(&rsc->h, &rsc_cache);
1081 }
1082
1083 void gss_svc_upcall_destroy_ctx(struct gss_svc_ctx *ctx)
1084 {
1085         struct rsc *rsc = container_of(ctx, struct rsc, ctx);
1086
1087         /* can't be found */
1088         set_bit(CACHE_NEGATIVE, &rsc->h.flags);
1089         /* to be removed at next scan */
1090         rsc->h.expiry_time = 1;
1091 }
1092
1093 int __init gss_init_svc_upcall(void)
1094 {
1095         int     i, rc;
1096
1097         spin_lock_init(&__ctx_index_lock);
1098         /*
1099          * this helps reducing context index confliction. after server reboot,
1100          * conflicting request from clients might be filtered out by initial
1101          * sequence number checking, thus no chance to sent error notification
1102          * back to clients.
1103          */
1104         cfs_get_random_bytes(&__ctx_index, sizeof(__ctx_index));
1105
1106         rc = _cache_register_net(&rsi_cache, &init_net);
1107         if (rc != 0)
1108                 return rc;
1109
1110         rc = _cache_register_net(&rsc_cache, &init_net);
1111         if (rc != 0) {
1112                 _cache_unregister_net(&rsi_cache, &init_net);
1113                 return rc;
1114         }
1115
1116         /* FIXME this looks stupid. we intend to give lsvcgssd a chance to open
1117          * the init upcall channel, otherwise there's big chance that the first
1118          * upcall issued before the channel be opened thus nfsv4 cache code will
1119          * drop the request direclty, thus lead to unnecessary recovery time.
1120          * here we wait at miximum 1.5 seconds. */
1121         for (i = 0; i < 6; i++) {
1122                 if (atomic_read(&rsi_cache.readers) > 0)
1123                         break;
1124                 set_current_state(TASK_UNINTERRUPTIBLE);
1125                 LASSERT(HZ >= 4);
1126                 schedule_timeout(HZ / 4);
1127         }
1128
1129         if (atomic_read(&rsi_cache.readers) == 0)
1130                 CWARN("Init channel is not opened by lsvcgssd, following "
1131                       "request might be dropped until lsvcgssd is active\n");
1132
1133         return 0;
1134 }
1135
1136 void gss_exit_svc_upcall(void)
1137 {
1138         cache_purge(&rsi_cache);
1139         _cache_unregister_net(&rsi_cache, &init_net);
1140
1141         cache_purge(&rsc_cache);
1142         _cache_unregister_net(&rsc_cache, &init_net);
1143 }