1 /* -*- Mode: C; tab-width: 4 -*- 2 * 3 * Copyright (c) 2011 Apple Computer, Inc. All rights reserved. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 #ifndef __DNSSEC_H 18 #define __DNSSEC_H 19 20 #include "CryptoAlg.h" 21 #include "mDNSDebug.h" 22 23 typedef enum 24 { 25 RRVS_rr, RRVS_rrsig, RRVS_key, RRVS_rrsig_key, RRVS_ds, RRVS_done, 26 } RRVerifierSet; 27 28 typedef struct RRVerifier_struct RRVerifier; 29 typedef struct DNSSECVerifier_struct DNSSECVerifier; 30 typedef struct AuthChain_struct AuthChain; 31 typedef struct InsecureContext_struct InsecureContext; 32 33 struct RRVerifier_struct 34 { 35 RRVerifier *next; 36 mDNSu16 rrtype; 37 mDNSu16 rrclass; 38 mDNSu32 rroriginalttl; 39 mDNSu16 rdlength; 40 mDNSu16 found; 41 mDNSu32 namehash; 42 mDNSu32 rdatahash; 43 domainname name; 44 mDNSu8 *rdata; 45 }; 46 47 // Each AuthChain element has one rrset (with multiple resource records of same type), rrsig and key 48 // that validates the rrset. 49 struct AuthChain_struct 50 { 51 AuthChain *next; // Next element in the chain 52 RRVerifier *rrset; // RRSET that is authenticated 53 RRVerifier *rrsig; // Signature for that RRSET 54 RRVerifier *key; // Public key for that RRSET 55 }; 56 57 #define ResetAuthChain(dv) { \ 58 (dv)->ac = mDNSNULL; \ 59 (dv)->actail = &((dv)->ac); \ 60 } 61 62 typedef void DNSSECVerifierCallback (mDNS *const m, DNSSECVerifier *dv, DNSSECStatus status); 63 // 64 // When we do a validation for a question, there might be additional validations that needs to be done e.g., 65 // wildcard expanded answer. It is also possible that in the case of nsec we need to prove both that a wildcard 66 // does not apply and the closest encloser proves that name does not exist. We identify these with the following 67 // flags. 68 // 69 // Note: In the following, by "marking the validation", we mean that as part of validation we need to prove 70 // the ones that are marked with. 71 // 72 // A wildcard may be used to answer a question. In that case, we need to verify that the right wildcard was 73 // used in answering the question. This is done by marking the validation with WILDCARD_PROVES_ANSWER_EXPANDED. 74 // 75 // Sometimes we get a NXDOMAIN response. In this case, we may have a wildcard where we need to prove 76 // that the wildcard proves that the name does not exist. This is done by marking the validation with 77 // WILDCARD_PROVES_NONAME_EXISTS. 78 // 79 // In the case of NODATA error, sometimes the name may exist but the query type does not exist. This is done by 80 // marking the validation with NSEC_PROVES_NOTYPE_EXISTS. 81 // 82 // In both NXDOMAIN and NODATA proofs, we may have to prove that the NAME does not exist. This is done by marking 83 // the validation with NSEC_PROVES_NONAME_EXISTS. 84 // 85 #define WILDCARD_PROVES_ANSWER_EXPANDED 0x00000001 86 #define WILDCARD_PROVES_NONAME_EXISTS 0x00000002 87 #define NSEC_PROVES_NOTYPE_EXISTS 0x00000004 88 #define NSEC_PROVES_NONAME_EXISTS 0x00000008 89 #define NSEC3_OPT_OUT 0x00000010 // OptOut was set in NSEC3 90 91 struct DNSSECVerifier_struct 92 { 93 domainname origName; // Original question name that needs verification 94 mDNSu16 origType; // Original question type corresponding to origName 95 mDNSu16 currQtype; // Current question type that is being verified 96 mDNSInterfaceID InterfaceID; // InterfaceID of the question 97 DNSQuestion q; 98 mDNSu8 recursed; // Number of times recursed during validation 99 mDNSu8 ValidationRequired; // Copy of the question's ValidationRequired status 100 mDNSu8 InsecureProofDone; 101 mDNSu8 NumPackets; // Number of packets that we send on the wire for DNSSEC verification. 102 mDNSs32 StartTime; // Time the DNSSEC verification starts 103 mDNSu32 flags; 104 RRVerifierSet next; 105 domainname *wildcardName; // set if the answer is wildcard expanded 106 RRVerifier *pendingNSEC; 107 DNSSECVerifierCallback *DVCallback; 108 DNSSECVerifier *parent; 109 RRVerifier *rrset; // rrset for which we have to verify 110 RRVerifier *rrsig; // RRSIG for rrset 111 RRVerifier *key; // DNSKEY for rrset 112 RRVerifier *rrsigKey; // RRSIG for DNSKEY 113 RRVerifier *ds; // DS for DNSKEY set in parent zone 114 AuthChain *saveac; 115 AuthChain *ac; 116 AuthChain **actail; 117 AlgContext *ctx; 118 }; 119 120 121 struct InsecureContext_struct 122 { 123 DNSSECVerifier *dv; // dv for which we are doing the insecure proof 124 mDNSu8 skip; // labels to skip for forming the name from origName 125 DNSSECStatus status; // status to deliver when done 126 mDNSu8 triggerLabelCount; // Label count of the name that triggered the insecure proof 127 DNSQuestion q; 128 }; 129 130 #define LogDNSSEC LogOperation 131 132 #define DNS_SERIAL_GT(a, b) ((int)((a) - (b)) > 0) 133 #define DNS_SERIAL_LT(a, b) ((int)((a) - (b)) < 0) 134 135 extern void StartDNSSECVerification(mDNS *const m, void *context); 136 extern RRVerifier* AllocateRRVerifier(const ResourceRecord *const rr, mStatus *status); 137 extern mStatus AddRRSetToVerifier(DNSSECVerifier *dv, const ResourceRecord *const rr, RRVerifier *rv, RRVerifierSet set); 138 extern void VerifySignature(mDNS *const m, DNSSECVerifier *dv, DNSQuestion *q); 139 extern void FreeDNSSECVerifier(mDNS *const m, DNSSECVerifier *dv); 140 extern DNSSECVerifier *AllocateDNSSECVerifier(mDNS *const m, const domainname *name, mDNSu16 rrtype, mDNSInterfaceID InterfaceID, 141 mDNSu8 ValidationRequired, DNSSECVerifierCallback dvcallback, mDNSQuestionCallback qcallback); 142 extern void InitializeQuestion(mDNS *const m, DNSQuestion *question, mDNSInterfaceID InterfaceID, const domainname *qname, 143 mDNSu16 qtype, mDNSQuestionCallback *callback, void *context); 144 extern void ValidateRRSIG(DNSSECVerifier *dv, RRVerifierSet type, const ResourceRecord *const rr); 145 extern void AuthChainLink(DNSSECVerifier *dv, AuthChain *ae); 146 extern mStatus DNSNameToLowerCase(domainname *d, domainname *result); 147 extern int DNSMemCmp(const mDNSu8 *const m1, const mDNSu8 *const m2, int len); 148 extern int DNSSECCanonicalOrder(const domainname *const d1, const domainname *const d2, int *subdomain); 149 extern void ProveInsecure(mDNS *const m, DNSSECVerifier *dv, InsecureContext *ic, domainname *trigger); 150 extern void BumpDNSSECStats(mDNS *const m, DNSSECStatsAction action, DNSSECStatsType type, mDNSu32 value); 151 extern char *DNSSECStatusName(DNSSECStatus status); 152 153 // DNSSECProbe belongs in DNSSECSupport.h but then we don't want to expose yet another plaform specific dnssec file 154 // to other platforms where dnssec is not supported. 155 extern void DNSSECProbe(mDNS *const m); 156 157 #endif // __DNSSEC_H 158