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_xmlsecurity.hxx" 26 27 #include <xsecctl.hxx> 28 #include "xsecparser.hxx" 29 #include <tools/debug.hxx> 30 31 #include <com/sun/star/xml/crypto/sax/XKeyCollector.hpp> 32 #include <com/sun/star/xml/crypto/sax/ElementMarkPriority.hpp> 33 #include <com/sun/star/xml/crypto/sax/XReferenceResolvedBroadcaster.hpp> 34 #include <com/sun/star/xml/crypto/sax/XReferenceCollector.hpp> 35 #include <com/sun/star/xml/crypto/sax/XSignatureVerifyResultBroadcaster.hpp> 36 #include <com/sun/star/xml/sax/SAXParseException.hpp> 37 38 // FIXME: copied from main/sal/rtl/source/strimp.c 39 static sal_Bool rtl_ImplIsWhitespace( sal_Unicode c ) 40 { 41 /* Space or Control character? */ 42 if ( (c <= 32) && c ) 43 return sal_True; 44 45 /* Only in the General Punctuation area Space or Control characters are included? */ 46 if ( (c < 0x2000) || (c > 0x206F) ) 47 return sal_False; 48 49 if ( ((c >= 0x2000) && (c <= 0x200B)) || /* All Spaces */ 50 (c == 0x2028) || /* LINE SEPARATOR */ 51 (c == 0x2029) ) /* PARAGRAPH SEPARATOR */ 52 return sal_True; 53 54 return sal_False; 55 } 56 57 namespace cssu = com::sun::star::uno; 58 namespace cssl = com::sun::star::lang; 59 namespace cssxc = com::sun::star::xml::crypto; 60 namespace cssxs = com::sun::star::xml::sax; 61 62 /* xml security framework components */ 63 #define SIGNATUREVERIFIER_COMPONENT "com.sun.star.xml.crypto.sax.SignatureVerifier" 64 65 /* protected: for signature verify */ 66 cssu::Reference< cssxc::sax::XReferenceResolvedListener > XSecController::prepareSignatureToRead( 67 sal_Int32 nSecurityId) 68 { 69 if ( m_nStatusOfSecurityComponents != INITIALIZED ) 70 { 71 return NULL; 72 } 73 74 sal_Int32 nIdOfSignatureElementCollector; 75 cssu::Reference< cssxc::sax::XReferenceResolvedListener > xReferenceResolvedListener; 76 77 nIdOfSignatureElementCollector = 78 m_xSAXEventKeeper->addSecurityElementCollector( cssxc::sax::ElementMarkPriority_BEFOREMODIFY, sal_False); 79 80 m_xSAXEventKeeper->setSecurityId(nIdOfSignatureElementCollector, nSecurityId); 81 82 /* 83 * create a SignatureVerifier 84 */ 85 cssu::Reference< cssl::XMultiComponentFactory > xMCF( mxCtx->getServiceManager() ); 86 xReferenceResolvedListener = cssu::Reference< cssxc::sax::XReferenceResolvedListener >( 87 xMCF->createInstanceWithContext( 88 rtl::OUString::createFromAscii( SIGNATUREVERIFIER_COMPONENT ), mxCtx), 89 cssu::UNO_QUERY); 90 91 cssu::Reference<cssl::XInitialization> xInitialization(xReferenceResolvedListener, cssu::UNO_QUERY); 92 93 cssu::Sequence<cssu::Any> args(5); 94 args[0] = cssu::makeAny(rtl::OUString::valueOf(nSecurityId)); 95 args[1] = cssu::makeAny(m_xSAXEventKeeper); 96 args[2] = cssu::makeAny(rtl::OUString::valueOf(nIdOfSignatureElementCollector)); 97 args[3] = cssu::makeAny(m_xSecurityContext); 98 args[4] = cssu::makeAny(m_xXMLSignature); 99 xInitialization->initialize(args); 100 101 cssu::Reference< cssxc::sax::XSignatureVerifyResultBroadcaster > 102 signatureVerifyResultBroadcaster(xReferenceResolvedListener, cssu::UNO_QUERY); 103 104 signatureVerifyResultBroadcaster->addSignatureVerifyResultListener( this ); 105 106 cssu::Reference<cssxc::sax::XReferenceResolvedBroadcaster> xReferenceResolvedBroadcaster 107 (m_xSAXEventKeeper, 108 cssu::UNO_QUERY); 109 110 xReferenceResolvedBroadcaster->addReferenceResolvedListener( 111 nIdOfSignatureElementCollector, 112 xReferenceResolvedListener); 113 114 cssu::Reference<cssxc::sax::XKeyCollector> keyCollector (xReferenceResolvedListener, cssu::UNO_QUERY); 115 keyCollector->setKeyId(0); 116 117 return xReferenceResolvedListener; 118 } 119 120 void XSecController::addSignature() 121 { 122 cssu::Reference< cssxc::sax::XReferenceResolvedListener > xReferenceResolvedListener = NULL; 123 sal_Int32 nSignatureId = 0; 124 125 126 if (m_bVerifyCurrentSignature) 127 { 128 chainOn(true); 129 xReferenceResolvedListener = prepareSignatureToRead( m_nReservedSignatureId ); 130 m_bVerifyCurrentSignature = false; 131 nSignatureId = m_nReservedSignatureId; 132 } 133 134 InternalSignatureInformation isi( nSignatureId, xReferenceResolvedListener ); 135 m_vInternalSignatureInformations.push_back( isi ); 136 } 137 138 void XSecController::addReference( const rtl::OUString& ouUri) 139 { 140 InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; 141 isi.addReference(TYPE_SAMEDOCUMENT_REFERENCE,ouUri, -1 ); 142 } 143 144 void XSecController::addStreamReference( 145 const rtl::OUString& ouUri, 146 bool isBinary ) 147 { 148 sal_Int32 type = (isBinary?TYPE_BINARYSTREAM_REFERENCE:TYPE_XMLSTREAM_REFERENCE); 149 150 InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; 151 152 if ( isi.xReferenceResolvedListener.is() ) 153 { 154 /* 155 * get the input stream 156 */ 157 cssu::Reference< com::sun::star::io::XInputStream > xObjectInputStream 158 = getObjectInputStream( ouUri ); 159 160 if ( xObjectInputStream.is() ) 161 { 162 cssu::Reference<cssxc::XUriBinding> xUriBinding 163 (isi.xReferenceResolvedListener, cssu::UNO_QUERY); 164 xUriBinding->setUriBinding(ouUri, xObjectInputStream); 165 } 166 } 167 168 isi.addReference(type, ouUri, -1); 169 } 170 171 void XSecController::setReferenceCount() const 172 { 173 const InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; 174 175 if ( isi.xReferenceResolvedListener.is() ) 176 { 177 const SignatureReferenceInformations &refInfors = isi.signatureInfor.vSignatureReferenceInfors; 178 179 int refNum = refInfors.size(); 180 sal_Int32 referenceCount = 0; 181 182 for(int i=0 ; i<refNum; ++i) 183 { 184 if (refInfors[i].nType == TYPE_SAMEDOCUMENT_REFERENCE ) 185 /* 186 * same-document reference 187 */ 188 { 189 referenceCount++; 190 } 191 } 192 193 cssu::Reference<cssxc::sax::XReferenceCollector> xReferenceCollector 194 (isi.xReferenceResolvedListener, cssu::UNO_QUERY); 195 xReferenceCollector->setReferenceCount( referenceCount ); 196 } 197 } 198 199 void XSecController::setIfEmpty(rtl::OUString &variable, const rtl::OUString &value) { 200 if (variable.getLength() == 0) { 201 variable = value; 202 } else if (variable != value) { 203 throw cssu::RuntimeException(rtl::OUString::createFromAscii("Value already set. Tampering?"), *this); 204 } 205 } 206 207 void XSecController::setX509IssuerName( rtl::OUString& ouX509IssuerName ) 208 { 209 InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; 210 setIfEmpty(isi.signatureInfor.ouX509IssuerName, ouX509IssuerName); 211 } 212 213 void XSecController::setX509SerialNumber( rtl::OUString& ouX509SerialNumber ) 214 { 215 InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; 216 setIfEmpty(isi.signatureInfor.ouX509SerialNumber, ouX509SerialNumber); 217 } 218 219 void XSecController::setX509Certificate( rtl::OUString& ouX509Certificate ) 220 { 221 InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; 222 setIfEmpty(isi.signatureInfor.ouX509Certificate, ouX509Certificate); 223 if (isi.signatureInfor.ouX509Certificate.getLength()) { 224 // We allow to re-set the same certificate only. 225 // Whitespace may change. 226 const sal_Int32 l1 = isi.signatureInfor.ouX509Certificate.getLength(); 227 const sal_Int32 l2 = ouX509Certificate.getLength(); 228 const sal_Unicode *s1 = isi.signatureInfor.ouX509Certificate.getStr(); 229 const sal_Unicode *s2 = ouX509Certificate.getStr(); 230 sal_Int32 i1 = 0, i2 = 0; 231 while ((i1 < l1) && (i2 < l2)) { 232 const sal_Unicode &c1 = s1[i1]; 233 const sal_Unicode &c2 = s2[i2]; 234 if (rtl_ImplIsWhitespace(c1)) { 235 ++i1; 236 continue; 237 } 238 if (rtl_ImplIsWhitespace(c2)) { 239 ++i2; 240 continue; 241 } 242 if (c1 != c2) { 243 throw cssu::RuntimeException(rtl::OUString::createFromAscii("Value already set. Tampering?"), *this); 244 } 245 ++i1; 246 ++i2; 247 } 248 // We could still have whitespace at the end of both strings 249 while ((i1 < l1) && rtl_ImplIsWhitespace(s1[l1])) { 250 ++i1; 251 } 252 while ((i2 < l2) && rtl_ImplIsWhitespace(s2[l2])) { 253 ++i2; 254 } 255 if ((i1 != l1) || (i2 != l2)) { 256 throw cssu::RuntimeException(rtl::OUString::createFromAscii("Value already set. Tampering?"), *this); 257 } 258 } 259 isi.signatureInfor.ouX509Certificate = ouX509Certificate; 260 } 261 262 void XSecController::setSignatureValue( rtl::OUString& ouSignatureValue ) 263 { 264 InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; 265 isi.signatureInfor.ouSignatureValue = ouSignatureValue; 266 } 267 268 void XSecController::setDigestValue( rtl::OUString& ouDigestValue ) 269 { 270 SignatureInformation &si = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1].signatureInfor; 271 SignatureReferenceInformation &reference = si.vSignatureReferenceInfors[si.vSignatureReferenceInfors.size()-1]; 272 reference.ouDigestValue = ouDigestValue; 273 } 274 275 void XSecController::setDate( rtl::OUString& ouDate ) 276 { 277 InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; 278 convertDateTime( isi.signatureInfor.stDateTime, ouDate ); 279 setIfEmpty(isi.signatureInfor.ouDateTime, ouDate); 280 } 281 282 /* 283 void XSecController::setTime( rtl::OUString& ouTime ) 284 { 285 InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; 286 isi.signatureInfor.ouTime = ouTime; 287 } 288 */ 289 290 void XSecController::setId( rtl::OUString& ouId ) 291 { 292 InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; 293 isi.signatureInfor.ouSignatureId = ouId; 294 } 295 296 void XSecController::setPropertyId( rtl::OUString& ouPropertyId ) 297 { 298 InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; 299 isi.signatureInfor.ouPropertyId = ouPropertyId; 300 } 301 302 /* public: for signature verify */ 303 void XSecController::collectToVerify( const rtl::OUString& referenceId ) 304 { 305 /* DBG_ASSERT( m_xSAXEventKeeper.is(), "the SAXEventKeeper is NULL" ); */ 306 307 if ( m_nStatusOfSecurityComponents == INITIALIZED ) 308 /* 309 * if all security components are ready, verify the signature. 310 */ 311 { 312 bool bJustChainingOn = false; 313 cssu::Reference< cssxs::XDocumentHandler > xHandler = NULL; 314 315 int i,j; 316 int sigNum = m_vInternalSignatureInformations.size(); 317 318 for (i=0; i<sigNum; ++i) 319 { 320 InternalSignatureInformation& isi = m_vInternalSignatureInformations[i]; 321 SignatureReferenceInformations& vReferenceInfors = isi.signatureInfor.vSignatureReferenceInfors; 322 int refNum = vReferenceInfors.size(); 323 324 for (j=0; j<refNum; ++j) 325 { 326 SignatureReferenceInformation &refInfor = vReferenceInfors[j]; 327 328 if (refInfor.ouURI == referenceId) 329 { 330 if (chainOn(false)) 331 { 332 bJustChainingOn = true; 333 xHandler = m_xSAXEventKeeper->setNextHandler(NULL); 334 } 335 336 sal_Int32 nKeeperId = m_xSAXEventKeeper->addSecurityElementCollector( 337 cssxc::sax::ElementMarkPriority_BEFOREMODIFY, sal_False ); 338 339 cssu::Reference<cssxc::sax::XReferenceResolvedBroadcaster> xReferenceResolvedBroadcaster 340 (m_xSAXEventKeeper, 341 cssu::UNO_QUERY ); 342 343 cssu::Reference<cssxc::sax::XReferenceCollector> xReferenceCollector 344 ( isi.xReferenceResolvedListener, cssu::UNO_QUERY ); 345 346 m_xSAXEventKeeper->setSecurityId(nKeeperId, isi.signatureInfor.nSecurityId); 347 xReferenceResolvedBroadcaster->addReferenceResolvedListener( nKeeperId, isi.xReferenceResolvedListener); 348 xReferenceCollector->setReferenceId( nKeeperId ); 349 350 isi.vKeeperIds[j] = nKeeperId; 351 break; 352 } 353 } 354 } 355 356 if ( bJustChainingOn ) 357 { 358 cssu::Reference< cssxs::XDocumentHandler > xSEKHandler(m_xSAXEventKeeper, cssu::UNO_QUERY); 359 if (m_xElementStackKeeper.is()) 360 { 361 m_xElementStackKeeper->retrieve(xSEKHandler, sal_True); 362 } 363 m_xSAXEventKeeper->setNextHandler(xHandler); 364 } 365 } 366 } 367 368 void XSecController::addSignature( sal_Int32 nSignatureId ) 369 { 370 DBG_ASSERT( m_pXSecParser != NULL, "No XSecParser initialized" ); 371 372 m_nReservedSignatureId = nSignatureId; 373 m_bVerifyCurrentSignature = true; 374 } 375 376 cssu::Reference< cssxs::XDocumentHandler > XSecController::createSignatureReader() 377 { 378 m_pXSecParser = new XSecParser( this, NULL ); 379 cssu::Reference< cssl::XInitialization > xInitialization = m_pXSecParser; 380 381 setSAXChainConnector(xInitialization, NULL, NULL); 382 383 return m_pXSecParser; 384 } 385 386 void XSecController::releaseSignatureReader() 387 { 388 clearSAXChainConnector( ); 389 m_pXSecParser = NULL; 390 } 391 392