1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER( update_precomp.py ): autogen include statement, do not remove 25 #include "precompiled_package.hxx" 26 #include <ManifestImport.hxx> 27 #include <ManifestDefines.hxx> 28 #include <Base64Codec.hxx> 29 30 #include <com/sun/star/xml/sax/XAttributeList.hpp> 31 #include <com/sun/star/xml/crypto/DigestID.hpp> 32 #include <com/sun/star/xml/crypto/CipherID.hpp> 33 #include <com/sun/star/beans/PropertyValue.hpp> 34 35 using namespace com::sun::star::uno; 36 using namespace com::sun::star::beans; 37 using namespace com::sun::star; 38 using namespace rtl; 39 using namespace std; 40 41 // --------------------------------------------------- 42 ManifestImport::ManifestImport( vector < Sequence < PropertyValue > > & rNewManVector ) 43 : nNumProperty ( 0 ) 44 , bIgnoreEncryptData ( sal_False ) 45 , nDerivedKeySize( 0 ) 46 , rManVector ( rNewManVector ) 47 48 , sFileEntryElement ( RTL_CONSTASCII_USTRINGPARAM ( ELEMENT_FILE_ENTRY ) ) 49 , sManifestElement ( RTL_CONSTASCII_USTRINGPARAM ( ELEMENT_MANIFEST ) ) 50 , sEncryptionDataElement( RTL_CONSTASCII_USTRINGPARAM ( ELEMENT_ENCRYPTION_DATA ) ) 51 , sAlgorithmElement ( RTL_CONSTASCII_USTRINGPARAM ( ELEMENT_ALGORITHM ) ) 52 , sStartKeyAlgElement ( RTL_CONSTASCII_USTRINGPARAM ( ELEMENT_START_KEY_GENERATION ) ) 53 , sKeyDerivationElement( RTL_CONSTASCII_USTRINGPARAM ( ELEMENT_KEY_DERIVATION ) ) 54 55 , sCdataAttribute ( RTL_CONSTASCII_USTRINGPARAM ( ATTRIBUTE_CDATA ) ) 56 , sMediaTypeAttribute ( RTL_CONSTASCII_USTRINGPARAM ( ATTRIBUTE_MEDIA_TYPE ) ) 57 , sVersionAttribute ( RTL_CONSTASCII_USTRINGPARAM ( ATTRIBUTE_VERSION ) ) 58 , sFullPathAttribute ( RTL_CONSTASCII_USTRINGPARAM ( ATTRIBUTE_FULL_PATH ) ) 59 , sSizeAttribute ( RTL_CONSTASCII_USTRINGPARAM ( ATTRIBUTE_SIZE ) ) 60 , sSaltAttribute ( RTL_CONSTASCII_USTRINGPARAM ( ATTRIBUTE_SALT ) ) 61 , sInitialisationVectorAttribute ( RTL_CONSTASCII_USTRINGPARAM ( ATTRIBUTE_INITIALISATION_VECTOR ) ) 62 , sIterationCountAttribute ( RTL_CONSTASCII_USTRINGPARAM ( ATTRIBUTE_ITERATION_COUNT ) ) 63 , sKeySizeAttribute ( RTL_CONSTASCII_USTRINGPARAM ( ATTRIBUTE_KEY_SIZE ) ) 64 , sAlgorithmNameAttribute ( RTL_CONSTASCII_USTRINGPARAM ( ATTRIBUTE_ALGORITHM_NAME ) ) 65 , sStartKeyAlgNameAttribute ( RTL_CONSTASCII_USTRINGPARAM ( ATTRIBUTE_START_KEY_GENERATION_NAME ) ) 66 , sKeyDerivationNameAttribute ( RTL_CONSTASCII_USTRINGPARAM ( ATTRIBUTE_KEY_DERIVATION_NAME ) ) 67 , sChecksumAttribute ( RTL_CONSTASCII_USTRINGPARAM ( ATTRIBUTE_CHECKSUM ) ) 68 , sChecksumTypeAttribute ( RTL_CONSTASCII_USTRINGPARAM ( ATTRIBUTE_CHECKSUM_TYPE ) ) 69 70 , sFullPathProperty ( RTL_CONSTASCII_USTRINGPARAM ( "FullPath" ) ) 71 , sMediaTypeProperty ( RTL_CONSTASCII_USTRINGPARAM ( "MediaType" ) ) 72 , sVersionProperty ( RTL_CONSTASCII_USTRINGPARAM ( "Version" ) ) 73 , sIterationCountProperty ( RTL_CONSTASCII_USTRINGPARAM ( "IterationCount" ) ) 74 , sDerivedKeySizeProperty ( RTL_CONSTASCII_USTRINGPARAM ( "DerivedKeySize" ) ) 75 , sSaltProperty ( RTL_CONSTASCII_USTRINGPARAM ( "Salt" ) ) 76 , sInitialisationVectorProperty ( RTL_CONSTASCII_USTRINGPARAM ( "InitialisationVector" ) ) 77 , sSizeProperty ( RTL_CONSTASCII_USTRINGPARAM ( "Size" ) ) 78 , sDigestProperty ( RTL_CONSTASCII_USTRINGPARAM ( "Digest" ) ) 79 , sEncryptionAlgProperty ( RTL_CONSTASCII_USTRINGPARAM ( "EncryptionAlgorithm" ) ) 80 , sStartKeyAlgProperty ( RTL_CONSTASCII_USTRINGPARAM ( "StartKeyAlgorithm" ) ) 81 , sDigestAlgProperty ( RTL_CONSTASCII_USTRINGPARAM ( "DigestAlgorithm" ) ) 82 83 , sWhiteSpace ( RTL_CONSTASCII_USTRINGPARAM ( " " ) ) 84 85 , sSHA256_URL ( RTL_CONSTASCII_USTRINGPARAM ( SHA256_URL ) ) 86 , sSHA1_Name ( RTL_CONSTASCII_USTRINGPARAM ( SHA1_NAME ) ) 87 , sSHA1_URL ( RTL_CONSTASCII_USTRINGPARAM ( SHA1_URL ) ) 88 89 , sSHA256_1k_URL ( RTL_CONSTASCII_USTRINGPARAM ( SHA256_1K_URL ) ) 90 , sSHA1_1k_Name ( RTL_CONSTASCII_USTRINGPARAM ( SHA1_1K_NAME ) ) 91 , sSHA1_1k_URL ( RTL_CONSTASCII_USTRINGPARAM ( SHA1_1K_URL ) ) 92 93 , sBlowfish_Name ( RTL_CONSTASCII_USTRINGPARAM ( BLOWFISH_NAME ) ) 94 , sBlowfish_URL ( RTL_CONSTASCII_USTRINGPARAM ( BLOWFISH_URL ) ) 95 , sAES128_URL ( RTL_CONSTASCII_USTRINGPARAM ( AES128_URL ) ) 96 , sAES192_URL ( RTL_CONSTASCII_USTRINGPARAM ( AES192_URL ) ) 97 , sAES256_URL ( RTL_CONSTASCII_USTRINGPARAM ( AES256_URL ) ) 98 99 , sPBKDF2_Name ( RTL_CONSTASCII_USTRINGPARAM ( PBKDF2_NAME ) ) 100 , sPBKDF2_URL ( RTL_CONSTASCII_USTRINGPARAM ( PBKDF2_URL ) ) 101 { 102 aStack.reserve( 10 ); 103 } 104 105 // --------------------------------------------------- 106 ManifestImport::~ManifestImport ( void ) 107 { 108 } 109 110 // --------------------------------------------------- 111 void SAL_CALL ManifestImport::startDocument( ) 112 throw( xml::sax::SAXException, uno::RuntimeException ) 113 { 114 } 115 116 // --------------------------------------------------- 117 void SAL_CALL ManifestImport::endDocument( ) 118 throw( xml::sax::SAXException, uno::RuntimeException ) 119 { 120 } 121 122 // --------------------------------------------------- 123 void SAL_CALL ManifestImport::startElement( const OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs ) 124 throw( xml::sax::SAXException, uno::RuntimeException ) 125 { 126 StringHashMap aConvertedAttribs; 127 ::rtl::OUString aConvertedName = PushNameAndNamespaces( aName, xAttribs, aConvertedAttribs ); 128 129 if ( aConvertedName == sFileEntryElement ) 130 { 131 aSequence.realloc ( PKG_SIZE_ENCR_MNFST ); 132 133 // Put full-path property first for MBA 134 aSequence[nNumProperty].Name = sFullPathProperty; 135 aSequence[nNumProperty++].Value <<= aConvertedAttribs[sFullPathAttribute]; 136 aSequence[nNumProperty].Name = sMediaTypeProperty; 137 aSequence[nNumProperty++].Value <<= aConvertedAttribs[sMediaTypeAttribute]; 138 139 OUString sVersion = aConvertedAttribs[sVersionAttribute]; 140 if ( sVersion.getLength() ) 141 { 142 aSequence[nNumProperty].Name = sVersionProperty; 143 aSequence[nNumProperty++].Value <<= sVersion; 144 } 145 146 OUString sSize = aConvertedAttribs[sSizeAttribute]; 147 if ( sSize.getLength() ) 148 { 149 sal_Int32 nSize; 150 nSize = sSize.toInt32(); 151 aSequence[nNumProperty].Name = sSizeProperty; 152 aSequence[nNumProperty++].Value <<= nSize; 153 } 154 } 155 else if ( aStack.size() > 1 ) 156 { 157 ManifestStack::reverse_iterator aIter = aStack.rbegin(); 158 aIter++; 159 160 if ( aIter->m_aConvertedName.equals( sFileEntryElement ) ) 161 { 162 if ( aConvertedName.equals( sEncryptionDataElement ) ) 163 { 164 // If this element exists, then this stream is encrypted and we need 165 // to import the initialisation vector, salt and iteration count used 166 nDerivedKeySize = 0; 167 OUString aString = aConvertedAttribs[sChecksumTypeAttribute]; 168 if ( !bIgnoreEncryptData ) 169 { 170 if ( aString.equals( sSHA1_1k_Name ) || aString.equals( sSHA1_1k_URL ) ) 171 { 172 aSequence[nNumProperty].Name = sDigestAlgProperty; 173 aSequence[nNumProperty++].Value <<= xml::crypto::DigestID::SHA1_1K; 174 } 175 else if ( aString.equals( sSHA256_1k_URL ) ) 176 { 177 aSequence[nNumProperty].Name = sDigestAlgProperty; 178 aSequence[nNumProperty++].Value <<= xml::crypto::DigestID::SHA256_1K; 179 } 180 else 181 bIgnoreEncryptData = sal_True; 182 183 if ( !bIgnoreEncryptData ) 184 { 185 aString = aConvertedAttribs[sChecksumAttribute]; 186 uno::Sequence < sal_Int8 > aDecodeBuffer; 187 Base64Codec::decodeBase64( aDecodeBuffer, aString ); 188 aSequence[nNumProperty].Name = sDigestProperty; 189 aSequence[nNumProperty++].Value <<= aDecodeBuffer; 190 } 191 } 192 } 193 } 194 else if ( aIter->m_aConvertedName.equals( sEncryptionDataElement ) ) 195 { 196 if ( aConvertedName == sAlgorithmElement ) 197 { 198 if ( !bIgnoreEncryptData ) 199 { 200 OUString aString = aConvertedAttribs[sAlgorithmNameAttribute]; 201 if ( aString.equals( sBlowfish_Name ) || aString.equals( sBlowfish_URL ) ) 202 { 203 aSequence[nNumProperty].Name = sEncryptionAlgProperty; 204 aSequence[nNumProperty++].Value <<= xml::crypto::CipherID::BLOWFISH_CFB_8; 205 } 206 else if ( aString.equals( sAES256_URL ) ) 207 { 208 aSequence[nNumProperty].Name = sEncryptionAlgProperty; 209 aSequence[nNumProperty++].Value <<= xml::crypto::CipherID::AES_CBC_W3C_PADDING; 210 OSL_ENSURE( !nDerivedKeySize || nDerivedKeySize == 32, "Unexpected derived key length!" ); 211 nDerivedKeySize = 32; 212 } 213 else if ( aString.equals( sAES192_URL ) ) 214 { 215 aSequence[nNumProperty].Name = sEncryptionAlgProperty; 216 aSequence[nNumProperty++].Value <<= xml::crypto::CipherID::AES_CBC_W3C_PADDING; 217 OSL_ENSURE( !nDerivedKeySize || nDerivedKeySize == 24, "Unexpected derived key length!" ); 218 nDerivedKeySize = 24; 219 } 220 else if ( aString.equals( sAES128_URL ) ) 221 { 222 aSequence[nNumProperty].Name = sEncryptionAlgProperty; 223 aSequence[nNumProperty++].Value <<= xml::crypto::CipherID::AES_CBC_W3C_PADDING; 224 OSL_ENSURE( !nDerivedKeySize || nDerivedKeySize == 16, "Unexpected derived key length!" ); 225 nDerivedKeySize = 16; 226 } 227 else 228 bIgnoreEncryptData = sal_True; 229 230 if ( !bIgnoreEncryptData ) 231 { 232 aString = aConvertedAttribs[sInitialisationVectorAttribute]; 233 uno::Sequence < sal_Int8 > aDecodeBuffer; 234 Base64Codec::decodeBase64 ( aDecodeBuffer, aString ); 235 aSequence[nNumProperty].Name = sInitialisationVectorProperty; 236 aSequence[nNumProperty++].Value <<= aDecodeBuffer; 237 } 238 } 239 } 240 else if ( aConvertedName == sKeyDerivationElement ) 241 { 242 if ( !bIgnoreEncryptData ) 243 { 244 OUString aString = aConvertedAttribs[sKeyDerivationNameAttribute]; 245 if ( aString.equals( sPBKDF2_Name ) || aString.equals( sPBKDF2_URL ) ) 246 { 247 aString = aConvertedAttribs[sSaltAttribute]; 248 uno::Sequence < sal_Int8 > aDecodeBuffer; 249 Base64Codec::decodeBase64 ( aDecodeBuffer, aString ); 250 aSequence[nNumProperty].Name = sSaltProperty; 251 aSequence[nNumProperty++].Value <<= aDecodeBuffer; 252 253 aString = aConvertedAttribs[sIterationCountAttribute]; 254 aSequence[nNumProperty].Name = sIterationCountProperty; 255 aSequence[nNumProperty++].Value <<= aString.toInt32(); 256 257 aString = aConvertedAttribs[sKeySizeAttribute]; 258 if ( aString.getLength() ) 259 { 260 sal_Int32 nKey = aString.toInt32(); 261 OSL_ENSURE( !nDerivedKeySize || nKey == nDerivedKeySize , "Provided derived key length differs from the expected one!" ); 262 nDerivedKeySize = nKey; 263 } 264 else if ( !nDerivedKeySize ) 265 nDerivedKeySize = 16; 266 else if ( nDerivedKeySize != 16 ) 267 OSL_ENSURE( sal_False, "Default derived key length differs from the expected one!" ); 268 269 aSequence[nNumProperty].Name = sDerivedKeySizeProperty; 270 aSequence[nNumProperty++].Value <<= nDerivedKeySize; 271 } 272 else 273 bIgnoreEncryptData = sal_True; 274 } 275 } 276 else if ( aConvertedName == sStartKeyAlgElement ) 277 { 278 OUString aString = aConvertedAttribs[sStartKeyAlgNameAttribute]; 279 if ( aString.equals( sSHA256_URL ) ) 280 { 281 aSequence[nNumProperty].Name = sStartKeyAlgProperty; 282 aSequence[nNumProperty++].Value <<= xml::crypto::DigestID::SHA256; 283 } 284 else if ( aString.equals( sSHA1_Name ) || aString.equals( sSHA1_URL ) ) 285 { 286 aSequence[nNumProperty].Name = sStartKeyAlgProperty; 287 aSequence[nNumProperty++].Value <<= xml::crypto::DigestID::SHA1; 288 } 289 else 290 bIgnoreEncryptData = sal_True; 291 } 292 } 293 } 294 } 295 296 // --------------------------------------------------- 297 void SAL_CALL ManifestImport::endElement( const OUString& aName ) 298 throw( xml::sax::SAXException, uno::RuntimeException ) 299 { 300 ::rtl::OUString aConvertedName = ConvertName( aName ); 301 if ( !aStack.empty() && aStack.rbegin()->m_aConvertedName.equals( aConvertedName ) ) 302 { 303 if ( aConvertedName.equals( sFileEntryElement ) ) 304 { 305 aSequence.realloc ( nNumProperty ); 306 bIgnoreEncryptData = sal_False; 307 rManVector.push_back ( aSequence ); 308 nNumProperty = 0; 309 } 310 311 aStack.pop_back(); 312 } 313 } 314 315 // --------------------------------------------------- 316 void SAL_CALL ManifestImport::characters( const OUString& /*aChars*/ ) 317 throw( xml::sax::SAXException, uno::RuntimeException ) 318 { 319 } 320 321 // --------------------------------------------------- 322 void SAL_CALL ManifestImport::ignorableWhitespace( const OUString& /*aWhitespaces*/ ) 323 throw( xml::sax::SAXException, uno::RuntimeException ) 324 { 325 } 326 327 // --------------------------------------------------- 328 void SAL_CALL ManifestImport::processingInstruction( const OUString& /*aTarget*/, const OUString& /*aData*/ ) 329 throw( xml::sax::SAXException, uno::RuntimeException ) 330 { 331 } 332 333 // --------------------------------------------------- 334 void SAL_CALL ManifestImport::setDocumentLocator( const uno::Reference< xml::sax::XLocator >& /*xLocator*/ ) 335 throw( xml::sax::SAXException, uno::RuntimeException ) 336 { 337 } 338 339 // --------------------------------------------------- 340 ::rtl::OUString ManifestImport::PushNameAndNamespaces( const ::rtl::OUString& aName, const uno::Reference< xml::sax::XAttributeList >& xAttribs, StringHashMap& o_aConvertedAttribs ) 341 { 342 StringHashMap aNamespaces; 343 ::std::vector< ::std::pair< ::rtl::OUString, ::rtl::OUString > > aAttribsStrs; 344 345 if ( xAttribs.is() ) 346 { 347 sal_Int16 nAttrCount = xAttribs.is() ? xAttribs->getLength() : 0; 348 aAttribsStrs.reserve( nAttrCount ); 349 350 for( sal_Int16 nInd = 0; nInd < nAttrCount; nInd++ ) 351 { 352 ::rtl::OUString aAttrName = xAttribs->getNameByIndex( nInd ); 353 ::rtl::OUString aAttrValue = xAttribs->getValueByIndex( nInd ); 354 if ( aAttrName.getLength() >= 5 355 && aAttrName.compareToAscii( "xmlns", 5 ) == 0 356 && ( aAttrName.getLength() == 5 || aAttrName.getStr()[5] == ( sal_Unicode )':' ) ) 357 { 358 // this is a namespace declaration 359 ::rtl::OUString aNsName( ( aAttrName.getLength() == 5 ) ? ::rtl::OUString() : aAttrName.copy( 6 ) ); 360 aNamespaces[aNsName] = aAttrValue; 361 } 362 else 363 { 364 // this is no namespace declaration 365 aAttribsStrs.push_back( pair< ::rtl::OUString, ::rtl::OUString >( aAttrName, aAttrValue ) ); 366 } 367 } 368 } 369 370 ::rtl::OUString aConvertedName = ConvertNameWithNamespace( aName, aNamespaces ); 371 if ( !aConvertedName.getLength() ) 372 aConvertedName = ConvertName( aName ); 373 374 aStack.push_back( ManifestScopeEntry( aConvertedName, aNamespaces ) ); 375 376 for ( sal_uInt16 nInd = 0; nInd < aAttribsStrs.size(); nInd++ ) 377 { 378 // convert the attribute names on filling 379 o_aConvertedAttribs[ConvertName( aAttribsStrs[nInd].first )] = aAttribsStrs[nInd].second; 380 } 381 382 return aConvertedName; 383 } 384 385 // --------------------------------------------------- 386 ::rtl::OUString ManifestImport::ConvertNameWithNamespace( const ::rtl::OUString& aName, const StringHashMap& aNamespaces ) 387 { 388 ::rtl::OUString aNsAlias; 389 ::rtl::OUString aPureName = aName; 390 391 sal_Int32 nInd = aName.indexOf( ( sal_Unicode )':' ); 392 if ( nInd != -1 && nInd < aName.getLength() ) 393 { 394 aNsAlias = aName.copy( 0, nInd ); 395 aPureName = aName.copy( nInd + 1 ); 396 } 397 398 ::rtl::OUString aResult; 399 400 StringHashMap::const_iterator aIter = aNamespaces.find( aNsAlias ); 401 if ( aIter != aNamespaces.end() 402 && ( aIter->second.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( MANIFEST_NAMESPACE ) ) ) 403 || aIter->second.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( MANIFEST_OASIS_NAMESPACE ) ) ) ) ) 404 { 405 // no check for manifest.xml consistency currently since the old versions have supported inconsistent documents as well 406 aResult = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( MANIFEST_NSPREFIX ) ); 407 aResult += aPureName; 408 } 409 410 return aResult; 411 } 412 413 // --------------------------------------------------- 414 ::rtl::OUString ManifestImport::ConvertName( const ::rtl::OUString& aName ) 415 { 416 ::rtl::OUString aConvertedName; 417 for ( ManifestStack::reverse_iterator aIter = aStack.rbegin(); !aConvertedName.getLength() && aIter != aStack.rend(); aIter++ ) 418 { 419 if ( !aIter->m_aNamespaces.empty() ) 420 aConvertedName = ConvertNameWithNamespace( aName, aIter->m_aNamespaces ); 421 } 422 423 if ( !aConvertedName.getLength() ) 424 aConvertedName = aName; 425 426 return aConvertedName; 427 } 428 429