Merged revisions 32373 via svnmerge from
authorKevin P. Fleming <kpfleming@digium.com>
Mon, 5 Jun 2006 20:10:06 +0000 (20:10 +0000)
committerKevin P. Fleming <kpfleming@digium.com>
Mon, 5 Jun 2006 20:10:06 +0000 (20:10 +0000)
https://origsvn.digium.com/svn/asterisk/branches/1.2

........
r32373 | kpfleming | 2006-06-05 14:53:16 -0500 (Mon, 05 Jun 2006) | 2 lines

ensure that the received number of bytes is included in all IAX2 incoming frame analysis checks (fixes a known vulnerability)

........

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

channels/chan_iax2.c

index 4c00a9b..7581db1 100644 (file)
@@ -6314,27 +6314,28 @@ static int socket_process(struct iax2_thread *thread)
        fd = thread->iofd;
        memcpy(&sin, &thread->iosin, sizeof(sin));
 
-       if (res < sizeof(struct ast_iax2_mini_hdr)) {
-               ast_log(LOG_WARNING, "midget packet received (%d of %d min)\n", res, (int)sizeof(struct ast_iax2_mini_hdr));
+       if (res < sizeof(*mh)) {
+               ast_log(LOG_WARNING, "midget packet received (%d of %zd min)\n", res, sizeof(*mh));
                return 1;
        }
-       if ((vh->zeros == 0) && (ntohs(vh->callno) & 0x8000)) {
+       if ((res >= sizeof(*vh)) && ((vh->zeros == 0) && (ntohs(vh->callno) & 0x8000))) {
                /* This is a video frame, get call number */
                fr->callno = find_callno(ntohs(vh->callno) & ~0x8000, dcallno, &sin, new, 1, fd);
                minivid = 1;
-       } else if (meta->zeros == 0) {
+       } else if ((res >= sizeof(*meta)) && (meta->zeros == 0) && !(ntohs(meta->metacmd) & 0x8000)) {
                unsigned char metatype;
                /* This is a meta header */
                switch(meta->metacmd) {
                case IAX_META_TRUNK:
-                       if (res < sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr)) {
-                               ast_log(LOG_WARNING, "midget meta trunk packet received (%d of %d min)\n", res, (int)sizeof(struct ast_iax2_mini_hdr));
+                       if (res < (sizeof(*meta) + sizeof(*mth))) {
+                               ast_log(LOG_WARNING, "midget meta trunk packet received (%d of %zd min)\n", res,
+                                       sizeof(*meta) + sizeof(*mth));
                                return 1;
                        }
                        mth = (struct ast_iax2_meta_trunk_hdr *)(meta->data);
                        ts = ntohl(mth->ts);
                        metatype = meta->cmddata;
-                       res -= (sizeof(struct ast_iax2_meta_hdr) + sizeof(struct ast_iax2_meta_trunk_hdr));
+                       res -= (sizeof(*meta) + sizeof(*mth));
                        ptr = mth->data;
                        tpeer = find_tpeer(&sin, fd);
                        if (!tpeer) {
@@ -6346,21 +6347,21 @@ static int socket_process(struct iax2_thread *thread)
                                tpeer->rxtrunktime = tpeer->trunkact;
                        rxtrunktime = tpeer->rxtrunktime;
                        ast_mutex_unlock(&tpeer->lock);
-                       while(res >= sizeof(struct ast_iax2_meta_trunk_entry)) {
+                       while(res >= sizeof(*mte)) {
                                /* Process channels */
                                unsigned short callno, trunked_ts, len;
 
-                               if(metatype == IAX_META_TRUNK_MINI) {
+                               if (metatype == IAX_META_TRUNK_MINI) {
                                        mtm = (struct ast_iax2_meta_trunk_mini *)ptr;
-                                       ptr += sizeof(struct ast_iax2_meta_trunk_mini);
-                                       res -= sizeof(struct ast_iax2_meta_trunk_mini);
+                                       ptr += sizeof(*mtm);
+                                       res -= sizeof(*mtm);
                                        len = ntohs(mtm->len);
                                        callno = ntohs(mtm->mini.callno);
                                        trunked_ts = ntohs(mtm->mini.ts);
-                               } else if ( metatype == IAX_META_TRUNK_SUPERMINI ) {
+                               } else if (metatype == IAX_META_TRUNK_SUPERMINI) {
                                        mte = (struct ast_iax2_meta_trunk_entry *)ptr;
-                                       ptr += sizeof(struct ast_iax2_meta_trunk_entry);
-                                       res -= sizeof(struct ast_iax2_meta_trunk_entry);
+                                       ptr += sizeof(*mte);
+                                       res -= sizeof(*mte);
                                        len = ntohs(mte->len);
                                        callno = ntohs(mte->callno);
                                        trunked_ts = 0;
@@ -6443,11 +6444,21 @@ static int socket_process(struct iax2_thread *thread)
                }
                return 1;
        }
+
+       /* if we got here and ->zeros contains zeros, this cannot be a valid
+          miniframe or full frame but it wasn't a valid video frame or meta
+          frame either, so we reject it
+       */
+       if (vh->zeros == 0) {
+               ast_log(LOG_WARNING, "Rejecting packet from '%s.%d' that is flagged as a video or meta frame but is not properly formatted\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port));
+               return 1;
+       }
+
 #ifdef DEBUG_SUPPORT
-       if (iaxdebug)
-               iax_showframe(NULL, fh, 1, &sin, res - sizeof(struct ast_iax2_full_hdr));
+       if (iaxdebug && (res >= sizeof(*fh)))
+               iax_showframe(NULL, fh, 1, &sin, res - sizeof(*fh));
 #endif
-       if (ntohs(mh->callno) & IAX_FLAG_FULL) {
+       if ((res >= sizeof(*fh)) && ntohs(mh->callno) & IAX_FLAG_FULL) {
                /* Get the destination call number */
                dcallno = ntohs(fh->dcallno) & ~IAX_FLAG_RETRANS;
                /* Retrieve the type and subclass */
@@ -6498,7 +6509,7 @@ static int socket_process(struct iax2_thread *thread)
                }
 #ifdef DEBUG_SUPPORT
                else if (iaxdebug)
-                       iax_showframe(NULL, fh, 3, &sin, res - sizeof(struct ast_iax2_full_hdr));
+                       iax_showframe(NULL, fh, 3, &sin, res - sizeof(*fh));
 #endif
        }
 
@@ -6583,12 +6594,12 @@ static int socket_process(struct iax2_thread *thread)
                                iaxs[fr->callno]->iseqno++;
                }
                /* A full frame */
-               if (res < sizeof(struct ast_iax2_full_hdr)) {
-                       ast_log(LOG_WARNING, "midget packet received (%d of %d min)\n", res, (int)sizeof(struct ast_iax2_full_hdr));
+               if (res < sizeof(*fh)) {
+                       ast_log(LOG_WARNING, "midget packet received (%d of %zd min)\n", res, sizeof(*fh));
                        ast_mutex_unlock(&iaxsl[fr->callno]);
                        return 1;
                }
-               f.datalen = res - sizeof(struct ast_iax2_full_hdr);
+               f.datalen = res - sizeof(*fh);
 
                /* Handle implicit ACKing unless this is an INVAL, and only if this is 
                   from the real peer, not the transfer peer */
@@ -6646,14 +6657,14 @@ static int socket_process(struct iax2_thread *thread)
 
                if (f.datalen) {
                        if (f.frametype == AST_FRAME_IAX) {
-                               if (iax_parse_ies(&ies, thread->buf + sizeof(struct ast_iax2_full_hdr), f.datalen)) {
+                               if (iax_parse_ies(&ies, thread->buf + sizeof(*fh), f.datalen)) {
                                        ast_log(LOG_WARNING, "Undecodable frame received from '%s'\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr));
                                        ast_mutex_unlock(&iaxsl[fr->callno]);
                                        return 1;
                                }
                                f.data = NULL;
                        } else
-                               f.data = thread->buf + sizeof(struct ast_iax2_full_hdr);
+                               f.data = thread->buf + sizeof(*fh);
                } else {
                        if (f.frametype == AST_FRAME_IAX)
                                f.data = NULL;
@@ -7557,9 +7568,9 @@ retryowner2:
                        ast_mutex_unlock(&iaxsl[fr->callno]);
                        return 1;
                }
-               f.datalen = res - sizeof(struct ast_iax2_video_hdr);
+               f.datalen = res - sizeof(*vh);
                if (f.datalen)
-                       f.data = thread->buf + sizeof(struct ast_iax2_video_hdr);
+                       f.data = thread->buf + sizeof(*vh);
                else
                        f.data = NULL;
 #ifdef IAXTESTS
@@ -7586,7 +7597,7 @@ retryowner2:
                        return 1;
                }
                if (f.datalen)
-                       f.data = thread->buf + sizeof(struct ast_iax2_mini_hdr);
+                       f.data = thread->buf + sizeof(*mh);
                else
                        f.data = NULL;
 #ifdef IAXTESTS