OpenDDS::Security::SSL::Certificate Class Reference

#include <Certificate.h>

Collaboration diagram for OpenDDS::Security::SSL::Certificate:
Collaboration graph
[legend]

List of all members.

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 ()
Certificateoperator= (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::OctetSeqoriginal_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 X509x509_from_pem (const std::string &path, const std::string &password="")
static X509x509_from_pem (const DDS::OctetSeq &bytes, const std::string &password="")

Private Attributes

X509x_
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)

Detailed Description

Definition at line 24 of file Certificate.h.


Member Typedef Documentation

Definition at line 29 of file Certificate.h.


Constructor & Destructor Documentation

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   }

Here is the call graph for this function:

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   }

Here is the call graph for this function:

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   }

Here is the call graph for this function:

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_.

00054   {
00055     if (x_) X509_free(x_);
00056   }


Member Function Documentation

int OpenDDS::Security::SSL::Certificate::cache_dsign_algo (  )  [private]
Returns:
int 0 on success; 1 on failure.

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   }

Here is the caller graph for this function:

int OpenDDS::Security::SSL::Certificate::deserialize ( const DDS::OctetSeq src  ) 
Returns:
int 0 on success; 1 on failure.

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   }

Here is the call graph for this function:

Here is the caller graph for this function:

const char* OpenDDS::Security::SSL::Certificate::dsign_algo (  )  const [inline]
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   }

Here is the caller graph for this function:

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   }

Here is the call graph for this function:

Here is the caller graph for this function:

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   }

Here is the call graph for this function:

Here is the caller graph for this function:

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   }

Here is the caller graph for this function:

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     }

Here is the caller graph for this function:

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   }

Here is the call graph for this function:

const DDS::OctetSeq& OpenDDS::Security::SSL::Certificate::original_bytes (  )  const [inline]
int OpenDDS::Security::SSL::Certificate::serialize ( DDS::OctetSeq dst  )  const
Returns:
int 0 on success; 1 on failure.

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   }

Here is the call graph for this function:

int OpenDDS::Security::SSL::Certificate::subject_name_digest ( std::vector< CORBA::Octet > &  dst  )  const
Returns:
int 0 on success; 1 on failure.

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
Returns:
int 0 on success; 1 on failure.

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   }

Here is the call graph for this function:

Here is the caller graph for this function:

int OpenDDS::Security::SSL::Certificate::validate ( const Certificate ca,
unsigned long int  flags = 0u 
) const
Returns:
int 0 on success; 1 on failure.

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   }

Here is the call graph for this function:

int OpenDDS::Security::SSL::Certificate::verify_signature ( const DDS::OctetSeq src,
const std::vector< const DDS::OctetSeq * > &  expected_contents 
) const
Returns:
int 0 on success; 1 on failure.

Definition at line 249 of file Certificate.cpp.

References pkey_, and x_.

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   }

Here is the caller graph for this function:


Friends And Related Function Documentation

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.


Member Data Documentation

Definition at line 116 of file Certificate.h.

Referenced by cache_dsign_algo(), and keypair_algo().


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 10 Aug 2018 for OpenDDS by  doxygen 1.6.1