Simplify buffer handling in dundi-parser.c. This also makes the code a bit

safer by removing various assumptions about sizes. (No vulnerabilities, though)

(closes issue #10977)
Reported by: dimas
Patches: 
      dundiparser.patch uploaded by dimas (license 88)


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@85558 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Russell Bryant
2007-10-15 15:55:23 +00:00
parent 3f2e8db598
commit be54dc15e5

View File

@@ -34,6 +34,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stddef.h>
#include "asterisk/frame.h" #include "asterisk/frame.h"
#include "asterisk/utils.h" #include "asterisk/utils.h"
@@ -126,18 +127,15 @@ int dundi_eid_cmp(dundi_eid *eid1, dundi_eid *eid2)
static void dump_string(char *output, int maxlen, void *value, int len) static void dump_string(char *output, int maxlen, void *value, int len)
{ {
maxlen--; if (maxlen > len + 1)
if (maxlen > len) maxlen = len + 1;
maxlen = len;
strncpy(output, value, maxlen); snprintf(output, maxlen, "%s", (char *) value);
output[maxlen] = '\0';
} }
static void dump_cbypass(char *output, int maxlen, void *value, int len) static void dump_cbypass(char *output, int maxlen, void *value, int len)
{ {
maxlen--; snprintf(output, maxlen, "Bypass Caches");
strncpy(output, "Bypass Caches", maxlen);
output[maxlen] = '\0';
} }
static void dump_eid(char *output, int maxlen, void *value, int len) static void dump_eid(char *output, int maxlen, void *value, int len)
@@ -170,20 +168,30 @@ char *dundi_hint2str(char *buf, int bufsiz, int flags)
static void dump_hint(char *output, int maxlen, void *value, int len) static void dump_hint(char *output, int maxlen, void *value, int len)
{ {
unsigned short flags;
char tmp[512];
char tmp2[256]; char tmp2[256];
if (len < 2) { char tmp3[256];
strncpy(output, "<invalid contents>", maxlen); int datalen;
struct dundi_hint *hint;
if (len < sizeof(*hint)) {
snprintf(output, maxlen, "<invalid contents>");
return; return;
} }
memcpy(&flags, value, sizeof(flags));
flags = ntohs(flags); hint = (struct dundi_hint *) value;;
memset(tmp, 0, sizeof(tmp));
dundi_hint2str(tmp2, sizeof(tmp2), flags); datalen = len - offsetof(struct dundi_hint, data);
snprintf(tmp, sizeof(tmp), "[%s] ", tmp2); if (datalen > sizeof(tmp3) - 1)
memcpy(tmp + strlen(tmp), value + 2, len - 2); datalen = sizeof(tmp3) - 1;
strncpy(output, tmp, maxlen - 1);
memcpy(tmp3, hint->data, datalen);
tmp3[datalen] = '\0';
dundi_hint2str(tmp2, sizeof(tmp2), ntohs(hint->flags));
if (ast_strlen_zero(tmp3))
snprintf(output, maxlen, "[%s]", tmp2);
else
snprintf(output, maxlen, "[%s] %s", tmp2, tmp3);
} }
static void dump_cause(char *output, int maxlen, void *value, int len) static void dump_cause(char *output, int maxlen, void *value, int len)
@@ -194,34 +202,37 @@ static void dump_cause(char *output, int maxlen, void *value, int len)
"DYNAMIC", "DYNAMIC",
"NOAUTH" , "NOAUTH" ,
}; };
char tmp[256];
char tmp2[256]; char tmp2[256];
int mlen; struct dundi_cause *cause;
unsigned char cause; int datalen;
if (len < 1) { int causecode;
strncpy(output, "<invalid contents>", maxlen);
if (len < sizeof(*cause)) {
snprintf(output, maxlen, "<invalid contents>");
return; return;
} }
cause = *((unsigned char *)value);
memset(tmp2, 0, sizeof(tmp2)); cause = (struct dundi_cause*) value;
mlen = len - 1; causecode = cause->causecode;
if (mlen > 255)
mlen = 255; datalen = len - offsetof(struct dundi_cause, desc);
memcpy(tmp2, value + 1, mlen); if (datalen > sizeof(tmp2) - 1)
if (cause < sizeof(causes) / sizeof(causes[0])) { datalen = sizeof(tmp2) - 1;
if (len > 1)
snprintf(tmp, sizeof(tmp), "%s: %s", causes[cause], tmp2); memcpy(tmp2, cause->desc, datalen);
tmp2[datalen] = '\0';
if (causecode < sizeof(causes) / sizeof(causes[0])) {
if (ast_strlen_zero(tmp2))
snprintf(output, maxlen, "%s", causes[causecode]);
else else
snprintf(tmp, sizeof(tmp), "%s", causes[cause]); snprintf(output, maxlen, "%s: %s", causes[causecode], tmp2);
} else { } else {
if (len > 1) if (ast_strlen_zero(tmp2))
snprintf(tmp, sizeof(tmp), "%d: %s", cause, tmp2); snprintf(output, maxlen, "%d", causecode);
else else
snprintf(tmp, sizeof(tmp), "%d", cause); snprintf(output, maxlen, "%d: %s", causecode, tmp2);
} }
strncpy(output,tmp, maxlen);
output[maxlen] = '\0';
} }
static void dump_int(char *output, int maxlen, void *value, int len) static void dump_int(char *output, int maxlen, void *value, int len)
@@ -315,17 +326,28 @@ static void dump_answer(char *output, int maxlen, void *value, int len)
char flags[40]; char flags[40];
char eid_str[40]; char eid_str[40];
char tmp[512]=""; char tmp[512]="";
if (len >= 10) { int datalen;
answer = (struct dundi_answer *)(value);
memcpy(tmp, answer->data, (len >= 500) ? 500 : len - 10); if (len < sizeof(*answer)) {
dundi_eid_to_str(eid_str, sizeof(eid_str), &answer->eid); snprintf(output, maxlen, "Invalid Answer");
snprintf(output, maxlen, "[%s] %d <%s/%s> from [%s]", return;
dundi_flags2str(flags, sizeof(flags), ntohs(answer->flags)), }
ntohs(answer->weight),
proto2str(answer->protocol, proto, sizeof(proto)), answer = (struct dundi_answer *)(value);
tmp, eid_str);
} else datalen = len - offsetof(struct dundi_answer, data);
strncpy(output, "Invalid Answer", maxlen - 1); if (datalen > sizeof(tmp) - 1)
datalen = sizeof(tmp) - 1;
memcpy(tmp, answer->data, datalen);
tmp[datalen] = '\0';
dundi_eid_to_str(eid_str, sizeof(eid_str), &answer->eid);
snprintf(output, maxlen, "[%s] %d <%s/%s> from [%s]",
dundi_flags2str(flags, sizeof(flags), ntohs(answer->flags)),
ntohs(answer->weight),
proto2str(answer->protocol, proto, sizeof(proto)),
tmp, eid_str);
} }
static void dump_encrypted(char *output, int maxlen, void *value, int len) static void dump_encrypted(char *output, int maxlen, void *value, int len)