[PATH] Possible buffer overflow gateway/gw/smsc/smsc_emi_x25.c

"Humberto Figuera" <[email protected]>
Newsgroups gmane.comp.mobile.kannel.devel
Message-ID <[email protected]>
Hi,

I've been using kannel since few months ago, looking the code found
possibles buffer overflow.

* fixed size local buffer : they are prime targets for buffer overflow attacks.
* sprintf : the format string could contain `%s' without precision
that could result in a buffer overflow.
* strcpy : if the argument 2 passed to this function copy more data
than can be handled, resulting in a buffer overflow.

I would since today follow looking all source tree and submit the patch.

I hope the list can appreciate it and it to be committed to CVS ;p

--- tmp/gateway/gw/smsc/smsc_emi_x25.c	2005-02-11 11:35:48.000000000 -0400
+++ gateway/gw/smsc/smsc_emi_x25.c	2006-05-10 19:38:00.000000000 -0400
@@ -137,11 +137,16 @@
 */
 static int emi_open_connection(SMSCenter *smsc)
 {
-    char tmpbuff[1024];
+    char *tmpbuff;
+
+    tmpbuff = gw_malloc(1024);
+    memset(tmpbuff, 0, 1024);

-    sprintf(tmpbuff, "/dev/%s", smsc->emi_serialdevice);
+    snprintf(tmpbuff, 1024 - 1, "/dev/%s", smsc->emi_serialdevice);
     smsc->emi_fd = at_dial(tmpbuff, smsc->emi_phonenum, "ATD", 30);

+    gw_free(tmpbuff);
+
     if (smsc->emi_fd <= 0)
         return -1;

@@ -170,7 +175,7 @@
     if (emi_open_connection(smsc) < 0)
         goto error;

-    sprintf(smsc->name, "EMI:%s:%s", smsc->emi_phonenum,
+    snprintf(smsc->name, 1024 - 1, "EMI:%s:%s", smsc->emi_phonenum,
             smsc->emi_username);
     return smsc;

@@ -224,20 +229,33 @@

 static int emi_open_session(SMSCenter *smsc)
 {
-    char message_whole  [1024];
-    char message_body   [1024];
-    char message_header [50];
-    char message_footer [10];
-    char my_buffer      [1024];
+    char *message_whole;
+    char *message_body;
+    char *message_header;
+    char *message_footer;
+    char *my_buffer;
     int length;

-    memset(message_whole,  0, sizeof(message_whole));
-    memset(message_body,   0, sizeof(message_body));
-    memset(message_header, 0, sizeof(message_header));
-    memset(message_footer, 0, sizeof(message_footer));
+    message_whole = gw_malloc(1024);
+    message_body = gw_malloc(1024);
+    message_header = gw_malloc(50);
+    message_footer = gw_malloc(10);
+    my_buffer = gw_malloc(1024);
+
+    memset(message_whole,  0, 1024);
+    memset(message_body,   0, 1024);
+    memset(message_header, 0, 50);
+    memset(message_footer, 0, 10);
+    memset(my_buffer, 0, 1024);

     if (emi_fill_ucp60_login(message_body, smsc->emi_username,
smsc->emi_password) < 0) {
         error(0, "emi_fill_ucp60_login failed");
+	gw_free(message_whole);
+	gw_free(message_body);
+	gw_free(message_header);
+	gw_free(message_footer);
+	gw_free(my_buffer);
+	
         return -1;
     }

@@ -246,21 +264,27 @@
     length += 2;   /* footer (fixed) */
     length += 2;   /* slashes between header, body, footer */

-    sprintf(message_header, "%02i/%05i/O/60",
+    snprintf(message_header, 50 - 1, "%02i/%05i/O/60",
             (smsc->emi_current_msg_number++ % 100), length);

     /* FOOTER */

-    sprintf(my_buffer, "%s/%s/", message_header, message_body);
+    snprintf(my_buffer, 1024 - 1, "%s/%s/", message_header, message_body);
     generate_checksum(my_buffer, message_footer);

-    sprintf(message_whole, "\x02%s/%s/%s\x03", message_header,
+    snprintf(message_whole, 1024 - 1, "\x02%s/%s/%s\x03", message_header,
             message_body, message_footer);

     debug("bb.sms.emi", 0, "final UCP60 msg: <%s>", message_whole);

     put_data(smsc, message_whole, strlen(message_whole), 0);

+    gw_free(message_whole);
+    gw_free(message_body);
+    gw_free(message_header);
+    gw_free(message_footer);
+    gw_free(my_buffer);
+
     if (!wait_for_ack(smsc, 60)) {
 	info(0, "emi_open_session: wait for ack failed!");
 	return -1;
@@ -471,7 +495,7 @@

 static int at_dial(char *device, char *phonenum, char *at_prefix,
time_t how_long)
 {
-    char tmpbuff[1024];
+    char *tmpbuff;
     int howmanyread = 0;
     int thistime = 0;
     int redial;
@@ -502,6 +526,9 @@
     tios.c_cflag |= (HUPCL | CREAD | CRTSCTS);
     tcsetattr(fd, TCSANOW, &tios);

+    tmpbuff = gw_malloc(1024);
+    memset(tmpbuff, 0, 1024);
+
     /* Dial using an AT command string. */
     for (redial = 1; redial; ) {
         info(0, "at_dial: dialing <%s> on <%s> for <%i> seconds",
@@ -510,9 +537,9 @@

         /* Send AT dial request. */
         howmanyread = 0;
-        sprintf(tmpbuff, "%s%s\r\n", at_prefix, phonenum);
+        snprintf(tmpbuff, 1024 - 1, "%s%s\r\n", at_prefix, phonenum);
         ret = write(fd, tmpbuff, strlen(tmpbuff));  /* errors... -mg */
-        memset(&tmpbuff, 0, sizeof(tmpbuff));
+        memset(tmpbuff, 0, 1024);

         /* Read the answer to the AT command and react accordingly. */
         for (; ; ) {
@@ -521,7 +548,7 @@
                 goto timeout;

             /* We don't need more space for dialout */
-            if (howmanyread >= (int) sizeof(tmpbuff))
+            if (howmanyread >= 1024)
                 goto error;

             /* We read 1 char a time so that we don't
@@ -580,15 +607,18 @@
     } /* End of dial loop. */

     debug("bb.sms.emi", 0, "at_dial: done with dialing");
+    gw_free(tmpbuff);
     return fd;

 timeout:
     error(0, "at_dial timed out");
+    gw_free(tmpbuff);
     close(fd);
     return -1;

 error:
     error(0, "at_dial failed");
+    gw_free(tmpbuff);
     close(fd);
     return -1;
 }
@@ -807,9 +837,15 @@
 */
 static int memorybuffer_has_rawmessage(SMSCenter *smsc, int type, char auth)
 {
-    char tmpbuff[1024], tmpbuff2[1024];
+    char *tmpbuff, *tmpbuff2;
     char *stx, *etx;

+    tmpbuff = gw_malloc(1024);
+    tmpbuff2 = gw_malloc(1024);
+
+    memset(tmpbuff, 0, 1024);
+    memset(tmpbuff2, 0, 1024);
+
     stx = memchr(smsc->buffer, '\2', smsc->buflen);
     etx = memchr(smsc->buffer, '\3', smsc->buflen);

@@ -817,15 +853,19 @@
         strncpy(tmpbuff, stx, etx - stx + 1);
         tmpbuff[etx - stx + 1] = '\0';
         if (auth)
-            sprintf(tmpbuff2, "/%c/%02i/", auth, type);
+            snprintf(tmpbuff2, 1024 - 1, "/%c/%02i/", auth, type);
         else
-            sprintf(tmpbuff2, "/%02i/", type);
+            snprintf(tmpbuff2, 1024 - 1, "/%02i/", type);

         if (strstr(tmpbuff, tmpbuff2) != NULL) {
             debug("bb.sms.emi", 0, "found message <%c/%02i>...msg
<%s>", auth, type, tmpbuff);
+	    gw_free(tmpbuff);
+	    gw_free(tmpbuff);
             return 1;
         }
     }
+    gw_free(tmpbuff);
+    gw_free(tmpbuff);
     return 0;

 }
@@ -880,13 +920,14 @@

     char emivars[128][1024];
     char *leftslash, *rightslash;
-    char isotext[2048];
+    char *isotext;
     int msgnbr;
     int tmpint;

     msgnbr = -1;

-    memset(isotext, 0, sizeof(isotext));
+    isotext = gw_malloc(2048);
+    memset(isotext, 0, 2048);

     strncpy(isotext, rawmessage, length);
     leftslash = isotext;
@@ -901,25 +942,25 @@
             break;

         *rightslash = '\0';
-        strcpy(emivars[tmpint], leftslash + 1);
+        strncpy(emivars[tmpint], leftslash + 1, sizeof(emivars[tmpint]) - 1);
         leftslash = rightslash;
     }

     if (strcmp(emivars[3], "01") == 0) {
         if (strcmp(emivars[7], "2") == 0) {
-            strcpy(isotext, emivars[8]);
+            strncpy(isotext, emivars[8], 2048 - 1);
         } else if (strcmp(emivars[7], "3") == 0) {
-            parse_emi_to_iso88591(emivars[8], isotext, sizeof(isotext),
+            parse_emi_to_iso88591(emivars[8], isotext, 2048,
                                   smsc->alt_charset);
         } else {
             error(0, "Unknown 01-type EMI SMS (%s)", emivars[7]);
             strcpy(isotext, "");
         }
     } else if (strcmp(emivars[3], "51") == 0) {
-        parse_emi_to_iso88591(emivars[24], isotext, sizeof(isotext),
+        parse_emi_to_iso88591(emivars[24], isotext, 2048,
                               smsc->alt_charset);
     } else if (strcmp(emivars[3], "52") == 0) {
-        parse_emi_to_iso88591(emivars[24], isotext, sizeof(isotext),
+        parse_emi_to_iso88591(emivars[24], isotext, 2048,
                               smsc->alt_charset);
     } else {
         error(0, "HEY WE SHOULD NOT BE HERE!! Type = %s", emivars[3]);
@@ -934,9 +975,11 @@
     (*msg)->sms.msgdata = octstr_create(isotext);
     (*msg)->sms.udhdata = NULL;

+    gw_free(isotext);
     return msgnbr;

 error:
+    gw_free(isotext);
     return -1;
 }

@@ -948,19 +991,25 @@
 {

     char emivars[128][1024];
-    char timestamp[2048], sender[2048], receiver[2048];
-    char emitext[2048], isotext[2048];
+    char *timestamp, *sender, *receiver;
+    char *emitext, *isotext;
     char *leftslash, *rightslash;
     int msgnbr;
     int tmpint;
     int is_backup = 0;

+    sender = gw_malloc(2048);
+    receiver = gw_malloc(2048);
+    emitext = gw_malloc(2048);
+    isotext = gw_malloc(2048);
+    timestamp = gw_malloc(2048);
+
     msgnbr = -1;
-    memset(&sender, 0, sizeof(sender));
-    memset(&receiver, 0, sizeof(receiver));
-    memset(&emitext, 0, sizeof(emitext));
-    memset(&isotext, 0, sizeof(isotext));
-    memset(&timestamp, 0, sizeof(timestamp));
+    memset(sender, 0, 2048);
+    memset(receiver, 0, 2048);
+    memset(emitext, 0, 2048);
+    memset(isotext, 0, 2048);
+    memset(timestamp, 0, 2048);

     strncpy(isotext, rawmessage, length);
     leftslash = isotext;
@@ -978,31 +1027,36 @@
             break;

         *rightslash = '\0';
-        strcpy(emivars[tmpint], leftslash + 1);
+        strncpy(emivars[tmpint], leftslash + 1, 1024 - 1);
         leftslash = rightslash;
     }

     /* BODY */
-    sprintf(isotext, "A//%s:%s", emivars[4], emivars[18]);
-    sprintf(isotext, "A//%s:", emivars[5]);
+    snprintf(isotext, 2048 - 1, "A//%s:%s", emivars[4], emivars[18]);
+    snprintf(isotext, 2048 - 1, "A//%s:", emivars[5]);
     is_backup = 0;

     /* HEADER */

     debug("bb.sms.emi", 0, "acknowledge: type = '%s'", emivars[3]);

-    sprintf(emitext, "%s/%05i/%s/%s", emivars[0], (int) strlen(isotext) + 17,
+    snprintf(emitext, 2048 - 1, "%s/%05i/%s/%s", emivars[0], (int)
strlen(isotext) + 17,
             "R", emivars[3]);

     smsc->emi_current_msg_number = atoi(emivars[0]) + 1;

     /* FOOTER */
-    sprintf(timestamp, "%s/%s/", emitext, isotext);
+    snprintf(timestamp, 2048 - 1, "%s/%s/", emitext, isotext);
     generate_checksum(timestamp, receiver);

-    sprintf(sender, "%c%s/%s/%s%c", 0x02, emitext, isotext, receiver, 0x03);
+    snprintf(sender, 2048 - 1, "%c%s/%s/%s%c", 0x02, emitext,
isotext, receiver, 0x03);
     put_data(smsc, sender, strlen(sender), is_backup);

+    gw_free(sender);
+    gw_free(receiver);
+    gw_free(emitext);
+    gw_free(isotext);
+    gw_free(timestamp);
     return msgnbr;

 }
@@ -1013,36 +1067,51 @@
 */
 static int parse_msg_to_rawmessage(SMSCenter *smsc, Msg *msg, char
*rawmessage, int rawmessage_length)
 {
-    char message_whole[10*1024];
-    char message_body[10*1024];
-    char message_header[1024];
-    char message_footer[1024];
-
-    char my_buffer[10*1024];
-    char my_buffer2[10*1024];
-    char msgtext[1024];
+    char *message_whole;
+    char *message_body;
+    char *message_header;
+    char *message_footer;
+
+    char *my_buffer;
+    char *my_buffer2;
+    char *msgtext;
     int length;
     char mt;
-    char mcl[20];
-    char snumbits[20];
-    char xser[1024];
+    char *mcl;
+    char *snumbits;
+    char *xser;
     int udh_len;

-    memset(&message_whole, 0, sizeof(message_whole));
-    memset(&message_body, 0, sizeof(message_body));
-    memset(&message_header, 0, sizeof(message_header));
-    memset(&message_footer, 0, sizeof(message_footer));
-    memset(&my_buffer, 0, sizeof(my_buffer));
-    memset(&my_buffer2, 0, sizeof(my_buffer2));
+    message_whole = gw_malloc(10 * 1024);
+    message_body = gw_malloc(10 * 1024);
+    message_header = gw_malloc(1024);
+    message_footer = gw_malloc(1024);
+    my_buffer = gw_malloc(10 * 1024);
+    my_buffer2 = gw_malloc(10 * 1024);
+    msgtext = gw_malloc(1024);
+    mcl = gw_malloc(20);
+    snumbits = gw_malloc(20);
+    xser = gw_malloc(1024);
+
+    memset(message_whole, 0, 10 * 1024);
+    memset(message_body, 0, 10 * 1024);
+    memset(message_header, 0, 1024);
+    memset(message_footer, 0, 1024);
+    memset(my_buffer, 0, 10 * 1024);
+    memset(my_buffer2, 0, 10 * 1024);
     mt = '3';
-    memset(&snumbits, 0, sizeof(snumbits));
-    memset(&xser, 0, sizeof(xser));
+    memset(msgtext, 0, 1024);
+    memset(mcl, 0, 20);
+    memset(snumbits, 0, 20);
+    memset(xser, 0, 1024);

     /* XXX parse_iso88591_to_emi shouldn't use NUL terminated
      * strings, but Octstr directly, or a char* and a length.
      */
     if (octstr_len(msg->sms.udhdata)) {
-        char xserbuf[258];
+        char *xserbuf;
+	xserbuf = gw_malloc(258);
+	memset(xserbuf, 0, 258);
         /* we need a properly formated UDH here, there first byte
contains his length
          * this will be formatted in the xser field of the EMI Protocol
          */
@@ -1051,6 +1120,7 @@
         xserbuf[1] = udh_len;
         octstr_get_many_chars(&xserbuf[2], msg->sms.udhdata, 0, udh_len);
         parse_binary_to_emi(xserbuf, xser, udh_len + 2);
+	gw_free(xserbuf);
     } else {
         udh_len = 0;
     }
@@ -1070,7 +1140,7 @@

         parse_binary_to_emi(msgtext, my_buffer2, octstr_len(msg->sms.msgdata));

-        sprintf(snumbits, "%04ld", octstr_len(msg->sms.msgdata)*8);
+        snprintf(snumbits, 20 - 1, "%04ld", octstr_len(msg->sms.msgdata)*8);
         mt = '4';
         strcpy(mcl, "1");
     }
@@ -1079,7 +1149,7 @@
      * Please someone encode it with fields_to_dcs
      */

-    sprintf(message_body,
+    snprintf(message_body, 10 * 1024 - 1,
             "%s/%s/%s/%s/%s//%s////////////%c/%s/%s////%s//////%s//",
             octstr_get_cstr(msg->sms.receiver),
             msg->sms.sender ? octstr_get_cstr(msg->sms.sender) : "",
@@ -1100,14 +1170,14 @@
     length += 2;  /* footer (fixed) */
     length += 2;  /* slashes between header, body, footer */

-    sprintf(message_header, "%02i/%05i/%s/%s",
(smsc->emi_current_msg_number++ % 100), length, "O", "51");
+    snprintf(message_header, 1024 - 1, "%02i/%05i/%s/%s",
(smsc->emi_current_msg_number++ % 100), length, "O", "51");

     /* FOOTER */

-    sprintf(my_buffer, "%s/%s/", message_header, message_body);
+    snprintf(my_buffer, 10 * 1024 - 1, "%s/%s/", message_header, message_body);
     generate_checksum(my_buffer, message_footer);

-    sprintf(message_whole, "%c%s/%s/%s%c", 0x02, message_header,
message_body, message_footer, 0x03);
+    snprintf(message_whole, 10 * 1024 - 1, "%c%s/%s/%s%c", 0x02,
message_header, message_body, message_footer, 0x03);

     strncpy(rawmessage, message_whole, rawmessage_length);

@@ -1117,6 +1187,17 @@
     }
     debug("bb.sms.emi", 0, "emi %d message %s",
           smsc->emi_current_msg_number, rawmessage);
+
+    gw_free(message_whole);
+    gw_free(message_body);
+    gw_free(message_header);
+    gw_free(message_footer);
+    gw_free(my_buffer);
+    gw_free(my_buffer2);
+    gw_free(msgtext);
+    gw_free(mcl);
+    gw_free(snumbits);
+    gw_free(xser);
     return strlen(rawmessage);
 }

@@ -1128,7 +1209,10 @@
 {
     int hmtg = 0;
     unsigned int mychar;
-    char tmpbuff[128];
+    char *tmpbuff;
+
+    tmpbuff = gw_malloc(128);
+    memset(tmpbuff, 0, 128);

     for (hmtg = 0; hmtg <= (int)strlen(from); hmtg += 2) {
         strncpy(tmpbuff, from + hmtg, 2);
@@ -1138,6 +1222,7 @@

     to[(hmtg / 2)-1] = '\0';

+    gw_free(tmpbuff);
     return 0;

 }
@@ -1148,22 +1233,25 @@
 static int parse_iso88591_to_emi(char *from, char *to,
         int length, int alt_charset)
 {
-    char buf[10];
+    char *buf;
     unsigned char tmpchar;
     char *ptr;

     if (!from || !to || length <= 0)
         return -1;

+    buf = gw_malloc(10);
+    memset(buf, 0, 10);
     *to = '\0';

     debug("bb.sms.emi", 0, "emi parsing <%s> to emi, length %d", from, length);

     for (ptr = from; length > 0; ptr++, length--) {
         tmpchar = char_iso_to_sms(*ptr, alt_charset);
-        sprintf(buf, "%02X", tmpchar);
+        snprintf(buf, 10 - 1, "%02X", tmpchar);
         strncat(to, buf, 2);
     }
+    gw_free(buf);
     return 0;
 }

@@ -1172,19 +1260,22 @@
 */
 static int parse_binary_to_emi(char *from, char *to, int length)
 {
-    char buf[10];
+    char *buf;
     char *ptr;

     if (!from || !to || length <= 0)
         return -1;

+    buf = gw_malloc(10);
+    memset(buf, 0, 10);
     *to = '\0';

     for (ptr = from; length > 0; ptr++, length--) {
-        sprintf(buf, "%02X", (unsigned char)*ptr);
+        snprintf(buf, 10 - 1, "%02X", (unsigned char)*ptr);
         strncat(to, buf, 2);
     }

+    gw_free(buf);
     return 0;
 }


--
Humberto Figuera - Using Linux 2.6.16
Usuario GNU/Linux 369709
Caracas - Venezuela
GPG Key Fingerprint = 5AAC DF0C 00F4 2834 28BA  37AD 3364 01D1 74CA 0603
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.