GnuTLS: remove GNUTLS_E_AGAIN handling
[exim.git] / src / src / tls-gnu.c
index 826a3fdc555ee51bd0736fa8289a5575e13e6bef..cf899454f69b512f1ccfe142dec71b5b5d715651 100644 (file)
@@ -53,6 +53,9 @@ require current GnuTLS, then we'll drop support for the ancient libraries).
 # warning "GnuTLS library version too old; tls:cert event unsupported"
 # define DISABLE_EVENT
 #endif
+#if GNUTLS_VERSION_NUMBER >= 0x030000
+# define SUPPORT_SELFSIGN      /* Uncertain what version is first usable but 2.12.23 is not */
+#endif
 #if GNUTLS_VERSION_NUMBER >= 0x030306
 # define SUPPORT_CA_DIR
 #else
@@ -824,13 +827,19 @@ gnutls_x509_privkey_t pkey = NULL;
 const uschar * where;
 int rc;
 
+#ifndef SUPPORT_SELFSIGN
+where = US"library too old";
+rc = GNUTLS_E_NO_CERTIFICATE_FOUND;
+if (TRUE) goto err;
+#endif
+
 where = US"initialising pkey";
 if ((rc = gnutls_x509_privkey_init(&pkey))) goto err;
 
 where = US"initialising cert";
 if ((rc = gnutls_x509_crt_init(&cert))) goto err;
 
-where = US"generating pkey";
+where = US"generating pkey";   /* Hangs on 2.12.23 */
 if ((rc = gnutls_x509_privkey_generate(pkey, GNUTLS_PK_RSA,
 #ifdef SUPPORT_PARAM_TO_PK_BITS
 # ifndef GNUTLS_SEC_PARAM_MEDIUM
@@ -2504,7 +2513,7 @@ sigalrm_seen = FALSE;
 if (smtp_receive_timeout > 0) ALARM(smtp_receive_timeout);
 do
   rc = gnutls_handshake(state->session);
-while (rc == GNUTLS_E_AGAIN ||  rc == GNUTLS_E_INTERRUPTED && !sigalrm_seen);
+while (rc == GNUTLS_E_INTERRUPTED && !sigalrm_seen);
 ALARM_CLR(0);
 
 if (rc != GNUTLS_E_SUCCESS)
@@ -2984,7 +2993,7 @@ sigalrm_seen = FALSE;
 ALARM(ob->command_timeout);
 do
   rc = gnutls_handshake(state->session);
-while (rc == GNUTLS_E_AGAIN || rc == GNUTLS_E_INTERRUPTED && !sigalrm_seen);
+while (rc == GNUTLS_E_INTERRUPTED && !sigalrm_seen);
 ALARM_CLR(0);
 
 if (rc != GNUTLS_E_SUCCESS)
@@ -3142,16 +3151,13 @@ tls_refill(unsigned lim)
 exim_gnutls_state_st * state = &state_server;
 ssize_t inbytes;
 
-DEBUG(D_tls) debug_printf("Calling gnutls_record_recv(%p, %p, %u)\n",
+DEBUG(D_tls) debug_printf("Calling gnutls_record_recv(session=%p, buffer=%p, buffersize=%u)\n",
   state->session, state->xfer_buffer, ssl_xfer_buffer_size);
 
 sigalrm_seen = FALSE;
 if (smtp_receive_timeout > 0) ALARM(smtp_receive_timeout);
 
-do
-  inbytes = gnutls_record_recv(state->session, state->xfer_buffer,
-    MIN(ssl_xfer_buffer_size, lim));
-while (inbytes == GNUTLS_E_AGAIN);
+inbytes = gnutls_record_recv(state->session, state->xfer_buffer, MIN(ssl_xfer_buffer_size, lim));
 
 if (smtp_receive_timeout > 0) ALARM_CLR(0);
 
@@ -3305,12 +3311,10 @@ if (state->xfer_buffer_lwm < state->xfer_buffer_hwm)
         state->xfer_buffer_hwm - state->xfer_buffer_lwm);
 
 DEBUG(D_tls)
-  debug_printf("Calling gnutls_record_recv(%p, %p, " SIZE_T_FMT ")\n",
+  debug_printf("Calling gnutls_record_recv(session=%p, buffer=%p, len=" SIZE_T_FMT ")\n",
       state->session, buff, len);
 
-do
-  inbytes = gnutls_record_recv(state->session, buff, len);
-while (inbytes == GNUTLS_E_AGAIN);
+inbytes = gnutls_record_recv(state->session, buff, len);
 
 if (inbytes > 0) return inbytes;
 if (inbytes == 0)
@@ -3353,9 +3357,14 @@ tls_write(void * ct_ctx, const uschar * buff, size_t len, BOOL more)
 ssize_t outbytes;
 size_t left = len;
 exim_gnutls_state_st * state = ct_ctx ? ct_ctx : &state_server;
-#ifdef SUPPORT_CORK
 
-if (more && !state->corked) gnutls_record_cork(state->session);
+#ifdef SUPPORT_CORK
+if (more && !state->corked)
+  {
+  DEBUG(D_tls) debug_printf("gnutls_record_cork(session=%p)\n", state->session);
+  gnutls_record_cork(state->session);
+  state->corked = TRUE;
+  }
 #endif
 
 DEBUG(D_tls) debug_printf("%s(%p, " SIZE_T_FMT "%s)\n", __FUNCTION__,
@@ -3363,14 +3372,13 @@ DEBUG(D_tls) debug_printf("%s(%p, " SIZE_T_FMT "%s)\n", __FUNCTION__,
 
 while (left > 0)
   {
-  DEBUG(D_tls) debug_printf("gnutls_record_send(%p, %p, " SIZE_T_FMT ")\n",
+  DEBUG(D_tls) debug_printf("gnutls_record_send(session=%p, buffer=%p, left=" SIZE_T_FMT ")\n",
       state->session, buff, left);
 
-  do
-    outbytes = gnutls_record_send(state->session, buff, left);
-  while (outbytes == GNUTLS_E_AGAIN);
+  outbytes = gnutls_record_send(state->session, buff, left);
 
   DEBUG(D_tls) debug_printf("outbytes=" SSIZE_T_FMT "\n", outbytes);
+
   if (outbytes < 0)
     {
     DEBUG(D_tls) debug_printf("%s: gnutls_record_send err\n", __FUNCTION__);
@@ -3396,10 +3404,18 @@ if (len > INT_MAX)
   }
 
 #ifdef SUPPORT_CORK
-if (more != state->corked)
-  {
-  if (!more) (void) gnutls_record_uncork(state->session, 0);
-  state->corked = more;
+if (!more && state->corked)
+  {
+  DEBUG(D_tls) debug_printf("gnutls_record_uncork(session=%p)\n", state->session);
+  do {
+      outbytes = gnutls_record_uncork(state->session, 0);
+     if (outbytes < 0)
+       {
+       record_io_error(state, len, US"uncork", NULL);
+       return -1;
+       }
+  } while (gnutls_record_check_corked(state->session) > 0);
+  state->corked = FALSE;
   }
 #endif