@@ -29,6 +29,8 @@ fedfs-get-nsdb-params \- send a FEDFS_GET_NSDB_PARAMS ADMIN protocol request
.SH SYNOPSIS
.B fedfs-get-nsdb-params
.RB [ \-?d ]
+.RB [ \-f
+.IR certfile ]
.RB [ \-n
.IR nettype ]
.RB [ \-h
@@ -80,6 +82,12 @@ Displays
.BR fedfs-get-nsdb-params (8)
version information and a usage message on
.IR stderr .
+.IP "\fB-f, \-\-certfile=\fIpathname\fP"
+Specifies the pathname of a local file to write received certificate
+material into, when the specified NSDB's connection security type is
+.BR TLS .
+If no file is specified, the certificate is ignored.
+The certificate is written to the specified file in PEM format.
.IP "\fB\-h, \-\-hostname=\fIhostname\fP"
Specifies the hostname of a remote FedFS ADMIN service.
If this option is not specified, the default value is
@@ -86,8 +86,11 @@ Displays
version information and a usage message on
.IR stderr .
.IP "\fB-f, \-\-certfile=\fIpathname\fP"
-Specifies the pathname of a local file containing the X.509 certificate
-to use for establishing a TLS connection with the specified NSDB.
+Specifies the pathname of a local file containing an x.509 certificate
+the remote system can use to authenticate the specified NSDB node.
+The specified file may be deleted after the command succeeds.
+Details on the contents of this file can be found in
+.BR nsdb-parameters (7).
.IP "\fB\-h, \-\-hostname=\fIhostname\fP"
Specifies the hostname of a remote FedFS ADMIN service.
If this option is not specified, the default value is
@@ -52,12 +52,13 @@ static struct timeval fedfs_get_nsdb_params_timeout = { 25, 0 };
/**
* Short form command line options
*/
-static const char fedfs_get_nsdb_params_opts[] = "?dh:l:n:r:";
+static const char fedfs_get_nsdb_params_opts[] = "?df:h:l:n:r:";
/**
* Long form command line options
*/
static const struct option fedfs_get_nsdb_params_longopts[] = {
+ { "certfile", 1, NULL, 'f', },
{ "debug", 0, NULL, 'd', },
{ "help", 0, NULL, '?', },
{ "hostname", 1, NULL, 'h', },
@@ -72,10 +73,12 @@ fedfs_get_nsdb_params_usage(const char *progname)
{
fprintf(stderr, "\n%s version " VERSION "\n", progname);
fprintf(stderr, "Usage: %s [-d] [-n nettype] [-h hostname] "
- "[-l nsdbname] [-r nsdbport]\n\n", progname);
+ "[-f certfile] [-l nsdbname] [-r nsdbport]\n\n",
+ progname);
fprintf(stderr, "\t-?, --help Print this help\n");
fprintf(stderr, "\t-d, --debug Enable debug messages\n");
+ fprintf(stderr, "\t-f, --certfile Where to write certificate\n");
fprintf(stderr, "\t-n, --nettype RPC transport (default: 'netpath')\n");
fprintf(stderr, "\t-h, --hostname ADMIN server hostname (default: 'localhost')\n");
fprintf(stderr, "\t-l, --nsdbname NSDB hostname\n");
@@ -87,7 +90,8 @@ fedfs_get_nsdb_params_usage(const char *progname)
}
static void
-fedfs_get_nsdb_params_print_result(FedFsGetNsdbParamsRes result)
+fedfs_get_nsdb_params_print_result(FedFsGetNsdbParamsRes result,
+ const char *certfile)
{
FedFsNsdbParams *params = &result.FedFsGetNsdbParamsRes_u.params;
@@ -101,8 +105,10 @@ fedfs_get_nsdb_params_print_result(FedFsGetNsdbParamsRes result)
break;
case FEDFS_SEC_TLS:
printf("ConnectionSec: FEDFS_SEC_TLS\n");
- printf("X.509 cert:\n%s\n",
- params->FedFsNsdbParams_u.secData.secData_val);
+ if (certfile != NULL)
+ (void)nsdb_connsec_write_pem_file(certfile,
+ params->FedFsNsdbParams_u.secData.secData_val,
+ params->FedFsNsdbParams_u.secData.secData_len);
break;
default:
printf("Unrecognized FedFsConnectionSec value: %u\n",
@@ -112,7 +118,8 @@ fedfs_get_nsdb_params_print_result(FedFsGetNsdbParamsRes result)
static FedFsStatus
fedfs_get_nsdb_params_call(const char *hostname, const char *nettype,
- char *nsdbname, const unsigned short nsdbport)
+ char *nsdbname, const unsigned short nsdbport,
+ const char *certfile)
{
FedFsGetNsdbParamsRes result;
enum clnt_stat status;
@@ -141,7 +148,7 @@ fedfs_get_nsdb_params_call(const char *hostname, const char *nettype,
clnt_perror(client, "FEDFS_GET_NSDB_PARAMS call failed");
result.status = FEDFS_ERR_SVRFAULT;
} else {
- fedfs_get_nsdb_params_print_result(result);
+ fedfs_get_nsdb_params_print_result(result, certfile);
clnt_freeres(client,
(xdrproc_t)xdr_FedFsGetNsdbParamsRes,
(caddr_t)&result);
@@ -155,7 +162,7 @@ out:
int
main(int argc, char **argv)
{
- char *progname, *hostname, *nettype, *nsdbname;
+ char *progname, *hostname, *nettype, *nsdbname, *certfile;
unsigned short nsdbport;
unsigned int seconds;
FedFsStatus status;
@@ -179,11 +186,15 @@ main(int argc, char **argv)
hostname = "localhost";
nettype = "netpath";
+ certfile = NULL;
while ((arg = getopt_long(argc, argv, fedfs_get_nsdb_params_opts, fedfs_get_nsdb_params_longopts, NULL)) != -1) {
switch (arg) {
case 'd':
xlog_config(D_ALL, 1);
break;
+ case 'f':
+ certfile = optarg;
+ break;
case 'h':
hostname = optarg;
break;
@@ -220,9 +231,11 @@ main(int argc, char **argv)
fedfs_get_nsdb_params_usage(progname);
}
+ nsdb_connsec_crypto_startup();
+
for (seconds = FEDFS_DELAY_MIN_SECS;; seconds = fedfs_delay(seconds)) {
status = fedfs_get_nsdb_params_call(hostname, nettype,
- nsdbname, nsdbport);
+ nsdbname, nsdbport, certfile);
if (status != FEDFS_ERR_DELAY)
break;
@@ -230,5 +243,7 @@ main(int argc, char **argv)
if (sleep(seconds) != 0)
break;
}
+
+ nsdb_connsec_crypto_shutdown();
return (int)status;
}
@@ -77,7 +77,7 @@ fedfs_set_nsdb_params_usage(const char *progname)
progname);
fprintf(stderr, "\t-d, --debug Enable debug messages\n");
- fprintf(stderr, "\t-f, --certfile Name of file containing X.509 cert\n");
+ fprintf(stderr, "\t-f, --certfile Where to read certificate\n");
fprintf(stderr, "\t-?, --help Print this help\n");
fprintf(stderr, "\t-n, --nettype RPC transport (default: 'netpath')\n");
fprintf(stderr, "\t-h, --hostname ADMIN server hostname (default: 'localhost')\n");
@@ -92,50 +92,30 @@ fedfs_set_nsdb_params_usage(const char *progname)
static _Bool
fedfs_set_nsdb_params_get_params(const char *certfile, FedFsNsdbParams *params)
{
- struct stat stb;
- size_t size;
- ssize_t len;
+ FedFsStatus retval;
+ unsigned int len;
char *buf;
- int fd;
if (certfile == NULL) {
params->secType = FEDFS_SEC_NONE;
return true;
}
- if (lstat(certfile, &stb) == -1) {
- fprintf(stderr, "Failed to stat %s: %s\n",
- certfile, strerror(errno));
+ retval = nsdb_connsec_read_pem_file(certfile, &buf, &len);
+ switch (retval) {
+ case FEDFS_OK:
+ break;
+ case FEDFS_ERR_INVAL:
+ fprintf(stderr, "Invalid certificate material\n");
return false;
- }
- size = stb.st_size;
-
- fd = open(certfile, O_RDONLY);
- if (fd == -1) {
- fprintf(stderr, "Failed to open %s: %s\n",
- certfile, strerror(errno));
- return false;
- }
-
- buf = malloc(size);
- if (buf == NULL) {
- fprintf(stderr, "Failed to allocate buffer to read %s\n",
- certfile);
- (void)close(fd);
- return false;
- }
-
- len = read(fd, buf, size);
- if (len < 0 || (size_t)len > size) {
- fprintf(stderr, "Failed to read %s: %s\n",
- certfile, strerror(errno));
- free(buf);
- (void)close(fd);
+ default:
+ fprintf(stderr, "Failed to validate %s: %s\n",
+ certfile, nsdb_display_fedfsstatus(retval));
return false;
}
params->secType = FEDFS_SEC_TLS;
- params->FedFsNsdbParams_u.secData.secData_len = size;
+ params->FedFsNsdbParams_u.secData.secData_len = len;
params->FedFsNsdbParams_u.secData.secData_val = buf;
return true;
}
@@ -256,6 +236,8 @@ main(int argc, char **argv)
fedfs_set_nsdb_params_usage(progname);
}
+ nsdb_connsec_crypto_startup();
+
for (seconds = FEDFS_DELAY_MIN_SECS;; seconds = fedfs_delay(seconds)) {
status = fedfs_set_nsdb_params_call(hostname, nettype,
nsdbname, nsdbport, certfile);
@@ -266,5 +248,7 @@ main(int argc, char **argv)
if (sleep(seconds) != 0)
break;
}
+
+ nsdb_connsec_crypto_shutdown();
return (int)status;
}
@@ -232,10 +232,14 @@ int main(int argc, char **argv)
xlog(L_NOTICE, "Version " VERSION " (built %s at %s) starting",
__DATE__, __TIME__);
+ nsdb_connsec_crypto_startup();
+
/* Normally doesn't return */
fedfsd_svc_create("fedfs", FEDFS_PROG, FEDFS_V1,
fedfsd_dispatch_1, listen_port);
+ nsdb_connsec_crypto_shutdown();
+
xlog(L_WARNING, "Exiting unexpectedly");
exit(EXIT_FAILURE);
}
@@ -984,11 +984,11 @@ fedfsd_test_nsdb(const char *hostname, unsigned short port)
static void
fedfsd_svc_set_nsdb_params_1(SVCXPRT *xprt)
{
- struct fedfs_secdata secdata;
FedFsSetNsdbParamsArgs args;
char *hostname = NULL;
unsigned short port;
FedFsStatus result;
+ nsdb_t host;
memset(&args, 0, sizeof(args));
if (!svc_getargs(xprt, (xdrproc_t)xdr_FedFsSetNsdbParamsArgs, (caddr_t)&args)) {
@@ -1001,28 +1001,44 @@ fedfsd_svc_set_nsdb_params_1(SVCXPRT *xprt)
if (result != FEDFS_OK)
goto out;
- result = fedfsd_test_nsdb(hostname, port);
- if (result != FEDFS_OK)
+ result = nsdb_lookup_nsdb(hostname, port, &host);
+ switch (result) {
+ case FEDFS_OK:
+ nsdb_free_nsdb(host);
+ break;
+ case FEDFS_ERR_NSDB_PARAMS:
+ result = fedfsd_test_nsdb(hostname, port);
+ if (result != FEDFS_OK)
+ goto out;
+ result = nsdb_create_nsdb(hostname, port);
+ if (result != FEDFS_OK) {
+ xlog(L_ERROR, "Failed to create entry for %s:%u in "
+ "local NSDB connection parameter database: %s",
+ hostname, port,
+ nsdb_display_fedfsstatus(result));
+ goto out;
+ }
+ break;
+ default:
+ xlog(L_ERROR, "Failed to access local NSDB "
+ "connection parameter dataase: %s",
+ nsdb_display_fedfsstatus(result));
goto out;
+ }
switch (args.params.secType) {
case FEDFS_SEC_NONE:
- secdata.len = 0;
- secdata.data = "";
+ result = nsdb_connsec_set_none(hostname, port);
break;
case FEDFS_SEC_TLS:
- secdata.len =
- args.params.FedFsNsdbParams_u.secData.secData_len;
- secdata.data =
- args.params.FedFsNsdbParams_u.secData.secData_val;
+ result = nsdb_connsec_set_tls_buf(hostname, port,
+ args.params.FedFsNsdbParams_u.secData.secData_val,
+ args.params.FedFsNsdbParams_u.secData.secData_len);
break;
default:
- result = FEDFS_ERR_BADXDR;
+ result = FEDFS_ERR_INVAL;
goto out;
}
- secdata.type = args.params.secType;
-
- result = nsdb_update_nsdb(hostname, port, &secdata);
out:
xlog(D_CALL, "%s: Replying with %s",
The latest ADMIN protocol document requires the use of DER encoding when transferring certificates on the wire. Our LDAP library uses certificates stored in PEM-format files when performing a START_TLS operation. Transformation between these two formats is required: o rpc.fedfsd should validate that incoming certificates are DER encoded, and should transform them to PEM format when storing them for use by our LDAP client (FEDFS_SET_NSDB_PARAMS) o rpc.fedfsd should transform stored PEM format certificates to DER before returning them to clients (FEDFS_GET_NSDB_PARAMS) o The fedfs-set-nsdb-params tool should validate user-provided certificate material, and should transform it to DER encoding before sending it to fedfsd o The fedfs-get-nsdb-params tool should transform certificate material retrieved from fedfsd into a PEM format file instead of displaying the raw certificate data. DER-encoded data is gibberish to a human Signed-off-by: Chuck Lever <chuck.lever@oracle.com> --- doc/man/fedfs-get-nsdb-params.8 | 8 ++++++ doc/man/fedfs-set-nsdb-params.8 | 7 ++++- src/fedfsc/fedfs-get-nsdb-params.c | 33 +++++++++++++++++------- src/fedfsc/fedfs-set-nsdb-params.c | 50 ++++++++++++------------------------ src/fedfsd/main.c | 4 +++ src/fedfsd/svc.c | 42 +++++++++++++++++++++--------- 6 files changed, 87 insertions(+), 57 deletions(-)