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>
22bool caseless_eq(
char a,
char b) {
23 return (std::tolower(
static_cast<unsigned char>(a)) == std::tolower(
static_cast<unsigned char>(b)));
26bool is_space(
char c) {
27 return c ==
' ' || c ==
'\t';
34 auto p1 = name1.begin();
35 auto p2 = name2.begin();
37 while((p1 != name1.end()) && is_space(*p1)) {
40 while((p2 != name2.end()) && is_space(*p2)) {
44 while(p1 != name1.end() && p2 != name2.end()) {
50 while((p1 != name1.end()) && is_space(*p1)) {
53 while((p2 != name2.end()) && is_space(*p2)) {
57 if(p1 == name1.end() && p2 == name2.end()) {
60 if(p1 == name1.end() || p2 == name2.end()) {
65 if(!caseless_eq(*p1, *p2)) {
73 while((p1 != name1.end()) && is_space(*p1)) {
76 if(p1 != name1.end()) {
80 while((p2 != name2.end()) && is_space(*p2)) {
83 if(p2 != name2.end()) {
106 m_rdn.push_back(std::make_pair(oid, str));
114 std::multimap<OID, std::string> retval;
116 for(
const auto& i : m_rdn) {
117 retval.emplace(i.first, i.second.value());
126 std::multimap<std::string, std::string> retval;
128 for(
const auto& i : m_rdn) {
129 retval.emplace(i.first.to_formatted_string(), i.second.value());
146 for(
const auto& i : m_rdn) {
161 for(
const auto& i : m_rdn) {
176 std::vector<std::string> values;
178 for(
const auto& i : m_rdn) {
180 values.push_back(i.second.value());
191 if(info ==
"Name" || info ==
"CommonName" || info ==
"CN") {
192 return "X520.CommonName";
194 if(info ==
"SerialNumber" || info ==
"SN") {
195 return "X520.SerialNumber";
197 if(info ==
"Country" || info ==
"C") {
198 return "X520.Country";
200 if(info ==
"Organization" || info ==
"O") {
201 return "X520.Organization";
203 if(info ==
"Organizational Unit" || info ==
"OrgUnit" || info ==
"OU") {
204 return "X520.OrganizationalUnit";
206 if(info ==
"Locality" || info ==
"L") {
207 return "X520.Locality";
209 if(info ==
"State" || info ==
"Province" || info ==
"ST") {
212 if(info ==
"Email") {
215 return std::string(info);
225 if(attr1.size() != attr2.size()) {
229 auto p1 = attr1.begin();
230 auto p2 = attr2.begin();
233 if(p1 == attr1.end() && p2 == attr2.end()) {
236 if(p1 == attr1.end()) {
239 if(p2 == attr2.end()) {
242 if(p1->first != p2->first) {
258 return !(dn1 == dn2);
269 if(attr1.size() < attr2.size()) {
272 if(attr1.size() > attr2.size()) {
277 auto p1 = attr1.begin();
278 auto p2 = attr2.begin();
280 while(p1 != attr1.end() && p2 != attr2.end()) {
281 if(p1->first != p2->first) {
282 return (p1->first < p2->first);
298 while(p1 != attr1.end() && p2 != attr2.end()) {
305 return (p1->second < p2->second);
318 std::vector<uint8_t> result;
330 if(!m_dn_bits.empty()) {
337 for(
const auto& dn : m_rdn) {
349 std::vector<uint8_t> bits;
379std::string to_short_form(
const OID& oid) {
382 if(long_id ==
"X520.CommonName") {
386 if(long_id ==
"X520.Country") {
390 if(long_id ==
"X520.Organization") {
394 if(long_id ==
"X520.OrganizationalUnit") {
404 std::ostringstream out;
410 const auto& info = dn.
dn_info();
412 for(
size_t i = 0; i != info.size(); ++i) {
413 out << to_short_form(info[i].first) <<
"=\"";
414 for(
const char c : info[i].second.value()) {
415 if(c ==
'\\' || c ==
'\"') {
422 if(i + 1 < info.size()) {
440 if(is_space(c) && key.empty()) {
442 }
else if(!is_space(c)) {
453 if(!is_space(c) && c !=
'=') {
455 }
else if(c ==
'=') {
462 bool in_quotes =
false;
467 if(!in_quotes && !val.empty()) {
469 }
else if(in_quotes) {
472 }
else if(c ==
'"') {
473 in_quotes = !in_quotes;
474 }
else if(c ==
'\\') {
479 }
else if(c ==
',' && !in_quotes) {
486 if(!key.empty() && !val.empty()) {
#define BOTAN_ASSERT_NOMSG(expr)
#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)