android icon indicating copy to clipboard operation
android copied to clipboard

Use a client side SSL certificate to authenticate the client through https

Open akirasan opened this issue 12 years ago • 35 comments

Hi,

I've an owncloud 5.0 server with https connection. I open by NAT the web connection from internet and protect the access with a certificate (on Apache 2). Therefore, to access to my owncloud I use https and a certifcate generate from my server. All work fine from web navigator (IE, Chrome, Firefox,...) when I configure the certificate (pfx, for example).

If I try to configure the android client to my server, not setting the certificate is available and the error appear: "Failed the inicialization SSL" (sorry I translate from Spanish message).

Is possible use a own certificate (.pfx or .crt) to use in the https connection?? (from the android client).

Regards, Akirasan

akirasan avatar May 13 '13 15:05 akirasan

In the login view, you should see a modal dialog with the option to see details about the certificate and trust it. Doesn't it appear?

Does your server use SNI ? The Android app does not support HTTPS with SNI.

davivel avatar May 14 '13 07:05 davivel

I don't see a modal dialog. When I try to configure my https, this is the error I see (the port at the end is omitted, but the entered url is "https://akirasan.dyndns-home.com:/owncloud":

1368519707006 1368519709925

I need to check if Apache is configured with SNI, but I think that the problem is: where I define my own SSL-Certificate in the client?, this certificate is require by Apache server.

akirasan avatar May 14 '13 08:05 akirasan

In the modal dialog that is not appearing. Seems there is some kind of problem in the SSL initialization before the client can reach your SSL certificate. I see you use dyndns, I assume it uses HTTP redirections. Well, we know there is a bug with some types of redirections in the client that we need to fix. Probably that is you real problem, and not the certificate.

davivel avatar May 14 '13 08:05 davivel

Thanks David, I've tried to connect with my the public IP (not DynDNS service), and the result is the same. :(

akirasan avatar May 14 '13 09:05 akirasan

I've force to no use SNI on the Apache server with the directive "SSLStrictSNIVHostCheck off", but the result is the same (failed). I've tried both url's: with dyndns and static ip public.

This is the directive that I use in Apache for request the certificate to the clients: SSLVerifyClient require

If I comment the SSLVerifyClient in the configuration the connection from the android is established and I don't have any problem to use the client.

akirasan avatar May 14 '13 09:05 akirasan

Oh, sorry, I didn't understand you before.

The app supports the existance of server certificates to ensure the server identity. But we have no support by now for granting the client identity with a client-side certificate. That is what the SSLVerifyClient directive enables.

I am not sure if the client-side certification is what you really wanted, or just were trying to get a "regular" HTTPS connection.

davivel avatar May 14 '13 09:05 davivel

Was just referenced here from https://github.com/bartoszprzybylski/owncloud-android/issues/23

It would be nice to be able to use/provide/configure client-side certs like the OP suggests. This would provide another security layer in that ONLY client apps that you have given a cert (through whatever mechanism you have, some other channel) would ever be able to connect to the server.

beddari avatar Jul 07 '13 12:07 beddari

I agree, i've just setup ownCloud to require a client certificate to be able to connect. Unfortunately i can't use the Android app until support for this is added.

asd-er avatar Aug 06 '13 17:08 asd-er

Let me update the title so it's a bit clearer.

davivel avatar Nov 21 '13 17:11 davivel

Hi all,

I'm using ownCloud personaly on my own private server to sync mobile data with home server (nginx). I wanted to make connection more secure by using client side ssl certificate verification and have noticed SSL issues with Android app.

I've found solution and it is very simple.

Problems are in class com.owncloud.android.lib.common.network.NetworkUtils:

  1. location of ssl certificate store is wrong (not available on locked mobile) file knownServers.p12 should be in external cache dir /sdcard/Android/data/com.owncloud.android/cache/
  2. type of certificate store. For pkcs, file format should not be BKS, but PKCS12 file knownServers.p12 should be in pkcs12 format
  3. file knownServers.p12 should be protected with "password"

