I'm trying to get a simple https embedded server running. This is for a test prototype, so real security isn't important at this point and fake or omitted certificates are fine, but my situation requires https vs regular http.
This code seems to call the right APIs, it runs, but the client browser gets "SSL Connection Error":
public class SimpleHttps {
public static final String SERVER_NAME = "https://localhost:8090";
public static final URI BASE_URI = URI.create(SERVER_NAME);
private static class TrustAllCerts implements X509TrustManager {
#Override public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { }
#Override public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { }
#Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
}
private final static TrustManager[] trustAllCerts = new TrustManager[] { new TrustAllCerts() };
public static SSLEngineConfigurator getSslEngineConfig() throws KeyManagementException, NoSuchAlgorithmException {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new SecureRandom());
SSLEngineConfigurator sslEngineConfigurator = new SSLEngineConfigurator(sc, false, false, false);
return sslEngineConfigurator;
}
public static void main(String[] args) throws Exception {
final ResourceConfig rc = new ResourceConfig().register(MyResource.class);
HttpServer httpServer = GrizzlyHttpServerFactory.createHttpServer(BASE_URI, rc, true, getSslEngineConfig());
System.in.read();
httpServer.stop();
}
}
Related
i had a code which app can access https, just like this :
public class HttpsTrustManager implements X509TrustManager {
private static TrustManager[] trustManagers;
private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[]{};
#Override
public void checkClientTrusted(java.security.cert.X509Certificate[] x509Certificates, String s)
throws java.security.cert.CertificateException {
}
#Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
try {
chain[0].checkValidity();
} catch (Exception e) {
throw new CertificateException("Certificate not valid or trusted.");
}
}
public boolean isClientTrusted(X509Certificate[] chain) {
return true;
}
public boolean isServerTrusted(X509Certificate[] chain) {
return true;
}
#Override
public X509Certificate[] getAcceptedIssuers() {
return _AcceptedIssuers;
}
public static void allowAllSSL() {
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
});
SSLContext context = null;
if (trustManagers == null) {
trustManagers = new TrustManager[]{new HttpsTrustManager()};
}
try {
context = SSLContext.getInstance("TLS");
context.init(null, trustManagers, new SecureRandom());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
HttpsURLConnection.setDefaultSSLSocketFactory(context
.getSocketFactory());
}
}
after that, google play console give me a notice :
Apache Trust Manager
Your app is using an unsafe implementation of the X509TrustManager interface with an Apache HTTP client, resulting in a security vulnerability. Please see this Google Help Center article for details, including the deadline for fixing the vulnerability.
Insecure Hostname Verifier
Your app is using an unsafe implementation of HostnameVerifier. Please see this Google Help Center article for details, including the deadline for fixing the vulnerability.
is there something wrong with my code ??
I am trying to create DI for my api client. So I can access it all over the app without big problems.
I have implemented normal singleton but I would like to change it to hilt.
Problem is, My client class needs a baseURL to be set up dynamicly on startup of application.
private APIClient(String baseURL) {
Retrofit retrofit = new Retrofit.Builder().baseUrl(baseURL)
.client(getUnsafeOkHttpClient().build())
.addConverterFactory(GsonConverterFactory.create())
.build();
sessionApi = retrofit.create(ISessionApi.class);
}
Is there a way to do it? I can't find anything similar.
Whole code:
public class APIClient {
private static APIClient instance = null;
private static String baseURL;
private ISessionApi sessionApi;
private APIClient(String baseURL) {
Retrofit retrofit = new Retrofit.Builder().baseUrl(baseURL)
.client(getUnsafeOkHttpClient().build())
.addConverterFactory(GsonConverterFactory.create())
.build();
sessionApi = retrofit.create(ISessionApi.class);
}
public static synchronized APIClient getInstance() {
if (instance == null) {
instance = new APIClient(baseURL);
}
return instance;
}
public static synchronized APIClient getInstance(String baseURL) {
APIClient.baseURL=baseURL;
if (instance == null) {
instance = new APIClient(baseURL);
}
return instance;
}
public ISessionApi getSessionApi() {
return sessionApi;
}
public static OkHttpClient.Builder getUnsafeOkHttpClient() {
try {
// Create a trust manager that does not validate certificate chains
final TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
#Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
#Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
#Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
}
};
// Install the all-trusting trust manager
final SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting manager
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0]);
builder.hostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
return builder;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
My question is similar to: SSLSocketFactory in java
I need to set a custom SSLSocketFactory...except I do NOT have an https connection (it's LDAPS), so can't use:
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
...to set the SSLSocketFactory. I have an SSLContext object initialized but when I make the LDAP connection the default SSLContext is called automatically since my custom one is not set:
dirContext = new InitialDirContext(env); // <-- reverts to default ssl context
Is there a non-HTTPS equivalent method to line #3 below:
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(myKeyManagerFactory.getKeyManagers(), myTrustManagerArray, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
Yes, there is.
env.put("java.naming.ldap.factory.socket", UnsecuredSSLSocketFactory.class.getName());
UnsecuredSSLSocketFactory.java:
public class UnsecuredSSLSocketFactory extends SSLSocketFactory
{
private SSLSocketFactory socketFactory;
public UnsecuredSSLSocketFactory()
{
try
{
var sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, new TrustManager[]{new X509TrustManager()
{
#Override
public void checkClientTrusted(X509Certificate[] xcs, String string){}
#Override
public void checkServerTrusted(X509Certificate[] xcs, String string){}
#Override
public X509Certificate[] getAcceptedIssuers()
{
return null;
}
}}, new SecureRandom());
socketFactory = sslContext.getSocketFactory();
}
catch(Exception e)
{
throw new RuntimeException(e);
}
}
#SuppressWarnings("unused")
public static SocketFactory getDefault()
{
return new UnsecuredSSLSocketFactory();
}
#Override
public String[] getDefaultCipherSuites()
{
return socketFactory.getDefaultCipherSuites();
}
#Override
public String[] getSupportedCipherSuites()
{
return socketFactory.getSupportedCipherSuites();
}
#Override
public Socket createSocket(Socket socket, String string, int i, boolean bln) throws IOException
{
return socketFactory.createSocket(socket, string, i, bln);
}
#Override
public Socket createSocket(String string, int i) throws IOException
{
return socketFactory.createSocket(string, i);
}
#Override
public Socket createSocket(String string, int i, InetAddress ia, int i1) throws IOException
{
return socketFactory.createSocket(string, i, ia, i1);
}
#Override
public Socket createSocket(InetAddress ia, int i) throws IOException
{
return socketFactory.createSocket(ia, i);
}
#Override
public Socket createSocket(InetAddress ia, int i, InetAddress ia1, int i1) throws IOException
{
return socketFactory.createSocket(ia, i, ia1, i1);
}
#Override
public Socket createSocket() throws IOException
{
return socketFactory.createSocket();
}
}
Note, if the issue is just a hostname mismatch (which is super common in clustered Active Directory Environments), you can just set the system property com.sun.jndi.ldap.object.disableEndpointIdentification to true, so as a command line arg -Dcom.sun.jndi.ldap.object.disableEndpointIdentification=true
Note this will only ignore a hostname mismatch on the certificate, you will still need to have a trust chain from ldap's cert to something in your truststore, but this seems to be the most common issue people have with SSL, LDAP and Active Directory, as the certificate's the domain generate for each domain controller don't include a subject alternate name for the domain itself, so if you follow the standard example of just pointing ldap to yourcomapanydomain.com, when it resolves to domaincontroller1.yourcompanydomain.com you get a failure. Note, if you are upgrading from an old java version, this behavior changed in https://www.oracle.com/java/technologies/javase/8u181-relnotes.html
My Android app tells me that my https certificate doesn't match the hostname:
javax.net.ssl.SSLException: hostname in certificate didn't match: <hostname1> != <oldhostname>
What is odd is that
The website (hostname1) gives the correct certificate (checked with browsers and the ssllabs tool)
oldhostname is the previous hostname I had set up in previous versions of the app
Is there some kind of cache for certificates? I cant't find any info on that
Add this class
public class HttpsTrustManager implements X509TrustManager {
private static TrustManager[] trustManagers;
private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[]{};
#Override
public void checkClientTrusted(
X509Certificate[] x509Certificates, String s)
throws java.security.cert.CertificateException {
}
#Override
public void checkServerTrusted(
X509Certificate[] x509Certificates, String s)
throws java.security.cert.CertificateException {
}
public boolean isClientTrusted(X509Certificate[] chain) {
return true;
}
public boolean isServerTrusted(X509Certificate[] chain) {
return true;
}
#Override
public X509Certificate[] getAcceptedIssuers() {
return _AcceptedIssuers;
}
public static void allowAllSSL() {
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
#Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
});
SSLContext context = null;
if (trustManagers == null) {
trustManagers = new TrustManager[]{new HttpsTrustManager()};
}
try {
context = SSLContext.getInstance("TLS");
context.init(null, trustManagers, new SecureRandom());
} catch (NoSuchAlgorithmException | KeyManagementException e) {
e.printStackTrace();
}
HttpsURLConnection.setDefaultSSLSocketFactory(context != null ? context.getSocketFactory() : null);
}
}
and call it from your MainActivity with HttpsTrustManager.allowAllSSL();
Although it's not save approach but i solve my problem with this.
I want to make a SSL connection as given on this http://docs.marklogic.com/guide/admin/SSL
But I'm getting the following exception:
Exception in thread "main"
com.marklogic.xcc.exceptions.ServerConnectionException: Unrecognized
SSL message, plaintext connection? [Session: user=demo, cb=Arg
[ContentSource: user=demo, cb=Arg [provider: SSLconn
address=localhost/127.0.0.1:9470, pool=0/64]]] [Client: XCC/7.0-2]
at
com.marklogic.xcc.impl.handlers.AbstractRequestController.runRequest(AbstractRequestController.java:124)
at
com.marklogic.xcc.impl.SessionImpl.submitRequestInternal(SessionImpl.java:388)
at
com.marklogic.xcc.impl.SessionImpl.submitRequest(SessionImpl.java:371)
at com.demoe2.MarklogicDemo.main(MarklogicDemo.java:41) Caused by:
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext
connection? at
sun.security.ssl.EngineInputRecord.bytesInCompletePacket(Unknown
Source) at sun.security.ssl.SSLEngineImpl.readNetRecord(Unknown
Source) at sun.security.ssl.SSLEngineImpl.unwrap(Unknown Source
My source code is for Java
public class MarklogicDemo {
public static void main(String[] args) throws Exception {
URI uri = new URI("xcc://demo:password#localhost:9470/Arg");
query = "for $x in cts:search(//PLAY,cts:element-word-query(xs:QName(\"LINE\"),\"King\")) return ($x//TITLE)";
ContentSource con =
ContentSourceFactory.newContentSource(
"localhost", 9470,
"demo", "password",
"Arg", newTrustOptions());
Session see = con.newSession();
Request req = see.newAdhocQuery(query);
ResultSequence rs = see.submitRequest (req);
System.out.println (rs.asString());
see.close();
}
protected static SecurityOptions newTrustOptions() throws Exception {
TrustManager[] trust =
new TrustManager[] {
new X509TrustManager() {
public void checkClientTrusted(
X509Certificate[] x509Certificates,
String s) throws CertificateException {
}
public void checkServerTrusted(
X509Certificate[] x509Certificates,
String s) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
};
SSLContext sslContext = SSLContext.getInstance("SSLv3");
sslContext.init(null, trust, null);
return new SecurityOptions(sslContext);
}
}
In the connection URL, use xccs instead of xcc.
You can also look at https://github.com/marklogic/xqsync/blob/1cf82faa2fa2e7fb3fa06f41e0938bf5b002b7fa/src/java/com/marklogic/ps/Connection.java#L100 to see an example that handles both xcc and xccs.