]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/staging/lustre/lustre/ptlrpc/gss/gss_bulk.c
staging: add Lustre file system client support
[karo-tx-linux.git] / drivers / staging / lustre / lustre / ptlrpc / gss / gss_bulk.c
1 /*
2  * GPL HEADER START
3  *
4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 only,
8  * as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License version 2 for more details (a copy is included
14  * in the LICENSE file that accompanied this code).
15  *
16  * You should have received a copy of the GNU General Public License
17  * version 2 along with this program; If not, see
18  * http://www.sun.com/software/products/lustre/docs/GPLv2.pdf
19  *
20  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
21  * CA 95054 USA or visit www.sun.com if you need additional information or
22  * have any questions.
23  *
24  * GPL HEADER END
25  */
26 /*
27  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
28  * Use is subject to license terms.
29  */
30 /*
31  * This file is part of Lustre, http://www.lustre.org/
32  * Lustre is a trademark of Sun Microsystems, Inc.
33  *
34  * lustre/ptlrpc/gss/gss_bulk.c
35  *
36  * Author: Eric Mei <eric.mei@sun.com>
37  */
38
39 #define DEBUG_SUBSYSTEM S_SEC
40 #include <linux/init.h>
41 #include <linux/module.h>
42 #include <linux/slab.h>
43 #include <linux/dcache.h>
44 #include <linux/fs.h>
45 #include <linux/mutex.h>
46 #include <linux/crypto.h>
47
48 #include <obd.h>
49 #include <obd_class.h>
50 #include <obd_support.h>
51 #include <lustre/lustre_idl.h>
52 #include <lustre_net.h>
53 #include <lustre_import.h>
54 #include <lustre_sec.h>
55
56 #include "gss_err.h"
57 #include "gss_internal.h"
58 #include "gss_api.h"
59
60 int gss_cli_ctx_wrap_bulk(struct ptlrpc_cli_ctx *ctx,
61                           struct ptlrpc_request *req,
62                           struct ptlrpc_bulk_desc *desc)
63 {
64         struct gss_cli_ctx            *gctx;
65         struct lustre_msg              *msg;
66         struct ptlrpc_bulk_sec_desc     *bsd;
67         rawobj_t                         token;
68         __u32                       maj;
69         int                           offset;
70         int                           rc;
71         ENTRY;
72
73         LASSERT(req->rq_pack_bulk);
74         LASSERT(req->rq_bulk_read || req->rq_bulk_write);
75
76         gctx = container_of(ctx, struct gss_cli_ctx, gc_base);
77         LASSERT(gctx->gc_mechctx);
78
79         switch (SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc)) {
80         case SPTLRPC_SVC_NULL:
81                 LASSERT(req->rq_reqbuf->lm_bufcount >= 3);
82                 msg = req->rq_reqbuf;
83                 offset = msg->lm_bufcount - 1;
84                 break;
85         case SPTLRPC_SVC_AUTH:
86         case SPTLRPC_SVC_INTG:
87                 LASSERT(req->rq_reqbuf->lm_bufcount >= 4);
88                 msg = req->rq_reqbuf;
89                 offset = msg->lm_bufcount - 2;
90                 break;
91         case SPTLRPC_SVC_PRIV:
92                 LASSERT(req->rq_clrbuf->lm_bufcount >= 2);
93                 msg = req->rq_clrbuf;
94                 offset = msg->lm_bufcount - 1;
95                 break;
96         default:
97                 LBUG();
98         }
99
100         bsd = lustre_msg_buf(msg, offset, sizeof(*bsd));
101         bsd->bsd_version = 0;
102         bsd->bsd_flags = 0;
103         bsd->bsd_type = SPTLRPC_BULK_DEFAULT;
104         bsd->bsd_svc = SPTLRPC_FLVR_BULK_SVC(req->rq_flvr.sf_rpc);
105
106         if (bsd->bsd_svc == SPTLRPC_BULK_SVC_NULL)
107                 RETURN(0);
108
109         LASSERT(bsd->bsd_svc == SPTLRPC_BULK_SVC_INTG ||
110                 bsd->bsd_svc == SPTLRPC_BULK_SVC_PRIV);
111
112         if (req->rq_bulk_read) {
113                 /*
114                  * bulk read: prepare receiving pages only for privacy mode.
115                  */
116                 if (bsd->bsd_svc == SPTLRPC_BULK_SVC_PRIV)
117                         return gss_cli_prep_bulk(req, desc);
118         } else {
119                 /*
120                  * bulk write: sign or encrypt bulk pages.
121                  */
122                 bsd->bsd_nob = desc->bd_nob;
123
124                 if (bsd->bsd_svc == SPTLRPC_BULK_SVC_INTG) {
125                         /* integrity mode */
126                         token.data = bsd->bsd_data;
127                         token.len = lustre_msg_buflen(msg, offset) -
128                                     sizeof(*bsd);
129
130                         maj = lgss_get_mic(gctx->gc_mechctx, 0, NULL,
131                                            desc->bd_iov_count, desc->bd_iov,
132                                            &token);
133                         if (maj != GSS_S_COMPLETE) {
134                                 CWARN("failed to sign bulk data: %x\n", maj);
135                                 RETURN(-EACCES);
136                         }
137                 } else {
138                         /* privacy mode */
139                         if (desc->bd_iov_count == 0)
140                                 RETURN(0);
141
142                         rc = sptlrpc_enc_pool_get_pages(desc);
143                         if (rc) {
144                                 CERROR("bulk write: failed to allocate "
145                                        "encryption pages: %d\n", rc);
146                                 RETURN(rc);
147                         }
148
149                         token.data = bsd->bsd_data;
150                         token.len = lustre_msg_buflen(msg, offset) -
151                                     sizeof(*bsd);
152
153                         maj = lgss_wrap_bulk(gctx->gc_mechctx, desc, &token, 0);
154                         if (maj != GSS_S_COMPLETE) {
155                                 CWARN("fail to encrypt bulk data: %x\n", maj);
156                                 RETURN(-EACCES);
157                         }
158                 }
159         }
160
161         RETURN(0);
162 }
163
164 int gss_cli_ctx_unwrap_bulk(struct ptlrpc_cli_ctx *ctx,
165                             struct ptlrpc_request *req,
166                             struct ptlrpc_bulk_desc *desc)
167 {
168         struct gss_cli_ctx            *gctx;
169         struct lustre_msg              *rmsg, *vmsg;
170         struct ptlrpc_bulk_sec_desc     *bsdr, *bsdv;
171         rawobj_t                         token;
172         __u32                       maj;
173         int                           roff, voff;
174         ENTRY;
175
176         LASSERT(req->rq_pack_bulk);
177         LASSERT(req->rq_bulk_read || req->rq_bulk_write);
178
179         switch (SPTLRPC_FLVR_SVC(req->rq_flvr.sf_rpc)) {
180         case SPTLRPC_SVC_NULL:
181                 vmsg = req->rq_repdata;
182                 voff = vmsg->lm_bufcount - 1;
183                 LASSERT(vmsg && vmsg->lm_bufcount >= 3);
184
185                 rmsg = req->rq_reqbuf;
186                 roff = rmsg->lm_bufcount - 1; /* last segment */
187                 LASSERT(rmsg && rmsg->lm_bufcount >= 3);
188                 break;
189         case SPTLRPC_SVC_AUTH:
190         case SPTLRPC_SVC_INTG:
191                 vmsg = req->rq_repdata;
192                 voff = vmsg->lm_bufcount - 2;
193                 LASSERT(vmsg && vmsg->lm_bufcount >= 4);
194
195                 rmsg = req->rq_reqbuf;
196                 roff = rmsg->lm_bufcount - 2; /* second last segment */
197                 LASSERT(rmsg && rmsg->lm_bufcount >= 4);
198                 break;
199         case SPTLRPC_SVC_PRIV:
200                 vmsg = req->rq_repdata;
201                 voff = vmsg->lm_bufcount - 1;
202                 LASSERT(vmsg && vmsg->lm_bufcount >= 2);
203
204                 rmsg = req->rq_clrbuf;
205                 roff = rmsg->lm_bufcount - 1; /* last segment */
206                 LASSERT(rmsg && rmsg->lm_bufcount >= 2);
207                 break;
208         default:
209                 LBUG();
210         }
211
212         bsdr = lustre_msg_buf(rmsg, roff, sizeof(*bsdr));
213         bsdv = lustre_msg_buf(vmsg, voff, sizeof(*bsdv));
214         LASSERT(bsdr && bsdv);
215
216         if (bsdr->bsd_version != bsdv->bsd_version ||
217             bsdr->bsd_type != bsdv->bsd_type ||
218             bsdr->bsd_svc != bsdv->bsd_svc) {
219                 CERROR("bulk security descriptor mismatch: "
220                        "(%u,%u,%u) != (%u,%u,%u)\n",
221                        bsdr->bsd_version, bsdr->bsd_type, bsdr->bsd_svc,
222                        bsdv->bsd_version, bsdv->bsd_type, bsdv->bsd_svc);
223                 RETURN(-EPROTO);
224         }
225
226         LASSERT(bsdv->bsd_svc == SPTLRPC_BULK_SVC_NULL ||
227                 bsdv->bsd_svc == SPTLRPC_BULK_SVC_INTG ||
228                 bsdv->bsd_svc == SPTLRPC_BULK_SVC_PRIV);
229
230         /*
231          * in privacy mode if return success, make sure bd_nob_transferred
232          * is the actual size of the clear text, otherwise upper layer
233          * may be surprised.
234          */
235         if (req->rq_bulk_write) {
236                 if (bsdv->bsd_flags & BSD_FL_ERR) {
237                         CERROR("server reported bulk i/o failure\n");
238                         RETURN(-EIO);
239                 }
240
241                 if (bsdv->bsd_svc == SPTLRPC_BULK_SVC_PRIV)
242                         desc->bd_nob_transferred = desc->bd_nob;
243         } else {
244                 /*
245                  * bulk read, upon return success, bd_nob_transferred is
246                  * the size of plain text actually received.
247                  */
248                 gctx = container_of(ctx, struct gss_cli_ctx, gc_base);
249                 LASSERT(gctx->gc_mechctx);
250
251                 if (bsdv->bsd_svc == SPTLRPC_BULK_SVC_INTG) {
252                         int i, nob;
253
254                         /* fix the actual data size */
255                         for (i = 0, nob = 0; i < desc->bd_iov_count; i++) {
256                                 if (desc->bd_iov[i].kiov_len + nob >
257                                     desc->bd_nob_transferred) {
258                                         desc->bd_iov[i].kiov_len =
259                                                 desc->bd_nob_transferred - nob;
260                                 }
261                                 nob += desc->bd_iov[i].kiov_len;
262                         }
263
264                         token.data = bsdv->bsd_data;
265                         token.len = lustre_msg_buflen(vmsg, voff) -
266                                     sizeof(*bsdv);
267
268                         maj = lgss_verify_mic(gctx->gc_mechctx, 0, NULL,
269                                               desc->bd_iov_count, desc->bd_iov,
270                                               &token);
271                         if (maj != GSS_S_COMPLETE) {
272                                 CERROR("failed to verify bulk read: %x\n", maj);
273                                 RETURN(-EACCES);
274                         }
275                 } else if (bsdv->bsd_svc == SPTLRPC_BULK_SVC_PRIV) {
276                         desc->bd_nob = bsdv->bsd_nob;
277                         if (desc->bd_nob == 0)
278                                 RETURN(0);
279
280                         token.data = bsdv->bsd_data;
281                         token.len = lustre_msg_buflen(vmsg, voff) -
282                                     sizeof(*bsdr);
283
284                         maj = lgss_unwrap_bulk(gctx->gc_mechctx, desc,
285                                                &token, 1);
286                         if (maj != GSS_S_COMPLETE) {
287                                 CERROR("failed to decrypt bulk read: %x\n",
288                                        maj);
289                                 RETURN(-EACCES);
290                         }
291
292                         desc->bd_nob_transferred = desc->bd_nob;
293                 }
294         }
295
296         RETURN(0);
297 }
298
299 static int gss_prep_bulk(struct ptlrpc_bulk_desc *desc,
300                          struct gss_ctx *mechctx)
301 {
302         int     rc;
303
304         if (desc->bd_iov_count == 0)
305                 return 0;
306
307         rc = sptlrpc_enc_pool_get_pages(desc);
308         if (rc)
309                 return rc;
310
311         if (lgss_prep_bulk(mechctx, desc) != GSS_S_COMPLETE)
312                 return -EACCES;
313
314         return 0;
315 }
316
317 int gss_cli_prep_bulk(struct ptlrpc_request *req,
318                       struct ptlrpc_bulk_desc *desc)
319 {
320         int          rc;
321         ENTRY;
322
323         LASSERT(req->rq_cli_ctx);
324         LASSERT(req->rq_pack_bulk);
325         LASSERT(req->rq_bulk_read);
326
327         if (SPTLRPC_FLVR_BULK_SVC(req->rq_flvr.sf_rpc) != SPTLRPC_BULK_SVC_PRIV)
328                 RETURN(0);
329
330         rc = gss_prep_bulk(desc, ctx2gctx(req->rq_cli_ctx)->gc_mechctx);
331         if (rc)
332                 CERROR("bulk read: failed to prepare encryption "
333                        "pages: %d\n", rc);
334
335         RETURN(rc);
336 }
337
338 int gss_svc_prep_bulk(struct ptlrpc_request *req,
339                       struct ptlrpc_bulk_desc *desc)
340 {
341         struct gss_svc_reqctx   *grctx;
342         struct ptlrpc_bulk_sec_desc  *bsd;
343         int                        rc;
344         ENTRY;
345
346         LASSERT(req->rq_svc_ctx);
347         LASSERT(req->rq_pack_bulk);
348         LASSERT(req->rq_bulk_write);
349
350         grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
351         LASSERT(grctx->src_reqbsd);
352         LASSERT(grctx->src_repbsd);
353         LASSERT(grctx->src_ctx);
354         LASSERT(grctx->src_ctx->gsc_mechctx);
355
356         bsd = grctx->src_reqbsd;
357         if (bsd->bsd_svc != SPTLRPC_BULK_SVC_PRIV)
358                 RETURN(0);
359
360         rc = gss_prep_bulk(desc, grctx->src_ctx->gsc_mechctx);
361         if (rc)
362                 CERROR("bulk write: failed to prepare encryption "
363                        "pages: %d\n", rc);
364
365         RETURN(rc);
366 }
367
368 int gss_svc_unwrap_bulk(struct ptlrpc_request *req,
369                         struct ptlrpc_bulk_desc *desc)
370 {
371         struct gss_svc_reqctx   *grctx;
372         struct ptlrpc_bulk_sec_desc  *bsdr, *bsdv;
373         rawobj_t                      token;
374         __u32                    maj;
375         ENTRY;
376
377         LASSERT(req->rq_svc_ctx);
378         LASSERT(req->rq_pack_bulk);
379         LASSERT(req->rq_bulk_write);
380
381         grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
382
383         LASSERT(grctx->src_reqbsd);
384         LASSERT(grctx->src_repbsd);
385         LASSERT(grctx->src_ctx);
386         LASSERT(grctx->src_ctx->gsc_mechctx);
387
388         bsdr = grctx->src_reqbsd;
389         bsdv = grctx->src_repbsd;
390
391         /* bsdr has been sanity checked during unpacking */
392         bsdv->bsd_version = 0;
393         bsdv->bsd_type = SPTLRPC_BULK_DEFAULT;
394         bsdv->bsd_svc = bsdr->bsd_svc;
395         bsdv->bsd_flags = 0;
396
397         switch (bsdv->bsd_svc) {
398         case SPTLRPC_BULK_SVC_INTG:
399                 token.data = bsdr->bsd_data;
400                 token.len = grctx->src_reqbsd_size - sizeof(*bsdr);
401
402                 maj = lgss_verify_mic(grctx->src_ctx->gsc_mechctx, 0, NULL,
403                                       desc->bd_iov_count, desc->bd_iov, &token);
404                 if (maj != GSS_S_COMPLETE) {
405                         bsdv->bsd_flags |= BSD_FL_ERR;
406                         CERROR("failed to verify bulk signature: %x\n", maj);
407                         RETURN(-EACCES);
408                 }
409                 break;
410         case SPTLRPC_BULK_SVC_PRIV:
411                 if (bsdr->bsd_nob != desc->bd_nob) {
412                         bsdv->bsd_flags |= BSD_FL_ERR;
413                         CERROR("prepared nob %d doesn't match the actual "
414                                "nob %d\n", desc->bd_nob, bsdr->bsd_nob);
415                         RETURN(-EPROTO);
416                 }
417
418                 if (desc->bd_iov_count == 0) {
419                         LASSERT(desc->bd_nob == 0);
420                         break;
421                 }
422
423                 token.data = bsdr->bsd_data;
424                 token.len = grctx->src_reqbsd_size - sizeof(*bsdr);
425
426                 maj = lgss_unwrap_bulk(grctx->src_ctx->gsc_mechctx,
427                                        desc, &token, 0);
428                 if (maj != GSS_S_COMPLETE) {
429                         bsdv->bsd_flags |= BSD_FL_ERR;
430                         CERROR("failed decrypt bulk data: %x\n", maj);
431                         RETURN(-EACCES);
432                 }
433                 break;
434         }
435
436         RETURN(0);
437 }
438
439 int gss_svc_wrap_bulk(struct ptlrpc_request *req,
440                       struct ptlrpc_bulk_desc *desc)
441 {
442         struct gss_svc_reqctx   *grctx;
443         struct ptlrpc_bulk_sec_desc  *bsdr, *bsdv;
444         rawobj_t                      token;
445         __u32                    maj;
446         int                        rc;
447         ENTRY;
448
449         LASSERT(req->rq_svc_ctx);
450         LASSERT(req->rq_pack_bulk);
451         LASSERT(req->rq_bulk_read);
452
453         grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
454
455         LASSERT(grctx->src_reqbsd);
456         LASSERT(grctx->src_repbsd);
457         LASSERT(grctx->src_ctx);
458         LASSERT(grctx->src_ctx->gsc_mechctx);
459
460         bsdr = grctx->src_reqbsd;
461         bsdv = grctx->src_repbsd;
462
463         /* bsdr has been sanity checked during unpacking */
464         bsdv->bsd_version = 0;
465         bsdv->bsd_type = SPTLRPC_BULK_DEFAULT;
466         bsdv->bsd_svc = bsdr->bsd_svc;
467         bsdv->bsd_flags = 0;
468
469         switch (bsdv->bsd_svc) {
470         case SPTLRPC_BULK_SVC_INTG:
471                 token.data = bsdv->bsd_data;
472                 token.len = grctx->src_repbsd_size - sizeof(*bsdv);
473
474                 maj = lgss_get_mic(grctx->src_ctx->gsc_mechctx, 0, NULL,
475                                    desc->bd_iov_count, desc->bd_iov, &token);
476                 if (maj != GSS_S_COMPLETE) {
477                         bsdv->bsd_flags |= BSD_FL_ERR;
478                         CERROR("failed to sign bulk data: %x\n", maj);
479                         RETURN(-EACCES);
480                 }
481                 break;
482         case SPTLRPC_BULK_SVC_PRIV:
483                 bsdv->bsd_nob = desc->bd_nob;
484
485                 if (desc->bd_iov_count == 0) {
486                         LASSERT(desc->bd_nob == 0);
487                         break;
488                 }
489
490                 rc = sptlrpc_enc_pool_get_pages(desc);
491                 if (rc) {
492                         bsdv->bsd_flags |= BSD_FL_ERR;
493                         CERROR("bulk read: failed to allocate encryption "
494                                "pages: %d\n", rc);
495                         RETURN(rc);
496                 }
497
498                 token.data = bsdv->bsd_data;
499                 token.len = grctx->src_repbsd_size - sizeof(*bsdv);
500
501                 maj = lgss_wrap_bulk(grctx->src_ctx->gsc_mechctx,
502                                      desc, &token, 1);
503                 if (maj != GSS_S_COMPLETE) {
504                         bsdv->bsd_flags |= BSD_FL_ERR;
505                         CERROR("failed to encrypt bulk data: %x\n", maj);
506                         RETURN(-EACCES);
507                 }
508                 break;
509         }
510
511         RETURN(0);
512 }