Allow config of the full KDM decryption chain.
authorCarl Hetherington <cth@carlh.net>
Thu, 30 Jul 2015 16:00:48 +0000 (17:00 +0100)
committerCarl Hetherington <cth@carlh.net>
Thu, 30 Jul 2015 16:00:48 +0000 (17:00 +0100)
ChangeLog
src/lib/config.cc
src/lib/config.h
src/lib/dcp_decoder.cc
src/lib/dcp_examiner.cc
src/wx/config_dialog.cc
src/wx/make_signer_chain_dialog.cc [deleted file]
src/wx/make_signer_chain_dialog.h [deleted file]
src/wx/wscript
test/import_dcp_test.cc

index 029a60cb824cdb100e0716658b6abca4d629c96f..6c01b76ddccb8510cc2c722019bbc0ed3e8f7963 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2015-07-30  c.hetherington  <cth@carlh.net>
+
+       * Allow recreation of the certificate chain and key
+       used for KDM decryption (#644).
+
 2015-07-29  Carl Hetherington  <cth@carlh.net>
 
        * Version 2.1.31 released.
index 7e3de966b4bfc79a40cc3d64508c74a47fbe2c27..d99cd5fcbff55edee61f31c61822eaaf515a71cb 100644 (file)
@@ -35,6 +35,7 @@
 #include <glib.h>
 #include <boost/filesystem.hpp>
 #include <boost/algorithm/string.hpp>
+#include <boost/foreach.hpp>
 #include <cstdlib>
 #include <fstream>
 
@@ -121,8 +122,8 @@ Config::read ()
        if (!boost::filesystem::exists (file ())) {
                /* Make a new set of signing certificates and key */
                _signer_chain.reset (new dcp::CertificateChain (openssl_path ()));
-               /* And decryption keys */
-               make_decryption_keys ();
+               /* And similar for decryption of KDMs */
+               _decryption_chain.reset (new dcp::CertificateChain (openssl_path ()));
                return;
        }
 
@@ -236,9 +237,8 @@ Config::read ()
        if (signer) {
                shared_ptr<dcp::CertificateChain> c (new dcp::CertificateChain ());
                /* Read the signing certificates and private key in from the config file */
-               list<cxml::NodePtr> certificates = signer->node_children ("Certificate");
-               for (list<cxml::NodePtr>::const_iterator i = certificates.begin(); i != certificates.end(); ++i) {
-                       c->add (dcp::Certificate ((*i)->content ()));
+               BOOST_FOREACH (cxml::NodePtr i, signer->node_children ("Certificate")) {
+                       c->add (dcp::Certificate (i->content ()));
                }
                c->set_key (signer->string_child ("PrivateKey"));
                _signer_chain = c;
@@ -247,28 +247,19 @@ Config::read ()
                _signer_chain.reset (new dcp::CertificateChain (openssl_path ()));
        }
 
-       if (f.optional_string_child ("DecryptionCertificate")) {
-               _decryption_certificate = dcp::Certificate (f.string_child ("DecryptionCertificate"));
-       }
-
-       if (f.optional_string_child ("DecryptionPrivateKey")) {
-               _decryption_private_key = f.string_child ("DecryptionPrivateKey");
-       }
-
-       if (!f.optional_string_child ("DecryptionCertificate") || !f.optional_string_child ("DecryptionPrivateKey")) {
-               /* Generate our own decryption certificate and key if either is not present in config */
-               make_decryption_keys ();
+       cxml::NodePtr decryption = f.optional_node_child ("Decryption");
+       if (decryption) {
+               shared_ptr<dcp::CertificateChain> c (new dcp::CertificateChain ());
+               BOOST_FOREACH (cxml::NodePtr i, decryption->node_children ("Certificate")) {
+                       c->add (dcp::Certificate (i->content ()));
+               }
+               c->set_key (signer->string_child ("PrivateKey"));
+               _decryption_chain = c;
+       } else {
+               _decryption_chain.reset (new dcp::CertificateChain (openssl_path ()));
        }
 }
 
-void
-Config::make_decryption_keys ()
-{
-       dcp::CertificateChain c (openssl_path ());
-       _decryption_certificate = c.leaf ();
-       _decryption_private_key = c.key().get ();
-}
-
 /** @return Filename to write configuration to */
 boost::filesystem::path
 Config::file () const
@@ -378,14 +369,16 @@ Config::write () const
 #endif
 
        xmlpp::Element* signer = root->add_child ("Signer");
-       dcp::CertificateChain::List certs = _signer_chain->root_to_leaf ();
-       for (dcp::CertificateChain::List::const_iterator i = certs.begin(); i != certs.end(); ++i) {
-               signer->add_child("Certificate")->add_child_text (i->certificate (true));
+       BOOST_FOREACH (dcp::Certificate const & i, _signer_chain->root_to_leaf ()) {
+               signer->add_child("Certificate")->add_child_text (i.certificate (true));
        }
        signer->add_child("PrivateKey")->add_child_text (_signer_chain->key().get ());
 
-       root->add_child("DecryptionCertificate")->add_child_text (_decryption_certificate.certificate (true));
-       root->add_child("DecryptionPrivateKey")->add_child_text (_decryption_private_key);
+       xmlpp::Element* decryption = root->add_child ("Decryption");
+       BOOST_FOREACH (dcp::Certificate const & i, _decryption_chain->root_to_leaf ()) {
+               decryption->add_child("Certificate")->add_child_text (i.certificate (true));
+       }
+       decryption->add_child("PrivateKey")->add_child_text (_decryption_chain->key().get ());
 
        for (vector<boost::filesystem::path>::const_iterator i = _history.begin(); i != _history.end(); ++i) {
                root->add_child("History")->add_child_text (i->string ());
index 573d2b29277953a08161ed297b6e9216a3b07a58..eeb167d0d0c52b964c85fb9b8e17d9522dd3d344 100644 (file)
@@ -203,12 +203,8 @@ public:
                return _signer_chain;
        }
 
-       dcp::Certificate decryption_certificate () const {
-               return _decryption_certificate;
-       }
-
-       std::string decryption_private_key () const {
-               return _decryption_private_key;
+       boost::shared_ptr<const dcp::CertificateChain> decryption_chain () const {
+               return _decryption_chain;
        }
 
        bool check_for_updates () const {
@@ -380,12 +376,8 @@ public:
                maybe_set (_signer_chain, s);
        }
 
-       void set_decryption_certificate (dcp::Certificate c) {
-               maybe_set (_decryption_certificate, c);
-       }
-
-       void set_decryption_private_key (std::string k) {
-               maybe_set (_decryption_private_key, k);
+       void set_decryption_chain (boost::shared_ptr<const dcp::CertificateChain> c) {
+               maybe_set (_decryption_chain, c);
        }
 
        void set_check_for_updates (bool c) {
@@ -430,7 +422,6 @@ private:
        Config ();
        boost::filesystem::path file () const;
        void read ();
-       void make_decryption_keys ();
        void set_defaults ();
        void set_kdm_email_to_default ();
 
@@ -490,8 +481,10 @@ private:
        std::string _kdm_bcc;
        std::string _kdm_email;
        boost::shared_ptr<const dcp::CertificateChain> _signer_chain;
-       dcp::Certificate _decryption_certificate;
-       std::string _decryption_private_key;
+       /** Chain used to decrypt KDMs; the leaf of this chain is the target
+        *  certificate for making KDMs given to DCP-o-matic.
+        */
+       boost::shared_ptr<const dcp::CertificateChain> _decryption_chain;
        /** true to check for updates on startup */
        bool _check_for_updates;
        bool _check_for_test_updates;
index 053ff4f68b1198d33d760ffd55d25860e5f852c6..9cd327a525ff1f0cd56c457bea9a9c5df8ea5db1 100644 (file)
@@ -49,7 +49,7 @@ DCPDecoder::DCPDecoder (shared_ptr<const DCPContent> c)
        dcp::DCP dcp (c->directory ());
        dcp.read ();
        if (c->kdm ()) {
-               dcp.add (dcp::DecryptedKDM (c->kdm().get (), Config::instance()->decryption_private_key ()));
+               dcp.add (dcp::DecryptedKDM (c->kdm().get (), Config::instance()->decryption_chain()->key().get ()));
        }
        DCPOMATIC_ASSERT (dcp.cpls().size() == 1);
        _reels = dcp.cpls().front()->reels ();
index 633e8e9d77a56409c89b7e41f3bfc172c8f12792..5da4a50023cad0d6f5b6138376115f889fa39e34 100644 (file)
@@ -51,7 +51,7 @@ DCPExaminer::DCPExaminer (shared_ptr<const DCPContent> content)
        dcp.read ();
 
        if (content->kdm ()) {
-               dcp.add (dcp::DecryptedKDM (content->kdm().get(), Config::instance()->decryption_private_key ()));
+               dcp.add (dcp::DecryptedKDM (content->kdm().get(), Config::instance()->decryption_chain()->key().get ()));
        }
 
        if (dcp.cpls().size() == 0) {
index da6a94bbe17b458bff2c8c89f6d7b9a07c8a080e..652f8dacb79e6dabb235e63bf3784e4b43a98a6d 100644 (file)
@@ -28,7 +28,7 @@
 #include "dir_picker_ctrl.h"
 #include "isdcf_metadata_dialog.h"
 #include "server_dialog.h"
-#include "make_signer_chain_dialog.h"
+#include "make_chain_dialog.h"
 #include "lib/config.h"
 #include "lib/ratio.h"
 #include "lib/filter.h"
@@ -46,6 +46,7 @@
 #include <wx/spinctrl.h>
 #include <boost/lexical_cast.hpp>
 #include <boost/filesystem.hpp>
+#include <boost/foreach.hpp>
 #include <iostream>
 
 using std::vector;
@@ -55,6 +56,7 @@ using std::cout;
 using boost::bind;
 using boost::shared_ptr;
 using boost::lexical_cast;
+using boost::function;
 
 class Page
 {
@@ -555,41 +557,35 @@ private:
        EditableList<string, ServerDialog>* _servers_list;
 };
 
-class KeysPage : public StandardPage
+class CertificateChainEditor : public wxPanel
 {
 public:
-       KeysPage (wxSize panel_size, int border)
-               : StandardPage (panel_size, border)
-       {}
-
-       wxString GetName () const
-       {
-               return _("Keys");
-       }
-
-#ifdef DCPOMATIC_OSX
-       wxBitmap GetLargeIcon () const
-       {
-               return wxBitmap ("keys", wxBITMAP_TYPE_PNG_RESOURCE);
-       }
-#endif
-
-private:
-       void setup ()
+       CertificateChainEditor (
+               wxWindow* parent,
+               wxString title,
+               int border,
+               function<void (shared_ptr<dcp::CertificateChain>)> set,
+               function<shared_ptr<const dcp::CertificateChain> (void)> get
+               )
+               : wxPanel (parent)
+               , _set (set)
+               , _get (get)
        {
                wxFont subheading_font (*wxNORMAL_FONT);
                subheading_font.SetWeight (wxFONTWEIGHT_BOLD);
 
+               wxSizer* sizer = new wxBoxSizer (wxVERTICAL);
+
                {
-                       wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Signing DCPs and KDMs"));
+                       wxStaticText* m = new wxStaticText (this, wxID_ANY, title);
                        m->SetFont (subheading_font);
-                       _panel->GetSizer()->Add (m, 0, wxALL, _border);
+                       sizer->Add (m, 0, wxALL, border);
                }
 
                wxBoxSizer* certificates_sizer = new wxBoxSizer (wxHORIZONTAL);
-               _panel->GetSizer()->Add (certificates_sizer, 0, wxLEFT | wxRIGHT, _border);
+               sizer->Add (certificates_sizer, 0, wxLEFT | wxRIGHT, border);
 
-               _certificates = new wxListCtrl (_panel, wxID_ANY, wxDefaultPosition, wxSize (400, 200), wxLC_REPORT | wxLC_SINGLE_SEL);
+               _certificates = new wxListCtrl (this, wxID_ANY, wxDefaultPosition, wxSize (400, 200), wxLC_REPORT | wxLC_SINGLE_SEL);
 
                {
                        wxListItem ip;
@@ -616,93 +612,70 @@ private:
 
                {
                        wxSizer* s = new wxBoxSizer (wxVERTICAL);
-                       _add_certificate = new wxButton (_panel, wxID_ANY, _("Add..."));
+                       _add_certificate = new wxButton (this, wxID_ANY, _("Add..."));
                        s->Add (_add_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
-                       _remove_certificate = new wxButton (_panel, wxID_ANY, _("Remove"));
+                       _remove_certificate = new wxButton (this, wxID_ANY, _("Remove"));
                        s->Add (_remove_certificate, 0, wxTOP | wxBOTTOM, DCPOMATIC_BUTTON_STACK_GAP);
                        certificates_sizer->Add (s, 0, wxLEFT, DCPOMATIC_SIZER_X_GAP);
                }
 
                wxGridBagSizer* table = new wxGridBagSizer (DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP);
-               _panel->GetSizer()->Add (table, 1, wxALL | wxEXPAND, _border);
-
+               sizer->Add (table, 1, wxALL | wxEXPAND, border);
                int r = 0;
 
-               add_label_to_grid_bag_sizer (table, _panel, _("Leaf private key"), true, wxGBPosition (r, 0));
-               _signer_private_key = new wxStaticText (_panel, wxID_ANY, wxT (""));
-               wxFont font = _signer_private_key->GetFont ();
+               add_label_to_grid_bag_sizer (table, this, _("Leaf private key"), true, wxGBPosition (r, 0));
+               _private_key = new wxStaticText (this, wxID_ANY, wxT (""));
+               wxFont font = _private_key->GetFont ();
                font.SetFamily (wxFONTFAMILY_TELETYPE);
-               _signer_private_key->SetFont (font);
-               table->Add (_signer_private_key, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
-               _load_signer_private_key = new wxButton (_panel, wxID_ANY, _("Load..."));
-               table->Add (_load_signer_private_key, wxGBPosition (r, 2));
+               _private_key->SetFont (font);
+               table->Add (_private_key, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
+               _load_private_key = new wxButton (this, wxID_ANY, _("Load..."));
+               table->Add (_load_private_key, wxGBPosition (r, 2));
                ++r;
 
-               _remake_certificates = new wxButton (_panel, wxID_ANY, _("Re-make certificates and key..."));
-               table->Add (_remake_certificates, wxGBPosition (r, 0), wxGBSpan (1, 3));
+               _button_sizer = new wxBoxSizer (wxHORIZONTAL);
+               _remake_certificates = new wxButton (this, wxID_ANY, _("Re-make certificates and key..."));
+               _button_sizer->Add (_remake_certificates, 1, wxRIGHT, border);
+               table->Add (_button_sizer, wxGBPosition (r, 0), wxGBSpan (1, 3));
                ++r;
 
-               {
-                       wxStaticText* m = new wxStaticText (_panel, wxID_ANY, _("Decrypting DCPs"));
-                       m->SetFont (subheading_font);
-                       table->Add (m, wxGBPosition (r, 0), wxGBSpan (1, 3), wxTOP, _border * 1.5);
-                       ++r;
-               }
+               _add_certificate->Bind     (wxEVT_COMMAND_BUTTON_CLICKED,       boost::bind (&CertificateChainEditor::add_certificate, this));
+               _remove_certificate->Bind  (wxEVT_COMMAND_BUTTON_CLICKED,       boost::bind (&CertificateChainEditor::remove_certificate, this));
+               _certificates->Bind        (wxEVT_COMMAND_LIST_ITEM_SELECTED,   boost::bind (&CertificateChainEditor::update_sensitivity, this));
+               _certificates->Bind        (wxEVT_COMMAND_LIST_ITEM_DESELECTED, boost::bind (&CertificateChainEditor::update_sensitivity, this));
+               _remake_certificates->Bind (wxEVT_COMMAND_BUTTON_CLICKED,       boost::bind (&CertificateChainEditor::remake_certificates, this));
+               _load_private_key->Bind    (wxEVT_COMMAND_BUTTON_CLICKED,       boost::bind (&CertificateChainEditor::load_private_key, this));
 
-               add_label_to_grid_bag_sizer (table, _panel, _("Certificate"), true, wxGBPosition (r, 0));
-               _decryption_certificate = new wxStaticText (_panel, wxID_ANY, wxT (""));
-               _decryption_certificate->SetFont (font);
-               table->Add (_decryption_certificate, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
-               _load_decryption_certificate = new wxButton (_panel, wxID_ANY, _("Load..."));
-               table->Add (_load_decryption_certificate, wxGBPosition (r, 2));
-               ++r;
-
-               add_label_to_grid_bag_sizer (table, _panel, _("Private key"), true, wxGBPosition (r, 0));
-               _decryption_private_key = new wxStaticText (_panel, wxID_ANY, wxT (""));
-               _decryption_private_key->SetFont (font);
-               table->Add (_decryption_private_key, wxGBPosition (r, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
-               _load_decryption_private_key = new wxButton (_panel, wxID_ANY, _("Load..."));
-               table->Add (_load_decryption_private_key, wxGBPosition (r, 2));
-               ++r;
-
-               _export_decryption_certificate = new wxButton (_panel, wxID_ANY, _("Export DCP decryption certificate..."));
-               table->Add (_export_decryption_certificate, wxGBPosition (r, 0), wxGBSpan (1, 3));
-               ++r;
-
-               _add_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KeysPage::add_certificate, this));
-               _remove_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KeysPage::remove_certificate, this));
-               _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_SELECTED, boost::bind (&KeysPage::update_sensitivity, this));
-               _certificates->Bind (wxEVT_COMMAND_LIST_ITEM_DESELECTED, boost::bind (&KeysPage::update_sensitivity, this));
-               _remake_certificates->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KeysPage::remake_certificates, this));
-               _load_signer_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KeysPage::load_signer_private_key, this));
-               _load_decryption_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KeysPage::load_decryption_certificate, this));
-               _load_decryption_private_key->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KeysPage::load_decryption_private_key, this));
-               _export_decryption_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KeysPage::export_decryption_certificate, this));
+               SetSizerAndFit (sizer);
        }
 
        void config_changed ()
        {
-               _signer.reset (new dcp::CertificateChain (*Config::instance()->signer_chain().get ()));
+               _chain.reset (new dcp::CertificateChain (*_get().get ()));
 
                update_certificate_list ();
-               update_signer_private_key ();
-               update_decryption_certificate ();
-               update_decryption_private_key ();
+               update_private_key ();
                update_sensitivity ();
        }
 
