Whamcloud - gitweb
LU-6356 gss: call out info must include 'self nid' 42/14042/2
authorSebastien Buisson <sebastien.buisson@bull.net>
Wed, 11 Mar 2015 10:13:31 +0000 (11:13 +0100)
committerOleg Drokin <oleg.drokin@intel.com>
Tue, 28 Apr 2015 05:30:55 +0000 (05:30 +0000)
When using interconnect different from eth, svc_princ_verify_host()
fails because remote node uses nid of target to build principal host
information.
Call out info must include a self nid so that svc_princ_verify_host()
can successfully match the host info built by the remote node.
For that purpose we add a new kup_selfnid field in struct
keyring_upcall_param, and a new lc_self_nid field in struct
lgss_cred.

Signed-off-by: Sebastien Buisson <sebastien.buisson@bull.net>
Change-Id: Ia44503a188feb162b32dea56333de6bafdfcfcd2
Reviewed-on: http://review.whamcloud.com/14042
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Jeremy Filizetti <jeremy.filizetti@gmail.com>
Reviewed-by: Dmitry Eremin <dmitry.eremin@intel.com>
Reviewed-by: Oleg Drokin <oleg.drokin@intel.com>
lustre/ptlrpc/gss/gss_keyring.c
lustre/ptlrpc/gss/gss_svc_upcall.c
lustre/utils/gss/lgss_keyring.c
lustre/utils/gss/lgss_krb5_utils.c
lustre/utils/gss/lgss_utils.h
lustre/utils/gss/svcgssd_proc.c

index 2803721..c0438e9 100644 (file)
@@ -757,11 +757,12 @@ struct ptlrpc_cli_ctx * gss_sec_lookup_ctx_kr(struct ptlrpc_sec *sec,
         if (coinfo == NULL)
                 goto out;
 
-        snprintf(coinfo, coinfo_size, "%d:%s:%u:%u:%s:%d:"LPX64":%s",
-                 sec->ps_id, sec2gsec(sec)->gs_mech->gm_name,
-                 vcred->vc_uid, vcred->vc_gid,
-                 co_flags, import_to_gss_svc(imp),
-                 imp->imp_connection->c_peer.nid, imp->imp_obd->obd_name);
+       snprintf(coinfo, coinfo_size, "%d:%s:%u:%u:%s:%d:"LPX64":%s:"LPX64,
+                sec->ps_id, sec2gsec(sec)->gs_mech->gm_name,
+                vcred->vc_uid, vcred->vc_gid,
+                co_flags, import_to_gss_svc(imp),
+                imp->imp_connection->c_peer.nid, imp->imp_obd->obd_name,
+                imp->imp_connection->c_self);
 
         CDEBUG(D_SEC, "requesting key for %s\n", desc);
 
index e3a7ab1..429b1eb 100644 (file)
@@ -550,13 +550,13 @@ static int rsc_parse(struct cache_detail *cd, char *mesg, int mlen)
         }
         rsci.ctx.gsc_remote = (tmp_int != 0);
 
-        /* root user flag */
-        rv = get_int(&mesg, &tmp_int);
-        if (rv) {
-                CERROR("fail to get oss user flag\n");
-                goto out;
-        }
-        rsci.ctx.gsc_usr_root = (tmp_int != 0);
+       /* root user flag */
+       rv = get_int(&mesg, &tmp_int);
+       if (rv) {
+               CERROR("fail to get root user flag\n");
+               goto out;
+       }
+       rsci.ctx.gsc_usr_root = (tmp_int != 0);
 
         /* mds user flag */
         rv = get_int(&mesg, &tmp_int);
