*/
public byte
verify(Message m, byte [] b, int length, TSIGRecord old) {
m.tsigState = Message.TSIG_FAILED;
TSIGRecord tsig = m.getTSIG();
HMAC hmac = new HMAC(digest, key);
if (tsig == null)
return Rcode.FORMERR;
if (!tsig.getName().equals(name) || !tsig.getAlgorithm().equals(alg)) {
if (Options.check("verbose"))
System.err.println("BADKEY failure");
return Rcode.BADKEY;
}
long now = System.currentTimeMillis();
long then = tsig.getTimeSigned().getTime();
long fudge = tsig.getFudge();
if (Math.abs(now - then) > fudge * 1000) {
if (Options.check("verbose"))
System.err.println("BADTIME failure");
return Rcode.BADTIME;
}
if (old != null && tsig.getError() != Rcode.BADKEY &&
tsig.getError() != Rcode.BADSIG)
{
DNSOutput out = new DNSOutput();
out.writeU16(old.getSignature().length);
hmac.update(out.toByteArray());
hmac.update(old.getSignature());
}
m.getHeader().decCount(Section.ADDITIONAL);
byte [] header = m.getHeader().toWire();
m.getHeader().incCount(Section.ADDITIONAL);
hmac.update(header);
int len = m.tsigstart - header.length;
hmac.update(b, header.length, len);
DNSOutput out = new DNSOutput();
tsig.getName().toWireCanonical(out);
out.writeU16(tsig.dclass);
out.writeU32(tsig.ttl);
tsig.getAlgorithm().toWireCanonical(out);
long time = tsig.getTimeSigned().getTime() / 1000;
int timeHigh = (int) (time >> 32);
long timeLow = (time & 0xFFFFFFFFL);
out.writeU16(timeHigh);
out.writeU32(timeLow);
out.writeU16(tsig.getFudge());
out.writeU16(tsig.getError());
if (tsig.getOther() != null) {
out.writeU16(tsig.getOther().length);
out.writeByteArray(tsig.getOther());
} else {
out.writeU16(0);
}
hmac.update(out.toByteArray());
if (hmac.verify(tsig.getSignature())) {
m.tsigState = Message.TSIG_VERIFIED;
return Rcode.NOERROR;
} else {
if (Options.check("verbose"))
System.err.println("BADSIG failure");