]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
IAX2 REGAUTH loop
authorDavid Vossel <dvossel@digium.com>
Fri, 15 May 2009 22:59:16 +0000 (22:59 +0000)
committerDavid Vossel <dvossel@digium.com>
Fri, 15 May 2009 22:59:16 +0000 (22:59 +0000)
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: https://origsvn.digium.com/svn/asterisk/branches/1.2@194878 65c4cc65-6c06-0410-ace0-fbb531ad65f3

apps/app_chanspy.c
channels/chan_iax2.c

index 34db4f7befcd9f68012b93edc0f917f3ec62076a..0d594996fcf9ca21a2956cdd7075299971c184b3 100644 (file)
@@ -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;
                }
index c7fe21d8ca065d95cbf298b8a0635597e28a634b..c2f96545312b9608e4a96d7316b3b861203b38f2 100644 (file)
@@ -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));