123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 |
- /*
- * Kamailio TLS module
- *
- * Copyright (C) 2010 iptelorg GmbH
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
- /**
- * openssl BIOs for reading/writing via a fixed memory buffer.
- * @file
- * @ingroup tls
- */
- #include "tls_bio.h"
- #include "../../compiler_opt.h"
- #include "../../dprint.h"
- #include "../../ut.h"
- #include "tls_cfg.h"
- /* 0xf2 should be unused (as of openssl 1.0.0 max.
- internal defined BIO is 23) */
- #define BIO_TYPE_TLS_MBUF (BIO_TYPE_SOURCE_SINK | 0xf2)
- /* debugging */
- #ifdef NO_TLS_BIO_DEBUG
- #undef TLS_BIO_DEBUG
- #endif
- #ifdef TLS_BIO_DEBUG
- #ifdef __SUNPRO_C
- #define TLS_BIO_DBG(...) \
- LOG_(DEFAULT_FACILITY, cfg_get(tls, tls_cfg, debug),\
- "tls_BIO: " LOC_INFO, __VA_ARGS__)
- #else
- #define TLS_BIO_DBG(args...) \
- LOG_(DEFAULT_FACILITY, cfg_get(tls, tls_cfg, debug),\
- "tls_BIO: " LOC_INFO, ## args)
- #endif /* __SUNPRO_c */
- #else /* TLS_BIO_DEBUG */
- #ifdef __SUNPRO_C
- #define TLS_BIO_DBG(...)
- #else
- #define TLS_BIO_DBG(fmt, args...)
- #endif /* __SUNPRO_c */
- #endif /* TLS_BIO_DEBUG */
- static int tls_bio_mbuf_new(BIO* b);
- static int tls_bio_mbuf_free(BIO* b);
- static int tls_bio_mbuf_write(BIO* b, const char* buf, int num);
- static int tls_bio_mbuf_read(BIO* b, char* buf, int num);
- static int tls_bio_mbuf_puts(BIO* b, const char* s);
- static long tls_bio_mbuf_ctrl(BIO* b, int cmd, long arg1, void* arg2);
- static BIO_METHOD tls_mbuf_method = {
- BIO_TYPE_TLS_MBUF, /* type */
- "sr_tls_mbuf", /* name */
- tls_bio_mbuf_write, /* write function */
- tls_bio_mbuf_read, /* read function */
- tls_bio_mbuf_puts, /* puts function */
- 0, /* gets function */
- tls_bio_mbuf_ctrl, /* ctrl function */
- tls_bio_mbuf_new, /* create(new) function */
- tls_bio_mbuf_free, /* destroy(free) function */
- 0 /* ctrl callback */
- };
- /** returns a custom tls_mbuf BIO. */
- BIO_METHOD* tls_BIO_mbuf(void)
- {
- return &tls_mbuf_method;
- }
- /** create an initialize a new tls_BIO_mbuf.
- * @return new BIO on success (!=0), 0 on error.
- */
- BIO* tls_BIO_new_mbuf(struct tls_mbuf* rd, struct tls_mbuf* wr)
- {
- BIO* ret;
-
- TLS_BIO_DBG("tls_BIO_new_mbuf called (%p, %p)\n", rd, wr);
- ret = BIO_new(tls_BIO_mbuf());
- if (unlikely(ret == 0))
- return 0;
- if (unlikely(tls_BIO_mbuf_set(ret, rd, wr) == 0)) {
- BIO_free(ret);
- return 0;
- }
- return ret;
- }
- /** sets the read and write mbuf for an mbuf BIO.
- * @return 1 on success, 0 on error (openssl BIO convention).
- */
- int tls_BIO_mbuf_set(BIO* b, struct tls_mbuf* rd, struct tls_mbuf* wr)
- {
- struct tls_bio_mbuf_data* d;
-
- TLS_BIO_DBG("tls_BIO_mbuf_set called (%p => %p, %p)\n", b, rd, wr);
- if (unlikely(b->ptr == 0)){
- BUG("null BIO ptr\n");
- return 0;
- }
- d = b->ptr;
- d->rd = rd;
- d->wr = wr;
- b->init = 1;
- return 1;
- }
- /** create a new BIO.
- * (internal openssl use via the tls_mbuf method)
- * @return 1 on success, 0 on error.
- */
- static int tls_bio_mbuf_new(BIO* b)
- {
- struct tls_bio_mbuf_data* d;
-
- TLS_BIO_DBG("tls_bio_mbuf_new called (%p)\n", b);
- b->init = 0; /* not initialized yet */
- b->num = 0;
- b->ptr = 0;
- b->flags = 0;
- d = OPENSSL_malloc(sizeof(*d));
- if (unlikely(d == 0))
- return 0;
- d->rd = 0;
- d->wr = 0;
- b->ptr = d;
- return 1;
- }
- /** destroy a tls mbuf BIO.
- * (internal openssl use via the tls_mbuf method)
- * @return 1 on success, 0 on error.
- */
- static int tls_bio_mbuf_free(BIO* b)
- {
- TLS_BIO_DBG("tls_bio_mbuf_free called (%p)\n", b);
- if (unlikely( b == 0))
- return 0;
- if (likely(b->ptr)){
- OPENSSL_free(b->ptr);
- b->ptr = 0;
- b->init = 0;
- }
- return 1;
- }
- /** read from a mbuf.
- * (internal openssl use via the tls_mbuf method)
- * @return bytes read on success (0< ret <=dst_len), -1 on empty buffer & sets
- * should_retry_read, -1 on some other errors (w/o should_retry_read set).
- */
- static int tls_bio_mbuf_read(BIO* b, char* dst, int dst_len)
- {
- struct tls_bio_mbuf_data* d;
- struct tls_mbuf* rd;
- int ret;
-
- ret = 0;
- if (likely(dst)) {
- d= b->ptr;
- BIO_clear_retry_flags(b);
- if (unlikely(d == 0 || d->rd->buf == 0)) {
- if (d == 0)
- BUG("tls_BIO_mbuf %p: read called with null b->ptr\n", b);
- else {
- /* this form of calling read with a null buffer is used
- as a shortcut when no data is available =>
- simulate EAGIAN/WANT_READ */
- TLS_BIO_DBG("read (%p, %p, %d) called with null read buffer"
- "(%p->%p) => simulating EAGAIN/WANT_READ\n",
- b, dst, dst_len, d, d->rd);
- BIO_set_retry_read(b);
- }
- return -1;
- }
- rd = d->rd;
- if (unlikely(rd->used == rd->pos && dst_len)) {
- /* mimic non-blocking read behaviour */
- TLS_BIO_DBG("read (%p, %p, %d) called with full rd (%d)"
- " => simulating EAGAIN/WANT_READ\n",
- b, dst, dst_len, rd->used);
- BIO_set_retry_read(b);
- return -1;
- }
- ret = MIN_int(rd->used - rd->pos, dst_len);
- /* copy data from rd.buf into dst */
- memcpy(dst, rd->buf+rd->pos, ret);
- TLS_BIO_DBG("read(%p, %p, %d) called with rd=%p pos=%d => %d bytes\n",
- b, dst, dst_len, rd->buf, rd->pos, ret);
- rd->pos += ret;
- /* if (unlikely(rd->pos < rd->used))
- BIO_set_retry_read(b);
- */
- }
- return ret;
- }
- /** write to a mbuf.
- * (internal openssl use via the tls_mbuf method)
- * @return bytes written on success (0<= ret <=src_len), -1 on error or buffer
- * full (in this case sets should_retry_write).
- */
- static int tls_bio_mbuf_write(BIO* b, const char* src, int src_len)
- {
- struct tls_bio_mbuf_data* d;
- struct tls_mbuf* wr;
- int ret;
-
- ret = 0;
- d= b->ptr;
- BIO_clear_retry_flags(b);
- if (unlikely(d == 0 || d->wr->buf == 0)) {
- if (d == 0)
- BUG("tls_BIO_mbuf %p: write called with null b->ptr\n", b);
- else {
- /* this form of calling write with a null buffer is used
- as a shortcut when no data is available =>
- simulate EAGAIN/WANT_WRITE */
- TLS_BIO_DBG("write (%p, %p, %d) called with null buffer"
- " => simulating WANT_WRITE\n", b, src, src_len);
- BIO_set_retry_write(b);
- }
- return -1;
- }
- wr = d->wr;
- if (unlikely(wr->size == wr->used && src_len)) {
- /* mimic non-blocking socket behaviour */
- TLS_BIO_DBG("write (%p, %p, %d) called with full wr buffer (%d)"
- " => simulating WANT_WRITE\n", b, src, src_len, wr->used);
- BIO_set_retry_write(b);
- return -1;
- }
- ret = MIN_int(wr->size - wr->used, src_len);
- memcpy(wr->buf + wr->used, src, ret);
- wr->used += ret;
- /* if (unlikely(ret < src_len))
- BIO_set_retry_write();
- */
- TLS_BIO_DBG("write called (%p, %p, %d) => %d\n", b, src, src_len, ret);
- return ret;
- }
- static long tls_bio_mbuf_ctrl(BIO* b, int cmd, long arg1, void* arg2)
- {
- long ret;
- ret=0;
- switch(cmd) {
- case BIO_C_SET_FD:
- case BIO_C_GET_FD:
- ret = -1; /* error, not supported */
- break;
- case BIO_CTRL_GET_CLOSE:
- case BIO_CTRL_SET_CLOSE:
- ret = 0;
- break;
- case BIO_CTRL_DUP:
- case BIO_CTRL_FLUSH:
- ret = 1;
- break;
- case BIO_CTRL_RESET:
- case BIO_C_FILE_SEEK:
- case BIO_C_FILE_TELL:
- case BIO_CTRL_INFO:
- case BIO_CTRL_PENDING:
- case BIO_CTRL_WPENDING:
- default:
- ret = 0;
- break;
- }
- TLS_BIO_DBG("ctrl called (%p, %d, %ld, %p) => %ld\n",
- b, cmd, arg1, arg2, ret);
- return ret;
- }
- static int tls_bio_mbuf_puts(BIO* b, const char* s)
- {
- int len;
-
- TLS_BIO_DBG("puts called (%p, %s)\n", b, s);
- len=strlen(s);
- return tls_bio_mbuf_write(b, s, len);
- }
- /* vi: set ts=4 sw=4 tw=79:ai:cindent: */
|