tls_bio.c

Go to the documentation of this file.
00001 /* 
00002  * Copyright (C) 2010 iptelorg GmbH
00003  *
00004  * Permission to use, copy, modify, and distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
00009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
00011  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00013  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00014  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00023 /*
00024  * History:
00025  * --------
00026  *  2010-03-25  initial version (andrei)
00027  *  2010-05-20  emulate EAGAIN on null rd/wr memory buffer; handle some
00028  *              needed commands in ctrl; debug support (TLS_BIO_DBG) (andrei)
00029 */
00030 
00031 #include "tls_bio.h"
00032 #include "../../compiler_opt.h"
00033 #include "../../dprint.h"
00034 #include "../../ut.h"
00035 #include "tls_cfg.h"
00036 
00037 /* 0xf2 should be unused (as of openssl 1.0.0 max.
00038    internal defined BIO is 23) */
00039 #define BIO_TYPE_TLS_MBUF       (BIO_TYPE_SOURCE_SINK | 0xf2)
00040 
00041 /* debugging */
00042 #ifdef NO_TLS_BIO_DEBUG
00043 #undef TLS_BIO_DEBUG
00044 #endif
00045 #ifdef TLS_BIO_DEBUG
00046         #ifdef __SUNPRO_C
00047                 #define TLS_BIO_DBG(...) \
00048                         LOG_(DEFAULT_FACILITY, cfg_get(tls, tls_cfg, debug),\
00049                                         "tls_BIO: " LOC_INFO,  __VA_ARGS__)
00050         #else
00051                 #define TLS_BIO_DBG(args...) \
00052                         LOG_(DEFAULT_FACILITY, cfg_get(tls, tls_cfg, debug),\
00053                                         "tls_BIO: " LOC_INFO, ## args)
00054         #endif /* __SUNPRO_c */
00055 #else /* TLS_BIO_DEBUG */
00056         #ifdef __SUNPRO_C
00057                 #define TLS_BIO_DBG(...)
00058         #else
00059                 #define TLS_BIO_DBG(fmt, args...)
00060         #endif /* __SUNPRO_c */
00061 #endif /* TLS_BIO_DEBUG */
00062 
00063 
00064 static int tls_bio_mbuf_new(BIO* b);
00065 static int tls_bio_mbuf_free(BIO* b);
00066 static int tls_bio_mbuf_write(BIO* b, const char* buf, int num);
00067 static int tls_bio_mbuf_read(BIO* b, char* buf, int num);
00068 static int tls_bio_mbuf_puts(BIO* b, const char* s);
00069 static long tls_bio_mbuf_ctrl(BIO* b, int cmd, long arg1, void* arg2);
00070 
00071 
00072 static BIO_METHOD tls_mbuf_method = {
00073         BIO_TYPE_TLS_MBUF,      /* type */
00074         "sr_tls_mbuf",          /* name */
00075         tls_bio_mbuf_write,     /* write function */
00076         tls_bio_mbuf_read,      /* read function */
00077         tls_bio_mbuf_puts,      /* puts function */
00078         0,                                      /* gets function */
00079         tls_bio_mbuf_ctrl,      /* ctrl function */
00080         tls_bio_mbuf_new,       /* create(new) function */
00081         tls_bio_mbuf_free,      /* destroy(free) function */
00082         0                                       /* ctrl callback */
00083 };
00084 
00085 
00087 BIO_METHOD* tls_BIO_mbuf(void)
00088 {
00089         return &tls_mbuf_method;
00090 }
00091 
00092 
00093 
00097 BIO* tls_BIO_new_mbuf(struct tls_mbuf* rd, struct tls_mbuf* wr)
00098 {
00099         BIO* ret;
00100         
00101         TLS_BIO_DBG("tls_BIO_new_mbuf called (%p, %p)\n", rd, wr);
00102         ret = BIO_new(tls_BIO_mbuf());
00103         if (unlikely(ret == 0))
00104                 return 0;
00105         if (unlikely(tls_BIO_mbuf_set(ret, rd, wr) == 0)) {
00106                 BIO_free(ret);
00107                 return 0;
00108         }
00109         return ret;
00110 }
00111 
00112 
00113 
00117 int tls_BIO_mbuf_set(BIO* b, struct tls_mbuf* rd, struct tls_mbuf* wr)
00118 {
00119         struct tls_bio_mbuf_data* d;
00120         
00121         TLS_BIO_DBG("tls_BIO_mbuf_set called (%p => %p, %p)\n", b, rd, wr);
00122         if (unlikely(b->ptr == 0)){
00123                 BUG("null BIO ptr\n");
00124                 return 0;
00125         }
00126         d = b->ptr;
00127         d->rd = rd;
00128         d->wr = wr;
00129         b->init = 1;
00130         return 1;
00131 }
00132 
00133 
00134 
00139 static int tls_bio_mbuf_new(BIO* b)
00140 {
00141         struct tls_bio_mbuf_data* d;
00142         
00143         TLS_BIO_DBG("tls_bio_mbuf_new called (%p)\n", b);
00144         b->init = 0; /* not initialized yet */
00145         b->num = 0;
00146         b->ptr = 0;
00147         b->flags = 0;
00148         d = OPENSSL_malloc(sizeof(*d));
00149         if (unlikely(d == 0))
00150                 return 0;
00151         d->rd = 0;
00152         d->wr = 0;
00153         b->ptr = d;
00154         return 1;
00155 }
00156 
00157 
00158 
00163 static int tls_bio_mbuf_free(BIO* b)
00164 {
00165         TLS_BIO_DBG("tls_bio_mbuf_free called (%p)\n", b);
00166         if (unlikely( b == 0))
00167                         return 0;
00168         if (likely(b->ptr)){
00169                 OPENSSL_free(b->ptr);
00170                 b->ptr = 0;
00171                 b->init = 0;
00172         }
00173         return 1;
00174 }
00175 
00176 
00177 
00183 static int tls_bio_mbuf_read(BIO* b, char* dst, int dst_len)
00184 {
00185         struct tls_bio_mbuf_data* d;
00186         struct tls_mbuf* rd;
00187         int ret;
00188         
00189         ret = 0;
00190         if (likely(dst)) {
00191                 d= b->ptr;
00192                 BIO_clear_retry_flags(b);
00193                 if (unlikely(d == 0 || d->rd->buf == 0)) {
00194                         if (d == 0)
00195                                 BUG("tls_BIO_mbuf %p: read called with null b->ptr\n", b);
00196                         else {
00197                                 /* this form of calling read with a null buffer is used
00198                                    as a shortcut when no data is available =>
00199                                    simulate EAGIAN/WANT_READ */
00200                                 TLS_BIO_DBG("read (%p, %p, %d) called with null read buffer"
00201                                                 "(%p->%p) => simulating EAGAIN/WANT_READ\n",
00202                                                 b, dst, dst_len, d, d->rd);
00203                                 BIO_set_retry_read(b);
00204                         }
00205                         return -1;
00206                 }
00207                 rd = d->rd;
00208                 if (unlikely(rd->used == rd->pos && dst_len)) {
00209                         /* mimic non-blocking read behaviour */
00210                         TLS_BIO_DBG("read (%p, %p, %d) called with full rd (%d)"
00211                                                 " => simulating EAGAIN/WANT_READ\n",
00212                                                 b, dst, dst_len, rd->used);
00213                         BIO_set_retry_read(b);
00214                         return -1;
00215                 }
00216                 ret = MIN_int(rd->used - rd->pos, dst_len);
00217                 /* copy data from rd.buf into dst */
00218                 memcpy(dst, rd->buf+rd->pos, ret);
00219                 TLS_BIO_DBG("read(%p, %p, %d) called with rd=%p pos=%d => %d bytes\n",
00220                                                 b, dst, dst_len, rd->buf, rd->pos, ret);
00221                 rd->pos += ret;
00222 /*              if (unlikely(rd->pos < rd->used))
00223                         BIO_set_retry_read(b);
00224 */
00225         }
00226         return ret;
00227 }
00228 
00229 
00230 
00236 static int tls_bio_mbuf_write(BIO* b, const char* src, int src_len)
00237 {
00238         struct tls_bio_mbuf_data* d;
00239         struct tls_mbuf* wr;
00240         int ret;
00241         
00242         ret = 0;
00243         d= b->ptr;
00244         BIO_clear_retry_flags(b);
00245         if (unlikely(d == 0 || d->wr->buf == 0)) {
00246                 if (d == 0)
00247                         BUG("tls_BIO_mbuf %p: write called with null b->ptr\n", b);
00248                 else {
00249                         /* this form of calling write with a null buffer is used
00250                            as a shortcut when no data is available =>
00251                            simulate EAGAIN/WANT_WRITE */
00252                         TLS_BIO_DBG("write (%p, %p, %d) called with null buffer"
00253                                         " => simulating WANT_WRITE\n", b, src, src_len);
00254                         BIO_set_retry_write(b);
00255                 }
00256                 return -1;
00257         }
00258         wr = d->wr;
00259         if (unlikely(wr->size == wr->used && src_len)) {
00260                 /* mimic non-blocking socket behaviour */
00261                 TLS_BIO_DBG("write (%p, %p, %d) called with full wr buffer (%d)"
00262                                         " => simulating WANT_WRITE\n", b, src, src_len, wr->used);
00263                 BIO_set_retry_write(b);
00264                 return -1;
00265         }
00266         ret = MIN_int(wr->size - wr->used, src_len);
00267         memcpy(wr->buf + wr->used, src, ret);
00268         wr->used += ret;
00269 /*      if (unlikely(ret < src_len))
00270                 BIO_set_retry_write();
00271 */
00272         TLS_BIO_DBG("write called (%p, %p, %d) => %d\n", b, src, src_len, ret);
00273         return ret;
00274 }
00275 
00276 
00277 
00278 static long tls_bio_mbuf_ctrl(BIO* b, int cmd, long arg1, void* arg2)
00279 {
00280         long ret;
00281         ret=0;
00282         switch(cmd) {
00283                 case BIO_C_SET_FD:
00284                 case BIO_C_GET_FD:
00285                         ret = -1; /* error, not supported */
00286                         break;
00287                 case BIO_CTRL_GET_CLOSE:
00288                 case BIO_CTRL_SET_CLOSE:
00289                         ret = 0;
00290                         break;
00291                 case BIO_CTRL_DUP:
00292                 case BIO_CTRL_FLUSH:
00293                         ret = 1;
00294                         break;
00295                 case BIO_CTRL_RESET:
00296                 case BIO_C_FILE_SEEK:
00297                 case BIO_C_FILE_TELL:
00298                 case BIO_CTRL_INFO:
00299                 case BIO_CTRL_PENDING:
00300                 case BIO_CTRL_WPENDING:
00301                 default:
00302                         ret = 0;
00303                         break;
00304         }
00305         TLS_BIO_DBG("ctrl called (%p, %d, %ld, %p) => %ld\n",
00306                                 b, cmd, arg1, arg2, ret);
00307         return ret;
00308 }
00309 
00310 
00311 
00312 static int tls_bio_mbuf_puts(BIO* b, const char* s)
00313 {
00314         int len;
00315         
00316         TLS_BIO_DBG("puts called (%p, %s)\n", b, s);
00317         len=strlen(s);
00318         return tls_bio_mbuf_write(b, s, len);
00319 }
00320 
00321 
00322 
00323 /* vi: set ts=4 sw=4 tw=79:ai:cindent: */