ostream-openssl.c revision 2454dfa32c93c20a8522c6ed42fe057baaac9f9a
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2009-2017 Dovecot authors, see the included COPYING file */
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Siraineno_stream_ssl_close(struct iostream_private *stream, bool close_parent)
52d19b57c2411bb1c60f8248ea5c8c1a1cfc1b4fTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)stream;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen o_stream_close(sstream->ssl_io->plain_output);
52d19b57c2411bb1c60f8248ea5c8c1a1cfc1b4fTimo Sirainenstatic void o_stream_ssl_destroy(struct iostream_private *stream)
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)stream;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Siraineno_stream_ssl_buffer(struct ssl_ostream *sstream, const struct const_iovec *iov,
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen unsigned int i;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen sstream->buffer = buffer_create_dynamic(default_pool, 4096);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen for (i = 0; i < iov_count; i++) {
1c3e5f6b1afaf119335e3892b0a5ca76a37acebdTimo Sirainen /* we're requeted 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 avail = sstream->ostream.max_buffer_size > sstream->buffer->used ?
1c3e5f6b1afaf119335e3892b0a5ca76a37acebdTimo Sirainen sstream->ostream.max_buffer_size - sstream->buffer->used : 0;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen size = I_MIN(iov[i].iov_len - skip_left, avail);
ed41ec8aa0efaa50954fd16cb44c86c8350dadccTimo Sirainen o_stream_set_flush_pending(sstream->ssl_io->plain_output, TRUE);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen for (; i < iov_count; i++) {
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen buffer_append(sstream->buffer, iov[i].iov_base, size);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen sstream->ostream.ostream.offset += bytes_sent;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenstatic int o_stream_ssl_flush_buffer(struct ssl_ostream *sstream)
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. */
3faa1040e5a3f9f35ffad29110216094ab2f5880Timo Sirainen ret = openssl_iostream_handle_write_error(sstream->ssl_io,
1c6f6f5bef70f16546b3bc8f4cd5f93f373e82a2Timo Sirainen io_stream_set_error(&sstream->ostream.iostream,
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen sstream->ostream.ostream.stream_errno = errno;
3faa1040e5a3f9f35ffad29110216094ab2f5880Timo Sirainen (void)openssl_iostream_bio_sync(sstream->ssl_io);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenstatic int o_stream_ssl_flush(struct ostream_private *stream)
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)stream;
3faa1040e5a3f9f35ffad29110216094ab2f5880Timo Sirainen if ((ret = openssl_iostream_more(sstream->ssl_io)) < 0) {
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen /* handshake failed */
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen } else if (ret > 0 && sstream->buffer != NULL &&
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen /* we can try to send some of our buffered data */
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen /* we need to read more data until we can continue. */
96f071012c4afc923890009398e8e5a59a693c58Timo Sirainen o_stream_set_flush_pending(sstream->ssl_io->plain_output,
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen sstream->ssl_io->ostream_flush_waiting_input = TRUE;
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Siraineno_stream_ssl_sendv(struct ostream_private *stream,
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen const struct const_iovec *iov, unsigned int iov_count)
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)stream;
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen bytes_sent = o_stream_ssl_buffer(sstream, iov, iov_count, bytes_sent);
b1faf5924b03c6863d37f828b6dfb67f91dafec8Timo Sirainen /* buffer was empty before calling this. try to write it
b1faf5924b03c6863d37f828b6dfb67f91dafec8Timo Sirainen immediately. */
71da447014454c84828d9dface77219875554d7dTimo Sirainenstatic void o_stream_ssl_switch_ioloop(struct ostream_private *stream)
71da447014454c84828d9dface77219875554d7dTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)stream;
71da447014454c84828d9dface77219875554d7dTimo Sirainen o_stream_switch_ioloop(sstream->ssl_io->plain_output);
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainenstatic int plain_flush_callback(struct ssl_ostream *sstream)
ce8cd19ccf52b19f14d4ea9c8b29bd94c0e48e4dTimo Sirainen struct ostream *ostream = &sstream->ostream.ostream;
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen /* try to actually flush the pending data */
e98de01b5644c88b6053e2921eb5e9a506fe263fTimo Sirainen if ((ret = o_stream_flush(sstream->ssl_io->plain_output)) < 0)
21fed972adb354b92771eefad27f8ac8cbd5dd45Timo Sirainen /* we may be able to copy more data, try it */
ce8cd19ccf52b19f14d4ea9c8b29bd94c0e48e4dTimo Sirainen ret2 = sstream->ostream.callback(sstream->ostream.context);
ce8cd19ccf52b19f14d4ea9c8b29bd94c0e48e4dTimo Sirainen ret2 = o_stream_flush(&sstream->ostream.ostream);
ce8cd19ccf52b19f14d4ea9c8b29bd94c0e48e4dTimo Sirainen o_stream_set_flush_pending(sstream->ssl_io->plain_output, TRUE);
31df48d66a9a2327f6de41796e6819543c4494e1Timo Sirainenstatic size_t o_stream_ssl_get_used_size(const struct ostream_private *stream)
31df48d66a9a2327f6de41796e6819543c4494e1Timo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)stream;
31df48d66a9a2327f6de41796e6819543c4494e1Timo Sirainen return o_stream_get_buffer_used_size(sstream->ssl_io->plain_output);
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Siraineno_stream_ssl_flush_pending(struct ostream_private *_stream, bool set)
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)_stream;
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Sirainen o_stream_set_flush_pending(sstream->ssl_io->plain_output, set);
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Sirainenstatic void o_stream_ssl_set_max_buffer_size(struct iostream_private *_stream,
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Sirainen struct ssl_ostream *sstream = (struct ssl_ostream *)_stream;
c239a1de4ad80639335c3ea4564537ca441eb76aTimo Sirainen o_stream_set_max_buffer_size(sstream->ssl_io->plain_output, max_size);
3faa1040e5a3f9f35ffad29110216094ab2f5880Timo Sirainenstruct ostream *openssl_o_stream_create_ssl(struct ssl_iostream *ssl_io)
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;
71da447014454c84828d9dface77219875554d7dTimo Sirainen sstream->ostream.switch_ioloop = o_stream_ssl_switch_ioloop;
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 =
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,