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_cmp(
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 std::isspace(
static_cast<unsigned char>(c));
36bool x500_name_cmp(std::string_view name1, std::string_view name2) {
37 auto p1 = name1.begin();
38 auto p2 = name2.begin();
40 while((p1 != name1.end()) && is_space(*p1)) {
43 while((p2 != name2.end()) && is_space(*p2)) {
47 while(p1 != name1.end() && p2 != name2.end()) {
53 while((p1 != name1.end()) && is_space(*p1)) {
56 while((p2 != name2.end()) && is_space(*p2)) {
60 if(p1 == name1.end() && p2 == name2.end()) {
63 if(p1 == name1.end() || p2 == name2.end()) {
68 if(!caseless_cmp(*p1, *p2)) {
75 while((p1 != name1.end()) && is_space(*p1)) {
78 while((p2 != name2.end()) && is_space(*p2)) {
82 if((p1 != name1.end()) || (p2 != name2.end())) {
105 m_rdn.push_back(std::make_pair(oid, str));
113 std::multimap<OID, std::string> retval;
115 for(
auto& i : m_rdn) {
116 retval.emplace(i.first, i.second.value());
125 std::multimap<std::string, std::string> retval;
127 for(
auto& i : m_rdn) {
128 retval.emplace(i.first.to_formatted_string(), i.second.value());
145 for(
auto& i : m_rdn) {
160 for(
auto& i : m_rdn) {
175 std::vector<std::string> values;
177 for(
auto& i : m_rdn) {
179 values.push_back(i.second.value());
190 if(info ==
"Name" || info ==
"CommonName" || info ==
"CN") {
191 return "X520.CommonName";
193 if(info ==
"SerialNumber" || info ==
"SN") {
194 return "X520.SerialNumber";
196 if(info ==
"Country" || info ==
"C") {
197 return "X520.Country";
199 if(info ==
"Organization" || info ==
"O") {
200 return "X520.Organization";
202 if(info ==
"Organizational Unit" || info ==
"OrgUnit" || info ==
"OU") {
203 return "X520.OrganizationalUnit";
205 if(info ==
"Locality" || info ==
"L") {
206 return "X520.Locality";
208 if(info ==
"State" || info ==
"Province" || info ==
"ST") {
211 if(info ==
"Email") {
214 return std::string(info);
224 if(attr1.size() != attr2.size()) {
228 auto p1 = attr1.begin();
229 auto p2 = attr2.begin();
232 if(p1 == attr1.end() && p2 == attr2.end()) {
235 if(p1 == attr1.end()) {
238 if(p2 == attr2.end()) {
241 if(p1->first != p2->first) {
244 if(!x500_name_cmp(p1->second, p2->second)) {
257 return !(dn1 == dn2);
268 if(attr1.size() < attr2.size()) {
271 if(attr1.size() > attr2.size()) {
276 auto p1 = attr1.begin();
277 auto p2 = attr2.begin();
279 while(p1 != attr1.end() && p2 != attr2.end()) {
280 if(p1->first != p2->first) {
281 return (p1->first < p2->first);
297 while(p1 != attr1.end() && p2 != attr2.end()) {
301 if(!x500_name_cmp(p1->second, p2->second)) {
304 return (p1->second < p2->second);
317 std::vector<uint8_t> result;
329 if(!m_dn_bits.empty()) {
336 for(
const auto& dn : m_rdn) {
348 std::vector<uint8_t> bits;
378std::string to_short_form(
const OID& oid) {
381 if(long_id ==
"X520.CommonName") {
385 if(long_id ==
"X520.Country") {
389 if(long_id ==
"X520.Organization") {
393 if(long_id ==
"X520.OrganizationalUnit") {
403 std::ostringstream out;
411 for(
size_t i = 0; i != info.size(); ++i) {
412 out << to_short_form(info[i].first) <<
"=\"";
413 for(
char c : info[i].second.value()) {
414 if(c ==
'\\' || c ==
'\"') {
421 if(i + 1 < info.size()) {
438 if(std::isspace(c) && key.empty()) {
440 }
else if(!std::isspace(c)) {
451 if(!std::isspace(c) && c !=
'=') {
453 }
else if(c ==
'=') {
460 bool in_quotes =
false;
464 if(std::isspace(c)) {
465 if(!in_quotes && !val.empty()) {
467 }
else if(in_quotes) {
470 }
else if(c ==
'"') {
471 in_quotes = !in_quotes;
472 }
else if(c ==
'\\') {
477 }
else if(c ==
',' && !in_quotes) {
484 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
void decode_from(BER_Decoder &) override
std::multimap< std::string, std::string > contents() const
void encode_into(DER_Encoder &) const override
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
std::vector< uint8_t > DER_encode() const
std::string to_string() const
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)