Solution is to replace two methods in mentioned class, here is the code. (it's not perfect but it works)

public static AdvancedSslSocketFactory getAdvancedSslSocketFactory(Context context) throws GeneralSecurityException, IOException {
    if (mAdvancedSslSocketFactory  == null) {           
        KeyStore trustStore = getKnownServersStore(context);
        AdvancedX509TrustManager trustMgr = new AdvancedX509TrustManager(trustStore);
        TrustManager[] tms = new TrustManager[] { trustMgr };

        SSLContext sslContext = SSLContext.getInstance("TLS");

        if("PKCS12".equals(KeyStore.getDefaultType())){
            String alg = KeyManagerFactory.getDefaultAlgorithm();
            KeyManagerFactory kmf = KeyManagerFactory.getInstance(alg);
            kmf.init(trustStore, LOCAL_TRUSTSTORE_PASSWORD.toCharArray());
            sslContext.init(kmf.getKeyManagers(), tms, null);
        } else {
            sslContext.init(null, tms, null);   
        }
        SSLContext.setDefault(sslContext);

        mHostnameVerifier = new BrowserCompatHostnameVerifier();
        mAdvancedSslSocketFactory = new AdvancedSslSocketFactory(sslContext, trustMgr, mHostnameVerifier);
    }
    return mAdvancedSslSocketFactory;
}

private static KeyStore getKnownServersStore(Context context) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
    if (mKnownServersStore == null) {                                   
        String defaultType = KeyStore.getDefaultType();
        Log.d(TAG, "Default store type :"  + defaultType);
        Security.setProperty("keystore.type", "PKCS12");
        File localTrustStoreFile = new File(context.getExternalCacheDir(), LOCAL_TRUSTSTORE_FILENAME.replace("bks", "p12"));
        Log.d(TAG, "Searching known-servers store at " + localTrustStoreFile.getAbsolutePath());
        if (!localTrustStoreFile.exists()) {
            Security.setProperty("keystore.type", defaultType);            
            localTrustStoreFile = new File(context.getFilesDir(), LOCAL_TRUSTSTORE_FILENAME);
            Log.d(TAG, "Searching known-servers store at " + localTrustStoreFile.getAbsolutePath());
        }

        //mKnownServersStore = KeyStore.getInstance("BKS");
        mKnownServersStore = KeyStore.getInstance(KeyStore.getDefaultType());            
        if (localTrustStoreFile.exists()) {
            InputStream in = new FileInputStream(localTrustStoreFile);
            try {
                mKnownServersStore.load(in, LOCAL_TRUSTSTORE_PASSWORD.toCharArray());
            } finally {
                in.close();
            }
        } else {
            mKnownServersStore.load(null, LOCAL_TRUSTSTORE_PASSWORD.toCharArray()); // necessary to initialize an empty KeyStore instance
        }
    }
    return mKnownServersStore;
}

tommys-place avatar Aug 26 '14 11:08 tommys-place

@tommys-place,

  • You say you "have noticed SSL issues", but you do not say what they are. We would appreciate you explained us what are the problems before providing a solution.
  • This issue is about using client certificates for authentication, not for anything about SSL. You say you tried to implement client side authentication, but I cannot understand how you do it with that code. Please, could you explain a bit more?
  • The keystore is stored in the private space of the app so that no other app can access to it; it's for exclusive use of the OC app. This is on purpose, we do not know any reason to move the file to a shared location. The keystore, besides, is only for server certificates, not for client ones.

davivel avatar Aug 28 '14 10:08 davivel

@davivel,

Sorry I was not clear enough.

As I understand, this thread is about client side SSL authetication issue? I have the same problem with SSL client certificate authentication so I've found solution that works for me. And this is what I posted here. This is the answer to your first question. Please read my second sentence once more....

I wanted to make connection more secure by using client side ssl certificate verification and have noticed SSL issues with Android app. Meaning , "I could not use client side SSL certificate authentication also"

I have modified original code to check for the private keys store in the first place and if not found, fallback to functionality of original version of the code. So, if someone needs client side SSL authentication, this code will search for p12 format keystore and try to load private keychain for authetication with the server. P12 keystore is the same one used in browsers but with different extension (pfx)

Java SSL engine should be configured differently when working with client side SSL authetication.

As mentioned, It's not perfect, but it works. Real solution would be possibility to import private ssl certificate into keystore stored in the private space of the app. This will require a lot more work than adding a quick fix. So my solution is a quick fix because I'm not Android developer and I needed SSL client side authtication.

Maybe there is an other way to put private SSL certificate in protected store but as i'm not android developer, I don't know how to do it. I didn't want to bother too much with changing a lot of code and I've used standard Java functionality... see method getKnownServersStore.

   -- keep original default store type (bks)
   String defaultType = KeyStore.getDefaultType();

    -- switch ssl engine to p12 
    Security.setProperty("keystore.type", "PKCS12");

Later, try to load p12 keystore and if not found , return engine to bks format and original functionality.

I hope it is more clear now.

cheers.

tommys-place avatar Aug 28 '14 11:08 tommys-place

Thank you very much for showing this is indeed possible to support :+1:

beddari avatar Aug 29 '14 07:08 beddari

I need this fix, the last post was 29 Aug 2014, will be fix???

flavio-pessoa avatar Apr 21 '15 22:04 flavio-pessoa

We don't have an estimated time of arrival for this feature. Being honest, right now this is not a high priority for us.

davivel avatar Apr 30 '15 06:04 davivel

@davivel Thanks for replying. I'd just add that I'm very glad @tommys-place stepped up to explain in detail how this could be implemented. At this point any larger organization with the resources needed could pick this up easily :+1: So far that has not happened but so is the nature of open source ... it doesn't mean it won't EVER happen.

beddari avatar May 03 '15 07:05 beddari

+1 for this. An additional layer of security through client certification would be a Very nice thing to have.