index 2a3fdf2..17c770e 100644 (file)
@@ -96,19 +96,20 @@ struct lgss_init_res {
 };
 
 struct keyring_upcall_param {
-        uint32_t        kup_ver;
-        uint32_t        kup_secid;
-        uint32_t        kup_uid;
-        uint32_t        kup_fsuid;
-        uint32_t        kup_gid;
-        uint32_t        kup_fsgid;
-        uint32_t        kup_svc;
-        uint64_t        kup_nid;
-        char            kup_tgt[64];
-        char            kup_mech[16];
-        unsigned int    kup_is_root:1,
-                        kup_is_mdt:1,
-                        kup_is_ost:1;
+       uint32_t        kup_ver;
+       uint32_t        kup_secid;
+       uint32_t        kup_uid;
+       uint32_t        kup_fsuid;
+       uint32_t        kup_gid;
+       uint32_t        kup_fsgid;
+       uint32_t        kup_svc;
+       uint64_t        kup_nid;
+       uint64_t        kup_selfnid;
+       char            kup_tgt[64];
+       char            kup_mech[16];
+       unsigned int    kup_is_root:1,
+                       kup_is_mdt:1,
+                       kup_is_ost:1;
 };
 
 /****************************************
@@ -541,16 +542,17 @@ out_cred:
  *  [5]: lustre_svc     (uint)
  *  [6]: target_nid     (uint64)
  *  [7]: target_uuid    (string)
+ *  [8]: self_nid        (uint64)
  */
 static int parse_callout_info(const char *coinfo,
                               struct keyring_upcall_param *uparam)
 {
-        const int       nargs = 8;
-        char            buf[1024];
-        char           *string = buf;
-        int             length, i;
-        char           *data[nargs];
-        char           *pos;
+       const int       nargs = 9;
+       char            buf[1024];
+       char           *string = buf;
+       int             length, i;
+       char           *data[nargs];
+       char           *pos;
 
         length = strlen(coinfo) + 1;
         if (length > 1024) {
@@ -572,31 +574,34 @@ static int parse_callout_info(const char *coinfo,
         }
         data[i] = string;
 
-        logmsg(LL_TRACE, "components: %s,%s,%s,%s,%s,%s,%s,%s\n",
-               data[0], data[1], data[2], data[3], data[4], data[5],
-               data[6], data[7]);
+       logmsg(LL_TRACE, "components: %s,%s,%s,%s,%s,%s,%s,%s,%s\n",
+              data[0], data[1], data[2], data[3], data[4], data[5],
+              data[6], data[7], data[8]);
 
-        uparam->kup_secid = strtol(data[0], NULL, 0);
+       uparam->kup_secid = strtol(data[0], NULL, 0);
        strlcpy(uparam->kup_mech, data[1], sizeof(uparam->kup_mech));
-        uparam->kup_uid = strtol(data[2], NULL, 0);
-        uparam->kup_gid = strtol(data[3], NULL, 0);
-        if (strchr(data[4], 'r'))
-                uparam->kup_is_root = 1;
-        if (strchr(data[4], 'm'))
-                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);
+       uparam->kup_uid = strtol(data[2], NULL, 0);
+       uparam->kup_gid = strtol(data[3], NULL, 0);
+       if (strchr(data[4], 'r'))
+               uparam->kup_is_root = 1;
+       if (strchr(data[4], 'm'))
+               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);
        strlcpy(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_mdt %d, is_ost %d, svc %d, nid 0x%llx, tgt %s\n",
-               uparam->kup_secid, uparam->kup_mech,
-               uparam->kup_uid, uparam->kup_gid,
-               uparam->kup_is_root, uparam->kup_is_mdt, uparam->kup_is_ost,
-               uparam->kup_svc, uparam->kup_nid, uparam->kup_tgt);
-        return 0;
+       uparam->kup_selfnid = strtoll(data[8], NULL, 0);
+
+       logmsg(LL_DEBUG, "parse call out info: secid %d, mech %s, ugid %u:%u, "
+              "is_root %d, is_mdt %d, is_ost %d, svc %d, nid 0x%llx, tgt %s, "
+              "self nid 0x%llx\n",
+              uparam->kup_secid, uparam->kup_mech,
+              uparam->kup_uid, uparam->kup_gid,
+              uparam->kup_is_root, uparam->kup_is_mdt, uparam->kup_is_ost,
+              uparam->kup_svc, uparam->kup_nid, uparam->kup_tgt,
+              uparam->kup_selfnid);
+       return 0;
 }
 
 #define LOG_LEVEL_PATH  "/proc/fs/lustre/sptlrpc/gss/lgss_keyring/debug_level"
@@ -717,12 +722,13 @@ int main(int argc, char *argv[])
                 return 1;
         }
 
