You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by ba...@apache.org on 2010/06/09 00:07:02 UTC
svn commit: r952843 - in /james/jdkim/trunk:
mailets/src/test/java/org/apache/james/jdkim/mailets/
main/src/main/java/org/apache/james/jdkim/
main/src/main/java/org/apache/james/jdkim/api/
main/src/main/java/org/apache/james/jdkim/tagvalue/
Author: bago
Date: Tue Jun 8 22:07:01 2010
New Revision: 952843
URL: http://svn.apache.org/viewvc?rev=952843&view=rev
Log:
Added basic support for t= parameter (signature timestamp) in the signature record (JDKIM-15)
Modified:
james/jdkim/trunk/mailets/src/test/java/org/apache/james/jdkim/mailets/DKIMSignTest.java
james/jdkim/trunk/main/src/main/java/org/apache/james/jdkim/DKIMVerifier.java
james/jdkim/trunk/main/src/main/java/org/apache/james/jdkim/api/SignatureRecord.java
james/jdkim/trunk/main/src/main/java/org/apache/james/jdkim/tagvalue/SignatureRecordImpl.java
Modified: james/jdkim/trunk/mailets/src/test/java/org/apache/james/jdkim/mailets/DKIMSignTest.java
URL: http://svn.apache.org/viewvc/james/jdkim/trunk/mailets/src/test/java/org/apache/james/jdkim/mailets/DKIMSignTest.java?rev=952843&r1=952842&r2=952843&view=diff
==============================================================================
--- james/jdkim/trunk/mailets/src/test/java/org/apache/james/jdkim/mailets/DKIMSignTest.java (original)
+++ james/jdkim/trunk/mailets/src/test/java/org/apache/james/jdkim/mailets/DKIMSignTest.java Tue Jun 8 22:07:01 2010
@@ -22,6 +22,7 @@ package org.apache.james.jdkim.mailets;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
+import java.util.List;
import java.util.Properties;
import javax.mail.Address;
@@ -35,6 +36,7 @@ import junit.framework.TestCase;
import org.apache.james.jdkim.DKIMVerifier;
import org.apache.james.jdkim.MockPublicKeyRecordRetriever;
+import org.apache.james.jdkim.api.SignatureRecord;
import org.apache.james.jdkim.exceptions.FailException;
import org.apache.james.jdkim.exceptions.PermFailException;
import org.apache.mailet.Mail;
@@ -64,7 +66,7 @@ public class DKIMSignTest extends TestCa
public void testDKIMSign() throws MessagingException, IOException,
FailException {
- String message = "Received: by 10.XX.XX.12 with SMTP id dfgskldjfhgkljsdfhgkljdhfg;\r\n\tTue, 06 Oct 2009 07:37:34 -0700 (PDT)\r\nReturn-Path: <bo...@example.com>\r\nReceived: from example.co.uk (example.co.uk [XX.XXX.125.19])\r\n\tby mx.example.com with ESMTP id dgdfgsdfgsd.97.2009.10.06.07.37.32;\r\n\tTue, 06 Oct 2009 07:37:32 -0700 (PDT)\r\nFrom: apache@bago.org\r\nTo: apache@bago.org\r\n\r\nbody\r\n";
+ String message = "Received: by 10.XX.XX.12 with SMTP id dfgskldjfhgkljsdfhgkljdhfg;\r\n\tTue, 06 Oct 2009 07:37:34 -0700 (PDT)\r\nReturn-Path: <bo...@example.com>\r\nReceived: from example.co.uk (example.co.uk [XX.XXX.125.19])\r\n\tby mx.example.com with ESMTP id dgdfgsdfgsd.97.2009.10.06.07.37.32;\r\n\tTue, 06 Oct 2009 07:37:32 -0700 (PDT)\r\nFrom: apache@bago.org\r\nTo: apache@bago.org\r\n\r\nbody\r\nprova\r\n";
Mailet mailet = new DKIMSign();
@@ -74,10 +76,45 @@ public class DKIMSignTest extends TestCa
.setProperty(
"signatureTemplate",
"v=1; s=selector; d=example.com; h=from:to:received:received; a=rsa-sha256; bh=; b=;");
+ mci.setProperty("privateKey", TESTING_PEM);
+
+ mailet.init(mci);
+
+ Mail mail = new FakeMail();
+ mail.setMessage(new MimeMessage(Session
+ .getDefaultInstance(new Properties()),
+ new ByteArrayInputStream(message.getBytes())));
+
+ mailet.service(mail);
+
+ Mailet m7bit = new ConvertTo7Bit();
+ m7bit.init(mci);
+ m7bit.service(mail);
+
+ ByteArrayOutputStream rawMessage = new ByteArrayOutputStream();
+ mail.getMessage().writeTo(rawMessage);
+ String res = rawMessage.toString();
+
+ MockPublicKeyRecordRetriever mockPublicKeyRecordRetriever = new MockPublicKeyRecordRetriever(
+ "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYDaYKXzwVYwqWbLhmuJ66aTAN8wmDR+rfHE8HfnkSOax0oIoTM5zquZrTLo30870YMfYzxwfB6j/Nz3QdwrUD/t0YMYJiUKyWJnCKfZXHJBJ+yfRHr7oW+UW3cVo9CG2bBfIxsInwYe175g9UjyntJpWueqdEIo1c2bhv9Mp66QIDAQAB;",
+ "selector", "example.com");
+ new DKIMVerifier(mockPublicKeyRecordRetriever)
+ .verify(new ByteArrayInputStream(res.getBytes()));
+ }
+
+ public void testDKIMSignFuture() throws MessagingException, IOException,
+ FailException {
+ String message = "Received: by 10.XX.XX.12 with SMTP id dfgskldjfhgkljsdfhgkljdhfg;\r\n\tTue, 06 Oct 2009 07:37:34 -0700 (PDT)\r\nReturn-Path: <bo...@example.com>\r\nReceived: from example.co.uk (example.co.uk [XX.XXX.125.19])\r\n\tby mx.example.com with ESMTP id dgdfgsdfgsd.97.2009.10.06.07.37.32;\r\n\tTue, 06 Oct 2009 07:37:32 -0700 (PDT)\r\nFrom: apache@bago.org\r\nTo: apache@bago.org\r\n\r\nbody\r\nprova\r\n";
+
+ Mailet mailet = new DKIMSign();
+
+ FakeMailetConfig mci = new FakeMailetConfig("Test",
+ new FakeMailContext());
mci
.setProperty(
- "privateKey",
- TESTING_PEM);
+ "signatureTemplate",
+ "v=1; t="+((System.currentTimeMillis()/1000)+1000)+"; s=selector; d=example.com; h=from:to:received:received; a=rsa-sha256; bh=; b=;");
+ mci.setProperty("privateKey", TESTING_PEM);
mailet.init(mci);
@@ -96,11 +133,62 @@ public class DKIMSignTest extends TestCa
mail.getMessage().writeTo(rawMessage);
String res = rawMessage.toString();
- MockPublicKeyRecordRetriever MockPublicKeyRecordRetriever = new MockPublicKeyRecordRetriever(
+ MockPublicKeyRecordRetriever mockPublicKeyRecordRetriever = new MockPublicKeyRecordRetriever(
"v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYDaYKXzwVYwqWbLhmuJ66aTAN8wmDR+rfHE8HfnkSOax0oIoTM5zquZrTLo30870YMfYzxwfB6j/Nz3QdwrUD/t0YMYJiUKyWJnCKfZXHJBJ+yfRHr7oW+UW3cVo9CG2bBfIxsInwYe175g9UjyntJpWueqdEIo1c2bhv9Mp66QIDAQAB;",
"selector", "example.com");
- new DKIMVerifier(MockPublicKeyRecordRetriever)
+ try {
+ new DKIMVerifier(mockPublicKeyRecordRetriever)
+ .verify(new ByteArrayInputStream(res.getBytes()));
+ fail("Expecting signature to be ignored");
+ } catch (PermFailException e) {
+ // signature ignored, so fail for missing signatures.
+ }
+ }
+
+
+ public void testDKIMSignTime() throws MessagingException, IOException,
+ FailException {
+ String message = "Received: by 10.XX.XX.12 with SMTP id dfgskldjfhgkljsdfhgkljdhfg;\r\n\tTue, 06 Oct 2009 07:37:34 -0700 (PDT)\r\nReturn-Path: <bo...@example.com>\r\nReceived: from example.co.uk (example.co.uk [XX.XXX.125.19])\r\n\tby mx.example.com with ESMTP id dgdfgsdfgsd.97.2009.10.06.07.37.32;\r\n\tTue, 06 Oct 2009 07:37:32 -0700 (PDT)\r\nFrom: apache@bago.org\r\nTo: apache@bago.org\r\n\r\nbody\r\nprova\r\n";
+
+ Mailet mailet = new DKIMSign();
+
+ FakeMailetConfig mci = new FakeMailetConfig("Test",
+ new FakeMailContext());
+ mci
+ .setProperty(
+ "signatureTemplate",
+ "v=1; t=; s=selector; d=example.com; h=from:to:received:received; a=rsa-sha256; bh=; b=;");
+ mci.setProperty("privateKey", TESTING_PEM);
+
+ mailet.init(mci);
+
+ Mail mail = new FakeMail();
+ mail.setMessage(new MimeMessage(Session
+ .getDefaultInstance(new Properties()),
+ new ByteArrayInputStream(message.getBytes())));
+
+ mailet.service(mail);
+
+ Mailet m7bit = new ConvertTo7Bit();
+ m7bit.init(mci);
+ m7bit.service(mail);
+
+ ByteArrayOutputStream rawMessage = new ByteArrayOutputStream();
+ mail.getMessage().writeTo(rawMessage);
+ String res = rawMessage.toString();
+
+ MockPublicKeyRecordRetriever mockPublicKeyRecordRetriever = new MockPublicKeyRecordRetriever(
+ "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYDaYKXzwVYwqWbLhmuJ66aTAN8wmDR+rfHE8HfnkSOax0oIoTM5zquZrTLo30870YMfYzxwfB6j/Nz3QdwrUD/t0YMYJiUKyWJnCKfZXHJBJ+yfRHr7oW+UW3cVo9CG2bBfIxsInwYe175g9UjyntJpWueqdEIo1c2bhv9Mp66QIDAQAB;",
+ "selector", "example.com");
+ List/* SignatureRecord */ rs = new DKIMVerifier(mockPublicKeyRecordRetriever)
.verify(new ByteArrayInputStream(res.getBytes()));
+
+ // check we have a valued signatureTimestamp
+ assertNotNull(((SignatureRecord) rs.get(0)).getSignatureTimestamp());
+ long ref = System.currentTimeMillis() / 1000;
+ // Chech that the signature timestamp is in the past 60 seconds.
+ assertTrue(((SignatureRecord) rs.get(0)).getSignatureTimestamp().longValue() <= ref);
+ assertTrue(((SignatureRecord) rs.get(0)).getSignatureTimestamp().longValue() >= ref - 60);
}
public void testDKIMSignMessageAsText() throws MessagingException,
@@ -109,7 +197,7 @@ public class DKIMSignTest extends TestCa
.getDefaultInstance(new Properties()));
mm.addFrom(new Address[] { new InternetAddress("io@bago.org") });
mm.addRecipient(RecipientType.TO, new InternetAddress("io@bago.org"));
- mm.setText("An 8bit encoded body with €uro symbol.", "ISO-8859-15");
+ mm.setText("An 8bit encoded body with \u20ACuro symbol.", "ISO-8859-15");
Mailet mailet = new DKIMSign();
@@ -140,10 +228,10 @@ public class DKIMSignTest extends TestCa
mail.getMessage().writeTo(rawMessage);
String res = rawMessage.toString();
- MockPublicKeyRecordRetriever MockPublicKeyRecordRetriever = new MockPublicKeyRecordRetriever(
+ MockPublicKeyRecordRetriever mockPublicKeyRecordRetriever = new MockPublicKeyRecordRetriever(
"v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYDaYKXzwVYwqWbLhmuJ66aTAN8wmDR+rfHE8HfnkSOax0oIoTM5zquZrTLo30870YMfYzxwfB6j/Nz3QdwrUD/t0YMYJiUKyWJnCKfZXHJBJ+yfRHr7oW+UW3cVo9CG2bBfIxsInwYe175g9UjyntJpWueqdEIo1c2bhv9Mp66QIDAQAB;",
"selector", "example.com");
- new DKIMVerifier(MockPublicKeyRecordRetriever)
+ new DKIMVerifier(mockPublicKeyRecordRetriever)
.verify(new ByteArrayInputStream(res.getBytes()));
}
Modified: james/jdkim/trunk/main/src/main/java/org/apache/james/jdkim/DKIMVerifier.java
URL: http://svn.apache.org/viewvc/james/jdkim/trunk/main/src/main/java/org/apache/james/jdkim/DKIMVerifier.java?rev=952843&r1=952842&r2=952843&view=diff
==============================================================================
--- james/jdkim/trunk/main/src/main/java/org/apache/james/jdkim/DKIMVerifier.java (original)
+++ james/jdkim/trunk/main/src/main/java/org/apache/james/jdkim/DKIMVerifier.java Tue Jun 8 22:07:01 2010
@@ -266,6 +266,17 @@ public class DKIMVerifier extends DKIMCo
throw new PermFailException(e.getMessage());
}
+ // Specification say we MAY refuse to verify the signature.
+ if (signatureRecord.getSignatureTimestamp() != null) {
+ long signedTime = signatureRecord.getSignatureTimestamp().longValue();
+ long elapsed = (System.currentTimeMillis()/1000 - signedTime);
+ if (elapsed < 0) {
+ // throw new IllegalStateException("Signature date is "
+ // + getTimeMeasure(elapsed) + " in the future.");
+ break;
+ }
+ }
+
// TODO here we could check more parameters for
// validation before running a network operation like the
// dns lookup.
Modified: james/jdkim/trunk/main/src/main/java/org/apache/james/jdkim/api/SignatureRecord.java
URL: http://svn.apache.org/viewvc/james/jdkim/trunk/main/src/main/java/org/apache/james/jdkim/api/SignatureRecord.java?rev=952843&r1=952842&r2=952843&view=diff
==============================================================================
--- james/jdkim/trunk/main/src/main/java/org/apache/james/jdkim/api/SignatureRecord.java (original)
+++ james/jdkim/trunk/main/src/main/java/org/apache/james/jdkim/api/SignatureRecord.java Tue Jun 8 22:07:01 2010
@@ -67,4 +67,6 @@ public interface SignatureRecord {
public abstract String toUnsignedString();
+ public abstract Long getSignatureTimestamp();
+
}
\ No newline at end of file
Modified: james/jdkim/trunk/main/src/main/java/org/apache/james/jdkim/tagvalue/SignatureRecordImpl.java
URL: http://svn.apache.org/viewvc/james/jdkim/trunk/main/src/main/java/org/apache/james/jdkim/tagvalue/SignatureRecordImpl.java?rev=952843&r1=952842&r2=952843&view=diff
==============================================================================
--- james/jdkim/trunk/main/src/main/java/org/apache/james/jdkim/tagvalue/SignatureRecordImpl.java (original)
+++ james/jdkim/trunk/main/src/main/java/org/apache/james/jdkim/tagvalue/SignatureRecordImpl.java Tue Jun 8 22:07:01 2010
@@ -74,32 +74,10 @@ public class SignatureRecordImpl extends
// (signature expired)
if (getValue("x") != null) {
long expiration = Long.parseLong(getValue("x").toString());
- long lifetime = (expiration - System.currentTimeMillis() / 1000);
- String measure = "s";
+ long lifetime = (expiration - System.currentTimeMillis()/1000);
if (lifetime < 0) {
- lifetime = -lifetime;
- if (lifetime > 600) {
- lifetime = lifetime / 60;
- measure = "m";
- if (lifetime > 600) {
- lifetime = lifetime / 60;
- measure = "h";
- if (lifetime > 120) {
- lifetime = lifetime / 24;
- measure = "d";
- if (lifetime > 90) {
- lifetime = lifetime / 30;
- measure = " months";
- if (lifetime > 24) {
- lifetime = lifetime / 12;
- measure = " years";
- }
- }
- }
- }
- }
throw new IllegalStateException("Signature is expired since "
- + lifetime + measure + ".");
+ + getTimeMeasure(lifetime) + ".");
}
}
@@ -111,6 +89,33 @@ public class SignatureRecordImpl extends
// this class).
}
+ private String getTimeMeasure(long lifetime) {
+ String measure = "s";
+ lifetime = -lifetime;
+ if (lifetime > 600) {
+ lifetime = lifetime / 60;
+ measure = "m";
+ if (lifetime > 600) {
+ lifetime = lifetime / 60;
+ measure = "h";
+ if (lifetime > 120) {
+ lifetime = lifetime / 24;
+ measure = "d";
+ if (lifetime > 90) {
+ lifetime = lifetime / 30;
+ measure = " months";
+ if (lifetime > 24) {
+ lifetime = lifetime / 12;
+ measure = " years";
+ }
+ }
+ }
+ }
+ }
+ String lifetimeMeasure = lifetime + measure;
+ return lifetimeMeasure;
+ }
+
/**
* @see org.apache.james.jdkim.api.SignatureRecord#getHeaders()
*/
@@ -274,6 +279,12 @@ public class SignatureRecordImpl extends
return Integer.parseInt(limit);
}
+ public Long getSignatureTimestamp() {
+ CharSequence cs = getValue("t");
+ if (cs == null) return null;
+ return Long.valueOf(Long.parseLong(cs.toString()));
+ }
+
public String getBodyCanonicalisationMethod() {
String c = getValue("c").toString();
int pSlash = c.toString().indexOf("/");
@@ -315,11 +326,14 @@ public class SignatureRecordImpl extends
public void setBodyHash(byte[] newBodyHash) {
String bodyHash = new String(Base64.encodeBase64(newBodyHash));
setValue("bh", bodyHash);
+ // If a t=; parameter is present in the signature, make sure to
+ // fill it with the current timestamp
+ if (getValue("t") != null && getValue("t").toString().trim().length() == 0) {
+ setValue("t", ""+(System.currentTimeMillis() / 1000));
+ }
}
public String toUnsignedString() {
return toString().replaceFirst("b=[^;]*", "b=");
}
-
-
}
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org