00001
00002
00003
00004
00005
00006
00007
00008
00009 #include <botan/asn1_obj.h>
00010 #include <botan/der_enc.h>
00011 #include <botan/ber_dec.h>
00012 #include <botan/oids.h>
00013 #include <botan/internal/stl_util.h>
00014 #include <botan/charset.h>
00015 #include <botan/parsing.h>
00016 #include <botan/loadstor.h>
00017
00018 namespace Botan {
00019
00020
00021
00022
00023 AlternativeName::AlternativeName(const std::string& email_addr,
00024 const std::string& uri,
00025 const std::string& dns,
00026 const std::string& ip)
00027 {
00028 add_attribute("RFC822", email_addr);
00029 add_attribute("DNS", dns);
00030 add_attribute("URI", uri);
00031 add_attribute("IP", ip);
00032 }
00033
00034
00035
00036
00037 void AlternativeName::add_attribute(const std::string& type,
00038 const std::string& str)
00039 {
00040 if(type == "" || str == "")
00041 return;
00042
00043 typedef std::multimap<std::string, std::string>::iterator iter;
00044 std::pair<iter, iter> range = alt_info.equal_range(type);
00045 for(iter j = range.first; j != range.second; ++j)
00046 if(j->second == str)
00047 return;
00048
00049 multimap_insert(alt_info, type, str);
00050 }
00051
00052
00053
00054
00055 void AlternativeName::add_othername(const OID& oid, const std::string& value,
00056 ASN1_Tag type)
00057 {
00058 if(value == "")
00059 return;
00060 multimap_insert(othernames, oid, ASN1_String(value, type));
00061 }
00062
00063
00064
00065
00066 std::multimap<std::string, std::string> AlternativeName::get_attributes() const
00067 {
00068 return alt_info;
00069 }
00070
00071
00072
00073
00074 std::multimap<OID, ASN1_String> AlternativeName::get_othernames() const
00075 {
00076 return othernames;
00077 }
00078
00079
00080
00081
00082 std::multimap<std::string, std::string> AlternativeName::contents() const
00083 {
00084 std::multimap<std::string, std::string> names;
00085
00086 typedef std::multimap<std::string, std::string>::const_iterator rdn_iter;
00087 for(rdn_iter j = alt_info.begin(); j != alt_info.end(); ++j)
00088 multimap_insert(names, j->first, j->second);
00089
00090 typedef std::multimap<OID, ASN1_String>::const_iterator on_iter;
00091 for(on_iter j = othernames.begin(); j != othernames.end(); ++j)
00092 multimap_insert(names, OIDS::lookup(j->first), j->second.value());
00093
00094 return names;
00095 }
00096
00097
00098
00099
00100 bool AlternativeName::has_items() const
00101 {
00102 return (alt_info.size() > 0 || othernames.size() > 0);
00103 }
00104
00105 namespace {
00106
00107
00108
00109
00110 void encode_entries(DER_Encoder& encoder,
00111 const std::multimap<std::string, std::string>& attr,
00112 const std::string& type, ASN1_Tag tagging)
00113 {
00114 typedef std::multimap<std::string, std::string>::const_iterator iter;
00115
00116 std::pair<iter, iter> range = attr.equal_range(type);
00117 for(iter j = range.first; j != range.second; ++j)
00118 {
00119 if(type == "RFC822" || type == "DNS" || type == "URI")
00120 {
00121 ASN1_String asn1_string(j->second, IA5_STRING);
00122 encoder.add_object(tagging, CONTEXT_SPECIFIC, asn1_string.iso_8859());
00123 }
00124 else if(type == "IP")
00125 {
00126 u32bit ip = string_to_ipv4(j->second);
00127 byte ip_buf[4] = { 0 };
00128 store_be(ip, ip_buf);
00129 encoder.add_object(tagging, CONTEXT_SPECIFIC, ip_buf, 4);
00130 }
00131 }
00132 }
00133
00134 }
00135
00136
00137
00138
00139 void AlternativeName::encode_into(DER_Encoder& der) const
00140 {
00141 der.start_cons(SEQUENCE);
00142
00143 encode_entries(der, alt_info, "RFC822", ASN1_Tag(1));
00144 encode_entries(der, alt_info, "DNS", ASN1_Tag(2));
00145 encode_entries(der, alt_info, "URI", ASN1_Tag(6));
00146 encode_entries(der, alt_info, "IP", ASN1_Tag(7));
00147
00148 std::multimap<OID, ASN1_String>::const_iterator i;
00149 for(i = othernames.begin(); i != othernames.end(); ++i)
00150 {
00151 der.start_explicit(0)
00152 .encode(i->first)
00153 .start_explicit(0)
00154 .encode(i->second)
00155 .end_explicit()
00156 .end_explicit();
00157 }
00158
00159 der.end_cons();
00160 }
00161
00162
00163
00164
00165 void AlternativeName::decode_from(BER_Decoder& source)
00166 {
00167 BER_Decoder names = source.start_cons(SEQUENCE);
00168
00169 while(names.more_items())
00170 {
00171 BER_Object obj = names.get_next_object();
00172 if((obj.class_tag != CONTEXT_SPECIFIC) &&
00173 (obj.class_tag != (CONTEXT_SPECIFIC | CONSTRUCTED)))
00174 continue;
00175
00176 ASN1_Tag tag = obj.type_tag;
00177
00178 if(tag == 0)
00179 {
00180 BER_Decoder othername(obj.value);
00181
00182 OID oid;
00183 othername.decode(oid);
00184 if(othername.more_items())
00185 {
00186 BER_Object othername_value_outer = othername.get_next_object();
00187 othername.verify_end();
00188
00189 if(othername_value_outer.type_tag != ASN1_Tag(0) ||
00190 othername_value_outer.class_tag !=
00191 (CONTEXT_SPECIFIC | CONSTRUCTED)
00192 )
00193 throw Decoding_Error("Invalid tags on otherName value");
00194
00195 BER_Decoder othername_value_inner(othername_value_outer.value);
00196
00197 BER_Object value = othername_value_inner.get_next_object();
00198 othername_value_inner.verify_end();
00199
00200 ASN1_Tag value_type = value.type_tag;
00201
00202 if(is_string_type(value_type) && value.class_tag == UNIVERSAL)
00203 add_othername(oid, ASN1::to_string(value), value_type);
00204 }
00205 }
00206 else if(tag == 1 || tag == 2 || tag == 6)
00207 {
00208 const std::string value = Charset::transcode(ASN1::to_string(obj),
00209 LATIN1_CHARSET,
00210 LOCAL_CHARSET);
00211
00212 if(tag == 1) add_attribute("RFC822", value);
00213 if(tag == 2) add_attribute("DNS", value);
00214 if(tag == 6) add_attribute("URI", value);
00215 }
00216 else if(tag == 7)
00217 {
00218 if(obj.value.size() == 4)
00219 {
00220 u32bit ip = load_be<u32bit>(obj.value.begin(), 0);
00221 add_attribute("IP", ipv4_to_string(ip));
00222 }
00223 }
00224
00225 }
00226 }
00227
00228 }