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/09/18 01:28:57 UTC
svn commit: r998369 - in /james/jdkim/trunk/mailets/src:
main/java/org/apache/james/jdkim/mailets/
test/java/org/apache/james/jdkim/mailets/
Author: bago
Date: Fri Sep 17 23:28:57 2010
New Revision: 998369
URL: http://svn.apache.org/viewvc?rev=998369&view=rev
Log:
Added DKIMVerify mailet (JDKIM-24)
Extracted common code from DKIMSign. Like DKIMSign we don't use jdkim mime4j parser but instead rely on javamail mimemessage for the needed header parsing.
The mailet simply adds a mail attribute: some more code/mailet will be needed to add headers.
Added:
james/jdkim/trunk/mailets/src/main/java/org/apache/james/jdkim/mailets/DKIMVerify.java (with props)
james/jdkim/trunk/mailets/src/main/java/org/apache/james/jdkim/mailets/MimeMessageHeaders.java (with props)
james/jdkim/trunk/mailets/src/test/java/org/apache/james/jdkim/mailets/DKIMVerifyTest.java (with props)
Modified:
james/jdkim/trunk/mailets/src/main/java/org/apache/james/jdkim/mailets/DKIMSign.java
james/jdkim/trunk/mailets/src/test/java/org/apache/james/jdkim/mailets/DKIMSignTest.java
Modified: james/jdkim/trunk/mailets/src/main/java/org/apache/james/jdkim/mailets/DKIMSign.java
URL: http://svn.apache.org/viewvc/james/jdkim/trunk/mailets/src/main/java/org/apache/james/jdkim/mailets/DKIMSign.java?rev=998369&r1=998368&r2=998369&view=diff
==============================================================================
--- james/jdkim/trunk/mailets/src/main/java/org/apache/james/jdkim/mailets/DKIMSign.java (original)
+++ james/jdkim/trunk/mailets/src/main/java/org/apache/james/jdkim/mailets/DKIMSign.java Fri Sep 17 23:28:57 2010
@@ -26,11 +26,9 @@ import java.security.NoSuchAlgorithmExce
import java.security.PrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.util.Enumeration;
-import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
import javax.mail.Header;
import javax.mail.MessagingException;
@@ -81,46 +79,6 @@ import org.apache.mailet.base.GenericMai
*/
public class DKIMSign extends GenericMailet {
- /**
- * An adapter to let DKIMSigner read headers from MimeMessage
- */
- private final class MimeMessageHeaders implements Headers {
-
- private Map<String, List<String>> headers;
- private List<String> fields;
-
- @SuppressWarnings("unchecked")
- public MimeMessageHeaders(MimeMessage message)
- throws MessagingException {
- headers = new HashMap<String, List<String>>();
- fields = new LinkedList<String>();
- for (Enumeration<String> e = message.getAllHeaderLines(); e
- .hasMoreElements();) {
- String head = (String) e.nextElement();
- int p = head.indexOf(':');
- if (p <= 0)
- throw new MessagingException("Bad header line: " + head);
- String headerName = head.substring(0, p).trim();
- String headerNameLC = headerName.toLowerCase();
- fields.add(headerName);
- List<String> strings = (List<String>) headers.get(headerNameLC);
- if (strings == null) {
- strings = new LinkedList<String>();
- headers.put(headerNameLC, strings);
- }
- strings.add(head);
- }
- }
-
- public List<String> getFields() {
- return fields;
- }
-
- public List<String> getFields(String name) {
- return headers.get(name);
- }
- }
-
private String signatureTemplate;
private PrivateKey privateKey;
Added: james/jdkim/trunk/mailets/src/main/java/org/apache/james/jdkim/mailets/DKIMVerify.java
URL: http://svn.apache.org/viewvc/james/jdkim/trunk/mailets/src/main/java/org/apache/james/jdkim/mailets/DKIMVerify.java?rev=998369&view=auto
==============================================================================
--- james/jdkim/trunk/mailets/src/main/java/org/apache/james/jdkim/mailets/DKIMVerify.java (added)
+++ james/jdkim/trunk/mailets/src/main/java/org/apache/james/jdkim/mailets/DKIMVerify.java Fri Sep 17 23:28:57 2010
@@ -0,0 +1,94 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.jdkim.mailets;
+
+import java.io.IOException;
+import java.util.List;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.james.jdkim.DKIMVerifier;
+import org.apache.james.jdkim.api.BodyHasher;
+import org.apache.james.jdkim.api.Headers;
+import org.apache.james.jdkim.api.SignatureRecord;
+import org.apache.james.jdkim.exceptions.FailException;
+import org.apache.mailet.Mail;
+import org.apache.mailet.base.GenericMailet;
+
+/**
+ * This mailet verify a message using the DKIM protocol
+ *
+ * Sample configuration:
+ * <pre><code>
+ * <mailet match="All" class="DKIMVerify">
+ * </mailet>
+ * </code></pre>
+ */
+public class DKIMVerify extends GenericMailet {
+
+ public static final String DKIM_AUTH_RESULT_ATTRIBUTE = "jDKIM.AUTHRESULT";
+
+ protected DKIMVerifier verifier = null;
+
+ @Override
+ public void init() throws MessagingException {
+ verifier = new DKIMVerifier();
+ }
+
+ public void service(Mail mail) throws MessagingException {
+ try {
+ MimeMessage message = mail.getMessage();
+ Headers headers = new MimeMessageHeaders(message);
+ BodyHasher bh = verifier.newBodyHasher(headers);
+ try {
+ if (bh != null) {
+ message.writeTo(new HeaderSkippingOutputStream(bh
+ .getOutputStream()));
+ bh.getOutputStream().close();
+ }
+
+ } catch (IOException e) {
+ throw new MessagingException("Exception calculating bodyhash: "
+ + e.getMessage(), e);
+ }
+ List<SignatureRecord> res = verifier.verify(bh);
+ if (res == null || res.isEmpty()) {
+ // neutral
+ mail.setAttribute(DKIM_AUTH_RESULT_ATTRIBUTE, "neutral (no signatures)");
+ } else {
+ // pass
+ StringBuilder msg = new StringBuilder();
+ msg.append("pass");
+ for (SignatureRecord rec : res) {
+ msg.append(" (");
+ msg.append("identity ");
+ msg.append(rec.getIdentity().toString());
+ msg.append(")");
+ }
+ mail.setAttribute(DKIM_AUTH_RESULT_ATTRIBUTE, msg.toString());
+ }
+ } catch (FailException e) {
+ // fail
+ mail.setAttribute(DKIM_AUTH_RESULT_ATTRIBUTE, "fail ("+(e.getRelatedRecordIdentity() != null ? "identity "+ e.getRelatedRecordIdentity() + ": " : "")+e.getMessage()+")");
+ }
+
+ }
+}
Propchange: james/jdkim/trunk/mailets/src/main/java/org/apache/james/jdkim/mailets/DKIMVerify.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: james/jdkim/trunk/mailets/src/main/java/org/apache/james/jdkim/mailets/MimeMessageHeaders.java
URL: http://svn.apache.org/viewvc/james/jdkim/trunk/mailets/src/main/java/org/apache/james/jdkim/mailets/MimeMessageHeaders.java?rev=998369&view=auto
==============================================================================
--- james/jdkim/trunk/mailets/src/main/java/org/apache/james/jdkim/mailets/MimeMessageHeaders.java (added)
+++ james/jdkim/trunk/mailets/src/main/java/org/apache/james/jdkim/mailets/MimeMessageHeaders.java Fri Sep 17 23:28:57 2010
@@ -0,0 +1,71 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.jdkim.mailets;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.james.jdkim.api.Headers;
+
+/**
+ * An adapter to let DKIMSigner read headers from MimeMessage
+ */
+final class MimeMessageHeaders implements Headers {
+
+ private Map<String, List<String>> headers;
+ private List<String> fields;
+
+ @SuppressWarnings("unchecked")
+ public MimeMessageHeaders(MimeMessage message)
+ throws MessagingException {
+ headers = new HashMap<String, List<String>>();
+ fields = new LinkedList<String>();
+ for (Enumeration<String> e = message.getAllHeaderLines(); e
+ .hasMoreElements();) {
+ String head = (String) e.nextElement();
+ int p = head.indexOf(':');
+ if (p <= 0)
+ throw new MessagingException("Bad header line: " + head);
+ String headerName = head.substring(0, p).trim();
+ String headerNameLC = headerName.toLowerCase();
+ fields.add(headerName);
+ List<String> strings = (List<String>) headers.get(headerNameLC);
+ if (strings == null) {
+ strings = new LinkedList<String>();
+ headers.put(headerNameLC, strings);
+ }
+ strings.add(head);
+ }
+ }
+
+ public List<String> getFields() {
+ return fields;
+ }
+
+ public List<String> getFields(String name) {
+ return headers.get(name.toLowerCase());
+ }
+}
\ No newline at end of file
Propchange: james/jdkim/trunk/mailets/src/main/java/org/apache/james/jdkim/mailets/MimeMessageHeaders.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
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=998369&r1=998368&r2=998369&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 Fri Sep 17 23:28:57 2010
@@ -132,12 +132,12 @@ public class DKIMSignTest extends TestCa
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");
try {
- List<SignatureRecord> sr = new DKIMVerifier(mockPublicKeyRecordRetriever)
+ new DKIMVerifier(mockPublicKeyRecordRetriever)
.verify(new ByteArrayInputStream(res.getBytes()));
fail("Expecting signature to be ignored");
} catch (PermFailException e) {
Added: james/jdkim/trunk/mailets/src/test/java/org/apache/james/jdkim/mailets/DKIMVerifyTest.java
URL: http://svn.apache.org/viewvc/james/jdkim/trunk/mailets/src/test/java/org/apache/james/jdkim/mailets/DKIMVerifyTest.java?rev=998369&view=auto
==============================================================================
--- james/jdkim/trunk/mailets/src/test/java/org/apache/james/jdkim/mailets/DKIMVerifyTest.java (added)
+++ james/jdkim/trunk/mailets/src/test/java/org/apache/james/jdkim/mailets/DKIMVerifyTest.java Fri Sep 17 23:28:57 2010
@@ -0,0 +1,119 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.jdkim.mailets;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+import javax.mail.MessagingException;
+import javax.mail.Session;
+import javax.mail.internet.MimeMessage;
+
+import junit.framework.TestCase;
+
+import org.apache.james.jdkim.DKIMVerifier;
+import org.apache.james.jdkim.MockPublicKeyRecordRetriever;
+import org.apache.james.jdkim.exceptions.FailException;
+import org.apache.mailet.Mail;
+import org.apache.mailet.Mailet;
+import org.apache.mailet.base.test.FakeMail;
+import org.apache.mailet.base.test.FakeMailContext;
+import org.apache.mailet.base.test.FakeMailetConfig;
+
+public class DKIMVerifyTest extends TestCase {
+
+ public void testDKIMVerifyPass() throws MessagingException, IOException,
+ FailException {
+ String message = "DKIM-Signature: v=1; d=example.com; t=1284762805; b=ZFfwSIzTQM7k9syRnl9VfQh0/dr99euvBe1gn/DiTrnEZjxyjzQBD2MMvowVdbHpPMtSjtCtehU9zZ3urXmj5iHKujpEkP92FEKinzElkQ2eT2zoxdg1zByPHsKPX+KjrBespAJcO2k052aOK5kIBFxpQumP4aiW7ZklBKSWMBk=; s=selector; a=rsa-sha256; bh=rHOD7fd9xnNxK7OSl5ellpQVF14NNFbOIizqtUMhnio=; h=from:to:received:received;\r\n"
+ + "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";
+
+ Mail mail = process(message);
+
+ String attr = (String) mail.getAttribute(DKIMVerify.DKIM_AUTH_RESULT_ATTRIBUTE);
+ assertNotNull(attr);
+ assertTrue(attr.startsWith("pass"));
+ }
+
+ public void testDKIMVerifyFail() throws MessagingException, IOException,
+ FailException {
+ // altered message body
+ String message = "DKIM-Signature: v=1; d=example.com; t=1284762805; b=ZFfwSIzTQM7k9syRnl9VfQh0/dr99euvBe1gn/DiTrnEZjxyjzQBD2MMvowVdbHpPMtSjtCtehU9zZ3urXmj5iHKujpEkP92FEKinzElkQ2eT2zoxdg1zByPHsKPX+KjrBespAJcO2k052aOK5kIBFxpQumP4aiW7ZklBKSWMBk=; s=selector; a=rsa-sha256; bh=rHOD7fd9xnNxK7OSl5ellpQVF14NNFbOIizqtUMhnio=; h=from:to:received:received;\r\n"
+ + "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 altered\r\n";
+
+ Mail mail = process(message);
+
+ String attr = (String) mail.getAttribute(DKIMVerify.DKIM_AUTH_RESULT_ATTRIBUTE);
+ assertNotNull(attr);
+ assertTrue(attr.startsWith("fail"));
+ }
+
+ public void testDKIMVerifyFailInvalid() throws MessagingException, IOException,
+ FailException {
+ // invalid version v=2
+ String message = "DKIM-Signature: v=2; d=example.com; t=1284762805; b=ZFfwSIzTQM7k9syRnl9VfQh0/dr99euvBe1gn/DiTrnEZjxyjzQBD2MMvowVdbHpPMtSjtCtehU9zZ3urXmj5iHKujpEkP92FEKinzElkQ2eT2zoxdg1zByPHsKPX+KjrBespAJcO2k052aOK5kIBFxpQumP4aiW7ZklBKSWMBk=; s=selector; a=rsa-sha256; bh=rHOD7fd9xnNxK7OSl5ellpQVF14NNFbOIizqtUMhnio=; h=from:to:received:received;\r\n"
+ + "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";
+
+ Mail mail = process(message);
+
+ String attr = (String) mail.getAttribute(DKIMVerify.DKIM_AUTH_RESULT_ATTRIBUTE);
+ assertNotNull(attr);
+ assertTrue(attr.startsWith("fail"));
+ }
+
+ public void testDKIMVerifyNeutral() throws MessagingException, IOException,
+ FailException {
+ // no signatures!
+ 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 altered\r\n";
+
+ Mail mail = process(message);
+
+ String attr = (String) mail.getAttribute(DKIMVerify.DKIM_AUTH_RESULT_ATTRIBUTE);
+ assertNotNull(attr);
+ assertTrue(attr.startsWith("neutral"));
+ }
+
+ private Mail process(String message) throws MessagingException {
+ Mailet mailet = new DKIMVerify() {
+
+ @Override
+ public void init() throws MessagingException {
+ verifier = new DKIMVerifier(new MockPublicKeyRecordRetriever(
+ "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYDaYKXzwVYwqWbLhmuJ66aTAN8wmDR+rfHE8HfnkSOax0oIoTM5zquZrTLo30870YMfYzxwfB6j/Nz3QdwrUD/t0YMYJiUKyWJnCKfZXHJBJ+yfRHr7oW+UW3cVo9CG2bBfIxsInwYe175g9UjyntJpWueqdEIo1c2bhv9Mp66QIDAQAB;",
+ "selector", "example.com"));
+ }
+
+ };
+
+ FakeMailetConfig mci = new FakeMailetConfig("Test",
+ new FakeMailContext());
+
+ mailet.init(mci);
+
+ Mail mail = new FakeMail();
+ mail.setMessage(new MimeMessage(Session
+ .getDefaultInstance(new Properties()),
+ new ByteArrayInputStream(message.getBytes())));
+
+ mailet.service(mail);
+ return mail;
+ }
+}
Propchange: james/jdkim/trunk/mailets/src/test/java/org/apache/james/jdkim/mailets/DKIMVerifyTest.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org