[svn-commits] dvossel: tag 1.4.25.1 r199204 - /tags/1.4.25.1/channels/chan_iax2.c
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Thu Jun 4 14:37:51 CDT 2009
Author: dvossel
Date: Thu Jun 4 14:37:42 2009
New Revision: 199204
URL: http://svn.asterisk.org/svn-view/asterisk?view=rev&rev=199204
Log:
IAX2 REGAUTH loop
IAX was not sending REGREJ to terminate invalid registrations. Instead it sent another REGAUTH if the authentication challenge failed. This caused a loop of REGREQ and REGAUTH frames.
(Related to Security fix AST-2009-001)
(closes issue #14867)
Reported by: aragon
Tested by: dvossel
(closes issue #14717)
Reported by: mobeck
Patches:
regauth_loop_update_patch.diff uploaded by dvossel (license 671)
Tested by: dvossel
Modified:
tags/1.4.25.1/channels/chan_iax2.c
Modified: tags/1.4.25.1/channels/chan_iax2.c
URL: http://svn.asterisk.org/svn-view/asterisk/tags/1.4.25.1/channels/chan_iax2.c?view=diff&rev=199204&r1=199203&r2=199204
==============================================================================
--- tags/1.4.25.1/channels/chan_iax2.c (original)
+++ tags/1.4.25.1/channels/chan_iax2.c Thu Jun 4 14:37:42 2009
@@ -229,10 +229,9 @@
static ast_cond_t sched_cond;
enum {
- IAX_STATE_STARTED = (1 << 0),
- IAX_STATE_AUTHENTICATED = (1 << 1),
- IAX_STATE_TBD = (1 << 2),
- IAX_STATE_UNCHANGED = (1 << 3),
+ IAX_STATE_STARTED = (1 << 0),
+ IAX_STATE_AUTHENTICATED = (1 << 1),
+ IAX_STATE_TBD = (1 << 2),
} iax2_state;
struct iax2_context {
@@ -513,7 +512,7 @@
/*! The jitterbuffer */
jitterbuf *jb;
/*! active jb read scheduler id */
- int jbid;
+ int jbid;
/*! LAG */
int lag;
/*! Error, as discovered by the manager */
@@ -5703,7 +5702,7 @@
int expire = 0;
int res = -1;
- ast_clear_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED | IAX_STATE_UNCHANGED);
+ ast_clear_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
/* iaxs[callno]->peer[0] = '\0'; not necc. any more-- stringfield is pre-inited to null string */
if (ies->username)
ast_copy_string(peer, ies->username, sizeof(peer));
@@ -5727,10 +5726,28 @@
ast_mutex_lock(&iaxsl[callno]);
if (!p || !iaxs[callno]) {
if (iaxs[callno]) {
+ int plaintext = ((last_authmethod & IAX_AUTH_PLAINTEXT) | (iaxs[callno]->authmethods & IAX_AUTH_PLAINTEXT));
+
ast_string_field_set(iaxs[callno], secret, "badsecret");
+
+ /* An AUTHREQ must be sent in response to a REGREQ of an invalid peer unless
+ * 1. A challenge already exists indicating a AUTHREQ was already sent out.
+ * 2. A plaintext secret is present in ie as result of a previous AUTHREQ requesting it.
+ * 3. A plaintext secret is present in the ie and the last_authmethod used by a peer happened
+ * to be plaintext, indicating it is an authmethod used by other peers on the system.
+ *
+ * If none of these cases exist, res will be returned as 0 without authentication indicating
+ * an AUTHREQ needs to be sent out. */
+
+ if (ast_strlen_zero(iaxs[callno]->challenge) &&
+ !(!ast_strlen_zero(secret) && plaintext)) {
+ /* by setting res to 0, an REGAUTH will be sent */
+ res = 0;
+ }
}
if (authdebug && !p)
ast_log(LOG_NOTICE, "No registration for peer '%s' (from %s)\n", peer, ast_inet_ntoa(sin->sin_addr));
+
goto return_unref;
}
@@ -5745,8 +5762,6 @@
ast_log(LOG_NOTICE, "Host %s denied access to register peer '%s'\n", ast_inet_ntoa(sin->sin_addr), p->name);
goto return_unref;
}
- if (!inaddrcmp(&p->addr, sin))
- ast_set_flag(&iaxs[callno]->state, IAX_STATE_UNCHANGED);
ast_string_field_set(iaxs[callno], secret, p->secret);
ast_string_field_set(iaxs[callno], inkeys, p->inkeys);
/* Check secret against what we have on file */
@@ -5762,7 +5777,7 @@
if (key && !ast_check_signature(key, iaxs[callno]->challenge, rsasecret)) {
ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
break;
- } else if (!key)
+ } else if (!key)
ast_log(LOG_WARNING, "requested inkey '%s' does not exist\n", keyn);
keyn = strsep(&stringp, ":");
}
@@ -5780,7 +5795,7 @@
struct MD5Context md5;
unsigned char digest[16];
char *tmppw, *stringp;
-
+
tmppw = ast_strdupa(p->secret);
stringp = tmppw;
while((tmppw = strsep(&stringp, ";"))) {
@@ -5790,7 +5805,7 @@
MD5Final(digest, &md5);
for (x=0;x<16;x++)
sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */
- if (!strcasecmp(requeststr, md5secret))
+ if (!strcasecmp(requeststr, md5secret))
break;
}
if (tmppw) {
@@ -5808,17 +5823,16 @@
goto return_unref;
} else
ast_set_flag(&iaxs[callno]->state, IAX_STATE_AUTHENTICATED);
- } else if (!ast_strlen_zero(iaxs[callno]->secret) || !ast_strlen_zero(iaxs[callno]->inkeys)) {
- if (authdebug &&
- ((!ast_strlen_zero(iaxs[callno]->secret) && (p->authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(iaxs[callno]->challenge)) ||
- (!ast_strlen_zero(iaxs[callno]->inkeys) && (p->authmethods & IAX_AUTH_RSA) && !ast_strlen_zero(iaxs[callno]->challenge)))) {
- ast_log(LOG_NOTICE, "Inappropriate authentication received for '%s'\n", p->name);
- } /* ELSE this is the first time through and no challenge exists, so it's not quite yet a failure. */
+ } else if (!ast_strlen_zero(iaxs[callno]->challenge) && ast_strlen_zero(md5secret) && ast_strlen_zero(rsasecret)) {
+ /* if challenge has been sent, but no challenge response if given, reject. */
goto return_unref;
}
ast_device_state_changed("IAX2/%s", p->name); /* Activate notification */
+ /* either Authentication has taken place, or a REGAUTH must be sent before verifying registration */
+ res = 0;
return_unref:
+
if (iaxs[callno]) {
ast_string_field_set(iaxs[callno], peer, peer);
@@ -5828,12 +5842,9 @@
}
}
- res = 0;
-
if (p) {
peer_unref(p);
}
-
return res;
}
@@ -6531,6 +6542,9 @@
* Therefore, we use whatever the last peer used (which may vary over the
* course of a server, which should leak minimal information). */
sentauthmethod = p ? p->authmethods : last_authmethod ? last_authmethod : (IAX_AUTH_MD5 | IAX_AUTH_PLAINTEXT);
+ if (!p) {
+ iaxs[callno]->authmethods = sentauthmethod;
+ }
iax_ie_append_short(&ied, IAX_IE_AUTHMETHODS, sentauthmethod);
if (sentauthmethod & (IAX_AUTH_RSA | IAX_AUTH_MD5)) {
/* Build the challenge */
@@ -8487,8 +8501,9 @@
ast_mutex_unlock(&iaxsl[fr->callno]);
return 1;
}
- if ((ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) ||
- ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED | IAX_STATE_UNCHANGED)) {
+ if ((ast_strlen_zero(iaxs[fr->callno]->secret) && ast_strlen_zero(iaxs[fr->callno]->inkeys)) ||
+ ast_test_flag(&iaxs[fr->callno]->state, IAX_STATE_AUTHENTICATED)) {
+
if (f.subclass == IAX_COMMAND_REGREL)
memset(&sin, 0, sizeof(sin));
if (update_registry(&sin, fr->callno, ies.devicetype, fd, ies.refresh))
More information about the svn-commits
mailing list