8#include <botan/pkix_types.h>
10#include <botan/ber_dec.h>
11#include <botan/der_enc.h>
12#include <botan/internal/stl_util.h>
23bool caseless_eq(
char a,
char b) {
24 return (std::tolower(
static_cast<unsigned char>(a)) == std::tolower(
static_cast<unsigned char>(b)));
27bool is_space(
char c) {
28 return c ==
' ' || c ==
'\t';
36bool x500_name_cmp(std::string_view name1, std::string_view name2) {
38 auto p1 = name1.begin();
39 auto p2 = name2.begin();
41 while((p1 != name1.end()) && is_space(*p1)) {
44 while((p2 != name2.end()) && is_space(*p2)) {
48 while(p1 != name1.end() && p2 != name2.end()) {
54 while((p1 != name1.end()) && is_space(*p1)) {
57 while((p2 != name2.end()) && is_space(*p2)) {
61 if(p1 == name1.end() && p2 == name2.end()) {
64 if(p1 == name1.end() || p2 == name2.end()) {
69 if(!caseless_eq(*p1, *p2)) {
77 while((p1 != name1.end()) && is_space(*p1)) {
80 if(p1 != name1.end()) {
84 while((p2 != name2.end()) && is_space(*p2)) {
87 if(p2 != name2.end()) {
112 m_rdn.push_back(std::make_pair(oid, str));
120 std::multimap<OID, std::string> retval;
122 for(
const auto& i : m_rdn) {
123 retval.emplace(i.first, i.second.value());
132 std::multimap<std::string, std::string> retval;
134 for(
const auto& i : m_rdn) {
135 retval.emplace(i.first.to_formatted_string(), i.second.value());
152 for(
const auto& i : m_rdn) {
167 for(
const auto& i : m_rdn) {
182 std::vector<std::string> values;
184 for(
const auto& i : m_rdn) {
186 values.push_back(i.second.value());
197 if(info ==
"Name" || info ==
"CommonName" || info ==
"CN") {
198 return "X520.CommonName";
200 if(info ==
"SerialNumber" || info ==
"SN") {
201 return "X520.SerialNumber";
203 if(info ==
"Country" || info ==
"C") {
204 return "X520.Country";
206 if(info ==
"Organization" || info ==
"O") {
207 return "X520.Organization";
209 if(info ==
"Organizational Unit" || info ==
"OrgUnit" || info ==
"OU") {
210 return "X520.OrganizationalUnit";
212 if(info ==
"Locality" || info ==
"L") {
213 return "X520.Locality";
215 if(info ==
"State" || info ==
"Province" || info ==
"ST") {
218 if(info ==
"Email") {
221 return std::string(info);
231 if(attr1.size() != attr2.size()) {
235 auto p1 = attr1.begin();
236 auto p2 = attr2.begin();
239 if(p1 == attr1.end() && p2 == attr2.end()) {
242 if(p1 == attr1.end()) {
245 if(p2 == attr2.end()) {
248 if(p1->first != p2->first) {
251 if(!x500_name_cmp(p1->second, p2->second)) {
264 return !(dn1 == dn2);
275 if(attr1.size() < attr2.size()) {
278 if(attr1.size() > attr2.size()) {
283 auto p1 = attr1.begin();
284 auto p2 = attr2.begin();
286 while(p1 != attr1.end() && p2 != attr2.end()) {
287 if(p1->first != p2->first) {
288 return (p1->first < p2->first);
304 while(p1 != attr1.end() && p2 != attr2.end()) {
308 if(!x500_name_cmp(p1->second, p2->second)) {
311 return (p1->second < p2->second);
324 std::vector<uint8_t> result;
336 if(!m_dn_bits.empty()) {
343 for(
const auto& dn : m_rdn) {
355 std::vector<uint8_t> bits;
385std::string to_short_form(
const OID& oid) {
388 if(long_id ==
"X520.CommonName") {
392 if(long_id ==
"X520.Country") {
396 if(long_id ==
"X520.Organization") {
400 if(long_id ==
"X520.OrganizationalUnit") {
410 std::ostringstream out;
416 const auto& info = dn.
dn_info();
418 for(
size_t i = 0; i != info.size(); ++i) {
419 out << to_short_form(info[i].first) <<
"=\"";
420 for(
char c : info[i].second.value()) {
421 if(c ==
'\\' || c ==
'\"') {
428 if(i + 1 < info.size()) {
446 if(is_space(c) && key.empty()) {
448 }
else if(!is_space(c)) {
459 if(!is_space(c) && c !=
'=') {
461 }
else if(c ==
'=') {
468 bool in_quotes =
false;
473 if(!in_quotes && !val.empty()) {
475 }
else if(in_quotes) {
478 }
else if(c ==
'"') {
479 in_quotes = !in_quotes;
480 }
else if(c ==
'\\') {
485 }
else if(c ==
',' && !in_quotes) {
492 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 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)