bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2009-2018 Dovecot authors, see the included COPYING file */
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen#include "lib.h"
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen#include "buffer.h"
0536ccb51d41e3078c3a9fa33e509fb4b2420f95Timo Sirainen#include "ostream-private.h"
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen#include "iostream-openssl.h"
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenstruct ssl_ostream {
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen struct ostream_private ostream;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen struct ssl_iostream *ssl_io;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen buffer_t *buffer;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen};
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainenstatic void
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Siraineno_stream_ssl_close(struct iostream_private *stream, bool close_parent)
52d19b57c2411bb1c60f8248ea5c8c1a1cfc1b4fTimo Sirainen{
52d19b57c2411bb1c60f8248ea5c8c1a1cfc1b4fTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)stream;
52d19b57c2411bb1c60f8248ea5c8c1a1cfc1b4fTimo Sirainen
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen if (close_parent)
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen o_stream_close(sstream->ssl_io->plain_output);
52d19b57c2411bb1c60f8248ea5c8c1a1cfc1b4fTimo Sirainen}
52d19b57c2411bb1c60f8248ea5c8c1a1cfc1b4fTimo Sirainen
52d19b57c2411bb1c60f8248ea5c8c1a1cfc1b4fTimo Sirainenstatic void o_stream_ssl_destroy(struct iostream_private *stream)
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen{
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)stream;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen sstream->ssl_io->ssl_output = NULL;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen ssl_iostream_unref(&sstream->ssl_io);
6307d76096764e66bddc63d4a3e5a1aa19cc528fJosef 'Jeff' Sipek buffer_free(&sstream->buffer);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen}
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenstatic size_t
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Siraineno_stream_ssl_buffer(struct ssl_ostream *sstream, const struct const_iovec *iov,
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen unsigned int iov_count, size_t bytes_sent)
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen{
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen size_t avail, skip_left, size;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen unsigned int i;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen if (sstream->buffer == NULL)
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen sstream->buffer = buffer_create_dynamic(default_pool, 4096);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen skip_left = bytes_sent;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen for (i = 0; i < iov_count; i++) {
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen if (skip_left < iov[i].iov_len)
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen break;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen skip_left -= iov[i].iov_len;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen }
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
1c3e5f6b1afaf119335e3892b0a5ca76a37acebdTimo Sirainen if (sstream->ostream.max_buffer_size == 0) {
19557f192d37cd54a1a090a8a26d9d47265e4413Aki Tuomi /* we're requested to use whatever space is available in
1c3e5f6b1afaf119335e3892b0a5ca76a37acebdTimo Sirainen the buffer */
8b48c53a81bdc67f267ffbcc45ba9860cb49e977Timo Sirainen avail = buffer_get_writable_size(sstream->buffer) - sstream->buffer->used;
1c3e5f6b1afaf119335e3892b0a5ca76a37acebdTimo Sirainen } else {
1c3e5f6b1afaf119335e3892b0a5ca76a37acebdTimo Sirainen avail = sstream->ostream.max_buffer_size > sstream->buffer->used ?
1c3e5f6b1afaf119335e3892b0a5ca76a37acebdTimo Sirainen sstream->ostream.max_buffer_size - sstream->buffer->used : 0;
1c3e5f6b1afaf119335e3892b0a5ca76a37acebdTimo Sirainen }
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen if (i < iov_count && skip_left > 0) {
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen size = I_MIN(iov[i].iov_len - skip_left, avail);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen buffer_append(sstream->buffer,
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen CONST_PTR_OFFSET(iov[i].iov_base, skip_left),
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen size);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen bytes_sent += size;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen avail -= size;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen if (size != iov[i].iov_len)
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen i = iov_count;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen }
ed41ec8aa0efaa50954fd16cb44c86c8350dadccTimo Sirainen if (avail > 0)
ed41ec8aa0efaa50954fd16cb44c86c8350dadccTimo Sirainen o_stream_set_flush_pending(sstream->ssl_io->plain_output, TRUE);
ed41ec8aa0efaa50954fd16cb44c86c8350dadccTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen for (; i < iov_count; i++) {
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen size = I_MIN(iov[i].iov_len, avail);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen buffer_append(sstream->buffer, iov[i].iov_base, size);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen bytes_sent += size;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen avail -= size;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen if (size != iov[i].iov_len)
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen break;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen }
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen sstream->ostream.ostream.offset += bytes_sent;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen return bytes_sent;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen}
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenstatic int o_stream_ssl_flush_buffer(struct ssl_ostream *sstream)
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen{
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen size_t pos = 0;
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen int ret = 1;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen while (pos < sstream->buffer->used) {
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen /* we're writing plaintext data to OpenSSL, which it encrypts
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen and writes to bio_int's buffer. ssl_iostream_bio_sync()
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen reads it from there and adds to plain_output stream. */
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen ret = SSL_write(sstream->ssl_io->ssl,
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen CONST_PTR_OFFSET(sstream->buffer->data, pos),
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen sstream->buffer->used - pos);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen if (ret <= 0) {
8bcf6fd065a71ae0ca6dc76989250e819d08d7f6Aki Tuomi ret = openssl_iostream_handle_error(sstream->ssl_io,
8bcf6fd065a71ae0ca6dc76989250e819d08d7f6Aki Tuomi ret, OPENSSL_IOSTREAM_SYNC_TYPE_WRITE, "SSL_write");
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen if (ret < 0) {
1c6f6f5bef70f16546b3bc8f4cd5f93f373e82a2Timo Sirainen io_stream_set_error(&sstream->ostream.iostream,
1c6f6f5bef70f16546b3bc8f4cd5f93f373e82a2Timo Sirainen "%s", sstream->ssl_io->last_error);
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen sstream->ostream.ostream.stream_errno = errno;
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen break;
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen }
ed41ec8aa0efaa50954fd16cb44c86c8350dadccTimo Sirainen if (ret == 0)
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen break;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen } else {
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen pos += ret;
8bcf6fd065a71ae0ca6dc76989250e819d08d7f6Aki Tuomi (void)openssl_iostream_bio_sync(sstream->ssl_io,
8bcf6fd065a71ae0ca6dc76989250e819d08d7f6Aki Tuomi OPENSSL_IOSTREAM_SYNC_TYPE_WRITE);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen }
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen }
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen buffer_delete(sstream->buffer, 0, pos);
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen return ret <= 0 ? ret : 1;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen}
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenstatic int o_stream_ssl_flush(struct ostream_private *stream)
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen{
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)stream;
16d3a9396730dae3d869dc8159f9c1287fc9f28eStephan Bosch struct ostream *plain_output = sstream->ssl_io->plain_output;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen int ret;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
8bcf6fd065a71ae0ca6dc76989250e819d08d7f6Aki Tuomi if ((ret = openssl_iostream_more(sstream->ssl_io,
8bcf6fd065a71ae0ca6dc76989250e819d08d7f6Aki Tuomi OPENSSL_IOSTREAM_SYNC_TYPE_HANDSHAKE)) < 0) {
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen /* handshake failed */
1c6f6f5bef70f16546b3bc8f4cd5f93f373e82a2Timo Sirainen io_stream_set_error(&stream->iostream, "%s",
1c6f6f5bef70f16546b3bc8f4cd5f93f373e82a2Timo Sirainen sstream->ssl_io->last_error);
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen stream->ostream.stream_errno = errno;
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen } else if (ret > 0 && sstream->buffer != NULL &&
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen sstream->buffer->used > 0) {
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen /* we can try to send some of our buffered data */
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen ret = o_stream_ssl_flush_buffer(sstream);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen }
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen if (ret == 0 && sstream->ssl_io->want_read) {
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen /* we need to read more data until we can continue. */
16d3a9396730dae3d869dc8159f9c1287fc9f28eStephan Bosch o_stream_set_flush_pending(plain_output, FALSE);
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen sstream->ssl_io->ostream_flush_waiting_input = TRUE;
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen ret = 1;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen }
092762029d2fd162283c1df6a40ddc1019605798Stephan Bosch
092762029d2fd162283c1df6a40ddc1019605798Stephan Bosch if (ret <= 0)
092762029d2fd162283c1df6a40ddc1019605798Stephan Bosch return ret;
092762029d2fd162283c1df6a40ddc1019605798Stephan Bosch
092762029d2fd162283c1df6a40ddc1019605798Stephan Bosch /* return 1 only when the output buffer is empty, which is what the
092762029d2fd162283c1df6a40ddc1019605798Stephan Bosch caller expects. */
092762029d2fd162283c1df6a40ddc1019605798Stephan Bosch return o_stream_get_buffer_used_size(plain_output) == 0 ? 1 : 0;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen}
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainenstatic ssize_t
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Siraineno_stream_ssl_sendv(struct ostream_private *stream,
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen const struct const_iovec *iov, unsigned int iov_count)
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen{
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)stream;
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen size_t bytes_sent = 0;
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen bytes_sent = o_stream_ssl_buffer(sstream, iov, iov_count, bytes_sent);
b1faf5924b03c6863d37f828b6dfb67f91dafec8Timo Sirainen if (sstream->ssl_io->handshaked &&
b1faf5924b03c6863d37f828b6dfb67f91dafec8Timo Sirainen sstream->buffer->used == bytes_sent) {
b1faf5924b03c6863d37f828b6dfb67f91dafec8Timo Sirainen /* buffer was empty before calling this. try to write it
b1faf5924b03c6863d37f828b6dfb67f91dafec8Timo Sirainen immediately. */
b1faf5924b03c6863d37f828b6dfb67f91dafec8Timo Sirainen if (o_stream_ssl_flush_buffer(sstream) < 0)
b1faf5924b03c6863d37f828b6dfb67f91dafec8Timo Sirainen return -1;
b1faf5924b03c6863d37f828b6dfb67f91dafec8Timo Sirainen }
b1faf5924b03c6863d37f828b6dfb67f91dafec8Timo Sirainen return bytes_sent;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen}
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
8aa8399893c66b40e2790a4568256807a6ec6742Stephan Boschstatic void o_stream_ssl_switch_ioloop_to(struct ostream_private *stream,
8aa8399893c66b40e2790a4568256807a6ec6742Stephan Bosch struct ioloop *ioloop)
71da447014454c84828d9dface77219875554d7dTimo Sirainen{
71da447014454c84828d9dface77219875554d7dTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)stream;
71da447014454c84828d9dface77219875554d7dTimo Sirainen
8aa8399893c66b40e2790a4568256807a6ec6742Stephan Bosch o_stream_switch_ioloop_to(sstream->ssl_io->plain_output, ioloop);
71da447014454c84828d9dface77219875554d7dTimo Sirainen}
71da447014454c84828d9dface77219875554d7dTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenstatic int plain_flush_callback(struct ssl_ostream *sstream)
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen{
ce8cd19ccf52b19f14d4ea9c8b29bd94c0e48e4dTimo Sirainen struct ostream *ostream = &sstream->ostream.ostream;
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen int ret, ret2;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen /* try to actually flush the pending data */
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen if ((ret = o_stream_flush(sstream->ssl_io->plain_output)) < 0)
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen return -1;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen /* we may be able to copy more data, try it */
ce8cd19ccf52b19f14d4ea9c8b29bd94c0e48e4dTimo Sirainen o_stream_ref(ostream);
ce8cd19ccf52b19f14d4ea9c8b29bd94c0e48e4dTimo Sirainen if (sstream->ostream.callback != NULL)
ce8cd19ccf52b19f14d4ea9c8b29bd94c0e48e4dTimo Sirainen ret2 = sstream->ostream.callback(sstream->ostream.context);
ce8cd19ccf52b19f14d4ea9c8b29bd94c0e48e4dTimo Sirainen else
ce8cd19ccf52b19f14d4ea9c8b29bd94c0e48e4dTimo Sirainen ret2 = o_stream_flush(&sstream->ostream.ostream);
ce8cd19ccf52b19f14d4ea9c8b29bd94c0e48e4dTimo Sirainen if (ret2 == 0)
ce8cd19ccf52b19f14d4ea9c8b29bd94c0e48e4dTimo Sirainen o_stream_set_flush_pending(sstream->ssl_io->plain_output, TRUE);
ce8cd19ccf52b19f14d4ea9c8b29bd94c0e48e4dTimo Sirainen o_stream_unref(&ostream);
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen if (ret2 < 0)
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen return -1;
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen return ret > 0 && ret2 > 0 ? 1 : 0;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen}
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
31df48d66a9a2327f6de41796e6819543c4494e1Timo Sirainenstatic size_t o_stream_ssl_get_used_size(const struct ostream_private *stream)
31df48d66a9a2327f6de41796e6819543c4494e1Timo Sirainen{
31df48d66a9a2327f6de41796e6819543c4494e1Timo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)stream;
31df48d66a9a2327f6de41796e6819543c4494e1Timo Sirainen
31df48d66a9a2327f6de41796e6819543c4494e1Timo Sirainen return o_stream_get_buffer_used_size(sstream->ssl_io->plain_output);
31df48d66a9a2327f6de41796e6819543c4494e1Timo Sirainen}
31df48d66a9a2327f6de41796e6819543c4494e1Timo Sirainen
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Sirainenstatic void
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Siraineno_stream_ssl_flush_pending(struct ostream_private *_stream, bool set)
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Sirainen{
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)_stream;
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Sirainen
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Sirainen o_stream_set_flush_pending(sstream->ssl_io->plain_output, set);
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Sirainen}
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Sirainen
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Sirainenstatic void o_stream_ssl_set_max_buffer_size(struct iostream_private *_stream,
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Sirainen size_t max_size)
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Sirainen{
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)_stream;
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Sirainen
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Sirainen sstream->ostream.max_buffer_size = max_size;
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Sirainen o_stream_set_max_buffer_size(sstream->ssl_io->plain_output, max_size);
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Sirainen}
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Sirainen
3faa1040e5a3f9f35ffad29110216094ab2f5880Timo Sirainenstruct ostream *openssl_o_stream_create_ssl(struct ssl_iostream *ssl_io)
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen{
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen struct ssl_ostream *sstream;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen ssl_io->refcount++;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen sstream = i_new(struct ssl_ostream, 1);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen sstream->ssl_io = ssl_io;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen sstream->ostream.max_buffer_size =
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen ssl_io->plain_output->real_stream->max_buffer_size;
52d19b57c2411bb1c60f8248ea5c8c1a1cfc1b4fTimo Sirainen sstream->ostream.iostream.close = o_stream_ssl_close;
52d19b57c2411bb1c60f8248ea5c8c1a1cfc1b4fTimo Sirainen sstream->ostream.iostream.destroy = o_stream_ssl_destroy;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen sstream->ostream.sendv = o_stream_ssl_sendv;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen sstream->ostream.flush = o_stream_ssl_flush;
8aa8399893c66b40e2790a4568256807a6ec6742Stephan Bosch sstream->ostream.switch_ioloop_to = o_stream_ssl_switch_ioloop_to;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
31df48d66a9a2327f6de41796e6819543c4494e1Timo Sirainen sstream->ostream.get_used_size = o_stream_ssl_get_used_size;
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Sirainen sstream->ostream.flush_pending = o_stream_ssl_flush_pending;
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Sirainen sstream->ostream.iostream.set_max_buffer_size =
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Sirainen o_stream_ssl_set_max_buffer_size;
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Sirainen
ce8cd19ccf52b19f14d4ea9c8b29bd94c0e48e4dTimo Sirainen sstream->ostream.callback = ssl_io->plain_output->real_stream->callback;
ce8cd19ccf52b19f14d4ea9c8b29bd94c0e48e4dTimo Sirainen sstream->ostream.context = ssl_io->plain_output->real_stream->context;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen o_stream_set_flush_callback(ssl_io->plain_output,
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen plain_flush_callback, sstream);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen return o_stream_create(&sstream->ostream, NULL,
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen o_stream_get_fd(ssl_io->plain_output));
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen}