All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.xbill.DNS.security.DNSSECVerifier Maven / Gradle / Ivy

There is a newer version: 2.0-beta-7
Show newest version
// Copyright (c) 1999-2004 Brian Wellington ([email protected])

package org.xbill.DNS.security;

import org.xbill.DNS.*;

import java.security.GeneralSecurityException;
import java.security.PublicKey;
import java.security.Signature;
import java.util.*;

/**
 * A class that verifies DNS data using digital signatures contained in DNSSEC
 * SIG records.  DNSSECVerifier stores a set of trusted keys.  Each specific
 * verification references a cache where additional secure keys may be found.
 * @see Verifier
 * @see DNSSEC
 *
 * @author Brian Wellington
 */

public class DNSSECVerifier implements Verifier {

private Map trustedKeys;

/** Creates a new DNSSECVerifier */
public
DNSSECVerifier() {
	trustedKeys = new HashMap();
}

/** Adds the specified key to the set of trusted keys */
public synchronized void
addTrustedKey(DNSKEYRecord key) {
	Name name = key.getName();
	List list = (List) trustedKeys.get(name);
	if (list == null)
		trustedKeys.put(name, list = new LinkedList());
	list.add(key);
}

/** Adds the specified key to the set of trusted keys */
public void
addTrustedKey(Name name, int alg, PublicKey key) {
	Record rec;
	rec = KEYConverter.buildRecord(name, Type.DNSKEY, DClass.IN, 0, 0,
				       DNSKEYRecord.Protocol.DNSSEC, alg, key);
	if (rec != null)
		addTrustedKey((DNSKEYRecord) rec);
}

private PublicKey
findMatchingKey(Iterator it, int algorithm, int footprint) {
	while (it.hasNext()) {
		DNSKEYRecord keyrec = (DNSKEYRecord) it.next();
		if (keyrec.getAlgorithm() == algorithm &&
		    keyrec.getFootprint() == footprint)
			return KEYConverter.parseRecord(keyrec);
	}
	return null;
}

private synchronized PublicKey
findTrustedKey(Name name, int algorithm, int footprint) {
	List list = (List) trustedKeys.get(name);
	if (list == null)
		return null;
	return findMatchingKey(list.iterator(), algorithm, footprint);
}

private PublicKey
findCachedKey(Cache cache, Name name, int algorithm, int footprint) {
	RRset [] keysets = cache.findAnyRecords(name, Type.DNSKEY);
	if (keysets == null)
		return null;
	RRset keys = keysets[0];
	return findMatchingKey(keys.rrs(), algorithm, footprint);
}

private PublicKey
findKey(Cache cache, Name name, int algorithm, int footprint) {
	PublicKey key = findTrustedKey(name, algorithm, footprint);
	if (key == null && cache != null)
		return findCachedKey(cache, name, algorithm, footprint);
	return key;
}

private int
verifySIG(RRset set, RRSIGRecord sigrec, Cache cache) {
	PublicKey key = findKey(cache, sigrec.getSigner(),
				sigrec.getAlgorithm(), sigrec.getFootprint());
	if (key == null)
		return DNSSEC.Insecure;

	Date now = new Date();
	if (now.compareTo(sigrec.getExpire()) > 0 ||
	    now.compareTo(sigrec.getTimeSigned()) < 0)
	{
		System.err.println("Outside of validity period");
		return DNSSEC.Failed;
	}
	byte [] data = DNSSEC.digestRRset(sigrec, set);

	byte [] sig;
	String algString;

	switch (sigrec.getAlgorithm()) {
		case DNSSEC.RSAMD5:
			sig = sigrec.getSignature();
			algString = "MD5withRSA";
			break;
		case DNSSEC.DSA:
		case DNSSEC.DSA_NSEC3_SHA1:
			sig = DSASignature.fromDNS(sigrec.getSignature());
			algString = "SHA1withDSA";
			break;
		case DNSSEC.RSASHA1:
		case DNSSEC.RSA_NSEC3_SHA1:
			sig = sigrec.getSignature();
			algString = "SHA1withRSA";
			break;
		default:
			return DNSSEC.Failed;
	}

	try {
		Signature s = Signature.getInstance(algString);
		s.initVerify(key);
		s.update(data);
		return s.verify(sig) ? DNSSEC.Secure : DNSSEC.Failed;
	}
	catch (GeneralSecurityException e) {
		if (Options.check("verboseexceptions"))
			System.err.println("Signing data: " + e);
		return DNSSEC.Failed;
	}
}

/**
 * Attempts to verify an RRset.  This does not modify the set.
 * @param set The RRset to verify
 * @param cache The Cache where obtained secure keys are found (may be null)
 * @return The new security status of the set
 * @see RRset
 */
public int
verify(RRset set, Cache cache) {
	Iterator sigs = set.sigs();
	if (Options.check("verbosesec"))
		System.out.print("Verifying " + set.getName() + "/" +
				 Type.string(set.getType()) + ": ");
	if (!sigs.hasNext()) {
		if (Options.check("verbosesec"))
			System.out.println("Insecure");
		return DNSSEC.Insecure;
	}
	while (sigs.hasNext()) {
		RRSIGRecord sigrec = (RRSIGRecord) sigs.next();
		if (verifySIG(set, sigrec, cache) == DNSSEC.Secure) {
			if (Options.check("verbosesec"))
				System.out.println("Secure");
			return DNSSEC.Secure;
		}
	}
	if (Options.check("verbosesec"))
		System.out.println("Failed");
	return DNSSEC.Failed;
}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy