summaryrefslogtreecommitdiff
path: root/res/res_pjsip_transport_websocket.c
diff options
context:
space:
mode:
authorJørgen H <asterisk.org@hovland.cx>2017-02-16 10:22:47 +0000
committerJoshua Colp <jcolp@digium.com>2017-03-01 09:53:18 -0600
commit7922f26cb0377b0d36ead20178bf1d3bf06db784 (patch)
tree9d39da2134783b6c6bab3b248b8427fd91bb31d9 /res/res_pjsip_transport_websocket.c
parent26bf1846e2d436ffec1867351f25e5bcd43139c6 (diff)
res_pjsip WebRTC/websockets: Fix usage of WS vs WSS.
According to the RFC[1] WSS should only be used in the Via header for secure Websockets. * Use WSS in Via for secure transport. * Only register one transport with the WS name because it would be ambiguous. Outgoing requests may try to find the transport by name and pjproject only finds the first one registered. This may mess up unsecure websockets but the impact should be minimal. Firefox and Chrome do not support anything other than secure websockets anymore. * Added and updated some debug messages concerning websockets. * security_events.c: Relax case restriction when determining security transport type. * The res_pjsip_nat module has been updated to not touch the transport on Websocket originating messages. [1] https://tools.ietf.org/html/rfc7118 ASTERISK-26796 #close Change-Id: Ie3a0fb1a41101a4c1e49d875a8aa87b189e7ab12
Diffstat (limited to 'res/res_pjsip_transport_websocket.c')
-rw-r--r--res/res_pjsip_transport_websocket.c53
1 files changed, 41 insertions, 12 deletions
diff --git a/res/res_pjsip_transport_websocket.c b/res/res_pjsip_transport_websocket.c
index a9f526884..a52b42dfc 100644
--- a/res/res_pjsip_transport_websocket.c
+++ b/res/res_pjsip_transport_websocket.c
@@ -38,7 +38,6 @@
#include "asterisk/res_pjsip_session.h"
#include "asterisk/taskprocessor.h"
-static int transport_type_ws;
static int transport_type_wss;
/*!
@@ -149,6 +148,7 @@ static int transport_create(void *data)
pjsip_endpoint *endpt = ast_sip_get_pjsip_endpoint();
struct pjsip_tpmgr *tpmgr = pjsip_endpt_get_tpmgr(endpt);
+ char *ws_addr_str;
pj_pool_t *pool;
pj_str_t buf;
pj_status_t status;
@@ -183,9 +183,23 @@ static int transport_create(void *data)
goto on_error;
}
- pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&buf, ast_sockaddr_stringify(ast_websocket_remote_address(newtransport->ws_session))), &newtransport->transport.key.rem_addr);
+ /*
+ * The type_name here is mostly used by log messages eihter in
+ * pjproject or Asterisk. Other places are reconstituting subscriptions
+ * after a restart (which could never work for a websocket connection anyway),
+ * received MESSAGE requests to set PJSIP_TRANSPORT, and most importantly
+ * by pjproject when generating the Via header.
+ */
+ newtransport->transport.type_name = ast_websocket_is_secure(newtransport->ws_session)
+ ? "WSS" : "WS";
+
+ ws_addr_str = ast_sockaddr_stringify(ast_websocket_remote_address(newtransport->ws_session));
+ ast_debug(4, "Creating websocket transport for %s:%s\n",
+ newtransport->transport.type_name, ws_addr_str);
+
+ pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&buf, ws_addr_str), &newtransport->transport.key.rem_addr);
newtransport->transport.key.rem_addr.addr.sa_family = pj_AF_INET();
- newtransport->transport.key.type = ast_websocket_is_secure(newtransport->ws_session) ? transport_type_wss : transport_type_ws;
+ newtransport->transport.key.type = transport_type_wss;
newtransport->transport.addr_len = pj_sockaddr_get_len(&newtransport->transport.key.rem_addr);
@@ -196,7 +210,6 @@ static int transport_create(void *data)
newtransport->transport.local_name.host.slen = pj_ansi_strlen(newtransport->transport.local_name.host.ptr);
newtransport->transport.local_name.port = pj_sockaddr_get_port(&newtransport->transport.key.rem_addr);
- newtransport->transport.type_name = (char *)pjsip_transport_get_type_name(newtransport->transport.key.type);
newtransport->transport.flag = pjsip_transport_get_flag_from_type((pjsip_transport_type_e)newtransport->transport.key.type);
newtransport->transport.info = (char *)pj_pool_alloc(newtransport->transport.pool, 64);
@@ -382,19 +395,27 @@ static pj_bool_t websocket_on_rx_msg(pjsip_rx_data *rdata)
long type = rdata->tp_info.transport->key.type;
- if (type != (long)transport_type_ws && type != (long)transport_type_wss) {
+ if (type != (long) transport_type_wss) {
return PJ_FALSE;
}
- if ((contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL)) && !contact->star &&
- (PJSIP_URI_SCHEME_IS_SIP(contact->uri) || PJSIP_URI_SCHEME_IS_SIPS(contact->uri))) {
+ contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL);
+ if (contact
+ && !contact->star
+ && (PJSIP_URI_SCHEME_IS_SIP(contact->uri) || PJSIP_URI_SCHEME_IS_SIPS(contact->uri))) {
pjsip_sip_uri *uri = pjsip_uri_get_uri(contact->uri);
+ const pj_str_t *txp_str = &STR_WS;
+
+ ast_debug(4, "%s re-writing Contact URI from %.*s:%d%s%.*s to %s:%d;transport=%s\n",
+ pjsip_rx_data_get_info(rdata),
+ (int)pj_strlen(&uri->host), pj_strbuf(&uri->host), uri->port,
+ pj_strlen(&uri->transport_param) ? ";transport=" : "",
+ (int)pj_strlen(&uri->transport_param), pj_strbuf(&uri->transport_param),
+ rdata->pkt_info.src_name ?: "", rdata->pkt_info.src_port, pj_strbuf(txp_str));
pj_cstr(&uri->host, rdata->pkt_info.src_name);
uri->port = rdata->pkt_info.src_port;
- ast_debug(4, "Re-wrote Contact URI host/port to %.*s:%d\n",
- (int)pj_strlen(&uri->host), pj_strbuf(&uri->host), uri->port);
- pj_strdup(rdata->tp_info.pool, &uri->transport_param, &STR_WS);
+ pj_strdup(rdata->tp_info.pool, &uri->transport_param, txp_str);
}
rdata->msg_info.via->rport_param = 0;
@@ -429,8 +450,16 @@ static int load_module(void)
{
CHECK_PJSIP_MODULE_LOADED();
- pjsip_transport_register_type(PJSIP_TRANSPORT_RELIABLE, "WS", 5060, &transport_type_ws);
- pjsip_transport_register_type(PJSIP_TRANSPORT_RELIABLE | PJSIP_TRANSPORT_SECURE, "WS", 5060, &transport_type_wss);
+ /*
+ * We only need one transport type defined. Firefox and Chrome
+ * do not support anything other than secure websockets anymore.
+ *
+ * Also we really cannot have two transports with the same name
+ * because it would be ambiguous. Outgoing requests may try to
+ * find the transport by name and pjproject only finds the first
+ * one registered.
+ */
+ pjsip_transport_register_type(PJSIP_TRANSPORT_RELIABLE | PJSIP_TRANSPORT_SECURE, "ws", 5060, &transport_type_wss);
if (ast_sip_register_service(&websocket_module) != PJ_SUCCESS) {
return AST_MODULE_LOAD_DECLINE;