~singpolyma/cheogram-android

de0272fd1ac231a532bcc9fedcd5e81fb15cb209 — Daniel Gultsch 5 years ago bd90f21
integrate trust manager into conversations
46 files changed, 40 insertions(+), 1054 deletions(-)

M build.gradle
D libs/MemorizingTrustManager/.gitignore
D libs/MemorizingTrustManager/AndroidManifest.xml
D libs/MemorizingTrustManager/LICENSE.txt
D libs/MemorizingTrustManager/README.mdwn
D libs/MemorizingTrustManager/ant.properties
D libs/MemorizingTrustManager/build.gradle
D libs/MemorizingTrustManager/build.xml
D libs/MemorizingTrustManager/example/AndroidManifest.xml
D libs/MemorizingTrustManager/example/ant.properties
D libs/MemorizingTrustManager/example/build.gradle
D libs/MemorizingTrustManager/example/build.xml
D libs/MemorizingTrustManager/example/proguard-project.txt
D libs/MemorizingTrustManager/example/project.properties
D libs/MemorizingTrustManager/example/res/layout/mtmexample.xml
D libs/MemorizingTrustManager/example/res/values/strings.xml
D libs/MemorizingTrustManager/example/src/de/duenndns/mtmexample/JULHandler.java
D libs/MemorizingTrustManager/example/src/de/duenndns/mtmexample/MTMExample.java
D libs/MemorizingTrustManager/libs/.android_sucks
D libs/MemorizingTrustManager/mtm-notification.png
D libs/MemorizingTrustManager/mtm-screenshot.png
D libs/MemorizingTrustManager/mtm-servername.png
D libs/MemorizingTrustManager/proguard-project.txt
D libs/MemorizingTrustManager/project.properties
D libs/MemorizingTrustManager/res/values-de/strings.xml
D libs/MemorizingTrustManager/res/values-es/strings.xml
D libs/MemorizingTrustManager/res/values-eu/strings.xml
D libs/MemorizingTrustManager/res/values-fi/strings.xml
D libs/MemorizingTrustManager/res/values-fr/strings.xml
D libs/MemorizingTrustManager/res/values-no/strings.xml
D libs/MemorizingTrustManager/res/values-v21/themes.xml
D libs/MemorizingTrustManager/res/values/defaults.xml
D libs/MemorizingTrustManager/res/values/strings.xml
D libs/MemorizingTrustManager/res/values/themes.xml
D libs/MemorizingTrustManager/settings.gradle
M settings.gradle
M src/main/AndroidManifest.xml
R libs/MemorizingTrustManager/src/de/duenndns/ssl/DomainHostnameVerifier.java => src/main/java/eu/siacs/conversations/crypto/DomainHostnameVerifier.java
M src/main/java/eu/siacs/conversations/crypto/XmppDomainVerifier.java
R libs/MemorizingTrustManager/src/de/duenndns/ssl/MTMDecision.java => src/main/java/eu/siacs/conversations/entities/MTMDecision.java
R libs/MemorizingTrustManager/src/de/duenndns/ssl/MemorizingTrustManager.java => src/main/java/eu/siacs/conversations/services/MemorizingTrustManager.java
M src/main/java/eu/siacs/conversations/services/XmppConnectionService.java
R libs/MemorizingTrustManager/src/de/duenndns/ssl/MemorizingActivity.java => src/main/java/eu/siacs/conversations/ui/MemorizingActivity.java
M src/main/java/eu/siacs/conversations/ui/SettingsActivity.java
M src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java
M src/main/res/values/strings.xml
M build.gradle => build.gradle +0 -1
@@ 33,7 33,6 @@ ext {
}

dependencies {
    implementation project(':libs:MemorizingTrustManager')
    implementation project(':libs:EnhancedListView')
    playstoreImplementation 'com.google.android.gms:play-services-gcm:11.8.0'
    implementation 'org.sufficientlysecure:openpgp-api:10.0'

D libs/MemorizingTrustManager/.gitignore => libs/MemorizingTrustManager/.gitignore +0 -11
@@ 1,11 0,0 @@
bin
build
gen
local.properties
example/bin
example/gen
tags
.project
.classpath
.gradle
.*.swp

D libs/MemorizingTrustManager/AndroidManifest.xml => libs/MemorizingTrustManager/AndroidManifest.xml +0 -11
@@ 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>

D libs/MemorizingTrustManager/LICENSE.txt => libs/MemorizingTrustManager/LICENSE.txt +0 -21
@@ 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.

D libs/MemorizingTrustManager/README.mdwn => libs/MemorizingTrustManager/README.mdwn +0 -125
@@ 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/)!

