X-Git-Url: https://vcs.fsf.org/?p=exim.git;a=blobdiff_plain;f=src%2Fsrc%2Ftls-gnu.c;h=cf899454f69b512f1ccfe142dec71b5b5d715651;hp=2e1b9e4d36a207937eb6fe2ec859d0effedbe14f;hb=0b049796b89a59fc322119b54199d92c404ef687;hpb=50a3f20592c79da4acd409b59803dd5ff31b9781 diff --git a/src/src/tls-gnu.c b/src/src/tls-gnu.c index 2e1b9e4d3..cf899454f 100644 --- a/src/src/tls-gnu.c +++ b/src/src/tls-gnu.c @@ -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) @@ -3148,10 +3157,7 @@ DEBUG(D_tls) debug_printf("Calling gnutls_record_recv(session=%p, buffer=%p, buf 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); @@ -3308,9 +3314,7 @@ DEBUG(D_tls) 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__, @@ -3366,11 +3375,10 @@ while (left > 0) 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