Annotation of embedaddon/dnsmasq/src/dnssec.c, revision 1.1

1.1     ! misho       1: /* dnssec.c is Copyright (c) 2012 Giovanni Bajo <rasky@develer.com>
        !             2:            and Copyright (c) 2012-2014 Simon Kelley
        !             3: 
        !             4:    This program is free software; you can redistribute it and/or modify
        !             5:    it under the terms of the GNU General Public License as published by
        !             6:    the Free Software Foundation; version 2 dated June, 1991, or
        !             7:    (at your option) version 3 dated 29 June, 2007.
        !             8: 
        !             9:    This program is distributed in the hope that it will be useful,
        !            10:    but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            11:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            12:    GNU General Public License for more details.
        !            13: 
        !            14:    You should have received a copy of the GNU General Public License
        !            15:    along with this program.  If not, see <http://www.gnu.org/licenses/>.
        !            16: */
        !            17: 
        !            18: #include "dnsmasq.h"
        !            19: 
        !            20: #ifdef HAVE_DNSSEC
        !            21: 
        !            22: #include <nettle/rsa.h>
        !            23: #include <nettle/dsa.h>
        !            24: #ifndef NO_NETTLE_ECC
        !            25: #  include <nettle/ecdsa.h>
        !            26: #  include <nettle/ecc-curve.h>
        !            27: #endif
        !            28: #include <nettle/nettle-meta.h>
        !            29: #include <gmp.h>
        !            30: 
        !            31: #define SERIAL_UNDEF  -100
        !            32: #define SERIAL_EQ        0
        !            33: #define SERIAL_LT       -1
        !            34: #define SERIAL_GT        1
        !            35: 
        !            36: /* http://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
        !            37: static char *ds_digest_name(int digest)
        !            38: {
        !            39:   switch (digest)
        !            40:     {
        !            41:     case 1: return "sha1";
        !            42:     case 2: return "sha256";
        !            43:     case 3: return "gosthash94";
        !            44:     case 4: return "sha384";
        !            45:     default: return NULL;
        !            46:     }
        !            47: }
        !            48:  
        !            49: /* http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
        !            50: static char *algo_digest_name(int algo)
        !            51: {
        !            52:   switch (algo)
        !            53:     {
        !            54:     case 1: return "md5";
        !            55:     case 3: return "sha1";
        !            56:     case 5: return "sha1";
        !            57:     case 6: return "sha1";
        !            58:     case 7: return "sha1";
        !            59:     case 8: return "sha256";
        !            60:     case 10: return "sha512";
        !            61:     case 12: return "gosthash94";
        !            62:     case 13: return "sha256";
        !            63:     case 14: return "sha384";
        !            64:     default: return NULL;
        !            65:     }
        !            66: }
        !            67:       
        !            68: /* Find pointer to correct hash function in nettle library */
        !            69: static const struct nettle_hash *hash_find(char *name)
        !            70: {
        !            71:   int i;
        !            72:   
        !            73:   if (!name)
        !            74:     return NULL;
        !            75:   
        !            76:   for (i = 0; nettle_hashes[i]; i++)
        !            77:     {
        !            78:       if (strcmp(nettle_hashes[i]->name, name) == 0)
        !            79:        return nettle_hashes[i];
        !            80:     }
        !            81: 
        !            82:   return NULL;
        !            83: }
        !            84: 
        !            85: /* expand ctx and digest memory allocations if necessary and init hash function */
        !            86: static int hash_init(const struct nettle_hash *hash, void **ctxp, unsigned char **digestp)
        !            87: {
        !            88:   static void *ctx = NULL;
        !            89:   static unsigned char *digest = NULL;
        !            90:   static unsigned int ctx_sz = 0;
        !            91:   static unsigned int digest_sz = 0;
        !            92: 
        !            93:   void *new;
        !            94: 
        !            95:   if (ctx_sz < hash->context_size)
        !            96:     {
        !            97:       if (!(new = whine_malloc(hash->context_size)))
        !            98:        return 0;
        !            99:       if (ctx)
        !           100:        free(ctx);
        !           101:       ctx = new;
        !           102:       ctx_sz = hash->context_size;
        !           103:     }
        !           104:   
        !           105:   if (digest_sz < hash->digest_size)
        !           106:     {
        !           107:       if (!(new = whine_malloc(hash->digest_size)))
        !           108:        return 0;
        !           109:       if (digest)
        !           110:        free(digest);
        !           111:       digest = new;
        !           112:       digest_sz = hash->digest_size;
        !           113:     }
        !           114: 
        !           115:   *ctxp = ctx;
        !           116:   *digestp = digest;
        !           117: 
        !           118:   hash->init(ctx);
        !           119: 
        !           120:   return 1;
        !           121: }
        !           122:   
        !           123: static int rsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
        !           124:                      unsigned char *digest, int algo)
        !           125: {
        !           126:   unsigned char *p;
        !           127:   size_t exp_len;
        !           128:   
        !           129:   static struct rsa_public_key *key = NULL;
        !           130:   static mpz_t sig_mpz;
        !           131:   
        !           132:   if (key == NULL)
        !           133:     {
        !           134:       if (!(key = whine_malloc(sizeof(struct rsa_public_key))))
        !           135:        return 0;
        !           136:       
        !           137:       nettle_rsa_public_key_init(key);
        !           138:       mpz_init(sig_mpz);
        !           139:     }
        !           140:   
        !           141:   if ((key_len < 3) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
        !           142:     return 0;
        !           143:   
        !           144:   key_len--;
        !           145:   if ((exp_len = *p++) == 0)
        !           146:     {
        !           147:       GETSHORT(exp_len, p);
        !           148:       key_len -= 2;
        !           149:     }
        !           150:   
        !           151:   if (exp_len >= key_len)
        !           152:     return 0;
        !           153:   
        !           154:   key->size =  key_len - exp_len;
        !           155:   mpz_import(key->e, exp_len, 1, 1, 0, 0, p);
        !           156:   mpz_import(key->n, key->size, 1, 1, 0, 0, p + exp_len);
        !           157: 
        !           158:   mpz_import(sig_mpz, sig_len, 1, 1, 0, 0, sig);
        !           159:   
        !           160:   switch (algo)
        !           161:     {
        !           162:     case 1:
        !           163:       return nettle_rsa_md5_verify_digest(key, digest, sig_mpz);
        !           164:     case 5: case 7:
        !           165:       return nettle_rsa_sha1_verify_digest(key, digest, sig_mpz);
        !           166:     case 8:
        !           167:       return nettle_rsa_sha256_verify_digest(key, digest, sig_mpz);
        !           168:     case 10:
        !           169:       return nettle_rsa_sha512_verify_digest(key, digest, sig_mpz);
        !           170:     }
        !           171: 
        !           172:   return 0;
        !           173: }  
        !           174: 
        !           175: static int dsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
        !           176:                      unsigned char *digest, int algo)
        !           177: {
        !           178:   unsigned char *p;
        !           179:   unsigned int t;
        !           180:   
        !           181:   static struct dsa_public_key *key = NULL;
        !           182:   static struct dsa_signature *sig_struct;
        !           183:   
        !           184:   if (key == NULL)
        !           185:     {
        !           186:       if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))) || 
        !           187:          !(key = whine_malloc(sizeof(struct dsa_public_key)))) 
        !           188:        return 0;
        !           189:       
        !           190:       nettle_dsa_public_key_init(key);
        !           191:       nettle_dsa_signature_init(sig_struct);
        !           192:     }
        !           193:   
        !           194:   if ((sig_len < 41) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
        !           195:     return 0;
        !           196:   
        !           197:   t = *p++;
        !           198:   
        !           199:   if (key_len < (213 + (t * 24)))
        !           200:     return 0;
        !           201:   
        !           202:   mpz_import(key->q, 20, 1, 1, 0, 0, p); p += 20;
        !           203:   mpz_import(key->p, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
        !           204:   mpz_import(key->g, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
        !           205:   mpz_import(key->y, 64 + (t*8), 1, 1, 0, 0, p); p += 64 + (t*8);
        !           206:   
        !           207:   mpz_import(sig_struct->r, 20, 1, 1, 0, 0, sig+1);
        !           208:   mpz_import(sig_struct->s, 20, 1, 1, 0, 0, sig+21);
        !           209:   
        !           210:   (void)algo;
        !           211:   
        !           212:   return nettle_dsa_sha1_verify_digest(key, digest, sig_struct);
        !           213: } 
        !           214:  
        !           215: #ifndef NO_NETTLE_ECC
        !           216: static int dnsmasq_ecdsa_verify(struct blockdata *key_data, unsigned int key_len, 
        !           217:                                unsigned char *sig, size_t sig_len,
        !           218:                                unsigned char *digest, size_t digest_len, int algo)
        !           219: {
        !           220:   unsigned char *p;
        !           221:   unsigned int t;
        !           222:   struct ecc_point *key;
        !           223: 
        !           224:   static struct ecc_point *key_256 = NULL, *key_384 = NULL;
        !           225:   static mpz_t x, y;
        !           226:   static struct dsa_signature *sig_struct;
        !           227:   
        !           228:   if (!sig_struct)
        !           229:     {
        !           230:       if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))))
        !           231:        return 0;
        !           232:       
        !           233:       nettle_dsa_signature_init(sig_struct);
        !           234:       mpz_init(x);
        !           235:       mpz_init(y);
        !           236:     }
        !           237:   
        !           238:   switch (algo)
        !           239:     {
        !           240:     case 13:
        !           241:       if (!key_256)
        !           242:        {
        !           243:          if (!(key_256 = whine_malloc(sizeof(struct ecc_point))))
        !           244:            return 0;
        !           245:          
        !           246:          nettle_ecc_point_init(key_256, &nettle_secp_256r1);
        !           247:        }
        !           248:       
        !           249:       key = key_256;
        !           250:       t = 32;
        !           251:       break;
        !           252:       
        !           253:     case 14:
        !           254:       if (!key_384)
        !           255:        {
        !           256:          if (!(key_384 = whine_malloc(sizeof(struct ecc_point))))
        !           257:            return 0;
        !           258:          
        !           259:          nettle_ecc_point_init(key_384, &nettle_secp_384r1);
        !           260:        }
        !           261:       
        !           262:       key = key_384;
        !           263:       t = 48;
        !           264:       break;
        !           265:         
        !           266:     default:
        !           267:       return 0;
        !           268:     }
        !           269:   
        !           270:   if (sig_len != 2*t || key_len != 2*t ||
        !           271:       (p = blockdata_retrieve(key_data, key_len, NULL)))
        !           272:     return 0;
        !           273:   
        !           274:   mpz_import(x, t , 1, 1, 0, 0, p);
        !           275:   mpz_import(y, t , 1, 1, 0, 0, p + t);
        !           276: 
        !           277:   if (!ecc_point_set(key, x, y))
        !           278:     return 0;
        !           279:   
        !           280:   mpz_import(sig_struct->r, t, 1, 1, 0, 0, sig);
        !           281:   mpz_import(sig_struct->s, t, 1, 1, 0, 0, sig + t);
        !           282:   
        !           283:   return nettle_ecdsa_verify(key, digest_len, digest, sig_struct);
        !           284: } 
        !           285: #endif 
        !           286: 
        !           287: static int verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
        !           288:                  unsigned char *digest, size_t digest_len, int algo)
        !           289: {
        !           290:   (void)digest_len;
        !           291: 
        !           292:   switch (algo)
        !           293:     {
        !           294:     case 1: case 5: case 7: case 8: case 10:
        !           295:       return rsa_verify(key_data, key_len, sig, sig_len, digest, algo);
        !           296:       
        !           297:     case 3: case 6: 
        !           298:       return dsa_verify(key_data, key_len, sig, sig_len, digest, algo);
        !           299:  
        !           300: #ifndef NO_NETTLE_ECC   
        !           301:     case 13: case 14:
        !           302:       return dnsmasq_ecdsa_verify(key_data, key_len, sig, sig_len, digest, digest_len, algo);
        !           303: #endif
        !           304:     }
        !           305:   
        !           306:   return 0;
        !           307: }
        !           308: 
        !           309: /* Convert from presentation format to wire format, in place.
        !           310:    Also map UC -> LC.
        !           311:    Note that using extract_name to get presentation format
        !           312:    then calling to_wire() removes compression and maps case,
        !           313:    thus generating names in canonical form.
        !           314:    Calling to_wire followed by from_wire is almost an identity,
        !           315:    except that the UC remains mapped to LC. 
        !           316: */
        !           317: static int to_wire(char *name)
        !           318: {
        !           319:   unsigned char *l, *p, term;
        !           320:   int len;
        !           321: 
        !           322:   for (l = (unsigned char*)name; *l != 0; l = p)
        !           323:     {
        !           324:       for (p = l; *p != '.' && *p != 0; p++)
        !           325:        if (*p >= 'A' && *p <= 'Z')
        !           326:          *p = *p - 'A' + 'a';
        !           327:       
        !           328:       term = *p;
        !           329:       
        !           330:       if ((len = p - l) != 0)
        !           331:        memmove(l+1, l, len);
        !           332:       *l = len;
        !           333:       
        !           334:       p++;
        !           335:       
        !           336:       if (term == 0)
        !           337:        *p = 0;
        !           338:     }
        !           339:   
        !           340:   return l + 1 - (unsigned char *)name;
        !           341: }
        !           342: 
        !           343: /* Note: no compression  allowed in input. */
        !           344: static void from_wire(char *name)
        !           345: {
        !           346:   unsigned char *l;
        !           347:   int len;
        !           348: 
        !           349:   for (l = (unsigned char *)name; *l != 0; l += len+1)
        !           350:     {
        !           351:       len = *l;
        !           352:       memmove(l, l+1, len);
        !           353:       l[len] = '.';
        !           354:     }
        !           355: 
        !           356:   if ((char *)l != name)
        !           357:     *(l-1) = 0;
        !           358: }
        !           359: 
        !           360: /* Input in presentation format */
        !           361: static int count_labels(char *name)
        !           362: {
        !           363:   int i;
        !           364: 
        !           365:   if (*name == 0)
        !           366:     return 0;
        !           367: 
        !           368:   for (i = 0; *name; name++)
        !           369:     if (*name == '.')
        !           370:       i++;
        !           371: 
        !           372:   return i+1;
        !           373: }
        !           374: 
        !           375: /* Implement RFC1982 wrapped compare for 32-bit numbers */
        !           376: static int serial_compare_32(unsigned long s1, unsigned long s2)
        !           377: {
        !           378:   if (s1 == s2)
        !           379:     return SERIAL_EQ;
        !           380: 
        !           381:   if ((s1 < s2 && (s2 - s1) < (1UL<<31)) ||
        !           382:       (s1 > s2 && (s1 - s2) > (1UL<<31)))
        !           383:     return SERIAL_LT;
        !           384:   if ((s1 < s2 && (s2 - s1) > (1UL<<31)) ||
        !           385:       (s1 > s2 && (s1 - s2) < (1UL<<31)))
        !           386:     return SERIAL_GT;
        !           387:   return SERIAL_UNDEF;
        !           388: }
        !           389: 
        !           390: /* Check whether today/now is between date_start and date_end */
        !           391: static int check_date_range(unsigned long date_start, unsigned long date_end)
        !           392: {
        !           393:   unsigned long curtime;
        !           394: 
        !           395:   /* Checking timestamps may be temporarily disabled */
        !           396:   if (option_bool(OPT_DNSSEC_TIME))
        !           397:     return 1;
        !           398:   
        !           399:   curtime = time(0);
        !           400:   
        !           401:   /* We must explicitly check against wanted values, because of SERIAL_UNDEF */
        !           402:   return serial_compare_32(curtime, date_start) == SERIAL_GT
        !           403:     && serial_compare_32(curtime, date_end) == SERIAL_LT;
        !           404: }
        !           405: 
        !           406: static u16 *get_desc(int type)
        !           407: {
        !           408:   /* List of RRtypes which include domains in the data.
        !           409:      0 -> domain
        !           410:      integer -> no of plain bytes
        !           411:      -1 -> end
        !           412: 
        !           413:      zero is not a valid RRtype, so the final entry is returned for
        !           414:      anything which needs no mangling.
        !           415:   */
        !           416:   
        !           417:   static u16 rr_desc[] = 
        !           418:     { 
        !           419:       T_NS, 0, -1, 
        !           420:       T_MD, 0, -1,
        !           421:       T_MF, 0, -1,
        !           422:       T_CNAME, 0, -1,
        !           423:       T_SOA, 0, 0, -1,
        !           424:       T_MB, 0, -1,
        !           425:       T_MG, 0, -1,
        !           426:       T_MR, 0, -1,
        !           427:       T_PTR, 0, -1,
        !           428:       T_MINFO, 0, 0, -1,
        !           429:       T_MX, 2, 0, -1,
        !           430:       T_RP, 0, 0, -1,
        !           431:       T_AFSDB, 2, 0, -1,
        !           432:       T_RT, 2, 0, -1,
        !           433:       T_SIG, 18, 0, -1,
        !           434:       T_PX, 2, 0, 0, -1,
        !           435:       T_NXT, 0, -1,
        !           436:       T_KX, 2, 0, -1,
        !           437:       T_SRV, 6, 0, -1,
        !           438:       T_DNAME, 0, -1,
        !           439:       0, -1 /* wildcard/catchall */
        !           440:     }; 
        !           441:   
        !           442:   u16 *p = rr_desc;
        !           443:   
        !           444:   while (*p != type && *p != 0)
        !           445:     while (*p++ != (u16)-1);
        !           446: 
        !           447:   return p+1;
        !           448: }
        !           449: 
        !           450: /* Return bytes of canonicalised rdata, when the return value is zero, the remaining 
        !           451:    data, pointed to by *p, should be used raw. */
        !           452: static int get_rdata(struct dns_header *header, size_t plen, unsigned char *end, char *buff, 
        !           453:                     unsigned char **p, u16 **desc)
        !           454: {
        !           455:   int d = **desc;
        !           456:   
        !           457:   (*desc)++;
        !           458:   
        !           459:   /* No more data needs mangling */
        !           460:   if (d == (u16)-1)
        !           461:     return 0;
        !           462:   
        !           463:   if (d == 0 && extract_name(header, plen, p, buff, 1, 0))
        !           464:     /* domain-name, canonicalise */
        !           465:     return to_wire(buff);
        !           466:   else
        !           467:     { 
        !           468:       /* plain data preceding a domain-name, don't run off the end of the data */
        !           469:       if ((end - *p) < d)
        !           470:        d = end - *p;
        !           471:       
        !           472:       if (d != 0)
        !           473:        {
        !           474:          memcpy(buff, *p, d);
        !           475:          *p += d;
        !           476:        }
        !           477:       
        !           478:       return d;
        !           479:     }
        !           480: }
        !           481: 
        !           482: static int expand_workspace(unsigned char ***wkspc, int *sz, int new)
        !           483: {
        !           484:   unsigned char **p;
        !           485:   int new_sz = *sz;
        !           486:   
        !           487:   if (new_sz > new)
        !           488:     return 1;
        !           489: 
        !           490:   if (new >= 100)
        !           491:     return 0;
        !           492: 
        !           493:   new_sz += 5;
        !           494:   
        !           495:   if (!(p = whine_malloc((new_sz) * sizeof(unsigned char **))))
        !           496:     return 0;  
        !           497:   
        !           498:   if (*wkspc)
        !           499:     {
        !           500:       memcpy(p, *wkspc, *sz * sizeof(unsigned char **));
        !           501:       free(*wkspc);
        !           502:     }
        !           503:   
        !           504:   *wkspc = p;
        !           505:   *sz = new_sz;
        !           506: 
        !           507:   return 1;
        !           508: }
        !           509: 
        !           510: /* Bubble sort the RRset into the canonical order. 
        !           511:    Note that the byte-streams from two RRs may get unsynced: consider 
        !           512:    RRs which have two domain-names at the start and then other data.
        !           513:    The domain-names may have different lengths in each RR, but sort equal
        !           514: 
        !           515:    ------------
        !           516:    |abcde|fghi|
        !           517:    ------------
        !           518:    |abcd|efghi|
        !           519:    ------------
        !           520: 
        !           521:    leaving the following bytes as deciding the order. Hence the nasty left1 and left2 variables.
        !           522: */
        !           523: 
        !           524: static void sort_rrset(struct dns_header *header, size_t plen, u16 *rr_desc, int rrsetidx, 
        !           525:                       unsigned char **rrset, char *buff1, char *buff2)
        !           526: {
        !           527:   int swap, quit, i;
        !           528:   
        !           529:   do
        !           530:     {
        !           531:       for (swap = 0, i = 0; i < rrsetidx-1; i++)
        !           532:        {
        !           533:          int rdlen1, rdlen2, left1, left2, len1, len2, len, rc;
        !           534:          u16 *dp1, *dp2;
        !           535:          unsigned char *end1, *end2;
        !           536:          /* Note that these have been determined to be OK previously,
        !           537:             so we don't need to check for NULL return here. */
        !           538:          unsigned char *p1 = skip_name(rrset[i], header, plen, 10);
        !           539:          unsigned char *p2 = skip_name(rrset[i+1], header, plen, 10);
        !           540:          
        !           541:          p1 += 8; /* skip class, type, ttl */
        !           542:          GETSHORT(rdlen1, p1);
        !           543:          end1 = p1 + rdlen1;
        !           544:          
        !           545:          p2 += 8; /* skip class, type, ttl */
        !           546:          GETSHORT(rdlen2, p2);
        !           547:          end2 = p2 + rdlen2; 
        !           548:          
        !           549:          dp1 = dp2 = rr_desc;
        !           550:          
        !           551:          for (quit = 0, left1 = 0, left2 = 0, len1 = 0, len2 = 0; !quit;)
        !           552:            {
        !           553:              if (left1 != 0)
        !           554:                memmove(buff1, buff1 + len1 - left1, left1);
        !           555:              
        !           556:              if ((len1 = get_rdata(header, plen, end1, buff1 + left1, &p1, &dp1)) == 0)
        !           557:                {
        !           558:                  quit = 1;
        !           559:                  len1 = end1 - p1;
        !           560:                  memcpy(buff1 + left1, p1, len1);
        !           561:                }
        !           562:              len1 += left1;
        !           563:              
        !           564:              if (left2 != 0)
        !           565:                memmove(buff2, buff2 + len2 - left2, left2);
        !           566:              
        !           567:              if ((len2 = get_rdata(header, plen, end2, buff2 + left2, &p2, &dp2)) == 0)
        !           568:                {
        !           569:                  quit = 1;
        !           570:                  len2 = end2 - p2;
        !           571:                  memcpy(buff2 + left2, p2, len2);
        !           572:                }
        !           573:              len2 += left2;
        !           574:               
        !           575:              if (len1 > len2)
        !           576:                left1 = len1 - len2, left2 = 0, len = len2;
        !           577:              else
        !           578:                left2 = len2 - len1, left1 = 0, len = len1;
        !           579:              
        !           580:              rc = (len == 0) ? 0 : memcmp(buff1, buff2, len);
        !           581:              
        !           582:              if (rc > 0 || (rc == 0 && quit && len1 > len2))
        !           583:                {
        !           584:                  unsigned char *tmp = rrset[i+1];
        !           585:                  rrset[i+1] = rrset[i];
        !           586:                  rrset[i] = tmp;
        !           587:                  swap = quit = 1;
        !           588:                }
        !           589:              else if (rc < 0)
        !           590:                quit = 1;
        !           591:            }
        !           592:        }
        !           593:     } while (swap);
        !           594: }
        !           595: 
        !           596: /* Validate a single RRset (class, type, name) in the supplied DNS reply 
        !           597:    Return code:
        !           598:    STAT_SECURE   if it validates.
        !           599:    STAT_SECURE_WILDCARD if it validates and is the result of wildcard expansion.
        !           600:    STAT_NO_SIG no RRsigs found.
        !           601:    STAT_INSECURE RRset empty.
        !           602:    STAT_BOGUS    signature is wrong, bad packet.
        !           603:    STAT_NEED_KEY need DNSKEY to complete validation (name is returned in keyname)
        !           604: 
        !           605:    if key is non-NULL, use that key, which has the algo and tag given in the params of those names,
        !           606:    otherwise find the key in the cache.
        !           607: 
        !           608:    name is unchanged on exit. keyname is used as workspace and trashed.
        !           609: */
        !           610: static int validate_rrset(time_t now, struct dns_header *header, size_t plen, int class, 
        !           611:                          int type, char *name, char *keyname, struct blockdata *key, int keylen, int algo_in, int keytag_in)
        !           612: {
        !           613:   static unsigned char **rrset = NULL, **sigs = NULL;
        !           614:   static int rrset_sz = 0, sig_sz = 0;
        !           615:   
        !           616:   unsigned char *p;
        !           617:   int rrsetidx, sigidx, res, rdlen, j, name_labels;
        !           618:   struct crec *crecp = NULL;
        !           619:   int type_covered, algo, labels, orig_ttl, sig_expiration, sig_inception, key_tag;
        !           620:   u16 *rr_desc = get_desc(type);
        !           621: 
        !           622:   if (!(p = skip_questions(header, plen)))
        !           623:     return STAT_BOGUS;
        !           624: 
        !           625:   name_labels = count_labels(name); /* For 4035 5.3.2 check */
        !           626: 
        !           627:   /* look for RRSIGs for this RRset and get pointers to each RR in the set. */
        !           628:   for (rrsetidx = 0, sigidx = 0, j = ntohs(header->ancount) + ntohs(header->nscount); 
        !           629:        j != 0; j--) 
        !           630:     {
        !           631:       unsigned char *pstart, *pdata;
        !           632:       int stype, sclass;
        !           633: 
        !           634:       pstart = p;
        !           635:       
        !           636:       if (!(res = extract_name(header, plen, &p, name, 0, 10)))
        !           637:        return STAT_BOGUS; /* bad packet */
        !           638:       
        !           639:       GETSHORT(stype, p);
        !           640:       GETSHORT(sclass, p);
        !           641:       p += 4; /* TTL */
        !           642:       
        !           643:       pdata = p;
        !           644: 
        !           645:       GETSHORT(rdlen, p);
        !           646:       
        !           647:       if (!CHECK_LEN(header, p, plen, rdlen))
        !           648:        return STAT_BOGUS; 
        !           649:       
        !           650:       if (res == 1 && sclass == class)
        !           651:        {
        !           652:          if (stype == type)
        !           653:            {
        !           654:              if (!expand_workspace(&rrset, &rrset_sz, rrsetidx))
        !           655:                return STAT_BOGUS; 
        !           656:              
        !           657:              rrset[rrsetidx++] = pstart;
        !           658:            }
        !           659:          
        !           660:          if (stype == T_RRSIG)
        !           661:            {
        !           662:              if (rdlen < 18)
        !           663:                return STAT_BOGUS; /* bad packet */ 
        !           664:              
        !           665:              GETSHORT(type_covered, p);
        !           666:              
        !           667:              if (type_covered == type)
        !           668:                {
        !           669:                  if (!expand_workspace(&sigs, &sig_sz, sigidx))
        !           670:                    return STAT_BOGUS; 
        !           671:                  
        !           672:                  sigs[sigidx++] = pdata;
        !           673:                } 
        !           674:              
        !           675:              p = pdata + 2; /* restore for ADD_RDLEN */
        !           676:            }
        !           677:        }
        !           678:       
        !           679:       if (!ADD_RDLEN(header, p, plen, rdlen))
        !           680:        return STAT_BOGUS;
        !           681:     }
        !           682:   
        !           683:   /* RRset empty */
        !           684:   if (rrsetidx == 0)
        !           685:     return STAT_INSECURE; 
        !           686: 
        !           687:   /* no RRSIGs */
        !           688:   if (sigidx == 0)
        !           689:     return STAT_NO_SIG; 
        !           690:   
        !           691:   /* Sort RRset records into canonical order. 
        !           692:      Note that at this point keyname and daemon->workspacename buffs are
        !           693:      unused, and used as workspace by the sort. */
        !           694:   sort_rrset(header, plen, rr_desc, rrsetidx, rrset, daemon->workspacename, keyname);
        !           695:          
        !           696:   /* Now try all the sigs to try and find one which validates */
        !           697:   for (j = 0; j <sigidx; j++)
        !           698:     {
        !           699:       unsigned char *psav, *sig, *digest;
        !           700:       int i, wire_len, sig_len;
        !           701:       const struct nettle_hash *hash;
        !           702:       void *ctx;
        !           703:       char *name_start;
        !           704:       u32 nsigttl;
        !           705:       
        !           706:       p = sigs[j];
        !           707:       GETSHORT(rdlen, p); /* rdlen >= 18 checked previously */
        !           708:       psav = p;
        !           709:       
        !           710:       p += 2; /* type_covered - already checked */
        !           711:       algo = *p++;
        !           712:       labels = *p++;
        !           713:       GETLONG(orig_ttl, p);
        !           714:       GETLONG(sig_expiration, p);
        !           715:       GETLONG(sig_inception, p);
        !           716:       GETSHORT(key_tag, p);
        !           717:       
        !           718:       if (!extract_name(header, plen, &p, keyname, 1, 0))
        !           719:        return STAT_BOGUS;
        !           720: 
        !           721:       /* RFC 4035 5.3.1 says that the Signer's Name field MUST equal
        !           722:         the name of the zone containing the RRset. We can't tell that
        !           723:         for certain, but we can check that  the RRset name is equal to
        !           724:         or encloses the signers name, which should be enough to stop 
        !           725:         an attacker using signatures made with the key of an unrelated 
        !           726:         zone he controls. Note that the root key is always allowed. */
        !           727:       if (*keyname != 0)
        !           728:        {
        !           729:          int failed = 0;
        !           730:          
        !           731:          for (name_start = name; !hostname_isequal(name_start, keyname); )
        !           732:            if ((name_start = strchr(name_start, '.')))
        !           733:              name_start++; /* chop a label off and try again */
        !           734:            else
        !           735:              {
        !           736:                failed = 1;
        !           737:                break;
        !           738:              }
        !           739: 
        !           740:          /* Bad sig, try another */
        !           741:          if (failed)
        !           742:            continue;
        !           743:        }
        !           744:       
        !           745:       /* Other 5.3.1 checks */
        !           746:       if (!check_date_range(sig_inception, sig_expiration) ||
        !           747:          labels > name_labels ||
        !           748:          !(hash = hash_find(algo_digest_name(algo))) ||
        !           749:          !hash_init(hash, &ctx, &digest))
        !           750:        continue;
        !           751:        
        !           752:       /* OK, we have the signature record, see if the relevant DNSKEY is in the cache. */
        !           753:       if (!key && !(crecp = cache_find_by_name(NULL, keyname, now, F_DNSKEY)))
        !           754:        return STAT_NEED_KEY;
        !           755:       
        !           756:       sig = p;
        !           757:       sig_len = rdlen - (p - psav);
        !           758:               
        !           759:       nsigttl = htonl(orig_ttl);
        !           760:       
        !           761:       hash->update(ctx, 18, psav);
        !           762:       wire_len = to_wire(keyname);
        !           763:       hash->update(ctx, (unsigned int)wire_len, (unsigned char*)keyname);
        !           764:       from_wire(keyname);
        !           765:       
        !           766:       for (i = 0; i < rrsetidx; ++i)
        !           767:        {
        !           768:          int seg;
        !           769:          unsigned char *end, *cp;
        !           770:          u16 len, *dp;
        !           771:          
        !           772:          p = rrset[i];
        !           773:          if (!extract_name(header, plen, &p, name, 1, 10)) 
        !           774:            return STAT_BOGUS;
        !           775: 
        !           776:          name_start = name;
        !           777:          
        !           778:          /* if more labels than in RRsig name, hash *.<no labels in rrsig labels field>  4035 5.3.2 */
        !           779:          if (labels < name_labels)
        !           780:            {
        !           781:              int k;
        !           782:              for (k = name_labels - labels; k != 0; k--)
        !           783:                while (*name_start != '.' && *name_start != 0)
        !           784:                  name_start++;
        !           785:              name_start--;
        !           786:              *name_start = '*';
        !           787:            }
        !           788:          
        !           789:          wire_len = to_wire(name_start);
        !           790:          hash->update(ctx, (unsigned int)wire_len, (unsigned char *)name_start);
        !           791:          hash->update(ctx, 4, p); /* class and type */
        !           792:          hash->update(ctx, 4, (unsigned char *)&nsigttl);
        !           793:          
        !           794:          p += 8; /* skip class, type, ttl */
        !           795:          GETSHORT(rdlen, p);
        !           796:          if (!CHECK_LEN(header, p, plen, rdlen))
        !           797:            return STAT_BOGUS; 
        !           798:          
        !           799:          end = p + rdlen;
        !           800:          
        !           801:          /* canonicalise rdata and calculate length of same, use name buffer as workspace */
        !           802:          cp = p;
        !           803:          dp = rr_desc;
        !           804:          for (len = 0; (seg = get_rdata(header, plen, end, name, &cp, &dp)) != 0; len += seg);
        !           805:          len += end - cp;
        !           806:          len = htons(len);
        !           807:          hash->update(ctx, 2, (unsigned char *)&len); 
        !           808:          
        !           809:          /* Now canonicalise again and digest. */
        !           810:          cp = p;
        !           811:          dp = rr_desc;
        !           812:          while ((seg = get_rdata(header, plen, end, name, &cp, &dp)))
        !           813:            hash->update(ctx, seg, (unsigned char *)name);
        !           814:          if (cp != end)
        !           815:            hash->update(ctx, end - cp, cp);
        !           816:        }
        !           817:      
        !           818:       hash->digest(ctx, hash->digest_size, digest);
        !           819:       
        !           820:       /* namebuff used for workspace above, restore to leave unchanged on exit */
        !           821:       p = (unsigned char*)(rrset[0]);
        !           822:       extract_name(header, plen, &p, name, 1, 0);
        !           823: 
        !           824:       if (key)
        !           825:        {
        !           826:          if (algo_in == algo && keytag_in == key_tag &&
        !           827:              verify(key, keylen, sig, sig_len, digest, hash->digest_size, algo))
        !           828:            return STAT_SECURE;
        !           829:        }
        !           830:       else
        !           831:        {
        !           832:          /* iterate through all possible keys 4035 5.3.1 */
        !           833:          for (; crecp; crecp = cache_find_by_name(crecp, keyname, now, F_DNSKEY))
        !           834:            if (crecp->addr.key.algo == algo && 
        !           835:                crecp->addr.key.keytag == key_tag &&
        !           836:                crecp->uid == (unsigned int)class &&
        !           837:                verify(crecp->addr.key.keydata, crecp->addr.key.keylen, sig, sig_len, digest, hash->digest_size, algo))
        !           838:              return (labels < name_labels) ? STAT_SECURE_WILDCARD : STAT_SECURE;
        !           839:        }
        !           840:     }
        !           841: 
        !           842:   return STAT_BOGUS;
        !           843: }
        !           844:  
        !           845: /* The DNS packet is expected to contain the answer to a DNSKEY query.
        !           846:    Put all DNSKEYs in the answer which are valid into the cache.
        !           847:    return codes:
        !           848:          STAT_INSECURE No DNSKEYs in reply.
        !           849:         STAT_SECURE   At least one valid DNSKEY found and in cache.
        !           850:         STAT_BOGUS    No DNSKEYs found, which  can be validated with DS,
        !           851:                       or self-sign for DNSKEY RRset is not valid, bad packet.
        !           852:         STAT_NEED_DS  DS records to validate a key not found, name in keyname 
        !           853: */
        !           854: int dnssec_validate_by_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class)
        !           855: {
        !           856:   unsigned char *psave, *p = (unsigned char *)(header+1);
        !           857:   struct crec *crecp, *recp1;
        !           858:   int rc, j, qtype, qclass, ttl, rdlen, flags, algo, valid, keytag, type_covered;
        !           859:   struct blockdata *key;
        !           860:   struct all_addr a;
        !           861: 
        !           862:   if (ntohs(header->qdcount) != 1 ||
        !           863:       !extract_name(header, plen, &p, name, 1, 4))
        !           864:     return STAT_BOGUS;
        !           865: 
        !           866:   GETSHORT(qtype, p);
        !           867:   GETSHORT(qclass, p);
        !           868:   
        !           869:   if (qtype != T_DNSKEY || qclass != class)
        !           870:     return STAT_BOGUS;
        !           871:   
        !           872:   if (ntohs(header->ancount) == 0)
        !           873:     return STAT_INSECURE;
        !           874: 
        !           875:   /* See if we have cached a DS record which validates this key */
        !           876:   if (!(crecp = cache_find_by_name(NULL, name, now, F_DS)))
        !           877:     {
        !           878:       strcpy(keyname, name);
        !           879:       return STAT_NEED_DS;
        !           880:     }
        !           881:   
        !           882:   /* If we've cached that DS provably doesn't exist, result must be INSECURE */
        !           883:   if (crecp->flags & F_NEG)
        !           884:     return STAT_INSECURE;
        !           885:   
        !           886:   /* NOTE, we need to find ONE DNSKEY which matches the DS */
        !           887:   for (valid = 0, j = ntohs(header->ancount); j != 0 && !valid; j--) 
        !           888:     {
        !           889:       /* Ensure we have type, class  TTL and length */
        !           890:       if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
        !           891:        return STAT_BOGUS; /* bad packet */
        !           892:   
        !           893:       GETSHORT(qtype, p); 
        !           894:       GETSHORT(qclass, p);
        !           895:       GETLONG(ttl, p);
        !           896:       GETSHORT(rdlen, p);
        !           897:  
        !           898:       if (!CHECK_LEN(header, p, plen, rdlen) || rdlen < 4)
        !           899:        return STAT_BOGUS; /* bad packet */
        !           900:       
        !           901:       if (qclass != class || qtype != T_DNSKEY || rc == 2)
        !           902:        {
        !           903:          p += rdlen;
        !           904:          continue;
        !           905:        }
        !           906:             
        !           907:       psave = p;
        !           908:       
        !           909:       GETSHORT(flags, p);
        !           910:       if (*p++ != 3)
        !           911:        return STAT_BOGUS;
        !           912:       algo = *p++;
        !           913:       keytag = dnskey_keytag(algo, flags, p, rdlen - 4);
        !           914:       key = NULL;
        !           915:       
        !           916:       /* key must have zone key flag set */
        !           917:       if (flags & 0x100)
        !           918:        key = blockdata_alloc((char*)p, rdlen - 4);
        !           919:       
        !           920:       p = psave;
        !           921:       
        !           922:       if (!ADD_RDLEN(header, p, plen, rdlen))
        !           923:        {
        !           924:          if (key)
        !           925:            blockdata_free(key);
        !           926:          return STAT_BOGUS; /* bad packet */
        !           927:        }
        !           928: 
        !           929:       /* No zone key flag or malloc failure */
        !           930:       if (!key)
        !           931:        continue;
        !           932:       
        !           933:       for (recp1 = crecp; recp1; recp1 = cache_find_by_name(recp1, name, now, F_DS))
        !           934:        {
        !           935:          void *ctx;
        !           936:          unsigned char *digest, *ds_digest;
        !           937:          const struct nettle_hash *hash;
        !           938:          
        !           939:          if (recp1->addr.ds.algo == algo && 
        !           940:              recp1->addr.ds.keytag == keytag &&
        !           941:              recp1->uid == (unsigned int)class &&
        !           942:              (hash = hash_find(ds_digest_name(recp1->addr.ds.digest))) &&
        !           943:              hash_init(hash, &ctx, &digest))
        !           944:            
        !           945:            {
        !           946:              int wire_len = to_wire(name);
        !           947:              
        !           948:              /* Note that digest may be different between DSs, so 
        !           949:                 we can't move this outside the loop. */
        !           950:              hash->update(ctx, (unsigned int)wire_len, (unsigned char *)name);
        !           951:              hash->update(ctx, (unsigned int)rdlen, psave);
        !           952:              hash->digest(ctx, hash->digest_size, digest);
        !           953:              
        !           954:              from_wire(name);
        !           955:              
        !           956:              if (recp1->addr.ds.keylen == (int)hash->digest_size &&
        !           957:                  (ds_digest = blockdata_retrieve(recp1->addr.key.keydata, recp1->addr.ds.keylen, NULL)) &&
        !           958:                  memcmp(ds_digest, digest, recp1->addr.ds.keylen) == 0 &&
        !           959:                  validate_rrset(now, header, plen, class, T_DNSKEY, name, keyname, key, rdlen - 4, algo, keytag) == STAT_SECURE)
        !           960:                {
        !           961:                  valid = 1;
        !           962:                  break;
        !           963:                }
        !           964:            }
        !           965:        }
        !           966:       blockdata_free(key);
        !           967:     }
        !           968: 
        !           969:   if (valid)
        !           970:     {
        !           971:       /* DNSKEY RRset determined to be OK, now cache it and the RRsigs that sign it. */
        !           972:       cache_start_insert();
        !           973:       
        !           974:       p = skip_questions(header, plen);
        !           975: 
        !           976:       for (j = ntohs(header->ancount); j != 0; j--) 
        !           977:        {
        !           978:          /* Ensure we have type, class  TTL and length */
        !           979:          if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
        !           980:            return STAT_INSECURE; /* bad packet */
        !           981:          
        !           982:          GETSHORT(qtype, p); 
        !           983:          GETSHORT(qclass, p);
        !           984:          GETLONG(ttl, p);
        !           985:          GETSHORT(rdlen, p);
        !           986:            
        !           987:          if (!CHECK_LEN(header, p, plen, rdlen))
        !           988:            return STAT_BOGUS; /* bad packet */
        !           989:          
        !           990:          if (qclass == class && rc == 1)
        !           991:            {
        !           992:              psave = p;
        !           993:              
        !           994:              if (qtype == T_DNSKEY)
        !           995:                {
        !           996:                  if (rdlen < 4)
        !           997:                    return STAT_BOGUS; /* bad packet */
        !           998:                  
        !           999:                  GETSHORT(flags, p);
        !          1000:                  if (*p++ != 3)
        !          1001:                    return STAT_BOGUS;
        !          1002:                  algo = *p++;
        !          1003:                  keytag = dnskey_keytag(algo, flags, p, rdlen - 4);
        !          1004:                  
        !          1005:                  /* Cache needs to known class for DNSSEC stuff */
        !          1006:                  a.addr.dnssec.class = class;
        !          1007:                  
        !          1008:                  if ((key = blockdata_alloc((char*)p, rdlen - 4)))
        !          1009:                    {
        !          1010:                      if (!(recp1 = cache_insert(name, &a, now, ttl, F_FORWARD | F_DNSKEY | F_DNSSECOK)))
        !          1011:                        blockdata_free(key);
        !          1012:                      else
        !          1013:                        {
        !          1014:                          a.addr.keytag = keytag;
        !          1015:                          log_query(F_KEYTAG | F_UPSTREAM, name, &a, "DNSKEY keytag %u");
        !          1016:                          
        !          1017:                          recp1->addr.key.keylen = rdlen - 4;
        !          1018:                          recp1->addr.key.keydata = key;
        !          1019:                          recp1->addr.key.algo = algo;
        !          1020:                          recp1->addr.key.keytag = keytag;
        !          1021:                          recp1->addr.key.flags = flags;
        !          1022:                        }
        !          1023:                    }
        !          1024:                }
        !          1025:              else if (qtype == T_RRSIG)
        !          1026:                {
        !          1027:                  /* RRSIG, cache if covers DNSKEY RRset */
        !          1028:                  if (rdlen < 18)
        !          1029:                    return STAT_BOGUS; /* bad packet */
        !          1030:                  
        !          1031:                  GETSHORT(type_covered, p);
        !          1032:                  
        !          1033:                  if (type_covered == T_DNSKEY)
        !          1034:                    {
        !          1035:                      a.addr.dnssec.class = class;
        !          1036:                      a.addr.dnssec.type = type_covered;
        !          1037:                      
        !          1038:                      algo = *p++;
        !          1039:                      p += 13; /* labels, orig_ttl, expiration, inception */
        !          1040:                      GETSHORT(keytag, p);      
        !          1041:                      if ((key = blockdata_alloc((char*)psave, rdlen)))
        !          1042:                        {
        !          1043:                          if (!(crecp = cache_insert(name, &a, now, ttl,  F_FORWARD | F_DNSKEY | F_DS)))
        !          1044:                            blockdata_free(key);
        !          1045:                          else
        !          1046:                            {
        !          1047:                              crecp->addr.sig.keydata = key;
        !          1048:                              crecp->addr.sig.keylen = rdlen;
        !          1049:                              crecp->addr.sig.keytag = keytag;
        !          1050:                              crecp->addr.sig.type_covered = type_covered;
        !          1051:                              crecp->addr.sig.algo = algo;
        !          1052:                            }
        !          1053:                        }
        !          1054:                    }
        !          1055:                }
        !          1056:              
        !          1057:              p = psave;
        !          1058:            }
        !          1059: 
        !          1060:          if (!ADD_RDLEN(header, p, plen, rdlen))
        !          1061:            return STAT_BOGUS; /* bad packet */
        !          1062:        }
        !          1063:       
        !          1064:       /* commit cache insert. */
        !          1065:       cache_end_insert();
        !          1066:       return STAT_SECURE;
        !          1067:     }
        !          1068: 
        !          1069:   log_query(F_UPSTREAM, name, NULL, "BOGUS DNSKEY");
        !          1070:   return STAT_BOGUS;
        !          1071: }
        !          1072: 
        !          1073: /* The DNS packet is expected to contain the answer to a DS query
        !          1074:    Put all DSs in the answer which are valid into the cache.
        !          1075:    return codes:
        !          1076:    STAT_INSECURE    no DS in reply or not signed.
        !          1077:    STAT_SECURE      At least one valid DS found and in cache.
        !          1078:    STAT_NO_DS       It's proved there's no DS here.
        !          1079:    STAT_BOGUS       At least one DS found, which fails validation, bad packet.
        !          1080:    STAT_NEED_DNSKEY DNSKEY records to validate a DS not found, name in keyname
        !          1081: */
        !          1082: 
        !          1083: int dnssec_validate_ds(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int class)
        !          1084: {
        !          1085:   unsigned char *p = (unsigned char *)(header+1);
        !          1086:   int qtype, qclass, val, i, neganswer;
        !          1087: 
        !          1088:   if (ntohs(header->qdcount) != 1 ||
        !          1089:       !(p = skip_name(p, header, plen, 4)))
        !          1090:     return STAT_BOGUS;
        !          1091:   
        !          1092:   GETSHORT(qtype, p);
        !          1093:   GETSHORT(qclass, p);
        !          1094: 
        !          1095:   if (qtype != T_DS || qclass != class)
        !          1096:     val = STAT_BOGUS;
        !          1097:   else
        !          1098:     val = dnssec_validate_reply(now, header, plen, name, keyname, NULL, &neganswer);
        !          1099: 
        !          1100:   if (val == STAT_NO_SIG)
        !          1101:     val = STAT_INSECURE;
        !          1102:   
        !          1103:   p = (unsigned char *)(header+1);
        !          1104:   extract_name(header, plen, &p, name, 1, 4);
        !          1105:   p += 4; /* qtype, qclass */
        !          1106:   
        !          1107:   if (!(p = skip_section(p, ntohs(header->ancount), header, plen)))
        !          1108:     return STAT_BOGUS;
        !          1109:   
        !          1110:   if (val == STAT_BOGUS)
        !          1111:     log_query(F_UPSTREAM, name, NULL, "BOGUS DS");
        !          1112:   
        !          1113:   if ((val == STAT_SECURE || val == STAT_INSECURE) && neganswer)
        !          1114:     {
        !          1115:       int rdlen, flags = F_FORWARD | F_DS | F_NEG;
        !          1116:       unsigned long ttl, minttl = ULONG_MAX;
        !          1117:       struct all_addr a;
        !          1118: 
        !          1119:       if (RCODE(header) == NXDOMAIN)
        !          1120:        flags |= F_NXDOMAIN;
        !          1121:       
        !          1122:       if (val == STAT_SECURE)
        !          1123:        flags |= F_DNSSECOK;
        !          1124:       
        !          1125:       for (i = ntohs(header->nscount); i != 0; i--)
        !          1126:        {
        !          1127:          if (!(p = skip_name(p, header, plen, 0)))
        !          1128:            return STAT_BOGUS;
        !          1129:          
        !          1130:          GETSHORT(qtype, p); 
        !          1131:          GETSHORT(qclass, p);
        !          1132:          GETLONG(ttl, p);
        !          1133:          GETSHORT(rdlen, p);
        !          1134: 
        !          1135:          if (!CHECK_LEN(header, p, plen, rdlen))
        !          1136:            return STAT_BOGUS; /* bad packet */
        !          1137:            
        !          1138:          if (qclass != class || qtype != T_SOA)
        !          1139:            {
        !          1140:              p += rdlen;
        !          1141:              continue;
        !          1142:            }
        !          1143:            
        !          1144:          if (ttl < minttl)
        !          1145:            minttl = ttl;
        !          1146:          
        !          1147:          /* MNAME */
        !          1148:          if (!(p = skip_name(p, header, plen, 0)))
        !          1149:            return STAT_BOGUS;
        !          1150:          /* RNAME */
        !          1151:          if (!(p = skip_name(p, header, plen, 20)))
        !          1152:            return STAT_BOGUS;
        !          1153:          p += 16; /* SERIAL REFRESH RETRY EXPIRE */
        !          1154:          
        !          1155:          GETLONG(ttl, p); /* minTTL */
        !          1156:          if (ttl < minttl)
        !          1157:            minttl = ttl;
        !          1158:          
        !          1159:          break;
        !          1160:        }
        !          1161:       
        !          1162:       if (i != 0)
        !          1163:        {
        !          1164:          cache_start_insert();
        !          1165:          
        !          1166:          a.addr.dnssec.class = class;
        !          1167:          cache_insert(name, &a, now, ttl, flags);
        !          1168:          
        !          1169:          cache_end_insert(); 
        !          1170:        }
        !          1171: 
        !          1172:       return (val == STAT_SECURE) ? STAT_NO_DS : STAT_INSECURE; 
        !          1173:     }
        !          1174: 
        !          1175:   return val;
        !          1176: }
        !          1177: 
        !          1178: /* 4034 6.1 */
        !          1179: static int hostname_cmp(const char *a, const char *b)
        !          1180: {
        !          1181:   char *sa, *ea, *ca, *sb, *eb, *cb;
        !          1182:   unsigned char ac, bc;
        !          1183:   
        !          1184:   sa = ea = (char *)a + strlen(a);
        !          1185:   sb = eb = (char *)b + strlen(b);
        !          1186:  
        !          1187:   while (1)
        !          1188:     {
        !          1189:       while (sa != a && *(sa-1) != '.')
        !          1190:        sa--;
        !          1191:       
        !          1192:       while (sb != b && *(sb-1) != '.')
        !          1193:        sb--;
        !          1194: 
        !          1195:       ca = sa;
        !          1196:       cb = sb;
        !          1197: 
        !          1198:       while (1) 
        !          1199:        {
        !          1200:          if (ca == ea)
        !          1201:            {
        !          1202:              if (cb == eb)
        !          1203:                break;
        !          1204:              
        !          1205:              return -1;
        !          1206:            }
        !          1207:          
        !          1208:          if (cb == eb)
        !          1209:            return 1;
        !          1210:          
        !          1211:          ac = (unsigned char) *ca++;
        !          1212:          bc = (unsigned char) *cb++;
        !          1213:          
        !          1214:          if (ac >= 'A' && ac <= 'Z')
        !          1215:            ac += 'a' - 'A';
        !          1216:          if (bc >= 'A' && bc <= 'Z')
        !          1217:            bc += 'a' - 'A';
        !          1218:          
        !          1219:          if (ac < bc)
        !          1220:            return -1;
        !          1221:          else if (ac != bc)
        !          1222:            return 1;
        !          1223:        }
        !          1224: 
        !          1225:      
        !          1226:       if (sa == a)
        !          1227:        {
        !          1228:          if (sb == b)
        !          1229:            return 0;
        !          1230:          
        !          1231:          return -1;
        !          1232:        }
        !          1233:       
        !          1234:       if (sb == b)
        !          1235:        return 1;
        !          1236:       
        !          1237:       ea = sa--;
        !          1238:       eb = sb--;
        !          1239:     }
        !          1240: }
        !          1241: 
        !          1242: /* Find all the NSEC or NSEC3 records in a reply.
        !          1243:    return an array of pointers to them. */
        !          1244: static int find_nsec_records(struct dns_header *header, size_t plen, unsigned char ***nsecsetp, int *nsecsetl, int class_reqd)
        !          1245: {
        !          1246:   static unsigned char **nsecset = NULL;
        !          1247:   static int nsecset_sz = 0;
        !          1248:   
        !          1249:   int type_found = 0;
        !          1250:   unsigned char *p = skip_questions(header, plen);
        !          1251:   int type, class, rdlen, i, nsecs_found;
        !          1252: 
        !          1253:   /* Move to NS section */
        !          1254:   if (!p || !(p = skip_section(p, ntohs(header->ancount), header, plen)))
        !          1255:     return 0;
        !          1256:   
        !          1257:   for (nsecs_found = 0, i = ntohs(header->nscount); i != 0; i--)
        !          1258:     {
        !          1259:       unsigned char *pstart = p;
        !          1260:       
        !          1261:       if (!(p = skip_name(p, header, plen, 10)))
        !          1262:        return 0;
        !          1263:       
        !          1264:       GETSHORT(type, p); 
        !          1265:       GETSHORT(class, p);
        !          1266:       p += 4; /* TTL */
        !          1267:       GETSHORT(rdlen, p);
        !          1268: 
        !          1269:       if (class == class_reqd && (type == T_NSEC || type == T_NSEC3))
        !          1270:        {
        !          1271:          /* No mixed NSECing 'round here, thankyouverymuch */
        !          1272:          if (type_found == T_NSEC && type == T_NSEC3)
        !          1273:            return 0;
        !          1274:          if (type_found == T_NSEC3 && type == T_NSEC)
        !          1275:            return 0;
        !          1276: 
        !          1277:          type_found = type;
        !          1278: 
        !          1279:          if (!expand_workspace(&nsecset, &nsecset_sz, nsecs_found))
        !          1280:            return 0; 
        !          1281:          
        !          1282:          nsecset[nsecs_found++] = pstart;
        !          1283:        }
        !          1284:       
        !          1285:       if (!ADD_RDLEN(header, p, plen, rdlen))
        !          1286:        return 0;
        !          1287:     }
        !          1288:   
        !          1289:   *nsecsetp = nsecset;
        !          1290:   *nsecsetl = nsecs_found;
        !          1291:   
        !          1292:   return type_found;
        !          1293: }
        !          1294: 
        !          1295: static int prove_non_existence_nsec(struct dns_header *header, size_t plen, unsigned char **nsecs, int nsec_count,
        !          1296:                                    char *workspace1, char *workspace2, char *name, int type)
        !          1297: {
        !          1298:   int i, rc, rdlen;
        !          1299:   unsigned char *p, *psave;
        !          1300:   int offset = (type & 0xff) >> 3;
        !          1301:   int mask = 0x80 >> (type & 0x07);
        !          1302:   
        !          1303:   /* Find NSEC record that proves name doesn't exist */
        !          1304:   for (i = 0; i < nsec_count; i++)
        !          1305:     {
        !          1306:       p = nsecs[i];
        !          1307:       if (!extract_name(header, plen, &p, workspace1, 1, 10))
        !          1308:        return STAT_BOGUS;
        !          1309:       p += 8; /* class, type, TTL */
        !          1310:       GETSHORT(rdlen, p);
        !          1311:       psave = p;
        !          1312:       if (!extract_name(header, plen, &p, workspace2, 1, 10))
        !          1313:        return STAT_BOGUS;
        !          1314:       
        !          1315:       rc = hostname_cmp(workspace1, name);
        !          1316:       
        !          1317:       if (rc == 0)
        !          1318:        {
        !          1319:          /* 4035 para 5.4. Last sentence */
        !          1320:          if (type == T_NSEC || type == T_RRSIG)
        !          1321:            return STAT_SECURE;
        !          1322: 
        !          1323:          /* NSEC with the same name as the RR we're testing, check
        !          1324:             that the type in question doesn't appear in the type map */
        !          1325:          rdlen -= p - psave;
        !          1326:          /* rdlen is now length of type map, and p points to it */
        !          1327:          
        !          1328:          while (rdlen >= 2)
        !          1329:            {
        !          1330:              if (!CHECK_LEN(header, p, plen, rdlen))
        !          1331:                return STAT_BOGUS;
        !          1332:              
        !          1333:              if (p[0] == type >> 8)
        !          1334:                {
        !          1335:                  /* Does the NSEC say our type exists? */
        !          1336:                  if (offset < p[1] && (p[offset+2] & mask) != 0)
        !          1337:                    return STAT_BOGUS;
        !          1338:                  
        !          1339:                  break; /* finshed checking */
        !          1340:                }
        !          1341:              
        !          1342:              rdlen -= p[1];
        !          1343:              p +=  p[1];
        !          1344:            }
        !          1345:          
        !          1346:          return STAT_SECURE;
        !          1347:        }
        !          1348:       else if (rc == -1)
        !          1349:        {
        !          1350:          /* Normal case, name falls between NSEC name and next domain name,
        !          1351:             wrap around case, name falls between NSEC name (rc == -1) and end */
        !          1352:          if (hostname_cmp(workspace2, name) == 1 || hostname_cmp(workspace1, workspace2) == 1)
        !          1353:            return STAT_SECURE;
        !          1354:        }
        !          1355:       else 
        !          1356:        {
        !          1357:          /* wrap around case, name falls between start and next domain name */
        !          1358:          if (hostname_cmp(workspace1, workspace2) == 1 && hostname_cmp(workspace2, name) == 1)
        !          1359:            return STAT_SECURE;
        !          1360:        }
        !          1361:     }
        !          1362:   
        !          1363:   return STAT_BOGUS;
        !          1364: }
        !          1365: 
        !          1366: /* return digest length, or zero on error */
        !          1367: static int hash_name(char *in, unsigned char **out, struct nettle_hash const *hash, 
        !          1368:                     unsigned char *salt, int salt_len, int iterations)
        !          1369: {
        !          1370:   void *ctx;
        !          1371:   unsigned char *digest;
        !          1372:   int i;
        !          1373: 
        !          1374:   if (!hash_init(hash, &ctx, &digest))
        !          1375:     return 0;
        !          1376:  
        !          1377:   hash->update(ctx, to_wire(in), (unsigned char *)in);
        !          1378:   hash->update(ctx, salt_len, salt);
        !          1379:   hash->digest(ctx, hash->digest_size, digest);
        !          1380: 
        !          1381:   for(i = 0; i < iterations; i++)
        !          1382:     {
        !          1383:       hash->update(ctx, hash->digest_size, digest);
        !          1384:       hash->update(ctx, salt_len, salt);
        !          1385:       hash->digest(ctx, hash->digest_size, digest);
        !          1386:     }
        !          1387:    
        !          1388:   from_wire(in);
        !          1389: 
        !          1390:   *out = digest;
        !          1391:   return hash->digest_size;
        !          1392: }
        !          1393: 
        !          1394: /* Decode base32 to first "." or end of string */
        !          1395: static int base32_decode(char *in, unsigned char *out)
        !          1396: {
        !          1397:   int oc, on, c, mask, i;
        !          1398:   unsigned char *p = out;
        !          1399:  
        !          1400:   for (c = *in, oc = 0, on = 0; c != 0 && c != '.'; c = *++in) 
        !          1401:     {
        !          1402:       if (c >= '0' && c <= '9')
        !          1403:        c -= '0';
        !          1404:       else if (c >= 'a' && c <= 'v')
        !          1405:        c -= 'a', c += 10;
        !          1406:       else if (c >= 'A' && c <= 'V')
        !          1407:        c -= 'A', c += 10;
        !          1408:       else
        !          1409:        return 0;
        !          1410:       
        !          1411:       for (mask = 0x10, i = 0; i < 5; i++)
        !          1412:         {
        !          1413:          if (c & mask)
        !          1414:            oc |= 1;
        !          1415:          mask = mask >> 1;
        !          1416:          if (((++on) & 7) == 0)
        !          1417:            *p++ = oc;
        !          1418:          oc = oc << 1;
        !          1419:        }
        !          1420:     }
        !          1421:   
        !          1422:   if ((on & 7) != 0)
        !          1423:     return 0;
        !          1424: 
        !          1425:   return p - out;
        !          1426: }
        !          1427: 
        !          1428: static int prove_non_existence_nsec3(struct dns_header *header, size_t plen, unsigned char **nsecs, int nsec_count,
        !          1429:                                     char *workspace1, char *workspace2, char *name, int type)
        !          1430: {
        !          1431:   unsigned char *salt, *p, *digest;
        !          1432:   int digest_len, i, iterations, salt_len, hash_len, base32_len, algo = 0;
        !          1433:   struct nettle_hash const *hash;
        !          1434:   char *closest_encloser, *next_closest, *wildcard;
        !          1435:  
        !          1436:   /* Look though the NSEC3 records to find the first one with 
        !          1437:      an algorithm we support (currently only algo == 1).
        !          1438: 
        !          1439:      Take the algo, iterations, and salt of that record
        !          1440:      as the ones we're going to use, and prune any 
        !          1441:      that don't match. */
        !          1442:   
        !          1443:   for (i = 0; i < nsec_count; i++)
        !          1444:     {
        !          1445:       if (!(p = skip_name(nsecs[i], header, plen, 15)))
        !          1446:        return STAT_BOGUS; /* bad packet */
        !          1447:       
        !          1448:       p += 10; /* type, class, TTL, rdlen */
        !          1449:       algo = *p++;
        !          1450:       
        !          1451:       if (algo == 1)
        !          1452:        break; /* known algo */
        !          1453:     }
        !          1454: 
        !          1455:   /* No usable NSEC3s */
        !          1456:   if (i == nsec_count)
        !          1457:     return STAT_BOGUS;
        !          1458: 
        !          1459:   p++; /* flags */
        !          1460:   GETSHORT (iterations, p);
        !          1461:   salt_len = *p++;
        !          1462:   salt = p;
        !          1463:   if (!CHECK_LEN(header, salt, plen, salt_len))
        !          1464:     return STAT_BOGUS; /* bad packet */
        !          1465:     
        !          1466:   /* Now prune so we only have NSEC3 records with same iterations, salt and algo */
        !          1467:   for (i = 0; i < nsec_count; i++)
        !          1468:     {
        !          1469:       unsigned char *nsec3p = nsecs[i];
        !          1470:       int this_iter;
        !          1471: 
        !          1472:       nsecs[i] = NULL; /* Speculative, will be restored if OK. */
        !          1473:       
        !          1474:       if (!(p = skip_name(nsec3p, header, plen, 15)))
        !          1475:        return STAT_BOGUS; /* bad packet */
        !          1476:       
        !          1477:       p += 10; /* type, class, TTL, rdlen */
        !          1478:       
        !          1479:       if (*p++ != algo)
        !          1480:        continue;
        !          1481:  
        !          1482:       p++; /* flags */
        !          1483:       
        !          1484:       GETSHORT(this_iter, p);
        !          1485:       if (this_iter != iterations)
        !          1486:        continue;
        !          1487: 
        !          1488:       if (salt_len != *p++)
        !          1489:        continue;
        !          1490:       
        !          1491:       if (!CHECK_LEN(header, p, plen, salt_len))
        !          1492:        return STAT_BOGUS; /* bad packet */
        !          1493: 
        !          1494:       if (memcmp(p, salt, salt_len) != 0)
        !          1495:        continue;
        !          1496: 
        !          1497:       /* All match, put the pointer back */
        !          1498:       nsecs[i] = nsec3p;
        !          1499:     }
        !          1500: 
        !          1501:   /* Algo is checked as 1 above */
        !          1502:   if (!(hash = hash_find("sha1")))
        !          1503:     return STAT_BOGUS;
        !          1504: 
        !          1505:   /* Now, we need the "closest encloser NSEC3" */
        !          1506:   closest_encloser = name;
        !          1507:   next_closest = NULL;
        !          1508: 
        !          1509:   do
        !          1510:     {
        !          1511:       if (*closest_encloser == '.')
        !          1512:        closest_encloser++;
        !          1513: 
        !          1514:       if ((digest_len = hash_name(closest_encloser, &digest, hash, salt, salt_len, iterations)) == 0)
        !          1515:        return STAT_BOGUS;
        !          1516:       
        !          1517:       for (i = 0; i < nsec_count; i++)
        !          1518:        if ((p = nsecs[i]))
        !          1519:          {
        !          1520:            if (!extract_name(header, plen, &p, workspace1, 1, 0) ||
        !          1521:                !(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
        !          1522:              return STAT_BOGUS;
        !          1523:          
        !          1524:            if (digest_len == base32_len &&
        !          1525:                memcmp(digest, workspace2, digest_len) == 0)
        !          1526:              break; /* Gotit */
        !          1527:          }
        !          1528:       
        !          1529:       if (i != nsec_count)
        !          1530:        break;
        !          1531:       
        !          1532:       next_closest = closest_encloser;
        !          1533:     }
        !          1534:   while ((closest_encloser = strchr(closest_encloser, '.')));
        !          1535:   
        !          1536:   /* No usable NSEC3s */
        !          1537:   if (i == nsec_count)
        !          1538:     return STAT_BOGUS;
        !          1539:   
        !          1540:   if (!next_closest)
        !          1541:     {
        !          1542:       /* We found an NSEC3 whose hashed name exactly matches the query, so
        !          1543:         Now we just need to check the type map. p points to the RR data for the record. */
        !          1544:       int rdlen;
        !          1545:       unsigned char *psave;
        !          1546:       int offset = (type & 0xff) >> 3;
        !          1547:       int mask = 0x80 >> (type & 0x07);
        !          1548:       
        !          1549:       p += 8; /* class, type, TTL */
        !          1550:       GETSHORT(rdlen, p);
        !          1551:       psave = p;
        !          1552:       p += 5 + salt_len; /* algo, flags, iterations, salt_len, salt */
        !          1553:       hash_len = *p++;
        !          1554:       if (!CHECK_LEN(header, p, plen, hash_len))
        !          1555:        return STAT_BOGUS; /* bad packet */
        !          1556:       p += hash_len;
        !          1557:       rdlen -= p - psave;
        !          1558:       
        !          1559:       while (rdlen >= 2)
        !          1560:        {
        !          1561:          if (!CHECK_LEN(header, p, plen, rdlen))
        !          1562:            return STAT_BOGUS;
        !          1563:          
        !          1564:          if (p[0] == type >> 8)
        !          1565:            {
        !          1566:              /* Does the NSEC3 say our type exists? */
        !          1567:              if (offset < p[1] && (p[offset+2] & mask) != 0)
        !          1568:                return STAT_BOGUS;
        !          1569:              
        !          1570:              break; /* finshed checking */
        !          1571:            }
        !          1572:          
        !          1573:          rdlen -= p[1];
        !          1574:          p +=  p[1];
        !          1575:        }
        !          1576:       
        !          1577:       return STAT_SECURE;
        !          1578:     }
        !          1579: 
        !          1580:   /* Look for NSEC3 that proves the non-existence of the next-closest encloser */
        !          1581:   if ((digest_len = hash_name(next_closest, &digest, hash, salt, salt_len, iterations)) == 0)
        !          1582:     return STAT_BOGUS;
        !          1583: 
        !          1584:   for (i = 0; i < nsec_count; i++)
        !          1585:     if ((p = nsecs[i]))
        !          1586:       {
        !          1587:                if (!extract_name(header, plen, &p, workspace1, 1, 0) ||
        !          1588:            !(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
        !          1589:          return STAT_BOGUS;
        !          1590:           
        !          1591:        p += 15 + salt_len; /* class, type, TTL, rdlen, algo, flags, iterations, salt_len, salt */
        !          1592:        hash_len = *p++; /* p now points to next hashed name */
        !          1593:  
        !          1594:        if (!CHECK_LEN(header, p, plen, hash_len))
        !          1595:          return STAT_BOGUS;
        !          1596:        
        !          1597:        if (digest_len == base32_len && hash_len == base32_len)
        !          1598:          {
        !          1599:            if (memcmp(workspace2, digest, digest_len) <= 0)
        !          1600:              {
        !          1601:                /* Normal case, hash falls between NSEC3 name-hash and next domain name-hash,
        !          1602:                   wrap around case, name-hash falls between NSEC3 name-hash and end */
        !          1603:                if (memcmp(p, digest, digest_len) > 0 || memcmp(workspace2, p, digest_len) > 0)
        !          1604:                  return STAT_SECURE;
        !          1605:              }
        !          1606:            else 
        !          1607:              {
        !          1608:                /* wrap around case, name falls between start and next domain name */
        !          1609:                if (memcmp(workspace2, p, digest_len) > 0 && memcmp(p, digest, digest_len) > 0)
        !          1610:                  return STAT_SECURE;
        !          1611:              }
        !          1612:          }
        !          1613:       }
        !          1614:   
        !          1615:   /* Finally, check that there's no seat of wildcard synthesis */
        !          1616:   if (!(wildcard = strchr(next_closest, '.')) || wildcard == next_closest)
        !          1617:     return STAT_BOGUS;
        !          1618:   
        !          1619:   wildcard--;
        !          1620:   *wildcard = '*';
        !          1621:   
        !          1622:   if ((digest_len = hash_name(wildcard, &digest, hash, salt, salt_len, iterations)) == 0)
        !          1623:     return STAT_BOGUS;
        !          1624:   
        !          1625:   for (i = 0; i < nsec_count; i++)
        !          1626:     if ((p = nsecs[i]))
        !          1627:       {
        !          1628:        if (!extract_name(header, plen, &p, workspace1, 1, 0) ||
        !          1629:            !(base32_len = base32_decode(workspace1, (unsigned char *)workspace2)))
        !          1630:          return STAT_BOGUS;
        !          1631:           
        !          1632:        p += 15 + salt_len; /* class, type, TTL, rdlen, algo, flags, iterations, salt_len, salt */
        !          1633:        hash_len = *p++; /* p now points to next hashed name */
        !          1634:  
        !          1635:        if (!CHECK_LEN(header, p, plen, hash_len))
        !          1636:          return STAT_BOGUS;
        !          1637:        
        !          1638:        if (digest_len == base32_len && hash_len == base32_len)
        !          1639:          {
        !          1640:            if (memcmp(workspace2, digest, digest_len) <= 0)
        !          1641:              {
        !          1642:                /* Normal case, hash falls between NSEC3 name-hash and next domain name-hash,
        !          1643:                   wrap around case, name-hash falls between NSEC3 name-hash and end */
        !          1644:                if (memcmp(p, digest, digest_len) > 0 || memcmp(workspace2, p, digest_len) > 0)
        !          1645:                  return STAT_SECURE;
        !          1646:              }
        !          1647:            else 
        !          1648:              {
        !          1649:                /* wrap around case, name falls between start and next domain name */
        !          1650:                if (memcmp(workspace2, p, digest_len) > 0 && memcmp(p, digest, digest_len) > 0)
        !          1651:                  return STAT_SECURE;
        !          1652:              }
        !          1653:          }
        !          1654:       }
        !          1655:   
        !          1656:   return STAT_BOGUS;
        !          1657: }
        !          1658:     
        !          1659: /* Validate all the RRsets in the answer and authority sections of the reply (4035:3.2.3) */
        !          1660: /* Returns are the same as validate_rrset, plus the class if the missing key is in *class */
        !          1661: int dnssec_validate_reply(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname, int *class, int *neganswer)
        !          1662: {
        !          1663:   unsigned char *ans_start, *qname, *p1, *p2, **nsecs;
        !          1664:   int type1, class1, rdlen1, type2, class2, rdlen2, qclass, qtype;
        !          1665:   int i, j, rc, nsec_count, cname_count = CNAME_CHAIN;
        !          1666:   int nsec_type = 0, have_answer = 0;
        !          1667: 
        !          1668:   if (neganswer)
        !          1669:     *neganswer = 0;
        !          1670:   
        !          1671:   if (RCODE(header) == SERVFAIL || ntohs(header->qdcount) != 1)
        !          1672:     return STAT_BOGUS;
        !          1673:   
        !          1674:   if (RCODE(header) != NXDOMAIN && RCODE(header) != NOERROR)
        !          1675:     return STAT_INSECURE;
        !          1676: 
        !          1677:   qname = p1 = (unsigned char *)(header+1);
        !          1678:   
        !          1679:   if (!extract_name(header, plen, &p1, name, 1, 4))
        !          1680:     return STAT_BOGUS;
        !          1681: 
        !          1682:   GETSHORT(qtype, p1);
        !          1683:   GETSHORT(qclass, p1);
        !          1684:   ans_start = p1;
        !          1685: 
        !          1686:   if (qtype == T_ANY)
        !          1687:     have_answer = 1;
        !          1688:  
        !          1689:   /* Can't validate an RRISG query */
        !          1690:   if (qtype == T_RRSIG)
        !          1691:     return STAT_INSECURE;
        !          1692:  
        !          1693:  cname_loop:
        !          1694:   for (j = ntohs(header->ancount); j != 0; j--) 
        !          1695:     {
        !          1696:       /* leave pointer to missing name in qname */
        !          1697:            
        !          1698:       if (!(rc = extract_name(header, plen, &p1, name, 0, 10)))
        !          1699:        return STAT_BOGUS; /* bad packet */
        !          1700:       
        !          1701:       GETSHORT(type2, p1); 
        !          1702:       GETSHORT(class2, p1);
        !          1703:       p1 += 4; /* TTL */
        !          1704:       GETSHORT(rdlen2, p1);
        !          1705: 
        !          1706:       if (rc == 1 && qclass == class2)
        !          1707:        {
        !          1708:          /* Do we have an answer for the question? */
        !          1709:          if (type2 == qtype)
        !          1710:            {
        !          1711:              have_answer = 1;
        !          1712:              break;
        !          1713:            }
        !          1714:          else if (type2 == T_CNAME)
        !          1715:            {
        !          1716:              qname = p1;
        !          1717:              
        !          1718:              /* looped CNAMES */
        !          1719:              if (!cname_count-- || !extract_name(header, plen, &p1, name, 1, 0))
        !          1720:                return STAT_BOGUS;
        !          1721:               
        !          1722:              p1 = ans_start;
        !          1723:              goto cname_loop;
        !          1724:            }
        !          1725:        } 
        !          1726: 
        !          1727:       if (!ADD_RDLEN(header, p1, plen, rdlen2))
        !          1728:        return STAT_BOGUS;
        !          1729:     }
        !          1730:    
        !          1731:   if (neganswer && !have_answer)
        !          1732:     *neganswer = 1;
        !          1733: 
        !          1734:   /* No data, therefore no sigs */
        !          1735:   if (ntohs(header->ancount) + ntohs(header->nscount) == 0)
        !          1736:     return STAT_NO_SIG;
        !          1737:   
        !          1738:   for (p1 = ans_start, i = 0; i < ntohs(header->ancount) + ntohs(header->nscount); i++)
        !          1739:     {
        !          1740:       if (!extract_name(header, plen, &p1, name, 1, 10))
        !          1741:        return STAT_BOGUS; /* bad packet */
        !          1742:       
        !          1743:       GETSHORT(type1, p1);
        !          1744:       GETSHORT(class1, p1);
        !          1745:       p1 += 4; /* TTL */
        !          1746:       GETSHORT(rdlen1, p1);
        !          1747:       
        !          1748:       /* Don't try and validate RRSIGs! */
        !          1749:       if (type1 != T_RRSIG)
        !          1750:        {
        !          1751:          /* Check if we've done this RRset already */
        !          1752:          for (p2 = ans_start, j = 0; j < i; j++)
        !          1753:            {
        !          1754:              if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
        !          1755:                return STAT_BOGUS; /* bad packet */
        !          1756:              
        !          1757:              GETSHORT(type2, p2);
        !          1758:              GETSHORT(class2, p2);
        !          1759:              p2 += 4; /* TTL */
        !          1760:              GETSHORT(rdlen2, p2);
        !          1761:              
        !          1762:              if (type2 == type1 && class2 == class1 && rc == 1)
        !          1763:                break; /* Done it before: name, type, class all match. */
        !          1764:              
        !          1765:              if (!ADD_RDLEN(header, p2, plen, rdlen2))
        !          1766:                return STAT_BOGUS;
        !          1767:            }
        !          1768:          
        !          1769:          /* Not done, validate now */
        !          1770:          if (j == i)
        !          1771:            {
        !          1772:              int ttl, keytag, algo, digest, type_covered;
        !          1773:              unsigned char *psave;
        !          1774:              struct all_addr a;
        !          1775:              struct blockdata *key;
        !          1776:              struct crec *crecp;
        !          1777:              
        !          1778:              rc = validate_rrset(now, header, plen, class1, type1, name, keyname, NULL, 0, 0, 0);
        !          1779:              
        !          1780:              if (rc == STAT_SECURE_WILDCARD)
        !          1781:                {
        !          1782:                  /* An attacker replay a wildcard answer with a different
        !          1783:                     answer and overlay a genuine RR. To prove this
        !          1784:                     hasn't happened, the answer must prove that
        !          1785:                     the gennuine record doesn't exist. Check that here. */
        !          1786:                  if (!nsec_type && !(nsec_type = find_nsec_records(header, plen, &nsecs, &nsec_count, class1)))
        !          1787:                    return STAT_BOGUS; /* No NSECs or bad packet */
        !          1788:                  
        !          1789:                  if (nsec_type == T_NSEC)
        !          1790:                    rc = prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1);
        !          1791:                  else
        !          1792:                    rc = prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, type1);
        !          1793: 
        !          1794:                  if (rc != STAT_SECURE)
        !          1795:                    return rc;
        !          1796:                } 
        !          1797:              else if (rc != STAT_SECURE)
        !          1798:                {
        !          1799:                  if (class)
        !          1800:                    *class = class1; /* Class for DS or DNSKEY */
        !          1801:                  return rc;
        !          1802:                }
        !          1803:              
        !          1804:              /* Cache RRsigs in answer section, and if we just validated a DS RRset, cache it */
        !          1805:              cache_start_insert();
        !          1806:              
        !          1807:              for (p2 = ans_start, j = 0; j < ntohs(header->ancount); j++)
        !          1808:                {
        !          1809:                  if (!(rc = extract_name(header, plen, &p2, name, 0, 10)))
        !          1810:                    return STAT_BOGUS; /* bad packet */
        !          1811:                      
        !          1812:                  GETSHORT(type2, p2);
        !          1813:                  GETSHORT(class2, p2);
        !          1814:                  GETLONG(ttl, p2);
        !          1815:                  GETSHORT(rdlen2, p2);
        !          1816:                       
        !          1817:                  if (!CHECK_LEN(header, p2, plen, rdlen2))
        !          1818:                    return STAT_BOGUS; /* bad packet */
        !          1819:                  
        !          1820:                  if (class2 == class1 && rc == 1)
        !          1821:                    { 
        !          1822:                      psave = p2;
        !          1823: 
        !          1824:                      if (type1 == T_DS && type2 == T_DS)
        !          1825:                        {
        !          1826:                          if (rdlen2 < 4)
        !          1827:                            return STAT_BOGUS; /* bad packet */
        !          1828:                          
        !          1829:                          GETSHORT(keytag, p2);
        !          1830:                          algo = *p2++;
        !          1831:                          digest = *p2++;
        !          1832:                          
        !          1833:                          /* Cache needs to known class for DNSSEC stuff */
        !          1834:                          a.addr.dnssec.class = class2;
        !          1835:                          
        !          1836:                          if ((key = blockdata_alloc((char*)p2, rdlen2 - 4)))
        !          1837:                            {
        !          1838:                              if (!(crecp = cache_insert(name, &a, now, ttl, F_FORWARD | F_DS | F_DNSSECOK)))
        !          1839:                                blockdata_free(key);
        !          1840:                              else
        !          1841:                                {
        !          1842:                                  a.addr.keytag = keytag;
        !          1843:                                  log_query(F_KEYTAG | F_UPSTREAM, name, &a, "DS keytag %u");
        !          1844:                                  crecp->addr.ds.digest = digest;
        !          1845:                                  crecp->addr.ds.keydata = key;
        !          1846:                                  crecp->addr.ds.algo = algo;
        !          1847:                                  crecp->addr.ds.keytag = keytag;
        !          1848:                                  crecp->addr.ds.keylen = rdlen2 - 4; 
        !          1849:                                } 
        !          1850:                            }
        !          1851:                        }
        !          1852:                      else if (type2 == T_RRSIG)
        !          1853:                        {
        !          1854:                          if (rdlen2 < 18)
        !          1855:                            return STAT_BOGUS; /* bad packet */
        !          1856:                          
        !          1857:                          GETSHORT(type_covered, p2);
        !          1858: 
        !          1859:                          if (type_covered == type1 && 
        !          1860:                              (type_covered == T_A || type_covered == T_AAAA ||
        !          1861:                               type_covered == T_CNAME || type_covered == T_DS || 
        !          1862:                               type_covered == T_DNSKEY || type_covered == T_PTR)) 
        !          1863:                            {
        !          1864:                              a.addr.dnssec.type = type_covered;
        !          1865:                              a.addr.dnssec.class = class1;
        !          1866:                              
        !          1867:                              algo = *p2++;
        !          1868:                              p2 += 13; /* labels, orig_ttl, expiration, inception */
        !          1869:                              GETSHORT(keytag, p2);
        !          1870:                              
        !          1871:                              if ((key = blockdata_alloc((char*)psave, rdlen2)))
        !          1872:                                {
        !          1873:                                  if (!(crecp = cache_insert(name, &a, now, ttl,  F_FORWARD | F_DNSKEY | F_DS)))
        !          1874:                                    blockdata_free(key);
        !          1875:                                  else
        !          1876:                                    {
        !          1877:                                      crecp->addr.sig.keydata = key;
        !          1878:                                      crecp->addr.sig.keylen = rdlen2;
        !          1879:                                      crecp->addr.sig.keytag = keytag;
        !          1880:                                      crecp->addr.sig.type_covered = type_covered;
        !          1881:                                      crecp->addr.sig.algo = algo;
        !          1882:                                    }
        !          1883:                                }
        !          1884:                            }
        !          1885:                        }
        !          1886:                      
        !          1887:                      p2 = psave;
        !          1888:                    }
        !          1889:                  
        !          1890:                  if (!ADD_RDLEN(header, p2, plen, rdlen2))
        !          1891:                    return STAT_BOGUS; /* bad packet */
        !          1892:                }
        !          1893:                  
        !          1894:              cache_end_insert();
        !          1895:            }
        !          1896:        }
        !          1897: 
        !          1898:       if (!ADD_RDLEN(header, p1, plen, rdlen1))
        !          1899:        return STAT_BOGUS;
        !          1900:     }
        !          1901: 
        !          1902:   /* OK, all the RRsets validate, now see if we have a NODATA or NXDOMAIN reply */
        !          1903:   if (have_answer)
        !          1904:     return STAT_SECURE;
        !          1905:      
        !          1906:   /* NXDOMAIN or NODATA reply, prove that (name, class1, type1) can't exist */
        !          1907:   /* First marshall the NSEC records, if we've not done it previously */
        !          1908:   if (!nsec_type && !(nsec_type = find_nsec_records(header, plen, &nsecs, &nsec_count, qclass)))
        !          1909:     return STAT_BOGUS; /* No NSECs */
        !          1910:    
        !          1911:   /* Get name of missing answer */
        !          1912:   if (!extract_name(header, plen, &qname, name, 1, 0))
        !          1913:     return STAT_BOGUS;
        !          1914:   
        !          1915:   if (nsec_type == T_NSEC)
        !          1916:     return prove_non_existence_nsec(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype);
        !          1917:   else
        !          1918:     return prove_non_existence_nsec3(header, plen, nsecs, nsec_count, daemon->workspacename, keyname, name, qtype);
        !          1919: }
        !          1920: 
        !          1921: /* Chase the CNAME chain in the packet until the first record which _doesn't validate.
        !          1922:    Needed for proving answer in unsigned space.
        !          1923:    Return STAT_NEED_* 
        !          1924:           STAT_BOGUS - error
        !          1925:           STAT_INSECURE - name of first non-secure record in name 
        !          1926: */
        !          1927: int dnssec_chase_cname(time_t now, struct dns_header *header, size_t plen, char *name, char *keyname)
        !          1928: {
        !          1929:   unsigned char *p = (unsigned char *)(header+1);
        !          1930:   int type, class, qclass, rdlen, j, rc;
        !          1931:   int cname_count = CNAME_CHAIN;
        !          1932: 
        !          1933:   /* Get question */
        !          1934:   if (!extract_name(header, plen, &p, name, 1, 4))
        !          1935:     return STAT_BOGUS;
        !          1936:   
        !          1937:   p +=2; /* type */
        !          1938:   GETSHORT(qclass, p);
        !          1939: 
        !          1940:   while (1)
        !          1941:     {
        !          1942:       for (j = ntohs(header->ancount); j != 0; j--) 
        !          1943:        {
        !          1944:          if (!(rc = extract_name(header, plen, &p, name, 0, 10)))
        !          1945:            return STAT_BOGUS; /* bad packet */
        !          1946:          
        !          1947:          GETSHORT(type, p); 
        !          1948:          GETSHORT(class, p);
        !          1949:          p += 4; /* TTL */
        !          1950:          GETSHORT(rdlen, p);
        !          1951: 
        !          1952:          /* Not target, loop */
        !          1953:          if (rc == 2 || qclass != class)
        !          1954:            {
        !          1955:              if (!ADD_RDLEN(header, p, plen, rdlen))
        !          1956:                return STAT_BOGUS;
        !          1957:              continue;
        !          1958:            }
        !          1959:          
        !          1960:          /* Got to end of CNAME chain. */
        !          1961:          if (type != T_CNAME)
        !          1962:            return STAT_INSECURE;
        !          1963:          
        !          1964:          /* validate CNAME chain, return if insecure or need more data */
        !          1965:          rc = validate_rrset(now, header, plen, class, type, name, keyname, NULL, 0, 0, 0);
        !          1966:          if (rc != STAT_SECURE)
        !          1967:            {
        !          1968:              if (rc == STAT_NO_SIG)
        !          1969:                rc = STAT_INSECURE;
        !          1970:              return rc;
        !          1971:            }
        !          1972: 
        !          1973:          /* Loop down CNAME chain/ */
        !          1974:          if (!cname_count-- || 
        !          1975:              !extract_name(header, plen, &p, name, 1, 0) ||
        !          1976:              !(p = skip_questions(header, plen)))
        !          1977:            return STAT_BOGUS;
        !          1978:          
        !          1979:          break;
        !          1980:        }
        !          1981: 
        !          1982:       /* End of CNAME chain */
        !          1983:       return STAT_INSECURE;    
        !          1984:     }
        !          1985: }
        !          1986: 
        !          1987: 
        !          1988: /* Compute keytag (checksum to quickly index a key). See RFC4034 */
        !          1989: int dnskey_keytag(int alg, int flags, unsigned char *key, int keylen)
        !          1990: {
        !          1991:   if (alg == 1)
        !          1992:     {
        !          1993:       /* Algorithm 1 (RSAMD5) has a different (older) keytag calculation algorithm.
        !          1994:          See RFC4034, Appendix B.1 */
        !          1995:       return key[keylen-4] * 256 + key[keylen-3];
        !          1996:     }
        !          1997:   else
        !          1998:     {
        !          1999:       unsigned long ac = flags + 0x300 + alg;
        !          2000:       int i;
        !          2001: 
        !          2002:       for (i = 0; i < keylen; ++i)
        !          2003:         ac += (i & 1) ? key[i] : key[i] << 8;
        !          2004: 
        !          2005:       ac += (ac >> 16) & 0xffff;
        !          2006:       return ac & 0xffff;
        !          2007:     }
        !          2008: }
        !          2009: 
        !          2010: size_t dnssec_generate_query(struct dns_header *header, char *end, char *name, int class, int type, union mysockaddr *addr)
        !          2011: {
        !          2012:   unsigned char *p;
        !          2013:   char *types = querystr("dnssec-query", type);
        !          2014: 
        !          2015:   if (addr->sa.sa_family == AF_INET) 
        !          2016:     log_query(F_DNSSEC | F_IPV4, name, (struct all_addr *)&addr->in.sin_addr, types);
        !          2017: #ifdef HAVE_IPV6
        !          2018:   else
        !          2019:     log_query(F_DNSSEC | F_IPV6, name, (struct all_addr *)&addr->in6.sin6_addr, types);
        !          2020: #endif
        !          2021:   
        !          2022:   header->qdcount = htons(1);
        !          2023:   header->ancount = htons(0);
        !          2024:   header->nscount = htons(0);
        !          2025:   header->arcount = htons(0);
        !          2026: 
        !          2027:   header->hb3 = HB3_RD; 
        !          2028:   SET_OPCODE(header, QUERY);
        !          2029:   /* For debugging, set Checking Disabled, otherwise, have the upstream check too,
        !          2030:      this allows it to select auth servers when one is returning bad data. */
        !          2031:   header->hb4 = option_bool(OPT_DNSSEC_DEBUG) ? HB4_CD : 0;
        !          2032: 
        !          2033:   /* ID filled in later */
        !          2034: 
        !          2035:   p = (unsigned char *)(header+1);
        !          2036:        
        !          2037:   p = do_rfc1035_name(p, name);
        !          2038:   *p++ = 0;
        !          2039:   PUTSHORT(type, p);
        !          2040:   PUTSHORT(class, p);
        !          2041: 
        !          2042:   return add_do_bit(header, p - (unsigned char *)header, end);
        !          2043: }
        !          2044: 
        !          2045: /* Go through a domain name, find "pointers" and fix them up based on how many bytes
        !          2046:    we've chopped out of the packet, or check they don't point into an elided part.  */
        !          2047: static int check_name(unsigned char **namep, struct dns_header *header, size_t plen, int fixup, unsigned char **rrs, int rr_count)
        !          2048: {
        !          2049:   unsigned char *ansp = *namep;
        !          2050: 
        !          2051:   while(1)
        !          2052:     {
        !          2053:       unsigned int label_type;
        !          2054:       
        !          2055:       if (!CHECK_LEN(header, ansp, plen, 1))
        !          2056:        return 0;
        !          2057:       
        !          2058:       label_type = (*ansp) & 0xc0;
        !          2059: 
        !          2060:       if (label_type == 0xc0)
        !          2061:        {
        !          2062:          /* pointer for compression. */
        !          2063:          unsigned int offset;
        !          2064:          int i;
        !          2065:          unsigned char *p;
        !          2066:          
        !          2067:          if (!CHECK_LEN(header, ansp, plen, 2))
        !          2068:            return 0;
        !          2069: 
        !          2070:          offset = ((*ansp++) & 0x3f) << 8;
        !          2071:          offset |= *ansp++;
        !          2072: 
        !          2073:          p = offset + (unsigned char *)header;
        !          2074:          
        !          2075:          for (i = 0; i < rr_count; i++)
        !          2076:            if (p < rrs[i])
        !          2077:              break;
        !          2078:            else
        !          2079:              if (i & 1)
        !          2080:                offset -= rrs[i] - rrs[i-1];
        !          2081: 
        !          2082:          /* does the pointer end up in an elided RR? */
        !          2083:          if (i & 1)
        !          2084:            return 0;
        !          2085: 
        !          2086:          /* No, scale the pointer */
        !          2087:          if (fixup)
        !          2088:            {
        !          2089:              ansp -= 2;
        !          2090:              *ansp++ = (offset >> 8) | 0xc0;
        !          2091:              *ansp++ = offset & 0xff;
        !          2092:            }
        !          2093:          break;
        !          2094:        }
        !          2095:       else if (label_type == 0x80)
        !          2096:        return 0; /* reserved */
        !          2097:       else if (label_type == 0x40)
        !          2098:        {
        !          2099:          /* Extended label type */
        !          2100:          unsigned int count;
        !          2101:          
        !          2102:          if (!CHECK_LEN(header, ansp, plen, 2))
        !          2103:            return 0;
        !          2104:          
        !          2105:          if (((*ansp++) & 0x3f) != 1)
        !          2106:            return 0; /* we only understand bitstrings */
        !          2107:          
        !          2108:          count = *(ansp++); /* Bits in bitstring */
        !          2109:          
        !          2110:          if (count == 0) /* count == 0 means 256 bits */
        !          2111:            ansp += 32;
        !          2112:          else
        !          2113:            ansp += ((count-1)>>3)+1;
        !          2114:        }
        !          2115:       else
        !          2116:        { /* label type == 0 Bottom six bits is length */
        !          2117:          unsigned int len = (*ansp++) & 0x3f;
        !          2118:          
        !          2119:          if (!ADD_RDLEN(header, ansp, plen, len))
        !          2120:            return 0;
        !          2121: 
        !          2122:          if (len == 0)
        !          2123:            break; /* zero length label marks the end. */
        !          2124:        }
        !          2125:     }
        !          2126: 
        !          2127:   *namep = ansp;
        !          2128: 
        !          2129:   return 1;
        !          2130: }
        !          2131: 
        !          2132: /* Go through RRs and check or fixup the domain names contained within */
        !          2133: static int check_rrs(unsigned char *p, struct dns_header *header, size_t plen, int fixup, unsigned char **rrs, int rr_count)
        !          2134: {
        !          2135:   int i, type, class, rdlen;
        !          2136:   unsigned char *pp;
        !          2137:   
        !          2138:   for (i = 0; i < ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount); i++)
        !          2139:     {
        !          2140:       pp = p;
        !          2141: 
        !          2142:       if (!(p = skip_name(p, header, plen, 10)))
        !          2143:        return 0;
        !          2144:       
        !          2145:       GETSHORT(type, p); 
        !          2146:       GETSHORT(class, p);
        !          2147:       p += 4; /* TTL */
        !          2148:       GETSHORT(rdlen, p);
        !          2149: 
        !          2150:       if (type != T_NSEC && type != T_NSEC3 && type != T_RRSIG)
        !          2151:        {
        !          2152:          /* fixup name of RR */
        !          2153:          if (!check_name(&pp, header, plen, fixup, rrs, rr_count))
        !          2154:            return 0;
        !          2155:          
        !          2156:          if (class == C_IN)
        !          2157:            {
        !          2158:              u16 *d;
        !          2159:  
        !          2160:              for (pp = p, d = get_desc(type); *d != (u16)-1; d++)
        !          2161:                {
        !          2162:                  if (*d != 0)
        !          2163:                    pp += *d;
        !          2164:                  else if (!check_name(&pp, header, plen, fixup, rrs, rr_count))
        !          2165:                    return 0;
        !          2166:                }
        !          2167:            }
        !          2168:        }
        !          2169:       
        !          2170:       if (!ADD_RDLEN(header, p, plen, rdlen))
        !          2171:        return 0;
        !          2172:     }
        !          2173:   
        !          2174:   return 1;
        !          2175: }
        !          2176:        
        !          2177: 
        !          2178: size_t filter_rrsigs(struct dns_header *header, size_t plen)
        !          2179: {
        !          2180:   static unsigned char **rrs;
        !          2181:   static int rr_sz = 0;
        !          2182:   
        !          2183:   unsigned char *p = (unsigned char *)(header+1);
        !          2184:   int i, rdlen, qtype, qclass, rr_found, chop_an, chop_ns, chop_ar;
        !          2185: 
        !          2186:   if (ntohs(header->qdcount) != 1 ||
        !          2187:       !(p = skip_name(p, header, plen, 4)))
        !          2188:     return plen;
        !          2189:   
        !          2190:   GETSHORT(qtype, p);
        !          2191:   GETSHORT(qclass, p);
        !          2192: 
        !          2193:   /* First pass, find pointers to start and end of all the records we wish to elide:
        !          2194:      records added for DNSSEC, unless explicity queried for */
        !          2195:   for (rr_found = 0, chop_ns = 0, chop_an = 0, chop_ar = 0, i = 0; 
        !          2196:        i < ntohs(header->ancount) + ntohs(header->nscount) + ntohs(header->arcount);
        !          2197:        i++)
        !          2198:     {
        !          2199:       unsigned char *pstart = p;
        !          2200:       int type, class;
        !          2201: 
        !          2202:       if (!(p = skip_name(p, header, plen, 10)))
        !          2203:        return plen;
        !          2204:       
        !          2205:       GETSHORT(type, p); 
        !          2206:       GETSHORT(class, p);
        !          2207:       p += 4; /* TTL */
        !          2208:       GETSHORT(rdlen, p);
        !          2209:       
        !          2210:       if ((type == T_NSEC || type == T_NSEC3 || type == T_RRSIG) && 
        !          2211:          (type != qtype || class != qclass))
        !          2212:        {
        !          2213:          if (!expand_workspace(&rrs, &rr_sz, rr_found + 1))
        !          2214:            return plen; 
        !          2215:          
        !          2216:          rrs[rr_found++] = pstart;
        !          2217: 
        !          2218:          if (!ADD_RDLEN(header, p, plen, rdlen))
        !          2219:            return plen;
        !          2220:          
        !          2221:          rrs[rr_found++] = p;
        !          2222:          
        !          2223:          if (i < ntohs(header->ancount))
        !          2224:            chop_an++;
        !          2225:          else if (i < (ntohs(header->nscount) + ntohs(header->ancount)))
        !          2226:            chop_ns++;
        !          2227:          else
        !          2228:            chop_ar++;
        !          2229:        }
        !          2230:       else if (!ADD_RDLEN(header, p, plen, rdlen))
        !          2231:        return plen;
        !          2232:     }
        !          2233:   
        !          2234:   /* Nothing to do. */
        !          2235:   if (rr_found == 0)
        !          2236:     return plen;
        !          2237: 
        !          2238:   /* Second pass, look for pointers in names in the records we're keeping and make sure they don't
        !          2239:      point to records we're going to elide. This is theoretically possible, but unlikely. If
        !          2240:      it happens, we give up and leave the answer unchanged. */
        !          2241:   p = (unsigned char *)(header+1);
        !          2242:   
        !          2243:   /* question first */
        !          2244:   if (!check_name(&p, header, plen, 0, rrs, rr_found))
        !          2245:     return plen;
        !          2246:   p += 4; /* qclass, qtype */
        !          2247:   
        !          2248:   /* Now answers and NS */
        !          2249:   if (!check_rrs(p, header, plen, 0, rrs, rr_found))
        !          2250:     return plen;
        !          2251:   
        !          2252:   /* Third pass, elide records */
        !          2253:   for (p = rrs[0], i = 1; i < rr_found; i += 2)
        !          2254:     {
        !          2255:       unsigned char *start = rrs[i];
        !          2256:       unsigned char *end = (i != rr_found - 1) ? rrs[i+1] : ((unsigned char *)(header+1)) + plen;
        !          2257:       
        !          2258:       memmove(p, start, end-start);
        !          2259:       p += end-start;
        !          2260:     }
        !          2261:      
        !          2262:   plen = p - (unsigned char *)header;
        !          2263:   header->ancount = htons(ntohs(header->ancount) - chop_an);
        !          2264:   header->nscount = htons(ntohs(header->nscount) - chop_ns);
        !          2265:   header->arcount = htons(ntohs(header->arcount) - chop_ar);
        !          2266: 
        !          2267:   /* Fourth pass, fix up pointers in the remaining records */
        !          2268:   p = (unsigned char *)(header+1);
        !          2269:   
        !          2270:   check_name(&p, header, plen, 1, rrs, rr_found);
        !          2271:   p += 4; /* qclass, qtype */
        !          2272:   
        !          2273:   check_rrs(p, header, plen, 1, rrs, rr_found);
        !          2274:   
        !          2275:   return plen;
        !          2276: }
        !          2277: 
        !          2278: unsigned char* hash_questions(struct dns_header *header, size_t plen, char *name)
        !          2279: {
        !          2280:   int q;
        !          2281:   unsigned int len;
        !          2282:   unsigned char *p = (unsigned char *)(header+1);
        !          2283:   const struct nettle_hash *hash;
        !          2284:   void *ctx;
        !          2285:   unsigned char *digest;
        !          2286:   
        !          2287:   if (!(hash = hash_find("sha1")) || !hash_init(hash, &ctx, &digest))
        !          2288:     return NULL;
        !          2289:   
        !          2290:   for (q = ntohs(header->qdcount); q != 0; q--) 
        !          2291:     {
        !          2292:       if (!extract_name(header, plen, &p, name, 1, 4))
        !          2293:        break; /* bad packet */
        !          2294:       
        !          2295:       len = to_wire(name);
        !          2296:       hash->update(ctx, len, (unsigned char *)name);
        !          2297:       /* CRC the class and type as well */
        !          2298:       hash->update(ctx, 4, p);
        !          2299: 
        !          2300:       p += 4;
        !          2301:       if (!CHECK_LEN(header, p, plen, 0))
        !          2302:        break; /* bad packet */
        !          2303:     }
        !          2304:   
        !          2305:   hash->digest(ctx, hash->digest_size, digest);
        !          2306:   return digest;
        !          2307: }
        !          2308: 
        !          2309: #endif /* HAVE_DNSSEC */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>