You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2021/11/12 07:40:37 UTC
[james-project] branch master updated: JAMES-1618 Fix manage sieve
implementation and test it with Thunderbird (#742)
This is an automated email from the ASF dual-hosted git repository.
btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
The following commit(s) were added to refs/heads/master by this push:
new 00fcf38 JAMES-1618 Fix manage sieve implementation and test it with Thunderbird (#742)
00fcf38 is described below
commit 00fcf384db0405900a2d766a5f126a7b3f19a849
Author: Benoit TELLIER <bt...@linagora.com>
AuthorDate: Fri Nov 12 14:40:28 2021 +0700
JAMES-1618 Fix manage sieve implementation and test it with Thunderbird (#742)
---
.../james/mpt/testsuite/AuthenticateContract.java | 7 +++++
.../james/managesieve/scripts/authenticate.test | 4 +--
.../{starttls.test => authenticateBase64.test} | 17 ++---------
.../james/managesieve/scripts/capability.test | 2 +-
.../james/managesieve/scripts/checkscript.test | 11 +++----
.../james/managesieve/scripts/deletescript.test | 12 ++++----
.../james/managesieve/scripts/getscript.test | 7 +++--
.../james/managesieve/scripts/havespace.test | 2 +-
.../james/managesieve/scripts/listscripts.test | 8 ++---
.../james/managesieve/scripts/putscript.test | 6 ++--
.../james/managesieve/scripts/renamescript.test | 12 ++++----
.../james/managesieve/scripts/setactive.test | 4 +--
.../apache/james/managesieve/scripts/starttls.test | 2 +-
.../james/managesieve/scripts/unauthenticate.test | 2 +-
.../james/managesieve/core/CoreProcessor.java | 4 +--
.../core/PlainAuthenticationProcessor.java | 18 +++++++----
.../managesieve/transcode/ArgumentParser.java | 25 ++++++++++++++--
.../transcode/ManageSieveProcessor.java | 10 +++++++
.../transcode/NotEnoughDataException.java | 24 +++++++++++++++
.../apache/james/managesieve/util/ParserUtils.java | 12 ++++++++
.../transport/mailets/jsieve/RedirectAction.java | 10 +++++--
.../transport/mailets/jsieve/RejectAction.java | 10 +++++--
.../transport/mailets/jsieve/VacationAction.java | 10 +++++--
.../mailets/managesieve/ManageSieveMailet.java | 5 ++--
.../netty/ChannelManageSieveResponseWriter.java | 35 ++++++++++++++++++++--
.../netty/ManageSieveChannelUpstreamHandler.java | 15 ++++++++--
.../netty/ManageSieveMDCContext.java | 4 ++-
27 files changed, 206 insertions(+), 72 deletions(-)
diff --git a/mpt/impl/managesieve/core/src/main/java/org/apache/james/mpt/testsuite/AuthenticateContract.java b/mpt/impl/managesieve/core/src/main/java/org/apache/james/mpt/testsuite/AuthenticateContract.java
index cc383f1..c74c67c 100644
--- a/mpt/impl/managesieve/core/src/main/java/org/apache/james/mpt/testsuite/AuthenticateContract.java
+++ b/mpt/impl/managesieve/core/src/main/java/org/apache/james/mpt/testsuite/AuthenticateContract.java
@@ -41,4 +41,11 @@ public interface AuthenticateContract extends HostSystemProvider {
.withLocale(Locale.US)
.run("authenticate");
}
+
+ @Test
+ default void authenticateBase64ShouldWork() throws Exception {
+ authenticateContractProtocol()
+ .withLocale(Locale.US)
+ .run("authenticateBase64");
+ }
}
diff --git a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/authenticate.test b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/authenticate.test
index 896c3d8..334699c 100644
--- a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/authenticate.test
+++ b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/authenticate.test
@@ -20,7 +20,7 @@
C: AUTHENTICATE
S: NO ManageSieve syntax is incorrect : You must specify a SASL mechanism as an argument of AUTHENTICATE command
-C: AUTHENTICATE UNKNOWN
+C: AUTHENTICATE "UNKNOWN"
S: NO Unknown SASL mechanism UNKNOWN
C: AUTHENTICATE "PLAIN"
@@ -34,4 +34,4 @@ S: NO authentication failed
C: AUTHENTICATE "PLAIN"
S: \+ ""
C: user password
-S: OK authentication successfull
\ No newline at end of file
+S: OK
\ No newline at end of file
diff --git a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/starttls.test b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/authenticateBase64.test
similarity index 80%
copy from mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/starttls.test
copy to mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/authenticateBase64.test
index 2706ff8..cee22fb 100644
--- a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/starttls.test
+++ b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/authenticateBase64.test
@@ -17,18 +17,5 @@
# under the License. #
################################################################
-C: STARTTLS
-S: OK
-
-C: STARTTLS
-S: NO You can't enable two time SSL encryption
-
-C: AUTHENTICATE "PLAIN"
-S: \+ ""
-C: user password
-S: OK authentication successfull
-
-C: STARTTLS
-S: NO command STARTTLS is issued in the wrong state. It must be issued as you are unauthenticated
-
-C: LOGOUT
\ No newline at end of file
+C: AUTHENTICATE "PLAIN" "AHVzZXIAcGFzc3dvcmQ="
+S: OK
\ No newline at end of file
diff --git a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/capability.test b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/capability.test
index 894d10c..1b2141b 100644
--- a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/capability.test
+++ b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/capability.test
@@ -40,7 +40,7 @@ S: OK
C: AUTHENTICATE "PLAIN"
S: \+ ""
C: user password
-S: OK authentication successfull
+S: OK
C: CAPABILITY
SUB {
diff --git a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/checkscript.test b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/checkscript.test
index cd48797..8fc76dd 100644
--- a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/checkscript.test
+++ b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/checkscript.test
@@ -23,8 +23,9 @@ S: NO " is an invalid size literal : it should be at least 4 char looking like \
C: CHECKSCRIPT unquoted
S: NO "unquoted is an invalid size literal : it should be at least 4 char looking like .*"
-C: CHECKSCRIPT {31+}
-S: NO "Missing argument: script content"
+# Now waits for extra data, the expected behaviour
+#C: CHECKSCRIPT {31+}
+#S: NO "Missing argument: script content"
C: CHECKSCRIPT {31+}
C: #comment
@@ -35,9 +36,9 @@ S: NO
C: AUTHENTICATE "PLAIN"
S: \+ ""
C: user password
-S: OK authentication successfull
+S: OK
-C: CHECKSCRIPT {110+}
+C: CHECKSCRIPT {99+}
C: require ["fileinto"];
C:
C: if envelope :contains "to" "tmartin+sent" {
@@ -49,5 +50,5 @@ C: CHECKSCRIPT {31+}
C: #comment
C: InvalidSieveCommand
C:
-S: NO "Syntax Error: org.apache.jsieve.parser.generated.ParseException: Encountered "<EOF>" at line 2, column 19.
+S: NO "Syntax Error: org.apache.jsieve.parser.generated.ParseException: Encountered "<EOF>" at line 2, column 21.
diff --git a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/deletescript.test b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/deletescript.test
index 72916ad..5352d2a 100644
--- a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/deletescript.test
+++ b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/deletescript.test
@@ -26,12 +26,12 @@ S: NO
C: AUTHENTICATE "PLAIN"
S: \+ ""
C: user password
-S: OK authentication successfull
+S: OK
C: DELETESCRIPT "foo"
S: NO \(NONEXISTENT\) "There is no script by that name"
-C: PUTSCRIPT "mysievescript" {110+}
+C: PUTSCRIPT "mysievescript" {99+}
C: require ["fileinto"];
C:
C: if envelope :contains "to" "tmartin+sent" {
@@ -40,12 +40,13 @@ C: }
S: OK
C: GETSCRIPT "mysievescript"
-S: \{97\}
+S: \{99\}
S: require \["fileinto"\];
S:
S: if envelope :contains "to" "tmartin\+sent" \{
S: fileinto "INBOX.sent";
S: \}
+S:
S: OK
C: DELETESCRIPT "mysievescript"
@@ -54,7 +55,7 @@ S: OK
C: GETSCRIPT "mysievescript"
S: NO \(NONEXISTENT\) "There is no script by that name"
-C: PUTSCRIPT "mysievescript" {110+}
+C: PUTSCRIPT "mysievescript" {99+}
C: require ["fileinto"];
C:
C: if envelope :contains "to" "tmartin+sent" {
@@ -63,12 +64,13 @@ C: }
S: OK
C: GETSCRIPT "mysievescript"
-S: \{97\}
+S: \{99\}
S: require \["fileinto"\];
S:
S: if envelope :contains "to" "tmartin\+sent" \{
S: fileinto "INBOX.sent";
S: \}
+S:
S: OK
C: SETACTIVE "mysievescript"
diff --git a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/getscript.test b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/getscript.test
index 19e0380..aa5ca1d 100644
--- a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/getscript.test
+++ b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/getscript.test
@@ -26,12 +26,12 @@ S: NO
C: AUTHENTICATE "PLAIN"
S: \+ ""
C: user password
-S: OK authentication successfull
+S: OK
C: GETSCRIPT "foo"
S: NO \(NONEXISTENT\) "There is no script by that name"
-C: PUTSCRIPT "mysievescript" {110+}
+C: PUTSCRIPT "mysievescript" {99+}
C: require ["fileinto"];
C:
C: if envelope :contains "to" "tmartin+sent" {
@@ -40,12 +40,13 @@ C: }
S: OK
C: GETSCRIPT "mysievescript"
-S: \{97\}
+S: \{99\}
S: require \["fileinto"\];
S:
S: if envelope :contains "to" "tmartin\+sent" \{
S: fileinto "INBOX.sent";
S: \}
+S:
S: OK
diff --git a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/havespace.test b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/havespace.test
index 7eda344..2b09582 100644
--- a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/havespace.test
+++ b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/havespace.test
@@ -29,7 +29,7 @@ S: NO
C: AUTHENTICATE "PLAIN"
S: \+ ""
C: user password
-S: OK authentication successfull
+S: OK
C: HAVESPACE "scriptname" 49
S: OK
diff --git a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/listscripts.test b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/listscripts.test
index 14bb2e3..1539277 100644
--- a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/listscripts.test
+++ b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/listscripts.test
@@ -23,12 +23,12 @@ S: NO
C: AUTHENTICATE "PLAIN"
S: \+ ""
C: user password
-S: OK authentication successfull
+S: OK
C: LISTSCRIPTS
S: OK
-C: PUTSCRIPT "mysievescript" {110+}
+C: PUTSCRIPT "mysievescript" {99+}
C: require ["fileinto"];
C:
C: if envelope :contains "to" "tmartin+sent" {
@@ -36,7 +36,7 @@ C: fileinto "INBOX.sent";
C: }
S: OK
-C: PUTSCRIPT "toto1" {110+}
+C: PUTSCRIPT "toto1" {99+}
C: require ["fileinto"];
C:
C: if envelope :contains "to" "tmartin+sent" {
@@ -44,7 +44,7 @@ C: fileinto "INBOX.sent";
C: }
S: OK
-C: PUTSCRIPT "toto2" {110+}
+C: PUTSCRIPT "toto2" {99+}
C: require ["fileinto"];
C:
C: if envelope :contains "to" "tmartin+sent" {
diff --git a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/putscript.test b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/putscript.test
index 073db5a..e8e300f 100644
--- a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/putscript.test
+++ b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/putscript.test
@@ -41,9 +41,9 @@ S: NO
C: AUTHENTICATE "PLAIN"
S: \+ ""
C: user password
-S: OK authentication successfull
+S: OK
-C: PUTSCRIPT "mysievescript" {110+}
+C: PUTSCRIPT "mysievescript" {97+}
C: require ["fileinto"];
C:
C: if envelope :contains "to" "tmartin+sent" {
@@ -55,5 +55,5 @@ C: PUTSCRIPT "foo" {31+}
C: #comment
C: InvalidSieveCommand
C:
-S: NO "Syntax Error: org.apache.jsieve.parser.generated.ParseException: Encountered "<EOF>" at line 2, column 19.
+S: NO "Syntax Error: org.apache.jsieve.parser.generated.ParseException: Encountered "<EOF>" at line 2, column 21.
diff --git a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/renamescript.test b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/renamescript.test
index ea9886e..355cd84 100644
--- a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/renamescript.test
+++ b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/renamescript.test
@@ -29,9 +29,9 @@ S: NO
C: AUTHENTICATE "PLAIN"
S: \+ ""
C: user password
-S: OK authentication successfull
+S: OK
-C: PUTSCRIPT "mysievescript" {110+}
+C: PUTSCRIPT "mysievescript" {99+}
C: require ["fileinto"];
C:
C: if envelope :contains "to" "tmartin+sent" {
@@ -40,30 +40,32 @@ C: }
S: OK
C: GETSCRIPT "mysievescript"
-S: \{97\}
+S: \{99\}
S: require \["fileinto"\];
S:
S: if envelope :contains "to" "tmartin\+sent" \{
S: fileinto "INBOX.sent";
S: \}
+S:
S: OK
C: RENAMESCRIPT "mysievescript" "mysievescriptbis"
S: OK
C: GETSCRIPT "mysievescriptbis"
-S: \{97\}
+S: \{99\}
S: require \["fileinto"\];
S:
S: if envelope :contains "to" "tmartin\+sent" \{
S: fileinto "INBOX.sent";
S: \}
+S:
S: OK
C: GETSCRIPT "mysievescript"
S: NO \(NONEXISTENT\) "There is no script by that name"
-C: PUTSCRIPT "mysievescript" {110+}
+C: PUTSCRIPT "mysievescript" {99+}
C: require ["fileinto"];
C:
C: if envelope :contains "to" "tmartin+sent" {
diff --git a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/setactive.test b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/setactive.test
index 0174316..c05ff82e 100644
--- a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/setactive.test
+++ b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/setactive.test
@@ -26,12 +26,12 @@ S: NO
C: AUTHENTICATE "PLAIN"
S: \+ ""
C: user password
-S: OK authentication successfull
+S: OK
C: SETACTIVE "foo"
S: NO \(NONEXISTENT\) "There is no script by that name"
-C: PUTSCRIPT "mysievescript" {110+}
+C: PUTSCRIPT "mysievescript" {99+}
C: require ["fileinto"];
C:
C: if envelope :contains "to" "tmartin+sent" {
diff --git a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/starttls.test b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/starttls.test
index 2706ff8..7e97354 100644
--- a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/starttls.test
+++ b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/starttls.test
@@ -26,7 +26,7 @@ S: NO You can't enable two time SSL encryption
C: AUTHENTICATE "PLAIN"
S: \+ ""
C: user password
-S: OK authentication successfull
+S: OK
C: STARTTLS
S: NO command STARTTLS is issued in the wrong state. It must be issued as you are unauthenticated
diff --git a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/unauthenticate.test b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/unauthenticate.test
index 658a410..4acc436 100644
--- a/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/unauthenticate.test
+++ b/mpt/impl/managesieve/core/src/main/resources/org/apache/james/managesieve/scripts/unauthenticate.test
@@ -29,7 +29,7 @@ S: NO UNAUTHENTICATE command must be issued in authenticated state
C: AUTHENTICATE "PLAIN"
S: \+ ""
C: user password
-S: OK authentication successfull
+S: OK
C: GETSCRIPT any
S: NO \(NONEXISTENT\) "There is no script by that name"
diff --git a/protocols/managesieve/src/main/java/org/apache/james/managesieve/core/CoreProcessor.java b/protocols/managesieve/src/main/java/org/apache/james/managesieve/core/CoreProcessor.java
index bf28ac8..cc84451 100644
--- a/protocols/managesieve/src/main/java/org/apache/james/managesieve/core/CoreProcessor.java
+++ b/protocols/managesieve/src/main/java/org/apache/james/managesieve/core/CoreProcessor.java
@@ -216,7 +216,7 @@ public class CoreProcessor implements CoreCommands {
if (Strings.isNullOrEmpty(mechanism)) {
return "NO ManageSieve syntax is incorrect : You must specify a SASL mechanism as an argument of AUTHENTICATE command";
}
- String unquotedMechanism = ParserUtils.unquote(mechanism);
+ String unquotedMechanism = ParserUtils.unquoteFirst(mechanism);
SupportedMechanism supportedMechanism = SupportedMechanism.retrieveMechanism(unquotedMechanism);
session.setChoosedAuthenticationMechanism(supportedMechanism);
@@ -237,7 +237,7 @@ public class CoreProcessor implements CoreCommands {
if (authenticatedUsername != null) {
session.setUser(authenticatedUsername);
session.setState(Session.State.AUTHENTICATED);
- return "OK authentication successfull";
+ return "OK";
} else {
session.setState(Session.State.UNAUTHENTICATED);
session.setUser(null);
diff --git a/protocols/managesieve/src/main/java/org/apache/james/managesieve/core/PlainAuthenticationProcessor.java b/protocols/managesieve/src/main/java/org/apache/james/managesieve/core/PlainAuthenticationProcessor.java
index f0d4f03..4c94818 100644
--- a/protocols/managesieve/src/main/java/org/apache/james/managesieve/core/PlainAuthenticationProcessor.java
+++ b/protocols/managesieve/src/main/java/org/apache/james/managesieve/core/PlainAuthenticationProcessor.java
@@ -20,6 +20,8 @@
package org.apache.james.managesieve.core;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
import java.util.Iterator;
import org.apache.james.core.Username;
@@ -54,15 +56,21 @@ public class PlainAuthenticationProcessor implements AuthenticationProcessor {
@Override
public Username isAuthenticationSuccesfull(Session session, String suppliedClientData) throws SyntaxException, AuthenticationException {
- if (suppliedClientData.contains("\u0000")) {
- return authenticateWithSeparator(session, suppliedClientData, '\u0000');
- } else {
- return authenticateWithSeparator(session, suppliedClientData, ' ');
+ try {
+ byte[] decoded = Base64.getDecoder().decode(suppliedClientData.getBytes());
+ String decodedString = new String(decoded, StandardCharsets.US_ASCII);
+ return authenticateWithSeparator(session, decodedString, '\u0000');
+ } catch (Exception e) {
+ if (suppliedClientData.contains("\u0000")) {
+ return authenticateWithSeparator(session, suppliedClientData, '\u0000');
+ } else {
+ return authenticateWithSeparator(session, suppliedClientData, ' ');
+ }
}
}
private Username authenticateWithSeparator(Session session, String suppliedClientData, char c) throws SyntaxException, AuthenticationException {
- Iterator<String> it = Splitter.on(c).split(suppliedClientData).iterator();
+ Iterator<String> it = Splitter.on(c).omitEmptyStrings().split(suppliedClientData).iterator();
if (!it.hasNext()) {
throw new SyntaxException("You must supply a username for the authentication mechanism. Formal syntax : <NULL>username<NULL>password");
}
diff --git a/protocols/managesieve/src/main/java/org/apache/james/managesieve/transcode/ArgumentParser.java b/protocols/managesieve/src/main/java/org/apache/james/managesieve/transcode/ArgumentParser.java
index eb8fa4e..e387707 100644
--- a/protocols/managesieve/src/main/java/org/apache/james/managesieve/transcode/ArgumentParser.java
+++ b/protocols/managesieve/src/main/java/org/apache/james/managesieve/transcode/ArgumentParser.java
@@ -40,10 +40,17 @@ import com.google.common.base.Strings;
public class ArgumentParser {
private final CoreCommands core;
+ private final boolean validatePutSize;
@Inject
public ArgumentParser(CoreCommands core) {
this.core = core;
+ this.validatePutSize = true;
+ }
+
+ public ArgumentParser(CoreCommands core, boolean validatePutSize) {
+ this.core = core;
+ this.validatePutSize = validatePutSize;
}
public String getAdvertisedCapabilities() {
@@ -109,11 +116,12 @@ public class ArgumentParser {
Iterator<String> firstLine = Splitter.on("\r\n").split(args.trim()).iterator();
Iterator<String> arguments = Splitter.on(' ').split(firstLine.next().trim()).iterator();
+ long size;
if (! arguments.hasNext()) {
return "NO : Missing argument: script size";
} else {
try {
- ParserUtils.getSize(arguments.next());
+ size = ParserUtils.getSize(arguments.next());
} catch (ArgumentException e) {
return "NO \"" + e.getMessage() + "\"";
}
@@ -122,6 +130,12 @@ public class ArgumentParser {
return "NO \"Extra arguments not supported\"";
} else {
String content = Joiner.on("\r\n").join(firstLine);
+ if (validatePutSize) {
+ content += "\r\n";
+ }
+ if (content.length() < size && validatePutSize) {
+ throw new NotEnoughDataException();
+ }
if (Strings.isNullOrEmpty(content)) {
return "NO \"Missing argument: script content\"";
}
@@ -162,6 +176,7 @@ public class ArgumentParser {
Iterator<String> arguments = Splitter.on(' ').split(firstLine.next().trim()).iterator();
String scriptName;
+ long size;
if (! arguments.hasNext()) {
return "NO \"Missing argument: script name\"";
} else {
@@ -174,7 +189,7 @@ public class ArgumentParser {
return "NO \"Missing argument: script size\"";
} else {
try {
- ParserUtils.getSize(arguments.next());
+ size = ParserUtils.getSize(arguments.next());
} catch (ArgumentException e) {
return "NO \"" + e.getMessage() + "\"";
}
@@ -183,6 +198,12 @@ public class ArgumentParser {
return "NO \"Extra arguments not supported\"";
} else {
String content = Joiner.on("\r\n").join(firstLine);
+ if (validatePutSize) {
+ content += "\r\n";
+ }
+ if (content.length() < size && validatePutSize) {
+ throw new NotEnoughDataException();
+ }
return core.putScript(session, ParserUtils.unquote(scriptName), content);
}
}
diff --git a/protocols/managesieve/src/main/java/org/apache/james/managesieve/transcode/ManageSieveProcessor.java b/protocols/managesieve/src/main/java/org/apache/james/managesieve/transcode/ManageSieveProcessor.java
index 85d00b6..52e68ed 100644
--- a/protocols/managesieve/src/main/java/org/apache/james/managesieve/transcode/ManageSieveProcessor.java
+++ b/protocols/managesieve/src/main/java/org/apache/james/managesieve/transcode/ManageSieveProcessor.java
@@ -22,6 +22,7 @@ package org.apache.james.managesieve.transcode;
import javax.inject.Inject;
+import org.apache.commons.lang3.StringUtils;
import org.apache.james.managesieve.api.ManageSieveException;
import org.apache.james.managesieve.api.Session;
import org.apache.james.managesieve.api.SessionTerminatedException;
@@ -88,6 +89,15 @@ public class ManageSieveProcessor {
return argumentParser.authenticate(session, arguments);
}
if (command.equalsIgnoreCase(AUTHENTICATE)) {
+ if (StringUtils.countMatches(arguments, "\"") == 4) {
+ argumentParser.chooseMechanism(session, arguments);
+ int bracket1 = arguments.indexOf('\"');
+ int bracket2 = arguments.indexOf('\"', bracket1 + 1);
+ int bracket3 = arguments.indexOf('\"', bracket2 + 1);
+ int bracket4 = arguments.indexOf('\"', bracket3 + 1);
+
+ return argumentParser.authenticate(session, arguments.substring(bracket3 + 1, bracket4));
+ }
return argumentParser.chooseMechanism(session, arguments);
} else if (command.equalsIgnoreCase(CAPABILITY)) {
return argumentParser.capability(session, arguments);
diff --git a/protocols/managesieve/src/main/java/org/apache/james/managesieve/transcode/NotEnoughDataException.java b/protocols/managesieve/src/main/java/org/apache/james/managesieve/transcode/NotEnoughDataException.java
new file mode 100644
index 0000000..9797bbd
--- /dev/null
+++ b/protocols/managesieve/src/main/java/org/apache/james/managesieve/transcode/NotEnoughDataException.java
@@ -0,0 +1,24 @@
+/*
+ * 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.managesieve.transcode;
+
+public class NotEnoughDataException extends RuntimeException {
+}
diff --git a/protocols/managesieve/src/main/java/org/apache/james/managesieve/util/ParserUtils.java b/protocols/managesieve/src/main/java/org/apache/james/managesieve/util/ParserUtils.java
index 6c36c36..f071988 100644
--- a/protocols/managesieve/src/main/java/org/apache/james/managesieve/util/ParserUtils.java
+++ b/protocols/managesieve/src/main/java/org/apache/james/managesieve/util/ParserUtils.java
@@ -50,4 +50,16 @@ public class ParserUtils {
return result;
}
+ public static String unquoteFirst(String quoted) {
+ if (quoted == null) {
+ return null;
+ }
+ if (quoted.length() > 2 && quoted.startsWith("\"") && quoted.indexOf('\"', 1) >= 0) {
+ return quoted.substring(1, quoted.indexOf('\"', 1));
+ } else if (quoted.startsWith("'") && quoted.endsWith("'")) {
+ return quoted.substring(1, quoted.length() - 1);
+ }
+ return null;
+ }
+
}
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/RedirectAction.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/RedirectAction.java
index ef422ad..ec9c6d4 100644
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/RedirectAction.java
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/RedirectAction.java
@@ -21,6 +21,7 @@ package org.apache.james.transport.mailets.jsieve;
import javax.mail.MessagingException;
import org.apache.james.core.MailAddress;
+import org.apache.james.lifecycle.api.LifecycleUtil;
import org.apache.james.server.core.MailImpl;
import org.apache.jsieve.mail.Action;
import org.apache.jsieve.mail.ActionRedirect;
@@ -57,12 +58,17 @@ public class RedirectAction implements MailAction {
public void execute(ActionRedirect anAction, Mail aMail, ActionContext context) throws MessagingException {
ActionUtils.detectAndHandleLocalLooping(aMail, context, "redirect");
- context.post(MailImpl.builder()
+ MailImpl redirectedMail = MailImpl.builder()
.name("redirect-" + aMail.getName())
.sender(aMail.getMaybeSender())
.addRecipient(new MailAddress(anAction.getAddress()))
.mimeMessage(aMail.getMessage())
- .build());
+ .build();
+ try {
+ context.post(redirectedMail);
+ } finally {
+ LifecycleUtil.dispose(redirectedMail);
+ }
LOGGER.debug("Redirected Message ID: {} to \"{}\"", aMail.getMessage().getMessageID(), anAction.getAddress());
DiscardAction.removeRecipient(aMail, context);
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/RejectAction.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/RejectAction.java
index d75350b..eca6337 100644
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/RejectAction.java
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/RejectAction.java
@@ -29,6 +29,7 @@ import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import org.apache.james.core.MailAddress;
+import org.apache.james.lifecycle.api.LifecycleUtil;
import org.apache.james.mdn.MDN;
import org.apache.james.mdn.MDNReport;
import org.apache.james.mdn.action.mode.DispositionActionMode;
@@ -137,14 +138,19 @@ public class RejectAction implements MailAction {
reply.saveChanges();
Address[] recipientAddresses = reply.getAllRecipients();
if (recipientAddresses != null) {
- context.post(MailImpl.builder()
+ MailImpl mail = MailImpl.builder()
.name(MailImpl.getId())
.addRecipients(Arrays.stream(recipientAddresses)
.map(address -> (InternetAddress) address)
.map(Throwing.function(MailAddress::new))
.collect(ImmutableList.toImmutableList()))
.mimeMessage(reply)
- .build());
+ .build();
+ try {
+ context.post(mail);
+ } finally {
+ LifecycleUtil.dispose(mail);
+ }
} else {
LOGGER.info("Unable to send reject MDN. Could not determine the recipient.");
}
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/VacationAction.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/VacationAction.java
index 10eab29..bef3040 100644
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/VacationAction.java
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/jsieve/VacationAction.java
@@ -28,6 +28,7 @@ import javax.mail.MessagingException;
import javax.mail.internet.AddressException;
import org.apache.james.core.MailAddress;
+import org.apache.james.lifecycle.api.LifecycleUtil;
import org.apache.james.server.core.MailImpl;
import org.apache.jsieve.mail.Action;
import org.apache.jsieve.mail.optional.ActionVacation;
@@ -66,12 +67,17 @@ public class VacationAction implements MailAction {
.subject(actionVacation.getSubject())
.build();
- context.post(MailImpl.builder()
+ MailImpl replyMail = MailImpl.builder()
.name(MailImpl.getId())
.sender(vacationReply.getSender())
.addRecipients(vacationReply.getRecipients())
.mimeMessage(vacationReply.getMimeMessage())
- .build());
+ .build();
+ try {
+ context.post(replyMail);
+ } finally {
+ LifecycleUtil.dispose(replyMail);
+ }
}
private boolean isStillInVacation(ActionVacation actionVacation, int dayDifference) {
diff --git a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/managesieve/ManageSieveMailet.java b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/managesieve/ManageSieveMailet.java
index 8225a8a..e1c6013 100644
--- a/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/managesieve/ManageSieveMailet.java
+++ b/server/mailet/mailets/src/main/java/org/apache/james/transport/mailets/managesieve/ManageSieveMailet.java
@@ -24,6 +24,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
+import java.nio.charset.StandardCharsets;
import java.util.Scanner;
import javax.inject.Inject;
@@ -115,7 +116,7 @@ public class ManageSieveMailet extends GenericMailet implements MessageToCoreToM
setHelpURL(getInitParameter("helpURL"));
cache = getInitParameter("cache", true);
transcoder = new MessageToCoreToMessage(new ManageSieveProcessor(
- new ArgumentParser(new CoreProcessor(sieveRepository, usersRepository, sieveParser))),
+ new ArgumentParser(new CoreProcessor(sieveRepository, usersRepository, sieveParser), false)),
this);
}
@@ -197,7 +198,7 @@ public class ManageSieveMailet extends GenericMailet implements MessageToCoreToM
Scanner scanner = null;
try {
stream = helpURL.openStream();
- scanner = new Scanner(stream, "UTF-8");
+ scanner = new Scanner(stream, StandardCharsets.UTF_8);
return scanner.useDelimiter("\\A").next();
} catch (IOException ex) {
throw new MessagingException("Unable to access help URL: " + helpURL.toExternalForm(), ex);
diff --git a/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ChannelManageSieveResponseWriter.java b/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ChannelManageSieveResponseWriter.java
index 97b579b..d131efb 100644
--- a/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ChannelManageSieveResponseWriter.java
+++ b/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ChannelManageSieveResponseWriter.java
@@ -20,24 +20,53 @@
package org.apache.james.managesieveserver.netty;
import java.io.ByteArrayInputStream;
-import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
+import org.apache.james.protocols.api.CommandDetectionSession;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.handler.stream.ChunkedStream;
-public class ChannelManageSieveResponseWriter {
+public class ChannelManageSieveResponseWriter implements CommandDetectionSession {
private final Channel channel;
+ private String cumulation = null;
public ChannelManageSieveResponseWriter(Channel channel) {
this.channel = channel;
}
- public void write(String response) throws IOException {
+ public void write(String response) {
if (channel.isConnected()) {
InputStream in = new ByteArrayInputStream(response.getBytes(StandardCharsets.UTF_8));
channel.write(new ChunkedStream(in));
}
}
+
+ @Override
+ public boolean needsCommandInjectionDetection() {
+ return false;
+ }
+
+ @Override
+ public void startDetectingCommandInjection() {
+
+ }
+
+ @Override
+ public void stopDetectingCommandInjection() {
+
+ }
+
+ public void resetCumulation() {
+ cumulation = null;
+ }
+
+ public String cumulate(String s) {
+ if (cumulation == null || cumulation.equals("\r\n")) {
+ cumulation = s;
+ } else {
+ cumulation += s;
+ }
+ return cumulation;
+ }
}
diff --git a/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ManageSieveChannelUpstreamHandler.java b/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ManageSieveChannelUpstreamHandler.java
index bb7963a..3274b9b 100644
--- a/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ManageSieveChannelUpstreamHandler.java
+++ b/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ManageSieveChannelUpstreamHandler.java
@@ -27,6 +27,7 @@ import javax.net.ssl.SSLContext;
import org.apache.james.managesieve.api.Session;
import org.apache.james.managesieve.api.SessionTerminatedException;
import org.apache.james.managesieve.transcode.ManageSieveProcessor;
+import org.apache.james.managesieve.transcode.NotEnoughDataException;
import org.apache.james.managesieve.util.SettableSession;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
@@ -64,16 +65,24 @@ public class ManageSieveChannelUpstreamHandler extends SimpleChannelUpstreamHand
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
+ ChannelManageSieveResponseWriter attachment = (ChannelManageSieveResponseWriter) ctx.getAttachment();
try (Closeable closeable = ManageSieveMDCContext.from(ctx, attributes)) {
- String request = (String) e.getMessage();
+ String request = attachment.cumulate((String) e.getMessage());
+ if (request.isEmpty() || request.startsWith("\r\n")) {
+ return;
+ }
+
Session manageSieveSession = attributes.get(ctx.getChannel());
String responseString = manageSieveProcessor.handleRequest(manageSieveSession, request);
- ((ChannelManageSieveResponseWriter) ctx.getAttachment()).write(responseString);
+ attachment.resetCumulation();
+ attachment.write(responseString);
if (manageSieveSession.getState() == Session.State.SSL_NEGOCIATION) {
turnSSLon(ctx.getChannel());
manageSieveSession.setSslEnabled(true);
manageSieveSession.setState(Session.State.UNAUTHENTICATED);
}
+ } catch (NotEnoughDataException ex) {
+ // Do nothing will keep the cumulation
}
}
@@ -116,7 +125,7 @@ public class ManageSieveChannelUpstreamHandler extends SimpleChannelUpstreamHand
attributes.set(ctx.getChannel(), session);
ctx.setAttachment(new ChannelManageSieveResponseWriter(ctx.getChannel()));
super.channelBound(ctx, e);
- ((ChannelManageSieveResponseWriter) ctx.getAttachment()).write(manageSieveProcessor.getAdvertisedCapabilities());
+ ((ChannelManageSieveResponseWriter) ctx.getAttachment()).write(manageSieveProcessor.getAdvertisedCapabilities() + "OK\r\n");
}
}
diff --git a/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ManageSieveMDCContext.java b/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ManageSieveMDCContext.java
index 52727c1..2e44aa2 100644
--- a/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ManageSieveMDCContext.java
+++ b/server/protocols/protocols-managesieve/src/main/java/org/apache/james/managesieveserver/netty/ManageSieveMDCContext.java
@@ -24,6 +24,7 @@ import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.Optional;
+import org.apache.james.core.Username;
import org.apache.james.managesieve.api.Session;
import org.apache.james.util.MDCBuilder;
import org.jboss.netty.channel.ChannelHandlerContext;
@@ -61,7 +62,8 @@ public class ManageSieveMDCContext {
private static MDCBuilder from(Session session) {
return Optional.ofNullable(session)
.map(s -> MDCBuilder.create()
- .addToContext(MDCBuilder.USER, s.getUser().asString()))
+ .addToContextIfPresent(MDCBuilder.USER, Optional.ofNullable(s.getUser())
+ .map(Username::asString)))
.orElse(MDCBuilder.create());
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org