/** * gnutls_session_get_data: * @session: is a #gnutls_session_t type. * @session_data: is a pointer to space to hold the session. * @session_data_size: is the session_data's size, or it will be set by the function. * * Returns all session parameters needed to be stored to support resumption. * The client should call this, and store the returned session data. A session * may be resumed later by calling gnutls_session_set_data(). * * This function will fail if called prior to handshake completion. In * case of false start TLS, the handshake completes only after data have * been successfully received from the peer. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise * an error code is returned. **/ int gnutls_session_get_data(gnutls_session_t session, void *session_data, size_t * session_data_size) { gnutls_datum_t psession; int ret; ret = gnutls_session_get_data2(session, &psession); if (ret < 0) { gnutls_assert(); return ret; } if (psession.size > *session_data_size) { *session_data_size = psession.size; ret = GNUTLS_E_SHORT_MEMORY_BUFFER; goto error; } *session_data_size = psession.size; if (session_data != NULL) memcpy(session_data, psession.data, psession.size); ret = 0; error: _gnutls_free_datum(&psession); return ret; }
static int ticket_callback(gnutls_session_t session, unsigned int htype, unsigned post, unsigned int incoming, const gnutls_datum_t *msg) { gnutls_datum *d; static int counter = 0; int ret; assert(htype == GNUTLS_HANDSHAKE_NEW_SESSION_TICKET); counter++; if (counter <= TLS13_TICKETS_TO_SEND) /* ignore the default tickets sent */ return 0; d = gnutls_session_get_ptr(session); if (post == GNUTLS_HOOK_POST) { tickets_seen++; if (d->data) gnutls_free(d->data); ret = gnutls_session_get_data2(session, d); assert(ret >= 0); assert(d->size > 4); return 0; } return 0; }
static void g_tls_client_connection_gnutls_finish_handshake (GTlsConnectionGnutls *conn, GError **inout_error) { GTlsClientConnectionGnutls *gnutls = G_TLS_CLIENT_CONNECTION_GNUTLS (conn); int resumed; g_assert (inout_error != NULL); if (g_error_matches (*inout_error, G_TLS_ERROR, G_TLS_ERROR_NOT_TLS) && gnutls->priv->cert_requested) { g_clear_error (inout_error); if (gnutls->priv->cert_error) { *inout_error = gnutls->priv->cert_error; gnutls->priv->cert_error = NULL; } else { g_set_error_literal (inout_error, G_TLS_ERROR, G_TLS_ERROR_CERTIFICATE_REQUIRED, _("Server required TLS certificate")); } } resumed = gnutls_session_is_resumed (g_tls_connection_gnutls_get_session (conn)); if (*inout_error || !resumed) { /* Clear session data since the server did not accept what we provided. */ gnutls->priv->session_data_override = FALSE; g_clear_pointer (&gnutls->priv->session_data, g_bytes_unref); if (gnutls->priv->session_id) g_tls_backend_gnutls_remove_session (GNUTLS_CLIENT, gnutls->priv->session_id); } if (!*inout_error && !resumed) { gnutls_datum_t session_datum; if (gnutls_session_get_data2 (g_tls_connection_gnutls_get_session (conn), &session_datum) == 0) { gnutls->priv->session_data = g_bytes_new_with_free_func (session_datum.data, session_datum.size, (GDestroyNotify)gnutls_free, session_datum.data); g_tls_backend_gnutls_store_session (GNUTLS_CLIENT, gnutls->priv->session_id, gnutls->priv->session_data); } } }
bool CTlsSocket::CopySessionData(const CTlsSocket* pPrimarySocket) { gnutls_datum_t d; int res = gnutls_session_get_data2(pPrimarySocket->m_session, &d); if (res) { m_pOwner->LogMessage(MessageType::Debug_Warning, _T("gnutls_session_get_data2 on primary socket failed: %d"), res); return true; } // Set session data res = gnutls_session_set_data(m_session, d.data, d.size ); gnutls_free(d.data); if (res) { m_pOwner->LogMessage(MessageType::Debug_Info, _T("gnutls_session_set_data failed: %d. Going to reinitialize session."), res); UninitSession(); if (!InitSession()) return false; } else m_pOwner->LogMessage(MessageType::Debug_Info, _T("Trying to resume existing TLS session.")); return true; }
static void client(int sds[], struct params_res *params) { int ret, ii; gnutls_session_t session; char buffer[MAX_BUF + 1]; gnutls_anon_client_credentials_t anoncred; /* Need to enable anonymous KX specifically. */ /* variables used in session resuming */ int t; gnutls_datum_t session_data; if (debug) { gnutls_global_set_log_function(tls_log_func); gnutls_global_set_log_level(3); } global_init(); gnutls_anon_allocate_client_credentials(&anoncred); for (t = 0; t < SESSIONS; t++) { int sd = sds[t]; /* Initialize TLS session */ gnutls_init(&session, GNUTLS_CLIENT | GNUTLS_DATAGRAM); /* Use default priorities */ if (params->enable_session_ticket_client) gnutls_priority_set_direct(session, "NONE:+VERS-DTLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-DH", NULL); else gnutls_priority_set_direct(session, "NONE:+VERS-DTLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-DH:%NO_TICKETS", NULL); /* put the anonymous credentials to the current session */ gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred); if (t > 0) { /* if this is not the first time we connect */ gnutls_session_set_data(session, session_data.data, session_data.size); gnutls_free(session_data.data); } gnutls_transport_set_int(session, sd); /* Perform the TLS handshake */ gnutls_dtls_set_timeouts(session, 3*1000, 240 * 1000); do { ret = gnutls_handshake(session); } while (ret < 0 && gnutls_error_is_fatal(ret) == 0); if (ret < 0) { gnutls_perror(ret); fail("client: Handshake failed\n"); goto end; } else { if (debug) success ("client: Handshake was completed\n"); } if (t == 0) { /* the first time we connect */ /* get the session data size */ ret = gnutls_session_get_data2(session, &session_data); if (ret < 0) fail("Getting resume data failed\n"); } else { /* the second time we connect */ /* check if we actually resumed the previous session */ if (gnutls_session_is_resumed(session) != 0) { if (params->expect_resume) { if (debug) success ("- Previous session was resumed\n"); } else fail("- Previous session was resumed\n"); } else { if (params->expect_resume) { fail("*** Previous session was NOT resumed\n"); } else { if (debug) success ("*** Previous session was NOT resumed (expected)\n"); } } } gnutls_record_send(session, MSG, strlen(MSG)); ret = gnutls_record_recv(session, buffer, MAX_BUF); if (ret == 0) { if (debug) success ("client: Peer has closed the TLS connection\n"); goto end; } else if (ret < 0) { fail("client: Error: %s\n", gnutls_strerror(ret)); goto end; } if (debug) { printf("- Received %d bytes: ", ret); for (ii = 0; ii < ret; ii++) { fputc(buffer[ii], stdout); } fputs("\n", stdout); } gnutls_bye(session, GNUTLS_SHUT_RDWR); close(sd); gnutls_deinit(session); } end: gnutls_anon_free_client_credentials(anoncred); }
/* Returns true if resumed */ static unsigned handshake(const char *prio, unsigned t, const gnutls_datum_t *sdata, gnutls_datum_t *ndata, gnutls_datum_t *skey, struct hsk_st *h) { int ret; /* 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; char buf[128]; gnutls_global_set_log_function(tls_log_func); if (debug) gnutls_global_set_log_level(6); assert(gnutls_certificate_allocate_credentials(&serverx509cred)>=0); assert(gnutls_certificate_set_x509_key_mem(serverx509cred, &server_cert, &server_key, GNUTLS_X509_FMT_PEM)>=0); assert(gnutls_init(&server, GNUTLS_SERVER)>=0); gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, serverx509cred); assert(gnutls_priority_set_direct(server, prio, NULL)>=0); gnutls_transport_set_push_function(server, server_push); gnutls_transport_set_pull_function(server, server_pull); gnutls_transport_set_ptr(server, server); gnutls_session_set_ptr(server, h); gnutls_db_set_cache_expiration(server, t); assert(gnutls_session_ticket_enable_server(server, skey) >= 0); gnutls_handshake_set_hook_function(server, -1, GNUTLS_HOOK_POST, handshake_callback); assert(gnutls_certificate_allocate_credentials(&clientx509cred)>=0); assert(gnutls_certificate_set_x509_trust_mem(clientx509cred, &ca_cert, GNUTLS_X509_FMT_PEM)>=0); assert(gnutls_init(&client, GNUTLS_CLIENT)>=0); assert(gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, clientx509cred)>=0); assert(gnutls_priority_set_direct(client, prio, NULL)>=0); gnutls_transport_set_push_function(client, client_push); gnutls_transport_set_pull_function(client, client_pull); gnutls_transport_set_ptr(client, client); if (sdata) { assert(gnutls_session_set_data(client, sdata->data, sdata->size)>=0); } memset(buf, 0, sizeof(buf)); ret = gnutls_session_set_data(client, buf, sizeof(buf)); if (ret != GNUTLS_E_DB_ERROR) { fail("unexpected error: %s\n", gnutls_strerror(ret)); } HANDSHAKE(client, server); gnutls_record_recv(client, buf, sizeof(buf)); if (ndata) { ret = gnutls_session_get_data2(client, ndata); if (ret < 0) { fail("unexpected error: %s\n", gnutls_strerror(ret)); } } ret = gnutls_session_is_resumed(client); gnutls_deinit(server); gnutls_deinit(client); gnutls_certificate_free_credentials(serverx509cred); gnutls_certificate_free_credentials(clientx509cred); reset_buffers(); return ret; }
void client (void) { int ret, sd, ii; gnutls_session_t session; char buffer[MAX_BUF + 1]; gnutls_anon_client_credentials_t anoncred; /* Need to enable anonymous KX specifically. */ const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 }; /* variables used in session resuming */ int t; gnutls_datum session_data; gnutls_global_init (); gnutls_anon_allocate_client_credentials (&anoncred); for (t = 0; t < 2; t++) { /* connect 2 times to the server */ /* connect to the peer */ sd = tcp_connect (); /* Initialize TLS session */ gnutls_init (&session, GNUTLS_CLIENT); /* Use default priorities */ gnutls_set_default_priority (session); gnutls_kx_set_priority (session, kx_prio); /* put the anonymous credentials to the current session */ gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred); if (t > 0) { /* if this is not the first time we connect */ gnutls_session_set_data (session, session_data.data, session_data.size); gnutls_free (session_data.data); } gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd); /* Perform the TLS handshake */ ret = gnutls_handshake (session); if (ret < 0) { fail ("client: Handshake failed\n"); gnutls_perror (ret); goto end; } else { success ("client: Handshake was completed\n"); } if (t == 0) { /* the first time we connect */ /* get the session data size */ ret = gnutls_session_get_data2 (session, &session_data); if (ret < 0) fail ("Getting resume data failed\n"); } else { /* the second time we connect */ /* check if we actually resumed the previous session */ if (gnutls_session_is_resumed (session) != 0) { success ("- Previous session was resumed\n"); } else { success ("*** Previous session was NOT resumed\n"); } } gnutls_record_send (session, MSG, strlen (MSG)); ret = gnutls_record_recv (session, buffer, MAX_BUF); if (ret == 0) { success ("client: Peer has closed the TLS connection\n"); goto end; } else if (ret < 0) { fail ("client: Error: %s\n", gnutls_strerror (ret)); goto end; } if (debug) { printf ("- Received %d bytes: ", ret); for (ii = 0; ii < ret; ii++) { fputc (buffer[ii], stdout); } fputs ("\n", stdout); } gnutls_bye (session, GNUTLS_SHUT_RDWR); end: tcp_close (sd); gnutls_deinit (session); } gnutls_anon_free_client_credentials (anoncred); }
int ne_sock_connect_ssl(ne_socket *sock, ne_ssl_context *ctx, void *userdata) { int ret; #if defined(HAVE_OPENSSL) SSL *ssl; if (seed_ssl_prng()) { set_error(sock, _("SSL disabled due to lack of entropy")); return NE_SOCK_ERROR; } /* If runtime library version differs from compile-time version * number in major/minor/fix level, abort soon. */ if ((SSLeay() ^ OPENSSL_VERSION_NUMBER) & 0xFFFFF000) { set_error(sock, _("SSL disabled due to library version mismatch")); return NE_SOCK_ERROR; } sock->ssl = ssl = SSL_new(ctx->ctx); if (!ssl) { set_error(sock, _("Could not create SSL structure")); return NE_SOCK_ERROR; } SSL_set_app_data(ssl, userdata); SSL_set_mode(ssl, SSL_MODE_AUTO_RETRY); SSL_set_fd(ssl, sock->fd); sock->ops = &iofns_ssl; if (ctx->sess) SSL_set_session(ssl, ctx->sess); ret = SSL_connect(ssl); if (ret != 1) { error_ossl(sock, ret); SSL_free(ssl); sock->ssl = NULL; return NE_SOCK_ERROR; } #elif defined(HAVE_GNUTLS) /* DH and RSA params are set in ne_ssl_context_create */ gnutls_init(&sock->ssl, GNUTLS_CLIENT); gnutls_set_default_priority(sock->ssl); gnutls_session_set_ptr(sock->ssl, userdata); gnutls_credentials_set(sock->ssl, GNUTLS_CRD_CERTIFICATE, ctx->cred); gnutls_transport_set_ptr(sock->ssl, (gnutls_transport_ptr) sock->fd); if (ctx->cache.client.data) { #if defined(HAVE_GNUTLS_SESSION_GET_DATA2) gnutls_session_set_data(sock->ssl, ctx->cache.client.data, ctx->cache.client.size); #else gnutls_session_set_data(sock->ssl, ctx->cache.client.data, ctx->cache.client.len); #endif } sock->ops = &iofns_ssl; ret = gnutls_handshake(sock->ssl); if (ret < 0) { error_gnutls(sock, ret); return NE_SOCK_ERROR; } if (!gnutls_session_is_resumed(sock->ssl)) { /* New session. The old method of using the _get_data * function seems to be broken with 1.3.0 and later*/ #if defined(HAVE_GNUTLS_SESSION_GET_DATA2) gnutls_session_get_data2(sock->ssl, &ctx->cache.client); #else ctx->cache.client.len = 0; if (gnutls_session_get_data(sock->ssl, NULL, &ctx->cache.client.len) == 0) { ctx->cache.client.data = ne_malloc(ctx->cache.client.len); gnutls_session_get_data(sock->ssl, ctx->cache.client.data, &ctx->cache.client.len); } #endif } #endif return 0; }
void doit(void) { int exit_code = EXIT_SUCCESS; int ret; /* 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; gnutls_datum_t data; char buf[128]; /* General init. */ global_init(); gnutls_global_set_log_function(tls_log_func); if (debug) gnutls_global_set_log_level(6); gnutls_global_set_time_function(mytime); /* 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_set_default_priority(server); gnutls_transport_set_push_function(server, server_push); gnutls_transport_set_pull_function(server, server_pull); gnutls_transport_set_ptr(server, server); /* Init client */ ret = gnutls_certificate_allocate_credentials(&clientx509cred); if (ret < 0) exit(1); ret = gnutls_certificate_set_x509_trust_mem(clientx509cred, &ca_cert, GNUTLS_X509_FMT_PEM); if (ret < 0) exit(1); ret = gnutls_init(&client, GNUTLS_CLIENT|GNUTLS_ENABLE_FALSE_START); if (ret < 0) exit(1); ret = gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, clientx509cred); if (ret < 0) exit(1); gnutls_set_default_priority(client); gnutls_transport_set_push_function(client, client_push); gnutls_transport_set_pull_function(client, client_pull); gnutls_transport_set_ptr(client, client); memset(buf, 0, sizeof(buf)); ret = gnutls_session_set_data(client, buf, sizeof(buf)); if (ret != GNUTLS_E_DB_ERROR) { fail("unexpected error: %s\n", gnutls_strerror(ret)); } HANDSHAKE(client, server); /* try obtaining the resumption data. This should fail because * the handshake is not yet complete (due to false start) */ ret = gnutls_session_get_data2(client, &data); if (ret != GNUTLS_E_UNAVAILABLE_DURING_HANDSHAKE) { fail("unexpected error: %s\n", gnutls_strerror(ret)); } ret = gnutls_record_recv(client, buf, sizeof(buf)); if (ret < 0 && ret != GNUTLS_E_AGAIN) { fail("unexpected error: %s\n", gnutls_strerror(ret)); } ret = gnutls_session_get_data2(client, &data); if (ret != 0) { fail("unexpected error: %s\n", gnutls_strerror(ret)); } gnutls_free(data.data); 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 > 0) { if (exit_code == 0) puts("Self-test successful"); else puts("Self-test failed"); } }
void session::get_data (gnutls_session_t session, gnutls_datum_t & data) const { RETWRAP (gnutls_session_get_data2 (s, &data)); }