Whamcloud - gitweb
if client_disconnect_export was called without force flag set,
[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  *   Author: Eric Mei <ericm@clusterfs.com>
6  *
7  *   This file is part of Lustre, http://www.lustre.org.
8  *
9  *   Lustre is free software; you can redistribute it and/or
10  *   modify it under the terms of version 2 of the GNU General Public
11  *   License as published by the Free Software Foundation.
12  *
13  *   Lustre is distributed in the hope that it will be useful,
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *   GNU General Public License for more details.
17  *
18  *   You should have received a copy of the GNU General Public License
19  *   along with Lustre; if not, write to the Free Software
20  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22
23 #ifndef EXPORT_SYMTAB
24 # define EXPORT_SYMTAB
25 #endif
26 #define DEBUG_SUBSYSTEM S_SEC
27
28 #ifndef __KERNEL__
29 #include <liblustre.h>
30 #endif
31
32 #include <obd_support.h>
33 #include <obd_class.h>
34 #include <lustre_net.h>
35 #include <lustre_sec.h>
36
37 static struct ptlrpc_sec_policy plain_policy;
38 static struct ptlrpc_ctx_ops    plain_ctx_ops;
39 static struct ptlrpc_sec        plain_sec;
40 static struct ptlrpc_cli_ctx    plain_cli_ctx;
41 static struct ptlrpc_svc_ctx    plain_svc_ctx;
42
43 /****************************************
44  * cli_ctx apis                         *
45  ****************************************/
46
47 static
48 int plain_ctx_refresh(struct ptlrpc_cli_ctx *ctx)
49 {
50         /* should never reach here */
51         LBUG();
52         return 0;
53 }
54
55 static
56 int plain_ctx_sign(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
57 {
58         struct lustre_msg_v2 *msg = req->rq_reqbuf;
59         ENTRY;
60
61         msg->lm_secflvr = req->rq_sec_flavor;
62         req->rq_reqdata_len = lustre_msg_size_v2(msg->lm_bufcount,
63                                                  msg->lm_buflens);
64         RETURN(0);
65 }
66
67 static
68 int plain_ctx_verify(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req)
69 {
70         struct lustre_msg *msg = req->rq_repbuf;
71         ENTRY;
72
73         if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
74                 if (msg->lm_bufcount != 2) {
75                         CERROR("Protocol error: invalid buf count %d\n",
76                                msg->lm_bufcount);
77                         RETURN(-EPROTO);
78                 }
79
80                 if (bulk_sec_desc_unpack(msg, 1)) {
81                         CERROR("Mal-formed bulk checksum reply\n");
82                         RETURN(-EINVAL);
83                 }
84         }
85
86         req->rq_repmsg = lustre_msg_buf(msg, 0, 0);
87         req->rq_replen = msg->lm_buflens[0];
88         RETURN(0);
89 }
90
91 static
92 int plain_cli_wrap_bulk(struct ptlrpc_cli_ctx *ctx,
93                         struct ptlrpc_request *req,
94                         struct ptlrpc_bulk_desc *desc)
95 {
96         struct sec_flavor_config *conf;
97
98         LASSERT(req->rq_import);
99         LASSERT(SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor));
100         LASSERT(req->rq_reqbuf->lm_bufcount >= 2);
101
102         conf = &req->rq_import->imp_obd->u.cli.cl_sec_conf;
103         return bulk_csum_cli_request(desc, req->rq_bulk_read,
104                                      conf->sfc_bulk_csum,
105                                      req->rq_reqbuf,
106                                      req->rq_reqbuf->lm_bufcount - 1);
107 }
108
109 static
110 int plain_cli_unwrap_bulk(struct ptlrpc_cli_ctx *ctx,
111                           struct ptlrpc_request *req,
112                           struct ptlrpc_bulk_desc *desc)
113 {
114         LASSERT(SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor));
115         LASSERT(req->rq_reqbuf->lm_bufcount >= 2);
116         LASSERT(req->rq_repbuf->lm_bufcount >= 2);
117
118         return bulk_csum_cli_reply(desc, req->rq_bulk_read,
119                                    req->rq_reqbuf,
120                                    req->rq_reqbuf->lm_bufcount - 1,
121                                    req->rq_repbuf,
122                                    req->rq_repbuf->lm_bufcount - 1);
123 }
124
125 /****************************************
126  * sec apis                             *
127  ****************************************/
128
129 static
130 struct ptlrpc_sec* plain_create_sec(struct obd_import *imp,
131                                     struct ptlrpc_svc_ctx *ctx,
132                                     __u32 flavor,
133                                     unsigned long flags)
134 {
135         ENTRY;
136         LASSERT(SEC_FLAVOR_POLICY(flavor) == SPTLRPC_POLICY_PLAIN);
137         RETURN(&plain_sec);
138 }
139
140 static
141 void plain_destroy_sec(struct ptlrpc_sec *sec)
142 {
143         ENTRY;
144         LASSERT(sec == &plain_sec);
145         EXIT;
146 }
147
148 static
149 struct ptlrpc_cli_ctx *plain_lookup_ctx(struct ptlrpc_sec *sec,
150                                         struct vfs_cred *vcred,
151                                         int create, int remove_dead)
152 {
153         ENTRY;
154         atomic_inc(&plain_cli_ctx.cc_refcount);
155         RETURN(&plain_cli_ctx);
156 }
157
158 static
159 int plain_flush_ctx_cache(struct ptlrpc_sec *sec,
160                           uid_t uid,
161                           int grace, int force)
162 {
163         return 0;
164 }
165
166 static
167 int plain_alloc_reqbuf(struct ptlrpc_sec *sec,
168                        struct ptlrpc_request *req,
169                        int msgsize)
170 {
171         struct sec_flavor_config *conf;
172         int bufcnt = 1, buflens[2], alloc_len;
173         ENTRY;
174
175         buflens[0] = msgsize;
176
177         if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor))
178                 buflens[bufcnt++] = sptlrpc_current_user_desc_size();
179
180         if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
181                 LASSERT(req->rq_bulk_read || req->rq_bulk_write);
182
183                 conf = &req->rq_import->imp_obd->u.cli.cl_sec_conf;
184                 buflens[bufcnt++] = bulk_sec_desc_size(conf->sfc_bulk_csum, 1,
185                                                        req->rq_bulk_read);
186         }
187
188         alloc_len = lustre_msg_size_v2(bufcnt, buflens);
189
190         if (!req->rq_reqbuf) {
191                 LASSERT(!req->rq_pool);
192
193                 alloc_len = size_roundup_power2(alloc_len);
194                 OBD_ALLOC(req->rq_reqbuf, alloc_len);
195                 if (!req->rq_reqbuf)
196                         RETURN(-ENOMEM);
197
198                 req->rq_reqbuf_len = alloc_len;
199         } else {
200                 LASSERT(req->rq_pool);
201                 LASSERT(req->rq_reqbuf_len >= alloc_len);
202                 memset(req->rq_reqbuf, 0, alloc_len);
203         }
204
205         lustre_init_msg_v2(req->rq_reqbuf, bufcnt, buflens, NULL);
206         req->rq_reqmsg = lustre_msg_buf_v2(req->rq_reqbuf, 0, 0);
207
208         if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor))
209                 sptlrpc_pack_user_desc(req->rq_reqbuf, 1);
210
211         RETURN(0);
212 }
213
214 static
215 void plain_free_reqbuf(struct ptlrpc_sec *sec,
216                        struct ptlrpc_request *req)
217 {
218         ENTRY;
219         if (!req->rq_pool) {
220                 OBD_FREE(req->rq_reqbuf, req->rq_reqbuf_len);
221                 req->rq_reqbuf = NULL;
222                 req->rq_reqbuf_len = 0;
223         }
224         EXIT;
225 }
226
227 static
228 int plain_alloc_repbuf(struct ptlrpc_sec *sec,
229                        struct ptlrpc_request *req,
230                        int msgsize)
231 {
232         struct sec_flavor_config *conf;
233         int bufcnt = 1, buflens[2], alloc_len;
234         ENTRY;
235
236         buflens[0] = msgsize;
237
238         if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
239                 LASSERT(req->rq_bulk_read || req->rq_bulk_write);
240
241                 conf = &req->rq_import->imp_obd->u.cli.cl_sec_conf;
242                 buflens[bufcnt++] = bulk_sec_desc_size(conf->sfc_bulk_csum, 0,
243                                                        req->rq_bulk_read);
244         }
245
246         alloc_len = lustre_msg_size_v2(bufcnt, buflens);
247         alloc_len = size_roundup_power2(alloc_len);
248
249         OBD_ALLOC(req->rq_repbuf, alloc_len);
250         if (!req->rq_repbuf)
251                 RETURN(-ENOMEM);
252
253         req->rq_repbuf_len = alloc_len;
254         RETURN(0);
255 }
256
257 static
258 void plain_free_repbuf(struct ptlrpc_sec *sec,
259                        struct ptlrpc_request *req)
260 {
261         ENTRY;
262         OBD_FREE(req->rq_repbuf, req->rq_repbuf_len);
263         req->rq_repbuf = NULL;
264         req->rq_repbuf_len = 0;
265         EXIT;
266 }
267
268 static
269 int plain_enlarge_reqbuf(struct ptlrpc_sec *sec,
270                          struct ptlrpc_request *req,
271                          int segment, int newsize)
272 {
273         struct lustre_msg      *newbuf;
274         int                     oldsize;
275         int                     newmsg_size, newbuf_size;
276         ENTRY;
277
278         /* embedded msg always at seg 0 */
279         LASSERT(req->rq_reqbuf);
280         LASSERT(req->rq_reqbuf_len >= req->rq_reqlen);
281         LASSERT(lustre_msg_buf(req->rq_reqbuf, 0, 0) == req->rq_reqmsg);
282
283         /* compute new embedded msg size.  */
284         oldsize = req->rq_reqmsg->lm_buflens[segment];
285         req->rq_reqmsg->lm_buflens[segment] = newsize;
286         newmsg_size = lustre_msg_size_v2(req->rq_reqmsg->lm_bufcount,
287                                          req->rq_reqmsg->lm_buflens);
288         req->rq_reqmsg->lm_buflens[segment] = oldsize;
289
290         /* compute new wrapper msg size.  */
291         oldsize = req->rq_reqbuf->lm_buflens[0];
292         req->rq_reqbuf->lm_buflens[0] = newmsg_size;
293         newbuf_size = lustre_msg_size_v2(req->rq_reqbuf->lm_bufcount,
294                                          req->rq_reqbuf->lm_buflens);
295         req->rq_reqbuf->lm_buflens[0] = oldsize;
296
297         /* request from pool should always have enough buffer */
298         LASSERT(!req->rq_pool || req->rq_reqbuf_len >= newbuf_size);
299
300         if (req->rq_reqbuf_len < newbuf_size) {
301                 newbuf_size = size_roundup_power2(newbuf_size);
302
303                 OBD_ALLOC(newbuf, newbuf_size);
304                 if (newbuf == NULL)
305                         RETURN(-ENOMEM);
306
307                 memcpy(newbuf, req->rq_reqbuf, req->rq_reqbuf_len);
308
309                 OBD_FREE(req->rq_reqbuf, req->rq_reqbuf_len);
310                 req->rq_reqbuf = newbuf;
311                 req->rq_reqbuf_len = newbuf_size;
312                 req->rq_reqmsg = lustre_msg_buf(req->rq_reqbuf, 0, 0);
313         }
314
315         _sptlrpc_enlarge_msg_inplace(req->rq_reqbuf, 0, newmsg_size);
316         _sptlrpc_enlarge_msg_inplace(req->rq_reqmsg, segment, newsize);
317
318         req->rq_reqlen = newmsg_size;
319         RETURN(0);
320 }
321
322 /****************************************
323  * service apis                         *
324  ****************************************/
325
326 static struct ptlrpc_svc_ctx plain_svc_ctx = {
327         .sc_refcount    = ATOMIC_INIT(1),
328         .sc_policy      = &plain_policy,
329 };
330
331 static
332 int plain_accept(struct ptlrpc_request *req)
333 {
334         struct lustre_msg *msg = req->rq_reqbuf;
335         int                bufcnt = 1;
336         ENTRY;
337
338         LASSERT(SEC_FLAVOR_POLICY(req->rq_sec_flavor) == SPTLRPC_POLICY_PLAIN);
339
340         if (SEC_FLAVOR_RPC(req->rq_sec_flavor) != SPTLRPC_FLVR_PLAIN) {
341                 CERROR("Invalid flavor 0x%x\n", req->rq_sec_flavor);
342                 return SECSVC_DROP;
343         }
344
345         if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor)) {
346                 if (msg->lm_bufcount < ++bufcnt) {
347                         CERROR("Protocal error: too small buf count %d\n",
348                                msg->lm_bufcount);
349                         RETURN(SECSVC_DROP);
350                 }
351
352                 if (sptlrpc_unpack_user_desc(msg, bufcnt - 1)) {
353                         CERROR("Mal-formed user descriptor\n");
354                         RETURN(SECSVC_DROP);
355                 }
356
357                 req->rq_user_desc = lustre_msg_buf(msg, bufcnt - 1, 0);
358         }
359
360         if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
361                 if (msg->lm_bufcount != ++bufcnt) {
362                         CERROR("Protocal error: invalid buf count %d\n",
363                                msg->lm_bufcount);
364                         RETURN(SECSVC_DROP);
365                 }
366
367                 if (bulk_sec_desc_unpack(msg, bufcnt - 1)) {
368                         CERROR("Mal-formed bulk checksum request\n");
369                         RETURN(SECSVC_DROP);
370                 }
371         }
372
373         req->rq_reqmsg = lustre_msg_buf(msg, 0, 0);
374         req->rq_reqlen = msg->lm_buflens[0];
375
376         req->rq_svc_ctx = &plain_svc_ctx;
377         atomic_inc(&req->rq_svc_ctx->sc_refcount);
378
379         RETURN(SECSVC_OK);
380 }
381
382 static
383 int plain_alloc_rs(struct ptlrpc_request *req, int msgsize)
384 {
385         struct ptlrpc_reply_state *rs;
386         struct ptlrpc_bulk_sec_desc *bsd;
387         int bufcnt = 1, buflens[2];
388         int rs_size = sizeof(*rs);
389         ENTRY;
390
391         LASSERT(msgsize % 8 == 0);
392
393         buflens[0] = msgsize;
394         if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor) &&
395             (req->rq_bulk_read || req->rq_bulk_write)) {
396                 bsd = lustre_msg_buf(req->rq_reqbuf,
397                                      req->rq_reqbuf->lm_bufcount - 1,
398                                      sizeof(*bsd));
399                 LASSERT(bsd);
400
401                 buflens[bufcnt++] = bulk_sec_desc_size(bsd->bsd_csum_alg, 0,
402                                                        req->rq_bulk_read);
403         }
404         rs_size += lustre_msg_size_v2(bufcnt, buflens);
405
406         rs = req->rq_reply_state;
407
408         if (rs) {
409                 /* pre-allocated */
410                 LASSERT(rs->rs_size >= rs_size);
411         } else {
412                 OBD_ALLOC(rs, rs_size);
413                 if (rs == NULL)
414                         RETURN(-ENOMEM);
415
416                 rs->rs_size = rs_size;
417         }
418
419         rs->rs_svc_ctx = req->rq_svc_ctx;
420         atomic_inc(&req->rq_svc_ctx->sc_refcount);
421         rs->rs_repbuf = (struct lustre_msg *) (rs + 1);
422         rs->rs_repbuf_len = rs_size - sizeof(*rs);
423
424         lustre_init_msg_v2(rs->rs_repbuf, bufcnt, buflens, NULL);
425         rs->rs_msg = lustre_msg_buf_v2(rs->rs_repbuf, 0, 0);
426
427         req->rq_reply_state = rs;
428         RETURN(0);
429 }
430
431 static
432 void plain_free_rs(struct ptlrpc_reply_state *rs)
433 {
434         ENTRY;
435
436         LASSERT(atomic_read(&rs->rs_svc_ctx->sc_refcount) > 1);
437         atomic_dec(&rs->rs_svc_ctx->sc_refcount);
438
439         if (!rs->rs_prealloc)
440                 OBD_FREE(rs, rs->rs_size);
441         EXIT;
442 }
443
444 static
445 int plain_authorize(struct ptlrpc_request *req)
446 {
447         struct ptlrpc_reply_state *rs = req->rq_reply_state;
448         struct lustre_msg_v2      *msg = rs->rs_repbuf;
449         int                        len;
450         ENTRY;
451
452         LASSERT(rs);
453         LASSERT(msg);
454
455         if (req->rq_replen != msg->lm_buflens[0])
456                 len = lustre_shrink_msg(msg, 0, req->rq_replen, 1);
457         else
458                 len = lustre_msg_size_v2(msg->lm_bufcount, msg->lm_buflens);
459
460         msg->lm_secflvr = req->rq_sec_flavor;
461         rs->rs_repdata_len = len;
462         RETURN(0);
463 }
464
465 static
466 int plain_svc_unwrap_bulk(struct ptlrpc_request *req,
467                           struct ptlrpc_bulk_desc *desc)
468 {
469         struct ptlrpc_reply_state      *rs = req->rq_reply_state;
470         int                             voff, roff;
471
472         LASSERT(rs);
473
474         voff = req->rq_reqbuf->lm_bufcount - 1;
475         roff = rs->rs_repbuf->lm_bufcount - 1;
476
477         return bulk_csum_svc(desc, req->rq_bulk_read,
478                              lustre_msg_buf(req->rq_reqbuf, voff, 0),
479                              lustre_msg_buflen(req->rq_reqbuf, voff),
480                              lustre_msg_buf(rs->rs_repbuf, roff, 0),
481                              lustre_msg_buflen(rs->rs_repbuf, roff));
482 }
483
484 static
485 int plain_svc_wrap_bulk(struct ptlrpc_request *req,
486                         struct ptlrpc_bulk_desc *desc)
487 {
488         struct ptlrpc_reply_state      *rs = req->rq_reply_state;
489         int                             voff, roff;
490
491         LASSERT(rs);
492
493         voff = req->rq_reqbuf->lm_bufcount - 1;
494         roff = rs->rs_repbuf->lm_bufcount - 1;
495
496         return bulk_csum_svc(desc, req->rq_bulk_read,
497                              lustre_msg_buf(req->rq_reqbuf, voff, 0),
498                              lustre_msg_buflen(req->rq_reqbuf, voff),
499                              lustre_msg_buf(rs->rs_repbuf, roff, 0),
500                              lustre_msg_buflen(rs->rs_repbuf, roff));
501 }
502
503 static struct ptlrpc_ctx_ops plain_ctx_ops = {
504         .refresh                = plain_ctx_refresh,
505         .sign                   = plain_ctx_sign,
506         .verify                 = plain_ctx_verify,
507         .wrap_bulk              = plain_cli_wrap_bulk,
508         .unwrap_bulk            = plain_cli_unwrap_bulk,
509 };
510
511 static struct ptlrpc_sec_cops plain_sec_cops = {
512         .create_sec             = plain_create_sec,
513         .destroy_sec            = plain_destroy_sec,
514         .lookup_ctx             = plain_lookup_ctx,
515         .flush_ctx_cache        = plain_flush_ctx_cache,
516         .alloc_reqbuf           = plain_alloc_reqbuf,
517         .alloc_repbuf           = plain_alloc_repbuf,
518         .free_reqbuf            = plain_free_reqbuf,
519         .free_repbuf            = plain_free_repbuf,
520         .enlarge_reqbuf         = plain_enlarge_reqbuf,
521 };
522
523 static struct ptlrpc_sec_sops plain_sec_sops = {
524         .accept                 = plain_accept,
525         .alloc_rs               = plain_alloc_rs,
526         .authorize              = plain_authorize,
527         .free_rs                = plain_free_rs,
528         .unwrap_bulk            = plain_svc_unwrap_bulk,
529         .wrap_bulk              = plain_svc_wrap_bulk,
530 };
531
532 static struct ptlrpc_sec_policy plain_policy = {
533         .sp_owner               = THIS_MODULE,
534         .sp_name                = "sec.plain",
535         .sp_policy              = SPTLRPC_POLICY_PLAIN,
536         .sp_cops                = &plain_sec_cops,
537         .sp_sops                = &plain_sec_sops,
538 };
539
540 static
541 void plain_init_internal(void)
542 {
543         static HLIST_HEAD(__list);
544
545         plain_sec.ps_policy = &plain_policy;
546         atomic_set(&plain_sec.ps_refcount, 1);     /* always busy */
547         plain_sec.ps_import = NULL;
548         plain_sec.ps_flavor = SPTLRPC_FLVR_PLAIN;
549         plain_sec.ps_flags = 0;
550         spin_lock_init(&plain_sec.ps_lock);
551         atomic_set(&plain_sec.ps_busy, 1);         /* for "plain_cli_ctx" */
552         CFS_INIT_LIST_HEAD(&plain_sec.ps_gc_list);
553         plain_sec.ps_gc_interval = 0;
554         plain_sec.ps_gc_next = 0;
555
556         hlist_add_head(&plain_cli_ctx.cc_cache, &__list);
557         atomic_set(&plain_cli_ctx.cc_refcount, 1);    /* for hash */
558         plain_cli_ctx.cc_sec = &plain_sec;
559         plain_cli_ctx.cc_ops = &plain_ctx_ops;
560         plain_cli_ctx.cc_expire = 0;
561         plain_cli_ctx.cc_flags = PTLRPC_CTX_CACHED | PTLRPC_CTX_ETERNAL |
562                                  PTLRPC_CTX_UPTODATE;
563         plain_cli_ctx.cc_vcred.vc_uid = 0;
564         spin_lock_init(&plain_cli_ctx.cc_lock);
565         CFS_INIT_LIST_HEAD(&plain_cli_ctx.cc_req_list);
566         CFS_INIT_LIST_HEAD(&plain_cli_ctx.cc_gc_chain);
567 }
568
569 int sptlrpc_plain_init(void)
570 {
571         int rc;
572
573         plain_init_internal();
574
575         rc = sptlrpc_register_policy(&plain_policy);
576         if (rc)
577                 CERROR("failed to register sec.plain: %d\n", rc);
578
579         return rc;
580 }
581
582 void sptlrpc_plain_fini(void)
583 {
584         int rc;
585
586         rc = sptlrpc_unregister_policy(&plain_policy);
587         if (rc)
588                 CERROR("cannot unregister sec.plain: %d\n", rc);
589 }