Allow nfs versions 2 and 3 to mount with -osec=krb5. --- util-linux-2.12-bfields/mount/nfs.5 | 37 +++++++++----- util-linux-2.12-bfields/mount/nfs_mount4.h | 18 ++++++- util-linux-2.12-bfields/mount/nfsmount.c | 74 ++++++++++++++++++++++++++++- 3 files changed, 112 insertions(+), 17 deletions(-) diff -puN mount/nfs.5~krb5 mount/nfs.5 --- util-linux-2.12/mount/nfs.5~krb5 2004-10-13 14:15:03.000000000 -0400 +++ util-linux-2.12-bfields/mount/nfs.5 2004-10-13 14:15:03.000000000 -0400 @@ -165,7 +165,7 @@ mount daemon program number. Use an alternate RPC version number to contact the mount daemon on the remote host. This option is useful for hosts that can run multiple NFS servers. -The default value is version 1. +The default value depends on which kernel you are using. .TP 1.5i .I nfsprog=n Use an alternate RPC program number to contact the @@ -178,7 +178,7 @@ NFS daemon program number. Use an alternate RPC version number to contact the NFS daemon on the remote host. This option is useful for hosts that can run multiple NFS servers. -The default value is version 2. +The default value depends on which kernel you are using. .TP 1.5i .I nolock Disable NFS locking. Do not start lockd. @@ -230,9 +230,25 @@ Suppress the retrieval of new attributes .TP 1.5i .I noac Disable all forms of attribute caching entirely. This extracts a -server performance penalty but it allows two different NFS clients -to get reasonable good results when both clients are actively -writing to common filesystem on the server. +significant performance penalty but it allows two different NFS clients +to get reasonable results when both clients are actively +writing to a common export on the server. +.TP 1.5i +.I sec=mode +Set the security flavor for this mount to "mode". +The default setting is \f3sec=sys\f1, which uses local +unix uids and gids to authenticate NFS operations (AUTH_SYS). +Other currently supported settings are: +\f3sec=krb5\f1, which uses Kerberos V5 instead of local unix uids +and gids to authenticate users; +\f3sec=krb5i\f1, which uses Kerberos V5 for user authentication +and performs integrity checking of NFS operations using secure +checksums to prevent data tampering; and +\f3sec=krb5p\f1, which uses Kerberos V5 for user authentication +and integrity checking, and encrypts NFS traffic to prevent +traffic sniffing (this is the most secure setting). +Note that there is a performance penalty when using integrity +or privacy. .TP 1.5i .I tcp Mount the NFS filesystem using the TCP protocol instead of the @@ -347,15 +363,8 @@ causes the client to use a specific call communicating with an NFS version 4 server. This option is currently ignored. .TP 1.5i -.I sec=n -Specify an advanced security mechanism for this file system. -To use Kerberos 5 mutual authentication, specify -.IR krb5 . -Kerberos 5 integrity checking is specified with -.IR krb5i , -and Kerberos 5 privacy is specified with -.IR krb5p . -Other security mechanisms may become available in the future. +.I sec=mode +Same as \f3sec=mode\f1 for the nfs filesystem type (see above). .TP 1.5i .I bg If an NFS mount attempt times out, retry the mount diff -puN mount/nfs_mount4.h~krb5 mount/nfs_mount4.h --- util-linux-2.12/mount/nfs_mount4.h~krb5 2004-10-13 14:15:03.000000000 -0400 +++ util-linux-2.12-bfields/mount/nfs_mount4.h 2004-10-13 14:16:45.000000000 -0400 @@ -8,7 +8,7 @@ * so it is easiest to ignore the kernel altogether (at compile time). */ -#define NFS_MOUNT_VERSION 4 +#define NFS_MOUNT_VERSION 5 struct nfs2_fh { char data[32]; @@ -36,6 +36,7 @@ struct nfs_mount_data { int namlen; /* 2 */ unsigned int bsize; /* 3 */ struct nfs3_fh root; /* 4 */ + int pseudoflavor; /* 5 */ }; /* bits in the flags field */ @@ -51,4 +52,19 @@ struct nfs_mount_data { #define NFS_MOUNT_KERBEROS 0x0100 /* 3 */ #define NFS_MOUNT_NONLM 0x0200 /* 3 */ #define NFS_MOUNT_BROKEN_SUID 0x0400 /* 4 */ +#define NFS_MOUNT_SECFLAVOUR 0x2000 /* 5 */ + +/* security pseudoflavors */ + +#ifndef AUTH_GSS_KRB5 +#define AUTH_GSS_KRB5 390003 +#define AUTH_GSS_KRB5I 390004 +#define AUTH_GSS_KRB5P 390005 +#define AUTH_GSS_LKEY 390006 +#define AUTH_GSS_LKEYI 390007 +#define AUTH_GSS_LKEYP 390008 +#define AUTH_GSS_SPKM 390009 +#define AUTH_GSS_SPKMI 390010 +#define AUTH_GSS_SPKMP 390011 +#endif diff -puN mount/nfsmount.c~krb5 mount/nfsmount.c --- util-linux-2.12/mount/nfsmount.c~krb5 2004-10-13 14:15:03.000000000 -0400 +++ util-linux-2.12-bfields/mount/nfsmount.c 2004-10-13 14:16:46.000000000 -0400 @@ -109,6 +109,8 @@ typedef struct { static const struct timeval TIMEOUT = { 20, 0 }; static const struct timeval RETRY_TIMEOUT = { 3, 0 }; +static int nfs_call_umount(clnt_addr_t *mnt_server, dirpath *argp); + /* Define the order in which to probe for UDP/TCP services */ static const u_int * proto_probelist(const int use_tcp) @@ -211,8 +213,10 @@ find_kernel_nfs_mount_version(void) { mnt_version = 4; /* since 2.2.18pre9 */ else if (kernel_version < MAKE_VERSION(2,3,99)) mnt_version = 3; + else if (kernel_version < MAKE_VERSION(2,6,0)) + mnt_version = 4; else - mnt_version = 4; /* since 2.3.99pre4 */ + mnt_version = 5; } if (mnt_version > NFS_MOUNT_VERSION) mnt_version = NFS_MOUNT_VERSION; @@ -596,6 +600,40 @@ parse_options(char *old_opts, struct nfs #endif } else if (!sloppy) goto bad_parameter; +#if NFS_MOUNT_VERSION >= 5 + } else if (!strcmp(opt, "sec")) { + char *secflavor = opteq+1; + /* see RFC 2623 */ + if (nfs_mount_version < 5) { + printf(_("Warning: ignoring sec=%s option\n"), secflavor); + continue; + } else if (!strcmp(secflavor, "sys")) + data->pseudoflavor = AUTH_SYS; + else if (!strcmp(secflavor, "krb5")) + data->pseudoflavor = AUTH_GSS_KRB5; + else if (!strcmp(secflavor, "krb5i")) + data->pseudoflavor = AUTH_GSS_KRB5I; + else if (!strcmp(secflavor, "krb5p")) + data->pseudoflavor = AUTH_GSS_KRB5P; + else if (!strcmp(secflavor, "lipkey")) + data->pseudoflavor = AUTH_GSS_LKEY; + else if (!strcmp(secflavor, "lipkey-i")) + data->pseudoflavor = AUTH_GSS_LKEYI; + else if (!strcmp(secflavor, "lipkey-p")) + data->pseudoflavor = AUTH_GSS_LKEYP; + else if (!strcmp(secflavor, "spkm3")) + data->pseudoflavor = AUTH_GSS_SPKM; + else if (!strcmp(secflavor, "spkm3i")) + data->pseudoflavor = AUTH_GSS_SPKMI; + else if (!strcmp(secflavor, "spkm3p")) + data->pseudoflavor = AUTH_GSS_SPKMP; + else if (!sloppy) { + printf(_("Warning: Unrecognized security flavor %s.\n"), + secflavor); + goto bad_parameter; + } + data->flags |= NFS_MOUNT_SECFLAVOUR; +#endif } else if (!strcmp(opt, "mounthost")) mounthost=xstrndup(opteq+1, strcspn(opteq+1," \t\n\r,")); @@ -745,7 +783,7 @@ nfsmount(const char *spec, const char *n mntres_t mntres; struct stat statbuf; - char *s, *p; + char *s; int bg, retry; int retval; time_t t; @@ -809,6 +847,7 @@ nfsmount(const char *spec, const char *n #if NFS_MOUNT_VERSION >= 2 data.namlen = NAME_MAX; #endif + data.pseudoflavor = AUTH_SYS; bg = 0; retry = 10000; /* 10000 minutes ~ 1 week */ @@ -847,6 +886,9 @@ nfsmount(const char *spec, const char *n printf("tcp = %d\n", (data.flags & NFS_MOUNT_TCP) != 0); #endif +#if NFS_MOUNT_VERSION >= 5 + printf("sec = %u\n", data.pseudoflavor); +#endif #endif data.version = nfs_mount_version; @@ -949,7 +991,9 @@ nfsmount(const char *spec, const char *n #endif } else { #if NFS_MOUNT_VERSION >= 4 + mountres3_ok *mountres; fhandle3 *fhandle; + int i, *flavor, yum = 0; if (mntres.nfsv3.fhs_status != 0) { fprintf(stderr, _("mount: %s:%s failed, reason given by server: %s\n"), @@ -957,6 +1001,32 @@ nfsmount(const char *spec, const char *n nfs_strerror(mntres.nfsv3.fhs_status)); goto fail; } +#if NFS_MOUNT_VERSION >= 5 + mountres = &mntres.nfsv3.mountres3_u.mountinfo; + i = mountres->auth_flavours.auth_flavours_len; + if (i <= 0) + goto noauth_flavours; + + flavor = mountres->auth_flavours.auth_flavours_val; + while (--i >= 0) { + if (flavor[i] == data.pseudoflavor) + yum = 1; +#ifdef NFS_MOUNT_DEBUG + printf("auth flavor %d: %d\n", + i, flavor[i]); +#endif + } + if (!yum) { + fprintf(stderr, + "mount: %s:%s failed, " + "security flavor not supported\n", + hostname, dirname); + /* server has registered us in mtab, send umount */ + nfs_call_umount(&mnt_server, &dirname); + goto fail; + } +noauth_flavours: +#endif fhandle = &mntres.nfsv3.mountres3_u.mountinfo.fhandle; memset(data.old_root.data, 0, NFS_FHSIZE); memset(&data.root, 0, sizeof(data.root)); _