1/* 2** Zabbix 3** Copyright (C) 2001-2021 Zabbix SIA 4** 5** This program is free software; you can redistribute it and/or modify 6** it under the terms of the GNU General Public License as published by 7** the Free Software Foundation; either version 2 of the License, or 8** (at your option) any later version. 9** 10** This program is distributed in the hope that it will be useful, 11** but WITHOUT ANY WARRANTY; without even the implied warranty of 12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13** GNU General Public License for more details. 14** 15** You should have received a copy of the GNU General Public License 16** along with this program; if not, write to the Free Software 17** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18**/ 19 20package tls 21 22/* 23#cgo CFLAGS: -I${SRCDIR}/../../../../include -I${SRCDIR}/../../../../build/win32/include 24 25#cgo openssl LDFLAGS: -lssl -lcrypto -lwsock32 -lws2_32 26 27#include <stdlib.h> 28#include <stdio.h> 29#include <string.h> 30#include <unistd.h> 31#include <ctype.h> 32#include "config.h" 33 34#define TLS_UNUSED(var) (void)(var) 35 36const char *tls_crypto_init_msg; 37 38#ifdef HAVE_OPENSSL 39#include <openssl/ssl.h> 40#include <openssl/err.h> 41#include <openssl/bio.h> 42#include <openssl/rand.h> 43 44#if defined(LIBRESSL_VERSION_NUMBER) 45# error package zabbix.com/pkg/tls cannot be compiled with LibreSSL. Encryption is supported with OpenSSL. 46#elif !defined(HAVE_OPENSSL_WITH_PSK) 47# error package zabbix.com/pkg/tls cannot be compiled with OpenSSL which has excluded PSK support. 48#elif defined(_WINDOWS) && OPENSSL_VERSION_NUMBER < 0x1010100fL // On MS Windows OpenSSL 1.1.1 is required 49# error on Microsoft Windows the package zabbix.com/pkg/tls requires OpenSSL 1.1.1 or newer. 50#elif OPENSSL_VERSION_NUMBER < 0x1000100fL 51 // OpenSSL before 1.0.1 52# error package zabbix.com/pkg/tls cannot be compiled with this OpenSSL version.\ 53 Supported versions are 1.0.1 and newer. 54#endif 55 56#if OPENSSL_VERSION_NUMBER < 0x1010000fL 57 // OpenSSL 1.0.1/1.0.2 (before 1.1.0) 58#include <openssl/x509v3.h> // string_to_hex() 59# define OPENSSL_hexstr2buf string_to_hex 60# define TLS_method TLSv1_2_method 61# define SSL_CTX_get_ciphers(ciphers) ((ciphers)->cipher_list) 62# define OPENSSL_VERSION SSLEAY_VERSION 63# define OpenSSL_version SSLeay_version 64# define SSL_CTX_set_min_proto_version(ctx, TLSv) 1 65#endif 66 67#define TLS_EX_DATA_ERRBIO 0 68#define TLS_EX_DATA_IDENTITY 1 69#define TLS_EX_DATA_KEY 2 70 71typedef SSL_CTX * SSL_CTX_LP; 72 73typedef struct { 74 SSL *ssl; 75 BIO *in; 76 BIO *out; 77 BIO *err; 78 int ready; 79 char *psk_identity; 80 char *psk_key; 81} tls_t; 82 83#if OPENSSL_VERSION_NUMBER < 0x1010000fL 84 // OpenSSL 1.0.1/1.0.2 (before 1.1.0) 85#include <pthread.h> 86 87// exit codes 88#define ZBX_EXIT_LOCK_FAILED 2 89#define ZBX_EXIT_UNLOCK_FAILED 3 90 91static pthread_mutex_t *mutexes = NULL; // Mutexes for multi-threaded OpenSSL (see "man 3ssl threads" 92 // and example in crypto/threads/mttest.c). 93 94static void zbx_mutex_lock(const char *filename, int line, int idx) 95{ 96 if (0 != pthread_mutex_lock(mutexes + idx)) 97 { 98 fprintf(stderr, "[file:'%s',line:%d] lock failed: [%d] %s\n", filename, line, errno, strerror(errno)); 99 exit(ZBX_EXIT_LOCK_FAILED); 100 } 101} 102 103static void zbx_mutex_unlock(const char *filename, int line, int idx) 104{ 105 if (0 != pthread_mutex_unlock(mutexes + idx)) 106 { 107 fprintf(stderr, "[file:'%s',line:%d] unlock failed: [%d] %s\n", filename, line, errno, strerror(errno)); 108 exit(ZBX_EXIT_UNLOCK_FAILED); 109 } 110} 111 112static void zbx_openssl_locking_cb(int mode, int n, const char *file, int line) 113{ 114 if (0 != (mode & CRYPTO_LOCK)) 115 zbx_mutex_lock(file, line, n); 116 else 117 zbx_mutex_unlock(file, line, n); 118} 119 120static int zbx_allocate_mutexes(const char **error_msg) 121{ 122 int num_locks, i; 123 124 num_locks = CRYPTO_num_locks(); 125 126 if (NULL == (mutexes = malloc((size_t)num_locks * sizeof(pthread_mutex_t)))) 127 { 128 *error_msg = strdup("cannot allocate mutexes for OpenSSL library: out of memory"); 129 return -1; 130 } 131 132 for (i = 0; i < num_locks; i++) 133 { 134 int res; 135 136 if (0 != (res = pthread_mutex_init(mutexes + i, NULL))) 137 { 138 char buf[128]; 139 140 snprintf(buf, sizeof(buf), "cannot initialize mutex %d (out of %d) for OpenSSL library:" 141 " pthread_mutex_init() returned %d", i, num_locks, res); 142 143 *error_msg = strdup(buf); 144 return -1; 145 } 146 } 147 148 return 0; 149} 150#endif 151 152static int tls_init(void) 153{ 154#if OPENSSL_VERSION_NUMBER >= 0x1010000fL 155 // OpenSSL 1.1.0 or newer 156 if (1 != OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL)) 157 { 158 tls_crypto_init_msg = "cannot initialize OpenSSL library"; 159 return -1; 160 } 161#else // OpenSSL 1.0.1/1.0.2 (before 1.1.0) 162 SSL_load_error_strings(); 163 ERR_load_BIO_strings(); 164 SSL_library_init(); 165 166 if (0 != zbx_allocate_mutexes(&tls_crypto_init_msg)) 167 return -1; 168 169 CRYPTO_set_locking_callback((void (*)(int, int, const char *, int))zbx_openssl_locking_cb); 170 171 // do not register our own threadid_func() callback, use OpenSSL default one 172#endif 173 if (1 != RAND_status()) // protect against not properly seeded PRNG 174 { 175 tls_crypto_init_msg = "cannot initialize PRNG"; 176 return -1; 177 } 178 179 tls_crypto_init_msg = "OpenSSL library successfully initialized"; 180 return 0; 181} 182 183static unsigned int tls_psk_client_cb(SSL *ssl, const char *hint, char *identity, 184 unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len) 185{ 186 size_t sz; 187 const char *psk_identity, *psk_key; 188 BIO *err; 189 unsigned char *key; 190 long key_len; 191 192 TLS_UNUSED(hint); 193 194 if (NULL == (err = (BIO *)SSL_get_ex_data(ssl, TLS_EX_DATA_ERRBIO))) 195 return 0; 196 197 if (NULL == (psk_identity = (const char *)SSL_get_ex_data(ssl, TLS_EX_DATA_IDENTITY))) 198 { 199 BIO_printf(err, "no PSK identity configured"); 200 return 0; 201 } 202 203 if (NULL == (psk_key = (const char *)SSL_get_ex_data(ssl, TLS_EX_DATA_KEY))) 204 { 205 BIO_printf(err, "no PSK key configured"); 206 return 0; 207 } 208 209 sz = strlen(psk_identity) + 1; 210 if (sz > max_identity_len) 211 { 212 BIO_printf(err, "PSK identity too large"); 213 return 0; 214 } 215 216 memcpy(identity, psk_identity, sz); 217 218 key = OPENSSL_hexstr2buf(psk_key, &key_len); 219 if (key == NULL) 220 { 221 BIO_printf(err, "invalid PSK key"); 222 return 0; 223 } 224 225 if (key_len > (long)max_psk_len) 226 { 227 BIO_printf(err, "PSK key is too large"); 228 OPENSSL_free(key); 229 return 0; 230 } 231 232 memcpy(psk, key, (size_t)key_len); 233 OPENSSL_free(key); 234 return (unsigned int)key_len; 235} 236 237static unsigned int tls_psk_server_cb(SSL *ssl, const char *identity, unsigned char *psk, unsigned int max_psk_len) 238{ 239 const char *psk_identity, *psk_key; 240 BIO *err; 241 unsigned char *key; 242 long key_len; 243 244 if (NULL == (err = (BIO *)SSL_get_ex_data(ssl, TLS_EX_DATA_ERRBIO))) 245 return 0; 246 247 if (NULL == (psk_identity = (const char *)SSL_get_ex_data(ssl, TLS_EX_DATA_IDENTITY))) 248 { 249 BIO_printf(err, "no PSK identity configured"); 250 return 0; 251 } 252 253 if (0 != strcmp(psk_identity, identity)) 254 { 255 BIO_printf(err, "invalid PSK identity"); 256 return 0; 257 } 258 259 if (NULL == (psk_key = (const char *)SSL_get_ex_data(ssl, TLS_EX_DATA_KEY))) 260 { 261 BIO_printf(err, "no PSK key configured"); 262 return 0; 263 } 264 265 key = OPENSSL_hexstr2buf(psk_key, &key_len); 266 if (key == NULL) 267 { 268 BIO_printf(err, "invalid PSK key"); 269 return 0; 270 } 271 272 if (key_len > (long)max_psk_len) 273 { 274 BIO_printf(err, "PSK key is too large"); 275 return 0; 276 } 277 278 memcpy(psk, key, (size_t)key_len); 279 OPENSSL_free(key); 280 return (unsigned int)key_len; 281} 282 283static int zbx_set_ecdhe_parameters(SSL_CTX *ctx) 284{ 285 EC_KEY *ecdh; 286 long res; 287 int ret = 0; 288 289 // use curve secp256r1/prime256v1/NIST P-256 290 291 if (NULL == (ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1))) 292 return -1; 293 294 SSL_CTX_set_options(ctx, SSL_OP_SINGLE_ECDH_USE); 295 296 if (1 != (res = SSL_CTX_set_tmp_ecdh(ctx, ecdh))) 297 ret = -1; 298 299 EC_KEY_free(ecdh); 300 301 return ret; 302} 303 304static void *tls_new_context(const char *ca_file, const char *crl_file, const char *cert_file, const char *key_file, 305 char **error) 306{ 307#define TLS_CIPHER_CERT_ECDHE "EECDH+aRSA+AES128:" 308#define TLS_CIPHER_CERT "RSA+aRSA+AES128" 309 310#if defined(HAVE_OPENSSL_WITH_PSK) 311#if OPENSSL_VERSION_NUMBER >= 0x1010100fL // OpenSSL 1.1.1 or newer 312 // TLS_AES_256_GCM_SHA384 is excluded from client ciphersuite list for PSK based connections. 313 // By default, in TLS 1.3 only *-SHA256 ciphersuites work with PSK. 314# define TLS_1_3_CIPHERSUITES "TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256" 315#endif 316#if OPENSSL_VERSION_NUMBER >= 0x1010000fL // OpenSSL 1.1.0 or newer 317# define TLS_CIPHER_PSK_ECDHE "kECDHEPSK+AES128:" 318# define TLS_CIPHER_PSK "kPSK+AES128" 319#else // OpenSSL 1.0.1/1.0.2 (before 1.1.0) 320# define TLS_CIPHER_PSK_ECDHE "" 321# define TLS_CIPHER_PSK "PSK-AES128-CBC-SHA" 322#endif 323#endif 324 SSL_CTX *ctx; 325 int ret = -1; 326 const char *ciphers; 327 328 if (NULL == (ctx = SSL_CTX_new(TLS_method()))) 329 goto out; 330 331 if (1 != SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION)) 332 goto out; 333 334 if (NULL != ca_file) 335 { 336 if (1 != SSL_CTX_load_verify_locations(ctx, ca_file, NULL)) 337 goto out; 338 339 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, NULL); 340 341 if (NULL != crl_file) 342 { 343 X509_STORE *store_cert; 344 X509_LOOKUP *lookup_cert; 345 int count_cert; 346 347 store_cert = SSL_CTX_get_cert_store(ctx); 348 349 if (NULL == (lookup_cert = X509_STORE_add_lookup(store_cert, X509_LOOKUP_file()))) 350 goto out; 351 352 if (0 >= (count_cert = X509_load_crl_file(lookup_cert, crl_file, X509_FILETYPE_PEM))) 353 goto out; 354 355 if (1 != X509_STORE_set_flags(store_cert, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL)) 356 goto out; 357 } 358 } 359 360 if (NULL != cert_file && 1 != SSL_CTX_use_certificate_chain_file(ctx, cert_file)) 361 goto out; 362 363 if (NULL != key_file && 1 != SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM)) 364 goto out; 365 366 SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); 367 SSL_CTX_set_options(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE | SSL_OP_NO_TICKET); 368 SSL_CTX_clear_options(ctx, SSL_OP_LEGACY_SERVER_CONNECT); 369 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF); 370 371 // try to enable ECDH ciphersuites 372 if (0 == zbx_set_ecdhe_parameters(ctx)) 373 { 374 if (NULL != ca_file) 375 ciphers = TLS_CIPHER_CERT_ECDHE TLS_CIPHER_CERT ":" TLS_CIPHER_PSK_ECDHE TLS_CIPHER_PSK; 376 else 377 ciphers = TLS_CIPHER_PSK_ECDHE TLS_CIPHER_PSK; 378 } 379 else 380 { 381 if (NULL != ca_file) 382 ciphers = TLS_CIPHER_CERT ":" TLS_CIPHER_PSK; 383 else 384 ciphers = TLS_CIPHER_PSK; 385 } 386 387#if OPENSSL_VERSION_NUMBER >= 0x1010100fL // OpenSSL 1.1.1 388 if (1 != SSL_CTX_set_ciphersuites(ctx, TLS_1_3_CIPHERSUITES)) 389 goto out; 390#endif 391 392 if (1 != SSL_CTX_set_cipher_list(ctx, ciphers)) 393 goto out; 394 395 ret = 0; 396out: 397 if (-1 == ret) 398 { 399 int sz; 400 BIO *err; 401 402 err = BIO_new(BIO_s_mem()); 403 BIO_set_nbio(err, 1); 404 ERR_print_errors(err); 405 406 sz = (int)BIO_ctrl_pending(err); 407 if (sz != 0) 408 { 409 *error = malloc((size_t)sz + 1); 410 BIO_read(err, *error, sz); 411 (*error)[sz] = '\0'; 412 } 413 else 414 *error = strdup("unknown openssl error"); 415 416 BIO_vfree(err); 417 if (NULL != ctx) 418 { 419 SSL_CTX_free(ctx); 420 ctx = NULL; 421 } 422 } 423 return ctx; 424} 425 426static void tls_free_context(SSL_CTX_LP ctx) 427{ 428 SSL_CTX_free(ctx); 429} 430 431static int tls_new(SSL_CTX_LP ctx, const char *psk_identity, const char *psk_key, tls_t **ptls) 432{ 433 tls_t *tls; 434 435 *ptls = tls = malloc(sizeof(tls_t)); 436 memset(tls, 0, sizeof(tls_t)); 437 438 if (NULL != psk_identity) 439 tls->psk_identity = strdup(psk_identity); 440 if (NULL != psk_key) 441 tls->psk_key = strdup(psk_key); 442 443 tls->err = BIO_new(BIO_s_mem()); 444 BIO_set_nbio(tls->err, 1); 445 446 if (NULL == (tls->ssl = SSL_new(ctx))) 447 return -1; 448 449 if (1 != SSL_set_ex_data(tls->ssl, TLS_EX_DATA_ERRBIO, (void *)tls->err)) 450 return -1; 451 452 if (1 != SSL_set_ex_data(tls->ssl, TLS_EX_DATA_IDENTITY, (void *)tls->psk_identity)) 453 return -1; 454 455 if (1 != SSL_set_ex_data(tls->ssl, TLS_EX_DATA_KEY, (void *)tls->psk_key)) 456 return -1; 457 458 tls->in = BIO_new(BIO_s_mem()); 459 tls->out = BIO_new(BIO_s_mem()); 460 BIO_set_nbio(tls->in, 1); 461 BIO_set_nbio(tls->out, 1); 462 SSL_set_bio(tls->ssl, tls->in, tls->out); 463 464 return 0; 465} 466 467static tls_t *tls_new_client(SSL_CTX_LP ctx, const char *psk_identity, const char *psk_key) 468{ 469 tls_t *tls; 470 int ret; 471 472 if (0 == tls_new(ctx, psk_identity, psk_key, &tls)) 473 { 474 if (psk_identity != NULL && psk_key != NULL) 475 SSL_set_psk_client_callback(tls->ssl, tls_psk_client_cb); 476 477 SSL_set_connect_state(tls->ssl); 478 if (1 == (ret = SSL_connect(tls->ssl)) || SSL_ERROR_WANT_READ == SSL_get_error(tls->ssl, ret)) 479 tls->ready = 1; 480 } 481 return tls; 482} 483 484static tls_t *tls_new_server(SSL_CTX_LP ctx, const char *psk_identity, const char *psk_key) 485{ 486 tls_t *tls; 487 int ret; 488 489 if (0 == tls_new(ctx, psk_identity, psk_key, &tls)) 490 { 491#if OPENSSL_VERSION_NUMBER >= 0x1010100fL // OpenSSL 1.1.1 or newer, or LibreSSL 492 if (1 != SSL_set_session_id_context(tls->ssl, (const unsigned char *)"Zbx", sizeof("Zbx") - 1)) 493 return tls; 494#endif 495 if (psk_identity != NULL && psk_key != NULL) 496 SSL_set_psk_server_callback(tls->ssl, tls_psk_server_cb); 497 498 SSL_set_accept_state(tls->ssl); 499 500 if (1 == (ret = SSL_accept(tls->ssl)) || SSL_ERROR_WANT_READ == SSL_get_error(tls->ssl, ret)) 501 tls->ready = 1; 502 } 503 return tls; 504} 505 506static int tls_recv(tls_t *tls, char *buf, int size) 507{ 508 if (BIO_ctrl_pending(tls->out)) 509 return BIO_read(tls->out, buf, size); 510 return 0; 511} 512 513static int tls_send(tls_t *tls, char *buf, int size) 514{ 515 return BIO_write(tls->in, buf, size); 516} 517 518static int tls_connected(tls_t *tls) 519{ 520 return SSL_is_init_finished(tls->ssl); 521} 522 523static int tls_write(tls_t *tls, char *buf, int len) 524{ 525 return SSL_write(tls->ssl, buf, len); 526} 527 528static int tls_read(tls_t *tls, char *buf, int len) 529{ 530 int ret; 531 ret = SSL_read(tls->ssl, buf, len); 532 if (0 > ret) { 533 if (SSL_ERROR_WANT_READ == SSL_get_error(tls->ssl, ret)) 534 return 0; 535 return ret; 536 } 537 return ret; 538} 539 540static int tls_handshake(tls_t *tls) 541{ 542 int ret; 543 ret = SSL_do_handshake(tls->ssl); 544 if (0 > ret) { 545 if (SSL_ERROR_WANT_READ == SSL_get_error(tls->ssl, ret)) 546 return 1; 547 return ret; 548 } 549 return 0; 550} 551 552static int tls_accept(tls_t *tls) 553{ 554 int ret; 555 ret = SSL_accept(tls->ssl); 556 if (0 > ret) { 557 if (SSL_ERROR_WANT_READ == SSL_get_error(tls->ssl, ret)) 558 return 1; 559 return ret; 560 } 561 return 0; 562} 563 564static size_t tls_error(tls_t *tls, char **buf) 565{ 566 size_t sz; 567 568 sz = BIO_ctrl_pending(tls->err); 569 if (sz == 0) 570 { 571 long verify_result; 572 573 if (X509_V_OK != (verify_result = SSL_get_verify_result(tls->ssl))) 574 BIO_printf(tls->err, "%s: ", X509_verify_cert_error_string(verify_result)); 575 576 ERR_print_errors(tls->err); 577 sz = BIO_ctrl_pending(tls->err); 578 } 579 580 if (sz != 0) 581 { 582 *buf = malloc(sz + 1); 583 BIO_read(tls->err, *buf, (int)sz); 584 (*buf)[sz] = '\0'; 585 } 586 else 587 *buf = strdup("unknown error"); 588 589 BIO_reset(tls->err); 590 return sz; 591} 592 593static int tls_ready(tls_t *tls) 594{ 595 return tls->ready; 596} 597 598static int tls_close(tls_t *tls) 599{ 600 int ret; 601 if (0 > (ret = SSL_shutdown(tls->ssl)) && SSL_ERROR_WANT_READ == SSL_get_error(tls->ssl, ret)) 602 return 0; 603 return ret; 604} 605 606static void tls_free(tls_t *tls) 607{ 608 if (NULL != tls->ssl) 609 SSL_free(tls->ssl); 610 if (NULL != tls->err) 611 BIO_vfree(tls->err); 612 if (NULL != tls->psk_identity) 613 free(tls->psk_identity); 614 if (NULL != tls->psk_key) 615 free(tls->psk_key); 616 free(tls); 617} 618 619static int tls_get_x509_name(tls_t *tls, X509_NAME *dn, char **name) 620{ 621 BIO *bio; 622 const char *data; 623 size_t len; 624 int ret = -1; 625 626 if (NULL == (bio = BIO_new(BIO_s_mem()))) 627 { 628 BIO_printf(tls->err, "cannot create OpenSSL BIO"); 629 return -1; 630 } 631 632 if (0 > X509_NAME_print_ex(bio, dn, 0, XN_FLAG_RFC2253 & ~ASN1_STRFLGS_ESC_MSB)) 633 { 634 BIO_printf(tls->err, "cannot print distinguished name"); 635 } 636 else 637 { 638 len = (size_t)BIO_get_mem_data(bio, &data); 639 *name = malloc(len + 1); 640 memcpy(*name, data, len); 641 (*name)[len] = '\0'; 642 ret = 0; 643 } 644 BIO_vfree(bio); 645 646 return ret; 647} 648 649static int tls_validate_issuer_and_subject(tls_t *tls, const char *issuer, const char *subject) 650{ 651 X509 *cert; 652 char *peer_issuer = NULL, *peer_subject = NULL; 653 int ret = -1; 654 655 if (NULL == (cert = SSL_get_peer_certificate(tls->ssl))) 656 { 657 BIO_printf(tls->err, "cannot obtain peer certificate"); 658 goto out; 659 } 660 661 if (NULL != issuer) 662 { 663 if (0 != tls_get_x509_name(tls, X509_get_issuer_name(cert), &peer_issuer)) 664 goto out; 665 if (0 != strcmp(issuer, peer_issuer)) 666 { 667 BIO_printf(tls->err, "invalid certificate issuer %s", peer_issuer); 668 goto out; 669 } 670 } 671 672 if (NULL != subject) 673 { 674 if (0 != tls_get_x509_name(tls, X509_get_subject_name(cert), &peer_subject)) 675 goto out; 676 if (0 != strcmp(subject, peer_subject)) 677 { 678 BIO_printf(tls->err, "invalid certificate subject %s", peer_subject); 679 goto out; 680 } 681 } 682 ret = 0; 683out: 684 free(peer_issuer); 685 free(peer_subject); 686 X509_free(cert); 687 return ret; 688} 689 690#define TLS_MAX_BUF_LEN 2048 691 692static void tls_description(tls_t *tls, char **desc) 693{ 694 X509 *cert; 695 char *peer_issuer = NULL, *peer_subject = NULL, buf[TLS_MAX_BUF_LEN], *ptr = buf; 696 697 ptr += snprintf(ptr, sizeof(buf), "%s %s", SSL_get_version(tls->ssl), SSL_get_cipher(tls->ssl)); 698 699 if ((sizeof(buf) - 1 > (size_t)(ptr - buf)) && NULL != (cert = SSL_get_peer_certificate(tls->ssl))) 700 { 701 if (0 == tls_get_x509_name(tls, X509_get_issuer_name(cert), &peer_issuer) && 702 0 == tls_get_x509_name(tls, X509_get_subject_name(cert), &peer_subject)) 703 { 704 // ensure buffer length for writing at least ', peer certificate issuer:" " subject:" "' 705 if (sizeof(buf) - (size_t)(ptr - buf) > 41) 706 { 707 snprintf(ptr, sizeof(buf) - (size_t)(ptr - buf), 708 ", peer certificate issuer:\"%s\" subject:\"%s\"", 709 peer_issuer, peer_subject); 710 } 711 } 712 } 713 *desc = strdup(buf); 714 free(peer_issuer); 715 free(peer_subject); 716} 717 718//***************************************************************************** 719// // 720// Function: tls_describe_ciphersuites // 721// // 722// Purpose: write names of enabled OpenSSL ciphersuites into dynamically // 723// allocated string // 724// // 725//***************************************************************************** 726static void tls_describe_ciphersuites(SSL_CTX_LP ctx, char **desc) 727{ 728#define TLS_CIPHERS_BUF_LEN 8192 729 730 int i, num; 731 size_t offset = 0; 732 STACK_OF(SSL_CIPHER) *cipher_list; 733 char buf[TLS_CIPHERS_BUF_LEN]; 734 735 buf[0] = '\0'; 736 cipher_list = SSL_CTX_get_ciphers(ctx); 737 num = sk_SSL_CIPHER_num(cipher_list); 738 739 for (i = 0; i < num; i++) 740 { 741 offset += (size_t)snprintf(buf + offset, sizeof(buf) - offset, " %s", 742 SSL_CIPHER_get_name(sk_SSL_CIPHER_value(cipher_list, i))); 743 744 if (sizeof(buf) - 2 <= offset) 745 { 746 const char *msg = "...(truncated)"; 747 748 snprintf(buf + sizeof(buf) - strlen(msg) - 1, strlen(msg) + 1, "%s", msg); 749 break; 750 } 751 } 752 *desc = strdup(buf); 753 754#undef TLS_CIPHERS_BUF_LEN 755} 756 757static const char *tls_version(void) 758{ 759 return OpenSSL_version(OPENSSL_VERSION); 760} 761 762static const char *tls_version_static(void) 763{ 764 return OPENSSL_VERSION_TEXT; 765} 766 767#elif defined(HAVE_GNUTLS) 768# error zabbix_agent2 does not support GnuTLS library. Compile with OpenSSL\ 769 (configure parameter --with-openssl) or without encryption support. 770#else // no crypto library requested, compile without encryption support 771 772typedef void * SSL_CTX_LP; 773 774typedef struct { 775} tls_t; 776 777static int tls_init(void) 778{ 779 tls_crypto_init_msg = "encryption support was not compiled in"; 780 return -1; 781} 782 783static void *tls_new_context(const char *ca_file, const char *crl_file, const char *cert_file, const char *key_file, 784 char **error) 785{ 786 TLS_UNUSED(ca_file); 787 TLS_UNUSED(crl_file); 788 TLS_UNUSED(cert_file); 789 TLS_UNUSED(key_file); 790 *error = strdup("built without OpenSSL"); 791 return NULL; 792} 793 794static void tls_free_context(SSL_CTX_LP ctx) 795{ 796 TLS_UNUSED(ctx); 797} 798 799static tls_t *tls_new_client(SSL_CTX_LP ctx, const char *psk_identity, const char *psk_key) 800{ 801 TLS_UNUSED(ctx); 802 TLS_UNUSED(psk_identity); 803 TLS_UNUSED(psk_key); 804 return NULL; 805} 806 807static tls_t *tls_new_server(SSL_CTX_LP ctx, const char *psk_identity, const char *psk_key) 808{ 809 TLS_UNUSED(ctx); 810 TLS_UNUSED(psk_identity); 811 TLS_UNUSED(psk_key); 812 return NULL; 813} 814 815static int tls_recv(tls_t *tls, char *buf, int size) 816{ 817 TLS_UNUSED(tls); 818 TLS_UNUSED(buf); 819 TLS_UNUSED(size); 820 return 0; 821} 822 823static int tls_send(tls_t *tls, char *buf, int size) 824{ 825 TLS_UNUSED(tls); 826 TLS_UNUSED(buf); 827 TLS_UNUSED(size); 828 return 0; 829} 830 831static int tls_connected(tls_t *tls) 832{ 833 TLS_UNUSED(tls); 834 return 0; 835} 836 837static int tls_write(tls_t *tls, char *buf, int len) 838{ 839 TLS_UNUSED(tls); 840 TLS_UNUSED(buf); 841 TLS_UNUSED(len); 842 return 0; 843} 844 845static int tls_read(tls_t *tls, char *buf, int len) 846{ 847 TLS_UNUSED(tls); 848 TLS_UNUSED(buf); 849 TLS_UNUSED(len); 850 return 0; 851} 852 853static int tls_handshake(tls_t *tls) 854{ 855 TLS_UNUSED(tls); 856 return 0; 857} 858 859static int tls_accept(tls_t *tls) 860{ 861 TLS_UNUSED(tls); 862 return 0; 863} 864 865static size_t tls_error(tls_t *tls, char **buf) 866{ 867 TLS_UNUSED(tls); 868 TLS_UNUSED(buf); 869 return 0; 870} 871 872static int tls_ready(tls_t *tls) 873{ 874 TLS_UNUSED(tls); 875 return 0; 876} 877 878static int tls_close(tls_t *tls) 879{ 880 TLS_UNUSED(tls); 881 return 0; 882} 883 884static void tls_free(tls_t *tls) 885{ 886 TLS_UNUSED(tls); 887} 888 889static int tls_validate_issuer_and_subject(tls_t *tls, const char *issuer, const char *subject) 890{ 891 TLS_UNUSED(tls); 892 TLS_UNUSED(issuer); 893 TLS_UNUSED(subject); 894 return 0; 895} 896 897static void tls_description(tls_t *tls, char **desc) 898{ 899 TLS_UNUSED(tls); 900 TLS_UNUSED(desc); 901} 902 903static void tls_describe_ciphersuites(SSL_CTX_LP ciphers, char **desc) 904{ 905 TLS_UNUSED(ciphers); 906 TLS_UNUSED(desc); 907} 908 909static const char *tls_version(void) 910{ 911 return NULL; 912} 913 914static const char *tls_version_static(void) 915{ 916 return NULL; 917} 918 919#endif 920 921*/ 922import "C" 923 924import ( 925 "errors" 926 "fmt" 927 "net" 928 "runtime" 929 "time" 930 "unsafe" 931 932 "zabbix.com/pkg/log" 933) 934 935// TLS initialization 936var supported bool // is TLS compiled in and successfully initialized 937var supportedMsg string // reason why TLS is not supported 938 939func Supported() bool { 940 return supported 941} 942 943func SupportedErrMsg() string { 944 return supportedMsg 945} 946 947func init() { 948 supported = C.tls_init() != -1 949 950 if !supported { 951 supportedMsg = C.GoString(C.tls_crypto_init_msg) 952 } 953} 954 955func describeCiphersuites(context unsafe.Pointer) (desc string) { 956 var cDesc *C.char 957 C.tls_describe_ciphersuites(C.SSL_CTX_LP(context), &cDesc) 958 desc = C.GoString(cDesc) 959 C.free(unsafe.Pointer(cDesc)) 960 return 961} 962 963type tlsConn struct { 964 conn net.Conn 965 tls unsafe.Pointer 966 buf []byte 967 timeout time.Duration 968 shiftDeadline bool 969} 970 971func (c *tlsConn) Error() (err error) { 972 var cBuf *C.char 973 var errmsg string 974 if c.tls != nil && 0 != C.tls_error((*C.tls_t)(c.tls), &cBuf) { 975 errmsg = C.GoString(cBuf) 976 C.free(unsafe.Pointer(cBuf)) 977 } else { 978 errmsg = "unknown openssl error" 979 } 980 return errors.New(errmsg) 981} 982 983func (c *tlsConn) ready() bool { 984 return C.tls_ready((*C.tls_t)(c.tls)) == 1 985} 986 987// Note, don't use flushTLS() and recvTLS() concurrently 988func (c *tlsConn) flushTLS() (err error) { 989 for { 990 if cn := C.tls_recv((*C.tls_t)(c.tls), (*C.char)(unsafe.Pointer(&c.buf[0])), C.int(len(c.buf))); cn > 0 { 991 if c.shiftDeadline { 992 if err = c.conn.SetWriteDeadline(time.Now().Add(c.timeout)); err != nil { 993 return 994 } 995 } 996 997 if _, err = c.conn.Write(c.buf[:cn]); err != nil { 998 return 999 } 1000 } else { 1001 return 1002 } 1003 } 1004} 1005 1006// Note, don't use flushTLS() and recvTLS() concurrently 1007func (c *tlsConn) recvTLS() (err error) { 1008 var n int 1009 if c.shiftDeadline { 1010 if err = c.conn.SetReadDeadline(time.Now().Add(c.timeout)); err != nil { 1011 return 1012 } 1013 } 1014 if n, err = c.conn.Read(c.buf); err != nil { 1015 return 1016 } 1017 C.tls_send((*C.tls_t)(c.tls), (*C.char)(unsafe.Pointer(&c.buf[0])), C.int(n)) 1018 return 1019} 1020 1021func (c *tlsConn) LocalAddr() net.Addr { 1022 return c.conn.LocalAddr() 1023} 1024 1025func (c *tlsConn) RemoteAddr() net.Addr { 1026 return c.conn.RemoteAddr() 1027} 1028 1029func (c *tlsConn) SetDeadline(t time.Time) error { 1030 return c.conn.SetDeadline(t) 1031} 1032 1033func (c *tlsConn) SetReadDeadline(t time.Time) error { 1034 return c.conn.SetReadDeadline(t) 1035} 1036 1037func (c *tlsConn) SetWriteDeadline(t time.Time) error { 1038 return c.conn.SetWriteDeadline(t) 1039} 1040 1041func (c *tlsConn) Close() (err error) { 1042 cr := C.tls_close((*C.tls_t)(c.tls)) 1043 c.conn.Close() 1044 if cr < 0 { 1045 return c.Error() 1046 } 1047 return 1048} 1049 1050func (c *tlsConn) verifyIssuerSubject(cfg *Config) (err error) { 1051 if cfg.Connect == ConnCert && (cfg.ServerCertIssuer != "" || cfg.ServerCertSubject != "") { 1052 var cSubject, cIssuer *C.char 1053 if cfg.ServerCertIssuer != "" { 1054 cIssuer = C.CString(cfg.ServerCertIssuer) 1055 defer C.free(unsafe.Pointer(cSubject)) 1056 } 1057 if cfg.ServerCertSubject != "" { 1058 cSubject = C.CString(cfg.ServerCertSubject) 1059 defer C.free(unsafe.Pointer(cSubject)) 1060 } 1061 if 0 != C.tls_validate_issuer_and_subject((*C.tls_t)(c.tls), cIssuer, cSubject) { 1062 return c.Error() 1063 } 1064 } 1065 return 1066} 1067 1068func (c *tlsConn) String() (desc string) { 1069 var cDesc *C.char 1070 C.tls_description((*C.tls_t)(c.tls), &cDesc) 1071 desc = C.GoString(cDesc) 1072 C.free(unsafe.Pointer(cDesc)) 1073 return 1074} 1075 1076// TLS connection client 1077type Client struct { 1078 tlsConn 1079} 1080 1081func (c *Client) checkConnection() (err error) { 1082 if C.tls_connected((*C.tls_t)(c.tls)) == C.int(1) { 1083 return 1084 } 1085 for C.tls_connected((*C.tls_t)(c.tls)) != C.int(1) { 1086 cRet := C.tls_handshake((*C.tls_t)(c.tls)) 1087 if cRet == 0 { 1088 break 1089 } 1090 if cRet < 0 { 1091 return c.Error() 1092 } 1093 if err = c.flushTLS(); err != nil { 1094 return 1095 } 1096 if err = c.recvTLS(); err != nil { 1097 return 1098 } 1099 } 1100 err = c.flushTLS() 1101 return 1102} 1103 1104func (c *Client) Write(b []byte) (n int, err error) { 1105 if err = c.checkConnection(); err != nil { 1106 return 1107 } 1108 cRet := C.tls_write((*C.tls_t)(c.tls), (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b))) 1109 if cRet <= 0 { 1110 return 0, c.Error() 1111 } 1112 if err = c.flushTLS(); err != nil { 1113 return 1114 } 1115 return len(b), nil 1116} 1117 1118func (c *Client) Read(b []byte) (n int, err error) { 1119 for { 1120 if err = c.checkConnection(); err != nil { 1121 return 1122 } 1123 cRet := C.tls_read((*C.tls_t)(c.tls), (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b))) 1124 if cRet > 0 { 1125 return int(cRet), nil 1126 } 1127 if cRet < 0 { 1128 return 0, c.Error() 1129 } 1130 if err = c.recvTLS(); err != nil { 1131 return 1132 } 1133 } 1134} 1135 1136func NewClient(nc net.Conn, cfg *Config, timeout time.Duration, shiftDeadline bool) (conn net.Conn, err error) { 1137 if !supported { 1138 return nil, errors.New(SupportedErrMsg()) 1139 } 1140 1141 if cfg.Connect == ConnUnencrypted { 1142 return nc, nil 1143 } 1144 1145 var cUser, cSecret *C.char 1146 context := defaultContext 1147 if cfg.Connect == ConnPSK { 1148 cUser = C.CString(cfg.PSKIdentity) 1149 cSecret = C.CString(cfg.PSKKey) 1150 1151 defer func() { 1152 C.free(unsafe.Pointer(cUser)) 1153 C.free(unsafe.Pointer(cSecret)) 1154 }() 1155 context = pskContext 1156 } 1157 1158 // for TLS we overwrite the timeoutMode and force it to move on every read or write 1159 c := &Client{ 1160 tlsConn: tlsConn{ 1161 conn: nc, 1162 buf: make([]byte, 4096), 1163 tls: unsafe.Pointer(C.tls_new_client(C.SSL_CTX_LP(context), cUser, cSecret)), 1164 timeout: timeout, 1165 shiftDeadline: shiftDeadline, 1166 }, 1167 } 1168 runtime.SetFinalizer(c, func(c *Client) { C.tls_free((*C.tls_t)(c.tls)) }) 1169 1170 if !c.ready() { 1171 return nil, c.Error() 1172 } 1173 if err = c.checkConnection(); err != nil { 1174 c.conn.Close() 1175 return 1176 } 1177 if err = c.verifyIssuerSubject(cfg); err != nil { 1178 c.Close() 1179 return 1180 } 1181 1182 log.Debugf("connection established using %s", c) 1183 1184 return c, nil 1185} 1186 1187// TLS connection server 1188type Server struct { 1189 tlsConn 1190} 1191 1192func (s *Server) checkConnection() (err error) { 1193 if C.tls_connected((*C.tls_t)(s.tls)) == C.int(1) { 1194 return 1195 } 1196 for { 1197 cRet := C.tls_accept((*C.tls_t)(s.tls)) 1198 if cRet == 0 { 1199 break 1200 } 1201 if cRet < 0 { 1202 return s.Error() 1203 } 1204 if err = s.flushTLS(); err != nil { 1205 return 1206 } 1207 if err = s.recvTLS(); err != nil { 1208 return 1209 } 1210 } 1211 err = s.flushTLS() 1212 return 1213} 1214 1215func (s *Server) Write(b []byte) (n int, err error) { 1216 if err = s.checkConnection(); err != nil { 1217 return 1218 } 1219 cRet := C.tls_write((*C.tls_t)(s.tls), (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b))) 1220 if cRet <= 0 { 1221 return 0, s.Error() 1222 } 1223 1224 return len(b), s.flushTLS() 1225} 1226 1227func (s *Server) Read(b []byte) (n int, err error) { 1228 for { 1229 if err = s.checkConnection(); err != nil { 1230 return 1231 } 1232 cRet := C.tls_read((*C.tls_t)(s.tls), (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b))) 1233 if cRet > 0 { 1234 return int(cRet), nil 1235 } 1236 if cRet < 0 { 1237 return 0, s.Error() 1238 } 1239 if err = s.recvTLS(); err != nil { 1240 return 1241 } 1242 } 1243} 1244 1245func NewServer(nc net.Conn, cfg *Config, b []byte, timeout time.Duration, shiftDeadline bool) (conn net.Conn, err error) { 1246 if !supported { 1247 return nil, errors.New(SupportedErrMsg()) 1248 } 1249 1250 var cUser, cSecret *C.char 1251 if cfg.Accept&ConnPSK != 0 { 1252 cUser = C.CString(cfg.PSKIdentity) 1253 cSecret = C.CString(cfg.PSKKey) 1254 1255 defer func() { 1256 C.free(unsafe.Pointer(cUser)) 1257 C.free(unsafe.Pointer(cSecret)) 1258 }() 1259 } 1260 1261 context := pskContext 1262 if cfg.Accept&ConnCert != 0 { 1263 context = defaultContext 1264 } 1265 1266 // for TLS we overwrite the timeoutMode and force it to move on every read or write 1267 s := &Server{ 1268 tlsConn: tlsConn{ 1269 conn: nc, 1270 buf: make([]byte, 4096), 1271 tls: unsafe.Pointer(C.tls_new_server(C.SSL_CTX_LP(context), cUser, cSecret)), 1272 timeout: timeout, 1273 shiftDeadline: shiftDeadline, 1274 }, 1275 } 1276 runtime.SetFinalizer(s, func(s *Server) { C.tls_free((*C.tls_t)(s.tls)) }) 1277 1278 if !s.ready() { 1279 return nil, s.Error() 1280 } 1281 1282 C.tls_send((*C.tls_t)(s.tls), (*C.char)(unsafe.Pointer(&b[0])), C.int(len(b))) 1283 1284 if err = s.checkConnection(); err != nil { 1285 s.conn.Close() 1286 return 1287 } 1288 if err = s.verifyIssuerSubject(cfg); err != nil { 1289 s.Close() 1290 return 1291 } 1292 1293 log.Debugf("connection established using %s", s) 1294 1295 return s, nil 1296} 1297 1298var pskContext, defaultContext unsafe.Pointer 1299 1300const ( 1301 ConnUnencrypted = 1 << iota 1302 ConnPSK 1303 ConnCert 1304) 1305 1306type Config struct { 1307 Accept int 1308 Connect int 1309 PSKIdentity string 1310 PSKKey string 1311 CAFile string 1312 CRLFile string 1313 CertFile string 1314 KeyFile string 1315 ServerCertIssuer string 1316 ServerCertSubject string 1317} 1318 1319func CopyrightMessage() (message string) { 1320 version := C.tls_version() 1321 if version == nil { 1322 return "" 1323 } 1324 1325 return fmt.Sprintf("\n\nThis product includes software developed by the OpenSSL Project\n"+ 1326 "for use in the OpenSSL Toolkit (http://www.openssl.org/).\n\n"+ 1327 "Compiled with %s\nRunning with %s\n", C.GoString(C.tls_version_static()), C.GoString(version)) 1328} 1329 1330func Init(config *Config) (err error) { 1331 if !supported { 1332 return errors.New(SupportedErrMsg()) 1333 } 1334 if pskContext != nil { 1335 C.tls_free_context(C.SSL_CTX_LP(pskContext)) 1336 } 1337 if defaultContext != nil { 1338 C.tls_free_context(C.SSL_CTX_LP(defaultContext)) 1339 } 1340 1341 var cErr, cCaFile, cCrlFile, cCertFile, cKeyFile, cNULL *C.char 1342 if (config.Accept|config.Connect)&ConnCert != 0 { 1343 cCaFile = C.CString(config.CAFile) 1344 cCertFile = C.CString(config.CertFile) 1345 cKeyFile = C.CString(config.KeyFile) 1346 defer C.free(unsafe.Pointer(cCaFile)) 1347 defer C.free(unsafe.Pointer(cCertFile)) 1348 defer C.free(unsafe.Pointer(cKeyFile)) 1349 1350 if config.CRLFile != "" { 1351 cCrlFile = C.CString(config.CRLFile) 1352 defer C.free(unsafe.Pointer(cCrlFile)) 1353 } 1354 } 1355 1356 if defaultContext = unsafe.Pointer(C.tls_new_context(cCaFile, cCrlFile, cCertFile, cKeyFile, &cErr)); defaultContext == nil { 1357 err = fmt.Errorf("cannot initialize default TLS context: %s", C.GoString(cErr)) 1358 C.free(unsafe.Pointer(cErr)) 1359 return 1360 } 1361 1362 if pskContext = unsafe.Pointer(C.tls_new_context(cNULL, cNULL, cNULL, cNULL, &cErr)); pskContext == nil { 1363 err = fmt.Errorf("cannot initialize PSK TLS context: %s", C.GoString(cErr)) 1364 C.free(unsafe.Pointer(cErr)) 1365 return 1366 } 1367 1368 log.Infof("OpenSSL library (%s) initialized", C.GoString(C.tls_version())) 1369 log.Debugf("default context ciphersuites:%s", describeCiphersuites(defaultContext)) 1370 log.Debugf("psk context ciphersuites:%s", describeCiphersuites(pskContext)) 1371 1372 return 1373} 1374