tls_open_funcs.c (55729B)
1 /* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */ 2 /* 3 This file is part of GNU libmicrohttpd. 4 Copyright (C) 2024-2025 Evgeny Grin (Karlson2k) 5 6 GNU libmicrohttpd is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 GNU libmicrohttpd is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 Alternatively, you can redistribute GNU libmicrohttpd and/or 17 modify it under the terms of the GNU General Public License as 18 published by the Free Software Foundation; either version 2 of 19 the License, or (at your option) any later version, together 20 with the eCos exception, as follows: 21 22 As a special exception, if other files instantiate templates or 23 use macros or inline functions from this file, or you compile this 24 file and link it with other works to produce a work based on this 25 file, this file does not by itself cause the resulting work to be 26 covered by the GNU General Public License. However the source code 27 for this file must still be made available in accordance with 28 section (3) of the GNU General Public License v2. 29 30 This exception does not invalidate any other reasons why a work 31 based on this file might be covered by the GNU General Public 32 License. 33 34 You should have received copies of the GNU Lesser General Public 35 License and the GNU General Public License along with this library; 36 if not, see <https://www.gnu.org/licenses/>. 37 */ 38 39 /** 40 * @file src/mhd2/tls_open_funcs.c 41 * @brief The implementation of OpenSSL wrapper functions 42 * @author Karlson2k (Evgeny Grin) 43 */ 44 45 #include "mhd_sys_options.h" 46 47 #include "sys_bool_type.h" 48 #include "sys_base_types.h" 49 50 #include "compat_calloc.h" 51 #include "sys_malloc.h" 52 #include <string.h> 53 54 #ifdef mhd_USE_TLS_DEBUG_MESSAGES 55 # include <stdio.h> /* For TLS debug printing */ 56 #endif 57 58 #include "mhd_assert.h" 59 #include "mhd_unreachable.h" 60 #include "mhd_assume.h" 61 62 #include "mhd_str.h" 63 #include "mhd_conn_socket.h" 64 65 #include "mhd_tls_internal.h" 66 67 #include "tls_open_tls_lib.h" 68 69 #include "mhd_tls_ver_stct.h" 70 71 #include "tls_open_daemon_data.h" 72 #include "tls_open_conn_data.h" 73 #include "tls_open_funcs.h" 74 75 #include "daemon_options.h" 76 77 #include "daemon_logger.h" 78 79 #include "microhttpd2_portability.h" 80 #include "mhd_public_api.h" 81 82 #if defined(HAVE_WUSED_BUT_MARKED_UNUSED) && defined(MHD_WARN_IGNORE_STYLE_GCC) 83 # define mhd_NOWARN_USED_UNUSED \ 84 MHD_WARN_PUSH_ MHD_WARN_IGNORE_ ("-Wused-but-marked-unused") 85 # define mhd_RESTORE_WARN_USED_UNUSED MHD_WARN_POP_ 86 #else 87 # define mhd_NOWARN_USED_UNUSED /* empty */ 88 # define mhd_RESTORE_WARN_USED_UNUSED /* empty */ 89 #endif 90 91 #ifdef mhd_USE_TLS_DEBUG_MESSAGES 92 93 static MHD_FN_PAR_NONNULL_ (1) int 94 mhd_tls_open_dbg_print_errs (const char *msg, 95 size_t msg_len, 96 void *cls) 97 { 98 int ret; 99 int print_size = (int)msg_len; 100 101 (void)cls; /* Not used */ 102 103 if ((print_size < 0) 104 || (msg_len != (unsigned int)print_size)) 105 print_size = (int)((~((unsigned int)0u)) >> 1); 106 107 ret = fprintf (stderr, 108 "## OpenSSL error: %.*s\n", 109 print_size, msg); 110 (void)fflush (stderr); 111 return ret; 112 } 113 114 115 # define mhd_DBG_PRINT_TLS_ERRS() \ 116 ERR_print_errors_cb (&mhd_tls_open_dbg_print_errs, NULL) 117 118 # define mhd_DBG_PRINT_TLS_INFO_MSG(message) \ 119 do { (void) fprintf (stderr, "## OpenSSL info: %s\n", (message)); \ 120 (void) fflush (stderr);} while (0) 121 # define mhd_DBG_PRINT_TLS_INFO_PARAM1(message, param) \ 122 do { (void) fprintf (stderr, "## OpenSSL info: " message "\n", (param)); \ 123 (void) fflush (stderr);} while (0) 124 #else 125 # define mhd_DBG_PRINT_TLS_ERRS() ERR_clear_error () 126 # define mhd_DBG_PRINT_TLS_INFO_MSG(message) ((void) 0) 127 # define mhd_DBG_PRINT_TLS_INFO_PARAM1(message, param) ((void) 0) 128 #endif 129 130 /* ** Global initialisation / de-initialisation ** */ 131 132 static bool openssl_lib_inited = false; 133 134 MHD_INTERNAL void 135 mhd_tls_open_global_init_once (void) 136 { 137 const unsigned long ver_num = OpenSSL_version_num (); 138 /* Make sure that used shared OpenSSL library has least the same version as 139 MHD was configured for. Fail if the version is earlier. */ 140 openssl_lib_inited = ((0x900000UL < ver_num) /* Versions before 3.0 */ 141 && (OPENSSL_VERSION_NUMBER <= ver_num)); 142 143 /* The call of OPENSSL_init_ssl() typically not needed, but it won't hurt 144 if library was initialised automatically. 145 In some exotic situations automatic initialisation could fail, and 146 this call would make sure that the library is initialised before used. */ 147 openssl_lib_inited = openssl_lib_inited 148 && (0 < OPENSSL_init_ssl (0, NULL)); 149 } 150 151 152 MHD_INTERNAL MHD_FN_PURE_ bool 153 mhd_tls_open_is_inited_fine (void) 154 { 155 return openssl_lib_inited; 156 } 157 158 159 /* ** Daemon initialisation / de-initialisation ** */ 160 161 /** 162 * Check application-provided daemon TLS settings 163 * @param d the daemon handle 164 * @param sk_edge_trigg the sockets polling uses edge-triggering 165 * @param s the application-provided settings 166 * @return #MHD_SC_OK on success, 167 * error code otherwise 168 */ 169 static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 170 check_app_tls_settings (struct MHD_Daemon *restrict d, 171 bool sk_edge_trigg, 172 struct DaemonOptions *restrict s) 173 { 174 mhd_assert (MHD_TLS_BACKEND_NONE != s->tls); 175 mhd_assert ((MHD_TLS_BACKEND_OPENSSL == s->tls) \ 176 || (MHD_TLS_BACKEND_ANY == s->tls)); 177 if (NULL == s->tls_cert_key.v_mem_cert) 178 { 179 mhd_LOG_MSG (d, MHD_SC_TLS_CONF_BAD_CERT, \ 180 "No valid TLS certificate is provided"); 181 return MHD_SC_TLS_CONF_BAD_CERT; 182 } 183 mhd_assert (NULL != s->tls_cert_key.v_mem_key); 184 185 if (sk_edge_trigg) 186 { 187 mhd_LOG_MSG (d, MHD_SC_TLS_BACKEND_DAEMON_INCOMPATIBLE_SETTINGS, \ 188 "Edge-triggered sockets polling cannot be used " 189 "with OpenSSL backend"); 190 return MHD_SC_TLS_BACKEND_DAEMON_INCOMPATIBLE_SETTINGS; 191 } 192 193 return MHD_SC_OK; 194 } 195 196 197 /* Helper to prevent password prompts in terminal */ 198 static int 199 null_passwd_cb (char *buf, 200 int size, 201 int rwflag, 202 void *cls) 203 { 204 (void)buf; 205 (void)size; 206 (void)rwflag; 207 (void)cls; /* Unused */ 208 mhd_DBG_PRINT_TLS_INFO_MSG ("The NULL passphrase callback is called\n"); 209 return 0; 210 } 211 212 213 /** 214 * Create new empty OpenSSL library context 215 * @param d the daemon handle 216 * @param d_tls the daemon TLS settings 217 * @return 'true' on success, 218 * 'false' otherwise 219 */ 220 static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ bool 221 create_lib_ctx (struct MHD_Daemon *restrict d, 222 struct mhd_TlsOpenDaemonData *restrict d_tls) 223 { 224 #ifndef MHD_SUPPORT_LOG_FUNCTIONALITY 225 (void)d; /* Used for logging only */ 226 #endif /* MHD_SUPPORT_LOG_FUNCTIONALITY */ 227 mhd_assert (NULL == d_tls->libctx); 228 229 d_tls->libctx = OSSL_LIB_CTX_new (); 230 231 if (NULL == d_tls->libctx) 232 { 233 mhd_DBG_PRINT_TLS_ERRS (); 234 mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \ 235 "Failed to create TLS library context"); 236 return false; 237 } 238 return true; 239 } 240 241 242 /** 243 * Reset OpenSSL library context. 244 * 245 * This function must not be called if library context is being used. 246 * @param d the daemon handle 247 * @param d_tls the daemon TLS settings 248 * @return 'true' on success, 249 * 'false' otherwise 250 */ 251 static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ bool 252 reset_lib_ctx (struct MHD_Daemon *restrict d, 253 struct mhd_TlsOpenDaemonData *restrict d_tls) 254 { 255 mhd_assert (NULL != d_tls->libctx); 256 257 OSSL_LIB_CTX_free (d_tls->libctx); 258 d_tls->libctx = NULL; 259 260 return create_lib_ctx (d, 261 d_tls); 262 } 263 264 265 /** 266 * Get non-default pathname for OpenSSL configuration file 267 * @param s the application-provided settings 268 * @param[out] conf_pathname set to the pathname on success 269 * @return #MHD_SC_OK on success, 270 * error code otherwise 271 */ 272 static MHD_FN_PAR_NONNULL_ALL_ 273 MHD_FN_PAR_OUT_ (2) MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 274 daemon_get_conf_file (struct DaemonOptions *restrict s, 275 char **restrict conf_pathname) 276 { 277 size_t name_len; 278 bool has_path; 279 280 mhd_assert (NULL != s->tls_openssl_def_file.v_pathname); 281 282 #ifndef MHD_SUPPORT_LOG_FUNCTIONALITY 283 (void)d; /* Used only for logging */ 284 #endif 285 286 /* Handle custom pathname */ 287 288 name_len = strlen (s->tls_openssl_def_file.v_pathname); 289 has_path = (NULL != memchr (s->tls_openssl_def_file.v_pathname, 290 '/', 291 name_len)); 292 #ifdef _WIN32 293 has_path = has_path || (NULL != memchr (s->tls_openssl_def_file, 294 '\\', 295 name_len)); 296 #endif /* _WIN32 */ 297 298 if ((!has_path) && (0u != name_len)) 299 { 300 const char *def_path; 301 size_t def_path_len; 302 303 def_path = X509_get_default_cert_area (); 304 if (NULL == def_path) 305 { 306 mhd_DBG_PRINT_TLS_ERRS (); 307 mhd_DBG_PRINT_TLS_INFO_MSG ("X509_get_default_cert_area() returned NULL"); 308 return MHD_SC_TLS_DAEMON_INIT_FAILED; /* Unrealistic */ 309 } 310 311 def_path_len = strlen (def_path); 312 313 *conf_pathname = 314 (char *)OPENSSL_malloc (def_path_len + 1u + name_len + 1u); 315 if (NULL == *conf_pathname) 316 return MHD_SC_DAEMON_MEM_ALLOC_FAILURE; 317 318 memcpy (*conf_pathname, 319 def_path, 320 def_path_len); 321 (*conf_pathname)[def_path_len] = '/'; 322 memcpy ((*conf_pathname) + def_path_len + 1u, 323 s->tls_openssl_def_file.v_pathname, 324 name_len + 1u); 325 326 return MHD_SC_OK; 327 } 328 329 *conf_pathname = (char *)OPENSSL_malloc (name_len + 1u); 330 if (NULL == *conf_pathname) 331 return MHD_SC_DAEMON_MEM_ALLOC_FAILURE; 332 333 memcpy (*conf_pathname, 334 s->tls_openssl_def_file.v_pathname, 335 name_len + 1u); 336 337 return MHD_SC_OK; 338 } 339 340 341 #ifdef mhd_TLS_OPEN_HAS_CONF_DIAG 342 # define mhd_LIBCTX_FORBIDS_FALLBACKS(d_tls) \ 343 (0 != OSSL_LIB_CTX_get_conf_diagnostics (d_tls->libctx)) 344 #else 345 # define mhd_LIBCTX_FORBIDS_FALLBACKS(d_tls) ((void) (d_tls), ! ! 0) 346 #endif /* ! mhd_TLS_OPEN_HAS_CONF_DIAG */ 347 348 349 static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) 350 MHD_FN_PAR_NONNULL_ (4) bool 351 daemon_load_conf_from_cfg (struct MHD_Daemon *restrict d, 352 const char *restrict filename, 353 const char *restrict app_name, 354 CONF *restrict cfg, 355 unsigned long load_flags, 356 bool log_missing_app_name) 357 { 358 #ifndef MHD_SUPPORT_LOG_FUNCTIONALITY 359 (void)d; /* Used for logging only */ 360 # ifndef mhd_USE_TLS_DEBUG_MESSAGES 361 (void)filename; /* Used for logs only */ 362 # endif /* mhd_USE_TLS_DEBUG_MESSAGES */ 363 #endif /* MHD_SUPPORT_LOG_FUNCTIONALITY */ 364 365 if (NULL != app_name) 366 { 367 if (NULL == NCONF_get_string (cfg, 368 NULL, 369 app_name)) 370 { 371 if (log_missing_app_name) 372 mhd_LOG_PRINT (d, 373 MHD_SC_TLS_LIB_CONF_WARNING, 374 mhd_LOG_FMT ("TLS library configuration '%s' " 375 "was not found in file '%s'"), 376 app_name, 377 filename); 378 else 379 mhd_DBG_PRINT_TLS_INFO_PARAM1 ("TLS library configuration '%s' " 380 "was not found in the configuration " 381 "file", 382 app_name); 383 return false; 384 } 385 mhd_DBG_PRINT_TLS_INFO_PARAM1 ("Trying to load configuration section " 386 "pointed by '%s'", 387 app_name); 388 } 389 else 390 mhd_DBG_PRINT_TLS_INFO_MSG ("Trying to load configuration section " 391 "pointed by default OpenSSL configuration"); 392 393 if (1 != CONF_modules_load (cfg, 394 app_name, 395 load_flags)) 396 { 397 mhd_DBG_PRINT_TLS_ERRS (); 398 399 mhd_LOG_PRINT (d, 400 MHD_SC_TLS_LIB_CONF_WARNING, 401 mhd_LOG_FMT ("Error loading TLS library " 402 "configuration '%s' " 403 "from file '%s'"), 404 app_name, 405 filename); 406 407 return false; 408 } 409 410 mhd_DBG_PRINT_TLS_INFO_MSG ("Successfully loaded OpenSSL configuration " 411 "from the configuration file"); 412 413 return true; 414 } 415 416 417 static MHD_FN_PAR_NONNULL_ALL_ 418 MHD_FN_PAR_INOUT_ (2) MHD_FN_PAR_INOUT_ (4) bool 419 cfg_reset_and_reload (struct MHD_Daemon *restrict d, 420 struct mhd_TlsOpenDaemonData *restrict d_tls, 421 const char *restrict filename, 422 CONF **restrict cfg_ptr) 423 { 424 #ifndef MHD_SUPPORT_LOG_FUNCTIONALITY 425 (void)d; /* Used for logging only */ 426 #endif /* MHD_SUPPORT_LOG_FUNCTIONALITY */ 427 mhd_assert (NULL != *cfg_ptr); 428 429 mhd_DBG_PRINT_TLS_INFO_MSG ("Resetting library CTX, CONF and reloading " 430 "configuration file"); 431 432 /* Destroy old cfg, which is connected to the library CTX */ 433 NCONF_free (*cfg_ptr); 434 *cfg_ptr = NULL; 435 436 /* Reset OpenSSL library CTX, which may have partially applied configuration */ 437 if (!reset_lib_ctx (d, 438 d_tls)) 439 return false; 440 441 /* Create a new cfg connected to the new CTX */ 442 *cfg_ptr = NCONF_new_ex (d_tls->libctx, 443 NULL); 444 if (NULL == *cfg_ptr) 445 { 446 mhd_DBG_PRINT_TLS_ERRS (); 447 448 mhd_DBG_PRINT_TLS_INFO_MSG ("Failed to create a new OpenSSL CONF"); 449 return false; 450 } 451 452 if (0 >= NCONF_load (*cfg_ptr, 453 filename, 454 NULL)) 455 { 456 mhd_DBG_PRINT_TLS_ERRS (); 457 458 mhd_DBG_PRINT_TLS_INFO_PARAM1 ("Failed to reload configuration file '%s'", 459 filename); 460 return false; 461 } 462 463 return true; 464 } 465 466 467 static inline MHD_FN_PAR_NONNULL_ALL_ bool 468 is_conf_file_fallback_allowed ( 469 const struct mhd_TlsOpenDaemonData *restrict d_tls, 470 const struct DaemonOptions *restrict s) 471 { 472 mhd_assert (NULL != d_tls->libctx); 473 474 if (!s->tls_openssl_def_file.v_disable_fallback) 475 return false; 476 if (mhd_LIBCTX_FORBIDS_FALLBACKS (d_tls)) 477 return false; 478 return true; 479 } 480 481 482 static inline MHD_FN_PAR_NONNULL_ALL_ bool 483 is_conf_fallback_allowed (const struct mhd_TlsOpenDaemonData *restrict d_tls, 484 const struct DaemonOptions *restrict s) 485 { 486 if (!s->tls_app_name.v_disable_fallback) 487 return false; 488 489 return is_conf_file_fallback_allowed (d_tls, 490 s); 491 } 492 493 494 /** 495 * Load OpenSSL configuration from OpenSSL configuration file 496 * @param d the daemon handle 497 * @param d_tls the daemon TLS settings 498 * @param s the application-provided settings 499 * @param use_custom_conf_pathname choose application-provided pathname or 500 * TLS backend default pathname 501 * @return #MHD_SC_OK on success, 502 * #MHD_SC_TLS_LIB_CONF_WARNING if configuration was not loaded due to 503 * non-fatal error, 504 * error code otherwise 505 */ 506 static MHD_FN_PAR_NONNULL_ (1) MHD_FN_PAR_NONNULL_ (2) MHD_FN_PAR_NONNULL_ (3) 507 MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 508 daemon_load_lib_conf (struct MHD_Daemon *restrict d, 509 struct mhd_TlsOpenDaemonData *restrict d_tls, 510 struct DaemonOptions *restrict s, 511 bool use_custom_conf_pathname) 512 { 513 char *conf_pathname; 514 CONF *conf; 515 enum MHD_StatusCode ret; 516 517 if (!use_custom_conf_pathname) 518 { 519 /* Use default pathname */ 520 conf_pathname = CONF_get1_default_config_file (); 521 522 if (NULL == conf_pathname) 523 { 524 mhd_DBG_PRINT_TLS_ERRS (); 525 526 ret = is_conf_fallback_allowed (d_tls, 527 s) 528 ? MHD_SC_TLS_LIB_CONF_WARNING : MHD_SC_TLS_DAEMON_INIT_FAILED; 529 530 mhd_LOG_MSG (d, ret, \ 531 "Failed to get default configuration file pathname"); 532 } 533 else 534 ret = MHD_SC_OK; 535 } 536 else 537 ret = daemon_get_conf_file (s, 538 &conf_pathname); 539 540 if (MHD_SC_OK != ret) 541 { 542 mhd_DBG_PRINT_TLS_INFO_MSG ("Failed to get configuration file pathname"); 543 return ret; 544 } 545 546 mhd_ASSUME (NULL != conf_pathname); 547 mhd_DBG_PRINT_TLS_INFO_PARAM1 ("Trying '%s' as OpenSSL configuration file", 548 conf_pathname); 549 550 if ('\0' == conf_pathname[0]) 551 { 552 OPENSSL_free (conf_pathname); /* A short-cut */ 553 554 if (NULL == s->tls_app_name.v_app_name) 555 return MHD_SC_OK; /* No special "application name" profile is needed */ 556 557 if (!s->tls_app_name.v_disable_fallback) 558 return MHD_SC_OK; /* Initialisation allowed with default values */ 559 560 /* Load of special "application name" profile is required */ 561 562 if (!use_custom_conf_pathname) 563 return MHD_SC_TLS_DAEMON_INIT_FAILED; /* No fallback pathname */ 564 565 mhd_assert (NULL != s->tls_openssl_def_file.v_pathname); 566 567 if (s->tls_openssl_def_file.v_disable_fallback) 568 return MHD_SC_TLS_DAEMON_INIT_FAILED; /* Fallback pathname is disallowed */ 569 570 /* Try to use fallback pathname to load special "application name" profile */ 571 return MHD_SC_TLS_LIB_CONF_WARNING; 572 } 573 574 conf = NCONF_new_ex (d_tls->libctx, 575 NULL); 576 if (NULL == conf) 577 { 578 mhd_DBG_PRINT_TLS_ERRS (); 579 580 ret = is_conf_fallback_allowed (d_tls, 581 s) 582 ? MHD_SC_TLS_LIB_CONF_WARNING : MHD_SC_TLS_DAEMON_INIT_FAILED; 583 mhd_LOG_MSG (d, ret, \ 584 "Failed to create OpenSSL empty configuration object"); 585 } 586 587 if (MHD_SC_OK == ret) 588 { 589 long err_line_num; 590 mhd_DBG_PRINT_TLS_INFO_PARAM1 ("Trying to load configuration file '%s'", 591 conf_pathname); 592 593 if (0 >= NCONF_load (conf, 594 conf_pathname, 595 &err_line_num)) 596 { 597 mhd_DBG_PRINT_TLS_ERRS (); 598 599 if (use_custom_conf_pathname) 600 ret = is_conf_file_fallback_allowed (d_tls, 601 s) 602 ? MHD_SC_TLS_LIB_CONF_WARNING : MHD_SC_TLS_DAEMON_INIT_FAILED; 603 else 604 ret = is_conf_fallback_allowed (d_tls, 605 s) 606 ? MHD_SC_TLS_LIB_CONF_WARNING : MHD_SC_TLS_DAEMON_INIT_FAILED; 607 608 mhd_LOG_PRINT (d, 609 ret, 610 mhd_LOG_FMT ("Error loading TLS library configuration " 611 "file '%s' at line %ld"), 612 conf_pathname, 613 err_line_num); 614 } 615 616 if (MHD_SC_OK == ret) 617 { 618 bool conf_loaded; 619 unsigned long flags; 620 621 flags = 0u; 622 if (!s->tls_app_name.v_disable_fallback) 623 flags |= CONF_MFLAGS_IGNORE_ERRORS; 624 625 conf_loaded = false; 626 627 if (NULL != s->tls_app_name.v_app_name) 628 { 629 char app_name_lc[128]; 630 const size_t app_name_len = strlen (s->tls_app_name.v_app_name); 631 632 /* Checked at the parameter processing */ 633 mhd_ASSUME ((128u) > app_name_len); 634 635 mhd_str_to_lowercase_bin_n (app_name_len + 1u, /* '+1' for zero termination */ 636 s->tls_app_name.v_app_name, 637 app_name_lc); 638 639 mhd_ASSUME ('\0' == app_name_lc[app_name_len]); 640 641 conf_loaded = 642 daemon_load_conf_from_cfg (d, 643 conf_pathname, 644 app_name_lc, 645 conf, 646 flags, 647 s->tls_app_name.v_disable_fallback 648 || mhd_LIBCTX_FORBIDS_FALLBACKS (d_tls)); 649 650 if (!conf_loaded) 651 { 652 if (s->tls_app_name.v_disable_fallback 653 || mhd_LIBCTX_FORBIDS_FALLBACKS (d_tls)) 654 ret = MHD_SC_TLS_DAEMON_INIT_FAILED; 655 else if (!cfg_reset_and_reload (d, 656 d_tls, 657 conf_pathname, 658 &conf)) 659 ret = MHD_SC_TLS_DAEMON_INIT_FAILED; 660 } 661 } 662 663 if (!conf_loaded 664 && (MHD_SC_OK == ret)) 665 { 666 667 mhd_assert ((NULL == s->tls_app_name.v_app_name) 668 || !s->tls_app_name.v_disable_fallback); 669 670 conf_loaded = 671 daemon_load_conf_from_cfg (d, 672 conf_pathname, 673 "libmicrohttpd", 674 conf, 675 flags, 676 false); 677 if ((!conf_loaded) 678 && (!cfg_reset_and_reload (d, 679 d_tls, 680 conf_pathname, 681 &conf))) 682 ret = MHD_SC_TLS_DAEMON_INIT_FAILED; 683 } 684 685 if (!conf_loaded 686 && (MHD_SC_OK == ret)) 687 { 688 689 mhd_assert ((NULL == s->tls_app_name.v_app_name) 690 || !s->tls_app_name.v_disable_fallback); 691 692 conf_loaded = 693 daemon_load_conf_from_cfg (d, 694 conf_pathname, 695 NULL, 696 conf, 697 flags, 698 true); 699 } 700 701 if (!conf_loaded) 702 ret = MHD_SC_TLS_LIB_CONF_WARNING; 703 } 704 705 NCONF_free (conf); /* Explicitly safe with NULL */ 706 } 707 708 OPENSSL_free (conf_pathname); 709 710 return ret; 711 } 712 713 714 /** 715 * Initialise OpenSSL library context 716 * @param d the daemon handle 717 * @param d_tls the daemon TLS settings 718 * @param s the application-provided settings 719 * @return #MHD_SC_OK on success, 720 * error code otherwise 721 */ 722 static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 723 daemon_init_lib_ctx (struct MHD_Daemon *restrict d, 724 struct mhd_TlsOpenDaemonData *restrict d_tls, 725 struct DaemonOptions *restrict s) 726 { 727 enum MHD_StatusCode ret; 728 729 #ifndef HAVE_NULL_PTR_ALL_ZEROS 730 d_tls->libctx = NULL; 731 #endif /* HAVE_NULL_PTR_ALL_ZEROS */ 732 733 if (!create_lib_ctx (d, d_tls)) 734 return MHD_SC_TLS_DAEMON_INIT_FAILED; 735 736 if (NULL != s->tls_openssl_def_file.v_pathname) 737 { 738 ret = daemon_load_lib_conf (d, 739 d_tls, 740 s, 741 true); 742 743 if (MHD_SC_OK == ret) 744 return MHD_SC_OK; 745 746 if (MHD_SC_TLS_LIB_CONF_WARNING == ret) 747 ret = s->tls_openssl_def_file.v_disable_fallback 748 ? MHD_SC_TLS_DAEMON_INIT_FAILED : MHD_SC_OK; 749 } 750 else 751 ret = MHD_SC_OK; 752 753 mhd_assert (MHD_SC_TLS_LIB_CONF_WARNING != ret); 754 755 if (MHD_SC_OK == ret) 756 { 757 mhd_assert ((NULL == s->tls_openssl_def_file.v_pathname) 758 || !s->tls_openssl_def_file.v_disable_fallback); 759 760 ret = daemon_load_lib_conf (d, 761 d_tls, 762 s, 763 false); 764 765 if (MHD_SC_OK == ret) 766 return MHD_SC_OK; 767 768 if (MHD_SC_TLS_LIB_CONF_WARNING == ret) 769 { 770 if ((!s->tls_app_name.v_disable_fallback) 771 && (!s->tls_openssl_def_file.v_disable_fallback)) 772 return MHD_SC_OK; /* Load without configuration file */ 773 774 ret = MHD_SC_TLS_DAEMON_INIT_FAILED; 775 } 776 } 777 778 mhd_assert (MHD_SC_TLS_LIB_CONF_WARNING != ret); 779 780 OSSL_LIB_CTX_free (d_tls->libctx); /* Explicitly safe with NULL */ 781 mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \ 782 "Failed to initialise TLS library context"); 783 return MHD_SC_TLS_DAEMON_INIT_FAILED; 784 } 785 786 787 /** 788 * De-initialise OpenSSL library context 789 * @param d_tls the daemon TLS settings 790 */ 791 static MHD_FN_PAR_NONNULL_ALL_ void 792 daemon_deinit_lib_ctx (struct mhd_TlsOpenDaemonData *restrict d_tls) 793 { 794 mhd_assert (NULL != d_tls->libctx); 795 OSSL_LIB_CTX_free (d_tls->libctx); 796 } 797 798 799 #define mhd_ALPN_CODE_HTTP1_0 \ 800 'h', 't', 't', 'p', '/', '1', '.', '0' /* Registered value for HTTP/1.0 */ 801 #define mhd_ALPN_CODE_HTTP1_1 \ 802 'h', 't', 't', 'p', '/', '1', '.', '1' /* Registered value for HTTP/1.1 */ 803 #ifdef MHD_SUPPORT_HTTP2 804 # define mhd_ALPN_CODE_HTTP2\ 805 'h', '2' /* Registered value for HTTP/2 over TLS */ 806 #endif /* MHD_SUPPORT_HTTP2 */ 807 #if 0 /* Disabled code */ 808 # define mhd_ALPN_CODE_HTTP3\ 809 'h', '3' /* Registered value for HTTP/3 */ 810 #endif /* Disabled code */ 811 812 813 #ifdef MHD_SUPPORT_HTTP2 814 static const unsigned char alpn_list_http2_1x[] = { 815 mhd_ALPN_H2_LEN, mhd_ALPN_CODE_HTTP2 816 , 817 mhd_ALPN_H1_1_LEN, mhd_ALPN_CODE_HTTP1_1 818 , 819 mhd_ALPN_H1_0_LEN, mhd_ALPN_CODE_HTTP1_0 820 }; 821 static const unsigned char alpn_list_http2_only[] = { 822 mhd_ALPN_H2_LEN, mhd_ALPN_CODE_HTTP2 823 }; 824 #endif /* MHD_SUPPORT_HTTP2 */ 825 static const unsigned char alpn_list_http1x_only[] = { 826 mhd_ALPN_H1_1_LEN, mhd_ALPN_CODE_HTTP1_1 827 , 828 mhd_ALPN_H1_0_LEN, mhd_ALPN_CODE_HTTP1_0 829 }; 830 831 #ifndef OPENSSL_NO_NEXTPROTONEG 832 /** 833 * Provide the list of supported protocols for NPN extension 834 * @param sess the TLS session (ignored) 835 * @param[out] out the pointer to get the location of the data 836 * @param[out] outlen the size of the data provided 837 * @param cls the closure (ignored) 838 * @return always SSL_TLSEXT_ERR_OK 839 */ 840 static int 841 get_npn_list (SSL *sess, 842 const unsigned char **out, 843 unsigned int *outlen, 844 void *cls) 845 { 846 struct mhd_TlsOpenDaemonData *const d_tls = 847 (struct mhd_TlsOpenDaemonData *)cls; 848 (void)sess; /* Unused */ 849 *out = d_tls->alpn_prots; 850 *outlen = d_tls->alpn_prots_size; 851 return SSL_TLSEXT_ERR_OK; 852 } 853 854 855 #endif /* ! OPENSSL_NO_NEXTPROTONEG */ 856 857 /** 858 * Select protocol from the provided list for ALPN extension 859 * @param sess the TLS session (ignored) 860 * @param[out] out the pointer to get the location of selected protocol value 861 * @param[out] outlen the size of the selected protocol value 862 * @param in the list of protocols values provided by the client 863 * @param inlen the size of the list of protocols values provided by the client 864 * @param cls the closure (ignored) 865 * @return SSL_TLSEXT_ERR_OK if matching protocol found and selected, 866 * SSL_TLSEXT_ERR_ALERT_FATAL otherwise 867 */ 868 static int 869 select_alpn_prot (SSL *sess, 870 const unsigned char **out, 871 unsigned char *outlen, 872 const unsigned char *in, 873 unsigned int inlen, 874 void *cls) 875 { 876 struct mhd_TlsOpenDaemonData *const d_tls = 877 (struct mhd_TlsOpenDaemonData *)cls; 878 (void)sess; /* Unused */ 879 if (OPENSSL_NPN_NEGOTIATED == 880 SSL_select_next_proto ((unsigned char **)mhd_DROP_CONST (out), 881 outlen, 882 in, 883 inlen, 884 d_tls->alpn_prots, 885 d_tls->alpn_prots_size)) 886 return SSL_TLSEXT_ERR_OK; /* Success */ 887 888 return SSL_TLSEXT_ERR_ALERT_FATAL; /* Failure */ 889 } 890 891 892 /** 893 * Initialise TLS server context 894 * @param d the daemon handle 895 * @param d_tls the daemon TLS settings 896 * @param s the application-provided settings 897 * @return #MHD_SC_OK on success, 898 * error code otherwise 899 */ 900 static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 901 daemon_init_ctx (struct MHD_Daemon *restrict d, 902 struct mhd_TlsOpenDaemonData *restrict d_tls, 903 struct DaemonOptions *restrict s) 904 { 905 uint64_t ctx_opts; 906 907 #ifndef MHD_SUPPORT_LOG_FUNCTIONALITY 908 (void)d; /* Mute compiler warning */ 909 #endif 910 (void)s; // TODO: support configuration options 911 912 mhd_assert (NULL != d_tls->libctx); 913 914 ERR_clear_error (); 915 916 d_tls->ctx = SSL_CTX_new_ex (d_tls->libctx, 917 NULL, 918 TLS_server_method ()); 919 if (NULL == d_tls->ctx) 920 { 921 mhd_DBG_PRINT_TLS_ERRS (); 922 mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \ 923 "Failed to initialise TLS server context"); 924 return MHD_SC_TLS_DAEMON_INIT_FAILED; 925 } 926 927 /* Enable some safe and useful workarounds */ 928 ctx_opts = SSL_OP_SAFARI_ECDHE_ECDSA_BUG | SSL_OP_TLSEXT_PADDING; 929 930 // TODO: add configuration option 931 // ctx_opts |= SSL_OP_CIPHER_SERVER_PREFERENCE; 932 933 #ifndef OPENSSL_NO_KTLS 934 /* Enable kernel TLS */ // TODO: add configuration option 935 ctx_opts |= SSL_OP_ENABLE_KTLS; 936 # ifdef SSL_OP_ENABLE_KTLS_TX_ZEROCOPY_SENDFILE 937 ctx_opts |= SSL_OP_ENABLE_KTLS_TX_ZEROCOPY_SENDFILE; 938 # endif 939 #endif 940 941 /* HTTP defines strict framing for the client-side data, 942 no risk of attack on server on unexpected connection interruption */ 943 /* ctx_opts |= SSL_OP_IGNORE_UNEXPECTED_EOF; */ // TODO: recheck 944 945 /* There is no reason to use re-negotiation with HTTP */ 946 ctx_opts |= SSL_OP_NO_RENEGOTIATION; 947 948 /* Do not use session resumption for now */ 949 ctx_opts |= SSL_OP_NO_TICKET; 950 951 (void)SSL_CTX_set_options (d_tls->ctx, 952 ctx_opts); 953 954 /* Prevent interactive password prompts */ 955 SSL_CTX_set_default_passwd_cb (d_tls->ctx, 956 &null_passwd_cb); 957 958 // TODO: make the setting configurable 959 /* SSL_CTX_set_security_level (d_tls->ctx, 0); */ 960 961 /* recv()- and send()-related options */ 962 (void)SSL_CTX_set_mode (d_tls->ctx, 963 SSL_MODE_ENABLE_PARTIAL_WRITE 964 | SSL_MODE_AUTO_RETRY); 965 (void)SSL_CTX_clear_mode (d_tls->ctx, 966 SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 967 | SSL_MODE_ASYNC); 968 969 SSL_CTX_set_read_ahead (d_tls->ctx, 970 !0); 971 972 /* ALPN and NPN */ 973 // TODO: use daemon option to disable ALPN 974 // TODO: use daemon option to select protocols for ALPN 975 #ifdef MHD_SUPPORT_HTTP2 976 if (1 /* enabled both HTTP/2 and HTTP/1.x */) 977 { 978 d_tls->alpn_prots = alpn_list_http2_1x; 979 d_tls->alpn_prots_size = sizeof(alpn_list_http2_1x); 980 } 981 else if (0 /* HTTP/2 only */) 982 { 983 d_tls->alpn_prots = alpn_list_http2_only; 984 d_tls->alpn_prots_size = sizeof(alpn_list_http2_only); 985 } 986 else 987 #endif /* MHD_SUPPORT_HTTP2 */ 988 if (1 /* HTTP/1.x only */) 989 { 990 d_tls->alpn_prots = alpn_list_http1x_only; 991 d_tls->alpn_prots_size = sizeof(alpn_list_http1x_only); 992 } 993 else 994 { 995 mhd_UNREACHABLE (); 996 } 997 SSL_CTX_set_alpn_select_cb (d_tls->ctx, 998 &select_alpn_prot, 999 d_tls); 1000 #ifndef OPENSSL_NO_NEXTPROTONEG 1001 SSL_CTX_set_next_protos_advertised_cb (d_tls->ctx, 1002 &get_npn_list, 1003 d_tls); 1004 #endif /* ! OPENSSL_NO_NEXTPROTONEG */ 1005 1006 return MHD_SC_OK; 1007 } 1008 1009 1010 /** 1011 * De-initialise TLS server context 1012 * @param d_tls the daemon TLS settings 1013 */ 1014 static MHD_FN_PAR_NONNULL_ALL_ void 1015 daemon_deinit_ctx (struct mhd_TlsOpenDaemonData *restrict d_tls) 1016 { 1017 mhd_assert (NULL != d_tls->ctx); 1018 SSL_CTX_free (d_tls->ctx); 1019 } 1020 1021 1022 /** 1023 * Load the certificates chain from the OpenSSL BIO 1024 * @param d the daemon handle 1025 * @param d_tls the daemon TLS settings 1026 * @param bio the certificates chain data opened in OpenSSL BIO 1027 * @return #MHD_SC_OK on success, 1028 * error code otherwise 1029 */ 1030 static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 1031 daemon_load_certs_chain_obio (struct MHD_Daemon *restrict d, 1032 struct mhd_TlsOpenDaemonData *restrict d_tls, 1033 BIO *restrict bio) 1034 { 1035 enum MHD_StatusCode ret; 1036 X509 *cert; 1037 1038 ret = MHD_SC_OK; 1039 1040 /* The certificate object must be pre-allocated to associate it with 1041 * the lib context */ 1042 cert = X509_new_ex (d_tls->libctx, 1043 NULL); 1044 if (NULL == cert) 1045 { 1046 mhd_DBG_PRINT_TLS_ERRS (); 1047 mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \ 1048 "Failed to create new certificate object"); 1049 return MHD_SC_TLS_DAEMON_INIT_FAILED; 1050 } 1051 1052 if (NULL == PEM_read_bio_X509_AUX (bio, 1053 &cert, 1054 &null_passwd_cb, 1055 NULL)) 1056 { 1057 mhd_DBG_PRINT_TLS_ERRS (); 1058 mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \ 1059 "Failed to process the certificate"); 1060 ret = MHD_SC_TLS_DAEMON_INIT_FAILED; 1061 } 1062 else 1063 { 1064 if (0 >= SSL_CTX_use_certificate (d_tls->ctx, 1065 cert)) 1066 { 1067 mhd_DBG_PRINT_TLS_ERRS (); 1068 mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \ 1069 "Failed to set the certificate"); 1070 ret = MHD_SC_TLS_DAEMON_INIT_FAILED; 1071 } 1072 else 1073 { 1074 if (0 != ERR_peek_error ()) 1075 mhd_DBG_PRINT_TLS_ERRS (); 1076 } 1077 } 1078 /* Free certificate: if it was successfully read, it has been "copied" to CTX */ 1079 X509_free (cert); 1080 if (MHD_SC_OK != ret) 1081 return ret; 1082 1083 do 1084 { 1085 X509 *inter_ca; /* Certifying certificate */ 1086 inter_ca = X509_new_ex (d_tls->libctx, 1087 NULL); 1088 if (NULL == inter_ca) 1089 { 1090 mhd_DBG_PRINT_TLS_ERRS (); 1091 mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \ 1092 "Failed to create new chain certificate object"); 1093 return MHD_SC_TLS_DAEMON_INIT_FAILED; 1094 } 1095 if (NULL == PEM_read_bio_X509 (bio, 1096 &inter_ca, 1097 &null_passwd_cb, 1098 NULL)) 1099 { 1100 unsigned long err; 1101 err = ERR_peek_last_error (); 1102 1103 mhd_NOWARN_USED_UNUSED 1104 1105 if ((ERR_LIB_PEM == ERR_GET_LIB (err)) 1106 && (PEM_R_NO_START_LINE == ERR_GET_REASON (err))) 1107 { 1108 /* End of data */ 1109 ERR_clear_error (); 1110 X509_free (inter_ca); /* Empty, not needed */ 1111 1112 mhd_assert (MHD_SC_OK == ret); 1113 return MHD_SC_OK; /* Success exit point */ 1114 } 1115 1116 mhd_RESTORE_WARN_USED_UNUSED 1117 mhd_DBG_PRINT_TLS_ERRS (); 1118 1119 mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \ 1120 "Failed to load next object in the certificates " \ 1121 "chain"); 1122 ret = MHD_SC_TLS_DAEMON_INIT_FAILED; 1123 } 1124 else 1125 { 1126 if (SSL_CTX_add0_chain_cert (d_tls->ctx, 1127 inter_ca)) 1128 { 1129 /* Success, do not free the certificate as 1130 * function '_add0_' was used to add it. */ 1131 /* Read the next certificate in the chain. */ 1132 continue; 1133 } 1134 1135 mhd_DBG_PRINT_TLS_ERRS (); 1136 mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \ 1137 "Failed to add the new certificate object " 1138 "to the chain"); 1139 ret = MHD_SC_TLS_DAEMON_INIT_FAILED; 1140 } 1141 1142 X509_free (inter_ca); /* Failed, the object is not needed */ 1143 mhd_assert (MHD_SC_OK != ret); 1144 } while (MHD_SC_OK == ret); 1145 mhd_assert (MHD_SC_OK != ret); 1146 return ret; 1147 } 1148 1149 1150 /** 1151 * Load the certificates chain based on application-provided settings 1152 * @param d the daemon handle 1153 * @param d_tls the daemon TLS settings 1154 * @param s the application-provided settings 1155 * @return #MHD_SC_OK on success, 1156 * error code otherwise 1157 */ 1158 static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 1159 daemon_load_certs_chain (struct MHD_Daemon *restrict d, 1160 struct mhd_TlsOpenDaemonData *restrict d_tls, 1161 struct DaemonOptions *restrict s) 1162 { 1163 enum MHD_StatusCode ret; 1164 BIO *m_bio; 1165 1166 mhd_assert (NULL != d_tls->libctx); 1167 mhd_assert (NULL != d_tls->ctx); 1168 1169 ERR_clear_error (); 1170 1171 m_bio = BIO_new_mem_buf (s->tls_cert_key.v_mem_cert, 1172 -1); 1173 if (NULL == m_bio) 1174 { 1175 mhd_DBG_PRINT_TLS_ERRS (); 1176 return MHD_SC_DAEMON_MEM_ALLOC_FAILURE; 1177 } 1178 ret = daemon_load_certs_chain_obio (d, 1179 d_tls, 1180 m_bio); 1181 BIO_free (m_bio); 1182 return ret; 1183 } 1184 1185 1186 /** 1187 * Initialise TLS certificate 1188 * The function loads the certificate chain and the private key. 1189 * @param d the daemon handle 1190 * @param d_tls the daemon TLS settings 1191 * @param s the application-provided settings 1192 * @return #MHD_SC_OK on success, 1193 * error code otherwise 1194 */ 1195 static MHD_FN_PAR_NONNULL_ALL_ MHD_FN_MUST_CHECK_RESULT_ enum MHD_StatusCode 1196 daemon_init_cert (struct MHD_Daemon *restrict d, 1197 struct mhd_TlsOpenDaemonData *restrict d_tls, 1198 struct DaemonOptions *restrict s) 1199 { 1200 enum MHD_StatusCode ret; 1201 BIO *m_bio; 1202 EVP_PKEY *pr_key; 1203 int res_i; 1204 long res_l; 1205 1206 mhd_assert (NULL != d_tls->libctx); 1207 mhd_assert (NULL != d_tls->ctx); 1208 1209 ERR_clear_error (); 1210 1211 ret = daemon_load_certs_chain (d, 1212 d_tls, 1213 s); 1214 if (MHD_SC_OK != ret) 1215 return ret; 1216 1217 /* Check and cache the certificates chain. 1218 This also prevents automatic chain re-building for each session. */ 1219 res_l = 1220 SSL_CTX_build_cert_chain ( 1221 d_tls->ctx, 1222 SSL_BUILD_CHAIN_FLAG_CHECK /* Use only certificates in the chain */ 1223 | SSL_BUILD_CHAIN_FLAG_UNTRUSTED /* Intermediate CA certs does not need to be trusted */ 1224 | SSL_BUILD_CHAIN_FLAG_NO_ROOT /* The root CA should not be added to the chain */ 1225 | SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR /* Allow the root CA to be not trusted */ 1226 ); 1227 if (0 >= res_l) 1228 { 1229 mhd_DBG_PRINT_TLS_ERRS (); 1230 mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \ 1231 "Failed rebuild certificate chain"); 1232 return MHD_SC_TLS_DAEMON_INIT_FAILED; 1233 } 1234 if (2 == res_l) 1235 mhd_DBG_PRINT_TLS_ERRS (); 1236 1237 m_bio = BIO_new_mem_buf (s->tls_cert_key.v_mem_key, 1238 -1); 1239 if (NULL == m_bio) 1240 { 1241 mhd_DBG_PRINT_TLS_ERRS (); 1242 return MHD_SC_DAEMON_MEM_ALLOC_FAILURE; 1243 } 1244 pr_key = 1245 PEM_read_bio_PrivateKey_ex (m_bio, 1246 NULL, 1247 NULL == s->tls_cert_key.v_mem_pass ? 1248 &null_passwd_cb : NULL, 1249 mhd_DROP_CONST (s->tls_cert_key.v_mem_pass), 1250 d_tls->libctx, 1251 NULL); 1252 BIO_free (m_bio); 1253 if (NULL == pr_key) 1254 { 1255 mhd_DBG_PRINT_TLS_ERRS (); 1256 mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \ 1257 "Failed to read the private key"); 1258 return MHD_SC_TLS_DAEMON_INIT_FAILED; 1259 } 1260 1261 res_i = SSL_CTX_use_PrivateKey (d_tls->ctx, 1262 pr_key); 1263 EVP_PKEY_free (pr_key); /* The key has been "copied" or failed */ 1264 if (1 != res_i) 1265 { 1266 mhd_DBG_PRINT_TLS_ERRS (); 1267 mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \ 1268 "Failed to set the private key"); 1269 return MHD_SC_TLS_DAEMON_INIT_FAILED; 1270 } 1271 /* This actually RE-checks the key. 1272 The key should be already checked automatically when it was set after 1273 setting the certificate. */ 1274 if (1 != SSL_CTX_check_private_key (d_tls->ctx)) 1275 { 1276 mhd_DBG_PRINT_TLS_ERRS (); 1277 mhd_LOG_MSG (d, MHD_SC_TLS_DAEMON_INIT_FAILED, \ 1278 "The private key does not match the certificate"); 1279 return MHD_SC_TLS_DAEMON_INIT_FAILED; 1280 } 1281 1282 return MHD_SC_OK; 1283 } 1284 1285 1286 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_ 1287 MHD_FN_PAR_OUT_ (4) mhd_StatusCodeInt 1288 mhd_tls_open_daemon_init (struct MHD_Daemon *restrict d, 1289 bool sk_edge_trigg, 1290 struct DaemonOptions *restrict s, 1291 struct mhd_TlsOpenDaemonData **restrict p_d_tls) 1292 { 1293 mhd_StatusCodeInt res; 1294 struct mhd_TlsOpenDaemonData *restrict d_tls; 1295 1296 /* Successful initialisation must be checked earlier */ 1297 mhd_assert (openssl_lib_inited); 1298 1299 res = check_app_tls_settings (d, sk_edge_trigg, s); 1300 if (MHD_SC_OK != res) 1301 return res; 1302 1303 d_tls = (struct mhd_TlsOpenDaemonData *) 1304 mhd_calloc (1, sizeof (struct mhd_TlsOpenDaemonData)); 1305 *p_d_tls = d_tls; 1306 if (NULL == d_tls) 1307 return MHD_SC_DAEMON_MEM_ALLOC_FAILURE; 1308 1309 res = daemon_init_lib_ctx (d, 1310 d_tls, 1311 s); 1312 if (MHD_SC_OK == res) 1313 { 1314 res = daemon_init_ctx (d, 1315 d_tls, 1316 s); 1317 if (MHD_SC_OK == res) 1318 { 1319 res = daemon_init_cert (d, 1320 d_tls, 1321 s); 1322 if (MHD_SC_OK == res) 1323 return MHD_SC_OK; /* Success exit point */ 1324 1325 /* Below is a clean-up code path */ 1326 daemon_deinit_ctx (d_tls); 1327 } 1328 daemon_deinit_lib_ctx (d_tls); 1329 } 1330 free (d_tls); 1331 *p_d_tls = NULL; 1332 mhd_assert (MHD_SC_OK != res); 1333 return res; /* Failure exit point */ 1334 } 1335 1336 1337 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1338 MHD_FN_PAR_INOUT_ (1) void 1339 mhd_tls_open_daemon_deinit (struct mhd_TlsOpenDaemonData *restrict d_tls) 1340 { 1341 mhd_assert (NULL != d_tls); 1342 daemon_deinit_ctx (d_tls); 1343 daemon_deinit_lib_ctx (d_tls); 1344 free (d_tls); 1345 } 1346 1347 1348 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1349 MHD_FN_PAR_INOUT_ (1) void 1350 mhd_tls_open_thread_cleanup (struct mhd_TlsOpenDaemonData *restrict d_tls) 1351 { 1352 OPENSSL_thread_stop_ex (d_tls->libctx); 1353 } 1354 1355 1356 /* ** Connection initialisation / de-initialisation ** */ 1357 1358 MHD_INTERNAL size_t 1359 mhd_tls_open_conn_get_tls_size_v (void) 1360 { 1361 return sizeof (struct mhd_TlsOpenConnData); 1362 } 1363 1364 1365 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_ 1366 MHD_FN_PAR_OUT_ (3) bool 1367 mhd_tls_open_conn_init (const struct mhd_TlsOpenDaemonData *restrict d_tls, 1368 const struct mhd_ConnSocket *sk, 1369 struct mhd_TlsOpenConnData *restrict c_tls) 1370 { 1371 int fd; 1372 1373 ERR_clear_error (); 1374 1375 fd = (int)sk->fd; 1376 if (sk->fd != (MHD_Socket)fd) 1377 return false; /* OpenSSL docs clam that it should not be possible */ 1378 1379 c_tls->sess = SSL_new (d_tls->ctx); 1380 1381 if (NULL == c_tls->sess) 1382 { 1383 mhd_DBG_PRINT_TLS_ERRS (); 1384 return false; 1385 } 1386 1387 if (0 < SSL_set_fd (c_tls->sess, fd)) 1388 { 1389 SSL_set_accept_state (c_tls->sess); /* Force server mode */ 1390 1391 #ifndef NDEBUG 1392 c_tls->dbg.is_inited = true; 1393 #endif 1394 return true; /* Success exit point */ 1395 } 1396 1397 SSL_free (c_tls->sess); 1398 c_tls->sess = NULL; 1399 return false; 1400 } 1401 1402 1403 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ void 1404 mhd_tls_open_conn_deinit (struct mhd_TlsOpenConnData *restrict c_tls) 1405 { 1406 mhd_assert (NULL != c_tls->sess); 1407 mhd_assert (c_tls->dbg.is_inited); 1408 SSL_free (c_tls->sess); 1409 } 1410 1411 1412 /* ** TLS connection establishing ** */ 1413 1414 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_ 1415 enum mhd_TlsProcedureResult 1416 mhd_tls_open_conn_handshake (struct mhd_TlsOpenConnData *restrict c_tls) 1417 { 1418 int res; 1419 1420 mhd_assert (c_tls->dbg.is_inited); 1421 mhd_assert (!c_tls->dbg.is_tls_handshake_completed); 1422 mhd_assert (!c_tls->shut_tls_wr_sent); 1423 mhd_assert (!c_tls->shut_tls_wr_received); 1424 mhd_assert (!c_tls->dbg.is_failed); 1425 1426 ERR_clear_error (); 1427 1428 res = SSL_do_handshake (c_tls->sess); 1429 1430 if (1 == res) 1431 { 1432 #ifndef NDEBUG 1433 c_tls->dbg.is_tls_handshake_completed = true; 1434 #endif /* ! NDEBUG */ 1435 return mhd_TLS_PROCED_SUCCESS; /* Success exit point */ 1436 } 1437 1438 switch (SSL_get_error (c_tls->sess, res)) 1439 { 1440 case SSL_ERROR_WANT_READ: 1441 /* OpenSSL does not distinguish between "interrupted" and "try again" codes. 1442 Based on OpenSSL result it is unclear whether the "recv-ready" flag 1443 should be reset or not. 1444 If edge-triggered sockets polling is used and the flag is cleared, but 1445 it should not (because the process has been "interrupted") then already 1446 pending data could be never processed. 1447 If the flag is not cleared, but it should be cleared (because all 1448 received data has been processed) then it would create busy-waiting loop 1449 with edge-triggered sockets polling. 1450 Temporal solution: disallow edge-triggered sockets polling with OpenSSL 1451 backend and use clear of "ready" flag. */ 1452 // TODO: replace "BIO" with custom version and track returned errors. 1453 return mhd_TLS_PROCED_SEND_MORE_NEEDED; 1454 case SSL_ERROR_WANT_WRITE: 1455 /* OpenSSL does not distinguish between "interrupted" and "try again" codes. 1456 Based on OpenSSL result it is unclear whether the "send-ready" flag 1457 should be reset or not. 1458 If edge-triggered sockets polling is used and the flag is cleared, but 1459 it should not (because the process has been "interrupted") then already 1460 pending data could be never sent. 1461 If the flag is not cleared, but it should be cleared (because all 1462 received data has been processed) then it would create busy-waiting loop 1463 with edge-triggered sockets polling. 1464 Temporal solution: disallow edge-triggered sockets polling with OpenSSL 1465 backend and use clear of "ready" flag. */ 1466 // TODO: replace "BIO" with custom version and track returned errors. 1467 return mhd_TLS_PROCED_RECV_MORE_NEEDED; 1468 case SSL_ERROR_NONE: 1469 mhd_assert (0 && "This should not be possible"); 1470 mhd_UNREACHABLE (); 1471 break; 1472 default: /* Handled with all other errors below */ 1473 break; 1474 } 1475 mhd_DBG_PRINT_TLS_ERRS (); 1476 #ifndef NDEBUG 1477 c_tls->dbg.is_failed = true; 1478 #endif /* ! NDEBUG */ 1479 return mhd_TLS_PROCED_FAILED; 1480 } 1481 1482 1483 MHD_INTERNAL MHD_FN_MUST_CHECK_RESULT_ MHD_FN_PAR_NONNULL_ALL_ 1484 enum mhd_TlsProcedureResult 1485 mhd_tls_open_conn_shutdown (struct mhd_TlsOpenConnData *restrict c_tls) 1486 { 1487 int res; 1488 1489 mhd_assert (c_tls->dbg.is_inited); 1490 mhd_assert (c_tls->dbg.is_tls_handshake_completed); 1491 mhd_assert (!c_tls->dbg.is_failed); 1492 1493 ERR_clear_error (); 1494 1495 res = SSL_shutdown (c_tls->sess); 1496 1497 if (1 == res) 1498 { 1499 c_tls->shut_tls_wr_sent = true; 1500 c_tls->shut_tls_wr_received = true; 1501 return mhd_TLS_PROCED_SUCCESS; /* Success exit point */ 1502 } 1503 1504 /* The OpenSSL documentation contradicts itself: there are two mutually 1505 exclusive statements on a single page. 1506 * https://docs.openssl.org/master/man3/SSL_shutdown/#shutdown-lifecycle 1507 indicates that for nonblocking socket ZERO could be returned when 1508 "close_notify" is GOING to be sent, but NOT sent yet. 1509 It also suggests to CALL SSL_get_error(3) when ZERO is returned. 1510 * https://docs.openssl.org/master/man3/SSL_shutdown/#return-values 1511 indicates ZERO is returned ONLY when "close_notify" HAS BEEN sent. 1512 It also suggests to NOT CALL SSL_get_error(3) when ZERO is returned. 1513 */ 1514 switch (SSL_get_error (c_tls->sess, res)) 1515 { 1516 case SSL_ERROR_WANT_READ: 1517 /* OpenSSL does not distinguish between "interrupted" and "try again" codes. 1518 Based on OpenSSL result it is unclear whether the "recv-ready" flag 1519 should be reset or not. 1520 If edge-triggered sockets polling is used and the flag is cleared, but 1521 it should not (because the process has been "interrupted") then already 1522 pending data could be never processed. 1523 If the flag is not cleared, but it should be cleared (because all 1524 received data has been processed) then it would create busy-waiting loop 1525 with edge-triggered sockets polling. 1526 Temporal solution: disallow edge-triggered sockets polling with OpenSSL 1527 backend and use clear of "ready" flag. */ 1528 // TODO: replace "BIO" with custom version and track returned errors. 1529 return mhd_TLS_PROCED_SEND_MORE_NEEDED; 1530 case SSL_ERROR_WANT_WRITE: 1531 c_tls->shut_tls_wr_sent = true; 1532 /* OpenSSL does not distinguish between "interrupted" and "try again" codes. 1533 Based on OpenSSL result it is unclear whether the "send-ready" flag 1534 should be reset or not. 1535 If edge-triggered sockets polling is used and the flag is cleared, but 1536 it should not (because the process has been "interrupted") then already 1537 pending data could be never sent. 1538 If the flag is not cleared, but it should be cleared (because all 1539 received data has been processed) then it would create busy-waiting loop 1540 with edge-triggered sockets polling. 1541 Temporal solution: disallow edge-triggered sockets polling with OpenSSL 1542 backend and use clear of "ready" flag. */ 1543 // TODO: replace "BIO" with custom version and track returned errors. 1544 return mhd_TLS_PROCED_RECV_MORE_NEEDED; 1545 case SSL_ERROR_NONE: 1546 mhd_assert (res != 0 && "Should not be possible"); 1547 c_tls->shut_tls_wr_sent = true; 1548 return mhd_TLS_PROCED_RECV_INTERRUPTED; 1549 default: /* Handled with all other errors below */ 1550 break; 1551 } 1552 mhd_DBG_PRINT_TLS_ERRS (); 1553 #ifndef NDEBUG 1554 c_tls->dbg.is_failed = true; 1555 #endif /* ! NDEBUG */ 1556 return mhd_TLS_PROCED_FAILED; 1557 } 1558 1559 1560 /* ** Data receiving and sending ** */ 1561 1562 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1563 MHD_FN_PAR_OUT_SIZE_ (3, 2) 1564 MHD_FN_PAR_OUT_ (4) enum mhd_SocketError 1565 mhd_tls_open_conn_recv (struct mhd_TlsOpenConnData *restrict c_tls, 1566 size_t buf_size, 1567 char buf[MHD_FN_PAR_DYN_ARR_SIZE_ (buf_size)], 1568 size_t *restrict received) 1569 { 1570 int res; 1571 1572 mhd_assert (c_tls->dbg.is_inited); 1573 mhd_assert (c_tls->dbg.is_tls_handshake_completed); 1574 mhd_assert (!c_tls->shut_tls_wr_sent); 1575 mhd_assert (!c_tls->dbg.is_failed); 1576 1577 ERR_clear_error (); 1578 1579 res = SSL_read_ex (c_tls->sess, 1580 buf, 1581 buf_size, 1582 received); 1583 if (1 == res) 1584 { 1585 mhd_assert (0 != *received); 1586 return mhd_SOCKET_ERR_NO_ERROR; /* Success exit point */ 1587 } 1588 1589 mhd_assert (0 == res); 1590 *received = 0; 1591 switch (SSL_get_error (c_tls->sess, res)) 1592 { 1593 case SSL_ERROR_ZERO_RETURN: /* Not an error */ 1594 c_tls->shut_tls_wr_received = true; 1595 return mhd_SOCKET_ERR_NO_ERROR; /* Success exit point */ 1596 case SSL_ERROR_WANT_READ: 1597 /* OpenSSL does not distinguish between "interrupted" and "try again" codes. 1598 Based on OpenSSL result it is unclear whether the "recv-ready" flag 1599 should be reset or not. 1600 If edge-triggered sockets polling is used and the flag is cleared, but 1601 it should not (because the process has been "interrupted") then already 1602 pending data could be never processed. 1603 If the flag is not cleared, but it should be cleared (because all 1604 received data has been processed) then it would create busy-waiting loop 1605 with edge-triggered sockets polling. 1606 Temporal solution: disallow edge-triggered sockets polling with OpenSSL 1607 backend and use clear of "ready" flag. */ 1608 // TODO: replace "BIO" with custom version and track returned errors. 1609 return mhd_SOCKET_ERR_AGAIN; 1610 case SSL_ERROR_NONE: 1611 mhd_assert (0 && "Should not be possible"); 1612 break; 1613 case SSL_ERROR_WANT_WRITE: 1614 mhd_assert (0 && "Should not be possible as re-handshakes are disallowed"); 1615 break; 1616 case SSL_ERROR_SYSCALL: 1617 mhd_DBG_PRINT_TLS_ERRS (); 1618 #ifndef NDEBUG 1619 c_tls->dbg.is_failed = true; 1620 #endif /* ! NDEBUG */ 1621 return mhd_SOCKET_ERR_CONN_BROKEN; 1622 case SSL_ERROR_SSL: 1623 default: 1624 break; 1625 } 1626 /* Treat all other kinds of errors as hard errors */ 1627 mhd_DBG_PRINT_TLS_ERRS (); 1628 #ifndef NDEBUG 1629 c_tls->dbg.is_failed = true; 1630 #endif /* ! NDEBUG */ 1631 return mhd_SOCKET_ERR_TLS; 1632 } 1633 1634 1635 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ bool 1636 mhd_tls_open_conn_has_data_in (struct mhd_TlsOpenConnData *restrict c_tls) 1637 { 1638 return 0 != SSL_pending (c_tls->sess); 1639 } 1640 1641 1642 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1643 MHD_FN_PAR_IN_SIZE_ (3, 2) 1644 MHD_FN_PAR_OUT_ (4) enum mhd_SocketError 1645 mhd_tls_open_conn_send4 (struct mhd_TlsOpenConnData *restrict c_tls, 1646 size_t buf_size, 1647 const char buf[MHD_FN_PAR_DYN_ARR_SIZE_ (buf_size)], 1648 size_t *restrict sent) 1649 { 1650 int res; 1651 1652 mhd_assert (c_tls->dbg.is_inited); 1653 mhd_assert (c_tls->dbg.is_tls_handshake_completed); 1654 mhd_assert (!c_tls->shut_tls_wr_sent); 1655 mhd_assert (!c_tls->dbg.is_failed); 1656 1657 ERR_clear_error (); 1658 1659 res = SSL_write_ex (c_tls->sess, 1660 buf, 1661 buf_size, 1662 sent); 1663 if (1 == res) 1664 { 1665 mhd_assert (0 != *sent); 1666 return mhd_SOCKET_ERR_NO_ERROR; /* Success exit point */ 1667 } 1668 1669 mhd_assert (0 == res); 1670 *sent = 0; 1671 switch (SSL_get_error (c_tls->sess, res)) 1672 { 1673 case SSL_ERROR_WANT_WRITE: 1674 /* OpenSSL does not distinguish between "interrupted" and "try again" codes. 1675 Based on OpenSSL result it is unclear whether the "send-ready" flag 1676 should be reset or not. 1677 If edge-triggered sockets polling is used and the flag is cleared, but 1678 it should not (because the process has been "interrupted") then already 1679 pending data could be never sent. 1680 If the flag is not cleared, but it should be cleared (because all 1681 received data has been processed) then it would create busy-waiting loop 1682 with edge-triggered sockets polling. 1683 Temporal solution: disallow edge-triggered sockets polling with OpenSSL 1684 backend and use clear of "ready" flag. */ 1685 // TODO: replace "BIO" with custom version and track returned errors. 1686 return mhd_SOCKET_ERR_AGAIN; 1687 case SSL_ERROR_NONE: 1688 mhd_assert (0 && "Should not be possible"); 1689 break; 1690 case SSL_ERROR_WANT_READ: 1691 mhd_assert (0 && "Should not be possible as re-handshakes are disallowed"); 1692 break; 1693 case SSL_ERROR_ZERO_RETURN: 1694 c_tls->shut_tls_wr_received = true; 1695 return mhd_SOCKET_ERR_AGAIN; 1696 case SSL_ERROR_SYSCALL: 1697 mhd_DBG_PRINT_TLS_ERRS (); 1698 #ifndef NDEBUG 1699 c_tls->dbg.is_failed = true; 1700 #endif /* ! NDEBUG */ 1701 return mhd_SOCKET_ERR_CONN_BROKEN; 1702 case SSL_ERROR_SSL: 1703 default: 1704 break; 1705 } 1706 /* Treat all other kinds of errors as hard errors */ 1707 mhd_DBG_PRINT_TLS_ERRS (); 1708 #ifndef NDEBUG 1709 c_tls->dbg.is_failed = true; 1710 #endif /* ! NDEBUG */ 1711 return mhd_SOCKET_ERR_TLS; 1712 } 1713 1714 1715 /* ** TLS connection information ** */ 1716 1717 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1718 MHD_FN_PAR_OUT_ (2) void 1719 mhd_tls_open_conn_get_tls_sess ( 1720 struct mhd_TlsOpenConnData *restrict c_tls, 1721 union MHD_ConnInfoDynamicTlsSess *restrict tls_sess_out) 1722 { 1723 tls_sess_out->v_openssl_session = c_tls->sess; 1724 } 1725 1726 1727 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ 1728 MHD_FN_PAR_OUT_ (2) bool 1729 mhd_tls_open_conn_get_tls_ver (struct mhd_TlsOpenConnData *restrict c_tls, 1730 struct mhd_StctTlsVersion *restrict tls_ver_out) 1731 { 1732 int openssl_tls_ver; 1733 1734 mhd_assert (c_tls->dbg.is_tls_handshake_completed); 1735 1736 openssl_tls_ver = SSL_version (c_tls->sess); 1737 switch (openssl_tls_ver) 1738 { 1739 case TLS1_VERSION: 1740 tls_ver_out->tls_ver = MHD_TLS_VERSION_1_0; 1741 break; 1742 case TLS1_1_VERSION: 1743 tls_ver_out->tls_ver = MHD_TLS_VERSION_1_1; 1744 break; 1745 case TLS1_2_VERSION: 1746 tls_ver_out->tls_ver = MHD_TLS_VERSION_1_2; 1747 break; 1748 case TLS1_3_VERSION: 1749 tls_ver_out->tls_ver = MHD_TLS_VERSION_1_3; 1750 break; 1751 case SSL3_VERSION: 1752 default: 1753 tls_ver_out->tls_ver = MHD_TLS_VERSION_UNKNOWN; 1754 break; 1755 } 1756 1757 return true; 1758 } 1759 1760 1761 MHD_INTERNAL MHD_FN_PAR_NONNULL_ALL_ enum mhd_TlsAlpnProt 1762 mhd_tls_open_conn_get_alpn_prot (struct mhd_TlsOpenConnData *restrict c_tls) 1763 { 1764 const unsigned char *sel_prot; 1765 unsigned int sel_prot_len; 1766 1767 SSL_get0_alpn_selected (c_tls->sess, 1768 &sel_prot, 1769 &sel_prot_len); 1770 1771 #ifndef OPENSSL_NO_NEXTPROTONEG 1772 if ((NULL == sel_prot) 1773 || (0 == sel_prot_len)) 1774 { 1775 SSL_get0_next_proto_negotiated (c_tls->sess, 1776 &sel_prot, 1777 &sel_prot_len); 1778 } 1779 #endif /* ! OPENSSL_NO_NEXTPROTONEG */ 1780 1781 mhd_assert (sel_prot_len == (size_t)sel_prot_len); 1782 1783 return mhd_tls_alpn_decode_n ((size_t)sel_prot_len, 1784 sel_prot); 1785 }