Add in bufflen limit when storing NetBIOS names. Remove safe_strcpy.
[abartlet/samba.git/.git] / source3 / libsmb / nmblib.c
index dbf996ee5e731977dc17d8ad6d8438f3b306e93e..39243a04f35524ffc4e628cd503ea87cf2a37727 100644 (file)
@@ -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;