Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/oox/source/crypto/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 7 kB image not shown  

Quelle  DocumentDecryption.cxx   Sprache: C

 
/* -*- 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/.
 *
 */


#include <oox/crypto/DocumentDecryption.hxx>

#include <comphelper/sequenceashashmap.hxx>

#include <com/sun/star/beans/NamedValue.hpp>
#include <com/sun/star/io/XSeekable.hpp>
#include <com/sun/star/io/XStream.hpp>
#include <com/sun/star/io/IOException.hpp>
#include <com/sun/star/uno/XComponentContext.hpp>
#include <com/sun/star/packages/XPackageEncryption.hpp>
#include <oox/ole/olestorage.hxx>
#include <oox/helper/binaryinputstream.hxx>

#include <sal/log.hxx>
#include <utility>

namespace
{
void lcl_getListOfStreams(oox::StorageBase* pStorage, std::vector<OUString>& rElementNames)
{
    std::vector<OUString> oElementNames;
    pStorage->getElementNames(oElementNames);
    for (const auto& sName : oElementNames)
    {
        oox::StorageRef rSubStorage = pStorage->openSubStorage(sName, false);
        if (rSubStorage && rSubStorage->isStorage())
        {
            lcl_getListOfStreams(rSubStorage.get(), rElementNames);
        }
        else
        {
            if (pStorage->isRootStorage())
                rElementNames.push_back(sName);
            else
                rElementNames.push_back(pStorage->getPath() + "/" + sName);
        }
    }
}
}

