__u64 rq_xid;
struct list_head rq_replay_list;
- struct ptlrpc_cred *rq_cred; /* client side credit */
- struct ptlrpc_svcsec *rq_svcsec; /* server side security */
- /* XXX temporarily put here XXX */
- void *rq_sec_svcdata; /* server security data */
- unsigned int rq_remote_realm;/* from remote realm */
- uid_t rq_auth_uid;
- uid_t rq_mapped_uid;
+ struct ptlrpc_cred *rq_cred; /* client side */
+ struct ptlrpc_svcsec *rq_svcsec; /* server side */
+ /* flavor of request, on both client & server */
+ __u32 rq_req_secflvr;
+ /* server side security tracking data, need cleanup */
+ void *rq_svcsec_data; /* server security data */
+ unsigned int rq_remote_realm:1, /* from remote realm */
+ rq_auth_usr_mds:1, /* auth as mds svc cred */
+ rq_auth_usr_oss:1; /* auth as oss svc cred */
+ uid_t rq_auth_uid;
+ uid_t rq_mapped_uid;
char *rq_reqbuf; /* backend request buffer */
int rq_reqbuf_len; /* backend request buffer length */
#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);
+
+
+#ifdef __KERNEL__
+
/* forward declaration */
struct obd_import;
struct ptlrpc_request;
struct ptlrpc_sec;
struct ptlrpc_secops;
-#define PTLRPC_SEC_MAX_FLAVORS (4)
-
-typedef struct ptlrpcs_flavor_s {
- __u32 flavor;
- __u32 subflavor;
-} ptlrpcs_flavor_t;
typedef struct {
struct list_head list;
- ptlrpcs_flavor_t sec;
+ __u32 flavor;
} deny_sec_t;
-enum ptlrpcs_security_type {
- PTLRPC_SEC_TYPE_NONE = 0, /* no security */
- PTLRPC_SEC_TYPE_AUTH = 1, /* authentication */
- PTLRPC_SEC_TYPE_PRIV = 2, /* privacy */
-};
-
/*
* 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;
};
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 {
};
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_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);
};
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_CREDCACHE_NR 8
#define PTLRPC_CREDCACHE_MASK (PTLRPC_CREDCACHE_NR - 1)
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);
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);
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);
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)
{
- int rc = 0;
- deny_sec_t *p_deny_sec = NULL;
+ 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;
-
- if (strcmp(sec, "null") == 0) {
- p_deny_sec->sec.flavor = PTLRPC_SEC_NULL;
- p_deny_sec->sec.subflavor = PTLRPC_SEC_NULL;
- }else if (strcmp(sec, "krb5i") == 0) {
- p_deny_sec->sec.flavor = PTLRPC_SEC_GSS;
- p_deny_sec->sec.subflavor = PTLRPC_SEC_GSS_KRB5I;
- }else if (strcmp(sec, "krb5p") == 0) {
- p_deny_sec->sec.flavor = PTLRPC_SEC_GSS;
- p_deny_sec->sec.subflavor = PTLRPC_SEC_GSS_KRB5P;
- }else{
- CERROR("unrecognized security type %s\n", (char*) sec);
- GOTO(out, rc = -EINVAL);
+ 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);
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,
#define SVC_LOGIN 4
#define SVC_LOGOUT 5
-/* FIXME
- * this should be a gss internal structure. fix these when we
- * sort out the flavor issues.
- */
-
-typedef struct rawobj_s {
- __u32 len;
- __u8 *data;
-} rawobj_t;
-
-/* on-the-wire gss cred: */
-struct rpc_gss_wire_cred {
- __u32 gc_v; /* version */
- __u32 gc_proc; /* control procedure */
- __u32 gc_seq; /* sequence number */
- __u32 gc_svc; /* service */
- rawobj_t gc_ctx; /* context handle */
-};
-
-struct gss_svc_data {
- __u32 subflavor; /* XXX */
- /* decoded gss client cred: */
- struct rpc_gss_wire_cred clcred;
- /* internal used status */
- unsigned int is_init:1,
- is_init_continue:1,
- is_err_notify:1,
- is_fini:1;
- int reserve_len;
-};
-
int svcsec_register(struct ptlrpc_svcsec *ss);
int svcsec_unregister(struct ptlrpc_svcsec *ss);
int svcsec_accept(struct ptlrpc_request *req, enum ptlrpcs_error *res);
int svcsec_null_init(void);
int svcsec_null_exit(void);
+#endif /* __KERNEL__ */
+
#endif /* __LINUX_SEC_H_ */
/* security flavors */
__u32 cl_sec_flavor;
- __u32 cl_sec_subflavor;
+ unsigned long cl_sec_flags;
//struct llog_canceld_ctxt *cl_llcd; /* it's included by obd_llog_ctxt */
void *cl_llcd_offset;
* EPERM found, refuse
*/
-static int check_deny_list(struct list_head *head, ptlrpcs_flavor_t *p_flavor)
+static int check_deny_list(struct list_head *head, __u32 flavor)
{
deny_sec_t *p_deny_sec = NULL;
deny_sec_t *n_deny_sec = NULL;
list_for_each_entry_safe(p_deny_sec, n_deny_sec, head, list) {
- if ((p_deny_sec->sec.flavor == p_flavor->flavor) &&
- (p_deny_sec->sec.subflavor == p_flavor->subflavor))
+ if (p_deny_sec->flavor == flavor)
return -EPERM;
}
return 0;
int target_check_deny_sec(struct obd_device *target, struct ptlrpc_request *req)
{
- struct gss_svc_data *svcdata;
- ptlrpcs_flavor_t flavor;
+ __u32 flavor;
int rc = 0;
- /* XXX hacking */
- svcdata = (struct gss_svc_data *) req->rq_sec_svcdata;
- if (svcdata == NULL) {
- flavor.flavor = PTLRPC_SEC_NULL;
- flavor.subflavor = 0;
- } else {
- flavor.flavor = PTLRPC_SEC_GSS;
- flavor.subflavor = svcdata->subflavor;
- }
+ flavor = req->rq_req_secflvr;
if (!strcmp(target->obd_type->typ_name, LUSTRE_MDS_NAME)) {
spin_lock(&target->u.mds.mds_denylist_lock);
- rc = check_deny_list(&target->u.mds.mds_denylist, &flavor);
+ rc = check_deny_list(&target->u.mds.mds_denylist, flavor);
spin_unlock(&target->u.mds.mds_denylist_lock);
} else if (!strcmp(target->obd_type->typ_name, "obdfilter")) {
spin_lock(&target->u.filter.fo_denylist_lock);
- rc = check_deny_list(&target->u.filter.fo_denylist, &flavor);
+ rc = check_deny_list(&target->u.filter.fo_denylist, flavor);
spin_unlock(&target->u.filter.fo_denylist_lock);
}
memcpy(copy_reqmsg, orig_req->rq_reqmsg, orig_req->rq_reqlen);
/* the copied req takes over the reply state and security data */
orig_req->rq_reply_state = NULL;
- orig_req->rq_sec_svcdata = NULL;
+ orig_req->rq_svcsec_data = NULL;
copy_req->rq_reqmsg = copy_reqmsg;
class_export_get(copy_req->rq_export);
struct ll_ra_info ll_ra_info;
- unsigned int ll_remote; /* remote client? */
+ unsigned int ll_remote; /* remote client? */
/* times spent waiting for locks in each call site. These are
* all protected by the ll_lock */
int ll_dentry_to_fh(struct dentry *, __u32 *datap, int *lenp, int need_parent);
int null_if_equal(struct ldlm_lock *lock, void *data);
int ll_process_config_update(struct ll_sb_info *sbi, int clean);
+int ll_show_options(struct seq_file *m, struct vfsmount *mnt);
int ll_flush_cred(struct inode *inode);
/* llite/special.c */
#include <linux/types.h>
#include <linux/random.h>
#include <linux/version.h>
+#include <linux/seq_file.h>
#include <linux/lustre_lite.h>
#include <linux/lustre_ha.h>
RETURN(rc);
}
+int ll_show_options(struct seq_file *m, struct vfsmount *mnt)
+{
+ struct ll_sb_info *sbi = ll_s2sbi(mnt->mnt_sb);
+ struct lustre_mount_data *lmd = sbi->ll_lmd;
+
+ if (lmd) {
+ seq_printf(m, ",mds_sec=%s,oss_sec=%s",
+ lmd->lmd_mds_security, lmd->lmd_oss_security);
+ }
+ seq_printf(m, ",%s", sbi->ll_remote ? "remote" : "local");
+ if (sbi->ll_remote && lmd) {
+ seq_printf(m, ",nllu=%u:%u", lmd->lmd_nllu, lmd->lmd_nllg);
+ }
+
+ return 0;
+}
+
int ll_get_fid(struct obd_export *exp, struct lustre_id *idp,
char *filename, struct lustre_id *ret)
{
.put_super = lustre_put_super,
.statfs = ll_statfs,
.umount_begin = ll_umount_begin,
- .umount_lustre = ll_umount_lustre
+ .umount_lustre = ll_umount_lustre,
+ .show_options = ll_show_options,
};
struct file_system_type lustre_lite_fs_type = {
/* maybe this could be default */
if ((keylen == strlen("sec") && strcmp(key, "sec") == 0) ||
+ (keylen == strlen("sec_flags") && strcmp(key, "sec_flags") == 0) ||
(keylen == strlen("nllu") && strcmp(key, "nllu") == 0)) {
struct obd_export *exp;
int rc = 0, err, i;
} else if (KEY_IS("unlinked") || KEY_IS("unrecovery")) {
if (vallen != 0)
RETURN(-EINVAL);
- } else if (KEY_IS("sec")) {
+ } else if (KEY_IS("sec") || KEY_IS("sec_flags")) {
struct lov_tgt_desc *tgt;
struct obd_export *exp;
int rc = 0, err, i;
memcmp(key, "sec", keylen) == 0) {
struct client_obd *cli = &exp->exp_obd->u.cli;
- if (vallen == strlen("null") &&
- memcmp(val, "null", vallen) == 0) {
- cli->cl_sec_flavor = PTLRPC_SEC_NULL;
- cli->cl_sec_subflavor = 0;
- RETURN(0);
- }
- if (vallen == strlen("krb5i") &&
- memcmp(val, "krb5i", vallen) == 0) {
- cli->cl_sec_flavor = PTLRPC_SEC_GSS;
- cli->cl_sec_subflavor = PTLRPC_SEC_GSS_KRB5I;
- RETURN(0);
- }
- if (vallen == strlen("krb5p") &&
- memcmp(val, "krb5p", vallen) == 0) {
- cli->cl_sec_flavor = PTLRPC_SEC_GSS;
- cli->cl_sec_subflavor = PTLRPC_SEC_GSS_KRB5P;
- RETURN(0);
+ cli->cl_sec_flavor = ptlrpcs_name2flavor(val);
+ if (cli->cl_sec_flavor == PTLRPCS_FLVR_INVALID) {
+ CERROR("unrecognized security type %s\n", (char*) val);
+ RETURN(-EINVAL);
}
- CERROR("unrecognized security type %s\n", (char*) val);
- rc = -EINVAL;
+
+ RETURN(0);
+ } else if (keylen == strlen("sec_flags") &&
+ memcmp(key, "sec_flags", keylen) == 0) {
+ struct client_obd *cli = &exp->exp_obd->u.cli;
+
+ cli->cl_sec_flags = *((unsigned long *) val);
+ RETURN(0);
} else if (keylen == strlen("flush_cred") &&
memcmp(key, "flush_cred", keylen) == 0) {
struct client_obd *cli = &exp->exp_obd->u.cli;
if (cli->cl_import)
ptlrpcs_import_flush_creds(cli->cl_import,
*((uid_t *) val));
- rc = 0;
+ RETURN(0);
} else if (keylen == strlen("async") && memcmp(key, "async", keylen) == 0) {
struct client_obd *cl = &exp->exp_obd->u.cli;
if (vallen != sizeof(int))
OBD_FREE(p_deny_sec, sizeof(*p_deny_sec));
}
spin_unlock(&mds->mds_denylist_lock);
- if(mds->mds_mds_sec)
- OBD_FREE(mds->mds_mds_sec, strlen(mds->mds_mds_sec) + 1);
- if(mds->mds_ost_sec)
- OBD_FREE(mds->mds_ost_sec, strlen(mds->mds_ost_sec) + 1);
RETURN(0);
}
static int set_security(const char *value, char **sec)
{
- int rc = 0;
-
- if (!strcmp(value, "null") ||
- !strcmp(value, "krb5i") ||
- !strcmp(value, "krb5p")) {
- OBD_ALLOC(*sec, strlen(value) + 1);
- if(!*sec)
- RETURN(-ENOMEM);
- memcpy(*sec, value, strlen(value) + 1);
- } else {
- CERROR("Unrecognized value, force use NULL\n");
- rc = -EINVAL;
+ if (!strcmp(value, "null"))
+ *sec = "null";
+ else if (!strcmp(value, "krb5i"))
+ *sec = "krb5i";
+ else if (!strcmp(value, "krb5p"))
+ *sec = "krb5p";
+ else {
+ CERROR("Unrecognized security flavor %s\n", value);
+ return -EINVAL;
}
- return rc;
+ return 0;
}
static int mds_process_config(struct obd_device *obd, obd_count len, void *buf)
}
break;
}
- default: {
+ default:
CERROR("Unknown command: %d\n", lcfg->lcfg_command);
GOTO(out, rc = -EINVAL);
-
- }
}
out:
RETURN(rc);
#include <linux/obd_support.h>
#include <linux/lustre_lib.h>
+#include <linux/lustre_sec.h>
#include <linux/lustre_ucache.h>
#include "mds_internal.h"
* root could set any group_info if we allowed setgroups, while
* normal user only could 'reduce' their group members -- which
* is somewhat expensive.
+ *
+ * authenticated as mds user (using mds service credential) could
+ * bypass all checkings.
*/
int mds_init_ucred(struct lvfs_ucred *ucred,
struct ptlrpc_request *req,
LASSERT(rsd);
LASSERT(rsd->rsd_ngroups <= LUSTRE_MAX_GROUPS);
- /* XXX We'v no dedicated bits indicating whether GSS is used,
- * and authenticated/mapped uid is valid. currently we suppose
- * gss must initialize rq_sec_svcdata.
- */
- if (req->rq_sec_svcdata && req->rq_auth_uid == -1) {
+ if (SEC_FLAVOR_MAJOR(req->rq_req_secflvr) == PTLRPCS_FLVR_MAJOR_GSS &&
+ (SEC_FLAVOR_SVC(req->rq_req_secflvr) == PTLRPCS_SVC_AUTH ||
+ SEC_FLAVOR_SVC(req->rq_req_secflvr) == PTLRPCS_SVC_PRIV))
+ strong_sec = 1;
+ else
+ strong_sec = 0;
+
+ LASSERT(!(req->rq_remote_realm && !strong_sec));
+
+ if (strong_sec && req->rq_auth_uid == -1) {
CWARN("user not authenticated, deny access\n");
RETURN(-EPERM);
}
- strong_sec = (req->rq_auth_uid != -1);
- LASSERT(!(req->rq_remote_realm && !strong_sec));
+ if (req->rq_auth_usr_mds)
+ goto get_lsd;
- /* if we use strong authentication for a local client, we
- * expect the uid which client claimed is true.
+ /* if we use strong authentication, we expect the uid which
+ * client claimed is true.
*/
- if (!med->med_remote && strong_sec &&
- req->rq_auth_uid != rsd->rsd_uid) {
- CWARN("nid "LPX64": UID %u was authenticated while client "
- "claimed %u, enforce to be %u\n",
- peernid, req->rq_auth_uid, rsd->rsd_uid,
- req->rq_auth_uid);
- if (rsd->rsd_uid != rsd->rsd_fsuid)
- rsd->rsd_uid = req->rq_auth_uid;
- else
- rsd->rsd_uid = rsd->rsd_fsuid = req->rq_auth_uid;
- }
+ if (strong_sec) {
+ if (!med->med_remote) {
+ if (req->rq_auth_uid != rsd->rsd_uid) {
+ CERROR("local client "LPU64": auth uid %u "
+ "while client claim %u:%u/%u:%u\n",
+ peernid, req->rq_auth_uid,
+ rsd->rsd_uid, rsd->rsd_gid,
+ rsd->rsd_fsuid, rsd->rsd_fsgid);
+ RETURN(-EPERM);
+ }
+ } else {
+ if (req->rq_mapped_uid == MDS_IDMAP_NOTFOUND) {
+ CWARN("no mapping found, deny\n");
+ RETURN(-EPERM);
+ }
- if (med->med_remote) {
- int rc;
+ if (mds_req_secdesc_do_map(med, rsd))
+ RETURN(-EPERM);
- if (req->rq_mapped_uid == MDS_IDMAP_NOTFOUND) {
- CWARN("no mapping found, deny\n");
- RETURN(-EPERM);
+ if (req->rq_mapped_uid != rsd->rsd_uid) {
+ CERROR("remote client "LPU64": auth uid %u "
+ "while client claim %u:%u/%u:%u\n",
+ peernid, req->rq_auth_uid,
+ rsd->rsd_uid, rsd->rsd_gid,
+ rsd->rsd_fsuid, rsd->rsd_fsgid);
+ }
}
-
- rc = mds_req_secdesc_do_map(med, rsd);
- if (rc)
- RETURN(rc);
}
+get_lsd:
/* now lsd come into play */
ucred->luc_ginfo = NULL;
ucred->luc_lsd = lsd = mds_get_lsd(rsd->rsd_uid);
RETURN(-EPERM);
}
+ lsd_perms = mds_lsd_get_perms(lsd, med->med_remote, 0, peernid);
+
+ if (req->rq_auth_usr_mds)
+ goto squash_root;
+
/* find out the setuid/setgid attempt */
setuid = (rsd->rsd_uid != rsd->rsd_fsuid);
setgid = (rsd->rsd_gid != rsd->rsd_fsgid ||
rsd->rsd_gid != lsd->lsd_gid);
- lsd_perms = mds_lsd_get_perms(lsd, med->med_remote, 0, peernid);
-
/* check permission of setuid */
if (setuid && !(lsd_perms & LSD_PERM_SETUID)) {
CWARN("mds blocked setuid attempt (%u -> %u) from "LPU64"\n",
/* check permission of setgid */
if (setgid && !(lsd_perms & LSD_PERM_SETGID)) {
- CWARN("mds blocked setgid attempt (%u/%u -> %u) from "LPU64"\n",
- rsd->rsd_gid, rsd->rsd_fsgid, lsd->lsd_gid, peernid);
+ CWARN("mds blocked setgid attempt (%u:%u/%u:%u -> %u) from "
+ LPU64"\n", rsd->rsd_uid, rsd->rsd_gid,
+ rsd->rsd_fsuid, rsd->rsd_fsgid, lsd->lsd_gid, peernid);
RETURN(-EPERM);
}
+squash_root:
root_squashed = mds_squash_root(mds, rsd, &peernid);
/* remove privilege for non-root user */
#include <linux/lustre_lib.h>
#include <linux/lustre_fsfilt.h>
#include <linux/lustre_lite.h>
+#include <linux/lustre_sec.h>
#include <asm/div64.h>
#include "mds_internal.h"
{
struct mds_obd *mds = &obd->u.mds;
struct lustre_handle conn = {0};
+ unsigned long sec_flags = PTLRPC_SEC_FL_MDS;
int rc, value;
__u32 valsize;
ENTRY;
GOTO(err_reg, rc);
}
+ rc = obd_set_info(mds->mds_md_exp, strlen("sec_flags"), "sec_flags",
+ sizeof(sec_flags), &sec_flags);
+ if (rc)
+ GOTO(err_reg, rc);
+
mds->mds_md_connected = 1;
up(&mds->mds_md_sem);
RETURN(0);
#include <linux/obd_lov.h>
#include <linux/lustre_lib.h>
#include <linux/lustre_fsfilt.h>
+#include <linux/lustre_sec.h>
#include "mds_internal.h"
{
struct mds_obd *mds = &obd->u.mds;
struct lustre_handle conn = { 0 };
+ unsigned long sec_flags = PTLRPC_SEC_FL_MDS;
int i, rc = 0;
ENTRY;
if (mds->mds_ost_sec) {
rc = obd_set_info(mds->mds_dt_obd->obd_self_export,
strlen("sec"), "sec",
- strlen(mds->mds_ost_sec),
- mds->mds_ost_sec);
+ strlen(mds->mds_ost_sec), mds->mds_ost_sec);
if (rc) {
mds->mds_dt_obd = ERR_PTR(rc);
RETURN(rc);
}
}
+ rc = obd_set_info(mds->mds_dt_obd->obd_self_export,
+ strlen("sec_flags"), "sec_flags",
+ sizeof(sec_flags), &sec_flags);
+ if (rc) {
+ mds->mds_dt_obd = ERR_PTR(rc);
+ RETURN(rc);
+ }
+
CDEBUG(D_HA, "obd: %s osc: %s lov_name: %s\n",
obd->obd_name, mds->mds_dt_obd->obd_name, lov_name);
memcmp(key, "sec", keylen) == 0) {
struct client_obd *cli = &exp->exp_obd->u.cli;
- if (vallen == strlen("null") &&
- memcmp(val, "null", vallen) == 0) {
- cli->cl_sec_flavor = PTLRPC_SEC_NULL;
- cli->cl_sec_subflavor = 0;
- RETURN(0);
- }
- if (vallen == strlen("krb5i") &&
- memcmp(val, "krb5i", vallen) == 0) {
- cli->cl_sec_flavor = PTLRPC_SEC_GSS;
- cli->cl_sec_subflavor = PTLRPC_SEC_GSS_KRB5I;
- RETURN(0);
- }
- if (vallen == strlen("krb5p") &&
- memcmp(val, "krb5p", vallen) == 0) {
- cli->cl_sec_flavor = PTLRPC_SEC_GSS;
- cli->cl_sec_subflavor = PTLRPC_SEC_GSS_KRB5P;
- RETURN(0);
+ cli->cl_sec_flavor = ptlrpcs_name2flavor(val);
+ if (cli->cl_sec_flavor == PTLRPCS_FLVR_INVALID) {
+ CERROR("unrecognized security flavor %s\n", (char*) val);
+ RETURN(-EINVAL);
}
- CERROR("unrecognized security type %s\n", (char*) val);
- RETURN(-EINVAL);
+
+ RETURN(0);
+ }
+
+ if (keylen == strlen("sec_flags") &&
+ memcmp(key, "sec_flags", keylen) == 0) {
+ struct client_obd *cli = &exp->exp_obd->u.cli;
+
+ cli->cl_sec_flags = *((unsigned long *) val);
+ RETURN(0);
}
if (keylen == strlen("flush_cred") &&
if (request->rq_ptlrpcs_err)
GOTO(out_cred, rc = -EPERM);
+ /* set default sec flavor for this req. in the future we might need
+ * increase security strengh, e.g. AUTH -> PRIV
+ */
+ request->rq_req_secflvr = imp->imp_sec->ps_flavor;
+
rc = lustre_pack_request(request, count, lengths, bufs);
if (rc) {
CERROR("cannot pack request %d\n", rc);
request->rq_auth_uid = -1;
request->rq_mapped_uid = -1;
request->rq_remote_realm = 0;
+ request->rq_auth_usr_mds = 0;
+ request->rq_auth_usr_oss = 0;
secrc = svcsec_accept(request, &sec_err);
switch(secrc) {
struct ptlrpc_sec;
struct ptlrpc_cred;
-/* rawobj stuff */
-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);
-int rawobj_dup(rawobj_t *dest, rawobj_t *src);
-int rawobj_serialize(rawobj_t *obj, __u32 **buf, __u32 *buflen);
-int rawobj_extract(rawobj_t *obj, __u32 **buf, __u32 *buflen);
-int rawobj_extract_local(rawobj_t *obj, __u32 **buf, __u32 *buflen);
+/*
+ * rawobj stuff
+ */
+typedef struct rawobj_s {
+ __u32 len;
+ __u8 *data;
+} rawobj_t;
typedef struct rawobj_buf_s {
__u32 dataoff;
__u8 *buf;
} rawobj_buf_t;
+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);
+int rawobj_dup(rawobj_t *dest, rawobj_t *src);
+int rawobj_serialize(rawobj_t *obj, __u32 **buf, __u32 *buflen);
+int rawobj_extract(rawobj_t *obj, __u32 **buf, __u32 *buflen);
+int rawobj_extract_local(rawobj_t *obj, __u32 **buf, __u32 *buflen);
+
/*
* mark of the interface between kernel and lgssd/lsvcgssd
*/
#define LUSTRE_GSS_SVC_MDS 0
#define LUSTRE_GSS_SVC_OSS 1
+
+/* on-the-wire gss cred: */
+struct rpc_gss_wire_cred {
+ __u32 gc_v; /* version */
+ __u32 gc_proc; /* control procedure */
+ __u32 gc_seq; /* sequence number */
+ __u32 gc_svc; /* service */
+ rawobj_t gc_ctx; /* context handle */
+};
+
+struct gss_svc_data {
+ /* decoded gss client cred: */
+ struct rpc_gss_wire_cred clcred;
+ /* internal used status */
+ unsigned int is_init:1,
+ is_init_continue:1,
+ is_err_notify:1,
+ is_fini:1;
+ int reserve_len;
+};
+
/*
* data types in gss header
*/
struct gss_cred {
struct ptlrpc_cred gc_base;
- ptlrpcs_flavor_t gc_flavor;
+ __u32 gc_flavor;
struct gss_cl_ctx *gc_ctx;
};
static struct subflavor_desc gss_kerberos_sfs[] = {
{
- .subflavor = PTLRPC_SEC_GSS_KRB5,
+ .subflavor = PTLRPCS_SUBFLVR_KRB5,
.qop = 0,
- .service = PTLRPC_SEC_TYPE_NONE,
+ .service = PTLRPCS_SVC_NONE,
.name = "krb5"
},
{
- .subflavor = PTLRPC_SEC_GSS_KRB5I,
+ .subflavor = PTLRPCS_SUBFLVR_KRB5I,
.qop = 0,
- .service = PTLRPC_SEC_TYPE_AUTH,
+ .service = PTLRPCS_SVC_AUTH,
.name = "krb5i"
},
{
- .subflavor = PTLRPC_SEC_GSS_KRB5P,
+ .subflavor = PTLRPCS_SUBFLVR_KRB5P,
.qop = 0,
- .service = PTLRPC_SEC_TYPE_PRIV,
+ .service = PTLRPCS_SVC_PRIV,
.name = "krb5p"
}
};
#include "gss_internal.h"
#include "gss_api.h"
-#define GSS_CREDCACHE_EXPIRE (60) /* 1 minute */
+#define GSS_CREDCACHE_EXPIRE (30 * 60) /* 30 minute */
+/* not used now */
+#if 0
#define GSS_CRED_EXPIRE (8 * 60 * 60) /* 8 hours */
#define GSS_CRED_SIGN_SIZE (1024)
#define GSS_CRED_VERIFY_SIZE (56)
+#endif
#define LUSTRE_PIPEDIR "/lustre"
/* security wire hdr */
hdr = buf_to_sec_hdr(buf);
- hdr->flavor = cpu_to_le32(PTLRPC_SEC_GSS);
- hdr->sectype = cpu_to_le32(PTLRPC_SEC_TYPE_NONE);
+ hdr->flavor = cpu_to_le32(PTLRPCS_FLVR_GSS_NONE);
hdr->msg_len = cpu_to_le32(lmsg_size);
hdr->sec_len = cpu_to_le32(8 * 4 + token_size);
/* gss hdr */
*p++ = cpu_to_le32(PTLRPC_SEC_GSS_VERSION); /* gss version */
- *p++ = cpu_to_le32(PTLRPC_SEC_GSS_KRB5I); /* subflavor */
- *p++ = cpu_to_le32(PTLRPC_GSS_PROC_INIT); /* proc */
+ *p++ = cpu_to_le32(PTLRPCS_FLVR_KRB5I); /* subflavor */
+ *p++ = cpu_to_le32(PTLRPCS_GSS_PROC_INIT); /* proc */
*p++ = cpu_to_le32(0); /* seq */
- *p++ = cpu_to_le32(PTLRPC_GSS_SVC_NONE); /* service */
+ *p++ = cpu_to_le32(PTLRPCS_GSS_SVC_NONE); /* service */
*p++ = cpu_to_le32(0); /* context handle */
/* plus lustre svc type */
}
hdr->flavor = le32_to_cpu(hdr->flavor);
- hdr->sectype = le32_to_cpu(hdr->sectype);
hdr->msg_len = le32_to_cpu(hdr->msg_len);
hdr->sec_len = le32_to_cpu(hdr->sec_len);
sec_len = le32_to_cpu(p[3]);
/* sanity checks */
- if (hdr->flavor != PTLRPC_SEC_GSS ||
- hdr->sectype != PTLRPC_SEC_TYPE_NONE) {
+ if (hdr->flavor != PTLRPCS_FLVR_GSS_NONE) {
CERROR("unexpected reply\n");
return -EINVAL;
}
spin_unlock(&ctx->gc_seq_lock);
*vp++ = cpu_to_le32(PTLRPC_SEC_GSS_VERSION); /* version */
- *vp++ = cpu_to_le32(PTLRPC_SEC_GSS_KRB5I); /* subflavor */
+ *vp++ = cpu_to_le32(PTLRPCS_FLVR_KRB5I); /* subflavor */
*vp++ = cpu_to_le32(ctx->gc_proc); /* proc */
*vp++ = cpu_to_le32(seqnum); /* seq */
- *vp++ = cpu_to_le32(PTLRPC_GSS_SVC_INTEGRITY); /* service */
+ *vp++ = cpu_to_le32(PTLRPCS_GSS_SVC_INTEGRITY); /* service */
vlen -= 5 * 4;
if (rawobj_serialize(&ctx->gc_wire_ctx, &vp, &vlen)) {
vlen -= 3 * 4;
switch (proc) {
- case PTLRPC_GSS_PROC_DATA:
+ case PTLRPCS_GSS_PROC_DATA:
seq = le32_to_cpu(*vp++);
svc = le32_to_cpu(*vp++);
- if (svc != PTLRPC_GSS_SVC_INTEGRITY) {
+ if (svc != PTLRPCS_GSS_SVC_INTEGRITY) {
CERROR("Unknown svc %d\n", svc);
RETURN(-EPROTO);
}
proc_data_out:
gss_put_ctx(ctx);
break;
- case PTLRPC_GSS_PROC_ERR:
+ case PTLRPCS_GSS_PROC_ERR:
major = le32_to_cpu(*vp++);
minor = le32_to_cpu(*vp++);
/* server return NO_CONTEXT might be caused by context expire
spin_unlock(&ctx->gc_seq_lock);
*vp++ = cpu_to_le32(PTLRPC_SEC_GSS_VERSION); /* version */
- *vp++ = cpu_to_le32(PTLRPC_SEC_GSS_KRB5P); /* subflavor */
+ *vp++ = cpu_to_le32(PTLRPCS_FLVR_KRB5P); /* subflavor */
*vp++ = cpu_to_le32(ctx->gc_proc); /* proc */
*vp++ = cpu_to_le32(seqnum); /* seq */
- *vp++ = cpu_to_le32(PTLRPC_GSS_SVC_PRIVACY); /* service */
+ *vp++ = cpu_to_le32(PTLRPCS_GSS_SVC_PRIVACY); /* service */
vlen -= 5 * 4;
if (rawobj_serialize(&ctx->gc_wire_ctx, &vp, &vlen)) {
vlen -= 5 * 4;
switch (proc) {
- case PTLRPC_GSS_PROC_DATA:
- if (svc != PTLRPC_GSS_SVC_PRIVACY) {
+ case PTLRPCS_GSS_PROC_DATA:
+ if (svc != PTLRPCS_GSS_SVC_PRIVACY) {
CERROR("Unknown svc %d\n", svc);
RETURN(-EPROTO);
}
atomic_inc(&cred->pc_refcount);
gcred = container_of(cred, struct gss_cred, gc_base);
- gcred->gc_ctx->gc_proc = PTLRPC_GSS_PROC_DESTROY;
+ gcred->gc_ctx->gc_proc = PTLRPCS_GSS_PROC_DESTROY;
CDEBUG(D_SEC, "client destroy gss cred %p(%u@%s)\n",
gcred, cred->pc_uid, imp->imp_target_uuid.uuid);
lmsg_size = lustre_msg_size(0, NULL);
+ req.rq_req_secflvr = cred->pc_sec->ps_flavor;
+ req.rq_cred = cred;
req.rq_reqbuf_len = sizeof(*hdr) + lmsg_size +
- ptlrpcs_est_req_payload(cred->pc_sec, lmsg_size);
+ ptlrpcs_est_req_payload(&req, lmsg_size);
OBD_ALLOC(req.rq_reqbuf, req.rq_reqbuf_len);
if (!req.rq_reqbuf) {
/* wire hdr */
hdr = buf_to_sec_hdr(req.rq_reqbuf);
- hdr->flavor = cpu_to_le32(PTLRPC_SEC_GSS);
- hdr->sectype = cpu_to_le32(PTLRPC_SEC_TYPE_AUTH);
+ hdr->flavor = cpu_to_le32(PTLRPCS_FLVR_GSS_AUTH);
hdr->msg_len = cpu_to_le32(lmsg_size);
hdr->sec_len = cpu_to_le32(0);
*********************************************/
static
-struct ptlrpc_sec* gss_create_sec(ptlrpcs_flavor_t *flavor,
+struct ptlrpc_sec* gss_create_sec(__u32 flavor,
const char *pipe_dir,
void *pipe_data)
{
#ifdef __KERNEL__
char *pos;
int pipepath_len;
+ uid_t save_uid;
#endif
ENTRY;
- LASSERT(flavor->flavor == PTLRPC_SEC_GSS);
+ LASSERT(SEC_FLAVOR_MAJOR(flavor) == PTLRPCS_FLVR_MAJOR_GSS);
OBD_ALLOC(gsec, sizeof(*gsec));
if (!gsec) {
RETURN(NULL);
}
- gsec->gs_mech = kgss_subflavor_to_mech(flavor->subflavor);
+ gsec->gs_mech = kgss_subflavor_to_mech(SEC_FLAVOR_SUB(flavor));
if (!gsec->gs_mech) {
- CERROR("subflavor %d not found\n", flavor->subflavor);
+ CERROR("subflavor 0x%x not found\n", flavor);
goto err_free;
}
if (!gsec->gs_pipepath)
goto err_mech_put;
+ /* pipe rpc require root permission */
+ save_uid = current->fsuid;
+ current->fsuid = 0;
+
sprintf(gsec->gs_pipepath, LUSTRE_PIPEDIR"/%s", pipe_dir);
if (IS_ERR(rpc_mkdir(gsec->gs_pipepath, NULL))) {
CERROR("can't make pipedir %s\n", gsec->gs_pipepath);
#endif
sec = &gsec->gs_base;
-
- switch (flavor->subflavor) {
- case PTLRPC_SEC_GSS_KRB5I:
- sec->ps_sectype = PTLRPC_SEC_TYPE_AUTH;
- break;
- case PTLRPC_SEC_GSS_KRB5P:
- sec->ps_sectype = PTLRPC_SEC_TYPE_PRIV;
- break;
- default:
- LBUG();
- }
-
sec->ps_expire = GSS_CREDCACHE_EXPIRE;
sec->ps_nextgc = get_seconds() + sec->ps_expire;
sec->ps_flags = 0;
+ current->fsuid = save_uid;
+
CDEBUG(D_SEC, "Create GSS security instance at %p(external %p)\n",
gsec, sec);
RETURN(sec);
*pos = 0;
rpc_rmdir(gsec->gs_pipepath);
err_free_path:
+ current->fsuid = save_uid;
OBD_FREE(gsec->gs_pipepath, pipepath_len);
err_mech_put:
#endif
RETURN(cred);
}
-static int gss_estimate_payload(struct ptlrpc_sec *sec, int msgsize)
+static int gss_estimate_payload(struct ptlrpc_sec *sec,
+ struct ptlrpc_request *req,
+ int msgsize)
{
- switch (sec->ps_sectype) {
- case PTLRPC_SEC_TYPE_AUTH:
+ switch (SEC_FLAVOR_SVC(req->rq_req_secflvr)) {
+ case PTLRPCS_SVC_AUTH:
return GSS_MAX_AUTH_PAYLOAD;
- case PTLRPC_SEC_TYPE_PRIV:
+ case PTLRPCS_SVC_PRIV:
return size_round16(GSS_MAX_AUTH_PAYLOAD + msgsize +
GSS_PRIVBUF_PREFIX_LEN +
GSS_PRIVBUF_SUFFIX_LEN);
/* In PRIVACY mode, lustre message is always 0 (already encoded into
* security payload).
*/
- privacy = sec->ps_sectype == PTLRPC_SEC_TYPE_PRIV;
+ privacy = (SEC_FLAVOR_SVC(req->rq_req_secflvr) == PTLRPCS_SVC_PRIV);
msg_payload = privacy ? 0 : lmsg_size;
- sec_payload = gss_estimate_payload(sec, lmsg_size);
+ sec_payload = gss_estimate_payload(sec, req, lmsg_size);
rc = sec_alloc_reqbuf(sec, req, msg_payload, sec_payload);
if (rc)
LASSERT(req->rq_reqmsg);
LASSERT(req->rq_reqlen);
- privacy = sec->ps_sectype == PTLRPC_SEC_TYPE_PRIV;
+ privacy = SEC_FLAVOR_SVC(req->rq_req_secflvr) == PTLRPCS_SVC_PRIV;
if (privacy) {
buf = (char *) req->rq_reqmsg - GSS_PRIVBUF_PREFIX_LEN;
LASSERT(buf < req->rq_reqbuf ||
static struct ptlrpc_sec_type gss_type = {
.pst_owner = THIS_MODULE,
- .pst_name = "GSS_SEC",
+ .pst_name = "sec.gss",
.pst_inst = ATOMIC_INIT(0),
- .pst_flavor = {PTLRPC_SEC_GSS, 0},
+ .pst_flavor = PTLRPCS_FLVR_MAJOR_GSS,
.pst_ops = &gss_secops,
};
struct rsc {
struct cache_head h;
rawobj_t handle;
- __u32 remote_realm;
+ __u32 remote_realm:1,
+ auth_usr_mds:1,
+ auth_usr_oss:1;
struct vfs_cred cred;
uid_t mapped_uid;
struct gss_svc_seq_data seqdata;
/* contexthandle expiry [ uid gid N <n gids> mechname
* ...mechdata... ] */
char *buf = mesg;
- int len, rv;
+ int len, rv, tmp_int;
struct rsc *rsci, *res = NULL;
time_t expiry;
int status = -EINVAL;
goto out;
/* remote flag */
- rv = get_int(&mesg, (int *)&rsci->remote_realm);
+ rv = get_int(&mesg, &tmp_int);
if (rv) {
CERROR("fail to get remote flag\n");
goto out;
}
+ rsci->remote_realm = (tmp_int != 0);
+
+ /* mds user flag */
+ rv = get_int(&mesg, &tmp_int);
+ if (rv) {
+ CERROR("fail to get mds user flag\n");
+ goto out;
+ }
+ rsci->auth_usr_mds = (tmp_int != 0);
+
+ /* oss user flag */
+ rv = get_int(&mesg, &tmp_int);
+ if (rv) {
+ CERROR("fail to get oss user flag\n");
+ goto out;
+ }
+ rsci->auth_usr_oss = (tmp_int != 0);
/* mapped uid */
rv = get_int(&mesg, (int *)&rsci->mapped_uid);
gss_pack_err_notify(struct ptlrpc_request *req,
__u32 major, __u32 minor)
{
- struct gss_svc_data *svcdata = req->rq_sec_svcdata;
+ struct gss_svc_data *svcdata = req->rq_svcsec_data;
__u32 reslen, *resp, *reslenp;
char nidstr[PTL_NALFMT_SIZE];
const __u32 secdata_len = 7 * 4;
resp = (__u32 *) req->rq_reply_state->rs_repbuf;
/* header */
- *resp++ = cpu_to_le32(PTLRPC_SEC_GSS);
- *resp++ = cpu_to_le32(PTLRPC_SEC_TYPE_NONE);
+ *resp++ = cpu_to_le32(PTLRPCS_FLVR_GSS_NONE);
+ *resp++ = cpu_to_le32(PTLRPCS_SVC_NONE);
*resp++ = cpu_to_le32(req->rq_replen);
reslenp = resp++;
* obj1(fake), obj2(fake)
*/
*resp++ = cpu_to_le32(PTLRPC_SEC_GSS_VERSION);
- *resp++ = cpu_to_le32(PTLRPC_SEC_GSS_KRB5I);
- *resp++ = cpu_to_le32(PTLRPC_GSS_PROC_ERR);
+ *resp++ = cpu_to_le32(PTLRPCS_FLVR_KRB5I);
+ *resp++ = cpu_to_le32(PTLRPCS_GSS_PROC_ERR);
*resp++ = cpu_to_le32(major);
*resp++ = cpu_to_le32(minor);
*resp++ = 0;
__u32 *secdata, __u32 seclen,
enum ptlrpcs_error *res)
{
- struct gss_svc_data *svcdata = req->rq_sec_svcdata;
+ struct gss_svc_data *svcdata = req->rq_svcsec_data;
struct rsc *rsci;
struct rsi *rsikey, *rsip;
rawobj_t tmpobj;
/* header */
resp = (__u32 *) req->rq_reply_state->rs_repbuf;
- *resp++ = cpu_to_le32(PTLRPC_SEC_GSS);
- *resp++ = cpu_to_le32(PTLRPC_SEC_TYPE_NONE);
+ *resp++ = cpu_to_le32(PTLRPCS_FLVR_GSS_NONE);
+ *resp++ = cpu_to_le32(PTLRPCS_SVC_NONE);
*resp++ = cpu_to_le32(req->rq_replen);
reslenp = resp++;
*res = PTLRPCS_OK;
- req->rq_auth_uid = rsci->cred.vc_uid;
req->rq_remote_realm = rsci->remote_realm;
+ req->rq_auth_usr_mds = rsci->auth_usr_mds;
+ req->rq_auth_usr_oss = rsci->auth_usr_oss;
+ req->rq_auth_uid = rsci->cred.vc_uid;
req->rq_mapped_uid = rsci->mapped_uid;
+ if (req->rq_auth_usr_mds) {
+ CWARN("usr from %s authenticated as mds svc cred\n",
+ portals_nid2str(req->rq_peer.peer_ni->pni_number,
+ req->rq_peer.peer_id.nid, nidstr));
+ }
+ if (req->rq_auth_usr_oss) {
+ CWARN("usr from %s authenticated as oss svc cred\n",
+ portals_nid2str(req->rq_peer.peer_ni->pni_number,
+ req->rq_peer.peer_id.nid, nidstr));
+ }
+
/* This is simplified since right now we doesn't support
* INIT_CONTINUE yet.
*/
}
switch (gc->gc_svc) {
- case PTLRPC_GSS_SVC_INTEGRITY:
+ case PTLRPCS_GSS_SVC_INTEGRITY:
major = gss_svc_verify_request(req, rsci, gc, secdata, seclen);
if (major == GSS_S_COMPLETE)
break;
portals_nid2str(req->rq_peer.peer_ni->pni_number,
req->rq_peer.peer_id.nid, nidstr));
goto notify_err;
- case PTLRPC_GSS_SVC_PRIVACY:
+ case PTLRPCS_GSS_SVC_PRIVACY:
major = gss_svc_unseal_request(req, rsci, gc, secdata, seclen);
if (major == GSS_S_COMPLETE)
break;
GOTO(out, rc = SVC_DROP);
}
- req->rq_auth_uid = rsci->cred.vc_uid;
req->rq_remote_realm = rsci->remote_realm;
+ req->rq_auth_usr_mds = rsci->auth_usr_mds;
+ req->rq_auth_usr_oss = rsci->auth_usr_oss;
+ req->rq_auth_uid = rsci->cred.vc_uid;
req->rq_mapped_uid = rsci->mapped_uid;
*res = PTLRPCS_OK;
__u32 *secdata, __u32 seclen,
enum ptlrpcs_error *res)
{
- struct gss_svc_data *svcdata = req->rq_sec_svcdata;
+ struct gss_svc_data *svcdata = req->rq_svcsec_data;
struct rsc *rsci;
char nidstr[PTL_NALFMT_SIZE];
int rc;
RETURN(SVC_DROP);
}
- if (gc->gc_svc != PTLRPC_GSS_SVC_INTEGRITY) {
+ if (gc->gc_svc != PTLRPCS_GSS_SVC_INTEGRITY) {
CERROR("service %d is not supported in destroy.\n",
gc->gc_svc);
GOTO(out, rc = SVC_DROP);
struct gss_svc_data *svcdata;
struct rpc_gss_wire_cred *gc;
struct ptlrpcs_wire_hdr *sec_hdr;
- __u32 seclen, *secdata, version;
+ __u32 subflavor, seclen, *secdata, version;
int rc;
ENTRY;
*res = PTLRPCS_BADCRED;
sec_hdr = buf_to_sec_hdr(req->rq_reqbuf);
- LASSERT(sec_hdr->flavor == PTLRPC_SEC_GSS);
+ LASSERT(SEC_FLAVOR_MAJOR(sec_hdr->flavor) == PTLRPCS_FLVR_MAJOR_GSS);
seclen = req->rq_reqbuf_len - sizeof(*sec_hdr) - sec_hdr->msg_len;
secdata = (__u32 *) buf_to_sec_data(req->rq_reqbuf);
RETURN(SVC_DROP);
}
- LASSERT(!req->rq_sec_svcdata);
+ LASSERT(!req->rq_svcsec_data);
OBD_ALLOC(svcdata, sizeof(*svcdata));
if (!svcdata) {
CERROR("fail to alloc svcdata\n");
RETURN(SVC_DROP);
}
- req->rq_sec_svcdata = svcdata;
+ req->rq_svcsec_data = svcdata;
gc = &svcdata->clcred;
/* Now secdata/seclen is what we want to parse
*/
version = le32_to_cpu(*secdata++); /* version */
- svcdata->subflavor = le32_to_cpu(*secdata++); /* subflavor */
+ subflavor = le32_to_cpu(*secdata++); /* subflavor */
gc->gc_proc = le32_to_cpu(*secdata++); /* proc */
gc->gc_seq = le32_to_cpu(*secdata++); /* seq */
gc->gc_svc = le32_to_cpu(*secdata++); /* service */
seclen -= 5 * 4;
CDEBUG(D_SEC, "wire gss_hdr: %u/%u/%u/%u/%u\n",
- version, svcdata->subflavor, gc->gc_proc,
+ version, subflavor, gc->gc_proc,
gc->gc_seq, gc->gc_svc);
if (version != PTLRPC_SEC_GSS_VERSION) {
}
err_free:
- if (rc == SVC_DROP && req->rq_sec_svcdata) {
- OBD_FREE(req->rq_sec_svcdata, sizeof(struct gss_svc_data));
- req->rq_sec_svcdata = NULL;
+ if (rc == SVC_DROP && req->rq_svcsec_data) {
+ OBD_FREE(req->rq_svcsec_data, sizeof(struct gss_svc_data));
+ req->rq_svcsec_data = NULL;
}
RETURN(rc);
gss_svcsec_authorize(struct ptlrpc_request *req)
{
struct ptlrpc_reply_state *rs = req->rq_reply_state;
- struct gss_svc_data *gsd = (struct gss_svc_data *)req->rq_sec_svcdata;
+ struct gss_svc_data *gsd = (struct gss_svc_data *)req->rq_svcsec_data;
struct rpc_gss_wire_cred *gc = &gsd->clcred;
struct rsc *rscp;
struct ptlrpcs_wire_hdr *sec_hdr;
sec_hdr = (struct ptlrpcs_wire_hdr *) rs->rs_repbuf;
switch (gc->gc_svc) {
- case PTLRPC_GSS_SVC_INTEGRITY:
+ case PTLRPCS_GSS_SVC_INTEGRITY:
/* prepare various pointers */
lmsg.len = req->rq_replen;
lmsg.data = (__u8 *) (rs->rs_repbuf + sizeof(*sec_hdr));
vlen = rs->rs_repbuf_len - sizeof(*sec_hdr) - lmsg.len;
seclen = vlen;
- sec_hdr->flavor = cpu_to_le32(PTLRPC_SEC_GSS);
- sec_hdr->sectype = cpu_to_le32(PTLRPC_SEC_TYPE_AUTH);
+ sec_hdr->flavor = cpu_to_le32(PTLRPCS_FLVR_GSS_AUTH);
sec_hdr->msg_len = cpu_to_le32(req->rq_replen);
/* standard gss hdr */
LASSERT(vlen >= 7 * 4);
*vp++ = cpu_to_le32(PTLRPC_SEC_GSS_VERSION);
- *vp++ = cpu_to_le32(PTLRPC_SEC_GSS_KRB5I);
+ *vp++ = cpu_to_le32(PTLRPCS_FLVR_KRB5I);
*vp++ = cpu_to_le32(RPC_GSS_PROC_DATA);
*vp++ = cpu_to_le32(gc->gc_seq);
- *vp++ = cpu_to_le32(PTLRPC_GSS_SVC_INTEGRITY);
+ *vp++ = cpu_to_le32(PTLRPCS_GSS_SVC_INTEGRITY);
*vp++ = 0; /* fake ctx handle */
vpsave = vp++; /* reserve size */
vlen -= 7 * 4;
sec_hdr->sec_len = cpu_to_le32(seclen);
rs->rs_repdata_len += size_round(seclen);
break;
- case PTLRPC_GSS_SVC_PRIVACY:
+ case PTLRPCS_GSS_SVC_PRIVACY:
vp = (__u32 *) (rs->rs_repbuf + sizeof(*sec_hdr));
vlen = rs->rs_repbuf_len - sizeof(*sec_hdr);
seclen = vlen;
- sec_hdr->flavor = cpu_to_le32(PTLRPC_SEC_GSS);
- sec_hdr->sectype = cpu_to_le32(PTLRPC_SEC_TYPE_PRIV);
+ sec_hdr->flavor = cpu_to_le32(PTLRPCS_FLVR_GSS_PRIV);
sec_hdr->msg_len = cpu_to_le32(0);
/* standard gss hdr */
LASSERT(vlen >= 7 * 4);
*vp++ = cpu_to_le32(PTLRPC_SEC_GSS_VERSION);
- *vp++ = cpu_to_le32(PTLRPC_SEC_GSS_KRB5I);
+ *vp++ = cpu_to_le32(PTLRPCS_FLVR_KRB5I);
*vp++ = cpu_to_le32(RPC_GSS_PROC_DATA);
*vp++ = cpu_to_le32(gc->gc_seq);
- *vp++ = cpu_to_le32(PTLRPC_GSS_SVC_PRIVACY);
+ *vp++ = cpu_to_le32(PTLRPCS_GSS_SVC_PRIVACY);
*vp++ = 0; /* fake ctx handle */
vpsave = vp++; /* reserve size */
vlen -= 7 * 4;
void gss_svcsec_cleanup_req(struct ptlrpc_svcsec *svcsec,
struct ptlrpc_request *req)
{
- struct gss_svc_data *gsd = (struct gss_svc_data *) req->rq_sec_svcdata;
+ struct gss_svc_data *gsd = (struct gss_svc_data *) req->rq_svcsec_data;
if (!gsd) {
CDEBUG(D_SEC, "no svc_data present. do nothing\n");
* to the incoming packet buffer, so don't need free it
*/
OBD_FREE(gsd, sizeof(*gsd));
- req->rq_sec_svcdata = NULL;
+ req->rq_svcsec_data = NULL;
return;
}
struct ptlrpc_request *req,
int msgsize)
{
- struct gss_svc_data *svcdata = req->rq_sec_svcdata;
+ struct gss_svc_data *svcdata = req->rq_svcsec_data;
ENTRY;
/* just return the pre-set reserve_len for init/fini/err cases.
CDEBUG(D_SEC, "is_fini, reserver size 0\n");
RETURN(0);
} else {
- if (svcdata->clcred.gc_svc == PTLRPC_GSS_SVC_NONE ||
- svcdata->clcred.gc_svc == PTLRPC_GSS_SVC_INTEGRITY)
+ if (svcdata->clcred.gc_svc == PTLRPCS_GSS_SVC_NONE ||
+ svcdata->clcred.gc_svc == PTLRPCS_GSS_SVC_INTEGRITY)
RETURN(size_round(GSS_MAX_AUTH_PAYLOAD));
- else if (svcdata->clcred.gc_svc == PTLRPC_GSS_SVC_PRIVACY)
+ else if (svcdata->clcred.gc_svc == PTLRPCS_GSS_SVC_PRIVACY)
RETURN(size_round16(GSS_MAX_AUTH_PAYLOAD + msgsize +
GSS_PRIVBUF_PREFIX_LEN +
GSS_PRIVBUF_SUFFIX_LEN));
struct ptlrpc_request *req,
int msgsize)
{
- struct gss_svc_data *gsd = (struct gss_svc_data *) req->rq_sec_svcdata;
+ struct gss_svc_data *gsd = (struct gss_svc_data *) req->rq_svcsec_data;
struct ptlrpc_reply_state *rs;
int msg_payload, sec_payload;
int privacy, rc;
LASSERT(gsd);
if (!gsd->is_init && !gsd->is_init_continue &&
!gsd->is_fini && !gsd->is_err_notify &&
- gsd->clcred.gc_svc == PTLRPC_GSS_SVC_PRIVACY)
+ gsd->clcred.gc_svc == PTLRPCS_GSS_SVC_PRIVACY)
privacy = 1;
else
privacy = 0;
struct ptlrpc_svcsec svcsec_gss = {
.pss_owner = THIS_MODULE,
- .pss_name = "GSS_SVCSEC",
- .pss_flavor = {PTLRPC_SEC_GSS, 0},
+ .pss_name = "svcsec.gss",
+ .pss_flavor = PTLRPCS_FLVR_MAJOR_GSS,
.accept = gss_svcsec_accept,
.authorize = gss_svcsec_authorize,
.alloc_repbuf = gss_svcsec_alloc_repbuf,
#include <linux/lustre_sec.h>
static spinlock_t sectypes_lock = SPIN_LOCK_UNLOCKED;
-static struct ptlrpc_sec_type *sectypes[PTLRPC_SEC_MAX_FLAVORS] = {
+static struct ptlrpc_sec_type *sectypes[PTLRPCS_FLVR_MAJOR_MAX] = {
NULL,
};
int ptlrpcs_register(struct ptlrpc_sec_type *type)
{
- __u32 flavor = type->pst_flavor.flavor;
+ __u32 flavor = type->pst_flavor;
LASSERT(type->pst_name);
LASSERT(type->pst_ops);
- if (flavor >= PTLRPC_SEC_MAX_FLAVORS)
+ if (flavor >= PTLRPCS_FLVR_MAJOR_MAX)
return -EINVAL;
spin_lock(§ypes_lock);
atomic_set(&type->pst_inst, 0);
spin_unlock(§ypes_lock);
- CWARN("Security module %s registered\n", type->pst_name);
+ CDEBUG(D_SEC, "%s: registered\n", type->pst_name);
return 0;
}
int ptlrpcs_unregister(struct ptlrpc_sec_type *type)
{
- __u32 flavor = type->pst_flavor.flavor;
+ __u32 major = type->pst_flavor;
- if (flavor >= PTLRPC_SEC_MAX_FLAVORS)
- return -EINVAL;
+ LASSERT(major < PTLRPCS_FLVR_MAJOR_MAX);
spin_lock(§ypes_lock);
- if (!sectypes[flavor]) {
+ if (!sectypes[major]) {
spin_unlock(§ypes_lock);
+ CERROR("%s: already unregistered?\n", type->pst_name);
return -EINVAL;
}
- if (sectypes[flavor] != type) {
- CERROR("invalid unregister\n");
- return -EINVAL;
- }
+ LASSERT(sectypes[major] == type);
if (atomic_read(&type->pst_inst)) {
- CERROR("sec module %s still have instance %d\n",
+ CERROR("%s: still have %d, instances\n",
type->pst_name, atomic_read(&type->pst_inst));
spin_unlock(§ypes_lock);
return -EINVAL;
}
- CDEBUG(D_SEC, "Security module %s unregistered\n", type->pst_name);
- sectypes[flavor] = NULL;
+ sectypes[major] = NULL;
spin_unlock(§ypes_lock);
+ CDEBUG(D_SEC, "%s: unregistered\n", type->pst_name);
return 0;
}
static
-struct ptlrpc_sec_type * ptlrpcs_flavor2type(ptlrpcs_flavor_t *flavor)
+struct ptlrpc_sec_type * ptlrpcs_flavor2type(__u32 flavor)
{
struct ptlrpc_sec_type *type;
- __u32 major = flavor->flavor;
+ __u32 major = SEC_FLAVOR_MAJOR(flavor);
- if (major >= PTLRPC_SEC_MAX_FLAVORS)
+ if (major >= PTLRPCS_FLVR_MAJOR_MAX)
return NULL;
spin_lock(§ypes_lock);
module_put(type->pst_owner);
}
+__u32 ptlrpcs_name2flavor(const char *name)
+{
+ if (!strcmp(name, "null"))
+ return PTLRPCS_FLVR_NULL;
+ if (!strcmp(name, "krb5"))
+ return PTLRPCS_FLVR_KRB5;
+ if (!strcmp(name, "krb5i"))
+ return PTLRPCS_FLVR_KRB5I;
+ if (!strcmp(name, "krb5p"))
+ return PTLRPCS_FLVR_KRB5P;
+
+ return PTLRPCS_FLVR_INVALID;
+}
+
+char *ptlrpcs_flavor2name(__u32 flavor)
+{
+ switch (flavor) {
+ case PTLRPCS_FLVR_NULL:
+ return "null";
+ case PTLRPCS_FLVR_KRB5:
+ return "krb5";
+ case PTLRPCS_FLVR_KRB5I:
+ return "krb5i";
+ case PTLRPCS_FLVR_KRB5P:
+ return "krb5p";
+ default:
+ CERROR("invalid flavor 0x%x\n", flavor);
+ }
+ return "unknown";
+}
+
/***********************************************
* credential cache helpers *
***********************************************/
int i;
for (i = 0; i < PTLRPC_CREDCACHE_NR; i++)
INIT_LIST_HEAD(&sec->ps_credcache[i]);
- sec->ps_nextgc = get_seconds() + (sec->ps_expire >> 1);
+
+ /* ps_nextgc == 0 means never do gc */
+ if (sec->ps_nextgc)
+ sec->ps_nextgc = get_seconds() + (sec->ps_expire >> 1);
}
/*
spin_lock(&sec->ps_lock);
/* do gc if expired */
- if (remove_dead && time_after(get_seconds(), sec->ps_nextgc))
+ if (remove_dead &&
+ sec->ps_nextgc && time_after(get_seconds(), sec->ps_nextgc))
ptlrpcs_credcache_gc(sec, &freelist);
list_for_each_entry_safe(cred, n, &sec->ps_credcache[hash], pc_hash) {
/* XXX
* for now we simply let PAG == real uid
*/
- vcred.vc_pag = (__u64) current->uid;
- vcred.vc_uid = current->uid;
+ if (sec->ps_flags & (PTLRPC_SEC_FL_MDS | PTLRPC_SEC_FL_REVERSE)) {
+ vcred.vc_pag = 0;
+ vcred.vc_uid = 0;
+ } else {
+ vcred.vc_pag = (__u64) current->uid;
+ vcred.vc_uid = current->uid;
+ }
return cred_cache_lookup(sec, &vcred, 1, 1);
}
CDEBUG(D_SEC, "wrap req %p\n", req);
cred = req->rq_cred;
- switch (cred->pc_sec->ps_sectype) {
- case PTLRPC_SEC_TYPE_NONE:
- case PTLRPC_SEC_TYPE_AUTH:
+ switch (SEC_FLAVOR_SVC(req->rq_req_secflvr)) {
+ case PTLRPCS_SVC_NONE:
+ case PTLRPCS_SVC_AUTH:
if (req->rq_req_wrapped) {
CDEBUG(D_SEC, "req %p(o%u,x"LPU64",t"LPU64") "
"already signed, resend?\n", req,
if (!rc)
req->rq_req_wrapped = 1;
break;
- case PTLRPC_SEC_TYPE_PRIV:
+ case PTLRPCS_SVC_PRIV:
if (req->rq_req_wrapped) {
CDEBUG(D_SEC, "req %p(o%u,x"LPU64",t"LPU64") "
"already encrypted, resend?\n", req,
sec_hdr = (struct ptlrpcs_wire_hdr *) req->rq_repbuf;
sec_hdr->flavor = le32_to_cpu(sec_hdr->flavor);
- sec_hdr->sectype = le32_to_cpu(sec_hdr->sectype);
sec_hdr->msg_len = le32_to_cpu(sec_hdr->msg_len);
sec_hdr->sec_len = le32_to_cpu(sec_hdr->sec_len);
- CDEBUG(D_SEC, "req %p, cred %p, flavor %u, sectype %u\n",
- req, cred, sec_hdr->flavor, sec_hdr->sectype);
+ CDEBUG(D_SEC, "req %p, cred %p, flavor 0x%x\n",
+ req, cred, sec_hdr->flavor);
sec = cred->pc_sec;
- if (sec_hdr->flavor != sec->ps_flavor.flavor) {
- CERROR("unmatched flavor %u while expect %u\n",
- sec_hdr->flavor, sec->ps_flavor.flavor);
+
+ /* only compare major flavor, reply might use different subflavor.
+ */
+ if (SEC_FLAVOR_MAJOR(sec_hdr->flavor) !=
+ SEC_FLAVOR_MAJOR(req->rq_req_secflvr)) {
+ CERROR("got major flavor %u while expect %u\n",
+ SEC_FLAVOR_MAJOR(sec_hdr->flavor),
+ SEC_FLAVOR_MAJOR(req->rq_req_secflvr));
RETURN(-EPROTO);
}
RETURN(-EPROTO);
}
- switch (sec_hdr->sectype) {
- case PTLRPC_SEC_TYPE_NONE:
- case PTLRPC_SEC_TYPE_AUTH: {
+ switch (SEC_FLAVOR_SVC(sec_hdr->flavor)) {
+ case PTLRPCS_SVC_NONE:
+ case PTLRPCS_SVC_AUTH: {
LASSERT(cred->pc_ops->verify);
rc = cred->pc_ops->verify(cred, req);
LASSERT(rc || req->rq_repmsg || req->rq_ptlrpcs_restart);
break;
- case PTLRPC_SEC_TYPE_PRIV:
+ case PTLRPCS_SVC_PRIV:
LASSERT(cred->pc_ops->unseal);
rc = cred->pc_ops->unseal(cred, req);
LASSERT(rc || req->rq_repmsg || req->rq_ptlrpcs_restart);
* security APIs *
**************************************************/
-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)
type = ptlrpcs_flavor2type(flavor);
if (!type) {
- CDEBUG(D_SEC, "invalid major flavor %u\n", flavor->flavor);
+ CERROR("invalid flavor 0x%x\n", flavor);
RETURN(NULL);
}
spin_lock_init(&sec->ps_lock);
ptlrpcs_init_credcache(sec);
sec->ps_type = type;
- sec->ps_flavor = *flavor;
+ sec->ps_flavor = flavor;
+ sec->ps_flags = flags;
sec->ps_import = class_import_get(import);
atomic_set(&sec->ps_refcount, 1);
atomic_set(&sec->ps_credcount, 0);
if (ncred == 0) {
ptlrpcs_sec_destroy(sec);
} else {
- CWARN("sec %p(%s) is no usage while %d cred still "
+ CWARN("%s %p is no usage while %d cred still "
"holded, destroy delayed\n",
- sec, sec->ps_type->pst_name,
+ sec->ps_type->pst_name, sec,
atomic_read(&sec->ps_credcount));
}
}
}
hdr = buf_to_sec_hdr(req->rq_reqbuf);
- hdr->flavor = cpu_to_le32(sec->ps_flavor.flavor);
- hdr->sectype = cpu_to_le32(sec->ps_sectype);
+ hdr->flavor = cpu_to_le32(req->rq_req_secflvr);
hdr->msg_len = msgsize;
/* security length will be filled later */
RETURN(ops->alloc_repbuf(sec, req, msgsize));
/* default allocation scheme */
- msg_payload = sec->ps_sectype == PTLRPC_SEC_TYPE_PRIV ? 0 : msgsize;
- sec_payload = size_round(ptlrpcs_est_rep_payload(sec, msgsize));
+ msg_payload = SEC_FLAVOR_SVC(req->rq_req_secflvr) == PTLRPCS_SVC_PRIV ?
+ 0 : msgsize;
+ sec_payload = size_round(ptlrpcs_est_rep_payload(req, msgsize));
req->rq_repbuf_len = sizeof(struct ptlrpcs_wire_hdr) +
msg_payload + sec_payload;
int ptlrpcs_import_get_sec(struct obd_import *imp)
{
- ptlrpcs_flavor_t flavor = {PTLRPC_SEC_NULL, 0};
+ __u32 flavor = PTLRPCS_FLVR_NULL;
+ unsigned long flags = 0;
char *pipedir = NULL;
ENTRY;
!strcmp(imp->imp_obd->obd_type->typ_name, "osc")) {
struct client_obd *cli = &imp->imp_obd->u.cli;
- if (cli->cl_sec_flavor == PTLRPC_SEC_GSS) {
- CWARN("select security gss/%s for %s(%s)\n",
- cli->cl_sec_subflavor == PTLRPC_SEC_GSS_KRB5I ?
- "krb5i" : "krb5p",
- imp->imp_obd->obd_type->typ_name,
- imp->imp_obd->obd_name);
- flavor.flavor = cli->cl_sec_flavor;
- flavor.subflavor = cli->cl_sec_subflavor;
- pipedir = imp->imp_obd->obd_name;
- } else if (cli->cl_sec_flavor == PTLRPC_SEC_NULL) {
+ switch (SEC_FLAVOR_MAJOR(cli->cl_sec_flavor)) {
+ case PTLRPCS_FLVR_MAJOR_NULL:
CWARN("select security null for %s(%s)\n",
- imp->imp_obd->obd_type->typ_name,
- imp->imp_obd->obd_name);
- } else {
- CWARN("unknown security flavor for mdc(%s), "
- "use 'null'\n", imp->imp_obd->obd_name);
+ imp->imp_obd->obd_type->typ_name,
+ imp->imp_obd->obd_name);
+ break;
+ case PTLRPCS_FLVR_MAJOR_GSS:
+ CWARN("select security %s for %s(%s)\n",
+ ptlrpcs_flavor2name(cli->cl_sec_flavor),
+ imp->imp_obd->obd_type->typ_name,
+ imp->imp_obd->obd_name);
+ flavor = cli->cl_sec_flavor;
+ pipedir = imp->imp_obd->obd_name;
+ break;
+ default:
+ CWARN("unknown security flavor for %s(%s), use null\n",
+ imp->imp_obd->obd_type->typ_name,
+ imp->imp_obd->obd_name);
}
+
+ flags = cli->cl_sec_flags;
}
- imp->imp_sec = ptlrpcs_sec_create(&flavor, imp, pipedir, imp);
+ imp->imp_sec = ptlrpcs_sec_create(flavor, flags, imp, pipedir, imp);
if (!imp->imp_sec)
RETURN(-EINVAL);
else
EXPORT_SYMBOL(svcsec_alloc_reply_state);
EXPORT_SYMBOL(svcsec_free_reply_state);
+EXPORT_SYMBOL(ptlrpcs_name2flavor);
+EXPORT_SYMBOL(ptlrpcs_flavor2name);
+
MODULE_AUTHOR("Cluster File Systems, Inc. <info@clusterfs.com>");
MODULE_DESCRIPTION("Lustre Security Support");
MODULE_LICENSE("GPL");
};
static
-struct ptlrpc_sec* null_create_sec(ptlrpcs_flavor_t *flavor,
+struct ptlrpc_sec* null_create_sec(__u32 flavor,
const char *pipe_dir,
void *pipe_data)
{
struct ptlrpc_sec *sec;
ENTRY;
- LASSERT(flavor->flavor == PTLRPC_SEC_NULL);
+ LASSERT(SEC_FLAVOR_MAJOR(flavor) == PTLRPCS_FLVR_MAJOR_NULL);
OBD_ALLOC(sec, sizeof(*sec));
if (!sec)
RETURN(ERR_PTR(-ENOMEM));
- sec->ps_sectype = PTLRPC_SEC_TYPE_NONE;
- sec->ps_expire = (-1UL >> 1); /* never expire */
- sec->ps_nextgc = (-1UL >> 1);
+ sec->ps_expire = 0; /* never expire */
+ sec->ps_nextgc = 0; /* never do gc */
sec->ps_flags = 0;
CDEBUG(D_SEC, "Create NULL security module at %p\n", sec);
static struct ptlrpc_sec_type null_type = {
.pst_owner = THIS_MODULE,
- .pst_name = "NULL_SEC",
+ .pst_name = "sec.null",
.pst_inst = ATOMIC_INIT(0),
- .pst_flavor = {PTLRPC_SEC_NULL, 0},
+ .pst_flavor = PTLRPCS_FLVR_MAJOR_NULL,
.pst_ops = &null_secops,
};
#include <linux/lustre_sec.h>
static spinlock_t svcsecs_lock = SPIN_LOCK_UNLOCKED;
-static struct ptlrpc_svcsec *svcsecs[PTLRPC_SEC_MAX_FLAVORS] = {
+static struct ptlrpc_svcsec *svcsecs[PTLRPCS_FLVR_MAJOR_MAX] = {
NULL,
};
int svcsec_register(struct ptlrpc_svcsec *sec)
{
- __u32 flavor = sec->pss_flavor.flavor;
+ __u32 major = sec->pss_flavor;
- if (flavor >= PTLRPC_SEC_MAX_FLAVORS)
+ if (major >= PTLRPCS_FLVR_MAJOR_MAX)
return -EINVAL;
spin_lock(&svcsecs_lock);
- if (svcsecs[flavor]) {
+ if (svcsecs[major]) {
spin_unlock(&svcsecs_lock);
return -EALREADY;
}
- svcsecs[flavor] = sec;
+ svcsecs[major] = sec;
spin_unlock(&svcsecs_lock);
- CDEBUG(D_SEC, "Registered svc security module %s\n", sec->pss_name);
+ CWARN("%s: registered\n", sec->pss_name);
return 0;
}
int svcsec_unregister(struct ptlrpc_svcsec *sec)
{
- __u32 flavor = sec->pss_flavor.flavor;
+ __u32 major = sec->pss_flavor;
- if (flavor >= PTLRPC_SEC_MAX_FLAVORS)
- return -EINVAL;
+ LASSERT(major < PTLRPCS_FLVR_MAJOR_MAX);
spin_lock(&svcsecs_lock);
- if (!svcsecs[flavor]) {
+ if (!svcsecs[major]) {
spin_unlock(&svcsecs_lock);
return -EINVAL;
}
- LASSERT(svcsecs[flavor] == sec);
+ LASSERT(svcsecs[major] == sec);
- CDEBUG(D_SEC, "Unregistered svc security module %s\n", sec->pss_name);
- svcsecs[flavor] = NULL;
+ svcsecs[major] = NULL;
spin_unlock(&svcsecs_lock);
+ CWARN("%s: unregistered\n", sec->pss_name);
return 0;
}
struct ptlrpc_svcsec * flavor2svcsec(__u32 flavor)
{
struct ptlrpc_svcsec *sec;
+ __u32 major = SEC_FLAVOR_MAJOR(flavor);
- if (flavor >= PTLRPC_SEC_MAX_FLAVORS)
+ if (major >= PTLRPCS_FLVR_MAJOR_MAX)
return NULL;
spin_lock(&svcsecs_lock);
- sec = svcsecs[flavor];
+ sec = svcsecs[major];
if (sec && !try_module_get(sec->pss_owner))
sec = NULL;
spin_unlock(&svcsecs_lock);
sec_hdr = (struct ptlrpcs_wire_hdr *) req->rq_reqbuf;
sec_hdr->flavor = le32_to_cpu(sec_hdr->flavor);
- sec_hdr->sectype = le32_to_cpu(sec_hdr->sectype);
sec_hdr->msg_len = le32_to_cpu(sec_hdr->msg_len);
sec_hdr->sec_len = le32_to_cpu(sec_hdr->sec_len);
/* sanity check */
- switch (sec_hdr->sectype) {
- case PTLRPC_SEC_TYPE_NONE:
- case PTLRPC_SEC_TYPE_AUTH:
- case PTLRPC_SEC_TYPE_PRIV:
+ switch (SEC_FLAVOR_SVC(sec_hdr->flavor)) {
+ case PTLRPCS_SVC_NONE:
+ case PTLRPCS_SVC_AUTH:
+ case PTLRPCS_SVC_PRIV:
break;
default:
- CERROR("unknown security type %d\n", sec_hdr->sectype);
+ CERROR("unknown security svc %d\n",
+ SEC_FLAVOR_SVC(sec_hdr->flavor));
RETURN(SVC_DROP);
}
CERROR("drop msg: unsupported flavor %d\n", sec_hdr->flavor);
RETURN(SVC_DROP);
}
- LASSERT(sec->accept);
+ /* flavor in the wire header might not be the real "end user" flavor,
+ * we set it here anyway, later accept() might override with correct
+ * value.
+ */
+ req->rq_req_secflvr = sec_hdr->flavor;
+
+ LASSERT(sec->accept);
rc = sec->accept(req, res);
switch (rc) {
ENTRY;
LASSERT(svcsec);
- LASSERT(svcsec->cleanup_req || !req->rq_sec_svcdata);
+ LASSERT(svcsec->cleanup_req || !req->rq_svcsec_data);
if (svcsec->cleanup_req)
svcsec->cleanup_req(svcsec, req);
struct ptlrpcs_wire_hdr *hdr = buf_to_sec_hdr(req->rq_reqbuf);
ENTRY;
- LASSERT(hdr->flavor == PTLRPC_SEC_NULL);
+ LASSERT(SEC_FLAVOR_MAJOR(hdr->flavor) == PTLRPCS_FLVR_MAJOR_NULL);
if (hdr->sec_len != 0) {
CERROR("security payload %d not zero\n", hdr->sec_len);
RETURN(SVC_DROP);
}
+ req->rq_req_secflvr = PTLRPCS_FLVR_NULL;
+
req->rq_reqmsg = (struct lustre_msg *)(hdr + 1);
req->rq_reqlen = hdr->msg_len;
*res = PTLRPCS_OK;
LASSERT(rs->rs_repbuf_len >= 4 * 4);
hdr = buf_to_sec_hdr(rs->rs_repbuf);
- hdr->flavor = cpu_to_le32(PTLRPC_SEC_NULL);
- hdr->sectype = cpu_to_le32(PTLRPC_SEC_TYPE_AUTH);
+ hdr->flavor = cpu_to_le32(PTLRPCS_FLVR_NULL);
hdr->msg_len = cpu_to_le32(req->rq_replen);
hdr->sec_len = cpu_to_le32(0);
static struct ptlrpc_svcsec null_svcsec = {
.pss_owner = THIS_MODULE,
- .pss_name = "NULL_SVCSEC",
- .pss_flavor = {PTLRPC_SEC_NULL, 0},
+ .pss_name = "svcsec.null",
+ .pss_flavor = PTLRPCS_FLVR_MAJOR_NULL,
.accept = null_svcsec_accept,
.authorize = null_svcsec_authorize,
};
fprintf(stderr, "%s: please use 'cfg_device name' to set the "
"device name for config commands.\n",
jt_cmdname(argv[0]));
- return -EINVAL;
+ return -EINVAL;
}
lustre_cfg_bufs_reset(&bufs, lcfg_devname);