Whamcloud - gitweb
2056753bbce7fb8df8440836900c1a9891747b64
[fs/lustre-release.git] / lustre / include / linux / lustre_sec.h
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  * Copyright (C) 2004 Cluster File Systems, Inc.
5  *
6  *   This file is part of Lustre, http://www.lustre.org.
7  *
8  *   Lustre is free software; you can redistribute it and/or
9  *   modify it under the terms of version 2 of the GNU General Public
10  *   License as published by the Free Software Foundation.
11  *
12  *   Lustre is distributed in the hope that it will be useful,
13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *   GNU General Public License for more details.
16  *
17  *   You should have received a copy of the GNU General Public License
18  *   along with Lustre; if not, write to the Free Software
19  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */
21
22 #ifndef __LINUX_SEC_H_
23 #define __LINUX_SEC_H_
24
25 enum ptlrpcs_major_flavors {
26         PTLRPCS_FLVR_MAJOR_NULL         = 0,
27         PTLRPCS_FLVR_MAJOR_GSS          = 1,
28         PTLRPCS_FLVR_MAJOR_MAX,
29 };
30
31 enum ptlrpcs_null_minor_flavors {
32         PTLRPCS_FLVR_MINOR_NULL         = 0,
33         PTLRPCS_FLVR_MINOR_NULL_MAX,
34 };
35 enum ptlrpcs_gss_minor_flavors {
36         PTLRPCS_FLVR_MINOR_GSS_NONE     = 0,
37         PTLRPCS_FLVR_MINOR_GSS_KRB5     = 1,
38         PTLRPCS_FLVR_MINOR_GSS_MAX,
39 };
40
41 enum ptlrpcs_security_type {
42         PTLRPCS_SVC_NONE                = 0,    /* no security */
43         PTLRPCS_SVC_AUTH                = 1,    /* authentication */
44         PTLRPCS_SVC_PRIV                = 2,    /* privacy */
45         PTLRPCS_SVC_MAX,
46 };
47
48 /*
49  * flavor compose/extract
50  */
51 #define SEC_FLAVOR_MAJOR_OFFSET         (24)
52 #define SEC_FLAVOR_RESERVE_OFFSET       (16)
53 #define SEC_FLAVOR_SVC_OFFSET           (8)
54 #define SEC_FLAVOR_MINOR_OFFSET         (0)
55
56 #define SEC_MAKE_FLAVOR(major, minor, svc)                      \
57         (((__u32)(major) << SEC_FLAVOR_MAJOR_OFFSET) |          \
58          ((__u32)(svc) << SEC_FLAVOR_SVC_OFFSET) |              \
59          ((__u32)(minor) << SEC_FLAVOR_MINOR_OFFSET))
60
61 #define SEC_MAKE_SUBFLAVOR(minor, svc)                          \
62         (((__u32)(svc) << SEC_FLAVOR_SVC_OFFSET) |              \
63          ((__u32)(minor) << SEC_FLAVOR_MINOR_OFFSET))
64
65 #define SEC_FLAVOR_MAJOR(flavor)                                        \
66         ((((__u32)(flavor)) >> SEC_FLAVOR_MAJOR_OFFSET) & 0xFF)
67 #define SEC_FLAVOR_MINOR(flavor)                                        \
68         ((((__u32)(flavor)) >> SEC_FLAVOR_MINOR_OFFSET) & 0xFF)
69 #define SEC_FLAVOR_SVC(flavor)                                          \
70         ((((__u32)(flavor)) >> SEC_FLAVOR_SVC_OFFSET) & 0xFF)
71 #define SEC_FLAVOR_SUB(flavor)                                          \
72         ((((__u32)(flavor)) >> SEC_FLAVOR_MINOR_OFFSET) & 0xFFFF)
73
74 /*
75  * general gss flavors
76  */
77 #define PTLRPCS_FLVR_GSS_NONE                           \
78         SEC_MAKE_FLAVOR(PTLRPCS_FLVR_MAJOR_GSS,         \
79                         PTLRPCS_FLVR_MINOR_GSS_NONE,    \
80                         PTLRPCS_SVC_NONE)
81 #define PTLRPCS_FLVR_GSS_AUTH                           \
82         SEC_MAKE_FLAVOR(PTLRPCS_FLVR_MAJOR_GSS,         \
83                         PTLRPCS_FLVR_MINOR_GSS_NONE,    \
84                         PTLRPCS_SVC_AUTH)
85 #define PTLRPCS_FLVR_GSS_PRIV                           \
86         SEC_MAKE_FLAVOR(PTLRPCS_FLVR_MAJOR_GSS,         \
87                         PTLRPCS_FLVR_MINOR_GSS_NONE,    \
88                         PTLRPCS_SVC_PRIV)
89
90 /*
91  * gss subflavors
92  */
93 #define PTLRPCS_SUBFLVR_KRB5                            \
94         SEC_MAKE_SUBFLAVOR(PTLRPCS_FLVR_MINOR_GSS_KRB5, \
95                            PTLRPCS_SVC_NONE)
96 #define PTLRPCS_SUBFLVR_KRB5I                           \
97         SEC_MAKE_SUBFLAVOR(PTLRPCS_FLVR_MINOR_GSS_KRB5, \
98                            PTLRPCS_SVC_AUTH)
99 #define PTLRPCS_SUBFLVR_KRB5P                           \
100         SEC_MAKE_SUBFLAVOR(PTLRPCS_FLVR_MINOR_GSS_KRB5, \
101                            PTLRPCS_SVC_PRIV)
102
103 /*
104  * "end user" flavors
105  */
106 #define PTLRPCS_FLVR_NULL                               \
107         SEC_MAKE_FLAVOR(PTLRPCS_FLVR_MAJOR_NULL,        \
108                         PTLRPCS_FLVR_MINOR_NULL,        \
109                         PTLRPCS_SVC_NONE)
110 #define PTLRPCS_FLVR_KRB5                               \
111         SEC_MAKE_FLAVOR(PTLRPCS_FLVR_MAJOR_GSS,         \
112                         PTLRPCS_FLVR_MINOR_GSS_KRB5,    \
113                         PTLRPCS_SVC_NONE)
114 #define PTLRPCS_FLVR_KRB5I                              \
115         SEC_MAKE_FLAVOR(PTLRPCS_FLVR_MAJOR_GSS,         \
116                         PTLRPCS_FLVR_MINOR_GSS_KRB5,    \
117                         PTLRPCS_SVC_AUTH)
118 #define PTLRPCS_FLVR_KRB5P                              \
119         SEC_MAKE_FLAVOR(PTLRPCS_FLVR_MAJOR_GSS,         \
120                         PTLRPCS_FLVR_MINOR_GSS_KRB5,    \
121                         PTLRPCS_SVC_PRIV)
122
123 #define PTLRPCS_FLVR_INVALID    (-1)
124
125 __u32 ptlrpcs_name2flavor(const char *name);
126 char *ptlrpcs_flavor2name(__u32 flavor);
127
128
129 #ifdef __KERNEL__
130
131 /* forward declaration */
132 struct obd_import;
133 struct ptlrpc_request;
134 struct ptlrpc_cred;
135 struct ptlrpc_credops;
136 struct ptlrpc_sec;
137 struct ptlrpc_secops;
138
139
140 typedef struct {
141         struct list_head        list;
142         __u32                   flavor;
143 } deny_sec_t;
144
145 /*
146  * This header is prepended at any on-wire ptlrpc packets
147  */
148 struct ptlrpcs_wire_hdr {
149         __u32   flavor;
150         __u32   unused;
151         __u32   msg_len;
152         __u32   sec_len;
153 };
154
155 static inline
156 struct ptlrpcs_wire_hdr *buf_to_sec_hdr(void *buf)
157 {
158         return (struct ptlrpcs_wire_hdr *) buf;
159 }
160
161 static inline
162 struct lustre_msg *buf_to_lustre_msg(void *buf)
163 {
164         return (struct lustre_msg *)
165                ((char *) buf + sizeof(struct ptlrpcs_wire_hdr));
166 }
167
168 static inline
169 __u8 *buf_to_sec_data(void *buf)
170 {
171         struct ptlrpcs_wire_hdr *hdr = buf_to_sec_hdr(buf);
172         return (__u8 *) (buf + sizeof(*hdr) + hdr->msg_len);
173 }
174
175 #define PTLRPC_SEC_GSS_VERSION (1)
176
177 enum ptlrpcs_gss_proc {
178         PTLRPCS_GSS_PROC_DATA           = 0,
179         PTLRPCS_GSS_PROC_INIT           = 1,
180         PTLRPCS_GSS_PROC_CONTINUE_INIT  = 2,
181         PTLRPCS_GSS_PROC_DESTROY        = 3,
182         PTLRPCS_GSS_PROC_ERR            = 4,
183 };
184                                                                                                                         
185 enum ptlrpcs_gss_svc {
186         PTLRPCS_GSS_SVC_NONE            = 1,
187         PTLRPCS_GSS_SVC_INTEGRITY       = 2,
188         PTLRPCS_GSS_SVC_PRIVACY         = 3,
189 };
190
191 enum ptlrpcs_error {
192         PTLRPCS_OK                      = 0,
193         PTLRPCS_BADCRED                 = 1,
194         PTLRPCS_REJECTEDCRED            = 2,
195         PTLRPCS_BADVERF                 = 3,
196         PTLRPCS_REJECTEDVERF            = 4,
197         PTLRPCS_TOOWEAK                 = 5,
198         /* GSS errors */
199         PTLRPCS_GSS_CREDPROBLEM         = 13,
200         PTLRPCS_GSS_CTXPROBLEM          = 14,
201 };
202
203 struct vfs_cred {
204         __u64                   vc_pag;
205         uid_t                   vc_uid;
206         gid_t                   vc_gid;
207         struct group_info      *vc_ginfo;
208 };
209
210 struct ptlrpc_credops {
211         int     (*match)  (struct ptlrpc_cred *cred, struct vfs_cred *vcred);
212         int     (*refresh)(struct ptlrpc_cred *cred);
213         void    (*destroy)(struct ptlrpc_cred *cred);
214         int     (*sign)   (struct ptlrpc_cred *cred,
215                            struct ptlrpc_request *req);
216         int     (*verify) (struct ptlrpc_cred *cred,
217                            struct ptlrpc_request *req);
218         int     (*seal)   (struct ptlrpc_cred *cred,
219                            struct ptlrpc_request *req);
220         int     (*unseal) (struct ptlrpc_cred *cred,
221                            struct ptlrpc_request *req);
222 };
223
224 #define PTLRPC_CRED_UPTODATE_BIT        0 /* uptodate */
225 #define PTLRPC_CRED_DEAD_BIT            1 /* mark expired gracefully */
226 #define PTLRPC_CRED_ERROR_BIT           2 /* fatal error (refresh, etc.) */
227
228 #define PTLRPC_CRED_UPTODATE            (1 << PTLRPC_CRED_UPTODATE_BIT)
229 #define PTLRPC_CRED_DEAD                (1 << PTLRPC_CRED_DEAD_BIT)
230 #define PTLRPC_CRED_ERROR               (1 << PTLRPC_CRED_ERROR_BIT)
231
232 #define PTLRPC_CRED_FLAGS_MASK          (PTLRPC_CRED_UPTODATE |         \
233                                          PTLRPC_CRED_DEAD |             \
234                                          PTLRPC_CRED_ERROR)
235
236 struct ptlrpc_cred {
237         struct list_head        pc_hash;   /* linked into hash table */
238         atomic_t                pc_refcount;
239         struct ptlrpc_sec      *pc_sec;
240         struct ptlrpc_credops  *pc_ops;
241         unsigned long           pc_expire;
242         unsigned long           pc_flags;
243         /* XXX maybe should not be here */
244         __u64                   pc_pag;
245         uid_t                   pc_uid;
246 };
247
248 struct ptlrpc_secops {
249         struct ptlrpc_sec *   (*create_sec)    (__u32 flavor,
250                                                 const char *pipe_dir,
251                                                 void *pipe_data);
252         void                  (*destroy_sec)   (struct ptlrpc_sec *sec);
253         struct ptlrpc_cred *  (*create_cred)   (struct ptlrpc_sec *sec,
254                                                 struct vfs_cred *vcred);
255         /* buffer manipulation */
256         int                   (*alloc_reqbuf)  (struct ptlrpc_sec *sec,
257                                                 struct ptlrpc_request *req,
258                                                 int lustre_msg_size);
259         int                   (*alloc_repbuf)  (struct ptlrpc_sec *sec,
260                                                 struct ptlrpc_request *req,
261                                                 int lustre_msg_size);
262         void                  (*free_reqbuf)   (struct ptlrpc_sec *sec,
263                                                 struct ptlrpc_request *req);
264         void                  (*free_repbuf)   (struct ptlrpc_sec *sec,
265                                                 struct ptlrpc_request *req);
266         /* security payload size estimation */
267         int                   (*est_req_payload)(struct ptlrpc_sec *sec,
268                                                  struct ptlrpc_request *req,
269                                                  int msgsize);
270         int                   (*est_rep_payload)(struct ptlrpc_sec *sec,
271                                                  struct ptlrpc_request *req,
272                                                  int msgsize);
273 };
274
275 struct ptlrpc_sec_type {
276         struct module          *pst_owner;
277         char                   *pst_name;
278         atomic_t                pst_inst;       /* instance, debug only */
279         __u32                   pst_flavor;     /* major flavor */
280         struct ptlrpc_secops   *pst_ops;
281 };
282
283 #define PTLRPC_SEC_FL_MDS               0x0001 /* outgoing from MDS */
284 #define PTLRPC_SEC_FL_REVERSE           0x0002 /* reverse sec */
285 #define PTLRPC_SEC_FL_PAG               0x0004 /* enable PAG */
286
287 #define PTLRPC_CREDCACHE_NR     8
288 #define PTLRPC_CREDCACHE_MASK   (PTLRPC_CREDCACHE_NR - 1)
289
290 struct ptlrpc_sec {
291         struct ptlrpc_sec_type *ps_type;
292         struct list_head        ps_credcache[PTLRPC_CREDCACHE_NR];
293         spinlock_t              ps_lock;        /* protect cred cache */
294         __u32                   ps_flavor;
295         atomic_t                ps_refcount;
296         atomic_t                ps_credcount;
297         struct obd_import      *ps_import;
298         /* actual security model need initialize following fields */
299         unsigned long           ps_expire;      /* cache expire interval */
300         unsigned long           ps_nextgc;      /* next gc time */
301         unsigned long           ps_flags;
302 };
303
304 /* sec.c */
305 int  ptlrpcs_register(struct ptlrpc_sec_type *type);
306 int  ptlrpcs_unregister(struct ptlrpc_sec_type *type);
307
308 struct ptlrpc_sec * ptlrpcs_sec_create(__u32 flavor,
309                                        unsigned long flags,
310                                        struct obd_import *import,
311                                        const char *pipe_dir,
312                                        void *pipe_data);
313 void ptlrpcs_sec_put(struct ptlrpc_sec *sec);
314 void ptlrpcs_sec_invalidate_cache(struct ptlrpc_sec *sec);
315
316 struct ptlrpc_cred * ptlrpcs_cred_lookup(struct ptlrpc_sec *sec,
317                                          struct vfs_cred *vcred);
318 void ptlrpcs_cred_put(struct ptlrpc_cred *cred, int sync);
319
320 static inline void ptlrpcs_cred_get(struct ptlrpc_cred *cred)
321 {
322         LASSERT(atomic_read(&cred->pc_refcount));
323         atomic_inc(&cred->pc_refcount);
324 }
325
326 static inline int ptlrpcs_cred_refresh(struct ptlrpc_cred *cred)
327 {
328         LASSERT(cred);
329         LASSERT(atomic_read(&cred->pc_refcount));
330         LASSERT(cred->pc_ops);
331         LASSERT(cred->pc_ops->refresh);
332         return cred->pc_ops->refresh(cred);
333 }
334
335 static inline int ptlrpcs_cred_is_uptodate(struct ptlrpc_cred *cred)
336 {
337         smp_mb();
338         return ((cred->pc_flags & PTLRPC_CRED_FLAGS_MASK) ==
339                 PTLRPC_CRED_UPTODATE);
340 }
341
342 static inline int ptlrpcs_cred_is_dead(struct ptlrpc_cred *cred)
343 {
344         smp_mb();
345         return ((cred->pc_flags & (PTLRPC_CRED_DEAD | PTLRPC_CRED_ERROR)) != 0);
346 }
347
348 #define ptlrpcs_cred_expire(cred)                                       \
349         if (!test_and_set_bit(PTLRPC_CRED_DEAD_BIT, &cred->pc_flags)) { \
350                 CWARN("cred %p: get expired\n", cred);                  \
351                 clear_bit(PTLRPC_CRED_UPTODATE_BIT, &cred->pc_flags);   \
352         }
353
354 static inline int ptlrpcs_cred_check_uptodate(struct ptlrpc_cred *cred)
355 {
356         LASSERT(atomic_read(&cred->pc_refcount));
357
358         if (!ptlrpcs_cred_is_uptodate(cred))
359                 return 1;
360
361         if (cred->pc_expire == 0)
362                 return 0;
363         if (time_after(cred->pc_expire, get_seconds()))
364                 return 0;
365         ptlrpcs_cred_expire(cred);
366         return 1;
367 }
368
369 static inline int ptlrpcs_est_req_payload(struct ptlrpc_request *req,
370                                           int datasize)
371 {
372         struct ptlrpc_sec *sec = req->rq_cred->pc_sec;
373         struct ptlrpc_secops *ops;
374
375         LASSERT(sec);
376         LASSERT(sec->ps_type);
377         LASSERT(sec->ps_type->pst_ops);
378
379         ops = sec->ps_type->pst_ops;
380         if (ops->est_req_payload)
381                 return ops->est_req_payload(sec, req, datasize);
382         else
383                 return 0;
384 }
385
386 static inline int ptlrpcs_est_rep_payload(struct ptlrpc_request *req,
387                                           int datasize)
388 {
389         struct ptlrpc_sec *sec = req->rq_cred->pc_sec;
390         struct ptlrpc_secops *ops;
391
392         LASSERT(sec);
393         LASSERT(sec->ps_type);
394         LASSERT(sec->ps_type->pst_ops);
395
396         ops = sec->ps_type->pst_ops;
397         if (ops->est_rep_payload)
398                 return ops->est_rep_payload(sec, req, datasize);
399         else
400                 return 0;
401 }
402
403 static inline int add_deny_security(char *sec, struct list_head *head)
404 {
405         deny_sec_t     *p_deny_sec = NULL;
406         int             rc = 0;
407
408         LASSERT(sec != NULL);
409
410         OBD_ALLOC(p_deny_sec, sizeof(*p_deny_sec));
411         if (p_deny_sec == NULL)
412                 return -ENOMEM;
413
414         p_deny_sec->flavor = ptlrpcs_name2flavor(sec);
415         if (p_deny_sec->flavor == PTLRPCS_FLVR_INVALID) {
416                 CERROR("unrecognized security type %s\n", (char*) sec);
417                 rc = -EINVAL;
418                 goto out;
419         }
420
421         list_add_tail(&p_deny_sec->list, head);
422 out:
423         if (rc) {
424                 if (p_deny_sec)
425                         OBD_FREE(p_deny_sec, sizeof(*p_deny_sec));
426         }
427         return rc;
428 }
429
430 int ptlrpcs_cli_wrap_request(struct ptlrpc_request *req);
431 int ptlrpcs_cli_unwrap_reply(struct ptlrpc_request *req);
432 int ptlrpcs_cli_alloc_reqbuf(struct ptlrpc_request *req, int msgsize);
433 int ptlrpcs_cli_alloc_repbuf(struct ptlrpc_request *req, int msgsize);
434 void ptlrpcs_cli_free_reqbuf(struct ptlrpc_request *req);
435 void ptlrpcs_cli_free_repbuf(struct ptlrpc_request *req);
436
437 /* higher interface */
438 int  ptlrpcs_import_get_sec(struct obd_import *imp);
439 void ptlrpcs_import_drop_sec(struct obd_import *imp);
440 void ptlrpcs_import_flush_current_creds(struct obd_import *imp);
441 int  ptlrpcs_req_get_cred(struct ptlrpc_request *req);
442 void ptlrpcs_req_drop_cred(struct ptlrpc_request *req);
443 int  ptlrpcs_req_replace_dead_cred(struct ptlrpc_request *req);
444 int  ptlrpcs_req_refresh_cred(struct ptlrpc_request *req);
445 int ptlrpcs_check_cred(struct obd_import *imp);
446
447 /* internal helpers */
448 int sec_alloc_reqbuf(struct ptlrpc_sec *sec, struct ptlrpc_request *req,
449                      int msgsize, int secsize);
450 void sec_free_reqbuf(struct ptlrpc_sec *sec, struct ptlrpc_request *req);
451
452 /* sec_null.c */
453 int ptlrpcs_null_init(void);
454 int ptlrpcs_null_exit(void);
455
456 /**********************************************************
457  * Server side stuff
458  **********************************************************/
459
460 struct ptlrpc_reply_state;
461
462 struct ptlrpc_svcsec {
463         struct module           *pss_owner;
464         char                    *pss_name;
465         __u32                    pss_flavor;    /* major flavor */
466         int                      pss_sec_size;
467
468         int                    (*accept)      (struct ptlrpc_request *req,
469                                                enum ptlrpcs_error *res);
470         int                    (*authorize)   (struct ptlrpc_request *req);
471         int                    (*alloc_repbuf)(struct ptlrpc_svcsec *svcsec,
472                                                struct ptlrpc_request *req,
473                                                int msgsize);
474         void                   (*free_repbuf) (struct ptlrpc_svcsec *svcsec,
475                                                struct ptlrpc_reply_state *rs);
476         void                   (*cleanup_req) (struct ptlrpc_svcsec *svcsec,
477                                                struct ptlrpc_request *req);
478 };
479
480 #define SVC_OK          1
481 #define SVC_COMPLETE    2
482 #define SVC_DROP        3
483 #define SVC_LOGIN       4
484 #define SVC_LOGOUT      5
485
486 int svcsec_register(struct ptlrpc_svcsec *ss);
487 int svcsec_unregister(struct ptlrpc_svcsec *ss);
488 int svcsec_accept(struct ptlrpc_request *req, enum ptlrpcs_error *res);
489 int svcsec_authorize(struct ptlrpc_request *req);
490 int svcsec_alloc_repbuf(struct ptlrpc_svcsec *svcsec,
491                         struct ptlrpc_request *req, int msgsize);
492 void svcsec_cleanup_req(struct ptlrpc_request *req);
493
494 struct ptlrpc_svcsec * svcsec_get(struct ptlrpc_svcsec *sec);
495 void svcsec_put(struct ptlrpc_svcsec *sec);
496
497 /* internal helpers */
498 int svcsec_alloc_reply_state(struct ptlrpc_request *req,
499                              int msgsize, int secsize);
500 void svcsec_free_reply_state(struct ptlrpc_reply_state *rs);
501
502 /* svcsec_null.c */
503 int svcsec_null_init(void);
504 int svcsec_null_exit(void);
505
506 #endif /* __KERNEL__ */
507
508 #endif /* __LINUX_SEC_H_ */