From 10c2e1749b764f4a225e857b1478c13a1b04f328 Mon Sep 17 00:00:00 2001 From: George Joseph <gjoseph@digium.com> Date: Thu, 28 Jan 2021 11:02:34 -0700 Subject: [PATCH] chan_iax2.c: Require secret and auth method if encryption is enabled If there's no secret specified for an iax2 peer and there's no secret specified in the dial string, Asterisk will crash if the auth method requested by the peer is MD5 or plaintext. You also couldn't specify a default auth method in the [general] section of iax.conf so if you don't have static peers defined and just use the dial string, Asterisk will still crash even if you have a secret specified in the dial string. * Added logic to iax2_call() and authenticate_reply() to print a warning and hanhup the call if encryption is requested and there's no secret or auth method. This prevents the crash. * Added the ability to specify a default "auth" in the [general] section of iax.conf. ASTERISK-29624 Reported by: N A Change-Id: I5928e16137581f7d383fcc7fa04ad96c919e6254 --- channels/chan_iax2.c | 39 ++++++++++++++++++++++++------- configs/samples/iax.conf.sample | 9 +++++++ doc/CHANGES-staging/chan_iax2.txt | 4 ++++ 3 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 doc/CHANGES-staging/chan_iax2.txt diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index b5600651bc..f07c22b8a6 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -433,6 +433,7 @@ static int amaflags = 0; static int adsi = 0; static int delayreject = 0; static int iax2_encryption = 0; +static int iax2_authmethods = 0; static struct ast_flags64 globalflags = { 0 }; @@ -4589,6 +4590,7 @@ struct create_addr_info { struct iax2_codec_pref prefs; int maxtime; int encmethods; + int authmethods; int found; int sockfd; int adsi; @@ -4664,6 +4666,7 @@ static int create_addr(const char *peername, struct ast_channel *c, struct ast_s cai->maxtime = peer->maxms; cai->capability = peer->capability; cai->encmethods = peer->encmethods; + cai->authmethods = peer->authmethods; cai->sockfd = peer->sockfd; cai->adsi = peer->adsi; cai->prefs = peer->prefs; @@ -5097,6 +5100,7 @@ static int iax2_call(struct ast_channel *c, const char *dest, int timeout) memset(&cai, 0, sizeof(cai)); cai.encmethods = iax2_encryption; + cai.authmethods = iax2_authmethods; memset(&pds, 0, sizeof(pds)); tmpstr = ast_strdupa(dest); @@ -5113,15 +5117,21 @@ static int iax2_call(struct ast_channel *c, const char *dest, int timeout) ast_log(LOG_WARNING, "No address associated with '%s'\n", pds.peer); return -1; } - if (ast_test_flag64(iaxs[callno], IAX_FORCE_ENCRYPT) && !cai.encmethods) { - ast_log(LOG_WARNING, "Encryption forced for call, but not enabled\n"); - ast_channel_hangupcause_set(c, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); - return -1; - } - if (ast_strlen_zero(cai.secret) && ast_test_flag64(iaxs[callno], IAX_FORCE_ENCRYPT)) { - ast_log(LOG_WARNING, "Call terminated. No secret given and force encrypt enabled\n"); - return -1; + + if (ast_test_flag64(&cai, IAX_FORCE_ENCRYPT) || + ast_test_flag64(iaxs[callno], IAX_FORCE_ENCRYPT)) { + if (!cai.encmethods) { + ast_log(LOG_WARNING, "Encryption forced for call, but not enabled\n"); + ast_channel_hangupcause_set(c, AST_CAUSE_BEARERCAPABILITY_NOTAVAIL); + return -1; + } + if (((cai.authmethods & IAX_AUTH_MD5) || (cai.authmethods & IAX_AUTH_PLAINTEXT)) && + ast_strlen_zero(cai.secret) && ast_strlen_zero(pds.password)) { + ast_log(LOG_WARNING, "Call terminated. Encryption forced but no secret provided\n"); + return -1; + } } + if (!pds.username && !ast_strlen_zero(cai.username)) pds.username = cai.username; if (!pds.password && !ast_strlen_zero(cai.secret)) @@ -8475,6 +8485,11 @@ static int authenticate_reply(struct chan_iax2_pvt *p, struct ast_sockaddr *addr } if (ies->encmethods) { + if (ast_strlen_zero(p->secret) && + ((ies->authmethods & IAX_AUTH_MD5) || (ies->authmethods & IAX_AUTH_PLAINTEXT))) { + ast_log(LOG_WARNING, "Call terminated. Encryption requested by peer but no secret available locally\n"); + return -1; + } ast_set_flag64(p, IAX_ENCRYPTED | IAX_KEYPOPULATED); } else if (ast_test_flag64(iaxs[callno], IAX_FORCE_ENCRYPT)) { ast_log(LOG_NOTICE, "Call initiated without encryption while forceencryption=yes option is set\n"); @@ -12811,6 +12826,7 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v, st if (firstpass) { ast_copy_flags64(peer, &globalflags, IAX_USEJITTERBUF | IAX_SENDCONNECTEDLINE | IAX_RECVCONNECTEDLINE | IAX_FORCE_ENCRYPT); peer->encmethods = iax2_encryption; + peer->authmethods = iax2_authmethods; peer->adsi = adsi; ast_string_field_set(peer, secret, ""); if (!found) { @@ -13151,6 +13167,7 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v, st user->prefs = prefs_global; user->capability = iax2_capability; user->encmethods = iax2_encryption; + user->authmethods = iax2_authmethods; user->adsi = adsi; user->calltoken_required = CALLTOKEN_DEFAULT; ast_string_field_set(user, name, name); @@ -13543,6 +13560,7 @@ static int set_config(const char *config_file, int reload, int forced) maxauthreq = 3; srvlookup = 0; + iax2_authmethods = 0; v = ast_variable_browse(cfg, "general"); @@ -13651,6 +13669,11 @@ static int set_config(const char *config_file, int reload, int forced) ast_log(LOG_WARNING, "Invalid address '%s' specified, at line %d\n", v->value, v->lineno); } } + } else if (!strcasecmp(v->name, "auth")) { + iax2_authmethods = get_auth_methods(v->value); + if (iax2_authmethods & IAX_AUTH_PLAINTEXT) { + ast_log(LOG_WARNING, "Default auth method is set to deprecated 'plaintext' at line %d of iax.conf\n", v->lineno); + } } else if (!strcasecmp(v->name, "authdebug")) { authdebug = ast_true(v->value); } else if (!strcasecmp(v->name, "encryption")) { diff --git a/configs/samples/iax.conf.sample b/configs/samples/iax.conf.sample index c6da46179c..1ee96ff872 100644 --- a/configs/samples/iax.conf.sample +++ b/configs/samples/iax.conf.sample @@ -201,6 +201,15 @@ jitterbuffer=no ;resyncthreshold=1000 ;jittertargetextra=40 +; There are three authentication methods that are supported: md5, plaintext, +; and rsa. The least secure is "plaintext", which sends passwords cleartext +; across the net. "md5" uses a challenge/response md5 sum arrangement, but +; still requires both ends have plain text access to the secret. "rsa" allows +; unidirectional secret knowledge through public/private keys. There is no +; default unless set here in the [general] section. +; +;auth=md5 + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; IAX2 Encryption ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/doc/CHANGES-staging/chan_iax2.txt b/doc/CHANGES-staging/chan_iax2.txt new file mode 100644 index 0000000000..4e1d844204 --- /dev/null +++ b/doc/CHANGES-staging/chan_iax2.txt @@ -0,0 +1,4 @@ +Subject: chan_iax2 + +You can now specify a default "auth" method in the +[general] section of iax.conf -- GitLab