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 if (isi.signatureInfor.ouX509Certificate.getLength()) { 223 // We allow to re-set the same certificate only. 224 // Whitespace may change. 225 const sal_Int32 l1 = isi.signatureInfor.ouX509Certificate.getLength(); 226 const sal_Int32 l2 = ouX509Certificate.getLength(); 227 const sal_Unicode *s1 = isi.signatureInfor.ouX509Certificate.getStr(); 228 const sal_Unicode *s2 = ouX509Certificate.getStr(); 229 sal_Int32 i1 = 0, i2 = 0; 230 while ((i1 < l1) && (i2 < l2)) { 231 const sal_Unicode &c1 = s1[i1]; 232 const sal_Unicode &c2 = s2[i2]; 233 if (rtl_ImplIsWhitespace(c1)) { 234 ++i1; 235 continue; 236 } 237 if (rtl_ImplIsWhitespace(c2)) { 238 ++i2; 239 continue; 240 } 241 if (c1 != c2) { 242 throw cssu::RuntimeException(rtl::OUString::createFromAscii("Value already set. Tampering?"), *this); 243 } 244 ++i1; 245 ++i2; 246 } 247 // We could still have whitespace at the end of both strings 248 while ((i1 < l1) && rtl_ImplIsWhitespace(s1[l1])) { 249 ++i1; 250 } 251 while ((i2 < l2) && rtl_ImplIsWhitespace(s2[l2])) { 252 ++i2; 253 } 254 if ((i1 != l1) || (i2 != l2)) { 255 throw cssu::RuntimeException(rtl::OUString::createFromAscii("Value already set. Tampering?"), *this); 256 } 257 } 258 isi.signatureInfor.ouX509Certificate = ouX509Certificate; 259 } 260 261 void XSecController::setSignatureValue( rtl::OUString& ouSignatureValue ) 262 { 263 InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; 264 isi.signatureInfor.ouSignatureValue = ouSignatureValue; 265 } 266 267 void XSecController::setDigestValue( rtl::OUString& ouDigestValue ) 268 { 269 SignatureInformation &si = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1].signatureInfor; 270 SignatureReferenceInformation &reference = si.vSignatureReferenceInfors[si.vSignatureReferenceInfors.size()-1]; 271 reference.ouDigestValue = ouDigestValue; 272 } 273 274 void XSecController::setDate( rtl::OUString& ouDate ) 275 { 276 InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; 277 convertDateTime( isi.signatureInfor.stDateTime, ouDate ); 278 setIfEmpty(isi.signatureInfor.ouDateTime, ouDate); 279 } 280 281 /* 282 void XSecController::setTime( rtl::OUString& ouTime ) 283 { 284 InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; 285 isi.signatureInfor.ouTime = ouTime; 286 } 287 */ 288 289 void XSecController::setId( rtl::OUString& ouId ) 290 { 291 InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; 292 isi.signatureInfor.ouSignatureId = ouId; 293 } 294 295 void XSecController::setPropertyId( rtl::OUString& ouPropertyId ) 296 { 297 InternalSignatureInformation &isi = m_vInternalSignatureInformations[m_vInternalSignatureInformations.size()-1]; 298 isi.signatureInfor.ouPropertyId = ouPropertyId; 299 } 300 301 /* public: for signature verify */ 302 void XSecController::collectToVerify( const rtl::OUString& referenceId ) 303 { 304 /* DBG_ASSERT( m_xSAXEventKeeper.is(), "the SAXEventKeeper is NULL" ); */ 305 306 if ( m_nStatusOfSecurityComponents == INITIALIZED ) 307 /* 308 * if all security components are ready, verify the signature. 309 */ 310 { 311 bool bJustChainingOn = false; 312 cssu::Reference< cssxs::XDocumentHandler > xHandler = NULL; 313 314 int i,j; 315 int sigNum = m_vInternalSignatureInformations.size(); 316 317 for (i=0; i<sigNum; ++i) 318 { 319 InternalSignatureInformation& isi = m_vInternalSignatureInformations[i]; 320 SignatureReferenceInformations& vReferenceInfors = isi.signatureInfor.vSignatureReferenceInfors; 321 int refNum = vReferenceInfors.size(); 322 323 for (j=0; j<refNum; ++j) 324 { 325 SignatureReferenceInformation &refInfor = vReferenceInfors[j]; 326 327 if (refInfor.ouURI == referenceId) 328 { 329 if (chainOn(false)) 330 { 331 bJustChainingOn = true; 332 xHandler = m_xSAXEventKeeper->setNextHandler(NULL); 333 } 334 335 sal_Int32 nKeeperId = m_xSAXEventKeeper->addSecurityElementCollector( 336 cssxc::sax::ElementMarkPriority_BEFOREMODIFY, sal_False ); 337 338 cssu::Reference<cssxc::sax::XReferenceResolvedBroadcaster> xReferenceResolvedBroadcaster 339 (m_xSAXEventKeeper, 340 cssu::UNO_QUERY ); 341 342 cssu::Reference<cssxc::sax::XReferenceCollector> xReferenceCollector 343 ( isi.xReferenceResolvedListener, cssu::UNO_QUERY ); 344 345 m_xSAXEventKeeper->setSecurityId(nKeeperId, isi.signatureInfor.nSecurityId); 346 xReferenceResolvedBroadcaster->addReferenceResolvedListener( nKeeperId, isi.xReferenceResolvedListener); 347 xReferenceCollector->setReferenceId( nKeeperId ); 348 349 isi.vKeeperIds[j] = nKeeperId; 350 break; 351 } 352 } 353 } 354 355 if ( bJustChainingOn ) 356 { 357 cssu::Reference< cssxs::XDocumentHandler > xSEKHandler(m_xSAXEventKeeper, cssu::UNO_QUERY); 358 if (m_xElementStackKeeper.is()) 359 { 360 m_xElementStackKeeper->retrieve(xSEKHandler, sal_True); 361 } 362 m_xSAXEventKeeper->setNextHandler(xHandler); 363 } 364 } 365 } 366 367 void XSecController::addSignature( sal_Int32 nSignatureId ) 368 { 369 DBG_ASSERT( m_pXSecParser != NULL, "No XSecParser initialized" ); 370 371 m_nReservedSignatureId = nSignatureId; 372 m_bVerifyCurrentSignature = true; 373 } 374 375 cssu::Reference< cssxs::XDocumentHandler > XSecController::createSignatureReader() 376 { 377 m_pXSecParser = new XSecParser( this, NULL ); 378 cssu::Reference< cssl::XInitialization > xInitialization = m_pXSecParser; 379 380 setSAXChainConnector(xInitialization, NULL, NULL); 381 382 return m_pXSecParser; 383 } 384 385 void XSecController::releaseSignatureReader() 386 { 387 clearSAXChainConnector( ); 388 m_pXSecParser = NULL; 389 } 390 391