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