[gnutls-help] GNUTLS_E_PULL_ERROR in gnutls_handshake
Alessandro Carminati
alessandro.carminati at gmail.com
Sun Feb 15 19:06:06 CET 2015
Hello,
thank you for answered my help request.
The following is the iksemel function handshake where I issue is spawned.
static int handshake (struct stream_data *data)
{
const int protocol_priority[] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 };
const int kx_priority[] = { GNUTLS_KX_RSA, 0 };
const int cipher_priority[] = { GNUTLS_CIPHER_3DES_CBC,
GNUTLS_CIPHER_ARCFOUR, 0};
const int comp_priority[] = { GNUTLS_COMP_ZLIB, GNUTLS_COMP_NULL, 0
};
const int mac_priority[] = { GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0 };
int ret;
if (gnutls_global_init () != 0) return IKS_NOMEM;
if (gnutls_certificate_allocate_credentials (&data->cred) < 0)
return IKS_NOMEM;
if (gnutls_init (&data->sess, GNUTLS_CLIENT) != 0) {
gnutls_certificate_free_credentials (data->cred);
return
IKS_NOMEM;
}
gnutls_protocol_set_priority (data->sess, protocol_priority);
gnutls_cipher_set_priority(data->sess, cipher_priority);
gnutls_compression_set_priority(data->sess, comp_priority);
gnutls_kx_set_priority(data->sess, kx_priority);
gnutls_mac_set_priority(data->sess, mac_priority);
gnutls_credentials_set (data->sess, GNUTLS_CRD_CERTIFICATE,
data->cred);
gnutls_transport_set_push_function (data->sess, (gnutls_push_func)
tls_push);
gnutls_transport_set_pull_function (data->sess, (gnutls_pull_func)
tls_pull);
gnutls_transport_set_ptr (data->sess, data->prs);
ret = gnutls_handshake (data->sess); //*****************here
gnutls_handshake returns GNUTLS_E_PULL_ERROR
if (ret != 0) {
gnutls_deinit (data->sess);
gnutls_certificate_free_credentials (data->cred);
return IKS_NET_TLSFAIL;
}
data->flags &= (~SF_TRY_SECURE);
data->flags |= SF_SECURE;
iks_send_header (data->prs, data->server);
return IKS_OK;
}
The followings are the gnutls functions involved in this issue:
static ssize_t _gnutls_stream_read(gnutls_session_t session,
mbuffer_st ** bufel,
size_t size,
gnutls_pull_func pull_func,
unsigned int *ms)
{
size_t left;
ssize_t i = 0;
size_t max_size = max_record_recv_size(session);
uint8_t *ptr;
gnutls_transport_ptr_t fd = session->internals.transport_recv_ptr;
int ret;
struct timespec t1, t2;
unsigned int diff;
session->internals.direction = 0;
*bufel = _mbuffer_alloc_align16(MAX(max_size, size),
get_total_headers(session));
if (!*bufel) {
gnutls_assert();
return GNUTLS_E_MEMORY_ERROR;
}
ptr = (*bufel)->msg.data;
left = size;
while (left > 0) {
if (ms && *ms > 0) {
ret =
_gnutls_io_check_recv(session, *ms);
if (ret < 0) {
gnutls_assert();
goto cleanup;
}
gettime(&t1);
}
reset_errno(session);
i = pull_func(fd, &ptr[size - left], left);
if (i < 0) {
int err = get_errno(session);
_gnutls_read_log("READ: %d returned
from %p, errno=%d gerrno=%d\n",(int) i, fd,
errno,session->internals.errnum);
if (err == EAGAIN || err == EINTR) {
if (size - left > 0) {
_gnutls_read_log("READ: returning %d bytes from %p\n",(int) (size - left),
fd);
goto finish;
}
ret = errno_to_gerr(err, 0);
goto cleanup;
}
else {
gnutls_assert();
ret = GNUTLS_E_PULL_ERROR2; // I changed this error code just to be sure
the problem was here, before my change it was GNUTLS_E_PULL_ERROR
goto cleanup;
}
}
else {
_gnutls_read_log("READ: Got %d bytes
from %p\n",(int) i, fd);
if (i == 0) break; /* EOF */
}
left -= i;
(*bufel)->msg.size += i;
if (ms && *ms > 0) {
gettime(&t2);
diff = timespec_sub_ms(&t2,
&t1);
if (diff < *ms) gettime(&t2);
diff = timespec_sub_ms(&t2,
&t1);
if (diff < *ms) *ms -= diff;
else {
ret =
gnutls_assert_val(GNUTLS_E_TIMEDOUT);
goto cleanup;
}
}
}
finish:
_gnutls_read_log("READ: read %d bytes from %p\n",(int) (size -
left), fd);
if (size - left == 0) _mbuffer_xfree(bufel);
return (size - left);
cleanup:
_mbuffer_xfree(bufel);
return ret;
}
static ssize_t pull_func(gnutls_transport_ptr_t p, void *data, size_t size)
{
priv_data_st *priv = p;
struct sockaddr_in cli_addr;
socklen_t cli_addr_size;
char buffer[64];
int ret;
cli_addr_size = sizeof(cli_addr);
ret = recvfrom(priv->fd, data, size, 0, (struct sockaddr *)
&cli_addr, &cli_addr_size);
if (ret == -1) return ret;
if (cli_addr_size == priv->cli_addr_size && memcmp(&cli_addr,
priv->cli_addr, sizeof(cli_addr)) == 0) return ret;
printf("Denied connection from %s\n", human_addr((struct sockaddr
*) &cli_addr, sizeof(cli_addr), buffer, sizeof(buffer)));
gnutls_transport_set_errno(priv->session, EAGAIN);
return -1;
}
My problem is I do not have an high level view of what gnutls is going to
do, so I can't figure out what the cause can be. Please help me to
understand.
Alessandro Carminati
-------------- next part --------------
An HTML attachment was scrubbed...
URL: </pipermail/attachments/20150215/5f8eb23a/attachment-0001.html>
More information about the Gnutls-help
mailing list