integrate trust manager into conversations
This commit is contained in:
parent
bd90f2140d
commit
de0272fd1a
|
@ -33,7 +33,6 @@ ext {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(':libs:MemorizingTrustManager')
|
|
||||||
implementation project(':libs:EnhancedListView')
|
implementation project(':libs:EnhancedListView')
|
||||||
playstoreImplementation 'com.google.android.gms:play-services-gcm:11.8.0'
|
playstoreImplementation 'com.google.android.gms:play-services-gcm:11.8.0'
|
||||||
implementation 'org.sufficientlysecure:openpgp-api:10.0'
|
implementation 'org.sufficientlysecure:openpgp-api:10.0'
|
||||||
|
|
|
@ -1,11 +0,0 @@
|
||||||
bin
|
|
||||||
build
|
|
||||||
gen
|
|
||||||
local.properties
|
|
||||||
example/bin
|
|
||||||
example/gen
|
|
||||||
tags
|
|
||||||
.project
|
|
||||||
.classpath
|
|
||||||
.gradle
|
|
||||||
.*.swp
|
|
|
@ -1,11 +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,17 +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 {
|
|
||||||
google()
|
|
||||||
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 25
|
|
||||||
}
|
|
||||||
|
|
||||||
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,92 +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>
|
|
|
@ -1,29 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
package="de.duenndns.mtmexample"
|
|
||||||
android:versionCode="1"
|
|
||||||
android:versionName="1.0">
|
|
||||||
|
|
||||||
<uses-sdk
|
|
||||||
android:minSdkVersion="3"
|
|
||||||
android:targetSdkVersion="19" />
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
|
||||||
|
|
||||||
<application android:label="@string/app_name" android:icon="@android:drawable/ic_lock_lock">
|
|
||||||
<activity
|
|
||||||
android:name=".MTMExample"
|
|
||||||
android:configChanges="keyboardHidden|orientation|screenSize|screenLayout"
|
|
||||||
android:label="@string/app_name" >
|
|
||||||
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MAIN" />
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
|
|
||||||
<!-- ADD THE FOLLOWING TO YOUR MANIFEST: -->
|
|
||||||
<activity android:name="de.duenndns.ssl.MemorizingActivity"
|
|
||||||
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
|
|
||||||
</application>
|
|
||||||
</manifest>
|
|
|
@ -1,18 +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.
|
|
||||||
|
|
||||||
application.package=de.duenndns.mtmexample
|
|
|
@ -1,23 +0,0 @@
|
||||||
apply plugin: 'android'
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
compile rootProject
|
|
||||||
}
|
|
||||||
|
|
||||||
android {
|
|
||||||
compileSdkVersion 19
|
|
||||||
buildToolsVersion "19.1"
|
|
||||||
defaultConfig {
|
|
||||||
minSdkVersion 7
|
|
||||||
targetSdkVersion 19
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceSets {
|
|
||||||
main {
|
|
||||||
manifest.srcFile 'AndroidManifest.xml'
|
|
||||||
java.srcDirs = ['src']
|
|
||||||
res.srcDirs = ['res']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,92 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project name="MTMExample" 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>
|
|
|
@ -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,12 +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.reference.1=../
|
|
||||||
# Project target.
|
|
||||||
target=android-19
|
|
|
@ -1,36 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="fill_parent" >
|
|
||||||
<EditText
|
|
||||||
android:id="@+id/url"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:hint="HTTPS address"
|
|
||||||
android:text="https://op-co.de/mtm/"
|
|
||||||
android:singleLine="true"
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
android:id="@+id/connect"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Connect"
|
|
||||||
/>
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/content"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:text="Please enter a HTTPS URL and press 'Connect'!"
|
|
||||||
android:textSize="11pt"
|
|
||||||
/>
|
|
||||||
<Button
|
|
||||||
android:id="@+id/manage"
|
|
||||||
android:layout_width="fill_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Clean up Certificates"
|
|
||||||
android:onClick="onManage"
|
|
||||||
/>
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
<string name="app_name">MemorizingTrustManager Example</string>
|
|
||||||
</resources>
|
|
|
@ -1,169 +0,0 @@
|
||||||
package de.duenndns.mtmexample;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.io.StringBufferInputStream;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.util.logging.Formatter;
|
|
||||||
import java.util.logging.Handler;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.LogManager;
|
|
||||||
import java.util.logging.LogRecord;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A <code>java.util.logging</code> (JUL) Handler for Android.
|
|
||||||
* <p>
|
|
||||||
* If you want fine-grained control over MTM's logging, you can copy this
|
|
||||||
* class to your code base and call the static {@link #initialize()} method.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* This JUL Handler passes log messages sent to JUL to the Android log, while
|
|
||||||
* keeping the format and stack traces of optionally supplied Exceptions. It
|
|
||||||
* further allows to install a {@link DebugLogSettings} class via
|
|
||||||
* {@link #setDebugLogSettings(DebugLogSettings)} that determines whether JUL log messages of
|
|
||||||
* level {@link java.util.logging.Level#FINE} or lower are logged. This gives
|
|
||||||
* the application developer more control over the logged messages, while
|
|
||||||
* allowing a library developer to place debug log messages without risking to
|
|
||||||
* spam the Android log.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* If there are no {@code DebugLogSettings} configured, then all messages sent
|
|
||||||
* to JUL will be logged.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Florian Schmaus
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public class JULHandler extends Handler {
|
|
||||||
|
|
||||||
/** Implement this interface to toggle debug logging.
|
|
||||||
*/
|
|
||||||
public interface DebugLogSettings {
|
|
||||||
public boolean isDebugLogEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final String CLASS_NAME = JULHandler.class.getName();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The global LogManager configuration.
|
|
||||||
* <p>
|
|
||||||
* This configures:
|
|
||||||
* <ul>
|
|
||||||
* <li> JULHandler as the default handler for all log messages
|
|
||||||
* <li> A default log level FINEST (300). Meaning that log messages of a level 300 or higher a
|
|
||||||
* logged
|
|
||||||
* </ul>
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
private static final InputStream LOG_MANAGER_CONFIG = new StringBufferInputStream(
|
|
||||||
// @formatter:off
|
|
||||||
"handlers = " + CLASS_NAME + '\n' +
|
|
||||||
".level = FINEST"
|
|
||||||
);
|
|
||||||
// @formatter:on
|
|
||||||
|
|
||||||
// Constants for Android vs. JUL debug level comparisons
|
|
||||||
private static final int FINE_INT = Level.FINE.intValue();
|
|
||||||
private static final int INFO_INT = Level.INFO.intValue();
|
|
||||||
private static final int WARN_INT = Level.WARNING.intValue();
|
|
||||||
private static final int SEVE_INT = Level.SEVERE.intValue();
|
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(CLASS_NAME);
|
|
||||||
|
|
||||||
/** A formatter that creates output similar to Android's Log.x. */
|
|
||||||
private static final Formatter FORMATTER = new Formatter() {
|
|
||||||
@Override
|
|
||||||
public String format(LogRecord logRecord) {
|
|
||||||
Throwable thrown = logRecord.getThrown();
|
|
||||||
if (thrown != null) {
|
|
||||||
StringWriter sw = new StringWriter();
|
|
||||||
PrintWriter pw = new PrintWriter(sw, false);
|
|
||||||
pw.write(logRecord.getMessage() + ' ');
|
|
||||||
thrown.printStackTrace(pw);
|
|
||||||
pw.flush();
|
|
||||||
return sw.toString();
|
|
||||||
} else {
|
|
||||||
return logRecord.getMessage();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private static DebugLogSettings sDebugLogSettings;
|
|
||||||
private static boolean initialized = false;
|
|
||||||
|
|
||||||
public static void initialize() {
|
|
||||||
try {
|
|
||||||
LogManager.getLogManager().readConfiguration(LOG_MANAGER_CONFIG);
|
|
||||||
initialized = true;
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e("JULHandler", "Can not initialize configuration", e);
|
|
||||||
}
|
|
||||||
if (initialized) LOGGER.info("Initialzied java.util.logging logger");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setDebugLogSettings(DebugLogSettings debugLogSettings) {
|
|
||||||
if (!isInitialized()) initialize();
|
|
||||||
sDebugLogSettings = debugLogSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isInitialized() {
|
|
||||||
return initialized;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JULHandler() {
|
|
||||||
setFormatter(FORMATTER);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void flush() {}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLoggable(LogRecord record) {
|
|
||||||
final boolean debugLog = sDebugLogSettings == null ? true : sDebugLogSettings
|
|
||||||
.isDebugLogEnabled();
|
|
||||||
|
|
||||||
if (record.getLevel().intValue() <= FINE_INT) {
|
|
||||||
return debugLog;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** JUL method that forwards log records to Android's LogCat. */
|
|
||||||
@Override
|
|
||||||
public void publish(LogRecord record) {
|
|
||||||
if (!isLoggable(record)) return;
|
|
||||||
|
|
||||||
final int priority = getAndroidPriority(record.getLevel());
|
|
||||||
final String tag = substringAfterLastDot(record.getSourceClassName());
|
|
||||||
final String msg = getFormatter().format(record);
|
|
||||||
|
|
||||||
Log.println(priority, tag, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Helper to convert JUL verbosity levels to Android's Log. */
|
|
||||||
private static int getAndroidPriority(Level level) {
|
|
||||||
int value = level.intValue();
|
|
||||||
if (value >= SEVE_INT) {
|
|
||||||
return Log.ERROR;
|
|
||||||
} else if (value >= WARN_INT) {
|
|
||||||
return Log.WARN;
|
|
||||||
} else if (value >= INFO_INT) {
|
|
||||||
return Log.INFO;
|
|
||||||
} else {
|
|
||||||
return Log.DEBUG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Helper to extract short class names. */
|
|
||||||
private static String substringAfterLastDot(String s) {
|
|
||||||
return s.substring(s.lastIndexOf('.') + 1).trim();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,143 +0,0 @@
|
||||||
package de.duenndns.mtmexample;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Handler;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.View.OnClickListener;
|
|
||||||
import android.view.Window;
|
|
||||||
import android.widget.ArrayAdapter;
|
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import java.net.URL;
|
|
||||||
import java.security.KeyStoreException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
|
|
||||||
import javax.net.ssl.HostnameVerifier;
|
|
||||||
import javax.net.ssl.SSLContext;
|
|
||||||
import javax.net.ssl.HttpsURLConnection;
|
|
||||||
import javax.net.ssl.X509TrustManager;
|
|
||||||
|
|
||||||
import de.duenndns.ssl.MemorizingTrustManager;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Example to demonstrate the use of MemorizingTrustManager on HTTPS
|
|
||||||
* sockets.
|
|
||||||
*/
|
|
||||||
public class MTMExample extends Activity implements OnClickListener
|
|
||||||
{
|
|
||||||
MemorizingTrustManager mtm;
|
|
||||||
|
|
||||||
TextView content;
|
|
||||||
HostnameVerifier defaultverifier;
|
|
||||||
EditText urlinput;
|
|
||||||
String text;
|
|
||||||
Handler hdlr;
|
|
||||||
|
|
||||||
/** Creates the Activity and registers a MemorizingTrustManager. */
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle savedInstanceState)
|
|
||||||
{
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
JULHandler.initialize();
|
|
||||||
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
|
|
||||||
setContentView(R.layout.mtmexample);
|
|
||||||
|
|
||||||
|
|
||||||
// set up gui elements
|
|
||||||
findViewById(R.id.connect).setOnClickListener(this);
|
|
||||||
content = (TextView)findViewById(R.id.content);
|
|
||||||
urlinput = (EditText)findViewById(R.id.url);
|
|
||||||
|
|
||||||
// register handler for background thread
|
|
||||||
hdlr = new Handler();
|
|
||||||
|
|
||||||
// Here, the MemorizingTrustManager is activated for HTTPS
|
|
||||||
try {
|
|
||||||
// set location of the keystore
|
|
||||||
MemorizingTrustManager.setKeyStoreFile("private", "sslkeys.bks");
|
|
||||||
|
|
||||||
// register MemorizingTrustManager for HTTPS
|
|
||||||
SSLContext sc = SSLContext.getInstance("TLS");
|
|
||||||
mtm = new MemorizingTrustManager(this);
|
|
||||||
sc.init(null, new X509TrustManager[] { mtm },
|
|
||||||
new java.security.SecureRandom());
|
|
||||||
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
|
|
||||||
HttpsURLConnection.setDefaultHostnameVerifier(
|
|
||||||
mtm.wrapHostnameVerifier(HttpsURLConnection.getDefaultHostnameVerifier()));
|
|
||||||
|
|
||||||
// disable redirects to reduce possible confusion
|
|
||||||
HttpsURLConnection.setFollowRedirects(false);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Updates the screen content from a background thread. */
|
|
||||||
void setText(final String s, final boolean progress) {
|
|
||||||
text = s;
|
|
||||||
hdlr.post(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
content.setText(s);
|
|
||||||
setProgressBarIndeterminateVisibility(progress);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Spawns a new thread connecting to the specified URL.
|
|
||||||
* The result of the request is displayed on the screen.
|
|
||||||
* @param urlString a HTTPS URL to connect to.
|
|
||||||
*/
|
|
||||||
void connect(final String urlString) {
|
|
||||||
new Thread() {
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
URL u = new URL(urlString);
|
|
||||||
HttpsURLConnection c = (HttpsURLConnection)u.openConnection();
|
|
||||||
c.connect();
|
|
||||||
setText("" + c.getResponseCode() + " "
|
|
||||||
+ c.getResponseMessage(), false);
|
|
||||||
c.disconnect();
|
|
||||||
} catch (Exception e) {
|
|
||||||
setText(e.toString(), false);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Reacts on the connect Button press. */
|
|
||||||
@Override
|
|
||||||
public void onClick(View view) {
|
|
||||||
String url = urlinput.getText().toString();
|
|
||||||
setText("Loading " + url, true);
|
|
||||||
setProgressBarIndeterminateVisibility(true);
|
|
||||||
connect(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** React on the "Manage Certificates" button press. */
|
|
||||||
public void onManage(View view) {
|
|
||||||
final ArrayList<String> aliases = Collections.list(mtm.getCertificates());
|
|
||||||
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.select_dialog_item, aliases);
|
|
||||||
new AlertDialog.Builder(this).setTitle("Tap Certificate to Delete")
|
|
||||||
.setNegativeButton(android.R.string.cancel, null)
|
|
||||||
.setAdapter(adapter, new DialogInterface.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which) {
|
|
||||||
try {
|
|
||||||
String alias = aliases.get(which);
|
|
||||||
mtm.deleteCertificate(alias);
|
|
||||||
setText("Deleted " + alias, false);
|
|
||||||
} catch (KeyStoreException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
setText("Error: " + e.getLocalizedMessage(), false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.create().show();
|
|
||||||
}
|
|
||||||
}
|
|
Binary file not shown.
Before Width: | Height: | Size: 58 KiB |
Binary file not shown.
Before Width: | Height: | Size: 83 KiB |
Binary file not shown.
Before Width: | Height: | Size: 82 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,12 +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,7 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
|
|
||||||
<style name="ConversationsTheme" parent="@android:style/Theme.Material.Light.DarkActionBar" />
|
|
||||||
<style name="ConversationsTheme.Dark" parent="android:Theme.Material" />
|
|
||||||
|
|
||||||
</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,7 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<resources>
|
|
||||||
|
|
||||||
<style name="ConversationsTheme" parent="@android:style/Theme.Holo.Light.DarkActionBar" />
|
|
||||||
<style name="ConversationsTheme.Dark" parent="@android:style/Theme.Holo" />
|
|
||||||
|
|
||||||
</resources>
|
|
|
@ -1 +0,0 @@
|
||||||
include ':example'
|
|
|
@ -1,3 +1,3 @@
|
||||||
include ':libs:MemorizingTrustManager', ':libs:EnhancedListView'
|
include ':libs:EnhancedListView'
|
||||||
|
|
||||||
rootProject.name = 'Conversations'
|
rootProject.name = 'Conversations'
|
||||||
|
|
|
@ -179,10 +179,6 @@
|
||||||
android:name=".ui.TrustKeysActivity"
|
android:name=".ui.TrustKeysActivity"
|
||||||
android:label="@string/trust_omemo_fingerprints"
|
android:label="@string/trust_omemo_fingerprints"
|
||||||
android:windowSoftInputMode="stateAlwaysHidden" />
|
android:windowSoftInputMode="stateAlwaysHidden" />
|
||||||
<activity
|
|
||||||
android:name="de.duenndns.ssl.MemorizingActivity"
|
|
||||||
android:theme="@style/ConversationsTheme"
|
|
||||||
tools:replace="android:theme" />
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.AboutActivity"
|
android:name=".ui.AboutActivity"
|
||||||
android:label="@string/title_activity_about"
|
android:label="@string/title_activity_about"
|
||||||
|
@ -192,6 +188,7 @@
|
||||||
android:value="eu.siacs.conversations.ui.SettingsActivity" />
|
android:value="eu.siacs.conversations.ui.SettingsActivity" />
|
||||||
</activity>
|
</activity>
|
||||||
<activity android:name="com.soundcloud.android.crop.CropImageActivity" />
|
<activity android:name="com.soundcloud.android.crop.CropImageActivity" />
|
||||||
|
<activity android:name=".ui.MemorizingActivity"/>
|
||||||
|
|
||||||
<service android:name=".services.ExportLogsService" />
|
<service android:name=".services.ExportLogsService" />
|
||||||
<service
|
<service
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package de.duenndns.ssl;
|
package eu.siacs.conversations.crypto;
|
||||||
|
|
||||||
import javax.net.ssl.HostnameVerifier;
|
import javax.net.ssl.HostnameVerifier;
|
||||||
import javax.net.ssl.SSLSession;
|
import javax.net.ssl.SSLSession;
|
|
@ -25,8 +25,6 @@ import java.util.List;
|
||||||
|
|
||||||
import javax.net.ssl.SSLSession;
|
import javax.net.ssl.SSLSession;
|
||||||
|
|
||||||
import de.duenndns.ssl.DomainHostnameVerifier;
|
|
||||||
|
|
||||||
public class XmppDomainVerifier implements DomainHostnameVerifier {
|
public class XmppDomainVerifier implements DomainHostnameVerifier {
|
||||||
|
|
||||||
private static final String LOGTAG = "XmppDomainVerifier";
|
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
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package de.duenndns.ssl;
|
package eu.siacs.conversations.entities;
|
||||||
|
|
||||||
class MTMDecision {
|
public class MTMDecision {
|
||||||
public final static int DECISION_INVALID = 0;
|
public final static int DECISION_INVALID = 0;
|
||||||
public final static int DECISION_ABORT = 1;
|
public final static int DECISION_ABORT = 1;
|
||||||
public final static int DECISION_ONCE = 2;
|
public final static int DECISION_ONCE = 2;
|
||||||
public final static int DECISION_ALWAYS = 3;
|
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
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package de.duenndns.ssl;
|
package eu.siacs.conversations.services;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.Application;
|
import android.app.Application;
|
||||||
|
@ -74,6 +74,11 @@ import javax.net.ssl.TrustManager;
|
||||||
import javax.net.ssl.TrustManagerFactory;
|
import javax.net.ssl.TrustManagerFactory;
|
||||||
import javax.net.ssl.X509TrustManager;
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
|
||||||
|
import eu.siacs.conversations.R;
|
||||||
|
import eu.siacs.conversations.crypto.DomainHostnameVerifier;
|
||||||
|
import eu.siacs.conversations.entities.MTMDecision;
|
||||||
|
import eu.siacs.conversations.ui.MemorizingActivity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A X509 trust manager implementation which asks the user about invalid
|
* A X509 trust manager implementation which asks the user about invalid
|
||||||
* certificates and memorizes their decision.
|
* certificates and memorizes their decision.
|
||||||
|
@ -94,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");
|
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 = "de.duenndns.ssl.DECISION";
|
||||||
final static String DECISION_INTENT_ID = DECISION_INTENT + ".decisionId";
|
public final static String DECISION_INTENT_ID = DECISION_INTENT + ".decisionId";
|
||||||
final static String DECISION_INTENT_CERT = DECISION_INTENT + ".cert";
|
public final static String DECISION_INTENT_CERT = DECISION_INTENT + ".cert";
|
||||||
final static String DECISION_INTENT_CHOICE = DECISION_INTENT + ".decisionChoice";
|
final static String DECISION_INTENT_CHOICE = DECISION_INTENT + ".decisionChoice";
|
||||||
|
|
||||||
private final static Logger LOGGER = Logger.getLogger(MemorizingTrustManager.class.getName());
|
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;
|
private final static int NOTIFICATION_ID = 100509;
|
||||||
|
|
||||||
final static String NO_TRUST_ANCHOR = "Trust anchor for certification path not found.";
|
final static String NO_TRUST_ANCHOR = "Trust anchor for certification path not found.";
|
||||||
|
@ -758,7 +763,7 @@ public class MemorizingTrustManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static void interactResult(int decisionId, int choice) {
|
public static void interactResult(int decisionId, int choice) {
|
||||||
MTMDecision d;
|
MTMDecision d;
|
||||||
synchronized(openDecisions) {
|
synchronized(openDecisions) {
|
||||||
d = openDecisions.get(decisionId);
|
d = openDecisions.get(decisionId);
|
|
@ -66,7 +66,6 @@ import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
import de.duenndns.ssl.MemorizingTrustManager;
|
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
import eu.siacs.conversations.crypto.PgpDecryptionService;
|
import eu.siacs.conversations.crypto.PgpDecryptionService;
|
||||||
|
|
|
@ -21,11 +21,9 @@
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
* THE SOFTWARE.
|
* THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
package de.duenndns.ssl;
|
package eu.siacs.conversations.ui;
|
||||||
|
|
||||||
|
|
||||||
import android.app.Activity;
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.DialogInterface.OnCancelListener;
|
import android.content.DialogInterface.OnCancelListener;
|
||||||
import android.content.DialogInterface.OnClickListener;
|
import android.content.DialogInterface.OnClickListener;
|
||||||
|
@ -33,15 +31,19 @@ import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
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.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
public class MemorizingActivity extends Activity
|
import eu.siacs.conversations.R;
|
||||||
implements OnClickListener,OnCancelListener {
|
import eu.siacs.conversations.entities.MTMDecision;
|
||||||
|
import eu.siacs.conversations.services.MemorizingTrustManager;
|
||||||
|
|
||||||
|
public class MemorizingActivity extends AppCompatActivity implements OnClickListener,OnCancelListener {
|
||||||
|
|
||||||
private final static Logger LOGGER = Logger.getLogger(MemorizingActivity.class.getName());
|
private final static Logger LOGGER = Logger.getLogger(MemorizingActivity.class.getName());
|
||||||
public static final String THEME = "theme";
|
|
||||||
|
|
||||||
int decisionId;
|
int decisionId;
|
||||||
|
|
||||||
|
@ -64,9 +66,9 @@ public class MemorizingActivity extends Activity
|
||||||
LOGGER.log(Level.FINE, "onResume with " + i.getExtras() + " decId=" + decisionId + " data: " + i.getData());
|
LOGGER.log(Level.FINE, "onResume with " + i.getExtras() + " decId=" + decisionId + " data: " + i.getData());
|
||||||
dialog = new AlertDialog.Builder(this).setTitle(titleId)
|
dialog = new AlertDialog.Builder(this).setTitle(titleId)
|
||||||
.setMessage(cert)
|
.setMessage(cert)
|
||||||
.setPositiveButton(R.string.mtm_decision_always, this)
|
.setPositiveButton(R.string.always, this)
|
||||||
.setNeutralButton(R.string.mtm_decision_once, this)
|
.setNeutralButton(R.string.once, this)
|
||||||
.setNegativeButton(R.string.mtm_decision_abort, this)
|
.setNegativeButton(R.string.cancel, this)
|
||||||
.setOnCancelListener(this)
|
.setOnCancelListener(this)
|
||||||
.create();
|
.create();
|
||||||
dialog.show();
|
dialog.show();
|
||||||
|
@ -86,7 +88,7 @@ public class MemorizingActivity extends Activity
|
||||||
}
|
}
|
||||||
|
|
||||||
protected int findTheme() {
|
protected int findTheme() {
|
||||||
return getPreferences().getString(THEME, getResources().getString(R.string.theme)).equals("dark") ? R.style.ConversationsTheme_Dark : R.style.ConversationsTheme;
|
return getPreferences().getString(SettingsActivity.THEME, getResources().getString(R.string.theme)).equals("dark") ? R.style.ConversationsTheme_Dark : R.style.ConversationsTheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected SharedPreferences getPreferences() {
|
protected SharedPreferences getPreferences() {
|
|
@ -28,11 +28,11 @@ import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import de.duenndns.ssl.MemorizingTrustManager;
|
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.R;
|
import eu.siacs.conversations.R;
|
||||||
import eu.siacs.conversations.entities.Account;
|
import eu.siacs.conversations.entities.Account;
|
||||||
import eu.siacs.conversations.services.ExportLogsService;
|
import eu.siacs.conversations.services.ExportLogsService;
|
||||||
|
import eu.siacs.conversations.services.MemorizingTrustManager;
|
||||||
import eu.siacs.conversations.xmpp.XmppConnection;
|
import eu.siacs.conversations.xmpp.XmppConnection;
|
||||||
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
|
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
|
||||||
import eu.siacs.conversations.xmpp.jid.Jid;
|
import eu.siacs.conversations.xmpp.jid.Jid;
|
||||||
|
|
|
@ -49,9 +49,8 @@ import javax.net.ssl.SSLSocketFactory;
|
||||||
import javax.net.ssl.X509KeyManager;
|
import javax.net.ssl.X509KeyManager;
|
||||||
import javax.net.ssl.X509TrustManager;
|
import javax.net.ssl.X509TrustManager;
|
||||||
|
|
||||||
import de.duenndns.ssl.DomainHostnameVerifier;
|
|
||||||
import de.duenndns.ssl.MemorizingTrustManager;
|
|
||||||
import eu.siacs.conversations.Config;
|
import eu.siacs.conversations.Config;
|
||||||
|
import eu.siacs.conversations.crypto.DomainHostnameVerifier;
|
||||||
import eu.siacs.conversations.crypto.XmppDomainVerifier;
|
import eu.siacs.conversations.crypto.XmppDomainVerifier;
|
||||||
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
|
||||||
import eu.siacs.conversations.crypto.sasl.Anonymous;
|
import eu.siacs.conversations.crypto.sasl.Anonymous;
|
||||||
|
@ -66,6 +65,7 @@ import eu.siacs.conversations.entities.Message;
|
||||||
import eu.siacs.conversations.entities.ServiceDiscoveryResult;
|
import eu.siacs.conversations.entities.ServiceDiscoveryResult;
|
||||||
import eu.siacs.conversations.generator.IqGenerator;
|
import eu.siacs.conversations.generator.IqGenerator;
|
||||||
import eu.siacs.conversations.persistance.FileBackend;
|
import eu.siacs.conversations.persistance.FileBackend;
|
||||||
|
import eu.siacs.conversations.services.MemorizingTrustManager;
|
||||||
import eu.siacs.conversations.services.NotificationService;
|
import eu.siacs.conversations.services.NotificationService;
|
||||||
import eu.siacs.conversations.services.XmppConnectionService;
|
import eu.siacs.conversations.services.XmppConnectionService;
|
||||||
import eu.siacs.conversations.utils.CryptoHelper;
|
import eu.siacs.conversations.utils.CryptoHelper;
|
||||||
|
|
|
@ -735,4 +735,13 @@
|
||||||
<string name="private_messages_are_disabled">Private messages are disabled</string>
|
<string name="private_messages_are_disabled">Private messages are disabled</string>
|
||||||
<string name="huawei_protected_apps">Protected Apps</string>
|
<string name="huawei_protected_apps">Protected Apps</string>
|
||||||
<string name="huawei_protected_apps_summary">To keep receiving notifications, even when the screen is turned off, you need to add Conversations to the list of protected apps.</string>
|
<string name="huawei_protected_apps_summary">To keep receiving notifications, even when the screen is turned off, you need to add Conversations to the list of protected apps.</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>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in New Issue