(root)/
glibc-2.38/
resolv/
tst-resolv-trustad.c
       1  /* Test the behavior of the trust-ad option.
       2     Copyright (C) 2019-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 <resolv.h>
      20  #include <stdlib.h>
      21  #include <string.h>
      22  #include <support/check.h>
      23  #include <support/check_nss.h>
      24  #include <support/resolv_test.h>
      25  #include <support/support.h>
      26  
      27  /* This controls properties of the response.  volatile because
      28     __res_send is incorrectly declared as __THROW.  */
      29  static volatile unsigned char response_number;
      30  static volatile bool response_ad_bit;
      31  static volatile bool query_ad_bit;
      32  
      33  static void
      34  response (const struct resolv_response_context *ctx,
      35            struct resolv_response_builder *b,
      36            const char *qname, uint16_t qclass, uint16_t qtype)
      37  {
      38    TEST_COMPARE (qclass, C_IN);
      39    TEST_COMPARE (qtype, T_A);
      40    TEST_COMPARE_STRING (qname, "www.example");
      41  
      42    HEADER header;
      43    memcpy (&header, ctx->query_buffer, sizeof (header));
      44    TEST_COMPARE (header.ad, query_ad_bit);
      45  
      46    struct resolv_response_flags flags = { .ad = response_ad_bit, };
      47    resolv_response_init (b, flags);
      48    resolv_response_add_question (b, qname, qclass, qtype);
      49    resolv_response_section (b, ns_s_an);
      50    resolv_response_open_record (b, qname, qclass, T_A, 0x12345678);
      51    char addr[4] = { 192, 0, 2, response_number };
      52    resolv_response_add_data (b, addr, sizeof (addr));
      53    resolv_response_close_record (b);
      54  }
      55  
      56  static void
      57  check_answer (const unsigned char *buffer, size_t buffer_length,
      58                bool expected_ad)
      59  {
      60    HEADER header;
      61    TEST_VERIFY (buffer_length > sizeof (header));
      62    memcpy (&header, buffer, sizeof (header));
      63    TEST_COMPARE (0, header.aa);
      64    TEST_COMPARE (expected_ad, header.ad);
      65    TEST_COMPARE (0, header.opcode);
      66    TEST_COMPARE (1, header.qr);
      67    TEST_COMPARE (0, header.rcode);
      68    TEST_COMPARE (1, header.rd);
      69    TEST_COMPARE (0, header.tc);
      70    TEST_COMPARE (1, ntohs (header.qdcount));
      71    TEST_COMPARE (1, ntohs (header.ancount));
      72    TEST_COMPARE (0, ntohs (header.nscount));
      73    TEST_COMPARE (0, ntohs (header.arcount));
      74  
      75    char *description = xasprintf ("response=%d ad=%d",
      76                                   response_number, expected_ad);
      77    char *expected = xasprintf ("name: www.example\n"
      78                                "address: 192.0.2.%d\n", response_number);
      79    check_dns_packet (description, buffer, buffer_length, expected);
      80    free (expected);
      81    free (description);
      82  }
      83  
      84  static int
      85  do_test (void)
      86  {
      87    struct resolv_test *aux = resolv_test_start
      88      ((struct resolv_redirect_config)
      89       {
      90         .response_callback = response,
      91       });
      92  
      93    /* By default, the resolver is not trusted, and the AD bit is
      94       cleared.  */
      95  
      96    static const unsigned char hand_crafted_query[] =
      97      {
      98       10, 11,                    /* Transaction ID.  */
      99       1, 0x20,                   /* Query with RD, AD flags.  */
     100       0, 1,                      /* One question.  */
     101       0, 0, 0, 0, 0, 0,          /* The other sections are empty.  */
     102       3, 'w', 'w', 'w', 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0,
     103       0, T_A,                    /* A query.  */
     104       0, 1,                      /* Class IN.  */
     105      };
     106  
     107    ++response_number;
     108    response_ad_bit = false;
     109  
     110    unsigned char buffer[512];
     111    memset (buffer, 255, sizeof (buffer));
     112    query_ad_bit = true;
     113    int ret = res_send (hand_crafted_query, sizeof (hand_crafted_query),
     114                        buffer, sizeof (buffer));
     115    TEST_VERIFY (ret > 0);
     116    check_answer (buffer, ret, false);
     117  
     118    ++response_number;
     119    memset (buffer, 255, sizeof (buffer));
     120    query_ad_bit = false;
     121    ret = res_query ("www.example", C_IN, T_A, buffer, sizeof (buffer));
     122    TEST_VERIFY (ret > 0);
     123    check_answer (buffer, ret, false);
     124    response_ad_bit = true;
     125  
     126    response_ad_bit = true;
     127  
     128    ++response_number;
     129    query_ad_bit = true;
     130    ret = res_send (hand_crafted_query, sizeof (hand_crafted_query),
     131                    buffer, sizeof (buffer));
     132    TEST_VERIFY (ret > 0);
     133    check_answer (buffer, ret, false);
     134  
     135    ++response_number;
     136    memset (buffer, 255, sizeof (buffer));
     137    query_ad_bit = false;
     138    ret = res_query ("www.example", C_IN, T_A, buffer, sizeof (buffer));
     139    TEST_VERIFY (ret > 0);
     140    check_answer (buffer, ret, false);
     141  
     142    /* No AD bit set in generated queries.  */
     143    memset (buffer, 255, sizeof (buffer));
     144    ret = res_mkquery (QUERY, "www.example", C_IN, T_A,
     145                       (const unsigned char *) "", 0, NULL,
     146                       buffer, sizeof (buffer));
     147    HEADER header;
     148    memcpy (&header, buffer, sizeof (header));
     149    TEST_VERIFY (!header.ad);
     150  
     151    /* With RES_TRUSTAD, the AD bit is passed through if it set in the
     152       response.  It is also included in queries.  */
     153  
     154    _res.options |= RES_TRUSTAD;
     155    query_ad_bit = true;
     156  
     157    response_ad_bit = false;
     158  
     159    ++response_number;
     160    memset (buffer, 255, sizeof (buffer));
     161    ret = res_send (hand_crafted_query, sizeof (hand_crafted_query),
     162                    buffer, sizeof (buffer));
     163    TEST_VERIFY (ret > 0);
     164    check_answer (buffer, ret, false);
     165  
     166    ++response_number;
     167    memset (buffer, 255, sizeof (buffer));
     168    ret = res_query ("www.example", C_IN, T_A, buffer, sizeof (buffer));
     169    TEST_VERIFY (ret > 0);
     170    check_answer (buffer, ret, false);
     171  
     172    response_ad_bit = true;
     173  
     174    ++response_number;
     175    memset (buffer, 0, sizeof (buffer));
     176    ret = res_send (hand_crafted_query, sizeof (hand_crafted_query),
     177                    buffer, sizeof (buffer));
     178    TEST_VERIFY (ret > 0);
     179    check_answer (buffer, ret, true);
     180  
     181    ++response_number;
     182    memset (buffer, 0, sizeof (buffer));
     183    ret = res_query ("www.example", C_IN, T_A, buffer, sizeof (buffer));
     184    TEST_VERIFY (ret > 0);
     185    check_answer (buffer, ret, true);
     186  
     187    /* AD bit set in generated queries.  */
     188    memset (buffer, 0, sizeof (buffer));
     189    ret = res_mkquery (QUERY, "www.example", C_IN, T_A,
     190                       (const unsigned char *) "", 0, NULL,
     191                       buffer, sizeof (buffer));
     192    memcpy (&header, buffer, sizeof (header));
     193    TEST_VERIFY (header.ad);
     194  
     195    resolv_test_end (aux);
     196  
     197    return 0;
     198  }
     199  
     200  #include <support/test-driver.c>