blob: 9f76b4bfaa4e5ab6d9a2ba9ed07ee616be41b638 [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 *
4 * Copyright (C) 2006-2010, Brainspark B.V.
5 *
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
30#ifdef WIN32
31#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 Bakker896ac222011-05-20 12:33:05 +000042#include "polarssl/havege.h"
43#include "polarssl/certs.h"
44#include "polarssl/x509.h"
45#include "polarssl/ssl.h"
46#include "polarssl/net.h"
47#include "polarssl/timing.h"
48
49#define HTTP_RESPONSE \
50 "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \
51 "<h2>PolarSSL Test Server</h2>\r\n" \
52 "<p>Successful connection using: %s</p>\r\n"
53
54/*
55 * Computing a "safe" DH-1024 prime can take a very
56 * long time, so a precomputed value is provided below.
57 * You may run dh_genprime to generate a new value.
58 */
59char *my_dhm_P =
60 "E4004C1F94182000103D883A448B3F80" \
61 "2CE4B44A83301270002C20D0321CFD00" \
62 "11CCEF784C26A400F43DFB901BCA7538" \
63 "F2C6B176001CF5A0FD16D2C48B1D0C1C" \
64 "F6AC8E1DA6BCC3B4E1F96B0564965300" \
65 "FFA1D0B601EB2800F489AA512C4B248C" \
66 "01F76949A60BB7F00A40B1EAB64BDD48" \
67 "E8A700D60B7F1200FA8E77B0A979DABF";
68
69char *my_dhm_G = "4";
70
71/*
72 * Sorted by order of preference
73 */
74int my_ciphersuites[] =
75{
76 SSL_EDH_RSA_AES_256_SHA,
77 SSL_EDH_RSA_CAMELLIA_256_SHA,
78 SSL_EDH_RSA_AES_128_SHA,
79 SSL_EDH_RSA_CAMELLIA_128_SHA,
80 SSL_EDH_RSA_DES_168_SHA,
81 SSL_RSA_AES_256_SHA,
82 SSL_RSA_CAMELLIA_256_SHA,
83 SSL_RSA_AES_128_SHA,
84 SSL_RSA_CAMELLIA_128_SHA,
85 SSL_RSA_DES_168_SHA,
86 SSL_RSA_RC4_128_SHA,
87 SSL_RSA_RC4_128_MD5,
88 0
89};
90
91#define DEBUG_LEVEL 0
92
93void my_debug( void *ctx, int level, const char *str )
94{
95 if( level < DEBUG_LEVEL )
96 {
97 fprintf( (FILE *) ctx, "%s", str );
98 fflush( (FILE *) ctx );
99 }
100}
101
102/*
103 * These session callbacks use a simple chained list
104 * to store and retrieve the session information.
105 */
106ssl_session *s_list_1st = NULL;
107ssl_session *cur, *prv;
108
109static int my_get_session( ssl_context *ssl )
110{
111 time_t t = time( NULL );
112
113 if( ssl->resume == 0 )
114 return( 1 );
115
116 cur = s_list_1st;
117 prv = NULL;
118
119 while( cur != NULL )
120 {
121 prv = cur;
122 cur = cur->next;
123
124 if( ssl->timeout != 0 && t - prv->start > ssl->timeout )
125 continue;
126
127 if( ssl->session->ciphersuite != prv->ciphersuite ||
128 ssl->session->length != prv->length )
129 continue;
130
131 if( memcmp( ssl->session->id, prv->id, prv->length ) != 0 )
132 continue;
133
134 memcpy( ssl->session->master, prv->master, 48 );
135 return( 0 );
136 }
137
138 return( 1 );
139}
140
141static int my_set_session( ssl_context *ssl )
142{
143 time_t t = time( NULL );
144
145 cur = s_list_1st;
146 prv = NULL;
147
148 while( cur != NULL )
149 {
150 if( ssl->timeout != 0 && t - cur->start > ssl->timeout )
151 break; /* expired, reuse this slot */
152
153 if( memcmp( ssl->session->id, cur->id, cur->length ) == 0 )
154 break; /* client reconnected */
155
156 prv = cur;
157 cur = cur->next;
158 }
159
160 if( cur == NULL )
161 {
162 cur = (ssl_session *) malloc( sizeof( ssl_session ) );
163 if( cur == NULL )
164 return( 1 );
165
166 if( prv == NULL )
167 s_list_1st = cur;
168 else prv->next = cur;
169 }
170
171 memcpy( cur, ssl->session, sizeof( ssl_session ) );
172
173 return( 0 );
174}
175
Paul Bakker5690efc2011-05-26 13:16:06 +0000176#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_CERTS_C) || \
177 !defined(POLARSSL_HAVEGE_C) || !defined(POLARSSL_SSL_TLS_C) || \
178 !defined(POLARSSL_SSL_SRV_C) || !defined(POLARSSL_NET_C) || \
179 !defined(POLARSSL_RSA_C)
180int main( void )
181{
182 printf("POLARSSL_BIGNUM_C and/or POLARSSL_CERTS_C and/or POLARSSL_HAVEGE_C "
183 "and/or POLARSSL_SSL_TLS_C and/or POLARSSL_SSL_SRV_C and/or "
184 "POLARSSL_NET_C and/or POLARSSL_RSA_C not defined.\n");
185 return( 0 );
186}
187#else
Paul Bakker896ac222011-05-20 12:33:05 +0000188int main( void )
189{
190 int ret, len, cnt = 0, pid;
191 int listen_fd;
192 int client_fd;
193 unsigned char buf[1024];
194
195 havege_state hs;
196 ssl_context ssl;
197 ssl_session ssn;
198 x509_cert srvcert;
199 rsa_context rsa;
200
201 signal( SIGCHLD, SIG_IGN );
202
203 /*
204 * 1. Load the certificates and private RSA key
205 */
206 printf( "\n . Loading the server cert. and key..." );
207 fflush( stdout );
208
209 memset( &srvcert, 0, sizeof( x509_cert ) );
210
211 /*
212 * This demonstration program uses embedded test certificates.
213 * Instead, you may want to use x509parse_crtfile() to read the
214 * server and CA certificates, as well as x509parse_keyfile().
215 */
216 ret = x509parse_crt( &srvcert, (unsigned char *) test_srv_crt,
217 strlen( test_srv_crt ) );
218 if( ret != 0 )
219 {
220 printf( " failed\n ! x509parse_crt returned %d\n\n", ret );
221 goto exit;
222 }
223
224 ret = x509parse_crt( &srvcert, (unsigned char *) test_ca_crt,
225 strlen( test_ca_crt ) );
226 if( ret != 0 )
227 {
228 printf( " failed\n ! x509parse_crt returned %d\n\n", ret );
229 goto exit;
230 }
231
232 rsa_init( &rsa, RSA_PKCS_V15, 0 );
233 ret = x509parse_key( &rsa, (unsigned char *) test_srv_key,
234 strlen( test_srv_key ), NULL, 0 );
235 if( ret != 0 )
236 {
237 printf( " failed\n ! x509parse_key returned %d\n\n", ret );
238 goto exit;
239 }
240
241 printf( " ok\n" );
242
243 /*
244 * 2. Setup the listening TCP socket
245 */
246 printf( " . Bind on https://localhost:4433/ ..." );
247 fflush( stdout );
248
249 if( ( ret = net_bind( &listen_fd, NULL, 4433 ) ) != 0 )
250 {
251 printf( " failed\n ! net_bind returned %d\n\n", ret );
252 goto exit;
253 }
254
255 printf( " ok\n" );
256
257 while( 1 )
258 {
259 /*
260 * 3. Wait until a client connects
261 */
262 client_fd = -1;
263 memset( &ssl, 0, sizeof( ssl ) );
264
265 printf( " . Waiting for a remote connection ..." );
266 fflush( stdout );
267
268 if( ( ret = net_accept( listen_fd, &client_fd, NULL ) ) != 0 )
269 {
270 printf( " failed\n ! net_accept returned %d\n\n", ret );
271 goto exit;
272 }
273
274 printf( " ok\n" );
275
276 /*
277 * 3.5. Forking server thread
278 */
279
280 pid = fork();
281
282 printf( " . Forking to handle connection ..." );
283 fflush( stdout );
284
285 if( pid < 0 )
286 {
287 printf(" failed\n ! fork returned %d\n\n", pid );
288 goto exit;
289 }
290
291 printf( " ok\n" );
292
293 if( pid != 0 )
294 {
295 close( client_fd );
296 continue;
297 }
298
299 close( listen_fd );
300
301 /*
302 * 4. Setup stuff
303 */
304 printf( " . Setting up the RNG and SSL data...." );
305 fflush( stdout );
306
307 havege_init( &hs );
308
309 if( ( ret = ssl_init( &ssl ) ) != 0 )
310 {
311 printf( " failed\n ! ssl_init returned %d\n\n", ret );
312 goto exit;
313 }
314
315 printf( " ok\n" );
316
317 ssl_set_endpoint( &ssl, SSL_IS_SERVER );
318 ssl_set_authmode( &ssl, SSL_VERIFY_NONE );
319
320 ssl_set_rng( &ssl, havege_rand, &hs );
321 ssl_set_dbg( &ssl, my_debug, stdout );
322 ssl_set_bio( &ssl, net_recv, &client_fd,
323 net_send, &client_fd );
324 ssl_set_scb( &ssl, my_get_session,
325 my_set_session );
326
327 ssl_set_ciphersuites( &ssl, my_ciphersuites );
328 ssl_set_session( &ssl, 1, 0, &ssn );
329
330 memset( &ssn, 0, sizeof( ssl_session ) );
331
332 ssl_set_ca_chain( &ssl, srvcert.next, NULL, NULL );
333 ssl_set_own_cert( &ssl, &srvcert, &rsa );
334 ssl_set_dh_param( &ssl, my_dhm_P, my_dhm_G );
335
336 /*
337 * 5. Handshake
338 */
339 printf( " . Performing the SSL/TLS handshake..." );
340 fflush( stdout );
341
342 while( ( ret = ssl_handshake( &ssl ) ) != 0 )
343 {
344 if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
345 {
346 printf( " failed\n ! ssl_handshake returned %d\n\n", ret );
347 goto exit;
348 }
349 }
350
351 printf( " ok\n" );
352
353 /*
354 * 6. Read the HTTP Request
355 */
356 printf( " < Read from client:" );
357 fflush( stdout );
358
359 do
360 {
361 len = sizeof( buf ) - 1;
362 memset( buf, 0, sizeof( buf ) );
363 ret = ssl_read( &ssl, buf, len );
364
365 if( ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE )
366 continue;
367
368 if( ret <= 0 )
369 {
370 switch( ret )
371 {
372 case POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY:
373 printf( " connection was closed gracefully\n" );
374 break;
375
376 case POLARSSL_ERR_NET_CONN_RESET:
377 printf( " connection was reset by peer\n" );
378 break;
379
380 default:
381 printf( " ssl_read returned %d\n", ret );
382 break;
383 }
384
385 break;
386 }
387
388 len = ret;
389 printf( " %d bytes read\n\n%s", len, (char *) buf );
390 }
391 while( 0 );
392
393 /*
394 * 7. Write the 200 Response
395 */
396 printf( " > Write to client:" );
397 fflush( stdout );
398
399 len = sprintf( (char *) buf, HTTP_RESPONSE,
400 ssl_get_ciphersuite( &ssl ) );
401
402 while( cnt < 100 )
403 {
404 while( ( ret = ssl_write( &ssl, buf, len ) ) <= 0 )
405 {
406 if( ret == POLARSSL_ERR_NET_CONN_RESET )
407 {
408 printf( " failed\n ! peer closed the connection\n\n" );
409 goto exit;
410 }
411
412 if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
413 {
414 printf( " failed\n ! ssl_write returned %d\n\n", ret );
415 goto exit;
416 }
417 }
418 len = ret;
419 printf( " %d bytes written\n\n%s\n", len, (char *) buf );
420
421 m_sleep( 1000 );
422 }
423
424 ssl_close_notify( &ssl );
425 goto exit;
426 }
427
428exit:
429
430 net_close( client_fd );
431 x509_free( &srvcert );
432 rsa_free( &rsa );
433 ssl_free( &ssl );
434
435 cur = s_list_1st;
436 while( cur != NULL )
437 {
438 prv = cur;
439 cur = cur->next;
440 memset( prv, 0, sizeof( ssl_session ) );
441 free( prv );
442 }
443
444 memset( &ssl, 0, sizeof( ssl_context ) );
445
446#ifdef WIN32
447 printf( " Press Enter to exit this program.\n" );
448 fflush( stdout ); getchar();
449#endif
450
451 return( ret );
452}
Paul Bakker5690efc2011-05-26 13:16:06 +0000453#endif /* POLARSSL_BIGNUM_C && POLARSSL_CERTS_C && POLARSSL_HAVEGE_C &&
454 POLARSSL_SSL_TLS_C && POLARSSL_SSL_SRV_C && POLARSSL_NET_C &&
455 POLARSSL_RSA_C */