1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <unotools/securityoptions.hxx>
21 #include <unotools/configmgr.hxx>
22 #include <unotools/configitem.hxx>
23 #include <unotools/ucbhelper.hxx>
24 #include <com/sun/star/uno/Any.hxx>
25 #include <com/sun/star/uno/Sequence.hxx>
27 #include <com/sun/star/beans/PropertyValue.hpp>
28 #include <comphelper/propertyvalue.hxx>
29 #include <comphelper/sequence.hxx>
30 #include <tools/urlobj.hxx>
32 #include <unotools/pathoptions.hxx>
33 #include <officecfg/Office/Common.hxx>
37 using namespace ::com::sun::star::uno
;
39 constexpr OUStringLiteral PROPERTYNAME_MACRO_TRUSTEDAUTHORS
= u
"TrustedAuthors";
40 constexpr OUStringLiteral PROPERTYNAME_TRUSTEDAUTHOR_SUBJECTNAME
= u
"SubjectName";
41 constexpr OUStringLiteral PROPERTYNAME_TRUSTEDAUTHOR_SERIALNUMBER
= u
"SerialNumber";
42 constexpr OUStringLiteral PROPERTYNAME_TRUSTEDAUTHOR_RAWDATA
= u
"RawData";
45 namespace SvtSecurityOptions
48 bool IsReadOnly( EOption eOption
)
53 case SvtSecurityOptions::EOption::SecureUrls
:
54 bReadonly
= officecfg::Office::Common::Security::Scripting::SecureURL::isReadOnly();
56 case SvtSecurityOptions::EOption::DocWarnSaveOrSend
:
57 bReadonly
= officecfg::Office::Common::Security::Scripting::WarnSaveOrSendDoc::isReadOnly();
59 case SvtSecurityOptions::EOption::DocWarnSigning
:
60 bReadonly
= officecfg::Office::Common::Security::Scripting::WarnSignDoc::isReadOnly();
62 case SvtSecurityOptions::EOption::DocWarnPrint
:
63 bReadonly
= officecfg::Office::Common::Security::Scripting::WarnPrintDoc::isReadOnly();
65 case SvtSecurityOptions::EOption::DocWarnCreatePdf
:
66 bReadonly
= officecfg::Office::Common::Security::Scripting::WarnCreatePDF::isReadOnly();
68 case SvtSecurityOptions::EOption::DocWarnRemovePersonalInfo
:
69 bReadonly
= officecfg::Office::Common::Security::Scripting::RemovePersonalInfoOnSaving::isReadOnly();
71 case SvtSecurityOptions::EOption::DocWarnRecommendPassword
:
72 bReadonly
= officecfg::Office::Common::Security::Scripting::RecommendPasswordProtection::isReadOnly();
74 case SvtSecurityOptions::EOption::MacroSecLevel
:
75 bReadonly
= officecfg::Office::Common::Security::Scripting::MacroSecurityLevel::isReadOnly();
77 case SvtSecurityOptions::EOption::MacroTrustedAuthors
:
78 bReadonly
= false; // TODO? officecfg::Office::Common::Security::Scripting::TrustedAuthors::isReadOnly();
80 case SvtSecurityOptions::EOption::CtrlClickHyperlink
:
81 bReadonly
= officecfg::Office::Common::Security::Scripting::HyperlinksWithCtrlClick::isReadOnly();
83 case SvtSecurityOptions::EOption::BlockUntrustedRefererLinks
:
84 bReadonly
= officecfg::Office::Common::Security::Scripting::BlockUntrustedRefererLinks::isReadOnly();
95 std::vector
< OUString
> GetSecureURLs()
97 if (utl::ConfigManager::IsFuzzing())
99 std::vector
<OUString
> aRet
= comphelper::sequenceToContainer
<std::vector
<OUString
>>(
100 officecfg::Office::Common::Security::Scripting::SecureURL::get());
102 std::transform(aRet
.begin(), aRet
.end(), aRet
.begin(),
103 [&aOpt
](const OUString
& rUrl
) -> OUString
{ return aOpt
.SubstituteVariable( rUrl
); });
107 void SetSecureURLs( std::vector
< OUString
>&& urlList
)
109 // DBG_ASSERT(!officecfg::SecureURL::isReadOnly(), "SvtSecurityOptions_Impl::SetSecureURLs()\nYou tried to write on a readonly value!\n");
110 // if (officecfg::SecureURL::isReadOnly())
112 std::vector
< OUString
> lURLs( std::move(urlList
) );
114 std::transform(lURLs
.begin(), lURLs
.end(), lURLs
.begin(),
115 [&aOpt
](const OUString
& rUrl
) -> OUString
{ return aOpt
.UseVariable( rUrl
); });
116 std::shared_ptr
<comphelper::ConfigurationChanges
> xChanges
= comphelper::ConfigurationChanges::create();
117 officecfg::Office::Common::Security::Scripting::SecureURL::set(comphelper::containerToSequence(lURLs
), xChanges
);
121 bool isSecureMacroUri(
122 OUString
const & uri
, OUString
const & referer
)
124 switch (INetURLObject(uri
).GetProtocol()) {
125 case INetProtocol::Macro
:
126 if (uri
.startsWithIgnoreAsciiCase("macro:///")) {
127 // Denotes an App-BASIC macro (see SfxMacroLoader::loadMacro), which
128 // is considered safe:
132 case INetProtocol::Slot
:
133 return referer
.equalsIgnoreAsciiCase("private:user")
134 || isTrustedLocationUri(referer
);
140 bool isUntrustedReferer(OUString
const & referer
)
142 return IsOptionSet(EOption::BlockUntrustedRefererLinks
)
143 && !(referer
.isEmpty() || referer
.startsWithIgnoreAsciiCase("private:")
144 || isTrustedLocationUri(referer
));
147 bool isTrustedLocationUri(OUString
const & uri
)
149 for (const auto & url
: GetSecureURLs())
151 if (utl::UCBContentHelper::IsSubPath(url
, uri
))
159 bool isTrustedLocationUriForUpdatingLinks(OUString
const & uri
)
161 return GetMacroSecurityLevel() == 0 || uri
.isEmpty()
162 || uri
.startsWithIgnoreAsciiCase("private:")
163 || isTrustedLocationUri(uri
);
166 sal_Int32
GetMacroSecurityLevel()
168 return utl::ConfigManager::IsFuzzing() ? 3 : officecfg::Office::Common::Security::Scripting::MacroSecurityLevel::get();
171 void SetMacroSecurityLevel( sal_Int32 _nLevel
)
173 if (utl::ConfigManager::IsFuzzing() || officecfg::Office::Common::Security::Scripting::MacroSecurityLevel::isReadOnly())
176 if( _nLevel
> 3 || _nLevel
< 0 )
179 std::shared_ptr
<comphelper::ConfigurationChanges
> xChanges
= comphelper::ConfigurationChanges::create();
180 officecfg::Office::Common::Security::Scripting::MacroSecurityLevel::set(_nLevel
, xChanges
);
184 bool IsMacroDisabled()
186 return utl::ConfigManager::IsFuzzing() || officecfg::Office::Common::Security::Scripting::DisableMacrosExecution::get();
189 std::vector
< SvtSecurityOptions::Certificate
> GetTrustedAuthors()
191 Reference
<css::container::XHierarchicalNameAccess
> xHierarchyAccess
= utl::ConfigManager::acquireTree(u
"Office.Common/Security/Scripting");
192 const Sequence
< OUString
> lAuthors
= utl::ConfigItem::GetNodeNames( xHierarchyAccess
, PROPERTYNAME_MACRO_TRUSTEDAUTHORS
, utl::ConfigNameFormat::LocalPath
);
193 sal_Int32 c1
= lAuthors
.getLength();
197 sal_Int32 c2
= c1
* 3; // 3 Properties inside Struct TrustedAuthor
198 Sequence
< OUString
> lAllAuthors( c2
);
199 auto plAllAuthors
= lAllAuthors
.getArray();
201 OUString
aSep( "/" );
202 for( const auto& rAuthor
: lAuthors
)
204 plAllAuthors
[ i2
] = PROPERTYNAME_MACRO_TRUSTEDAUTHORS
+ aSep
+ rAuthor
+ aSep
+ PROPERTYNAME_TRUSTEDAUTHOR_SUBJECTNAME
;
206 plAllAuthors
[ i2
] = PROPERTYNAME_MACRO_TRUSTEDAUTHORS
+ aSep
+ rAuthor
+ aSep
+ PROPERTYNAME_TRUSTEDAUTHOR_SERIALNUMBER
;
208 plAllAuthors
[ i2
] = PROPERTYNAME_MACRO_TRUSTEDAUTHORS
+ aSep
+ rAuthor
+ aSep
+ PROPERTYNAME_TRUSTEDAUTHOR_RAWDATA
;
212 Sequence
< Any
> lValues
= utl::ConfigItem::GetProperties( xHierarchyAccess
, lAllAuthors
, /*bAllLocales*/false );
213 if( lValues
.getLength() != c2
)
216 std::vector
< SvtSecurityOptions::Certificate
> aTrustedAuthors
;
217 SvtSecurityOptions::Certificate aCert
;
219 for( sal_Int32 i1
= 0; i1
< c1
; ++i1
)
221 lValues
[ i2
] >>= aCert
.SubjectName
;
223 lValues
[ i2
] >>= aCert
.SerialNumber
;
225 lValues
[ i2
] >>= aCert
.RawData
;
227 // Filter out TrustedAuthor entries with empty RawData, which
228 // would cause an unexpected std::bad_alloc in
229 // SecurityEnvironment_NssImpl::createCertificateFromAscii and
230 // have been observed in the wild (fdo#55019):
231 if( !aCert
.RawData
.isEmpty() )
233 aTrustedAuthors
.push_back( aCert
);
236 return aTrustedAuthors
;
239 void SetTrustedAuthors( const std::vector
< Certificate
>& rAuthors
)
241 // DBG_ASSERT(!m_bROTrustedAuthors, "SvtSecurityOptions_Impl::SetTrustedAuthors()\nYou tried to write on a readonly value!\n");
242 // if( m_bROTrustedAuthors )
245 Reference
<css::container::XHierarchicalNameAccess
> xHierarchyAccess
= utl::ConfigManager::acquireTree(u
"Office.Common/Security/Scripting");
246 sal_Int32 nCnt
= rAuthors
.size();
247 for( sal_Int32 i
= 0; i
< nCnt
; ++i
)
250 PROPERTYNAME_MACRO_TRUSTEDAUTHORS
+ "/a"
251 + OUString::number(i
) + "/");
252 Sequence
< css::beans::PropertyValue
> lPropertyValues
{
253 comphelper::makePropertyValue(aPrefix
+ PROPERTYNAME_TRUSTEDAUTHOR_SUBJECTNAME
,
254 rAuthors
[i
].SubjectName
),
255 comphelper::makePropertyValue(aPrefix
+ PROPERTYNAME_TRUSTEDAUTHOR_SERIALNUMBER
,
256 rAuthors
[i
].SerialNumber
),
257 comphelper::makePropertyValue(aPrefix
+ PROPERTYNAME_TRUSTEDAUTHOR_RAWDATA
,
261 utl::ConfigItem::SetSetProperties( xHierarchyAccess
, PROPERTYNAME_MACRO_TRUSTEDAUTHORS
, lPropertyValues
);
265 bool IsOptionSet( EOption eOption
)
267 if (utl::ConfigManager::IsFuzzing())
272 case SvtSecurityOptions::EOption::DocWarnSaveOrSend
:
273 bSet
= officecfg::Office::Common::Security::Scripting::WarnSaveOrSendDoc::get();
275 case SvtSecurityOptions::EOption::DocWarnSigning
:
276 bSet
= officecfg::Office::Common::Security::Scripting::WarnSignDoc::get();
278 case SvtSecurityOptions::EOption::DocWarnPrint
:
279 bSet
= officecfg::Office::Common::Security::Scripting::WarnPrintDoc::get();
281 case SvtSecurityOptions::EOption::DocWarnCreatePdf
:
282 bSet
= officecfg::Office::Common::Security::Scripting::WarnCreatePDF::get();
284 case SvtSecurityOptions::EOption::DocWarnRemovePersonalInfo
:
285 bSet
= officecfg::Office::Common::Security::Scripting::RemovePersonalInfoOnSaving::get();
287 case SvtSecurityOptions::EOption::DocWarnRecommendPassword
:
288 bSet
= officecfg::Office::Common::Security::Scripting::RecommendPasswordProtection::get();
290 case SvtSecurityOptions::EOption::CtrlClickHyperlink
:
291 bSet
= officecfg::Office::Common::Security::Scripting::HyperlinksWithCtrlClick::get();
293 case SvtSecurityOptions::EOption::BlockUntrustedRefererLinks
:
294 bSet
= officecfg::Office::Common::Security::Scripting::BlockUntrustedRefererLinks::get();
304 void SetOption( EOption eOption
, bool bValue
)
306 std::shared_ptr
<comphelper::ConfigurationChanges
> xChanges
= comphelper::ConfigurationChanges::create();
309 case SvtSecurityOptions::EOption::DocWarnSaveOrSend
:
310 officecfg::Office::Common::Security::Scripting::WarnSaveOrSendDoc::set(bValue
, xChanges
);
312 case SvtSecurityOptions::EOption::DocWarnSigning
:
313 officecfg::Office::Common::Security::Scripting::WarnSignDoc::set(bValue
, xChanges
);
315 case SvtSecurityOptions::EOption::DocWarnPrint
:
316 officecfg::Office::Common::Security::Scripting::WarnPrintDoc::set(bValue
, xChanges
);
318 case SvtSecurityOptions::EOption::DocWarnCreatePdf
:
319 officecfg::Office::Common::Security::Scripting::WarnCreatePDF::set(bValue
, xChanges
);
321 case SvtSecurityOptions::EOption::DocWarnRemovePersonalInfo
:
322 officecfg::Office::Common::Security::Scripting::RemovePersonalInfoOnSaving::set(bValue
, xChanges
);
324 case SvtSecurityOptions::EOption::DocWarnRecommendPassword
:
325 officecfg::Office::Common::Security::Scripting::RecommendPasswordProtection::set(bValue
, xChanges
);
327 case SvtSecurityOptions::EOption::CtrlClickHyperlink
:
328 officecfg::Office::Common::Security::Scripting::HyperlinksWithCtrlClick::set(bValue
, xChanges
);
330 case SvtSecurityOptions::EOption::BlockUntrustedRefererLinks
:
331 officecfg::Office::Common::Security::Scripting::BlockUntrustedRefererLinks::set(bValue
, xChanges
);
340 } // namespace SvtSecurityOptions
343 // map personal info strings to 1, 2, ... to remove personal info
344 size_t SvtSecurityMapPersonalInfo::GetInfoID( const OUString sPersonalInfo
)
346 auto aIter
= aInfoIDs
.find( sPersonalInfo
);
347 if ( aIter
== aInfoIDs
.end() )
349 size_t nNewID
= aInfoIDs
.size() + 1;
350 aInfoIDs
[sPersonalInfo
] = nNewID
;
354 return aIter
->second
;
357 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */