/* -*- 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 namespace com::sun::star::graphic { class XGraphic; } using namespace css; using namespace css::uno; using namespace css::graphic; /* protected: for signature generation */ OUString XSecController::createId() { sal_uInt8 aSeq[16]; rtl_createUuid( aSeq, nullptr, true ); char str[68]="ID_"; int length = 3; for (sal_uInt8 i : aSeq) { SAL_WNODEPRECATED_DECLARATIONS_PUSH // sprintf (macOS 13 SDK) length += sprintf(str+length, "%04x", i); SAL_WNODEPRECATED_DECLARATIONS_POP } return OUString::createFromAscii(str); } css::uno::Reference< css::xml::crypto::sax::XReferenceResolvedListener > XSecController::prepareSignatureToWrite( InternalSignatureInformation& internalSignatureInfor, sal_Int32 nStorageFormat, bool bXAdESCompliantIfODF) { sal_Int32 nSecurityId = internalSignatureInfor.signatureInfor.nSecurityId; SignatureReferenceInformations& vReferenceInfors = internalSignatureInfor.signatureInfor.vSignatureReferenceInfors; sal_Int32 nIdOfSignatureElementCollector; nIdOfSignatureElementCollector = m_xSAXEventKeeper->addSecurityElementCollector( css::xml::crypto::sax::ElementMarkPriority_AFTERMODIFY, true ); m_xSAXEventKeeper->setSecurityId(nIdOfSignatureElementCollector, nSecurityId); rtl::Reference xSignatureCreator(new SignatureCreatorImpl); css::uno::Sequence args { Any(OUString::number(nSecurityId)), Any(uno::Reference(m_xSAXEventKeeper)), Any(OUString::number(nIdOfSignatureElementCollector)), //for nss, the internal module is used for signing, which needs to be improved later Any(m_xSecurityContext->getSecurityEnvironment()), Any(m_xXMLSignature) }; xSignatureCreator->initialize(args); sal_Int32 nBlockerId = m_xSAXEventKeeper->addBlocker(); m_xSAXEventKeeper->setSecurityId(nBlockerId, nSecurityId); xSignatureCreator->setBlockerId(nBlockerId); xSignatureCreator->addSignatureCreationResultListener(this); m_xSAXEventKeeper->addReferenceResolvedListener(nIdOfSignatureElementCollector, xSignatureCreator); int size = vReferenceInfors.size(); sal_Int32 nReferenceCount = 0; for(int i=0; isetSecurityId(keeperId, nSecurityId); m_xSAXEventKeeper->addReferenceResolvedListener( keeperId, xSignatureCreator); xSignatureCreator->setReferenceId( keeperId ); nReferenceCount++; } } xSignatureCreator->setReferenceCount( nReferenceCount ); /* * adds all URI binding */ for(int i=0; i xInputStream = getObjectInputStream( refInfor.ouURI ); if (xInputStream.is()) xSignatureCreator->setUriBinding(refInfor.ouURI,xInputStream); } xSignatureCreator->setKeyId(0); // use sha512 for gpg signing unconditionally const sal_Int32 digestID = !internalSignatureInfor.signatureInfor.ouGpgCertificate.isEmpty()? css::xml::crypto::DigestID::SHA512 : (bXAdESCompliantIfODF ? css::xml::crypto::DigestID::SHA256 : css::xml::crypto::DigestID::SHA1); if (nStorageFormat != embed::StorageFormats::OFOPXML) { internalSignatureInfor.signatureInfor.ouSignatureId = createId(); internalSignatureInfor.signatureInfor.ouDateTimePropertyId = createId(); internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, internalSignatureInfor.signatureInfor.ouDateTimePropertyId, -1, OUString() ); size++; if (bXAdESCompliantIfODF) { OUString aId = "idSignedProperties_" + internalSignatureInfor.signatureInfor.ouSignatureId; // We write a new reference, so it's possible to use the correct type URI. internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, aId, -1, u"http://uri.etsi.org/01903#SignedProperties"_ustr); size++; } if (!internalSignatureInfor.signatureInfor.ouDescription.isEmpty()) { // Only mention the hash of the description in the signature if it's non-empty. internalSignatureInfor.signatureInfor.ouDescriptionPropertyId = createId(); internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, internalSignatureInfor.signatureInfor.ouDescriptionPropertyId, -1, OUString()); size++; } } else // OOXML { OUString aID = createId(); internalSignatureInfor.signatureInfor.ouSignatureId = aID; internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idPackageObject_" + aID, -1, OUString()); size++; internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idOfficeObject_" + aID, -1, OUString()); size++; internalSignatureInfor.addReference(SignatureReferenceType::SAMEDOCUMENT, digestID, "idSignedProperties_" + aID, -1, OUString()); size++; } /* * replace both digestValues and signatureValue to " " */ for(int i=0; i& xValidGraphic) { int nIndex = findSignatureInfor(nSecurityId); if (nIndex == -1) { InternalSignatureInformation aInformation(nSecurityId, nullptr); aInformation.signatureInfor.aValidSignatureImage = xValidGraphic; m_vInternalSignatureInformations.push_back(aInformation); } else { SignatureInformation& rInformation = m_vInternalSignatureInformations[nIndex].signatureInfor; rInformation.aValidSignatureImage = xValidGraphic; } } void XSecController::setSignatureLineInvalidGraphic( sal_Int32 nSecurityId, const Reference& xInvalidGraphic) { int nIndex = findSignatureInfor(nSecurityId); if (nIndex == -1) { InternalSignatureInformation aInformation(nSecurityId, nullptr); aInformation.signatureInfor.aInvalidSignatureImage = xInvalidGraphic; m_vInternalSignatureInformations.push_back(aInformation); } else { SignatureInformation& rInformation = m_vInternalSignatureInformations[nIndex].signatureInfor; rInformation.aInvalidSignatureImage = xInvalidGraphic; } } bool XSecController::WriteSignature( const css::uno::Reference& xDocumentHandler, bool bXAdESCompliantIfODF ) { bool rc = false; SAL_WARN_IF( !xDocumentHandler.is(), "xmlsecurity.helper", "I really need a document handler!" ); /* * chain the SAXEventKeeper to the SAX chain */ chainOn(); if ( m_eStatusOfSecurityComponents == InitializationState::INITIALIZED ) /* * if all security components are ready, add the signature * stream. */ { m_bIsSAXEventKeeperSticky = true; m_xSAXEventKeeper->setNextHandler(xDocumentHandler); try { /* * export the signature template */ css::uno::Reference xSEKHandler(m_xSAXEventKeeper); int i; int sigNum = m_vInternalSignatureInformations.size(); for (i=0; isetNextHandler( nullptr ); m_bIsSAXEventKeeperSticky = false; } return rc; } bool XSecController::WriteOOXMLSignature(const uno::Reference& xRootStorage, const uno::Reference& xDocumentHandler) { bool bRet = false; SAL_WARN_IF(!xDocumentHandler.is(), "xmlsecurity.helper", "empty xDocumentHandler reference"); // Chain the SAXEventKeeper to the SAX chain. chainOn(); if (m_eStatusOfSecurityComponents == InitializationState::INITIALIZED) { m_bIsSAXEventKeeperSticky = true; m_xSAXEventKeeper->setNextHandler(xDocumentHandler); try { // Export the signature template. css::uno::Reference xSEKHandler(m_xSAXEventKeeper); for (InternalSignatureInformation & rInformation : m_vInternalSignatureInformations) { // Prepare the signature creator. rInformation.xReferenceResolvedListener = prepareSignatureToWrite(rInformation, embed::StorageFormats::OFOPXML, false); exportOOXMLSignature(xRootStorage, xSEKHandler, rInformation.signatureInfor); } m_bIsSAXEventKeeperSticky = false; chainOff(); bRet = true; } catch(const uno::Exception&) { } m_xSAXEventKeeper->setNextHandler(nullptr); m_bIsSAXEventKeeperSticky = false; } return bRet; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */