Changeset 2036

Show
Ignore:
Timestamp:
02/17/11 11:21:16 (2 years ago)
Author:
ahu
Message:

TSIG-verify first answer chunk ('envelope') of incoming AXFR. I don't understand the RFC on how to verify subsequent
envelopes.

Location:
trunk/pdns/pdns
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • trunk/pdns/pdns/resolver.cc

    r2035 r2036  
    134134} 
    135135 
    136 static int parseResult(const char* buffer, unsigned int len, const std::string& origQname, uint16_t origQtype, uint16_t id, Resolver::res_t* result) 
     136static int parseResult(MOADNSParser& mdp, const std::string& origQname, uint16_t origQtype, uint16_t id, Resolver::res_t* result) 
    137137{ 
    138138  result->clear(); 
    139   shared_ptr<MOADNSParser> mdp; 
    140    
    141   try { 
    142     mdp=shared_ptr<MOADNSParser>(new MOADNSParser(buffer, len)); 
    143   } 
    144   catch(...) { 
    145     throw ResolverException("resolver: unable to parse packet of "+itoa(len)+" bytes"); 
    146   } 
    147    
    148   if(mdp->d_header.rcode)  
    149     return mdp->d_header.rcode; 
     139   
     140  if(mdp.d_header.rcode)  
     141    return mdp.d_header.rcode; 
    150142       
    151143  if(!origQname.empty()) {  // not AXFR 
    152     if(mdp->d_header.id != id)  
     144    if(mdp.d_header.id != id)  
    153145      throw ResolverException("Remote nameserver replied with wrong id"); 
    154     if(mdp->d_header.qdcount != 1) 
    155       throw ResolverException("resolver: received answer with wrong number of questions ("+itoa(mdp->d_header.qdcount)+")"); 
    156     if(mdp->d_qname != origQname+".") 
    157       throw ResolverException(string("resolver: received an answer to another question (")+mdp->d_qname+"!="+ origQname+".)"); 
     146    if(mdp.d_header.qdcount != 1) 
     147      throw ResolverException("resolver: received answer with wrong number of questions ("+itoa(mdp.d_header.qdcount)+")"); 
     148    if(mdp.d_qname != origQname+".") 
     149      throw ResolverException(string("resolver: received an answer to another question (")+mdp.d_qname+"!="+ origQname+".)"); 
    158150  } 
    159151     
    160152  vector<DNSResourceRecord> ret;  
    161153  DNSResourceRecord rr; 
    162   for(MOADNSParser::answers_t::const_iterator i=mdp->d_answers.begin(); i!=mdp->d_answers.end(); ++i) {           
     154  for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {           
    163155    rr.qname = i->first.d_label; 
    164156    if(!rr.qname.empty()) 
     
    267259      throw ResolverException("recvfrom error waiting for answer: "+stringerror()); 
    268260   
    269     return parseResult(buffer, len, domain, type, id, res); 
     261    MOADNSParser mdp(buffer, len); 
     262    return parseResult(mdp, domain, type, id, res); 
    270263  } 
    271264  catch(ResolverException &re) { 
     
    297290 
    298291AXFRRetriever::AXFRRetriever(const ComboAddress& remote, const string& domain, const string& tsigkeyname, const string& tsigalgorithm, const string& tsigsecret) 
     292: d_tsigkeyname(tsigkeyname), d_tsigsecret(tsigsecret) 
    299293{ 
    300294  ComboAddress local; 
     
    317311 
    318312  if(!tsigkeyname.empty()) { 
    319     TSIGRecordContent trc; 
    320     trc.d_algoName = tsigalgorithm + ".sig-alg.reg.int."; 
    321     trc.d_time = time(0); 
    322     trc.d_fudge = 300; 
    323     trc.d_origID=ntohs(pw.getHeader()->id); 
    324     trc.d_eRcode=0; 
    325     addTSIG(pw, &trc, tsigkeyname, tsigsecret, "", false); 
     313    d_trc.d_algoName = tsigalgorithm + ".sig-alg.reg.int."; 
     314    d_trc.d_time = time(0); 
     315    d_trc.d_fudge = 300; 
     316    d_trc.d_origID=ntohs(pw.getHeader()->id); 
     317    d_trc.d_eRcode=0; 
     318    addTSIG(pw, &d_trc, tsigkeyname, tsigsecret, "", false); 
    326319  } 
    327320 
     
    358351  timeoutReadn(len);  
    359352 
    360   int err = parseResult(d_buf.get(), len, "", 0, 0, &res); 
     353  MOADNSParser mdp(d_buf.get(), len); 
     354   
     355  if(!d_soacount && !d_tsigkeyname.empty()) { // TSIG verify first message 
     356    string theirMac; 
     357    BOOST_FOREACH(const MOADNSParser::answers_t::value_type& answer, mdp.d_answers) { 
     358      if(answer.first.d_type == QType::TSIG) 
     359        theirMac = boost::dynamic_pointer_cast<TSIGRecordContent>(answer.first.d_content)->d_mac; 
     360    } 
     361    string message = makeTSIGMessageFromTSIGPacket(string(d_buf.get(), len), mdp.getTSIGPos(), d_tsigkeyname, d_trc, d_trc.d_mac, false); // insert our question MAC 
     362    string ourMac=calculateMD5HMAC(d_tsigsecret, message); 
     363    // ourMac[0]++; // sabotage 
     364    if(ourMac != theirMac) 
     365      throw ResolverException("AXFR response from "+d_remote.toStringWithPort()+" was not signed correctly with TSIG key '"+d_tsigkeyname+"'"); 
     366  } 
     367   
     368  int err = parseResult(mdp, "", 0, 0, &res); 
    361369  if(err)  
    362370    throw ResolverException("AXFR chunk with a non-zero rcode "+lexical_cast<string>(err)); 
  • trunk/pdns/pdns/resolver.hh

    r2035 r2036  
    9696    int d_soacount; 
    9797    ComboAddress d_remote; 
     98     
     99    string d_tsigkeyname; 
     100    string d_tsigsecret; 
     101    TSIGRecordContent d_trc; 
    98102}; 
    99103