Patchwork [08/11] nsdbparams: "update" subcommand shouldn't wipe security data

login
register
mail settings
Submitter Chuck Lever
Date Jan. 16, 2013, 9:52 p.m.
Message ID <20130116215254.21683.8118.stgit@seurat.1015granger.net>
Download mbox | patch
Permalink /patch/213076/
State Accepted
Headers show

Comments

Chuck Lever - Jan. 16, 2013, 9:52 p.m.
"nsdbparams update" updates the NSDB's security data every time it
is invoked.  That means every time an NSDB connection parameters
update is done (say, to prevent LDAP referral following), the
previous security settings for that NSDB are wiped.

It's always worked this way, but until now, fedfs-utils has supported
only one connection security type, a type which had no security data
associated with it.  So we couldn't tell it was broken.

Also, nsdbparams should validate incoming certificate material.  And
let's document in the man page what kind of certificate is needed.

Finally, a minor UI change: allow users to specify "--certfile"
without "--sectype" to enable TLS mode.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---

 doc/man/nsdbparams.8    |   59 ++++++++++++++++--------
 src/nsdbparams/main.c   |    4 ++
 src/nsdbparams/update.c |  115 +++++++++++++++++++++++++++++++----------------
 3 files changed, 120 insertions(+), 58 deletions(-)

Patch

diff --git a/doc/man/nsdbparams.8 b/doc/man/nsdbparams.8
index 84820c5..7f48411 100644
--- a/doc/man/nsdbparams.8
+++ b/doc/man/nsdbparams.8
@@ -82,16 +82,24 @@  a coherent namespace across multiple file servers using
 For further details, see
 .BR fedfs (7).
 .P
-The bulk of FedFS junction information in a FedFS domain is stored
-on one or more LDAP servers.
+The bulk of FedFS metadata is stored on one or more LDAP servers.
 These servers are known as
 .IR "namespace databases" ,
 or NSDBs, for short.
-On systems that contact NSDBs,
-a local database stores connection parameters for each NSDB.
-These connection parameters are used during file server operations
-that access NSDBs,
-and when executing NSDB administrative commands.
+An
+.I NSDB client
+is any system that communicates with an NSDB.
+This can be either a fileserver or an NSDB administrative client.
+.P
+On NSDB clients,
+a small local database stores information about how to connect
+to each NSDB node.  These
+.I NSDB connection parameters
+are used when an NSDB client contacts an NSDB node to perform file
+server operations or when executing NSDB administrative commands.
+.P
+The settings in this database effect only the behavior of the local
+NSDB client.  They have no effect on the operation of NSDBs nodes.
 .SH DESCRIPTION
 The
 .BR nsdbparams (8)
@@ -188,10 +196,9 @@  If no NSDB port number is provided on the command line, the
 command uses the default LDAP port (389).
 .P
 The database matches NSDB domain names and ports by exact value.
-If two unique domain names point
-to the IP address of the same physical NSDB,
-they are considered separate entries
-in the local NSDB connection parameter database.
+Details on NSDB connection parameters database entry matching can be
+found in
+.BR nsdb-parameters (7).
 .SS Command line options
 .IP "\fB\-d, \-\-debug"
 Enables debugging messages during subcommand operation.
@@ -209,12 +216,13 @@  This option is valid for the
 .B update
 subcommand.
 .IP "\fB-f, \-\-certfile=\fIpathname\fP"
-Specifies the pathname of a local file containing the X.509 certificate
-to establish a TLS connection with the specified NSDB.
-The
-.BR nsdbparams (8)
-command copies the specified certificate to a private directory.
-The specified file can be deleted after the subcommand succeeds.
+Specifies the pathname of a local file containing security data
+appropriate for the
+.B "\-\-sectype"
+specified on the command line.
+The specified file may be deleted after the command succeeds.
+Details on security data can be found in
+.BR nsdb-parameters (7).
 This option is valid for the
 .B update
 subcommand.
@@ -272,6 +280,19 @@  If that user doesn't exist, then the UID for
 .I nobody
 is used instead.
 This option is valid for all subcommands.
