summaryrefslogtreecommitdiffstats
path: root/mDNSResponder/mDNSCore/dnssec.h
blob: b770af8de0a9e6a032302c03c22e49b6433cfed3 (plain) (blame)
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
149
150
151
152
153
154
155
156
157
158
/* -*- Mode: C; tab-width: 4 -*-
 *
 * Copyright (c) 2011-2013 Apple Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef __DNSSEC_H
#define __DNSSEC_H

#include "CryptoAlg.h"
#include "mDNSDebug.h"

typedef enum
{
    RRVS_rr, RRVS_rrsig, RRVS_key, RRVS_rrsig_key, RRVS_ds, RRVS_done,
} RRVerifierSet;

typedef struct RRVerifier_struct RRVerifier;
typedef struct DNSSECVerifier_struct DNSSECVerifier;
typedef struct AuthChain_struct AuthChain;
typedef struct InsecureContext_struct InsecureContext;

struct RRVerifier_struct
{
    RRVerifier *next;
    mDNSu16 rrtype;
    mDNSu16 rrclass;
    mDNSu32 rroriginalttl;
    mDNSu16 rdlength;
    mDNSu16 found;
    mDNSu32 namehash;
    mDNSu32 rdatahash;
    domainname name;
    mDNSu8  *rdata;
};

// Each AuthChain element has one rrset (with multiple resource records of same type), rrsig and key
// that validates the rrset.
struct AuthChain_struct
{
	AuthChain  *next;		// Next element in the chain
	RRVerifier *rrset;		// RRSET that is authenticated
	RRVerifier *rrsig;		// Signature for that RRSET
	RRVerifier *key;		// Public key for that RRSET
};

#define ResetAuthChain(dv) {    \
    (dv)->ac = mDNSNULL;        \
    (dv)->actail = &((dv)->ac); \
}

typedef void DNSSECVerifierCallback (mDNS *const m, DNSSECVerifier *dv, DNSSECStatus status);
//
// When we do a validation for a question, there might be additional validations that needs to be done e.g.,
// wildcard expanded answer. It is also possible that in the case of nsec we need to prove both that a wildcard
// does not apply and the closest encloser proves that name does not exist. We identify these with the following
// flags.
//
// Note: In the following, by "marking the validation", we mean that as part of validation we need to prove
// the ones that are marked with.
//
// A wildcard may be used to answer a question. In that case, we need to verify that the right wildcard was
// used in answering the question. This is done by marking the validation with WILDCARD_PROVES_ANSWER_EXPANDED.
//
// Sometimes we get a NXDOMAIN response. In this case, we may have a wildcard where we need to prove
// that the wildcard proves that the name does not exist. This is done by marking the validation with
// WILDCARD_PROVES_NONAME_EXISTS.
//
// In the case of NODATA error, sometimes the name may exist but the query type does not exist. This is done by
// marking the validation with NSEC_PROVES_NOTYPE_EXISTS.
//
// In both NXDOMAIN and NODATA proofs, we may have to prove that the NAME does not exist. This is done by marking
// the validation with NSEC_PROVES_NONAME_EXISTS.
//
#define WILDCARD_PROVES_ANSWER_EXPANDED 0x00000001
#define WILDCARD_PROVES_NONAME_EXISTS   0x00000002
#define NSEC_PROVES_NOTYPE_EXISTS       0x00000004
#define NSEC_PROVES_NONAME_EXISTS       0x00000008
#define NSEC3_OPT_OUT					0x00000010 // OptOut was set in NSEC3

struct DNSSECVerifier_struct
{
    domainname origName;            // Original question name that needs verification
    mDNSu16 origType;               // Original question type corresponding to origName
    mDNSu16 currQtype;              // Current question type that is being verified
    mDNSInterfaceID InterfaceID;    // InterfaceID of the question
    DNSQuestion q;
    mDNSu8 recursed;                // Number of times recursed during validation
    mDNSu8 ValidationRequired;      // Copy of the question's ValidationRequired status
    mDNSu8 InsecureProofDone;
    mDNSu8 NumPackets;              // Number of packets that we send on the wire for DNSSEC verification.
    mDNSs32 StartTime;              // Time the DNSSEC verification starts
    mDNSu32 flags;
    RRVerifierSet next;
    domainname *wildcardName;       // set if the answer is wildcard expanded
    RRVerifier *pendingNSEC;
    DNSSECVerifierCallback *DVCallback;
    DNSSECVerifier *parent;
    RRVerifier *rrset;              // rrset for which we have to verify
    RRVerifier *rrsig;              // RRSIG for rrset
    RRVerifier *key;                // DNSKEY for rrset
    RRVerifier *rrsigKey;           // RRSIG for DNSKEY
    RRVerifier *ds;                 // DS for DNSKEY set in parent zone
    AuthChain *saveac;
    AuthChain *ac;
    AuthChain **actail;
    AlgContext *ctx;
};


struct InsecureContext_struct
{
    DNSSECVerifier *dv;             // dv for which we are doing the insecure proof
    mDNSu8 skip;                    // labels to skip for forming the name from origName
    DNSSECStatus status;            // status to deliver when done
    mDNSu8 triggerLabelCount;       // Label count of the name that triggered the insecure proof
    DNSQuestion q;
};

#define LogDNSSEC LogOperation

#define DNS_SERIAL_GT(a, b) ((int)((a) - (b)) > 0)
#define DNS_SERIAL_LT(a, b) ((int)((a) - (b)) < 0)

extern void StartDNSSECVerification(mDNS *const m, void *context);
extern RRVerifier* AllocateRRVerifier(const ResourceRecord *const rr, mStatus *status);
extern mStatus AddRRSetToVerifier(DNSSECVerifier *dv, const ResourceRecord *const rr, RRVerifier *rv, RRVerifierSet set);
extern void VerifySignature(mDNS *const m, DNSSECVerifier *dv, DNSQuestion *q);
extern void FreeDNSSECVerifier(mDNS *const m, DNSSECVerifier *dv);
extern DNSSECVerifier *AllocateDNSSECVerifier(mDNS *const m, const domainname *name, mDNSu16 rrtype, mDNSInterfaceID InterfaceID,
                                              mDNSu8 ValidationRequired, DNSSECVerifierCallback dvcallback, mDNSQuestionCallback qcallback);
extern void InitializeQuestion(mDNS *const m, DNSQuestion *question, mDNSInterfaceID InterfaceID, const domainname *qname,
                               mDNSu16 qtype, mDNSQuestionCallback *callback, void *context);
extern void ValidateRRSIG(DNSSECVerifier *dv, RRVerifierSet type, const ResourceRecord *const rr);
extern void AuthChainLink(DNSSECVerifier *dv, AuthChain *ae);
extern mStatus DNSNameToLowerCase(domainname *d, domainname *result);
extern int DNSMemCmp(const mDNSu8 *const m1, const mDNSu8 *const m2, int len);
extern int DNSSECCanonicalOrder(const domainname *const d1, const domainname *const d2, int *subdomain);
extern void ProveInsecure(mDNS *const m, DNSSECVerifier *dv, InsecureContext *ic, domainname *trigger);
extern void BumpDNSSECStats(mDNS *const m, DNSSECStatsAction action, DNSSECStatsType type, mDNSu32 value);
extern char *DNSSECStatusName(DNSSECStatus status);

// DNSSECProbe belongs in DNSSECSupport.h but then we don't want to expose yet another plaform specific dnssec file
// to other platforms where dnssec is not supported.
extern void DNSSECProbe(mDNS *const m);

#endif // __DNSSEC_H