From aa145aa1fdfab120acd3de5cf5af067d9ca516f6 Mon Sep 17 00:00:00 2001 From: Eric Mei Date: Thu, 14 Oct 2010 21:41:11 -0600 Subject: [PATCH] b=23728 gss: allow oss authenticate with mgs. r=di.wang --- lustre/include/lustre_net.h | 1 + lustre/ptlrpc/gss/gss_cli_upcall.c | 1 + lustre/ptlrpc/gss/gss_internal.h | 1 + lustre/ptlrpc/gss/gss_keyring.c | 18 ++- lustre/ptlrpc/gss/gss_svc_upcall.c | 36 +++-- lustre/ptlrpc/gss/sec_gss.c | 7 +- lustre/ptlrpc/sec.c | 109 +++++++------- lustre/utils/gss/lgss_keyring.c | 24 ++-- lustre/utils/gss/lgss_krb5_utils.c | 281 +++++++++++++++++++++---------------- lustre/utils/gss/lgss_utils.c | 2 +- lustre/utils/gss/lgss_utils.h | 13 +- lustre/utils/gss/svcgssd_proc.c | 129 ++++++++++------- 12 files changed, 370 insertions(+), 252 deletions(-) diff --git a/lustre/include/lustre_net.h b/lustre/include/lustre_net.h index a85c8c3..7693eef 100644 --- a/lustre/include/lustre_net.h +++ b/lustre/include/lustre_net.h @@ -575,6 +575,7 @@ struct ptlrpc_request { rq_auth_remote:1, /* authed as remote user */ rq_auth_usr_root:1, /* authed as root */ rq_auth_usr_mdt:1, /* authed as mdt */ + rq_auth_usr_ost:1, /* authed as ost */ /* security tfm flags */ rq_pack_udesc:1, rq_pack_bulk:1, diff --git a/lustre/ptlrpc/gss/gss_cli_upcall.c b/lustre/ptlrpc/gss/gss_cli_upcall.c index ed2f672..eb9536b 100644 --- a/lustre/ptlrpc/gss/gss_cli_upcall.c +++ b/lustre/ptlrpc/gss/gss_cli_upcall.c @@ -91,6 +91,7 @@ int ctx_init_pack_request(struct obd_import *imp, /* gss hdr */ ghdr = lustre_msg_buf(msg, 0, sizeof(*ghdr)); ghdr->gh_version = PTLRPC_GSS_VERSION; + ghdr->gh_sp = (__u8) imp->imp_sec->ps_part; ghdr->gh_flags = 0; ghdr->gh_proc = PTLRPC_GSS_PROC_INIT; ghdr->gh_seq = 0; diff --git a/lustre/ptlrpc/gss/gss_internal.h b/lustre/ptlrpc/gss/gss_internal.h index 08e91af..78ae0d5 100644 --- a/lustre/ptlrpc/gss/gss_internal.h +++ b/lustre/ptlrpc/gss/gss_internal.h @@ -232,6 +232,7 @@ struct gss_svc_ctx { uid_t gsc_mapped_uid; unsigned int gsc_usr_root:1, gsc_usr_mds:1, + gsc_usr_oss:1, gsc_remote:1, gsc_reverse:1; }; diff --git a/lustre/ptlrpc/gss/gss_keyring.c b/lustre/ptlrpc/gss/gss_keyring.c index 4cd78d7..a6dc099 100644 --- a/lustre/ptlrpc/gss/gss_keyring.c +++ b/lustre/ptlrpc/gss/gss_keyring.c @@ -721,7 +721,23 @@ struct ptlrpc_cli_ctx * gss_sec_lookup_ctx_kr(struct ptlrpc_sec *sec, /* update reverse handle for root user */ sec2gsec(sec)->gs_rvs_hdl = gss_get_next_ctx_index(); - co_flags = "r"; + switch (sec->ps_part) { + case LUSTRE_SP_MDT: + co_flags = "m"; + break; + case LUSTRE_SP_OST: + co_flags = "o"; + break; + case LUSTRE_SP_MGC: + co_flags = "rmo"; + break; + case LUSTRE_SP_CLI: + co_flags = "r"; + break; + case LUSTRE_SP_MGS: + default: + LBUG(); + } } /* in case of setuid, key will be constructed as owner of fsuid/fsgid, diff --git a/lustre/ptlrpc/gss/gss_svc_upcall.c b/lustre/ptlrpc/gss/gss_svc_upcall.c index aaa4c85..307f1efd 100644 --- a/lustre/ptlrpc/gss/gss_svc_upcall.c +++ b/lustre/ptlrpc/gss/gss_svc_upcall.c @@ -671,6 +671,14 @@ static int rsc_parse(struct cache_detail *cd, char *mesg, int mlen) } rsci.ctx.gsc_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.ctx.gsc_usr_oss = (tmp_int != 0); + /* mapped uid */ rv = get_int(&mesg, (int *) &rsci.ctx.gsc_mapped_uid); if (rv) { @@ -822,6 +830,14 @@ static int rsc_parse(struct cache_detail *cd, char *mesg, int mlen) } rsci.ctx.gsc_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.ctx.gsc_usr_oss = (tmp_int != 0); + /* mapped uid */ rv = get_int(&mesg, (int *) &rsci.ctx.gsc_mapped_uid); if (rv) { @@ -1069,10 +1085,12 @@ int gss_svc_upcall_install_rvs_ctx(struct obd_import *imp, } rsci.h.expiry_time = (time_t) ctx_expiry; - /* FIXME */ - rsci.ctx.gsc_usr_root = 1; - rsci.ctx.gsc_usr_mds= 1; - rsci.ctx.gsc_reverse = 1; + if (strcmp(imp->imp_obd->obd_type->typ_name, LUSTRE_MDC_NAME) == 0) + rsci.ctx.gsc_usr_mds = 1; + else if (strcmp(imp->imp_obd->obd_type->typ_name, LUSTRE_OSC_NAME) == 0) + rsci.ctx.gsc_usr_oss = 1; + else + rsci.ctx.gsc_usr_root = 1; rscp = rsc_update(&rsci, rscp); if (rscp == NULL) @@ -1124,10 +1142,12 @@ int gss_svc_upcall_install_rvs_ctx(struct obd_import *imp, } rsci.h.expiry_time = (time_t) ctx_expiry; - /* FIXME */ - rsci.ctx.gsc_usr_root = 1; - rsci.ctx.gsc_usr_mds= 1; - rsci.ctx.gsc_reverse = 1; + if (strcmp(imp->imp_obd->obd_type->typ_name, LUSTRE_MDC_NAME) == 0) + rsci.ctx.gsc_usr_mds = 1; + else if (strcmp(imp->imp_obd->obd_type->typ_name, LUSTRE_OSC_NAME) == 0) + rsci.ctx.gsc_usr_oss = 1; + else + rsci.ctx.gsc_usr_root = 1; rscp = rsc_lookup(&rsci, 1); if (rscp == NULL) { diff --git a/lustre/ptlrpc/gss/sec_gss.c b/lustre/ptlrpc/gss/sec_gss.c index 2a32e3c..74b0d33 100644 --- a/lustre/ptlrpc/gss/sec_gss.c +++ b/lustre/ptlrpc/gss/sec_gss.c @@ -2056,10 +2056,12 @@ int gss_svc_handle_init(struct ptlrpc_request *req, if (rc != SECSVC_OK) RETURN(rc); - if (grctx->src_ctx->gsc_usr_mds || grctx->src_ctx->gsc_usr_root) + if (grctx->src_ctx->gsc_usr_mds || grctx->src_ctx->gsc_usr_oss || + grctx->src_ctx->gsc_usr_root) CWARN("create svc ctx %p: user from %s authenticated as %s\n", grctx->src_ctx, libcfs_nid2str(req->rq_peer.nid), - grctx->src_ctx->gsc_usr_mds ? "mds" : "root"); + grctx->src_ctx->gsc_usr_mds ? "mds" : + (grctx->src_ctx->gsc_usr_oss ? "oss" : "root")); else CWARN("create svc ctx %p: accept user %u from %s\n", grctx->src_ctx, grctx->src_ctx->gsc_uid, @@ -2419,6 +2421,7 @@ int gss_svc_accept(struct ptlrpc_sec_policy *policy, struct ptlrpc_request *req) req->rq_auth_gss = 1; req->rq_auth_remote = grctx->src_ctx->gsc_remote; req->rq_auth_usr_mdt = grctx->src_ctx->gsc_usr_mds; + req->rq_auth_usr_ost = grctx->src_ctx->gsc_usr_oss; req->rq_auth_usr_root = grctx->src_ctx->gsc_usr_root; req->rq_auth_uid = grctx->src_ctx->gsc_uid; req->rq_auth_mapped_uid = grctx->src_ctx->gsc_mapped_uid; diff --git a/lustre/ptlrpc/sec.c b/lustre/ptlrpc/sec.c index bf7db85..1494e0d 100644 --- a/lustre/ptlrpc/sec.c +++ b/lustre/ptlrpc/sec.c @@ -462,9 +462,9 @@ int sptlrpc_req_ctx_switch(struct ptlrpc_request *req, struct ptlrpc_cli_ctx *newctx) { struct sptlrpc_flavor old_flvr; - char *reqmsg; + char *reqmsg = NULL; /* to workaround old gcc */ int reqmsg_size; - int rc; + int rc = 0; LASSERT(req->rq_reqmsg); LASSERT(req->rq_reqlen); @@ -482,10 +482,12 @@ int sptlrpc_req_ctx_switch(struct ptlrpc_request *req, /* save request message */ reqmsg_size = req->rq_reqlen; - OBD_ALLOC(reqmsg, reqmsg_size); - if (reqmsg == NULL) - return -ENOMEM; - memcpy(reqmsg, req->rq_reqmsg, reqmsg_size); + if (reqmsg_size != 0) { + OBD_ALLOC(reqmsg, reqmsg_size); + if (reqmsg == NULL) + return -ENOMEM; + memcpy(reqmsg, req->rq_reqmsg, reqmsg_size); + } /* release old req/rep buf */ req->rq_cli_ctx = oldctx; @@ -498,18 +500,19 @@ int sptlrpc_req_ctx_switch(struct ptlrpc_request *req, /* alloc new request buffer * we don't need to alloc reply buffer here, leave it to the - * rest procedure of ptlrpc - */ - rc = sptlrpc_cli_alloc_reqbuf(req, reqmsg_size); - if (!rc) { - LASSERT(req->rq_reqmsg); - memcpy(req->rq_reqmsg, reqmsg, reqmsg_size); - } else { - CWARN("failed to alloc reqbuf: %d\n", rc); - req->rq_flvr = old_flvr; - } + * rest procedure of ptlrpc */ + if (reqmsg_size != 0) { + rc = sptlrpc_cli_alloc_reqbuf(req, reqmsg_size); + if (!rc) { + LASSERT(req->rq_reqmsg); + memcpy(req->rq_reqmsg, reqmsg, reqmsg_size); + } else { + CWARN("failed to alloc reqbuf: %d\n", rc); + req->rq_flvr = old_flvr; + } - OBD_FREE(reqmsg, reqmsg_size); + OBD_FREE(reqmsg, reqmsg_size); + } return rc; } @@ -1805,12 +1808,14 @@ int sptlrpc_target_export_check(struct obd_export *exp, /* if it's gss, we only interested in root ctx init */ if (req->rq_auth_gss && - !(req->rq_ctx_init && (req->rq_auth_usr_root || - req->rq_auth_usr_mdt))) { + !(req->rq_ctx_init && + (req->rq_auth_usr_root || req->rq_auth_usr_mdt || + req->rq_auth_usr_ost))) { cfs_spin_unlock(&exp->exp_lock); - CDEBUG(D_SEC, "is good but not root(%d:%d:%d:%d)\n", + CDEBUG(D_SEC, "is good but not root(%d:%d:%d:%d:%d)\n", req->rq_auth_gss, req->rq_ctx_init, - req->rq_auth_usr_root, req->rq_auth_usr_mdt); + req->rq_auth_usr_root, req->rq_auth_usr_mdt, + req->rq_auth_usr_ost); return 0; } @@ -1827,7 +1832,8 @@ int sptlrpc_target_export_check(struct obd_export *exp, /* most cases should return here, we only interested in * gss root ctx init */ if (!req->rq_auth_gss || !req->rq_ctx_init || - (!req->rq_auth_usr_root && !req->rq_auth_usr_mdt)) { + (!req->rq_auth_usr_root && !req->rq_auth_usr_mdt && + !req->rq_auth_usr_ost)) { cfs_spin_unlock(&exp->exp_lock); return 0; } @@ -1919,11 +1925,12 @@ int sptlrpc_target_export_check(struct obd_export *exp, cfs_spin_unlock(&exp->exp_lock); - CWARN("exp %p(%s): req %p (%u|%u|%u|%u|%u) with " + CWARN("exp %p(%s): req %p (%u|%u|%u|%u|%u|%u) with " "unauthorized flavor %x, expect %x|%x(%+ld)|%x(%+ld)\n", exp, exp->exp_obd->obd_name, req, req->rq_auth_gss, req->rq_ctx_init, req->rq_ctx_fini, - req->rq_auth_usr_root, req->rq_auth_usr_mdt, req->rq_flvr.sf_rpc, + req->rq_auth_usr_root, req->rq_auth_usr_mdt, req->rq_auth_usr_ost, + req->rq_flvr.sf_rpc, exp->exp_flvr.sf_rpc, exp->exp_flvr_old[0].sf_rpc, exp->exp_flvr_expire[0] ? @@ -1979,43 +1986,41 @@ EXPORT_SYMBOL(sptlrpc_target_update_exp_flavor); static int sptlrpc_svc_check_from(struct ptlrpc_request *req, int svc_rc) { - if (svc_rc == SECSVC_DROP) - return SECSVC_DROP; + /* peer's claim is unreliable unless gss is being used */ + if (!req->rq_auth_gss || svc_rc == SECSVC_DROP) + return svc_rc; switch (req->rq_sp_from) { case LUSTRE_SP_CLI: + if (req->rq_auth_usr_mdt || req->rq_auth_usr_ost) { + DEBUG_REQ(D_ERROR, req, "faked source CLI"); + svc_rc = SECSVC_DROP; + } + break; case LUSTRE_SP_MDT: + if (!req->rq_auth_usr_mdt) { + DEBUG_REQ(D_ERROR, req, "faked source MDT"); + svc_rc = SECSVC_DROP; + } + break; case LUSTRE_SP_OST: - case LUSTRE_SP_MGC: + if (!req->rq_auth_usr_ost) { + DEBUG_REQ(D_ERROR, req, "faked source OST"); + svc_rc = SECSVC_DROP; + } + break; case LUSTRE_SP_MGS: - case LUSTRE_SP_ANY: + case LUSTRE_SP_MGC: + if (!req->rq_auth_usr_root && !req->rq_auth_usr_mdt && + !req->rq_auth_usr_ost) { + DEBUG_REQ(D_ERROR, req, "faked source MGC/MGS"); + svc_rc = SECSVC_DROP; + } break; + case LUSTRE_SP_ANY: default: DEBUG_REQ(D_ERROR, req, "invalid source %u", req->rq_sp_from); - return SECSVC_DROP; - } - - if (!req->rq_auth_gss) - return svc_rc; - - if (unlikely(req->rq_sp_from == LUSTRE_SP_ANY)) { - CERROR("not specific part\n"); - return SECSVC_DROP; - } - - /* from MDT, must be authenticated as MDT */ - if (unlikely(req->rq_sp_from == LUSTRE_SP_MDT && - !req->rq_auth_usr_mdt)) { - DEBUG_REQ(D_ERROR, req, "fake source MDT"); - return SECSVC_DROP; - } - - /* from OST, must be callback to MDT and CLI, the reverse sec - * was from mdt/root keytab, so it should be MDT or root FIXME */ - if (unlikely(req->rq_sp_from == LUSTRE_SP_OST && - !req->rq_auth_usr_mdt && !req->rq_auth_usr_root)) { - DEBUG_REQ(D_ERROR, req, "fake source OST"); - return SECSVC_DROP; + svc_rc = SECSVC_DROP; } return svc_rc; diff --git a/lustre/utils/gss/lgss_keyring.c b/lustre/utils/gss/lgss_keyring.c index b220317..26777767 100644 --- a/lustre/utils/gss/lgss_keyring.c +++ b/lustre/utils/gss/lgss_keyring.c @@ -105,8 +105,9 @@ struct keyring_upcall_param { uint64_t kup_nid; char kup_tgt[64]; char kup_mech[16]; - int kup_is_root; - int kup_is_mds; + unsigned int kup_is_root:1, + kup_is_mdt:1, + kup_is_ost:1; }; /**************************************** @@ -535,7 +536,7 @@ out_cred: * [1]: mech_name (string) * [2]: uid (uint) * [3]: gid (uint) - * [4]: flags (chars) FMT: r-root; m-mds + * [4]: flags (string) FMT: r-root; m-mdt; o-ost * [5]: lustre_svc (uint) * [6]: target_nid (uint64) * [7]: target_uuid (string) @@ -581,17 +582,19 @@ static int parse_callout_info(const char *coinfo, if (strchr(data[4], 'r')) uparam->kup_is_root = 1; if (strchr(data[4], 'm')) - uparam->kup_is_mds = 1; + uparam->kup_is_mdt = 1; + if (strchr(data[4], 'o')) + uparam->kup_is_ost = 1; uparam->kup_svc = strtol(data[5], NULL, 0); uparam->kup_nid = strtoll(data[6], NULL, 0); strncpy(uparam->kup_tgt, data[7], sizeof(uparam->kup_tgt)); logmsg(LL_DEBUG, "parse call out info: secid %d, mech %s, ugid %u:%u " - "is_root %d, is_mds %d, svc %d, nid 0x%Lx, tgt %s\n", + "is_root %d, is_mdt %d, is_ost %d, svc %d, nid 0x%Lx, tgt %s\n", uparam->kup_secid, uparam->kup_mech, uparam->kup_uid, uparam->kup_gid, - uparam->kup_is_root, uparam->kup_is_mds, uparam->kup_svc, - uparam->kup_nid, uparam->kup_tgt); + uparam->kup_is_root, uparam->kup_is_mdt, uparam->kup_is_ost, + uparam->kup_svc, uparam->kup_nid, uparam->kup_tgt); return 0; } @@ -714,8 +717,9 @@ int main(int argc, char *argv[]) } cred->lc_uid = uparam.kup_uid; - cred->lc_fl_root = (uparam.kup_is_root != 0); - cred->lc_fl_mds = (uparam.kup_is_mds != 0); + cred->lc_root_flags |= uparam.kup_is_root ? LGSS_ROOT_CRED_ROOT : 0; + cred->lc_root_flags |= uparam.kup_is_mdt ? LGSS_ROOT_CRED_MDT : 0; + cred->lc_root_flags |= uparam.kup_is_ost ? LGSS_ROOT_CRED_OST : 0; cred->lc_tgt_nid = uparam.kup_nid; cred->lc_tgt_svc = uparam.kup_svc; @@ -731,7 +735,7 @@ int main(int argc, char *argv[]) * on it, and share it among all root sessions; otherswise link to * session keyring. */ - if (cred->lc_fl_root || cred->lc_fl_mds) + if (cred->lc_root_flags != 0) inst_keyring = 0; else inst_keyring = KEY_SPEC_SESSION_KEYRING; diff --git a/lustre/utils/gss/lgss_krb5_utils.c b/lustre/utils/gss/lgss_krb5_utils.c index e0aa169..7310e33 100644 --- a/lustre/utils/gss/lgss_krb5_utils.c +++ b/lustre/utils/gss/lgss_krb5_utils.c @@ -156,13 +156,15 @@ static void lgss_krb5_mutex_unlock(void) const char *krb5_cc_type_mem = "MEMORY:"; const char *krb5_cc_type_file = "FILE:"; +const char *krb5_cred_root_suffix = "lustre_root"; +const char *krb5_cred_mds_suffix = "lustre_mds"; +const char *krb5_cred_oss_suffix = "lustre_oss"; char *krb5_this_realm = NULL; char *krb5_keytab_file = "/etc/krb5.keytab"; char *krb5_cc_type = "FILE:"; char *krb5_cc_dir = "/tmp"; char *krb5_cred_prefix = "krb5cc_"; -char *krb5_cred_root_suffix = "lustre_root"; struct lgss_krb5_cred { char kc_ccname[128]; @@ -272,9 +274,12 @@ int svc_princ_verify_host(krb5_context ctx, static int lkrb5_cc_check_tgt_princ(krb5_context ctx, krb5_ccache ccache, - krb5_principal princ) + krb5_principal princ, + unsigned int flag) { - logmsg(LL_TRACE, "principal: realm %.*s, type %d, size %d, name %.*s\n", + const char *princ_name; + + logmsg(LL_DEBUG, "principal: realm %.*s, type %d, size %d, name %.*s\n", krb5_princ_realm(ctx, princ)->length, krb5_princ_realm(ctx, princ)->data, krb5_princ_type(ctx, princ), @@ -298,67 +303,94 @@ int lkrb5_cc_check_tgt_princ(krb5_context ctx, return -1; } - /* if it's mds service principal, or lustre_root principal - * with host part, verify the hostname. - * note we allow lustre_root without host part */ - if (lgss_krb5_strcmp(krb5_princ_name(ctx, princ), - LGSS_SVC_MDS_STR) == 0) { - if (svc_princ_verify_host(ctx, princ, LL_WARN)) { - logmsg(LL_WARN, "mds service principal doesn't belong " - "to this node\n"); + /* check principal name */ + switch (flag) { + case LGSS_ROOT_CRED_ROOT: + princ_name = LGSS_USR_ROOT_STR; + break; + case LGSS_ROOT_CRED_MDT: + princ_name = LGSS_SVC_MDS_STR; + break; + case LGSS_ROOT_CRED_OST: + princ_name = LGSS_SVC_OSS_STR; + break; + default: + lassert(0); + } + + if (lgss_krb5_strcmp(krb5_princ_name(ctx, princ), princ_name)) { + logmsg(LL_WARN, "%.*s: we expect %s instead\n", + krb5_princ_name(ctx, princ)->length, + krb5_princ_name(ctx, princ)->data, + princ_name); + return -1; + } + + /* + * verify the hostname part of the principal, except we do allow + * lustre_root without binding to a host. + */ + if (krb5_princ_component(ctx, princ, 1) == NULL) { + if (flag != LGSS_ROOT_CRED_ROOT) { + logmsg(LL_WARN, "%.*s: missing hostname\n", + krb5_princ_name(ctx, princ)->length, + krb5_princ_name(ctx, princ)->data); return -1; } - } else if (lgss_krb5_strcmp(krb5_princ_name(ctx, princ), - LGSS_USR_ROOT_STR) == 0) { - if (krb5_princ_component(ctx, princ, 1) != NULL && - svc_princ_verify_host(ctx, princ, LL_WARN)) { - logmsg(LL_WARN, "lustre_root principal doesn't belong " - "to this node\n"); + } else { + if (svc_princ_verify_host(ctx, princ, LL_WARN)) { + logmsg(LL_DEBUG, "%.*s: doesn't belong to this node\n", + krb5_princ_name(ctx, princ)->length, + krb5_princ_name(ctx, princ)->data); return -1; } - } else { - logmsg(LL_WARN, "unexpected krb5 cc principal name %.*s\n", - krb5_princ_name(ctx, princ)->length, - krb5_princ_name(ctx, princ)->data); - return -1; } logmsg(LL_TRACE, "principal is OK\n"); return 0; } -/* - * find out whether current TGT cache is valid or not +/** + * compose the TGT cc name, according to the root flags. */ static -int lkrb5_check_root_tgt_cc(krb5_context ctx, - krb5_ccache ccache, - char *ccname) +void get_root_tgt_ccname(char *ccname, int size, unsigned int flag) +{ + const char *suffix; + + switch (flag) { + case LGSS_ROOT_CRED_ROOT: + suffix = krb5_cred_root_suffix; + break; + case LGSS_ROOT_CRED_MDT: + suffix = krb5_cred_mds_suffix; + break; + case LGSS_ROOT_CRED_OST: + suffix = krb5_cred_oss_suffix; + break; + default: + lassert(0); + } + + snprintf(ccname, size, "%s%s/%s%s_%s", + krb5_cc_type, krb5_cc_dir, krb5_cred_prefix, + suffix, krb5_this_realm); +} + +static +int lkrb5_check_root_tgt_cc_base(krb5_context ctx, + krb5_ccache ccache, + char *ccname, + unsigned int flag) { - struct stat statbuf; krb5_ccache tgt_ccache; krb5_creds cred; krb5_principal princ; krb5_cc_cursor cursor; krb5_error_code code; - char *ccfile; time_t now; int rc = -1, found = 0; - if (strncmp(ccname, krb5_cc_type, strlen(krb5_cc_type_file))) { - logmsg(LL_ERR, "unexpected cc type\n"); - return -1; - } - - ccfile = ccname + strlen(krb5_cc_type_file); - logmsg(LL_TRACE, "cc file name: %s\n", ccfile); - - /* firstly make sure the cache file is there */ - if (stat(ccfile, &statbuf)) { - logmsg(LL_DEBUG, "krb5 cc %s: %s\n", ccname, strerror(errno)); - return -1; - } - /* prepare parsing the cache file */ code = krb5_cc_resolve(ctx, ccname, &tgt_ccache); if (code) { @@ -374,10 +406,8 @@ int lkrb5_check_root_tgt_cc(krb5_context ctx, goto out_cc; } - if (lkrb5_cc_check_tgt_princ(ctx, tgt_ccache, princ)) { - logmsg(LL_WARN, "cc principal is not valid\n"); + if (lkrb5_cc_check_tgt_princ(ctx, tgt_ccache, princ, flag)) goto out_princ; - } /* * find a valid entry @@ -465,6 +495,47 @@ out_cc: return rc; } +/** + * find out whether current TGT cache is valid or not + */ +static +int lkrb5_check_root_tgt_cc(krb5_context ctx, + krb5_ccache ccache, + unsigned int root_flags) +{ + struct stat statbuf; + unsigned int flag; + char ccname[1024]; + char *ccfile; + int i, rc; + + for (i = 0; i < LGSS_ROOT_CRED_NR; i++) { + flag = 1 << i; + + if ((root_flags & flag) == 0) + continue; + + get_root_tgt_ccname(ccname, sizeof(ccname), flag); + logmsg(LL_DEBUG, "root krb5 TGT ccname: %s\n", ccname); + + /* currently we only support type "FILE", firstly make sure + * the cache file is there */ + ccfile = ccname + strlen(krb5_cc_type); + if (stat(ccfile, &statbuf)) { + logmsg(LL_DEBUG, "krb5 cc %s: %s\n", + ccname, strerror(errno)); + continue; + } + + rc = lkrb5_check_root_tgt_cc_base(ctx, ccache, ccname, flag); + if (rc == 0) + return 0; + } + + logmsg(LL_TRACE, "doesn't find a valid tgt cc\n"); + return -1; +} + static int lkrb5_get_root_tgt_keytab(krb5_context ctx, krb5_ccache ccache, @@ -559,14 +630,15 @@ out_cred: static int lkrb5_refresh_root_tgt_cc(krb5_context ctx, krb5_ccache ccache, - const char *ccname) + unsigned int root_flags) { krb5_keytab kt; krb5_keytab_entry kte; krb5_kt_cursor cursor; - krb5_principal princ = NULL, princ2; + krb5_principal princ = NULL; krb5_error_code code; - int general_root = 0; + char ccname[1024]; + unsigned int flag = 0; int rc = -1; /* prepare parsing the keytab file */ @@ -585,6 +657,8 @@ int lkrb5_refresh_root_tgt_cc(krb5_context ctx, /* iterate keytab to find proper a entry */ do { + krb5_data *princname; + code = krb5_kt_next_entry(ctx, kt, &kte, &cursor); if (code != 0) break; @@ -601,77 +675,44 @@ int lkrb5_refresh_root_tgt_cc(krb5_context ctx, if (!princ_is_local_realm(ctx, kte.principal)) continue; - /* lustre_root[/host]@realm */ - if (lgss_krb5_strcmp(krb5_princ_name(ctx, kte.principal), - LGSS_USR_ROOT_STR) == 0) { - int tmp_general_root = 0; - - if (krb5_princ_component(ctx, kte.principal,1) == NULL){ - if (princ != NULL) { - logmsg(LL_TRACE, "lustre_root: " - "already picked one, skip\n"); - continue; - } - - tmp_general_root = 1; - } else { - if (svc_princ_verify_host(ctx, kte.principal, - LL_TRACE)) { - logmsg(LL_TRACE, "lustre_root: " - "doesn't belong to this node\n"); - continue; - } - - if (princ != NULL && !general_root) { - logmsg(LL_TRACE, "lustre_root: already " - "have a host-specific one, " - "skip\n"); - continue; - } - } - - code = krb5_copy_principal(ctx, kte.principal, &princ2); - if (code) { - logmsg(LL_ERR, "copy lustre_root princ: %s\n", - krb5_err_msg(code)); - continue; - } - - if (princ != NULL) { - logmsg(LL_TRACE, "release a lustre_root one\n"); - krb5_free_principal(ctx, princ); - } - princ = princ2; - - general_root = tmp_general_root; + princname = krb5_princ_name(ctx, kte.principal); + + if ((root_flags & LGSS_ROOT_CRED_ROOT) != 0 && + lgss_krb5_strcmp(princname, LGSS_USR_ROOT_STR) == 0) { + flag = LGSS_ROOT_CRED_ROOT; + } else if ((root_flags & LGSS_ROOT_CRED_MDT) != 0 && + lgss_krb5_strcmp(princname, LGSS_SVC_MDS_STR) == 0) { + flag = LGSS_ROOT_CRED_MDT; + } else if ((root_flags & LGSS_ROOT_CRED_OST) != 0 && + lgss_krb5_strcmp(princname, LGSS_SVC_OSS_STR) == 0) { + flag = LGSS_ROOT_CRED_OST; + } else { + logmsg(LL_TRACE, "not what we want, skip\n"); continue; } - /* lustre_mds/host@realm */ - if (lgss_krb5_strcmp(krb5_princ_name(ctx, kte.principal), - LGSS_SVC_MDS_STR) == 0) { - if (svc_princ_verify_host(ctx, kte.principal, - LL_TRACE)) { - logmsg(LL_TRACE, "mds service principal: " - "doesn't belong to this node\n"); + if (krb5_princ_component(ctx, kte.principal, 1) == NULL) { + if (flag != LGSS_ROOT_CRED_ROOT) { + logmsg(LL_TRACE, "no hostname, skip\n"); continue; } - - /* select this one */ - code = krb5_copy_principal(ctx, kte.principal, &princ2); - if (code) { - logmsg(LL_ERR, "copy lustre_mds princ: %s\n", - krb5_err_msg(code)); + } else { + if (svc_princ_verify_host(ctx, kte.principal, + LL_TRACE)) { + logmsg(LL_TRACE, "doesn't belong to this " + "node, skip\n"); continue; } + } - if (princ != NULL) { - logmsg(LL_TRACE, "release a lustre_root one\n"); - krb5_free_principal(ctx, princ); - } - princ = princ2; - break; + code = krb5_copy_principal(ctx, kte.principal, &princ); + if (code) { + logmsg(LL_ERR, "copy princ: %s\n", krb5_err_msg(code)); + continue; } + + lassert(princ != NULL); + break; } while (1); krb5_kt_end_seq_get(ctx, kt, &cursor); @@ -682,6 +723,7 @@ int lkrb5_refresh_root_tgt_cc(krb5_context ctx, } /* obtain root TGT */ + get_root_tgt_ccname(ccname, sizeof(ccname), flag); rc = lkrb5_get_root_tgt_keytab(ctx, ccache, kt, princ, ccname); krb5_free_principal(ctx, princ); @@ -697,22 +739,14 @@ int lkrb5_prepare_root_cred(struct lgss_cred *cred) krb5_ccache ccache; krb5_error_code code; struct lgss_krb5_cred *kcred; - char tgtcc[1024]; int rc = -1; lassert(krb5_this_realm != NULL); kcred = (struct lgss_krb5_cred *) cred->lc_mech_cred; - /* compose the TGT cc name */ - snprintf(tgtcc, sizeof(tgtcc), "%s%s/%s%s_%s", - krb5_cc_type, krb5_cc_dir, krb5_cred_prefix, - krb5_cred_root_suffix, krb5_this_realm); - logmsg(LL_DEBUG, "root krb5 TGT ccname: %s\n", tgtcc); - /* compose the memory cc name, since the only user is myself, - * the name could be fixed - */ + * the name could be fixed */ snprintf(kcred->kc_ccname, sizeof(kcred->kc_ccname), "%s/self", krb5_cc_type_mem); logmsg(LL_TRACE, "private cc: %s\n", kcred->kc_ccname); @@ -737,9 +771,10 @@ int lkrb5_prepare_root_cred(struct lgss_cred *cred) */ lgss_krb5_mutex_lock(); - rc = lkrb5_check_root_tgt_cc(ctx, ccache, tgtcc); + rc = lkrb5_check_root_tgt_cc(ctx, ccache, cred->lc_root_flags); if (rc != 0) - rc = lkrb5_refresh_root_tgt_cc(ctx, ccache, tgtcc); + rc = lkrb5_refresh_root_tgt_cc(ctx, ccache, + cred->lc_root_flags); if (rc == 0) rc = lgss_krb5_set_ccache_name(kcred->kc_ccname); @@ -797,7 +832,7 @@ int lgss_krb5_prepare_cred(struct lgss_cred *cred) kcred->kc_remove = 0; cred->lc_mech_cred = kcred; - if (cred->lc_fl_root || cred->lc_fl_mds) { + if (cred->lc_root_flags != 0) { if (lgss_krb5_get_local_realm()) return -1; diff --git a/lustre/utils/gss/lgss_utils.c b/lustre/utils/gss/lgss_utils.c index 9c41f3b..c611218 100644 --- a/lustre/utils/gss/lgss_utils.c +++ b/lustre/utils/gss/lgss_utils.c @@ -104,7 +104,7 @@ const char *lgss_svc_str[LGSS_SVC_MAX] = { [LGSS_SVC_MGS] = LGSS_SVC_MGS_STR, [LGSS_SVC_MDS] = LGSS_SVC_MDS_STR, - [LGSS_SVC_OSS] = LGSS_SVC_OST_STR, + [LGSS_SVC_OSS] = LGSS_SVC_OSS_STR, }; /**************************************** diff --git a/lustre/utils/gss/lgss_utils.h b/lustre/utils/gss/lgss_utils.h index 2e52843..0bec168 100644 --- a/lustre/utils/gss/lgss_utils.h +++ b/lustre/utils/gss/lgss_utils.h @@ -49,7 +49,7 @@ #define LGSS_SVC_MGS_STR "lustre_mgs" #define LGSS_SVC_MDS_STR "lustre_mds" -#define LGSS_SVC_OST_STR "lustre_oss" +#define LGSS_SVC_OSS_STR "lustre_oss" #define LGSS_USR_ROOT_STR "lustre_root" typedef enum { @@ -160,10 +160,17 @@ struct lgss_mech_type { int (*lmt_using_cred)(struct lgss_cred *cred); }; +enum { + LGSS_ROOT_CRED_ROOT = 0x01, + LGSS_ROOT_CRED_MDT = 0x02, + LGSS_ROOT_CRED_OST = 0x04, + + LGSS_ROOT_CRED_NR = 3 +}; + struct lgss_cred { int lc_uid; - unsigned int lc_fl_root:1, - lc_fl_mds:1; + unsigned int lc_root_flags; uint64_t lc_tgt_nid; uint32_t lc_tgt_svc; diff --git a/lustre/utils/gss/svcgssd_proc.c b/lustre/utils/gss/svcgssd_proc.c index 5074a0e..6a1fe4e 100644 --- a/lustre/utils/gss/svcgssd_proc.c +++ b/lustre/utils/gss/svcgssd_proc.c @@ -62,6 +62,7 @@ struct svc_cred { uint32_t cr_remote; uint32_t cr_usr_root; uint32_t cr_usr_mds; + uint32_t cr_usr_oss; uid_t cr_uid; uid_t cr_mapped_uid; uid_t cr_gid; @@ -91,6 +92,7 @@ do_svc_downcall(gss_buffer_desc *out_handle, struct svc_cred *cred, qword_printint(f, cred->cr_remote); qword_printint(f, cred->cr_usr_root); qword_printint(f, cred->cr_usr_mds); + qword_printint(f, cred->cr_usr_oss); qword_printint(f, cred->cr_mapped_uid); qword_printint(f, cred->cr_uid); qword_printint(f, cred->cr_gid); @@ -308,7 +310,8 @@ get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred, gss_OID name_type = GSS_C_NO_OID; struct passwd *pw; - cred->cr_remote = cred->cr_usr_root = cred->cr_usr_mds = 0; + cred->cr_remote = 0; + cred->cr_usr_root = cred->cr_usr_mds = cred->cr_usr_oss = 0; cred->cr_uid = cred->cr_mapped_uid = cred->cr_gid = -1; maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type); @@ -344,9 +347,8 @@ get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred, if (host) *host++ = '\0'; - if (strcmp(sname, GSSD_SERVICE_OSS) == 0 || - strcmp(sname, GSSD_SERVICE_MGS) == 0) { - printerr(0, "forbid %s as user name\n", sname); + if (strcmp(sname, GSSD_SERVICE_MGS) == 0) { + printerr(0, "forbid %s as a user name\n", sname); goto out_free; } @@ -366,61 +368,84 @@ get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred, goto out_free; } } else { - if (!strcmp(sname, GSSD_SERVICE_MDS)) { - printerr(0, "ERROR: "GSSD_SERVICE_MDS"@%s from %016llx " - "doesn't bind with hostname\n", realm, nid); + if (!strcmp(sname, GSSD_SERVICE_MDS) || + !strcmp(sname, GSSD_SERVICE_OSS)) { + printerr(0, "ERROR: %s@%s from %016llx doesn't " + "bind with hostname\n", sname, realm, nid); goto out_free; } } - /* 2. check realm */ - if (!mds_local_realm || strcasecmp(mds_local_realm, realm)) { - cred->cr_remote = 1; - - /* Allow mapped user from remote realm */ - if (cred->cr_mapped_uid != -1) - res = 0; - /* Allow OSS auth using client machine credential */ - else if (lustre_svc == LUSTRE_GSS_SVC_OSS && - !strcmp(sname, LUSTRE_ROOT_NAME)) - res = 0; - /* Invalid remote user */ - else - printerr(0, "ERROR: %s%s%s@%s from %016llx is remote " - "but without mapping\n", sname, - host ? "/" : "", host ? host : "", realm, nid); + /* 2. check realm and user */ + switch (lustre_svc) { + case LUSTRE_GSS_SVC_MDS: + if (strcasecmp(mds_local_realm, realm)) { + cred->cr_remote = 1; + + /* only allow mapped user from remote realm */ + if (cred->cr_mapped_uid == -1) { + printerr(0, "ERROR: %s%s%s@%s from %016llx " + "is remote but without mapping\n", + sname, host ? "/" : "", + host ? host : "", realm, nid); + break; + } + } else { + if (!strcmp(sname, LUSTRE_ROOT_NAME)) { + cred->cr_uid = 0; + cred->cr_usr_root = 1; + } else if (!strcmp(sname, GSSD_SERVICE_MDS)) { + cred->cr_uid = 0; + cred->cr_usr_mds = 1; + } else if (!strcmp(sname, GSSD_SERVICE_OSS)) { + printerr(0, "ERROR: MDS doesn't accept " + "user "GSSD_SERVICE_OSS"\n"); + break; + } else { + pw = getpwnam(sname); + if (pw != NULL) { + cred->cr_uid = pw->pw_uid; + printerr(2, "%s resolve to uid %u\n", + sname, cred->cr_uid); + } else if (cred->cr_mapped_uid != -1) { + printerr(2, "user %s from %016llx is " + "mapped to %u\n", sname, nid, + cred->cr_mapped_uid); + } else { + printerr(0, "ERROR: invalid user, " + "%s/%s@%s from %016llx\n", + sname, host, realm, nid); + break; + } + } + } - /* skip local user check */ - goto out_free; + res = 0; + break; + case LUSTRE_GSS_SVC_MGS: + if (!strcmp(sname, GSSD_SERVICE_OSS)) { + cred->cr_uid = 0; + cred->cr_usr_oss = 1; + } + /* fall through */ + case LUSTRE_GSS_SVC_OSS: + if (!strcmp(sname, LUSTRE_ROOT_NAME)) { + cred->cr_uid = 0; + cred->cr_usr_root = 1; + } else if (!strcmp(sname, GSSD_SERVICE_MDS)) { + cred->cr_uid = 0; + cred->cr_usr_mds = 1; + } else { + printerr(0, "ERROR: svc %d doesn't accept user %s" + "from %016llx\n", lustre_svc, sname, nid); + break; + } + res = 0; + break; + default: + assert(0); } - /* 3. check user */ - if (!(pw = getpwnam(sname))) { - /* map lustre_root/lustre_mds to root user, which is subject - * to further mapping by root-squash in kernel. */ - if (!strcmp(sname, LUSTRE_ROOT_NAME)) { - cred->cr_uid = 0; - cred->cr_usr_root = 1; - } else if (!strcmp(sname, GSSD_SERVICE_MDS)) { - cred->cr_uid = 0; - cred->cr_usr_mds = 1; - } else { - if (cred->cr_mapped_uid == -1) { - printerr(0, "ERROR: invalid user, %s/%s@%s " - "from %016llx\n", sname, host, - realm, nid); - goto out_free; - } - } - printerr(2, "user %s from %016llx is mapped to %u\n", - sname, nid, cred->cr_mapped_uid); - } else { - /* note: a mapped local user will go to here too */ - cred->cr_uid = pw->pw_uid; - printerr(2, "%s resolve to uid %u\n", sname, cred->cr_uid); - } - - res = 0; out_free: if (!res) printerr(1, "%s: authenticated %s%s%s@%s from %016llx\n", -- 1.8.3.1