Whamcloud - gitweb
83025d146e28bd463eddef8387f9228b2727fa96
[fs/lustre-release.git] / lustre / ptlrpc / gss / sec_gss.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Modifications for Lustre
5  * Copyright 2004 - 2006, Cluster File Systems, Inc.
6  * All rights reserved
7  * Author: Eric Mei <ericm@clusterfs.com>
8  */
9
10 /*
11  * linux/net/sunrpc/auth_gss.c
12  *
13  * RPCSEC_GSS client authentication.
14  *
15  *  Copyright (c) 2000 The Regents of the University of Michigan.
16  *  All rights reserved.
17  *
18  *  Dug Song       <dugsong@monkey.org>
19  *  Andy Adamson   <andros@umich.edu>
20  *
21  *  Redistribution and use in source and binary forms, with or without
22  *  modification, are permitted provided that the following conditions
23  *  are met:
24  *
25  *  1. Redistributions of source code must retain the above copyright
26  *     notice, this list of conditions and the following disclaimer.
27  *  2. Redistributions in binary form must reproduce the above copyright
28  *     notice, this list of conditions and the following disclaimer in the
29  *     documentation and/or other materials provided with the distribution.
30  *  3. Neither the name of the University nor the names of its
31  *     contributors may be used to endorse or promote products derived
32  *     from this software without specific prior written permission.
33  *
34  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
35  *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
36  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
37  *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38  *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
39  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
40  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41  *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
42  *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
43  *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
44  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45  *
46  */
47
48 #ifndef EXPORT_SYMTAB
49 # define EXPORT_SYMTAB
50 #endif
51 #define DEBUG_SUBSYSTEM S_SEC
52 #ifdef __KERNEL__
53 #include <linux/init.h>
54 #include <linux/module.h>
55 #include <linux/slab.h>
56 #include <linux/dcache.h>
57 #include <linux/fs.h>
58 #include <linux/random.h>
59 #include <asm/atomic.h>
60 #else
61 #include <liblustre.h>
62 #endif
63
64 #include <obd.h>
65 #include <obd_class.h>
66 #include <obd_support.h>
67 #include <lustre/lustre_idl.h>
68 #include <lustre_net.h>
69 #include <lustre_import.h>
70 #include <lustre_sec.h>
71
72 #include "gss_err.h"
73 #include "gss_internal.h"
74 #include "gss_api.h"
75
76 #include <linux/crypto.h>
77
78 /* pre-definition */
79 static struct ptlrpc_sec_policy gss_policy;
80 static struct ptlrpc_cli_ctx * gss_sec_create_ctx(struct ptlrpc_sec *sec,
81                                                   struct vfs_cred *vcred);
82 static void gss_sec_destroy_ctx(struct ptlrpc_sec *sec,
83                                 struct ptlrpc_cli_ctx *ctx);
84 /********************************************
85  * wire data swabber                        *
86  ********************************************/
87
88 static
89 void gss_header_swabber(struct gss_header *ghdr)
90 {
91         __swab32s(&ghdr->gh_version);
92         __swab32s(&ghdr->gh_flags);
93         __swab32s(&ghdr->gh_proc);
94         __swab32s(&ghdr->gh_seq);
95         __swab32s(&ghdr->gh_svc);
96         __swab32s(&ghdr->gh_pad1);
97         __swab32s(&ghdr->gh_pad2);
98         __swab32s(&ghdr->gh_pad3);
99         __swab32s(&ghdr->gh_handle.len);
100 }
101
102 struct gss_header *gss_swab_header(struct lustre_msg *msg, int segment)
103 {
104         struct gss_header *ghdr;
105
106         ghdr = lustre_swab_buf(msg, segment, sizeof(*ghdr),
107                                gss_header_swabber);
108
109         if (ghdr &&
110             sizeof(*ghdr) + ghdr->gh_handle.len > msg->lm_buflens[segment]) {
111                 CERROR("gss header require length %d, now %d received\n",
112                        sizeof(*ghdr) + ghdr->gh_handle.len,
113                        msg->lm_buflens[segment]);
114                 return NULL;
115         }
116
117         return ghdr;
118 }
119
120 static
121 void gss_netobj_swabber(netobj_t *obj)
122 {
123         __swab32s(&obj->len);
124 }
125
126 netobj_t *gss_swab_netobj(struct lustre_msg *msg, int segment)
127 {
128         netobj_t  *obj;
129
130         obj = lustre_swab_buf(msg, segment, sizeof(*obj), gss_netobj_swabber);
131         if (obj && sizeof(*obj) + obj->len > msg->lm_buflens[segment]) {
132                 CERROR("netobj require length %d but only %d received\n",
133                        sizeof(*obj) + obj->len, msg->lm_buflens[segment]);
134                 return NULL;
135         }
136
137         return obj;
138 }
139
140 /*
141  * payload should be obtained from mechanism. but currently since we
142  * only support kerberos, we could simply use fixed value.
143  * krb5 header:         16
144  * krb5 checksum:       20
145  */
146 #define GSS_KRB5_INTEG_MAX_PAYLOAD      (40)
147
148 static inline
149 int gss_estimate_payload(struct gss_ctx *mechctx, int msgsize, int privacy)
150 {
151         if (privacy) {
152                 /* we suppose max cipher block size is 16 bytes. here we
153                  * add 16 for confounder and 16 for padding.
154                  */
155                 return GSS_KRB5_INTEG_MAX_PAYLOAD + msgsize + 16 + 16 + 16;
156         } else {
157                 return GSS_KRB5_INTEG_MAX_PAYLOAD;
158         }
159 }
160
161 /*
162  * return signature size, otherwise < 0 to indicate error
163  */
164 static
165 int gss_sign_msg(struct lustre_msg *msg,
166                  struct gss_ctx *mechctx,
167                  __u32 proc, __u32 seq,
168                  rawobj_t *handle)
169 {
170         struct gss_header      *ghdr;
171         rawobj_t                text[3], mic;
172         int                     textcnt, mic_idx = msg->lm_bufcount - 1;
173         __u32                   major;
174
175         LASSERT(msg->lm_bufcount >= 3);
176
177         /* gss hdr */
178         LASSERT(msg->lm_buflens[0] >=
179                 sizeof(*ghdr) + (handle ? handle->len : 0));
180         ghdr = lustre_msg_buf(msg, 0, 0);
181
182         ghdr->gh_version = PTLRPC_GSS_VERSION;
183         ghdr->gh_flags = 0;
184         ghdr->gh_proc = proc;
185         ghdr->gh_seq = seq;
186         ghdr->gh_svc = PTLRPC_GSS_SVC_INTEGRITY;
187         if (!handle) {
188                 /* fill in a fake one */
189                 ghdr->gh_handle.len = 0;
190         } else {
191                 ghdr->gh_handle.len = handle->len;
192                 memcpy(ghdr->gh_handle.data, handle->data, handle->len);
193         }
194
195         /* MIC */
196         for (textcnt = 0; textcnt < mic_idx; textcnt++) {
197                 text[textcnt].len = msg->lm_buflens[textcnt];
198                 text[textcnt].data = lustre_msg_buf(msg, textcnt, 0);
199         }
200
201         mic.len = msg->lm_buflens[mic_idx];
202         mic.data = lustre_msg_buf(msg, mic_idx, 0);
203
204         major = lgss_get_mic(mechctx, textcnt, text, &mic);
205         if (major != GSS_S_COMPLETE) {
206                 CERROR("fail to generate MIC: %08x\n", major);
207                 return -EPERM;
208         }
209         LASSERT(mic.len <= msg->lm_buflens[mic_idx]);
210
211         return lustre_shrink_msg(msg, mic_idx, mic.len, 0);
212 }
213
214 /*
215  * return gss error
216  */
217 static
218 __u32 gss_verify_msg(struct lustre_msg *msg,
219                    struct gss_ctx *mechctx)
220 {
221         rawobj_t         text[3];
222         rawobj_t         mic;
223         int              textcnt, mic_idx = msg->lm_bufcount - 1;
224         __u32            major;
225
226         for (textcnt = 0; textcnt < mic_idx; textcnt++) {
227                 text[textcnt].len = msg->lm_buflens[textcnt];
228                 text[textcnt].data = lustre_msg_buf(msg, textcnt, 0);
229         }
230
231         mic.len = msg->lm_buflens[mic_idx];
232         mic.data = lustre_msg_buf(msg, mic_idx, 0);
233
234         major = lgss_verify_mic(mechctx, textcnt, text, &mic);
235         if (major != GSS_S_COMPLETE)
236                 CERROR("mic verify error: %08x\n", major);
237
238         return major;
239 }
240
241 /*
242  * return gss error code
243  */
244 static
245 __u32 gss_unseal_msg(struct gss_ctx *mechctx,
246                    struct lustre_msg *msgbuf,
247                    int *msg_len, int msgbuf_len)
248 {
249         rawobj_t                 clear_obj, micobj, msgobj, token;
250         __u8                    *clear_buf;
251         int                      clear_buflen;
252         __u32                    major;
253         ENTRY;
254
255         if (msgbuf->lm_bufcount != 3) {
256                 CERROR("invalid bufcount %d\n", msgbuf->lm_bufcount);
257                 RETURN(GSS_S_FAILURE);
258         }
259
260         /* verify gss header */
261         msgobj.len = msgbuf->lm_buflens[0];
262         msgobj.data = lustre_msg_buf(msgbuf, 0, 0);
263         micobj.len = msgbuf->lm_buflens[1];
264         micobj.data = lustre_msg_buf(msgbuf, 1, 0);
265
266         major = lgss_verify_mic(mechctx, 1, &msgobj, &micobj);
267         if (major != GSS_S_COMPLETE) {
268                 CERROR("priv: mic verify error: %08x\n", major);
269                 RETURN(major);
270         }
271
272         /* temporary clear text buffer */
273         clear_buflen = msgbuf->lm_buflens[2];
274         OBD_ALLOC(clear_buf, clear_buflen);
275         if (!clear_buf)
276                 RETURN(GSS_S_FAILURE);
277
278         token.len = msgbuf->lm_buflens[2];
279         token.data = lustre_msg_buf(msgbuf, 2, 0);
280
281         clear_obj.len = clear_buflen;
282         clear_obj.data = clear_buf;
283
284         major = lgss_unwrap(mechctx, &token, &clear_obj);
285         if (major != GSS_S_COMPLETE) {
286                 CERROR("priv: unwrap message error: %08x\n", major);
287                 GOTO(out_free, major = GSS_S_FAILURE);
288         }
289         LASSERT(clear_obj.len <= clear_buflen);
290
291         /* now the decrypted message */
292         memcpy(msgbuf, clear_obj.data, clear_obj.len);
293         *msg_len = clear_obj.len;
294
295         major = GSS_S_COMPLETE;
296 out_free:
297         OBD_FREE(clear_buf, clear_buflen);
298         RETURN(major);
299 }
300
301 /********************************************
302  * gss client context manipulation helpers  *
303  ********************************************/
304
305 void gss_cli_ctx_uptodate(struct gss_cli_ctx *gctx)
306 {
307         struct ptlrpc_cli_ctx *ctx = &gctx->gc_base;
308         unsigned long ctx_expiry;
309
310         if (lgss_inquire_context(gctx->gc_mechctx, &ctx_expiry)) {
311                 CERROR("ctx %p(%u): unable to inquire, expire it now\n",
312                        gctx, ctx->cc_vcred.vc_uid);
313                 ctx_expiry = 1; /* make it expired now */
314         }
315
316         ctx->cc_expire = gss_round_ctx_expiry(ctx_expiry,
317                                               ctx->cc_sec->ps_flags);
318
319         /* At this point this ctx might have been marked as dead by
320          * someone else, in which case nobody will make further use
321          * of it. we don't care, and mark it UPTODATE will help
322          * destroying server side context when it be destroied.
323          */
324         set_bit(PTLRPC_CTX_UPTODATE_BIT, &ctx->cc_flags);
325
326         CWARN("%s ctx %p(%u->%s), will expire at %lu(%lds lifetime)\n",
327               (ctx->cc_sec->ps_flags & PTLRPC_SEC_FL_REVERSE ?
328                "server installed reverse" : "client refreshed"),
329               ctx, ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec),
330               ctx->cc_expire, (long) (ctx->cc_expire - get_seconds()));
331 }
332
333 static
334 void gss_cli_ctx_finalize(struct gss_cli_ctx *gctx)
335 {
336         if (gctx->gc_mechctx)
337                 lgss_delete_sec_context(&gctx->gc_mechctx);
338
339         rawobj_free(&gctx->gc_handle);
340 }
341
342 /*
343  * Based on sequence number algorithm as specified in RFC 2203.
344  *
345  * modified for our own problem: arriving request has valid sequence number,
346  * but unwrapping request might cost a long time, after that its sequence
347  * are not valid anymore (fall behind the window). It rarely happen, mostly
348  * under extreme load.
349  *
350  * note we should not check sequence before verify the integrity of incoming
351  * request, because just one attacking request with high sequence number might
352  * cause all following request be dropped.
353  *
354  * so here we use a multi-phase approach: prepare 2 sequence windows,
355  * "main window" for normal sequence and "back window" for fall behind sequence.
356  * and 3-phase checking mechanism:
357  *  0 - before integrity verification, perform a initial sequence checking in
358  *      main window, which only try and don't actually set any bits. if the
359  *      sequence is high above the window or fit in the window and the bit
360  *      is 0, then accept and proceed to integrity verification. otherwise
361  *      reject this sequence.
362  *  1 - after integrity verification, check in main window again. if this
363  *      sequence is high above the window or fit in the window and the bit
364  *      is 0, then set the bit and accept; if it fit in the window but bit
365  *      already set, then reject; if it fall behind the window, then proceed
366  *      to phase 2.
367  *  2 - check in back window. if it is high above the window or fit in the
368  *      window and the bit is 0, then set the bit and accept. otherwise reject.
369  *
370  * return value:
371  *   1: looks like a replay
372  *   0: is ok
373  *  -1: is a replay
374  *
375  * note phase 0 is necessary, because otherwise replay attacking request of
376  * sequence which between the 2 windows can't be detected.
377  *
378  * this mechanism can't totally solve the problem, but could help much less
379  * number of valid requests be dropped.
380  */
381 static
382 int gss_do_check_seq(unsigned long *window, __u32 win_size, __u32 *max_seq,
383                      __u32 seq_num, int phase)
384 {
385         LASSERT(phase >= 0 && phase <= 2);
386
387         if (seq_num > *max_seq) {
388                 /*
389                  * 1. high above the window
390                  */
391                 if (phase == 0)
392                         return 0;
393
394                 if (seq_num >= *max_seq + win_size) {
395                         memset(window, 0, win_size / 8);
396                         *max_seq = seq_num;
397                 } else {
398                         while(*max_seq < seq_num) {
399                                 (*max_seq)++;
400                                 __clear_bit((*max_seq) % win_size, window);
401                         }
402                 }
403                 __set_bit(seq_num % win_size, window);
404         } else if (seq_num + win_size <= *max_seq) {
405                 /*
406                  * 2. low behind the window
407                  */
408                 if (phase == 0 || phase == 2)
409                         goto replay;
410
411                 CWARN("seq %u is %u behind (size %d), check backup window\n",
412                       seq_num, *max_seq - win_size - seq_num, win_size);
413                 return 1;
414         } else {
415                 /*
416                  * 3. fit into the window
417                  */
418                 switch (phase) {
419                 case 0:
420                         if (test_bit(seq_num % win_size, window))
421                                 goto replay;
422                         break;
423                 case 1:
424                 case 2:
425                      if (__test_and_set_bit(seq_num % win_size, window))
426                                 goto replay;
427                         break;
428                 }
429         }
430
431         return 0;
432
433 replay:
434         CERROR("seq %u (%s %s window) is a replay: max %u, winsize %d\n",
435                seq_num,
436                seq_num + win_size > *max_seq ? "in" : "behind",
437                phase == 2 ? "backup " : "main",
438                *max_seq, win_size);
439         return -1;
440 }
441
442 /*
443  * Based on sequence number algorithm as specified in RFC 2203.
444  *
445  * if @set == 0: initial check, don't set any bit in window
446  * if @sec == 1: final check, set bit in window
447  */
448 int gss_check_seq_num(struct gss_svc_seq_data *ssd, __u32 seq_num, int set)
449 {
450         int rc = 0;
451
452         spin_lock(&ssd->ssd_lock);
453
454         if (set == 0) {
455                 /*
456                  * phase 0 testing
457                  */
458                 rc = gss_do_check_seq(ssd->ssd_win_main, GSS_SEQ_WIN_MAIN,
459                                       &ssd->ssd_max_main, seq_num, 0);
460                 if (unlikely(rc))
461                         gss_stat_oos_record_svc(0, 1);
462         } else {
463                 /*
464                  * phase 1 checking main window
465                  */
466                 rc = gss_do_check_seq(ssd->ssd_win_main, GSS_SEQ_WIN_MAIN,
467                                       &ssd->ssd_max_main, seq_num, 1);
468                 switch (rc) {
469                 case -1:
470                         gss_stat_oos_record_svc(1, 1);
471                         /* fall through */
472                 case 0:
473                         goto exit;
474                 }
475                 /*
476                  * phase 2 checking back window
477                  */
478                 rc = gss_do_check_seq(ssd->ssd_win_back, GSS_SEQ_WIN_BACK,
479                                       &ssd->ssd_max_back, seq_num, 2);
480                 if (rc)
481                         gss_stat_oos_record_svc(2, 1);
482                 else
483                         gss_stat_oos_record_svc(2, 0);
484         }
485 exit:
486         spin_unlock(&ssd->ssd_lock);
487         return rc;
488 }
489
490 /***************************************
491  * cred APIs                           *
492  ***************************************/
493
494 static inline
495 int gss_cli_payload(struct ptlrpc_cli_ctx *ctx,
496                     int msgsize, int privacy)
497 {
498         return gss_estimate_payload(NULL, msgsize, privacy);
499 }
500
501 static
502 int gss_cli_ctx_refresh(struct ptlrpc_cli_ctx *ctx)
503 {
504         /* if we are refreshing for root, also update the reverse
505          * handle index, do not confuse reverse contexts.
506          */
507         if (ctx->cc_vcred.vc_uid == 0) {
508                 struct gss_sec *gsec;
509
510                 gsec = container_of(ctx->cc_sec, struct gss_sec, gs_base);
511                 gsec->gs_rvs_hdl = gss_get_next_ctx_index();
512         }
513
514         return gss_ctx_refresh_pipefs(ctx);
515 }
516
517 static
518 int gss_cli_ctx_match(struct ptlrpc_cli_ctx *ctx, struct vfs_cred *vcred)
519 {
520         return (ctx->cc_vcred.vc_uid == vcred->vc_uid);
521 }
522
523 static
524 void gss_cli_ctx_flags2str(unsigned long flags, char *buf, int bufsize)
525 {
526         buf[0] = '\0';
527
528         if (flags & PTLRPC_CTX_UPTODATE)
529                 strncat(buf, "uptodate,", bufsize);
530         if (flags & PTLRPC_CTX_DEAD)
531                 strncat(buf, "dead,", bufsize);
532         if (flags & PTLRPC_CTX_ERROR)
533                 strncat(buf, "error,", bufsize);
534         if (flags & PTLRPC_CTX_HASHED)
535                 strncat(buf, "hashed,", bufsize);
536         if (flags & PTLRPC_CTX_ETERNAL)
537                 strncat(buf, "eternal,", bufsize);
538         if (buf[0] == '\0')
539                 strncat(buf, "-,", bufsize);
540
541         buf[strlen(buf) - 1] = '\0';
542 }
543
544 static
545 int gss_cli_ctx_display(struct ptlrpc_cli_ctx *ctx, char *buf, int bufsize)
546 {
547         struct gss_cli_ctx     *gctx;
548         char                    flags_str[40];
549         int                     written;
550
551         gctx = container_of(ctx, struct gss_cli_ctx, gc_base);
552
553         gss_cli_ctx_flags2str(ctx->cc_flags, flags_str, sizeof(flags_str));
554
555         written = snprintf(buf, bufsize,
556                         "UID %d:\n" 
557                         "  flags:       %s\n"
558                         "  seqwin:      %d\n"
559                         "  sequence:    %d\n",
560                         ctx->cc_vcred.vc_uid,
561                         flags_str,
562                         gctx->gc_win,
563                         atomic_read(&gctx->gc_seq));
564
565         if (gctx->gc_mechctx) {
566                 written += lgss_display(gctx->gc_mechctx,
567                                         buf + written, bufsize - written);
568         }
569
570         return written;
571 }
572
573 static
574 int gss_cli_ctx_sign(struct ptlrpc_cli_ctx *ctx,
575                      struct ptlrpc_request *req)
576 {
577         struct gss_cli_ctx      *gctx;
578         __u32                    seq;
579         int                      rc;
580         ENTRY;
581
582         LASSERT(req->rq_reqbuf);
583         LASSERT(req->rq_reqbuf->lm_bufcount >= 3);
584         LASSERT(req->rq_cli_ctx == ctx);
585
586         /* nothing to do for context negotiation RPCs */
587         if (req->rq_ctx_init)
588                 RETURN(0);
589
590         gctx = container_of(ctx, struct gss_cli_ctx, gc_base);
591 redo:
592         seq = atomic_inc_return(&gctx->gc_seq);
593
594         rc = gss_sign_msg(req->rq_reqbuf, gctx->gc_mechctx,
595                           gctx->gc_proc, seq, &gctx->gc_handle);
596         if (rc < 0)
597                 RETURN(rc);
598
599         /* gss_sign_msg() msg might take long time to finish, in which period
600          * more rpcs could be wrapped up and sent out. if we found too many
601          * of them we should repack this rpc, because sent it too late might
602          * lead to the sequence number fall behind the window on server and
603          * be dropped. also applies to gss_cli_ctx_seal().
604          */
605         if (atomic_read(&gctx->gc_seq) - seq > GSS_SEQ_REPACK_THRESHOLD) {
606                 int behind = atomic_read(&gctx->gc_seq) - seq;
607
608                 gss_stat_oos_record_cli(behind);
609                 CWARN("req %p: %u behind, retry signing\n", req, behind);
610                 goto redo;
611         }
612
613         req->rq_reqdata_len = rc;
614         RETURN(0);
615 }
616
617 static
618 int gss_cli_ctx_handle_err_notify(struct ptlrpc_cli_ctx *ctx,
619                                   struct ptlrpc_request *req,
620                                   struct gss_header *ghdr)
621 {
622         struct gss_err_header *errhdr;
623         int rc;
624
625         LASSERT(ghdr->gh_proc == PTLRPC_GSS_PROC_ERR);
626
627         errhdr = (struct gss_err_header *) ghdr;
628
629         /* server return NO_CONTEXT might be caused by context expire
630          * or server reboot/failover. we refresh the cred transparently
631          * to upper layer.
632          * In some cases, our gss handle is possible to be incidentally
633          * identical to another handle since the handle itself is not
634          * fully random. In krb5 case, the GSS_S_BAD_SIG will be
635          * returned, maybe other gss error for other mechanism.
636          *
637          * if we add new mechanism, make sure the correct error are
638          * returned in this case.
639          *
640          * but in any cases, don't resend ctx destroying rpc, don't resend
641          * reverse rpc.
642          */
643         if (req->rq_ctx_fini) {
644                 CWARN("server respond error (%08x/%08x) for ctx fini\n",
645                       errhdr->gh_major, errhdr->gh_minor);
646                 rc = -EINVAL;
647         } else if (ctx->cc_sec->ps_flags & PTLRPC_SEC_FL_REVERSE) {
648                 CWARN("reverse server respond error (%08x/%08x)\n",
649                       errhdr->gh_major, errhdr->gh_minor);
650                 rc = -EINVAL;
651         } else if (errhdr->gh_major == GSS_S_NO_CONTEXT ||
652                    errhdr->gh_major == GSS_S_BAD_SIG) {
653                 CWARN("req x"LPU64"/t"LPU64": server respond ctx %p(%u->%s) "
654                       "%s, server might lost the context.\n",
655                       req->rq_xid, req->rq_transno, ctx, ctx->cc_vcred.vc_uid,
656                       sec2target_str(ctx->cc_sec),
657                       errhdr->gh_major == GSS_S_NO_CONTEXT ?
658                       "NO_CONTEXT" : "BAD_SIG");
659
660                 sptlrpc_ctx_expire(ctx);
661                 req->rq_resend = 1;
662                 rc = 0;
663         } else {
664                 CERROR("req %p: server report gss error (%x/%x)\n",
665                         req, errhdr->gh_major, errhdr->gh_minor);
666                 rc = -EACCES;
667         }
668
669         return rc;
670 }
671
672 static
673 int gss_cli_ctx_verify(struct ptlrpc_cli_ctx *ctx,
674                        struct ptlrpc_request *req)
675 {
676         struct gss_cli_ctx     *gctx;
677         struct gss_header      *ghdr, *reqhdr;
678         struct lustre_msg      *msg = req->rq_repbuf;
679         __u32                   major;
680         int                     rc = 0;
681         ENTRY;
682
683         LASSERT(req->rq_cli_ctx == ctx);
684         LASSERT(msg);
685
686         req->rq_repdata_len = req->rq_nob_received;
687         gctx = container_of(ctx, struct gss_cli_ctx, gc_base);
688
689         /* special case for context negotiation, rq_repmsg/rq_replen actually
690          * are not used currently.
691          */
692         if (req->rq_ctx_init) {
693                 req->rq_repmsg = lustre_msg_buf(msg, 1, 0);
694                 req->rq_replen = msg->lm_buflens[1];
695                 RETURN(0);
696         }
697
698         if (msg->lm_bufcount < 3 || msg->lm_bufcount > 4) {
699                 CERROR("unexpected bufcount %u\n", msg->lm_bufcount);
700                 RETURN(-EPROTO);
701         }
702
703         ghdr = gss_swab_header(msg, 0);
704         if (ghdr == NULL) {
705                 CERROR("can't decode gss header\n");
706                 RETURN(-EPROTO);
707         }
708
709         /* sanity checks */
710         reqhdr = lustre_msg_buf(msg, 0, sizeof(*reqhdr));
711         LASSERT(reqhdr);
712
713         if (ghdr->gh_version != reqhdr->gh_version) {
714                 CERROR("gss version %u mismatch, expect %u\n",
715                        ghdr->gh_version, reqhdr->gh_version);
716                 RETURN(-EPROTO);
717         }
718
719         switch (ghdr->gh_proc) {
720         case PTLRPC_GSS_PROC_DATA:
721                 if (ghdr->gh_seq != reqhdr->gh_seq) {
722                         CERROR("seqnum %u mismatch, expect %u\n",
723                                ghdr->gh_seq, reqhdr->gh_seq);
724                         RETURN(-EPROTO);
725                 }
726
727                 if (ghdr->gh_svc != PTLRPC_GSS_SVC_INTEGRITY) {
728                         CERROR("unexpected svc %d\n", ghdr->gh_svc);
729                         RETURN(-EPROTO);
730                 }
731
732                 if (lustre_msg_swabbed(msg))
733                         gss_header_swabber(ghdr);
734
735                 major = gss_verify_msg(msg, gctx->gc_mechctx);
736                 if (major != GSS_S_COMPLETE)
737                         RETURN(-EPERM);
738
739                 req->rq_repmsg = lustre_msg_buf(msg, 1, 0);
740                 req->rq_replen = msg->lm_buflens[1];
741
742                 if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
743                         if (msg->lm_bufcount < 4) {
744                                 CERROR("Invalid reply bufcount %u\n",
745                                        msg->lm_bufcount);
746                                 RETURN(-EPROTO);
747                         }
748
749                         /* bulk checksum is the second last segment */
750                         rc = bulk_sec_desc_unpack(msg, msg->lm_bufcount - 2);
751                 }
752                 break;
753         case PTLRPC_GSS_PROC_ERR:
754                 rc = gss_cli_ctx_handle_err_notify(ctx, req, ghdr);
755                 break;
756         default:
757                 CERROR("unknown gss proc %d\n", ghdr->gh_proc);
758                 rc = -EPROTO;
759         }
760
761         RETURN(rc);
762 }
763
764 static
765 int gss_cli_ctx_seal(struct ptlrpc_cli_ctx *ctx,
766                      struct ptlrpc_request *req)
767 {
768         struct gss_cli_ctx      *gctx;
769         rawobj_t                 msgobj, cipher_obj, micobj;
770         struct gss_header       *ghdr;
771         int                      buflens[3], wiresize, rc;
772         __u32                    major;
773         ENTRY;
774
775         LASSERT(req->rq_clrbuf);
776         LASSERT(req->rq_cli_ctx == ctx);
777         LASSERT(req->rq_reqlen);
778
779         gctx = container_of(ctx, struct gss_cli_ctx, gc_base);
780
781         /* close clear data length */
782         req->rq_clrdata_len = lustre_msg_size_v2(req->rq_clrbuf->lm_bufcount,
783                                                  req->rq_clrbuf->lm_buflens);
784
785         /* calculate wire data length */
786         buflens[0] = PTLRPC_GSS_HEADER_SIZE;
787         buflens[1] = gss_cli_payload(&gctx->gc_base, buflens[0], 0);
788         buflens[2] = gss_cli_payload(&gctx->gc_base, req->rq_clrdata_len, 1);
789         wiresize = lustre_msg_size_v2(3, buflens);
790
791         /* allocate wire buffer */
792         if (req->rq_pool) {
793                 /* pre-allocated */
794                 LASSERT(req->rq_reqbuf);
795                 LASSERT(req->rq_reqbuf != req->rq_clrbuf);
796                 LASSERT(req->rq_reqbuf_len >= wiresize);
797         } else {
798                 OBD_ALLOC(req->rq_reqbuf, wiresize);
799                 if (!req->rq_reqbuf)
800                         RETURN(-ENOMEM);
801                 req->rq_reqbuf_len = wiresize;
802         }
803
804         lustre_init_msg_v2(req->rq_reqbuf, 3, buflens, NULL);
805         req->rq_reqbuf->lm_secflvr = req->rq_sec_flavor;
806
807         /* gss header */
808         ghdr = lustre_msg_buf(req->rq_reqbuf, 0, 0);
809         ghdr->gh_version = PTLRPC_GSS_VERSION;
810         ghdr->gh_flags = 0;
811         ghdr->gh_proc = gctx->gc_proc;
812         ghdr->gh_seq = atomic_inc_return(&gctx->gc_seq);
813         ghdr->gh_svc = PTLRPC_GSS_SVC_PRIVACY;
814         ghdr->gh_handle.len = gctx->gc_handle.len;
815         memcpy(ghdr->gh_handle.data, gctx->gc_handle.data, gctx->gc_handle.len);
816
817 redo:
818         /* header signature */
819         msgobj.len = req->rq_reqbuf->lm_buflens[0];
820         msgobj.data = lustre_msg_buf(req->rq_reqbuf, 0, 0);
821         micobj.len = req->rq_reqbuf->lm_buflens[1];
822         micobj.data = lustre_msg_buf(req->rq_reqbuf, 1, 0);
823
824         major = lgss_get_mic(gctx->gc_mechctx, 1, &msgobj, &micobj);
825         if (major != GSS_S_COMPLETE) {
826                 CERROR("priv: sign message error: %08x\n", major);
827                 GOTO(err_free, rc = -EPERM);
828         }
829         /* perhaps shrink msg has potential problem in re-packing???
830          * ship a little bit more data is fine.
831         lustre_shrink_msg(req->rq_reqbuf, 1, micobj.len, 0);
832          */
833
834         /* clear text */
835         msgobj.len = req->rq_clrdata_len;
836         msgobj.data = (__u8 *) req->rq_clrbuf;
837
838         /* cipher text */
839         cipher_obj.len = req->rq_reqbuf->lm_buflens[2];
840         cipher_obj.data = lustre_msg_buf(req->rq_reqbuf, 2, 0);
841
842         major = lgss_wrap(gctx->gc_mechctx, &msgobj, req->rq_clrbuf_len,
843                           &cipher_obj);
844         if (major != GSS_S_COMPLETE) {
845                 CERROR("priv: wrap message error: %08x\n", major);
846                 GOTO(err_free, rc = -EPERM);
847         }
848         LASSERT(cipher_obj.len <= buflens[2]);
849
850         /* see explain in gss_cli_ctx_sign() */
851         if (atomic_read(&gctx->gc_seq) - ghdr->gh_seq >
852             GSS_SEQ_REPACK_THRESHOLD) {
853                 int behind = atomic_read(&gctx->gc_seq) - ghdr->gh_seq;
854
855                 gss_stat_oos_record_cli(behind);
856                 CWARN("req %p: %u behind, retry sealing\n", req, behind);
857
858                 ghdr->gh_seq = atomic_inc_return(&gctx->gc_seq);
859                 goto redo;
860         }
861
862         /* now set the final wire data length */
863         req->rq_reqdata_len = lustre_shrink_msg(req->rq_reqbuf, 2,
864                                                 cipher_obj.len, 0);
865
866         RETURN(0);
867
868 err_free:
869         if (!req->rq_pool) {
870                 OBD_FREE(req->rq_reqbuf, req->rq_reqbuf_len);
871                 req->rq_reqbuf = NULL;
872                 req->rq_reqbuf_len = 0;
873         }
874         RETURN(rc);
875 }
876
877 static
878 int gss_cli_ctx_unseal(struct ptlrpc_cli_ctx *ctx,
879                        struct ptlrpc_request *req)
880 {
881         struct gss_cli_ctx      *gctx;
882         struct gss_header       *ghdr;
883         int                      msglen, rc;
884         __u32                    major;
885         ENTRY;
886
887         LASSERT(req->rq_repbuf);
888         LASSERT(req->rq_cli_ctx == ctx);
889
890         gctx = container_of(ctx, struct gss_cli_ctx, gc_base);
891
892         ghdr = gss_swab_header(req->rq_repbuf, 0);
893         if (ghdr == NULL) {
894                 CERROR("can't decode gss header\n");
895                 RETURN(-EPROTO);
896         }
897
898         /* sanity checks */
899         if (ghdr->gh_version != PTLRPC_GSS_VERSION) {
900                 CERROR("gss version %u mismatch, expect %u\n",
901                        ghdr->gh_version, PTLRPC_GSS_VERSION);
902                 RETURN(-EPROTO);
903         }
904
905         switch (ghdr->gh_proc) {
906         case PTLRPC_GSS_PROC_DATA:
907                 if (lustre_msg_swabbed(req->rq_repbuf))
908                         gss_header_swabber(ghdr);
909
910                 major = gss_unseal_msg(gctx->gc_mechctx, req->rq_repbuf,
911                                        &msglen, req->rq_repbuf_len);
912                 if (major != GSS_S_COMPLETE) {
913                         rc = -EPERM;
914                         break;
915                 }
916
917                 if (lustre_unpack_msg(req->rq_repbuf, msglen)) {
918                         CERROR("Failed to unpack after decryption\n");
919                         RETURN(-EPROTO);
920                 }
921                 req->rq_repdata_len = msglen;
922
923                 if (req->rq_repbuf->lm_bufcount < 1) {
924                         CERROR("Invalid reply buffer: empty\n");
925                         RETURN(-EPROTO);
926                 }
927
928                 if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
929                         if (req->rq_repbuf->lm_bufcount < 2) {
930                                 CERROR("Too few request buffer segments %d\n",
931                                        req->rq_repbuf->lm_bufcount);
932                                 RETURN(-EPROTO);
933                         }
934
935                         /* bulk checksum is the last segment */
936                         if (bulk_sec_desc_unpack(req->rq_repbuf,
937                                                  req->rq_repbuf->lm_bufcount-1))
938                                 RETURN(-EPROTO);
939                 }
940
941                 req->rq_repmsg = lustre_msg_buf(req->rq_repbuf, 0, 0);
942                 req->rq_replen = req->rq_repbuf->lm_buflens[0];
943
944                 rc = 0;
945                 break;
946         case PTLRPC_GSS_PROC_ERR:
947                 rc = gss_cli_ctx_handle_err_notify(ctx, req, ghdr);
948                 break;
949         default:
950                 CERROR("unexpected proc %d\n", ghdr->gh_proc);
951                 rc = -EPERM;
952         }
953
954         RETURN(rc);
955 }
956
957 static struct ptlrpc_ctx_ops gss_ctxops = {
958         .refresh        = gss_cli_ctx_refresh,
959         .match          = gss_cli_ctx_match,
960         .display        = gss_cli_ctx_display,
961         .sign           = gss_cli_ctx_sign,
962         .verify         = gss_cli_ctx_verify,
963         .seal           = gss_cli_ctx_seal,
964         .unseal         = gss_cli_ctx_unseal,
965         .wrap_bulk      = gss_cli_ctx_wrap_bulk,
966         .unwrap_bulk    = gss_cli_ctx_unwrap_bulk,
967 };
968
969 /*********************************************
970  * reverse context installation              *
971  *********************************************/
972 static
973 int gss_install_rvs_cli_ctx(struct gss_sec *gsec,
974                             struct ptlrpc_svc_ctx *svc_ctx)
975 {
976         struct vfs_cred          vcred;
977         struct gss_svc_reqctx   *grctx;
978         struct ptlrpc_cli_ctx   *cli_ctx;
979         struct gss_cli_ctx      *cli_gctx;
980         struct gss_ctx          *mechctx = NULL;
981         __u32                    major;
982         int                      rc;
983         ENTRY;
984
985         vcred.vc_uid = 0;
986
987         cli_ctx = gss_sec_create_ctx(&gsec->gs_base, &vcred);
988         if (!cli_ctx)
989                 RETURN(-ENOMEM);
990
991         grctx = container_of(svc_ctx, struct gss_svc_reqctx, src_base);
992         LASSERT(grctx);
993         LASSERT(grctx->src_ctx);
994         LASSERT(grctx->src_ctx->gsc_mechctx);
995
996         major = lgss_copy_reverse_context(grctx->src_ctx->gsc_mechctx, &mechctx);
997         if (major != GSS_S_COMPLETE)
998                 GOTO(err_ctx, rc = -ENOMEM);
999
1000         cli_gctx = container_of(cli_ctx, struct gss_cli_ctx, gc_base);
1001
1002         cli_gctx->gc_proc = PTLRPC_GSS_PROC_DATA;
1003         cli_gctx->gc_win = GSS_SEQ_WIN;
1004         atomic_set(&cli_gctx->gc_seq, 0);
1005
1006         if (rawobj_dup(&cli_gctx->gc_handle, &grctx->src_ctx->gsc_rvs_hdl))
1007                 GOTO(err_mechctx, rc = -ENOMEM);
1008
1009         cli_gctx->gc_mechctx = mechctx;
1010         gss_cli_ctx_uptodate(cli_gctx);
1011
1012         sptlrpc_ctx_replace(&gsec->gs_base, cli_ctx);
1013         RETURN(0);
1014
1015 err_mechctx:
1016         lgss_delete_sec_context(&mechctx);
1017 err_ctx:
1018         gss_sec_destroy_ctx(cli_ctx->cc_sec, cli_ctx);
1019         return rc;
1020 }
1021
1022
1023 static inline
1024 int gss_install_rvs_svc_ctx(struct obd_import *imp,
1025                             struct gss_sec *gsec,
1026                             struct gss_cli_ctx *gctx)
1027 {
1028         return gss_svc_upcall_install_rvs_ctx(imp, gsec, gctx);
1029 }
1030
1031 /*********************************************
1032  * GSS security APIs                         *
1033  *********************************************/
1034
1035 static
1036 struct ptlrpc_cli_ctx * gss_sec_create_ctx(struct ptlrpc_sec *sec,
1037                                            struct vfs_cred *vcred)
1038 {
1039         struct gss_cli_ctx    *gctx;
1040         struct ptlrpc_cli_ctx *ctx;
1041         ENTRY;
1042
1043         OBD_ALLOC_PTR(gctx);
1044         if (!gctx)
1045                 RETURN(NULL);
1046
1047         gctx->gc_win = 0;
1048         atomic_set(&gctx->gc_seq, 0);
1049
1050         ctx = &gctx->gc_base;
1051         INIT_HLIST_NODE(&ctx->cc_hash);
1052         atomic_set(&ctx->cc_refcount, 0);
1053         ctx->cc_sec = sec;
1054         ctx->cc_ops = &gss_ctxops;
1055         ctx->cc_expire = 0;
1056         ctx->cc_flags = 0;
1057         ctx->cc_vcred = *vcred;
1058         spin_lock_init(&ctx->cc_lock);
1059         INIT_LIST_HEAD(&ctx->cc_req_list);
1060
1061         CDEBUG(D_SEC, "create a gss cred at %p(uid %u)\n", ctx, vcred->vc_uid);
1062         RETURN(ctx);
1063 }
1064
1065 static
1066 void gss_sec_destroy_ctx(struct ptlrpc_sec *sec, struct ptlrpc_cli_ctx *ctx)
1067 {
1068         struct gss_cli_ctx *gctx;
1069         ENTRY;
1070
1071         LASSERT(ctx);
1072         LASSERT(atomic_read(&ctx->cc_refcount) == 0);
1073
1074         gctx = container_of(ctx, struct gss_cli_ctx, gc_base);
1075         if (gctx->gc_mechctx) {
1076                 gss_do_ctx_fini_rpc(gctx);
1077                 gss_cli_ctx_finalize(gctx);
1078         }
1079
1080         CWARN("%s@%p: destroy ctx %p(%u->%s)\n",
1081               ctx->cc_sec->ps_policy->sp_name, ctx->cc_sec,
1082               ctx, ctx->cc_vcred.vc_uid, sec2target_str(ctx->cc_sec));
1083
1084         OBD_FREE_PTR(gctx);
1085         EXIT;
1086 }
1087
1088 #define GSS_CCACHE_SIZE         (32)
1089
1090 static
1091 struct ptlrpc_sec* gss_sec_create(struct obd_import *imp,
1092                                   struct ptlrpc_svc_ctx *ctx,
1093                                   __u32 flavor,
1094                                   unsigned long flags)
1095 {
1096         struct gss_sec      *gsec;
1097         struct ptlrpc_sec   *sec;
1098         int                  alloc_size, cache_size, i;
1099         ENTRY;
1100
1101         LASSERT(imp);
1102         LASSERT(SEC_FLAVOR_POLICY(flavor) == SPTLRPC_POLICY_GSS);
1103
1104         if (ctx || flags & (PTLRPC_SEC_FL_ROOTONLY | PTLRPC_SEC_FL_REVERSE))
1105                 cache_size = 1;
1106         else
1107                 cache_size = GSS_CCACHE_SIZE;
1108
1109         alloc_size = sizeof(*gsec) + sizeof(struct list_head) * cache_size;
1110
1111         OBD_ALLOC(gsec, alloc_size);
1112         if (!gsec)
1113                 RETURN(NULL);
1114
1115         gsec->gs_mech = lgss_subflavor_to_mech(SEC_FLAVOR_SUB(flavor));
1116         if (!gsec->gs_mech) {
1117                 CERROR("gss backend 0x%x not found\n", SEC_FLAVOR_SUB(flavor));
1118                 goto err_free;
1119         }
1120
1121         spin_lock_init(&gsec->gs_lock);
1122         gsec->gs_rvs_hdl = 0ULL; /* will be updated later */
1123
1124         sec = &gsec->gs_base;
1125         sec->ps_policy = &gss_policy;
1126         sec->ps_flavor = flavor;
1127         sec->ps_flags = flags;
1128         sec->ps_import = class_import_get(imp);
1129         sec->ps_lock = SPIN_LOCK_UNLOCKED;
1130         sec->ps_ccache_size = cache_size;
1131         sec->ps_ccache = (struct hlist_head *) (gsec + 1);
1132         atomic_set(&sec->ps_busy, 0);
1133
1134         for (i = 0; i < cache_size; i++)
1135                 INIT_HLIST_HEAD(&sec->ps_ccache[i]);
1136
1137         if (!ctx) {
1138                 if (gss_sec_upcall_init(gsec))
1139                         goto err_mech;
1140
1141                 sec->ps_gc_interval = 30 * 60; /* 30 minutes */
1142                 sec->ps_gc_next = cfs_time_current_sec() + sec->ps_gc_interval;
1143         } else {
1144                 LASSERT(sec->ps_flags & PTLRPC_SEC_FL_REVERSE);
1145
1146                 if (gss_install_rvs_cli_ctx(gsec, ctx))
1147                         goto err_mech;
1148
1149                 /* never do gc on reverse sec */
1150                 sec->ps_gc_interval = 0;
1151                 sec->ps_gc_next = 0;
1152         }
1153
1154         if (SEC_FLAVOR_SVC(flavor) == SPTLRPC_SVC_PRIV &&
1155             flags & PTLRPC_SEC_FL_BULK)
1156                 sptlrpc_enc_pool_add_user();
1157
1158         CWARN("create %s%s@%p\n", (ctx ? "reverse " : ""),
1159               gss_policy.sp_name, gsec);
1160         RETURN(sec);
1161
1162 err_mech:
1163         lgss_mech_put(gsec->gs_mech);
1164 err_free:
1165         OBD_FREE(gsec, alloc_size);
1166         RETURN(NULL);
1167 }
1168
1169 static
1170 void gss_sec_destroy(struct ptlrpc_sec *sec)
1171 {
1172         struct gss_sec *gsec;
1173         ENTRY;
1174
1175         gsec = container_of(sec, struct gss_sec, gs_base);
1176         CWARN("destroy %s@%p\n", gss_policy.sp_name, gsec);
1177
1178         LASSERT(gsec->gs_mech);
1179         LASSERT(sec->ps_import);
1180         LASSERT(sec->ps_ccache);
1181         LASSERT(sec->ps_ccache_size);
1182         LASSERT(atomic_read(&sec->ps_refcount) == 0);
1183         LASSERT(atomic_read(&sec->ps_busy) == 0);
1184
1185         gss_sec_upcall_cleanup(gsec);
1186         lgss_mech_put(gsec->gs_mech);
1187
1188         class_import_put(sec->ps_import);
1189
1190         if (SEC_FLAVOR_SVC(sec->ps_flavor) == SPTLRPC_SVC_PRIV &&
1191             sec->ps_flags & PTLRPC_SEC_FL_BULK)
1192                 sptlrpc_enc_pool_del_user();
1193
1194         OBD_FREE(gsec, sizeof(*gsec) +
1195                        sizeof(struct list_head) * sec->ps_ccache_size);
1196         EXIT;
1197 }
1198
1199 static
1200 int gss_alloc_reqbuf_auth(struct ptlrpc_sec *sec,
1201                           struct ptlrpc_request *req,
1202                           int msgsize)
1203 {
1204         struct sec_flavor_config *conf;
1205         int bufsize, txtsize;
1206         int buflens[5], bufcnt = 2;
1207         ENTRY;
1208
1209         /*
1210          * - gss header
1211          * - lustre message
1212          * - user descriptor
1213          * - bulk sec descriptor
1214          * - signature
1215          */
1216         buflens[0] = PTLRPC_GSS_HEADER_SIZE;
1217         buflens[1] = msgsize;
1218         txtsize = buflens[0] + buflens[1];
1219
1220         if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor)) {
1221                 buflens[bufcnt] = sptlrpc_user_desc_size();
1222                 txtsize += buflens[bufcnt];
1223                 bufcnt++;
1224         }
1225
1226         if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
1227                 conf = &req->rq_import->imp_obd->u.cli.cl_sec_conf;
1228                 buflens[bufcnt] = bulk_sec_desc_size(conf->sfc_bulk_csum, 1,
1229                                                      req->rq_bulk_read);
1230                 txtsize += buflens[bufcnt];
1231                 bufcnt++;
1232         }
1233
1234         buflens[bufcnt++] = req->rq_ctx_init ? GSS_CTX_INIT_MAX_LEN :
1235                             gss_cli_payload(req->rq_cli_ctx, txtsize, 0);
1236
1237         bufsize = lustre_msg_size_v2(bufcnt, buflens);
1238
1239         if (!req->rq_reqbuf) {
1240                 OBD_ALLOC(req->rq_reqbuf, bufsize);
1241                 if (!req->rq_reqbuf)
1242                         RETURN(-ENOMEM);
1243
1244                 req->rq_reqbuf_len = bufsize;
1245         } else {
1246                 LASSERT(req->rq_pool);
1247                 LASSERT(req->rq_reqbuf_len >= bufsize);
1248                 memset(req->rq_reqbuf, 0, bufsize);
1249         }
1250
1251         lustre_init_msg_v2(req->rq_reqbuf, bufcnt, buflens, NULL);
1252         req->rq_reqbuf->lm_secflvr = req->rq_sec_flavor;
1253
1254         req->rq_reqmsg = lustre_msg_buf(req->rq_reqbuf, 1, msgsize);
1255         LASSERT(req->rq_reqmsg);
1256
1257         /* pack user desc here, later we might leave current user's process */
1258         if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor))
1259                 sptlrpc_pack_user_desc(req->rq_reqbuf, 2);
1260
1261         RETURN(0);
1262 }
1263
1264 static
1265 int gss_alloc_reqbuf_priv(struct ptlrpc_sec *sec,
1266                           struct ptlrpc_request *req,
1267                           int msgsize)
1268 {
1269         struct sec_flavor_config *conf;
1270         int ibuflens[3], ibufcnt;
1271         int buflens[3];
1272         int clearsize, wiresize;
1273         ENTRY;
1274
1275         LASSERT(req->rq_clrbuf == NULL);
1276         LASSERT(req->rq_clrbuf_len == 0);
1277
1278         /* Inner (clear) buffers
1279          *  - lustre message
1280          *  - user descriptor
1281          *  - bulk checksum
1282          */
1283         ibufcnt = 1;
1284         ibuflens[0] = msgsize;
1285
1286         if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor))
1287                 ibuflens[ibufcnt++] = sptlrpc_user_desc_size();
1288         if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
1289                 conf = &req->rq_import->imp_obd->u.cli.cl_sec_conf;
1290                 ibuflens[ibufcnt++] = bulk_sec_desc_size(conf->sfc_bulk_csum, 1,
1291                                                          req->rq_bulk_read);
1292         }
1293         clearsize = lustre_msg_size_v2(ibufcnt, ibuflens);
1294         /* to allow append padding during encryption */
1295         clearsize += GSS_MAX_CIPHER_BLOCK;
1296
1297         /* Wrapper (wire) buffers
1298          *  - gss header
1299          *  - signature of gss header
1300          *  - cipher text
1301          */
1302         buflens[0] = PTLRPC_GSS_HEADER_SIZE;
1303         buflens[1] = gss_cli_payload(req->rq_cli_ctx, buflens[0], 0);
1304         buflens[2] = gss_cli_payload(req->rq_cli_ctx, clearsize, 1);
1305         wiresize = lustre_msg_size_v2(3, buflens);
1306
1307         if (req->rq_pool) {
1308                 /* rq_reqbuf is preallocated */
1309                 LASSERT(req->rq_reqbuf);
1310                 LASSERT(req->rq_reqbuf_len >= wiresize);
1311
1312                 memset(req->rq_reqbuf, 0, req->rq_reqbuf_len);
1313
1314                 /* if the pre-allocated buffer is big enough, we just pack
1315                  * both clear buf & request buf in it, to avoid more alloc.
1316                  */
1317                 if (clearsize + wiresize <= req->rq_reqbuf_len) {
1318                         req->rq_clrbuf =
1319                                 (void *) (((char *) req->rq_reqbuf) + wiresize);
1320                 } else {
1321                         CWARN("pre-allocated buf size %d is not enough for "
1322                               "both clear (%d) and cipher (%d) text, proceed "
1323                               "with extra allocation\n", req->rq_reqbuf_len,
1324                               clearsize, wiresize);
1325                 }
1326         }
1327
1328         if (!req->rq_clrbuf) {
1329                 OBD_ALLOC(req->rq_clrbuf, clearsize);
1330                 if (!req->rq_clrbuf)
1331                         RETURN(-ENOMEM);
1332         }
1333         req->rq_clrbuf_len = clearsize;
1334
1335         lustre_init_msg_v2(req->rq_clrbuf, ibufcnt, ibuflens, NULL);
1336         req->rq_reqmsg = lustre_msg_buf(req->rq_clrbuf, 0, msgsize);
1337
1338         if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor))
1339                 sptlrpc_pack_user_desc(req->rq_clrbuf, 1);
1340
1341         RETURN(0);
1342 }
1343
1344 static
1345 int gss_alloc_reqbuf(struct ptlrpc_sec *sec,
1346                      struct ptlrpc_request *req,
1347                      int msgsize)
1348 {
1349         LASSERT(!SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor) ||
1350                 (req->rq_bulk_read || req->rq_bulk_write));
1351
1352         switch (SEC_FLAVOR_SVC(req->rq_sec_flavor)) {
1353         case SPTLRPC_SVC_NONE:
1354         case SPTLRPC_SVC_AUTH:
1355                 return gss_alloc_reqbuf_auth(sec, req, msgsize);
1356         case SPTLRPC_SVC_PRIV:
1357                 return gss_alloc_reqbuf_priv(sec, req, msgsize);
1358         default:
1359                 LBUG();
1360         }
1361         return 0;
1362 }
1363
1364 static
1365 void gss_free_reqbuf(struct ptlrpc_sec *sec,
1366                      struct ptlrpc_request *req)
1367 {
1368         int privacy;
1369         ENTRY;
1370
1371         LASSERT(!req->rq_pool || req->rq_reqbuf);
1372         privacy = SEC_FLAVOR_SVC(req->rq_sec_flavor) == SPTLRPC_SVC_PRIV;
1373
1374         if (!req->rq_clrbuf)
1375                 goto release_reqbuf;
1376
1377         /* release clear buf*/
1378         LASSERT(privacy);
1379         LASSERT(req->rq_clrbuf_len);
1380
1381         if (req->rq_pool &&
1382             req->rq_clrbuf >= req->rq_reqbuf &&
1383             (char *) req->rq_clrbuf <
1384             (char *) req->rq_reqbuf + req->rq_reqbuf_len)
1385                 goto release_reqbuf;
1386
1387         OBD_FREE(req->rq_clrbuf, req->rq_clrbuf_len);
1388         req->rq_clrbuf = NULL;
1389         req->rq_clrbuf_len = 0;
1390
1391 release_reqbuf:
1392         if (!req->rq_pool && req->rq_reqbuf) {
1393                 OBD_FREE(req->rq_reqbuf, req->rq_reqbuf_len);
1394                 req->rq_reqbuf = NULL;
1395                 req->rq_reqbuf_len = 0;
1396         }
1397
1398         EXIT;
1399 }
1400
1401 static
1402 int gss_alloc_repbuf(struct ptlrpc_sec *sec,
1403                      struct ptlrpc_request *req,
1404                      int msgsize)
1405 {
1406         struct sec_flavor_config *conf;
1407         int privacy = (SEC_FLAVOR_SVC(req->rq_sec_flavor) == SPTLRPC_SVC_PRIV);
1408         int bufsize, txtsize;
1409         int buflens[4], bufcnt;
1410         ENTRY;
1411
1412         LASSERT(!SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor) ||
1413                 (req->rq_bulk_read || req->rq_bulk_write));
1414
1415         if (privacy) {
1416                 bufcnt = 1;
1417                 buflens[0] = msgsize;
1418                 if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
1419                         conf = &req->rq_import->imp_obd->u.cli.cl_sec_conf;
1420                         buflens[bufcnt++] = bulk_sec_desc_size(
1421                                                         conf->sfc_bulk_csum, 0,
1422                                                         req->rq_bulk_read);
1423                 }
1424                 txtsize = lustre_msg_size_v2(bufcnt, buflens);
1425                 txtsize += GSS_MAX_CIPHER_BLOCK;
1426
1427                 bufcnt = 3;
1428                 buflens[0] = PTLRPC_GSS_HEADER_SIZE;
1429                 buflens[1] = gss_cli_payload(req->rq_cli_ctx, buflens[0], 0);
1430                 buflens[2] = gss_cli_payload(req->rq_cli_ctx, txtsize, 1);
1431         } else {
1432                 bufcnt = 2;
1433                 buflens[0] = PTLRPC_GSS_HEADER_SIZE;
1434                 buflens[1] = msgsize;
1435                 txtsize = buflens[0] + buflens[1];
1436
1437                 if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
1438                         conf = &req->rq_import->imp_obd->u.cli.cl_sec_conf;
1439                         buflens[bufcnt] = bulk_sec_desc_size(
1440                                                         conf->sfc_bulk_csum, 0,
1441                                                         req->rq_bulk_read);
1442                         txtsize += buflens[bufcnt];
1443                         bufcnt++;
1444                 }
1445                 buflens[bufcnt++] = req->rq_ctx_init ? GSS_CTX_INIT_MAX_LEN :
1446                                    gss_cli_payload(req->rq_cli_ctx, txtsize, 0);
1447         }
1448
1449         bufsize = lustre_msg_size_v2(bufcnt, buflens);
1450
1451         OBD_ALLOC(req->rq_repbuf, bufsize);
1452         if (!req->rq_repbuf)
1453                 return -ENOMEM;
1454
1455         req->rq_repbuf_len = bufsize;
1456         return 0;
1457 }
1458
1459 static
1460 void gss_free_repbuf(struct ptlrpc_sec *sec,
1461                      struct ptlrpc_request *req)
1462 {
1463         OBD_FREE(req->rq_repbuf, req->rq_repbuf_len);
1464         req->rq_repbuf = NULL;
1465         req->rq_repbuf_len = 0;
1466 }
1467
1468 static
1469 int gss_sec_install_rctx(struct obd_import *imp,
1470                          struct ptlrpc_sec *sec,
1471                          struct ptlrpc_cli_ctx *ctx)
1472 {
1473         struct gss_sec     *gsec;
1474         struct gss_cli_ctx *gctx;
1475         int                 rc;
1476
1477         gsec = container_of(sec, struct gss_sec, gs_base);
1478         gctx = container_of(ctx, struct gss_cli_ctx, gc_base);
1479
1480         rc = gss_install_rvs_svc_ctx(imp, gsec, gctx);
1481         return rc;
1482 }
1483
1484 static struct ptlrpc_sec_cops gss_sec_cops = {
1485         .create_sec             = gss_sec_create,
1486         .destroy_sec            = gss_sec_destroy,
1487         .create_ctx             = gss_sec_create_ctx,
1488         .destroy_ctx            = gss_sec_destroy_ctx,
1489         .install_rctx           = gss_sec_install_rctx,
1490         .alloc_reqbuf           = gss_alloc_reqbuf,
1491         .free_reqbuf            = gss_free_reqbuf,
1492         .alloc_repbuf           = gss_alloc_repbuf,
1493         .free_repbuf            = gss_free_repbuf,
1494 };
1495
1496 /********************************************
1497  * server side API                          *
1498  ********************************************/
1499
1500 static inline
1501 int gss_svc_reqctx_is_special(struct gss_svc_reqctx *grctx)
1502 {
1503         LASSERT(grctx);
1504         return (grctx->src_init || grctx->src_init_continue ||
1505                 grctx->src_err_notify);
1506 }
1507
1508 static
1509 void gss_svc_reqctx_free(struct gss_svc_reqctx *grctx)
1510 {
1511         if (grctx->src_ctx)
1512                 gss_svc_upcall_put_ctx(grctx->src_ctx);
1513
1514         sptlrpc_policy_put(grctx->src_base.sc_policy);
1515         OBD_FREE_PTR(grctx);
1516 }
1517
1518 static inline
1519 void gss_svc_reqctx_addref(struct gss_svc_reqctx *grctx)
1520 {
1521         LASSERT(atomic_read(&grctx->src_base.sc_refcount) > 0);
1522         atomic_inc(&grctx->src_base.sc_refcount);
1523 }
1524
1525 static inline
1526 void gss_svc_reqctx_decref(struct gss_svc_reqctx *grctx)
1527 {
1528         LASSERT(atomic_read(&grctx->src_base.sc_refcount) > 0);
1529
1530         if (atomic_dec_and_test(&grctx->src_base.sc_refcount))
1531                 gss_svc_reqctx_free(grctx);
1532 }
1533
1534 static
1535 int gss_svc_sign(struct ptlrpc_request *req,
1536                  struct ptlrpc_reply_state *rs,
1537                  struct gss_svc_reqctx *grctx)
1538 {
1539         int     rc;
1540         ENTRY;
1541
1542         LASSERT(rs->rs_msg == lustre_msg_buf(rs->rs_repbuf, 1, 0));
1543
1544         /* embedded lustre_msg might have been shrinked */
1545         if (req->rq_replen != rs->rs_repbuf->lm_buflens[1])
1546                 lustre_shrink_msg(rs->rs_repbuf, 1, req->rq_replen, 1);
1547
1548         rc = gss_sign_msg(rs->rs_repbuf, grctx->src_ctx->gsc_mechctx,
1549                           PTLRPC_GSS_PROC_DATA, grctx->src_wirectx.gw_seq,
1550                           NULL);
1551         if (rc < 0)
1552                 RETURN(rc);
1553
1554         rs->rs_repdata_len = rc;
1555         RETURN(0);
1556 }
1557
1558 int gss_pack_err_notify(struct ptlrpc_request *req, __u32 major, __u32 minor)
1559 {
1560         struct gss_svc_reqctx     *grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
1561         struct ptlrpc_reply_state *rs;
1562         struct gss_err_header     *ghdr;
1563         int                        replen = sizeof(struct ptlrpc_body);
1564         int                        rc;
1565         ENTRY;
1566
1567         //OBD_FAIL_RETURN(OBD_FAIL_SVCGSS_ERR_NOTIFY|OBD_FAIL_ONCE, -EINVAL);
1568
1569         grctx->src_err_notify = 1;
1570         grctx->src_reserve_len = 0;
1571
1572         rc = lustre_pack_reply_v2(req, 1, &replen, NULL);
1573         if (rc) {
1574                 CERROR("could not pack reply, err %d\n", rc);
1575                 RETURN(rc);
1576         }
1577
1578         /* gss hdr */
1579         rs = req->rq_reply_state;
1580         LASSERT(rs->rs_repbuf->lm_buflens[1] >= sizeof(*ghdr));
1581         ghdr = lustre_msg_buf(rs->rs_repbuf, 0, 0);
1582         ghdr->gh_version = PTLRPC_GSS_VERSION;
1583         ghdr->gh_flags = 0;
1584         ghdr->gh_proc = PTLRPC_GSS_PROC_ERR;
1585         ghdr->gh_major = major;
1586         ghdr->gh_minor = minor;
1587         ghdr->gh_handle.len = 0; /* fake context handle */
1588
1589         rs->rs_repdata_len = lustre_msg_size_v2(rs->rs_repbuf->lm_bufcount,
1590                                                 rs->rs_repbuf->lm_buflens);
1591
1592         CDEBUG(D_SEC, "prepare gss error notify(0x%x/0x%x) to %s\n",
1593                major, minor, libcfs_nid2str(req->rq_peer.nid));
1594         RETURN(0);
1595 }
1596
1597 static
1598 int gss_svc_handle_init(struct ptlrpc_request *req,
1599                         struct gss_wire_ctx *gw)
1600 {
1601         struct gss_svc_reqctx     *grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
1602         struct lustre_msg         *reqbuf = req->rq_reqbuf;
1603         struct obd_uuid           *uuid;
1604         struct obd_device         *target;
1605         rawobj_t                   uuid_obj, rvs_hdl, in_token;
1606         __u32                      lustre_svc;
1607         __u32                     *secdata, seclen;
1608         int                        rc;
1609         ENTRY;
1610
1611         CDEBUG(D_SEC, "processing gss init(%d) request from %s\n", gw->gw_proc,
1612                libcfs_nid2str(req->rq_peer.nid));
1613
1614         if (gw->gw_proc == PTLRPC_GSS_PROC_INIT && gw->gw_handle.len != 0) {
1615                 CERROR("proc %u: invalid handle length %u\n",
1616                        gw->gw_proc, gw->gw_handle.len);
1617                 RETURN(SECSVC_DROP);
1618         }
1619
1620         if (reqbuf->lm_bufcount < 3 || reqbuf->lm_bufcount > 4){
1621                 CERROR("Invalid bufcount %d\n", reqbuf->lm_bufcount);
1622                 RETURN(SECSVC_DROP);
1623         }
1624
1625         /* ctx initiate payload is in last segment */
1626         secdata = lustre_msg_buf(reqbuf, reqbuf->lm_bufcount - 1, 0);
1627         seclen = reqbuf->lm_buflens[reqbuf->lm_bufcount - 1];
1628
1629         if (seclen < 4 + 4) {
1630                 CERROR("sec size %d too small\n", seclen);
1631                 RETURN(SECSVC_DROP);
1632         }
1633
1634         /* lustre svc type */
1635         lustre_svc = le32_to_cpu(*secdata++);
1636         seclen -= 4;
1637
1638         /* extract target uuid, note this code is somewhat fragile
1639          * because touched internal structure of obd_uuid
1640          */
1641         if (rawobj_extract(&uuid_obj, &secdata, &seclen)) {
1642                 CERROR("failed to extract target uuid\n");
1643                 RETURN(SECSVC_DROP);
1644         }
1645         uuid_obj.data[uuid_obj.len - 1] = '\0';
1646
1647         uuid = (struct obd_uuid *) uuid_obj.data;
1648         target = class_uuid2obd(uuid);
1649         if (!target || target->obd_stopping || !target->obd_set_up) {
1650                 CERROR("target '%s' is not available for context init (%s)",
1651                        uuid->uuid, target == NULL ? "no target" :
1652                        (target->obd_stopping ? "stopping" : "not set up"));
1653                 RETURN(SECSVC_DROP);
1654         }
1655
1656         /* extract reverse handle */
1657         if (rawobj_extract(&rvs_hdl, &secdata, &seclen)) {
1658                 CERROR("failed extract reverse handle\n");
1659                 RETURN(SECSVC_DROP);
1660         }
1661
1662         /* extract token */
1663         if (rawobj_extract(&in_token, &secdata, &seclen)) {
1664                 CERROR("can't extract token\n");
1665                 RETURN(SECSVC_DROP);
1666         }
1667
1668         rc = gss_svc_upcall_handle_init(req, grctx, gw, target, lustre_svc,
1669                                         &rvs_hdl, &in_token);
1670         if (rc != SECSVC_OK)
1671                 RETURN(rc);
1672
1673         if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor)) {
1674                 if (reqbuf->lm_bufcount < 4) {
1675                         CERROR("missing user descriptor\n");
1676                         RETURN(SECSVC_DROP);
1677                 }
1678                 if (sptlrpc_unpack_user_desc(reqbuf, 2)) {
1679                         CERROR("Mal-formed user descriptor\n");
1680                         RETURN(SECSVC_DROP);
1681                 }
1682                 req->rq_user_desc = lustre_msg_buf(reqbuf, 2, 0);
1683         }
1684
1685         req->rq_reqmsg = lustre_msg_buf(reqbuf, 1, 0);
1686         req->rq_reqlen = lustre_msg_buflen(reqbuf, 1);
1687
1688         RETURN(rc);
1689 }
1690
1691 /*
1692  * last segment must be the gss signature.
1693  */
1694 static
1695 int gss_svc_verify_request(struct ptlrpc_request *req,
1696                            struct gss_svc_ctx *gctx,
1697                            struct gss_wire_ctx *gw,
1698                            __u32 *major)
1699 {
1700         struct lustre_msg  *msg = req->rq_reqbuf;
1701         int                 offset = 2;
1702         ENTRY;
1703
1704         *major = GSS_S_COMPLETE;
1705
1706         if (msg->lm_bufcount < 3) {
1707                 CERROR("Too few segments (%u) in request\n", msg->lm_bufcount);
1708                 RETURN(-EINVAL);
1709         }
1710
1711         if (gss_check_seq_num(&gctx->gsc_seqdata, gw->gw_seq, 0)) {
1712                 CERROR("phase 0: discard replayed req: seq %u\n", gw->gw_seq);
1713                 *major = GSS_S_DUPLICATE_TOKEN;
1714                 RETURN(-EACCES);
1715         }
1716
1717         *major = gss_verify_msg(msg, gctx->gsc_mechctx);
1718         if (*major != GSS_S_COMPLETE)
1719                 RETURN(-EACCES);
1720
1721         if (gss_check_seq_num(&gctx->gsc_seqdata, gw->gw_seq, 1)) {
1722                 CERROR("phase 1+: discard replayed req: seq %u\n", gw->gw_seq);
1723                 *major = GSS_S_DUPLICATE_TOKEN;
1724                 RETURN(-EACCES);
1725         }
1726
1727         /* user descriptor */
1728         if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor)) {
1729                 if (msg->lm_bufcount < (offset + 1 + 1)) {
1730                         CERROR("no user desc included\n");
1731                         RETURN(-EINVAL);
1732                 }
1733
1734                 if (sptlrpc_unpack_user_desc(msg, offset)) {
1735                         CERROR("Mal-formed user descriptor\n");
1736                         RETURN(-EINVAL);
1737                 }
1738
1739                 req->rq_user_desc = lustre_msg_buf(msg, offset, 0);
1740                 offset++;
1741         }
1742
1743         /* check bulk cksum data */
1744         if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
1745                 if (msg->lm_bufcount < (offset + 1 + 1)) {
1746                         CERROR("no bulk checksum included\n");
1747                         RETURN(-EINVAL);
1748                 }
1749
1750                 if (bulk_sec_desc_unpack(msg, offset))
1751                         RETURN(-EINVAL);
1752         }
1753
1754         req->rq_reqmsg = lustre_msg_buf(msg, 1, 0);
1755         req->rq_reqlen = msg->lm_buflens[1];
1756         RETURN(0);
1757 }
1758
1759 static
1760 int gss_svc_unseal_request(struct ptlrpc_request *req,
1761                            struct gss_svc_ctx *gctx,
1762                            struct gss_wire_ctx *gw,
1763                            __u32 *major)
1764 {
1765         struct lustre_msg  *msg = req->rq_reqbuf;
1766         int                 msglen, offset = 1;
1767         ENTRY;
1768
1769         if (gss_check_seq_num(&gctx->gsc_seqdata, gw->gw_seq, 0)) {
1770                 CERROR("phase 0: discard replayed req: seq %u\n", gw->gw_seq);
1771                 *major = GSS_S_DUPLICATE_TOKEN;
1772                 RETURN(-EACCES);
1773         }
1774
1775         *major = gss_unseal_msg(gctx->gsc_mechctx, msg,
1776                                &msglen, req->rq_reqdata_len);
1777         if (*major != GSS_S_COMPLETE)
1778                 RETURN(-EACCES);
1779
1780         if (gss_check_seq_num(&gctx->gsc_seqdata, gw->gw_seq, 1)) {
1781                 CERROR("phase 1+: discard replayed req: seq %u\n", gw->gw_seq);
1782                 *major = GSS_S_DUPLICATE_TOKEN;
1783                 RETURN(-EACCES);
1784         }
1785
1786         if (lustre_unpack_msg(msg, msglen)) {
1787                 CERROR("Failed to unpack after decryption\n");
1788                 RETURN(-EINVAL);
1789         }
1790         req->rq_reqdata_len = msglen;
1791
1792         if (msg->lm_bufcount < 1) {
1793                 CERROR("Invalid buffer: is empty\n");
1794                 RETURN(-EINVAL);
1795         }
1796
1797         if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor)) {
1798                 if (msg->lm_bufcount < offset + 1) {
1799                         CERROR("no user descriptor included\n");
1800                         RETURN(-EINVAL);
1801                 }
1802
1803                 if (sptlrpc_unpack_user_desc(msg, offset)) {
1804                         CERROR("Mal-formed user descriptor\n");
1805                         RETURN(-EINVAL);
1806                 }
1807
1808                 req->rq_user_desc = lustre_msg_buf(msg, offset, 0);
1809                 offset++;
1810         }
1811
1812         if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
1813                 if (msg->lm_bufcount < offset + 1) {
1814                         CERROR("no bulk checksum included\n");
1815                         RETURN(-EINVAL);
1816                 }
1817
1818                 if (bulk_sec_desc_unpack(msg, offset))
1819                         RETURN(-EINVAL);
1820         }
1821
1822         req->rq_reqmsg = lustre_msg_buf(req->rq_reqbuf, 0, 0);
1823         req->rq_reqlen = req->rq_reqbuf->lm_buflens[0];
1824         RETURN(0);
1825 }
1826
1827 static
1828 int gss_svc_handle_data(struct ptlrpc_request *req,
1829                         struct gss_wire_ctx *gw)
1830 {
1831         struct gss_svc_reqctx *grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
1832         __u32                  major = 0;
1833         int                    rc = 0;
1834         ENTRY;
1835
1836         grctx->src_ctx = gss_svc_upcall_get_ctx(req, gw);
1837         if (!grctx->src_ctx) {
1838                 major = GSS_S_NO_CONTEXT;
1839                 goto error;
1840         }
1841
1842         switch (gw->gw_svc) {
1843         case PTLRPC_GSS_SVC_INTEGRITY:
1844                 rc = gss_svc_verify_request(req, grctx->src_ctx, gw, &major);
1845                 break;
1846         case PTLRPC_GSS_SVC_PRIVACY:
1847                 rc = gss_svc_unseal_request(req, grctx->src_ctx, gw, &major);
1848                 break;
1849         default:
1850                 CERROR("unsupported gss service %d\n", gw->gw_svc);
1851                 rc = -EINVAL;
1852         }
1853
1854         if (rc != 0)
1855                 goto error;
1856
1857         RETURN(SECSVC_OK);
1858
1859 error:
1860         CERROR("svc %u failed: major 0x%08x: ctx %p(%u->%s)\n",
1861                gw->gw_svc, major, grctx->src_ctx, grctx->src_ctx->gsc_uid,
1862                libcfs_nid2str(req->rq_peer.nid));
1863         /*
1864          * we only notify client in case of NO_CONTEXT/BAD_SIG, which
1865          * might happen after server reboot, to allow recovery.
1866          */
1867         if ((major == GSS_S_NO_CONTEXT || major == GSS_S_BAD_SIG) &&
1868             gss_pack_err_notify(req, major, 0) == 0)
1869                 RETURN(SECSVC_COMPLETE);
1870
1871         RETURN(SECSVC_DROP);
1872 }
1873
1874 static
1875 int gss_svc_handle_destroy(struct ptlrpc_request *req,
1876                            struct gss_wire_ctx *gw)
1877 {
1878         struct gss_svc_reqctx  *grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
1879         int                     replen = sizeof(struct ptlrpc_body);
1880         __u32                   major;
1881         ENTRY;
1882
1883         grctx->src_ctx = gss_svc_upcall_get_ctx(req, gw);
1884         if (!grctx->src_ctx) {
1885                 CWARN("invalid gss context handle for destroy.\n");
1886                 RETURN(SECSVC_DROP);
1887         }
1888
1889         if (gw->gw_svc != PTLRPC_GSS_SVC_INTEGRITY) {
1890                 CERROR("svc %u is not supported in destroy.\n", gw->gw_svc);
1891                 RETURN(SECSVC_DROP);
1892         }
1893
1894         if (gss_svc_verify_request(req, grctx->src_ctx, gw, &major))
1895                 RETURN(SECSVC_DROP);
1896
1897         if (lustre_pack_reply_v2(req, 1, &replen, NULL))
1898                 RETURN(SECSVC_DROP);
1899
1900         CWARN("gss svc destroy ctx %p(%u->%s)\n", grctx->src_ctx,
1901               grctx->src_ctx->gsc_uid, libcfs_nid2str(req->rq_peer.nid));
1902
1903         gss_svc_upcall_destroy_ctx(grctx->src_ctx);
1904
1905         if (SEC_FLAVOR_HAS_USER(req->rq_sec_flavor)) {
1906                 if (req->rq_reqbuf->lm_bufcount < 4) {
1907                         CERROR("missing user descriptor, ignore it\n");
1908                         RETURN(SECSVC_OK);
1909                 }
1910                 if (sptlrpc_unpack_user_desc(req->rq_reqbuf, 2)) {
1911                         CERROR("Mal-formed user descriptor, ignore it\n");
1912                         RETURN(SECSVC_OK);
1913                 }
1914                 req->rq_user_desc = lustre_msg_buf(req->rq_reqbuf, 2, 0);
1915         }
1916
1917         RETURN(SECSVC_OK);
1918 }
1919
1920 static
1921 int gss_svc_accept(struct ptlrpc_request *req)
1922 {
1923         struct gss_header      *ghdr;
1924         struct gss_svc_reqctx  *grctx;
1925         struct gss_wire_ctx    *gw;
1926         int                     rc;
1927         ENTRY;
1928
1929         LASSERT(req->rq_reqbuf);
1930         LASSERT(req->rq_svc_ctx == NULL);
1931
1932         if (req->rq_reqbuf->lm_bufcount < 2) {
1933                 CERROR("buf count only %d\n", req->rq_reqbuf->lm_bufcount);
1934                 RETURN(SECSVC_DROP);
1935         }
1936
1937         ghdr = gss_swab_header(req->rq_reqbuf, 0);
1938         if (ghdr == NULL) {
1939                 CERROR("can't decode gss header\n");
1940                 RETURN(SECSVC_DROP);
1941         }
1942
1943         /* sanity checks */
1944         if (ghdr->gh_version != PTLRPC_GSS_VERSION) {
1945                 CERROR("gss version %u, expect %u\n", ghdr->gh_version,
1946                        PTLRPC_GSS_VERSION);
1947                 RETURN(SECSVC_DROP);
1948         }
1949
1950         /* alloc grctx data */
1951         OBD_ALLOC_PTR(grctx);
1952         if (!grctx) {
1953                 CERROR("fail to alloc svc reqctx\n");
1954                 RETURN(SECSVC_DROP);
1955         }
1956         grctx->src_base.sc_policy = sptlrpc_policy_get(&gss_policy);
1957         atomic_set(&grctx->src_base.sc_refcount, 1);
1958         req->rq_svc_ctx = &grctx->src_base;
1959         gw = &grctx->src_wirectx;
1960
1961         /* save wire context */
1962         gw->gw_proc = ghdr->gh_proc;
1963         gw->gw_seq = ghdr->gh_seq;
1964         gw->gw_svc = ghdr->gh_svc;
1965         rawobj_from_netobj(&gw->gw_handle, &ghdr->gh_handle);
1966
1967         /* keep original wire header which subject to checksum verification */
1968         if (lustre_msg_swabbed(req->rq_reqbuf))
1969                 gss_header_swabber(ghdr);
1970
1971         switch(ghdr->gh_proc) {
1972         case PTLRPC_GSS_PROC_INIT:
1973         case PTLRPC_GSS_PROC_CONTINUE_INIT:
1974                 rc = gss_svc_handle_init(req, gw);
1975                 break;
1976         case PTLRPC_GSS_PROC_DATA:
1977                 rc = gss_svc_handle_data(req, gw);
1978                 break;
1979         case PTLRPC_GSS_PROC_DESTROY:
1980                 rc = gss_svc_handle_destroy(req, gw);
1981                 break;
1982         default:
1983                 CERROR("unknown proc %u\n", gw->gw_proc);
1984                 rc = SECSVC_DROP;
1985                 break;
1986         }
1987
1988         switch (rc) {
1989         case SECSVC_OK:
1990                 LASSERT (grctx->src_ctx);
1991
1992                 req->rq_auth_gss = 1;
1993                 req->rq_auth_remote = grctx->src_ctx->gsc_remote;
1994                 req->rq_auth_usr_mdt = grctx->src_ctx->gsc_usr_mds;
1995                 req->rq_auth_usr_root = grctx->src_ctx->gsc_usr_root;
1996                 req->rq_auth_uid = grctx->src_ctx->gsc_uid;
1997                 req->rq_auth_mapped_uid = grctx->src_ctx->gsc_mapped_uid;
1998                 break;
1999         case SECSVC_COMPLETE:
2000                 break;
2001         case SECSVC_DROP:
2002                 gss_svc_reqctx_free(grctx);
2003                 req->rq_svc_ctx = NULL;
2004                 break;
2005         }
2006
2007         RETURN(rc);
2008 }
2009
2010 static inline
2011 int gss_svc_payload(struct gss_svc_reqctx *grctx, int msgsize, int privacy)
2012 {
2013         if (gss_svc_reqctx_is_special(grctx))
2014                 return grctx->src_reserve_len;
2015
2016         return gss_estimate_payload(NULL, msgsize, privacy);
2017 }
2018
2019 static
2020 int gss_svc_alloc_rs(struct ptlrpc_request *req, int msglen)
2021 {
2022         struct gss_svc_reqctx       *grctx;
2023         struct ptlrpc_reply_state   *rs;
2024         struct ptlrpc_bulk_sec_desc *bsd;
2025         int                          privacy;
2026         int                          ibuflens[2], ibufcnt = 0;
2027         int                          buflens[4], bufcnt;
2028         int                          txtsize, wmsg_size, rs_size;
2029         ENTRY;
2030
2031         LASSERT(msglen % 8 == 0);
2032
2033         if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor) &&
2034             !req->rq_bulk_read && !req->rq_bulk_write) {
2035                 CERROR("client request bulk sec on non-bulk rpc\n");
2036                 RETURN(-EPROTO);
2037         }
2038
2039         grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
2040         if (gss_svc_reqctx_is_special(grctx))
2041                 privacy = 0;
2042         else
2043                 privacy = (SEC_FLAVOR_SVC(req->rq_sec_flavor) ==
2044                            SPTLRPC_SVC_PRIV);
2045
2046         if (privacy) {
2047                 /* Inner buffer */
2048                 ibufcnt = 1;
2049                 ibuflens[0] = msglen;
2050
2051                 if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
2052                         LASSERT(req->rq_reqbuf->lm_bufcount >= 2);
2053                         bsd = lustre_msg_buf(req->rq_reqbuf,
2054                                              req->rq_reqbuf->lm_bufcount - 1,
2055                                              sizeof(*bsd));
2056
2057                         ibuflens[ibufcnt++] = bulk_sec_desc_size(
2058                                                         bsd->bsd_csum_alg, 0,
2059                                                         req->rq_bulk_read);
2060                 }
2061
2062                 txtsize = lustre_msg_size_v2(ibufcnt, ibuflens);
2063                 txtsize += GSS_MAX_CIPHER_BLOCK;
2064
2065                 /* wrapper buffer */
2066                 bufcnt = 3;
2067                 buflens[0] = PTLRPC_GSS_HEADER_SIZE;
2068                 buflens[1] = gss_svc_payload(grctx, buflens[0], 0);
2069                 buflens[2] = gss_svc_payload(grctx, txtsize, 1);
2070         } else {
2071                 bufcnt = 2;
2072                 buflens[0] = PTLRPC_GSS_HEADER_SIZE;
2073                 buflens[1] = msglen;
2074                 txtsize = buflens[0] + buflens[1];
2075
2076                 if (SEC_FLAVOR_HAS_BULK(req->rq_sec_flavor)) {
2077                         LASSERT(req->rq_reqbuf->lm_bufcount >= 4);
2078                         bsd = lustre_msg_buf(req->rq_reqbuf,
2079                                              req->rq_reqbuf->lm_bufcount - 2,
2080                                              sizeof(*bsd));
2081
2082                         buflens[bufcnt] = bulk_sec_desc_size(
2083                                                         bsd->bsd_csum_alg, 0,
2084                                                         req->rq_bulk_read);
2085                         txtsize += buflens[bufcnt];
2086                         bufcnt++;
2087                 }
2088                 buflens[bufcnt++] = gss_svc_payload(grctx, txtsize, 0);
2089         }
2090
2091         wmsg_size = lustre_msg_size_v2(bufcnt, buflens);
2092
2093         rs_size = sizeof(*rs) + wmsg_size;
2094         rs = req->rq_reply_state;
2095
2096         if (rs) {
2097                 /* pre-allocated */
2098                 LASSERT(rs->rs_size >= rs_size);
2099         } else {
2100                 OBD_ALLOC(rs, rs_size);
2101                 if (rs == NULL)
2102                         RETURN(-ENOMEM);
2103
2104                 rs->rs_size = rs_size;
2105         }
2106
2107         rs->rs_repbuf = (struct lustre_msg *) (rs + 1);
2108         rs->rs_repbuf_len = wmsg_size;
2109
2110         if (privacy) {
2111                 lustre_init_msg_v2(rs->rs_repbuf, ibufcnt, ibuflens, NULL);
2112                 rs->rs_msg = lustre_msg_buf(rs->rs_repbuf, 0, msglen);
2113         } else {
2114                 lustre_init_msg_v2(rs->rs_repbuf, bufcnt, buflens, NULL);
2115                 rs->rs_repbuf->lm_secflvr = req->rq_sec_flavor;
2116
2117                 rs->rs_msg = (struct lustre_msg *)
2118                                 lustre_msg_buf(rs->rs_repbuf, 1, 0);
2119         }
2120
2121         gss_svc_reqctx_addref(grctx);
2122         rs->rs_svc_ctx = req->rq_svc_ctx;
2123
2124         LASSERT(rs->rs_msg);
2125         req->rq_reply_state = rs;
2126         RETURN(0);
2127 }
2128
2129 static
2130 int gss_svc_seal(struct ptlrpc_request *req,
2131                  struct ptlrpc_reply_state *rs,
2132                  struct gss_svc_reqctx *grctx)
2133 {
2134         struct gss_svc_ctx      *gctx = grctx->src_ctx;
2135         rawobj_t                 msgobj, cipher_obj, micobj;
2136         struct gss_header       *ghdr;
2137         __u8                    *cipher_buf;
2138         int                      cipher_buflen, buflens[3];
2139         int                      msglen, rc;
2140         __u32                    major;
2141         ENTRY;
2142
2143         /* embedded lustre_msg might have been shrinked */
2144         if (req->rq_replen != rs->rs_repbuf->lm_buflens[0])
2145                 lustre_shrink_msg(rs->rs_repbuf, 0, req->rq_replen, 1);
2146
2147         /* clear data length */
2148         msglen = lustre_msg_size_v2(rs->rs_repbuf->lm_bufcount,
2149                                     rs->rs_repbuf->lm_buflens);
2150
2151         /* clear text */
2152         msgobj.len = msglen;
2153         msgobj.data = (__u8 *) rs->rs_repbuf;
2154
2155         /* allocate temporary cipher buffer */
2156         cipher_buflen = gss_estimate_payload(gctx->gsc_mechctx, msglen, 1);
2157         OBD_ALLOC(cipher_buf, cipher_buflen);
2158         if (!cipher_buf)
2159                 RETURN(-ENOMEM);
2160
2161         cipher_obj.len = cipher_buflen;
2162         cipher_obj.data = cipher_buf;
2163
2164         major = lgss_wrap(gctx->gsc_mechctx, &msgobj, rs->rs_repbuf_len,
2165                           &cipher_obj);
2166         if (major != GSS_S_COMPLETE) {
2167                 CERROR("priv: wrap message error: %08x\n", major);
2168                 GOTO(out_free, rc = -EPERM);
2169         }
2170         LASSERT(cipher_obj.len <= cipher_buflen);
2171
2172         /* now the real wire data */
2173         buflens[0] = PTLRPC_GSS_HEADER_SIZE;
2174         buflens[1] = gss_estimate_payload(gctx->gsc_mechctx, buflens[0], 0);
2175         buflens[2] = cipher_obj.len;
2176
2177         LASSERT(lustre_msg_size_v2(3, buflens) <= rs->rs_repbuf_len);
2178         lustre_init_msg_v2(rs->rs_repbuf, 3, buflens, NULL);
2179         rs->rs_repbuf->lm_secflvr = req->rq_sec_flavor;
2180
2181         /* gss header */
2182         ghdr = lustre_msg_buf(rs->rs_repbuf, 0, 0);
2183         ghdr->gh_version = PTLRPC_GSS_VERSION;
2184         ghdr->gh_flags = 0;
2185         ghdr->gh_proc = PTLRPC_GSS_PROC_DATA;
2186         ghdr->gh_seq = grctx->src_wirectx.gw_seq;
2187         ghdr->gh_svc = PTLRPC_GSS_SVC_PRIVACY;
2188         ghdr->gh_handle.len = 0;
2189
2190         /* header signature */
2191         msgobj.len = rs->rs_repbuf->lm_buflens[0];
2192         msgobj.data = lustre_msg_buf(rs->rs_repbuf, 0, 0);
2193         micobj.len = rs->rs_repbuf->lm_buflens[1];
2194         micobj.data = lustre_msg_buf(rs->rs_repbuf, 1, 0);
2195
2196         major = lgss_get_mic(gctx->gsc_mechctx, 1, &msgobj, &micobj);
2197         if (major != GSS_S_COMPLETE) {
2198                 CERROR("priv: sign message error: %08x\n", major);
2199                 GOTO(out_free, rc = -EPERM);
2200         }
2201         lustre_shrink_msg(rs->rs_repbuf, 1, micobj.len, 0);
2202
2203         /* cipher token */
2204         memcpy(lustre_msg_buf(rs->rs_repbuf, 2, 0),
2205                cipher_obj.data, cipher_obj.len);
2206
2207         rs->rs_repdata_len = lustre_shrink_msg(rs->rs_repbuf, 2,
2208                                                cipher_obj.len, 0);
2209
2210         /* to catch upper layer's further access */
2211         rs->rs_msg = NULL;
2212         req->rq_repmsg = NULL;
2213         req->rq_replen = 0;
2214
2215         rc = 0;
2216 out_free:
2217         OBD_FREE(cipher_buf, cipher_buflen);
2218         RETURN(rc);
2219 }
2220
2221 int gss_svc_authorize(struct ptlrpc_request *req)
2222 {
2223         struct ptlrpc_reply_state *rs = req->rq_reply_state;
2224         struct gss_svc_reqctx     *grctx = gss_svc_ctx2reqctx(req->rq_svc_ctx);
2225         struct gss_wire_ctx       *gw;
2226         int                        rc;
2227         ENTRY;
2228
2229         if (gss_svc_reqctx_is_special(grctx))
2230                 RETURN(0);
2231
2232         gw = &grctx->src_wirectx;
2233         if (gw->gw_proc != PTLRPC_GSS_PROC_DATA &&
2234             gw->gw_proc != PTLRPC_GSS_PROC_DESTROY) {
2235                 CERROR("proc %d not support\n", gw->gw_proc);
2236                 RETURN(-EINVAL);
2237         }
2238
2239         LASSERT(grctx->src_ctx);
2240
2241         switch (gw->gw_svc) {
2242         case  PTLRPC_GSS_SVC_INTEGRITY:
2243                 rc = gss_svc_sign(req, rs, grctx);
2244                 break;
2245         case  PTLRPC_GSS_SVC_PRIVACY:
2246                 rc = gss_svc_seal(req, rs, grctx);
2247                 break;
2248         default:
2249                 CERROR("Unknown service %d\n", gw->gw_svc);
2250                 GOTO(out, rc = -EINVAL);
2251         }
2252         rc = 0;
2253
2254 out:
2255         RETURN(rc);
2256 }
2257
2258 static
2259 void gss_svc_free_rs(struct ptlrpc_reply_state *rs)
2260 {
2261         struct gss_svc_reqctx *grctx;
2262
2263         LASSERT(rs->rs_svc_ctx);
2264         grctx = container_of(rs->rs_svc_ctx, struct gss_svc_reqctx, src_base);
2265
2266         gss_svc_reqctx_decref(grctx);
2267         rs->rs_svc_ctx = NULL;
2268
2269         if (!rs->rs_prealloc)
2270                 OBD_FREE(rs, rs->rs_size);
2271 }
2272
2273 static
2274 void gss_svc_free_ctx(struct ptlrpc_svc_ctx *ctx)
2275 {
2276         LASSERT(atomic_read(&ctx->sc_refcount) == 0);
2277         gss_svc_reqctx_free(gss_svc_ctx2reqctx(ctx));
2278 }
2279
2280 static
2281 int gss_svc_install_rctx(struct obd_import *imp, struct ptlrpc_svc_ctx *ctx)
2282 {
2283         struct gss_sec *gsec;
2284
2285         LASSERT(imp->imp_sec);
2286         LASSERT(ctx);
2287
2288         gsec = container_of(imp->imp_sec, struct gss_sec, gs_base);
2289         return gss_install_rvs_cli_ctx(gsec, ctx);
2290 }
2291
2292 static struct ptlrpc_sec_sops gss_sec_sops = {
2293         .accept                 = gss_svc_accept,
2294         .alloc_rs               = gss_svc_alloc_rs,
2295         .authorize              = gss_svc_authorize,
2296         .free_rs                = gss_svc_free_rs,
2297         .free_ctx               = gss_svc_free_ctx,
2298         .unwrap_bulk            = gss_svc_unwrap_bulk,
2299         .wrap_bulk              = gss_svc_wrap_bulk,
2300         .install_rctx           = gss_svc_install_rctx,
2301 };
2302
2303 static struct ptlrpc_sec_policy gss_policy = {
2304         .sp_owner               = THIS_MODULE,
2305         .sp_name                = "sec.gss",
2306         .sp_policy              = SPTLRPC_POLICY_GSS,
2307         .sp_cops                = &gss_sec_cops,
2308         .sp_sops                = &gss_sec_sops,
2309 };
2310
2311 int __init sptlrpc_gss_init(void)
2312 {
2313         int rc;
2314
2315         rc = sptlrpc_register_policy(&gss_policy);
2316         if (rc)
2317                 return rc;
2318
2319         rc = gss_init_lproc();
2320         if (rc)
2321                 goto out_type;
2322
2323         rc = gss_init_upcall();
2324         if (rc)
2325                 goto out_lproc;
2326
2327         rc = init_kerberos_module();
2328         if (rc)
2329                 goto out_upcall;
2330
2331         return 0;
2332 out_upcall:
2333         gss_exit_upcall();
2334 out_lproc:
2335         gss_exit_lproc();
2336 out_type:
2337         sptlrpc_unregister_policy(&gss_policy);
2338         return rc;
2339 }
2340
2341 static void __exit sptlrpc_gss_exit(void)
2342 {
2343         cleanup_kerberos_module();
2344         gss_exit_upcall();
2345         gss_exit_lproc();
2346         sptlrpc_unregister_policy(&gss_policy);
2347 }
2348
2349 MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
2350 MODULE_DESCRIPTION("GSS security policy for Lustre");
2351 MODULE_LICENSE("GPL");
2352
2353 module_init(sptlrpc_gss_init);
2354 module_exit(sptlrpc_gss_exit);