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

TLS #53

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft

TLS #53

wants to merge 5 commits into from

Conversation

mdavidsaver
Copy link
Member

@mdavidsaver mdavidsaver commented Aug 17, 2023

Applying OpenSSL to PVXS.

Wire compatibility with existing (plain tcp) clients/servers is maintained. Likewise this PR is compatible with work by @kasemir adding TLS support to core.pva in the phoebus repository.

To maintain compatibility. When configured with a keychain file, client search requests include two "protocol" names: tcp and tls. Server listens on a second TCP port for TLS connections, prefers to respond with tls when both present.

Adds x509 AUTHZ method. Client advertises x509 when configured with a client certificate. Server prefers x509 to ca. If selected, uses client cert commonName as account name. eg. CN=foo appears to ACF logic as foo. (note, this really needs an extension to the ACF logic to account for different source of accounts)

TLS features/restrictions

  • OpenSSL >= 3.0
  • TLS protocol version >= 1.3 required
  • ALPN extension negotiates with protocol pva/1. (mandatory?)
  • Client/server reload TLS configuration (eg. replace cert) at runtime. Forces closes connections.

New Configuration:

  • $EPICS_PVAS_TLS_KEYCHAIN $EPICS_PVA_TLS_KEYCHAIN name of a PKCS12 file containing some combination of key, server/client certificate, and/or CA certificates. The file path may optionally be followed by ; and a password. eg. EPICS_PVAS_TLS_KEYCHAIN=/path/to/some.p12;secret.
  • $EPICS_PVAS_TLS_OPTIONS $EPICS_PVA_TLS_OPTIONS space separated list of key=value pairs. Currently supported are client_cert=optional and client_cert=required.
  • $EPICS_PVAS_TLS_PORT $EPICS_PVA_TLS_PORT default port to listen for TLS connections
  • $OPENSSL_CONF Location of OpenSSL config file. Defaults to /usr/lib/ssl/openssl.cnf on Linux. Application name pvxs is used.
  • $SSLKEYLOGFILE If set, TLS session keys will be written here. eg. for use by wireshark. cf. Decode PVA in TLS via ALPN mdavidsaver/cashark#14 (may be disabled at build time with make PVXS_ENABLE_SSLKEYLOGFILE=NO ...)

Building:

libevent must be built with optional openssl support (bundled build will detect). openssl is expected to be installed in the default search path. I have no plans to bundled openssl.

