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