Whamcloud - gitweb
branch: HEAD
[fs/lustre-release.git] / lustre / ptlrpc / sec_plain.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Copyright (C) 2006 Cluster File Systems, Inc.
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
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.
11  *
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.
16  *
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.
20  */
21
22 #ifndef EXPORT_SYMTAB
23 # define EXPORT_SYMTAB
24 #endif
25 #define DEBUG_SUBSYSTEM S_SEC
26
27 #ifndef __KERNEL__
28 #include <liblustre.h>
29 #endif
30
31 #include <obd_support.h>
32 #include <obd_class.h>
33 #include <lustre_net.h>
34 #include <lustre_sec.h>
35
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;
40
41 static
42 int plain_ctx_refresh(struct ptlrpc_cli_ctx *ctx)
43 {
44         /* should never reach here */
45         LBUG();
46         return 0;
47 }
48
49 static
50 int plain_ctx_sign(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
51 {
52         struct lustre_msg_v2 *msg = req->rq_reqbuf;
53         ENTRY;
54
55         msg->lm_secflvr = req->rq_sec_flavor;
56         req->rq_reqdata_len = lustre_msg_size_v2(msg->lm_bufcount,
57                                                  msg->lm_buflens);
58         RETURN(0);
59 }
60
61 static
62 int plain_ctx_verify(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
63 {
64         struct lustre_msg *msg = req->rq_repbuf;
65         ENTRY;
66
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",
70                                msg->lm_bufcount);
71                         RETURN(-EPROTO);
72                 }
73
74                 if (bulk_sec_desc_unpack(msg, 1)) {
75                         CERROR("Mal-formed bulk checksum reply\n");
76                         RETURN(-EINVAL);
77                 }
78         }
79
80         req->rq_repmsg = lustre_msg_buf(msg, 0, 0);
81         req->rq_replen = msg->lm_buflens[0];
82         RETURN(0);
83 }
84
85 static
86 int plain_cli_wrap_bulk(struct ptlrpc_cli_ctx *ctx,
87                         struct ptlrpc_request *req,
88                         struct ptlrpc_bulk_desc *desc)
89 {
90         struct sec_flavor_config *conf;
91
92         LASSERT(req->rq_import);
93         LASSERT(SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor));
94         LASSERT(req->rq_reqbuf->lm_bufcount >= 2);
95
96         conf = &req->rq_import->imp_obd->u.cli.cl_sec_conf;
97         return bulk_csum_cli_request(desc, req->rq_bulk_read,
98                                      conf->sfc_bulk_csum,
99                                      req->rq_reqbuf,
100                                      req->rq_reqbuf->lm_bufcount - 1);
101 }
102
103 static
104 int plain_cli_unwrap_bulk(struct ptlrpc_cli_ctx *ctx,
105                           struct ptlrpc_request *req,
106                           struct ptlrpc_bulk_desc *desc)
107 {
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);
111
112         return bulk_csum_cli_reply(desc, req->rq_bulk_read,
113                                    req->rq_reqbuf,
114                                    req->rq_reqbuf->lm_bufcount - 1,
115                                    req->rq_repbuf,
116                                    req->rq_repbuf->lm_bufcount - 1);
117 }
118
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,
125 };
126
127 static struct ptlrpc_svc_ctx plain_svc_ctx = {
128         .sc_refcount    = ATOMIC_INIT(1),
129         .sc_policy      = &plain_policy,
130 };
131
132 static
133 struct ptlrpc_sec* plain_create_sec(struct obd_import *imp,
134                                     struct ptlrpc_svc_ctx *ctx,
135                                     __u32 flavor,
136                                     unsigned long flags)
137 {
138         ENTRY;
139         LASSERT(SEC_FLAVOR_POLICY(flavor) == SPTLRPC_POLICY_PLAIN);
140         RETURN(&plain_sec);
141 }
142
143 static
144 void plain_destroy_sec(struct ptlrpc_sec *sec)
145 {
146         ENTRY;
147         LASSERT(sec == &plain_sec);
148         EXIT;
149 }
150
151 static
152 struct ptlrpc_cli_ctx *plain_lookup_ctx(struct ptlrpc_sec *sec,
153                                         struct vfs_cred *vcred,
154                                         int create, int remove_dead)
155 {
156         ENTRY;
157         atomic_inc(&plain_cli_ctx.cc_refcount);
158         RETURN(&plain_cli_ctx);
159 }
160
161 static
162 int plain_flush_ctx_cache(struct ptlrpc_sec *sec,
163                           uid_t uid,
164                           int grace, int force)
165 {
166         return 0;
167 }
168
169 static
170 int plain_alloc_reqbuf(struct ptlrpc_sec *sec,
171                        struct ptlrpc_request *req,
172                        int msgsize)
173 {
174         struct sec_flavor_config *conf;
175         int bufcnt = 1, buflens[2], alloc_len;
176         ENTRY;
177
178         buflens[0] = msgsize;
179
180         if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor))
181                 buflens[bufcnt++] = sptlrpc_current_user_desc_size();
182
183         if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
184                 LASSERT(req->rq_bulk_read || req->rq_bulk_write);
185
186                 conf = &req->rq_import->imp_obd->u.cli.cl_sec_conf;
187                 buflens[bufcnt++] = bulk_sec_desc_size(conf->sfc_bulk_csum, 1,
188                                                        req->rq_bulk_read);
189         }
190
191         alloc_len = lustre_msg_size_v2(bufcnt, buflens);
192
193         if (!req->rq_reqbuf) {
194                 LASSERT(!req->rq_pool);
195
196                 alloc_len = size_roundup_power2(alloc_len);
197                 OBD_ALLOC(req->rq_reqbuf, alloc_len);
198                 if (!req->rq_reqbuf)
199                         RETURN(-ENOMEM);
200
201                 req->rq_reqbuf_len = alloc_len;
202         } else {
203                 LASSERT(req->rq_pool);
204                 LASSERT(req->rq_reqbuf_len >= alloc_len);
205                 memset(req->rq_reqbuf, 0, alloc_len);
206         }
207
208         lustre_init_msg_v2(req->rq_reqbuf, bufcnt, buflens, NULL);
209         req->rq_reqmsg = lustre_msg_buf_v2(req->rq_reqbuf, 0, 0);
210
211         if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor))
212                 sptlrpc_pack_user_desc(req->rq_reqbuf, 1);
213
214         RETURN(0);
215 }
216
217 static
218 void plain_free_reqbuf(struct ptlrpc_sec *sec,
219                        struct ptlrpc_request *req)
220 {
221         ENTRY;
222         if (!req->rq_pool) {
223                 OBD_FREE(req->rq_reqbuf, req->rq_reqbuf_len);
224                 req->rq_reqbuf = NULL;
225                 req->rq_reqbuf_len = 0;
226         }
227         EXIT;
228 }
229
230 static
231 int plain_alloc_repbuf(struct ptlrpc_sec *sec,
232                        struct ptlrpc_request *req,
233                        int msgsize)
234 {
235         struct sec_flavor_config *conf;
236         int bufcnt = 1, buflens[2], alloc_len;
237         ENTRY;
238
239         buflens[0] = msgsize;
240
241         if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
242                 LASSERT(req->rq_bulk_read || req->rq_bulk_write);
243
244                 conf = &req->rq_import->imp_obd->u.cli.cl_sec_conf;
245                 buflens[bufcnt++] = bulk_sec_desc_size(conf->sfc_bulk_csum, 0,
246                                                        req->rq_bulk_read);
247         }
248
249         alloc_len = lustre_msg_size_v2(bufcnt, buflens);
250         alloc_len = size_roundup_power2(alloc_len);
251
252         OBD_ALLOC(req->rq_repbuf, alloc_len);
253         if (!req->rq_repbuf)
254                 RETURN(-ENOMEM);
255
256         req->rq_repbuf_len = alloc_len;
257         RETURN(0);
258 }
259
260 static
261 void plain_free_repbuf(struct ptlrpc_sec *sec,
262                        struct ptlrpc_request *req)
263 {
264         ENTRY;
265         OBD_FREE(req->rq_repbuf, req->rq_repbuf_len);
266         req->rq_repbuf = NULL;
267         req->rq_repbuf_len = 0;
268         EXIT;
269 }
270
271 static
272 int plain_enlarge_reqbuf(struct ptlrpc_sec *sec,
273                          struct ptlrpc_request *req,
274                          int segment, int newsize)
275 {
276         struct lustre_msg      *newbuf;
277         int                     oldsize;
278         int                     newmsg_size, newbuf_size;
279         ENTRY;
280
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);
285
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;
292
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;
299
300         /* request from pool should always have enough buffer */
301         LASSERT(!req->rq_pool || req->rq_reqbuf_len >= newbuf_size);
302
303         if (req->rq_reqbuf_len < newbuf_size) {
304                 newbuf_size = size_roundup_power2(newbuf_size);
305
306                 OBD_ALLOC(newbuf, newbuf_size);
307                 if (newbuf == NULL)
308                         RETURN(-ENOMEM);
309
310                 memcpy(newbuf, req->rq_reqbuf, req->rq_reqbuf_len);
311
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);
316         }
317
318         _sptlrpc_enlarge_msg_inplace(req->rq_reqbuf, 0, newmsg_size);
319         _sptlrpc_enlarge_msg_inplace(req->rq_reqmsg, segment, newsize);
320
321         req->rq_reqlen = newmsg_size;
322         RETURN(0);
323 }
324
325 static
326 int plain_accept(struct ptlrpc_request *req)
327 {
328         struct lustre_msg *msg = req->rq_reqbuf;
329         int                bufcnt = 1;
330         ENTRY;
331
332         LASSERT(SEC_FLAVOR_POLICY(req->rq_sec_flavor) == SPTLRPC_POLICY_PLAIN);
333
334         if (SEC_FLAVOR_RPC(req->rq_sec_flavor) != SPTLRPC_FLVR_PLAIN) {
335                 CERROR("Invalid flavor 0x%x\n", req->rq_sec_flavor);
336                 return SECSVC_DROP;
337         }
338
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",
342                                msg->lm_bufcount);
343                         RETURN(SECSVC_DROP);
344                 }
345
346                 if (sptlrpc_unpack_user_desc(msg, bufcnt - 1)) {
347                         CERROR("Mal-formed user descriptor\n");
348                         RETURN(SECSVC_DROP);
349                 }
350
351                 req->rq_user_desc = lustre_msg_buf(msg, bufcnt - 1, 0);
352         }
353
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",
357                                msg->lm_bufcount);
358                         RETURN(SECSVC_DROP);
359                 }
360
361                 if (bulk_sec_desc_unpack(msg, bufcnt - 1)) {
362                         CERROR("Mal-formed bulk checksum request\n");
363                         RETURN(SECSVC_DROP);
364                 }
365         }
366
367         req->rq_reqmsg = lustre_msg_buf(msg, 0, 0);
368         req->rq_reqlen = msg->lm_buflens[0];
369
370         req->rq_svc_ctx = &plain_svc_ctx;
371         atomic_inc(&req->rq_svc_ctx->sc_refcount);
372
373         RETURN(SECSVC_OK);
374 }
375
376 static
377 int plain_alloc_rs(struct ptlrpc_request *req, int msgsize)
378 {
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);
383         ENTRY;
384
385         LASSERT(msgsize % 8 == 0);
386
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,
392                                      sizeof(*bsd));
393                 LASSERT(bsd);
394
395                 buflens[bufcnt++] = bulk_sec_desc_size(bsd->bsd_csum_alg, 0,
396                                                        req->rq_bulk_read);
397         }
398         rs_size += lustre_msg_size_v2(bufcnt, buflens);
399
400         rs = req->rq_reply_state;
401
402         if (rs) {
403                 /* pre-allocated */
404                 LASSERT(rs->rs_size >= rs_size);
405         } else {
406                 OBD_ALLOC(rs, rs_size);
407                 if (rs == NULL)
408                         RETURN(-ENOMEM);
409
410                 rs->rs_size = rs_size;
411         }
412
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);
417
418         lustre_init_msg_v2(rs->rs_repbuf, bufcnt, buflens, NULL);
419         rs->rs_msg = lustre_msg_buf_v2(rs->rs_repbuf, 0, 0);
420
421         req->rq_reply_state = rs;
422         RETURN(0);
423 }
424
425 static
426 void plain_free_rs(struct ptlrpc_reply_state *rs)
427 {
428         ENTRY;
429
430         LASSERT(atomic_read(&rs->rs_svc_ctx->sc_refcount) > 1);
431         atomic_dec(&rs->rs_svc_ctx->sc_refcount);
432
433         if (!rs->rs_prealloc)
434                 OBD_FREE(rs, rs->rs_size);
435         EXIT;
436 }
437
438 static
439 int plain_authorize(struct ptlrpc_request *req)
440 {
441         struct ptlrpc_reply_state *rs = req->rq_reply_state;
442         struct lustre_msg_v2      *msg = rs->rs_repbuf;
443         int                        len;
444         ENTRY;
445
446         LASSERT(rs);
447         LASSERT(msg);
448
449         if (req->rq_replen != msg->lm_buflens[0])
450                 len = lustre_shrink_msg(msg, 0, req->rq_replen, 1);
451         else
452                 len = lustre_msg_size_v2(msg->lm_bufcount, msg->lm_buflens);
453
454         msg->lm_secflvr = req->rq_sec_flavor;
455         rs->rs_repdata_len = len;
456         RETURN(0);
457 }
458
459 static
460 int plain_svc_unwrap_bulk(struct ptlrpc_request *req,
461                           struct ptlrpc_bulk_desc *desc)
462 {
463         struct ptlrpc_reply_state *rs = req->rq_reply_state;
464
465         LASSERT(rs);
466
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);
470 }
471
472 static
473 int plain_svc_wrap_bulk(struct ptlrpc_request *req,
474                         struct ptlrpc_bulk_desc *desc)
475 {
476         struct ptlrpc_reply_state *rs = req->rq_reply_state;
477
478         LASSERT(rs);
479
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);
483 }
484
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,
495 };
496
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,
504 };
505
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,
512 };
513
514 static
515 void plain_init_internal(void)
516 {
517         static HLIST_HEAD(__list);
518
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;
529
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 |
536                                  PTLRPC_CTX_UPTODATE;
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);
540 }
541
542 int sptlrpc_plain_init(void)
543 {
544         int rc;
545
546         plain_init_internal();
547
548         rc = sptlrpc_register_policy(&plain_policy);
549         if (rc)
550                 CERROR("failed to register sec.plain: %d\n", rc);
551
552         return rc;
553 }
554
555 void sptlrpc_plain_fini(void)
556 {
557         int rc;
558
559         rc = sptlrpc_unregister_policy(&plain_policy);
560         if (rc)
561                 CERROR("cannot unregister sec.plain: %d\n", rc);
562 }