Botan 3.5.0
Crypto and TLS for C&
asn1_alt_name.cpp
Go to the documentation of this file.
1/*
2* AlternativeName
3* (C) 1999-2007 Jack Lloyd
4* 2007 Yves Jerschow
5*
6* Botan is released under the Simplified BSD License (see license.txt)
7*/
8
9#include <botan/pkix_types.h>
10
11#include <botan/internal/fmt.h>
12#include <botan/internal/parsing.h>
13#include <sstream>
14
15namespace Botan {
16
17/*
18* Create an AlternativeName
19*/
20AlternativeName::AlternativeName(std::string_view email_addr,
21 std::string_view uri,
22 std::string_view dns,
23 std::string_view ip) {
24 if(!email_addr.empty()) {
25 add_email(email_addr);
26 }
27 if(!dns.empty()) {
28 add_dns(dns);
29 }
30 if(!uri.empty()) {
31 add_uri(uri);
32 }
33 if(!ip.empty()) {
34 if(auto ipv4 = string_to_ipv4(ip)) {
35 add_ipv4_address(*ipv4);
36 } else {
37 throw Invalid_Argument(fmt("Invalid IPv4 address '{}'", ip));
38 }
39 }
40}
41
42/*
43* Add an attribute to an alternative name
44*/
45void AlternativeName::add_attribute(std::string_view type, std::string_view value) {
46 if(type.empty() || value.empty()) {
47 return;
48 }
49
50 if(type == "DNS") {
51 this->add_dns(value);
52 } else if(type == "RFC822") {
53 this->add_email(value);
54 } else if(type == "URI") {
55 this->add_uri(value);
56 } else if(type == "DN") {
57 X509_DN dn;
58 std::istringstream ss{std::string(value)};
59 ss >> dn;
60 this->add_dn(dn);
61 } else if(type == "IP") {
62 if(auto ipv4 = string_to_ipv4(value)) {
63 add_ipv4_address(*ipv4);
64 } else {
65 throw Invalid_Argument(fmt("Invalid IPv4 address '{}'", value));
66 }
67 } else {
68 throw Not_Implemented(fmt("Unknown AlternativeName name type {}", type));
69 }
70}
71
72/*
73* Add an OtherName field
74*/
75void AlternativeName::add_othername(const OID& oid, std::string_view value, ASN1_Type type) {
76 if(value.empty()) {
77 return;
78 }
79 this->add_other_name(oid, ASN1_String(value, type));
80}
81
82/*
83* Return all of the alternative names
84*/
85std::multimap<std::string, std::string> AlternativeName::contents() const {
86 std::multimap<std::string, std::string> names;
87
88 for(const auto& nm : this->dns()) {
89 names.emplace("DNS", nm);
90 }
91
92 for(const auto& nm : this->email()) {
93 names.emplace("RFC822", nm);
94 }
95
96 for(const auto& nm : this->uris()) {
97 names.emplace("URI", nm);
98 }
99
100 for(uint32_t ipv4 : this->ipv4_address()) {
101 names.emplace("IP", ipv4_to_string(ipv4));
102 }
103
104 for(const auto& nm : this->directory_names()) {
105 names.emplace("DN", nm.to_string());
106 }
107
108 for(const auto& othername : this->other_names()) {
109 names.emplace(othername.first.to_formatted_string(), othername.second.value());
110 }
111
112 return names;
113}
114
115std::multimap<std::string, std::string, std::less<>> AlternativeName::get_attributes() const {
116 std::multimap<std::string, std::string, std::less<>> r;
117
118 for(const auto& c : this->contents()) {
119 r.emplace(c.first, c.second);
120 }
121
122 return r;
123}
124
125bool AlternativeName::has_field(std::string_view attr) const {
126 return !this->get_attribute(attr).empty();
127}
128
129std::string AlternativeName::get_first_attribute(std::string_view type) const {
130 auto attr = this->get_attribute(type);
131
132 if(!attr.empty()) {
133 return attr[0];
134 }
135
136 return "";
137}
138
139std::vector<std::string> AlternativeName::get_attribute(std::string_view attr) const {
140 auto set_to_vector = [](const std::set<std::string>& s) -> std::vector<std::string> { return {s.begin(), s.end()}; };
141
142 if(attr == "DNS") {
143 return set_to_vector(this->dns());
144 } else if(attr == "RFC822") {
145 return set_to_vector(this->email());
146 } else if(attr == "URI") {
147 return set_to_vector(this->uris());
148 } else if(attr == "DN") {
149 std::vector<std::string> ret;
150
151 for(const auto& nm : this->directory_names()) {
152 ret.push_back(nm.to_string());
153 }
154
155 return ret;
156 } else if(attr == "IP") {
157 std::vector<std::string> ip_str;
158 for(uint32_t ipv4 : this->ipv4_address()) {
159 ip_str.push_back(ipv4_to_string(ipv4));
160 }
161 return ip_str;
162 } else {
163 return {};
164 }
165}
166
168 // This logic really does not make any sense, but it is
169 // how this function was historically implemented.
170
171 X509_DN combined_dn;
172
173 for(const auto& dn : this->directory_names()) {
174 std::ostringstream oss;
175 oss << dn;
176
177 std::istringstream iss(oss.str());
178 iss >> combined_dn;
179 }
180
181 return combined_dn;
182}
183
184/*
185* Return if this object has anything useful
186*/
187} // namespace Botan
const std::set< X509_DN > & directory_names() const
Return the set of directory names included in this alternative name.
Definition pkix_types.h:164
std::string get_first_attribute(std::string_view attr) const
void add_dns(std::string_view dns)
Add a DNS name to this AlternativeName.
Definition alt_name.cpp:30
void add_ipv4_address(uint32_t ipv4)
Add an IP address to this alternative name.
Definition alt_name.cpp:44
void add_email(std::string_view addr)
Add a URI to this AlternativeName.
Definition alt_name.cpp:24
std::multimap< std::string, std::string > contents() const
std::vector< std::string > get_attribute(std::string_view attr) const
const std::set< uint32_t > & ipv4_address() const
Return the set of IPv4 addresses included in this alternative name.
Definition pkix_types.h:155
const std::set< std::pair< OID, ASN1_String > > & other_names() const
Return the set of "other names" included in this alternative name.
Definition pkix_types.h:159
const std::set< std::string > & uris() const
Return the set of URIs included in this alternative name.
Definition pkix_types.h:146
void add_uri(std::string_view uri)
Add a URI to this AlternativeName.
Definition alt_name.cpp:18
void add_attribute(std::string_view type, std::string_view value)
const std::set< std::string > & dns() const
Return the set of DNS names included in this alternative name.
Definition pkix_types.h:152
std::multimap< std::string, std::string, std::less<> > get_attributes() const
void add_other_name(const OID &oid, const ASN1_String &value)
Add an "OtherName" identified by object identifier to this AlternativeName.
Definition alt_name.cpp:36
void add_othername(const OID &oid, std::string_view value, ASN1_Type type)
AlternativeName()
Create an empty name.
Definition pkix_types.h:125
const std::set< std::string > & email() const
Return the set of email addresses included in this alternative name.
Definition pkix_types.h:149
void add_dn(const X509_DN &dn)
Add a directory name to this AlternativeName.
Definition alt_name.cpp:40
bool has_field(std::string_view attr) const
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
ASN1_Type
Definition asn1_obj.h:44
std::optional< uint32_t > string_to_ipv4(std::string_view str)
Definition parsing.cpp:156
std::string ipv4_to_string(uint32_t ip)
Definition parsing.cpp:225