summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/libsmb/nmblib.c48
1 files changed, 32 insertions, 16 deletions
diff --git a/source3/libsmb/nmblib.c b/source3/libsmb/nmblib.c
index dbf996ee5e..39243a04f3 100644
--- a/source3/libsmb/nmblib.c
+++ b/source3/libsmb/nmblib.c
@@ -288,7 +288,7 @@ void put_name(char *dest, const char *name, int pad, unsigned int name_type)
If buf == NULL this is a length calculation.
******************************************************************/
-static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
+static int put_nmb_name(char *buf, size_t buflen, int offset,struct nmb_name *name)
{
int ret,m;
nstring buf1;
@@ -302,6 +302,9 @@ static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
}
if (buf) {
+ if (offset >= buflen) {
+ return 0;
+ }
buf[offset] = 0x20;
}
@@ -309,6 +312,9 @@ static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
for (m=0;m<MAX_NETBIOSNAME_LEN;m++) {
if (buf) {
+ if (offset+2+2*m >= buflen) {
+ return 0;
+ }
buf[offset+1+2*m] = 'A' + ((buf1[m]>>4)&0xF);
buf[offset+2+2*m] = 'A' + (buf1[m]&0xF);
}
@@ -316,20 +322,30 @@ static int put_nmb_name(char *buf,int offset,struct nmb_name *name)
offset += 33;
if (buf) {
+ if (offset >= buflen) {
+ return 0;
+ }
buf[offset] = 0;
}
if (name->scope[0]) {
/* XXXX this scope handling needs testing */
- ret += strlen(name->scope) + 1;
+ size_t scopenamelen = strlen(name->scope) + 1;
+ ret += scopenamelen;
if (buf) {
- safe_strcpy(&buf[offset+1],name->scope,
- sizeof(name->scope));
+ if (offset+1+scopenamelen >= buflen) {
+ return 0;
+ }
+ strlcpy(&buf[offset+1],name->scope,
+ buflen - (offset+1));
p = &buf[offset+1];
while ((p = strchr_m(p,'.'))) {
buf[offset] = PTR_DIFF(p,&buf[offset+1]);
offset += (buf[offset] + 1);
+ if (offset+1 >= buflen) {
+ return 0;
+ }
p = &buf[offset+1];
}
buf[offset] = strlen(&buf[offset+1]);
@@ -404,13 +420,13 @@ static bool parse_alloc_res_rec(char *inbuf,int *offset,int length,
If buf == NULL this is a length calculation.
******************************************************************/
-static int put_res_rec(char *buf,int offset,struct res_rec *recs,int count)
+static int put_res_rec(char *buf, size_t buflen, int offset,struct res_rec *recs,int count)
{
int ret=0;
int i;
for (i=0;i<count;i++) {
- int l = put_nmb_name(buf,offset,&recs[i].rr_name);
+ int l = put_nmb_name(buf,buflen,offset,&recs[i].rr_name);
offset += l;
ret += l;
if (buf) {
@@ -887,8 +903,8 @@ static int build_dgram(char *buf, size_t len, struct dgram_packet *dgram)
if (dgram->header.msg_type == 0x10 ||
dgram->header.msg_type == 0x11 ||
dgram->header.msg_type == 0x12) {
- offset += put_nmb_name((char *)ubuf,offset,&dgram->source_name);
- offset += put_nmb_name((char *)ubuf,offset,&dgram->dest_name);
+ offset += put_nmb_name((char *)ubuf,len,offset,&dgram->source_name);
+ offset += put_nmb_name((char *)ubuf,len,offset,&dgram->dest_name);
}
if (buf) {
@@ -979,13 +995,13 @@ static int build_nmb(char *buf, size_t len, struct nmb_packet *nmb)
/* XXXX this doesn't handle a qdcount of > 1 */
if (len) {
/* Length check. */
- int extra = put_nmb_name(NULL,offset,
+ int extra = put_nmb_name(NULL,0,offset,
&nmb->question.question_name);
if (offset + extra > len) {
return 0;
}
}
- offset += put_nmb_name((char *)ubuf,offset,
+ offset += put_nmb_name((char *)ubuf,len,offset,
&nmb->question.question_name);
if (buf) {
RSSVAL(ubuf,offset,nmb->question.question_type);
@@ -997,26 +1013,26 @@ static int build_nmb(char *buf, size_t len, struct nmb_packet *nmb)
if (nmb->header.ancount) {
if (len) {
/* Length check. */
- int extra = put_res_rec(NULL,offset,nmb->answers,
+ int extra = put_res_rec(NULL,0,offset,nmb->answers,
nmb->header.ancount);
if (offset + extra > len) {
return 0;
}
}
- offset += put_res_rec((char *)ubuf,offset,nmb->answers,
+ offset += put_res_rec((char *)ubuf,len,offset,nmb->answers,
nmb->header.ancount);
}
if (nmb->header.nscount) {
if (len) {
/* Length check. */
- int extra = put_res_rec(NULL,offset,nmb->nsrecs,
+ int extra = put_res_rec(NULL,0,offset,nmb->nsrecs,
nmb->header.nscount);
if (offset + extra > len) {
return 0;
}
}
- offset += put_res_rec((char *)ubuf,offset,nmb->nsrecs,
+ offset += put_res_rec((char *)ubuf,len,offset,nmb->nsrecs,
nmb->header.nscount);
}
@@ -1048,13 +1064,13 @@ static int build_nmb(char *buf, size_t len, struct nmb_packet *nmb)
} else if (nmb->header.arcount) {
if (len) {
/* Length check. */
- int extra = put_res_rec(NULL,offset,nmb->additional,
+ int extra = put_res_rec(NULL,0,offset,nmb->additional,
nmb->header.arcount);
if (offset + extra > len) {
return 0;
}
}
- offset += put_res_rec((char *)ubuf,offset,nmb->additional,
+ offset += put_res_rec((char *)ubuf,len,offset,nmb->additional,
nmb->header.arcount);
}
return offset;