static int o_stream_ssl_flush(struct ostream_private *stream) { struct ssl_ostream *sstream = (struct ssl_ostream *)stream; int ret; if ((ret = openssl_iostream_more(sstream->ssl_io)) < 0) { /* handshake failed */ io_stream_set_error(&stream->iostream, "%s", sstream->ssl_io->last_error); stream->ostream.stream_errno = errno; } else if (ret > 0 && sstream->buffer != NULL && sstream->buffer->used > 0) { /* we can try to send some of our buffered data */ ret = o_stream_ssl_flush_buffer(sstream); } if (ret == 0 && sstream->ssl_io->want_read) { /* we need to read more data until we can continue. */ o_stream_set_flush_pending(sstream->ssl_io->plain_output, FALSE); sstream->ssl_io->ostream_flush_waiting_input = TRUE; ret = 1; } return ret; }
static void openssl_iostream_destroy(struct ssl_iostream *ssl_io) { (void)SSL_shutdown(ssl_io->ssl); (void)openssl_iostream_more(ssl_io); (void)o_stream_flush(ssl_io->plain_output); ssl_iostream_unref(&ssl_io); }
static void openssl_iostream_destroy(struct ssl_iostream *ssl_io) { (void)SSL_shutdown(ssl_io->ssl); (void)openssl_iostream_more(ssl_io); (void)o_stream_flush(ssl_io->plain_output); /* close the plain i/o streams, because their fd may be closed soon, but we may still keep this ssl-iostream referenced until later. */ i_stream_close(ssl_io->plain_input); o_stream_close(ssl_io->plain_output); ssl_iostream_unref(&ssl_io); }
static void openssl_iostream_destroy(struct ssl_iostream *ssl_io) { if (SSL_shutdown(ssl_io->ssl) != 1) { /* if bidirectional shutdown fails we need to clear the error queue */ openssl_iostream_clear_errors(); } (void)openssl_iostream_more(ssl_io); (void)o_stream_flush(ssl_io->plain_output); /* close the plain i/o streams, because their fd may be closed soon, but we may still keep this ssl-iostream referenced until later. */ i_stream_close(ssl_io->plain_input); o_stream_close(ssl_io->plain_output); ssl_iostream_unref(&ssl_io); }
static ssize_t i_stream_ssl_read_real(struct istream_private *stream) { struct ssl_istream *sstream = (struct ssl_istream *)stream; struct ssl_iostream *ssl_io = sstream->ssl_io; unsigned char buffer[IO_BLOCK_SIZE]; size_t max_buffer_size = i_stream_get_max_buffer_size(&stream->istream); size_t orig_max_buffer_size = stream->max_buffer_size; size_t size; ssize_t ret, total_ret; if (sstream->seen_eof) { stream->istream.eof = TRUE; return -1; } if (stream->pos >= max_buffer_size) { i_stream_compress(stream); if (stream->pos >= max_buffer_size) return -2; } ret = openssl_iostream_more(ssl_io); if (ret <= 0) { if (ret < 0) { /* handshake failed */ i_assert(errno != 0); io_stream_set_error(&stream->iostream, "%s", ssl_io->last_error); stream->istream.stream_errno = errno; } return ret; } if (!i_stream_try_alloc(stream, 1, &size)) i_unreached(); if (stream->pos + size > max_buffer_size) { i_assert(max_buffer_size > stream->pos); size = max_buffer_size - stream->pos; } while ((ret = SSL_read(ssl_io->ssl, stream->w_buffer + stream->pos, size)) <= 0) { /* failed to read anything */ ret = openssl_iostream_handle_error(ssl_io, ret, "SSL_read"); if (ret <= 0) { if (ret == 0) return 0; if (ssl_io->last_error != NULL) { io_stream_set_error(&stream->iostream, "%s", ssl_io->last_error); } if (errno != EPIPE) stream->istream.stream_errno = errno; stream->istream.eof = TRUE; sstream->seen_eof = TRUE; return -1; } /* we did some BIO I/O, try reading again */ } stream->pos += ret; total_ret = ret; /* now make sure that we read everything already buffered in OpenSSL into the stream (without reading anything more). this makes I/O loop behave similary for ssl-istream as file-istream. */ sstream->ssl_io->input_handler = FALSE; stream->max_buffer_size = (size_t)-1; while ((ret = SSL_read(ssl_io->ssl, buffer, sizeof(buffer))) > 0) { memcpy(i_stream_alloc(stream, ret), buffer, ret); stream->pos += ret; total_ret += ret; } stream->max_buffer_size = orig_max_buffer_size; return total_ret; }