Discussion:
PKCS12 with password
nmset
2011-07-25 12:10:02 UTC
Permalink
Hello,

Gajim is excellent for client authentication through credentials stored in a PKCS12 container. It rejects however a PKCS12 file
protected by a password.

tlsnb_nb.py opens the PKCS12 file with :

p12 = OpenSSL.crypto.load_pkcs12(open(conn.client_cert).read())

It may also open a password protected PKCS12 container with :

p12 = OpenSSL.crypto.load_pkcs12(open(conn.client_cert).read(), p12pwd)

Testing with hard-coded password works fine.

I don't have the resources to code in Python, I guess it would be fairly easy for Python gurus to modify tls_nb.py to popup a
dialog requesting a password for the container. This will enhance security when connecting to a jabberd server from a host
accessed by many users in one same desktop session, each one having created an account in Gajim and each one having a
client certificate with the certificate's cn == jid (the server doesn't request password authentication in this case).

So this is a request that may enhance security in certain use cases. Of course it's not for the common user who just want
to beep short messages at the other end of the globe.

Thank you for considering.
Yann Leboulanger
2011-07-25 13:17:57 UTC
Permalink
Post by nmset
Hello,
Gajim is excellent for client authentication through credentials stored in a PKCS12 container. It rejects however a PKCS12 file
protected by a password.
p12 = OpenSSL.crypto.load_pkcs12(open(conn.client_cert).read())
p12 = OpenSSL.crypto.load_pkcs12(open(conn.client_cert).read(), p12pwd)
Testing with hard-coded password works fine.
I don't have the resources to code in Python, I guess it would be fairly easy for Python gurus to modify tls_nb.py to popup a
dialog requesting a password for the container.
Hi,

It's not that easy because tls_nb.py has nothing to do with GUI, so it
cannot display a dialog itself. Connection object should try to open the
certificat, if that fails, asks a password, before trying to connect.
But I can look at that.

Could you tell me what happens if you call directly
OpenSSL.crypto.load_pkcs12(open(PATH_TO_CERT).read()) on a password
protected cert? Does it raises a message about missing password?
I ask that to know how to detect it's protected or not.
--
Yann
Saleem Edah-Tally
2011-07-25 14:12:56 UTC
Permalink
Here's the CLI output running gajim in non-verbose, with a PKCS12 password
protected container :

*************************************************************************************

