Skip to content

driver/http: make TLS verification configurable, add trust store - #452

Open
sch-m wants to merge 1 commit into
estkme-group:mainfrom
TDT-AG:pr/20260722-http-curl-ssl-verify
Open

sch-m wants to merge 1 commit into
estkme-group:mainfrom
TDT-AG:pr/20260722-http-curl-ssl-verify

Conversation

@sch-m

@sch-m sch-m commented Jul 22, 2026 •

Copy link
Copy Markdown
Contributor

By default lpac's HTTP backends do not verify the SM-DP+/SM-DS
server's TLS certificate or hostname, since some servers use
certificates issued by CAs that are not (yet) part of the GSMA CI
trust store shipped with common OS trust stores. This makes it
impossible to opt back into full verification even when the target
server's certificate is trusted.

Add environment variables to opt back into standard TLS verification
and to verify against a custom trust store, e.g. the GSMA CI
certificates:

LPAC_HTTP_SSL_VERIFY=1
LPAC_HTTP_TRUST_STORE=/path/to/bundle.pem

LPAC_HTTP_SSL_VERIFY accepts the usual boolean values (1, true, yes,
on, ...). LPAC_HTTP_TRUST_STORE is a PEM file with the CA certificates
to trust. If it is set, only these certificates are trusted (the
system trust store is not used), and verification is enabled unless
LPAC_HTTP_SSL_VERIFY is explicitly set to a falsy value. A trust store
that cannot be read makes the backend initialization fail.

When both are unset, behavior is unchanged for both backends
(verification disabled), preserving backward compatibility.

