diff --git a/include/polarssl/ssl.h b/include/polarssl/ssl.h index 7493fce5a..996460791 100644 --- a/include/polarssl/ssl.h +++ b/include/polarssl/ssl.h @@ -1136,6 +1136,16 @@ typedef int ssl_cookie_check_t( void *ctx, * \brief Register callbacks for DTLS cookies * (Server only. DTLS only.) * + * Default: dummy callbacks that fail, to force you to + * register working callbacks (and initialize their context). + * + * To disable HelloVerifyRequest, register NULL callbacks. + * + * \warning Disabling hello verification allows your server to be used + * for amplification in DoS attacks against other hosts. + * Only disable if you known this can't happen in your + * particular environment. + * * \param ssl SSL context * \param f_cookie_write Cookie write callback * \param f_cookie_check Cookie check callback diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 13af7a150..a66fcb3ed 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -1441,28 +1441,33 @@ static int ssl_parse_client_hello( ssl_context *ssl ) buf + cookie_offset + 1, cookie_len ); #if defined(POLARSSL_SSL_DTLS_HELLO_VERIFY) - if( ssl->f_cookie_check( ssl->p_cookie, - buf + cookie_offset + 1, cookie_len, - ssl->cli_id, ssl->cli_id_len ) != 0 ) + if( ssl->f_cookie_check != NULL ) { - SSL_DEBUG_MSG( 2, ( "client hello, cookie verification failed" ) ); - ssl->handshake->verify_cookie_len = 1; + if( ssl->f_cookie_check( ssl->p_cookie, + buf + cookie_offset + 1, cookie_len, + ssl->cli_id, ssl->cli_id_len ) != 0 ) + { + SSL_DEBUG_MSG( 2, ( "cookie verification failed" ) ); + ssl->handshake->verify_cookie_len = 1; + } + else + { + SSL_DEBUG_MSG( 2, ( "cookie verification passed" ) ); + ssl->handshake->verify_cookie_len = 0; + } } else - { - SSL_DEBUG_MSG( 2, ( "client hello, cookie verification passed" ) ); - ssl->handshake->verify_cookie_len = 0; - } -#else - /* We know we didn't send a cookie, so it should be empty */ - if( cookie_len != 0 ) - { - SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); - return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); - } - - SSL_DEBUG_MSG( 2, ( "client hello, cookie verification skipped" ) ); #endif /* POLARSSL_SSL_DTLS_HELLO_VERIFY */ + { + /* We know we didn't send a cookie, so it should be empty */ + if( cookie_len != 0 ) + { + SSL_DEBUG_MSG( 1, ( "bad client hello message" ) ); + return( POLARSSL_ERR_SSL_BAD_HS_CLIENT_HELLO ); + } + + SSL_DEBUG_MSG( 2, ( "cookie verification skipped" ) ); + } } #endif /* POLARSSL_SSL_PROTO_DTLS */ @@ -1982,6 +1987,13 @@ static int ssl_write_hello_verify_request( ssl_context *ssl ) SSL_DEBUG_BUF( 3, "server version", (unsigned char *) p, 2 ); p += 2; + /* If we get here, f_cookie_check is not null */ + if( ssl->f_cookie_write == NULL ) + { + SSL_DEBUG_MSG( 1, ( "inconsistent cookie callbacks" ) ); + return( POLARSSL_ERR_SSL_INTERNAL_ERROR ); + } + /* Skip length byte until we know the length */ cookie_len_byte = p++; diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 288ef6920..a2539d7ec 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -3607,6 +3607,35 @@ static int ssl_handshake_init( ssl_context *ssl ) return( 0 ); } +#if defined(POLARSSL_SSL_DTLS_HELLO_VERIFY) +/* Dummy cookie callbacks for defaults */ +static int ssl_cookie_write_dummy( void *ctx, + unsigned char **p, unsigned char *end, + const unsigned char *cli_id, size_t cli_id_len ) +{ + ((void) ctx); + ((void) p); + ((void) end); + ((void) cli_id); + ((void) cli_id_len); + + return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); +} + +static int ssl_cookie_check_dummy( void *ctx, + const unsigned char *cookie, size_t cookie_len, + const unsigned char *cli_id, size_t cli_id_len ) +{ + ((void) ctx); + ((void) cookie); + ((void) cookie_len); + ((void) cli_id); + ((void) cli_id_len); + + return( POLARSSL_ERR_SSL_FEATURE_UNAVAILABLE ); +} +#endif /* POLARSSL_SSL_DTLS_HELLO_VERIFY */ + /* * Initialize an SSL context */ @@ -3670,6 +3699,11 @@ int ssl_init( ssl_context *ssl ) ssl->curve_list = ecp_grp_id_list( ); #endif +#if defined(POLARSSL_SSL_DTLS_HELLO_VERIFY) + ssl->f_cookie_write = ssl_cookie_write_dummy; + ssl->f_cookie_check = ssl_cookie_check_dummy; +#endif + if( ( ret = ssl_handshake_init( ssl ) ) != 0 ) return( ret );