diff options
Diffstat (limited to 'libmu_auth/tls.c')
-rw-r--r-- | libmu_auth/tls.c | 89 |
1 files changed, 81 insertions, 8 deletions
diff --git a/libmu_auth/tls.c b/libmu_auth/tls.c index ae2aa1d29..2c6f68e32 100644 --- a/libmu_auth/tls.c +++ b/libmu_auth/tls.c @@ -1,5 +1,5 @@ /* GNU Mailutils -- a suite of utilities for electronic mail - Copyright (C) 2003-2019 Free Software Foundation, Inc. + Copyright (C) 2003-2024 Free Software Foundation, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -92,7 +92,11 @@ _tls_stream_pull (gnutls_transport_ptr_t fd, void *buf, size_t size) ; if (rc) - return -1; + { + mu_debug (MU_DEBCAT_STREAM, MU_DEBUG_ERROR, + ("_tls_stream_pull: %s", mu_stream_strerror (stream, rc))); + return -1; + } return rdbytes; } @@ -105,8 +109,8 @@ _tls_stream_push (gnutls_transport_ptr_t fd, const void *buf, size_t size) rc = mu_stream_write (stream, buf, size, &size); if (rc) { - mu_error ("_tls_stream_push: %s", - mu_stream_strerror (stream, rc)); /* FIXME */ + mu_debug (MU_DEBCAT_STREAM, MU_DEBUG_ERROR, + ("_tls_stream_push: %s", mu_stream_strerror (stream, rc))); return -1; } @@ -253,16 +257,47 @@ _tls_open (mu_stream_t stream) rc = gnutls_handshake (sp->session); if (rc != GNUTLS_E_SUCCESS) { + mu_transport_t t[2]; + mu_debug (MU_DEBCAT_STREAM, MU_DEBUG_ERROR, ("gnutls_handshake: %s", gnutls_strerror (rc))); sp->tls_err = rc; + switch (rc) + { + case GNUTLS_E_PULL_ERROR: + if (mu_stream_ioctl (sp->transport[0], + MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET, + &t) == 0 && + mu_stream_err (t[0])) + rc = mu_stream_last_error (t[0]); + else + rc = MU_ERR_READ; + break; + + case GNUTLS_E_PUSH_ERROR: + if (mu_stream_ioctl (sp->transport[1], + MU_IOCTL_TRANSPORT, MU_IOCTL_OP_GET, + &t) == 0 && + mu_stream_err (t[1])) + rc = mu_stream_last_error (t[1]); + else + rc = MU_ERR_WRITE; + break; + + default: + rc = MU_ERR_TLS; + } + gnutls_deinit (sp->session); sp->session = NULL; sp->state = state_init; } else - /* FIXME: if (ssl_cafile) verify_certificate (s->session); */ - sp->state = state_open; + { + /* FIXME: if (ssl_cafile) verify_certificate (s->session); */ + sp->state = state_open; + rc = 0; + } break; default: @@ -391,7 +426,29 @@ _tls_ioctl (struct _mu_stream *stream, int code, int opcode, void *arg) case MU_IOCTL_TCPSTREAM: return mu_stream_ioctl (sp->transport[0], code, opcode, arg); - + + case MU_IOCTL_TIMEOUT: + { + int rc; + + switch (opcode) + { + case MU_IOCTL_OP_SET: + rc = mu_stream_ioctl (sp->transport[0], code, opcode, arg); + if (rc == 0) + rc = mu_stream_ioctl (sp->transport[1], code, opcode, arg); + break; + + case MU_IOCTL_OP_GET: + rc = mu_stream_ioctl (sp->transport[0], code, opcode, arg); + break; + + default: + return EINVAL; + } + return rc; + } + default: return ENOSYS; } @@ -462,6 +519,20 @@ _tls_error_string (struct _mu_stream *stream, int rc) } static void +_tls_event (struct _mu_stream *str, int code, + unsigned long lval, void *pval) +{ + struct _mu_tls_stream *sp = (struct _mu_tls_stream *)str; + if (code == _MU_STR_EVENT_CLRFLAG && lval == _MU_STR_ERR) + { + if (sp->transport[MU_TRANSPORT_INPUT]) + mu_stream_clearerr (sp->transport[MU_TRANSPORT_INPUT]); + if (sp->transport[MU_TRANSPORT_OUTPUT]) + mu_stream_clearerr (sp->transport[MU_TRANSPORT_OUTPUT]); + } +} + +static void free_conf (struct mu_tls_config *conf) { free (conf->cert_file); @@ -581,7 +652,9 @@ mu_tls_stream_create (mu_stream_t *pstream, sp->stream.ctl = _tls_ioctl; sp->stream.wait = _tls_wait; sp->stream.error_string = _tls_error_string; - + sp->stream.event_cb = _tls_event; + sp->stream.event_mask = _MU_STR_EVMASK (_MU_STR_EVENT_CLRFLAG); + mu_stream_set_buffer (strin, mu_buffer_none, 0); mu_stream_set_buffer (strout, mu_buffer_none, 0); |