Author: rmudgett Date: Thu Oct 2 16:55:37 2014 New Revision: 424395 URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=424395 Log: 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 ........ Merged revisions 424394 from http://svn.asterisk.org/svn/asterisk/branches/13 Modified: trunk/ (props changed) trunk/configs/samples/pjsip.conf.sample trunk/res/res_pjsip.c trunk/res/res_pjsip/config_transport.c Propchange: trunk/ ------------------------------------------------------------------------------ Binary property 'branch-13-merged' - no diff available. Modified: trunk/configs/samples/pjsip.conf.sample URL: http://svnview.digium.com/svn/asterisk/trunk/configs/samples/pjsip.conf.sample?view=diff&rev=424395&r1=424394&r2=424395 ============================================================================== --- trunk/configs/samples/pjsip.conf.sample (original) +++ trunk/configs/samples/pjsip.conf.sample Thu Oct 2 16:55:37 2014 @@ -148,7 +148,7 @@ ;bind=0.0.0.0 ;cert_file=/path/mycert.crt ;priv_key_file=/path/mykey.key -;cipher=ALL +;cipher=ADH-AES256-SHA,ADH-AES128-SHA ;method=tlsv1 @@ -648,7 +648,7 @@ ;ca_list_file= ; File containing a list of certificates to read TLS ONLY ; (default: "") ;cert_file= ; Certificate file for endpoint TLS ONLY (default: "") -;cipher= ; Preferred Cryptography Cipher TLS ONLY (default: "") +;cipher= ; Preferred cryptography cipher names TLS ONLY (default: "") ;domain= ; Domain the transport comes from (default: "") ;external_media_address= ; External IP address to use in RTP handling ; (default: "") Modified: trunk/res/res_pjsip.c URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_pjsip.c?view=diff&rev=424395&r1=424394&r2=424395 ============================================================================== --- trunk/res/res_pjsip.c (original) +++ trunk/res/res_pjsip.c Thu Oct 2 16:55:37 2014 @@ -653,9 +653,9 @@ <description><para> This option only applies if <replaceable>media_encryption</replaceable> is set to <literal>dtls</literal>. - </para><para> - Many options for acceptable ciphers. See link for more: - http://www.openssl.org/docs/apps/ciphers.html#CIPHER_STRINGS + </para> + <para>Many options for acceptable ciphers. See link for more:</para> + <para>http://www.openssl.org/docs/apps/ciphers.html#CIPHER_STRINGS </para></description> </configOption> <configOption name="dtls_ca_file"> @@ -820,11 +820,17 @@ <synopsis>Certificate file for endpoint (TLS ONLY)</synopsis> </configOption> <configOption name="cipher"> - <synopsis>Preferred Cryptography Cipher (TLS ONLY)</synopsis> - <description><para> - Many options for acceptable ciphers see link for more: - http://www.openssl.org/docs/apps/ciphers.html#CIPHER_STRINGS - </para></description> + <synopsis>Preferred cryptography cipher names (TLS ONLY)</synopsis> + <description> + <para>Comma separated list of cipher names or numeric equivalents. + Numeric quivalents can be either decimal or hexadecimal (0xX). + </para> + <para>There are many cipher names. Use the CLI command + <literal>pjsip list ciphers</literal> to see a list of cipher + names available for your installation. See link for more:</para> + <para>http://www.openssl.org/docs/apps/ciphers.html#CIPHER_SUITE_NAMES + </para> + </description> </configOption> <configOption name="domain"> <synopsis>Domain the transport comes from</synopsis> Modified: trunk/res/res_pjsip/config_transport.c URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_pjsip/config_transport.c?view=diff&rev=424395&r1=424394&r2=424395 ============================================================================== --- trunk/res/res_pjsip/config_transport.c (original) +++ trunk/res/res_pjsip/config_transport.c Thu Oct 2 16:55:37 2014 @@ -389,17 +389,19 @@ /*! \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 @@ 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) -{ - struct ast_sip_transport *transport = 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) +{ pj_ssl_cipher cipher; - - 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); - + int idx; + + 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); - return -1; - } + ast_log(LOG_ERROR, "Cipher '%s' is unsupported\n", name); + return -1; + } +} + +/*! \brief Custom handler for TLS cipher setting */ +static int transport_tls_cipher_handler(const struct aco_option *opt, struct ast_variable *var, void *obj) +{ + 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) { + *buf = NULL; + return; + } + + 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)); + ast_free(str); } static int transport_tls_cipher_to_str(const void *obj, const intptr_t *args, char **buf) { - RAII_VAR(struct ast_str *, str, ast_str_create(MAX_OBJECT_FIELD), ast_free); - const struct ast_sip_transport *transport = obj; - int i; - - if (!str) { - return -1; - } - - 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, ","); - } - } - - *buf = ast_strdup(ast_str_buffer(str)); - return 0; + 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 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" -- _____________________________________________________________________ -- Bandwidth and Colocation Provided by http://www.api-digital.com -- svn-commits mailing list To UNSUBSCRIBE or update options visit: http://lists.digium.com/mailman/listinfo/svn-commits
