X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Finclude%2Flinux%2Flustre_sec.h;h=723f76aa8a8a34b2b52ba7b9aa947d414b73c24f;hb=99bf8fb2147b61f11e61d3330b61147eba48d5fd;hp=e1e866cd827c9e2267cfc86f5e57ff15c5c77eaf;hpb=89f9a5bced24ecb7c84040a1ed88dcef4384f7c6;p=fs%2Flustre-release.git diff --git a/lustre/include/linux/lustre_sec.h b/lustre/include/linux/lustre_sec.h index e1e866c..723f76a 100644 --- a/lustre/include/linux/lustre_sec.h +++ b/lustre/include/linux/lustre_sec.h @@ -22,6 +22,111 @@ #ifndef __LINUX_SEC_H_ #define __LINUX_SEC_H_ +enum ptlrpcs_major_flavors { + PTLRPCS_FLVR_MAJOR_NULL = 0, + PTLRPCS_FLVR_MAJOR_GSS = 1, + PTLRPCS_FLVR_MAJOR_MAX, +}; + +enum ptlrpcs_null_minor_flavors { + PTLRPCS_FLVR_MINOR_NULL = 0, + PTLRPCS_FLVR_MINOR_NULL_MAX, +}; + +enum ptlrpcs_gss_minor_flavors { + PTLRPCS_FLVR_MINOR_GSS_NONE = 0, + PTLRPCS_FLVR_MINOR_GSS_KRB5 = 1, + PTLRPCS_FLVR_MINOR_GSS_MAX, +}; + +enum ptlrpcs_security_type { + PTLRPCS_SVC_NONE = 0, /* no security */ + PTLRPCS_SVC_AUTH = 1, /* authentication */ + PTLRPCS_SVC_PRIV = 2, /* privacy */ + PTLRPCS_SVC_MAX, +}; + +/* + * flavor compose/extract + */ +#define SEC_FLAVOR_MAJOR_OFFSET (24) +#define SEC_FLAVOR_RESERVE_OFFSET (16) +#define SEC_FLAVOR_SVC_OFFSET (8) +#define SEC_FLAVOR_MINOR_OFFSET (0) + +#define SEC_MAKE_FLAVOR(major, minor, svc) \ + (((__u32)(major) << SEC_FLAVOR_MAJOR_OFFSET) | \ + ((__u32)(svc) << SEC_FLAVOR_SVC_OFFSET) | \ + ((__u32)(minor) << SEC_FLAVOR_MINOR_OFFSET)) + +#define SEC_MAKE_SUBFLAVOR(minor, svc) \ + (((__u32)(svc) << SEC_FLAVOR_SVC_OFFSET) | \ + ((__u32)(minor) << SEC_FLAVOR_MINOR_OFFSET)) + +#define SEC_FLAVOR_MAJOR(flavor) \ + ((((__u32)(flavor)) >> SEC_FLAVOR_MAJOR_OFFSET) & 0xFF) +#define SEC_FLAVOR_MINOR(flavor) \ + ((((__u32)(flavor)) >> SEC_FLAVOR_MINOR_OFFSET) & 0xFF) +#define SEC_FLAVOR_SVC(flavor) \ + ((((__u32)(flavor)) >> SEC_FLAVOR_SVC_OFFSET) & 0xFF) +#define SEC_FLAVOR_SUB(flavor) \ + ((((__u32)(flavor)) >> SEC_FLAVOR_MINOR_OFFSET) & 0xFFFF) + +/* + * general gss flavors + */ +#define PTLRPCS_FLVR_GSS_NONE \ + SEC_MAKE_FLAVOR(PTLRPCS_FLVR_MAJOR_GSS, \ + PTLRPCS_FLVR_MINOR_GSS_NONE, \ + PTLRPCS_SVC_NONE) +#define PTLRPCS_FLVR_GSS_AUTH \ + SEC_MAKE_FLAVOR(PTLRPCS_FLVR_MAJOR_GSS, \ + PTLRPCS_FLVR_MINOR_GSS_NONE, \ + PTLRPCS_SVC_AUTH) +#define PTLRPCS_FLVR_GSS_PRIV \ + SEC_MAKE_FLAVOR(PTLRPCS_FLVR_MAJOR_GSS, \ + PTLRPCS_FLVR_MINOR_GSS_NONE, \ + PTLRPCS_SVC_PRIV) + +/* + * gss subflavors + */ +#define PTLRPCS_SUBFLVR_KRB5 \ + SEC_MAKE_SUBFLAVOR(PTLRPCS_FLVR_MINOR_GSS_KRB5, \ + PTLRPCS_SVC_NONE) +#define PTLRPCS_SUBFLVR_KRB5I \ + SEC_MAKE_SUBFLAVOR(PTLRPCS_FLVR_MINOR_GSS_KRB5, \ + PTLRPCS_SVC_AUTH) +#define PTLRPCS_SUBFLVR_KRB5P \ + SEC_MAKE_SUBFLAVOR(PTLRPCS_FLVR_MINOR_GSS_KRB5, \ + PTLRPCS_SVC_PRIV) + +/* + * "end user" flavors + */ +#define PTLRPCS_FLVR_NULL \ + SEC_MAKE_FLAVOR(PTLRPCS_FLVR_MAJOR_NULL, \ + PTLRPCS_FLVR_MINOR_NULL, \ + PTLRPCS_SVC_NONE) +#define PTLRPCS_FLVR_KRB5 \ + SEC_MAKE_FLAVOR(PTLRPCS_FLVR_MAJOR_GSS, \ + PTLRPCS_FLVR_MINOR_GSS_KRB5, \ + PTLRPCS_SVC_NONE) +#define PTLRPCS_FLVR_KRB5I \ + SEC_MAKE_FLAVOR(PTLRPCS_FLVR_MAJOR_GSS, \ + PTLRPCS_FLVR_MINOR_GSS_KRB5, \ + PTLRPCS_SVC_AUTH) +#define PTLRPCS_FLVR_KRB5P \ + SEC_MAKE_FLAVOR(PTLRPCS_FLVR_MAJOR_GSS, \ + PTLRPCS_FLVR_MINOR_GSS_KRB5, \ + PTLRPCS_SVC_PRIV) + +#define PTLRPCS_FLVR_INVALID (-1) + +__u32 ptlrpcs_name2flavor(const char *name); +char *ptlrpcs_flavor2name(__u32 flavor); + + /* forward declaration */ struct obd_import; struct ptlrpc_request; @@ -30,25 +135,17 @@ struct ptlrpc_credops; struct ptlrpc_sec; struct ptlrpc_secops; -#define PTLRPC_SEC_MAX_FLAVORS (4) - -typedef struct ptlrpcs_flavor_s { - __u32 flavor; - __u32 subflavor; -} ptlrpcs_flavor_t; - -enum ptlrpcs_security_type { - PTLRPC_SEC_TYPE_NONE = 0, /* no security */ - PTLRPC_SEC_TYPE_AUTH = 1, /* authentication */ - PTLRPC_SEC_TYPE_PRIV = 2, /* privacy */ -}; +typedef struct { + struct list_head list; + __u32 flavor; +} deny_sec_t; /* * This header is prepended at any on-wire ptlrpc packets */ struct ptlrpcs_wire_hdr { __u32 flavor; - __u32 sectype; + __u32 unused; __u32 msg_len; __u32 sec_len; }; @@ -73,87 +170,85 @@ __u8 *buf_to_sec_data(void *buf) return (__u8 *) (buf + sizeof(*hdr) + hdr->msg_len); } -enum ptlrpcs_flavors { - PTLRPC_SEC_NULL = 0, - PTLRPC_SEC_GSS = 1, -}; - #define PTLRPC_SEC_GSS_VERSION (1) -enum ptlrpcs_gss_subflavors { - PTLRPC_SEC_GSS_KRB5 = 0, - PTLRPC_SEC_GSS_KRB5I = 1, - PTLRPC_SEC_GSS_KRB5P = 2, -}; - enum ptlrpcs_gss_proc { - PTLRPC_GSS_PROC_DATA = 0, - PTLRPC_GSS_PROC_INIT = 1, - PTLRPC_GSS_PROC_CONTINUE_INIT = 2, - PTLRPC_GSS_PROC_DESTROY = 3, - PTLRPC_GSS_PROC_ERR = 4, + PTLRPCS_GSS_PROC_DATA = 0, + PTLRPCS_GSS_PROC_INIT = 1, + PTLRPCS_GSS_PROC_CONTINUE_INIT = 2, + PTLRPCS_GSS_PROC_DESTROY = 3, + PTLRPCS_GSS_PROC_ERR = 4, }; enum ptlrpcs_gss_svc { - PTLRPC_GSS_SVC_NONE = 1, - PTLRPC_GSS_SVC_INTEGRITY = 2, - PTLRPC_GSS_SVC_PRIVACY = 3, + PTLRPCS_GSS_SVC_NONE = 1, + PTLRPCS_GSS_SVC_INTEGRITY = 2, + PTLRPCS_GSS_SVC_PRIVACY = 3, }; enum ptlrpcs_error { - PTLRPCS_OK = 0, - PTLRPCS_BADCRED = 1, - PTLRPCS_REJECTEDCRED = 2, - PTLRPCS_BADVERF = 3, - PTLRPCS_REJECTEDVERF = 4, - PTLRPCS_TOOWEAK = 5, + PTLRPCS_OK = 0, + PTLRPCS_BADCRED = 1, + PTLRPCS_REJECTEDCRED = 2, + PTLRPCS_BADVERF = 3, + PTLRPCS_REJECTEDVERF = 4, + PTLRPCS_TOOWEAK = 5, /* GSS errors */ - PTLRPCS_GSS_CREDPROBLEM = 13, - PTLRPCS_GSS_CTXPROBLEM = 14, + PTLRPCS_GSS_CREDPROBLEM = 13, + PTLRPCS_GSS_CTXPROBLEM = 14, }; struct vfs_cred { - __u64 vc_pag; - uid_t vc_uid; - gid_t vc_gid; - struct group_info *vc_ginfo; + __u64 vc_pag; + uid_t vc_uid; + gid_t vc_gid; + struct group_info *vc_ginfo; }; struct ptlrpc_credops { + int (*match) (struct ptlrpc_cred *cred, struct vfs_cred *vcred); int (*refresh)(struct ptlrpc_cred *cred); - int (*match) (struct ptlrpc_cred *cred, - struct ptlrpc_request *req, - struct vfs_cred *vcred); - int (*sign) (struct ptlrpc_cred *cred, struct ptlrpc_request *req); - int (*verify) (struct ptlrpc_cred *cred, struct ptlrpc_request *req); - int (*seal) (struct ptlrpc_cred *cred, struct ptlrpc_request *req); - int (*unseal) (struct ptlrpc_cred *cred, struct ptlrpc_request *req); void (*destroy)(struct ptlrpc_cred *cred); + int (*sign) (struct ptlrpc_cred *cred, + struct ptlrpc_request *req); + int (*verify) (struct ptlrpc_cred *cred, + struct ptlrpc_request *req); + int (*seal) (struct ptlrpc_cred *cred, + struct ptlrpc_request *req); + int (*unseal) (struct ptlrpc_cred *cred, + struct ptlrpc_request *req); }; -#define PTLRPC_CRED_UPTODATE 0x00000001 -#define PTLRPC_CRED_DEAD 0x00000002 +#define PTLRPC_CRED_UPTODATE_BIT 0 /* uptodate */ +#define PTLRPC_CRED_DEAD_BIT 1 /* mark expired gracefully */ +#define PTLRPC_CRED_ERROR_BIT 2 /* fatal error (refresh, etc.) */ + +#define PTLRPC_CRED_UPTODATE (1 << PTLRPC_CRED_UPTODATE_BIT) +#define PTLRPC_CRED_DEAD (1 << PTLRPC_CRED_DEAD_BIT) +#define PTLRPC_CRED_ERROR (1 << PTLRPC_CRED_ERROR_BIT) + +#define PTLRPC_CRED_FLAGS_MASK (PTLRPC_CRED_UPTODATE | \ + PTLRPC_CRED_DEAD | \ + PTLRPC_CRED_ERROR) struct ptlrpc_cred { struct list_head pc_hash; /* linked into hash table */ atomic_t pc_refcount; struct ptlrpc_sec *pc_sec; struct ptlrpc_credops *pc_ops; - struct ptlrpc_request *pc_req; unsigned long pc_expire; - int pc_flags; + unsigned long pc_flags; /* XXX maybe should not be here */ __u64 pc_pag; uid_t pc_uid; }; struct ptlrpc_secops { - struct ptlrpc_sec * (*create_sec) (ptlrpcs_flavor_t *flavor, + struct ptlrpc_sec * (*create_sec) (__u32 flavor, const char *pipe_dir, void *pipe_data); void (*destroy_sec) (struct ptlrpc_sec *sec); struct ptlrpc_cred * (*create_cred) (struct ptlrpc_sec *sec, - struct ptlrpc_request *req, struct vfs_cred *vcred); /* buffer manipulation */ int (*alloc_reqbuf) (struct ptlrpc_sec *sec, @@ -168,8 +263,10 @@ struct ptlrpc_secops { struct ptlrpc_request *req); /* security payload size estimation */ int (*est_req_payload)(struct ptlrpc_sec *sec, + struct ptlrpc_request *req, int msgsize); int (*est_rep_payload)(struct ptlrpc_sec *sec, + struct ptlrpc_request *req, int msgsize); }; @@ -177,10 +274,14 @@ struct ptlrpc_sec_type { struct module *pst_owner; char *pst_name; atomic_t pst_inst; /* instance, debug only */ - ptlrpcs_flavor_t pst_flavor; + __u32 pst_flavor; /* major flavor */ struct ptlrpc_secops *pst_ops; }; +#define PTLRPC_SEC_FL_MDS 0x0001 /* outgoing from MDS */ +#define PTLRPC_SEC_FL_REVERSE 0x0002 /* reverse sec */ +#define PTLRPC_SEC_FL_PAG 0x0004 /* enable PAG */ + #define PTLRPC_CREDCACHE_NR 8 #define PTLRPC_CREDCACHE_MASK (PTLRPC_CREDCACHE_NR - 1) @@ -188,22 +289,22 @@ struct ptlrpc_sec { struct ptlrpc_sec_type *ps_type; struct list_head ps_credcache[PTLRPC_CREDCACHE_NR]; spinlock_t ps_lock; /* protect cred cache */ - __u32 ps_sectype; - ptlrpcs_flavor_t ps_flavor; + __u32 ps_flavor; atomic_t ps_refcount; atomic_t ps_credcount; struct obd_import *ps_import; /* actual security model need initialize following fields */ unsigned long ps_expire; /* cache expire interval */ unsigned long ps_nextgc; /* next gc time */ - unsigned int ps_flags; + unsigned long ps_flags; }; /* sec.c */ int ptlrpcs_register(struct ptlrpc_sec_type *type); int ptlrpcs_unregister(struct ptlrpc_sec_type *type); -struct ptlrpc_sec * ptlrpcs_sec_create(ptlrpcs_flavor_t *flavor, +struct ptlrpc_sec * ptlrpcs_sec_create(__u32 flavor, + unsigned long flags, struct obd_import *import, const char *pipe_dir, void *pipe_data); @@ -220,12 +321,6 @@ static inline void ptlrpcs_cred_get(struct ptlrpc_cred *cred) atomic_inc(&cred->pc_refcount); } -static inline int ptlrpcs_cred_is_uptodate(struct ptlrpc_cred *cred) -{ - LASSERT(cred); - LASSERT(atomic_read(&cred->pc_refcount)); - return (cred->pc_flags & PTLRPC_CRED_UPTODATE); -} static inline int ptlrpcs_cred_refresh(struct ptlrpc_cred *cred) { LASSERT(cred); @@ -234,26 +329,45 @@ static inline int ptlrpcs_cred_refresh(struct ptlrpc_cred *cred) LASSERT(cred->pc_ops->refresh); return cred->pc_ops->refresh(cred); } -static inline void ptlrpcs_cred_die(struct ptlrpc_cred *cred) + +static inline int ptlrpcs_cred_is_uptodate(struct ptlrpc_cred *cred) { - LASSERT(atomic_read(&cred->pc_refcount)); - LASSERT(cred->pc_sec); - if (!(cred->pc_flags & PTLRPC_CRED_DEAD)) { - spin_lock(&cred->pc_sec->ps_lock); - cred->pc_flags |= PTLRPC_CRED_DEAD; - cred->pc_flags &= ~PTLRPC_CRED_UPTODATE; - list_del_init(&cred->pc_hash); - spin_unlock(&cred->pc_sec->ps_lock); - } + smp_mb(); + return ((cred->pc_flags & PTLRPC_CRED_FLAGS_MASK) == + PTLRPC_CRED_UPTODATE); } + static inline int ptlrpcs_cred_is_dead(struct ptlrpc_cred *cred) { - return(cred->pc_flags & PTLRPC_CRED_DEAD); + smp_mb(); + return ((cred->pc_flags & (PTLRPC_CRED_DEAD | PTLRPC_CRED_ERROR)) != 0); +} + +#define ptlrpcs_cred_expire(cred) \ + if (!test_and_set_bit(PTLRPC_CRED_DEAD_BIT, &cred->pc_flags)) { \ + CWARN("cred %p: get expired\n", cred); \ + clear_bit(PTLRPC_CRED_UPTODATE_BIT, &cred->pc_flags); \ + } + +static inline int ptlrpcs_cred_check_uptodate(struct ptlrpc_cred *cred) +{ + LASSERT(atomic_read(&cred->pc_refcount)); + + if (!ptlrpcs_cred_is_uptodate(cred)) + return 1; + + if (cred->pc_expire == 0) + return 0; + if (time_after(cred->pc_expire, get_seconds())) + return 0; + ptlrpcs_cred_expire(cred); + return 1; } -static inline int ptlrpcs_est_req_payload(struct ptlrpc_sec *sec, +static inline int ptlrpcs_est_req_payload(struct ptlrpc_request *req, int datasize) { + struct ptlrpc_sec *sec = req->rq_cred->pc_sec; struct ptlrpc_secops *ops; LASSERT(sec); @@ -262,14 +376,15 @@ static inline int ptlrpcs_est_req_payload(struct ptlrpc_sec *sec, ops = sec->ps_type->pst_ops; if (ops->est_req_payload) - return ops->est_req_payload(sec, datasize); + return ops->est_req_payload(sec, req, datasize); else return 0; } -static inline int ptlrpcs_est_rep_payload(struct ptlrpc_sec *sec, +static inline int ptlrpcs_est_rep_payload(struct ptlrpc_request *req, int datasize) { + struct ptlrpc_sec *sec = req->rq_cred->pc_sec; struct ptlrpc_secops *ops; LASSERT(sec); @@ -278,11 +393,38 @@ static inline int ptlrpcs_est_rep_payload(struct ptlrpc_sec *sec, ops = sec->ps_type->pst_ops; if (ops->est_rep_payload) - return ops->est_rep_payload(sec, datasize); + return ops->est_rep_payload(sec, req, datasize); else return 0; } +static inline int add_deny_security(char *sec, struct list_head *head) +{ + deny_sec_t *p_deny_sec = NULL; + int rc = 0; + + LASSERT(sec != NULL); + + OBD_ALLOC(p_deny_sec, sizeof(*p_deny_sec)); + if (p_deny_sec == NULL) + return -ENOMEM; + + p_deny_sec->flavor = ptlrpcs_name2flavor(sec); + if (p_deny_sec->flavor == PTLRPCS_FLVR_INVALID) { + CERROR("unrecognized security type %s\n", (char*) sec); + rc = -EINVAL; + goto out; + } + + list_add_tail(&p_deny_sec->list, head); +out: + if (rc) { + if (p_deny_sec) + OBD_FREE(p_deny_sec, sizeof(*p_deny_sec)); + } + return rc; +} + int ptlrpcs_cli_wrap_request(struct ptlrpc_request *req); int ptlrpcs_cli_unwrap_reply(struct ptlrpc_request *req); int ptlrpcs_cli_alloc_reqbuf(struct ptlrpc_request *req, int msgsize); @@ -293,10 +435,12 @@ void ptlrpcs_cli_free_repbuf(struct ptlrpc_request *req); /* higher interface */ int ptlrpcs_import_get_sec(struct obd_import *imp); void ptlrpcs_import_drop_sec(struct obd_import *imp); +void ptlrpcs_import_flush_current_creds(struct obd_import *imp); int ptlrpcs_req_get_cred(struct ptlrpc_request *req); void ptlrpcs_req_drop_cred(struct ptlrpc_request *req); int ptlrpcs_req_replace_dead_cred(struct ptlrpc_request *req); int ptlrpcs_req_refresh_cred(struct ptlrpc_request *req); +int ptlrpcs_check_cred(struct obd_import *imp); /* internal helpers */ int sec_alloc_reqbuf(struct ptlrpc_sec *sec, struct ptlrpc_request *req, @@ -316,7 +460,7 @@ struct ptlrpc_reply_state; struct ptlrpc_svcsec { struct module *pss_owner; char *pss_name; - ptlrpcs_flavor_t pss_flavor; + __u32 pss_flavor; /* major flavor */ int pss_sec_size; int (*accept) (struct ptlrpc_request *req, @@ -357,4 +501,173 @@ void svcsec_free_reply_state(struct ptlrpc_reply_state *rs); int svcsec_null_init(void); int svcsec_null_exit(void); +/* capability */ +#ifdef __KERNEL__ +#include +#endif + +#define NR_CAPAHASH 32 +#define CAPA_TIMEOUT 1800 /* sec, == 30 min */ +#define CAPA_KEY_TIMEOUT (24 * 60 * 60) /* sec, == 1 day */ +#define CAPA_CACHE_SIZE 1000 /* for MDS & OST */ +#define CAPA_HMAC_ALG "sha1" + +struct lustre_capa_data { + __u32 lc_uid; /* uid */ + __u32 lc_op; /* operations allowed */ + __u64 lc_ino; /* inode# */ + __u32 lc_mdsid; /* mds# */ + __u32 lc_keyid; /* key used for the capability */ + __u64 lc_expiry; /* expiry time: servers have clocks */ + __u32 lc_flags; /* security features for capability */ +} __attribute__((packed)); + +struct client_capa { + struct inode *inode; /* this should be always valid + * if c_refc > 0 */ + struct lustre_handle handle; /* handle of mds_file_data */ +#if 0 /* TODO: support multi mount point */ + struct list_head *list; /* the capa list belong to this client */ + struct timer_list *timer; /* timer belong to this client */ +#endif +}; + +struct filter_capa { + int bvalid; /* black key here valid or not */ + __u32 bkeyid; /* black key id */ + __u8 bhmac[CAPA_DIGEST_SIZE]; /* black key */ +}; + +struct obd_capa { + struct hlist_node c_hash; + struct list_head c_list; + + struct lustre_capa c_capa; /* capa */ + int c_type; + atomic_t c_refc; + + union { + struct client_capa client; + struct filter_capa filter; + } u; +}; + +#define c_inode u.client.inode +#define c_handle u.client.handle +#define c_bvalid u.filter.bvalid +#define c_bkeyid u.filter.bkeyid +#define c_bhmac u.filter.bhmac + +enum lustre_capa_type { + CLIENT_CAPA = 0, + MDS_CAPA = 1, + FILTER_CAPA = 2, +}; + +#define DEBUG_CAPA(level, capa, fmt, args...) \ +do { \ +CDEBUG(level, fmt " capa@%p uid %u op %u ino "LPU64" mdsid %d keyid %d " \ + "expiry "LPU64" flags %u\n", \ + ##args, capa, (capa)->lc_uid, (capa)->lc_op, (capa)->lc_ino, \ + (capa)->lc_mdsid, (capa)->lc_keyid, (capa)->lc_expiry, \ + (capa)->lc_flags); \ +} while (0) + +#define DEBUG_CAPA_KEY(level, key, fmt, args...) \ +do { \ +CDEBUG(level, fmt " capa key@%p mdsid %d keyid %d expiry "LPU64"\n", \ + ##args, key, (key)->lk_mdsid, (key)->lk_keyid, (key)->lk_expiry); \ +} while (0) + +#define DEBUG_MDS_CAPA_KEY(level, mkey, fmt, args...) \ +do { \ +CDEBUG(level, fmt " capa key@%p mdsid %d keyid %d expiry "LPU64"\n", \ + ##args, mkey, le32_to_cpu((mkey)->k_key->lk_mdsid), \ + le32_to_cpu((mkey)->k_key->lk_keyid), \ + le64_to_cpu((mkey)->k_key->lk_expiry)); \ +} while (0) + +extern spinlock_t capa_lock; +extern struct hlist_head *capa_hash; +extern struct list_head capa_list[]; +extern struct timer_list ll_capa_timer; + +/* obdclass/capa.c */ +int capa_op(int flags); +void __capa_get(struct obd_capa *ocapa); +struct obd_capa *capa_get(uid_t uid, int capa_op, __u64 mdsid, + unsigned long ino, int type, + struct lustre_capa *capa, struct inode *inode, + struct lustre_handle *handle); +void capa_put(struct obd_capa *ocapa, int type); +int capa_renew(struct lustre_capa *capa, int type); +void capa_hmac(struct crypto_tfm *tfm, __u8 *key, struct lustre_capa *capa); +void capa_dup(void *dst, struct obd_capa *ocapa); +void capa_dup2(void *dst, struct lustre_capa *capa); +int capa_expired(struct lustre_capa *capa); +int __capa_is_to_expire(struct obd_capa *ocapa); +int capa_is_to_expire(struct obd_capa *ocapa); + +#define CAPA_EXPIRY_SHIFT 10 /* 1024 sec */ +#define CAPA_EXPIRY (1UL << PAGE_SHIFT) +#define CAPA_EXPIRY_MASK (~(CAPA_EXPIRY-1)) + +#define CAPA_PRE_EXPIRY_NOROUND 3 /* sec */ +#define CAPA_PRE_EXPIRY 300 /* sec */ + +/* struct lustre_capa.lc_flags */ +#define CAPA_FL_NOROUND 0x001 /* capa expiry not rounded */ +#define CAPA_FL_REMUID 0x002 /* remote uid */ + +static inline unsigned long capa_pre_expiry(struct lustre_capa *capa) +{ + return (capa->lc_flags & CAPA_FL_NOROUND) ? + CAPA_PRE_EXPIRY_NOROUND : CAPA_PRE_EXPIRY; +} + +static inline __u64 +round_expiry(__u32 timeout) +{ + struct timeval tv; + __u64 expiry; + + do_gettimeofday(&tv); + expiry = tv.tv_sec + timeout; + + if (timeout > CAPA_EXPIRY) + expiry = (expiry + CAPA_EXPIRY - 1) & CAPA_EXPIRY_MASK; + + return expiry; +} + +static inline int +capa_key_cmp(struct lustre_capa_key *k1, struct lustre_capa_key *k2) +{ + return k1->lk_keyid - k2->lk_keyid; +} + +static inline unsigned long +expiry_to_jiffies(__u64 expiry) +{ + /* sec -> jiffies */ + struct timeval tv; + unsigned long timeout; + + do_gettimeofday(&tv); + timeout = jiffies + ((unsigned long)expiry - tv.tv_sec) * HZ; + return timeout; +} + +struct mds_capa_key { + struct list_head k_list; + + struct lustre_capa_key *k_key; + struct obd_device *k_obd; +}; + +struct filter_capa_key { + struct list_head k_list; + struct lustre_capa_key k_key; +}; + #endif /* __LINUX_SEC_H_ */