Ejemplo n.º 1
0
Archivo: mdns.c Proyecto: agb861/STM32F
static void dns_get_next_question( dns_message_iterator_t* iter, dns_question_t* q, dns_name_t* name )
{
	// Set the name pointers and then skip it
	name->start_of_name   = (u8*) iter->iter;
	name->start_of_packet = (u8*) iter->header;
	dns_skip_name( iter );

	// Read the type and class
	q->question_type  = dns_read_uint16( iter );
	q->question_class = dns_read_uint16( iter );
}
Ejemplo n.º 2
0
int dns_msg_parse(u_char* msg, int len, dns_parse_fct fct, void* data)
{
  u_char* begin = msg;
  u_char* p = begin + HEADER_OFFSET;
  u_char* end = msg + len;

  if(p >= end) return -1;

  // skip query section
  for(int i=0; i<dns_msg_count(begin,dns_s_qd); i++){
    // query name
    if(dns_skip_name(&p,end) < 0) return -1;
    // skip query type+class
    if((p += 4) > end) return -1;
  }
  
  dns_record rr;
  for(int s = (int)dns_s_an; s < (int)__dns_max_sections; ++s){
    for(int i=0; i<dns_msg_count(begin,(dns_section_type)s); i++){

      // expand name
      if(dns_expand_name(&p,begin,end,(u_char*)rr.name,NS_MAXDNAME) < 0) return -1;

      // at least 8 bytes for type+class+ttl left?
      if((p + 8) > end) return -1;
      
      rr.type = dns_get_16(p);
      p += 2;

      rr.rr_class = dns_get_16(p);
      p += 2;

      rr.ttl = dns_get_32(p);
      p+= 4;

      // fetch rdata len
      if(p+2 > end) return -1;
      rr.rdata_len = *(p++) << 8;
      rr.rdata_len |= *(p++);
      rr.rdata = p;

      // skip rdata
      if((p += rr.rdata_len) > end) return -1;

      // call provided function
      if(fct && (*fct)(&rr,(dns_section_type)s,begin,end,data)) return -1;
    }
  }

  return 0;
}
Ejemplo n.º 3
0
/**
 * Find an RR in a reply packet corresponding to our query
 *
 * @v dns		DNS request
 * @v reply		DNS reply
 * @ret rr		DNS RR, or NULL if not found
 */
