Commit message: seas: safety check for target buffer size before copying message in encode_msg()

- avoid buffer overflow for large SIP messages
- reported by Stelios Tsampas
CVE: CVE-2016-2385
CWE: CWE-119
Vulnerability description: Heap-based buffer overflow in the encode_msg function in encode_msg.c in the SEAS module in Kamailio (formerly OpenSER and SER) before 4.3.5 allows remote attackers to cause a denial of service (memory corruption and process crash) or possibly execute arbitrary code via a large SIP packet.

Project: kamailio
File: encode_msg.c

int decode_msg(struct sip_msg *msg,char *code, unsigned int len)
{
   unsigned short int h;
   char *myerror=NULL;

   memcpy(&h,&code[2],2);
   h=ntohs(h);
   /*TODO use shorcuts in meta-info header.*/

   msg->buf=&code[h];
   memcpy(&h,&code[4],2);
   h=ntohs(h);
   msg->len=h;
   if(parse_headers(msg,HDR_EOH_F,0)<0){
      myerror="in parse_headers";
      goto error;
   }
error:
   LM_ERR("(%s)\n",myerror);
   return -1;
}

Project: kamailio
File: encode_msg.c

int dump_msg_test(char *code,FILE* fd,char header,char segregationLevel)
{
   unsigned short int i,j,l,m,msglen;
   int k;
   char r,*msg;
   unsigned char *payload;
   payload=(unsigned char*)code;
   memcpy(&i,code,2);/*the CODE of the request/response*/
   memcpy(&j,&code[MSG_START_IDX],2);/*where the MSG starts*/
   memcpy(&msglen,&code[MSG_LEN_IDX],2);/*how long the MSG is*/
   i=ntohs(i);
   j=ntohs(j);
   msglen=ntohs(msglen);
   if(header==0){
      fwrite(code,1,j+msglen,fd);
      fwrite(&theSignal,1,4,fd);
      return 0;
   }
   msg=(char*)&payload[j];
   r=(i<100)?1:0;
   if(r){
      if(segregationLevel & ALSO_RURI){
	 if(!(segregationLevel & JUNIT)){ 
	    
	    k=htonl(payload[REQUEST_URI_IDX+1]+payload[REQUEST_URI_IDX+2]);
	    fwrite(&k,1,4,fd);
	    fwrite(msg,1,ntohl(k),fd);
	    k=htonl((long)payload[REQUEST_URI_IDX]);
	    fwrite(&k,1,4,fd);
	    fwrite(&payload[REQUEST_URI_IDX+1],1,payload[REQUEST_URI_IDX],fd);
	    fwrite(&theSignal,1,4,fd);
	 }else
	    print_uri_junit_tests(msg,payload[REQUEST_URI_IDX+1]+payload[REQUEST_URI_IDX+2]
		  ,&payload[REQUEST_URI_IDX+1],payload[REQUEST_URI_IDX],fd,1,"");
      }
      i=REQUEST_URI_IDX+1+payload[REQUEST_URI_IDX];
   }else{
      i=REQUEST_URI_IDX;
   }
   j=payload[i];
   i++;
   for(k=i;k<i+(j*3);k+=3){
      memcpy(&l,&payload[k+1],2);
      memcpy(&m,&payload[k+4],2);
      l=ntohs(l);
      m=ntohs(m);
      if(header==(char)payload[k] ||
	    (header=='U' &&
	     (payload[k]=='f' ||
	      payload[k]=='t' ||
	      payload[k]=='m' ||
	      payload[k]=='o' ||
	      payload[k]=='p')))
	 dump_headers_test(msg,msglen,&payload[i+(j*3)+l+3],m-l,payload[k],fd,segregationLevel);
   }
   return 1;
}

Project: kamailio
File: encode_msg.c