+       void add_button (wxWindow* button)
+       {
+               _button_sizer->Add (button);
+       }
+
+private:
        void add_certificate ()
        {
-               wxFileDialog* d = new wxFileDialog (_panel, _("Select Certificate File"));
+               wxFileDialog* d = new wxFileDialog (this, _("Select Certificate File"));
 
                if (d->ShowModal() == wxID_OK) {
                        try {
                                dcp::Certificate c (dcp::file_to_string (wx_to_std (d->GetPath ())));
-                               _signer->add (c);
-                               Config::instance()->set_signer_chain (_signer);
+                               _chain->add (c);
+                               _set (_chain);
                                update_certificate_list ();
                        } catch (dcp::MiscError& e) {
-                               error_dialog (_panel, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
+                               error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
                        }
                }
 
@@ -719,8 +692,8 @@ private:
                }
 
                _certificates->DeleteItem (i);
-               _signer->remove (i);
-               Config::instance()->set_signer_chain (_signer);
+               _chain->remove (i);
+               _set (_chain);
 
                update_sensitivity ();
        }
@@ -728,13 +701,13 @@ private:
        void update_certificate_list ()
        {
                _certificates->DeleteAllItems ();
-               dcp::CertificateChain::List certs = _signer->root_to_leaf ();
                size_t n = 0;
-               for (dcp::CertificateChain::List::const_iterator i = certs.begin(); i != certs.end(); ++i) {
+               dcp::CertificateChain::List certs = _chain->root_to_leaf ();
+               BOOST_FOREACH (dcp::Certificate const & i, certs) {
                        wxListItem item;
                        item.SetId (n);
                        _certificates->InsertItem (item);
-                       _certificates->SetItem (n, 1, std_to_wx (i->thumbprint ()));
+                       _certificates->SetItem (n, 1, std_to_wx (i.thumbprint ()));
 
                        if (n == 0) {
                                _certificates->SetItem (n, 0, _("Root"));
@@ -750,7 +723,7 @@ private:
 
        void remake_certificates ()
        {
-               shared_ptr<const dcp::CertificateChain> chain = Config::instance()->signer_chain ();
+               shared_ptr<const dcp::CertificateChain> chain = _get ();
 
                string intermediate_common_name;
                if (chain->root_to_leaf().size() >= 3) {
@@ -760,8 +733,8 @@ private:
                        intermediate_common_name = i->subject_common_name ();
                }
 
-               MakeSignerChainDialog* d = new MakeSignerChainDialog (
-                       _panel,
+               MakeChainDialog* d = new MakeChainDialog (
+                       this,
                        chain->root().subject_organization_name (),
                        chain->root().subject_organizational_unit_name (),
                        chain->root().subject_common_name (),
@@ -770,7 +743,7 @@ private:
                        );
 
                if (d->ShowModal () == wxID_OK) {
-                       _signer.reset (
+                       _chain.reset (
                                new dcp::CertificateChain (
                                        openssl_path (),
                                        d->organisation (),
@@ -781,9 +754,9 @@ private:
                                        )
                                );
 
-                       Config::instance()->set_signer_chain (_signer);
+                       _set (_chain);
                        update_certificate_list ();
-                       update_signer_private_key ();
+                       update_private_key ();
                }
 
                d->Destroy ();
@@ -794,28 +767,28 @@ private:
                _remove_certificate->Enable (_certificates->GetNextItem (-1, wxLIST_NEXT_ALL, wxLIST_STATE_SELECTED) != -1);
        }
 
-       void update_signer_private_key ()
+       void update_private_key ()
        {
-               checked_set (_signer_private_key, dcp::private_key_fingerprint (_signer->key().get ()));
+               checked_set (_private_key, dcp::private_key_fingerprint (_chain->key().get ()));
        }
 
-       void load_signer_private_key ()
+       void load_private_key ()
        {
-               wxFileDialog* d = new wxFileDialog (_panel, _("Select Key File"));
+               wxFileDialog* d = new wxFileDialog (this, _("Select Key File"));
 
                if (d->ShowModal() == wxID_OK) {
                        try {
                                boost::filesystem::path p (wx_to_std (d->GetPath ()));
                                if (boost::filesystem::file_size (p) > 1024) {
-                                       error_dialog (_panel, wxString::Format (_("Could not read key file (%s)"), std_to_wx (p.string ())));
+                                       error_dialog (this, wxString::Format (_("Could not read key file (%s)"), std_to_wx (p.string ())));
                                        return;
                                }
 
-                               _signer->set_key (dcp::file_to_string (p));
-                               Config::instance()->set_signer_chain (_signer);
-                               update_signer_private_key ();
+                               _chain->set_key (dcp::file_to_string (p));
+                               _set (_chain);
+                               update_private_key ();
                        } catch (dcp::MiscError& e) {
-                               error_dialog (_panel, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
+                               error_dialog (this, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
                        }
                }
 
@@ -825,48 +798,61 @@ private:
 
        }
 
-       void load_decryption_certificate ()
-       {
-               wxFileDialog* d = new wxFileDialog (_panel, _("Select Certificate File"));
+       wxListCtrl* _certificates;
+       wxButton* _add_certificate;
+       wxButton* _remove_certificate;
+       wxButton* _remake_certificates;
+       wxStaticText* _private_key;
+       wxButton* _load_private_key;
+       wxBoxSizer* _button_sizer;
+       shared_ptr<dcp::CertificateChain> _chain;
+       boost::function<void (shared_ptr<dcp::CertificateChain>)> _set;
+       boost::function<shared_ptr<const dcp::CertificateChain> (void)> _get;
+};
 
-               if (d->ShowModal() == wxID_OK) {
-                       try {
-                               dcp::Certificate c (dcp::file_to_string (wx_to_std (d->GetPath ())));
-                               Config::instance()->set_decryption_certificate (c);
-                               update_decryption_certificate ();
-                       } catch (dcp::MiscError& e) {
-                               error_dialog (_panel, wxString::Format (_("Could not read certificate file (%s)"), e.what ()));
-                       }
-               }
+class KeysPage : public StandardPage
+{
+public:
+       KeysPage (wxSize panel_size, int border)
+               : StandardPage (panel_size, border)
+       {}
 
-               d->Destroy ();
+       wxString GetName () const
+       {
+               return _("Keys");
        }
 
-       void update_decryption_certificate ()
+#ifdef DCPOMATIC_OSX
+       wxBitmap GetLargeIcon () const
        {
-               checked_set (_decryption_certificate, Config::instance()->decryption_certificate().thumbprint ());
+               return wxBitmap ("keys", wxBITMAP_TYPE_PNG_RESOURCE);
        }
+#endif
 
-       void load_decryption_private_key ()
+private:
+
+       void setup ()
        {
-               wxFileDialog* d = new wxFileDialog (_panel, _("Select Key File"));
+               _signer = new CertificateChainEditor (
+                       _panel, _("Signing DCPs and KDMs"), _border,
+                       boost::bind (&Config::set_signer_chain, Config::instance (), _1),
+                       boost::bind (&Config::signer_chain, Config::instance ())
+                       );
 
-               if (d->ShowModal() == wxID_OK) {
-                       try {
-                               boost::filesystem::path p (wx_to_std (d->GetPath ()));
-                               Config::instance()->set_decryption_private_key (dcp::file_to_string (p));
-                               update_decryption_private_key ();
-                       } catch (dcp::MiscError& e) {
-                               error_dialog (_panel, wxString::Format (_("Could not read key file (%s)"), e.what ()));
-                       }
-               }
+               _panel->GetSizer()->Add (_signer);
 
-               d->Destroy ();
-       }
+               _decryption = new CertificateChainEditor (
+                       _panel, _("Decrypting DCPs"), _border,
+                       boost::bind (&Config::set_decryption_chain, Config::instance (), _1),
+                       boost::bind (&Config::decryption_chain, Config::instance ())
+                       );
 
-       void update_decryption_private_key ()
-       {
-               checked_set (_decryption_private_key, dcp::private_key_fingerprint (Config::instance()->decryption_private_key()));
+               _panel->GetSizer()->Add (_decryption);
+
+               _export_decryption_certificate = new wxButton (_decryption, wxID_ANY, _("Export DCP decryption certificate..."));
+               _decryption->add_button (_export_decryption_certificate);
+
+               _export_decryption_certificate->Bind (wxEVT_COMMAND_BUTTON_CLICKED, boost::bind (&KeysPage::export_decryption_certificate, this));
        }
 
        void export_decryption_certificate ()
@@ -882,25 +868,22 @@ private:
                                throw OpenFileError (wx_to_std (d->GetPath ()));
                        }
 
-                       string const s = Config::instance()->decryption_certificate().certificate (true);
+                       string const s = Config::instance()->decryption_chain()->leaf().certificate (true);
                        fwrite (s.c_str(), 1, s.length(), f);
                        fclose (f);
                }
                d->Destroy ();
        }
 
-       wxListCtrl* _certificates;
-       wxButton* _add_certificate;
-       wxButton* _remove_certificate;
-       wxButton* _remake_certificates;
-       wxStaticText* _signer_private_key;
-       wxButton* _load_signer_private_key;
-       wxStaticText* _decryption_certificate;
-       wxButton* _load_decryption_certificate;
-       wxStaticText* _decryption_private_key;
-       wxButton* _load_decryption_private_key;
+       void config_changed ()
+       {
+               _signer->config_changed ();
+               _decryption->config_changed ();
+       }
+
+       CertificateChainEditor* _signer;
+       CertificateChainEditor* _decryption;
        wxButton* _export_decryption_certificate;
-       shared_ptr<dcp::CertificateChain> _signer;
 };
 
 class TMSPage : public StandardPage
diff --git a/src/wx/make_signer_chain_dialog.cc b/src/wx/make_signer_chain_dialog.cc
deleted file mode 100644 (file)
index df8b198..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
-    Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "make_signer_chain_dialog.h"
-#include <boost/algorithm/string.hpp>
-
-using std::string;
-
-MakeSignerChainDialog::MakeSignerChainDialog (
-       wxWindow* parent,
-       string organisation,
-       string organisational_unit_name,
-       string root_common_name,
-       string intermediate_common_name,
-       string leaf_common_name
-       )
-       : TableDialog (parent, _("Make certificate chain"), 2, true)
-{
-       wxTextValidator validator (wxFILTER_EXCLUDE_CHAR_LIST);
-       validator.SetCharExcludes (wxT ("/"));
-
-       if (boost::algorithm::starts_with (root_common_name, ".")) {
-               root_common_name = root_common_name.substr (1);
-       }
-
-       if (boost::algorithm::starts_with (intermediate_common_name, ".")) {
-               intermediate_common_name = intermediate_common_name.substr (1);
-       }
-
-       if (boost::algorithm::starts_with (leaf_common_name, "CS.")) {
-               leaf_common_name = leaf_common_name.substr (3);
-       }
-
-       add (_("Organisation"), true);
-       add (_organisation = new wxTextCtrl (this, wxID_ANY, std_to_wx (organisation), wxDefaultPosition, wxDefaultSize, 0, validator));
-       add (_("Organisational unit"), true);
-       add (_organisational_unit = new wxTextCtrl (this, wxID_ANY, std_to_wx (organisational_unit_name), wxDefaultPosition, wxDefaultSize, 0, validator));
-
-       add (_("Root common name"), true);
-
-       {
-               wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
-               s->Add (new wxStaticText (this, wxID_ANY, wxT (".")), 0, wxALIGN_CENTER_VERTICAL);
-               s->Add (_root_common_name = new wxTextCtrl (
-                               this, wxID_ANY, std_to_wx (root_common_name), wxDefaultPosition, wxDefaultSize, 0, validator), 1, wxALIGN_CENTER_VERTICAL
-                       );
-               add (s);
-       }
-
-       add (_("Intermediate common name"), true);
-
-       {
-               wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
-               s->Add (new wxStaticText (this, wxID_ANY, wxT (".")), 0, wxALIGN_CENTER_VERTICAL);
-               s->Add (_intermediate_common_name = new wxTextCtrl (
-                               this, wxID_ANY, std_to_wx (intermediate_common_name), wxDefaultPosition, wxDefaultSize, 0, validator), 1, wxALIGN_CENTER_VERTICAL
-                       );
-               add (s);
-       }
-
-       add (_("Leaf common name"), true);
-
-       {
-               wxBoxSizer* s = new wxBoxSizer (wxHORIZONTAL);
-               s->Add (new wxStaticText (this, wxID_ANY, wxT ("CS.")), 0, wxALIGN_CENTER_VERTICAL);
-               s->Add (_leaf_common_name = new wxTextCtrl (
-                               this, wxID_ANY, std_to_wx (leaf_common_name), wxDefaultPosition, wxDefaultSize, 0, validator), 1, wxALIGN_CENTER_VERTICAL
-                       );
-               add (s);
-       }
-
-       layout ();
-
-       SetSize (640, -1);
-}
diff --git a/src/wx/make_signer_chain_dialog.h b/src/wx/make_signer_chain_dialog.h
deleted file mode 100644 (file)
index 0ebffeb..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
-    Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-*/
-
-#include "table_dialog.h"
-#include "wx_util.h"
-
-class MakeSignerChainDialog : public TableDialog
-{
-public:
-       MakeSignerChainDialog (
-               wxWindow* parent,
-               std::string organisation,
-               std::string organisational_unit_name,
-               std::string root_common_name,
-               std::string intermediate_common_name,
-               std::string leaf_common_name
-               );
-
-       std::string organisation () const {
-               return wx_to_std (_organisation->GetValue ());
-       }
-
-       std::string organisational_unit () const {
-               return wx_to_std (_organisational_unit->GetValue ());
-       }
-
-       std::string root_common_name () const {
-               return "." + wx_to_std (_root_common_name->GetValue ());
-       }
-
-       std::string intermediate_common_name () const {
-               return "." + wx_to_std (_intermediate_common_name->GetValue ());
-       }
-
-       std::string leaf_common_name () const {
-               return "CS." + wx_to_std (_leaf_common_name->GetValue ());
-       }
-
-
-private:
-       wxTextCtrl* _organisation;
-       wxTextCtrl* _organisational_unit;
-       wxTextCtrl* _root_common_name;
-       wxTextCtrl* _intermediate_common_name;
-       wxTextCtrl* _leaf_common_name;
-};
index 72c811732c061526f75b596bf4a64ee0a2c314ec..96a0c48693df3105ac63d64ba670c63a4b73216a 100644 (file)
@@ -55,7 +55,7 @@ sources = """
           job_manager_view.cc
           kdm_dialog.cc
           key_dialog.cc
-          make_signer_chain_dialog.cc
+          make_chain_dialog.cc
           new_film_dialog.cc
           preset_colour_conversion_dialog.cc
           repeat_dialog.cc
index 3f6f41b55af551a9a4c044282b59bb0b7e50fb37..84d02c0bfc8bb7005ef45275668eed449a1f89a1 100644 (file)
@@ -50,7 +50,7 @@ BOOST_AUTO_TEST_CASE (import_dcp_test)
        A_dcp.read ();
 
        dcp::EncryptedKDM kdm = A->make_kdm (
-               Config::instance()->decryption_certificate(),
+               Config::instance()->decryption_chain()->leaf (),
                A_dcp.cpls().front()->file (),
                dcp::LocalTime ("2014-07-21T00:00:00+00:00"),
                dcp::LocalTime ("2024-07-21T00:00:00+00:00"),