The OpenOffice.org Document Signatures

Test Integration

Version 0.1, October 2003

Michael Mi

Andrew Fan

DEPRECATED

This document describes how first implementations of the

OOo XML Security Framework

where integrated into OpenOffice.org for testing purpose.

This is not how it is really done in OpenOffice.org.

The current implementation in described in

OpenDocumentSignatures.sxw

When saving a writer file, give id attribute to each xml stream, including meta.xml, styles.xml, settings.xml and connent.xml.

Modify the file source/core/xmlexp.cxx in xmloff project, add following lines to the method SvXMLExport::exportDoc.

sal_uInt32 SvXMLExport::exportDoc( enum ::xmloff::token::XMLTokenEnum eClass )

{

...

// namespace attributes

// ( The namespace decls should be first attributes in the element;

// some faulty XML parsers (JAXP1.1) have a problem with this,

// also it's more elegant )

sal_uInt16 nPos = pNamespaceMap->GetFirstKey();

while( USHRT_MAX != nPos )

{

pAttrList->AddAttribute( pNamespaceMap->GetAttrNameByKey( nPos ),

pNamespaceMap->GetNameByKey( nPos ) );

nPos = pNamespaceMap->GetNextKey( nPos );

}

// add id attribute.

{

const sal_Int32 nExportMode = mnExportFlags & (EXPORT_META|EXPORT_STYLES|EXPORT_CONTENT|EXPORT_SETTINGS);

OUString idStr(RTL_CONSTASCII_USTRINGPARAM("id"));

if( EXPORT_META == nExportMode )

{

// export only meta

pAttrList->AddAttribute( idStr, OUString(RTL_CONSTASCII_USTRINGPARAM("meta_id")));

}

else if ( EXPORT_SETTINGS == nExportMode )

{

// export only settings

pAttrList->AddAttribute( idStr, OUString(RTL_CONSTASCII_USTRINGPARAM("settings_id")));

}

else if( EXPORT_STYLES == nExportMode )

{

// export only styles

pAttrList->AddAttribute( idStr, OUString(RTL_CONSTASCII_USTRINGPARAM("styles_id")));

}

else if( EXPORT_CONTENT == nExportMode )

{

// export only content

pAttrList->AddAttribute( idStr, OUString(RTL_CONSTASCII_USTRINGPARAM("content_id")));

}

}

...

}

Add xml security related part into the saving process

The saving process is in sw project. Two methods in the file source/filter/xml/wrtxml.cxx are involved, they are

sal_uInt32 SwXMLWriter::_Write()

and

sal_Bool SwXMLWriter::WriteThroughComponent(

const Reference<io::XOutputStream> & xOutputStream,

const Reference<XComponent> & xComponent,

const Reference<XMultiServiceFactory> & rFactory,

const sal_Char* pServiceName,

const Sequence<Any> & rArguments,

const Sequence<PropertyValue> & rMediaDesc )

Modify the _Write method

Following operations are added to the method:

create xml security components

buffer the meta stream

buffer the style stream

buffer the setting stream

buffer the content stream

generate the signature stream.

New lines are highlighted by blue color.

sal_uInt32 SwXMLWriter::_Write()

