#include <Certificate.h>
Public Types | |
typedef DCPS::unique_ptr < Certificate > | unique_ptr |
Public Member Functions | |
Certificate (const std::string &uri, const std::string &password="") | |
Certificate (const DDS::OctetSeq &src) | |
Certificate (const Certificate &other) | |
Certificate () | |
virtual | ~Certificate () |
Certificate & | operator= (const Certificate &rhs) |
bool | load (DDS::Security::SecurityException &ex, const std::string &uri, const std::string &password="") |
int | validate (const Certificate &ca, unsigned long int flags=0u) const |
int | verify_signature (const DDS::OctetSeq &src, const std::vector< const DDS::OctetSeq * > &expected_contents) const |
int | subject_name_to_str (std::string &dst, unsigned long flags=XN_FLAG_ONELINE) const |
int | subject_name_digest (std::vector< CORBA::Octet > &dst) const |
int | serialize (DDS::OctetSeq &dst) const |
int | deserialize (const DDS::OctetSeq &src) |
const DDS::OctetSeq & | original_bytes () const |
const char * | dsign_algo () const |
const char * | keypair_algo () const |
Private Member Functions | |
bool | loaded () |
int | cache_dsign_algo () |
void | load_cert_bytes (const std::string &path) |
void | load_cert_data_bytes (const std::string &data) |
Static Private Member Functions | |
static X509 * | x509_from_pem (const std::string &path, const std::string &password="") |
static X509 * | x509_from_pem (const DDS::OctetSeq &bytes, const std::string &password="") |
Private Attributes | |
X509 * | x_ |
DDS::OctetSeq | original_bytes_ |
std::string | dsign_algo_ |
Friends | |
class | verify_signature_impl |
DdsSecurity_Export std::ostream & | operator<< (std::ostream &, const Certificate &) |
DdsSecurity_Export bool | operator== (const Certificate &lhs, const Certificate &rhs) |
Definition at line 24 of file Certificate.h.
Definition at line 29 of file Certificate.h.
OpenDDS::Security::SSL::Certificate::Certificate | ( | const std::string & | uri, | |
const std::string & | password = "" | |||
) |
Definition at line 23 of file Certificate.cpp.
References LM_WARNING, load(), and DDS::Security::SecurityException::message.
00025 : x_(NULL), original_bytes_(), dsign_algo_("") 00026 { 00027 DDS::Security::SecurityException ex; 00028 if (! load(ex, uri, password)) { 00029 ACE_ERROR((LM_WARNING, "(%P|%t) %C\n", ex.message.in())); 00030 } 00031 }
OpenDDS::Security::SSL::Certificate::Certificate | ( | const DDS::OctetSeq & | src | ) |
Definition at line 33 of file Certificate.cpp.
References deserialize().
00034 : x_(NULL), original_bytes_(), dsign_algo_("") 00035 { 00036 deserialize(src); 00037 }
OpenDDS::Security::SSL::Certificate::Certificate | ( | const Certificate & | other | ) |
Definition at line 45 of file Certificate.cpp.
References deserialize(), and original_bytes_.
00046 : x_(NULL), original_bytes_(), dsign_algo_("") 00047 { 00048 if (0 < other.original_bytes_.length()) { 00049 deserialize(other.original_bytes_); 00050 } 00051 }
OpenDDS::Security::SSL::Certificate::Certificate | ( | ) |
Definition at line 39 of file Certificate.cpp.
00040 : x_(NULL), original_bytes_(), dsign_algo_("") 00041 { 00042 00043 }
OpenDDS::Security::SSL::Certificate::~Certificate | ( | ) | [virtual] |
Definition at line 53 of file Certificate.cpp.
References x_.
int OpenDDS::Security::SSL::Certificate::cache_dsign_algo | ( | ) | [private] |
Definition at line 400 of file Certificate.cpp.
References dsign_algo_, and x_.
Referenced by deserialize(), and load().
00401 { 00402 return cache_dsign_algo_impl()(x_, dsign_algo_); 00403 }
int OpenDDS::Security::SSL::Certificate::deserialize | ( | const DDS::OctetSeq & | src | ) |
Definition at line 580 of file Certificate.cpp.
References cache_dsign_algo(), original_bytes_, and x_.
Referenced by Certificate(), and operator=().
00581 { 00582 int err = deserialize_impl(src)(x_) || cache_dsign_algo(); 00583 if (! err) { 00584 original_bytes_ = src; 00585 } 00586 00587 return err; 00588 }
const char* OpenDDS::Security::SSL::Certificate::dsign_algo | ( | ) | const [inline] |
Definition at line 88 of file Certificate.h.
Referenced by OpenDDS::Security::AuthenticationBuiltInImpl::begin_handshake_reply(), OpenDDS::Security::AuthenticationBuiltInImpl::begin_handshake_request(), and OpenDDS::Security::CredentialHash::operator()().
00088 { return dsign_algo_.c_str(); }
const char * OpenDDS::Security::SSL::Certificate::keypair_algo | ( | ) | const |
Definition at line 335 of file Certificate.cpp.
References dsign_algo_.
Referenced by OpenDDS::Security::AuthenticationBuiltInImpl::get_identity_token().
00336 { 00337 // This should probably be pulling the information directly from 00338 // the certificate. 00339 if (std::string("RSASSA-PSS-SHA256") == dsign_algo_) { 00340 return "RSA-2048"; 00341 00342 } else if (std::string("ECDSA-SHA256") == dsign_algo_) { 00343 return "EC-prime256v1"; 00344 00345 } else { 00346 return "UNKNOWN"; 00347 } 00348 }
bool OpenDDS::Security::SSL::Certificate::load | ( | DDS::Security::SecurityException & | ex, | |
const std::string & | uri, | |||
const std::string & | password = "" | |||
) |
Definition at line 69 of file Certificate.cpp.
References cache_dsign_algo(), OpenDDS::Security::CommonUtilities::URI::everything_else, LM_WARNING, load_cert_bytes(), load_cert_data_bytes(), loaded(), original_bytes_, OpenDDS::Security::CommonUtilities::URI::scheme, OpenDDS::Security::CommonUtilities::set_security_error(), OpenDDS::Security::CommonUtilities::URI::URI_DATA, OpenDDS::Security::CommonUtilities::URI::URI_FILE, OpenDDS::Security::CommonUtilities::URI::URI_PKCS11, OpenDDS::Security::CommonUtilities::URI::URI_UNKNOWN, x509_from_pem(), and x_.
Referenced by Certificate().
00072 { 00073 using namespace CommonUtilities; 00074 00075 if (x_) { 00076 set_security_error(ex, -1, 0, "SSL::Certificate::load: WARNING: document already loaded"); 00077 return false; 00078 } 00079 00080 URI uri_info(uri); 00081 00082 switch (uri_info.scheme) { 00083 case URI::URI_FILE: 00084 load_cert_bytes(uri_info.everything_else); 00085 x_ = x509_from_pem(original_bytes_, password); 00086 break; 00087 00088 case URI::URI_DATA: 00089 load_cert_data_bytes(uri_info.everything_else); 00090 x_ = x509_from_pem(original_bytes_, password); 00091 break; 00092 00093 case URI::URI_PKCS11: 00094 case URI::URI_UNKNOWN: 00095 default: 00096 ACE_ERROR((LM_WARNING, 00097 "(%P|%t) SSL::Certificate::load: WARNING: Unsupported URI scheme\n")); 00098 00099 break; 00100 } 00101 00102 if (! loaded()) { 00103 std::stringstream msg; 00104 msg << "SSL::Certificate::load: WARNING: Failed to load document supplied " 00105 "with URI '" << uri << "'"; 00106 set_security_error(ex, -1, 0, msg.str().c_str()); 00107 return false; 00108 } 00109 00110 int err = cache_dsign_algo(); 00111 if (err) { 00112 set_security_error(ex, -1, 0, "SSL::Certificate::load: WARNING: Failed to cache signature algorithm"); 00113 return false; 00114 } 00115 return true; 00116 }
void OpenDDS::Security::SSL::Certificate::load_cert_bytes | ( | const std::string & | path | ) | [private] |
Definition at line 405 of file Certificate.cpp.
References OpenDDS::DCPS::back_inserter(), LM_ERROR, original_bytes_, and strerror().
Referenced by load().
00406 { 00407 std::ifstream in(path.c_str(), std::ios::binary); 00408 00409 if (in.fail()) { 00410 ACE_ERROR((LM_ERROR, 00411 "(%P|%t) Certificate::load_cert_bytes:" 00412 "WARNING: Failed to load file '%C'; errno: '%C'\n", 00413 path.c_str(), strerror(errno))); 00414 return; 00415 } 00416 00417 DCPS::SequenceBackInsertIterator<DDS::OctetSeq> back_inserter(original_bytes_); 00418 00419 std::copy((std::istreambuf_iterator<char>(in)), 00420 std::istreambuf_iterator<char>(), 00421 back_inserter); 00422 00423 // To appease the other DDS security implementations which 00424 // append a null byte at the end of the cert. 00425 *back_inserter = 0u; 00426 }
void OpenDDS::Security::SSL::Certificate::load_cert_data_bytes | ( | const std::string & | data | ) | [private] |
Definition at line 428 of file Certificate.cpp.
References original_bytes_.
Referenced by load().
00429 { 00430 // The minus 1 is because path contains a comma in element 0 and that 00431 // comma is not included in the cert string 00432 original_bytes_.length(data.size() - 1); 00433 std::memcpy(original_bytes_.get_buffer(), &data[1], 00434 original_bytes_.length()); 00435 00436 // To appease the other DDS security implementations which 00437 // append a null byte at the end of the cert. 00438 original_bytes_.length(original_bytes_.length() + 1); 00439 original_bytes_[original_bytes_.length() - 1] = 0; 00440 }
bool OpenDDS::Security::SSL::Certificate::loaded | ( | ) | [inline, private] |
Definition at line 94 of file Certificate.h.
Referenced by load().
00094 { 00095 return (x_ != NULL) && 00096 (0 < original_bytes_.length()); 00097 }
Certificate & OpenDDS::Security::SSL::Certificate::operator= | ( | const Certificate & | rhs | ) |
Definition at line 58 of file Certificate.cpp.
References deserialize(), original_bytes_, and x_.
00059 { 00060 if (this != &rhs) { 00061 if (rhs.x_ && (0 < rhs.original_bytes_.length())) { 00062 deserialize(rhs.original_bytes_); 00063 } 00064 00065 } 00066 return *this; 00067 }
const DDS::OctetSeq& OpenDDS::Security::SSL::Certificate::original_bytes | ( | ) | const [inline] |
Definition at line 86 of file Certificate.h.
Referenced by OpenDDS::Security::AuthenticationBuiltInImpl::begin_handshake_reply(), OpenDDS::Security::AuthenticationBuiltInImpl::begin_handshake_request(), and OpenDDS::Security::CredentialHash::operator()().
00086 { return original_bytes_; }
int OpenDDS::Security::SSL::Certificate::serialize | ( | DDS::OctetSeq & | dst | ) | const |
Definition at line 516 of file Certificate.cpp.
References OpenDDS::DCPS::back_inserter(), OpenDDS::DCPS::const_sequence_begin(), OpenDDS::DCPS::const_sequence_end(), and original_bytes_.
00517 { 00518 std::copy(DCPS::const_sequence_begin(original_bytes_), 00519 DCPS::const_sequence_end(original_bytes_), 00520 DCPS::back_inserter(dst)); 00521 00522 if (dst.length() == original_bytes_.length()) { 00523 return 0; 00524 } 00525 00526 return 1; 00527 }
int OpenDDS::Security::SSL::Certificate::subject_name_digest | ( | std::vector< CORBA::Octet > & | dst | ) | const |
Definition at line 309 of file Certificate.cpp.
References len, OPENDDS_SSL_LOG_ERR, and x_.
00310 { 00311 dst.clear(); 00312 00313 if (!x_) return 1; 00314 00315 /* Do not free name! */ 00316 X509_NAME* name = X509_get_subject_name(x_); 00317 if (NULL == name) { 00318 OPENDDS_SSL_LOG_ERR("X509_get_subject_name failed"); 00319 return 1; 00320 } 00321 00322 std::vector<CORBA::Octet> tmp(EVP_MAX_MD_SIZE); 00323 00324 unsigned int len = 0; 00325 if (1 != X509_NAME_digest(name, EVP_sha256(), &tmp[0], &len)) { 00326 OPENDDS_SSL_LOG_ERR("X509_NAME_digest failed"); 00327 return 1; 00328 } 00329 00330 dst.insert(dst.begin(), tmp.begin(), tmp.begin() + len); 00331 00332 return 0; 00333 }
int OpenDDS::Security::SSL::Certificate::subject_name_to_str | ( | std::string & | dst, | |
unsigned long | flags = XN_FLAG_ONELINE | |||
) | const |
Definition at line 267 of file Certificate.cpp.
References OpenDDS::DCPS::back_inserter(), len, OPENDDS_SSL_LOG_ERR, and x_.
Referenced by OpenDDS::Security::AuthenticationBuiltInImpl::get_identity_token(), and OpenDDS::Security::AccessControlBuiltInImpl::validate_remote_permissions().
00269 { 00270 int result = 1; 00271 00272 dst.clear(); 00273 00274 if (x_) { 00275 /* Do not free name! */ 00276 X509_NAME* name = X509_get_subject_name(x_); 00277 if (name) { 00278 BIO* buffer = BIO_new(BIO_s_mem()); 00279 if (buffer) { 00280 int len = X509_NAME_print_ex(buffer, name, 0, flags); 00281 if (len > 0) { 00282 std::vector<char> tmp(len + 00283 1); // BIO_gets will add null hence +1 00284 len = BIO_gets(buffer, &tmp[0], len + 1); 00285 if (len > 0) { 00286 std::copy( 00287 tmp.begin(), 00288 tmp.end() - 00289 1, // But... string inserts a null so it's not needed 00290 std::back_inserter(dst)); 00291 result = 0; 00292 00293 } else { 00294 OPENDDS_SSL_LOG_ERR("failed to write BIO to string"); 00295 } 00296 00297 } else { 00298 OPENDDS_SSL_LOG_ERR("failed to read X509_NAME into BIO buffer"); 00299 } 00300 00301 BIO_free(buffer); 00302 } 00303 } 00304 } 00305 00306 return result; 00307 }
int OpenDDS::Security::SSL::Certificate::validate | ( | const Certificate & | ca, | |
unsigned long int | flags = 0u | |||
) | const |
Definition at line 118 of file Certificate.cpp.
References ACE_TEXT(), LM_WARNING, OPENDDS_SSL_LOG_ERR, and x_.
00119 { 00120 int result = X509_V_ERR_UNSPECIFIED; 00121 00122 if (x_) { 00123 if (ca.x_) { 00124 X509_STORE* certs = X509_STORE_new(); 00125 if (certs) { 00126 X509_STORE_add_cert(certs, ca.x_); 00127 00128 X509_STORE_CTX* validation_ctx = X509_STORE_CTX_new(); 00129 if (validation_ctx) { 00130 X509_STORE_CTX_init(validation_ctx, certs, x_, NULL); 00131 X509_STORE_CTX_set_flags(validation_ctx, flags); 00132 00133 if (X509_verify_cert(validation_ctx) == 1) { 00134 result = X509_V_OK; 00135 00136 } else { 00137 int err = X509_STORE_CTX_get_error(validation_ctx), 00138 depth = X509_STORE_CTX_get_error_depth(validation_ctx); 00139 00140 ACE_ERROR((LM_WARNING, 00141 ACE_TEXT("(%P|%t) SSL::Certificate::verify: WARNING '%C' occurred using cert at " 00142 "depth '%i', validation failed.\n"), 00143 X509_verify_cert_error_string(err), 00144 depth)); 00145 00146 result = err; 00147 } 00148 00149 X509_STORE_CTX_free(validation_ctx); 00150 } 00151 00152 X509_STORE_free(certs); 00153 00154 } else { 00155 OPENDDS_SSL_LOG_ERR("failed to create X509_STORE"); 00156 } 00157 00158 } else { 00159 ACE_ERROR((LM_WARNING, 00160 ACE_TEXT("(%P|%t) SSL::Certificate::verify: WARNING, passed-in CA has not loaded a " 00161 "certificate\n"))); 00162 } 00163 00164 } else { 00165 ACE_ERROR((LM_WARNING, 00166 ACE_TEXT("(%P|%t) SSL::Certificate::verify: WARNING, a certificate must be loaded before " 00167 "it can be verified\n"))); 00168 } 00169 00170 return result; 00171 }
int OpenDDS::Security::SSL::Certificate::verify_signature | ( | const DDS::OctetSeq & | src, | |
const std::vector< const DDS::OctetSeq * > & | expected_contents | |||
) | const |
Definition at line 249 of file Certificate.cpp.
00252 { 00253 #ifdef OPENSSL_V_1_0 00254 struct EVP_PKEY_Handle { 00255 EVP_PKEY* pkey_; 00256 explicit EVP_PKEY_Handle(EVP_PKEY* pkey) : pkey_(pkey) {} 00257 operator EVP_PKEY*() { return pkey_; } 00258 ~EVP_PKEY_Handle() { EVP_PKEY_free(pkey_); } 00259 } pkey(X509_get_pubkey(x_)); 00260 #else 00261 EVP_PKEY* pkey = X509_get0_pubkey(x_); 00262 #endif 00263 verify_implementation verify(pkey); 00264 return verify(src, expected_contents); 00265 }
X509 * OpenDDS::Security::SSL::Certificate::x509_from_pem | ( | const DDS::OctetSeq & | bytes, | |
const std::string & | password = "" | |||
) | [static, private] |
Definition at line 474 of file Certificate.cpp.
References OPENDDS_SSL_LOG_ERR.
00476 { 00477 X509* result = NULL; 00478 00479 BIO* filebuf = BIO_new(BIO_s_mem()); 00480 do { 00481 if (filebuf) { 00482 if (0 >= BIO_write(filebuf, bytes.get_buffer(), bytes.length())) { 00483 OPENDDS_SSL_LOG_ERR("BIO_write failed"); 00484 break; 00485 } 00486 if (password != "") { 00487 result = PEM_read_bio_X509_AUX(filebuf, NULL, NULL, 00488 (void*)password.c_str()); 00489 if (!result) { 00490 OPENDDS_SSL_LOG_ERR("PEM_read_bio_X509_AUX failed"); 00491 break; 00492 } 00493 00494 } else { 00495 result = PEM_read_bio_X509_AUX(filebuf, NULL, NULL, NULL); 00496 if (!result) { 00497 OPENDDS_SSL_LOG_ERR("PEM_read_bio_X509_AUX failed"); 00498 break; 00499 } 00500 } 00501 00502 } else { 00503 std::stringstream errmsg; 00504 errmsg << "BIO_new failed"; 00505 OPENDDS_SSL_LOG_ERR(errmsg.str().c_str()); 00506 break; 00507 } 00508 00509 } while (0); 00510 00511 BIO_free(filebuf); 00512 00513 return result; 00514 }
X509 * OpenDDS::Security::SSL::Certificate::x509_from_pem | ( | const std::string & | path, | |
const std::string & | password = "" | |||
) | [static, private] |
Definition at line 442 of file Certificate.cpp.
References OPENDDS_SSL_LOG_ERR.
Referenced by load().
00444 { 00445 X509* result = NULL; 00446 00447 BIO* filebuf = BIO_new_file(path.c_str(), "r"); 00448 if (filebuf) { 00449 if (password != "") { 00450 result = 00451 PEM_read_bio_X509_AUX(filebuf, NULL, NULL, (void*)password.c_str()); 00452 if (!result) { 00453 OPENDDS_SSL_LOG_ERR("PEM_read_bio_X509_AUX failed"); 00454 } 00455 00456 } else { 00457 result = PEM_read_bio_X509_AUX(filebuf, NULL, NULL, NULL); 00458 if (!result) { 00459 OPENDDS_SSL_LOG_ERR("PEM_read_bio_X509_AUX failed"); 00460 } 00461 } 00462 00463 BIO_free(filebuf); 00464 00465 } else { 00466 std::stringstream errmsg; 00467 errmsg << "failed to read file '" << path << "' using BIO_new_file"; 00468 OPENDDS_SSL_LOG_ERR(errmsg.str().c_str()); 00469 } 00470 00471 return result; 00472 }
DdsSecurity_Export std::ostream& operator<< | ( | std::ostream & | , | |
const Certificate & | ||||
) | [friend] |
DdsSecurity_Export bool operator== | ( | const Certificate & | lhs, | |
const Certificate & | rhs | |||
) | [friend] |
friend class verify_signature_impl [friend] |
Definition at line 27 of file Certificate.h.
std::string OpenDDS::Security::SSL::Certificate::dsign_algo_ [private] |
Definition at line 116 of file Certificate.h.
Referenced by cache_dsign_algo(), and keypair_algo().
Definition at line 115 of file Certificate.h.
Referenced by Certificate(), deserialize(), load(), load_cert_bytes(), load_cert_data_bytes(), operator=(), and serialize().
X509* OpenDDS::Security::SSL::Certificate::x_ [private] |
Definition at line 114 of file Certificate.h.
Referenced by cache_dsign_algo(), deserialize(), load(), OpenDDS::Security::SSL::verify_signature_impl::operator()(), operator=(), subject_name_digest(), subject_name_to_str(), validate(), verify_signature(), and ~Certificate().