namespace oox::crypto
{
using namespace css;

DocumentDecryption::DocumentDecryption(css::uno::Reference<css::uno::XComponentContext> xContext,
                                       oox::ole::OleStorage& rOleStorage)
    : mxContext(std::move(xContext))
    , mrOleStorage(rOleStorage)
{
    // Get OLE streams into sequences for later use in CryptoEngine
    std::vector<OUString> aStreamNames;
    lcl_getListOfStreams(&mrOleStorage, aStreamNames);

    comphelper::SequenceAsHashMap aStreamsData;
    for (const auto& sStreamName : aStreamNames)
    {
        uno::Reference<io::XInputStream> xStream = mrOleStorage.openInputStream(sStreamName);
        if (!xStream.is())
            throw io::IOException("Cannot open OLE input stream for " + sStreamName + "!");

        BinaryXInputStream aBinaryInputStream(xStream, true);

        css::uno::Sequence<sal_Int8> oData;
        sal_Int32 nStreamSize = aBinaryInputStream.size();
        sal_Int32 nReadBytes = aBinaryInputStream.readData(oData, nStreamSize);

        if (nStreamSize != nReadBytes)
        {
            SAL_WARN("oox""OLE stream invalid content");
            throw io::IOException("OLE stream invalid content for " + sStreamName + "!");
        }

        aStreamsData[sStreamName] <<= oData;
    }
    maStreamsSequence = aStreamsData.getAsConstNamedValueList();
}

bool DocumentDecryption::generateEncryptionKey(const OUString& rPassword)
{
    if (mxPackageEncryption.is())
        return mxPackageEncryption->generateEncryptionKey(rPassword);
    return false;
}

bool DocumentDecryption::readEncryptionInfo()
{
    if (!mrOleStorage.isStorage())
        return false;

    // Read 0x6DataSpaces/DataSpaceMap
    uno::Reference<io::XInputStream> xDataSpaceMap
        = mrOleStorage.openInputStream(u"\006DataSpaces/DataSpaceMap"_ustr);
    OUString sDataSpaceName;

    if (xDataSpaceMap.is())
    {
        bool bBroken = false;

        BinaryXInputStream aDataSpaceStream(xDataSpaceMap, true);
        sal_uInt32 aHeaderLength = aDataSpaceStream.readuInt32();
        SAL_WARN_IF(aHeaderLength != 8, "oox",
                    "DataSpaceMap length != 8 is not supported. Some content may be skipped");
        sal_uInt32 aEntryCount = aDataSpaceStream.readuInt32();
        SAL_WARN_IF(aEntryCount != 1, "oox",
                    "DataSpaceMap contains more than one entry. Some content may be skipped");

        // Read each DataSpaceMapEntry (MS-OFFCRYPTO 2.1.6.1)
        for (sal_uInt32 i = 0; i < aEntryCount && !bBroken; i++)
        {
            // entryLen unused for the moment
            aDataSpaceStream.skip(sizeof(sal_uInt32));

            // Read each DataSpaceReferenceComponent (MS-OFFCRYPTO 2.1.6.2)
            sal_uInt32 aReferenceComponentCount = aDataSpaceStream.readuInt32();
            for (sal_uInt32 j = 0; j < aReferenceComponentCount && !bBroken; j++)
            {
                // Read next reference component
                // refComponentType unused for the moment
                aDataSpaceStream.skip(sizeof(sal_uInt32));
                sal_uInt32 aReferenceComponentNameLength = aDataSpaceStream.readuInt32();
                // sReferenceComponentName unused for the moment
                if (aDataSpaceStream.getRemaining() < aReferenceComponentNameLength)
                {
                    bBroken = true;
                    break;
                }
                aDataSpaceStream.readUnicodeArray(aReferenceComponentNameLength / 2);
                aDataSpaceStream.skip((4 - (aReferenceComponentNameLength & 3))
                                      & 3); // Skip padding

                bBroken |= aDataSpaceStream.isEof();
            }

            sal_uInt32 aDataSpaceNameLength = aDataSpaceStream.readuInt32();
            if (aDataSpaceStream.getRemaining() < aDataSpaceNameLength)
            {
                bBroken = true;
                break;
            }
            sDataSpaceName = aDataSpaceStream.readUnicodeArray(aDataSpaceNameLength / 2);
            aDataSpaceStream.skip((4 - (aDataSpaceNameLength & 3)) & 3); // Skip padding

            bBroken |= aDataSpaceStream.isEof();
        }

        if (bBroken)
        {
            SAL_WARN("oox""EOF on parsing DataSpaceMapEntry table");
            return false;
        }
    }
    else
    {
        // Fallback for documents generated by LO: they sometimes do not have all
        // required by MS-OFFCRYPTO specification streams (0x6DataSpaces/DataSpaceMap and others)
        SAL_WARN("oox""Encrypted package does not contain DataSpaceMap");
        sDataSpaceName = "StrongEncryptionDataSpace";
    }

    uno::Sequence<uno::Any> aArguments;
    mxPackageEncryption.set(
        mxContext->getServiceManager()->createInstanceWithArgumentsAndContext(
            "com.sun.star.comp.oox.crypto." + sDataSpaceName, aArguments, mxContext),
        css::uno::UNO_QUERY);

    if (!mxPackageEncryption.is())
    {
        // we do not know how to decrypt this document
        return false;
    }

    return mxPackageEncryption->readEncryptionInfo(maStreamsSequence);
}

uno::Sequence<beans::NamedValue> DocumentDecryption::createEncryptionData(const OUString& rPassword)
{
    if (!mxPackageEncryption.is())
        return uno::Sequence<beans::NamedValue>();

    return mxPackageEncryption->createEncryptionData(rPassword);
}

bool DocumentDecryption::decrypt(const uno::Reference<io::XStream>& xDocumentStream)
{
    bool bResult = false;

    if (!mrOleStorage.isStorage())
        return false;

    if (!mxPackageEncryption.is())
        return false;

    // open the required input streams in the encrypted package
    uno::Reference<io::XInputStream> xEncryptedPackage
        = mrOleStorage.openInputStream(u"EncryptedPackage"_ustr);

    // create temporary file for unencrypted package
    uno::Reference<io::XOutputStream> xDecryptedPackage = xDocumentStream->getOutputStream();

    bResult = mxPackageEncryption->decrypt(xEncryptedPackage, xDecryptedPackage);

    css::uno::Reference<io::XSeekable> xSeekable(xDecryptedPackage, css::uno::UNO_QUERY);
    xSeekable->seek(0);

    if (bResult)
        return mxPackageEncryption->checkDataIntegrity();

    return bResult;
}

// namespace oox::crypto

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=96 H=99 G=97

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

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.