+.SH CHANGING SECURITY TYPES
+You can change connection security types used to contact an NSDB node
+using the
+.B update
+subcommand.  Simply specify the new security type with the
+.B "\-\-sectype"
+option.
+Specifying the NONE type removes existing stored certificate material
+for that NSDB node.
+Specifying the TLS type replaces existing stored certificate material
+with new material specified with the
+.B "\-\-certfile"
+option.
 .SH EXAMPLES
 If there is an NSDB called
 .IR nsdb.example.net ,
@@ -304,7 +325,7 @@  subcommand and specify the
 and
 .B \-\-certfile
 options.
-For instance, if an X.509 certificate for
+For instance, if an x.509 certificate for
 .I nsdb.example.net
 were contained in a local file called
 .IR /tmp/nsdb.pem ,
@@ -325,7 +346,7 @@  you might use:
 database of NSDB connection parameters
 .TP
 .I @statedir@/nsdbcerts
-local directory that stores X.509 certificates for NSDBs
+local directory that stores x.509 certificates for NSDBs
 .SH "SEE ALSO"
 .BR fedfs (7),
 .BR nsdb-parameters (7),
diff --git a/src/nsdbparams/main.c b/src/nsdbparams/main.c
index 6e96c1c..103761f 100644
--- a/src/nsdbparams/main.c
+++ b/src/nsdbparams/main.c
@@ -206,6 +206,8 @@  main(int argc, char **argv)
 		goto out;
 	}
 
+	nsdb_connsec_crypto_startup();
+
 	if (strcasecmp(argv[1], "delete") == 0)
 		exit_status = nsdbparams_delete(progname, argc - 1, argv + 1);
 	else if (strcasecmp(argv[1], "list") == 0)
@@ -219,6 +221,8 @@  main(int argc, char **argv)
 		nsdbparams_usage(progname);
 	}
 
+	nsdb_connsec_crypto_shutdown();
+
 out:
 	exit(exit_status);
 }
diff --git a/src/nsdbparams/update.c b/src/nsdbparams/update.c
index 60db7a5..62de0c2 100644
--- a/src/nsdbparams/update.c
+++ b/src/nsdbparams/update.c
@@ -138,7 +138,7 @@  nsdbparams_test_nsdb(const char *nsdbname, unsigned short nsdbport)
  * @return false if could not parse security type
  */
 static _Bool