{

...

// properties

Sequence < PropertyValue > aProps( pOrigFileName ? 1 : 0 );

if( pOrigFileName )

{

PropertyValue *pProps = aProps.getArray();

pProps->Name = OUString( RTL_CONSTASCII_USTRINGPARAM("FileName") );

(pProps++)->Value <<= OUString( *pOrigFileName );

}

// Create xmlsecurity component

createXSecComponent( xServiceFactory );

...

if( !bOrganizerMode && !bBlock &&

SFX_CREATE_MODE_EMBEDDED != pDoc->GetDocShell()->GetCreateMode() )

{

// buffer the meta stream

metaKeeperId = xSAXEventKeeper->addSecurityElementCollector(

ConstOfPriority::PRI_AFTERMODIFY,

sal_False);

if( !WriteThroughComponent(

xModelComp, "meta.xml", xServiceFactory,

"com.sun.star.comp.Writer.XMLMetaExporter",

aEmptyArgs, aProps, sal_True ) )

{

bWarn = sal_True;

sWarnFile = String( RTL_CONSTASCII_STRINGPARAM("meta.xml"),

RTL_TEXTENCODING_ASCII_US );

}

}

// buffer the style stream

stylesKeeperId = xSAXEventKeeper->addSecurityElementCollector(

ConstOfPriority::PRI_AFTERMODIFY,

sal_False);

if( !WriteThroughComponent(

xModelComp, "styles.xml", xServiceFactory,

"com.sun.star.comp.Writer.XMLStylesExporter",

aFilterArgs, aProps, sal_False ) )

{

bErr = sal_True;

sErrFile = String( RTL_CONSTASCII_STRINGPARAM("styles.xml"),

RTL_TEXTENCODING_ASCII_US );

}

if( !bErr )

{

if( !bBlock )

{

// buffer the setting stream

settingsKeeperId = xSAXEventKeeper->addSecurityElementCollector(

ConstOfPriority::PRI_AFTERMODIFY,

sal_False);

if( !WriteThroughComponent(

xModelComp, "settings.xml", xServiceFactory,

"com.sun.star.comp.Writer.XMLSettingsExporter",

aEmptyArgs, aProps, sal_False ) )

{

...

}

}

}

if( !bOrganizerMode && !bErr )

{

// buffer the content stream

contentKeeperId = xSAXEventKeeper->addSecurityElementCollector(

ConstOfPriority::PRI_AFTERMODIFY,

sal_False);

if( !WriteThroughComponent(

xModelComp, "content.xml", xServiceFactory,

"com.sun.star.comp.Writer.XMLContentExporter",

aFilterArgs, aProps, sal_False ) )

{

...

RTL_TEXTENCODING_ASCII_US );

}

}

// create the signature stream

WriteSignatue(

"signature.xml",

xServiceFactory,

sal_False,

pStg );

...

}

The createXSecComponent method is used to created all xml security related component, including SAXEventKeeper, XMLDocumentWrapper, etc.

The WriteSignature method is used to create the signature stream.

Both methods are defined in the xsecctl.cxx, which will be attached with this document.

Modify the WriteThroughComponent method

Following operations are added to the method:

chain the SAXEventKeeper to the SAX chain

unchain the SAXEventKeeper from the SAX chain

New lines are highlighted by blue color.

sal_Bool SwXMLWriter::WriteThroughComponent(

...

)

{

...

aArgs[0] <<= xDocHandler;

for(sal_Int32 i = 0; i < rArguments.getLength(); i++)

aArgs[i+1] = rArguments[i];

// chain the SAXEventKeeper to the SAX chain

ASSERT( xSAXEventKeeper.is(), "the SAXEventKeeper is NULL" );

Reference<xml::sax::XDocumentHandler> xSEKHandler( xSAXEventKeeper,UNO_QUERY);

xSAXEventKeeper->setNextHandler(xDocHandler);

aArgs[0] <<= xSEKHandler;

...

// get filter component

Reference< document::XExporter > xExporter(

rFactory->createInstanceWithArguments(

OUString::createFromAscii(pServiceName), aArgs), UNO_QUERY);

...

return xFilter->filter( rMediaDesc );

// unchain the SAXEventKeeper from the SAX chain

sal_Bool rc = xFilter->filter( rMediaDesc );

xSAXEventKeeper->setNextHandler( NULL );

return rc;

}

Add xml security related part into the loading process

The loading process is in sw project. Two methods in the file source/filter/xml/swxml.cxx are involved, they are

// read a component (file + filter version)

sal_Int32 ReadThroughComponent(...)

and

sal_uInt32 XMLReader::Read( SwDoc &rDoc, SwPaM &rPaM, const String & rName )

Modify the _Read method

Following operations are added to the method:

create xml security components

buffer the meta stream

buffer the setting stream

buffer the style stream

buffer the content stream

verify the signature stream.

New lines are highlighted by blue color.

sal_uInt32 XMLReader::Read( SwDoc &rDoc, SwPaM &rPaM, const String & rName )

