diff -urBb --exclude-from=../../../samba-cvs/diff.excludes samba-3.0.5-orig/source/libsmb/nmblib.c samba-3.0.5/source/libsmb/nmblib.c --- samba-3.0.5-orig/source/libsmb/nmblib.c 2004-07-20 11:28:04.000000000 -0500 +++ samba-3.0.5/source/libsmb/nmblib.c 2004-09-09 09:17:47.873805426 -0500 @@ -475,6 +475,11 @@ dgram->datasize = length-offset; memcpy(dgram->data,inbuf+offset,dgram->datasize); + /* Paranioa. Ensure the last 2 bytes in the dgram buffer are + zero. This should be true anyway, just enforce it for paranioa sake. JRA. */ + SMB_ASSERT(dgram->datasize <= (sizeof(dgram->data)-2)); + memset(&dgram->data[sizeof(dgram->data)-2], '\0', 2); + return(True); } diff -urBb --exclude-from=../../../samba-cvs/diff.excludes samba-3.0.5-orig/source/nmbd/nmbd_packets.c samba-3.0.5/source/nmbd/nmbd_packets.c --- samba-3.0.5-orig/source/nmbd/nmbd_packets.c 2004-07-20 11:28:11.000000000 -0500 +++ samba-3.0.5/source/nmbd/nmbd_packets.c 2004-09-09 09:17:47.880803725 -0500 @@ -1203,6 +1203,16 @@ return; } + /* Ensure we have a large enough packet before looking inside. */ + if (dgram->datasize < (smb_vwv12 - 2)) { + /* That's the offset minus the 4 byte length + 2 bytes of offset. */ + DEBUG(0,("process_dgram: ignoring too short dgram packet (%u) sent to name %s from IP %s\n", + (unsigned int)dgram->datasize, + nmb_namestr(&dgram->dest_name), + inet_ntoa(p->ip) )); + return; + } + buf = &dgram->data[0]; buf -= 4; /* XXXX for the pseudo tcp length - someday I need to get rid of this */ @@ -1212,14 +1222,36 @@ len = SVAL(buf,smb_vwv11); buf2 = smb_base(buf) + SVAL(buf,smb_vwv12); - if (len <= 0) + if (len <= 0 || len > dgram->datasize) { + DEBUG(0,("process_dgram: ignoring malformed1 (datasize = %d, len = %d) datagram \ +packet sent to name %s from IP %s\n", + dgram->datasize, + len, + nmb_namestr(&dgram->dest_name), + inet_ntoa(p->ip) )); return; + } - if (buf2 + len > buf + sizeof(dgram->data)) { - DEBUG(2,("process_dgram: datagram from %s to %s IP %s for %s len=%d too long.\n", - nmb_namestr(&dgram->source_name),nmb_namestr(&dgram->dest_name), - inet_ntoa(p->ip), smb_buf(buf),len)); - len = (buf + sizeof(dgram->data)) - buf; + if (buf2 < dgram->data || (buf2 >= dgram->data + dgram->datasize)) { + DEBUG(0,("process_dgram: ignoring malformed2 (datasize = %d, len=%d, off=%d) datagram \ +packet sent to name %s from IP %s\n", + dgram->datasize, + len, + PTR_DIFF(buf2, dgram->data), + nmb_namestr(&dgram->dest_name), + inet_ntoa(p->ip) )); + return; + } + + if ((buf2 + len < dgram->data) || (buf2 + len > dgram->data + dgram->datasize)) { + DEBUG(0,("process_dgram: ignoring malformed3 (datasize = %d, len=%d, off=%d) datagram \ +packet sent to name %s from IP %s\n", + dgram->datasize, + len, + PTR_DIFF(buf2, dgram->data), + nmb_namestr(&dgram->dest_name), + inet_ntoa(p->ip) )); + return; } DEBUG(4,("process_dgram: datagram from %s to %s IP %s for %s of type %d len=%d\n", diff -urBb --exclude-from=../../../samba-cvs/diff.excludes samba-3.0.5-orig/source/nmbd/nmbd_processlogon.c samba-3.0.5/source/nmbd/nmbd_processlogon.c --- samba-3.0.5-orig/source/nmbd/nmbd_processlogon.c 2004-07-20 11:28:10.000000000 -0500 +++ samba-3.0.5/source/nmbd/nmbd_processlogon.c 2004-09-09 09:17:49.244472259 -0500 @@ -102,8 +102,22 @@ char *machine = q; char *user = skip_string(machine,1); + if (PTR_DIFF(user, buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } getdc = skip_string(user,1); + + if (PTR_DIFF(getdc, buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } q = skip_string(getdc,1); + + if (PTR_DIFF(q + 5, buf) > len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } token = SVAL(q,3); fstrcpy(reply_name,my_name); @@ -151,7 +165,17 @@ } getdc = skip_string(machine,1); + + if (PTR_DIFF(getdc, buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } q = skip_string(getdc,1); + + if (PTR_DIFF(q, buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } q = ALIGN2(q, buf); /* At this point we can work out if this is a W9X or NT style @@ -165,9 +189,19 @@ } else { unicomp = q; + if (PTR_DIFF(q, buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } + /* A full length (NT style) request */ q = skip_unibuf(unicomp, PTR_DIFF(buf + len, unicomp)); + if (PTR_DIFF(q, buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } + if (len - PTR_DIFF(q, buf) > 8) { /* with NT5 clients we can sometimes get additional data - a length specificed string @@ -180,6 +214,12 @@ } q += 16; } + + if (PTR_DIFF(q + 8, buf) > len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } + ntversion = IVAL(q, 0); lmnttoken = SVAL(q, 4); lm20token = SVAL(q, 6); @@ -240,10 +280,34 @@ fstring asccomp; q += 2; + + if (PTR_DIFF(q, buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } + unicomp = q; uniuser = skip_unibuf(unicomp, PTR_DIFF(buf+len, unicomp)); + + if (PTR_DIFF(uniuser, buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } + getdc = skip_unibuf(uniuser,PTR_DIFF(buf+len, uniuser)); + + if (PTR_DIFF(getdc, buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } + q = skip_string(getdc,1); + + if (PTR_DIFF(q + 8, buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } + q += 4; /* Account Control Bits - indicating username type */ domainsidsize = IVAL(q, 0); q += 4; @@ -270,6 +334,11 @@ q += 16; } + if (PTR_DIFF(q + 8, buf) > len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } + ntversion = IVAL(q, 0); lmnttoken = SVAL(q, 4); lm20token = SVAL(q, 6); @@ -458,6 +527,11 @@ /* Header */ + if (PTR_DIFF(q + 16, buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } + low_serial = IVAL(q, 0); q += 4; /* Low serial number */ q += 4; /* Date/time */ @@ -467,14 +541,42 @@ /* Domain info */ q = skip_string(q, 1); /* PDC name */ + + if (PTR_DIFF(q, buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } + q = skip_string(q, 1); /* Domain name */ + + if (PTR_DIFF(q, buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } + q = skip_unibuf(q, PTR_DIFF(buf + len, q)); /* Unicode PDC name */ + + if (PTR_DIFF(q, buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } + q = skip_unibuf(q, PTR_DIFF(buf + len, q)); /* Unicode domain name */ /* Database info */ + if (PTR_DIFF(q + 2, buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } + db_count = SVAL(q, 0); q += 2; + if (PTR_DIFF(q + (db_count*20), buf) >= len) { + DEBUG(0,("process_logon_packet: bad packet\n")); + return; + } + db_info = (struct sam_database_info *) malloc(sizeof(struct sam_database_info) * db_count); diff -urBb --exclude-from=../../../samba-cvs/diff.excludes samba-3.0.5-orig/source/libsmb/asn1.c samba-3.0.5/source/libsmb/asn1.c --- samba-3.0.5-orig/source/libsmb/asn1.c 2004-07-20 11:28:04.000000000 -0500 +++ samba-3.0.5/source/libsmb/asn1.c 2004-09-09 09:41:23.170796486 -0500 @@ -219,6 +219,9 @@ /* read from a ASN1 buffer, advancing the buffer pointer */ BOOL asn1_read(ASN1_DATA *data, void *p, int len) { + if (data->has_error) + return False; + if (len < 0 || data->ofs + len < data->ofs || data->ofs + len < len) { data->has_error = True; return False; @@ -309,6 +312,9 @@ /* work out how many bytes are left in this nested tag */ int asn1_tag_remaining(ASN1_DATA *data) { + if (data->has_error) + return 0; + if (!data->nesting) { data->has_error = True; return -1;