-
Notifications
You must be signed in to change notification settings - Fork 648
TLS library-agnostic X509 certificate interrogation functions #1057
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
Closed
rousskov
wants to merge
25
commits into
squid-cache:master
from
measurement-factory:SQUID-642-cert-manipulators
Closed
Changes from 23 commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
255b45c
Provide X509 certificate manipulation functions
yadij 6a0d479
fixup: Assert no nil LockingPointer dereference (a branch TODO)
rousskov 707b56b
fixup: Renamed src/security/CertGadgets.* to .../Certificate.*
rousskov 5e5f9a3
fixup: Moved certificate printing operator declaration to Certificate.h
rousskov 527c752
fixup: Removed unnecessary Cert prefix from Certificate info getters
rousskov 585dc84
fixup: Fixed OpenSSL error stack handling in new functions
rousskov 37f5c4d
fixup: Do not report successfully extracted certificate fields
rousskov e64ea89
fixup: Formatted modified sources
rousskov 10c24f1
fixup: Avoid Foo:: inside Foo
rousskov 9a3f84d
fixup: Polished branch-added source code comments
rousskov 7b19ec7
Use newly added Security::IsIssuedBy() and Security::IsSelfSigned()
rousskov 651bdfd
Use newly added X509_NAME_oneline() replacements, where feasible
rousskov fdfcba3
fiuxp: Simplified conditional #includes
rousskov f77814e
fixup: Highlight that we print OpenSSL-saved errors on their own lines
rousskov d9061dc
fixup: const-correctness
rousskov 4dc60c3
fixup: Polished variable names
rousskov 2a3cac8
fixup: Undo unnatural squid_LDADD reordering
rousskov 0dbbf52
fixup: Found better names for two new functions
rousskov 9b02b6b
fixup: Polished new function descriptions
rousskov b511fb5
fixup: Removed known memory leaks in branch-added OpenSSL code
rousskov eadc2ba
fixup: Avoid duplicating UniqueCString-related code
rousskov 4c16b6c
fixup: Rewrapped to avoid arguing; also fixed the now-modified debugs()
rousskov 9846104
fixup: Removed a likely misleading TODO
rousskov 6b13931
fixup: Fix build [-Wunused-parameter]
rousskov cd79f49
Merge branch 'master' into SQUID-642-cert-manipulators
rousskov File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,137 @@ | ||
| /* | ||
| * Copyright (C) 1996-2022 The Squid Software Foundation and contributors | ||
| * | ||
| * Squid software is distributed under GPLv2+ license and includes | ||
| * contributions from numerous individuals and organizations. | ||
| * Please see the COPYING and CONTRIBUTORS files for details. | ||
| */ | ||
|
|
||
| #include "squid.h" | ||
| #include "debug/Stream.h" | ||
| #include "sbuf/SBuf.h" | ||
| #include "security/Certificate.h" | ||
|
|
||
| #if USE_OPENSSL | ||
| #include "ssl/gadgets.h" | ||
| #endif | ||
|
|
||
| #include <iostream> | ||
|
|
||
| inline | ||
| const char * | ||
| MissingLibraryError() | ||
| { | ||
| return "[need OpenSSL or GnuTLS]"; | ||
| } | ||
|
|
||
| SBuf | ||
| Security::IssuerName(Certificate &cert) | ||
| { | ||
| SBuf out; | ||
|
|
||
| #if USE_OPENSSL | ||
| Ssl::ForgetErrors(); | ||
| const auto name = Ssl::OneLineSummary(*X509_get_issuer_name(&cert)); | ||
| if (!name) { | ||
| debugs(83, DBG_PARSE_NOTE(2), "WARNING: cannot get certificate Issuer:" << | ||
| Ssl::ReportAndForgetErrors); | ||
| return out; | ||
| } | ||
| out.append(name.get()); | ||
|
|
||
| #elif USE_GNUTLS | ||
| gnutls_x509_dn_t issuer; | ||
| auto x = gnutls_x509_crt_get_issuer(&cert, &issuer); | ||
| if (x != GNUTLS_E_SUCCESS) { | ||
| debugs(83, DBG_PARSE_NOTE(2), "WARNING: cannot get certificate Issuer: " << ErrorString(x)); | ||
| return out; | ||
| } | ||
|
|
||
| gnutls_datum_t name; | ||
| x = gnutls_x509_dn_get_str(issuer, &name); | ||
| if (x != GNUTLS_E_SUCCESS) { | ||
| debugs(83, DBG_PARSE_NOTE(2), "WARNING: cannot describe certificate Issuer: " << ErrorString(x)); | ||
| return out; | ||
| } | ||
| out.append(reinterpret_cast<const char *>(name.data), name.size); | ||
| gnutls_free(name.data); | ||
|
|
||
| #else | ||
| debugs(83, DBG_PARSE_NOTE(2), "WARNING: cannot get certificate Issuer: " << MissingLibraryError()); | ||
| #endif | ||
|
|
||
| return out; | ||
| } | ||
|
|
||
| SBuf | ||
| Security::SubjectName(Certificate &cert) | ||
| { | ||
| SBuf out; | ||
|
|
||
| #if USE_OPENSSL | ||
| Ssl::ForgetErrors(); | ||
| const auto name = Ssl::OneLineSummary(*X509_get_subject_name(&cert)); | ||
| if (!name) { | ||
| debugs(83, DBG_PARSE_NOTE(2), "WARNING: cannot get certificate SubjectName:" << | ||
| Ssl::ReportAndForgetErrors); | ||
| return out; | ||
| } | ||
| out.append(name.get()); | ||
|
|
||
| #elif USE_GNUTLS | ||
| gnutls_x509_dn_t subject; | ||
| auto x = gnutls_x509_crt_get_subject(&cert, &subject); | ||
| if (x != GNUTLS_E_SUCCESS) { | ||
| debugs(83, DBG_PARSE_NOTE(2), "WARNING: cannot get certificate SubjectName: " << ErrorString(x)); | ||
| return out; | ||
| } | ||
|
|
||
| gnutls_datum_t name; | ||
| x = gnutls_x509_dn_get_str(subject, &name); | ||
| if (x != GNUTLS_E_SUCCESS) { | ||
| debugs(83, DBG_PARSE_NOTE(2), "WARNING: cannot describe certificate SubjectName: " << ErrorString(x)); | ||
| return out; | ||
| } | ||
| out.append(reinterpret_cast<const char *>(name.data), name.size); | ||
| gnutls_free(name.data); | ||
|
|
||
| #else | ||
| debugs(83, DBG_PARSE_NOTE(2), "WARNING: cannot get certificate SubjectName: " << MissingLibraryError()); | ||
| #endif | ||
|
|
||
| return out; | ||
| } | ||
|
|
||
| bool | ||
| Security::IssuedBy(Certificate &cert, Certificate &issuer) | ||
| { | ||
| #if USE_OPENSSL | ||
| Ssl::ForgetErrors(); | ||
| const auto result = X509_check_issued(&issuer, &cert); | ||
| if (result == X509_V_OK) | ||
| return true; | ||
| debugs(83, DBG_PARSE_NOTE(3), issuer << " did not sign " << cert << ":" << | ||
| Debug::Extra << "X509_check_issued() result: " << X509_verify_cert_error_string(result) << " (" << result << ")" << | ||
| Ssl::ReportAndForgetErrors); | ||
| #elif USE_GNUTLS | ||
| const auto result = gnutls_x509_crt_check_issuer(&cert, &issuer); | ||
| if (result == 1) | ||
| return true; | ||
| debugs(83, DBG_PARSE_NOTE(3), issuer << " did not sign " << cert); | ||
| #else | ||
| debugs(83, DBG_PARSE_NOTE(2), "WARNING: cannot determine certificates relationship: " << MissingLibraryError()); | ||
| #endif | ||
| return false; | ||
| } | ||
|
|
||
| std::ostream & | ||
| operator <<(std::ostream &os, Security::Certificate &cert) | ||
| { | ||
| const auto name = Security::SubjectName(cert); | ||
| if (name.isEmpty()) | ||
| os << "[no subject name]"; | ||
| else | ||
| os << name; | ||
| return os; | ||
| } | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| /* | ||
| * Copyright (C) 1996-2022 The Squid Software Foundation and contributors | ||
| * | ||
| * Squid software is distributed under GPLv2+ license and includes | ||
| * contributions from numerous individuals and organizations. | ||
| * Please see the COPYING and CONTRIBUTORS files for details. | ||
| */ | ||
|
|
||
| #ifndef SQUID_SRC_SECURITY_CERTIFICATE_H | ||
| #define SQUID_SRC_SECURITY_CERTIFICATE_H | ||
|
|
||
| #include "security/forward.h" | ||
|
|
||
| // The accessing/testing functions below require a non-constant Certificate when | ||
| // it is modified by an underlying library implementation (e.g., GnuTLS). | ||
|
|
||
| namespace Security | ||
| { | ||
|
|
||
| /// The SubjectName field of the given certificate (if found) or an empty SBuf. | ||
| SBuf SubjectName(Certificate &); | ||
|
|
||
| /// The Issuer field of the given certificate (if found) or an empty SBuf. | ||
| SBuf IssuerName(Certificate &); | ||
|
|
||
| /// Whether cert was (correctly) issued by the given issuer. | ||
| /// Due to complexity of the underlying checks, it is impossible to clearly | ||
| /// distinguish pure negative answers (e.g., two independent certificates) | ||
| /// from errors (e.g., the issuer certificate lacks the right CA extension). | ||
| bool IssuedBy(Certificate &cert, Certificate &issuer); | ||
|
|
||
| /// Whether the given certificate is self-signed. | ||
| inline bool SelfSigned(Certificate &c) { return IssuedBy(c, c); } | ||
|
|
||
| } // namespace Security | ||
|
|
||
| // Declared outside Security because all underlying Security::Certificate types | ||
| // are declared inside global namespace. | ||
| /// reports a one-line gist of the Certificate Subject Name (for debugging) | ||
| std::ostream &operator <<(std::ostream &, Security::Certificate &); | ||
|
|
||
| #endif /* SQUID_SRC_SECURITY_CERTIFICATE_H */ | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.