int print_encoded_msg(FILE* fd,char *code,char *prefix)
{
   unsigned short int i,j,k,l,m,msglen;
   char r,*msg;
   unsigned char *payload;
   
   payload=(unsigned char*)code;
   memcpy(&i,code,2);
   memcpy(&j,&code[MSG_START_IDX],2);
   memcpy(&msglen,&code[MSG_LEN_IDX],2);
   i=ntohs(i);
   j=ntohs(j);
   msglen=ntohs(msglen);
   for(k=0;k<j;k++)
      fprintf(fd,"%s%d%s",k==0?"ENCODED-MSG:[":":",payload[k],k==j-1?"]\n":"");
   msg=(char*)&payload[j];
   fprintf(fd,"MESSAGE:\n[%.*s]\n",msglen,msg);
   r=(i<100)?1:0;
   if(r){
      fprintf(fd,"%sREQUEST CODE=%d==%.*s,URI=%.*s,VERSION=%*.s\n",prefix,i,
	    payload[METHOD_CODE_IDX+1],&msg[payload[METHOD_CODE_IDX]],
	    payload[URI_REASON_IDX+1],&msg[payload[URI_REASON_IDX]],
	    payload[VERSION_IDX+1],&msg[payload[VERSION_IDX]]);
      print_encoded_uri(fd,&payload[REQUEST_URI_IDX+1],payload[REQUEST_URI_IDX],msg,50,strcat(prefix,"  "));
      prefix[strlen(prefix)-2]=0;
      i=REQUEST_URI_IDX+1+payload[REQUEST_URI_IDX];
   }else{
      fprintf(fd,"%sRESPONSE CODE=%d==%.*s,REASON=%.*s,VERSION=%.*s\n",prefix,i,
	    payload[METHOD_CODE_IDX+1],&msg[payload[METHOD_CODE_IDX]],
	    payload[URI_REASON_IDX+1],&msg[payload[URI_REASON_IDX]],
	    payload[VERSION_IDX+1],&msg[payload[VERSION_IDX]]);
      i=REQUEST_URI_IDX;
   }
   k=((payload[CONTENT_IDX]<<8)|payload[CONTENT_IDX+1]);
   j=msglen-k;
   fprintf(fd,"%sMESSAGE CONTENT:%.*s\n",prefix,j,&msg[k]);
   j=payload[i];
   fprintf(fd,"%sHEADERS PRESENT(%d):",prefix,j);
   i++;
   for(k=i;k<i+(j*3);k+=3)
      fprintf(fd,"%c%d%c",k==i?'[':',',payload[k],k==(i+3*j-3)?']':' ');
   fprintf(fd,"\n");
   for(k=i;k<i+(j*3);k+=3){
      memcpy(&l,&payload[k+1],2);
      memcpy(&m,&payload[k+4],2);
      l=ntohs(l);
      m=ntohs(m);
      print_encoded_header(fd,msg,msglen,&payload[l],m-l,payload[k],prefix);
   }
   return 1;
}

Project: kamailio
File: encode_msg.c

int print_msg_junit_test(char *code,FILE* fd,char header,char segregationLevel)
{
   unsigned short int i,j,l,m,msglen;
   int k;
   char r,*msg;
   unsigned char *payload;
   payload=(unsigned char*)code;
   memcpy(&i,code,2);/*the CODE of the request/response*/
   memcpy(&j,&code[MSG_START_IDX],2);/*where the MSG starts*/
   memcpy(&msglen,&code[MSG_LEN_IDX],2);/*how long the MSG is*/
   i=ntohs(i);
   j=ntohs(j);
   msglen=ntohs(msglen);
   if(header==0){
      fwrite(code,1,j+msglen,fd);
      fwrite(&theSignal,1,4,fd);
      return 0;
   }
   msg=(char*)&payload[j];
   r=(i<100)?1:0;
   if(r){
      if(segregationLevel & ALSO_RURI){
	 k=htonl(50);
	 fwrite(&k,1,4,fd);
	 fwrite(msg,1,50,fd);
	 k=htonl((long)payload[REQUEST_URI_IDX]);
	 fwrite(&k,1,4,fd);
	 fwrite(&payload[REQUEST_URI_IDX+1],1,payload[REQUEST_URI_IDX],fd);
	 fwrite(&theSignal,1,4,fd);
      }
      i=REQUEST_URI_IDX+1+payload[REQUEST_URI_IDX];
   }else{
      i=REQUEST_URI_IDX;
   }
   j=payload[i];
   i++;
   for(k=i;k<i+(j*3);k+=3){
      memcpy(&l,&payload[k+1],2);
      memcpy(&m,&payload[k+4],2);
      l=ntohs(l);
      m=ntohs(m);
      if(header==(char)payload[k] ||
	    (header=='U' &&
	     (payload[k]=='f' ||
	      payload[k]=='t' ||
	      payload[k]=='m' ||
	      payload[k]=='o' ||
	      payload[k]=='p')))
	 dump_headers_test(msg,msglen,&payload[i+(j*3)+l+3],m-l,payload[k],fd,segregationLevel);
   }
   return 1;
}