Whamcloud - gitweb
- CROW-related fixes from b_hd_mdref
[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 /* forward declaration */
26 struct obd_import;
27 struct ptlrpc_request;
28 struct ptlrpc_cred;
29 struct ptlrpc_credops;
30 struct ptlrpc_sec;
31 struct ptlrpc_secops;
32
33 #define PTLRPC_SEC_MAX_FLAVORS   (4)
34
35 typedef struct ptlrpcs_flavor_s {
36         __u32   flavor;
37         __u32   subflavor;
38 } ptlrpcs_flavor_t;
39
40 typedef struct {
41         struct list_head        list;
42         ptlrpcs_flavor_t        sec;
43 } deny_sec_t;
44
45 enum ptlrpcs_security_type {
46         PTLRPC_SEC_TYPE_NONE    = 0,    /* no security */
47         PTLRPC_SEC_TYPE_AUTH    = 1,    /* authentication */
48         PTLRPC_SEC_TYPE_PRIV    = 2,    /* privacy */
49 };
50
51 /*
52  * This header is prepended at any on-wire ptlrpc packets
53  */
54 struct ptlrpcs_wire_hdr {
55         __u32   flavor;
56         __u32   sectype;
57         __u32   msg_len;
58         __u32   sec_len;
59 };
60
61 static inline
62 struct ptlrpcs_wire_hdr *buf_to_sec_hdr(void *buf)
63 {
64         return (struct ptlrpcs_wire_hdr *) buf;
65 }
66
67 static inline
68 struct lustre_msg *buf_to_lustre_msg(void *buf)
69 {
70         return (struct lustre_msg *)
71                ((char *) buf + sizeof(struct ptlrpcs_wire_hdr));
72 }
73
74 static inline
75 __u8 *buf_to_sec_data(void *buf)
76 {
77         struct ptlrpcs_wire_hdr *hdr = buf_to_sec_hdr(buf);
78         return (__u8 *) (buf + sizeof(*hdr) + hdr->msg_len);
79 }
80
81 enum ptlrpcs_flavors {
82         PTLRPC_SEC_NULL = 0,
83         PTLRPC_SEC_GSS  = 1,
84 };
85
86 #define PTLRPC_SEC_GSS_VERSION (1)
87
88 enum ptlrpcs_gss_subflavors {
89         PTLRPC_SEC_GSS_KRB5  = 0,
90         PTLRPC_SEC_GSS_KRB5I = 1,
91         PTLRPC_SEC_GSS_KRB5P = 2,
92 };
93
94 enum ptlrpcs_gss_proc {
95         PTLRPC_GSS_PROC_DATA =          0,
96         PTLRPC_GSS_PROC_INIT =          1,
97         PTLRPC_GSS_PROC_CONTINUE_INIT = 2,
98         PTLRPC_GSS_PROC_DESTROY =       3,
99         PTLRPC_GSS_PROC_ERR =           4,
100 };
101                                                                                                                         
102 enum ptlrpcs_gss_svc {
103         PTLRPC_GSS_SVC_NONE =           1,
104         PTLRPC_GSS_SVC_INTEGRITY =      2,
105         PTLRPC_GSS_SVC_PRIVACY =        3,
106 };
107
108 enum ptlrpcs_error {
109         PTLRPCS_OK =                    0,
110         PTLRPCS_BADCRED =               1,
111         PTLRPCS_REJECTEDCRED =          2,
112         PTLRPCS_BADVERF =               3,
113         PTLRPCS_REJECTEDVERF =          4,
114         PTLRPCS_TOOWEAK =               5,
115         /* GSS errors */
116         PTLRPCS_GSS_CREDPROBLEM =       13,
117         PTLRPCS_GSS_CTXPROBLEM =        14,
118 };
119
120 struct vfs_cred {
121         __u64   vc_pag;
122         uid_t   vc_uid;
123         gid_t   vc_gid;
124         struct group_info *vc_ginfo;
125 };
126
127 struct ptlrpc_credops {
128         int     (*match)  (struct ptlrpc_cred *cred, struct vfs_cred *vcred);
129         int     (*refresh)(struct ptlrpc_cred *cred);
130         void    (*destroy)(struct ptlrpc_cred *cred);
131         int     (*sign)   (struct ptlrpc_cred *cred,
132                            struct ptlrpc_request *req);
133         int     (*verify) (struct ptlrpc_cred *cred,
134                            struct ptlrpc_request *req);
135         int     (*seal)   (struct ptlrpc_cred *cred,
136                            struct ptlrpc_request *req);
137         int     (*unseal) (struct ptlrpc_cred *cred,
138                            struct ptlrpc_request *req);
139 };
140
141 #define PTLRPC_CRED_UPTODATE_BIT        0 /* uptodate */
142 #define PTLRPC_CRED_DEAD_BIT            1 /* mark expired gracefully */
143 #define PTLRPC_CRED_ERROR_BIT           2 /* fatal error (refresh, etc.) */
144
145 #define PTLRPC_CRED_UPTODATE            (1 << PTLRPC_CRED_UPTODATE_BIT)
146 #define PTLRPC_CRED_DEAD                (1 << PTLRPC_CRED_DEAD_BIT)
147 #define PTLRPC_CRED_ERROR               (1 << PTLRPC_CRED_ERROR_BIT)
148
149 #define PTLRPC_CRED_FLAGS_MASK          (PTLRPC_CRED_UPTODATE |         \
150                                          PTLRPC_CRED_DEAD |             \
151                                          PTLRPC_CRED_ERROR)
152
153 struct ptlrpc_cred {
154         struct list_head        pc_hash;   /* linked into hash table */
155         atomic_t                pc_refcount;
156         struct ptlrpc_sec      *pc_sec;
157         struct ptlrpc_credops  *pc_ops;
158         unsigned long           pc_expire;
159         unsigned long           pc_flags;
160         /* XXX maybe should not be here */
161         __u64                   pc_pag;
162         uid_t                   pc_uid;
163 };
164
165 struct ptlrpc_secops {
166         struct ptlrpc_sec *   (*create_sec)    (ptlrpcs_flavor_t *flavor,
167                                                 const char *pipe_dir,
168                                                 void *pipe_data);
169         void                  (*destroy_sec)   (struct ptlrpc_sec *sec);
170         struct ptlrpc_cred *  (*create_cred)   (struct ptlrpc_sec *sec,
171                                                 struct vfs_cred *vcred);
172         /* buffer manipulation */
173         int                   (*alloc_reqbuf)  (struct ptlrpc_sec *sec,
174                                                 struct ptlrpc_request *req,
175                                                 int lustre_msg_size);
176         int                   (*alloc_repbuf)  (struct ptlrpc_sec *sec,
177                                                 struct ptlrpc_request *req,
178                                                 int lustre_msg_size);
179         void                  (*free_reqbuf)   (struct ptlrpc_sec *sec,
180                                                 struct ptlrpc_request *req);
181         void                  (*free_repbuf)   (struct ptlrpc_sec *sec,
182                                                 struct ptlrpc_request *req);
183         /* security payload size estimation */
184         int                   (*est_req_payload)(struct ptlrpc_sec *sec,
185                                                  int msgsize);
186         int                   (*est_rep_payload)(struct ptlrpc_sec *sec,
187                                                  int msgsize);
188 };
189
190 struct ptlrpc_sec_type {
191         struct module          *pst_owner;
192         char                   *pst_name;
193         atomic_t                pst_inst;       /* instance, debug only */
194         ptlrpcs_flavor_t        pst_flavor;
195         struct ptlrpc_secops   *pst_ops;
196 };
197
198 #define PTLRPC_CREDCACHE_NR     8
199 #define PTLRPC_CREDCACHE_MASK   (PTLRPC_CREDCACHE_NR - 1)
200
201 struct ptlrpc_sec {
202         struct ptlrpc_sec_type *ps_type;
203         struct list_head        ps_credcache[PTLRPC_CREDCACHE_NR];
204         spinlock_t              ps_lock;        /* protect cred cache */
205         __u32                   ps_sectype;
206         ptlrpcs_flavor_t        ps_flavor;
207         atomic_t                ps_refcount;
208         atomic_t                ps_credcount;
209         struct obd_import      *ps_import;
210         /* actual security model need initialize following fields */
211         unsigned long           ps_expire;      /* cache expire interval */
212         unsigned long           ps_nextgc;      /* next gc time */
213         unsigned int            ps_flags;
214 };
215
216 /* sec.c */
217 int  ptlrpcs_register(struct ptlrpc_sec_type *type);
218 int  ptlrpcs_unregister(struct ptlrpc_sec_type *type);
219
220 struct ptlrpc_sec * ptlrpcs_sec_create(ptlrpcs_flavor_t *flavor,
221                                        struct obd_import *import,
222                                        const char *pipe_dir,
223                                        void *pipe_data);
224 void ptlrpcs_sec_put(struct ptlrpc_sec *sec);
225 void ptlrpcs_sec_invalidate_cache(struct ptlrpc_sec *sec);
226
227 struct ptlrpc_cred * ptlrpcs_cred_lookup(struct ptlrpc_sec *sec,
228                                          struct vfs_cred *vcred);
229 void ptlrpcs_cred_put(struct ptlrpc_cred *cred, int sync);
230
231 static inline void ptlrpcs_cred_get(struct ptlrpc_cred *cred)
232 {
233         LASSERT(atomic_read(&cred->pc_refcount));
234         atomic_inc(&cred->pc_refcount);
235 }
236
237 static inline int ptlrpcs_cred_refresh(struct ptlrpc_cred *cred)
238 {
239         LASSERT(cred);
240         LASSERT(atomic_read(&cred->pc_refcount));
241         LASSERT(cred->pc_ops);
242         LASSERT(cred->pc_ops->refresh);
243         return cred->pc_ops->refresh(cred);
244 }
245
246 static inline int ptlrpcs_cred_is_uptodate(struct ptlrpc_cred *cred)
247 {
248         smp_mb();
249         return ((cred->pc_flags & PTLRPC_CRED_FLAGS_MASK) ==
250                 PTLRPC_CRED_UPTODATE);
251 }
252
253 static inline int ptlrpcs_cred_is_dead(struct ptlrpc_cred *cred)
254 {
255         smp_mb();
256         return ((cred->pc_flags & (PTLRPC_CRED_DEAD | PTLRPC_CRED_ERROR)) != 0);
257 }
258
259 #define ptlrpcs_cred_expire(cred)                                       \
260         if (!test_and_set_bit(PTLRPC_CRED_DEAD_BIT, &cred->pc_flags)) { \
261                 CWARN("cred %p: get expired\n", cred);                  \
262                 clear_bit(PTLRPC_CRED_UPTODATE_BIT, &cred->pc_flags);   \
263         }
264
265 static inline int ptlrpcs_cred_check_uptodate(struct ptlrpc_cred *cred)
266 {
267         LASSERT(atomic_read(&cred->pc_refcount));
268
269         if (!ptlrpcs_cred_is_uptodate(cred))
270                 return 1;
271
272         if (cred->pc_expire == 0)
273                 return 0;
274         if (time_after(cred->pc_expire, get_seconds()))
275                 return 0;
276         ptlrpcs_cred_expire(cred);
277         return 1;
278 }
279
280 static inline int ptlrpcs_est_req_payload(struct ptlrpc_sec *sec,
281                                           int datasize)
282 {
283         struct ptlrpc_secops *ops;
284
285         LASSERT(sec);
286         LASSERT(sec->ps_type);
287         LASSERT(sec->ps_type->pst_ops);
288
289         ops = sec->ps_type->pst_ops;
290         if (ops->est_req_payload)
291                 return ops->est_req_payload(sec, datasize);
292         else
293                 return 0;
294 }
295
296 static inline int ptlrpcs_est_rep_payload(struct ptlrpc_sec *sec,
297                                           int datasize)
298 {
299         struct ptlrpc_secops *ops;
300
301         LASSERT(sec);
302         LASSERT(sec->ps_type);
303         LASSERT(sec->ps_type->pst_ops);
304
305         ops = sec->ps_type->pst_ops;
306         if (ops->est_rep_payload)
307                 return ops->est_rep_payload(sec, datasize);
308         else
309                 return 0;
310 }
311
312 static inline int add_deny_security(char *sec, struct list_head *head)
313 {
314         int rc = 0;
315         deny_sec_t      *p_deny_sec = NULL;
316
317         LASSERT(sec != NULL);
318
319         OBD_ALLOC(p_deny_sec, sizeof(*p_deny_sec));
320         if (p_deny_sec == NULL) return -ENOMEM;
321
322         if (strcmp(sec, "null") == 0) {
323                 p_deny_sec->sec.flavor = PTLRPC_SEC_NULL;
324                 p_deny_sec->sec.subflavor = PTLRPC_SEC_NULL;
325         }else if (strcmp(sec, "krb5i") == 0) {
326                p_deny_sec->sec.flavor = PTLRPC_SEC_GSS;
327                p_deny_sec->sec.subflavor = PTLRPC_SEC_GSS_KRB5I;
328         }else if (strcmp(sec, "krb5p") == 0) {
329                p_deny_sec->sec.flavor = PTLRPC_SEC_GSS;
330                p_deny_sec->sec.subflavor = PTLRPC_SEC_GSS_KRB5P;
331         }else{
332                CERROR("unrecognized security type %s\n", (char*) sec);
333                GOTO(out, rc = -EINVAL);
334         }
335
336         list_add_tail(&p_deny_sec->list, head);
337 out:
338         if (rc) {
339                 if (p_deny_sec)
340                         OBD_FREE(p_deny_sec, sizeof(*p_deny_sec));
341         }
342         return rc;
343 }
344
345 int ptlrpcs_cli_wrap_request(struct ptlrpc_request *req);
346 int ptlrpcs_cli_unwrap_reply(struct ptlrpc_request *req);
347 int ptlrpcs_cli_alloc_reqbuf(struct ptlrpc_request *req, int msgsize);
348 int ptlrpcs_cli_alloc_repbuf(struct ptlrpc_request *req, int msgsize);
349 void ptlrpcs_cli_free_reqbuf(struct ptlrpc_request *req);
350 void ptlrpcs_cli_free_repbuf(struct ptlrpc_request *req);
351
352 /* higher interface */
353 int  ptlrpcs_import_get_sec(struct obd_import *imp);
354 void ptlrpcs_import_drop_sec(struct obd_import *imp);
355 void ptlrpcs_import_flush_creds(struct obd_import *imp, uid_t uid);
356 int  ptlrpcs_req_get_cred(struct ptlrpc_request *req);
357 void ptlrpcs_req_drop_cred(struct ptlrpc_request *req);
358 int  ptlrpcs_req_replace_dead_cred(struct ptlrpc_request *req);
359 int  ptlrpcs_req_refresh_cred(struct ptlrpc_request *req);
360 int ptlrpcs_check_cred(struct obd_import *imp);
361
362 /* internal helpers */
363 int sec_alloc_reqbuf(struct ptlrpc_sec *sec, struct ptlrpc_request *req,
364                      int msgsize, int secsize);
365 void sec_free_reqbuf(struct ptlrpc_sec *sec, struct ptlrpc_request *req);
366
367 /* sec_null.c */
368 int ptlrpcs_null_init(void);
369 int ptlrpcs_null_exit(void);
370
371 /**********************************************************
372  * Server side stuff
373  **********************************************************/
374
375 struct ptlrpc_reply_state;
376
377 struct ptlrpc_svcsec {
378         struct module           *pss_owner;
379         char                    *pss_name;
380         ptlrpcs_flavor_t         pss_flavor;
381         int                      pss_sec_size;
382
383         int                    (*accept)      (struct ptlrpc_request *req,
384                                                enum ptlrpcs_error *res);
385         int                    (*authorize)   (struct ptlrpc_request *req);
386         int                    (*alloc_repbuf)(struct ptlrpc_svcsec *svcsec,
387                                                struct ptlrpc_request *req,
388                                                int msgsize);
389         void                   (*free_repbuf) (struct ptlrpc_svcsec *svcsec,
390                                                struct ptlrpc_reply_state *rs);
391         void                   (*cleanup_req) (struct ptlrpc_svcsec *svcsec,
392                                                struct ptlrpc_request *req);
393 };
394
395 #define SVC_OK          1
396 #define SVC_COMPLETE    2
397 #define SVC_DROP        3
398 #define SVC_LOGIN       4
399 #define SVC_LOGOUT      5
400
401 /* FIXME
402  * this should be a gss internal structure. fix these when we
403  * sort out the flavor issues.
404  */
405
406 typedef struct rawobj_s {
407         __u32           len;
408         __u8           *data;
409 } rawobj_t;
410
411 /* on-the-wire gss cred: */
412 struct rpc_gss_wire_cred {
413         __u32                   gc_v;           /* version */
414         __u32                   gc_proc;        /* control procedure */
415         __u32                   gc_seq;         /* sequence number */
416         __u32                   gc_svc;         /* service */
417         rawobj_t                gc_ctx;         /* context handle */
418 };
419
420 struct gss_svc_data {
421         __u32                           subflavor; /* XXX */
422         /* decoded gss client cred: */
423         struct rpc_gss_wire_cred        clcred;
424         /* internal used status */
425         unsigned int                    is_init:1,
426                                         is_init_continue:1,
427                                         is_err_notify:1,
428                                         is_fini:1;
429         int                             reserve_len;
430 };
431
432 int svcsec_register(struct ptlrpc_svcsec *ss);
433 int svcsec_unregister(struct ptlrpc_svcsec *ss);
434 int svcsec_accept(struct ptlrpc_request *req, enum ptlrpcs_error *res);
435 int svcsec_authorize(struct ptlrpc_request *req);
436 int svcsec_alloc_repbuf(struct ptlrpc_svcsec *svcsec,
437                         struct ptlrpc_request *req, int msgsize);
438 void svcsec_cleanup_req(struct ptlrpc_request *req);
439
440 struct ptlrpc_svcsec * svcsec_get(struct ptlrpc_svcsec *sec);
441 void svcsec_put(struct ptlrpc_svcsec *sec);
442
443 /* internal helpers */
444 int svcsec_alloc_reply_state(struct ptlrpc_request *req,
445                              int msgsize, int secsize);
446 void svcsec_free_reply_state(struct ptlrpc_reply_state *rs);
447
448 /* svcsec_null.c */
449 int svcsec_null_init(void);
450 int svcsec_null_exit(void);
451
452 #endif /* __LINUX_SEC_H_ */