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 <[email protected]>
---

 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(-)

diff --git a/doc/man/fedfs-get-nsdb-params.8 b/doc/man/fedfs-get-nsdb-params.8
index 2aac0b2..fb14df3 100644
--- a/doc/man/fedfs-get-nsdb-params.8
+++ b/doc/man/fedfs-get-nsdb-params.8
@@ -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
diff --git a/doc/man/fedfs-set-nsdb-params.8 b/doc/man/fedfs-set-nsdb-params.8
index 4321693..78bfdf1 100644
--- a/doc/man/fedfs-set-nsdb-params.8
+++ b/doc/man/fedfs-set-nsdb-params.8
@@ -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
diff --git a/src/fedfsc/fedfs-get-nsdb-params.c 
b/src/fedfsc/fedfs-get-nsdb-params.c
index 786804d..b8c7995 100644
--- a/src/fedfsc/fedfs-get-nsdb-params.c
+++ b/src/fedfsc/fedfs-get-nsdb-params.c
@@ -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;
 }
diff --git a/src/fedfsc/fedfs-set-nsdb-params.c 
b/src/fedfsc/fedfs-set-nsdb-params.c
index df53620..ca88ef1 100644
--- a/src/fedfsc/fedfs-set-nsdb-params.c
+++ b/src/fedfsc/fedfs-set-nsdb-params.c
@@ -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;
 }
diff --git a/src/fedfsd/main.c b/src/fedfsd/main.c
index 59cb12a..7e481f6 100644
--- a/src/fedfsd/main.c
+++ b/src/fedfsd/main.c
@@ -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);
 }
diff --git a/src/fedfsd/svc.c b/src/fedfsd/svc.c
index e3c9bc4..861e92f 100644
--- a/src/fedfsd/svc.c
+++ b/src/fedfsd/svc.c
@@ -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",


_______________________________________________
fedfs-utils-devel mailing list
[email protected]
https://oss.oracle.com/mailman/listinfo/fedfs-utils-devel

Reply via email to