diff options
Diffstat (limited to 'source3/libsmb')
-rw-r--r-- | source3/libsmb/cliconnect.c | 15 | ||||
-rw-r--r-- | source3/libsmb/nmblib.c | 86 |
2 files changed, 68 insertions, 33 deletions
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index f76f17c1bd..1e11e158f7 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -2230,6 +2230,7 @@ bool cli_session_request(struct cli_state *cli, { char *p; int len = 4; + int namelen = 0; char *tmp; /* 445 doesn't have session request */ @@ -2248,8 +2249,11 @@ bool cli_session_request(struct cli_state *cli, } p = cli->outbuf+len; - memcpy(p, tmp, name_len(tmp)); - len += name_len(tmp); + namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp)); + if (namelen > 0) { + memcpy(p, tmp, namelen); + len += namelen; + } TALLOC_FREE(tmp); /* and my name */ @@ -2261,8 +2265,11 @@ bool cli_session_request(struct cli_state *cli, } p = cli->outbuf+len; - memcpy(p, tmp, name_len(tmp)); - len += name_len(tmp); + namelen = name_len((unsigned char *)tmp, talloc_get_size(tmp)); + if (namelen > 0) { + memcpy(p, tmp, namelen); + len += namelen; + } TALLOC_FREE(tmp); /* send a session request (RFC 1002) */ diff --git a/source3/libsmb/nmblib.c b/source3/libsmb/nmblib.c index 150e1f6af9..1c95d0e99f 100644 --- a/source3/libsmb/nmblib.c +++ b/source3/libsmb/nmblib.c @@ -1241,21 +1241,33 @@ void sort_query_replies(char *data, int n, struct in_addr ip) /**************************************************************************** Interpret the weird netbios "name" into a unix fstring. Return the name type. + Returns -1 on error. ****************************************************************************/ -static int name_interpret(char *in, fstring name) +static int name_interpret(unsigned char *buf, size_t buf_len, + unsigned char *in, fstring name) { + unsigned char *end_ptr = buf + buf_len; int ret; - int len = (*in++) / 2; + unsigned int len; fstring out_string; - char *out = out_string; + unsigned char *out = (unsigned char *)out_string; *out=0; - if (len > 30 || len<1) - return(0); + if (in >= end_ptr) { + return -1; + } + len = (*in++) / 2; + + if (len<1) { + return -1; + } while (len--) { + if (&in[1] >= end_ptr) { + return -1; + } if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') { *out = 0; return(0); @@ -1263,21 +1275,13 @@ static int name_interpret(char *in, fstring name) *out = ((in[0]-'A')<<4) + (in[1]-'A'); in += 2; out++; + if (PTR_DIFF(out,out_string) >= sizeof(fstring)) { + return -1; + } } ret = out[-1]; out[-1] = 0; -#ifdef NETBIOS_SCOPE - /* Handle any scope names */ - while(*in) { - *out++ = '.'; /* Scope names are separated by periods */ - len = *(unsigned char *)in++; - StrnCpy(out, in, len); - out += len; - *out=0; - in += len; - } -#endif pull_ascii_fstring(name, out_string); return(ret); @@ -1356,12 +1360,25 @@ char *name_mangle(TALLOC_CTX *mem_ctx, char *In, char name_type) Find a pointer to a netbios name. ****************************************************************************/ -static char *name_ptr(char *buf,int ofs) +static unsigned char *name_ptr(unsigned char *buf, size_t buf_len, unsigned int ofs) { - unsigned char c = *(unsigned char *)(buf+ofs); + unsigned char c = 0; + + if (ofs > buf_len || buf_len < 1) { + return NULL; + } + c = *(unsigned char *)(buf+ofs); if ((c & 0xC0) == 0xC0) { - uint16 l = RSVAL(buf, ofs) & 0x3FFF; + uint16 l = 0; + + if (ofs > buf_len - 1) { + return NULL; + } + l = RSVAL(buf, ofs) & 0x3FFF; + if (l > buf_len) { + return NULL; + } DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l)); return(buf + l); } else { @@ -1371,37 +1388,48 @@ static char *name_ptr(char *buf,int ofs) /**************************************************************************** Extract a netbios name from a buf (into a unix string) return name type. + Returns -1 on error. ****************************************************************************/ -int name_extract(char *buf,int ofs, fstring name) +int name_extract(unsigned char *buf, size_t buf_len, unsigned int ofs, fstring name) { - char *p = name_ptr(buf,ofs); - int d = PTR_DIFF(p,buf+ofs); + unsigned char *p = name_ptr(buf,buf_len,ofs); name[0] = '\0'; - if (d < -50 || d > 50) - return(0); - return(name_interpret(p,name)); + if (p == NULL) { + return -1; + } + return(name_interpret(buf,buf_len,p,name)); } /**************************************************************************** Return the total storage length of a mangled name. + Returns -1 on error. ****************************************************************************/ -int name_len(char *s1) +int name_len(unsigned char *s1, size_t buf_len) { /* NOTE: this argument _must_ be unsigned */ unsigned char *s = (unsigned char *)s1; - int len; + int len = 0; + if (buf_len < 1) { + return -1; + } /* If the two high bits of the byte are set, return 2. */ - if (0xC0 == (*s & 0xC0)) + if (0xC0 == (*s & 0xC0)) { + if (buf_len < 2) { + return -1; + } return(2); + } /* Add up the length bytes. */ for (len = 1; (*s); s += (*s) + 1) { len += *s + 1; - SMB_ASSERT(len < 80); + if (len > buf_len) { + return -1; + } } return(len); |