From: Carl Hetherington Date: Sun, 31 Mar 2019 23:31:22 +0000 (+0100) Subject: Complain on startup if signer or decryption chains are inconsistent (#1520). X-Git-Tag: v2.15.1~30 X-Git-Url: https://git.carlh.net/gitweb/?p=dcpomatic.git;a=commitdiff_plain;h=a7ccdd22a980d1b18ecf4477a912bab7510be14a Complain on startup if signer or decryption chains are inconsistent (#1520). --- diff --git a/src/lib/config.cc b/src/lib/config.cc index 4ce4517f8..ea2a57939 100644 --- a/src/lib/config.cc +++ b/src/lib/config.cc @@ -69,7 +69,7 @@ Config* Config::_instance = 0; int const Config::_current_version = 3; boost::signals2::signal Config::FailedToLoad; boost::signals2::signal Config::Warning; -boost::signals2::signal Config::BadSignerChain; +boost::signals2::signal Config::Bad; /** Construct default configuration */ Config::Config () @@ -441,30 +441,6 @@ try } #endif - /* These must be done before we call BadSignerChain as that might set one - of the nags. - */ - BOOST_FOREACH (cxml::NodePtr i, f.node_children("Nagged")) { - int const id = i->number_attribute("Id"); - if (id >= 0 && id < NAG_COUNT) { - _nagged[id] = raw_convert(i->content()); - } - } - - bool bad_signer_chain = false; - BOOST_FOREACH (dcp::Certificate const & i, _signer_chain->unordered()) { - if (i.has_utf8_strings()) { - bad_signer_chain = true; - } - } - - if (bad_signer_chain) { - optional const remake = BadSignerChain(); - if (remake && *remake) { - _signer_chain = create_certificate_chain (); - } - } - cxml::NodePtr decryption = f.optional_node_child ("Decryption"); #ifdef DCPOMATIC_VARIANT_SWAROOP if (decryption && decryption->node_children().size() == 1) { @@ -492,6 +468,48 @@ try _decryption_chain = create_certificate_chain (); } #endif + + /* These must be done before we call Bad as that might set one + of the nags. + */ + BOOST_FOREACH (cxml::NodePtr i, f.node_children("Nagged")) { + int const id = i->number_attribute("Id"); + if (id >= 0 && id < NAG_COUNT) { + _nagged[id] = raw_convert(i->content()); + } + } + + optional bad; + + BOOST_FOREACH (dcp::Certificate const & i, _signer_chain->unordered()) { + if (i.has_utf8_strings()) { + bad = BAD_SIGNER_UTF8_STRINGS; + } + } + + if (!_signer_chain->private_key_valid() || !_signer_chain->chain_valid()) { + bad = BAD_SIGNER_INCONSISTENT; + } + + if (!_decryption_chain->private_key_valid() || !_decryption_chain->chain_valid()) { + bad = BAD_DECRYPTION_INCONSISTENT; + } + + if (bad) { + optional const remake = Bad(*bad); + if (remake && *remake) { + switch (*bad) { + case BAD_SIGNER_UTF8_STRINGS: + case BAD_SIGNER_INCONSISTENT: + _signer_chain = create_certificate_chain (); + break; + case BAD_DECRYPTION_INCONSISTENT: + _decryption_chain = create_certificate_chain (); + break; + } + } + } + if (f.optional_node_child("DKDMGroup")) { /* New-style: all DKDMs in a group */ _dkdms = dynamic_pointer_cast (DKDMBase::read (f.node_child("DKDMGroup"))); diff --git a/src/lib/config.h b/src/lib/config.h index 1d0501ce4..a8427663d 100644 --- a/src/lib/config.h +++ b/src/lib/config.h @@ -1072,10 +1072,16 @@ public: static boost::signals2::signal FailedToLoad; /** Emitted if read() issued a warning which the user might want to know about */ static boost::signals2::signal Warning; - /** Emitted if there is a bad certificate in the signer chain. Handler can call - * true to ask Config to re-create the chain. + /** Emitted if there is a something wrong the contents of our config. Handler can call + * true to ask Config to solve the problem (by discarding and recreating the bad thing) */ - static boost::signals2::signal BadSignerChain; + enum BadReason { + BAD_SIGNER_UTF8_STRINGS, ///< signer chain contains UTF-8 strings (not PRINTABLESTRING) + BAD_SIGNER_INCONSISTENT, ///< signer chain is somehow inconsistent + BAD_DECRYPTION_INCONSISTENT, ///< KDM decryption chain is somehow inconsistent + }; + + static boost::signals2::signal Bad; void write () const; void write_config () const; diff --git a/src/tools/dcpomatic.cc b/src/tools/dcpomatic.cc index 5bd22041e..7cac8e7f0 100644 --- a/src/tools/dcpomatic.cc +++ b/src/tools/dcpomatic.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2018 Carl Hetherington + Copyright (C) 2012-2019 Carl Hetherington This file is part of DCP-o-matic. @@ -1455,20 +1455,20 @@ public: App () : wxApp () , _frame (0) + , _splash (0) {} private: bool OnInit () { - wxSplashScreen* splash = 0; try { wxInitAllImageHandlers (); Config::FailedToLoad.connect (boost::bind (&App::config_failed_to_load, this)); Config::Warning.connect (boost::bind (&App::config_warning, this, _1)); - splash = maybe_show_splash (); + _splash = maybe_show_splash (); SetAppName (_("DCP-o-matic")); @@ -1506,14 +1506,14 @@ private: */ Config::drop (); - Config::BadSignerChain.connect (boost::bind (&App::config_bad_signer_chain, this)); + Config::Bad.connect (boost::bind(&App::config_bad, this, _1)); _frame = new DOMFrame (_("DCP-o-matic")); SetTopWindow (_frame); _frame->Maximize (); - if (splash) { - splash->Destroy (); - splash = 0; + if (_splash) { + _splash->Destroy (); + _splash = 0; } if (!Config::instance()->nagged(Config::NAG_INITIAL_SETUP)) { @@ -1558,8 +1558,9 @@ private: } catch (exception& e) { - if (splash) { - splash->Destroy (); + if (_splash) { + _splash->Destroy (); + _splash = 0; } error_dialog (0, wxString::Format ("DCP-o-matic could not start."), std_to_wx(e.what())); } @@ -1659,19 +1660,73 @@ private: message_dialog (_frame, std_to_wx (m)); } - bool config_bad_signer_chain () + bool config_bad (Config::BadReason reason) { - if (Config::instance()->nagged(Config::NAG_BAD_SIGNER_CHAIN)) { - return false; - } + /* Destroy the splash screen here, as otherwise bad things seem to happen (for reasons unknown) + when we open our recreate dialog, close it, *then* try to Destroy the splash (the Destroy fails). + */ + _splash->Destroy (); + _splash = 0; - RecreateChainDialog* d = new RecreateChainDialog (_frame); - int const r = d->ShowModal (); - d->Destroy (); - return r == wxID_OK; + Config* config = Config::instance(); + switch (reason) { + case Config::BAD_SIGNER_UTF8_STRINGS: + { + if (config->nagged(Config::NAG_BAD_SIGNER_CHAIN)) { + return false; + } + RecreateChainDialog* d = new RecreateChainDialog ( + _frame, _("Recreate signing certificates"), + _("The certificate chain that DCP-o-matic uses for signing DCPs and KDMs contains a small error\n" + "which will prevent DCPs from being validated correctly on some systems. Do you want to re-create\n" + "the certificate chain for signing DCPs and KDMs?"), + _("Do nothing"), + Config::NAG_BAD_SIGNER_CHAIN + ); + int const r = d->ShowModal (); + d->Destroy (); + return r == wxID_OK; + } + case Config::BAD_SIGNER_INCONSISTENT: + { + RecreateChainDialog* d = new RecreateChainDialog ( + _frame, _("Recreate signing certificates"), + _("The certificate chain that DCP-o-matic uses for signing DCPs and KDMs is inconsistent and\n" + "cannot be used. DCP-o-matic cannot start unless you re-create it. Do you want to re-create\n" + "the certificate chain for signing DCPs and KDMs?"), + _("Close DCP-o-matic") + ); + int const r = d->ShowModal (); + d->Destroy (); + if (r != wxID_OK) { + exit (EXIT_FAILURE); + } + return true; + } + case Config::BAD_DECRYPTION_INCONSISTENT: + { + RecreateChainDialog* d = new RecreateChainDialog ( + _frame, _("Recreate KDM decryption chain"), + _("The certificate chain that DCP-o-matic uses for decrypting KDMs is inconsistent and\n" + "cannot be used. DCP-o-matic cannot start unless you re-create it. Do you want to re-create\n" + "the certificate chain for decrypting KDMs? You may want to say \"No\" here and back up your\n" + "configuration before continuing."), + _("Close DCP-o-matic") + ); + int const r = d->ShowModal (); + d->Destroy (); + if (r != wxID_OK) { + exit (EXIT_FAILURE); + } + return true; + } + default: + DCPOMATIC_ASSERT (false); + } } DOMFrame* _frame; + wxSplashScreen* _splash; shared_ptr _timer; string _film_to_load; string _film_to_create; diff --git a/src/wx/recreate_chain_dialog.cc b/src/wx/recreate_chain_dialog.cc index 1dd14e0c8..e477cdc1f 100644 --- a/src/wx/recreate_chain_dialog.cc +++ b/src/wx/recreate_chain_dialog.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2018 Carl Hetherington + Copyright (C) 2018-2019 Carl Hetherington This file is part of DCP-o-matic. @@ -28,20 +28,19 @@ using std::list; using std::string; +using boost::optional; -RecreateChainDialog::RecreateChainDialog (wxWindow* parent) - : QuestionDialog (parent, _("Certificate chain"), _("Recreate signing certificates"), _("Do nothing")) +RecreateChainDialog::RecreateChainDialog (wxWindow* parent, wxString title, wxString message, wxString cancel, optional nag) + : QuestionDialog (parent, _("Certificate chain"), title, cancel) + , _nag (nag) { - wxString const message = _("The certificate chain that DCP-o-matic uses for signing DCPs and KDMs contains a small error\n" - "which will prevent DCPs from being validated correctly on some systems. Do you want to re-create\n" - "the certificate chain for signing DCPs and KDMs?"); - _sizer->Add (new StaticText (this, message), 1, wxEXPAND | wxALL, DCPOMATIC_DIALOG_BORDER); - wxCheckBox* shut_up = new CheckBox (this, _("Don't ask this again")); - _sizer->Add (shut_up, 0, wxALL, DCPOMATIC_DIALOG_BORDER); - - shut_up->Bind (wxEVT_CHECKBOX, bind (&RecreateChainDialog::shut_up, this, _1)); + if (nag) { + wxCheckBox* shut_up = new CheckBox (this, _("Don't ask this again")); + _sizer->Add (shut_up, 0, wxALL, DCPOMATIC_DIALOG_BORDER); + shut_up->Bind (wxEVT_CHECKBOX, bind (&RecreateChainDialog::shut_up, this, _1)); + } layout (); } @@ -49,5 +48,5 @@ RecreateChainDialog::RecreateChainDialog (wxWindow* parent) void RecreateChainDialog::shut_up (wxCommandEvent& ev) { - Config::instance()->set_nagged (Config::NAG_BAD_SIGNER_CHAIN, ev.IsChecked()); + Config::instance()->set_nagged(*_nag, ev.IsChecked()); } diff --git a/src/wx/recreate_chain_dialog.h b/src/wx/recreate_chain_dialog.h index 287e65767..10086be86 100644 --- a/src/wx/recreate_chain_dialog.h +++ b/src/wx/recreate_chain_dialog.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2018 Carl Hetherington + Copyright (C) 2018-2019 Carl Hetherington This file is part of DCP-o-matic. @@ -19,14 +19,16 @@ */ #include "question_dialog.h" +#include "lib/config.h" #include #include class RecreateChainDialog : public QuestionDialog { public: - RecreateChainDialog (wxWindow* parent); + RecreateChainDialog (wxWindow* parent, wxString title, wxString message, wxString cancel, boost::optional nag = boost::optional()); private: void shut_up (wxCommandEvent& ev); + boost::optional _nag; };