1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * Copyright (C) 2004 Cluster File Systems, Inc.
6 * This file is part of Lustre, http://www.lustre.org.
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.
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.
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.
22 #ifndef __LINUX_SEC_H_
23 #define __LINUX_SEC_H_
25 /* forward declaration */
27 struct ptlrpc_request;
29 struct ptlrpc_credops;
33 #define PTLRPC_SEC_MAX_FLAVORS (4)
35 typedef struct ptlrpcs_flavor_s {
41 struct list_head list;
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 */
52 * This header is prepended at any on-wire ptlrpc packets
54 struct ptlrpcs_wire_hdr {
62 struct ptlrpcs_wire_hdr *buf_to_sec_hdr(void *buf)
64 return (struct ptlrpcs_wire_hdr *) buf;
68 struct lustre_msg *buf_to_lustre_msg(void *buf)
70 return (struct lustre_msg *)
71 ((char *) buf + sizeof(struct ptlrpcs_wire_hdr));
75 __u8 *buf_to_sec_data(void *buf)
77 struct ptlrpcs_wire_hdr *hdr = buf_to_sec_hdr(buf);
78 return (__u8 *) (buf + sizeof(*hdr) + hdr->msg_len);
81 enum ptlrpcs_flavors {
86 #define PTLRPC_SEC_GSS_VERSION (1)
88 enum ptlrpcs_gss_subflavors {
89 PTLRPC_SEC_GSS_KRB5 = 0,
90 PTLRPC_SEC_GSS_KRB5I = 1,
91 PTLRPC_SEC_GSS_KRB5P = 2,
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,
102 enum ptlrpcs_gss_svc {
103 PTLRPC_GSS_SVC_NONE = 1,
104 PTLRPC_GSS_SVC_INTEGRITY = 2,
105 PTLRPC_GSS_SVC_PRIVACY = 3,
111 PTLRPCS_REJECTEDCRED = 2,
113 PTLRPCS_REJECTEDVERF = 4,
116 PTLRPCS_GSS_CREDPROBLEM = 13,
117 PTLRPCS_GSS_CTXPROBLEM = 14,
124 struct group_info *vc_ginfo;
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);
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.) */
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)
149 #define PTLRPC_CRED_FLAGS_MASK (PTLRPC_CRED_UPTODATE | \
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 */
165 struct ptlrpc_secops {
166 struct ptlrpc_sec * (*create_sec) (ptlrpcs_flavor_t *flavor,
167 const char *pipe_dir,
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,
186 int (*est_rep_payload)(struct ptlrpc_sec *sec,
190 struct ptlrpc_sec_type {
191 struct module *pst_owner;
193 atomic_t pst_inst; /* instance, debug only */
194 ptlrpcs_flavor_t pst_flavor;
195 struct ptlrpc_secops *pst_ops;
198 #define PTLRPC_CREDCACHE_NR 8
199 #define PTLRPC_CREDCACHE_MASK (PTLRPC_CREDCACHE_NR - 1)
202 struct ptlrpc_sec_type *ps_type;
203 struct list_head ps_credcache[PTLRPC_CREDCACHE_NR];
204 spinlock_t ps_lock; /* protect cred cache */
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;
217 int ptlrpcs_register(struct ptlrpc_sec_type *type);
218 int ptlrpcs_unregister(struct ptlrpc_sec_type *type);
220 struct ptlrpc_sec * ptlrpcs_sec_create(ptlrpcs_flavor_t *flavor,
221 struct obd_import *import,
222 const char *pipe_dir,
224 void ptlrpcs_sec_put(struct ptlrpc_sec *sec);
225 void ptlrpcs_sec_invalidate_cache(struct ptlrpc_sec *sec);
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);
231 static inline void ptlrpcs_cred_get(struct ptlrpc_cred *cred)
233 LASSERT(atomic_read(&cred->pc_refcount));
234 atomic_inc(&cred->pc_refcount);
237 static inline int ptlrpcs_cred_refresh(struct ptlrpc_cred *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);
246 static inline int ptlrpcs_cred_is_uptodate(struct ptlrpc_cred *cred)
249 return ((cred->pc_flags & PTLRPC_CRED_FLAGS_MASK) ==
250 PTLRPC_CRED_UPTODATE);
253 static inline int ptlrpcs_cred_is_dead(struct ptlrpc_cred *cred)
256 return ((cred->pc_flags & (PTLRPC_CRED_DEAD | PTLRPC_CRED_ERROR)) != 0);
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); \
265 static inline int ptlrpcs_cred_check_uptodate(struct ptlrpc_cred *cred)
267 LASSERT(atomic_read(&cred->pc_refcount));
269 if (!ptlrpcs_cred_is_uptodate(cred))
272 if (cred->pc_expire == 0)
274 if (time_after(cred->pc_expire, get_seconds()))
276 ptlrpcs_cred_expire(cred);
280 static inline int ptlrpcs_est_req_payload(struct ptlrpc_sec *sec,
283 struct ptlrpc_secops *ops;
286 LASSERT(sec->ps_type);
287 LASSERT(sec->ps_type->pst_ops);
289 ops = sec->ps_type->pst_ops;
290 if (ops->est_req_payload)
291 return ops->est_req_payload(sec, datasize);
296 static inline int ptlrpcs_est_rep_payload(struct ptlrpc_sec *sec,
299 struct ptlrpc_secops *ops;
302 LASSERT(sec->ps_type);
303 LASSERT(sec->ps_type->pst_ops);
305 ops = sec->ps_type->pst_ops;
306 if (ops->est_rep_payload)
307 return ops->est_rep_payload(sec, datasize);
312 static inline int add_deny_security(char *sec, struct list_head *head)
315 deny_sec_t *p_deny_sec = NULL;
317 LASSERT(sec != NULL);
319 OBD_ALLOC(p_deny_sec, sizeof(*p_deny_sec));
320 if (p_deny_sec == NULL) return -ENOMEM;
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;
332 CERROR("unrecognized security type %s\n", (char*) sec);
333 GOTO(out, rc = -EINVAL);
336 list_add_tail(&p_deny_sec->list, head);
340 OBD_FREE(p_deny_sec, sizeof(*p_deny_sec));
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);
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);
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);
368 int ptlrpcs_null_init(void);
369 int ptlrpcs_null_exit(void);
371 /**********************************************************
373 **********************************************************/
375 struct ptlrpc_reply_state;
377 struct ptlrpc_svcsec {
378 struct module *pss_owner;
380 ptlrpcs_flavor_t pss_flavor;
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,
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);
396 #define SVC_COMPLETE 2
402 * this should be a gss internal structure. fix these when we
403 * sort out the flavor issues.
406 typedef struct rawobj_s {
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 */
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,
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);
440 struct ptlrpc_svcsec * svcsec_get(struct ptlrpc_svcsec *sec);
441 void svcsec_put(struct ptlrpc_svcsec *sec);
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);
449 int svcsec_null_init(void);
450 int svcsec_null_exit(void);
452 #endif /* __LINUX_SEC_H_ */