diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6a28b65b4b..221a102ba8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ diff --git a/app/src/main/java/org/flyve/mdm/agent/core/deeplink/DeeplinkModel.java b/app/src/main/java/org/flyve/mdm/agent/core/deeplink/DeeplinkModel.java index bf890190bf..d2ddc207c4 100644 --- a/app/src/main/java/org/flyve/mdm/agent/core/deeplink/DeeplinkModel.java +++ b/app/src/main/java/org/flyve/mdm/agent/core/deeplink/DeeplinkModel.java @@ -152,11 +152,9 @@ public void saveSupervisor(Context context, String name, String phone, String we @Override public void saveMQTTConfig(Context context, String url, String userToken, String invitationToken) { MqttData cache = new MqttData(context); - if(cache.getUrl().isEmpty()) { - cache.setUrl(url); - cache.setUserToken(userToken); - cache.setInvitationToken(invitationToken); - } + cache.setUrl(url); + cache.setUserToken(userToken); + cache.setInvitationToken(invitationToken); } @Override diff --git a/app/src/main/java/org/flyve/mdm/agent/core/mqtt/MqttModel.java b/app/src/main/java/org/flyve/mdm/agent/core/mqtt/MqttModel.java index 5276785425..04565d8363 100644 --- a/app/src/main/java/org/flyve/mdm/agent/core/mqtt/MqttModel.java +++ b/app/src/main/java/org/flyve/mdm/agent/core/mqtt/MqttModel.java @@ -34,6 +34,7 @@ import org.eclipse.paho.client.mqttv3.MqttCallback; import org.eclipse.paho.client.mqttv3.MqttClient; import org.eclipse.paho.client.mqttv3.MqttConnectOptions; +import org.eclipse.paho.client.mqttv3.MqttException; import org.eclipse.paho.client.mqttv3.MqttMessage; import org.flyve.mdm.agent.R; import org.flyve.mdm.agent.core.CommonErrorType; @@ -84,14 +85,24 @@ import org.flyve.mdm.agent.utils.Helpers; import org.json.JSONArray; import org.json.JSONObject; + +import java.security.KeyStore; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; import java.util.Date; +import java.util.Enumeration; import java.util.Timer; import java.util.TimerTask; +import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; public class MqttModel implements mqtt.Model { + + private static int mqttModelInstanceCount = 0; + private static final String QUERY = "query"; private mqtt.Presenter presenter; @@ -105,9 +116,10 @@ public class MqttModel implements mqtt.Model { private long timeLastReconnection = 0; private Boolean executeConnection = true; private int tryEverySeconds = 30; - ; + private static int mqtt_object_count = 0; public MqttModel(mqtt.Presenter presenter) { + mqttModelInstanceCount++; this.presenter = presenter; } @@ -133,7 +145,11 @@ public void sendInventory(Context context) { @Override public void connect(final Context context, final MqttCallback callback) { // if the device is connected exit + + + FlyveLog.d("MQTT Model connect method call: modelCount " + mqttModelInstanceCount); if(getMqttClient()!=null && getMqttClient().isConnected()) { + setStatus(context, callback, true); return; } @@ -163,18 +179,32 @@ public void connect(final Context context, final MqttCallback callback) { } String clientId; - try { - clientId = MqttClient.generateClientId(); - client = new MqttAndroidClient(context, protocol + "://" + mBroker + ":" + mPort, clientId); - } catch (ExceptionInInitializerError ex) { - showDetailError(context, CommonErrorType.MQTT_IN_INITIALIZER_ERROR, ex.getMessage()); - reconnect(context, callback); - return; - } + MqttConnectOptions options; - client.setCallback( callback ); + if(client==null) { + mqtt_object_count++; + FlyveLog.d("MQTT Connect Call Count (connect): " + mqtt_object_count); + try { + clientId = MqttClient.generateClientId(); + client = new MqttAndroidClient(context, protocol + "://" + mBroker + ":" + mPort, clientId); + } catch (ExceptionInInitializerError ex) { + showDetailError(context, CommonErrorType.MQTT_IN_INITIALIZER_ERROR, ex.getMessage()); + reconnect(context, callback); + return; + } + + client.setCallback(callback); + } else { + //May be here ? + try{ + FlyveLog.d("MQTT Model Connect Methodd: Forcing disconnect ..."); + client.disconnect(); + FlyveLog.d("MQTT Model Connect Methodd: Forcing disconnect done"); + } catch (MqttException mqttException){ + FlyveLog.d("MQTT Model Connect Methodd: Error while Forcing disconnect ..." + mqttException.getMessage(), mqttException); + } + } - MqttConnectOptions options; try { options = new MqttConnectOptions(); options.setPassword(mPassword.toCharArray()); @@ -190,9 +220,37 @@ public void connect(final Context context, final MqttCallback callback) { // If TLS is active needs ssl connection option if (mTLS.equals("1")) { + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + + KeyStore caKeyStore = KeyStore.getInstance(KeyStore.getDefaultType()); + caKeyStore.load(null, null); + + CertificateFactory certificationFactory = CertificateFactory.getInstance("X.509"); + X509Certificate ca = (X509Certificate) certificationFactory.generateCertificate(context.getResources().openRawResource(R.raw.flyve_org)); + String alias = ca.getSubjectX500Principal().getName(); + + // Set propper alias name + caKeyStore.setCertificateEntry(alias, ca); + trustManagerFactory.init(caKeyStore); + + FlyveLog.v("Certificate Owner: %s", ca.getSubjectDN().toString()); + FlyveLog.v("Certificate Issuer: %s", ca.getIssuerDN().toString()); + FlyveLog.v("Certificate Serial Number: %s", ca.getSerialNumber().toString()); + FlyveLog.v("Certificate Algorithm: %s", ca.getSigAlgName()); + FlyveLog.v("Certificate Version: %s", ca.getVersion()); + FlyveLog.v("Certificate OID: %s", ca.getSigAlgOID()); + Enumeration aliasesCA = caKeyStore.aliases(); + for (; aliasesCA.hasMoreElements(); ) { + String o = aliasesCA.nextElement(); + FlyveLog.v("Alias: %s isKeyEntry:%s isCertificateEntry:%s", o, caKeyStore.isKeyEntry(o), caKeyStore.isCertificateEntry(o)); + } + + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("X509"); + keyManagerFactory.init(null,null); + // SSL - SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); - sslContext.init(null, null, null); + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); options.setSocketFactory(sslContext.getSocketFactory()); } } catch (Exception ex) { @@ -200,6 +258,7 @@ public void connect(final Context context, final MqttCallback callback) { return; } + try { IMqttToken token = client.connect(options); token.setActionCallback(new IMqttActionListener() { @@ -208,6 +267,9 @@ public void onSuccess(IMqttToken asyncActionToken) { // We are connected setStatus(context, callback, true); + // set the reconnection counter to 0 + reconnectionCounter = 0; + // Everything ready waiting for message PoliciesController policiesController = new PoliciesController(context, client); @@ -259,6 +321,7 @@ public void run() { executeConnection = true; } else { executeConnection = false; + return; } } else { timeLastReconnection = new Date().getTime(); @@ -268,11 +331,6 @@ public void run() { if(!isConnected()) { if(executeConnection) { reconnectionCounter++; - - if((reconnectionCounter % 10)==0) { - tryEverySeconds *= 2; - } - String message = "Reconnecting " + reconnectionCounter + " times"; if(new AppData(context).getEnableNotificationConnection()) { @@ -280,7 +338,6 @@ public void run() { } FlyveLog.d(message); - connect(context, callback); } } else { diff --git a/app/src/main/java/org/flyve/mdm/agent/core/mqtt/MqttPresenter.java b/app/src/main/java/org/flyve/mdm/agent/core/mqtt/MqttPresenter.java index cd7c14cb90..2cafeb4d14 100644 --- a/app/src/main/java/org/flyve/mdm/agent/core/mqtt/MqttPresenter.java +++ b/app/src/main/java/org/flyve/mdm/agent/core/mqtt/MqttPresenter.java @@ -32,10 +32,14 @@ public class MqttPresenter implements mqtt.Presenter { + + private static int mqttPresenterInstanceCount = 0; + private mqtt.View view; private mqtt.Model model; public MqttPresenter(mqtt.View view){ + mqttPresenterInstanceCount++; this.view = view; model = new MqttModel(this); } diff --git a/app/src/main/java/org/flyve/mdm/agent/policies/AirplaneModePolicy.java b/app/src/main/java/org/flyve/mdm/agent/policies/AirplaneModePolicy.java index 368d51f839..7e9c16a36a 100644 --- a/app/src/main/java/org/flyve/mdm/agent/policies/AirplaneModePolicy.java +++ b/app/src/main/java/org/flyve/mdm/agent/policies/AirplaneModePolicy.java @@ -44,7 +44,7 @@ public AirplaneModePolicy(Context context) { protected boolean process() { try { boolean disable = Boolean.parseBoolean(this.policyValue.toString()); - PoliciesConnectivity.disableRoaming(disable); + PoliciesConnectivity.disableAirplaneMode(disable); return true; } catch (Exception ex) { FlyveLog.e(ex.getMessage()); diff --git a/app/src/main/java/org/flyve/mdm/agent/services/MQTTService.java b/app/src/main/java/org/flyve/mdm/agent/services/MQTTService.java index 2f3065235a..0f8daa68a1 100644 --- a/app/src/main/java/org/flyve/mdm/agent/services/MQTTService.java +++ b/app/src/main/java/org/flyve/mdm/agent/services/MQTTService.java @@ -41,6 +41,10 @@ * This is the service get and send message from MQTT */ public class MQTTService extends Service implements MqttCallback, mqtt.View { + + private static int instanceCount = 0; + private static int connectCount = 0; + private mqtt.Presenter presenter; IBinder mBinder = new LocalBinder(); @@ -59,6 +63,10 @@ public static Intent start(Context context) { */ public MQTTService() { FlyveLog.d("MQTT Service Constructor"); + + instanceCount++; + FlyveLog.d("MQTT Service Constructor " + instanceCount); + presenter = new MqttPresenter(this); } @@ -95,6 +103,9 @@ public IBinder onBind(Intent intent) { public int onStartCommand(Intent intent, int flags, int startId) { super.onStartCommand(intent, flags, startId); + connectCount++; + FlyveLog.d("MQTT Service Connect Call Count (onStartCommand): " + connectCount + "(instance count: " + instanceCount + ")"); + presenter.connect(getApplicationContext(), MQTTService.this); return START_STICKY; } diff --git a/app/src/main/java/org/flyve/mdm/agent/ui/MainActivity.java b/app/src/main/java/org/flyve/mdm/agent/ui/MainActivity.java index 33e901391b..c31e31d1e8 100644 --- a/app/src/main/java/org/flyve/mdm/agent/ui/MainActivity.java +++ b/app/src/main/java/org/flyve/mdm/agent/ui/MainActivity.java @@ -59,21 +59,6 @@ public class MainActivity extends AppCompatActivity { private Intent mServiceIntent; private AppData cache; - /** - * Perform the final clenup before the activity is destroyed - */ - @Override - public void onDestroy() { - // stop the service - if(mServiceIntent!=null) { - stopService(mServiceIntent); - } - - FlyveLog.i("onDestroy!"); - - super.onDestroy(); - } - /** * Called when the activity is starting * @param savedInstanceState if the activity is being re-initialized, it contains the data it most recently supplied diff --git a/app/src/main/res/raw/flyve_org.crt b/app/src/main/res/raw/flyve_org.crt new file mode 100644 index 0000000000..5a3a086a00 --- /dev/null +++ b/app/src/main/res/raw/flyve_org.crt @@ -0,0 +1,106 @@ +-----BEGIN CERTIFICATE----- +MIIGSTCCBTGgAwIBAgIRANqLnfa49y3i8XwRhca1euswDQYJKoZIhvcNAQELBQAw +gZAxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO +BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTYwNAYD +VQQDEy1DT01PRE8gUlNBIERvbWFpbiBWYWxpZGF0aW9uIFNlY3VyZSBTZXJ2ZXIg +Q0EwHhcNMTgwMjI4MDAwMDAwWhcNMTkwMjI4MjM1OTU5WjBYMSEwHwYDVQQLExhE +b21haW4gQ29udHJvbCBWYWxpZGF0ZWQxHTAbBgNVBAsTFFBvc2l0aXZlU1NMIFdp +bGRjYXJkMRQwEgYDVQQDDAsqLmZseXZlLm9yZzCCAiIwDQYJKoZIhvcNAQEBBQAD +ggIPADCCAgoCggIBANt/hIavXeSdpFIwEr8gijqQfoosbPqjXGIEbqJ3oFLtSgeM +UQXTZQ7mnxFRBegXqMHV2w2hum56zM89v/Yw17W/9OW3kro4za/et9kY6bkesqOp +Sz5jh2uB2behWIWHabaNhjOWS+vralu2t4xka4/T8zhVMtheIyHpCvjZmiQ1iHuA +w3O8uThjt9Axott7sQxTN+4ipg/Q9dvFs3I0KPoNQpFcBuSUgbH+5HW+u95LC2Xw +CI3xEZOHmUYdVzbo3a2/Tpfp4mRaCYyoBuV8vvSnYWV6DpMDIUbiAf4Om5bmoXJn +HhUKE4FwcrNY/UBPiokBW64egec6YoljMR2RGPirbc7sHiNXM3aDiht/S/Bf0FA0 +NVgTHvmy+LtRlYlijQr9lnLlaKpEpBNENc3ErSPbUOQi4Qm3KvDVoZHqJ7Rj9iNi +be8RMP6PuPVD4oy2j03aUjr3nlWD290KlcNLLcr+Zvlwn/10hA2OjnA7Gc5ABImm +khBRIlUlmjNZdVElEPZDRnx2lX12sxOFrDhumdaeSTO6yo+l9sGA4EbFpurVnhEQ +M6HuviXVMn6ue+Nqc/MiiIA2N2o4zVMPrhio+hGTFbz6mIomwKGnfacUGPTSFlP7 +acD79HjCHPybyOY1s9WuI8z8vvBVPZLHLzY6nATCyI4BH50cgM+ScmSBIyLvAgMB +AAGjggHTMIIBzzAfBgNVHSMEGDAWgBSQr2o6lFoL2JDqElZz30O0Oija5zAdBgNV +HQ4EFgQU9ZzpVuXIHDaLHeZ+r0X7hg6WMUUwDgYDVR0PAQH/BAQDAgWgMAwGA1Ud +EwEB/wQCMAAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCME8GA1UdIARI +MEYwOgYLKwYBBAGyMQECAgcwKzApBggrBgEFBQcCARYdaHR0cHM6Ly9zZWN1cmUu +Y29tb2RvLmNvbS9DUFMwCAYGZ4EMAQIBMFQGA1UdHwRNMEswSaBHoEWGQ2h0dHA6 +Ly9jcmwuY29tb2RvY2EuY29tL0NPTU9ET1JTQURvbWFpblZhbGlkYXRpb25TZWN1 +cmVTZXJ2ZXJDQS5jcmwwgYUGCCsGAQUFBwEBBHkwdzBPBggrBgEFBQcwAoZDaHR0 +cDovL2NydC5jb21vZG9jYS5jb20vQ09NT0RPUlNBRG9tYWluVmFsaWRhdGlvblNl +Y3VyZVNlcnZlckNBLmNydDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2Rv +Y2EuY29tMCEGA1UdEQQaMBiCCyouZmx5dmUub3JngglmbHl2ZS5vcmcwDQYJKoZI +hvcNAQELBQADggEBAAlsg691Yr/7nbDJs9R8CbHG8MUsSO5hiF41BryLMltXzuuy +8cxl5m7JqOomgwCMisbffEhg2qx6J7Ex0Fk8oSDo46EE9BqnKa3pA/mHY/7ETZmZ +IYvIQlTWzsOEazrjQ5Ur6rKCsXL3PGYzZ2OAqAZT1dFG7awP6w1w+kR0O/56R9s+ +/jdZHN2sYEic5fRERvCjW4g7hctI0+rr1ZpquRSlwtz7141uXXhiUzW+vO5WPYMa +DomLkVJg9IiRK5ruSdMTg5qrjMMKnM6RSrFcYxjo87mvZ3vqccKOmPcjY7bb3KIg +fXofENTHa9VGol8ieitiFIVi4TiPBP9JpTXXEtc= +-----END CERTIFICATE----- + +-----BEGIN CERTIFICATE----- +MIIGCDCCA/CgAwIBAgIQKy5u6tl1NmwUim7bo3yMBzANBgkqhkiG9w0BAQwFADCB +hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G +A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV +BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTQwMjEy +MDAwMDAwWhcNMjkwMjExMjM1OTU5WjCBkDELMAkGA1UEBhMCR0IxGzAZBgNVBAgT +EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR +Q09NT0RPIENBIExpbWl0ZWQxNjA0BgNVBAMTLUNPTU9ETyBSU0EgRG9tYWluIFZh +bGlkYXRpb24gU2VjdXJlIFNlcnZlciBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBAI7CAhnhoFmk6zg1jSz9AdDTScBkxwtiBUUWOqigwAwCfx3M28Sh +bXcDow+G+eMGnD4LgYqbSRutA776S9uMIO3Vzl5ljj4Nr0zCsLdFXlIvNN5IJGS0 +Qa4Al/e+Z96e0HqnU4A7fK31llVvl0cKfIWLIpeNs4TgllfQcBhglo/uLQeTnaG6 +ytHNe+nEKpooIZFNb5JPJaXyejXdJtxGpdCsWTWM/06RQ1A/WZMebFEh7lgUq/51 +UHg+TLAchhP6a5i84DuUHoVS3AOTJBhuyydRReZw3iVDpA3hSqXttn7IzW3uLh0n +c13cRTCAquOyQQuvvUSH2rnlG51/ruWFgqUCAwEAAaOCAWUwggFhMB8GA1UdIwQY +MBaAFLuvfgI9+qbxPISOre44mOzZMjLUMB0GA1UdDgQWBBSQr2o6lFoL2JDqElZz +30O0Oija5zAOBgNVHQ8BAf8EBAMCAYYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNV +HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwGwYDVR0gBBQwEjAGBgRVHSAAMAgG +BmeBDAECATBMBgNVHR8ERTBDMEGgP6A9hjtodHRwOi8vY3JsLmNvbW9kb2NhLmNv +bS9DT01PRE9SU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDBxBggrBgEFBQcB +AQRlMGMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9E +T1JTQUFkZFRydXN0Q0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21v +ZG9jYS5jb20wDQYJKoZIhvcNAQEMBQADggIBAE4rdk+SHGI2ibp3wScF9BzWRJ2p +mj6q1WZmAT7qSeaiNbz69t2Vjpk1mA42GHWx3d1Qcnyu3HeIzg/3kCDKo2cuH1Z/ +e+FE6kKVxF0NAVBGFfKBiVlsit2M8RKhjTpCipj4SzR7JzsItG8kO3KdY3RYPBps +P0/HEZrIqPW1N+8QRcZs2eBelSaz662jue5/DJpmNXMyYE7l3YphLG5SEXdoltMY +dVEVABt0iN3hxzgEQyjpFv3ZBdRdRydg1vs4O2xyopT4Qhrf7W8GjEXCBgCq5Ojc +2bXhc3js9iPc0d1sjhqPpepUfJa3w/5Vjo1JXvxku88+vZbrac2/4EjxYoIQ5QxG +V/Iz2tDIY+3GH5QFlkoakdH368+PUq4NCNk+qKBR6cGHdNXJ93SrLlP7u3r7l+L4 +HyaPs9Kg4DdbKDsx5Q5XLVq4rXmsXiBmGqW5prU5wfWYQ//u+aen/e7KJD2AFsQX +j4rBYKEMrltDR5FL1ZoXX/nUh8HCjLfn4g8wGTeGrODcQgPmlKidrv0PJFGUzpII +0fxQ8ANAe4hZ7Q7drNJ3gjTcBpUC2JD5Leo31Rpg0Gcg19hCC0Wvgmje3WYkN5Ap +lBlGGSW4gNfL1IYoakRwJiNiqZ+Gb7+6kHDSVneFeO/qJakXzlByjAA6quPbYzSf ++AZxAeKCINT+b72x +-----END CERTIFICATE----- + +-----BEGIN CERTIFICATE----- +MIIFdDCCBFygAwIBAgIQJ2buVutJ846r13Ci/ITeIjANBgkqhkiG9w0BAQwFADBv +MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFk +ZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBF +eHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFow +gYUxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO +BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMSswKQYD +VQQDEyJDT01PRE8gUlNBIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkq +hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAkehUktIKVrGsDSTdxc9EZ3SZKzejfSNw +AHG8U9/E+ioSj0t/EFa9n3Byt2F/yUsPF6c947AEYe7/EZfH9IY+Cvo+XPmT5jR6 +2RRr55yzhaCCenavcZDX7P0N+pxs+t+wgvQUfvm+xKYvT3+Zf7X8Z0NyvQwA1onr +ayzT7Y+YHBSrfuXjbvzYqOSSJNpDa2K4Vf3qwbxstovzDo2a5JtsaZn4eEgwRdWt +4Q08RWD8MpZRJ7xnw8outmvqRsfHIKCxH2XeSAi6pE6p8oNGN4Tr6MyBSENnTnIq +m1y9TBsoilwie7SrmNnu4FGDwwlGTm0+mfqVF9p8M1dBPI1R7Qu2XK8sYxrfV8g/ +vOldxJuvRZnio1oktLqpVj3Pb6r/SVi+8Kj/9Lit6Tf7urj0Czr56ENCHonYhMsT +8dm74YlguIwoVqwUHZwK53Hrzw7dPamWoUi9PPevtQ0iTMARgexWO/bTouJbt7IE +IlKVgJNp6I5MZfGRAy1wdALqi2cVKWlSArvX31BqVUa/oKMoYX9w0MOiqiwhqkfO +KJwGRXa/ghgntNWutMtQ5mv0TIZxMOmm3xaG4Nj/QN370EKIf6MzOi5cHkERgWPO +GHFrK+ymircxXDpqR+DDeVnWIBqv8mqYqnK8V0rSS527EPywTEHl7R09XiidnMy/ +s1Hap0flhFMCAwEAAaOB9DCB8TAfBgNVHSMEGDAWgBStvZh6NLQm9/rEJlTvA73g +JMtUGjAdBgNVHQ4EFgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQD +AgGGMA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0gBAowCDAGBgRVHSAAMEQGA1UdHwQ9 +MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9BZGRUcnVzdEV4dGVy +bmFsQ0FSb290LmNybDA1BggrBgEFBQcBAQQpMCcwJQYIKwYBBQUHMAGGGWh0dHA6 +Ly9vY3NwLnVzZXJ0cnVzdC5jb20wDQYJKoZIhvcNAQEMBQADggEBAGS/g/FfmoXQ +zbihKVcN6Fr30ek+8nYEbvFScLsePP9NDXRqzIGCJdPDoCpdTPW6i6FtxFQJdcfj +Jw5dhHk3QBN39bSsHNA7qxcS1u80GH4r6XnTq1dFDK8o+tDb5VCViLvfhVdpfZLY +Uspzgb8c8+a4bmYRBbMelC1/kZWSWfFMzqORcUx8Rww7Cxn2obFshj5cqsQugsv5 +B5a6SE2Q8pTIqXOi6wZ7I53eovNNVZ96YUWYGGjHXkBrI/V5eu+MtWuLt29G9Hvx +PUsE2JOAWVrgQSQdso8VYFhH2+9uRv0V9dlfmrPb2LjkQLPNlzmuhbsdjrzch5vR +pu/xO28QOG8= +-----END CERTIFICATE----- +