From 0d88b3296cf28c8222359f9a19e42e423e2e3b28 Mon Sep 17 00:00:00 2001 From: Sebastien Buisson Date: Wed, 11 Mar 2015 11:13:31 +0100 Subject: [PATCH] LU-6356 gss: call out info must include 'self nid' 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 Change-Id: Ia44503a188feb162b32dea56333de6bafdfcfcd2 Reviewed-on: http://review.whamcloud.com/14042 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Jeremy Filizetti Reviewed-by: Dmitry Eremin Reviewed-by: Oleg Drokin --- lustre/ptlrpc/gss/gss_keyring.c | 11 +-- lustre/ptlrpc/gss/gss_svc_upcall.c | 14 ++-- lustre/utils/gss/lgss_keyring.c | 100 ++++++++++++------------ lustre/utils/gss/lgss_krb5_utils.c | 153 +++++++++++++++++++++---------------- lustre/utils/gss/lgss_utils.h | 15 ++-- lustre/utils/gss/svcgssd_proc.c | 10 +-- 6 files changed, 167 insertions(+), 136 deletions(-) diff --git a/lustre/ptlrpc/gss/gss_keyring.c b/lustre/ptlrpc/gss/gss_keyring.c index 2803721..c0438e9 100644 --- a/lustre/ptlrpc/gss/gss_keyring.c +++ b/lustre/ptlrpc/gss/gss_keyring.c @@ -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); diff --git a/lustre/ptlrpc/gss/gss_svc_upcall.c b/lustre/ptlrpc/gss/gss_svc_upcall.c index e3a7ab1..429b1eb 100644 --- a/lustre/ptlrpc/gss/gss_svc_upcall.c +++ b/lustre/ptlrpc/gss/gss_svc_upcall.c @@ -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); diff --git a/lustre/utils/gss/lgss_keyring.c b/lustre/utils/gss/lgss_keyring.c index 2a3fdf2..17c770e 100644 --- a/lustre/utils/gss/lgss_keyring.c +++ b/lustre/utils/gss/lgss_keyring.c @@ -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 " diff --git a/lustre/utils/gss/lgss_krb5_utils.c b/lustre/utils/gss/lgss_krb5_utils.c index 2b2d9d8..ec6614f 100644 --- a/lustre/utils/gss/lgss_krb5_utils.c +++ b/lustre/utils/gss/lgss_krb5_utils.c @@ -126,6 +126,7 @@ #endif #include +#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); diff --git a/lustre/utils/gss/lgss_utils.h b/lustre/utils/gss/lgss_utils.h index b5b96b0..01405e6 100644 --- a/lustre/utils/gss/lgss_utils.h +++ b/lustre/utils/gss/lgss_utils.h @@ -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); diff --git a/lustre/utils/gss/svcgssd_proc.c b/lustre/utils/gss/svcgssd_proc.c index 7876c04..4983b23 100644 --- a/lustre/utils/gss/svcgssd_proc.c +++ b/lustre/utils/gss/svcgssd_proc.c @@ -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; } -- 1.8.3.1