ssl-proxy-gnutls.c revision 89a126810703c666309310d0f3189e9834d70b5b
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2002-2007 Dovecot authors, see the included COPYING file */
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch { GNUTLS_KX_DHE_DSS, GNUTLS_KX_RSA, GNUTLS_KX_DHE_RSA, 0 };
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch { GNUTLS_CIPHER_RIJNDAEL_CBC, GNUTLS_CIPHER_3DES_CBC,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch GNUTLS_CIPHER_ARCFOUR_128, GNUTLS_CIPHER_ARCFOUR_40, 0 };
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch { GNUTLS_COMP_LZO, GNUTLS_COMP_ZLIB, GNUTLS_COMP_NULL, 0 };
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic gnutls_certificate_credentials x509_cred;
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic void ssl_input(struct ssl_proxy *proxy);
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic void plain_input(struct ssl_proxy *proxy);
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic bool ssl_proxy_destroy(struct ssl_proxy *proxy);
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic const char *get_alert_text(struct ssl_proxy *proxy)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch return gnutls_alert_get_name(gnutls_alert_get(proxy->session));
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic int handle_ssl_error(struct ssl_proxy *proxy, int error)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (error == GNUTLS_E_WARNING_ALERT_RECEIVED) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch i_warning("Received SSL warning alert: %s [%s]",
56d1345c43bbd28c36b7faa85e4163bd9e874290Timo Sirainen /* fatal error occurred */
9d0aee99a8c80d71137aa9b8c216cc203bec7a9aTimo Sirainen i_warning("Received SSL fatal alert: %s [%s]",
35e962a9186b4e9b2001628c1d7b55c24b33ce84Timo Sirainen i_warning("Error reading from SSL client: %s [%s]",
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch gnutls_alert_send_appropriate(proxy->session, error);
a8c4e79ff50fac21b05a7368b052583d410ca15cTimo Sirainenstatic int proxy_recv_ssl(struct ssl_proxy *proxy, void *data, size_t size)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch rcvd = gnutls_record_recv(proxy->session, data, size);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (rcvd == 0 || rcvd == GNUTLS_E_UNEXPECTED_PACKET_LENGTH) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch /* disconnected, either by nicely telling us that we'll
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch close the connection, or by simply killing the
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch connection which gives us the packet length error. */
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic int proxy_send_ssl(struct ssl_proxy *proxy,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch sent = gnutls_record_send(proxy->session, data, size);
aacf2a69acc59e9382578d6f4e030788abc79706Timo Sirainen if (sent == GNUTLS_E_PUSH_ERROR || sent == GNUTLS_E_INVALID_SESSION) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch /* don't warn about errors related to unexpected
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch disconnection */
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic int ssl_proxy_destroy(struct ssl_proxy *proxy)
fc94140acba51adafedafbc8491a3223a51db7a8Stephan Boschstatic void ssl_output(struct ssl_proxy *proxy)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch proxy->outbuf_plain + proxy->outbuf_pos_plain,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch /* disconnected */
1a9a35a6b307f8d5b25345af55e40a99162b4072Timo Sirainen /* everything is sent, start reading again */
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch proxy->io_ssl = io_add(proxy->fd_ssl, IO_READ, ssl_input, proxy);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch rcvd = proxy_recv_ssl(proxy, proxy->outbuf_plain,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch sent = net_transmit(proxy->fd_plain, proxy->outbuf_plain, (size_t)rcvd);
17cd0e0963f2fb0e66d49703e8cd0bda1b842468Timo Sirainen /* disconnected */
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainen /* everything wasn't sent - don't read anything until we've
ba1c847d0af4afe4787ed470d0c818e948e184e2Timo Sirainen sent it all */
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainen proxy->io_ssl = io_add(proxy->fd_ssl, IO_WRITE, ssl_output, proxy);
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainenstatic void plain_output(struct ssl_proxy *proxy)
35e962a9186b4e9b2001628c1d7b55c24b33ce84Timo Sirainen sent = proxy_send_ssl(proxy, NULL, proxy->send_left_ssl);
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainen /* everything is sent, start reading again */
415e16c3dc185578695b7d88e561a52de6c8b1b1Timo Sirainen proxy->io_plain = io_add(proxy->fd_plain, IO_READ, plain_input, proxy);
if (rcvd < 0) {
if (ret >= 0) {
return session;
if (!ssl_initialized) {
main_ref();
if (ret < 0)
fname);
if (ret < 0)
if (bits == 0)
if (ret < 0) {
gnutls_datum m, e, d, p, q, u;
int ret;
if (ret < 0) {
int fd;
t_push();
t_pop();
void ssl_proxy_init(void)
int ret;
if (ret < 0) {
void ssl_proxy_deinit(void)
if (!ssl_initialized)