]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
IAX2 encryption regression
authorDavid Vossel <dvossel@digium.com>
Thu, 10 Sep 2009 21:06:07 +0000 (21:06 +0000)
committerDavid Vossel <dvossel@digium.com>
Thu, 10 Sep 2009 21:06:07 +0000 (21:06 +0000)
The IAX2 Call Token security patch inadvertently broke the use of
encryption due to the reorganization of code in the socket_process()
function.  When encryption is used, an incoming full frame must first
be decrypted before the information elements can be parsed.  The
security release mistakenly moved IE parsing before decryption in
order to process the new Call Token IE.  To resolve this, decryption
of full frames is once again done before looking into the frame.  This
involves searching for an existing callno, checking the pvt to see if
encryption is turned on, and decrypting the packet before the internal
fields of the full frame are accessed.

associated with AST-2009-006

(closes issue #15834)
Reported by: karesmakro
Patches:
      iax2_encryption_fix_1.4.diff uploaded by dvossel (license 671)
Tested by: dvossel, karesmakro

Review: https://reviewboard.asterisk.org/r/355/

git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.4@217806 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_iax2.c

index fea253c26d3fa25eb2abbf49f35ba0686720c6c0..1aca432dbd97a3d08ecfd4a2c956eb3d3676f9ee 100644 (file)
@@ -8234,6 +8234,7 @@ static int socket_process(struct iax2_thread *thread)
        int new = NEW_PREVENT;
        void *ptr;
        int dcallno = 0;
+       char decrypted = 0;
        struct ast_iax2_full_hdr *fh = (struct ast_iax2_full_hdr *)thread->buf;
        struct ast_iax2_mini_hdr *mh = (struct ast_iax2_mini_hdr *)thread->buf;
        struct ast_iax2_meta_hdr *meta = (struct ast_iax2_meta_hdr *)thread->buf;
@@ -8410,6 +8411,25 @@ static int socket_process(struct iax2_thread *thread)
 
                /* Get the destination call number */
                dcallno = ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS;
+
+
+               /* check to make sure this full frame isn't encrypted before we attempt
+                * to look inside of it. If it is encrypted, decrypt it first. Its ok if the
+                * callno is not found here, that just means one hasn't been allocated for
+                * this connection yet. */
+               if ((dcallno != 1) && (fr->callno = find_callno(ntohs(mh->callno) & ~IAX_FLAG_FULL, dcallno, &sin, NEW_PREVENT, fd, 1))) {
+                       ast_mutex_lock(&iaxsl[fr->callno]);
+                       if (ast_test_flag(iaxs[fr->callno], IAX_ENCRYPTED)) {
+                               if (decrypt_frame(fr->callno, fh, &f, &res)) {
+                                       ast_log(LOG_NOTICE, "Packet Decrypt Failed!\n");
+                                       ast_mutex_unlock(&iaxsl[fr->callno]);
+                                       return 1;
+                               }
+                               decrypted = 1;
+                       }
+                       ast_mutex_unlock(&iaxsl[fr->callno]);
+               }
+
                /* Retrieve the type and subclass */
                f.frametype = fh->type;
                if (f.frametype == AST_FRAME_VIDEO) {
@@ -8521,17 +8541,19 @@ static int socket_process(struct iax2_thread *thread)
                        ast_mutex_unlock(&iaxsl[fr->callno]);
                return 1;
        }
-       if (ast_test_flag(iaxs[fr->callno], IAX_ENCRYPTED)) {
+       if (ast_test_flag(iaxs[fr->callno], IAX_ENCRYPTED) && !decrypted) {
                if (decrypt_frame(fr->callno, fh, &f, &res)) {
                        ast_log(LOG_NOTICE, "Packet Decrypt Failed!\n");
                        ast_mutex_unlock(&iaxsl[fr->callno]);
                        return 1;
-               }
+       }
+               decrypted = 1;
+       }
 #ifdef DEBUG_SUPPORT
-               else if (iaxdebug)
-                       iax_showframe(NULL, fh, 3, &sin, res - sizeof(*fh));
-#endif
+       if (decrypted && iaxdebug) {
+               iax_showframe(NULL, fh, 3, &sin, res - sizeof(*fh));
        }
+#endif
 
        /* count this frame */
        iaxs[fr->callno]->frames_received++;