nfs-utils/nfs-utils.1.2.8.rc4.patch
Steve Dickson 446b32aaf5 Updated to latest upstream RC release: nfs-utils.1.2.8-rc4
Signed-off-by: Steve Dickson <steved@redhat.com>
2013-03-25 10:25:28 -04:00

1576 lines
49 KiB
Diff

diff --git a/README b/README
index 61702f7..7034c00 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-This is version 1.2.6 of nfs-utils, the Linux NFS utility package.
+This is nfs-utils, the Linux NFS userland utility package.
0. PROJECT RESOURCES
diff --git a/aclocal/librpcsecgss.m4 b/aclocal/librpcsecgss.m4
index d1dd25e..e833141 100644
--- a/aclocal/librpcsecgss.m4
+++ b/aclocal/librpcsecgss.m4
@@ -14,6 +14,8 @@ AC_DEFUN([AC_LIBRPCSECGSS], [
[AC_DEFINE([HAVE_AUTHGSS_SET_DEBUG_LEVEL], 1,
[Define to 1 if you have the `authgss_set_debug_level' function.])])
+ AC_DEFINE([HAVE_AUTHGSS_FREE_PRIVATE_DATA], 1,
+ [Define to 1 if your rpcsec library provides authgss_free_private_data,])
fi
])dnl
diff --git a/aclocal/libtirpc.m4 b/aclocal/libtirpc.m4
index 19b8361..b823364 100644
--- a/aclocal/libtirpc.m4
+++ b/aclocal/libtirpc.m4
@@ -24,6 +24,13 @@ AC_DEFUN([AC_LIBTIRPC], [
fi
if test "$enable_tirpc" != "no"; then
+
+ dnl Check if library contains authgss_free_private_data
+ AC_CHECK_LIB([tirpc], [authgss_free_private_data], [have_free_private_data=yes],
+ [have_free_private_data=no])
+ fi
+
+ if test "$enable_tirpc" != "no"; then
dnl also must have the headers installed where we expect
dnl look for headers; add -I compiler option if found
AC_CHECK_HEADERS([${tirpc_header_dir}/netconfig.h],
@@ -42,6 +49,10 @@ AC_DEFUN([AC_LIBTIRPC], [
AC_DEFINE([HAVE_LIBTIRPC], 1,
[Define to 1 if you have and wish to use libtirpc.])
LIBTIRPC="-ltirpc"
+ if test "$have_free_private_data" = "yes"; then
+ AC_DEFINE([HAVE_AUTHGSS_FREE_PRIVATE_DATA], 1,
+ [Define to 1 if your rpcsec library provides authgss_free_private_data,])
+ fi
else
LIBTIRPC=""
fi
diff --git a/configure.ac b/configure.ac
index f461219..cc7f3b4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -358,7 +358,7 @@ AC_CHECK_HEADERS([arpa/inet.h fcntl.h libintl.h limits.h \
stdlib.h string.h sys/file.h sys/ioctl.h sys/mount.h \
sys/param.h sys/socket.h sys/time.h sys/vfs.h \
syslog.h unistd.h com_err.h et/com_err.h \
- ifaddrs.h nfs-plugin.h])
+ ifaddrs.h nfs-plugin.h libio.h])
dnl *************************************************************
dnl Checks for typedefs, structures, and compiler characteristics
diff --git a/support/export/rmtab.c b/support/export/rmtab.c
index 31c0f50..d16b3b3 100644
--- a/support/export/rmtab.c
+++ b/support/export/rmtab.c
@@ -1,7 +1,7 @@
/*
- * support/export/rmntab.c
+ * support/export/rmtab.c
*
- * Interface to the rmnt file.
+ * Interface to the rmtab file.
*
*/
@@ -12,7 +12,7 @@
#include <stdlib.h>
#include <string.h>
#include <errno.h>
-#include "xmalloc.h"
+
#include "misc.h"
#include "nfslib.h"
#include "exportfs.h"
diff --git a/support/export/xtab.c b/support/export/xtab.c
index 2a43193..e953071 100644
--- a/support/export/xtab.c
+++ b/support/export/xtab.c
@@ -14,7 +14,7 @@
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
-#include "xmalloc.h"
+
#include "nfslib.h"
#include "exportfs.h"
#include "xio.h"
diff --git a/support/include/sockaddr.h b/support/include/sockaddr.h
index 72766db..a1c30f9 100644
--- a/support/include/sockaddr.h
+++ b/support/include/sockaddr.h
@@ -20,7 +20,13 @@
#ifndef NFS_UTILS_SOCKADDR_H
#define NFS_UTILS_SOCKADDR_H
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_LIBIO_H
#include <libio.h>
+#endif
#include <stdbool.h>
#include <sys/socket.h>
#include <netinet/in.h>
diff --git a/support/nfs/cacheio.c b/support/nfs/cacheio.c
index e641c45..61e07a8 100644
--- a/support/nfs/cacheio.c
+++ b/support/nfs/cacheio.c
@@ -162,11 +162,16 @@ int qword_eol(FILE *f)
{
int err;
- fprintf(f,"\n");
- err = fflush(f);
- if (err) {
- xlog_warn("qword_eol: fflush failed: errno %d (%s)",
+ err = fprintf(f,"\n");
+ if (err < 0) {
+ xlog_warn("qword_eol: fprintf failed: errno %d (%s)",
errno, strerror(errno));
+ } else {
+ err = fflush(f);
+ if (err) {
+ xlog_warn("qword_eol: fflush failed: errno %d (%s)",
+ errno, strerror(errno));
+ }
}
/*
* We must send one line (and one line only) in a single write
diff --git a/support/nfs/exports.c b/support/nfs/exports.c
index 84a2b08..6c08a2b 100644
--- a/support/nfs/exports.c
+++ b/support/nfs/exports.c
@@ -643,6 +643,8 @@ bad_option:
cp++;
}
+ if (ep->e_secinfo[0].flav == NULL)
+ secinfo_addflavor(find_flavor("sys"), ep);
fix_pseudoflavor_flags(ep);
ep->e_squids = squids;
ep->e_sqgids = sqgids;
diff --git a/tools/nfs-iostat/nfs-iostat.py b/tools/nfs-iostat/nfs-iostat.py
index d909632..dfbef87 100644
--- a/tools/nfs-iostat/nfs-iostat.py
+++ b/tools/nfs-iostat/nfs-iostat.py
@@ -3,6 +3,8 @@
"""Emulate iostat for NFS mount points using /proc/self/mountstats
"""
+from __future__ import print_function
+
__copyright__ = """
Copyright (C) 2005, Chuck Lever <cel@netapp.com>
@@ -201,9 +203,9 @@ class DeviceData:
result = DeviceData()
# copy self into result
- for key, value in self.__nfs_data.iteritems():
+ for key, value in self.__nfs_data.items():
result.__nfs_data[key] = value
- for key, value in self.__rpc_data.iteritems():
+ for key, value in self.__rpc_data.items():
result.__rpc_data[key] = value
# compute the difference of each item in the list
@@ -233,9 +235,9 @@ class DeviceData:
client_bytes_read = float(nfs_stats['serverreadbytes'] - nfs_stats['directreadbytes'])
ratio = ((app_bytes_read - client_bytes_read) * 100) / app_bytes_read
- print
- print 'app bytes: %f client bytes %f' % (app_bytes_read, client_bytes_read)
- print 'Data cache hit ratio: %4.2f%%' % ratio
+ print()
+ print('app bytes: %f client bytes %f' % (app_bytes_read, client_bytes_read))
+ print('Data cache hit ratio: %4.2f%%' % ratio)
def __print_attr_cache_stats(self, sample_time):
"""Print attribute cache efficiency stats
@@ -255,13 +257,13 @@ class DeviceData:
data_invalidates = float(nfs_stats['datainvalidates'])
attr_invalidates = float(nfs_stats['attrinvalidates'])
- print
- print '%d inode revalidations, hitting in cache %4.2f%% of the time' % \
- (revalidates, ratio)
- print '%d open operations (mandatory GETATTR requests)' % opens
+ print()
+ print('%d inode revalidations, hitting in cache %4.2f%% of the time' % \
+ (revalidates, ratio))
+ print('%d open operations (mandatory GETATTR requests)' % opens)
if getattr_ops != 0:
- print '%4.2f%% of GETATTRs resulted in data cache invalidations' % \
- ((data_invalidates * 100) / getattr_ops)
+ print('%4.2f%% of GETATTRs resulted in data cache invalidations' % \
+ ((data_invalidates * 100) / getattr_ops))
def __print_dir_cache_stats(self, sample_time):
"""Print directory stats
@@ -277,13 +279,13 @@ class DeviceData:
lookups = nfs_stats['vfslookup']
getdents = nfs_stats['vfsreaddir']
- print
- print '%d open operations (pathname lookups)' % opens
- print '%d dentry revalidates and %d vfs lookup requests' % \
- (dentry_revals, lookups),
- print 'resulted in %d LOOKUPs on the wire' % lookup_ops
- print '%d vfs getdents calls resulted in %d READDIRs on the wire' % \
- (getdents, readdir_ops)
+ print()
+ print('%d open operations (pathname lookups)' % opens)
+ print('%d dentry revalidates and %d vfs lookup requests' % \
+ (dentry_revals, lookups))
+ print('resulted in %d LOOKUPs on the wire' % lookup_ops)
+ print('%d vfs getdents calls resulted in %d READDIRs on the wire' % \
+ (getdents, readdir_ops))
def __print_page_stats(self, sample_time):
"""Print page cache stats
@@ -297,33 +299,33 @@ class DeviceData:
vfswritepages = nfs_stats['vfswritepages']
pages_written = nfs_stats['writepages']
- print
- print '%d nfs_readpage() calls read %d pages' % \
- (vfsreadpage, vfsreadpage)
- print '%d nfs_readpages() calls read %d pages' % \
- (vfsreadpages, pages_read - vfsreadpage),
+ print()
+ print('%d nfs_readpage() calls read %d pages' % \
+ (vfsreadpage, vfsreadpage))
+ print('%d nfs_readpages() calls read %d pages' % \
+ (vfsreadpages, pages_read - vfsreadpage))
if vfsreadpages != 0:
- print '(%.1f pages per call)' % \
- (float(pages_read - vfsreadpage) / vfsreadpages)
+ print('(%.1f pages per call)' % \
+ (float(pages_read - vfsreadpage) / vfsreadpages))
else:
- print
-
- print
- print '%d nfs_updatepage() calls' % nfs_stats['vfsupdatepage']
- print '%d nfs_writepage() calls wrote %d pages' % \
- (vfswritepage, vfswritepage)
- print '%d nfs_writepages() calls wrote %d pages' % \
- (vfswritepages, pages_written - vfswritepage),
+ print()
+
+ print()
+ print('%d nfs_updatepage() calls' % nfs_stats['vfsupdatepage'])
+ print('%d nfs_writepage() calls wrote %d pages' % \
+ (vfswritepage, vfswritepage))
+ print('%d nfs_writepages() calls wrote %d pages' % \
+ (vfswritepages, pages_written - vfswritepage))
if (vfswritepages) != 0:
- print '(%.1f pages per call)' % \
- (float(pages_written - vfswritepage) / vfswritepages)
+ print('(%.1f pages per call)' % \
+ (float(pages_written - vfswritepage) / vfswritepages))
else:
- print
+ print()
congestionwaits = nfs_stats['congestionwait']
if congestionwaits != 0:
- print
- print '%d congestion waits' % congestionwaits
+ print()
+ print('%d congestion waits' % congestionwaits)
def __print_rpc_op_stats(self, op, sample_time):
"""Print generic stats for one RPC op
@@ -351,15 +353,15 @@ class DeviceData:
exe_per_op = 0.0
op += ':'
- print '%s' % op.lower().ljust(15),
- print ' ops/s\t\t kB/s\t\t kB/op\t\tretrans\t\tavg RTT (ms)\tavg exe (ms)'
+ print('%s' % op.lower().ljust(15))
+ print(' ops/s\t\t kB/s\t\t kB/op\t\tretrans\t\tavg RTT (ms)\tavg exe (ms)')
- print '\t\t%7.3f' % (ops / sample_time),
- print '\t%7.3f' % (kilobytes / sample_time),
- print '\t%7.3f' % kb_per_op,
- print ' %7d (%3.1f%%)' % (retrans, retrans_percent),
- print '\t%7.3f' % rtt_per_op,
- print '\t%7.3f' % exe_per_op
+ print('\t\t%7.3f' % (ops / sample_time))
+ print('\t%7.3f' % (kilobytes / sample_time))
+ print('\t%7.3f' % kb_per_op)
+ print(' %7d (%3.1f%%)' % (retrans, retrans_percent))
+ print('\t%7.3f' % rtt_per_op)
+ print('\t%7.3f' % exe_per_op)
def ops(self, sample_time):
sends = float(self.__rpc_data['rpcsends'])
@@ -384,14 +386,14 @@ class DeviceData:
else:
backlog = 0.0
- print
- print '%s mounted on %s:' % \
- (self.__nfs_data['export'], self.__nfs_data['mountpoint'])
- print
+ print()
+ print('%s mounted on %s:' % \
+ (self.__nfs_data['export'], self.__nfs_data['mountpoint']))
+ print()
- print ' op/s\t\trpc bklog'
- print '%7.2f' % (sends / sample_time),
- print '\t%7.2f' % backlog
+ print(' op/s\t\trpc bklog')
+ print('%7.2f' % (sends / sample_time))
+ print('\t%7.2f' % backlog)
if which == 0:
self.__print_rpc_op_stats('READ', sample_time)
@@ -424,7 +426,7 @@ def parse_stats_file(filename):
ms_dict = dict()
key = ''
- f = file(filename)
+ f = open(filename)
for line in f.readlines():
words = line.split()
if len(words) == 0:
@@ -494,7 +496,7 @@ def list_nfs_mounts(givenlist, mountstats):
if stats.is_nfs_mountpoint():
list += [device]
else:
- for device, descr in mountstats.iteritems():
+ for device, descr in mountstats.items():
stats = DeviceData()
stats.parse_stats(descr)
if stats.is_nfs_mountpoint():
@@ -527,7 +529,7 @@ client are listed.
usage="usage: %prog [ <interval> [ <count> ] ] [ <options> ] [ <mount point> ]",
description=mydescription,
version='version %s' % Iostats_version)
- parser.set_defaults(which=0, sort=False, list=sys.maxint)
+ parser.set_defaults(which=0, sort=False, list=sys.maxsize)
statgroup = OptionGroup(parser, "Statistics Options",
'File I/O is displayed unless one of the following is specified:')
@@ -572,29 +574,29 @@ client are listed.
try:
interval = int(arg)
except:
- print 'Illegal <interval> value %s' % arg
+ print('Illegal <interval> value %s' % arg)
return
if interval > 0:
interval_seen = True
else:
- print 'Illegal <interval> value %s' % arg
+ print('Illegal <interval> value %s' % arg)
return
elif not count_seen:
try:
count = int(arg)
except:
- print 'Ilegal <count> value %s' % arg
+ print('Ilegal <count> value %s' % arg)
return
if count > 0:
count_seen = True
else:
- print 'Illegal <count> value %s' % arg
+ print('Illegal <count> value %s' % arg)
return
# make certain devices contains only NFS mount points
devices = list_nfs_mounts(origdevices, mountstats)
if len(devices) == 0:
- print 'No NFS mount points were found'
+ print('No NFS mount points were found')
return
@@ -616,7 +618,7 @@ client are listed.
# we need to recheck the devices list when reparsing
devices = list_nfs_mounts(origdevices,mountstats)
if len(devices) == 0:
- print 'No NFS mount points were found'
+ print('No NFS mount points were found')
return
count -= 1
else:
@@ -630,7 +632,7 @@ client are listed.
# we need to recheck the devices list when reparsing
devices = list_nfs_mounts(origdevices,mountstats)
if len(devices) == 0:
- print 'No NFS mount points were found'
+ print('No NFS mount points were found')
return
#
@@ -641,7 +643,7 @@ prog = os.path.basename(sys.argv[0])
try:
iostat_command(prog)
except KeyboardInterrupt:
- print 'Caught ^C... exiting'
+ print('Caught ^C... exiting')
sys.exit(1)
sys.exit(0)
diff --git a/tools/rpcdebug/Makefile.am b/tools/rpcdebug/Makefile.am
index 39b70c9..b0a3e1f 100644
--- a/tools/rpcdebug/Makefile.am
+++ b/tools/rpcdebug/Makefile.am
@@ -1,15 +1,9 @@
## Process this file with automake to produce Makefile.in
-CC=$(CC_FOR_BUILD)
-LIBTOOL = @LIBTOOL@ --tag=CC
-
man8_MANS = rpcdebug.man
EXTRA_DIST = $(man8_MANS)
sbin_PROGRAMS = rpcdebug
rpcdebug_SOURCES = rpcdebug.c
-rpcdebug_CFLAGS=$(CFLAGS_FOR_BUILD)
-rpcdebug_CPPFLAGS=$(CPPFLAGS_FOR_BUILD) -I$(top_srcdir)/support/include
-rpcdebug_LDFLAGS=$(LDFLAGS_FOR_BUILD)
MAINTAINERCLEANFILES = Makefile.in
diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c
index a3292c9..0be2517 100644
--- a/utils/gssd/gssd.c
+++ b/utils/gssd/gssd.c
@@ -147,7 +147,7 @@ main(int argc, char *argv[])
#ifdef HAVE_SET_ALLOWABLE_ENCTYPES
limit_to_legacy_enctypes = 1;
#else
- errx(1, "Setting encryption type not support by Kerberos libraries.");
+ errx(1, "Encryption type limits not supported by Kerberos libraries.");
#endif
break;
default:
diff --git a/utils/gssd/gssd.man b/utils/gssd/gssd.man
index c74b7e8..79d9bf9 100644
--- a/utils/gssd/gssd.man
+++ b/utils/gssd/gssd.man
@@ -2,22 +2,197 @@
.\" rpc.gssd(8)
.\"
.\" Copyright (C) 2003 J. Bruce Fields <bfields@umich.edu>
-.TH rpc.gssd 8 "14 Mar 2007"
+.\"
+.TH rpc.gssd 8 "20 Feb 2013"
.SH NAME
-rpc.gssd \- rpcsec_gss daemon
+rpc.gssd \- RPCSEC_GSS daemon
.SH SYNOPSIS
-.B "rpc.gssd [-f] [-n] [-k keytab] [-l] [-p pipefsdir] [-v] [-r] [-d ccachedir]"
+.B rpc.gssd
+.RB [ \-fMnlvr ]
+.RB [ \-k
+.IR keytab ]
+.RB [ \-p
+.IR pipefsdir ]
+.RB [ \-d
+.IR ccachedir ]
+.RB [ \-t
+.IR timeout ]
+.RB [ \-R
+.IR realm ]
+.SH INTRODUCTION
+The RPCSEC_GSS protocol, defined in RFC 5403, is used to provide
+strong security for RPC-based protocols such as NFS.
+.P
+Before exchanging RPC requests using RPCSEC_GSS, an RPC client must
+establish a GSS
+.IR "security context" .
+A security context is shared state on each
+end of a network transport that enables GSS-API security services.
+.P
+Security contexts are established using
+.IR "security credentials" .
+A credential grants temporary access to a secure network service,
+much as a railway ticket grants temporary access to use a rail service.
+.P
+A user typically obtains a credential by providing a password to the
+.BR kinit (1)
+command, or via a PAM library at login time.
+A credential acquired with a
+.I user principal
+is known as a
+.I user credential
+(see
+.BR kerberos (1)
+for more on principals).
+.P
+For certain operations, a credential is required
+which represents no user,
+is otherwise unprivileged,
+and is always available.
+This is referred to as a
+.IR "machine credential" .
+.P
+Machine credentials are typically established using a
+.IR "service principal" ,
+whose encrypted password, called its
+.IR key ,
+is stored in a file, called a
+.IR keytab ,
+to avoid requiring a user prompt.
+A machine credential effectively does not expire because the system
+can renew it as needed without user intervention.
+.P
+Once obtained, credentials are typically stored in local temporary files
+with well-known pathnames.
.SH DESCRIPTION
-The rpcsec_gss protocol gives a means of using the gss-api generic security
-api to provide security for protocols using rpc (in particular, nfs). Before
-exchanging any rpc requests using rpcsec_gss, the rpc client must first
-establish a security context. The linux kernel's implementation of rpcsec_gss
-depends on the userspace daemon
+To establish GSS security contexts using these credential files,
+the Linux kernel RPC client depends on a userspace daemon called
+.BR rpc.gssd .
+The
+.B rpc.gssd
+daemon uses the rpc_pipefs filesystem to communicate with the kernel.
+.SS User Credentials
+When a user authenticates using a command such as
+.BR kinit (1),
+the resulting credential is stored in a file with a well-known name
+constructed using the user's UID.
+.P
+To interact with an NFS server
+on behalf of a particular Kerberos-authenticated user,
+the Linux kernel RPC client requests that
+.B rpc.gssd
+initialize a security context with the credential
+in that user's credential file.
+.P
+Typically, credential files are placed in
+.IR /tmp .
+However,
+.B rpc.gssd
+can search for credential files in more than one directory.
+See the description of the
+.B -d
+option for details.
+.SS Machine Credentials
+A user credential is established by a user and
+is then shared with the kernel and
+.BR rpc.gssd .
+A machine credential is established by
+.B rpc.gssd
+for the kernel when there is no user.
+Therefore
+.B rpc.gssd
+must already have the materials on hand to establish this credential
+without requiring user intervention.
+.P
+.B rpc.gssd
+searches the local system's keytab for a principal and key to use
+to establish the machine credential.
+By default,
.B rpc.gssd
-to establish security contexts. The
+assumes the file
+.I /etc/krb5.keytab
+contains principals and keys that can be used to obtain machine credentials.
+.P
+.B rpc.gssd
+searches in the following order for a principal to use.
+The first matching credential is used.
+For the search, <hostname> and <REALM> are replaced with the local
+system's hostname and Kerberos realm.
+.sp
+ <HOSTNAME>$@<REALM>
+.br
+ root/<hostname>@<REALM>
+.br
+ nfs/<hostname>@<REALM>
+.br
+ host/<hostname>@<REALM>
+.br
+ root/<anyname>@<REALM>
+.br
+ nfs/<anyname>@<REALM>
+.br
+ host/<anyname>@<REALM>
+.sp
+The <anyname> entries match on the service name and realm, but ignore the hostname.
+These can be used if a principal matching the local host's name is not found.
+.P
+Note that the first principal in the search order is a user principal
+that enables Kerberized NFS when the local system is joined
+to an Active Directory domain using Samba.
+A password for this principal must be provided in the local system's keytab.
+.P
+You can specify another keytab by using the
+.B -k
+option if
+.I /etc/krb5.keytab
+does not exist or does not provide one of these principals.
+.SS Credentials for UID 0
+UID 0 is a special case.
+By default
+.B rpc.gssd
+uses the system's machine credentials for UID 0 accesses
+that require GSS authentication.
+This limits the privileges of the root user
+when accessing network resources that require authentication.
+.P
+Specify the
+.B -n
+option when starting
.B rpc.gssd
-daemon uses files in the rpc_pipefs filesystem to communicate with the kernel.
-
+if you'd like to force the root user to obtain a user credential
+rather than use the local system's machine credential.
+.P
+When
+.B -n
+is specified,
+the kernel continues to request a GSS context established
+with a machine credential for NFSv4 operations,
+such as SETCLIENTID or RENEW, that manage state.
+If
+.B rpc.gssd
+cannot obtain a machine credential (say, the local system has
+no keytab), NFSv4 operations that require machine credentials will fail.
+.SS Encryption types
+A realm administrator can choose to add keys encoded in a number of different
+encryption types to the local system's keytab.
+For instance, a host/ principal might have keys for the
+.BR aes256-cts-hmac-sha1-96 ,
+.BR aes128-cts-hmac-sha1-96 ,
+.BR des3-cbc-sha1 ", and"
+.BR arcfour-hmac " encryption types."
+This permits
+.B rpc.gssd
+to choose an appropriate encryption type that the target NFS server
+supports.
+.P
+These encryption types are stronger than legacy single-DES encryption types.
+To interoperate in environments where servers support
+only weak encryption types,
+you can restrict your client to use only single-DES encryption types
+by specifying the
+.B -l
+option when starting
+.BR rpc.gssd .
.SH OPTIONS
.TP
.B -f
@@ -26,115 +201,76 @@ Runs
in the foreground and sends output to stderr (as opposed to syslogd)
.TP
.B -n
-By default,
-.B rpc.gssd
-treats accesses by the user with UID 0 specially, and uses
-"machine credentials" for all accesses by that user which
-require Kerberos authentication.
-With the \-n option, "machine credentials" will not be used
-for accesses by UID 0. Instead, credentials must be obtained
-manually like all other users. Use of this option means that
-"root" must manually obtain Kerberos credentials before
-attempting to mount an nfs filesystem requiring Kerberos
-authentication.
+When specified, UID 0 is forced to obtain user credentials
+which are used instead of the local system's machine credentials.
.TP
-.B -k keytab
+.BI "-k " keytab
Tells
.B rpc.gssd
to use the keys found in
.I keytab
-to obtain "machine credentials".
-The default value is "/etc/krb5.keytab".
-.IP
-Previous versions of
-.B rpc.gssd
-used only "nfs/*" keys found within the keytab.
-To be more consistent with other implementations, we now look for
-specific keytab entries. The search order for keytabs to be used
-for "machine credentials" is now:
-.br
- <HOSTNAME>$@<REALM>
-.br
- root/<hostname>@<REALM>
-.br
- nfs/<hostname>@<REALM>
-.br
- host/<hostname>@<REALM>
-.br
- root/<anyname>@<REALM>
-.br
- nfs/<anyname>@<REALM>
-.br
- host/<anyname>@<REALM>
-.IP
-If this search order does not use the correct key then provide a
-keytab file that contains only correct keys.
+to obtain machine credentials.
+The default value is
+.IR /etc/krb5.keytab .
.TP
.B -l
-Tells
+When specified, restricts
.B rpc.gssd
-to limit session keys to Single DES even if the kernel supports stronger
-encryption types. Service ticket encryption is still governed by what
-the KDC believes the target server supports. This way the client can
-access a server that has strong keys in its keytab for ticket decryption
-but whose kernel only supports Single DES.
-.IP
-The alternative is to put only Single DES keys in the server's keytab
-and limit encryption types for its principal to Single DES on the KDC
-which will cause service tickets for this server to be encrypted using
-only Single DES and (as a side-effect) contain only Single DES session
-keys.
-.IP
-This legacy behaviour is only required for older servers
-(pre nfs-utils-1.2.4). If the server has a recent kernel, Kerberos
-implementation and nfs-utils it will work just fine with stronger
-encryption.
-.IP
-.B Note:
-This option is only available with Kerberos libraries that
-support setable encryption types.
+to sessions to weak encryption types such as
+.BR des-cbc-crc .
+This option is available only when the local system's Kerberos library
+supports settable encryption types.
.TP
-.B -p path
+.BI "-p " path
Tells
.B rpc.gssd
where to look for the rpc_pipefs filesystem. The default value is
-"/var/lib/nfs/rpc_pipefs".
+.IR /var/lib/nfs/rpc_pipefs .
.TP
-.B -d directory
-Tells
+.BI "-d " search-path
+This option specifies a colon separated list of directories that
+.B rpc.gssd
+searches for credential files. The default value is
+.IR /tmp:/run/user/%U .
+The literal sequence "%U" can be specified to substitue the UID
+of the user for whom credentials are being searched.
+.TP
+.B -M
+By default, machine credentials are stored in files in the first
+directory in the credential directory search path (see the
+.B -d
+option). When
+.B -M
+is set,
.B rpc.gssd
-where to look for Kerberos credential files. The default value is
-"/tmp:/run/user/%U".
-This can also be a colon separated list of directories to be searched for
-Kerberos credential files. The sequence "%U", if used, is replaced with
-the UID of the user for whom credentials are being searched.
-Note that if machine credentials are being
-stored in files, then the first directory on this list is where the
-machine credentials are stored.
+stores machine credentials in memory instead.
.TP
.B -v
Increases the verbosity of the output (can be specified multiple times).
.TP
.B -r
-If the rpcsec_gss library supports setting debug level,
+If the RPCSEC_GSS library supports setting debug level,
increases the verbosity of the output (can be specified multiple times).
.TP
-.B -R realm
+.BI "-R " realm
Kerberos tickets from this
.I realm
will be preferred when scanning available credentials cache files to be
used to create a context. By default, the default realm, as configured
in the Kerberos configuration file, is preferred.
.TP
-.B -t timeout
-Timeout, in seconds, for kernel gss contexts. This option allows you to force
+.BI "-t " timeout
+Timeout, in seconds, for kernel GSS contexts. This option allows you to force
new kernel contexts to be negotiated after
.I timeout
seconds, which allows changing Kerberos tickets and identities frequently.
The default is no explicit timeout, which means the kernel context will live
the lifetime of the Kerberos service ticket used in its creation.
.SH SEE ALSO
-.BR rpc.svcgssd(8)
+.BR rpc.svcgssd (8),
+.BR kerberos (1),
+.BR kinit (1),
+.BR krb5.conf (5)
.SH AUTHORS
.br
Dug Song <dugsong@umich.edu>
diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
index ec251fa..698f86f 100644
--- a/utils/gssd/gssd_proc.c
+++ b/utils/gssd/gssd_proc.c
@@ -52,6 +52,7 @@
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/fsuid.h>
+#include <sys/resource.h>
#include <stdio.h>
#include <stdlib.h>
@@ -168,7 +169,7 @@ sockaddr_to_hostname(const struct sockaddr *sa, const char *addr)
{
socklen_t addrlen;
int err;
- char *hostname;
+ char *hostname;
char hbuf[NI_MAXHOST];
switch (sa->sa_family) {
@@ -250,21 +251,10 @@ read_service_info(char *info_file_name, char **servicename, char **servername,
if ((p = strstr(buf, "port")) != NULL)
sscanf(p, "port: %127s\n", port);
- /* check service, program, and version */
- if (memcmp(service, "nfs", 3) != 0)
- return -1;
+ /* get program, and version numbers */
*prog = atoi(program + 1); /* skip open paren */
*vers = atoi(version);
- if (strlen(service) == 3 ) {
- if ((*prog != 100003) || ((*vers != 2) && (*vers != 3) &&
- (*vers != 4)))
- goto fail;
- } else if (memcmp(service, "nfs4_cb", 7) == 0) {
- if (*vers != 1)
- goto fail;
- }
-
if (!addrstr_to_sockaddr(addr, address, port))
goto fail;
@@ -398,10 +388,10 @@ process_clnt_dir_files(struct clnt_info * clp)
static int
get_poll_index(int *ind)
{
- int i;
+ unsigned int i;
*ind = -1;
- for (i=0; i<FD_ALLOC_BLOCK; i++) {
+ for (i=0; i<pollsize; i++) {
if (pollarray[i].events == 0) {
*ind = i;
break;
@@ -483,9 +473,13 @@ fail_keep_client:
void
init_client_list(void)
{
+ struct rlimit rlim;
TAILQ_INIT(&clnt_list);
/* Eventually plan to grow/shrink poll array: */
pollsize = FD_ALLOC_BLOCK;
+ if (getrlimit(RLIMIT_NOFILE, &rlim) == 0 &&
+ rlim.rlim_cur != RLIM_INFINITY)
+ pollsize = rlim.rlim_cur;
pollarray = calloc(pollsize, sizeof(struct pollfd));
}
@@ -567,9 +561,8 @@ process_pipedir(char *pipe_name)
update_old_clients(namelist, j, pipe_name);
for (i=0; i < j; i++) {
- if (i < FD_ALLOC_BLOCK
- && !strncmp(namelist[i]->d_name, "clnt", 4)
- && !find_client(namelist[i]->d_name, pipe_name))
+ if (!strncmp(namelist[i]->d_name, "clnt", 4)
+ && !find_client(namelist[i]->d_name, pipe_name))
process_clnt_dir(namelist[i]->d_name, pipe_name);
free(namelist[i]);
}
@@ -715,7 +708,7 @@ out_err:
/*
* If the port isn't already set, do an rpcbind query to the remote server
- * using the program and version and get the port.
+ * using the program and version and get the port.
*
* Newer kernels send the value of the port= mount option in the "info"
* file for the upcall or '0' for NFSv2/3. For NFSv4 it sends the value
@@ -962,12 +955,6 @@ process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname,
printerr(1, "handling krb5 upcall (%s)\n", clp->dirname);
- if (tgtname) {
- if (clp->servicename) {
- free(clp->servicename);
- clp->servicename = strdup(tgtname);
- }
- }
token.length = 0;
token.value = NULL;
memset(&pd, 0, sizeof(struct authgss_private_data));
@@ -1016,7 +1003,8 @@ process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname,
int success = 0;
do {
gssd_refresh_krb5_machine_credential(clp->servername,
- NULL, service);
+ NULL, service,
+ tgtname);
/*
* Get a list of credential cache names and try each
* of them until one works or we've tried them all
@@ -1025,7 +1013,7 @@ process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname,
printerr(0, "ERROR: No credentials found "
"for connection to server %s\n",
clp->servername);
- goto out_return_error;
+ goto out_return_error;
}
for (ccname = credlist; ccname && *ccname; ccname++) {
gssd_setup_krb5_machine_gss_ccache(*ccname);
@@ -1035,12 +1023,12 @@ process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname,
/* Success! */
success++;
break;
- }
+ }
printerr(2, "WARNING: Failed to create machine krb5 context "
"with credentials cache %s for server %s\n",
*ccname, clp->servername);
}
- gssd_free_krb5_machine_cred_list(credlist);
+ gssd_free_krb5_machine_cred_list(credlist);
if (!success) {
if(nocache == 0) {
nocache++;
@@ -1090,7 +1078,7 @@ process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname,
out:
if (token.value)
free(token.value);
-#ifndef HAVE_LIBTIRPC
+#ifdef HAVE_AUTHGSS_FREE_PRIVATE_DATA
if (pd.pd_ctx_hndl.length != 0)
authgss_free_private_data(&pd);
#endif
@@ -1237,6 +1225,6 @@ out:
free(enctypes);
free(target);
free(service);
- return;
+ return;
}
diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
index 60ba594..20b55b3 100644
--- a/utils/gssd/krb5_util.c
+++ b/utils/gssd/krb5_util.c
@@ -169,13 +169,13 @@ select_krb5_ccache(const struct dirent *d)
/*
* Look in directory "dirname" for files that look like they
- * are Kerberos Credential Cache files for a given UID. Return
- * non-zero and the dirent pointer for the entry most likely to be
- * what we want. Otherwise, return zero and no dirent pointer.
- * The caller is responsible for freeing the dirent if one is returned.
+ * are Kerberos Credential Cache files for a given UID.
*
- * Returns 0 if a valid-looking entry was found and a non-zero error
- * code otherwise.
+ * Returns 0 if a valid-looking entry is found. "*cctype" is
+ * set to the name of the cache type. A pointer to the dirent
+ * is planted in "*d". Caller must free "*d" with free(3).
+ *
+ * Otherwise, a negative errno is returned.
*/
static int
gssd_find_existing_krb5_ccache(uid_t uid, char *dirname,
@@ -350,6 +350,11 @@ gssd_get_single_krb5_cred(krb5_context context,
memset(&my_creds, 0, sizeof(my_creds));
+ /*
+ * Workaround for clock skew among NFS server, NFS client and KDC
+ * 300 because clock skew must be within 300sec for kerberos
+ */
+ now += 300;
if (ple->ccname && ple->endtime > now && !nocache) {
printerr(2, "INFO: Credentials in CC '%s' are good until %d\n",
ple->ccname, ple->endtime);
@@ -774,12 +779,16 @@ gssd_search_krb5_keytab(krb5_context context, krb5_keytab kt,
}
/*
- * Find a keytab entry to use for a given target hostname.
+ * Find a keytab entry to use for a given target realm.
* Tries to find the most appropriate keytab to use given the
* name of the host we are trying to connect with.
+ *
+ * Note: the tgtname contains a hostname in the realm that we
+ * are authenticating to. It may, or may not be the same as
+ * the server hostname.
*/
static int
-find_keytab_entry(krb5_context context, krb5_keytab kt, const char *hostname,
+find_keytab_entry(krb5_context context, krb5_keytab kt, const char *tgtname,
krb5_keytab_entry *kte, const char **svcnames)
{
krb5_error_code code;
@@ -795,14 +804,14 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *hostname,
/* Get full target hostname */
- retval = get_full_hostname(hostname, targethostname,
+ retval = get_full_hostname(tgtname, targethostname,
sizeof(targethostname));
if (retval)
goto out;
/* Get full local hostname */
- retval = gethostname(myhostname, sizeof(myhostname));
- if (retval) {
+ if (gethostname(myhostname, sizeof(myhostname)) == -1) {
+ retval = errno;
k5err = gssd_k5_err_msg(context, retval);
printerr(1, "%s while getting local hostname\n", k5err);
goto out;
@@ -1033,7 +1042,7 @@ err_cache:
* given only a UID. We really need more information, but we
* do the best we can.
*
- * Returns 0 if a ccache was found, and a non-zero error code otherwise.
+ * Returns 0 if a ccache was found, or a negative errno otherwise.
*/
int
gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername, char *dirpattern)
@@ -1078,7 +1087,7 @@ gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername, char *dirpattern)
printerr(2, "using %s as credentials cache for client with "
"uid %u for server %s\n", buf, uid, servername);
gssd_set_krb5_ccache_name(buf);
- return err;
+ return 0;
}
/*
@@ -1128,7 +1137,7 @@ gssd_get_krb5_machine_cred_list(char ***list)
if (ple->ccname) {
/* Make sure cred is up-to-date before returning it */
retval = gssd_refresh_krb5_machine_credential(NULL, ple,
- NULL);
+ NULL, NULL);
if (retval)
continue;
if (i + 1 > listsize) {
@@ -1208,9 +1217,9 @@ gssd_destroy_krb5_machine_creds(void)
"cache '%s'\n", k5err, ple->ccname);
}
}
+ krb5_free_context(context);
out:
free(k5err);
- krb5_free_context(context);
}
/*
@@ -1219,7 +1228,8 @@ gssd_destroy_krb5_machine_creds(void)
int
gssd_refresh_krb5_machine_credential(char *hostname,
struct gssd_k5_kt_princ *ple,
- char *service)
+ char *service,
+ char *tgtname)
{
krb5_error_code code = 0;
krb5_context context;
@@ -1252,19 +1262,22 @@ gssd_refresh_krb5_machine_credential(char *hostname,
k5err = gssd_k5_err_msg(context, code);
printerr(0, "ERROR: %s: %s while resolving keytab '%s'\n",
__func__, k5err, keytabfile);
- goto out;
+ goto out_free_context;
}
if (ple == NULL) {
krb5_keytab_entry kte;
- code = find_keytab_entry(context, kt, hostname, &kte, svcnames);
+ if (tgtname == NULL)
+ tgtname = hostname;
+
+ code = find_keytab_entry(context, kt, tgtname, &kte, svcnames);
if (code) {
printerr(0, "ERROR: %s: no usable keytab entry found "
"in keytab %s for connection with host %s\n",
__FUNCTION__, keytabfile, hostname);
retval = code;
- goto out;
+ goto out_free_kt;
}
ple = get_ple_by_princ(context, kte.principal);
@@ -1280,14 +1293,15 @@ gssd_refresh_krb5_machine_credential(char *hostname,
__FUNCTION__, pname ? pname : "<unparsable>",
hostname);
if (pname) k5_free_unparsed_name(context, pname);
- goto out;
+ goto out_free_kt;
}
}
retval = gssd_get_single_krb5_cred(context, kt, ple, 0);
-out:
- if (kt)
- krb5_kt_close(context, kt);
+out_free_kt:
+ krb5_kt_close(context, kt);
+out_free_context:
krb5_free_context(context);
+out:
free(k5err);
return retval;
}
diff --git a/utils/gssd/krb5_util.h b/utils/gssd/krb5_util.h
index cd6e107..9f41625 100644
--- a/utils/gssd/krb5_util.h
+++ b/utils/gssd/krb5_util.h
@@ -31,7 +31,8 @@ void gssd_setup_krb5_machine_gss_ccache(char *servername);
void gssd_destroy_krb5_machine_creds(void);
int gssd_refresh_krb5_machine_credential(char *hostname,
struct gssd_k5_kt_princ *ple,
- char *service);
+ char *service,
+ char *tgtname);
char *gssd_k5_err_msg(krb5_context context, krb5_error_code code);
void gssd_k5_get_default_realm(char **def_realm);
diff --git a/utils/gssd/svcgssd_krb5.c b/utils/gssd/svcgssd_krb5.c
index 6c34faf..1d44d34 100644
--- a/utils/gssd/svcgssd_krb5.c
+++ b/utils/gssd/svcgssd_krb5.c
@@ -38,6 +38,7 @@
#include <stdio.h>
#include <errno.h>
+#include <ctype.h>
#include <gssapi/gssapi.h>
#include <krb5.h>
@@ -98,6 +99,12 @@ parse_enctypes(char *enctypes)
if (n == 0)
return ENOENT;
+ /* Skip pass any non digits */
+ while (*enctypes && isdigit(*enctypes) == 0)
+ enctypes++;
+ if (*enctypes == '\0')
+ return EINVAL;
+
/* Allocate space for enctypes array */
if ((parsed_enctypes = (int *) calloc(n, sizeof(int))) == NULL) {
return ENOMEM;
diff --git a/utils/idmapd/idmapd.c b/utils/idmapd/idmapd.c
index e80efb4..beba9c4 100644
--- a/utils/idmapd/idmapd.c
+++ b/utils/idmapd/idmapd.c
@@ -145,7 +145,6 @@ static void svrreopen(int, short, void *);
static int nfsopen(struct idmap_client *);
static void nfscb(int, short, void *);
static void nfsdcb(int, short, void *);
-static int validateascii(char *, u_int32_t);
static int addfield(char **, ssize_t *, char *);
static int getfield(char **, char *, size_t);
@@ -425,7 +424,8 @@ dirscancb(int UNUSED(fd), short UNUSED(which), void *data)
pipefsdir, ents[i]->d_name);
if ((ic->ic_dirfd = open(path, O_RDONLY, 0)) == -1) {
- xlog_warn("dirscancb: open(%s): %s", path, strerror(errno));
+ if (verbose > 0)
+ xlog_warn("dirscancb: open(%s): %s", path, strerror(errno));
free(ic);
goto out;
}
@@ -642,6 +642,8 @@ out:
static void
imconv(struct idmap_client *ic, struct idmap_msg *im)
{
+ u_int32_t len;
+
switch (im->im_conv) {
case IDMAP_CONV_IDTONAME:
idtonameres(im);
@@ -652,10 +654,10 @@ imconv(struct idmap_client *ic, struct idmap_msg *im)
im->im_id, im->im_name);
break;
case IDMAP_CONV_NAMETOID:
- if (validateascii(im->im_name, sizeof(im->im_name)) == -1) {
- im->im_status |= IDMAP_STATUS_INVALIDMSG;
+ len = strnlen(im->im_name, IDMAP_NAMESZ - 1);
+ /* Check for NULL termination just to be careful */
+ if (im->im_name[len+1] != '\0')
return;
- }
nametoidres(im);
if (verbose > 1)
xlog_warn("%s %s: (%s) name \"%s\" -> id \"%d\"",
@@ -855,25 +857,6 @@ nametoidres(struct idmap_msg *im)
}
static int
-validateascii(char *string, u_int32_t len)
-{
- u_int32_t i;
-
- for (i = 0; i < len; i++) {
- if (string[i] == '\0')
- break;
-
- if (string[i] & 0x80)
- return (-1);
- }
-
- if ((i >= len) || string[i] != '\0')
- return (-1);
-
- return (i + 1);
-}
-
-static int
addfield(char **bpp, ssize_t *bsizp, char *fld)
{
char ch, *bp = *bpp;
diff --git a/utils/mount/error.c b/utils/mount/error.c
index 83ad1d2..f8fc13f 100644
--- a/utils/mount/error.c
+++ b/utils/mount/error.c
@@ -225,7 +225,7 @@ void mount_error(const char *spec, const char *mount_point, int error)
case ENOENT:
if (spec)
nfs_error(_("%s: mounting %s failed, "
- "reason given by server:\n %s"),
+ "reason given by server: %s"),
progname, spec, strerror(error));
else
nfs_error(_("%s: mount point %s does not exist"),
diff --git a/utils/mount/nfs.man b/utils/mount/nfs.man
index c15de98..374ac06 100644
--- a/utils/mount/nfs.man
+++ b/utils/mount/nfs.man
@@ -347,6 +347,13 @@ using an automounter (refer to
.BR automount (8)
for details).
.TP 1.5i
+.BR rdirplus " / " nordirplus
+Selects whether to use NFS v3 or v4 READDIRPLUS requests.
+If this option is not specified, the NFS client uses READDIRPLUS requests
+on NFS v3 or v4 mounts to read small directories.
+Some applications perform better if the client uses only READDIR requests
+for all directories.
+.TP 1.5i
.BI retry= n
The number of minutes that the
.BR mount (8)
@@ -708,13 +715,6 @@ Disabling the NFSACL sideband protocol may be necessary
if the negotiation causes problems on the client or server.
Refer to the SECURITY CONSIDERATIONS section for more details.
.TP 1.5i
-.BR rdirplus " / " nordirplus
-Selects whether to use NFS version 3 READDIRPLUS requests.
-If this option is not specified, the NFS client uses READDIRPLUS requests
-on NFS version 3 mounts to read small directories.
-Some applications perform better if the client uses only READDIR requests
-for all directories.
-.TP 1.5i
.BR local_lock= mechanism
Specifies whether to use local locking for any or both of the flock and the
POSIX locking mechanisms.
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
index 9b4197b..8ee3024 100644
--- a/utils/mount/stropts.c
+++ b/utils/mount/stropts.c
@@ -666,6 +666,7 @@ static int nfs_try_mount_v3v2(struct nfsmount_info *mi)
case EOPNOTSUPP:
case EHOSTUNREACH:
case ETIMEDOUT:
+ case EACCES:
continue;
default:
goto out;
@@ -761,6 +762,7 @@ static int nfs_try_mount_v4(struct nfsmount_info *mi)
case ECONNREFUSED:
case EHOSTUNREACH:
case ETIMEDOUT:
+ case EACCES:
continue;
default:
goto out;
diff --git a/utils/mountd/auth.c b/utils/mountd/auth.c
index 508040a..330cab5 100644
--- a/utils/mountd/auth.c
+++ b/utils/mountd/auth.c
@@ -10,10 +10,12 @@
#include <config.h>
#endif
+#include <sys/types.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
+#include <fcntl.h>
#include <unistd.h>
#include "sockaddr.h"
@@ -21,7 +23,6 @@
#include "nfslib.h"
#include "exportfs.h"
#include "mountd.h"
-#include "xmalloc.h"
#include "v4root.h"
enum auth_error
diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c
index e950ec6..978698d 100644
--- a/utils/mountd/cache.c
+++ b/utils/mountd/cache.c
@@ -29,7 +29,6 @@
#include "nfslib.h"
#include "exportfs.h"
#include "mountd.h"
-#include "xmalloc.h"
#include "fsloc.h"
#include "pseudoflavors.h"
@@ -109,12 +108,10 @@ static void auth_unix_ip(FILE *f)
struct addrinfo *ai = NULL;
ai = client_resolve(tmp->ai_addr);
- if (ai == NULL)
- goto out;
- client = client_compose(ai);
- freeaddrinfo(ai);
- if (!client)
- goto out;
+ if (ai) {
+ client = client_compose(ai);
+ freeaddrinfo(ai);
+ }
}
qword_print(f, "nfsd");
qword_print(f, ipaddr);
@@ -127,7 +124,6 @@ static void auth_unix_ip(FILE *f)
xlog(D_CALL, "auth_unix_ip: client %p '%s'", client, client?client: "DEFAULT");
free(client);
-out:
freeaddrinfo(tmp);
}
@@ -347,6 +343,30 @@ static char *next_mnt(void **v, char *p)
return me->mnt_dir;
}
+static int is_subdirectory(char *child, char *parent)
+{
+ size_t l = strlen(parent);
+
+ if (strcmp(parent, "/") == 0)
+ return 1;
+
+ return strcmp(child, parent) == 0
+ || (strncmp(child, parent, l) == 0 && child[l] == '/');
+}
+
+static int path_matches(nfs_export *exp, char *path)
+{
+ if (exp->m_export.e_flags & NFSEXP_CROSSMOUNT)
+ return is_subdirectory(path, exp->m_export.e_path);
+ return strcmp(path, exp->m_export.e_path) == 0;
+}
+
+static int
+export_matches(nfs_export *exp, char *dom, char *path, struct addrinfo *ai)
+{
+ return path_matches(exp, path) && client_matches(exp, dom, ai);
+}
+
/* True iff e1 is a child of e2 and e2 has crossmnt set: */
static bool subexport(struct exportent *e1, struct exportent *e2)
{
@@ -354,8 +374,8 @@ static bool subexport(struct exportent *e1, struct exportent *e2)
size_t l2 = strlen(p2);
return e2->e_flags & NFSEXP_CROSSMOUNT
- && strncmp(p1, p2, l2) == 0
- && p1[l2] == '/';
+ && strncmp(p1, p2, l2) == 0
+ && p1[l2] == '/';
}
struct parsed_fsid {
@@ -756,27 +776,6 @@ static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *ex
return qword_eol(f);
}
-static int is_subdirectory(char *child, char *parent)
-{
- size_t l = strlen(parent);
-
- return strcmp(child, parent) == 0
- || (strncmp(child, parent, l) == 0 && child[l] == '/');
-}
-
-static int path_matches(nfs_export *exp, char *path)
-{
- if (exp->m_export.e_flags & NFSEXP_CROSSMOUNT)
- return is_subdirectory(path, exp->m_export.e_path);
- return strcmp(path, exp->m_export.e_path) == 0;
-}
-
-static int
-export_matches(nfs_export *exp, char *dom, char *path, struct addrinfo *ai)
-{
- return path_matches(exp, path) && client_matches(exp, dom, ai);
-}
-
static nfs_export *
lookup_export(char *dom, char *path, struct addrinfo *ai)
{
@@ -830,6 +829,7 @@ lookup_export(char *dom, char *path, struct addrinfo *ai)
#ifdef HAVE_NFS_PLUGIN_H
#include <dlfcn.h>
+#include <link.h>
#include <nfs-plugin.h>
/*
@@ -1094,6 +1094,7 @@ static struct exportent *lookup_junction(char *dom, const char *pathname,
struct addrinfo *ai)
{
struct exportent *exp;
+ struct link_map *map;
void *handle;
handle = dlopen("libnfsjunct.so", RTLD_NOW);
@@ -1101,6 +1102,11 @@ static struct exportent *lookup_junction(char *dom, const char *pathname,
xlog(D_GENERAL, "%s: dlopen: %s", __func__, dlerror());
return NULL;
}
+
+ if (dlinfo(handle, RTLD_DI_LINKMAP, &map) == 0)
+ xlog(D_GENERAL, "%s: loaded plug-in %s",
+ __func__, map->l_name);
+
(void)dlerror(); /* Clear any error */
exp = invoke_junction_ops(handle, dom, pathname, ai);
diff --git a/utils/mountd/v4root.c b/utils/mountd/v4root.c
index 726b50d..34d098a 100644
--- a/utils/mountd/v4root.c
+++ b/utils/mountd/v4root.c
@@ -55,7 +55,8 @@ static nfs_export pseudo_root = {
.m_warned = 0,
};
-void set_pseudofs_security(struct exportent *pseudo, struct exportent *source)
+static void
+set_pseudofs_security(struct exportent *pseudo, struct exportent *source)
{
struct sec_entry *se;
int i;
@@ -121,7 +122,8 @@ v4root_support(void)
return 0;
}
-int pseudofs_update(char *hostname, char *path, nfs_export *source)
+static int
+pseudofs_update(char *hostname, char *path, nfs_export *source)
{
nfs_export *exp;
diff --git a/utils/nfsdcltrack/nfsdcltrack.c b/utils/nfsdcltrack/nfsdcltrack.c
index 9801b9c..4334340 100644
--- a/utils/nfsdcltrack/nfsdcltrack.c
+++ b/utils/nfsdcltrack/nfsdcltrack.c
@@ -379,6 +379,17 @@ cltrack_legacy_gracedone(void)
while ((entry = readdir(v4recovery))) {
int len;
+ /* skip "." and ".." */
+ if (entry->d_name[0] == '.') {
+ switch (entry->d_name[1]) {
+ case '\0':
+ continue;
+ case '.':
+ if (entry->d_name[2] == '\0')
+ continue;
+ }
+ }
+
/* borrow the clientid blob for this */
len = snprintf((char *)blob, sizeof(blob), "%s/%s", dirname,
entry->d_name);
diff --git a/utils/statd/rmtcall.c b/utils/statd/rmtcall.c
index 4ecb03c..fd576d9 100644
--- a/utils/statd/rmtcall.c
+++ b/utils/statd/rmtcall.c
@@ -68,21 +68,19 @@ statd_get_socket(void)
{
struct sockaddr_in sin;
struct servent *se;
- int loopcnt = 100;
+ const int loopcnt = 100;
+ int i, tmp_sockets[loopcnt];
if (sockfd >= 0)
return sockfd;
- while (loopcnt-- > 0) {
-
- if (sockfd >= 0) close(sockfd);
+ for (i = 0; i < loopcnt; ++i) {
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
xlog(L_ERROR, "%s: Can't create socket: %m", __func__);
- return -1;
+ break;
}
-
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
@@ -96,7 +94,16 @@ statd_get_socket(void)
if (se == NULL)
break;
/* rather not use that port, try again */
+
+ tmp_sockets[i] = sockfd;
}
+
+ while (--i >= 0)
+ close(tmp_sockets[i]);
+
+ if (sockfd < 0)
+ return -1;
+
FD_SET(sockfd, &SVC_FDSET);
return sockfd;
}