summaryrefslogtreecommitdiff
path: root/res/res_pjsip/config_transport.c
diff options
context:
space:
mode:
authorRichard Mudgett <rmudgett@digium.com>2014-10-02 21:52:56 +0000
committerRichard Mudgett <rmudgett@digium.com>2014-10-02 21:52:56 +0000
commit94105b30a602881c9f6bf5176a28cbf9e4bdf3db (patch)
tree0dcc547d06c40a320cb186ec06787e5d483f56d0 /res/res_pjsip/config_transport.c
parent9ff743e9958e4fafa57a0ecd448e653f61668b5d (diff)
res_pjsip: Make transport cipher option accept a comma separated list of cipher names.
Improvements to the res_pjsip transport cipher option. * Made the cipher option accept a comma separated list of OpenSSL cipher names. Users of realtime will be glad if they have more than one name to list. * Added the CLI command 'pjsip list ciphers' so a user can know what OpenSSL names are available for the cipher option. * Updated the cipher option online XML documentation to specify what is expected for the value. * Updated pjsip.conf.sample to not indicate that ALL is acceptable since ALL does not imply a preference order for the ciphers and PJSIP does not simply pass the string to OpenSSL for interpretation. ASTERISK-24199 #close Reported by: Joshua Colp Review: https://reviewboard.asterisk.org/r/4018/ ........ Merged revisions 424393 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/13@424394 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'res/res_pjsip/config_transport.c')
-rw-r--r--res/res_pjsip/config_transport.c133
1 files changed, 103 insertions, 30 deletions
diff --git a/res/res_pjsip/config_transport.c b/res/res_pjsip/config_transport.c
index 9996ddd08..fe7612fa5 100644
--- a/res/res_pjsip/config_transport.c
+++ b/res/res_pjsip/config_transport.c
@@ -389,17 +389,19 @@ static int tls_method_to_str(const void *obj, const intptr_t *args, char **buf)
/*! \brief Helper function which turns a cipher name into an identifier */
static pj_ssl_cipher cipher_name_to_id(const char *name)
{
- pj_ssl_cipher ciphers[100], id = 0;
+ pj_ssl_cipher ciphers[100];
+ pj_ssl_cipher id = 0;
unsigned int cipher_num = PJ_ARRAY_SIZE(ciphers);
int pos;
+ const char *pos_name;
if (pj_ssl_cipher_get_availables(ciphers, &cipher_num)) {
return 0;
}
for (pos = 0; pos < cipher_num; ++pos) {
- if (!pj_ssl_cipher_name(ciphers[pos]) ||
- strcmp(pj_ssl_cipher_name(ciphers[pos]), name)) {
+ pos_name = pj_ssl_cipher_name(ciphers[pos]);
+ if (!pos_name || strcmp(pos_name, name)) {
continue;
}
@@ -410,60 +412,130 @@ static pj_ssl_cipher cipher_name_to_id(const char *name)
return id;
}
-/*! \brief Custom handler for TLS cipher setting */
-static int transport_tls_cipher_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
+/*!
+ * \internal
+ * \brief Add a new cipher to the transport's cipher list array.
+ *
+ * \param transport Which transport to add the cipher to.
+ * \param name Cipher identifier name.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int transport_cipher_add(struct ast_sip_transport *transport, const char *name)
{
- struct ast_sip_transport *transport = obj;
pj_ssl_cipher cipher;
+ int idx;
- if (ast_strlen_zero(var->value)) {
- return 0;
- }
-
- if (transport->tls.ciphers_num == (SIP_TLS_MAX_CIPHERS - 1)) {
- return -1;
- }
-
- cipher = cipher_name_to_id(var->value);
-
+ cipher = cipher_name_to_id(name);
if (!cipher) {
/* TODO: Check this over/tweak - it's taken from pjsua for now */
- if (!strnicmp(var->value, "0x", 2)) {
- pj_str_t cipher_st = pj_str((char*)var->value + 2);
+ if (!strnicmp(name, "0x", 2)) {
+ pj_str_t cipher_st = pj_str((char *) name + 2);
cipher = pj_strtoul2(&cipher_st, NULL, 16);
} else {
- cipher = atoi(var->value);
+ cipher = atoi(name);
}
}
if (pj_ssl_cipher_is_supported(cipher)) {
+ for (idx = transport->tls.ciphers_num; idx--;) {
+ if (transport->ciphers[idx] == cipher) {
+ /* The cipher is already in the list. */
+ return 0;
+ }
+ }
transport->ciphers[transport->tls.ciphers_num++] = cipher;
return 0;
} else {
- ast_log(LOG_ERROR, "Cipher '%s' is unsupported\n", var->value);
+ ast_log(LOG_ERROR, "Cipher '%s' is unsupported\n", name);
return -1;
}
}
-static int transport_tls_cipher_to_str(const void *obj, const intptr_t *args, char **buf)
+/*! \brief Custom handler for TLS cipher setting */
+static int transport_tls_cipher_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
{
- RAII_VAR(struct ast_str *, str, ast_str_create(MAX_OBJECT_FIELD), ast_free);
- const struct ast_sip_transport *transport = obj;
- int i;
+ struct ast_sip_transport *transport = obj;
+ char *parse;
+ char *name;
+ int res = 0;
+
+ parse = ast_strdupa(S_OR(var->value, ""));
+ while ((name = strsep(&parse, ","))) {
+ name = ast_strip(name);
+ if (ast_strlen_zero(name)) {
+ continue;
+ }
+ if (ARRAY_LEN(transport->ciphers) <= transport->tls.ciphers_num) {
+ ast_log(LOG_ERROR, "Too many ciphers specified\n");
+ res = -1;
+ break;
+ }
+ res |= transport_cipher_add(transport, name);
+ }
+ return res ? -1 : 0;
+}
+
+static void cipher_to_str(char **buf, const pj_ssl_cipher *ciphers, unsigned int cipher_num)
+{
+ struct ast_str *str;
+ int idx;
+ str = ast_str_create(128);
if (!str) {
- return -1;
+ *buf = NULL;
+ return;
}
- for (i = 0; i < transport->tls.ciphers_num; ++i) {
- ast_str_append(&str, 0, "%s", pj_ssl_cipher_name(transport->ciphers[i]));
- if (i < transport->tls.ciphers_num - 1) {
- ast_str_append(&str, 0, ",");
+ for (idx = 0; idx < cipher_num; ++idx) {
+ ast_str_append(&str, 0, "%s", pj_ssl_cipher_name(ciphers[idx]));
+ if (idx < cipher_num - 1) {
+ ast_str_append(&str, 0, ", ");
}
}
*buf = ast_strdup(ast_str_buffer(str));
- return 0;
+ ast_free(str);
+}
+
+static int transport_tls_cipher_to_str(const void *obj, const intptr_t *args, char **buf)
+{
+ const struct ast_sip_transport *transport = obj;
+
+ cipher_to_str(buf, transport->ciphers, transport->tls.ciphers_num);
+ return *buf ? 0 : -1;
+}
+
+static char *handle_pjsip_list_ciphers(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+ pj_ssl_cipher ciphers[100];
+ unsigned int cipher_num = PJ_ARRAY_SIZE(ciphers);
+ char *buf;
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "pjsip list ciphers";
+ e->usage = "Usage: pjsip list ciphers\n"
+ " List available OpenSSL cipher names.\n";
+ return NULL;
+ case CLI_GENERATE:
+ return NULL;
+ }
+
+ if (pj_ssl_cipher_get_availables(ciphers, &cipher_num) || !cipher_num) {
+ buf = NULL;
+ } else {
+ cipher_to_str(&buf, ciphers, cipher_num);
+ }
+
+ if (!ast_strlen_zero(buf)) {
+ ast_cli(a->fd, "Available ciphers: '%s'\n", buf);
+ } else {
+ ast_cli(a->fd, "No available ciphers\n");
+ }
+ ast_free(buf);
+ return CLI_SUCCESS;
}
/*! \brief Custom handler for localnet setting */
@@ -638,6 +710,7 @@ static int cli_print_body(void *obj, void *arg, int flags)
}
static struct ast_cli_entry cli_commands[] = {
+ AST_CLI_DEFINE(handle_pjsip_list_ciphers, "List available OpenSSL cipher names"),
AST_CLI_DEFINE(ast_sip_cli_traverse_objects, "List PJSIP Transports",
.command = "pjsip list transports",
.usage = "Usage: pjsip list transports\n"