diff --git a/src/main/java/hudson/tasks/SMTPAuthentication.java b/src/main/java/hudson/tasks/SMTPAuthentication.java
index da921c42..c8f6010a 100644
--- a/src/main/java/hudson/tasks/SMTPAuthentication.java
+++ b/src/main/java/hudson/tasks/SMTPAuthentication.java
@@ -3,9 +3,15 @@
import hudson.Extension;
import hudson.model.AbstractDescribableImpl;
import hudson.model.Descriptor;
+import hudson.util.FormValidation;
import hudson.util.Secret;
+import jenkins.security.FIPS140;
import org.kohsuke.stapler.DataBoundConstructor;
import hudson.Util;
+import org.kohsuke.stapler.QueryParameter;
+import org.kohsuke.stapler.interceptor.RequirePOST;
+
+import java.io.ObjectStreamException;
/**
* @author Nicolas De Loof
@@ -20,6 +26,9 @@ public class SMTPAuthentication extends AbstractDescribableImpl {
@@ -37,5 +53,13 @@ public static class DescriptorImpl extends Descriptor {
public String getDisplayName() {
return "Use SMTP Authentication";
}
+
+ @RequirePOST
+ public FormValidation doCheckPassword(@QueryParameter Secret password) {
+ if (FIPS140.useCompliantAlgorithms() && Secret.toString(password).length() < 14) {
+ return FormValidation.error(jenkins.plugins.mailer.tasks.i18n.Messages.Mailer_SmtpPassNotFipsCompliant());
+ }
+ return FormValidation.ok();
+ }
}
}
diff --git a/src/main/resources/jenkins/plugins/mailer/tasks/i18n/Messages.properties b/src/main/resources/jenkins/plugins/mailer/tasks/i18n/Messages.properties
index ad728e9a..5a9fe43d 100644
--- a/src/main/resources/jenkins/plugins/mailer/tasks/i18n/Messages.properties
+++ b/src/main/resources/jenkins/plugins/mailer/tasks/i18n/Messages.properties
@@ -49,6 +49,6 @@ Mailer.TestMail.Subject=Test email #{0}
Mailer.TestMail.Content=This is test email #{0} sent from {1}
Mailer.InsecureAuthWarning=For security when using authentication it is recommended to enable either TLS or SSL
Mailer.InsecureAuthError=Authentication requires either TLS or SSL to be enabled
-
+Mailer.SmtpPassNotFipsCompliant=When running in FIPS compliance mode, the password must be at least 14 characters long
MailCommand.ShortDescription=\
Reads stdin and sends that out as an e-mail.
diff --git a/src/test/java/jenkins/plugins/mailer/FipsModeTest.java b/src/test/java/jenkins/plugins/mailer/FipsModeTest.java
new file mode 100644
index 00000000..c6f92504
--- /dev/null
+++ b/src/test/java/jenkins/plugins/mailer/FipsModeTest.java
@@ -0,0 +1,108 @@
+package jenkins.plugins.mailer;
+
+import hudson.ExtensionList;
+import hudson.diagnosis.OldDataMonitor;
+import hudson.tasks.Mailer;
+import io.jenkins.plugins.casc.ConfigurationAsCode;
+import io.jenkins.plugins.casc.ConfiguratorException;
+import org.htmlunit.WebResponse;
+import org.htmlunit.html.HtmlForm;
+import org.htmlunit.html.HtmlPage;
+import org.junit.Assume;
+import org.junit.Rule;
+import org.junit.Test;
+import org.jvnet.hudson.test.JenkinsRule;
+import org.jvnet.hudson.test.RealJenkinsRule;
+import org.jvnet.hudson.test.recipes.LocalData;
+import org.xml.sax.SAXException;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.net.URL;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.nullValue;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+public class FipsModeTest {
+ public static final String SHORT_PWD_ERROR_MESSAGE = "When running in FIPS compliance mode, the password must be at least 14 characters long";
+ @Rule
+ public RealJenkinsRule r = new RealJenkinsRule().javaOptions("-Djenkins.security.FIPS140.COMPLIANCE=true").withDebugPort(5008);
+
+ @Test @LocalData
+ public void testBlowsUpOnStart() throws Throwable {
+ r.then(FipsModeTest::verifyOldData);
+ }
+
+ static void verifyOldData(JenkinsRule j) throws Throwable {
+ OldDataMonitor monitor = ExtensionList.lookupSingleton(OldDataMonitor.class);
+ Mailer.DescriptorImpl descriptor = Mailer.descriptor();
+ assertNull(descriptor.getAuthentication());
+ OldDataMonitor.VersionRange versionRange = monitor.getData().get(descriptor);
+ assertNotNull(versionRange);
+ assertThat(versionRange.extra, containsString("Mailer SMTP password: " + SHORT_PWD_ERROR_MESSAGE));
+ }
+
+ @Test
+ public void testConfig() throws Throwable {
+ r.then(FipsModeTest::_testConfig);
+ }
+
+ public static void _testConfig(JenkinsRule j) throws Exception {
+ Assume.assumeThat("TODO the form elements for email-ext have the same names", j.getPluginManager().getPlugin("email-ext"), is(nullValue()));
+ try (JenkinsRule.WebClient wc = j.createWebClient()) {
+ HtmlPage cp = wc.goTo("configure");
+ wc.setThrowExceptionOnFailingStatusCode(false);
+ HtmlForm form = cp.getFormByName("config");
+
+ form.getInputByName("_.smtpHost").setValue("acme.com");
+ form.getInputByName("_.defaultSuffix").setValue("@acme.com");
+ form.getInputByName("_.authentication").setChecked(true);
+ form.getInputByName("_.username").setValue("user");
+ form.getInputByName("_.password").setValue("pass");
+ wc.waitForBackgroundJavaScript(1000);
+ assertThat(form.getTextContent(), containsString(SHORT_PWD_ERROR_MESSAGE));
+ HtmlPage page = j.submit(form);
+ WebResponse webResponse = page.getWebResponse();
+ assertNotEquals(200, webResponse.getStatusCode());
+ assertThat(webResponse.getContentAsString(), containsString(SHORT_PWD_ERROR_MESSAGE));
+ }
+
+ }
+
+ @Test @LocalData
+ public void casc() throws Throwable {
+ URL url = getClass().getResource("bad_fips_casc.yaml");
+ r.then(new _casc(url.toString()));
+ }
+
+ public static class _casc implements RealJenkinsRule.Step2 {
+ String resUrl;
+
+ public _casc(String resUrl) {
+ this.resUrl = resUrl;
+ }
+
+ @Override
+ public Serializable run(JenkinsRule r) throws Throwable {
+ try {
+ ConfigurationAsCode.get().configure(resUrl);
+ fail("The configuration should fail.");
+ } catch (ConfiguratorException e) {
+ Throwable cause = e.getCause();
+ assertNotNull(cause);
+ cause = cause.getCause();
+ assertThat(cause, instanceOf(IllegalArgumentException.class));
+ assertThat(cause.getMessage(), containsString(SHORT_PWD_ERROR_MESSAGE));
+ }
+ return null;
+ }
+ }
+
+}
diff --git a/src/test/resources/jenkins/plugins/mailer/FipsModeTest/casc/secrets/hudson.util.Secret b/src/test/resources/jenkins/plugins/mailer/FipsModeTest/casc/secrets/hudson.util.Secret
new file mode 100644
index 00000000..c9e4e308
--- /dev/null
+++ b/src/test/resources/jenkins/plugins/mailer/FipsModeTest/casc/secrets/hudson.util.Secret
@@ -0,0 +1,2 @@
+Ħ5uM3|Mn+^E;jy;qJKMJ- mKE`wTȴyMG^,m
+(gr,T̉028WN2
rDiE}sa=<0 C]S~0TQl2|@ּr&[Q_]殣Kv`]ҋr0XnS=
uOOdbזo(Z7㘎>0`|j&C
\ No newline at end of file
diff --git a/src/test/resources/jenkins/plugins/mailer/FipsModeTest/casc/secrets/jenkins.model.Jenkins.crumbSalt b/src/test/resources/jenkins/plugins/mailer/FipsModeTest/casc/secrets/jenkins.model.Jenkins.crumbSalt
new file mode 100644
index 00000000..f05abb66
--- /dev/null
+++ b/src/test/resources/jenkins/plugins/mailer/FipsModeTest/casc/secrets/jenkins.model.Jenkins.crumbSalt
@@ -0,0 +1,2 @@
+8eJVWO2
t.˿u=
+
\ No newline at end of file
diff --git a/src/test/resources/jenkins/plugins/mailer/FipsModeTest/casc/secrets/master.key b/src/test/resources/jenkins/plugins/mailer/FipsModeTest/casc/secrets/master.key
new file mode 100644
index 00000000..2f2aab79
--- /dev/null
+++ b/src/test/resources/jenkins/plugins/mailer/FipsModeTest/casc/secrets/master.key
@@ -0,0 +1 @@
+98e782a367e04fbffad76f28cc32eb0b7757ff91bd31656cdbcc42a0acf3b92f925b0abf9fbbbd51e7d79bace99d182bb4b337a485b519a73e9089c3e6a78184aeb514731bbb578c205879187411f7e8f709f183c5fdf098155ef56362636c4a5762aa831b6d5d82deb1adfc7f306139e6d480093f639484ecb3f9143bc56097
\ No newline at end of file
diff --git a/src/test/resources/jenkins/plugins/mailer/FipsModeTest/casc/secrets/org.jenkinsci.main.modules.instance_identity.InstanceIdentity.KEY b/src/test/resources/jenkins/plugins/mailer/FipsModeTest/casc/secrets/org.jenkinsci.main.modules.instance_identity.InstanceIdentity.KEY
new file mode 100644
index 00000000..d8614fd3
Binary files /dev/null and b/src/test/resources/jenkins/plugins/mailer/FipsModeTest/casc/secrets/org.jenkinsci.main.modules.instance_identity.InstanceIdentity.KEY differ
diff --git a/src/test/resources/jenkins/plugins/mailer/FipsModeTest/testBlowsUpOnStart/hudson.tasks.Mailer.xml b/src/test/resources/jenkins/plugins/mailer/FipsModeTest/testBlowsUpOnStart/hudson.tasks.Mailer.xml
new file mode 100644
index 00000000..a2fb6fbf
--- /dev/null
+++ b/src/test/resources/jenkins/plugins/mailer/FipsModeTest/testBlowsUpOnStart/hudson.tasks.Mailer.xml
@@ -0,0 +1,11 @@
+
+
+
+
+ smtpusr
+ {AQAAABAAAAAQcrlS6VKIiJEH44B7K+oxdcs0j4LcZbicOnwQK0Ivlfg=}
+
+ true
+ false
+ UTF-8
+
\ No newline at end of file
diff --git a/src/test/resources/jenkins/plugins/mailer/FipsModeTest/testBlowsUpOnStart/jenkins.model.JenkinsLocationConfiguration.xml b/src/test/resources/jenkins/plugins/mailer/FipsModeTest/testBlowsUpOnStart/jenkins.model.JenkinsLocationConfiguration.xml
new file mode 100644
index 00000000..bae8aa3c
--- /dev/null
+++ b/src/test/resources/jenkins/plugins/mailer/FipsModeTest/testBlowsUpOnStart/jenkins.model.JenkinsLocationConfiguration.xml
@@ -0,0 +1,5 @@
+
+
+ address not configured yet <nobody@nowhere>
+ http://localhost:8080/jenkins/
+
\ No newline at end of file
diff --git a/src/test/resources/jenkins/plugins/mailer/FipsModeTest/testBlowsUpOnStart/secrets/hudson.util.Secret b/src/test/resources/jenkins/plugins/mailer/FipsModeTest/testBlowsUpOnStart/secrets/hudson.util.Secret
new file mode 100644
index 00000000..c9e4e308
--- /dev/null
+++ b/src/test/resources/jenkins/plugins/mailer/FipsModeTest/testBlowsUpOnStart/secrets/hudson.util.Secret
@@ -0,0 +1,2 @@
+Ħ5uM3|Mn+^E;jy;qJKMJ- mKE`wTȴyMG^,m
+(gr,T̉028WN2
rDiE}sa=<0 C]S~0TQl2|@ּr&[Q_]殣Kv`]ҋr0XnS=
uOOdbזo(Z7㘎>0`|j&C
\ No newline at end of file
diff --git a/src/test/resources/jenkins/plugins/mailer/FipsModeTest/testBlowsUpOnStart/secrets/jenkins.model.Jenkins.crumbSalt b/src/test/resources/jenkins/plugins/mailer/FipsModeTest/testBlowsUpOnStart/secrets/jenkins.model.Jenkins.crumbSalt
new file mode 100644
index 00000000..f05abb66
--- /dev/null
+++ b/src/test/resources/jenkins/plugins/mailer/FipsModeTest/testBlowsUpOnStart/secrets/jenkins.model.Jenkins.crumbSalt
@@ -0,0 +1,2 @@
+8eJVWO2
t.˿u=
+
\ No newline at end of file
diff --git a/src/test/resources/jenkins/plugins/mailer/FipsModeTest/testBlowsUpOnStart/secrets/master.key b/src/test/resources/jenkins/plugins/mailer/FipsModeTest/testBlowsUpOnStart/secrets/master.key
new file mode 100644
index 00000000..2f2aab79
--- /dev/null
+++ b/src/test/resources/jenkins/plugins/mailer/FipsModeTest/testBlowsUpOnStart/secrets/master.key
@@ -0,0 +1 @@
+98e782a367e04fbffad76f28cc32eb0b7757ff91bd31656cdbcc42a0acf3b92f925b0abf9fbbbd51e7d79bace99d182bb4b337a485b519a73e9089c3e6a78184aeb514731bbb578c205879187411f7e8f709f183c5fdf098155ef56362636c4a5762aa831b6d5d82deb1adfc7f306139e6d480093f639484ecb3f9143bc56097
\ No newline at end of file
diff --git a/src/test/resources/jenkins/plugins/mailer/FipsModeTest/testBlowsUpOnStart/secrets/org.jenkinsci.main.modules.instance_identity.InstanceIdentity.KEY b/src/test/resources/jenkins/plugins/mailer/FipsModeTest/testBlowsUpOnStart/secrets/org.jenkinsci.main.modules.instance_identity.InstanceIdentity.KEY
new file mode 100644
index 00000000..d8614fd3
Binary files /dev/null and b/src/test/resources/jenkins/plugins/mailer/FipsModeTest/testBlowsUpOnStart/secrets/org.jenkinsci.main.modules.instance_identity.InstanceIdentity.KEY differ
diff --git a/src/test/resources/jenkins/plugins/mailer/bad_fips_casc.yaml b/src/test/resources/jenkins/plugins/mailer/bad_fips_casc.yaml
new file mode 100644
index 00000000..e1b06d2e
--- /dev/null
+++ b/src/test/resources/jenkins/plugins/mailer/bad_fips_casc.yaml
@@ -0,0 +1,8 @@
+unclassified:
+ mailer:
+ authentication:
+ password: "{AQAAABAAAAAQcrlS6VKIiJEH44B7K+oxdcs0j4LcZbicOnwQK0Ivlfg=}"
+ username: "smtpusr"
+ charset: "UTF-8"
+ useSsl: true
+ useTls: false
\ No newline at end of file