diff options
Diffstat (limited to 'unotools/source/config/securityoptions.cxx')
-rw-r--r-- | unotools/source/config/securityoptions.cxx | 357 |
1 files changed, 357 insertions, 0 deletions
diff --git a/unotools/source/config/securityoptions.cxx b/unotools/source/config/securityoptions.cxx new file mode 100644 index 000000000..4749065fb --- /dev/null +++ b/unotools/source/config/securityoptions.cxx @@ -0,0 +1,357 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <unotools/securityoptions.hxx> +#include <unotools/configmgr.hxx> +#include <unotools/configitem.hxx> +#include <unotools/ucbhelper.hxx> +#include <com/sun/star/uno/Any.hxx> +#include <com/sun/star/uno/Sequence.hxx> + +#include <com/sun/star/beans/PropertyValue.hpp> +#include <comphelper/propertyvalue.hxx> +#include <comphelper/sequence.hxx> +#include <tools/urlobj.hxx> + +#include <unotools/pathoptions.hxx> +#include <officecfg/Office/Common.hxx> + +// namespaces + +using namespace ::com::sun::star::uno; + +constexpr OUStringLiteral PROPERTYNAME_MACRO_TRUSTEDAUTHORS = u"TrustedAuthors"; +constexpr OUStringLiteral PROPERTYNAME_TRUSTEDAUTHOR_SUBJECTNAME = u"SubjectName"; +constexpr OUStringLiteral PROPERTYNAME_TRUSTEDAUTHOR_SERIALNUMBER = u"SerialNumber"; +constexpr OUStringLiteral PROPERTYNAME_TRUSTEDAUTHOR_RAWDATA = u"RawData"; + + +namespace SvtSecurityOptions +{ + +bool IsReadOnly( EOption eOption ) +{ + bool bReadonly; + switch(eOption) + { + case SvtSecurityOptions::EOption::SecureUrls : + bReadonly = officecfg::Office::Common::Security::Scripting::SecureURL::isReadOnly(); + break; + case SvtSecurityOptions::EOption::DocWarnSaveOrSend: + bReadonly = officecfg::Office::Common::Security::Scripting::WarnSaveOrSendDoc::isReadOnly(); + break; + case SvtSecurityOptions::EOption::DocWarnSigning: + bReadonly = officecfg::Office::Common::Security::Scripting::WarnSignDoc::isReadOnly(); + break; + case SvtSecurityOptions::EOption::DocWarnPrint: + bReadonly = officecfg::Office::Common::Security::Scripting::WarnPrintDoc::isReadOnly(); + break; + case SvtSecurityOptions::EOption::DocWarnCreatePdf: + bReadonly = officecfg::Office::Common::Security::Scripting::WarnCreatePDF::isReadOnly(); + break; + case SvtSecurityOptions::EOption::DocWarnRemovePersonalInfo: + bReadonly = officecfg::Office::Common::Security::Scripting::RemovePersonalInfoOnSaving::isReadOnly(); + break; + case SvtSecurityOptions::EOption::DocWarnRecommendPassword: + bReadonly = officecfg::Office::Common::Security::Scripting::RecommendPasswordProtection::isReadOnly(); + break; + case SvtSecurityOptions::EOption::MacroSecLevel: + bReadonly = officecfg::Office::Common::Security::Scripting::MacroSecurityLevel::isReadOnly(); + break; + case SvtSecurityOptions::EOption::MacroTrustedAuthors: + bReadonly = false; // TODO? officecfg::Office::Common::Security::Scripting::TrustedAuthors::isReadOnly(); + break; + case SvtSecurityOptions::EOption::CtrlClickHyperlink: + bReadonly = officecfg::Office::Common::Security::Scripting::HyperlinksWithCtrlClick::isReadOnly(); + break; + case SvtSecurityOptions::EOption::BlockUntrustedRefererLinks: + bReadonly = officecfg::Office::Common::Security::Scripting::BlockUntrustedRefererLinks::isReadOnly(); + break; + + default: + assert(false); + bReadonly = true; + } + + return bReadonly; +} + +std::vector< OUString > GetSecureURLs() +{ + if (utl::ConfigManager::IsFuzzing()) + return {}; + std::vector<OUString> aRet = comphelper::sequenceToContainer<std::vector<OUString>>( + officecfg::Office::Common::Security::Scripting::SecureURL::get()); + SvtPathOptions aOpt; + std::transform(aRet.begin(), aRet.end(), aRet.begin(), + [&aOpt](const OUString& rUrl) -> OUString { return aOpt.SubstituteVariable( rUrl ); }); + return aRet; +} + +void SetSecureURLs( std::vector< OUString >&& urlList ) +{ +// DBG_ASSERT(!officecfg::SecureURL::isReadOnly(), "SvtSecurityOptions_Impl::SetSecureURLs()\nYou tried to write on a readonly value!\n"); +// if (officecfg::SecureURL::isReadOnly()) +// return; + std::vector< OUString > lURLs( std::move(urlList) ); + SvtPathOptions aOpt; + std::transform(lURLs.begin(), lURLs.end(), lURLs.begin(), + [&aOpt](const OUString& rUrl) -> OUString { return aOpt.UseVariable( rUrl ); }); + std::shared_ptr<comphelper::ConfigurationChanges> xChanges = comphelper::ConfigurationChanges::create(); + officecfg::Office::Common::Security::Scripting::SecureURL::set(comphelper::containerToSequence(lURLs), xChanges); + xChanges->commit(); +} + +bool isSecureMacroUri( + OUString const & uri, OUString const & referer) +{ + switch (INetURLObject(uri).GetProtocol()) { + case INetProtocol::Macro: + if (uri.startsWithIgnoreAsciiCase("macro:///")) { + // Denotes an App-BASIC macro (see SfxMacroLoader::loadMacro), which + // is considered safe: + return true; + } + [[fallthrough]]; + case INetProtocol::Slot: + return referer.equalsIgnoreAsciiCase("private:user") + || isTrustedLocationUri(referer); + default: + return true; + } +} + +bool isUntrustedReferer(OUString const & referer) +{ + return IsOptionSet(EOption::BlockUntrustedRefererLinks) + && !(referer.isEmpty() || referer.startsWithIgnoreAsciiCase("private:") + || isTrustedLocationUri(referer)); +} + +bool isTrustedLocationUri(OUString const & uri) +{ + for (const auto & url : GetSecureURLs()) + { + if (utl::UCBContentHelper::IsSubPath(url, uri)) + { + return true; + } + } + return false; +} + +bool isTrustedLocationUriForUpdatingLinks(OUString const & uri) +{ + return GetMacroSecurityLevel() == 0 || uri.isEmpty() + || uri.startsWithIgnoreAsciiCase("private:") + || isTrustedLocationUri(uri); +} + +sal_Int32 GetMacroSecurityLevel() +{ + return officecfg::Office::Common::Security::Scripting::MacroSecurityLevel::get(); +} + +void SetMacroSecurityLevel( sal_Int32 _nLevel ) +{ + if( officecfg::Office::Common::Security::Scripting::MacroSecurityLevel::isReadOnly() ) + return; + + if( _nLevel > 3 || _nLevel < 0 ) + _nLevel = 3; + + std::shared_ptr<comphelper::ConfigurationChanges> xChanges = comphelper::ConfigurationChanges::create(); + officecfg::Office::Common::Security::Scripting::MacroSecurityLevel::set(_nLevel, xChanges); + xChanges->commit(); +} + +bool IsMacroDisabled() +{ + return officecfg::Office::Common::Security::Scripting::DisableMacrosExecution::get(); +} + +std::vector< SvtSecurityOptions::Certificate > GetTrustedAuthors() +{ + Reference<css::container::XHierarchicalNameAccess> xHierarchyAccess = utl::ConfigManager::acquireTree(u"Office.Common/Security/Scripting"); + const Sequence< OUString > lAuthors = utl::ConfigItem::GetNodeNames( xHierarchyAccess, PROPERTYNAME_MACRO_TRUSTEDAUTHORS, utl::ConfigNameFormat::LocalPath ); + sal_Int32 c1 = lAuthors.getLength(); + if( !c1 ) + return {}; + + sal_Int32 c2 = c1 * 3; // 3 Properties inside Struct TrustedAuthor + Sequence< OUString > lAllAuthors( c2 ); + auto plAllAuthors = lAllAuthors.getArray(); + sal_Int32 i2 = 0; + OUString aSep( "/" ); + for( const auto& rAuthor : lAuthors ) + { + plAllAuthors[ i2 ] = PROPERTYNAME_MACRO_TRUSTEDAUTHORS + aSep + rAuthor + aSep + PROPERTYNAME_TRUSTEDAUTHOR_SUBJECTNAME; + ++i2; + plAllAuthors[ i2 ] = PROPERTYNAME_MACRO_TRUSTEDAUTHORS + aSep + rAuthor + aSep + PROPERTYNAME_TRUSTEDAUTHOR_SERIALNUMBER; + ++i2; + plAllAuthors[ i2 ] = PROPERTYNAME_MACRO_TRUSTEDAUTHORS + aSep + rAuthor + aSep + PROPERTYNAME_TRUSTEDAUTHOR_RAWDATA; + ++i2; + } + + Sequence< Any > lValues = utl::ConfigItem::GetProperties( xHierarchyAccess, lAllAuthors, /*bAllLocales*/false ); + if( lValues.getLength() != c2 ) + return {}; + + std::vector< SvtSecurityOptions::Certificate > aTrustedAuthors; + SvtSecurityOptions::Certificate aCert; + i2 = 0; + for( sal_Int32 i1 = 0; i1 < c1; ++i1 ) + { + lValues[ i2 ] >>= aCert.SubjectName; + ++i2; + lValues[ i2 ] >>= aCert.SerialNumber; + ++i2; + lValues[ i2 ] >>= aCert.RawData; + ++i2; + // Filter out TrustedAuthor entries with empty RawData, which + // would cause an unexpected std::bad_alloc in + // SecurityEnvironment_NssImpl::createCertificateFromAscii and + // have been observed in the wild (fdo#55019): + if( !aCert.RawData.isEmpty() ) + { + aTrustedAuthors.push_back( aCert ); + } + } + return aTrustedAuthors; +} + +void SetTrustedAuthors( const std::vector< Certificate >& rAuthors ) +{ +// DBG_ASSERT(!m_bROTrustedAuthors, "SvtSecurityOptions_Impl::SetTrustedAuthors()\nYou tried to write on a readonly value!\n"); +// if( m_bROTrustedAuthors ) +// return; + + Reference<css::container::XHierarchicalNameAccess> xHierarchyAccess = utl::ConfigManager::acquireTree(u"Office.Common/Security/Scripting"); + sal_Int32 nCnt = rAuthors.size(); + for( sal_Int32 i = 0; i < nCnt; ++i ) + { + OUString aPrefix( + PROPERTYNAME_MACRO_TRUSTEDAUTHORS + "/a" + + OUString::number(i) + "/"); + Sequence< css::beans::PropertyValue > lPropertyValues{ + comphelper::makePropertyValue(aPrefix + PROPERTYNAME_TRUSTEDAUTHOR_SUBJECTNAME, + rAuthors[i].SubjectName), + comphelper::makePropertyValue(aPrefix + PROPERTYNAME_TRUSTEDAUTHOR_SERIALNUMBER, + rAuthors[i].SerialNumber), + comphelper::makePropertyValue(aPrefix + PROPERTYNAME_TRUSTEDAUTHOR_RAWDATA, + rAuthors[i].RawData) + }; + + utl::ConfigItem::SetSetProperties( xHierarchyAccess, PROPERTYNAME_MACRO_TRUSTEDAUTHORS, lPropertyValues ); + } +} + +bool IsOptionSet( EOption eOption ) +{ + if (utl::ConfigManager::IsFuzzing()) + return false; + bool bSet = false; + switch(eOption) + { + case SvtSecurityOptions::EOption::DocWarnSaveOrSend: + bSet = officecfg::Office::Common::Security::Scripting::WarnSaveOrSendDoc::get(); + break; + case SvtSecurityOptions::EOption::DocWarnSigning: + bSet = officecfg::Office::Common::Security::Scripting::WarnSignDoc::get(); + break; + case SvtSecurityOptions::EOption::DocWarnPrint: + bSet = officecfg::Office::Common::Security::Scripting::WarnPrintDoc::get(); + break; + case SvtSecurityOptions::EOption::DocWarnCreatePdf: + bSet = officecfg::Office::Common::Security::Scripting::WarnCreatePDF::get(); + break; + case SvtSecurityOptions::EOption::DocWarnRemovePersonalInfo: + bSet = officecfg::Office::Common::Security::Scripting::RemovePersonalInfoOnSaving::get(); + break; + case SvtSecurityOptions::EOption::DocWarnRecommendPassword: + bSet = officecfg::Office::Common::Security::Scripting::RecommendPasswordProtection::get(); + break; + case SvtSecurityOptions::EOption::CtrlClickHyperlink: + bSet = officecfg::Office::Common::Security::Scripting::HyperlinksWithCtrlClick::get(); + break; + case SvtSecurityOptions::EOption::BlockUntrustedRefererLinks: + bSet = officecfg::Office::Common::Security::Scripting::BlockUntrustedRefererLinks::get(); + break; + + default: + assert(false); + } + + return bSet; +} + +void SetOption( EOption eOption, bool bValue ) +{ + std::shared_ptr<comphelper::ConfigurationChanges> xChanges = comphelper::ConfigurationChanges::create(); + switch(eOption) + { + case SvtSecurityOptions::EOption::DocWarnSaveOrSend: + officecfg::Office::Common::Security::Scripting::WarnSaveOrSendDoc::set(bValue, xChanges); + break; + case SvtSecurityOptions::EOption::DocWarnSigning: + officecfg::Office::Common::Security::Scripting::WarnSignDoc::set(bValue, xChanges); + break; + case SvtSecurityOptions::EOption::DocWarnPrint: + officecfg::Office::Common::Security::Scripting::WarnPrintDoc::set(bValue, xChanges); + break; + case SvtSecurityOptions::EOption::DocWarnCreatePdf: + officecfg::Office::Common::Security::Scripting::WarnCreatePDF::set(bValue, xChanges); + break; + case SvtSecurityOptions::EOption::DocWarnRemovePersonalInfo: + officecfg::Office::Common::Security::Scripting::RemovePersonalInfoOnSaving::set(bValue, xChanges); + break; + case SvtSecurityOptions::EOption::DocWarnRecommendPassword: + officecfg::Office::Common::Security::Scripting::RecommendPasswordProtection::set(bValue, xChanges); + break; + case SvtSecurityOptions::EOption::CtrlClickHyperlink: + officecfg::Office::Common::Security::Scripting::HyperlinksWithCtrlClick::set(bValue, xChanges); + break; + case SvtSecurityOptions::EOption::BlockUntrustedRefererLinks: + officecfg::Office::Common::Security::Scripting::BlockUntrustedRefererLinks::set(bValue, xChanges); + break; + + default: + assert(false); + } + xChanges->commit(); +} + +} // namespace SvtSecurityOptions + + +// map personal info strings to 1, 2, ... to remove personal info +size_t SvtSecurityMapPersonalInfo::GetInfoID( const OUString sPersonalInfo ) +{ + auto aIter = aInfoIDs.find( sPersonalInfo ); + if ( aIter == aInfoIDs.end() ) + { + size_t nNewID = aInfoIDs.size() + 1; + aInfoIDs[sPersonalInfo] = nNewID; + return nNewID; + } + + return aIter->second; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |