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