11#include " cert_auth_processor.h"
22
33#include < openssl/x509.h>
4+ #include < openssl/x509v3.h>
45#include < openssl/pem.h>
56#include < openssl/bio.h>
67#include < openssl/objects.h>
@@ -100,6 +101,56 @@ TVector<std::pair<TString, TString>> X509CertificateReader::ReadIssuerTerms(cons
100101 return ReadTerms (name);
101102}
102103
104+ static void FreeList (GENERAL_NAMES* list) {
105+ sk_GENERAL_NAME_pop_free (list, GENERAL_NAME_free);
106+ }
107+
108+ TVector<TString> X509CertificateReader::ReadSubjectDns (const X509Ptr& x509, const std::vector<std::pair<TString, TString>>& subjectTerms) {
109+ TVector<TString> result;
110+ // 1. Subject's common name (CN) must be a subject DNS name, so add it to DNS names of subject first
111+ for (const auto & [k, v] : subjectTerms) {
112+ if (k == " CN" ) {
113+ result.emplace_back (v);
114+ }
115+ }
116+
117+ using TGeneralNamesPtr = std::unique_ptr<GENERAL_NAMES, deleter_from_fn<&FreeList>>;
118+ TGeneralNamesPtr subjectAltNames ((GENERAL_NAMES*)X509_get_ext_d2i (x509.get (), NID_subject_alt_name, NULL , NULL ));
119+ if (!subjectAltNames) {
120+ return result;
121+ }
122+ const int subjectAltNamesCount = sk_GENERAL_NAME_num (subjectAltNames.get ());
123+ if (subjectAltNamesCount <= 0 ) {
124+ return result;
125+ }
126+
127+ result.reserve (static_cast <size_t >(subjectAltNamesCount) + result.size ());
128+ // 2. Additionally find subject alternative names with type=DNS
129+ for (int i = 0 ; i < subjectAltNamesCount; ++i) {
130+ const GENERAL_NAME* name = sk_GENERAL_NAME_value (subjectAltNames.get (), i);
131+ if (!name) {
132+ continue ;
133+ }
134+ if (name->type == GEN_DNS) {
135+ const ASN1_STRING* value = name->d .dNSName ;
136+ if (!value) {
137+ continue ;
138+ }
139+
140+ const char * data = reinterpret_cast <const char *>(ASN1_STRING_get0_data (value));
141+ if (!data) {
142+ continue ;
143+ }
144+ int size = ASN1_STRING_length (value);
145+ if (size <= 0 ) {
146+ continue ;
147+ }
148+ result.emplace_back (data, static_cast <size_t >(size));
149+ }
150+ }
151+ return result;
152+ }
153+
103154TString X509CertificateReader::GetFingerprint (const X509Ptr& x509) {
104155 static constexpr size_t FINGERPRINT_LENGTH = SHA_DIGEST_LENGTH;
105156 unsigned char fingerprint[FINGERPRINT_LENGTH];
@@ -109,14 +160,16 @@ TString X509CertificateReader::GetFingerprint(const X509Ptr& x509) {
109160 return HexEncode (fingerprint, FINGERPRINT_LENGTH);
110161}
111162
112- TCertificateAuthorizationParams::TCertificateAuthorizationParams (const TDN& dn, bool requireSameIssuer, const std::vector<TString>& groups)
163+ TCertificateAuthorizationParams::TCertificateAuthorizationParams (const TDN& dn, const std::optional<TRDN>& subjectDns, bool requireSameIssuer, const std::vector<TString>& groups)
113164 : SubjectDn(dn)
165+ , SubjectDns(subjectDns)
114166 , RequireSameIssuer(requireSameIssuer)
115167 , Groups(groups)
116168{}
117169
118- TCertificateAuthorizationParams::TCertificateAuthorizationParams (TDN&& dn, bool requireSameIssuer, std::vector<TString>&& groups)
170+ TCertificateAuthorizationParams::TCertificateAuthorizationParams (TDN&& dn, std::optional<TRDN>&& subjectDns, bool requireSameIssuer, std::vector<TString>&& groups)
119171 : SubjectDn(std::move(dn))
172+ , SubjectDns(std::move(subjectDns))
120173 , RequireSameIssuer(requireSameIssuer)
121174 , Groups(std::move(groups))
122175{}
@@ -127,59 +180,44 @@ TCertificateAuthorizationParams::TDN& TCertificateAuthorizationParams::TDN::AddR
127180}
128181
129182TCertificateAuthorizationParams::operator bool () const {
130- return SubjectDn;
183+ return SubjectDn || SubjectDns ;
131184}
132185
133- bool TCertificateAuthorizationParams::CheckSubject (const std::unordered_map<TString, std::vector<TString>>& subjectDescription) const {
134- bool isDescriptionMatched = false ;
135- for (const auto & rdn: SubjectDn.RDNs ) {
136- isDescriptionMatched = false ;
186+ bool TCertificateAuthorizationParams::CheckSubject (const std::unordered_map<TString, std::vector<TString>>& subjectDescription, const std::vector<TString>& subjectDns) const {
187+ for (const TRDN& rdn: SubjectDn.RDNs ) {
137188 auto fieldIt = subjectDescription.find (rdn.Attribute );
138189 if (fieldIt == subjectDescription.cend ()) {
139- break ;
190+ return false ;
140191 }
141192
142193 const auto & attributeValues = fieldIt->second ;
143- bool attributeMatched = false ;
144- for (const auto & attributeValue : attributeValues) {
145- attributeMatched = false ;
146- for (const auto & value: rdn.Values ) {
147- if (value == attributeValue) {
148- attributeMatched = true ;
149- break ;
150- }
151- }
152- if (!attributeMatched) {
153- for (const auto & suffix: rdn.Suffixes ) {
154- if (attributeValue.EndsWith (suffix)) {
155- attributeMatched = true ;
156- break ;
157- }
158- }
159- }
160- if (!attributeMatched) {
194+ if (!rdn.Match (attributeValues)) {
195+ return false ;
196+ }
197+ }
198+
199+ if (SubjectDns) {
200+ bool dnsMatched = false ;
201+ for (const TString& dns : subjectDns) {
202+ if (SubjectDns->Match (dns)) {
203+ dnsMatched = true ;
161204 break ;
162205 }
163206 }
164- if (!attributeMatched) {
165- isDescriptionMatched = false ;
166- break ;
207+ if (!dnsMatched) {
208+ return false ;
167209 }
168- isDescriptionMatched = true ;
169210 }
170211
171- if (isDescriptionMatched) {
172- return true ;
173- }
174- return false ;
212+ return true ;
175213}
176214
177215TCertificateAuthorizationParams::TDN::operator bool () const {
178216 return !RDNs.empty ();
179217}
180218
181- TCertificateAuthorizationParams::TRDN::TRDN (const TString& Attribute )
182- :Attribute(Attribute )
219+ TCertificateAuthorizationParams::TRDN::TRDN (const TString& attribute )
220+ : Attribute(attribute )
183221{}
184222
185223TCertificateAuthorizationParams::TRDN& TCertificateAuthorizationParams::TRDN::AddValue (const TString& val)
@@ -194,4 +232,30 @@ TCertificateAuthorizationParams::TRDN& TCertificateAuthorizationParams::TRDN::Ad
194232 return *this ;
195233}
196234
235+ bool TCertificateAuthorizationParams::TRDN::Match (const TString& value) const
236+ {
237+ for (const auto & v : Values) {
238+ if (value == v) {
239+ return true ;
240+ }
241+ }
242+ for (const auto & s : Suffixes) {
243+ if (value.EndsWith (s)) {
244+ return true ;
245+ }
246+ }
247+
248+ return false ;
249+ }
250+
251+ bool TCertificateAuthorizationParams::TRDN::Match (const std::vector<TString>& values) const
252+ {
253+ for (const auto & value : values) {
254+ if (!Match (value)) {
255+ return false ;
256+ }
257+ }
258+ return true ;
259+ }
260+
197261} // namespace NKikimr {
0 commit comments