ssl_fork_server.c 14 KB

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