integrate trust manager into conversations
This commit is contained in:
parent
89927cee8e
commit
f5854d238e
34 changed files with 163 additions and 619 deletions
61
build.gradle
61
build.gradle
|
@ -30,7 +30,7 @@ allprojects {
|
|||
}
|
||||
|
||||
configurations {
|
||||
standardPushCompile
|
||||
standardPushimplementation
|
||||
}
|
||||
|
||||
ext {
|
||||
|
@ -38,36 +38,35 @@ ext {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
compile project(':libs:MemorizingTrustManager')
|
||||
compile project(':libs:android-transcoder')
|
||||
standardPushCompile 'com.google.android.gms:play-services-gcm:11.8.0'
|
||||
compile 'org.sufficientlysecure:openpgp-api:10.0'
|
||||
compile 'com.soundcloud.android:android-crop:1.0.1@aar'
|
||||
compile 'org.bouncycastle:bcmail-jdk15on:1.58'
|
||||
compile 'org.jitsi:org.otr4j:0.22'
|
||||
compile 'org.gnu.inet:libidn:1.15'
|
||||
compile 'com.google.zxing:core:3.3.0'
|
||||
compile 'de.measite.minidns:minidns-hla:0.2.4'
|
||||
compile 'me.leolin:ShortcutBadger:1.1.21@aar'
|
||||
compile 'com.kyleduo.switchbutton:library:1.2.8'
|
||||
compile 'org.whispersystems:signal-protocol-java:2.6.2'
|
||||
compile 'com.makeramen:roundedimageview:2.3.0'
|
||||
compile 'jetty:javax.servlet:5.1.12'
|
||||
compile 'com.google.code.gson:gson:2.8.0'
|
||||
compile 'com.android.support:multidex:1.0.3'
|
||||
compile "com.android.support:support-v13:$supportLibVersion"
|
||||
compile "com.android.support:appcompat-v7:$supportLibVersion"
|
||||
compile "com.android.support:support-v4:$supportLibVersion"
|
||||
compile "com.android.support:support-emoji:$supportLibVersion"
|
||||
compile "com.android.support:support-emoji-bundled:$supportLibVersion"
|
||||
compile "com.android.support:support-emoji-appcompat:$supportLibVersion"
|
||||
compile "com.android.support:exifinterface:$supportLibVersion"
|
||||
compile 'com.github.bumptech.glide:glide:3.8.0'
|
||||
compile 'com.github.chrisbanes:PhotoView:2.0.0'
|
||||
compile 'com.github.rtoshiro.fullscreenvideoview:fullscreenvideoview:1.1.3'
|
||||
compile 'pub.devrel:easypermissions:1.1.3'
|
||||
compile 'com.wefika:flowlayout:0.4.1'
|
||||
compile 'com.googlecode.ez-vcard:ez-vcard:0.10.3'
|
||||
implementation project(':libs:android-transcoder')
|
||||
standardPushimplementation 'com.google.android.gms:play-services-gcm:11.8.0'
|
||||
implementation 'org.sufficientlysecure:openpgp-api:10.0'
|
||||
implementation 'com.soundcloud.android:android-crop:1.0.1@aar'
|
||||
implementation 'org.bouncycastle:bcmail-jdk15on:1.58'
|
||||
implementation 'org.jitsi:org.otr4j:0.22'
|
||||
implementation 'org.gnu.inet:libidn:1.15'
|
||||
implementation 'com.google.zxing:core:3.3.0'
|
||||
implementation 'de.measite.minidns:minidns-hla:0.2.4'
|
||||
implementation 'me.leolin:ShortcutBadger:1.1.21@aar'
|
||||
implementation 'com.kyleduo.switchbutton:library:1.2.8'
|
||||
implementation 'org.whispersystems:signal-protocol-java:2.6.2'
|
||||
implementation 'com.makeramen:roundedimageview:2.3.0'
|
||||
implementation 'jetty:javax.servlet:5.1.12'
|
||||
implementation 'com.google.code.gson:gson:2.8.0'
|
||||
implementation 'com.android.support:multidex:1.0.3'
|
||||
implementation "com.android.support:support-v13:$supportLibVersion"
|
||||
implementation "com.android.support:appcompat-v7:$supportLibVersion"
|
||||
implementation "com.android.support:support-v4:$supportLibVersion"
|
||||
implementation "com.android.support:support-emoji:$supportLibVersion"
|
||||
implementation "com.android.support:support-emoji-bundled:$supportLibVersion"
|
||||
implementation "com.android.support:support-emoji-appcompat:$supportLibVersion"
|
||||
implementation "com.android.support:exifinterface:$supportLibVersion"
|
||||
implementation 'com.github.bumptech.glide:glide:3.8.0'
|
||||
implementation 'com.github.chrisbanes:PhotoView:2.0.0'
|
||||
implementation 'com.github.rtoshiro.fullscreenvideoview:fullscreenvideoview:1.1.3'
|
||||
implementation 'pub.devrel:easypermissions:1.1.3'
|
||||
implementation 'com.wefika:flowlayout:0.4.1'
|
||||
implementation 'com.googlecode.ez-vcard:ez-vcard:0.10.3'
|
||||
}
|
||||
|
||||
ext {
|
||||
|
|
11
libs/MemorizingTrustManager/.gitignore
vendored
11
libs/MemorizingTrustManager/.gitignore
vendored
|
@ -1,11 +0,0 @@
|
|||
bin
|
||||
build
|
||||
gen
|
||||
local.properties
|
||||
example/bin
|
||||
example/gen
|
||||
tags
|
||||
.project
|
||||
.classpath
|
||||
.gradle
|
||||
.*.swp
|
|
@ -1,12 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="de.duenndns.ssl"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
|
||||
<application android:label="MemorizingTrustManager">
|
||||
<activity
|
||||
android:name="de.duenndns.ssl.MemorizingActivity"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
|
||||
</application>
|
||||
</manifest>
|
|
@ -1,21 +0,0 @@
|
|||
The MIT license.
|
||||
|
||||
Copyright (c) 2010 Georg Lukas <georg@op-co.de>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
|
@ -1,125 +0,0 @@
|
|||
# MemorizingTrustManager - Private Cloud Support for Your App
|
||||
|
||||
MemorizingTrustManager (MTM) is a project to enable smarter and more secure use
|
||||
of SSL on Android. If it encounters an unknown SSL certificate, it asks the
|
||||
user whether to accept the certificate once, permanently or to abort the
|
||||
connection. This is a step in preventing man-in-the-middle attacks by blindly
|
||||
accepting any invalid, self-signed and/or expired certificates.
|
||||
|
||||
MTM is aimed at providing seamless integration into your Android application,
|
||||
and the source code is available under the MIT license.
|
||||
|
||||
## Screenshots
|
||||
|
||||
![MemorizingTrustManager dialog](mtm-screenshot.png)
|
||||
![MemorizingTrustManager notification](mtm-notification.png)
|
||||
![MemorizingTrustManager server name dialog](mtm-servername.png)
|
||||
|
||||
## Status
|
||||
|
||||
MemorizingTrustManager is in production use in the
|
||||
[yaxim XMPP client](https://yaxim.org/). It is usable and easy to integrate,
|
||||
though it does not yet support hostname validation (the Java API makes it
|
||||
**hard** to integrate).
|
||||
|
||||
## Integration
|
||||
|
||||
MTM is easy to integrate into your own application. Follow these steps or have
|
||||
a look into the demo application in the `example` directory.
|
||||
|
||||
### 1. Add MTM to your project
|
||||
|
||||
Download the MTM source from GitHub, or add it as a
|
||||
[git submodule](http://git-scm.com/docs/git-submodule):
|
||||
|
||||
# plain download:
|
||||
git clone https://github.com/ge0rg/MemorizingTrustManager
|
||||
# submodule:
|
||||
git submodule add https://github.com/ge0rg/MemorizingTrustManager
|
||||
|
||||
Then add a library project dependency to `default.properties`:
|
||||
|
||||
android.library.reference.1=MemorizingTrustManager
|
||||
|
||||
### 2. Add the MTM (popup) Activity to your manifest
|
||||
|
||||
Edit your `AndroidManifest.xml` and add the MTM activity element right before the
|
||||
end of your closing `</application>` tag.
|
||||
|
||||
...
|
||||
<activity android:name="de.duenndns.ssl.MemorizingActivity"
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar"
|
||||
/>
|
||||
</application>
|
||||
</manifest>
|
||||
|
||||
### 3. Hook MTM as the default TrustManager for your connection type
|
||||
|
||||
Hooking MemorizingTrustmanager in HTTPS connections:
|
||||
|
||||
// register MemorizingTrustManager for HTTPS
|
||||
SSLContext sc = SSLContext.getInstance("TLS");
|
||||
MemorizingTrustManager mtm = new MemorizingTrustManager(this);
|
||||
sc.init(null, new X509TrustManager[] { mtm }, new java.security.SecureRandom());
|
||||
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
|
||||
HttpsURLConnection.setDefaultHostnameVerifier(
|
||||
mtm.wrapHostnameVerifier(HttpsURLConnection.getDefaultHostnameVerifier()));
|
||||
|
||||
|
||||
Or, for aSmack you can use `setCustomSSLContext()`:
|
||||
|
||||
org.jivesoftware.smack.ConnectionConfiguration connectionConfiguration = …
|
||||
SSLContext sc = SSLContext.getInstance("TLS");
|
||||
MemorizingTrustManager mtm = new MemorizingTrustManager(this);
|
||||
sc.init(null, new X509TrustManager[] { mtm }, new java.security.SecureRandom());
|
||||
connectionConfiguration.setCustomSSLContext(sc);
|
||||
connectionConfiguration.setHostnameVerifier(
|
||||
mtm.wrapHostnameVerifier(new org.apache.http.conn.ssl.StrictHostnameVerifier()));
|
||||
|
||||
By default, MTM falls back to the system `TrustManager` before asking the user.
|
||||
If you do not trust the establishment, you can enforce a dialog on *every new
|
||||
connection* by supplying a `defaultTrustManager = null` parameter to the
|
||||
constructor:
|
||||
|
||||
MemorizingTrustManager mtm = new MemorizingTrustManager(this, null);
|
||||
|
||||
If you want to use a different underlying `TrustManager`, like
|
||||
[AndroidPinning](https://github.com/moxie0/AndroidPinning), just supply that to
|
||||
MTM's constructor:
|
||||
|
||||
X509TrustManager pinning = new PinningTrustManager(SystemKeyStore.getInstance(),
|
||||
new String[] {"f30012bbc18c231ac1a44b788e410ce754182513"}, 0);
|
||||
MemorizingTrustManager mtm = new MemorizingTrustManager(this, pinning);
|
||||
|
||||
### 4. Profit!
|
||||
|
||||
### Logging
|
||||
|
||||
MTM uses java.util.logging (JUL) for logging purposes. If you have not
|
||||
configured a Handler for JUL, then Android will by default log all
|
||||
messages of Level.INFO or higher. In order to get also the debug log
|
||||
messages (those with Level.FINE or lower) you need to configure a
|
||||
Handler accordingly. The MTM example project contains
|
||||
de.duenndns.mtmexample.JULHandler, which allows to enable and disable
|
||||
debug logging at runtime.
|
||||
|
||||
## Alternatives
|
||||
|
||||
MemorizingTrustManager is not the only one out there.
|
||||
|
||||
[**NetCipher**](https://guardianproject.info/code/netcipher/) is an Android
|
||||
library made by the [Guardian Project](https://guardianproject.info/) to
|
||||
improve network security for mobile apps. It comes with a StrongTrustManager
|
||||
to do more thorough certificate checks, an independent Root CA store, and code
|
||||
to easily route your traffic through
|
||||
[the Tor network](https://www.torproject.org/) using [Orbot](https://guardianproject.info/apps/orbot/).
|
||||
|
||||
[**AndroidPinning**](https://github.com/moxie0/AndroidPinning) is another Android
|
||||
library, written by [Moxie Marlinspike](http://www.thoughtcrime.org/) to allow
|
||||
pinning of server certificates, improving security against government-scale
|
||||
MitM attacks. Use this if your app is made to communicate with a specific
|
||||
server!
|
||||
|
||||
## Contribute
|
||||
|
||||
Please [help translating MTM into more languages](https://translations.launchpad.net/yaxim/master/+pots/mtm/)!
|
|
@ -1,14 +0,0 @@
|
|||
# This file is used to override default values used by the Ant build system.
|
||||
#
|
||||
# This file must be checked in Version Control Systems, as it is
|
||||
# integral to the build system of your project.
|
||||
# This file is only used by the Ant script.
|
||||
# You can use this to override default values such as
|
||||
# 'source.dir' for the location of your java source folder and
|
||||
# 'out.dir' for the location of your output folder.
|
||||
# You can also use it define how the release builds are signed by declaring
|
||||
# the following properties:
|
||||
# 'key.store' for the location of your keystore and
|
||||
# 'key.alias' for the name of the key to use.
|
||||
# The password will be asked during the build when you use the 'release' target.
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:3.0.1'
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 27
|
||||
buildToolsVersion "27.0.3"
|
||||
defaultConfig {
|
||||
minSdkVersion 14
|
||||
targetSdkVersion 26
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
manifest.srcFile 'AndroidManifest.xml'
|
||||
java.srcDirs = ['src']
|
||||
resources.srcDirs = ['src']
|
||||
aidl.srcDirs = ['src']
|
||||
renderscript.srcDirs = ['src']
|
||||
res.srcDirs = ['res']
|
||||
assets.srcDirs = ['assets']
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="MemorizingTrustManager" default="help">
|
||||
|
||||
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||
It contains the path to the SDK. It should *NOT* be checked into
|
||||
Version Control Systems. -->
|
||||
<property file="local.properties" />
|
||||
|
||||
<!-- The ant.properties file can be created by you. It is only edited by the
|
||||
'android' tool to add properties to it.
|
||||
This is the place to change some Ant specific build properties.
|
||||
Here are some properties you may want to change/update:
|
||||
|
||||
source.dir
|
||||
The name of the source directory. Default is 'src'.
|
||||
out.dir
|
||||
The name of the output directory. Default is 'bin'.
|
||||
|
||||
For other overridable properties, look at the beginning of the rules
|
||||
files in the SDK, at tools/ant/build.xml
|
||||
|
||||
Properties related to the SDK location or the project target should
|
||||
be updated using the 'android' tool with the 'update' action.
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems.
|
||||
|
||||
-->
|
||||
<property file="ant.properties" />
|
||||
|
||||
<!-- if sdk.dir was not set from one of the property file, then
|
||||
get it from the ANDROID_HOME env var.
|
||||
This must be done before we load project.properties since
|
||||
the proguard config can use sdk.dir -->
|
||||
<property environment="env" />
|
||||
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
|
||||
<isset property="env.ANDROID_HOME" />
|
||||
</condition>
|
||||
|
||||
<!-- The project.properties file is created and updated by the 'android'
|
||||
tool, as well as ADT.
|
||||
|
||||
This contains project specific properties such as project target, and library
|
||||
dependencies. Lower level build properties are stored in ant.properties
|
||||
(or in .classpath for Eclipse projects).
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems. -->
|
||||
<loadproperties srcFile="project.properties" />
|
||||
|
||||
<!-- quick check on sdk.dir -->
|
||||
<fail
|
||||
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
|
||||
unless="sdk.dir" />
|
||||
|
||||
<!--
|
||||
Import per project custom build rules if present at the root of the project.
|
||||
This is the place to put custom intermediary targets such as:
|
||||
-pre-build
|
||||
-pre-compile
|
||||
-post-compile (This is typically used for code obfuscation.
|
||||
Compiled code location: ${out.classes.absolute.dir}
|
||||
If this is not done in place, override ${out.dex.input.absolute.dir})
|
||||
-post-package
|
||||
-post-build
|
||||
-pre-clean
|
||||
-->
|
||||
<import file="custom_rules.xml" optional="true" />
|
||||
|
||||
<!-- Import the actual build file.
|
||||
|
||||
To customize existing targets, there are two options:
|
||||
- Customize only one target:
|
||||
- copy/paste the target into this file, *before* the
|
||||
<import> task.
|
||||
- customize it to your needs.
|
||||
- Customize the whole content of build.xml
|
||||
- copy/paste the content of the rules files (minus the top node)
|
||||
into this file, replacing the <import> task.
|
||||
- customize to your needs.
|
||||
|
||||
***********************
|
||||
****** IMPORTANT ******
|
||||
***********************
|
||||
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
|
||||
in order to avoid having your file be overridden by tools such as "android update project"
|
||||
-->
|
||||
<!-- version-tag: 1 -->
|
||||
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||
|
||||
</project>
|
Binary file not shown.
Before Width: | Height: | Size: 50 KiB |
Binary file not shown.
Before Width: | Height: | Size: 57 KiB |
Binary file not shown.
Before Width: | Height: | Size: 56 KiB |
|
@ -1,20 +0,0 @@
|
|||
# To enable ProGuard in your project, edit project.properties
|
||||
# to define the proguard.config property as described in that file.
|
||||
#
|
||||
# Add project specific ProGuard rules here.
|
||||
# By default, the flags in this file are appended to flags specified
|
||||
# in ${sdk.dir}/tools/proguard/proguard-android.txt
|
||||
# You can edit the include path and order by changing the ProGuard
|
||||
# include property in project.properties.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# Add any project specific keep options here:
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
|
@ -1,11 +0,0 @@
|
|||
# This file is automatically generated by Android Tools.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file must be checked in Version Control Systems.
|
||||
#
|
||||
# To customize properties used by the Ant build system use,
|
||||
# "ant.properties", and override values to adapt the script to your
|
||||
# project structure.
|
||||
android.library=true
|
||||
# Project target.
|
||||
target=android-19
|
|
@ -1,17 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="mtm_accept_cert">Unbekanntes Zertifikat akzeptieren?</string>
|
||||
<string name="mtm_trust_anchor">Das Serverzertifikat stammt nicht von einer bekannten Ausstellungsstelle (CA).</string>
|
||||
<string name="mtm_cert_expired">The server certificate is expired.</string>
|
||||
<string name="mtm_accept_servername">Abweichenden Servernamen akzeptieren?</string>
|
||||
<string name="mtm_hostname_mismatch">Der Server konnte sich nicht als \"%s\" ausweisen. Das Zertifikat gilt nur für:</string>
|
||||
|
||||
<string name="mtm_connect_anyway">Verbindung trotzdem aufbauen?</string>
|
||||
<string name="mtm_cert_details">Zertifikat-Details:</string>
|
||||
|
||||
<string name="mtm_decision_always">Immer</string>
|
||||
<string name="mtm_decision_once">Einmal</string>
|
||||
<string name="mtm_decision_abort">Abbrechen</string>
|
||||
|
||||
<string name="mtm_notification">Zertifikatsprüfung</string>
|
||||
</resources>
|
|
@ -1,17 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="mtm_accept_cert">¿Aceptar certicado desconocido?</string>
|
||||
<string name="mtm_trust_anchor">El certificado del servidor no está firmado por una Autoridad Conocida (CA).</string>
|
||||
<string name="mtm_cert_expired">The server certificate is expired.</string>
|
||||
<string name="mtm_accept_servername">¿Aceptar discordancia en nombre del servidor?</string>
|
||||
<string name="mtm_hostname_mismatch">El servidor no ha podido autenticarte como \"%s\". El certificado es solo válido para:</string>
|
||||
|
||||
<string name="mtm_connect_anyway">¿Quieres conectar de todas formas?</string>
|
||||
<string name="mtm_cert_details">Detalle del certificado:</string>
|
||||
|
||||
<string name="mtm_decision_always">Siempre</string>
|
||||
<string name="mtm_decision_once">Una vez</string>
|
||||
<string name="mtm_decision_abort">Abortar</string>
|
||||
|
||||
<string name="mtm_notification">Verificación de Certificado</string>
|
||||
</resources>
|
|
@ -1,17 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="mtm_accept_cert">Ziurtagiri ezezaguna onartu?</string>
|
||||
<string name="mtm_trust_anchor">Zerbitzariaren ziurtagiria ez dago Ziurtagiri-emaile Autoritate ezagun batez sinatuta.</string>
|
||||
<string name="mtm_cert_expired">Zerbitzariaren ziurtagiria iraungi da.</string>
|
||||
<string name="mtm_accept_servername">Zerbitzariaren izeneko desadostasuna onartu?</string>
|
||||
<string name="mtm_hostname_mismatch">Zerbitzaria ezin izan da \"%s\" bezala autentifikatu. Ziurtagiria soilik honetarako baliagarria da:</string>
|
||||
|
||||
<string name="mtm_connect_anyway">Konektatu hala ere?</string>
|
||||
<string name="mtm_cert_details">Ziurtagiriaren xehetasunak:</string>
|
||||
|
||||
<string name="mtm_decision_always">Beti</string>
|
||||
<string name="mtm_decision_once">Behin</string>
|
||||
<string name="mtm_decision_abort">Utzi</string>
|
||||
|
||||
<string name="mtm_notification">Ziurtagiriaren egiaztapena</string>
|
||||
</resources>
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="mtm_accept_cert">Hyväksytäänkö palvelimen antama tuntematon varmenne?</string>
|
||||
<string name="mtm_trust_anchor">Palvelimen varmenne ei ole tunnetun varmentajan (CA) allekirjoittama.</string>
|
||||
<string name="mtm_accept_servername">Sallitaanko palvelimen nimi, joka ei vastaa varmeenteessa olevaa nimeä?</string>
|
||||
<string name="mtm_hostname_mismatch">Palvelimella ei ole varmennetta nimelle \"%s\". Varmenteen sisältämät nimet:</string>
|
||||
|
||||
<string name="mtm_connect_anyway">Haluatko jatkaa yhteyden muodostamista?</string>
|
||||
<string name="mtm_cert_details">Sertifikaatin tiedot:</string>
|
||||
|
||||
<string name="mtm_decision_always">Aina</string>
|
||||
<string name="mtm_decision_once">Kerran</string>
|
||||
<string name="mtm_decision_abort">Keskeytä</string>
|
||||
|
||||
<string name="mtm_notification">Varmenteen tarkistus</string>
|
||||
</resources>
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="mtm_accept_cert">Accept Unknown Certificate?</string>
|
||||
<string name="mtm_trust_anchor">Le certificat du serveur n’est pas signé par une Autorité de Certification reconnue.</string>
|
||||
<string name="mtm_accept_servername">Accept Mismatching Server Name?</string>
|
||||
<string name="mtm_hostname_mismatch">Server could not authenticate as \"%s\". The certificate is only valid for:</string>
|
||||
|
||||
<string name="mtm_connect_anyway">Do you want to connect anyway?</string>
|
||||
<string name="mtm_cert_details">Détails du certificat :</string>
|
||||
|
||||
<string name="mtm_decision_always">Toujours</string>
|
||||
<string name="mtm_decision_once">Une seule fois</string>
|
||||
<string name="mtm_decision_abort">Annuler</string>
|
||||
|
||||
<string name="mtm_notification">Certificate Verification</string>
|
||||
</resources>
|
|
@ -1,16 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="mtm_accept_cert">Godta ukjent sertifikat?</string>
|
||||
<string name="mtm_trust_anchor">Sertifikatet er ikke utstilt av en kjent utstiller (CA).</string>
|
||||
<string name="mtm_accept_servername">Godta feil servernavn?</string>
|
||||
<string name="mtm_hostname_mismatch">Serveren heter ikke \"%s\". Sertifikatet gjelder bare for: </string>
|
||||
|
||||
<string name="mtm_connect_anyway">Vil du bruke serveren likevel?</string>
|
||||
<string name="mtm_cert_details">Sertifikatdetaljer:</string>
|
||||
|
||||
<string name="mtm_decision_always">Alltid</string>
|
||||
<string name="mtm_decision_once">En gang</string>
|
||||
<string name="mtm_decision_abort">Avbryt</string>
|
||||
|
||||
<string name="mtm_notification">Sertifikat-sjekk</string>
|
||||
</resources>
|
|
@ -1,4 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="theme">light</string>
|
||||
</resources>
|
|
@ -1,17 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="mtm_accept_cert">Accept Unknown Certificate?</string>
|
||||
<string name="mtm_trust_anchor">The server certificate is not signed by a known Certificate Authority.</string>
|
||||
<string name="mtm_cert_expired">The server certificate is expired.</string>
|
||||
<string name="mtm_accept_servername">Accept Mismatching Server Name?</string>
|
||||
<string name="mtm_hostname_mismatch">Server could not authenticate as \"%s\". The certificate is only valid for:</string>
|
||||
|
||||
<string name="mtm_connect_anyway">Do you want to connect anyway?</string>
|
||||
<string name="mtm_cert_details">Certificate details:</string>
|
||||
|
||||
<string name="mtm_decision_always">Always</string>
|
||||
<string name="mtm_decision_once">Once</string>
|
||||
<string name="mtm_decision_abort">Abort</string>
|
||||
|
||||
<string name="mtm_notification">Certificate Verification</string>
|
||||
</resources>
|
|
@ -1 +0,0 @@
|
|||
include ':example'
|
|
@ -1,3 +1,2 @@
|
|||
include ':libs:MemorizingTrustManager'
|
||||
include ':libs:android-transcoder'
|
||||
rootProject.name = 'Pix-Art Messenger'
|
||||
|
|
|
@ -237,10 +237,6 @@
|
|||
android:name=".ui.TrustKeysActivity"
|
||||
android:label="@string/trust_omemo_fingerprints"
|
||||
android:windowSoftInputMode="stateAlwaysHidden" />
|
||||
<activity
|
||||
android:name="de.duenndns.ssl.MemorizingActivity" />
|
||||
<!--android:theme="@style/ConversationsTheme"-->
|
||||
<!--tools:replace="android:theme" />-->
|
||||
<activity
|
||||
android:name=".ui.AboutActivity"
|
||||
android:label="@string/title_activity_about"
|
||||
|
@ -256,11 +252,8 @@
|
|||
android:launchMode="singleTask"
|
||||
android:theme="@style/ConversationsTheme">
|
||||
</activity>
|
||||
<activity
|
||||
android:name="com.soundcloud.android.crop.CropImageActivity">
|
||||
</activity>
|
||||
|
||||
<service android:name=".services.UpdateService" />
|
||||
<activity android:name="com.soundcloud.android.crop.CropImageActivity" />
|
||||
<activity android:name=".ui.MemorizingActivity" />
|
||||
<service android:name=".services.ExportLogsService" />
|
||||
<service
|
||||
android:name=".services.ContactChooserTargetService"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package de.duenndns.ssl;
|
||||
package de.pixart.messenger.crypto;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.SSLSession;
|
||||
|
@ -7,4 +7,4 @@ public interface DomainHostnameVerifier extends HostnameVerifier {
|
|||
|
||||
boolean verify(String domain, String hostname, SSLSession sslSession);
|
||||
|
||||
}
|
||||
}
|
|
@ -25,8 +25,6 @@ import java.util.List;
|
|||
|
||||
import javax.net.ssl.SSLSession;
|
||||
|
||||
import de.duenndns.ssl.DomainHostnameVerifier;
|
||||
|
||||
public class XmppDomainVerifier implements DomainHostnameVerifier {
|
||||
|
||||
private static final String LOGTAG = "XmppDomainVerifier";
|
||||
|
|
|
@ -21,13 +21,13 @@
|
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package de.duenndns.ssl;
|
||||
package de.pixart.messenger.entities;
|
||||
|
||||
class MTMDecision {
|
||||
public final static int DECISION_INVALID = 0;
|
||||
public final static int DECISION_ABORT = 1;
|
||||
public final static int DECISION_ONCE = 2;
|
||||
public final static int DECISION_ALWAYS = 3;
|
||||
public class MTMDecision {
|
||||
public final static int DECISION_INVALID = 0;
|
||||
public final static int DECISION_ABORT = 1;
|
||||
public final static int DECISION_ONCE = 2;
|
||||
public final static int DECISION_ALWAYS = 3;
|
||||
|
||||
int state = DECISION_INVALID;
|
||||
}
|
||||
public int state = DECISION_INVALID;
|
||||
}
|
|
@ -24,7 +24,7 @@
|
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package de.duenndns.ssl;
|
||||
package de.pixart.messenger.services;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
|
@ -33,11 +33,11 @@ import android.app.Service;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Handler;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Base64;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.os.Handler;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
@ -52,24 +52,19 @@ import java.io.IOException;
|
|||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.*;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateExpiredException;
|
||||
import java.security.cert.CertificateParsingException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
|
@ -79,6 +74,11 @@ import javax.net.ssl.TrustManager;
|
|||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import de.pixart.messenger.R;
|
||||
import de.pixart.messenger.crypto.DomainHostnameVerifier;
|
||||
import de.pixart.messenger.entities.MTMDecision;
|
||||
import de.pixart.messenger.ui.MemorizingActivity;
|
||||
|
||||
/**
|
||||
* A X509 trust manager implementation which asks the user about invalid
|
||||
* certificates and memorizes their decision.
|
||||
|
@ -99,12 +99,12 @@ public class MemorizingTrustManager {
|
|||
private static final Pattern PATTERN_IPV6 = Pattern.compile("\\A(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\\z");
|
||||
|
||||
final static String DECISION_INTENT = "de.duenndns.ssl.DECISION";
|
||||
final static String DECISION_INTENT_ID = DECISION_INTENT + ".decisionId";
|
||||
final static String DECISION_INTENT_CERT = DECISION_INTENT + ".cert";
|
||||
public final static String DECISION_INTENT_ID = DECISION_INTENT + ".decisionId";
|
||||
public final static String DECISION_INTENT_CERT = DECISION_INTENT + ".cert";
|
||||
final static String DECISION_INTENT_CHOICE = DECISION_INTENT + ".decisionChoice";
|
||||
|
||||
private final static Logger LOGGER = Logger.getLogger(MemorizingTrustManager.class.getName());
|
||||
final static String DECISION_TITLE_ID = DECISION_INTENT + ".titleId";
|
||||
public final static String DECISION_TITLE_ID = DECISION_INTENT + ".titleId";
|
||||
private final static int NOTIFICATION_ID = 100509;
|
||||
|
||||
final static String NO_TRUST_ANCHOR = "Trust anchor for certification path not found.";
|
||||
|
@ -125,18 +125,17 @@ public class MemorizingTrustManager {
|
|||
private X509TrustManager appTrustManager;
|
||||
private String poshCacheDir;
|
||||
|
||||
/**
|
||||
* Creates an instance of the MemorizingTrustManager class that falls back to a custom TrustManager.
|
||||
* <p>
|
||||
/** Creates an instance of the MemorizingTrustManager class that falls back to a custom TrustManager.
|
||||
*
|
||||
* You need to supply the application context. This has to be one of:
|
||||
* - Application
|
||||
* - Activity
|
||||
* - Service
|
||||
* <p>
|
||||
* - Application
|
||||
* - Activity
|
||||
* - Service
|
||||
*
|
||||
* The context is used for file management, to display the dialog /
|
||||
* notification and for obtaining translated strings.
|
||||
*
|
||||
* @param m Context for the application.
|
||||
* @param m Context for the application.
|
||||
* @param defaultTrustManager Delegate trust management to this TM. If null, the user must accept every certificate.
|
||||
*/
|
||||
public MemorizingTrustManager(Context m, X509TrustManager defaultTrustManager) {
|
||||
|
@ -145,14 +144,13 @@ public class MemorizingTrustManager {
|
|||
this.defaultTrustManager = defaultTrustManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of the MemorizingTrustManager class using the system X509TrustManager.
|
||||
* <p>
|
||||
/** Creates an instance of the MemorizingTrustManager class using the system X509TrustManager.
|
||||
*
|
||||
* You need to supply the application context. This has to be one of:
|
||||
* - Application
|
||||
* - Activity
|
||||
* - Service
|
||||
* <p>
|
||||
* - Application
|
||||
* - Activity
|
||||
* - Service
|
||||
*
|
||||
* The context is used for file management, to display the dialog /
|
||||
* notification and for obtaining translated strings.
|
||||
*
|
||||
|
@ -167,22 +165,21 @@ public class MemorizingTrustManager {
|
|||
void init(Context m) {
|
||||
master = m;
|
||||
masterHandler = new Handler(m.getMainLooper());
|
||||
notificationManager = (NotificationManager) master.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
notificationManager = (NotificationManager)master.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
|
||||
Application app;
|
||||
if (m instanceof Application) {
|
||||
app = (Application) m;
|
||||
app = (Application)m;
|
||||
} else if (m instanceof Service) {
|
||||
app = ((Service) m).getApplication();
|
||||
app = ((Service)m).getApplication();
|
||||
} else if (m instanceof Activity) {
|
||||
app = ((Activity) m).getApplication();
|
||||
} else
|
||||
throw new ClassCastException("MemorizingTrustManager context must be either Activity or Service!");
|
||||
app = ((Activity)m).getApplication();
|
||||
} else throw new ClassCastException("MemorizingTrustManager context must be either Activity or Service!");
|
||||
|
||||
File dir = app.getDir(KEYSTORE_DIR, Context.MODE_PRIVATE);
|
||||
keyStoreFile = new File(dir + File.separator + KEYSTORE_FILE);
|
||||
|
||||
poshCacheDir = app.getFilesDir().getAbsolutePath() + "/posh_cache/";
|
||||
poshCacheDir = app.getFilesDir().getAbsolutePath()+"/posh_cache/";
|
||||
|
||||
appKeyStore = loadAppKeyStore();
|
||||
}
|
||||
|
@ -190,11 +187,11 @@ public class MemorizingTrustManager {
|
|||
|
||||
/**
|
||||
* Binds an Activity to the MTM for displaying the query dialog.
|
||||
* <p>
|
||||
*
|
||||
* This is useful if your connection is run from a service that is
|
||||
* triggered by user interaction -- in such cases the activity is
|
||||
* visible and the user tends to ignore the service notification.
|
||||
* <p>
|
||||
*
|
||||
* You should never have a hidden activity bound to MTM! Use this
|
||||
* function in onResume() and @see unbindDisplayActivity in onPause().
|
||||
*
|
||||
|
@ -206,7 +203,7 @@ public class MemorizingTrustManager {
|
|||
|
||||
/**
|
||||
* Removes an Activity from the MTM display stack.
|
||||
* <p>
|
||||
*
|
||||
* Always call this function when the Activity added with
|
||||
* {@link #bindDisplayActivity(Activity)} is hidden.
|
||||
*
|
||||
|
@ -220,11 +217,11 @@ public class MemorizingTrustManager {
|
|||
|
||||
/**
|
||||
* Changes the path for the KeyStore file.
|
||||
* <p>
|
||||
*
|
||||
* The actual filename relative to the app's directory will be
|
||||
* <code>app_<i>dirname</i>/<i>filename</i></code>.
|
||||
*
|
||||
* @param dirname directory to store the KeyStore.
|
||||
* @param dirname directory to store the KeyStore.
|
||||
* @param filename file name for the KeyStore.
|
||||
*/
|
||||
public static void setKeyStoreFile(String dirname, String filename) {
|
||||
|
@ -250,6 +247,7 @@ public class MemorizingTrustManager {
|
|||
* Get a certificate for a given alias.
|
||||
*
|
||||
* @param alias the certificate's alias as returned by {@link #getCertificates()}.
|
||||
*
|
||||
* @return the certificate associated with the alias or <tt>null</tt> if none found.
|
||||
*/
|
||||
public Certificate getCertificate(String alias) {
|
||||
|
@ -263,15 +261,15 @@ public class MemorizingTrustManager {
|
|||
|
||||
/**
|
||||
* Removes the given certificate from MTMs key store.
|
||||
* <p>
|
||||
*
|
||||
* <p>
|
||||
* <b>WARNING</b>: this does not immediately invalidate the certificate. It is
|
||||
* well possible that (a) data is transmitted over still existing connections or
|
||||
* (b) new connections are created using TLS renegotiation, without a new cert
|
||||
* check.
|
||||
* </p>
|
||||
*
|
||||
* @param alias the certificate's alias as returned by {@link #getCertificates()}.
|
||||
*
|
||||
* @throws KeyStoreException if the certificate could not be deleted.
|
||||
*/
|
||||
public void deleteCertificate(String alias) throws KeyStoreException {
|
||||
|
@ -281,27 +279,28 @@ public class MemorizingTrustManager {
|
|||
|
||||
/**
|
||||
* Creates a new hostname verifier supporting user interaction.
|
||||
* <p>
|
||||
*
|
||||
* <p>This method creates a new {@link HostnameVerifier} that is bound to
|
||||
* the given instance of {@link MemorizingTrustManager}, and leverages an
|
||||
* existing {@link HostnameVerifier}. The returned verifier performs the
|
||||
* following steps, returning as soon as one of them succeeds:
|
||||
* </p>
|
||||
* <ol>
|
||||
* <li>Success, if the wrapped defaultVerifier accepts the certificate.</li>
|
||||
* <li>Success, if the server certificate is stored in the keystore under the given hostname.</li>
|
||||
* <li>Ask the user and return accordingly.</li>
|
||||
* <li>Failure on exception.</li>
|
||||
* </ol>
|
||||
* </p>
|
||||
* <ol>
|
||||
* <li>Success, if the wrapped defaultVerifier accepts the certificate.</li>
|
||||
* <li>Success, if the server certificate is stored in the keystore under the given hostname.</li>
|
||||
* <li>Ask the user and return accordingly.</li>
|
||||
* <li>Failure on exception.</li>
|
||||
* </ol>
|
||||
*
|
||||
* @param defaultVerifier the {@link HostnameVerifier} that should perform the actual check
|
||||
* @return a new hostname verifier using the MTM's key store
|
||||
*
|
||||
* @throws IllegalArgumentException if the defaultVerifier parameter is null
|
||||
*/
|
||||
public DomainHostnameVerifier wrapHostnameVerifier(final HostnameVerifier defaultVerifier, final boolean interactive) {
|
||||
if (defaultVerifier == null) {
|
||||
if (defaultVerifier == null)
|
||||
throw new IllegalArgumentException("The default verifier may not be null");
|
||||
}
|
||||
|
||||
return new MemorizingHostnameVerifier(defaultVerifier, interactive);
|
||||
}
|
||||
|
||||
|
@ -311,7 +310,7 @@ public class MemorizingTrustManager {
|
|||
tmf.init(ks);
|
||||
for (TrustManager t : tmf.getTrustManagers()) {
|
||||
if (t instanceof X509TrustManager) {
|
||||
return (X509TrustManager) t;
|
||||
return (X509TrustManager)t;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -397,7 +396,8 @@ public class MemorizingTrustManager {
|
|||
}
|
||||
|
||||
public void checkCertTrusted(X509Certificate[] chain, String authType, String domain, boolean isServer, boolean interactive)
|
||||
throws CertificateException {
|
||||
throws CertificateException
|
||||
{
|
||||
LOGGER.log(Level.FINE, "checkCertTrusted(" + chain + ", " + authType + ", " + isServer + ")");
|
||||
try {
|
||||
LOGGER.log(Level.FINE, "checkCertTrusted: trying appTrustManager");
|
||||
|
@ -427,10 +427,10 @@ public class MemorizingTrustManager {
|
|||
} catch (CertificateException e) {
|
||||
boolean trustSystemCAs = !PreferenceManager.getDefaultSharedPreferences(master).getBoolean("dont_trust_system_cas", false);
|
||||
if (domain != null && isServer && trustSystemCAs && !isIp(domain)) {
|
||||
String hash = getBase64Hash(chain[0], "SHA-256");
|
||||
String hash = getBase64Hash(chain[0],"SHA-256");
|
||||
List<String> fingerprints = getPoshFingerprints(domain);
|
||||
if (hash != null && fingerprints.contains(hash)) {
|
||||
Log.d("mtm", "trusted cert fingerprint of " + domain + " via posh");
|
||||
Log.d("mtm","trusted cert fingerprint of "+domain+" via posh");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -454,11 +454,11 @@ public class MemorizingTrustManager {
|
|||
}
|
||||
|
||||
private List<String> getPoshFingerprintsFromServer(String domain) {
|
||||
return getPoshFingerprintsFromServer(domain, "https://" + domain + "/.well-known/posh/xmpp-client.json", -1, true);
|
||||
return getPoshFingerprintsFromServer(domain, "https://"+domain+"/.well-known/posh/xmpp-client.json",-1,true);
|
||||
}
|
||||
|
||||
private List<String> getPoshFingerprintsFromServer(String domain, String url, int maxTtl, boolean followUrl) {
|
||||
Log.d("mtm", "downloading json for " + domain + " from " + url);
|
||||
Log.d("mtm","downloading json for "+domain+" from "+url);
|
||||
try {
|
||||
List<String> results = new ArrayList<>();
|
||||
HttpsURLConnection connection = (HttpsURLConnection) new URL(url).openConnection();
|
||||
|
@ -477,7 +477,7 @@ public class MemorizingTrustManager {
|
|||
return new ArrayList<>();
|
||||
}
|
||||
if (maxTtl >= 0) {
|
||||
expires = Math.min(maxTtl, expires);
|
||||
expires = Math.min(maxTtl,expires);
|
||||
}
|
||||
String redirect;
|
||||
try {
|
||||
|
@ -489,23 +489,23 @@ public class MemorizingTrustManager {
|
|||
return getPoshFingerprintsFromServer(domain, redirect, expires, false);
|
||||
}
|
||||
JSONArray fingerprints = jsonObject.getJSONArray("fingerprints");
|
||||
for (int i = 0; i < fingerprints.length(); i++) {
|
||||
for(int i = 0; i < fingerprints.length(); i++) {
|
||||
JSONObject fingerprint = fingerprints.getJSONObject(i);
|
||||
String sha256 = fingerprint.getString("sha-256");
|
||||
if (sha256 != null) {
|
||||
results.add(sha256);
|
||||
}
|
||||
}
|
||||
writeFingerprintsToCache(domain, results, 1000L * expires + System.currentTimeMillis());
|
||||
writeFingerprintsToCache(domain, results,1000L * expires+System.currentTimeMillis());
|
||||
return results;
|
||||
} catch (Exception e) {
|
||||
Log.d("mtm", "error fetching posh " + e.getMessage());
|
||||
Log.d("mtm","error fetching posh "+e.getMessage());
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
private File getPoshCacheFile(String domain) {
|
||||
return new File(poshCacheDir + domain + ".json");
|
||||
return new File(poshCacheDir+domain+".json");
|
||||
}
|
||||
|
||||
private void writeFingerprintsToCache(String domain, List<String> results, long expires) {
|
||||
|
@ -514,8 +514,8 @@ public class MemorizingTrustManager {
|
|||
try {
|
||||
file.createNewFile();
|
||||
JSONObject jsonObject = new JSONObject();
|
||||
jsonObject.put("expires", expires);
|
||||
jsonObject.put("fingerprints", new JSONArray(results));
|
||||
jsonObject.put("expires",expires);
|
||||
jsonObject.put("fingerprints",new JSONArray(results));
|
||||
FileOutputStream outputStream = new FileOutputStream(file);
|
||||
outputStream.write(jsonObject.toString().getBytes());
|
||||
outputStream.flush();
|
||||
|
@ -534,7 +534,7 @@ public class MemorizingTrustManager {
|
|||
String line = buf.readLine();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
while (line != null) {
|
||||
while(line != null){
|
||||
sb.append(line).append("\n");
|
||||
line = buf.readLine();
|
||||
}
|
||||
|
@ -546,11 +546,11 @@ public class MemorizingTrustManager {
|
|||
file.delete();
|
||||
return null;
|
||||
} else {
|
||||
Log.d("mtm", "posh fingerprints expire in " + (expiresIn / 1000) + "s");
|
||||
Log.d("mtm","posh fingerprints expire in "+(expiresIn/1000)+"s");
|
||||
}
|
||||
List<String> result = new ArrayList<>();
|
||||
JSONArray jsonArray = jsonObject.getJSONArray("fingerprints");
|
||||
for (int i = 0; i < jsonArray.length(); ++i) {
|
||||
for(int i = 0; i < jsonArray.length(); ++i) {
|
||||
result.add(jsonArray.getString(i));
|
||||
}
|
||||
return result;
|
||||
|
@ -581,7 +581,7 @@ public class MemorizingTrustManager {
|
|||
return null;
|
||||
}
|
||||
md.update(certificate.getEncoded());
|
||||
return Base64.encodeToString(md.digest(), Base64.NO_WRAP);
|
||||
return Base64.encodeToString(md.digest(),Base64.NO_WRAP);
|
||||
}
|
||||
|
||||
private X509Certificate[] getAcceptedIssuers() {
|
||||
|
@ -591,7 +591,7 @@ public class MemorizingTrustManager {
|
|||
|
||||
private int createDecisionId(MTMDecision d) {
|
||||
int myId;
|
||||
synchronized (openDecisions) {
|
||||
synchronized(openDecisions) {
|
||||
myId = decisionId;
|
||||
openDecisions.put(myId, d);
|
||||
decisionId += 1;
|
||||
|
@ -676,7 +676,7 @@ public class MemorizingTrustManager {
|
|||
Object name = altName.get(1);
|
||||
if (name instanceof String) {
|
||||
si.append("[");
|
||||
si.append((Integer) altName.get(0));
|
||||
si.append((Integer)altName.get(0));
|
||||
si.append("] ");
|
||||
si.append(name);
|
||||
si.append("\n");
|
||||
|
@ -695,7 +695,6 @@ public class MemorizingTrustManager {
|
|||
certDetails(si, cert);
|
||||
return si.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the top-most entry of the activity stack.
|
||||
*
|
||||
|
@ -706,7 +705,7 @@ public class MemorizingTrustManager {
|
|||
}
|
||||
|
||||
int interact(final String message, final int titleId) {
|
||||
/* prepare the MTMDecision blocker object */
|
||||
/* prepare the MTMDecision blocker object */
|
||||
MTMDecision choice = new MTMDecision();
|
||||
final int myId = createDecisionId(choice);
|
||||
|
||||
|
@ -731,9 +730,7 @@ public class MemorizingTrustManager {
|
|||
|
||||
LOGGER.log(Level.FINE, "openDecisions: " + openDecisions + ", waiting on " + myId);
|
||||
try {
|
||||
synchronized (choice) {
|
||||
choice.wait();
|
||||
}
|
||||
synchronized(choice) { choice.wait(); }
|
||||
} catch (InterruptedException e) {
|
||||
LOGGER.log(Level.FINER, "InterruptedException", e);
|
||||
}
|
||||
|
@ -742,7 +739,8 @@ public class MemorizingTrustManager {
|
|||
}
|
||||
|
||||
void interactCert(final X509Certificate[] chain, String authType, CertificateException cause)
|
||||
throws CertificateException {
|
||||
throws CertificateException
|
||||
{
|
||||
switch (interact(certChainMessage(chain, cause), R.string.mtm_accept_cert)) {
|
||||
case MTMDecision.DECISION_ALWAYS:
|
||||
storeCert(chain[0]); // only store the server cert, not the whole chain
|
||||
|
@ -753,7 +751,8 @@ public class MemorizingTrustManager {
|
|||
}
|
||||
}
|
||||
|
||||
boolean interactHostname(X509Certificate cert, String hostname) {
|
||||
boolean interactHostname(X509Certificate cert, String hostname)
|
||||
{
|
||||
switch (interact(hostNameMessage(cert, hostname), R.string.mtm_accept_servername)) {
|
||||
case MTMDecision.DECISION_ALWAYS:
|
||||
storeCert(hostname, cert);
|
||||
|
@ -764,9 +763,9 @@ public class MemorizingTrustManager {
|
|||
}
|
||||
}
|
||||
|
||||
protected static void interactResult(int decisionId, int choice) {
|
||||
public static void interactResult(int decisionId, int choice) {
|
||||
MTMDecision d;
|
||||
synchronized (openDecisions) {
|
||||
synchronized(openDecisions) {
|
||||
d = openDecisions.get(decisionId);
|
||||
openDecisions.remove(decisionId);
|
||||
}
|
||||
|
@ -774,7 +773,7 @@ public class MemorizingTrustManager {
|
|||
LOGGER.log(Level.SEVERE, "interactResult: aborting due to stale decision reference!");
|
||||
return;
|
||||
}
|
||||
synchronized (d) {
|
||||
synchronized(d) {
|
||||
d.state = choice;
|
||||
d.notify();
|
||||
}
|
||||
|
@ -794,7 +793,7 @@ public class MemorizingTrustManager {
|
|||
LOGGER.log(Level.FINE, "hostname verifier for " + domain + ", trying default verifier first");
|
||||
// if the default verifier accepts the hostname, we are done
|
||||
if (defaultVerifier instanceof DomainHostnameVerifier) {
|
||||
if (((DomainHostnameVerifier) defaultVerifier).verify(domain, hostname, session)) {
|
||||
if (((DomainHostnameVerifier) defaultVerifier).verify(domain,hostname, session)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
|
@ -803,9 +802,10 @@ public class MemorizingTrustManager {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// otherwise, we check if the hostname is an alias for this cert in our keystore
|
||||
try {
|
||||
X509Certificate cert = (X509Certificate) session.getPeerCertificates()[0];
|
||||
X509Certificate cert = (X509Certificate)session.getPeerCertificates()[0];
|
||||
//Log.d(TAG, "cert: " + cert);
|
||||
if (cert.equals(appKeyStore.getCertificate(domain.toLowerCase(Locale.US)))) {
|
||||
LOGGER.log(Level.FINE, "certificate for " + domain + " is in our keystore. accepting.");
|
||||
|
@ -826,10 +826,11 @@ public class MemorizingTrustManager {
|
|||
|
||||
@Override
|
||||
public boolean verify(String domain, SSLSession sslSession) {
|
||||
return verify(domain, null, sslSession);
|
||||
return verify(domain,null,sslSession);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public X509TrustManager getNonInteractive(String domain) {
|
||||
return new NonInteractiveMemorizingTrustManager(domain);
|
||||
}
|
||||
|
@ -895,4 +896,4 @@ public class MemorizingTrustManager {
|
|||
return MemorizingTrustManager.this.getAcceptedIssuers();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -70,7 +70,6 @@ import java.util.concurrent.CountDownLatch;
|
|||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import de.duenndns.ssl.MemorizingTrustManager;
|
||||
import de.pixart.messenger.BuildConfig;
|
||||
import de.pixart.messenger.Config;
|
||||
import de.pixart.messenger.R;
|
||||
|
|
|
@ -21,11 +21,8 @@
|
|||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
package de.duenndns.ssl;
|
||||
package de.pixart.messenger.ui;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnCancelListener;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
|
@ -33,15 +30,20 @@ import android.content.Intent;
|
|||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class MemorizingActivity extends Activity
|
||||
implements OnClickListener, OnCancelListener {
|
||||
import de.pixart.messenger.R;
|
||||
import de.pixart.messenger.entities.MTMDecision;
|
||||
import de.pixart.messenger.services.MemorizingTrustManager;
|
||||
|
||||
public class MemorizingActivity extends AppCompatActivity implements OnClickListener,OnCancelListener {
|
||||
|
||||
public static final String THEME = "theme";
|
||||
private final static Logger LOGGER = Logger.getLogger(MemorizingActivity.class.getName());
|
||||
|
||||
int decisionId;
|
||||
|
||||
AlertDialog dialog;
|
||||
|
@ -49,7 +51,7 @@ public class MemorizingActivity extends Activity
|
|||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
LOGGER.log(Level.FINE, "onCreate");
|
||||
// setTheme(findTheme());
|
||||
//setTheme(findTheme());
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
|
@ -63,9 +65,9 @@ public class MemorizingActivity extends Activity
|
|||
LOGGER.log(Level.FINE, "onResume with " + i.getExtras() + " decId=" + decisionId + " data: " + i.getData());
|
||||
dialog = new AlertDialog.Builder(this).setTitle(titleId)
|
||||
.setMessage(cert)
|
||||
.setPositiveButton(R.string.mtm_decision_always, this)
|
||||
.setNeutralButton(R.string.mtm_decision_once, this)
|
||||
.setNegativeButton(R.string.mtm_decision_abort, this)
|
||||
.setPositiveButton(R.string.always, this)
|
||||
.setNeutralButton(R.string.once, this)
|
||||
.setNegativeButton(R.string.cancel, this)
|
||||
.setOnCancelListener(this)
|
||||
.create();
|
||||
dialog.show();
|
||||
|
@ -84,12 +86,14 @@ public class MemorizingActivity extends Activity
|
|||
finish();
|
||||
}
|
||||
|
||||
// protected int findTheme() {
|
||||
// return getPreferences().getString(THEME, getResources().getString(R.string.theme)).equals("dark") ? R.style.ConversationsTheme_Dark : R.style.ConversationsTheme;
|
||||
// }
|
||||
protected int findTheme() {
|
||||
return 0;
|
||||
//return getPreferences().getString(SettingsActivity.THEME, getResources().getString(R.string.theme)).equals("dark") ? R.style.ConversationsTheme_Dark : R.style.ConversationsTheme;
|
||||
}
|
||||
|
||||
protected SharedPreferences getPreferences() {
|
||||
return PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
|
||||
return PreferenceManager
|
||||
.getDefaultSharedPreferences(getApplicationContext());
|
||||
}
|
||||
|
||||
// react on AlertDialog button press
|
||||
|
@ -112,4 +116,4 @@ public class MemorizingActivity extends Activity
|
|||
public void onCancel(DialogInterface dialog) {
|
||||
sendDecision(MTMDecision.DECISION_ABORT);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,7 +29,7 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import de.duenndns.ssl.MemorizingTrustManager;
|
||||
import de.pixart.messenger.services.MemorizingTrustManager;
|
||||
import de.pixart.messenger.Config;
|
||||
import de.pixart.messenger.R;
|
||||
import de.pixart.messenger.entities.Account;
|
||||
|
|
|
@ -50,8 +50,8 @@ import javax.net.ssl.SSLSocketFactory;
|
|||
import javax.net.ssl.X509KeyManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import de.duenndns.ssl.DomainHostnameVerifier;
|
||||
import de.duenndns.ssl.MemorizingTrustManager;
|
||||
import de.pixart.messenger.crypto.DomainHostnameVerifier;
|
||||
import de.pixart.messenger.services.MemorizingTrustManager;
|
||||
import de.pixart.messenger.Config;
|
||||
import de.pixart.messenger.crypto.XmppDomainVerifier;
|
||||
import de.pixart.messenger.crypto.axolotl.AxolotlService;
|
||||
|
|
|
@ -763,4 +763,14 @@
|
|||
<string name="huawei_protected_apps_summary">To keep receiving notifications, even when the screen is turned off, you need to add Pix-Art Messenger to the list of protected apps.</string>
|
||||
<string name="pref_enable_multi_accounts_title">Enable multiple accounts</string>
|
||||
<string name="pref_enable_multi_accounts_summary">You want to use multiple accounts, so you have to set a password for daily backups.</string>
|
||||
<string name="mtm_accept_cert">Accept Unknown Certificate?</string>
|
||||
<string name="mtm_trust_anchor">The server certificate is not signed by a known Certificate Authority.</string>
|
||||
<string name="mtm_cert_expired">The server certificate is expired.</string>
|
||||
<string name="mtm_accept_servername">Accept Mismatching Server Name?</string>
|
||||
<string name="mtm_hostname_mismatch">Server could not authenticate as \"%s\". The certificate is only valid for:</string>
|
||||
<string name="mtm_connect_anyway">Do you want to connect anyway?</string>
|
||||
<string name="mtm_cert_details">Certificate details:</string>
|
||||
<string name="mtm_notification">Certificate Verification</string>
|
||||
<string name="once">Once</string>
|
||||
<string name="theme">Theme</string>
|
||||
</resources>
|
||||
|
|
Reference in a new issue