1
2 #include "tsigverifier.hh"
3 #include "dnssecinfra.hh"
4
check(const string & data,const MOADNSParser & mdp)5 bool TSIGTCPVerifier::check(const string& data, const MOADNSParser& mdp)
6 {
7 if(d_tt.name.empty()) { // TSIG verify message
8 return true;
9 }
10
11 string theirMac;
12 bool checkTSIG = false;
13 // If we have multiple messages, we need to concatenate them together. We also need to make sure we know the location of
14 // the TSIG record so we can remove it in makeTSIGMessageFromTSIGPacket
15 d_signData.append(data);
16 if (mdp.getTSIGPos() == 0) {
17 d_tsigPos += data.size();
18 }
19 else {
20 d_tsigPos += mdp.getTSIGPos();
21 }
22
23 for(const auto& answer : mdp.d_answers) {
24 if (answer.first.d_type == QType::SOA) {
25 // A SOA is either the first or the last record. We need to check TSIG if that's the case.
26 checkTSIG = true;
27 }
28
29 if(answer.first.d_type == QType::TSIG) {
30 shared_ptr<TSIGRecordContent> trc = getRR<TSIGRecordContent>(answer.first);
31 if(trc) {
32 theirMac = trc->d_mac;
33 d_trc.d_time = trc->d_time;
34 d_trc.d_fudge = trc->d_fudge;
35 d_trc.d_eRcode = trc->d_eRcode;
36 d_trc.d_origID = trc->d_origID;
37 checkTSIG = true;
38 }
39 }
40 }
41
42 if(!checkTSIG && d_nonSignedMessages > 99) { // We're allowed to get 100 digest without a TSIG.
43 throw std::runtime_error("No TSIG message received in last 100 messages of AXFR transfer.");
44 }
45
46 if (checkTSIG) {
47 if (theirMac.empty()) {
48 throw std::runtime_error("No TSIG on AXFR response from "+d_remote.toStringWithPort()+" , should be signed with TSIG key '"+d_tt.name.toLogString()+"'");
49 }
50
51 try {
52 if (!d_prevMac.empty()) {
53 validateTSIG(d_signData, d_tsigPos, d_tt, d_trc, d_prevMac, theirMac, true, d_signData.size()-data.size());
54 }
55 else {
56 validateTSIG(d_signData, d_tsigPos, d_tt, d_trc, d_trc.d_mac, theirMac, false);
57 }
58 }
59 catch(const std::runtime_error& err) {
60 throw std::runtime_error("Error while validating TSIG signature on AXFR response from "+d_remote.toStringWithPort()+":"+err.what());
61 }
62
63 // Reset and store some values for the next chunks.
64 d_prevMac = theirMac;
65 d_nonSignedMessages = 0;
66 d_signData.clear();
67 d_tsigPos = 0;
68 }
69 else
70 d_nonSignedMessages++;
71
72 return true;
73 }
74