Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support client certificates #1005

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ configurations {
}

dependencies {
implementation 'com.github.stephanritscher:InteractiveKeyManager:0.1'
implementation 'org.apache.jackrabbit:jackrabbit-webdav:2.13.5'
api 'com.squareup.okhttp3:okhttp:5.0.0-alpha.10'
implementation 'com.gitlab.bitfireAT:dav4jvm:2.1.3' // in transition phase, we use old and new libs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

package com.owncloud.android.lib.common;

import android.content.Context;
import android.net.Uri;

import com.nextcloud.common.DNSCache;
Expand Down Expand Up @@ -53,6 +54,10 @@
import java.net.SocketTimeoutException;
import java.util.Locale;

import de.ritscher.ssl.InteractiveKeyManager;
import lombok.Getter;
import lombok.Setter;

public class OwnCloudClient extends HttpClient {

private static final String TAG = OwnCloudClient.class.getSimpleName();
Expand All @@ -69,17 +74,24 @@ public class OwnCloudClient extends HttpClient {
private OwnCloudCredentials credentials = null;
private int mInstanceNumber;

@Getter private Uri baseUri;
@Setter private String userId;
private Context context;

/**
* Constructor
*/
public OwnCloudClient(Uri baseUri, HttpConnectionManager connectionMgr) {
public OwnCloudClient(Uri baseUri, HttpConnectionManager connectionMgr, Context context) {
super(connectionMgr);

if (baseUri == null) {
throw new IllegalArgumentException("Parameter 'baseUri' cannot be NULL");
}
nextcloudUriDelegate = new NextcloudUriDelegate(baseUri);

this.baseUri = baseUri;
this.context = context;

mInstanceNumber = sInstanceCounter++;
Log_OC.d(TAG + " #" + mInstanceNumber, "Creating OwnCloudClient");

Expand Down Expand Up @@ -206,6 +218,10 @@ public int executeMethod(HttpMethod method) throws IOException {
// logCookiesAtState("after");
// logSetCookiesAtResponse(method.getResponseHeaders());

if (status >= 400 && status < 500) {
Log_OC.w(TAG, "executeMethod failed with error code " + status + "; remove key chain aliases disabled");
//new InteractiveKeyManager(context).removeKeys(baseUri.getHost(), baseUri.getPort());
}
return status;

} catch (SocketTimeoutException | ConnectException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,8 @@ public static OwnCloudClient createOwnCloudClient(Uri uri, Context context, bool
Log_OC.e(TAG, "The local server truststore could not be read. Default SSL management" +
" in the system will be used for HTTPS connections", e);
}
OwnCloudClient client = new OwnCloudClient(uri, NetworkUtils.getMultiThreadedConnManager());

OwnCloudClient client = new OwnCloudClient(uri, NetworkUtils.getMultiThreadedConnManager(), context);
client.setDefaultTimeouts(DEFAULT_DATA_TIMEOUT, DEFAULT_CONNECTION_TIMEOUT);
client.setFollowRedirects(followRedirects);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
package com.owncloud.android.lib.common.network;

import com.nextcloud.common.DNSCache;
import android.content.Context;
import android.util.Log;

import com.owncloud.android.lib.common.utils.Log_OC;

import org.apache.commons.httpclient.ConnectTimeoutException;
Expand All @@ -50,6 +53,8 @@
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;

import de.ritscher.ssl.InteractiveKeyManager;


/**
* AdvancedSSLProtocolSocketFactory allows to create SSL {@link Socket}s with
Expand All @@ -65,12 +70,14 @@ public class AdvancedSslSocketFactory implements SecureProtocolSocketFactory {
private SSLContext mSslContext = null;
private AdvancedX509TrustManager mTrustManager = null;
private X509HostnameVerifier mHostnameVerifier = null;
private Context mContext = null;

/**
* Constructor for AdvancedSSLProtocolSocketFactory.
*/
public AdvancedSslSocketFactory(
SSLContext sslContext, AdvancedX509TrustManager trustManager, X509HostnameVerifier hostnameVerifier
SSLContext sslContext, AdvancedX509TrustManager trustManager, X509HostnameVerifier hostnameVerifier,
Context context
) {

if (sslContext == null)
Expand All @@ -83,6 +90,7 @@ public AdvancedSslSocketFactory(
mSslContext = sslContext;
mTrustManager = trustManager;
mHostnameVerifier = hostnameVerifier;
mContext = context;
}

public SSLContext getSslContext() {
Expand Down Expand Up @@ -249,8 +257,13 @@ private void verifyPeerIdentity(String host, int port, Socket socket) throws IOE
/// (that should be an instance of AdvancedX509TrustManager)
try {
SSLSocket sock = (SSLSocket) socket; // a new SSLSession instance is created as a "side effect"
sock.startHandshake();

try {
sock.startHandshake();
} catch (SSLHandshakeException e1) {
Log.w(TAG, "SSL handshake failed; remove key chain aliases disabled", e1);
//new InteractiveKeyManager(mContext).removeKeys(sock.getInetAddress().getHostName(), sock.getPort());
throw e1;
}
} catch (RuntimeException e) {

if (e instanceof CertificateCombinedException) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,11 @@
import java.security.cert.CertificateException;

import javax.net.ssl.SSLContext;
import javax.net.ssl.KeyManager;
import javax.net.ssl.TrustManager;

import de.ritscher.ssl.InteractiveKeyManager;

public class NetworkUtils {

final private static String TAG = NetworkUtils.class.getSimpleName();
Expand Down Expand Up @@ -116,13 +119,23 @@ public static AdvancedSslSocketFactory getAdvancedSslSocketFactory(Context conte
if (mAdvancedSslSocketFactory == null) {
KeyStore trustStore = getKnownServersStore(context);
AdvancedX509TrustManager trustMgr = new AdvancedX509TrustManager(trustStore);
TrustManager[] tms = new TrustManager[]{trustMgr};
TrustManager[] tms = new TrustManager[] { trustMgr };
InteractiveKeyManager keyMgr = new InteractiveKeyManager(context);
KeyManager[] kms = new KeyManager[] { keyMgr };

SSLContext sslContext = getSSLContext();
sslContext.init(null, tms, null);
SSLContext sslContext;
try {
sslContext = SSLContext.getInstance("TLSv1.2");
} catch (NoSuchAlgorithmException e) {
Log_OC.w(TAG, "TLSv1.2 is not supported in this device; falling through TLSv1.0");
sslContext = SSLContext.getInstance("TLSv1");
// should be available in any device; see reference of supported protocols in
// http://developer.android.com/reference/javax/net/ssl/SSLSocket.html
}
sslContext.init(kms, tms, null);

Check failure

Code scanning / CodeQL

`TrustManager` that accepts all certificates

This uses [TrustManager](1), which is defined in [AdvancedX509TrustManager](2) and trusts any certificate.

mHostnameVerifier = new BrowserCompatHostnameVerifier();
mAdvancedSslSocketFactory = new AdvancedSslSocketFactory(sslContext, trustMgr, mHostnameVerifier);
mAdvancedSslSocketFactory = new AdvancedSslSocketFactory(sslContext, trustMgr, mHostnameVerifier, context);
}
return mAdvancedSslSocketFactory;
}
Expand Down
2 changes: 1 addition & 1 deletion sample_client/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ android {
exclude 'META-INF/LICENSE.txt'
}
defaultConfig {
minSdkVersion 14
minSdkVersion 21
targetSdkVersion 28
}
}
Expand Down