forked from organicmaps/organicmaps
[android] Supported client cert - added cert for uploader
This commit is contained in:
parent
1305da5b91
commit
f14b93d95f
6 changed files with 32 additions and 205 deletions
|
@ -74,7 +74,7 @@ set(
|
|||
com/mapswithme/opengl/androidoglcontextfactory.cpp
|
||||
com/mapswithme/opengl/gl3stub.c
|
||||
com/mapswithme/platform/HttpThread.cpp
|
||||
com/mapswithme/platform/HttpUploader.cpp
|
||||
com/mapswithme/util/HttpUploader.cpp
|
||||
com/mapswithme/platform/HttpUserAgent.cpp
|
||||
com/mapswithme/platform/GuiThread.cpp
|
||||
com/mapswithme/platform/Language.cpp
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#include <jni.h>
|
||||
|
||||
#include "com/mapswithme/core/jni_helper.hpp"
|
||||
#include "com/mapswithme/core/ScopedEnv.hpp"
|
||||
#include "com/mapswithme/core/ScopedLocalRef.hpp"
|
||||
#include "com/mapswithme/core/jni_helper.hpp"
|
||||
|
||||
#include "platform/http_uploader.hpp"
|
||||
|
||||
|
@ -18,16 +18,16 @@ namespace
|
|||
platform::HttpUploader::Result ToNativeResult(JNIEnv * env, jobject const src)
|
||||
{
|
||||
static jmethodID const getHttpCode =
|
||||
env->GetMethodID(g_httpUploaderResultClazz, "getHttpCode", "()I");
|
||||
env->GetMethodID(g_httpUploaderResultClazz, "getHttpCode", "()I");
|
||||
static jmethodID const getDescription =
|
||||
env->GetMethodID(g_httpUploaderResultClazz, "getDescription", "()Ljava/lang/String;");
|
||||
env->GetMethodID(g_httpUploaderResultClazz, "getDescription", "()Ljava/lang/String;");
|
||||
|
||||
platform::HttpUploader::Result result;
|
||||
|
||||
result.m_httpCode = static_cast<int32_t>(env->CallIntMethod(src, getHttpCode));
|
||||
|
||||
jni::ScopedLocalRef<jstring> const description(
|
||||
env, static_cast<jstring>(env->CallObjectMethod(src, getDescription)));
|
||||
env, static_cast<jstring>(env->CallObjectMethod(src, getDescription)));
|
||||
result.m_description = jni::ToNativeString(env, description.get());
|
||||
|
||||
return result;
|
||||
|
@ -43,10 +43,11 @@ HttpUploader::Result HttpUploader::Upload() const
|
|||
CHECK(env, ());
|
||||
|
||||
static jmethodID const httpUploaderConstructor =
|
||||
jni::GetConstructorID(env, g_httpUploaderClazz, "(Ljava/lang/String;Ljava/lang/String;"
|
||||
"[Lcom/mapswithme/util/KeyValue;"
|
||||
"[Lcom/mapswithme/util/KeyValue;"
|
||||
"Ljava/lang/String;Ljava/lang/String;Z)V");
|
||||
jni::GetConstructorID(env, g_httpUploaderClazz,
|
||||
"(Ljava/lang/String;Ljava/lang/String;"
|
||||
"[Lcom/mapswithme/util/KeyValue;"
|
||||
"[Lcom/mapswithme/util/KeyValue;"
|
||||
"Ljava/lang/String;Ljava/lang/String;Z)V");
|
||||
|
||||
jni::ScopedLocalRef<jstring> const method(env, jni::ToJavaString(env, m_method));
|
||||
jni::ScopedLocalRef<jstring> const url(env, jni::ToJavaString(env, m_url));
|
||||
|
@ -56,15 +57,15 @@ HttpUploader::Result HttpUploader::Upload() const
|
|||
jni::ScopedLocalRef<jstring> const filePath(env, jni::ToJavaString(env, m_filePath));
|
||||
|
||||
jni::ScopedLocalRef<jobject> const httpUploaderObject(
|
||||
env, env->NewObject(g_httpUploaderClazz, httpUploaderConstructor, method.get(), url.get(),
|
||||
params.get(), headers.get(), fileKey.get(), filePath.get(),
|
||||
static_cast<jboolean>(m_needClientAuth)));
|
||||
env, env->NewObject(g_httpUploaderClazz, httpUploaderConstructor, method.get(), url.get(),
|
||||
params.get(), headers.get(), fileKey.get(), filePath.get(),
|
||||
static_cast<jboolean>(m_needClientAuth)));
|
||||
|
||||
static jmethodID const uploadId = jni::GetMethodID(env, httpUploaderObject, "upload",
|
||||
"()Lcom/mapswithme/util/HttpUploader$Result;");
|
||||
|
||||
jni::ScopedLocalRef<jobject> const result(
|
||||
env, env->CallObjectMethod(httpUploaderObject, uploadId));
|
||||
jni::ScopedLocalRef<jobject> const result(env,
|
||||
env->CallObjectMethod(httpUploaderObject, uploadId));
|
||||
|
||||
if (jni::HandleJavaException(env))
|
||||
{
|
||||
|
@ -76,16 +77,19 @@ HttpUploader::Result HttpUploader::Upload() const
|
|||
|
||||
return ToNativeResult(env, result);
|
||||
}
|
||||
} // namespace platform
|
||||
} // namespace platform
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_mapswithme_util_HttpUploader_nativeUserBindingCertificate(JNIEnv * env, jclass)
|
||||
extern "C"
|
||||
{
|
||||
return jni::ToJavaString(env, USER_BINDING_PKCS12);
|
||||
}
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_mapswithme_util_HttpUploader_nativeUserBindingCertificate(JNIEnv * env, jclass)
|
||||
{
|
||||
return jni::ToJavaString(env, USER_BINDING_PKCS12);
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_mapswithme_util_HttpUploader_nativeUserBindingPassword(JNIEnv * env, jclass)
|
||||
{
|
||||
return jni::ToJavaString(env, USER_BINDING_PKCS12_PASSWORD);
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_mapswithme_util_HttpUploader_nativeUserBindingPassword(JNIEnv * env, jclass)
|
||||
{
|
||||
return jni::ToJavaString(env, USER_BINDING_PKCS12_PASSWORD);
|
||||
}
|
||||
}
|
|
@ -1,10 +1,8 @@
|
|||
package com.mapswithme.maps;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.support.annotation.NonNull;
|
||||
|
|
|
@ -1,161 +0,0 @@
|
|||
package com.mapswithme.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.security.KeyManagementException;
|
||||
import java.security.KeyStore;
|
||||
import java.security.KeyStoreException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.UnrecoverableKeyException;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import org.apache.http.conn.ssl.SSLSocketFactory;
|
||||
|
||||
/**
|
||||
* Allows you to trust certificates from additional KeyStores in addition to
|
||||
* the default KeyStore
|
||||
*/
|
||||
public class AdditionalKeyStoresSSLSocketFactory extends javax.net.ssl.SSLSocketFactory
|
||||
{
|
||||
protected SSLContext sslContext = SSLContext.getInstance("TLS");
|
||||
|
||||
public AdditionalKeyStoresSSLSocketFactory(KeyStore keyStore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
|
||||
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
|
||||
kmf.init(keyStore, "".toCharArray());
|
||||
sslContext.init(kmf.getKeyManagers(), new TrustManager[]{new ClientKeyStoresTrustManager(keyStore)}, new SecureRandom());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getDefaultCipherSuites()
|
||||
{
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getSupportedCipherSuites()
|
||||
{
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException {
|
||||
return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket() throws IOException {
|
||||
return sslContext.getSocketFactory().createSocket();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String host, int port) throws IOException, UnknownHostException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress host, int port) throws IOException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Based on http://download.oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html#X509TrustManager
|
||||
*/
|
||||
public static class ClientKeyStoresTrustManager implements X509TrustManager {
|
||||
|
||||
protected ArrayList<X509TrustManager> x509TrustManagers = new ArrayList<X509TrustManager>();
|
||||
|
||||
protected ClientKeyStoresTrustManager(KeyStore... additionalkeyStores) {
|
||||
final ArrayList<TrustManagerFactory> factories = new ArrayList<TrustManagerFactory>();
|
||||
|
||||
try {
|
||||
// The default Trustmanager with default keystore
|
||||
final TrustManagerFactory original = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
original.init((KeyStore) null);
|
||||
factories.add(original);
|
||||
|
||||
for ( KeyStore keyStore : additionalkeyStores ) {
|
||||
final TrustManagerFactory additionalCerts = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
|
||||
additionalCerts.init(keyStore);
|
||||
factories.add(additionalCerts);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterate over the returned trustmanagers, and hold on
|
||||
* to any that are X509TrustManagers
|
||||
*/
|
||||
for (TrustManagerFactory tmf : factories)
|
||||
for ( TrustManager tm : tmf.getTrustManagers() )
|
||||
if (tm instanceof X509TrustManager)
|
||||
x509TrustManagers.add( (X509TrustManager) tm );
|
||||
|
||||
if ( x509TrustManagers.size() == 0 )
|
||||
throw new RuntimeException("Couldn't find any X509TrustManagers");
|
||||
|
||||
}
|
||||
|
||||
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
||||
for ( X509TrustManager tm : x509TrustManagers ) {
|
||||
try {
|
||||
tm.checkClientTrusted(chain, authType);
|
||||
return;
|
||||
} catch ( CertificateException e ) {
|
||||
|
||||
}
|
||||
}
|
||||
throw new CertificateException();
|
||||
}
|
||||
|
||||
/*
|
||||
* Loop over the trustmanagers until we find one that accepts our server
|
||||
*/
|
||||
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
||||
for ( X509TrustManager tm : x509TrustManagers ) {
|
||||
try {
|
||||
tm.checkServerTrusted(chain, authType);
|
||||
return;
|
||||
} catch ( CertificateException e ) {
|
||||
|
||||
}
|
||||
}
|
||||
throw new CertificateException();
|
||||
}
|
||||
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
final ArrayList<X509Certificate> list = new ArrayList<X509Certificate>();
|
||||
for ( X509TrustManager tm : x509TrustManagers )
|
||||
list.addAll(Arrays.asList(tm.getAcceptedIssuers()));
|
||||
return list.toArray(new X509Certificate[list.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -3,27 +3,21 @@ package com.mapswithme.util;
|
|||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.mapswithme.util.log.Logger;
|
||||
import com.mapswithme.util.log.LoggerFactory;
|
||||
|
||||
import javax.net.ssl.KeyManagerFactory;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.SSLSocketFactory;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyStore;
|
||||
import java.security.SecureRandom;
|
||||
|
||||
public class ClientCertTLSSocketFactory {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.INSTANCE.getLogger(LoggerFactory.Type.NETWORK);
|
||||
private static final String TAG = ClientCertTLSSocketFactory.class.getSimpleName();
|
||||
|
||||
private static final String PROTOCOL = "TLS";
|
||||
private static final String ALGORITHM = "X509";
|
||||
private static final String KEY_STORE_TYPE = "PKCS12";
|
||||
|
||||
@NonNull
|
||||
public static SSLSocketFactory create(@NonNull byte[] payload, @Nullable char[] password)
|
||||
{
|
||||
InputStream inputStream = null;
|
||||
|
@ -44,17 +38,7 @@ public class ClientCertTLSSocketFactory {
|
|||
}
|
||||
finally
|
||||
{
|
||||
if (inputStream != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
inputStream.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOGGER.d(TAG, "Stream not closed", e);
|
||||
}
|
||||
}
|
||||
Utils.closeSafely(inputStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import android.support.annotation.NonNull;
|
|||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import android.util.Base64;
|
||||
import com.mapswithme.maps.BuildConfig;
|
||||
import com.mapswithme.maps.Framework;
|
||||
import com.mapswithme.util.log.Logger;
|
||||
|
@ -149,7 +150,8 @@ public final class HttpUploader
|
|||
{
|
||||
String cert = HttpUploader.nativeUserBindingCertificate();
|
||||
String pwd = HttpUploader.nativeUserBindingPassword();
|
||||
SSLSocketFactory socketFactory = ClientCertTLSSocketFactory.create(cert.getBytes(), pwd.toCharArray());
|
||||
byte[] decodedCert = Base64.decode(cert, Base64.DEFAULT);
|
||||
SSLSocketFactory socketFactory = ClientCertTLSSocketFactory.create(decodedCert, pwd.toCharArray());
|
||||
connection.setSSLSocketFactory(socketFactory);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue