13 #include <gnutls/gnutls.h> 14 #include <gnutls/x509.h> 20 get_gnutls_priorities(gnutls_credentials_type_t cred_type)
24 if (prio_base == NULL) {
28 if (cred_type == GNUTLS_CRD_ANON) {
30 }
else if (cred_type == GNUTLS_CRD_PSK) {
33 return strdup(prio_base);
38 tls_cred_str(gnutls_credentials_type_t cred_type)
40 if (cred_type == GNUTLS_CRD_ANON) {
41 return "unauthenticated";
42 }
else if (cred_type == GNUTLS_CRD_PSK) {
43 return "shared-key-authenticated";
44 }
else if (cred_type == GNUTLS_CRD_CERTIFICATE) {
45 return "certificate-authenticated";
68 crm_err(
"Failed to set X509 CA file: %s", gnutls_strerror(rc));
80 crm_err(
"Failed to set X509 CRL file: %s",
91 GNUTLS_X509_FMT_PEM, NULL,
94 crm_err(
"Failed to set X509 cert/key pair: %s",
110 verify_peer_cert(gnutls_session_t session)
118 rc = gnutls_certificate_verify_peers3(session, NULL, &status);
123 if (rc != GNUTLS_E_SUCCESS) {
124 crm_err(
"Failed to verify peer certificate: %s", gnutls_strerror(rc));
133 type = gnutls_certificate_type_get(session);
134 gnutls_certificate_verification_status_print(status,
type, &out, 0);
135 crm_err(
"Peer certificate invalid: %s", out.data);
136 gnutls_free(out.data);
137 return GNUTLS_E_CERTIFICATE_VERIFICATION_ERROR;
141 _gnutls_log_func(
int level,
const char *msg)
164 }
else if (tls->
cred_type == GNUTLS_CRD_CERTIFICATE) {
166 }
else if (tls->
cred_type == GNUTLS_CRD_PSK) {
177 gnutls_global_deinit();
191 signal(SIGPIPE, SIG_IGN);
200 gnutls_global_init();
201 gnutls_global_set_log_level(8);
202 gnutls_global_set_log_function(_gnutls_log_func);
214 (*tls)->server = server;
216 if (cred_type == GNUTLS_CRD_ANON) {
218 gnutls_anon_allocate_server_credentials(&(*tls)->credentials.anon_s);
219 gnutls_anon_set_server_dh_params((*tls)->credentials.anon_s,
222 gnutls_anon_allocate_client_credentials(&(*tls)->credentials.anon_c);
224 }
else if (cred_type == GNUTLS_CRD_CERTIFICATE) {
229 if (pcmk__str_empty((*tls)->ca_file)) {
230 (*tls)->ca_file = getenv(
"CIB_ca_file");
234 if (pcmk__str_empty((*tls)->cert_file)) {
235 (*tls)->cert_file = getenv(
"CIB_cert_file");
239 if (pcmk__str_empty((*tls)->crl_file)) {
240 (*tls)->crl_file = getenv(
"CIB_crl_file");
244 if (pcmk__str_empty((*tls)->key_file)) {
245 (*tls)->key_file = getenv(
"CIB_key_file");
248 gnutls_certificate_allocate_credentials(&(*tls)->credentials.cert);
251 gnutls_certificate_set_dh_params((*tls)->credentials.cert,
256 rc = tls_load_x509_data(*tls);
262 }
else if (cred_type == GNUTLS_CRD_PSK) {
264 gnutls_psk_allocate_server_credentials(&(*tls)->credentials.psk_s);
265 gnutls_psk_set_server_dh_params((*tls)->credentials.psk_s,
268 gnutls_psk_allocate_client_credentials(&(*tls)->credentials.psk_c);
278 int rc = GNUTLS_E_SUCCESS;
279 unsigned int dh_bits = 0;
282 rc = gnutls_dh_params_init(dh_params);
283 if (rc != GNUTLS_E_SUCCESS) {
287 dh_bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH,
288 GNUTLS_SEC_PARAM_NORMAL);
290 rc = GNUTLS_E_DH_PRIME_UNACCEPTABLE;
295 if ((dh_max_bits > 0) && (dh_bits > dh_max_bits)) {
296 dh_bits = dh_max_bits;
299 crm_info(
"Generating Diffie-Hellman parameters with %u-bit prime for TLS",
301 rc = gnutls_dh_params_generate2(*dh_params, dh_bits);
302 if (rc != GNUTLS_E_SUCCESS) {
309 crm_err(
"Could not initialize Diffie-Hellman parameters for TLS: %s " 310 QB_XS
" rc=%d", gnutls_strerror(rc), rc);
317 unsigned int conn_type = tls->
server ? GNUTLS_SERVER : GNUTLS_CLIENT;
318 int rc = GNUTLS_E_SUCCESS;
320 gnutls_session_t session = NULL;
322 rc = gnutls_init(&session, conn_type);
323 if (rc != GNUTLS_E_SUCCESS) {
333 prio = get_gnutls_priorities(tls->
cred_type);
339 rc = gnutls_priority_set_direct(session, prio, NULL);
340 if (rc != GNUTLS_E_SUCCESS) {
344 gnutls_transport_set_ptr(session,
345 (gnutls_transport_ptr_t) GINT_TO_POINTER(csock));
350 }
else if (tls->
cred_type == GNUTLS_CRD_ANON) {
352 }
else if (tls->
cred_type == GNUTLS_CRD_CERTIFICATE) {
356 }
else if (tls->
cred_type == GNUTLS_CRD_PSK) {
364 if (rc != GNUTLS_E_SUCCESS) {
370 if (tls->
cred_type == GNUTLS_CRD_CERTIFICATE) {
371 if (conn_type == GNUTLS_SERVER) {
373 gnutls_certificate_server_set_request(session, GNUTLS_CERT_REQUIRE);
381 gnutls_certificate_set_verify_function(tls->
credentials.
cert, verify_peer_cert);
387 crm_err(
"Could not initialize %s TLS %s session: %s " QB_XS
" rc=%d priority='%s'",
389 (conn_type == GNUTLS_SERVER)?
"server" :
"client",
390 gnutls_strerror(rc), rc, prio);
392 if (session != NULL) {
393 gnutls_deinit(session);
408 }
while (rc == GNUTLS_E_INTERRUPTED);
410 if (rc == GNUTLS_E_AGAIN) {
415 }
else if (rc != GNUTLS_E_SUCCESS) {
416 crm_err(
"TLS handshake with remote client failed: %s " 417 QB_XS
" rc=%d", gnutls_strerror(rc), rc);
433 gnutls_psk_server_credentials_function *cb)
441 gnutls_x509_crt_t cert;
442 const gnutls_datum_t *datum = NULL;
445 if (session == NULL) {
449 if (gnutls_certificate_type_get(session) != GNUTLS_CRT_X509) {
453 datum = gnutls_certificate_get_ours(session);
458 gnutls_x509_crt_init(&cert);
459 gnutls_x509_crt_import(cert, datum, GNUTLS_X509_FMT_DER);
461 expiry = gnutls_x509_crt_get_expiration_time(cert);
464 time_t now = time(NULL);
467 if (expiry - now <= 60 * 60 * 24 * 30) {
470 crm_time_log(LOG_WARNING,
"TLS certificate will expire on",
476 gnutls_x509_crt_deinit(cert);
484 if (gnutls_rc != NULL) {
485 *gnutls_rc = GNUTLS_E_SUCCESS;
491 case GNUTLS_E_SUCCESS:
495 case GNUTLS_E_INTERRUPTED:
501 if (gnutls_rc != NULL) {
516 const time_t time_limit = time(NULL) + timeout_sec;
524 }
while (time(NULL) < time_limit);
538 !pcmk__str_empty(getenv(
"CIB_cert_file"))) &&
540 !pcmk__str_empty(getenv(
"CIB_ca_file"))) &&
542 !pcmk__str_empty(getenv(
"CIB_key_file")));
#define CRM_CHECK(expr, failure_action)
#define PCMK__ENV_CA_FILE
int pcmk__scan_min_int(const char *text, int *result, int minimum)
#define crm_time_log_timeofday
gnutls_psk_client_credentials_t psk_c
enum pcmk_ipc_server type
bool pcmk__x509_enabled(void)
crm_time_t * pcmk__copy_timet(time_t source)
struct crm_time_s crm_time_t
#define PCMK__ENV_CRL_FILE
#define PCMK__ENV_KEY_FILE
gnutls_session_t pcmk__new_tls_session(pcmk__tls_t *tls, int csock)
#define DEFAULT_REMOTE_USERNAME
int pcmk__tls_client_handshake(pcmk__remote_t *remote, int timeout_sec, int *gnutls_rc)
const char * pcmk__env_option(const char *option)
#define PCMK__GNUTLS_PRIORITIES
int pcmk__init_tls(pcmk__tls_t **tls, bool server, gnutls_credentials_type_t cred_type)
int pcmk__read_handshake_data(const pcmk__client_t *client)
#define PCMK__ENV_TLS_PRIORITIES
gnutls_anon_client_credentials_t anon_c
#define crm_trace(fmt, args...)
int pcmk__init_tls_dh(gnutls_dh_params_t *dh_params)
gnutls_credentials_type_t cred_type
#define crm_time_log(level, prefix, dt, flags)
gnutls_certificate_credentials_t cert
#define PCMK__ENV_CERT_FILE
#define pcmk__assert(expr)
union pcmk__tls_t::@10 credentials
int pcmk__tls_client_try_handshake(pcmk__remote_t *remote, int *gnutls_rc)
#define crm_err(fmt, args...)
void pcmk__tls_check_cert_expiration(gnutls_session_t session)
gnutls_dh_params_t dh_params
void pcmk__tls_add_psk_callback(pcmk__tls_t *tls, gnutls_psk_server_credentials_function *cb)
gnutls_session_t tls_session
gnutls_psk_server_credentials_t psk_s
gnutls_anon_server_credentials_t anon_s
#define PCMK__ENV_DH_MAX_BITS
struct pcmk__remote_s * remote
#define pcmk__assert_alloc(nmemb, size)
void pcmk__tls_add_psk_key(pcmk__tls_t *tls, gnutls_datum_t *key)
#define crm_info(fmt, args...)
#define crm_time_log_date
void pcmk__free_tls(pcmk__tls_t *tls)
char * crm_strdup_printf(char const *format,...) G_GNUC_PRINTF(1
void crm_time_free(crm_time_t *dt)