blob: 881a68e4038ef49191e443afc1387d015f081a5a [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 );
382 ssl_set_dh_param( &ssl, my_dhm_P, my_dhm_G );
383
384 /*
385 * 5. Handshake
386 */
387 printf( " . Performing the SSL/TLS handshake..." );
388 fflush( stdout );
389
390 while( ( ret = ssl_handshake( &ssl ) ) != 0 )
391 {
392 if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
393 {
394 printf( " failed\n ! ssl_handshake returned %d\n\n", ret );
395 goto exit;
396 }
397 }
398
399 printf( " ok\n" );
400
401 /*
402 * 6. Read the HTTP Request
403 */
404 printf( " < Read from client:" );
405 fflush( stdout );
406
407 do
408 {
409 len = sizeof( buf ) - 1;
410 memset( buf, 0, sizeof( buf ) );
411 ret = ssl_read( &ssl, buf, len );
412
413 if( ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE )
414 continue;
415
416 if( ret <= 0 )
417 {
418 switch( ret )
419 {
420 case POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY:
421 printf( " connection was closed gracefully\n" );
422 break;
423
424 case POLARSSL_ERR_NET_CONN_RESET:
425 printf( " connection was reset by peer\n" );
426 break;
427
428 default:
429 printf( " ssl_read returned %d\n", ret );
430 break;
431 }
432
433 break;
434 }
435
436 len = ret;
437 printf( " %d bytes read\n\n%s", len, (char *) buf );
438 }
439 while( 0 );
440
441 /*
442 * 7. Write the 200 Response
443 */
444 printf( " > Write to client:" );
445 fflush( stdout );
446
447 len = sprintf( (char *) buf, HTTP_RESPONSE,
448 ssl_get_ciphersuite( &ssl ) );
449
450 while( cnt < 100 )
451 {
452 while( ( ret = ssl_write( &ssl, buf, len ) ) <= 0 )
453 {
454 if( ret == POLARSSL_ERR_NET_CONN_RESET )
455 {
456 printf( " failed\n ! peer closed the connection\n\n" );
457 goto exit;
458 }
459
460 if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
461 {
462 printf( " failed\n ! ssl_write returned %d\n\n", ret );
463 goto exit;
464 }
465 }
466 len = ret;
467 printf( " %d bytes written\n\n%s\n", len, (char *) buf );
468
469 m_sleep( 1000 );
470 }
471
472 ssl_close_notify( &ssl );
473 goto exit;
474 }
475
476exit:
477
478 net_close( client_fd );
479 x509_free( &srvcert );
480 rsa_free( &rsa );
481 ssl_free( &ssl );
482
483 cur = s_list_1st;
484 while( cur != NULL )
485 {
486 prv = cur;
487 cur = cur->next;
488 memset( prv, 0, sizeof( ssl_session ) );
489 free( prv );
490 }
491
492 memset( &ssl, 0, sizeof( ssl_context ) );
493
Paul Bakkercce9d772011-11-18 14:26:47 +0000494#if defined(_WIN32)
Paul Bakker896ac222011-05-20 12:33:05 +0000495 printf( " Press Enter to exit this program.\n" );
496 fflush( stdout ); getchar();
497#endif
498
499 return( ret );
500}
Paul Bakker508ad5a2011-12-04 17:09:26 +0000501#endif /* POLARSSL_BIGNUM_C && POLARSSL_CERTS_C && POLARSSL_ENTROPY_C &&
Paul Bakker5690efc2011-05-26 13:16:06 +0000502 POLARSSL_SSL_TLS_C && POLARSSL_SSL_SRV_C && POLARSSL_NET_C &&
Paul Bakker508ad5a2011-12-04 17:09:26 +0000503 POLARSSL_RSA_C && POLARSSL_CTR_DRBG_C */