Check for signer chains containing UTF8-marked strings and offer
authorCarl Hetherington <cth@carlh.net>
Fri, 9 Mar 2018 00:55:49 +0000 (00:55 +0000)
committerCarl Hetherington <cth@carlh.net>
Fri, 9 Mar 2018 01:00:32 +0000 (01:00 +0000)
to fix them on startup (#1218).

src/lib/config.cc
src/lib/config.h
src/tools/dcpomatic.cc
src/wx/recreate_chain_dialog.cc [new file with mode: 0644]
src/wx/recreate_chain_dialog.h [new file with mode: 0644]
src/wx/wscript

index ec5b05a..2ae7939 100644 (file)
@@ -67,6 +67,7 @@ Config* Config::_instance = 0;
 int const Config::_current_version = 3;
 boost::signals2::signal<void ()> Config::FailedToLoad;
 boost::signals2::signal<void (string)> Config::Warning;
+boost::signals2::signal<bool (void)> Config::BadSignerChain;
 boost::optional<boost::filesystem::path> Config::test_path;
 
 /** Construct default configuration */
@@ -349,6 +350,30 @@ try
                _signer_chain = create_certificate_chain ();
        }
 
+       /* 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<int>("Id");
+               if (id >= 0 && id < NAG_COUNT) {
+                       _nagged[id] = raw_convert<int>(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<bool> const remake = BadSignerChain();
+               if (remake && *remake) {
+                       _signer_chain = create_certificate_chain ();
+               }
+       }
+
        cxml::NodePtr decryption = f.optional_node_child ("Decryption");
        if (decryption) {
                shared_ptr<dcp::CertificateChain> c (new dcp::CertificateChain ());
@@ -379,12 +404,6 @@ try
        _dcp_metadata_filename_format = dcp::NameFormat (f.optional_string_child("DCPMetadataFilenameFormat").get_value_or ("%t"));
        _dcp_asset_filename_format = dcp::NameFormat (f.optional_string_child("DCPAssetFilenameFormat").get_value_or ("%t"));
        _jump_to_selected = f.optional_bool_child("JumpToSelected").get_value_or (true);
-       BOOST_FOREACH (cxml::NodePtr i, f.node_children("Nagged")) {
-               int const id = i->number_attribute<int>("Id");
-               if (id >= 0 && id < NAG_COUNT) {
-                       _nagged[id] = raw_convert<int>(i->content());
-               }
-       }
        /* The variable was renamed but not the XML tag */
        _sound = f.optional_bool_child("PreviewSound").get_value_or (true);
        _sound_output = f.optional_string_child("PreviewSoundOutput");
index 90ebb0b..2fca969 100644 (file)
@@ -330,6 +330,7 @@ public:
                NAG_DKDM_CONFIG,
                NAG_ENCRYPTED_METADATA,
                NAG_REMAKE_DECRYPTION_CHAIN,
+               NAG_BAD_SIGNER_CHAIN,
                NAG_COUNT
        };
 
@@ -696,6 +697,10 @@ public:
        static boost::signals2::signal<void ()> FailedToLoad;
        /** Emitted if read() issued a warning which the user might want to know about */
        static boost::signals2::signal<void (std::string)> Warning;
+       /** Emitted if there is a bad certificate in the signer chain.  Handler can call
+        *  true to ask Config to re-create the chain.
+        */
+       static boost::signals2::signal<bool (void)> BadSignerChain;
 
        void write () const;
        void write_config () const;
index 7391dde..829cd47 100644 (file)
@@ -29,6 +29,7 @@
 #include "wx/wx_util.h"
 #include "wx/film_name_location_dialog.h"
 #include "wx/wx_signal_manager.h"
+#include "wx/recreate_chain_dialog.h"
 #include "wx/about_dialog.h"
 #include "wx/kdm_dialog.h"
 #include "wx/self_dkdm_dialog.h"
@@ -1279,6 +1280,8 @@ private:
                */
                Config::drop ();
 
+               Config::BadSignerChain.connect (boost::bind (&App::config_bad_signer_chain, this));
+
                _frame = new DOMFrame (_("DCP-o-matic"));
                SetTopWindow (_frame);
                _frame->Maximize ();
@@ -1418,6 +1421,18 @@ private:
                message_dialog (_frame, std_to_wx (m));
        }
 
+       bool config_bad_signer_chain ()
+       {
+               if (Config::instance()->nagged(Config::NAG_BAD_SIGNER_CHAIN)) {
+                       return false;
+               }
+
+               RecreateChainDialog* d = new RecreateChainDialog (_frame);
+               int const r = d->ShowModal ();
+               d->Destroy ();
+               return r == wxID_OK;
+       }
+
        DOMFrame* _frame;
        shared_ptr<wxTimer> _timer;
        string _film_to_load;
diff --git a/src/wx/recreate_chain_dialog.cc b/src/wx/recreate_chain_dialog.cc
new file mode 100644 (file)
index 0000000..b59e99d
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+    Copyright (C) 2018 Carl Hetherington <cth@carlh.net>
+
+    This file is part of DCP-o-matic.
+
+    DCP-o-matic 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.
+
+    DCP-o-matic 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 DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "recreate_chain_dialog.h"
+#include "wx_util.h"
+#include "lib/config.h"
+#include "lib/cinema_kdms.h"
+#include <boost/foreach.hpp>
+
+using std::list;
+using std::string;
+
+RecreateChainDialog::RecreateChainDialog (wxWindow* parent)
+       : QuestionDialog (parent, _("Certificate chain"), _("Recreate signing certificates"), _("Do nothing"))
+{
+       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 wxStaticText (this, wxID_ANY, message), 1, wxEXPAND | wxALL, DCPOMATIC_DIALOG_BORDER);
+
+       wxCheckBox* shut_up = new wxCheckBox (this, wxID_ANY, _("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 ();
+}
+
+void
+RecreateChainDialog::shut_up (wxCommandEvent& ev)
+{
+       std::cout << "set nagged " << ev.IsChecked() << "\n";
+       Config::instance()->set_nagged (Config::NAG_BAD_SIGNER_CHAIN, ev.IsChecked());
+}
diff --git a/src/wx/recreate_chain_dialog.h b/src/wx/recreate_chain_dialog.h
new file mode 100644 (file)
index 0000000..287e657
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+    Copyright (C) 2018 Carl Hetherington <cth@carlh.net>
+
+    This file is part of DCP-o-matic.
+
+    DCP-o-matic 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.
+
+    DCP-o-matic 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 DCP-o-matic.  If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "question_dialog.h"
+#include <wx/wx.h>
+#include <list>
+
+class RecreateChainDialog : public QuestionDialog
+{
+public:
+       RecreateChainDialog (wxWindow* parent);
+
+private:
+       void shut_up (wxCommandEvent& ev);
+};
index 8606573..227691b 100644 (file)
@@ -82,6 +82,7 @@ sources = """
           playhead_to_timecode_dialog.cc
           playhead_to_frame_dialog.cc
           question_dialog.cc
+          recreate_chain_dialog.cc
           repeat_dialog.cc
           report_problem_dialog.cc
           rename_template_dialog.cc