This is an automated email from the ASF dual-hosted git repository. rcordier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit e70b8696448b794b55fc46fba8bc028a13fe0f5d Author: Benoit Tellier <[email protected]> AuthorDate: Fri May 29 09:17:21 2020 +0700 JAMES-3196 CanSendFromImpl: enable sender correlation for SMTP and JMAP Explicitly link the user with the alias when allowing the mail submission to ease audit. --- .../methods/integration/SetMessagesMethodTest.java | 4 ++-- .../methods/MailboxSendingNotAllowedException.java | 21 +++++++++++++------ .../methods/SetMessagesCreationProcessor.java | 24 ++++++++++++++++------ .../draft/methods/SetMessagesUpdateProcessor.java | 5 +++-- .../SenderAuthIdentifyVerificationRcptHook.java | 12 ++++++++++- 5 files changed, 49 insertions(+), 17 deletions(-) diff --git a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SetMessagesMethodTest.java b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SetMessagesMethodTest.java index 46ab5db..38c9e99 100644 --- a/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SetMessagesMethodTest.java +++ b/server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/java/org/apache/james/jmap/draft/methods/integration/SetMessagesMethodTest.java @@ -2651,7 +2651,7 @@ public abstract class SetMessagesMethodTest { .body(ARGUMENTS + ".notCreated", aMapWithSize(1)) .body(ARGUMENTS + ".notCreated", hasKey(messageCreationId)) .body(ARGUMENTS + ".notCreated." + messageCreationId + ".type", equalTo("invalidProperties")) - .body(ARGUMENTS + ".notCreated." + messageCreationId + ".description", equalTo("Invalid 'from' field. Must be " + USERNAME.asString())); + .body(ARGUMENTS + ".notCreated." + messageCreationId + ".description", equalTo("Invalid 'from' field. One accepted value is " + USERNAME.asString())); } @Test @@ -2999,7 +2999,7 @@ public abstract class SetMessagesMethodTest { .body(ARGUMENTS + ".notCreated[\"" + messageCreationId + "\"].type", equalTo("invalidProperties")) .body(ARGUMENTS + ".notCreated[\"" + messageCreationId + "\"].properties", hasSize(1)) .body(ARGUMENTS + ".notCreated[\"" + messageCreationId + "\"].properties", contains("from")) - .body(ARGUMENTS + ".notCreated[\"" + messageCreationId + "\"].description", endsWith("Invalid 'from' field. Must be [email protected]")) + .body(ARGUMENTS + ".notCreated[\"" + messageCreationId + "\"].description", endsWith("Invalid 'from' field. One accepted value is [email protected]")) .body(ARGUMENTS + ".created", aMapWithSize(0)); } diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/MailboxSendingNotAllowedException.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/MailboxSendingNotAllowedException.java index 19ac45f..8c3f0f5 100644 --- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/MailboxSendingNotAllowedException.java +++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/MailboxSendingNotAllowedException.java @@ -19,18 +19,27 @@ package org.apache.james.jmap.draft.methods; +import java.util.Optional; + +import org.apache.james.core.Username; import org.apache.james.mailbox.exception.MailboxException; public class MailboxSendingNotAllowedException extends MailboxException { - private String allowedFrom; + private final Username connectedUser; + private final Optional<Username> fromField; - public MailboxSendingNotAllowedException(String allowedFrom) { + public MailboxSendingNotAllowedException(Username connectedUser, Optional<Username> fromField) { super(); - this.allowedFrom = allowedFrom; + this.connectedUser = connectedUser; + this.fromField = fromField; + } + + public Optional<Username> getFromField() { + return fromField; } - - public String getAllowedFrom() { - return allowedFrom; + + public Username getConnectedUser() { + return connectedUser; } } diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMessagesCreationProcessor.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMessagesCreationProcessor.java index 77c53b6..a384bd8 100644 --- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMessagesCreationProcessor.java +++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMessagesCreationProcessor.java @@ -132,12 +132,14 @@ public class SetMessagesCreationProcessor implements SetMessagesProcessor { assertIsUserOwnerOfMailboxes(mailboxIds, mailboxSession); performCreate(create, responseBuilder, mailboxSession); } catch (MailboxSendingNotAllowedException e) { + LOG.debug("{} is not allowed to send a mail using {} identity", e.getConnectedUser().asString(), e.getFromField()); + responseBuilder.notCreated(create.getCreationId(), SetError.builder() .type(SetError.Type.INVALID_PROPERTIES) .properties(MessageProperty.from) - .description("Invalid 'from' field. Must be " + - e.getAllowedFrom()) + .description("Invalid 'from' field. One accepted value is " + + e.getConnectedUser().asString()) .build()); } catch (InvalidDraftKeywordsException e) { @@ -296,14 +298,24 @@ public class SetMessagesCreationProcessor implements SetMessagesProcessor { @VisibleForTesting void assertUserCanSendFrom(Username connectedUser, Optional<DraftEmailer> from) throws MailboxSendingNotAllowedException { - if (!from.flatMap(DraftEmailer::getEmail) - .filter(email -> canSendFrom.userCanSendFrom(connectedUser, Username.of(email))) - .isPresent()) { + + Optional<Username> maybeFromUser = from.flatMap(DraftEmailer::getEmail) + .map(Username::of); + + if (!canSendMailUsingIdentity(connectedUser, maybeFromUser)) { String allowedSender = connectedUser.asString(); - throw new MailboxSendingNotAllowedException(allowedSender); + throw new MailboxSendingNotAllowedException(connectedUser, maybeFromUser); + } else { + LOG.debug("{} is allowed to send a mail using {} identity", connectedUser.asString(), from); } } + private boolean canSendMailUsingIdentity(Username connectedUser, Optional<Username> maybeFromUser) { + return maybeFromUser + .filter(fromUser -> canSendFrom.userCanSendFrom(connectedUser, fromUser)) + .isPresent(); + } + private MessageWithId handleDraftMessages(CreationMessageEntry entry, MailboxSession session) throws MailboxException, MessagingException, IOException { MetaDataWithContent newMessage = messageAppender.appendMessageInMailboxes(entry, toMailboxIds(entry), session); MessageFullView jmapMessage = messageFullViewFactory.fromMetaDataWithContent(newMessage).block(); diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMessagesUpdateProcessor.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMessagesUpdateProcessor.java index c6f4039..35ba365 100644 --- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMessagesUpdateProcessor.java +++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/SetMessagesUpdateProcessor.java @@ -198,8 +198,9 @@ public class SetMessagesUpdateProcessor implements SetMessagesProcessor { void assertUserCanSendFrom(Username connectedUser, Optional<Username> fromUser) throws MailboxSendingNotAllowedException { if (!fromUser.filter(from -> canSendFrom.userCanSendFrom(connectedUser, from)) .isPresent()) { - String allowedSender = connectedUser.asString(); - throw new MailboxSendingNotAllowedException(allowedSender); + throw new MailboxSendingNotAllowedException(connectedUser, fromUser); + } else { + LOGGER.debug("{} is allowed to send a mail using {} identity", connectedUser.asString(), fromUser); } } diff --git a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/SenderAuthIdentifyVerificationRcptHook.java b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/SenderAuthIdentifyVerificationRcptHook.java index cf6924c..2543fab 100644 --- a/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/SenderAuthIdentifyVerificationRcptHook.java +++ b/server/protocols/protocols-smtp/src/main/java/org/apache/james/smtpserver/SenderAuthIdentifyVerificationRcptHook.java @@ -32,11 +32,15 @@ import org.apache.james.protocols.smtp.hook.HookResult; import org.apache.james.rrt.api.CanSendFrom; import org.apache.james.user.api.UsersRepository; import org.apache.james.user.api.UsersRepositoryException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Handler which check if the authenticated user is incorrect */ public class SenderAuthIdentifyVerificationRcptHook extends AbstractSenderAuthIdentifyVerificationRcptHook { + private static final Logger LOGGER = LoggerFactory.getLogger(SenderAuthIdentifyVerificationRcptHook.class); + private final DomainList domains; private final UsersRepository users; private final CanSendFrom canSendFrom; @@ -78,6 +82,12 @@ public class SenderAuthIdentifyVerificationRcptHook extends AbstractSenderAuthId @Override protected boolean isSenderAllowed(Username connectedUser, Username sender) { - return canSendFrom.userCanSendFrom(connectedUser, sender); + boolean allowed = canSendFrom.userCanSendFrom(connectedUser, sender); + if (allowed) { + LOGGER.debug("{} is allowed to send a mail using {} identity", connectedUser.asString(), sender.asString()); + } else { + LOGGER.info("{} is not allowed to send a mail using {} identity", connectedUser.asString(), sender.asString()); + } + return allowed; } } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