TODO:

  • Configure TLS in $EPICS_PVA_NAME_SERVERS w/ URI-ish pvas://1.2.3.4:5678.
  • Verify interoperability with PKCS12 created by java keytool (OpenSSL parser for PKCS12 is... limited)
    • Can work with files created by openssl pkcs12 or keytool. (although Java can't current work with openssl created files)
    • Handle password protected PKCS12 (which java keytool insists on...)
  • Configure client cert. required at TLS level?
  • Fix OSX RPATH issue
  • Fix MSVC build failure w/ appveyor
  • IOC shell commands to manage TLS (re)configuration
  • Test server reconfigure
    • Expose server credentials to client
  • x509 AUTHZ method design
    • Add authority alongside method and account
  • Update python module build
  • Config for openssl outside of implicit search path (OSX brew).
  • What to do about CMD_BEACON ?
  • OSCP over PVA?
  • What to do about certificate expiration? (drop credentials? force reconnect w/o TLS?)
  • Include CA IDs in search request/reply? (more graceful fallback if mis-matched CA certs)
  • Investigate openssl provider/engine support. eg tpm2-openssl

Supersedes https://github.com/mdavidsaver/pvxs-dev/pull/2

@mdavidsaver mdavidsaver mentioned this pull request Aug 17, 2023
16 tasks
@mdavidsaver
Copy link
Member Author

I think this work has progressed far enough to be (somewhat) more widely testable. The unittest process creates a consistent set of TLS certificates which may be useful for some manual testing. Though I would not recommend them for anything beyond some basic exploration. Some knowledge of x509 certificates will be needed to go beyond the recipe shown below.

An example of running the ticker example server, and subscribing with pvxmonitor.

EPICS_PVA_TLS_KEYCHAIN=test/O.linux-x86_64/server1.p12 \
  ./example/O.linux-x86_64/ticker cnt
EPICS_PVA_TLS_KEYCHAIN=test/O.linux-x86_64/ca.p12 \
  ./bin/linux-x86_64-debug/pvxmonitor cnt

Verification is easier with an IOC.

cat <<EOF > tick.db
record(calc, "\$(P=)cnt") {
  field(INPA, "\$(P=)cnt")
  field(CALC, "A+1")
  field(SCAN, "1 second")
}
EOF
EPICS_PVA_TLS_KEYCHAIN=test/O.linux-x86_64/server1.p12
  ./bin/linux-x86_64/softIocPVX -d tick.db
INFO: PVXS QSRV2 is loaded and ENABLED.
Starting iocInit
...
epics> dbl
cnt
epics> pvxsr 3
...
TLS Cert. subject:CN=server1 issuer:CN=intermediateCA from: Aug 17 17:00:23 2023 GMT until: Aug 14 17:00:24 2033 GMT
    Peer[fe80::7816:e3ff:fe25:5208]%5:59152 backlog=0 TX=994 RX=120 auth=ca TLS
        Cred: ca/mdavidsaver@[fe80::7816:e3ff:fe25:5208]%5:59152
        cnt TX=927 RX=46         Executing ioid=268443648 MONITOR
epics>

On the client side, switching from ca.p12 to client1.p12 will use client certificate authentication. Then Cred: ca/mdavidsaver... becomes Cred: x509rootCA/client1....

...
TLS Cert. subject:CN=server1 issuer:CN=intermediateCA from: Aug 17 17:00:23 2023 GMT until: Aug 14 17:00:24 2033 GMT
    Peer[fe80::7816:e3ff:fe25:5208]%5:40564 backlog=0 TX=1035 RX=86 auth=x509 TLS
        Cred: x509rootCA/client1@[fe80::7816:e3ff:fe25:5208]%5:40564
        Cert: subject:CN=client1 issuer:CN=intermediateCA from: Aug 17 17:00:24 2023 GMT until: Aug 14 17:00:25 2033 GMT
        cnt TX=968 RX=46         Executing ioid=268443648 MONITOR

@mdavidsaver
Copy link
Member Author

Update. @kasemir When built against what will become openssl 3.2.x, test/gen_test_certs.cpp will now produce .p12 files which work with java. (see #ifdef NID_oracle_jdk_trustedkeyusage) Note that this does not yet apply to files produced by openssl pkcs12 ....

@AppVeyorBot
Copy link

Build pvxs 1.0.925 failed (commit 2dd4c3047b by @mdavidsaver)

@AppVeyorBot
Copy link

Build pvxs 1.0.932 completed (commit 17690ff5cf by @mdavidsaver)

@mdavidsaver
Copy link
Member Author

Updated to add $EPICS_PVAS_TLS_OPTIONS $EPICS_PVA_TLS_OPTIONS as space separated list of key=value pairs. Currently supported are client_cert=optional (default) and client_cert=required. Where required causes a server to set SSL_VERIFY_FAIL_IF_NO_PEER_CERT so that the TLS handshake will fail unless a valid client cert is presented.

@mdavidsaver
Copy link
Member Author

I have also added another make variable OPENSSL which should function like LIBEVENT to set an external/non-epics installation prefix path when these packages are outside of the default search paths.

Also like LIBEVENT, OPENSSL should only be set during PVXS builds. The result is captured and written to cfg/TOOLCHAIN_PVXS.$(T_A) for use by dependent modules.

So if all goes well, the added dependency on libssl should not require changes to downstream Makefiles...

@AppVeyorBot
Copy link

Build pvxs 1.0.940 completed (commit 2ddbc86084 by @mdavidsaver)

@AppVeyorBot
Copy link

Build pvxs 1.0.1004 failed (commit d451688aef by @mdavidsaver)

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

Successfully merging this pull request may close these issues.

2 participants