Skip to content

Add pkcs#11 support with tls-auth option

Anton K requested to merge tracefinder/NetworkManager-openvpn:main into main

This merge request is based on heyLu/NetworkManager-openvpn!2. It allows using PKCS#11 tokens and adds two new connection types.

The issues with original MR were:

  • TLS Authentication tab is missing in Advanced Setting
  • Authentication Type names don't match settings behind it

I haven't found any style guides or linters. Thus, provide MR as is.

Motivation

Secure storage of credentials can be archived in different ways with different security levels. One way is to store certificates and private keys for VPN on a hardware token.
Usually, tokens support a PKCS#11 interface. This MR adds ability to use it, additionally specifying a module with particular a PKCS#11 implementation.

MR changes

The MR adds two new connection types:

  • Certificates (TLS), PKCS#11
  • Password with Certificates (TLS), PKCS#11

These connection types support new fields:

  • PKCS#11 providers (rename to PKCS#11 provider?)
  • PKCS#11 id
  • PKCS#11 pin

If the field PKCS#11 providers is empty, p11-kit can be used.

How to test

The following is required:

  1. OpenVPN server
  2. PKCS#11 token
  3. Compiled and installed NetworkManager-openvpn plugin

To deploy an OpenVPN server you can use this article. As a token emulator use SoftHSM2.

Assuming you have client's certificate (cert.pem) and key (key.pem) add them to the token this way:

LABEL=nm-openvpn-plugin-test
softhsm2-util --init-token --slot 0 --label ${LABEL}
TOKEN_URL=$(p11tool --list-tokens | grep ${LABEL} | grep URL | awk '{print $2}')
p11tool --login --write ${TOKEN_URL} --load-certificate cert.pem --label ovpn-test
p11tool --login --write ${TOKEN_URL} --load-privkey key.pem --label ovpn-test

To get PKCS#11 providers and id run the following commands:

PKCS11_MODULE=$(p11tool --list-tokens | grep libsofthsm2.so | awk '{print $2}')
echo "Provider: ${PKCS11_MODULE}"
echo -E "ID: $(openvpn --show-pkcs11-ids ${PKCS11_MODULE} | grep "Serialized id:" | awk '{print $3}')"

You must know PIN yourself.
Then create a new connection of type Certificates (TLS), PKCS#11 and specify parameters. You're all set.

Security considerations

As mentioned in the comments to the MR, a user can elevate their privileges specifying arbitrary so-file. It works because an so-file is run with root privileges when the connection is activated. To protect from this issue NM_OPENVPN_PKCS11_PROVIDERS_PREFIX was introduced effectively limiting available so-files. Thus, only root user can add new modules under NM_OPENVPN_PKCS11_PROVIDERS_PREFIX. It was considered a good enough solution until CVE-2023-38408. Now I see several possible solutions:

  1. limit NM_OPENVPN_PKCS11_PROVIDERS_PREFIX even more (a bad one)
  2. create symlinks to allowed modules/providers somewhere under /etc/NetworkManager/ and use them
  3. completely rely on p11-kit

The third solution seems to be the most robust. NetworkManager itself behaves in a similar way.

Edited by Anton K

Merge request reports