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