Blame SOURCES/nfs-utils-1.3.0-nfsidmap-update.patch

e19a30
diff --git a/aclocal/keyutils.m4 b/aclocal/keyutils.m4
e19a30
index a392c0e..16b225d 100644
e19a30
--- a/aclocal/keyutils.m4
e19a30
+++ b/aclocal/keyutils.m4
e19a30
@@ -8,4 +8,8 @@ AC_DEFUN([AC_KEYUTILS], [
e19a30
 
e19a30
   AC_CHECK_HEADERS([keyutils.h])
e19a30
 
e19a30
+  AC_CHECK_LIB([keyutils], [find_key_by_type_and_desc],
e19a30
+		[AC_DEFINE([HAVE_FIND_KEY_BY_TYPE_AND_DESC], [1],
e19a30
+			[Define to 1 if you have the `find_key_by_type_and_desc' function.])],)
e19a30
+
e19a30
 ])dnl
e19a30
diff --git a/utils/nfsidmap/nfsidmap.c b/utils/nfsidmap/nfsidmap.c
e19a30
index 10f69f9..9c49d42 100644
e19a30
--- a/utils/nfsidmap/nfsidmap.c
e19a30
+++ b/utils/nfsidmap/nfsidmap.c
e19a30
@@ -1,3 +1,4 @@
e19a30
+#include "config.h"
e19a30
 
e19a30
 #include <stdarg.h>
e19a30
 #include <stdio.h>
e19a30
@@ -15,7 +16,7 @@
e19a30
 #include "conffile.h"
e19a30
 
e19a30
 int verbose = 0;
e19a30
-char *usage="Usage: %s [-v] [-c || [-u|-g|-r key] || [-t timeout] key desc]";
e19a30
+char *usage = "Usage: %s [-v] [-c || [-u|-g|-r key] || -d || -l || [-t timeout] key desc]";
e19a30
 
e19a30
 #define MAX_ID_LEN   11
e19a30
 #define IDMAP_NAMESZ 128
e19a30
@@ -31,15 +32,163 @@ char *usage="Usage: %s [-v] [-c || [-u|-g|-r key] || [-t timeout] key desc]";
e19a30
 #define PATH_IDMAPDCONF "/etc/idmapd.conf"
e19a30
 #endif
e19a30
 
e19a30
-static int keyring_clear(char *keyring);
e19a30
-
e19a30
 #define UIDKEYS 0x1
e19a30
 #define GIDKEYS 0x2
e19a30
 
e19a30
+#ifndef HAVE_FIND_KEY_BY_TYPE_AND_DESC
e19a30
+static key_serial_t find_key_by_type_and_desc(const char *type,
e19a30
+		const char *desc, key_serial_t destringid)
e19a30
+{
e19a30
+	char buf[BUFSIZ];
e19a30
+	key_serial_t key;
e19a30
+	FILE *fp;
e19a30
+
e19a30
+	if ((fp = fopen(PROCKEYS, "r")) == NULL) {
e19a30
+		xlog_err("fopen(%s) failed: %m", PROCKEYS);
e19a30
+		return -1;
e19a30
+	}
e19a30
+
e19a30
+	key = -1;
e19a30
+	while(fgets(buf, BUFSIZ, fp) != NULL) {
e19a30
+		unsigned int id;
e19a30
+
e19a30
+		if (strstr(buf, type) == NULL)
e19a30
+			continue;
e19a30
+		if (strstr(buf, desc) == NULL)
e19a30
+			continue;
e19a30
+		if (sscanf(buf, "%x %*s", &id) != 1) {
e19a30
+			xlog_err("Unparsable keyring entry in %s", PROCKEYS);
e19a30
+			continue;
e19a30
+		}
e19a30
+
e19a30
+		key = (key_serial_t)id;
e19a30
+		break;
e19a30
+	}
e19a30
+
e19a30
+	fclose(fp);
e19a30
+	return key;
e19a30
+}
e19a30
+#endif
e19a30
+
e19a30
+/*
e19a30
+ * Clear all the keys on the given keyring
e19a30
+ */
e19a30
+static int keyring_clear(const char *keyring)
e19a30
+{
e19a30
+	key_serial_t key;
e19a30
+
e19a30
+	key = find_key_by_type_and_desc("keyring", keyring, 0);
e19a30
+	if (key == -1) {
e19a30
+		if (verbose)
e19a30
+			xlog_warn("'%s' keyring was not found.", keyring);
e19a30
+		return EXIT_SUCCESS;
e19a30
+	}
e19a30
+
e19a30
+	if (keyctl_clear(key) < 0) {
e19a30
+		xlog_err("keyctl_clear(0x%x) failed: %m",
e19a30
+				(unsigned int)key);
e19a30
+		return EXIT_FAILURE;
e19a30
+	}
e19a30
+
e19a30
+	if (verbose)
e19a30
+		xlog_warn("'%s' cleared", keyring);
e19a30
+	return EXIT_SUCCESS;
e19a30
+}
e19a30
+
e19a30
+static int display_default_domain(void)
e19a30
+{
e19a30
+	char domain[NFS4_MAX_DOMAIN_LEN];
e19a30
+	int rc;
e19a30
+
e19a30
+	rc = nfs4_get_default_domain(NULL, domain, NFS4_MAX_DOMAIN_LEN);
e19a30
+	if (rc) {
e19a30
+		xlog_errno(rc, "nfs4_get_default_domain failed: %m");
e19a30
+		return EXIT_FAILURE;
e19a30
+	}
e19a30
+
e19a30
+	printf("%s\n", domain);
e19a30
+	return EXIT_SUCCESS;
e19a30
+}
e19a30
+
e19a30
+static void list_key(key_serial_t key)
e19a30
+{
e19a30
+	char *buffer, *c;
e19a30
+	int rc;
e19a30
+
e19a30
+	rc = keyctl_describe_alloc(key, &buffer);
e19a30
+	if (rc < 0) {
e19a30
+		switch (errno) {
e19a30
+		case EKEYEXPIRED:
e19a30
+			printf("Expired key not displayed\n");
e19a30
+			break;
e19a30
+		default:
e19a30
+			xlog_err("Failed to describe key: %m");
e19a30
+		}
e19a30
+		return;
e19a30
+	}
e19a30
+
e19a30
+	c = strrchr(buffer, ';');
e19a30
+	if (!c) {
e19a30
+		xlog_err("Unparsable key not displayed\n");
e19a30
+		goto out_free;
e19a30
+	}
e19a30
+	printf("  %s\n", ++c);
e19a30
+
e19a30
+out_free:
e19a30
+	free(buffer);
e19a30
+}
e19a30
+
e19a30
+static void list_keys(const char *ring_name, key_serial_t ring_id)
e19a30
+{
e19a30
+	key_serial_t *key;
e19a30
+	void *keylist;
e19a30
+	int count;
e19a30
+
e19a30
+	count = keyctl_read_alloc(ring_id, &keylist);
e19a30
+	if (count < 0) {
e19a30
+		xlog_err("Failed to read keyring %s: %m", ring_name);
e19a30
+		return;
e19a30
+	}
e19a30
+	count /= (int)sizeof(*key);
e19a30
+
e19a30
+	switch (count) {
e19a30
+	case 0:
e19a30
+		printf("No %s keys found.\n", ring_name);
e19a30
+		break;
e19a30
+	case 1:
e19a30
+		printf("1 %s key found:\n", ring_name);
e19a30
+		break;
e19a30
+	default:
e19a30
+		printf("%u %s keys found:\n", count, ring_name);
e19a30
+	}
e19a30
+
e19a30
+	for (key = keylist; count--; key++)
e19a30
+		list_key(*key);
e19a30
+
e19a30
+	free(keylist);
e19a30
+}
e19a30
+
e19a30
+/*
e19a30
+ * List all keys on a keyring
e19a30
+ */
e19a30
+static int list_keyring(const char *keyring)
e19a30
+{
e19a30
+	key_serial_t key;
e19a30
+
e19a30
+	key = find_key_by_type_and_desc("keyring", keyring, 0);
e19a30
+	if (key == -1) {
e19a30
+		xlog_err("'%s' keyring was not found.", keyring);
e19a30
+		return EXIT_FAILURE;
e19a30
+	}
e19a30
+
e19a30
+	list_keys(keyring, key);
e19a30
+	return EXIT_SUCCESS;
e19a30
+}
e19a30
+
e19a30
 /*
e19a30
  * Find either a user or group id based on the name@domain string
e19a30
  */
e19a30
-int id_lookup(char *name_at_domain, key_serial_t key, int type)
e19a30
+static int id_lookup(char *name_at_domain, key_serial_t key, int type)
e19a30
 {
e19a30
 	char id[MAX_ID_LEN];
e19a30
 	uid_t uid = 0;
e19a30
@@ -53,30 +202,33 @@ int id_lookup(char *name_at_domain, key_serial_t key, int type)
e19a30
 		rc = nfs4_group_owner_to_gid(name_at_domain, &gid;;
e19a30
 		sprintf(id, "%u", gid);
e19a30
 	}
e19a30
-	if (rc < 0)
e19a30
+	if (rc < 0) {
e19a30
 		xlog_errno(rc, "id_lookup: %s: failed: %m",
e19a30
 			(type == USER ? "nfs4_owner_to_uid" : "nfs4_group_owner_to_gid"));
e19a30
+		return EXIT_FAILURE;
e19a30
+	}
e19a30
 
e19a30
-	if (rc == 0) {
e19a30
-		rc = keyctl_instantiate(key, id, strlen(id) + 1, 0);
e19a30
-		if (rc < 0) {
e19a30
-			switch(rc) {
e19a30
-			case -EDQUOT:
e19a30
-			case -ENFILE:
e19a30
-			case -ENOMEM:
e19a30
-				/*
e19a30
-			 	 * The keyring is full. Clear the keyring and try again
e19a30
-			 	 */
e19a30
-				rc = keyring_clear(DEFAULT_KEYRING);
e19a30
-				if (rc == 0)
e19a30
-					rc = keyctl_instantiate(key, id, strlen(id) + 1, 0);
e19a30
-				break;
e19a30
-			default:
e19a30
+	rc = EXIT_SUCCESS;
e19a30
+	if (keyctl_instantiate(key, id, strlen(id) + 1, 0)) {
e19a30
+		switch (errno) {
e19a30
+		case EDQUOT:
e19a30
+		case ENFILE:
e19a30
+		case ENOMEM:
e19a30
+			/*
e19a30
+			 * The keyring is full. Clear the keyring and try again
e19a30
+			 */
e19a30
+			rc = keyring_clear(DEFAULT_KEYRING);
e19a30
+			if (rc)
e19a30
 				break;
e19a30
+			if (keyctl_instantiate(key, id, strlen(id) + 1, 0)) {
e19a30
+				rc = EXIT_FAILURE;
e19a30
+				xlog_err("id_lookup: keyctl_instantiate failed: %m");
e19a30
 			}
e19a30
+			break;
e19a30
+		default:
e19a30
+			rc = EXIT_FAILURE;
e19a30
+			break;
e19a30
 		}
e19a30
-		if (rc < 0)
e19a30
-			xlog_err("id_lookup: keyctl_instantiate failed: %m");
e19a30
 	}
e19a30
 
e19a30
 	return rc;
e19a30
@@ -85,7 +237,7 @@ int id_lookup(char *name_at_domain, key_serial_t key, int type)
e19a30
 /*
e19a30
  * Find the name@domain string from either a user or group id
e19a30
  */
e19a30
-int name_lookup(char *id, key_serial_t key, int type)
e19a30
+static int name_lookup(char *id, key_serial_t key, int type)
e19a30
 {
e19a30
 	char name[IDMAP_NAMESZ];
e19a30
 	char domain[NFS4_MAX_DOMAIN_LEN];
e19a30
@@ -94,11 +246,10 @@ int name_lookup(char *id, key_serial_t key, int type)
e19a30
 	int rc;
e19a30
 
e19a30
 	rc = nfs4_get_default_domain(NULL, domain, NFS4_MAX_DOMAIN_LEN);
e19a30
-	if (rc != 0) {
e19a30
+	if (rc) {
e19a30
 		xlog_errno(rc,
e19a30
 			"name_lookup: nfs4_get_default_domain failed: %m");
e19a30
-		rc = -1;
e19a30
-		goto out;
e19a30
+		return EXIT_FAILURE;
e19a30
 	}
e19a30
 
e19a30
 	if (type == USER) {
e19a30
@@ -108,61 +259,21 @@ int name_lookup(char *id, key_serial_t key, int type)
e19a30
 		gid = atoi(id);
e19a30
 		rc = nfs4_gid_to_name(gid, domain, name, IDMAP_NAMESZ);
e19a30
 	}
e19a30
-	if (rc < 0)
e19a30
+	if (rc) {
e19a30
 		xlog_errno(rc, "name_lookup: %s: failed: %m",
e19a30
 			(type == USER ? "nfs4_uid_to_name" : "nfs4_gid_to_name"));
e19a30
-
e19a30
-	if (rc == 0) {
e19a30
-		rc = keyctl_instantiate(key, &name, strlen(name), 0);
e19a30
-		if (rc < 0)
e19a30
-			xlog_err("name_lookup: keyctl_instantiate failed: %m");
e19a30
+		return EXIT_FAILURE;
e19a30
 	}
e19a30
-out:
e19a30
-	return rc;
e19a30
-}
e19a30
-/*
e19a30
- * Clear all the keys on the given keyring
e19a30
- */
e19a30
-static int keyring_clear(char *keyring)
e19a30
-{
e19a30
-	FILE *fp;
e19a30
-	char buf[BUFSIZ];
e19a30
-	key_serial_t key;
e19a30
 
e19a30
-	if (keyring == NULL)
e19a30
-		keyring = DEFAULT_KEYRING;
e19a30
-
e19a30
-	if ((fp = fopen(PROCKEYS, "r")) == NULL) {
e19a30
-		xlog_err("fopen(%s) failed: %m", PROCKEYS);
e19a30
-		return 1;
e19a30
+	rc = EXIT_SUCCESS;
e19a30
+	if (keyctl_instantiate(key, &name, strlen(name), 0)) {
e19a30
+		rc = EXIT_FAILURE;
e19a30
+		xlog_err("name_lookup: keyctl_instantiate failed: %m");
e19a30
 	}
e19a30
 
e19a30
-	while(fgets(buf, BUFSIZ, fp) != NULL) {
e19a30
-		if (strstr(buf, "keyring") == NULL)
e19a30
-			continue;
e19a30
-		if (strstr(buf, keyring) == NULL)
e19a30
-			continue;
e19a30
-		if (verbose) {
e19a30
-			*(strchr(buf, '\n')) = '\0';
e19a30
-			xlog_warn("clearing '%s'", buf);
e19a30
-		}
e19a30
-		/*
e19a30
-		 * The key is the first arugment in the string
e19a30
-		 */
e19a30
-		*(strchr(buf, ' ')) = '\0';
e19a30
-		sscanf(buf, "%x", &key);
e19a30
-		if (keyctl_clear(key) < 0) {
e19a30
-			xlog_err("keyctl_clear(0x%x) failed: %m", key);
e19a30
-			fclose(fp);
e19a30
-			return 1;
e19a30
-		}
e19a30
-		fclose(fp);
e19a30
-		return 0;
e19a30
-	}
e19a30
-	xlog_err("'%s' keyring was not found.", keyring);
e19a30
-	fclose(fp);
e19a30
-	return 1;
e19a30
+	return rc;
e19a30
 }
e19a30
+
e19a30
 /*
e19a30
  * Revoke a key 
e19a30
  */
e19a30
@@ -177,7 +288,7 @@ static int key_invalidate(char *keystr, int keymask)
e19a30
 
e19a30
 	if ((fp = fopen(PROCKEYS, "r")) == NULL) {
e19a30
 		xlog_err("fopen(%s) failed: %m", PROCKEYS);
e19a30
-		return 1;
e19a30
+		return EXIT_FAILURE;
e19a30
 	}
e19a30
 
e19a30
 	while(fgets(buf, BUFSIZ, fp) != NULL) {
e19a30
@@ -211,18 +322,18 @@ static int key_invalidate(char *keystr, int keymask)
e19a30
 		if (keyctl_invalidate(key) < 0) {
e19a30
 			xlog_err("keyctl_invalidate(0x%x) failed: %m", key);
e19a30
 			fclose(fp);
e19a30
-			return 1;
e19a30
+			return EXIT_FAILURE;
e19a30
 		}
e19a30
 
e19a30
 		keymask &= ~mask;
e19a30
 		if (keymask == 0) {
e19a30
 			fclose(fp);
e19a30
-			return 0;
e19a30
+			return EXIT_SUCCESS;
e19a30
 		}
e19a30
 	}
e19a30
 	xlog_err("'%s' key was not found.", keystr);
e19a30
 	fclose(fp);
e19a30
-	return 1;
e19a30
+	return EXIT_FAILURE;
e19a30
 }
e19a30
 
e19a30
 int main(int argc, char **argv)
e19a30
@@ -234,7 +345,7 @@ int main(int argc, char **argv)
e19a30
 	int timeout = 600;
e19a30
 	key_serial_t key;
e19a30
 	char *progname, *keystr = NULL;
e19a30
-	int clearing = 0, keymask = 0;
e19a30
+	int clearing = 0, keymask = 0, display = 0, list = 0;
e19a30
 
e19a30
 	/* Set the basename */
e19a30
 	if ((progname = strrchr(argv[0], '/')) != NULL)
e19a30
@@ -244,8 +355,14 @@ int main(int argc, char **argv)
e19a30
 
e19a30
 	xlog_open(progname);
e19a30
 
e19a30
-	while ((opt = getopt(argc, argv, "u:g:r:ct:v")) != -1) {
e19a30
+	while ((opt = getopt(argc, argv, "du:g:r:ct:vl")) != -1) {
e19a30
 		switch (opt) {
e19a30
+		case 'd':
e19a30
+			display++;
e19a30
+			break;
e19a30
+		case 'l':
e19a30
+			list++;
e19a30
+			break;
e19a30
 		case 'u':
e19a30
 			keymask = UIDKEYS;
e19a30
 			keystr = strdup(optarg);
e19a30
@@ -273,28 +390,35 @@ int main(int argc, char **argv)
e19a30
 		}
e19a30
 	}
e19a30
 
e19a30
+	if (geteuid() != 0) {
e19a30
+		xlog_err("Must be run as root.");
e19a30
+		return EXIT_FAILURE;
e19a30
+	}
e19a30
+
e19a30
 	if ((rc = nfs4_init_name_mapping(PATH_IDMAPDCONF)))  {
e19a30
 		xlog_errno(rc, "Unable to create name to user id mappings.");
e19a30
-		return 1;
e19a30
+		return EXIT_FAILURE;
e19a30
 	}
e19a30
 	if (!verbose)
e19a30
 		verbose = conf_get_num("General", "Verbosity", 0);
e19a30
 
e19a30
+	if (display)
e19a30
+		return display_default_domain();
e19a30
+	if (list)
e19a30
+		return list_keyring(DEFAULT_KEYRING);
e19a30
 	if (keystr) {
e19a30
-		rc = key_invalidate(keystr, keymask);
e19a30
-		return rc;		
e19a30
+		return key_invalidate(keystr, keymask);
e19a30
 	}
e19a30
 	if (clearing) {
e19a30
 		xlog_syslog(0);
e19a30
-		rc = keyring_clear(DEFAULT_KEYRING);
e19a30
-		return rc;		
e19a30
+		return keyring_clear(DEFAULT_KEYRING);
e19a30
 	}
e19a30
 
e19a30
-	xlog_stderr(0);
e19a30
+	xlog_stderr(verbose);
e19a30
 	if ((argc - optind) != 2) {
e19a30
-		xlog_err("Bad arg count. Check /etc/request-key.conf");
e19a30
+		xlog_warn("Bad arg count. Check /etc/request-key.conf");
e19a30
 		xlog_warn(usage, progname);
e19a30
-		return 1;
e19a30
+		return EXIT_FAILURE;
e19a30
 	}
e19a30
 
e19a30
 	if (verbose)
e19a30
@@ -305,11 +429,15 @@ int main(int argc, char **argv)
e19a30
 	arg = strdup(argv[optind]);
e19a30
 	if (arg == NULL) {
e19a30
 		xlog_err("strdup failed: %m");
e19a30
-		return 1;
e19a30
+		return EXIT_FAILURE;
e19a30
 	}
e19a30
 	type = strtok(arg, ":");
e19a30
 	value = strtok(NULL, ":");
e19a30
-
e19a30
+	if (value == NULL) {
e19a30
+		free(arg);
e19a30
+		xlog_err("Error: Null uid/gid value.");
e19a30
+		return EXIT_FAILURE;
e19a30
+	}
e19a30
 	if (verbose) {
e19a30
 		xlog_warn("key: 0x%lx type: %s value: %s timeout %ld",
e19a30
 			key, type, value, timeout);
e19a30
@@ -328,7 +456,7 @@ int main(int argc, char **argv)
e19a30
 		rc = name_lookup(value, key, GROUP);
e19a30
 
e19a30
 	/* Set timeout to 10 (600 seconds) minutes */
e19a30
-	if (rc == 0)
e19a30
+	if (rc == EXIT_SUCCESS)
e19a30
 		keyctl_set_timeout(key, timeout);
e19a30
 
e19a30
 	free(arg);
e19a30
diff --git a/utils/nfsidmap/nfsidmap.man b/utils/nfsidmap/nfsidmap.man
e19a30
index 3a3a523..0275bdf 100644
e19a30
--- a/utils/nfsidmap/nfsidmap.man
e19a30
+++ b/utils/nfsidmap/nfsidmap.man
e19a30
@@ -11,30 +11,72 @@ nfsidmap \- The NFS idmapper upcall program
e19a30
 .B "nfsidmap [-v] [-c]"
e19a30
 .br
e19a30
 .B "nfsidmap [-v] [-u|-g|-r user]"
e19a30
+.br
e19a30
+.B "nfsidmap -d"
e19a30
+.br
e19a30
+.B "nfsidmap -l"
e19a30
 .SH DESCRIPTION
e19a30
-The file
e19a30
+The NFSv4 protocol represents the local system's UID and GID values
e19a30
+on the wire as strings of the form
e19a30
+.IR user@domain .
e19a30
+The process of translating from UID to string and string to UID is
e19a30
+referred to as "ID mapping."
e19a30
+.PP
e19a30
+The system derives the
e19a30
+.I user
e19a30
+part of the string by performing a password or group lookup.
e19a30
+The lookup mechanism is configured in
e19a30
+.IR /etc/idmapd.conf .
e19a30
+.PP
e19a30
+By default, the
e19a30
+.I domain
e19a30
+part of the string is the system's DNS domain name.
e19a30
+It can also be specified in
e19a30
+.I /etc/idmapd.conf
e19a30
+if the system is multi-homed,
e19a30
+or if the system's DNS domain name does
e19a30
+not match the name of the system's Kerberos realm.
e19a30
+.PP
e19a30
+The
e19a30
 .I /usr/sbin/nfsidmap
e19a30
-is used by the NFS idmapper to translate user and group ids into names, and to
e19a30
-translate user and group names into ids. Idmapper uses request-key to perform
e19a30
-the upcall and cache the result.
e19a30
+program performs translations on behalf of the kernel.
e19a30
+The kernel uses the request-key mechanism to perform
e19a30
+an upcall.
e19a30
 .I /usr/sbin/nfsidmap
e19a30
-is called by /sbin/request-key, and will perform the translation and
e19a30
-initialize a key with the resulting information.
e19a30
+is invoked by /sbin/request-key, performs the translation,
e19a30
+and initializes a key with the resulting information.
e19a30
+The kernel then caches the translation results in the key.
e19a30
 .PP
e19a30
 .I nfsidmap
e19a30
-can also used to clear the keyring of all the keys or 
e19a30
-revoke one particular key.  
e19a30
-This is useful when the id mappings have failed to due 
e19a30
-to a lookup error resulting in all the cached uids/gids to be set 
e19a30
-to the user id nobody.
e19a30
+can also clear cached ID map results in the kernel,
e19a30
+or revoke one particular key.
e19a30
+An incorrect cached key can result in file and directory ownership
e19a30
+reverting to "nobody" on NFSv4 mount points.
e19a30
+.PP
e19a30
+In addition, the
e19a30
+.B -d
e19a30
+and
e19a30
+.B -l
e19a30
+options are available to help diagnose misconfigurations.
e19a30
+They have no effect on the keyring containing ID mapping results.
e19a30
 .SH OPTIONS
e19a30
 .TP
e19a30
 .B -c 
e19a30
 Clear the keyring of all the keys.
e19a30
 .TP
e19a30
+.B -d
e19a30
+Display the system's effective NFSv4 domain name on
e19a30
+.IR stdout .
e19a30
+.TP
e19a30
 .B -g user
e19a30
 Revoke the gid key of the given user.
e19a30
 .TP
e19a30
+.B -l
e19a30
+Display on
e19a30
+.I stdout
e19a30
+all keys currently in the keyring used to cache ID mapping results.
e19a30
+These keys are visible only to the superuser.
e19a30
+.TP
e19a30
 .B -r user
e19a30
 Revoke both the uid and gid key of the given user.
e19a30
 .TP
e19a30
@@ -89,5 +131,15 @@ Notice that the new line was added above the line for the generic program.
e19a30
 request-key will find the first matching line and run the corresponding program.
e19a30
 In this case, /some/other/program will handle all uid lookups, and
e19a30
 /usr/sbin/nfsidmap will handle gid, user, and group lookups.
e19a30
+.SH FILES
e19a30
+.TP
e19a30
+.I /etc/idmapd.conf
e19a30
+ID mapping configuration file
e19a30
+.TP
e19a30
+.I /etc/request-key.conf
e19a30
+Request key configuration file
e19a30
+.SH "SEE ALSO"
e19a30
+.BR idmapd.conf (5),
e19a30
+.BR request-key (8)
e19a30
 .SH AUTHOR
e19a30
 Bryan Schumaker, <bjschuma@netapp.com>