Deprecate tls-sni challenges

acmev1
Richard Körber 2018-01-13 14:02:59 +01:00
parent a01a9165a8
commit 1fd515912a
No known key found for this signature in database
GPG Key ID: AAB9FD19C78AA3E0
13 changed files with 27 additions and 67 deletions

View File

@ -19,7 +19,12 @@ 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;

View File

@ -19,7 +19,11 @@ 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;

View File

@ -41,6 +41,7 @@ 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<String, Function<Session, Challenge>> CHALLENGES = challengeMap();

View File

@ -40,6 +40,7 @@ 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

View File

@ -45,6 +45,7 @@ public class TlsSni01ChallengeTest {
* 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"));

View File

@ -45,6 +45,7 @@ public class TlsSni02ChallengeTest {
* 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"));

View File

@ -41,6 +41,7 @@ import org.shredzone.acme4j.toolbox.TestUtils;
/**
* Unit tests for {@link AbstractAcmeProvider}.
*/
@SuppressWarnings("deprecation")
public class AbstractAcmeProviderTest {
/**

View File

@ -41,6 +41,7 @@ public class LetsEncryptHttpConnectorTest {
*/
@Test
@Category(HttpURLConnection.class)
@SuppressWarnings("deprecation")
public void testCertificate() throws IOException, URISyntaxException {
LetsEncryptHttpConnector connector = new LetsEncryptHttpConnector();
@ -68,6 +69,7 @@ public class LetsEncryptHttpConnectorTest {
* Test that the {@link SSLSocketFactory} can be instantiated and is cached.
*/
@Test
@SuppressWarnings("deprecation")
public void testCreateSocketFactory() throws IOException {
LetsEncryptHttpConnector connector = new LetsEncryptHttpConnector();

View File

@ -65,7 +65,7 @@ public class ClientTest {
private static final Logger LOG = LoggerFactory.getLogger(ClientTest.class);
private enum ChallengeType { HTTP, DNS, TLSSNI }
private enum ChallengeType { HTTP, DNS }
/**
* Generates a certificate for the given domains. Also takes care for the registration
@ -210,10 +210,6 @@ public class ClientTest {
case DNS:
challenge = dnsChallenge(auth, domain);
break;
case TLSSNI:
challenge = tlsSniChallenge(auth, domain);
break;
}
if (challenge == null) {
@ -329,63 +325,6 @@ public class ClientTest {
return challenge;
}
/**
* Prepares a TLS-SNI challenge.
* <p>
* The verification of this challenge expects that the web server returns a special
* validation certificate.
* <p>
* This example outputs instructions that need to be executed manually. In a
* production environment, you would rather configure your web server automatically.
*
* @param auth
* {@link Authorization} to find the challenge in
* @param domain
* Domain name to be authorized
* @return {@link Challenge} to verify
*/
public Challenge tlsSniChallenge(Authorization auth, String domain) throws AcmeException {
// Find a single tls-sni-01 challenge
org.shredzone.acme4j.challenge.TlsSni01Challenge challenge = auth.findChallenge(org.shredzone.acme4j.challenge.TlsSni01Challenge.TYPE);
if (challenge == null) {
throw new AcmeException("Found no " + org.shredzone.acme4j.challenge.TlsSni01Challenge.TYPE + " challenge, don't know what to do...");
}
// Get the Subject
String subject = challenge.getSubject();
// Create a validation key pair
KeyPair domainKeyPair;
try (FileWriter fw = new FileWriter("tlssni.key")) {
domainKeyPair = KeyPairUtils.createKeyPair(2048);
KeyPairUtils.writeKeyPair(domainKeyPair, fw);
} catch (IOException ex) {
throw new AcmeException("Could not write keypair", ex);
}
// Create a validation certificate
try (FileWriter fw = new FileWriter("tlssni.crt")) {
X509Certificate cert = CertificateUtils.createTlsSniCertificate(domainKeyPair, subject);
CertificateUtils.writeX509Certificate(cert, fw);
} catch (IOException ex) {
throw new AcmeException("Could not write certificate", ex);
}
// Output the challenge, wait for acknowledge...
LOG.info("Please configure your web server.");
LOG.info("It must return the certificate 'tlssni.crt' on a SNI request to:");
LOG.info(subject);
LOG.info("The matching keypair is available at 'tlssni.key'.");
LOG.info("If you're ready, dismiss the dialog...");
StringBuilder message = new StringBuilder();
message.append("Please use 'tlssni.key' and 'tlssni.crt' cert for SNI requests to:\n\n");
message.append("https://").append(subject).append("\n\n");
acceptChallenge(message.toString());
return challenge;
}
/**
* Presents the instructions for preparing the challenge validation, and waits for
* dismissal. If the user cancelled the dialog, an exception is thrown.

View File

@ -39,7 +39,6 @@ import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.pkcs.PKCS10CertificationRequest;
import org.shredzone.acme4j.challenge.TlsSni02Challenge;
/**
* Utility class offering convenience methods for certificates.
@ -177,14 +176,17 @@ public final class CertificateUtils {
* @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 TlsSni02Challenge}. The certificate is valid for 7 days.
* {@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
@ -193,7 +195,9 @@ public final class CertificateUtils {
* @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);

View File

@ -125,8 +125,8 @@ public class CertificateUtilsTest {
* Test if {@link CertificateUtils#createTlsSniCertificate(KeyPair, String)} creates a
* good certificate.
*/
@SuppressWarnings("deprecation")
@Test
@SuppressWarnings("deprecation") // test deprecated method
public void testCreateTlsSniCertificate() throws IOException, CertificateParsingException {
String subject = "30c452b9bd088cdbc2c4094947025d7c.7364ea602ac325a1b55ceaae024fbe29.acme.invalid";
@ -149,6 +149,7 @@ public class CertificateUtilsTest {
* 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";

View File

@ -1,6 +1,6 @@
# tls-sni-01 Challenge
> **NOTE:** In ACMEv2, this challenge is going to be replaced by [tls-sni-02](./tls-sni-02.html). However, the _Let's Encrypt_ ACMEv1 server is still offering this challenge as the only TLS-SNI based challenge. To be on the safe side, request both challenges and process the one that is returned.
> **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.

View File

@ -1,6 +1,6 @@
# tls-sni-02 Challenge
> **NOTE:** According to the ACME specifications, this challenge will replace [tls-sni-01](./tls-sni-01.html). However, _Let's Encrypt_ does not currently support `tls-sni-02`. To be on the safe side, request both challenges and process the one that is returned.
> **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.