Whamcloud - gitweb
b=23728 gss: allow oss authenticate with mgs.
authorEric Mei <eric.mei@oracle.com>
Fri, 15 Oct 2010 03:41:11 +0000 (21:41 -0600)
committerVitaly Fertman <vitaly.fertman@sun.com>
Mon, 18 Oct 2010 22:24:16 +0000 (02:24 +0400)
r=di.wang

12 files changed:
lustre/include/lustre_net.h
lustre/ptlrpc/gss/gss_cli_upcall.c
lustre/ptlrpc/gss/gss_internal.h
lustre/ptlrpc/gss/gss_keyring.c
lustre/ptlrpc/gss/gss_svc_upcall.c
lustre/ptlrpc/gss/sec_gss.c
lustre/ptlrpc/sec.c
lustre/utils/gss/lgss_keyring.c
lustre/utils/gss/lgss_krb5_utils.c
lustre/utils/gss/lgss_utils.c
lustre/utils/gss/lgss_utils.h
lustre/utils/gss/svcgssd_proc.c

index a85c8c3..7693eef 100644 (file)
@@ -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,
index ed2f672..eb9536b 100644 (file)
@@ -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;
index 08e91af..78ae0d5 100644 (file)
@@ -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;
 };
index 4cd78d7..a6dc099 100644 (file)
@@ -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,
index aaa4c85..307f1ef 100644 (file)
@@ -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) {
index 2a32e3c..74b0d33 100644 (file)
@@ -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;
index bf7db85..1494e0d 100644 (file)
@@ -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;
index b220317..2677776 100644 (file)
@@ -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;
index e0aa169..7310e33 100644 (file)
@@ -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;
 
index 9c41f3b..c611218 100644 (file)
 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,
 };
 
 /****************************************
index 2e52843..0bec168 100644 (file)
@@ -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;
 
index 5074a0e..6a1fe4e 100644 (file)
@@ -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",