New upstream version 5.7.5

mr10.5.7 upstream/5.7.5
Victor Seva 1 year ago
parent 4abdbda9f9
commit 4534c8f0ac

File diff suppressed because it is too large Load Diff

@ -220,6 +220,14 @@ enable_tls=yes
/* upper limit for TLS connections */
tls_max_connections=2048
/* For OpenSSL 3 integration
* functions calling libssl3 can be invoked in a transient thread
* 0: disable threaded calls
* 1: use thread executors for process#0 only
* 2: no thread executors, but use atfork handler to reset thread-locals to NULL
* 3: use thread executors for all processes */
tls_threads_mode=1
#!endif
/* set it to yes to enable sctp and load sctp.so module */
@ -257,6 +265,12 @@ voicemail.srv_port = "5060" desc "VoiceMail Port"
/* set paths to location of modules */
# mpath="/usr/local/lib/kamailio/modules/"
# when using TLS with OpenSSL it is recommended to load this module
# first so that OpenSSL is initialized correctly
#!ifdef WITH_TLS
loadmodule "tls.so"
#!endif
#!ifdef WITH_MYSQL
loadmodule "db_mysql.so"
#!endif
@ -319,10 +333,6 @@ loadmodule "rtpproxy.so"
#!endif
#!endif
#!ifdef WITH_TLS
loadmodule "tls.so"
#!endif
#!ifdef WITH_HTABLE
loadmodule "htable.so"
#!endif

@ -4,7 +4,7 @@
# Maintainer: Nathan Angelacos <nangel@alpinelinux.org>
pkgname=kamailio
pkgver=5.7.4
pkgver=5.7.5
pkgrel=0
# If building from a git snapshot, specify the gitcommit

@ -1,3 +1,9 @@
kamailio (5.7.5) unstable; urgency=medium
* version set 5.7.5
-- Victor Seva <vseva@debian.org> Wed, 08 May 2024 07:57:10 +0200
kamailio (5.7.4) unstable; urgency=medium
* version set 5.7.4

@ -1,3 +1,9 @@
kamailio (5.7.5) unstable; urgency=medium
* version set 5.7.5
-- Victor Seva <vseva@debian.org> Wed, 08 May 2024 07:57:10 +0200
kamailio (5.7.4) unstable; urgency=medium
* version set 5.7.4

@ -1,3 +1,9 @@
kamailio (5.7.5) unstable; urgency=medium
* version set 5.7.5
-- Victor Seva <vseva@debian.org> Wed, 08 May 2024 07:57:10 +0200
kamailio (5.7.4) unstable; urgency=medium
* version set 5.7.4

@ -1,3 +1,9 @@
kamailio (5.7.5) unstable; urgency=medium
* version set 5.7.5
-- Victor Seva <vseva@debian.org> Wed, 08 May 2024 07:57:10 +0200
kamailio (5.7.4) unstable; urgency=medium
* version set 5.7.4

@ -1,3 +1,9 @@
kamailio (5.7.5) unstable; urgency=medium
* version set 5.7.5
-- Victor Seva <vseva@debian.org> Wed, 08 May 2024 07:57:10 +0200
kamailio (5.7.4) unstable; urgency=medium
* version set 5.7.4

@ -1,3 +1,9 @@
kamailio (5.7.5) unstable; urgency=medium
* version set 5.7.5
-- Victor Seva <vseva@debian.org> Wed, 08 May 2024 07:57:10 +0200
kamailio (5.7.4) unstable; urgency=medium
* version set 5.7.4

@ -1,3 +1,9 @@
kamailio (5.7.5) unstable; urgency=medium
* version set 5.7.5
-- Victor Seva <vseva@debian.org> Wed, 08 May 2024 07:57:10 +0200
kamailio (5.7.4) unstable; urgency=medium
* version set 5.7.4

@ -1,3 +1,9 @@
kamailio (5.7.5) unstable; urgency=medium
* version set 5.7.5
-- Victor Seva <vseva@debian.org> Wed, 08 May 2024 07:57:10 +0200
kamailio (5.7.4) unstable; urgency=medium
* version set 5.7.4

@ -1,3 +1,9 @@
kamailio (5.7.5) unstable; urgency=medium
* version set 5.7.5
-- Victor Seva <vseva@debian.org> Wed, 08 May 2024 07:57:10 +0200
kamailio (5.7.4) unstable; urgency=medium
* version set 5.7.4

@ -1,3 +1,9 @@
kamailio (5.7.5) unstable; urgency=medium
* version set 5.7.5
-- Victor Seva <vseva@debian.org> Wed, 08 May 2024 07:57:10 +0200
kamailio (5.7.4) unstable; urgency=medium
* version set 5.7.4

@ -1,3 +1,9 @@
kamailio (5.7.5) unstable; urgency=medium
* version set 5.7.5
-- Victor Seva <vseva@debian.org> Wed, 08 May 2024 07:57:10 +0200
kamailio (5.7.4) unstable; urgency=medium
* version set 5.7.4

@ -1,3 +1,9 @@
kamailio (5.7.5) unstable; urgency=medium
* version set 5.7.5
-- Victor Seva <vseva@debian.org> Wed, 08 May 2024 07:57:10 +0200
kamailio (5.7.4) unstable; urgency=medium
* version set 5.7.4

@ -1,3 +1,9 @@
kamailio (5.7.5) unstable; urgency=medium
* version set 5.7.5
-- Victor Seva <vseva@debian.org> Wed, 08 May 2024 07:57:10 +0200
kamailio (5.7.4) unstable; urgency=medium
* version set 5.7.4

@ -1,3 +1,9 @@
kamailio (5.7.5) unstable; urgency=medium
* version set 5.7.5
-- Victor Seva <vseva@debian.org> Wed, 08 May 2024 07:57:10 +0200
kamailio (5.7.4) unstable; urgency=medium
* version set 5.7.4

@ -1,5 +1,5 @@
%define name kamailio
%define ver 5.7.4
%define ver 5.7.5
%define rel dev1.0%{dist}
%if 0%{?fedora}

@ -106,7 +106,7 @@ INSTALL_FLAVOUR=$(FLAVOUR)
# version number
VERSION = 5
PATCHLEVEL = 7
SUBLEVEL = 4
SUBLEVEL = 5
EXTRAVERSION =
# memory manager switcher

@ -2,6 +2,6 @@
* DO NOT EDIT IT
*/
#define REPO_VER "dc393e"
#define REPO_HASH "dc393e"
#define REPO_VER "58499a"
#define REPO_HASH "58499a"
#define REPO_STATE ""

@ -439,6 +439,7 @@ TCP_WAIT_DATA "tcp_wait_data"
TCP_SCRIPT_MODE "tcp_script_mode"
DISABLE_TLS "disable_tls"|"tls_disable"
ENABLE_TLS "enable_tls"|"tls_enable"
TLS_THREADS_MODE "tls_threads_mode"
TLSLOG "tlslog"|"tls_log"
TLS_PORT_NO "tls_port_no"
TLS_METHOD "tls_method"
@ -953,6 +954,7 @@ IMPORTFILE "import_file"
<INITIAL>{TCP_SCRIPT_MODE} { count(); yylval.strval=yytext; return TCP_SCRIPT_MODE; }
<INITIAL>{DISABLE_TLS} { count(); yylval.strval=yytext; return DISABLE_TLS; }
<INITIAL>{ENABLE_TLS} { count(); yylval.strval=yytext; return ENABLE_TLS; }
<INITIAL>{TLS_THREADS_MODE} { count(); yylval.strval=yytext; return TLS_THREADS_MODE; }
<INITIAL>{TLSLOG} { count(); yylval.strval=yytext; return TLS_PORT_NO; }
<INITIAL>{TLS_PORT_NO} { count(); yylval.strval=yytext; return TLS_PORT_NO; }
<INITIAL>{TLS_METHOD} { count(); yylval.strval=yytext; return TLS_METHOD; }

