]> git.ipfire.org Git - thirdparty/squid.git/blob - src/security/Certificate.cc
Maintenance: update --with-gnutls detection (#1685)
[thirdparty/squid.git] / src / security / Certificate.cc
1 /*
2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 #include "squid.h"
10 #include "debug/Stream.h"
11 #include "sbuf/SBuf.h"
12 #include "security/Certificate.h"
13
14 #if USE_OPENSSL
15 #include "ssl/gadgets.h"
16 #endif
17
18 #include <iostream>
19
20 inline
21 const char *
22 MissingLibraryError()
23 {
24 return "[need OpenSSL or GnuTLS]";
25 }
26
27 SBuf
28 Security::IssuerName(Certificate &cert)
29 {
30 SBuf out;
31
32 #if USE_OPENSSL
33 Ssl::ForgetErrors();
34 const auto name = Ssl::OneLineSummary(*X509_get_issuer_name(&cert));
35 if (!name) {
36 debugs(83, DBG_PARSE_NOTE(2), "WARNING: cannot get certificate Issuer:" <<
37 Ssl::ReportAndForgetErrors);
38 return out;
39 }
40 out.append(name.get());
41
42 #elif HAVE_LIBGNUTLS
43 gnutls_x509_dn_t issuer;
44 auto x = gnutls_x509_crt_get_issuer(&cert, &issuer);
45 if (x != GNUTLS_E_SUCCESS) {
46 debugs(83, DBG_PARSE_NOTE(2), "WARNING: cannot get certificate Issuer: " << ErrorString(x));
47 return out;
48 }
49
50 gnutls_datum_t name;
51 x = gnutls_x509_dn_get_str(issuer, &name);
52 if (x != GNUTLS_E_SUCCESS) {
53 debugs(83, DBG_PARSE_NOTE(2), "WARNING: cannot describe certificate Issuer: " << ErrorString(x));
54 return out;
55 }
56 out.append(reinterpret_cast<const char *>(name.data), name.size);
57 gnutls_free(name.data);
58
59 #else
60 debugs(83, DBG_PARSE_NOTE(2), "WARNING: cannot get certificate Issuer: " << MissingLibraryError());
61 (void)cert;
62 #endif
63
64 return out;
65 }
66
67 SBuf
68 Security::SubjectName(Certificate &cert)
69 {
70 SBuf out;
71
72 #if USE_OPENSSL
73 Ssl::ForgetErrors();
74 const auto name = Ssl::OneLineSummary(*X509_get_subject_name(&cert));
75 if (!name) {
76 debugs(83, DBG_PARSE_NOTE(2), "WARNING: cannot get certificate SubjectName:" <<
77 Ssl::ReportAndForgetErrors);
78 return out;
79 }
80 out.append(name.get());
81
82 #elif HAVE_LIBGNUTLS
83 gnutls_x509_dn_t subject;
84 auto x = gnutls_x509_crt_get_subject(&cert, &subject);
85 if (x != GNUTLS_E_SUCCESS) {
86 debugs(83, DBG_PARSE_NOTE(2), "WARNING: cannot get certificate SubjectName: " << ErrorString(x));
87 return out;
88 }
89
90 gnutls_datum_t name;
91 x = gnutls_x509_dn_get_str(subject, &name);
92 if (x != GNUTLS_E_SUCCESS) {
93 debugs(83, DBG_PARSE_NOTE(2), "WARNING: cannot describe certificate SubjectName: " << ErrorString(x));
94 return out;
95 }
96 out.append(reinterpret_cast<const char *>(name.data), name.size);
97 gnutls_free(name.data);
98
99 #else
100 debugs(83, DBG_PARSE_NOTE(2), "WARNING: cannot get certificate SubjectName: " << MissingLibraryError());
101 (void)cert;
102 #endif
103
104 return out;
105 }
106
107 bool
108 Security::IssuedBy(Certificate &cert, Certificate &issuer)
109 {
110 #if USE_OPENSSL
111 Ssl::ForgetErrors();
112 const auto result = X509_check_issued(&issuer, &cert);
113 if (result == X509_V_OK)
114 return true;
115 debugs(83, DBG_PARSE_NOTE(3), issuer << " did not sign " << cert << ":" <<
116 Debug::Extra << "X509_check_issued() result: " << X509_verify_cert_error_string(result) << " (" << result << ")" <<
117 Ssl::ReportAndForgetErrors);
118 #elif HAVE_LIBGNUTLS
119 const auto result = gnutls_x509_crt_check_issuer(&cert, &issuer);
120 if (result == 1)
121 return true;
122 debugs(83, DBG_PARSE_NOTE(3), issuer << " did not sign " << cert);
123 #else
124 debugs(83, DBG_PARSE_NOTE(2), "WARNING: cannot determine certificates relationship: " << MissingLibraryError());
125 (void)cert;
126 (void)issuer;
127 #endif
128 return false;
129 }
130
131 std::ostream &
132 operator <<(std::ostream &os, Security::Certificate &cert)
133 {
134 const auto name = Security::SubjectName(cert);
135 if (name.isEmpty())
136 os << "[no subject name]";
137 else
138 os << name;
139 return os;
140 }
141