diff --git a/aclocal/libtirpc.m4 b/aclocal/libtirpc.m4 index b7de636..27368ff 100644 --- a/aclocal/libtirpc.m4 +++ b/aclocal/libtirpc.m4 @@ -20,6 +20,12 @@ AC_DEFUN([AC_LIBTIRPC], [ [Define to 1 if your rpcsec library provides authgss_free_private_data])],, [${LIBS}])]) + AS_IF([test -n "${LIBTIRPC}"], + [AC_CHECK_LIB([tirpc], [libtirpc_set_debug], + [AC_DEFINE([HAVE_LIBTIRPC_SET_DEBUG], [1], + [Define to 1 if your tirpc library provides libtirpc_set_debug])],, + [${LIBS}])]) + AC_SUBST([AM_CPPFLAGS]) AC_SUBST(LIBTIRPC) diff --git a/support/export/client.c b/support/export/client.c index 95156f0..af9e6bb 100644 --- a/support/export/client.c +++ b/support/export/client.c @@ -686,6 +686,21 @@ check_netgroup(const nfs_client *clp, const struct addrinfo *ai) } } + /* check whether the IP itself is in the netgroup */ + for (tmp = (struct addrinfo *)ai ; tmp != NULL ; tmp = tmp->ai_next) { + free(hname); + hname = calloc(INET6_ADDRSTRLEN, 1); + + if (inet_ntop(tmp->ai_family, &(((struct sockaddr_in *)tmp->ai_addr)->sin_addr), hname, INET6_ADDRSTRLEN) != hname) { + xlog(D_GENERAL, " %s: unable to inet_ntop addrinfo %p: %m", __func__, tmp, errno); + goto out; + } + if (innetgr(netgroup, hname, NULL, NULL)) { + match = 1; + goto out; + } + } + /* Okay, strip off the domain (if we have one) */ dot = strchr(hname, '.'); if (dot == NULL) diff --git a/support/export/hostname.c b/support/export/hostname.c index 169baa5..7a44d42 100644 --- a/support/export/hostname.c +++ b/support/export/hostname.c @@ -134,6 +134,8 @@ host_pton(const char *paddr) break; } return ai; + case EAI_NONAME: + break; case EAI_SYSTEM: xlog(D_GENERAL, "%s: failed to convert %s: (%d) %m", __func__, paddr, errno); diff --git a/support/include/nfslib.h b/support/include/nfslib.h index c9a13cb..ddd71ac 100644 --- a/support/include/nfslib.h +++ b/support/include/nfslib.h @@ -176,6 +176,9 @@ size_t strlcpy(char *, const char *, size_t); ssize_t atomicio(ssize_t (*f) (int, void*, size_t), int, void *, size_t); +#ifdef HAVE_LIBTIRPC_SET_DEBUG +void libtirpc_set_debug(char *name, int level, int use_stderr); +#endif #define UNUSED(x) UNUSED_ ## x __attribute__((unused)) diff --git a/support/nfs/mydaemon.c b/support/nfs/mydaemon.c index 3391eff..343e80b 100644 --- a/support/nfs/mydaemon.c +++ b/support/nfs/mydaemon.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include "nfslib.h" @@ -122,6 +123,7 @@ daemon_init(bool fg) dup2(tempfd, 0); dup2(tempfd, 1); dup2(tempfd, 2); + closelog(); dup2(pipefds[1], 3); pipefds[1] = 3; closeall(4); diff --git a/systemd/Makefile.am b/systemd/Makefile.am index 0331926..03f96e9 100644 --- a/systemd/Makefile.am +++ b/systemd/Makefile.am @@ -28,9 +28,13 @@ endif if CONFIG_GSS unit_files += \ auth-rpcgss-module.service \ - rpc-gssd.service \ + rpc-gssd.service + +if CONFIG_SVCGSS +unit_files += \ rpc-svcgssd.service endif +endif EXTRA_DIST = $(unit_files) diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c index 8758231..c7a79a6 100644 --- a/utils/exportfs/exportfs.c +++ b/utils/exportfs/exportfs.c @@ -499,9 +499,10 @@ unexportfs(char *arg, int verbose) static int can_test(void) { - char buf[1024]; + char buf[1024] = { 0 }; int fd; int n; + size_t bufsiz = sizeof(buf); fd = open("/proc/net/rpc/auth.unix.ip/channel", O_WRONLY); if (fd < 0) @@ -514,9 +515,9 @@ static int can_test(void) * commit 2f74f972 (sunrpc: prepare NFS for 2038). */ if (time(NULL) > INT_TO_LONG_THRESHOLD_SECS) - sprintf(buf, "nfsd 0.0.0.0 %ld -test-client-\n", LONG_MAX); + snprintf(buf, bufsiz-1, "nfsd 0.0.0.0 %ld -test-client-\n", LONG_MAX); else - sprintf(buf, "nfsd 0.0.0.0 %d -test-client-\n", INT_MAX); + snprintf(buf, bufsiz-1, "nfsd 0.0.0.0 %d -test-client-\n", INT_MAX); n = write(fd, buf, strlen(buf)); close(fd); @@ -532,7 +533,8 @@ static int can_test(void) static int test_export(char *path, int with_fsid) { - char buf[1024]; + /* beside max path, buf size should take protocol str into account */ + char buf[NFS_MAXPATHLEN+1+64] = { 0 }; char *bp = buf; int len = sizeof(buf); int fd, n; @@ -758,7 +760,8 @@ dumpopt(char c, char *fmt, ...) static void dump(int verbose, int export_format) { - char buf[1024]; + /* buf[] size should >= sizeof(struct exportent->e_path) */ + char buf[NFS_MAXPATHLEN+1] = { 0 }; char *bp; int len; nfs_export *exp; diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c index e480349..078e558 100644 --- a/utils/gssd/gssd.c +++ b/utils/gssd/gssd.c @@ -869,6 +869,13 @@ main(int argc, char *argv[]) if (verbosity && rpc_verbosity == 0) rpc_verbosity = verbosity; authgss_set_debug_level(rpc_verbosity); +#elif HAVE_LIBTIRPC_SET_DEBUG + /* + * Only set the libtirpc debug level if explicitly requested via -r... + * gssd is chatty enough as it is. + */ + if (rpc_verbosity > 0) + libtirpc_set_debug(progname, rpc_verbosity, fg); #else if (rpc_verbosity > 0) printerr(0, "Warning: rpcsec_gss library does not " diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c index 11168b2..cee8991 100644 --- a/utils/gssd/gssd_proc.c +++ b/utils/gssd/gssd_proc.c @@ -348,16 +348,9 @@ create_auth_rpc_client(struct clnt_info *clp, printerr(2, "creating %s client for server %s\n", clp->protocol, clp->servername); - if ((strcmp(clp->protocol, "tcp")) == 0) { - protocol = IPPROTO_TCP; - } else if ((strcmp(clp->protocol, "udp")) == 0) { + protocol = IPPROTO_TCP; + if ((strcmp(clp->protocol, "udp")) == 0) protocol = IPPROTO_UDP; - } else { - printerr(0, "WARNING: unrecognized protocol, '%s', requested " - "for connection to server %s for user with uid %d\n", - clp->protocol, clp->servername, uid); - goto out_fail; - } switch (addr->sa_family) { case AF_INET: diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c index ecf17a2..f48de2c 100644 --- a/utils/gssd/krb5_util.c +++ b/utils/gssd/krb5_util.c @@ -801,7 +801,7 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *tgtname, char *default_realm = NULL; char *realm; char *k5err = NULL; - int tried_all = 0, tried_default = 0; + int tried_all = 0, tried_default = 0, tried_upper = 0; krb5_principal princ; const char *notsetstr = "not set"; char *adhostoverride; @@ -835,7 +835,6 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *tgtname, strcpy(myhostad, myhostname); for (i = 0; myhostad[i] != 0; ++i) { if (myhostad[i] == '.') break; - myhostad[i] = toupper(myhostad[i]); } myhostad[i] = '$'; myhostad[i+1] = 0; @@ -936,6 +935,19 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *tgtname, k5err = gssd_k5_err_msg(context, code); printerr(3, "%s while getting keytab entry for '%s'\n", k5err, spn); + /* + * We tried the active directory machine account + * with the hostname part as-is and failed... + * convert it to uppercase and try again before + * moving on to the svcname + */ + if (strcmp(svcnames[j],"$") == 0 && !tried_upper) { + for (i = 0; myhostad[i] != '$'; ++i) { + myhostad[i] = toupper(myhostad[i]); + } + j--; + tried_upper = 1; + } } else { printerr(3, "Success getting keytab entry for '%s'\n",spn); retval = 0; diff --git a/utils/gssd/svcgssd.c b/utils/gssd/svcgssd.c index f1b4347..0fe7c6d 100644 --- a/utils/gssd/svcgssd.c +++ b/utils/gssd/svcgssd.c @@ -135,6 +135,13 @@ main(int argc, char *argv[]) if (verbosity && rpc_verbosity == 0) rpc_verbosity = verbosity; authgss_set_debug_level(rpc_verbosity); +#elif HAVE_LIBTIRPC_SET_DEBUG + /* + * Only set the libtirpc debug level if explicitly requested via -r... + * svcgssd is chatty enough as it is. + */ + if (rpc_verbosity > 0) + libtirpc_set_debug(progname, rpc_verbosity, fg); #else if (rpc_verbosity > 0) printerr(0, "Warning: rpcsec_gss library does not " diff --git a/utils/mountd/auth.c b/utils/mountd/auth.c index 330cab5..894a7a5 100644 --- a/utils/mountd/auth.c +++ b/utils/mountd/auth.c @@ -85,7 +85,7 @@ auth_reload() { struct stat stb; static ino_t last_inode; - static int last_fd; + static int last_fd = -1; static unsigned int counter; int fd; @@ -93,11 +93,22 @@ auth_reload() xlog(L_FATAL, "couldn't open %s", _PATH_ETAB); } else if (fstat(fd, &stb) < 0) { xlog(L_FATAL, "couldn't stat %s", _PATH_ETAB); - } else if (stb.st_ino == last_inode) { + close(fd); + } else if (last_fd != -1 && stb.st_ino == last_inode) { + /* We opened the etab file before, and its inode + * number hasn't changed since then. + */ close(fd); return counter; } else { - close(last_fd); + /* Need to process entries from the etab file. Close + * the file descriptor from the previous open (last_fd), + * and keep the current file descriptor open to prevent + * the file system reusing the current inode number + * (last_inode). + */ + if (last_fd != -1) + close(last_fd); last_fd = fd; last_inode = stb.st_ino; } diff --git a/utils/nfsd/nfssvc.c b/utils/nfsd/nfssvc.c index a2b11d8..e8efd06 100644 --- a/utils/nfsd/nfssvc.c +++ b/utils/nfsd/nfssvc.c @@ -168,22 +168,22 @@ nfssvc_setfds(const struct addrinfo *hints, const char *node, const char *port) continue; } - xlog(D_GENERAL, "Creating %s %s socket.", family, proto); - /* open socket and prepare to hand it off to kernel */ sockfd = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); if (sockfd < 0) { - if (errno == EAFNOSUPPORT) - xlog(L_NOTICE, "address family %s not " - "supported by protocol %s", - family, proto); - else + if (errno != EAFNOSUPPORT) { xlog(L_ERROR, "unable to create %s %s socket: " "errno %d (%m)", family, proto, errno); - rc = errno; - goto error; + rc = errno; + goto error; + } + addr = addr->ai_next; + continue; } + + xlog(D_GENERAL, "Created %s %s socket.", family, proto); + #ifdef IPV6_SUPPORTED if (addr->ai_family == AF_INET6 && setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on))) { diff --git a/utils/statd/rmtcall.c b/utils/statd/rmtcall.c index 45c84f9..c4f6364 100644 --- a/utils/statd/rmtcall.c +++ b/utils/statd/rmtcall.c @@ -113,7 +113,6 @@ statd_get_socket(void) if (sockfd < 0) return -1; - FD_SET(sockfd, &SVC_FDSET); return sockfd; } diff --git a/utils/statd/statd.c b/utils/statd/statd.c index 2b7a167..e5b4c98 100644 --- a/utils/statd/statd.c +++ b/utils/statd/statd.c @@ -247,6 +247,7 @@ int main (int argc, char **argv) int port = 0, out_port = 0; int nlm_udp = 0, nlm_tcp = 0; struct rlimit rlim; + int notify_sockfd; /* Default: daemon mode, no other options */ run_mode = 0; @@ -437,7 +438,7 @@ int main (int argc, char **argv) } /* Make sure we have a privilege port for calling into the kernel */ - if (statd_get_socket() < 0) + if ((notify_sockfd = statd_get_socket()) < 0) exit(1); /* If sm-notify didn't take all the state files, load @@ -484,7 +485,7 @@ int main (int argc, char **argv) * Handle incoming requests: SM_NOTIFY socket requests, as * well as callbacks from lockd. */ - my_svc_run(); /* I rolled my own, Olaf made it better... */ + my_svc_run(notify_sockfd); /* I rolled my own, Olaf made it better... */ /* Only get here when simulating a crash so we should probably * start sm-notify running again. As we have already dropped diff --git a/utils/statd/statd.h b/utils/statd/statd.h index a1d8035..231ac7e 100644 --- a/utils/statd/statd.h +++ b/utils/statd/statd.h @@ -28,7 +28,7 @@ extern _Bool statd_present_address(const struct sockaddr *sap, char *buf, __attribute__((__malloc__)) extern char * statd_canonical_name(const char *hostname); -extern void my_svc_run(void); +extern void my_svc_run(int); extern void notify_hosts(void); extern void shuffle_dirs(void); extern int statd_get_socket(void); diff --git a/utils/statd/svc_run.c b/utils/statd/svc_run.c index d98ecee..28c1ad6 100644 --- a/utils/statd/svc_run.c +++ b/utils/statd/svc_run.c @@ -78,7 +78,7 @@ my_svc_exit(void) * The heart of the server. A crib from libc for the most part... */ void -my_svc_run(void) +my_svc_run(int sockfd) { FD_SET_TYPE readfds; int selret; @@ -96,6 +96,8 @@ my_svc_run(void) } readfds = SVC_FDSET; + /* Set notify sockfd for waiting for reply */ + FD_SET(sockfd, &readfds); if (notify) { struct timeval tv; @@ -125,8 +127,10 @@ my_svc_run(void) default: selret -= process_reply(&readfds); - if (selret) + if (selret) { + FD_CLR(sockfd, &readfds); svc_getreqset(&readfds); + } } } }