X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fconfig.cc;h=04cf6dd9b5cfa12ae124bb9b1a44113964dd4263;hb=9da0bac018e0e7dcad0c1aafaa7f6be6d434da96;hp=e61eea3a6f89f7cd916be30b9cb8a54aa595dc95;hpb=5ab0c3bc04e4aa5acd883bb8126fc6b185c6c5d6;p=dcpomatic.git diff --git a/src/lib/config.cc b/src/lib/config.cc index e61eea3a6..04cf6dd9b 100644 --- a/src/lib/config.cc +++ b/src/lib/config.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. @@ -32,6 +32,7 @@ #include "film.h" #include "dkdm_wrapper.h" #include "compose.hpp" +#include "crypto.h" #include #include #include @@ -61,6 +62,7 @@ using boost::shared_ptr; using boost::optional; using boost::dynamic_pointer_cast; using boost::algorithm::trim; +using boost::shared_array; using dcp::raw_convert; Config* Config::_instance = 0; @@ -177,6 +179,8 @@ Config::set_defaults () _player_watermark_period = 1; _player_watermark_duration = 50; _player_lock_file = boost::none; + _signer_chain_path = "signer"; + _decryption_chain_path = "decryption"; #endif _allowed_dcp_frame_rates.clear (); @@ -392,6 +396,21 @@ try } cxml::NodePtr signer = f.optional_node_child ("Signer"); +#ifdef DCPOMATIC_VARIANT_SWAROOP + if (signer && signer->node_children().size() == 1) { + /* The content of is a path to a file; if it's relative it's in the same + directory as .config. */ + _signer_chain_path = signer->content(); + if (_signer_chain_path.is_relative()) { + _signer_chain = read_swaroop_chain (path(_signer_chain_path.string())); + } else { + _signer_chain = read_swaroop_chain (_signer_chain_path); + } + } else { + /* is not present or has children: ignore it and remake. */ + _signer_chain = create_certificate_chain (); + } +#else if (signer) { shared_ptr c (new dcp::CertificateChain ()); /* Read the signing certificates and private key in from the config file */ @@ -404,6 +423,7 @@ try /* Make a new set of signing certificates and key */ _signer_chain = create_certificate_chain (); } +#endif /* These must be done before we call BadSignerChain as that might set one of the nags. @@ -430,6 +450,21 @@ try } cxml::NodePtr decryption = f.optional_node_child ("Decryption"); +#ifdef DCPOMATIC_VARIANT_SWAROOP + if (decryption && decryption->node_children().size() == 1) { + /* The content of is a path to a file; if it's relative, it's in the same + directory as .config. */ + _decryption_chain_path = decryption->content(); + if (_decryption_chain_path.is_relative()) { + _decryption_chain = read_swaroop_chain (path(_decryption_chain_path.string())); + } else { + _decryption_chain = read_swaroop_chain (_decryption_chain_path); + } + } else { + /* is not present or has more children: ignore it and remake. */ + _decryption_chain = create_certificate_chain (); + } +#else if (decryption) { shared_ptr c (new dcp::CertificateChain ()); BOOST_FOREACH (cxml::NodePtr i, decryption->node_children ("Certificate")) { @@ -440,7 +475,7 @@ try } else { _decryption_chain = create_certificate_chain (); } - +#endif if (f.optional_node_child("DKDMGroup")) { /* New-style: all DKDMs in a group */ _dkdms = dynamic_pointer_cast (DKDMBase::read (f.node_child("DKDMGroup"))); @@ -766,31 +801,38 @@ Config::write_config () const /* [XML] Signer Certificate chain and private key to use when signing DCPs and KDMs. Should contain <Certificate> tags in order and a <PrivateKey> tag all containing PEM-encoded certificates or private keys as appropriate. */ +#ifdef DCPOMATIC_VARIANT_SWAROOP + if (_signer_chain_path.is_relative()) { + write_swaroop_chain (_signer_chain, path(_signer_chain_path.string())); + } else { + write_swaroop_chain (_signer_chain, _signer_chain_path); + } + root->add_child("Signer")->add_child_text(_signer_chain_path.string()); +#else xmlpp::Element* signer = root->add_child ("Signer"); DCPOMATIC_ASSERT (_signer_chain); BOOST_FOREACH (dcp::Certificate const & i, _signer_chain->unordered()) { signer->add_child("Certificate")->add_child_text (i.certificate (true)); } -#ifdef DCPOMATIC_SWAROOP - FILE* f = fopen_boost (path("private"), "wb"); - if (!f) { - throw FileError ("Could not open file for writing", path("private")); - } - shared_array iv = dcpomatic::random_iv (); - dcp::Data encrypted_key = dcpomatic::encrypt (_signer_chain->key().get(), key, iv); - fwrite (encrypted_key.data().get(), encrypted_key.data().size(), 1, f); - fclose (f); -#else signer->add_child("PrivateKey")->add_child_text (_signer_chain->key().get ()); -#endif +#endif /* [XML] Decryption Certificate chain and private key to use when decrypting KDMs */ +#ifdef DCPOMATIC_VARIANT_SWAROOP + if (_decryption_chain_path.is_relative()) { + write_swaroop_chain (_decryption_chain, path(_decryption_chain_path.string())); + } else { + write_swaroop_chain (_decryption_chain, _decryption_chain_path); + } + root->add_child("Decryption")->add_child_text(_decryption_chain_path.string()); +#else xmlpp::Element* decryption = root->add_child ("Decryption"); DCPOMATIC_ASSERT (_decryption_chain); BOOST_FOREACH (dcp::Certificate const & i, _decryption_chain->unordered()) { decryption->add_child("Certificate")->add_child_text (i.certificate (true)); } decryption->add_child("PrivateKey")->add_child_text (_decryption_chain->key().get ()); +#endif /* [XML] History Filename of DCP to present in the File menu of the GUI; there can be more than one of these tags. @@ -959,17 +1001,15 @@ Config::write_config () const try { string const s = doc.write_to_string_formatted (); - boost::filesystem::path const cf = config_file (); - FILE* f = fopen_boost (cf, "w"); + boost::filesystem::path tmp (string(config_file().string()).append(".tmp")); + FILE* f = fopen_boost (tmp, "w"); if (!f) { - throw FileError (_("Could not open file for writing"), cf); - } - size_t const w = fwrite (s.c_str(), 1, s.length(), f); - if (w != s.length()) { - fclose (f); - throw FileError (_("Could not write whole file"), cf); + throw FileError (_("Could not open file for writing"), tmp); } + checked_fwrite (s.c_str(), s.length(), f, tmp); fclose (f); + boost::filesystem::remove (config_file()); + boost::filesystem::rename (tmp, config_file()); } catch (xmlpp::exception& e) { string s = e.what (); trim (s); @@ -989,7 +1029,9 @@ Config::write_cinemas () const } try { - doc.write_to_file_formatted (_cinemas_file.string ()); + doc.write_to_file_formatted (_cinemas_file.string() + ".tmp"); + boost::filesystem::remove (_cinemas_file); + boost::filesystem::rename (_cinemas_file.string() + ".tmp", _cinemas_file); } catch (xmlpp::exception& e) { string s = e.what (); trim (s); @@ -1214,10 +1256,16 @@ Config::config_file () } /* See if there's a link */ - f.read_file (main); - optional link = f.optional_string_child("Link"); - if (link) { - return *link; + try { + f.read_file (main); + optional link = f.optional_string_child("Link"); + if (link) { + return *link; + } + } catch (xmlpp::exception& e) { + /* There as a problem reading the main configuration file, + so there can't be a link. + */ } return main;