Botan 3.13.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// TODO(Botan4) this entire file can be deleted
10
11#include <botan/pkix_types.h>
12
13#include <botan/internal/fmt.h>
14#include <sstream>
15
16namespace Botan {
17
18/*
19* Create an AlternativeName
20*/
21AlternativeName::AlternativeName(std::string_view email_addr,
22 std::string_view uri,
23 std::string_view dns,
24 std::string_view ip) {
25 if(!email_addr.empty()) {
26 add_email(email_addr);
27 }
28 if(!dns.empty()) {
29 add_dns(dns);
30 }
31 if(!uri.empty()) {
32 add_uri(uri);
33 }
34 if(!ip.empty()) {
35 if(auto ipv4 = IPv4Address::from_string(ip)) {
36 add_ipv4_address(*ipv4);
37 } else {
38 throw Invalid_Argument(fmt("Invalid IPv4 address '{}'", ip));
39 }
40 }
41}
42
43/*
44* Add an attribute to an alternative name
45*/
46void AlternativeName::add_attribute(std::string_view type, std::string_view value) {
47 if(type.empty() || value.empty()) {
48 return;
49 }
50
51 if(type == "DNS") {
52 this->add_dns(value);
53 } else if(type == "RFC822") {
54 this->add_email(value);
55 } else if(type == "URI") {
56 this->add_uri(value);
57 } else if(type == "DN") {
58 if(auto dn = X509_DN::parse(value)) {
59 this->add_dn(*dn);
60 } else {
61 throw Invalid_Argument(fmt("Invalid X.509 DN '{}'", value));
62 }
63 } else if(type == "IP") {
64 if(auto ipv4 = IPv4Address::from_string(value)) {
65 add_ipv4_address(*ipv4);
66 } else {
67 throw Invalid_Argument(fmt("Invalid IPv4 address '{}'", value));
68 }
69 } else {
70 throw Not_Implemented(fmt("Unknown AlternativeName name type {}", type));
71 }
72}
73
74/*
75* Add an OtherName field
76*/
77void AlternativeName::add_othername(const OID& oid, std::string_view value, ASN1_Type type) {
78 if(value.empty()) {
79 return;
80 }
81 this->add_other_name(oid, ASN1_String(value, type));
82}
83
84/*
85* Return all of the alternative names
86*/
87std::multimap<std::string, std::string> AlternativeName::contents() const {
88 std::multimap<std::string, std::string> names;
89
90 for(const auto& nm : this->dns()) {
91 names.emplace("DNS", nm);
92 }
93
94 for(const auto& nm : this->email()) {
95 names.emplace("RFC822", nm);
96 }
97
98 for(const auto& nm : this->uris()) {
99 names.emplace("URI", nm);
100 }
101
102 for(const auto& ipv4 : this->ipv4_addresses()) {
103 names.emplace("IP", ipv4.to_string());
104 }
105
106 for(const auto& ipv6 : this->ipv6_addresses()) {
107 names.emplace("IPv6", ipv6.to_string());
108 }
109
110 for(const auto& nm : this->directory_names()) {
111 names.emplace("DN", nm.to_string());
112 }
113
114 for(const auto& othername : this->other_names()) {
115 names.emplace(othername.first.to_formatted_string(), othername.second.value());
116 }
117
118 return names;
119}
120
121std::multimap<std::string, std::string, std::less<>> AlternativeName::get_attributes() const {
122 std::multimap<std::string, std::string, std::less<>> r;
123
124 for(const auto& c : this->contents()) {
125 r.emplace(c.first, c.second);
126 }
127
128 return r;
129}
130
131bool AlternativeName::has_field(std::string_view attr) const {
132 return !this->get_attribute(attr).empty();
133}
134
135std::string AlternativeName::get_first_attribute(std::string_view type) const {
136 auto attr = this->get_attribute(type);
137
138 if(!attr.empty()) {
139 return attr[0];
140 }
141
142 return "";
143}
144
145std::vector<std::string> AlternativeName::get_attribute(std::string_view attr) const {
146 auto set_to_vector = [](const std::set<std::string>& s) -> std::vector<std::string> { return {s.begin(), s.end()}; };
147
148 if(attr == "DNS") {
149 return set_to_vector(this->dns());
150 } else if(attr == "RFC822") {
151 return set_to_vector(this->email());
152 } else if(attr == "URI") {
153 return set_to_vector(this->uris());
154 } else if(attr == "DN") {
155 std::vector<std::string> ret;
156
157 for(const auto& nm : this->directory_names()) {
158 ret.push_back(nm.to_string());
159 }
160
161 return ret;
162 } else if(attr == "IP") {
163 std::vector<std::string> ip_str;
164 for(const auto& ipv4 : this->ipv4_addresses()) {
165 ip_str.push_back(ipv4.to_string());
166 }
167 return ip_str;
168 } else {
169 return {};
170 }
171}
172
174 // This logic really does not make any sense, but it is
175 // how this function was historically implemented.
176
177 X509_DN combined_dn;
178
179 for(const auto& dn : this->directory_names()) {
180 for(const auto& rdn : dn.rdns()) {
181 combined_dn.add_rdn(rdn);
182 }
183 }
184
185 return combined_dn;
186}
187
188std::set<uint32_t> AlternativeName::ipv4_address() const {
189 std::set<uint32_t> out;
190 for(const auto& a : m_ipv4_addrs) {
191 out.insert(a.address());
192 }
193 return out;
194}
195
196} // namespace Botan
const std::set< IPv6Address > & ipv6_addresses() const
Return the set of IPv6 addresses included in this alternative name.
Definition pkix_types.h:423
const std::set< X509_DN > & directory_names() const
Return the set of directory names included in this alternative name.
Definition pkix_types.h:443
std::string get_first_attribute(std::string_view attr) const
void add_dns(std::string_view dns)
Add a DNS name to this AlternativeName, parsing and validating the input.
Definition alt_name.cpp:63
std::set< std::string > dns() const
Definition alt_name.cpp:78
void add_ipv4_address(uint32_t ipv4)
Add an IP address to this alternative name.
Definition pkix_types.h:374
void add_email(std::string_view addr)
Add an email address to this AlternativeName, parsing and validating the input.
Definition alt_name.cpp:40
std::set< uint32_t > ipv4_address() const
Return the set of IPv4 addresses included in this alternative name.
std::multimap< std::string, std::string > contents() const
std::vector< std::string > get_attribute(std::string_view attr) const
const std::set< std::pair< OID, ASN1_String > > & other_names() const
Return the set of "other names" whose value was a recognized ASN1_String type.
Definition pkix_types.h:427
void add_uri(std::string_view uri)
Add a URI to this AlternativeName, parsing and validating the input.
Definition alt_name.cpp:17
void add_attribute(std::string_view type, std::string_view value)
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:86
std::set< std::string > uris() const
Definition alt_name.cpp:32
void add_othername(const OID &oid, std::string_view value, ASN1_Type type)
std::set< std::string > email() const
Definition alt_name.cpp:55
const std::set< IPv4Address > & ipv4_addresses() const
Return the set of IPv4 addresses included in this alternative name.
Definition pkix_types.h:420
void add_dn(const X509_DN &dn)
Add a directory name to this AlternativeName.
Definition alt_name.cpp:101
AlternativeName()=default
Create an empty name.
bool has_field(std::string_view attr) const
static std::optional< IPv4Address > from_string(std::string_view str)
void add_rdn(std::vector< std::pair< OID, ASN1_String > > rdn)
Definition x509_dn.cpp:155
static std::optional< X509_DN > parse(std::string_view str)
Definition x509_dn.cpp:554
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
ASN1_Type
Definition asn1_obj.h:47