-        cred->lc_uid = uparam.kup_uid;
-        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;
+       cred->lc_uid = uparam.kup_uid;
+       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;
+       cred->lc_self_nid = uparam.kup_selfnid;
 
         if (lgss_prepare_cred(cred)) {
                 logmsg(LL_ERR, "key %08x: failed to prepare credentials "
index 2b2d9d8..ec6614f 100644 (file)
 #endif
 #include <krb5.h>
 
+#include "lsupport.h"
 #include "lgss_utils.h"
 #include "lgss_krb5_utils.h"
 
@@ -234,46 +235,62 @@ int princ_is_local_realm(krb5_context ctx, krb5_principal princ)
 
 static
 int svc_princ_verify_host(krb5_context ctx,
-                          krb5_principal princ,
-                          loglevel_t loglevel)
+                         krb5_principal princ,
+                         uint64_t self_nid,
+                         loglevel_t loglevel)
 {
-        struct utsname utsbuf;
-        struct hostent *host;
-
-        if (krb5_princ_component(ctx, princ, 1) == NULL) {
-                logmsg(loglevel, "service principal has no host part\n");
-                return -1;
-        }
-
-        if (uname(&utsbuf)) {
-                logmsg(loglevel, "get UTS name: %s\n", strerror(errno));
-                return -1;
-        }
-
-        host = gethostbyname(utsbuf.nodename);
-        if (host == NULL) {
-                logmsg(loglevel, "failed to get local hostname\n");
-                return -1;
-        }
-
-        if (lgss_krb5_strcasecmp(krb5_princ_component(ctx, princ, 1),
-                                 host->h_name)) {
-                logmsg(loglevel, "service principal: hostname %.*s "
-                       "doesn't match localhost %s\n",
-                       krb5_princ_component(ctx, princ, 1)->length,
-                       krb5_princ_component(ctx, princ, 1)->data,
-                       host->h_name);
-                return -1;
-        }
-
-        return 0;
+       struct utsname utsbuf;
+       struct hostent *host;
+       const int max_namelen = 512;
+       char namebuf[max_namelen];
+       char *h_name;
+
+       if (krb5_princ_component(ctx, princ, 1) == NULL) {
+               logmsg(loglevel, "service principal has no host part\n");
+               return -1;
+       }
+
+       if (self_nid != 0) {
+               if (lnet_nid2hostname(self_nid, namebuf, max_namelen)) {
+                       logmsg(loglevel,
+                              "can't resolve hostname from nid %llx\n",
+                              self_nid);
+                       return -1;
+               }
+               h_name = namebuf;
+       } else {
+               if (uname(&utsbuf)) {
+                       logmsg(loglevel, "get UTS name: %s\n", strerror(errno));
+                       return -1;
+               }
+
+               host = gethostbyname(utsbuf.nodename);
+               if (host == NULL) {
+                       logmsg(loglevel, "failed to get local hostname\n");
+                       return -1;
+               }
+               h_name = host->h_name;
+       }
+
+       if (lgss_krb5_strcasecmp(krb5_princ_component(ctx, princ, 1),
+                                h_name)) {
+               logmsg(loglevel, "service principal: hostname %.*s "
+                      "doesn't match localhost %s\n",
+                      krb5_princ_component(ctx, princ, 1)->length,
+                      krb5_princ_component(ctx, princ, 1)->data,
+                      h_name);
+               return -1;
+       }
+
+       return 0;
 }
 
 static
 int lkrb5_cc_check_tgt_princ(krb5_context ctx,
-                             krb5_ccache ccache,
-                             krb5_principal princ,
-                             unsigned int flag)
+                            krb5_ccache ccache,
+                            krb5_principal princ,
+                            unsigned int flag,
+                            uint64_t self_nid)
 {
         const char     *princ_name;
 
@@ -335,14 +352,14 @@ int lkrb5_cc_check_tgt_princ(krb5_context ctx,
                                krb5_princ_name(ctx, princ)->data);
                         return -1;
                 }
-        } 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 {
+               if (svc_princ_verify_host(ctx, princ, self_nid, 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;
+               }
+       }
 
         logmsg(LL_TRACE, "principal is OK\n");
         return 0;
@@ -377,9 +394,10 @@ void get_root_tgt_ccname(char *ccname, int size, unsigned int flag)
 
 static
 int lkrb5_check_root_tgt_cc_base(krb5_context ctx,
-                                 krb5_ccache ccache,
-                                 char *ccname,
-                                 unsigned int flag)
+                                krb5_ccache ccache,
+                                char *ccname,
+                                unsigned int flag,
+                                uint64_t self_nid)
 {
         krb5_ccache             tgt_ccache;
         krb5_creds              cred;
@@ -404,8 +422,8 @@ int lkrb5_check_root_tgt_cc_base(krb5_context ctx,
                 goto out_cc;
         }
 
-        if (lkrb5_cc_check_tgt_princ(ctx, tgt_ccache, princ, flag))
-                goto out_princ;
+       if (lkrb5_cc_check_tgt_princ(ctx, tgt_ccache, princ, flag, self_nid))
+               goto out_princ;
 
         /*
          * find a valid entry
@@ -498,8 +516,9 @@ out_cc:
  */
 static
 int lkrb5_check_root_tgt_cc(krb5_context ctx,
-                            krb5_ccache ccache,
-                            unsigned int root_flags)
+                           krb5_ccache ccache,
+                           unsigned int root_flags,
+                           uint64_t self_nid)
 {
         struct stat             statbuf;
         unsigned int            flag;
@@ -525,7 +544,8 @@ int lkrb5_check_root_tgt_cc(krb5_context ctx,
                         continue;
                 }
 
-                rc = lkrb5_check_root_tgt_cc_base(ctx, ccache, ccname, flag);
+               rc = lkrb5_check_root_tgt_cc_base(ctx, ccache, ccname, flag,
+                                                 self_nid);
                 if (rc == 0)
                         return 0;
         }
