int SSL_pending (SSL * ssl) { if (ssl->ssl_peek_avail) return ssl->ssl_peek_avail; return gnutls_record_check_pending (ssl->gnutls_state); }
static gint ssl_read(gnutls_session_t ssl, gchar *buf, gint len) { gint r; if (gnutls_record_check_pending(ssl) == 0) { if (fd_check_io(GPOINTER_TO_INT(gnutls_transport_get_ptr(ssl)), G_IO_IN) < 0) return -1; } while (1) { r = gnutls_record_recv(ssl, buf, len); if (r > 0) return r; switch (r) { case 0: /* closed connection */ return -1; case GNUTLS_E_REHANDSHAKE: do { r = gnutls_handshake(ssl); } while (r == GNUTLS_E_AGAIN || r == GNUTLS_E_INTERRUPTED); break; /* re-receive */ case GNUTLS_E_AGAIN: case GNUTLS_E_INTERRUPTED: errno = EAGAIN; return -1; default: return -1; } } }
static int wgnutls_poll (int fd, double timeout, int wait_for, void *arg) { struct wgnutls_transport_context *ctx = arg; return ctx->peeklen || gnutls_record_check_pending (ctx->session) || select_fd (fd, timeout, wait_for); }
/** * This function was created to handle per-connection processing that * has to happen even if the socket cannot be read or written to. All * implementations (multithreaded, external select, internal select) * call this function. * * @param connection being handled * @return MHD_YES if we should continue to process the * connection (not dead yet), MHD_NO if it died */ static int MHD_tls_connection_handle_idle (struct MHD_Connection *connection) { unsigned int timeout; #if DEBUG_STATES MHD_DLOG (connection->daemon, "%s: state: %s\n", __FUNCTION__, MHD_state_to_string (connection->state)); #endif timeout = connection->connection_timeout; if ( (timeout != 0) && (time (NULL) - timeout > connection->last_activity)) MHD_connection_close (connection, MHD_REQUEST_TERMINATED_TIMEOUT_REACHED); switch (connection->state) { /* on newly created connections we might reach here before any reply has been received */ case MHD_TLS_CONNECTION_INIT: return MHD_YES; /* close connection if necessary */ case MHD_CONNECTION_CLOSED: gnutls_bye (connection->tls_session, GNUTLS_SHUT_RDWR); return MHD_connection_handle_idle (connection); default: if ( (0 != gnutls_record_check_pending (connection->tls_session)) && (MHD_YES != MHD_tls_connection_handle_read (connection)) ) return MHD_YES; return MHD_connection_handle_idle (connection); } return MHD_YES; }
static int readable_gnutls(ne_socket *sock, int secs) { if (gnutls_record_check_pending(sock->ssl)) { return 0; } return readable_raw(sock, secs); }
static gboolean ssl_sock_check(GSource *source) { SockInfo *sock = ((SockSource *)source)->sock; struct timeval timeout = {0, 0}; fd_set fds; GIOCondition condition = 0; if (!sock || !sock->sock) return FALSE; condition = sock->condition; if ((condition & G_IO_IN) == G_IO_IN && gnutls_record_check_pending(sock->ssl) != 0) return TRUE; FD_ZERO(&fds); FD_SET(sock->sock, &fds); select(sock->sock + 1, (condition & G_IO_IN) ? &fds : NULL, (condition & G_IO_OUT) ? &fds : NULL, NULL, &timeout); return FD_ISSET(sock->sock, &fds) != 0; }
int rfbssl_pending(rfbClientPtr cl) { struct rfbssl_ctx *ctx = (struct rfbssl_ctx *)cl->sslctx; int ret = ctx->peeklen; if (ret <= 0) ret = gnutls_record_check_pending(ctx->session); return ret; }
static int wait_read(mailstream_low * s) { fd_set fds_read; struct timeval timeout; int fd; struct mailstream_ssl_data * ssl_data; int max_fd; int r; int cancelled; int got_data; #ifdef WIN32 HANDLE event; #endif ssl_data = (struct mailstream_ssl_data *) s->data; timeout = mailstream_network_delay; #ifdef USE_GNUTLS if (gnutls_record_check_pending(ssl_data->session) != 0) return 0; #endif FD_ZERO(&fds_read); fd = mailstream_cancel_get_fd(ssl_data->cancel); FD_SET(fd, &fds_read); #ifdef WIN32 event = CreateEvent(NULL, TRUE, FALSE, NULL); WSAEventSelect(ssl_data->fd, event, FD_READ | FD_CLOSE); FD_SET(event, &fds_read); r = WaitForMultipleObjects(fds_read.fd_count, fds_read.fd_array, FALSE, timeout.tv_sec * 1000 + timeout.tv_usec / 1000); if (WAIT_TIMEOUT == r) return -1; cancelled = (fds_read.fd_array[r - WAIT_OBJECT_0] == fd); got_data = (fds_read.fd_array[r - WAIT_OBJECT_0] == event); #else FD_SET(ssl_data->fd, &fds_read); max_fd = ssl_data->fd; if (fd > max_fd) max_fd = fd; r = select(max_fd + 1, &fds_read, NULL, NULL, &timeout); if (r <= 0) return -1; cancelled = (FD_ISSET(fd, &fds_read)); got_data = FD_ISSET(ssl_data->fd, &fds_read); #endif if (cancelled) { /* cancelled */ mailstream_cancel_ack(ssl_data->cancel); return -1; } return 0; }
ssize_t TCPStream::dataAvailable() { if(secure) { return gnutls_record_check_pending(*m_session); } else { int nbrBytes = 0; ioctl(m_sd,FIONREAD,&nbrBytes); return nbrBytes; } }
/* returns IN_KEYBOARD for keyboard input and IN_NET for network input */ static int check_net_or_keyboard_input(socket_st* hd) { int maxfd; fd_set rset; int err; struct timeval tv; do { FD_ZERO (&rset); FD_SET (hd->fd, &rset); #ifndef _WIN32 FD_SET (fileno (stdin), &rset); maxfd = MAX (fileno (stdin), hd->fd); #else maxfd = hd->fd; #endif tv.tv_sec = 0; tv.tv_usec = 50 * 1000; if (hd->secure == 1) if (gnutls_record_check_pending(hd->session)) return IN_NET; err = select (maxfd + 1, &rset, NULL, NULL, &tv); if (err < 0) continue; if (FD_ISSET (hd->fd, &rset)) return IN_NET; #ifdef _WIN32 { int state; state = WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 200); if (state == WAIT_OBJECT_0) return IN_KEYBOARD; } #else if (FD_ISSET (fileno (stdin), &rset)) return IN_KEYBOARD; #endif } while(err == 0); return IN_NONE; }
static inline void tls_signal_pending(struct gnutella_socket *s) { size_t n = gnutls_record_check_pending(tls_socket_get_session(s)); if (n > 0) { int saved_errno = errno; if (GNET_PROPERTY(tls_debug) > 1) { g_debug("%s: pending=%zu", G_STRFUNC, n); } inputevt_set_readable(s->file_desc); errno = saved_errno; } }
int ssl_pending( void *conn ) { if( conn == NULL ) return 0; if( !((struct scd*)conn)->established ) { ssl_errno = SSL_NOHANDSHAKE; return 0; } #if GNUTLS_VERSION_NUMBER >= 0x03000d && GNUTLS_VERSION_NUMBER <= 0x030012 if( ssl_errno == SSL_AGAIN ) return 0; #endif return gnutls_record_check_pending( ((struct scd*)conn)->session ) != 0; }
static int tlsg_sb_ctrl( Sockbuf_IO_Desc *sbiod, int opt, void *arg ) { struct tls_data *p; assert( sbiod != NULL ); assert( sbiod->sbiod_pvt != NULL ); p = (struct tls_data *)sbiod->sbiod_pvt; if ( opt == LBER_SB_OPT_GET_SSL ) { *((tlsg_session **)arg) = p->session; return 1; } else if ( opt == LBER_SB_OPT_DATA_READY ) { if( gnutls_record_check_pending( p->session->session ) > 0 ) { return 1; } } return LBER_SBIOD_CTRL_NEXT( sbiod, opt, arg ); }
static int wgnutls_peek (int fd, char *buf, int bufsize, void *arg) { int read = 0; struct wgnutls_transport_context *ctx = arg; int offset = MIN (bufsize, ctx->peeklen); if (bufsize > sizeof ctx->peekbuf) bufsize = sizeof ctx->peekbuf; if (ctx->peeklen) memcpy (buf, ctx->peekbuf, offset); if (bufsize > offset) { if (gnutls_record_check_pending (ctx->session) <= 0 && select_fd (fd, 0.0, WAIT_FOR_READ) <= 0) read = 0; else read = gnutls_record_recv (ctx->session, buf + offset, bufsize - offset); if (read < 0) { if (offset) read = 0; else return read; } if (read > 0) { memcpy (ctx->peekbuf + offset, buf + offset, read); ctx->peeklen += read; } } return offset + read; }
/* returns IN_KEYBOARD for keyboard input and IN_NET for network input */ static int check_net_or_keyboard_input(socket_st* hd) { int maxfd; fd_set rset; int err; struct timeval tv; do { FD_ZERO (&rset); FD_SET (fileno (stdin), &rset); FD_SET (hd->fd, &rset); maxfd = MAX (fileno (stdin), hd->fd); tv.tv_sec = 0; tv.tv_usec = 500 * 1000; if (hd->secure == 1) if (gnutls_record_check_pending(hd->session)) return IN_NET; err = select (maxfd + 1, &rset, NULL, NULL, &tv); if (err < 0) continue; if (FD_ISSET (hd->fd, &rset)) return IN_NET; if (FD_ISSET (fileno (stdin), &rset)) return IN_KEYBOARD; } while(err == 0); return IN_NONE; }
/** * This function was created to handle per-connection processing that * has to happen even if the socket cannot be read or written to. All * implementations (multithreaded, external select, internal select) * call this function. * * @param connection being handled * @return #MHD_YES if we should continue to process the * connection (not dead yet), #MHD_NO if it died */ static int MHD_tls_connection_handle_idle (struct MHD_Connection *connection) { unsigned int timeout; #if DEBUG_STATES MHD_DLOG (connection->daemon, _("In function %s handling connection at state: %s\n"), __FUNCTION__, MHD_state_to_string (connection->state)); #endif timeout = connection->connection_timeout; if ( (timeout != 0) && (timeout <= (MHD_monotonic_sec_counter() - connection->last_activity))) MHD_connection_close_ (connection, MHD_REQUEST_TERMINATED_TIMEOUT_REACHED); switch (connection->state) { /* on newly created connections we might reach here before any reply has been received */ case MHD_TLS_CONNECTION_INIT: break; /* close connection if necessary */ case MHD_CONNECTION_CLOSED: return MHD_connection_handle_idle (connection); default: if ( (0 != gnutls_record_check_pending (connection->tls_session)) && (MHD_YES != MHD_tls_connection_handle_read (connection)) ) return MHD_YES; return MHD_connection_handle_idle (connection); } #ifdef EPOLL_SUPPORT return MHD_connection_epoll_update_ (connection); #else return MHD_YES; #endif }
static int wait_read(mailstream_low * s) { struct timeval timeout; int cancellation_fd; struct mailstream_ssl_data * ssl_data; int r; int cancelled; #if defined(WIN32) fd_set fds_read; HANDLE event; #elif USE_POLL struct pollfd pfd[2]; #else fd_set fds_read; int max_fd; #endif ssl_data = (struct mailstream_ssl_data *) s->data; if (s->timeout == 0) { timeout = mailstream_network_delay; } else { timeout.tv_sec = s->timeout; timeout.tv_usec = 0; } #ifdef USE_GNUTLS if (gnutls_record_check_pending(ssl_data->session) != 0) return 0; #endif cancellation_fd = mailstream_cancel_get_fd(ssl_data->cancel); #if defined(WIN32) FD_ZERO(&fds_read); FD_SET(cancellation_fd, &fds_read); event = CreateEvent(NULL, TRUE, FALSE, NULL); WSAEventSelect(ssl_data->fd, event, FD_READ | FD_CLOSE); FD_SET(event, &fds_read); r = WaitForMultipleObjects(fds_read.fd_count, fds_read.fd_array, FALSE, timeout.tv_sec * 1000 + timeout.tv_usec / 1000); if (WAIT_TIMEOUT == r) { WSAEventSelect(ssl_data->fd, event, 0); CloseHandle(event); return -1; } cancelled = (fds_read.fd_array[r - WAIT_OBJECT_0] == cancellation_fd); WSAEventSelect(ssl_data->fd, event, 0); CloseHandle(event); #elif USE_POLL pfd[0].fd = ssl_data->fd; pfd[0].events = POLLIN; pfd[0].revents = 0; pfd[1].fd = cancellation_fd; pfd[1].events = POLLIN; pfd[1].revents = 0; r = poll(&pfd[0], 2, timeout.tv_sec * 1000 + timeout.tv_usec / 1000); if (r <= 0) return -1; cancelled = pfd[1].revents & POLLIN; #else FD_ZERO(&fds_read); FD_SET(cancellation_fd, &fds_read); FD_SET(ssl_data->fd, &fds_read); max_fd = cancellation_fd > ssl_data->fd ? cancellation_fd : ssl_data->fd; r = select(max_fd + 1, &fds_read, NULL, NULL, &timeout); if (r <= 0) return -1; cancelled = FD_ISSET(cancellation_fd, &fds_read); #endif if (cancelled) { /* cancelled */ mailstream_cancel_ack(ssl_data->cancel); return -1; } return 0; }
size_t session::check_pending () const { return gnutls_record_check_pending (s); }
bool SocketRWCommon::hasTlsPendingData() const { if (tlsActive) return (gnutls_record_check_pending(tls) > 0); else return false; }
static gint xfce_mailwatch_net_conn_recv_internal(XfceMailwatchNetConn *net_conn, guchar *buf, gsize buf_len, gboolean block, GError **error) { gint ret, bin = 0, code = XFCE_MAILWATCH_ERROR_FAILED; const gchar *reason; TIMER_INIT; TIMER_START; do { fd_set rfd; struct timeval tv = { 1, 0 }; FD_ZERO(&rfd); FD_SET(net_conn->fd, &rfd); if(!block) tv.tv_sec = 0; #ifdef HAVE_SSL_SUPPORT /* Read data from the gnutls read buffer, first. */ if (net_conn->is_secure && (ret = gnutls_record_check_pending(net_conn->gt_session)) > 0) { break; } #endif ret = select(FD_SETSIZE, &rfd, NULL, NULL, &tv); if(ret > 0 && FD_ISSET(net_conn->fd, &rfd)) break; else if(ret < 0 && errno != EINTR) { g_set_error(error, XFCE_MAILWATCH_ERROR, XFCE_MAILWATCH_ERROR_FAILED, "%s", strerror(errno)); return -1; } else if(!block) return 0; } while((ret == 0 || (ret < 0 && errno == EINTR)) && !TIMER_EXPIRED(RECV_TIMEOUT) && SHOULD_CONTINUE(net_conn)); if(ret < 0 && errno != EINTR) { if(error) { g_set_error(error, XFCE_MAILWATCH_ERROR, XFCE_MAILWATCH_ERROR_FAILED, "%s", strerror(errno)); } return -1; } else if(!SHOULD_CONTINUE(net_conn)) { if(error) { g_set_error(error, XFCE_MAILWATCH_ERROR, XFCE_MAILWATCH_ERROR_ABORTED, "%s", _("Operation aborted")); } return -1; } else if(TIMER_EXPIRED(RECV_TIMEOUT)) { if(error) { g_set_error(error, XFCE_MAILWATCH_ERROR, XFCE_MAILWATCH_ERROR_FAILED, "%s", strerror(ETIMEDOUT)); } return -1; } #ifdef HAVE_SSL_SUPPORT if(net_conn->is_secure) { gint gret; code = XFCE_MAILWATCH_ERROR_FAILED; TIMER_START; do { gret = gnutls_record_recv(net_conn->gt_session, buf, buf_len); if(gret == GNUTLS_E_REHANDSHAKE) { if(!xfce_mailwatch_net_conn_tls_handshake(net_conn, error)) return -1; gret = GNUTLS_E_AGAIN; } } while((gret == GNUTLS_E_INTERRUPTED || gret == GNUTLS_E_AGAIN) && !TIMER_EXPIRED(RECV_TIMEOUT) && SHOULD_CONTINUE(net_conn)); if(gret < 0) { if(error) { if(!SHOULD_CONTINUE(net_conn)) { code = XFCE_MAILWATCH_ERROR_ABORTED; reason = _("Operation aborted"); } else if(TIMER_EXPIRED(RECV_TIMEOUT)) reason = strerror(ETIMEDOUT); else reason = gnutls_strerror(gret); g_set_error(error, XFCE_MAILWATCH_ERROR, code, _("Failed to receive encrypted data: %s"), reason); } bin = -1; } else bin = gret; } else #endif { gint pret; code = XFCE_MAILWATCH_ERROR_FAILED; TIMER_START; do { pret = recv(net_conn->fd, buf, buf_len, MSG_NOSIGNAL); } while(pret < 0 && (errno == EINTR || errno == EAGAIN) && !TIMER_EXPIRED(RECV_TIMEOUT) && SHOULD_CONTINUE(net_conn)); if(pret < 0) { if(error) { if(!SHOULD_CONTINUE(net_conn)) { code = XFCE_MAILWATCH_ERROR_ABORTED; reason = _("Operation aborted"); } else if(TIMER_EXPIRED(RECV_TIMEOUT)) reason = strerror(ETIMEDOUT); else reason = strerror(errno); g_set_error(error, XFCE_MAILWATCH_ERROR, code, _("Failed to receive data: %s"), reason); } bin = -1; } else bin = pret; } return bin; }
int SSL_pending (SSL * ssl) { return gnutls_record_check_pending (ssl->gnutls_state); }
int tls_pending(tls_t *tls) { return gnutls_record_check_pending (tls->session); }
/** Handles one client. * This one connects to the remote server, and proxies every traffic * between our client and the server. * * @param config is the main CryWrap configuration structure. * @param insock is the socket through which the client sends input. * @param outsock is the socket through which we send output. * * @note Exits on error. */ static int _crywrap_do_one(const crywrap_config_t * config, int insock, int outsock) { int sock, ret, tls_pending; gnutls_session_t session; char buffer[_CRYWRAP_MAXBUF + 2]; fd_set fdset; unsigned int status = 0; struct sockaddr_storage faddr; socklen_t socklen = sizeof(struct sockaddr_storage); char peer_name[NI_MAXHOST]; /* Log the connection */ if (getpeername(insock, (struct sockaddr *) &faddr, &socklen) != 0) cry_error("getpeername(): %s", strerror(errno)); else { getnameinfo((struct sockaddr *) &faddr, sizeof(struct sockaddr_storage), peer_name, sizeof(peer_name), NULL, 0, NI_NUMERICHOST); cry_log("Accepted connection from %s on %d to %s/%d", peer_name, insock, config->dest.host, config->dest.port); } /* Do the handshake with our peer */ session = _crywrap_tls_session_create(config); gnutls_transport_set_ptr2(session, (gnutls_transport_ptr_t) insock, (gnutls_transport_ptr_t) outsock); do { ret = gnutls_handshake(session); } while (ret == GNUTLS_E_AGAIN || ret == GNUTLS_E_INTERRUPTED); if (ret < 0) { cry_error("Handshake failed: %s", gnutls_strerror(ret)); gnutls_alert_send_appropriate(session, ret); goto error; } /* Verify the client's certificate, if any. */ if (config->verify) { ret = gnutls_certificate_verify_peers2(session, &status); if (ret < 0) cry_log ("Error getting certificate from client: %s", gnutls_strerror(ret)); if (ret == 0 && status != 0) { if (status & GNUTLS_CERT_INVALID) cry_log("%s", "Client certificate not trusted or invalid"); } if (config->verify > 0 && status != 0) { ret = -1; gnutls_alert_send(session, GNUTLS_AL_FATAL, GNUTLS_A_INSUFFICIENT_SECURITY); goto error; } } /* Connect to the remote host */ sock = _crywrap_remote_connect(config->dest.addr, htons(config->dest.port)); for (;;) { FD_ZERO(&fdset); FD_SET(insock, &fdset); FD_SET(sock, &fdset); memset(buffer, 0, _CRYWRAP_MAXBUF + 1); tls_pending = 0; if (gnutls_record_check_pending(session) > 0) tls_pending = 1; else { select(sock + 1, &fdset, NULL, NULL, NULL); if (FD_ISSET(insock, &fdset)) tls_pending = 1; } /* TLS client */ if (tls_pending != 0) { ret = gnutls_record_recv(session, buffer, _CRYWRAP_MAXBUF); if (ret == 0) { cry_log("%s", "Peer has closed the GNUTLS connection"); break; } else if (ret < 0) { cry_log("Received corrupted data: %s.", gnutls_strerror(ret)); break; } else send(sock, buffer, ret, 0); } /* Remote server */ if (FD_ISSET(sock, &fdset)) { ret = recv(sock, buffer, _CRYWRAP_MAXBUF, 0); if (ret == 0) { cry_log("%s", "Server has closed the connection"); break; } else if (ret < 0) { cry_log("Received corrupted data: %s.", strerror(errno)); break; } else { int r, o = 0; do { r = gnutls_record_send(session, &buffer[o], ret - o); o += r; } while (r > 0 && ret > o); if (r < 0) cry_log ("Received corrupt data: %s", gnutls_strerror(r)); } } } error: gnutls_bye(session, GNUTLS_SHUT_WR); gnutls_deinit(session); close(insock); close(outsock); return (ret == 0) ? 0 : 1; }
/* * Return zero if session tickets haven't been enabled. */ int _gnutls_recv_new_session_ticket(gnutls_session_t session) { uint8_t *p; int data_size; gnutls_buffer_st buf; uint16_t ticket_len; int ret; session_ticket_ext_st *priv = NULL; gnutls_ext_priv_data_t epriv; if (session->internals.flags & GNUTLS_NO_TICKETS) return 0; if (!session->internals.session_ticket_renew) return 0; /* This is the last flight and peer cannot be sure * we have received it unless we notify him. So we * wait for a message and retransmit if needed. */ if (IS_DTLS(session) && !_dtls_is_async(session)) { unsigned have; mbuffer_st *bufel = NULL; have = gnutls_record_check_pending(session) + record_check_unprocessed(session); if (have != 0) { bufel = _mbuffer_head_get_first(&session->internals.record_buffer, NULL); } if (have == 0 || (bufel && bufel->type != GNUTLS_HANDSHAKE)) { ret = _dtls_wait_and_retransmit(session); if (ret < 0) return gnutls_assert_val(ret); } } ret = _gnutls_recv_handshake(session, GNUTLS_HANDSHAKE_NEW_SESSION_TICKET, 0, &buf); if (ret < 0) return gnutls_assert_val_fatal(ret); p = buf.data; data_size = buf.length; DECR_LENGTH_COM(data_size, 4, ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH; goto error); /* skip over lifetime hint */ p += 4; DECR_LENGTH_COM(data_size, 2, ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH; goto error); ticket_len = _gnutls_read_uint16(p); p += 2; DECR_LENGTH_COM(data_size, ticket_len, ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH; goto error); priv = gnutls_calloc(1, sizeof(*priv)); if (!priv) { gnutls_assert(); ret = GNUTLS_E_MEMORY_ERROR; goto error; } priv->session_ticket = gnutls_realloc_fast(priv->session_ticket, ticket_len); if (!priv->session_ticket) { gnutls_free(priv); gnutls_assert(); ret = GNUTLS_E_MEMORY_ERROR; goto error; } memcpy(priv->session_ticket, p, ticket_len); priv->session_ticket_len = ticket_len; epriv = priv; /* Discard the current session ID. (RFC5077 3.4) */ ret = _gnutls_generate_session_id(session->security_parameters. session_id, &session->security_parameters. session_id_size); if (ret < 0) { gnutls_assert(); session_ticket_deinit_data(epriv); ret = GNUTLS_E_INTERNAL_ERROR; goto error; } ret = 0; _gnutls_handshake_log ("HSK[%p]: received session ticket\n", session); session->internals.hsk_flags |= HSK_TICKET_RECEIVED; _gnutls_hello_ext_set_priv(session, GNUTLS_EXTENSION_SESSION_TICKET, epriv); error: _gnutls_buffer_clear(&buf); return ret; }
size_t /* O - Bytes available */ _httpTLSPending(http_t *http) /* I - HTTP connection */ { return (gnutls_record_check_pending(http->tls)); }
bool_t SSLi_data_pending(SSL_handle_t *session) { return gnutls_record_check_pending(*session); }
int _gnutls_recv_new_session_ticket(gnutls_session_t session) { uint8_t *p; int data_size; gnutls_buffer_st buf; uint16_t ticket_len; int ret; session_ticket_ext_st *priv = NULL; extension_priv_data_t epriv; ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SESSION_TICKET, &epriv); if (ret < 0) { gnutls_assert(); return 0; } priv = epriv; if (!priv->session_ticket_renew) return 0; /* This is the last flight and peer cannot be sure * we have received it unless we notify him. So we * wait for a message and retransmit if needed. */ if (IS_DTLS(session) && !_dtls_is_async(session) && (gnutls_record_check_pending(session) + record_check_unprocessed(session)) == 0) { ret = _dtls_wait_and_retransmit(session); if (ret < 0) return gnutls_assert_val(ret); } ret = _gnutls_recv_handshake(session, GNUTLS_HANDSHAKE_NEW_SESSION_TICKET, 0, &buf); if (ret < 0) return gnutls_assert_val_fatal(ret); p = buf.data; data_size = buf.length; DECR_LENGTH_COM(data_size, 4, ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH; goto error); /* skip over lifetime hint */ p += 4; DECR_LENGTH_COM(data_size, 2, ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH; goto error); ticket_len = _gnutls_read_uint16(p); p += 2; DECR_LENGTH_COM(data_size, ticket_len, ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH; goto error); priv->session_ticket = gnutls_realloc_fast(priv->session_ticket, ticket_len); if (!priv->session_ticket) { gnutls_assert(); ret = GNUTLS_E_MEMORY_ERROR; goto error; } memcpy(priv->session_ticket, p, ticket_len); priv->session_ticket_len = ticket_len; /* Discard the current session ID. (RFC5077 3.4) */ ret = _gnutls_generate_session_id(session->security_parameters. session_id, &session->security_parameters. session_id_size); if (ret < 0) { gnutls_assert(); gnutls_free(priv->session_ticket); priv->session_ticket = NULL; ret = GNUTLS_E_INTERNAL_ERROR; goto error; } ret = 0; error: _gnutls_buffer_clear(&buf); return ret; }