blob: 5076be398dfdf815448c2bc4479cdbf6a643d5b6 [file] [log] [blame]
Paul Bakkerb60b95f2012-09-25 09:05:17 +00001/*
2 * SSL client with options
3 *
4 * Copyright (C) 2006-2012, 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#if defined(_WIN32)
31#include <windows.h>
32#endif
33
34#include <string.h>
35#include <stdlib.h>
36#include <stdio.h>
37
38#include "polarssl/config.h"
39
40#include "polarssl/net.h"
41#include "polarssl/ssl.h"
42#include "polarssl/entropy.h"
43#include "polarssl/ctr_drbg.h"
44#include "polarssl/certs.h"
45#include "polarssl/x509.h"
46#include "polarssl/error.h"
47
Paul Bakker0a597072012-09-25 21:55:46 +000048#if defined(POLARSSL_SSL_CACHE_C)
49#include "polarssl/ssl_cache.h"
50#endif
51
Paul Bakkerb60b95f2012-09-25 09:05:17 +000052#define DFL_SERVER_PORT 4433
53#define DFL_REQUEST_PAGE "/"
54#define DFL_DEBUG_LEVEL 0
55#define DFL_CA_FILE ""
56#define DFL_CA_PATH ""
57#define DFL_CRT_FILE ""
58#define DFL_KEY_FILE ""
59#define DFL_FORCE_CIPHER 0
60#define DFL_RENEGOTIATION SSL_RENEGOTIATION_ENABLED
61#define DFL_ALLOW_LEGACY SSL_LEGACY_NO_RENEGOTIATION
Paul Bakker1d29fb52012-09-28 13:28:45 +000062#define DFL_MIN_VERSION -1
Paul Bakkerb60b95f2012-09-25 09:05:17 +000063
64#define HTTP_RESPONSE \
65 "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \
66 "<h2>PolarSSL Test Server</h2>\r\n" \
67 "<p>Successful connection using: %s</p>\r\n"
68
69/*
Paul Bakkerb60b95f2012-09-25 09:05:17 +000070 * global options
71 */
72struct options
73{
74 int server_port; /* port on which the ssl service runs */
75 int debug_level; /* level of debugging */
76 char *ca_file; /* the file with the CA certificate(s) */
77 char *ca_path; /* the path with the CA certificate(s) reside */
78 char *crt_file; /* the file with the client certificate */
79 char *key_file; /* the file with the client key */
80 int force_ciphersuite[2]; /* protocol/ciphersuite to use, or all */
81 int renegotiation; /* enable / disable renegotiation */
82 int allow_legacy; /* allow legacy renegotiation */
Paul Bakker1d29fb52012-09-28 13:28:45 +000083 int min_version; /* minimum protocol version accepted */
Paul Bakkerb60b95f2012-09-25 09:05:17 +000084} opt;
85
86void my_debug( void *ctx, int level, const char *str )
87{
88 if( level < opt.debug_level )
89 {
90 fprintf( (FILE *) ctx, "%s", str );
91 fflush( (FILE *) ctx );
92 }
93}
94
Paul Bakkerb60b95f2012-09-25 09:05:17 +000095#if defined(POLARSSL_FS_IO)
96#define USAGE_IO \
97 " ca_file=%%s default: \"\" (pre-loaded)\n" \
98 " ca_path=%%s default: \"\" (pre-loaded) (overrides ca_file)\n" \
99 " crt_file=%%s default: \"\" (pre-loaded)\n" \
100 " key_file=%%s default: \"\" (pre-loaded)\n"
101#else
102#define USAGE_IO \
103 " No file operations available (POLARSSL_FS_IO not defined)\n"
104#endif /* POLARSSL_FS_IO */
105
106#define USAGE \
107 "\n usage: ssl_server2 param=<>...\n" \
108 "\n acceptable parameters:\n" \
109 " server_port=%%d default: 4433\n" \
110 " debug_level=%%d default: 0 (disabled)\n" \
111 USAGE_IO \
112 " request_page=%%s default: \".\"\n" \
113 " renegotiation=%%d default: 1 (enabled)\n" \
114 " allow_legacy=%%d default: 0 (disabled)\n" \
Paul Bakker1d29fb52012-09-28 13:28:45 +0000115 " min_version=%%s default: \"ssl3\"\n" \
116 " options: ssl3, tls1, tls1_1, tls1_2\n" \
Paul Bakkerb60b95f2012-09-25 09:05:17 +0000117 " force_ciphersuite=<name> default: all enabled\n"\
118 " acceptable ciphersuite names:\n"
119
120#if !defined(POLARSSL_BIGNUM_C) || !defined(POLARSSL_ENTROPY_C) || \
121 !defined(POLARSSL_SSL_TLS_C) || !defined(POLARSSL_SSL_SRV_C) || \
122 !defined(POLARSSL_NET_C) || !defined(POLARSSL_RSA_C) || \
123 !defined(POLARSSL_CTR_DRBG_C)
124int main( int argc, char *argv[] )
125{
126 ((void) argc);
127 ((void) argv);
128
129 printf("POLARSSL_BIGNUM_C and/or POLARSSL_ENTROPY_C and/or "
130 "POLARSSL_SSL_TLS_C and/or POLARSSL_SSL_SRV_C and/or "
131 "POLARSSL_NET_C and/or POLARSSL_RSA_C and/or "
132 "POLARSSL_CTR_DRBG_C not defined.\n");
133 return( 0 );
134}
135#else
136int main( int argc, char *argv[] )
137{
138 int ret = 0, len;
139 int listen_fd;
140 int client_fd = -1;
141 unsigned char buf[1024];
142 char *pers = "ssl_server2";
143
144 entropy_context entropy;
145 ctr_drbg_context ctr_drbg;
146 ssl_context ssl;
Paul Bakkerb60b95f2012-09-25 09:05:17 +0000147 x509_cert cacert;
148 x509_cert srvcert;
149 rsa_context rsa;
Paul Bakker0a597072012-09-25 21:55:46 +0000150#if defined(POLARSSL_SSL_CACHE_C)
151 ssl_cache_context cache;
152#endif
Paul Bakkerb60b95f2012-09-25 09:05:17 +0000153
154 int i;
Paul Bakkerb60b95f2012-09-25 09:05:17 +0000155 char *p, *q;
156 const int *list;
157
158 /*
159 * Make sure memory references are valid.
160 */
161 listen_fd = 0;
Paul Bakkerb60b95f2012-09-25 09:05:17 +0000162 memset( &cacert, 0, sizeof( x509_cert ) );
163 memset( &srvcert, 0, sizeof( x509_cert ) );
164 memset( &rsa, 0, sizeof( rsa_context ) );
Paul Bakker0a597072012-09-25 21:55:46 +0000165#if defined(POLARSSL_SSL_CACHE_C)
166 ssl_cache_init( &cache );
167#endif
Paul Bakkerb60b95f2012-09-25 09:05:17 +0000168
169 if( argc == 0 )
170 {
171 usage:
172 if( ret == 0 )
173 ret = 1;
174
175 printf( USAGE );
176
177 list = ssl_list_ciphersuites();
178 while( *list )
179 {
180 printf(" %s\n", ssl_get_ciphersuite_name( *list ) );
181 list++;
182 }
183 printf("\n");
184 goto exit;
185 }
186
187 opt.server_port = DFL_SERVER_PORT;
188 opt.debug_level = DFL_DEBUG_LEVEL;
189 opt.ca_file = DFL_CA_FILE;
190 opt.ca_path = DFL_CA_PATH;
191 opt.crt_file = DFL_CRT_FILE;
192 opt.key_file = DFL_KEY_FILE;
193 opt.force_ciphersuite[0]= DFL_FORCE_CIPHER;
194 opt.renegotiation = DFL_RENEGOTIATION;
195 opt.allow_legacy = DFL_ALLOW_LEGACY;
Paul Bakker1d29fb52012-09-28 13:28:45 +0000196 opt.min_version = DFL_MIN_VERSION;
Paul Bakkerb60b95f2012-09-25 09:05:17 +0000197
198 for( i = 1; i < argc; i++ )
199 {
Paul Bakkerb60b95f2012-09-25 09:05:17 +0000200 p = argv[i];
201 if( ( q = strchr( p, '=' ) ) == NULL )
202 goto usage;
203 *q++ = '\0';
204
205 if( strcmp( p, "server_port" ) == 0 )
206 {
207 opt.server_port = atoi( q );
208 if( opt.server_port < 1 || opt.server_port > 65535 )
209 goto usage;
210 }
211 else if( strcmp( p, "debug_level" ) == 0 )
212 {
213 opt.debug_level = atoi( q );
214 if( opt.debug_level < 0 || opt.debug_level > 65535 )
215 goto usage;
216 }
217 else if( strcmp( p, "ca_file" ) == 0 )
218 opt.ca_file = q;
219 else if( strcmp( p, "ca_path" ) == 0 )
220 opt.ca_path = q;
221 else if( strcmp( p, "crt_file" ) == 0 )
222 opt.crt_file = q;
223 else if( strcmp( p, "key_file" ) == 0 )
224 opt.key_file = q;
225 else if( strcmp( p, "force_ciphersuite" ) == 0 )
226 {
227 opt.force_ciphersuite[0] = -1;
228
229 opt.force_ciphersuite[0] = ssl_get_ciphersuite_id( q );
230
231 if( opt.force_ciphersuite[0] <= 0 )
232 {
233 ret = 2;
234 goto usage;
235 }
236 opt.force_ciphersuite[1] = 0;
237 }
238 else if( strcmp( p, "renegotiation" ) == 0 )
239 {
240 opt.renegotiation = (atoi( q )) ? SSL_RENEGOTIATION_ENABLED :
241 SSL_RENEGOTIATION_DISABLED;
242 }
243 else if( strcmp( p, "allow_legacy" ) == 0 )
244 {
245 opt.allow_legacy = atoi( q );
246 if( opt.allow_legacy < 0 || opt.allow_legacy > 1 )
247 goto usage;
248 }
Paul Bakker1d29fb52012-09-28 13:28:45 +0000249 else if( strcmp( p, "min_version" ) == 0 )
250 {
251 if( strcmp( q, "ssl3" ) == 0 )
252 opt.min_version = SSL_MINOR_VERSION_0;
253 else if( strcmp( q, "tls1" ) == 0 )
254 opt.min_version = SSL_MINOR_VERSION_1;
255 else if( strcmp( q, "tls1_1" ) == 0 )
256 opt.min_version = SSL_MINOR_VERSION_2;
257 else if( strcmp( q, "tls1_2" ) == 0 )
258 opt.min_version = SSL_MINOR_VERSION_3;
259 else
260 goto usage;
261 }
Paul Bakkerb60b95f2012-09-25 09:05:17 +0000262 else
263 goto usage;
264 }
265
266 /*
267 * 0. Initialize the RNG and the session data
268 */
269 printf( "\n . Seeding the random number generator..." );
270 fflush( stdout );
271
272 entropy_init( &entropy );
273 if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,
274 (unsigned char *) pers, strlen( pers ) ) ) != 0 )
275 {
276 printf( " failed\n ! ctr_drbg_init returned -0x%x\n", -ret );
277 goto exit;
278 }
279
280 printf( " ok\n" );
281
282 /*
283 * 1.1. Load the trusted CA
284 */
285 printf( " . Loading the CA root certificate ..." );
286 fflush( stdout );
287
288#if defined(POLARSSL_FS_IO)
289 if( strlen( opt.ca_path ) )
290 ret = x509parse_crtpath( &cacert, opt.ca_path );
291 else if( strlen( opt.ca_file ) )
292 ret = x509parse_crtfile( &cacert, opt.ca_file );
293 else
294#endif
295#if defined(POLARSSL_CERTS_C)
296 ret = x509parse_crt( &cacert, (unsigned char *) test_ca_crt,
297 strlen( test_ca_crt ) );
298#else
299 {
300 ret = 1;
301 printf("POLARSSL_CERTS_C not defined.");
302 }
303#endif
304 if( ret < 0 )
305 {
306 printf( " failed\n ! x509parse_crt returned -0x%x\n\n", -ret );
307 goto exit;
308 }
309
310 printf( " ok (%d skipped)\n", ret );
311
312 /*
313 * 1.2. Load own certificate and private key
314 */
315 printf( " . Loading the server cert. and key..." );
316 fflush( stdout );
317
318#if defined(POLARSSL_FS_IO)
319 if( strlen( opt.crt_file ) )
320 ret = x509parse_crtfile( &srvcert, opt.crt_file );
321 else
322#endif
323#if defined(POLARSSL_CERTS_C)
324 ret = x509parse_crt( &srvcert, (unsigned char *) test_srv_crt,
325 strlen( test_srv_crt ) );
326#else
327 {
328 ret = 1;
329 printf("POLARSSL_CERTS_C not defined.");
330 }
331#endif
332 if( ret != 0 )
333 {
334 printf( " failed\n ! x509parse_crt returned -0x%x\n\n", -ret );
335 goto exit;
336 }
337
338#if defined(POLARSSL_FS_IO)
339 if( strlen( opt.key_file ) )
340 ret = x509parse_keyfile( &rsa, opt.key_file, "" );
341 else
342#endif
343#if defined(POLARSSL_CERTS_C)
344 ret = x509parse_key( &rsa, (unsigned char *) test_srv_key,
345 strlen( test_srv_key ), NULL, 0 );
346#else
347 {
348 ret = 1;
349 printf("POLARSSL_CERTS_C not defined.");
350 }
351#endif
352 if( ret != 0 )
353 {
354 printf( " failed\n ! x509parse_key returned -0x%x\n\n", -ret );
355 goto exit;
356 }
357
358 printf( " ok\n" );
359
360 /*
361 * 2. Setup the listening TCP socket
362 */
363 printf( " . Bind on tcp://localhost:%-4d/ ...", opt.server_port );
364 fflush( stdout );
365
366 if( ( ret = net_bind( &listen_fd, NULL, opt.server_port ) ) != 0 )
367 {
368 printf( " failed\n ! net_bind returned -0x%x\n\n", -ret );
369 goto exit;
370 }
371
372 printf( " ok\n" );
373
374 /*
375 * 3. Setup stuff
376 */
377 printf( " . Setting up the SSL/TLS structure..." );
378 fflush( stdout );
379
380 if( ( ret = ssl_init( &ssl ) ) != 0 )
381 {
382 printf( " failed\n ! ssl_init returned -0x%x\n\n", -ret );
383 goto exit;
384 }
385
386 ssl_set_endpoint( &ssl, SSL_IS_SERVER );
387 ssl_set_authmode( &ssl, SSL_VERIFY_NONE );
388
389 ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
390 ssl_set_dbg( &ssl, my_debug, stdout );
391
Paul Bakker0a597072012-09-25 21:55:46 +0000392#if defined(POLARSSL_SSL_CACHE_C)
393 ssl_set_session_cache( &ssl, ssl_cache_get, &cache,
394 ssl_cache_set, &cache );
395#endif
Paul Bakkerb60b95f2012-09-25 09:05:17 +0000396
397 if( opt.force_ciphersuite[0] == DFL_FORCE_CIPHER )
398 ssl_set_ciphersuites( &ssl, ssl_default_ciphersuites );
399 else
400 ssl_set_ciphersuites( &ssl, opt.force_ciphersuite );
401
402 ssl_set_renegotiation( &ssl, opt.renegotiation );
403 ssl_legacy_renegotiation( &ssl, opt.allow_legacy );
404
Paul Bakkerb60b95f2012-09-25 09:05:17 +0000405 ssl_set_ca_chain( &ssl, &cacert, NULL, NULL );
406 ssl_set_own_cert( &ssl, &srvcert, &rsa );
407
408#if defined(POLARSSL_DHM_C)
Paul Bakker5d19f862012-09-28 07:33:00 +0000409 /*
410 * Use different group than default DHM group
411 */
Paul Bakkerd4324102012-09-26 08:29:38 +0000412 ssl_set_dh_param( &ssl, POLARSSL_DHM_RFC5114_MODP_2048_P,
413 POLARSSL_DHM_RFC5114_MODP_2048_G );
Paul Bakkerb60b95f2012-09-25 09:05:17 +0000414#endif
415
Paul Bakker1d29fb52012-09-28 13:28:45 +0000416 if( opt.min_version != -1 )
417 ssl_set_min_version( &ssl, SSL_MAJOR_VERSION_3, opt.min_version );
418
Paul Bakkerb60b95f2012-09-25 09:05:17 +0000419 printf( " ok\n" );
420
421reset:
422#ifdef POLARSSL_ERROR_C
423 if( ret != 0 )
424 {
425 char error_buf[100];
426 error_strerror( ret, error_buf, 100 );
427 printf("Last error was: %d - %s\n\n", ret, error_buf );
428 }
429#endif
430
431 if( client_fd != -1 )
432 net_close( client_fd );
433
434 ssl_session_reset( &ssl );
435
436 /*
437 * 3. Wait until a client connects
438 */
439#if defined(_WIN32_WCE)
440 {
441 SHELLEXECUTEINFO sei;
442
443 ZeroMemory( &sei, sizeof( SHELLEXECUTEINFO ) );
444
445 sei.cbSize = sizeof( SHELLEXECUTEINFO );
446 sei.fMask = 0;
447 sei.hwnd = 0;
448 sei.lpVerb = _T( "open" );
449 sei.lpFile = _T( "https://localhost:4433/" );
450 sei.lpParameters = NULL;
451 sei.lpDirectory = NULL;
452 sei.nShow = SW_SHOWNORMAL;
453
454 ShellExecuteEx( &sei );
455 }
456#elif defined(_WIN32)
457 ShellExecute( NULL, "open", "https://localhost:4433/",
458 NULL, NULL, SW_SHOWNORMAL );
459#endif
460
461 client_fd = -1;
462
463 printf( " . Waiting for a remote connection ..." );
464 fflush( stdout );
465
466 if( ( ret = net_accept( listen_fd, &client_fd, NULL ) ) != 0 )
467 {
468 printf( " failed\n ! net_accept returned -0x%x\n\n", -ret );
469 goto exit;
470 }
471
472 ssl_set_bio( &ssl, net_recv, &client_fd,
473 net_send, &client_fd );
474
475 printf( " ok\n" );
476
477 /*
478 * 4. Handshake
479 */
480 printf( " . Performing the SSL/TLS handshake..." );
481 fflush( stdout );
482
483 while( ( ret = ssl_handshake( &ssl ) ) != 0 )
484 {
485 if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
486 {
487 printf( " failed\n ! ssl_handshake returned -0x%x\n\n", -ret );
Paul Bakker1d29fb52012-09-28 13:28:45 +0000488 goto reset;
Paul Bakkerb60b95f2012-09-25 09:05:17 +0000489 }
490 }
491
492 printf( " ok\n [ Ciphersuite is %s ]\n",
493 ssl_get_ciphersuite( &ssl ) );
494
495 /*
496 * 5. Verify the server certificate
497 */
498 printf( " . Verifying peer X.509 certificate..." );
499
500 if( ( ret = ssl_get_verify_result( &ssl ) ) != 0 )
501 {
502 printf( " failed\n" );
503
504 if( !ssl.session->peer_cert )
505 printf( " ! no client certificate sent\n" );
506
507 if( ( ret & BADCERT_EXPIRED ) != 0 )
508 printf( " ! client certificate has expired\n" );
509
510 if( ( ret & BADCERT_REVOKED ) != 0 )
511 printf( " ! client certificate has been revoked\n" );
512
513 if( ( ret & BADCERT_NOT_TRUSTED ) != 0 )
514 printf( " ! self-signed or not signed by a trusted CA\n" );
515
516 printf( "\n" );
517 }
518 else
519 printf( " ok\n" );
520
521 if( ssl.session->peer_cert )
522 {
523 printf( " . Peer certificate information ...\n" );
524 x509parse_cert_info( (char *) buf, sizeof( buf ) - 1, " ",
525 ssl.session->peer_cert );
526 printf( "%s\n", buf );
527 }
528
529 /*
530 * 6. Read the HTTP Request
531 */
532 printf( " < Read from client:" );
533 fflush( stdout );
534
535 do
536 {
537 len = sizeof( buf ) - 1;
538 memset( buf, 0, sizeof( buf ) );
539 ret = ssl_read( &ssl, buf, len );
540
541 if( ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE )
542 continue;
543
544 if( ret <= 0 )
545 {
546 switch( ret )
547 {
548 case POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY:
549 printf( " connection was closed gracefully\n" );
550 break;
551
552 case POLARSSL_ERR_NET_CONN_RESET:
553 printf( " connection was reset by peer\n" );
554 break;
555
556 default:
557 printf( " ssl_read returned -0x%x\n", -ret );
558 break;
559 }
560
561 break;
562 }
563
564 len = ret;
565 printf( " %d bytes read\n\n%s", len, (char *) buf );
566
567 if( ret > 0 )
568 break;
569 }
570 while( 1 );
571
572 /*
573 * 7. Write the 200 Response
574 */
575 printf( " > Write to client:" );
576 fflush( stdout );
577
578 len = sprintf( (char *) buf, HTTP_RESPONSE,
579 ssl_get_ciphersuite( &ssl ) );
580
581 while( ( ret = ssl_write( &ssl, buf, len ) ) <= 0 )
582 {
583 if( ret == POLARSSL_ERR_NET_CONN_RESET )
584 {
585 printf( " failed\n ! peer closed the connection\n\n" );
586 goto reset;
587 }
588
589 if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
590 {
591 printf( " failed\n ! ssl_write returned %d\n\n", ret );
592 goto exit;
593 }
594 }
595
596 len = ret;
597 printf( " %d bytes written\n\n%s\n", len, (char *) buf );
598
599 ret = 0;
600 goto reset;
601
602exit:
603
604#ifdef POLARSSL_ERROR_C
605 if( ret != 0 )
606 {
607 char error_buf[100];
608 error_strerror( ret, error_buf, 100 );
609 printf("Last error was: -0x%X - %s\n\n", -ret, error_buf );
610 }
611#endif
612
613 net_close( client_fd );
614 x509_free( &srvcert );
615 x509_free( &cacert );
616 rsa_free( &rsa );
Paul Bakkerb60b95f2012-09-25 09:05:17 +0000617 ssl_free( &ssl );
618
Paul Bakker0a597072012-09-25 21:55:46 +0000619#if defined(POLARSSL_SSL_CACHE_C)
620 ssl_cache_free( &cache );
621#endif
622
Paul Bakkerb60b95f2012-09-25 09:05:17 +0000623#if defined(_WIN32)
624 printf( " + Press Enter to exit this program.\n" );
625 fflush( stdout ); getchar();
626#endif
627
628 return( ret );
629}
630#endif /* POLARSSL_BIGNUM_C && POLARSSL_ENTROPY_C && POLARSSL_SSL_TLS_C &&
631 POLARSSL_SSL_SRV_C && POLARSSL_NET_C && POLARSSL_RSA_C &&
632 POLARSSL_CTR_DRBG_C */