Home | History | Annotate | Download | only in unit
      1 /***************************************************************************
      2  *                                  _   _ ____  _
      3  *  Project                     ___| | | |  _ \| |
      4  *                             / __| | | | |_) | |
      5  *                            | (__| |_| |  _ <| |___
      6  *                             \___|\___/|_| \_\_____|
      7  *
      8  * Copyright (C) 2018 - 2019, Daniel Stenberg, <daniel (at) haxx.se>, et al.
      9  *
     10  * This software is licensed as described in the file COPYING, which
     11  * you should have received as part of this distribution. The terms
     12  * are also available at https://curl.haxx.se/docs/copyright.html.
     13  *
     14  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     15  * copies of the Software, and permit persons to whom the Software is
     16  * furnished to do so, under the terms of the COPYING file.
     17  *
     18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     19  * KIND, either express or implied.
     20  *
     21  ***************************************************************************/
     22 #include "curlcheck.h"
     23 
     24 #include "doh.h"
     25 
     26 static CURLcode unit_setup(void)
     27 {
     28   return CURLE_OK;
     29 }
     30 
     31 static void unit_stop(void)
     32 {
     33 
     34 }
     35 
     36 #ifdef USE_NGHTTP2
     37 #define DNS_PREAMBLE "\x00\x00\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00"
     38 #define LABEL_TEST "\x04\x74\x65\x73\x74"
     39 #define LABEL_HOST "\x04\x68\x6f\x73\x74"
     40 #define LABEL_NAME "\x04\x6e\x61\x6d\x65"
     41 #define DNSA_TYPE "\x01"
     42 #define DNSAAAA_TYPE "\x1c"
     43 #define DNSA_EPILOGUE "\x00\x00" DNSA_TYPE "\x00\x01"
     44 #define DNSAAAA_EPILOGUE "\x00\x00" DNSAAAA_TYPE "\x00\x01"
     45 
     46 #define DNS_Q1 DNS_PREAMBLE LABEL_TEST LABEL_HOST LABEL_NAME DNSA_EPILOGUE
     47 #define DNS_Q2 DNS_PREAMBLE LABEL_TEST LABEL_HOST LABEL_NAME DNSAAAA_EPILOGUE
     48 
     49 struct dohrequest {
     50   /* input */
     51   const char *name;
     52   DNStype type;
     53 
     54   /* output */
     55   const char *packet;
     56   size_t size;
     57   int rc;
     58 };
     59 
     60 
     61 static struct dohrequest req[] = {
     62   {"test.host.name", DNS_TYPE_A, DNS_Q1, sizeof(DNS_Q1)-1, 0 },
     63   {"test.host.name", DNS_TYPE_AAAA, DNS_Q2, sizeof(DNS_Q2)-1, 0 },
     64   {"zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
     65    ".host.name",
     66    DNS_TYPE_AAAA, NULL, 0, DOH_DNS_BAD_LABEL }
     67 };
     68 
     69 struct dohresp {
     70   /* input */
     71   const char *packet;
     72   size_t size;
     73   DNStype type;
     74 
     75   /* output */
     76   int rc;
     77   const char *out;
     78 };
     79 
     80 #define DNS_FOO_EXAMPLE_COM                                          \
     81   "\x00\x00\x01\x00\x00\x01\x00\x01\x00\x00\x00\x00\x03\x66\x6f\x6f" \
     82   "\x07\x65\x78\x61\x6d\x70\x6c\x65\x03\x63\x6f\x6d\x00\x00\x01\x00" \
     83   "\x01\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x37\x00\x04\x7f\x00\x00" \
     84   "\x01"
     85 
     86 static const char full49[] = DNS_FOO_EXAMPLE_COM;
     87 
     88 static struct dohresp resp[] = {
     89   {"\x00\x00", 2, DNS_TYPE_A, DOH_TOO_SMALL_BUFFER, NULL },
     90   {"\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01", 12,
     91    DNS_TYPE_A, DOH_DNS_BAD_ID, NULL },
     92   {"\x00\x00\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01", 12,
     93    DNS_TYPE_A, DOH_DNS_BAD_RCODE, NULL },
     94   {"\x00\x00\x01\x00\x00\x01\x00\x01\x00\x00\x00\x00\x03\x66\x6f\x6f", 16,
     95    DNS_TYPE_A, DOH_DNS_OUT_OF_RANGE, NULL },
     96   {"\x00\x00\x01\x00\x00\x01\x00\x01\x00\x00\x00\x00\x03\x66\x6f\x6f\x00", 17,
     97    DNS_TYPE_A, DOH_DNS_OUT_OF_RANGE, NULL },
     98   {"\x00\x00\x01\x00\x00\x01\x00\x01\x00\x00\x00\x00\x03\x66\x6f\x6f\x00"
     99    "\x00\x01\x00\x01", 21,
    100    DNS_TYPE_A, DOH_DNS_OUT_OF_RANGE, NULL },
    101   {"\x00\x00\x01\x00\x00\x01\x00\x01\x00\x00\x00\x00\x03\x66\x6f\x6f\x00"
    102    "\x00\x01\x00\x01"
    103    "\x04", 18,
    104    DNS_TYPE_A, DOH_DNS_OUT_OF_RANGE, NULL },
    105 
    106   {"\x00\x00\x01\x00\x00\x01\x00\x01\x00\x00\x00\x00\x04\x63\x75\x72"
    107    "\x6c\x04\x63\x75\x72\x6c\x00\x00\x05\x00\x01\xc0\x0c\x00\x05\x00"
    108    "\x01\x00\x00\x00\x37\x00\x11\x08\x61\x6e\x79\x77\x68\x65\x72\x65"
    109    "\x06\x72\x65\x61\x6c\x6c\x79\x00", 56,
    110    DNS_TYPE_A, DOH_OK, "anywhere.really "},
    111 
    112   {DNS_FOO_EXAMPLE_COM, 49, DNS_TYPE_A, DOH_OK, "127.0.0.1 "},
    113 
    114   {"\x00\x00\x01\x00\x00\x01\x00\x01\x00\x00\x00\x00\x04\x61\x61\x61"
    115    "\x61\x07\x65\x78\x61\x6d\x70\x6c\x65\x03\x63\x6f\x6d\x00\x00\x1c"
    116    "\x00\x01\xc0\x0c\x00\x1c\x00\x01\x00\x00\x00\x37\x00\x10\x20\x20"
    117    "\x20\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x20", 62,
    118    DNS_TYPE_AAAA, DOH_OK,
    119    "2020:2020:0000:0000:0000:0000:0000:2020 " },
    120 
    121   {"\x00\x00\x01\x00\x00\x01\x00\x01\x00\x00\x00\x00\x04\x63\x75\x72"
    122    "\x6c\x04\x63\x75\x72\x6c\x00\x00\x05\x00\x01\xc0\x0c\x00\x05\x00"
    123    "\x01\x00\x00\x00\x37\x00"
    124    "\x07\x03\x61\x6e\x79\xc0\x27\x00", 46,
    125    DNS_TYPE_A, DOH_DNS_LABEL_LOOP, NULL},
    126 
    127   /* packet with NSCOUNT == 1 */
    128   {"\x00\x00\x01\x00\x00\x01\x00\x01\x00\x01\x00\x00\x04\x61\x61\x61"
    129    "\x61\x07\x65\x78\x61\x6d\x70\x6c\x65\x03\x63\x6f\x6d\x00\x00\x1c"
    130    "\x00\x01\xc0\x0c\x00\x1c\x00\x01\x00\x00\x00\x37\x00\x10\x20\x20"
    131    "\x20\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x20"
    132    LABEL_TEST LABEL_HOST LABEL_NAME DNSAAAA_EPILOGUE "\x00\x00\x00\x01"
    133    "\00\x04\x01\x01\x01\x01", /* RDDATA */
    134 
    135    62 + 30,
    136    DNS_TYPE_AAAA, DOH_OK,
    137    "2020:2020:0000:0000:0000:0000:0000:2020 " },
    138 
    139   /* packet with ARCOUNT == 1 */
    140   {"\x00\x00\x01\x00\x00\x01\x00\x01\x00\x00\x00\x01\x04\x61\x61\x61"
    141    "\x61\x07\x65\x78\x61\x6d\x70\x6c\x65\x03\x63\x6f\x6d\x00\x00\x1c"
    142    "\x00\x01\xc0\x0c\x00\x1c\x00\x01\x00\x00\x00\x37\x00\x10\x20\x20"
    143    "\x20\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x20"
    144    LABEL_TEST LABEL_HOST LABEL_NAME DNSAAAA_EPILOGUE "\x00\x00\x00\x01"
    145    "\00\x04\x01\x01\x01\x01", /* RDDATA */
    146 
    147    62 + 30,
    148    DNS_TYPE_AAAA, DOH_OK,
    149    "2020:2020:0000:0000:0000:0000:0000:2020 " },
    150 
    151 };
    152 
    153 UNITTEST_START
    154 {
    155   size_t size = 0;
    156   unsigned char buffer[256];
    157   size_t i;
    158   unsigned char *p;
    159   for(i = 0; i < sizeof(req) / sizeof(req[0]); i++) {
    160     int rc = doh_encode(req[i].name, req[i].type,
    161                         buffer, sizeof(buffer), &size);
    162     if(rc != req[i].rc) {
    163       fprintf(stderr, "req %zu: Expected return code %d got %d\n", i,
    164               req[i].rc, rc);
    165       return 1;
    166     }
    167     else if(size != req[i].size) {
    168       fprintf(stderr, "req %zu: Expected size %zu got %zu\n", i,
    169               req[i].size, size);
    170       fprintf(stderr, "DNS encode made: %s\n", hexdump(buffer, size));
    171       return 2;
    172     }
    173     else if(req[i].packet && memcmp(req[i].packet, buffer, size)) {
    174       fprintf(stderr, "DNS encode made: %s\n", hexdump(buffer, size));
    175       fprintf(stderr, "... instead of: %s\n",
    176              hexdump((unsigned char *)req[i].packet, size));
    177       return 3;
    178     }
    179   }
    180 
    181   for(i = 0; i < sizeof(resp) / sizeof(resp[0]); i++) {
    182     struct dohentry d;
    183     int rc;
    184     char *ptr;
    185     size_t len;
    186     int u;
    187     memset(&d, 0, sizeof(d));
    188     rc = doh_decode((unsigned char *)resp[i].packet, resp[i].size,
    189                     resp[i].type, &d);
    190     if(rc != resp[i].rc) {
    191       fprintf(stderr, "resp %zu: Expected return code %d got %d\n", i,
    192               resp[i].rc, rc);
    193       return 4;
    194     }
    195     len = sizeof(buffer);
    196     ptr = (char *)buffer;
    197     for(u = 0; u < d.numaddr; u++) {
    198       size_t o;
    199       struct dohaddr *a;
    200       a = &d.addr[u];
    201       if(resp[i].type == DNS_TYPE_A) {
    202         p = &a->ip.v4[0];
    203         msnprintf(ptr, len, "%u.%u.%u.%u ", p[0], p[1], p[2], p[3]);
    204         o = strlen(ptr);
    205         len -= o;
    206         ptr += o;
    207       }
    208       else {
    209         int j;
    210         for(j = 0; j < 16; j += 2) {
    211           size_t l;
    212           msnprintf(ptr, len, "%s%02x%02x", j?":":"", a->ip.v6[j],
    213                    a->ip.v6[j + 1]);
    214           l = strlen(ptr);
    215           len -= l;
    216           ptr += l;
    217         }
    218         msnprintf(ptr, len, " ");
    219         len--;
    220         ptr++;
    221       }
    222     }
    223     for(u = 0; u < d.numcname; u++) {
    224       size_t o;
    225       msnprintf(ptr, len, "%s ", d.cname[u].alloc);
    226       o = strlen(ptr);
    227       len -= o;
    228       ptr += o;
    229     }
    230     de_cleanup(&d);
    231     if(resp[i].out && strcmp((char *)buffer, resp[i].out)) {
    232       fprintf(stderr, "resp %zu: Expected %s got %s\n", i,
    233               resp[i].out, buffer);
    234       return 1;
    235     }
    236   }
    237 
    238   {
    239     /* pass all sizes into the decoder until full */
    240     for(i = 0; i < sizeof(full49)-1; i++) {
    241       struct dohentry d;
    242       int rc;
    243       memset(&d, 0, sizeof(d));
    244       rc = doh_decode((unsigned char *)full49, i, DNS_TYPE_A, &d);
    245       if(!rc) {
    246         /* none of them should work */
    247         fprintf(stderr, "%zu: %d\n", i, rc);
    248         return 5;
    249       }
    250     }
    251     /* and try all pieces from the other end of the packet */
    252     for(i = 1; i < sizeof(full49); i++) {
    253       struct dohentry d;
    254       int rc;
    255       memset(&d, 0, sizeof(d));
    256       rc = doh_decode((unsigned char *)&full49[i], sizeof(full49)-i-1,
    257                       DNS_TYPE_A, &d);
    258       if(!rc) {
    259         /* none of them should work */
    260         fprintf(stderr, "2 %zu: %d\n", i, rc);
    261         return 7;
    262       }
    263     }
    264     {
    265       int rc;
    266       struct dohentry d;
    267       struct dohaddr *a;
    268       memset(&d, 0, sizeof(d));
    269       rc = doh_decode((unsigned char *)full49, sizeof(full49)-1,
    270                       DNS_TYPE_A, &d);
    271       fail_if(d.numaddr != 1, "missing address");
    272       a = &d.addr[0];
    273       p = &a->ip.v4[0];
    274       msnprintf((char *)buffer, sizeof(buffer),
    275                 "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);
    276       if(rc || strcmp((char *)buffer, "127.0.0.1")) {
    277         fprintf(stderr, "bad address decoded: %s, rc == %d\n", buffer, rc);
    278         return 7;
    279       }
    280       fail_if(d.numcname, "bad cname counter");
    281     }
    282   }
    283 }
    284 UNITTEST_STOP
    285 
    286 #else /* USE_NGHTTP2 */
    287 UNITTEST_START
    288 {
    289   return 1; /* nothing to do, just fail */
    290 }
    291 UNITTEST_STOP
    292 
    293 
    294 #endif
    295