/src/botan/src/lib/x509/asn1_alt_name.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | |
15 | | namespace Botan { |
16 | | |
17 | | /* |
18 | | * Create an AlternativeName |
19 | | */ |
20 | | AlternativeName::AlternativeName(std::string_view email_addr, |
21 | | std::string_view uri, |
22 | | std::string_view dns, |
23 | 0 | std::string_view ip) { |
24 | 0 | if(!email_addr.empty()) { |
25 | 0 | add_email(email_addr); |
26 | 0 | } |
27 | 0 | if(!dns.empty()) { |
28 | 0 | add_dns(dns); |
29 | 0 | } |
30 | 0 | if(!uri.empty()) { |
31 | 0 | add_uri(uri); |
32 | 0 | } |
33 | 0 | if(!ip.empty()) { |
34 | 0 | if(auto ipv4 = string_to_ipv4(ip)) { |
35 | 0 | add_ipv4_address(*ipv4); |
36 | 0 | } else { |
37 | 0 | throw Invalid_Argument(fmt("Invalid IPv4 address '{}'", ip)); |
38 | 0 | } |
39 | 0 | } |
40 | 0 | } |
41 | | |
42 | | /* |
43 | | * Add an attribute to an alternative name |
44 | | */ |
45 | 0 | void AlternativeName::add_attribute(std::string_view type, std::string_view value) { |
46 | 0 | if(type.empty() || value.empty()) { |
47 | 0 | return; |
48 | 0 | } |
49 | | |
50 | 0 | if(type == "DNS") { |
51 | 0 | this->add_dns(value); |
52 | 0 | } else if(type == "RFC822") { |
53 | 0 | this->add_email(value); |
54 | 0 | } else if(type == "URI") { |
55 | 0 | this->add_uri(value); |
56 | 0 | } else if(type == "DN") { |
57 | 0 | X509_DN dn; |
58 | 0 | std::istringstream ss{std::string(value)}; |
59 | 0 | ss >> dn; |
60 | 0 | this->add_dn(dn); |
61 | 0 | } else if(type == "IP") { |
62 | 0 | if(auto ipv4 = string_to_ipv4(value)) { |
63 | 0 | add_ipv4_address(*ipv4); |
64 | 0 | } else { |
65 | 0 | throw Invalid_Argument(fmt("Invalid IPv4 address '{}'", value)); |
66 | 0 | } |
67 | 0 | } else { |
68 | 0 | throw Not_Implemented(fmt("Unknown AlternativeName name type {}", type)); |
69 | 0 | } |
70 | 0 | } |
71 | | |
72 | | /* |
73 | | * Add an OtherName field |
74 | | */ |
75 | 6.50k | void AlternativeName::add_othername(const OID& oid, std::string_view value, ASN1_Type type) { |
76 | 6.50k | if(value.empty()) { |
77 | 152 | return; |
78 | 152 | } |
79 | 6.35k | this->add_other_name(oid, ASN1_String(value, type)); |
80 | 6.35k | } |
81 | | |
82 | | /* |
83 | | * Return all of the alternative names |
84 | | */ |
85 | 3.75k | std::multimap<std::string, std::string> AlternativeName::contents() const { |
86 | 3.75k | std::multimap<std::string, std::string> names; |
87 | | |
88 | 3.75k | for(const auto& nm : this->dns()) { |
89 | 970 | names.emplace("DNS", nm); |
90 | 970 | } |
91 | | |
92 | 4.89k | for(const auto& nm : this->email()) { |
93 | 4.89k | names.emplace("RFC822", nm); |
94 | 4.89k | } |
95 | | |
96 | 3.75k | for(const auto& nm : this->uris()) { |
97 | 3.08k | names.emplace("URI", nm); |
98 | 3.08k | } |
99 | | |
100 | 3.75k | for(uint32_t ipv4 : this->ipv4_address()) { |
101 | 2.30k | names.emplace("IP", ipv4_to_string(ipv4)); |
102 | 2.30k | } |
103 | | |
104 | 3.75k | for(const auto& nm : this->directory_names()) { |
105 | 2.02k | names.emplace("DN", nm.to_string()); |
106 | 2.02k | } |
107 | | |
108 | 3.75k | for(const auto& othername : this->other_names()) { |
109 | 2.53k | names.emplace(othername.first.to_formatted_string(), othername.second.value()); |
110 | 2.53k | } |
111 | | |
112 | 3.75k | return names; |
113 | 3.75k | } |
114 | | |
115 | 0 | std::multimap<std::string, std::string, std::less<>> AlternativeName::get_attributes() const { |
116 | 0 | std::multimap<std::string, std::string, std::less<>> r; |
117 | |
|
118 | 0 | for(const auto& c : this->contents()) { |
119 | 0 | r.emplace(c.first, c.second); |
120 | 0 | } |
121 | |
|
122 | 0 | return r; |
123 | 0 | } |
124 | | |
125 | 0 | bool AlternativeName::has_field(std::string_view attr) const { |
126 | 0 | return !this->get_attribute(attr).empty(); |
127 | 0 | } |
128 | | |
129 | 0 | std::string AlternativeName::get_first_attribute(std::string_view type) const { |
130 | 0 | auto attr = this->get_attribute(type); |
131 | |
|
132 | 0 | if(!attr.empty()) { |
133 | 0 | return attr[0]; |
134 | 0 | } |
135 | | |
136 | 0 | return ""; |
137 | 0 | } |
138 | | |
139 | 3 | std::vector<std::string> AlternativeName::get_attribute(std::string_view attr) const { |
140 | 3 | auto set_to_vector = [](const std::set<std::string>& s) -> std::vector<std::string> { return {s.begin(), s.end()}; }; |
141 | | |
142 | 3 | if(attr == "DNS") { |
143 | 0 | return set_to_vector(this->dns()); |
144 | 3 | } else if(attr == "RFC822") { |
145 | 0 | return set_to_vector(this->email()); |
146 | 3 | } else if(attr == "URI") { |
147 | 0 | return set_to_vector(this->uris()); |
148 | 3 | } else if(attr == "DN") { |
149 | 0 | std::vector<std::string> ret; |
150 | |
|
151 | 0 | for(const auto& nm : this->directory_names()) { |
152 | 0 | ret.push_back(nm.to_string()); |
153 | 0 | } |
154 | |
|
155 | 0 | return ret; |
156 | 3 | } else if(attr == "IP") { |
157 | 0 | std::vector<std::string> ip_str; |
158 | 0 | for(uint32_t ipv4 : this->ipv4_address()) { |
159 | 0 | ip_str.push_back(ipv4_to_string(ipv4)); |
160 | 0 | } |
161 | 0 | return ip_str; |
162 | 3 | } else { |
163 | 3 | return {}; |
164 | 3 | } |
165 | 3 | } |
166 | | |
167 | 0 | X509_DN AlternativeName::dn() const { |
168 | | // This logic really does not make any sense, but it is |
169 | | // how this function was historically implemented. |
170 | |
|
171 | 0 | X509_DN combined_dn; |
172 | |
|
173 | 0 | for(const auto& dn : this->directory_names()) { |
174 | 0 | std::ostringstream oss; |
175 | 0 | oss << dn; |
176 | |
|
177 | 0 | std::istringstream iss(oss.str()); |
178 | 0 | iss >> combined_dn; |
179 | 0 | } |
180 | |
|
181 | 0 | return combined_dn; |
182 | 0 | } |
183 | | |
184 | | /* |
185 | | * Return if this object has anything useful |
186 | | */ |
187 | | } // namespace Botan |