1/* 2 * SSL server demonstration program using fork() for handling multiple clients 3 * 4 * Copyright The Mbed TLS Contributors 5 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6 */ 7 8#include "mbedtls/build_info.h" 9 10#include "mbedtls/platform.h" 11 12#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) || \ 13 !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_SRV_C) || \ 14 !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_RSA_C) || \ 15 !defined(MBEDTLS_CTR_DRBG_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ 16 !defined(MBEDTLS_TIMING_C) || !defined(MBEDTLS_FS_IO) || \ 17 !defined(MBEDTLS_PEM_PARSE_C) 18int main(int argc, char *argv[]) 19{ 20 ((void) argc); 21 ((void) argv); 22 23 mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C " 24 "and/or MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_SRV_C and/or " 25 "MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or " 26 "MBEDTLS_CTR_DRBG_C and/or MBEDTLS_X509_CRT_PARSE_C and/or " 27 "MBEDTLS_TIMING_C and/or MBEDTLS_PEM_PARSE_C not defined.\n"); 28 mbedtls_exit(0); 29} 30#elif defined(_WIN32) 31int main(void) 32{ 33 mbedtls_printf("_WIN32 defined. This application requires fork() and signals " 34 "to work correctly.\n"); 35 mbedtls_exit(0); 36} 37#else 38 39#include "mbedtls/entropy.h" 40#include "mbedtls/ctr_drbg.h" 41#include "test/certs.h" 42#include "mbedtls/x509.h" 43#include "mbedtls/ssl.h" 44#include "mbedtls/net_sockets.h" 45#include "mbedtls/timing.h" 46 47#include <string.h> 48#include <signal.h> 49 50#if !defined(_MSC_VER) || defined(EFIX64) || defined(EFI32) 51#include <unistd.h> 52#endif 53 54#define HTTP_RESPONSE \ 55 "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \ 56 "<h2>Mbed TLS Test Server</h2>\r\n" \ 57 "<p>Successful connection using: %s</p>\r\n" 58 59#define DEBUG_LEVEL 0 60 61 62static void my_debug(void *ctx, int level, 63 const char *file, int line, 64 const char *str) 65{ 66 ((void) level); 67 68 mbedtls_fprintf((FILE *) ctx, "%s:%04d: %s", file, line, str); 69 fflush((FILE *) ctx); 70} 71 72int main(void) 73{ 74 int ret = 1, len, cnt = 0, pid; 75 int exit_code = MBEDTLS_EXIT_FAILURE; 76 mbedtls_net_context listen_fd, client_fd; 77 unsigned char buf[1024]; 78 const char *pers = "ssl_fork_server"; 79 80 mbedtls_entropy_context entropy; 81 mbedtls_ctr_drbg_context ctr_drbg; 82 mbedtls_ssl_context ssl; 83 mbedtls_ssl_config conf; 84 mbedtls_x509_crt srvcert; 85 mbedtls_pk_context pkey; 86 87 mbedtls_net_init(&listen_fd); 88 mbedtls_net_init(&client_fd); 89 mbedtls_ssl_init(&ssl); 90 mbedtls_ssl_config_init(&conf); 91 mbedtls_entropy_init(&entropy); 92 mbedtls_pk_init(&pkey); 93 mbedtls_x509_crt_init(&srvcert); 94 mbedtls_ctr_drbg_init(&ctr_drbg); 95 96#if defined(MBEDTLS_USE_PSA_CRYPTO) 97 psa_status_t status = psa_crypto_init(); 98 if (status != PSA_SUCCESS) { 99 mbedtls_fprintf(stderr, "Failed to initialize PSA Crypto implementation: %d\n", 100 (int) status); 101 goto exit; 102 } 103#endif /* MBEDTLS_USE_PSA_CRYPTO */ 104 105 signal(SIGCHLD, SIG_IGN); 106 107 /* 108 * 0. Initial seeding of the RNG 109 */ 110 mbedtls_printf("\n . Initial seeding of the random generator..."); 111 fflush(stdout); 112 113 if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, 114 (const unsigned char *) pers, 115 strlen(pers))) != 0) { 116 mbedtls_printf(" failed! mbedtls_ctr_drbg_seed returned %d\n\n", ret); 117 goto exit; 118 } 119 120 mbedtls_printf(" ok\n"); 121 122 /* 123 * 1. Load the certificates and private RSA key 124 */ 125 mbedtls_printf(" . Loading the server cert. and key..."); 126 fflush(stdout); 127 128 /* 129 * This demonstration program uses embedded test certificates. 130 * Instead, you may want to use mbedtls_x509_crt_parse_file() to read the 131 * server and CA certificates, as well as mbedtls_pk_parse_keyfile(). 132 */ 133 ret = mbedtls_x509_crt_parse(&srvcert, (const unsigned char *) mbedtls_test_srv_crt, 134 mbedtls_test_srv_crt_len); 135 if (ret != 0) { 136 mbedtls_printf(" failed! mbedtls_x509_crt_parse returned %d\n\n", ret); 137 goto exit; 138 } 139 140 ret = mbedtls_x509_crt_parse(&srvcert, (const unsigned char *) mbedtls_test_cas_pem, 141 mbedtls_test_cas_pem_len); 142 if (ret != 0) { 143 mbedtls_printf(" failed! mbedtls_x509_crt_parse returned %d\n\n", ret); 144 goto exit; 145 } 146 147 ret = mbedtls_pk_parse_key(&pkey, (const unsigned char *) mbedtls_test_srv_key, 148 mbedtls_test_srv_key_len, NULL, 0, 149 mbedtls_ctr_drbg_random, &ctr_drbg); 150 if (ret != 0) { 151 mbedtls_printf(" failed! mbedtls_pk_parse_key returned %d\n\n", ret); 152 goto exit; 153 } 154 155 mbedtls_printf(" ok\n"); 156 157 /* 158 * 1b. Prepare SSL configuration 159 */ 160 mbedtls_printf(" . Configuring SSL..."); 161 fflush(stdout); 162 163 if ((ret = mbedtls_ssl_config_defaults(&conf, 164 MBEDTLS_SSL_IS_SERVER, 165 MBEDTLS_SSL_TRANSPORT_STREAM, 166 MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { 167 mbedtls_printf(" failed! mbedtls_ssl_config_defaults returned %d\n\n", ret); 168 goto exit; 169 } 170 171 mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg); 172 mbedtls_ssl_conf_dbg(&conf, my_debug, stdout); 173 174 mbedtls_ssl_conf_ca_chain(&conf, srvcert.next, NULL); 175 if ((ret = mbedtls_ssl_conf_own_cert(&conf, &srvcert, &pkey)) != 0) { 176 mbedtls_printf(" failed! mbedtls_ssl_conf_own_cert returned %d\n\n", ret); 177 goto exit; 178 } 179 180 mbedtls_printf(" ok\n"); 181 182 /* 183 * 2. Setup the listening TCP socket 184 */ 185 mbedtls_printf(" . Bind on https://localhost:4433/ ..."); 186 fflush(stdout); 187 188 if ((ret = mbedtls_net_bind(&listen_fd, NULL, "4433", MBEDTLS_NET_PROTO_TCP)) != 0) { 189 mbedtls_printf(" failed! mbedtls_net_bind returned %d\n\n", ret); 190 goto exit; 191 } 192 193 mbedtls_printf(" ok\n"); 194 195 while (1) { 196 /* 197 * 3. Wait until a client connects 198 */ 199 mbedtls_net_init(&client_fd); 200 mbedtls_ssl_init(&ssl); 201 202 mbedtls_printf(" . Waiting for a remote connection ...\n"); 203 fflush(stdout); 204 205 if ((ret = mbedtls_net_accept(&listen_fd, &client_fd, 206 NULL, 0, NULL)) != 0) { 207 mbedtls_printf(" failed! mbedtls_net_accept returned %d\n\n", ret); 208 goto exit; 209 } 210 211 /* 212 * 3.5. Forking server thread 213 */ 214 215 mbedtls_printf(" . Forking to handle connection ..."); 216 fflush(stdout); 217 218 pid = fork(); 219 220 if (pid < 0) { 221 mbedtls_printf(" failed! fork returned %d\n\n", pid); 222 goto exit; 223 } 224 225 if (pid != 0) { 226 mbedtls_printf(" ok\n"); 227 mbedtls_net_close(&client_fd); 228 229 if ((ret = mbedtls_ctr_drbg_reseed(&ctr_drbg, 230 (const unsigned char *) "parent", 231 6)) != 0) { 232 mbedtls_printf(" failed! mbedtls_ctr_drbg_reseed returned %d\n\n", ret); 233 goto exit; 234 } 235 236 continue; 237 } 238 239 mbedtls_net_close(&listen_fd); 240 241 pid = getpid(); 242 243 /* 244 * 4. Setup stuff 245 */ 246 mbedtls_printf("pid %d: Setting up the SSL data.\n", pid); 247 fflush(stdout); 248 249 if ((ret = mbedtls_ctr_drbg_reseed(&ctr_drbg, 250 (const unsigned char *) "child", 251 5)) != 0) { 252 mbedtls_printf( 253 "pid %d: SSL setup failed! mbedtls_ctr_drbg_reseed returned %d\n\n", 254 pid, ret); 255 goto exit; 256 } 257 258 if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) { 259 mbedtls_printf( 260 "pid %d: SSL setup failed! mbedtls_ssl_setup returned %d\n\n", 261 pid, ret); 262 goto exit; 263 } 264 265 mbedtls_ssl_set_bio(&ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, NULL); 266 267 mbedtls_printf("pid %d: SSL setup ok\n", pid); 268 269 /* 270 * 5. Handshake 271 */ 272 mbedtls_printf("pid %d: Performing the SSL/TLS handshake.\n", pid); 273 fflush(stdout); 274 275 while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) { 276 if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { 277 mbedtls_printf( 278 "pid %d: SSL handshake failed! mbedtls_ssl_handshake returned %d\n\n", 279 pid, ret); 280 goto exit; 281 } 282 } 283 284 mbedtls_printf("pid %d: SSL handshake ok\n", pid); 285 286 /* 287 * 6. Read the HTTP Request 288 */ 289 mbedtls_printf("pid %d: Start reading from client.\n", pid); 290 fflush(stdout); 291 292 do { 293 len = sizeof(buf) - 1; 294 memset(buf, 0, sizeof(buf)); 295 ret = mbedtls_ssl_read(&ssl, buf, len); 296 297 if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) { 298 continue; 299 } 300 301 if (ret <= 0) { 302 switch (ret) { 303 case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: 304 mbedtls_printf("pid %d: connection was closed gracefully\n", pid); 305 break; 306 307 case MBEDTLS_ERR_NET_CONN_RESET: 308 mbedtls_printf("pid %d: connection was reset by peer\n", pid); 309 break; 310 311 default: 312 mbedtls_printf("pid %d: mbedtls_ssl_read returned %d\n", pid, ret); 313 break; 314 } 315 316 break; 317 } 318 319 len = ret; 320 mbedtls_printf("pid %d: %d bytes read\n\n%s", pid, len, (char *) buf); 321 322 if (ret > 0) { 323 break; 324 } 325 } while (1); 326 327 /* 328 * 7. Write the 200 Response 329 */ 330 mbedtls_printf("pid %d: Start writing to client.\n", pid); 331 fflush(stdout); 332 333 len = sprintf((char *) buf, HTTP_RESPONSE, 334 mbedtls_ssl_get_ciphersuite(&ssl)); 335 336 while (cnt++ < 100) { 337 while ((ret = mbedtls_ssl_write(&ssl, buf, len)) <= 0) { 338 if (ret == MBEDTLS_ERR_NET_CONN_RESET) { 339 mbedtls_printf( 340 "pid %d: Write failed! peer closed the connection\n\n", pid); 341 goto exit; 342 } 343 344 if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { 345 mbedtls_printf( 346 "pid %d: Write failed! mbedtls_ssl_write returned %d\n\n", 347 pid, ret); 348 goto exit; 349 } 350 } 351 len = ret; 352 mbedtls_printf("pid %d: %d bytes written\n\n%s\n", pid, len, (char *) buf); 353 354 mbedtls_net_usleep(1000000); 355 } 356 357 mbedtls_ssl_close_notify(&ssl); 358 goto exit; 359 } 360 361 exit_code = MBEDTLS_EXIT_SUCCESS; 362 363exit: 364 mbedtls_net_free(&client_fd); 365 mbedtls_net_free(&listen_fd); 366 mbedtls_x509_crt_free(&srvcert); 367 mbedtls_pk_free(&pkey); 368 mbedtls_ssl_free(&ssl); 369 mbedtls_ssl_config_free(&conf); 370 mbedtls_ctr_drbg_free(&ctr_drbg); 371 mbedtls_entropy_free(&entropy); 372#if defined(MBEDTLS_USE_PSA_CRYPTO) 373 mbedtls_psa_crypto_free(); 374#endif /* MBEDTLS_USE_PSA_CRYPTO */ 375 376 mbedtls_exit(exit_code); 377} 378#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && 379 MBEDTLS_SSL_TLS_C && MBEDTLS_SSL_SRV_C && MBEDTLS_NET_C && 380 MBEDTLS_RSA_C && MBEDTLS_CTR_DRBG_C && MBEDTLS_PEM_PARSE_C && 381 ! _WIN32 */ 382