[Libvir] PATCH: More useful error messages with missing certs

Daniel P. Berrange berrange at redhat.com
Wed Jul 11 19:51:26 UTC 2007


On the server end if you try to start the server with TLS enabled and you
don't have the certs setup, you get a cryptic:

gnutls_certificate_set_x509_trust_file: Error while reading file.

Rather useless the gnutls error message not telling you what file was
missing.

Similarly with virsh:

 # ~/usr/bin/virsh  --connect  qemu://localhost/system list
 libvir: Remote error : Error while reading file.

Since GNU TLS doesn't even tell you the actual problem - was it wrong
permissions, or missing file altogether, I decided its better to do an
explicit 'stat' check ahead of time.

So now it gives:

$ ~/usr/bin/virsh  --connect  qemu://celery.virt.boston.redhat.com/system start demo
libvir: Remote error : Cannot access CA certificate 
 '/home/berrange/usr/etc/pki/CA/cacert.pem': No such file or directory (2)

Or

$ ~/usr/bin/virsh  --connect  qemu://celery.virt.boston.redhat.com/system start demo
libvir: Remote error : Cannot access CA certificate 
 '/home/berrange/usr/etc/pki/CA/cacert.pem': Permission denied (13)

Or in the daemon

# /usr/sbin/libvirtd --listen
Cannot access CA certificate '/home/berrange/usr/etc/pki/CA/cacert.pem': No such file or directory (2)


Dan.
-- 
|=- Red Hat, Engineering, Emerging Technologies, Boston.  +1 978 392 2496 -=|
|=-           Perl modules: http://search.cpan.org/~danberr/              -=|
|=-               Projects: http://freshmeat.net/~danielpb/               -=|
|=-  GnuPG: 7D3B9505   F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505  -=| 
-------------- next part --------------
diff -u -p -r1.52 qemud.c
--- qemud/qemud.c	26 Jun 2007 23:48:47 -0000	1.52
+++ qemud/qemud.c	11 Jul 2007 19:32:30 -0000
@@ -116,6 +116,7 @@ static int
 remoteInitializeGnuTLS (void)
 {
     int err;
+    struct stat sb;
 
     /* Initialise GnuTLS. */
     gnutls_global_init ();
@@ -127,8 +128,16 @@ remoteInitializeGnuTLS (void)
         return -1;
     }
 
+#define CHECK_CERT(type, file) \
+    do { if (stat(file, &sb) < 0) {                                      \
+            qemudLog (QEMUD_ERR, "Cannot access " type " '%s': %s (%d)", \
+                         file, strerror(errno), errno); \
+            return -1;                                  \
+        } } while (0)
+
     if (ca_file && ca_file[0] != '\0') {
         qemudDebug ("loading CA cert from %s", ca_file);
+        CHECK_CERT("CA certificate", ca_file);
         err = gnutls_certificate_set_x509_trust_file (x509_cred, ca_file,
                                                       GNUTLS_X509_FMT_PEM);
         if (err < 0) {
@@ -140,6 +149,7 @@ remoteInitializeGnuTLS (void)
 
     if (crl_file && crl_file[0] != '\0') {
         qemudDebug ("loading CRL from %s", crl_file);
+        CHECK_CERT("CA revocation list", ca_file);
         err = gnutls_certificate_set_x509_crl_file (x509_cred, crl_file,
                                                     GNUTLS_X509_FMT_PEM);
         if (err < 0) {
@@ -150,6 +160,8 @@ remoteInitializeGnuTLS (void)
     }
 
     if (cert_file && cert_file[0] != '\0' && key_file && key_file[0] != '\0') {
+        CHECK_CERT("server certificate", cert_file);
+        CHECK_CERT("server key", key_file);
         qemudDebug ("loading cert and key from %s and %s",
                     cert_file, key_file);
         err =
@@ -163,6 +175,8 @@ remoteInitializeGnuTLS (void)
         }
     }
 
+#undef CHECK_CERT
+
     /* Generate Diffie Hellman parameters - for use with DHE
      * kx algorithms. These should be discarded and regenerated
      * once a day, once a week or once a month. Depending on the
diff -u -p -r1.14 remote_internal.c
--- src/remote_internal.c	6 Jul 2007 15:02:09 -0000	1.14
+++ src/remote_internal.c	11 Jul 2007 19:32:31 -0000
@@ -895,6 +895,7 @@ initialise_gnutls (virConnectPtr conn AT
 {
     static int initialised = 0;
     int err;
+    struct stat sb;
 
     if (initialised) return 0;
 
@@ -907,6 +908,22 @@ initialise_gnutls (virConnectPtr conn AT
         return -1;
     }
 
+
+#define CHECK_CERT(type, file) \
+    do { if (stat(file, &sb) < 0) {                                      \
+        __virRaiseError (NULL, NULL, NULL, VIR_FROM_REMOTE, VIR_ERR_RPC, \
+                         VIR_ERR_ERROR, LIBVIRT_CACERT, NULL, NULL, 0, 0, \
+                         "Cannot access " type " '%s': %s (%d)", \
+                         file, strerror(errno), errno); \
+        return -1; \
+    } } while (0)
+
+    CHECK_CERT("CA certificate", LIBVIRT_CACERT);
+    CHECK_CERT("client key", LIBVIRT_CLIENTKEY);
+    CHECK_CERT("client certificate", LIBVIRT_CLIENTCERT);
+
+#undef CHECK_CERT
+
     /* Set the trusted CA cert. */
 #if DEBUG
     fprintf (stderr, "loading CA file %s\n", LIBVIRT_CACERT);


More information about the libvir-list mailing list