ostream-openssl.c revision 4b794181a01c04d1dd33c9a8339ddbc826106408
657afb33796f8216c568ad813627da89970760beTimo Sirainen/* Copyright (c) 2009-2012 Dovecot authors, see the included COPYING file */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic void o_stream_ssl_close(struct iostream_private *stream)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)stream;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen o_stream_close(sstream->ssl_io->plain_output);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic void o_stream_ssl_destroy(struct iostream_private *stream)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)stream;
657afb33796f8216c568ad813627da89970760beTimo Siraineno_stream_ssl_buffer(struct ssl_ostream *sstream, const struct const_iovec *iov,
657afb33796f8216c568ad813627da89970760beTimo Sirainen unsigned int i;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen sstream->buffer = buffer_create_dynamic(default_pool, 4096);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen for (i = 0; i < iov_count; i++) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen avail = sstream->ostream.max_buffer_size > sstream->buffer->used ?
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen sstream->ostream.max_buffer_size - sstream->buffer->used : 0;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen size = I_MIN(iov[i].iov_len - skip_left, avail);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen o_stream_set_flush_pending(sstream->ssl_io->plain_output, TRUE);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen for (; i < iov_count; i++) {
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen buffer_append(sstream->buffer, iov[i].iov_base, size);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen sstream->ostream.ostream.offset += bytes_sent;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic int o_stream_ssl_flush_buffer(struct ssl_ostream *sstream)
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_iostream_handle_write_error(sstream->ssl_io,
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen sstream->ostream.ostream.stream_errno = errno;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic int o_stream_ssl_flush(struct ostream_private *stream)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)stream;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if ((ret = ssl_iostream_more(sstream->ssl_io)) < 0) {
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen /* handshake failed */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen } else if (ret > 0 && sstream->buffer != NULL &&
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* we can try to send some of our buffered data */
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen /* we need to read more data until we can continue. */
bbf81c8fc6f21382707673dc6bd7b87ffc27981bTimo Sirainen o_stream_set_flush_pending(sstream->ssl_io->plain_output,
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen sstream->ssl_io->ostream_flush_waiting_input = TRUE;
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Siraineno_stream_ssl_sendv_try(struct ssl_ostream *sstream,
1e0bdb2d0fa7bbd0a0a254754680f6c6d0195333Timo Sirainen const struct const_iovec *iov, unsigned int iov_count,
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen unsigned int i;
662a9000b1788f1cdf765e6b1c89df9a42cc3e32Timo Sirainen ret = ssl_iostream_handle_write_error(sstream->ssl_io,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen sstream->ostream.ostream.stream_errno = errno;
66d2db642fe24d555d113ba463e446b038d476efTimo Siraineno_stream_ssl_sendv(struct ostream_private *stream,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen const struct const_iovec *iov, unsigned int iov_count)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)stream;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen ret = o_stream_ssl_sendv_try(sstream, iov, iov_count,
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 Sirainenstatic void o_stream_ssl_switch_ioloop(struct ostream_private *stream)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)stream;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen o_stream_switch_ioloop(sstream->ssl_io->plain_output);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic int plain_flush_callback(struct ssl_ostream *sstream)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct ostream *ostream = &sstream->ostream.ostream;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* try to actually flush the pending data */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen if ((ret = o_stream_flush(sstream->ssl_io->plain_output)) < 0)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen /* we may be able to copy more data, try it */
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen ret2 = sstream->ostream.callback(sstream->ostream.context);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen ret2 = o_stream_flush(&sstream->ostream.ostream);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen o_stream_set_flush_pending(sstream->ssl_io->plain_output, TRUE);
66d2db642fe24d555d113ba463e446b038d476efTimo Siraineno_stream_ssl_flush_pending(struct ostream_private *_stream, bool set)
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)_stream;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen o_stream_set_flush_pending(sstream->ssl_io->plain_output, set);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstatic void o_stream_ssl_set_max_buffer_size(struct iostream_private *_stream,
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)_stream;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen o_stream_set_max_buffer_size(sstream->ssl_io->plain_output, max_size);
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainenstruct ostream *o_stream_create_ssl(struct ssl_iostream *ssl_io)
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;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen sstream->ostream.switch_ioloop = o_stream_ssl_switch_ioloop;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen sstream->ostream.flush_pending = o_stream_ssl_flush_pending;
66d2db642fe24d555d113ba463e446b038d476efTimo Sirainen sstream->ostream.iostream.set_max_buffer_size =
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,