Merged massive SSL Testing improvements

This commit is contained in:
Paul Bakker 2014-03-14 16:30:36 +01:00
commit a4b0343edf
17 changed files with 2400 additions and 681 deletions

3
.gitignore vendored
View File

@ -4,3 +4,6 @@ CTestTestfile.cmake
cmake_install.cmake
Testing
Coverage
*.gcno
*.gcda
library/polarssl.info

View File

@ -76,10 +76,22 @@ ADD_CUSTOM_TARGET(test-ref-config
COMMAND tests/scripts/test-ref-configs.pl
)
# add programs/test/selftest even though the selftest functions are
# called from the testsuites since it runs them in verbose mode,
# avoiding spurious "uncovered" printf lines
ADD_CUSTOM_TARGET(covtest
COMMAND make test
COMMAND programs/test/selftest
COMMAND cd tests && ./compat.sh
COMMAND cd tests && ./ssl-opt.sh
)
ADD_CUSTOM_TARGET(lcov
COMMAND geninfo *.gcda
COMMAND genhtml -o ../../../Coverage *.info
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/library/CMakeFiles/polarssl.dir
COMMAND rm -rf Coverage
COMMAND lcov --capture --directory library/CMakeFiles/polarssl.dir -o polarssl.info
COMMAND gendesc tests/Descriptions.txt -o descriptions
COMMAND genhtml --title PolarSSL --description-file descriptions --keep-descriptions --legend --no-branch-coverage -o Coverage polarssl.info
COMMAND rm -f polarssl.info descriptions
)
ADD_CUSTOM_TARGET(memcheck

View File

@ -3,7 +3,7 @@ PolarSSL ChangeLog (Sorted per branch, date)
= PolarSSL 1.3 branch
Features
* HMAC-DRBG as a separate module
* Option to set the Curve preference order
* Option to set the Curve preference order (disabled by default)
* Single Platform compatilibity layer (for memory / printf / fprintf)
* Ability to provide alternate timing implementation
* Ability to force the entropy module to use SHA-256 as its basis
@ -35,6 +35,14 @@ Bugfix
* Programs rsa_sign_pss and rsa_verify_pss were not using PSS since 1.3.0
* Bignum's MIPS-32 assembly was used on MIPS-64, causing chaos. (Found by
Alex Wilson.)
* ssl_cache was creating entries when max_entries=0 if TIMING_C was enabled.
* m_sleep() was sleeping twice too long on most Unix platforms.
* Fixed bug with session tickets and non-blocking I/O in the unlikely case
send() would return an EAGAIN error when sending the ticket.
* ssl_cache was leaking memory when reusing a timed out entry containing a
client certificate.
* ssl_srv was leaking memory when client presented a timed out ticket
containing a client certificate
= PolarSSL 1.3.4 released on 2014-01-27
Features

View File

@ -56,10 +56,23 @@ check: lib
test-ref-configs:
tests/scripts/test-ref-configs.pl
# note: for coverage testing, build with:
# CFLAGS='--coverage' make OFLAGS='-g3 -O0'
covtest:
make check
# add programs/test/selftest even though the selftest functions are
# called from the testsuites since it runs them in verbose mode,
# avoiding spurious "uncovered" printf lines
programs/test/selftest
( cd tests && ./compat.sh )
( cd tests && ./ssl-opt.sh )
lcov:
rm -rf Coverage
( cd library && geninfo *.gcda )
( cd library && genhtml -o ../Coverage *.info )
lcov --capture --directory library -o polarssl.info
gendesc tests/Descriptions.txt -o descriptions
genhtml --title PolarSSL --description-file descriptions --keep-descriptions --legend --no-branch-coverage -o Coverage polarssl.info
rm -f polarssl.info descriptions
apidoc:
mkdir -p apidoc

View File

@ -2273,6 +2273,11 @@
#error "POLARSSL_SSL_SESSION_TICKETS_C defined, but not all prerequisites"
#endif
#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) && \
!defined(POLARSSL_X509_CRT_PARSE_C)
#error "POLARSSL_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites"
#endif
#if defined(POLARSSL_THREADING_PTHREAD)
#if !defined(POLARSSL_THREADING_C) || defined(POLARSSL_THREADING_IMPL)
#error "POLARSSL_THREADING_PTHREAD defined, but not all prerequisites"

View File

@ -1118,7 +1118,7 @@ int ssl_set_psk( ssl_context *ssl, const unsigned char *psk, size_t psk_len,
*
* If set, the PSK callback is called for each
* handshake where a PSK ciphersuite was negotiated.
* The callback provides the identity received and wants to
* The caller provides the identity received and wants to
* receive the actual PSK data and length.
*
* The callback has the following parameters: (void *parameter,

View File

@ -106,7 +106,7 @@ int ssl_cache_set( void *data, const ssl_session *session );
* A timeout of 0 indicates no timeout.
*
* \param cache SSL cache context
* \param timeout cache entry timeout
* \param timeout cache entry timeout in seconds
*/
void ssl_cache_set_timeout( ssl_cache_context *cache, int timeout );
#endif /* POLARSSL_HAVE_TIME */

View File

@ -169,55 +169,56 @@ const char test_ca_pwd_rsa[] = "PolarSSLTest";
const char test_srv_crt_rsa[] =
"-----BEGIN CERTIFICATE-----\r\n"
"MIIDPzCCAiegAwIBAgIBATANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"
"MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"
"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n"
"MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n"
"A1UEChMIUG9sYXJTU0wxGjAYBgNVBAMTEVBvbGFyU1NMIFNlcnZlciAxMIIBIjAN\r\n"
"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqQIfPUBq1VVTi/027oJlLhVhXom/\r\n"
"uOhFkNvuiBZS0/FDUEeWEllkh2v9K+BG+XO+3c+S4ZFb7Wagb4kpeUWA0INq1UFD\r\n"
"d185fAkER4KwVzlw7aPsFRkeqDMIR8EFQqn9TMO0390GH00QUUBncxMPQPhtgSVf\r\n"
"CrFTxjB+FTms+Vruf5KepgVb5xOXhbUjktnUJAbVCSWJdQfdphqPPwkZvq1lLGTr\r\n"
"lZvc/kFeF6babFtpzAK6FCwWJJxK3M3Q91Jnc/EtoCP9fvQxyi1wyokLBNsupk9w\r\n"
"bp7OvViJ4lNZnm5akmXiiD8MlBmj3eXonZUT7Snbq3AS3FrKaxerUoJUsQIDAQAB\r\n"
"o00wSzAJBgNVHRMEAjAAMB0GA1UdDgQWBBQfdNY/KcF0dEU7BRIsPai9Q1kCpjAf\r\n"
"BgNVHSMEGDAWgBS0WuSls97SUva51aaVD+s+vMf9/zANBgkqhkiG9w0BAQUFAAOC\r\n"
"AQEAvc+WwZUemsJu2IiI2Cp6liA+UAvIx98dQe3kZs2zAoF9VwQbXcYzWQ/BILkj\r\n"
"NImKbPL9x0g2jIDn4ZvGYFywMwIO/d++YbwYiQw42/v7RiMy94zBPnzeHi86dy/0\r\n"
"jpOOJUx3IXRsGLdyjb/1T11klcFqGnARiK+8VYolMPP6afKvLXX7K4kiUpsFQhUp\r\n"
"E5VeM5pV1Mci2ETOJau2cO40FJvI/C9W/wR+GAArMaw2fxG77E3laaa0LAOlexM6\r\n"
"A4KOb5f5cGTM5Ih6tEF5FVq3/9vzNIYMa1FqzacBLZF8zSHYLEimXBdzjBoN4qDU\r\n"
"/WzRyYRBRjAI49mzHX6raleqnw==\r\n"
"MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n"
"A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n"
"AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n"
"owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n"
"NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n"
"tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n"
"hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n"
"HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n"
"VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n"
"FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAJxnXClY\r\n"
"oHkbp70cqBrsGXLybA74czbO5RdLEgFs7rHVS9r+c293luS/KdliLScZqAzYVylw\r\n"
"UfRWvKMoWhHYKp3dEIS4xTXk6/5zXxhv9Rw8SGc8qn6vITHk1S1mPevtekgasY5Y\r\n"
"iWQuM3h4YVlRH3HHEMAD1TnAexfXHHDFQGe+Bd1iAbz1/sH9H8l4StwX6egvTK3M\r\n"
"wXRwkKkvjKaEDA9ATbZx0mI8LGsxSuCqe9r9dyjmttd47J1p1Rulz3CLzaRcVIuS\r\n"
"RRQfaD8neM9c1S/iJ/amTVqJxA1KOdOS5780WhPfSArA+g4qAmSjelc3p4wWpha8\r\n"
"zhuYwjVuX6JHG0c=\r\n"
"-----END CERTIFICATE-----\r\n";
const char test_srv_key_rsa[] =
"-----BEGIN RSA PRIVATE KEY-----\r\n"
"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\r\n"
"-----END RSA PRIVATE KEY-----\r\n";
const char test_cli_crt_rsa[] =
"-----BEGIN CERTIFICATE-----\r\n"
"MIIDPzCCAiegAwIBAgIBBDANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n"

View File

@ -186,17 +186,15 @@ int ssl_cache_set( void *data, const ssl_session *session )
/*
* Reuse oldest entry if max_entries reached
*/
if( old != NULL && count >= cache->max_entries )
if( count >= cache->max_entries )
{
cur = old;
memset( &cur->session, 0, sizeof(ssl_session) );
#if defined(POLARSSL_X509_CRT_PARSE_C)
if( cur->peer_cert.p != NULL )
if( old == NULL )
{
polarssl_free( cur->peer_cert.p );
memset( &cur->peer_cert, 0, sizeof(x509_buf) );
ret = 1;
goto exit;
}
#endif /* POLARSSL_X509_CRT_PARSE_C */
cur = old;
}
#else /* POLARSSL_HAVE_TIME */
/*
@ -213,21 +211,15 @@ int ssl_cache_set( void *data, const ssl_session *session )
cur = cache->chain;
cache->chain = cur->next;
#if defined(POLARSSL_X509_CRT_PARSE_C)
if( cur->peer_cert.p != NULL )
{
polarssl_free( cur->peer_cert.p );
memset( &cur->peer_cert, 0, sizeof(x509_buf) );
}
#endif /* POLARSSL_X509_CRT_PARSE_C */
memset( cur, 0, sizeof(ssl_cache_entry) );
cur->next = NULL;
prv->next = cur;
}
#endif /* POLARSSL_HAVE_TIME */
else
{
/*
* max_entries not reached, create new entry
*/
cur = (ssl_cache_entry *) polarssl_malloc( sizeof(ssl_cache_entry) );
if( cur == NULL )
{
@ -251,6 +243,15 @@ int ssl_cache_set( void *data, const ssl_session *session )
memcpy( &cur->session, session, sizeof( ssl_session ) );
#if defined(POLARSSL_X509_CRT_PARSE_C)
/*
* If we're reusing an entry, free its certificate first
*/
if( cur->peer_cert.p != NULL )
{
polarssl_free( cur->peer_cert.p );
memset( &cur->peer_cert, 0, sizeof(x509_buf) );
}
/*
* Store peer certificate
*/

View File

@ -310,7 +310,7 @@ static int ssl_parse_ticket( ssl_context *ssl,
if( ( ret = ssl_load_session( &session, ticket, clear_len ) ) != 0 )
{
SSL_DEBUG_MSG( 1, ( "failed to parse ticket content" ) );
memset( &session, 0, sizeof( ssl_session ) );
ssl_session_free( &session );
return( ret );
}
@ -319,7 +319,7 @@ static int ssl_parse_ticket( ssl_context *ssl,
if( (int) ( time( NULL) - session.start ) > ssl->ticket_lifetime )
{
SSL_DEBUG_MSG( 1, ( "session ticket expired" ) );
memset( &session, 0, sizeof( ssl_session ) );
ssl_session_free( &session );
return( POLARSSL_ERR_SSL_SESSION_TICKET_EXPIRED );
}
#endif
@ -367,6 +367,8 @@ static int ssl_parse_servername_ext( ssl_context *ssl,
size_t servername_list_size, hostname_len;
const unsigned char *p;
SSL_DEBUG_MSG( 3, ( "parse ServerName extension" ) );
servername_list_size = ( ( buf[0] << 8 ) | ( buf[1] ) );
if( servername_list_size + 2 != len )
{
@ -389,6 +391,7 @@ static int ssl_parse_servername_ext( ssl_context *ssl,
ret = ssl_sni_wrapper( ssl, p + 3, hostname_len );
if( ret != 0 )
{
SSL_DEBUG_RET( 1, "ssl_sni_wrapper", ret );
ssl_send_alert_message( ssl, SSL_ALERT_LEVEL_FATAL,
SSL_ALERT_MSG_UNRECOGNIZED_NAME );
return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO );
@ -1690,6 +1693,7 @@ static int ssl_write_server_hello( ssl_context *ssl )
ssl->f_get_cache != NULL &&
ssl->f_get_cache( ssl->p_get_cache, ssl->session_negotiate ) == 0 )
{
SSL_DEBUG_MSG( 3, ( "session successfully restored from cache" ) );
ssl->handshake->resume = 1;
}
@ -2041,7 +2045,7 @@ static int ssl_write_server_key_exchange( ssl_context *ssl )
{
ssl_get_ecdh_params_from_cert( ssl );
SSL_DEBUG_MSG( 2, ( "<= skip parse server key exchange" ) );
SSL_DEBUG_MSG( 2, ( "<= skip write server key exchange" ) );
ssl->state++;
return( 0 );
}
@ -2999,15 +3003,18 @@ static int ssl_write_new_session_ticket( ssl_context *ssl )
ssl->out_msglen = 10 + tlen;
/*
* Morally equivalent to updating ssl->state, but NewSessionTicket and
* ChangeCipherSpec share the same state.
*/
ssl->handshake->new_session_ticket = 0;
if( ( ret = ssl_write_record( ssl ) ) != 0 )
{
SSL_DEBUG_RET( 1, "ssl_write_record", ret );
return( ret );
}
/* No need to remember writing a NewSessionTicket any more */
ssl->handshake->new_session_ticket = 0;
SSL_DEBUG_MSG( 2, ( "<= write new session ticket" ) );
return( 0 );

View File

@ -302,7 +302,7 @@ void m_sleep( int milliseconds )
struct timeval tv;
tv.tv_sec = milliseconds / 1000;
tv.tv_usec = milliseconds * 1000;
tv.tv_usec = ( milliseconds % 1000 ) * 1000;
select( 0, NULL, NULL, NULL, &tv );
}

View File

@ -37,10 +37,16 @@
#include "polarssl/x509.h"
#include "polarssl/error.h"
#if defined(POLARSSL_TIMING_C)
#include "polarssl/timing.h"
#endif
#define DFL_SERVER_NAME "localhost"
#define DFL_SERVER_ADDR NULL
#define DFL_SERVER_PORT 4433
#define DFL_REQUEST_PAGE "/"
#define DFL_DEBUG_LEVEL 0
#define DFL_NBIO 0
#define DFL_CA_FILE ""
#define DFL_CA_PATH ""
#define DFL_CRT_FILE ""
@ -50,12 +56,14 @@
#define DFL_FORCE_CIPHER 0
#define DFL_RENEGOTIATION SSL_RENEGOTIATION_ENABLED
#define DFL_ALLOW_LEGACY SSL_LEGACY_NO_RENEGOTIATION
#define DFL_RENEGOTIATE 0
#define DFL_MIN_VERSION -1
#define DFL_MAX_VERSION -1
#define DFL_AUTH_MODE SSL_VERIFY_REQUIRED
#define DFL_MFL_CODE SSL_MAX_FRAG_LEN_NONE
#define DFL_TRUNC_HMAC 0
#define DFL_RECONNECT 0
#define DFL_RECO_DELAY 0
#define DFL_TICKETS SSL_SESSION_TICKETS_ENABLED
#define LONG_HEADER "User-agent: blah-blah-blah-blah-blah-blah-blah-blah-" \
@ -71,17 +79,16 @@
* longer paquets (for fragmentation purposes) */
#define GET_REQUEST "GET %s HTTP/1.0\r\n" /* LONG_HEADER */ "\r\n"
/* Uncomment to test client-initiated renegotiation */
// #define TEST_RENEGO
/*
* global options
*/
struct options
{
const char *server_name; /* hostname of the server (client only) */
const char *server_addr; /* address of the server (client only) */
int server_port; /* port on which the ssl service runs */
int debug_level; /* level of debugging */
int nbio; /* should I/O be blocking? */
const char *request_page; /* page on server to request */
const char *ca_file; /* the file with the CA certificate(s) */
const char *ca_path; /* the path with the CA certificate(s) reside */
@ -92,12 +99,14 @@ struct options
int force_ciphersuite[2]; /* protocol/ciphersuite to use, or all */
int renegotiation; /* enable / disable renegotiation */
int allow_legacy; /* allow legacy renegotiation */
int renegotiate; /* attempt renegotiation? */
int min_version; /* minimum protocol version accepted */
int max_version; /* maximum protocol version accepted */
int auth_mode; /* verify mode for connection */
unsigned char mfl_code; /* code for maximum fragment length */
int trunc_hmac; /* negotiate truncated hmac or not */
int reconnect; /* attempt to resume session */
int reco_delay; /* delay in seconds before resuming session */
int tickets; /* enable / disable session tickets */
} opt;
@ -110,6 +119,44 @@ static void my_debug( void *ctx, int level, const char *str )
}
}
/*
* Test recv/send functions that make sure each try returns
* WANT_READ/WANT_WRITE at least once before sucesseding
*/
static int my_recv( void *ctx, unsigned char *buf, size_t len )
{
static int first_try = 1;
int ret;
if( first_try )
{
first_try = 0;
return( POLARSSL_ERR_NET_WANT_READ );
}
ret = net_recv( ctx, buf, len );
if( ret != POLARSSL_ERR_NET_WANT_READ )
first_try = 1; /* Next call will be a new operation */
return( ret );
}
static int my_send( void *ctx, const unsigned char *buf, size_t len )
{
static int first_try = 1;
int ret;
if( first_try )
{
first_try = 0;
return( POLARSSL_ERR_NET_WANT_WRITE );
}
ret = net_send( ctx, buf, len );
if( ret != POLARSSL_ERR_NET_WANT_WRITE )
first_try = 1; /* Next call will be a new operation */
return( ret );
}
#if defined(POLARSSL_X509_CRT_PARSE_C)
/*
* Enabled if debug_level > 1 in code below
@ -199,18 +246,38 @@ static int my_verify( void *data, x509_crt *crt, int depth, int *flags )
#define USAGE_MAX_FRAG_LEN ""
#endif /* POLARSSL_SSL_MAX_FRAGMENT_LENGTH */
#if defined(POLARSSL_TIMING_C)
#define USAGE_TIME \
" reco_delay=%%d default: 0 seconds\n"
#else
#define USAGE_TIME ""
#endif /* POLARSSL_TIMING_C */
#define USAGE \
"\n usage: ssl_client2 param=<>...\n" \
"\n acceptable parameters:\n" \
" server_name=%%s default: localhost\n" \
" server_addr=%%s default: given by name\n" \
" server_port=%%d default: 4433\n" \
" debug_level=%%d default: 0 (disabled)\n" \
USAGE_IO \
" request_page=%%s default: \".\"\n" \
" debug_level=%%d default: 0 (disabled)\n" \
" nbio=%%d default: 0 (blocking I/O)\n" \
" options: 1 (non-blocking), 2 (added delays)\n" \
"\n" \
" auth_mode=%%s default: \"optional\"\n" \
" options: none, optional, required\n" \
USAGE_IO \
"\n" \
USAGE_PSK \
"\n" \
" renegotiation=%%d default: 1 (enabled)\n" \
" allow_legacy=%%d default: 0 (disabled)\n" \
" renegotiate=%%d default: 0 (disabled)\n" \
" reconnect=%%d default: 0 (disabled)\n" \
USAGE_TIME \
USAGE_TICKETS \
USAGE_MAX_FRAG_LEN \
USAGE_TRUNC_HMAC \
"\n" \
" min_version=%%s default: \"\" (ssl3)\n" \
" max_version=%%s default: \"\" (tls1_2)\n" \
@ -218,9 +285,6 @@ static int my_verify( void *data, x509_crt *crt, int depth, int *flags )
" options: ssl3, tls1, tls1_1, tls1_2\n" \
" auth_mode=%%s default: \"required\"\n" \
" options: none, optional, required\n" \
USAGE_MAX_FRAG_LEN \
USAGE_TRUNC_HMAC \
USAGE_PSK \
"\n" \
" force_ciphersuite=<name> default: all enabled\n"\
" acceptable ciphersuite names:\n"
@ -296,8 +360,10 @@ int main( int argc, char *argv[] )
}
opt.server_name = DFL_SERVER_NAME;
opt.server_addr = DFL_SERVER_ADDR;
opt.server_port = DFL_SERVER_PORT;
opt.debug_level = DFL_DEBUG_LEVEL;
opt.nbio = DFL_NBIO;
opt.request_page = DFL_REQUEST_PAGE;
opt.ca_file = DFL_CA_FILE;
opt.ca_path = DFL_CA_PATH;
@ -308,12 +374,14 @@ int main( int argc, char *argv[] )
opt.force_ciphersuite[0]= DFL_FORCE_CIPHER;
opt.renegotiation = DFL_RENEGOTIATION;
opt.allow_legacy = DFL_ALLOW_LEGACY;
opt.renegotiate = DFL_RENEGOTIATE;
opt.min_version = DFL_MIN_VERSION;
opt.max_version = DFL_MAX_VERSION;
opt.auth_mode = DFL_AUTH_MODE;
opt.mfl_code = DFL_MFL_CODE;
opt.trunc_hmac = DFL_TRUNC_HMAC;
opt.reconnect = DFL_RECONNECT;
opt.reco_delay = DFL_RECO_DELAY;
opt.tickets = DFL_TICKETS;
for( i = 1; i < argc; i++ )
@ -325,6 +393,8 @@ int main( int argc, char *argv[] )
if( strcmp( p, "server_name" ) == 0 )
opt.server_name = q;
else if( strcmp( p, "server_addr" ) == 0 )
opt.server_addr = q;
else if( strcmp( p, "server_port" ) == 0 )
{
opt.server_port = atoi( q );
@ -337,6 +407,12 @@ int main( int argc, char *argv[] )
if( opt.debug_level < 0 || opt.debug_level > 65535 )
goto usage;
}
else if( strcmp( p, "nbio" ) == 0 )
{
opt.nbio = atoi( q );
if( opt.nbio < 0 || opt.nbio > 2 )
goto usage;
}
else if( strcmp( p, "request_page" ) == 0 )
opt.request_page = q;
else if( strcmp( p, "ca_file" ) == 0 )
@ -375,12 +451,24 @@ int main( int argc, char *argv[] )
if( opt.allow_legacy < 0 || opt.allow_legacy > 1 )
goto usage;
}
else if( strcmp( p, "renegotiate" ) == 0 )
{
opt.renegotiate = atoi( q );
if( opt.renegotiate < 0 || opt.renegotiate > 1 )
goto usage;
}
else if( strcmp( p, "reconnect" ) == 0 )
{
opt.reconnect = atoi( q );
if( opt.reconnect < 0 || opt.reconnect > 2 )
goto usage;
}
else if( strcmp( p, "reco_delay" ) == 0 )
{
opt.reco_delay = atoi( q );
if( opt.reco_delay < 0 )
goto usage;
}
else if( strcmp( p, "tickets" ) == 0 )
{
opt.tickets = atoi( q );
@ -573,9 +661,15 @@ int main( int argc, char *argv[] )
#if defined(POLARSSL_FS_IO)
if( strlen( opt.ca_path ) )
ret = x509_crt_parse_path( &cacert, opt.ca_path );
if( strcmp( opt.ca_path, "none" ) == 0 )
ret = 0;
else
ret = x509_crt_parse_path( &cacert, opt.ca_path );
else if( strlen( opt.ca_file ) )
ret = x509_crt_parse_file( &cacert, opt.ca_file );
if( strcmp( opt.ca_file, "none" ) == 0 )
ret = 0;
else
ret = x509_crt_parse_file( &cacert, opt.ca_file );
else
#endif
#if defined(POLARSSL_CERTS_C)
@ -605,7 +699,10 @@ int main( int argc, char *argv[] )
#if defined(POLARSSL_FS_IO)
if( strlen( opt.crt_file ) )
ret = x509_crt_parse_file( &clicert, opt.crt_file );
if( strcmp( opt.crt_file, "none" ) == 0 )
ret = 0;
else
ret = x509_crt_parse_file( &clicert, opt.crt_file );
else
#endif
#if defined(POLARSSL_CERTS_C)
@ -625,7 +722,10 @@ int main( int argc, char *argv[] )
#if defined(POLARSSL_FS_IO)
if( strlen( opt.key_file ) )
ret = pk_parse_keyfile( &pkey, opt.key_file, "" );
if( strcmp( opt.key_file, "none" ) == 0 )
ret = 0;
else
ret = pk_parse_keyfile( &pkey, opt.key_file, "" );
else
#endif
#if defined(POLARSSL_CERTS_C)
@ -649,17 +749,30 @@ int main( int argc, char *argv[] )
/*
* 2. Start the connection
*/
printf( " . Connecting to tcp/%s/%-4d...", opt.server_name,
if( opt.server_addr == NULL)
opt.server_addr = opt.server_name;
printf( " . Connecting to tcp/%s/%-4d...", opt.server_addr,
opt.server_port );
fflush( stdout );
if( ( ret = net_connect( &server_fd, opt.server_name,
if( ( ret = net_connect( &server_fd, opt.server_addr,
opt.server_port ) ) != 0 )
{
printf( " failed\n ! net_connect returned -0x%x\n\n", -ret );
goto exit;
}
if( opt.nbio > 0 )
ret = net_set_nonblock( server_fd );
else
ret = net_set_block( server_fd );
if( ret != 0 )
{
printf( " failed\n ! net_set_(non)block() returned -0x%x\n\n", -ret );
goto exit;
}
printf( " ok\n" );
/*
@ -695,8 +808,11 @@ int main( int argc, char *argv[] )
ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
ssl_set_dbg( &ssl, my_debug, stdout );
ssl_set_bio( &ssl, net_recv, &server_fd,
net_send, &server_fd );
if( opt.nbio == 2 )
ssl_set_bio( &ssl, my_recv, &server_fd, my_send, &server_fd );
else
ssl_set_bio( &ssl, net_recv, &server_fd, net_send, &server_fd );
#if defined(POLARSSL_SSL_SESSION_TICKETS)
ssl_set_session_tickets( &ssl, opt.tickets );
@ -709,8 +825,16 @@ int main( int argc, char *argv[] )
ssl_legacy_renegotiation( &ssl, opt.allow_legacy );
#if defined(POLARSSL_X509_CRT_PARSE_C)
ssl_set_ca_chain( &ssl, &cacert, NULL, opt.server_name );
ssl_set_own_cert( &ssl, &clicert, &pkey );
if( strcmp( opt.ca_path, "none" ) != 0 &&
strcmp( opt.ca_file, "none" ) != 0 )
{
ssl_set_ca_chain( &ssl, &cacert, NULL, opt.server_name );
}
if( strcmp( opt.crt_file, "none" ) != 0 &&
strcmp( opt.key_file, "none" ) != 0 )
{
ssl_set_own_cert( &ssl, &clicert, &pkey );
}
#endif
#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
@ -804,23 +928,25 @@ int main( int argc, char *argv[] )
}
#endif /* POLARSSL_X509_CRT_PARSE_C */
#ifdef TEST_RENEGO
/*
* Perform renegotiation (this must be done when the server is waiting
* for input from our side).
*/
printf( " . Performing renegotiation..." );
fflush( stdout );
while( ( ret = ssl_renegotiate( &ssl ) ) != 0 )
if( opt.renegotiate )
{
if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
/*
* Perform renegotiation (this must be done when the server is waiting
* for input from our side).
*/
printf( " . Performing renegotiation..." );
fflush( stdout );
while( ( ret = ssl_renegotiate( &ssl ) ) != 0 )
{
printf( " failed\n ! ssl_renegotiate returned %d\n\n", ret );
goto exit;
if( ret != POLARSSL_ERR_NET_WANT_READ &&
ret != POLARSSL_ERR_NET_WANT_WRITE )
{
printf( " failed\n ! ssl_renegotiate returned %d\n\n", ret );
goto exit;
}
}
printf( " ok\n" );
}
printf( " ok\n" );
#endif
/*
* 6. Write the GET request
@ -829,7 +955,10 @@ send_request:
printf( " > Write to server:" );
fflush( stdout );
len = sprintf( (char *) buf, GET_REQUEST, opt.request_page );
if( strcmp( opt.request_page, "SERVERQUIT" ) == 0 )
len = sprintf( (char *) buf, "%s", opt.request_page );
else
len = sprintf( (char *) buf, GET_REQUEST, opt.request_page );
for( written = 0, frags = 0; written < len; written += ret, frags++ )
{
@ -887,8 +1016,10 @@ send_request:
{
--opt.reconnect;
// printf( " ! Press a key to reconnect\n" );
// (void) getchar();
#if defined(POLARSSL_TIMING_C)
if( opt.reco_delay > 0 )
m_sleep( 1000 * opt.reco_delay );
#endif
printf( " . Reconnecting with saved session..." );
fflush( stdout );
@ -931,6 +1062,9 @@ exit:
char error_buf[100];
polarssl_strerror( ret, error_buf, 100 );
printf("Last error was: -0x%X - %s\n\n", -ret, error_buf );
if( ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY )
ret = 0;
}
#endif

View File

@ -25,6 +25,17 @@
#include "polarssl/config.h"
#if defined(POLARSSL_SSL_SERVER_NAME_INDICATION) && defined(POLARSSL_FS_IO)
#define POLARSSL_SNI
#endif
#if defined(POLARSSL_PLATFORM_C)
#include "polarssl/platform.h"
#else
#define polarssl_malloc malloc
#define polarssl_free free
#endif
#if defined(_WIN32)
#include <windows.h>
#endif
@ -52,6 +63,7 @@
#define DFL_SERVER_ADDR NULL
#define DFL_SERVER_PORT 4433
#define DFL_DEBUG_LEVEL 0
#define DFL_NBIO 0
#define DFL_CA_FILE ""
#define DFL_CA_PATH ""
#define DFL_CRT_FILE ""
@ -63,11 +75,16 @@
#define DFL_FORCE_CIPHER 0
#define DFL_RENEGOTIATION SSL_RENEGOTIATION_ENABLED
#define DFL_ALLOW_LEGACY SSL_LEGACY_NO_RENEGOTIATION
#define DFL_RENEGOTIATE 0
#define DFL_MIN_VERSION -1
#define DFL_MAX_VERSION -1
#define DFL_AUTH_MODE SSL_VERIFY_OPTIONAL
#define DFL_MFL_CODE SSL_MAX_FRAG_LEN_NONE
#define DFL_TICKETS SSL_SESSION_TICKETS_ENABLED
#define DFL_TICKET_TIMEOUT -1
#define DFL_CACHE_MAX -1
#define DFL_CACHE_TIMEOUT -1
#define DFL_SNI NULL
#define LONG_RESPONSE "<p>01-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \
"02-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \
@ -84,9 +101,6 @@
"<h2>PolarSSL Test Server</h2>\r\n" \
"<p>Successful connection using: %s</p>\r\n" // LONG_RESPONSE
/* Uncomment to test server-initiated renegotiation */
// #define TEST_RENEGO
/*
* global options
*/
@ -95,6 +109,7 @@ struct options
const char *server_addr; /* address on which the ssl service runs */
int server_port; /* port on which the ssl service runs */
int debug_level; /* level of debugging */
int nbio; /* should I/O be blocking? */
const char *ca_file; /* the file with the CA certificate(s) */
const char *ca_path; /* the path with the CA certificate(s) reside */
const char *crt_file; /* the file with the server certificate */
@ -106,11 +121,16 @@ struct options
int force_ciphersuite[2]; /* protocol/ciphersuite to use, or all */
int renegotiation; /* enable / disable renegotiation */
int allow_legacy; /* allow legacy renegotiation */
int renegotiate; /* attempt renegotiation? */
int min_version; /* minimum protocol version accepted */
int max_version; /* maximum protocol version accepted */
int auth_mode; /* verify mode for connection */
unsigned char mfl_code; /* code for maximum fragment length */
int tickets; /* enable / disable session tickets */
int ticket_timeout; /* session ticket lifetime */
int cache_max; /* max number of session cache entries */
int cache_timeout; /* expiration delay of session cache entries */
char *sni; /* string decribing sni information */
} opt;
static void my_debug( void *ctx, int level, const char *str )
@ -122,6 +142,43 @@ static void my_debug( void *ctx, int level, const char *str )
}
}
/*
* Test recv/send functions that make sure each try returns
* WANT_READ/WANT_WRITE at least once before sucesseding
*/
static int my_recv( void *ctx, unsigned char *buf, size_t len )
{
static int first_try = 1;
int ret;
if( first_try )
{
first_try = 0;
return( POLARSSL_ERR_NET_WANT_READ );
}
ret = net_recv( ctx, buf, len );
if( ret != POLARSSL_ERR_NET_WANT_READ )
first_try = 1; /* Next call will be a new operation */
return( ret );
}
static int my_send( void *ctx, const unsigned char *buf, size_t len )
{
static int first_try = 1;
int ret;
if( first_try )
{
first_try = 0;
return( POLARSSL_ERR_NET_WANT_WRITE );
}
ret = net_send( ctx, buf, len );
if( ret != POLARSSL_ERR_NET_WANT_WRITE )
first_try = 1; /* Next call will be a new operation */
return( ret );
}
#if defined(POLARSSL_X509_CRT_PARSE_C)
#if defined(POLARSSL_FS_IO)
@ -158,11 +215,28 @@ static void my_debug( void *ctx, int level, const char *str )
#if defined(POLARSSL_SSL_SESSION_TICKETS)
#define USAGE_TICKETS \
" tickets=%%d default: 1 (enabled)\n"
" tickets=%%d default: 1 (enabled)\n" \
" ticket_timeout=%%d default: ticket default (1d)\n"
#else
#define USAGE_TICKETS ""
#endif /* POLARSSL_SSL_SESSION_TICKETS */
#if defined(POLARSSL_SSL_CACHE_C)
#define USAGE_CACHE \
" cache_max=%%d default: cache default (50)\n" \
" cache_timeout=%%d default: cache default (1d)\n"
#else
#define USAGE_CACHE ""
#endif /* POLARSSL_SSL_CACHE_C */
#if defined(POLARSSL_SNI)
#define USAGE_SNI \
" sni=%%s name1,cert1,key1[,name2,cert2,key2[,...]]\n" \
" default: disabled\n"
#else
#define USAGE_SNI ""
#endif /* POLARSSL_SNI */
#if defined(POLARSSL_SSL_MAX_FRAGMENT_LENGTH)
#define USAGE_MAX_FRAG_LEN \
" max_frag_len=%%d default: 16384 (tls default)\n" \
@ -177,19 +251,27 @@ static void my_debug( void *ctx, int level, const char *str )
" server_addr=%%d default: (all interfaces)\n" \
" server_port=%%d default: 4433\n" \
" debug_level=%%d default: 0 (disabled)\n" \
" nbio=%%d default: 0 (blocking I/O)\n" \
" options: 1 (non-blocking), 2 (added delays)\n" \
"\n" \
" auth_mode=%%s default: \"optional\"\n" \
" options: none, optional, required\n" \
USAGE_IO \
" request_page=%%s default: \".\"\n" \
USAGE_SNI \
"\n" \
USAGE_PSK \
"\n" \
" renegotiation=%%d default: 1 (enabled)\n" \
USAGE_TICKETS \
" allow_legacy=%%d default: 0 (disabled)\n" \
" renegotiate=%%d default: 0 (disabled)\n" \
USAGE_TICKETS \
USAGE_CACHE \
USAGE_MAX_FRAG_LEN \
"\n" \
" min_version=%%s default: \"ssl3\"\n" \
" max_version=%%s default: \"tls1_2\"\n" \
" force_version=%%s default: \"\" (none)\n" \
" options: ssl3, tls1, tls1_1, tls1_2\n" \
" auth_mode=%%s default: \"optional\"\n" \
" options: none, optional, required\n" \
USAGE_MAX_FRAG_LEN \
USAGE_PSK \
"\n" \
" force_ciphersuite=<name> default: all enabled\n"\
" acceptable ciphersuite names:\n"
@ -208,6 +290,116 @@ int main( int argc, char *argv[] )
return( 0 );
}
#else
#if defined(POLARSSL_SNI)
typedef struct _sni_entry sni_entry;
struct _sni_entry {
const char *name;
x509_crt *cert;
pk_context *key;
sni_entry *next;
};
/*
* Parse a string of triplets name1,crt1,key1[,name2,crt2,key2[,...]]
* into a usable sni_entry list.
*
* Note: this is not production quality: leaks memory if parsing fails,
* and error reporting is poor.
*/
sni_entry *sni_parse( char *sni_string )
{
sni_entry *cur = NULL, *new = NULL;
char *p = sni_string;
char *end = p;
char *crt_file, *key_file;
while( *end != '\0' )
++end;
*end = ',';
while( p <= end )
{
if( ( new = polarssl_malloc( sizeof( sni_entry ) ) ) == NULL )
return( NULL );
memset( new, 0, sizeof( sni_entry ) );
if( ( new->cert = polarssl_malloc( sizeof( x509_crt ) ) ) == NULL ||
( new->key = polarssl_malloc( sizeof( pk_context ) ) ) == NULL )
return( NULL );
x509_crt_init( new->cert );
pk_init( new->key );
new->name = p;
while( *p != ',' ) if( ++p > end ) return( NULL );
*p++ = '\0';
crt_file = p;
while( *p != ',' ) if( ++p > end ) return( NULL );
*p++ = '\0';
key_file = p;
while( *p != ',' ) if( ++p > end ) return( NULL );
*p++ = '\0';
if( x509_crt_parse_file( new->cert, crt_file ) != 0 ||
pk_parse_keyfile( new->key, key_file, "" ) != 0 )
return( NULL );
new->next = cur;
cur = new;
}
return( cur );
}
void sni_free( sni_entry *head )
{
sni_entry *cur = head, *next;
while( cur != NULL )
{
x509_crt_free( cur->cert );
polarssl_free( cur->cert );
pk_free( cur->key );
polarssl_free( cur->key );
next = cur->next;
polarssl_free( cur );
cur = next;
}
}
/*
* SNI callback.
*/
int sni_callback( void *p_info, ssl_context *ssl,
const unsigned char *name, size_t name_len )
{
sni_entry *cur = (sni_entry *) p_info;
while( cur != NULL )
{
if( name_len == strlen( cur->name ) &&
memcmp( name, cur->name, name_len ) == 0 )
{
ssl_set_own_cert( ssl, cur->cert, cur->key );
return( 0 );
}
cur = cur->next;
}
return( -1 );
}
#endif /* POLARSSL_SNI */
int main( int argc, char *argv[] )
{
int ret = 0, len, written, frags;
@ -234,6 +426,9 @@ int main( int argc, char *argv[] )
#if defined(POLARSSL_SSL_CACHE_C)
ssl_cache_context cache;
#endif
#if defined(POLARSSL_SNI)
sni_entry *sni_info = NULL;
#endif
#if defined(POLARSSL_MEMORY_BUFFER_ALLOC_C)
unsigned char alloc_buf[100000];
#endif
@ -287,6 +482,7 @@ int main( int argc, char *argv[] )
opt.server_addr = DFL_SERVER_ADDR;
opt.server_port = DFL_SERVER_PORT;
opt.debug_level = DFL_DEBUG_LEVEL;
opt.nbio = DFL_NBIO;
opt.ca_file = DFL_CA_FILE;
opt.ca_path = DFL_CA_PATH;
opt.crt_file = DFL_CRT_FILE;
@ -298,11 +494,16 @@ int main( int argc, char *argv[] )
opt.force_ciphersuite[0]= DFL_FORCE_CIPHER;
opt.renegotiation = DFL_RENEGOTIATION;
opt.allow_legacy = DFL_ALLOW_LEGACY;
opt.renegotiate = DFL_RENEGOTIATE;
opt.min_version = DFL_MIN_VERSION;
opt.max_version = DFL_MAX_VERSION;
opt.auth_mode = DFL_AUTH_MODE;
opt.mfl_code = DFL_MFL_CODE;
opt.tickets = DFL_TICKETS;
opt.ticket_timeout = DFL_TICKET_TIMEOUT;
opt.cache_max = DFL_CACHE_MAX;
opt.cache_timeout = DFL_CACHE_TIMEOUT;
opt.sni = DFL_SNI;
for( i = 1; i < argc; i++ )
{
@ -325,6 +526,12 @@ int main( int argc, char *argv[] )
if( opt.debug_level < 0 || opt.debug_level > 65535 )
goto usage;
}
else if( strcmp( p, "nbio" ) == 0 )
{
opt.nbio = atoi( q );
if( opt.nbio < 0 || opt.nbio > 2 )
goto usage;
}
else if( strcmp( p, "ca_file" ) == 0 )
opt.ca_file = q;
else if( strcmp( p, "ca_path" ) == 0 )
@ -365,6 +572,12 @@ int main( int argc, char *argv[] )
if( opt.allow_legacy < 0 || opt.allow_legacy > 1 )
goto usage;
}
else if( strcmp( p, "renegotiate" ) == 0 )
{
opt.renegotiate = atoi( q );
if( opt.renegotiate < 0 || opt.renegotiate > 1 )
goto usage;
}
else if( strcmp( p, "min_version" ) == 0 )
{
if( strcmp( q, "ssl3" ) == 0 )
@ -446,6 +659,28 @@ int main( int argc, char *argv[] )
if( opt.tickets < 0 || opt.tickets > 1 )
goto usage;
}
else if( strcmp( p, "ticket_timeout" ) == 0 )
{
opt.ticket_timeout = atoi( q );
if( opt.ticket_timeout < 0 )
goto usage;
}
else if( strcmp( p, "cache_max" ) == 0 )
{
opt.cache_max = atoi( q );
if( opt.cache_max < 0 )
goto usage;
}
else if( strcmp( p, "cache_timeout" ) == 0 )
{
opt.cache_timeout = atoi( q );
if( opt.cache_timeout < 0 )
goto usage;
}
else if( strcmp( p, "sni" ) == 0 )
{
opt.sni = q;
}
else
goto usage;
}
@ -551,9 +786,15 @@ int main( int argc, char *argv[] )
#if defined(POLARSSL_FS_IO)
if( strlen( opt.ca_path ) )
ret = x509_crt_parse_path( &cacert, opt.ca_path );
if( strcmp( opt.ca_path, "none" ) == 0 )
ret = 0;
else
ret = x509_crt_parse_path( &cacert, opt.ca_path );
else if( strlen( opt.ca_file ) )
ret = x509_crt_parse_file( &cacert, opt.ca_file );
if( strcmp( opt.ca_file, "none" ) == 0 )
ret = 0;
else
ret = x509_crt_parse_file( &cacert, opt.ca_file );
else
#endif
#if defined(POLARSSL_CERTS_C)
@ -580,7 +821,7 @@ int main( int argc, char *argv[] )
fflush( stdout );
#if defined(POLARSSL_FS_IO)
if( strlen( opt.crt_file ) )
if( strlen( opt.crt_file ) && strcmp( opt.crt_file, "none" ) != 0 )
{
key_cert_init++;
if( ( ret = x509_crt_parse_file( &srvcert, opt.crt_file ) ) != 0 )
@ -590,7 +831,7 @@ int main( int argc, char *argv[] )
goto exit;
}
}
if( strlen( opt.key_file ) )
if( strlen( opt.key_file ) && strcmp( opt.key_file, "none" ) != 0 )
{
key_cert_init++;
if( ( ret = pk_parse_keyfile( &pkey, opt.key_file, "" ) ) != 0 )
@ -605,7 +846,7 @@ int main( int argc, char *argv[] )
goto exit;
}
if( strlen( opt.crt_file2 ) )
if( strlen( opt.crt_file2 ) && strcmp( opt.crt_file2, "none" ) != 0 )
{
key_cert_init2++;
if( ( ret = x509_crt_parse_file( &srvcert2, opt.crt_file2 ) ) != 0 )
@ -615,7 +856,7 @@ int main( int argc, char *argv[] )
goto exit;
}
}
if( strlen( opt.key_file2 ) )
if( strlen( opt.key_file2 ) && strcmp( opt.key_file2, "none" ) != 0 )
{
key_cert_init2++;
if( ( ret = pk_parse_keyfile( &pkey2, opt.key_file2, "" ) ) != 0 )
@ -631,7 +872,12 @@ int main( int argc, char *argv[] )
goto exit;
}
#endif
if( key_cert_init == 0 && key_cert_init2 == 0 )
if( key_cert_init == 0 &&
strcmp( opt.crt_file, "none" ) != 0 &&
strcmp( opt.key_file, "none" ) != 0 &&
key_cert_init2 == 0 &&
strcmp( opt.crt_file2, "none" ) != 0 &&
strcmp( opt.key_file2, "none" ) != 0 )
{
#if !defined(POLARSSL_CERTS_C)
printf( "Not certificated or key provided, and \n"
@ -678,6 +924,22 @@ int main( int argc, char *argv[] )
printf( " ok\n" );
#endif /* POLARSSL_X509_CRT_PARSE_C */
#if defined(POLARSSL_SNI)
if( opt.sni != NULL )
{
printf( " . Setting up SNI information..." );
fflush( stdout );
if( ( sni_info = sni_parse( opt.sni ) ) == NULL )
{
printf( " failed\n" );
goto exit;
}
printf( " ok\n" );
}
#endif /* POLARSSL_SNI */
/*
* 2. Setup the listening TCP socket
*/
@ -716,12 +978,21 @@ int main( int argc, char *argv[] )
ssl_set_dbg( &ssl, my_debug, stdout );
#if defined(POLARSSL_SSL_CACHE_C)
if( opt.cache_max != -1 )
ssl_cache_set_max_entries( &cache, opt.cache_max );
if( opt.cache_timeout != -1 )
ssl_cache_set_timeout( &cache, opt.cache_timeout );
ssl_set_session_cache( &ssl, ssl_cache_get, &cache,
ssl_cache_set, &cache );
#endif
#if defined(POLARSSL_SSL_SESSION_TICKETS)
ssl_set_session_tickets( &ssl, opt.tickets );
if( opt.ticket_timeout != -1 )
ssl_set_session_ticket_lifetime( &ssl, opt.ticket_timeout );
#endif
if( opt.force_ciphersuite[0] != DFL_FORCE_CIPHER )
@ -731,13 +1002,22 @@ int main( int argc, char *argv[] )
ssl_legacy_renegotiation( &ssl, opt.allow_legacy );
#if defined(POLARSSL_X509_CRT_PARSE_C)
ssl_set_ca_chain( &ssl, &cacert, NULL, NULL );
if( strcmp( opt.ca_path, "none" ) != 0 &&
strcmp( opt.ca_file, "none" ) != 0 )
{
ssl_set_ca_chain( &ssl, &cacert, NULL, NULL );
}
if( key_cert_init )
ssl_set_own_cert( &ssl, &srvcert, &pkey );
if( key_cert_init2 )
ssl_set_own_cert( &ssl, &srvcert2, &pkey2 );
#endif
#if defined(POLARSSL_SNI)
if( opt.sni != NULL )
ssl_set_sni( &ssl, sni_callback, sni_info );
#endif
#if defined(POLARSSL_KEY_EXCHANGE__SOME__PSK_ENABLED)
ssl_set_psk( &ssl, psk, psk_len, (const unsigned char *) opt.psk_identity,
strlen( opt.psk_identity ) );
@ -788,8 +1068,20 @@ reset:
goto exit;
}
ssl_set_bio( &ssl, net_recv, &client_fd,
net_send, &client_fd );
if( opt.nbio > 0 )
ret = net_set_nonblock( client_fd );
else
ret = net_set_block( client_fd );
if( ret != 0 )
{
printf( " failed\n ! net_set_(non)block() returned -0x%x\n\n", -ret );
goto exit;
}
if( opt.nbio == 2 )
ssl_set_bio( &ssl, my_recv, &client_fd, my_send, &client_fd );
else
ssl_set_bio( &ssl, net_recv, &client_fd, net_send, &client_fd );
printf( " ok\n" );
@ -926,43 +1218,48 @@ reset:
buf[written] = '\0';
printf( " %d bytes written in %d fragments\n\n%s\n", written, frags, (char *) buf );
#ifdef TEST_RENEGO
/*
* Request renegotiation (this must be done when the client is still
* waiting for input from our side).
*/
printf( " . Requestion renegotiation..." );
fflush( stdout );
while( ( ret = ssl_renegotiate( &ssl ) ) != 0 )
if( opt.renegotiate )
{
if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
/*
* Request renegotiation (this must be done when the client is still
* waiting for input from our side).
*/
printf( " . Requestion renegotiation..." );
fflush( stdout );
while( ( ret = ssl_renegotiate( &ssl ) ) != 0 )
{
printf( " failed\n ! ssl_renegotiate returned %d\n\n", ret );
goto exit;
}
}
/*
* Should be a while loop, not an if, but here we're not actually
* expecting data from the client, and since we're running tests locally,
* we can just hope the handshake will finish the during the first call.
*/
if( ( ret = ssl_read( &ssl, buf, 0 ) ) != 0 )
{
if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
{
printf( " failed\n ! ssl_read returned %d\n\n", ret );
/* Unexpected message probably means client didn't renegotiate */
if( ret == POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE )
goto reset;
else
if( ret != POLARSSL_ERR_NET_WANT_READ &&
ret != POLARSSL_ERR_NET_WANT_WRITE )
{
printf( " failed\n ! ssl_renegotiate returned %d\n\n", ret );
goto exit;
}
}
}
printf( " ok\n" );
#endif
/*
* Should be a while loop, not an if, but here we're not actually
* expecting data from the client, and since we're running tests
* locally, we can just hope the handshake will finish the during the
* first call.
*/
if( ( ret = ssl_read( &ssl, buf, 0 ) ) != 0 )
{
if( ret != POLARSSL_ERR_NET_WANT_READ &&
ret != POLARSSL_ERR_NET_WANT_WRITE )
{
printf( " failed\n ! ssl_read returned %d\n\n", ret );
/* Unexpected message probably means client didn't renegotiate
* as requested */
if( ret == POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE )
goto reset;
else
goto exit;
}
}
printf( " ok\n" );
}
ret = 0;
goto reset;
@ -986,6 +1283,9 @@ exit:
x509_crt_free( &srvcert2 );
pk_free( &pkey2 );
#endif
#if defined(POLARSSL_SNI)
sni_free( sni_info );
#endif
ssl_free( &ssl );
entropy_free( &entropy );

