diff --git a/configure.ac b/configure.ac index a594a7b..d3ad854 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. dnl -AC_INIT([linux nfs-utils],[1.2.7],[linux-nfs@vger.kernel.org],[nfs-utils]) +AC_INIT([linux nfs-utils],[1.2.8],[linux-nfs@vger.kernel.org],[nfs-utils]) AC_CANONICAL_BUILD([]) AC_CANONICAL_HOST([]) AC_CONFIG_MACRO_DIR(aclocal) diff --git a/support/include/nfsrpc.h b/support/include/nfsrpc.h index a0b80e1..1bfae7a 100644 --- a/support/include/nfsrpc.h +++ b/support/include/nfsrpc.h @@ -156,6 +156,11 @@ extern unsigned long nfs_pmap_getport(const struct sockaddr_in *, const struct timeval *); /* + * Use nfs_pmap_getport to see if statd is running locally + */ +extern int nfs_probe_statd(void); + +/* * Contact a remote RPC service to discover whether it is responding * to requests. */ diff --git a/support/nfs/getport.c b/support/nfs/getport.c index 3331ad4..081594c 100644 --- a/support/nfs/getport.c +++ b/support/nfs/getport.c @@ -1102,3 +1102,25 @@ unsigned long nfs_pmap_getport(const struct sockaddr_in *sin, return port; } + +static const char *nfs_ns_pgmtbl[] = { + "status", + NULL, +}; + +/* + * nfs_probe_statd - use nfs_pmap_getport to see if statd is running locally + * + * Returns non-zero if statd is running locally. + */ +int nfs_probe_statd(void) +{ + struct sockaddr_in addr = { + .sin_family = AF_INET, + .sin_addr.s_addr = htonl(INADDR_LOOPBACK), + }; + rpcprog_t program = nfs_getrpcbyname(NSMPROG, nfs_ns_pgmtbl); + + return nfs_getport_ping((struct sockaddr *)(char *)&addr, sizeof(addr), + program, (rpcvers_t)1, IPPROTO_UDP); +} diff --git a/tools/nfs-iostat/nfs-iostat.py b/tools/nfs-iostat/nfs-iostat.py index dfbef87..c035537 100644 --- a/tools/nfs-iostat/nfs-iostat.py +++ b/tools/nfs-iostat/nfs-iostat.py @@ -353,14 +353,14 @@ class DeviceData: exe_per_op = 0.0 op += ':' - print('%s' % op.lower().ljust(15)) + print('%s' % op.lower().ljust(15), end='') 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\t%7.3f' % (ops / sample_time), end='') + print('\t%7.3f' % (kilobytes / sample_time), end='') + print('\t%7.3f' % kb_per_op, end='') + print(' %7d (%3.1f%%)' % (retrans, retrans_percent), end='') + print('\t%7.3f' % rtt_per_op, end='') print('\t%7.3f' % exe_per_op) def ops(self, sample_time): @@ -392,7 +392,7 @@ class DeviceData: print() print(' op/s\t\trpc bklog') - print('%7.2f' % (sends / sample_time)) + print('%7.2f' % (sends / sample_time), end='') print('\t%7.2f' % backlog) if which == 0: diff --git a/utils/gssd/gssd.man b/utils/gssd/gssd.man index 1df75c5..ac13fd4 100644 --- a/utils/gssd/gssd.man +++ b/utils/gssd/gssd.man @@ -195,11 +195,28 @@ option when starting .BR rpc.gssd . .SH OPTIONS .TP -.B -D -DNS Reverse lookups are not used for determining the -server names pass to GSSAPI. This option will reverses that and forces -the use of DNS Reverse resolution of the server's IP address to -retrieve the server name to use in GSAPI authentication. +.B \-D +The server name passed to GSSAPI for authentication is normally the +name exactly as requested. e.g. for NFS +it is the server name in the "servername:/path" mount request. Only if this +servername appears to be an IP address (IPv4 or IPv6) or an +unqualified name (no dots) will a reverse DNS lookup +will be performed to get the canoncial server name. + +If +.B \-D +is present, a reverse DNS lookup will +.I always +be used, even if the server name looks like a canonical name. So it +is needed if partially qualified, or non canonical names are regularly +used. + +Using +.B \-D +can introduce a security vulnerability, so it is recommended that +.B \-D +not be used, and that canonical names always be used when requesting +services. .TP .B -f Runs diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c index af1844c..b7e2bbb 100644 --- a/utils/gssd/gssd_proc.c +++ b/utils/gssd/gssd_proc.c @@ -67,7 +67,6 @@ #include #include #include -#include #include "gssd.h" #include "err_util.h" @@ -176,7 +175,6 @@ get_servername(const char *name, const struct sockaddr *sa, const char *addr) char *hostname; char hbuf[NI_MAXHOST]; unsigned char buf[sizeof(struct in6_addr)]; - int servername = 0; if (avoid_dns) { /* @@ -184,15 +182,18 @@ get_servername(const char *name, const struct sockaddr *sa, const char *addr) * If it is an IP address, do the DNS lookup otherwise * skip the DNS lookup. */ - servername = 0; - if (strchr(name, '.') && inet_pton(AF_INET, name, buf) == 1) - servername = 1; /* IPv4 */ - else if (strchr(name, ':') && inet_pton(AF_INET6, name, buf) == 1) - servername = 1; /* or IPv6 */ - - if (servername) { + int is_fqdn = 1; + if (strchr(name, '.') == NULL) + is_fqdn = 0; /* local name */ + else if (inet_pton(AF_INET, name, buf) == 1) + is_fqdn = 0; /* IPv4 address */ + else if (inet_pton(AF_INET6, name, buf) == 1) + is_fqdn = 0; /* IPv6 addrss */ + + if (is_fqdn) { return strdup(name); } + /* Sorry, cannot avoid dns after all */ } switch (sa->sa_family) { diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c index 6275dd8..83b9651 100644 --- a/utils/gssd/krb5_util.c +++ b/utils/gssd/krb5_util.c @@ -231,7 +231,7 @@ gssd_find_existing_krb5_ccache(uid_t uid, char *dirname, continue; } if (uid == 0 && !root_uses_machine_creds && - strstr(namelist[i]->d_name, "_machine_")) { + strstr(namelist[i]->d_name, "machine_")) { printerr(3, "CC '%s' not available to root\n", statname); free(namelist[i]); @@ -825,8 +825,10 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *tgtname, myhostad[i+1] = 0; retval = get_full_hostname(myhostname, myhostname, sizeof(myhostname)); - if (retval) - goto out; + if (retval) { + /* Don't use myhostname */ + myhostname[0] = 0; + } code = krb5_get_default_realm(context, &default_realm); if (code) { @@ -852,11 +854,19 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *tgtname, } /* - * Try the "appropriate" realm first, and if nothing found for that - * realm, try the default realm (if it hasn't already been tried). + * Make sure the preferred_realm, which may have been explicitly set + * on the command line, is tried first. If nothing is found go on with + * the host and local default realm (if that hasn't already been tried). */ i = 0; realm = realmnames[i]; + + if (strcmp (realm, preferred_realm) != 0) { + realm = preferred_realm; + /* resetting the realmnames index */ + i = -1; + } + while (1) { if (realm == NULL) { tried_all = 1; @@ -883,6 +893,8 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *tgtname, myhostad, NULL); } else { + if (!myhostname[0]) + continue; snprintf(spn, sizeof(spn), "%s/%s@%s", svcnames[j], myhostname, realm); code = krb5_build_principal_ext(context, &princ, @@ -1236,7 +1248,7 @@ gssd_refresh_krb5_machine_credential(char *hostname, krb5_keytab kt = NULL;; int retval = 0; char *k5err = NULL; - const char *svcnames[5] = { "$", "root", "nfs", "host", NULL }; + const char *svcnames[] = { "$", "root", "nfs", "host", NULL }; /* * If a specific service name was specified, use it. diff --git a/utils/mount/network.c b/utils/mount/network.c index 4be48cd..e2cdcaf 100644 --- a/utils/mount/network.c +++ b/utils/mount/network.c @@ -65,11 +65,6 @@ extern int nfs_mount_data_version; extern char *progname; extern int verbose; -static const char *nfs_ns_pgmtbl[] = { - "status", - NULL, -}; - static const char *nfs_mnt_pgmtbl[] = { "mount", "mountd", @@ -761,18 +756,6 @@ int probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server) &nfs_server->pmap); } -static int nfs_probe_statd(void) -{ - struct sockaddr_in addr = { - .sin_family = AF_INET, - .sin_addr.s_addr = htonl(INADDR_LOOPBACK), - }; - rpcprog_t program = nfs_getrpcbyname(NSMPROG, nfs_ns_pgmtbl); - - return nfs_getport_ping(SAFE_SOCKADDR(&addr), sizeof(addr), - program, (rpcvers_t)1, IPPROTO_UDP); -} - /** * start_statd - attempt to start rpc.statd * diff --git a/utils/mount/nfs.man b/utils/mount/nfs.man index a8ec46c..2a42b93 100644 --- a/utils/mount/nfs.man +++ b/utils/mount/nfs.man @@ -84,6 +84,20 @@ in .SS "Options supported by all versions" These options are valid to use with any NFS version. .TP 1.5i +.BI nfsvers= n +The NFS protocol version number used to contact the server's NFS service. +If the server does not support the requested version, the mount request +fails. +If this option is not specified, the client negotiates a suitable version +with +the server, trying version 4 first, version 3 second, and version 2 last. +.TP 1.5i +.BI vers= n +This option is an alternative to the +.B nfsvers +option. +It is included for compatibility with other operating systems +.TP 1.5i .BR soft " / " hard Determines the recovery behavior of the NFS client after an NFS request times out. @@ -621,18 +635,6 @@ Using this option ensures that reports the proper maximum component length to applications in such cases. .TP 1.5i -.BI nfsvers= n -The NFS protocol version number used to contact the server's NFS service. -If the server does not support the requested version, the mount request fails. -If this option is not specified, the client negotiates a suitable version with -the server, trying version 4 first, version 3 second, and version 2 last. -.TP 1.5i -.BI vers= n -This option is an alternative to the -.B nfsvers -option. -It is included for compatibility with other operating systems. -.TP 1.5i .BR lock " / " nolock Selects whether to use the NLM sideband protocol to lock files on the server. If neither option is specified (or if diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c index 737927c..517aa62 100644 --- a/utils/mountd/cache.c +++ b/utils/mountd/cache.c @@ -347,20 +347,26 @@ static char *next_mnt(void **v, char *p) static int is_subdirectory(char *child, char *parent) { + /* Check is child is strictly a subdirectory of + * parent or a more distant descendant. + */ size_t l = strlen(parent); - if (strcmp(parent, "/") == 0) + if (strcmp(parent, "/") == 0 && child[1] != 0) return 1; - return strcmp(child, parent) == 0 - || (strncmp(child, parent, l) == 0 && child[l] == '/'); + return (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; + /* Does the path match the export? I.e. is it an + * exact match, or does the export have CROSSMOUNT, and path + * is a descendant? + */ + return strcmp(path, exp->m_export.e_path) == 0 + || ((exp->m_export.e_flags & NFSEXP_CROSSMOUNT) + && is_subdirectory(path, exp->m_export.e_path)); } static int @@ -369,15 +375,13 @@ 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: */ +/* True iff e1 is a child of e2 (or descendant) and e2 has crossmnt set: */ static bool subexport(struct exportent *e1, struct exportent *e2) { char *p1 = e1->e_path, *p2 = e2->e_path; - 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 { diff --git a/utils/nfsdcltrack/nfsdcltrack.man b/utils/nfsdcltrack/nfsdcltrack.man index 47007df..6940788 100644 --- a/utils/nfsdcltrack/nfsdcltrack.man +++ b/utils/nfsdcltrack/nfsdcltrack.man @@ -1,53 +1,3 @@ -.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. .ie \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" @@ -59,70 +9,6 @@ . de IX .. .\} -.\" -.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). -.\" Fear. Run. Save yourself. No user-serviceable parts. -. \" fudge factors for nroff and troff -.if n \{\ -. ds #H 0 -. ds #V .8m -. ds #F .3m -. ds #[ \f1 -. ds #] \fP -.\} -.if t \{\ -. ds #H ((1u-(\\\\n(.fu%2u))*.13m) -. ds #V .6m -. ds #F 0 -. ds #[ \& -. ds #] \& -.\} -. \" simple accents for nroff and troff -.if n \{\ -. ds ' \& -. ds ` \& -. ds ^ \& -. ds , \& -. ds ~ ~ -. ds / -.\} -.if t \{\ -. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" -. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' -. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' -. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' -. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' -. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' -.\} -. \" troff and (daisy-wheel) nroff accents -.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' -.ds 8 \h'\*(#H'\(*b\h'-\*(#H' -.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] -.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' -.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' -.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] -.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] -.ds ae a\h'-(\w'a'u*4/10)'e -.ds Ae A\h'-(\w'A'u*4/10)'E -. \" corrections for vroff -.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' -.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' -. \" for low resolution devices (crt and lpr) -.if \n(.H>23 .if \n(.V>19 \ -\{\ -. ds : e -. ds 8 ss -. ds o a -. ds d- d\h'-1'\(ga -. ds D- D\h'-1'\(hy -. ds th \o'bp' -. ds Th \o'LP' -. ds ae ae -. ds Ae AE -.\} -.rm #[ #] #H #V #F C -.\" ======================================================================== -.\" .IX Title "NFSDCLTRACK 8" .TH NFSDCLTRACK 8 "2012-10-24" "" "" .\" For nroff, turn off justification. Always turn off hyphenation; it makes diff --git a/utils/nfsidmap/Makefile.am b/utils/nfsidmap/Makefile.am index c0675c4..737a219 100644 --- a/utils/nfsidmap/Makefile.am +++ b/utils/nfsidmap/Makefile.am @@ -1,9 +1,10 @@ ## Process this file with automake to produce Makefile.in man8_MANS = nfsidmap.man - sbin_PROGRAMS = nfsidmap + nfsidmap_SOURCES = nfsidmap.c nfsidmap_LDADD = $(LIBNFSIDMAP) -lkeyutils ../../support/nfs/libnfs.a MAINTAINERCLEANFILES = Makefile.in +EXTRA_DIST = id_resolver.conf diff --git a/utils/nfsidmap/id_resolver.conf b/utils/nfsidmap/id_resolver.conf new file mode 100644 index 0000000..2c156c6 --- /dev/null +++ b/utils/nfsidmap/id_resolver.conf @@ -0,0 +1 @@ +create id_resolver * * /usr/sbin/nfsidmap -t 600 %k %d diff --git a/utils/statd/statd.c b/utils/statd/statd.c index 652546c..8c51bcc 100644 --- a/utils/statd/statd.c +++ b/utils/statd/statd.c @@ -28,6 +28,7 @@ #include "statd.h" #include "nfslib.h" +#include "nfsrpc.h" #include "nsm.h" /* Socket operations */ @@ -237,6 +238,12 @@ int main (int argc, char **argv) /* Set hostname */ MY_NAME = NULL; + /* Refuse to start if another statd is running */ + if (nfs_probe_statd()) { + fprintf(stderr, "Statd service already running!\n"); + exit(1); + } + /* Process command line switches */ while ((arg = getopt_long(argc, argv, "h?vVFNH:dn:p:o:P:L", longopts, NULL)) != EOF) { switch (arg) {