doxygen: some fixes in tls module
[sip-router] / modules / tls / tls_bio.c
1 /* 
2  * $Id$
3  * 
4  * Copyright (C) 2010 iptelorg GmbH
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18
19 /**
20  * openssl BIOs for reading/writing via a fixed memory buffer.
21  * @file
22  * @ingroup tls
23  * @Module: @ref tls
24  */
25
26 /*
27  * History:
28  * --------
29  *  2010-03-25  initial version (andrei)
30  *  2010-05-20  emulate EAGAIN on null rd/wr memory buffer; handle some
31  *              needed commands in ctrl; debug support (TLS_BIO_DBG) (andrei)
32 */
33
34 #include "tls_bio.h"
35 #include "../../compiler_opt.h"
36 #include "../../dprint.h"
37 #include "../../ut.h"
38 #include "tls_cfg.h"
39
40 /* 0xf2 should be unused (as of openssl 1.0.0 max.
41    internal defined BIO is 23) */
42 #define BIO_TYPE_TLS_MBUF       (BIO_TYPE_SOURCE_SINK | 0xf2)
43
44 /* debugging */
45 #ifdef NO_TLS_BIO_DEBUG
46 #undef TLS_BIO_DEBUG
47 #endif
48 #ifdef TLS_BIO_DEBUG
49         #ifdef __SUNPRO_C
50                 #define TLS_BIO_DBG(...) \
51                         LOG_(DEFAULT_FACILITY, cfg_get(tls, tls_cfg, debug),\
52                                         "tls_BIO: " LOC_INFO,  __VA_ARGS__)
53         #else
54                 #define TLS_BIO_DBG(args...) \
55                         LOG_(DEFAULT_FACILITY, cfg_get(tls, tls_cfg, debug),\
56                                         "tls_BIO: " LOC_INFO, ## args)
57         #endif /* __SUNPRO_c */
58 #else /* TLS_BIO_DEBUG */
59         #ifdef __SUNPRO_C
60                 #define TLS_BIO_DBG(...)
61         #else
62                 #define TLS_BIO_DBG(fmt, args...)
63         #endif /* __SUNPRO_c */
64 #endif /* TLS_BIO_DEBUG */
65
66
67 static int tls_bio_mbuf_new(BIO* b);
68 static int tls_bio_mbuf_free(BIO* b);
69 static int tls_bio_mbuf_write(BIO* b, const char* buf, int num);
70 static int tls_bio_mbuf_read(BIO* b, char* buf, int num);
71 static int tls_bio_mbuf_puts(BIO* b, const char* s);
72 static long tls_bio_mbuf_ctrl(BIO* b, int cmd, long arg1, void* arg2);
73
74
75 static BIO_METHOD tls_mbuf_method = {
76         BIO_TYPE_TLS_MBUF,      /* type */
77         "sr_tls_mbuf",          /* name */
78         tls_bio_mbuf_write,     /* write function */
79         tls_bio_mbuf_read,      /* read function */
80         tls_bio_mbuf_puts,      /* puts function */
81         0,                                      /* gets function */
82         tls_bio_mbuf_ctrl,      /* ctrl function */
83         tls_bio_mbuf_new,       /* create(new) function */
84         tls_bio_mbuf_free,      /* destroy(free) function */
85         0                                       /* ctrl callback */
86 };
87
88
89 /** returns a custom tls_mbuf BIO. */
90 BIO_METHOD* tls_BIO_mbuf(void)
91 {
92         return &tls_mbuf_method;
93 }
94
95
96
97 /** create an initialize a new tls_BIO_mbuf.
98  * @return new BIO on success (!=0), 0 on error.
99  */
100 BIO* tls_BIO_new_mbuf(struct tls_mbuf* rd, struct tls_mbuf* wr)
101 {
102         BIO* ret;
103         
104         TLS_BIO_DBG("tls_BIO_new_mbuf called (%p, %p)\n", rd, wr);
105         ret = BIO_new(tls_BIO_mbuf());
106         if (unlikely(ret == 0))
107                 return 0;
108         if (unlikely(tls_BIO_mbuf_set(ret, rd, wr) == 0)) {
109                 BIO_free(ret);
110                 return 0;
111         }
112         return ret;
113 }
114
115
116
117 /** sets the read and write mbuf for an  mbuf BIO.
118  * @return 1 on success, 0 on error (openssl BIO convention).
119  */
120 int tls_BIO_mbuf_set(BIO* b, struct tls_mbuf* rd, struct tls_mbuf* wr)
121 {
122         struct tls_bio_mbuf_data* d;
123         
124         TLS_BIO_DBG("tls_BIO_mbuf_set called (%p => %p, %p)\n", b, rd, wr);
125         if (unlikely(b->ptr == 0)){
126                 BUG("null BIO ptr\n");
127                 return 0;
128         }
129         d = b->ptr;
130         d->rd = rd;
131         d->wr = wr;
132         b->init = 1;
133         return 1;
134 }
135
136
137
138 /** create a new BIO.
139  * (internal openssl use via the tls_mbuf method)
140  * @return 1 on success, 0 on error.
141  */
142 static int tls_bio_mbuf_new(BIO* b)
143 {
144         struct tls_bio_mbuf_data* d;
145         
146         TLS_BIO_DBG("tls_bio_mbuf_new called (%p)\n", b);
147         b->init = 0; /* not initialized yet */
148         b->num = 0;
149         b->ptr = 0;
150         b->flags = 0;
151         d = OPENSSL_malloc(sizeof(*d));
152         if (unlikely(d == 0))
153                 return 0;
154         d->rd = 0;
155         d->wr = 0;
156         b->ptr = d;
157         return 1;
158 }
159
160
161
162 /** destroy a tls mbuf BIO.
163  * (internal openssl use via the tls_mbuf method)
164  * @return 1 on success, 0 on error.
165  */
166 static int tls_bio_mbuf_free(BIO* b)
167 {
168         TLS_BIO_DBG("tls_bio_mbuf_free called (%p)\n", b);
169         if (unlikely( b == 0))
170                         return 0;
171         if (likely(b->ptr)){
172                 OPENSSL_free(b->ptr);
173                 b->ptr = 0;
174                 b->init = 0;
175         }
176         return 1;
177 }
178
179
180
181 /** read from a mbuf.
182  * (internal openssl use via the tls_mbuf method)
183  * @return bytes read on success (0< ret <=dst_len), -1 on empty buffer & sets
184  *  should_retry_read, -1 on some other errors (w/o should_retry_read set).
185  */
186 static int tls_bio_mbuf_read(BIO* b, char* dst, int dst_len)
187 {
188         struct tls_bio_mbuf_data* d;
189         struct tls_mbuf* rd;
190         int ret;
191         
192         ret = 0;
193         if (likely(dst)) {
194                 d= b->ptr;
195                 BIO_clear_retry_flags(b);
196                 if (unlikely(d == 0 || d->rd->buf == 0)) {
197                         if (d == 0)
198                                 BUG("tls_BIO_mbuf %p: read called with null b->ptr\n", b);
199                         else {
200                                 /* this form of calling read with a null buffer is used
201                                    as a shortcut when no data is available =>
202                                    simulate EAGIAN/WANT_READ */
203                                 TLS_BIO_DBG("read (%p, %p, %d) called with null read buffer"
204                                                 "(%p->%p) => simulating EAGAIN/WANT_READ\n",
205                                                 b, dst, dst_len, d, d->rd);
206                                 BIO_set_retry_read(b);
207                         }
208                         return -1;
209                 }
210                 rd = d->rd;
211                 if (unlikely(rd->used == rd->pos && dst_len)) {
212                         /* mimic non-blocking read behaviour */
213                         TLS_BIO_DBG("read (%p, %p, %d) called with full rd (%d)"
214                                                 " => simulating EAGAIN/WANT_READ\n",
215                                                 b, dst, dst_len, rd->used);
216                         BIO_set_retry_read(b);
217                         return -1;
218                 }
219                 ret = MIN_int(rd->used - rd->pos, dst_len);
220                 /* copy data from rd.buf into dst */
221                 memcpy(dst, rd->buf+rd->pos, ret);
222                 TLS_BIO_DBG("read(%p, %p, %d) called with rd=%p pos=%d => %d bytes\n",
223                                                 b, dst, dst_len, rd->buf, rd->pos, ret);
224                 rd->pos += ret;
225 /*              if (unlikely(rd->pos < rd->used))
226                         BIO_set_retry_read(b);
227 */
228         }
229         return ret;
230 }
231
232
233
234 /** write to a mbuf.
235  * (internal openssl use via the tls_mbuf method)
236  * @return bytes written on success (0<= ret <=src_len), -1 on error or buffer
237  * full (in this case sets should_retry_write).
238  */
239 static int tls_bio_mbuf_write(BIO* b, const char* src, int src_len)
240 {
241         struct tls_bio_mbuf_data* d;
242         struct tls_mbuf* wr;
243         int ret;
244         
245         ret = 0;
246         d= b->ptr;
247         BIO_clear_retry_flags(b);
248         if (unlikely(d == 0 || d->wr->buf == 0)) {
249                 if (d == 0)
250                         BUG("tls_BIO_mbuf %p: write called with null b->ptr\n", b);
251                 else {
252                         /* this form of calling write with a null buffer is used
253                            as a shortcut when no data is available =>
254                            simulate EAGAIN/WANT_WRITE */
255                         TLS_BIO_DBG("write (%p, %p, %d) called with null buffer"
256                                         " => simulating WANT_WRITE\n", b, src, src_len);
257                         BIO_set_retry_write(b);
258                 }
259                 return -1;
260         }
261         wr = d->wr;
262         if (unlikely(wr->size == wr->used && src_len)) {
263                 /* mimic non-blocking socket behaviour */
264                 TLS_BIO_DBG("write (%p, %p, %d) called with full wr buffer (%d)"
265                                         " => simulating WANT_WRITE\n", b, src, src_len, wr->used);
266                 BIO_set_retry_write(b);
267                 return -1;
268         }
269         ret = MIN_int(wr->size - wr->used, src_len);
270         memcpy(wr->buf + wr->used, src, ret);
271         wr->used += ret;
272 /*      if (unlikely(ret < src_len))
273                 BIO_set_retry_write();
274 */
275         TLS_BIO_DBG("write called (%p, %p, %d) => %d\n", b, src, src_len, ret);
276         return ret;
277 }
278
279
280
281 static long tls_bio_mbuf_ctrl(BIO* b, int cmd, long arg1, void* arg2)
282 {
283         long ret;
284         ret=0;
285         switch(cmd) {
286                 case BIO_C_SET_FD:
287                 case BIO_C_GET_FD:
288                         ret = -1; /* error, not supported */
289                         break;
290                 case BIO_CTRL_GET_CLOSE:
291                 case BIO_CTRL_SET_CLOSE:
292                         ret = 0;
293                         break;
294                 case BIO_CTRL_DUP:
295                 case BIO_CTRL_FLUSH:
296                         ret = 1;
297                         break;
298                 case BIO_CTRL_RESET:
299                 case BIO_C_FILE_SEEK:
300                 case BIO_C_FILE_TELL:
301                 case BIO_CTRL_INFO:
302                 case BIO_CTRL_PENDING:
303                 case BIO_CTRL_WPENDING:
304                 default:
305                         ret = 0;
306                         break;
307         }
308         TLS_BIO_DBG("ctrl called (%p, %d, %ld, %p) => %ld\n",
309                                 b, cmd, arg1, arg2, ret);
310         return ret;
311 }
312
313
314
315 static int tls_bio_mbuf_puts(BIO* b, const char* s)
316 {
317         int len;
318         
319         TLS_BIO_DBG("puts called (%p, %s)\n", b, s);
320         len=strlen(s);
321         return tls_bio_mbuf_write(b, s, len);
322 }
323
324
325
326 /* vi: set ts=4 sw=4 tw=79:ai:cindent: */