blob: 416d4bf18667c11d5b99d3277433f8713db2fed4 [file] [log] [blame]
Paul Bakker896ac222011-05-20 12:33:05 +00001/*
Paul Bakkercb79ae0b2011-05-20 12:44:16 +00002 * SSL server demonstration program using fork() for handling multiple clients
Paul Bakker896ac222011-05-20 12:33:05 +00003 *
Paul Bakkercce9d772011-11-18 14:26:47 +00004 * Copyright (C) 2006-2011, Brainspark B.V.
Paul Bakker896ac222011-05-20 12:33:05 +00005 *
6 * This file is part of PolarSSL (http://www.polarssl.org)
7 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
8 *
9 * All rights reserved.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 */
25
26#ifndef _CRT_SECURE_NO_DEPRECATE
27#define _CRT_SECURE_NO_DEPRECATE 1
28#endif
29
Paul Bakkercce9d772011-11-18 14:26:47 +000030#if defined(_WIN32)
Paul Bakker896ac222011-05-20 12:33:05 +000031#include <windows.h>
32#endif
33
34#include <string.h>
35#include <stdlib.h>
36#include <stdio.h>
37#include <unistd.h>
38#include <signal.h>
39
Paul Bakker5690efc2011-05-26 13:16:06 +000040#include "polarssl/config.h"
41
Paul Bakker508ad5a2011-12-04 17:09:26 +000042#include "polarssl/entropy.h"
43#include "polarssl/ctr_drbg.h"
Paul Bakker896ac222011-05-20 12:33:05 +000044#include "polarssl/certs.h"
45#include "polarssl/x509.h"
46#include "polarssl/ssl.h"
47#include "polarssl/net.h"
48#include "polarssl/timing.h"
49
50#define HTTP_RESPONSE \
51 "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \
52 "<h2>PolarSSL Test Server</h2>\r\n" \
53 "<p>Successful connection using: %s</p>\r\n"
54
Paul Bakkerb892b132011-10-12 09:19:43 +000055#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_CERTS_C) || \
Paul Bakker508ad5a2011-12-04 17:09:26 +000056 !defined(POLARSSL_ENTROPY_C) || !defined(POLARSSL_SSL_TLS_C) || \
Paul Bakkerb892b132011-10-12 09:19:43 +000057 !defined(POLARSSL_SSL_SRV_C) || !defined(POLARSSL_NET_C) || \
Paul Bakker508ad5a2011-12-04 17:09:26 +000058 !defined(POLARSSL_RSA_C) || !defined(POLARSSL_CTR_DRBG_C)
Paul Bakkercce9d772011-11-18 14:26:47 +000059int main( int argc, char *argv[] )
Paul Bakkerb892b132011-10-12 09:19:43 +000060{
Paul Bakkercce9d772011-11-18 14:26:47 +000061 ((void) argc);
62 ((void) argv);
63
Paul Bakker508ad5a2011-12-04 17:09:26 +000064 printf("POLARSSL_BIGNUM_C and/or POLARSSL_CERTS_C and/or POLARSSL_ENTROPY_C "
Paul Bakkerb892b132011-10-12 09:19:43 +000065 "and/or POLARSSL_SSL_TLS_C and/or POLARSSL_SSL_SRV_C and/or "
Paul Bakker508ad5a2011-12-04 17:09:26 +000066 "POLARSSL_NET_C and/or POLARSSL_RSA_C and/or "
67 "POLARSSL_CTR_DRBG_C not defined.\n");
Paul Bakkerb892b132011-10-12 09:19:43 +000068 return( 0 );
69}
Paul Bakkercce9d772011-11-18 14:26:47 +000070#elif defined(_WIN32)
71int main( int argc, char *argv[] )
Paul Bakkerb892b132011-10-12 09:19:43 +000072{
Paul Bakkercce9d772011-11-18 14:26:47 +000073 ((void) argc);
74 ((void) argv);
75
76 printf("_WIN32 defined. This application requires fork() and signals "
Paul Bakkerb892b132011-10-12 09:19:43 +000077 "to work correctly.\n");
78 return( 0 );
79}
80#else
Paul Bakker896ac222011-05-20 12:33:05 +000081/*
82 * Computing a "safe" DH-1024 prime can take a very
83 * long time, so a precomputed value is provided below.
84 * You may run dh_genprime to generate a new value.
85 */
86char *my_dhm_P =
87 "E4004C1F94182000103D883A448B3F80" \
88 "2CE4B44A83301270002C20D0321CFD00" \
89 "11CCEF784C26A400F43DFB901BCA7538" \
90 "F2C6B176001CF5A0FD16D2C48B1D0C1C" \
91 "F6AC8E1DA6BCC3B4E1F96B0564965300" \
92 "FFA1D0B601EB2800F489AA512C4B248C" \
93 "01F76949A60BB7F00A40B1EAB64BDD48" \
94 "E8A700D60B7F1200FA8E77B0A979DABF";
95
96char *my_dhm_G = "4";
97
98/*
99 * Sorted by order of preference
100 */
101int my_ciphersuites[] =
102{
103 SSL_EDH_RSA_AES_256_SHA,
104 SSL_EDH_RSA_CAMELLIA_256_SHA,
105 SSL_EDH_RSA_AES_128_SHA,
106 SSL_EDH_RSA_CAMELLIA_128_SHA,
107 SSL_EDH_RSA_DES_168_SHA,
108 SSL_RSA_AES_256_SHA,
109 SSL_RSA_CAMELLIA_256_SHA,
110 SSL_RSA_AES_128_SHA,
111 SSL_RSA_CAMELLIA_128_SHA,
112 SSL_RSA_DES_168_SHA,
113 SSL_RSA_RC4_128_SHA,
114 SSL_RSA_RC4_128_MD5,
115 0
116};
117
118#define DEBUG_LEVEL 0
119
120void my_debug( void *ctx, int level, const char *str )
121{
122 if( level < DEBUG_LEVEL )
123 {
124 fprintf( (FILE *) ctx, "%s", str );
125 fflush( (FILE *) ctx );
126 }
127}
128
129/*
130 * These session callbacks use a simple chained list
131 * to store and retrieve the session information.
132 */
133ssl_session *s_list_1st = NULL;
134ssl_session *cur, *prv;
135
136static int my_get_session( ssl_context *ssl )
137{
138 time_t t = time( NULL );
139
140 if( ssl->resume == 0 )
141 return( 1 );
142
143 cur = s_list_1st;
144 prv = NULL;
145
146 while( cur != NULL )
147 {
148 prv = cur;
149 cur = cur->next;
150
151 if( ssl->timeout != 0 && t - prv->start > ssl->timeout )
152 continue;
153
154 if( ssl->session->ciphersuite != prv->ciphersuite ||
155 ssl->session->length != prv->length )
156 continue;
157
158 if( memcmp( ssl->session->id, prv->id, prv->length ) != 0 )
159 continue;
160
161 memcpy( ssl->session->master, prv->master, 48 );
162 return( 0 );
163 }
164
165 return( 1 );
166}
167
168static int my_set_session( ssl_context *ssl )
169{
170 time_t t = time( NULL );
171
172 cur = s_list_1st;
173 prv = NULL;
174
175 while( cur != NULL )
176 {
177 if( ssl->timeout != 0 && t - cur->start > ssl->timeout )
178 break; /* expired, reuse this slot */
179
180 if( memcmp( ssl->session->id, cur->id, cur->length ) == 0 )
181 break; /* client reconnected */
182
183 prv = cur;
184 cur = cur->next;
185 }
186
187 if( cur == NULL )
188 {
189 cur = (ssl_session *) malloc( sizeof( ssl_session ) );
190 if( cur == NULL )
191 return( 1 );
192
193 if( prv == NULL )
194 s_list_1st = cur;
195 else prv->next = cur;
196 }
197
198 memcpy( cur, ssl->session, sizeof( ssl_session ) );
199
200 return( 0 );
201}
202
Paul Bakkercce9d772011-11-18 14:26:47 +0000203int main( int argc, char *argv[] )
Paul Bakker896ac222011-05-20 12:33:05 +0000204{
205 int ret, len, cnt = 0, pid;
206 int listen_fd;
207 int client_fd;
208 unsigned char buf[1024];
Paul Bakker508ad5a2011-12-04 17:09:26 +0000209 char *pers = "ssl_fork_server";
Paul Bakker896ac222011-05-20 12:33:05 +0000210
Paul Bakker508ad5a2011-12-04 17:09:26 +0000211 entropy_context entropy;
212 ctr_drbg_context ctr_drbg;
Paul Bakker896ac222011-05-20 12:33:05 +0000213 ssl_context ssl;
214 ssl_session ssn;
215 x509_cert srvcert;
216 rsa_context rsa;
217
Paul Bakkercce9d772011-11-18 14:26:47 +0000218 ((void) argc);
219 ((void) argv);
220
Paul Bakker896ac222011-05-20 12:33:05 +0000221 signal( SIGCHLD, SIG_IGN );
222
223 /*
Paul Bakker508ad5a2011-12-04 17:09:26 +0000224 * 0. Initial seeding of the RNG
225 */
226 printf( "\n . Initial seeding of the random generator..." );
227 fflush( stdout );
228
229 entropy_init( &entropy );
230 if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,
231 (unsigned char *) pers, strlen( pers ) ) ) != 0 )
232 {
233 printf( " failed\n ! ctr_drbg_init returned %d\n", ret );
234 goto exit;
235 }
236
237 printf( " ok\n" );
238
239 /*
Paul Bakker896ac222011-05-20 12:33:05 +0000240 * 1. Load the certificates and private RSA key
241 */
Paul Bakker508ad5a2011-12-04 17:09:26 +0000242 printf( " . Loading the server cert. and key..." );
Paul Bakker896ac222011-05-20 12:33:05 +0000243 fflush( stdout );
244
245 memset( &srvcert, 0, sizeof( x509_cert ) );
246
247 /*
248 * This demonstration program uses embedded test certificates.
249 * Instead, you may want to use x509parse_crtfile() to read the
250 * server and CA certificates, as well as x509parse_keyfile().
251 */
252 ret = x509parse_crt( &srvcert, (unsigned char *) test_srv_crt,
Paul Bakker69e095c2011-12-10 21:55:01 +0000253 strlen( test_srv_crt ) );
Paul Bakker896ac222011-05-20 12:33:05 +0000254 if( ret != 0 )
255 {
256 printf( " failed\n ! x509parse_crt returned %d\n\n", ret );
257 goto exit;
258 }
259
260 ret = x509parse_crt( &srvcert, (unsigned char *) test_ca_crt,
Paul Bakker69e095c2011-12-10 21:55:01 +0000261 strlen( test_ca_crt ) );
Paul Bakker896ac222011-05-20 12:33:05 +0000262 if( ret != 0 )
263 {
264 printf( " failed\n ! x509parse_crt returned %d\n\n", ret );
265 goto exit;
266 }
267
268 rsa_init( &rsa, RSA_PKCS_V15, 0 );
269 ret = x509parse_key( &rsa, (unsigned char *) test_srv_key,
270 strlen( test_srv_key ), NULL, 0 );
271 if( ret != 0 )
272 {
273 printf( " failed\n ! x509parse_key returned %d\n\n", ret );
274 goto exit;
275 }
276
277 printf( " ok\n" );
278
279 /*
280 * 2. Setup the listening TCP socket
281 */
282 printf( " . Bind on https://localhost:4433/ ..." );
283 fflush( stdout );
284
285 if( ( ret = net_bind( &listen_fd, NULL, 4433 ) ) != 0 )
286 {
287 printf( " failed\n ! net_bind returned %d\n\n", ret );
288 goto exit;
289 }
290
291 printf( " ok\n" );
292
293 while( 1 )
294 {
295 /*
296 * 3. Wait until a client connects
297 */
298 client_fd = -1;
299 memset( &ssl, 0, sizeof( ssl ) );
300
301 printf( " . Waiting for a remote connection ..." );
302 fflush( stdout );
303
304 if( ( ret = net_accept( listen_fd, &client_fd, NULL ) ) != 0 )
305 {
306 printf( " failed\n ! net_accept returned %d\n\n", ret );
307 goto exit;
308 }
309
310 printf( " ok\n" );
311
312 /*
313 * 3.5. Forking server thread
314 */
315
316 pid = fork();
317
318 printf( " . Forking to handle connection ..." );
319 fflush( stdout );
320
321 if( pid < 0 )
322 {
323 printf(" failed\n ! fork returned %d\n\n", pid );
324 goto exit;
325 }
326
327 printf( " ok\n" );
328
329 if( pid != 0 )
330 {
Paul Bakker508ad5a2011-12-04 17:09:26 +0000331 if( ( ret = ctr_drbg_reseed( &ctr_drbg,
332 (unsigned char* ) "parent", 6 ) ) != 0 )
333 {
334 printf( " failed\n ! ctr_drbg_reseed returned %d\n", ret );
335 goto exit;
336 }
337
Paul Bakker896ac222011-05-20 12:33:05 +0000338 close( client_fd );
339 continue;
340 }
341
342 close( listen_fd );
343
344 /*
345 * 4. Setup stuff
346 */
Paul Bakker508ad5a2011-12-04 17:09:26 +0000347 printf( " . Setting up the SSL data...." );
Paul Bakker896ac222011-05-20 12:33:05 +0000348 fflush( stdout );
349
Paul Bakker508ad5a2011-12-04 17:09:26 +0000350 if( ( ret = ctr_drbg_reseed( &ctr_drbg,
351 (unsigned char *) "child", 5 ) ) != 0 )
352 {
353 printf( " failed\n ! ctr_drbg_reseed returned %d\n", ret );
354 goto exit;
355 }
356
Paul Bakker896ac222011-05-20 12:33:05 +0000357 if( ( ret = ssl_init( &ssl ) ) != 0 )
358 {
359 printf( " failed\n ! ssl_init returned %d\n\n", ret );
360 goto exit;
361 }
362
363 printf( " ok\n" );
364
365 ssl_set_endpoint( &ssl, SSL_IS_SERVER );
366 ssl_set_authmode( &ssl, SSL_VERIFY_NONE );
367
Paul Bakker508ad5a2011-12-04 17:09:26 +0000368 ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
Paul Bakker896ac222011-05-20 12:33:05 +0000369 ssl_set_dbg( &ssl, my_debug, stdout );
370 ssl_set_bio( &ssl, net_recv, &client_fd,
371 net_send, &client_fd );
372 ssl_set_scb( &ssl, my_get_session,
373 my_set_session );
374
375 ssl_set_ciphersuites( &ssl, my_ciphersuites );
376 ssl_set_session( &ssl, 1, 0, &ssn );
377
378 memset( &ssn, 0, sizeof( ssl_session ) );
379
380 ssl_set_ca_chain( &ssl, srvcert.next, NULL, NULL );
381 ssl_set_own_cert( &ssl, &srvcert, &rsa );
Paul Bakker48916f92012-09-16 19:57:18 +0000382#if defined(POLARSSL_DHM_C)
Paul Bakker896ac222011-05-20 12:33:05 +0000383 ssl_set_dh_param( &ssl, my_dhm_P, my_dhm_G );
Paul Bakker48916f92012-09-16 19:57:18 +0000384#endif
Paul Bakker896ac222011-05-20 12:33:05 +0000385
386 /*
387 * 5. Handshake
388 */
389 printf( " . Performing the SSL/TLS handshake..." );
390 fflush( stdout );
391
392 while( ( ret = ssl_handshake( &ssl ) ) != 0 )
393 {
394 if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
395 {
396 printf( " failed\n ! ssl_handshake returned %d\n\n", ret );
397 goto exit;
398 }
399 }
400
401 printf( " ok\n" );
402
403 /*
404 * 6. Read the HTTP Request
405 */
406 printf( " < Read from client:" );
407 fflush( stdout );
408
409 do
410 {
411 len = sizeof( buf ) - 1;
412 memset( buf, 0, sizeof( buf ) );
413 ret = ssl_read( &ssl, buf, len );
414
415 if( ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE )
416 continue;
417
418 if( ret <= 0 )
419 {
420 switch( ret )
421 {
422 case POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY:
423 printf( " connection was closed gracefully\n" );
424 break;
425
426 case POLARSSL_ERR_NET_CONN_RESET:
427 printf( " connection was reset by peer\n" );
428 break;
429
430 default:
431 printf( " ssl_read returned %d\n", ret );
432 break;
433 }
434
435 break;
436 }
437
438 len = ret;
439 printf( " %d bytes read\n\n%s", len, (char *) buf );
440 }
441 while( 0 );
442
443 /*
444 * 7. Write the 200 Response
445 */
446 printf( " > Write to client:" );
447 fflush( stdout );
448
449 len = sprintf( (char *) buf, HTTP_RESPONSE,
450 ssl_get_ciphersuite( &ssl ) );
451
452 while( cnt < 100 )
453 {
454 while( ( ret = ssl_write( &ssl, buf, len ) ) <= 0 )
455 {
456 if( ret == POLARSSL_ERR_NET_CONN_RESET )
457 {
458 printf( " failed\n ! peer closed the connection\n\n" );
459 goto exit;
460 }
461
462 if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
463 {
464 printf( " failed\n ! ssl_write returned %d\n\n", ret );
465 goto exit;
466 }
467 }
468 len = ret;
469 printf( " %d bytes written\n\n%s\n", len, (char *) buf );
470
471 m_sleep( 1000 );
472 }
473
474 ssl_close_notify( &ssl );
475 goto exit;
476 }
477
478exit:
479
480 net_close( client_fd );
481 x509_free( &srvcert );
482 rsa_free( &rsa );
483 ssl_free( &ssl );
484
485 cur = s_list_1st;
486 while( cur != NULL )
487 {
488 prv = cur;
489 cur = cur->next;
490 memset( prv, 0, sizeof( ssl_session ) );
491 free( prv );
492 }
493
494 memset( &ssl, 0, sizeof( ssl_context ) );
495
Paul Bakkercce9d772011-11-18 14:26:47 +0000496#if defined(_WIN32)
Paul Bakker896ac222011-05-20 12:33:05 +0000497 printf( " Press Enter to exit this program.\n" );
498 fflush( stdout ); getchar();
499#endif
500
501 return( ret );
502}
Paul Bakker508ad5a2011-12-04 17:09:26 +0000503#endif /* POLARSSL_BIGNUM_C && POLARSSL_CERTS_C && POLARSSL_ENTROPY_C &&
Paul Bakker5690efc2011-05-26 13:16:06 +0000504 POLARSSL_SSL_TLS_C && POLARSSL_SSL_SRV_C && POLARSSL_NET_C &&
Paul Bakker508ad5a2011-12-04 17:09:26 +0000505 POLARSSL_RSA_C && POLARSSL_CTR_DRBG_C */