diff options
| author | Carl Hetherington <cth@carlh.net> | 2013-01-01 20:11:25 +0000 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2013-01-01 20:11:25 +0000 |
| commit | 3adf49eea65c2c015ae0b5bc7f066a599faf3933 (patch) | |
| tree | 93e571aea5eec12772cf39058b51ddcabd8f3ee9 /src | |
| parent | 4f902db0ad994910a34ca845225635ceefcac96e (diff) | |
Some work on encryption / signing.
Diffstat (limited to 'src')
| -rw-r--r-- | src/certificates.cc | 120 | ||||
| -rw-r--r-- | src/certificates.h | 46 | ||||
| -rw-r--r-- | src/dcp.cc | 20 | ||||
| -rw-r--r-- | src/dcp.h | 6 | ||||
| -rw-r--r-- | src/dcp_time.h | 3 | ||||
| -rw-r--r-- | src/wscript | 1 |
6 files changed, 191 insertions, 5 deletions
diff --git a/src/certificates.cc b/src/certificates.cc new file mode 100644 index 00000000..c1e71b14 --- /dev/null +++ b/src/certificates.cc @@ -0,0 +1,120 @@ +#include <sstream> +#include <vector> +#include <boost/algorithm/string.hpp> +#include <openssl/x509.h> +#include <openssl/ssl.h> +#include <openssl/asn1.h> +#include "certificates.h" +#include "exceptions.h" + +using std::list; +using std::string; +using std::stringstream; +using std::vector; +using boost::shared_ptr; +using namespace libdcp; + +/** @param c X509 certificate, which this object will take ownership of */ +Certificate::Certificate (X509* c) + : _certificate (c) +{ + +} + +Certificate::~Certificate () +{ + X509_free (_certificate); +} + +string +Certificate::issuer () const +{ + X509_NAME* n = X509_get_issuer_name (_certificate); + assert (n); + + char b[256]; + X509_NAME_oneline (n, b, 256); + return b; +} + +string +Certificate::name_for_xml (string const & n) +{ + stringstream x; + + vector<string> p; + boost::split (p, n, boost::is_any_of ("/")); + for (vector<string>::const_reverse_iterator i = p.rbegin(); i != p.rend(); ++i) { + x << *i << ","; + } + + return x.str().substr(0, x.str().length() - 2); +} + +string +Certificate::subject () const +{ + X509_NAME* n = X509_get_subject_name (_certificate); + assert (n); + + char b[256]; + X509_NAME_oneline (n, b, 256); + return b; +} + +string +Certificate::serial () const +{ + ASN1_INTEGER* s = X509_get_serialNumber (_certificate); + assert (s); + + BIGNUM* b = ASN1_INTEGER_to_BN (s, 0); + char* c = BN_bn2dec (b); + BN_free (b); + + string st (c); + OPENSSL_free (c); + + return st; +} + + +/** @param filename Text file of PEM-format certificates, + * in the order: + * + * 1. self-signed root certificate + * 2. intermediate certificate signed by root certificate + * ... + * n. leaf certificate signed by previous intermediate. + */ + +CertificateChain::CertificateChain (string const & filename) +{ + FILE* f = fopen (filename.c_str(), "r"); + if (!f) { + throw FileError ("could not open file", filename); + } + + while (1) { + X509* c = 0; + if (!PEM_read_X509 (f, &c, 0, 0)) { + break; + } + + _certificates.push_back (shared_ptr<Certificate> (new Certificate (c))); + } +} + +shared_ptr<Certificate> +CertificateChain::root () const +{ + assert (!_certificates.empty()); + return _certificates.front (); +} + +shared_ptr<Certificate> +CertificateChain::leaf () const +{ + assert (_certificates.size() >= 2); + return _certificates.back (); +} diff --git a/src/certificates.h b/src/certificates.h new file mode 100644 index 00000000..6baea84a --- /dev/null +++ b/src/certificates.h @@ -0,0 +1,46 @@ +#ifndef LIBDCP_CERTIFICATES_H +#define LIBDCP_CERTIFICATES_H + +#include <string> +#include <list> +#include <boost/noncopyable.hpp> +#include <boost/shared_ptr.hpp> +#include <openssl/x509.h> + +class certificates; + +namespace libdcp { + +class Certificate : public boost::noncopyable +{ +public: + Certificate (X509 *); + ~Certificate (); + + std::string issuer () const; + std::string serial () const; + std::string subject () const; + + static std::string name_for_xml (std::string const &); + +private: + X509* _certificate; +}; + +class CertificateChain +{ +public: + CertificateChain () {} + CertificateChain (std::string const &); + + boost::shared_ptr<Certificate> root () const; + boost::shared_ptr<Certificate> leaf () const; + +private: + friend class ::certificates; + std::list<boost::shared_ptr<Certificate> > _certificates; +}; + +} + +#endif @@ -51,6 +51,7 @@ using namespace libdcp; DCP::DCP (string directory) : _directory (directory) + , _encrypted (false) { boost::filesystem::create_directories (directory); } @@ -59,7 +60,7 @@ void DCP::write_xml () const { for (list<shared_ptr<const CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) { - (*i)->write_xml (); + (*i)->write_xml (_encrypted, _certificates); } string pkl_uuid = make_uuid (); @@ -423,7 +424,7 @@ CPL::add_reel (shared_ptr<const Reel> reel) } void -CPL::write_xml () const +CPL::write_xml (bool encrypted, CertificateChain const & certificates) const { boost::filesystem::path p; p /= _directory; @@ -453,8 +454,19 @@ CPL::write_xml () const os << " </AssetList>\n" << " </Reel>\n" - << " </ReelList>\n" - << "</CompositionPlaylist>\n"; + << " </ReelList>\n"; + + if (encrypted) { + os << " <dsig:X509Data>\n" + << " <dsig:X509IssuerSerial>\n" + << " <dsig:X509IssuerName>" << Certificate::name_for_xml (certificates.leaf()->issuer()) << "</dsig:IssuerName>\n" + << " <dsig:X509SerialNumber>" << certificates.leaf()->serial() << "</dsig:X509SerialNumber>\n" + << " <dsig:X509IssuerSerial>\n" + << " <dsig:X509SubjectName>" << Certificate::name_for_xml (certificates.leaf()->subject()) << "</dsig:X509SubjectName>\n" + << " </dsig:X509Data>\n"; + } + + os << "</CompositionPlaylist>\n"; os.close (); @@ -29,6 +29,7 @@ #include <boost/shared_ptr.hpp> #include <boost/signals2.hpp> #include "types.h" +#include "certificates.h" namespace xmlpp { class Node; @@ -85,7 +86,7 @@ public: bool equals (CPL const & other, EqualityOptions options, std::list<std::string>& notes) const; - void write_xml () const; + void write_xml (bool, CertificateChain const &) const; void write_to_assetmap (std::ostream& s) const; void write_to_pkl (std::ostream& s) const; @@ -182,6 +183,9 @@ private: /** the directory that we are writing to */ std::string _directory; std::list<boost::shared_ptr<const CPL> > _cpls; + + bool _encrypted; + CertificateChain _certificates; }; } diff --git a/src/dcp_time.h b/src/dcp_time.h index 8033348b..eff69579 100644 --- a/src/dcp_time.h +++ b/src/dcp_time.h @@ -56,6 +56,9 @@ public: std::string to_string () const; int64_t to_ticks () const; + +private: + void set (double); }; extern bool operator== (Time const & a, Time const & b); diff --git a/src/wscript b/src/wscript index 04656976..56a99063 100644 --- a/src/wscript +++ b/src/wscript @@ -12,6 +12,7 @@ def build(bld): obj.source = """ asset.cc asset_map.cc + certificates.cc cpl_file.cc dcp.cc dcp_time.cc |