sakishrist avatar Aug 06 '15 16:08 sakishrist

Is there still development or any work around for this bug? I cannot use my OwnCloud weather with official certificates or self signed ones I always get the "SSL initialization failed" error. I don't want an ETA I just wan't to know if this get fixed anyway because for me and many others this makes the app unusable.

bentalexanderhaase avatar Oct 12 '15 13:10 bentalexanderhaase

+1

luckyhacky avatar Nov 28 '15 18:11 luckyhacky

This thread was created in 2013 and this feature wasn't implemented yet. Is there any chance it can be added? I can't use android mobile app because of this error. Thanks for answer.

wlp7s0 avatar Dec 19 '15 23:12 wlp7s0

@wip7s0 there is just not enough man power to do all wishes. The best would be a contribution. That would speed it up...

@ET-Bent "with official certificates or self signed". This issue is about client certificates. I think you are talking about server certificates? If so, please open a new issue and we can try to help you.

tobiasKaminsky avatar Dec 20 '15 07:12 tobiasKaminsky

Okay I'm the next one with the same problem.

@tommys-place run your quick fix without problems?

Is there any work around this bug?

agroeschl avatar Jan 10 '16 19:01 agroeschl

@tobiasKaminsky @agroeschl I fixed the issue by using this https://www.ssllabs.com/ssltest/ to see all issues with my ssl setup. It turned out that I had some issues with my keychain. After resolving all issues that SSLLabs selftest showed all works fine on any phone and pc.

bentalexanderhaase avatar Jan 10 '16 19:01 bentalexanderhaase

@et-bent sorry but how can this fix the bug in the owncloud Android APP?

I have the same Problem as akirasan and tommys-place: I wanted to make connection more secure by using client side ssl certificate verification and have noticed SSL issues with Android app. Meaning , "I could not use client side SSL certificate authentication"

agroeschl avatar Jan 10 '16 20:01 agroeschl

@agroeschl Sorry I misunderstood you then, so you are referring to the fact that the OwnCloud App does not allow to use SSL Certificates as authentication method right?

bentalexanderhaase avatar Jan 10 '16 20:01 bentalexanderhaase

@ET-BENT I'm using SSLVerifyClient require in Apache to increase the owncloud security. And I have no problems with Firefox, IE or chrome.

But the owncloud APP doesn't work. I get the same error message as described in this thread.

agroeschl avatar Jan 10 '16 20:01 agroeschl

Has been implemented in the ownCloud desktop sync client: https://github.com/owncloud/client/issues/69#issuecomment-264898683

michaelstingl avatar Aug 01 '17 16:08 michaelstingl

Hello everybody,

I'm also interested in client certificate authentication.

As far as I understand, the suggestion of tommys-place of 26 Aug 2014 was kindof roasted by davivel - and it looks like since then, no more efforts have been made on this topic?

I didn't want to wait any longer and tried to implement client-cert auth myself. Seems to work.

The user experience is just like in the web browser: A dialog will pop up that lists all installed client certificates, so that the user can choose one.

Changes in code in short:

  1. I have borrowed the class KeyChainKeyManager from https://android.googlesource.com/platform/packages/apps/KeyChain/+/aa14e89b1194c4d4054fcd8dbd0af9d08dd5715c/tests/src/com/android/keychain/tests/KeyChainTestActivity.java
  2. ... and used in com.owncloud.android.lib.common.network.NetworkUtils.getAdvancedSslSocketFactory(...) .

Problems:

  1. Since I'm new to owncloud development, what are the next steps? a. Sigining https://owncloud.org/wp-content/themes/owncloudorgnew/assets/files/owncloud-copyright-assignment-common.pdf ? and b. issuing a pull request? c. Or just posting the code here?
  2. I have questions left concerning the architecture, i. e. a. The android.security.KeyChain.choosePrivateKeyAlias method which I used needs a reference to the parent Activity. Am I really supposed to pass that reference through the whole call hierarchy into the utility class NetworkUtils? - My current version uses a global variable. That's very dirty, of course. b. I am not using application private storage for the client certificate. I load them from android system-wide certificate storage (Settings->Security->User credentials ("Nutzeranmeldedaten")). This is not consistent with the current functionality concerining the server-side certificates, which I consider as quite strange: Server-Side certs for which I have installed system-wide Root Certs (Settings->Security->Trusted credentials ("Vertrauenswürdige Anmeldedaten") are shown as untrusted(!) and I have to trust them manually by clicking yes in a dialog. Then, they seem to get copied in app private storage!?

Thanks in advance for any hints concerning functionality or integration into owncloud-android .

fjf2002 avatar Aug 06 '17 13:08 fjf2002

Great project an thanks to contributors. I would be happy to see this functionality.

smalltoe avatar Jan 14 '18 21:01 smalltoe

@tommys-place @fjf2002 have you touched the server to make your code explained in comments above works? Thanks

davigonz avatar Nov 16 '18 09:11 davigonz