mirror of https://github.com/shred/acme4j
Minor optimizations
parent
06e03880c9
commit
ef5ca28fd9
|
@ -135,13 +135,16 @@ public final class EmailProcessor {
|
|||
boolean hasMatch = false;
|
||||
for (SignerInformation signer : signed.getSignerInfos().getSigners()) {
|
||||
hasMatch |= signer.verify(verifier);
|
||||
if (hasMatch) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!hasMatch) {
|
||||
throw new AcmeInvalidMessageException("The S/MIME signature is invalid");
|
||||
}
|
||||
|
||||
MimeMessage content = signed.getContentAsMimeMessage(mailSession);
|
||||
if (!content.getContentType().equalsIgnoreCase("message/rfc822; forwarded=no")) {
|
||||
if (!"message/rfc822; forwarded=no".equalsIgnoreCase(content.getContentType())) {
|
||||
throw new AcmeInvalidMessageException("Message does not contain protected headers");
|
||||
}
|
||||
|
||||
|
@ -214,7 +217,7 @@ public final class EmailProcessor {
|
|||
if (from == null) {
|
||||
throw new AcmeInvalidMessageException("Message has no 'From' header");
|
||||
}
|
||||
if (from.length != 1) {
|
||||
if (from.length != 1 || from[0] == null) {
|
||||
throw new AcmeInvalidMessageException("Message must have exactly one sender, but has " + from.length);
|
||||
}
|
||||
if (validFromAddresses != null && !validFromAddresses.contains(from[0])) {
|
||||
|
@ -222,8 +225,7 @@ public final class EmailProcessor {
|
|||
}
|
||||
if (strict && signedMessage != null) {
|
||||
Address[] outerFrom = message.getFrom();
|
||||
if ((outerFrom.length > 1) || (outerFrom.length == 1 && outerFrom[0] != null
|
||||
&& !outerFrom[0].equals(from[0]))) {
|
||||
if (outerFrom == null || outerFrom.length != 1 || !from[0].equals(outerFrom[0])) {
|
||||
throw new AcmeInvalidMessageException("Protected 'From' header does not match envelope header");
|
||||
}
|
||||
}
|
||||
|
@ -233,13 +235,12 @@ public final class EmailProcessor {
|
|||
if (to == null) {
|
||||
throw new AcmeInvalidMessageException("Message has no 'To' header");
|
||||
}
|
||||
if (to.length != 1) {
|
||||
if (to.length != 1 || to[0] == null) {
|
||||
throw new AcmeProtocolException("Message must have exactly one recipient, but has " + to.length);
|
||||
}
|
||||
if (strict && signedMessage != null) {
|
||||
Address[] outerTo = message.getRecipients(TO);
|
||||
if ((outerTo.length > 1) || (outerTo.length == 1 && outerTo[0] != null
|
||||
&& !outerTo[0].equals(to[0]))) {
|
||||
if (outerTo == null || outerTo.length != 1 || !to[0].equals(outerTo[0])) {
|
||||
throw new AcmeInvalidMessageException("Protected 'To' header does not match envelope header");
|
||||
}
|
||||
}
|
||||
|
@ -249,9 +250,8 @@ public final class EmailProcessor {
|
|||
if (subject == null) {
|
||||
throw new AcmeInvalidMessageException("Message has no 'Subject' header");
|
||||
}
|
||||
if (strict && signedMessage != null
|
||||
&& message.getSubject() != null
|
||||
&& !message.getSubject().equals(signedMessage.getSubject())) {
|
||||
if (strict && signedMessage != null &&
|
||||
(message.getSubject() == null || !message.getSubject().equals(signedMessage.getSubject()))) {
|
||||
throw new AcmeInvalidMessageException("Protected 'Subject' header does not match envelope header");
|
||||
}
|
||||
Matcher m = SUBJECT_PATTERN.matcher(subject);
|
||||
|
|
|
@ -68,9 +68,9 @@ public abstract class SMIMETests {
|
|||
*
|
||||
* @param name
|
||||
* Name of the mock message to be read from the test resources.
|
||||
* @return Mock {@link Message} that was created
|
||||
* @return Mock {@link MimeMessage} that was created
|
||||
*/
|
||||
protected Message mockMessage(String name) {
|
||||
protected MimeMessage mockMessage(String name) {
|
||||
try (InputStream in = SMIMETests.class.getResourceAsStream("/email/" + name + ".eml")) {
|
||||
return new MimeMessage(mailSession, in);
|
||||
} catch (IOException ex) {
|
||||
|
|
|
@ -67,19 +67,21 @@ public class EmailProcessorTest extends SMIMETests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testValidSignature() throws AcmeInvalidMessageException, IOException {
|
||||
MimeMessage message = (MimeMessage) mockMessage("valid-mail");
|
||||
public void testValidSignature() {
|
||||
assertThatNoException().isThrownBy(() -> {
|
||||
MimeMessage message = mockMessage("valid-mail");
|
||||
X509Certificate certificate = readCertificate("valid-signer");
|
||||
EmailProcessor processor = EmailProcessor.smimeMessage(message, mailSession, certificate, true);
|
||||
EmailProcessor.smimeMessage(message, mailSession, certificate, true);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvalidSignature() {
|
||||
assertThatExceptionOfType(AcmeInvalidMessageException.class)
|
||||
.isThrownBy(() -> {
|
||||
MimeMessage message = (MimeMessage) mockMessage("invalid-signed-mail");
|
||||
MimeMessage message = mockMessage("invalid-signed-mail");
|
||||
X509Certificate certificate = readCertificate("valid-signer");
|
||||
EmailProcessor processor = EmailProcessor.smimeMessage(message, mailSession, certificate, true);
|
||||
EmailProcessor.smimeMessage(message, mailSession, certificate, true);
|
||||
})
|
||||
.withMessage("The S/MIME signature is invalid");
|
||||
}
|
||||
|
@ -88,9 +90,9 @@ public class EmailProcessorTest extends SMIMETests {
|
|||
public void testValidSignatureButNoSAN() {
|
||||
assertThatExceptionOfType(AcmeInvalidMessageException.class)
|
||||
.isThrownBy(() -> {
|
||||
MimeMessage message = (MimeMessage) mockMessage("invalid-nosan");
|
||||
MimeMessage message = mockMessage("invalid-nosan");
|
||||
X509Certificate certificate = readCertificate("valid-signer-nosan");
|
||||
EmailProcessor processor = EmailProcessor.smimeMessage(message, mailSession, certificate, true);
|
||||
EmailProcessor.smimeMessage(message, mailSession, certificate, true);
|
||||
})
|
||||
.withMessage("Signing certificate does not provide a rfc822Name subjectAltName");
|
||||
}
|
||||
|
@ -99,9 +101,9 @@ public class EmailProcessorTest extends SMIMETests {
|
|||
public void testSANDoesNotMatchFrom() {
|
||||
assertThatExceptionOfType(AcmeInvalidMessageException.class)
|
||||
.isThrownBy(() -> {
|
||||
MimeMessage message = (MimeMessage) mockMessage("invalid-cert-mismatch");
|
||||
MimeMessage message = mockMessage("invalid-cert-mismatch");
|
||||
X509Certificate certificate = readCertificate("valid-signer");
|
||||
EmailProcessor processor = EmailProcessor.smimeMessage(message, mailSession, certificate, true);
|
||||
EmailProcessor.smimeMessage(message, mailSession, certificate, true);
|
||||
})
|
||||
.withMessage("Sender 'different-ca@example.com' was not found in signing certificate");
|
||||
}
|
||||
|
@ -110,9 +112,9 @@ public class EmailProcessorTest extends SMIMETests {
|
|||
public void testInvalidProtectedFromHeader() {
|
||||
assertThatExceptionOfType(AcmeInvalidMessageException.class)
|
||||
.isThrownBy(() -> {
|
||||
MimeMessage message = (MimeMessage) mockMessage("invalid-protected-mail-from");
|
||||
MimeMessage message = mockMessage("invalid-protected-mail-from");
|
||||
X509Certificate certificate = readCertificate("valid-signer");
|
||||
EmailProcessor processor = EmailProcessor.smimeMessage(message, mailSession, certificate, true);
|
||||
EmailProcessor.smimeMessage(message, mailSession, certificate, true);
|
||||
})
|
||||
.withMessage("Protected 'From' header does not match envelope header");
|
||||
}
|
||||
|
@ -121,9 +123,9 @@ public class EmailProcessorTest extends SMIMETests {
|
|||
public void testInvalidProtectedToHeader() {
|
||||
assertThatExceptionOfType(AcmeInvalidMessageException.class)
|
||||
.isThrownBy(() -> {
|
||||
MimeMessage message = (MimeMessage) mockMessage("invalid-protected-mail-to");
|
||||
MimeMessage message = mockMessage("invalid-protected-mail-to");
|
||||
X509Certificate certificate = readCertificate("valid-signer");
|
||||
EmailProcessor processor = EmailProcessor.smimeMessage(message, mailSession, certificate, true);
|
||||
EmailProcessor.smimeMessage(message, mailSession, certificate, true);
|
||||
})
|
||||
.withMessage("Protected 'To' header does not match envelope header");
|
||||
}
|
||||
|
@ -132,9 +134,9 @@ public class EmailProcessorTest extends SMIMETests {
|
|||
public void testInvalidProtectedSubjectHeader() {
|
||||
assertThatExceptionOfType(AcmeInvalidMessageException.class)
|
||||
.isThrownBy(() -> {
|
||||
MimeMessage message = (MimeMessage) mockMessage("invalid-protected-mail-subject");
|
||||
MimeMessage message = mockMessage("invalid-protected-mail-subject");
|
||||
X509Certificate certificate = readCertificate("valid-signer");
|
||||
EmailProcessor processor = EmailProcessor.smimeMessage(message, mailSession, certificate, true);
|
||||
EmailProcessor.smimeMessage(message, mailSession, certificate, true);
|
||||
})
|
||||
.withMessage("Protected 'Subject' header does not match envelope header");
|
||||
}
|
||||
|
@ -143,66 +145,80 @@ public class EmailProcessorTest extends SMIMETests {
|
|||
public void testNonStrictInvalidProtectedSubjectHeader() {
|
||||
assertThatNoException()
|
||||
.isThrownBy(() -> {
|
||||
MimeMessage message = (MimeMessage) mockMessage("invalid-protected-mail-subject");
|
||||
MimeMessage message = mockMessage("invalid-protected-mail-subject");
|
||||
X509Certificate certificate = readCertificate("valid-signer");
|
||||
EmailProcessor processor = EmailProcessor.smimeMessage(message, mailSession, certificate, false);
|
||||
EmailProcessor.smimeMessage(message, mailSession, certificate, false);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void textExpectedFromFails() {
|
||||
assertThrows(AcmeProtocolException.class, () -> {
|
||||
assertThatExceptionOfType(AcmeProtocolException.class)
|
||||
.isThrownBy(() -> {
|
||||
EmailProcessor processor = EmailProcessor.plainMessage(message);
|
||||
processor.expectedFrom(expectedTo);
|
||||
});
|
||||
})
|
||||
.withMessage("Message is not sent by the expected sender");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void textExpectedToFails() {
|
||||
assertThrows(AcmeProtocolException.class, () -> {
|
||||
assertThatExceptionOfType(AcmeProtocolException.class)
|
||||
.isThrownBy(() -> {
|
||||
EmailProcessor processor = EmailProcessor.plainMessage(message);
|
||||
processor.expectedTo(expectedFrom);
|
||||
});
|
||||
})
|
||||
.withMessage("Message is not addressed to expected recipient");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void textExpectedIdentifierFails1() {
|
||||
assertThrows(AcmeProtocolException.class, () -> {
|
||||
assertThatExceptionOfType(AcmeProtocolException.class)
|
||||
.isThrownBy(() -> {
|
||||
EmailProcessor processor = EmailProcessor.plainMessage(message);
|
||||
processor.expectedIdentifier(EmailIdentifier.email(expectedFrom));
|
||||
});
|
||||
})
|
||||
.withMessage("Message is not addressed to expected recipient");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void textExpectedIdentifierFails2() {
|
||||
assertThrows(AcmeProtocolException.class, () -> {
|
||||
assertThatExceptionOfType(AcmeProtocolException.class)
|
||||
.isThrownBy(() -> {
|
||||
EmailProcessor processor = EmailProcessor.plainMessage(message);
|
||||
processor.expectedIdentifier(Identifier.ip("192.168.0.1"));
|
||||
});
|
||||
})
|
||||
.withMessage("Wrong identifier type: ip");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void textNoChallengeFails1() {
|
||||
assertThrows(IllegalStateException.class, () -> {
|
||||
assertThatExceptionOfType(IllegalStateException.class)
|
||||
.isThrownBy(() -> {
|
||||
EmailProcessor processor = EmailProcessor.plainMessage(message);
|
||||
processor.getToken();
|
||||
});
|
||||
})
|
||||
.withMessage("No challenge has been set yet");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void textNoChallengeFails2() {
|
||||
assertThrows(IllegalStateException.class, () -> {
|
||||
assertThatExceptionOfType(IllegalStateException.class)
|
||||
.isThrownBy(() -> {
|
||||
EmailProcessor processor = EmailProcessor.plainMessage(message);
|
||||
processor.getAuthorization();
|
||||
});
|
||||
})
|
||||
.withMessage("No challenge has been set yet");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void textNoChallengeFails3() {
|
||||
assertThrows(IllegalStateException.class, () -> {
|
||||
assertThatExceptionOfType(IllegalStateException.class)
|
||||
.isThrownBy(() -> {
|
||||
EmailProcessor processor = EmailProcessor.plainMessage(message);
|
||||
processor.respond();
|
||||
});
|
||||
})
|
||||
.withMessage("No challenge has been set yet");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -218,11 +234,13 @@ public class EmailProcessorTest extends SMIMETests {
|
|||
|
||||
@Test
|
||||
public void testChallengeMismatch() {
|
||||
assertThrows(AcmeProtocolException.class, () -> {
|
||||
assertThatExceptionOfType(AcmeProtocolException.class)
|
||||
.isThrownBy(() -> {
|
||||
EmailReply00Challenge challenge = mockChallenge("emailReplyChallengeMismatch");
|
||||
EmailProcessor processor = EmailProcessor.plainMessage(message);
|
||||
processor.withChallenge(challenge);
|
||||
});
|
||||
})
|
||||
.withMessage("Message is not sent by the expected sender");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in New Issue