Skip to content

Commit

Permalink
Feature: libcib: Support TLS cert authentication for remote CIB opera…
Browse files Browse the repository at this point in the history
…tions.

Ref T365
  • Loading branch information
clumens committed Nov 26, 2024
1 parent 6d7b1d4 commit 81f5c53
Showing 1 changed file with 56 additions and 6 deletions.
62 changes: 56 additions & 6 deletions lib/cib/cib_remote.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@
#include <crm/common/output_internal.h>

#include <gnutls/gnutls.h>
#include <gnutls/x509.h>

// GnuTLS handshake timeout in seconds
#define TLS_HANDSHAKE_TIMEOUT 5

static gnutls_anon_client_credentials_t anon_cred_c;
static gnutls_certificate_credentials_t cert_cred_c;
static gboolean remote_gnutls_credentials_init = FALSE;

#include <arpa/inet.h>
Expand Down Expand Up @@ -321,7 +323,14 @@ cib_tls_close(cib_t *cib)
private->command.tls_session = NULL;
private->callback.tls_session = NULL;
if (remote_gnutls_credentials_init) {
gnutls_anon_free_client_credentials(anon_cred_c);
if (anon_cred_c != NULL) {
gnutls_anon_free_client_credentials(anon_cred_c);
}

if (cert_cred_c != NULL) {
gnutls_certificate_free_credentials(cert_cred_c);
}

gnutls_global_deinit();
remote_gnutls_credentials_init = FALSE;
}
Expand Down Expand Up @@ -357,6 +366,8 @@ static int
cib_tls_signon(cib_t *cib, pcmk__remote_t *connection, gboolean event_channel)
{
cib_remote_opaque_t *private = cib->variant_opaque;
gnutls_credentials_type_t cred_type;
void *credentials = NULL;
int rc;

xmlNode *answer = NULL;
Expand All @@ -381,18 +392,57 @@ cib_tls_signon(cib_t *cib, pcmk__remote_t *connection, gboolean event_channel)
if (private->encrypted) {
int tls_rc = GNUTLS_E_SUCCESS;

/* initialize GnuTls lib */
if (remote_gnutls_credentials_init == FALSE) {
if (!remote_gnutls_credentials_init) {
crm_gnutls_global_init();
gnutls_anon_allocate_client_credentials(&anon_cred_c);
remote_gnutls_credentials_init = TRUE;
}

if (pcmk__x509_enabled()) {
const char *ca_file = pcmk__env_option(PCMK__ENV_CA_FILE);
const char *cert_file = pcmk__env_option(PCMK__ENV_CERT_FILE);
const char *key_file = pcmk__env_option(PCMK__ENV_KEY_FILE);

gnutls_certificate_allocate_credentials(&cert_cred_c);

/* Load a trusted CA to be used to verify client certificates. Use
* of this function instead of gnutls_certificate_set_x509_system_trust
* means we do not look at the system-wide authorities installed in
* /etc/pki somewhere. This requires the cluster admin to set up their
* own CA.
*/
rc = gnutls_certificate_set_x509_trust_file(cert_cred_c, ca_file,
GNUTLS_X509_FMT_PEM);
if (rc <= 0) {
crm_err("Failed to set X509 CA file: %s", gnutls_strerror(rc));
return -1;
}

/* NULL = no password for the key, GNUTLS_PKCS_PLAIN = unencrypted key
* file
*/
rc = gnutls_certificate_set_x509_key_file2(cert_cred_c, cert_file,
key_file, GNUTLS_X509_FMT_PEM,
NULL, GNUTLS_PKCS_PLAIN);
if (rc < 0) {
crm_err("Failed to set X509 cert/key pair: %s",
gnutls_strerror(rc));
return -1;
}

cred_type = GNUTLS_CRD_CERTIFICATE;
credentials = cert_cred_c;

} else {
gnutls_anon_allocate_client_credentials(&anon_cred_c);
cred_type = GNUTLS_CRD_ANON;
credentials = anon_cred_c;
}

/* bind the socket to GnuTls lib */
connection->tls_session = pcmk__new_tls_session(connection->tcp_socket,
GNUTLS_CLIENT,
GNUTLS_CRD_ANON,
anon_cred_c);
cred_type,
credentials);
if (connection->tls_session == NULL) {
cib_tls_close(cib);
return -1;
Expand Down

0 comments on commit 81f5c53

Please sign in to comment.