curl backend (driver/http/curl.c):

  • When enabled, both CURLOPT_SSL_VERIFYPEER and CURLOPT_SSL_VERIFYHOST
    are set to enable verification (CURLOPT_SSL_VERIFYHOST is set to 2,
    matching curl's requirement that this option only accepts 0 or 2).
  • With a trust store, CURLOPT_CAINFO is set to it and CURLOPT_CAPATH
    is cleared, since libcurl would otherwise still consult its default
    CA directory as well (e.g. /etc/ssl/certs on Debian/Ubuntu).
  • libcurl's error buffer is printed when a request fails, so that
    verification errors can be told apart.
  • The settings are read once in libhttpinterface_init() and applied to
    every request made via http_interface_transmit().

WinHTTP backend (driver/http/winhttp.c):

  • When enabled, WINHTTP_OPTION_SECURITY_FLAGS is set to 0 instead of
    SECURITY_FLAG_IGNORE_UNKNOWN_CA, so the request goes through
    WinHTTP's standard certificate verification.
  • With a trust store, its certificates are loaded into a memory store,
    which is used as exclusive root store of a certificate chain engine.
    WinHTTP keeps ignoring unknown CAs then, but only sends the request
    headers first: the server certificate chain (including validity,
    usage and hostname) is verified with that engine before the request
    body is written. HTTP redirects are not followed in this mode, like
    the curl backend never follows them.
  • Same as the curl backend, the settings are read once in
    libhttpinterface_init() and applied via static variables in
    http_interface_transmit().

Both variables are documented in docs/ENVVARS.md.

@CoelacanthusHex

Copy link
Copy Markdown
Contributor

IMO, I will want to expand it to WinHTTP backend as well and named it as LPAC_HTTP_SSL_VERIFY.

@sch-m
sch-m force-pushed the pr/20260722-http-curl-ssl-verify branch from 70cbb42 to f1b52b2 Compare July 24, 2026 08:37
@sch-m sch-m changed the title driver/http/curl: make TLS certificate/hostname verification configurable driver/http: make TLS certificate/hostname verification configurable Jul 24, 2026
@sch-m

sch-m commented Jul 24, 2026

Copy link
Copy Markdown
Contributor Author

IMO, I will want to expand it to WinHTTP backend as well and named it as LPAC_HTTP_SSL_VERIFY.

OK, I've renamed the option and added WinHTTP backend changes (untested) as well.

Comment thread driver/http/curl.c
@sch-m
sch-m force-pushed the pr/20260722-http-curl-ssl-verify branch from f1b52b2 to 01ed0c5 Compare September 17, 2026 07:12

@septs septs left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accept an externally specified trust store file.

A typical user story:

$ wget https://euicc-manual.osmocom.org/docs/pki/ci/bundle.pem
$ export LPAC_HTTP_TRUST_STORE=./bundle.pem
$ lpac profile download ...

By default lpac's HTTP backends do not verify the SM-DP+/SM-DS
server's TLS certificate or hostname, since some servers use
certificates issued by CAs that are not (yet) part of the GSMA CI
trust store shipped with common OS trust stores. This makes it
impossible to opt back into full verification even when the target
server's certificate is trusted.

Add environment variables to opt back into standard TLS verification
and to verify against a custom trust store, e.g. the GSMA CI
certificates:

  LPAC_HTTP_SSL_VERIFY=1
  LPAC_HTTP_TRUST_STORE=/path/to/bundle.pem

LPAC_HTTP_SSL_VERIFY accepts the usual boolean values (1, true, yes,
on, ...). LPAC_HTTP_TRUST_STORE is a PEM file with the CA certificates
to trust. If it is set, only these certificates are trusted (the
system trust store is not used), and verification is enabled unless
LPAC_HTTP_SSL_VERIFY is explicitly set to a falsy value. A trust store
that cannot be read makes the backend initialization fail.

When both are unset, behavior is unchanged for both backends
(verification disabled), preserving backward compatibility.

curl backend (driver/http/curl.c):
- When enabled, both CURLOPT_SSL_VERIFYPEER and CURLOPT_SSL_VERIFYHOST
  are set to enable verification (CURLOPT_SSL_VERIFYHOST is set to 2,
  matching curl's requirement that this option only accepts 0 or 2).
- With a trust store, CURLOPT_CAINFO is set to it and CURLOPT_CAPATH
  is cleared, since libcurl would otherwise still consult its default
  CA directory as well (e.g. /etc/ssl/certs on Debian/Ubuntu).
- libcurl's error buffer is printed when a request fails, so that
  verification errors can be told apart.
- The settings are read once in libhttpinterface_init() and applied to
  every request made via http_interface_transmit().

WinHTTP backend (driver/http/winhttp.c):
- When enabled, WINHTTP_OPTION_SECURITY_FLAGS is set to 0 instead of
  SECURITY_FLAG_IGNORE_UNKNOWN_CA, so the request goes through
  WinHTTP's standard certificate verification.
- With a trust store, its certificates are loaded into a memory store,
  which is used as exclusive root store of a certificate chain engine.
  WinHTTP keeps ignoring unknown CAs then, but only sends the request
  headers first: the server certificate chain (including validity,
  usage and hostname) is verified with that engine before the request
  body is written. HTTP redirects are not followed in this mode, like
  the curl backend never follows them.
- Same as the curl backend, the settings are read once in
  libhttpinterface_init() and applied via static variables in
  http_interface_transmit().

Both variables are documented in docs/ENVVARS.md.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Martin Schiller <ms@dev.tdt.de>
@sch-m
sch-m force-pushed the pr/20260722-http-curl-ssl-verify branch from 01ed0c5 to 998d0af Compare October 23, 2026 06:06
@sch-m sch-m changed the title driver/http: make TLS certificate/hostname verification configurable driver/http: make TLS verification configurable, add trust store Oct 23, 2026
@sch-m

sch-m commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor Author

Accept an externally specified trust store file.

A typical user story:

$ wget https://euicc-manual.osmocom.org/docs/pki/ci/bundle.pem
$ export LPAC_HTTP_TRUST_STORE=./bundle.pem
$ lpac profile download ...

OK, I've added the optional trust store feature.

WinHTTP is still untested.

@septs septs left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@CoelacanthusHex please review

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.

3 participants