summaryrefslogtreecommitdiffabout
path: root/kmicromail/libetpan/tools/mailstream_ssl.c
Unidiff
Diffstat (limited to 'kmicromail/libetpan/tools/mailstream_ssl.c') (more/less context) (ignore whitespace changes)
-rw-r--r--kmicromail/libetpan/tools/mailstream_ssl.c312
1 files changed, 312 insertions, 0 deletions
diff --git a/kmicromail/libetpan/tools/mailstream_ssl.c b/kmicromail/libetpan/tools/mailstream_ssl.c
new file mode 100644
index 0000000..9f5008d
--- a/dev/null
+++ b/kmicromail/libetpan/tools/mailstream_ssl.c
@@ -0,0 +1,312 @@
1/*
2 * libEtPan! -- a mail stuff library
3 *
4 * Copyright (C) 2001, 2002 - DINH Viet Hoa
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the libEtPan! project nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32/*
33 * $Id$
34 */
35
36/*
37 NOTE :
38
39 The user has to call himself SSL_library_init() if he wants to
40 use SSL.
41*/
42
43#include "mailstream_ssl.h"
44#include <unistd.h>
45#include <fcntl.h>
46
47#ifndef CONFIG_H
48#define CONFIG_H
49#include "config.h"
50#endif
51
52/*
53 these 3 headers MUST be included before <sys/select.h>
54 to insure compatibility with Mac OS X (this is true for 10.2)
55*/
56#include <sys/time.h>
57#include <sys/types.h>
58#include <unistd.h>
59#include <sys/select.h>
60
61/* mailstream_low, ssl */
62
63#ifdef USE_SSL
64#include <openssl/ssl.h>
65#include <pthread.h>
66#endif
67
68#ifdef USE_SSL
69struct mailstream_ssl_data {
70 int fd;
71 SSL * ssl_conn;
72 SSL_CTX * ssl_ctx;
73};
74#endif
75
76#ifdef USE_SSL
77static pthread_mutex_t ssl_lock = PTHREAD_MUTEX_INITIALIZER;
78static int ssl_init_done = 0;
79#endif
80
81#ifdef USE_SSL
82static int mailstream_low_ssl_close(mailstream_low * s);
83static ssize_t mailstream_low_ssl_read(mailstream_low * s,
84 void * buf, size_t count);
85static ssize_t mailstream_low_ssl_write(mailstream_low * s,
86 const void * buf, size_t count);
87static void mailstream_low_ssl_free(mailstream_low * s);
88static int mailstream_low_ssl_get_fd(mailstream_low * s);
89
90static mailstream_low_driver local_mailstream_ssl_driver = {
91 mailstream_read: mailstream_low_ssl_read,
92 mailstream_write: mailstream_low_ssl_write,
93 mailstream_close: mailstream_low_ssl_close,
94 mailstream_free: mailstream_low_ssl_free,
95 mailstream_get_fd: mailstream_low_ssl_get_fd,
96};
97
98mailstream_low_driver * mailstream_ssl_driver = &local_mailstream_ssl_driver;
99#endif
100
101/* file descriptor must be given in (default) blocking-mode */
102
103#ifdef USE_SSL
104static struct mailstream_ssl_data * ssl_data_new(int fd)
105{
106 struct mailstream_ssl_data * ssl_data;
107 SSL * ssl_conn;
108 int r;
109 SSL_CTX * tmp_ctx;
110 int fd_flags;
111 int old_fd_flags;
112
113 pthread_mutex_lock(&ssl_lock);
114 if (!ssl_init_done) {
115 SSL_library_init();
116 ssl_init_done = 1;
117 }
118 pthread_mutex_unlock(&ssl_lock);
119
120 tmp_ctx = SSL_CTX_new(TLSv1_client_method());
121 if (tmp_ctx == NULL)
122 goto err;
123
124 ssl_conn = (SSL *) SSL_new(tmp_ctx);
125 if (ssl_conn == NULL)
126 goto free_ctx;
127
128 if (SSL_set_fd(ssl_conn, fd) == 0)
129 goto free_ssl_conn;
130
131 SSL_set_read_ahead(ssl_conn, 1);
132
133 r = SSL_connect(ssl_conn);
134 if (r <= 0)
135 goto free_ssl_conn;
136
137 fd_flags = fcntl(fd, F_GETFL, 0);
138 old_fd_flags = fd_flags;
139 fd_flags |= O_NDELAY;
140 r = fcntl(fd, F_SETFL, fd_flags);
141 if (r < 0)
142 goto free_ssl_conn;
143
144 ssl_data = malloc(sizeof(* ssl_data));
145 if (ssl_data == NULL)
146 goto reset_fd_flags;
147
148 ssl_data->fd = fd;
149 ssl_data->ssl_conn = ssl_conn;
150 ssl_data->ssl_ctx = tmp_ctx;
151
152 return ssl_data;
153
154 reset_fd_flags:
155 fcntl(fd, F_SETFL, old_fd_flags);
156 free_ctx:
157 SSL_CTX_free(tmp_ctx);
158 free_ssl_conn:
159 SSL_free(ssl_conn);
160 err:
161 return NULL;
162}
163
164static void ssl_data_free(struct mailstream_ssl_data * ssl_data)
165{
166 free(ssl_data);
167}
168
169static void ssl_data_close(struct mailstream_ssl_data * ssl_data)
170{
171 SSL_free(ssl_data->ssl_conn);
172 ssl_data->ssl_conn = NULL;
173 SSL_CTX_free(ssl_data->ssl_ctx);
174 ssl_data->ssl_ctx = NULL;
175 close(ssl_data->fd);
176 ssl_data->fd = -1;
177}
178#endif
179
180mailstream_low * mailstream_low_ssl_open(int fd)
181{
182#ifdef USE_SSL
183 mailstream_low * s;
184 struct mailstream_ssl_data * ssl_data;
185
186 ssl_data = ssl_data_new(fd);
187 if (ssl_data == NULL)
188 goto err;
189
190 s = mailstream_low_new(ssl_data, mailstream_ssl_driver);
191 if (s == NULL)
192 goto free_ssl_data;
193
194 return s;
195
196 free_ssl_data:
197 ssl_data_free(ssl_data);
198 err:
199 return NULL;
200#else
201 return NULL;
202#endif
203}
204
205#ifdef USE_SSL
206static int mailstream_low_ssl_close(mailstream_low * s)
207{
208 struct mailstream_ssl_data * ssl_data;
209
210 ssl_data = (struct mailstream_ssl_data *) s->data;
211 ssl_data_close(ssl_data);
212
213 return 0;
214}
215
216static void mailstream_low_ssl_free(mailstream_low * s)
217{
218 struct mailstream_ssl_data * ssl_data;
219
220 ssl_data = (struct mailstream_ssl_data *) s->data;
221 ssl_data_free(ssl_data);
222 s->data = NULL;
223
224 free(s);
225}
226
227static int mailstream_low_ssl_get_fd(mailstream_low * s)
228{
229 struct mailstream_ssl_data * ssl_data;
230
231 ssl_data = (struct mailstream_ssl_data *) s->data;
232 return ssl_data->fd;
233}
234
235static ssize_t mailstream_low_ssl_read(mailstream_low * s,
236 void * buf, size_t count)
237{
238 struct mailstream_ssl_data * ssl_data;
239 int r;
240
241 ssl_data = (struct mailstream_ssl_data *) s->data;
242
243 while (1) {
244 int ssl_r;
245 fd_set fds_read;
246 struct timeval timeout;
247
248 r = SSL_read(ssl_data->ssl_conn, buf, count);
249 if (r > 0)
250 return r;
251
252 ssl_r = SSL_get_error(ssl_data->ssl_conn, r);
253 switch (ssl_r) {
254 case SSL_ERROR_NONE:
255 return r;
256
257 case SSL_ERROR_ZERO_RETURN:
258 return r;
259
260 case SSL_ERROR_WANT_READ:
261 timeout = mailstream_network_delay;
262
263 FD_ZERO(&fds_read);
264 FD_SET(ssl_data->fd, &fds_read);
265 r = select(ssl_data->fd + 1, &fds_read, NULL, NULL, &timeout);
266 if (r == 0)
267 return -1;
268 break;
269
270 default:
271 return r;
272 }
273 }
274}
275
276static ssize_t mailstream_low_ssl_write(mailstream_low * s,
277 const void * buf, size_t count)
278{
279 struct mailstream_ssl_data * ssl_data;
280
281 ssl_data = (struct mailstream_ssl_data *) s->data;
282 return SSL_write(ssl_data->ssl_conn, buf, count);
283}
284#endif
285
286/* mailstream */
287
288mailstream * mailstream_ssl_open(int fd)
289{
290#ifdef USE_SSL
291 mailstream_low * low;
292 mailstream * s;
293
294 low = mailstream_low_ssl_open(fd);
295 if (low == NULL)
296 goto err;
297
298 s = mailstream_new(low, 8192);
299 if (s == NULL)
300 goto free_low;
301
302 return s;
303
304 free_low:
305 mailstream_low_close(low);
306 err:
307 return NULL;
308#else
309 return NULL;
310#endif
311}
312