25 #include <openssl/ssl.h>
43 std::ifstream pem( file );
44 std::string head =
"";
45 std::getline( pem, head );
46 std::regex re(
"-----BEGIN (.*)-----");
49 if (std::regex_search( head, match, re ) && match.size() > 1 ) {
65 for (
auto item : items ) {
68 if ( kvpair.size() == 2 ) {
69 if ( kvpair[0] ==
"C" ) identity.
countryCode = kvpair[1];
70 else if ( kvpair[0] ==
"ST" ) identity.
state = kvpair[1];
71 else if ( kvpair[0] ==
"L" ) identity.
locality = kvpair[1];
72 else if ( kvpair[0] ==
"O" ) identity.
organization = kvpair[1];
74 else if ( kvpair[0] ==
"CN" ) identity.
commonName = kvpair[1];
75 else if ( kvpair[0] ==
"emailAddress" ) identity.
email = kvpair[1];
76 else if ( kvpair[0] ==
"businessCategory" ) identity.
businessCategory = kvpair[1];
77 else if ( kvpair[0] ==
"jurisdictionC" ) identity.
jurisdictionC = kvpair[1];
78 else if ( kvpair[0] ==
"jurisdictionST" ) identity.
jurisdictionST = kvpair[1];
79 else if ( kvpair[0] ==
"serialNumber" ) identity.
serialNumber = kvpair[1];
80 else if ( kvpair[0] ==
"street" ) identity.
street = kvpair[1];
81 else if ( kvpair[0] ==
"postalCode" ) identity.
postalCode = kvpair[1];
82 else identity.
other[ kvpair[0] ] = kvpair[1];
93 BIO* pembio = BIO_new( BIO_s_file() );
95 if ( pembio ==
nullptr )
throw_Exception(
"BIO_new( BIO_s_file() ) failed " +
97 int rc = BIO_read_filename( pembio, file.c_str() );
100 X509_REQ* temp = PEM_read_bio_X509_REQ( pembio,
nullptr,
nullptr,
nullptr );
101 if ( temp ==
nullptr )
throw_Exception(
"PEM_read_bio_X509_AUX failed " +
113 X509_NAME* name = X509_REQ_get_subject_name( cert );
114 BIO* output_bio = BIO_new( BIO_s_mem() );
115 X509_NAME_print_ex( output_bio, name, 0, XN_FLAG_RFC2253 );
117 BIO_free( output_bio );
122 std::stringstream ss;
123 ss << std::hex << std::setfill(
'0');
124 unsigned int hash_size;
125 unsigned char hash[EVP_MAX_MD_SIZE];
126 const EVP_MD * digest = EVP_get_digestbyname( hashname.c_str() );
127 if ( digest ==
nullptr )
throw_Exception(
"EVP_get_digestbyname failed " +
129 int rc = X509_REQ_digest( cert, digest, hash, &hash_size);
132 for(
unsigned int pos = 0; pos < hash_size; pos++ ) {
133 if ( pos ) ss <<
":";
134 ss << std::setw(2) << (
unsigned int)hash[pos];
144 BIO* pembio = BIO_new( BIO_s_file() );
146 if ( pembio ==
nullptr )
throw_Exception(
"BIO_new( BIO_s_file() ) failed " +
148 int rc = BIO_read_filename( pembio, file.c_str() );
151 X509* temp = PEM_read_bio_X509_AUX( pembio,
nullptr,
nullptr,
nullptr );
152 if ( temp ==
nullptr )
throw_Exception(
"PEM_read_bio_X509_AUX failed " +
164 X509_NAME* name = X509_get_issuer_name( cert );
165 BIO* output_bio = BIO_new( BIO_s_mem() );
166 X509_NAME_print_ex( output_bio, name, 0, XN_FLAG_RFC2253 );
168 BIO_free( output_bio );
173 const ASN1_INTEGER* val = X509_get0_serialNumber( cert );
174 BIGNUM *bnser = ASN1_INTEGER_to_BN( val,
nullptr );
175 char *serialChar = BN_bn2hex(bnser);
176 std::string tmp = serialChar;
183 X509_NAME* name = X509_get_subject_name( cert );
184 BIO* output_bio = BIO_new( BIO_s_mem() );
185 X509_NAME_print_ex( output_bio, name, 0, XN_FLAG_RFC2253 );
187 BIO_free( output_bio );
193 std::list<X509Certificate::SAN> result;
194 GENERAL_NAMES* subjectaltnames = (GENERAL_NAMES*)X509_get_ext_d2i( cert, NID_subject_alt_name, NULL, NULL);
195 if ( !subjectaltnames )
return result;
196 int altnamecount = sk_GENERAL_NAME_num(subjectaltnames);
197 for (
int i = 0; i < altnamecount; i++ ) {
198 GENERAL_NAME* generalname = sk_GENERAL_NAME_value( subjectaltnames, i) ;
200 if ( generalname->type == GEN_URI ||
201 generalname->type == GEN_DNS ||
202 generalname->type == GEN_EMAIL ) {
203 std::string san = std::string(
reinterpret_cast<char*
>(generalname->d.ia5->data));
205 }
else if ( generalname->type == GEN_IPADD) {
206 unsigned char *data = generalname->d.ip->data;
207 if ( generalname->d.ip->length == 4 ) {
208 std::stringstream ip;
209 ip << (int)data[0] <<
'.' << (
int)data[1] <<
'.' << (int)data[2] <<
'.' << (
int)data[3];
212 const unsigned char *ipdata = ASN1_STRING_get0_data( generalname->d.iPAddress );
213 int datalen = ASN1_STRING_length( generalname->d.ia5 );
214 const unsigned char *p = ipdata;
215 std::stringstream ip;
216 for (
int j = 0; j < datalen/2 ; j++ ) {
217 if ( j > 0 ) ip <<
":";
218 ip << std::hex << (int)(p[0] << 8 | p[1]);
226 if ( subjectaltnames ) sk_GENERAL_NAME_pop_free( subjectaltnames, GENERAL_NAME_free );
231 std::stringstream ss;
232 ss << std::hex << std::setfill(
'0') << std::uppercase;
233 unsigned int hash_size;
234 unsigned char hash[EVP_MAX_MD_SIZE];
235 const EVP_MD * digest = EVP_get_digestbyname( hashname.c_str() );
236 if ( digest ==
nullptr )
throw_Exception(
"EVP_get_digestbyname failed " +
238 int rc = X509_digest( cert, digest, hash, &hash_size);
241 for(
unsigned int pos = 0; pos < hash_size; pos++ ) {
242 if ( pos ) ss <<
":";
243 ss << std::setw(2) << (
unsigned int)hash[pos];
249 if ( peer.length() < san.length() )
return false;
250 auto itr_peer = peer.rbegin();
251 auto itr_san = san.rbegin();
252 while ( itr_peer != peer.rend() && itr_san != san.rend() ) {
253 if ( *itr_peer != *itr_san ) {
254 if ( allowwildcard && *itr_san ==
'*' ) {
256 while ( itr_peer != peer.rend() ) {
257 if ( *itr_peer ==
'.' )
return false;
266 return peer.length() == san.length();
272 if ( addr_peer.
isValid() && addr_san.
isValid() && addr_peer == addr_san )
279 bool verified =
false;
287 verified = std::any_of( cert_sans.cbegin(),
289 [san,wildcards](
const SAN &s) ->
bool { return s.san_type == san.san_type &&
290 verifyName( san.san_name, s.san_name, wildcards ); } );
294 verified = std::any_of( cert_sans.cbegin(),
296 [san](
const SAN &s) ->
bool { return s.san_type == san.san_type &&
297 verifyIP( san.san_name, s.san_name ); } );