D libs/MemorizingTrustManager/ant.properties => libs/MemorizingTrustManager/ant.properties +0 -17
@@ 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.


D libs/MemorizingTrustManager/build.gradle => libs/MemorizingTrustManager/build.gradle +0 -33
@@ 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']
		}
	}

}

D libs/MemorizingTrustManager/build.xml => libs/MemorizingTrustManager/build.xml +0 -92
@@ 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>

D libs/MemorizingTrustManager/example/AndroidManifest.xml => libs/MemorizingTrustManager/example/AndroidManifest.xml +0 -29
@@ 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> 

D libs/MemorizingTrustManager/example/ant.properties => libs/MemorizingTrustManager/example/ant.properties +0 -18
@@ 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

D libs/MemorizingTrustManager/example/build.gradle => libs/MemorizingTrustManager/example/build.gradle +0 -23
@@ 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']
		}
	}

}

D libs/MemorizingTrustManager/example/build.xml => libs/MemorizingTrustManager/example/build.xml +0 -92
@@ 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>

D libs/MemorizingTrustManager/example/proguard-project.txt => libs/MemorizingTrustManager/example/proguard-project.txt +0 -20
@@ 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 *;
#}

D libs/MemorizingTrustManager/example/project.properties => libs/MemorizingTrustManager/example/project.properties +0 -12
@@ 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

D libs/MemorizingTrustManager/example/res/layout/mtmexample.xml => libs/MemorizingTrustManager/example/res/layout/mtmexample.xml +0 -36
@@ 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>


D libs/MemorizingTrustManager/example/res/values/strings.xml => libs/MemorizingTrustManager/example/res/values/strings.xml +0 -4
@@ 1,4 0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">MemorizingTrustManager Example</string>
</resources>

D libs/MemorizingTrustManager/example/src/de/duenndns/mtmexample/JULHandler.java => libs/MemorizingTrustManager/example/src/de/duenndns/mtmexample/JULHandler.java +0 -169
@@ 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();
	}
}

D libs/MemorizingTrustManager/example/src/de/duenndns/mtmexample/MTMExample.java => libs/MemorizingTrustManager/example/src/de/duenndns/mtmexample/MTMExample.java +0 -143
@@ 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();
	}
}

D libs/MemorizingTrustManager/libs/.android_sucks => libs/MemorizingTrustManager/libs/.android_sucks +0 -0
D libs/MemorizingTrustManager/mtm-notification.png => libs/MemorizingTrustManager/mtm-notification.png +0 -0
D libs/MemorizingTrustManager/mtm-screenshot.png => libs/MemorizingTrustManager/mtm-screenshot.png +0 -0
D libs/MemorizingTrustManager/mtm-servername.png => libs/MemorizingTrustManager/mtm-servername.png +0 -0
D libs/MemorizingTrustManager/proguard-project.txt => libs/MemorizingTrustManager/proguard-project.txt +0 -20
@@ 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 *;
#}

D libs/MemorizingTrustManager/project.properties => libs/MemorizingTrustManager/project.properties +0 -12
@@ 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

D libs/MemorizingTrustManager/res/values-de/strings.xml => libs/MemorizingTrustManager/res/values-de/strings.xml +0 -17
@@ 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>

D libs/MemorizingTrustManager/res/values-es/strings.xml => libs/MemorizingTrustManager/res/values-es/strings.xml +0 -17
@@ 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>

D libs/MemorizingTrustManager/res/values-eu/strings.xml => libs/MemorizingTrustManager/res/values-eu/strings.xml +0 -17
@@ 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 \&quot;%s\&quot; 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>

D libs/MemorizingTrustManager/res/values-fi/strings.xml => libs/MemorizingTrustManager/res/values-fi/strings.xml +0 -16
@@ 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>

D libs/MemorizingTrustManager/res/values-fr/strings.xml => libs/MemorizingTrustManager/res/values-fr/strings.xml +0 -16
@@ 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>

D libs/MemorizingTrustManager/res/values-no/strings.xml => libs/MemorizingTrustManager/res/values-no/strings.xml +0 -16
@@ 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>

D libs/MemorizingTrustManager/res/values-v21/themes.xml => libs/MemorizingTrustManager/res/values-v21/themes.xml +0 -7
@@ 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>
\ No newline at end of file

D libs/MemorizingTrustManager/res/values/defaults.xml => libs/MemorizingTrustManager/res/values/defaults.xml +0 -4
@@ 1,4 0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="theme">light</string>
</resources>

