ostream-openssl.c revision 4b794181a01c04d1dd33c9a8339ddbc826106408
657afb33796f8216c568ad813627da89970760beTimo Sirainen/* Copyright (c) 2009-2012 Dovecot authors, see the included COPYING file */
657afb33796f8216c568ad813627da89970760beTimo Sirainen
657afb33796f8216c568ad813627da89970760beTimo Sirainen#include "lib.h"
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen#include "buffer.h"
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen#include "ostream-private.h"
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen#include "iostream-openssl.h"
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstruct ssl_ostream {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct ostream_private ostream;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct ssl_iostream *ssl_io;
ecb1b2d6236942bf82f822e8d0167f0e160b206dTimo Sirainen buffer_t *buffer;
657afb33796f8216c568ad813627da89970760beTimo Sirainen};
657afb33796f8216c568ad813627da89970760beTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic void o_stream_ssl_close(struct iostream_private *stream)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)stream;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen o_stream_close(sstream->ssl_io->plain_output);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic void o_stream_ssl_destroy(struct iostream_private *stream)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)stream;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen sstream->ssl_io->ssl_output = NULL;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen ssl_iostream_unref(&sstream->ssl_io);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (sstream->buffer != NULL)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen buffer_free(&sstream->buffer);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic size_t
657afb33796f8216c568ad813627da89970760beTimo Siraineno_stream_ssl_buffer(struct ssl_ostream *sstream, const struct const_iovec *iov,
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen unsigned int iov_count, size_t bytes_sent)
657afb33796f8216c568ad813627da89970760beTimo Sirainen{
9b62bbaf33d4516b5dffb36c3ea32ce217e7fbb1Timo Sirainen size_t avail, skip_left, size;
657afb33796f8216c568ad813627da89970760beTimo Sirainen unsigned int i;
ad49932dae8ba31e07544b66bbc4f4de707a751cTimo Sirainen
657afb33796f8216c568ad813627da89970760beTimo Sirainen if (sstream->buffer == NULL)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen sstream->buffer = buffer_create_dynamic(default_pool, 4096);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen skip_left = bytes_sent;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen for (i = 0; i < iov_count; i++) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (skip_left < iov[i].iov_len)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen break;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen skip_left -= iov[i].iov_len;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen avail = sstream->ostream.max_buffer_size > sstream->buffer->used ?
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen sstream->ostream.max_buffer_size - sstream->buffer->used : 0;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (i < iov_count && skip_left > 0) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen size = I_MIN(iov[i].iov_len - skip_left, avail);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen buffer_append(sstream->buffer,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen CONST_PTR_OFFSET(iov[i].iov_base, skip_left),
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen size);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen bytes_sent += size;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen avail -= size;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (size != iov[i].iov_len)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen i = iov_count;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (avail > 0)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen o_stream_set_flush_pending(sstream->ssl_io->plain_output, TRUE);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen for (; i < iov_count; i++) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen size = I_MIN(iov[i].iov_len, avail);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen buffer_append(sstream->buffer, iov[i].iov_base, size);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen bytes_sent += size;
b1e6ea3323b4d753909f79226a8a98d854f819faTimo Sirainen avail -= size;
b1e6ea3323b4d753909f79226a8a98d854f819faTimo Sirainen
b1e6ea3323b4d753909f79226a8a98d854f819faTimo Sirainen if (size != iov[i].iov_len)
b1e6ea3323b4d753909f79226a8a98d854f819faTimo Sirainen break;
b1e6ea3323b4d753909f79226a8a98d854f819faTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen sstream->ostream.ostream.offset += bytes_sent;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return bytes_sent;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic int o_stream_ssl_flush_buffer(struct ssl_ostream *sstream)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
657afb33796f8216c568ad813627da89970760beTimo Sirainen size_t pos = 0;
657afb33796f8216c568ad813627da89970760beTimo Sirainen int ret = 1;
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen while (pos < sstream->buffer->used) {
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen /* we're writing plaintext data to OpenSSL, which it encrypts
657afb33796f8216c568ad813627da89970760beTimo Sirainen and writes to bio_int's buffer. ssl_iostream_bio_sync()
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen reads it from there and adds to plain_output stream. */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen ret = SSL_write(sstream->ssl_io->ssl,
657afb33796f8216c568ad813627da89970760beTimo Sirainen CONST_PTR_OFFSET(sstream->buffer->data, pos),
657afb33796f8216c568ad813627da89970760beTimo Sirainen sstream->buffer->used - pos);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (ret <= 0) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen ret = ssl_iostream_handle_write_error(sstream->ssl_io,
657afb33796f8216c568ad813627da89970760beTimo Sirainen ret, "SSL_write");
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (ret < 0) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen sstream->ostream.ostream.stream_errno = errno;
657afb33796f8216c568ad813627da89970760beTimo Sirainen break;
657afb33796f8216c568ad813627da89970760beTimo Sirainen }
70905e51a5148bd5613cb04720807177474a2496Timo Sirainen if (ret == 0)
657afb33796f8216c568ad813627da89970760beTimo Sirainen break;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen } else {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen pos += ret;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen (void)ssl_iostream_bio_sync(sstream->ssl_io);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen buffer_delete(sstream->buffer, 0, pos);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return ret <= 0 ? ret : 1;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic int o_stream_ssl_flush(struct ostream_private *stream)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)stream;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen int ret;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if ((ret = ssl_iostream_more(sstream->ssl_io)) < 0) {
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen /* handshake failed */
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen stream->ostream.stream_errno = errno;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen } else if (ret > 0 && sstream->buffer != NULL &&
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen sstream->buffer->used > 0) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* we can try to send some of our buffered data */
bbf81c8fc6f21382707673dc6bd7b87ffc27981bTimo Sirainen ret = o_stream_ssl_flush_buffer(sstream);
bbf81c8fc6f21382707673dc6bd7b87ffc27981bTimo Sirainen }
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen
bbf81c8fc6f21382707673dc6bd7b87ffc27981bTimo Sirainen if (ret == 0 && sstream->ssl_io->want_read) {
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen /* we need to read more data until we can continue. */
bbf81c8fc6f21382707673dc6bd7b87ffc27981bTimo Sirainen o_stream_set_flush_pending(sstream->ssl_io->plain_output,
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen FALSE);
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen sstream->ssl_io->ostream_flush_waiting_input = TRUE;
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen ret = 1;
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return ret;
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen}
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic ssize_t
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Siraineno_stream_ssl_sendv_try(struct ssl_ostream *sstream,
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen const struct const_iovec *iov, unsigned int iov_count,
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen size_t *bytes_sent_r)
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen{
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen unsigned int i;
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen size_t pos;
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen ssize_t ret = 0;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen *bytes_sent_r = 0;
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen for (i = 0, pos = 0; i < iov_count; ) {
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen ret = SSL_write(sstream->ssl_io->ssl,
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen CONST_PTR_OFFSET(iov[i].iov_base, pos),
52d3cbc21e8fe482b9b8c832f3921824a7aa6ebeTimo Sirainen iov[i].iov_len - pos);
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen if (ret <= 0) {
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen ret = ssl_iostream_handle_write_error(sstream->ssl_io,
8e176dbc6e220c4658afdcc17b097dab83b0d014Timo Sirainen ret, "SSL_write");
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (ret < 0) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen sstream->ostream.ostream.stream_errno = errno;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen break;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (ret == 0)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen break;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen } else {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen *bytes_sent_r += ret;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if ((size_t)ret < iov[i].iov_len)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen pos += ret;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen else {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen i++;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen pos = 0;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen (void)ssl_iostream_bio_sync(sstream->ssl_io);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return ret < 0 ? -1 : 0;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic ssize_t
66d2db642fe24d555d113ba463e446b038d476efTimo Siraineno_stream_ssl_sendv(struct ostream_private *stream,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen const struct const_iovec *iov, unsigned int iov_count)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)stream;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen size_t bytes_sent = 0;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen int ret;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (!sstream->ssl_io->handshaked)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen ret = 0;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen else {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen ret = o_stream_ssl_sendv_try(sstream, iov, iov_count,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen &bytes_sent);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen }
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen bytes_sent = o_stream_ssl_buffer(sstream, iov, iov_count, bytes_sent);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return bytes_sent != 0 ? (ssize_t)bytes_sent : ret;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic void o_stream_ssl_switch_ioloop(struct ostream_private *stream)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)stream;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen o_stream_switch_ioloop(sstream->ssl_io->plain_output);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic int plain_flush_callback(struct ssl_ostream *sstream)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct ostream *ostream = &sstream->ostream.ostream;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen int ret, ret2;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* try to actually flush the pending data */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if ((ret = o_stream_flush(sstream->ssl_io->plain_output)) < 0)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return -1;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* we may be able to copy more data, try it */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen o_stream_ref(ostream);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (sstream->ostream.callback != NULL)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen ret2 = sstream->ostream.callback(sstream->ostream.context);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen else
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen ret2 = o_stream_flush(&sstream->ostream.ostream);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (ret2 == 0)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen o_stream_set_flush_pending(sstream->ssl_io->plain_output, TRUE);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen o_stream_unref(&ostream);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if (ret2 < 0)
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return -1;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return ret > 0 && ret2 > 0 ? 1 : 0;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic void
66d2db642fe24d555d113ba463e446b038d476efTimo Siraineno_stream_ssl_flush_pending(struct ostream_private *_stream, bool set)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)_stream;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen o_stream_set_flush_pending(sstream->ssl_io->plain_output, set);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic void o_stream_ssl_set_max_buffer_size(struct iostream_private *_stream,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen size_t max_size)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)_stream;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen sstream->ostream.max_buffer_size = max_size;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen o_stream_set_max_buffer_size(sstream->ssl_io->plain_output, max_size);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstruct ostream *o_stream_create_ssl(struct ssl_iostream *ssl_io)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen{
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct ssl_ostream *sstream;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen ssl_io->refcount++;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen sstream = i_new(struct ssl_ostream, 1);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen sstream->ssl_io = ssl_io;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen sstream->ostream.max_buffer_size =
657afb33796f8216c568ad813627da89970760beTimo Sirainen ssl_io->plain_output->real_stream->max_buffer_size;
657afb33796f8216c568ad813627da89970760beTimo Sirainen sstream->ostream.iostream.close = o_stream_ssl_close;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen sstream->ostream.iostream.destroy = o_stream_ssl_destroy;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen sstream->ostream.sendv = o_stream_ssl_sendv;
657afb33796f8216c568ad813627da89970760beTimo Sirainen sstream->ostream.flush = o_stream_ssl_flush;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen sstream->ostream.switch_ioloop = o_stream_ssl_switch_ioloop;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen sstream->ostream.flush_pending = o_stream_ssl_flush_pending;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen sstream->ostream.iostream.set_max_buffer_size =
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen o_stream_ssl_set_max_buffer_size;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen sstream->ostream.callback = ssl_io->plain_output->real_stream->callback;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen sstream->ostream.context = ssl_io->plain_output->real_stream->context;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen o_stream_set_flush_callback(ssl_io->plain_output,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen plain_flush_callback, sstream);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen return o_stream_create(&sstream->ostream, NULL);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen}
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen