diff --git a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultSettingsBuilder.java b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultSettingsBuilder.java index 76695f4b1f53..be7dd9e86312 100644 --- a/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultSettingsBuilder.java +++ b/impl/maven-impl/src/main/java/org/apache/maven/impl/DefaultSettingsBuilder.java @@ -268,6 +268,22 @@ private Settings decrypt( UnaryOperator decryptFunction = str -> { if (str != null && !str.isEmpty() && !str.contains("${") && secDispatcher.isAnyEncryptedString(str)) { if (secDispatcher.isLegacyEncryptedString(str)) { + // the call above return true for too broad types of strings, original idea with 2.x sec-dispatcher + // was to make it possible to add "descriptions" to encrypted passwords. Maven 4 is + // limiting itself to decryption of ONLY the simplest cases of legacy passwords, those having form + // as documented on page: https://maven.apache.org/guides/mini/guide-encryption.html + // Examples of decrypted legacy passwords: + // {COQLCE6DU6GtcS5P=} + // Oleg reset this password on 2009-03-11 {COQLCE6DU6GtcS5P=} + + // In short, secDispatcher#isLegacyEncryptedString(str) did return true, but we apply more scrutiny + // and check does string start with "{" or contains " {" (whitespace before opening curly braces), + // and that it ends with "}" strictly. Otherwise, we refuse it. + if ((!str.startsWith("{") && !str.contains(" {")) || !str.endsWith("}")) { + // this is not a legacy password we care for + return str; + } + // add a problem preMaven4Passwords.incrementAndGet(); } diff --git a/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITgh10210SettingsXmlDecryptTest.java b/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITgh10210SettingsXmlDecryptTest.java new file mode 100644 index 000000000000..8742ff9388b6 --- /dev/null +++ b/its/core-it-suite/src/test/java/org/apache/maven/it/MavenITgh10210SettingsXmlDecryptTest.java @@ -0,0 +1,78 @@ +/* + * 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.maven.it; + +import java.io.File; +import java.nio.file.Files; +import java.util.Arrays; + +import org.junit.Assert; +import org.junit.jupiter.api.Test; + +/** + * This is a test set for GH-10210. + */ +class MavenITgh10210SettingsXmlDecryptTest extends AbstractMavenIntegrationTestCase { + + MavenITgh10210SettingsXmlDecryptTest() { + super("(4.0.0-rc4,)"); // fixed post 4.0.0-rc-4 + } + + @Test + void testItPass() throws Exception { + File testDir = extractResources("/gh-10210-settings-xml-decrypt"); + + Verifier verifier = new Verifier(testDir.getAbsolutePath()); + verifier.setUserHomeDirectory(testDir.toPath().resolve("HOME")); + verifier.addCliArgument("-s"); + verifier.addCliArgument("settings-passes.xml"); + verifier.addCliArgument("process-resources"); + verifier.execute(); + + Assert.assertEquals( + Arrays.asList( + "prop1=%{foo}.txt", + "prop2=${foo}.txt", + "prop3=whatever {foo}.txt", + "prop4=whatever", + "prop5=Hello Oleg {L6L/HbmrY+cH+sNkphnq3fguYepTpM04WlIXb8nB1pk=} is this a password?", + "prop6=password", + "prop7=password"), + Files.readAllLines(testDir.toPath().resolve("target/classes/file.properties"))); + } + + @Test + void testItFail() throws Exception { + File testDir = extractResources("/gh-10210-settings-xml-decrypt"); + + Verifier verifier = new Verifier(testDir.getAbsolutePath()); + verifier.setUserHomeDirectory(testDir.toPath().resolve("HOME")); + verifier.addCliArgument("-s"); + verifier.addCliArgument("settings-fails.xml"); + verifier.addCliArgument("process-resources"); + try { + verifier.execute(); + } catch (VerificationException e) { + Assert.assertTrue( + verifier.loadLogContent() + .contains( + "Could not decrypt password (fix the corrupted password or remove it, if unused) {L6L/HbmrY+cH+sNkphn-this password is corrupted intentionally-q3fguYepTpM04WlIXb8nB1pk=}")); + } + } +} diff --git a/its/core-it-suite/src/test/java/org/apache/maven/it/TestSuiteOrdering.java b/its/core-it-suite/src/test/java/org/apache/maven/it/TestSuiteOrdering.java index cc0ee65b997e..207595094a1b 100644 --- a/its/core-it-suite/src/test/java/org/apache/maven/it/TestSuiteOrdering.java +++ b/its/core-it-suite/src/test/java/org/apache/maven/it/TestSuiteOrdering.java @@ -105,6 +105,7 @@ public TestSuiteOrdering() { */ suite.addTestSuite(MavenITgh11055DIServiceInjectionTest.class); suite.addTestSuite(MavenITgh11084ReactorReaderPreferConsumerPomTest.class); + suite.addTestSuite(MavenITgh10210SettingsXmlDecryptTest.class); suite.addTestSuite(MavenITgh10312TerminallyDeprecatedMethodInGuiceTest.class); suite.addTestSuite(MavenITgh10937QuotedPipesInMavenOptsTest.class); suite.addTestSuite(MavenITgh2532DuplicateDependencyEffectiveModelTest.class); diff --git a/its/core-it-suite/src/test/resources/gh-10210-settings-xml-decrypt/HOME/.m2/settings-security.xml b/its/core-it-suite/src/test/resources/gh-10210-settings-xml-decrypt/HOME/.m2/settings-security.xml new file mode 100644 index 000000000000..f88e932cf871 --- /dev/null +++ b/its/core-it-suite/src/test/resources/gh-10210-settings-xml-decrypt/HOME/.m2/settings-security.xml @@ -0,0 +1,3 @@ + + {KDvsYOFLlXgH4LU8tvpzAGg5otiosZXvfdQq0yO86LU=} + \ No newline at end of file diff --git a/its/core-it-suite/src/test/resources/gh-10210-settings-xml-decrypt/pom.xml b/its/core-it-suite/src/test/resources/gh-10210-settings-xml-decrypt/pom.xml new file mode 100644 index 000000000000..d6c72b24a42c --- /dev/null +++ b/its/core-it-suite/src/test/resources/gh-10210-settings-xml-decrypt/pom.xml @@ -0,0 +1,40 @@ + + + + 4.0.0 + + org.apache.maven.its.gh-10210 + test + 1.0 + jar + + Maven Integration Test :: gh-10210 + Empty POM, as settings.xml decrypt failure will fail the build anyway. + + + + + true + src/main/resources + + + + + diff --git a/its/core-it-suite/src/test/resources/gh-10210-settings-xml-decrypt/settings-fails.xml b/its/core-it-suite/src/test/resources/gh-10210-settings-xml-decrypt/settings-fails.xml new file mode 100644 index 000000000000..dd3f44f0e904 --- /dev/null +++ b/its/core-it-suite/src/test/resources/gh-10210-settings-xml-decrypt/settings-fails.xml @@ -0,0 +1,42 @@ + + + + + + + + just-some-random-profile + + + %{foo}.txt + ${foo}.txt + whatever {foo}.txt + whatever + Hello Oleg {L6L/HbmrY+cH+sNkphnq3fguYepTpM04WlIXb8nB1pk=} is this a password? + + {L6L/HbmrY+cH+sNkphn-this password is corrupted intentionally-q3fguYepTpM04WlIXb8nB1pk=} + Hello Oleg {L6L/HbmrY+cH+sNkphnq3fguYepTpM04WlIXb8nB1pk=} + + + + + just-some-random-profile + + diff --git a/its/core-it-suite/src/test/resources/gh-10210-settings-xml-decrypt/settings-passes.xml b/its/core-it-suite/src/test/resources/gh-10210-settings-xml-decrypt/settings-passes.xml new file mode 100644 index 000000000000..dcfb8e5c5129 --- /dev/null +++ b/its/core-it-suite/src/test/resources/gh-10210-settings-xml-decrypt/settings-passes.xml @@ -0,0 +1,42 @@ + + + + + + + + just-some-random-profile + + + %{foo}.txt + ${foo}.txt + whatever {foo}.txt + whatever + Hello Oleg {L6L/HbmrY+cH+sNkphnq3fguYepTpM04WlIXb8nB1pk=} is this a password? + + {L6L/HbmrY+cH+sNkphnq3fguYepTpM04WlIXb8nB1pk=} + Hello Oleg {L6L/HbmrY+cH+sNkphnq3fguYepTpM04WlIXb8nB1pk=} + + + + + just-some-random-profile + + diff --git a/its/core-it-suite/src/test/resources/gh-10210-settings-xml-decrypt/src/main/resources/file.properties b/its/core-it-suite/src/test/resources/gh-10210-settings-xml-decrypt/src/main/resources/file.properties new file mode 100644 index 000000000000..0ccd6e3c49c9 --- /dev/null +++ b/its/core-it-suite/src/test/resources/gh-10210-settings-xml-decrypt/src/main/resources/file.properties @@ -0,0 +1,7 @@ +prop1=${prop1} +prop2=${prop2} +prop3=${prop3} +prop4=${prop4} +prop5=${prop5} +prop6=${prop6} +prop7=${prop7}