/* 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 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 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;
}