diff options
-rw-r--r-- | source3/libsmb/nmblib.c | 48 |
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; |