D libs/MemorizingTrustManager/res/values/strings.xml => libs/MemorizingTrustManager/res/values/strings.xml +0 -17
@@ 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 \&quot;%s\&quot;. 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>

D libs/MemorizingTrustManager/res/values/themes.xml => libs/MemorizingTrustManager/res/values/themes.xml +0 -7
@@ 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>
\ No newline at end of file

D libs/MemorizingTrustManager/settings.gradle => libs/MemorizingTrustManager/settings.gradle +0 -1
@@ 1,1 0,0 @@
include ':example'

M settings.gradle => settings.gradle +1 -1
@@ 1,3 1,3 @@
include ':libs:MemorizingTrustManager', ':libs:EnhancedListView'
include ':libs:EnhancedListView'

rootProject.name = 'Conversations'

M src/main/AndroidManifest.xml => src/main/AndroidManifest.xml +1 -4
@@ 180,10 180,6 @@
            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"
            android:parentActivityName=".ui.SettingsActivity">


@@ 192,6 188,7 @@
                android:value="eu.siacs.conversations.ui.SettingsActivity" />
        </activity>
        <activity android:name="com.soundcloud.android.crop.CropImageActivity" />
        <activity android:name=".ui.MemorizingActivity"/>

        <service android:name=".services.ExportLogsService" />
        <service

R libs/MemorizingTrustManager/src/de/duenndns/ssl/DomainHostnameVerifier.java => src/main/java/eu/siacs/conversations/crypto/DomainHostnameVerifier.java +1 -1
@@ 1,4 1,4 @@
package de.duenndns.ssl;
package eu.siacs.conversations.crypto;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession;

M src/main/java/eu/siacs/conversations/crypto/XmppDomainVerifier.java => src/main/java/eu/siacs/conversations/crypto/XmppDomainVerifier.java +0 -2
@@ 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";

R libs/MemorizingTrustManager/src/de/duenndns/ssl/MTMDecision.java => src/main/java/eu/siacs/conversations/entities/MTMDecision.java +3 -3
@@ 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 eu.siacs.conversations.entities;

class MTMDecision {
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;
}

R libs/MemorizingTrustManager/src/de/duenndns/ssl/MemorizingTrustManager.java => src/main/java/eu/siacs/conversations/services/MemorizingTrustManager.java +10 -5
@@ 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 eu.siacs.conversations.services;

import android.app.Activity;
import android.app.Application;


@@ 74,6 74,11 @@ import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
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
 * 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");

	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.";


@@ 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;
		synchronized(openDecisions) {
			 d = openDecisions.get(decisionId);

M src/main/java/eu/siacs/conversations/services/XmppConnectionService.java => src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +0 -1
@@ 66,7 66,6 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

import de.duenndns.ssl.MemorizingTrustManager;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.crypto.PgpDecryptionService;

R libs/MemorizingTrustManager/src/de/duenndns/ssl/MemorizingActivity.java => src/main/java/eu/siacs/conversations/ui/MemorizingActivity.java +12 -10
@@ 21,11 21,9 @@
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * 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.OnCancelListener;
import android.content.DialogInterface.OnClickListener;


@@ 33,15 31,19 @@ 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 eu.siacs.conversations.R;
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());
	public static final String THEME = "theme";

	int decisionId;



@@ 64,9 66,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();


@@ 86,7 88,7 @@ public class MemorizingActivity extends Activity
	}

	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() {

M src/main/java/eu/siacs/conversations/ui/SettingsActivity.java => src/main/java/eu/siacs/conversations/ui/SettingsActivity.java +1 -1
@@ 28,11 28,11 @@ import java.util.Collections;
import java.util.List;
import java.util.Locale;

import de.duenndns.ssl.MemorizingTrustManager;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.services.ExportLogsService;
import eu.siacs.conversations.services.MemorizingTrustManager;
import eu.siacs.conversations.xmpp.XmppConnection;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;

M src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java => src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java +2 -2
@@ 49,9 49,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 eu.siacs.conversations.Config;
import eu.siacs.conversations.crypto.DomainHostnameVerifier;
import eu.siacs.conversations.crypto.XmppDomainVerifier;
import eu.siacs.conversations.crypto.axolotl.AxolotlService;
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.generator.IqGenerator;
import eu.siacs.conversations.persistance.FileBackend;
import eu.siacs.conversations.services.MemorizingTrustManager;
import eu.siacs.conversations.services.NotificationService;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.utils.CryptoHelper;

M src/main/res/values/strings.xml => src/main/res/values/strings.xml +9 -0
@@ 735,4 735,13 @@
	<string name="private_messages_are_disabled">Private messages are disabled</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="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 \&quot;%s\&quot;. 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>