8#include <botan/pkix_types.h>
10#include <botan/assert.h>
11#include <botan/ber_dec.h>
12#include <botan/der_enc.h>
13#include <botan/internal/x509_utils.h>
21bool is_space(
char c) {
22 return c ==
' ' || c ==
'\t';
28class X500_Char_Iterator final {
30 explicit X500_Char_Iterator(std::string_view s) : m_str(s), m_pos(0) {
32 while(m_pos < m_str.size() && is_space(m_str[m_pos])) {
38 std::optional<char> next() {
39 if(m_pos >= m_str.size()) {
43 if(is_space(m_str[m_pos])) {
45 while(m_pos < m_str.size() && is_space(m_str[m_pos])) {
49 if(m_pos < m_str.size()) {
55 const char c = m_str[m_pos++];
57 if(c >=
'A' && c <=
'Z') {
58 return static_cast<char>(c + (
'a' -
'A'));
63 static std::string canonicalize(std::string_view name) {
65 result.reserve(name.size());
67 X500_Char_Iterator it(name);
68 while(
auto c = it.next()) {
76 std::string_view m_str;
83 X500_Char_Iterator it1(name1);
84 X500_Char_Iterator it2(name2);
87 const auto c1 = it1.next();
88 const auto c2 = it2.next();
93 if(!c1.has_value() && !c2.has_value()) {
114 m_rdn.push_back(std::make_pair(oid, str));
122 std::multimap<OID, std::string> retval;
124 for(
const auto& i : m_rdn) {
125 retval.emplace(i.first, i.second.value());
134 std::multimap<std::string, std::string> retval;
136 for(
const auto& i : m_rdn) {
137 retval.emplace(i.first.to_formatted_string(), i.second.value());
154 for(
const auto& i : m_rdn) {
169 for(
const auto& i : m_rdn) {
184 std::vector<std::string> values;
186 for(
const auto& i : m_rdn) {
188 values.push_back(i.second.value());
199 if(info ==
"Name" || info ==
"CommonName" || info ==
"CN") {
200 return "X520.CommonName";
202 if(info ==
"SerialNumber" || info ==
"SN") {
203 return "X520.SerialNumber";
205 if(info ==
"Country" || info ==
"C") {
206 return "X520.Country";
208 if(info ==
"Organization" || info ==
"O") {
209 return "X520.Organization";
211 if(info ==
"Organizational Unit" || info ==
"OrgUnit" || info ==
"OU") {
212 return "X520.OrganizationalUnit";
214 if(info ==
"Locality" || info ==
"L") {
215 return "X520.Locality";
217 if(info ==
"State" || info ==
"Province" || info ==
"ST") {
220 if(info ==
"Email") {
223 return std::string(info);
233 if(attr1.size() != attr2.size()) {
237 auto p1 = attr1.begin();
238 auto p2 = attr2.begin();
241 if(p1 == attr1.end() && p2 == attr2.end()) {
244 if(p1 == attr1.end()) {
247 if(p2 == attr2.end()) {
250 if(p1->first != p2->first) {
266 return !(dn1 == dn2);
277 if(attr1.size() != attr2.size()) {
278 return attr1.size() < attr2.size();
282 auto p1 = attr1.begin();
283 auto p2 = attr2.begin();
285 while(p1 != attr1.end() && p2 != attr2.end()) {
286 if(p1->first != p2->first) {
287 return (p1->first < p2->first);
292 const std::string c1 = X500_Char_Iterator::canonicalize(p1->second);
293 const std::string c2 = X500_Char_Iterator::canonicalize(p2->second);
308 std::vector<uint8_t> result;
320 if(!m_dn_bits.empty()) {
327 for(
const auto& dn : m_rdn) {
339 std::vector<uint8_t> bits;
369std::string to_short_form(
const OID& oid) {
372 if(long_id ==
"X520.CommonName") {
376 if(long_id ==
"X520.Country") {
380 if(long_id ==
"X520.Organization") {
384 if(long_id ==
"X520.OrganizationalUnit") {
394 std::ostringstream out;
400 const auto& info = dn.
dn_info();
402 for(
size_t i = 0; i != info.size(); ++i) {
403 out << to_short_form(info[i].first) <<
"=\"";
404 for(
const char c : info[i].second.value()) {
405 if(c ==
'\\' || c ==
'\"') {
412 if(i + 1 < info.size()) {
430 if(is_space(c) && key.empty()) {
432 }
else if(!is_space(c)) {
443 if(!is_space(c) && c !=
'=') {
445 }
else if(c ==
'=') {
452 bool in_quotes =
false;
457 if(!in_quotes && !val.empty()) {
459 }
else if(in_quotes) {
462 }
else if(c ==
'"') {
463 in_quotes = !in_quotes;
464 }
else if(c ==
'\\') {
469 }
else if(c ==
',' && !in_quotes) {
476 if(!key.empty() && !val.empty()) {
#define BOTAN_DEBUG_ASSERT(expr)
const std::string & value() const
BER_Decoder & decode(bool &out)
BER_Decoder & raw_bytes(std::vector< uint8_t, Alloc > &out)
BER_Decoder start_sequence()
DER_Encoder & start_set()
DER_Encoder & start_sequence()
DER_Encoder & raw_bytes(const uint8_t val[], size_t len)
DER_Encoder & encode(bool b)
std::string to_formatted_string() const
static OID from_string(std::string_view str)
bool has_field(const OID &oid) const
std::multimap< std::string, std::string > contents() const
std::vector< std::string > get_attribute(std::string_view attr) const
void add_attribute(std::string_view key, std::string_view val)
std::multimap< OID, std::string > get_attributes() const
ASN1_String get_first_attribute(const OID &oid) const
const std::vector< std::pair< OID, ASN1_String > > & dn_info() const
void encode_into(DER_Encoder &to) const override
std::vector< uint8_t > DER_encode() const
std::string to_string() const
void decode_from(BER_Decoder &from) override
static std::string deref_info_field(std::string_view key)
bool x500_name_cmp(std::string_view name1, std::string_view name2)
bool operator<(const OID &a, const OID &b)
std::ostream & operator<<(std::ostream &out, const OID &oid)
bool operator!=(const AlgorithmIdentifier &a1, const AlgorithmIdentifier &a2)
bool operator==(const AlgorithmIdentifier &a1, const AlgorithmIdentifier &a2)
int operator>>(int fd, Pipe &pipe)