diff --git a/nfs-utils.1.2.8.rc2.patch b/nfs-utils.1.2.8.rc2.patch deleted file mode 100644 index 2cda8c6..0000000 --- a/nfs-utils.1.2.8.rc2.patch +++ /dev/null @@ -1,535 +0,0 @@ -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 - #include - #include --#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 - #include - #include --#include "xmalloc.h" -+ - #include "nfslib.h" - #include "exportfs.h" - #include "xio.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/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c -index ec251fa..d01ba2f 100644 ---- a/utils/gssd/gssd_proc.c -+++ b/utils/gssd/gssd_proc.c -@@ -52,6 +52,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -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; id_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]); - } -@@ -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 -diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c -index 60ba594..aeb8f70 100644 ---- a/utils/gssd/krb5_util.c -+++ b/utils/gssd/krb5_util.c -@@ -774,12 +774,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,7 +799,7 @@ 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; -@@ -1128,7 +1132,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) { -@@ -1219,7 +1223,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; -@@ -1258,7 +1263,10 @@ gssd_refresh_krb5_machine_credential(char *hostname, - 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", -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 - #include -+#include - #include - #include - -@@ -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..9d66225 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); - -@@ -642,6 +641,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 +653,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 +856,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/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 - #endif - -+#include - #include - #include - #include - #include -+#include - #include - - #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..45012be 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,7 @@ 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] == '/'; -+ && is_subdirectory(p1, p2); - } - - struct parsed_fsid { -@@ -756,27 +775,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 +828,7 @@ lookup_export(char *dom, char *path, struct addrinfo *ai) - - #ifdef HAVE_NFS_PLUGIN_H - #include -+#include - #include - - /* -@@ -1094,6 +1093,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 +1101,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/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/nfs-utils.1.2.8.rc4.patch b/nfs-utils.1.2.8.rc4.patch new file mode 100644 index 0000000..69f47a2 --- /dev/null +++ b/nfs-utils.1.2.8.rc4.patch @@ -0,0 +1,1575 @@ +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 + #include + #include +-#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 + #include + #include +-#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 ++#endif ++ ++#ifdef HAVE_LIBIO_H + #include ++#endif + #include + #include + #include +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 + +@@ -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 [ [ ] ] [ ] [ ]", + 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 value %s' % arg ++ print('Illegal value %s' % arg) + return + if interval > 0: + interval_seen = True + else: +- print 'Illegal value %s' % arg ++ print('Illegal value %s' % arg) + return + elif not count_seen: + try: + count = int(arg) + except: +- print 'Ilegal value %s' % arg ++ print('Ilegal value %s' % arg) + return + if count > 0: + count_seen = True + else: +- print 'Illegal value %s' % arg ++ print('Illegal 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 +-.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, and are replaced with the local ++system's hostname and Kerberos realm. ++.sp ++ $@ ++.br ++ root/@ ++.br ++ nfs/@ ++.br ++ host/@ ++.br ++ root/@ ++.br ++ nfs/@ ++.br ++ host/@ ++.sp ++The 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 +- $@ +-.br +- root/@ +-.br +- nfs/@ +-.br +- host/@ +-.br +- root/@ +-.br +- nfs/@ +-.br +- host/@ +-.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 +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 + #include + #include ++#include + + #include + #include +@@ -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; id_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 : "", + 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 + #include ++#include + #include + #include + +@@ -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 + #endif + ++#include + #include + #include + #include + #include ++#include + #include + + #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 ++#include + #include + + /* +@@ -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; + } diff --git a/nfs-utils.spec b/nfs-utils.spec index dea3bbb..275639d 100644 --- a/nfs-utils.spec +++ b/nfs-utils.spec @@ -36,7 +36,7 @@ Source51: nfs-server.preconfig Source52: nfs-server.postconfig %define nfs_configs %{SOURCE50} %{SOURCE51} %{SOURCE52} -Patch001: nfs-utils.1.2.8.rc3.patch +Patch001: nfs-utils.1.2.8.rc4.patch Patch100: nfs-utils-1.2.1-statdpath-man.patch Patch101: nfs-utils-1.2.1-exp-subtree-warn-off.patch @@ -299,6 +299,7 @@ fi %changelog * Mon Mar 25 2013 Steve Dickson 1.2.7-5 +- Updated to latest upstream RC release: nfs-utils.1.2.8-rc4 - Added nfs-lock.service to After line in nfs-server.service (bz 914792) * Thu Feb 14 2013 Fedora Release Engineering - 1:1.2.7-4