"Fossies" - the Fresh Open Source Software Archive

Member "c-ares-1.17.2/src/lib/ares_parse_caa_reply.c" (8 Aug 2021, 5502 Bytes) of package /linux/misc/dns/c-ares-1.17.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ares_parse_caa_reply.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.17.1_vs_1.17.2.

    1 
    2 /* Copyright 2020 by <danny.sonnenschein@platynum.ch>
    3  *
    4  * Permission to use, copy, modify, and distribute this
    5  * software and its documentation for any purpose and without
    6  * fee is hereby granted, provided that the above copyright
    7  * notice appear in all copies and that both that copyright
    8  * notice and this permission notice appear in supporting
    9  * documentation, and that the name of M.I.T. not be used in
   10  * advertising or publicity pertaining to distribution of the
   11  * software without specific, written prior permission.
   12  * M.I.T. makes no representations about the suitability of
   13  * this software for any purpose.  It is provided "as is"
   14  * without express or implied warranty.
   15  */
   16 
   17 #include "ares_setup.h"
   18 
   19 #ifdef HAVE_NETINET_IN_H
   20 #  include <netinet/in.h>
   21 #endif
   22 #ifdef HAVE_NETDB_H
   23 #  include <netdb.h>
   24 #endif
   25 #ifdef HAVE_ARPA_INET_H
   26 #  include <arpa/inet.h>
   27 #endif
   28 
   29 #include "ares_nameser.h"
   30 
   31 #ifdef HAVE_STRINGS_H
   32 #  include <strings.h>
   33 #endif
   34 
   35 #include "ares.h"
   36 #include "ares_dns.h"
   37 #include "ares_data.h"
   38 #include "ares_private.h"
   39 
   40 int
   41 ares_parse_caa_reply (const unsigned char *abuf, int alen,
   42                       struct ares_caa_reply **caa_out)
   43 {
   44   unsigned int qdcount, ancount, i;
   45   const unsigned char *aptr;
   46   const unsigned char *strptr;
   47   int status, rr_type, rr_class, rr_len;
   48   long len;
   49   char *hostname = NULL, *rr_name = NULL;
   50   struct ares_caa_reply *caa_head = NULL;
   51   struct ares_caa_reply *caa_last = NULL;
   52   struct ares_caa_reply *caa_curr;
   53 
   54   /* Set *caa_out to NULL for all failure cases. */
   55   *caa_out = NULL;
   56 
   57   /* Give up if abuf doesn't have room for a header. */
   58   if (alen < HFIXEDSZ)
   59     return ARES_EBADRESP;
   60 
   61   /* Fetch the question and answer count from the header. */
   62   qdcount = DNS_HEADER_QDCOUNT (abuf);
   63   ancount = DNS_HEADER_ANCOUNT (abuf);
   64   if (qdcount != 1)
   65     return ARES_EBADRESP;
   66   if (ancount == 0)
   67     return ARES_ENODATA;
   68 
   69   /* Expand the name from the question, and skip past the question. */
   70   aptr = abuf + HFIXEDSZ;
   71   status = ares_expand_name (aptr, abuf, alen, &hostname, &len);
   72   if (status != ARES_SUCCESS)
   73     return status;
   74 
   75   if (aptr + len + QFIXEDSZ > abuf + alen)
   76     {
   77       ares_free (hostname);
   78       return ARES_EBADRESP;
   79     }
   80   aptr += len + QFIXEDSZ;
   81 
   82   /* Examine each answer resource record (RR) in turn. */
   83   for (i = 0; i < ancount; i++)
   84     {
   85       /* Decode the RR up to the data field. */
   86       status = ares_expand_name (aptr, abuf, alen, &rr_name, &len);
   87       if (status != ARES_SUCCESS)
   88         {
   89           break;
   90         }
   91       aptr += len;
   92       if (aptr + RRFIXEDSZ > abuf + alen)
   93         {
   94           status = ARES_EBADRESP;
   95           break;
   96         }
   97       rr_type = DNS_RR_TYPE (aptr);
   98       rr_class = DNS_RR_CLASS (aptr);
   99       rr_len = DNS_RR_LEN (aptr);
  100       aptr += RRFIXEDSZ;
  101       if (aptr + rr_len > abuf + alen)
  102         {
  103           status = ARES_EBADRESP;
  104           break;
  105         }
  106 
  107       /* Check if we are really looking at a CAA record */
  108       if ((rr_class == C_IN || rr_class == C_CHAOS) && rr_type == T_CAA)
  109         {
  110           strptr = aptr;
  111 
  112           /* Allocate storage for this CAA answer appending it to the list */
  113           caa_curr = ares_malloc_data(ARES_DATATYPE_CAA_REPLY);
  114           if (!caa_curr)
  115             {
  116               status = ARES_ENOMEM;
  117               break;
  118             }
  119           if (caa_last)
  120             {
  121               caa_last->next = caa_curr;
  122             }
  123           else
  124             {
  125               caa_head = caa_curr;
  126             }
  127           caa_last = caa_curr;
  128           if (rr_len < 2)
  129             {
  130               status = ARES_EBADRESP;
  131               break;
  132             }
  133           caa_curr->critical = (int)*strptr++;
  134           caa_curr->plength = (int)*strptr++;
  135           if (caa_curr->plength <= 0 || (int)caa_curr->plength >= rr_len - 2)
  136             {
  137               status = ARES_EBADRESP;
  138               break;
  139             }
  140           caa_curr->property = ares_malloc (caa_curr->plength + 1/* Including null byte */);
  141           if (caa_curr->property == NULL)
  142             {
  143               status = ARES_ENOMEM;
  144               break;
  145             }
  146           memcpy ((char *) caa_curr->property, strptr, caa_curr->plength);
  147           /* Make sure we NULL-terminate */
  148           caa_curr->property[caa_curr->plength] = 0;
  149           strptr += caa_curr->plength;
  150 
  151           caa_curr->length = rr_len - caa_curr->plength - 2;
  152           if (caa_curr->length <= 0)
  153             {
  154               status = ARES_EBADRESP;
  155               break;
  156             }
  157           caa_curr->value = ares_malloc (caa_curr->length + 1/* Including null byte */);
  158           if (caa_curr->value == NULL)
  159             {
  160               status = ARES_ENOMEM;
  161               break;
  162             }
  163           memcpy ((char *) caa_curr->value, strptr, caa_curr->length);
  164           /* Make sure we NULL-terminate */
  165           caa_curr->value[caa_curr->length] = 0;
  166         }
  167 
  168       /* Propagate any failures */
  169       if (status != ARES_SUCCESS)
  170         {
  171           break;
  172         }
  173 
  174       /* Don't lose memory in the next iteration */
  175       ares_free (rr_name);
  176       rr_name = NULL;
  177 
  178       /* Move on to the next record */
  179       aptr += rr_len;
  180     }
  181 
  182   if (hostname)
  183     ares_free (hostname);
  184   if (rr_name)
  185     ares_free (rr_name);
  186 
  187   /* clean up on error */
  188   if (status != ARES_SUCCESS)
  189     {
  190       if (caa_head)
  191         ares_free_data (caa_head);
  192       return status;
  193     }
  194 
  195   /* everything looks fine, return the data */
  196   *caa_out = caa_head;
  197 
  198   return ARES_SUCCESS;
  199 }