diff options
author | dvossel <dvossel@f38db490-d61c-443f-a65b-d21fe96a405b> | 2009-05-15 22:59:16 +0000 |
---|---|---|
committer | dvossel <dvossel@f38db490-d61c-443f-a65b-d21fe96a405b> | 2009-05-15 22:59:16 +0000 |
commit | d3d9f91a7c98a9126f1cfe5f64a48b32c524afb2 (patch) | |
tree | b761081589ae8cd5bbe5948701b67fbf06d72afa | |
parent | d9f8f9e00f9162f6ca1af9cfc20041675d5cb2d1 (diff) |
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. This patch also fixes some compile errors that occured using gcc v4.3.2.
(Related to Security fix AST-2009-001)
(closes issue #14386)
Reported by: sabbathbh
git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.2@194878 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r-- | apps/app_chanspy.c | 2 | ||||
-rw-r--r-- | channels/chan_iax2.c | 30 |
2 files changed, 19 insertions, 13 deletions
diff --git a/apps/app_chanspy.c b/apps/app_chanspy.c index 34db4f7be..0d594996f 100644 --- a/apps/app_chanspy.c +++ b/apps/app_chanspy.c @@ -438,7 +438,7 @@ static int chanspy_exec(struct ast_channel *chan, void *data) if (recbase) { char filename[512]; snprintf(filename,sizeof(filename),"%s/%s.%d.raw",ast_config_AST_MONITOR_DIR, recbase, (int)time(NULL)); - if ((fd = open(filename, O_CREAT | O_WRONLY, O_TRUNC, 0644)) <= 0) { + if ((fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0644)) <= 0) { ast_log(LOG_WARNING, "Cannot open %s for recording\n", filename); fd = 0; } diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index c7fe21d8c..c2f965453 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -1445,7 +1445,7 @@ static int try_firmware(char *s) ast_log(LOG_WARNING, "Cannot open '%s': %s\n", s, strerror(errno)); return -1; } - fd = open(s2, O_RDWR | O_CREAT | O_EXCL); + fd = open(s2, O_RDWR | O_CREAT | O_EXCL, 0600); if (fd < 0) { ast_log(LOG_WARNING, "Cannot open '%s' for writing: %s\n", s2, strerror(errno)); close(ifd); @@ -5386,6 +5386,7 @@ static int register_verify(int callno, struct sockaddr_in *sin, struct iax_ies * /* We release the lock for the call to prevent a deadlock, but it's okay because only the current thread could possibly make it go away or make changes */ ast_mutex_unlock(&iaxsl[callno]); + /* SLD: first call to lookup peer during registration */ p = find_peer(peer, 1); ast_mutex_lock(&iaxsl[callno]); @@ -5394,6 +5395,12 @@ static int register_verify(int callno, struct sockaddr_in *sin, struct iax_ies * if (authdebug) ast_log(LOG_NOTICE, "No registration for peer '%s' (from %s)\n", peer, ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr)); ast_copy_string(iaxs[callno]->secret, "invalidpassword", sizeof(iaxs[callno]->secret)); + + /* A AUTHREQ must be sent to a invalid peer. By returning 0, a REGAUTH with a md5/rsa challenge + * will be sent. If the challenge has already been sent, return -1 to REGREJ the invalid peer. */ + if (ast_strlen_zero(iaxs[callno]->challenge)) { + return 0; + } return -1; } @@ -5427,7 +5434,7 @@ static int register_verify(int callno, struct sockaddr_in *sin, struct iax_ies * 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, ":"); } @@ -5459,7 +5466,7 @@ static int register_verify(int callno, struct sockaddr_in *sin, struct iax_ies * struct MD5Context md5; unsigned char digest[16]; char *tmppw, *stringp; - + tmppw = ast_strdupa(p->secret); stringp = tmppw; while((tmppw = strsep(&stringp, ";"))) { @@ -5469,7 +5476,7 @@ static int register_verify(int callno, struct sockaddr_in *sin, struct iax_ies * 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) { @@ -5481,12 +5488,8 @@ static int register_verify(int callno, struct sockaddr_in *sin, struct iax_ies * destroy_peer(p); return -1; } - } else if (!ast_strlen_zero(p->secret) || !ast_strlen_zero(p->inkeys)) { - if (authdebug && - ((!ast_strlen_zero(p->secret) && (p->authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(iaxs[callno]->challenge)) || - (!ast_strlen_zero(p->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 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. */ if (ast_test_flag(p, IAX_TEMPONLY)) destroy_peer(p); return -1; @@ -5496,7 +5499,6 @@ static int register_verify(int callno, struct sockaddr_in *sin, struct iax_ies * if (ast_test_flag(p, IAX_TEMPONLY)) destroy_peer(p); return 0; - } static int authenticate(char *challenge, char *secret, char *keyn, int authmethods, struct iax_ie_data *ied, struct sockaddr_in *sin, aes_encrypt_ctx *ecx, aes_decrypt_ctx *dcx) @@ -7850,7 +7852,11 @@ retryowner2: /* For security, always ack immediately */ if (delayreject) send_command_immediate(iaxs[fr->callno], AST_FRAME_IAX, IAX_COMMAND_ACK, fr->ts, NULL, 0,fr->iseqno); - register_verify(fr->callno, &sin, &ies); + if (register_verify(fr->callno, &sin, &ies)) { + /* Send delayed failure */ + auth_fail(fr->callno, IAX_COMMAND_REGREJ); + break; + } 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)); |