// #if 0 // Don't compile the detection functions if they're not used
int rule23039eval(void *p) {
    const u_int8_t  *cursor_normal  = 0;
    SFSnortPacket *sp = (SFSnortPacket *) p;

    if(sp == NULL)
        return RULE_NOMATCH;

    if(sp->payload == NULL)
        return RULE_NOMATCH;

    // flow:to_server;
    if(checkFlow(p, rule23039options[0]->option_u.flowFlags) <= 0 )
        return RULE_NOMATCH;
   
    // content:"|00 01 00 00 00 00|", offset 4, depth 8, fast_pattern;
    if(contentMatch( p, rule23039options[1]->option_u.content, &cursor_normal ) <= 0)
        return RULE_NOMATCH;

    // The last |00| in the match above drops the cursor at the beginning of the first query,
    //      12 bytes from the beginning of the payload.  If the first 2 bits are set on this byte,
    //      it means we're looking at a pointer.  In that event, we'll go ahead and flag it, because
    //      we've already verified that there is only one query.

    return detectDNSloop(sp, cursor_normal );
}
int rule37676eval(void *p) {
   const uint8_t *cursor_normal = 0, *end_of_buffer;
   SFSnortPacket *sp = (SFSnortPacket *) p;

   if(sp == NULL)
      return RULE_NOMATCH;

   if(sp->payload == NULL)
      return RULE_NOMATCH;

   // flow:to_server
   if(checkFlow(p, rule37676options[0]->option_u.flowFlags) <= 0)
      return RULE_NOMATCH;

   // content:"|84|", fast_pattern:only;
   // if(contentMatch(p, rule37676options[1]->option_u.content, &cursor_normal) <= 0)
   //    return RULE_NOMATCH;
  
   // content:"|20|", offset 17, depth 1;
   if(contentMatch(p, rule37676options[2]->option_u.content, &cursor_normal) <= 0)
      return RULE_NOMATCH;

   if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &cursor_normal, &end_of_buffer) <= 0)
      return RULE_NOMATCH;

   return DetectCiscoIkeBof(sp, cursor_normal, end_of_buffer);
}
// #if 0 // Don't compile the detection functions if they're not used
int rule18063eval(void *p) {
    const uint8_t *cursor_normal = 0, *OfficeArtSPContainer = 0, *OfficeArtSpgrContainer = 0, *OfficeArtFSP = 0, *OfficeArtFSPGR = 0;
    const uint8_t *beg_of_payload = 0, *end_of_payload = 0, *tmp_payload = 0;
    uint32_t OfficeArtSpgrContainer_size = 0, OfficeArtSPContainer_size = 0;
    SFSnortPacket *sp = (SFSnortPacket *) p;

    if(sp == NULL)
        return RULE_NOMATCH;

    if(sp->payload == NULL)
        return RULE_NOMATCH;
    
    // flow:established, to_client;
    if (checkFlow(p, rule18063options[0]->option_u.flowFlags) <= 0 ) {
       return RULE_NOMATCH;
    }
    // flowbits:isset "file.doc";
    if (processFlowbits(p, rule18063options[1]->option_u.flowBit) <= 0) {
       return RULE_NOMATCH;
    }
    if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0) {
      return RULE_NOMATCH;
    }

    // Start by finding inner container
    // content:"|0F 00 04 F0|", depth 0, fast_pattern;
    if (contentMatch(p, rule18063options[3]->option_u.content, &OfficeArtSPContainer) <= 0) {
       return RULE_NOMATCH;
    }

    DEBUG_SO(fprintf(stderr, "OfficeArtSPContainer found: %p\n", OfficeArtSPContainer);)
    
    // Find the outer container - This may or may not exist
    // content:"|0F 00 03 F0|", depth 0; 
    if(contentMatch(p, rule18063options[2]->option_u.content, &OfficeArtSpgrContainer) <= 0) {
int rule35943eval(void *p) {
   const uint8_t *cursor_normal = 0, *end_of_buffer;
   SFSnortPacket *sp = (SFSnortPacket *) p;

   if(sp == NULL)
      return RULE_NOMATCH;

   if(sp->payload == NULL)
      return RULE_NOMATCH;
   
   // flow:established, to_server;
   if(checkFlow(p, rule35943options[0]->option_u.flowFlags) <= 0)
      return RULE_NOMATCH;
   
   // content:"|00 01|", offset 6, depth 2;
   if(contentMatch(p, rule35943options[2]->option_u.content, &cursor_normal) <= 0)
      return RULE_NOMATCH;
   
   // content:"|00 00 00|", offset 2, depth 3, relative;
   if(contentMatch(p, rule35943options[3]->option_u.content, &cursor_normal) <= 0)
      return RULE_NOMATCH;

   if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &cursor_normal, &end_of_buffer) <= 0)
      return RULE_NOMATCH;

   // move cursor to flags
   // in the TCP case, flags are at offset 4
   cursor_normal += 4;

   return DetectBindTkeyDos(cursor_normal, end_of_buffer);
}
// #if 0 // Don't compile the detection functions if they're not used
int rule18101eval(void *p) {
   const uint8_t *cursor_normal = 0;
   SFSnortPacket *sp = (SFSnortPacket *) p;
   const uint8_t *end_of_payload;

   BER_ELEMENT ber_element;

   if(sp == NULL)
      return RULE_NOMATCH;
    
   // flow:established, to_server;
   if(checkFlow(p, rule18101options[0]->option_u.flowFlags) <= 0 )
      return RULE_NOMATCH;

   if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &cursor_normal, &end_of_payload) <= 0)
      return RULE_NOMATCH;

   BER_DATA(0x30);
   BER_SKIP(0x02);

   if(ber_get_element(sp, cursor_normal, &ber_element) < 0)
      return RULE_NOMATCH;

   // Exploit condition is SearchRequest (0x63) or ModifyDNRequest (0x6c) with
   // large size.  We're going with 1000 as a max size, apparently.
   if(ber_element.data_len > 1000 && (ber_element.type == 0x63 || ber_element.type == 0x6c))
      return RULE_MATCH;

   return RULE_NOMATCH;
}
Example #6
0
void NetwalkWindow::mapViewTileClicked( Widget& o, int x, int y, MouseButtons mb )
{
  if ( mb.left ) {
    rotate( x, y, true );
    pCliConn = 0;
    checkFlow();
    scoreLabel.setText( Utils::toWString(++pTurns) );
    o.updated();
  } else if ( mb.right ) {
    rotate( x, y, false );
    pCliConn = 0;
    checkFlow();
    scoreLabel.setText( Utils::toWString(++pTurns) );
    o.updated();
  }
}
Example #7
0
void eMP3Decoder::outputReady(int what)
{
	(void)what;
	singleLock s(lock); // must protect access on all eIOBuffer, position, outputbr
	if (type != codecMPG)
	{
		if ( ( pcmsettings.reconfigure 
				|| (pcmsettings.samplerate != audiodecoder->pcmsettings.samplerate) 
				|| (pcmsettings.channels != audiodecoder->pcmsettings.channels)))
		{
			pcmsettings=audiodecoder->pcmsettings;
			
			outputbr=pcmsettings.samplerate*pcmsettings.channels*16;
			if (::ioctl(dspfd[0], SNDCTL_DSP_SPEED, &pcmsettings.samplerate) < 0)
				eDebug("SNDCTL_DSP_SPEED failed (%m)");
			if (::ioctl(dspfd[0], SNDCTL_DSP_CHANNELS, &pcmsettings.channels) < 0)
				eDebug("SNDCTL_DSP_CHANNELS failed (%m)");
			if (::ioctl(dspfd[0], SNDCTL_DSP_SETFMT, &pcmsettings.format) < 0)
				eDebug("SNDCTL_DSP_SETFMT failed (%m)");
//			eDebug("reconfigured audio interface...");
		}
	}
	seekbusy-=output.tofile(dspfd[0], 65536);
	if (seekbusy < 0)
		seekbusy=0;
	checkFlow(0);
}
Example #8
0
void eMP3Decoder::outputReady2(int what)
{
	(void)what;
	singleLock s(lock); // must protect access on all eIOBuffer, position, outputbr
	output2.tofile(dspfd[1], 65536);
	checkFlow(0);
}
/* detection functions */
int rule15968eval(void *p) {
    const uint8_t *cursor_normal = 0, *beg_of_payload, *end_of_payload;
    SFSnortPacket *sp = (SFSnortPacket *) p;

    uint32_t MsgLen, stringOffset;

    if(sp == NULL)
        return RULE_NOMATCH;

    if(sp->payload == NULL)
        return RULE_NOMATCH;
    
    // flow:established, to_server;
    if (checkFlow(p, rule15968options[0]->option_u.flowFlags) > 0 ) {
        // content:"heal", offset 14, depth 4, fast_pattern;
        if (contentMatch(p, rule15968options[1]->option_u.content, &cursor_normal) > 0) {
            // content:"sdfx", depth 4;
            if (contentMatch(p, rule15968options[2]->option_u.content, &cursor_normal) > 0) {

                // This protocol is goofy.  stringOffset, in the payload, is little endian.
                // MsgLen, in the header, is big endian.
                // Vulnerable condition is if stringOffset is less than 0x24 or greater
                // than MsgLen.
                if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0)
                   return RULE_NOMATCH;
 
                if(end_of_payload - beg_of_payload < 38)
                   return RULE_NOMATCH;

                cursor_normal = beg_of_payload + 34;
                stringOffset = *cursor_normal++;
                stringOffset |= *cursor_normal++ << 8;
                stringOffset |= *cursor_normal++ << 16;
                stringOffset |= *cursor_normal << 24;

                //printf("stringOffset = %d (0x%08x)\n", stringOffset, stringOffset);

                if(stringOffset < 0x24)
                    return RULE_MATCH;

                cursor_normal = beg_of_payload + 4;
                MsgLen = *cursor_normal++ << 24;
                MsgLen |= *cursor_normal++ << 16;
                MsgLen |= *cursor_normal++ << 8;
                MsgLen |= *cursor_normal;

                //printf("MsgLen = %d (0x%08x)\n", MsgLen, MsgLen);

                if(stringOffset > MsgLen)
                    return RULE_MATCH;

                // Note there is also a two-byte big endian value PayloadLen at offset 12
                // and a four-byte little endian dataLen at offset 18.
                // We ignore them, because they do not seem relevant to detection.
            }
        }
    }
    return RULE_NOMATCH;
}
/* detection functions */
int rule13308eval(void *p) {
    const u_int8_t *cursor_normal = 0;
    const u_int8_t *beg_of_buffer, *end_of_buffer;

    SFSnortPacket *sp = (SFSnortPacket *) p;
    
    // Base64 stuff
    u_int8_t base64buf[256], decodedbuf[256];
    u_int32_t inputchars, base64bytes, decodedbytes;

    int i;

    if(sp == NULL)
        return RULE_NOMATCH;

    // flow:established, to_server;
    if (checkFlow(p, rule13308options[0]->option_u.flowFlags) <= 0)
        return RULE_NOMATCH;

    // Doing this content match is pretty useless because it's duplicated in our PCRE.
    // But we want to keep the structure for the pattern matcher.
//    // content:"Authorization|3A|", depth 0, nocase, fast_pattern;
//    if (contentMatch(p, rule13308options[1]->option_u.content, &cursor_normal) <= 0)
//        return RULE_NOMATCH;

    // pcre:"^Authorization\x3A\s*Basic[ \t]+", dotall, multiline, nocase;
    if (pcreMatch(p, rule13308options[2]->option_u.pcre, &cursor_normal) <= 0)
        return RULE_NOMATCH;

    if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_buffer, &end_of_buffer) != CURSOR_IN_BOUNDS)
        return RULE_NOMATCH;

    // At this point, cursor should point to the start of the auth data
    inputchars = (end_of_buffer > cursor_normal + sizeof(base64buf)) ? sizeof(base64buf) : end_of_buffer - cursor_normal;

    DEBUG_SO(printf("%d input chars: %*s\n", inputchars, inputchars, cursor_normal));

    if(unfold_header(cursor_normal, inputchars, base64buf, sizeof(base64buf), &base64bytes) != 0)
        return RULE_NOMATCH;

    DEBUG_SO(printf("Successfully unfolded header (%s)(%d)\n", base64buf, base64bytes));

    if(base64decode(base64buf, base64bytes, decodedbuf, sizeof(decodedbuf), &decodedbytes) < 0)
        return RULE_NOMATCH;

    DEBUG_SO(printf("Successfully base64 decoded (%s)(%d)\n", decodedbuf, decodedbytes));
  
    for(i=0; i<decodedbytes; i++) {
        DEBUG_SO(printf("checking byte: %c\n", decodedbuf[i]));
        if(decodedbuf[i] == '%') {
            return RULE_MATCH;
        } else if(decodedbuf[i] == ':') {
            // Separator between username:password
            return RULE_NOMATCH;
        }
    }        
        
    return RULE_NOMATCH;
}
/* detection functions */
int rule17741eval(void *p)
{
    const uint8_t *cursor_normal = 0, *end_of_payload;    
    SFSnortPacket *sp = (SFSnortPacket *) p;

    BER_ELEMENT ber_element;
    BER_ELEMENT req_body;
    BER_ELEMENT req_body_SEQUENCE;       
    int         ret;

    DEBUG_SO(printf("rule17741eval enter\n"));

    if(sp == NULL)
       return RULE_NOMATCH;

    // flow:to_server;
    if(checkFlow(p, rule17741options[0]->option_u.flowFlags) <= 0 )
        return RULE_NOMATCH;
        
    if (getBuffer(sp, CONTENT_BUF_NORMALIZED, &cursor_normal, &end_of_payload) <= 0)
        return RULE_NOMATCH;
  
    ret = ber_get_element(sp, cursor_normal, &ber_element);

    DEBUG_SO(printf("First element type 0x%02x\n", ber_element.type));

    if(ret < 0 || ((ber_element.type != 0x6a) && (ber_element.type != 0x6c)))
       return RULE_NOMATCH;

    // We want to delve into this element
    cursor_normal = ber_element.data.data_ptr;
 
    BER_DATA(0x30);         // SEQUENCE
    BER_SKIP(0xA1);         // pvno [1] INTEGER (5)
    BER_SKIP(0xA2);         // msg-type [2] INTEGER (10 -- AS -- | 12 -- TGS --)
    
    // if optional PA-DATA exists, skip it
    // 10 1 00011  (context-specific, structured, tag number 3)
    if (cursor_normal < end_of_payload && *cursor_normal == 0xA3)
        BER_SKIP(0xA3);     // padata [3] SEQUENCE OF PA-DATA OPTIONAL
   
    // req-body [4] KDC-REQ-BODY
    // req-body is defined as SEQUENCE and if req-body's data size is not equal to 
    // the total size of SEQUENCE, it is malicious
    
    ret = ber_get_element(sp, cursor_normal, &req_body);
    if (ret < 0)
        return RULE_NOMATCH;
    
    BER_DATA(0xA4);         

    ret = ber_get_element(sp, cursor_normal, &req_body_SEQUENCE);
    if (ret < 0)
        return RULE_NOMATCH;
 
    DEBUG_SO(printf("req_body.data_len = 0x%08x, req_body_SEQUENCE.specified_total_len = 0x%08x\n", req_body.data_len, req_body_SEQUENCE.specified_total_len);)
        
    if (req_body.data_len != req_body_SEQUENCE.specified_total_len)
/* detection functions */
int rule16396eval(void *p) {
    const uint8_t *cursor_normal = 0;
    SFSnortPacket *sp = (SFSnortPacket *) p;

    const uint8_t *beg_of_payload, *end_of_payload;
    uint32_t length = 0;
    uint16_t WCT;
    uint16_t BCC;

    if(sp == NULL)
        return RULE_NOMATCH;

    if(sp->payload == NULL)
        return RULE_NOMATCH;
    
    // flow:established, to_server;
    if (checkFlow(p, rule16396options[0]->option_u.flowFlags) > 0 ) {
        // content:"|FF|SMBr", offset 4, depth 5, fast_pattern;
        if (contentMatch(p, rule16396options[1]->option_u.content, &cursor_normal) > 0) {

            if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0)
                     return RULE_NOMATCH;

            // isdataat:offset 30, relative;
            if (cursor_normal + 30 <= end_of_payload) {

                //Extract length from Netbios session header
                //Previous content match assures us no buffer underread
                length = *(cursor_normal-8) << 16;
                length |= *(cursor_normal-7) << 8;
                length |= *(cursor_normal-6);

                //Extract WCT Word Count
                //Word Count should be usually be zero in negotiate requests
                //But we need to be able to handle the case where there is 
                //some value in there.
                cursor_normal += 27;
                WCT =  2 * *cursor_normal++;
                cursor_normal += WCT;                

                //Make sure there is enough room to extract BCC
                if (cursor_normal + 2 > end_of_payload)
                    return RULE_NOMATCH;

                //Extract BCC Byte Count
                BCC = read_little_16_inc(cursor_normal);

                //Alert if your netbios session size is bigger than
                //Byte count + number of words * 2 + 32-byte SMB header
                //+ 3 bytes (1 for the WCT field, and 2 for the BCC field)
                if (length > (BCC + WCT + 35))
                    return RULE_MATCH;
            }
        }
    }
    return RULE_NOMATCH;
}
/* detection functions */
int rule16180eval(void *p) {
    const u_int8_t *cursor_normal = 0;
    SFSnortPacket *sp = (SFSnortPacket *) p;
    const u_int8_t *beg_of_payload, *end_of_payload;
    const u_int8_t *end_of_CommonName;

    if(sp == NULL)
        return RULE_NOMATCH;

    if(sp->payload == NULL)
        return RULE_NOMATCH;
    
    // flow:established, to_client;
    if (checkFlow(p, rule16180options[0]->option_u.flowFlags) > 0 ) {

        // content:"|16 03|", depth 0;
        if (contentMatch(p, rule16180options[1]->option_u.content, &cursor_normal) > 0) {

            // content:"U|04 03|", depth 0, relative, fast_pattern;
            if (contentMatch(p, rule16180options[2]->option_u.content, &cursor_normal) > 0) {

                if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0)
                  return RULE_NOMATCH;

                // Skip single byte type value, we're not checking it
                cursor_normal++;

                if(cursor_normal + 1 > end_of_payload)
                   return RULE_NOMATCH;

                // Extract one-byte length value and use it to set end_of_CommonName
                end_of_CommonName = cursor_normal + *cursor_normal + 1;

                // Skip length value
                cursor_normal++;

                // Ensure we don't go past the end of the payload
                if (end_of_payload < end_of_CommonName) {
                    end_of_CommonName = end_of_payload;
                }

                // Zip through the field, stop at end or NULL
                while ((cursor_normal < end_of_CommonName) && (*cursor_normal++)) {
                   // empty loop
                }

                // If we stop before the end, there was a NULL so alert
                if (cursor_normal < end_of_CommonName) {
                    return RULE_MATCH;
                }
            }
        }
    }
    return RULE_NOMATCH;
}
/* detection functions */
int rule19187eval(void *p) {
   const u_int8_t *cursor_normal = 0;
   SFSnortPacket *sp = (SFSnortPacket *) p;

   u_int16_t flags, num_of_answers, data_len;
   const u_int8_t *beg_of_payload, *end_of_payload;
   const u_int8_t *start_hostent, *end_hostent;

   int i;

   if(sp == NULL)
       return RULE_NOMATCH;

   if(sp->payload == NULL)
       return RULE_NOMATCH;

   // flow:to_client;
   if (checkFlow(p, rule19187options[0]->option_u.flowFlags) > 0 ) {

      if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0)
         return RULE_NOMATCH;

      // Ensure we have enough data
      // txid, flags, num records * 4, query response (unk), at least 256 bytes of hostent
      // So, at least 300 bytes, I guess.
      DEBUG_SO(printf("Payload size = %d\n", (int)(end_of_payload - beg_of_payload));)
      if(end_of_payload - beg_of_payload < 300)
         return RULE_NOMATCH;

      // Forcing to be only one response entry
      // content:"|00 01|", offset 4, depth 2, fast_pattern;
      if (contentMatch(p, rule19187options[1]->option_u.content, &cursor_normal) <= 0) {
          return RULE_NOMATCH;
      }

      // Now, let's make sure this is actually a standard query response.
      // Our content match above ensures we have requisite data.

      flags = *(cursor_normal - 4) << 8;
      flags |= *(cursor_normal - 3);

      if((flags & 0xFA0F) != 0x8000) {
         // 1 bit - response (1 = response)
         // 4 bits - opcode (0000 = standard query)
         // 1 bit - authoritative (don't care)
         // 1 bit - truncated (0 = not truncated)
         // 5 bits - recursion and other don't cares
         // 4 bits - reply code (0000 = no error)
         return RULE_NOMATCH;
      }

      // Get number of answers
      num_of_answers = *cursor_normal++ << 8;
      num_of_answers |= *cursor_normal;
      DEBUG_SO(printf("We have %d answers\n", num_of_answers);)
int ruleMYSQL_COM_TABLE_DUMPeval(void *p) {
   const uint8_t *cursor_normal = 0, *beg_of_payload = 0, *end_of_payload = 0;
   uint32_t packet_length;
   uint8_t db_name_length, table_name_length;

   SFSnortPacket *sp = (SFSnortPacket *) p; 

   // flow:established, to_server;
   if(checkFlow(p, ruleMYSQL_COM_TABLE_DUMPoptions[0]->option_u.flowFlags) > 0 ) {

      /* Make sure the packet is long enough */
      if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0)
         return RULE_NOMATCH;

      if((end_of_payload - beg_of_payload) < 6)
         return RULE_NOMATCH;


      // content:"|13|", depth 1; offset 4;
      if(contentMatch(p, ruleMYSQL_COM_TABLE_DUMPoptions[1]->option_u.content, &cursor_normal) > 0) {

         // Grab the size of the "packet" -- this is the size (in bytes) of
         // data after the message number byte, including the command byte
         // Packet size is 3 bytes, little endian
         packet_length = beg_of_payload[0];
         packet_length += beg_of_payload[1] << 8;
         packet_length += beg_of_payload[2] << 16;

         // Grab the length of the DB Name
         db_name_length = beg_of_payload[5];

         // if db name length > packet length (+2 for length and command
         // bytes), flag
         if((db_name_length + 2) > packet_length) {
            return RULE_MATCH;
         }  else {
            // else grab table name length
            // table_name_length is at offset of db_name + db_name_length 
            // + size byte
            if((end_of_payload - beg_of_payload) < 5 + db_name_length + 2) 
               return RULE_NOMATCH;

            table_name_length = beg_of_payload[5 + db_name_length + 1]; 

            // if table name length + db name length + size bytes
            // + command byte > packet length, flag
            if((db_name_length + table_name_length + 3) > packet_length)
               return RULE_MATCH;
         }
      }  
   }  

   return RULE_NOMATCH;
}
/* detection functions */
int rule13897eval(void *p) {
   const u_int8_t *cursor_normal = 0;
   SFSnortPacket *sp = (SFSnortPacket *) p;

   const u_int8_t *beg_of_payload, *end_of_payload;
   u_int32_t atom_size;
   u_int16_t region_size;
      
   if(sp == NULL)
      return RULE_NOMATCH;

   if(sp->payload == NULL)
      return RULE_NOMATCH;
    
   // flow:established, to_client;
   if(checkFlow(p, rule13897options[0]->option_u.flowFlags) > 0 ) {
      // flowbits:isset "file.quicktime";
      if(processFlowbits(p, rule13897options[1]->option_u.flowBit) > 0) {
        // content:"crgn";
        if(contentMatch(p, rule13897options[2]->option_u.content, &cursor_normal) > 0) {
           if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0)
              return RULE_NOMATCH;
                
           if(cursor_normal + 2 >= end_of_payload)
              return RULE_NOMATCH;
   
           region_size = (*cursor_normal++) << 8;
           region_size |= *cursor_normal++;
   
           DEBUG_WRAP(printf("REGION SIZE: %d\n", region_size));
      
           cursor_normal = cursor_normal - 10;

           if(cursor_normal < beg_of_payload)
              return RULE_NOMATCH;
      
           atom_size = (*cursor_normal++) << 24;   
           atom_size |= (*cursor_normal++) << 16;
           atom_size |= (*cursor_normal++) << 8;
           atom_size |= *cursor_normal++;
   
           DEBUG_WRAP(printf("ATOM SIZE: %d\n", atom_size));
  
           // Changed from region_size > (atom_size - 8) to avoid
           // integer underflow from (atom_size - 8)
           if(((u_int32_t)region_size + 8) > atom_size) 
              return RULE_MATCH;
         }
      }
   }

   return RULE_NOMATCH;
}
/* detection functions */
int ruleCITRIX_METAFRAME_BOeval(void *p) {
    const uint8_t *cursor_normal = 0, *beg_of_payload, *end_of_payload;

    const uint8_t *cursor_extract = 0;
    uint32_t event_data_length, description_length, encr_data_length;

    SFSnortPacket *sp = (SFSnortPacket *) p;

    // flow:established, to_server;
    if (checkFlow(p, ruleCITRIX_METAFRAME_BOoptions[0]->option_u.flowFlags) > 0 ) {

        // content:"A|80 00 00 02|", offset 28, depth 5;
        if (contentMatch(p, ruleCITRIX_METAFRAME_BOoptions[1]->option_u.content, &cursor_normal) > 0) {

            // byte_test:size 4, value 16, operator <, offset 4, endian little;
            if (byteTest(p, ruleCITRIX_METAFRAME_BOoptions[2]->option_u.byte, cursor_normal) > 0) {

                if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0)
                     return RULE_NOMATCH;

                if((end_of_payload - beg_of_payload) < 0x28)
                   return RULE_NOMATCH;


                // Extract Event Data Length ( 4 bytes little endian )
                cursor_extract = &(beg_of_payload[0x0008]);
                event_data_length  = (*cursor_extract++) & 0xFF;
                event_data_length |= ((*cursor_extract++) & 0xFF) << 8;
                event_data_length |= ((*cursor_extract++) & 0xFF) << 16;
                event_data_length |= ((*cursor_extract++) & 0xFF) << 24;

                // Extract Description Length ( 2 bytes little endian )
                cursor_extract = &(beg_of_payload[0x0022]);
                description_length  = (*cursor_extract++) & 0xFF;
                description_length |= ((*cursor_extract++) & 0xFF) << 8;

		// extract Encrypted Data Length ( 4 bytes little endian )
                cursor_extract = &(beg_of_payload[0x00024]);
                encr_data_length  = (*cursor_extract++) & 0xFF;
                encr_data_length |= ((*cursor_extract++) & 0xFF) << 8;
                encr_data_length |= ((*cursor_extract++) & 0xFF) << 16;
                encr_data_length |= ((*cursor_extract++) & 0xFF) << 24;

                if(description_length + encr_data_length > event_data_length)
                   return RULE_MATCH;
            }
        }
    }
    return RULE_NOMATCH;
}
/* detection functions */
int rule14646eval(void *p) {
    const uint8_t *cursor_normal = 0, *end_of_payload;
    SFSnortPacket *sp = (SFSnortPacket *) p;

    int retval;
    BER_ELEMENT element;

    if(sp == NULL)
        return RULE_NOMATCH;

    if(sp->payload == NULL)
        return RULE_NOMATCH;

    // flow:established, to_server;
    if(checkFlow(p, rule14646options[0]->option_u.flowFlags) <= 0 )
        return RULE_NOMATCH;

    if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &cursor_normal, &end_of_payload) <= 0)
        return RULE_NOMATCH;

    // Universal Sequence
    if(ber_point_to_data(sp, &cursor_normal, 0x30) < 0)
        return RULE_NOMATCH;

    // message ID
    if(ber_skip_element(sp, &cursor_normal, 0x02) < 0)
        return RULE_NOMATCH;

    // search request
    if(ber_point_to_data(sp, &cursor_normal, 0x63) < 0)
        return RULE_NOMATCH;

    // Here's the meat
    retval = ber_get_element(sp, cursor_normal, &element);

    if(retval == -1)
        return RULE_NOMATCH;

    //DEBUG_WRAP(printf("found baseObject string.  checking values type=0x%02x size=%d\n", element.type, element.data_len));

    /* vuln is 0x43 + len(baseObject first part) + 3 * len(baseObject dc) > 0xFFA
       We simplify to data_len > 1200 since that's more than reasonable and shortest possible
       length to exploit is len(baseObject) == len(d) == 1363
    */
    if(element.type == 0x04 && ((element.data_len > 1200) || (retval == -2)))
        return RULE_MATCH;

    return RULE_NOMATCH;
}
/* detection functions */
int rule15149eval(void *p) {
    const uint8_t *cursor_normal = 0, *end_of_payload;
    SFSnortPacket *sp = (SFSnortPacket *) p;

   int retval;
   BER_ELEMENT element;

    if(sp == NULL)
        return RULE_NOMATCH;

    if(sp->payload == NULL)
        return RULE_NOMATCH;
    
    // flow:established, to_server;
    if (checkFlow(p, rule15149options[0]->option_u.flowFlags) <= 0 ) {
        return RULE_NOMATCH;
    }

   if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &cursor_normal, &end_of_payload) <= 0)
      return RULE_NOMATCH;

   // Universal Sequence
   if(ber_point_to_data(sp, &cursor_normal, 0x30) < 0)
      return RULE_NOMATCH;

   // message ID
   if(ber_skip_element(sp, &cursor_normal, 0x02) < 0)
      return RULE_NOMATCH;

   // find the bind request
   if(ber_point_to_data(sp, &cursor_normal, 0x60) < 0)
      return RULE_NOMATCH;

   /* bind requests are defined as:
      int version
      LDAPDN name
      auth authenticationChoice
      bug here is if the version element is specified as a cursor (0x30) vs. an int (0x02)
   */
   retval = ber_get_element(sp, cursor_normal, &element);

   if(retval == -1)
      return RULE_NOMATCH;

   if(element.type == 0x30)
      return RULE_MATCH;

    return RULE_NOMATCH;
}
/* detection functions */
int rule23847eval(void *p) {
    const u_int8_t *cursor_normal = 0;
    SFSnortPacket *sp = (SFSnortPacket *) p;
    const u_int8_t *end_of_payload = 0;
    const u_int8_t *beg_of_payload = 0;
    const u_int8_t *beg_of_servers = 0;
    const u_int8_t *start_of_smb = 0;

    int16_t converter = 0;
    int16_t server_comment = 0;
    int16_t server_comment_position = 0;

    u_int32_t entries = 0;
    u_int32_t netbios_message_length = 0; 

    int i;

    if(sp == NULL)
        return RULE_NOMATCH;

    if(sp->payload == NULL)
        return RULE_NOMATCH;
    
    // flow:established, to_client;
    if (checkFlow(p, rule23847options[0]->option_u.flowFlags) <= 0 )
      return RULE_NOMATCH;

    // Verify we are looking at an SMB Trans (0x25) response.
    // Verify the SMB Request was STATUS_SUCCESS (0x00000000)
    // content:"|FF|SMB|25 00 00 00 00|", depth 0, fast_pattern;
    if (contentMatch(p, rule23847options[1]->option_u.content, &cursor_normal) <= 0)
      return RULE_NOMATCH;

    // Verify LANMAN protocol is reporting additional data available.
    // content:"|EA 00|", offset 47, depth 2, relative;
    if(contentMatch(p, rule23847options[2]->option_u.content, &cursor_normal) <= 0)
      return RULE_NOMATCH;

    // Get the beginning of payload and end of payload positions.
    if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0)
      return RULE_NOMATCH;

    start_of_smb = beg_of_payload + 4;  // Beginning of 9-byte content match

    netbios_message_length = READ_BIG_16(beg_of_payload + 2); // 2 byte size field
    DEBUG_SO(fprintf(stderr,"\nnetbios_message_length: %d\n", netbios_message_length);)