16:01:50 (W) gajim.c.x.tls_nb Unable to load client pkcs12 certificate from file
/home/user/xmpp_lab_set_pwd.p12: ([('PKCS12 routines', 'PKCS12_parse', 'mac
verify failure')],) ... Is it a valid PKCS12 cert?
16:01:50 (E) gajim.c.x.tls_nb Error while TLS handshake:
Traceback (most recent call last):
File "/usr/share/gajim/src/common/xmpp/tls_nb.py", line 422, in
_startSSL_pyOpenSSL
tcpsock._sslObj.do_handshake()
SysCallError: (-1, 'Unexpected EOF')
*************************************************************************************


Attached is a verbose log also.

More precision : I am using jabberd2 2.2.14 configured to accept only encrypted
connections.

Thank you for considering.





----- Message d'origine ----
De : Yann Leboulanger <***@lagaule.org>
À : nmset <***@yahoo.com>
Cc : Gajim Devel <gajim-***@gajim.org>
Envoyé le : Lun 25 juillet 2011, 15h 17min 57s
Objet : Re: [Gajim-devel] PKCS12 with password
Yann Leboulanger
2011-07-25 15:06:35 UTC
Permalink
the only thing I see is that:

Unable to load client pkcs12 certificate from file
/home/user/xmpp_lab_set_pwd.p12: ([('PKCS12 routines', 'PKCS12_parse',
'mac verify failure')],) ... Is it a valid PKCS12 cert?

which isn't very explicit why it fails to open the cert. We don't know
if it's because it's encrypted.
import OpenSSL.crypto
OpenSSL.crypto.load_pkcs12(open('FULL_PATH_TO_YOUR_CERT').read())
what does that print?

The only other solution I see is: try to open cert, if that fails for
any reason, ask for a passphrase. That's not very nice, but why not ...
Saleem Edah-Tally
2011-07-25 18:16:25 UTC
Permalink
import OpenSSL.crypto
OpenSSL.crypto.load_pkcs12(open('/home/user/xmpp_lab_set_pwd.p12').read())
Traceback (most recent call
last):

File "<stdin>", line 1, in
<module>

OpenSSL.crypto.Error: [('PKCS12 routines', 'PKCS12_parse', 'mac verify
failure')]
OpenSSL.crypto.load_pkcs12(open('/home/user/xmpp_lab_set_pwd.p12').read(),
'REAL_PWD')
<PKCS12 object at 0x7f33978ffb90>

Well it's really because the PKCS12 container is encrypted. If I remove the
password from the same p12 file, I can authenticate successfully.

I don't know at all if it's a huge task but it would complete the effectiveness
of the whole security approach.

Much emphasis has been laid out with MITM attacks in diverse fields of
electronic cummunication. It's a real threat, but it's more likely that userA
steals userB unencrypted credentials in a desktop session that is supposed to be
used by many users and do whatever evil afterwards, pretending to be userB.
userA will most probably lack required skills to sniff the network, intercept
userB's communications, decrypt, alter and re-encrypt the content which he then
forwards to userC.

(I am well aware that super hackers, national security agencies can do
unthinkable piracy acts for whatever reason, but that's not the point here).

Have a nice day !





----- Message d'origine ----
De : Yann Leboulanger <***@lagaule.org>
À : Saleem Edah-Tally <***@yahoo.com>
Cc : gajim-***@gajim.org
Envoyé le : Lun 25 juillet 2011, 17h 06min 35s
Objet : Re: Re : [Gajim-devel] PKCS12 with password
Saleem Edah-Tally
2011-07-25 20:23:53 UTC
Permalink
----- Message d'origine ----

De : Yann Leboulanger <***@lagaule.org>
À : nmset <***@yahoo.com>
Cc : Gajim Devel <gajim-***@gajim.org>
Envoyé le : Lun 25 juillet 2011, 15h 17min 57s
Objet : Re: [Gajim-devel] PKCS12 with password
Post by Yann Leboulanger
Connection object should try to open the
certificat, if that fails, asks a password, before trying to connect.
One suggestion :

In the UI where the user declares what p12 to use for his account, there could
be a checkbox with which the user says if the p12 file is encrypted or not.

This way, the code in tls_nb.py does not have to be exception dependent but
rather based on user declaration.

If the user has declared an encrypted p12 file, a dialog asks for the password
and load_pkcs is called with two arguments (the file, the password), else, with
one single argument. as it is now.
Saleem Edah-Tally
2011-07-26 17:29:00 UTC
Permalink
Yep I'll do that.
Which version of Gajim do you use? Do you use development version? If I
send you a patch for this version, could you test it as I cannot test
that myself?
From debian repos : Gajim 0.14.0.1-51c9600fc1f1
But I did also compile 0.14.4 from source successfully.

As for the development version, if you post a relevant link, I could compile it
also.

Usually we patch a reference source tree, in its simplest form, with

patch -p1 < patch.file

I just have to know what the reference version is and grab it.

Thanks.
Yann Leboulanger
2011-07-26 17:57:23 UTC
Permalink
Yep I'll do that.
Which version of Gajim do you use? Do you use development version? If I
send you a patch for this version, could you test it as I cannot test
that myself?
From debian repos : Gajim 0.14.0.1-51c9600fc1f1
But I did also compile 0.14.4 from source successfully.
As for the development version, if you post a relevant link, I could compile it
also.
Usually we patch a reference source tree, in its simplest form, with
patch -p1< patch.file
I just have to know what the reference version is and grab it.
Thanks.
Ok nice, just:
hg clone http://hg.gajim.org/gajim gajim-dev
cd gajim-dev
patch -p1 < cert.diff (attached)
./launch.sh

There is now a checkbox near the place where you set the path of the
certificate.

Thanks for testing!
--
Yann
Saleem Edah-Tally
2011-07-26 19:42:25 UTC
Permalink
1. Connecting an account with an encrypted PKCS12 container
**************************************************************************

It works flawlessly. The checkbox is 'checked', a dialog pops up upon
connection to request the container password and then connection proceeds
successfully.


2. Connecting an account with an UNencrypted PKCS12 container
******************************************************************************

It fails constantly, a dialog appears proposing plain connection.

Err output :
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

ici
21:20:53 (W) gajim.c.x.tls_nb Unknown error while loading certificate from file
/home/user/xmpp_lab_test.p12
21:20:53 (E) gajim.c.x.tls_nb Error while TLS handshake:
Traceback (most recent call last):
File "/home/user/tmp/gajim-dev/src/common/xmpp/tls_nb.py", line 423, in
_startSSL_pyOpenSSL
tcpsock._sslObj.do_handshake()
SysCallError: (-1, 'Unexpected EOF')
ici
ici
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



So it seems to have created one unexpected problem if the container is not
password protected.

Looking into tls_nb.py, I have modified line 362 as follows :

if (conn.client_cert_passphrase == None) :
p12 = OpenSSL.crypto.load_pkcs12(open(conn.client_cert).read())
else:
p12 = OpenSSL.crypto.load_pkcs12(open(conn.client_cert).read(),
conn.client_cert_passphrase)

This way I can connect with both encrypted and unencrypted p12 containers.

Well it's all like I could imagine. I suppose it would be committed in the next
release.

By the way, I've tested a few other XMPP clients, Gajim is the only one I've
seen that binds an account to its own SSL credentials, and that's great.

Thank you very much.
Post by Yann Leboulanger
hg clone http://hg.gajim.org/gajim gajim-dev
cd gajim-dev
patch -p1 < cert.diff (attached)
.>/launch.sh
Yann Leboulanger
2011-07-26 20:05:22 UTC
Permalink
Post by Saleem Edah-Tally
1. Connecting an account with an encrypted PKCS12 container
**************************************************************************
It works flawlessly. The checkbox is 'checked', a dialog pops up upon
connection to request the container password and then connection proceeds
successfully.
Good start!
Post by Saleem Edah-Tally
2. Connecting an account with an UNencrypted PKCS12 container
******************************************************************************
It fails constantly, a dialog appears proposing plain connection.
Ok, it's probably because I try to open cert file with None password:
OpenSSL.crypto.load_pkcs12(open(CERT_PATH).read(), None)

Could you try that in a console:
import OpenSSL.crypto
OpenSSL.crypto.load_pkcs12(open(CERT_PATH).read(), '')

if that doesn't work I'll call it without the second argument.

Thanks
--
Yann
Saleem Edah-Tally
2011-07-26 20:33:36 UTC
Permalink
import OpenSSL.crypto
OpenSSL.crypto.load_pkcs12(open(CERT_PATH).read(), '')
if that doesn't work I'll call it without the second argument
Here's the result :

*******************************************************************************************

Python 2.6.6 (r266:84292, Dec 26 2010, 22:31:48)
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
import OpenSSL.crypto
OpenSSL.crypto.load_pkcs12(open('/home/user/xmpp_lab_test.p12').read(), '')
<PKCS12 object at 0x7f48788485a0>
*******************************************************************************************


So opening with an empty 'string' works fine. So the password argument can
default to '' rather than None.

Thanks.
Yann Leboulanger
2011-07-26 20:45:02 UTC
Permalink
Post by Saleem Edah-Tally
import OpenSSL.crypto
OpenSSL.crypto.load_pkcs12(open(CERT_PATH).read(), '')
if that doesn't work I'll call it without the second argument
*******************************************************************************************
Python 2.6.6 (r266:84292, Dec 26 2010, 22:31:48)
[GCC 4.4.5] on linux2
Type "help", "copyright", "credits" or "license" for more information.
import OpenSSL.crypto
OpenSSL.crypto.load_pkcs12(open('/home/user/xmpp_lab_test.p12').read(), '')
<PKCS12 object at 0x7f48788485a0>
*******************************************************************************************
So opening with an empty 'string' works fine. So the password argument can
default to '' rather than None.
Perfect, it's commited to trunk.

Thanks for the tests!
You can use it by doing:
hg revert -a
hg pull -u
./launch.sh
--
Yann
Saleem Edah-Tally
2011-07-27 05:00:22 UTC
Permalink
Post by Yann Leboulanger
Perfect, it's commited to trunk.
Thanks for the tests!
Unfortunately, connecting with an unencrypted p12 container still constantly
fails with the following error :

*********************************************************************************************

06:47:51 (W) gajim.c.x.tls_nb Unknown error while loading certificate from file
/home/user/xmpp_lab_test.p12
06:47:51 (E) gajim.c.x.tls_nb Error while TLS handshake:
Traceback (most recent call last):
File "/home/user/tmp/gajim-dev/src/common/xmpp/tls_nb.py", line 423, in
_startSSL_pyOpenSSL
tcpsock._sslObj.do_handshake()
SysCallError: (-1, 'Unexpected EOF')
*********************************************************************************************


It seems that conn.client_cert_passphrase in tls_nb.py still defaults to None.
Connection succeeds with :
*********************************************************************************************

if (conn.client_cert_passphrase == None):
conn.client_cert_passphrase = ''
p12 = OpenSSL.crypto.load_pkcs12(open(conn.client_cert).read(),
conn.client_cert_passphrase)
*********************************************************************************************
Yann Leboulanger
2011-07-28 20:43:53 UTC
Permalink
Post by Saleem Edah-Tally
Post by Yann Leboulanger
Perfect, it's commited to trunk.
Thanks for the tests!
Unfortunately, connecting with an unencrypted p12 container still constantly
Indeed I did a mistake. Should be fixed now.

Thanks
--
Yann
Loading...