case CookieEntry::Support::Unknown:
assert(0);
case CookieEntry::Support::Unsupported:
- default:
- cerr << "This server does not support cookies or we don't know yet:" << endl;
+ cerr << "This server does not support cookies" << endl;
+ break;
}
}
else {
uint16_t ercode = (edo.d_extRCode << 4) | lwr->d_rcode;
if (ercode == ERCode::BADCOOKIE) {
lwr->d_validpacket = true;
- return LWResult::Result::BadCookie;
+ return LWResult::Result::BadCookie; // proper use of BacCookie, we did update he entry
}
}
else {
- // Server responded with a wrong client cookie, fall back to TCP
- cerr << "Wrong cookie" << endl;
- lwr->d_validpacket = true;
- return LWResult::Result::Spoofed;
+ if (!doTCP) {
+ // Server responded with a wrong client cookie, fall back to TCP
+ cerr << "Wrong cookie" << endl;
+ lwr->d_validpacket = true;
+ return LWResult::Result::Spoofed;
+ }
+ // ignore bad cookie when already doing TCP
}
}
else {
- // We sent a cookie out but it's not in the table?
+ // We receivd cookie (we might have sent one out) but it's not in the table?
cerr << "Cookie not found back"<< endl;
- lwr->d_validpacket = true;
- return LWResult::Result::BadCookie; // XXX
+ lwr->d_rcode = RCode::FormErr;
+ lwr->d_validpacket = false;
+ return LWResult::Result::Success; // success - oddly enough
}
}
else {
- cerr << "Malformed cookie in reply"<< endl;
- lwr->d_validpacket = true;
- return LWResult::Result::BadCookie; // XXX
+ cerr << "Malformed cookie in reply" << endl;
+ // Do something special if we get malformed repeatedly? And or consider current status: Supported
+ lwr->d_rcode = RCode::FormErr;
+ lwr->d_validpacket = false;
+ return LWResult::Result::Success; // succes - odly enough
}
}
}
// Case: we sent out a cookie but did not get one back
if (cookieSentOut && !cookieFoundInReply && !*chained) {
cerr << "No cookie in reply"<< endl;
- lwr->d_validpacket = true;
- return LWResult::Result::BadCookie; // XXX
+ auto lock = s_cookiestore.lock();
+ auto found = lock->find(address);
+ if (found != lock->end()) {
+ switch (found->getSupport()) {
+ case CookieEntry::Support::Unknown:
+ assert(0);
+ case CookieEntry::Support::Probing:
+ cerr << "Was probing, setting support to Unsupported" << endl;
+ found->setSupport(CookieEntry::Support::Unsupported);
+ break;
+ case CookieEntry::Support::Unsupported:
+ break;
+ case CookieEntry::Support::Supported:
+ lwr->d_validpacket = true;
+ return LWResult::Result::BadCookie; // XXX, we did not update cookie info...
+ break;
+ }
+ }
+ else {
+ // Table entry lost? XXX
+ }
}
if (outgoingLoggers) {
class CookiesTest(RecursorTest):
_confdir = 'Cookies'
-
_config_template = """
recursor:
forward_zones:
- zone: cookies.example
- forwarders: [%s.25]
+ forwarders: [%s.25, %s.26]
outgoing:
- cookies: true""" % (os.environ['PREFIX'])
+ cookies: true""" % (os.environ['PREFIX'], os.environ['PREFIX'])
_expectedCookies = 'no'
@classmethod
def startResponders(cls):
print("Launching responders..")
- address = cls._PREFIX + '.25'
+ address1 = cls._PREFIX + '.25'
+ address2 = cls._PREFIX + '.26'
port = 53
- reactor.listenUDP(port, UDPResponder(), interface=address)
- reactor.listenTCP(port, TCPFactory(), interface=address)
+ reactor.listenUDP(port, UDPResponder(), interface=address1)
+ reactor.listenTCP(port, TCPFactory(), interface=address1)
+ reactor.listenUDP(port, UDPResponder(), interface=address2)
+ reactor.listenTCP(port, TCPFactory(), interface=address2)
if not reactor.running:
cls.Responder = threading.Thread(name='Responder', target=reactor.run, args=(False,))
cls.Responder.daemon = True
cls.Responder.start()
- #cls._TCPResponder = threading.Thread(name='TCP Responder', target=reactor.run, args=(False,))
- #cls._TCPResponder.daemon = True
- #cls._TCPResponder.start()
- def checkCookies(self, support):
+ def checkCookies(self, support, server='127.0.0.25'):
confdir = os.path.join('configs', self._confdir)
output = self.recControl(confdir, 'dump-cookies', '-')
for line in output.splitlines():
tokens = line.split()
- if tokens[0] != '127.0.0.25':
+ if tokens[0] != server:
continue
- print(tokens)
+ #print(tokens)
self.assertEqual(len(tokens), 5)
self.assertEqual(tokens[3], support)
res = self.sendUDPQuery(query)
self.assertRcodeEqual(res, dns.rcode.NOERROR)
self.assertRRsetInAnswer(res, expected)
- self.checkCookies('no')
+ self.checkCookies('Unsupported')
def testAuthRepliesWithCookies(self):
confdir = os.path.join('configs', self._confdir)
res = self.sendUDPQuery(query)
self.assertRcodeEqual(res, dns.rcode.NOERROR)
self.assertRRsetInAnswer(res, expected)
- self.checkCookies('yes')
+ self.checkCookies('Supported')
# Case: we get a an correct client and server cookie back
# We do not clear the cookie tables, so the old server cookie gets re-used
res = self.sendUDPQuery(query)
self.assertRcodeEqual(res, dns.rcode.NOERROR)
self.assertRRsetInAnswer(res, expected)
- self.checkCookies('yes')
+ self.checkCookies('Supported')
def testAuthSendsIncorrectClientCookie(self):
confdir = os.path.join('configs', self._confdir)
- # Case: rec gets a an incorrect client cookie back
- # Fails at the moment, as we do not do the right thing yet server side XXXX
+ # Case: rec gets a an incorrect client cookie back, we ignore that over TCP
self.recControl(confdir, 'clear-cookies')
query = dns.message.make_query('d.cookies.example.', 'A')
expected = dns.rrset.from_text('d.cookies.example.', 15, dns.rdataclass.IN, 'A', '127.0.0.1')
res = self.sendUDPQuery(query)
self.assertRcodeEqual(res, dns.rcode.NOERROR)
self.assertRRsetInAnswer(res, expected)
- self.checkCookies('yes')
+ self.checkCookies('Probing')
def testAuthSendsBADCOOKIEOverUDP(self):
confdir = os.path.join('configs', self._confdir)
res = self.sendUDPQuery(query)
self.assertRcodeEqual(res, dns.rcode.NOERROR)
self.assertRRsetInAnswer(res, expected)
- self.checkCookies('yes')
+ self.checkCookies('Supported')
+
+ def testAuthSendsMalformedCookie(self):
+ confdir = os.path.join('configs', self._confdir)
+ # Case: rec gets a malformed cookie, should ignore packet
+ self.recControl(confdir, 'clear-cookies')
+ query = dns.message.make_query('f.cookies.example.', 'A')
+ expected = dns.rrset.from_text('f.cookies.example.', 15, dns.rdataclass.IN, 'A', '127.0.0.1')
+ res = self.sendUDPQuery(query)
+ self.assertRcodeEqual(res, dns.rcode.NOERROR)
+ self.assertRRsetInAnswer(res, expected)
+ self.checkCookies('Probing', '127.0.0.25')
+ self.checkCookies('Supported', '127.0.0.26')
class UDPResponder(DatagramProtocol):
response.set_rcode(23) # BADCOOKIE
response.answer.append(answer)
+ # Case send malformed cookie for server .25
+ elif question.name == dns.name.from_text('f.cookies.example.') and question.rdtype == dns.rdatatype.A:
+ answer = dns.rrset.from_text('f.cookies.example.', 15, dns.rdataclass.IN, 'A', '127.0.0.1')
+ clientcookie = self.getCookie(request)
+ print(self.transport.getHost().host)
+ if self.transport.getHost().host == os.environ['PREFIX'] + '.26':
+ if clientcookie is not None:
+ response.use_edns(options = [self.createCookie(clientcookie)])
+ else:
+ full = dns.edns.GenericOption(dns.edns.COOKIE, '')
+ response.use_edns(options = [full])
+ response.answer.append(answer)
+
return response.to_wire()
def datagramReceived(self, datagram, address):