/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include // 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 aRet = comphelper::sequenceToContainer>( 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 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 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 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 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 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: */