0e1d02452b
In qcrypto_tls_creds_get_path() coverity complains that we are checking '*creds' for NULL, despite having dereferenced it previously. This is harmless bug due to fact that the trace call was too early. Moving it after the cleanup gets the desired semantics. In qcrypto_tls_creds_check_cert_key_purpose() coverity complains that we're passing a pointer to a previously free'd buffer into gnutls_x509_crt_get_key_purpose_oid() This is harmless because we're passing a size == 0, so gnutls won't access the buffer, but rather just report what size it needs to be. We can avoid it though by explicitly setting the buffer to NULL after free'ing it. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
252 lines
6.8 KiB
C
252 lines
6.8 KiB
C
/*
|
|
* QEMU crypto TLS credential support
|
|
*
|
|
* Copyright (c) 2015 Red Hat, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
#include "crypto/tlscredspriv.h"
|
|
#include "trace.h"
|
|
|
|
#define DH_BITS 2048
|
|
|
|
#ifdef CONFIG_GNUTLS
|
|
int
|
|
qcrypto_tls_creds_get_dh_params_file(QCryptoTLSCreds *creds,
|
|
const char *filename,
|
|
gnutls_dh_params_t *dh_params,
|
|
Error **errp)
|
|
{
|
|
int ret;
|
|
|
|
trace_qcrypto_tls_creds_load_dh(creds, filename ? filename : "<generated>");
|
|
|
|
if (filename == NULL) {
|
|
ret = gnutls_dh_params_init(dh_params);
|
|
if (ret < 0) {
|
|
error_setg(errp, "Unable to initialize DH parameters: %s",
|
|
gnutls_strerror(ret));
|
|
return -1;
|
|
}
|
|
ret = gnutls_dh_params_generate2(*dh_params, DH_BITS);
|
|
if (ret < 0) {
|
|
gnutls_dh_params_deinit(*dh_params);
|
|
*dh_params = NULL;
|
|
error_setg(errp, "Unable to generate DH parameters: %s",
|
|
gnutls_strerror(ret));
|
|
return -1;
|
|
}
|
|
} else {
|
|
GError *gerr = NULL;
|
|
gchar *contents;
|
|
gsize len;
|
|
gnutls_datum_t data;
|
|
if (!g_file_get_contents(filename,
|
|
&contents,
|
|
&len,
|
|
&gerr)) {
|
|
|
|
error_setg(errp, "%s", gerr->message);
|
|
g_error_free(gerr);
|
|
return -1;
|
|
}
|
|
data.data = (unsigned char *)contents;
|
|
data.size = len;
|
|
ret = gnutls_dh_params_init(dh_params);
|
|
if (ret < 0) {
|
|
g_free(contents);
|
|
error_setg(errp, "Unable to initialize DH parameters: %s",
|
|
gnutls_strerror(ret));
|
|
return -1;
|
|
}
|
|
ret = gnutls_dh_params_import_pkcs3(*dh_params,
|
|
&data,
|
|
GNUTLS_X509_FMT_PEM);
|
|
g_free(contents);
|
|
if (ret < 0) {
|
|
gnutls_dh_params_deinit(*dh_params);
|
|
*dh_params = NULL;
|
|
error_setg(errp, "Unable to load DH parameters from %s: %s",
|
|
filename, gnutls_strerror(ret));
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int
|
|
qcrypto_tls_creds_get_path(QCryptoTLSCreds *creds,
|
|
const char *filename,
|
|
bool required,
|
|
char **cred,
|
|
Error **errp)
|
|
{
|
|
struct stat sb;
|
|
int ret = -1;
|
|
|
|
if (!creds->dir) {
|
|
if (required) {
|
|
error_setg(errp, "Missing 'dir' property value");
|
|
return -1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
*cred = g_strdup_printf("%s/%s", creds->dir, filename);
|
|
|
|
if (stat(*cred, &sb) < 0) {
|
|
if (errno == ENOENT && !required) {
|
|
ret = 0;
|
|
} else {
|
|
error_setg_errno(errp, errno,
|
|
"Unable to access credentials %s",
|
|
*cred);
|
|
}
|
|
g_free(*cred);
|
|
*cred = NULL;
|
|
goto cleanup;
|
|
}
|
|
|
|
ret = 0;
|
|
cleanup:
|
|
trace_qcrypto_tls_creds_get_path(creds, filename,
|
|
*cred ? *cred : "<none>");
|
|
return ret;
|
|
}
|
|
|
|
|
|
#endif /* ! CONFIG_GNUTLS */
|
|
|
|
|
|
static void
|
|
qcrypto_tls_creds_prop_set_verify(Object *obj,
|
|
bool value,
|
|
Error **errp G_GNUC_UNUSED)
|
|
{
|
|
QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
|
|
|
|
creds->verifyPeer = value;
|
|
}
|
|
|
|
|
|
static bool
|
|
qcrypto_tls_creds_prop_get_verify(Object *obj,
|
|
Error **errp G_GNUC_UNUSED)
|
|
{
|
|
QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
|
|
|
|
return creds->verifyPeer;
|
|
}
|
|
|
|
|
|
static void
|
|
qcrypto_tls_creds_prop_set_dir(Object *obj,
|
|
const char *value,
|
|
Error **errp G_GNUC_UNUSED)
|
|
{
|
|
QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
|
|
|
|
creds->dir = g_strdup(value);
|
|
}
|
|
|
|
|
|
static char *
|
|
qcrypto_tls_creds_prop_get_dir(Object *obj,
|
|
Error **errp G_GNUC_UNUSED)
|
|
{
|
|
QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
|
|
|
|
return g_strdup(creds->dir);
|
|
}
|
|
|
|
|
|
static void
|
|
qcrypto_tls_creds_prop_set_endpoint(Object *obj,
|
|
int value,
|
|
Error **errp G_GNUC_UNUSED)
|
|
{
|
|
QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
|
|
|
|
creds->endpoint = value;
|
|
}
|
|
|
|
|
|
static int
|
|
qcrypto_tls_creds_prop_get_endpoint(Object *obj,
|
|
Error **errp G_GNUC_UNUSED)
|
|
{
|
|
QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
|
|
|
|
return creds->endpoint;
|
|
}
|
|
|
|
|
|
static void
|
|
qcrypto_tls_creds_init(Object *obj)
|
|
{
|
|
QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
|
|
|
|
creds->verifyPeer = true;
|
|
|
|
object_property_add_bool(obj, "verify-peer",
|
|
qcrypto_tls_creds_prop_get_verify,
|
|
qcrypto_tls_creds_prop_set_verify,
|
|
NULL);
|
|
object_property_add_str(obj, "dir",
|
|
qcrypto_tls_creds_prop_get_dir,
|
|
qcrypto_tls_creds_prop_set_dir,
|
|
NULL);
|
|
object_property_add_enum(obj, "endpoint",
|
|
"QCryptoTLSCredsEndpoint",
|
|
QCryptoTLSCredsEndpoint_lookup,
|
|
qcrypto_tls_creds_prop_get_endpoint,
|
|
qcrypto_tls_creds_prop_set_endpoint,
|
|
NULL);
|
|
}
|
|
|
|
|
|
static void
|
|
qcrypto_tls_creds_finalize(Object *obj)
|
|
{
|
|
QCryptoTLSCreds *creds = QCRYPTO_TLS_CREDS(obj);
|
|
|
|
g_free(creds->dir);
|
|
}
|
|
|
|
|
|
static const TypeInfo qcrypto_tls_creds_info = {
|
|
.parent = TYPE_OBJECT,
|
|
.name = TYPE_QCRYPTO_TLS_CREDS,
|
|
.instance_size = sizeof(QCryptoTLSCreds),
|
|
.instance_init = qcrypto_tls_creds_init,
|
|
.instance_finalize = qcrypto_tls_creds_finalize,
|
|
.class_size = sizeof(QCryptoTLSCredsClass),
|
|
.abstract = true,
|
|
};
|
|
|
|
|
|
static void
|
|
qcrypto_tls_creds_register_types(void)
|
|
{
|
|
type_register_static(&qcrypto_tls_creds_info);
|
|
}
|
|
|
|
|
|
type_init(qcrypto_tls_creds_register_types);
|