Skip to content

Commit

Permalink
Merge pull request #87 from harlem88/fw-1.0-ssl
Browse files Browse the repository at this point in the history
Forward changes from release 1.0 to 1.1
  • Loading branch information
lucaato authored Oct 3, 2024
2 parents 059db09 + 2e7720f commit 294e039
Show file tree
Hide file tree
Showing 11 changed files with 150 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@ public class AstartePairingHandler {

private Certificate m_certificate;

private boolean ignoreSSLErrors;

public AstartePairingHandler(
String pairingUrl,
String astarteRealm,
String deviceId,
String credentialSecret,
AstarteCryptoStore cryptoStore) {
AstarteCryptoStore cryptoStore,
boolean ignoreSSLErrors) {
m_astarteRealm = astarteRealm;
m_deviceId = deviceId;
m_credentialSecret = credentialSecret;
Expand All @@ -31,6 +34,8 @@ public AstartePairingHandler(
m_AstartePairingService = new AstartePairingService(pairingUrl, astarteRealm);

m_certificate = m_cryptoStore.getCertificate();

this.ignoreSSLErrors = ignoreSSLErrors;
}

public void init() throws AstartePairingException {
Expand Down Expand Up @@ -74,7 +79,8 @@ public boolean isCertificateAvailable() {

private void reloadTransports() throws AstartePairingException {
m_transports =
m_AstartePairingService.reloadTransports(m_credentialSecret, m_cryptoStore, m_deviceId);
m_AstartePairingService.reloadTransports(
m_credentialSecret, m_cryptoStore, m_deviceId, ignoreSSLErrors);
}

public void requestNewCertificate() throws AstartePairingException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,10 @@ public String registerDevice(String jwtToken, String deviceId)
}

protected List<AstarteTransport> reloadTransports(
String credentialSecret, AstarteCryptoStore cryptoStore, String deviceId)
String credentialSecret,
AstarteCryptoStore cryptoStore,
String deviceId,
boolean ignoreSSLErrors)
throws AstartePairingException {
// Build the request URL for Astarte MQTT v1
HttpUrl requestUrl;
Expand Down Expand Up @@ -161,7 +164,8 @@ protected List<AstarteTransport> reloadTransports(
m_astarteRealm,
deviceId,
transportObjects.getJSONObject(key),
cryptoStore);
cryptoStore,
ignoreSSLErrors);
transports.add(supportedTransport);
} catch (Exception e) {
e.printStackTrace();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public interface AstarteCryptoStore {

String generateCSR(String directoryString) throws IOException, OperatorCreationException;

SSLSocketFactory getSSLSocketFactory()
SSLSocketFactory getSSLSocketFactory(boolean ignoreSSLErrors)
throws KeyManagementException, NoSuchAlgorithmException, CertificateException,
KeyStoreException, IOException;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.astarteplatform.devicesdk.transport;

import javax.net.ssl.*;
import org.astarteplatform.devicesdk.crypto.AstarteCryptoStore;
import org.astarteplatform.devicesdk.protocol.AstarteProtocolType;
import org.astarteplatform.devicesdk.transport.mqtt.AstarteMqttV1Transport;
Expand All @@ -12,7 +13,8 @@ public static AstarteTransport createAstarteTransportFromPairing(
String astarteRealm,
String deviceId,
JSONObject protocolData,
AstarteCryptoStore cryptoStore) {
AstarteCryptoStore cryptoStore,
boolean ignoreSSLErrors) {
switch (protocolType) {
case ASTARTE_MQTT_V1:
try {
Expand All @@ -22,7 +24,11 @@ public static AstarteTransport createAstarteTransportFromPairing(
}
return new AstarteMqttV1Transport(
new MutualSSLAuthenticationMqttConnectionInfo(
brokerUrl, astarteRealm, deviceId, cryptoStore.getSSLSocketFactory()));
brokerUrl,
astarteRealm,
deviceId,
cryptoStore.getSSLSocketFactory(ignoreSSLErrors),
ignoreSSLErrors));
} catch (Exception e) {
e.printStackTrace();
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ public class MutualSSLAuthenticationMqttConnectionInfo implements MqttConnection
private final String m_clientId;

public MutualSSLAuthenticationMqttConnectionInfo(
String brokerUrl, String astarteRealm, String deviceId, SSLSocketFactory sslSocketFactory) {
String brokerUrl,
String astarteRealm,
String deviceId,
SSLSocketFactory sslSocketFactory,
boolean ignoreSSLErrors) {
m_brokerUrl = brokerUrl;
m_mqttConnectOptions = new MqttConnectOptions();
m_mqttConnectOptions.setConnectionTimeout(60);
Expand All @@ -24,6 +28,9 @@ public MutualSSLAuthenticationMqttConnectionInfo(
} catch (Exception e) {
e.printStackTrace();
}
if (ignoreSSLErrors) {
m_mqttConnectOptions.setHttpsHostnameVerificationEnabled(false);
}
m_clientId = astarteRealm + "/" + deviceId;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,10 @@ public String generateCSR(String directoryString) throws IOException, OperatorCr
}

@Override
public SSLSocketFactory getSSLSocketFactory()
public SSLSocketFactory getSSLSocketFactory(boolean ignoreSSLErrors)
throws KeyManagementException, NoSuchAlgorithmException, CertificateException,
KeyStoreException, IOException {
return new AstarteAndroidMutualSSLSocketFactory();
return new AstarteAndroidMutualSSLSocketFactory(ignoreSSLErrors);
}

private String csrToString(PKCS10CertificationRequest csr) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,33 @@ public AstarteAndroidDevice(
String pairingBaseUrl,
Context context)
throws JSONException, AstarteInvalidInterfaceException {
this(
deviceId,
astarteRealm,
credentialSecret,
interfaceProvider,
pairingBaseUrl,
context,
false);
}

public AstarteAndroidDevice(
String deviceId,
String astarteRealm,
String credentialSecret,
AstarteInterfaceProvider interfaceProvider,
String pairingBaseUrl,
Context context,
boolean ignoreSSLErrors)
throws JSONException, AstarteInvalidInterfaceException {
super(
new AstartePairingHandler(
pairingBaseUrl,
astarteRealm,
deviceId,
credentialSecret,
new AstarteAndroidCryptoStore()),
new AstarteAndroidCryptoStore(),
ignoreSSLErrors),
new AstarteAndroidPropertyStorage(context, "astarte.property_store." + deviceId),
new AstarteAndroidFailedMessageStorage(
AstarteAndroidRoomDatabase.getDatabase(context).astarteFailedMessageDao()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,43 @@
import java.security.PrivateKey;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509ExtendedKeyManager;
import javax.net.ssl.*;

class AstarteAndroidMutualSSLSocketFactory extends SSLSocketFactory {
private SSLSocketFactory internalSSLSocketFactory;

public AstarteAndroidMutualSSLSocketFactory()
public AstarteAndroidMutualSSLSocketFactory(boolean ignoreSSLErrors)
throws KeyManagementException, NoSuchAlgorithmException, CertificateException,
KeyStoreException, IOException {
// CA certificate is used to authenticate server
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore caStore = KeyStore.getInstance("AndroidCAStore");
caStore.load(null);
trustManagerFactory.init(caStore);
TrustManager[] trustManagers;
if (ignoreSSLErrors) {
TrustManager[] trustAllCerts =
new TrustManager[] {
new X509TrustManager() {
@Override
public void checkClientTrusted(

Check warning on line 28 in DeviceSDKAndroid/src/main/java/org/astarteplatform/devicesdk/android/AstarteAndroidMutualSSLSocketFactory.java

View workflow job for this annotation

GitHub Actions / lint

Insecure TLS/SSL trust manager: `checkClientTrusted` is empty, which could cause insecure network traffic due to trusting arbitrary TLS/SSL certificates presented by peers
java.security.cert.X509Certificate[] chain, String authType) {}

@Override
public void checkServerTrusted(

Check warning on line 32 in DeviceSDKAndroid/src/main/java/org/astarteplatform/devicesdk/android/AstarteAndroidMutualSSLSocketFactory.java

View workflow job for this annotation

GitHub Actions / lint

Insecure TLS/SSL trust manager: `checkServerTrusted` is empty, which could cause insecure network traffic due to trusting arbitrary TLS/SSL certificates presented by peers
java.security.cert.X509Certificate[] chain, String authType) {}

@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[] {};
}
}
};
trustManagers = trustAllCerts;
} else {
// CA certificate is used to authenticate server
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore caStore = KeyStore.getInstance("AndroidCAStore");
caStore.load(null);
trustManagerFactory.init(caStore);
trustManagers = trustManagerFactory.getTrustManagers();
}

// client key and certificates are sent to server so it can authenticate us
final KeyStore androidKeyStore = KeyStore.getInstance("AndroidKeyStore");
Expand Down Expand Up @@ -84,7 +102,7 @@ public PrivateKey getPrivateKey(String alias) {

// finally, create SSL socket factory
SSLContext context = SSLContext.getInstance("TLSv1.2");
context.init(new KeyManager[] {keyManager}, trustManagerFactory.getTrustManagers(), null);
context.init(new KeyManager[] {keyManager}, trustManagers, null);

internalSSLSocketFactory = context.getSocketFactory();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,11 @@ public String generateCSR(String directoryString) throws IOException, OperatorCr
}

@Override
public SSLSocketFactory getSSLSocketFactory()
public SSLSocketFactory getSSLSocketFactory(boolean ignoreSSLErrors)
throws KeyManagementException, NoSuchAlgorithmException, CertificateException,
KeyStoreException, IOException {
if (m_socketFactory == null) {
m_socketFactory = new AstarteGenericMutualSSLSocketFactory(this);
m_socketFactory = new AstarteGenericMutualSSLSocketFactory(this, ignoreSSLErrors);
}

return m_socketFactory;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,26 @@ public AstarteGenericDevice(
ConnectionSource connectionSource)
throws JSONException, AstarteInvalidInterfaceException, AstartePropertyStorageException,
SQLException {
this(
deviceId,
astarteRealm,
credentialSecret,
interfaceProvider,
pairingBaseUrl,
connectionSource,
false);
}

public AstarteGenericDevice(
String deviceId,
String astarteRealm,
String credentialSecret,
AstarteInterfaceProvider interfaceProvider,
String pairingBaseUrl,
ConnectionSource connectionSource,
boolean ignoreSSLErrors)
throws JSONException, AstarteInvalidInterfaceException, AstartePropertyStorageException,
SQLException {
this(
deviceId,
astarteRealm,
Expand All @@ -31,7 +51,8 @@ public AstarteGenericDevice(
new AstarteGenericPropertyStorage(
DaoManager.createDao(connectionSource, AstarteGenericPropertyEntry.class)),
new AstarteGenericFailedMessageStorage(
DaoManager.createDao(connectionSource, AstarteGenericFailedMessage.class)));
DaoManager.createDao(connectionSource, AstarteGenericFailedMessage.class)),
ignoreSSLErrors);
}

public AstarteGenericDevice(
Expand All @@ -41,15 +62,17 @@ public AstarteGenericDevice(
AstarteInterfaceProvider interfaceProvider,
String pairingBaseUrl,
AstartePropertyStorage propertyStorage,
AstarteFailedMessageStorage failedMessageStorage)
AstarteFailedMessageStorage failedMessageStorage,
boolean ignoreSSLErrors)
throws JSONException, AstarteInvalidInterfaceException {
super(
new AstartePairingHandler(
pairingBaseUrl,
astarteRealm,
deviceId,
credentialSecret,
new AstarteGenericCryptoStore()),
new AstarteGenericCryptoStore(),
ignoreSSLErrors),
propertyStorage,
failedMessageStorage,
interfaceProvider);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,49 @@
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509ExtendedKeyManager;
import javax.net.ssl.*;

class AstarteGenericMutualSSLSocketFactory extends SSLSocketFactory {
private SSLSocketFactory internalSSLSocketFactory;
private AstarteGenericCryptoStore mCryptoStore;

public AstarteGenericMutualSSLSocketFactory(AstarteGenericCryptoStore cryptoStore)
public AstarteGenericMutualSSLSocketFactory(
AstarteGenericCryptoStore cryptoStore, boolean ignoreSSLErrors)
throws KeyManagementException, NoSuchAlgorithmException, CertificateException,
KeyStoreException, IOException {
// CA certificate is used to authenticate server
String caFile = System.getProperty("java.home") + "/lib/security/cacerts";
KeyStore caStore = KeyStore.getInstance(KeyStore.getDefaultType());
try (InputStream is = Files.newInputStream(Paths.get(caFile))) {
caStore.load(is, null);
TrustManager[] trustManagers;
if (ignoreSSLErrors) {
TrustManager[] trustAllCerts =
new TrustManager[] {
new X509TrustManager() {
@Override
public void checkClientTrusted(
java.security.cert.X509Certificate[] chain, String authType) {}

@Override
public void checkServerTrusted(
java.security.cert.X509Certificate[] chain, String authType) {}

@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[] {};
}
}
};
trustManagers = trustAllCerts;
} else {
// CA certificate is used to authenticate server
String caFile = System.getProperty("java.home") + "/lib/security/cacerts";
KeyStore caStore = KeyStore.getInstance(KeyStore.getDefaultType());
try (InputStream is = Files.newInputStream(Paths.get(caFile))) {
caStore.load(is, null);
}

TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(caStore);
trustManagers = trustManagerFactory.getTrustManagers();
}
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(caStore);

mCryptoStore = cryptoStore;

Expand Down Expand Up @@ -82,7 +102,7 @@ public PrivateKey getPrivateKey(String alias) {

// finally, create SSL socket factory
SSLContext context = SSLContext.getInstance("TLSv1.2");
context.init(new KeyManager[] {keyManager}, trustManagerFactory.getTrustManagers(), null);
context.init(new KeyManager[] {keyManager}, trustManagers, null);

internalSSLSocketFactory = context.getSocketFactory();
}
Expand Down

0 comments on commit 294e039

Please sign in to comment.