File: tsigverifier.cc

package info (click to toggle)
pdns-recursor 4.1.11-1+deb10u1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 7,936 kB
  • sloc: cpp: 54,211; javascript: 26,587; sh: 11,872; makefile: 453; xml: 37
file content (74 lines) | stat: -rw-r--r-- 2,292 bytes parent folder | download | duplicates (3)
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

#include "tsigverifier.hh"
#include "dnssecinfra.hh"
#include "gss_context.hh"

bool TSIGTCPVerifier::check(const string& data, const MOADNSParser& mdp)
{
  if(d_tt.name.empty()) { // TSIG verify message
    return true;
  }

  string theirMac;
  bool checkTSIG = false;
  // If we have multiple messages, we need to concatenate them together. We also need to make sure we know the location of
  // the TSIG record so we can remove it in makeTSIGMessageFromTSIGPacket
  d_signData.append(data);
  if (mdp.getTSIGPos() == 0) {
    d_tsigPos += data.size();
  }
  else {
    d_tsigPos += mdp.getTSIGPos();
  }

  for(const auto& answer :  mdp.d_answers) {
    if (answer.first.d_type == QType::SOA) {
      // A SOA is either the first or the last record. We need to check TSIG if that's the case.
      checkTSIG = true;
    }

    if(answer.first.d_type == QType::TSIG) {
      shared_ptr<TSIGRecordContent> trc = getRR<TSIGRecordContent>(answer.first);
      if(trc) {
        theirMac = trc->d_mac;
        d_trc.d_time = trc->d_time;
        d_trc.d_fudge = trc->d_fudge;
        d_trc.d_eRcode = trc->d_eRcode;
        d_trc.d_origID = trc->d_origID;
        checkTSIG = true;
      }
    }
  }

  if(!checkTSIG && d_nonSignedMessages > 99) { // We're allowed to get 100 digest without a TSIG.
    throw std::runtime_error("No TSIG message received in last 100 messages of AXFR transfer.");
  }

  if (checkTSIG) {
    if (theirMac.empty()) {
      throw std::runtime_error("No TSIG on AXFR response from "+d_remote.toStringWithPort()+" , should be signed with TSIG key '"+d_tt.name.toString()+"'");
    }

    try {
      if (!d_prevMac.empty()) {
        validateTSIG(d_signData, d_tsigPos, d_tt, d_trc, d_prevMac, theirMac, true, d_signData.size()-data.size());
      }
      else {
        validateTSIG(d_signData, d_tsigPos, d_tt, d_trc, d_trc.d_mac, theirMac, false);
      }
    }
    catch(const std::runtime_error& err) {
      throw std::runtime_error("Error while validating TSIG signature on AXFR response from "+d_remote.toStringWithPort()+":"+err.what());
    }

    // Reset and store some values for the next chunks.
    d_prevMac = theirMac;
    d_nonSignedMessages = 0;
    d_signData.clear();
    d_tsigPos = 0;
  }
  else
    d_nonSignedMessages++;

  return true;
}