diff options
author | Jeremy Allison <jra@samba.org> | 2010-09-26 02:59:32 -0700 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2010-09-26 03:01:03 -0700 |
commit | 03841f9e44950811907ea83e8caedac2a80bce06 (patch) | |
tree | 39d6d5112f636b8640d5af3622fefdd376058e15 /source3/smbd/reply.c | |
parent | 80f8419ef25baa7b2f6d78469084a2ee80296fa1 (diff) | |
download | samba-03841f9e44950811907ea83e8caedac2a80bce06.tar.gz samba-03841f9e44950811907ea83e8caedac2a80bce06.tar.xz samba-03841f9e44950811907ea83e8caedac2a80bce06.zip |
Fix bug #7698 - Assert causes smbd to panic on invalid NetBIOS session request.
Found by the CodeNomicon test suites at the SNIA plugfest.
http://www.codenomicon.com/
If an invalid NetBIOS session request is received the code in name_len() in
libsmb/nmblib.c can hit an assert.
Re-write name_len() and name_extract() to use "buf/len" pairs and
always limit reads.
Jeremy.
Diffstat (limited to 'source3/smbd/reply.c')
-rw-r--r-- | source3/smbd/reply.c | 41 |
1 files changed, 30 insertions, 11 deletions
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 43ca479e281..abff317d523 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -483,16 +483,13 @@ static bool netbios_session_retarget(struct smbd_server_connection *sconn, } /**************************************************************************** - Reply to a (netbios-level) special message. + Reply to a (netbios-level) special message. ****************************************************************************/ -void reply_special(struct smbd_server_connection *sconn, char *inbuf) +void reply_special(struct smbd_server_connection *sconn, char *inbuf, size_t inbuf_size) { int msg_type = CVAL(inbuf,0); int msg_flags = CVAL(inbuf,1); - fstring name1,name2; - char name_type1, name_type2; - /* * We only really use 4 bytes of the outbuf, but for the smb_setlen * calculation & friends (srv_send_smb uses that) we need the full smb @@ -500,14 +497,19 @@ void reply_special(struct smbd_server_connection *sconn, char *inbuf) */ char outbuf[smb_size]; - *name1 = *name2 = 0; - memset(outbuf, '\0', sizeof(outbuf)); smb_setlen(outbuf,0); switch (msg_type) { case 0x81: /* session request */ + { + /* inbuf_size is guarenteed to be at least 4. */ + fstring name1,name2; + int name_type1, name_type2; + int name_len1, name_len2; + + *name1 = *name2 = 0; if (sconn->nbt.got_session) { exit_server_cleanly("multiple session request not permitted"); @@ -515,13 +517,29 @@ void reply_special(struct smbd_server_connection *sconn, char *inbuf) SCVAL(outbuf,0,0x82); SCVAL(outbuf,3,0); - if (name_len(inbuf+4) > 50 || - name_len(inbuf+4 + name_len(inbuf + 4)) > 50) { + + /* inbuf_size is guaranteed to be at least 4. */ + name_len1 = name_len((unsigned char *)(inbuf+4),inbuf_size - 4); + if (name_len1 <= 0 || name_len1 > inbuf_size - 4) { + DEBUG(0,("Invalid name length in session request\n")); + return; + } + name_len2 = name_len((unsigned char *)(inbuf+4+name_len1),inbuf_size - 4 - name_len1); + if (name_len2 <= 0 || name_len2 > inbuf_size - 4 - name_len1) { DEBUG(0,("Invalid name length in session request\n")); return; } - name_type1 = name_extract(inbuf,4,name1); - name_type2 = name_extract(inbuf,4 + name_len(inbuf + 4),name2); + + name_type1 = name_extract((unsigned char *)inbuf, + inbuf_size,(unsigned int)4,name1); + name_type2 = name_extract((unsigned char *)inbuf, + inbuf_size,(unsigned int)(4 + name_len1),name2); + + if (name_type1 == -1 || name_type2 == -1) { + DEBUG(0,("Invalid name type in session request\n")); + return; + } + DEBUG(2,("netbios connect: name1=%s0x%x name2=%s0x%x\n", name1, name_type1, name2, name_type2)); @@ -564,6 +582,7 @@ void reply_special(struct smbd_server_connection *sconn, char *inbuf) sconn->nbt.got_session = true; break; + } case 0x89: /* session keepalive request (some old clients produce this?) */ |