/* detection functions */
int rule15329eval(void *p) {
    const u_int8_t *cursor_normal = 0;
    SFSnortPacket *sp = (SFSnortPacket *) p;
    u_int8_t countOne = 0;
    u_int8_t countTwo = 0;
    const u_int8_t *beg_of_payload, *end_of_payload;

    if(sp == NULL)
        return RULE_NOMATCH;

    if(sp->payload == NULL)
        return RULE_NOMATCH;


    // flow:established, to_server;
    if (checkFlow(p, rule15329options[0]->option_u.flowFlags) > 0 ) {
        // content:"MODPROPS"; nocase; 
        if (contentMatch(p, rule15329options[1]->option_u.content, &cursor_normal) > 0) {

            if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0)
                return RULE_NOMATCH;

            while ((cursor_normal < end_of_payload) && (*cursor_normal != '\r') && (*cursor_normal != '\n')) {
                if (*cursor_normal == ',') {
                    countOne++;
                }
                cursor_normal++;
            }
            if (contentMatch(p, rule15329options[2]->option_u.content, &cursor_normal) > 0) {
                while ((cursor_normal < end_of_payload) && (*cursor_normal != '\r') && (*cursor_normal != '\n')) {
                    if (*cursor_normal == ',') {
                        countTwo++;
                    }
                    cursor_normal++;
                }
            }
            // Yes, technically these are both off-by-one on the count...but why waste the CPU
            // necessary to increment them both when leaving them as-is yields the same result?
            if (countTwo > countOne) {
                return RULE_MATCH;
            }
        }
    }
    return RULE_NOMATCH;
}
int rule23040eval(void *p) {
    const u_int8_t *cursor_normal = 0;
    SFSnortPacket *sp = (SFSnortPacket *) p;

    if(sp == NULL)
        return RULE_NOMATCH;

    if(sp->payload == NULL)
        return RULE_NOMATCH;
    
    // flow:established, to_server;
    if(checkFlow(p, rule23040options[0]->option_u.flowFlags) <= 0 ) 
        return RULE_NOMATCH;

    // content:"|00 01 00 00 00 00 00 00|", offset 6, depth 8, fast_pattern;
    if(contentMatch(p, rule23040options[1]->option_u.content, &cursor_normal) <= 0)  
        return RULE_NOMATCH;

    return detectDNSloop( sp, cursor_normal );
}
/* detection functions */
int rule13469eval(void *p) {
    const uint8_t *cursor_normal = 0;
    const uint8_t *beg_of_payload, *end_of_payload;
    uint32_t length;

    SFSnortPacket *sp = (SFSnortPacket *) p;

    // flow:established, to_client;
    if (checkFlow(p, rule13469options[0]->option_u.flowFlags) > 0 ) {
        // flowbits:isset "file.doc";
        if (processFlowbits(p, rule13469options[1]->option_u.flowBit) > 0) {

            // content:"bjbj";
            if (contentMatch(p, rule13469options[2]->option_u.content, &cursor_normal) > 0) {
                // content:"|00 00 00 00|", offset 62, depth 4, relative;
                if (!(contentMatch(p, rule13469options[3]->option_u.content, &cursor_normal) > 0)) {

                if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0)
                    return RULE_NOMATCH;

                // At this point, cursor_normal is still right after bjbj because negative
                // content matches do not move the pointer
                // Start custom detection here
                if((cursor_normal + 572) > end_of_payload)
                   return RULE_NOMATCH;

                cursor_normal += 568;
                length = *cursor_normal++;
                length |= *cursor_normal++ << 8;
                length |= *cursor_normal++ << 16;
                length |= *cursor_normal++ << 24;

                if((length - 4) % 0x1a)
                   return RULE_MATCH;
                }
            }
        }
    }
    return RULE_NOMATCH;
}
/* detection functions */
int rule15148eval(void *p) {
    const u_int8_t *cursor_normal = 0, *beg_of_payload, *end_of_payload;
    SFSnortPacket *sp = (SFSnortPacket *) p;
    u_int16_t data_len;

    if(sp == NULL)
        return RULE_NOMATCH;

    if(sp->payload == NULL)
        return RULE_NOMATCH;
    
    // flow:established, to_server;
    if (checkFlow(p, rule15148options[0]->option_u.flowFlags) > 0 ) {
        // content:"RCH0", depth 4, nocase;
        if (contentMatch(p, rule15148options[1]->option_u.content, &cursor_normal) > 0) {
            // content:"RCHE", offset 4, depth 4, nocase, relative;
            if (contentMatch(p, rule15148options[2]->option_u.content, &cursor_normal) > 0) {
                cursor_normal = cursor_normal - 8;
                data_len = *cursor_normal++;
                data_len |= (*cursor_normal++) << 8;

                if(data_len >= 130)
                   return RULE_MATCH;

                if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0)
                   return RULE_NOMATCH;

                // Normally, we'd be nervous about this check with TCP, but given the
                // packet sizes involved, we'll take the false positives from segmentation
                // on such a small packet.
                if(cursor_normal + 6 + data_len != end_of_payload)
                   return RULE_MATCH;
            }
        }
    }
    return RULE_NOMATCH;
}
/* detection functions */
int rule17697eval(void *p) {
    const uint8_t *cursor_normal = 0;
    const uint8_t *beg_of_buffer, *end_of_buffer;

    uint8_t decodedbuf[MAX_BASE64_BUFFER_SIZE], *decodedbuf_ptr;
    uint32_t inputchars, decodedbytes;
    SFSnortPacket *sp = (SFSnortPacket *) p;

    uint32_t tmpval = 0;

    if(sp == NULL)
        return RULE_NOMATCH;

    if(sp->payload == NULL)
        return RULE_NOMATCH;
    
    // flow:established, to_server;
    if (checkFlow(p, rule17697options[0]->option_u.flowFlags) > 0 ) {
        // content:"-----BEGIN PGP MESSAGE-----", depth 0, nocase, fast_pattern;
        if (contentMatch(p, rule17697options[1]->option_u.content, &cursor_normal) > 0) {
            DEBUG_SO(printf("Matched the PGP header\n"));

            // content:"Version|3A|", offset 2, depth 8, nocase, relative;
            if (contentMatch(p, rule17697options[2]->option_u.content, &cursor_normal) > 0) {
                DEBUG_SO(printf("Matched the version\n"));

                // content:"|0D 0A 0D 0A|", depth 0, relative;
                if (contentMatch(p, rule17697options[3]->option_u.content, &cursor_normal) > 0) {
                    DEBUG_SO(printf("Matched the newline\n"));

                    if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_buffer, &end_of_buffer) != CURSOR_IN_BOUNDS)
                        return RULE_NOMATCH;
               
                    // We should now be at the beginning of the PGP data
                    // Four base64 input chars become three output chars
                    inputchars = (end_of_buffer > cursor_normal + (sizeof(decodedbuf) * 4 / 3)) ? (sizeof(decodedbuf) * 4 / 3) : end_of_buffer - cursor_normal;
                    DEBUG_SO(printf("Decoding %d bytes\n", inputchars));

                    // Only need 6 output bytes, plus 1 byte for the NULL added by base64decode()
                    if(base64decode(cursor_normal, inputchars, decodedbuf, 7, &decodedbytes) < 0) {
                        DEBUG_SO(printf("Failed to decode any data to work with\n"));
                        return RULE_NOMATCH;
                    }
                    
                    DEBUG_SO(printf("Decoded %d bytes\n", decodedbytes));

                    // Make sure we have enough data to work with
                    if(decodedbytes >= 6) {
                        decodedbuf_ptr = decodedbuf;

                        // New format with content tag of 16 or 61 (both in the first byte)
                        DEBUG_SO(printf("Packet format: %01x\n", decodedbuf[0]));

                        // The top two bits are set, the lower six we want to be either 16 or 61.
                        // 0xC0 + 16 = 0xD0,  0xC0 + 61 = 0xFD
                        if((decodedbuf[0] == (uint8_t)0xD0) || (decodedbuf[0] == (uint8_t)0xFD)) {

                            if(decodedbuf[1] == 0xFF) {
                               decodedbuf_ptr = decodedbuf + 2;

                               tmpval =  *decodedbuf_ptr++;
                               tmpval |= *decodedbuf_ptr++ << 8;
                               tmpval |= *decodedbuf_ptr++ << 16;
                               tmpval |= *decodedbuf_ptr++ << 24;

                               DEBUG_SO(printf("Packet Size: 0x%08x\n", tmpval));

                               if((tmpval >= 0xF9FFFFFF) && (tmpval <= 0xFEFFFFFF)) {
                                  return RULE_MATCH;
                               }
                            }
                        }       
                    }
                }
            }
        }
    }
    return RULE_NOMATCH;
}
/* detection functions */
int rule13666eval(void *p) {
    const uint8_t *cursor_normal = 0, *cursor_offBmi;
    SFSnortPacket *sp = (SFSnortPacket *) p;

    const uint8_t *record_size_ptr, *beg_of_payload, *end_of_payload;

    uint32_t recordType, offBmi, bcSize;
    uint16_t bcWidth,bcHeight,bcPlanes,bcBitCount;
    uint64_t Value;  // For storing exploit calculations

    if(sp == NULL)
        return RULE_NOMATCH;

    if(sp->payload == NULL)
        return RULE_NOMATCH;
    
    // flow:established, to_client;
    if (checkFlow(p, rule13666options[0]->option_u.flowFlags) <= 0 )
        return RULE_NOMATCH;
    
    // flowbits:isset "file.emf";
    if (processFlowbits(p, rule13666options[1]->option_u.flowBit) <= 0)
        return RULE_NOMATCH;
    
    // content:" EMF|00 00 01 00|";
    if (contentMatch(p, rule13666options[2]->option_u.content, &cursor_normal) > 0) {
        // content:"|01 00 00 00|", offset -48, depth 4, relative;
        if (contentMatch(p, rule13666options[3]->option_u.content, &cursor_normal) > 0) {
            // byte_jump:size 4, relative, endian little;
            if (byteJump(p, rule13666options[4]->option_u.byte, &cursor_normal) > 0) {
                
                if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0)
                    return RULE_NOMATCH;

                // Now we're at the start of records.  Find the interesting ones.
                while(cursor_normal < end_of_payload) {
                     
                    // We point to record size so we're at the right state for the relative jump
                    // if it turns out the record doesn't have a BITMAPCOREHEADER. 
                    record_size_ptr = cursor_normal - 4;                    

                    // content:"|5E 00 00 00|", offset -8, depth 4, relative;  XXX /* EMR_CREATEDIBPATTERNBRUSHPT */
                    if (contentMatch(p, rule13666options[5]->option_u.content, &cursor_normal) > 0
                        // content:"|51 00 00 00|", offset -8, depth 4, relative; XXX /* EMR_STRETCHDIBITS */
                        || (contentMatch(p, rule13666options[6]->option_u.content, &cursor_normal) > 0))
                    {
                        recordType = *(cursor_normal - 4);
                        switch(recordType)
                        {
                            case EMR_CREATEDIBPATTERNBRUSHPT:
                                DEBUG_SO(printf("matched EMR_CREATEDIBPATTERNBRUSHPT\n");)
                                    
                                if (cursor_normal + 28 > end_of_payload) // Make sure there's enough room
                                    return RULE_NOMATCH;

                                // extract offset to BITMAPCOREHEADER.  can't use byte_jump because it could put us
                                // past end of packet since the "jump" actually starts from an earlier offset
                                cursor_offBmi = cursor_normal + 12;
                                offBmi = read_little_32(cursor_offBmi);
                                break;
                                    
                            case EMR_STRETCHDIBITS: 
                                DEBUG_SO(printf("matched EMR_STRETCHDIBITS\n");)

                                if (cursor_normal + 60 > end_of_payload) 
                                    return RULE_NOMATCH;
                        
                                // read offBmiSrc field 
                                cursor_offBmi = cursor_normal + 44;
                                offBmi = read_little_32(cursor_offBmi);
                                break;
                                
                            default:
                                DEBUG_SO(printf("This case must not happen\n");)
                                return RULE_NOMATCH;                                    
                        }
                                    
                        if (offBmi + cursor_normal - 4 < cursor_normal)  // check integer overflow
                            return RULE_NOMATCH;

                        // move cursor to the beginning of a device independent bitmap (DIB)
                        DEBUG_SO(printf("offBmi=0x%08x\n", offBmi);)  
                        cursor_normal += offBmi - 4; 
                                  
                        if(cursor_normal + 12 > end_of_payload)
                           return RULE_NOMATCH;
                                  
                        // match size of BITMAPCOREHEADER to determine if it's the proper structure
                        bcSize = read_little_32(cursor_normal);
                        cursor_normal += 4;
                        DEBUG_SO(printf("bcSize=0x%08x\n", bcSize);)
        
                        if (bcSize == 12) // checks BITMAPCOREHEADER
/* detection functions */
int rule16394eval(void *p) {
   const uint8_t *cursor_normal = 0;
   SFSnortPacket *sp = (SFSnortPacket *) p;

   const uint8_t *cursor_padata;

   BER_ELEMENT ber_element;
   int retval;

   uint32_t renew_realm_len;
   const uint8_t *renew_realm_str;

   uint32_t ticket_realm_len;
   const uint8_t *ticket_realm_str;

   DEBUG_SO(int i);

   DEBUG_SO(printf("rule16394eval enter\n"));

   if(sp == NULL)
      return RULE_NOMATCH;

   if(sp->payload == NULL)
      return RULE_NOMATCH;
   
   // flow:established, to_server;
   if(checkFlow(p, rule16394options[0]->option_u.flowFlags) <= 0)
      return RULE_NOMATCH;

   // For speed and for ease of programming, we take advantage of some content matches
   // here in some places at the expense of false negatives.
   // But they do also to give us a nice content match.

   // This content match skips over a few items then matches on Kerberos protocol
   // version (pvno) 5 and mesg type TGS-REQ (12)
   // content:"|A1 03 02 01 05 A2 03 02 01 0C|", payload raw, depth 22, fast_pattern;
   if(contentMatch(p, rule16394options[1]->option_u.content, &cursor_normal) <= 0)
      return RULE_NOMATCH;

   // Save the pointer so we can come back here, and we're going to jump ahead to make
   // sure this is a renew packet as well as store the pointer to and size of the
   // renewal realm
   cursor_padata = cursor_normal;

   BER_SKIP(0xa3); // This is a wrapper to ber_skip_element() that NOMATCH's on failure

   // We should now be at the start of the KDC_REQ_BODY

   BER_DATA(0xa4); // This is a wrapper to ber_point_to_data() that NOMATCH's on failure
   BER_DATA(0x30); 

   // We're going to cheat again here and do a quick content match.
   // Plus, this is our fast pattern match.
   // content:"|A0 07 03 05 00 00 00 00 02|", payload raw, depth 9, relative, fast_pattern;
   if(contentMatch(p, rule16394options[2]->option_u.content, &cursor_normal) <= 0)
      return RULE_NOMATCH;

   BER_DATA(0xa2);
 
   // Grab the piece of data we've been looking for
   retval = ber_get_element(sp, cursor_normal, &ber_element);

   // Type 0x1b is essentially a string.  Don't know why it's not type 0x04. 
   // Negative return value means error.  0 means 0 data bytes and therefore useless.
   // Also make sure there is the full amount of data present.
   if((retval <= 0) || (ber_element.type != 0x1b) || (retval < ber_element.data_len))
      return RULE_NOMATCH;

   renew_realm_len = ber_element.data_len;
   renew_realm_str = ber_element.data.data_ptr;

   DEBUG_SO(for(i=0; i<renew_realm_len; i++) printf("%c", renew_realm_str[i]); printf("\n"));

   // Now that we have our renew_realm info and we've verified the data is complete,
   // Let's go back to the beginning and get our ticket_realm information
   cursor_normal = cursor_padata;

   // This is a very long list.  Glad we made sure we were in a renewal packet and
   // had all of the data we need before we bother with this.  :)
   BER_DATA(0xa3);
   BER_DATA(0x30);
   BER_DATA(0x30); 
   BER_SKIP(0xa1);
   BER_DATA(0xa2);
   BER_DATA(0x04);
   BER_DATA(0x6e);
   BER_DATA(0x30);
   BER_SKIP(0xa0);
   BER_SKIP(0xa1);
   BER_SKIP(0xa2);
   BER_DATA(0xa3);
   BER_DATA(0x61);
   BER_DATA(0x30);
   BER_SKIP(0xa0);
   BER_DATA(0xa1);

   // Same code and checks as above for our ticket/home realm
   retval = ber_get_element(sp, cursor_normal, &ber_element);
   if((retval <= 0) || (ber_element.type != 0x1b) || (retval < ber_element.data_len))
      return RULE_NOMATCH;

   ticket_realm_len = ber_element.data_len;
   ticket_realm_str = ber_element.data.data_ptr;

   DEBUG_SO(for(i=0; i<ticket_realm_len; i++) printf("%c", ticket_realm_str[i]); printf("\n"));

   // Match if the realm names are different (either lens are diff or value is diff)
   if(ticket_realm_len != renew_realm_len || memcmp(ticket_realm_str, renew_realm_str, ticket_realm_len))
      return RULE_MATCH;

   return RULE_NOMATCH;
}
/* detection functions */
int rule16375eval(void *p) {
   const u_int8_t *cursor_normal = 0, *beg_of_payload, *end_of_payload;
   SFSnortPacket *sp = (SFSnortPacket *) p;

   BER_ELEMENT ber_element;

   const u_int8_t *end_of_string;
   u_int32_t namelen = 0;

   if(sp == NULL)
      return RULE_NOMATCH;

   if(sp->payload == NULL)
      return RULE_NOMATCH;
   
   // flow:established, to_server;
   if(checkFlow(p, rule16375options[0]->option_u.flowFlags) <= 0)
      return RULE_NOMATCH;

   // Initialize our pointer
   if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0)
      return RULE_NOMATCH;

   // Universal Sequence
   if(ber_point_to_data(sp, &cursor_normal, 0x30) < 0)
      return RULE_NOMATCH;

   // Message ID
   if(ber_skip_element(sp, &cursor_normal, 0x02) < 0)
      return RULE_NOMATCH;

   // Search Request
   if(ber_point_to_data(sp, &cursor_normal, 0x66) < 0)
      return RULE_NOMATCH;

   // Object
   if(ber_get_element(sp, cursor_normal, &ber_element) < 0)
      return RULE_NOMATCH;

   // Make sure it's a string
   if(ber_element.type != 0x04)
      return RULE_NOMATCH;

   // Move the cursor to the start of the string data
   cursor_normal = ber_element.data.data_ptr;

   end_of_string = cursor_normal + ber_element.data_len;

   // Check for end of buffer
   if(end_of_string > end_of_payload)
      end_of_string = end_of_payload;

   // Now we have cursor_normal pointing to the start of the
   // string and end_of_string set appropriately.  Now,
   // let's see how long the parameter names are.
   while(cursor_normal < end_of_string) {
      if(*cursor_normal != '=')
         namelen++;
      else {
         DEBUG_SO(printf("rule16375: namelen=%d\n", namelen));

         if(namelen > 100)
            return RULE_MATCH;

         // Length is fine.  Set back to zero.
         namelen = 0;

         // Now jump over the value
         while((cursor_normal < end_of_string) && (*cursor_normal != ','))
            cursor_normal++;
      }

      cursor_normal++;
   }

   // If we were in the middle of an overly long parameter name
   // when we ran out of data, match.
   if(namelen > 100)
      return RULE_MATCH;

   return RULE_NOMATCH;
}
int ruleIMAIL_LDAPeval(void *p) {
   u_int32_t current_byte = 0;
   u_int32_t width, value, lengthwidth;
   int retval;

   u_int32_t payload_len;

   const u_int8_t *cursor_normal, *beg_of_payload, *end_of_payload;

   SFSnortPacket *sp = (SFSnortPacket *) p;

   if(sp == NULL)
      return RULE_NOMATCH;

   if(sp->payload == NULL)
      return RULE_NOMATCH;

   /* call flow match */
   if (checkFlow(sp, ruleIMAIL_LDAPoptions[0]->option_u.flowFlags) <= 0 )
      return RULE_NOMATCH;

   /* call content match */
   if (contentMatch(sp, ruleIMAIL_LDAPoptions[1]->option_u.content, &cursor_normal) <= 0) {
      return RULE_NOMATCH;
   }

   if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0)
      return RULE_NOMATCH;

   payload_len = end_of_payload - beg_of_payload;

   if(payload_len < 10)   /* Minimum bind request length */
      return RULE_NOMATCH;

   /* our contentMatch already assures us the first byte is \x30, so just jump over it */
   current_byte++;

   /* Begin packet structure processing */
   /* Packet length (only care about width of the specifier) */
   if(beg_of_payload[current_byte] & 0x80) {
      current_byte += beg_of_payload[current_byte] & 0x0F;  /* Does imail do this properly? */
   }
   current_byte++;

   /* Message number (only care about width of the specifier) */
   if(payload_len < current_byte + 8) 
      return RULE_NOMATCH;

   if(beg_of_payload[current_byte] != 0x02) /* Int data type */
      return RULE_NOMATCH;
   current_byte++;

   /* int width specifier */
   if(beg_of_payload[current_byte] & 0x80) {
      width = beg_of_payload[current_byte] & 0x0F;
      current_byte++;

      if(payload_len < current_byte + width) 
         return RULE_NOMATCH;

      retval = process_val(&(beg_of_payload[current_byte]), width, &value);
      if(retval < 0) 
         return RULE_NOMATCH;  /* width is either 0 or > 4 */
      current_byte += width;   /* width of data width specifier */
      current_byte += value;   /* width of data itself */
   }  else {
      current_byte += beg_of_payload[current_byte] + 1;
   }

   /* Bind request */
   if(payload_len < current_byte + 5) 
      return RULE_NOMATCH;

   if(beg_of_payload[current_byte] != 0x60) 
      return RULE_NOMATCH;

   current_byte++;

   /* Message length  (only care about width of the specifier) */
   if(beg_of_payload[current_byte] & 0x80) {
      current_byte += beg_of_payload[current_byte] & 0x0F; 
   }
   current_byte++;

   /* ldap version */
   if(payload_len < current_byte + 3) 
      return RULE_NOMATCH;

   /* ldap version */
   if(beg_of_payload[current_byte] != 0x02) /* Int data type */
      return RULE_NOMATCH;
   current_byte++;

   /* Now check for funkiness with the version field */
   /* Get width of version number */
   if(beg_of_payload[current_byte] & 0x80) {

      /* Excess bits in the high nibble */
      if(beg_of_payload[current_byte] & 0x70)
         return RULE_MATCH;

      lengthwidth = beg_of_payload[current_byte] & 0x0F;
      current_byte++;
  
      if(payload_len < current_byte + lengthwidth) 
         return RULE_NOMATCH;

      retval = process_val(&(beg_of_payload[current_byte]), lengthwidth, &value);
      if(retval < 0)
          return RULE_MATCH; /* Something screwy's going on around here */
      width = value;
      current_byte += lengthwidth;
   }  else {
      width = beg_of_payload[current_byte];
      current_byte++;
   }

   if(payload_len < current_byte + width)
      return RULE_NOMATCH;

   /* In this case, if the version value is this fubar, trigger */
   retval = process_val(&(beg_of_payload[current_byte]), width, &value);
   if(retval < 0)
         return RULE_MATCH;

   /* LDAP version > 9 (currently, should be 1-3) */
   if(value > 9)
      return RULE_MATCH;

   return RULE_NOMATCH;
}
static int rule13921eval(void *p) {
   SFSnortPacket *sp = (SFSnortPacket *)p;

   const u_int8_t *cursor, *beg_of_payload, *end_of_payload;

   int16_t lm_x;  

   int n;  /* cruft */

   /* Data for holding our base64 data */
   u_int8_t decoded_data[16];
   u_int32_t num_bytes_extracted;


   /* General sanity checking */
  if(sp == NULL)
      return RULE_NOMATCH;

   if(sp->payload == NULL)
      return RULE_NOMATCH;

   if(getBuffer(sp, CONTENT_BUF_NORMALIZED, &beg_of_payload, &end_of_payload) <= 0)
      return RULE_NOMATCH;

   if((end_of_payload - beg_of_payload) < 32)
      return RULE_NOMATCH;

   /* call flow match */
   if (checkFlow(sp, rule13921options[0]->option_u.flowFlags) <= 0 )
      return RULE_NOMATCH;

   /* call first content match */
   if (contentMatch(sp, rule13921options[1]->option_u.content, &cursor) <= 0) {
      return RULE_NOMATCH;
   }

   /* call second content match */
   if (contentMatch(sp, rule13921options[2]->option_u.content, &cursor) <= 0) {
      return RULE_NOMATCH;
   }

   /* Decode the part containing "/P.\x03/" to ensure the proper header and message type */
   n = base64decode(&(beg_of_payload[8]), 4, decoded_data, sizeof(decoded_data), &num_bytes_extracted);

   if((n < 0) || (num_bytes_extracted < 3))
      return RULE_NOMATCH;

   /* verify contents */
   if((decoded_data[0] != 'P') || (decoded_data[2] != 0x03))
      return RULE_NOMATCH;

   /* Now decode the part containing LM_X */
   n = base64decode(&(beg_of_payload[24]), 8, decoded_data, sizeof(decoded_data), &num_bytes_extracted);

   if((n < 0) || (num_bytes_extracted < 6))
      return RULE_NOMATCH;

   /* Extract LM_X, a signed 16-bit entity in little-endian format */
   lm_x = decoded_data[2];
   lm_x += decoded_data[3] << 8; 

   if((lm_x < 0) || (lm_x > 56))
      return RULE_MATCH;

   return RULE_NOMATCH;
}