#include <config.h>
#include "virnettlsconfig.h"
+#include "viralloc.h"
#include "virlog.h"
#include "virutil.h"
+#include "virfile.h"
+#include "virerror.h"
#define VIR_FROM_THIS VIR_FROM_RPC
-VIR_LOG_INIT("rpc.nettlscontext");
+VIR_LOG_INIT("rpc.nettlsconfig");
char *virNetTLSConfigUserPKIBaseDir(void)
{
key);
}
-void virNetTLSConfigCustomCreds(const char *pkipath,
- bool isServer,
- char **cacert,
- char **cacrl,
- char **cert,
- char **key)
+
+int virNetTLSConfigCheckTrust(const char *cacert, const char *cacrl,
+ bool *cacertExists, bool *cacrlExists,
+ bool allowMissingCA)
+{
+ if (cacertExists)
+ *cacertExists = true;
+ if (cacrlExists)
+ *cacrlExists = true;
+ VIR_DEBUG("Checking CA certificate '%s' and CRL '%s'", cacert, NULLSTR(cacrl));
+ if (!virFileExists(cacert)) {
+ if (allowMissingCA) {
+ VIR_DEBUG("CA certificate '%s' does not exist", cacert);
+ if (cacertExists)
+ *cacertExists = false;
+ } else {
+ virReportSystemError(errno, _("CA certificate '%1$s' does not exist"),
+ cacert);
+ return -1;
+ }
+ }
+ if (cacrl != NULL && !virFileExists(cacrl)) {
+ VIR_DEBUG("CA CRL '%s' does not exist", cacrl);
+ if (cacrlExists)
+ *cacrlExists = false;
+ }
+ return 0;
+}
+
+static int virNetTLSConfigEnsureTrust(char **cacert, char **cacrl,
+ bool allowMissingCA)
+{
+ bool cacertExists, cacrlExists;
+
+ if (virNetTLSConfigCheckTrust(*cacert, *cacrl,
+ &cacertExists, &cacrlExists,
+ allowMissingCA) < 0)
+ return -1;
+
+ if (!cacertExists)
+ VIR_FREE(*cacert);
+ if (!cacrlExists)
+ VIR_FREE(*cacrl);
+
+ return 0;
+}
+
+int virNetTLSConfigCheckIdentity(const char *cert, const char *key,
+ bool *identityExists, bool allowMissing)
+{
+ if (identityExists)
+ *identityExists = true;
+ VIR_DEBUG("Checking certificate '%s' and key '%s'", cert, key);
+ if (!virFileExists(cert)) {
+ int saved_errno = errno;
+ if (allowMissing) {
+ if (virFileExists(key)) {
+ virReportSystemError(
+ saved_errno,
+ _("Certificate '%1$s' does not exist, but key '%2$s' does"),
+ cert, key);
+ return -1;
+ }
+ if (identityExists)
+ *identityExists = false;
+ VIR_DEBUG("Missing cert '%s' / key '%s'", cert, key);
+ return 0;
+ } else {
+ virReportSystemError(saved_errno, _("Certificate '%1$s' does not exist"),
+ cert);
+ return -1;
+ }
+ } else {
+ if (!virFileExists(key)) {
+ virReportSystemError(errno,
+ _("Key '%1$s' does not exist, but certificate '%2$s' does"),
+ key, cert);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
+static int virNetTLSConfigEnsureIdentity(char **cert, char **key,
+ bool allowMissing)
+{
+ bool identityExists;
+
+ if (virNetTLSConfigCheckIdentity(*cert, *key, &identityExists,
+ allowMissing) < 0)
+ return -1;
+
+ if (!identityExists) {
+ VIR_FREE(*cert);
+ VIR_FREE(*key);
+ }
+
+ return 0;
+}
+
+
+int virNetTLSConfigCustomCreds(const char *pkipath,
+ bool isServer,
+ char **cacert,
+ char **cacrl,
+ char **cert,
+ char **key)
{
VIR_DEBUG("Locating creds in custom dir %s", pkipath);
virNetTLSConfigTrust(pkipath,
pkipath,
cacert,
cacrl);
+
+ if (virNetTLSConfigEnsureTrust(cacert, cacrl, false) < 0)
+ return -1;
+
virNetTLSConfigIdentity(isServer,
pkipath,
pkipath,
cert,
key);
+
+
+ if (virNetTLSConfigEnsureIdentity(cert, key, !isServer) < 0)
+ return -1;
+
+ return 0;
}
-void virNetTLSConfigUserCreds(bool isServer,
- char **cacert,
- char **cacrl,
- char **cert,
- char **key)
+int virNetTLSConfigUserCreds(bool isServer,
+ char **cacert,
+ char **cacrl,
+ char **cert,
+ char **key)
{
g_autofree char *pkipath = virNetTLSConfigUserPKIBaseDir();
pkipath,
cacert,
cacrl);
+
+ if (virNetTLSConfigEnsureTrust(cacert, cacrl, true) < 0)
+ return -1;
+
virNetTLSConfigIdentity(isServer,
pkipath,
pkipath,
cert,
key);
+
+ if (virNetTLSConfigEnsureIdentity(cert, key, true) < 0)
+ return -1;
+
+ return 0;
}
-void virNetTLSConfigSystemCreds(bool isServer,
- char **cacert,
- char **cacrl,
- char **cert,
- char **key)
+int virNetTLSConfigSystemCreds(bool isServer,
+ char **cacert,
+ char **cacrl,
+ char **cert,
+ char **key)
{
VIR_DEBUG("Locating creds in system dir %s", LIBVIRT_PKI_DIR);
LIBVIRT_CACRL_DIR,
cacert,
cacrl);
+
+ if (virNetTLSConfigEnsureTrust(cacert, cacrl, false) < 0)
+ return -1;
+
virNetTLSConfigIdentity(isServer,
LIBVIRT_CERT_DIR,
LIBVIRT_KEY_DIR,
cert,
key);
+
+ if (virNetTLSConfigEnsureIdentity(cert, key, !isServer) < 0)
+ return -1;
+
+ return 0;
}
#include "virnettlscert.h"
#include "virstring.h"
-#include "viralloc.h"
#include "virerror.h"
#include "virfile.h"
#include "virutil.h"
VIR_ONCE_GLOBAL_INIT(virNetTLSContext);
-static int
-virNetTLSContextCheckCertFile(const char *type, const char *file, bool allowMissing)
-{
- if (!virFileExists(file)) {
- if (allowMissing)
- return 1;
-
- virReportSystemError(errno,
- _("Cannot read %1$s '%2$s'"),
- type, file);
- return -1;
- }
- return 0;
-}
-
-
static void virNetTLSLog(int level G_GNUC_UNUSED,
const char *str G_GNUC_UNUSED)
{
static int virNetTLSContextLoadCredentials(virNetTLSContext *ctxt,
- bool isServer,
const char *cacert,
const char *cacrl,
const char *const *certs,
int err;
size_t i;
- if (cacert && cacert[0] != '\0') {
- if (virNetTLSContextCheckCertFile("CA certificate", cacert, false) < 0)
- return -1;
+ VIR_DEBUG("loading CA cert from %s", cacert);
+ err = gnutls_certificate_set_x509_trust_file(ctxt->x509cred,
+ cacert,
+ GNUTLS_X509_FMT_PEM);
+ if (err < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("Unable to set x509 CA certificate: %1$s: %2$s"),
+ cacert, gnutls_strerror(err));
+ return -1;
+ }
- VIR_DEBUG("loading CA cert from %s", cacert);
- err = gnutls_certificate_set_x509_trust_file(ctxt->x509cred,
- cacert,
- GNUTLS_X509_FMT_PEM);
+ if (cacrl) {
+ VIR_DEBUG("loading CRL from %s", cacrl);
+ err = gnutls_certificate_set_x509_crl_file(ctxt->x509cred,
+ cacrl,
+ GNUTLS_X509_FMT_PEM);
if (err < 0) {
virReportError(VIR_ERR_SYSTEM_ERROR,
- _("Unable to set x509 CA certificate: %1$s: %2$s"),
- cacert, gnutls_strerror(err));
- return -1;
- }
- }
-
- if (cacrl && cacrl[0] != '\0') {
- int rv;
- if ((rv = virNetTLSContextCheckCertFile("CA revocation list", cacrl, true)) < 0)
+ _("Unable to set x509 certificate revocation list: %1$s: %2$s"),
+ cacrl, gnutls_strerror(err));
return -1;
-
- if (rv == 0) {
- VIR_DEBUG("loading CRL from %s", cacrl);
- err = gnutls_certificate_set_x509_crl_file(ctxt->x509cred,
- cacrl,
- GNUTLS_X509_FMT_PEM);
- if (err < 0) {
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("Unable to set x509 certificate revocation list: %1$s: %2$s"),
- cacrl, gnutls_strerror(err));
- return -1;
- }
- } else {
- VIR_DEBUG("Skipping non-existent CA CRL %s", cacrl);
}
+ } else {
+ VIR_DEBUG("no CRL file to load");
}
for (i = 0; certs[i] != NULL && keys[i] != NULL; i++) {
- int rv;
- if ((rv = virNetTLSContextCheckCertFile("certificate", certs[i], !isServer)) < 0)
- return -1;
- if (rv == 0 &&
- (rv = virNetTLSContextCheckCertFile("private key", keys[i], !isServer)) < 0)
+ VIR_DEBUG("loading cert and key from %s and %s", certs[i], keys[i]);
+ err = gnutls_certificate_set_x509_key_file(ctxt->x509cred,
+ certs[i], keys[i],
+ GNUTLS_X509_FMT_PEM);
+ if (err < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("Unable to set x509 key and certificate: %1$s, %2$s: %3$s"),
+ keys[i], certs[i], gnutls_strerror(err));
return -1;
-
- if (rv == 0) {
- VIR_DEBUG("loading cert and key from %s and %s", certs[i], keys[i]);
- err =
- gnutls_certificate_set_x509_key_file(ctxt->x509cred,
- certs[i], keys[i],
- GNUTLS_X509_FMT_PEM);
- if (err < 0) {
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("Unable to set x509 key and certificate: %1$s, %2$s: %3$s"),
- keys[i], certs[i], gnutls_strerror(err));
- return -1;
- }
- } else {
- VIR_DEBUG("Skipping non-existent cert %s key %s on client",
- certs[i], keys[i]);
}
}
{
virNetTLSContext *ctxt;
int err;
+ g_autofree char *certlist = certs ? g_strjoinv(", ", (char **)certs) : NULL;
+ g_autofree char *keylist = keys ? g_strjoinv(", ", (char **)keys) : NULL;
+ g_autofree char *acllist = x509dnACL ? g_strjoinv(", ", (char **)x509dnACL) : NULL;
+
+ VIR_DEBUG("CA cert=%s CRL=%s certs='%s' keys='%s' ACL='%s' "
+ "priority=%s sanity-check=%d require-valid=%d is-server=%d",
+ cacert, NULLSTR(cacrl), NULLSTR(certlist), NULLSTR(keylist),
+ NULLSTR(acllist), priority, sanityCheckCert, requireValidCert,
+ isServer);
if (virNetTLSContextInitialize() < 0)
return NULL;
virNetTLSCertSanityCheck(isServer, cacert, certs) < 0)
goto error;
- if (virNetTLSContextLoadCredentials(ctxt, isServer, cacert, cacrl,
+ if (virNetTLSContextLoadCredentials(ctxt, cacert, cacrl,
certs, keys) < 0)
goto error;
* files actually exist there
*/
if (pkipath) {
- virNetTLSConfigCustomCreds(pkipath, isServer,
- cacert, cacrl,
- cert, key);
+ if (virNetTLSConfigCustomCreds(pkipath, isServer,
+ cacert, cacrl,
+ cert, key) < 0)
+ return -1;
} else {
- if (tryUserPkiPath) {
+ if (tryUserPkiPath &&
virNetTLSConfigUserCreds(isServer,
cacert, cacrl,
- cert, key);
-
- /*
- * If some of the files can't be found, fallback
- * to the global location for them
- */
- if (!virFileExists(*cacert))
- VIR_FREE(*cacert);
- if (!virFileExists(*cacrl))
- VIR_FREE(*cacrl);
-
- /* Check these as a pair, since it they are
- * mutually dependent
- */
- if (!virFileExists(*key) || !virFileExists(*cert)) {
- VIR_FREE(*key);
- VIR_FREE(*cert);
- }
- }
+ cert, key) < 0)
+ return -1;
- virNetTLSConfigSystemCreds(isServer,
- cacert, cacrl,
- cert, key);
+ if (virNetTLSConfigSystemCreds(isServer,
+ cacert, cacrl,
+ cert, key) < 0)
+ return -1;
}
-
return 0;
}
bool sanityCheckCert,
bool requireValidCert)
{
+ size_t i;
+ if (virNetTLSConfigCheckTrust(cacert, cacrl, NULL, NULL, false) < 0)
+ return NULL;
+ for (i = 0; certs[i] != NULL && keys[i] != NULL; i++) {
+ if (virNetTLSConfigCheckIdentity(certs[i], keys[i], NULL, false) < 0)
+ return NULL;
+ }
return virNetTLSContextNew(cacert, cacrl, certs, keys, x509dnACL, priority,
sanityCheckCert, requireValidCert, true);
}
if (virNetTLSCertSanityCheck(true, cacert, certs))
goto error;
- if (virNetTLSContextLoadCredentials(ctxt, true, cacert, cacrl,
+ if (virNetTLSContextLoadCredentials(ctxt, cacert, cacrl,
certs, keys))
goto error;
bool sanityCheckCert,
bool requireValidCert)
{
+ size_t i;
+ if (virNetTLSConfigCheckTrust(cacert, cacrl, NULL, NULL, false) < 0)
+ return NULL;
+ for (i = 0; certs[i] != NULL && keys[i] != NULL; i++) {
+ if (virNetTLSConfigCheckIdentity(certs[i], keys[i], NULL, false) < 0)
+ return NULL;
+ }
return virNetTLSContextNew(cacert, cacrl, certs, keys, NULL, priority,
sanityCheckCert, requireValidCert, false);
}