DAHDI_DIR
DAHDI_INCLUDE
DAHDI_LIB
+PBX_OPENSSL_BIO_METHOD
+OPENSSL_BIO_METHOD_DIR
+OPENSSL_BIO_METHOD_INCLUDE
+OPENSSL_BIO_METHOD_LIB
PBX_OPENSSL_SRTP
OPENSSL_SRTP_DIR
OPENSSL_SRTP_INCLUDE
+OPENSSL_BIO_METHOD_DESCRIP="OpenSSL BIO Method Support"
+OPENSSL_BIO_METHOD_OPTION=crypto
+OPENSSL_BIO_METHOD_DIR=${CRYPTO_DIR}
+
+PBX_OPENSSL_BIO_METHOD=0
+
+
+
+
+
+
+
DAHDI_DESCRIP="DAHDI"
DAHDI_OPTION="dahdi"
PBX_DAHDI=0
fi
+
+if test "x${PBX_OPENSSL_BIO_METHOD}" != "x1" -a "${USE_OPENSSL_BIO_METHOD}" != "no"; then
+ pbxlibdir=""
+ # if --with-OPENSSL_BIO_METHOD=DIR has been specified, use it.
+ if test "x${OPENSSL_BIO_METHOD_DIR}" != "x"; then
+ if test -d ${OPENSSL_BIO_METHOD_DIR}/lib; then
+ pbxlibdir="-L${OPENSSL_BIO_METHOD_DIR}/lib"
+ else
+ pbxlibdir="-L${OPENSSL_BIO_METHOD_DIR}"
+ fi
+ fi
+
+ ast_ext_lib_check_save_CFLAGS="${CFLAGS}"
+ CFLAGS="${CFLAGS} "
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BIO_meth_new in -lssl" >&5
+$as_echo_n "checking for BIO_meth_new in -lssl... " >&6; }
+if ${ac_cv_lib_ssl_BIO_meth_new+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lssl ${pbxlibdir} -lcrypto $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char BIO_meth_new ();
+int
+main ()
+{
+return BIO_meth_new ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_ssl_BIO_meth_new=yes
+else
+ ac_cv_lib_ssl_BIO_meth_new=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_BIO_meth_new" >&5
+$as_echo "$ac_cv_lib_ssl_BIO_meth_new" >&6; }
+if test "x$ac_cv_lib_ssl_BIO_meth_new" = xyes; then :
+ AST_OPENSSL_BIO_METHOD_FOUND=yes
+else
+ AST_OPENSSL_BIO_METHOD_FOUND=no
+fi
+
+ CFLAGS="${ast_ext_lib_check_save_CFLAGS}"
+
+
+ # now check for the header.
+ if test "${AST_OPENSSL_BIO_METHOD_FOUND}" = "yes"; then
+ OPENSSL_BIO_METHOD_LIB="${pbxlibdir} -lssl -lcrypto"
+ # if --with-OPENSSL_BIO_METHOD=DIR has been specified, use it.
+ if test "x${OPENSSL_BIO_METHOD_DIR}" != "x"; then
+ OPENSSL_BIO_METHOD_INCLUDE="-I${OPENSSL_BIO_METHOD_DIR}/include"
+ fi
+ OPENSSL_BIO_METHOD_INCLUDE="${OPENSSL_BIO_METHOD_INCLUDE} "
+
+ # check for the header
+ ast_ext_lib_check_saved_CPPFLAGS="${CPPFLAGS}"
+ CPPFLAGS="${CPPFLAGS} ${OPENSSL_BIO_METHOD_INCLUDE}"
+ ac_fn_c_check_header_mongrel "$LINENO" "openssl/ssl.h" "ac_cv_header_openssl_ssl_h" "$ac_includes_default"
+if test "x$ac_cv_header_openssl_ssl_h" = xyes; then :
+ OPENSSL_BIO_METHOD_HEADER_FOUND=1
+else
+ OPENSSL_BIO_METHOD_HEADER_FOUND=0
+fi
+
+
+ CPPFLAGS="${ast_ext_lib_check_saved_CPPFLAGS}"
+
+ if test "x${OPENSSL_BIO_METHOD_HEADER_FOUND}" = "x0" ; then
+ OPENSSL_BIO_METHOD_LIB=""
+ OPENSSL_BIO_METHOD_INCLUDE=""
+ else
+
+ PBX_OPENSSL_BIO_METHOD=1
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_OPENSSL_BIO_METHOD 1
+_ACEOF
+
+ fi
+ fi
+fi
+
+
fi
if test "$PBX_OPENSSL" = "1";
#define DEFAULT_STRICT_RTP STRICT_RTP_YES /*!< Enabled by default */
#define DEFAULT_ICESUPPORT 1
+#define DEFAULT_DTLS_MTU 1200
extern struct ast_srtp_res *res_srtp;
extern struct ast_srtp_policy_res *res_srtp_policy;
static int turnport = DEFAULT_TURN_PORT;
static pj_str_t turnusername;
static pj_str_t turnpassword;
+#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
+static int dtls_mtu = DEFAULT_DTLS_MTU;
+#endif
static struct ast_ha *ice_blacklist = NULL; /*!< Blacklisted ICE networks */
static ast_rwlock_t ice_blacklist_lock = AST_RWLOCK_INIT_VALUE;
#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
static int ast_rtp_activate(struct ast_rtp_instance *instance);
-static void dtls_srtp_check_pending(struct ast_rtp_instance *instance, struct ast_rtp *rtp, int rtcp);
static void dtls_srtp_start_timeout_timer(struct ast_rtp_instance *instance, struct ast_rtp *rtp, int rtcp);
static void dtls_srtp_stop_timeout_timer(struct ast_rtp_instance *instance, struct ast_rtp *rtp, int rtcp);
+static int dtls_bio_write(BIO *bio, const char *buf, int len);
+static long dtls_bio_ctrl(BIO *bio, int cmd, long arg1, void *arg2);
+static int dtls_bio_new(BIO *bio);
+static int dtls_bio_free(BIO *bio);
+
+#ifndef HAVE_OPENSSL_BIO_METHOD
+static BIO_METHOD dtls_bio_methods = {
+ .type = BIO_TYPE_BIO,
+ .name = "rtp write",
+ .bwrite = dtls_bio_write,
+ .ctrl = dtls_bio_ctrl,
+ .create = dtls_bio_new,
+ .destroy = dtls_bio_free,
+};
+#else
+static BIO_METHOD *dtls_bio_methods;
+#endif
#endif
static int __rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int rtcp, int *via_ice, int use_srtp);
+#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
+static int dtls_bio_new(BIO *bio)
+{
+#ifdef HAVE_OPENSSL_BIO_METHOD
+ BIO_set_init(bio, 1);
+ BIO_set_data(bio, NULL);
+ BIO_set_shutdown(bio, 0);
+#else
+ bio->init = 1;
+ bio->ptr = NULL;
+ bio->flags = 0;
+#endif
+ return 1;
+}
+
+static int dtls_bio_free(BIO *bio)
+{
+ /* The pointer on the BIO is that of the RTP instance. It is not reference counted as the BIO
+ * lifetime is tied to the instance, and actions on the BIO are taken by the thread handling
+ * the RTP instance - not another thread.
+ */
+#ifdef HAVE_OPENSSL_BIO_METHOD
+ BIO_set_data(bio, NULL);
+#else
+ bio->ptr = NULL;
+#endif
+ return 1;
+}
+
+static int dtls_bio_write(BIO *bio, const char *buf, int len)
+{
+#ifdef HAVE_OPENSSL_BIO_METHOD
+ struct ast_rtp_instance *instance = BIO_get_data(bio);
+#else
+ struct ast_rtp_instance *instance = bio->ptr;
+#endif
+ struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+ int rtcp = 0;
+ struct ast_sockaddr remote_address = { {0, } };
+ int ice;
+
+ if (rtp->rtcp && rtp->rtcp->dtls.write_bio == bio) {
+ rtcp = 1;
+ ast_sockaddr_copy(&remote_address, &rtp->rtcp->them);
+ } else {
+ ast_rtp_instance_get_remote_address(instance, &remote_address);
+ }
+
+ if (ast_sockaddr_isnull(&remote_address)) {
+ return 0;
+ }
+
+ return __rtp_sendto(instance, (char *)buf, len, 0, &remote_address, rtcp, &ice, 0);
+}
+
+static long dtls_bio_ctrl(BIO *bio, int cmd, long arg1, void *arg2)
+{
+ switch (cmd) {
+ case BIO_CTRL_FLUSH:
+ return 1;
+ case BIO_CTRL_DGRAM_QUERY_MTU:
+ return dtls_mtu;
+ case BIO_CTRL_WPENDING:
+ case BIO_CTRL_PENDING:
+ return 0L;
+ default:
+ return 0;
+ }
+}
+
+#endif
+
#ifdef HAVE_PJPROJECT
/*! \brief Helper function which clears the ICE host candidate mapping */
static void host_candidate_overrides_clear(void)
}
static int dtls_details_initialize(struct dtls_details *dtls, SSL_CTX *ssl_ctx,
- enum ast_rtp_dtls_setup setup)
+ enum ast_rtp_dtls_setup setup, struct ast_rtp_instance *instance)
{
dtls->dtls_setup = setup;
}
BIO_set_mem_eof_return(dtls->read_bio, -1);
- if (!(dtls->write_bio = BIO_new(BIO_s_mem()))) {
+#ifdef HAVE_OPENSSL_BIO_METHOD
+ if (!(dtls->write_bio = BIO_new(dtls_bio_methods))) {
ast_log(LOG_ERROR, "Failed to allocate memory for outbound SSL traffic\n");
goto error;
}
- BIO_set_mem_eof_return(dtls->write_bio, -1);
+ BIO_set_data(dtls->write_bio, instance);
+#else
+ if (!(dtls->write_bio = BIO_new(&dtls_bio_methods))) {
+ ast_log(LOG_ERROR, "Failed to allocate memory for outbound SSL traffic\n");
+ goto error;
+ }
+ dtls->write_bio->ptr = instance;
+#endif
SSL_set_bio(dtls->ssl, dtls->read_bio, dtls->write_bio);
if (dtls->dtls_setup == AST_RTP_DTLS_SETUP_PASSIVE) {
return 0;
}
- return dtls_details_initialize(&rtp->rtcp->dtls, rtp->ssl_ctx, rtp->dtls.dtls_setup);
+ return dtls_details_initialize(&rtp->rtcp->dtls, rtp->ssl_ctx, rtp->dtls.dtls_setup, instance);
}
static const SSL_METHOD *get_dtls_method(void)
rtp->rekey = dtls_cfg->rekey;
rtp->suite = dtls_cfg->suite;
- res = dtls_details_initialize(&rtp->dtls, rtp->ssl_ctx, dtls_cfg->default_setup);
+ res = dtls_details_initialize(&rtp->dtls, rtp->ssl_ctx, dtls_cfg->default_setup, instance);
if (!res) {
dtls_setup_rtcp(instance);
}
* timer before we have a chance to even start it.
*/
dtls_srtp_start_timeout_timer(instance, rtp, rtcp);
-
- /*
- * We must call dtls_srtp_check_pending() after starting the timer.
- * Otherwise we won't prevent the race condition.
- */
- dtls_srtp_check_pending(instance, rtp, rtcp);
}
#endif
struct timeval dtls_timeout;
DTLSv1_handle_timeout(dtls->ssl);
- dtls_srtp_check_pending(instance, rtp, rtcp);
/* If a timeout can't be retrieved then this recurring scheduled item must stop */
if (!DTLSv1_get_timeout(dtls->ssl, &dtls_timeout)) {
AST_SCHED_DEL_UNREF(rtp->sched, dtls->timeout_timer, ao2_ref(instance, -1));
}
-/*! \pre instance is locked */
-static void dtls_srtp_check_pending(struct ast_rtp_instance *instance, struct ast_rtp *rtp, int rtcp)
-{
- struct dtls_details *dtls = !rtcp ? &rtp->dtls : &rtp->rtcp->dtls;
- size_t pending;
-
- if (!dtls->ssl || !dtls->write_bio) {
- return;
- }
-
- pending = BIO_ctrl_pending(dtls->write_bio);
-
- if (pending > 0) {
- char outgoing[pending];
- size_t out;
- struct ast_sockaddr remote_address = { {0, } };
- int ice;
-
- if (!rtcp) {
- ast_rtp_instance_get_remote_address(instance, &remote_address);
- } else {
- ast_sockaddr_copy(&remote_address, &rtp->rtcp->them);
- }
-
- /* If we do not yet know an address to send this to defer it until we do */
- if (ast_sockaddr_isnull(&remote_address)) {
- return;
- }
-
- out = BIO_read(dtls->write_bio, outgoing, sizeof(outgoing));
- __rtp_sendto(instance, outgoing, out, 0, &remote_address, rtcp, &ice, 0);
- }
-}
-
/* Scheduler callback */
static int dtls_srtp_renegotiate(const void *data)
{
SSL_renegotiate(rtp->dtls.ssl);
SSL_do_handshake(rtp->dtls.ssl);
- dtls_srtp_check_pending(instance, rtp, 0);
if (rtp->rtcp && rtp->rtcp->dtls.ssl && rtp->rtcp->dtls.ssl != rtp->dtls.ssl) {
SSL_renegotiate(rtp->rtcp->dtls.ssl);
SSL_do_handshake(rtp->rtcp->dtls.ssl);
- dtls_srtp_check_pending(instance, rtp, 1);
}
rtp->rekeyid = -1;
SSL_set_accept_state(dtls->ssl);
}
- dtls_srtp_check_pending(instance, rtp, rtcp);
-
BIO_write(dtls->read_bio, buf, len);
len = SSL_read(dtls->ssl, buf, len);
return -1;
}
- dtls_srtp_check_pending(instance, rtp, rtcp);
-
if (SSL_is_init_finished(dtls->ssl)) {
/* Any further connections will be existing since this is now established */
dtls->connection = AST_RTP_DTLS_CONNECTION_EXISTING;
blacklist_clear(&stun_blacklist_lock, &stun_blacklist);
#endif
+#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
+ dtls_mtu = DEFAULT_DTLS_MTU;
+#endif
+
if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
rtpstart = atoi(s);
if (rtpstart < MINIMUM_RTP_PORT)
/* Read STUN blacklist configuration lines */
blacklist_config_load(cfg, "stun_blacklist", &stun_blacklist_lock, &stun_blacklist);
#endif
+#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
+ if ((s = ast_variable_retrieve(cfg, "general", "dtls_mtu"))) {
+ if ((sscanf(s, "%d", &dtls_mtu) != 1) || dtls_mtu < 256) {
+ ast_log(LOG_WARNING, "Value for 'dtls_mtu' could not be read, using default of '%d' instead\n",
+ DEFAULT_DTLS_MTU);
+ dtls_mtu = DEFAULT_DTLS_MTU;
+ }
+ }
+#endif
ast_config_destroy(cfg);
#endif
+#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
+ dtls_bio_methods = BIO_meth_new(BIO_TYPE_BIO, "rtp write");
+ if (!dtls_bio_methods) {
+#ifdef HAVE_PJPROJECT
+ rtp_terminate_pjproject();
+#endif
+ return AST_MODULE_LOAD_DECLINE;
+ }
+ BIO_meth_set_write(dtls_bio_methods, dtls_bio_write);
+ BIO_meth_set_ctrl(dtls_bio_methods, dtls_bio_ctrl);
+ BIO_meth_set_create(dtls_bio_methods, dtls_bio_new);
+ BIO_meth_set_destroy(dtls_bio_methods, dtls_bio_free);
+#endif
+
if (ast_rtp_engine_register(&asterisk_rtp_engine)) {
+#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
+ BIO_meth_free(dtls_bio_methods);
+#endif
#ifdef HAVE_PJPROJECT
rtp_terminate_pjproject();
#endif
}
if (ast_cli_register_multiple(cli_rtp, ARRAY_LEN(cli_rtp))) {
+#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
+ BIO_meth_free(dtls_bio_methods);
+#endif
#ifdef HAVE_PJPROJECT
ast_rtp_engine_unregister(&asterisk_rtp_engine);
rtp_terminate_pjproject();
ast_rtp_engine_unregister(&asterisk_rtp_engine);
ast_cli_unregister_multiple(cli_rtp, ARRAY_LEN(cli_rtp));
+#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
+ if (dtls_bio_methods) {
+ BIO_meth_free(dtls_bio_methods);
+ }
+#endif
+
#ifdef HAVE_PJPROJECT
host_candidate_overrides_clear();
pj_thread_register_check();