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

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

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