File: nsec.c

package info (click to toggle)
validns 0.8%2Bgit20230810.a7e6b4f-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,260 kB
  • sloc: ansic: 7,496; perl: 308; makefile: 163
file content (148 lines) | stat: -rw-r--r-- 4,232 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
 * Part of DNS zone file validator `validns`.
            604800  NSEC    example.com. NS DS RRSIG NSEC
            604800  RRSIG   NSEC 10 3 604800 20130321184221 (
                    20130219184221 35615 example.com.
                    WWg7EiYoY8Hp593I2i5Mkl2ezg7YuAnq0y75
                    oymTCuEfGwh4OxbMT/mWNqAFL5Y8f0YoQOOY
                    wZP0m/sGK/EJN7ulNsfQyULY4WsyHIGlKMwT
                    KdyDXJLrmrzlmRnGv7pFb0bo53n3osE0uFfH
                    yMQYOkQRYfqa4yWXF9Nl48dy67frtVih0foy
                    9Mm76mmJSDUd/jGsYQmaoFGVU/a64rWapVQ9
                    O/mXPqr6Pw2ZCHecsF4ElMEp41YqG1DfR5QR
                    khTjvTlg4aTKvgX1YuvDhjUygSHit47xn2NC
                    2WwEZF+vYXT9DIUCMcKdVeb4bjWwUXbWNFqz
                    Ca3jb/mpOpUDFnrRPw== )
 *
 * Copyright 2011-2014 Anton Berezin <tobez@tobez.org>
 * Modified BSD license.
 * (See LICENSE file in the distribution.)
 *
 */
#include <ctype.h>
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include "common.h"
#include "textparse.h"
#include "mempool.h"
#include "carp.h"
#include "rr.h"

static struct rr* nsec_parse(char *name, long ttl, int type, char *s)
{
    struct rr_nsec *rr = getmem(sizeof(*rr));
    struct binary_data bitmap;
    char *str_type = NULL;
    int ltype;

    rr->next_domain = extract_name(&s, "next domain", KEEP_CAPITALIZATION);
    /* TODO: validate next_domain, http://tools.ietf.org/html/rfc4034#section-4.1.1 */

    bitmap = new_set();
    while (s && *s) {
        str_type = extract_label(&s, "type list", "temporary");
        if (!str_type) return NULL;
        ltype = str2rdtype(str_type, NULL);
        if (ltype < 0)
            return NULL;
        add_bit_to_set(&bitmap, ltype);
    }
    if (!s)
        return NULL;
    if (!str_type) {
        return bitch("NSEC type list should not be empty");
    }
    rr->type_bitmap = compressed_set(&bitmap);
    G.dnssec_active = 1;

    return store_record(type, name, ttl, rr);
}

static char* nsec_human(struct rr *rrv)
{
    RRCAST(nsec);
    char ss[1024];
    char *s = ss;
    int l;
    char *base;
    int i, k;
    int type;
    char *type_name;

    l = snprintf(s, 1024, "%s", rr->next_domain);
    s += l;
    base = rr->type_bitmap.data;
    while (base - rr->type_bitmap.data < rr->type_bitmap.length) {
        for (i = 0; i < base[1]; i++) {
            for (k = 0; k <= 7; k++) {
                if (base[2+i] & (0x80 >> k)) {
                    type = ((unsigned char)base[0])*256 + i*8 + k;
                    type_name = rdtype2str(type);
                    l = snprintf(s, 1024-(s-ss), " %s", type_name);
                    s += l;
                }
            }
        }
        base += base[1]+2;
    }
    return quickstrdup_temp(ss);
}

static struct binary_data nsec_wirerdata(struct rr *rrv)
{
    RRCAST(nsec);

    return compose_binary_data("dd", 1,
        name2wire_name(rr->next_domain), rr->type_bitmap);
}

static void* nsec_validate(struct rr *rrv)
{
    RRCAST(nsec);
    struct named_rr *named_rr;

    named_rr = rr->rr.rr_set->named_rr;
    if (!check_typemap(rr->type_bitmap, named_rr, rrv))
        return NULL;

    return rr;
}

void validate_nsec_chain(void)
{
    struct rr_set *rr_set;
    struct named_rr *named_rr;

    rr_set = find_rr_set(T_NSEC, zone_apex);
    if (!rr_set) {
        named_rr = find_named_rr(zone_apex);
        moan(named_rr->file_name, named_rr->line, "apex NSEC not found");
        return;
    }
    while (1) {
        char name[1024];
        struct rr_nsec *rr = (struct rr_nsec *)rr_set->tail;
        char *s, *t;

        if (strcasecmp(rr->next_domain, zone_apex) == 0) /* chain complete */
            break;
        freeall_temp();
        s = rr->next_domain;
        t = name;
        while (*s) *t++ = tolower(*s++);
        *t = 0;
        rr_set = find_rr_set(T_NSEC, name);
        if (!rr_set) {
            moan(rr->rr.file_name, rr->rr.line, "broken NSEC chain %s -> %s",
                 rr->rr.rr_set->named_rr->name, rr->next_domain);
            break;
        }
    }
    freeall_temp();
}

struct rr_methods nsec_methods = { nsec_parse, nsec_human, nsec_wirerdata, NULL, nsec_validate };