diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/OutOfBand01Challenge.java b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/OutOfBand01Challenge.java deleted file mode 100644 index 498c16fd..00000000 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/OutOfBand01Challenge.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * acme4j - Java ACME client - * - * Copyright (C) 2016 Richard "Shred" Körber - * http://acme4j.shredzone.org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.shredzone.acme4j.challenge; - -import java.net.URL; - -import org.shredzone.acme4j.Session; - -/** - * Implements the {@value TYPE} challenge. - * - * @deprecated This challenge has been removed from the ACMEv2 specs. - */ -@Deprecated -public class OutOfBand01Challenge extends Challenge { - private static final long serialVersionUID = -7459595198486630582L; - - /** - * Challenge type name: {@value} - */ - public static final String TYPE = "oob-01"; - - /** - * Creates a new generic {@link OutOfBand01Challenge} object. - * - * @param session - * {@link Session} to bind to. - */ - public OutOfBand01Challenge(Session session) { - super(session); - } - - /** - * Returns the validation URL to be visited by the customer in order to complete the - * challenge. - */ - public URL getValidationUrl() { - return getJSON().get("href").asURL(); - } - -} diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TlsSni01Challenge.java b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TlsSni01Challenge.java deleted file mode 100644 index a4c18a47..00000000 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TlsSni01Challenge.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * acme4j - Java ACME client - * - * Copyright (C) 2015 Richard "Shred" Körber - * http://acme4j.shredzone.org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.shredzone.acme4j.challenge; - -import static org.shredzone.acme4j.toolbox.AcmeUtils.*; - -import org.shredzone.acme4j.Session; - -/** - * Implements the {@value TYPE} challenge. - * - * @deprecated This challenge is vulnerable and will be removed from the ACME specs. Do - * not use! Let's Encrypt does not offer this challenge to the general public - * any more. - */ -@Deprecated -public class TlsSni01Challenge extends TokenChallenge { - private static final long serialVersionUID = 7370329525205430573L; - - /** - * Challenge type name: {@value} - */ - public static final String TYPE = "tls-sni-01"; - - private String subject; - - /** - * Creates a new generic {@link TlsSni01Challenge} object. - * - * @param session - * {@link Session} to bind to. - */ - public TlsSni01Challenge(Session session) { - super(session); - } - - /** - * Return the subject to generate a self-signed certificate for. - */ - public String getSubject() { - return subject; - } - - @Override - protected boolean acceptable(String type) { - return TYPE.equals(type); - } - - @Override - protected void authorize() { - super.authorize(); - - String hash = hexEncode(sha256hash(getAuthorization())); - subject = hash.substring(0, 32) + '.' + hash.substring(32) + ".acme.invalid"; - } - -} diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TlsSni02Challenge.java b/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TlsSni02Challenge.java deleted file mode 100644 index cd8d21c9..00000000 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/challenge/TlsSni02Challenge.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * acme4j - Java ACME client - * - * Copyright (C) 2016 Richard "Shred" Körber - * http://acme4j.shredzone.org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.shredzone.acme4j.challenge; - -import static org.shredzone.acme4j.toolbox.AcmeUtils.*; - -import org.shredzone.acme4j.Session; - -/** - * Implements the {@value TYPE} challenge. - * - * @deprecated This challenge is vulnerable and will be removed from the ACME specs. Do - * not use! - */ -@Deprecated -public class TlsSni02Challenge extends TokenChallenge { - private static final long serialVersionUID = 8921833167878544518L; - - /** - * Challenge type name: {@value} - */ - public static final String TYPE = "tls-sni-02"; - - private String subject; - private String sanB; - - /** - * Creates a new generic {@link TlsSni02Challenge} object. - * - * @param session - * {@link Session} to bind to. - */ - public TlsSni02Challenge(Session session) { - super(session); - } - - /** - * Returns the subject, which is to be used as "SAN-A" in a self-signed certificate. - * The CA will send the SNI request against this domain. - */ - public String getSubject() { - return subject; - } - - /** - * Returns the key authorization, which is to be used as "SAN-B" in a self-signed - * certificate. - */ - public String getSanB() { - return sanB; - } - - @Override - protected boolean acceptable(String type) { - return TYPE.equals(type); - } - - @Override - protected void authorize() { - super.authorize(); - - String tokenHash = hexEncode(sha256hash(getToken())); - subject = tokenHash.substring(0, 32) + '.' + tokenHash.substring(32) + ".token.acme.invalid"; - - String kaHash = hexEncode(sha256hash(getAuthorization())); - sanB = kaHash.substring(0, 32) + '.' + kaHash.substring(32) + ".ka.acme.invalid"; - } - -} diff --git a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/AbstractAcmeProvider.java b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/AbstractAcmeProvider.java index 79ba2a8e..df4e1b53 100644 --- a/acme4j-client/src/main/java/org/shredzone/acme4j/provider/AbstractAcmeProvider.java +++ b/acme4j-client/src/main/java/org/shredzone/acme4j/provider/AbstractAcmeProvider.java @@ -25,9 +25,6 @@ import org.shredzone.acme4j.Session; import org.shredzone.acme4j.challenge.Challenge; import org.shredzone.acme4j.challenge.Dns01Challenge; import org.shredzone.acme4j.challenge.Http01Challenge; -import org.shredzone.acme4j.challenge.OutOfBand01Challenge; -import org.shredzone.acme4j.challenge.TlsSni01Challenge; -import org.shredzone.acme4j.challenge.TlsSni02Challenge; import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.connector.DefaultConnection; import org.shredzone.acme4j.connector.HttpConnector; @@ -41,7 +38,6 @@ import org.shredzone.acme4j.toolbox.JSON; * Implementing classes must implement at least {@link AcmeProvider#accepts(URI)} * and {@link AbstractAcmeProvider#resolve(URI)}. */ -@SuppressWarnings("deprecation") public abstract class AbstractAcmeProvider implements AcmeProvider { private static final Map> CHALLENGES = challengeMap(); @@ -68,10 +64,7 @@ public abstract class AbstractAcmeProvider implements AcmeProvider { Map> map = new HashMap<>(); map.put(Dns01Challenge.TYPE, Dns01Challenge::new); - map.put(TlsSni01Challenge.TYPE, TlsSni01Challenge::new); - map.put(TlsSni02Challenge.TYPE, TlsSni02Challenge::new); map.put(Http01Challenge.TYPE, Http01Challenge::new); - map.put(OutOfBand01Challenge.TYPE, OutOfBand01Challenge::new); return Collections.unmodifiableMap(map); } diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/AuthorizationTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/AuthorizationTest.java index 8bfee1e7..1f218a11 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/AuthorizationTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/AuthorizationTest.java @@ -30,7 +30,6 @@ import org.junit.Test; import org.shredzone.acme4j.challenge.Challenge; import org.shredzone.acme4j.challenge.Dns01Challenge; import org.shredzone.acme4j.challenge.Http01Challenge; -import org.shredzone.acme4j.challenge.TlsSni02Challenge; import org.shredzone.acme4j.exception.AcmeException; import org.shredzone.acme4j.exception.AcmeRetryAfterException; import org.shredzone.acme4j.provider.TestableConnectionProvider; @@ -40,7 +39,6 @@ import org.shredzone.acme4j.toolbox.JSONBuilder; /** * Unit tests for {@link Authorization}. */ -@SuppressWarnings("deprecation") public class AuthorizationTest { private static final String SNAILMAIL_TYPE = "snail-01"; // a non-existent challenge @@ -63,10 +61,6 @@ public class AuthorizationTest { Challenge c2 = authorization.findChallenge(Http01Challenge.TYPE); assertThat(c2, is(notNullValue())); assertThat(c2, is(instanceOf(Http01Challenge.class))); - - // TlsSniChallenge is available, but not as standalone challenge - Challenge c3 = authorization.findChallenge(TlsSni02Challenge.TYPE); - assertThat(c3, is(nullValue())); } /** @@ -84,31 +78,19 @@ public class AuthorizationTest { assertThat(c1, contains(instanceOf(Http01Challenge.class))); // Available combined challenge - Collection c2 = authorization.findCombination(Dns01Challenge.TYPE, TlsSni02Challenge.TYPE); - assertThat(c2, hasSize(2)); - assertThat(c2, contains(instanceOf(Dns01Challenge.class), - instanceOf(TlsSni02Challenge.class))); + Collection c2 = authorization.findCombination(Dns01Challenge.TYPE, Http01Challenge.TYPE); + assertThat(c2, hasSize(1)); + assertThat(c2, contains(instanceOf(Http01Challenge.class))); // Order does not matter - Collection c3 = authorization.findCombination(TlsSni02Challenge.TYPE, Dns01Challenge.TYPE); - assertThat(c3, hasSize(2)); - assertThat(c3, contains(instanceOf(Dns01Challenge.class), - instanceOf(TlsSni02Challenge.class))); + Collection c3 = authorization.findCombination(Http01Challenge.TYPE, Dns01Challenge.TYPE); + assertThat(c3, hasSize(1)); + assertThat(c3, contains(instanceOf(Http01Challenge.class))); // Finds smaller combinations as well - Collection c4 = authorization.findCombination(Dns01Challenge.TYPE, TlsSni02Challenge.TYPE, SNAILMAIL_TYPE); - assertThat(c4, hasSize(2)); - assertThat(c4, contains(instanceOf(Dns01Challenge.class), - instanceOf(TlsSni02Challenge.class))); - - // Finds the smallest possible combination - Collection c5 = authorization.findCombination(Dns01Challenge.TYPE, TlsSni02Challenge.TYPE, Http01Challenge.TYPE); - assertThat(c5, hasSize(1)); - assertThat(c5, contains(instanceOf(Http01Challenge.class))); - - // Finds only entire combinations - Collection c6 = authorization.findCombination(Dns01Challenge.TYPE); - assertThat(c6, is(empty())); + Collection c4 = authorization.findCombination(Dns01Challenge.TYPE, Http01Challenge.TYPE, SNAILMAIL_TYPE); + assertThat(c4, hasSize(1)); + assertThat(c4, contains(instanceOf(Http01Challenge.class))); // Does not find challenges that have not been provided Collection c7 = authorization.findCombination(SNAILMAIL_TYPE); @@ -327,7 +309,6 @@ public class AuthorizationTest { provider.putTestChallenge(Http01Challenge.TYPE, new Http01Challenge(session)); provider.putTestChallenge(Dns01Challenge.TYPE, new Dns01Challenge(session)); - provider.putTestChallenge(TlsSni02Challenge.TYPE, new TlsSni02Challenge(session)); Authorization authorization = new Authorization(session, locationUrl); authorization.unmarshalAuthorization(getJsonAsObject("authorizationChallenges")); diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/OutOfBandChallengeTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/OutOfBandChallengeTest.java deleted file mode 100644 index 218df02c..00000000 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/OutOfBandChallengeTest.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * acme4j - Java ACME client - * - * Copyright (C) 2016 Richard "Shred" Körber - * http://acme4j.shredzone.org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.shredzone.acme4j.challenge; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; -import static org.shredzone.acme4j.toolbox.TestUtils.getJsonAsObject; -import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs; - -import java.io.IOException; -import java.net.URL; - -import org.junit.BeforeClass; -import org.junit.Test; -import org.shredzone.acme4j.Session; -import org.shredzone.acme4j.Status; -import org.shredzone.acme4j.toolbox.JSONBuilder; -import org.shredzone.acme4j.toolbox.TestUtils; - -/** - * Unit tests for {@link OutOfBand01Challenge}. - */ -public class OutOfBandChallengeTest { - private static Session session; - - @BeforeClass - public static void setup() throws IOException { - session = TestUtils.session(); - } - - /** - * Test that {@link OutOfBand01Challenge} is returning the validation URL. - */ - @Test - @SuppressWarnings("deprecation") - public void testHttpChallenge() throws IOException { - OutOfBand01Challenge challenge = new OutOfBand01Challenge(session); - challenge.unmarshall(getJsonAsObject("oobChallenge")); - - assertThat(challenge.getType(), is(OutOfBand01Challenge.TYPE)); - assertThat(challenge.getStatus(), is(Status.PENDING)); - assertThat(challenge.getValidationUrl(), - is(new URL("https://example.com/validate/evaGxfADs6pSRb2LAv9IZ"))); - - JSONBuilder cb = new JSONBuilder(); - challenge.respond(cb); - - assertThat(cb.toString(), sameJSONAs("{\"type\": \"oob-01\"}")); - } - -} diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/TlsSni01ChallengeTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/TlsSni01ChallengeTest.java deleted file mode 100644 index 69929609..00000000 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/TlsSni01ChallengeTest.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * acme4j - Java ACME client - * - * Copyright (C) 2015 Richard "Shred" Körber - * http://acme4j.shredzone.org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.shredzone.acme4j.challenge; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; -import static org.shredzone.acme4j.toolbox.TestUtils.getJsonAsObject; -import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs; - -import java.io.IOException; - -import org.junit.BeforeClass; -import org.junit.Test; -import org.shredzone.acme4j.Session; -import org.shredzone.acme4j.Status; -import org.shredzone.acme4j.toolbox.JSONBuilder; -import org.shredzone.acme4j.toolbox.TestUtils; - -/** - * Unit tests for {@link TlsSni01Challenge}. - */ -public class TlsSni01ChallengeTest { - private static final String KEY_AUTHORIZATION = - "VNLBdSiZ3LppU2CRG8bilqlwq4DuApJMg3ZJowU6JhQ.HnWjTDnyqlCrm6tZ-6wX-TrEXgRdeNu9G71gqxSO6o0"; - - private static Session session; - - @BeforeClass - public static void setup() throws IOException { - session = TestUtils.session(); - } - - /** - * Test that {@link TlsSni01Challenge} generates a correct authorization key. - */ - @Test - @SuppressWarnings("deprecation") - public void testTlsSniChallenge() throws IOException { - TlsSni01Challenge challenge = new TlsSni01Challenge(session); - challenge.unmarshall(getJsonAsObject("tlsSniChallenge")); - - assertThat(challenge.getType(), is(TlsSni01Challenge.TYPE)); - assertThat(challenge.getStatus(), is(Status.PENDING)); - assertThat(challenge.getSubject(), is("14e2350a04434f93c2e0b6012968d99d.ed459b6a7a019d9695609b8514f9d63d.acme.invalid")); - - JSONBuilder cb = new JSONBuilder(); - challenge.respond(cb); - - assertThat(cb.toString(), sameJSONAs("{\"keyAuthorization\"=\"" - + KEY_AUTHORIZATION + "\"}").allowingExtraUnexpectedFields()); - } - -} diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/TlsSni02ChallengeTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/TlsSni02ChallengeTest.java deleted file mode 100644 index 46b388e4..00000000 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/challenge/TlsSni02ChallengeTest.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * acme4j - Java ACME client - * - * Copyright (C) 2016 Richard "Shred" Körber - * http://acme4j.shredzone.org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ -package org.shredzone.acme4j.challenge; - -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; -import static org.shredzone.acme4j.toolbox.TestUtils.getJsonAsObject; -import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs; - -import java.io.IOException; - -import org.junit.BeforeClass; -import org.junit.Test; -import org.shredzone.acme4j.Session; -import org.shredzone.acme4j.Status; -import org.shredzone.acme4j.toolbox.JSONBuilder; -import org.shredzone.acme4j.toolbox.TestUtils; - -/** - * Unit tests for {@link TlsSni02Challenge}. - */ -public class TlsSni02ChallengeTest { - private static final String KEY_AUTHORIZATION = - "VNLBdSiZ3LppU2CRG8bilqlwq4DuApJMg3ZJowU6JhQ.HnWjTDnyqlCrm6tZ-6wX-TrEXgRdeNu9G71gqxSO6o0"; - - private static Session session; - - @BeforeClass - public static void setup() throws IOException { - session = TestUtils.session(); - } - - /** - * Test that {@link TlsSni02Challenge} generates a correct authorization key. - */ - @Test - @SuppressWarnings("deprecation") - public void testTlsSni02Challenge() throws IOException { - TlsSni02Challenge challenge = new TlsSni02Challenge(session); - challenge.unmarshall(getJsonAsObject("tlsSni02Challenge")); - - assertThat(challenge.getType(), is(TlsSni02Challenge.TYPE)); - assertThat(challenge.getStatus(), is(Status.PENDING)); - assertThat(challenge.getSubject(), is("5bf0b9908ed73bc53ed3327afa52f76b.0a4bea00520f0753f42abe0bb39e3ea8.token.acme.invalid")); - assertThat(challenge.getSanB(), is("14e2350a04434f93c2e0b6012968d99d.ed459b6a7a019d9695609b8514f9d63d.ka.acme.invalid")); - - JSONBuilder cb = new JSONBuilder(); - challenge.respond(cb); - - assertThat(cb.toString(), sameJSONAs("{\"keyAuthorization\"=\"" - + KEY_AUTHORIZATION + "\"}").allowingExtraUnexpectedFields()); - } - -} diff --git a/acme4j-client/src/test/java/org/shredzone/acme4j/provider/AbstractAcmeProviderTest.java b/acme4j-client/src/test/java/org/shredzone/acme4j/provider/AbstractAcmeProviderTest.java index 2540a3ab..d0f1c3e3 100644 --- a/acme4j-client/src/test/java/org/shredzone/acme4j/provider/AbstractAcmeProviderTest.java +++ b/acme4j-client/src/test/java/org/shredzone/acme4j/provider/AbstractAcmeProviderTest.java @@ -30,8 +30,6 @@ import org.shredzone.acme4j.Session; import org.shredzone.acme4j.challenge.Challenge; import org.shredzone.acme4j.challenge.Dns01Challenge; import org.shredzone.acme4j.challenge.Http01Challenge; -import org.shredzone.acme4j.challenge.OutOfBand01Challenge; -import org.shredzone.acme4j.challenge.TlsSni02Challenge; import org.shredzone.acme4j.connector.Connection; import org.shredzone.acme4j.connector.DefaultConnection; import org.shredzone.acme4j.connector.HttpConnector; @@ -41,7 +39,6 @@ import org.shredzone.acme4j.toolbox.TestUtils; /** * Unit tests for {@link AbstractAcmeProvider}. */ -@SuppressWarnings("deprecation") public class AbstractAcmeProviderTest { /** @@ -148,21 +145,9 @@ public class AbstractAcmeProviderTest { assertThat(c3, not(nullValue())); assertThat(c3, instanceOf(Dns01Challenge.class)); - Challenge c4 = provider.createChallenge(session, org.shredzone.acme4j.challenge.TlsSni01Challenge.TYPE); - assertThat(c4, not(nullValue())); - assertThat(c4, instanceOf(org.shredzone.acme4j.challenge.TlsSni01Challenge.class)); - - Challenge c5 = provider.createChallenge(session, TlsSni02Challenge.TYPE); - assertThat(c5, not(nullValue())); - assertThat(c5, instanceOf(TlsSni02Challenge.class)); - Challenge c6 = provider.createChallenge(session, "foobar-01"); assertThat(c6, is(nullValue())); - Challenge c7 = provider.createChallenge(session, OutOfBand01Challenge.TYPE); - assertThat(c7, not(nullValue())); - assertThat(c7, instanceOf(OutOfBand01Challenge.class)); - Challenge c8 = provider.createChallenge(session, ""); assertThat(c8, is(nullValue())); diff --git a/acme4j-client/src/test/resources/json.properties b/acme4j-client/src/test/resources/json.properties index 201e60fc..6055b50b 100644 --- a/acme4j-client/src/test/resources/json.properties +++ b/acme4j-client/src/test/resources/json.properties @@ -201,14 +201,9 @@ authorizationChallenges = \ "type": "dns-01",\ "uri": "https://example.com/authz/asdf/1",\ "token": "DGyRejmCefe7v4NfDGDKfA"\ - },\ - {\ - "type": "tls-sni-02",\ - "uri": "https://example.com/authz/asdf/2",\ - "token": "VNLBdSiZ3LppU2CRG8bilqlwq4DuApJMg3ZJowU6JhQ"\ }\ ],\ - "combinations": [[0], [1,2]]\ + "combinations": [[0],[1]]\ } @@ -245,24 +240,4 @@ httpNoTokenChallenge = \ "status":"pending" \ } -tlsSniChallenge = \ - { \ - "type":"tls-sni-01", \ - "status":"pending", \ - "token": "VNLBdSiZ3LppU2CRG8bilqlwq4DuApJMg3ZJowU6JhQ" \ - } - -tlsSni02Challenge = \ - { \ - "type":"tls-sni-02", \ - "status":"pending", \ - "token": "VNLBdSiZ3LppU2CRG8bilqlwq4DuApJMg3ZJowU6JhQ" \ - } - -oobChallenge = \ - { \ - "type": "oob-01", \ - "href": "https://example.com/validate/evaGxfADs6pSRb2LAv9IZ" \ - } - # \ No newline at end of file diff --git a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CertificateUtils.java b/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CertificateUtils.java index 422ae809..69ab5e4b 100644 --- a/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CertificateUtils.java +++ b/acme4j-utils/src/main/java/org/shredzone/acme4j/util/CertificateUtils.java @@ -132,22 +132,6 @@ public final class CertificateUtils { } } - /** - * Writes an X.509 certificate chain PEM file. - * - * @param chain - * {@link X509Certificate[]} to write - * @param w - * {@link Writer} to write the PEM file to. The {@link Writer} is closed - * after use. - * @deprecated Use - * {@link #writeX509CertificateChain(Writer, X509Certificate, X509Certificate...)} - */ - @Deprecated - public static void writeX509CertificateChain(X509Certificate[] chain, Writer w) throws IOException { - writeX509CertificateChain(w, null, chain); - } - /** * Reads a CSR PEM file. * @@ -166,43 +150,6 @@ public final class CertificateUtils { } } - /** - * Creates a self-signed {@link X509Certificate} that can be used for - * {@link org.shredzone.acme4j.challenge.TlsSni01Challenge}. The certificate is valid - * for 7 days. - * - * @param keypair - * A domain {@link KeyPair} to be used for the challenge - * @param subject - * Subject to create a certificate for - * @return Created certificate - * @deprecated The tls-sni-01 challenge is deprecated - */ - @Deprecated - public static X509Certificate createTlsSniCertificate(KeyPair keypair, String subject) throws IOException { - return createCertificate(keypair, subject); - } - - /** - * Creates a self-signed {@link X509Certificate} that can be used for - * {@link org.shredzone.acme4j.challenge.TlsSni02Challenge}. The certificate is valid - * for 7 days. - * - * @param keypair - * A domain {@link KeyPair} to be used for the challenge - * @param sanA - * SAN-A to be used in the certificate - * @param sanB - * SAN-B to be used in the certificate - * @return Created certificate - * @deprecated The tls-sni-02 challenge is deprecated - */ - @Deprecated - public static X509Certificate createTlsSni02Certificate(KeyPair keypair, String sanA, String sanB) - throws IOException { - return createCertificate(keypair, sanA, sanB); - } - /** * Creates a generic self-signed challenge {@link X509Certificate}. The certificate is * valid for 7 days. diff --git a/acme4j-utils/src/test/java/org/shredzone/acme4j/util/CertificateUtilsTest.java b/acme4j-utils/src/test/java/org/shredzone/acme4j/util/CertificateUtilsTest.java index 2791ff64..0127f4f4 100644 --- a/acme4j-utils/src/test/java/org/shredzone/acme4j/util/CertificateUtilsTest.java +++ b/acme4j-utils/src/test/java/org/shredzone/acme4j/util/CertificateUtilsTest.java @@ -28,9 +28,6 @@ import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.CertificateParsingException; import java.security.cert.X509Certificate; -import java.time.Duration; -import java.time.Instant; -import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -121,55 +118,6 @@ public class CertificateUtilsTest { assertThat(countCertificates(out), is(3)); } - /** - * Test if {@link CertificateUtils#createTlsSniCertificate(KeyPair, String)} creates a - * good certificate. - */ - @SuppressWarnings("deprecation") - @Test - public void testCreateTlsSniCertificate() throws IOException, CertificateParsingException { - String subject = "30c452b9bd088cdbc2c4094947025d7c.7364ea602ac325a1b55ceaae024fbe29.acme.invalid"; - - KeyPair keypair = KeyPairUtils.createKeyPair(2048); - - X509Certificate cert = CertificateUtils.createTlsSniCertificate(keypair, subject); - - Instant now = Instant.now(); - Instant end = now.plus(Duration.ofDays(8)); - - assertThat(cert, not(nullValue())); - assertThat(cert.getNotAfter(), is(greaterThan(Date.from(now)))); - assertThat(cert.getNotAfter(), is(lessThan(Date.from(end)))); - assertThat(cert.getNotBefore(), is(lessThanOrEqualTo(Date.from(now)))); - assertThat(cert.getSubjectX500Principal().getName(), is("CN=acme.invalid")); - assertThat(getSANs(cert), containsInAnyOrder(subject)); - } - - /** - * Test if {@link CertificateUtils#createTlsSni02Certificate(KeyPair, String, String)} - * creates a good certificate. - */ - @SuppressWarnings("deprecation") - @Test - public void testCreateTlsSni02Certificate() throws IOException, CertificateParsingException { - String sanA = "1082909237a535173c8415a44539f84e.248317530d8d1a0c71de8fd23f1beae4.token.acme.invalid"; - String sanB = "edc3a1d40199c1723358d57853bc23ff.4d4473417a6d76e80df17bbcfbe53d2c.ka.acme.invalid"; - - KeyPair keypair = KeyPairUtils.createKeyPair(2048); - - X509Certificate cert = CertificateUtils.createTlsSni02Certificate(keypair, sanA, sanB); - - Instant now = Instant.now(); - Instant end = now.plus(Duration.ofDays(8)); - - assertThat(cert, not(nullValue())); - assertThat(cert.getNotAfter(), is(greaterThan(Date.from(now)))); - assertThat(cert.getNotAfter(), is(lessThan(Date.from(end)))); - assertThat(cert.getNotBefore(), is(lessThanOrEqualTo(Date.from(now)))); - assertThat(cert.getSubjectX500Principal().getName(), is("CN=acme.invalid")); - assertThat(getSANs(cert), containsInAnyOrder(sanA, sanB)); - } - /** * Test if {@link CertificateUtils#readCSR(InputStream)} reads an identical CSR. */ diff --git a/src/site/markdown/challenge/index.md b/src/site/markdown/challenge/index.md index cba4c31d..d42fe6fe 100644 --- a/src/site/markdown/challenge/index.md +++ b/src/site/markdown/challenge/index.md @@ -10,6 +10,3 @@ The ACME specifications define these standard challenges: * [http-01](./http-01.html) * [dns-01](./dns-01.html) -* [tls-sni-01](./tls-sni-01.html) -* [tls-sni-02](./tls-sni-02.html) -* [oob-01](./oob-01.html) diff --git a/src/site/markdown/challenge/oob-01.md b/src/site/markdown/challenge/oob-01.md deleted file mode 100644 index 2a8cb490..00000000 --- a/src/site/markdown/challenge/oob-01.md +++ /dev/null @@ -1,11 +0,0 @@ -# oob-01 Challenge - -> **NOTE:** `oob-01` challenge has been removed in ACMEv2. - -The `oob-01` challenge is an "out of band" challenge that is used when there is no automatic way of validating ownership of a domain. The client is instead required to perform actions outside of the ACME protocol. - -`OutOfBand01Challenge` implements this challenge. Its `getValidationUrl()` method returns a URL that refers to a web page with further instructions about the actions to be taken. - -The challenge must be triggered before the URL is opened in a browser. - -Due to the nature of this challenge, it may take a considerable amount of time until its state changes to `VALID`. diff --git a/src/site/markdown/challenge/tls-sni-01.md b/src/site/markdown/challenge/tls-sni-01.md deleted file mode 100644 index 58afcdb2..00000000 --- a/src/site/markdown/challenge/tls-sni-01.md +++ /dev/null @@ -1,44 +0,0 @@ -# tls-sni-01 Challenge - -> **SECURITY:** [This challenge is vulnerable in shared hosting environments](https://community.letsencrypt.org/t/2018-01-09-issue-with-tls-sni-01-and-shared-hosting-infrastructure/49996), and is going to be removed from the ACME specs. _Let's Encrypt_ does not offer this challenge to the general public any more. - -With the `tls-sni-01` challenge, you prove to the CA that you are able to control the web server of the domain to be authorized, by letting it respond to a SNI request with a specific self-signed cert. - -`TlsSni01Challenge` provides a subject: - -```java -TlsSni01Challenge challenge = auth.findChallenge(TlsSni01Challenge.TYPE); - -String subject = challenge.getSubject(); -``` - -The `subject` is basically a domain name formed like in this example: - -``` -30c452b9bd088cdbc2c4094947025d7c.7364ea602ac325a1b55ceaae024fbe29.acme.invalid -``` - -You need to create a self-signed certificate with the subject set as _Subject Alternative Name_. After that, configure your web server so it will use this certificate on a SNI request to the `subject`. - -The `TlsSni01Challenge` class does not generate a self-signed certificate, as it would require _Bouncy Castle_. However, there is a utility method in the _acme4j-utils_ module for this use case: - -```java -KeyPair sniKeyPair = KeyPairUtils.createKeyPair(2048); -X509Certificate cert = CertificateUtils.createTlsSniCertificate(sniKeyPair, subject); -``` - -Now use `cert` and `sniKeyPair` to let your web server respond to a SNI request to `subject`. - -The challenge is completed when the CA was able to send the SNI request and get the correct certificate in return. - -Note that the request is sent to port 443 only. There is no way to choose a different port, for security reasons. This is a limitation of the ACME protocol, not of _acme4j_. - -This shell command line may be helpful to test your web server configuration: - -```shell -echo QUIT | \ - openssl s_client -servername $subject -connect $server_ip:443 | \ - openssl x509 -text -noout -``` - -It should return a certificate with `subject` set as `X509v3 Subject Alternative Name`. diff --git a/src/site/markdown/challenge/tls-sni-02.md b/src/site/markdown/challenge/tls-sni-02.md deleted file mode 100644 index cb121364..00000000 --- a/src/site/markdown/challenge/tls-sni-02.md +++ /dev/null @@ -1,46 +0,0 @@ -# tls-sni-02 Challenge - -> **SECURITY:** [This challenge is vulnerable in shared hosting environments](https://community.letsencrypt.org/t/2018-01-09-issue-with-tls-sni-01-and-shared-hosting-infrastructure/49996), and is going to be removed from the ACME specs. - -With the `tls-sni-02` challenge, you prove to the CA that you are able to control the web server of the domain to be authorized, by letting it respond to a SNI request with a specific self-signed cert. - -`TlsSni02Challenge` provides a subject and a key-authorization domain: - -```java -TlsSni02Challenge challenge = auth.findChallenge(TlsSni02Challenge.TYPE); - -String subject = challenge.getSubject(); // SAN-A -String sanB = challenge.getSanB(); // SAN-B -``` - -`subject` and `sanB` are basically domain names formed like in this example: - -``` -5bf0b9908ed73bc53ed3327afa52f76b.0a4bea00520f0753f42abe0bb39e3ea8.token.acme.invalid -14e2350a04434f93c2e0b6012968d99d.ed459b6a7a019d9695609b8514f9d63d.ka.acme.invalid -``` - -You need to create a self-signed certificate with both `subject` and `sanB` set as _Subject Alternative Name_. After that, configure your web server so it will use this certificate on a SNI request to `subject`. - -The `TlsSni02Challenge` class does not generate a self-signed certificate, as it would require _Bouncy Castle_. However, there is a utility method in the _acme4j-utils_ module for this use case: - -```java -KeyPair sniKeyPair = KeyPairUtils.createKeyPair(2048); -X509Certificate cert = CertificateUtils.createTlsSni02Certificate(sniKeyPair, subject, sanB); -``` - -Now use `cert` and `sniKeyPair` to let your web server respond to SNI requests to `subject`. The CA is not allowed to reveal `sanB`, so it will not perform SNI requests to that domain. - -The challenge is completed when the CA was able to send the SNI request and get the correct certificate in return. - -Note that the request is sent to port 443 only. There is no way to choose a different port, for security reasons. This is a limitation of the ACME protocol, not of _acme4j_. - -This shell command line may be helpful to test your web server configuration: - -```shell -echo QUIT | \ - openssl s_client -servername $subject -connect $server_ip:443 | \ - openssl x509 -text -noout -``` - -It should return a certificate with both `subject` and `sanB` set as `X509v3 Subject Alternative Name`. diff --git a/src/site/site.xml b/src/site/site.xml index f79416e6..4f1a0411 100644 --- a/src/site/site.xml +++ b/src/site/site.xml @@ -40,9 +40,6 @@ - - -