(root)/
glibc-2.38/
resolv/
tst-ns_rr_cursor.c
       1  /* Tests for resource record parsing.
       2     Copyright (C) 2022-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <arpa/nameser.h>
      20  #include <string.h>
      21  #include <support/check.h>
      22  #include <support/next_to_fault.h>
      23  
      24  /* Reference packet for packet parsing.  */
      25  static const unsigned char valid_packet[] =
      26    { 0x11, 0x12, 0x13, 0x14,
      27      0x00, 0x01,               /* Question count.  */
      28      0x00, 0x02,               /* Answer count.  */
      29      0x21, 0x22, 0x23, 0x24,   /* Other counts (not actually in packet).  */
      30      3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0,
      31      0x00, 0x1c,               /* Question type: AAAA.  */
      32      0x00, 0x01,               /* Question class: IN.  */
      33      0xc0, 0x0c,               /* Compression reference to QNAME.  */
      34      0x00, 0x1c,               /* Record type: AAAA.  */
      35      0x00, 0x01,               /* Record class: IN.  */
      36      0x12, 0x34, 0x56, 0x78,   /* Record TTL.  */
      37      0x00, 0x10,               /* Record data length (16 bytes).  */
      38      0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
      39      0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, /* IPv6 address.  */
      40      0xc0, 0x0c,               /* Compression reference to QNAME.  */
      41      0x00, 0x1c,               /* Record type: AAAA.  */
      42      0x00, 0x01,               /* Record class: IN.  */
      43      0x11, 0x33, 0x55, 0x77,   /* Record TTL.  */
      44      0x00, 0x10,               /* Record data length (16 bytes).  */
      45      0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
      46      0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, /* IPv6 address.  */
      47    };
      48  
      49  /* Special offsets in valid_packet.  */
      50  enum
      51    {
      52      offset_of_first_record = 29,
      53      offset_of_second_record = 57,
      54    };
      55  
      56  /* Check that parsing valid_packet succeeds.  */
      57  static void
      58  test_valid (void)
      59  {
      60    struct ns_rr_cursor c;
      61    TEST_VERIFY_EXIT (__ns_rr_cursor_init (&c, valid_packet,
      62                                           sizeof (valid_packet)));
      63    TEST_COMPARE (ns_rr_cursor_rcode (&c), 4);
      64    TEST_COMPARE (ns_rr_cursor_ancount (&c), 2);
      65    TEST_COMPARE (ns_rr_cursor_nscount (&c), 0x2122);
      66    TEST_COMPARE (ns_rr_cursor_adcount (&c), 0x2324);
      67    TEST_COMPARE_BLOB (ns_rr_cursor_qname (&c), 13, &valid_packet[12], 13);
      68    TEST_COMPARE (ns_rr_cursor_qtype (&c), T_AAAA);
      69    TEST_COMPARE (ns_rr_cursor_qclass (&c), C_IN);
      70    TEST_COMPARE (c.current - valid_packet, offset_of_first_record);
      71  
      72    struct ns_rr_wire r;
      73    TEST_VERIFY_EXIT (__ns_rr_cursor_next (&c, &r));
      74    TEST_COMPARE (r.rtype, T_AAAA);
      75    TEST_COMPARE (r.rclass, C_IN);
      76    TEST_COMPARE (r.ttl, 0x12345678);
      77    TEST_COMPARE_BLOB (r.rdata, r.rdlength,
      78                       "\x90\x91\x92\x93\x94\x95\x96\x97"
      79                       "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f", 16);
      80    TEST_COMPARE (c.current - valid_packet, offset_of_second_record);
      81    TEST_VERIFY_EXIT (__ns_rr_cursor_next (&c, &r));
      82    TEST_COMPARE (r.rtype, T_AAAA);
      83    TEST_COMPARE (r.rclass, C_IN);
      84    TEST_COMPARE (r.ttl, 0x11335577);
      85    TEST_COMPARE_BLOB (r.rdata, r.rdlength,
      86                       "\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7"
      87                       "\xa8\xa9\xaa\xab\xac\xad\xae\xaf", 16);
      88    TEST_VERIFY (c.current == c.end);
      89  }
      90  
      91  /* Check that trying to parse a packet with a compressed QNAME fails.  */
      92  static void
      93  test_compressed_qname (void)
      94  {
      95    static const unsigned char packet[] =
      96      { 0x11, 0x12, 0x13, 0x14,
      97        0x00, 0x01,               /* Question count.  */
      98        0x00, 0x00,               /* Answer count.  */
      99        0x00, 0x00, 0x00, 0x00,   /* Other counts.  */
     100        3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0xc0, 0x04,
     101        0x00, 0x01,               /* Question type: A.  */
     102        0x00, 0x01,               /* Question class: IN.  */
     103      };
     104  
     105    struct ns_rr_cursor c;
     106    TEST_VERIFY_EXIT (!__ns_rr_cursor_init (&c, packet, sizeof (packet)));
     107  }
     108  
     109  /* Check that trying to parse a packet with two questions fails.  */
     110  static void
     111  test_two_questions (void)
     112  {
     113    static const unsigned char packet[] =
     114      { 0x11, 0x12, 0x13, 0x14,
     115        0x00, 0x02,               /* Question count.  */
     116        0x00, 0x00,               /* Answer count.  */
     117        0x00, 0x00, 0x00, 0x00,   /* Other counts.  */
     118        3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0xc0, 0x04,
     119        0x00, 0x01,               /* Question type: A.  */
     120        0x00, 0x01,               /* Question class: IN.  */
     121        3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0xc0, 0x04,
     122        0x00, 0x1c,               /* Question type: AAAA.  */
     123        0x00, 0x01,               /* Question class: IN.  */
     124      };
     125  
     126    struct ns_rr_cursor c;
     127    TEST_VERIFY_EXIT (!__ns_rr_cursor_init (&c, packet, sizeof (packet)));
     128  }
     129  
     130  /* Used to check that parsing truncated packets does not over-read.  */
     131  static struct support_next_to_fault ntf;
     132  
     133  /* Truncated packet in the second resource record.  */
     134  static void
     135  test_truncated_one_rr (size_t length)
     136  {
     137    unsigned char *end = (unsigned char *) ntf.buffer - ntf.length;
     138    unsigned char *start = end - length;
     139  
     140    /* Produce the truncated packet.  */
     141    memcpy (start, valid_packet, length);
     142  
     143    struct ns_rr_cursor c;
     144    TEST_VERIFY_EXIT (__ns_rr_cursor_init (&c, start, length));
     145    TEST_COMPARE (ns_rr_cursor_rcode (&c), 4);
     146    TEST_COMPARE (ns_rr_cursor_ancount (&c), 2);
     147    TEST_COMPARE (ns_rr_cursor_nscount (&c), 0x2122);
     148    TEST_COMPARE (ns_rr_cursor_adcount (&c), 0x2324);
     149    TEST_COMPARE_BLOB (ns_rr_cursor_qname (&c), 13, &valid_packet[12], 13);
     150    TEST_COMPARE (ns_rr_cursor_qtype (&c), T_AAAA);
     151    TEST_COMPARE (ns_rr_cursor_qclass (&c), C_IN);
     152    TEST_COMPARE (c.current - start, offset_of_first_record);
     153  
     154    struct ns_rr_wire r;
     155    TEST_VERIFY_EXIT (__ns_rr_cursor_next (&c, &r));
     156    TEST_COMPARE (r.rtype, T_AAAA);
     157    TEST_COMPARE (r.rclass, C_IN);
     158    TEST_COMPARE (r.ttl, 0x12345678);
     159    TEST_COMPARE_BLOB (r.rdata, r.rdlength,
     160                       "\x90\x91\x92\x93\x94\x95\x96\x97"
     161                       "\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f", 16);
     162    TEST_COMPARE (c.current - start, offset_of_second_record);
     163    TEST_VERIFY (!__ns_rr_cursor_next (&c, &r));
     164  }
     165  
     166  /* Truncated packet in the first resource record.  */
     167  static void
     168  test_truncated_no_rr (size_t length)
     169  {
     170    unsigned char *end = (unsigned char *) ntf.buffer - ntf.length;
     171    unsigned char *start = end - length;
     172  
     173    /* Produce the truncated packet.  */
     174    memcpy (start, valid_packet, length);
     175  
     176    struct ns_rr_cursor c;
     177    TEST_VERIFY_EXIT (__ns_rr_cursor_init (&c, start, length));
     178    TEST_COMPARE (ns_rr_cursor_rcode (&c), 4);
     179    TEST_COMPARE (ns_rr_cursor_ancount (&c), 2);
     180    TEST_COMPARE (ns_rr_cursor_nscount (&c), 0x2122);
     181    TEST_COMPARE (ns_rr_cursor_adcount (&c), 0x2324);
     182    TEST_COMPARE_BLOB (ns_rr_cursor_qname (&c), 13, &valid_packet[12], 13);
     183    TEST_COMPARE (ns_rr_cursor_qtype (&c), T_AAAA);
     184    TEST_COMPARE (ns_rr_cursor_qclass (&c), C_IN);
     185    TEST_COMPARE (c.current - start, offset_of_first_record);
     186  
     187    struct ns_rr_wire r;
     188    TEST_VERIFY (!__ns_rr_cursor_next (&c, &r));
     189  }
     190  
     191  /* Truncated packet before first resource record.  */
     192  static void
     193  test_truncated_before_rr (size_t length)
     194  {
     195    unsigned char *end = (unsigned char *) ntf.buffer - ntf.length;
     196    unsigned char *start = end - length;
     197  
     198    /* Produce the truncated packet.  */
     199    memcpy (start, valid_packet, length);
     200  
     201    struct ns_rr_cursor c;
     202    TEST_VERIFY_EXIT (!__ns_rr_cursor_init (&c, start, length));
     203  }
     204  
     205  static int
     206  do_test (void)
     207  {
     208    ntf = support_next_to_fault_allocate (sizeof (valid_packet));
     209  
     210    test_valid ();
     211    test_compressed_qname ();
     212    test_two_questions ();
     213  
     214    for (int length = offset_of_second_record; length < sizeof (valid_packet);
     215         ++length)
     216      test_truncated_one_rr (length);
     217    for (int length = offset_of_first_record; length < offset_of_second_record;
     218         ++length)
     219      test_truncated_no_rr (length);
     220    for (int length = 0; length < offset_of_first_record; ++length)
     221      test_truncated_before_rr (length);
     222  
     223    support_next_to_fault_free (&ntf);
     224    return 0;
     225  }
     226  
     227  #include <support/test-driver.c>