/* -*- 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 .
*/
usingnamespace ::com::sun::star; using ::com::sun::star::uno::Sequence; using ::std::vector;
bool ScPassHashHelper::needsPassHashRegen(const ScDocument& rDoc, ScPasswordHash eHash1, ScPasswordHash eHash2)
{ if (rDoc.IsDocProtected())
{ const ScDocProtection* p = rDoc.GetDocProtection(); if (!p->isPasswordEmpty() && !p->hasPasswordHash(eHash1, eHash2)) returntrue;
}
SCTAB nTabCount = rDoc.GetTableCount(); for (SCTAB i = 0; i < nTabCount; ++i)
{ const ScTableProtection* p = rDoc.GetTabProtection(i); if (!p || !p->isProtected()) // Sheet not protected. Skip it. continue;
if (!p->isPasswordEmpty() && !p->hasPasswordHash(eHash1, eHash2)) returntrue;
}
returnfalse;
}
const OUString & ScPassHashHelper::getHashURI(ScPasswordHash eHash)
{ switch (eHash)
{ case PASSHASH_SHA256: return URI_SHA256_ODF12; case PASSHASH_SHA1: return URI_SHA1; case PASSHASH_XL: return URI_XLS_LEGACY; case PASSHASH_UNSPECIFIED: default:
;
} return EMPTY_OUSTRING;
}
// TODO: Right now, we only support double-hash by SHA1. if (eHash == PASSHASH_SHA1)
{ auto aChars = comphelper::sequenceToContainer<vector<char>>(rPassHash);
void ScTableProtectionImpl::setProtected(bool bProtected)
{
mbProtected = bProtected; // We need to keep the old password even when the protection is off. So, // don't erase the password data here.
}
void ScTableProtectionImpl::setPassword(const OUString& aPassText)
{ // We can't hash it here because we don't know whether this document will // get saved to Excel or ODF, depending on which we will need to use a // different hashing algorithm. One alternative is to hash it using all // hash algorithms that we support, and store them all.
if (mbEmptyPass) // Flagged as empty. return aPassHash;
if (!maPassText.isEmpty())
{ // Cleartext password exists. Hash it.
aPassHash = hashPassword(maPassText, eHash); if (eHash2 != PASSHASH_UNSPECIFIED) // Double-hash it.
aPassHash = hashPassword(aPassHash, eHash2);
return aPassHash;
} else
{ // No clear text password. Check if we have a hash value of the right hash type. if (meHash1 == eHash)
{
aPassHash = maPassHash;
if (meHash2 == eHash2) // Matching double-hash requested. return aPassHash; elseif (meHash2 == PASSHASH_UNSPECIFIED) // primary hashing type match. Double hash it by the requested // double-hash type. return hashPassword(aPassHash, eHash2);
}
}
#if DEBUG_TAB_PROTECTION for (sal_Int8 n : aPassword)
printf("%2.2X ", static_cast<sal_uInt8>(n));
printf("\n"); #endif
}
void ScTableProtectionImpl::setPasswordHash( const OUString& rAlgorithmName, const OUString& rHashValue, const OUString& rSaltValue, sal_uInt32 nSpinCount )
{ if (!rHashValue.isEmpty())
{ // Invalidate the other hashes.
setPasswordHash( uno::Sequence<sal_Int8>(), PASSHASH_UNSPECIFIED, PASSHASH_UNSPECIFIED);
// We don't know whether this is an empty password (or would // unnecessarily have to try to verify an empty password), assume it is // not. A later verifyPassword() with an empty password will determine. // If this was not set to false then a verifyPassword() with an empty // password would unlock even if this hash here wasn't for an empty // password. Ugly stuff.
mbEmptyPass = false;
}
if (!maPassText.isEmpty()) // Clear text password exists, and this one takes precedence. return aPassText == maPassText;
// For PASSHASH_UNSPECIFIED also maPassHash is empty and any aPassText // would yield an empty hash as well and thus compare true. Don't. if (meHash1 != PASSHASH_UNSPECIFIED)
{
Sequence<sal_Int8> aHash = hashPassword(aPassText, meHash1);
aHash = hashPassword(aHash, meHash2);
#if DEBUG_TAB_PROTECTION
fprintf(stdout, "ScTableProtectionImpl::verifyPassword: hash = "); for (sal_Int32 i = 0; i < aHash.getLength(); ++i)
printf("%2.2X ", static_cast<sal_uInt8>(aHash[i]));
printf("\n"); #endif
if (aHash == maPassHash)
{ returntrue;
}
}
// tdf#115483 compat hack for ODF 1.2; for now UTF8-SHA1 passwords are only // verified, not generated if (meHash1 == PASSHASH_SHA1 && meHash2 == PASSHASH_UNSPECIFIED)
{
Sequence<sal_Int8> const aHash2 = hashPassword(aPassText, PASSHASH_SHA1_UTF8); return aHash2 == maPassHash;
}
// Not yet generated or tracked with meHash1 or meHash2, but can be read // from OOXML. return maPasswordHash.verifyPassword( aPassText);
}
bool ScTableProtectionImpl::isBlockEditable( const ScRange& rRange ) const
{ /* TODO: ask for password (and remember) if a password was set for * a matching range and no matching range without password was encountered. * Would need another return type than boolean to reflect
* "password required for a specific protection". */
// No protection exception or overriding permission to edit if empty. if (maEnhancedProtection.empty()) returnfalse;
// No security descriptor in an enhanced protection means the ranges of // that protection are editable. If there is any security descriptor // present we assume the permission to edit is not granted. Until we // actually can evaluate the descriptors...
{ auto lIsEditable = [rRange](const ScEnhancedProtection& rEnhancedProtection) { return !rEnhancedProtection.hasSecurityDescriptor()
&& rEnhancedProtection.maRangeList.is() && rEnhancedProtection.maRangeList->Contains( rRange)
&& !rEnhancedProtection.hasPassword(); // Range is editable if no password is assigned.
}; if (std::any_of(maEnhancedProtection.begin(), maEnhancedProtection.end(), std::move(lIsEditable))) returntrue;
}
// For a single address, a simple check with single ranges was sufficient. if (rRange.aStart == rRange.aEnd) returnfalse;
// Test also for cases where rRange is encompassed by a union of two or // more ranges of the list. The original ranges are not necessarily joined. for (constauto& rEnhancedProtection : maEnhancedProtection)
{ if (!rEnhancedProtection.hasSecurityDescriptor() && rEnhancedProtection.maRangeList.is())
{
ScRangeList aList( rEnhancedProtection.maRangeList->GetIntersectedRange( rRange)); if (aList.size() == 1 && aList[0] == rRange)
{ // Range is editable if no password is assigned. if (!rEnhancedProtection.hasPassword()) returntrue;
}
}
}
// Ranges may even be distributed over different protection records, for // example if they are assigned different names, and can have different // passwords. Combine the ones that can be edited. /* TODO: once we handle passwords, remember a successful unlock at
* ScEnhancedProtection so we can use that here. */
ScRangeList aRangeList; for (constauto& rEnhancedProtection : maEnhancedProtection)
{ if (!rEnhancedProtection.hasSecurityDescriptor() && rEnhancedProtection.maRangeList.is())
{ // Ranges are editable if no password is assigned. if (!rEnhancedProtection.hasPassword())
{ const ScRangeList& rRanges = *rEnhancedProtection.maRangeList;
size_t nRanges = rRanges.size(); for (size_t i=0; i < nRanges; ++i)
{
aRangeList.push_back( rRanges[i]);
}
}
}
}
ScRangeList aResultList( aRangeList.GetIntersectedRange( rRange)); return aResultList.size() == 1 && aResultList[0] == rRange;
}
// Currently Calc doesn't support document protection options. So, let's // assume that when the document is protected, its structure is protected. // We need to do this for Excel export.
mpImpl->setOption(ScDocProtection::STRUCTURE, bProtected);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.