nm-l2tp / NetworkManager-l2tp

L2TP and L2TP/IPsec support for NetworkManager
GNU General Public License v2.0
486 stars 84 forks source link

p12 certificate - error parsing #121

Closed madman9999 closed 4 years ago

madman9999 commented 4 years ago

Hello,

I try to use a p12 certificate, wha I am missing? Why does the l2tp Plugin can't parse the p12 file? Using Linux Mint 19.3

Feb 14 23:38:16 soeren-virtual-machine NetworkManager[747]: [1581719896.4346] vpn-connection[0x55a11314e170,e9487b28-06ab-4e37-a4c4-7273cef99cec,"L2TP",0]: VPN connection: failed to connect: 'Error parsing PKCS#12 file '/home/soeren/macbook.p12'.' Feb 14 23:38:16 soeren-virtual-machine NetworkManager[747]: [1581719896.4480] vpn-connection[0x55a11314e170,e9487b28-06ab-4e37-a4c4-7273cef99cec,"L2TP",0]: VPN plugin: state changed: stopped (6) Feb 14 23:39:17 soeren-virtual-machine gcr-viewer: Libgcrypt warning: missing initialization - please fix the application

Thanks

dkosovic commented 4 years ago

As it is using libcrypto from openssl, can you confirm that the openssl command-line is able to parse the certificate without error by doing the following ? :

openssl pkcs12 -info -in /home/soeren/macbook.p12

You might be prompted to to enter the password 3 times, but that is normal.

The error is from the following code :

The error might be a bit misleading as it could also mean the the certificate's password isn't correct.

madman9999 commented 4 years ago

The command works without any issue, I can see the certificate. But the l2tp plugin still shows the same error.

Does the plugin need something else to work?

dkosovic commented 4 years ago

With the below code which uses the OpenSSL PKCS12_parse() function and produces the Error parsing PKCS#12 file, it only takes 2 inputs, the PKCS#12 certificate and the password. So the issue can only be with either the file or the password.

if (!PKCS12_parse(p12, password, &pkey, &cert, &ca)) {
    g_set_error (error, NM_CRYPTO_ERROR,
                 NM_CRYPTO_ERROR_DECRYPTION_FAILED,
                 _("Error parsing PKCS#12 file '%s'."),
                 p12_filename);
    PKCS12_free(p12);
    return;
}

As you have confirmed you are using the same password with NetworkManager-l2tp as you used on the command-line, the only thing I can think of is that the password is getting corrupted.

Extract from the PKCS12_parse() documentation regarding the password parameter :

The password parameter is interpreted as a string in the UTF-8 encoding. If it is not valid UTF-8, then it is assumed to be ISO8859-1 instead.

In particular, this means that passwords in the locale character set must potentially be converted to UTF-8 before use. This may include passwords from local text files, or input from the terminal or command line.

I'm not sure which language or locale character set the certificate's password is in, but I'm guessing the conversion is getting corrupted.

Could you try removing the certificate's password, in the following you will end up with a new unprotected.p12 certificate which has an empty password :

Export to temporary pem file

openssl pkcs12 -in protected.p12 -nodes -out temp.pem
#  -> Enter password

Convert pem back to p12

openssl pkcs12 -export -in temp.pem  -out unprotected.p12
# -> Just press [enter] twice for no password

Remove temporary pem file

rm temp.pem

now try using the unprotected.p12 file in the NetworkManager-l2tp GUI editor.

madman9999 commented 4 years ago

If I use the certificate without password, it works.

I compiled the latest version for Linux Mint 19.3 using the steps mentioned on the homepage. Did I maybe miss something? It looks, that somehow the password get corrupted.

Thanks

dkosovic commented 4 years ago

What is the output of the locale command, in particular LANG ? e.g. :

$ locale
LANG=en_AU.UTF-8
LANGUAGE=en_AU:en_GB:en
LC_CTYPE="en_AU.UTF-8"
...

The password stored in macbook.p12 might be something other than UTF-8.

Try modifying the source code to use a locale based password instead of UTF-8. in shared/nm-l2tp-crypto-openssl.c, add the following lines of code immediately before the 3 lines that contain PKCS12_parse :

fprintf(stderr, "*** UTF-8 password = \"%s\"\n", password);
password = g_locale_from_utf8 (password, -1, NULL, NULL, NULL);
fprintf(stderr, "*** locale password = \"%s\"\n", password);

After you have done a make and sudo make install, run the following and try to connect to the VPN server. You should then see the password before and after it is converted from UTF-8 to the locale version .

sudo killall -TERM nm-l2tp-service
sudo /usr/lib/NetworkManager/nm-l2tp-service --debug

Hopefully you'll be able to tell if the correct password is then getting passed to PKCS12_parse() function.

madman9999 commented 4 years ago

