X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fptlrpc%2Fgss%2Fgss_internal.h;h=65fc5f8289f6c73e74ec248a274badd8f2e9ba9e;hb=2c27b194121665061cc0527e8bef35886ec7fea8;hp=8fd8014047062d1d98e7a22254b0e82eb8909b14;hpb=d2d56f38da01001c92a09afc6b52b5acbd9bc13c;p=fs%2Flustre-release.git diff --git a/lustre/ptlrpc/gss/gss_internal.h b/lustre/ptlrpc/gss/gss_internal.h index 8fd8014..65fc5f8 100644 --- a/lustre/ptlrpc/gss/gss_internal.h +++ b/lustre/ptlrpc/gss/gss_internal.h @@ -1,15 +1,17 @@ -/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- - * vim:expandtab:shiftwidth=8:tabstop=8: - * +/* * Modified from NFSv4 project for Lustre - * Copyright 2004 - 2006, Cluster File Systems, Inc. - * All rights reserved + * + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * + * Copyright (c) 2012, 2016, Intel Corporation. + * * Author: Eric Mei */ #ifndef __PTLRPC_GSS_GSS_INTERNAL_H_ #define __PTLRPC_GSS_GSS_INTERNAL_H_ +#include #include /* @@ -36,6 +38,7 @@ typedef struct rawobj_buf_s { __u8 *buf; } rawobj_buf_t; +int rawobj_empty(rawobj_t *obj); int rawobj_alloc(rawobj_t *obj, char *buf, int len); void rawobj_free(rawobj_t *obj); int rawobj_equal(rawobj_t *a, rawobj_t *b); @@ -44,9 +47,12 @@ int rawobj_serialize(rawobj_t *obj, __u32 **buf, __u32 *buflen); int rawobj_extract(rawobj_t *obj, __u32 **buf, __u32 *buflen); int rawobj_extract_alloc(rawobj_t *obj, __u32 **buf, __u32 *buflen); int rawobj_extract_local(rawobj_t *obj, __u32 **buf, __u32 *buflen); +int rawobj_extract_local_alloc(rawobj_t *obj, __u32 **buf, __u32 *buflen); int rawobj_from_netobj(rawobj_t *rawobj, netobj_t *netobj); int rawobj_from_netobj_alloc(rawobj_t *obj, netobj_t *netobj); +int buffer_extract_bytes(const void **buf, __u32 *buflen, + void *res, __u32 reslen); /* * several timeout values. client refresh upcall timeout we using @@ -61,6 +67,11 @@ int rawobj_from_netobj_alloc(rawobj_t *obj, netobj_t *netobj); #define GSS_SECFINI_RPC_TIMEOUT (__TIMEOUT_DELTA) #define GSS_SECSVC_UPCALL_TIMEOUT (GSS_SECINIT_RPC_TIMEOUT) +/* + * default gc interval + */ +#define GSS_GC_INTERVAL (60 * 60) /* 60 minutes */ + static inline unsigned long gss_round_ctx_expiry(unsigned long expiry, unsigned long sec_flags) @@ -74,27 +85,6 @@ unsigned long gss_round_ctx_expiry(unsigned long expiry, return expiry; } -/* we try to force reconnect import 20m eariler than real expiry. - * kerberos 5 usually allow 5m time skew, but which is adjustable, - * so if we set krb5 to allow > 20m time skew, we have chance that - * server's reverse ctx expired but client still hasn't start to - * refresh it -- it's BAD. So here we actually put a limit on the - * enviroment of krb5 (or other authentication mechanism) - */ -#define GSS_MAX_TIME_SKEW (20 * 60) - -static inline -unsigned long gss_round_imp_reconnect(unsigned long expiry) -{ - unsigned long now = get_seconds(); - unsigned long nice = GSS_MAX_TIME_SKEW + __TIMEOUT_DELTA; - - while (nice && (now + nice >= expiry)) - nice = nice / 2; - - return (expiry - nice); -} - /* * Max encryption element in block cipher algorithms. */ @@ -103,7 +93,11 @@ unsigned long gss_round_imp_reconnect(unsigned long expiry) /* * XXX make it visible of kernel and lgssd/lsvcgssd */ -#define GSSD_INTERFACE_VERSION (1) +enum { + GSSD_INTERFACE_VERSION_V1 = 1, + GSSD_INTERFACE_VERSION_V2 = 2, + GSSD_INTERFACE_VERSION = GSSD_INTERFACE_VERSION_V2, +}; #define PTLRPC_GSS_VERSION (1) @@ -116,22 +110,41 @@ enum ptlrpc_gss_proc { PTLRPC_GSS_PROC_ERR = 4, }; -enum ptlrpc_gss_svc { - PTLRPC_GSS_SVC_NONE = 1, - PTLRPC_GSS_SVC_INTEGRITY = 2, - PTLRPC_GSS_SVC_PRIVACY = 3, +enum ptlrpc_gss_tgt { + LUSTRE_GSS_TGT_MGS = 0, + LUSTRE_GSS_TGT_MDS = 1, + LUSTRE_GSS_TGT_OSS = 2, }; -enum ptlrpc_gss_tgt { - LUSTRE_GSS_TGT_MDS = 0, - LUSTRE_GSS_TGT_OSS = 1, +enum ptlrpc_gss_header_flags { + LUSTRE_GSS_PACK_BULK = 1, + LUSTRE_GSS_PACK_USER = 2, }; +static inline +__u32 import_to_gss_svc(struct obd_import *imp) +{ + const char *name = imp->imp_obd->obd_type->typ_name; + + if (!strcmp(name, LUSTRE_MGC_NAME)) + return LUSTRE_GSS_TGT_MGS; + if (!strcmp(name, LUSTRE_MDC_NAME) || + !strcmp(name, LUSTRE_LWP_NAME)) + return LUSTRE_GSS_TGT_MDS; + if (!strcmp(name, LUSTRE_OSC_NAME) || + !strcmp(name, LUSTRE_OSP_NAME)) + return LUSTRE_GSS_TGT_OSS; + + return 0; +} + /* * following 3 header must have the same size and offset */ struct gss_header { - __u32 gh_version; /* gss version */ + __u8 gh_version; /* gss version */ + __u8 gh_sp; /* sec part */ + __u16 gh_pad0; __u32 gh_flags; /* wrap flags */ __u32 gh_proc; /* proc */ __u32 gh_seq; /* sequence */ @@ -143,7 +156,9 @@ struct gss_header { }; struct gss_rep_header { - __u32 gh_version; + __u8 gh_version; + __u8 gh_sp; + __u16 gh_pad0; __u32 gh_flags; __u32 gh_proc; __u32 gh_major; @@ -155,7 +170,9 @@ struct gss_rep_header { }; struct gss_err_header { - __u32 gh_version; + __u8 gh_version; + __u8 gh_sp; + __u16 gh_pad0; __u32 gh_flags; __u32 gh_proc; __u32 gh_major; @@ -171,6 +188,7 @@ struct gss_err_header { * used later by server. */ struct gss_wire_ctx { + __u32 gw_flags; __u32 gw_proc; __u32 gw_seq; __u32 gw_svc; @@ -182,13 +200,21 @@ struct gss_wire_ctx { PTLRPC_GSS_MAX_HANDLE_SIZE) -#define GSS_SEQ_WIN (256) +static inline __u64 gss_handle_to_u64(rawobj_t *handle) +{ + if (handle->len != PTLRPC_GSS_MAX_HANDLE_SIZE) + return -1; + return *((__u64 *) handle->data); +} + +#define GSS_SEQ_WIN (2048) #define GSS_SEQ_WIN_MAIN GSS_SEQ_WIN -#define GSS_SEQ_WIN_BACK (64) -#define GSS_SEQ_REPACK_THRESHOLD (GSS_SEQ_WIN_MAIN / 2) +#define GSS_SEQ_WIN_BACK (128) +#define GSS_SEQ_REPACK_THRESHOLD (GSS_SEQ_WIN_MAIN / 2 + \ + GSS_SEQ_WIN_MAIN / 4) struct gss_svc_seq_data { - spinlock_t ssd_lock; + spinlock_t ssd_lock; /* * highest sequence number seen so far, for main and back window */ @@ -204,44 +230,128 @@ struct gss_svc_seq_data { }; struct gss_svc_ctx { - unsigned int gsc_usr_root:1, - gsc_usr_mds:1, - gsc_remote:1; + struct gss_ctx *gsc_mechctx; + struct gss_svc_seq_data gsc_seqdata; + rawobj_t gsc_rvs_hdl; + __u32 gsc_rvs_seq; uid_t gsc_uid; gid_t gsc_gid; uid_t gsc_mapped_uid; - rawobj_t gsc_rvs_hdl; - struct gss_svc_seq_data gsc_seqdata; - struct gss_ctx *gsc_mechctx; + unsigned int gsc_usr_root:1, + gsc_usr_mds:1, + gsc_usr_oss:1, + gsc_remote:1, + gsc_reverse:1; }; struct gss_svc_reqctx { - struct ptlrpc_svc_ctx src_base; - struct gss_wire_ctx src_wirectx; - struct gss_svc_ctx *src_ctx; - unsigned int src_init:1, - src_init_continue:1, - src_err_notify:1; - int src_reserve_len; + struct ptlrpc_svc_ctx src_base; + /* + * context + */ + struct gss_wire_ctx src_wirectx; + struct gss_svc_ctx *src_ctx; + /* + * record place of bulk_sec_desc in request/reply buffer + */ + struct ptlrpc_bulk_sec_desc *src_reqbsd; + int src_reqbsd_size; + struct ptlrpc_bulk_sec_desc *src_repbsd; + int src_repbsd_size; + /* + * flags + */ + unsigned int src_init:1, + src_init_continue:1, + src_err_notify:1; + int src_reserve_len; }; struct gss_cli_ctx { - struct ptlrpc_cli_ctx gc_base; - __u32 gc_flavor; - __u32 gc_proc; - __u32 gc_win; - atomic_t gc_seq; - rawobj_t gc_handle; - struct gss_ctx *gc_mechctx; + struct ptlrpc_cli_ctx gc_base; + __u32 gc_flavor; + __u32 gc_proc; + __u32 gc_win; + atomic_t gc_seq; + rawobj_t gc_handle; + struct gss_ctx *gc_mechctx; + /* handle for the buddy svc ctx */ + rawobj_t gc_svc_handle; +}; + +struct gss_cli_ctx_keyring { + struct gss_cli_ctx gck_base; + struct key *gck_key; + struct timer_list *gck_timer; }; struct gss_sec { - struct ptlrpc_sec gs_base; - struct gss_api_mech *gs_mech; - spinlock_t gs_lock; - __u64 gs_rvs_hdl; + struct ptlrpc_sec gs_base; + struct gss_api_mech *gs_mech; + spinlock_t gs_lock; + __u64 gs_rvs_hdl; }; +struct gss_sec_pipefs { + struct gss_sec gsp_base; + int gsp_chash_size; /* must be 2^n */ + struct hlist_head gsp_chash[0]; +}; + +/* + * FIXME cleanup the keyring upcall mutexes + */ +#define HAVE_KEYRING_UPCALL_SERIALIZED 1 + +struct gss_sec_keyring { + struct gss_sec gsk_base; + /* + * all contexts listed here. access is protected by sec spinlock. + */ + struct hlist_head gsk_clist; + /* + * specially point to root ctx (only one at a time). access is + * protected by sec spinlock. + */ + struct ptlrpc_cli_ctx *gsk_root_ctx; + /* + * specially serialize upcalls for root context. + */ + struct mutex gsk_root_uc_lock; + +#ifdef HAVE_KEYRING_UPCALL_SERIALIZED + struct mutex gsk_uc_lock; /* serialize upcalls */ +#endif +}; + +static inline struct gss_cli_ctx *ctx2gctx(struct ptlrpc_cli_ctx *ctx) +{ + return container_of(ctx, struct gss_cli_ctx, gc_base); +} + +static inline +struct gss_cli_ctx_keyring *ctx2gctx_keyring(struct ptlrpc_cli_ctx *ctx) +{ + return container_of(ctx2gctx(ctx), + struct gss_cli_ctx_keyring, gck_base); +} + +static inline struct gss_sec *sec2gsec(struct ptlrpc_sec *sec) +{ + return container_of(sec, struct gss_sec, gs_base); +} + +static inline struct gss_sec_pipefs *sec2gsec_pipefs(struct ptlrpc_sec *sec) +{ + return container_of(sec2gsec(sec), struct gss_sec_pipefs, gsp_base); +} + +static inline struct gss_sec_keyring *sec2gsec_keyring(struct ptlrpc_sec *sec) +{ + return container_of(sec2gsec(sec), struct gss_sec_keyring, gsk_base); +} + + #define GSS_CTX_INIT_MAX_LEN (1024) /* @@ -258,30 +368,105 @@ struct gss_svc_reqctx *gss_svc_ctx2reqctx(struct ptlrpc_svc_ctx *ctx) return container_of(ctx, struct gss_svc_reqctx, src_base); } +static inline +struct gss_svc_ctx *gss_svc_ctx2gssctx(struct ptlrpc_svc_ctx *ctx) +{ + LASSERT(ctx); + return gss_svc_ctx2reqctx(ctx)->src_ctx; +} + /* sec_gss.c */ -struct gss_header *gss_swab_header(struct lustre_msg *msg, int segment); +int gss_cli_ctx_match(struct ptlrpc_cli_ctx *ctx, struct vfs_cred *vcred); +int gss_cli_ctx_display(struct ptlrpc_cli_ctx *ctx, char *buf, int bufsize); +int gss_cli_ctx_sign(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req); +int gss_cli_ctx_verify(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req); +int gss_cli_ctx_seal(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req); +int gss_cli_ctx_unseal(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req); + +int gss_sec_install_rctx(struct obd_import *imp, struct ptlrpc_sec *sec, + struct ptlrpc_cli_ctx *ctx); +int gss_alloc_reqbuf(struct ptlrpc_sec *sec, struct ptlrpc_request *req, + int msgsize); +void gss_free_reqbuf(struct ptlrpc_sec *sec, struct ptlrpc_request *req); +int gss_alloc_repbuf(struct ptlrpc_sec *sec, struct ptlrpc_request *req, + int msgsize); +void gss_free_repbuf(struct ptlrpc_sec *sec, struct ptlrpc_request *req); +int gss_enlarge_reqbuf(struct ptlrpc_sec *sec, struct ptlrpc_request *req, + int segment, int newsize); + +int gss_svc_accept(struct ptlrpc_sec_policy *policy, + struct ptlrpc_request *req); +void gss_svc_invalidate_ctx(struct ptlrpc_svc_ctx *svc_ctx); +int gss_svc_alloc_rs(struct ptlrpc_request *req, int msglen); +int gss_svc_authorize(struct ptlrpc_request *req); +void gss_svc_free_rs(struct ptlrpc_reply_state *rs); +void gss_svc_free_ctx(struct ptlrpc_svc_ctx *ctx); + +int cli_ctx_expire(struct ptlrpc_cli_ctx *ctx); +int cli_ctx_check_death(struct ptlrpc_cli_ctx *ctx); + +int gss_copy_rvc_cli_ctx(struct ptlrpc_cli_ctx *cli_ctx, + struct ptlrpc_svc_ctx *svc_ctx); + +struct gss_header *gss_swab_header(struct lustre_msg *msg, int segment, + int swabbed); netobj_t *gss_swab_netobj(struct lustre_msg *msg, int segment); void gss_cli_ctx_uptodate(struct gss_cli_ctx *gctx); int gss_pack_err_notify(struct ptlrpc_request *req, __u32 major, __u32 minor); int gss_check_seq_num(struct gss_svc_seq_data *sd, __u32 seq_num, int set); +int gss_sec_create_common(struct gss_sec *gsec, + struct ptlrpc_sec_policy *policy, + struct obd_import *imp, + struct ptlrpc_svc_ctx *ctx, + struct sptlrpc_flavor *sf); +void gss_sec_destroy_common(struct gss_sec *gsec); +void gss_sec_kill(struct ptlrpc_sec *sec); + +int gss_cli_ctx_init_common(struct ptlrpc_sec *sec, + struct ptlrpc_cli_ctx *ctx, + struct ptlrpc_ctx_ops *ctxops, + struct vfs_cred *vcred); +int gss_cli_ctx_fini_common(struct ptlrpc_sec *sec, + struct ptlrpc_cli_ctx *ctx); + +void gss_cli_ctx_flags2str(unsigned long flags, char *buf, int bufsize); + +/* gss_keyring.c */ +#ifndef HAVE_GSS_KEYRING +static inline int __init gss_init_keyring(void) { return 0; } +static inline void __exit gss_exit_keyring(void) { return; } +#else +int __init gss_init_keyring(void); +void __exit gss_exit_keyring(void); +#endif + +/* gss_pipefs.c */ +#ifndef HAVE_GSS_PIPEFS +static inline int __init gss_init_pipefs(void) { return 0; } +static inline void __exit gss_exit_pipefs(void) { return; } +#else +int __init gss_init_pipefs(void); +void __exit gss_exit_pipefs(void); +#endif + /* gss_bulk.c */ +int gss_cli_prep_bulk(struct ptlrpc_request *req, + struct ptlrpc_bulk_desc *desc); int gss_cli_ctx_wrap_bulk(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req, struct ptlrpc_bulk_desc *desc); int gss_cli_ctx_unwrap_bulk(struct ptlrpc_cli_ctx *ctx, struct ptlrpc_request *req, struct ptlrpc_bulk_desc *desc); +int gss_svc_prep_bulk(struct ptlrpc_request *req, + struct ptlrpc_bulk_desc *desc); int gss_svc_unwrap_bulk(struct ptlrpc_request *req, struct ptlrpc_bulk_desc *desc); int gss_svc_wrap_bulk(struct ptlrpc_request *req, struct ptlrpc_bulk_desc *desc); -/* gss_mech_switch.c */ -int init_kerberos_module(void); -void cleanup_kerberos_module(void); - /* gss_generic_token.c */ int g_token_size(rawobj_t *mech, unsigned int body_size); void g_make_token_header(rawobj_t *mech, int body_size, unsigned char **buf); @@ -289,20 +474,21 @@ __u32 g_verify_token_header(rawobj_t *mech, int *body_size, unsigned char **buf_in, int toksize); -/* gss_upcall.c */ -int gss_do_ctx_init_rpc(char *buffer, unsigned long count); +/* gss_cli_upcall.c */ +int gss_do_ctx_init_rpc(char __user *buffer, unsigned long count); int gss_do_ctx_fini_rpc(struct gss_cli_ctx *gctx); -int gss_ctx_refresh_pipefs(struct ptlrpc_cli_ctx *ctx); -int gss_sec_upcall_init(struct gss_sec *gsec); -void gss_sec_upcall_cleanup(struct gss_sec *gsec); -int __init gss_init_upcall(void); -void __exit gss_exit_upcall(void); + +int __init gss_init_cli_upcall(void); +void gss_exit_cli_upcall(void); /* gss_svc_upcall.c */ __u64 gss_get_next_ctx_index(void); int gss_svc_upcall_install_rvs_ctx(struct obd_import *imp, struct gss_sec *gsec, struct gss_cli_ctx *gctx); +int gss_svc_upcall_expire_rvs_ctx(rawobj_t *handle); +int gss_svc_upcall_dup_handle(rawobj_t *handle, struct gss_svc_ctx *ctx); +int gss_svc_upcall_update_sequence(rawobj_t *handle, __u32 seq); int gss_svc_upcall_handle_init(struct ptlrpc_request *req, struct gss_svc_reqctx *grctx, struct gss_wire_ctx *gw, @@ -315,19 +501,32 @@ struct gss_svc_ctx *gss_svc_upcall_get_ctx(struct ptlrpc_request *req, void gss_svc_upcall_put_ctx(struct gss_svc_ctx *ctx); void gss_svc_upcall_destroy_ctx(struct gss_svc_ctx *ctx); -int __init gss_svc_init_upcall(void); -void __exit gss_svc_exit_upcall(void); +int __init gss_init_svc_upcall(void); +void gss_exit_svc_upcall(void); /* lproc_gss.c */ void gss_stat_oos_record_cli(int behind); void gss_stat_oos_record_svc(int phase, int replay); -int gss_init_lproc(void); + +int __init gss_init_lproc(void); void gss_exit_lproc(void); +/* gss_null_mech.c */ +int __init init_null_module(void); +void cleanup_null_module(void); + /* gss_krb5_mech.c */ int __init init_kerberos_module(void); -void __exit cleanup_kerberos_module(void); +void cleanup_kerberos_module(void); +/* gss_sk_mech.c */ +#ifdef HAVE_OPENSSL_SSK +int __init init_sk_module(void); +void cleanup_sk_module(void); +#else +static inline int init_sk_module(void) { return 0; } +static inline void cleanup_sk_module(void) { return; } +#endif /* HAVE_OPENSSL_SSK */ /* debug */ static inline @@ -338,14 +537,14 @@ void __dbg_memdump(char *name, void *ptr, int size) OBD_ALLOC(buf, bufsize); if (!buf) { - printk("DUMP ERROR: can't alloc %d bytes\n", bufsize); + CDEBUG(D_ERROR, "DUMP ERROR: can't alloc %d bytes\n", bufsize); return; } for (i = 0; i < size; i++) sprintf(&buf[i+i], "%02x", (__u8) p[i]); buf[size + size] = '\0'; - printk("DUMP %s@%p(%d): %s\n", name, ptr, size, buf); + LCONSOLE_INFO("DUMP %s@%p(%d): %s\n", name, ptr, size, buf); OBD_FREE(buf, bufsize); }