package mireka.forward; import static org.junit.Assert.*; import java.security.Key; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import mireka.address.DomainPart; import mireka.address.MailAddressFactory; import mireka.address.Recipient; import mireka.address.RemotePartContainingRecipient; import mireka.address.ReversePath; import mireka.filter.local.table.InlineDomainRegistry; import org.apache.commons.codec.binary.Hex; import org.joda.time.DateTimeUtils; import org.joda.time.Instant; import org.junit.After; import org.junit.Before; import org.junit.Test; public class SrsTest { final InlineDomainRegistry localDomains = new InlineDomainRegistry(); public SrsTest() { localDomains.addDomain("example.com"); localDomains.addDomain("example.net"); } @Before public void setup() { DateTimeUtils.setCurrentMillisFixed(new Instant("2011-07-21T12:00Z") .getMillis()); } @After public void tearDown() { DateTimeUtils.setCurrentMillisSystem(); } @Test public void testTimestamp() { Srs srs = new Srs(); srs.setMaximumAge(10); assertTrue(srs.isValidTimeslot(0, 0)); assertTrue(srs.isValidTimeslot(0, 10)); assertFalse(srs.isValidTimeslot(0, 11)); // one day in the future is acceptable assertTrue(srs.isValidTimeslot(10, 9)); // two days in the future are not assertFalse(srs.isValidTimeslot(10, 8)); // wraparounds // one day in the future assertTrue(srs.isValidTimeslot(0, 1023)); // two days in the future assertFalse(srs.isValidTimeslot(0, 1022)); // timestamp is at the end of the window assertTrue(srs.isValidTimeslot(1020, 0)); } @Test public final void testNormalReversePath() { Srs srs = new Srs(); srs.setDefaultRemotePart(new DomainPart("example.net")); srs.setLocalDomains(localDomains); srs.setSecretKey("19AF"); ReversePath originalReversePath = new MailAddressFactory() .createReversePathAlreadyVerified("john@third-party.example.org"); Recipient originalRecipient = new MailAddressFactory() .createRecipientAlreadyVerified("jane@example.com"); ReversePath newReversePath = srs.forward(originalReversePath, originalRecipient); assertEquals("SRS0=NKFJ=2I=third-party.example.org=john@example.com", newReversePath.getSmtpText()); } @Test public final void testSrs0ReversePath() { Srs srs = new Srs(); srs.setDefaultRemotePart(new DomainPart("we.example.net")); srs.setLocalDomains(localDomains); srs.setSecretKey("19AF"); ReversePath originalReversePath = new MailAddressFactory() .createReversePathAlreadyVerified("SRS0=uwWh=2I=source.example.com=john@forwarder.example.com"); Recipient originalRecipient = new MailAddressFactory() .createRecipientAlreadyVerified("jane@we.example.net"); ReversePath newReversePath = srs.forward(originalReversePath, originalRecipient); assertEquals( "SRS1=jdhx=forwarder.example.com==uwWh=2I=source.example.com=john@we.example.net", newReversePath.getSmtpText()); } @Test public final void testSrs1ReversePath() { Srs srs = new Srs(); srs.setDefaultRemotePart(new DomainPart("we.example.net")); srs.setLocalDomains(localDomains); srs.setSecretKey("19AF"); ReversePath originalReversePath = new MailAddressFactory() .createReversePathAlreadyVerified("SRS1=AAAA=forwarder.example.com==uwWh=2I=source.example.com=john@bouncer.example.net"); Recipient originalRecipient = new MailAddressFactory() .createRecipientAlreadyVerified("jane@we.example.net"); ReversePath newReversePath = srs.forward(originalReversePath, originalRecipient); assertEquals( "SRS1=jdhx=forwarder.example.com==uwWh=2I=source.example.com=john@we.example.net", newReversePath.getSmtpText()); } @Test public void testPerlHashCompatibility() throws Exception { String source = "A"; byte[] secretKey = "secret".getBytes("UTF-8"); Mac mac = Mac.getInstance("HmacSHA1"); Key key = new SecretKeySpec(secretKey, "HmacSHA1"); mac.init(key); byte[] digestBytes = mac.doFinal(source.getBytes("UTF-8")); String hexDigest = Hex.encodeHexString(digestBytes); assertEquals("955a367a4c01f58118021054729c7fb54b5de94e", hexDigest); } @Test public final void testPerlCompatibility() throws InvalidSrsException { // Test values are coming from the SRS-0.31 PERL module on // the date which is included in the setup function. Srs srs = new Srs(); srs.setDefaultRemotePart(new DomainPart("hostb.com")); srs.setLocalDomains(localDomains); srs.setSecretKeyString("secret"); String rp0 = forward(srs, "usera@hosta.com", "userb@hostb.com"); assertEquals("SRS0=VtG6=2I=hosta.com=usera@hostb.com", rp0); assertEquals("usera@hosta.com", reverse(srs, rp0)); srs.setDefaultRemotePart(new DomainPart("hostc.com")); String rp1 = forward(srs, rp0, "userc@hostc.com"); assertEquals("SRS1=IC2k=hostb.com==VtG6=2I=hosta.com=usera@hostc.com", rp1); assertEquals(rp0, reverse(srs, rp1)); srs.setDefaultRemotePart(new DomainPart("hostd.com")); String rp2 = forward(srs, rp1, "userd@hostd.com"); assertEquals("SRS1=IC2k=hostb.com==VtG6=2I=hosta.com=usera@hostd.com", rp2); assertEquals(rp0, reverse(srs, rp2)); } private String forward(Srs srs, String originalReversePath, String originalRecipient) { ReversePath originalReversePathObject = new MailAddressFactory() .createReversePathAlreadyVerified(originalReversePath); Recipient originalRecipientObject = new MailAddressFactory() .createRecipientAlreadyVerified(originalRecipient); ReversePath newReversePath = srs.forward(originalReversePathObject, originalRecipientObject); return newReversePath.getSmtpText(); } private String reverse(Srs srs, String srsRecipient) throws InvalidSrsException { Recipient recipient = new MailAddressFactory() .createRecipientAlreadyVerified(srsRecipient); Recipient newRecipient = srs.reverse(recipient); return ((RemotePartContainingRecipient) newRecipient).getMailbox() .getSmtpText(); } }