1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2006 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
28 #include <liblustre.h>
31 #include <obd_support.h>
32 #include <obd_class.h>
33 #include <lustre_net.h>
34 #include <lustre_sec.h>
36 static struct ptlrpc_sec_policy plain_policy;
37 static struct ptlrpc_sec plain_sec;
38 static struct ptlrpc_cli_ctx plain_cli_ctx;
39 static struct ptlrpc_svc_ctx plain_svc_ctx;
42 int plain_ctx_refresh(struct ptlrpc_cli_ctx *ctx)
44 /* should never reach here */
50 int plain_ctx_sign(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
52 struct lustre_msg_v2 *msg = req->rq_reqbuf;
55 msg->lm_secflvr = req->rq_sec_flavor;
56 req->rq_reqdata_len = lustre_msg_size_v2(msg->lm_bufcount,
62 int plain_ctx_verify(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
64 struct lustre_msg *msg = req->rq_repbuf;
67 if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
68 if (msg->lm_bufcount != 2) {
69 CERROR("Protocol error: invalid buf count %d\n",
74 if (bulk_sec_desc_unpack(msg, 1)) {
75 CERROR("Mal-formed bulk checksum reply\n");
80 req->rq_repmsg = lustre_msg_buf(msg, 0, 0);
81 req->rq_replen = msg->lm_buflens[0];
86 int plain_cli_wrap_bulk(struct ptlrpc_cli_ctx *ctx,
87 struct ptlrpc_request *req,
88 struct ptlrpc_bulk_desc *desc)
90 struct sec_flavor_config *conf;
92 LASSERT(req->rq_import);
93 LASSERT(SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor));
94 LASSERT(req->rq_reqbuf->lm_bufcount >= 2);
96 conf = &req->rq_import->imp_obd->u.cli.cl_sec_conf;
97 return bulk_csum_cli_request(desc, req->rq_bulk_read,
100 req->rq_reqbuf->lm_bufcount - 1);
104 int plain_cli_unwrap_bulk(struct ptlrpc_cli_ctx *ctx,
105 struct ptlrpc_request *req,
106 struct ptlrpc_bulk_desc *desc)
108 LASSERT(SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor));
109 LASSERT(req->rq_reqbuf->lm_bufcount >= 2);
110 LASSERT(req->rq_repbuf->lm_bufcount >= 2);
112 return bulk_csum_cli_reply(desc, req->rq_bulk_read,
114 req->rq_reqbuf->lm_bufcount - 1,
116 req->rq_repbuf->lm_bufcount - 1);
119 static struct ptlrpc_ctx_ops plain_ctx_ops = {
120 .refresh = plain_ctx_refresh,
121 .sign = plain_ctx_sign,
122 .verify = plain_ctx_verify,
123 .wrap_bulk = plain_cli_wrap_bulk,
124 .unwrap_bulk = plain_cli_unwrap_bulk,
127 static struct ptlrpc_svc_ctx plain_svc_ctx = {
128 .sc_refcount = ATOMIC_INIT(1),
129 .sc_policy = &plain_policy,
133 struct ptlrpc_sec* plain_create_sec(struct obd_import *imp,
134 struct ptlrpc_svc_ctx *ctx,
139 LASSERT(SEC_FLAVOR_POLICY(flavor) == SPTLRPC_POLICY_PLAIN);
144 void plain_destroy_sec(struct ptlrpc_sec *sec)
147 LASSERT(sec == &plain_sec);
152 struct ptlrpc_cli_ctx *plain_lookup_ctx(struct ptlrpc_sec *sec,
153 struct vfs_cred *vcred,
154 int create, int remove_dead)
157 atomic_inc(&plain_cli_ctx.cc_refcount);
158 RETURN(&plain_cli_ctx);
162 int plain_flush_ctx_cache(struct ptlrpc_sec *sec,
164 int grace, int force)
170 int plain_alloc_reqbuf(struct ptlrpc_sec *sec,
171 struct ptlrpc_request *req,
174 struct sec_flavor_config *conf;
175 int bufcnt = 1, buflens[2], alloc_len;
178 buflens[0] = msgsize;
180 if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor))
181 buflens[bufcnt++] = sptlrpc_current_user_desc_size();
183 if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
184 LASSERT(req->rq_bulk_read || req->rq_bulk_write);
186 conf = &req->rq_import->imp_obd->u.cli.cl_sec_conf;
187 buflens[bufcnt++] = bulk_sec_desc_size(conf->sfc_bulk_csum, 1,
191 alloc_len = lustre_msg_size_v2(bufcnt, buflens);
193 if (!req->rq_reqbuf) {
194 LASSERT(!req->rq_pool);
196 alloc_len = size_roundup_power2(alloc_len);
197 OBD_ALLOC(req->rq_reqbuf, alloc_len);
201 req->rq_reqbuf_len = alloc_len;
203 LASSERT(req->rq_pool);
204 LASSERT(req->rq_reqbuf_len >= alloc_len);
205 memset(req->rq_reqbuf, 0, alloc_len);
208 lustre_init_msg_v2(req->rq_reqbuf, bufcnt, buflens, NULL);
209 req->rq_reqmsg = lustre_msg_buf_v2(req->rq_reqbuf, 0, 0);
211 if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor))
212 sptlrpc_pack_user_desc(req->rq_reqbuf, 1);
218 void plain_free_reqbuf(struct ptlrpc_sec *sec,
219 struct ptlrpc_request *req)
223 OBD_FREE(req->rq_reqbuf, req->rq_reqbuf_len);
224 req->rq_reqbuf = NULL;
225 req->rq_reqbuf_len = 0;
231 int plain_alloc_repbuf(struct ptlrpc_sec *sec,
232 struct ptlrpc_request *req,
235 struct sec_flavor_config *conf;
236 int bufcnt = 1, buflens[2], alloc_len;
239 buflens[0] = msgsize;
241 if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
242 LASSERT(req->rq_bulk_read || req->rq_bulk_write);
244 conf = &req->rq_import->imp_obd->u.cli.cl_sec_conf;
245 buflens[bufcnt++] = bulk_sec_desc_size(conf->sfc_bulk_csum, 0,
249 alloc_len = lustre_msg_size_v2(bufcnt, buflens);
250 alloc_len = size_roundup_power2(alloc_len);
252 OBD_ALLOC(req->rq_repbuf, alloc_len);
256 req->rq_repbuf_len = alloc_len;
261 void plain_free_repbuf(struct ptlrpc_sec *sec,
262 struct ptlrpc_request *req)
265 OBD_FREE(req->rq_repbuf, req->rq_repbuf_len);
266 req->rq_repbuf = NULL;
267 req->rq_repbuf_len = 0;
272 int plain_enlarge_reqbuf(struct ptlrpc_sec *sec,
273 struct ptlrpc_request *req,
274 int segment, int newsize)
276 struct lustre_msg *newbuf;
278 int newmsg_size, newbuf_size;
281 /* embedded msg always at seg 0 */
282 LASSERT(req->rq_reqbuf);
283 LASSERT(req->rq_reqbuf_len >= req->rq_reqlen);
284 LASSERT(lustre_msg_buf(req->rq_reqbuf, 0, 0) == req->rq_reqmsg);
286 /* compute new embedded msg size. */
287 oldsize = req->rq_reqmsg->lm_buflens[segment];
288 req->rq_reqmsg->lm_buflens[segment] = newsize;
289 newmsg_size = lustre_msg_size_v2(req->rq_reqmsg->lm_bufcount,
290 req->rq_reqmsg->lm_buflens);
291 req->rq_reqmsg->lm_buflens[segment] = oldsize;
293 /* compute new wrapper msg size. */
294 oldsize = req->rq_reqbuf->lm_buflens[0];
295 req->rq_reqbuf->lm_buflens[0] = newmsg_size;
296 newbuf_size = lustre_msg_size_v2(req->rq_reqbuf->lm_bufcount,
297 req->rq_reqbuf->lm_buflens);
298 req->rq_reqbuf->lm_buflens[0] = oldsize;
300 /* request from pool should always have enough buffer */
301 LASSERT(!req->rq_pool || req->rq_reqbuf_len >= newbuf_size);
303 if (req->rq_reqbuf_len < newbuf_size) {
304 newbuf_size = size_roundup_power2(newbuf_size);
306 OBD_ALLOC(newbuf, newbuf_size);
310 memcpy(newbuf, req->rq_reqbuf, req->rq_reqbuf_len);
312 OBD_FREE(req->rq_reqbuf, req->rq_reqbuf_len);
313 req->rq_reqbuf = newbuf;
314 req->rq_reqbuf_len = newbuf_size;
315 req->rq_reqmsg = lustre_msg_buf(req->rq_reqbuf, 0, 0);
318 _sptlrpc_enlarge_msg_inplace(req->rq_reqbuf, 0, newmsg_size);
319 _sptlrpc_enlarge_msg_inplace(req->rq_reqmsg, segment, newsize);
321 req->rq_reqlen = newmsg_size;
326 int plain_accept(struct ptlrpc_request *req)
328 struct lustre_msg *msg = req->rq_reqbuf;
332 LASSERT(SEC_FLAVOR_POLICY(req->rq_sec_flavor) == SPTLRPC_POLICY_PLAIN);
334 if (SEC_FLAVOR_RPC(req->rq_sec_flavor) != SPTLRPC_FLVR_PLAIN) {
335 CERROR("Invalid flavor 0x%x\n", req->rq_sec_flavor);
339 if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor)) {
340 if (msg->lm_bufcount < ++bufcnt) {
341 CERROR("Protocal error: too small buf count %d\n",
346 if (sptlrpc_unpack_user_desc(msg, bufcnt - 1)) {
347 CERROR("Mal-formed user descriptor\n");
351 req->rq_user_desc = lustre_msg_buf(msg, bufcnt - 1, 0);
354 if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
355 if (msg->lm_bufcount != ++bufcnt) {
356 CERROR("Protocal error: invalid buf count %d\n",
361 if (bulk_sec_desc_unpack(msg, bufcnt - 1)) {
362 CERROR("Mal-formed bulk checksum request\n");
367 req->rq_reqmsg = lustre_msg_buf(msg, 0, 0);
368 req->rq_reqlen = msg->lm_buflens[0];
370 req->rq_svc_ctx = &plain_svc_ctx;
371 atomic_inc(&req->rq_svc_ctx->sc_refcount);
377 int plain_alloc_rs(struct ptlrpc_request *req, int msgsize)
379 struct ptlrpc_reply_state *rs;
380 struct ptlrpc_bulk_sec_desc *bsd;
381 int bufcnt = 1, buflens[2];
382 int rs_size = sizeof(*rs);
385 LASSERT(msgsize % 8 == 0);
387 buflens[0] = msgsize;
388 if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor) &&
389 (req->rq_bulk_read || req->rq_bulk_write)) {
390 bsd = lustre_msg_buf(req->rq_reqbuf,
391 req->rq_reqbuf->lm_bufcount - 1,
395 buflens[bufcnt++] = bulk_sec_desc_size(bsd->bsd_csum_alg, 0,
398 rs_size += lustre_msg_size_v2(bufcnt, buflens);
400 rs = req->rq_reply_state;
404 LASSERT(rs->rs_size >= rs_size);
406 OBD_ALLOC(rs, rs_size);
410 rs->rs_size = rs_size;
413 rs->rs_svc_ctx = req->rq_svc_ctx;
414 atomic_inc(&req->rq_svc_ctx->sc_refcount);
415 rs->rs_repbuf = (struct lustre_msg *) (rs + 1);
416 rs->rs_repbuf_len = rs_size - sizeof(*rs);
418 lustre_init_msg_v2(rs->rs_repbuf, bufcnt, buflens, NULL);
419 rs->rs_msg = lustre_msg_buf_v2(rs->rs_repbuf, 0, 0);
421 req->rq_reply_state = rs;
426 void plain_free_rs(struct ptlrpc_reply_state *rs)
430 LASSERT(atomic_read(&rs->rs_svc_ctx->sc_refcount) > 1);
431 atomic_dec(&rs->rs_svc_ctx->sc_refcount);
433 if (!rs->rs_prealloc)
434 OBD_FREE(rs, rs->rs_size);
439 int plain_authorize(struct ptlrpc_request *req)
441 struct ptlrpc_reply_state *rs = req->rq_reply_state;
442 struct lustre_msg_v2 *msg = rs->rs_repbuf;
449 if (req->rq_replen != msg->lm_buflens[0])
450 len = lustre_shrink_msg(msg, 0, req->rq_replen, 1);
452 len = lustre_msg_size_v2(msg->lm_bufcount, msg->lm_buflens);
454 msg->lm_secflvr = req->rq_sec_flavor;
455 rs->rs_repdata_len = len;
460 int plain_svc_unwrap_bulk(struct ptlrpc_request *req,
461 struct ptlrpc_bulk_desc *desc)
463 struct ptlrpc_reply_state *rs = req->rq_reply_state;
467 return bulk_csum_svc(desc, req->rq_bulk_read,
468 req->rq_reqbuf, req->rq_reqbuf->lm_bufcount - 1,
469 rs->rs_repbuf, rs->rs_repbuf->lm_bufcount - 1);
473 int plain_svc_wrap_bulk(struct ptlrpc_request *req,
474 struct ptlrpc_bulk_desc *desc)
476 struct ptlrpc_reply_state *rs = req->rq_reply_state;
480 return bulk_csum_svc(desc, req->rq_bulk_read,
481 req->rq_reqbuf, req->rq_reqbuf->lm_bufcount - 1,
482 rs->rs_repbuf, rs->rs_repbuf->lm_bufcount - 1);
485 static struct ptlrpc_sec_cops plain_sec_cops = {
486 .create_sec = plain_create_sec,
487 .destroy_sec = plain_destroy_sec,
488 .lookup_ctx = plain_lookup_ctx,
489 .flush_ctx_cache = plain_flush_ctx_cache,
490 .alloc_reqbuf = plain_alloc_reqbuf,
491 .alloc_repbuf = plain_alloc_repbuf,
492 .free_reqbuf = plain_free_reqbuf,
493 .free_repbuf = plain_free_repbuf,
494 .enlarge_reqbuf = plain_enlarge_reqbuf,
497 static struct ptlrpc_sec_sops plain_sec_sops = {
498 .accept = plain_accept,
499 .alloc_rs = plain_alloc_rs,
500 .authorize = plain_authorize,
501 .free_rs = plain_free_rs,
502 .unwrap_bulk = plain_svc_unwrap_bulk,
503 .wrap_bulk = plain_svc_wrap_bulk,
506 static struct ptlrpc_sec_policy plain_policy = {
507 .sp_owner = THIS_MODULE,
508 .sp_name = "sec.plain",
509 .sp_policy = SPTLRPC_POLICY_PLAIN,
510 .sp_cops = &plain_sec_cops,
511 .sp_sops = &plain_sec_sops,
515 void plain_init_internal(void)
517 static HLIST_HEAD(__list);
519 plain_sec.ps_policy = &plain_policy;
520 atomic_set(&plain_sec.ps_refcount, 1); /* always busy */
521 plain_sec.ps_import = NULL;
522 plain_sec.ps_flavor = SPTLRPC_FLVR_PLAIN;
523 plain_sec.ps_flags = 0;
524 spin_lock_init(&plain_sec.ps_lock);
525 atomic_set(&plain_sec.ps_busy, 1); /* for "plain_cli_ctx" */
526 INIT_LIST_HEAD(&plain_sec.ps_gc_list);
527 plain_sec.ps_gc_interval = 0;
528 plain_sec.ps_gc_next = 0;
530 hlist_add_head(&plain_cli_ctx.cc_hash, &__list);
531 atomic_set(&plain_cli_ctx.cc_refcount, 1); /* for hash */
532 plain_cli_ctx.cc_sec = &plain_sec;
533 plain_cli_ctx.cc_ops = &plain_ctx_ops;
534 plain_cli_ctx.cc_expire = 0;
535 plain_cli_ctx.cc_flags = PTLRPC_CTX_CACHED | PTLRPC_CTX_ETERNAL |
537 plain_cli_ctx.cc_vcred.vc_uid = 0;
538 spin_lock_init(&plain_cli_ctx.cc_lock);
539 INIT_LIST_HEAD(&plain_cli_ctx.cc_req_list);
542 int sptlrpc_plain_init(void)
546 plain_init_internal();
548 rc = sptlrpc_register_policy(&plain_policy);
550 CERROR("failed to register sec.plain: %d\n", rc);
555 void sptlrpc_plain_fini(void)
559 rc = sptlrpc_unregister_policy(&plain_policy);
561 CERROR("cannot unregister sec.plain: %d\n", rc);