-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
1,197 additions
and
545 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
205 changes: 205 additions & 0 deletions
205
xmppserver/src/test/java/org/jivesoftware/openfire/session/AbstractRemoteServerDummy.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,205 @@ | ||
package org.jivesoftware.openfire.session; | ||
|
||
import org.dom4j.DocumentException; | ||
import org.dom4j.DocumentHelper; | ||
import org.dom4j.Element; | ||
import org.jivesoftware.openfire.keystore.KeystoreTestUtils; | ||
|
||
import javax.net.ssl.KeyManager; | ||
import javax.net.ssl.TrustManager; | ||
import javax.net.ssl.X509KeyManager; | ||
import javax.net.ssl.X509TrustManager; | ||
import java.net.Socket; | ||
import java.security.KeyPair; | ||
import java.security.Principal; | ||
import java.security.PrivateKey; | ||
import java.security.cert.CertificateException; | ||
import java.security.cert.X509Certificate; | ||
import java.time.Duration; | ||
import java.time.Instant; | ||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
|
||
public class AbstractRemoteServerDummy | ||
{ | ||
public static final String XMPP_DOMAIN = "remote-dummy.example.org"; | ||
public static final Duration SO_TIMEOUT = Duration.ofMillis(500); | ||
protected boolean useExpiredEndEntityCertificate; | ||
protected boolean useSelfSignedCertificate; | ||
protected boolean disableDialback; | ||
protected ServerSettings.EncryptionPolicy encryptionPolicy = ServerSettings.EncryptionPolicy.OPTIONAL; | ||
protected KeystoreTestUtils.ResultHolder generatedPKIX; | ||
|
||
/** | ||
* Updates the TLS encryption policy that's observed by this server. | ||
*/ | ||
public void setEncryptionPolicy(ServerSettings.EncryptionPolicy encryptionPolicy) | ||
{ | ||
this.encryptionPolicy = encryptionPolicy; | ||
} | ||
|
||
/** | ||
* When set to 'true', this instance will identify itself with a TLS certificate that is self-signed. | ||
* | ||
* Must be invoked before {@link #preparePKIX()} is invoked. | ||
* | ||
* @param useSelfSignedCertificate 'true' to use a self-signed certificate | ||
*/ | ||
public void setUseSelfSignedCertificate(boolean useSelfSignedCertificate) | ||
{ | ||
if (generatedPKIX != null) { | ||
throw new IllegalStateException("Cannot change PKIX settings after PKIX has been prepared."); | ||
} | ||
this.useSelfSignedCertificate = useSelfSignedCertificate; | ||
} | ||
|
||
/** | ||
* When set to 'true', this instance will identify itself with a TLS certificate that is expired (its 'notBefore' | ||
* and 'notAfter' values define a period of validity that does not include the current date and time). | ||
* | ||
* Must be invoked before {@link #preparePKIX()} is invoked. | ||
* | ||
* @param useExpiredEndEntityCertificate 'true' to use an expired certificate | ||
*/ | ||
public void setUseExpiredEndEntityCertificate(boolean useExpiredEndEntityCertificate) | ||
{ | ||
if (generatedPKIX != null) { | ||
throw new IllegalStateException("Cannot change PKIX settings after PKIX has been prepared."); | ||
} | ||
this.useExpiredEndEntityCertificate = useExpiredEndEntityCertificate; | ||
} | ||
|
||
/** | ||
* When set to 'true', this instance will NOT advertise support for the Dialback authentication mechanism, and will | ||
* reject Dialback authentication attempts. | ||
*/ | ||
public void setDisableDialback(boolean disableDialback) { | ||
this.disableDialback = disableDialback; | ||
} | ||
|
||
/** | ||
* Generates KeyPairs and certificates that are used to identify this server using TLS. | ||
* | ||
* The data that is generated by this method can be configured by invoking methods such as | ||
* {@link #setUseSelfSignedCertificate(boolean)} and | ||
* {@link #setUseExpiredEndEntityCertificate(boolean)}. These must be invoked before invoking #preparePKIX | ||
*/ | ||
public void preparePKIX() throws Exception | ||
{ | ||
if (generatedPKIX != null) { | ||
throw new IllegalStateException("PKIX already prepared."); | ||
} | ||
|
||
final String commonName = XMPP_DOMAIN; | ||
if (useSelfSignedCertificate) { | ||
generatedPKIX = useExpiredEndEntityCertificate ? KeystoreTestUtils.generateExpiredSelfSignedCertificate(commonName) : KeystoreTestUtils.generateSelfSignedCertificate(commonName); | ||
} else { | ||
generatedPKIX = useExpiredEndEntityCertificate ? KeystoreTestUtils.generateCertificateChainWithExpiredEndEntityCert(commonName) : KeystoreTestUtils.generateValidCertificateChain(commonName); | ||
} | ||
} | ||
|
||
/** | ||
* Returns the KeyPairs and certificates that are used to identify this server using TLS. | ||
* | ||
* @return TLS identification material for this server. | ||
*/ | ||
public KeystoreTestUtils.ResultHolder getGeneratedPKIX() { | ||
return generatedPKIX; | ||
} | ||
|
||
/** | ||
* Parses text as an XML element. | ||
* | ||
* When the provided input is an element that is not closed, then a closing element is automatically generated. This | ||
* helps to parse `stream` elements, that are closed only when the XMPP session ends. | ||
* | ||
* @param xml The data to parse | ||
* @return an XML element | ||
*/ | ||
public static Element parse(final String xml) throws DocumentException | ||
{ | ||
String toParse = xml; | ||
|
||
if (!xml.endsWith("/>")) { | ||
Matcher matcher = Pattern.compile("[A-Za-z:]+").matcher(xml); | ||
if (matcher.find()) { | ||
final String fakeEndTag = "</" + matcher.group() + ">"; | ||
if (!xml.trim().endsWith(fakeEndTag)) { | ||
toParse += fakeEndTag; | ||
} | ||
} | ||
} | ||
|
||
return DocumentHelper.parseText(toParse).getRootElement(); | ||
} | ||
|
||
/** | ||
* Creates a TrustManager that will blindly accept all certificates. | ||
*/ | ||
public static TrustManager[] createTrustManagerThatTrustsAll() | ||
{ | ||
// Create a trust manager that does not validate certificate chains | ||
return new TrustManager[]{ | ||
new X509TrustManager() | ||
{ | ||
public X509Certificate[] getAcceptedIssuers() { | ||
return new X509Certificate[0]; | ||
} | ||
|
||
public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException | ||
{ | ||
if (Instant.now().isAfter(certs[0].getNotAfter().toInstant()) || Instant.now().isBefore(certs[0].getNotBefore().toInstant())) { | ||
throw new CertificateException("Peer certificate is expired."); | ||
} | ||
} | ||
|
||
public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException { | ||
if (Instant.now().isAfter(certs[0].getNotAfter().toInstant()) || Instant.now().isBefore(certs[0].getNotBefore().toInstant())) { | ||
throw new CertificateException("Peer certificate is expired."); | ||
} | ||
} | ||
} | ||
}; | ||
} | ||
|
||
/** | ||
* Creates a KeyManager that identifies with the provided keyPair and certificate chain. | ||
*/ | ||
public static KeyManager[] createKeyManager(final KeyPair keyPair, final X509Certificate... chain) | ||
{ | ||
return new KeyManager[]{ | ||
new X509KeyManager() | ||
{ | ||
@Override | ||
public String[] getClientAliases(String keyType, Principal[] issuers) { | ||
throw new IllegalStateException("Should not be used."); | ||
} | ||
|
||
@Override | ||
public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) { | ||
throw new IllegalStateException("Should not be used."); | ||
} | ||
|
||
@Override | ||
public String[] getServerAliases(String keyType, Principal[] issuers) { | ||
return new String[] { XMPP_DOMAIN }; | ||
} | ||
|
||
@Override | ||
public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) { | ||
return XMPP_DOMAIN; | ||
} | ||
|
||
@Override | ||
public X509Certificate[] getCertificateChain(String alias) { | ||
return chain; | ||
} | ||
|
||
@Override | ||
public PrivateKey getPrivateKey(String alias) { | ||
return keyPair.getPrivate(); | ||
} | ||
} | ||
}; | ||
} | ||
} |
Oops, something went wrong.