LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/sc/source/core/data - tabprotection.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 73 191 38.2 %
Date: 2013-07-09 Functions: 25 51 49.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      20             : #include "tabprotection.hxx"
      21             : #include "svl/PasswordHelper.hxx"
      22             : #include <comphelper/docpasswordhelper.hxx>
      23             : #include "document.hxx"
      24             : 
      25             : #include <vector>
      26             : 
      27             : #define DEBUG_TAB_PROTECTION 0
      28             : 
      29             : #define URI_SHA1 "http://www.w3.org/2000/09/xmldsig#sha1"
      30             : #define URI_XLS_LEGACY "http://docs.oasis-open.org/office/ns/table/legacy-hash-excel"
      31             : 
      32             : using namespace ::com::sun::star;
      33             : using ::com::sun::star::uno::Sequence;
      34             : using ::std::vector;
      35             : 
      36             : // ============================================================================
      37             : 
      38           9 : bool ScPassHashHelper::needsPassHashRegen(const ScDocument& rDoc, ScPasswordHash eHash1, ScPasswordHash eHash2)
      39             : {
      40           9 :     if (rDoc.IsDocProtected())
      41             :     {
      42           0 :         const ScDocProtection* p = rDoc.GetDocProtection();
      43           0 :         if (!p->isPasswordEmpty() && !p->hasPasswordHash(eHash1, eHash2))
      44           0 :             return true;
      45             :     }
      46             : 
      47           9 :     SCTAB nTabCount = rDoc.GetTableCount();
      48          19 :     for (SCTAB i = 0; i < nTabCount; ++i)
      49             :     {
      50          10 :         const ScTableProtection* p = rDoc.GetTabProtection(i);
      51          10 :         if (!p || !p->isProtected())
      52             :             // Sheet not protected.  Skip it.
      53          10 :             continue;
      54             : 
      55           0 :         if (!p->isPasswordEmpty() && !p->hasPasswordHash(eHash1, eHash2))
      56           0 :             return true;
      57             :     }
      58             : 
      59           9 :     return false;
      60             : }
      61             : 
      62           0 : OUString ScPassHashHelper::getHashURI(ScPasswordHash eHash)
      63             : {
      64           0 :     switch (eHash)
      65             :     {
      66             :         case PASSHASH_SHA1:
      67           0 :             return OUString(URI_SHA1);
      68             :         case PASSHASH_XL:
      69           0 :             return OUString(URI_XLS_LEGACY);
      70             :         case PASSHASH_UNSPECIFIED:
      71             :         default:
      72             :             ;
      73             :     }
      74           0 :     return OUString();
      75             : }
      76             : 
      77           0 : ScPasswordHash ScPassHashHelper::getHashTypeFromURI(const OUString& rURI)
      78             : {
      79           0 :     if ( rURI == URI_SHA1 )
      80           0 :         return PASSHASH_SHA1;
      81           0 :     else if ( rURI == URI_XLS_LEGACY )
      82           0 :         return PASSHASH_XL;
      83           0 :     return PASSHASH_UNSPECIFIED;
      84             : }
      85             : 
      86             : // ============================================================================
      87             : 
      88          29 : ScPassHashProtectable::~ScPassHashProtectable()
      89             : {
      90          29 : }
      91             : 
      92             : // ============================================================================
      93             : 
      94          29 : class ScTableProtectionImpl
      95             : {
      96             : public:
      97             :     static Sequence<sal_Int8> hashPassword(const String& aPassText, ScPasswordHash eHash = PASSHASH_SHA1);
      98             :     static Sequence<sal_Int8> hashPassword(const Sequence<sal_Int8>& rPassHash, ScPasswordHash eHash = PASSHASH_SHA1);
      99             : 
     100             :     explicit ScTableProtectionImpl(SCSIZE nOptSize);
     101             :     explicit ScTableProtectionImpl(const ScTableProtectionImpl& r);
     102             : 
     103             :     bool isProtected() const;
     104             :     bool isProtectedWithPass() const;
     105             :     void setProtected(bool bProtected);
     106             : 
     107             :     bool isPasswordEmpty() const;
     108             :     bool hasPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2 = PASSHASH_UNSPECIFIED) const;
     109             :     void setPassword(const String& aPassText);
     110             :     ::com::sun::star::uno::Sequence<sal_Int8> getPasswordHash(
     111             :         ScPasswordHash eHash, ScPasswordHash eHash2 = PASSHASH_UNSPECIFIED) const;
     112             :     void setPasswordHash(
     113             :         const ::com::sun::star::uno::Sequence<sal_Int8>& aPassword,
     114             :         ScPasswordHash eHash = PASSHASH_SHA1, ScPasswordHash eHash2 = PASSHASH_UNSPECIFIED);
     115             :     bool verifyPassword(const String& aPassText) const;
     116             : 
     117             :     bool isOptionEnabled(SCSIZE nOptId) const;
     118             :     void setOption(SCSIZE nOptId, bool bEnabled);
     119             : 
     120             : private:
     121             :     String maPassText;
     122             :     ::com::sun::star::uno::Sequence<sal_Int8>   maPassHash;
     123             :     ::std::vector<bool> maOptions;
     124             :     bool mbEmptyPass;
     125             :     bool mbProtected;
     126             :     ScPasswordHash meHash1;
     127             :     ScPasswordHash meHash2;
     128             : };
     129             : 
     130           0 : Sequence<sal_Int8> ScTableProtectionImpl::hashPassword(const String& aPassText, ScPasswordHash eHash)
     131             : {
     132           0 :     Sequence<sal_Int8> aHash;
     133           0 :     switch (eHash)
     134             :     {
     135             :         case PASSHASH_XL:
     136           0 :             aHash = ::comphelper::DocPasswordHelper::GetXLHashAsSequence( aPassText, RTL_TEXTENCODING_UTF8 );
     137           0 :         break;
     138             :         case PASSHASH_SHA1:
     139           0 :             SvPasswordHelper::GetHashPassword(aHash, aPassText);
     140           0 :         break;
     141             :         default:
     142             :             ;
     143             :     }
     144           0 :     return aHash;
     145             : }
     146             : 
     147           0 : Sequence<sal_Int8> ScTableProtectionImpl::hashPassword(
     148             :     const Sequence<sal_Int8>& rPassHash, ScPasswordHash eHash)
     149             : {
     150           0 :     if (!rPassHash.getLength() || eHash == PASSHASH_UNSPECIFIED)
     151           0 :         return rPassHash;
     152             : 
     153             :     // TODO: Right now, we only support double-hash by SHA1.
     154           0 :     if (eHash == PASSHASH_SHA1)
     155             :     {
     156           0 :         vector<sal_Char> aChars;
     157           0 :         sal_Int32 n = rPassHash.getLength();
     158           0 :         aChars.reserve(n);
     159           0 :         for (sal_Int32 i = 0; i < n; ++i)
     160           0 :             aChars.push_back(static_cast<sal_Char>(rPassHash[i]));
     161             : 
     162           0 :         Sequence<sal_Int8> aNewHash;
     163           0 :         SvPasswordHelper::GetHashPassword(aNewHash, &aChars[0], aChars.size());
     164           0 :         return aNewHash;
     165             :     }
     166             : 
     167           0 :     return rPassHash;
     168             : }
     169             : 
     170          13 : ScTableProtectionImpl::ScTableProtectionImpl(SCSIZE nOptSize) :
     171             :     maOptions(nOptSize),
     172             :     mbEmptyPass(true),
     173             :     mbProtected(false),
     174             :     meHash1(PASSHASH_SHA1),
     175          13 :     meHash2(PASSHASH_UNSPECIFIED)
     176             : {
     177          13 : }
     178             : 
     179          16 : ScTableProtectionImpl::ScTableProtectionImpl(const ScTableProtectionImpl& r) :
     180             :     maPassText(r.maPassText),
     181             :     maPassHash(r.maPassHash),
     182             :     maOptions(r.maOptions),
     183             :     mbEmptyPass(r.mbEmptyPass),
     184             :     mbProtected(r.mbProtected),
     185             :     meHash1(r.meHash1),
     186          16 :     meHash2(r.meHash2)
     187             : {
     188          16 : }
     189             : 
     190           8 : bool ScTableProtectionImpl::isProtected() const
     191             : {
     192           8 :     return mbProtected;
     193             : }
     194             : 
     195           0 : bool ScTableProtectionImpl::isProtectedWithPass() const
     196             : {
     197           0 :     if (!mbProtected)
     198           0 :         return false;
     199             : 
     200           0 :     return maPassText.Len() || maPassHash.getLength();
     201             : }
     202             : 
     203          15 : void ScTableProtectionImpl::setProtected(bool bProtected)
     204             : {
     205          15 :     mbProtected = bProtected;
     206             :     // We need to keep the old password even when the protection is off.  So,
     207             :     // don't erase the password data here.
     208          15 : }
     209             : 
     210           1 : void ScTableProtectionImpl::setPassword(const String& aPassText)
     211             : {
     212             :     // We can't hash it here because we don't know whether this document will
     213             :     // get saved to Excel or ODF, depending on which we will need to use a
     214             :     // different hashing algorithm.  One alternative is to hash it using all
     215             :     // hash algorithms that we support, and store them all.
     216             : 
     217           1 :     maPassText = aPassText;
     218           1 :     mbEmptyPass = aPassText.Len() == 0;
     219           1 :     if (mbEmptyPass)
     220             :     {
     221           0 :         maPassHash = Sequence<sal_Int8>();
     222             :     }
     223           1 : }
     224             : 
     225           0 : bool ScTableProtectionImpl::isPasswordEmpty() const
     226             : {
     227           0 :     return mbEmptyPass;
     228             : }
     229             : 
     230           0 : bool ScTableProtectionImpl::hasPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2) const
     231             : {
     232           0 :     if (mbEmptyPass)
     233           0 :         return true;
     234             : 
     235           0 :     if (maPassText.Len())
     236           0 :         return true;
     237             : 
     238           0 :     if (meHash1 == eHash)
     239             :     {
     240           0 :         if (meHash2 == PASSHASH_UNSPECIFIED)
     241             :             // single hash.
     242           0 :             return true;
     243             : 
     244           0 :         return meHash2 == eHash2;
     245             :     }
     246             : 
     247           0 :     return false;
     248             : }
     249             : 
     250           0 : Sequence<sal_Int8> ScTableProtectionImpl::getPasswordHash(
     251             :     ScPasswordHash eHash, ScPasswordHash eHash2) const
     252             : {
     253           0 :     Sequence<sal_Int8> aPassHash;
     254             : 
     255           0 :     if (mbEmptyPass)
     256             :         // Flaged as empty.
     257           0 :         return aPassHash;
     258             : 
     259           0 :     if (maPassText.Len())
     260             :     {
     261             :         // Cleartext password exists.  Hash it.
     262           0 :         aPassHash = hashPassword(maPassText, eHash);
     263           0 :         if (eHash2 != PASSHASH_UNSPECIFIED)
     264             :             // Double-hash it.
     265           0 :             aPassHash = hashPassword(aPassHash, eHash2);
     266             : 
     267           0 :         return aPassHash;
     268             :     }
     269             :     else
     270             :     {
     271             :         // No clear text password.  Check if we have a hash value of the right hash type.
     272           0 :         if (meHash1 == eHash)
     273             :         {
     274           0 :             aPassHash = maPassHash;
     275             : 
     276           0 :             if (meHash2 == eHash2)
     277             :                 // Matching double-hash requested.
     278           0 :                 return aPassHash;
     279           0 :             else if (meHash2 == PASSHASH_UNSPECIFIED)
     280             :                 // primary hashing type match.  Double hash it by the requested
     281             :                 // double-hash type.
     282           0 :                 return hashPassword(aPassHash, eHash2);
     283             :         }
     284             :     }
     285             : 
     286             :     // failed.
     287           0 :     return Sequence<sal_Int8>();
     288             : }
     289             : 
     290           0 : void ScTableProtectionImpl::setPasswordHash(
     291             :     const uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash, ScPasswordHash eHash2)
     292             : {
     293           0 :     sal_Int32 nLen = aPassword.getLength();
     294           0 :     mbEmptyPass = nLen <= 0 ? true : false;
     295           0 :     meHash1 = eHash;
     296           0 :     meHash2 = eHash2;
     297           0 :     maPassHash = aPassword;
     298             : 
     299             : #if DEBUG_TAB_PROTECTION
     300             :     for (sal_Int32 i = 0; i < nLen; ++i)
     301             :         printf("%2.2X ", static_cast<sal_uInt8>(aPassword[i]));
     302             :     printf("\n");
     303             : #endif
     304           0 : }
     305             : 
     306           2 : bool ScTableProtectionImpl::verifyPassword(const String& aPassText) const
     307             : {
     308             : #if DEBUG_TAB_PROTECTION
     309             :     fprintf(stdout, "ScTableProtectionImpl::verifyPassword: input = '%s'\n",
     310             :             OUStringToOString(OUString(aPassText), RTL_TEXTENCODING_UTF8).getStr());
     311             : #endif
     312             : 
     313           2 :     if (mbEmptyPass)
     314           0 :         return aPassText.Len() == 0;
     315             : 
     316           2 :     if (maPassText.Len())
     317             :         // Clear text password exists, and this one takes precedence.
     318           2 :         return aPassText.Equals(maPassText);
     319             : 
     320           0 :     Sequence<sal_Int8> aHash = hashPassword(aPassText, meHash1);
     321           0 :     aHash = hashPassword(aHash, meHash2);
     322             : 
     323             : #if DEBUG_TAB_PROTECTION
     324             :     fprintf(stdout, "ScTableProtectionImpl::verifyPassword: hash = ");
     325             :     for (sal_Int32 i = 0; i < aHash.getLength(); ++i)
     326             :         printf("%2.2X ", static_cast<sal_uInt8>(aHash[i]));
     327             :     printf("\n");
     328             : #endif
     329             : 
     330           0 :     return aHash == maPassHash;
     331             : }
     332             : 
     333           0 : bool ScTableProtectionImpl::isOptionEnabled(SCSIZE nOptId) const
     334             : {
     335           0 :     if ( maOptions.size() <= static_cast<size_t>(nOptId) )
     336             :     {
     337             :         OSL_FAIL("ScTableProtectionImpl::isOptionEnabled: wrong size");
     338           0 :         return false;
     339             :     }
     340             : 
     341           0 :     return maOptions[nOptId];
     342             : }
     343             : 
     344         193 : void ScTableProtectionImpl::setOption(SCSIZE nOptId, bool bEnabled)
     345             : {
     346         193 :     if ( maOptions.size() <= static_cast<size_t>(nOptId) )
     347             :     {
     348             :         OSL_FAIL("ScTableProtectionImpl::setOption: wrong size");
     349         193 :         return;
     350             :     }
     351             : 
     352         193 :     maOptions[nOptId] = bEnabled;
     353             : }
     354             : 
     355             : // ============================================================================
     356             : 
     357           2 : ScDocProtection::ScDocProtection() :
     358           2 :     mpImpl(new ScTableProtectionImpl(static_cast<SCSIZE>(ScDocProtection::NONE)))
     359             : {
     360           2 : }
     361             : 
     362           5 : ScDocProtection::ScDocProtection(const ScDocProtection& r) :
     363             :     ScPassHashProtectable(),
     364           5 :     mpImpl(new ScTableProtectionImpl(*r.mpImpl))
     365             : {
     366           5 : }
     367             : 
     368          13 : ScDocProtection::~ScDocProtection()
     369             : {
     370          13 : }
     371             : 
     372           8 : bool ScDocProtection::isProtected() const
     373             : {
     374           8 :     return mpImpl->isProtected();
     375             : }
     376             : 
     377           0 : bool ScDocProtection::isProtectedWithPass() const
     378             : {
     379           0 :     return mpImpl->isProtectedWithPass();
     380             : }
     381             : 
     382           4 : void ScDocProtection::setProtected(bool bProtected)
     383             : {
     384           4 :     mpImpl->setProtected(bProtected);
     385             : 
     386             :     // Currently Calc doesn't support document protection options.  So, let's
     387             :     // assume that when the document is protected, its structure is protected.
     388             :     // We need to do this for Excel export.
     389           4 :     mpImpl->setOption(ScDocProtection::STRUCTURE, bProtected);
     390           4 : }
     391             : 
     392           0 : bool ScDocProtection::isPasswordEmpty() const
     393             : {
     394           0 :     return mpImpl->isPasswordEmpty();
     395             : }
     396             : 
     397           0 : bool ScDocProtection::hasPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2) const
     398             : {
     399           0 :     return mpImpl->hasPasswordHash(eHash, eHash2);
     400             : }
     401             : 
     402           1 : void ScDocProtection::setPassword(const String& aPassText)
     403             : {
     404           1 :     mpImpl->setPassword(aPassText);
     405           1 : }
     406             : 
     407           0 : uno::Sequence<sal_Int8> ScDocProtection::getPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2) const
     408             : {
     409           0 :     return mpImpl->getPasswordHash(eHash, eHash2);
     410             : }
     411             : 
     412           0 : void ScDocProtection::setPasswordHash(
     413             :     const uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash, ScPasswordHash eHash2)
     414             : {
     415           0 :     mpImpl->setPasswordHash(aPassword, eHash, eHash2);
     416           0 : }
     417             : 
     418           2 : bool ScDocProtection::verifyPassword(const String& aPassText) const
     419             : {
     420           2 :     return mpImpl->verifyPassword(aPassText);
     421             : }
     422             : 
     423           0 : bool ScDocProtection::isOptionEnabled(Option eOption) const
     424             : {
     425           0 :     return mpImpl->isOptionEnabled(eOption);
     426             : }
     427             : 
     428           2 : void ScDocProtection::setOption(Option eOption, bool bEnabled)
     429             : {
     430           2 :     mpImpl->setOption(eOption, bEnabled);
     431           2 : }
     432             : 
     433             : // ============================================================================
     434             : 
     435          11 : ScTableProtection::ScTableProtection() :
     436          11 :     mpImpl(new ScTableProtectionImpl(static_cast<SCSIZE>(ScTableProtection::NONE)))
     437             : {
     438             :     // Set default values for the options.
     439          11 :     mpImpl->setOption(SELECT_LOCKED_CELLS,   true);
     440          11 :     mpImpl->setOption(SELECT_UNLOCKED_CELLS, true);
     441          11 : }
     442             : 
     443          11 : ScTableProtection::ScTableProtection(const ScTableProtection& r) :
     444             :     ScPassHashProtectable(),
     445          11 :     mpImpl(new ScTableProtectionImpl(*r.mpImpl))
     446             : {
     447          11 : }
     448             : 
     449          44 : ScTableProtection::~ScTableProtection()
     450             : {
     451          44 : }
     452             : 
     453           0 : bool ScTableProtection::isProtected() const
     454             : {
     455           0 :     return mpImpl->isProtected();
     456             : }
     457             : 
     458           0 : bool ScTableProtection::isProtectedWithPass() const
     459             : {
     460           0 :     return mpImpl->isProtectedWithPass();
     461             : }
     462             : 
     463          11 : void ScTableProtection::setProtected(bool bProtected)
     464             : {
     465          11 :     mpImpl->setProtected(bProtected);
     466          11 : }
     467             : 
     468           0 : bool ScTableProtection::isPasswordEmpty() const
     469             : {
     470           0 :     return mpImpl->isPasswordEmpty();
     471             : }
     472             : 
     473           0 : bool ScTableProtection::hasPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2) const
     474             : {
     475           0 :     return mpImpl->hasPasswordHash(eHash, eHash2);
     476             : }
     477             : 
     478           0 : void ScTableProtection::setPassword(const String& aPassText)
     479             : {
     480           0 :     mpImpl->setPassword(aPassText);
     481           0 : }
     482             : 
     483           0 : Sequence<sal_Int8> ScTableProtection::getPasswordHash(ScPasswordHash eHash, ScPasswordHash eHash2) const
     484             : {
     485           0 :     return mpImpl->getPasswordHash(eHash, eHash2);
     486             : }
     487             : 
     488           0 : void ScTableProtection::setPasswordHash(
     489             :     const uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash, ScPasswordHash eHash2)
     490             : {
     491           0 :     mpImpl->setPasswordHash(aPassword, eHash, eHash2);
     492           0 : }
     493             : 
     494           0 : bool ScTableProtection::verifyPassword(const String& aPassText) const
     495             : {
     496           0 :     return mpImpl->verifyPassword(aPassText);
     497             : }
     498             : 
     499           0 : bool ScTableProtection::isOptionEnabled(Option eOption) const
     500             : {
     501           0 :     return mpImpl->isOptionEnabled(eOption);
     502             : }
     503             : 
     504         165 : void ScTableProtection::setOption(Option eOption, bool bEnabled)
     505             : {
     506         165 :     mpImpl->setOption(eOption, bEnabled);
     507         165 : }
     508             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10