diff --git a/conf/rayo/autoload_configs/rayo.conf.xml b/conf/rayo/autoload_configs/rayo.conf.xml
index f9ac49b99d..0cb46d7992 100644
--- a/conf/rayo/autoload_configs/rayo.conf.xml
+++ b/conf/rayo/autoload_configs/rayo.conf.xml
@@ -11,8 +11,10 @@
-
+
+
+
diff --git a/src/mod/event_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml b/src/mod/event_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml
index f9ac49b99d..0cb46d7992 100644
--- a/src/mod/event_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml
+++ b/src/mod/event_handlers/mod_rayo/conf/autoload_configs/rayo.conf.xml
@@ -11,8 +11,10 @@
-
+
+
+
diff --git a/src/mod/event_handlers/mod_rayo/iks_helpers.h b/src/mod/event_handlers/mod_rayo/iks_helpers.h
index 4e21113452..442722a267 100644
--- a/src/mod/event_handlers/mod_rayo/iks_helpers.h
+++ b/src/mod/event_handlers/mod_rayo/iks_helpers.h
@@ -39,8 +39,7 @@
#define IKS_NS_XMPP_STANZAS "urn:ietf:params:xml:ns:xmpp-stanzas"
#define IKS_NS_XMPP_STREAMS "http://etherx.jabber.org/streams"
#define IKS_NS_XMPP_DIALBACK "jabber:server:dialback"
-#define IKS_NS_BIDI_FEATURE "urn:xmpp:features:bidi"
-#define IKS_NS_BIDI "urn:xmpp:bidi"
+#define IKS_NS_XMPP_TLS "urn:ietf:params:xml:ns:xmpp-tls"
struct xmpp_error {
const char *name;
diff --git a/src/mod/event_handlers/mod_rayo/mod_rayo.c b/src/mod/event_handlers/mod_rayo/mod_rayo.c
index 24b187d739..a110cdb703 100644
--- a/src/mod/event_handlers/mod_rayo/mod_rayo.c
+++ b/src/mod/event_handlers/mod_rayo/mod_rayo.c
@@ -3079,6 +3079,8 @@ static switch_status_t do_config(switch_memory_pool_t *pool, const char *config_
switch_xml_t l;
const char *shared_secret = switch_xml_attr_soft(domain, "shared-secret");
const char *name = switch_xml_attr_soft(domain, "name");
+ const char *cert = switch_xml_attr_soft(domain, "cert");
+ const char *key = switch_xml_attr_soft(domain, "key");
if (zstr(name)) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing
#include
+#include
+
#include "xmpp_streams.h"
#include "iks_helpers.h"
#include "sasl.h"
@@ -63,6 +65,10 @@ struct xmpp_stream_context {
int shutdown;
/** prevents context shutdown until all threads are finished */
switch_thread_rwlock_t *shutdown_rwlock;
+ /** path to cert PEM file */
+ const char *cert_pem_file;
+ /** path to key PEM file */
+ const char *key_pem_file;
};
/**
@@ -71,8 +77,8 @@ struct xmpp_stream_context {
enum xmpp_stream_state {
/** new connection */
XSS_CONNECT,
- /** bidirectional comms established */
- XSS_BIDI,
+ /** encrypted comms established */
+ XSS_SECURE,
/** remote party authenticated */
XSS_AUTHENTICATED,
/** client resource bound */
@@ -159,7 +165,7 @@ static const char *xmpp_stream_state_to_string(enum xmpp_stream_state state)
{
switch(state) {
case XSS_CONNECT: return "CONNECT";
- case XSS_BIDI: return "BIDI";
+ case XSS_SECURE: return "SECURE";
case XSS_AUTHENTICATED: return "AUTHENTICATED";
case XSS_RESOURCE_BOUND: return "RESOURCE_BOUND";
case XSS_READY: return "READY";
@@ -358,6 +364,31 @@ static void xmpp_send_client_header_auth(struct xmpp_stream *stream)
free(header);
}
+/**
+ * Send sasl + starttls reply to xmpp
+ * @param stream the xmpp stream
+ */
+static void xmpp_send_client_header_tls(struct xmpp_stream *stream)
+{
+ if (stream->context->key_pem_file && stream->context->cert_pem_file) {
+ struct xmpp_stream_context *context = stream->context;
+ char *header = switch_mprintf(
+ ""
+ ""
+ ""
+ "PLAIN"
+ "", context->domain, stream->id);
+ iks_send_raw(stream->parser, header);
+ free(header);
+ } else {
+ /* not set up for TLS, skip it */
+ stream->state = XSS_SECURE;
+ xmpp_send_client_header_auth(stream);
+ }
+}
+
/**
* Send sasl reply to xmpp
* @param stream the xmpp stream
@@ -370,12 +401,6 @@ static void xmpp_send_server_header_auth(struct xmpp_stream *stream)
" from='%s' id='%s' xml:lang='en' version='1.0'"
" xmlns:stream='"IKS_NS_XMPP_STREAMS"'>"
""
-#if 0
- ""
- ""
- "PLAIN"
- ""
-#endif
"",
context->domain, stream->id);
iks_send_raw(stream->parser, header);
@@ -417,6 +442,21 @@ static void xmpp_send_outbound_server_header(struct xmpp_stream *stream)
free(header);
}
+/**
+ * Handle message.
+ * @param the xmpp stream
+ * @param node the packet
+ */
+static void on_stream_starttls(struct xmpp_stream *stream, iks *node)
+{
+ /* wait for handshake to start */
+ if (iks_proceed_tls(stream->parser, stream->context->cert_pem_file, stream->context->key_pem_file, 1) == IKS_OK) {
+ stream->state = XSS_SECURE;
+ } else {
+ stream->state = XSS_ERROR;
+ }
+}
+
/**
* Handle message. Only PLAIN supported.
* @param stream the xmpp stream
@@ -431,7 +471,7 @@ static void on_stream_auth(struct xmpp_stream *stream, iks *node)
switch_log_printf(SWITCH_CHANNEL_UUID_LOG(stream->id), SWITCH_LOG_DEBUG, "%s, auth, state = %s\n", stream->jid, xmpp_stream_state_to_string(stream->state));
/* wrong state for authentication */
- if (stream->state != XSS_BIDI) {
+ if (stream->state != XSS_SECURE) {
switch_log_printf(SWITCH_CHANNEL_UUID_LOG(stream->id), SWITCH_LOG_WARNING, "%s, auth UNEXPECTED, state = %s\n", stream->jid, xmpp_stream_state_to_string(stream->state));
/* on_auth unexpected error */
stream->state = XSS_ERROR;
@@ -486,38 +526,6 @@ static void on_stream_auth(struct xmpp_stream *stream, iks *node)
}
}
-/**
- * Handle message.
- * @param stream the xmpp stream
- * @param node the packet
- */
-static void on_stream_bidi(struct xmpp_stream *stream, iks *node)
-{
- /* only allow bidi on s2s connections before auth */
- if (stream->s2s) {
- switch(stream->state) {
- case XSS_CONNECT:
- stream->state = XSS_BIDI;
- break;
- case XSS_BIDI:
- case XSS_AUTHENTICATED:
- case XSS_RESOURCE_BOUND:
- case XSS_READY:
- case XSS_SHUTDOWN:
- case XSS_ERROR:
- case XSS_DESTROY:
- /* error */
- stream->state = XSS_ERROR;
- switch_log_printf(SWITCH_CHANNEL_UUID_LOG(stream->id), SWITCH_LOG_INFO, "%s, bad state: %s\n", stream->jid, xmpp_stream_state_to_string(stream->state));
- break;
- }
- } else {
- /* error */
- stream->state = XSS_ERROR;
- switch_log_printf(SWITCH_CHANNEL_UUID_LOG(stream->id), SWITCH_LOG_INFO, "%s, bidi not allowed from client\n", stream->jid);
- }
-}
-
/**
* Handle request
* @param stream the xmpp stream
@@ -606,7 +614,7 @@ static void on_stream_iq(struct xmpp_stream *stream, iks *iq)
struct xmpp_stream_context *context = stream->context;
switch(stream->state) {
case XSS_CONNECT:
- case XSS_BIDI: {
+ case XSS_SECURE: {
iks *error = iks_new_error(iq, STANZA_ERROR_NOT_AUTHORIZED);
xmpp_stream_stanza_send(stream, error);
break;
@@ -689,7 +697,9 @@ static void on_client_stream_start(struct xmpp_stream *stream, iks *node)
switch (stream->state) {
case XSS_CONNECT:
- case XSS_BIDI:
+ xmpp_send_client_header_tls(stream);
+ break;
+ case XSS_SECURE:
xmpp_send_client_header_auth(stream);
break;
case XSS_AUTHENTICATED:
@@ -960,7 +970,7 @@ static void on_outbound_server_stream_start(struct xmpp_stream *stream, iks *nod
/* strange... I expect IKS_NODE_STOP, this is a workaround. */
stream->state = XSS_DESTROY;
break;
- case XSS_BIDI:
+ case XSS_SECURE:
case XSS_AUTHENTICATED:
case XSS_RESOURCE_BOUND:
case XSS_READY:
@@ -1001,7 +1011,7 @@ static void on_inbound_server_stream_start(struct xmpp_stream *stream, iks *node
case XSS_CONNECT:
xmpp_send_server_header_auth(stream);
break;
- case XSS_BIDI:
+ case XSS_SECURE:
break;
case XSS_AUTHENTICATED: {
/* all set */
@@ -1075,8 +1085,8 @@ static int on_stream(void *user_data, int type, iks *node)
on_stream_presence(stream, node);
} else if (!strcmp("auth", name)) {
on_stream_auth(stream, node);
- } else if (!strcmp("bidi", name)) {
- on_stream_bidi(stream, node);
+ } else if (!strcmp("starttls", name)) {
+ on_stream_starttls(stream, node);
} else if (!strcmp("db:result", name)) {
on_stream_dialback_result(stream, node);
} else if (!strcmp("db:verify", name)) {
@@ -1194,6 +1204,7 @@ static void *SWITCH_THREAD_FUNC xmpp_stream_thread(switch_thread_t *thread, void
case IKS_OK:
err_count = 0;
break;
+ case IKS_NET_TLSFAIL:
case IKS_NET_RWERR:
case IKS_NET_NOCONN:
case IKS_NET_NOSOCK:
@@ -1291,11 +1302,6 @@ static struct xmpp_stream *xmpp_stream_init(struct xmpp_stream_context *context,
stream->incoming = incoming;
switch_queue_create(&stream->msg_queue, MAX_QUEUE_LEN, pool);
- if (!stream->s2s) {
- /* client is already bi-directional */
- stream->state = XSS_BIDI;
- }
-
/* set up XMPP stream parser */
stream->parser = iks_stream_new(stream->s2s ? IKS_NS_SERVER : IKS_NS_CLIENT, stream, on_stream);
@@ -1829,6 +1835,23 @@ void *xmpp_stream_get_private(struct xmpp_stream *stream)
return stream->user_private;
}
+/**
+ * Add PEM cert file to stream for new SSL connections
+ */
+void xmpp_stream_context_add_cert(struct xmpp_stream_context *context, const char *cert_pem_file)
+{
+ context->cert_pem_file = switch_core_strdup(context->pool, cert_pem_file);
+}
+
+/**
+ * Add PEM key file to stream for new SSL connections
+ */
+void xmpp_stream_context_add_key(struct xmpp_stream_context *context, const char *key_pem_file)
+{
+ context->key_pem_file = switch_core_strdup(context->pool, key_pem_file);
+}
+
+
/* For Emacs:
* Local Variables:
* mode:c
diff --git a/src/mod/event_handlers/mod_rayo/xmpp_streams.h b/src/mod/event_handlers/mod_rayo/xmpp_streams.h
index d4ba663246..a07c75d025 100644
--- a/src/mod/event_handlers/mod_rayo/xmpp_streams.h
+++ b/src/mod/event_handlers/mod_rayo/xmpp_streams.h
@@ -37,6 +37,8 @@ typedef void (* xmpp_stream_recv_callback)(struct xmpp_stream *stream, iks *stan
typedef void (* xmpp_stream_destroy_callback)(struct xmpp_stream *stream);
extern struct xmpp_stream_context *xmpp_stream_context_create(const char *domain, const char *domain_secret, xmpp_stream_ready_callback ready, xmpp_stream_recv_callback recv, xmpp_stream_destroy_callback destroy);
+extern void xmpp_stream_context_add_cert(struct xmpp_stream_context *context, const char *cert_pem_file);
+extern void xmpp_stream_context_add_key(struct xmpp_stream_context *context, const char *key_pem_file);
extern void xmpp_stream_context_add_user(struct xmpp_stream_context *context, const char *user, const char *password);
extern void xmpp_stream_context_dump(struct xmpp_stream_context *context, switch_stream_handle_t *stream);
extern void xmpp_stream_context_destroy(struct xmpp_stream_context *context);