/* Return zero if an alert value can be ignored. */ static int check_alert(ne_socket *sock, ssize_t ret) { const char *alert; if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED) { alert = gnutls_alert_get_name(gnutls_alert_get(sock->ssl)); NE_DEBUG(NE_DBG_SOCKET, "TLS warning alert: %s\n", alert); return 0; } else if (ret == GNUTLS_E_FATAL_ALERT_RECEIVED) { alert = gnutls_alert_get_name(gnutls_alert_get(sock->ssl)); NE_DEBUG(NE_DBG_SOCKET, "TLS fatal alert: %s\n", alert); return -1; } return ret; }
u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn, const u8 *in_data, size_t in_len, size_t *out_len) { u8 *out_data; int ret; if (in_data && in_len) { if (conn->pull_buf) { wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in " "pull_buf", __func__, conn->pull_buf_len); free(conn->pull_buf); } conn->pull_buf = malloc(in_len); if (conn->pull_buf == NULL) return NULL; memcpy(conn->pull_buf, in_data, in_len); conn->pull_buf_offset = conn->pull_buf; conn->pull_buf_len = in_len; } ret = gnutls_handshake(conn->session); if (ret < 0) { switch (ret) { case GNUTLS_E_AGAIN: break; case GNUTLS_E_FATAL_ALERT_RECEIVED: wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert", __func__, gnutls_alert_get_name( gnutls_alert_get(conn->session))); conn->read_alerts++; /* continue */ default: wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed " "-> %s", __func__, gnutls_strerror(ret)); conn->failed++; } } else { wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully"); if (conn->verify_peer && tls_connection_verify_peer(conn)) { wpa_printf(MSG_INFO, "TLS: Peer certificate chain " "failed validation"); conn->failed++; return NULL; } conn->established = 1; if (conn->push_buf == NULL) { /* Need to return something to get final TLS ACK. */ conn->push_buf = malloc(1); } } out_data = conn->push_buf; *out_len = conn->push_buf_len; conn->push_buf = NULL; conn->push_buf_len = 0; return out_data; }
void CTlsSocket::PrintAlert(MessageType logLevel) { gnutls_alert_description_t last_alert = gnutls_alert_get(m_session); const char* alert = gnutls_alert_get_name(last_alert); if (alert) { wxString str(alert, wxConvLocal); m_pOwner->LogMessage(logLevel, _("Received TLS alert from the server: %s (%d)"), str, last_alert); } else m_pOwner->LogMessage(logLevel, _("Received unknown TLS alert %d from the server"), last_alert); }
static void record_io_error(int ec, uschar *when, uschar *text) { const char *msg; if (ec == GNUTLS_E_FATAL_ALERT_RECEIVED) msg = string_sprintf("%s: %s", gnutls_strerror(ec), gnutls_alert_get_name(gnutls_alert_get(tls_session))); else msg = gnutls_strerror(ec); tls_error(when, client_host, msg); }
int do_handshake (gnutls_session session) { int ret, alert; do { ret = gnutls_handshake (session); } while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN); handshake_output = ret; if (ret < 0 && verbose > 1) { if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) { alert = gnutls_alert_get (session); printf ("\n"); printf ("*** Received alert [%d]: %s\n", alert, gnutls_alert_get_name (alert)); } } if (ret < 0) return TEST_FAILED; gnutls_session_get_data (session, NULL, &session_data_size); if (sfree != 0) { free (session_data); sfree = 0; } session_data = malloc (session_data_size); sfree = 1; if (session_data == NULL) { fprintf (stderr, "Memory error\n"); exit (1); } gnutls_session_get_data (session, session_data, &session_data_size); session_id_size = sizeof (session_id); gnutls_session_get_id (session, session_id, &session_id_size); return TEST_SUCCEED; }
static Eina_Bool _process_data(gnutls_session_t client, Ecore_Fd_Handler * fd_handler) { static int ret, lastret; static unsigned int count = 0; if (!done) { lastret = ret; ret = gnutls_handshake(client); count++; if (gnutls_record_get_direction(client)) ecore_main_fd_handler_active_set(fd_handler, ECORE_FD_WRITE); else ecore_main_fd_handler_active_set(fd_handler, ECORE_FD_READ); /* avoid printing messages infinity times */ if (lastret != ret && ret != 0 && ret != GNUTLS_E_AGAIN) { print("gnutls returned with: %s - %s", gnutls_strerror_name(ret), gnutls_strerror(ret)); if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED) || (ret == GNUTLS_E_FATAL_ALERT_RECEIVED)) print("Also received alert: %s", gnutls_alert_get_name (gnutls_alert_get(client))); print("last out: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS (gnutls_handshake_get_last_out(client))); print("last in: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS (gnutls_handshake_get_last_in(client))); } if (gnutls_error_is_fatal(ret)) { print("yarrr this be an error!"); exit(1); } } if (ret == GNUTLS_E_SUCCESS) { done = 1; //print("Handshake successful in %u handshake calls!", count); ecore_main_loop_quit(); } return ECORE_CALLBACK_RENEW; }
void CTlsSocket::PrintAlert() { gnutls_alert_description_t last_alert = gnutls_alert_get(m_session); const char* alert = gnutls_alert_get_name(last_alert); if (alert) { #if wxUSE_UNICODE wxString str(alert, wxConvLocal); #else wxString str(alert); #endif m_pOwner->LogMessage(::Debug_Warning, _T("GnuTLS alert %d: %s"), last_alert, str.c_str()); } else m_pOwner->LogMessage(::Debug_Warning, _T("GnuTLS alert %d"), last_alert); }
/* Returns zero if the error code was successfully handled. */ static int handle_error (socket_st * hd, int err) { int alert, ret; const char *err_type, *str; if (err >= 0) return 0; if (gnutls_error_is_fatal (err) == 0) { ret = 0; err_type = "Non fatal"; } else { ret = err; err_type = "Fatal"; } str = gnutls_strerror (err); if (str == NULL) str = str_unknown; fprintf (stderr, "*** %s error: %s\n", err_type, str); if (err == GNUTLS_E_WARNING_ALERT_RECEIVED || err == GNUTLS_E_FATAL_ALERT_RECEIVED) { alert = gnutls_alert_get (hd->session); str = gnutls_alert_get_name (alert); if (str == NULL) str = str_unknown; printf ("*** Received alert [%d]: %s\n", alert, str); /* In SRP if the alert is MISSING_SRP_USERNAME, * we should read the username/password and * call gnutls_handshake(). This is not implemented * here. */ } check_rehandshake (hd, err); return ret; }
/* moved down here, to keep from interrupting the flow with verbose error crap */ void handle_gnutls_read_error(int readbytes, struct connection_state *scs) { if (gnutls_error_is_fatal(readbytes) == 1) { TDM(DEBUG_ERROR, "%s: Received corrupted data(%d) - server has terminated the connection abnormally\n", scs->name, readbytes); } else { if (readbytes == GNUTLS_E_WARNING_ALERT_RECEIVED || readbytes == GNUTLS_E_FATAL_ALERT_RECEIVED) TDM(DEBUG_ERROR, "* Received alert [%d]\n", gnutls_alert_get(scs->tls_state)); if (readbytes == GNUTLS_E_REHANDSHAKE) TDM(DEBUG_ERROR, "* Received HelloRequest message\n"); } TDM(DEBUG_ERROR, "%s: gnutls error reading: %s\n", scs->name, gnutls_strerror(readbytes)); }
/* Returns zero if the error code was successfully handled. */ static int handle_error (socket_st * hd, int err) { int alert, ret; const char *err_type, *str; if (err >= 0 || err == GNUTLS_E_AGAIN || err == GNUTLS_E_INTERRUPTED) return 0; if (gnutls_error_is_fatal (err) == 0) { ret = 0; err_type = "Non fatal"; } else { ret = err; err_type = "Fatal"; } str = gnutls_strerror (err); if (str == NULL) str = str_unknown; fprintf (stderr, "*** %s error: %s\n", err_type, str); if (err == GNUTLS_E_WARNING_ALERT_RECEIVED || err == GNUTLS_E_FATAL_ALERT_RECEIVED) { alert = gnutls_alert_get (hd->session); str = gnutls_alert_get_name (alert); if (str == NULL) str = str_unknown; printf ("*** Received alert [%d]: %s\n", alert, str); } check_rehandshake (hd, err); return ret; }
/* This function will check whether the given return code from * a gnutls function (recv/send), is an alert, and will print * that alert. */ void check_alert (gnutls_session_t session, int ret) { int last_alert; if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) { last_alert = gnutls_alert_get (session); /* The check for renegotiation is only useful if we are * a server, and we had requested a rehandshake. */ if (last_alert == GNUTLS_A_NO_RENEGOTIATION && ret == GNUTLS_E_WARNING_ALERT_RECEIVED) printf ("* Received NO_RENEGOTIATION alert. " "Client Does not support renegotiation.\n"); else printf ("* Received alert '%d': %s.\n", last_alert, gnutls_alert_get_name (last_alert)); } }
static ssize_t error_gnutls(ne_socket *sock, ssize_t sret) { ssize_t ret; switch (sret) { case 0: ret = NE_SOCK_CLOSED; set_error(sock, _("Connection closed")); break; case GNUTLS_E_FATAL_ALERT_RECEIVED: ret = NE_SOCK_ERROR; ne_snprintf(sock->error, sizeof sock->error, _("SSL alert received: %s"), gnutls_alert_get_name(gnutls_alert_get(sock->ssl))); break; case GNUTLS_E_UNEXPECTED_PACKET_LENGTH: /* It's not exactly an API guarantee but this error will * always mean a premature EOF. */ ret = NE_SOCK_TRUNC; set_error(sock, _("Secure connection truncated")); break; case GNUTLS_E_PUSH_ERROR: ret = NE_SOCK_RESET; set_error(sock, ("SSL socket write failed")); break; case GNUTLS_E_PULL_ERROR: ret = NE_SOCK_RESET; set_error(sock, _("SSL socket read failed")); break; default: ret = NE_SOCK_ERROR; ne_snprintf(sock->error, sizeof sock->error, _("SSL error: %s"), gnutls_strerror(sret)); } return ret; }
u8 * tls_connection_handshake(void *ssl_ctx, struct tls_connection *conn, const u8 *in_data, size_t in_len, size_t *out_len, u8 **appl_data, size_t *appl_data_len) { struct tls_global *global = ssl_ctx; u8 *out_data; int ret; if (appl_data) *appl_data = NULL; if (in_data && in_len) { if (conn->pull_buf) { wpa_printf(MSG_DEBUG, "%s - %d bytes remaining in " "pull_buf", __func__, conn->pull_buf_len); os_free(conn->pull_buf); } conn->pull_buf = os_malloc(in_len); if (conn->pull_buf == NULL) return NULL; os_memcpy(conn->pull_buf, in_data, in_len); conn->pull_buf_offset = conn->pull_buf; conn->pull_buf_len = in_len; } ret = gnutls_handshake(conn->session); if (ret < 0) { switch (ret) { case GNUTLS_E_AGAIN: if (global->server && conn->established && conn->push_buf == NULL) { /* Need to return something to trigger * completion of EAP-TLS. */ conn->push_buf = os_malloc(1); } break; case GNUTLS_E_FATAL_ALERT_RECEIVED: wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert", __func__, gnutls_alert_get_name( gnutls_alert_get(conn->session))); conn->read_alerts++; /* continue */ default: wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed " "-> %s", __func__, gnutls_strerror(ret)); conn->failed++; } } else { size_t size; if (conn->verify_peer && tls_connection_verify_peer(conn)) { wpa_printf(MSG_INFO, "TLS: Peer certificate chain " "failed validation"); conn->failed++; return NULL; } if (conn->tls_ia && !gnutls_ia_handshake_p(conn->session)) { wpa_printf(MSG_INFO, "TLS: No TLS/IA negotiation"); conn->failed++; return NULL; } if (conn->tls_ia) wpa_printf(MSG_DEBUG, "TLS: Start TLS/IA handshake"); else { wpa_printf(MSG_DEBUG, "TLS: Handshake completed " "successfully"); } conn->established = 1; if (conn->push_buf == NULL) { /* Need to return something to get final TLS ACK. */ conn->push_buf = os_malloc(1); } gnutls_session_get_data(conn->session, NULL, &size); if (global->session_data == NULL || global->session_data_size < size) { os_free(global->session_data); global->session_data = os_malloc(size); } if (global->session_data) { global->session_data_size = size; gnutls_session_get_data(conn->session, global->session_data, &global->session_data_size); } } out_data = conn->push_buf; *out_len = conn->push_buf_len; conn->push_buf = NULL; conn->push_buf_len = 0; return out_data; }
int _gnutls_recv_client_certificate (gnutls_session_t session) { int datasize; opaque *data; int ret = 0; int optional; if (session->internals.auth_struct->gnutls_process_client_certificate != NULL) { /* if we have not requested a certificate then just return */ if (session->internals.send_cert_req == 0) { return 0; } if (session->internals.send_cert_req == GNUTLS_CERT_REQUIRE) optional = MANDATORY_PACKET; else optional = OPTIONAL_PACKET; ret = _gnutls_recv_handshake (session, &data, &datasize, GNUTLS_HANDSHAKE_CERTIFICATE_PKT, optional); if (ret < 0) { /* Handle the case of old SSL3 clients who send * a warning alert instead of an empty certificate to indicate * no certificate. */ if (optional == OPTIONAL_PACKET && ret == GNUTLS_E_WARNING_ALERT_RECEIVED && gnutls_protocol_get_version (session) == GNUTLS_SSL3 && gnutls_alert_get (session) == GNUTLS_A_SSL3_NO_CERTIFICATE) { /* SSL3 does not send an empty certificate, * but this alert. So we just ignore it. */ gnutls_assert (); return 0; } /* certificate was required */ if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) && optional == MANDATORY_PACKET) { gnutls_assert (); return GNUTLS_E_NO_CERTIFICATE_FOUND; } return ret; } if (ret == 0 && datasize == 0 && optional == OPTIONAL_PACKET) { /* Client has not sent the certificate message. * well I'm not sure we should accept this * behaviour. */ gnutls_assert (); return 0; } ret = session->internals. auth_struct->gnutls_process_client_certificate (session, data, datasize); gnutls_free (data); if (ret < 0 && ret != GNUTLS_E_NO_CERTIFICATE_FOUND) { gnutls_assert (); return ret; } /* ok we should expect a certificate verify message now */ if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND && optional == OPTIONAL_PACKET) ret = 0; else session->key->certificate_requested = 1; } return ret; }
struct wpabuf * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { struct tls_global *global = tls_ctx; struct wpabuf *out_data; int ret; if (appl_data) *appl_data = NULL; if (in_data && wpabuf_len(in_data) > 0) { if (conn->pull_buf) { wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " "pull_buf", __func__, (unsigned long) wpabuf_len(conn->pull_buf)); wpabuf_free(conn->pull_buf); } conn->pull_buf = wpabuf_dup(in_data); if (conn->pull_buf == NULL) return NULL; conn->pull_buf_offset = wpabuf_head(conn->pull_buf); } ret = gnutls_handshake(conn->session); if (ret < 0) { gnutls_alert_description_t alert; switch (ret) { case GNUTLS_E_AGAIN: if (global->server && conn->established && conn->push_buf == NULL) { /* Need to return something to trigger * completion of EAP-TLS. */ conn->push_buf = wpabuf_alloc(0); } break; case GNUTLS_E_FATAL_ALERT_RECEIVED: alert = gnutls_alert_get(conn->session); wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert", __func__, gnutls_alert_get_name(alert)); conn->read_alerts++; if (conn->global->event_cb != NULL) { union tls_event_data ev; os_memset(&ev, 0, sizeof(ev)); ev.alert.is_local = 0; ev.alert.type = gnutls_alert_get_name(alert); ev.alert.description = ev.alert.type; conn->global->event_cb(conn->global->cb_ctx, TLS_ALERT, &ev); } /* continue */ default: wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed " "-> %s", __func__, gnutls_strerror(ret)); conn->failed++; } } else { size_t size; wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully"); #if GNUTLS_VERSION_NUMBER >= 0x03010a { char *desc; desc = gnutls_session_get_desc(conn->session); if (desc) { wpa_printf(MSG_DEBUG, "GnuTLS: %s", desc); gnutls_free(desc); } } #endif /* GnuTLS 3.1.10 or newer */ conn->established = 1; if (conn->push_buf == NULL) { /* Need to return something to get final TLS ACK. */ conn->push_buf = wpabuf_alloc(0); } gnutls_session_get_data(conn->session, NULL, &size); if (global->session_data == NULL || global->session_data_size < size) { os_free(global->session_data); global->session_data = os_malloc(size); } if (global->session_data) { global->session_data_size = size; gnutls_session_get_data(conn->session, global->session_data, &global->session_data_size); } if (conn->pull_buf && appl_data) *appl_data = gnutls_get_appl_data(conn); } out_data = conn->push_buf; conn->push_buf = NULL; return out_data; }
/* this function does a SSL/TLS (re-)handshake */ static CURLcode handshake(struct connectdata *conn, int sockindex, bool duringconnect, bool nonblocking) { struct SessionHandle *data = conn->data; struct ssl_connect_data *connssl = &conn->ssl[sockindex]; gnutls_session session = conn->ssl[sockindex].session; curl_socket_t sockfd = conn->sock[sockindex]; long timeout_ms; int rc; int what; for(;;) { /* check allowed time left */ timeout_ms = Curl_timeleft(data, NULL, duringconnect); if(timeout_ms < 0) { /* no need to continue if time already is up */ failf(data, "SSL connection timeout"); return CURLE_OPERATION_TIMEDOUT; } /* if ssl is expecting something, check if it's available. */ if(connssl->connecting_state == ssl_connect_2_reading || connssl->connecting_state == ssl_connect_2_writing) { curl_socket_t writefd = ssl_connect_2_writing== connssl->connecting_state?sockfd:CURL_SOCKET_BAD; curl_socket_t readfd = ssl_connect_2_reading== connssl->connecting_state?sockfd:CURL_SOCKET_BAD; what = Curl_socket_ready(readfd, writefd, nonblocking?0: timeout_ms?timeout_ms:1000); if(what < 0) { /* fatal error */ failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); return CURLE_SSL_CONNECT_ERROR; } else if(0 == what) { if(nonblocking) return CURLE_OK; else if(timeout_ms) { /* timeout */ failf(data, "SSL connection timeout at %ld", timeout_ms); return CURLE_OPERATION_TIMEDOUT; } } /* socket is readable or writable */ } rc = gnutls_handshake(session); if((rc == GNUTLS_E_AGAIN) || (rc == GNUTLS_E_INTERRUPTED)) { connssl->connecting_state = gnutls_record_get_direction(session)? ssl_connect_2_writing:ssl_connect_2_reading; continue; if(nonblocking) return CURLE_OK; } else if((rc < 0) && !gnutls_error_is_fatal(rc)) { const char *strerr = NULL; if(rc == GNUTLS_E_WARNING_ALERT_RECEIVED) { int alert = gnutls_alert_get(session); strerr = gnutls_alert_get_name(alert); } if(strerr == NULL) strerr = gnutls_strerror(rc); failf(data, "gnutls_handshake() warning: %s", strerr); } else if(rc < 0) { const char *strerr = NULL; if(rc == GNUTLS_E_FATAL_ALERT_RECEIVED) { int alert = gnutls_alert_get(session); strerr = gnutls_alert_get_name(alert); } if(strerr == NULL) strerr = gnutls_strerror(rc); failf(data, "gnutls_handshake() failed: %s", strerr); return CURLE_SSL_CONNECT_ERROR; } /* Reset our connect state machine */ connssl->connecting_state = ssl_connect_1; return CURLE_OK; } }
gnutls_alert_description_t session::get_alert () const { return gnutls_alert_get (s); }
static int gnutls_do_handshake(mgs_handle_t * ctxt) { int ret; int errcode; int maxtries = HANDSHAKE_MAX_TRIES; if (ctxt->status != 0 || ctxt->session == NULL) { return -1; } tryagain: do { ret = gnutls_handshake(ctxt->session); maxtries--; } while ((ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) && maxtries > 0); if (maxtries < 1) { ctxt->status = -1; #if USING_2_1_RECENT ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, ctxt->c, "GnuTLS: Handshake Failed. Hit Maximum Attempts"); #else ap_log_error(APLOG_MARK, APLOG_ERR, 0, ctxt->c->base_server, "GnuTLS: Handshake Failed. Hit Maximum Attempts"); #endif if (ctxt->session) { gnutls_alert_send(ctxt->session, GNUTLS_AL_FATAL, gnutls_error_to_alert (GNUTLS_E_INTERNAL_ERROR, NULL)); gnutls_deinit(ctxt->session); } ctxt->session = NULL; return -1; } if (ret < 0) { if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) { errcode = gnutls_alert_get(ctxt->session); ap_log_error(APLOG_MARK, APLOG_INFO, 0, ctxt->c->base_server, "GnuTLS: Hanshake Alert (%d) '%s'.", errcode, gnutls_alert_get_name(errcode)); } if (!gnutls_error_is_fatal(ret)) { ap_log_error(APLOG_MARK, APLOG_INFO, 0, ctxt->c->base_server, "GnuTLS: Non-Fatal Handshake Error: (%d) '%s'", ret, gnutls_strerror(ret)); goto tryagain; } #if USING_2_1_RECENT ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, ctxt->c, "GnuTLS: Handshake Failed (%d) '%s'", ret, gnutls_strerror(ret)); #else ap_log_error(APLOG_MARK, APLOG_INFO, 0, ctxt->c->base_server, "GnuTLS: Handshake Failed (%d) '%s'", ret, gnutls_strerror(ret)); #endif ctxt->status = -1; if (ctxt->session) { gnutls_alert_send(ctxt->session, GNUTLS_AL_FATAL, gnutls_error_to_alert(ret, NULL)); gnutls_deinit(ctxt->session); } ctxt->session = NULL; return ret; } else { /* all done with the handshake */ ctxt->status = 1; /* If the session was resumed, we did not set the correct * server_rec in ctxt->sc. Go Find it. (ick!) */ if (gnutls_session_is_resumed(ctxt->session)) { mgs_srvconf_rec *sc; sc = mgs_find_sni_server(ctxt->session); if (sc) { ctxt->sc = sc; } } return 0; } }
struct wpabuf * tls_connection_handshake(void *tls_ctx, struct tls_connection *conn, const struct wpabuf *in_data, struct wpabuf **appl_data) { struct tls_global *global = tls_ctx; struct wpabuf *out_data; int ret; if (appl_data) *appl_data = NULL; if (in_data && wpabuf_len(in_data) > 0) { if (conn->pull_buf) { wpa_printf(MSG_DEBUG, "%s - %lu bytes remaining in " "pull_buf", __func__, (unsigned long) wpabuf_len(conn->pull_buf)); wpabuf_free(conn->pull_buf); } conn->pull_buf = wpabuf_dup(in_data); if (conn->pull_buf == NULL) return NULL; conn->pull_buf_offset = wpabuf_head(conn->pull_buf); } ret = gnutls_handshake(conn->session); if (ret < 0) { switch (ret) { case GNUTLS_E_AGAIN: if (global->server && conn->established && conn->push_buf == NULL) { /* Need to return something to trigger * completion of EAP-TLS. */ conn->push_buf = wpabuf_alloc(0); } break; case GNUTLS_E_FATAL_ALERT_RECEIVED: wpa_printf(MSG_DEBUG, "%s - received fatal '%s' alert", __func__, gnutls_alert_get_name( gnutls_alert_get(conn->session))); conn->read_alerts++; /* continue */ default: wpa_printf(MSG_DEBUG, "%s - gnutls_handshake failed " "-> %s", __func__, gnutls_strerror(ret)); conn->failed++; } } else { size_t size; gnutls_alert_description_t err; if (conn->verify_peer && tls_connection_verify_peer(conn, &err)) { wpa_printf(MSG_INFO, "TLS: Peer certificate chain " "failed validation"); conn->failed++; gnutls_alert_send(conn->session, GNUTLS_AL_FATAL, err); goto out; } wpa_printf(MSG_DEBUG, "TLS: Handshake completed successfully"); conn->established = 1; if (conn->push_buf == NULL) { /* Need to return something to get final TLS ACK. */ conn->push_buf = wpabuf_alloc(0); } gnutls_session_get_data(conn->session, NULL, &size); if (global->session_data == NULL || global->session_data_size < size) { os_free(global->session_data); global->session_data = os_malloc(size); } if (global->session_data) { global->session_data_size = size; gnutls_session_get_data(conn->session, global->session_data, &global->session_data_size); } if (conn->pull_buf && appl_data) *appl_data = gnutls_get_appl_data(conn); } out: out_data = conn->push_buf; conn->push_buf = NULL; return out_data; }
PresentationServer::PresentationServer(const std::string & conferenceUrl, const std::string & managerHost, unsigned short managerPort, int screenWidth, int screenHeight, const std::string & caCertificate, const std::string & managerPath, const std::string & managerParam) : _server(0), _fps(5) { if (caCertificate.empty()) { throw std::invalid_argument("no CA Certificate provided!"); } //Erstmal d�rfte jetzt die Authorisierung und die Anfrage an den Manager geschehen //Dazu einfach �ber nen Socket ne primitive http anfrage senden und die Antwort auswerten //Achtung momentan ist BUF_SIZE auch die maximale Nachrichtengr��e die Empfangen werden kann!! //@TODO Dringend ne bessere HTTP Implementation verwenden oder selber bauen. const int BUF_SIZE = 2048; char tmpBuffer[BUF_SIZE]; SOCKET httpSocket = rfbConnectToTcpAddr(const_cast<char*> (managerHost.c_str()), managerPort); std::string httpResponse; if (httpSocket == INVALID_SOCKET) { std::cerr << "Failed to connect to " << managerHost << ":" << managerPort << std::endl; throw std::runtime_error(STR_ERR_WEBHOST_UNREACHABLE); return; } //HTTPS Verbindung mit GnuTLS und handkodierter HTTP Nachricht :) gnutls_session_t session = 0; gnutls_certificate_credentials_t credentials = 0; gnutls_datum_t data; int gtlsRet = GNUTLS_E_SUCCESS; try { //Zertifikat if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_certificate_allocate_credentials(&credentials))) { std::cerr << "failed to allocate credentials." << std::endl; throw std::runtime_error("failed to allocate credentials."); } data.size = caCertificate.size(); data.data = (unsigned char*) caCertificate.data(); gnutls_certificate_set_x509_trust_mem(credentials, &data, GNUTLS_X509_FMT_PEM); // Verifizierung des Zertifikats in der übergebenen Callback Funktion, Ausführung erfolgt als Teil des Handshakes gnutls_certificate_set_verify_function(credentials, [] (gnutls_session_t session) throw () -> int { std::cout << "verifying certificate..."; //Server Zertifikat prüfen: unsigned int verify = 0; if (GNUTLS_E_SUCCESS != gnutls_certificate_verify_peers3(session, (const char*) gnutls_session_get_ptr(session), &verify)) { std::cerr << "certficate verification failed." << std::endl; return -1; } if (verify != 0) { gnutls_datum_t pr; std::cout << "no" << std::endl; gnutls_certificate_verification_status_print(verify, GNUTLS_CRT_X509, &pr, 0); std::cerr << pr.data << std::endl; free(pr.data); return -2; } std::cout << "yes" << std::endl; return 0; }); //Session if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_init(&session, GNUTLS_CLIENT))) { std::cerr << "failed to init session." << std::endl; throw std::runtime_error("failed to init session."); } gnutls_server_name_set(session, GNUTLS_NAME_DNS, managerHost.data(), managerHost.length()); gnutls_session_set_ptr(session, (void*) managerHost.c_str()); if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_priority_set_direct(session, CIPHERSUITE_PRIORITIES, 0))) { std::cerr << "failed to set priority." << std::endl; throw std::runtime_error("failed to set priority."); } gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, credentials); gnutls_transport_set_int(session, httpSocket); gnutls_handshake_set_timeout(session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); if (GNUTLS_E_SUCCESS != ((gtlsRet = gnutls_handshake(session)))) { std::cerr << "handshake failed." << std::endl; throw std::runtime_error("handshake failed."); } //Ciphersuite std::cout << "ciphersuite: " << gnutls_cipher_suite_get_name(gnutls_kx_get(session), gnutls_cipher_get(session), gnutls_mac_get(session)) << std::endl; //Prepare HTTP Request std::string httpRequest; std::string httpRequestBody = managerParam + "=" + urlencode(conferenceUrl) + "&version=" + std::to_string(TOOL_VERSION); httpRequest += "POST "; httpRequest += managerPath; httpRequest += " HTTP/1.1\r\n"; httpRequest += "Host: "; httpRequest += managerHost + "\r\n"; httpRequest += "Content-Type: application/x-www-form-urlencoded\r\n"; //< Beachte der Webserver kann auf der Zielroute momentan auch nichts anderes httpRequest += "Connection: close\r\n"; sprintf(tmpBuffer, "%d", httpRequestBody.length()); httpRequest += "Content-Length: " + std::string(tmpBuffer) + "\r\n"; httpRequest += "\r\n"; httpRequest += httpRequestBody; std::cout << "SEND >>" << std::endl << httpRequest << std::endl << "<<" << std::endl; gnutls_record_send(session, httpRequest.data(), httpRequest.length()); std::cout << "WAITING TO RECEIVE.." << std::endl; //Alles lesen und hoffen dass sich der Webserver dran h�lt und die Verbindung schlie�t //wenn er fertig mit Senden ist int c = 0, r = 0; do { r = gnutls_record_recv(session, tmpBuffer + c, BUF_SIZE - c); if (r > 0) c += r; } while (r > 0 && c < BUF_SIZE); if (c > 1024 || c <= 0) { std::cout << "received " << c << " bytes" << std::endl; std::cout << std::string(tmpBuffer, c) << std::endl; std::cerr << "Couldn't receive answer." << std::endl; throw std::runtime_error(STR_ERR_WRONG_ANSWER); } httpResponse = std::string(tmpBuffer, c); //Und fertig Verbindung beenden gnutls_bye(session, GNUTLS_SHUT_RDWR); gnutls_deinit(session); gnutls_certificate_free_credentials(credentials); closesocket(httpSocket); } catch (...) { //Irgendein Fehler trat auf, dann schließen. std::cerr << gtlsRet << ' ' << gnutls_error_is_fatal(gtlsRet) << std::endl; std::cerr << gnutls_strerror(gtlsRet) << std::endl; std::cerr << gnutls_alert_get_name(gnutls_alert_get(session)) << std::endl; if (session) gnutls_deinit(session); if (credentials) gnutls_certificate_free_credentials(credentials); closesocket(httpSocket); throw std::runtime_error(STR_ERR_TLS_FAILED); //weiterschmeißen } std::cout << "RECV >>" << std::endl << httpResponse << std::endl << "<<" << std::endl; /** Antwort sollte jetzt der typische HTTP Antwortquark sein und als Inhalt sollte ein Text der folgenden Form sein: PresentationServerUseHost: <host>\n PresentationServerUsePort: <port>\n */ unsigned short port; std::string host; int lifetime; try { _messageBox = utf8_to_ucs2(getParameter(httpResponse, "MessageBox", "")); port = atoi(getParameter(httpResponse, "PresentationServerUsePort").c_str()); host = getParameter(httpResponse, "PresentationServerUseHost"); _demo = atoi(getParameter(httpResponse, "Demo", "0").c_str()) ? true : false; lifetime = atoi(getParameter(httpResponse, "RuntimeSec", "0").c_str()); _serverPassword = getParameter(httpResponse, "PresentationServerPassword"); } catch (std::runtime_error e) { if (!_messageBox.empty()) throw runtime_error_with_extra_msg(_messageBox, getParameter(httpResponse, "Message")); throw std::runtime_error(getParameter(httpResponse, "Message")); } //Wenn die erfolgreich war dann den Server erstellen, Gr��e = Desktopgr��e _initRfbServer(screenWidth, screenHeight, _serverPassword, managerHost, caCertificate, host, port); if (lifetime > 0) { _timeOfDeath = std::chrono::system_clock::now() + std::chrono::seconds(lifetime); _useTimeOfDeath = true; } else { _useTimeOfDeath = false; } }
rfbNewClientAction upgradeNewClientToTls (_rfbClientRec* cl) { //Eine SSL Session beginnen gnutls_session_t session = 0; gnutls_certificate_credentials_t credentials = 0; gnutls_datum_t data; int gtlsRet = GNUTLS_E_SUCCESS; std::cout<<"New Client Connection, upgrade protocol to Tls"<<std::endl; try { //Zertifikat if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_certificate_allocate_credentials(&credentials))) { std::cerr << "failed to allocate credentials." << std::endl; throw std::runtime_error("failed to allocate credentials."); } data.size = g_caCertificate.size(); data.data = (unsigned char*) g_caCertificate.data(); gnutls_certificate_set_x509_trust_mem(credentials, &data, GNUTLS_X509_FMT_PEM); // Verifizierung des Zertifikats in der übergebenen Callback Funktion, Ausführung erfolgt als Teil des Handshakes gnutls_certificate_set_verify_function(credentials, [] (gnutls_session_t session) throw () -> int { std::cout << "verifying certificate..."; //Server Zertifikat prüfen: unsigned int verify = 0; if (GNUTLS_E_SUCCESS != gnutls_certificate_verify_peers3(session, (const char*) gnutls_session_get_ptr(session), &verify)) { std::cerr << "certficate verification failed." << std::endl; return -1; } if (verify != 0) { gnutls_datum_t pr; std::cout << "no" << std::endl; gnutls_certificate_verification_status_print(verify, GNUTLS_CRT_X509, &pr, 0); std::cerr << pr.data << std::endl; free(pr.data); return -2; } std::cout << "yes" << std::endl; return 0; }); //Session if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_init(&session, GNUTLS_CLIENT))) { std::cerr << "failed to init session." << std::endl; throw std::runtime_error("failed to init session."); } gnutls_server_name_set(session, GNUTLS_NAME_DNS, g_peerHostName.data(), g_peerHostName.length()); gnutls_session_set_ptr(session, (void*) g_peerHostName.c_str()); if (GNUTLS_E_SUCCESS != (gtlsRet = gnutls_priority_set_direct(session, CIPHERSUITE_PRIORITIES, 0))) { std::cerr << "failed to set priority." << std::endl; throw std::runtime_error("failed to set priority."); } gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, credentials); gnutls_transport_set_int(session, cl->sock); gnutls_handshake_set_timeout(session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT); if (GNUTLS_E_SUCCESS != ((gtlsRet = gnutls_handshake(session)))) { std::cerr << "handshake failed." << std::endl; throw std::runtime_error("handshake failed."); } //Ciphersuite std::cout << "ciphersuite: " << gnutls_cipher_suite_get_name(gnutls_kx_get(session), gnutls_cipher_get(session), gnutls_mac_get(session)) << std::endl; //Send password, which was received in answer of webserver if ((gtlsRet = gnutls_record_send(session, (void*)g_serverPassword.data(), g_serverPassword.size())) <= 0) { std::cerr << "Sending Password failed." << std::endl; throw std::runtime_error("Sending Password failed."); } rfbssl_ctx* ctx = (rfbssl_ctx*) malloc(sizeof(struct rfbssl_ctx)); ctx->peeklen = 0; ctx->peekstart = 0; ctx->session = session; ctx->x509_cred = credentials; ctx->dh_params = 0; cl->sslctx = (rfbSslCtx*)ctx; } catch (...) { //Irgendein Fehler trat auf, dann schließen. std::cerr << gtlsRet << ' ' << gnutls_error_is_fatal(gtlsRet) << std::endl; std::cerr << gnutls_strerror(gtlsRet) << std::endl; std::cerr << gnutls_alert_get_name(gnutls_alert_get(session)) << std::endl; if (session) gnutls_deinit(session); if (credentials) gnutls_certificate_free_credentials(credentials); return RFB_CLIENT_REFUSE; } return RFB_CLIENT_ACCEPT; }
/** * tls_negotiate - Negotiate TLS connection * @param conn Connection to a server * @retval 0 Success * @retval -1 Error * * After TLS state has been initialized, attempt to negotiate TLS over the * wire, including certificate checks. */ static int tls_negotiate(struct Connection *conn) { struct TlsSockData *data = mutt_mem_calloc(1, sizeof(struct TlsSockData)); conn->sockdata = data; int err = gnutls_certificate_allocate_credentials(&data->xcred); if (err < 0) { FREE(&conn->sockdata); mutt_error("gnutls_certificate_allocate_credentials: %s", gnutls_strerror(err)); return -1; } gnutls_certificate_set_x509_trust_file(data->xcred, C_CertificateFile, GNUTLS_X509_FMT_PEM); /* ignore errors, maybe file doesn't exist yet */ if (C_SslCaCertificatesFile) { gnutls_certificate_set_x509_trust_file(data->xcred, C_SslCaCertificatesFile, GNUTLS_X509_FMT_PEM); } if (C_SslClientCert) { mutt_debug(LL_DEBUG2, "Using client certificate %s\n", C_SslClientCert); gnutls_certificate_set_x509_key_file(data->xcred, C_SslClientCert, C_SslClientCert, GNUTLS_X509_FMT_PEM); } #ifdef HAVE_DECL_GNUTLS_VERIFY_DISABLE_TIME_CHECKS /* disable checking certificate activation/expiration times * in gnutls, we do the checks ourselves */ gnutls_certificate_set_verify_flags(data->xcred, GNUTLS_VERIFY_DISABLE_TIME_CHECKS); #endif err = gnutls_init(&data->state, GNUTLS_CLIENT); if (err) { mutt_error("gnutls_handshake: %s", gnutls_strerror(err)); goto fail; } /* set socket */ gnutls_transport_set_ptr(data->state, (gnutls_transport_ptr_t)(long) conn->fd); if (gnutls_server_name_set(data->state, GNUTLS_NAME_DNS, conn->account.host, mutt_str_strlen(conn->account.host))) { mutt_error(_("Warning: unable to set TLS SNI host name")); } if (tls_set_priority(data) < 0) { goto fail; } if (C_SslMinDhPrimeBits > 0) { gnutls_dh_set_prime_bits(data->state, C_SslMinDhPrimeBits); } /* gnutls_set_cred (data->state, GNUTLS_ANON, NULL); */ gnutls_credentials_set(data->state, GNUTLS_CRD_CERTIFICATE, data->xcred); err = gnutls_handshake(data->state); while (err == GNUTLS_E_AGAIN) { err = gnutls_handshake(data->state); } if (err < 0) { if (err == GNUTLS_E_FATAL_ALERT_RECEIVED) { mutt_error("gnutls_handshake: %s(%s)", gnutls_strerror(err), gnutls_alert_get_name(gnutls_alert_get(data->state))); } else { mutt_error("gnutls_handshake: %s", gnutls_strerror(err)); } goto fail; } if (tls_check_certificate(conn) == 0) goto fail; /* set Security Strength Factor (SSF) for SASL */ /* NB: gnutls_cipher_get_key_size() returns key length in bytes */ conn->ssf = gnutls_cipher_get_key_size(gnutls_cipher_get(data->state)) * 8; tls_get_client_cert(conn); if (!OptNoCurses) { mutt_message(_("SSL/TLS connection using %s (%s/%s/%s)"), gnutls_protocol_get_name(gnutls_protocol_get_version(data->state)), gnutls_kx_get_name(gnutls_kx_get(data->state)), gnutls_cipher_get_name(gnutls_cipher_get(data->state)), gnutls_mac_get_name(gnutls_mac_get(data->state))); mutt_sleep(0); } return 0; fail: gnutls_certificate_free_credentials(data->xcred); gnutls_deinit(data->state); FREE(&conn->sockdata); return -1; }
static Ecore_Con_Ssl_Error _ecore_con_ssl_client_init_gnutls(Ecore_Con_Client *cl) { const gnutls_datum_t *cert_list; unsigned int iter, cert_list_size; const char *priority = "NONE:%VERIFY_ALLOW_X509_V1_CA_CRT:+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+COMP-DEFLATE:+COMP-NULL:+CTYPE-X509:+SHA1:+SHA256:+SHA384:+SHA512:+AES-256-CBC:+AES-128-CBC:+3DES-CBC:+VERS-TLS1.2:+VERS-TLS1.1:+VERS-TLS1.0:+VERS-SSL3.0"; int ret = 0; switch (cl->ssl_state) { case ECORE_CON_SSL_STATE_DONE: return ECORE_CON_SSL_ERROR_NONE; case ECORE_CON_SSL_STATE_INIT: if (cl->host_server->type & ECORE_CON_USE_SSL2) /* not supported because of security issues */ return ECORE_CON_SSL_ERROR_SSL2_NOT_SUPPORTED; switch (cl->host_server->type & ECORE_CON_SSL) { case ECORE_CON_USE_SSL3: case ECORE_CON_USE_SSL3 | ECORE_CON_LOAD_CERT: priority = "NONE:%VERIFY_ALLOW_X509_V1_CA_CRT:+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+COMP-DEFLATE:+COMP-NULL:+CTYPE-X509:+SHA1:+SHA256:+SHA384:+SHA512:+AES-256-CBC:+AES-128-CBC:+3DES-CBC:!VERS-TLS1.0:!VERS-TLS1.1"; break; case ECORE_CON_USE_TLS: case ECORE_CON_USE_TLS | ECORE_CON_LOAD_CERT: priority = "NONE:%VERIFY_ALLOW_X509_V1_CA_CRT:+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+COMP-DEFLATE:+COMP-NULL:+CTYPE-X509:+SHA1:+SHA256:+SHA384:+SHA512:+AES-256-CBC:+AES-128-CBC:+3DES-CBC:!VERS-SSL3.0"; break; case ECORE_CON_USE_MIXED: case ECORE_CON_USE_MIXED | ECORE_CON_LOAD_CERT: break; default: return ECORE_CON_SSL_ERROR_NONE; } _client_connected++; SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_init(&cl->session, GNUTLS_SERVER)); SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_session_ticket_key_generate(&cl->session_ticket)); SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_session_ticket_enable_server(cl->session, &cl->session_ticket)); INF("Applying priority string: %s", priority); SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_priority_set_direct(cl->session, priority, NULL)); SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(cl->session, GNUTLS_CRD_CERTIFICATE, cl->host_server->cert)); // SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(cl->session, GNUTLS_CRD_PSK, cl->host_server->pskcred_s)); if (!cl->host_server->use_cert) SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_credentials_set(cl->session, GNUTLS_CRD_ANON, cl->host_server->anoncred_s)); gnutls_certificate_server_set_request(cl->session, GNUTLS_CERT_REQUEST); gnutls_dh_set_prime_bits(cl->session, 2048); gnutls_transport_set_ptr(cl->session, (gnutls_transport_ptr_t)((intptr_t)cl->fd)); cl->ssl_state = ECORE_CON_SSL_STATE_HANDSHAKING; case ECORE_CON_SSL_STATE_HANDSHAKING: if (!cl->session) { DBG("Client was previously lost, going to error condition"); goto error; } DBG("calling gnutls_handshake()"); ret = gnutls_handshake(cl->session); SSL_ERROR_CHECK_GOTO_ERROR(gnutls_error_is_fatal(ret)); if (!ret) { cl->handshaking = EINA_FALSE; cl->ssl_state = ECORE_CON_SSL_STATE_DONE; } else { if (gnutls_record_get_direction(cl->session)) ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_WRITE); else ecore_main_fd_handler_active_set(cl->fd_handler, ECORE_FD_READ); return ECORE_CON_SSL_ERROR_NONE; } default: break; } if (!cl->host_server->verify) /* not verifying certificates, so we're done! */ return ECORE_CON_SSL_ERROR_NONE; ret = 0; /* use CRL/CA lists to verify */ SSL_ERROR_CHECK_GOTO_ERROR(ret = gnutls_certificate_verify_peers2(cl->session, &iter)); if (iter & GNUTLS_CERT_INVALID) ERR("The certificate is not trusted."); else if (iter & GNUTLS_CERT_SIGNER_NOT_FOUND) ERR("The certificate hasn't got a known issuer."); else if (iter & GNUTLS_CERT_REVOKED) ERR("The certificate has been revoked."); else if (iter & GNUTLS_CERT_EXPIRED) ERR("The certificate has expired"); else if (iter & GNUTLS_CERT_NOT_ACTIVATED) ERR("The certificate is not yet activated"); if (iter) goto error; if (gnutls_certificate_type_get(cl->session) != GNUTLS_CRT_X509) { ERR("Warning: PGP certificates are not yet supported!"); goto error; } SSL_ERROR_CHECK_GOTO_ERROR(!(cert_list = gnutls_certificate_get_peers(cl->session, &cert_list_size))); SSL_ERROR_CHECK_GOTO_ERROR(!cert_list_size); DBG("SSL certificate verification succeeded!"); return ECORE_CON_SSL_ERROR_NONE; error: _gnutls_print_errors(ret); if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED) || (ret == GNUTLS_E_FATAL_ALERT_RECEIVED)) ERR("Also received alert: %s", gnutls_alert_get_name(gnutls_alert_get(cl->session))); if (cl->session && (cl->ssl_state != ECORE_CON_SSL_STATE_DONE)) { ERR("last out: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_out(cl->session))); ERR("last in: %s", SSL_GNUTLS_PRINT_HANDSHAKE_STATUS(gnutls_handshake_get_last_in(cl->session))); } _ecore_con_ssl_client_shutdown_gnutls(cl); return ECORE_CON_SSL_ERROR_SERVER_INIT_FAILED; }
static apr_status_t gnutls_io_input_read(mgs_handle_t * ctxt, char *buf, apr_size_t * len) { apr_size_t wanted = *len; apr_size_t bytes = 0; int rc; *len = 0; /* If we have something leftover from last time, try that first. */ if ((bytes = char_buffer_read(&ctxt->input_cbuf, buf, wanted))) { *len = bytes; if (ctxt->input_mode == AP_MODE_SPECULATIVE) { /* We want to rollback this read. */ if (ctxt->input_cbuf.length > 0) { ctxt->input_cbuf.value -= bytes; ctxt->input_cbuf.length += bytes; } else { char_buffer_write(&ctxt->input_cbuf, buf, (int) bytes); } return APR_SUCCESS; } /* This could probably be *len == wanted, but be safe from stray * photons. */ if (*len >= wanted) { return APR_SUCCESS; } if (ctxt->input_mode == AP_MODE_GETLINE) { if (memchr(buf, APR_ASCII_LF, *len)) { return APR_SUCCESS; } } else { /* Down to a nonblock pattern as we have some data already */ ctxt->input_block = APR_NONBLOCK_READ; } } if (ctxt->session == NULL) { return APR_EGENERAL; } while (1) { rc = gnutls_record_recv(ctxt->session, buf + bytes, wanted - bytes); if (rc > 0) { *len += rc; if (ctxt->input_mode == AP_MODE_SPECULATIVE) { /* We want to rollback this read. */ char_buffer_write(&ctxt->input_cbuf, buf, rc); } return ctxt->input_rc; } else if (rc == 0) { /* If EAGAIN, we will loop given a blocking read, * otherwise consider ourselves at EOF. */ if (APR_STATUS_IS_EAGAIN(ctxt->input_rc) || APR_STATUS_IS_EINTR(ctxt->input_rc)) { /* Already read something, return APR_SUCCESS instead. * On win32 in particular, but perhaps on other kernels, * a blocking call isn't 'always' blocking. */ if (*len > 0) { ctxt->input_rc = APR_SUCCESS; break; } if (ctxt->input_block == APR_NONBLOCK_READ) { break; } } else { if (*len > 0) { ctxt->input_rc = APR_SUCCESS; } else { ctxt->input_rc = APR_EOF; } break; } } else { /* (rc < 0) */ if (rc == GNUTLS_E_REHANDSHAKE) { /* A client has asked for a new Hankshake. Currently, we don't do it */ ap_log_error(APLOG_MARK, APLOG_INFO, ctxt->input_rc, ctxt->c->base_server, "GnuTLS: Error reading data. Client Requested a New Handshake." " (%d) '%s'", rc, gnutls_strerror(rc)); } else if (rc == GNUTLS_E_WARNING_ALERT_RECEIVED) { rc = gnutls_alert_get(ctxt->session); ap_log_error(APLOG_MARK, APLOG_INFO, ctxt->input_rc, ctxt->c->base_server, "GnuTLS: Warning Alert From Client: " " (%d) '%s'", rc, gnutls_alert_get_name(rc)); } else if (rc == GNUTLS_E_FATAL_ALERT_RECEIVED) { rc = gnutls_alert_get(ctxt->session); ap_log_error(APLOG_MARK, APLOG_INFO, ctxt->input_rc, ctxt->c->base_server, "GnuTLS: Fatal Alert From Client: " "(%d) '%s'", rc, gnutls_alert_get_name(rc)); ctxt->input_rc = APR_EGENERAL; break; } else { /* Some Other Error. Report it. Die. */ if (gnutls_error_is_fatal(rc)) { ap_log_error(APLOG_MARK, APLOG_INFO, ctxt->input_rc, ctxt->c->base_server, "GnuTLS: Error reading data. (%d) '%s'", rc, gnutls_strerror(rc)); } else if (*len > 0) { ctxt->input_rc = APR_SUCCESS; break; } } if (ctxt->input_rc == APR_SUCCESS) { ctxt->input_rc = APR_EGENERAL; } break; } } return ctxt->input_rc; }
static void fusion_tls_connection_handle_error (FusionTLSConnection* self, int ecode, gint where, GError** error) { gboolean _tmp0_ = FALSE; int _tmp1_ = 0; gboolean _tmp3_ = FALSE; gboolean _tmp8_ = FALSE; int _tmp9_ = 0; gboolean _tmp12_ = FALSE; GError * _inner_error_ = NULL; g_return_if_fail (self != NULL); _tmp1_ = ecode; if (_tmp1_ == GNUTLS_E_WARNING_ALERT_RECEIVED) { _tmp0_ = TRUE; } else { int _tmp2_ = 0; _tmp2_ = ecode; _tmp0_ = _tmp2_ == GNUTLS_E_FATAL_ALERT_RECEIVED; } _tmp3_ = _tmp0_; if (_tmp3_) { gnutls_alert_description_t alert = 0; struct gnutls_session_int* _tmp4_ = NULL; gnutls_alert_description_t _tmp5_ = 0; gnutls_alert_description_t _tmp6_ = 0; const gchar* _tmp7_ = NULL; _tmp4_ = self->tls_session; _tmp5_ = gnutls_alert_get (_tmp4_); alert = _tmp5_; _tmp6_ = alert; _tmp7_ = gnutls_alert_get_name (_tmp6_); g_warning ("TLSConnection.vala:74: TLS handshake alert: %s", _tmp7_); } _tmp9_ = ecode; if (_tmp9_ < 0) { int _tmp10_ = 0; gboolean _tmp11_ = FALSE; _tmp10_ = ecode; _tmp11_ = gnutls_error_is_fatal (_tmp10_); _tmp8_ = _tmp11_; } else { _tmp8_ = FALSE; } _tmp12_ = _tmp8_; if (_tmp12_) { gint _tmp13_ = 0; _tmp13_ = where; switch (_tmp13_) { case 0: { int _tmp14_ = 0; const gchar* _tmp15_ = NULL; GError* _tmp16_ = NULL; _tmp14_ = ecode; _tmp15_ = gnutls_strerror (_tmp14_); _tmp16_ = g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED, "Handshake failed: %s", _tmp15_); _inner_error_ = _tmp16_; if (_inner_error_->domain == G_IO_ERROR) { g_propagate_error (error, _inner_error_); return; } else { g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); g_clear_error (&_inner_error_); return; } } case 1: { int _tmp17_ = 0; const gchar* _tmp18_ = NULL; GError* _tmp19_ = NULL; _tmp17_ = ecode; _tmp18_ = gnutls_strerror (_tmp17_); _tmp19_ = g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED, "Receive failed: %s", _tmp18_); _inner_error_ = _tmp19_; if (_inner_error_->domain == G_IO_ERROR) { g_propagate_error (error, _inner_error_); return; } else { g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); g_clear_error (&_inner_error_); return; } } case 2: { int _tmp20_ = 0; const gchar* _tmp21_ = NULL; GError* _tmp22_ = NULL; _tmp20_ = ecode; _tmp21_ = gnutls_strerror (_tmp20_); _tmp22_ = g_error_new (G_IO_ERROR, G_IO_ERROR_FAILED, "Send failed: %s", _tmp21_); _inner_error_ = _tmp22_; if (_inner_error_->domain == G_IO_ERROR) { g_propagate_error (error, _inner_error_); return; } else { g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error_->message, g_quark_to_string (_inner_error_->domain), _inner_error_->code); g_clear_error (&_inner_error_); return; } } default: { g_assert_not_reached (); } } } }
/* tls_negotiate: After TLS state has been initialised, attempt to negotiate * TLS over the wire, including certificate checks. */ static int tls_negotiate (CONNECTION * conn) { tlssockdata *data; int err; size_t nproto = 0; /* number of tls/ssl protocols */ data = (tlssockdata *) safe_calloc (1, sizeof (tlssockdata)); conn->sockdata = data; err = gnutls_certificate_allocate_credentials (&data->xcred); if (err < 0) { FREE(&conn->sockdata); mutt_error ("gnutls_certificate_allocate_credentials: %s", gnutls_strerror(err)); mutt_sleep (2); return -1; } gnutls_certificate_set_x509_trust_file (data->xcred, SslCertFile, GNUTLS_X509_FMT_PEM); /* ignore errors, maybe file doesn't exist yet */ if (SslCACertFile) { gnutls_certificate_set_x509_trust_file (data->xcred, SslCACertFile, GNUTLS_X509_FMT_PEM); } if (SslClientCert) { dprint (2, (debugfile, "Using client certificate %s\n", SslClientCert)); gnutls_certificate_set_x509_key_file (data->xcred, SslClientCert, SslClientCert, GNUTLS_X509_FMT_PEM); } #if HAVE_DECL_GNUTLS_VERIFY_DISABLE_TIME_CHECKS /* disable checking certificate activation/expiration times in gnutls, we do the checks ourselves */ gnutls_certificate_set_verify_flags(data->xcred, GNUTLS_VERIFY_DISABLE_TIME_CHECKS); #endif if ((err = gnutls_init(&data->state, GNUTLS_CLIENT))) { mutt_error ("gnutls_handshake: %s", gnutls_strerror(err)); mutt_sleep (2); goto fail; } /* set socket */ gnutls_transport_set_ptr (data->state, (gnutls_transport_ptr)conn->fd); if (option(OPTTLSV1_2)) protocol_priority[nproto++] = GNUTLS_TLS1_2; if (option(OPTTLSV1_1)) protocol_priority[nproto++] = GNUTLS_TLS1_1; if (option(OPTTLSV1)) protocol_priority[nproto++] = GNUTLS_TLS1; if (option(OPTSSLV3)) protocol_priority[nproto++] = GNUTLS_SSL3; protocol_priority[nproto] = 0; /* disable TLS/SSL protocols as needed */ if (nproto == 0) { mutt_error (_("All available protocols for TLS/SSL connection disabled")); goto fail; } /* else use the list set above */ /* We use default priorities (see gnutls documentation), except for protocol version */ gnutls_set_default_priority (data->state); gnutls_protocol_set_priority (data->state, protocol_priority); if (SslDHPrimeBits > 0) { gnutls_dh_set_prime_bits (data->state, SslDHPrimeBits); } /* gnutls_set_cred (data->state, GNUTLS_ANON, NULL); */ gnutls_credentials_set (data->state, GNUTLS_CRD_CERTIFICATE, data->xcred); err = gnutls_handshake(data->state); while (err == GNUTLS_E_AGAIN || err == GNUTLS_E_INTERRUPTED) { err = gnutls_handshake(data->state); } if (err < 0) { if (err == GNUTLS_E_FATAL_ALERT_RECEIVED) { mutt_error("gnutls_handshake: %s(%s)", gnutls_strerror(err), gnutls_alert_get_name(gnutls_alert_get(data->state))); } else { mutt_error("gnutls_handshake: %s", gnutls_strerror(err)); } mutt_sleep (2); goto fail; } if (!tls_check_certificate(conn)) goto fail; /* set Security Strength Factor (SSF) for SASL */ /* NB: gnutls_cipher_get_key_size() returns key length in bytes */ conn->ssf = gnutls_cipher_get_key_size (gnutls_cipher_get (data->state)) * 8; tls_get_client_cert (conn); if (!option(OPTNOCURSES)) { mutt_message (_("SSL/TLS connection using %s (%s/%s/%s)"), gnutls_protocol_get_name (gnutls_protocol_get_version (data->state)), gnutls_kx_get_name (gnutls_kx_get (data->state)), gnutls_cipher_get_name (gnutls_cipher_get (data->state)), gnutls_mac_get_name (gnutls_mac_get (data->state))); mutt_sleep (0); } return 0; fail: gnutls_certificate_free_credentials (data->xcred); gnutls_deinit (data->state); FREE(&conn->sockdata); return -1; }
static const char *get_alert_text(struct ssl_proxy *proxy) { return gnutls_alert_get_name(gnutls_alert_get(proxy->session)); }
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); } } }
int _gnutls_recv_client_certificate(gnutls_session_t session) { gnutls_buffer_st buf; int ret = 0; int optional; if (session->internals.auth_struct-> gnutls_process_client_certificate == NULL) return 0; /* if we have not requested a certificate then just return */ if (session->internals.send_cert_req == 0) { return 0; } if (session->internals.send_cert_req == GNUTLS_CERT_REQUIRE) optional = 0; else optional = 1; ret = _gnutls_recv_handshake(session, GNUTLS_HANDSHAKE_CERTIFICATE_PKT, optional, &buf); if (ret < 0) { /* Handle the case of old SSL3 clients who send * a warning alert instead of an empty certificate to indicate * no certificate. */ #ifdef ENABLE_SSL3 if (optional != 0 && ret == GNUTLS_E_WARNING_ALERT_RECEIVED && get_num_version(session) == GNUTLS_SSL3 && gnutls_alert_get(session) == GNUTLS_A_SSL3_NO_CERTIFICATE) { /* SSL3 does not send an empty certificate, * but this alert. So we just ignore it. */ gnutls_assert(); return 0; } #endif /* certificate was required */ if ((ret == GNUTLS_E_WARNING_ALERT_RECEIVED || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) && optional == 0) { gnutls_assert(); return GNUTLS_E_NO_CERTIFICATE_FOUND; } return ret; } if (ret == 0 && buf.length == 0 && optional != 0) { /* Client has not sent the certificate message. * well I'm not sure we should accept this * behaviour. */ gnutls_assert(); ret = 0; goto cleanup; } ret = session->internals.auth_struct-> gnutls_process_client_certificate(session, buf.data, buf.length); if (ret < 0 && ret != GNUTLS_E_NO_CERTIFICATE_FOUND) { gnutls_assert(); goto cleanup; } /* ok we should expect a certificate verify message now */ if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND && optional != 0) ret = 0; else session->internals.crt_requested = 1; cleanup: _gnutls_buffer_clear(&buf); return ret; }