static void do_handle_error(liGnuTLSFilter *f, const char *gnutlsfunc, int r, gboolean writing) { switch (r) { case GNUTLS_E_AGAIN: if (writing) f->write_wants_read = TRUE; break; case GNUTLS_E_REHANDSHAKE: #ifdef HAVE_SAVE_RENEGOTIATION if (f->initial_handshaked_finished && !gnutls_safe_renegotiation_status(f->session)) { _ERROR(f->srv, f->wrk, f->log_context, "%s: client initiated unsafe renegotitation, closing connection", gnutlsfunc); f_close_with_alert(f, r); } else { _DEBUG(f->srv, f->wrk, f->log_context, "%s: client initiated renegotitation", gnutlsfunc); } #else if (f->initial_handshaked_finished) { _ERROR(f->srv, f->wrk, f->log_context, "%s: client initiated renegotitation, closing connection", gnutlsfunc); f_close_with_alert(f, r); } #endif break; case GNUTLS_E_UNEXPECTED_PACKET_LENGTH: f_close_with_alert(f, r); break; case GNUTLS_E_UNKNOWN_CIPHER_SUITE: case GNUTLS_E_UNSUPPORTED_VERSION_PACKET: _DEBUG(f->srv, f->wrk, f->log_context, "%s (%s): %s", gnutlsfunc, gnutls_strerror_name(r), gnutls_strerror(r)); f_close_with_alert(f, r); break; default: if (gnutls_error_is_fatal(r)) { _ERROR(f->srv, f->wrk, f->log_context, "%s (%s): %s", gnutlsfunc, gnutls_strerror_name(r), gnutls_strerror(r)); if (f->initial_handshaked_finished) { f_close_with_alert(f, r); } else { f_abort_gnutls(f); } } else { _ERROR(f->srv, f->wrk, f->log_context, "%s non fatal (%s): %s", gnutlsfunc, gnutls_strerror_name(r), gnutls_strerror(r)); } } }
void doit(void) { /* Server stuff. */ gnutls_certificate_credentials_t serverx509cred; gnutls_session_t server; int sret = GNUTLS_E_AGAIN; /* Client stuff. */ gnutls_certificate_credentials_t clientx509cred; gnutls_session_t client; int cret = GNUTLS_E_AGAIN; /* General init. */ gnutls_global_init (); gnutls_global_set_log_function (tls_log_func); if (debug) gnutls_global_set_log_level (2); /* Init server */ gnutls_certificate_allocate_credentials (&serverx509cred); gnutls_certificate_set_x509_key_mem (serverx509cred, &server_cert, &server_key, GNUTLS_X509_FMT_PEM); gnutls_init (&server, GNUTLS_SERVER); gnutls_credentials_set (server, GNUTLS_CRD_CERTIFICATE, serverx509cred); gnutls_priority_set_direct (server, "NORMAL", NULL); gnutls_transport_set_push_function (server, server_push); gnutls_transport_set_pull_function (server, server_pull); gnutls_transport_set_ptr (server, (gnutls_transport_ptr_t)server); /* Init client */ gnutls_certificate_allocate_credentials (&clientx509cred); gnutls_init (&client, GNUTLS_CLIENT); gnutls_credentials_set (client, GNUTLS_CRD_CERTIFICATE, clientx509cred); gnutls_priority_set_direct (client, "NORMAL", NULL); gnutls_transport_set_push_function (client, client_push); gnutls_transport_set_pull_function (client, client_pull); gnutls_transport_set_ptr (client, (gnutls_transport_ptr_t)client); /* Check that initially no session use the extension. */ if (gnutls_safe_renegotiation_status (server) || gnutls_safe_renegotiation_status (client)) { puts ("Client or server using extension before handshake?"); abort (); } HANDSHAKE(client, server); /* Check that both sessions use the extension. */ if (!gnutls_safe_renegotiation_status (server) || !gnutls_safe_renegotiation_status (client)) { puts ("Client or server not using safe renegotiation extension?"); abort (); } sret = gnutls_rehandshake (server); if (debug) { tls_log_func (0, "gnutls_rehandshake (server)...\n"); tls_log_func (0, gnutls_strerror (sret)); tls_log_func (0, "\n"); } { ssize_t n; char b[1]; n = gnutls_record_recv (client, b, 1); if (n != GNUTLS_E_REHANDSHAKE) abort (); } HANDSHAKE(client, server); /* Check that session still use the extension. */ if (!gnutls_safe_renegotiation_status (server) || !gnutls_safe_renegotiation_status (client)) { puts ("Client or server not using safe renegotiation extension?"); abort (); } /* Check that this API does not affect anything after first handshake. gnutls_safe_negotiation_set_initial (server, 0); */ sret = gnutls_rehandshake (server); if (debug) { tls_log_func (0, "gnutls_rehandshake (server)...\n"); tls_log_func (0, gnutls_strerror (sret)); tls_log_func (0, "\n"); } { ssize_t n; char b[1]; n = gnutls_record_recv (client, b, 1); if (n != GNUTLS_E_REHANDSHAKE) abort (); } HANDSHAKE(client, server); /* Check that disabling the extension will break rehandshakes. gnutls_safe_renegotiation_set (client, 0); */ sret = gnutls_rehandshake (server); if (debug) { tls_log_func (0, "gnutls_rehandshake (server)...\n"); tls_log_func (0, gnutls_strerror (sret)); tls_log_func (0, "\n"); } { ssize_t n; char b[1]; n = gnutls_record_recv (client, b, 1); if (n != GNUTLS_E_REHANDSHAKE) abort (); } HANDSHAKE(client, server); gnutls_bye (client, GNUTLS_SHUT_RDWR); gnutls_bye (server, GNUTLS_SHUT_RDWR); gnutls_deinit (client); gnutls_deinit (server); gnutls_certificate_free_credentials (serverx509cred); gnutls_certificate_free_credentials (clientx509cred); gnutls_global_deinit (); if (debug) { puts ("Self-test successful"); } return; }
static void do_handle_error(liGnuTLSFilter *f, const char *gnutlsfunc, int r, gboolean writing) { switch (r) { case GNUTLS_E_AGAIN: if (writing) f->write_wants_read = TRUE; return; case GNUTLS_E_REHANDSHAKE: #ifdef HAVE_SAVE_RENEGOTIATION if (f->initial_handshaked_finished && !gnutls_safe_renegotiation_status(f->session)) { _ERROR(f->srv, f->wrk, f->log_context, "%s: client initiated unsafe renegotitation, closing connection", gnutlsfunc); f_close_with_alert(f, r); } else { _DEBUG(f->srv, f->wrk, f->log_context, "%s: client initiated renegotitation", gnutlsfunc); } #else if (f->initial_handshaked_finished) { _ERROR(f->srv, f->wrk, f->log_context, "%s: client initiated renegotitation, closing connection", gnutlsfunc); f_close_with_alert(f, r); } #endif return; case GNUTLS_E_UNEXPECTED_PACKET_LENGTH: f_close_with_alert(f, r); return; case GNUTLS_E_UNKNOWN_CIPHER_SUITE: case GNUTLS_E_UNSUPPORTED_VERSION_PACKET: _DEBUG(f->srv, f->wrk, f->log_context, "%s (%s): %s", gnutlsfunc, gnutls_strerror_name(r), gnutls_strerror(r)); f_close_with_alert(f, r); return; case GNUTLS_E_FATAL_ALERT_RECEIVED: case GNUTLS_E_WARNING_ALERT_RECEIVED: { gnutls_alert_description_t alert_desc = gnutls_alert_get(f->session); const char* alert_desc_name = gnutls_alert_get_name(alert_desc); _INFO(f->srv, f->wrk, f->log_context, "%s (%s): %s %s (%u)", gnutlsfunc, gnutls_strerror_name(r), gnutls_strerror(r), (NULL != alert_desc_name) ? alert_desc_name : "unknown alert", (unsigned int) alert_desc); } /* error not handled yet: break instead of return */ break; default: if (gnutls_error_is_fatal(r)) { _ERROR(f->srv, f->wrk, f->log_context, "%s (%s): %s", gnutlsfunc, gnutls_strerror_name(r), gnutls_strerror(r)); } else { _WARNING(f->srv, f->wrk, f->log_context, "%s non fatal (%s): %s", gnutlsfunc, gnutls_strerror_name(r), gnutls_strerror(r)); } /* error not handled yet: break instead of return */ break; } /* generic error handling */ if (gnutls_error_is_fatal(r)) { if (f->initial_handshaked_finished) { f_close_with_alert(f, r); } else { f_abort_gnutls(f); } } }
void doit(void) { /* Server stuff. */ gnutls_certificate_credentials_t serverx509cred; gnutls_session_t server; int sret = GNUTLS_E_AGAIN; /* Client stuff. */ gnutls_certificate_credentials_t clientx509cred; gnutls_session_t client; int cret = GNUTLS_E_AGAIN; /* General init. */ global_init(); gnutls_global_set_log_function(tls_log_func); if (debug) gnutls_global_set_log_level(2); /* Init server */ gnutls_certificate_allocate_credentials(&serverx509cred); gnutls_certificate_set_x509_key_mem(serverx509cred, &server_cert, &server_key, GNUTLS_X509_FMT_PEM); gnutls_init(&server, GNUTLS_SERVER); gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, serverx509cred); gnutls_priority_set_direct(server, "NORMAL", NULL); gnutls_transport_set_push_function(server, server_push); gnutls_transport_set_pull_function(server, server_pull); gnutls_transport_set_ptr(server, server); /* Init client */ gnutls_certificate_allocate_credentials(&clientx509cred); gnutls_init(&client, GNUTLS_CLIENT); gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, clientx509cred); gnutls_priority_set_direct(client, "NORMAL", NULL); gnutls_transport_set_push_function(client, client_push); gnutls_transport_set_pull_function(client, client_pull); gnutls_transport_set_ptr(client, client); HANDSHAKE(client, server); if (!gnutls_safe_renegotiation_status(client) || !gnutls_safe_renegotiation_status(server)) { tls_log_func(0, "Session not using safe renegotiation!\n"); exit(1); } if (!(gnutls_session_get_flags(client) & GNUTLS_SFLAGS_SAFE_RENEGOTIATION) || !(gnutls_session_get_flags(server) & GNUTLS_SFLAGS_SAFE_RENEGOTIATION)) { tls_log_func(0, "Session not using safe renegotiation!\n"); exit(1); } sret = gnutls_rehandshake(server); if (debug) { tls_log_func(0, "gnutls_rehandshake (server)...\n"); tls_log_func(0, gnutls_strerror(sret)); tls_log_func(0, "\n"); } { ssize_t n; char b[1]; n = gnutls_record_recv(client, b, 1); if (n != GNUTLS_E_REHANDSHAKE) abort(); } HANDSHAKE(client, server); if (!gnutls_safe_renegotiation_status(client) || !gnutls_safe_renegotiation_status(server)) { tls_log_func(0, "Rehandshaked session not using safe renegotiation!\n"); exit(1); } if (!(gnutls_session_get_flags(client) & GNUTLS_SFLAGS_SAFE_RENEGOTIATION) || !(gnutls_session_get_flags(server) & GNUTLS_SFLAGS_SAFE_RENEGOTIATION)) { tls_log_func(0, "Rehandshaked session not using safe renegotiation!\n"); exit(1); } gnutls_bye(client, GNUTLS_SHUT_RDWR); gnutls_bye(server, GNUTLS_SHUT_RDWR); gnutls_deinit(client); gnutls_deinit(server); gnutls_certificate_free_credentials(serverx509cred); gnutls_certificate_free_credentials(clientx509cred); gnutls_global_deinit(); if (debug) { puts("Self-test successful"); } return; }
int main (int argc, char *argv[]) { int debug_level = argc - 1; int exit_code = EXIT_SUCCESS; /* Server stuff. */ gnutls_certificate_credentials_t serverx509cred; gnutls_session_t server; int sret = GNUTLS_E_AGAIN; /* Client stuff. */ gnutls_certificate_credentials_t clientx509cred; gnutls_session_t client; int cret = GNUTLS_E_AGAIN; /* General init. */ gnutls_global_init (); gnutls_global_set_log_function (tls_log_func); gnutls_global_set_log_level (debug_level); /* Init server */ gnutls_certificate_allocate_credentials (&serverx509cred); gnutls_certificate_set_x509_key_mem (serverx509cred, &server_cert, &server_key, GNUTLS_X509_FMT_PEM); gnutls_init (&server, GNUTLS_SERVER); gnutls_credentials_set (server, GNUTLS_CRD_CERTIFICATE, serverx509cred); gnutls_priority_set_direct (server, "NORMAL:%DISABLE_SAFE_RENEGOTIATION", NULL); gnutls_transport_set_push_function (server, server_push); gnutls_transport_set_pull_function (server, server_pull); /* Init client */ gnutls_certificate_allocate_credentials (&clientx509cred); gnutls_init (&client, GNUTLS_CLIENT); gnutls_credentials_set (client, GNUTLS_CRD_CERTIFICATE, clientx509cred); gnutls_priority_set_direct (client, "NORMAL", NULL); gnutls_transport_set_push_function (client, client_push); gnutls_transport_set_pull_function (client, client_pull); /* Check that initially no session use the extension. */ if (gnutls_safe_renegotiation_status (server) || gnutls_safe_renegotiation_status (client)) { puts ("Client or server using extension before handshake?"); abort (); } do { static int max_iter = 0; if (max_iter++ > 10) abort (); if (cret == GNUTLS_E_AGAIN) { cret = gnutls_handshake (client); if (debug_level > 0) { tls_log_func (0, "gnutls_handshake (client)...\n"); tls_log_func (0, gnutls_strerror (cret)); tls_log_func (0, "\n"); } } if (sret == GNUTLS_E_AGAIN) { sret = gnutls_handshake (server); if (debug_level > 0) { tls_log_func (0, "gnutls_handshake (server)...\n"); tls_log_func (0, gnutls_strerror (sret)); tls_log_func (0, "\n"); } } } while ( /* Not done: */ !(cret == GNUTLS_E_SUCCESS && sret == GNUTLS_E_SUCCESS) /* No error: */ && (cret == GNUTLS_E_AGAIN || sret == GNUTLS_E_AGAIN)); if (cret != GNUTLS_E_SUCCESS && sret != GNUTLS_E_SUCCESS) exit_code = EXIT_FAILURE; if (gnutls_safe_renegotiation_status (client) || gnutls_safe_renegotiation_status (server)) { tls_log_func (0, "Session using safe renegotiation but shouldn't?!\n"); exit_code = EXIT_FAILURE; } sret = gnutls_rehandshake (server); if (debug_level > 0) { tls_log_func (0, "gnutls_rehandshake (server)...\n"); tls_log_func (0, gnutls_strerror (sret)); tls_log_func (0, "\n"); } { ssize_t n; char b[1]; n = gnutls_record_recv (client, b, 1); if (n != GNUTLS_E_REHANDSHAKE) abort (); } cret = GNUTLS_E_AGAIN; sret = GNUTLS_E_AGAIN; do { static int max_iter = 0; if (max_iter++ > 10) abort (); if (cret == GNUTLS_E_AGAIN) { cret = gnutls_handshake (client); if (debug_level > 0) { tls_log_func (0, "second gnutls_handshake (client)...\n"); tls_log_func (0, gnutls_strerror (cret)); tls_log_func (0, "\n"); } } if (sret == GNUTLS_E_AGAIN) { sret = gnutls_handshake (server); if (debug_level > 0) { tls_log_func (0, "second gnutls_handshake (server)...\n"); tls_log_func (0, gnutls_strerror (sret)); tls_log_func (0, "\n"); } } if (cret == GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED) break; } while ( /* Not done: */ !(cret == GNUTLS_E_SUCCESS && sret == GNUTLS_E_SUCCESS) /* No error: */ && (cret == GNUTLS_E_AGAIN || sret == GNUTLS_E_AGAIN)); if (cret != GNUTLS_E_UNSAFE_RENEGOTIATION_DENIED && sret != GNUTLS_E_SUCCESS) exit_code = 1; if (gnutls_safe_renegotiation_status (client) || gnutls_safe_renegotiation_status (server)) { tls_log_func (0, "Rehandshaked worked and uses safe reneg?!\n"); exit_code = EXIT_FAILURE; } gnutls_bye (client, GNUTLS_SHUT_RDWR); gnutls_bye (server, GNUTLS_SHUT_RDWR); gnutls_deinit (client); gnutls_deinit (server); free (to_server); free (to_client); gnutls_certificate_free_credentials (serverx509cred); gnutls_global_deinit (); if (debug_level > 0) { if (exit_code == 0) puts ("Self-test successful"); else puts ("Self-test failed"); } return exit_code; }