(root)/
glibc-2.38/
resolv/
tst-resolv-network.c
       1  /* Test getnetbyname and getnetbyaddr.
       2     Copyright (C) 2016-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 <netdb.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  #include <support/xmemstream.h>
      27  
      28  static void
      29  send_ptr (struct resolv_response_builder *b,
      30            const char *qname, uint16_t qclass, uint16_t qtype,
      31            const char *alias)
      32  {
      33    resolv_response_init (b, (struct resolv_response_flags) {});
      34    resolv_response_add_question (b, qname, qclass, qtype);
      35    resolv_response_section (b, ns_s_an);
      36    resolv_response_open_record (b, qname, qclass, T_PTR, 0);
      37    resolv_response_add_name (b, alias);
      38    resolv_response_close_record (b);
      39  }
      40  
      41  static void
      42  handle_code (const struct resolv_response_context *ctx,
      43               struct resolv_response_builder *b,
      44               const char *qname, uint16_t qclass, uint16_t qtype,
      45               int code)
      46  {
      47    switch (code)
      48      {
      49      case 1:
      50        send_ptr (b, qname, qclass, qtype, "1.in-addr.arpa");
      51        break;
      52      case 2:
      53        send_ptr (b, qname, qclass, qtype, "2.1.in-addr.arpa");
      54        break;
      55      case 3:
      56        send_ptr (b, qname, qclass, qtype, "3.2.1.in-addr.arpa");
      57        break;
      58      case 4:
      59        send_ptr (b, qname, qclass, qtype, "4.3.2.1.in-addr.arpa");
      60        break;
      61      case 5:
      62        /* Test multiple PTR records.  */
      63        resolv_response_init (b, (struct resolv_response_flags) {});
      64        resolv_response_add_question (b, qname, qclass, qtype);
      65        resolv_response_section (b, ns_s_an);
      66        resolv_response_open_record (b, qname, qclass, T_PTR, 0);
      67        resolv_response_add_name (b, "127.in-addr.arpa");
      68        resolv_response_close_record (b);
      69        resolv_response_open_record (b, qname, qclass, T_PTR, 0);
      70        resolv_response_add_name (b, "0.in-addr.arpa");
      71        resolv_response_close_record (b);
      72        break;
      73      case 6:
      74        /* Test skipping of RRSIG record.  */
      75        resolv_response_init (b, (struct resolv_response_flags) { });
      76        resolv_response_add_question (b, qname, qclass, qtype);
      77        resolv_response_section (b, ns_s_an);
      78  
      79        resolv_response_open_record (b, qname, qclass, T_PTR, 0);
      80        resolv_response_add_name (b, "127.in-addr.arpa");
      81        resolv_response_close_record (b);
      82  
      83        resolv_response_open_record (b, qname, qclass, 46 /* RRSIG */, 0);
      84        {
      85          char buf[500];
      86          memset (buf, 0x3f, sizeof (buf));
      87          resolv_response_add_data (b, buf, sizeof (buf));
      88        }
      89        resolv_response_close_record (b);
      90  
      91        resolv_response_open_record (b, qname, qclass, T_PTR, 0);
      92        resolv_response_add_name (b, "0.in-addr.arpa");
      93        resolv_response_close_record (b);
      94        break;
      95      case 7:
      96        /* Test CNAME handling.  */
      97        resolv_response_init (b, (struct resolv_response_flags) { });
      98        resolv_response_add_question (b, qname, qclass, qtype);
      99        resolv_response_section (b, ns_s_an);
     100        resolv_response_open_record (b, qname, qclass, T_CNAME, 0);
     101        resolv_response_add_name (b, "cname.example");
     102        resolv_response_close_record (b);
     103        resolv_response_open_record (b, "cname.example", qclass, T_PTR, 0);
     104        resolv_response_add_name (b, "4.3.2.1.in-addr.arpa");
     105        resolv_response_close_record (b);
     106        break;
     107  
     108      case 100:
     109        resolv_response_init (b, (struct resolv_response_flags) { .rcode = 0, });
     110        resolv_response_add_question (b, qname, qclass, qtype);
     111        break;
     112      case 101:
     113        resolv_response_init (b, (struct resolv_response_flags)
     114                              { .rcode = NXDOMAIN, });
     115        resolv_response_add_question (b, qname, qclass, qtype);
     116        break;
     117      case 102:
     118        resolv_response_init (b, (struct resolv_response_flags) {.rcode = SERVFAIL});
     119        resolv_response_add_question (b, qname, qclass, qtype);
     120        break;
     121      case 103:
     122        /* Check response length matching.  */
     123        if (!ctx->tcp)
     124          {
     125            resolv_response_init (b, (struct resolv_response_flags) {.tc = true});
     126            resolv_response_add_question (b, qname, qclass, qtype);
     127          }
     128        else
     129          {
     130            resolv_response_init (b, (struct resolv_response_flags) {.ancount = 1});
     131            resolv_response_add_question (b, qname, qclass, qtype);
     132            resolv_response_section (b, ns_s_an);
     133            resolv_response_open_record (b, qname, qclass, T_PTR, 0);
     134            resolv_response_add_name (b, "127.in-addr.arpa");
     135            resolv_response_close_record (b);
     136            resolv_response_open_record (b, qname, qclass, T_PTR, 0);
     137            resolv_response_add_name (b, "example");
     138            resolv_response_close_record (b);
     139  
     140            resolv_response_open_record (b, qname, qclass, T_PTR, 0);
     141            size_t to_fill = 65535 - resolv_response_length (b)
     142              - 2 /* length, "n" */ - 2 /* compression reference */
     143              - 2 /* RR type */;
     144            for (size_t i = 0; i < to_fill; ++i)
     145              resolv_response_add_data (b, "", 1);
     146            resolv_response_close_record (b);
     147            resolv_response_add_name (b, "n.example");
     148            uint16_t rrtype = htons (T_PTR);
     149            resolv_response_add_data (b, &rrtype, sizeof (rrtype));
     150          }
     151        break;
     152      case 104:
     153        send_ptr (b, qname, qclass, qtype, "host.example");
     154        break;
     155      default:
     156        FAIL_EXIT1 ("invalid QNAME: %s (code %d)", qname, code);
     157      }
     158  }
     159  
     160  static void
     161  response (const struct resolv_response_context *ctx,
     162            struct resolv_response_builder *b,
     163            const char *qname, uint16_t qclass, uint16_t qtype)
     164  {
     165    int code;
     166    if (strstr (qname, "in-addr.arpa") == NULL)
     167      {
     168        char *tail;
     169        if (sscanf (qname, "code%d.%ms", &code, &tail) != 2
     170            || strcmp (tail, "example") != 0)
     171          FAIL_EXIT1 ("invalid QNAME: %s", qname);
     172        free (tail);
     173        handle_code (ctx, b, qname, qclass, qtype, code);
     174      }
     175    else
     176      {
     177        /* Reverse lookup.  */
     178        int components[4];
     179        char *tail;
     180        if (sscanf (qname, "%d.%d.%d.%d.%ms",
     181                    components, components + 1, components + 2, components + 3,
     182                    &tail) != 5
     183            || strcmp (tail, "in-addr.arpa") != 0)
     184          FAIL_EXIT1 ("invalid QNAME: %s", qname);
     185        free (tail);
     186        handle_code (ctx, b, qname, qclass, qtype, components[3]);
     187      }
     188  }
     189  
     190  static void
     191  check_reverse (int code, const char *expected)
     192  {
     193    char *query = xasprintf ("code=%d", code);
     194    check_netent (query, getnetbyaddr (code, AF_INET), expected);
     195    free (query);
     196  }
     197  
     198  /* Test for CVE-2016-3075.  */
     199  static void
     200  check_long_name (void)
     201  {
     202    struct xmemstream mem;
     203    xopen_memstream (&mem);
     204  
     205    char label[65];
     206    memset (label, 'x', 63);
     207    label[63] = '.';
     208    label[64] = '\0';
     209    for (unsigned i = 0; i < 64 * 1024 * 1024 / strlen (label); ++i)
     210      fprintf (mem.out, "%s", label);
     211  
     212    xfclose_memstream (&mem);
     213  
     214    check_netent ("long name", getnetbyname (mem.buffer),
     215                  "error: NO_RECOVERY\n");
     216  
     217    free (mem.buffer);
     218  }
     219  
     220  static int
     221  do_test (void)
     222  {
     223    struct resolv_test *obj = resolv_test_start
     224      ((struct resolv_redirect_config)
     225       {
     226         .response_callback = response
     227       });
     228  
     229    /* Lookup by name, success cases.  */
     230    check_netent ("code1.example", getnetbyname ("code1.example"),
     231                  "alias: 1.in-addr.arpa\n"
     232                  "net: 0x00000001\n");
     233    check_netent ("code2.example", getnetbyname ("code2.example"),
     234                  "alias: 2.1.in-addr.arpa\n"
     235                  "net: 0x00000102\n");
     236    check_netent ("code3.example", getnetbyname ("code3.example"),
     237                  "alias: 3.2.1.in-addr.arpa\n"
     238                  "net: 0x00010203\n");
     239    check_netent ("code4.example", getnetbyname ("code4.example"),
     240                  "alias: 4.3.2.1.in-addr.arpa\n"
     241                  "net: 0x01020304\n");
     242    check_netent ("code5.example", getnetbyname ("code5.example"),
     243                  "alias: 127.in-addr.arpa\n"
     244                  "alias: 0.in-addr.arpa\n"
     245                  "net: 0x0000007f\n");
     246    check_netent ("code6.example", getnetbyname ("code6.example"),
     247                  "alias: 127.in-addr.arpa\n"
     248                  "alias: 0.in-addr.arpa\n"
     249                  "net: 0x0000007f\n");
     250    check_netent ("code7.example", getnetbyname ("code7.example"),
     251                  "alias: 4.3.2.1.in-addr.arpa\n"
     252                  "net: 0x01020304\n");
     253  
     254    /* Lookup by name, failure cases.  */
     255    check_netent ("code100.example", getnetbyname ("code100.example"),
     256                  "error: NO_ADDRESS\n");
     257    check_netent ("code101.example", getnetbyname ("code101.example"),
     258                  "error: HOST_NOT_FOUND\n");
     259    check_netent ("code102.example", getnetbyname ("code102.example"),
     260                  "error: TRY_AGAIN\n");
     261    check_netent ("code103.example", getnetbyname ("code103.example"),
     262                  "error: NO_RECOVERY\n");
     263    /* Test bug #17630.  */
     264    check_netent ("code104.example", getnetbyname ("code104.example"),
     265                  "error: TRY_AGAIN\n");
     266  
     267    /* Lookup by address, success cases.  */
     268    check_reverse (1,
     269                   "name: 1.in-addr.arpa\n"
     270                   "net: 0x00000001\n");
     271    check_reverse (2,
     272                   "name: 2.1.in-addr.arpa\n"
     273                   "net: 0x00000002\n");
     274    check_reverse (3,
     275                   "name: 3.2.1.in-addr.arpa\n"
     276                   "net: 0x00000003\n");
     277    check_reverse (4,
     278                   "name: 4.3.2.1.in-addr.arpa\n"
     279                   "net: 0x00000004\n");
     280    check_reverse (5,
     281                   "name: 127.in-addr.arpa\n"
     282                   "alias: 0.in-addr.arpa\n"
     283                   "net: 0x00000005\n");
     284    check_reverse (6,
     285                   "name: 127.in-addr.arpa\n"
     286                   "alias: 0.in-addr.arpa\n"
     287                   "net: 0x00000006\n");
     288    check_reverse (7,
     289                   "name: 4.3.2.1.in-addr.arpa\n"
     290                   "net: 0x00000007\n");
     291  
     292    /* Lookup by address, failure cases.  */
     293    check_reverse (100,
     294                   "error: NO_ADDRESS\n");
     295    check_reverse (101,
     296                   "error: HOST_NOT_FOUND\n");
     297    check_reverse (102,
     298                   "error: TRY_AGAIN\n");
     299    check_reverse (103,
     300                   "error: NO_RECOVERY\n");
     301  
     302    check_long_name ();
     303  
     304    resolv_test_end (obj);
     305  
     306    return 0;
     307  }
     308  
     309  #include <support/test-driver.c>