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

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

Open
akirasan opened this issue May 13, 2013 · 35 comments
Open
Labels

Comments

@akirasan
Copy link

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

@davivel
Copy link
Contributor

davivel commented May 14, 2013

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.

@akirasan
Copy link
Author

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.

@davivel
Copy link
Contributor

davivel commented May 14, 2013

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.

@akirasan
Copy link
Author

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

@akirasan
Copy link
Author

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.

@davivel
Copy link
Contributor

davivel commented May 14, 2013

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.

@beddari
Copy link

beddari commented Jul 7, 2013

Was just referenced here from przybylski/owncloud-android#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.

@asd-er
Copy link

asd-er commented Aug 6, 2013

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.

@davivel
Copy link
Contributor

davivel commented Nov 21, 2013

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

@tommys-place
Copy link

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;
}

@davivel
Copy link
Contributor

davivel commented Aug 28, 2014

@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.

@tommys-place
Copy link

@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.

@beddari
Copy link

beddari commented Aug 29, 2014

Thank you very much for showing this is indeed possible to support 👍

@flavio-pessoa
Copy link

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

@davivel
Copy link
Contributor

davivel commented Apr 30, 2015

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

@beddari
Copy link

beddari commented May 3, 2015

@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 👍 So far that has not happened but so is the nature of open source ... it doesn't mean it won't EVER happen.

@sakishrist
Copy link

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

@BentHaase
Copy link

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.

@luckyhacky
Copy link

+1

@wlp7s0
Copy link

wlp7s0 commented Dec 19, 2015

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.

@tobiasKaminsky
Copy link
Contributor

@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.

@agroeschl
Copy link

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?

@BentHaase
Copy link

@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.

@agroeschl
Copy link

@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"

@BentHaase
Copy link

@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?

@agroeschl
Copy link

@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.

@michaelstingl
Copy link
Contributor

Has been implemented in the ownCloud desktop sync client: owncloud/client#69 (comment)

@fjf2002
Copy link

fjf2002 commented Aug 6, 2017

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 .

@smalltoe
Copy link

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

@davigonz davigonz changed the title Use a SSL certificate to authenticate the client through https Use a client side SSL certificate to authenticate the client through https Oct 29, 2018
@jesmrec jesmrec added this to the 2.10.0 milestone Nov 6, 2018
@davigonz
Copy link
Contributor

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

@michaelstingl michaelstingl modified the milestones: 2.10.0, backlog Jan 8, 2019
@ghost
Copy link

ghost commented Jun 3, 2020

+1 for this feature.
This is the missing link for us for a almost perfect file-sharing solution across all devices in our company.

@jesmrec jesmrec removed the network label Aug 11, 2021
hannesa2 pushed a commit that referenced this issue Oct 9, 2023
Support in library for multiple public shares per file
@bsodcc
Copy link

bsodcc commented Nov 2, 2023

Any news? It still is not supported, would be great to have it, and as others say, its the only reason why I cannot use the android app

@jesmrec
Copy link
Collaborator

jesmrec commented Nov 2, 2023

no news

@bestrocker221
Copy link

Nextcloud just added this feature. Might be interesting for speeding up further development of the owncloud android project

nextcloud/android#603 (comment)
MR: nextcloud/android#12408

@JuancaG05 JuancaG05 removed this from the backlog milestone May 3, 2024
@lemiceo
Copy link

lemiceo commented Oct 15, 2024

Hello ! Really looking forward to this, it would decrease the attack barrier much further. As mentionned before, this is how Nextcloud Android client has implemented it. Thanks !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests