From: Timothy Day Date: Mon, 15 May 2023 20:34:01 +0000 (+0000) Subject: LU-16751 gss: remove old patches for nfs-utils 1.0.* X-Git-Tag: 2.15.56~21 X-Git-Url: https://git.whamcloud.com/gitweb?a=commitdiff_plain;h=75285f28532b8a39e091962cf7f86fc61fe13ba3;p=fs%2Flustre-release.git LU-16751 gss: remove old patches for nfs-utils 1.0.* Remove patches for an old version of nfs-utils. Remove the README that suggests using them. lustre/utils/gss has an entire fork of nfs-utils utils/gssd directory already. Also, sk_utils.c shouldn't be executable. Test-Parameters: trivial Signed-off-by: Timothy Day Change-Id: Ia47193073d2403125043d51db889d0ded41ea9b7 Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/51003 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Oleg Drokin Reviewed-by: Andreas Dilger Reviewed-by: Sebastien Buisson Reviewed-by: Aurelien Degremont --- diff --git a/lustre/utils/gss/README b/lustre/utils/gss/README deleted file mode 100644 index 576c45c..0000000 --- a/lustre/utils/gss/README +++ /dev/null @@ -1,12 +0,0 @@ -lustre/utils/gss: client & server side gss daemons for Lustre. - -All files came from standard nfs-utils package, applied with patches -created by Sun Microsystems, Inc. - -1. Stock nfs-utils-1.0.11.tgz -2. Apply nfs-utils-1.0.11-CITI_NFS4_ALL-1.dif from Center for Information - Technology Integration, University of Michigan - (http://www.citi.umich.edu/projects/nfsv4/linux/) -3. Apply lustre patch: nfs-utils-1.0.11-lustre.diff -4. Copy nfs-utils-1.0.10/aclocal/kerberos5.m4 to lustre/autoconf -5. Copy nfs-utils-1.0.10/utils/gssd/*.[ch] to here diff --git a/lustre/utils/gss/nfs-utils-1.0.10-lustre.diff b/lustre/utils/gss/nfs-utils-1.0.10-lustre.diff deleted file mode 100644 index 366d2d2..0000000 --- a/lustre/utils/gss/nfs-utils-1.0.10-lustre.diff +++ /dev/null @@ -1,4771 +0,0 @@ -diff -rNup nfs-utils-1.0.10/configure.in nfs-utils-1.0.10.lustre/configure.in ---- nfs-utils-1.0.10/configure.in 2007-05-15 13:02:26.000000000 -0600 -+++ nfs-utils-1.0.10.lustre/configure.in 2007-05-15 13:00:53.000000000 -0600 -@@ -17,61 +17,14 @@ AC_ARG_WITH(release, - RELEASE=$withval, - RELEASE=1) - AC_SUBST(RELEASE) --AC_ARG_WITH(statedir, -- [ --with-statedir=/foo use state dir /foo [/var/lib/nfs]], -- statedir=$withval, -- statedir=/var/lib/nfs) -- AC_SUBST(statedir) --AC_ARG_WITH(statduser, -- [AC_HELP_STRING([--with-statduser=rpcuser], -- [statd to run under @<:@rpcuser or nobody@:>@] -- )], -- statduser=$withval, -- if test "x$cross_compiling" = "xno"; then -- if grep -s '^rpcuser:' /etc/passwd > /dev/null; then -- statduser=rpcuser -- else -- statduser=nobody -- fi -- else -- statduser=nobody -- fi) -- AC_SUBST(statduser) --AC_ARG_ENABLE(nfsv3, -- [AC_HELP_STRING([--enable-nfsv3], -- [enable support for NFSv3 @<:@default=yes@:>@])], -- enable_nfsv3=$enableval, -- enable_nfsv3=yes) -- if test "$enable_nfsv3" = yes; then -- AC_DEFINE(NFS3_SUPPORTED, 1, [Define this if you want NFSv3 support compiled in]) -- else -- enable_nfsv3= -- fi -- AC_SUBST(enable_nfsv3) --AC_ARG_ENABLE(nfsv4, -- [AC_HELP_STRING([--enable-nfsv4], -- [enable support for NFSv4 @<:@default=yes@:>@])], -- enable_nfsv4=$enableval, -- enable_nfsv4=yes) -- if test "$enable_nfsv4" = yes; then -- AC_DEFINE(NFS4_SUPPORTED, 1, [Define this if you want NFSv4 support compiled in]) -- IDMAPD=idmapd -- else -- enable_nfsv4= -- IDMAPD= -- fi -- AC_SUBST(IDMAPD) -- AC_SUBST(enable_nfsv4) -- AM_CONDITIONAL(CONFIG_NFSV4, [test "$enable_nfsv4" = "yes"]) - AC_ARG_ENABLE(gss, - [AC_HELP_STRING([--enable-gss], - [enable support for rpcsec_gss @<:@default=yes@:>@])], - enable_gss=$enableval, - enable_gss=yes) - if test "$enable_gss" = yes; then -- AC_DEFINE(GSS_SUPPORTED, 1, [Define this if you want rpcsec_gss support compiled in]) -- GSSD=gssd -- SVCGSSD=svcgssd -+ GSSD=lgssd -+ SVCGSSD=lsvcgssd - else - enable_gss= - GSSD= -@@ -81,38 +34,6 @@ AC_ARG_ENABLE(gss, - AC_SUBST(SVCGSSD) - AC_SUBST(enable_gss) - AM_CONDITIONAL(CONFIG_GSS, [test "$enable_gss" = "yes"]) --AC_ARG_ENABLE(kprefix, -- [AC_HELP_STRING([--enable-kprefix], [install progs as rpc.knfsd etc])], -- test "$enableval" = "yes" && kprefix=k, -- kprefix=) -- AC_SUBST(kprefix) --AC_ARG_ENABLE(secure-statd, -- [AC_HELP_STRING([--enable-secure-statd], -- [Only lockd can use statd (security)])], -- test "$enableval" = "yes" && secure_statd=yes, -- secure_statd=no) -- if test "$secure_statd" = yes; then -- AC_DEFINE(RESTRICTED_STATD, 1, [Define this if you want to enable various security checks in statd. These checks basically keep anyone but lockd from using this service.]) -- fi -- AC_SUBST(secure_statd) --AC_ARG_ENABLE(rquotad, -- [AC_HELP_STRING([--enable-rquotad], -- [enable rquotad @<:@default=yes@:>@])], -- enable_rquotad=$enableval, -- enable_rquotad=yes) -- if test "$enable_rquotad" = yes; then -- RQUOTAD=rquotad -- else -- RQUOTAD= -- fi -- AM_CONDITIONAL(CONFIG_RQUOTAD, [test "$enable_rquotad" = "yes"]) -- --AC_ARG_ENABLE(mount, -- [AC_HELP_STRING([--enable-mount], -- [Create mount.nfs and don't use the util-linux mount(8) functionality. @<:@default=no@:>@])], -- enable_mount=$enableval, -- enable_mount=no) -- AM_CONDITIONAL(CONFIG_MOUNT, [test "$enable_mount" = "yes"]) - - # Check whether user wants TCP wrappers support - AC_TCP_WRAPPERS -@@ -155,47 +76,17 @@ AC_CHECK_FUNC(connect, , - AC_MSG_ERROR(Function 'socket' not found.), $LIBNSL)) - - AC_CHECK_LIB(crypt, crypt, [LIBCRYPT="-lcrypt"]) --if test "$enable_nfsv4" = yes; then -- AC_CHECK_LIB(event, event_dispatch, [libevent=1], AC_MSG_ERROR([libevent needed for nfsv4 support])) -- AC_CHECK_LIB(nfsidmap, nfs4_init_name_mapping, [libnfsidmap=1], AC_MSG_ERROR([libnfsidmap needed for nfsv4 support])) -- AC_CHECK_HEADERS(event.h, ,AC_MSG_ERROR([libevent needed for nfsv4 support])) -- AC_CHECK_HEADERS(nfsidmap.h, ,AC_MSG_ERROR([libnfsidmap needed for nfsv4 support])) -- dnl librpcsecgss already has a dependency on libgssapi, -- dnl but we need to make sure we get the right version - if test "$enable_gss" = yes; then -- PKG_CHECK_MODULES(RPCSECGSS, librpcsecgss >= 0.10, , -- [AC_MSG_ERROR([Unable to locate information required to use librpcsecgss. If you have pkgconfig installed, you might try setting environment variable PKG_CONFIG_PATH to /usr/local/lib/pkgconfig]) -- ] -- ) - PKG_CHECK_MODULES(GSSAPI, libgssapi >= 0.9) - fi - --fi --if test "$knfsd_cv_glibc2" = no; then -- AC_CHECK_LIB(bsd, daemon, [LIBBSD="-lbsd"]) --fi - AC_SUBST(LIBSOCKET) - AC_SUBST(LIBCRYPT) - AC_SUBST(LIBBSD) - - if test "$enable_gss" = yes; then -- dnl 'gss' also depends on nfsidmap.h - at least for svcgssd_proc.c -- AC_CHECK_HEADERS(nfsidmap.h, ,AC_MSG_ERROR([libnfsidmap needed for gss support])) -- AC_CHECK_HEADERS(spkm3.h, ,AC_MSG_WARN([could not locate SPKM3 header; will not have SPKM3 support])) -- dnl the nfs4_set_debug function doesn't appear in all version of the library -- AC_CHECK_LIB(nfsidmap, nfs4_set_debug, -- AC_DEFINE(HAVE_NFS4_SET_DEBUG,1, -- [Whether nfs4_set_debug() is present in libnfsidmap]),) -- - dnl Check for Kerberos V5 - AC_KERBEROS_V5 -- -- dnl This is not done until here because we need to have KRBLIBS set -- dnl ("librpcsecgss=1" is so that it doesn't get added to LIBS) -- AC_CHECK_LIB(rpcsecgss, authgss_create_default, [librpcsecgss=1], AC_MSG_ERROR([librpcsecgss needed for nfsv4 support]), -lgssapi -ldl) -- AC_CHECK_LIB(rpcsecgss, authgss_set_debug_level, -- AC_DEFINE(HAVE_AUTHGSS_SET_DEBUG_LEVEL, 1, [Define this if the rpcsec_gss library has the function authgss_set_debug_level]),, -lgssapi -ldl) -- - fi - - dnl ************************************************************* -@@ -307,35 +198,7 @@ AC_SUBST([ACLOCAL_AMFLAGS], ["-I $ac_mac - - AC_CONFIG_FILES([ - Makefile -- linux-nfs/Makefile -- support/Makefile -- support/export/Makefile -- support/include/nfs/Makefile -- support/include/rpcsvc/Makefile -- support/include/sys/fs/Makefile -- support/include/sys/Makefile -- support/include/Makefile -- support/misc/Makefile -- support/nfs/Makefile -- tools/Makefile -- tools/getiversion/Makefile -- tools/getkversion/Makefile -- tools/locktest/Makefile -- tools/nlmtest/Makefile -- tools/rpcdebug/Makefile -- tools/rpcgen/Makefile - utils/Makefile -- utils/exportfs/Makefile -- utils/gssd/Makefile -- utils/idmapd/Makefile -- utils/lockd/Makefile -- utils/mount/Makefile -- utils/mountd/Makefile -- utils/nfsd/Makefile -- utils/nfsstat/Makefile -- utils/nhfsstone/Makefile -- utils/rquotad/Makefile -- utils/showmount/Makefile -- utils/statd/Makefile]) -+ utils/gssd/Makefile]) - AC_OUTPUT - -diff -rNup nfs-utils-1.0.10/Makefile.am nfs-utils-1.0.10.lustre/Makefile.am ---- nfs-utils-1.0.10/Makefile.am 2007-05-15 13:02:26.000000000 -0600 -+++ nfs-utils-1.0.10.lustre/Makefile.am 2007-05-15 13:00:53.000000000 -0600 -@@ -1,6 +1,6 @@ - ## Process this file with automake to produce Makefile.in - --SUBDIRS = tools support utils linux-nfs -+SUBDIRS = utils - - MAINTAINERCLEANFILES = Makefile.in - -diff -rNup nfs-utils-1.0.10/utils/gssd/cacheio.c nfs-utils-1.0.10.lustre/utils/gssd/cacheio.c ---- nfs-utils-1.0.10/utils/gssd/cacheio.c 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10.lustre/utils/gssd/cacheio.c 2007-05-15 13:01:35.000000000 -0600 -@@ -227,7 +227,8 @@ int qword_get(char **bpp, char *dest, in - return -1; - while (*bp == ' ') bp++; - *bpp = bp; -- *dest = '\0'; -+// why should we clear *dest??? -+// *dest = '\0'; - return len; - } - -diff -rNup nfs-utils-1.0.10/utils/gssd/context.c nfs-utils-1.0.10.lustre/utils/gssd/context.c ---- nfs-utils-1.0.10/utils/gssd/context.c 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10.lustre/utils/gssd/context.c 2007-05-15 13:01:35.000000000 -0600 -@@ -33,8 +33,6 @@ - #include - #include - #include --#include --#include - #include "gss_util.h" - #include "gss_oids.h" - #include "err_util.h" -diff -rNup nfs-utils-1.0.10/utils/gssd/context.h nfs-utils-1.0.10.lustre/utils/gssd/context.h ---- nfs-utils-1.0.10/utils/gssd/context.h 2007-05-15 13:02:26.000000000 -0600 -+++ nfs-utils-1.0.10.lustre/utils/gssd/context.h 2007-05-15 13:01:35.000000000 -0600 -@@ -31,8 +31,6 @@ - #ifndef _CONTEXT_H_ - #define _CONTEXT_H_ - --#include -- - /* Hopefully big enough to hold any serialized context */ - #define MAX_CTX_LEN 4096 - -diff -rNup nfs-utils-1.0.10/utils/gssd/context_lucid.c nfs-utils-1.0.10.lustre/utils/gssd/context_lucid.c ---- nfs-utils-1.0.10/utils/gssd/context_lucid.c 2007-05-15 13:02:26.000000000 -0600 -+++ nfs-utils-1.0.10.lustre/utils/gssd/context_lucid.c 2007-05-15 13:01:35.000000000 -0600 -@@ -41,11 +41,7 @@ - #include - #include - #include --#include "gss_util.h" --#include "gss_oids.h" --#include "err_util.h" --#include "context.h" -- -+#include - #include - #include - #ifndef OM_uint64 -@@ -53,6 +49,11 @@ typedef uint64_t OM_uint64; - #endif - #include - -+#include "gss_util.h" -+#include "gss_oids.h" -+#include "err_util.h" -+#include "context.h" -+ - static int - write_lucid_keyblock(char **p, char *end, gss_krb5_lucid_key_t *key) - { -@@ -354,6 +355,7 @@ static int - prepare_krb5_rfc4121_buffer(gss_krb5_lucid_context_v1_t *lctx, - gss_buffer_desc *buf) - { -+ static int constant_two = 2; - char *p, *end; - uint32_t v2_flags = 0; - gss_krb5_lucid_key_t enc_key; -@@ -372,7 +374,7 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc - end = buf->value + MAX_CTX_LEN; - - /* Version 2 */ -- if (WRITE_BYTES(&p, end, lctx->initiate)) goto out_err; -+ if (WRITE_BYTES(&p, end, constant_two)) goto out_err; - if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err; - - if (lctx->initiate) -@@ -434,14 +436,25 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc - goto out_err; - - /* Kc */ -- if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key, -- &derived_key, -- KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM)) -- goto out_err; -- if (write_bytes(&p, end, derived_key.data, -- derived_key.length)) -- goto out_err; -- free(derived_key.data); -+ /* -+ * RC4 is special, it dosen't need key derivation. Actually -+ * the Ke is based on plain text. Here we just let all three -+ * key identical, kernel will handle everything. --ericm -+ */ -+ if (lctx->rfc1964_kd.ctx_key.type == ENCTYPE_ARCFOUR_HMAC) { -+ if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data, -+ lctx->rfc1964_kd.ctx_key.length)) -+ goto out_err; -+ } else { -+ if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key, -+ &derived_key, -+ KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM)) -+ goto out_err; -+ if (write_bytes(&p, end, derived_key.data, -+ derived_key.length)) -+ goto out_err; -+ free(derived_key.data); -+ } - } else { - gss_krb5_lucid_key_t *keyptr; - uint32_t sign_usage, seal_usage; -@@ -451,6 +464,7 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc - else - keyptr = &lctx->cfx_kd.ctx_key; - -+#if 0 - if (lctx->initiate == 1) { - sign_usage = KG_USAGE_INITIATOR_SIGN; - seal_usage = KG_USAGE_INITIATOR_SEAL; -@@ -458,6 +472,19 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc - sign_usage = KG_USAGE_ACCEPTOR_SIGN; - seal_usage = KG_USAGE_ACCEPTOR_SEAL; - } -+#else -+ /* FIXME -+ * These are from rfc4142, but I don't understand: if we supply -+ * different 'usage' value for client & server, then the peers -+ * will have different derived keys. How could this work? -+ * -+ * Here we simply use old SIGN/SEAL values until we find the -+ * answer. --ericm -+ * FIXME -+ */ -+ sign_usage = KG_USAGE_SIGN; -+ seal_usage = KG_USAGE_SEAL; -+#endif - - /* derive and send down: Ke, Ki, and Kc */ - -diff -rNup nfs-utils-1.0.10/utils/gssd/context_mit.c nfs-utils-1.0.10.lustre/utils/gssd/context_mit.c ---- nfs-utils-1.0.10/utils/gssd/context_mit.c 2007-05-15 13:02:26.000000000 -0600 -+++ nfs-utils-1.0.10.lustre/utils/gssd/context_mit.c 2007-05-15 13:01:35.000000000 -0600 -@@ -39,7 +39,6 @@ - #include - #include - #include --#include - #include "gss_util.h" - #include "gss_oids.h" - #include "err_util.h" -@@ -333,12 +332,7 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss - * keydata-2; ( Ki (Kseq for DES3) ) - * keydata-3; ( Kc (derived checksum key) ) - */ -- if (kctx->initiate) { -- if (WRITE_BYTES(&p, end, constant_one)) goto out_err; -- } -- else { -- if (WRITE_BYTES(&p, end, constant_zero)) goto out_err; -- } -+ if (WRITE_BYTES(&p, end, constant_two)) goto out_err; - if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err; - - /* Only applicable flag for this is initiator */ -diff -rNup nfs-utils-1.0.10/utils/gssd/context_spkm3.c nfs-utils-1.0.10.lustre/utils/gssd/context_spkm3.c ---- nfs-utils-1.0.10/utils/gssd/context_spkm3.c 2007-05-15 13:02:26.000000000 -0600 -+++ nfs-utils-1.0.10.lustre/utils/gssd/context_spkm3.c 2007-05-15 13:01:35.000000000 -0600 -@@ -33,8 +33,6 @@ - #include - #include - #include --#include --#include - #include "gss_util.h" - #include "gss_oids.h" - #include "err_util.h" -diff -rNup nfs-utils-1.0.10/utils/gssd/err_util.c nfs-utils-1.0.10.lustre/utils/gssd/err_util.c ---- nfs-utils-1.0.10/utils/gssd/err_util.c 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10.lustre/utils/gssd/err_util.c 2007-05-15 13:01:35.000000000 -0600 -@@ -32,6 +32,8 @@ - #include - #include - #include -+#include -+#include - #include "err_util.h" - - static int verbosity = 0; -@@ -91,3 +93,40 @@ printit: - /* reset the buffer */ - memset(message_buf, 0, sizeof(message_buf)); - } -+ -+void print_hexl(int pri, unsigned char *cp, int length) -+{ -+ int i, j, jm; -+ unsigned char c; -+ -+ printerr(pri, "length %d\n",length); -+ printerr(pri, "\n"); -+ -+ for (i = 0; i < length; i += 0x10) { -+ printerr(pri, " %04x: ", (u_int)i); -+ jm = length - i; -+ jm = jm > 16 ? 16 : jm; -+ -+ for (j = 0; j < jm; j++) { -+ if ((j % 2) == 1) -+ printerr(pri,"%02x ", (u_int)cp[i+j]); -+ else -+ printerr(pri,"%02x", (u_int)cp[i+j]); -+ } -+ for (; j < 16; j++) { -+ if ((j % 2) == 1) -+ printerr(pri," "); -+ else -+ printerr(pri," "); -+ } -+ printerr(pri," "); -+ -+ for (j = 0; j < jm; j++) { -+ c = cp[i+j]; -+ c = isprint(c) ? c : '.'; -+ printerr(pri,"%c", c); -+ } -+ printerr(pri,"\n"); -+ } -+} -+ -diff -rNup nfs-utils-1.0.10/utils/gssd/err_util.h nfs-utils-1.0.10.lustre/utils/gssd/err_util.h ---- nfs-utils-1.0.10/utils/gssd/err_util.h 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10.lustre/utils/gssd/err_util.h 2007-05-15 13:01:35.000000000 -0600 -@@ -33,5 +33,6 @@ - - void initerr(char *progname, int verbosity, int fg); - void printerr(int priority, char *format, ...); -+void print_hexl(int pri, unsigned char *cp, int length); - - #endif /* _ERR_UTIL_H_ */ -diff -rNup nfs-utils-1.0.10/utils/gssd/gss_clnt_send_err.c nfs-utils-1.0.10.lustre/utils/gssd/gss_clnt_send_err.c ---- nfs-utils-1.0.10/utils/gssd/gss_clnt_send_err.c 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10.lustre/utils/gssd/gss_clnt_send_err.c 2007-05-15 13:00:53.000000000 -0600 -@@ -47,6 +47,7 @@ - #include "gssd.h" - #include "write_bytes.h" - -+#if 0 - char pipefsdir[PATH_MAX] = GSSD_PIPEFS_DIR; - - static void -@@ -102,3 +103,4 @@ main(int argc, char *argv[]) - } - exit(0); - } -+#endif -diff -rNup nfs-utils-1.0.10/utils/gssd/gssd.c nfs-utils-1.0.10.lustre/utils/gssd/gssd.c ---- nfs-utils-1.0.10/utils/gssd/gssd.c 2007-05-15 13:02:26.000000000 -0600 -+++ nfs-utils-1.0.10.lustre/utils/gssd/gssd.c 2007-05-15 13:01:35.000000000 -0600 -@@ -38,9 +38,12 @@ - - #include "config.h" - -+#include - #include - #include --#include -+#include -+#include -+#include - - #include - #include -@@ -48,23 +51,107 @@ - #include - #include - #include -+#include - #include "gssd.h" - #include "err_util.h" - #include "gss_util.h" - #include "krb5_util.h" -+#include "lsupport.h" - - char pipefs_dir[PATH_MAX] = GSSD_PIPEFS_DIR; - char pipefs_nfsdir[PATH_MAX] = GSSD_PIPEFS_DIR; - char keytabfile[PATH_MAX] = GSSD_DEFAULT_KEYTAB_FILE; - char ccachedir[PATH_MAX] = GSSD_DEFAULT_CRED_DIR; - int use_memcache = 0; -+int lgssd_mutex_downcall = -1; - --void --sig_die(int signal) -+static int lgssd_create_mutex(int *semid) -+{ -+ int id; -+ int arg; -+ -+ id = semget(IPC_PRIVATE, 1, IPC_CREAT); -+ if (id == -1) { -+ printerr(0, "semget: %s\n", strerror(errno)); -+ return -1; -+ } -+ -+ arg = 1; -+ if (semctl(id, 0, SETVAL, arg) != 0) { -+ printerr(0, "semctl: %s\n", strerror(errno)); -+ semctl(id, 1, IPC_RMID, arg); -+ return -1; -+ } -+ -+ *semid = id; -+ return 0; -+} -+ -+void lgssd_init_mutexs(void) -+{ -+ if (lgssd_create_mutex(&lgssd_mutex_downcall)) { -+ printerr(0, "can't create downcall mutex\n"); -+ exit(1); -+ } -+} -+ -+void lgssd_fini_mutexs(void) -+{ -+ int arg = 0; -+ -+ if (lgssd_mutex_downcall != -1) -+ semctl(lgssd_mutex_downcall, 1, IPC_RMID, arg); -+} -+ -+void lgssd_mutex_get(int semid) -+{ -+ struct sembuf op[1] = { {0, -1, SEM_UNDO} }; -+ int rc; -+ -+ rc = semop(semid, op, 1); -+ if (rc != 0) { -+ printerr(0, "exit on mutex_get err %d: %s\n", -+ rc, strerror(errno)); -+ exit(1); -+ } -+} -+ -+void lgssd_mutex_put(int semid) - { -+ struct sembuf op[1] = { {0, 1, 0} }; -+ int rc; -+ -+ rc = semop(semid, op, 1); -+ if (rc != 0) { -+ printerr(0, "ignore mutex_put err %d: %s\n", -+ rc, strerror(errno)); -+ } -+} -+ -+static void lgssd_cleanup(void) -+{ -+ pid_t child_pid; -+ -+ /* make sure all children finished */ -+ while (1) { -+ child_pid = waitpid(-1, NULL, 0); -+ if (child_pid < 0) -+ break; -+ -+ printerr(3, "cleanup: child %d terminated\n", child_pid); -+ } -+ -+ lgssd_fini_mutexs(); -+ - /* destroy krb5 machine creds */ - gssd_destroy_krb5_machine_creds(); -+} -+ -+void -+sig_die(int signal) -+{ - printerr(1, "exiting on signal %d\n", signal); -+ lgssd_cleanup(); - exit(1); - } - -@@ -79,7 +166,7 @@ sig_hup(int signal) - static void - usage(char *progname) - { -- fprintf(stderr, "usage: %s [-f] [-v] [-r] [-p pipefsdir] [-k keytab] [-d ccachedir]\n", -+ fprintf(stderr, "usage: %s [-f] [-v] [-p pipefsdir] [-k keytab] [-d ccachedir]\n", - progname); - exit(1); - } -@@ -89,7 +176,6 @@ main(int argc, char *argv[]) - { - int fg = 0; - int verbosity = 0; -- int rpc_verbosity = 0; - int opt; - extern char *optarg; - char *progname; -@@ -99,18 +185,12 @@ main(int argc, char *argv[]) - case 'f': - fg = 1; - break; -- case 'm': -- /* Accept but ignore this. Now the default. */ -- break; - case 'M': - use_memcache = 1; - break; - case 'v': - verbosity++; - break; -- case 'r': -- rpc_verbosity++; -- break; - case 'p': - strncpy(pipefs_dir, optarg, sizeof(pipefs_dir)); - if (pipefs_dir[sizeof(pipefs_dir)-1] != '\0') -@@ -131,10 +211,6 @@ main(int argc, char *argv[]) - break; - } - } -- snprintf(pipefs_nfsdir, sizeof(pipefs_nfsdir), "%s/%s", -- pipefs_dir, GSSD_SERVICE_NAME); -- if (pipefs_nfsdir[sizeof(pipefs_nfsdir)-1] != '\0') -- errx(1, "pipefs_nfsdir path name too long"); - - if ((progname = strrchr(argv[0], '/'))) - progname++; -@@ -142,30 +218,42 @@ main(int argc, char *argv[]) - progname = argv[0]; - - initerr(progname, verbosity, fg); --#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL -- authgss_set_debug_level(rpc_verbosity); --#else -- if (rpc_verbosity > 0) -- printerr(0, "Warning: rpcsec_gss library does not " -- "support setting debug level\n"); --#endif - - if (gssd_check_mechs() != 0) - errx(1, "Problem with gssapi library"); - -+ if (gssd_get_local_realm()) -+ errx(1, "get local realm"); -+ - if (!fg && daemon(0, 0) < 0) - errx(1, "fork"); - -+ /* This should be checked _after_ daemon(), because we need to own -+ * the undo-able semaphore by this process -+ */ -+ gssd_init_unique(GSSD_CLI); -+ -+ /* Process keytab file and get machine credentials. This will modify -+ * disk status so do it after we are sure we are the only instance -+ */ -+ if (gssd_refresh_krb5_machine_creds()) -+ return -1; -+ - signal(SIGINT, sig_die); - signal(SIGTERM, sig_die); - signal(SIGHUP, sig_hup); - -- /* Process keytab file and get machine credentials */ -- gssd_refresh_krb5_machine_creds(); -+#if 0 - /* Determine Kerberos information from the kernel */ - gssd_obtain_kernel_krb5_info(); -+#endif -+ -+ lgssd_init_mutexs(); -+ -+ printerr(0, "lgssd initialized and ready to serve\n"); -+ lgssd_run(); - -- gssd_run(); -- printerr(0, "gssd_run returned!\n"); -- abort(); -+ lgssd_cleanup(); -+ printerr(0, "lgssd exiting\n"); -+ return 0; - } -diff -rNup nfs-utils-1.0.10/utils/gssd/gssd.h nfs-utils-1.0.10.lustre/utils/gssd/gssd.h ---- nfs-utils-1.0.10/utils/gssd/gssd.h 2007-05-15 13:02:26.000000000 -0600 -+++ nfs-utils-1.0.10.lustre/utils/gssd/gssd.h 2007-05-15 13:01:35.000000000 -0600 -@@ -48,8 +48,13 @@ - #define GSSD_DEFAULT_CRED_PREFIX "krb5cc_" - #define GSSD_DEFAULT_MACHINE_CRED_SUFFIX "machine" - #define GSSD_DEFAULT_KEYTAB_FILE "/etc/krb5.keytab" --#define GSSD_SERVICE_NAME "nfs" --#define GSSD_SERVICE_NAME_LEN 3 -+#define GSSD_SERVICE_MDS "lustre_mds" -+#define GSSD_SERVICE_OSS "lustre_oss" -+#define GSSD_SERVICE_MDS_NAMELEN 10 -+#define GSSD_SERVICE_OSS_NAMELEN 10 -+ -+#define LUSTRE_ROOT_NAME "lustre_root" -+#define LUSTRE_ROOT_NAMELEN 11 - - /* - * The gss mechanisms that we can handle -@@ -59,9 +64,9 @@ enum {AUTHTYPE_KRB5, AUTHTYPE_SPKM3, AUT - - - extern char pipefs_dir[PATH_MAX]; --extern char pipefs_nfsdir[PATH_MAX]; - extern char keytabfile[PATH_MAX]; - extern char ccachedir[PATH_MAX]; -+extern char gethostname_ex[PATH_MAX]; - extern int use_memcache; - - TAILQ_HEAD(clnt_list_head, clnt_info) clnt_list; -@@ -71,10 +76,6 @@ struct clnt_info { - char *dirname; - int dir_fd; - char *servicename; -- char *servername; -- int prog; -- int vers; -- char *protocol; - int krb5_fd; - int krb5_poll_index; - int spkm3_fd; -@@ -85,8 +86,14 @@ void init_client_list(void); - int update_client_list(void); - void handle_krb5_upcall(struct clnt_info *clp); - void handle_spkm3_upcall(struct clnt_info *clp); --int gssd_acquire_cred(char *server_name); --void gssd_run(void); -+void lgssd_run(void); -+ -+ -+extern int lgssd_mutex_downcall; - -+void lgssd_init_mutexs(void); -+void lgssd_fini_mutexs(void); -+void lgssd_mutex_get(int semid); -+void lgssd_mutex_put(int semid); - - #endif /* _RPC_GSSD_H_ */ -diff -rNup nfs-utils-1.0.10/utils/gssd/gssd_main_loop.c nfs-utils-1.0.10.lustre/utils/gssd/gssd_main_loop.c ---- nfs-utils-1.0.10/utils/gssd/gssd_main_loop.c 2007-05-15 13:02:26.000000000 -0600 -+++ nfs-utils-1.0.10.lustre/utils/gssd/gssd_main_loop.c 2007-05-15 13:01:35.000000000 -0600 -@@ -94,11 +94,13 @@ scan_poll_results(int ret) - }; - - void --gssd_run() -+lgssd_run() - { - int ret; - struct sigaction dn_act; - int fd; -+ time_t child_check = 0; -+ pid_t child_pid; - - /* Taken from linux/Documentation/dnotify.txt: */ - dn_act.sa_sigaction = dir_notify_handler; -@@ -106,10 +108,10 @@ gssd_run() - dn_act.sa_flags = SA_SIGINFO; - sigaction(DNOTIFY_SIGNAL, &dn_act, NULL); - -- if ((fd = open(pipefs_nfsdir, O_RDONLY)) == -1) { -+ if ((fd = open(pipefs_dir, O_RDONLY)) == -1) { - printerr(0, "ERROR: failed to open %s: %s\n", -- pipefs_nfsdir, strerror(errno)); -- exit(1); -+ pipefs_dir, strerror(errno)); -+ return; - } - fcntl(fd, F_SETSIG, DNOTIFY_SIGNAL); - fcntl(fd, F_NOTIFY, DN_CREATE|DN_DELETE|DN_MODIFY|DN_MULTISHOT); -@@ -119,12 +121,30 @@ gssd_run() - while (1) { - while (dir_changed) { - dir_changed = 0; -+ printerr(2, "pipefs root dir changed\n"); - if (update_client_list()) { - printerr(0, "ERROR: couldn't update " - "client list\n"); -- exit(1); -+ goto out; - } - } -+ -+ /* every 5s cleanup possible zombies of child processes */ -+ if (time(NULL) - child_check >= 5) { -+ printerr(3, "check zombie children...\n"); -+ -+ while (1) { -+ child_pid = waitpid(-1, NULL, WNOHANG); -+ if (child_pid <= 0) -+ break; -+ -+ printerr(2, "terminate zombie child: %d\n", -+ child_pid); -+ } -+ -+ child_check = time(NULL); -+ } -+ - /* race condition here: dir_changed could be set before we - * enter the poll, and we'd never notice if it weren't for the - * timeout. */ -@@ -139,6 +159,7 @@ gssd_run() - scan_poll_results(ret); - } - } -+out: - close(fd); - return; - } -diff -rNup nfs-utils-1.0.10/utils/gssd/gssd_proc.c nfs-utils-1.0.10.lustre/utils/gssd/gssd_proc.c ---- nfs-utils-1.0.10/utils/gssd/gssd_proc.c 2007-05-15 13:02:26.000000000 -0600 -+++ nfs-utils-1.0.10.lustre/utils/gssd/gssd_proc.c 2007-05-15 13:21:06.000000000 -0600 -@@ -43,7 +43,6 @@ - #endif - #include "config.h" - #include --#include - #include - #include - #include -@@ -69,6 +68,7 @@ - #include "gss_oids.h" - #include "krb5_util.h" - #include "context.h" -+#include "lsupport.h" - - /* - * pollarray: -@@ -99,86 +99,10 @@ struct pollfd * pollarray; - - int pollsize; /* the size of pollaray (in pollfd's) */ - --/* XXX buffer problems: */ --static int --read_service_info(char *info_file_name, char **servicename, char **servername, -- int *prog, int *vers, char **protocol) { --#define INFOBUFLEN 256 -- char buf[INFOBUFLEN]; -- static char dummy[128]; -- int nbytes; -- static char service[128]; -- static char address[128]; -- char program[16]; -- char version[16]; -- char protoname[16]; -- in_addr_t inaddr; -- int fd = -1; -- struct hostent *ent = NULL; -- int numfields; -- -- *servicename = *servername = *protocol = NULL; -- -- if ((fd = open(info_file_name, O_RDONLY)) == -1) { -- printerr(0, "ERROR: can't open %s: %s\n", info_file_name, -- strerror(errno)); -- goto fail; -- } -- if ((nbytes = read(fd, buf, INFOBUFLEN)) == -1) -- goto fail; -- close(fd); -- -- numfields = sscanf(buf,"RPC server: %127s\n" -- "service: %127s %15s version %15s\n" -- "address: %127s\n" -- "protocol: %15s\n", -- dummy, -- service, program, version, -- address, -- protoname); -- -- if (numfields == 5) { -- strcpy(protoname, "tcp"); -- } else if (numfields != 6) { -- goto fail; -- } -- -- /* check service, program, and version */ -- if(memcmp(service, "nfs", 3)) return -1; -- *prog = atoi(program + 1); /* skip open paren */ -- *vers = atoi(version); -- if((*prog != 100003) || ((*vers != 2) && (*vers != 3) && (*vers != 4))) -- goto fail; -- -- /* create service name */ -- inaddr = inet_addr(address); -- if (!(ent = gethostbyaddr(&inaddr, sizeof(inaddr), AF_INET))) { -- printerr(0, "ERROR: can't resolve server %s name\n", address); -- goto fail; -- } -- if (!(*servername = calloc(strlen(ent->h_name) + 1, 1))) -- goto fail; -- memcpy(*servername, ent->h_name, strlen(ent->h_name)); -- snprintf(buf, INFOBUFLEN, "%s@%s", service, ent->h_name); -- if (!(*servicename = calloc(strlen(buf) + 1, 1))) -- goto fail; -- memcpy(*servicename, buf, strlen(buf)); -- -- if (!(*protocol = strdup(protoname))) -- goto fail; -- return 0; --fail: -- printerr(0, "ERROR: failed to read service info\n"); -- if (fd != -1) close(fd); -- if (*servername) free(*servername); -- if (*servicename) free(*servicename); -- if (*protocol) free(*protocol); -- return -1; --} -- - static void - destroy_client(struct clnt_info *clp) - { -+ printerr(3, "clp %p: dirname %s, krb5fd %d\n", clp, clp->dirname, clp->krb5_fd); - if (clp->krb5_poll_index != -1) - memset(&pollarray[clp->krb5_poll_index], 0, - sizeof(struct pollfd)); -@@ -190,8 +114,6 @@ destroy_client(struct clnt_info *clp) - if (clp->spkm3_fd != -1) close(clp->spkm3_fd); - if (clp->dirname) free(clp->dirname); - if (clp->servicename) free(clp->servicename); -- if (clp->servername) free(clp->servername); -- if (clp->protocol) free(clp->protocol); - free(clp); - } - -@@ -221,7 +143,6 @@ process_clnt_dir_files(struct clnt_info - { - char kname[32]; - char sname[32]; -- char info_file_name[32]; - - if (clp->krb5_fd == -1) { - snprintf(kname, sizeof(kname), "%s/krb5", clp->dirname); -@@ -233,13 +154,6 @@ process_clnt_dir_files(struct clnt_info - } - if((clp->krb5_fd == -1) && (clp->spkm3_fd == -1)) - return -1; -- snprintf(info_file_name, sizeof(info_file_name), "%s/info", -- clp->dirname); -- if ((clp->servicename == NULL) && -- read_service_info(info_file_name, &clp->servicename, -- &clp->servername, &clp->prog, &clp->vers, -- &clp->protocol)) -- return -1; - return 0; - } - -@@ -273,6 +187,8 @@ insert_clnt_poll(struct clnt_info *clp) - } - pollarray[clp->krb5_poll_index].fd = clp->krb5_fd; - pollarray[clp->krb5_poll_index].events |= POLLIN; -+ printerr(2, "monitoring krb5 channel under %s\n", -+ clp->dirname); - } - - if ((clp->spkm3_fd != -1) && (clp->spkm3_poll_index == -1)) { -@@ -386,67 +302,106 @@ find_client(char *dirname) - int - update_client_list(void) - { -- struct dirent **namelist; -+ char lustre_dir[PATH_MAX]; -+ struct dirent lustre_dirent = { .d_name = "lustre" }; -+ struct dirent *namelist[1]; -+ struct stat statbuf; - int i, j; - -- if (chdir(pipefs_nfsdir) < 0) { -+ if (chdir(pipefs_dir) < 0) { - printerr(0, "ERROR: can't chdir to %s: %s\n", -- pipefs_nfsdir, strerror(errno)); -+ pipefs_dir, strerror(errno)); - return -1; - } - -- j = scandir(pipefs_nfsdir, &namelist, NULL, alphasort); -- if (j < 0) { -- printerr(0, "ERROR: can't scandir %s: %s\n", -- pipefs_nfsdir, strerror(errno)); -- return -1; -+ snprintf(lustre_dir, sizeof(lustre_dir), "%s/%s", pipefs_dir, "lustre"); -+ if (stat(lustre_dir, &statbuf) == 0) { -+ namelist[0] = &lustre_dirent; -+ j = 1; -+ printerr(2, "re-processing lustre directory\n"); -+ } else { -+ namelist[0] = NULL; -+ j = 0; -+ printerr(2, "lustre directory not exist\n"); - } -+ - update_old_clients(namelist, j); - for (i=0; i < j; i++) { -- if (i < FD_ALLOC_BLOCK -- && !strncmp(namelist[i]->d_name, "clnt", 4) -- && !find_client(namelist[i]->d_name)) -+ if (i < FD_ALLOC_BLOCK && !find_client(namelist[i]->d_name)) - process_clnt_dir(namelist[i]->d_name); -- free(namelist[i]); - } - -- free(namelist); -+ chdir("/"); - return 0; - } - -+/* Context creation response. */ -+struct lustre_gss_init_res { -+ gss_buffer_desc gr_ctx; /* context handle */ -+ u_int gr_major; /* major status */ -+ u_int gr_minor; /* minor status */ -+ u_int gr_win; /* sequence window */ -+ gss_buffer_desc gr_token; /* token */ -+}; -+ -+struct lustre_gss_data { -+ int lgd_established; -+ int lgd_lustre_svc; /* mds/oss */ -+ int lgd_uid; /* uid */ -+ char *lgd_uuid; /* client device uuid */ -+ gss_name_t lgd_name; /* service name */ -+ -+ gss_OID lgd_mech; /* mech OID */ -+ u_int lgd_req_flags; /* request flags */ -+ gss_cred_id_t lgd_cred; /* credential */ -+ gss_ctx_id_t lgd_ctx; /* session context */ -+ gss_buffer_desc lgd_rmt_ctx; /* remote handle of context */ -+ uint32_t lgd_seq_win; /* sequence window */ -+ -+ int lgd_rpc_err; -+ int lgd_gss_err; -+}; -+ - static int --do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd, -- gss_buffer_desc *context_token) -+do_downcall(int k5_fd, struct lgssd_upcall_data *updata, -+ struct lustre_gss_data *lgd, gss_buffer_desc *context_token) - { - char *buf = NULL, *p = NULL, *end = NULL; - unsigned int timeout = 0; /* XXX decide on a reasonable value */ - unsigned int buf_size = 0; - -- printerr(1, "doing downcall\n"); -- buf_size = sizeof(uid) + sizeof(timeout) + sizeof(pd->pd_seq_win) + -- sizeof(pd->pd_ctx_hndl.length) + pd->pd_ctx_hndl.length + -+ printerr(2, "doing downcall\n"); -+ buf_size = sizeof(updata->seq) + sizeof(timeout) + -+ sizeof(lgd->lgd_seq_win) + -+ sizeof(lgd->lgd_rmt_ctx.length) + lgd->lgd_rmt_ctx.length + - sizeof(context_token->length) + context_token->length; - p = buf = malloc(buf_size); - end = buf + buf_size; - -- if (WRITE_BYTES(&p, end, uid)) goto out_err; -+ if (WRITE_BYTES(&p, end, updata->seq)) goto out_err; - /* Not setting any timeout for now: */ - if (WRITE_BYTES(&p, end, timeout)) goto out_err; -- if (WRITE_BYTES(&p, end, pd->pd_seq_win)) goto out_err; -- if (write_buffer(&p, end, &pd->pd_ctx_hndl)) goto out_err; -+ if (WRITE_BYTES(&p, end, lgd->lgd_seq_win)) goto out_err; -+ if (write_buffer(&p, end, &lgd->lgd_rmt_ctx)) goto out_err; - if (write_buffer(&p, end, context_token)) goto out_err; - -- if (write(k5_fd, buf, p - buf) < p - buf) goto out_err; -+ lgssd_mutex_get(lgssd_mutex_downcall); -+ if (write(k5_fd, buf, p - buf) < p - buf) { -+ lgssd_mutex_put(lgssd_mutex_downcall); -+ goto out_err; -+ } -+ lgssd_mutex_put(lgssd_mutex_downcall); -+ - if (buf) free(buf); - return 0; - out_err: - if (buf) free(buf); -- printerr(0, "Failed to write downcall!\n"); -+ printerr(0, "ERROR: Failed to write downcall!\n"); - return -1; - } - - static int --do_error_downcall(int k5_fd, uid_t uid, int err) -+do_error_downcall(int k5_fd, uint32_t seq, int rpc_err, int gss_err) - { - char buf[1024]; - char *p = buf, *end = buf + 1024; -@@ -455,19 +410,26 @@ do_error_downcall(int k5_fd, uid_t uid, - - printerr(1, "doing error downcall\n"); - -- if (WRITE_BYTES(&p, end, uid)) goto out_err; -+ if (WRITE_BYTES(&p, end, seq)) goto out_err; - if (WRITE_BYTES(&p, end, timeout)) goto out_err; - /* use seq_win = 0 to indicate an error: */ - if (WRITE_BYTES(&p, end, zero)) goto out_err; -- if (WRITE_BYTES(&p, end, err)) goto out_err; -+ if (WRITE_BYTES(&p, end, rpc_err)) goto out_err; -+ if (WRITE_BYTES(&p, end, gss_err)) goto out_err; - -- if (write(k5_fd, buf, p - buf) < p - buf) goto out_err; -+ lgssd_mutex_get(lgssd_mutex_downcall); -+ if (write(k5_fd, buf, p - buf) < p - buf) { -+ lgssd_mutex_put(lgssd_mutex_downcall); -+ goto out_err; -+ } -+ lgssd_mutex_put(lgssd_mutex_downcall); - return 0; - out_err: - printerr(0, "Failed to write error downcall!\n"); - return -1; - } - -+#if 0 - /* - * Create an RPC connection and establish an authenticated - * gss context with a server. -@@ -659,7 +621,287 @@ int create_auth_rpc_client(struct clnt_i - - goto out; - } -+#endif -+ -+static -+int do_negotiation(struct lustre_gss_data *lgd, -+ gss_buffer_desc *gss_token, -+ struct lustre_gss_init_res *gr, -+ int timeout) -+{ -+ char *file = "/proc/fs/lustre/sptlrpc/gss/init_channel"; -+ struct lgssd_ioctl_param param; -+ struct passwd *pw; -+ int fd, ret; -+ char outbuf[8192]; -+ unsigned int *p; -+ int res; -+ -+ pw = getpwuid(lgd->lgd_uid); -+ if (!pw) { -+ printerr(0, "no uid %u in local user database\n", -+ lgd->lgd_uid); -+ return -1; -+ } -+ -+ param.version = GSSD_INTERFACE_VERSION; -+ param.uuid = lgd->lgd_uuid; -+ param.lustre_svc = lgd->lgd_lustre_svc; -+ param.uid = lgd->lgd_uid; -+ param.gid = pw->pw_gid; -+ param.send_token_size = gss_token->length; -+ param.send_token = (char *) gss_token->value; -+ param.reply_buf_size = sizeof(outbuf); -+ param.reply_buf = outbuf; -+ -+ fd = open(file, O_RDWR); -+ if (fd < 0) { -+ printerr(0, "can't open file %s\n", file); -+ return -1; -+ } -+ -+ ret = write(fd, ¶m, sizeof(param)); -+ -+ if (ret != sizeof(param)) { -+ printerr(0, "lustre ioctl err: %d\n", strerror(errno)); -+ close(fd); -+ return -1; -+ } -+ if (param.status) { -+ close(fd); -+ printerr(0, "status: %d (%s)\n", -+ param.status, strerror((int)param.status)); -+ if (param.status == -ETIMEDOUT) { -+ /* kernel return -ETIMEDOUT means the rpc timedout, -+ * we should notify the caller to reinitiate the -+ * gss negotiation, by return -ERESTART -+ */ -+ lgd->lgd_rpc_err = -ERESTART; -+ lgd->lgd_gss_err = 0; -+ } else { -+ lgd->lgd_rpc_err = param.status; -+ lgd->lgd_gss_err = 0; -+ } -+ return -1; -+ } -+ p = (unsigned int *)outbuf; -+ res = *p++; -+ gr->gr_major = *p++; -+ gr->gr_minor = *p++; -+ gr->gr_win = *p++; -+ -+ gr->gr_ctx.length = *p++; -+ gr->gr_ctx.value = malloc(gr->gr_ctx.length); -+ memcpy(gr->gr_ctx.value, p, gr->gr_ctx.length); -+ p += (((gr->gr_ctx.length + 3) & ~3) / 4); -+ -+ gr->gr_token.length = *p++; -+ gr->gr_token.value = malloc(gr->gr_token.length); -+ memcpy(gr->gr_token.value, p, gr->gr_token.length); -+ p += (((gr->gr_token.length + 3) & ~3) / 4); -+ -+ printerr(2, "do_negotiation: receive handle len %d, token len %d\n", -+ gr->gr_ctx.length, gr->gr_token.length); -+ close(fd); -+ return 0; -+} -+ -+static -+int gssd_refresh_lgd(struct lustre_gss_data *lgd) -+{ -+ struct lustre_gss_init_res gr; -+ gss_buffer_desc *recv_tokenp, send_token; -+ OM_uint32 maj_stat, min_stat, call_stat, ret_flags; -+ -+ /* GSS context establishment loop. */ -+ memset(&gr, 0, sizeof(gr)); -+ recv_tokenp = GSS_C_NO_BUFFER; -+ -+ for (;;) { -+ /* print the token we just received */ -+ if (recv_tokenp != GSS_C_NO_BUFFER) { -+ printerr(3, "The received token length %d\n", -+ recv_tokenp->length); -+ print_hexl(3, recv_tokenp->value, recv_tokenp->length); -+ } -+ -+ maj_stat = gss_init_sec_context(&min_stat, -+ lgd->lgd_cred, -+ &lgd->lgd_ctx, -+ lgd->lgd_name, -+ lgd->lgd_mech, -+ lgd->lgd_req_flags, -+ 0, /* time req */ -+ NULL, /* channel */ -+ recv_tokenp, -+ NULL, /* used mech */ -+ &send_token, -+ &ret_flags, -+ NULL); /* time rec */ -+ -+ if (recv_tokenp != GSS_C_NO_BUFFER) { -+ gss_release_buffer(&min_stat, &gr.gr_token); -+ recv_tokenp = GSS_C_NO_BUFFER; -+ } -+ if (maj_stat != GSS_S_COMPLETE && -+ maj_stat != GSS_S_CONTINUE_NEEDED) { -+ pgsserr("gss_init_sec_context", maj_stat, min_stat, -+ lgd->lgd_mech); -+ break; -+ } -+ if (send_token.length != 0) { -+ memset(&gr, 0, sizeof(gr)); -+ -+ /* print the token we are about to send */ -+ printerr(3, "token being sent length %d\n", -+ send_token.length); -+ print_hexl(3, send_token.value, send_token.length); -+ -+ call_stat = do_negotiation(lgd, &send_token, &gr, 0); -+ gss_release_buffer(&min_stat, &send_token); -+ -+ if (call_stat != 0 || -+ (gr.gr_major != GSS_S_COMPLETE && -+ gr.gr_major != GSS_S_CONTINUE_NEEDED)) { -+ printerr(0, "call stat %d, major stat 0x%x\n", -+ (int)call_stat, gr.gr_major); -+ return -1; -+ } -+ -+ if (gr.gr_ctx.length != 0) { -+ if (lgd->lgd_rmt_ctx.value) -+ gss_release_buffer(&min_stat, -+ &lgd->lgd_rmt_ctx); -+ lgd->lgd_rmt_ctx = gr.gr_ctx; -+ } -+ if (gr.gr_token.length != 0) { -+ if (maj_stat != GSS_S_CONTINUE_NEEDED) -+ break; -+ recv_tokenp = &gr.gr_token; -+ } -+ } -+ -+ /* GSS_S_COMPLETE => check gss header verifier, -+ * usually checked in gss_validate -+ */ -+ if (maj_stat == GSS_S_COMPLETE) { -+ lgd->lgd_established = 1; -+ lgd->lgd_seq_win = gr.gr_win; -+ break; -+ } -+ } -+ /* End context negotiation loop. */ -+ if (!lgd->lgd_established) { -+ if (gr.gr_token.length != 0) -+ gss_release_buffer(&min_stat, &gr.gr_token); -+ -+ printerr(0, "context negotiation failed\n"); -+ return -1; -+ } -+ -+ printerr(2, "successfully refreshed lgd\n"); -+ return 0; -+} - -+static -+int gssd_create_lgd(struct clnt_info *clp, -+ struct lustre_gss_data *lgd, -+ struct lgssd_upcall_data *updata, -+ int authtype) -+{ -+ gss_buffer_desc sname; -+ OM_uint32 maj_stat, min_stat; -+ int retval = -1; -+ -+ lgd->lgd_established = 0; -+ lgd->lgd_lustre_svc = updata->svc; -+ lgd->lgd_uid = updata->uid; -+ lgd->lgd_uuid = updata->obd; -+ -+ switch (authtype) { -+ case AUTHTYPE_KRB5: -+ lgd->lgd_mech = (gss_OID) &krb5oid; -+ lgd->lgd_req_flags = GSS_C_MUTUAL_FLAG; -+ break; -+ case AUTHTYPE_SPKM3: -+ lgd->lgd_mech = (gss_OID) &spkm3oid; -+ /* XXX sec.req_flags = GSS_C_ANON_FLAG; -+ * Need a way to switch.... -+ */ -+ lgd->lgd_req_flags = GSS_C_MUTUAL_FLAG; -+ break; -+ default: -+ printerr(0, "Invalid authentication type (%d)\n", authtype); -+ return -1; -+ } -+ -+ lgd->lgd_cred = GSS_C_NO_CREDENTIAL; -+ lgd->lgd_ctx = GSS_C_NO_CONTEXT; -+ lgd->lgd_rmt_ctx = (gss_buffer_desc) GSS_C_EMPTY_BUFFER; -+ lgd->lgd_seq_win = 0; -+ -+ sname.value = clp->servicename; -+ sname.length = strlen(clp->servicename); -+ -+ maj_stat = gss_import_name(&min_stat, &sname, -+ (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, -+ &lgd->lgd_name); -+ if (maj_stat != GSS_S_COMPLETE) { -+ pgsserr(0, maj_stat, min_stat, lgd->lgd_mech); -+ goto out_fail; -+ } -+ -+ retval = gssd_refresh_lgd(lgd); -+ -+ if (lgd->lgd_name != GSS_C_NO_NAME) -+ gss_release_name(&min_stat, &lgd->lgd_name); -+ -+ if (lgd->lgd_cred != GSS_C_NO_CREDENTIAL) -+ gss_release_cred(&min_stat, &lgd->lgd_cred); -+ -+ out_fail: -+ return retval; -+} -+ -+static -+void gssd_free_lgd(struct lustre_gss_data *lgd) -+{ -+ gss_buffer_t token = GSS_C_NO_BUFFER; -+ OM_uint32 maj_stat, min_stat; -+ -+ if (lgd->lgd_ctx == GSS_C_NO_CONTEXT) -+ return; -+ -+ maj_stat = gss_delete_sec_context(&min_stat, &lgd->lgd_ctx, token); -+} -+ -+static -+int construct_service_name(struct clnt_info *clp, -+ struct lgssd_upcall_data *ud) -+{ -+ const int buflen = 256; -+ char name[buflen]; -+ -+ if (clp->servicename) { -+ free(clp->servicename); -+ clp->servicename = NULL; -+ } -+ -+ if (lnet_nid2hostname(ud->nid, name, buflen)) -+ return -1; -+ -+ clp->servicename = malloc(32 + strlen(name)); -+ if (!clp->servicename) { -+ printerr(0, "can't alloc memory\n"); -+ return -1; -+ } -+ sprintf(clp->servicename, "%s@%s", -+ ud->svc == LUSTRE_GSS_SVC_MDS ? -+ GSSD_SERVICE_MDS : GSSD_SERVICE_OSS, -+ name); -+ printerr(2, "constructed servicename: %s\n", clp->servicename); -+ return 0; -+} - - /* - * this code uses the userland rpcsec gss library to create a krb5 -@@ -668,103 +910,145 @@ int create_auth_rpc_client(struct clnt_i - void - handle_krb5_upcall(struct clnt_info *clp) - { -- uid_t uid; -- CLIENT *rpc_clnt = NULL; -- AUTH *auth = NULL; -- struct authgss_private_data pd; -- gss_buffer_desc token; -+ pid_t pid; -+ gss_buffer_desc token = { 0, NULL }; -+ struct lgssd_upcall_data updata; -+ struct lustre_gss_data lgd; - char **credlist = NULL; - char **ccname; -+ int read_rc; - -- printerr(1, "handling krb5 upcall\n"); -+ printerr(2, "handling krb5 upcall\n"); - -- token.length = 0; -- token.value = NULL; -- memset(&pd, 0, sizeof(struct authgss_private_data)); -+ memset(&lgd, 0, sizeof(lgd)); -+ lgd.lgd_rpc_err = -EPERM; /* default error code */ - -- if (read(clp->krb5_fd, &uid, sizeof(uid)) < sizeof(uid)) { -- printerr(0, "WARNING: failed reading uid from krb5 " -+ read_rc = read(clp->krb5_fd, &updata, sizeof(updata)); -+ if (read_rc < 0) { -+ printerr(0, "WARNING: failed reading from krb5 " - "upcall pipe: %s\n", strerror(errno)); -- goto out; -+ return; -+ } else if (read_rc != sizeof(updata)) { -+ printerr(0, "upcall data mismatch: length %d, expect %d\n", -+ read_rc, sizeof(updata)); -+ -+ /* the sequence number must be the first field. if read >= 4 -+ * bytes then we know at least sequence is fine, try to send -+ * error notification nicely. -+ */ -+ if (read_rc >= 4) -+ do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0); -+ return; -+ } -+ -+ /* FIXME temporary fix, do this before fork. -+ * in case of errors could have memory leak!!! -+ */ -+ if (updata.uid == 0) { -+ if (gssd_get_krb5_machine_cred_list(&credlist)) { -+ printerr(0, "ERROR: Failed to obtain machine " -+ "credentials\n"); -+ do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0); -+ return; -+ } -+ } -+ -+ /* fork child process */ -+ pid = fork(); -+ if (pid < 0) { -+ printerr(0, "can't fork: %s\n", strerror(errno)); -+ do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0); -+ return; -+ } else if (pid > 0) { -+ printerr(2, "forked child process: %d\n", pid); -+ return; -+ } -+ -+ printerr(1, "krb5 upcall: seq %u, uid %u, svc %u, nid 0x%llx, obd %s\n", -+ updata.seq, updata.uid, updata.svc, updata.nid, updata.obd); -+ -+ if (updata.svc != LUSTRE_GSS_SVC_MDS && -+ updata.svc != LUSTRE_GSS_SVC_OSS) { -+ printerr(0, "invalid svc %d\n", updata.svc); -+ lgd.lgd_rpc_err = -EPROTO; -+ goto out_return_error; -+ } -+ updata.obd[sizeof(updata.obd)-1] = '\0'; -+ -+ if (construct_service_name(clp, &updata)) { -+ printerr(0, "failed to construct service name\n"); -+ goto out_return_error; - } - -- if (uid == 0) { -+ if (updata.uid == 0) { - int success = 0; - - /* - * Get a list of credential cache names and try each - * of them until one works or we've tried them all - */ -+/* - if (gssd_get_krb5_machine_cred_list(&credlist)) { -- printerr(0, "WARNING: Failed to obtain machine " -- "credentials for connection to " -- "server %s\n", clp->servername); -- goto out_return_error; -+ printerr(0, "ERROR: Failed to obtain machine " -+ "credentials for %s\n", clp->servicename); -+ goto out_return_error; - } -+*/ - for (ccname = credlist; ccname && *ccname; ccname++) { - gssd_setup_krb5_machine_gss_ccache(*ccname); -- if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid, -- AUTHTYPE_KRB5)) == 0) { -+ if ((gssd_create_lgd(clp, &lgd, &updata, -+ AUTHTYPE_KRB5)) == 0) { - /* Success! */ - success++; - break; - } - printerr(2, "WARNING: Failed to create krb5 context " - "for user with uid %d with credentials " -- "cache %s for server %s\n", -- uid, *ccname, clp->servername); -+ "cache %s for service %s\n", -+ updata.uid, *ccname, clp->servicename); - } - gssd_free_krb5_machine_cred_list(credlist); - if (!success) { -- printerr(0, "WARNING: Failed to create krb5 context " -+ printerr(0, "ERROR: Failed to create krb5 context " - "for user with uid %d with any " -- "credentials cache for server %s\n", -- uid, clp->servername); -+ "credentials cache for service %s\n", -+ updata.uid, clp->servicename); - goto out_return_error; - } - } - else { - /* Tell krb5 gss which credentials cache to use */ -- gssd_setup_krb5_user_gss_ccache(uid, clp->servername); -+ gssd_setup_krb5_user_gss_ccache(updata.uid, clp->servicename); - -- if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid, -- AUTHTYPE_KRB5)) != 0) { -+ if ((gssd_create_lgd(clp, &lgd, &updata, AUTHTYPE_KRB5)) != 0) { - printerr(0, "WARNING: Failed to create krb5 context " -- "for user with uid %d for server %s\n", -- uid, clp->servername); -+ "for user with uid %d for service %s\n", -+ updata.uid, clp->servicename); - goto out_return_error; - } - } - -- if (!authgss_get_private_data(auth, &pd)) { -- printerr(0, "WARNING: Failed to obtain authentication " -- "data for user with uid %d for server %s\n", -- uid, clp->servername); -- goto out_return_error; -- } -- -- if (serialize_context_for_kernel(pd.pd_ctx, &token, &krb5oid)) { -+ if (serialize_context_for_kernel(lgd.lgd_ctx, &token, &krb5oid)) { - printerr(0, "WARNING: Failed to serialize krb5 context for " -- "user with uid %d for server %s\n", -- uid, clp->servername); -+ "user with uid %d for service %s\n", -+ updata.uid, clp->servicename); - goto out_return_error; - } - -- do_downcall(clp->krb5_fd, uid, &pd, &token); -+ printerr(1, "refreshed: %u@%s for %s\n", -+ updata.uid, updata.obd, clp->servicename); -+ do_downcall(clp->krb5_fd, &updata, &lgd, &token); - - out: - if (token.value) - free(token.value); -- if (pd.pd_ctx_hndl.length != 0) -- authgss_free_private_data(&pd); -- if (auth) -- AUTH_DESTROY(auth); -- if (rpc_clnt) -- clnt_destroy(rpc_clnt); -- return; -+ -+ gssd_free_lgd(&lgd); -+ exit(0); /* i'm child process */ - - out_return_error: -- do_error_downcall(clp->krb5_fd, uid, -1); -+ do_error_downcall(clp->krb5_fd, updata.seq, -+ lgd.lgd_rpc_err, lgd.lgd_gss_err); - goto out; - } - -@@ -775,6 +1059,7 @@ out_return_error: - void - handle_spkm3_upcall(struct clnt_info *clp) - { -+#if 0 - uid_t uid; - CLIENT *rpc_clnt = NULL; - AUTH *auth = NULL; -@@ -826,4 +1111,5 @@ out: - out_return_error: - do_error_downcall(clp->spkm3_fd, uid, -1); - goto out; -+#endif - } -diff -rNup nfs-utils-1.0.10/utils/gssd/gss_util.c nfs-utils-1.0.10.lustre/utils/gssd/gss_util.c ---- nfs-utils-1.0.10/utils/gssd/gss_util.c 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10.lustre/utils/gssd/gss_util.c 2007-05-15 13:01:35.000000000 -0600 -@@ -87,9 +87,16 @@ - #ifdef HAVE_COM_ERR_H - #include - #endif -+#include "lsupport.h" - - /* Global gssd_credentials handle */ --gss_cred_id_t gssd_creds; -+gss_cred_id_t gssd_cred_mds; -+gss_cred_id_t gssd_cred_oss; -+int gssd_cred_mds_valid = 0; -+int gssd_cred_oss_valid = 0; -+ -+char *mds_local_realm = NULL; -+char *oss_local_realm = NULL; - - gss_OID g_mechOid = GSS_C_NULL_OID;; - -@@ -183,15 +190,56 @@ pgsserr(char *msg, u_int32_t maj_stat, u - display_status_2(msg, maj_stat, min_stat, mech); - } - --int --gssd_acquire_cred(char *server_name) -+static -+int extract_realm_name(gss_buffer_desc *name, char **realm) -+{ -+ char *sname, *c; -+ int rc = 0; -+ -+ sname = malloc(name->length + 1); -+ if (!sname) { -+ printerr(0, "out of memory\n"); -+ return -ENOMEM; -+ } -+ -+ memcpy(sname, name->value, name->length); -+ sname[name->length] = '\0'; -+ printerr(1, "service principal: %s\n", sname); -+ -+ c = strchr(sname, '@'); -+ if (!c) { -+ printerr(2, "no realm found in principal, use default\n"); -+ *realm = strdup(this_realm); -+ if (!*realm) { -+ printerr(0, "failed to duplicate default realm\n"); -+ rc = -ENOMEM; -+ } -+ } else { -+ c++; -+ *realm = strdup(c); -+ if (!*realm) { -+ printerr(0, "failed to duplicated realm\n"); -+ rc = -ENOMEM; -+ } -+ } -+ free(sname); -+ -+ return rc; -+} -+ -+static -+int gssd_acquire_cred(char *server_name, gss_cred_id_t *cred, -+ char **local_realm, int *valid) - { - gss_buffer_desc name; - gss_name_t target_name; - u_int32_t maj_stat, min_stat; - u_int32_t ignore_maj_stat, ignore_min_stat; -+ gss_OID name_type; - gss_buffer_desc pbuf; - -+ *valid = 0; -+ - name.value = (void *)server_name; - name.length = strlen(server_name); - -@@ -201,12 +249,20 @@ gssd_acquire_cred(char *server_name) - - if (maj_stat != GSS_S_COMPLETE) { - pgsserr("gss_import_name", maj_stat, min_stat, g_mechOid); -- return (FALSE); -+ return -1; -+ } -+ -+ maj_stat = gss_display_name(&min_stat, target_name, &name, &name_type); -+ if (maj_stat != GSS_S_COMPLETE) { -+ pgsserr(0, maj_stat, min_stat, g_mechOid); -+ return -1; - } -+ if (extract_realm_name(&name, local_realm)) -+ return -1; - - maj_stat = gss_acquire_cred(&min_stat, target_name, 0, - GSS_C_NULL_OID_SET, GSS_C_ACCEPT, -- &gssd_creds, NULL, NULL); -+ cred, NULL, NULL); - - if (maj_stat != GSS_S_COMPLETE) { - pgsserr("gss_acquire_cred", maj_stat, min_stat, g_mechOid); -@@ -218,11 +274,67 @@ gssd_acquire_cred(char *server_name) - ignore_maj_stat = gss_release_buffer(&ignore_min_stat, - &pbuf); - } -- } -+ } else -+ *valid = 1; - - ignore_maj_stat = gss_release_name(&ignore_min_stat, &target_name); - -- return (maj_stat == GSS_S_COMPLETE); -+ if (maj_stat != GSS_S_COMPLETE) -+ return -1; -+ return 0; -+} -+ -+int gssd_prepare_creds(int must_srv_mds, int must_srv_oss) -+{ -+ if (gssd_acquire_cred(GSSD_SERVICE_MDS, &gssd_cred_mds, -+ &mds_local_realm, &gssd_cred_mds_valid)) { -+ if (must_srv_mds) -+ return -1; -+ } -+ -+ if (gssd_acquire_cred(GSSD_SERVICE_OSS, &gssd_cred_oss, -+ &oss_local_realm, &gssd_cred_oss_valid)) { -+ if (must_srv_oss) -+ return -1; -+ } -+ -+ if (!gssd_cred_mds_valid && !gssd_cred_oss_valid) { -+ printerr(0, "can't obtain both mds & oss creds, exit\n"); -+ return -1; -+ } -+ -+ if (gssd_cred_mds_valid) -+ printerr(0, "Ready to serve Lustre MDS in realm %s\n", -+ mds_local_realm ? mds_local_realm : "N/A"); -+ if (gssd_cred_oss_valid) -+ printerr(0, "Ready to serve Lustre OSS in realm %s\n", -+ oss_local_realm ? oss_local_realm : "N/A"); -+ -+ return 0; -+} -+ -+gss_cred_id_t gssd_select_svc_cred(int lustre_svc) -+{ -+ switch (lustre_svc) { -+ case LUSTRE_GSS_SVC_MDS: -+ if (!gssd_cred_mds_valid) { -+ printerr(0, "ERROR: service cred for mds not ready\n"); -+ return NULL; -+ } -+ printerr(2, "select mds service cred\n"); -+ return gssd_cred_mds; -+ case LUSTRE_GSS_SVC_OSS: -+ if (!gssd_cred_oss_valid) { -+ printerr(0, "ERROR: service cred for oss not ready\n"); -+ return NULL; -+ } -+ printerr(2, "select oss service cred\n"); -+ return gssd_cred_oss; -+ default: -+ printerr(0, "ERROR: invalid lustre svc id %d\n", lustre_svc); -+ } -+ -+ return NULL; - } - - int gssd_check_mechs(void) -@@ -249,3 +361,42 @@ out: - return retval; - } - -+/********************************* -+ * FIXME should be in krb5_util.c -+ *********************************/ -+ -+#include "krb5_util.h" -+ -+/* realm of this node */ -+char *this_realm = NULL; -+ -+int gssd_get_local_realm(void) -+{ -+ krb5_context context = NULL; -+ krb5_error_code code; -+ int retval = -1; -+ -+ if (this_realm != NULL) -+ return 0; -+ -+ code = krb5_init_context(&context); -+ if (code) { -+ printerr(0, "ERROR: get default realm: init ctx: %s\n", -+ error_message(code)); -+ goto out; -+ } -+ -+ code = krb5_get_default_realm(context, &this_realm); -+ if (code) { -+ printerr(0, "ERROR: get default realm: %s\n", -+ error_message(code)); -+ goto out; -+ } -+ retval = 0; -+ -+ printerr(1, "Local realm: %s\n", this_realm); -+out: -+ krb5_free_context(context); -+ return retval; -+} -+ -diff -rNup nfs-utils-1.0.10/utils/gssd/gss_util.h nfs-utils-1.0.10.lustre/utils/gssd/gss_util.h ---- nfs-utils-1.0.10/utils/gssd/gss_util.h 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10.lustre/utils/gssd/gss_util.h 2007-05-15 13:01:35.000000000 -0600 -@@ -32,14 +32,14 @@ - #define _GSS_UTIL_H_ - - #include --#include - #include "write_bytes.h" - -+char *this_realm; - extern gss_cred_id_t gssd_creds; - --int gssd_acquire_cred(char *server_name); - void pgsserr(char *msg, u_int32_t maj_stat, u_int32_t min_stat, - const gss_OID mech); - int gssd_check_mechs(void); -+int gssd_get_local_realm(void); - - #endif /* _GSS_UTIL_H_ */ -diff -rNup nfs-utils-1.0.10/utils/gssd/krb5_util.c nfs-utils-1.0.10.lustre/utils/gssd/krb5_util.c ---- nfs-utils-1.0.10/utils/gssd/krb5_util.c 2007-05-15 13:02:26.000000000 -0600 -+++ nfs-utils-1.0.10.lustre/utils/gssd/krb5_util.c 2007-05-15 13:01:35.000000000 -0600 -@@ -99,12 +99,15 @@ - #include - #include - #include -+#include - #include - #include - -+#include - #include - #include - #include -+#include - #include - #include - #include -@@ -114,7 +117,6 @@ - #include - #endif - #include --#include - - #include "gssd.h" - #include "err_util.h" -@@ -129,6 +131,9 @@ struct gssd_k5_kt_princ *gssd_k5_kt_prin - int num_krb5_enctypes = 0; - krb5_enctype *krb5_enctypes = NULL; - -+/* credential expire time in advance */ -+unsigned long machine_cred_expire_advance = 300; /* 5 mins */ -+ - /*==========================*/ - /*=== Internal routines ===*/ - /*==========================*/ -@@ -137,11 +142,55 @@ static int select_krb5_ccache(const stru - static int gssd_find_existing_krb5_ccache(uid_t uid, struct dirent **d); - static int gssd_get_single_krb5_cred(krb5_context context, - krb5_keytab kt, struct gssd_k5_kt_princ *ple); --static int gssd_have_realm_ple(void *realm); - static int gssd_process_krb5_keytab(krb5_context context, krb5_keytab kt, - char *kt_name); - - /* -+ * convenient macros, these perhaps need further cleanup -+ */ -+#ifdef HAVE_KRB5 -+ -+#define KEYTAB_ENTRY_MATCH(kte, name) \ -+ ( \ -+ (kte).principal->data[0].length == (sizeof(name)-1) && \ -+ strncmp((kte).principal->data[0].data, (name), sizeof(name)-1) == 0 \ -+ ) -+#define KRB5_FREE_UNPARSED_NAME(ctx, name) \ -+ krb5_free_unparsed_name((ctx), (name)); -+#define KRB5_STRDUP(str) \ -+ strndup((str).data, (str).length) -+#define KRB5_STRCMP(str, name) \ -+ ( \ -+ (str)->length != strlen(name) || \ -+ strncmp((str)->data, (name), (str)->length) != 0 \ -+ ) -+#define KRB5_STRCASECMP(str, name) \ -+ ( \ -+ (str)->length != strlen(name) || \ -+ strncasecmp((str)->data, (name), (str)->length) != 0 \ -+ ) -+ -+#else /* !HAVE_KRB5 */ -+ -+#define KEYTAB_ENTRY_MATCH(kte, name) \ -+ ( \ -+ strlen((kte).principal->name.name_string.val[0]) == \ -+ (sizeof(name)-1) && \ -+ strncmp(kte.principal->name.name_string.val[0], (name), \ -+ sizeof(name)-1) == 0 \ -+ ) -+#define KRB5_FREE_UNPARSED_NAME(ctx, name) \ -+ free(pname); -+#define KRB5_STRDUP(str) \ -+ strdup(str) -+#define KRB5_STRCMP(str, name) \ -+ strcmp((str), (name)) -+#define KRB5_STRCASECMP(str, name) \ -+ strcmp((str), (name)) -+ -+#endif /* HAVE_KRB5 */ -+ -+/* - * Called from the scandir function to weed out potential krb5 - * credentials cache files - * -@@ -294,7 +343,7 @@ gssd_get_single_krb5_cred(krb5_context c - - memset(&my_creds, 0, sizeof(my_creds)); - -- if (ple->ccname && ple->endtime > now) { -+ if (ple->ccname && ple->endtime > now + machine_cred_expire_advance) { - printerr(2, "INFO: Credentials in CC '%s' are good until %d\n", - ple->ccname, ple->endtime); - code = 0; -@@ -314,6 +363,12 @@ gssd_get_single_krb5_cred(krb5_context c - /* set a short lifetime (for debugging only!) */ - printerr(0, "WARNING: Using (debug) short machine cred lifetime!\n"); - krb5_get_init_creds_opt_set_tkt_life(&options, 5*60); -+#else -+ /* FIXME try to get the ticket with lifetime as long as possible, -+ * to work around ticket-expiry + recovery problem in cmd3-11 -+ * remove this!!! -+ */ -+ krb5_get_init_creds_opt_set_tkt_life(&options, 30*24*60*60); - #endif - if ((code = krb5_get_init_creds_keytab(context, &my_creds, ple->princ, - kt, 0, NULL, &options))) { -@@ -325,11 +380,7 @@ gssd_get_single_krb5_cred(krb5_context c - "principal '%s' from keytab '%s'\n", - error_message(code), - pname ? pname : "", kt_name); --#ifdef HAVE_KRB5 -- if (pname) krb5_free_unparsed_name(context, pname); --#else -- if (pname) free(pname); --#endif -+ if (pname) KRB5_FREE_UNPARSED_NAME(context, pname); - goto out; - } - -@@ -378,15 +429,7 @@ gssd_get_single_krb5_cred(krb5_context c - return (code); - } - --/* -- * Determine if we already have a ple for the given realm -- * -- * Returns: -- * 0 => no ple found for given realm -- * 1 => found ple for given realm -- */ --static int --gssd_have_realm_ple(void *r) -+static struct gssd_k5_kt_princ * gssd_get_realm_ple(void *r) - { - struct gssd_k5_kt_princ *ple; - #ifdef HAVE_KRB5 -@@ -396,18 +439,76 @@ gssd_have_realm_ple(void *r) - #endif - - for (ple = gssd_k5_kt_princ_list; ple; ple = ple->next) { --#ifdef HAVE_KRB5 -- if ((realm->length == strlen(ple->realm)) && -- (strncmp(realm->data, ple->realm, realm->length) == 0)) { --#else -- if (strcmp(realm, ple->realm) == 0) { --#endif -- return 1; -- } -+ if (KRB5_STRCMP(realm, ple->realm) == 0) -+ return ple; -+ } -+ return NULL; -+} -+ -+static void gssd_free_ple(krb5_context kctx, struct gssd_k5_kt_princ *ple) -+{ -+ if (ple->princ) -+ krb5_free_principal(kctx, ple->princ); -+ if (ple->realm) -+ free(ple->realm); -+ if (ple->ccname) -+ free(ple->ccname); -+ free(ple); -+} -+ -+static int gssd_remove_ple(krb5_context kctx, struct gssd_k5_kt_princ *ple) -+{ -+ struct gssd_k5_kt_princ **prev = &gssd_k5_kt_princ_list; -+ struct gssd_k5_kt_princ *ent = gssd_k5_kt_princ_list; -+ -+ for (; ent; prev = &ent->next, ent = ent->next) { -+ if (ent != ple) -+ continue; -+ -+ *prev = ent->next; -+ gssd_free_ple(kctx, ent); -+ return 1; - } - return 0; - } - -+static -+struct gssd_k5_kt_princ *gssd_create_ple(krb5_context kctx, -+ krb5_principal principal) -+{ -+ struct gssd_k5_kt_princ *ple; -+ krb5_error_code code; -+ -+ ple = malloc(sizeof(*ple)); -+ if (ple == NULL) { -+ printerr(0, "ERROR: could not allocate storage " -+ "for principal list entry\n"); -+ return NULL; -+ } -+ -+ memset(ple, 0, sizeof(*ple)); -+ -+ ple->realm = KRB5_STRDUP(principal->realm); -+ if (ple->realm == NULL) { -+ printerr(0, "ERROR: not enough memory while copying realm to " -+ "principal list entry\n"); -+ goto err_free; -+ } -+ -+ code = krb5_copy_principal(kctx, principal, &ple->princ); -+ if (code) { -+ printerr(0, "ERROR: %s while copying principal " -+ "to principal list entry\n", -+ error_message(code)); -+ goto err_free; -+ } -+ -+ return ple; -+err_free: -+ gssd_free_ple(kctx, ple); -+ return NULL; -+} -+ - /* - * Process the given keytab file and create a list of principals we - * might use to perform mount operations. -@@ -451,82 +552,106 @@ gssd_process_krb5_keytab(krb5_context co - } - printerr(2, "Processing keytab entry for principal '%s'\n", - pname); --#ifdef HAVE_KRB5 -- if ( (kte.principal->data[0].length == GSSD_SERVICE_NAME_LEN) && -- (strncmp(kte.principal->data[0].data, GSSD_SERVICE_NAME, -- GSSD_SERVICE_NAME_LEN) == 0) && --#else -- if ( (strlen(kte.principal->name.name_string.val[0]) == GSSD_SERVICE_NAME_LEN) && -- (strncmp(kte.principal->name.name_string.val[0], GSSD_SERVICE_NAME, -- GSSD_SERVICE_NAME_LEN) == 0) && -- --#endif -- (!gssd_have_realm_ple((void *)&kte.principal->realm)) ) { -- printerr(2, "We will use this entry (%s)\n", pname); -- ple = malloc(sizeof(struct gssd_k5_kt_princ)); -- if (ple == NULL) { -- printerr(0, "ERROR: could not allocate storage " -- "for principal list entry\n"); --#ifdef HAVE_KRB5 -- krb5_free_unparsed_name(context, pname); --#else -- free(pname); --#endif -- retval = ENOMEM; -- goto out; -+ -+ /* mds service entry: -+ * - hostname and realm should match this node -+ * - replace existing non-mds entry of this realm -+ */ -+ if (KEYTAB_ENTRY_MATCH(kte, GSSD_SERVICE_MDS)) { -+ krb5_principal princ = kte.principal; -+ krb5_data *princ_host; -+ struct utsname utsbuf; -+ struct hostent *host; -+ -+ if (KRB5_STRCASECMP(krb5_princ_realm(context, princ), -+ this_realm) != 0) { -+ printerr(2, "alien mds service entry, skip\n"); -+ goto next; - } -- /* These will be filled in later */ -- ple->next = NULL; -- ple->ccname = NULL; -- ple->endtime = 0; -- if ((ple->realm = --#ifdef HAVE_KRB5 -- strndup(kte.principal->realm.data, -- kte.principal->realm.length)) --#else -- strdup(kte.principal->realm)) --#endif -- == NULL) { -- printerr(0, "ERROR: %s while copying realm to " -- "principal list entry\n", -- "not enough memory"); --#ifdef HAVE_KRB5 -- krb5_free_unparsed_name(context, pname); --#else -- free(pname); --#endif -- retval = ENOMEM; -- goto out; -+ -+ princ_host = krb5_princ_component(context, princ, 1); -+ if (princ_host == NULL) { -+ printerr(2, "mds service entry: no hostname in " -+ "principal, skip\n"); -+ goto next; - } -- if ((code = krb5_copy_principal(context, -- kte.principal, &ple->princ))) { -- printerr(0, "ERROR: %s while copying principal " -- "to principal list entry\n", -- error_message(code)); --#ifdef HAVE_KRB5 -- krb5_free_unparsed_name(context, pname); --#else -- free(pname); --#endif -- retval = code; -- goto out; -+ -+ if (uname(&utsbuf)) { -+ printerr(2, "mds service entry: unable to get " -+ "UTS name, skip\n"); -+ goto next; - } -- if (gssd_k5_kt_princ_list == NULL) -- gssd_k5_kt_princ_list = ple; -- else { -- ple->next = gssd_k5_kt_princ_list; -- gssd_k5_kt_princ_list = ple; -+ host = gethostbyname(utsbuf.nodename); -+ if (host == NULL) { -+ printerr(2, "mds service entry: unable to get " -+ "local hostname, skip\n"); -+ goto next; - } -- } -- else { -+ -+ if (KRB5_STRCASECMP(princ_host, host->h_name) != 0) { -+ printerr(2, "mds service entry: hostname " -+ "doesn't match: %s - %.*s, skip\n", -+ host->h_name, -+ princ_host->length, princ_host->data); -+ goto next; -+ } -+ -+ ple = gssd_get_realm_ple((void *)&kte.principal->realm); -+ if (ple) { -+ if (ple->fl_mds) { -+ printerr(2,"mds service entry: found a " -+ "duplicated one, it's like a " -+ "mis-configuration, skip\n"); -+ goto next; -+ } -+ -+ gssd_remove_ple(context, ple); -+ printerr(2, "mds service entry: replace an " -+ "existed non-mds one\n"); -+ } -+ } else if (KEYTAB_ENTRY_MATCH(kte, LUSTRE_ROOT_NAME)) { -+ ple = gssd_get_realm_ple((void *)&kte.principal->realm); -+ if (ple) { -+ if (ple->fl_mds || ple->fl_root) { -+ printerr(2, "root entry: found a " -+ "existed %s entry, skip\n", -+ ple->fl_mds ? "mds" : "root"); -+ goto next; -+ } -+ -+ gssd_remove_ple(context, ple); -+ printerr(2, "root entry: replace an existed " -+ "non-mds non-root one\n"); -+ } -+ } else { - printerr(2, "We will NOT use this entry (%s)\n", - pname); -+ goto next; - } --#ifdef HAVE_KRB5 -- krb5_free_unparsed_name(context, pname); --#else -- free(pname); --#endif -+ -+ /* construct ple */ -+ printerr(2, "We will use this entry (%s)\n", pname); -+ ple = gssd_create_ple(context, kte.principal); -+ if (ple == NULL) { -+ KRB5_FREE_UNPARSED_NAME(context, pname); -+ goto out; -+ } -+ -+ /* add proper flags */ -+ if (KEYTAB_ENTRY_MATCH(kte, GSSD_SERVICE_MDS)) -+ ple->fl_mds = 1; -+ else if (KEYTAB_ENTRY_MATCH(kte, LUSTRE_ROOT_NAME)) -+ ple->fl_root = 1; -+ -+ /* enqueue */ -+ if (gssd_k5_kt_princ_list == NULL) -+ gssd_k5_kt_princ_list = ple; -+ else { -+ ple->next = gssd_k5_kt_princ_list; -+ gssd_k5_kt_princ_list = ple; -+ } -+ next: -+ KRB5_FREE_UNPARSED_NAME(context, pname); - } - - if ((code = krb5_kt_end_seq_get(context, kt, &cursor))) { -@@ -642,6 +767,7 @@ gssd_setup_krb5_user_gss_ccache(uid_t ui - printerr(2, "getting credentials for client with uid %u for " - "server %s\n", uid, servername); - memset(buf, 0, sizeof(buf)); -+ - if (gssd_find_existing_krb5_ccache(uid, &d)) { - snprintf(buf, sizeof(buf), "FILE:%s/%s", - ccachedir, d->d_name); -@@ -702,7 +828,7 @@ gssd_refresh_krb5_machine_creds(void) - goto out; - } - -- printerr(1, "Using keytab file '%s'\n", keytabfile); -+ printerr(2, "Using keytab file '%s'\n", keytabfile); - - if ((code = krb5_kt_resolve(context, keytabfile, &kt))) { - printerr(0, "ERROR: %s while resolving keytab '%s'\n", -@@ -717,12 +843,12 @@ gssd_refresh_krb5_machine_creds(void) - if (gssd_k5_kt_princ_list == NULL) { - printerr(0, "ERROR: No usable keytab entries found in " - "keytab '%s'\n", keytabfile); -- printerr(0, "Do you have a valid keytab entry for " -- "%s/@ in " -+ printerr(0, "You must have a valid keytab entry for " -+ "%s/@ on MDT nodes, " -+ "and %s@ on client nodes, in " - "keytab file %s ?\n", -- GSSD_SERVICE_NAME, keytabfile); -- printerr(0, "Continuing without (machine) credentials " -- "- nfs4 mounts with Kerberos will fail\n"); -+ GSSD_SERVICE_MDS, LUSTRE_ROOT_NAME, -+ keytabfile); - } - } - -@@ -872,6 +998,7 @@ gssd_destroy_krb5_machine_creds(void) - krb5_free_context(context); - } - -+#if 0 - #ifdef HAVE_SET_ALLOWABLE_ENCTYPES - /* - * this routine obtains a credentials handle via gss_acquire_cred() -@@ -927,6 +1054,7 @@ limit_krb5_enctypes(struct rpc_gss_sec * - return 0; - } - #endif /* HAVE_SET_ALLOWABLE_ENCTYPES */ -+#endif - - /* - * Obtain supported enctypes from kernel. -diff -rNup nfs-utils-1.0.10/utils/gssd/krb5_util.h nfs-utils-1.0.10.lustre/utils/gssd/krb5_util.h ---- nfs-utils-1.0.10/utils/gssd/krb5_util.h 2007-05-15 13:02:26.000000000 -0600 -+++ nfs-utils-1.0.10.lustre/utils/gssd/krb5_util.h 2007-05-15 13:01:35.000000000 -0600 -@@ -10,6 +10,8 @@ - struct gssd_k5_kt_princ { - struct gssd_k5_kt_princ *next; - krb5_principal princ; -+ unsigned int fl_root:1, -+ fl_mds:1; - char *ccname; - char *realm; - krb5_timestamp endtime; -@@ -25,8 +27,4 @@ void gssd_destroy_krb5_machine_creds(voi - void gssd_obtain_kernel_krb5_info(void); - - --#ifdef HAVE_SET_ALLOWABLE_ENCTYPES --int limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid); --#endif -- - #endif /* KRB5_UTIL_H */ -diff -rNup nfs-utils-1.0.10/utils/gssd/lgss_keyring.c nfs-utils-1.0.10.lustre/utils/gssd/lgss_keyring.c ---- nfs-utils-1.0.10/utils/gssd/lgss_keyring.c 1969-12-31 17:00:00.000000000 -0700 -+++ nfs-utils-1.0.10.lustre/utils/gssd/lgss_keyring.c 2007-05-15 13:01:35.000000000 -0600 -@@ -0,0 +1,776 @@ -+/* -+ * lucall_keyring.c -+ * user-space upcall to create GSS context, using keyring interface to kernel -+ * -+ * Copyright (c) 2007 Cluster File Systems, Inc. -+ * Author: Eric Mei -+ * -+ * This file is part of the Lustre file system, http://www.lustre.org -+ * Lustre is a trademark of Cluster File Systems, Inc. -+ * -+ * You may have signed or agreed to another license before downloading -+ * this software. If so, you are bound by the terms and conditions -+ * of that agreement, and the following does not apply to you. See the -+ * LICENSE file included with this distribution for more information. -+ * -+ * If you did not agree to a different license, then this copy of Lustre -+ * is open source software; you can redistribute it and/or modify it -+ * under the terms of version 2 of the GNU General Public License as -+ * published by the Free Software Foundation. -+ * -+ * In either case, Lustre is distributed in the hope that it will be -+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty -+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * license text for more details. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#include "lsupport.h" -+#include "write_bytes.h" -+#include "krb5_util.h" -+#include "gss_oids.h" -+#include "context.h" -+ -+/* -+ * XXX TEMP to satisfy link. should be removed!!! -+ */ -+char ccachedir[PATH_MAX] = "/tmp"; -+char keytabfile[PATH_MAX] = "/etc/krb5.keytab"; -+int use_memcache = 0; -+ -+/**************************************** -+ * log facilities * -+ ****************************************/ -+ -+/* -+ * log level: -+ * 0: critical error messages -+ * 1: warning included -+ * 2: debugging -+ * 3: excessive messages -+ */ -+typedef enum { -+ LL_ERR = 0, -+ LL_WARN = 1, -+ LL_INFO = 2, -+ LL_TRACE = 3, -+} loglevel_t; -+ -+loglevel_t g_log_level = LL_TRACE; -+ -+static void logmsg(loglevel_t level, const char *format, ...) -+{ -+ char buf[1024]; -+ int offset; -+ va_list ap; -+ -+ if (level > g_log_level) -+ return; -+ -+ offset = snprintf(buf, sizeof(buf), "[%d]: ", getpid()); -+ -+ va_start(ap, format); -+ vsnprintf(buf + offset, sizeof(buf) - offset, format, ap); -+ va_end(ap); -+ -+ syslog(LOG_INFO, "%s", buf); -+} -+ -+static void logmsg_gss(loglevel_t level, const gss_OID mech, -+ u_int32_t major, u_int32_t minor, -+ const char *format, ...) -+{ -+ va_list ap; -+ u_int32_t maj_stat1, min_stat1; -+ u_int32_t maj_stat2, min_stat2; -+ gss_buffer_desc maj_gss_buf = GSS_C_EMPTY_BUFFER; -+ gss_buffer_desc min_gss_buf = GSS_C_EMPTY_BUFFER; -+ char maj_buf[30], min_buf[30]; -+ char *maj, *min; -+ uint32_t msg_ctx = 0; -+ -+ if (level > g_log_level) -+ return; -+ -+ /* Get major status message */ -+ maj_stat1 = gss_display_status(&min_stat1, major, -+ GSS_C_GSS_CODE, mech, &msg_ctx, &maj_gss_buf); -+ -+ if (maj_stat1 != GSS_S_COMPLETE) { -+ snprintf(maj_buf, sizeof(maj_buf), "(0x%08x)", major); -+ maj = &maj_buf[0]; -+ } else { -+ maj = maj_gss_buf.value; -+ } -+ -+ /* Get minor status message */ -+ maj_stat2 = gss_display_status(&min_stat2, minor, -+ GSS_C_MECH_CODE, mech, &msg_ctx, &min_gss_buf); -+ -+ if (maj_stat2 != GSS_S_COMPLETE) { -+ snprintf(min_buf, sizeof(min_buf), "(0x%08x)", minor); -+ min = &min_buf[0]; -+ } else { -+ min = min_gss_buf.value; -+ } -+ -+ syslog(LOG_INFO, "GSS-API: %s - %s\n", maj, min); -+ -+ va_start(ap, format); -+ vsyslog(LOG_INFO, format, ap); -+ va_end(ap); -+ -+ if (maj_gss_buf.length != 0) -+ (void) gss_release_buffer(&min_stat1, &maj_gss_buf); -+ if (min_gss_buf.length != 0) -+ (void) gss_release_buffer(&min_stat2, &min_gss_buf); -+} -+ -+#define lassert(exp) \ -+ { \ -+ if ((int)(exp) == 0) { \ -+ logmsg(LL_ERR, "ASSERTION FAILED: #exp"); \ -+ exit(-1); \ -+ } \ -+ } -+ -+/**************************************** -+ * global declaration * -+ ****************************************/ -+ -+typedef enum { -+ LGSS_SVC_MDS = 0, -+ LGSS_SVC_OSS = 1, -+ LGSS_SVC_MAX -+} lgss_svc_t; -+ -+const char *lgss_svc_name[LGSS_SVC_MAX] = { -+ [LGSS_SVC_MDS] = "lustre_mds", -+ [LGSS_SVC_OSS] = "lustre_oss", -+}; -+ -+typedef enum { -+ LGSS_AUTH_KRB5, -+} lgss_auth_t; -+ -+/* -+ * all data about negotiation -+ */ -+struct lgss_nego_data { -+ uint32_t lnd_established:1; -+ uint32_t lnd_uid; -+ uint32_t lnd_lsvc; -+ char *lnd_uuid; -+ -+ gss_OID lnd_mech; /* mech OID */ -+ gss_name_t lnd_svc_name; /* service name */ -+ u_int lnd_req_flags; /* request flags */ -+ gss_cred_id_t lnd_cred; /* credential */ -+ gss_ctx_id_t lnd_ctx; /* session context */ -+ gss_buffer_desc lnd_rmt_ctx; /* remote handle of context */ -+ uint32_t lnd_seq_win; /* sequence window */ -+ -+ int lnd_rpc_err; -+ int lnd_gss_err; -+}; -+ -+/* -+ * context creation response -+ */ -+struct lgss_init_res { -+ gss_buffer_desc gr_ctx; /* context handle */ -+ u_int gr_major; /* major status */ -+ u_int gr_minor; /* minor status */ -+ u_int gr_win; /* sequence window */ -+ gss_buffer_desc gr_token; /* token */ -+}; -+ -+struct keyring_upcall_param { -+ uint32_t kup_ver; -+ uint32_t kup_uid; -+ uint32_t kup_gid; -+ uint32_t kup_svc; -+ uint64_t kup_nid; -+ char kup_tgt[64]; -+}; -+ -+/* -+ * gss target string of lustre service we are negotiating for -+ */ -+char *g_service = NULL; -+ -+/**************************************** -+ * child process: gss negotiation * -+ ****************************************/ -+ -+#define INIT_CHANNEL "/proc/fs/lustre/sptlrpc/gss/init_channel" -+ -+int do_nego_rpc(struct lgss_nego_data *lnd, -+ gss_buffer_desc *gss_token, -+ struct lgss_init_res *gr) -+{ -+ struct lgssd_ioctl_param param; -+ struct passwd *pw; -+ int fd, ret, res; -+ char outbuf[8192]; -+ unsigned int *p; -+ -+ logmsg(LL_TRACE, "do_nego_rpc: get started\n"); -+ -+ pw = getpwuid(lnd->lnd_uid); -+ if (!pw) { -+ logmsg(LL_ERR, "no uid %u in local user database\n", -+ lnd->lnd_uid); -+ return -1; -+ } -+ -+ param.version = GSSD_INTERFACE_VERSION; -+ param.uuid = lnd->lnd_uuid; -+ param.lustre_svc = lnd->lnd_lsvc; -+ param.uid = lnd->lnd_uid; -+ param.gid = pw->pw_gid; -+ param.send_token_size = gss_token->length; -+ param.send_token = (char *) gss_token->value; -+ param.reply_buf_size = sizeof(outbuf); -+ param.reply_buf = outbuf; -+ -+ logmsg(LL_TRACE, "to open " INIT_CHANNEL "\n"); -+ -+ fd = open(INIT_CHANNEL, O_WRONLY); -+ if (fd < 0) { -+ logmsg(LL_ERR, "can't open " INIT_CHANNEL "\n"); -+ return -1; -+ } -+ -+ logmsg(LL_TRACE, "to down-write\n"); -+ -+ ret = write(fd, ¶m, sizeof(param)); -+ if (ret != sizeof(param)) { -+ logmsg(LL_ERR, "lustre ioctl err: %d\n", strerror(errno)); -+ close(fd); -+ return -1; -+ } -+ close(fd); -+ -+ logmsg(LL_TRACE, "do_nego_rpc: to parse reply\n"); -+ if (param.status) { -+ logmsg(LL_ERR, "status: %d (%s)\n", -+ param.status, strerror((int)param.status)); -+ -+ if (param.status == -ETIMEDOUT) { -+ /* kernel return -ETIMEDOUT means the rpc timedout, -+ * we should notify the caller to reinitiate the -+ * gss negotiation, by return -ERESTART -+ */ -+ lnd->lnd_rpc_err = -ERESTART; -+ lnd->lnd_gss_err = 0; -+ } else { -+ lnd->lnd_rpc_err = param.status; -+ lnd->lnd_gss_err = 0; -+ } -+ -+ return -1; -+ } -+ -+ p = (unsigned int *)outbuf; -+ res = *p++; -+ gr->gr_major = *p++; -+ gr->gr_minor = *p++; -+ gr->gr_win = *p++; -+ -+ gr->gr_ctx.length = *p++; -+ gr->gr_ctx.value = malloc(gr->gr_ctx.length); -+ memcpy(gr->gr_ctx.value, p, gr->gr_ctx.length); -+ p += (((gr->gr_ctx.length + 3) & ~3) / 4); -+ -+ gr->gr_token.length = *p++; -+ gr->gr_token.value = malloc(gr->gr_token.length); -+ memcpy(gr->gr_token.value, p, gr->gr_token.length); -+ p += (((gr->gr_token.length + 3) & ~3) / 4); -+ -+ logmsg(LL_INFO, "do_nego_rpc: receive handle len %d, token len %d\n", -+ gr->gr_ctx.length, gr->gr_token.length); -+ return 0; -+} -+ -+/* -+ * if return error, the lnd_rpc_err or lnd_gss_err is set. -+ */ -+int lgssc_negotiation(struct lgss_nego_data *lnd) -+{ -+ struct lgss_init_res gr; -+ gss_buffer_desc *recv_tokenp, send_token; -+ OM_uint32 maj_stat, min_stat, ret_flags; -+ int call_stat; -+ -+ logmsg(LL_TRACE, "start negotiation\n"); -+ -+ /* GSS context establishment loop. */ -+ memset(&gr, 0, sizeof(gr)); -+ recv_tokenp = GSS_C_NO_BUFFER; -+ -+ for (;;) { -+#if 0 -+ /* print the token we just received */ -+ if (recv_tokenp != GSS_C_NO_BUFFER) { -+ printerr(3, "The received token length %d\n", -+ recv_tokenp->length); -+ print_hexl(3, recv_tokenp->value, recv_tokenp->length); -+ } -+#endif -+ -+ maj_stat = gss_init_sec_context(&min_stat, -+ lnd->lnd_cred, -+ &lnd->lnd_ctx, -+ lnd->lnd_svc_name, -+ lnd->lnd_mech, -+ lnd->lnd_req_flags, -+ 0, /* time req */ -+ NULL, /* channel */ -+ recv_tokenp, -+ NULL, /* used mech */ -+ &send_token, -+ &ret_flags, -+ NULL); /* time rec */ -+ -+ if (recv_tokenp != GSS_C_NO_BUFFER) { -+ gss_release_buffer(&min_stat, &gr.gr_token); -+ recv_tokenp = GSS_C_NO_BUFFER; -+ } -+ -+ if (maj_stat != GSS_S_COMPLETE && -+ maj_stat != GSS_S_CONTINUE_NEEDED) { -+ lnd->lnd_gss_err = maj_stat; -+ -+ logmsg_gss(LL_ERR, lnd->lnd_mech, maj_stat, min_stat, -+ "failed init context\n"); -+ break; -+ } -+ -+ if (send_token.length != 0) { -+ memset(&gr, 0, sizeof(gr)); -+#if 0 -+ /* print the token we are about to send */ -+ printerr(3, "token being sent length %d\n", -+ send_token.length); -+ print_hexl(3, send_token.value, send_token.length); -+#endif -+ call_stat = do_nego_rpc(lnd, &send_token, &gr); -+ gss_release_buffer(&min_stat, &send_token); -+ -+ if (call_stat != 0 || -+ (gr.gr_major != GSS_S_COMPLETE && -+ gr.gr_major != GSS_S_CONTINUE_NEEDED)) { -+ lnd->lnd_rpc_err = call_stat; -+ lnd->lnd_gss_err = gr.gr_major; -+ -+ logmsg(LL_ERR, "call stat %d, major stat %x\n", -+ call_stat, gr.gr_major); -+ return -1; -+ } -+ -+ if (gr.gr_ctx.length != 0) { -+ if (lnd->lnd_rmt_ctx.value) -+ gss_release_buffer(&min_stat, -+ &lnd->lnd_rmt_ctx); -+ lnd->lnd_rmt_ctx = gr.gr_ctx; -+ } -+ -+ if (gr.gr_token.length != 0) { -+ if (maj_stat != GSS_S_CONTINUE_NEEDED) -+ break; -+ recv_tokenp = &gr.gr_token; -+ } -+ } -+ -+ /* GSS_S_COMPLETE => check gss header verifier, -+ * usually checked in gss_validate -+ */ -+ if (maj_stat == GSS_S_COMPLETE) { -+ lnd->lnd_established = 1; -+ lnd->lnd_seq_win = gr.gr_win; -+ break; -+ } -+ } -+ -+ /* End context negotiation loop. */ -+ if (!lnd->lnd_established) { -+ if (gr.gr_token.length != 0) -+ gss_release_buffer(&min_stat, &gr.gr_token); -+ -+ if (lnd->lnd_gss_err == GSS_S_COMPLETE) -+ lnd->lnd_rpc_err = -EACCES; -+ -+ logmsg(LL_ERR, "context negotiation failed\n"); -+ return -1; -+ } -+ -+ logmsg(LL_INFO, "successfully negotiated context\n"); -+ return 0; -+} -+ -+int construct_service(struct keyring_upcall_param *kup) -+{ -+ const int max_namelen = 512; -+ char namebuf[max_namelen]; -+ int alloc_size; -+ -+ lassert(g_service == NULL); -+ -+ if (kup->kup_svc >= LGSS_SVC_MAX) { -+ logmsg(LL_ERR, "invalid lgss service %d\n", kup->kup_svc); -+ return 1; -+ } -+ -+ if (lnet_nid2hostname(kup->kup_nid, namebuf, max_namelen)) -+ return 1; -+ -+ alloc_size = 32 + strlen(namebuf); -+ -+ g_service = malloc(alloc_size); -+ if (g_service == NULL) { -+ logmsg(LL_ERR, "can't malloc %d bytes\n", alloc_size); -+ return 1; -+ } -+ -+ snprintf(g_service, alloc_size, "%s@%s", -+ lgss_svc_name[kup->kup_svc], namebuf); -+ -+ logmsg(LL_INFO, "constructed service: %s\n", g_service); -+ return 0; -+} -+ -+/* -+ * if return error, the lnd_rpc_err or lnd_gss_err is set. -+ */ -+int lgssc_init_nego_data(struct lgss_nego_data *lnd, -+ struct keyring_upcall_param *kup, -+ lgss_auth_t authtype) -+{ -+ gss_buffer_desc sname; -+ OM_uint32 maj_stat, min_stat; -+ -+ memset(lnd, 0, sizeof(*lnd)); -+ -+ lnd->lnd_uid = kup->kup_uid; -+ lnd->lnd_lsvc = kup->kup_svc; -+ lnd->lnd_uuid = kup->kup_tgt; -+ -+ lnd->lnd_established = 0; -+ lnd->lnd_svc_name = GSS_C_NO_NAME; -+ lnd->lnd_cred = GSS_C_NO_CREDENTIAL; -+ lnd->lnd_ctx = GSS_C_NO_CONTEXT; -+ lnd->lnd_rmt_ctx = (gss_buffer_desc) GSS_C_EMPTY_BUFFER; -+ lnd->lnd_seq_win = 0; -+ -+ switch (authtype) { -+ case LGSS_AUTH_KRB5: -+ lnd->lnd_mech = (gss_OID) &krb5oid; -+ lnd->lnd_req_flags = GSS_C_MUTUAL_FLAG; -+ break; -+ default: -+ logmsg(LL_ERR, "invalid auth type: %d\n", authtype); -+ lnd->lnd_rpc_err = -EACCES; -+ return -1; -+ } -+ -+ sname.value = g_service; -+ sname.length = strlen(g_service); -+ -+ maj_stat = gss_import_name(&min_stat, &sname, -+ (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, -+ &lnd->lnd_svc_name); -+ if (maj_stat != GSS_S_COMPLETE) { -+ logmsg_gss(LL_ERR, lnd->lnd_mech, maj_stat, min_stat, -+ "can't import svc name\n"); -+ lnd->lnd_gss_err = maj_stat; -+ return -1; -+ } -+ -+ return 0; -+} -+ -+void lgssc_fini_nego_data(struct lgss_nego_data *lnd) -+{ -+ OM_uint32 maj_stat, min_stat; -+ -+ if (lnd->lnd_svc_name != GSS_C_NO_NAME) { -+ maj_stat = gss_release_name(&min_stat, &lnd->lnd_svc_name); -+ if (maj_stat != GSS_S_COMPLETE) -+ logmsg_gss(LL_ERR, lnd->lnd_mech, maj_stat, min_stat, -+ "can't release service name\n"); -+ } -+ -+ if (lnd->lnd_cred != GSS_C_NO_CREDENTIAL) { -+ maj_stat = gss_release_cred(&min_stat, &lnd->lnd_cred); -+ if (maj_stat != GSS_S_COMPLETE) -+ logmsg_gss(LL_ERR, lnd->lnd_mech, maj_stat, min_stat, -+ "can't release credential\n"); -+ } -+} -+ -+static -+int error_kernel_key(key_serial_t keyid, int rpc_error, int gss_error) -+{ -+ int seqwin = 0; -+ char buf[32]; -+ char *p, *end; -+ -+ logmsg(LL_TRACE, "revoking kernel key 0x%x\n", keyid); -+ -+ p = buf; -+ end = buf + sizeof(buf); -+ -+ WRITE_BYTES(&p, end, seqwin); -+ WRITE_BYTES(&p, end, rpc_error); -+ WRITE_BYTES(&p, end, gss_error); -+ -+again: -+ if (keyctl_update(keyid, buf, p - buf)) { -+ if (errno != EAGAIN) { -+ logmsg(LL_ERR, "failed to revoke key 0x%x: %s\n", -+ keyid, strerror(errno)); -+ return -1; -+ } -+ -+ logmsg(LL_WARN, "revoke key 0x%x too soon, try again\n", keyid); -+ sleep(2); -+ goto again; -+ } -+ -+ logmsg(LL_INFO, "successfully revoke key 0x%x\n", keyid); -+ return 0; -+} -+ -+static -+int update_kernel_key(key_serial_t keyid, -+ struct lgss_nego_data *lnd, -+ gss_buffer_desc *ctx_token) -+{ -+ char *buf = NULL, *p = NULL, *end = NULL; -+ unsigned int buf_size = 0; -+ int rc; -+ -+ logmsg(LL_TRACE, "updating kernel key 0x%x\n", keyid); -+ -+ buf_size = sizeof(lnd->lnd_seq_win) + -+ sizeof(lnd->lnd_rmt_ctx.length) + lnd->lnd_rmt_ctx.length + -+ sizeof(ctx_token->length) + ctx_token->length; -+ buf = malloc(buf_size); -+ if (buf == NULL) { -+ logmsg(LL_ERR, "failed to alloc key update buf: size %d\n", -+ buf_size); -+ return 1; -+ } -+ -+ p = buf; -+ end = buf + buf_size; -+ rc = -1; -+ -+ if (WRITE_BYTES(&p, end, lnd->lnd_seq_win)) -+ goto out; -+ if (write_buffer(&p, end, &lnd->lnd_rmt_ctx)) -+ goto out; -+ if (write_buffer(&p, end, ctx_token)) -+ goto out; -+ -+again: -+ if (keyctl_update(keyid, buf, p - buf)) { -+ if (errno != EAGAIN) { -+ logmsg(LL_ERR, "failed to update key 0x%x: %s\n", -+ keyid, strerror(errno)); -+ goto out; -+ } -+ -+ logmsg(LL_WARN, "update key 0x%x too soon, try again\n", keyid); -+ sleep(2); -+ goto again; -+ } -+ -+ rc = 0; -+ logmsg(LL_INFO, "successfully updated key 0x%x\n", keyid); -+out: -+ free(buf); -+ return rc; -+} -+ -+/* -+ * note we can't assume authority in child process -+ */ -+int lgssc_kr_negotiate(key_serial_t keyid, struct keyring_upcall_param *kup) -+{ -+ struct lgss_nego_data lnd; -+ gss_buffer_desc token = GSS_C_EMPTY_BUFFER; -+ OM_uint32 min_stat; -+ int rc; -+ -+ logmsg(LL_TRACE, "child start on behalf of key 0x%x\n", keyid); -+ -+ if (kup->kup_gid != 0 && setregid(kup->kup_gid, kup->kup_gid)) { -+ logmsg(LL_ERR, "key 0x%x, failed set gids to %u: %s\n", -+ keyid, kup->kup_gid, strerror(errno)); -+ } -+ -+ if (kup->kup_uid != 0 && setreuid(kup->kup_uid, kup->kup_uid)) { -+ logmsg(LL_ERR, "key 0x%x, failed set uids to %u: %s\n", -+ keyid, kup->kup_uid, strerror(errno)); -+ } -+ -+ /* -+ * link to session keyring, allow the key to be found. -+ */ -+ if (keyctl_link(keyid, KEY_SPEC_SESSION_KEYRING)) { -+ logmsg(LL_ERR, "key 0x%x, failed to link to session " -+ "keyring: %s\n", keyid, strerror(errno)); -+ error_kernel_key(keyid, -EACCES, 0); -+ return -1; -+ } -+ -+ rc = -1; -+ if (construct_service(kup)) { -+ error_kernel_key(keyid, -EACCES, 0); -+ goto out_unlink; -+ } -+ -+ if (1/* kup->kup_uid == 0 FIXME */) { -+ gssd_setup_krb5_user_gss_ccache(kup->kup_uid, g_service); -+ } -+ -+ if (lgssc_init_nego_data(&lnd, kup, LGSS_AUTH_KRB5)) { -+ error_kernel_key(keyid, lnd.lnd_rpc_err, lnd.lnd_gss_err); -+ goto out_unlink; -+ } -+ -+ rc = lgssc_negotiation(&lnd); -+ if (rc) { -+ error_kernel_key(keyid, lnd.lnd_rpc_err, lnd.lnd_gss_err); -+ goto out; -+ } -+ -+ rc = serialize_context_for_kernel(lnd.lnd_ctx, &token, lnd.lnd_mech); -+ if (rc) { -+ error_kernel_key(keyid, rc, lnd.lnd_gss_err); -+ -+ logmsg(LL_ERR, "failed to export context\n"); -+ goto out; -+ } -+ -+ rc = update_kernel_key(keyid, &lnd, &token); -+ if (rc) -+ goto out; -+ -+ rc = 0; -+ logmsg(LL_INFO, "key update OK!\n"); -+out: -+ if (token.length != 0) -+ gss_release_buffer(&min_stat, &token); -+ -+ lgssc_fini_nego_data(&lnd); -+ -+out_unlink: -+ if (keyctl_unlink(keyid, KEY_SPEC_SESSION_KEYRING)) { -+ logmsg(LL_ERR, "failed to unlink key %d: %s\n", -+ keyid, strerror(errno)); -+ } -+ -+ return rc; -+} -+ -+/**************************************** -+ * main process * -+ ****************************************/ -+ -+int main(int argc, char *argv[]) -+{ -+ struct keyring_upcall_param uparam; -+ key_serial_t keyid; -+ key_serial_t /*tring, pring, */sring; -+ key_serial_t inst_keyring; -+ int is_root; -+ pid_t child; -+ -+ if (argc != 10 + 1) { -+ logmsg(LL_ERR, "Invalid parameter number %d\n", argc); -+ return 1; -+ } -+ -+#if 0 -+ logmsg(LL_TRACE, "OP: %s\n", argv[1]); -+ logmsg(LL_TRACE, "KeyID: %s\n", argv[2]); -+ logmsg(LL_TRACE, "KeyType: %s\n", argv[3]); -+ logmsg(LL_TRACE, "KeyDesc: %s\n", argv[4]); -+ logmsg(LL_TRACE, "COInfo: %s\n", argv[5]); -+ logmsg(LL_TRACE, "UID: %s\n", argv[6]); -+ logmsg(LL_TRACE, "GID: %s\n", argv[7]); -+ logmsg(LL_TRACE, "TKeyring: %s\n", argv[8]); -+ logmsg(LL_TRACE, "PKeyring: %s\n", argv[9]); -+ logmsg(LL_TRACE, "SKeyring: %s\n", argv[10]); -+#endif -+ logmsg(LL_INFO, "[%u/%u]: key %s, desc %s, uid %s, sring %s\n", -+ getuid(), geteuid(), -+ argv[2], argv[4], argv[6], argv[10]); -+ -+ memset(&uparam, 0, sizeof(uparam)); -+ -+ if (strcmp(argv[1], "create") != 0) { -+ logmsg(LL_ERR, "invalid OP %s\n", argv[1]); -+ return 1; -+ } -+ -+ if (sscanf(argv[2], "%d", &keyid) != 1) { -+ logmsg(LL_ERR, "can't extract KeyID\n"); -+ return 1; -+ } -+ -+ if (sscanf(argv[6], "%d", &uparam.kup_uid) != 1) { -+ logmsg(LL_ERR, "can't extract uid\n"); -+ return 1; -+ } -+ -+ if (sscanf(argv[10], "%d", &sring) != 1) { -+ logmsg(LL_ERR, "can't extract session keyring\n"); -+ return 1; -+ } -+ -+ if (sscanf(argv[5], "%d:%d:%Lx:%s", &is_root, &uparam.kup_svc, -+ &uparam.kup_nid, uparam.kup_tgt) != 4) { -+ logmsg(LL_ERR, "can't extract callout info: %s\n", argv[5]); -+ return 1; -+ } -+ logmsg(LL_INFO, "coinfo: fl %d, svc %d, nid 0x%Lx, tgt %s\n", -+ is_root, uparam.kup_svc, uparam.kup_nid, uparam.kup_tgt); -+ -+ if (is_root) -+ inst_keyring = 0; -+ else -+ inst_keyring = KEY_SPEC_SESSION_KEYRING; -+ -+ if (keyctl_instantiate(keyid, NULL, 0, inst_keyring)) { -+ logmsg(LL_ERR, "key instantiate: %s\n", strerror(errno)); -+ return 1; -+ } -+ -+ child = fork(); -+ if (child == -1) { -+ logmsg(LL_ERR, "can't create child: %s\n", strerror(errno)); -+ return 1; -+ } else if (child == 0) { -+ return lgssc_kr_negotiate(keyid, &uparam); -+ } -+ -+ return 0; -+} -diff -rNup nfs-utils-1.0.10/utils/gssd/l_idmap.c nfs-utils-1.0.10.lustre/utils/gssd/l_idmap.c ---- nfs-utils-1.0.10/utils/gssd/l_idmap.c 1969-12-31 17:00:00.000000000 -0700 -+++ nfs-utils-1.0.10.lustre/utils/gssd/l_idmap.c 2007-05-15 13:01:35.000000000 -0600 -@@ -0,0 +1,37 @@ -+#include -+#include -+#include -+ -+#include "lsupport.h" -+ -+int main(int argc, char **argv) -+{ -+ lnet_nid_t nid; -+ uid_t uid; -+ int rc; -+ -+ if (argc < 3) { -+ printf("Usage:\n" -+ "%s \n", -+ basename(argv[0])); -+ return 1; -+ } -+ -+ nid = libcfs_str2nid(argv[2]); -+ if (nid == LNET_NID_ANY) { -+ printf("parse nid %s failed\n", argv[2]); -+ return 1; -+ } -+ rc = lookup_mapping(argv[1], nid, &uid); -+ if (rc == -1) { -+ printf("lookup mapping failed\n"); -+ return 1; -+ } -+ -+ printf("principal: %s\n" -+ "nid: %#llx\n" -+ "uid: %u\n", -+ argv[1], nid, uid); -+ -+ return 0; -+} -diff -rNup nfs-utils-1.0.10/utils/gssd/lsupport.c nfs-utils-1.0.10.lustre/utils/gssd/lsupport.c ---- nfs-utils-1.0.10/utils/gssd/lsupport.c 1969-12-31 17:00:00.000000000 -0700 -+++ nfs-utils-1.0.10.lustre/utils/gssd/lsupport.c 2007-05-15 13:01:35.000000000 -0600 -@@ -0,0 +1,781 @@ -+/* -+ * Copyright (c) 2005 Cluster File Systems, Inc. -+ * -+ * This file is part of Lustre, http://www.lustre.org. -+ * -+ * Lustre is free software; you can redistribute it and/or -+ * modify it under the terms of version 2 of the GNU General Public -+ * License as published by the Free Software Foundation. -+ * -+ * Lustre is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with Lustre; if not, write to the Free Software -+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -+ */ -+ -+#ifndef _GNU_SOURCE -+#define _GNU_SOURCE -+#endif -+#include "config.h" -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#ifdef HAVE_GETHOSTBYNAME -+# include -+#endif -+ -+#include "err_util.h" -+#include "gssd.h" -+#include "lsupport.h" -+ -+/**************************************** -+ * exclusive startup * -+ ****************************************/ -+ -+static struct __sem_s { -+ char *name; -+ key_t sem_key; -+ int sem_id; -+} sems[2] = { -+ [GSSD_CLI] = { "client", 0x3a92d473, 0 }, -+ [GSSD_SVC] = { "server", 0x3b92d473, 0 }, -+}; -+ -+void gssd_init_unique(int type) -+{ -+ struct __sem_s *sem = &sems[type]; -+ struct sembuf sembuf; -+ -+ assert(type == GSSD_CLI || type == GSSD_SVC); -+ -+again: -+ sem->sem_id = semget(sem->sem_key, 1, IPC_CREAT | IPC_EXCL | 0700); -+ if (sem->sem_id == -1) { -+ if (errno != EEXIST) { -+ printerr(0, "Create sem: %s\n", strerror(errno)); -+ exit(-1); -+ } -+ -+ /* already exist. Note there's still a small window racing -+ * with other processes, due to the stupid semaphore semantics. -+ */ -+ sem->sem_id = semget(sem->sem_key, 0, 0700); -+ if (sem->sem_id == -1) { -+ if (errno == ENOENT) { -+ printerr(0, "another instance just exit, " -+ "try again\n"); -+ goto again; -+ } -+ -+ printerr(0, "Obtain sem: %s\n", strerror(errno)); -+ exit(-1); -+ } -+ } else { -+ int val = 1; -+ -+ if (semctl(sem->sem_id, 0, SETVAL, val) == -1) { -+ printerr(0, "Initialize sem: %s\n", -+ strerror(errno)); -+ exit(-1); -+ } -+ } -+ -+ sembuf.sem_num = 0; -+ sembuf.sem_op = -1; -+ sembuf.sem_flg = IPC_NOWAIT | SEM_UNDO; -+ -+ if (semop(sem->sem_id, &sembuf, 1) != 0) { -+ if (errno == EAGAIN) { -+ printerr(0, "Another instance is running, exit\n"); -+ exit(0); -+ } -+ printerr(0, "Grab sem: %s\n", strerror(errno)); -+ exit(0); -+ } -+ -+ printerr(2, "Successfully created %s global identity\n", sem->name); -+} -+ -+void gssd_exit_unique(int type) -+{ -+ assert(type == GSSD_CLI || type == GSSD_SVC); -+ -+ /* -+ * do nothing. we can't remove the sem here, otherwise the race -+ * window would be much bigger. So it's sad we have to leave the -+ * sem in the system forever. -+ */ -+} -+ -+/**************************************** -+ * client side resolvation: * -+ * lnd/netid/nid => hostname * -+ ****************************************/ -+ -+char gethostname_ex[PATH_MAX] = GSSD_DEFAULT_GETHOSTNAME_EX; -+ -+typedef int lnd_nid2hostname_t(char *lnd, uint32_t net, uint32_t addr, -+ char *buf, int buflen); -+ -+/* FIXME what about IPv6? */ -+static -+int socklnd_nid2hostname(char *lnd, uint32_t net, uint32_t addr, -+ char *buf, int buflen) -+{ -+ struct hostent *ent; -+ -+ addr = htonl(addr); -+ ent = gethostbyaddr(&addr, sizeof(addr), AF_INET); -+ if (!ent) { -+ printerr(0, "%s: can't resolve 0x%x\n", lnd, addr); -+ return -1; -+ } -+ if (strlen(ent->h_name) >= buflen) { -+ printerr(0, "%s: name too long: %s\n", lnd, ent->h_name); -+ return -1; -+ } -+ strcpy(buf, ent->h_name); -+ -+ printerr(2, "%s: net 0x%x, addr 0x%x => %s\n", -+ lnd, net, addr, buf); -+ return 0; -+} -+ -+static -+int lolnd_nid2hostname(char *lnd, uint32_t net, uint32_t addr, -+ char *buf, int buflen) -+{ -+ struct utsname uts; -+ struct hostent *ent; -+ -+ if (addr) { -+ printerr(0, "%s: addr is 0x%x, we expect 0\n", lnd, addr); -+ return -1; -+ } -+ -+ if (uname(&uts)) { -+ printerr(0, "%s: failed obtain local machine name\n", lnd); -+ return -1; -+ } -+ -+ ent = gethostbyname(uts.nodename); -+ if (!ent) { -+ printerr(0, "%s: failed obtain canonical name of %s\n", -+ lnd, uts.nodename); -+ return -1; -+ } -+ -+ if (strlen(ent->h_name) >= buflen) { -+ printerr(0, "%s: name too long: %s\n", lnd, ent->h_name); -+ return -1; -+ } -+ strcpy(buf, ent->h_name); -+ -+ printerr(2, "%s: addr 0x%x => %s\n", lnd, addr, buf); -+ return 0; -+} -+ -+static int is_space(char c) -+{ -+ return (c == ' ' || c == '\t' || c == '\n'); -+} -+ -+static -+int external_nid2hostname(char *lnd, uint32_t net, uint32_t addr, -+ char *namebuf, int namebuflen) -+{ -+ const int bufsize = PATH_MAX + 256; -+ char buf[bufsize], *head, *tail; -+ FILE *fghn; -+ -+ sprintf(buf, "%s %s 0x%x 0x%x", gethostname_ex, lnd, net, addr); -+ printerr(2, "cmd: %s\n", buf); -+ -+ fghn = popen(buf, "r"); -+ if (fghn == NULL) { -+ printerr(0, "failed to call %s\n", gethostname_ex); -+ return -1; -+ } -+ -+ head = fgets(buf, bufsize, fghn); -+ if (head == NULL) { -+ printerr(0, "can't read from %s\n", gethostname_ex); -+ return -1; -+ } -+ if (pclose(fghn) == -1) -+ printerr(1, "pclose failed, continue\n"); -+ -+ /* trim head/tail space */ -+ while (is_space(*head)) -+ head++; -+ -+ tail = head + strlen(head); -+ if (tail <= head) { -+ printerr(0, "no output from %s\n", gethostname_ex); -+ return -1; -+ } -+ while (is_space(*(tail - 1))) -+ tail--; -+ if (tail <= head) { -+ printerr(0, "output are all space from %s\n", gethostname_ex); -+ return -1; -+ } -+ *tail = '\0'; -+ -+ /* start with '@' means error msg */ -+ if (head[0] == '@') { -+ printerr(0, "error from %s: %s\n", gethostname_ex, &head[1]); -+ return -1; -+ } -+ -+ if (tail - head > namebuflen) { -+ printerr(0, "external hostname too long: %s\n", head); -+ return -1; -+ } -+ -+ printerr(2, "%s: net 0x%x, addr 0x%x => %s\n", -+ lnd, net, addr, head); -+ strcpy(namebuf, head); -+ return 0; -+} -+ -+static struct { -+ char *name; -+ lnd_nid2hostname_t *nid2name; -+} converter[LND_ENUM_END_MARKER] = { -+ {"UNUSED0", NULL}, -+ [QSWLND] = { "QSWLND", external_nid2hostname}, -+ [SOCKLND] = { "SOCKLND", socklnd_nid2hostname }, -+ [GMLND] = { "GMLND", external_nid2hostname}, -+ [PTLLND] = { "PTLLND", external_nid2hostname }, -+ [O2IBLND] = { "O2IBLND", socklnd_nid2hostname }, /* XXX */ -+ [CIBLND] = { "CIBLND", external_nid2hostname }, -+ [OPENIBLND] = { "OPENIBLND",external_nid2hostname }, -+ [IIBLND] = { "IIBLND", external_nid2hostname }, -+ [LOLND] = { "LOLND", lolnd_nid2hostname }, -+ [RALND] = { "RALND", external_nid2hostname }, -+ [VIBLND] = { "VIBLND", external_nid2hostname }, -+}; -+ -+int lnet_nid2hostname(lnet_nid_t nid, char *buf, int buflen) -+{ -+ uint32_t lnd, net, addr; -+ -+ addr = LNET_NIDADDR(nid); -+ net = LNET_NIDNET(nid); -+ lnd = LNET_NETTYP(net); -+ -+ if (lnd >= LND_ENUM_END_MARKER) { -+ printerr(0, "ERROR: Unrecognized LND %u\n", lnd); -+ return -1; -+ } -+ -+ if (converter[lnd].nid2name == NULL) { -+ printerr(0, "ERROR: %s converter not ready\n", -+ converter[lnd].name); -+ return -1; -+ } -+ -+ return converter[lnd].nid2name(converter[lnd].name, net, addr, -+ buf, buflen); -+} -+ -+ -+/**************************************** -+ * lnet support routine * -+ * (from lnet/libcfs/nidstrings.c * -+ ****************************************/ -+ -+#define LNET_NIDSTR_SIZE 32 /* size of each one (see below for usage) */ -+ -+static int libcfs_lo_str2addr(char *str, int nob, uint32_t *addr); -+static void libcfs_ip_addr2str(uint32_t addr, char *str); -+static int libcfs_ip_str2addr(char *str, int nob, uint32_t *addr); -+static void libcfs_decnum_addr2str(uint32_t addr, char *str); -+static void libcfs_hexnum_addr2str(uint32_t addr, char *str); -+static int libcfs_num_str2addr(char *str, int nob, uint32_t *addr); -+ -+struct netstrfns { -+ int nf_type; -+ char *nf_name; -+ char *nf_modname; -+ void (*nf_addr2str)(uint32_t addr, char *str); -+ int (*nf_str2addr)(char *str, int nob, uint32_t *addr); -+}; -+ -+static struct netstrfns libcfs_netstrfns[] = { -+ {/* .nf_type */ LOLND, -+ /* .nf_name */ "lo", -+ /* .nf_modname */ "klolnd", -+ /* .nf_addr2str */ libcfs_decnum_addr2str, -+ /* .nf_str2addr */ libcfs_lo_str2addr}, -+ {/* .nf_type */ SOCKLND, -+ /* .nf_name */ "tcp", -+ /* .nf_modname */ "ksocklnd", -+ /* .nf_addr2str */ libcfs_ip_addr2str, -+ /* .nf_str2addr */ libcfs_ip_str2addr}, -+ {/* .nf_type */ O2IBLND, -+ /* .nf_name */ "o2ib", -+ /* .nf_modname */ "ko2iblnd", -+ /* .nf_addr2str */ libcfs_ip_addr2str, -+ /* .nf_str2addr */ libcfs_ip_str2addr}, -+ {/* .nf_type */ CIBLND, -+ /* .nf_name */ "cib", -+ /* .nf_modname */ "kciblnd", -+ /* .nf_addr2str */ libcfs_ip_addr2str, -+ /* .nf_str2addr */ libcfs_ip_str2addr}, -+ {/* .nf_type */ OPENIBLND, -+ /* .nf_name */ "openib", -+ /* .nf_modname */ "kopeniblnd", -+ /* .nf_addr2str */ libcfs_ip_addr2str, -+ /* .nf_str2addr */ libcfs_ip_str2addr}, -+ {/* .nf_type */ IIBLND, -+ /* .nf_name */ "iib", -+ /* .nf_modname */ "kiiblnd", -+ /* .nf_addr2str */ libcfs_ip_addr2str, -+ /* .nf_str2addr */ libcfs_ip_str2addr}, -+ {/* .nf_type */ VIBLND, -+ /* .nf_name */ "vib", -+ /* .nf_modname */ "kviblnd", -+ /* .nf_addr2str */ libcfs_ip_addr2str, -+ /* .nf_str2addr */ libcfs_ip_str2addr}, -+ {/* .nf_type */ RALND, -+ /* .nf_name */ "ra", -+ /* .nf_modname */ "kralnd", -+ /* .nf_addr2str */ libcfs_ip_addr2str, -+ /* .nf_str2addr */ libcfs_ip_str2addr}, -+ {/* .nf_type */ QSWLND, -+ /* .nf_name */ "elan", -+ /* .nf_modname */ "kqswlnd", -+ /* .nf_addr2str */ libcfs_decnum_addr2str, -+ /* .nf_str2addr */ libcfs_num_str2addr}, -+ {/* .nf_type */ GMLND, -+ /* .nf_name */ "gm", -+ /* .nf_modname */ "kgmlnd", -+ /* .nf_addr2str */ libcfs_hexnum_addr2str, -+ /* .nf_str2addr */ libcfs_num_str2addr}, -+ {/* .nf_type */ PTLLND, -+ /* .nf_name */ "ptl", -+ /* .nf_modname */ "kptllnd", -+ /* .nf_addr2str */ libcfs_decnum_addr2str, -+ /* .nf_str2addr */ libcfs_num_str2addr}, -+ /* placeholder for net0 alias. It MUST BE THE LAST ENTRY */ -+ {/* .nf_type */ -1}, -+}; -+ -+const int libcfs_nnetstrfns = sizeof(libcfs_netstrfns)/sizeof(libcfs_netstrfns[0]); -+ -+static int -+libcfs_lo_str2addr(char *str, int nob, uint32_t *addr) -+{ -+ *addr = 0; -+ return 1; -+} -+ -+static void -+libcfs_ip_addr2str(uint32_t addr, char *str) -+{ -+ snprintf(str, LNET_NIDSTR_SIZE, "%u.%u.%u.%u", -+ (addr >> 24) & 0xff, (addr >> 16) & 0xff, -+ (addr >> 8) & 0xff, addr & 0xff); -+} -+ -+/* CAVEAT EMPTOR XscanfX -+ * I use "%n" at the end of a sscanf format to detect trailing junk. However -+ * sscanf may return immediately if it sees the terminating '0' in a string, so -+ * I initialise the %n variable to the expected length. If sscanf sets it; -+ * fine, if it doesn't, then the scan ended at the end of the string, which is -+ * fine too :) */ -+ -+static int -+libcfs_ip_str2addr(char *str, int nob, uint32_t *addr) -+{ -+ int a; -+ int b; -+ int c; -+ int d; -+ int n = nob; /* XscanfX */ -+ -+ /* numeric IP? */ -+ if (sscanf(str, "%u.%u.%u.%u%n", &a, &b, &c, &d, &n) >= 4 && -+ n == nob && -+ (a & ~0xff) == 0 && (b & ~0xff) == 0 && -+ (c & ~0xff) == 0 && (d & ~0xff) == 0) { -+ *addr = ((a<<24)|(b<<16)|(c<<8)|d); -+ return 1; -+ } -+ -+#ifdef HAVE_GETHOSTBYNAME -+ /* known hostname? */ -+ if (('a' <= str[0] && str[0] <= 'z') || -+ ('A' <= str[0] && str[0] <= 'Z')) { -+ char *tmp; -+ -+ tmp = malloc(nob + 1); -+ if (tmp != NULL) { -+ struct hostent *he; -+ -+ memcpy(tmp, str, nob); -+ tmp[nob] = 0; -+ -+ he = gethostbyname(tmp); -+ -+ free(tmp); -+ tmp = NULL; -+ -+ if (he != NULL) { -+ uint32_t ip = *(uint32_t *)he->h_addr; -+ -+ *addr = ntohl(ip); -+ return 1; -+ } -+ } -+ } -+#endif -+ return 0; -+} -+ -+static void -+libcfs_decnum_addr2str(uint32_t addr, char *str) -+{ -+ snprintf(str, LNET_NIDSTR_SIZE, "%u", addr); -+} -+ -+static void -+libcfs_hexnum_addr2str(uint32_t addr, char *str) -+{ -+ snprintf(str, LNET_NIDSTR_SIZE, "0x%x", addr); -+} -+ -+static int -+libcfs_num_str2addr(char *str, int nob, uint32_t *addr) -+{ -+ int n; -+ -+ n = nob; -+ if (sscanf(str, "0x%x%n", addr, &n) >= 1 && n == nob) -+ return 1; -+ -+ n = nob; -+ if (sscanf(str, "0X%x%n", addr, &n) >= 1 && n == nob) -+ return 1; -+ -+ n = nob; -+ if (sscanf(str, "%u%n", addr, &n) >= 1 && n == nob) -+ return 1; -+ -+ return 0; -+} -+ -+static struct netstrfns * -+libcfs_lnd2netstrfns(int lnd) -+{ -+ int i; -+ -+ if (lnd >= 0) -+ for (i = 0; i < libcfs_nnetstrfns; i++) -+ if (lnd == libcfs_netstrfns[i].nf_type) -+ return &libcfs_netstrfns[i]; -+ -+ return NULL; -+} -+ -+static struct netstrfns * -+libcfs_str2net_internal(char *str, uint32_t *net) -+{ -+ struct netstrfns *nf; -+ int nob; -+ int netnum; -+ int i; -+ -+ for (i = 0; i < libcfs_nnetstrfns; i++) { -+ nf = &libcfs_netstrfns[i]; -+ if (nf->nf_type >= 0 && -+ !strncmp(str, nf->nf_name, strlen(nf->nf_name))) -+ break; -+ } -+ -+ if (i == libcfs_nnetstrfns) -+ return NULL; -+ -+ nob = strlen(nf->nf_name); -+ -+ if (strlen(str) == (unsigned int)nob) { -+ netnum = 0; -+ } else { -+ if (nf->nf_type == LOLND) /* net number not allowed */ -+ return NULL; -+ -+ str += nob; -+ i = strlen(str); -+ if (sscanf(str, "%u%n", &netnum, &i) < 1 || -+ i != (int)strlen(str)) -+ return NULL; -+ } -+ -+ *net = LNET_MKNET(nf->nf_type, netnum); -+ return nf; -+} -+ -+lnet_nid_t -+libcfs_str2nid(char *str) -+{ -+ char *sep = strchr(str, '@'); -+ struct netstrfns *nf; -+ uint32_t net; -+ uint32_t addr; -+ -+ if (sep != NULL) { -+ nf = libcfs_str2net_internal(sep + 1, &net); -+ if (nf == NULL) -+ return LNET_NID_ANY; -+ } else { -+ sep = str + strlen(str); -+ net = LNET_MKNET(SOCKLND, 0); -+ nf = libcfs_lnd2netstrfns(SOCKLND); -+ if (!nf) -+ return LNET_NID_ANY; -+ } -+ -+ if (!nf->nf_str2addr(str, sep - str, &addr)) -+ return LNET_NID_ANY; -+ -+ return LNET_MKNID(net, addr); -+} -+ -+/**************************************** -+ * user mapping database handling * -+ * (very rudiment) * -+ ****************************************/ -+ -+#define MAPPING_GROW_SIZE 512 -+#define MAX_LINE_LEN 256 -+ -+struct user_map_item { -+ char *principal; /* NULL means match all, will cause multi->single mapped, FORBID */ -+ lnet_nid_t nid; -+ uid_t uid; -+}; -+ -+struct user_mapping { -+ int nitems; -+ struct user_map_item *items; -+}; -+ -+static struct user_mapping mapping = {0, NULL}; -+/* FIXME to be finished: monitor change of mapping database */ -+static int mapping_mtime = 0; -+ -+void cleanup_mapping(void) -+{ -+ if (mapping.items) { -+ for (; mapping.nitems > 0; mapping.nitems--) -+ free(mapping.items[mapping.nitems - 1].principal); -+ free(mapping.items); -+ mapping.items = NULL; -+ } -+} -+ -+static int grow_mapping(int nitems) -+{ -+ struct user_map_item *new; -+ int oldsize, newsize; -+ -+ oldsize = (mapping.nitems * sizeof(struct user_map_item) + -+ MAPPING_GROW_SIZE - 1) / MAPPING_GROW_SIZE; -+ newsize = (nitems * sizeof(struct user_map_item) + -+ MAPPING_GROW_SIZE - 1) / MAPPING_GROW_SIZE; -+ while (newsize <= oldsize) -+ return 0; -+ -+ newsize *= MAPPING_GROW_SIZE; -+ new = malloc(newsize); -+ if (!new) { -+ printerr(0, "can't alloc mapping size %d\n", newsize); -+ return -1; -+ } -+ -+ if (mapping.items) { -+ memcpy(new, mapping.items, mapping.nitems * sizeof(struct user_map_item)); -+ free(mapping.items); -+ } -+ mapping.items = new; -+ return 0; -+} -+ -+uid_t parse_uid(char *uidstr) -+{ -+ struct passwd *pw; -+ char *p = NULL; -+ long uid; -+ -+ pw = getpwnam(uidstr); -+ if (pw) -+ return pw->pw_uid; -+ -+ uid = strtol(uidstr, &p, 0); -+ if (*p == '\0') -+ return (uid_t) uid; -+ -+ return -1; -+} -+ -+static int read_mapping_db(void) -+{ -+ char princ[MAX_LINE_LEN]; -+ char nid_str[MAX_LINE_LEN]; -+ char dest[MAX_LINE_LEN]; -+ char linebuf[MAX_LINE_LEN]; -+ char *line; -+ lnet_nid_t nid; -+ uid_t dest_uid; -+ FILE *f; -+ -+ /* cleanup old mappings */ -+ cleanup_mapping(); -+ -+ f = fopen(MAPPING_DATABASE_FILE, "r"); -+ if (!f) { -+ printerr(0, "can't open mapping database: %s\n", -+ MAPPING_DATABASE_FILE); -+ return -1; -+ } -+ -+ while ((line = fgets(linebuf, MAX_LINE_LEN, f)) != NULL) { -+ char *name; -+ -+ if (strlen(line) >= MAX_LINE_LEN) { -+ printerr(0, "invalid mapping db: line too long (%d)\n", -+ strlen(line)); -+ continue; -+ } -+ -+ if (sscanf(line, "%s %s %s", princ, nid_str, dest) != 3) { -+ printerr(0, "mapping db: syntax error\n"); -+ continue; -+ } -+ -+ if (!strcmp(princ, "*")) { -+ printerr(0, "NOT permit \"*\" princ, it will cause multi->single mapped\n"); -+ continue; -+ } else { -+ name = strdup(princ); -+ if (!name) { -+ printerr(0, "fail to dup str %s\n", princ); -+ continue; -+ } -+ } -+ -+ if (!strcmp(nid_str, "*")) { -+ nid = LNET_NID_ANY; -+ } else { -+ nid = libcfs_str2nid(nid_str); -+ if (nid == LNET_NID_ANY) { -+ printerr(0, "fail to parse nid %s\n", nid_str); -+ free(name); -+ continue; -+ } -+ } -+ -+ dest_uid = parse_uid(dest); -+ if (dest_uid == -1) { -+ printerr(0, "no valid user: %s\n", dest); -+ free(name); -+ continue; -+ } -+ -+ if (grow_mapping(mapping.nitems + 1)) { -+ printerr(0, "fail to grow mapping to %d\n", -+ mapping.nitems + 1); -+ free(name); -+ fclose(f); -+ return -1; -+ } -+ -+ mapping.items[mapping.nitems].principal = name; -+ mapping.items[mapping.nitems].nid = nid; -+ mapping.items[mapping.nitems].uid = dest_uid; -+ mapping.nitems++; -+ printerr(1, "add mapping: %s(%s/0x%llx) ==> %d\n", -+ name, nid_str, nid, dest_uid); -+ } -+ -+ fclose(f); -+ return 0; -+} -+ -+static inline int mapping_changed(void) -+{ -+ struct stat st; -+ -+ if (stat(MAPPING_DATABASE_FILE, &st) == -1) { -+ /* stat failed, treat it like doesn't exist or be removed */ -+ if (mapping_mtime == 0) { -+ return 0; -+ } else { -+ printerr(0, "Warning: stat %s failed: %s\n", -+ MAPPING_DATABASE_FILE, strerror(errno)); -+ -+ mapping_mtime = 0; -+ return 1; -+ } -+ } -+ -+ if (st.st_mtime != mapping_mtime) { -+ mapping_mtime = st.st_mtime; -+ return 1; -+ } -+ -+ return 0; -+} -+ -+int lookup_mapping(char *princ, lnet_nid_t nid, uid_t *uid) -+{ -+ int n; -+ -+ *uid = -1; -+ -+ /* FIXME race condition here */ -+ if (mapping_changed()) { -+ if (read_mapping_db()) -+ printerr(0, "all remote users will be denied\n"); -+ } -+ -+ for (n = 0; n < mapping.nitems; n++) { -+ struct user_map_item *entry = &mapping.items[n]; -+ -+ if (entry->nid != LNET_NID_ANY && entry->nid != nid) -+ continue; -+ if (!strcasecmp(entry->principal, princ)) { -+ printerr(1, "found mapping: %s ==> %d\n", -+ princ, entry->uid); -+ *uid = entry->uid; -+ return 0; -+ } -+ } -+ -+ printerr(2, "no mapping for %s/%#Lx\n", princ, nid); -+ return -1; -+} -diff -rNup nfs-utils-1.0.10/utils/gssd/lsupport.h nfs-utils-1.0.10.lustre/utils/gssd/lsupport.h ---- nfs-utils-1.0.10/utils/gssd/lsupport.h 1969-12-31 17:00:00.000000000 -0700 -+++ nfs-utils-1.0.10.lustre/utils/gssd/lsupport.h 2007-05-15 13:01:35.000000000 -0600 -@@ -0,0 +1,85 @@ -+#ifndef __LIBCFS_H__ -+#define __LIBCFS_H__ -+ -+#include -+#include -+ -+#define GSSD_CLI (0) -+#define GSSD_SVC (1) -+ -+void gssd_init_unique(int type); -+void gssd_exit_unique(int type); -+ -+/* -+ * copied from lustre source -+ */ -+ -+#define LUSTRE_GSS_SVC_MDS 0 -+#define LUSTRE_GSS_SVC_OSS 1 -+ -+struct lgssd_upcall_data { -+ uint32_t seq; -+ uint32_t uid; -+ uint32_t gid; -+ uint32_t svc; -+ uint64_t nid; -+ char obd[64]; -+}; -+ -+#define GSSD_INTERFACE_VERSION (1) -+ -+struct lgssd_ioctl_param { -+ int version; /* in */ -+ char *uuid; /* in */ -+ int lustre_svc; /* in */ -+ uid_t uid; /* in */ -+ gid_t gid; /* in */ -+ long send_token_size;/* in */ -+ char *send_token; /* in */ -+ long reply_buf_size; /* in */ -+ char *reply_buf; /* in */ -+ long status; /* out */ -+ long reply_length; /* out */ -+}; -+ -+#define GSSD_DEFAULT_GETHOSTNAME_EX "/etc/lustre/nid2hostname" -+#define MAPPING_DATABASE_FILE "/etc/lustre/idmap.conf" -+ -+typedef uint64_t lnet_nid_t; -+typedef uint32_t lnet_netid_t; -+ -+#define LNET_NID_ANY ((lnet_nid_t) -1) -+#define LNET_PID_ANY ((lnet_pid_t) -1) -+ -+enum { -+ /* Only add to these values (i.e. don't ever change or redefine them): -+ * network addresses depend on them... */ -+ QSWLND = 1, -+ SOCKLND = 2, -+ GMLND = 3, -+ PTLLND = 4, -+ O2IBLND = 5, -+ CIBLND = 6, -+ OPENIBLND = 7, -+ IIBLND = 8, -+ LOLND = 9, -+ RALND = 10, -+ VIBLND = 11, -+ LND_ENUM_END_MARKER -+}; -+ -+int lnet_nid2hostname(lnet_nid_t nid, char *buf, int buflen); -+void cleanup_mapping(void); -+int lookup_mapping(char *princ, uint64_t nid, uid_t *uid); -+lnet_nid_t libcfs_str2nid(char *str); -+ -+/* how an LNET NID encodes net:address */ -+#define LNET_NIDADDR(nid) ((uint32_t)((nid) & 0xffffffff)) -+#define LNET_NIDNET(nid) ((uint32_t)(((nid) >> 32)) & 0xffffffff) -+#define LNET_MKNID(net,addr) ((((uint64_t)(net))<<32)|((uint64_t)(addr))) -+/* how net encodes type:number */ -+#define LNET_NETNUM(net) ((net) & 0xffff) -+#define LNET_NETTYP(net) (((net) >> 16) & 0xffff) -+#define LNET_MKNET(typ,num) ((((uint32_t)(typ))<<16)|((uint32_t)(num))) -+ -+#endif /* __LIBCFS_H__ */ -diff -rNup nfs-utils-1.0.10/utils/gssd/Makefile.am nfs-utils-1.0.10.lustre/utils/gssd/Makefile.am ---- nfs-utils-1.0.10/utils/gssd/Makefile.am 2007-05-15 13:02:26.000000000 -0600 -+++ nfs-utils-1.0.10.lustre/utils/gssd/Makefile.am 2007-05-15 13:00:53.000000000 -0600 -@@ -1,17 +1,11 @@ - ## Process this file with automake to produce Makefile.in - --man8_MANS = gssd.man svcgssd.man -- --RPCPREFIX = rpc. -+RPCPREFIX = - KPREFIX = @kprefix@ --sbin_PREFIXED = gssd svcgssd --sbin_PROGRAMS = $(sbin_PREFIXED) gss_clnt_send_err -+sbin_PREFIXED = lgssd lsvcgssd -+sbin_PROGRAMS = $(sbin_PREFIXED) - sbin_SCRIPTS = gss_destroy_creds - --EXTRA_DIST = \ -- gss_destroy_creds \ -- $(man8_MANS) -- - COMMON_SRCS = \ - context.c \ - context_mit.c \ -@@ -21,13 +15,15 @@ COMMON_SRCS = \ - gss_util.c \ - gss_oids.c \ - err_util.c \ -+ lsupport.c \ - \ - context.h \ - err_util.h \ - gss_oids.h \ -- gss_util.h -+ gss_util.h \ -+ lsupport.h - --gssd_SOURCES = \ -+lgssd_SOURCES = \ - $(COMMON_SRCS) \ - gssd.c \ - gssd_main_loop.c \ -@@ -38,13 +34,12 @@ gssd_SOURCES = \ - krb5_util.h \ - write_bytes.h - --gssd_LDADD = $(RPCSECGSS_LIBS) $(KRBLIBS) --gssd_LDFLAGS = $(KRBLDFLAGS) -+lgssd_LDADD = $(GSSAPI_LIBS) $(KRBLIBS) -+lgssd_LDFLAGS = $(KRBLDFLAGS) - --gssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \ -- $(RPCSECGSS_CFLAGS) $(KRBCFLAGS) -+lgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(GSSAPI_CFLAGS) $(KRBCFLAGS) - --svcgssd_SOURCES = \ -+lsvcgssd_SOURCES = \ - $(COMMON_SRCS) \ - cacheio.c \ - svcgssd.c \ -@@ -55,20 +50,11 @@ svcgssd_SOURCES = \ - cacheio.h \ - svcgssd.h - --svcgssd_LDADD = \ -- ../../support/nfs/libnfs.a \ -- $(RPCSECGSS_LIBS) -lnfsidmap \ -- $(KRBLIBS) -- --svcgssd_LDFLAGS = $(KRBLDFLAGS) -- --svcgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \ -- $(RPCSECGSS_CFLAGS) $(KRBCFLAGS) -+lsvcgssd_LDADD = $(GSSAPI_LIBS) $(KRBLIBS) - --gss_clnt_send_err_SOURCES = gss_clnt_send_err.c -+lsvcgssd_LDFLAGS = $(KRBLDFLAGS) - --gss_clnt_send_err_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \ -- $(RPCSECGSS_CFLAGS) $(KRBCFLAGS) -+lsvcgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(GSSAPI_CFLAGS) $(KRBCFLAGS) - - MAINTAINERCLEANFILES = Makefile.in - -@@ -92,23 +78,3 @@ uninstall-hook: - done) - - --# XXX This makes some assumptions about what automake does. --# XXX But there is no install-man-hook or install-man-local. --install-man: install-man8 install-man-links --uninstall-man: uninstall-man8 uninstall-man-links -- --install-man-links: -- (cd $(DESTDIR)$(man8dir) && \ -- for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \ -- inst=`echo $$m | sed -e 's/man$$/8/'`; \ -- rm -f $(RPCPREFIX)$$inst ; \ -- $(LN_S) $$inst $(RPCPREFIX)$$inst ; \ -- done) -- --uninstall-man-links: -- (cd $(DESTDIR)$(man8dir) && \ -- for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \ -- inst=`echo $$m | sed -e 's/man$$/8/'`; \ -- rm -f $(RPCPREFIX)$$inst ; \ -- done) -- -diff -rNup nfs-utils-1.0.10/utils/gssd/svcgssd.c nfs-utils-1.0.10.lustre/utils/gssd/svcgssd.c ---- nfs-utils-1.0.10/utils/gssd/svcgssd.c 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10.lustre/utils/gssd/svcgssd.c 2007-05-15 13:01:35.000000000 -0600 -@@ -43,7 +43,6 @@ - #include - #include - #include --#include - #include - #include - -@@ -54,11 +53,33 @@ - #include - #include - #include --#include "nfslib.h" -+#include - #include "svcgssd.h" - #include "gss_util.h" - #include "err_util.h" -+#include "lsupport.h" - -+void -+closeall(int min) -+{ -+ DIR *dir = opendir("/proc/self/fd"); -+ if (dir != NULL) { -+ int dfd = dirfd(dir); -+ struct dirent *d; -+ -+ while ((d = readdir(dir)) != NULL) { -+ char *endp; -+ long n = strtol(d->d_name, &endp, 10); -+ if (*endp != '\0' && n >= min && n != dfd) -+ (void) close(n); -+ } -+ closedir(dir); -+ } else { -+ int fd = sysconf(_SC_OPEN_MAX); -+ while (--fd >= min) -+ (void) close(fd); -+ } -+} - /* - * mydaemon creates a pipe between the partent and child - * process. The parent process will wait until the -@@ -139,6 +160,7 @@ void - sig_die(int signal) - { - /* destroy krb5 machine creds */ -+ cleanup_mapping(); - printerr(1, "exiting on signal %d\n", signal); - exit(1); - } -@@ -165,8 +187,8 @@ main(int argc, char *argv[]) - int get_creds = 1; - int fg = 0; - int verbosity = 0; -- int rpc_verbosity = 0; - int opt; -+ int must_srv_mds = 0, must_srv_oss = 0; - extern char *optarg; - char *progname; - -@@ -181,8 +203,13 @@ main(int argc, char *argv[]) - case 'v': - verbosity++; - break; -- case 'r': -- rpc_verbosity++; -+ case 'm': -+ get_creds = 1; -+ must_srv_mds = 1; -+ break; -+ case 'o': -+ get_creds = 1; -+ must_srv_oss = 1; - break; - default: - usage(argv[0]); -@@ -196,27 +223,18 @@ main(int argc, char *argv[]) - progname = argv[0]; - - initerr(progname, verbosity, fg); --#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL -- authgss_set_debug_level(rpc_verbosity); --#else -- if (rpc_verbosity > 0) -- printerr(0, "Warning: rpcsec_gss library does not " -- "support setting debug level\n"); --#endif - - if (gssd_check_mechs() != 0) { - printerr(0, "ERROR: Problem with gssapi library\n"); - exit(1); - } - -- if (!fg) -- mydaemon(0, 0); -- -- signal(SIGINT, sig_die); -- signal(SIGTERM, sig_die); -- signal(SIGHUP, sig_hup); -+ if (gssd_get_local_realm()) { -+ printerr(0, "ERROR: Can't get Local Kerberos realm\n"); -+ exit(1); -+ } - -- if (get_creds && !gssd_acquire_cred(GSSD_SERVICE_NAME)) { -+ if (get_creds && gssd_prepare_creds(must_srv_mds, must_srv_oss)) { - printerr(0, "unable to obtain root (machine) credentials\n"); - printerr(0, "do you have a keytab entry for " - "nfs/@ in " -@@ -225,9 +243,23 @@ main(int argc, char *argv[]) - } - - if (!fg) -+ mydaemon(0, 0); -+ -+ /* -+ * XXX: There is risk of memory leak for missing call -+ * cleanup_mapping() for SIGKILL and SIGSTOP. -+ */ -+ signal(SIGINT, sig_die); -+ signal(SIGTERM, sig_die); -+ signal(SIGHUP, sig_hup); -+ -+ if (!fg) - release_parent(); - -- gssd_run(); -+ gssd_init_unique(GSSD_SVC); -+ -+ svcgssd_run(); -+ cleanup_mapping(); - printerr(0, "gssd_run returned!\n"); - abort(); - } -diff -rNup nfs-utils-1.0.10/utils/gssd/svcgssd.h nfs-utils-1.0.10.lustre/utils/gssd/svcgssd.h ---- nfs-utils-1.0.10/utils/gssd/svcgssd.h 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10.lustre/utils/gssd/svcgssd.h 2007-05-15 13:01:35.000000000 -0600 -@@ -35,9 +35,20 @@ - #include - #include - --void handle_nullreq(FILE *f); --void gssd_run(void); -+int handle_nullreq(FILE *f); -+void svcgssd_run(void); -+int gssd_prepare_creds(int must_srv_mds, int must_srv_oss); -+gss_cred_id_t gssd_select_svc_cred(int lustre_svc); - --#define GSSD_SERVICE_NAME "nfs" -+extern char *mds_local_realm; -+extern char *oss_local_realm; -+ -+#define GSSD_SERVICE_NAME "lustre" -+ -+/* XXX */ -+#define GSSD_SERVICE_MDS "lustre_mds" -+#define GSSD_SERVICE_OSS "lustre_oss" -+#define LUSTRE_ROOT_NAME "lustre_root" -+#define LUSTRE_ROOT_NAMELEN 11 - - #endif /* _RPC_SVCGSSD_H_ */ -diff -rNup nfs-utils-1.0.10/utils/gssd/svcgssd_main_loop.c nfs-utils-1.0.10.lustre/utils/gssd/svcgssd_main_loop.c ---- nfs-utils-1.0.10/utils/gssd/svcgssd_main_loop.c 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10.lustre/utils/gssd/svcgssd_main_loop.c 2007-05-15 13:01:35.000000000 -0600 -@@ -46,46 +46,66 @@ - #include "svcgssd.h" - #include "err_util.h" - -+/* -+ * nfs4 in-kernel cache implementation make upcall failed directly -+ * if there's no listener detected. so here we should keep the init -+ * channel file open as possible as we can. -+ * -+ * unfortunately the proc doesn't support dir change notification. -+ * and when an entry get unlinked, we only got POLLIN event once, -+ * it's the only oppotunity we can close the file and startover. -+ */ - void --gssd_run() -+svcgssd_run() - { - int ret; -- FILE *f; -+ FILE *f = NULL; - struct pollfd pollfd; -+ struct timespec halfsec = { .tv_sec = 0, .tv_nsec = 500000000 }; - --#define NULLRPC_FILE "/proc/net/rpc/auth.rpcsec.init/channel" -+#define NULLRPC_FILE "/proc/net/rpc/auth.ptlrpcs.init/channel" - -- f = fopen(NULLRPC_FILE, "rw"); -- -- if (!f) { -- printerr(0, "failed to open %s: %s\n", -- NULLRPC_FILE, strerror(errno)); -- exit(1); -- } -- pollfd.fd = fileno(f); -- pollfd.events = POLLIN; - while (1) { - int save_err; - -+ while (f == NULL) { -+ f = fopen(NULLRPC_FILE, "rw"); -+ if (f == NULL) { -+ printerr(4, "failed to open %s: %s\n", -+ NULLRPC_FILE, strerror(errno)); -+ nanosleep(&halfsec, NULL); -+ } else { -+ printerr(1, "successfully open %s\n", -+ NULLRPC_FILE); -+ break; -+ } -+ } -+ pollfd.fd = fileno(f); -+ pollfd.events = POLLIN; -+ - pollfd.revents = 0; -- printerr(1, "entering poll\n"); -- ret = poll(&pollfd, 1, -1); -+ ret = poll(&pollfd, 1, 1000); - save_err = errno; -- printerr(1, "leaving poll\n"); -+ - if (ret < 0) { -- if (save_err != EINTR) -- printerr(0, "error return from poll: %s\n", -- strerror(save_err)); -+ printerr(0, "error return from poll: %s\n", -+ strerror(save_err)); -+ fclose(f); -+ f = NULL; - } else if (ret == 0) { -- /* timeout; shouldn't happen. */ -+ printerr(3, "poll timeout\n"); - } else { - if (ret != 1) { - printerr(0, "bug: unexpected poll return %d\n", - ret); - exit(1); - } -- if (pollfd.revents & POLLIN) -- handle_nullreq(f); -+ if (pollfd.revents & POLLIN) { -+ if (handle_nullreq(f) < 0) { -+ fclose(f); -+ f = NULL; -+ } -+ } - } - } - } -diff -rNup nfs-utils-1.0.10/utils/gssd/svcgssd_proc.c nfs-utils-1.0.10.lustre/utils/gssd/svcgssd_proc.c ---- nfs-utils-1.0.10/utils/gssd/svcgssd_proc.c 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10.lustre/utils/gssd/svcgssd_proc.c 2007-05-15 13:01:35.000000000 -0600 -@@ -35,7 +35,6 @@ - - #include - #include --#include - - #include - #include -@@ -44,25 +43,28 @@ - #include - #include - #include --#include -+#include - - #include "svcgssd.h" - #include "gss_util.h" - #include "err_util.h" - #include "context.h" - #include "cacheio.h" -+#include "lsupport.h" - - extern char * mech2file(gss_OID mech); --#define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.rpcsec.context/channel" --#define SVCGSSD_INIT_CHANNEL "/proc/net/rpc/auth.rpcsec.init/channel" -+#define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.ptlrpcs.context/channel" -+#define SVCGSSD_INIT_CHANNEL "/proc/net/rpc/auth.ptlrpcs.init/channel" - - #define TOKEN_BUF_SIZE 8192 - - struct svc_cred { -- uid_t cr_uid; -- gid_t cr_gid; -- int cr_ngroups; -- gid_t cr_groups[NGROUPS]; -+ uint32_t cr_remote; -+ uint32_t cr_usr_root; -+ uint32_t cr_usr_mds; -+ uid_t cr_uid; -+ uid_t cr_mapped_uid; -+ uid_t cr_gid; - }; - - static int -@@ -70,10 +72,9 @@ do_svc_downcall(gss_buffer_desc *out_han - gss_OID mech, gss_buffer_desc *context_token) - { - FILE *f; -- int i; - char *fname = NULL; - -- printerr(1, "doing downcall\n"); -+ printerr(2, "doing downcall\n"); - if ((fname = mech2file(mech)) == NULL) - goto out_err; - f = fopen(SVCGSSD_CONTEXT_CHANNEL, "w"); -@@ -86,11 +87,12 @@ do_svc_downcall(gss_buffer_desc *out_han - qword_printhex(f, out_handle->value, out_handle->length); - /* XXX are types OK for the rest of this? */ - qword_printint(f, 0x7fffffff); /*XXX need a better timeout */ -+ 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_mapped_uid); - qword_printint(f, cred->cr_uid); - qword_printint(f, cred->cr_gid); -- qword_printint(f, cred->cr_ngroups); -- for (i=0; i < cred->cr_ngroups; i++) -- qword_printint(f, cred->cr_groups[i]); - qword_print(f, fname); - qword_printhex(f, context_token->value, context_token->length); - qword_eol(f); -@@ -119,7 +121,7 @@ send_response(FILE *f, gss_buffer_desc * - /* XXXARG: */ - int g; - -- printerr(1, "sending null reply\n"); -+ printerr(2, "sending null reply\n"); - - qword_addhex(&bp, &blen, in_handle->value, in_handle->length); - qword_addhex(&bp, &blen, in_token->value, in_token->length); -@@ -159,6 +161,7 @@ send_response(FILE *f, gss_buffer_desc * - #define rpcsec_gsserr_credproblem 13 - #define rpcsec_gsserr_ctxproblem 14 - -+#if 0 - static void - add_supplementary_groups(char *secname, char *name, struct svc_cred *cred) - { -@@ -182,7 +185,9 @@ add_supplementary_groups(char *secname, - } - } - } -+#endif - -+#if 0 - static int - get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred) - { -@@ -248,7 +253,9 @@ out_free: - out: - return res; - } -+#endif - -+#if 0 - void - print_hexl(int pri, unsigned char *cp, int length) - { -@@ -285,12 +292,121 @@ print_hexl(int pri, unsigned char *cp, i - printerr(pri,"\n"); - } - } -+#endif - --void -+static int -+get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred, -+ lnet_nid_t nid, uint32_t lustre_svc) -+{ -+ u_int32_t maj_stat, min_stat; -+ gss_buffer_desc name; -+ char *sname, *realm, *slash; -+ int res = -1; -+ 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_uid = cred->cr_mapped_uid = cred->cr_gid = -1; -+ -+ maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type); -+ if (maj_stat != GSS_S_COMPLETE) { -+ pgsserr("get_ids: gss_display_name", -+ maj_stat, min_stat, mech); -+ return -1; -+ } -+ if (name.length >= 0xffff || /* be certain name.length+1 doesn't overflow */ -+ !(sname = calloc(name.length + 1, 1))) { -+ printerr(0, "WARNING: get_ids: error allocating %d bytes " -+ "for sname\n", name.length + 1); -+ gss_release_buffer(&min_stat, &name); -+ return -1; -+ } -+ memcpy(sname, name.value, name.length); -+ printerr(1, "authenticated %s from %016llx\n", sname, nid); -+ gss_release_buffer(&min_stat, &name); -+ -+ if (lustre_svc == LUSTRE_GSS_SVC_MDS) -+ lookup_mapping(sname, nid, &cred->cr_mapped_uid); -+ else -+ cred->cr_mapped_uid = -1; -+ -+ realm = strchr(sname, '@'); -+ if (!realm) { -+ printerr(0, "WARNNING: principal %s contains no realm name\n", -+ sname); -+ cred->cr_remote = (mds_local_realm != NULL); -+ } else { -+ *realm++ = '\0'; -+ if (!mds_local_realm) -+ cred->cr_remote = 1; -+ else -+ cred->cr_remote = -+ (strcasecmp(mds_local_realm, realm) != 0); -+ } -+ -+ if (cred->cr_remote) { -+ if (cred->cr_mapped_uid != -1) -+ res = 0; -+ else if (lustre_svc == LUSTRE_GSS_SVC_OSS && -+ strcmp(sname, "lustre_root") == 0) -+ res = 0; -+ else -+ printerr(0, "principal %s is remote without mapping\n", -+ sname); -+ goto out_free; -+ } -+ -+ slash = strchr(sname, '/'); -+ if (slash) -+ *slash = '\0'; -+ -+ if (!(pw = getpwnam(sname))) { -+ /* If client use machine credential, we map it to root, which -+ * will subject to further mapping by root-squash in kernel. -+ * -+ * MDS service keytab is treated as special user, also mapped -+ * to root. OSS service keytab can't be used as a user. -+ */ -+ if (!strcmp(sname, LUSTRE_ROOT_NAME)) { -+ printerr(2, "lustre_root principal, resolve to uid 0\n"); -+ cred->cr_uid = 0; -+ cred->cr_usr_root = 1; -+ } else if (!strcmp(sname, GSSD_SERVICE_MDS)) { -+ printerr(2, "mds service principal, resolve to uid 0\n"); -+ cred->cr_uid = 0; -+ cred->cr_usr_mds = 1; -+ } else { -+ cred->cr_uid = -1; -+ if (cred->cr_mapped_uid == -1) { -+ printerr(0, "invalid user %s\n", sname); -+ goto out_free; -+ } -+ printerr(2, "user %s mapped to %u\n", -+ sname, cred->cr_mapped_uid); -+ } -+ } else { -+ cred->cr_uid = pw->pw_uid; -+ printerr(2, "%s resolve to uid %u\n", sname, cred->cr_uid); -+ } -+ -+ res = 0; -+out_free: -+ free(sname); -+ return res; -+} -+ -+typedef struct gss_union_ctx_id_t { -+ gss_OID mech_type; -+ gss_ctx_id_t internal_ctx_id; -+} gss_union_ctx_id_desc, *gss_union_ctx_id_t; -+ -+/* -+ * return -1 only if we detect error during reading from upcall channel, -+ * all other cases return 0. -+ */ -+int - handle_nullreq(FILE *f) { -- /* XXX initialize to a random integer to reduce chances of unnecessary -- * invalidation of existing ctx's on restarting svcgssd. */ -- static u_int32_t handle_seq = 0; -+ uint64_t handle_seq; - char in_tok_buf[TOKEN_BUF_SIZE]; - char in_handle_buf[15]; - char out_handle_buf[15]; -@@ -302,10 +418,13 @@ handle_nullreq(FILE *f) { - ignore_out_tok = {.value = NULL}, - /* XXX isn't there a define for this?: */ - null_token = {.value = NULL}; -+ uint32_t lustre_svc; -+ lnet_nid_t nid; - u_int32_t ret_flags; - gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; - gss_name_t client_name; - gss_OID mech = GSS_C_NO_OID; -+ gss_cred_id_t svc_cred; - u_int32_t maj_stat = GSS_S_FAILURE, min_stat = 0; - u_int32_t ignore_min_stat; - struct svc_cred cred; -@@ -313,25 +432,31 @@ handle_nullreq(FILE *f) { - static int lbuflen = 0; - static char *cp; - -- printerr(1, "handling null request\n"); -+ printerr(2, "handling null request\n"); - - if (readline(fileno(f), &lbuf, &lbuflen) != 1) { - printerr(0, "WARNING: handle_nullreq: " - "failed reading request\n"); -- return; -+ return -1; - } - - cp = lbuf; - -+ qword_get(&cp, (char *) &lustre_svc, sizeof(lustre_svc)); -+ qword_get(&cp, (char *) &nid, sizeof(nid)); -+ qword_get(&cp, (char *) &handle_seq, sizeof(handle_seq)); -+ printerr(1, "handling req: svc %u, nid %016llx, idx %llx\n", -+ lustre_svc, nid, handle_seq); -+ - in_handle.length = (size_t) qword_get(&cp, in_handle.value, - sizeof(in_handle_buf)); -- printerr(2, "in_handle: \n"); -- print_hexl(2, in_handle.value, in_handle.length); -+ printerr(3, "in_handle: \n"); -+ print_hexl(3, in_handle.value, in_handle.length); - - in_tok.length = (size_t) qword_get(&cp, in_tok.value, - sizeof(in_tok_buf)); -- printerr(2, "in_tok: \n"); -- print_hexl(2, in_tok.value, in_tok.length); -+ printerr(3, "in_tok: \n"); -+ print_hexl(3, in_tok.value, in_tok.length); - - if (in_tok.length < 0) { - printerr(0, "WARNING: handle_nullreq: " -@@ -351,7 +476,13 @@ handle_nullreq(FILE *f) { - memcpy(&ctx, in_handle.value, in_handle.length); - } - -- maj_stat = gss_accept_sec_context(&min_stat, &ctx, gssd_creds, -+ svc_cred = gssd_select_svc_cred(lustre_svc); -+ if (!svc_cred) { -+ printerr(0, "no service credential for svc %u\n", lustre_svc); -+ goto out_err; -+ } -+ -+ maj_stat = gss_accept_sec_context(&min_stat, &ctx, svc_cred, - &in_tok, GSS_C_NO_CHANNEL_BINDINGS, &client_name, - &mech, &out_tok, &ret_flags, NULL, NULL); - -@@ -369,7 +500,8 @@ handle_nullreq(FILE *f) { - maj_stat, min_stat, mech); - goto out_err; - } -- if (get_ids(client_name, mech, &cred)) { -+ -+ if (get_ids(client_name, mech, &cred, nid, lustre_svc)) { - /* get_ids() prints error msg */ - maj_stat = GSS_S_BAD_NAME; /* XXX ? */ - gss_release_name(&ignore_min_stat, &client_name); -@@ -377,10 +509,8 @@ handle_nullreq(FILE *f) { - } - gss_release_name(&ignore_min_stat, &client_name); - -- - /* Context complete. Pass handle_seq in out_handle to use - * for context lookup in the kernel. */ -- handle_seq++; - out_handle.length = sizeof(handle_seq); - memcpy(out_handle.value, &handle_seq, sizeof(handle_seq)); - -@@ -404,8 +534,7 @@ out: - free(ctx_token.value); - if (out_tok.value != NULL) - gss_release_buffer(&ignore_min_stat, &out_tok); -- printerr(1, "finished handling null request\n"); -- return; -+ return 0; - - out_err: - if (ctx != GSS_C_NO_CONTEXT) -diff -rNup nfs-utils-1.0.10/utils/Makefile.am nfs-utils-1.0.10.lustre/utils/Makefile.am ---- nfs-utils-1.0.10/utils/Makefile.am 2006-08-07 00:40:50.000000000 -0600 -+++ nfs-utils-1.0.10.lustre/utils/Makefile.am 2007-05-15 13:00:53.000000000 -0600 -@@ -2,31 +2,6 @@ - - OPTDIRS = - --if CONFIG_RQUOTAD --OPTDIRS += rquotad --endif -- --if CONFIG_NFSV4 --OPTDIRS += idmapd --endif -- --if CONFIG_GSS --OPTDIRS += gssd --endif -- --if CONFIG_MOUNT --OPTDIRS += mount --endif -- --SUBDIRS = \ -- exportfs \ -- lockd \ -- mountd \ -- nfsd \ -- nfsstat \ -- nhfsstone \ -- showmount \ -- statd \ -- $(OPTDIRS) -+SUBDIRS = gssd - - MAINTAINERCLEANFILES = Makefile.in diff --git a/lustre/utils/gss/nfs-utils-1.0.11-lustre.diff b/lustre/utils/gss/nfs-utils-1.0.11-lustre.diff deleted file mode 100644 index cf3a40c..0000000 --- a/lustre/utils/gss/nfs-utils-1.0.11-lustre.diff +++ /dev/null @@ -1,3237 +0,0 @@ -diff -Nrup nfs-utils-1.0.11.lustre/configure.in nfs-utils-1.0.11/configure.in ---- nfs-utils-1.0.11.lustre/configure.in 2007-02-21 21:50:03.000000000 -0700 -+++ nfs-utils-1.0.11/configure.in 2008-01-02 18:10:29.000000000 -0700 -@@ -18,61 +18,14 @@ AC_ARG_WITH(release, - RELEASE=$withval, - RELEASE=1) - AC_SUBST(RELEASE) --AC_ARG_WITH(statedir, -- [ --with-statedir=/foo use state dir /foo [/var/lib/nfs]], -- statedir=$withval, -- statedir=/var/lib/nfs) -- AC_SUBST(statedir) --AC_ARG_WITH(statduser, -- [AC_HELP_STRING([--with-statduser=rpcuser], -- [statd to run under @<:@rpcuser or nobody@:>@] -- )], -- statduser=$withval, -- if test "x$cross_compiling" = "xno"; then -- if grep -s '^rpcuser:' /etc/passwd > /dev/null; then -- statduser=rpcuser -- else -- statduser=nobody -- fi -- else -- statduser=nobody -- fi) -- AC_SUBST(statduser) --AC_ARG_ENABLE(nfsv3, -- [AC_HELP_STRING([--enable-nfsv3], -- [enable support for NFSv3 @<:@default=yes@:>@])], -- enable_nfsv3=$enableval, -- enable_nfsv3=yes) -- if test "$enable_nfsv3" = yes; then -- AC_DEFINE(NFS3_SUPPORTED, 1, [Define this if you want NFSv3 support compiled in]) -- else -- enable_nfsv3= -- fi -- AC_SUBST(enable_nfsv3) --AC_ARG_ENABLE(nfsv4, -- [AC_HELP_STRING([--enable-nfsv4], -- [enable support for NFSv4 @<:@default=yes@:>@])], -- enable_nfsv4=$enableval, -- enable_nfsv4=yes) -- if test "$enable_nfsv4" = yes; then -- AC_DEFINE(NFS4_SUPPORTED, 1, [Define this if you want NFSv4 support compiled in]) -- IDMAPD=idmapd -- else -- enable_nfsv4= -- IDMAPD= -- fi -- AC_SUBST(IDMAPD) -- AC_SUBST(enable_nfsv4) -- AM_CONDITIONAL(CONFIG_NFSV4, [test "$enable_nfsv4" = "yes"]) - AC_ARG_ENABLE(gss, - [AC_HELP_STRING([--enable-gss], - [enable support for rpcsec_gss @<:@default=yes@:>@])], - enable_gss=$enableval, - enable_gss=yes) - if test "$enable_gss" = yes; then -- AC_DEFINE(GSS_SUPPORTED, 1, [Define this if you want rpcsec_gss support compiled in]) -- GSSD=gssd -- SVCGSSD=svcgssd -+ GSSD=lgssd -+ SVCGSSD=lsvcgssd - else - enable_gss= - GSSD= -@@ -82,38 +35,6 @@ AC_ARG_ENABLE(gss, - AC_SUBST(SVCGSSD) - AC_SUBST(enable_gss) - AM_CONDITIONAL(CONFIG_GSS, [test "$enable_gss" = "yes"]) --AC_ARG_ENABLE(kprefix, -- [AC_HELP_STRING([--enable-kprefix], [install progs as rpc.knfsd etc])], -- test "$enableval" = "yes" && kprefix=k, -- kprefix=) -- AC_SUBST(kprefix) --AC_ARG_ENABLE(secure-statd, -- [AC_HELP_STRING([--enable-secure-statd], -- [Only lockd can use statd (security)])], -- test "$enableval" = "yes" && secure_statd=yes, -- secure_statd=no) -- if test "$secure_statd" = yes; then -- AC_DEFINE(RESTRICTED_STATD, 1, [Define this if you want to enable various security checks in statd. These checks basically keep anyone but lockd from using this service.]) -- fi -- AC_SUBST(secure_statd) --AC_ARG_ENABLE(rquotad, -- [AC_HELP_STRING([--enable-rquotad], -- [enable rquotad @<:@default=yes@:>@])], -- enable_rquotad=$enableval, -- enable_rquotad=yes) -- if test "$enable_rquotad" = yes; then -- RQUOTAD=rquotad -- else -- RQUOTAD= -- fi -- AM_CONDITIONAL(CONFIG_RQUOTAD, [test "$enable_rquotad" = "yes"]) -- --AC_ARG_ENABLE(mount, -- [AC_HELP_STRING([--enable-mount], -- [Create mount.nfs and don't use the util-linux mount(8) functionality. @<:@default=no@:>@])], -- enable_mount=$enableval, -- enable_mount=no) -- AM_CONDITIONAL(CONFIG_MOUNT, [test "$enable_mount" = "yes"]) - - # Check whether user wants TCP wrappers support - AC_TCP_WRAPPERS -@@ -156,50 +77,15 @@ AC_CHECK_FUNC(connect, , - AC_MSG_ERROR(Function 'socket' not found.), $LIBNSL)) - - AC_CHECK_LIB(crypt, crypt, [LIBCRYPT="-lcrypt"]) --if test "$enable_nfsv4" = yes; then -- AC_CHECK_LIB(event, event_dispatch, [libevent=1], AC_MSG_ERROR([libevent needed for nfsv4 support])) -- AC_CHECK_LIB(nfsidmap, nfs4_init_name_mapping, [libnfsidmap=1], AC_MSG_ERROR([libnfsidmap needed for nfsv4 support])) -- AC_CHECK_HEADERS(event.h, ,AC_MSG_ERROR([libevent needed for nfsv4 support])) -- AC_CHECK_HEADERS(nfsidmap.h, ,AC_MSG_ERROR([libnfsidmap needed for nfsv4 support])) -- dnl librpcsecgss already has a dependency on libgssapi, -- dnl but we need to make sure we get the right version -- if test "$enable_gss" = yes; then -- PKG_CHECK_MODULES(RPCSECGSS, librpcsecgss >= 0.10, , -- [AC_MSG_ERROR([Unable to locate information required to use librpcsecgss. If you have pkgconfig installed, you might try setting environment variable PKG_CONFIG_PATH to /usr/local/lib/pkgconfig]) -- ] -- ) -- PKG_CHECK_MODULES(GSSAPI, libgssapi >= 0.9) -- fi -- --fi --if test "$knfsd_cv_glibc2" = no; then -- AC_CHECK_LIB(bsd, daemon, [LIBBSD="-lbsd"]) --fi --AC_CHECK_LIB(blkid, blkid_get_cache, [LIBBLKID="-lblkid"], AC_MSG_ERROR([libblkid needed])) --AC_CHECK_HEADER(blkid/blkid.h, , AC_MSG_ERROR([Cannot file libblkid header file blkid/blkid.h])) -+PKG_CHECK_MODULES(GSSAPI, libgssapi >= 0.9) - AC_SUBST(LIBSOCKET) - AC_SUBST(LIBCRYPT) - AC_SUBST(LIBBSD) - AC_SUBST(LIBBLKID) - - if test "$enable_gss" = yes; then -- dnl 'gss' also depends on nfsidmap.h - at least for svcgssd_proc.c -- AC_CHECK_HEADERS(nfsidmap.h, ,AC_MSG_ERROR([libnfsidmap needed for gss support])) -- AC_CHECK_HEADERS(spkm3.h, ,AC_MSG_WARN([could not locate SPKM3 header; will not have SPKM3 support])) -- dnl the nfs4_set_debug function doesn't appear in all version of the library -- AC_CHECK_LIB(nfsidmap, nfs4_set_debug, -- AC_DEFINE(HAVE_NFS4_SET_DEBUG,1, -- [Whether nfs4_set_debug() is present in libnfsidmap]),) -- - dnl Check for Kerberos V5 - AC_KERBEROS_V5 -- -- dnl This is not done until here because we need to have KRBLIBS set -- dnl ("librpcsecgss=1" is so that it doesn't get added to LIBS) -- AC_CHECK_LIB(rpcsecgss, authgss_create_default, [librpcsecgss=1], AC_MSG_ERROR([librpcsecgss needed for nfsv4 support]), -lgssapi -ldl) -- AC_CHECK_LIB(rpcsecgss, authgss_set_debug_level, -- AC_DEFINE(HAVE_AUTHGSS_SET_DEBUG_LEVEL, 1, [Define this if the rpcsec_gss library has the function authgss_set_debug_level]),, -lgssapi -ldl) -- - fi - - dnl ************************************************************* -@@ -311,33 +197,7 @@ AC_SUBST([ACLOCAL_AMFLAGS], ["-I $ac_mac - - AC_CONFIG_FILES([ - Makefile -- linux-nfs/Makefile -- support/Makefile -- support/export/Makefile -- support/include/nfs/Makefile -- support/include/rpcsvc/Makefile -- support/include/sys/fs/Makefile -- support/include/sys/Makefile -- support/include/Makefile -- support/misc/Makefile -- support/nfs/Makefile -- tools/Makefile -- tools/getiversion/Makefile -- tools/locktest/Makefile -- tools/nlmtest/Makefile -- tools/rpcdebug/Makefile -- tools/rpcgen/Makefile - utils/Makefile -- utils/exportfs/Makefile -- utils/gssd/Makefile -- utils/idmapd/Makefile -- utils/lockd/Makefile -- utils/mount/Makefile -- utils/mountd/Makefile -- utils/nfsd/Makefile -- utils/nfsstat/Makefile -- utils/rquotad/Makefile -- utils/showmount/Makefile -- utils/statd/Makefile]) -+ utils/gssd/Makefile]) - AC_OUTPUT - -diff -Nrup nfs-utils-1.0.11.lustre/Makefile.am nfs-utils-1.0.11/Makefile.am ---- nfs-utils-1.0.11.lustre/Makefile.am 2007-02-21 21:50:03.000000000 -0700 -+++ nfs-utils-1.0.11/Makefile.am 2008-01-02 18:10:29.000000000 -0700 -@@ -1,6 +1,6 @@ - ## Process this file with automake to produce Makefile.in - --SUBDIRS = tools support utils linux-nfs -+SUBDIRS = utils - - MAINTAINERCLEANFILES = Makefile.in - -diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/cacheio.c nfs-utils-1.0.11/utils/gssd/cacheio.c ---- nfs-utils-1.0.11.lustre/utils/gssd/cacheio.c 2007-02-21 21:50:03.000000000 -0700 -+++ nfs-utils-1.0.11/utils/gssd/cacheio.c 2008-01-02 18:11:38.000000000 -0700 -@@ -240,7 +240,8 @@ int qword_get(char **bpp, char *dest, in - return -1; - while (*bp == ' ') bp++; - *bpp = bp; -- *dest = '\0'; -+// why should we clear *dest??? -+// *dest = '\0'; - return len; - } - -diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/context.c nfs-utils-1.0.11/utils/gssd/context.c ---- nfs-utils-1.0.11.lustre/utils/gssd/context.c 2007-02-21 21:50:03.000000000 -0700 -+++ nfs-utils-1.0.11/utils/gssd/context.c 2008-01-02 18:11:38.000000000 -0700 -@@ -33,11 +33,14 @@ - #include - #include - #include --#include --#include --#include "gss_util.h" --#include "gss_oids.h" --#include "err_util.h" -+ -+#ifdef _NEW_BUILD_ -+# include "lgss_utils.h" -+#else -+# include "gss_util.h" -+# include "gss_oids.h" -+# include "err_util.h" -+#endif - #include "context.h" - - int -diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/context.h nfs-utils-1.0.11/utils/gssd/context.h ---- nfs-utils-1.0.11.lustre/utils/gssd/context.h 2008-01-02 17:22:48.000000000 -0700 -+++ nfs-utils-1.0.11/utils/gssd/context.h 2008-01-02 18:11:38.000000000 -0700 -@@ -31,8 +31,6 @@ - #ifndef _CONTEXT_H_ - #define _CONTEXT_H_ - --#include -- - /* Hopefully big enough to hold any serialized context */ - #define MAX_CTX_LEN 4096 - -diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/context_heimdal.c nfs-utils-1.0.11/utils/gssd/context_heimdal.c ---- nfs-utils-1.0.11.lustre/utils/gssd/context_heimdal.c 2007-02-21 21:50:03.000000000 -0700 -+++ nfs-utils-1.0.11/utils/gssd/context_heimdal.c 2008-01-02 18:11:38.000000000 -0700 -@@ -43,8 +43,13 @@ - #ifdef HAVE_COM_ERR_H - #include - #endif --#include "err_util.h" --#include "gss_oids.h" -+ -+#ifdef _NEW_BUILD_ -+# include "lgss_utils.h" -+#else -+# include "err_util.h" -+# include "gss_oids.h" -+#endif - #include "write_bytes.h" - - int write_heimdal_keyblock(char **p, char *end, krb5_keyblock *key) -diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/context_lucid.c nfs-utils-1.0.11/utils/gssd/context_lucid.c ---- nfs-utils-1.0.11.lustre/utils/gssd/context_lucid.c 2008-01-02 17:22:48.000000000 -0700 -+++ nfs-utils-1.0.11/utils/gssd/context_lucid.c 2008-01-02 18:11:38.000000000 -0700 -@@ -41,11 +41,7 @@ - #include - #include - #include --#include "gss_util.h" --#include "gss_oids.h" --#include "err_util.h" --#include "context.h" -- -+#include - #include - #include - #ifndef OM_uint64 -@@ -53,6 +49,16 @@ typedef uint64_t OM_uint64; - #endif - #include - -+#ifdef _NEW_BUILD_ -+# include "lgss_utils.h" -+#else -+# include "gss_util.h" -+# include "gss_oids.h" -+# include "err_util.h" -+#endif -+#include "write_bytes.h" -+#include "context.h" -+ - static int - write_lucid_keyblock(char **p, char *end, gss_krb5_lucid_key_t *key) - { -@@ -354,6 +360,7 @@ static int - prepare_krb5_rfc4121_buffer(gss_krb5_lucid_context_v1_t *lctx, - gss_buffer_desc *buf) - { -+ static int constant_two = 2; - char *p, *end; - uint32_t v2_flags = 0; - gss_krb5_lucid_key_t enc_key; -@@ -372,7 +379,7 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc - end = buf->value + MAX_CTX_LEN; - - /* Version 2 */ -- if (WRITE_BYTES(&p, end, lctx->initiate)) goto out_err; -+ if (WRITE_BYTES(&p, end, constant_two)) goto out_err; - if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err; - - if (lctx->initiate) -@@ -387,7 +394,7 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc - if (WRITE_BYTES(&p, end, lctx->send_seq)) goto out_err; - - /* Protocol 0 here implies DES3 or RC4 */ -- printerr(2, "%s: protocol %d\n", __FUNCTION__, lctx->protocol); -+ printerr(3, "protocol %d\n", lctx->protocol); - if (lctx->protocol == 0) { - enctype = lctx->rfc1964_kd.ctx_key.type; - #ifdef HAVE_HEIMDAL -@@ -415,8 +422,8 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc - } - numkeys = 3; - } -- printerr(2, "%s: serializing %d keys with enctype %d and size %d\n", -- __FUNCTION__, numkeys, enctype, keysize); -+ printerr(3, "serializing %d keys with enctype %d and size %d\n", -+ numkeys, enctype, keysize); - if (WRITE_BYTES(&p, end, enctype)) goto out_err; - if (WRITE_BYTES(&p, end, keysize)) goto out_err; - if (WRITE_BYTES(&p, end, numkeys)) goto out_err; -@@ -434,14 +441,25 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc - goto out_err; - - /* Kc */ -- if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key, -- &derived_key, -- KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM)) -- goto out_err; -- if (write_bytes(&p, end, derived_key.data, -- derived_key.length)) -- goto out_err; -- free(derived_key.data); -+ /* -+ * RC4 is special, it dosen't need key derivation. Actually -+ * the Ke is based on plain text. Here we just let all three -+ * key identical, kernel will handle everything. --ericm -+ */ -+ if (lctx->rfc1964_kd.ctx_key.type == ENCTYPE_ARCFOUR_HMAC) { -+ if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data, -+ lctx->rfc1964_kd.ctx_key.length)) -+ goto out_err; -+ } else { -+ if (derive_key_lucid(&lctx->rfc1964_kd.ctx_key, -+ &derived_key, -+ KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM)) -+ goto out_err; -+ if (write_bytes(&p, end, derived_key.data, -+ derived_key.length)) -+ goto out_err; -+ free(derived_key.data); -+ } - } else { - gss_krb5_lucid_key_t *keyptr; - uint32_t sign_usage, seal_usage; -@@ -451,6 +469,7 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc - else - keyptr = &lctx->cfx_kd.ctx_key; - -+#if 0 - if (lctx->initiate == 1) { - sign_usage = KG_USAGE_INITIATOR_SIGN; - seal_usage = KG_USAGE_INITIATOR_SEAL; -@@ -458,6 +477,19 @@ prepare_krb5_rfc4121_buffer(gss_krb5_luc - sign_usage = KG_USAGE_ACCEPTOR_SIGN; - seal_usage = KG_USAGE_ACCEPTOR_SEAL; - } -+#else -+ /* FIXME -+ * These are from rfc4142, but I don't understand: if we supply -+ * different 'usage' value for client & server, then the peers -+ * will have different derived keys. How could this work? -+ * -+ * Here we simply use old SIGN/SEAL values until we find the -+ * answer. --ericm -+ * FIXME -+ */ -+ sign_usage = KG_USAGE_SIGN; -+ seal_usage = KG_USAGE_SEAL; -+#endif - - /* derive and send down: Ke, Ki, and Kc */ - -@@ -515,7 +547,7 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss - gss_krb5_lucid_context_v1_t *lctx = 0; - int retcode = 0; - -- printerr(2, "DEBUG: %s: lucid version!\n", __FUNCTION__); -+ printerr(3, "lucid version!\n"); - maj_stat = gss_export_lucid_sec_context(&min_stat, &ctx, - 1, &return_ctx); - if (maj_stat != GSS_S_COMPLETE) { -diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/context_mit.c nfs-utils-1.0.11/utils/gssd/context_mit.c ---- nfs-utils-1.0.11.lustre/utils/gssd/context_mit.c 2008-01-02 17:22:48.000000000 -0700 -+++ nfs-utils-1.0.11/utils/gssd/context_mit.c 2008-01-02 18:11:38.000000000 -0700 -@@ -39,10 +39,15 @@ - #include - #include - #include --#include --#include "gss_util.h" --#include "gss_oids.h" --#include "err_util.h" -+ -+#ifdef _NEW_BUILD_ -+# include "lgss_utils.h" -+# include "write_bytes.h" -+#else -+# include "gss_util.h" -+# include "gss_oids.h" -+# include "err_util.h" -+#endif - #include "context.h" - - #include -@@ -333,12 +338,7 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss - * keydata-2; ( Ki (Kseq for DES3) ) - * keydata-3; ( Kc (derived checksum key) ) - */ -- if (kctx->initiate) { -- if (WRITE_BYTES(&p, end, constant_one)) goto out_err; -- } -- else { -- if (WRITE_BYTES(&p, end, constant_zero)) goto out_err; -- } -+ if (WRITE_BYTES(&p, end, constant_two)) goto out_err; - if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err; - - /* Only applicable flag for this is initiator */ -diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/context_spkm3.c nfs-utils-1.0.11/utils/gssd/context_spkm3.c ---- nfs-utils-1.0.11.lustre/utils/gssd/context_spkm3.c 2007-02-21 21:50:03.000000000 -0700 -+++ nfs-utils-1.0.11/utils/gssd/context_spkm3.c 2008-01-02 18:11:38.000000000 -0700 -@@ -33,8 +33,6 @@ - #include - #include - #include --#include --#include - #include "gss_util.h" - #include "gss_oids.h" - #include "err_util.h" -diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/err_util.c nfs-utils-1.0.11/utils/gssd/err_util.c ---- nfs-utils-1.0.11.lustre/utils/gssd/err_util.c 2007-02-21 21:50:03.000000000 -0700 -+++ nfs-utils-1.0.11/utils/gssd/err_util.c 2008-01-02 18:11:38.000000000 -0700 -@@ -32,6 +32,8 @@ - #include - #include - #include -+#include -+#include - #include "err_util.h" - - static int verbosity = 0; -@@ -91,3 +93,40 @@ printit: - /* reset the buffer */ - memset(message_buf, 0, sizeof(message_buf)); - } -+ -+void print_hexl(int pri, unsigned char *cp, int length) -+{ -+ int i, j, jm; -+ unsigned char c; -+ -+ printerr(pri, "length %d\n",length); -+ printerr(pri, "\n"); -+ -+ for (i = 0; i < length; i += 0x10) { -+ printerr(pri, " %04x: ", (u_int)i); -+ jm = length - i; -+ jm = jm > 16 ? 16 : jm; -+ -+ for (j = 0; j < jm; j++) { -+ if ((j % 2) == 1) -+ printerr(pri,"%02x ", (u_int)cp[i+j]); -+ else -+ printerr(pri,"%02x", (u_int)cp[i+j]); -+ } -+ for (; j < 16; j++) { -+ if ((j % 2) == 1) -+ printerr(pri," "); -+ else -+ printerr(pri," "); -+ } -+ printerr(pri," "); -+ -+ for (j = 0; j < jm; j++) { -+ c = cp[i+j]; -+ c = isprint(c) ? c : '.'; -+ printerr(pri,"%c", c); -+ } -+ printerr(pri,"\n"); -+ } -+} -+ -diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/err_util.h nfs-utils-1.0.11/utils/gssd/err_util.h ---- nfs-utils-1.0.11.lustre/utils/gssd/err_util.h 2007-02-21 21:50:03.000000000 -0700 -+++ nfs-utils-1.0.11/utils/gssd/err_util.h 2008-01-02 18:11:38.000000000 -0700 -@@ -33,5 +33,6 @@ - - void initerr(char *progname, int verbosity, int fg); - void printerr(int priority, char *format, ...); -+void print_hexl(int pri, unsigned char *cp, int length); - - #endif /* _ERR_UTIL_H_ */ -diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gss_clnt_send_err.c nfs-utils-1.0.11/utils/gssd/gss_clnt_send_err.c ---- nfs-utils-1.0.11.lustre/utils/gssd/gss_clnt_send_err.c 2007-02-21 21:50:03.000000000 -0700 -+++ nfs-utils-1.0.11/utils/gssd/gss_clnt_send_err.c 2008-01-02 18:10:29.000000000 -0700 -@@ -47,6 +47,7 @@ - #include "gssd.h" - #include "write_bytes.h" - -+#if 0 - char pipefsdir[PATH_MAX] = GSSD_PIPEFS_DIR; - - static void -@@ -102,3 +103,4 @@ main(int argc, char *argv[]) - } - exit(0); - } -+#endif -diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gssd.c nfs-utils-1.0.11/utils/gssd/gssd.c ---- nfs-utils-1.0.11.lustre/utils/gssd/gssd.c 2008-01-02 17:22:48.000000000 -0700 -+++ nfs-utils-1.0.11/utils/gssd/gssd.c 2008-01-02 18:11:38.000000000 -0700 -@@ -38,9 +38,12 @@ - - #include "config.h" - -+#include - #include - #include --#include -+#include -+#include -+#include - - #include - #include -@@ -48,23 +51,107 @@ - #include - #include - #include -+#include - #include "gssd.h" - #include "err_util.h" - #include "gss_util.h" - #include "krb5_util.h" -+#include "lsupport.h" - - char pipefs_dir[PATH_MAX] = GSSD_PIPEFS_DIR; - char pipefs_nfsdir[PATH_MAX] = GSSD_PIPEFS_DIR; - char keytabfile[PATH_MAX] = GSSD_DEFAULT_KEYTAB_FILE; - char ccachedir[PATH_MAX] = GSSD_DEFAULT_CRED_DIR; - int use_memcache = 0; -+int lgssd_mutex_downcall = -1; - --void --sig_die(int signal) -+static int lgssd_create_mutex(int *semid) -+{ -+ int id; -+ int arg; -+ -+ id = semget(IPC_PRIVATE, 1, IPC_CREAT); -+ if (id == -1) { -+ printerr(0, "semget: %s\n", strerror(errno)); -+ return -1; -+ } -+ -+ arg = 1; -+ if (semctl(id, 0, SETVAL, arg) != 0) { -+ printerr(0, "semctl: %s\n", strerror(errno)); -+ semctl(id, 1, IPC_RMID, arg); -+ return -1; -+ } -+ -+ *semid = id; -+ return 0; -+} -+ -+void lgssd_init_mutexs(void) -+{ -+ if (lgssd_create_mutex(&lgssd_mutex_downcall)) { -+ printerr(0, "can't create downcall mutex\n"); -+ exit(1); -+ } -+} -+ -+void lgssd_fini_mutexs(void) -+{ -+ int arg = 0; -+ -+ if (lgssd_mutex_downcall != -1) -+ semctl(lgssd_mutex_downcall, 1, IPC_RMID, arg); -+} -+ -+void lgssd_mutex_get(int semid) -+{ -+ struct sembuf op[1] = { {0, -1, SEM_UNDO} }; -+ int rc; -+ -+ rc = semop(semid, op, 1); -+ if (rc != 0) { -+ printerr(0, "exit on mutex_get err %d: %s\n", -+ rc, strerror(errno)); -+ exit(1); -+ } -+} -+ -+void lgssd_mutex_put(int semid) - { -+ struct sembuf op[1] = { {0, 1, 0} }; -+ int rc; -+ -+ rc = semop(semid, op, 1); -+ if (rc != 0) { -+ printerr(0, "ignore mutex_put err %d: %s\n", -+ rc, strerror(errno)); -+ } -+} -+ -+static void lgssd_cleanup(void) -+{ -+ pid_t child_pid; -+ -+ /* make sure all children finished */ -+ while (1) { -+ child_pid = waitpid(-1, NULL, 0); -+ if (child_pid < 0) -+ break; -+ -+ printerr(3, "cleanup: child %d terminated\n", child_pid); -+ } -+ -+ lgssd_fini_mutexs(); -+ - /* destroy krb5 machine creds */ - gssd_destroy_krb5_machine_creds(); -+} -+ -+void -+sig_die(int signal) -+{ - printerr(1, "exiting on signal %d\n", signal); -+ lgssd_cleanup(); - exit(1); - } - -@@ -79,7 +166,7 @@ sig_hup(int signal) - static void - usage(char *progname) - { -- fprintf(stderr, "usage: %s [-f] [-v] [-r] [-p pipefsdir] [-k keytab] [-d ccachedir]\n", -+ fprintf(stderr, "usage: %s [-f] [-v] [-p pipefsdir] [-k keytab] [-d ccachedir]\n", - progname); - exit(1); - } -@@ -89,7 +176,6 @@ main(int argc, char *argv[]) - { - int fg = 0; - int verbosity = 0; -- int rpc_verbosity = 0; - int opt; - extern char *optarg; - char *progname; -@@ -99,18 +185,12 @@ main(int argc, char *argv[]) - case 'f': - fg = 1; - break; -- case 'm': -- /* Accept but ignore this. Now the default. */ -- break; - case 'M': - use_memcache = 1; - break; - case 'v': - verbosity++; - break; -- case 'r': -- rpc_verbosity++; -- break; - case 'p': - strncpy(pipefs_dir, optarg, sizeof(pipefs_dir)); - if (pipefs_dir[sizeof(pipefs_dir)-1] != '\0') -@@ -131,10 +211,6 @@ main(int argc, char *argv[]) - break; - } - } -- snprintf(pipefs_nfsdir, sizeof(pipefs_nfsdir), "%s/%s", -- pipefs_dir, GSSD_SERVICE_NAME); -- if (pipefs_nfsdir[sizeof(pipefs_nfsdir)-1] != '\0') -- errx(1, "pipefs_nfsdir path name too long"); - - if ((progname = strrchr(argv[0], '/'))) - progname++; -@@ -142,30 +218,42 @@ main(int argc, char *argv[]) - progname = argv[0]; - - initerr(progname, verbosity, fg); --#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL -- authgss_set_debug_level(rpc_verbosity); --#else -- if (rpc_verbosity > 0) -- printerr(0, "Warning: rpcsec_gss library does not " -- "support setting debug level\n"); --#endif - - if (gssd_check_mechs() != 0) - errx(1, "Problem with gssapi library"); - -+ if (gssd_get_local_realm()) -+ errx(1, "get local realm"); -+ - if (!fg && daemon(0, 0) < 0) - errx(1, "fork"); - -+ /* This should be checked _after_ daemon(), because we need to own -+ * the undo-able semaphore by this process -+ */ -+ gssd_init_unique(GSSD_CLI); -+ -+ /* Process keytab file and get machine credentials. This will modify -+ * disk status so do it after we are sure we are the only instance -+ */ -+ if (gssd_refresh_krb5_machine_creds()) -+ return -1; -+ - signal(SIGINT, sig_die); - signal(SIGTERM, sig_die); - signal(SIGHUP, sig_hup); - -- /* Process keytab file and get machine credentials */ -- gssd_refresh_krb5_machine_creds(); -+#if 0 - /* Determine Kerberos information from the kernel */ - gssd_obtain_kernel_krb5_info(); -+#endif -+ -+ lgssd_init_mutexs(); -+ -+ printerr(0, "lgssd initialized and ready to serve\n"); -+ lgssd_run(); - -- gssd_run(); -- printerr(0, "gssd_run returned!\n"); -- abort(); -+ lgssd_cleanup(); -+ printerr(0, "lgssd exiting\n"); -+ return 0; - } -diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gssd.h nfs-utils-1.0.11/utils/gssd/gssd.h ---- nfs-utils-1.0.11.lustre/utils/gssd/gssd.h 2008-01-02 17:22:48.000000000 -0700 -+++ nfs-utils-1.0.11/utils/gssd/gssd.h 2008-01-02 18:11:38.000000000 -0700 -@@ -48,8 +48,13 @@ - #define GSSD_DEFAULT_CRED_PREFIX "krb5cc_" - #define GSSD_DEFAULT_MACHINE_CRED_SUFFIX "machine" - #define GSSD_DEFAULT_KEYTAB_FILE "/etc/krb5.keytab" --#define GSSD_SERVICE_NAME "nfs" --#define GSSD_SERVICE_NAME_LEN 3 -+#define GSSD_SERVICE_MDS "lustre_mds" -+#define GSSD_SERVICE_OSS "lustre_oss" -+#define GSSD_SERVICE_MDS_NAMELEN 10 -+#define GSSD_SERVICE_OSS_NAMELEN 10 -+ -+#define LUSTRE_ROOT_NAME "lustre_root" -+#define LUSTRE_ROOT_NAMELEN 11 - - /* - * The gss mechanisms that we can handle -@@ -59,9 +64,9 @@ enum {AUTHTYPE_KRB5, AUTHTYPE_SPKM3, AUT - - - extern char pipefs_dir[PATH_MAX]; --extern char pipefs_nfsdir[PATH_MAX]; - extern char keytabfile[PATH_MAX]; - extern char ccachedir[PATH_MAX]; -+extern char gethostname_ex[PATH_MAX]; - extern int use_memcache; - - TAILQ_HEAD(clnt_list_head, clnt_info) clnt_list; -@@ -71,10 +76,6 @@ struct clnt_info { - char *dirname; - int dir_fd; - char *servicename; -- char *servername; -- int prog; -- int vers; -- char *protocol; - int krb5_fd; - int krb5_poll_index; - int spkm3_fd; -@@ -85,8 +86,14 @@ void init_client_list(void); - int update_client_list(void); - void handle_krb5_upcall(struct clnt_info *clp); - void handle_spkm3_upcall(struct clnt_info *clp); --int gssd_acquire_cred(char *server_name); --void gssd_run(void); -+void lgssd_run(void); -+ -+ -+extern int lgssd_mutex_downcall; - -+void lgssd_init_mutexs(void); -+void lgssd_fini_mutexs(void); -+void lgssd_mutex_get(int semid); -+void lgssd_mutex_put(int semid); - - #endif /* _RPC_GSSD_H_ */ -diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gssd_main_loop.c nfs-utils-1.0.11/utils/gssd/gssd_main_loop.c ---- nfs-utils-1.0.11.lustre/utils/gssd/gssd_main_loop.c 2008-01-02 17:22:48.000000000 -0700 -+++ nfs-utils-1.0.11/utils/gssd/gssd_main_loop.c 2008-01-02 18:11:38.000000000 -0700 -@@ -44,6 +44,10 @@ - #include - #include - #include -+/* For time() */ -+#include -+/* For waitpid() */ -+#include - - #include "gssd.h" - #include "err_util.h" -@@ -94,11 +98,13 @@ scan_poll_results(int ret) - }; - - void --gssd_run() -+lgssd_run() - { - int ret; - struct sigaction dn_act; - int fd; -+ time_t child_check = 0; -+ pid_t child_pid; - - /* Taken from linux/Documentation/dnotify.txt: */ - dn_act.sa_sigaction = dir_notify_handler; -@@ -106,10 +112,10 @@ gssd_run() - dn_act.sa_flags = SA_SIGINFO; - sigaction(DNOTIFY_SIGNAL, &dn_act, NULL); - -- if ((fd = open(pipefs_nfsdir, O_RDONLY)) == -1) { -+ if ((fd = open(pipefs_dir, O_RDONLY)) == -1) { - printerr(0, "ERROR: failed to open %s: %s\n", -- pipefs_nfsdir, strerror(errno)); -- exit(1); -+ pipefs_dir, strerror(errno)); -+ return; - } - fcntl(fd, F_SETSIG, DNOTIFY_SIGNAL); - fcntl(fd, F_NOTIFY, DN_CREATE|DN_DELETE|DN_MODIFY|DN_MULTISHOT); -@@ -119,12 +125,30 @@ gssd_run() - while (1) { - while (dir_changed) { - dir_changed = 0; -+ printerr(2, "pipefs root dir changed\n"); - if (update_client_list()) { - printerr(0, "ERROR: couldn't update " - "client list\n"); -- exit(1); -+ goto out; - } - } -+ -+ /* every 5s cleanup possible zombies of child processes */ -+ if (time(NULL) - child_check >= 5) { -+ printerr(3, "check zombie children...\n"); -+ -+ while (1) { -+ child_pid = waitpid(-1, NULL, WNOHANG); -+ if (child_pid <= 0) -+ break; -+ -+ printerr(2, "terminate zombie child: %d\n", -+ child_pid); -+ } -+ -+ child_check = time(NULL); -+ } -+ - /* race condition here: dir_changed could be set before we - * enter the poll, and we'd never notice if it weren't for the - * timeout. */ -@@ -139,6 +163,7 @@ gssd_run() - scan_poll_results(ret); - } - } -+out: - close(fd); - return; - } -diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gssd_proc.c nfs-utils-1.0.11/utils/gssd/gssd_proc.c ---- nfs-utils-1.0.11.lustre/utils/gssd/gssd_proc.c 2008-01-02 17:22:48.000000000 -0700 -+++ nfs-utils-1.0.11/utils/gssd/gssd_proc.c 2008-01-02 18:11:38.000000000 -0700 -@@ -43,7 +43,6 @@ - #endif - #include "config.h" - #include --#include - #include - #include - #include -@@ -69,6 +68,7 @@ - #include "gss_oids.h" - #include "krb5_util.h" - #include "context.h" -+#include "lsupport.h" - - /* - * pollarray: -@@ -99,86 +99,10 @@ struct pollfd * pollarray; - - int pollsize; /* the size of pollaray (in pollfd's) */ - --/* XXX buffer problems: */ --static int --read_service_info(char *info_file_name, char **servicename, char **servername, -- int *prog, int *vers, char **protocol) { --#define INFOBUFLEN 256 -- char buf[INFOBUFLEN]; -- static char dummy[128]; -- int nbytes; -- static char service[128]; -- static char address[128]; -- char program[16]; -- char version[16]; -- char protoname[16]; -- in_addr_t inaddr; -- int fd = -1; -- struct hostent *ent = NULL; -- int numfields; -- -- *servicename = *servername = *protocol = NULL; -- -- if ((fd = open(info_file_name, O_RDONLY)) == -1) { -- printerr(0, "ERROR: can't open %s: %s\n", info_file_name, -- strerror(errno)); -- goto fail; -- } -- if ((nbytes = read(fd, buf, INFOBUFLEN)) == -1) -- goto fail; -- close(fd); -- -- numfields = sscanf(buf,"RPC server: %127s\n" -- "service: %127s %15s version %15s\n" -- "address: %127s\n" -- "protocol: %15s\n", -- dummy, -- service, program, version, -- address, -- protoname); -- -- if (numfields == 5) { -- strcpy(protoname, "tcp"); -- } else if (numfields != 6) { -- goto fail; -- } -- -- /* check service, program, and version */ -- if(memcmp(service, "nfs", 3)) return -1; -- *prog = atoi(program + 1); /* skip open paren */ -- *vers = atoi(version); -- if((*prog != 100003) || ((*vers != 2) && (*vers != 3) && (*vers != 4))) -- goto fail; -- -- /* create service name */ -- inaddr = inet_addr(address); -- if (!(ent = gethostbyaddr(&inaddr, sizeof(inaddr), AF_INET))) { -- printerr(0, "ERROR: can't resolve server %s name\n", address); -- goto fail; -- } -- if (!(*servername = calloc(strlen(ent->h_name) + 1, 1))) -- goto fail; -- memcpy(*servername, ent->h_name, strlen(ent->h_name)); -- snprintf(buf, INFOBUFLEN, "%s@%s", service, ent->h_name); -- if (!(*servicename = calloc(strlen(buf) + 1, 1))) -- goto fail; -- memcpy(*servicename, buf, strlen(buf)); -- -- if (!(*protocol = strdup(protoname))) -- goto fail; -- return 0; --fail: -- printerr(0, "ERROR: failed to read service info\n"); -- if (fd != -1) close(fd); -- if (*servername) free(*servername); -- if (*servicename) free(*servicename); -- if (*protocol) free(*protocol); -- return -1; --} -- - static void - destroy_client(struct clnt_info *clp) - { -+ printerr(3, "clp %p: dirname %s, krb5fd %d\n", clp, clp->dirname, clp->krb5_fd); - if (clp->krb5_poll_index != -1) - memset(&pollarray[clp->krb5_poll_index], 0, - sizeof(struct pollfd)); -@@ -190,8 +114,6 @@ destroy_client(struct clnt_info *clp) - if (clp->spkm3_fd != -1) close(clp->spkm3_fd); - if (clp->dirname) free(clp->dirname); - if (clp->servicename) free(clp->servicename); -- if (clp->servername) free(clp->servername); -- if (clp->protocol) free(clp->protocol); - free(clp); - } - -@@ -221,7 +143,6 @@ process_clnt_dir_files(struct clnt_info - { - char kname[32]; - char sname[32]; -- char info_file_name[32]; - - if (clp->krb5_fd == -1) { - snprintf(kname, sizeof(kname), "%s/krb5", clp->dirname); -@@ -233,13 +154,6 @@ process_clnt_dir_files(struct clnt_info - } - if((clp->krb5_fd == -1) && (clp->spkm3_fd == -1)) - return -1; -- snprintf(info_file_name, sizeof(info_file_name), "%s/info", -- clp->dirname); -- if ((clp->servicename == NULL) && -- read_service_info(info_file_name, &clp->servicename, -- &clp->servername, &clp->prog, &clp->vers, -- &clp->protocol)) -- return -1; - return 0; - } - -@@ -273,6 +187,8 @@ insert_clnt_poll(struct clnt_info *clp) - } - pollarray[clp->krb5_poll_index].fd = clp->krb5_fd; - pollarray[clp->krb5_poll_index].events |= POLLIN; -+ printerr(2, "monitoring krb5 channel under %s\n", -+ clp->dirname); - } - - if ((clp->spkm3_fd != -1) && (clp->spkm3_poll_index == -1)) { -@@ -386,67 +302,106 @@ find_client(char *dirname) - int - update_client_list(void) - { -- struct dirent **namelist; -+ char lustre_dir[PATH_MAX]; -+ struct dirent lustre_dirent = { .d_name = "lustre" }; -+ struct dirent *namelist[1]; -+ struct stat statbuf; - int i, j; - -- if (chdir(pipefs_nfsdir) < 0) { -+ if (chdir(pipefs_dir) < 0) { - printerr(0, "ERROR: can't chdir to %s: %s\n", -- pipefs_nfsdir, strerror(errno)); -+ pipefs_dir, strerror(errno)); - return -1; - } - -- j = scandir(pipefs_nfsdir, &namelist, NULL, alphasort); -- if (j < 0) { -- printerr(0, "ERROR: can't scandir %s: %s\n", -- pipefs_nfsdir, strerror(errno)); -- return -1; -+ snprintf(lustre_dir, sizeof(lustre_dir), "%s/%s", pipefs_dir, "lustre"); -+ if (stat(lustre_dir, &statbuf) == 0) { -+ namelist[0] = &lustre_dirent; -+ j = 1; -+ printerr(2, "re-processing lustre directory\n"); -+ } else { -+ namelist[0] = NULL; -+ j = 0; -+ printerr(2, "lustre directory not exist\n"); - } -+ - update_old_clients(namelist, j); - for (i=0; i < j; i++) { -- if (i < FD_ALLOC_BLOCK -- && !strncmp(namelist[i]->d_name, "clnt", 4) -- && !find_client(namelist[i]->d_name)) -+ if (i < FD_ALLOC_BLOCK && !find_client(namelist[i]->d_name)) - process_clnt_dir(namelist[i]->d_name); -- free(namelist[i]); - } - -- free(namelist); -+ chdir("/"); - return 0; - } - -+/* Context creation response. */ -+struct lustre_gss_init_res { -+ gss_buffer_desc gr_ctx; /* context handle */ -+ u_int gr_major; /* major status */ -+ u_int gr_minor; /* minor status */ -+ u_int gr_win; /* sequence window */ -+ gss_buffer_desc gr_token; /* token */ -+}; -+ -+struct lustre_gss_data { -+ int lgd_established; -+ int lgd_lustre_svc; /* mds/oss */ -+ int lgd_uid; /* uid */ -+ char *lgd_uuid; /* client device uuid */ -+ gss_name_t lgd_name; /* service name */ -+ -+ gss_OID lgd_mech; /* mech OID */ -+ u_int lgd_req_flags; /* request flags */ -+ gss_cred_id_t lgd_cred; /* credential */ -+ gss_ctx_id_t lgd_ctx; /* session context */ -+ gss_buffer_desc lgd_rmt_ctx; /* remote handle of context */ -+ uint32_t lgd_seq_win; /* sequence window */ -+ -+ int lgd_rpc_err; -+ int lgd_gss_err; -+}; -+ - static int --do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd, -- gss_buffer_desc *context_token) -+do_downcall(int k5_fd, struct lgssd_upcall_data *updata, -+ struct lustre_gss_data *lgd, gss_buffer_desc *context_token) - { - char *buf = NULL, *p = NULL, *end = NULL; - unsigned int timeout = 0; /* XXX decide on a reasonable value */ - unsigned int buf_size = 0; - -- printerr(1, "doing downcall\n"); -- buf_size = sizeof(uid) + sizeof(timeout) + sizeof(pd->pd_seq_win) + -- sizeof(pd->pd_ctx_hndl.length) + pd->pd_ctx_hndl.length + -+ printerr(2, "doing downcall\n"); -+ buf_size = sizeof(updata->seq) + sizeof(timeout) + -+ sizeof(lgd->lgd_seq_win) + -+ sizeof(lgd->lgd_rmt_ctx.length) + lgd->lgd_rmt_ctx.length + - sizeof(context_token->length) + context_token->length; - p = buf = malloc(buf_size); - end = buf + buf_size; - -- if (WRITE_BYTES(&p, end, uid)) goto out_err; -+ if (WRITE_BYTES(&p, end, updata->seq)) goto out_err; - /* Not setting any timeout for now: */ - if (WRITE_BYTES(&p, end, timeout)) goto out_err; -- if (WRITE_BYTES(&p, end, pd->pd_seq_win)) goto out_err; -- if (write_buffer(&p, end, &pd->pd_ctx_hndl)) goto out_err; -+ if (WRITE_BYTES(&p, end, lgd->lgd_seq_win)) goto out_err; -+ if (write_buffer(&p, end, &lgd->lgd_rmt_ctx)) goto out_err; - if (write_buffer(&p, end, context_token)) goto out_err; - -- if (write(k5_fd, buf, p - buf) < p - buf) goto out_err; -+ lgssd_mutex_get(lgssd_mutex_downcall); -+ if (write(k5_fd, buf, p - buf) < p - buf) { -+ lgssd_mutex_put(lgssd_mutex_downcall); -+ goto out_err; -+ } -+ lgssd_mutex_put(lgssd_mutex_downcall); -+ - if (buf) free(buf); - return 0; - out_err: - if (buf) free(buf); -- printerr(0, "Failed to write downcall!\n"); -+ printerr(0, "ERROR: Failed to write downcall!\n"); - return -1; - } - - static int --do_error_downcall(int k5_fd, uid_t uid, int err) -+do_error_downcall(int k5_fd, uint32_t seq, int rpc_err, int gss_err) - { - char buf[1024]; - char *p = buf, *end = buf + 1024; -@@ -455,19 +410,26 @@ do_error_downcall(int k5_fd, uid_t uid, - - printerr(1, "doing error downcall\n"); - -- if (WRITE_BYTES(&p, end, uid)) goto out_err; -+ if (WRITE_BYTES(&p, end, seq)) goto out_err; - if (WRITE_BYTES(&p, end, timeout)) goto out_err; - /* use seq_win = 0 to indicate an error: */ - if (WRITE_BYTES(&p, end, zero)) goto out_err; -- if (WRITE_BYTES(&p, end, err)) goto out_err; -+ if (WRITE_BYTES(&p, end, rpc_err)) goto out_err; -+ if (WRITE_BYTES(&p, end, gss_err)) goto out_err; - -- if (write(k5_fd, buf, p - buf) < p - buf) goto out_err; -+ lgssd_mutex_get(lgssd_mutex_downcall); -+ if (write(k5_fd, buf, p - buf) < p - buf) { -+ lgssd_mutex_put(lgssd_mutex_downcall); -+ goto out_err; -+ } -+ lgssd_mutex_put(lgssd_mutex_downcall); - return 0; - out_err: - printerr(0, "Failed to write error downcall!\n"); - return -1; - } - -+#if 0 - /* - * Create an RPC connection and establish an authenticated - * gss context with a server. -@@ -659,7 +621,287 @@ int create_auth_rpc_client(struct clnt_i - - goto out; - } -+#endif -+ -+static -+int do_negotiation(struct lustre_gss_data *lgd, -+ gss_buffer_desc *gss_token, -+ struct lustre_gss_init_res *gr, -+ int timeout) -+{ -+ char *file = "/proc/fs/lustre/sptlrpc/gss/init_channel"; -+ struct lgssd_ioctl_param param; -+ struct passwd *pw; -+ int fd, ret; -+ char outbuf[8192]; -+ unsigned int *p; -+ int res; -+ -+ pw = getpwuid(lgd->lgd_uid); -+ if (!pw) { -+ printerr(0, "no uid %u in local user database\n", -+ lgd->lgd_uid); -+ return -1; -+ } -+ -+ param.version = GSSD_INTERFACE_VERSION; -+ param.uuid = lgd->lgd_uuid; -+ param.lustre_svc = lgd->lgd_lustre_svc; -+ param.uid = lgd->lgd_uid; -+ param.gid = pw->pw_gid; -+ param.send_token_size = gss_token->length; -+ param.send_token = (char *) gss_token->value; -+ param.reply_buf_size = sizeof(outbuf); -+ param.reply_buf = outbuf; -+ -+ fd = open(file, O_RDWR); -+ if (fd < 0) { -+ printerr(0, "can't open file %s\n", file); -+ return -1; -+ } -+ -+ ret = write(fd, ¶m, sizeof(param)); -+ -+ if (ret != sizeof(param)) { -+ printerr(0, "lustre ioctl err: %d\n", strerror(errno)); -+ close(fd); -+ return -1; -+ } -+ if (param.status) { -+ close(fd); -+ printerr(0, "status: %d (%s)\n", -+ param.status, strerror((int)param.status)); -+ if (param.status == -ETIMEDOUT) { -+ /* kernel return -ETIMEDOUT means the rpc timedout, -+ * we should notify the caller to reinitiate the -+ * gss negotiation, by return -ERESTART -+ */ -+ lgd->lgd_rpc_err = -ERESTART; -+ lgd->lgd_gss_err = 0; -+ } else { -+ lgd->lgd_rpc_err = param.status; -+ lgd->lgd_gss_err = 0; -+ } -+ return -1; -+ } -+ p = (unsigned int *)outbuf; -+ res = *p++; -+ gr->gr_major = *p++; -+ gr->gr_minor = *p++; -+ gr->gr_win = *p++; -+ -+ gr->gr_ctx.length = *p++; -+ gr->gr_ctx.value = malloc(gr->gr_ctx.length); -+ memcpy(gr->gr_ctx.value, p, gr->gr_ctx.length); -+ p += (((gr->gr_ctx.length + 3) & ~3) / 4); -+ -+ gr->gr_token.length = *p++; -+ gr->gr_token.value = malloc(gr->gr_token.length); -+ memcpy(gr->gr_token.value, p, gr->gr_token.length); -+ p += (((gr->gr_token.length + 3) & ~3) / 4); -+ -+ printerr(2, "do_negotiation: receive handle len %d, token len %d\n", -+ gr->gr_ctx.length, gr->gr_token.length); -+ close(fd); -+ return 0; -+} -+ -+static -+int gssd_refresh_lgd(struct lustre_gss_data *lgd) -+{ -+ struct lustre_gss_init_res gr; -+ gss_buffer_desc *recv_tokenp, send_token; -+ OM_uint32 maj_stat, min_stat, call_stat, ret_flags; -+ -+ /* GSS context establishment loop. */ -+ memset(&gr, 0, sizeof(gr)); -+ recv_tokenp = GSS_C_NO_BUFFER; -+ -+ for (;;) { -+ /* print the token we just received */ -+ if (recv_tokenp != GSS_C_NO_BUFFER) { -+ printerr(3, "The received token length %d\n", -+ recv_tokenp->length); -+ print_hexl(3, recv_tokenp->value, recv_tokenp->length); -+ } -+ -+ maj_stat = gss_init_sec_context(&min_stat, -+ lgd->lgd_cred, -+ &lgd->lgd_ctx, -+ lgd->lgd_name, -+ lgd->lgd_mech, -+ lgd->lgd_req_flags, -+ 0, /* time req */ -+ NULL, /* channel */ -+ recv_tokenp, -+ NULL, /* used mech */ -+ &send_token, -+ &ret_flags, -+ NULL); /* time rec */ -+ -+ if (recv_tokenp != GSS_C_NO_BUFFER) { -+ gss_release_buffer(&min_stat, &gr.gr_token); -+ recv_tokenp = GSS_C_NO_BUFFER; -+ } -+ if (maj_stat != GSS_S_COMPLETE && -+ maj_stat != GSS_S_CONTINUE_NEEDED) { -+ pgsserr("gss_init_sec_context", maj_stat, min_stat, -+ lgd->lgd_mech); -+ break; -+ } -+ if (send_token.length != 0) { -+ memset(&gr, 0, sizeof(gr)); -+ -+ /* print the token we are about to send */ -+ printerr(3, "token being sent length %d\n", -+ send_token.length); -+ print_hexl(3, send_token.value, send_token.length); -+ -+ call_stat = do_negotiation(lgd, &send_token, &gr, 0); -+ gss_release_buffer(&min_stat, &send_token); -+ -+ if (call_stat != 0 || -+ (gr.gr_major != GSS_S_COMPLETE && -+ gr.gr_major != GSS_S_CONTINUE_NEEDED)) { -+ printerr(0, "call stat %d, major stat 0x%x\n", -+ (int)call_stat, gr.gr_major); -+ return -1; -+ } -+ -+ if (gr.gr_ctx.length != 0) { -+ if (lgd->lgd_rmt_ctx.value) -+ gss_release_buffer(&min_stat, -+ &lgd->lgd_rmt_ctx); -+ lgd->lgd_rmt_ctx = gr.gr_ctx; -+ } -+ if (gr.gr_token.length != 0) { -+ if (maj_stat != GSS_S_CONTINUE_NEEDED) -+ break; -+ recv_tokenp = &gr.gr_token; -+ } -+ } -+ -+ /* GSS_S_COMPLETE => check gss header verifier, -+ * usually checked in gss_validate -+ */ -+ if (maj_stat == GSS_S_COMPLETE) { -+ lgd->lgd_established = 1; -+ lgd->lgd_seq_win = gr.gr_win; -+ break; -+ } -+ } -+ /* End context negotiation loop. */ -+ if (!lgd->lgd_established) { -+ if (gr.gr_token.length != 0) -+ gss_release_buffer(&min_stat, &gr.gr_token); -+ -+ printerr(0, "context negotiation failed\n"); -+ return -1; -+ } -+ -+ printerr(2, "successfully refreshed lgd\n"); -+ return 0; -+} - -+static -+int gssd_create_lgd(struct clnt_info *clp, -+ struct lustre_gss_data *lgd, -+ struct lgssd_upcall_data *updata, -+ int authtype) -+{ -+ gss_buffer_desc sname; -+ OM_uint32 maj_stat, min_stat; -+ int retval = -1; -+ -+ lgd->lgd_established = 0; -+ lgd->lgd_lustre_svc = updata->svc; -+ lgd->lgd_uid = updata->uid; -+ lgd->lgd_uuid = updata->obd; -+ -+ switch (authtype) { -+ case AUTHTYPE_KRB5: -+ lgd->lgd_mech = (gss_OID) &krb5oid; -+ lgd->lgd_req_flags = GSS_C_MUTUAL_FLAG; -+ break; -+ case AUTHTYPE_SPKM3: -+ lgd->lgd_mech = (gss_OID) &spkm3oid; -+ /* XXX sec.req_flags = GSS_C_ANON_FLAG; -+ * Need a way to switch.... -+ */ -+ lgd->lgd_req_flags = GSS_C_MUTUAL_FLAG; -+ break; -+ default: -+ printerr(0, "Invalid authentication type (%d)\n", authtype); -+ return -1; -+ } -+ -+ lgd->lgd_cred = GSS_C_NO_CREDENTIAL; -+ lgd->lgd_ctx = GSS_C_NO_CONTEXT; -+ lgd->lgd_rmt_ctx = (gss_buffer_desc) GSS_C_EMPTY_BUFFER; -+ lgd->lgd_seq_win = 0; -+ -+ sname.value = clp->servicename; -+ sname.length = strlen(clp->servicename); -+ -+ maj_stat = gss_import_name(&min_stat, &sname, -+ (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, -+ &lgd->lgd_name); -+ if (maj_stat != GSS_S_COMPLETE) { -+ pgsserr(0, maj_stat, min_stat, lgd->lgd_mech); -+ goto out_fail; -+ } -+ -+ retval = gssd_refresh_lgd(lgd); -+ -+ if (lgd->lgd_name != GSS_C_NO_NAME) -+ gss_release_name(&min_stat, &lgd->lgd_name); -+ -+ if (lgd->lgd_cred != GSS_C_NO_CREDENTIAL) -+ gss_release_cred(&min_stat, &lgd->lgd_cred); -+ -+ out_fail: -+ return retval; -+} -+ -+static -+void gssd_free_lgd(struct lustre_gss_data *lgd) -+{ -+ gss_buffer_t token = GSS_C_NO_BUFFER; -+ OM_uint32 maj_stat, min_stat; -+ -+ if (lgd->lgd_ctx == GSS_C_NO_CONTEXT) -+ return; -+ -+ maj_stat = gss_delete_sec_context(&min_stat, &lgd->lgd_ctx, token); -+} -+ -+static -+int construct_service_name(struct clnt_info *clp, -+ struct lgssd_upcall_data *ud) -+{ -+ const int buflen = 256; -+ char name[buflen]; -+ -+ if (clp->servicename) { -+ free(clp->servicename); -+ clp->servicename = NULL; -+ } -+ -+ if (lnet_nid2hostname(ud->nid, name, buflen)) -+ return -1; -+ -+ clp->servicename = malloc(32 + strlen(name)); -+ if (!clp->servicename) { -+ printerr(0, "can't alloc memory\n"); -+ return -1; -+ } -+ sprintf(clp->servicename, "%s@%s", -+ ud->svc == LUSTRE_GSS_SVC_MDS ? -+ GSSD_SERVICE_MDS : GSSD_SERVICE_OSS, -+ name); -+ printerr(2, "constructed servicename: %s\n", clp->servicename); -+ return 0; -+} - - /* - * this code uses the userland rpcsec gss library to create a krb5 -@@ -668,103 +910,145 @@ int create_auth_rpc_client(struct clnt_i - void - handle_krb5_upcall(struct clnt_info *clp) - { -- uid_t uid; -- CLIENT *rpc_clnt = NULL; -- AUTH *auth = NULL; -- struct authgss_private_data pd; -- gss_buffer_desc token; -+ pid_t pid; -+ gss_buffer_desc token = { 0, NULL }; -+ struct lgssd_upcall_data updata; -+ struct lustre_gss_data lgd; - char **credlist = NULL; - char **ccname; -+ int read_rc; - -- printerr(1, "handling krb5 upcall\n"); -+ printerr(2, "handling krb5 upcall\n"); - -- token.length = 0; -- token.value = NULL; -- memset(&pd, 0, sizeof(struct authgss_private_data)); -+ memset(&lgd, 0, sizeof(lgd)); -+ lgd.lgd_rpc_err = -EPERM; /* default error code */ - -- if (read(clp->krb5_fd, &uid, sizeof(uid)) < sizeof(uid)) { -- printerr(0, "WARNING: failed reading uid from krb5 " -+ read_rc = read(clp->krb5_fd, &updata, sizeof(updata)); -+ if (read_rc < 0) { -+ printerr(0, "WARNING: failed reading from krb5 " - "upcall pipe: %s\n", strerror(errno)); -- goto out; -+ return; -+ } else if (read_rc != sizeof(updata)) { -+ printerr(0, "upcall data mismatch: length %d, expect %d\n", -+ read_rc, sizeof(updata)); -+ -+ /* the sequence number must be the first field. if read >= 4 -+ * bytes then we know at least sequence is fine, try to send -+ * error notification nicely. -+ */ -+ if (read_rc >= 4) -+ do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0); -+ return; -+ } -+ -+ /* FIXME temporary fix, do this before fork. -+ * in case of errors could have memory leak!!! -+ */ -+ if (updata.uid == 0) { -+ if (gssd_get_krb5_machine_cred_list(&credlist)) { -+ printerr(0, "ERROR: Failed to obtain machine " -+ "credentials\n"); -+ do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0); -+ return; -+ } -+ } -+ -+ /* fork child process */ -+ pid = fork(); -+ if (pid < 0) { -+ printerr(0, "can't fork: %s\n", strerror(errno)); -+ do_error_downcall(clp->krb5_fd, updata.seq, -EPERM, 0); -+ return; -+ } else if (pid > 0) { -+ printerr(2, "forked child process: %d\n", pid); -+ return; -+ } -+ -+ printerr(1, "krb5 upcall: seq %u, uid %u, svc %u, nid 0x%llx, obd %s\n", -+ updata.seq, updata.uid, updata.svc, updata.nid, updata.obd); -+ -+ if (updata.svc != LUSTRE_GSS_SVC_MDS && -+ updata.svc != LUSTRE_GSS_SVC_OSS) { -+ printerr(0, "invalid svc %d\n", updata.svc); -+ lgd.lgd_rpc_err = -EPROTO; -+ goto out_return_error; -+ } -+ updata.obd[sizeof(updata.obd)-1] = '\0'; -+ -+ if (construct_service_name(clp, &updata)) { -+ printerr(0, "failed to construct service name\n"); -+ goto out_return_error; - } - -- if (uid == 0) { -+ if (updata.uid == 0) { - int success = 0; - - /* - * Get a list of credential cache names and try each - * of them until one works or we've tried them all - */ -+/* - if (gssd_get_krb5_machine_cred_list(&credlist)) { -- printerr(0, "WARNING: Failed to obtain machine " -- "credentials for connection to " -- "server %s\n", clp->servername); -- goto out_return_error; -+ printerr(0, "ERROR: Failed to obtain machine " -+ "credentials for %s\n", clp->servicename); -+ goto out_return_error; - } -+*/ - for (ccname = credlist; ccname && *ccname; ccname++) { - gssd_setup_krb5_machine_gss_ccache(*ccname); -- if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid, -- AUTHTYPE_KRB5)) == 0) { -+ if ((gssd_create_lgd(clp, &lgd, &updata, -+ AUTHTYPE_KRB5)) == 0) { - /* Success! */ - success++; - break; - } - printerr(2, "WARNING: Failed to create krb5 context " - "for user with uid %d with credentials " -- "cache %s for server %s\n", -- uid, *ccname, clp->servername); -+ "cache %s for service %s\n", -+ updata.uid, *ccname, clp->servicename); - } - gssd_free_krb5_machine_cred_list(credlist); - if (!success) { -- printerr(0, "WARNING: Failed to create krb5 context " -+ printerr(0, "ERROR: Failed to create krb5 context " - "for user with uid %d with any " -- "credentials cache for server %s\n", -- uid, clp->servername); -+ "credentials cache for service %s\n", -+ updata.uid, clp->servicename); - goto out_return_error; - } - } - else { - /* Tell krb5 gss which credentials cache to use */ -- gssd_setup_krb5_user_gss_ccache(uid, clp->servername); -+ gssd_setup_krb5_user_gss_ccache(updata.uid, clp->servicename); - -- if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid, -- AUTHTYPE_KRB5)) != 0) { -+ if ((gssd_create_lgd(clp, &lgd, &updata, AUTHTYPE_KRB5)) != 0) { - printerr(0, "WARNING: Failed to create krb5 context " -- "for user with uid %d for server %s\n", -- uid, clp->servername); -+ "for user with uid %d for service %s\n", -+ updata.uid, clp->servicename); - goto out_return_error; - } - } - -- if (!authgss_get_private_data(auth, &pd)) { -- printerr(0, "WARNING: Failed to obtain authentication " -- "data for user with uid %d for server %s\n", -- uid, clp->servername); -- goto out_return_error; -- } -- -- if (serialize_context_for_kernel(pd.pd_ctx, &token, &krb5oid)) { -+ if (serialize_context_for_kernel(lgd.lgd_ctx, &token, &krb5oid)) { - printerr(0, "WARNING: Failed to serialize krb5 context for " -- "user with uid %d for server %s\n", -- uid, clp->servername); -+ "user with uid %d for service %s\n", -+ updata.uid, clp->servicename); - goto out_return_error; - } - -- do_downcall(clp->krb5_fd, uid, &pd, &token); -+ printerr(1, "refreshed: %u@%s for %s\n", -+ updata.uid, updata.obd, clp->servicename); -+ do_downcall(clp->krb5_fd, &updata, &lgd, &token); - - out: - if (token.value) - free(token.value); -- if (pd.pd_ctx_hndl.length != 0) -- authgss_free_private_data(&pd); -- if (auth) -- AUTH_DESTROY(auth); -- if (rpc_clnt) -- clnt_destroy(rpc_clnt); -- return; -+ -+ gssd_free_lgd(&lgd); -+ exit(0); /* i'm child process */ - - out_return_error: -- do_error_downcall(clp->krb5_fd, uid, -1); -+ do_error_downcall(clp->krb5_fd, updata.seq, -+ lgd.lgd_rpc_err, lgd.lgd_gss_err); - goto out; - } - -@@ -775,6 +1059,7 @@ out_return_error: - void - handle_spkm3_upcall(struct clnt_info *clp) - { -+#if 0 - uid_t uid; - CLIENT *rpc_clnt = NULL; - AUTH *auth = NULL; -@@ -826,4 +1111,5 @@ out: - out_return_error: - do_error_downcall(clp->spkm3_fd, uid, -1); - goto out; -+#endif - } -diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gss_util.c nfs-utils-1.0.11/utils/gssd/gss_util.c ---- nfs-utils-1.0.11.lustre/utils/gssd/gss_util.c 2007-02-21 21:50:03.000000000 -0700 -+++ nfs-utils-1.0.11/utils/gssd/gss_util.c 2008-01-02 18:11:38.000000000 -0700 -@@ -87,9 +87,16 @@ - #ifdef HAVE_COM_ERR_H - #include - #endif -+#include "lsupport.h" - - /* Global gssd_credentials handle */ --gss_cred_id_t gssd_creds; -+gss_cred_id_t gssd_cred_mds; -+gss_cred_id_t gssd_cred_oss; -+int gssd_cred_mds_valid = 0; -+int gssd_cred_oss_valid = 0; -+ -+char *mds_local_realm = NULL; -+char *oss_local_realm = NULL; - - gss_OID g_mechOid = GSS_C_NULL_OID;; - -@@ -183,15 +190,56 @@ pgsserr(char *msg, u_int32_t maj_stat, u - display_status_2(msg, maj_stat, min_stat, mech); - } - --int --gssd_acquire_cred(char *server_name) -+static -+int extract_realm_name(gss_buffer_desc *name, char **realm) -+{ -+ char *sname, *c; -+ int rc = 0; -+ -+ sname = malloc(name->length + 1); -+ if (!sname) { -+ printerr(0, "out of memory\n"); -+ return -ENOMEM; -+ } -+ -+ memcpy(sname, name->value, name->length); -+ sname[name->length] = '\0'; -+ printerr(1, "service principal: %s\n", sname); -+ -+ c = strchr(sname, '@'); -+ if (!c) { -+ printerr(2, "no realm found in principal, use default\n"); -+ *realm = strdup(this_realm); -+ if (!*realm) { -+ printerr(0, "failed to duplicate default realm\n"); -+ rc = -ENOMEM; -+ } -+ } else { -+ c++; -+ *realm = strdup(c); -+ if (!*realm) { -+ printerr(0, "failed to duplicated realm\n"); -+ rc = -ENOMEM; -+ } -+ } -+ free(sname); -+ -+ return rc; -+} -+ -+static -+int gssd_acquire_cred(char *server_name, gss_cred_id_t *cred, -+ char **local_realm, int *valid) - { - gss_buffer_desc name; - gss_name_t target_name; - u_int32_t maj_stat, min_stat; - u_int32_t ignore_maj_stat, ignore_min_stat; -+ gss_OID name_type; - gss_buffer_desc pbuf; - -+ *valid = 0; -+ - name.value = (void *)server_name; - name.length = strlen(server_name); - -@@ -201,12 +249,20 @@ gssd_acquire_cred(char *server_name) - - if (maj_stat != GSS_S_COMPLETE) { - pgsserr("gss_import_name", maj_stat, min_stat, g_mechOid); -- return (FALSE); -+ return -1; -+ } -+ -+ maj_stat = gss_display_name(&min_stat, target_name, &name, &name_type); -+ if (maj_stat != GSS_S_COMPLETE) { -+ pgsserr(0, maj_stat, min_stat, g_mechOid); -+ return -1; - } -+ if (extract_realm_name(&name, local_realm)) -+ return -1; - - maj_stat = gss_acquire_cred(&min_stat, target_name, 0, - GSS_C_NULL_OID_SET, GSS_C_ACCEPT, -- &gssd_creds, NULL, NULL); -+ cred, NULL, NULL); - - if (maj_stat != GSS_S_COMPLETE) { - pgsserr("gss_acquire_cred", maj_stat, min_stat, g_mechOid); -@@ -218,11 +274,67 @@ gssd_acquire_cred(char *server_name) - ignore_maj_stat = gss_release_buffer(&ignore_min_stat, - &pbuf); - } -- } -+ } else -+ *valid = 1; - - ignore_maj_stat = gss_release_name(&ignore_min_stat, &target_name); - -- return (maj_stat == GSS_S_COMPLETE); -+ if (maj_stat != GSS_S_COMPLETE) -+ return -1; -+ return 0; -+} -+ -+int gssd_prepare_creds(int must_srv_mds, int must_srv_oss) -+{ -+ if (gssd_acquire_cred(GSSD_SERVICE_MDS, &gssd_cred_mds, -+ &mds_local_realm, &gssd_cred_mds_valid)) { -+ if (must_srv_mds) -+ return -1; -+ } -+ -+ if (gssd_acquire_cred(GSSD_SERVICE_OSS, &gssd_cred_oss, -+ &oss_local_realm, &gssd_cred_oss_valid)) { -+ if (must_srv_oss) -+ return -1; -+ } -+ -+ if (!gssd_cred_mds_valid && !gssd_cred_oss_valid) { -+ printerr(0, "can't obtain both mds & oss creds, exit\n"); -+ return -1; -+ } -+ -+ if (gssd_cred_mds_valid) -+ printerr(0, "Ready to serve Lustre MDS in realm %s\n", -+ mds_local_realm ? mds_local_realm : "N/A"); -+ if (gssd_cred_oss_valid) -+ printerr(0, "Ready to serve Lustre OSS in realm %s\n", -+ oss_local_realm ? oss_local_realm : "N/A"); -+ -+ return 0; -+} -+ -+gss_cred_id_t gssd_select_svc_cred(int lustre_svc) -+{ -+ switch (lustre_svc) { -+ case LUSTRE_GSS_SVC_MDS: -+ if (!gssd_cred_mds_valid) { -+ printerr(0, "ERROR: service cred for mds not ready\n"); -+ return NULL; -+ } -+ printerr(2, "select mds service cred\n"); -+ return gssd_cred_mds; -+ case LUSTRE_GSS_SVC_OSS: -+ if (!gssd_cred_oss_valid) { -+ printerr(0, "ERROR: service cred for oss not ready\n"); -+ return NULL; -+ } -+ printerr(2, "select oss service cred\n"); -+ return gssd_cred_oss; -+ default: -+ printerr(0, "ERROR: invalid lustre svc id %d\n", lustre_svc); -+ } -+ -+ return NULL; - } - - int gssd_check_mechs(void) -@@ -249,3 +361,42 @@ out: - return retval; - } - -+/********************************* -+ * FIXME should be in krb5_util.c -+ *********************************/ -+ -+#include "krb5_util.h" -+ -+/* realm of this node */ -+char *this_realm = NULL; -+ -+int gssd_get_local_realm(void) -+{ -+ krb5_context context = NULL; -+ krb5_error_code code; -+ int retval = -1; -+ -+ if (this_realm != NULL) -+ return 0; -+ -+ code = krb5_init_context(&context); -+ if (code) { -+ printerr(0, "ERROR: get default realm: init ctx: %s\n", -+ error_message(code)); -+ goto out; -+ } -+ -+ code = krb5_get_default_realm(context, &this_realm); -+ if (code) { -+ printerr(0, "ERROR: get default realm: %s\n", -+ error_message(code)); -+ goto out; -+ } -+ retval = 0; -+ -+ printerr(1, "Local realm: %s\n", this_realm); -+out: -+ krb5_free_context(context); -+ return retval; -+} -+ -diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/gss_util.h nfs-utils-1.0.11/utils/gssd/gss_util.h ---- nfs-utils-1.0.11.lustre/utils/gssd/gss_util.h 2007-02-21 21:50:03.000000000 -0700 -+++ nfs-utils-1.0.11/utils/gssd/gss_util.h 2008-01-02 18:11:38.000000000 -0700 -@@ -32,14 +32,14 @@ - #define _GSS_UTIL_H_ - - #include --#include - #include "write_bytes.h" - -+char *this_realm; - extern gss_cred_id_t gssd_creds; - --int gssd_acquire_cred(char *server_name); - void pgsserr(char *msg, u_int32_t maj_stat, u_int32_t min_stat, - const gss_OID mech); - int gssd_check_mechs(void); -+int gssd_get_local_realm(void); - - #endif /* _GSS_UTIL_H_ */ -diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/krb5_util.c nfs-utils-1.0.11/utils/gssd/krb5_util.c ---- nfs-utils-1.0.11.lustre/utils/gssd/krb5_util.c 2008-01-02 17:22:48.000000000 -0700 -+++ nfs-utils-1.0.11/utils/gssd/krb5_util.c 2008-01-02 18:11:38.000000000 -0700 -@@ -99,12 +99,15 @@ - #include - #include - #include -+#include - #include - #include - -+#include - #include - #include - #include -+#include - #include - #include - #include -@@ -114,7 +117,6 @@ - #include - #endif - #include --#include - - #include "gssd.h" - #include "err_util.h" -@@ -129,6 +131,9 @@ struct gssd_k5_kt_princ *gssd_k5_kt_prin - int num_krb5_enctypes = 0; - krb5_enctype *krb5_enctypes = NULL; - -+/* credential expire time in advance */ -+unsigned long machine_cred_expire_advance = 300; /* 5 mins */ -+ - /*==========================*/ - /*=== Internal routines ===*/ - /*==========================*/ -@@ -137,11 +142,55 @@ static int select_krb5_ccache(const stru - static int gssd_find_existing_krb5_ccache(uid_t uid, struct dirent **d); - static int gssd_get_single_krb5_cred(krb5_context context, - krb5_keytab kt, struct gssd_k5_kt_princ *ple); --static int gssd_have_realm_ple(void *realm); - static int gssd_process_krb5_keytab(krb5_context context, krb5_keytab kt, - char *kt_name); - - /* -+ * convenient macros, these perhaps need further cleanup -+ */ -+#ifdef HAVE_KRB5 -+ -+#define KEYTAB_ENTRY_MATCH(kte, name) \ -+ ( \ -+ (kte).principal->data[0].length == (sizeof(name)-1) && \ -+ strncmp((kte).principal->data[0].data, (name), sizeof(name)-1) == 0 \ -+ ) -+#define KRB5_FREE_UNPARSED_NAME(ctx, name) \ -+ krb5_free_unparsed_name((ctx), (name)); -+#define KRB5_STRDUP(str) \ -+ strndup((str).data, (str).length) -+#define KRB5_STRCMP(str, name) \ -+ ( \ -+ (str)->length != strlen(name) || \ -+ strncmp((str)->data, (name), (str)->length) != 0 \ -+ ) -+#define KRB5_STRCASECMP(str, name) \ -+ ( \ -+ (str)->length != strlen(name) || \ -+ strncasecmp((str)->data, (name), (str)->length) != 0 \ -+ ) -+ -+#else /* !HAVE_KRB5 */ -+ -+#define KEYTAB_ENTRY_MATCH(kte, name) \ -+ ( \ -+ strlen((kte).principal->name.name_string.val[0]) == \ -+ (sizeof(name)-1) && \ -+ strncmp(kte.principal->name.name_string.val[0], (name), \ -+ sizeof(name)-1) == 0 \ -+ ) -+#define KRB5_FREE_UNPARSED_NAME(ctx, name) \ -+ free(pname); -+#define KRB5_STRDUP(str) \ -+ strdup(str) -+#define KRB5_STRCMP(str, name) \ -+ strcmp((str), (name)) -+#define KRB5_STRCASECMP(str, name) \ -+ strcmp((str), (name)) -+ -+#endif /* HAVE_KRB5 */ -+ -+/* - * Called from the scandir function to weed out potential krb5 - * credentials cache files - * -@@ -288,7 +337,7 @@ gssd_get_single_krb5_cred(krb5_context c - - memset(&my_creds, 0, sizeof(my_creds)); - -- if (ple->ccname && ple->endtime > now) { -+ if (ple->ccname && ple->endtime > now + machine_cred_expire_advance) { - printerr(2, "INFO: Credentials in CC '%s' are good until %d\n", - ple->ccname, ple->endtime); - code = 0; -@@ -308,6 +357,12 @@ gssd_get_single_krb5_cred(krb5_context c - /* set a short lifetime (for debugging only!) */ - printerr(0, "WARNING: Using (debug) short machine cred lifetime!\n"); - krb5_get_init_creds_opt_set_tkt_life(&options, 5*60); -+#else -+ /* FIXME try to get the ticket with lifetime as long as possible, -+ * to work around ticket-expiry + recovery problem in cmd3-11 -+ * remove this!!! -+ */ -+ krb5_get_init_creds_opt_set_tkt_life(&options, 30*24*60*60); - #endif - if ((code = krb5_get_init_creds_keytab(context, &my_creds, ple->princ, - kt, 0, NULL, &options))) { -@@ -319,11 +374,7 @@ gssd_get_single_krb5_cred(krb5_context c - "principal '%s' from keytab '%s'\n", - error_message(code), - pname ? pname : "", kt_name); --#ifdef HAVE_KRB5 -- if (pname) krb5_free_unparsed_name(context, pname); --#else -- if (pname) free(pname); --#endif -+ if (pname) KRB5_FREE_UNPARSED_NAME(context, pname); - goto out; - } - -@@ -372,15 +423,7 @@ gssd_get_single_krb5_cred(krb5_context c - return (code); - } - --/* -- * Determine if we already have a ple for the given realm -- * -- * Returns: -- * 0 => no ple found for given realm -- * 1 => found ple for given realm -- */ --static int --gssd_have_realm_ple(void *r) -+static struct gssd_k5_kt_princ * gssd_get_realm_ple(void *r) - { - struct gssd_k5_kt_princ *ple; - #ifdef HAVE_KRB5 -@@ -390,18 +433,76 @@ gssd_have_realm_ple(void *r) - #endif - - for (ple = gssd_k5_kt_princ_list; ple; ple = ple->next) { --#ifdef HAVE_KRB5 -- if ((realm->length == strlen(ple->realm)) && -- (strncmp(realm->data, ple->realm, realm->length) == 0)) { --#else -- if (strcmp(realm, ple->realm) == 0) { --#endif -- return 1; -- } -+ if (KRB5_STRCMP(realm, ple->realm) == 0) -+ return ple; -+ } -+ return NULL; -+} -+ -+static void gssd_free_ple(krb5_context kctx, struct gssd_k5_kt_princ *ple) -+{ -+ if (ple->princ) -+ krb5_free_principal(kctx, ple->princ); -+ if (ple->realm) -+ free(ple->realm); -+ if (ple->ccname) -+ free(ple->ccname); -+ free(ple); -+} -+ -+static int gssd_remove_ple(krb5_context kctx, struct gssd_k5_kt_princ *ple) -+{ -+ struct gssd_k5_kt_princ **prev = &gssd_k5_kt_princ_list; -+ struct gssd_k5_kt_princ *ent = gssd_k5_kt_princ_list; -+ -+ for (; ent; prev = &ent->next, ent = ent->next) { -+ if (ent != ple) -+ continue; -+ -+ *prev = ent->next; -+ gssd_free_ple(kctx, ent); -+ return 1; - } - return 0; - } - -+static -+struct gssd_k5_kt_princ *gssd_create_ple(krb5_context kctx, -+ krb5_principal principal) -+{ -+ struct gssd_k5_kt_princ *ple; -+ krb5_error_code code; -+ -+ ple = malloc(sizeof(*ple)); -+ if (ple == NULL) { -+ printerr(0, "ERROR: could not allocate storage " -+ "for principal list entry\n"); -+ return NULL; -+ } -+ -+ memset(ple, 0, sizeof(*ple)); -+ -+ ple->realm = KRB5_STRDUP(principal->realm); -+ if (ple->realm == NULL) { -+ printerr(0, "ERROR: not enough memory while copying realm to " -+ "principal list entry\n"); -+ goto err_free; -+ } -+ -+ code = krb5_copy_principal(kctx, principal, &ple->princ); -+ if (code) { -+ printerr(0, "ERROR: %s while copying principal " -+ "to principal list entry\n", -+ error_message(code)); -+ goto err_free; -+ } -+ -+ return ple; -+err_free: -+ gssd_free_ple(kctx, ple); -+ return NULL; -+} -+ - /* - * Process the given keytab file and create a list of principals we - * might use to perform mount operations. -@@ -445,82 +546,106 @@ gssd_process_krb5_keytab(krb5_context co - } - printerr(2, "Processing keytab entry for principal '%s'\n", - pname); --#ifdef HAVE_KRB5 -- if ( (kte.principal->data[0].length == GSSD_SERVICE_NAME_LEN) && -- (strncmp(kte.principal->data[0].data, GSSD_SERVICE_NAME, -- GSSD_SERVICE_NAME_LEN) == 0) && --#else -- if ( (strlen(kte.principal->name.name_string.val[0]) == GSSD_SERVICE_NAME_LEN) && -- (strncmp(kte.principal->name.name_string.val[0], GSSD_SERVICE_NAME, -- GSSD_SERVICE_NAME_LEN) == 0) && -- --#endif -- (!gssd_have_realm_ple((void *)&kte.principal->realm)) ) { -- printerr(2, "We will use this entry (%s)\n", pname); -- ple = malloc(sizeof(struct gssd_k5_kt_princ)); -- if (ple == NULL) { -- printerr(0, "ERROR: could not allocate storage " -- "for principal list entry\n"); --#ifdef HAVE_KRB5 -- krb5_free_unparsed_name(context, pname); --#else -- free(pname); --#endif -- retval = ENOMEM; -- goto out; -- } -- /* These will be filled in later */ -- ple->next = NULL; -- ple->ccname = NULL; -- ple->endtime = 0; -- if ((ple->realm = --#ifdef HAVE_KRB5 -- strndup(kte.principal->realm.data, -- kte.principal->realm.length)) --#else -- strdup(kte.principal->realm)) --#endif -- == NULL) { -- printerr(0, "ERROR: %s while copying realm to " -- "principal list entry\n", -- "not enough memory"); --#ifdef HAVE_KRB5 -- krb5_free_unparsed_name(context, pname); --#else -- free(pname); --#endif -- retval = ENOMEM; -- goto out; -- } -- if ((code = krb5_copy_principal(context, -- kte.principal, &ple->princ))) { -- printerr(0, "ERROR: %s while copying principal " -- "to principal list entry\n", -- error_message(code)); --#ifdef HAVE_KRB5 -- krb5_free_unparsed_name(context, pname); --#else -- free(pname); --#endif -- retval = code; -- goto out; -- } -- if (gssd_k5_kt_princ_list == NULL) -- gssd_k5_kt_princ_list = ple; -- else { -- ple->next = gssd_k5_kt_princ_list; -- gssd_k5_kt_princ_list = ple; -+ -+ /* mds service entry: -+ * - hostname and realm should match this node -+ * - replace existing non-mds entry of this realm -+ */ -+ if (KEYTAB_ENTRY_MATCH(kte, GSSD_SERVICE_MDS)) { -+ krb5_principal princ = kte.principal; -+ krb5_data *princ_host; -+ struct utsname utsbuf; -+ struct hostent *host; -+ -+ if (KRB5_STRCASECMP(krb5_princ_realm(context, princ), -+ this_realm) != 0) { -+ printerr(2, "alien mds service entry, skip\n"); -+ goto next; -+ } -+ -+ princ_host = krb5_princ_component(context, princ, 1); -+ if (princ_host == NULL) { -+ printerr(2, "mds service entry: no hostname in " -+ "principal, skip\n"); -+ goto next; -+ } -+ -+ if (uname(&utsbuf)) { -+ printerr(2, "mds service entry: unable to get " -+ "UTS name, skip\n"); -+ goto next; -+ } -+ host = gethostbyname(utsbuf.nodename); -+ if (host == NULL) { -+ printerr(2, "mds service entry: unable to get " -+ "local hostname, skip\n"); -+ goto next; -+ } -+ -+ if (KRB5_STRCASECMP(princ_host, host->h_name) != 0) { -+ printerr(2, "mds service entry: hostname " -+ "doesn't match: %s - %.*s, skip\n", -+ host->h_name, -+ princ_host->length, princ_host->data); -+ goto next; -+ } -+ -+ ple = gssd_get_realm_ple((void *)&kte.principal->realm); -+ if (ple) { -+ if (ple->fl_mds) { -+ printerr(2,"mds service entry: found a " -+ "duplicated one, it's like a " -+ "mis-configuration, skip\n"); -+ goto next; -+ } -+ -+ gssd_remove_ple(context, ple); -+ printerr(2, "mds service entry: replace an " -+ "existed non-mds one\n"); -+ } -+ } else if (KEYTAB_ENTRY_MATCH(kte, LUSTRE_ROOT_NAME)) { -+ ple = gssd_get_realm_ple((void *)&kte.principal->realm); -+ if (ple) { -+ if (ple->fl_mds || ple->fl_root) { -+ printerr(2, "root entry: found a " -+ "existed %s entry, skip\n", -+ ple->fl_mds ? "mds" : "root"); -+ goto next; -+ } -+ -+ gssd_remove_ple(context, ple); -+ printerr(2, "root entry: replace an existed " -+ "non-mds non-root one\n"); - } -- } -- else { -+ } else { - printerr(2, "We will NOT use this entry (%s)\n", - pname); -+ goto next; - } --#ifdef HAVE_KRB5 -- krb5_free_unparsed_name(context, pname); --#else -- free(pname); --#endif -+ -+ /* construct ple */ -+ printerr(2, "We will use this entry (%s)\n", pname); -+ ple = gssd_create_ple(context, kte.principal); -+ if (ple == NULL) { -+ KRB5_FREE_UNPARSED_NAME(context, pname); -+ goto out; -+ } -+ -+ /* add proper flags */ -+ if (KEYTAB_ENTRY_MATCH(kte, GSSD_SERVICE_MDS)) -+ ple->fl_mds = 1; -+ else if (KEYTAB_ENTRY_MATCH(kte, LUSTRE_ROOT_NAME)) -+ ple->fl_root = 1; -+ -+ /* enqueue */ -+ if (gssd_k5_kt_princ_list == NULL) -+ gssd_k5_kt_princ_list = ple; -+ else { -+ ple->next = gssd_k5_kt_princ_list; -+ gssd_k5_kt_princ_list = ple; -+ } -+ next: -+ KRB5_FREE_UNPARSED_NAME(context, pname); - } - - if ((code = krb5_kt_end_seq_get(context, kt, &cursor))) { -@@ -636,6 +761,7 @@ gssd_setup_krb5_user_gss_ccache(uid_t ui - printerr(2, "getting credentials for client with uid %u for " - "server %s\n", uid, servername); - memset(buf, 0, sizeof(buf)); -+ - if (gssd_find_existing_krb5_ccache(uid, &d)) { - snprintf(buf, sizeof(buf), "FILE:%s/%s", - ccachedir, d->d_name); -@@ -696,7 +822,7 @@ gssd_refresh_krb5_machine_creds(void) - goto out; - } - -- printerr(1, "Using keytab file '%s'\n", keytabfile); -+ printerr(2, "Using keytab file '%s'\n", keytabfile); - - if ((code = krb5_kt_resolve(context, keytabfile, &kt))) { - printerr(0, "ERROR: %s while resolving keytab '%s'\n", -@@ -711,12 +837,12 @@ gssd_refresh_krb5_machine_creds(void) - if (gssd_k5_kt_princ_list == NULL) { - printerr(0, "ERROR: No usable keytab entries found in " - "keytab '%s'\n", keytabfile); -- printerr(0, "Do you have a valid keytab entry for " -- "%s/@ in " -+ printerr(0, "You must have a valid keytab entry for " -+ "%s/@ on MDT nodes, " -+ "and %s@ on client nodes, in " - "keytab file %s ?\n", -- GSSD_SERVICE_NAME, keytabfile); -- printerr(0, "Continuing without (machine) credentials " -- "- nfs4 mounts with Kerberos will fail\n"); -+ GSSD_SERVICE_MDS, LUSTRE_ROOT_NAME, -+ keytabfile); - } - } - -@@ -866,6 +992,7 @@ gssd_destroy_krb5_machine_creds(void) - krb5_free_context(context); - } - -+#if 0 - #ifdef HAVE_SET_ALLOWABLE_ENCTYPES - /* - * this routine obtains a credentials handle via gss_acquire_cred() -@@ -921,7 +1048,9 @@ limit_krb5_enctypes(struct rpc_gss_sec * - return 0; - } - #endif /* HAVE_SET_ALLOWABLE_ENCTYPES */ -+#endif - -+#if 0 - /* - * Obtain supported enctypes from kernel. - * Set defaults if info is not available. -@@ -988,3 +1117,4 @@ gssd_obtain_kernel_krb5_info(void) - code); - } - } -+#endif -diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/krb5_util.h nfs-utils-1.0.11/utils/gssd/krb5_util.h ---- nfs-utils-1.0.11.lustre/utils/gssd/krb5_util.h 2008-01-02 17:22:48.000000000 -0700 -+++ nfs-utils-1.0.11/utils/gssd/krb5_util.h 2008-01-02 18:11:38.000000000 -0700 -@@ -10,6 +10,8 @@ - struct gssd_k5_kt_princ { - struct gssd_k5_kt_princ *next; - krb5_principal princ; -+ unsigned int fl_root:1, -+ fl_mds:1; - char *ccname; - char *realm; - krb5_timestamp endtime; -@@ -25,8 +27,4 @@ void gssd_destroy_krb5_machine_creds(voi - void gssd_obtain_kernel_krb5_info(void); - - --#ifdef HAVE_SET_ALLOWABLE_ENCTYPES --int limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid); --#endif -- - #endif /* KRB5_UTIL_H */ -diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/Makefile.am nfs-utils-1.0.11/utils/gssd/Makefile.am ---- nfs-utils-1.0.11.lustre/utils/gssd/Makefile.am 2007-02-21 21:50:03.000000000 -0700 -+++ nfs-utils-1.0.11/utils/gssd/Makefile.am 2008-01-02 18:10:29.000000000 -0700 -@@ -1,17 +1,11 @@ - ## Process this file with automake to produce Makefile.in - --man8_MANS = gssd.man svcgssd.man -- --RPCPREFIX = rpc. -+RPCPREFIX = - KPREFIX = @kprefix@ --sbin_PREFIXED = gssd svcgssd --sbin_PROGRAMS = $(sbin_PREFIXED) gss_clnt_send_err -+sbin_PREFIXED = lgssd lsvcgssd -+sbin_PROGRAMS = $(sbin_PREFIXED) - sbin_SCRIPTS = gss_destroy_creds - --EXTRA_DIST = \ -- gss_destroy_creds \ -- $(man8_MANS) -- - COMMON_SRCS = \ - context.c \ - context_mit.c \ -@@ -21,13 +15,15 @@ COMMON_SRCS = \ - gss_util.c \ - gss_oids.c \ - err_util.c \ -+ lsupport.c \ - \ - context.h \ - err_util.h \ - gss_oids.h \ -- gss_util.h -+ gss_util.h \ -+ lsupport.h - --gssd_SOURCES = \ -+lgssd_SOURCES = \ - $(COMMON_SRCS) \ - gssd.c \ - gssd_main_loop.c \ -@@ -38,13 +34,12 @@ gssd_SOURCES = \ - krb5_util.h \ - write_bytes.h - --gssd_LDADD = $(RPCSECGSS_LIBS) $(KRBLIBS) --gssd_LDFLAGS = $(KRBLDFLAGS) -+lgssd_LDADD = $(GSSAPI_LIBS) $(KRBLIBS) -+lgssd_LDFLAGS = $(KRBLDFLAGS) - --gssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \ -- $(RPCSECGSS_CFLAGS) $(KRBCFLAGS) -+lgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(GSSAPI_CFLAGS) $(KRBCFLAGS) - --svcgssd_SOURCES = \ -+lsvcgssd_SOURCES = \ - $(COMMON_SRCS) \ - cacheio.c \ - svcgssd.c \ -@@ -55,20 +50,11 @@ svcgssd_SOURCES = \ - cacheio.h \ - svcgssd.h - --svcgssd_LDADD = \ -- ../../support/nfs/libnfs.a \ -- $(RPCSECGSS_LIBS) -lnfsidmap \ -- $(KRBLIBS) -- --svcgssd_LDFLAGS = $(KRBLDFLAGS) -- --svcgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \ -- $(RPCSECGSS_CFLAGS) $(KRBCFLAGS) -+lsvcgssd_LDADD = $(GSSAPI_LIBS) $(KRBLIBS) - --gss_clnt_send_err_SOURCES = gss_clnt_send_err.c -+lsvcgssd_LDFLAGS = $(KRBLDFLAGS) - --gss_clnt_send_err_CFLAGS = $(AM_CFLAGS) $(CFLAGS) \ -- $(RPCSECGSS_CFLAGS) $(KRBCFLAGS) -+lsvcgssd_CFLAGS = $(AM_CFLAGS) $(CFLAGS) $(GSSAPI_CFLAGS) $(KRBCFLAGS) - - MAINTAINERCLEANFILES = Makefile.in - -@@ -92,23 +78,3 @@ uninstall-hook: - done) - - --# XXX This makes some assumptions about what automake does. --# XXX But there is no install-man-hook or install-man-local. --install-man: install-man8 install-man-links --uninstall-man: uninstall-man8 uninstall-man-links -- --install-man-links: -- (cd $(DESTDIR)$(man8dir) && \ -- for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \ -- inst=`echo $$m | sed -e 's/man$$/8/'`; \ -- rm -f $(RPCPREFIX)$$inst ; \ -- $(LN_S) $$inst $(RPCPREFIX)$$inst ; \ -- done) -- --uninstall-man-links: -- (cd $(DESTDIR)$(man8dir) && \ -- for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \ -- inst=`echo $$m | sed -e 's/man$$/8/'`; \ -- rm -f $(RPCPREFIX)$$inst ; \ -- done) -- -diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/svcgssd.c nfs-utils-1.0.11/utils/gssd/svcgssd.c ---- nfs-utils-1.0.11.lustre/utils/gssd/svcgssd.c 2007-02-21 21:50:03.000000000 -0700 -+++ nfs-utils-1.0.11/utils/gssd/svcgssd.c 2008-01-02 18:11:38.000000000 -0700 -@@ -43,7 +43,6 @@ - #include - #include - #include --#include - #include - #include - -@@ -54,11 +53,33 @@ - #include - #include - #include --#include --#include "nfslib.h" -+#include - #include "svcgssd.h" - #include "gss_util.h" - #include "err_util.h" -+#include "lsupport.h" -+ -+void -+closeall(int min) -+{ -+ DIR *dir = opendir("/proc/self/fd"); -+ if (dir != NULL) { -+ int dfd = dirfd(dir); -+ struct dirent *d; -+ -+ while ((d = readdir(dir)) != NULL) { -+ char *endp; -+ long n = strtol(d->d_name, &endp, 10); -+ if (*endp != '\0' && n >= min && n != dfd) -+ (void) close(n); -+ } -+ closedir(dir); -+ } else { -+ int fd = sysconf(_SC_OPEN_MAX); -+ while (--fd >= min) -+ (void) close(fd); -+ } -+} - - /* - * mydaemon creates a pipe between the partent and child -@@ -140,6 +161,7 @@ void - sig_die(int signal) - { - /* destroy krb5 machine creds */ -+ cleanup_mapping(); - printerr(1, "exiting on signal %d\n", signal); - exit(1); - } -@@ -155,7 +177,7 @@ sig_hup(int signal) - static void - usage(char *progname) - { -- fprintf(stderr, "usage: %s [-n] [-f] [-v] [-r] [-i]\n", -+ fprintf(stderr, "usage: %s [-n] [-f] [-v] [-r] [-m] [-o]\n", - progname); - exit(1); - } -@@ -166,9 +188,8 @@ main(int argc, char *argv[]) - int get_creds = 1; - int fg = 0; - int verbosity = 0; -- int rpc_verbosity = 0; -- int idmap_verbosity = 0; - int opt; -+ int must_srv_mds = 0, must_srv_oss = 0; - extern char *optarg; - char *progname; - -@@ -177,17 +198,19 @@ main(int argc, char *argv[]) - case 'f': - fg = 1; - break; -- case 'i': -- idmap_verbosity++; -- break; - case 'n': - get_creds = 0; - break; - case 'v': - verbosity++; - break; -- case 'r': -- rpc_verbosity++; -+ case 'm': -+ get_creds = 1; -+ must_srv_mds = 1; -+ break; -+ case 'o': -+ get_creds = 1; -+ must_srv_oss = 1; - break; - default: - usage(argv[0]); -@@ -201,34 +224,18 @@ main(int argc, char *argv[]) - progname = argv[0]; - - initerr(progname, verbosity, fg); --#ifdef HAVE_AUTHGSS_SET_DEBUG_LEVEL -- authgss_set_debug_level(rpc_verbosity); --#else -- if (rpc_verbosity > 0) -- printerr(0, "Warning: rpcsec_gss library does not " -- "support setting debug level\n"); --#endif --#ifdef HAVE_NFS4_SET_DEBUG -- nfs4_set_debug(idmap_verbosity, NULL); --#else -- if (idmap_verbosity > 0) -- printerr(0, "Warning: your nfsidmap library does not " -- "support setting debug level\n"); --#endif - - if (gssd_check_mechs() != 0) { - printerr(0, "ERROR: Problem with gssapi library\n"); - exit(1); - } - -- if (!fg) -- mydaemon(0, 0); -- -- signal(SIGINT, sig_die); -- signal(SIGTERM, sig_die); -- signal(SIGHUP, sig_hup); -- -- if (get_creds && !gssd_acquire_cred(GSSD_SERVICE_NAME)) { -+ if (gssd_get_local_realm()) { -+ printerr(0, "ERROR: Can't get Local Kerberos realm\n"); -+ exit(1); -+ } -+ -+ if (get_creds && gssd_prepare_creds(must_srv_mds, must_srv_oss)) { - printerr(0, "unable to obtain root (machine) credentials\n"); - printerr(0, "do you have a keytab entry for " - "nfs/@ in " -@@ -237,9 +244,23 @@ main(int argc, char *argv[]) - } - - if (!fg) -+ mydaemon(0, 0); -+ -+ /* -+ * XXX: There is risk of memory leak for missing call -+ * cleanup_mapping() for SIGKILL and SIGSTOP. -+ */ -+ signal(SIGINT, sig_die); -+ signal(SIGTERM, sig_die); -+ signal(SIGHUP, sig_hup); -+ -+ if (!fg) - release_parent(); - -- gssd_run(); -+ gssd_init_unique(GSSD_SVC); -+ -+ svcgssd_run(); -+ cleanup_mapping(); - printerr(0, "gssd_run returned!\n"); - abort(); - } -diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/svcgssd.h nfs-utils-1.0.11/utils/gssd/svcgssd.h ---- nfs-utils-1.0.11.lustre/utils/gssd/svcgssd.h 2007-02-21 21:50:03.000000000 -0700 -+++ nfs-utils-1.0.11/utils/gssd/svcgssd.h 2008-01-02 18:11:38.000000000 -0700 -@@ -35,9 +35,20 @@ - #include - #include - --void handle_nullreq(FILE *f); --void gssd_run(void); -+int handle_nullreq(FILE *f); -+void svcgssd_run(void); -+int gssd_prepare_creds(int must_srv_mds, int must_srv_oss); -+gss_cred_id_t gssd_select_svc_cred(int lustre_svc); - --#define GSSD_SERVICE_NAME "nfs" -+extern char *mds_local_realm; -+extern char *oss_local_realm; -+ -+#define GSSD_SERVICE_NAME "lustre" -+ -+/* XXX */ -+#define GSSD_SERVICE_MDS "lustre_mds" -+#define GSSD_SERVICE_OSS "lustre_oss" -+#define LUSTRE_ROOT_NAME "lustre_root" -+#define LUSTRE_ROOT_NAMELEN 11 - - #endif /* _RPC_SVCGSSD_H_ */ -diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/svcgssd_main_loop.c nfs-utils-1.0.11/utils/gssd/svcgssd_main_loop.c ---- nfs-utils-1.0.11.lustre/utils/gssd/svcgssd_main_loop.c 2007-02-21 21:50:03.000000000 -0700 -+++ nfs-utils-1.0.11/utils/gssd/svcgssd_main_loop.c 2008-01-02 18:11:38.000000000 -0700 -@@ -42,50 +42,72 @@ - #include - #include - #include -+/* For nanosleep() */ -+#include - - #include "svcgssd.h" - #include "err_util.h" - -+/* -+ * nfs4 in-kernel cache implementation make upcall failed directly -+ * if there's no listener detected. so here we should keep the init -+ * channel file open as possible as we can. -+ * -+ * unfortunately the proc doesn't support dir change notification. -+ * and when an entry get unlinked, we only got POLLIN event once, -+ * it's the only oppotunity we can close the file and startover. -+ */ - void --gssd_run() -+svcgssd_run() - { - int ret; -- FILE *f; -+ FILE *f = NULL; - struct pollfd pollfd; -+ struct timespec halfsec = { .tv_sec = 0, .tv_nsec = 500000000 }; - --#define NULLRPC_FILE "/proc/net/rpc/auth.rpcsec.init/channel" -+#define NULLRPC_FILE "/proc/net/rpc/auth.sptlrpc.init/channel" - -- f = fopen(NULLRPC_FILE, "rw"); -- -- if (!f) { -- printerr(0, "failed to open %s: %s\n", -- NULLRPC_FILE, strerror(errno)); -- exit(1); -- } -- pollfd.fd = fileno(f); -- pollfd.events = POLLIN; - while (1) { - int save_err; - -+ while (f == NULL) { -+ f = fopen(NULLRPC_FILE, "rw"); -+ if (f == NULL) { -+ printerr(4, "failed to open %s: %s\n", -+ NULLRPC_FILE, strerror(errno)); -+ nanosleep(&halfsec, NULL); -+ } else { -+ printerr(1, "successfully open %s\n", -+ NULLRPC_FILE); -+ break; -+ } -+ } -+ pollfd.fd = fileno(f); -+ pollfd.events = POLLIN; -+ - pollfd.revents = 0; -- printerr(1, "entering poll\n"); -- ret = poll(&pollfd, 1, -1); -+ ret = poll(&pollfd, 1, 1000); - save_err = errno; -- printerr(1, "leaving poll\n"); -+ - if (ret < 0) { -- if (save_err != EINTR) -- printerr(0, "error return from poll: %s\n", -- strerror(save_err)); -+ printerr(0, "error return from poll: %s\n", -+ strerror(save_err)); -+ fclose(f); -+ f = NULL; - } else if (ret == 0) { -- /* timeout; shouldn't happen. */ -+ printerr(3, "poll timeout\n"); - } else { - if (ret != 1) { - printerr(0, "bug: unexpected poll return %d\n", - ret); - exit(1); - } -- if (pollfd.revents & POLLIN) -- handle_nullreq(f); -+ if (pollfd.revents & POLLIN) { -+ if (handle_nullreq(f) < 0) { -+ fclose(f); -+ f = NULL; -+ } -+ } - } - } - } -diff -Nrup nfs-utils-1.0.11.lustre/utils/gssd/svcgssd_proc.c nfs-utils-1.0.11/utils/gssd/svcgssd_proc.c ---- nfs-utils-1.0.11.lustre/utils/gssd/svcgssd_proc.c 2007-02-21 21:50:03.000000000 -0700 -+++ nfs-utils-1.0.11/utils/gssd/svcgssd_proc.c 2008-01-02 18:11:38.000000000 -0700 -@@ -35,7 +35,6 @@ - - #include - #include --#include - - #include - #include -@@ -44,25 +43,28 @@ - #include - #include - #include --#include -+#include - - #include "svcgssd.h" - #include "gss_util.h" - #include "err_util.h" - #include "context.h" - #include "cacheio.h" -+#include "lsupport.h" - - extern char * mech2file(gss_OID mech); --#define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.rpcsec.context/channel" --#define SVCGSSD_INIT_CHANNEL "/proc/net/rpc/auth.rpcsec.init/channel" -+#define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.sptlrpc.context/channel" -+#define SVCGSSD_INIT_CHANNEL "/proc/net/rpc/auth.sptlrpc.init/channel" - - #define TOKEN_BUF_SIZE 8192 - - struct svc_cred { -- uid_t cr_uid; -- gid_t cr_gid; -- int cr_ngroups; -- gid_t cr_groups[NGROUPS]; -+ uint32_t cr_remote; -+ uint32_t cr_usr_root; -+ uint32_t cr_usr_mds; -+ uid_t cr_uid; -+ uid_t cr_mapped_uid; -+ uid_t cr_gid; - }; - - static int -@@ -70,11 +72,10 @@ do_svc_downcall(gss_buffer_desc *out_han - gss_OID mech, gss_buffer_desc *context_token) - { - FILE *f; -- int i; - char *fname = NULL; - int err; - -- printerr(1, "doing downcall\n"); -+ printerr(2, "doing downcall\n"); - if ((fname = mech2file(mech)) == NULL) - goto out_err; - f = fopen(SVCGSSD_CONTEXT_CHANNEL, "w"); -@@ -87,11 +88,12 @@ do_svc_downcall(gss_buffer_desc *out_han - qword_printhex(f, out_handle->value, out_handle->length); - /* XXX are types OK for the rest of this? */ - qword_printint(f, 0x7fffffff); /*XXX need a better timeout */ -+ 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_mapped_uid); - qword_printint(f, cred->cr_uid); - qword_printint(f, cred->cr_gid); -- qword_printint(f, cred->cr_ngroups); -- for (i=0; i < cred->cr_ngroups; i++) -- qword_printint(f, cred->cr_groups[i]); - qword_print(f, fname); - qword_printhex(f, context_token->value, context_token->length); - err = qword_eol(f); -@@ -120,7 +122,7 @@ send_response(FILE *f, gss_buffer_desc * - /* XXXARG: */ - int g; - -- printerr(1, "sending null reply\n"); -+ printerr(2, "sending null reply\n"); - - qword_addhex(&bp, &blen, in_handle->value, in_handle->length); - qword_addhex(&bp, &blen, in_token->value, in_token->length); -@@ -160,6 +162,7 @@ send_response(FILE *f, gss_buffer_desc * - #define rpcsec_gsserr_credproblem 13 - #define rpcsec_gsserr_ctxproblem 14 - -+#if 0 - static void - add_supplementary_groups(char *secname, char *name, struct svc_cred *cred) - { -@@ -183,7 +186,9 @@ add_supplementary_groups(char *secname, - } - } - } -+#endif - -+#if 0 - static int - get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred) - { -@@ -249,7 +254,9 @@ out_free: - out: - return res; - } -+#endif - -+#if 0 - void - print_hexl(int pri, unsigned char *cp, int length) - { -@@ -286,12 +293,149 @@ print_hexl(int pri, unsigned char *cp, i - printerr(pri,"\n"); - } - } -+#endif - --void -+static int -+get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred, -+ lnet_nid_t nid, uint32_t lustre_svc) -+{ -+ u_int32_t maj_stat, min_stat; -+ gss_buffer_desc name; -+ char *sname, *host, *realm; -+ const int namebuf_size = 512; -+ char namebuf[namebuf_size]; -+ int res = -1; -+ 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_uid = cred->cr_mapped_uid = cred->cr_gid = -1; -+ -+ maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type); -+ if (maj_stat != GSS_S_COMPLETE) { -+ pgsserr("get_ids: gss_display_name", -+ maj_stat, min_stat, mech); -+ return -1; -+ } -+ if (name.length >= 0xffff || /* be certain name.length+1 doesn't overflow */ -+ !(sname = calloc(name.length + 1, 1))) { -+ printerr(0, "WARNING: get_ids: error allocating %d bytes " -+ "for sname\n", name.length + 1); -+ gss_release_buffer(&min_stat, &name); -+ return -1; -+ } -+ memcpy(sname, name.value, name.length); -+ gss_release_buffer(&min_stat, &name); -+ -+ if (lustre_svc == LUSTRE_GSS_SVC_MDS) -+ lookup_mapping(sname, nid, &cred->cr_mapped_uid); -+ else -+ cred->cr_mapped_uid = -1; -+ -+ realm = strchr(sname, '@'); -+ if (realm) -+ *realm++ = '\0'; -+ -+ host = strchr(sname, '/'); -+ if (host) -+ *host++ = '\0'; -+ -+ if (strcmp(sname, GSSD_SERVICE_OSS) == 0) { -+ printerr(0, "forbid "GSSD_SERVICE_OSS" as user name\n"); -+ goto out_free; -+ } -+ -+ /* 1. check host part */ -+ if (host) { -+ if (lnet_nid2hostname(nid, namebuf, namebuf_size)) { -+ printerr(0, "ERROR: failed to resolve hostname for " -+ "%s/%s@%s from %016llx\n", -+ sname, host, realm, nid); -+ goto out_free; -+ } -+ -+ if (strcasecmp(host, namebuf)) { -+ printerr(0, "ERROR: %s/%s@s claimed hostname doesn't " -+ "match %s, nid %016llx\n", sname, host, realm, -+ namebuf, nid); -+ 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 ? realm : "", nid); -+ goto out_free; -+ } -+ } -+ -+ /* 2. check realm */ -+ if (!realm) { -+ /* just deny it -+ cred->cr_remote = (mds_local_realm != NULL); -+ */ -+ printerr(0, "ERROR: %s%s%s have no realm name\n", -+ sname, host ? "/" : "", host ? "host" : ""); -+ goto out_free; -+ } -+ -+ if (!mds_local_realm || strcasecmp(mds_local_realm, realm)) { -+ cred->cr_remote = 1; -+ -+ if (cred->cr_mapped_uid == -1) -+ printerr(0, "ERROR: %s from %016llx is remote but " -+ "without mapping\n", sname, nid); -+ /* mapped, skip user checking */ -+ goto out_free; -+ } -+ -+ /* 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); -+ } -+ -+ printerr(1, "%s: authenticated %s%s%s@%s from %016llx\n", -+ lustre_svc_name[lustre_svc], sname, -+ host ? "/" : "", host ? host : "", realm, nid); -+ res = 0; -+out_free: -+ free(sname); -+ return res; -+} -+ -+typedef struct gss_union_ctx_id_t { -+ gss_OID mech_type; -+ gss_ctx_id_t internal_ctx_id; -+} gss_union_ctx_id_desc, *gss_union_ctx_id_t; -+ -+/* -+ * return -1 only if we detect error during reading from upcall channel, -+ * all other cases return 0. -+ */ -+int - handle_nullreq(FILE *f) { -- /* XXX initialize to a random integer to reduce chances of unnecessary -- * invalidation of existing ctx's on restarting svcgssd. */ -- static u_int32_t handle_seq = 0; -+ uint64_t handle_seq; - char in_tok_buf[TOKEN_BUF_SIZE]; - char in_handle_buf[15]; - char out_handle_buf[15]; -@@ -303,10 +447,13 @@ handle_nullreq(FILE *f) { - ignore_out_tok = {.value = NULL}, - /* XXX isn't there a define for this?: */ - null_token = {.value = NULL}; -+ uint32_t lustre_svc; -+ lnet_nid_t nid; - u_int32_t ret_flags; - gss_ctx_id_t ctx = GSS_C_NO_CONTEXT; - gss_name_t client_name; - gss_OID mech = GSS_C_NO_OID; -+ gss_cred_id_t svc_cred; - u_int32_t maj_stat = GSS_S_FAILURE, min_stat = 0; - u_int32_t ignore_min_stat; - struct svc_cred cred; -@@ -314,25 +461,31 @@ handle_nullreq(FILE *f) { - static int lbuflen = 0; - static char *cp; - -- printerr(1, "handling null request\n"); -+ printerr(2, "handling null request\n"); - - if (readline(fileno(f), &lbuf, &lbuflen) != 1) { - printerr(0, "WARNING: handle_nullreq: " - "failed reading request\n"); -- return; -+ return -1; - } - - cp = lbuf; - -+ qword_get(&cp, (char *) &lustre_svc, sizeof(lustre_svc)); -+ qword_get(&cp, (char *) &nid, sizeof(nid)); -+ qword_get(&cp, (char *) &handle_seq, sizeof(handle_seq)); -+ printerr(2, "handling req: svc %u, nid %016llx, idx %llx\n", -+ lustre_svc, nid, handle_seq); -+ - in_handle.length = (size_t) qword_get(&cp, in_handle.value, - sizeof(in_handle_buf)); -- printerr(2, "in_handle: \n"); -- print_hexl(2, in_handle.value, in_handle.length); -+ printerr(3, "in_handle: \n"); -+ print_hexl(3, in_handle.value, in_handle.length); - - in_tok.length = (size_t) qword_get(&cp, in_tok.value, - sizeof(in_tok_buf)); -- printerr(2, "in_tok: \n"); -- print_hexl(2, in_tok.value, in_tok.length); -+ printerr(3, "in_tok: \n"); -+ print_hexl(3, in_tok.value, in_tok.length); - - if (in_tok.length < 0) { - printerr(0, "WARNING: handle_nullreq: " -@@ -352,7 +505,13 @@ handle_nullreq(FILE *f) { - memcpy(&ctx, in_handle.value, in_handle.length); - } - -- maj_stat = gss_accept_sec_context(&min_stat, &ctx, gssd_creds, -+ svc_cred = gssd_select_svc_cred(lustre_svc); -+ if (!svc_cred) { -+ printerr(0, "no service credential for svc %u\n", lustre_svc); -+ goto out_err; -+ } -+ -+ maj_stat = gss_accept_sec_context(&min_stat, &ctx, svc_cred, - &in_tok, GSS_C_NO_CHANNEL_BINDINGS, &client_name, - &mech, &out_tok, &ret_flags, NULL, NULL); - -@@ -370,7 +529,8 @@ handle_nullreq(FILE *f) { - maj_stat, min_stat, mech); - goto out_err; - } -- if (get_ids(client_name, mech, &cred)) { -+ -+ if (get_ids(client_name, mech, &cred, nid, lustre_svc)) { - /* get_ids() prints error msg */ - maj_stat = GSS_S_BAD_NAME; /* XXX ? */ - gss_release_name(&ignore_min_stat, &client_name); -@@ -378,10 +538,8 @@ handle_nullreq(FILE *f) { - } - gss_release_name(&ignore_min_stat, &client_name); - -- - /* Context complete. Pass handle_seq in out_handle to use - * for context lookup in the kernel. */ -- handle_seq++; - out_handle.length = sizeof(handle_seq); - memcpy(out_handle.value, &handle_seq, sizeof(handle_seq)); - -@@ -405,8 +563,7 @@ out: - free(ctx_token.value); - if (out_tok.value != NULL) - gss_release_buffer(&ignore_min_stat, &out_tok); -- printerr(1, "finished handling null request\n"); -- return; -+ return 0; - - out_err: - if (ctx != GSS_C_NO_CONTEXT) -diff -Nrup nfs-utils-1.0.11.lustre/utils/Makefile.am nfs-utils-1.0.11/utils/Makefile.am ---- nfs-utils-1.0.11.lustre/utils/Makefile.am 2007-02-21 21:50:03.000000000 -0700 -+++ nfs-utils-1.0.11/utils/Makefile.am 2008-01-02 18:10:29.000000000 -0700 -@@ -2,30 +2,6 @@ - - OPTDIRS = - --if CONFIG_RQUOTAD --OPTDIRS += rquotad --endif -- --if CONFIG_NFSV4 --OPTDIRS += idmapd --endif -- --if CONFIG_GSS --OPTDIRS += gssd --endif -- --if CONFIG_MOUNT --OPTDIRS += mount --endif -- --SUBDIRS = \ -- exportfs \ -- lockd \ -- mountd \ -- nfsd \ -- nfsstat \ -- showmount \ -- statd \ -- $(OPTDIRS) -+SUBDIRS = gssd - - MAINTAINERCLEANFILES = Makefile.in diff --git a/lustre/utils/gss/sk_utils.c b/lustre/utils/gss/sk_utils.c old mode 100755 new mode 100644