@@ -627,8 +647,9 @@ out_cred:
  */
 static
 int lkrb5_refresh_root_tgt_cc(krb5_context ctx,
-                              krb5_ccache ccache,
-                              unsigned int root_flags)
+                             krb5_ccache ccache,
+                             unsigned int root_flags,
+                             uint64_t self_nid)
 {
         krb5_keytab             kt;
         krb5_keytab_entry       kte;
@@ -694,14 +715,14 @@ int lkrb5_refresh_root_tgt_cc(krb5_context ctx,
                                 logmsg(LL_TRACE, "no hostname, skip\n");
                                 continue;
                         }
-                } else {
-                        if (svc_princ_verify_host(ctx, kte.principal,
-                                                  LL_TRACE)) {
-                                logmsg(LL_TRACE, "doesn't belong to this "
-                                       "node, skip\n");
-                                continue;
-                        }
-                }
+               } else {
+                       if (svc_princ_verify_host(ctx, kte.principal, self_nid,
+                                                 LL_TRACE)) {
+                               logmsg(LL_TRACE, "doesn't belong to this "
+                                      "node, skip\n");
+                               continue;
+                       }
+               }
 
                 code = krb5_copy_principal(ctx, kte.principal, &princ);
                 if (code) {
@@ -769,10 +790,12 @@ int lkrb5_prepare_root_cred(struct lgss_cred *cred)
          */
         lgss_krb5_mutex_lock();
 
-        rc = lkrb5_check_root_tgt_cc(ctx, ccache, cred->lc_root_flags);
-        if (rc != 0)
-                rc = lkrb5_refresh_root_tgt_cc(ctx, ccache,
-                                               cred->lc_root_flags);
+       rc = lkrb5_check_root_tgt_cc(ctx, ccache, cred->lc_root_flags,
+                                    cred->lc_self_nid);
+       if (rc != 0)
+               rc = lkrb5_refresh_root_tgt_cc(ctx, ccache,
+                                              cred->lc_root_flags,
+                                              cred->lc_self_nid);
 
         if (rc == 0)
                 rc = lgss_krb5_set_ccache_name(kcred->kc_ccname);
index b5b96b0..01405e6 100644 (file)
@@ -167,13 +167,14 @@ enum {
 };
 
 struct lgss_cred {
-        int                     lc_uid;
-        unsigned int            lc_root_flags;
-        uint64_t                lc_tgt_nid;
-        uint32_t                lc_tgt_svc;
-
-        struct lgss_mech_type  *lc_mech;
-        void                   *lc_mech_cred;
+       int                     lc_uid;
+       unsigned int            lc_root_flags;
+       uint64_t                lc_self_nid;
+       uint64_t                lc_tgt_nid;
+       uint32_t                lc_tgt_svc;
+
+       struct lgss_mech_type  *lc_mech;
+       void                   *lc_mech_cred;
 };
 
 struct lgss_mech_type *lgss_name2mech(const char *mech_name);
index 7876c04..4983b23 100644 (file)
@@ -401,9 +401,8 @@ get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred,
                                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;
+                               cred->cr_uid = 0;
+                               cred->cr_usr_oss = 1;
                        } else {
                                pw = getpwnam(sname);
                                if (pw != NULL) {
@@ -438,8 +437,9 @@ get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred,
                } 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"
+               }
+               if (cred->cr_uid == -1) {
+                       printerr(0, "ERROR: svc %d doesn't accept user %s "
                                 "from %016llx\n", lustre_svc, sname, nid);
                        break;
                }