1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2004 Cluster File Systems, Inc.
6 * This file is part of Lustre, http://www.lustre.org.
8 * Lustre is free software; you can redistribute it and/or
9 * modify it under the terms of version 2 of the GNU General Public
10 * License as published by the Free Software Foundation.
12 * Lustre is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Lustre; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 # define EXPORT_SYMTAB
25 #define DEBUG_SUBSYSTEM S_SEC
27 #include <linux/init.h>
28 #include <linux/module.h>
29 #include <linux/slab.h>
31 #include <liblustre.h>
34 #include <libcfs/kp30.h>
35 #include <linux/obd.h>
36 #include <linux/obd_class.h>
37 #include <linux/obd_support.h>
38 #include <linux/lustre_net.h>
39 #include <linux/lustre_import.h>
40 #include <linux/lustre_dlm.h>
41 #include <linux/lustre_sec.h>
43 static spinlock_t sectypes_lock = SPIN_LOCK_UNLOCKED;
44 static struct ptlrpc_sec_type *sectypes[PTLRPCS_FLVR_MAJOR_MAX] = {
48 int ptlrpcs_register(struct ptlrpc_sec_type *type)
50 __u32 flavor = type->pst_flavor;
52 LASSERT(type->pst_name);
53 LASSERT(type->pst_ops);
55 if (flavor >= PTLRPCS_FLVR_MAJOR_MAX)
58 spin_lock(§ypes_lock);
59 if (sectypes[flavor]) {
60 spin_unlock(§ypes_lock);
63 sectypes[flavor] = type;
64 atomic_set(&type->pst_inst, 0);
65 spin_unlock(§ypes_lock);
67 CWARN("%s: registered\n", type->pst_name);
71 int ptlrpcs_unregister(struct ptlrpc_sec_type *type)
73 __u32 major = type->pst_flavor;
75 LASSERT(major < PTLRPCS_FLVR_MAJOR_MAX);
77 spin_lock(§ypes_lock);
78 if (!sectypes[major]) {
79 spin_unlock(§ypes_lock);
80 CERROR("%s: already unregistered?\n", type->pst_name);
84 LASSERT(sectypes[major] == type);
86 if (atomic_read(&type->pst_inst)) {
87 CERROR("%s: still have %d instances\n",
88 type->pst_name, atomic_read(&type->pst_inst));
89 spin_unlock(§ypes_lock);
93 sectypes[major] = NULL;
94 spin_unlock(§ypes_lock);
96 CDEBUG(D_SEC, "%s: unregistered\n", type->pst_name);
101 struct ptlrpc_sec_type * ptlrpcs_flavor2type(__u32 flavor)
103 struct ptlrpc_sec_type *type;
104 __u32 major = SEC_FLAVOR_MAJOR(flavor);
106 if (major >= PTLRPCS_FLVR_MAJOR_MAX)
109 spin_lock(§ypes_lock);
110 type = sectypes[major];
111 if (type && !try_module_get(type->pst_owner))
113 spin_unlock(§ypes_lock);
118 void ptlrpcs_type_put(struct ptlrpc_sec_type *type)
120 module_put(type->pst_owner);
123 __u32 ptlrpcs_name2flavor(const char *name)
125 if (!strcmp(name, "null"))
126 return PTLRPCS_FLVR_NULL;
127 if (!strcmp(name, "krb5"))
128 return PTLRPCS_FLVR_KRB5;
129 if (!strcmp(name, "krb5i"))
130 return PTLRPCS_FLVR_KRB5I;
131 if (!strcmp(name, "krb5p"))
132 return PTLRPCS_FLVR_KRB5P;
134 return PTLRPCS_FLVR_INVALID;
137 char *ptlrpcs_flavor2name(__u32 flavor)
140 case PTLRPCS_FLVR_NULL:
142 case PTLRPCS_FLVR_KRB5:
144 case PTLRPCS_FLVR_KRB5I:
146 case PTLRPCS_FLVR_KRB5P:
149 CERROR("invalid flavor 0x%x\n", flavor);
154 /***********************************************
155 * credential cache helpers *
156 ***********************************************/
158 void ptlrpcs_init_credcache(struct ptlrpc_sec *sec)
161 for (i = 0; i < PTLRPC_CREDCACHE_NR; i++)
162 INIT_LIST_HEAD(&sec->ps_credcache[i]);
164 /* ps_nextgc == 0 means never do gc */
166 sec->ps_nextgc = get_seconds() + (sec->ps_expire >> 1);
170 * return 1 means we should also destroy the sec structure.
173 static int ptlrpcs_cred_destroy(struct ptlrpc_cred *cred)
175 struct ptlrpc_sec *sec = cred->pc_sec;
178 LASSERT(cred->pc_sec);
179 LASSERT(atomic_read(&cred->pc_refcount) == 0);
180 LASSERT(list_empty(&cred->pc_hash));
182 cred->pc_ops->destroy(cred);
184 /* spinlock to protect against ptlrpcs_sec_put() */
185 LASSERT(atomic_read(&sec->ps_credcount));
186 spin_lock(&sec->ps_lock);
187 if (atomic_dec_and_test(&sec->ps_credcount) &&
188 !atomic_read(&sec->ps_refcount))
190 spin_unlock(&sec->ps_lock);
194 static void ptlrpcs_destroy_credlist(struct list_head *head)
196 struct ptlrpc_cred *cred;
198 while (!list_empty(head)) {
199 cred = list_entry(head->next, struct ptlrpc_cred, pc_hash);
200 list_del_init(&cred->pc_hash);
201 ptlrpcs_cred_destroy(cred);
206 int cred_check_dead(struct ptlrpc_cred *cred,
207 struct list_head *freelist, int removal)
209 /* here we do the exact thing as asked. but an alternative
210 * way is remove dead entries immediately without be asked
211 * remove, since dead entry will not lead to further rpcs.
213 if (unlikely(ptlrpcs_cred_is_dead(cred))) {
214 /* don't try to destroy a busy entry */
215 if (atomic_read(&cred->pc_refcount))
220 /* a busy non-dead entry is considered as "good" one.
221 * Note in a very busy client where cred always busy, we
222 * will not be able to find the expire here, but some other
223 * part will, e.g. checking during refresh, or got error
224 * notification from server, etc. We don't touch busy cred
225 * here is because a busy cred's flag might be changed at
226 * anytime by the owner, we don't want to compete with them.
228 if (atomic_read(&cred->pc_refcount) != 0)
231 /* expire is 0 means never expire. a newly created gss cred
232 * which during upcall also has 0 expiration
234 if (cred->pc_expire == 0)
237 /* check real expiration */
238 if (time_after(cred->pc_expire, get_seconds()))
241 /* although we'v checked the bit right above, there's still
242 * possibility that somebody else set the bit elsewhere.
244 ptlrpcs_cred_expire(cred);
248 LASSERT(atomic_read(&cred->pc_refcount) >= 0);
249 LASSERT(cred->pc_sec);
250 LASSERT(spin_is_locked(&cred->pc_sec->ps_lock));
253 list_move(&cred->pc_hash, freelist);
259 void ptlrpcs_credcache_gc(struct ptlrpc_sec *sec,
260 struct list_head *freelist)
262 struct ptlrpc_cred *cred, *n;
266 CDEBUG(D_SEC, "do gc on sec %s\n", sec->ps_type->pst_name);
267 for (i = 0; i < PTLRPC_CREDCACHE_NR; i++) {
268 list_for_each_entry_safe(cred, n, &sec->ps_credcache[i],
270 cred_check_dead(cred, freelist, 1);
272 sec->ps_nextgc = get_seconds() + sec->ps_expire;
277 * @uid: which user. "-1" means flush all.
278 * @grace: mark cred DEAD, allow graceful destroy like notify
280 * @force: flush all entries, otherwise only free ones be flushed.
283 int flush_credcache(struct ptlrpc_sec *sec, unsigned long pag, uid_t uid,
284 int grace, int force)
286 struct ptlrpc_cred *cred, *n;
291 might_sleep_if(grace);
293 spin_lock(&sec->ps_lock);
294 for (i = 0; i < PTLRPC_CREDCACHE_NR; i++) {
295 list_for_each_entry_safe(cred, n, &sec->ps_credcache[i],
297 LASSERT(atomic_read(&cred->pc_refcount) >= 0);
299 if (sec->ps_flags & PTLRPC_SEC_FL_PAG) {
300 if (pag != -1 && pag != cred->pc_pag)
303 if (uid != -1 && uid != cred->pc_uid)
307 if (atomic_read(&cred->pc_refcount)) {
311 list_del_init(&cred->pc_hash);
312 CDEBUG(D_SEC, "sec %p: flush busy(%d) cred %p "
314 atomic_read(&cred->pc_refcount), cred);
316 list_move(&cred->pc_hash, &freelist);
318 set_bit(PTLRPC_CRED_DEAD_BIT, &cred->pc_flags);
320 clear_bit(PTLRPC_CRED_UPTODATE_BIT,
324 spin_unlock(&sec->ps_lock);
326 ptlrpcs_destroy_credlist(&freelist);
330 /**************************************************
332 **************************************************/
335 int ptlrpcs_cred_get_hash(__u64 pag)
337 LASSERT((pag & PTLRPC_CREDCACHE_MASK) < PTLRPC_CREDCACHE_NR);
338 return (pag & PTLRPC_CREDCACHE_MASK);
342 * return an uptodate or newly created cred entry.
345 struct ptlrpc_cred * cred_cache_lookup(struct ptlrpc_sec *sec,
346 struct vfs_cred *vcred,
347 int create, int remove_dead)
349 struct ptlrpc_cred *cred, *new = NULL, *n;
356 hash = ptlrpcs_cred_get_hash(vcred->vc_pag);
359 spin_lock(&sec->ps_lock);
361 /* do gc if expired */
363 sec->ps_nextgc && time_after(get_seconds(), sec->ps_nextgc))
364 ptlrpcs_credcache_gc(sec, &freelist);
366 list_for_each_entry_safe(cred, n, &sec->ps_credcache[hash], pc_hash) {
367 if (cred_check_dead(cred, &freelist, remove_dead))
369 if (cred->pc_ops->match(cred, vcred)) {
376 if (new && new != cred) {
377 /* lost the race, just free it */
378 list_add(&new->pc_hash, &freelist);
380 list_move(&cred->pc_hash, &sec->ps_credcache[hash]);
383 list_add(&new->pc_hash, &sec->ps_credcache[hash]);
386 spin_unlock(&sec->ps_lock);
387 new = sec->ps_type->pst_ops->create_cred(sec, vcred);
389 atomic_inc(&sec->ps_credcount);
398 atomic_inc(&cred->pc_refcount);
400 spin_unlock(&sec->ps_lock);
402 ptlrpcs_destroy_credlist(&freelist);
406 struct ptlrpc_cred * ptlrpcs_cred_lookup(struct ptlrpc_sec *sec,
407 struct vfs_cred *vcred)
409 struct ptlrpc_cred *cred;
412 cred = cred_cache_lookup(sec, vcred, 0, 1);
416 static struct ptlrpc_cred *get_cred(struct ptlrpc_sec *sec)
418 struct vfs_cred vcred;
423 (PTLRPC_SEC_FL_MDS | PTLRPC_SEC_FL_OSS | PTLRPC_SEC_FL_REVERSE)) {
427 if (sec->ps_flags & PTLRPC_SEC_FL_PAG)
428 vcred.vc_pag = (__u64) current->pag;
430 vcred.vc_pag = (__u64) current->uid;
431 vcred.vc_uid = current->uid;
434 return cred_cache_lookup(sec, &vcred, 1, 1);
437 int ptlrpcs_req_get_cred(struct ptlrpc_request *req)
439 struct obd_import *imp = req->rq_import;
442 LASSERT(!req->rq_cred);
445 req->rq_cred = get_cred(imp->imp_sec);
448 CERROR("req %p: fail to get cred from cache\n", req);
456 * check whether current user have valid credential for an import or not.
457 * might repeatedly try in case of non-fatal errors.
458 * return 0 on success, 1 on failure
460 int ptlrpcs_check_cred(struct obd_import *imp)
462 struct ptlrpc_cred *cred;
467 cred = get_cred(imp->imp_sec);
471 if (ptlrpcs_cred_is_uptodate(cred)) {
472 /* get_cred() has done expire checking, so we don't
473 * expect it could expire so quickly, and actually
476 ptlrpcs_cred_put(cred, 1);
480 ptlrpcs_cred_refresh(cred);
481 if (ptlrpcs_cred_is_uptodate(cred)) {
482 ptlrpcs_cred_put(cred, 1);
486 if (cred->pc_flags & PTLRPC_CRED_ERROR ||
487 !imp->imp_replayable) {
488 ptlrpcs_cred_put(cred, 1);
492 ptlrpcs_cred_put(cred, 1);
494 if (signal_pending(current)) {
495 CWARN("%s: interrupted\n", current->comm);
501 static void ptlrpcs_sec_destroy(struct ptlrpc_sec *sec);
503 void ptlrpcs_cred_put(struct ptlrpc_cred *cred, int sync)
505 struct ptlrpc_sec *sec = cred->pc_sec;
508 LASSERT(atomic_read(&cred->pc_refcount));
510 spin_lock(&sec->ps_lock);
512 /* this has to be protected by ps_lock, because cred cache
513 * management code might increase ref against a 0-refed cred.
515 if (!atomic_dec_and_test(&cred->pc_refcount)) {
516 spin_unlock(&sec->ps_lock);
520 /* if sec already unused, we have to destroy the cred (prevent it
521 * hanging there for ever)
523 if (atomic_read(&sec->ps_refcount) == 0) {
524 if (!test_and_set_bit(PTLRPC_CRED_DEAD_BIT, &cred->pc_flags))
525 CWARN("cred %p: force expire on a unused sec\n", cred);
526 list_del_init(&cred->pc_hash);
527 } else if (unlikely(sync && ptlrpcs_cred_is_dead(cred)))
528 list_del_init(&cred->pc_hash);
530 if (!list_empty(&cred->pc_hash)) {
531 spin_unlock(&sec->ps_lock);
535 /* if required async, and we reached here, we have to clear
536 * the UPTODATE bit, thus no rpc is needed in destroy procedure.
539 clear_bit(PTLRPC_CRED_UPTODATE_BIT, &cred->pc_flags);
541 spin_unlock(&sec->ps_lock);
543 /* destroy this cred */
544 if (!ptlrpcs_cred_destroy(cred))
547 LASSERT(!atomic_read(&sec->ps_credcount));
548 LASSERT(!atomic_read(&sec->ps_refcount));
550 CWARN("sec %p(%s), put last cred, also destroy the sec\n",
551 sec, sec->ps_type->pst_name);
554 void ptlrpcs_req_drop_cred(struct ptlrpc_request *req)
559 LASSERT(req->rq_cred);
562 /* this could be called with spinlock hold, use async mode */
563 ptlrpcs_cred_put(req->rq_cred, 0);
566 CDEBUG(D_SEC, "req %p have no cred\n", req);
571 * request must have a cred. if failed to get new cred,
572 * just restore the old one
574 int ptlrpcs_req_replace_dead_cred(struct ptlrpc_request *req)
576 struct ptlrpc_cred *cred = req->rq_cred;
581 LASSERT(test_bit(PTLRPC_CRED_DEAD_BIT, &cred->pc_flags));
583 ptlrpcs_cred_get(cred);
584 ptlrpcs_req_drop_cred(req);
585 LASSERT(!req->rq_cred);
586 rc = ptlrpcs_req_get_cred(req);
588 LASSERT(req->rq_cred);
589 LASSERT(req->rq_cred != cred);
590 ptlrpcs_cred_put(cred, 1);
592 LASSERT(!req->rq_cred);
599 * since there's no lock on the cred, its status could be changed
600 * by other threads at any time, we allow this race. If an uptodate
601 * cred turn to dead quickly under us, we don't know and continue
602 * using it, that's fine. if necessary the later error handling code
605 int ptlrpcs_req_refresh_cred(struct ptlrpc_request *req)
607 struct ptlrpc_cred *cred = req->rq_cred;
612 if (!ptlrpcs_cred_check_uptodate(cred))
615 if (test_bit(PTLRPC_CRED_ERROR_BIT, &cred->pc_flags)) {
616 req->rq_ptlrpcs_err = 1;
620 if (test_bit(PTLRPC_CRED_DEAD_BIT, &cred->pc_flags)) {
621 if (ptlrpcs_req_replace_dead_cred(req) == 0) {
622 LASSERT(cred != req->rq_cred);
623 CDEBUG(D_SEC, "req %p: replace cred %p => %p\n",
624 req, cred, req->rq_cred);
627 LASSERT(cred == req->rq_cred);
628 CERROR("req %p: failed to replace dead cred %p\n",
630 req->rq_ptlrpcs_err = 1;
635 ptlrpcs_cred_refresh(cred);
637 if (!ptlrpcs_cred_is_uptodate(cred)) {
638 if (test_bit(PTLRPC_CRED_ERROR_BIT, &cred->pc_flags))
639 req->rq_ptlrpcs_err = 1;
641 CERROR("req %p: failed to refresh cred %p, fatal %d\n",
642 req, cred, req->rq_ptlrpcs_err);
648 int ptlrpcs_cli_wrap_request(struct ptlrpc_request *req)
650 struct ptlrpc_cred *cred;
654 LASSERT(req->rq_cred);
655 LASSERT(req->rq_cred->pc_sec);
656 LASSERT(req->rq_cred->pc_ops);
657 LASSERT(req->rq_reqbuf);
658 LASSERT(req->rq_reqbuf_len);
660 rc = ptlrpcs_req_refresh_cred(req);
664 CDEBUG(D_SEC, "wrap req %p\n", req);
667 switch (SEC_FLAVOR_SVC(req->rq_req_secflvr)) {
668 case PTLRPCS_SVC_NONE:
669 case PTLRPCS_SVC_AUTH:
670 if (req->rq_req_wrapped) {
671 CDEBUG(D_SEC, "req %p(o%u,x"LPU64",t"LPU64") "
672 "already signed, resend?\n", req,
673 req->rq_reqmsg ? req->rq_reqmsg->opc : -1,
674 req->rq_xid, req->rq_transno);
675 req->rq_req_wrapped = 0;
676 req->rq_reqdata_len = sizeof(struct ptlrpcs_wire_hdr) +
678 LASSERT(req->rq_reqdata_len % 8 == 0);
681 LASSERT(cred->pc_ops->sign);
682 rc = cred->pc_ops->sign(cred, req);
684 req->rq_req_wrapped = 1;
686 case PTLRPCS_SVC_PRIV:
687 if (req->rq_req_wrapped) {
688 CDEBUG(D_SEC, "req %p(o%u,x"LPU64",t"LPU64") "
689 "already encrypted, resend?\n", req,
690 req->rq_reqmsg ? req->rq_reqmsg->opc : -1,
691 req->rq_xid, req->rq_transno);
692 req->rq_req_wrapped = 0;
693 req->rq_reqdata_len = sizeof(struct ptlrpcs_wire_hdr);
694 LASSERT(req->rq_reqdata_len % 8 == 0);
697 LASSERT(cred->pc_ops->seal);
698 rc = cred->pc_ops->seal(cred, req);
700 req->rq_req_wrapped = 1;
705 LASSERT(req->rq_reqdata_len);
706 LASSERT(req->rq_reqdata_len % 8 == 0);
707 LASSERT(req->rq_reqdata_len >= sizeof(struct ptlrpcs_wire_hdr));
708 LASSERT(req->rq_reqdata_len <= req->rq_reqbuf_len);
713 /* rq_nob_received is the actual received data length */
714 int ptlrpcs_cli_unwrap_reply(struct ptlrpc_request *req)
716 struct ptlrpc_cred *cred = req->rq_cred;
717 struct ptlrpc_sec *sec;
718 struct ptlrpcs_wire_hdr *sec_hdr;
723 LASSERT(cred->pc_sec);
724 LASSERT(cred->pc_ops);
725 LASSERT(req->rq_repbuf);
727 if (req->rq_nob_received < sizeof(*sec_hdr)) {
728 CERROR("req %p: reply size only %d\n",
729 req, req->rq_nob_received);
733 sec_hdr = (struct ptlrpcs_wire_hdr *) req->rq_repbuf;
734 sec_hdr->flavor = le32_to_cpu(sec_hdr->flavor);
735 sec_hdr->msg_len = le32_to_cpu(sec_hdr->msg_len);
736 sec_hdr->sec_len = le32_to_cpu(sec_hdr->sec_len);
738 CDEBUG(D_SEC, "req %p, cred %p, flavor 0x%x\n",
739 req, cred, sec_hdr->flavor);
743 /* only compare major flavor, reply might use different subflavor.
745 if (SEC_FLAVOR_MAJOR(sec_hdr->flavor) !=
746 SEC_FLAVOR_MAJOR(req->rq_req_secflvr)) {
747 CERROR("got major flavor %u while expect %u\n",
748 SEC_FLAVOR_MAJOR(sec_hdr->flavor),
749 SEC_FLAVOR_MAJOR(req->rq_req_secflvr));
753 if (sizeof(*sec_hdr) + sec_hdr->msg_len + sec_hdr->sec_len >
754 req->rq_nob_received) {
755 CERROR("msg %u, sec %u, while only get %d\n",
756 sec_hdr->msg_len, sec_hdr->sec_len,
757 req->rq_nob_received);
761 switch (SEC_FLAVOR_SVC(sec_hdr->flavor)) {
762 case PTLRPCS_SVC_NONE:
763 case PTLRPCS_SVC_AUTH: {
764 LASSERT(cred->pc_ops->verify);
765 rc = cred->pc_ops->verify(cred, req);
766 LASSERT(rc || req->rq_repmsg || req->rq_ptlrpcs_restart);
768 case PTLRPCS_SVC_PRIV:
769 LASSERT(cred->pc_ops->unseal);
770 rc = cred->pc_ops->unseal(cred, req);
771 LASSERT(rc || req->rq_repmsg || req->rq_ptlrpcs_restart);
781 /**************************************************
783 **************************************************/
785 struct ptlrpc_sec * ptlrpcs_sec_create(__u32 flavor,
787 struct obd_import *import,
788 const char *pipe_dir,
791 struct ptlrpc_sec_type *type;
792 struct ptlrpc_sec *sec;
795 type = ptlrpcs_flavor2type(flavor);
797 CERROR("invalid flavor 0x%x\n", flavor);
801 sec = type->pst_ops->create_sec(flavor, pipe_dir, pipe_data);
803 spin_lock_init(&sec->ps_lock);
804 ptlrpcs_init_credcache(sec);
806 sec->ps_flavor = flavor;
807 sec->ps_flags = flags;
808 sec->ps_import = class_import_get(import);
809 atomic_set(&sec->ps_refcount, 1);
810 atomic_set(&sec->ps_credcount, 0);
811 atomic_inc(&type->pst_inst);
813 ptlrpcs_type_put(type);
818 static void ptlrpcs_sec_destroy(struct ptlrpc_sec *sec)
820 struct ptlrpc_sec_type *type = sec->ps_type;
821 struct obd_import *imp = sec->ps_import;
823 LASSERT(type && type->pst_ops);
824 LASSERT(type->pst_ops->destroy_sec);
826 type->pst_ops->destroy_sec(sec);
827 atomic_dec(&type->pst_inst);
828 ptlrpcs_type_put(type);
829 class_import_put(imp);
832 void ptlrpcs_sec_put(struct ptlrpc_sec *sec)
836 if (atomic_dec_and_test(&sec->ps_refcount)) {
837 flush_credcache(sec, -1, -1, 1, 1);
839 /* this spinlock is protect against ptlrpcs_cred_destroy() */
840 spin_lock(&sec->ps_lock);
841 ncred = atomic_read(&sec->ps_credcount);
842 spin_unlock(&sec->ps_lock);
845 ptlrpcs_sec_destroy(sec);
847 CWARN("%s %p is no usage while %d cred still "
848 "holded, destroy delayed\n",
849 sec->ps_type->pst_name, sec,
850 atomic_read(&sec->ps_credcount));
855 void ptlrpcs_sec_invalidate_cache(struct ptlrpc_sec *sec)
857 flush_credcache(sec, -1, -1, 0, 1);
860 int sec_alloc_reqbuf(struct ptlrpc_sec *sec,
861 struct ptlrpc_request *req,
862 int msgsize, int secsize)
864 struct ptlrpcs_wire_hdr *hdr;
867 LASSERT(msgsize % 8 == 0);
868 LASSERT(secsize % 8 == 0);
870 req->rq_reqbuf_len = sizeof(*hdr) + msgsize + secsize;
871 OBD_ALLOC(req->rq_reqbuf, req->rq_reqbuf_len);
872 if (!req->rq_reqbuf) {
873 CERROR("can't alloc %d\n", req->rq_reqbuf_len);
877 hdr = buf_to_sec_hdr(req->rq_reqbuf);
878 hdr->flavor = cpu_to_le32(req->rq_req_secflvr);
879 hdr->msg_len = msgsize;
880 /* security length will be filled later */
882 /* later reqdata_len will be added on actual security payload */
883 req->rq_reqdata_len = sizeof(*hdr) + msgsize;
884 req->rq_reqmsg = buf_to_lustre_msg(req->rq_reqbuf);
886 CDEBUG(D_SEC, "req %p: rqbuf at %p, len %d, msg %d, sec %d\n",
887 req, req->rq_reqbuf, req->rq_reqbuf_len,
893 /* when complete successfully, req->rq_reqmsg should point to the
896 int ptlrpcs_cli_alloc_reqbuf(struct ptlrpc_request *req, int msgsize)
898 struct ptlrpc_cred *cred = req->rq_cred;
899 struct ptlrpc_sec *sec;
900 struct ptlrpc_secops *ops;
902 LASSERT(msgsize % 8 == 0);
903 LASSERT(sizeof(struct ptlrpcs_wire_hdr) % 8 == 0);
905 LASSERT(atomic_read(&cred->pc_refcount));
906 LASSERT(cred->pc_sec);
907 LASSERT(cred->pc_sec->ps_type);
908 LASSERT(cred->pc_sec->ps_type->pst_ops);
909 LASSERT(req->rq_reqbuf == NULL);
910 LASSERT(req->rq_reqmsg == NULL);
913 ops = sec->ps_type->pst_ops;
914 if (ops->alloc_reqbuf)
915 return ops->alloc_reqbuf(sec, req, msgsize);
917 return sec_alloc_reqbuf(sec, req, msgsize, 0);
920 void sec_free_reqbuf(struct ptlrpc_sec *sec,
921 struct ptlrpc_request *req)
923 LASSERT(req->rq_reqbuf);
924 LASSERT(req->rq_reqbuf_len);
927 if (req->rq_reqmsg) {
928 LASSERT((char *) req->rq_reqmsg >= req->rq_reqbuf &&
929 (char *) req->rq_reqmsg < req->rq_reqbuf +
933 OBD_FREE(req->rq_reqbuf, req->rq_reqbuf_len);
934 req->rq_reqbuf = NULL;
935 req->rq_reqmsg = NULL;
938 void ptlrpcs_cli_free_reqbuf(struct ptlrpc_request *req)
940 struct ptlrpc_cred *cred = req->rq_cred;
941 struct ptlrpc_sec *sec;
942 struct ptlrpc_secops *ops;
945 LASSERT(atomic_read(&cred->pc_refcount));
946 LASSERT(cred->pc_sec);
947 LASSERT(cred->pc_sec->ps_type);
948 LASSERT(cred->pc_sec->ps_type->pst_ops);
949 LASSERT(req->rq_reqbuf);
952 ops = sec->ps_type->pst_ops;
953 if (ops->free_reqbuf)
954 ops->free_reqbuf(sec, req);
956 sec_free_reqbuf(sec, req);
959 int ptlrpcs_cli_alloc_repbuf(struct ptlrpc_request *req, int msgsize)
961 struct ptlrpc_cred *cred = req->rq_cred;
962 struct ptlrpc_sec *sec;
963 struct ptlrpc_secops *ops;
964 int msg_payload, sec_payload;
967 LASSERT(msgsize % 8 == 0);
968 LASSERT(sizeof(struct ptlrpcs_wire_hdr) % 8 == 0);
970 LASSERT(atomic_read(&cred->pc_refcount));
971 LASSERT(cred->pc_sec);
972 LASSERT(cred->pc_sec->ps_type);
973 LASSERT(cred->pc_sec->ps_type->pst_ops);
974 LASSERT(req->rq_repbuf == NULL);
977 ops = sec->ps_type->pst_ops;
978 if (ops->alloc_repbuf)
979 RETURN(ops->alloc_repbuf(sec, req, msgsize));
981 /* default allocation scheme */
982 msg_payload = SEC_FLAVOR_SVC(req->rq_req_secflvr) == PTLRPCS_SVC_PRIV ?
984 sec_payload = size_round(ptlrpcs_est_rep_payload(req, msgsize));
986 req->rq_repbuf_len = sizeof(struct ptlrpcs_wire_hdr) +
987 msg_payload + sec_payload;
988 OBD_ALLOC(req->rq_repbuf, req->rq_repbuf_len);
992 CDEBUG(D_SEC, "req %p: repbuf at %p, len %d, msg %d, sec %d\n",
993 req, req->rq_repbuf, req->rq_repbuf_len,
994 msg_payload, sec_payload);
999 void ptlrpcs_cli_free_repbuf(struct ptlrpc_request *req)
1001 struct ptlrpc_cred *cred = req->rq_cred;
1002 struct ptlrpc_sec *sec;
1003 struct ptlrpc_secops *ops;
1007 LASSERT(atomic_read(&cred->pc_refcount));
1008 LASSERT(cred->pc_sec);
1009 LASSERT(cred->pc_sec->ps_type);
1010 LASSERT(cred->pc_sec->ps_type->pst_ops);
1011 LASSERT(req->rq_repbuf);
1014 ops = sec->ps_type->pst_ops;
1015 if (ops->free_repbuf)
1016 ops->free_repbuf(sec, req);
1018 OBD_FREE(req->rq_repbuf, req->rq_repbuf_len);
1019 req->rq_repbuf = NULL;
1020 req->rq_repmsg = NULL;
1025 int ptlrpcs_import_get_sec(struct obd_import *imp)
1027 __u32 flavor = PTLRPCS_FLVR_NULL;
1028 unsigned long flags = 0;
1029 char *pipedir = NULL;
1032 LASSERT(imp->imp_obd);
1033 LASSERT(imp->imp_obd->obd_type);
1035 /* old sec might be still there in reconnecting */
1039 /* find actual flavor for client obd. right now server side
1040 * obd (reverse imp, etc) will simply use NULL. */
1041 if (!strcmp(imp->imp_obd->obd_type->typ_name, OBD_MDC_DEVICENAME) ||
1042 !strcmp(imp->imp_obd->obd_type->typ_name, OBD_OSC_DEVICENAME)) {
1043 struct client_obd *cli = &imp->imp_obd->u.cli;
1045 switch (SEC_FLAVOR_MAJOR(cli->cl_sec_flavor)) {
1046 case PTLRPCS_FLVR_MAJOR_NULL:
1047 CWARN("select security null for %s(%s)\n",
1048 imp->imp_obd->obd_type->typ_name,
1049 imp->imp_obd->obd_name);
1051 case PTLRPCS_FLVR_MAJOR_GSS:
1052 CWARN("select security %s for %s(%s)\n",
1053 ptlrpcs_flavor2name(cli->cl_sec_flavor),
1054 imp->imp_obd->obd_type->typ_name,
1055 imp->imp_obd->obd_name);
1056 flavor = cli->cl_sec_flavor;
1057 pipedir = imp->imp_obd->obd_name;
1060 CWARN("unknown security flavor for %s(%s), "
1062 imp->imp_obd->obd_type->typ_name,
1063 imp->imp_obd->obd_name);
1066 flags = cli->cl_sec_flags;
1069 imp->imp_sec = ptlrpcs_sec_create(flavor, flags, imp, pipedir, imp);
1076 void ptlrpcs_import_drop_sec(struct obd_import *imp)
1080 ptlrpcs_sec_put(imp->imp_sec);
1081 imp->imp_sec = NULL;
1086 void ptlrpcs_import_flush_current_creds(struct obd_import *imp)
1090 class_import_get(imp);
1092 flush_credcache(imp->imp_sec, current->pag, current->uid, 1, 1);
1093 class_import_put(imp);
1096 int __init ptlrpc_sec_init(void)
1100 if ((rc = ptlrpcs_null_init()))
1103 if ((rc = svcsec_null_init())) {
1104 ptlrpcs_null_exit();
1109 #if !defined __KERNEL__ && defined ENABLE_GSS
1116 #if defined __KERNEL__ && defined ENABLE_GSS
1117 static void __exit ptlrpc_sec_exit(void)
1120 ptlrpcs_null_exit();
1124 EXPORT_SYMBOL(ptlrpcs_register);
1125 EXPORT_SYMBOL(ptlrpcs_unregister);
1126 EXPORT_SYMBOL(ptlrpcs_sec_create);
1127 EXPORT_SYMBOL(ptlrpcs_sec_put);
1128 EXPORT_SYMBOL(ptlrpcs_sec_invalidate_cache);
1129 EXPORT_SYMBOL(ptlrpcs_import_get_sec);
1130 EXPORT_SYMBOL(ptlrpcs_import_drop_sec);
1131 EXPORT_SYMBOL(ptlrpcs_import_flush_current_creds);
1132 EXPORT_SYMBOL(ptlrpcs_cred_lookup);
1133 EXPORT_SYMBOL(ptlrpcs_cred_put);
1134 EXPORT_SYMBOL(ptlrpcs_req_get_cred);
1135 EXPORT_SYMBOL(ptlrpcs_req_drop_cred);
1136 EXPORT_SYMBOL(ptlrpcs_req_replace_dead_cred);
1137 EXPORT_SYMBOL(ptlrpcs_req_refresh_cred);
1138 EXPORT_SYMBOL(ptlrpcs_check_cred);
1139 EXPORT_SYMBOL(ptlrpcs_cli_alloc_reqbuf);
1140 EXPORT_SYMBOL(ptlrpcs_cli_free_reqbuf);
1141 EXPORT_SYMBOL(ptlrpcs_cli_alloc_repbuf);
1142 EXPORT_SYMBOL(ptlrpcs_cli_free_repbuf);
1143 EXPORT_SYMBOL(ptlrpcs_cli_wrap_request);
1144 EXPORT_SYMBOL(ptlrpcs_cli_unwrap_reply);
1145 EXPORT_SYMBOL(sec_alloc_reqbuf);
1146 EXPORT_SYMBOL(sec_free_reqbuf);
1148 EXPORT_SYMBOL(svcsec_register);
1149 EXPORT_SYMBOL(svcsec_unregister);
1150 EXPORT_SYMBOL(svcsec_accept);
1151 EXPORT_SYMBOL(svcsec_authorize);
1152 EXPORT_SYMBOL(svcsec_alloc_repbuf);
1153 EXPORT_SYMBOL(svcsec_cleanup_req);
1154 EXPORT_SYMBOL(svcsec_get);
1155 EXPORT_SYMBOL(svcsec_put);
1156 EXPORT_SYMBOL(svcsec_alloc_reply_state);
1157 EXPORT_SYMBOL(svcsec_free_reply_state);
1159 EXPORT_SYMBOL(ptlrpcs_name2flavor);
1160 EXPORT_SYMBOL(ptlrpcs_flavor2name);
1162 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
1163 MODULE_DESCRIPTION("Lustre Security Support");
1164 MODULE_LICENSE("GPL");
1166 module_init(ptlrpc_sec_init);
1167 module_exit(ptlrpc_sec_exit);