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