static union dns_rr_info * dns_find_rr ( struct dns_request *dns,
					 const struct dns_header *reply ) {
	int i, cmp;
	const char *p = ( ( char * ) reply ) + sizeof ( struct dns_header );
	union dns_rr_info *rr_info;

	/* Skip over the questions section */
	for ( i = ntohs ( reply->qdcount ) ; i > 0 ; i-- ) {
		p = dns_skip_name ( p ) + sizeof ( struct dns_query_info );
	}

	/* Process the answers section */
	for ( i = ntohs ( reply->ancount ) ; i > 0 ; i-- ) {
		cmp = dns_name_cmp ( dns, reply, p );
		p = dns_skip_name ( p );
		rr_info = ( ( union dns_rr_info * ) p );
		if ( cmp == 0 )
			return rr_info;
		p += ( sizeof ( rr_info->common ) +
		       ntohs ( rr_info->common.rdlength ) );
	}

	return NULL;
}
Ejemplo n.º 4
0
static int
dns_parse_packet(struct dns_state *s, byte *p, unsigned int plen)
{
  byte *end = p + plen;
  unsigned int i, j, len;
  unsigned int UNUSED x;

#if 0
  /* Dump the packet */
  for (i=0; i<plen; i++)
    {
      if (!(i%16)) printf("%04x:", i);
      printf(" %02x", p[i]);
      if ((i%16)==15 || i==plen-1) putchar('\n');
    }
#endif

  GET32(x);				/* ID and flags are ignored */
  for (i=0; i<DNS_NUM_SECTIONS; i++)
    GET16(s->counts[i]);
  for (i=0; i<DNS_NUM_SECTIONS; i++)
    {
      s->sections[i] = p;
      for (j=0; j < s->counts[i]; j++)
	{
	  p = dns_skip_name(p, end);	/* Name */
	  if (!p)
	    goto err;
	  GET32(x);			/* Type and class */
	  if (i != DNS_SEC_QUESTION)
	    {
	      GET32(x);			/* TTL */
	      GET16(len);		/* Length of data */
	      p += len;
	      if (p > end)
		goto err;
	    }
	}
    }
  s->sections[i] = p;
  return 0;

err:
  return -1;
}
Ejemplo n.º 5
0
static int
dns_parse_rr(struct dns_state *s)
{
  byte *p = s->sec_ptr;
  byte *end = s->sec_end;

  if (p == end)
    return 0;
  p = dns_skip_name(p, end);
  if (!p)
    goto err;
  GET16(s->rr_type);
  GET16(s->rr_class);
  GET32(s->rr_ttl);
  GET16(s->rr_len);
  s->rr_data = p;
  s->sec_ptr = p + s->rr_len;
  return 1;

err:
  return -1;
}
Ejemplo n.º 6
0
/* detection functions */
int rule15734eval(void *p) {
   const u_int8_t *cursor_raw = 0, *end_of_payload;
   SFSnortPacket *sp = (SFSnortPacket *) p;

   const u_int8_t *junkptr; // for getBuffer()

   u_int16_t num_updates;
   u_int16_t num_addtl_rrs;
   u_int16_t data_len;
   u_int16_t record_type;

   // cruft
   int i;

   if(sp == NULL)
      return RULE_NOMATCH;

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

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

   DEBUG_WRAP(printf("passed content\n"));

   if(getBuffer(p, CONTENT_BUF_NORMALIZED, &junkptr, &end_of_payload) <= 0)
      return RULE_NOMATCH;

   if(cursor_raw + 25 >= end_of_payload)
      return RULE_NOMATCH;

   num_updates = *cursor_raw++ << 8;
   num_updates |= *cursor_raw++;

   DEBUG_WRAP(printf("num_updates=%d\n", num_updates));

   if(num_updates == 0)
      return RULE_NOMATCH;

   num_addtl_rrs = *cursor_raw++ << 8;
   num_addtl_rrs |= *cursor_raw++;

   DEBUG_WRAP(printf("num_addtl_rrs=%d\n", num_addtl_rrs));

   // Zone section (we force this to be one entry by content match)
   if(dns_skip_name(&cursor_raw, end_of_payload) <= 0)
      return RULE_NOMATCH;

   if(cursor_raw + 18 >= end_of_payload)
      return RULE_NOMATCH;

   DEBUG_WRAP(printf("SOA: 0x%02x%02x Class: 0x%02x%02x\n", cursor_raw[0], cursor_raw[1],cursor_raw[2],cursor_raw[3]));

   // Verify Type: SOA and Class: IN
   if(memcmp(cursor_raw, "\x00\x06\x00\x01", 4))
      return RULE_NOMATCH;

   cursor_raw += 4;

   // Prerequisites section (we force this to be one entry by content match)
   if(dns_skip_name(&cursor_raw, end_of_payload) <= 0)
      return RULE_NOMATCH;

   if(cursor_raw + 14 >= end_of_payload)
      return RULE_NOMATCH;

   // FP reduction.  Microsoft clients do ANY-ANY
   // Better solution is to make sure EXTERNAL_NET is set correctly
   // Verify Type: ANY Class: IN
   if(memcmp(cursor_raw, "\x00\xff\x00\x01", 4))
      return RULE_NOMATCH;

   cursor_raw += 8; // Skip over class and type and Skip TTL

   data_len = *cursor_raw++ << 8;
   data_len |= *cursor_raw++;     
   cursor_raw += data_len;   

   // Updates (YAY!!)
   DEBUG_WRAP(printf("Checking updates\n"));
   for(i = 0; i < num_updates; i++) {
      DEBUG_WRAP(printf("Checking update %d...", i));

      if(dns_skip_name(&cursor_raw, end_of_payload) <= 0)
         return RULE_NOMATCH;

      if(cursor_raw + 2 >= end_of_payload)
         return RULE_NOMATCH;
   
      record_type = *cursor_raw++ << 8;
      record_type |= *cursor_raw++;

      DEBUG_WRAP(printf("record_type 0x%04x\n", record_type));  
      // Alert if we see an update of type ANY (0x00FF) 
      if(record_type == 0x00FF)
         return RULE_MATCH;

      if(cursor_raw + 8 >= end_of_payload)
         return RULE_NOMATCH;

      cursor_raw += 6;

      data_len = *cursor_raw++ << 8;
      data_len |= *cursor_raw++;   
      cursor_raw += data_len;
   }

   // Currently, we don't care about the Additional RRs section, but if it turns
   // out we get false positives, we can add the requirement that there be no
   // TSIG (0x00fa) records aka unauthenticated update requests

   return RULE_NOMATCH;
}
static int DetectBindTkeyDos(const uint8_t *cursor_normal, const uint8_t *end_of_buffer) {
   const uint8_t *query_name, *additional_name, *check;
   uint16_t flags, num_of_answers, answer_data_len,
            num_of_additional, additional_rr_type,
            additional_data_len;
   unsigned int i, query_name_len, additional_name_len;

   // check if we can read flags (2 bytes)
   // skip question number (2 bytes)
   // read answer number (2 bytes)
   // skip authority RR number (2 bytes)
   // and read additional RR number (2 bytes)
   if(cursor_normal + 10 > end_of_buffer)
      return RULE_NOMATCH;

   flags = read_big_16_inc(cursor_normal);

   // flags
   //
   // mask:
   // 0b1111101000001111 = 0xFA0F
   //   ^^   ^^^    ^   
   //   ||   |||    |   
   //   ||   |||    `- reply code (0000 = no error)
   //   ||   ||`- recursion and others
   //   ||   |`- truncated (0 = not truncated)
   //   ||   `- authoritative
   //   |`- opcode (0000 = standard query)
   //   `- response (0 = query)
   //
   if((flags & 0xFA0F) != 0)
      return RULE_NOMATCH;

   // skip question number (we limit it to 1)
   cursor_normal += 2;

   // get the number of answers
   num_of_answers = read_big_16_inc(cursor_normal);

   // if num_of_answers > 5, bail
   if(num_of_answers > 5)
      return RULE_NOMATCH;

   // skip authority RR number
   cursor_normal += 2;

   // get the number of additional RRs
   num_of_additional = read_big_16_inc(cursor_normal);

   // if num_of_additional > 5, bail
   if(num_of_additional > 5)
      return RULE_NOMATCH;

   // store start of query name
   query_name = cursor_normal;

   // skip question Name (we limit to 1)
   if(dns_skip_name(&cursor_normal, end_of_buffer) != DNS_SUCCESS)
      return RULE_NOMATCH;

   // store size of query name
   query_name_len = cursor_normal - query_name;

   // only compare up to 255 bytes 
   if(query_name_len > 255)
      return RULE_NOMATCH;

   // check that we can read the query type 
   if(cursor_normal + 2 > end_of_buffer)
      return RULE_NOMATCH;

   // verify that the query type is TKEY (0x00F9)
   // checked "backwards" to drop out faster since first byte is usually 0x00
   if((cursor_normal[1] != 0xF9) || (cursor_normal[0] != 0x00))
      return RULE_NOMATCH;

   // skip type & class
   cursor_normal += 4;

   // go to the end of the answer section (up to 5)
   for(i=0; i < num_of_answers; i++)
   {
      // skip answer
      if(dns_skip_name(&cursor_normal, end_of_buffer) != DNS_SUCCESS)
         return RULE_NOMATCH;

      // skip type, class, TTL
      cursor_normal += 8;

      // make sure we can read the answer data length
      if(cursor_normal + 2 > end_of_buffer)
         return RULE_NOMATCH;

      // read the answer data length
      answer_data_len = read_big_16_inc(cursor_normal);

      // jump the answer data length
      check = cursor_normal + answer_data_len;

      // integer overflow check
      if(check < cursor_normal)
         return RULE_NOMATCH;

      cursor_normal = check;
   }

   // parse additional RRs (up to 5)
   for(i=0; i < num_of_additional; i++)
   {
      // store start of additional name
      additional_name = cursor_normal;

      // skip Additional RR Name
      if(dns_skip_name(&cursor_normal, end_of_buffer) != DNS_SUCCESS)
         return RULE_NOMATCH;

      // calculate size of additional RR name
      additional_name_len = cursor_normal - additional_name;

      // verify we can read Type (2 bytes)
      // skip class & TTL (or EDNS data) (6 bytes)
      // and read data length (2 bytes)
      if(cursor_normal + 10 > end_of_buffer)
         return RULE_NOMATCH;

      // read the additional RR type
      additional_rr_type = read_big_16_inc(cursor_normal);

      // skip class & TTL (or EDNS data)
      cursor_normal += 6;

      // read additional RR data length
      additional_data_len = read_big_16_inc(cursor_normal);

      // jump the additional RR data length
      check = cursor_normal + additional_data_len;

      // integer overflow check
      if(check < cursor_normal)
         return RULE_NOMATCH;

      cursor_normal = check;

      // verify type is NOT TKEY (1st condition of vuln)
      if(additional_rr_type == 0x00F9)
         continue;

      // if we skipped a pointer to the Query, then the
      // Additional RR Name is equal to the Query Name
      // (2nd condition of the vuln), alert.
      if(additional_name_len == 2)
         if((additional_name[0] == 0xC0) && (additional_name[1] == 0x0C))
            return RULE_MATCH;   

      // verify dns_skip_name skipped an Additional RR Name
      // with the same size as the Query Name
      //
      // (if the sizes are different, they can't be the same)
      if(query_name_len != additional_name_len)
         continue;

      // finally, verify the Additional RR Name is
      // equal to the Query Name for uncompressed names
      // (2nd condition of vuln), alert.
      if(memcmp(query_name, additional_name, query_name_len) == 0)
         return RULE_MATCH;
   }

   return RULE_NOMATCH;
}