-nsdbparams_sectype(const char *arg, unsigned int *type)
+nsdbparams_sectype(const char *arg, FedFsConnectionSec *type)
 {
 	unsigned long tmp;
 	char *endptr;
@@ -171,6 +171,55 @@  try_symbolic:
 }
 
 /**
+ * Update the security setting for this NSDB
+ *
+ * @param nsdbname NUL-terminated UTF-8 string containing NSDB hostname
+ * @param nsdbport NSDB's IP port number
+ * @param type connection security type for this NSDB
+ * @param certfile NUL-terminated UTF-8 string containing pathname of file
+ * @return a FedFsStatus code
+ */
+static FedFsStatus
+nsdbparams_update_security(const char *nsdbname, unsigned short nsdbport,
+		FedFsConnectionSec type, const char *certfile)
+{
+	FedFsStatus retval;
+
+	switch (type) {
+	case FEDFS_SEC_NONE:
+		if (certfile != NULL)
+			xlog(L_ERROR, "The specified certfile was ignored");
+
+		retval = nsdb_connsec_set_none(nsdbname, nsdbport);
+		if (retval != FEDFS_OK) {
+			xlog(L_ERROR, "Failed to update security pararmeters: %s",
+				nsdb_display_fedfsstatus(retval));
+			return retval;
+		}
+		break;
+	case FEDFS_SEC_TLS:
+		if (certfile == NULL) {
+			xlog(L_ERROR, "No certfile was specified");
+			return FEDFS_ERR_INVAL;
+		}
+
+		retval = nsdb_connsec_set_tls_file(nsdbname, nsdbport,
+							certfile);
+		if (retval != FEDFS_OK) {
+			xlog(L_ERROR, "Failed to update security pararmeters: %s",
+				nsdb_display_fedfsstatus(retval));
+			return retval;
+		}
+		break;
+	default:
+		xlog(L_ERROR, "Unrecognized connection security type");
+		return FEDFS_ERR_INVAL;
+	}
+
+	return FEDFS_OK;
+}
+
+/**
  * Update an NSDB entry in our NSDB connection parameter database
  *
  * @param progname NUL-terminated UTF-8 string containing name of this program
@@ -181,12 +230,10 @@  try_symbolic:
 int
 nsdbparams_update(const char *progname, int argc, char **argv)
 {
-	char *binddn, *certfile, *nce, *nsdbname, *endptr;
+	char *binddn, *certfile, *nce, *nsdbname, *endptr, *data = NULL;
 	unsigned short nsdbport = LDAP_PORT;
-	unsigned int type = FEDFS_SEC_NONE;
-	struct fedfs_secdata secdata = {
-		.type		= type,
-	};
+	FedFsConnectionSec type = FEDFS_SEC_NONE;
+	_Bool update_security = false;
 	int arg, follow_referrals;
 	FedFsStatus retval;
 	unsigned long tmp;
@@ -227,7 +274,9 @@  nsdbparams_update(const char *progname, int argc, char **argv)
 			nce = optarg;
 			break;
 		case 'f':
+			type = FEDFS_SEC_TLS;
 			certfile = optarg;
+			update_security = true;
 			break;
 		case 'g':
 			if (optarg == NULL || *optarg == '\0') {
@@ -287,6 +336,7 @@  nsdbparams_update(const char *progname, int argc, char **argv)
 				nsdbparams_update_usage(progname);
 				goto out;
 			}
+			update_security = true;
 			break;
 		case 'u':
 			if (optarg == NULL || *optarg == '\0') {
@@ -348,62 +398,49 @@  nsdbparams_update(const char *progname, int argc, char **argv)
 		retval = nsdbparams_test_nsdb(nsdbname, nsdbport);
 		if (retval != FEDFS_OK)
 			goto out;
+		retval = nsdb_create_nsdb(nsdbname, nsdbport);
+		if (retval != FEDFS_OK) {
+			xlog(L_ERROR, "Failed to create NSDB "
+				"connection parameters for %s:%d: %s",
+				nsdbname, nsdbport,
+				nsdb_display_fedfsstatus(retval));
+			goto out;
+		}
 		break;
 	default:
 		xlog(L_ERROR, "Failed to access NSDB "
 			"connection parameter database: %s",
-			nsdbname, nsdbport, nsdb_display_fedfsstatus(retval));
+				nsdb_display_fedfsstatus(retval));
 		goto out;
 	}
 
-	if (type != FEDFS_SEC_NONE) {
-		if (certfile == NULL) {
-			xlog(L_ERROR, "No certfile was specified");
-			nsdbparams_update_usage(progname);
-			goto out;
-		}
-
-		retval = nsdb_read_certfile(certfile,
-						&secdata.data, &secdata.len);
-		if (retval != FEDFS_OK) {
-			xlog(L_ERROR, "Failed to read certfile: %s",
-					nsdb_display_fedfsstatus(retval));
+	if (update_security) {
+		retval = nsdbparams_update_security(nsdbname, nsdbport,
+							type, certfile);
+		if (retval != FEDFS_OK)
 			goto out;
-		}
 	}
 
-	/*
-	 * Ensure entry for this NSDB exists before trying to
-	 * update bind DN, NCE, and referral flags for it.
-	 */
-	if (nsdb_update_nsdb(nsdbname, nsdbport, &secdata) == FEDFS_OK) {
-		printf("NSDB list was updated successfully.\n");
-		rc = EXIT_SUCCESS;
-	}
-	free(secdata.data);
-
 	if (binddn != NULL)
 		if (nsdb_update_default_binddn(nsdbname, nsdbport,
-						binddn) != FEDFS_OK) {
-			rc = EXIT_FAILURE;
+							binddn) != FEDFS_OK)
 			goto out;
-		}
 
 	if (nce != NULL)
 		if (nsdb_update_default_nce(nsdbname, nsdbport,
-						nce) != FEDFS_OK) {
-			rc = EXIT_FAILURE;
+							nce) != FEDFS_OK)
 			goto out;
-		}
+
 	if (follow_referrals != 0) {
 		_Bool follow = follow_referrals == 2 ? true : false;
 		if (nsdb_update_follow_referrals(nsdbname, nsdbport,
-						follow) != FEDFS_OK) {
-			rc = EXIT_FAILURE;
+							follow) != FEDFS_OK)
 			goto out;
-		}
 	}
 
+	printf("NSDB connection parameters updated successfully.\n");
+	rc = EXIT_SUCCESS;
 out:
+	free(data);
 	return rc;
 }