{

...

// force redline mode to "none"

rDoc.SetRedlineMode_intern( REDLINE_NONE );

// create xmlsecurity component

createXSecComponent( xServiceFactory );

sal_uInt32 nWarn = 0;

sal_uInt32 nWarn2 = 0;

// read storage streams

if( !(IsOrganizerMode() || IsBlockMode() || aOpt.IsFmtsOnly() ||

bInsertMode) )

{

// buffer the meta stream

metaKeeperId = xSAXEventKeeper->addSecurityElementCollector(

ConstOfPriority::PRI_BEFOREMODIFY,

sal_False);

nWarn = ReadThroughComponent(

pStorage, xModelComp, "meta.xml", "Meta.xml", xServiceFactory,

"com.sun.star.comp.Writer.XMLMetaImporter",

aEmptyArgs, rName, sal_False, IsBlockMode(), xInsertTextRange,

aOpt.IsFmtsOnly(), nStyleFamilyMask, aOpt.IsMerge(),

sal_False );

// buffer the setting stream

settingsKeeperId = xSAXEventKeeper->addSecurityElementCollector(

ConstOfPriority::PRI_BEFOREMODIFY,

sal_False);

nWarn2 = ReadThroughComponent(

pStorage, xModelComp, "settings.xml", NULL, xServiceFactory,

"com.sun.star.comp.Writer.XMLSettingsImporter",

aFilterArgs, rName, sal_False, IsBlockMode(), xInsertTextRange,

aOpt.IsFmtsOnly(), nStyleFamilyMask, aOpt.IsMerge(),

IsOrganizerMode() );

}

// buffer the style stream

stylesKeeperId = xSAXEventKeeper->addSecurityElementCollector(

ConstOfPriority::PRI_BEFOREMODIFY,

sal_False);

nRet = ReadThroughComponent(

pStorage, xModelComp, "styles.xml", NULL, xServiceFactory,

"com.sun.star.comp.Writer.XMLStylesImporter",

aFilterArgs, rName, sal_True, IsBlockMode(), xInsertTextRange,

aOpt.IsFmtsOnly(), nStyleFamilyMask, aOpt.IsMerge(),

IsOrganizerMode() );

if( !nRet && !(IsOrganizerMode() || aOpt.IsFmtsOnly()) )

{

// buffer the content stream

contentKeeperId = xSAXEventKeeper->addSecurityElementCollector(

ConstOfPriority::PRI_BEFOREMODIFY,

sal_False);

nRet = ReadThroughComponent(

pStorage, xModelComp, "content.xml", "Content.xml", xServiceFactory,

"com.sun.star.comp.Writer.XMLContentImporter",

aFilterArgs, rName, sal_True, IsBlockMode(), xInsertTextRange,

aOpt.IsFmtsOnly(), nStyleFamilyMask, aOpt.IsMerge(),

sal_False );

}

// verify the signature stream

ReadSignatue(

"signature.xml",

xServiceFactory,

sal_False,

pStorage,

rName );

...

}

The ReadSignature method is used to try to read and verify the signature stream. It is defined in the xsecctl.cxx, which will be attached with this document.

Modify the ReadThroughComponent method

Following operations are added to the method:

chain the SAXEventKeeper to the SAX chain

unchain the SAXEventKeeper from the SAX chain

New lines are highlighted by blue color.

/// read a component (file + filter version)

sal_Int32 ReadThroughComponent(

...

)

{

...

if( !xFilter.is() )

return ERR_SWG_READ_ERROR;

RTL_LOGFILE_CONTEXT_TRACE1( aLog, "%s created", pFilterName );

// connect parser and filter

xParser->setDocumentHandler( xFilter );

// chain the SAXEventKeeper to the SAX chain

ASSERT( xSAXEventKeeper.is(), "the SAXEventKeeper is NULL" );

xSAXEventKeeper->setNextHandler(xFilter);

Reference<xml::sax::XDocumentHandler> xSEKHandler( xSAXEventKeeper,UNO_QUERY);

xParser->setDocumentHandler( xSEKHandler );

...

// unchain the SAXEventKeeper from the SAX chain

xSAXEventKeeper->setNextHandler( NULL );

return 0;

}

Attachment

/sw/source/filter/xml/xsecctl.hxx

/sw/source/filter/xml/xsecctl.cxx

/sw/source/filter/xml/makefile.mk

(these two xsec... files are new files to sw module, and they are added to the makefile.mk in the sw/source/filter/xml folder.)

/sw/source/filter/xml/swxml.cxx

/sw/source/filter/xml/wrtxml.cxx

(these two files are modified, they belong to the sw module.)

/xmloff/source/core/xmlexp.cxx

(above file is modified, it belongs to the xmloff module.)

6/6

1995-11-21T17:41:00

Malte Timmermann