There are three times the function "PKCS12_parse" and I pasted it once above the latest function and one time inside. Like this, both times it gave me the same Core Dump.

if (!PKCS12_parse (p12, password, &pkey, &cert, &ca)) { fprintf(stderr, " UTF-8 password = \"%s\"\n", password); password = g_locale_from_utf8 (password, -1, NULL, NULL, NULL); fprintf(stderr, " locale password = \"%s\"\n", password); g_set_error (error, NM_CRYPTO_ERROR, NM_CRYPTO_ERROR_DECRYPTIONFAILED, ("Error parsing PKCS#12 file '%s'."), p12_filename); PKCS12_free(p12); return FALSE; }

It gives me this error:

Feb 18 10:18:34 soeren-virtual-machine nm-l2tp-service[14008]: Check port 1701 Feb 18 10:18:34 soeren-virtual-machine NetworkManager[692]: *** UTF-8 password = "(null)" Feb 18 10:18:34 soeren-virtual-machine kernel: [ 2857.766762] nm-l2tp-service[14008]: segfault at 0 ip 00007faf59d36f98 sp 00007ffc2bb71340 error 4 in libglib-2.0.so.0.5600.4[7faf59cb9000+114000] Feb 18 10:18:34 soeren-virtual-machine kernel: [ 2857.766795] Code: 29 48 89 f5 e8 f9 e5 ff ff 4d 85 e4 74 04 49 89 04 24 48 01 eb 48 39 d8 0f 94 c0 5b 0f b6 c0 5d 41 5c c3 0f 1f 80 00 00 00 00 <0f> b6 07 84 c0 75 15 eb 27 0f 1f 80 00 00 00 00 0f b6 41 01 48 8d Feb 18 10:18:34 soeren-virtual-machine systemd[1]: Started Process Core Dump (PID 14013/UID 0).

locale:

soeren@soeren-virtual-machine:~/Downloads/NetworkManager-l2tp-1.8.0$ locale LANG=de_DE.UTF-8 LANGUAGE= LC_CTYPE="de_DE.UTF-8" LC_NUMERIC="de_DE.UTF-8" LC_TIME="de_DE.UTF-8" LC_COLLATE="de_DE.UTF-8" LC_MONETARY="de_DE.UTF-8" LC_MESSAGES="de_DE.UTF-8" LC_PAPER="de_DE.UTF-8" LC_NAME="de_DE.UTF-8" LC_ADDRESS="de_DE.UTF-8" LC_TELEPHONE="de_DE.UTF-8" LC_MEASUREMENT="de_DE.UTF-8" LC_IDENTIFICATION="de_DE.UTF-8" LC_ALL=

What did I wrong?

dkosovic commented 4 years ago

g_locale_from_utf8() doesn't like NULL passwords and was causing a core dump. The code was also added after PKCS12_parse and not before.

I've github forked NetworkManager-l2tp, please use the following shared/nm-l2tp-crypto-openssl.c file (either copy the raw file or do a git clone of the new repository) :

You can see the changes here:

The new code has more debugging and will also prevent the NULL password being supplied to g_locale_from_utf8().

madman9999 commented 4 years ago

Thanks! Now it does not crash, but it looks like this:

Feb 18 13:48:55 soeren-virtual-machine nm-l2tp-service[15884]: Check port 1701 Feb 18 13:48:55 soeren-virtual-machine NetworkManager[737]: crypto_pkcs12_to_pem_files() Feb 18 13:48:55 soeren-virtual-machine NetworkManager[737]: UTF-8 password = "(null)" Feb 18 13:48:55 soeren-virtual-machine NetworkManager[737]: [1582030135.6154] vpn-connection[0x55aab06a4510,9398fbf6-398e-42b5-a3c0-fe193413962f,"L2TP_Test",0]: VPN connection: failed to connect: 'Error parsing PKCS#12 file '/home/soeren/certificate/macbook.p12'.'

madman9999 commented 4 years ago

It looks that somehow the password can't be read from the GUI.

dkosovic commented 4 years ago

Yeah, looks like the password is NULL because it wasn't able to get the password from the GNOME Secret Service.

Just so I can try to reproduce the issue, are you storing the password or having it prompt for the password each time? I'll install Linux Mint 19.3 on a VM.

madman9999 commented 4 years ago

It doesn't make any difference, stored or prompted, always the same error message. Thanks for checking this :)

dkosovic commented 4 years ago

I believe this issue has been fixed with commit# https://github.com/nm-l2tp/NetworkManager-l2tp/commit/26fe2bdf942de1f01818918700a0aff168753601

I've been testing with the same certificates for both user and machine authentication, so didn't notice the wrong password was being used for user certificates.

Also most users use machine certificates, not user certificates, so hasn't been used and tested much.

Thanks for your help.

madman9999 commented 4 years ago

Great, I just tested it and it works :)

Thank you very much.