-
Notifications
You must be signed in to change notification settings - Fork 94
Implement querying the system certificate store on each platform #4892
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
base: develop
Are you sure you want to change the base?
Conversation
- Move the enumerations of the certificates into the LLBasicCertificateVector and implement a derived class LLSystemCertificateVector - For each platform try to query the system certificate store and fall back to the application provided certification bundle if that fails - Be more restrictive in issuing warning messages about rejected certificates since the system certificate store on Windows and Mac at least generally also contains a few expired certificates
| { | ||
| bool success = false; | ||
| #if LL_WINDOWS | ||
| HCERTSTORE cert_store = CertOpenSystemStoreA(0, storename.empty() ? "ROOT" : storename.c_str()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason to call the ANSI version explicitly instead of using CertOpenSystemStore?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually yes. It avoids having to make a std::string to std:wstring conversion. Basically std::string is always an 8-bit string while the undecorated Win32 API may use wchar or char, depending on some "obscure" UNICODE preprocessor define. So if someone changes that define you end up with compiler errors. The undecorated Win32 API should only be used if you also pass TCHAR/LPTCHAR variables to them. Otherwise you create a potential type conversion error.
Since this string is anyhow only for special cases (needs more work to make this a somewhat useful parameter across all three platforms) and the various security stores on each platform have varying ideas about how they organize it (on my Mac only the kSecTrustSettingsDomainSystem really returns any significant number of certificates, it turned out to be a somewhat academic parameter. However I left it in as an option for now.
The idea was that by passing in different keywords, one could select a specific sort of keystore to query. On Windows this would by for instance ROOT, MY and CA, on Mac one of the three enums, on Linux ... oh well it's a mess! :-)
If we really want to use that eventually, an enum similar to what the Mac uses may be more prudent but more likely it just can go away eventually.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest adding this as a comment in-code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MacOS isn't quite my expertise. But I see that in the test build it fails because of these:
Undefined symbols for architecture arm64:
"_SecCertificateCopyData", referenced from:
LLSystemCertificateVector::load_from_system(std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator> const&, bool) in llsechandler_basic.o
"_SecTrustSettingsCopyCertificates", referenced from:
LLSystemCertificateVector::load_from_system(std::__1::basic_string<char, std::__1::char_traits, std::__1::allocator> const&, bool) in llsechandler_basic.o
Does this mean that these SecCertificate.. APIs have been depreciated, not implemented, forgotten by Apple or what for the ARM platform?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
According to AI it might be because security framework isn't linked to the test in question.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missed the x86_64 failure. Those logs are unwieldly long. :-(
What about an option to disable the system store with an optional parameter to the LLSecAPIBasicHandler() constructor? If this parameter is set to true, it instantiates the LLBasicCertificateVector with the existing certificate file rather than the derived LLSystemCertificateVector.
Although that won't solve the linking issue. Have to think about this a bit more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'll need to add a find_library(SECURITY_LIBRARY Security) in Linking.cmake and add it to the list of linked libraries.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'll need to add a find_library(SECURITY_LIBRARY Security)
Thanks! I knew that it needed a framework or library, but I just don't see where viewer is adding it or how to do it.
What about an option to disable the system store with an optional parameter to the LLSecAPIBasicHandler() constructor?
It's a linking error, not a runtime one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'll need to add a find_library(SECURITY_LIBRARY Security)
Thanks! I knew that it needed a framework or library, but I just don't see where viewer is adding it or how to do it.
Already found it. It is in indra/cmake/Linking.cmake where it needs to be added. Also needs a similar addition for crypt32 in the Windows case. Wonder why it compiled and linked for me on both Mac and Windows without that.
What about an option to disable the system store with an optional parameter to the LLSecAPIBasicHandler() constructor?
It's a linking error, not a runtime one.
Yes I know. But my concern is more about the fact that a half working system store (not sure how the test systems are exactly setup and if they are a fully installed OS image) might actually make the tests fail for some reason as they are working with specific pre configured certificate resources.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But my concern is more about the fact that a half working system store
It only uses old LLBasicCertificateVector's constructor so that part should be fine. And if not the right way might be to update test<5> to account for extra certs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR implements querying the system certificate store on each platform (Windows, macOS, and Linux) to provide CA certificates for SSL/TLS validation, with a fallback to the bundled certificate file. The implementation moves certificate enumeration logic into LLBasicCertificateVector and adds a new LLSystemCertificateVector class that queries platform-specific certificate stores.
Key changes:
- Refactored certificate loading into reusable methods in
LLBasicCertificateVectorwith proper validation - Added
LLSystemCertificateVectorclass with platform-specific implementations for Windows (CryptoAPI), macOS (Security framework), and Linux (filesystem paths) - Added
suppress_expire_warningparameter throughout the certificate validation chain to reduce noise from expired certificates in system stores
Reviewed Changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| indra/newview/llsechandler_basic.h | Added LLSystemCertificateVector class and refactored LLBasicCertificateVector to support loading certificates from files/directories; cleaned up redundant declarations |
| indra/newview/llsechandler_basic.cpp | Implemented platform-specific system certificate store enumeration for Windows, macOS, and Linux; refactored certificate loading and validation logic; updated initialization to use system certificates |
| indra/newview/llsecapi.h | Added suppress_warning parameter to LLCertException and LLCertValidationExpirationException constructors |
| indra/newview/llsecapi.cpp | Modified LLCertException constructor to conditionally suppress warning messages based on the new parameter |
| indra/newview/tests/llsechandler_basic_test.cpp | Updated test mock to match new LLCertException constructor signature with suppress_warning parameter |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } | ||
|
|
||
| // verify the certificate to be valid and not expired and add it to the store. If the certificate | ||
| // already exists in the store (based on CERT_SUBJECT_KEY_IDENTFIER), it will be ignored |
Copilot
AI
Nov 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo in comment: "CERT_SUBJECT_KEY_IDENTFIER" should be "CERT_SUBJECT_KEY_IDENTIFIER" (missing 'I')
| CertCloseStore(cert_store, 0); | ||
| #elif LL_DARWIN | ||
| // FM: Quite some googling led eventually to some old MacOS Open Source repository that showed the | ||
| // implementation for SecTrustSettignsCopyCertificates() and that eventually led to this code |
Copilot
AI
Nov 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo in comment: "SecTrustSettignsCopyCertificates" should be "SecTrustSettingsCopyCertificates"
| // implementation for SecTrustSettignsCopyCertificates() and that eventually led to this code | |
| // implementation for SecTrustSettingsCopyCertificates() and that eventually led to this code |
| } | ||
| else | ||
| { | ||
| LL_WARNS("SECAPI") << "Failed to initialize the certificate store with valid CA certificates." |
Copilot
AI
Nov 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing space between sentences in the warning message. Should be: "It's probably not possible to connect to any internet service!" or add a space before "It's"
| LL_WARNS("SECAPI") << "Failed to initialize the certificate store with valid CA certificates." | |
| LL_WARNS("SECAPI") << "Failed to initialize the certificate store with valid CA certificates. " |
| "/etc/pki/tls/certs", // Fedora/RHEL | ||
| }; | ||
|
|
||
| const std::string certFile = getenv("SSL_CERT_FILE"); |
Copilot
AI
Nov 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return value of getenv("SSL_CERT_FILE") can be nullptr on some platforms, which would cause undefined behavior when constructing a std::string. Use a null check before constructing the string, e.g., const char* env_val = getenv("SSL_CERT_FILE"); const std::string certFile = env_val ? env_val : "";
| } | ||
| if (!success) | ||
| { | ||
| const std::string dirs = getenv("SSL_CERT_DIR"); |
Copilot
AI
Nov 17, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return value of getenv("SSL_CERT_DIR") can be nullptr on some platforms, which would cause undefined behavior when constructing a std::string. Use a null check before constructing the string, e.g., const char* env_val = getenv("SSL_CERT_DIR"); const std::string dirs = env_val ? env_val : "";
| const std::string dirs = getenv("SSL_CERT_DIR"); | |
| const char* env_val = getenv("SSL_CERT_DIR"); | |
| const std::string dirs = env_val ? env_val : ""; |
Description
This could eventually allow to not having to ship the application provided CA certificate bundle anymore and rely on the certificates from the Operating System, which are normally regularly updated.
Related Issues
Checklist
Please ensure the following before requesting review: