diff options
-rw-r--r-- | res/res_pjsip.c | 39 | ||||
-rw-r--r-- | res/res_pjsip_sips_contact.c | 107 |
2 files changed, 145 insertions, 1 deletions
diff --git a/res/res_pjsip.c b/res/res_pjsip.c index afc383225..fd470b719 100644 --- a/res/res_pjsip.c +++ b/res/res_pjsip.c @@ -2309,6 +2309,42 @@ pjsip_dialog *ast_sip_create_dialog_uac(const struct ast_sip_endpoint *endpoint, return dlg; } +/*! + * \brief Determine if a SIPS Contact header is required. + * + * This uses the guideline provided in RFC 3261 Section 12.1.1 to + * determine if the Contact header must be a sips: URI. + * + * \param rdata The incoming dialog-starting request + * \retval 0 SIPS not required + * \retval 1 SIPS required + */ +static int uas_use_sips_contact(pjsip_rx_data *rdata) +{ + pjsip_rr_hdr *record_route; + + if (PJSIP_URI_SCHEME_IS_SIPS(rdata->msg_info.msg->line.req.uri)) { + return 1; + } + + record_route = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_RECORD_ROUTE, NULL); + if (record_route) { + if (PJSIP_URI_SCHEME_IS_SIPS(&record_route->name_addr)) { + return 1; + } + } else { + pjsip_contact_hdr *contact; + + contact = pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_CONTACT, NULL); + ast_assert(contact != NULL); + if (PJSIP_URI_SCHEME_IS_SIPS(contact->uri)) { + return 1; + } + } + + return 0; +} + pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, pjsip_rx_data *rdata, pj_status_t *status) { pjsip_dialog *dlg; @@ -2331,7 +2367,8 @@ pjsip_dialog *ast_sip_create_dialog_uas(const struct ast_sip_endpoint *endpoint, contact.ptr = pj_pool_alloc(rdata->tp_info.pool, PJSIP_MAX_URL_SIZE); contact.slen = pj_ansi_snprintf(contact.ptr, PJSIP_MAX_URL_SIZE, - "<sip:%s%.*s%s:%d%s%s>", + "<%s:%s%.*s%s:%d%s%s>", + uas_use_sips_contact(rdata) ? "sips" : "sip", (type & PJSIP_TRANSPORT_IPV6) ? "[" : "", (int)transport->local_name.host.slen, transport->local_name.host.ptr, diff --git a/res/res_pjsip_sips_contact.c b/res/res_pjsip_sips_contact.c new file mode 100644 index 000000000..f8e554cf4 --- /dev/null +++ b/res/res_pjsip_sips_contact.c @@ -0,0 +1,107 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2015, Digium, Inc. + * + * Mark Michelson <mmichelson@digium.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*** MODULEINFO + <depend>pjproject</depend> + <depend>res_pjsip</depend> + <support_level>core</support_level> + ***/ + +#include "asterisk.h" + +#include <pjsip.h> + +#include "asterisk/res_pjsip.h" +#include "asterisk/module.h" + +/*! + * \brief Upgrade Contact URIs on outgoing SIP requests to SIPS if required. + * + * The rules being used here are according to RFC 3261 section 8.1.1.8. In + * brief, if the request URI is SIPS or the topmost Route header is SIPS, + * then the Contact header we send must also be SIPS. + */ +static pj_status_t sips_contact_on_tx_request(pjsip_tx_data *tdata) +{ + pjsip_contact_hdr *contact; + pjsip_route_hdr *route; + pjsip_sip_uri *contact_uri; + + contact = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_CONTACT, NULL); + if (!contact) { + return PJ_SUCCESS; + } + + contact_uri = pjsip_uri_get_uri(contact->uri); + if (PJSIP_URI_SCHEME_IS_SIPS(contact_uri)) { + /* If the Contact header is already SIPS, then we don't need to do anything */ + return PJ_SUCCESS; + } + + if (PJSIP_URI_SCHEME_IS_SIPS(tdata->msg->line.req.uri)) { + ast_debug(1, "Upgrading contact URI on outgoing SIP request to SIPS due to SIPS Request URI\n"); + pjsip_sip_uri_set_secure(contact_uri, PJ_TRUE); + return PJ_SUCCESS; + } + + route = pjsip_msg_find_hdr(tdata->msg, PJSIP_H_ROUTE, NULL); + if (!route) { + return PJ_SUCCESS; + } + + if (!PJSIP_URI_SCHEME_IS_SIPS(&route->name_addr)) { + return PJ_SUCCESS; + } + + /* Our Contact header is not a SIPS URI, but our topmost Route header is. */ + ast_debug(1, "Upgrading contact URI on outgoing SIP request to SIPS due to SIPS Route header\n"); + pjsip_sip_uri_set_secure(contact_uri, PJ_TRUE); + + return PJ_SUCCESS; +} + +static pjsip_module sips_contact_module = { + .name = {"SIPS Contact", 12 }, + .id = -1, + .priority = PJSIP_MOD_PRIORITY_TSX_LAYER - 2, + .on_tx_request = sips_contact_on_tx_request, +}; + +static int unload_module(void) +{ + ast_sip_unregister_service(&sips_contact_module); + return 0; +} + +static int load_module(void) +{ + CHECK_PJSIP_MODULE_LOADED(); + + if (ast_sip_register_service(&sips_contact_module)) { + return AST_MODULE_LOAD_DECLINE; + } + + return AST_MODULE_LOAD_SUCCESS; +} + +AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "UAC SIPS Contact support", + .support_level = AST_MODULE_SUPPORT_CORE, + .load = load_module, + .unload = unload_module, + .load_pri = AST_MODPRI_APP_DEPEND, + ); |