-Add secinfo processing.
-From: Fred Isaman <iisaman@citi.umich.edu>
-Signed-off-by: Fred Isaman <iisaman@citi.umich.edu>
+The complete set of CITI nfs-utils patches rolled into one patch.
-Add secinfo processing.
----
-
- support/include/nfslib.h | 6 ++
- support/nfs/exports.c | 145 ++++++++++++++++++++++++++++++++++++++++++++-
- utils/exportfs/exportfs.c | 3 +
- utils/mountd/cache.c | 14 ++++
- 4 files changed, 164 insertions(+), 4 deletions(-)
-
-Try to use kernel function to determine supported Kerberos enctypes.
+Changes since 1.0.11-CITI_NFS4_ALL-1:
-From: Kevin Coffman <kwc@citi.umich.edu>
+ * Update to nfs-utils-1.1.0
-Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
+ * Include patches from git not yet in a release:
+ - Fix mount error messages
-This patch replaces a hard-coded list with a function to obtain
-the Kerberos encryption types that the kernel's rpcsec_gss code
-can support. Defaults to old behavior if kernel does not supply
-information.
----
-
- utils/gssd/gssd.c | 2
- utils/gssd/krb5_util.c | 228 +++++++++++++++++++++++++++++++++++++-----------
- utils/gssd/krb5_util.h | 2
- 3 files changed, 182 insertions(+), 50 deletions(-)
+ * Update gssd usage message to include new -n option.
-Add EXPERIMENTAL support for non-DES encryption types.
+ * Patches from Bruce Fields to clean up compile warning, and
+ move pseudoflavor code to a common location
-From: Kevin Coffman <kwc@citi.umich.edu>
+ * Patch from Bruce Fields and Fred Isaman that adds support
+ to exportfs for reading a sec= option and sending server
+ security data through cache via
+ "... secinfo n flavor1 flag1 ... flavorN flagN".
-Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
-Adds EXPERIMENTAL support for non-DES encryption types. Sends a new
-format of context information to the kernel.
-(Requires kernel support to do anything useful.)
---
- utils/gssd/context.h | 6 +
- utils/gssd/context_lucid.c | 391 ++++++++++++++++++++++++++++++++++++++++++--
- utils/gssd/context_mit.c | 254 +++++++++++++++++++++++++----
- 3 files changed, 603 insertions(+), 48 deletions(-)
+ nfs-utils-1.1.0-kwc/support/include/nfslib.h | 10 +
+ nfs-utils-1.1.0-kwc/support/include/pseudoflavors.h | 17 ++
+ nfs-utils-1.1.0-kwc/support/nfs/exports.c | 158 ++++++++++++++++++--
+ nfs-utils-1.1.0-kwc/utils/exportfs/exportfs.c | 1
+ nfs-utils-1.1.0-kwc/utils/gssd/gssd.c | 2
+ nfs-utils-1.1.0-kwc/utils/mount/mount.c | 40 ++++-
+ nfs-utils-1.1.0-kwc/utils/mount/nfs4_mount.h | 12 -
+ nfs-utils-1.1.0-kwc/utils/mount/nfs4mount.c | 27 ---
+ nfs-utils-1.1.0-kwc/utils/mountd/cache.c | 21 ++
+ 10 files changed, 240 insertions(+), 49 deletions(-)
-diff --git a/support/include/nfslib.h b/support/include/nfslib.h
-index c085029..6d7743d 100644
---- a/support/include/nfslib.h
-+++ b/support/include/nfslib.h
-@@ -57,6 +57,9 @@ enum cle_maptypes {
- #define _PATH_PROC_EXPORTS_ALT "/proc/fs/nfsd/exports"
- #endif
+diff -puN utils/mount/mount.c~CITI_NFS4_ALL utils/mount/mount.c
+--- nfs-utils-1.1.0/utils/mount/mount.c~CITI_NFS4_ALL 2007-06-22 10:51:38.885022000 -0400
++++ nfs-utils-1.1.0-kwc/utils/mount/mount.c 2007-06-22 10:52:04.954241000 -0400
+@@ -285,22 +285,49 @@ static void parse_opts (const char *opti
+ }
+ }
-+#define SECFLAVOR_COUNT 7
-+extern char *secflavor_name[SECFLAVOR_COUNT];
+-static void mount_error(char *node)
++static void mount_error(char *mntpnt, char *node)
+ {
+ switch(errno) {
+ case ENOTDIR:
+- fprintf(stderr, "%s: mount point %s is not a directory\n", progname, node);
++ fprintf(stderr, "%s: mount point %s is not a directory\n",
++ progname, mntpnt);
+ break;
+ case EBUSY:
+- fprintf(stderr, "%s: %s is already mounted or busy\n", progname, node);
++ fprintf(stderr, "%s: %s is already mounted or busy\n",
++ progname, mntpnt);
+ break;
+ case ENOENT:
+- fprintf(stderr, "%s: mount point %s does not exist\n", progname, node);
++ if (node) {
++ fprintf(stderr, "%s: %s failed, reason given by server: %s\n",
++ progname, node, strerror(errno));
++ } else
++ fprintf(stderr, "%s: mount point %s does not exist\n",
++ progname, mntpnt);
+ break;
+ default:
+ fprintf(stderr, "%s: %s\n", progname, strerror(errno));
+ }
+ }
++static int chk_mountpoint(char *mount_point)
++{
++ struct stat sb;
+
- /*
- * Data related to a single exports entry as returned by getexportent.
- * FIXME: export options should probably be parsed at a later time to
-@@ -83,6 +86,8 @@ struct exportent {
- int e_fslocmethod;
- char * e_fslocdata;
- char * e_uuid;
-+ int e_secinfo_order[SECFLAVOR_COUNT+1];
-+ int e_secinfo_flags[SECFLAVOR_COUNT];
- };
++ if (stat(mount_point, &sb) < 0){
++ mount_error(mount_point, NULL);
++ return 1;
++ }
++ if (S_ISDIR(sb.st_mode) == 0){
++ errno = ENOTDIR;
++ mount_error(mount_point, NULL);
++ return 1;
++ }
++ if (access(mount_point, X_OK) < 0) {
++ mount_error(mount_point, NULL);
++ return 1;
++ }
++
++ return 0;
++}
- struct rmtabent {
-@@ -96,6 +101,7 @@ struct rmtabent {
- */
- void setexportent(char *fname, char *type);
- struct exportent * getexportent(int,int);
-+void secinfo_show(FILE *fp, struct exportent *ep);
- void putexportent(struct exportent *xep);
- void endexportent(void);
- struct exportent * mkexportent(char *hname, char *path, char *opts);
-diff --git a/support/nfs/exports.c b/support/nfs/exports.c
-index 294e1c9..af9ab2f 100644
---- a/support/nfs/exports.c
-+++ b/support/nfs/exports.c
-@@ -51,6 +51,10 @@ static int parsenum(char **cpp);
- static int parsenum(char **cpp);
- static void freesquash(void);
- static void syntaxerr(char *msg);
-+static unsigned int parse_flavors(char *str, struct exportent *ep);
-+static int secinfo_default(struct exportent *ep);
-+static void setflags(int mask, unsigned int *ap, struct exportent *ep);
-+static void clearflags(int mask, unsigned int *ap, struct exportent *ep);
+ extern u_short getport(
+ struct sockaddr_in *saddr,
+@@ -508,6 +535,9 @@ int main(int argc, char *argv[])
+ }
+ }
- void
- setexportent(char *fname, char *type)
-@@ -102,6 +106,7 @@ getexportent(int fromkernel, int fromexp
++ if (chk_mountpoint(mount_point))
++ exit(EX_FAIL);
++
+ if (nfs_mount_vers == 4)
+ mnt_err = nfs4mount(spec, mount_point, &flags, &extra_opts, &mount_opts, 0);
+ else {
+@@ -538,7 +568,7 @@ int main(int argc, char *argv[])
+ mount_opts);
+
+ if (mnt_err) {
+- mount_error(mount_point);
++ mount_error(mount_point, spec);
+ exit(EX_FAIL);
+ }
+ }
+diff -puN utils/gssd/gssd.c~CITI_NFS4_ALL utils/gssd/gssd.c
+--- nfs-utils-1.1.0/utils/gssd/gssd.c~CITI_NFS4_ALL 2007-06-22 10:51:53.782368000 -0400
++++ nfs-utils-1.1.0-kwc/utils/gssd/gssd.c 2007-06-22 10:51:56.521019000 -0400
+@@ -81,7 +81,7 @@ sig_hup(int signal)
+ static void
+ usage(char *progname)
+ {
+- fprintf(stderr, "usage: %s [-f] [-n] [-v] [-r] [-p pipefsdir] [-k keytab] [-d ccachedir]\n",
++ fprintf(stderr, "usage: %s [-f] [-M] [-n] [-v] [-r] [-p pipefsdir] [-k keytab] [-d ccachedir]\n",
+ progname);
+ exit(1);
+ }
+diff -puN /dev/null support/include/pseudoflavors.h
+--- /dev/null 2007-06-21 19:03:53.875366737 -0400
++++ nfs-utils-1.1.0-kwc/support/include/pseudoflavors.h 2007-06-22 10:52:22.335293000 -0400
+@@ -0,0 +1,17 @@
++#define RPC_AUTH_GSS_KRB5 390003
++#define RPC_AUTH_GSS_KRB5I 390004
++#define RPC_AUTH_GSS_KRB5P 390005
++#define RPC_AUTH_GSS_LKEY 390006
++#define RPC_AUTH_GSS_LKEYI 390007
++#define RPC_AUTH_GSS_LKEYP 390008
++#define RPC_AUTH_GSS_SPKM 390009
++#define RPC_AUTH_GSS_SPKMI 390010
++#define RPC_AUTH_GSS_SPKMP 390011
++
++struct flav_info {
++ char *flavour;
++ int fnum;
++};
++
++extern struct flav_info flav_map[];
++extern const int flav_map_size;
+diff -puN support/nfs/exports.c~CITI_NFS4_ALL support/nfs/exports.c
+--- nfs-utils-1.1.0/support/nfs/exports.c~CITI_NFS4_ALL 2007-06-22 10:52:16.682999000 -0400
++++ nfs-utils-1.1.0-kwc/support/nfs/exports.c 2007-06-22 10:52:40.578175000 -0400
+@@ -30,10 +30,29 @@
+ #include "xmalloc.h"
+ #include "xlog.h"
+ #include "xio.h"
++#include "pseudoflavors.h"
+
+ #define EXPORT_DEFAULT_FLAGS \
+ (NFSEXP_READONLY|NFSEXP_ROOTSQUASH|NFSEXP_GATHERED_WRITES|NFSEXP_NOSUBTREECHECK)
+
++struct flav_info flav_map[] = {
++ { "krb5", RPC_AUTH_GSS_KRB5 },
++ { "krb5i", RPC_AUTH_GSS_KRB5I },
++ { "krb5p", RPC_AUTH_GSS_KRB5P },
++ { "lipkey", RPC_AUTH_GSS_LKEY },
++ { "lipkey-i", RPC_AUTH_GSS_LKEYI },
++ { "lipkey-p", RPC_AUTH_GSS_LKEYP },
++ { "spkm3", RPC_AUTH_GSS_SPKM },
++ { "spkm3i", RPC_AUTH_GSS_SPKMI },
++ { "spkm3p", RPC_AUTH_GSS_SPKMP },
++ { "unix", AUTH_UNIX },
++ { "sys", AUTH_SYS },
++ { "null", AUTH_NULL },
++ { "none", AUTH_NONE },
++};
++
++const int flav_map_size = sizeof(flav_map)/sizeof(flav_map[0]);
++
+ int export_errno;
+
+ static char *efname = NULL;
+@@ -100,6 +119,7 @@ getexportent(int fromkernel, int fromexp
def_ee.e_mountpoint = NULL;
def_ee.e_fslocmethod = FSLOC_NONE;
def_ee.e_fslocdata = NULL;
-+ def_ee.e_secinfo_order[0] = -1;
++ def_ee.e_secinfo[0].flav = NULL;
def_ee.e_nsquids = 0;
def_ee.e_nsqgids = 0;
-@@ -182,6 +187,19 @@ getexportent(int fromkernel, int fromexp
+@@ -179,6 +199,27 @@ getexportent(int fromkernel, int fromexp
+ return ⅇ
}
- void
-+secinfo_show(FILE *fp, struct exportent *ep)
++void secinfo_show(FILE *fp, struct exportent *ep)
+{
-+ int *p1, *p2;
-+ for (p1=ep->e_secinfo_order; *p1>=0; p1=p2) {
-+ fprintf(fp, ",sec=%s", secflavor_name[*p1]);
-+ for (p2=p1+1; (*p2>=0) && (ep->e_secinfo_flags[*p1]==ep->e_secinfo_flags[*p2]); p2++) {
-+ fprintf(fp, ":%s", secflavor_name[*p2]);
++ struct sec_entry *p1, *p2;
++ int flags;
++
++ for (p1=ep->e_secinfo; p1->flav; p1=p2) {
++
++ fprintf(fp, ",sec=%s", p1->flav->flavour);
++ for (p2=p1+1; (p2->flav != NULL) && (p1->flags == p2->flags);
++ p2++) {
++ fprintf(fp, ":%s", p2->flav->flavour);
+ }
-+ fprintf(fp, ",%s", (ep->e_secinfo_flags[*p1] & NFSEXP_READONLY)? "ro" : "rw");
++ flags = p1->flags;
++ fprintf(fp, ",%s", (flags & NFSEXP_READONLY) ? "ro" : "rw");
++ fprintf(fp, ",%sroot_squash", (flags & NFSEXP_ROOTSQUASH)?
++ "" : "no_");
++ fprintf(fp, ",%sall_squash", (flags & NFSEXP_ALLSQUASH)?
++ "" : "no_");
+ }
+}
+
-+void
+ void
putexportent(struct exportent *ep)
{
- FILE *fp;
-@@ -199,7 +217,6 @@ putexportent(struct exportent *ep)
- fprintf(fp, "%c", esc[i]);
-
- fprintf(fp, "\t%s(", ep->e_hostname);
-- fprintf(fp, "%s,", (ep->e_flags & NFSEXP_READONLY)? "ro" : "rw");
- fprintf(fp, "%ssync,", (ep->e_flags & NFSEXP_ASYNC)? "a" : "");
- fprintf(fp, "%swdelay,", (ep->e_flags & NFSEXP_GATHERED_WRITES)?
- "" : "no_");
-@@ -276,7 +293,9 @@ #endif
+@@ -259,7 +300,9 @@ putexportent(struct exportent *ep)
else
fprintf(fp, "%d,", id[i]);
}
}
void
-@@ -325,6 +344,7 @@ mkexportent(char *hname, char *path, cha
+@@ -307,6 +350,7 @@ mkexportent(char *hname, char *path, cha
ee.e_mountpoint = NULL;
ee.e_fslocmethod = FSLOC_NONE;
ee.e_fslocdata = NULL;
-+ ee.e_secinfo_order[0] = -1;
++ ee.e_secinfo[0].flav = NULL;
ee.e_nsquids = 0;
ee.e_nsqgids = 0;
ee.e_uuid = NULL;
-@@ -376,6 +396,9 @@ parseopts(char *cp, struct exportent *ep
- int had_subtree_opt = 0;
- char *flname = efname?efname:"command line";
- int flline = efp?efp->x_line:0;
-+ int *p;
-+ unsigned int active = 0;
-+ int secmask = NFSEXP_READONLY; /* options that can vary per flavor */
-
- squids = ep->e_squids; nsquids = ep->e_nsquids;
- sqgids = ep->e_sqgids; nsqgids = ep->e_nsqgids;
-@@ -398,9 +421,9 @@ parseopts(char *cp, struct exportent *ep
-
- /* process keyword */
- if (strcmp(opt, "ro") == 0)
-- ep->e_flags |= NFSEXP_READONLY;
-+ setflags(NFSEXP_READONLY, &active, ep);
- else if (strcmp(opt, "rw") == 0)
-- ep->e_flags &= ~NFSEXP_READONLY;
-+ clearflags(NFSEXP_READONLY, &active, ep);
- else if (!strcmp(opt, "secure"))
- ep->e_flags &= ~NFSEXP_INSECURE_PORT;
- else if (!strcmp(opt, "insecure"))
-@@ -522,6 +545,10 @@ #endif
- } else if (strncmp(opt, "replicas=", 9) == 0) {
- ep->e_fslocmethod = FSLOC_REPLICA;
- ep->e_fslocdata = strdup(opt+9);
-+ } else if (strncmp(opt, "sec=", 4) == 0) {
-+ active = parse_flavors(opt+4, ep);
-+ if (!active)
-+ goto bad_option;
- } else {
- xlog(L_ERROR, "%s:%d: unknown keyword \"%s\"\n",
- flname, flline, opt);
-@@ -533,6 +560,12 @@ #endif
- cp++;
- }
-
-+ if (!active)
-+ active = secinfo_default(ep);
-+ for (p=ep->e_secinfo_order; *p>=0; p++)
-+ ep->e_secinfo_flags[*p] |= (ep->e_flags & ~secmask);
-+ /* If did not use sec= option, ensure e_flags is backward compatible */
-+ ep->e_flags = ep->e_secinfo_flags[ep->e_secinfo_order[0]];
- ep->e_squids = squids;
- ep->e_sqgids = sqgids;
- ep->e_nsquids = nsquids;
-@@ -663,3 +696,107 @@ syntaxerr(char *msg)
- efname, efp?efp->x_line:0, msg);
+@@ -350,18 +394,110 @@ static int valid_uuid(char *uuid)
}
-+char *secflavor_name[SECFLAVOR_COUNT] = { "sys",
-+ "krb5",
-+ "krb5i",
-+ "krb5p",
-+ "spkm3",
-+ "spkm3i",
-+ "spkm3p"
-+};
-+
-+static void
-+secinfo_addflavor(int bit, struct exportent *ep)
+ /*
++ * Append the given flavor to the exportent's e_secinfo array, or
++ * do nothing if it's already there. Returns the index of flavor
++ * in the resulting array in any case.
++ */
++static int secinfo_addflavor(struct flav_info *flav, struct exportent *ep)
+{
-+ int *p;
-+ for (p=ep->e_secinfo_order; *p>=0; p++) {
-+ if (*p == bit)
-+ return;
++ struct sec_entry *p;
++
++ for (p=ep->e_secinfo; p->flav; p++) {
++ if (p->flav == flav)
++ return p - ep->e_secinfo;
+ }
-+ *p++ = bit;
-+ *p = -1;
-+ ep->e_secinfo_flags[bit] = 0;
++ if (p - ep->e_secinfo >= SECFLAVOR_COUNT) {
++ xlog(L_ERROR, "more than %d security flavors on an export\n",
++ SECFLAVOR_COUNT);
++ return -1;
++ }
++ p->flav = flav;
++ p->flags = ep->e_flags;
++ (p+1)->flav = NULL;
++ return p - ep->e_secinfo;
+}
+
-+static int
-+secinfo_nameindex(char *name)
++static struct flav_info *find_flavor(char *name)
+{
-+ int i;
-+ for (i=0; i<SECFLAVOR_COUNT; i++) {
-+ if (strcmp(secflavor_name[i], name) == 0)
-+ return i;
-+ }
-+ return -1;
++ struct flav_info *flav;
++ for (flav = flav_map; flav < flav_map + flav_map_size; flav++)
++ if (strcmp(flav->flavour, name) == 0)
++ return flav;
++ return NULL;
+}
+
+/* @str is a colon seperated list of security flavors. Their order
+ * is recorded in @ep, and a bitmap corresponding to the list is returned.
+ * A zero return indicates an error.
+ */
-+static unsigned int
-+parse_flavors(char *str, struct exportent *ep)
++static unsigned int parse_flavors(char *str, struct exportent *ep)
+{
+ unsigned int out=0;
+ char *flavor;
-+ int bit;
++ int bit;
+
+ while ( (flavor=strsep(&str, ":")) ) {
-+ bit = secinfo_nameindex(flavor);
-+ if (bit == -1) {
++ struct flav_info *flav = find_flavor(flavor);
++ if (flav == NULL) {
+ xlog(L_ERROR, "unknown flavor %s\n", flavor);
+ return 0;
+ }
++ bit = secinfo_addflavor(flav, ep);
++ if (bit < 0)
++ return 0;
+ out |= 1<<bit;
-+ secinfo_addflavor(bit, ep);
+ }
+ return out;
+}
+
-+/* Determine a default security flavor based on ep->e_hostname. */
-+static int
-+secinfo_default(struct exportent *ep)
-+{
-+ int i=-1;
-+ if (strncmp(ep->e_hostname, "gss/", 4) == 0) {
-+ i = secinfo_nameindex(ep->e_hostname + 4);
-+ if (i < 0)
-+ xlog(L_WARNING, "unknown flavor %s\n", ep->e_hostname);
-+ }
-+ /* Default to auth_sys */
-+ if (i < 0)
-+ i = secinfo_nameindex("sys");
-+ secinfo_addflavor(i, ep);
-+ return 1<<i;
-+}
-+
+/* Sets the bits in @mask for the appropriate security flavor flags. */
-+static void
-+setflags(int mask, unsigned int *ap, struct exportent *ep)
++static void setflags(int mask, unsigned int active, struct exportent *ep)
+{
-+ int active, flavor=0;
-+ if (!*ap)
-+ *ap = secinfo_default(ep);
-+ active = *ap;
++ int bit=0;
++
++ ep->e_flags |= mask;
++
+ while (active) {
+ if (active & 1)
-+ ep->e_secinfo_flags[flavor] |= mask;
-+ flavor++;
++ ep->e_secinfo[bit].flags |= mask;
++ bit++;
+ active >>= 1;
+ }
+}
+
+/* Clears the bits in @mask for the appropriate security flavor flags. */
-+static void
-+clearflags(int mask, unsigned int *ap, struct exportent *ep)
++static void clearflags(int mask, unsigned int active, struct exportent *ep)
+{
-+ int active, flavor=0;
-+ if (!*ap)
-+ *ap = secinfo_default(ep);
-+ active = *ap;
++ int bit=0;
++
++ ep->e_flags &= ~mask;
++
+ while (active) {
+ if (active & 1)
-+ ep->e_secinfo_flags[flavor] &= ~mask;
-+ flavor++;
++ ep->e_secinfo[bit].flags &= ~mask;
++ bit++;
+ active >>= 1;
+ }
+}
-diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c
-index 22e13a3..30732b8 100644
---- a/utils/exportfs/exportfs.c
-+++ b/utils/exportfs/exportfs.c
-@@ -376,10 +376,12 @@ dump(int verbose)
- continue;
- }
- c = '(';
-+ /*
- if (ep->e_flags & NFSEXP_READONLY)
- c = dumpopt(c, "ro");
- else
- c = dumpopt(c, "rw");
-+ */
- if (ep->e_flags & NFSEXP_ASYNC)
- c = dumpopt(c, "async");
- if (ep->e_flags & NFSEXP_GATHERED_WRITES)
-@@ -433,6 +435,7 @@ #ifdef DEBUG
- break;
- #endif
- }
-+ secinfo_show(stdout, ep);
- printf("%c\n", (c != '(')? ')' : ' ');
- }
- }
-diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c
-index 5f0d12a..78a8f75 100644
---- a/utils/mountd/cache.c
-+++ b/utils/mountd/cache.c
-@@ -445,6 +445,19 @@ static void write_fsloc(FILE *f, struct
- release_replicas(servers);
- }
-
-+static void write_secinfo(FILE *f, struct exportent *ep)
-+{
-+ int *p;
-+ qword_print(f, "secinfo");
-+ for (p=ep->e_secinfo_order; *p>=0; p++)
-+ ; /* Do nothing */
-+ qword_printint(f, p - ep->e_secinfo_order);
-+ for (p=ep->e_secinfo_order; *p>=0; p++) {
-+ qword_print(f, secflavor_name[*p]);
-+ qword_printint(f, ep->e_secinfo_flags[*p]);
-+ }
-+}
+
- static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *exp)
++/* options that can vary per flavor: */
++#define NFSEXP_SECINFO_FLAGS (NFSEXP_READONLY | NFSEXP_ROOTSQUASH \
++ | NFSEXP_ALLSQUASH)
++
++/*
+ * Parse option string pointed to by cp and set mount options accordingly.
+ */
+ static int
+ parseopts(char *cp, struct exportent *ep, int warn, int *had_subtree_opt_ptr)
{
- qword_print(f, domain);
-@@ -466,6 +479,7 @@ static int dump_to_cache(FILE *f, char *
- qword_printhex(f, exp->e_uuid, 16);
- }
- #endif
-+ write_secinfo(f, exp);
- }
- return qword_eol(f);
- }
-diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c
-index 08a6c10..44afdd0 100644
---- a/utils/gssd/gssd.c
-+++ b/utils/gssd/gssd.c
-@@ -162,6 +162,8 @@ #endif
- /* Process keytab file and get machine credentials */
- if (root_uses_machine_creds)
- gssd_refresh_krb5_machine_creds();
-+ /* Determine Kerberos information from the kernel */
-+ gssd_obtain_kernel_krb5_info();
++ struct sec_entry *p;
+ int had_subtree_opt = 0;
+ char *flname = efname?efname:"command line";
+ int flline = efp?efp->x_line:0;
++ unsigned int active = 0;
- gssd_run();
- printerr(0, "gssd_run returned!\n");
-diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
-index 096f6cf..96e91ae 100644
---- a/utils/gssd/krb5_util.c
-+++ b/utils/gssd/krb5_util.c
-@@ -97,6 +97,7 @@ #endif
- #include "config.h"
- #include <sys/param.h>
- #include <rpc/rpc.h>
-+#include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
-@@ -105,6 +106,7 @@ #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <dirent.h>
-+#include <fcntl.h>
- #include <errno.h>
- #include <time.h>
- #include <gssapi/gssapi.h>
-@@ -123,6 +125,10 @@ #include "krb5_util.h"
- /* Global list of principals/cache file names for machine credentials */
- struct gssd_k5_kt_princ *gssd_k5_kt_princ_list = NULL;
+ squids = ep->e_squids; nsquids = ep->e_nsquids;
+ sqgids = ep->e_sqgids; nsqgids = ep->e_nsqgids;
+-
+ if (!cp)
+ goto out;
-+/* Encryption types supported by the kernel rpcsec_gss code */
-+int num_krb5_enctypes = 0;
-+krb5_enctype *krb5_enctypes = NULL;
-+
- /*==========================*/
- /*=== Internal routines ===*/
- /*==========================*/
-@@ -256,56 +262,6 @@ gssd_find_existing_krb5_ccache(uid_t uid
- }
+@@ -380,9 +516,9 @@ parseopts(char *cp, struct exportent *ep
+ /* process keyword */
+ if (strcmp(opt, "ro") == 0)
+- ep->e_flags |= NFSEXP_READONLY;
++ setflags(NFSEXP_READONLY, active, ep);
+ else if (strcmp(opt, "rw") == 0)
+- ep->e_flags &= ~NFSEXP_READONLY;
++ clearflags(NFSEXP_READONLY, active, ep);
+ else if (!strcmp(opt, "secure"))
+ ep->e_flags &= ~NFSEXP_INSECURE_PORT;
+ else if (!strcmp(opt, "insecure"))
+@@ -404,13 +540,13 @@ parseopts(char *cp, struct exportent *ep
+ else if (!strcmp(opt, "no_wdelay"))
+ ep->e_flags &= ~NFSEXP_GATHERED_WRITES;
+ else if (strcmp(opt, "root_squash") == 0)
+- ep->e_flags |= NFSEXP_ROOTSQUASH;
++ setflags(NFSEXP_ROOTSQUASH, active, ep);
+ else if (!strcmp(opt, "no_root_squash"))
+- ep->e_flags &= ~NFSEXP_ROOTSQUASH;
++ clearflags(NFSEXP_ROOTSQUASH, active, ep);
+ else if (strcmp(opt, "all_squash") == 0)
+- ep->e_flags |= NFSEXP_ALLSQUASH;
++ setflags(NFSEXP_ALLSQUASH, active, ep);
+ else if (strcmp(opt, "no_all_squash") == 0)
+- ep->e_flags &= ~NFSEXP_ALLSQUASH;
++ clearflags(NFSEXP_ALLSQUASH, active, ep);
+ else if (strcmp(opt, "subtree_check") == 0) {
+ had_subtree_opt = 1;
+ ep->e_flags &= ~NFSEXP_NOSUBTREECHECK;
+@@ -498,6 +634,10 @@ bad_option:
+ } else if (strncmp(opt, "replicas=", 9) == 0) {
+ ep->e_fslocmethod = FSLOC_REPLICA;
+ ep->e_fslocdata = strdup(opt+9);
++ } else if (strncmp(opt, "sec=", 4) == 0) {
++ active = parse_flavors(opt+4, ep);
++ if (!active)
++ goto bad_option;
+ } else {
+ xlog(L_ERROR, "%s:%d: unknown keyword \"%s\"\n",
+ flname, flline, opt);
+@@ -509,6 +649,8 @@ bad_option:
+ cp++;
+ }
--#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
--/*
-- * this routine obtains a credentials handle via gss_acquire_cred()
-- * then calls gss_krb5_set_allowable_enctypes() to limit the encryption
-- * types negotiated.
-- *
-- * XXX Should call some function to determine the enctypes supported
-- * by the kernel. (Only need to do that once!)
-- *
-- * Returns:
-- * 0 => all went well
-- * -1 => there was an error
-- */
--
--int
--limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
--{
-- u_int maj_stat, min_stat;
-- gss_cred_id_t credh;
-- gss_OID_set_desc desired_mechs;
-- krb5_enctype enctypes[] = { ENCTYPE_DES_CBC_CRC };
-- int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
--
-- /* We only care about getting a krb5 cred */
-- desired_mechs.count = 1;
-- desired_mechs.elements = &krb5oid;
--
-- maj_stat = gss_acquire_cred(&min_stat, NULL, 0,
-- &desired_mechs, GSS_C_INITIATE,
-- &credh, NULL, NULL);
--
-- if (maj_stat != GSS_S_COMPLETE) {
-- pgsserr("gss_acquire_cred",
-- maj_stat, min_stat, &krb5oid);
-- return -1;
-- }
--
-- maj_stat = gss_set_allowable_enctypes(&min_stat, credh, &krb5oid,
-- num_enctypes, &enctypes);
-- if (maj_stat != GSS_S_COMPLETE) {
-- pgsserr("gss_set_allowable_enctypes",
-- maj_stat, min_stat, &krb5oid);
-- return -1;
-- }
-- sec->cred = credh;
--
-- return 0;
--}
--#endif /* HAVE_SET_ALLOWABLE_ENCTYPES */
--
- /*
- * Obtain credentials via a key in the keytab given
- * a keytab handle and a gssd_k5_kt_princ structure.
-@@ -609,6 +565,56 @@ #else
++ for (p = ep->e_secinfo; p->flav; p++)
++ p->flags |= ep->e_flags & ~NFSEXP_SECINFO_FLAGS;
+ ep->e_squids = squids;
+ ep->e_sqgids = sqgids;
+ ep->e_nsquids = nsquids;
+diff -puN utils/mount/nfs4mount.c~CITI_NFS4_ALL utils/mount/nfs4mount.c
+--- nfs-utils-1.1.0/utils/mount/nfs4mount.c~CITI_NFS4_ALL 2007-06-22 10:52:18.413097000 -0400
++++ nfs-utils-1.1.0-kwc/utils/mount/nfs4mount.c 2007-06-22 10:52:25.846889000 -0400
+@@ -36,6 +36,7 @@
+ #define nfsstat nfs_stat
#endif
- }
-
-+/*
-+ * Parse the supported encryption type information
-+ */
-+static int
-+parse_enctypes(char *enctypes)
-+{
-+ int n = 0;
-+ char *curr, *comma;
-+ int i;
-+
-+ /* Just in case this ever gets called more than once */
-+ if (krb5_enctypes != NULL) {
-+ free(krb5_enctypes);
-+ krb5_enctypes = NULL;
-+ num_krb5_enctypes = 0;
-+ }
-+
-+ /* count the number of commas */
-+ for (curr = enctypes; curr && *curr != '\0'; curr = ++comma) {
-+ comma = strchr(curr, ',');
-+ if (comma != NULL)
-+ n++;
-+ else
-+ break;
-+ }
-+ /* If no more commas and we're not at the end, there's one more value */
-+ if (*curr != '\0')
-+ n++;
-+
-+ /* Empty string, return an error */
-+ if (n == 0)
-+ return ENOENT;
-+
-+ /* Allocate space for enctypes array */
-+ if ((krb5_enctypes = (int *) calloc(n, sizeof(int))) == NULL) {
-+ return ENOMEM;
-+ }
-+
-+ /* Now parse each value into the array */
-+ for (curr = enctypes, i = 0; curr && *curr != '\0'; curr = ++comma) {
-+ krb5_enctypes[i++] = atoi(curr);
-+ comma = strchr(curr, ',');
-+ if (comma == NULL)
-+ break;
-+ }
-+
-+ num_krb5_enctypes = n;
-+ return 0;
-+}
-+
- /*==========================*/
- /*=== External routines ===*/
- /*==========================*/
-@@ -860,3 +866,125 @@ 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()
-+ * then calls gss_krb5_set_allowable_enctypes() to limit the encryption
-+ * types negotiated.
-+ *
-+ * Returns:
-+ * 0 => all went well
-+ * -1 => there was an error
-+ */
-+
-+int
-+limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid)
-+{
-+ u_int maj_stat, min_stat;
-+ gss_cred_id_t credh;
-+ gss_OID_set_desc desired_mechs;
-+ krb5_enctype enctypes[] = {ENCTYPE_DES_CBC_CRC};
-+ int num_enctypes = sizeof(enctypes) / sizeof(enctypes[0]);
-+
-+ /* We only care about getting a krb5 cred */
-+ desired_mechs.count = 1;
-+ desired_mechs.elements = &krb5oid;
-+
-+ maj_stat = gss_acquire_cred(&min_stat, NULL, 0,
-+ &desired_mechs, GSS_C_INITIATE,
-+ &credh, NULL, NULL);
-+
-+ if (maj_stat != GSS_S_COMPLETE) {
-+ pgsserr("gss_acquire_cred",
-+ maj_stat, min_stat, &krb5oid);
-+ return -1;
-+ }
-+
-+ /*
-+ * If we failed for any reason to produce global
-+ * list of supported enctypes, use local default here.
-+ */
-+ if (krb5_enctypes == NULL)
-+ maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
-+ &krb5oid, num_enctypes, &enctypes);
-+ else
-+ maj_stat = gss_set_allowable_enctypes(&min_stat, credh,
-+ &krb5oid, num_krb5_enctypes,
-+ krb5_enctypes);
-+ if (maj_stat != GSS_S_COMPLETE) {
-+ pgsserr("gss_set_allowable_enctypes",
-+ maj_stat, min_stat, &krb5oid);
-+ return -1;
-+ }
-+ sec->cred = credh;
-+
-+ return 0;
-+}
-+#endif /* HAVE_SET_ALLOWABLE_ENCTYPES */
-+
-+/*
-+ * Obtain supported enctypes from kernel.
-+ * Set defaults if info is not available.
-+ */
-+void
-+gssd_obtain_kernel_krb5_info(void)
-+{
-+ char enctype_file_name[128];
-+ char buf[1024];
-+ char enctypes[128];
-+ int nscanned;
-+ int fd;
-+ int use_default_enctypes = 0;
-+ int nbytes, numfields;
-+ char default_enctypes[] = "1,3,2";
-+ int code;
-+
-+ snprintf(enctype_file_name, sizeof(enctype_file_name),
-+ "%s/%s", pipefs_dir, "krb5_info");
-+
-+ if ((fd = open(enctype_file_name, O_RDONLY)) == -1) {
-+ printerr(1, "WARNING: gssd_obtain_kernel_krb5_info: "
-+ "Unable to open '%s'. Unable to determine "
-+ "Kerberos encryption types supported by the "
-+ "kernel; using defaults (%s).\n",
-+ enctype_file_name, default_enctypes);
-+ use_default_enctypes = 1;
-+ goto do_the_parse;
-+ }
-+ memset(buf, 0, sizeof(buf));
-+ if ((nbytes = read(fd, buf, sizeof(buf)-1)) == -1) {
-+ printerr(0, "WARNING: gssd_obtain_kernel_krb5_info: "
-+ "Error reading Kerberos encryption type "
-+ "information file '%s'; using defaults (%s).\n",
-+ enctype_file_name, default_enctypes);
-+ use_default_enctypes = 1;
-+ close(fd);
-+ goto do_the_parse;
-+ }
-+ close(fd);
-+ numfields = sscanf(buf, "enctypes: %s\n%n", enctypes, &nscanned);
-+ if (numfields < 1) {
-+ printerr(0, "WARNING: gssd_obtain_kernel_krb5_info: "
-+ "error parsing Kerberos encryption type "
-+ "information from file '%s'; using defaults (%s).\n",
-+ enctype_file_name, default_enctypes);
-+ use_default_enctypes = 1;
-+ goto do_the_parse;
-+ }
-+ if (nbytes > nscanned) {
-+ printerr(2, "gssd_obtain_kernel_krb5_info: "
-+ "Ignoring extra information, '%s', from '%s'\n",
-+ buf+nscanned, enctype_file_name);
-+ goto do_the_parse;
-+ }
-+ do_the_parse:
-+ if (use_default_enctypes)
-+ strcpy(enctypes, default_enctypes);
-+
-+ if ((code = parse_enctypes(enctypes)) != 0) {
-+ printerr(0, "ERROR: gssd_obtain_kernel_krb5_info: "
-+ "parse_enctypes%s failed with code %d\n",
-+ use_default_enctypes ? " (with default enctypes)" : "",
-+ code);
-+ }
-+}
-diff --git a/utils/gssd/krb5_util.h b/utils/gssd/krb5_util.h
-index da04530..2af1a25 100644
---- a/utils/gssd/krb5_util.h
-+++ b/utils/gssd/krb5_util.h
-@@ -22,6 +22,8 @@ int gssd_refresh_krb5_machine_creds(voi
- void gssd_free_krb5_machine_cred_list(char **list);
- void gssd_setup_krb5_machine_gss_ccache(char *servername);
- void gssd_destroy_krb5_machine_creds(void);
-+void gssd_obtain_kernel_krb5_info(void);
-+
- #ifdef HAVE_SET_ALLOWABLE_ENCTYPES
- int limit_krb5_enctypes(struct rpc_gss_sec *sec, uid_t uid);
-diff --git a/utils/gssd/context.h b/utils/gssd/context.h
-index 67ed3bb..68b0c11 100644
---- a/utils/gssd/context.h
-+++ b/utils/gssd/context.h
-@@ -1,5 +1,5 @@
- /*
-- Copyright (c) 2004 The Regents of the University of Michigan.
-+ Copyright (c) 2004-2006 The Regents of the University of Michigan.
- All rights reserved.
++#include "pseudoflavors.h"
+ #include "nls.h"
+ #include "conn.h"
+ #include "xcommon.h"
+@@ -71,26 +72,6 @@ char *GSSDLCK = DEFAULT_DIR "/rpcgssd";
+ #define NFS_PORT 2049
+ #endif
- Redistribution and use in source and binary forms, with or without
-@@ -36,6 +36,10 @@ #include <rpc/rpc.h>
- /* Hopefully big enough to hold any serialized context */
- #define MAX_CTX_LEN 4096
+-struct {
+- char *flavour;
+- int fnum;
+-} flav_map[] = {
+- { "krb5", RPC_AUTH_GSS_KRB5 },
+- { "krb5i", RPC_AUTH_GSS_KRB5I },
+- { "krb5p", RPC_AUTH_GSS_KRB5P },
+- { "lipkey", RPC_AUTH_GSS_LKEY },
+- { "lipkey-i", RPC_AUTH_GSS_LKEYI },
+- { "lipkey-p", RPC_AUTH_GSS_LKEYP },
+- { "spkm3", RPC_AUTH_GSS_SPKM },
+- { "spkm3i", RPC_AUTH_GSS_SPKMI },
+- { "spkm3p", RPC_AUTH_GSS_SPKMP },
+- { "unix", AUTH_UNIX },
+- { "sys", AUTH_SYS },
+- { "null", AUTH_NULL },
+- { "none", AUTH_NONE },
+-};
+-
+-#define FMAPSIZE (sizeof(flav_map)/sizeof(flav_map[0]))
+ #define MAX_USER_FLAVOUR 16
-+/* New context format flag values */
-+#define KRB5_CTX_FLAG_INITIATOR 0x00000001
-+#define KRB5_CTX_FLAG_CFX 0x00000002
-+#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004
+ static int parse_sec(char *sec, int *pseudoflavour)
+@@ -104,13 +85,13 @@ static int parse_sec(char *sec, int *pse
+ "exceeded\n"));
+ return 0;
+ }
+- for (i = 0; i < FMAPSIZE; i++) {
++ for (i = 0; i < flav_map_size; i++) {
+ if (strcmp(sec, flav_map[i].flavour) == 0) {
+ pseudoflavour[num_flavour++] = flav_map[i].fnum;
+ break;
+ }
+ }
+- if (i == FMAPSIZE) {
++ if (i == flav_map_size) {
+ fprintf(stderr,
+ _("mount: unknown security type %s\n"), sec);
+ return 0;
+@@ -399,7 +380,7 @@ int nfs4mount(const char *spec, const ch
+
+ printf("sec = ");
+ for (pf_cnt = 0; pf_cnt < num_flavour; pf_cnt++) {
+- for (i = 0; i < FMAPSIZE; i++) {
++ for (i = 0; i < flav_map_size; i++) {
+ if (flav_map[i].fnum == pseudoflavour[pf_cnt]) {
+ printf("%s", flav_map[i].flavour);
+ break;
+diff -puN utils/mount/nfs4_mount.h~CITI_NFS4_ALL utils/mount/nfs4_mount.h
+--- nfs-utils-1.1.0/utils/mount/nfs4_mount.h~CITI_NFS4_ALL 2007-06-22 10:52:21.626744000 -0400
++++ nfs-utils-1.1.0-kwc/utils/mount/nfs4_mount.h 2007-06-22 10:52:24.715391000 -0400
+@@ -67,18 +67,6 @@ struct nfs4_mount_data {
+ #define NFS4_MOUNT_STRICTLOCK 0x1000 /* 1 */
+ #define NFS4_MOUNT_FLAGMASK 0xFFFF
+
+-/* pseudoflavors: */
+-
+-#define RPC_AUTH_GSS_KRB5 390003
+-#define RPC_AUTH_GSS_KRB5I 390004
+-#define RPC_AUTH_GSS_KRB5P 390005
+-#define RPC_AUTH_GSS_LKEY 390006
+-#define RPC_AUTH_GSS_LKEYI 390007
+-#define RPC_AUTH_GSS_LKEYP 390008
+-#define RPC_AUTH_GSS_SPKM 390009
+-#define RPC_AUTH_GSS_SPKMI 390010
+-#define RPC_AUTH_GSS_SPKMP 390011
+-
+ int nfs4mount(const char *, const char *, int *, char **,
+ char **, int);
- int serialize_context_for_kernel(gss_ctx_id_t ctx, gss_buffer_desc *buf,
- gss_OID mech);
-diff --git a/utils/gssd/context_lucid.c b/utils/gssd/context_lucid.c
-index 3550762..c824dcd 100644
---- a/utils/gssd/context_lucid.c
-+++ b/utils/gssd/context_lucid.c
-@@ -40,6 +40,7 @@ #ifdef HAVE_LUCID_CONTEXT_SUPPORT
- #include <stdio.h>
- #include <syslog.h>
- #include <string.h>
-+#include <errno.h>
- #include "gss_util.h"
- #include "gss_oids.h"
- #include "err_util.h"
-@@ -113,15 +114,13 @@ #ifdef HAVE_HEIMDAL
- * Note that the rfc1964 version only supports DES enctypes.
- */
- if (lctx->rfc1964_kd.ctx_key.type != 4) {
-- printerr(1, "prepare_krb5_rfc1964_buffer: "
-- "overriding heimdal keytype (%d => %d)\n",
-- lctx->rfc1964_kd.ctx_key.type, 4);
-+ printerr(2, "%s: overriding heimdal keytype (%d => %d)\n",
-+ __FUNCTION__, lctx->rfc1964_kd.ctx_key.type, 4);
- lctx->rfc1964_kd.ctx_key.type = 4;
- }
+diff -puN support/include/nfslib.h~CITI_NFS4_ALL support/include/nfslib.h
+--- nfs-utils-1.1.0/support/include/nfslib.h~CITI_NFS4_ALL 2007-06-22 10:52:31.311234000 -0400
++++ nfs-utils-1.1.0-kwc/support/include/nfslib.h 2007-06-22 10:52:39.718626000 -0400
+@@ -51,6 +51,14 @@
+ #define _PATH_PROC_EXPORTS_ALT "/proc/fs/nfsd/exports"
#endif
-- printerr(2, "prepare_krb5_rfc1964_buffer: serializing keys with "
-- "enctype %d and length %d\n",
-- lctx->rfc1964_kd.ctx_key.type,
-+ printerr(2, "%s: serializing keys with enctype %d and length %d\n",
-+ __FUNCTION__, lctx->rfc1964_kd.ctx_key.type,
- lctx->rfc1964_kd.ctx_key.length);
-
- /* derive the encryption key and copy it into buffer */
-@@ -152,15 +151,361 @@ out_err:
- return -1;
- }
--static int
--prepare_krb5_rfc_cfx_buffer(gss_krb5_lucid_context_v1_t *lctx,
-- gss_buffer_desc *buf)
-+/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
-+/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
++/* Maximum number of security flavors on an export: */
++#define SECFLAVOR_COUNT 8
+
-+/* for 3DES */
-+#define KG_USAGE_SEAL 22
-+#define KG_USAGE_SIGN 23
-+#define KG_USAGE_SEQ 24
-+
-+/* for rfc???? */
-+#define KG_USAGE_ACCEPTOR_SEAL 22
-+#define KG_USAGE_ACCEPTOR_SIGN 23
-+#define KG_USAGE_INITIATOR_SEAL 24
-+#define KG_USAGE_INITIATOR_SIGN 25
-+
-+/* Lifted from mit src/lib/gssapi/krb5/gssapiP_krb5.h */
-+enum seal_alg {
-+ SEAL_ALG_NONE = 0xffff,
-+ SEAL_ALG_DES = 0x0000,
-+ SEAL_ALG_1 = 0x0001, /* not published */
-+ SEAL_ALG_MICROSOFT_RC4 = 0x0010, /* microsoft w2k; */
-+ SEAL_ALG_DES3KD = 0x0002
++struct sec_entry {
++ struct flav_info *flav;
++ int flags;
+};
+
-+#define KEY_USAGE_SEED_ENCRYPTION 0xAA
-+#define KEY_USAGE_SEED_INTEGRITY 0x55
-+#define KEY_USAGE_SEED_CHECKSUM 0x99
-+#define K5CLENGTH 5
-+
-+/* Flags for version 2 context flags */
-+#define KRB5_CTX_FLAG_INITIATOR 0x00000001
-+#define KRB5_CTX_FLAG_CFX 0x00000002
-+#define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004
-+
-+/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
-+/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
-+/*
-+ * We don't have "legal" access to these MIT-only
-+ * structures located in libk5crypto
-+ */
-+extern void krb5int_enc_arcfour;
-+extern void krb5int_enc_des3;
-+extern void krb5int_enc_aes128;
-+extern void krb5int_enc_aes256;
-+extern int krb5_derive_key();
-+
-+static void
-+key_lucid_to_krb5(const gss_krb5_lucid_key_t *lin, krb5_keyblock *kout)
- {
-- printerr(0, "ERROR: prepare_krb5_rfc_cfx_buffer: not implemented\n");
-- return -1;
-+ memset(kout, '\0', sizeof(kout));
-+#ifdef HAVE_KRB5
-+ kout->enctype = lin->type;
-+ kout->length = lin->length;
-+ kout->contents = lin->data;
-+#else
-+ kout->keytype = lin->type;
-+ kout->keyvalue.length = lin->length;
-+ kout->keyvalue.data = lin->data;
-+#endif
-+}
-+
-+static void
-+key_krb5_to_lucid(const krb5_keyblock *kin, gss_krb5_lucid_key_t *lout)
-+{
-+ memset(lout, '\0', sizeof(lout));
-+#ifdef HAVE_KRB5
-+ lout->type = kin->enctype;
-+ lout->length = kin->length;
-+ lout->data = kin->contents;
-+#else
-+ lout->type = kin->keytype;
-+ lout->length = kin->keyvalue.length;
-+ memcpy(lout->data, kin->keyvalue.data, kin->keyvalue.length);
-+#endif
-+}
-+
-+/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
-+/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
-+/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
-+/* XXX Hack alert! XXX Do NOT submit upstream! XXX */
-+/*
-+ * Function to derive a new key from a given key and given constant data.
-+ */
-+static krb5_error_code
-+derive_key_lucid(const gss_krb5_lucid_key_t *in, gss_krb5_lucid_key_t *out,
-+ int usage, char extra)
-+{
-+ krb5_error_code code;
-+ unsigned char constant_data[K5CLENGTH];
-+ krb5_data datain;
-+ int keylength;
-+ void *enc;
-+ krb5_keyblock kin, kout; /* must send krb5_keyblock, not lucid! */
-+#ifdef HAVE_HEIMDAL
-+ krb5_context kcontext;
-+ krb5_keyblock *outkey;
-+#endif
-+
-+ /*
-+ * XXX Hack alert. We don't have "legal" access to these
-+ * values and structures located in libk5crypto
-+ */
-+ switch (in->type) {
-+ case ENCTYPE_DES3_CBC_SHA1:
-+#ifdef HAVE_KRB5
-+ case ENCTYPE_DES3_CBC_RAW:
-+#endif
-+ keylength = 24;
-+#ifdef HAVE_KRB5
-+ enc = &krb5int_enc_des3;
-+#endif
-+ break;
-+ case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
-+ keylength = 16;
-+#ifdef HAVE_KRB5
-+ enc = &krb5int_enc_aes128;
-+#endif
-+ break;
-+ case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
-+ keylength = 32;
-+#ifdef HAVE_KRB5
-+ enc = &krb5int_enc_aes256;
-+#endif
-+ break;
-+ default:
-+ code = KRB5_BAD_ENCTYPE;
-+ goto out;
-+ }
-+
-+ /* allocate memory for output key */
-+ if ((out->data = malloc(keylength)) == NULL) {
-+ code = ENOMEM;
-+ goto out;
-+ }
-+ out->length = keylength;
-+ out->type = in->type;
-+
-+ /* Convert to correct format for call to krb5_derive_key */
-+ key_lucid_to_krb5(in, &kin);
-+ key_lucid_to_krb5(out, &kout);
-+
-+ datain.data = (char *) constant_data;
-+ datain.length = K5CLENGTH;
-+
-+ ((char *)(datain.data))[0] = (usage>>24)&0xff;
-+ ((char *)(datain.data))[1] = (usage>>16)&0xff;
-+ ((char *)(datain.data))[2] = (usage>>8)&0xff;
-+ ((char *)(datain.data))[3] = usage&0xff;
-+
-+ ((char *)(datain.data))[4] = (char) extra;
-+
-+#ifdef HAVE_KRB5
-+ code = krb5_derive_key(enc, &kin, &kout, &datain);
-+#else
-+ if ((code = krb5_init_context(&kcontext))) {
-+ }
-+ code = krb5_derive_key(kcontext, &kin, in->type, constant_data, K5CLENGTH, &outkey);
-+#endif
-+ if (code) {
-+ free(out->data);
-+ out->data = NULL;
-+ goto out;
-+ }
-+#ifdef HAVE_KRB5
-+ key_krb5_to_lucid(&kout, out);
-+#else
-+ key_krb5_to_lucid(outkey, out);
-+ krb5_free_keyblock(kcontext, outkey);
-+ krb5_free_context(kcontext);
-+#endif
-+
-+ out:
-+ if (code)
-+ printerr(0, "ERROR: %s: returning error %d (%s)\n",
-+ __FUNCTION__, code, error_message(code));
-+ return (code);
- }
-
-
-+/*
-+ * Prepare a new-style buffer, as defined in rfc4121 (a.k.a. cfx),
-+ * to send to the kernel for newer encryption types -- or for DES3.
-+ *
-+ * The new format is:
-+ *
-+ * u32 initiate; ( whether we are the initiator or not )
-+ * s32 endtime;
-+ * u32 flags;
-+ * #define KRB5_CTX_FLAG_INITIATOR 0x00000001
-+ * #define KRB5_CTX_FLAG_CFX 0x00000002
-+ * #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004
-+ * u64 seq_send;
-+ * u32 enctype; ( encrption type of keys )
-+ * u32 size_of_each_key; ( size of each key in bytes )
-+ * u32 number_of_keys; ( N -- should always be 3 for now )
-+ * keydata-1; ( Ke )
-+ * keydata-2; ( Ki )
-+ * keydata-3; ( Kc )
-+ *
-+ */
-+static int
-+prepare_krb5_rfc4121_buffer(gss_krb5_lucid_context_v1_t *lctx,
-+ gss_buffer_desc *buf)
-+{
-+ char *p, *end;
-+ uint32_t v2_flags = 0;
-+ gss_krb5_lucid_key_t enc_key;
-+ gss_krb5_lucid_key_t derived_key;
-+ gss_buffer_desc fakeoid;
-+ uint32_t enctype;
-+ uint32_t keysize;
-+ uint32_t numkeys;
-+
-+ memset(&enc_key, 0, sizeof(enc_key));
-+ memset(&fakeoid, 0, sizeof(fakeoid));
-+
-+ if (!(buf->value = calloc(1, MAX_CTX_LEN)))
-+ goto out_err;
-+ p = buf->value;
-+ end = buf->value + MAX_CTX_LEN;
-+
-+ /* Version 2 */
-+ if (WRITE_BYTES(&p, end, lctx->initiate)) goto out_err;
-+ if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err;
-+
-+ if (lctx->initiate)
-+ v2_flags |= KRB5_CTX_FLAG_INITIATOR;
-+ if (lctx->protocol != 0)
-+ v2_flags |= KRB5_CTX_FLAG_CFX;
-+ if (lctx->protocol != 0 && lctx->cfx_kd.have_acceptor_subkey == 1)
-+ v2_flags |= KRB5_CTX_FLAG_ACCEPTOR_SUBKEY;
-+
-+ if (WRITE_BYTES(&p, end, v2_flags)) goto out_err;
-+
-+ 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);
-+ if (lctx->protocol == 0) {
-+ enctype = lctx->rfc1964_kd.ctx_key.type;
-+#ifdef HAVE_HEIMDAL
-+ /*
-+ * The kernel gss code expects ENCTYPE_DES3_CBC_RAW (6) for
-+ * 3des keys, but Heimdal key has ENCTYPE_DES3_CBC_SHA1 (16).
-+ * Force the Heimdal enctype to 6.
-+ */
-+ if (enctype == ENCTYPE_DES3_CBC_SHA1) {
-+ printerr(2, "%s: overriding heimdal keytype (%d => %d)\n",
-+ __FUNCTION__, enctype, 6);
-+
-+ enctype = 6;
-+ }
-+#endif
-+ keysize = lctx->rfc1964_kd.ctx_key.length;
-+ numkeys = 3; /* XXX is always gonna be three? */
-+ } else {
-+ if (lctx->cfx_kd.have_acceptor_subkey) {
-+ enctype = lctx->cfx_kd.acceptor_subkey.type;
-+ keysize = lctx->cfx_kd.acceptor_subkey.length;
-+ } else {
-+ enctype = lctx->cfx_kd.ctx_key.type;
-+ keysize = lctx->cfx_kd.ctx_key.length;
-+ }
-+ numkeys = 3;
-+ }
-+ printerr(2, "%s: serializing %d keys with enctype %d and size %d\n",
-+ __FUNCTION__, 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;
-+
-+ if (lctx->protocol == 0) {
-+ /* derive and send down: Ke, Ki, and Kc */
-+ /* Ke */
-+ if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
-+ lctx->rfc1964_kd.ctx_key.length))
-+ goto out_err;
-+
-+ /* Ki */
-+ if (write_bytes(&p, end, lctx->rfc1964_kd.ctx_key.data,
-+ lctx->rfc1964_kd.ctx_key.length))
-+ 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);
-+ } else {
-+ gss_krb5_lucid_key_t *keyptr;
-+ uint32_t sign_usage, seal_usage;
-+
-+ if (lctx->cfx_kd.have_acceptor_subkey)
-+ keyptr = &lctx->cfx_kd.acceptor_subkey;
-+ else
-+ keyptr = &lctx->cfx_kd.ctx_key;
-+
-+ if (lctx->initiate == 1) {
-+ sign_usage = KG_USAGE_INITIATOR_SIGN;
-+ seal_usage = KG_USAGE_INITIATOR_SEAL;
-+ } else {
-+ sign_usage = KG_USAGE_ACCEPTOR_SIGN;
-+ seal_usage = KG_USAGE_ACCEPTOR_SEAL;
-+ }
-+
-+ /* derive and send down: Ke, Ki, and Kc */
-+
-+ /* Ke */
-+ if (derive_key_lucid(keyptr, &derived_key,
-+ seal_usage, KEY_USAGE_SEED_ENCRYPTION))
-+ goto out_err;
-+ if (write_bytes(&p, end, derived_key.data,
-+ derived_key.length))
-+ goto out_err;
-+ free(derived_key.data);
-+
-+ /* Ki */
-+ if (derive_key_lucid(keyptr, &derived_key,
-+ seal_usage, KEY_USAGE_SEED_INTEGRITY))
-+ goto out_err;
-+ if (write_bytes(&p, end, derived_key.data,
-+ derived_key.length))
-+ goto out_err;
-+ free(derived_key.data);
-+
-+ /* Kc */
-+ if (derive_key_lucid(keyptr, &derived_key,
-+ sign_usage, 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);
-+ }
-+
-+ buf->length = p - (char *)buf->value;
-+ return 0;
-+
-+out_err:
-+ printerr(0, "ERROR: %s: failed serializing krb5 context for kernel\n",
-+ __FUNCTION__);
-+ if (buf->value) {
-+ free(buf->value);
-+ buf->value = NULL;
-+ }
-+ buf->length = 0;
-+ if (enc_key.data) {
-+ free(enc_key.data);
-+ enc_key.data = NULL;
-+ }
-+ return -1;
-+}
- int
- serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf)
- {
-@@ -170,7 +515,7 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
- gss_krb5_lucid_context_v1_t *lctx = 0;
- int retcode = 0;
-
-- printerr(2, "DEBUG: serialize_krb5_ctx: lucid version!\n");
-+ printerr(2, "DEBUG: %s: lucid version!\n", __FUNCTION__);
- maj_stat = gss_export_lucid_sec_context(&min_stat, &ctx,
- 1, &return_ctx);
- if (maj_stat != GSS_S_COMPLETE) {
-@@ -192,11 +537,20 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
- break;
- }
-
-- /* Now lctx points to a lucid context that we can send down to kernel */
-- if (lctx->protocol == 0)
-+ /*
-+ * Now lctx points to a lucid context that we can send down to kernel
-+ *
-+ * Note: we send down different information to the kernel depending
-+ * on the protocol version and the enctyption type.
-+ * For protocol version 0 with all enctypes besides DES3, we use
-+ * the original format. For protocol version != 0 or DES3, we
-+ * send down the new style information.
-+ */
-+
-+ if (lctx->protocol == 0 && lctx->rfc1964_kd.ctx_key.type <= 4)
- retcode = prepare_krb5_rfc1964_buffer(lctx, buf);
- else
-- retcode = prepare_krb5_rfc_cfx_buffer(lctx, buf);
-+ retcode = prepare_krb5_rfc4121_buffer(lctx, buf);
-
- maj_stat = gss_free_lucid_sec_context(&min_stat, ctx, return_ctx);
- if (maj_stat != GSS_S_COMPLETE) {
-@@ -206,8 +560,8 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
- }
-
- if (retcode) {
-- printerr(1, "serialize_krb5_ctx: prepare_krb5_*_buffer "
-- "failed (retcode = %d)\n", retcode);
-+ printerr(1, "%s: prepare_krb5_*_buffer failed (retcode = %d)\n",
-+ __FUNCTION__, retcode);
- goto out_err;
- }
-
-@@ -217,4 +571,7 @@ out_err:
- printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
- return -1;
- }
-+
-+
-+
- #endif /* HAVE_LUCID_CONTEXT_SUPPORT */
-diff --git a/utils/gssd/context_mit.c b/utils/gssd/context_mit.c
-index 94b2266..cd6ab0f 100644
---- a/utils/gssd/context_mit.c
-+++ b/utils/gssd/context_mit.c
-@@ -1,5 +1,5 @@
/*
-- Copyright (c) 2004 The Regents of the University of Michigan.
-+ Copyright (c) 2004-2006 The Regents of the University of Michigan.
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
-@@ -36,6 +36,7 @@ #ifdef HAVE_KRB5
- #include <stdio.h>
- #include <syslog.h>
- #include <string.h>
-+#include <errno.h>
- #include <gssapi/gssapi.h>
- #include <rpc/rpc.h>
- #include <rpc/auth_gss.h>
-@@ -50,8 +51,7 @@ #if (KRB5_VERSION > 131)
- /* XXX argggg, there's gotta be a better way than just duplicating this
- * whole struct. Unfortunately, this is in a "private" header file,
- * so this is our best choice at this point :-/
-- *
-- * XXX Does this match the Heimdal definition? */
-+ */
+ * Data related to a single exports entry as returned by getexportent.
+ * FIXME: export options should probably be parsed at a later time to
+@@ -76,6 +84,7 @@ struct exportent {
+ int e_fslocmethod;
+ char * e_fslocdata;
+ char * e_uuid;
++ struct sec_entry e_secinfo[SECFLAVOR_COUNT+1];
+ };
- typedef struct _krb5_gss_ctx_id_rec {
- unsigned int initiate : 1; /* nonzero if initiating, zero if accepting */
-@@ -139,6 +139,124 @@ write_keyblock(char **p, char *end, stru
+ struct rmtabent {
+@@ -89,6 +98,7 @@ struct rmtabent {
+ */
+ void setexportent(char *fname, char *type);
+ struct exportent * getexportent(int,int);
++void secinfo_show(FILE *fp, struct exportent *ep);
+ void putexportent(struct exportent *xep);
+ void endexportent(void);
+ struct exportent * mkexportent(char *hname, char *path, char *opts);
+diff -puN utils/exportfs/exportfs.c~CITI_NFS4_ALL utils/exportfs/exportfs.c
+--- nfs-utils-1.1.0/utils/exportfs/exportfs.c~CITI_NFS4_ALL 2007-06-22 10:52:33.386332000 -0400
++++ nfs-utils-1.1.0-kwc/utils/exportfs/exportfs.c 2007-06-22 10:52:40.698175000 -0400
+@@ -515,6 +515,7 @@ dump(int verbose)
+ break;
+ #endif
+ }
++ secinfo_show(stdout, ep);
+ printf("%c\n", (c != '(')? ')' : ' ');
+ }
+ }
+diff -puN utils/mountd/cache.c~CITI_NFS4_ALL utils/mountd/cache.c
+--- nfs-utils-1.1.0/utils/mountd/cache.c~CITI_NFS4_ALL 2007-06-22 10:52:38.862018000 -0400
++++ nfs-utils-1.1.0-kwc/utils/mountd/cache.c 2007-06-22 10:52:40.837142000 -0400
+@@ -30,6 +30,7 @@
+ #include "mountd.h"
+ #include "xmalloc.h"
+ #include "fsloc.h"
++#include "pseudoflavors.h"
+
+ #ifdef USE_BLKID
+ #include "blkid/blkid.h"
+@@ -518,6 +519,25 @@ static void write_fsloc(FILE *f, struct
+ release_replicas(servers);
}
- /*
-+ * XXX Hack alert! XXX Do NOT submit upstream!
-+ * XXX Hack alert! XXX Do NOT submit upstream!
-+ *
-+ * We shouldn't be using these definitions
-+ *
-+ * XXX Hack alert! XXX Do NOT submit upstream!
-+ * XXX Hack alert! XXX Do NOT submit upstream!
-+ */
-+/* for 3DES */
-+#define KG_USAGE_SEAL 22
-+#define KG_USAGE_SIGN 23
-+#define KG_USAGE_SEQ 24
-+
-+/* for rfc???? */
-+#define KG_USAGE_ACCEPTOR_SEAL 22
-+#define KG_USAGE_ACCEPTOR_SIGN 23
-+#define KG_USAGE_INITIATOR_SEAL 24
-+#define KG_USAGE_INITIATOR_SIGN 25
-+
-+/* Lifted from mit src/lib/gssapi/krb5/gssapiP_krb5.h */
-+enum seal_alg {
-+ SEAL_ALG_NONE = 0xffff,
-+ SEAL_ALG_DES = 0x0000,
-+ SEAL_ALG_1 = 0x0001, /* not published */
-+ SEAL_ALG_MICROSOFT_RC4 = 0x0010, /* microsoft w2k; */
-+ SEAL_ALG_DES3KD = 0x0002
-+};
-+
-+#define KEY_USAGE_SEED_ENCRYPTION 0xAA
-+#define KEY_USAGE_SEED_INTEGRITY 0x55
-+#define KEY_USAGE_SEED_CHECKSUM 0x99
-+#define K5CLENGTH 5
-+
-+extern void krb5_enc_des3;
-+extern void krb5int_enc_des3;
-+extern void krb5int_enc_arcfour;
-+extern void krb5int_enc_aes128;
-+extern void krb5int_enc_aes256;
-+extern int krb5_derive_key();
-+
-+/*
-+ * XXX Hack alert! XXX Do NOT submit upstream!
-+ * XXX Hack alert! XXX Do NOT submit upstream!
-+ *
-+ * We should be passing down a single key to the kernel
-+ * and it should be deriving the other keys. We cannot
-+ * depend on any of this stuff being accessible in the
-+ * future.
-+ *
-+ * XXX Hack alert! XXX Do NOT submit upstream!
-+ * XXX Hack alert! XXX Do NOT submit upstream!
-+ */
-+/*
-+ * Function to derive a new key from a given key and given constant data.
-+ */
-+static krb5_error_code
-+derive_key(const krb5_keyblock *in, krb5_keyblock *out, int usage, char extra)
++static void write_secinfo(FILE *f, struct exportent *ep)
+{
-+ krb5_error_code code;
-+ unsigned char constant_data[K5CLENGTH];
-+ krb5_data datain;
-+ int keylength;
-+ void *enc;
-+
-+ switch (in->enctype) {
-+#ifdef ENCTYPE_DES3_CBC_RAW
-+ case ENCTYPE_DES3_CBC_RAW:
-+ keylength = 24;
-+/* Extra hack, the structure was renamed as rc4 was added... */
-+#if defined(ENCTYPE_ARCFOUR_HMAC)
-+ enc = &krb5int_enc_des3;
-+#else
-+ enc = &krb5_enc_des3;
-+#endif
-+ break;
-+#endif
-+#ifdef ENCTYPE_ARCFOUR_HMAC
-+ case ENCTYPE_ARCFOUR_HMAC:
-+ keylength = 16;
-+ enc = &krb5int_enc_arcfour;
-+ break;
-+#endif
-+ default:
-+ code = KRB5_BAD_ENCTYPE;
-+ goto out;
-+ }
++ struct sec_entry *p;
+
-+ /* allocate memory for output key */
-+ if ((out->contents = malloc(keylength)) == NULL) {
-+ code = ENOMEM;
-+ goto out;
++ for (p = ep->e_secinfo; p->flav; p++)
++ ; /* Do nothing */
++ if (p == ep->e_secinfo) {
++ /* There was no sec= option */
++ return;
+ }
-+ out->length = keylength;
-+ out->enctype = in->enctype;
-+
-+ datain.data = (char *) constant_data;
-+ datain.length = K5CLENGTH;
-+
-+ datain.data[0] = (usage>>24)&0xff;
-+ datain.data[1] = (usage>>16)&0xff;
-+ datain.data[2] = (usage>>8)&0xff;
-+ datain.data[3] = usage&0xff;
-+
-+ datain.data[4] = (char) extra;
-+
-+ if ((code = krb5_derive_key(enc, in, out, &datain))) {
-+ free(out->contents);
-+ out->contents = NULL;
++ qword_print(f, "secinfo");
++ qword_printint(f, p - ep->e_secinfo);
++ for (p = ep->e_secinfo; p->flav; p++) {
++ qword_printint(f, p->flav->fnum);
++ qword_printint(f, p->flags);
+ }
+
-+ out:
-+ if (code)
-+ printerr(0, "ERROR: derive_key returning error %d (%s)\n",
-+ code, error_message(code));
-+ return (code);
+}
+
-+/*
- * We really shouldn't know about glue-layer context structure, but
- * we need to get at the real krb5 context pointer. This should be
- * removed as soon as we say there is no support for MIT Kerberos
-@@ -154,48 +272,124 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss
+ static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *exp)
{
- krb5_gss_ctx_id_t kctx = ((gss_union_ctx_id_t)ctx)->internal_ctx_id;
- char *p, *end;
-- static int constant_one = 1;
- static int constant_zero = 0;
-+ static int constant_one = 1;
-+ static int constant_two = 2;
- uint32_t word_seq_send;
-+ u_int64_t seq_send_64bit;
-+ uint32_t v2_flags = 0;
-+ krb5_keyblock derived_key;
-+ uint32_t numkeys;
-
- if (!(buf->value = calloc(1, MAX_CTX_LEN)))
- goto out_err;
- p = buf->value;
- end = buf->value + MAX_CTX_LEN;
-
-- 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 (kctx->seed_init) {
-- 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, &kctx->seed, sizeof(kctx->seed)))
-- goto out_err;
-- if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err;
-- if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err;
-- if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
-- word_seq_send = kctx->seq_send;
-- if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err;
-- if (write_oid(&p, end, kctx->mech_used)) goto out_err;
-+ switch (kctx->sealalg) {
-+ case SEAL_ALG_DES:
-+ /* Old format of context to the kernel */
-+ 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 (kctx->seed_init) {
-+ 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, &kctx->seed, sizeof(kctx->seed)))
-+ goto out_err;
-+ if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err;
-+ if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err;
-+ if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
-+ word_seq_send = kctx->seq_send;
-+ if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err;
-+ if (write_oid(&p, end, kctx->mech_used)) goto out_err;
-+
-+ printerr(2, "serialize_krb5_ctx: serializing keys with "
-+ "enctype %d and length %d\n",
-+ kctx->enc->enctype, kctx->enc->length);
-+
-+ if (write_keyblock(&p, end, kctx->enc)) goto out_err;
-+ if (write_keyblock(&p, end, kctx->seq)) goto out_err;
-+ break;
-+ case SEAL_ALG_MICROSOFT_RC4:
-+ case SEAL_ALG_DES3KD:
-+ /* New format of context to the kernel */
-+ /* s32 endtime;
-+ * u32 flags;
-+ * #define KRB5_CTX_FLAG_INITIATOR 0x00000001
-+ * #define KRB5_CTX_FLAG_CFX 0x00000002
-+ * #define KRB5_CTX_FLAG_ACCEPTOR_SUBKEY 0x00000004
-+ * u64 seq_send;
-+ * u32 enctype;
-+ * u32 size_of_each_key; ( size in bytes )
-+ * u32 number_of_keys; ( N (assumed to be 3 for now) )
-+ * keydata-1; ( Ke (Kenc for DES3) )
-+ * 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, kctx->endtime)) goto out_err;
-+
-+ /* Only applicable flag for this is initiator */
-+ if (kctx->initiate) v2_flags |= KRB5_CTX_FLAG_INITIATOR;
-+ if (WRITE_BYTES(&p, end, v2_flags)) goto out_err;
-+
-+ seq_send_64bit = kctx->seq_send;
-+ if (WRITE_BYTES(&p, end, seq_send_64bit)) goto out_err;
-
-- printerr(2, "serialize_krb5_ctx: serializing keys with "
-- "enctype %d and length %d\n",
-- kctx->enc->enctype, kctx->enc->length);
-+ if (WRITE_BYTES(&p, end, kctx->enc->enctype)) goto out_err;
-+ if (WRITE_BYTES(&p, end, kctx->enc->length)) goto out_err;
-+ numkeys = 3;
-+ if (WRITE_BYTES(&p, end, numkeys)) goto out_err;
-+ printerr(2, "serialize_krb5_ctx: serializing %d keys with "
-+ "enctype %d and size %d\n",
-+ numkeys, kctx->enc->enctype, kctx->enc->length);
-
-- if (write_keyblock(&p, end, kctx->enc)) goto out_err;
-- if (write_keyblock(&p, end, kctx->seq)) goto out_err;
-+ /* Ke */
-+ if (write_bytes(&p, end, kctx->enc->contents,
-+ kctx->enc->length))
-+ goto out_err;
-+
-+ /* Ki */
-+ if (write_bytes(&p, end, kctx->enc->contents,
-+ kctx->enc->length))
-+ goto out_err;
-+
-+ /* Kc */
-+ if (derive_key(kctx->seq, &derived_key,
-+ KG_USAGE_SIGN, KEY_USAGE_SEED_CHECKSUM))
-+ goto out_err;
-+ if (write_bytes(&p, end, derived_key.contents,
-+ derived_key.length))
-+ goto out_err;
-+ free(derived_key.contents);
-+ break;
-+ default:
-+ printerr(0, "ERROR: serialize_krb5_ctx: unsupported seal "
-+ "algorithm %d\n", kctx->sealalg);
-+ goto out_err;
-+ }
-
- buf->length = p - (char *)buf->value;
- return 0;
-+
- out_err:
- printerr(0, "ERROR: failed serializing krb5 context for kernel\n");
-- if (buf->value) free(buf->value);
-+ if (buf->value) {
-+ free(buf->value);
-+ }
-+ buf->value = NULL;
- buf->length = 0;
- return -1;
- }
+ qword_print(f, domain);
+@@ -529,6 +549,7 @@ static int dump_to_cache(FILE *f, char *
+ qword_printint(f, exp->e_anongid);
+ qword_printint(f, exp->e_fsid);
+ write_fsloc(f, exp, path);
++ write_secinfo(f, exp);
+ #if USE_BLKID
+ if (exp->e_uuid == NULL) {
+ char u[16];
+
+_