16
tests/Descriptions.txt Normal file
View File

@ -0,0 +1,16 @@
test_suites
The various 'test_suite_XXX' programs from the 'tests' directory, executed
using 'make check' (Unix make) or 'make test' (Cmake), include test cases
(reference test vectors, sanity checks, etc.) for all modules except the
SSL modules.
compat
The 'tests/compat.sh' script checks interoperability with OpenSSL for every
ciphersuite, in every version, using client authentication or not. For
each ciphersuite/version it performs a full handshake and a small data
exchange.
ssl_opt
The 'tests/ssl-opt.sh' script checks various options and/or operations not
covered by compat.sh: session resumption (using session cache or tickets),
renegotiation, SNI, other extensions, etc.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
Client_identity:6162636465666768696a6b6c6d6e6f70

887
tests/ssl-opt.sh Executable file
View File

@ -0,0 +1,887 @@
#!/bin/sh
# Test various options that are not covered by compat.sh
#
# Here the goal is not to cover every ciphersuite/version, but
# rather specific options (max fragment length, truncated hmac, etc)
# or procedures (session resumption from cache or ticket, renego, etc).
#
# Assumes all options are compiled in.
set -u
# default values, can be overriden by the environment
: ${P_SRV:=../programs/ssl/ssl_server2}
: ${P_CLI:=../programs/ssl/ssl_client2}
: ${OPENSSL_CMD:=openssl} # OPENSSL would conflict with the build system
O_SRV="$OPENSSL_CMD s_server -www -cert data_files/server5.crt -key data_files/server5.key"
O_CLI="echo 'GET / HTTP/1.0' | $OPENSSL_CMD s_client"
TESTS=0
FAILS=0
MEMCHECK=0
FILTER='.*'
EXCLUDE='SSLv2' # disabled by default, needs OpenSSL compiled with SSLv2
print_usage() {
echo "Usage: $0 [options]"
echo -e " -h|--help\tPrint this help."
echo -e " -m|--memcheck\tCheck memory leaks and errors."
echo -e " -f|--filter\tOnly matching tests are executed (default: '$FILTER')"
echo -e " -e|--exclude\tMatching tests are excluded (default: '$EXCLUDE')"
}
get_options() {
while [ $# -gt 0 ]; do
case "$1" in
-f|--filter)
shift; FILTER=$1
;;
-e|--exclude)
shift; EXCLUDE=$1
;;
-m|--memcheck)
MEMCHECK=1
;;
-h|--help)
print_usage
exit 0
;;
*)
echo "Unkown argument: '$1'"
print_usage
exit 1
;;
esac
shift
done
}
# print_name <name>
print_name() {
echo -n "$1 "
LEN=`echo "$1" | wc -c`
LEN=`echo 72 - $LEN | bc`
for i in `seq 1 $LEN`; do echo -n '.'; done
echo -n ' '
TESTS=`echo $TESTS + 1 | bc`
}
# fail <message>
fail() {
echo "FAIL"
echo " ! $1"
cp srv_out o-srv-${TESTS}.log
cp cli_out o-cli-${TESTS}.log
echo " ! outputs saved to o-srv-${TESTS}.log and o-cli-${TESTS}.log"
FAILS=`echo $FAILS + 1 | bc`
}
# is_polar <cmd_line>
is_polar() {
echo "$1" | grep 'ssl_server2\|ssl_client2' > /dev/null
}
# has_mem_err <log_file_name>
has_mem_err() {
if ( grep -F 'All heap blocks were freed -- no leaks are possible' "$1" &&
grep -F 'ERROR SUMMARY: 0 errors from 0 contexts' "$1" ) > /dev/null
then
return 1 # false: does not have errors
else
return 0 # true: has errors
fi
}
# Usage: run_test name srv_cmd cli_cmd cli_exit [option [...]]
# Options: -s pattern pattern that must be present in server output
# -c pattern pattern that must be present in client output
# -S pattern pattern that must be absent in server output
# -C pattern pattern that must be absent in client output
run_test() {
NAME="$1"
SRV_CMD="$2"
CLI_CMD="$3"
CLI_EXPECT="$4"
shift 4
if echo "$NAME" | grep "$FILTER" | grep -v "$EXCLUDE" >/dev/null; then :
else
return
fi
print_name "$NAME"
# prepend valgrind to our commands if active
if [ "$MEMCHECK" -gt 0 ]; then
if is_polar "$SRV_CMD"; then
SRV_CMD="valgrind --leak-check=full $SRV_CMD"
fi
if is_polar "$CLI_CMD"; then
CLI_CMD="valgrind --leak-check=full $CLI_CMD"
fi
fi
# run the commands
echo "$SRV_CMD" > srv_out
$SHELL -c "$SRV_CMD" >> srv_out 2>&1 &
SRV_PID=$!
sleep 1
echo "$CLI_CMD" > cli_out
$SHELL -c "$CLI_CMD" >> cli_out 2>&1
CLI_EXIT=$?
if is_polar "$SRV_CMD"; then
"$P_CLI" request_page=SERVERQUIT tickets=0 auth_mode=none \
crt_file=data_files/cli2.crt key_file=data_files/cli2.key \
>/dev/null
else
kill $SRV_PID
fi
wait $SRV_PID
# check if the client and server went at least to the handshake stage
# (usefull to avoid tests with only negative assertions and non-zero
# expected client exit to incorrectly succeed in case of catastrophic
# failure)
if is_polar "$SRV_CMD"; then
if grep "Performing the SSL/TLS handshake" srv_out >/dev/null; then :;
else
fail "server failed to start"
return
fi
fi
if is_polar "$CLI_CMD"; then
if grep "Performing the SSL/TLS handshake" cli_out >/dev/null; then :;
else
fail "client failed to start"
return
fi
fi
# check server exit code
if [ $? != 0 ]; then
fail "server fail"
return
fi
# check client exit code
if [ \( "$CLI_EXPECT" = 0 -a "$CLI_EXIT" != 0 \) -o \
\( "$CLI_EXPECT" != 0 -a "$CLI_EXIT" = 0 \) ]
then
fail "bad client exit code"
return
fi
# check other assertions
while [ $# -gt 0 ]
do
case $1 in
"-s")
if grep "$2" srv_out >/dev/null; then :; else
fail "-s $2"
return
fi
;;
"-c")
if grep "$2" cli_out >/dev/null; then :; else
fail "-c $2"
return
fi
;;
"-S")
if grep "$2" srv_out >/dev/null; then
fail "-S $2"
return
fi
;;
"-C")
if grep "$2" cli_out >/dev/null; then
fail "-C $2"
return
fi
;;
*)
echo "Unkown test: $1" >&2
exit 1
esac
shift 2
done
# check valgrind's results
if [ "$MEMCHECK" -gt 0 ]; then
if is_polar "$SRV_CMD" && has_mem_err srv_out; then
fail "Server has memory errors"
return
fi
if is_polar "$CLI_CMD" && has_mem_err cli_out; then
fail "Client has memory errors"
return
fi
fi
# if we're here, everything is ok
echo "PASS"
rm -f srv_out cli_out
}
cleanup() {
rm -f cli_out srv_out sess
kill $SRV_PID
exit 1
}
#
# MAIN
#
# sanity checks, avoid an avalanche of errors
if [ ! -x "$P_SRV" ]; then
echo "Command '$P_SRV' is not an executable file"
exit 1
fi
if [ ! -x "$P_CLI" ]; then
echo "Command '$P_CLI' is not an executable file"
exit 1
fi
if which $OPENSSL_CMD >/dev/null 2>&1; then :; else
echo "Command '$OPENSSL_CMD' not found"
exit 1
fi
get_options "$@"
killall -q openssl ssl_server ssl_server2
trap cleanup INT TERM HUP
# Test for SSLv2 ClientHello
run_test "SSLv2 ClientHello #0 (reference)" \
"$P_SRV debug_level=3" \
"$O_CLI -no_ssl2" \
0 \
-S "parse client hello v2" \
-S "ssl_handshake returned"
# Adding a SSL2-only suite makes OpenSSL client send SSLv2 ClientHello
run_test "SSLv2 ClientHello #1 (actual test)" \
"$P_SRV debug_level=3" \
"$O_CLI -cipher 'DES-CBC-MD5:ALL'" \
0 \
-s "parse client hello v2" \
-S "ssl_handshake returned"
# Tests for Truncated HMAC extension
run_test "Truncated HMAC #0" \
"$P_SRV debug_level=5" \
"$P_CLI trunc_hmac=0 force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \
0 \
-s "dumping 'computed mac' (20 bytes)"
run_test "Truncated HMAC #1" \
"$P_SRV debug_level=5" \
"$P_CLI trunc_hmac=1 force_ciphersuite=TLS-RSA-WITH-AES-128-CBC-SHA" \
0 \
-s "dumping 'computed mac' (10 bytes)"
# Tests for Session Tickets
run_test "Session resume using tickets #1 (basic)" \
"$P_SRV debug_level=4 tickets=1" \
"$P_CLI debug_level=4 tickets=1 reconnect=1" \
0 \
-c "client hello, adding session ticket extension" \
-s "found session ticket extension" \
-s "server hello, adding session ticket extension" \
-c "found session_ticket extension" \
-c "parse new session ticket" \
-S "session successfully restored from cache" \
-s "session successfully restored from ticket" \
-s "a session has been resumed" \
-c "a session has been resumed"
run_test "Session resume using tickets #2 (cache disabled)" \
"$P_SRV debug_level=4 tickets=1 cache_max=0" \
"$P_CLI debug_level=4 tickets=1 reconnect=1" \
0 \
-c "client hello, adding session ticket extension" \
-s "found session ticket extension" \
-s "server hello, adding session ticket extension" \
-c "found session_ticket extension" \
-c "parse new session ticket" \
-S "session successfully restored from cache" \
-s "session successfully restored from ticket" \
-s "a session has been resumed" \
-c "a session has been resumed"
run_test "Session resume using tickets #3 (timeout)" \
"$P_SRV debug_level=4 tickets=1 cache_max=0 ticket_timeout=1" \
"$P_CLI debug_level=4 tickets=1 reconnect=1 reco_delay=2" \
0 \
-c "client hello, adding session ticket extension" \
-s "found session ticket extension" \
-s "server hello, adding session ticket extension" \
-c "found session_ticket extension" \
-c "parse new session ticket" \
-S "session successfully restored from cache" \
-S "session successfully restored from ticket" \
-S "a session has been resumed" \
-C "a session has been resumed"
run_test "Session resume using tickets #4 (openssl server)" \
"$O_SRV" \
"$P_CLI debug_level=4 tickets=1 reconnect=1" \
0 \
-c "client hello, adding session ticket extension" \
-c "found session_ticket extension" \
-c "parse new session ticket" \
-c "a session has been resumed"
run_test "Session resume using tickets #5 (openssl client)" \
"$P_SRV debug_level=4 tickets=1" \
"($O_CLI -sess_out sess; $O_CLI -sess_in sess; rm -f sess)" \
0 \
-s "found session ticket extension" \
-s "server hello, adding session ticket extension" \
-S "session successfully restored from cache" \
-s "session successfully restored from ticket" \
-s "a session has been resumed"
# Tests for Session Resume based on session-ID and cache
run_test "Session resume using cache #1 (tickets enabled on client)" \
"$P_SRV debug_level=4 tickets=0" \
"$P_CLI debug_level=4 tickets=1 reconnect=1" \
0 \
-c "client hello, adding session ticket extension" \
-s "found session ticket extension" \
-S "server hello, adding session ticket extension" \
-C "found session_ticket extension" \
-C "parse new session ticket" \
-s "session successfully restored from cache" \
-S "session successfully restored from ticket" \
-s "a session has been resumed" \
-c "a session has been resumed"
run_test "Session resume using cache #2 (tickets enabled on server)" \
"$P_SRV debug_level=4 tickets=1" \
"$P_CLI debug_level=4 tickets=0 reconnect=1" \
0 \
-C "client hello, adding session ticket extension" \
-S "found session ticket extension" \
-S "server hello, adding session ticket extension" \
-C "found session_ticket extension" \
-C "parse new session ticket" \
-s "session successfully restored from cache" \
-S "session successfully restored from ticket" \
-s "a session has been resumed" \
-c "a session has been resumed"
run_test "Session resume using cache #3 (cache_max=0)" \
"$P_SRV debug_level=4 tickets=0 cache_max=0" \
"$P_CLI debug_level=4 tickets=0 reconnect=1" \
0 \
-S "session successfully restored from cache" \
-S "session successfully restored from ticket" \
-S "a session has been resumed" \
-C "a session has been resumed"
run_test "Session resume using cache #4 (cache_max=1)" \
"$P_SRV debug_level=4 tickets=0 cache_max=1" \
"$P_CLI debug_level=4 tickets=0 reconnect=1" \
0 \
-s "session successfully restored from cache" \
-S "session successfully restored from ticket" \
-s "a session has been resumed" \
-c "a session has been resumed"
run_test "Session resume using cache #5 (timemout > delay)" \
"$P_SRV debug_level=4 tickets=0" \
"$P_CLI debug_level=4 tickets=0 reconnect=1 reco_delay=0" \
0 \
-s "session successfully restored from cache" \
-S "session successfully restored from ticket" \
-s "a session has been resumed" \
-c "a session has been resumed"
run_test "Session resume using cache #6 (timeout < delay)" \
"$P_SRV debug_level=4 tickets=0 cache_timeout=1" \
"$P_CLI debug_level=4 tickets=0 reconnect=1 reco_delay=2" \
0 \
-S "session successfully restored from cache" \
-S "session successfully restored from ticket" \
-S "a session has been resumed" \
-C "a session has been resumed"
run_test "Session resume using cache #7 (no timeout)" \
"$P_SRV debug_level=4 tickets=0 cache_timeout=0" \
"$P_CLI debug_level=4 tickets=0 reconnect=1 reco_delay=2" \
0 \
-s "session successfully restored from cache" \
-S "session successfully restored from ticket" \
-s "a session has been resumed" \
-c "a session has been resumed"
run_test "Session resume using cache #8 (openssl client)" \
"$P_SRV debug_level=4 tickets=0" \
"($O_CLI -sess_out sess; $O_CLI -sess_in sess; rm -f sess)" \
0 \
-s "found session ticket extension" \
-S "server hello, adding session ticket extension" \
-s "session successfully restored from cache" \
-S "session successfully restored from ticket" \
-s "a session has been resumed"
run_test "Session resume using cache #9 (openssl server)" \
"$O_SRV" \
"$P_CLI debug_level=4 tickets=0 reconnect=1" \
0 \
-C "found session_ticket extension" \
-C "parse new session ticket" \
-c "a session has been resumed"
# Tests for Max Fragment Length extension
run_test "Max fragment length #1" \
"$P_SRV debug_level=4" \
"$P_CLI debug_level=4" \
0 \
-C "client hello, adding max_fragment_length extension" \
-S "found max fragment length extension" \
-S "server hello, max_fragment_length extension" \
-C "found max_fragment_length extension"
run_test "Max fragment length #2" \
"$P_SRV debug_level=4" \
"$P_CLI debug_level=4 max_frag_len=4096" \
0 \
-c "client hello, adding max_fragment_length extension" \
-s "found max fragment length extension" \
-s "server hello, max_fragment_length extension" \
-c "found max_fragment_length extension"
run_test "Max fragment length #3" \
"$P_SRV debug_level=4 max_frag_len=4096" \
"$P_CLI debug_level=4" \
0 \
-C "client hello, adding max_fragment_length extension" \
-S "found max fragment length extension" \
-S "server hello, max_fragment_length extension" \
-C "found max_fragment_length extension"
# Tests for renegotiation
run_test "Renegotiation #0 (none)" \
"$P_SRV debug_level=4" \
"$P_CLI debug_level=4" \
0 \
-C "client hello, adding renegotiation extension" \
-s "received TLS_EMPTY_RENEGOTIATION_INFO" \
-S "found renegotiation extension" \
-s "server hello, secure renegotiation extension" \
-c "found renegotiation extension" \
-C "=> renegotiate" \
-S "=> renegotiate" \
-S "write hello request"
run_test "Renegotiation #1 (enabled, client-initiated)" \
"$P_SRV debug_level=4" \
"$P_CLI debug_level=4 renegotiate=1" \
0 \
-c "client hello, adding renegotiation extension" \
-s "received TLS_EMPTY_RENEGOTIATION_INFO" \
-s "found renegotiation extension" \
-s "server hello, secure renegotiation extension" \
-c "found renegotiation extension" \
-c "=> renegotiate" \
-s "=> renegotiate" \
-S "write hello request"
run_test "Renegotiation #2 (enabled, server-initiated)" \
"$P_SRV debug_level=4 renegotiate=1" \
"$P_CLI debug_level=4" \
0 \
-c "client hello, adding renegotiation extension" \
-s "received TLS_EMPTY_RENEGOTIATION_INFO" \
-s "found renegotiation extension" \
-s "server hello, secure renegotiation extension" \
-c "found renegotiation extension" \
-c "=> renegotiate" \
-s "=> renegotiate" \
-s "write hello request"
run_test "Renegotiation #3 (enabled, double)" \
"$P_SRV debug_level=4 renegotiate=1" \
"$P_CLI debug_level=4 renegotiate=1" \
0 \
-c "client hello, adding renegotiation extension" \
-s "received TLS_EMPTY_RENEGOTIATION_INFO" \
-s "found renegotiation extension" \
-s "server hello, secure renegotiation extension" \
-c "found renegotiation extension" \
-c "=> renegotiate" \
-s "=> renegotiate" \
-s "write hello request"
run_test "Renegotiation #4 (client-initiated, server-rejected)" \
"$P_SRV debug_level=4 renegotiation=0" \
"$P_CLI debug_level=4 renegotiate=1" \
1 \
-c "client hello, adding renegotiation extension" \
-s "received TLS_EMPTY_RENEGOTIATION_INFO" \
-S "found renegotiation extension" \
-s "server hello, secure renegotiation extension" \
-c "found renegotiation extension" \
-c "=> renegotiate" \
-S "=> renegotiate" \
-S "write hello request"
run_test "Renegotiation #5 (server-initiated, client-rejected)" \
"$P_SRV debug_level=4 renegotiate=1" \
"$P_CLI debug_level=4 renegotiation=0" \
0 \
-C "client hello, adding renegotiation extension" \
-s "received TLS_EMPTY_RENEGOTIATION_INFO" \
-S "found renegotiation extension" \
-s "server hello, secure renegotiation extension" \
-c "found renegotiation extension" \
-C "=> renegotiate" \
-S "=> renegotiate" \
-s "write hello request" \
-s "SSL - An unexpected message was received from our peer" \
-s "failed"
# Tests for auth_mode
run_test "Authentication #1 (server badcert, client required)" \
"$P_SRV crt_file=data_files/server5-badsign.crt \
key_file=data_files/server5.key" \
"$P_CLI debug_level=2 auth_mode=required" \
1 \
-c "x509_verify_cert() returned" \
-c "! self-signed or not signed by a trusted CA" \
-c "! ssl_handshake returned" \
-c "X509 - Certificate verification failed"
run_test "Authentication #2 (server badcert, client optional)" \
"$P_SRV crt_file=data_files/server5-badsign.crt \
key_file=data_files/server5.key" \
"$P_CLI debug_level=2 auth_mode=optional" \
0 \
-c "x509_verify_cert() returned" \
-c "! self-signed or not signed by a trusted CA" \
-C "! ssl_handshake returned" \
-C "X509 - Certificate verification failed"
run_test "Authentication #3 (server badcert, client none)" \
"$P_SRV crt_file=data_files/server5-badsign.crt \
key_file=data_files/server5.key" \
"$P_CLI debug_level=2 auth_mode=none" \
0 \
-C "x509_verify_cert() returned" \
-C "! self-signed or not signed by a trusted CA" \
-C "! ssl_handshake returned" \
-C "X509 - Certificate verification failed"
run_test "Authentication #4 (client badcert, server required)" \
"$P_SRV debug_level=4 auth_mode=required" \
"$P_CLI debug_level=4 crt_file=data_files/server5-badsign.crt \
key_file=data_files/server5.key" \
1 \
-S "skip write certificate request" \
-C "skip parse certificate request" \
-c "got a certificate request" \
-C "skip write certificate" \
-C "skip write certificate verify" \
-S "skip parse certificate verify" \
-s "x509_verify_cert() returned" \
-S "! self-signed or not signed by a trusted CA" \
-s "! ssl_handshake returned" \
-c "! ssl_handshake returned" \
-s "X509 - Certificate verification failed"
run_test "Authentication #5 (client badcert, server optional)" \
"$P_SRV debug_level=4 auth_mode=optional" \
"$P_CLI debug_level=4 crt_file=data_files/server5-badsign.crt \
key_file=data_files/server5.key" \
0 \
-S "skip write certificate request" \
-C "skip parse certificate request" \
-c "got a certificate request" \
-C "skip write certificate" \
-C "skip write certificate verify" \
-S "skip parse certificate verify" \
-s "x509_verify_cert() returned" \
-s "! self-signed or not signed by a trusted CA" \
-S "! ssl_handshake returned" \
-C "! ssl_handshake returned" \
-S "X509 - Certificate verification failed"
run_test "Authentication #6 (client badcert, server none)" \
"$P_SRV debug_level=4 auth_mode=none" \
"$P_CLI debug_level=4 crt_file=data_files/server5-badsign.crt \
key_file=data_files/server5.key" \
0 \
-s "skip write certificate request" \
-C "skip parse certificate request" \
-c "got no certificate request" \
-c "skip write certificate" \
-c "skip write certificate verify" \
-s "skip parse certificate verify" \
-S "x509_verify_cert() returned" \
-S "! self-signed or not signed by a trusted CA" \
-S "! ssl_handshake returned" \
-C "! ssl_handshake returned" \
-S "X509 - Certificate verification failed"
run_test "Authentication #7 (client no cert, server optional)" \
"$P_SRV debug_level=4 auth_mode=optional" \
"$P_CLI debug_level=4 crt_file=none key_file=none" \
0 \
-S "skip write certificate request" \
-C "skip parse certificate request" \
-c "got a certificate request" \
-C "skip write certificate$" \
-C "got no certificate to send" \
-S "SSLv3 client has no certificate" \
-c "skip write certificate verify" \
-s "skip parse certificate verify" \
-s "! no client certificate sent" \
-S "! ssl_handshake returned" \
-C "! ssl_handshake returned" \
-S "X509 - Certificate verification failed"
run_test "Authentication #8 (openssl client no cert, server optional)" \
"$P_SRV debug_level=4 auth_mode=optional" \
"$O_CLI" \
0 \
-S "skip write certificate request" \
-s "skip parse certificate verify" \
-s "! no client certificate sent" \
-S "! ssl_handshake returned" \
-S "X509 - Certificate verification failed"
run_test "Authentication #9 (client no cert, openssl server optional)" \
"$O_SRV -verify 10" \
"$P_CLI debug_level=4 crt_file=none key_file=none" \
0 \
-C "skip parse certificate request" \
-c "got a certificate request" \
-C "skip write certificate$" \
-c "skip write certificate verify" \
-C "! ssl_handshake returned"
run_test "Authentication #10 (client no cert, ssl3)" \
"$P_SRV debug_level=4 auth_mode=optional force_version=ssl3" \
"$P_CLI debug_level=4 crt_file=none key_file=none" \
0 \
-S "skip write certificate request" \
-C "skip parse certificate request" \
-c "got a certificate request" \
-C "skip write certificate$" \
-c "skip write certificate verify" \
-c "got no certificate to send" \
-s "SSLv3 client has no certificate" \
-s "skip parse certificate verify" \
-s "! no client certificate sent" \
-S "! ssl_handshake returned" \
-C "! ssl_handshake returned" \
-S "X509 - Certificate verification failed"
# tests for SNI
run_test "SNI #0 (no SNI callback)" \
"$P_SRV debug_level=4 server_addr=127.0.0.1 \
crt_file=data_files/server5.crt key_file=data_files/server5.key" \
"$P_CLI debug_level=0 server_addr=127.0.0.1 \
server_name=localhost" \
0 \
-S "parse ServerName extension" \
-c "issuer name *: C=NL, O=PolarSSL, CN=Polarssl Test EC CA" \
-c "subject name *: C=NL, O=PolarSSL, CN=localhost"
run_test "SNI #1 (matching cert 1)" \
"$P_SRV debug_level=4 server_addr=127.0.0.1 \
crt_file=data_files/server5.crt key_file=data_files/server5.key \
sni='localhost,data_files/server2.crt,data_files/server2.key,PolarSSL Server 1,data_files/server1.crt,data_files/server1.key'" \
"$P_CLI debug_level=0 server_addr=127.0.0.1 \
server_name=localhost" \
0 \
-s "parse ServerName extension" \
-c "issuer name *: C=NL, O=PolarSSL, CN=PolarSSL Test CA" \
-c "subject name *: C=NL, O=PolarSSL, CN=localhost"
run_test "SNI #2 (matching cert 2)" \
"$P_SRV debug_level=4 server_addr=127.0.0.1 \
crt_file=data_files/server5.crt key_file=data_files/server5.key \
sni='localhost,data_files/server2.crt,data_files/server2.key,PolarSSL Server 1,data_files/server1.crt,data_files/server1.key'" \
"$P_CLI debug_level=0 server_addr=127.0.0.1 \
server_name='PolarSSL Server 1'" \
0 \
-s "parse ServerName extension" \
-c "issuer name *: C=NL, O=PolarSSL, CN=PolarSSL Test CA" \
-c "subject name *: C=NL, O=PolarSSL, CN=PolarSSL Server 1"
run_test "SNI #3 (no matching cert)" \
"$P_SRV debug_level=4 server_addr=127.0.0.1 \
crt_file=data_files/server5.crt key_file=data_files/server5.key \
sni='localhost,data_files/server2.crt,data_files/server2.key,PolarSSL Server 1,data_files/server1.crt,data_files/server1.key'" \
"$P_CLI debug_level=0 server_addr=127.0.0.1 \
server_name='PolarSSL Server 2'" \
1 \
-s "parse ServerName extension" \
-s "ssl_sni_wrapper() returned" \
-s "ssl_handshake returned" \
-c "ssl_handshake returned" \
-c "SSL - A fatal alert message was received from our peer"
# Tests for non-blocking I/O: exercise a variety of handshake flows
run_test "Non-blocking I/O #1 (basic handshake)" \
"$P_SRV nbio=2 tickets=0 auth_mode=none" \
"$P_CLI nbio=2 tickets=0" \
0 \
-S "ssl_handshake returned" \
-C "ssl_handshake returned" \
-c "Read from server: .* bytes read"
run_test "Non-blocking I/O #2 (client auth)" \
"$P_SRV nbio=2 tickets=0 auth_mode=required" \
"$P_CLI nbio=2 tickets=0" \
0 \
-S "ssl_handshake returned" \
-C "ssl_handshake returned" \
-c "Read from server: .* bytes read"
run_test "Non-blocking I/O #3 (ticket)" \
"$P_SRV nbio=2 tickets=1 auth_mode=none" \
"$P_CLI nbio=2 tickets=1" \
0 \
-S "ssl_handshake returned" \
-C "ssl_handshake returned" \
-c "Read from server: .* bytes read"
run_test "Non-blocking I/O #4 (ticket + client auth)" \
"$P_SRV nbio=2 tickets=1 auth_mode=required" \
"$P_CLI nbio=2 tickets=1" \
0 \
-S "ssl_handshake returned" \
-C "ssl_handshake returned" \
-c "Read from server: .* bytes read"
run_test "Non-blocking I/O #5 (ticket + client auth + resume)" \
"$P_SRV nbio=2 tickets=1 auth_mode=required" \
"$P_CLI nbio=2 tickets=1 reconnect=1" \
0 \
-S "ssl_handshake returned" \
-C "ssl_handshake returned" \
-c "Read from server: .* bytes read"
run_test "Non-blocking I/O #6 (ticket + resume)" \
"$P_SRV nbio=2 tickets=1 auth_mode=none" \
"$P_CLI nbio=2 tickets=1 reconnect=1" \
0 \
-S "ssl_handshake returned" \
-C "ssl_handshake returned" \
-c "Read from server: .* bytes read"
run_test "Non-blocking I/O #7 (session-id resume)" \
"$P_SRV nbio=2 tickets=0 auth_mode=none" \
"$P_CLI nbio=2 tickets=0 reconnect=1" \
0 \
-S "ssl_handshake returned" \
-C "ssl_handshake returned" \
-c "Read from server: .* bytes read"
run_test "Version check #1 (all -> 1.2)" \
"$P_SRV" \
"$P_CLI" \
0 \
-S "ssl_handshake returned" \
-C "ssl_handshake returned" \
-s "Protocol is TLSv1.2" \
-c "Protocol is TLSv1.2"
run_test "Version check #2 (cli max 1.1 -> 1.1)" \
"$P_SRV" \
"$P_CLI max_version=tls1_1" \
0 \
-S "ssl_handshake returned" \
-C "ssl_handshake returned" \
-s "Protocol is TLSv1.1" \
-c "Protocol is TLSv1.1"
run_test "Version check #3 (srv max 1.1 -> 1.1)" \
"$P_SRV max_version=tls1_1" \
"$P_CLI" \
0 \
-S "ssl_handshake returned" \
-C "ssl_handshake returned" \
-s "Protocol is TLSv1.1" \
-c "Protocol is TLSv1.1"
run_test "Version check #4 (cli+srv max 1.1 -> 1.1)" \
"$P_SRV max_version=tls1_1" \
"$P_CLI max_version=tls1_1" \
0 \
-S "ssl_handshake returned" \
-C "ssl_handshake returned" \
-s "Protocol is TLSv1.1" \
-c "Protocol is TLSv1.1"
run_test "Version check #5 (cli max 1.1, srv min 1.1 -> 1.1)" \
"$P_SRV min_version=tls1_1" \
"$P_CLI max_version=tls1_1" \
0 \
-S "ssl_handshake returned" \
-C "ssl_handshake returned" \
-s "Protocol is TLSv1.1" \
-c "Protocol is TLSv1.1"
run_test "Version check #6 (cli min 1.1, srv max 1.1 -> 1.1)" \
"$P_SRV max_version=tls1_1" \
"$P_CLI min_version=tls1_1" \
0 \
-S "ssl_handshake returned" \
-C "ssl_handshake returned" \
-s "Protocol is TLSv1.1" \
-c "Protocol is TLSv1.1"
run_test "Version check #7 (cli min 1.2, srv max 1.1 -> fail)" \
"$P_SRV max_version=tls1_1" \
"$P_CLI min_version=tls1_2" \
1 \
-s "ssl_handshake returned" \
-c "ssl_handshake returned" \
-c "SSL - Handshake protocol not within min/max boundaries"
run_test "Version check #8 (srv min 1.2, cli max 1.1 -> fail)" \
"$P_SRV min_version=tls1_2" \
"$P_CLI max_version=tls1_1" \
1 \
-s "ssl_handshake returned" \
-c "ssl_handshake returned" \
-s "SSL - Handshake protocol not within min/max boundaries"
# Final report
echo "------------------------------------------------------------------------"
if [ $FAILS = 0 ]; then
echo -n "PASSED"
else
echo -n "FAILED"
fi
PASSES=`echo $TESTS - $FAILS | bc`
echo " ($PASSES / $TESTS tests)"
exit $FAILS