@ -469,6 +469,7 @@ extern char *default_routename;
%token TCP_SCRIPT_MODE
%token DISABLE_TLS
%token ENABLE_TLS
%token TLS_THREADS_MODE
%token TLSLOG
%token TLS_PORT_NO
%token TLS_METHOD
@ -1440,6 +1441,14 @@ assign_stm:
#endif
}
| ENABLE_TLS EQUAL error { yyerror("boolean value expected"); }
| TLS_THREADS_MODE EQUAL NUMBER {
#ifdef USE_TLS
ksr_tls_threads_mode = $3;
#else
warn("tls support not compiled in");
#endif
}
| TLS_THREADS_MODE EQUAL error { yyerror("int value expected"); }
| TLSLOG EQUAL NUMBER {
#ifdef CORE_TLS
tls_log=$3;

@ -25,6 +25,7 @@
#include "dprint.h"
#include "globals.h"
#include "dset.h"
#include "resolve.h"
#include "fmsg.h"
@ -57,6 +58,8 @@ static void faked_msg_buf_init(void)
static int faked_msg_init_new(sip_msg_t *fmsg)
{
str loip = str_init("127.0.0.1");
faked_msg_buf_init();
/* init faked sip msg */
@ -75,13 +78,9 @@ static int faked_msg_init_new(sip_msg_t *fmsg)
fmsg->rcv.proto = PROTO_UDP;
fmsg->rcv.src_port = 5060;
fmsg->rcv.src_ip.u.addr32[0] = 0x7f000001;
fmsg->rcv.src_ip.af = AF_INET;
fmsg->rcv.src_ip.len = 4;
str2ipbuf(&loip, &fmsg->rcv.src_ip);
fmsg->rcv.dst_port = 5060;
fmsg->rcv.dst_ip.u.addr32[0] = 0x7f000001;
fmsg->rcv.dst_ip.af = AF_INET;
fmsg->rcv.dst_ip.len = 4;
str2ipbuf(&loip, &fmsg->rcv.dst_ip);
return 0;
}

@ -188,7 +188,8 @@ static inline int msg_send_buffer(
su2ip_addr(&ip, &dst->to);
if(tcp_connection_match == TCPCONN_MATCH_STRICT) {
con = tcpconn_lookup(dst->id, &ip, port, from,
(dst->send_sock) ? dst->send_sock->port_no : 0, 0);
(dst->send_sock) ? dst->send_sock->port_no : 0, 0,
dst->proto);
} else {
con = tcpconn_get(dst->id, &ip, port, from, 0);
}

@ -108,6 +108,7 @@ extern int ksr_tcp_script_mode;
#ifdef USE_TLS
extern int tls_disable;
extern unsigned short tls_port_no;
extern int ksr_tls_threads_mode;
#endif
#ifdef USE_SCTP
extern int sctp_disable;

@ -87,7 +87,18 @@ int run_onsend(sip_msg_t *orig_msg, dest_info_t *dst, char *buf, int len)
orig_msg->fwd_send_flags = fwd_snd_flags_bak;
orig_msg->rpl_send_flags = rpl_snd_flags_bak;
exec_post_script_cb(orig_msg, ONSEND_CB_TYPE);
if((ret == 0) && !(ra_ctx.run_flags & DROP_R_F)) {
/* - handle drop action with flag DROP_R_F
* KEMI case (python,lua,jsdt)
* ret = 1 always
* Native case:
* ret = 1 success
* ret = 0 drop the message
*/
if(ra_ctx.run_flags & DROP_R_F) {
ret = 0;
} else if(ret == 0) {
/* native case where run_actions return 0
* but DROP_R_F is not set */
ret = 1;
}
} else {

@ -209,6 +209,8 @@ static inline int skip_name(str *_s)
}
#define KSR_MAX_CONTACTS 256
/*
* Parse contacts in a Contact HF
*/
@ -217,9 +219,13 @@ int parse_contacts(str *_s, contact_t **_c)
contact_t *c;
param_hooks_t hooks;
str sv;
int n;
int star;
sv = *_s;
n = 0;
star = 0;
while(1) {
/* Allocate and clear contact structure */
c = (contact_t *)pkg_malloc(sizeof(contact_t));
@ -261,6 +267,24 @@ int parse_contacts(str *_s, contact_t **_c)
LM_ERR("invalid contact uri\n");
goto error;
}
if(c->uri.len == 1) {
if(c->uri.s[0] == '*') {
if(star == 1) {
LM_ERR("too many star contacts - index %d\n", n);
goto error;
} else {
star = 1;
}
} else {
LM_ERR("contact uri size 1 is too short - index %d\n", n);
goto error;
}
} else if(c->uri.len < 3) {
/* minimum length 's:a' (s - schema; a - address) */
LM_ERR("contact uri size %d is too short - index %d\n", n,
c->uri.len);
goto error;
}
if(_s->len == 0)
goto ok;
@ -301,7 +325,12 @@ int parse_contacts(str *_s, contact_t **_c)
c->next = *_c;
*_c = c;
c = NULL;
n++;
if(n > KSR_MAX_CONTACTS) {
LM_ERR("too many contacts: %d\n", n);
goto error;
}
if(_s->len == 0) {
LM_ERR("text after comma missing\n");
goto error;

@ -444,20 +444,28 @@ int print_rr_body(
i = (nb_recs == NULL) ? 0 : *nb_recs;
while(i < n) {
memcpy(cp, route[i].s, route[i].len);
cp += route[i].len;
if(++i < n)
*(cp++) = ',';
if(route[i].s != NULL) {
memcpy(cp, route[i].s, route[i].len);
cp += route[i].len;
if(++i < n)
*(cp++) = ',';
} else {
i++;
}
}
} else {
i = (nb_recs == NULL) ? n - 1 : (n - *nb_recs - 1);
while(i >= 0) {
memcpy(cp, route[i].s, route[i].len);
cp += route[i].len;
if(i-- > 0)
*(cp++) = ',';
if(route[i].s != NULL) {
memcpy(cp, route[i].s, route[i].len);
cp += route[i].len;
if(i-- > 0)
*(cp++) = ',';
} else {
i--;
}
}
}
oroute->len = cp - start;

@ -510,6 +510,8 @@ char *pp_defexp_eval(char *exval, int exlen, int qmode)
LM_DBG("expression string result: [%s]\n", result->param.stz.sval);
sval.s = result->param.stz.sval;
sval.len = strlen(result->param.stz.sval);
} else {
goto done;
}
if(qmode == 1) {

@ -1526,8 +1526,8 @@ size_t create_srv_pref_list(char *proto, struct dns_srv_proto *list)
if(naptr_proto_supported(i) == 0) {
continue;
} else {
list[i - 1].proto_pref = tmp.proto_pref;
list[i - 1].proto = i;
list[list_len].proto_pref = tmp.proto_pref;
list[list_len].proto = i;
list_len++;
}
};

@ -0,0 +1,294 @@
/*
* Copyright (C) 2024 Chan Shih-Ping
*
* This file is part of Kamailio, a free SIP server.
*
* 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.
*/
/*
* A set of helpers to run functions in threads.
*
* This is not a thread pool implementation -
* - it runs functions in a run-once thread to avoid
* creating thread-locals in the calling thread.
*
* Primary use case: to init libssl in a separate thread
*/
#include <pthread.h>
#include "./globals.h"
/*
* prototype: void *fn(void *arg) { ... }
*/
typedef void *(*_thread_proto)(void *);
#ifndef KSR_RTHREAD_SKIP_P
static void *run_threadP(_thread_proto fn, void *arg)
{
#ifdef USE_TLS
pthread_t tid;
void *ret = NULL;
if(likely(ksr_tls_threads_mode == 0 || ksr_tls_threads_mode == 2
|| (ksr_tls_threads_mode == 1 && process_no > 0))) {
return fn(arg);
}
pthread_create(&tid, NULL, fn, arg);
pthread_join(tid, &ret);
return ret;
#else
return fn(arg);
#endif /* USE_TLS */
}
#endif
/*
* prototype: void *fn(void *arg1, int arg2) { ... }
*/
#ifdef KSR_RTHREAD_NEED_PI
typedef void *(*_thread_protoPI)(void *, int);
struct _thread_argsPI
{
_thread_protoPI fn;
void *tptr;
int tint;
};
static void *run_thread_wrapPI(struct _thread_argsPI *args)
{
return (*args->fn)(args->tptr, args->tint);
}
static void *run_threadPI(_thread_protoPI fn, void *arg1, int arg2)
{
#ifdef USE_TLS
pthread_t tid;
void *ret = NULL;
if(likely(ksr_tls_threads_mode == 0 || ksr_tls_threads_mode == 2
|| (ksr_tls_threads_mode == 1 && process_no > 0))) {
return fn(arg1, arg2);
}
pthread_create(&tid, NULL, (_thread_proto)&run_thread_wrapPI,
&(struct _thread_argsPI){fn, arg1, arg2});
pthread_join(tid, &ret);
return ret;
#else
return fn(arg1, arg2);
#endif
}
#endif
/*
* prototype: void fn(void) { ... }
*/
#ifdef KSR_RTHREAD_NEED_V
typedef void (*_thread_protoV)(void);
struct _thread_argsV
{
_thread_protoV fn;
};
static void *run_thread_wrapV(struct _thread_argsV *args)
{
(*args->fn)();
return NULL;
}
static void run_threadV(_thread_protoV fn)
{
#ifdef USE_TLS
pthread_t tid;
if(likely(ksr_tls_threads_mode == 0 || ksr_tls_threads_mode == 2
|| (ksr_tls_threads_mode == 1 && process_no > 0))) {
fn();
return;
}
pthread_create(&tid, NULL, (_thread_proto)run_thread_wrapV,
&(struct _thread_argsV){fn});
pthread_join(tid, NULL);
#else
fn();
#endif
}
#endif
/*
* prototype: int fn(void *, void *) { ... }
*/
#ifdef KSR_RTHREAD_NEED_4PP
typedef int (*_thread_proto4PP)(void *, void *);
struct _thread_args4PP
{
_thread_proto4PP fn;
void *arg1;
void *arg2;
int *ret;
};
static void *run_thread_wrap4PP(struct _thread_args4PP *args)
{
*args->ret = (*args->fn)(args->arg1, args->arg2);
return NULL;
}
static int run_thread4PP(_thread_proto4PP fn, void *arg1, void *arg2)
{
#ifdef USE_TLS
pthread_t tid;
int ret = 0;
if(likely(ksr_tls_threads_mode == 0 || ksr_tls_threads_mode == 2
|| (ksr_tls_threads_mode == 1 && process_no > 0))) {
return fn(arg1, arg2);
}
pthread_create(&tid, NULL, (_thread_proto)run_thread_wrap4PP,
&(struct _thread_args4PP){fn, arg1, arg2, &ret});
pthread_join(tid, NULL);
return ret;
#else
return fn(arg1, arg2);
#endif
}
#endif
/*
* prototype: void fn(void *) { ... }
*/
#ifdef KSR_RTHREAD_NEED_0P
typedef void (*_thread_proto0P)(void *);
struct _thread_args0P
{
_thread_proto0P fn;
void *arg1;
};
static void *run_thread_wrap0P(struct _thread_args0P *args)
{
(*args->fn)(args->arg1);
return NULL;
}
static void run_thread0P(_thread_proto0P fn, void *arg1)
{
#ifdef USE_TLS
pthread_t tid;
if(likely(ksr_tls_threads_mode == 0 || ksr_tls_threads_mode == 2
|| (ksr_tls_threads_mode == 1 && process_no > 0))) {
fn(arg1);
return;
}
pthread_create(&tid, NULL, (_thread_proto)run_thread_wrap0P,
&(struct _thread_args0P){fn, arg1});
pthread_join(tid, NULL);
#else
fn(arg1)
#endif
}
#endif
/*
* prototype:
* db_unixodbc_query(const db1_con_t *_h, const db_key_t *_k,
* const db_op_t *_op, const db_val_t *_v, const db_key_t *_c,
* const int _n, const int _nc, const db_key_t _o, db1_res_t **_r)
*/
#ifdef KSR_RTHREAD_NEED_4P5I2P2
typedef int (*_thread_proto4P5I2P2)(
void *, void *, void *, void *, void *, int, int, void *, void *);
struct _thread_args4P5I2P2
{
_thread_proto4P5I2P2 fn;
void *arg1;
void *arg2;
void *arg3;
void *arg4;
void *arg5;
int arg6;
int arg7;
void *arg8;
void *arg9;
int *ret;
};
static void *run_thread_wrap4P5I2P2(struct _thread_args4P5I2P2 *args)
{
*args->ret = (*args->fn)(args->arg1, args->arg2, args->arg3, args->arg4,
args->arg5, args->arg6, args->arg7, args->arg8, args->arg9);
return NULL;
}
static int run_thread4P5I2P2(_thread_proto4P5I2P2 fn, void *arg1, void *arg2,
void *arg3, void *arg4, void *arg5, int arg6, int arg7, void *arg8,
void *arg9)
{
#ifdef USE_TLS
pthread_t tid;
int ret = 0;
if(likely(ksr_tls_threads_mode == 0 || ksr_tls_threads_mode == 2
|| (ksr_tls_threads_mode == 1 && process_no > 0))) {
return fn(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
}
pthread_create(&tid, NULL, (_thread_proto)run_thread_wrap4P5I2P2,
&(struct _thread_args4P5I2P2){fn, arg1, arg2, arg3, arg4, arg5,
arg6, arg7, arg8, arg9, &ret});
pthread_join(tid, NULL);
return ret;
#else
return fn(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
#endif
}
#endif
/*
* prototype: CURLcode curl_global_init(long flags) { ... }
*/
#ifdef KSR_RTHREAD_NEED_4L
typedef int (*_thread_proto4L)(long);
struct _thread_args4L
{
_thread_proto4L fn;
long arg1;
int *ret;
};
static void *run_thread_wrap4L(struct _thread_args4L *args)
{
*args->ret = (*args->fn)(args->arg1);
return NULL;
}
static int run_thread4L(_thread_proto4L fn, long arg1)
{
#ifdef USE_TLS
pthread_t tid;
int ret = 0;
if(likely(ksr_tls_threads_mode == 0 || ksr_tls_threads_mode == 2
|| (ksr_tls_threads_mode == 1 && process_no > 0))) {
return fn(arg1);
}
pthread_create(&tid, NULL, (_thread_proto)run_thread_wrap4L,
&(struct _thread_args4L){fn, arg1, &ret});
pthread_join(tid, NULL);
return ret;
#else
return fn(arg1)
#endif
}
#endif

@ -1387,7 +1387,7 @@ int select_ip_port(str *res, select_t *s, struct sip_msg *msg)
if(param & SEL_PROTO) {
switch(msg->rcv.proto) {
case PROTO_NONE:
proto_str.s = 0;
proto_str.s = "";
proto_str.len = 0;
break;
@ -1411,6 +1411,16 @@ int select_ip_port(str *res, select_t *s, struct sip_msg *msg)
proto_str.len = 4;
break;
case PROTO_WS:
proto_str.s = "ws";
proto_str.len = 2;
break;
case PROTO_WSS:
proto_str.s = "wss";
proto_str.len = 3;
break;
default:
LM_ERR("Unknown transport protocol\n");
return -1;

@ -203,7 +203,7 @@ int fix_switch(struct action *t)
return E_BUG;
}
if(rval_expr_eval_long(0, 0, &c->label.match_int, c->ct_rve) < 0) {
LM_ERR("case expression (%d,%d) has non-interger type\n",
LM_ERR("case expression (%d,%d) has non-integer type\n",
c->ct_rve->fpos.s_line, c->ct_rve->fpos.s_col);
return E_BUG;
}

@ -407,7 +407,8 @@ struct tcp_connection *tcpconn_get(int id, struct ip_addr *ip, int port,
union sockaddr_union *local_addr, ticks_t timeout);
struct tcp_connection *tcpconn_lookup(int id, struct ip_addr *ip, int port,
union sockaddr_union *local_addr, int try_local_port, ticks_t timeout);
union sockaddr_union *local_addr, int try_local_port, ticks_t timeout,
sip_protos_t proto);
typedef struct tcp_event_info
{
@ -421,6 +422,7 @@ typedef struct tcp_event_info
typedef struct tcp_closed_event_info
{
enum tcp_closed_reason reason;
int id;
struct tcp_connection *con;
} tcp_closed_event_info_t;
@ -432,4 +434,6 @@ typedef struct ws_event_info
int id;
} ws_event_info_t;
tcp_connection_t *ksr_tcpcon_evcb_get(void);
#endif

@ -1693,12 +1693,12 @@ void tcpconn_rm(struct tcp_connection *c)
/* finds a connection, if id=0 uses the ip addr, port, local_ip and local port
* (host byte order) and tries to find the connection that matches all of
* them. Wild cards can be used for local_ip and local_port (a 0 filled
* ip address and/or a 0 local port).
* them. Wild cards can be used for local_ip, local_port and proto (a 0 filled
* ip address and/or a 0 local port and/or PROTO_NONE).
* WARNING: unprotected (locks) use tcpconn_get unless you really
* know what you are doing */
struct tcp_connection *_tcpconn_find(
int id, struct ip_addr *ip, int port, struct ip_addr *l_ip, int l_port)
struct tcp_connection *_tcpconn_find(int id, struct ip_addr *ip, int port,
struct ip_addr *l_ip, int l_port, sip_protos_t proto)
{
struct tcp_connection *c;
@ -1737,7 +1737,8 @@ struct tcp_connection *_tcpconn_find(
&& (ip_addr_cmp(ip, &a->parent->rcv.src_ip))
&& (is_local_ip_any
|| ip_addr_cmp(l_ip, &a->parent->rcv.dst_ip)
|| ip_addr_cmp(l_ip, &a->parent->cinfo.dst_ip))) {
|| ip_addr_cmp(l_ip, &a->parent->cinfo.dst_ip))
&& (proto == PROTO_NONE || a->parent->rcv.proto == proto)) {
LM_DBG("found connection by peer address (id: %d)\n",
a->parent->id);
return a->parent;
@ -1749,16 +1750,16 @@ struct tcp_connection *_tcpconn_find(
/**
* find if a tcp connection exits by id or remote+local address/port
* find if a tcp connection exits by id or remote+local address/port and protocol
* - return: 1 if found; 0 if not found
*/
int tcpconn_exists(int conn_id, ip_addr_t *peer_ip, int peer_port,
ip_addr_t *local_ip, int local_port)
ip_addr_t *local_ip, int local_port, sip_protos_t proto)
{
tcp_connection_t *c;
TCPCONN_LOCK;
c = _tcpconn_find(conn_id, peer_ip, peer_port, local_ip, local_port);
c = _tcpconn_find(conn_id, peer_ip, peer_port, local_ip, local_port, proto);
TCPCONN_UNLOCK;
if(c) {
return 1;
@ -1769,12 +1770,14 @@ int tcpconn_exists(int conn_id, ip_addr_t *peer_ip, int peer_port,
/* TCP connection find with locks and timeout
* - local_addr contains the desired local ip:port. If null any local address
* will be used. IN*ADDR_ANY or 0 port are wild cards.
* - proto is the protocol to match (PROTO_NONE for any)
* - try_local_port makes the search use it first, instead of port from local_addr
* If found, the connection's reference counter will be incremented, you might
* want to decrement it after use.
*/
struct tcp_connection *tcpconn_lookup(int id, struct ip_addr *ip, int port,
union sockaddr_union *local_addr, int try_local_port, ticks_t timeout)
union sockaddr_union *local_addr, int try_local_port, ticks_t timeout,
sip_protos_t proto)
{
struct tcp_connection *c;
struct ip_addr local_ip;
@ -1793,10 +1796,10 @@ struct tcp_connection *tcpconn_lookup(int id, struct ip_addr *ip, int port,
}
TCPCONN_LOCK;
if(likely(try_local_port != 0) && likely(local_port == 0)) {
c = _tcpconn_find(id, ip, port, &local_ip, try_local_port);
c = _tcpconn_find(id, ip, port, &local_ip, try_local_port, proto);
}
if(unlikely(c == NULL)) {
c = _tcpconn_find(id, ip, port, &local_ip, local_port);
c = _tcpconn_find(id, ip, port, &local_ip, local_port, proto);
}
if(likely(c)) {
atomic_inc(&c->refcnt);
@ -1821,7 +1824,7 @@ struct tcp_connection *tcpconn_lookup(int id, struct ip_addr *ip, int port,
struct tcp_connection *tcpconn_get(int id, struct ip_addr *ip, int port,
union sockaddr_union *local_addr, ticks_t timeout)
{
return tcpconn_lookup(id, ip, port, local_addr, 0, timeout);
return tcpconn_lookup(id, ip, port, local_addr, 0, timeout, PROTO_NONE);
}
@ -1947,7 +1950,7 @@ int tcpconn_add_alias(int id, int port, int proto)
port = port ? port : ((proto == PROTO_TLS) ? SIPS_PORT : SIP_PORT);
TCPCONN_LOCK;
/* check if alias already exists */
c = _tcpconn_find(id, 0, 0, 0, 0);
c = _tcpconn_find(id, 0, 0, 0, 0, PROTO_NONE);
if(likely(c)) {
ip_addr_mk_any(c->rcv.src_ip.af, &zero_ip);
alias_flags = cfg_get(tcp, tcp_cfg, alias_flags);
@ -2088,8 +2091,8 @@ int tcp_send(struct dest_info *dst, union sockaddr_union *from, const char *buf,
if(likely(port)) {
su2ip_addr(&ip, &dst->to);
if(tcp_connection_match == TCPCONN_MATCH_STRICT) {
c = tcpconn_lookup(
dst->id, &ip, port, from, try_local_port, con_lifetime);
c = tcpconn_lookup(dst->id, &ip, port, from, try_local_port,
con_lifetime, dst->proto);
} else {
c = tcpconn_get(dst->id, &ip, port, from, con_lifetime);
}
@ -2105,8 +2108,8 @@ int tcp_send(struct dest_info *dst, union sockaddr_union *from, const char *buf,
if(likely(port)) {
/* try again w/o id */
if(tcp_connection_match == TCPCONN_MATCH_STRICT) {
c = tcpconn_lookup(
0, &ip, port, from, try_local_port, con_lifetime);
c = tcpconn_lookup(0, &ip, port, from, try_local_port,
con_lifetime, dst->proto);
} else {
c = tcpconn_get(0, &ip, port, from, con_lifetime);
}
@ -3650,6 +3653,12 @@ again:
return n;
}
static tcp_connection_t *_ksr_tcpcon_evcb = NULL;
tcp_connection_t *ksr_tcpcon_evcb_get(void)
{
return _ksr_tcpcon_evcb;
}
static int tcp_emit_closed_event(struct tcp_connection *con)
{
@ -3669,9 +3678,12 @@ static int tcp_emit_closed_event(struct tcp_connection *con)
if(likely(sr_event_enabled(SREV_TCP_CLOSED))) {
memset(&tev, 0, sizeof(tcp_closed_event_info_t));
tev.reason = reason;
tev.id = con->id;
tev.con = con;
evp.data = (void *)(&tev);
_ksr_tcpcon_evcb = con;
ret = sr_event_exec(SREV_TCP_CLOSED, &evp);
_ksr_tcpcon_evcb = NULL;
} else {
LM_DBG("no callback registering for handling TCP closed event\n");
}
@ -4478,7 +4490,8 @@ static inline int handle_new_connect(struct socket_info *si)
if(likely(tcpconn)) {
if(tcp_accept_unique) {
if(tcpconn_exists(0, &tcpconn->rcv.dst_ip, tcpconn->rcv.dst_port,
&tcpconn->rcv.src_ip, tcpconn->rcv.src_port)) {
&tcpconn->rcv.src_ip, tcpconn->rcv.src_port,
si->proto)) {
LM_ERR("duplicated connection by local and remote addresses\n");
_tcpconn_free(tcpconn);
tcp_safe_close(new_sock);
@ -5430,7 +5443,8 @@ int wss_send(dest_info_t *dst, const char *buf, unsigned len)
su2ip_addr(&ip, &dst->to);
if(tcp_connection_match == TCPCONN_MATCH_STRICT) {
con = tcpconn_lookup(dst->id, &ip, port, from,
(dst->send_sock) ? dst->send_sock->port_no : 0, 0);
(dst->send_sock) ? dst->send_sock->port_no : 0, 0,
dst->proto);
} else {
con = tcpconn_get(dst->id, &ip, port, from, 0);
}

@ -312,7 +312,7 @@ static inline char *int2strbuf(unsigned long l, char *r, int r_size, int *len)
}
extern char ut_buf_int2str[INT2STR_MAX_LEN];
/** interger(long) to string conversion.
/** integer(long) to string conversion.
* This version uses a static buffer (shared with sint2str()).
* WARNING: other function calls might overwrite the static buffer, so
* either always save the result immediately or use int2strbuf(...).

@ -326,8 +326,9 @@ int tcp_disable = 0; /* 1 if tcp is disabled */
int tls_disable = 0; /* tls enabled by default */
#else
int tls_disable = 1; /* tls disabled by default */
#endif /* CORE_TLS */
#endif /* USE_TLS */
#endif /* CORE_TLS */
int ksr_tls_threads_mode = 0; /* threads execution mode for tls with libssl */
#endif /* USE_TLS */
#ifdef USE_SCTP
int sctp_children_no = 0;
int sctp_disable = 2; /* 1 if sctp is disabled, 2 if auto mode, 0 enabled */

@ -127,8 +127,10 @@ struct acc_extra *parse_acc_extra(char *extra_str)
foo = s;
while(*s && !isspace((int)*s) && EQUAL != *s)
s++;
if(*s == 0)
if(*s == 0) {
LM_ERR("unexpected end of string\n");
goto parse_error;
}
if(*s == EQUAL) {
extra->name.len = (s++) - foo;
} else {
@ -136,8 +138,10 @@ struct acc_extra *parse_acc_extra(char *extra_str)
/* skip spaces */
while(*s && isspace((int)*s))
s++;
if(*s != EQUAL)
if(*s != EQUAL) {
LM_ERR("unexpected char '%c' instead of '='\n", *s);
goto parse_error;
}
s++;
}
extra->name.s = foo;
@ -149,15 +153,19 @@ struct acc_extra *parse_acc_extra(char *extra_str)
/* get value type */
stmp.s = s;
stmp.len = strlen(s);
if((foo = pv_parse_spec(&stmp, &extra->spec)) == 0)
if((foo = pv_parse_spec(&stmp, &extra->spec)) == 0) {
LM_ERR("failed to parse variable name\n");
goto parse_error;
}
s = foo;
/* skip spaces */
while(*s && isspace((int)*s))
s++;
if(*s && (*(s++) != SEPARATOR || *s == 0))
if(*s && (*(s++) != SEPARATOR || *s == 0)) {
LM_ERR("unexpected char at end of name=var group\n");
goto parse_error;
}
}
/* go throught all extras and make the names null terminated */

@ -49,37 +49,44 @@ static int blst_rpl_set_ignore_f(struct sip_msg *, char *, char *);
static int blst_rpl_clear_ignore_f(struct sip_msg *, char *, char *);
static cmd_export_t cmds[] = {{"blst_add", blst_add0_f, 0, 0, 0, ANY_ROUTE},
{"blst_add", blst_add1_f, 1, fixup_var_int_1, 0, ANY_ROUTE},
{"blst_add_retry_after", blst_add_retry_after_f, 2, fixup_var_int_12, 0,
/* clang-format off */
static cmd_export_t cmds[] = {
{"blst_add", blst_add0_f, 0, 0, 0, ANY_ROUTE},
{"blst_add", blst_add1_f, 1, fixup_var_int_1, 0, ANY_ROUTE},
{"blst_add_retry_after", blst_add_retry_after_f, 2, fixup_var_int_12, 0,
ANY_ROUTE},
{"blst_del", blst_del_f, 0, 0, 0, ANY_ROUTE},
{"blst_is_blocklisted", blst_is_blocklisted_f, 0, 0, 0, ANY_ROUTE},
{"blst_set_ignore", blst_set_ignore_f, 0, 0, 0, ANY_ROUTE},
{"blst_set_ignore", blst_set_ignore_f, 1, fixup_var_int_1, 0,
{"blst_del", blst_del_f, 0, 0, 0, ANY_ROUTE},
{"blst_is_blocklisted", blst_is_blocklisted_f, 0, 0, 0, ANY_ROUTE},
{"blst_set_ignore", blst_set_ignore_f, 0, 0, 0, ANY_ROUTE},
{"blst_set_ignore", blst_set_ignore_f, 1, fixup_var_int_1, 0,
ANY_ROUTE},
{"blst_clear_ignore", blst_clear_ignore_f, 0, 0, 0, ANY_ROUTE},
{"blst_clear_ignore", blst_clear_ignore_f, 1, fixup_var_int_1, 0,
{"blst_clear_ignore", blst_clear_ignore_f, 0, 0, 0, ANY_ROUTE},
{"blst_clear_ignore", blst_clear_ignore_f, 1, fixup_var_int_1, 0,
ANY_ROUTE},
{"blst_rpl_set_ignore", blst_rpl_set_ignore_f, 0, 0, 0, ANY_ROUTE},
{"blst_rpl_set_ignore", blst_rpl_set_ignore_f, 1, fixup_var_int_1, 0,
{"blst_rpl_set_ignore", blst_rpl_set_ignore_f, 0, 0, 0, ANY_ROUTE},
{"blst_rpl_set_ignore", blst_rpl_set_ignore_f, 1, fixup_var_int_1, 0,
ANY_ROUTE},
{"blst_rpl_clear_ignore", blst_rpl_clear_ignore_f, 0, 0, 0, ANY_ROUTE},
{"blst_rpl_clear_ignore", blst_rpl_clear_ignore_f, 1, fixup_var_int_1,
{"blst_rpl_clear_ignore", blst_rpl_clear_ignore_f, 0, 0, 0, ANY_ROUTE},
{"blst_rpl_clear_ignore", blst_rpl_clear_ignore_f, 1, fixup_var_int_1,
0, ANY_ROUTE},
{0, 0, 0, 0, 0, 0}};
{0, 0, 0, 0, 0, 0}
};
static param_export_t params[] = {{0, 0, 0}}; /* no params */
struct module_exports exports = {
"blst", DEFAULT_DLFLAGS, /* dlopen flags */
cmds, params, 0, /* RPC methods */
0, /* pseudo-variables exports */
0, /* response function */
0, /* module initialization function */
0, /* per-child init function */
0 /* destroy function */
"blst",
DEFAULT_DLFLAGS, /* dlopen flags */
cmds,
params,
0, /* RPC methods */
0, /* pseudo-variables exports */
0, /* response function */
0, /* module initialization function */
0, /* per-child init function */
0 /* destroy function */
};
/* clang-format on */
/**

@ -444,7 +444,7 @@ static int corex_dns_cache_param_add(str *pval)
}
} else if(pit->name.len == 8
&& strncasecmp(pit->name.s, "priority", 8) == 0) {
if(dns_flags == 0) {
if(dns_priority == 0) {
if(str2sint(&pit->body, &dns_priority) < 0) {
LM_ERR("invalid priority: %.*s\n", pit->body.len,
pit->body.s);
@ -453,7 +453,7 @@ static int corex_dns_cache_param_add(str *pval)
}
} else if(pit->name.len == 6
&& strncasecmp(pit->name.s, "weight", 6) == 0) {
if(dns_flags == 0) {
if(dns_weight == 0) {
if(str2sint(&pit->body, &dns_weight) < 0) {
LM_ERR("invalid weight: %.*s\n", pit->body.len,
pit->body.s);
@ -462,7 +462,7 @@ static int corex_dns_cache_param_add(str *pval)
}
} else if(pit->name.len == 4
&& strncasecmp(pit->name.s, "port", 4) == 0) {
if(dns_flags == 0) {
if(dns_port == 0) {
if(str2sint(&pit->body, &dns_port) < 0) {
LM_ERR("invalid port: %.*s\n", pit->body.len, pit->body.s);
return -1;

@ -719,10 +719,12 @@ inline static unsigned char *binrpc_read_record(struct binrpc_parse_ctx *ctx,
*err = E_BINRPC_MORE_DATA;
goto error;
}
if((v->type != type) && (v->type != BINRPC_T_ALL)) {
goto error_type;
if(!(v->type == BINRPC_T_DOUBLE && type == BINRPC_T_INT)) {
if((v->type != type) && (v->type != BINRPC_T_ALL)) {
goto error_type;
}
v->type = type;
}
v->type = type;
switch(type) {
case BINRPC_T_STRUCT:
if(ctx->in_struct) {
@ -779,7 +781,12 @@ inline static unsigned char *binrpc_read_record(struct binrpc_parse_ctx *ctx,
case BINRPC_T_INT:
if(ctx->in_struct && smode == 0)
goto error_record;
p = binrpc_read_int(&v->u.intval, len, p, end, err);
if(v->type == BINRPC_T_DOUBLE) {
p = binrpc_read_int(&tmp, len, p, end, err);
v->u.fval = tmp;
} else {
p = binrpc_read_int(&v->u.intval, len, p, end, err);
}
break;
case BINRPC_T_STR:
if(ctx->in_struct && smode == 0)

@ -736,6 +736,7 @@ int fifo_process(char *msg_buf, int size, int *bytes_needed, void *sh,
static rpc_ctx_t context;
unsigned int rdata;
log_prefix_set(NULL);
DBG("process_fifo: called with %d bytes, offset %d: %.*s\n", size,
(int)(long)*saved_state, size, msg_buf);
/* search for the end of the request (\n\r) */

@ -26,6 +26,7 @@
#include "../../core/mem/mem.h"
#include "../../core/rpc.h" /* who & ls rpcs */
#include "../../core/ut.h"
#include "../../core/action.h"
#include "../../core/cfg/cfg_struct.h"
#include "ctrl_socks.h"
@ -203,16 +204,14 @@ void io_listen_loop(int fd_no, struct ctrl_socket *cs_lst)
if(poll_err || (poll_method == 0)) {
poll_method = choose_poll_method();
if(poll_err) {
LOG(L_ERR, "ERROR: io_listen_loop: %s, using %s instead\n",
poll_err, poll_method_name(poll_method));
LOG(L_ERR, "%s, using %s instead\n", poll_err,
poll_method_name(poll_method));
} else {
LOG(L_INFO,
"io_listen_loop: using %s as the io watch method"
" (auto detected)\n",
LOG(L_INFO, "using %s as the io watch method (auto detected)\n",
poll_method_name(poll_method));
}
} else {
LOG(L_INFO, "io_listen_loop: using %s io watch method (config)\n",
LOG(L_INFO, "using %s io watch method (config)\n",
poll_method_name(poll_method));
}
@ -235,24 +234,20 @@ void io_listen_loop(int fd_no, struct ctrl_socket *cs_lst)
cs->data =
s_conn_new(cs->fd, cs, &cs->u); /* reuse stream conn */
if(cs->data == 0) {
LOG(L_ERR, "ERROR: io_listen_loop: out of memory\n");
LOG(L_ERR, "out of memory\n");
goto error;
}
break;
#endif
case UNKNOWN_SOCK:
LOG(L_CRIT,
"BUG: io_listen_loop: bad control socket transport"
" %d\n",
LOG(L_CRIT, "BUG: bad control socket transport %d\n",
cs->transport);
goto error;
}
DBG("io_listen_loop: adding socket %d, type %d, transport"
" %d (%s)\n",
cs->fd, type, cs->transport, cs->name);
DBG("adding socket %d, type %d, transport %d (%s)\n", cs->fd, type,
cs->transport, cs->name);
if(io_watch_add(&ctl_io_h, cs->fd, POLLIN, type, cs) < 0) {
LOG(L_CRIT, "ERROR: io_listen_loop: init: failed to add"
"listen socket to the fd list\n");
LOG(L_CRIT, "init: failed to add listen socket to the fd list\n");
goto error;
}
}
@ -309,16 +304,14 @@ void io_listen_loop(int fd_no, struct ctrl_socket *cs_lst)
break;
#endif
default:
LOG(L_CRIT,
"BUG: io_listen_loop: no support for poll method "
" %s (%d)\n",
LOG(L_CRIT, "BUG: no support for poll method %s (%d)\n",
poll_method_name(ctl_io_h.poll_method),
ctl_io_h.poll_method);
goto error;
}
/* should never reach this point under normal (non-error) circumstances */
error:
LOG(L_CRIT, "ERROR: io_listen_loop exiting ...\n");
LOG(L_CRIT, "exiting ...\n");
}
@ -346,6 +339,7 @@ static int handle_ctrl_dgram(struct ctrl_socket *cs)
struct send_handle sh;
void *saved_state;
log_prefix_set(NULL);
saved_state = 0; /* we get always a new datagram */
sh.fd = cs->fd;
sh.type = S_DISCONNECTED;
@ -361,11 +355,11 @@ again:
} else if(errno == EINTR) {
goto again;
}
LOG(L_ERR, "ERROR; handle_ctrl_dgram: recvfrom on %s: [%d] %s\n",
cs->name, errno, strerror(errno));
LOG(L_ERR, "recvfrom on %s: [%d] %s\n", cs->name, errno,
strerror(errno));
goto error;
}
DBG("handle_ctrl_dgram: new packet on %s\n", cs->name);
DBG("new packet on %s\n", cs->name);
ret = 1;
#ifdef USE_FIFO
if(cs->p_proto == P_FIFO)
@ -414,24 +408,19 @@ again:
} else if(errno == EINTR) {
goto again;
}
LOG(L_ERR,
"ERROR: io_listen: handle_new_connect:"
" error while accepting connection on %s: [%d] %s\n",
LOG(L_ERR, " error while accepting connection on %s: [%d] %s\n",
cs->name, errno, strerror(errno));
goto error;
}
ret = 1;
if(io_read_connections >= MAX_IO_READ_CONNECTIONS) {
LOG(L_ERR,
"ERROR: io listen: maximum number of connections"
" exceeded: %d/%d\n",
LOG(L_ERR, "maximum number of connections exceeded: %d/%d\n",
io_read_connections, MAX_IO_READ_CONNECTIONS);
close(new_sock);
goto skip; /* success because accept was successful */
}
if(init_sock_opt(new_sock, cs->transport) < 0) {
LOG(L_ERR, "ERROR: io listen: handle_new_connect:"
" init_sock_opt failed\n");
LOG(L_ERR, "init_sock_opt failed\n");
close(new_sock);
goto skip;
}
@ -441,14 +430,12 @@ again:
s_conn_add(s_conn);
io_watch_add(&ctl_io_h, s_conn->fd, POLLIN, F_T_READ_STREAM, s_conn);
} else {
LOG(L_ERR, "ERROR: io listen: handle_new_connect:"
" s_conn_new failed\n");
LOG(L_ERR, "s_conn_new failed\n");
close(new_sock);
goto skip;
}
io_read_connections++;
DBG("handle_stream read: new connection (%d) on %s\n", io_read_connections,
cs->name);
DBG("new connection (%d) on %s\n", io_read_connections, cs->name);
skip:
return ret;
error:
@ -486,8 +473,9 @@ static int handle_stream_read(struct stream_connection *s_c, int idx)
sh.from_len = 0;
r = &s_c->req;
bytes_free = STREAM_BUF_SIZE - (int)(r->end - r->buf);
log_prefix_set(NULL);
if(bytes_free == 0) {
LOG(L_ERR, "ERROR: handle_stream_read: buffer overrun\n");
LOG(L_ERR, "buffer overrun\n");
goto close_connection;
}
again:
@ -495,10 +483,14 @@ again:
if(bytes_read == -1) {
if((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
goto no_read; /* nothing has been read */
} else if(errno == EINTR)
} else if(errno == EINTR) {
goto again;
LOG(L_ERR, "ERROR: handle_stream_read: error reading: %s [%d]\n",
strerror(errno), errno);
}
if(errno == ECONNRESET) {
LOG(L_INFO, "error reading: %s [%d]\n", strerror(errno), errno);
} else {
LOG(L_ERR, "error reading: %s [%d]\n", strerror(errno), errno);
}
goto error_read;
} else if(bytes_read == 0) { /* eof */
DBG("handle_stream read: eof on %s\n", s_c->parent->name);
@ -530,7 +522,7 @@ again:
r->bytes_to_go = bytes_needed;
if(bytes_needed > 0) {
if(bytes_read == 0) { /*want more bytes, but we have eof*/
LOG(L_ERR, "ERROR: handle_stream_read: unexpected EOF\n");
LOG(L_ERR, "unexpected EOF\n");
goto close_connection;
}
break; /* no more read bytes ready for processing */
@ -604,7 +596,7 @@ static int handle_fifo_read(struct ctrl_socket *cs, int idx)
r = &(sc->req);
bytes_free = STREAM_BUF_SIZE - (int)(r->end - r->buf);
if(bytes_free == 0) {
LOG(L_ERR, "ERROR: handle_stream_read: buffer overrun\n");
LOG(L_ERR, "buffer overrun\n");
goto error;
}
again:
@ -614,11 +606,14 @@ again:
goto no_read; /* nothing has been read */
} else if(errno == EINTR)
goto again;
LOG(L_ERR, "ERROR: handle_fifo_read: error reading: %s [%d]\n",
strerror(errno), errno);
if(errno == ECONNRESET) {
LOG(L_INFO, "error reading: %s [%d]\n", strerror(errno), errno);
} else {
LOG(L_ERR, "error reading: %s [%d]\n", strerror(errno), errno);
}
goto error_read;
} else if(bytes_read == 0) { /* eof */
DBG("handle_fifo_read: eof on %s\n", cs->name);
DBG("eof on %s\n", cs->name);
}
r->end += bytes_read;
if(bytes_read && (bytes_read < r->bytes_to_go)) {
@ -637,7 +632,7 @@ again:
r->bytes_to_go = bytes_needed;
if(bytes_needed > 0) {
if(bytes_read == 0) { /*want more bytes, but we have eof*/
LOG(L_ERR, "ERROR: handle_fifo_read: unexpected EOF\n");
LOG(L_ERR, "unexpected EOF\n");
goto discard; /* discard buffered contents */
}
break; /* no more read bytes ready for processing */
@ -647,7 +642,7 @@ again:
if(bytes_processed == 0) {
/* nothing processed, nothing needed, no error - looks like
* a bug */
LOG(L_ERR, "ERROR: handle_fifo_read: unexpected return\n");
LOG(L_ERR, "unexpected return\n");
goto discard;
}
} while(r->proc < r->end);
@ -722,11 +717,10 @@ inline static int handle_io(struct fd_map *fm, short events, int idx)
break;
#endif
case F_T_RESERVED:
LOG(L_CRIT, "BUG: io listen handle_io: empty fd map\n");
LOG(L_CRIT, "empty fd map\n");
goto error;
default:
LOG(L_CRIT, "BUG: io listen handle_io: unknown fd type %d\n",
fm->type);
LOG(L_CRIT, "unknown fd type %d\n", fm->type);
goto error;
}
return ret;

@ -32,6 +32,7 @@ Daniel-Constantin Mierla
3.5. insert_delayed (integer)
3.6. update_affected_found (integer)
3.7. opt_ssl_mode (integer)
3.8. opt_ssl_ca (string)
4. Functions
5. Installation
@ -46,9 +47,10 @@ Daniel-Constantin Mierla
1.5. Set insert_delayed parameter
1.6. Set update_affected_found parameter
1.7. Set opt_ssl_mode parameter
1.8. Set a my.cnf group in db_url parameter
1.9. Adding a kamailio group to my.cnf
1.10. Using [client] and specific group
1.8. Set opt_ssl_ca parameter
1.9. Set a my.cnf group in db_url parameter
1.10. Adding a kamailio group to my.cnf
1.11. Using [client] and specific group
Chapter 1. Admin Guide
@ -69,6 +71,7 @@ Chapter 1. Admin Guide
3.5. insert_delayed (integer)
3.6. update_affected_found (integer)
3.7. opt_ssl_mode (integer)
3.8. opt_ssl_ca (string)
4. Functions
5. Installation
@ -105,6 +108,7 @@ Chapter 1. Admin Guide
3.5. insert_delayed (integer)
3.6. update_affected_found (integer)
3.7. opt_ssl_mode (integer)
3.8. opt_ssl_ca (string)
3.1. ping_interval (integer)
@ -209,6 +213,21 @@ modparam("db_mysql", "update_affected_found", 1)
modparam("db_mysql", "opt_ssl_mode", 1)
...
3.8. opt_ssl_ca (string)
Configures the CA certs used to verify the MySQL server cert when SSL
is enabled.
Required when opt_ssl_mode = 4 or 5 and db_mysql is built with
libmysqlclient.
Default value is NULL (NULL - not configured).
Example 1.8. Set opt_ssl_ca parameter
...
modparam("db_mysql", "opt_ssl_ca", "/etc/ssl/certs/mysql-ca.pem")
...
4. Functions
No function exported to be used from configuration file.
@ -235,12 +254,12 @@ modparam("db_mysql", "opt_ssl_mode", 1)
* mysql://user:pass@[group]/db
* mysql://[group]/db
Example 1.8. Set a my.cnf group in db_url parameter
Example 1.9. Set a my.cnf group in db_url parameter
...
modparam("usrloc", "db_url", "mysql://[kamailio]/kamailio)
...
Example 1.9. Adding a kamailio group to my.cnf
Example 1.10. Adding a kamailio group to my.cnf
...
[kamailio]
socket = /path/to/mysql.sock
@ -254,7 +273,7 @@ default-character-set = utf8
both your specific group and the client group, then the value is taken
from the last one.
Example 1.10. Using [client] and specific group
Example 1.11. Using [client] and specific group
...
[client]
socket = /run/mysql/mysqld.sock

@ -47,6 +47,7 @@ unsigned int my_server_timezone =
unsigned long my_client_ver = 0;
int db_mysql_unsigned_type = 0;
int db_mysql_opt_ssl_mode = 0;
char *db_mysql_opt_ssl_ca = NULL;
struct mysql_counters_h mysql_cnts_h;
counter_def_t mysql_cnt_defs[] = {
@ -100,6 +101,7 @@ static param_export_t params[] = {
{"insert_delayed", INT_PARAM, &db_mysql_insert_all_delayed},
{"update_affected_found", INT_PARAM, &db_mysql_update_affected_found},
{"unsigned_type", PARAM_INT, &db_mysql_unsigned_type},
{"opt_ssl_ca", PARAM_STRING, &db_mysql_opt_ssl_ca},
{"opt_ssl_mode", PARAM_INT, &db_mysql_opt_ssl_mode}, {0, 0, 0}};

@ -211,6 +211,30 @@ modparam("db_mysql", "update_affected_found", 1)
...
modparam("db_mysql", "opt_ssl_mode", 1)
...
</programlisting>
</example>
</section>
<section id="db_mysql.p.opt_ssl_ca">
<title><varname>opt_ssl_ca</varname> (string)</title>
<para>
Configures the CA certs used to verify the MySQL server cert when
SSL is enabled.
</para>
<para>
Required when opt_ssl_mode = 4 or 5 and db_mysql is built
with libmysqlclient.
</para>
<para>
<emphasis>
Default value is NULL (NULL - not configured).
</emphasis>
</para>
<example>
<title>Set <varname>opt_ssl_ca</varname> parameter</title>
<programlisting format="linespecific">
...
modparam("db_mysql", "opt_ssl_ca", "/etc/ssl/certs/mysql-ca.pem")
...
</programlisting>
</example>
</section>

@ -38,6 +38,11 @@
#include "../../core/mem/mem.h"
#include "../../core/dprint.h"
#include "../../core/async_task.h"
#define KSR_RTHREAD_NEED_4PP
#define KSR_RTHREAD_NEED_0P
#define KSR_RTHREAD_NEED_4P5I2P2
#include "../../core/rthreads.h"
#include "../../lib/srdb1/db_query.h"
#include "../../lib/srdb1/db_ut.h"
#include "db_mysql.h"
@ -66,7 +71,7 @@ static char *mysql_sql_buf;
* \param _s executed query
* \return zero on success, negative value on failure
*/
static int db_mysql_submit_query(const db1_con_t *_h, const str *_s)
static int db_mysql_submit_query_impl(const db1_con_t *_h, const str *_s)
{
time_t t;
int i, code;
@ -127,6 +132,11 @@ static int db_mysql_submit_query(const db1_con_t *_h, const str *_s)
}
static int db_mysql_submit_query(const db1_con_t *_h, const str *_s)
{
return run_thread4PP((_thread_proto4PP)db_mysql_submit_query_impl,
(void *)_h, (void *)_s);
}
/**
*
*/
@ -197,8 +207,10 @@ static char *db_mysql_tquote = "`";
* No function should be called before this
* \param _url URL used for initialization
* \return zero on success, negative value on failure
*
* Init libssl in a thread
*/
db1_con_t *db_mysql_init(const str *_url)
static db1_con_t *db_mysql_init0(const str *_url)
{
db1_con_t *c;
c = db_do_init(_url, (void *)db_mysql_new_connection);
@ -208,17 +220,26 @@ db1_con_t *db_mysql_init(const str *_url)
}
db1_con_t *db_mysql_init(const str *_url)
{
return run_threadP((_thread_proto)db_mysql_init0, (void *)_url);
}
/**
* Shut down the database module.
* No function should be called after this
* \param _h handle to the closed connection
* \return zero on success, negative value on failure
*/
void db_mysql_close(db1_con_t *_h)
static void db_mysql_close_impl(db1_con_t *_h)
{
db_do_close(_h, db_mysql_free_connection);
}
void db_mysql_close(db1_con_t *_h)
{
run_thread0P((_thread_proto0P)db_mysql_close_impl, _h);
}
/**
* Retrieve a result set
@ -328,12 +349,26 @@ int db_mysql_free_result(const db1_con_t *_h, db1_res_t *_r)
* \param _r pointer to a structure representing the result
* \return zero on success, negative value on failure
*/
/*
* this function observed to invoke SSL_read() under libmysqlclient.so.21
* but not libmariadb.so.3; apply libssl guard
*/
static int db_mysql_query_impl(const db1_con_t *_h, const db_key_t *_k,
const db_op_t *_op, const db_val_t *_v, const db_key_t *_c,
const int _n, const int _nc, const db_key_t _o, db1_res_t **_r)
{
return db_do_query(_h, _k, _op, _v, _c, _n, _nc, _o, _r, db_mysql_val2str,
db_mysql_submit_query, db_mysql_store_result);
}
int db_mysql_query(const db1_con_t *_h, const db_key_t *_k, const db_op_t *_op,
const db_val_t *_v, const db_key_t *_c, const int _n, const int _nc,
const db_key_t _o, db1_res_t **_r)
{
return db_do_query(_h, _k, _op, _v, _c, _n, _nc, _o, _r, db_mysql_val2str,
db_mysql_submit_query, db_mysql_store_result);
return run_thread4P5I2P2((_thread_proto4P5I2P2)&db_mysql_query_impl,
(void *)_h, (void *)_k, (void *)_op, (void *)_v, (void *)_c, _n,
_nc, (void *)_o, (void *)_r);
}
/**

@ -41,6 +41,7 @@
#include "db_mysql.h"
extern int db_mysql_opt_ssl_mode;
extern char *db_mysql_opt_ssl_ca;
/*! \brief
* Create a new connection structure,
@ -116,7 +117,36 @@ struct my_con *db_mysql_new_connection(const struct db_id *id)
(const void *)&db_mysql_timeout_interval);
mysql_options(ptr->con, MYSQL_OPT_WRITE_TIMEOUT,
(const void *)&db_mysql_timeout_interval);
#if MYSQL_VERSION_ID > 50710 && !defined(MARIADB_BASE_VERSION)
#ifdef MARIADB_BASE_VERSION
/*
* emulate SSL_MODE_XXXX from MySQL
*/
switch(db_mysql_opt_ssl_mode) {
case 0: /* opt_ssl_mode = 0(off) */
case 1: /* SSL_MODE_DISABLED */
break;
case 2: /* SSL_MODE_PREFERRED */
case 3: /* SSL_MODE_REQUIRED */
case 4: /* SSL_MODE_VERIFY_CA */
#if MYSQL_VERSION_ID >= 100339
mysql_options(ptr->con, MYSQL_OPT_SSL_ENFORCE, (void *)&(int){1});
#else
LM_WARN("ssl mode not supported by %s\n", MARIADB_BASE_VERSION);
#endif
break;
case 5: /* SSL_MODE_VERIFY_IDENTITY */
mysql_options(ptr->con, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
(void *)&(int){1});
break;
default:
LM_WARN("opt_ssl_mode = %d not supported by MariaDB Connector/C\n",
db_mysql_opt_ssl_mode);
break;
}
#else
#if MYSQL_VERSION_ID > 50710
if(db_mysql_opt_ssl_mode != 0) {
unsigned int optuint = 0;
if(db_mysql_opt_ssl_mode == 1) {
@ -136,7 +166,11 @@ struct my_con *db_mysql_new_connection(const struct db_id *id)
"ignoring\n",
(unsigned int)db_mysql_opt_ssl_mode);
}
#endif
#endif /* MYSQL_VERSION_ID */
#endif /* MARIADB_BASE_VERSION */
if(db_mysql_opt_ssl_ca)
mysql_options(
ptr->con, MYSQL_OPT_SSL_CA, (const void *)db_mysql_opt_ssl_ca);
#if MYSQL_VERSION_ID > 50012
/* set reconnect flag if enabled */

@ -43,6 +43,10 @@
#include "../../core/locking.h"
#include "../../core/hashes.h"
#include "../../core/clist.h"
#define KSR_RTHREAD_NEED_PI
#define KSR_RTHREAD_NEED_4PP
#define KSR_RTHREAD_NEED_0P
#include "../../core/rthreads.h"
#include "km_dbase.h"
#include "km_pg_con.h"
#include "km_val.h"
@ -108,34 +112,52 @@ static void db_postgres_free_query(const db1_con_t *_con);
* \param _url URL of the database that should be opened
* \return database connection on success, NULL on error
* \note this function must be called prior to any database functions
*
* Init libssl in a thread
*/
db1_con_t *db_postgres_init(const str *_url)
static db1_con_t *db_postgres_init0(const str *_url)
{
return db_do_init(_url, (void *)db_postgres_new_connection);
}
db1_con_t *db_postgres_init(const str *_url)
{
return run_threadP((_thread_proto)db_postgres_init0, (void *)_url);
}
/*!
* \brief Initialize database for future queries, specify pooling
* \param _url URL of the database that should be opened
* \param pooling whether or not to use a pooled connection
* \return database connection on success, NULL on error
* \note this function must be called prior to any database functions
*
* Init libssl in thread
*/
db1_con_t *db_postgres_init2(const str *_url, db_pooling_t pooling)
static db1_con_t *db_postgres_init2_impl(const str *_url, db_pooling_t pooling)
{
return db_do_init2(_url, (void *)db_postgres_new_connection, pooling);
}
db1_con_t *db_postgres_init2(const str *_url, db_pooling_t pooling)
{
return run_threadPI(
(_thread_protoPI)db_postgres_init2_impl, (void *)_url, pooling);
}
/*!
* \brief Close database when the database is no longer needed
* \param _h closed connection, as returned from db_postgres_init
* \note free all memory and resources
*/
void db_postgres_close(db1_con_t *_h)
static void db_postgres_close_impl(db1_con_t *_h)
{
db_do_close(_h, db_postgres_free_connection);
}
void db_postgres_close(db1_con_t *_h)
{
run_thread0P((_thread_proto0P)db_postgres_close_impl, _h);
}
/*!
* \brief Submit_query, run a query
@ -143,7 +165,7 @@ void db_postgres_close(db1_con_t *_h)
* \param _s query string
* \return 0 on success, negative on failure
*/
static int db_postgres_submit_query(const db1_con_t *_con, const str *_s)
static int db_postgres_submit_query_impl(const db1_con_t *_con, const str *_s)
{
char *s = NULL;
int i, retries;
@ -271,6 +293,12 @@ static int db_postgres_submit_query(const db1_con_t *_con, const str *_s)
return -1;
}
static int db_postgres_submit_query(const db1_con_t *_con, const str *_s)
{
return run_thread4PP((_thread_proto4PP)db_postgres_submit_query_impl,
(void *)_con, (void *)_s);
}
void db_postgres_async_exec_task(void *param)
{
str *p;

@ -22,10 +22,13 @@
*
*/
#include "../../core/mem/mem.h"
#include "../../core/dprint.h"
#include "../../core/async_task.h"
#define KSR_RTHREAD_NEED_4PP
#define KSR_RTHREAD_NEED_4P5I2P2
#define KSR_RTHREAD_NEED_0P
#include "../../core/rthreads.h"
#include "../../lib/srdb1/db_query.h"
#include "val.h"
#include "connection.h"
@ -81,7 +84,7 @@ static int reconnect(const db1_con_t *_h)
/*
* Send an SQL query to the server
*/
static int db_unixodbc_submit_query(const db1_con_t *_h, const str *_s)
static int db_unixodbc_submit_query_impl(const db1_con_t *_h, const str *_s)
{
int ret = 0;
SQLCHAR sqlstate[7];
@ -155,6 +158,11 @@ static int db_unixodbc_submit_query(const db1_con_t *_h, const str *_s)
return ret;
}
static int db_unixodbc_submit_query(const db1_con_t *_h, const str *_s)
{
return run_thread4PP((_thread_proto4PP)db_unixodbc_submit_query_impl,
(void *)_h, (void *)_s);
}
/**
*
*/
@ -227,8 +235,10 @@ extern char *db_unixodbc_tquote;
/*
* Initialize database module
* No function should be called before this
*
* Init libssl in a thread
*/
db1_con_t *db_unixodbc_init(const str *_url)
static db1_con_t *db_unixodbc_init0(const str *_url)
{
db1_con_t *c;
c = db_do_init(_url, (void *)db_unixodbc_new_connection);
@ -237,15 +247,25 @@ db1_con_t *db_unixodbc_init(const str *_url)
return c;
}
db1_con_t *db_unixodbc_init(const str *_url)
{
return run_threadP((_thread_proto)&db_unixodbc_init0, (void *)_url);
}
/*
* Shut down database module
* No function should be called after this
*/
void db_unixodbc_close(db1_con_t *_h)
static void db_unixodbc_close_impl(db1_con_t *_h)
{
return db_do_close(_h, db_unixodbc_free_connection);
}
void db_unixodbc_close(db1_con_t *_h)
{
run_thread0P((_thread_proto0P)db_unixodbc_close_impl, _h);
}
/*
* Retrieve result set
*/
@ -286,7 +306,7 @@ static int db_unixodbc_store_result(const db1_con_t *_h, db1_res_t **_r)
/*
* Release a result set from memory
*/
int db_unixodbc_free_result(db1_con_t *_h, db1_res_t *_r)
static int db_unixodbc_free_result_impl(db1_con_t *_h, db1_res_t *_r)
{
if((!_h) || (!_r)) {
LM_ERR("invalid parameter value\n");
@ -302,6 +322,11 @@ int db_unixodbc_free_result(db1_con_t *_h, db1_res_t *_r)
return 0;
}
int db_unixodbc_free_result(db1_con_t *_h, db1_res_t *_r)
{
return run_thread4PP((_thread_proto4PP)db_unixodbc_free_result_impl, _h, _r);
}
/*
* Query table for specified rows
* _h: structure representing database connection
@ -313,7 +338,7 @@ int db_unixodbc_free_result(db1_con_t *_h, db1_res_t *_r)
* _nc: number of columns to return
* _o: order by the specified column
*/
int db_unixodbc_query(const db1_con_t *_h, const db_key_t *_k,
static int db_unixodbc_query_impl(const db1_con_t *_h, const db_key_t *_k,
const db_op_t *_op, const db_val_t *_v, const db_key_t *_c,
const int _n, const int _nc, const db_key_t _o, db1_res_t **_r)
{
@ -322,6 +347,15 @@ int db_unixodbc_query(const db1_con_t *_h, const db_key_t *_k,
db_unixodbc_store_result);
}
int db_unixodbc_query(const db1_con_t *_h, const db_key_t *_k,
const db_op_t *_op, const db_val_t *_v, const db_key_t *_c,
const int _n, const int _nc, const db_key_t _o, db1_res_t **_r)
{
return run_thread4P5I2P2((_thread_proto4P5I2P2)db_unixodbc_query_impl,
(void *)_h, (void *)_k, (void *)_op, (void *)_v, (void *)_c, _n,
_nc, (void *)_o, (void *)_r);
}
/*!
* \brief Gets a partial result set, fetch rows from a result
*

@ -405,8 +405,10 @@ int extract_node_list(dmq_node_list_t *update_list, struct sip_msg *msg)
/* trim the \r, \n and \0's */
trim_r(tmp_uri);
find = build_dmq_node(&tmp_uri, 0);
if(find == NULL)
return -1;
if(find == NULL) {
LM_ERR("error building dmq node\n");
goto error;
}
ret = find_dmq_node(update_list, find);
if(!ret) {
LM_DBG("found new node %.*s\n", STR_FMT(&tmp_uri));

@ -50,6 +50,9 @@
#include "../../core/cfg/cfg_struct.h"
#include "../../core/fmsg.h"
#include "../../core/kemi.h"
#define KSR_RTHREAD_NEED_V
#define KSR_RTHREAD_SKIP_P
#include "../../core/rthreads.h"
#include "../../modules/tm/tm_load.h"
#include "../../modules/pv/pv_api.h"
@ -285,7 +288,7 @@ static int mod_init(void)
return -1;
}
set_curl_mem_callbacks();
run_threadV((_thread_protoV)&set_curl_mem_callbacks);
/* init faked sip msg */
if(faked_msg_init() < 0) {

@ -64,6 +64,9 @@
#include "../../core/lvalue.h"
#include "../../core/pt.h" /* Process table */
#include "../../core/kemi.h"
#define KSR_RTHREAD_NEED_4L
#define KSR_RTHREAD_SKIP_P
#include "../../core/rthreads.h"
#include "functions.h"
#include "curlcon.h"
@ -278,7 +281,7 @@ static int mod_init(void)
LM_DBG("init curl module\n");
/* Initialize curl */
if(curl_global_init(CURL_GLOBAL_ALL)) {
if(run_thread4L((_thread_proto4L)&curl_global_init, CURL_GLOBAL_ALL)) {
LM_ERR("curl_global_init failed\n");
return -1;
}

@ -40,6 +40,9 @@ int janssonmod_get_helper(
pv_value_t dst_val;
json_t *json = NULL;
json_error_t parsing_error;
char *path = NULL;
char *freeme = NULL;
STR_VTOZ(src_s->s[src_s->len], c);
json = json_loads(src_s->s, JSON_REJECT_DUPLICATES, &parsing_error);
STR_ZTOV(src_s->s[src_s->len], c);
@ -50,14 +53,13 @@ int janssonmod_get_helper(
goto fail;
}
char *path = path_s->s;
path = path_s->s;
json_t *v = json_path_get(json, path);
if(!v) {
goto fail;
}
char *freeme = NULL;
if(jansson_to_val(&dst_val, &freeme, v) < 0)
goto fail;
@ -130,6 +132,12 @@ int janssonmod_set(unsigned int append, struct sip_msg *msg, char *type_in,
char c;
pv_spec_t *result_pv;
pv_value_t result_val;
json_t *result_json = NULL;
json_t *value = NULL;
char *freeme = NULL;
json_error_t parsing_error = {0};
char *endptr;
char *path = NULL;
if(fixup_get_svalue(msg, (gparam_p)type_in, &type_s) != 0) {
ERR("cannot get type string value\n");
@ -161,12 +169,6 @@ int janssonmod_set(unsigned int append, struct sip_msg *msg, char *type_in,
LM_DBG("value is: %.*s\n", value_s.len, value_s.s);
LM_DBG("result is: %.*s\n", result_val.rs.len, result_val.rs.s);
json_t *result_json = NULL;
json_t *value = NULL;
char *freeme = NULL;
json_error_t parsing_error = {0};
char *endptr;
/* check the type */
if(STR_EQ_STATIC(type_s, "object") || STR_EQ_STATIC(type_s, "obj")) {
STR_VTOZ(value_s.s[value_s.len], c);
@ -241,7 +243,8 @@ int janssonmod_set(unsigned int append, struct sip_msg *msg, char *type_in,
goto fail;
}
char *path = path_s.s;
path = path_s.s;
STR_VTOZ(result_val.rs.s[result_val.rs.len], c);
result_json =
json_loads(result_val.rs.s, JSON_REJECT_DUPLICATES, &parsing_error);
@ -281,6 +284,8 @@ int janssonmod_array_size(
str path_s;
pv_spec_t *dst_pv;
pv_value_t dst_val;
char *path = NULL;
int size = 0;
if(fixup_get_svalue(msg, (gparam_p)src_in, &src_s) != 0) {
ERR("cannot get json string value\n");
@ -305,7 +310,7 @@ int janssonmod_array_size(
goto fail;
}
char *path = path_s.s;
path = path_s.s;
json_t *v = json_path_get(json, path);
if(!v) {
@ -318,7 +323,7 @@ int janssonmod_array_size(
goto fail;
}
int size = json_array_size(v);
size = json_array_size(v);
dst_val.ri = size;
dst_val.flags = PV_TYPE_INT | PV_VAL_INT;

@ -69,13 +69,15 @@ typedef struct _ka_initial_dest
typedef struct _ka_dest
{
str uri;
str owner; // name of destination "owner"
// (module asking to monitor this destination
str uuid; // Universal id for this record
str owner; /*!< Name of destination "owner" */
/*!< Module asking to monitor this destination */
str uuid; /*!< Universal id for this record */
int flags;
int state;
time_t last_checked, last_up, last_down;
int counter; // counts unreachable attempts
time_t last_checked;
time_t last_up; /*!< Time of last successful SIP reply */
time_t last_down; /*!< Time of last failure SIP reply */
int counter; /*!< Counts unreachable attempts */
ticks_t ping_interval; /*!< Actual interval between OPTIONS */
void *user_attr;

@ -131,11 +131,11 @@ static void ka_options_callback(
// accepting 2XX return codes
if(ps->code >= 200 && ps->code <= 299) {
state = KA_STATE_UP;
ka_dest->last_down = time(NULL);
ka_dest->last_up = time(NULL);
ka_dest->counter = 0;
} else {
state = KA_STATE_DOWN;
ka_dest->last_up = time(NULL);
ka_dest->last_down = time(NULL);
ka_dest->counter++;
}

@ -485,13 +485,14 @@ int redisc_reconnect_server(redisc_server_t *rsrv)
for(i = 0; i < sentinels_count; i++) {
char *sentinelAddr = sentinels[i];
char *pos;
int srvfound = 0;
redisContext *redis;
redisReply *res, *res2;
port = 6379;
if((pos = strchr(sentinelAddr, ':')) != NULL) {
port = atoi(pos + 1);
pos[i] = '\0';
pos[0] = '\0';
}
redis = redisConnectWithTimeout(sentinelAddr, port, tv_conn);
@ -507,6 +508,7 @@ int redisc_reconnect_server(redisc_server_t *rsrv)
port = atoi(res->element[1]->str);
LOG(ndb_redis_debug, "sentinel replied: %s:%d\n", addr,
port);
srvfound = 1;
}
} else {
res = redisCommand(
@ -530,9 +532,13 @@ int redisc_reconnect_server(redisc_server_t *rsrv)
}
LOG(ndb_redis_debug, "slave for %s: %s:%d\n",
sentinel_group, addr, port);
srvfound = 1;
}
}
}
if(srvfound == 1) {
break;
}
}
}

@ -40,6 +40,10 @@
#include "../../core/parser/parse_uri.h"
#include "../../core/parser/parse_supported.h"
#define KSR_RTHREAD_SKIP_P
#define KSR_RTHREAD_NEED_V
#include "../../core/rthreads.h"
#include "api.h"
#include "config.h"
@ -75,26 +79,25 @@ struct module_exports exports = {
destroy /* destroy function */
};
static void *mod_init_openssl(void *arg) {
if(flow_token_secret.s) {
assert(ob_key.len == SHA_DIGEST_LENGTH);
LM_DBG("flow_token_secret mod param set. use persistent ob_key");
static void mod_init_openssl(void)
{
if(flow_token_secret.s) {
assert(ob_key.len == SHA_DIGEST_LENGTH);
LM_DBG("flow_token_secret mod param set. use persistent ob_key");
#if OPENSSL_VERSION_NUMBER < 0x030000000L
SHA1((const unsigned char *)flow_token_secret.s, flow_token_secret.len,
(unsigned char *)ob_key.s);
SHA1((const unsigned char *)flow_token_secret.s, flow_token_secret.len,
(unsigned char *)ob_key.s);
#else
EVP_Q_digest(NULL, "SHA1", NULL, flow_token_secret.s,
flow_token_secret.len, (unsigned char *)ob_key.s, NULL);
EVP_Q_digest(NULL, "SHA1", NULL, flow_token_secret.s,
flow_token_secret.len, (unsigned char *)ob_key.s, NULL);
#endif
} else {
if(RAND_bytes((unsigned char *)ob_key.s, ob_key.len) == 0) {
LM_ERR("unable to get %d cryptographically strong pseudo-"
"random bytes\n",
ob_key.len);
}
}
return NULL;
} else {
if(RAND_bytes((unsigned char *)ob_key.s, ob_key.len) == 0) {
LM_ERR("unable to get %d cryptographically strong pseudo-"
"random bytes\n",
ob_key.len);
}
}
}
static int mod_init(void)
@ -116,12 +119,9 @@ static int mod_init(void)
ob_key.len = OB_KEY_LEN;
#if OPENSSL_VERSION_NUMBER < 0x010101000L
mod_init_openssl(NULL);
mod_init_openssl();
#else
pthread_t tid;
void *retval;
pthread_create(&tid, NULL, mod_init_openssl, NULL);
pthread_join(tid, &retval);
run_threadV(mod_init_openssl);
#endif
if(cfg_declare("outbound", outbound_cfg_def, &default_outbound_cfg,

@ -386,20 +386,20 @@ static int pdb_query(struct sip_msg *_msg, struct multiparam_t *_number,
goto found;
}
break;
case PDB_CODE_NOT_NUMBER:
LM_NOTICE("Number %s has letters in it\n",
number.s);
carrierid = 0;
goto found;
case PDB_CODE_NOT_FOUND:
LM_NOTICE("Number %s pdb_id not found\n",
number.s);
carrierid = 0;
carrierid = -1;
goto found;
case PDB_CODE_NOT_NUMBER:
LM_NOTICE("Number %s has letters in it\n",
number.s);
carrierid = -2;
goto found;
default:
LM_NOTICE("Invalid code %d received\n",
msg.hdr.code);
carrierid = 0;
carrierid = -3;
goto found;
}

@ -7,6 +7,7 @@ NAME=phonenum.so
CXX?=g++
LD?=g++
CSTDVER?="c++17"
LIBS+=-L$(LOCALBASE)/lib cphonenumber.o -lphonenumber -lgeocoding
DEFS+=-I$(LOCALBASE)/include
@ -18,7 +19,7 @@ include ../../Makefile.modules
cphonenumber.o: cphonenumber.cpp cphonenumber.h
@echo "Compiling $<"
$(CXX) -std=c++11 $(CXXFLAGS) $(CFLAGS) $(C_DEFS) $(DEFS) -c $< -o $@
$(CXX) -std=$(CSTDVER) $(CXXFLAGS) $(CFLAGS) $(C_DEFS) $(DEFS) -c $< -o $@
phonenum.so: cphonenumber.o

@ -2717,6 +2717,13 @@ int pv_get_tcpconn_id(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
if(msg == NULL)
return -1;
/* use first the connection set for event_route[tcp:...] */
con = ksr_tcpcon_evcb_get();
if(con != NULL) {
return pv_get_sintval(msg, param, res, con->id);
}
/* find connection from sip message structure */
if((con = tcpconn_get(msg->rcv.proto_reserved1, 0, 0, 0, 0)) == NULL)
return pv_get_null(msg, param, res);

@ -3131,6 +3131,7 @@ static char *send_rtpp_command(
len = _rtpe_lwscb.request(&node->rn_url, (str *)&rtpe_proto, &request,
&response, rtpengine_tout_ms * 1000);
pkg_free(request.s);
if(len < 0) {
LM_ERR("failed to do websocket request\n");

@ -91,19 +91,29 @@ Registration Procedures: Standards Action Process or expert approval
*/
typedef struct _codecsmap
{
/* clang-format off */
typedef struct _codecsmap {
str name;
str ids;
} codecsmap_t;
codecsmap_t sdpops_codecsmap_table[] = {{{"PCMU", 4}, {"0", 1}},
{{"GSM", 3}, {"3", 1}}, {{"G723", 4}, {"4", 1}},
{{"DVI4", 4}, {"5,6,16,17", 9}}, {{"LPC", 3}, {"7", 1}},
{{"PCMA", 4}, {"8", 1}}, {{"G722", 4}, {"9", 1}},
{{"L16", 3}, {"10,11", 5}}, {{"QCELP", 5}, {"12", 2}},
{{"CN", 2}, {"13", 5}}, {{"MPA", 3}, {"14", 2}},
{{"G728", 4}, {"15", 2}}, {{"G729", 4}, {"18", 2}}, {{0, 0}, {0, 0}}};
codecsmap_t sdpops_codecsmap_table[] = {
{{"PCMU", 4}, {"0", 1}},
{{"GSM", 3}, {"3", 1}},
{{"G723", 4}, {"4", 1}},
{{"DVI4", 4}, {"5,6,16,17", 9}},
{{"LPC", 3}, {"7", 1}},
{{"PCMA", 4}, {"8", 1}},
{{"G722", 4}, {"9", 1}},
{{"L16", 3}, {"10,11", 5}},
{{"QCELP", 5}, {"12", 2}},
{{"CN", 2}, {"13", 5}},
{{"MPA", 3}, {"14", 2}},
{{"G728", 4}, {"15", 2}},
{{"G729", 4}, {"18", 2}},
{{0, 0}, {0, 0}}
};
/* clang-format on */
/**
* set the string with the IDs mapped to codec name

@ -218,11 +218,12 @@ Chapter 1. Admin Guide
Database URL.
Default value is "".
Default value is “mysql://kamailio:kamailiorw@localhost/kamailio”.
Example 1.1. Set db_url parameter
...
modparam("sipcapture", "db_url", "mysql://user:passwd@host/dbname")
modparam("sipcapture", "db_url", "mysql://kamailio:kamailiorw@localhost/kamailio
")
...
3.2. table_name (str)

@ -89,14 +89,14 @@
</para>
<para>
<emphasis>
Default value is "".
Default value is <quote>&defaultdb;</quote>.
</emphasis>
</para>
<example>
<title>Set <varname>db_url</varname> parameter</title>
<programlisting format="linespecific">
...
modparam("sipcapture", "db_url", "mysql://user:passwd@host/dbname")
modparam("sipcapture", "db_url", "&defaultdb;")
...
</programlisting>
</example>

@ -33,6 +33,8 @@ Carsten Bock
4.1. isRPDATA()
4.2. smsdump()
5. Variables
List of Examples
1.1. isRPDATA() usage
@ -57,6 +59,8 @@ Chapter 1. Admin Guide
4.1. isRPDATA()
4.2. smsdump()
5. Variables
1. Overview
This module collects the Transformations for 3GPP-SMS.
@ -115,3 +119,12 @@ if (isRPDATA())
...
smsdump();
...
5. Variables
Several variables are exported by the module to access the attributes
of the SMS.
* $smsack
$smsbody
$rpdata(key)
$tpdu(key)

@ -95,5 +95,19 @@ smsdump();
</section>
</section><!-- end of functions -->
<section>
<title>Variables</title>
<para>Several variables are exported by the module to access the
attributes of the SMS.</para>
<itemizedlist>
<listitem>
<para><emphasis>$smsack</emphasis></para>
<para><emphasis>$smsbody</emphasis></para>
<para><emphasis>$rpdata(key)</emphasis></para>
<para><emphasis>$tpdu(key)</emphasis></para>
</listitem>
</itemizedlist>
</section>
</chapter>

@ -30,31 +30,36 @@
MODULE_VERSION
static pv_export_t mod_pvs[] = {{{"smsack", sizeof("smsack") - 1}, PVT_OTHER,
pv_sms_ack, 0, 0, 0, 0, 0},
{{"rpdata", sizeof("rpdata") - 1}, PVT_OTHER, pv_get_sms, pv_set_sms,
pv_parse_rpdata_name, 0, 0, 0},
{{"tpdu", sizeof("tpdu") - 1}, PVT_OTHER, pv_get_sms, pv_set_sms,
/* clang-format off */
static pv_export_t mod_pvs[] = {
{{"smsack", sizeof("smsack") - 1}, PVT_OTHER, pv_sms_ack, 0, 0, 0, 0, 0},
{{"rpdata", sizeof("rpdata") - 1}, PVT_OTHER, pv_get_sms, pv_set_sms,
pv_parse_rpdata_name, 0, 0, 0},
{{"tpdu", sizeof("tpdu") - 1}, PVT_OTHER, pv_get_sms, pv_set_sms,
pv_parse_tpdu_name, 0, 0, 0},
{{"smsbody", sizeof("smsbody") - 1}, PVT_OTHER, pv_sms_body, 0, 0, 0, 0,
0},
{{0, 0}, 0, 0, 0, 0, 0, 0, 0}};
{{"smsbody", sizeof("smsbody") - 1}, PVT_OTHER, pv_sms_body, 0, 0, 0, 0, 0},
{{0, 0}, 0, 0, 0, 0, 0, 0, 0}
};
static cmd_export_t cmds[] = {
{"smsdump", (cmd_function)smsdump, 0, 0, 0, REQUEST_ROUTE},
{"isRPDATA", (cmd_function)isRPDATA, 0, 0, 0, REQUEST_ROUTE},
{0, 0, 0, 0, 0, 0}};
{"smsdump", (cmd_function)smsdump, 0, 0, 0, REQUEST_ROUTE},
{"isRPDATA", (cmd_function)isRPDATA, 0, 0, 0, REQUEST_ROUTE},
{0, 0, 0, 0, 0, 0}
};
/** module exports */
struct module_exports exports = {
"smsops", /* module name */
DEFAULT_DLFLAGS, /* dlopen flags */
cmds, /* exported functions */
0, /* exported parameters */
0, /* exported rpc functions */
mod_pvs, /* exported pseudo-variables */
0, /* response handling function*/
0, /* module init function */
0, /* per-child init function */
0 /* module destroy function */
"smsops", /* module name */
DEFAULT_DLFLAGS, /* dlopen flags */
cmds, /* exported functions */
0, /* exported parameters */
0, /* exported rpc functions */
mod_pvs, /* exported pseudo-variables */
0, /* response handling function*/
0, /* module init function */
0, /* per-child init function */
0 /* module destroy function */
};
/* clang-format on */

@ -249,6 +249,7 @@ static void tcpops_tcp_closed_run_route(tcp_closed_event_info_t *tev)
sr_kemi_eng_t *keng = NULL;
str *evname;
LM_DBG("event reason id: %d\n", tev->reason);
if(tcpops_event_callback.len > 0) {
rt = -1;
keng = sr_kemi_eng_get();
@ -258,9 +259,10 @@ static void tcpops_tcp_closed_run_route(tcp_closed_event_info_t *tev)
}
} else {
rt = tcp_closed_routes[tev->reason];
LM_DBG("event reason id: %d rt: %d\n", tev->reason, rt);
if(rt == -1)
if(rt == -1) {
LM_DBG("event reason id: %d - event route not set\n", tev->reason);
return;
}
}
if(faked_msg_init() < 0) {

@ -30,13 +30,21 @@
#include <openssl/bn.h>
#include <openssl/dh.h>
#if OPENSSL_VERSION_NUMBER >= 0x030000000L
#define OPENSSL_NO_ENGINE
/* only OpenSSL <= 1.1.1 */
#if !defined(OPENSSL_NO_ENGINE) && OPENSSL_VERSION_NUMBER < 0x030000000L
#define KSR_SSL_COMMON
#define KSR_SSL_ENGINE
#define KEY_PREFIX "/engine:"
#define KEY_PREFIX_LEN (strlen(KEY_PREFIX))
#include <openssl/engine.h>
extern EVP_PKEY *tls_engine_private_key(const char *key_id);
#endif
#ifndef OPENSSL_NO_ENGINE
#include <openssl/engine.h>
#include "tls_map.h"
#if !defined(OPENSSL_NO_PROVIDER) && OPENSSL_VERSION_NUMBER >= 0x030000000L
#define KSR_SSL_COMMON
#define KSR_SSL_PROVIDER
#define KEY_PREFIX "/uri:"
#define KEY_PREFIX_LEN (strlen(KEY_PREFIX))
extern EVP_PKEY *tls_engine_private_key(const char *key_id);
#endif
@ -1227,32 +1235,7 @@ err:
#endif
}
#ifndef OPENSSL_NO_ENGINE
/*
* Implement a hash map from SSL_CTX to private key
* as HSM keys need to be process local
*/
static map_void_t private_key_map;
/**
* @brief Return a private key from the lookup table
* @param p SSL_CTX*
* @return EVP_PKEY on success, NULL on error
*/
EVP_PKEY *tls_lookup_private_key(SSL_CTX *ctx)
{
void *pkey;
char ctx_str[64];
snprintf(ctx_str, 64, "SSL_CTX-%p", ctx);
pkey = map_get(&private_key_map, ctx_str);
LM_DBG("Private key lookup for %s: %p\n", ctx_str, pkey);
if(pkey)
return *(EVP_PKEY **)pkey;
else
return NULL;
}
#ifdef KSR_SSL_COMMON
/**
* @brief Load a private key from an OpenSSL engine
* @param d TLS domain
@ -1262,7 +1245,7 @@ EVP_PKEY *tls_lookup_private_key(SSL_CTX *ctx)
* to be fork() safe
*
* private_key setting which starts with /engine: is assumed to be
* an HSM key and not a file-based key
* an HSM key and not a file-based key (/uri: for OpenSSL 3 key URIs)
*
* We store the private key in a local memory hash table as
* HSM keys must be process-local. We use the SSL_CTX* address
@ -1273,31 +1256,22 @@ static int load_engine_private_key(tls_domain_t *d)
{
int idx, ret_pwd, i;
EVP_PKEY *pkey = 0;
int procs_no;
char ctx_str[64];
if(!d->pkey_file.s || !d->pkey_file.len) {
DBG("%s: No private key specified\n", tls_domain_str(d));
return 0;
}
if(strncmp(d->pkey_file.s, "/engine:", 8) != 0)
if(strncmp(d->pkey_file.s, KEY_PREFIX, KEY_PREFIX_LEN) != 0)
return 0;
procs_no = get_max_procs();
for(i = 0; i < procs_no; i++) {
snprintf(ctx_str, 64, "SSL_CTX-%p", d->ctx[i]);
do {
i = process_no;
for(idx = 0, ret_pwd = 0; idx < 3; idx++) {
if(i) {
map_set(&private_key_map, ctx_str, pkey);
ret_pwd = 1;
pkey = tls_engine_private_key(d->pkey_file.s + KEY_PREFIX_LEN);
if(pkey) {
ret_pwd = SSL_CTX_use_PrivateKey(d->ctx[i], pkey);
} else {
pkey = tls_engine_private_key(d->pkey_file.s + 8);
if(pkey) {
map_set(&private_key_map, ctx_str, pkey);
// store the key for i = 0 to perform certificate sanity check
ret_pwd = SSL_CTX_use_PrivateKey(d->ctx[i], pkey);
} else {
ret_pwd = 0;
}
ret_pwd = 0;
}
if(ret_pwd) {
break;
@ -1315,21 +1289,21 @@ static int load_engine_private_key(tls_domain_t *d)
TLS_ERR("load_private_key:");
return -1;
}
if(i == 0 && !SSL_CTX_check_private_key(d->ctx[i])) {
if(!SSL_CTX_check_private_key(d->ctx[i])) {
ERR("%s: Key '%s' does not match the public key of the"
" certificate\n",
tls_domain_str(d), d->pkey_file.s);
TLS_ERR("load_engine_private_key:");
return -1;
}
}
} while(0);
LM_INFO("%s: Key '%s' successfully loaded\n", tls_domain_str(d),
d->pkey_file.s);
return 0;
}
#endif
#endif /* KSR_SSL_COMMON */
/**
* @brief Load a private key from a file
* @param d TLS domain
@ -1353,10 +1327,10 @@ static int load_private_key(tls_domain_t *d)
SSL_CTX_set_default_passwd_cb_userdata(d->ctx[i], d->pkey_file.s);
for(idx = 0, ret_pwd = 0; idx < 3; idx++) {
#ifndef OPENSSL_NO_ENGINE
#ifdef KSR_SSL_COMMON
// in PROC_INIT skip loading HSM keys due to
// fork() issues with PKCS#11 libraries
if(strncmp(d->pkey_file.s, "/engine:", 8) != 0) {
if(strncmp(d->pkey_file.s, KEY_PREFIX, KEY_PREFIX_LEN) != 0) {
ret_pwd = SSL_CTX_use_PrivateKey_file(
d->ctx[i], d->pkey_file.s, SSL_FILETYPE_PEM);
} else {
@ -1365,7 +1339,7 @@ static int load_private_key(tls_domain_t *d)
#else
ret_pwd = SSL_CTX_use_PrivateKey_file(
d->ctx[i], d->pkey_file.s, SSL_FILETYPE_PEM);
#endif
#endif /* KSR_SSL_COMMON */
if(ret_pwd) {
break;
} else {
@ -1382,12 +1356,12 @@ static int load_private_key(tls_domain_t *d)
TLS_ERR("load_private_key:");
return -1;
}
#ifndef OPENSSL_NO_ENGINE
if(strncmp(d->pkey_file.s, "/engine:", 8) == 0) {
#ifdef KSR_SSL_COMMON
if(strncmp(d->pkey_file.s, KEY_PREFIX, KEY_PREFIX_LEN) == 0) {
// skip private key validity check for HSM keys
continue;
}
#endif
#endif /* KSR_SSL_COMMON */
if(!SSL_CTX_check_private_key(d->ctx[i])) {
ERR("%s: Key '%s' does not match the public key of the"
" certificate\n",
@ -1403,7 +1377,7 @@ static int load_private_key(tls_domain_t *d)
}
#ifndef OPENSSL_NO_ENGINE
#ifdef KSR_SSL_COMMON
/**
* @brief Initialize engine private keys
*
@ -1435,7 +1409,7 @@ int tls_fix_engine_keys(tls_domains_cfg_t *cfg, tls_domain_t *srv_defaults,
return 0;
}
#endif
#endif /* KSR_SSL_COMMON */
/**
* @brief Initialize attributes of all domains from default domains if necessary
*

@ -737,43 +737,43 @@ int tls_pre_init(void)
* left here in case more complex requirements arise in
* OpenSSL >= 3.2.
*/
long tls_h_mod_randctx(void *param)
int tls_h_mod_randctx()
{
do {
OSSL_LIB_CTX *osslglobal = NULL;
EVP_RAND_CTX *randctx = NULL;
LM_DBG("enabling locking for rand ctx\n");
osslglobal = OSSL_LIB_CTX_get0_global_default();
if(osslglobal == NULL) {
LM_ERR("failed to get lib ssl global ctx\n");
return -1L;
}
randctx = RAND_get0_primary(osslglobal);
if(randctx == NULL) {
LM_ERR("primary rand ctx is null\n");
return -1L;
}
EVP_RAND_enable_locking(randctx);
randctx = RAND_get0_public(osslglobal);
if(randctx == NULL) {
LM_ERR("public rand ctx is null\n");
return -1L;
}
EVP_RAND_enable_locking(randctx);
randctx = RAND_get0_private(osslglobal);
if(randctx == NULL) {
LM_ERR("private rand ctx is null\n");
return -1L;
}
EVP_RAND_enable_locking(randctx);
} while(0);
return 0L;
do {
OSSL_LIB_CTX *osslglobal = NULL;
EVP_RAND_CTX *randctx = NULL;
LM_DBG("enabling locking for rand ctx\n");
osslglobal = OSSL_LIB_CTX_get0_global_default();
if(osslglobal == NULL) {
LM_ERR("failed to get lib ssl global ctx\n");
return -1;
}
randctx = RAND_get0_primary(osslglobal);
if(randctx == NULL) {
LM_ERR("primary rand ctx is null\n");
return -1;
}
EVP_RAND_enable_locking(randctx);
randctx = RAND_get0_public(osslglobal);
if(randctx == NULL) {
LM_ERR("public rand ctx is null\n");
return -1;
}
EVP_RAND_enable_locking(randctx);
randctx = RAND_get0_private(osslglobal);
if(randctx == NULL) {
LM_ERR("private rand ctx is null\n");
return -1;
}
EVP_RAND_enable_locking(randctx);
} while(0);
return 0;
}
#endif /* OPENSSL_VERSION_NUMBER */
@ -801,21 +801,19 @@ int tls_h_mod_pre_init_f(void)
SSL_load_error_strings();
#endif
#if 0
#if OPENSSL_VERSION_NUMBER >= 0x030000000L
/*
/*
* With deferred initialisation it is not necessary to enable threading
* on the EVP_RAND_CTX. We leave this block here as an example of how
* to do it in case of future requirements.
* on the EVP_RAND_CTX in tls_threads_mode = 1
*/
pthread_t tid;
long rl;
pthread_create(&tid, NULL, (void *(*)(void *))tls_h_mod_randctx, NULL);
pthread_join(tid, (void **)&rl);
if ((int)rl)
return (int)rl;
int ret;
if(ksr_tls_threads_mode == 0) {
ret = tls_h_mod_randctx();
if(ret)
return ret;
}
#endif /* OPENSSL_VERSION_NUMBER */
#endif /* 0 */
tls_mod_preinitialized = 1;
return 0;

@ -1,213 +0,0 @@
/**
* Copyright (c) 2014 rxi
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the MIT license. See LICENSE for details.
*/
#include <stdlib.h>
#include <string.h>
#include "../../core/mem/mem.h"
#include "tls_map.h"
struct map_node_t
{
unsigned hash;
void *value;
map_node_t *next;
/* char key[]; */
/* char value[]; */
};
static unsigned map_hash(const char *str)
{
unsigned hash = 5381;
while(*str) {
hash = ((hash << 5) + hash) ^ *str++;
}
return hash;
}
static map_node_t *map_newnode(const char *key, void *value, int vsize)
{
map_node_t *node;
int ksize = strlen(key) + 1;
int voffset = ksize + ((sizeof(void *) - ksize) % sizeof(void *));
node = pkg_malloc(sizeof(*node) + voffset + vsize);
if(!node)
return NULL;
memcpy(node + 1, key, ksize);
node->hash = map_hash(key);
node->value = ((char *)(node + 1)) + voffset;
memcpy(node->value, value, vsize);
return node;
}
static int map_bucketidx(map_base_t *m, unsigned hash)
{
/* If the implementation is changed to allow a non-power-of-2 bucket count,
* the line below should be changed to use mod instead of AND */
return hash & (m->nbuckets - 1);
}
static void map_addnode(map_base_t *m, map_node_t *node)
{
int n = map_bucketidx(m, node->hash);
node->next = m->buckets[n];
m->buckets[n] = node;
}
static int map_resize(map_base_t *m, int nbuckets)
{
map_node_t *nodes, *node, *next;
map_node_t **buckets;
int i;
/* Chain all nodes together */
nodes = NULL;
i = m->nbuckets;
while(i--) {
node = (m->buckets)[i];
while(node) {
next = node->next;
node->next = nodes;
nodes = node;
node = next;
}
}
/* Reset buckets */
buckets = realloc(m->buckets, sizeof(*m->buckets) * nbuckets);
if(buckets != NULL) {
m->buckets = buckets;
m->nbuckets = nbuckets;
}
if(m->buckets) {
memset(m->buckets, 0, sizeof(*m->buckets) * m->nbuckets);
/* Re-add nodes to buckets */
node = nodes;
while(node) {
next = node->next;
map_addnode(m, node);
node = next;
}
}
/* Return error code if realloc() failed */
return (buckets == NULL) ? -1 : 0;
}
static map_node_t **map_getref(map_base_t *m, const char *key)
{
unsigned hash = map_hash(key);
map_node_t **next;
if(m->nbuckets > 0) {
next = &m->buckets[map_bucketidx(m, hash)];
while(*next) {
if((*next)->hash == hash && !strcmp((char *)(*next + 1), key)) {
return next;
}
next = &(*next)->next;
}
}
return NULL;
}
void map_deinit_(map_base_t *m)
{
map_node_t *next, *node;
int i;
i = m->nbuckets;
while(i--) {
node = m->buckets[i];
while(node) {
next = node->next;
pkg_free(node);
node = next;
}
}
pkg_free(m->buckets);
}
void *map_get_(map_base_t *m, const char *key)
{
map_node_t **next = map_getref(m, key);
return next ? (*next)->value : NULL;
}
int map_set_(map_base_t *m, const char *key, void *value, int vsize)
{
int n, err;
map_node_t **next, *node;
/* Find & replace existing node */
next = map_getref(m, key);
if(next) {
memcpy((*next)->value, value, vsize);
return 0;
}
/* Add new node */
node = map_newnode(key, value, vsize);
if(node == NULL)
goto fail;
if(m->nnodes >= m->nbuckets) {
n = (m->nbuckets > 0) ? (m->nbuckets << 1) : 1;
err = map_resize(m, n);
if(err)
goto fail;
}
map_addnode(m, node);
m->nnodes++;
return 0;
fail:
if(node)
pkg_free(node);
return -1;
}
void map_remove_(map_base_t *m, const char *key)
{
map_node_t *node;
map_node_t **next = map_getref(m, key);
if(next) {
node = *next;
*next = (*next)->next;
pkg_free(node);
m->nnodes--;
}
}
map_iter_t map_iter_(void)
{
map_iter_t iter;
iter.bucketidx = -1;
iter.node = NULL;
return iter;
}
const char *map_next_(map_base_t *m, map_iter_t *iter)
{
if(iter->node) {
iter->node = iter->node->next;
if(iter->node == NULL)
goto nextBucket;
} else {
nextBucket:
do {
if(++iter->bucketidx >= m->nbuckets) {
return NULL;
}
iter->node = m->buckets[iter->bucketidx];
} while(iter->node == NULL);
}
return (char *)(iter->node + 1);
}

@ -1,77 +0,0 @@
/**
* Copyright (c) 2014 rxi
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the MIT license. See LICENSE for details.
*/
#ifndef _TLS_MAP_H
#define _TLS_MAP_H
#include <string.h>
#define MAP_VERSION "0.1.0"
struct map_node_t;
typedef struct map_node_t map_node_t;
typedef struct
{
map_node_t **buckets;
unsigned nbuckets, nnodes;
} map_base_t;
typedef struct
{
unsigned bucketidx;
map_node_t *node;
} map_iter_t;
#define map_t(T) \
struct \
{ \
map_base_t base; \
T *ref; \
T tmp; \
}
#define map_init(m) memset(m, 0, sizeof(*(m)))
#define map_deinit(m) map_deinit_(&(m)->base)
#define map_get(m, key) ((m)->ref = map_get_(&(m)->base, key))
#define map_set(m, key, value) \
((m)->tmp = (value), map_set_(&(m)->base, key, &(m)->tmp, sizeof((m)->tmp)))
#define map_remove(m, key) map_remove_(&(m)->base, key)
#define map_iter(m) map_iter_()
#define map_next(m, iter) map_next_(&(m)->base, iter)
void map_deinit_(map_base_t *m);
void *map_get_(map_base_t *m, const char *key);
int map_set_(map_base_t *m, const char *key, void *value, int vsize);
void map_remove_(map_base_t *m, const char *key);
map_iter_t map_iter_(void);
const char *map_next_(map_base_t *m, map_iter_t *iter);
typedef map_t(void *) map_void_t;
typedef map_t(char *) map_str_t;
typedef map_t(int) map_int_t;
typedef map_t(char) map_char_t;
typedef map_t(float) map_float_t;
typedef map_t(double) map_double_t;
#endif /* _TLS_MAP_H */

@ -42,6 +42,10 @@
#include "../../core/dprint.h"
#include "../../core/mod_fix.h"
#include "../../core/kemi.h"
#define KSR_RTHREAD_SKIP_P
#define KSR_RTHREAD_NEED_4PP
#include "../../core/rthreads.h"
#include "tls_init.h"
#include "tls_server.h"
#include "tls_domain.h"
@ -87,10 +91,23 @@ int ksr_rand_engine_param(modparam_t type, void *val);
MODULE_VERSION
#if OPENSSL_VERSION_NUMBER >= 0x030000000L
#define OPENSSL_NO_ENGINE
/* Engine is deprecated in OpenSSL 3 */
#if !defined(OPENSSL_NO_ENGINE) && OPENSSL_VERSION_NUMBER < 0x030000000L
#define KSR_SSL_COMMON
#define KSR_SSL_ENGINE
#define KEY_PREFIX "/engine:"
#define KEY_PREFIX_LEN (strlen(KEY_PREFIX))
#endif
#if !defined(OPENSSL_NO_PROVIDER) && OPENSSL_VERSION_NUMBER >= 0x030000000L
#define KSR_SSL_COMMON
#define KSR_SSL_PROVIDER
#include <openssl/store.h>
#define KEY_PREFIX "/uri:"
#define KEY_PREFIX_LEN (strlen(KEY_PREFIX))
#endif
extern str sr_tls_event_callback;
str sr_tls_xavp_cfg = {0, 0};
/*
@ -145,24 +162,29 @@ tls_domain_t srv_defaults = {
};
#ifndef OPENSSL_NO_ENGINE
#ifdef KSR_SSL_ENGINE
typedef struct tls_engine
{
str engine;
str engine_config;
str engine_algorithms;
} tls_engine_t;
#include <openssl/conf.h>
#include <openssl/engine.h>
static ENGINE *ksr_tls_engine;
static tls_engine_t tls_engine_settings = {
STR_STATIC_INIT("NONE"),
STR_STATIC_INIT("NONE"),
STR_STATIC_INIT("ALL"),
};
#endif /* OPENSSL_NO_ENGINE */
#include <openssl/conf.h>
#include <openssl/engine.h>
static ENGINE *ksr_tls_engine;
#endif
#ifdef KSR_SSL_PROVIDER
static int tls_provider_quirks;
#endif
/*
* Default settings for client domains when using external config file
*/
@ -227,12 +249,16 @@ static param_export_t params[] = {
{"crl", PARAM_STR, &default_tls_cfg.crl},
{"cipher_list", PARAM_STR, &default_tls_cfg.cipher_list},
{"connection_timeout", PARAM_INT, &default_tls_cfg.con_lifetime},
#ifndef OPENSSL_NO_ENGINE
#ifdef KSR_SSL_ENGINE
{"engine", PARAM_STR, &tls_engine_settings.engine},
{"engine_config", PARAM_STR, &tls_engine_settings.engine_config},
{"engine_algorithms", PARAM_STR,
&tls_engine_settings.engine_algorithms},
#endif /* OPENSSL_NO_ENGINE */
#endif /* KSR_SSL_ENGINE */
#ifdef KSR_SSL_PROVIDER
{"provider_quirks", PARAM_INT,
&tls_provider_quirks}, /* OpenSSL 3 provider that needs new OSSL_LIB_CTX in child */
#endif /* KSR_SSL_PROVIDER */
{"tls_log", PARAM_INT, &default_tls_cfg.log},
{"tls_debug", PARAM_INT, &default_tls_cfg.debug},
{"session_cache", PARAM_INT, &default_tls_cfg.session_cache},
@ -311,11 +337,28 @@ static tls_domains_cfg_t* tls_use_modparams(void)
}
#endif
/* global config tls_threads_mode = 2
* - force all thread-locals to be 0x0 after fork()
* - with OpenSSL loaded the largest value observed
* is < 10
*
*/
static int tls_pthreads_key_mark;
static void fork_child(void)
{
int k;
for(k = 0; k < tls_pthreads_key_mark; k++) {
if(pthread_getspecific(k) != 0)
pthread_setspecific(k, 0x0);
}
}
static int mod_init(void)
{
int method;
int verify_client;
unsigned char rand_buf[32];
int k;
if(tls_disable) {
LM_WARN("tls support is disabled "
@ -420,6 +463,26 @@ static int mod_init(void)
if(ksr_tls_init_mode & TLS_MODE_FORK_PREPARE) {
ksr_module_set_flag(KSRMOD_FLAG_POSTCHILDINIT);
}
#endif
if(ksr_tls_threads_mode == 2) {
pthread_atfork(NULL, NULL, &fork_child);
}
#if OPENSSL_VERSION_NUMBER >= 0x010101000L
/*
* force creation of all thread-locals now so that other libraries
* that use pthread_key_create(), e.g. python,
* will have larger key values
*/
if(ksr_tls_threads_mode > 0) {
ERR_clear_error();
RAND_bytes(rand_buf, sizeof(rand_buf));
for(k = 0; k < 32; k++) {
if(pthread_getspecific(k))
tls_pthreads_key_mark = k + 1;
}
LM_WARN("set maximum pthreads key to %d\n", tls_pthreads_key_mark);
}
#endif
return 0;
error:
@ -428,10 +491,10 @@ error:
}
#ifndef OPENSSL_NO_ENGINE
#ifdef KSR_SSL_COMMON
static int tls_engine_init();
int tls_fix_engine_keys(tls_domains_cfg_t *, tls_domain_t *, tls_domain_t *);
#endif
#endif /* KSR_SSL_COMMON */
/*
* OpenSSL 1.1.1+: SSL_CTX is repeated in each worker
@ -443,50 +506,76 @@ int tls_fix_engine_keys(tls_domains_cfg_t *, tls_domain_t *, tls_domain_t *);
*
* EC operations do not use pthread_self(), so could use shared SSL_CTX
*/
static int mod_child_hook(int *rank, void *dummy)
{
LM_INFO("Loading SSL_CTX in process_no=%d rank=%d "
"ksr_tls_threads_mode=%d\n",
process_no, *rank, ksr_tls_threads_mode);
if(cfg_get(tls, tls_cfg, config_file).s) {
if(tls_fix_domains_cfg(*tls_domains_cfg, &srv_defaults, &cli_defaults)
< 0)
return -1;
} else {
if(tls_fix_domains_cfg(*tls_domains_cfg, &mod_params, &mod_params) < 0)
return -1;
}
return 0;
}
#ifdef KSR_SSL_PROVIDER
static OSSL_LIB_CTX *orig_ctx;
static OSSL_LIB_CTX *new_ctx;
#endif
static int mod_child(int rank)
{
int k;
if(tls_disable || (tls_domains_cfg == 0))
return 0;
#if OPENSSL_VERSION_NUMBER >= 0x010101000L
/*
* OpenSSL 3.x/1.1.1: create shared SSL_CTX* in worker to avoid init of
* libssl in rank 0(thread#1)
*/
if(rank == PROC_SIPINIT) {
#else
if(rank == PROC_INIT) {
#endif
if(cfg_get(tls, tls_cfg, config_file).s) {
if(tls_fix_domains_cfg(
*tls_domains_cfg, &srv_defaults, &cli_defaults)
< 0)
return -1;
} else {
if(tls_fix_domains_cfg(*tls_domains_cfg, &mod_params, &mod_params)
< 0)
return -1;
}
return 0;
/*
* OpenSSL 3.x/1.1.1: create shared SSL_CTX* in thread executor
* to avoid init of libssl in thread#1: ksr_tls_threads_mode = 1
*/
if(rank == PROC_INIT) {
return run_thread4PP((_thread_proto4PP)mod_child_hook, &rank, NULL);
}
if(ksr_tls_threads_mode == 1 && rank && rank != PROC_INIT
&& rank != PROC_POSTCHILDINIT) {
for(k = 0; k < tls_pthreads_key_mark; k++)
pthread_setspecific(k, 0x0);
LM_WARN("clean-up of thread-locals key < %d\n", tls_pthreads_key_mark);
}
#ifndef OPENSSL_NO_ENGINE
#ifdef KSR_SSL_COMMON
/*
* after the child is fork()ed we go through the TLS domains
* and fix up private keys from engine
*/
#ifdef KSR_SSL_ENGINE
if(!strncmp(tls_engine_settings.engine.s, "NONE", 4))
return 0;
#endif /* KSR_SSL_ENGINE */
if(rank > 0) {
#ifdef KSR_SSL_PROVIDER
if(tls_provider_quirks & 1) {
new_ctx = OSSL_LIB_CTX_new();
orig_ctx = OSSL_LIB_CTX_set0_default(new_ctx);
CONF_modules_load_file(CONF_get1_default_config_file(), NULL, 0L);
}
#endif /* KSR_SSL_PROVIDER */
if(tls_engine_init() < 0)
return -1;
if(tls_fix_engine_keys(*tls_domains_cfg, &srv_defaults, &cli_defaults)
< 0)
return -1;
LM_INFO("OpenSSL Engine loaded private keys in child: %d\n", rank);
LM_INFO("OpenSSL loaded private keys in child: %d\n", rank);
}
#endif
#endif /* KSR_SSL_PROVIDER */
return 0;
}
@ -678,17 +767,25 @@ int mod_register(char *path, int *dlflags, void *p1, void *p2)
register_tls_hooks(&tls_h);
/*
/*
* GH #3695: OpenSSL 1.1.1 historical note: it is no longer
* needed to replace RAND with cryptorand
* needed to replace RAND with cryptorand in tls_threads_mode = 1
*/
#if OPENSSL_VERSION_NUMBER >= 0x10100000L \
&& OPENSSL_VERSION_NUMBER < 0x030000000L
if(ksr_tls_threads_mode == 0) {
LM_WARN("OpenSSL 1.1.1 setting cryptorand random engine\n");
RAND_set_rand_method(RAND_ksr_cryptorand_method());
}
#endif
sr_kemi_modules_add(sr_kemi_tls_exports);
return 0;
}
#ifndef OPENSSL_NO_ENGINE
#ifdef KSR_SSL_ENGINE
/*
* initialize OpenSSL engine in child process
* PKCS#11 libraries are not guaranteed to be fork() safe
@ -714,6 +811,7 @@ static int tls_engine_init()
* We are in the child process and the global engine linked-list
* is initialized in the parent.
*/
ENGINE_load_builtin_engines();
e = ENGINE_by_id("dynamic");
if(!e) {
err = "Error loading dynamic engine";
@ -781,4 +879,53 @@ EVP_PKEY *tls_engine_private_key(const char *key_id)
{
return ENGINE_load_private_key(ksr_tls_engine, key_id, NULL, NULL);
}
#endif /* KSR_SSL_ENGINE */
#ifdef KSR_SSL_PROVIDER
#include <openssl/store.h>
static int tls_engine_init()
{
return 0;
}
EVP_PKEY *tls_engine_private_key(const char *key_id)
{
OSSL_STORE_CTX *ctx;
EVP_PKEY *pkey = NULL;
ctx = OSSL_STORE_open_ex(key_id, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
if(!ctx) {
LM_ERR("[ERR] could not load URI %s\n", key_id);
goto error;
}
OSSL_STORE_expect(ctx, OSSL_STORE_INFO_PKEY);
while(!(OSSL_STORE_eof(ctx))) {
OSSL_STORE_INFO *info = OSSL_STORE_load(ctx);
if(info == NULL)
continue;
int type;
type = OSSL_STORE_INFO_get_type(info);
switch(type) {
case OSSL_STORE_INFO_PKEY:
pkey = OSSL_STORE_INFO_get1_PKEY(info);
break;
default:
continue;
break;
}
OSSL_STORE_INFO_free(info);
if(pkey)
break;
}
LM_INFO("Loaded private key = %p\n", pkey);
error:
OSSL_STORE_close(ctx);
return pkey;
}
#endif

@ -21,10 +21,10 @@
#define _TLS_RAND_H_
#include <openssl/ssl.h>
#include <openssl/rand.h>
#if OPENSSL_VERSION_NUMBER >= 0x10100000L \
&& OPENSSL_VERSION_NUMBER < 0x030000000L
#include <openssl/rand.h>
const RAND_METHOD *RAND_ksr_krand_method(void);
const RAND_METHOD *RAND_ksr_fastrand_method(void);

@ -128,10 +128,6 @@ int tls_run_event_routes(struct tcp_connection *c);
#endif /* __SUNPRO_c */
#endif /* TLS_RD_DEBUG */
#if OPENSSL_VERSION_NUMBER >= 0x030000000L
#define OPENSSL_NO_ENGINE
#endif
extern str sr_tls_xavp_cfg;
static str _ksr_tls_connect_server_id = STR_NULL;
@ -426,11 +422,6 @@ static void tls_dump_cert_info(char *s, X509 *cert)
}
}
#ifndef OPENSSL_NO_ENGINE
// lookup HSM keys in process-local memory
EVP_PKEY *tls_lookup_private_key(SSL_CTX *);
#endif
/** wrapper around SSL_accept, usin SSL return convention.
* It will also log critical errors and certificate debugging info.
* @param c - tcp connection with tls (extra_data must be a filled
@ -461,12 +452,7 @@ int tls_accept(struct tcp_connection *c, int *error)
BUG("Invalid connection state %d (bug in TLS code)\n", tls_c->state);
goto err;
}
#ifndef OPENSSL_NO_ENGINE
/* check if we have a HSM key */
EVP_PKEY *pkey = tls_lookup_private_key(SSL_get_SSL_CTX(ssl));
if(pkey)
SSL_use_PrivateKey(ssl, pkey);
#endif
tls_openssl_clear_errors();
ret = SSL_accept(ssl);
if(unlikely(ret == 1)) {
@ -531,13 +517,7 @@ int tls_connect(struct tcp_connection *c, int *error)
BUG("Invalid connection state %d (bug in TLS code)\n", tls_c->state);
goto err;
}
#ifndef OPENSSL_NO_ENGINE
// lookup HSM private key in process-local memory
EVP_PKEY *pkey = tls_lookup_private_key(SSL_get_SSL_CTX(ssl));
if(pkey) {
SSL_use_PrivateKey(ssl, pkey);
}
#endif
tls_openssl_clear_errors();
ret = SSL_connect(ssl);
if(unlikely(ret == 1)) {

@ -1,308 +0,0 @@
/*
* 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 "../../core/compiler_opt.h"
#include "../../core/dprint.h"
#include "../../core/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 0x4f2
/* debugging */
#ifdef NO_TLS_BIO_DEBUG
#undef TLS_BIO_DEBUG
#endif
#ifdef TLS_BIO_DEBUG
#ifdef __SUNPRO_C
#define TLS_BIO_DBG(...) \
LOG_FP(DEFAULT_FACILITY, cfg_get(tls, tls_cfg, debug), \
"tls_BIO: " LOC_INFO, __VA_ARGS__)
#else
#define TLS_BIO_DBG(args...) \
LOG_FP(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(WOLFSSL_BIO *b);
static int tls_bio_mbuf_free(WOLFSSL_BIO *b);
static int tls_bio_mbuf_write(WOLFSSL_BIO *b, const char *buf, int num);
static int tls_bio_mbuf_read(WOLFSSL_BIO *b, char *buf, int num);
static int tls_bio_mbuf_puts(WOLFSSL_BIO *b, const char *s);
static long tls_bio_mbuf_ctrl(WOLFSSL_BIO *b, int cmd, long arg1, void *arg2);
static WOLFSSL_BIO_METHOD *tls_mbuf_method = NULL;
/** returns a custom tls_mbuf BIO. */
WOLFSSL_BIO_METHOD *tls_BIO_mbuf(void)
{
if(tls_mbuf_method != NULL) {
return tls_mbuf_method;
}
tls_mbuf_method = wolfSSL_BIO_meth_new(BIO_TYPE_TLS_MBUF, "sr_tls_mbuf");
if(tls_mbuf_method == NULL) {
LM_ERR("cannot get a new bio method structure\n");
return NULL;
}
wolfSSL_BIO_meth_set_write(tls_mbuf_method, tls_bio_mbuf_write);
wolfSSL_BIO_meth_set_read(tls_mbuf_method, tls_bio_mbuf_read);
wolfSSL_BIO_meth_set_puts(tls_mbuf_method, tls_bio_mbuf_puts);
wolfSSL_BIO_meth_set_gets(tls_mbuf_method, NULL);
wolfSSL_BIO_meth_set_ctrl(tls_mbuf_method, tls_bio_mbuf_ctrl);
wolfSSL_BIO_meth_set_create(tls_mbuf_method, tls_bio_mbuf_new);
wolfSSL_BIO_meth_set_destroy(tls_mbuf_method, tls_bio_mbuf_free);
return tls_mbuf_method;
}
/** create an initialize a new tls_BIO_mbuf.
* @return new BIO on success (!=0), 0 on error.
*/
WOLFSSL_BIO *tls_BIO_new_mbuf(struct tls_mbuf *rd, struct tls_mbuf *wr)
{
WOLFSSL_BIO *ret;
TLS_BIO_DBG("tls_BIO_new_mbuf called (%p, %p)\n", rd, wr);
ret = wolfSSL_BIO_new(tls_BIO_mbuf());
if(unlikely(ret == 0))
return 0;
if(unlikely(tls_BIO_mbuf_set(ret, rd, wr) == 0)) {
wolfSSL_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(WOLFSSL_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);
d = wolfSSL_BIO_get_data(b);
if(unlikely(d == 0)) {
BUG("null BIO ptr data\n");
return 0;
}
d->rd = rd;
d->wr = wr;
wolfSSL_BIO_set_init(b, 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(WOLFSSL_BIO *b)
{
struct tls_bio_mbuf_data *d;
TLS_BIO_DBG("tls_bio_mbuf_new called (%p)\n", b);
wolfSSL_BIO_set_init(b, 0);
wolfSSL_BIO_set_data(b, NULL);
d = wolfSSL_Malloc(sizeof(*d));
memset(d, 0, sizeof(*d));
if(unlikely(d == 0))
return 0;
wolfSSL_BIO_set_data(b, 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(WOLFSSL_BIO *b)
{
TLS_BIO_DBG("tls_bio_mbuf_free called (%p)\n", b);
if(unlikely(b == 0))
return 0;
do {
struct tls_bio_mbuf_data *d;
d = wolfSSL_BIO_get_data(b);
if(likely(d)) {
wolfSSL_OPENSSL_free(d);
wolfSSL_BIO_set_data(b, NULL);
wolfSSL_BIO_set_init(b, 0);
}
} while(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(WOLFSSL_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 = wolfSSL_BIO_get_data(b);
wolfSSL_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))
wolfSSL_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(WOLFSSL_BIO *b, const char *src, int src_len)
{
struct tls_bio_mbuf_data *d;
struct tls_mbuf *wr;
int ret;
ret = 0;
d = wolfSSL_BIO_get_data(b);
wolfSSL_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))
wolfSSL_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(WOLFSSL_BIO *b, int cmd, long arg1, void *arg2)
{
long ret;
ret = 0;
switch(cmd) {
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_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(WOLFSSL_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: */

@ -1,68 +0,0 @@
/*
* 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 modules/tls/tls_bio.h
* @ingroup tls
*/
#ifndef __tls_bio_h
#define __tls_bio_h
#include <wolfssl/options.h>
#include <wolfssl/ssl.h>
/* memory buffer used for tls I/O */
struct tls_mbuf
{
unsigned char *buf;
int pos; /**< current position in the buffer while reading or writing*/
int used; /**< how much it's used (read or write)*/
int size; /**< total buffer size (fixed) */
};
struct tls_bio_mbuf_data
{
struct tls_mbuf *rd;
struct tls_mbuf *wr;
};
WOLFSSL_BIO_METHOD *tls_BIO_mbuf(void);
WOLFSSL_BIO *tls_BIO_new_mbuf(struct tls_mbuf *rd, struct tls_mbuf *wr);
int tls_BIO_mbuf_set(WOLFSSL_BIO *b, struct tls_mbuf *rd, struct tls_mbuf *wr);
/** initialize an mbuf structure.
* @param mb - struct tls_mbuf pointer that will be initialized.
* @param b - buffer (unsigned char*).
* @param sz - suze of the buffer (int).
* WARNING: the buffer will not be copied, but referenced.
*/
#define tls_mbuf_init(mb, b, sz) \
do { \
(mb)->buf = (b); \
(mb)->size = (sz); \
(mb)->pos = 0; \
(mb)->used = 0; \
} while(0)
#endif /*__tls_bio_h*/
/* vi: set ts=4 sw=4 tw=79:ai:cindent: */

@ -60,8 +60,6 @@ struct cfg_group_tls default_tls_cfg = {
-1, /* ssl_max_send_fragment (use the default: 16k), requires openssl
> 0.9.9 */
0, /* ssl_read_ahead (off, not needed, we have our own buffering BIO)*/
-1, /* low_mem_threshold1 */
-1, /* low_mem_threshold2 */
10 * 1024 * 1024, /* ct_wq_max: 10 Mb by default */
64 * 1024, /* con_ct_wq_max: 64Kb by default */
4096, /* ct_wq_blk_size */
@ -200,12 +198,6 @@ cfg_def_t tls_cfg_def[] = {{"force_run", CFG_VAR_INT | CFG_READONLY, 0, 1, 0, 0,
" module versions it is better to have read ahead disabled, "
"since"
" everything it is buffered in memory anyway"},
{"low_mem_threshold1", CFG_VAR_INT | CFG_ATOMIC, -1, 1 << 30, 0, 0,
"sets the minimum amount of free memory for accepting new TLS"
" connections (KB)"},
{"low_mem_threshold2", CFG_VAR_INT | CFG_ATOMIC, -1, 1 << 30, 0, 0,
"sets the minimum amount of free memory after which no more TLS"
" operations will be attempted (even on existing connections)"},
{"ct_wq_max", CFG_VAR_INT | CFG_ATOMIC, 0, 1 << 30, 0, 0,
"maximum bytes queued globally for write when write has to "
"wait due"

@ -90,8 +90,6 @@ struct cfg_group_tls
* now)
*/
int ssl_read_ahead;
int low_mem_threshold1;
int low_mem_threshold2;
int ct_wq_max; /* maximum overall tls write clear text queued bytes */
int con_ct_wq_max; /* maximum clear text write queued bytes per con */
int ct_wq_blk_size; /* minimum block size for the clear text write queue */

@ -29,9 +29,6 @@
#include "../../core/str.h"
#include "tls_domain.h"
#include <wolfssl/options.h>
#include <wolfssl/ssl.h>
tls_domains_cfg_t *tls_load_config(str *filename);
/*

@ -29,7 +29,6 @@
#define __tls_ct_wrq_h
#include "tls_ct_q.h"
#include "tls_server.h"
#include "../../core/tcp_conn.h"

@ -26,10 +26,6 @@
#include <stdlib.h>
#include <wolfssl/options.h>
#include <wolfssl/ssl.h>
// # include <wolfssl/openssl/ui.h>
#include "../../core/ut.h"
#include "../../core/mem/shm_mem.h"
#include "../../core/pt.h"
@ -157,17 +153,13 @@ tls_domain_t *tls_new_domain(int type, struct ip_addr *ip, unsigned short port)
*/
void tls_free_domain(tls_domain_t *d)
{
int i;
int procs_no;
if(!d)
return;
if(d->ctx) {
procs_no = get_max_procs();
for(i = 0; i < procs_no; i++) {
if(d->ctx[i])
wolfSSL_CTX_free(d->ctx[i]);
}
do {
if(d->ctx[0])
wolfSSL_CTX_free(d->ctx[0]);
} while(0);
shm_free(d->ctx);
}
@ -378,14 +370,12 @@ typedef int (*per_ctx_cbk_f)(WOLFSSL_CTX *ctx, long larg, void *parg);
static int tls_domain_foreach_CTX(
tls_domain_t *d, per_ctx_cbk_f ctx_cbk, long l1, void *p2)
{
int i, ret;
int procs_no;
int ret;
procs_no = get_max_procs();
for(i = 0; i < procs_no; i++) {
if((ret = ctx_cbk(d->ctx[i], l1, p2)) < 0)
do {
if((ret = ctx_cbk(d->ctx[0], l1, p2)) < 0)
return ret;
}
} while(0);
return 0;
}
@ -519,24 +509,21 @@ int fix_shm_pathname(str *path)
*/
static int load_cert(tls_domain_t *d)
{
int i;
int procs_no;
if(!d->cert_file.s || !d->cert_file.len) {
DBG("%s: No certificate configured\n", tls_domain_str(d));
return 0;
}
if(fix_shm_pathname(&d->cert_file) < 0)
return -1;
procs_no = get_max_procs();
for(i = 0; i < procs_no; i++) {
if(!wolfSSL_CTX_use_certificate_chain_file(d->ctx[i], d->cert_file.s)) {
do {
if(!wolfSSL_CTX_use_certificate_chain_file(d->ctx[0], d->cert_file.s)) {
ERR("%s: Unable to load certificate file '%s'\n", tls_domain_str(d),
d->cert_file.s);
TLS_ERR("load_cert:");
return -1;
}
}
} while(0);
return 0;
}
@ -548,9 +535,6 @@ static int load_cert(tls_domain_t *d)
*/
static int load_ca_list(tls_domain_t *d)
{
int i;
int procs_no;
if((!d->ca_file.s || !d->ca_file.len)
&& (!d->ca_path.s || !d->ca_path.len)) {
DBG("%s: No CA list configured\n", tls_domain_str(d));
@ -560,10 +544,10 @@ static int load_ca_list(tls_domain_t *d)
return -1;
if(d->ca_path.s && d->ca_path.len > 0 && fix_shm_pathname(&d->ca_path) < 0)
return -1;
procs_no = get_max_procs();
for(i = 0; i < procs_no; i++) {
do {
if(wolfSSL_CTX_load_verify_locations(
d->ctx[i], d->ca_file.s, d->ca_path.s)
d->ctx[0], d->ca_file.s, d->ca_path.s)
!= 1) {
ERR("%s: Unable to load CA list file '%s' dir '%s'\n",
tls_domain_str(d), (d->ca_file.s) ? d->ca_file.s : "",
@ -573,8 +557,8 @@ static int load_ca_list(tls_domain_t *d)
}
if(d->ca_file.s && d->ca_file.len > 0) {
wolfSSL_CTX_set_client_CA_list(
d->ctx[i], wolfSSL_load_client_CA_file(d->ca_file.s));
if(wolfSSL_CTX_get_client_CA_list(d->ctx[i]) == 0) {
d->ctx[0], wolfSSL_load_client_CA_file(d->ca_file.s));
if(wolfSSL_CTX_get_client_CA_list(d->ctx[0]) == 0) {
ERR("%s: Error while setting client CA list file [%.*s/%d]\n",
tls_domain_str(d), (d->ca_file.s) ? d->ca_file.len : 0,
(d->ca_file.s) ? d->ca_file.s : "", d->ca_file.len);
@ -582,7 +566,7 @@ static int load_ca_list(tls_domain_t *d)
return -1;
}
}
}
} while(0);
return 0;
}
@ -594,9 +578,7 @@ static int load_ca_list(tls_domain_t *d)
*/
static int load_crl(tls_domain_t *d)
{
int i;
int procs_no;
X509_STORE *store;
WOLFSSL_X509_STORE *store;
if(!d->crl_file.s) {
DBG("%s: No CRL configured\n", tls_domain_str(d));
@ -606,19 +588,19 @@ static int load_crl(tls_domain_t *d)
return -1;
LOG(L_INFO, "%s: Certificate revocation lists will be checked (%.*s)\n",
tls_domain_str(d), d->crl_file.len, d->crl_file.s);
procs_no = get_max_procs();
for(i = 0; i < procs_no; i++) {
if(wolfSSL_CTX_load_verify_locations(d->ctx[i], d->crl_file.s, 0)
do {
if(wolfSSL_CTX_load_verify_locations(d->ctx[0], d->crl_file.s, 0)
!= 1) {
ERR("%s: Unable to load certificate revocation list '%s'\n",
tls_domain_str(d), d->crl_file.s);
TLS_ERR("load_crl:");
return -1;
}
store = wolfSSL_CTX_get_cert_store(d->ctx[i]);
X509_STORE_set_flags(
store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
}
store = wolfSSL_CTX_get_cert_store(d->ctx[0]);
wolfSSL_X509_STORE_set_flags(
store, WOLFSSL_CRL_CHECK | WOLFSSL_CRL_CHECKALL);
} while(0);
return 0;
}
@ -636,43 +618,20 @@ static int load_crl(tls_domain_t *d)
static int set_cipher_list(tls_domain_t *) __attribute__((unused));
static int set_cipher_list(tls_domain_t *d)
{
int i;
int procs_no;
char *cipher_list;
cipher_list = d->cipher_list.s;
#ifdef TLS_KSSL_WORKAROUND
if(openssl_kssl_malloc_bug) { /* is openssl bug #1467 present ? */
if(d->cipher_list.s == 0) {
/* use "DEFAULT:!KRB5" */
cipher_list = "DEFAULT:!KRB5";
} else {
/* append ":!KRB5" */
cipher_list =
shm_malloc(d->cipher_list.len + C_NO_KRB5_SUFFIX_LEN + 1);
if(cipher_list) {
memcpy(cipher_list, d->cipher_list.s, d->cipher_list.len);
memcpy(cipher_list + d->cipher_list.len, C_NO_KRB5_SUFFIX,
C_NO_KRB5_SUFFIX_LEN);
cipher_list[d->cipher_list.len + C_NO_KRB5_SUFFIX_LEN] = 0;
shm_free(d->cipher_list.s);
d->cipher_list.s = cipher_list;
d->cipher_list.len += C_NO_KRB5_SUFFIX_LEN;
}
}
}
#endif /* TLS_KSSL_WORKAROUND */
if(!cipher_list)
return 0;
procs_no = get_max_procs();
for(i = 0; i < procs_no; i++) {
if(wolfSSL_CTX_set_cipher_list(d->ctx[i], cipher_list) == 0) {
do {
if(wolfSSL_CTX_set_cipher_list(d->ctx[0], cipher_list) == 0) {
ERR("%s: Failure to set SSL context cipher list \"%s\"\n",
tls_domain_str(d), cipher_list);
return -1;
}
setup_dh(d->ctx[i]);
}
setup_dh(d->ctx[0]);
} while(0);
return 0;
}
@ -684,8 +643,7 @@ static int set_cipher_list(tls_domain_t *d)
*/
static int set_verification(tls_domain_t *d)
{
int verify_mode, i;
int procs_no;
int verify_mode;
if(d->require_cert || d->verify_client == TLS_VERIFY_CLIENT_ON) {
verify_mode = WOLFSSL_VERIFY_PEER | WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT;
@ -718,17 +676,16 @@ static int set_verification(tls_domain_t *d)
}
}
procs_no = get_max_procs();
for(i = 0; i < procs_no; i++) {
do {
if(d->verify_client >= TLS_VERIFY_CLIENT_OPTIONAL_NO_CA) {
/* Note that actual verification result is available in $tls_peer_verified */
wolfSSL_CTX_set_verify(d->ctx[i], verify_mode,
wolfSSL_CTX_set_verify(d->ctx[0], verify_mode,
verify_callback_unconditional_success);
} else {
wolfSSL_CTX_set_verify(d->ctx[i], verify_mode, 0);
wolfSSL_CTX_set_verify(d->ctx[0], verify_mode, 0);
}
wolfSSL_CTX_set_verify_depth(d->ctx[i], d->verify_depth);
}
wolfSSL_CTX_set_verify_depth(d->ctx[0], d->verify_depth);
} while(0);
return 0;
}
@ -769,21 +726,17 @@ static void sr_ssl_ctx_info_callback(const SSL *ssl, int event, int ret)
*/
static int set_ssl_options(tls_domain_t *d)
{
int i;
int procs_no;
long options;
procs_no = get_max_procs();
options = SSL_OP_ALL; /* all the bug workarounds by default */
options |= SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
| SSL_OP_CIPHER_SERVER_PREFERENCE;
| WOLFSSL_OP_CIPHER_SERVER_PREFERENCE;
for(i = 0; i < procs_no; i++) {
wolfSSL_CTX_set_options(d->ctx[i], options);
do {
wolfSSL_CTX_set_options(d->ctx[0], options);
if(sr_tls_renegotiation == 0)
wolfSSL_CTX_set_info_callback(d->ctx[i], sr_ssl_ctx_info_callback);
}
wolfSSL_CTX_set_info_callback(d->ctx[0], sr_ssl_ctx_info_callback);
} while(0);
return 0;
}
@ -795,24 +748,21 @@ static int set_ssl_options(tls_domain_t *d)
*/
static int set_session_cache(tls_domain_t *d)
{
int i;
int procs_no;
str tls_session_id;
procs_no = get_max_procs();
tls_session_id = cfg_get(tls, tls_cfg, session_id);
for(i = 0; i < procs_no; i++) {
do {
/* janakj: I am not sure if session cache makes sense in ser, session
* cache is stored in SSL_CTX and we have one SSL_CTX per process,
* thus sessions among processes will not be reused
*/
wolfSSL_CTX_set_session_cache_mode(d->ctx[i],
cfg_get(tls, tls_cfg, session_cache) ? SSL_SESS_CACHE_SERVER
: SSL_SESS_CACHE_OFF);
wolfSSL_CTX_set_session_cache_mode(d->ctx[0],
cfg_get(tls, tls_cfg, session_cache) ? WOLFSSL_SESS_CACHE_SERVER
: WOLFSSL_SESS_CACHE_OFF);
/* not really needed is SSL_SESS_CACHE_OFF */
wolfSSL_CTX_set_session_id_context(d->ctx[i],
wolfSSL_CTX_set_session_id_context(d->ctx[0],
(unsigned char *)tls_session_id.s, tls_session_id.len);
}
} while(0);
return 0;
}
@ -844,6 +794,7 @@ static int tls_ssl_ctx_mode(WOLFSSL_CTX *ctx, long mode, void *clear)
*/
static int tls_ssl_ctx_set_freelist(WOLFSSL_CTX *ctx, long val, void *unused)
{
/* NOOP */
return 0;
}
@ -857,10 +808,7 @@ static int tls_ssl_ctx_set_freelist(WOLFSSL_CTX *ctx, long val, void *unused)
static int tls_ssl_ctx_set_max_send_fragment(
WOLFSSL_CTX *ctx, long val, void *unused)
{
/* WOLFFIX if (val >= 0)
return SSL_CTX_set_max_send_fragment(ctx, val) -1;
*/
/* NOOP */
return 0;
}
@ -891,8 +839,7 @@ static int tls_server_name_cb(SSL *ssl, int *ad, void *private)
str server_name;
orig_domain = (tls_domain_t *)private;
server_name.s =
(char *)wolfSSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
server_name.s = (char *)wolfSSL_get_servername(ssl, WOLFSSL_SNI_HOST_NAME);
if(server_name.s) {
LM_DBG("received server_name (TLS extension): '%s'\n", server_name.s);
} else {
@ -918,10 +865,9 @@ static int tls_server_name_cb(SSL *ssl, int *ad, void *private)
" socket [%s:%d] server name='%s' -"
" switching SSL CTX to %p dom %p%s\n",
server_name.s, ip_addr2a(&new_domain->ip), new_domain->port,
ZSW(new_domain->server_name.s), new_domain->ctx[process_no],
new_domain,
ZSW(new_domain->server_name.s), new_domain->ctx[0], new_domain,
(new_domain->type & TLS_DOMAIN_DEF) ? " (default)" : "");
wolfSSL_set_SSL_CTX(ssl, new_domain->ctx[process_no]);
wolfSSL_set_SSL_CTX(ssl, new_domain->ctx[0]);
/* SSL_set_SSL_CTX only sets the correct certificate parameters, but does
set the proper verify options. Thus this will be done manually! */
@ -952,9 +898,6 @@ static int tls_server_name_cb(SSL *ssl, int *ad, void *private)
*/
static int ksr_tls_fix_domain(tls_domain_t *d, tls_domain_t *def)
{
int i;
int procs_no;
if(ksr_tls_fill_missing(d, def) < 0)
return -1;
@ -966,8 +909,7 @@ static int ksr_tls_fix_domain(tls_domain_t *d, tls_domain_t *def)
}
}
procs_no = get_max_procs();
d->ctx = (WOLFSSL_CTX **)shm_malloc(sizeof(WOLFSSL_CTX *) * procs_no);
d->ctx = (WOLFSSL_CTX **)shm_malloc(sizeof(WOLFSSL_CTX *) * 1);
if(!d->ctx) {
ERR("%s: Cannot allocate shared memory\n", tls_domain_str(d));
return -1;
@ -977,38 +919,21 @@ static int ksr_tls_fix_domain(tls_domain_t *d, tls_domain_t *def)
} else {
LM_DBG("using one tls method version: %d\n", d->method);
}
memset(d->ctx, 0, sizeof(WOLFSSL_CTX *) * procs_no);
for(i = 0; i < procs_no; i++) {
memset(d->ctx, 0, sizeof(WOLFSSL_CTX *) * 1);
do {
/* libssl >= 1.1.0 */
//d->ctx[i] = SSL_CTX_new(sr_tls_methods[d->method - 1].TLSMethod);
d->ctx[i] = wolfSSL_CTX_new(wolfSSLv23_method());
if(d->ctx[i] == NULL) {
d->ctx[0] = wolfSSL_CTX_new(wolfSSLv23_method());
if(d->ctx[0] == NULL) {
unsigned long e = 0;
e = ERR_peek_last_error();
ERR("%s: Cannot create SSL context [%d] (%lu: %s / %s)\n",
tls_domain_str(d), i, e, ERR_error_string(e, NULL),
tls_domain_str(d), 0, e, ERR_error_string(e, NULL),
ERR_reason_error_string(e));
return -1;
}
wolfSSL_CTX_set_min_proto_version(d->ctx[i], TLS1_2_VERSION);
#if 0
if(d->method>TLS_USE_TLSvRANGE) {
if(sr_tls_methods[d->method - 1].TLSMethodMin) {
SSL_CTX_set_min_proto_version(d->ctx[i],
sr_tls_methods[d->method - 1].TLSMethodMin);
}
} else {
if(sr_tls_methods[d->method - 1].TLSMethodMin) {
SSL_CTX_set_min_proto_version(d->ctx[i],
sr_tls_methods[d->method - 1].TLSMethodMin);
}
if(sr_tls_methods[d->method - 1].TLSMethodMax) {
SSL_CTX_set_max_proto_version(d->ctx[i],
sr_tls_methods[d->method - 1].TLSMethodMax);
}
}
#endif
wolfSSL_CTX_set_min_proto_version(d->ctx[0], TLS1_2_VERSION);
/*
* check server domains for server_name extension and register
@ -1017,22 +942,22 @@ static int ksr_tls_fix_domain(tls_domain_t *d, tls_domain_t *def)
if((d->type & TLS_DOMAIN_SRV)
&& (d->server_name.len > 0 || (d->type & TLS_DOMAIN_DEF))) {
if(!wolfSSL_CTX_set_tlsext_servername_callback(
d->ctx[i], tls_server_name_cb)) {
d->ctx[0], tls_server_name_cb)) {
LM_ERR("register server_name callback handler for socket "
"[%s:%d], server_name='%s' failed for proc %d\n",
ip_addr2a(&d->ip), d->port,
(d->server_name.s) ? d->server_name.s : "<default>", i);
(d->server_name.s) ? d->server_name.s : "<default>", 0);
return -1;
}
if(!wolfSSL_CTX_set_servername_arg(d->ctx[i], d)) {
if(!wolfSSL_CTX_set_servername_arg(d->ctx[0], d)) {
LM_ERR("register server_name callback handler data for socket "
"[%s:%d], server_name='%s' failed for proc %d\n",
ip_addr2a(&d->ip), d->port,
(d->server_name.s) ? d->server_name.s : "<default>", i);
(d->server_name.s) ? d->server_name.s : "<default>", 0);
return -1;
}
}
}
} while(0);
if((d->type & TLS_DOMAIN_SRV)
&& (d->server_name.len > 0 || (d->type & TLS_DOMAIN_DEF))) {
@ -1065,8 +990,7 @@ static int ksr_tls_fix_domain(tls_domain_t *d, tls_domain_t *def)
*/
static int load_private_key(tls_domain_t *d)
{
int idx, ret_pwd, i;
int procs_no;
int idx, ret_pwd;
if(!d->pkey_file.s || !d->pkey_file.len) {
DBG("%s: No private key specified\n", tls_domain_str(d));
@ -1075,12 +999,11 @@ static int load_private_key(tls_domain_t *d)
if(fix_shm_pathname(&d->pkey_file) < 0)
return -1;
procs_no = get_max_procs();
for(i = 0; i < procs_no; i++) {
do {
for(idx = 0, ret_pwd = 0; idx < 3; idx++) {
ret_pwd = wolfSSL_CTX_use_PrivateKey_file(
d->ctx[i], d->pkey_file.s, SSL_FILETYPE_PEM);
d->ctx[0], d->pkey_file.s, SSL_FILETYPE_PEM);
if(ret_pwd) {
break;
} else {
@ -1097,14 +1020,14 @@ static int load_private_key(tls_domain_t *d)
TLS_ERR("load_private_key:");
return -1;
}
if(!wolfSSL_CTX_check_private_key(d->ctx[i])) {
if(!wolfSSL_CTX_check_private_key(d->ctx[0])) {
ERR("%s: Key '%s' does not match the public key of the"
" certificate\n",
tls_domain_str(d), d->pkey_file.s);
TLS_ERR("load_private_key:");
return -1;
}
}
} while(0);
DBG("%s: Key '%s' successfully loaded\n", tls_domain_str(d),
d->pkey_file.s);

@ -1,170 +0,0 @@
/*
* TLS module
*
* Copyright (C) 2006 enum.at
*
* This file is part of Kamailio, a free SIP server.
*
* Kamailio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version
*
* Kamailio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Exception: permission to copy, modify, propagate, and distribute a work
* formed by combining OpenSSL toolkit software and the code in this file,
* such as linking with software components and libraries released under
* OpenSSL project license.
*/
/** log the verification failure reason.
* @file tls_dump_vf.c
* @ingroup: tls
* Module: @ref tls
*/
#include "tls_dump_vf.h"
#include <wolfssl/options.h>
#include <wolfssl/ssl.h>
#include "../../core/dprint.h"
#include "tls_wolfssl_mod.h"
#include "tls_cfg.h"
/** log the verification failure reason.
*/
void tls_dump_verification_failure(long verification_result)
{
int tls_log;
tls_log = cfg_get(tls, tls_cfg, log);
switch(verification_result) {
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
LOG(tls_log,
"verification failure: unable to get issuer certificate\n");
break;
case X509_V_ERR_UNABLE_TO_GET_CRL:
LOG(tls_log,
"verification failure: unable to get certificate CRL\n");
break;
case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
LOG(tls_log, "verification failure: unable to decrypt "
"certificate's signature\n");
break;
case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
LOG(tls_log, "verification failure: unable to decrypt CRL's "
"signature\n");
break;
case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
LOG(tls_log, "verification failure: unable to decode issuer public "
"key\n");
break;
case X509_V_ERR_CERT_SIGNATURE_FAILURE:
LOG(tls_log,
"verification failure: certificate signature failure\n");
break;
case X509_V_ERR_CRL_SIGNATURE_FAILURE:
LOG(tls_log, "verification failure: CRL signature failure\n");
break;
case X509_V_ERR_CERT_NOT_YET_VALID:
LOG(tls_log,
"verification failure: certificate is not yet valid\n");
break;
case X509_V_ERR_CERT_HAS_EXPIRED:
LOG(tls_log, "verification failure: certificate has expired\n");
break;
case X509_V_ERR_CRL_NOT_YET_VALID:
LOG(tls_log, "verification failure: CRL is not yet valid\n");
break;
case X509_V_ERR_CRL_HAS_EXPIRED:
LOG(tls_log, "verification failure: CRL has expired\n");
break;
case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
LOG(tls_log, "verification failure: format error in certificate's "
"notBefore field\n");
break;
case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
LOG(tls_log, "verification failure: format error in certificate's "
"notAfter field\n");
break;
case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
LOG(tls_log, "verification failure: format error in CRL's "
"lastUpdate field\n");
break;
case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
LOG(tls_log, "verification failure: format error in CRL's "
"nextUpdate field\n");
break;
case X509_V_ERR_OUT_OF_MEM:
LOG(tls_log, "verification failure: out of memory\n");
break;
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
LOG(tls_log, "verification failure: self signed certificate\n");
break;
case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
LOG(tls_log, "verification failure: self signed certificate in "
"certificate chain\n");
break;
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
LOG(tls_log, "verification failure: unable to get local issuer "
"certificate\n");
break;
case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
LOG(tls_log, "verification failure: unable to verify the first "
"certificate\n");
break;
case X509_V_ERR_CERT_CHAIN_TOO_LONG:
LOG(tls_log, "verification failure: certificate chain too long\n");
break;
case X509_V_ERR_CERT_REVOKED:
LOG(tls_log, "verification failure: certificate revoked\n");
break;
case X509_V_ERR_INVALID_CA:
LOG(tls_log, "verification failure: invalid CA certificate\n");
break;
case X509_V_ERR_PATH_LENGTH_EXCEEDED:
LOG(tls_log,
"verification failure: path length constraint exceeded\n");
break;
case X509_V_ERR_INVALID_PURPOSE:
LOG(tls_log,
"verification failure: unsupported certificate purpose\n");
break;
case X509_V_ERR_CERT_UNTRUSTED:
LOG(tls_log, "verification failure: certificate not trusted\n");
break;
case X509_V_ERR_CERT_REJECTED:
LOG(tls_log, "verification failure: certificate rejected\n");
break;
case X509_V_ERR_SUBJECT_ISSUER_MISMATCH:
LOG(tls_log, "verification failure: subject issuer mismatch\n");
break;
case X509_V_ERR_AKID_SKID_MISMATCH:
LOG(tls_log, "verification failure: authority and subject key "
"identifier mismatch\n");
break;
case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH:
LOG(tls_log, "verification failure: authority and issuer serial "
"number mismatch\n");
break;
case X509_V_ERR_KEYUSAGE_NO_CERTSIGN:
LOG(tls_log, "verification failure: key usage does not include "
"certificate signing\n");
break;
case X509_V_ERR_APPLICATION_VERIFICATION:
LOG(tls_log,
"verification failure: application verification failure\n");
break;
}
}
/* vi: set ts=4 sw=4 tw=79:ai:cindent: */

@ -1,41 +0,0 @@
/*
* TLS module
*
* Copyright (C) 2006 enum.at
*
* This file is part of Kamailio, a free SIP server.
*
* Kamailio is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version
*
* Kamailio is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Exception: permission to copy, modify, propagate, and distribute a work
* formed by combining OpenSSL toolkit software and the code in this file,
* such as linking with software components and libraries released under
* OpenSSL project license.
*/
/** log the verification failure reason.
* @file tls_dump_vf.h
* @ingroup: tls
* Module: @ref tls
*/
#ifndef __tls_dump_vf_h
#define __tls_dump_vf_h
void tls_dump_verification_failure(long verification_result);
#endif /*__tls_dump_vf_h*/
/* vi: set ts=4 sw=4 tw=79:ai:cindent: */

@ -318,73 +318,61 @@ static void init_ssl_methods(void)
memset(sr_tls_methods, 0, sizeof(sr_tls_methods));
/* any SSL/TLS version */
sr_tls_methods[TLS_USE_SSLv23_cli - 1].TLSMethod = TLS_client_method();
sr_tls_methods[TLS_USE_SSLv23_srv - 1].TLSMethod = TLS_server_method();
sr_tls_methods[TLS_USE_SSLv23 - 1].TLSMethod = TLS_method();
#ifndef OPENSSL_NO_SSL3_METHOD
sr_tls_methods[TLS_USE_SSLv3_cli - 1].TLSMethod = TLS_client_method();
sr_tls_methods[TLS_USE_SSLv3_cli - 1].TLSMethodMin = SSL3_VERSION;
sr_tls_methods[TLS_USE_SSLv3_cli - 1].TLSMethodMax = SSL3_VERSION;
sr_tls_methods[TLS_USE_SSLv3_srv - 1].TLSMethod = TLS_server_method();
sr_tls_methods[TLS_USE_SSLv3_srv - 1].TLSMethodMin = SSL3_VERSION;
sr_tls_methods[TLS_USE_SSLv3_srv - 1].TLSMethodMax = SSL3_VERSION;
sr_tls_methods[TLS_USE_SSLv3 - 1].TLSMethod = TLS_method();
sr_tls_methods[TLS_USE_SSLv3 - 1].TLSMethodMin = SSL3_VERSION;
sr_tls_methods[TLS_USE_SSLv3 - 1].TLSMethodMax = SSL3_VERSION;
#endif
sr_tls_methods[TLS_USE_SSLv23_cli - 1].TLSMethod = wolfTLS_client_method();
sr_tls_methods[TLS_USE_SSLv23_srv - 1].TLSMethod = wolfTLS_server_method();
sr_tls_methods[TLS_USE_SSLv23 - 1].TLSMethod = wolfSSLv23_method();
sr_tls_methods[TLS_USE_TLSv1_cli - 1].TLSMethod = TLS_client_method();
sr_tls_methods[TLS_USE_TLSv1_cli - 1].TLSMethod = wolfTLS_client_method();
sr_tls_methods[TLS_USE_TLSv1_cli - 1].TLSMethodMin = TLS1_VERSION;
sr_tls_methods[TLS_USE_TLSv1_cli - 1].TLSMethodMax = TLS1_VERSION;
sr_tls_methods[TLS_USE_TLSv1_srv - 1].TLSMethod = TLS_server_method();
sr_tls_methods[TLS_USE_TLSv1_srv - 1].TLSMethod = wolfTLS_server_method();
sr_tls_methods[TLS_USE_TLSv1_srv - 1].TLSMethodMin = TLS1_VERSION;
sr_tls_methods[TLS_USE_TLSv1_srv - 1].TLSMethodMax = TLS1_VERSION;
sr_tls_methods[TLS_USE_TLSv1 - 1].TLSMethod = TLS_method();
sr_tls_methods[TLS_USE_TLSv1 - 1].TLSMethod = wolfSSLv23_method();
sr_tls_methods[TLS_USE_TLSv1 - 1].TLSMethodMin = TLS1_VERSION;
sr_tls_methods[TLS_USE_TLSv1 - 1].TLSMethodMax = TLS1_VERSION;
sr_tls_methods[TLS_USE_TLSv1_1_cli - 1].TLSMethod = TLS_client_method();
sr_tls_methods[TLS_USE_TLSv1_1_cli - 1].TLSMethod = wolfTLS_client_method();
sr_tls_methods[TLS_USE_TLSv1_1_cli - 1].TLSMethodMin = TLS1_1_VERSION;
sr_tls_methods[TLS_USE_TLSv1_1_cli - 1].TLSMethodMax = TLS1_1_VERSION;
sr_tls_methods[TLS_USE_TLSv1_1_srv - 1].TLSMethod = TLS_server_method();
sr_tls_methods[TLS_USE_TLSv1_1_srv - 1].TLSMethod = wolfTLS_server_method();
sr_tls_methods[TLS_USE_TLSv1_1_srv - 1].TLSMethodMin = TLS1_1_VERSION;
sr_tls_methods[TLS_USE_TLSv1_1_srv - 1].TLSMethodMax = TLS1_1_VERSION;
sr_tls_methods[TLS_USE_TLSv1_1 - 1].TLSMethod = TLS_method();
sr_tls_methods[TLS_USE_TLSv1_1 - 1].TLSMethod = wolfSSLv23_method();
sr_tls_methods[TLS_USE_TLSv1_1 - 1].TLSMethodMin = TLS1_1_VERSION;
sr_tls_methods[TLS_USE_TLSv1_1 - 1].TLSMethodMax = TLS1_1_VERSION;
sr_tls_methods[TLS_USE_TLSv1_2_cli - 1].TLSMethod = TLS_client_method();
sr_tls_methods[TLS_USE_TLSv1_2_cli - 1].TLSMethod = wolfTLS_client_method();
sr_tls_methods[TLS_USE_TLSv1_2_cli - 1].TLSMethodMin = TLS1_2_VERSION;
sr_tls_methods[TLS_USE_TLSv1_2_cli - 1].TLSMethodMax = TLS1_2_VERSION;
sr_tls_methods[TLS_USE_TLSv1_2_srv - 1].TLSMethod = TLS_server_method();
sr_tls_methods[TLS_USE_TLSv1_2_srv - 1].TLSMethod = wolfTLS_server_method();
sr_tls_methods[TLS_USE_TLSv1_2_srv - 1].TLSMethodMin = TLS1_2_VERSION;
sr_tls_methods[TLS_USE_TLSv1_2_srv - 1].TLSMethodMax = TLS1_2_VERSION;
sr_tls_methods[TLS_USE_TLSv1_2 - 1].TLSMethod = TLS_method();
sr_tls_methods[TLS_USE_TLSv1_2 - 1].TLSMethod = wolfSSLv23_method();
sr_tls_methods[TLS_USE_TLSv1_2 - 1].TLSMethodMin = TLS1_2_VERSION;
sr_tls_methods[TLS_USE_TLSv1_2 - 1].TLSMethodMax = TLS1_2_VERSION;
sr_tls_methods[TLS_USE_TLSv1_3_cli - 1].TLSMethod = TLS_client_method();
sr_tls_methods[TLS_USE_TLSv1_3_cli - 1].TLSMethod = wolfTLS_client_method();
sr_tls_methods[TLS_USE_TLSv1_3_cli - 1].TLSMethodMin = TLS1_3_VERSION;
sr_tls_methods[TLS_USE_TLSv1_3_cli - 1].TLSMethodMax = TLS1_3_VERSION;
sr_tls_methods[TLS_USE_TLSv1_3_srv - 1].TLSMethod = TLS_server_method();
sr_tls_methods[TLS_USE_TLSv1_3_srv - 1].TLSMethod = wolfTLS_server_method();
sr_tls_methods[TLS_USE_TLSv1_3_srv - 1].TLSMethodMin = TLS1_3_VERSION;
sr_tls_methods[TLS_USE_TLSv1_3_srv - 1].TLSMethodMax = TLS1_3_VERSION;
sr_tls_methods[TLS_USE_TLSv1_3 - 1].TLSMethod = TLS_method();
sr_tls_methods[TLS_USE_TLSv1_3 - 1].TLSMethod = wolfSSLv23_method();
sr_tls_methods[TLS_USE_TLSv1_3 - 1].TLSMethodMin = TLS1_3_VERSION;
sr_tls_methods[TLS_USE_TLSv1_3 - 1].TLSMethodMax = TLS1_3_VERSION;
/* ranges of TLS versions (require a minimum TLS version) */
sr_tls_methods[TLS_USE_TLSv1_PLUS - 1].TLSMethod = TLS_method();
sr_tls_methods[TLS_USE_TLSv1_PLUS - 1].TLSMethod = wolfSSLv23_method();
sr_tls_methods[TLS_USE_TLSv1_PLUS - 1].TLSMethodMin = TLS1_VERSION;
sr_tls_methods[TLS_USE_TLSv1_1_PLUS - 1].TLSMethod = TLS_method();
sr_tls_methods[TLS_USE_TLSv1_1_PLUS - 1].TLSMethod = wolfSSLv23_method();
sr_tls_methods[TLS_USE_TLSv1_1_PLUS - 1].TLSMethodMin = TLS1_1_VERSION;
sr_tls_methods[TLS_USE_TLSv1_2_PLUS - 1].TLSMethod = TLS_method();
sr_tls_methods[TLS_USE_TLSv1_2_PLUS - 1].TLSMethod = wolfSSLv23_method();
sr_tls_methods[TLS_USE_TLSv1_2_PLUS - 1].TLSMethodMin = TLS1_2_VERSION;
sr_tls_methods[TLS_USE_TLSv1_3_PLUS - 1].TLSMethod = TLS_method();
sr_tls_methods[TLS_USE_TLSv1_3_PLUS - 1].TLSMethod = wolfSSLv23_method();
sr_tls_methods[TLS_USE_TLSv1_3_PLUS - 1].TLSMethodMin = TLS1_3_VERSION;
}

@ -27,14 +27,12 @@
#ifndef _TLS_INIT_H
#define _TLS_INIT_H
#include <wolfssl/options.h>
#include <wolfssl/ssl.h>
#include "../../core/ip_addr.h"
#include "tls_domain.h"
typedef struct sr_tls_methods_s
{
const SSL_METHOD *TLSMethod;
const WOLFSSL_METHOD *TLSMethod;
int TLSMethodMin;
int TLSMethodMax;
} sr_tls_methods_t;

@ -1,213 +0,0 @@
/**
* Copyright (c) 2014 rxi
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the MIT license. See LICENSE for details.
*/
#include <stdlib.h>
#include <string.h>
#include "../../core/mem/mem.h"
#include "tls_map.h"
struct map_node_t
{
unsigned hash;
void *value;
map_node_t *next;
/* char key[]; */
/* char value[]; */
};
static unsigned map_hash(const char *str)
{
unsigned hash = 5381;
while(*str) {
hash = ((hash << 5) + hash) ^ *str++;
}
return hash;
}
static map_node_t *map_newnode(const char *key, void *value, int vsize)
{
map_node_t *node;
int ksize = strlen(key) + 1;
int voffset = ksize + ((sizeof(void *) - ksize) % sizeof(void *));
node = pkg_malloc(sizeof(*node) + voffset + vsize);
if(!node)
return NULL;
memcpy(node + 1, key, ksize);
node->hash = map_hash(key);
node->value = ((char *)(node + 1)) + voffset;
memcpy(node->value, value, vsize);
return node;
}
static int map_bucketidx(map_base_t *m, unsigned hash)
{
/* If the implementation is changed to allow a non-power-of-2 bucket count,
* the line below should be changed to use mod instead of AND */
return hash & (m->nbuckets - 1);
}
static void map_addnode(map_base_t *m, map_node_t *node)
{
int n = map_bucketidx(m, node->hash);
node->next = m->buckets[n];
m->buckets[n] = node;
}
static int map_resize(map_base_t *m, int nbuckets)
{
map_node_t *nodes, *node, *next;
map_node_t **buckets;
int i;
/* Chain all nodes together */
nodes = NULL;
i = m->nbuckets;
while(i--) {
node = (m->buckets)[i];
while(node) {
next = node->next;
node->next = nodes;
nodes = node;
node = next;
}
}
/* Reset buckets */
buckets = realloc(m->buckets, sizeof(*m->buckets) * nbuckets);
if(buckets != NULL) {
m->buckets = buckets;
m->nbuckets = nbuckets;
}
if(m->buckets) {
memset(m->buckets, 0, sizeof(*m->buckets) * m->nbuckets);
/* Re-add nodes to buckets */
node = nodes;
while(node) {
next = node->next;
map_addnode(m, node);
node = next;
}
}
/* Return error code if realloc() failed */
return (buckets == NULL) ? -1 : 0;
}
static map_node_t **map_getref(map_base_t *m, const char *key)
{
unsigned hash = map_hash(key);
map_node_t **next;
if(m->nbuckets > 0) {
next = &m->buckets[map_bucketidx(m, hash)];
while(*next) {
if((*next)->hash == hash && !strcmp((char *)(*next + 1), key)) {
return next;
}
next = &(*next)->next;
}
}
return NULL;
}
void map_deinit_(map_base_t *m)
{
map_node_t *next, *node;
int i;
i = m->nbuckets;
while(i--) {
node = m->buckets[i];
while(node) {
next = node->next;
pkg_free(node);
node = next;
}
}
pkg_free(m->buckets);
}
void *map_get_(map_base_t *m, const char *key)
{
map_node_t **next = map_getref(m, key);
return next ? (*next)->value : NULL;
}
int map_set_(map_base_t *m, const char *key, void *value, int vsize)
{
int n, err;
map_node_t **next, *node;
/* Find & replace existing node */
next = map_getref(m, key);
if(next) {
memcpy((*next)->value, value, vsize);
return 0;
}
/* Add new node */
node = map_newnode(key, value, vsize);
if(node == NULL)
goto fail;
if(m->nnodes >= m->nbuckets) {
n = (m->nbuckets > 0) ? (m->nbuckets << 1) : 1;
err = map_resize(m, n);
if(err)
goto fail;
}
map_addnode(m, node);
m->nnodes++;
return 0;
fail:
if(node)
pkg_free(node);
return -1;
}
void map_remove_(map_base_t *m, const char *key)
{
map_node_t *node;
map_node_t **next = map_getref(m, key);
if(next) {
node = *next;
*next = (*next)->next;
pkg_free(node);
m->nnodes--;
}
}
map_iter_t map_iter_(void)
{
map_iter_t iter;
iter.bucketidx = -1;
iter.node = NULL;
return iter;
}
const char *map_next_(map_base_t *m, map_iter_t *iter)
{
if(iter->node) {
iter->node = iter->node->next;
if(iter->node == NULL)
goto nextBucket;
} else {
nextBucket:
do {
if(++iter->bucketidx >= m->nbuckets) {
return NULL;
}
iter->node = m->buckets[iter->bucketidx];
} while(iter->node == NULL);
}
return (char *)(iter->node + 1);
}

@ -1,77 +0,0 @@
/**
* Copyright (c) 2014 rxi
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the MIT license. See LICENSE for details.
*/
#ifndef _TLS_MAP_H
#define _TLS_MAP_H
#include <string.h>
#define MAP_VERSION "0.1.0"
struct map_node_t;
typedef struct map_node_t map_node_t;
typedef struct
{
map_node_t **buckets;
unsigned nbuckets, nnodes;
} map_base_t;
typedef struct
{
unsigned bucketidx;
map_node_t *node;
} map_iter_t;
#define map_t(T) \
struct \
{ \
map_base_t base; \
T *ref; \
T tmp; \
}
#define map_init(m) memset(m, 0, sizeof(*(m)))
#define map_deinit(m) map_deinit_(&(m)->base)
#define map_get(m, key) ((m)->ref = map_get_(&(m)->base, key))
#define map_set(m, key, value) \
((m)->tmp = (value), map_set_(&(m)->base, key, &(m)->tmp, sizeof((m)->tmp)))
#define map_remove(m, key) map_remove_(&(m)->base, key)
#define map_iter(m) map_iter_()
#define map_next(m, iter) map_next_(&(m)->base, iter)
void map_deinit_(map_base_t *m);
void *map_get_(map_base_t *m, const char *key);
int map_set_(map_base_t *m, const char *key, void *value, int vsize);
void map_remove_(map_base_t *m, const char *key);
map_iter_t map_iter_(void);
const char *map_next_(map_base_t *m, map_iter_t *iter);
typedef map_t(void *) map_void_t;
typedef map_t(char *) map_str_t;
typedef map_t(int) map_int_t;
typedef map_t(char) map_char_t;
typedef map_t(float) map_float_t;
typedef map_t(double) map_double_t;
#endif /* _TLS_MAP_H */

@ -1,169 +0,0 @@
/*
* TLS module
*
* Copyright (C) 2019 Asipto 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 docs:
* https://www.openssl.org/docs/man1.1.1/man7/RAND.html
* https://www.openssl.org/docs/man1.1.1/man3/RAND_set_rand_method.html
*/
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "tls_rand.h"
#include "../../core/dprint.h"
#include "../../core/locking.h"
#include "../../core/mem/shm.h"
#include "../../core/rand/kam_rand.h"
#include "../../core/rand/fastrand.h"
#include "../../core/rand/fortuna/random.h"
/*
* Implementation for tests with system library PNRG,
* do not use this in production.
*/
static int ksr_krand_bytes(unsigned char *outdata, int size)
{
int r;
if(size < 0) {
return 0;
} else if(size == 0) {
return 1;
}
while(size >= sizeof(int)) {
r = kam_rand();
memcpy(outdata, &r, sizeof(int));
size -= sizeof(int);
outdata += sizeof(int);
}
if(size > 0) {
r = kam_rand();
memcpy(outdata, &r, size);
}
return 1;
}
static int ksr_krand_pseudorand(unsigned char *outdata, int size)
{
return ksr_krand_bytes(outdata, size);
}
static int ksr_krand_status(void)
{
return 1;
}
const WOLFSSL_RAND_METHOD _ksr_krand_method = {NULL, ksr_krand_bytes, NULL,
NULL, ksr_krand_pseudorand, ksr_krand_status};
const WOLFSSL_RAND_METHOD *RAND_ksr_krand_method(void)
{
return &_ksr_krand_method;
}
/*
* Implementation for tests with fastrand implementation,
* better as system library but still not secure enough.
* Do not use this in production.y
*/
static int ksr_fastrand_bytes(unsigned char *outdata, int size)
{
int r;
if(size < 0) {
return 0;
} else if(size == 0) {
return 1;
}
while(size >= sizeof(int)) {
r = fastrand();
memcpy(outdata, &r, sizeof(int));
size -= sizeof(int);
outdata += sizeof(int);
}
if(size > 0) {
r = fastrand();
memcpy(outdata, &r, size);
}
return 1;
}
static int ksr_fastrand_pseudorand(unsigned char *outdata, int size)
{
return ksr_fastrand_bytes(outdata, size);
}
static int ksr_fastrand_status(void)
{
return 1;
}
const WOLFSSL_RAND_METHOD _ksr_fastrand_method = {NULL, ksr_fastrand_bytes,
NULL, NULL, ksr_fastrand_pseudorand, ksr_fastrand_status};
const WOLFSSL_RAND_METHOD *RAND_ksr_fastrand_method(void)
{
return &_ksr_fastrand_method;
}
/*
* Implementation with Fortuna cryptographic PRNG.
* We are not strictly implementing the OpenSSL API here - we will
* not return an error if the PRNG has not been seeded with enough
* randomness to ensure an unpredictable byte sequence.
*/
static int ksr_cryptorand_bytes(unsigned char *outdata, int size)
{
if(size < 0) {
return 0;
} else if(size == 0) {
return 1;
}
sr_get_pseudo_random_bytes(outdata, size);
return 1;
}
static int ksr_cryptorand_status(void)
{
return 1;
}
/*
* We don't have a dedicated function for pseudo-random
* bytes, just use the secure version as well for it.
*/
const WOLFSSL_RAND_METHOD _ksr_cryptorand_method = {NULL, ksr_cryptorand_bytes,
NULL, NULL, ksr_cryptorand_bytes, ksr_cryptorand_status};
const WOLFSSL_RAND_METHOD *RAND_ksr_cryptorand_method(void)
{
return &_ksr_cryptorand_method;
}
/**
* PRNG by using default libssl random engine protected by lock
*/
// WOLFFIX no libssl rand method

@ -1,30 +0,0 @@
/*
* TLS module
*
* Copyright (C) 2019 Asipto 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.
*/
#ifndef _TLS_RAND_H_
#define _TLS_RAND_H_
#include <wolfssl/options.h>
#include <wolfssl/ssl.h>
const WOLFSSL_RAND_METHOD *RAND_ksr_krand_method(void);
const WOLFSSL_RAND_METHOD *RAND_ksr_fastrand_method(void);
const WOLFSSL_RAND_METHOD *RAND_ksr_cryptorand_method(void);
// WOLFFIX const WOLFSSL_RAND_METHOD *RAND_ksr_kxlibssl_method(void);
#endif

@ -186,16 +186,13 @@ static void tls_list(rpc_t *rpc, void *c)
state = "established";
break;
}
rpc->struct_add(handle, "sddds", "cipher", tls_info,
rpc->struct_add(handle, "sdds", "cipher", tls_info,
"ct_wq_size", tls_d->ct_wq ? tls_d->ct_wq->queued : 0,
"enc_rd_buf",
tls_d->enc_rd_buf ? tls_d->enc_rd_buf->size : 0,
"flags", tls_d->flags, "state", state);
lock_release(&con->write_lock);
} else {
rpc->struct_add(handle, "sddds", "cipher", "unknown",
"ct_wq_size", 0, "enc_rd_buf", 0, "flags", 0, "state",
"pre-init");
rpc->struct_add(handle, "sdds", "cipher", "unknown",
"ct_wq_size", 0, "flags", 0, "state", "pre-init");
}
}
}
@ -225,15 +222,14 @@ static void tls_options(rpc_t *rpc, void *c)
{
void *handle;
rpc->add(c, "{", &handle);
rpc->struct_add(handle, "dSdddSSSSSdSSdddddddddddddd", "force_run",
rpc->struct_add(handle, "dSdddSSSSSdSSdddddddddddd", "force_run",
cfg_get(tls, tls_cfg, force_run), "method",
&cfg_get(tls, tls_cfg, method), "verify_certificate",
cfg_get(tls, tls_cfg, verify_cert),
"verify_depth", cfg_get(tls, tls_cfg, verify_depth),
"require_certificate", cfg_get(tls, tls_cfg, require_cert),
"verify_client", &cfg_get(tls, tls_cfg, verify_client),
"private_key", &cfg_get(tls, tls_cfg, private_key), "ca_list",
cfg_get(tls, tls_cfg, verify_cert), "verify_depth",
cfg_get(tls, tls_cfg, verify_depth), "require_certificate",
cfg_get(tls, tls_cfg, require_cert), "verify_client",
&cfg_get(tls, tls_cfg, verify_client), "private_key",
&cfg_get(tls, tls_cfg, private_key), "ca_list",
&cfg_get(tls, tls_cfg, ca_list), "certificate",
&cfg_get(tls, tls_cfg, certificate), "cipher_list",
&cfg_get(tls, tls_cfg, cipher_list), "session_cache",
@ -249,9 +245,7 @@ static void tls_options(rpc_t *rpc, void *c)
"ssl_max_send_fragment",
cfg_get(tls, tls_cfg, ssl_max_send_fragment), "ssl_read_ahead",
cfg_get(tls, tls_cfg, ssl_read_ahead), "send_close_notify",
cfg_get(tls, tls_cfg, send_close_notify), "low_mem_threshold1",
cfg_get(tls, tls_cfg, low_mem_threshold1), "low_mem_threshold2",
cfg_get(tls, tls_cfg, low_mem_threshold2), "ct_wq_max",
cfg_get(tls, tls_cfg, send_close_notify), "ct_wq_max",
cfg_get(tls, tls_cfg, ct_wq_max), "con_ct_wq_max",
cfg_get(tls, tls_cfg, con_ct_wq_max), "ct_wq_blk_size",
cfg_get(tls, tls_cfg, ct_wq_blk_size));

@ -158,10 +158,10 @@ static SSL *get_ssl(struct tcp_connection *c)
}
static int get_cert(
X509 **cert, struct tcp_connection **c, struct sip_msg *msg, int my)
static int get_cert(WOLFSSL_X509 **cert, struct tcp_connection **c,
struct sip_msg *msg, int my)
{
SSL *ssl;
WOLFSSL *ssl;
*cert = 0;
*c = get_cur_connection(msg);
@ -197,7 +197,7 @@ static int get_cipher(str *res, sip_msg_t *msg)
static char buf[1024];
struct tcp_connection *c;
SSL *ssl;
WOLFSSL *ssl;
c = get_cur_connection(msg);
if(!c) {
@ -253,7 +253,7 @@ static int get_bits(str *res, long *i, sip_msg_t *msg)
static char buf[1024];
struct tcp_connection *c;
SSL *ssl;
WOLFSSL *ssl;
c = get_cur_connection(msg);
if(!c) {
@ -404,17 +404,17 @@ static int pv_desc(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
static int get_cert_version(str *res, int local, sip_msg_t *msg)
{
static char buf[INT2STR_MAX_LEN];
X509 *cert;
WOLFSSL_X509 *cert;
struct tcp_connection *c;
char *version;
if(get_cert(&cert, &c, msg, local) < 0)
return -1;
version = int2str(X509_get_version(cert), &res->len);
version = int2str(wolfSSL_X509_get_version(cert), &res->len);
memcpy(buf, version, res->len);
res->s = buf;
if(!local)
X509_free(cert);
wolfSSL_X509_free(cert);
tcpconn_put(c);
return 0;
}
@ -470,7 +470,7 @@ static int check_cert(str *res, long *ires, int local, int err, sip_msg_t *msg)
struct tcp_connection *c;
SSL *ssl;
X509 *cert = 0;
WOLFSSL_X509 *cert = 0;
c = get_cur_connection(msg);
if(!c)
@ -485,7 +485,7 @@ static int check_cert(str *res, long *ires, int local, int err, sip_msg_t *msg)
goto error;
} else {
if((cert = wolfSSL_get_peer_certificate(ssl))
&& SSL_get_verify_result(ssl) == err) {
&& wolfSSL_get_verify_result(ssl) == err) {
*res = succ;
if(ires)
*ires = 1;
@ -497,7 +497,7 @@ static int check_cert(str *res, long *ires, int local, int err, sip_msg_t *msg)
}
if(cert)
X509_free(cert);
wolfSSL_X509_free(cert);
tcpconn_put(c);
return 0;
@ -583,21 +583,21 @@ static int get_validity(str *res, int local, int bound, sip_msg_t *msg)
#define NOT_BEFORE 0
#define NOT_AFTER 1
static char buf[1024];
X509 *cert;
WOLFSSL_X509 *cert;
struct tcp_connection *c;
BUF_MEM *p;
BIO *mem = 0;
ASN1_TIME *date;
WOLFSSL_BUF_MEM *p;
WOLFSSL_BIO *mem = 0;
WOLFSSL_ASN1_TIME *date;
if(get_cert(&cert, &c, msg, local) < 0)
return -1;
switch(bound) {
case NOT_BEFORE:
date = X509_get_notBefore(cert);
date = wolfSSL_X509_get_notBefore(cert);
break;
case NOT_AFTER:
date = X509_get_notAfter(cert);
date = wolfSSL_X509_get_notAfter(cert);
break;
default:
BUG("Unexpected parameter value \"%d\"\n", bound);
@ -610,12 +610,12 @@ static int get_validity(str *res, int local, int bound, sip_msg_t *msg)
goto err;
}
if(!ASN1_TIME_print(mem, date)) {
if(!wolfSSL_ASN1_TIME_print(mem, date)) {
ERR("Error while printing certificate date/time\n");
goto err;
}
BIO_get_mem_ptr(mem, &p);
wolfSSL_BIO_get_mem_ptr(mem, &p);
if(p->length >= 1024) {
ERR("Date/time too long\n");
goto err;
@ -624,16 +624,16 @@ static int get_validity(str *res, int local, int bound, sip_msg_t *msg)
res->s = buf;
res->len = p->length;
BIO_free(mem);
wolfSSL_BIO_free(mem);
if(!local)
X509_free(cert);
wolfSSL_X509_free(cert);
tcpconn_put(c);
return 0;
err:
if(mem)
BIO_free(mem);
wolfSSL_BIO_free(mem);
if(!local)
X509_free(cert);
wolfSSL_X509_free(cert);
tcpconn_put(c);
return -1;
}
@ -699,7 +699,7 @@ static int pv_validity(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
static int get_sn(str *res, int local, sip_msg_t *msg)
{
static char buf[80]; // > log(2^256,10)
X509 *cert;
WOLFSSL_X509 *cert;
struct tcp_connection *c;
char *sn = NULL;
WOLFSSL_BIGNUM *bn = NULL;
@ -718,7 +718,7 @@ static int get_sn(str *res, int local, sip_msg_t *msg)
res->s = buf;
if(!local)
X509_free(cert);
wolfSSL_X509_free(cert);
tcpconn_put(c);
wolfSSL_OPENSSL_free(sn);
wolfSSL_BN_free(bn);
@ -777,7 +777,7 @@ static int cert_to_buf(X509 *cert, char **bufptr, size_t *len)
{
#define MAX_CERT_SIZE 16384
static char buf[MAX_CERT_SIZE];
BIO *mem = NULL;
WOLFSSL_BIO *mem = NULL;
mem = wolfSSL_BIO_new(wolfSSL_BIO_s_mem());
if(!mem) {
@ -786,29 +786,29 @@ static int cert_to_buf(X509 *cert, char **bufptr, size_t *len)
}
/* Write a certificate to a BIO */
if(!PEM_write_bio_X509(mem, cert)) {
if(!wolfSSL_PEM_write_bio_X509(mem, cert)) {
goto err;
}
*len = BIO_pending(mem);
*len = wolfSSL_BIO_pending(mem);
if(*len > MAX_CERT_SIZE) {
ERR("certificate is too long\n");
goto err;
}
if(BIO_read(mem, buf, *len) <= 0) {
if(wolfSSL_BIO_read(mem, buf, *len) <= 0) {
ERR("problem reading data out of BIO");
goto err;
}
*bufptr = buf;
BIO_free(mem);
wolfSSL_BIO_free(mem);
return 0;
err:
if(mem)
BIO_free(mem);
wolfSSL_BIO_free(mem);
return -1;
}
@ -818,7 +818,7 @@ static int get_ssl_cert(str *res, int local, int urlencoded, sip_msg_t *msg)
char *buf = NULL;
/* buf2 holds the urlencoded version of buf, which can be up to 3 times its size */
static char buf2[MAX_CERT_SIZE * 3 + 1];
X509 *cert;
WOLFSSL_X509 *cert;
struct tcp_connection *c;
size_t len;
str temp_str;
@ -847,13 +847,13 @@ static int get_ssl_cert(str *res, int local, int urlencoded, sip_msg_t *msg)
}
if(!local)
X509_free(cert);
wolfSSL_X509_free(cert);
tcpconn_put(c);
return 0;
err:
if(!local)
X509_free(cert);
wolfSSL_X509_free(cert);
tcpconn_put(c);
return -1;
}
@ -918,8 +918,8 @@ static int pv_ssl_cert(sip_msg_t *msg, pv_param_t *param, pv_value_t *res)
/* NB: SSL_get0_verified_chain() was introduced in OpenSSL 1.1.0 */
static int get_verified_cert_chain(
STACK_OF(X509) * *chain, struct tcp_connection **c, struct sip_msg *msg)
static int get_verified_cert_chain(WOLF_STACK_OF(WOLFSSL_X509) * *chain,
struct tcp_connection **c, struct sip_msg *msg)
{
SSL *ssl;
@ -950,8 +950,8 @@ static int sel_ssl_verified_cert_chain(str *res, select_t *s, sip_msg_t *msg)
char *buf = NULL;
struct tcp_connection *c;
size_t len;
STACK_OF(X509) * chain;
X509 *cert;
WOLF_STACK_OF(WOLFSSL_X509) * chain;
WOLFSSL_X509 *cert;
int i;
if(get_verified_cert_chain(&chain, &c, msg) < 0)
@ -962,10 +962,10 @@ static int sel_ssl_verified_cert_chain(str *res, select_t *s, sip_msg_t *msg)
} else
return -1;
if(i < 0 || i >= sk_X509_num(chain))
if(i < 0 || i >= wolfSSL_sk_X509_num(chain))
return -1;
cert = sk_X509_value(chain, i);
cert = wolfSSL_sk_X509_value(chain, i);
if(!cert)
return -1;
@ -989,11 +989,11 @@ err:
static int get_comp(str *res, int local, int issuer, int nid, sip_msg_t *msg)
{
static char buf[1024];
X509 *cert;
WOLFSSL_X509 *cert;
struct tcp_connection *c;
X509_NAME *name;
X509_NAME_ENTRY *e;
ASN1_STRING *asn1;
WOLFSSL_X509_NAME *name;
WOLFSSL_X509_NAME_ENTRY *e;
WOLFSSL_ASN1_STRING *asn1;
int index, text_len;
char *elem;
unsigned char *text_s;
@ -1003,13 +1003,14 @@ static int get_comp(str *res, int local, int issuer, int nid, sip_msg_t *msg)
if(get_cert(&cert, &c, msg, local) < 0)
return -1;
name = issuer ? X509_get_issuer_name(cert) : X509_get_subject_name(cert);
name = issuer ? wolfSSL_X509_get_issuer_name(cert)
: wolfSSL_X509_get_subject_name(cert);
if(!name) {
ERR("Cannot extract subject or issuer name from peer certificate\n");
goto err;
}
index = X509_NAME_get_index_by_NID(name, nid, -1);
index = wolfSSL_X509_NAME_get_index_by_NID(name, nid, -1);
if(index == -1) {
switch(nid) {
case NID_commonName:
@ -1041,9 +1042,9 @@ static int get_comp(str *res, int local, int issuer, int nid, sip_msg_t *msg)
goto err;
}
e = X509_NAME_get_entry(name, index);
asn1 = X509_NAME_ENTRY_get_data(e);
text_len = ASN1_STRING_to_UTF8(&text_s, asn1);
e = wolfSSL_X509_NAME_get_entry(name, index);
asn1 = wolfSSL_X509_NAME_ENTRY_get_data(e);
text_len = wolfSSL_ASN1_STRING_to_UTF8(&text_s, asn1);
if(text_len < 0 || text_len >= 1024) {
ERR("Error converting ASN1 string\n");
goto err;
@ -1054,7 +1055,7 @@ static int get_comp(str *res, int local, int issuer, int nid, sip_msg_t *msg)
wolfSSL_OPENSSL_free(text_s);
if(!local)
X509_free(cert);
wolfSSL_X509_free(cert);
tcpconn_put(c);
return 0;
@ -1187,9 +1188,9 @@ static int get_alt(str *res, int local, int type, sip_msg_t *msg)
{
static char buf[1024];
int n, found = 0;
STACK_OF(GENERAL_NAME) *names = 0;
GENERAL_NAME *nm;
X509 *cert;
WOLF_STACK_OF(WOLF_GENERAL_NAME) *names = 0;
WOLFSSL_GENERAL_NAME *nm;
WOLFSSL_X509 *cert;
struct tcp_connection *c;
str text;
struct ip_addr ip;
@ -1197,14 +1198,14 @@ static int get_alt(str *res, int local, int type, sip_msg_t *msg)
if(get_cert(&cert, &c, msg, local) < 0)
return -1;
names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
names = wolfSSL_X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL);
if(!names) {
DBG("Cannot get certificate alternative subject\n");
goto err;
}
for(n = 0; n < sk_GENERAL_NAME_num(names); n++) {
nm = sk_GENERAL_NAME_value(names, n);
for(n = 0; n < wolfSSL_sk_GENERAL_NAME_num(names); n++) {
nm = wolfSSL_sk_GENERAL_NAME_value(names, n);
if(nm->type != type)
continue;
switch(type) {
@ -1241,16 +1242,16 @@ static int get_alt(str *res, int local, int type, sip_msg_t *msg)
goto err;
if(names)
sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
wolfSSL_sk_GENERAL_NAME_pop_free(names, wolfSSL_GENERAL_NAME_free);
if(!local)
X509_free(cert);
wolfSSL_X509_free(cert);
tcpconn_put(c);
return 0;
err:
if(names)
sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free);
wolfSSL_sk_GENERAL_NAME_pop_free(names, wolfSSL_GENERAL_NAME_free);
if(!local)
X509_free(cert);
wolfSSL_X509_free(cert);
tcpconn_put(c);
return -1;
}
@ -1467,7 +1468,7 @@ int pv_get_tls(struct sip_msg *msg, pv_param_t *param, pv_value_t *res)
{
SSL *ssl = NULL;
tcp_connection_t *c = NULL;
X509 *cert = NULL;
WOLFSSL_X509 *cert = NULL;
str sv = STR_NULL;
if(msg == NULL || param == NULL) {

@ -57,8 +57,7 @@
#include "tls_wolfssl_mod.h"
#include "tls_server.h"
#include "tls_select.h"
#include "tls_bio.h"
#include "tls_dump_vf.h"
#include "tls_cfg.h"
int tls_run_event_routes(struct tcp_connection *c);
@ -225,6 +224,9 @@ static int tls_complete_init(struct tcp_connection *c)
str *sname = NULL;
str *srvid = NULL;
WOLFSSL_BIO *internal_bio, *rw_bio;
/* Get current TLS configuration and increase reference
* count immediately.
*/
@ -258,8 +260,7 @@ static int tls_complete_init(struct tcp_connection *c)
goto error;
}
DBG("Using initial TLS domain %s (dom %p ctx %p sn [%s])\n",
tls_domain_str(dom), dom, dom->ctx[process_no],
ZSW(dom->server_name.s));
tls_domain_str(dom), dom, dom->ctx[0], ZSW(dom->server_name.s));
data = (struct tls_extra_data *)shm_malloc(sizeof(struct tls_extra_data));
if(!data) {
@ -267,8 +268,10 @@ static int tls_complete_init(struct tcp_connection *c)
goto error;
}
memset(data, '\0', sizeof(struct tls_extra_data));
data->ssl = wolfSSL_new(dom->ctx[process_no]);
data->rwbio = tls_BIO_new_mbuf(0, 0);
data->ssl = wolfSSL_new(dom->ctx[0]);
wolfSSL_BIO_new_bio_pair(
&internal_bio, TLS_WR_MBUF_SZ, &rw_bio, TLS_RD_MBUF_SZ);
data->rwbio = rw_bio;
data->cfg = cfg;
data->state = state;
@ -277,7 +280,7 @@ static int tls_complete_init(struct tcp_connection *c)
if(data->ssl)
wolfSSL_free(data->ssl);
if(data->rwbio)
BIO_free(data->rwbio);
wolfSSL_BIO_free(data->rwbio);
goto error;
}
@ -287,14 +290,14 @@ static int tls_complete_init(struct tcp_connection *c)
if(data->ssl)
wolfSSL_free(data->ssl);
if(data->rwbio)
BIO_free(data->rwbio);
wolfSSL_BIO_free(data->rwbio);
goto error;
}
LM_DBG("outbound TLS server name set to: %s\n", sname->s);
}
#endif
wolfSSL_set_bio(data->ssl, data->rwbio, data->rwbio);
wolfSSL_set_bio(data->ssl, internal_bio, internal_bio);
c->extra_data = data;
/* link the extra data struct inside ssl connection*/
@ -351,33 +354,15 @@ static int tls_fix_connection(struct tcp_connection *c)
}
/** sets an mbuf pair for the bio used by the tls connection.
* WARNING: must be called with c->write_lock held.
* @return 0 on success, -1 on error.
*/
static int tls_set_mbufs(
struct tcp_connection *c, struct tls_mbuf *rd, struct tls_mbuf *wr)
{
BIO *rwbio;
rwbio = ((struct tls_extra_data *)c->extra_data)->rwbio;
if(unlikely(tls_BIO_mbuf_set(rwbio, rd, wr) <= 0)) {
/* it should be always 1 */
ERR("failed to set mbufs");
return -1;
}
return 0;
}
static void tls_dump_cert_info(char *s, X509 *cert)
static void tls_dump_cert_info(char *s, WOLFSSL_X509 *cert)
{
char *subj;
char *issuer;
subj = issuer = 0;
subj = X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
issuer = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
subj = wolfSSL_X509_NAME_oneline(wolfSSL_X509_get_subject_name(cert), 0, 0);
issuer =
wolfSSL_X509_NAME_oneline(wolfSSL_X509_get_issuer_name(cert), 0, 0);
if(subj) {
LOG(cfg_get(tls, tls_cfg, log), "%s subject:%s\n", s ? s : "", subj);
@ -407,12 +392,12 @@ static void tls_dump_cert_info(char *s, X509 *cert)
int tls_accept(struct tcp_connection *c, int *error)
{
int ret;
SSL *ssl = NULL;
X509 *cert;
WOLFSSL *ssl = NULL;
WOLFSSL_X509 *cert;
struct tls_extra_data *tls_c;
int tls_log;
*error = SSL_ERROR_NONE;
*error = WOLFSSL_ERROR_NONE;
tls_c = (struct tls_extra_data *)c->extra_data;
ssl = tls_c->ssl;
@ -439,7 +424,7 @@ int tls_accept(struct tcp_connection *c, int *error)
"verification failed!!!\n");
tls_dump_verification_failure(wolfSSL_get_verify_result(ssl));
}
X509_free(cert);
wolfSSL_X509_free(cert);
} else {
LOG(tls_log, "tls_accept: client did not present a certificate\n");
}
@ -469,13 +454,13 @@ err:
*/
int tls_connect(struct tcp_connection *c, int *error)
{
SSL *ssl;
WOLFSSL *ssl;
int ret;
X509 *cert;
WOLFSSL_X509 *cert;
struct tls_extra_data *tls_c;
int tls_log;
*error = SSL_ERROR_NONE;
*error = WOLFSSL_ERROR_NONE;
tls_c = (struct tls_extra_data *)c->extra_data;
ssl = tls_c->ssl;
@ -502,7 +487,7 @@ int tls_connect(struct tcp_connection *c, int *error)
"verification failed!!!\n");
tls_dump_verification_failure(wolfSSL_get_verify_result(ssl));
}
X509_free(cert);
wolfSSL_X509_free(cert);
} else {
/* this should not happen, servers always present a cert */
LOG(tls_log, "tls_connect: server did not "
@ -526,7 +511,7 @@ static int tls_shutdown(struct tcp_connection *c)
{
int ret, err, ssl_err;
struct tls_extra_data *tls_c;
SSL *ssl;
WOLFSSL *ssl;
tls_c = (struct tls_extra_data *)c->extra_data;
if(unlikely(tls_c == 0 || tls_c->ssl == 0)) {
@ -549,31 +534,31 @@ static int tls_shutdown(struct tcp_connection *c)
} else {
err = wolfSSL_get_error(ssl, ret);
switch(err) {
case SSL_ERROR_ZERO_RETURN:
case WOLFSSL_ERROR_ZERO_RETURN:
DBG("TLS shutdown failed cleanly\n");
goto err;
case SSL_ERROR_WANT_READ:
case WOLFSSL_ERROR_WANT_READ:
DBG("Need to get more data to finish TLS shutdown\n");
break;
case SSL_ERROR_WANT_WRITE:
case WOLFSSL_ERROR_WANT_WRITE:
DBG("Need to send more data to finish TLS shutdown\n");
break;
case SSL_ERROR_WANT_CONNECT:
case WOLFSSL_ERROR_WANT_CONNECT:
DBG("Need to retry connect\n");
break;
case SSL_ERROR_WANT_ACCEPT:
case WOLFSSL_ERROR_WANT_ACCEPT:
DBG("Need to retry accept\n");
break;
case SSL_ERROR_WANT_X509_LOOKUP:
case WOLFSSL_ERROR_WANT_X509_LOOKUP:
DBG("Application callback asked to be called again\n");
break;
case SSL_ERROR_SYSCALL:
case WOLFSSL_ERROR_SYSCALL:
TLS_ERR_RET(ssl_err, "TLS shutdown");
if(!ssl_err) {
if(ret == 0) {
@ -585,7 +570,7 @@ static int tls_shutdown(struct tcp_connection *c)
}
goto err;
case SSL_ERROR_SSL:
case WOLFSSL_ERROR_SSL:
default:
TLS_ERR("SSL error:");
goto err;
@ -627,8 +612,8 @@ void tls_h_tcpconn_clean_f(struct tcp_connection *c)
{
struct tls_extra_data *extra;
/*
* runs within global tcp lock
*/
* runs within global tcp lock
*/
if((c->type != PROTO_TLS) && (c->type != PROTO_WSS)) {
BUG("Bad connection structure\n");
abort();
@ -636,13 +621,10 @@ void tls_h_tcpconn_clean_f(struct tcp_connection *c)
if(c->extra_data) {
extra = (struct tls_extra_data *)c->extra_data;
wolfSSL_free(extra->ssl);
wolfSSL_BIO_free_all(extra->rwbio);
atomic_dec(&extra->cfg->ref_count);
if(extra->ct_wq)
tls_ct_wq_free(&extra->ct_wq);
if(extra->enc_rd_buf) {
shm_free(extra->enc_rd_buf);
extra->enc_rd_buf = 0;
}
shm_free(c->extra_data);
c->extra_data = 0;
}
@ -651,10 +633,20 @@ void tls_h_tcpconn_clean_f(struct tcp_connection *c)
/** perform one-way shutdown, do not wait for notify from the remote peer.
*/
/*
* wolfSSL implementation detail: BIO pair uses a ring buffer -
* wolfSSL_BIO_read does not do wrap-around; you may need a 2-pass read
* 1st read - front of buffer, 2nd read - wrap-around
* fixed in 4f1d777090 post-v5.6.6-stable
*/
void tls_h_tcpconn_close_f(struct tcp_connection *c, int fd)
{
unsigned char wr_buf[TLS_WR_MBUF_SZ];
struct tls_mbuf rd, wr;
WOLFSSL_BIO *rwbio;
size_t wr_used, nr, npos;
/*
* runs either within global tcp lock or after the connection has
@ -671,19 +663,27 @@ void tls_h_tcpconn_close_f(struct tcp_connection *c, int fd)
lock_release(&c->write_lock);
return;
}
tls_mbuf_init(&rd, 0, 0); /* no read */
tls_mbuf_init(&wr, wr_buf, sizeof(wr_buf));
if(tls_set_mbufs(c, &rd, &wr) == 0) {
tls_shutdown(c); /* shutdown only on successful set fd */
/* write as much as possible and update wr.
* Since this is a close, we don't want to queue the write
* (if it can't write immediately, just fail silently)
*/
if(wr.used)
_tcpconn_write_nb(fd, c, (char *)wr.buf, wr.used);
/* we don't bother reading anything (we don't want to wait
on close) */
rwbio = ((struct tls_extra_data *)c->extra_data)->rwbio;
tls_shutdown(c); /* shutdown only on successful set fd */
/* write as much as possible and update wr.
* Since this is a close, we don't want to queue the write
* (if it can't write immediately, just fail silently)
*/
/* use 2-pass read for wolfSSL ring buffer */
wr_used = wolfSSL_BIO_pending(rwbio);
if(wr_used) {
for(nr = 0; nr < wr_used;) {
npos = wolfSSL_BIO_read(rwbio, wr_buf + nr, wr_used - nr);
if(npos <= 0)
break;
nr += npos;
}
assert(nr == wr_used);
_tcpconn_write_nb(fd, c, (char *)wr_buf, wr_used);
}
/* we don't bother reading anything (we don't want to wait
on close) */
lock_release(&c->write_lock);
}
}
@ -724,10 +724,12 @@ int tls_h_encode_f(struct tcp_connection *c, const char **pbuf,
snd_flags_t *send_flags)
{
int n, offs;
SSL *ssl = NULL;
WOLFSSL *ssl = NULL;
WOLFSSL_BIO *rwbio;
struct tls_extra_data *tls_c;
static unsigned char wr_buf[TLS_WR_MBUF_SZ];
struct tls_mbuf rd, wr;
size_t wr_used = 0, nr, npos;
int ssl_error;
char *err_src;
char ip_buf[64];
@ -744,7 +746,7 @@ int tls_h_encode_f(struct tcp_connection *c, const char **pbuf,
su2a(&c->rcv.src_su, sizeof(c->rcv.src_su)));
n = 0;
offs = 0;
ssl_error = SSL_ERROR_NONE;
ssl_error = WOLFSSL_ERROR_NONE;
err_src = "TLS write:";
if(unlikely(tls_fix_connection_unsafe(c) < 0)) {
/* c->extra_data might be null => exit immediately */
@ -755,8 +757,7 @@ int tls_h_encode_f(struct tcp_connection *c, const char **pbuf,
}
tls_c = (struct tls_extra_data *)c->extra_data;
ssl = tls_c->ssl;
tls_mbuf_init(&rd, 0, 0); /* no read */
tls_mbuf_init(&wr, wr_buf, sizeof(wr_buf));
rwbio = tls_c->rwbio;
/* clear text already queued (WANTS_READ) queue directly*/
if(unlikely(tls_write_wants_read(tls_c))) {
TLS_WR_TRACE("(%p) WANTS_READ queue present => queueing"
@ -773,10 +774,7 @@ int tls_h_encode_f(struct tcp_connection *c, const char **pbuf,
send_flags->f &= ~SND_F_CON_CLOSE;
goto end;
}
if(unlikely(tls_set_mbufs(c, &rd, &wr) < 0)) {
ERR("tls_set_mbufs failed\n");
goto error;
}
redo_wr:
if(unlikely(tls_c->state == S_TLS_CONNECTING)) {
n = tls_connect(c, &ssl_error);
@ -787,7 +785,7 @@ redo_wr:
ssl_error = wolfSSL_get_error(ssl, n);
} else {
/* tls_connect failed/needs more IO */
if(unlikely(n < 0 && ssl_error == SSL_ERROR_NONE))
if(unlikely(n < 0 && ssl_error == WOLFSSL_ERROR_NONE))
goto error;
err_src = "TLS connect:";
}
@ -800,29 +798,31 @@ redo_wr:
ssl_error = wolfSSL_get_error(ssl, n);
} else {
/* tls_accept failed/needs more IO */
if(unlikely(n < 0 && ssl_error == SSL_ERROR_NONE))
if(unlikely(n < 0 && ssl_error == WOLFSSL_ERROR_NONE))
goto error;
err_src = "TLS accept:";
}
} else {
n = SSL_write(ssl, buf + offs, len - offs);
n = wolfSSL_write(ssl, buf + offs, len - offs);
if(unlikely(n <= 0))
ssl_error = SSL_get_error(ssl, n);
ssl_error = wolfSSL_get_error(ssl, n);
}
TLS_WR_TRACE("(%p) SSL_write(%p + %d, %d) => %d (err=%d)\n", c, buf, offs,
len - offs, n, ssl_error);
TLS_WR_TRACE("(%p) wolfSSL_write(%p + %d, %d) => %d (err=%d)\n", c, buf,
offs, len - offs, n, ssl_error);
/* check for possible ssl errors */
wr_used = wolfSSL_BIO_pending(rwbio);
if(unlikely(n <= 0)) {
switch(ssl_error) {
case SSL_ERROR_NONE:
case WOLFSSL_ERROR_NONE:
BUG("unexpected SSL_ERROR_NONE for n=%d\n", n);
goto error;
break;
case SSL_ERROR_ZERO_RETURN:
case WOLFSSL_ERROR_ZERO_RETURN:
/* SSL EOF */
ERR("ssl level EOF\n");
goto ssl_eof;
case SSL_ERROR_WANT_READ:
case WOLFSSL_ERROR_WANT_READ:
/* queue write buffer */
TLS_WR_TRACE("(%p) SSL_ERROR_WANT_READ => queueing for read"
" (%p + %d, %d)\n",
@ -835,24 +835,24 @@ redo_wr:
}
tls_c->flags |= F_TLS_CON_WR_WANTS_RD;
/* buffer queued for a future send attempt, after first
* reading some data (key exchange) => don't allow immediate
* closing of the connection */
* reading some data (key exchange) => don't allow immediate
* closing of the connection */
send_flags->f &= ~SND_F_CON_CLOSE;
break; /* or goto end */
case SSL_ERROR_WANT_WRITE:
case WOLFSSL_ERROR_WANT_WRITE:
if(unlikely(offs == 0)) {
/* error, no record fits in the buffer or
* no partial write enabled and buffer to small to fit
* all the records */
BUG("write buffer too small (%d/%d bytes)\n", wr.used,
wr.size);
* no partial write enabled and buffer to small to fit
* all the records */
BUG("write buffer too small (%d/%d bytes)\n", (int)wr_used,
TLS_WR_MBUF_SZ);
goto bug;
} else {
/* offs != 0 => something was "written" */
*rest_buf = buf + offs;
*rest_len = len - offs;
/* this function should be called again => disallow
* immediate closing of the connection */
* immediate closing of the connection */
send_flags->f &= ~SND_F_CON_CLOSE;
TLS_WR_TRACE("(%p) SSL_ERROR_WANT_WRITE partial write"
" (written %p , %d, rest_buf=%p"
@ -860,7 +860,7 @@ redo_wr:
c, buf, offs, *rest_buf, *rest_len);
}
break; /* or goto end */
case SSL_ERROR_SSL:
case WOLFSSL_ERROR_SSL:
/* protocol level error */
ERR("protocol level error\n");
TLS_ERR_SSL(err_src, ssl);
@ -873,27 +873,27 @@ redo_wr:
goto error;
case SSL_ERROR_WANT_CONNECT:
case WOLFSSL_ERROR_WANT_CONNECT:
/* only if the underlying BIO is not yet connected
* and the call would block in connect().
* (not possible in our case) */
* and the call would block in connect().
* (not possible in our case) */
BUG("unexpected SSL_ERROR_WANT_CONNECT\n");
break;
case SSL_ERROR_WANT_ACCEPT:
case WOLFSSL_ERROR_WANT_ACCEPT:
/* only if the underlying BIO is not yet connected
* and call would block in accept()
* (not possible in our case) */
* and call would block in accept()
* (not possible in our case) */
BUG("unexpected SSL_ERROR_WANT_ACCEPT\n");
break;
case SSL_ERROR_WANT_X509_LOOKUP:
case WOLFSSL_ERROR_WANT_X509_LOOKUP:
/* can only appear on client application and it indicates that
* an installed client cert. callback should be called again
* (it returned < 0 indicated that it wants to be called
* later). Not possible in our case */
* an installed client cert. callback should be called again
* (it returned < 0 indicated that it wants to be called
* later). Not possible in our case */
BUG("unsupported SSL_ERROR_WANT_X509_LOOKUP");
goto bug;
case SSL_ERROR_SYSCALL:
case WOLFSSL_ERROR_SYSCALL:
TLS_ERR_RET(x, err_src);
if(!x) {
if(n == 0) {
@ -916,26 +916,42 @@ redo_wr:
offs += n;
goto redo_wr;
}
tls_set_mbufs(c, 0, 0);
end:
*pbuf = (const char *)wr.buf;
*plen = wr.used;
/* use 2-pass read for wolfSSL ring buffer */
wr_used = wolfSSL_BIO_pending(rwbio);
for(nr = 0; nr < wr_used;) {
npos = wolfSSL_BIO_read(rwbio, wr_buf + nr, wr_used - nr);
if(npos <= 0)
break;
nr += npos;
}
assert(nr == wr_used);
*plen = wr_used;
*pbuf = (const char *)wr_buf;
TLS_WR_TRACE("(%p) end (offs %d, rest_buf=%p rest_len=%d 0x%0x) => %d \n",
c, offs, *rest_buf, *rest_len, send_flags->f, *plen);
return *plen;
error:
/*error_send:*/
/*error_send:*/
error_wq_full:
bug:
tls_set_mbufs(c, 0, 0);
TLS_WR_TRACE(
"(%p) end error (offs %d, %d encoded) => -1\n", c, offs, wr.used);
"(%p) end error (offs %d, %d encoded) => -1\n", c, offs, wr_used);
return -1;
ssl_eof:
c->state = S_CONN_EOF;
c->flags |= F_CONN_FORCE_EOF;
*pbuf = (const char *)wr.buf;
*plen = wr.used;
/* use 2-pass read for wolfSSL ring buffer */
wr_used = wolfSSL_BIO_pending(rwbio);
for(nr = 0; nr < wr_used;) {
npos = wolfSSL_BIO_read(rwbio, wr_buf + nr, wr_used - nr);
if(npos <= 0)
break;
nr += npos;
}
assert(nr == wr_used);
*plen = wr_used;
*pbuf = (const char *)wr_buf;
DBG("TLS connection has been closed\n");
TLS_WR_TRACE("(%p) end EOF (offs %d) => (%d\n", c, offs, *plen);
return *plen;
@ -973,12 +989,13 @@ int tls_h_read_f(struct tcp_connection *c, rd_conn_flags_t *flags)
{
struct tcp_req *r;
int bytes_free, bytes_read, read_size, ssl_error, ssl_read;
SSL *ssl;
WOLFSSL *ssl;
WOLFSSL_BIO *rwbio;
unsigned char rd_buf[TLS_RD_MBUF_SZ];
unsigned char wr_buf[TLS_WR_MBUF_SZ];
struct tls_mbuf rd, wr;
size_t wr_used, rd_unused;
size_t nr, npos, nw;
struct tls_extra_data *tls_c;
struct tls_rd_buf *enc_rd_buf;
int n, flush_flags;
char *err_src;
char ip_buf[64];
@ -991,7 +1008,7 @@ int tls_h_read_f(struct tcp_connection *c, rd_conn_flags_t *flags)
ip_addr2a(&c->rcv.dst_ip), c->rcv.dst_port);
ssl_read = 0;
r = &c->req;
enc_rd_buf = 0;
*flags &= ~RD_CONN_REPEAT_READ;
if(unlikely(tls_fix_connection(c) < 0)) {
TLS_RD_TRACE("(%p, %p) end: tls_fix_connection failed =>"
@ -1003,6 +1020,7 @@ int tls_h_read_f(struct tcp_connection *c, rd_conn_flags_t *flags)
* If it's != 0 is changed only on destroy. It's not possible to have
* parallel reads.*/
tls_c = c->extra_data;
rwbio = tls_c->rwbio;
bytes_free = c->req.b_size - (unsigned int)(r->pos - r->buf);
if(unlikely(bytes_free <= 0)) {
ERR("Buffer overrun, dropping\n");
@ -1010,53 +1028,35 @@ int tls_h_read_f(struct tcp_connection *c, rd_conn_flags_t *flags)
return -1;
}
redo_read:
/* if data queued from a previous read(), use it (don't perform
* a real read()).
*/
if(unlikely(tls_c->enc_rd_buf)) {
/* use queued data */
/* safe to use without locks, because only read changes it and
* there can't be parallel reads on the same connection */
enc_rd_buf = tls_c->enc_rd_buf;
tls_c->enc_rd_buf = 0;
TLS_RD_TRACE("(%p, %p) using queued data (%p: %p %d bytes)\n", c, flags,
enc_rd_buf, enc_rd_buf->buf + enc_rd_buf->pos,
enc_rd_buf->size - enc_rd_buf->pos);
tls_mbuf_init(&rd, enc_rd_buf->buf + enc_rd_buf->pos,
enc_rd_buf->size - enc_rd_buf->pos);
rd.used = enc_rd_buf->size - enc_rd_buf->pos;
} else {
/* if we were using using queued data before, free & reset the
the queued read data before performing the real read() */
if(unlikely(enc_rd_buf)) {
TLS_RD_TRACE("(%p, %p) reset prev. used enc_rd_buf (%p)\n", c,
flags, enc_rd_buf);
shm_free(enc_rd_buf);
enc_rd_buf = 0;
/* real read() */
/* read() only if no previously detected EOF, or previous
* short read (which means the socket buffer was emptied) */
if(likely(!(*flags & (RD_CONN_EOF | RD_CONN_SHORT_READ)))) {
/* don't read more than the free bytes in the tcp req buffer */
read_size = MIN_unsigned(TLS_RD_MBUF_SZ, bytes_free);
bytes_read = tcp_read_data(c->fd, c, (char *)rd_buf, read_size, flags);
TLS_RD_TRACE("(%p, %p) tcp_read_data(..., %d, *%d) => %d bytes\n", c,
flags, read_size, *flags, bytes_read);
/* try SSL_read even on 0 bytes read, it might have
* internally buffered data */
if(unlikely(bytes_read < 0)) {
goto error;
}
/* real read() */
tls_mbuf_init(&rd, rd_buf, sizeof(rd_buf));
/* read() only if no previously detected EOF, or previous
* short read (which means the socket buffer was emptied) */
if(likely(!(*flags & (RD_CONN_EOF | RD_CONN_SHORT_READ)))) {
/* don't read more than the free bytes in the tcp req buffer */
read_size = MIN_unsigned(rd.size, bytes_free);
bytes_read =
tcp_read_data(c->fd, c, (char *)rd.buf, read_size, flags);
TLS_RD_TRACE("(%p, %p) tcp_read_data(..., %d, *%d) => %d bytes\n",
c, flags, read_size, *flags, bytes_read);
/* try SSL_read even on 0 bytes read, it might have
* internally buffered data */
if(unlikely(bytes_read < 0)) {
goto error;
}
rd.used = bytes_read;
/*
* use 2-pass write for wolfSSL ring buffer
* fixed in 4f1d777090, post-v5.6.6-stable
*/
for(nw = 0; nw < bytes_read;) {
npos = wolfSSL_BIO_write(rwbio, rd_buf + nw, bytes_read - nw);
if(npos <= 0)
break;
nw += npos;
}
assert(nw == bytes_read);
}
continue_ssl_read:
tls_mbuf_init(&wr, wr_buf, sizeof(wr_buf));
ssl_error = SSL_ERROR_NONE;
ssl_error = WOLFSSL_ERROR_NONE;
err_src = "TLS read:";
/* we have to avoid to run in the same time
* with a tls_write because of the
@ -1064,7 +1064,6 @@ continue_ssl_read:
* stealing the wbio or rbio under us or vice versa)
* => lock on con->write_lock (ugly hack) */
lock_get(&c->write_lock);
tls_set_mbufs(c, &rd, &wr);
ssl = tls_c->ssl;
n = 0;
if(unlikely(tls_write_wants_read(tls_c) && !(*flags & RD_CONN_EOF))) {
@ -1073,7 +1072,6 @@ continue_ssl_read:
" ct_wq_flush()=> %d (ff=%d ssl_error=%d))\n",
c, flags, n, flush_flags, ssl_error);
if(unlikely(n < 0)) {
tls_set_mbufs(c, 0, 0);
lock_release(&c->write_lock);
ERR("write flush error (%d)\n", n);
goto error;
@ -1083,7 +1081,7 @@ continue_ssl_read:
if(unlikely(flush_flags & F_BUFQ_ERROR_FLUSH))
err_src = "TLS write:";
}
if(likely(ssl_error == SSL_ERROR_NONE)) {
if(likely(ssl_error == WOLFSSL_ERROR_NONE)) {
if(unlikely(tls_c->state == S_TLS_CONNECTING)) {
n = tls_connect(c, &ssl_error);
TLS_RD_TRACE("(%p, %p) tls_connect() => %d (err=%d)\n", c, flags, n,
@ -1092,7 +1090,7 @@ continue_ssl_read:
n = wolfSSL_read(ssl, r->pos, bytes_free);
} else {
/* tls_connect failed/needs more IO */
if(unlikely(n < 0 && ssl_error == SSL_ERROR_NONE)) {
if(unlikely(n < 0 && ssl_error == WOLFSSL_ERROR_NONE)) {
lock_release(&c->write_lock);
goto error;
}
@ -1107,7 +1105,7 @@ continue_ssl_read:
n = wolfSSL_read(ssl, r->pos, bytes_free);
} else {
/* tls_accept failed/needs more IO */
if(unlikely(n < 0 && ssl_error == SSL_ERROR_NONE)) {
if(unlikely(n < 0 && ssl_error == WOLFSSL_ERROR_NONE)) {
lock_release(&c->write_lock);
goto error;
}
@ -1116,74 +1114,74 @@ continue_ssl_read:
}
} else {
/* if bytes in then decrypt read buffer into tcpconn req.
* buffer */
* buffer */
n = wolfSSL_read(ssl, r->pos, bytes_free);
}
/** handle SSL_read() return.
* There are 3 main cases, each with several sub-cases, depending
* on whether or not the output buffer was filled, if there
* is still unconsumed input data in the input buffer (rd)
* and if there is "cached" data in the internal openssl
* buffers.
* 0. error (n<=0):
* SSL_ERROR_WANT_READ - input data fully
* consumed, no more returnable cached data inside openssl
* => exit.
* SSL_ERROR_WANT_WRITE - should never happen (the write
* buffer is big enough to handle any re-negociation).
* SSL_ERROR_ZERO_RETURN - ssl level shutdown => exit.
* other errors are unexpected.
* 1. output buffer filled (n == bytes_free):
* 1i. - still unconsumed input, nothing buffered by openssl
* 1ip. - unconsumed input + buffered data by openssl (pending
* on the next SSL_read).
* 1p. - completely consumed input, buffered data internally
* by openssl (pending).
* Likely to happen, about the only case when
* SSL_pending() could be used (but only if readahead=0).
* 1f. - consumed input, no buffered data.
* 2. output buffer not fully filled (n < bytes_free):
* 2i. - still unconsumed input, nothing buffered by openssl.
* This can appear if SSL readahead is 0 (SSL_read()
* tries to get only 1 record from the input).
* 2ip. - unconsumed input and buffered data by openssl.
* Unlikely to happen (e.g. readahead is 1, more
* records are buffered internally by openssl, but
* there was not enough space for buffering the whole
* input).
* 2p - consumed input, but buffered data by openssl.
* It happens especially when readahead is 1.
* 2f. - consumed input, no buffered data.
*
* One should repeat SSL_read() until and error is detected
* (0*) or the input and internal ssl buffers are fully consumed
* (1f or 2f). However in general is not possible to see if
* SSL_read() could return more data. SSL_pending() has very
* limited usability (basically it would return !=0 only if there
* was no enough space in the output buffer and only if this did
* not happen at a record boundary).
* The solution is to repeat SSL_read() until error or until
* the output buffer is filled (0* or 1*).
* In the later case, this whole function should be called again
* once there is more output space (set RD_CONN_REPEAT_READ).
*/
* There are 3 main cases, each with several sub-cases, depending
* on whether or not the output buffer was filled, if there
* is still unconsumed input data in the input buffer (rd)
* and if there is "cached" data in the internal openssl
* buffers.
* 0. error (n<=0):
* SSL_ERROR_WANT_READ - input data fully
* consumed, no more returnable cached data inside openssl
* => exit.
* SSL_ERROR_WANT_WRITE - should never happen (the write
* buffer is big enough to handle any re-negociation).
* SSL_ERROR_ZERO_RETURN - ssl level shutdown => exit.
* other errors are unexpected.
* 1. output buffer filled (n == bytes_free):
* 1i. - still unconsumed input, nothing buffered by openssl
* 1ip. - unconsumed input + buffered data by openssl (pending
* on the next SSL_read).
* 1p. - completely consumed input, buffered data internally
* by openssl (pending).
* Likely to happen, about the only case when
* SSL_pending() could be used (but only if readahead=0).
* 1f. - consumed input, no buffered data.
* 2. output buffer not fully filled (n < bytes_free):
* 2i. - still unconsumed input, nothing buffered by openssl.
* This can appear if SSL readahead is 0 (SSL_read()
* tries to get only 1 record from the input).
* 2ip. - unconsumed input and buffered data by openssl.
* Unlikely to happen (e.g. readahead is 1, more
* records are buffered internally by openssl, but
* there was not enough space for buffering the whole
* input).
* 2p - consumed input, but buffered data by openssl.
* It happens especially when readahead is 1.
* 2f. - consumed input, no buffered data.
*
* One should repeat SSL_read() until and error is detected
* (0*) or the input and internal ssl buffers are fully consumed
* (1f or 2f). However in general is not possible to see if
* SSL_read() could return more data. SSL_pending() has very
* limited usability (basically it would return !=0 only if there
* was no enough space in the output buffer and only if this did
* not happen at a record boundary).
* The solution is to repeat SSL_read() until error or until
* the output buffer is filled (0* or 1*).
* In the later case, this whole function should be called again
* once there is more output space (set RD_CONN_REPEAT_READ).
*/
if(unlikely(tls_c->flags & F_TLS_CON_RENEGOTIATION)) {
/* Fix CVE-2009-3555 - disable renegotiation if started by client
* - simulate SSL EOF to force close connection*/
* - simulate SSL EOF to force close connection*/
tls_dbg = cfg_get(tls, tls_cfg, debug);
LOG(tls_dbg,
"Reading on a renegotiation of connection (n:%d) (%d)\n", n,
wolfSSL_get_error(ssl, n));
err_src = "TLS R-N read:";
ssl_error = SSL_ERROR_ZERO_RETURN;
ssl_error = WOLFSSL_ERROR_ZERO_RETURN;
} else {
if(unlikely(n <= 0)) {
ssl_error = wolfSSL_get_error(ssl, n);
err_src = "TLS read:";
/* errors handled below, outside the lock */
} else {
ssl_error = SSL_ERROR_NONE;
ssl_error = WOLFSSL_ERROR_NONE;
r->pos += n;
ssl_read += n;
bytes_free -= n;
@ -1194,68 +1192,76 @@ continue_ssl_read:
c, flags, n, ssl_error, ssl_read, *flags, tls_c->flags);
ssl_read_skipped:;
}
if(unlikely(wr.used != 0 && ssl_error != SSL_ERROR_ZERO_RETURN)) {
wr_used = wolfSSL_BIO_pending(rwbio);
if(unlikely(wr_used != 0 && ssl_error != WOLFSSL_ERROR_ZERO_RETURN)) {
TLS_RD_TRACE(
"(%p, %p) tcpconn_send_unsafe %d bytes\n", c, flags, wr.used);
"(%p, %p) tcpconn_send_unsafe %d bytes\n", c, flags, wr_used);
/* something was written and it's not ssl EOF*/
/* use 2-pass read for wolfSSL ring buffer */
for(nr = 0; nr < wr_used;) {
npos = wolfSSL_BIO_read(rwbio, wr_buf + nr, wr_used - nr);
if(npos <= 0)
break;
nr += npos;
}
assert(nr == wr_used);
if(unlikely(tcpconn_send_unsafe(
c->fd, c, (char *)wr.buf, wr.used, c->send_flags)
c->fd, c, (char *)wr_buf, wr_used, c->send_flags)
< 0)) {
tls_set_mbufs(c, 0, 0);
lock_release(&c->write_lock);
TLS_RD_TRACE("(%p, %p) tcpconn_send_unsafe error\n", c, flags);
goto error_send;
}
}
/* quickly catch bugs: segfault if accessed and not set */
tls_set_mbufs(c, 0, 0);
lock_release(&c->write_lock);
switch(ssl_error) {
case SSL_ERROR_NONE:
case WOLFSSL_ERROR_NONE:
if(unlikely(n < 0)) {
BUG("unexpected SSL_ERROR_NONE for n=%d\n", n);
goto error;
}
break;
case SSL_ERROR_ZERO_RETURN:
case WOLFSSL_ERROR_ZERO_RETURN:
/* SSL EOF */
TLS_RD_TRACE("(%p, %p) SSL EOF (fd=%d)\n", c, flags, c->fd);
goto ssl_eof;
case SSL_ERROR_WANT_READ:
case WOLFSSL_ERROR_WANT_READ:
TLS_RD_TRACE("(%p, %p) SSL_ERROR_WANT_READ *flags=%d\n", c, flags,
*flags);
/* needs to read more data */
if(unlikely(rd.pos != rd.used)) {
if(unlikely((rd_unused = wolfSSL_BIO_wpending(rwbio)))) {
/* data still in the read buffer */
BUG("SSL_ERROR_WANT_READ but data still in"
" the rbio (%p, %d bytes at %d)\n",
rd.buf, rd.used - rd.pos, rd.pos);
" the rbio (%d bytes)\n",
(int)rd_unused);
goto bug;
}
if(unlikely((*flags & (RD_CONN_EOF | RD_CONN_SHORT_READ)) == 0)
&& bytes_free) {
/* there might still be data to read and there is space
* to decrypt it in tcp_req (no byte has been written into
* tcp_req in this case) */
* to decrypt it in tcp_req (no byte has been written into
* tcp_req in this case) */
TLS_RD_TRACE("(%p, %p) redo read *flags=%d bytes_free=%d\n", c,
flags, *flags, bytes_free);
goto redo_read;
}
goto end; /* no more data to read */
case SSL_ERROR_WANT_WRITE:
if(wr.used) {
case WOLFSSL_ERROR_WANT_WRITE:
if(wr_used) {
/* something was written => buffer not big enough to hold
* everything => reset buffer & retry (the tcp_write already
* happened if we are here) */
* everything => reset buffer & retry (the tcp_write already
* happened if we are here) */
TLS_RD_TRACE("(%p) SSL_ERROR_WANT_WRITE partial write"
" (written %d), retrying\n",
c, wr.used);
c, wr_used);
goto continue_ssl_read;
}
/* else write buffer too small, nothing written */
BUG("write buffer too small (%d/%d bytes)\n", wr.used, wr.size);
BUG("write buffer too small (%d/%d bytes)\n", (int)wr_used,
TLS_WR_MBUF_SZ);
goto bug;
case SSL_ERROR_SSL:
case WOLFSSL_ERROR_SSL:
/* protocol level error */
ERR("protocol level error\n");
TLS_ERR_SSL(err_src, ssl);
@ -1268,27 +1274,27 @@ continue_ssl_read:
goto error;
case SSL_ERROR_WANT_CONNECT:
case WOLFSSL_ERROR_WANT_CONNECT:
/* only if the underlying BIO is not yet connected
* and the call would block in connect().
* (not possible in our case) */
* and the call would block in connect().
* (not possible in our case) */
BUG("unexpected SSL_ERROR_WANT_CONNECT\n");
goto bug;
case SSL_ERROR_WANT_ACCEPT:
case WOLFSSL_ERROR_WANT_ACCEPT:
/* only if the underlying BIO is not yet connected
* and call would block in accept()
* (not possible in our case) */
* and call would block in accept()
* (not possible in our case) */
BUG("unexpected SSL_ERROR_WANT_ACCEPT\n");
goto bug;
case SSL_ERROR_WANT_X509_LOOKUP:
case WOLFSSL_ERROR_WANT_X509_LOOKUP:
/* can only appear on client application and it indicates that
* an installed client cert. callback should be called again
* (it returned < 0 indicated that it wants to be called
* later). Not possible in our case */
* an installed client cert. callback should be called again
* (it returned < 0 indicated that it wants to be called
* later). Not possible in our case */
BUG("unsupported SSL_ERROR_WANT_X509_LOOKUP");
goto bug;
case SSL_ERROR_SYSCALL:
case WOLFSSL_ERROR_SYSCALL:
TLS_ERR_RET(x, err_src);
if(!x) {
if(n == 0) {
@ -1308,65 +1314,8 @@ continue_ssl_read:
BUG("unexpected value (n = %d)\n", n);
goto bug;
}
if(unlikely(rd.pos != rd.used)) {
/* encrypted data still in the read buffer (SSL_read() did not
* consume all of it) */
if(unlikely(n < 0))
/* here n should always be >= 0 */
BUG("unexpected value (n = %d)\n", n);
else {
if(unlikely(bytes_free != 0)) {
/* 2i or 2ip: unconsumed input and output buffer not filled =>
* retry ssl read (SSL_read() will read will stop at
* record boundaries, unless readahead==1).
* No tcp_read() is attempted, since that would reset the
* current no-yet-consumed input data.
*/
TLS_RD_TRACE("(%p, %p) input not fully consumed =>"
" retry SSL_read"
" (pos: %d, remaining %d, output free %d)\n",
c, flags, rd.pos, rd.used - rd.pos, bytes_free);
goto continue_ssl_read;
}
/* 1i or 1ip: bytes_free == 0
* (unconsumed input, but filled output buffer) =>
* queue read data, and exit asking for repeating the call
* once there is some space in the output buffer.
*/
if(likely(!enc_rd_buf)) {
TLS_RD_TRACE("(%p, %p) creating enc_rd_buf (for %d bytes)\n", c,
flags, rd.used - rd.pos);
enc_rd_buf =
shm_malloc(sizeof(*enc_rd_buf) - sizeof(enc_rd_buf->buf)
+ rd.used - rd.pos);
if(unlikely(enc_rd_buf == 0)) {
ERR("memory allocation error (%d bytes requested)\n",
(int)(sizeof(*enc_rd_buf) + sizeof(enc_rd_buf->buf)
+ rd.used - rd.pos));
goto error;
}
enc_rd_buf->pos = 0;
enc_rd_buf->size = rd.used - rd.pos;
memcpy(enc_rd_buf->buf, rd.buf + rd.pos, enc_rd_buf->size);
} else if((enc_rd_buf->buf + enc_rd_buf->pos) == rd.buf) {
TLS_RD_TRACE("(%p, %p) enc_rd_buf already in use,"
" updating pos %d\n",
c, flags, enc_rd_buf->pos);
enc_rd_buf->pos += rd.pos;
} else {
BUG("enc_rd_buf->buf = %p, pos = %d, rd_buf.buf = %p\n",
enc_rd_buf->buf, enc_rd_buf->pos, rd.buf);
goto bug;
}
if(unlikely(tls_c->enc_rd_buf))
BUG("tls_c->enc_rd_buf!=0 (%p)\n", tls_c->enc_rd_buf);
/* there can't be 2 reads in parallel, so no locking is needed
* here */
tls_c->enc_rd_buf = enc_rd_buf;
enc_rd_buf = 0;
*flags |= RD_CONN_REPEAT_READ;
}
} else if(bytes_free != 0) {
if(bytes_free != 0) {
/* 2f or 2p: input fully consumed (rd.pos == rd.used),
* output buffer not filled, still possible to have pending
* data buffered by openssl */
@ -1402,15 +1351,11 @@ continue_ssl_read:
}
end:
if(enc_rd_buf)
shm_free(enc_rd_buf);
TLS_RD_TRACE(
"(%p, %p) end => %d (*flags=%d)\n", c, flags, ssl_read, *flags);
return ssl_read;
ssl_eof:
/* behave as an EOF would have been received at the tcp level */
if(enc_rd_buf)
shm_free(enc_rd_buf);
c->state = S_CONN_EOF;
*flags |= RD_CONN_EOF;
TLS_RD_TRACE(
@ -1419,8 +1364,6 @@ ssl_eof:
error_send:
error:
bug:
if(enc_rd_buf)
shm_free(enc_rd_buf);
r->error = TCP_READ_ERROR;
TLS_RD_TRACE("(%p, %p) end error => %d (*flags=%d)\n", c, flags, ssl_read,
*flags);

@ -62,7 +62,7 @@ typedef struct tls_extra_data
* (openssl code might add buffering BIOs so
* it's better to remember our original BIO) */
tls_ct_q *ct_wq;
struct tls_rd_buf *enc_rd_buf;
unsigned int flags;
enum tls_conn_states state;
} tls_extra_data_t;

@ -96,3 +96,19 @@ void collect_garbage(void)
lock_release(tls_domains_cfg_lock);
}
/** log the verification failure reason.
* wolfSSL has a different set of return values
* than OpenSSL
*/
void tls_dump_verification_failure(long verification_result)
{
int tls_log;
tls_log = cfg_get(tls, tls_cfg, log);
LOG(tls_log, "%s\n", wolfSSL_ERR_reason_error_string(verification_result));
}
/* vi: set ts=4 sw=4 tw=79:ai:cindent: */

@ -26,11 +26,9 @@
#ifndef _TLS_UTIL_H
#define _TLS_UTIL_H
#include <wolfssl/options.h>
#include <wolfssl/ssl.h>
#include "../../core/dprint.h"
#include "../../core/str.h"
#include "tls_cfg.h"
#include "tls_domain.h"
static inline int tls_err_ret(
@ -47,8 +45,8 @@ static inline int tls_err_ret(
}
while((err = ERR_get_error())) {
ret = 1;
ERR("%s%s (sni: %s)\n", s ? s : "", wolfSSL_ERR_error_string(err, 0),
(sn) ? sn : "unknown");
ERR("%s%s (sni: %s)\n", s ? s : "",
wolfSSL_ERR_error_string(err, 0), (sn) ? sn : "unknown");
}
}
return ret;
@ -83,4 +81,6 @@ int shm_asciiz_dup(char **dest, char *val);
*/
void collect_garbage(void);
void tls_dump_verification_failure(long verification_result);
#endif /* _TLS_UTIL_H */

@ -30,107 +30,8 @@
/* FIXME: remove this and use the value in domains instead */
#define VERIFY_DEPTH_S 3
/* This callback is called during each verification process,
at each step during the chain of certificates (this function
is not the certificate_verification one!). */
int verify_callback(int pre_verify_ok, X509_STORE_CTX *ctx)
{
char buf[256];
X509 *err_cert;
int err, depth;
depth = X509_STORE_CTX_get_error_depth(ctx);
LM_DBG("tls init - depth = %d\n", depth);
if(depth > VERIFY_DEPTH_S) {
LM_NOTICE("tls init - cert chain too long ( depth > VERIFY_DEPTH_S)\n");
pre_verify_ok = 0;
}
if(pre_verify_ok) {
LM_NOTICE("tls init - preverify is good: verify return: %d\n",
pre_verify_ok);
return pre_verify_ok;
}
err_cert = X509_STORE_CTX_get_current_cert(ctx);
err = X509_STORE_CTX_get_error(ctx);
X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof buf);
LM_NOTICE("tls init - subject = %s\n", buf);
LM_NOTICE("tls init - verify error - num=%d:%s\n", err,
X509_verify_cert_error_string(err));
LM_NOTICE("tls init - error code is %d (depth: %d)\n", err, depth);
switch(err) {
case X509_V_OK:
LM_NOTICE("tls init - all ok\n");
break;
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
X509_NAME_oneline(X509_get_issuer_name(err_cert), buf, sizeof buf);
LM_NOTICE("tls init - issuer= %s\n", buf);
break;
case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
case X509_V_ERR_CERT_NOT_YET_VALID:
LM_NOTICE("tls init - notBefore\n");
break;
case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
case X509_V_ERR_CERT_HAS_EXPIRED:
LM_NOTICE("tls init - notAfter\n");
break;
case X509_V_ERR_CERT_SIGNATURE_FAILURE:
case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
LM_NOTICE("tls init - unable to decrypt cert signature\n");
break;
case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
LM_NOTICE("tls init - unable to decode issuer public key\n");
break;
case X509_V_ERR_OUT_OF_MEM:
LM_ERR("tls init - Out of memory \n");
break;
case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
LM_NOTICE("tls init - Self signed certificate issue\n");
break;
case X509_V_ERR_CERT_CHAIN_TOO_LONG:
LM_NOTICE("tls init - certificate chain too long\n");
break;
case X509_V_ERR_INVALID_CA:
LM_NOTICE("tls init - invalid CA\n");
break;
case X509_V_ERR_PATH_LENGTH_EXCEEDED:
LM_NOTICE("tls init - path length exceeded\n");
break;
case X509_V_ERR_INVALID_PURPOSE:
LM_NOTICE("tls init - invalid purpose\n");
break;
case X509_V_ERR_CERT_UNTRUSTED:
LM_NOTICE("tls init - certificate untrusted\n");
break;
case X509_V_ERR_CERT_REJECTED:
LM_NOTICE("tls init - certificate rejected\n");
break;
default:
LM_NOTICE("tls init - something wrong with the"
" cert ... error code is %d (check x509_vfy.h)\n",
err);
break;
}
LM_NOTICE("tls init - verify return: %d\n", pre_verify_ok);
return (pre_verify_ok);
}
int verify_callback_unconditional_success(
int pre_verify_ok, X509_STORE_CTX *ctx)
int pre_verify_ok, WOLFSSL_X509_STORE_CTX *ctx)
{
LM_NOTICE("Post-verification callback: unconditional success\n");
return 1;

@ -29,15 +29,10 @@
#include <wolfssl/options.h>
#include <wolfssl/ssl.h>
/* This callback is called during each verification process,
at each step during the chain of certificates (this function
is not the certificate_verification one!). */
int verify_callback(int pre_verify_ok, X509_STORE_CTX *ctx);
/* Post-verification callback handler which unconditionally returns 1 (success)
Note that actual verification result can be retrieved through TLS PVs after-the-fact
*/
int verify_callback_unconditional_success(
int pre_verify_ok, X509_STORE_CTX *ctx);
int pre_verify_ok, WOLFSSL_X509_STORE_CTX *ctx);
#endif /* _TLS_VERIFY_H */

@ -53,7 +53,6 @@
#include "tls_util.h"
#include "tls_wolfssl_mod.h"
#include "tls_cfg.h"
#include "tls_rand.h"
#ifndef TLS_HOOKS
#error "TLS_HOOKS must be defined, or the tls module won't work"
@ -85,8 +84,6 @@ static void destroy(void);
static int w_is_peer_verified(struct sip_msg *msg, char *p1, char *p2);
static int w_tls_set_connect_server_id(sip_msg_t *msg, char *psrvid, char *p2);
int ksr_rand_engine_param(modparam_t type, void *val);
MODULE_VERSION
@ -225,13 +222,9 @@ static param_export_t params[] = {
{"ct_wq_max", PARAM_INT, &default_tls_cfg.ct_wq_max},
{"ct_wq_blk_size", PARAM_INT, &default_tls_cfg.ct_wq_blk_size},
{"tls_force_run", PARAM_INT, &default_tls_cfg.force_run},
{"low_mem_threshold1", PARAM_INT, &default_tls_cfg.low_mem_threshold1},
{"low_mem_threshold2", PARAM_INT, &default_tls_cfg.low_mem_threshold2},
{"renegotiation", PARAM_INT, &sr_tls_renegotiation},
{"xavp_cfg", PARAM_STR, &sr_tls_xavp_cfg},
{"event_callback", PARAM_STR, &sr_tls_event_callback},
{"rand_engine", PARAM_STR | USE_FUNC_PARAM,
(void *)ksr_rand_engine_param},
{0, 0, 0}};
@ -422,40 +415,12 @@ static void destroy(void)
}
int ksr_rand_engine_param(modparam_t type, void *val)
{
str *reng;
if(val == NULL) {
return -1;
}
reng = (str *)val;
LM_DBG("random engine: %.*s\n", reng->len, reng->s);
if(reng->len == 5 && strncasecmp(reng->s, "krand", 5) == 0) {
LM_DBG("setting krand random engine\n");
wolfSSL_RAND_set_rand_method(RAND_ksr_krand_method());
} else if(reng->len == 8 && strncasecmp(reng->s, "fastrand", 8) == 0) {
LM_DBG("setting fastrand random engine\n");
wolfSSL_RAND_set_rand_method(RAND_ksr_fastrand_method());
} else if(reng->len == 10 && strncasecmp(reng->s, "cryptorand", 10) == 0) {
LM_DBG("setting cryptorand random engine\n");
wolfSSL_RAND_set_rand_method(RAND_ksr_cryptorand_method());
}
/* WOLFFIX else if (reng->len == 8 && strncasecmp(reng->s, "kxlibssl", 8) == 0) {
LM_DBG("setting kxlibssl random engine\n");
wolfSSL_RAND_set_rand_method(RAND_ksr_kxlibssl_method());
} */
return 0;
}
static int ki_is_peer_verified(sip_msg_t *msg)
{
struct tcp_connection *c;
SSL *ssl;
long ssl_verify;
X509 *x509_cert;
WOLFSSL_X509 *x509_cert;
LM_DBG("started...\n");
if(msg->rcv.proto != PROTO_TLS) {
@ -488,7 +453,8 @@ static int ki_is_peer_verified(sip_msg_t *msg)
ssl = ((struct tls_extra_data *)c->extra_data)->ssl;
ssl_verify = wolfSSL_get_verify_result(ssl);
if(ssl_verify != X509_V_OK) {
// WOLFSSL_X509_V_OK / X509_V_OK
if(ssl_verify != 0) {
LM_WARN("verification of presented certificate failed... return -1\n");
tcpconn_put(c);
return -1;
@ -505,7 +471,7 @@ static int ki_is_peer_verified(sip_msg_t *msg)
return -1;
}
X509_free(x509_cert);
wolfSSL_X509_free(x509_cert);
tcpconn_put(c);
@ -593,9 +559,6 @@ int mod_register(char *path, int *dlflags, void *p1, void *p2)
register_tls_hooks(&tls_h);
LM_DBG("setting cryptorand random engine\n");
wolfSSL_RAND_set_rand_method(RAND_ksr_cryptorand_method());
sr_kemi_modules_add(sr_kemi_tls_exports);
return 0;

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save