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_support.h>
36 #include <linux/lustre_idl.h>
37 #include <linux/lustre_net.h>
38 #include <linux/lustre_sec.h>
40 static spinlock_t svcsecs_lock = SPIN_LOCK_UNLOCKED;
41 static struct ptlrpc_svcsec *svcsecs[PTLRPC_SEC_MAX_FLAVORS] = {
45 int svcsec_register(struct ptlrpc_svcsec *sec)
47 __u32 flavor = sec->pss_flavor.flavor;
49 if (flavor >= PTLRPC_SEC_MAX_FLAVORS)
52 spin_lock(&svcsecs_lock);
53 if (svcsecs[flavor]) {
54 spin_unlock(&svcsecs_lock);
57 svcsecs[flavor] = sec;
58 spin_unlock(&svcsecs_lock);
60 CDEBUG(D_SEC, "Registered svc security module %s\n", sec->pss_name);
64 int svcsec_unregister(struct ptlrpc_svcsec *sec)
66 __u32 flavor = sec->pss_flavor.flavor;
68 if (flavor >= PTLRPC_SEC_MAX_FLAVORS)
71 spin_lock(&svcsecs_lock);
72 if (!svcsecs[flavor]) {
73 spin_unlock(&svcsecs_lock);
77 LASSERT(svcsecs[flavor] == sec);
79 CDEBUG(D_SEC, "Unregistered svc security module %s\n", sec->pss_name);
80 svcsecs[flavor] = NULL;
81 spin_unlock(&svcsecs_lock);
87 struct ptlrpc_svcsec * flavor2svcsec(__u32 flavor)
89 struct ptlrpc_svcsec *sec;
91 if (flavor >= PTLRPC_SEC_MAX_FLAVORS)
94 spin_lock(&svcsecs_lock);
95 sec = svcsecs[flavor];
96 if (sec && !try_module_get(sec->pss_owner))
98 spin_unlock(&svcsecs_lock);
102 struct ptlrpc_svcsec * svcsec_get(struct ptlrpc_svcsec *sec)
106 // spin_lock(&svcsecs_lock);
107 rc = try_module_get(sec->pss_owner);
108 // spin_unlock(&svcsecs_lock);
113 void svcsec_put(struct ptlrpc_svcsec *sec)
115 // spin_lock(&svcsecs_lock);
116 module_put(sec->pss_owner);
117 // spin_unlock(&svcsecs_lock);
121 * common code to allocate reply_state buffer.
123 int svcsec_alloc_reply_state(struct ptlrpc_request *req,
124 int msgsize, int secsize)
126 struct ptlrpc_reply_state *rs;
128 int repsize, bufsize;
131 LASSERT(msgsize % 8 == 0);
132 LASSERT(secsize % 8 == 0);
134 repsize = sizeof(struct ptlrpcs_wire_hdr) + msgsize + secsize;
135 bufsize = repsize + sizeof(struct ptlrpc_reply_state);
137 OBD_ALLOC(buf, bufsize);
139 CERROR("can't alloc %d\n", bufsize);
143 /* req->rq_repbuf is not used on server side */
144 rs = (struct ptlrpc_reply_state *) (buf + repsize);
146 rs->rs_buf_len = bufsize;
148 rs->rs_repbuf_len = repsize;
149 /* current known data length is hdr + msg, security payload
150 * will be added on later.
152 rs->rs_repdata_len = sizeof(struct ptlrpcs_wire_hdr) + msgsize;
153 req->rq_repmsg = rs->rs_msg = (struct lustre_msg *)
154 (rs->rs_repbuf + sizeof(struct ptlrpcs_wire_hdr));
156 req->rq_reply_state = rs;
158 CDEBUG(D_SEC, "alloc rs buf at %p, len %d; repbuf at %p, len %d\n",
159 rs->rs_buf, rs->rs_buf_len, rs->rs_repbuf, rs->rs_repbuf_len);
164 void svcsec_free_reply_state(struct ptlrpc_reply_state *rs)
169 /* for work around memory-alloc debug poison */
172 OBD_FREE(p, rs->rs_buf_len);
176 int svcsec_alloc_repbuf(struct ptlrpc_svcsec *svcsec,
177 struct ptlrpc_request *req,
181 LASSERT(msgsize % 8 == 0);
183 if (svcsec->alloc_repbuf)
184 return svcsec->alloc_repbuf(svcsec, req, msgsize);
186 return svcsec_alloc_reply_state(req, msgsize, 0);
189 int svcsec_accept(struct ptlrpc_request *req, enum ptlrpcs_error *res)
191 struct ptlrpc_svcsec *sec;
192 struct ptlrpcs_wire_hdr *sec_hdr;
196 LASSERT(req->rq_reqbuf);
197 LASSERT(!req->rq_reqmsg);
198 LASSERT(!req->rq_svcsec);
200 *res = PTLRPCS_BADCRED;
201 if (req->rq_reqbuf_len < sizeof(*sec_hdr)) {
202 CERROR("drop too short msg (length: %d)\n", req->rq_reqbuf_len);
206 sec_hdr = (struct ptlrpcs_wire_hdr *) req->rq_reqbuf;
207 sec_hdr->flavor = le32_to_cpu(sec_hdr->flavor);
208 sec_hdr->sectype = le32_to_cpu(sec_hdr->sectype);
209 sec_hdr->msg_len = le32_to_cpu(sec_hdr->msg_len);
210 sec_hdr->sec_len = le32_to_cpu(sec_hdr->sec_len);
213 switch (sec_hdr->sectype) {
214 case PTLRPC_SEC_TYPE_NONE:
215 case PTLRPC_SEC_TYPE_AUTH:
216 case PTLRPC_SEC_TYPE_PRIV:
219 CERROR("unknown security type %d\n", sec_hdr->sectype);
223 if (sizeof(*sec_hdr) + sec_hdr->msg_len + sec_hdr->sec_len >
224 req->rq_reqbuf_len) {
225 CERROR("received %d, msg %d, sec %d\n",
226 req->rq_reqbuf_len, sec_hdr->msg_len, sec_hdr->sec_len);
230 req->rq_svcsec = sec = flavor2svcsec(sec_hdr->flavor);
232 CERROR("drop msg: unsupported flavor %d\n", sec_hdr->flavor);
235 LASSERT(sec->accept);
237 rc = sec->accept(req, res);
242 req->rq_svcsec = NULL;
247 LASSERT(req->rq_reqmsg);
254 int svcsec_authorize(struct ptlrpc_request *req)
256 LASSERT(req->rq_svcsec);
257 LASSERT(req->rq_svcsec->authorize);
259 return (req->rq_svcsec->authorize(req));
262 void svcsec_cleanup_req(struct ptlrpc_request *req)
264 struct ptlrpc_svcsec *svcsec = req->rq_svcsec;
268 LASSERT(svcsec->cleanup_req || !req->rq_sec_svcdata);
270 if (svcsec->cleanup_req)
271 svcsec->cleanup_req(svcsec, req);