[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