1
1
#include " cert_auth_processor.h"
2
2
3
3
#include < openssl/x509.h>
4
+ #include < openssl/x509v3.h>
4
5
#include < openssl/pem.h>
5
6
#include < openssl/bio.h>
6
7
#include < openssl/objects.h>
@@ -100,6 +101,56 @@ TVector<std::pair<TString, TString>> X509CertificateReader::ReadIssuerTerms(cons
100
101
return ReadTerms (name);
101
102
}
102
103
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
+
103
154
TString X509CertificateReader::GetFingerprint (const X509Ptr& x509) {
104
155
static constexpr size_t FINGERPRINT_LENGTH = SHA_DIGEST_LENGTH;
105
156
unsigned char fingerprint[FINGERPRINT_LENGTH];
@@ -109,14 +160,16 @@ TString X509CertificateReader::GetFingerprint(const X509Ptr& x509) {
109
160
return HexEncode (fingerprint, FINGERPRINT_LENGTH);
110
161
}
111
162
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)
113
164
: SubjectDn(dn)
165
+ , SubjectDns(subjectDns)
114
166
, RequireSameIssuer(requireSameIssuer)
115
167
, Groups(groups)
116
168
{}
117
169
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)
119
171
: SubjectDn(std::move(dn))
172
+ , SubjectDns(std::move(subjectDns))
120
173
, RequireSameIssuer(requireSameIssuer)
121
174
, Groups(std::move(groups))
122
175
{}
@@ -127,59 +180,44 @@ TCertificateAuthorizationParams::TDN& TCertificateAuthorizationParams::TDN::AddR
127
180
}
128
181
129
182
TCertificateAuthorizationParams::operator bool () const {
130
- return SubjectDn;
183
+ return SubjectDn || SubjectDns ;
131
184
}
132
185
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 ) {
137
188
auto fieldIt = subjectDescription.find (rdn.Attribute );
138
189
if (fieldIt == subjectDescription.cend ()) {
139
- break ;
190
+ return false ;
140
191
}
141
192
142
193
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 ;
161
204
break ;
162
205
}
163
206
}
164
- if (!attributeMatched) {
165
- isDescriptionMatched = false ;
166
- break ;
207
+ if (!dnsMatched) {
208
+ return false ;
167
209
}
168
- isDescriptionMatched = true ;
169
210
}
170
211
171
- if (isDescriptionMatched) {
172
- return true ;
173
- }
174
- return false ;
212
+ return true ;
175
213
}
176
214
177
215
TCertificateAuthorizationParams::TDN::operator bool () const {
178
216
return !RDNs.empty ();
179
217
}
180
218
181
- TCertificateAuthorizationParams::TRDN::TRDN (const TString& Attribute )
182
- :Attribute(Attribute )
219
+ TCertificateAuthorizationParams::TRDN::TRDN (const TString& attribute )
220
+ : Attribute(attribute )
183
221
{}
184
222
185
223
TCertificateAuthorizationParams::TRDN& TCertificateAuthorizationParams::TRDN::AddValue (const TString& val)
@@ -194,4 +232,30 @@ TCertificateAuthorizationParams::TRDN& TCertificateAuthorizationParams::TRDN::Ad
194
232
return *this ;
195
233
}
196
234
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
+
197
261
} // namespace NKikimr {
0 commit comments