5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome/* -*- Mode: C; tab-width: 4 -*-
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome * Copyright (c) 2012-2013 Apple Inc. All rights reserved.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * Licensed under the Apache License, Version 2.0 (the "License");
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * you may not use this file except in compliance with the License.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * You may obtain a copy of the License at
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * http://www.apache.org/licenses/LICENSE-2.0
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * Unless required by applicable law or agreed to in writing, software
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * distributed under the License is distributed on an "AS IS" BASIS,
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * See the License for the specific language governing permissions and
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * limitations under the License.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome#include "mDNSEmbeddedAPI.h"
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome#include "CryptoAlg.h"
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome#include "anonymous.h"
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome#include "DNSCommon.h"
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// Define ANONYMOUS_DISABLED to remove all the anonymous functionality
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// and use the stub functions implemented later in this file.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome#ifndef ANONYMOUS_DISABLED
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome#define ANON_NSEC3_ITERATIONS 1
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soomestruct AnonInfoResourceRecord_struct
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome{
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome ResourceRecord resrec;
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome RData rdatastorage;
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome};
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soometypedef struct AnonInfoResourceRecord_struct AnonInfoResourceRecord;
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSlocal mDNSBool InitializeNSEC3Record(ResourceRecord *rr, const mDNSu8 *AnonData, int len, mDNSu32 salt)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome{
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome const mDNSu8 *ptr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome rdataNSEC3 *nsec3 = (rdataNSEC3 *)rr->rdata->u.data;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome mDNSu8 *tmp, *nxt;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome unsigned short iter = ANON_NSEC3_ITERATIONS;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome int hlen;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome const mDNSu8 hashName[NSEC3_MAX_HASH_LEN];
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // Construct the RDATA first and construct the owner name based on that.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ptr = (const mDNSu8 *)&salt;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("InitializeNSEC3Record: %x%x%x%x, name %##s", ptr[0], ptr[1], ptr[2], ptr[3], rr->name->c);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // Set the RDATA
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome nsec3->alg = SHA1_DIGEST_TYPE;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome nsec3->flags = 0;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome nsec3->iterations = swap16(iter);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome nsec3->saltLength = 4;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome tmp = (mDNSu8 *)&nsec3->salt;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *tmp++ = ptr[0];
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *tmp++ = ptr[1];
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *tmp++ = ptr[2];
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *tmp++ = ptr[3];
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // hashLength, nxt, bitmap
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *tmp++ = SHA1_HASH_LENGTH; // hash length
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome nxt = tmp;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome tmp += SHA1_HASH_LENGTH;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *tmp++ = 0; // window number
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *tmp++ = NSEC_MCAST_WINDOW_SIZE; // window length
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome mDNSPlatformMemZero(tmp, NSEC_MCAST_WINDOW_SIZE);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome tmp[kDNSType_PTR >> 3] |= 128 >> (kDNSType_PTR & 7);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // Hash the base service name + salt + AnonData
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!NSEC3HashName(rr->name, nsec3, AnonData, len, hashName, &hlen))
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome LogMsg("InitializeNSEC3Record: NSEC3HashName failed for ##s", rr->name->c);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return mDNSfalse;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (hlen != SHA1_HASH_LENGTH)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome LogMsg("InitializeNSEC3Record: hlen wrong %d", hlen);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return mDNSfalse;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome mDNSPlatformMemCopy(nxt, hashName, hlen);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return mDNStrue;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome}
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSlocal ResourceRecord *ConstructNSEC3Record(const domainname *service, const mDNSu8 *AnonData, int len, mDNSu32 salt)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome{
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ResourceRecord *rr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome int dlen;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome domainname *name;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // We are just allocating an RData which has StandardAuthRDSize
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (StandardAuthRDSize < MCAST_NSEC3_RDLENGTH)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome LogMsg("ConstructNSEC3Record: StandardAuthRDSize %d smaller than MCAST_NSEC3_RDLENGTH %d", StandardAuthRDSize, MCAST_NSEC3_RDLENGTH);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return mDNSNULL;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome dlen = DomainNameLength(service);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // Allocate space for the name and RData.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome rr = mDNSPlatformMemAllocate(sizeof(ResourceRecord) + dlen + sizeof(RData));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!rr)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return mDNSNULL;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome name = (domainname *)((mDNSu8 *)rr + sizeof(ResourceRecord));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome rr->RecordType = kDNSRecordTypePacketAuth;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome rr->InterfaceID = mDNSInterface_Any;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome rr->name = (const domainname *)name;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome rr->rrtype = kDNSType_NSEC3;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome rr->rrclass = kDNSClass_IN;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome rr->rroriginalttl = kStandardTTL;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome rr->rDNSServer = mDNSNULL;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome rr->rdlength = MCAST_NSEC3_RDLENGTH;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome rr->rdestimate = MCAST_NSEC3_RDLENGTH;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome rr->rdata = (RData *)((mDNSu8 *)rr->name + dlen);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome AssignDomainName(name, service);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!InitializeNSEC3Record(rr, AnonData, len, salt))
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome mDNSPlatformMemFree(rr);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return mDNSNULL;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return rr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome}
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSlocal ResourceRecord *CopyNSEC3ResourceRecord(AnonymousInfo *si, const ResourceRecord *rr)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome{
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome AnonInfoResourceRecord *anonRR;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome domainname *name;
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome mDNSu32 neededLen;
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome mDNSu32 extraLen;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (rr->rdlength < MCAST_NSEC3_RDLENGTH)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome LogMsg("CopyNSEC3ResourceRecord: rdlength %d smaller than MCAST_NSEC3_RDLENGTH %d", rr->rdlength, MCAST_NSEC3_RDLENGTH);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return mDNSNULL;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // Allocate space for the name and the rdata along with the ResourceRecord
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome neededLen = rr->rdlength + DomainNameLength(rr->name);
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome extraLen = (neededLen > sizeof(RDataBody)) ? (neededLen - sizeof(RDataBody)) : 0;
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome anonRR = (AnonInfoResourceRecord *)mDNSPlatformMemAllocate(sizeof(AnonInfoResourceRecord) + extraLen);
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome if (!anonRR)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return mDNSNULL;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome anonRR->resrec = *rr;
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome anonRR->rdatastorage.MaxRDLength = rr->rdlength;
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome mDNSPlatformMemCopy(anonRR->rdatastorage.u.data, rr->rdata->u.data, rr->rdlength);
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome name = (domainname *)(anonRR->rdatastorage.u.data + rr->rdlength);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome AssignDomainName(name, rr->name);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome anonRR->resrec.name = name;
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome anonRR->resrec.rdata = &anonRR->rdatastorage;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome si->nsec3RR = (ResourceRecord *)anonRR;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome return si->nsec3RR;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome}
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// When a service is started or a browse is started with the Anonymous data, we allocate a new random
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// number and based on that allocate a new NSEC3 resource record whose hash is a function of random number (salt) and
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// the anonymous data.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome//
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// If we receive a packet with the NSEC3 option, we need to cache that along with the resource record so that we can
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// check against the question to see whether it answers them or not. In that case, we pass the "rr" that we received.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport AnonymousInfo *AllocateAnonInfo(const domainname *service, const mDNSu8 *data, int len, const ResourceRecord *rr)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome{
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome AnonymousInfo *ai;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ai = (AnonymousInfo *)mDNSPlatformMemAllocate(sizeof(AnonymousInfo));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!ai)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return mDNSNULL;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome mDNSPlatformMemZero(ai, sizeof(AnonymousInfo));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (rr)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!CopyNSEC3ResourceRecord(ai, rr))
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome mDNSPlatformMemFree(ai);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return mDNSNULL;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return ai;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ai->salt = mDNSRandom(0xFFFFFFFF);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ai->AnonData = mDNSPlatformMemAllocate(len);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!ai->AnonData)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome mDNSPlatformMemFree(ai);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return mDNSNULL;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ai->AnonDataLen = len;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome mDNSPlatformMemCopy(ai->AnonData, data, len);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ai->nsec3RR = ConstructNSEC3Record(service, data, len, ai->salt);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!ai->nsec3RR)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome mDNSPlatformMemFree(ai);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return mDNSNULL;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return ai;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome}
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport void FreeAnonInfo(AnonymousInfo *ai)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome{
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (ai->nsec3RR)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome mDNSPlatformMemFree(ai->nsec3RR);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (ai->AnonData)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome mDNSPlatformMemFree(ai->AnonData);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome mDNSPlatformMemFree(ai);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome}
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport void ReInitAnonInfo(AnonymousInfo **AnonInfo, const domainname *name)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome{
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (*AnonInfo)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome AnonymousInfo *ai = *AnonInfo;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *AnonInfo = AllocateAnonInfo(name, ai->AnonData, ai->AnonDataLen, mDNSNULL);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!(*AnonInfo))
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *AnonInfo = ai;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome else
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome FreeAnonInfo(ai);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome}
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// This function should be used only if you know that the question and
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// the resource record belongs to the same set. The main usage is
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// in ProcessQuery where we find the question to be part of the same
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// set as the resource record, but it needs the AnonData to be
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// initialized so that it can walk the cache records to see if they
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// answer the question.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport void SetAnonData(DNSQuestion *q, ResourceRecord *rr, mDNSBool ForQuestion)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome{
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!q->AnonInfo || !rr->AnonInfo)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome LogMsg("SetAnonData: question %##s(%p), rr %##s(%p), NULL", q->qname.c, q->AnonInfo, rr->name->c, rr->AnonInfo);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("SetAnonData: question %##s(%p), rr %##s(%p)", q->qname.c, q->AnonInfo, rr->name->c, rr->AnonInfo);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (ForQuestion)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!q->AnonInfo->AnonData)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome q->AnonInfo->AnonData = mDNSPlatformMemAllocate(rr->AnonInfo->AnonDataLen);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!q->AnonInfo->AnonData)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome mDNSPlatformMemCopy(q->AnonInfo->AnonData, rr->AnonInfo->AnonData, rr->AnonInfo->AnonDataLen);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome q->AnonInfo->AnonDataLen = rr->AnonInfo->AnonDataLen;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome else
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!rr->AnonInfo->AnonData)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome rr->AnonInfo->AnonData = mDNSPlatformMemAllocate(q->AnonInfo->AnonDataLen);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!rr->AnonInfo->AnonData)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome mDNSPlatformMemCopy(rr->AnonInfo->AnonData, q->AnonInfo->AnonData, q->AnonInfo->AnonDataLen);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome rr->AnonInfo->AnonDataLen = q->AnonInfo->AnonDataLen;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome}
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// returns -1 if the caller should ignore the result
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// returns 1 if the record answers the question
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// returns 0 if the record does not answer the question
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport int AnonInfoAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome{
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome mDNSexport mDNS mDNSStorage;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ResourceRecord *nsec3RR;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome int i;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome AnonymousInfo *qai, *rai;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome mDNSu8 *AnonData;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome int AnonDataLen;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome rdataNSEC3 *nsec3;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome int hlen;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome const mDNSu8 hashName[NSEC3_MAX_HASH_LEN];
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome int nxtLength;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome mDNSu8 *nxtName;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("AnonInfoAnswersQuestion: question qname %##s", q->qname.c);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // Currently only PTR records can have anonymous information
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (q->qtype != kDNSType_PTR)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return -1;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // We allow anonymous questions to be answered by both normal services (without the
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // anonymous information) and anonymous services that are part of the same set. And
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // normal questions discover normal services and all anonymous services.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome //
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // The three cases have been enumerated clearly even though they all behave the
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // same way.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!q->AnonInfo)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("AnonInfoAnswersQuestion: not a anonymous type question");
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!rr->AnonInfo)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // case 1
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return -1;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome else
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // case 2
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("AnonInfoAnswersQuestion: Question %##s not answered using anonymous record %##s", q->qname.c, rr->name->c);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return -1;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome else
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // case 3
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!rr->AnonInfo)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("AnonInfoAnswersQuestion: not a anonymous type record");
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return -1;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // case 4: We have the anonymous information both in the question and the record. We need
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // two sets of information to validate.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome //
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // 1) Anonymous data that identifies the set/group
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // 2) NSEC3 record that contains the hash and the salt
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome //
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // If the question is a remote one, it does not have the anonymous information to validate (just
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // the NSEC3 record) and hence the anonymous data should come from the local resource record. If the
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // question is local, it can come from either of them and if there is a mismatch between the
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // question and record, it won't validate.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome qai = q->AnonInfo;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome rai = rr->AnonInfo;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (qai->AnonData && rai->AnonData)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // Before a cache record is created, if there is a matching question i.e., part
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // of the same set, then when the cache is created we also set the anonymous
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // information. Otherwise, the cache record contains just the NSEC3 record and we
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // won't be here for that case.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome //
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // It is also possible that a local question is matched against the local AuthRecord
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // as that is also the case for which the AnonData would be non-NULL for both.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // We match questions against AuthRecords (rather than the cache) for LocalOnly case and
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // to see whether a .local query should be suppressed or not. The latter never happens
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // because PTR queries are never suppressed.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // If they don't belong to the same anonymous set, then no point in validating.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if ((qai->AnonDataLen != rai->AnonDataLen) ||
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome mDNSPlatformMemCmp(qai->AnonData, rai->AnonData, qai->AnonDataLen) != 0)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("AnonInfoAnswersQuestion: AnonData mis-match for record %s question %##s ",
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome RRDisplayString(&mDNSStorage, rr), q->qname.c);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return 0;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // AnonData matches i.e they belong to the same group and the same service.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome LogInfo("AnonInfoAnswersQuestion: Answering qname %##s, rname %##s, without validation", q->qname.c,
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome rr->name->c);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return 1;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome else
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("AnonInfoAnswersQuestion: question %p, record %p", qai->AnonData, rai->AnonData);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (qai->AnonData)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // If there is AnonData, then this is a local question. The
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // NSEC3 RR comes from the resource record which could be part
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // of the cache or local auth record. The cache entry could
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // be from a remote host or created when we heard our own
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // announcements. In any case, we use that to see if it matches
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // the question.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome AnonData = qai->AnonData;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome AnonDataLen = qai->AnonDataLen;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome nsec3RR = rai->nsec3RR;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome else
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // Remote question or hearing our own question back
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome AnonData = rai->AnonData;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome AnonDataLen = rai->AnonDataLen;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome nsec3RR = qai->nsec3RR;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!AnonData || !nsec3RR)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // AnonData can be NULL for the cache entry and if we are hearing our own question back, AnonData is NULL for
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // that too and we can end up here for that case.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("AnonInfoAnswersQuestion: AnonData %p or nsec3RR %p, NULL for question %##s, record %s", AnonData, nsec3RR,
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome q->qname.c, RRDisplayString(&mDNSStorage, rr));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return 0;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("AnonInfoAnswersQuestion: Validating question %##s, ResourceRecord %s", q->qname.c, RRDisplayString(&mDNSStorage, nsec3RR));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome nsec3 = (rdataNSEC3 *)nsec3RR->rdata->u.data;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!NSEC3HashName(nsec3RR->name, nsec3, AnonData, AnonDataLen, hashName, &hlen))
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome LogMsg("AnonInfoAnswersQuestion: NSEC3HashName failed for ##s", nsec3RR->name->c);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return mDNSfalse;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (hlen != SHA1_HASH_LENGTH)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome LogMsg("AnonInfoAnswersQuestion: hlen wrong %d", hlen);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return mDNSfalse;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome NSEC3Parse(nsec3RR, mDNSNULL, &nxtLength, &nxtName, mDNSNULL, mDNSNULL);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (hlen != nxtLength)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome LogMsg("AnonInfoAnswersQuestion: ERROR!! hlen %d not same as nxtLength %d", hlen, nxtLength);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return mDNSfalse;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome for (i = 0; i < nxtLength; i++)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (nxtName[i] != hashName[i])
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("AnonInfoAnswersQuestion: mismatch output %x, digest %x, i %d", nxtName[i+1], hashName[i], i);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return 0;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome LogInfo("AnonInfoAnswersQuestion: ResourceRecord %s matched question %##s (%s)", RRDisplayString(&mDNSStorage, nsec3RR), q->qname.c, DNSTypeName(q->qtype));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return 1;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome}
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// Find a matching NSEC3 record for the name. We parse the questions and the records in the packet in order.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// Similarly we also parse the NSEC3 records in order and this mapping to the questions and records
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// respectively.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSlocal CacheRecord *FindMatchingNSEC3ForName(mDNS *const m, CacheRecord **nsec3, const domainname *name)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome{
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome CacheRecord *cr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome CacheRecord **prev = nsec3;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void) m;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome for (cr = *nsec3; cr; cr = cr->next)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (SameDomainName(cr->resrec.name, name))
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("FindMatchingNSEC3ForName: NSEC3 record %s matched %##s", CRDisplayString(m, cr), name->c);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *prev = cr->next;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome cr->next = mDNSNULL;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return cr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome prev = &cr->next;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return mDNSNULL;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome}
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport void InitializeAnonInfoForQuestion(mDNS *const m, CacheRecord **McastNSEC3Records, DNSQuestion *q)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome{
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome CacheRecord *nsec3CR;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (q->qtype != kDNSType_PTR)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome nsec3CR = FindMatchingNSEC3ForName(m, McastNSEC3Records, &q->qname);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (nsec3CR)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome q->AnonInfo = AllocateAnonInfo(mDNSNULL, mDNSNULL, 0, &nsec3CR->resrec);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (q->AnonInfo)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("InitializeAnonInfoForQuestion: Found a matching NSEC3 record %s, for %##s (%s)",
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome RRDisplayString(m, q->AnonInfo->nsec3RR), q->qname.c, DNSTypeName(q->qtype));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ReleaseCacheRecord(m, nsec3CR);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome}
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport void InitializeAnonInfoForCR(mDNS *const m, CacheRecord **McastNSEC3Records, CacheRecord *cr)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome{
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome CacheRecord *nsec3CR;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!(*McastNSEC3Records))
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // If already initialized or not a PTR type, we don't have to do anything
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (cr->resrec.AnonInfo || cr->resrec.rrtype != kDNSType_PTR)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome nsec3CR = FindMatchingNSEC3ForName(m, McastNSEC3Records, cr->resrec.name);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (nsec3CR)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome cr->resrec.AnonInfo = AllocateAnonInfo(mDNSNULL, mDNSNULL, 0, &nsec3CR->resrec);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (cr->resrec.AnonInfo)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("InitializeAnonInfoForCR: Found a matching NSEC3 record %s, for %##s (%s)",
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome RRDisplayString(m, cr->resrec.AnonInfo->nsec3RR), cr->resrec.name->c,
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome DNSTypeName(cr->resrec.rrtype));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ReleaseCacheRecord(m, nsec3CR);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome}
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport mDNSBool IdenticalAnonInfo(AnonymousInfo *a1, AnonymousInfo *a2)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome{
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // if a1 is NULL and a2 is not NULL AND vice-versa
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // return false as there is a change.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if ((a1 != mDNSNULL) != (a2 != mDNSNULL))
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return mDNSfalse;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // Both could be NULL or non-NULL
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (a1 && a2)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // The caller already verified that the owner name is the same.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // Check whether the RData is same.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!IdenticalSameNameRecord(a1->nsec3RR, a2->nsec3RR))
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome debugf("IdenticalAnonInfo: nsec3RR mismatch");
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return mDNSfalse;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return mDNStrue;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome}
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport void CopyAnonInfoForCR(mDNS *const m, CacheRecord *crto, CacheRecord *crfrom)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome{
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome AnonymousInfo *aifrom = crfrom->resrec.AnonInfo;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome AnonymousInfo *aito = crto->resrec.AnonInfo;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void) m;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (!aifrom)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (aito)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome crto->resrec.AnonInfo = aifrom;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome FreeAnonInfo(aito);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome crfrom->resrec.AnonInfo = mDNSNULL;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome else
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome FreeAnonInfo(aifrom);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome crfrom->resrec.AnonInfo = mDNSNULL;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome }
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome}
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome#else // !ANONYMOUS_DISABLED
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport void ReInitAnonInfo(AnonymousInfo **si, const domainname *name)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome{
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void)si;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void)name;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome}
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport AnonymousInfo * AllocateAnonInfo(const domainname *service, const mDNSu8 *AnonData, int len, const ResourceRecord *rr)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome{
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void)service;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void)AnonData;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void)len;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void)rr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return mDNSNULL;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome}
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport void FreeAnonInfo(AnonymousInfo *ai)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome{
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void)ai;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome}
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport void SetAnonData(DNSQuestion *q, ResourceRecord *rr, mDNSBool ForQuestion)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome{
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void)q;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void)rr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void)ForQuestion;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome}
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport int AnonInfoAnswersQuestion(const ResourceRecord *const rr, const DNSQuestion *const q)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome{
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void)rr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void)q;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return mDNSfalse;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome}
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport void InitializeAnonInfoForQuestion(mDNS *const m, CacheRecord **McastNSEC3Records, DNSQuestion *q)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome{
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void)m;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void)McastNSEC3Records;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void)q;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome}
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport void InitializeAnonInfoForCR(mDNS *const m, CacheRecord **McastNSEC3Records, CacheRecord *cr)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome{
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void)m;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void)McastNSEC3Records;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void)cr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome}
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport void CopyAnonInfoForCR(mDNS *const m, CacheRecord *crto, CacheRecord *crfrom)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome{
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void)m;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void)crto;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void)crfrom;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome}
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas SoomemDNSexport mDNSBool IdenticalAnonInfo(AnonymousInfo *a1, AnonymousInfo *a2)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome{
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void)a1;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome (void)a2;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return mDNStrue;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome}
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome#endif // !ANONYMOUS_DISABLED