-diff -rup nfs-utils-1.0.10.orig/configure.in nfs-utils-1.0.10/configure.in
---- nfs-utils-1.0.10.orig/configure.in 2006-11-15 21:26:08.000000000 -0700
-+++ nfs-utils-1.0.10/configure.in 2006-12-15 15:11:52.000000000 -0700
+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)
+ utils/gssd/Makefile])
AC_OUTPUT
-diff -rup nfs-utils-1.0.10.orig/Makefile.am nfs-utils-1.0.10/Makefile.am
---- nfs-utils-1.0.10.orig/Makefile.am 2006-11-15 21:26:08.000000000 -0700
-+++ nfs-utils-1.0.10/Makefile.am 2006-12-15 15:11:52.000000000 -0700
+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
MAINTAINERCLEANFILES = Makefile.in
-diff -rup nfs-utils-1.0.10.orig/utils/gssd/cacheio.c nfs-utils-1.0.10/utils/gssd/cacheio.c
---- nfs-utils-1.0.10.orig/utils/gssd/cacheio.c 2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/cacheio.c 2006-12-15 15:12:23.000000000 -0700
+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++;
return len;
}
-diff -rup nfs-utils-1.0.10.orig/utils/gssd/context.c nfs-utils-1.0.10/utils/gssd/context.c
---- nfs-utils-1.0.10.orig/utils/gssd/context.c 2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/context.c 2006-12-15 15:12:23.000000000 -0700
+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 <syslog.h>
#include <string.h>
#include "gss_util.h"
#include "gss_oids.h"
#include "err_util.h"
-diff -rup nfs-utils-1.0.10.orig/utils/gssd/context.h nfs-utils-1.0.10/utils/gssd/context.h
---- nfs-utils-1.0.10.orig/utils/gssd/context.h 2006-11-15 21:26:08.000000000 -0700
-+++ nfs-utils-1.0.10/utils/gssd/context.h 2006-12-15 15:12:23.000000000 -0700
+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_
/* Hopefully big enough to hold any serialized context */
#define MAX_CTX_LEN 4096
-diff -rup nfs-utils-1.0.10.orig/utils/gssd/context_lucid.c nfs-utils-1.0.10/utils/gssd/context_lucid.c
---- nfs-utils-1.0.10.orig/utils/gssd/context_lucid.c 2006-11-15 21:26:08.000000000 -0700
-+++ nfs-utils-1.0.10/utils/gssd/context_lucid.c 2006-12-15 15:12:23.000000000 -0700
+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 <syslog.h>
#include <string.h>
/* derive and send down: Ke, Ki, and Kc */
-diff -rup nfs-utils-1.0.10.orig/utils/gssd/context_mit.c nfs-utils-1.0.10/utils/gssd/context_mit.c
---- nfs-utils-1.0.10.orig/utils/gssd/context_mit.c 2006-11-15 21:26:08.000000000 -0700
-+++ nfs-utils-1.0.10/utils/gssd/context_mit.c 2006-12-15 15:12:23.000000000 -0700
+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 <errno.h>
#include <gssapi/gssapi.h>
if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
/* Only applicable flag for this is initiator */
-diff -rup nfs-utils-1.0.10.orig/utils/gssd/context_spkm3.c nfs-utils-1.0.10/utils/gssd/context_spkm3.c
---- nfs-utils-1.0.10.orig/utils/gssd/context_spkm3.c 2006-11-15 21:26:08.000000000 -0700
-+++ nfs-utils-1.0.10/utils/gssd/context_spkm3.c 2006-12-15 15:12:23.000000000 -0700
+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 <syslog.h>
#include <string.h>
#include "gss_util.h"
#include "gss_oids.h"
#include "err_util.h"
-diff -rup nfs-utils-1.0.10.orig/utils/gssd/err_util.c nfs-utils-1.0.10/utils/gssd/err_util.c
---- nfs-utils-1.0.10.orig/utils/gssd/err_util.c 2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/err_util.c 2006-12-15 15:12:23.000000000 -0700
+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 <stdarg.h>
#include <syslog.h>
+ }
+}
+
-diff -rup nfs-utils-1.0.10.orig/utils/gssd/err_util.h nfs-utils-1.0.10/utils/gssd/err_util.h
---- nfs-utils-1.0.10.orig/utils/gssd/err_util.h 2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/err_util.h 2006-12-15 15:12:23.000000000 -0700
+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 print_hexl(int pri, unsigned char *cp, int length);
#endif /* _ERR_UTIL_H_ */
-diff -rup nfs-utils-1.0.10.orig/utils/gssd/gss_clnt_send_err.c nfs-utils-1.0.10/utils/gssd/gss_clnt_send_err.c
---- nfs-utils-1.0.10.orig/utils/gssd/gss_clnt_send_err.c 2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/gss_clnt_send_err.c 2006-12-15 15:12:23.000000000 -0700
+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"
exit(0);
}
+#endif
-diff -rup nfs-utils-1.0.10.orig/utils/gssd/gssd.c nfs-utils-1.0.10/utils/gssd/gssd.c
---- nfs-utils-1.0.10.orig/utils/gssd/gssd.c 2006-11-15 21:26:08.000000000 -0700
-+++ nfs-utils-1.0.10/utils/gssd/gssd.c 2006-12-15 15:12:23.000000000 -0700
+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"
+ printerr(0, "lgssd exiting\n");
+ return 0;
}
-diff -rup nfs-utils-1.0.10.orig/utils/gssd/gssd.h nfs-utils-1.0.10/utils/gssd/gssd.h
---- nfs-utils-1.0.10.orig/utils/gssd/gssd.h 2006-11-15 21:26:08.000000000 -0700
-+++ nfs-utils-1.0.10/utils/gssd/gssd.h 2006-12-15 15:12:23.000000000 -0700
+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"
+void lgssd_mutex_put(int semid);
#endif /* _RPC_GSSD_H_ */
-diff -rup nfs-utils-1.0.10.orig/utils/gssd/gssd_main_loop.c nfs-utils-1.0.10/utils/gssd/gssd_main_loop.c
---- nfs-utils-1.0.10.orig/utils/gssd/gssd_main_loop.c 2006-11-15 21:26:08.000000000 -0700
-+++ nfs-utils-1.0.10/utils/gssd/gssd_main_loop.c 2006-12-15 15:12:23.000000000 -0700
+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)
};
close(fd);
return;
}
-diff -rup nfs-utils-1.0.10.orig/utils/gssd/gssd_proc.c nfs-utils-1.0.10/utils/gssd/gssd_proc.c
---- nfs-utils-1.0.10.orig/utils/gssd/gssd_proc.c 2006-11-15 21:26:08.000000000 -0700
-+++ nfs-utils-1.0.10/utils/gssd/gssd_proc.c 2006-12-15 15:12:23.000000000 -0700
+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"
+ printerr(2, "successfully refreshed lgd\n");
+ return 0;
+}
-+
+
+static
+int gssd_create_lgd(struct clnt_info *clp,
+ struct lustre_gss_data *lgd,
+ 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)
/*
* this code uses the userland rpcsec gss library to create a krb5
-@@ -668,27 +910,78 @@ int create_auth_rpc_client(struct clnt_i
+@@ -668,103 +910,145 @@ int create_auth_rpc_client(struct clnt_i
void
handle_krb5_upcall(struct clnt_info *clp)
{
+ 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) {
+ return;
+ }
+
-+ printerr(1, "krb5 upcall: seq %u, uid %u, svc %u, nid 0x%llx, "
-+ "pag %llx, obd %s\n", updata.seq, updata.uid, updata.svc,
-+ updata.nid, updata.pag, updata.obd);
++ 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);
+
-+ /* XXX in kernel pag is defined as "unsigned long", which might
-+ * not keep original signed value after converted to u64.
-+ */
-+ if (updata.pag != updata.uid &&
-+ ((updata.pag == 0xffffffffffffffffULL) ||
-+ (updata.pag == 0xffffffff))) {
-+ printerr(0, "uid %u: pag %llx not allowed\n",
-+ updata.uid, updata.pag);
-+ lgd.lgd_rpc_err = -EPROTO;
-+ goto out_return_error;
- }
-
-- if (uid == 0) {
+ if (updata.svc != LUSTRE_GSS_SVC_MDS &&
+ updata.svc != LUSTRE_GSS_SVC_OSS) {
+ printerr(0, "invalid svc %d\n", updata.svc);
+ 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;
/*
-@@ -696,75 +989,66 @@ handle_krb5_upcall(struct clnt_info *clp
+ * 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 "
+ "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,
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.pag, updata.uid,
-+ clp->servicename);
++ gssd_setup_krb5_user_gss_ccache(updata.uid, clp->servicename);
- if ((create_auth_rpc_client(clp, &rpc_clnt, &auth, uid,
- AUTHTYPE_KRB5)) != 0) {
goto out;
+#endif
}
-diff -rup nfs-utils-1.0.10.orig/utils/gssd/gss_util.c nfs-utils-1.0.10/utils/gssd/gss_util.c
---- nfs-utils-1.0.10.orig/utils/gssd/gss_util.c 2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/gss_util.c 2006-12-15 15:12:23.000000000 -0700
+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 <com_err.h>
+ return retval;
+}
+
-diff -rup nfs-utils-1.0.10.orig/utils/gssd/gss_util.h nfs-utils-1.0.10/utils/gssd/gss_util.h
---- nfs-utils-1.0.10.orig/utils/gssd/gss_util.h 2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/gss_util.h 2006-12-15 15:12:23.000000000 -0700
+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_
+int gssd_get_local_realm(void);
#endif /* _GSS_UTIL_H_ */
-diff -rup nfs-utils-1.0.10.orig/utils/gssd/krb5_util.c nfs-utils-1.0.10/utils/gssd/krb5_util.c
---- nfs-utils-1.0.10.orig/utils/gssd/krb5_util.c 2006-11-15 21:26:08.000000000 -0700
-+++ nfs-utils-1.0.10/utils/gssd/krb5_util.c 2006-12-15 15:12:23.000000000 -0700
+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 <rpc/rpc.h>
#include <sys/types.h>
printerr(2, "INFO: Credentials in CC '%s' are good until %d\n",
ple->ccname, ple->endtime);
code = 0;
-@@ -325,11 +374,7 @@ gssd_get_single_krb5_cred(krb5_context c
+@@ -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 : "<unparsable>", kt_name);
goto out;
}
-@@ -378,15 +423,7 @@ gssd_get_single_krb5_cred(krb5_context c
+@@ -378,15 +429,7 @@ gssd_get_single_krb5_cred(krb5_context c
return (code);
}
{
struct gssd_k5_kt_princ *ple;
#ifdef HAVE_KRB5
-@@ -396,18 +433,76 @@ gssd_have_realm_ple(void *r)
+@@ -396,18 +439,76 @@ gssd_have_realm_ple(void *r)
#endif
for (ple = gssd_k5_kt_princ_list; ple; ple = ple->next) {
/*
* Process the given keytab file and create a list of principals we
* might use to perform mount operations.
-@@ -451,82 +546,106 @@ gssd_process_krb5_keytab(krb5_context co
+@@ -451,82 +552,106 @@ gssd_process_krb5_keytab(krb5_context co
}
printerr(2, "Processing keytab entry for principal '%s'\n",
pname);
}
if ((code = krb5_kt_end_seq_get(context, kt, &cursor))) {
-@@ -634,14 +753,21 @@ parse_enctypes(char *enctypes)
- * void
- */
- void
--gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername)
-+gssd_setup_krb5_user_gss_ccache(uint64_t pag, uid_t uid, char *servername)
- {
- char buf[MAX_NETOBJ_SZ];
- struct dirent *d;
-
-- printerr(2, "getting credentials for client with uid %u for "
-- "server %s\n", uid, servername);
-+ printerr(2, "getting credentials for client with pag %llx/uid %u for "
-+ "server %s\n", pag, uid, servername);
+@@ -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 (pag != uid) {
-+ snprintf(buf, sizeof(buf), "FILE:%s/%spag_%llx",
-+ ccachedir, GSSD_DEFAULT_CRED_PREFIX, pag);
-+ goto set_ccname;
-+ }
-+
if (gssd_find_existing_krb5_ccache(uid, &d)) {
snprintf(buf, sizeof(buf), "FILE:%s/%s",
ccachedir, d->d_name);
-@@ -652,6 +778,7 @@ gssd_setup_krb5_user_gss_ccache(uid_t ui
- ccachedir, GSSD_DEFAULT_CRED_PREFIX, uid);
- printerr(2, "using %s as credentials cache for client with "
- "uid %u for server %s\n", buf, uid, servername);
-+set_ccname:
- gssd_set_krb5_ccache_name(buf);
- }
-
-@@ -702,7 +829,7 @@ gssd_refresh_krb5_machine_creds(void)
+@@ -702,7 +828,7 @@ gssd_refresh_krb5_machine_creds(void)
goto out;
}
if ((code = krb5_kt_resolve(context, keytabfile, &kt))) {
printerr(0, "ERROR: %s while resolving keytab '%s'\n",
-@@ -717,12 +844,12 @@ gssd_refresh_krb5_machine_creds(void)
+@@ -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);
}
}
-@@ -872,6 +999,7 @@ gssd_destroy_krb5_machine_creds(void)
+@@ -872,6 +998,7 @@ gssd_destroy_krb5_machine_creds(void)
krb5_free_context(context);
}
#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
/*
* this routine obtains a credentials handle via gss_acquire_cred()
-@@ -927,6 +1055,7 @@ limit_krb5_enctypes(struct rpc_gss_sec *
+@@ -927,6 +1054,7 @@ limit_krb5_enctypes(struct rpc_gss_sec *
return 0;
}
#endif /* HAVE_SET_ALLOWABLE_ENCTYPES */
/*
* Obtain supported enctypes from kernel.
-diff -rup nfs-utils-1.0.10.orig/utils/gssd/krb5_util.h nfs-utils-1.0.10/utils/gssd/krb5_util.h
---- nfs-utils-1.0.10.orig/utils/gssd/krb5_util.h 2006-11-15 21:26:08.000000000 -0700
-+++ nfs-utils-1.0.10/utils/gssd/krb5_util.h 2006-12-15 15:12:23.000000000 -0700
-@@ -10,13 +10,15 @@
+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;
char *ccname;
char *realm;
krb5_timestamp endtime;
- };
-
-
--void gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername);
-+void gssd_setup_krb5_user_gss_ccache(uint64_t pag, uid_t uid, char *servername);
- int gssd_get_krb5_machine_cred_list(char ***list);
- int gssd_refresh_krb5_machine_creds(void);
- void gssd_free_krb5_machine_cred_list(char **list);
@@ -25,8 +27,4 @@ void gssd_destroy_krb5_machine_creds(voi
void gssd_obtain_kernel_krb5_info(void);
-#endif
-
#endif /* KRB5_UTIL_H */
-diff -rup nfs-utils-1.0.10.orig/utils/gssd/lsupport.c nfs-utils-1.0.10/utils/gssd/lsupport.c
---- nfs-utils-1.0.10.orig/utils/gssd/lsupport.c 2006-11-15 21:41:25.000000000 -0700
-+++ nfs-utils-1.0.10/utils/gssd/lsupport.c 2006-12-15 15:12:23.000000000 -0700
-@@ -0,0 +1,782 @@
+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,778 @@
++/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
++ * vim:expandtab:shiftwidth=8:tabstop=8:
++ *
++ * 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 <ericm@clusterfs.com>
++ *
++ * 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 <unistd.h>
++#include <stdlib.h>
++#include <stdio.h>
++#include <fcntl.h>
++#include <string.h>
++#include <errno.h>
++#include <stdarg.h>
++#include <syslog.h>
++#include <assert.h>
++#include <pwd.h>
++#include <keyutils.h>
++#include <gssapi/gssapi.h>
++
++#include <libcfs/libcfs.h>
++
++#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 <sys/types.h>
++#include <stdlib.h>
++#include <stdio.h>
++
++#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 <princ> <nid>\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,783 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ *
+} converter[LND_ENUM_END_MARKER] = {
+ {"UNUSED0", NULL},
+ [QSWLND] = { "QSWLND", external_nid2hostname},
-+ [SOCKLND] = { "SOCKLND", socklnd_nid2hostname},
++ [SOCKLND] = { "SOCKLND", socklnd_nid2hostname },
+ [GMLND] = { "GMLND", external_nid2hostname},
+ [PTLLND] = { "PTLLND", external_nid2hostname },
-+ [O2IBLND] = { "O2IBLND", external_nid2hostname },
++ [O2IBLND] = { "O2IBLND", socklnd_nid2hostname }, /* XXX */
+ [CIBLND] = { "CIBLND", external_nid2hostname },
+ [OPENIBLND] = { "OPENIBLND",external_nid2hostname },
+ [IIBLND] = { "IIBLND", external_nid2hostname },
+ ****************************************/
+
+#define MAPPING_GROW_SIZE 512
-+#define MAX_LINE_LEN 1024
++#define MAX_LINE_LEN 256
+
+struct user_map_item {
-+ char *principal; /* NULL means match all */
++ char *principal; /* NULL means match all, will cause multi->single mapped, FORBID */
+ lnet_nid_t nid;
+ uid_t uid;
+};
+
+struct user_mapping {
-+ int size;
+ int nitems;
+ struct user_map_item *items;
+};
+
-+static struct user_mapping mapping = {0, 0, NULL};
++static struct user_mapping mapping = {0, NULL};
+/* FIXME to be finished: monitor change of mapping database */
+static int mapping_mtime = 0;
+
-+static
+void cleanup_mapping(void)
+{
-+ int n;
-+
-+ for (n = 0; n < mapping.nitems; n++) {
-+ if (mapping.items[n].principal)
-+ free(mapping.items[n].principal);
++ if (mapping.items) {
++ for (; mapping.nitems > 0; mapping.nitems--)
++ free(mapping.items[mapping.nitems - 1].principal);
++ free(mapping.items);
++ mapping.items = NULL;
+ }
-+ mapping.nitems = 0;
+}
+
-+static
-+int grow_mapping(int size)
++static int grow_mapping(int nitems)
+{
+ struct user_map_item *new;
-+ int newsize;
++ int oldsize, newsize;
+
-+ if (size <= mapping.size)
++ 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.size + MAPPING_GROW_SIZE;
-+ while (newsize < size)
-+ newsize += MAPPING_GROW_SIZE;
-+
-+ new = malloc(newsize * sizeof(struct user_map_item));
++ newsize *= MAPPING_GROW_SIZE;
++ new = malloc(newsize);
+ if (!new) {
+ printerr(0, "can't alloc mapping size %d\n", newsize);
+ return -1;
+ }
-+ memcpy(new, mapping.items, mapping.nitems * sizeof(void*));
-+ free(mapping.items);
++
++ if (mapping.items) {
++ memcpy(new, mapping.items, mapping.nitems * sizeof(struct user_map_item));
++ free(mapping.items);
++ }
+ mapping.items = new;
-+ mapping.size = newsize;
+ return 0;
+}
+
+ return -1;
+}
+
-+static
-+int read_mapping_db(void)
++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;
-+ char *line, linebuf[MAX_LINE_LEN];
+
+ /* cleanup old mappings */
+ cleanup_mapping();
+ return -1;
+ }
+
-+ while ((line = fgets(linebuf, MAX_LINE_LEN, f))) {
++ 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));
-+ cleanup_mapping();
-+ fclose(f);
-+ return -1;
++ continue;
+ }
++
+ if (sscanf(line, "%s %s %s", princ, nid_str, dest) != 3) {
+ printerr(0, "mapping db: syntax error\n");
-+ cleanup_mapping();
-+ fclose(f);
-+ return -1;
-+ }
-+ if (grow_mapping(mapping.nitems + 1)) {
-+ printerr(0, "fail to grow mapping to %d\n",
-+ mapping.nitems + 1);
-+ fclose(f);
-+ return -1;
++ continue;
+ }
++
+ if (!strcmp(princ, "*")) {
-+ name = NULL;
++ 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);
-+ fclose(f);
-+ return -1;
++ 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);
-+ fclose(f);
-+ return -1;
++ 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].uid = dest_uid;
+ mapping.nitems++;
+ printerr(1, "add mapping: %s(%s/0x%llx) ==> %d\n",
-+ name ? name : "*", nid_str, nid, dest_uid);
++ name, nid_str, nid, dest_uid);
+ }
+
++ fclose(f);
+ return 0;
+}
+
+{
+ int n;
+
++ *uid = -1;
++
+ /* FIXME race condition here */
+ if (mapping_changed()) {
+ if (read_mapping_db())
+
+ if (entry->nid != LNET_NID_ANY && entry->nid != nid)
+ continue;
-+ if (!entry->principal ||
-+ !strcasecmp(entry->principal, princ)) {
++ 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);
-+ *uid = -1;
+ return -1;
+}
-+
-diff -rup nfs-utils-1.0.10.orig/utils/gssd/lsupport.h nfs-utils-1.0.10/utils/gssd/lsupport.h
---- nfs-utils-1.0.10.orig/utils/gssd/lsupport.h 2006-11-15 21:41:23.000000000 -0700
-+++ nfs-utils-1.0.10/utils/gssd/lsupport.h 2006-12-15 15:12:23.000000000 -0700
+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,89 @@
+/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
+ * vim:expandtab:shiftwidth=8:tabstop=8:
+ uint32_t gid;
+ uint32_t svc;
+ uint64_t nid;
-+ uint64_t pag;
+ char obd[64];
+};
+
+};
+
+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);
+
+#define LNET_MKNET(typ,num) ((((uint32_t)(typ))<<16)|((uint32_t)(num)))
+
+#endif /* __LIBCFS_H__ */
-diff -rup nfs-utils-1.0.10.orig/utils/gssd/Makefile.am nfs-utils-1.0.10/utils/gssd/Makefile.am
---- nfs-utils-1.0.10.orig/utils/gssd/Makefile.am 2006-11-15 21:26:08.000000000 -0700
-+++ nfs-utils-1.0.10/utils/gssd/Makefile.am 2006-12-15 15:11:52.000000000 -0700
+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
- rm -f $(RPCPREFIX)$$inst ; \
- done)
-
-diff -rup nfs-utils-1.0.10.orig/utils/gssd/svcgssd.c nfs-utils-1.0.10/utils/gssd/svcgssd.c
---- nfs-utils-1.0.10.orig/utils/gssd/svcgssd.c 2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/svcgssd.c 2006-12-15 15:12:23.000000000 -0700
+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 <sys/types.h>
#include <sys/stat.h>
/*
* mydaemon creates a pipe between the partent and child
* process. The parent process will wait until the
-@@ -165,8 +186,8 @@ main(int argc, char *argv[])
+@@ -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;
extern char *optarg;
char *progname;
-@@ -181,8 +202,13 @@ main(int argc, char *argv[])
+@@ -181,8 +203,13 @@ main(int argc, char *argv[])
case 'v':
verbosity++;
break;
break;
default:
usage(argv[0]);
-@@ -196,27 +222,18 @@ main(int argc, char *argv[])
+@@ -196,27 +223,18 @@ main(int argc, char *argv[])
progname = argv[0];
initerr(progname, verbosity, fg);
printerr(0, "unable to obtain root (machine) credentials\n");
printerr(0, "do you have a keytab entry for "
"nfs/<your.host>@<YOUR.REALM> in "
-@@ -225,9 +242,18 @@ main(int argc, char *argv[])
+@@ -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);
+ gssd_init_unique(GSSD_SVC);
+
+ svcgssd_run();
++ cleanup_mapping();
printerr(0, "gssd_run returned!\n");
abort();
}
-diff -rup nfs-utils-1.0.10.orig/utils/gssd/svcgssd.h nfs-utils-1.0.10/utils/gssd/svcgssd.h
---- nfs-utils-1.0.10.orig/utils/gssd/svcgssd.h 2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/svcgssd.h 2006-12-15 15:12:23.000000000 -0700
+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 <sys/queue.h>
#include <gssapi/gssapi.h>
+#define LUSTRE_ROOT_NAMELEN 11
#endif /* _RPC_SVCGSSD_H_ */
-diff -rup nfs-utils-1.0.10.orig/utils/gssd/svcgssd_main_loop.c nfs-utils-1.0.10/utils/gssd/svcgssd_main_loop.c
---- nfs-utils-1.0.10.orig/utils/gssd/svcgssd_main_loop.c 2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/svcgssd_main_loop.c 2006-12-15 15:12:23.000000000 -0700
+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"
}
}
}
-diff -rup nfs-utils-1.0.10.orig/utils/gssd/svcgssd_proc.c nfs-utils-1.0.10/utils/gssd/svcgssd_proc.c
---- nfs-utils-1.0.10.orig/utils/gssd/svcgssd_proc.c 2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/gssd/svcgssd_proc.c 2006-12-15 15:12:23.000000000 -0700
+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 <sys/param.h>
out_err:
if (ctx != GSS_C_NO_CONTEXT)
-diff -rup nfs-utils-1.0.10.orig/utils/Makefile.am nfs-utils-1.0.10/utils/Makefile.am
---- nfs-utils-1.0.10.orig/utils/Makefile.am 2006-08-07 00:40:50.000000000 -0600
-+++ nfs-utils-1.0.10/utils/Makefile.am 2006-12-15 15:11:52.000000000 -0700
+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 =