On 06/25/2018 12:01 PM, Richard W.M. Jones wrote:
---
  docs/nbdkit.pod.in |  45 +++++++++--
  src/crypto.c       | 234 +++++++++++++++++++++++++++++++++++++----------------
  src/internal.h     |   1 +
  src/main.c         |   8 +-
  4 files changed, 210 insertions(+), 78 deletions(-)


+Create a PSK file containing one or more C<username:key> pairs.  It is
+easiest to use L<psktool(1)> for this:
+
+ psktool -u rich -p /tmp/psk
+
+The PSK file contains the hex-encoded random keys in plaintext.  Any
+client which can read this file will be able to connect to the server.

If I'm understanding correctly, it's also possible for a server to create a file that supports multiple users:

c1:1234
c2:2345

but then hand out a smaller file to client c1 that contains only the c2:1234 line, and another small file to client c2, and then a single server can not only accept multiple clients but also distinguish which client connected. Is there any reason for nbdkit as a server to additionally limit which resources are served depending on which client connected?

But that's probably overkill for now; as it's just as easy to point nbdkit to the smaller file in the first place, and since right now nbdkit serves up at most one file, provided the client can connect in the first place (it would matter more for something like nbd-server, which has an init file that specifies multiple resources served by a single server, and therefore might want per-user restrictions on those resources).

+++ b/src/crypto.c
@@ -37,10 +37,12 @@
  #include <stdlib.h>
  #include <stdarg.h>
  #include <stdint.h>
+#include <stdbool.h>
  #include <inttypes.h>
  #include <string.h>
  #include <unistd.h>
  #include <fcntl.h>
+#include <limits.h>
  #include <errno.h>
  #include <sys/types.h>
  #include <assert.h>
@@ -51,7 +53,12 @@
#include <gnutls/gnutls.h> +static int crypto_auth = 0;

Explicit assignment to 0 is not necessary for static variables (and in general, the assignment moves the variable from .bss into .data for a larger binary, although gcc has options for changing this).


+static int
+start_psk (void)
+{
+  int err;
+  CLEANUP_FREE char *abs_psk_file = NULL;
+
+  /* Make sure the path to the PSK file is absolute. */
+  abs_psk_file = realpath (tls_psk, NULL);
+  if (abs_psk_file == NULL) {
+    perror (tls_psk);
+    exit (EXIT_FAILURE);
+  }
+
+  err = gnutls_psk_allocate_server_credentials (&psk_creds);
+  if (err < 0) {
+    print_gnutls_error (err, "allocating PSK credentials");
+    exit (EXIT_FAILURE);

Do you care about lint-like efforts to free abs_psk_file before exit? (I don't)

+  }
+
+  /* Note that this function makes a copy of the string so it
+   * is safe to free it afterwards.
+   */
+  gnutls_psk_set_server_credentials_file (psk_creds, abs_psk_file);
+
+  return 0;

Based on the comment, isn't this a leak of abs_psk_file?

+}
+
+/* Initialize crypto.  This also handles the command line parameters
+ * and loading the server certificate.
+ */
+void
+crypto_init (int tls_set_on_cli)
+{
+  int err, r;
+  const char *what;
+
+  err = gnutls_global_init ();
+  if (err < 0) {
+    print_gnutls_error (err, "initializing GnuTLS");
+    exit (EXIT_FAILURE);
+  }
+
+  if (tls == 0)                 /* --tls=off */
+    return;
+
+  /* --tls-psk overrides certificates. */
+  if (tls_psk != NULL) {
+    r = start_psk ();
+    what = "Pre-Shared Keys (PSK)";
+    if (r == 0) crypto_auth = CRYPTO_AUTH_PSK;

Isn't it more typical to put the 'if' and statement on separate lines?

+  }
+  else {
+    r = start_certificates ();
+    what = "X.509 certificates";
+    if (r == 0) crypto_auth = CRYPTO_AUTH_CERTIFICATES;

but at least you're doing the one-liner layout consistently.

+++ b/src/main.c
@@ -144,6 +145,7 @@ static const struct option long_options[] = {
    { "threads",    1, NULL, 't' },
    { "tls",        1, NULL, 0 },
    { "tls-certificates", 1, NULL, 0 },
+  { "tls-psk",    1, NULL, 0 },

Pre-existing (so separate cleanup if desired), but we should probably use the symbolic names 'no_argument', 'required_argument', 'optional_argument' instead of 0, 1, 2.

    { "tls-verify-peer", 0, NULL, 0 },
    { "unix",       1, NULL, 'U' },
    { "user",       1, NULL, 'u' },
@@ -161,7 +163,7 @@ usage (void)
            "       [--newstyle] [--oldstyle] [-P PIDFILE] [-p PORT] [-r]\n"
            "       [--run CMD] [-s] [--selinux-label LABEL] [-t THREADS]\n"
            "       [--tls=off|on|require] [--tls-certificates 
/path/to/certificates]\n"
-          "       [--tls-verify-peer]\n"
+          "       [--tls-psk /path/to/pskfile] [--tls-verify-peer]\n"
            "       [-U SOCKET] [-u USER] [-v] [-V]\n"
            "       PLUGIN [key=value [key=value [...]]]\n"
            "\n"
@@ -314,6 +316,10 @@ main (int argc, char *argv[])
          tls_certificates_dir = optarg;
          break;
        }
+      else if (strcmp (long_options[option_index].name, "tls-psk") == 0) {

Pre-existing, but if you assign values larger than 256 to the 'val' member in long_options above, then you can directly switch() to these cases rather than having an ever-growing 'if' branching chain for long-only options. (Hmm, since I'm pointing out pre-existing getopt_long() usage idioms, I should probably post that cleanup patch).

Overall it looks good. The best part is that you've done interoperability testing with your pending qemu patch (I have not yet tried to repeat the interoperability testing at this point, though).

--
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org

_______________________________________________
Libguestfs mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/libguestfs

Reply via email to