1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_svl.hxx" 30 31 #include "passwordcontainer.hxx" 32 33 #include <unotools/pathoptions.hxx> 34 #include "cppuhelper/factory.hxx" 35 #include <com/sun/star/registry/XSimpleRegistry.hpp> 36 #include <com/sun/star/beans/PropertyValue.hpp> 37 #include <com/sun/star/task/MasterPasswordRequest.hpp> 38 #include <com/sun/star/task/NoMasterException.hpp> 39 40 #include <rtl/cipher.h> 41 #include <rtl/digest.h> 42 #include <rtl/byteseq.hxx> 43 44 #ifndef _TOOLS_INETSTRM_HXX 45 // @@@ #include <inetstrm.hxx> 46 #endif 47 48 using namespace std; 49 using namespace osl; 50 using namespace utl; 51 using namespace com::sun::star; 52 using namespace com::sun::star::uno; 53 using namespace com::sun::star::registry; 54 using namespace com::sun::star::lang; 55 using namespace com::sun::star::task; 56 using namespace com::sun::star::ucb; 57 58 //------------------------------------------------------------------------- 59 //------------------------------------------------------------------------- 60 61 static ::rtl::OUString createIndex( vector< ::rtl::OUString > lines ) 62 { 63 ::rtl::OString aResult; 64 const sal_Char* pLine; 65 66 for( unsigned int i = 0; i < lines.size(); i++ ) 67 { 68 if( i ) 69 aResult += ::rtl::OString( "__" ); 70 ::rtl::OString line = ::rtl::OUStringToOString( lines[i], RTL_TEXTENCODING_UTF8 ); 71 pLine = line.getStr(); 72 73 while( *pLine ) 74 { 75 if( ( *pLine >= 'A' && *pLine <= 'Z' ) 76 || ( *pLine >= 'a' && *pLine <= 'z' ) 77 || ( *pLine >= '0' && *pLine <= '9' ) ) 78 { 79 aResult += ::rtl::OString::valueOf( *pLine ); 80 } 81 else 82 { 83 aResult += ::rtl::OString("_"); 84 aResult += ::rtl::OString::valueOf( (sal_Int32) *pLine, 16 ); 85 } 86 87 pLine++; 88 } 89 } 90 91 return ::rtl::OUString::createFromAscii( aResult.getStr() ); 92 } 93 94 //------------------------------------------------------------------------- 95 96 static vector< ::rtl::OUString > getInfoFromInd( ::rtl::OUString aInd ) 97 { 98 vector< ::rtl::OUString > aResult; 99 sal_Bool aStart = sal_True; 100 101 ::rtl::OString line = ::rtl::OUStringToOString( aInd, RTL_TEXTENCODING_ASCII_US ); 102 const sal_Char* pLine = line.getStr(); 103 do 104 { 105 ::rtl::OUString newItem; 106 if( !aStart ) 107 pLine += 2; 108 else 109 aStart = sal_False; 110 111 while( *pLine && !( pLine[0] == '_' && pLine[1] == '_' )) 112 if( *pLine != '_' ) 113 { 114 newItem += ::rtl::OUString::valueOf( (sal_Unicode) *pLine ); 115 pLine++; 116 } 117 else 118 { 119 ::rtl::OUString aNum; 120 for( int i = 1; i < 3; i++ ) 121 { 122 if( !pLine[i] 123 || ( ( pLine[i] < '0' || pLine[i] > '9' ) 124 && ( pLine[i] < 'a' || pLine[i] > 'f' ) 125 && ( pLine[i] < 'A' || pLine[i] > 'F' ) ) ) 126 { 127 OSL_ENSURE( sal_False, "Wrong index syntax!\n" ); 128 return aResult; 129 } 130 131 aNum += ::rtl::OUString::valueOf( (sal_Unicode) pLine[i] ); 132 } 133 134 newItem += ::rtl::OUString::valueOf( (sal_Unicode) aNum.toInt32( 16 ) ); 135 pLine += 3; 136 } 137 138 aResult.push_back( newItem ); 139 } while( pLine[0] == '_' && pLine[1] == '_' ); 140 141 if( *pLine ) 142 OSL_ENSURE( sal_False, "Wrong index syntax!\n" ); 143 144 return aResult; 145 } 146 147 //------------------------------------------------------------------------- 148 149 static sal_Bool shorterUrl( ::rtl::OUString& aURL ) 150 { 151 sal_Int32 aInd = aURL.lastIndexOf( sal_Unicode( '/' ) ); 152 if( aInd > 0 && aURL.indexOf( ::rtl::OUString::createFromAscii( "://" ) ) != aInd-2 ) 153 { 154 aURL = aURL.copy( 0, aInd ); 155 return sal_True; 156 } 157 158 return sal_False; 159 } 160 161 //------------------------------------------------------------------------- 162 163 static ::rtl::OUString getAsciiLine( const ::rtl::ByteSequence& buf ) 164 { 165 ::rtl::OUString aResult; 166 167 ::rtl::ByteSequence outbuf( buf.getLength()*2+1 ); 168 169 for( int ind = 0; ind < buf.getLength(); ind++ ) 170 { 171 outbuf[ind*2] = ( ((sal_uInt8)buf[ind]) >> 4 ) + 'a'; 172 outbuf[ind*2+1] = ( ((sal_uInt8)buf[ind]) & 0x0f ) + 'a'; 173 } 174 outbuf[buf.getLength()*2] = '\0'; 175 176 aResult = ::rtl::OUString::createFromAscii( (sal_Char*)outbuf.getArray() ); 177 178 return aResult; 179 } 180 181 //------------------------------------------------------------------------- 182 183 static ::rtl::ByteSequence getBufFromAsciiLine( ::rtl::OUString line ) 184 { 185 OSL_ENSURE( line.getLength() % 2 == 0, "Wrong syntax!\n" ); 186 ::rtl::OString tmpLine = ::rtl::OUStringToOString( line, RTL_TEXTENCODING_ASCII_US ); 187 ::rtl::ByteSequence aResult(line.getLength()/2); 188 189 for( int ind = 0; ind < tmpLine.getLength()/2; ind++ ) 190 { 191 aResult[ind] = ( (sal_uInt8)( tmpLine.getStr()[ind*2] - 'a' ) << 4 ) | (sal_uInt8)( tmpLine.getStr()[ind*2+1] - 'a' ); 192 } 193 194 return aResult; 195 } 196 197 //------------------------------------------------------------------------- 198 199 static Sequence< ::rtl::OUString > copyVectorToSequence( const vector< ::rtl::OUString >& original ) 200 { 201 Sequence< ::rtl::OUString > newOne ( original.size() ); 202 for( unsigned int i = 0; i < original.size() ; i++ ) 203 newOne[i] = original[i]; 204 205 return newOne; 206 } 207 208 static vector< ::rtl::OUString > copySequenceToVector( const Sequence< ::rtl::OUString >& original ) 209 { 210 vector< ::rtl::OUString > newOne ( original.getLength() ); 211 for( int i = 0; i < original.getLength() ; i++ ) 212 newOne[i] = original[i]; 213 214 return newOne; 215 } 216 217 //------------------------------------------------------------------------- 218 //------------------------------------------------------------------------- 219 220 PassMap StorageItem::getInfo() 221 { 222 PassMap aResult; 223 224 Sequence< ::rtl::OUString > aNodeNames = ConfigItem::GetNodeNames( ::rtl::OUString::createFromAscii("Store") ); 225 sal_Int32 aNodeCount = aNodeNames.getLength(); 226 Sequence< ::rtl::OUString > aPropNames( aNodeCount ); 227 sal_Int32 aNodeInd; 228 229 for( aNodeInd = 0; aNodeInd < aNodeCount; ++aNodeInd ) 230 { 231 aPropNames[aNodeInd] = ::rtl::OUString::createFromAscii( "Store/Passwordstorage['" ); 232 aPropNames[aNodeInd] += aNodeNames[aNodeInd]; 233 aPropNames[aNodeInd] += ::rtl::OUString::createFromAscii( "']/Password" ); 234 } 235 236 Sequence< Any > aPropertyValues = ConfigItem::GetProperties( aPropNames ); 237 238 if( aPropertyValues.getLength() != aNodeNames.getLength() ) 239 { 240 OSL_ENSURE( aPropertyValues.getLength() == aNodeNames.getLength(), "Problems during reading\n" ); 241 return aResult; 242 } 243 244 for( aNodeInd = 0; aNodeInd < aNodeCount; ++aNodeInd ) 245 { 246 vector< ::rtl::OUString > aUrlUsr = getInfoFromInd( aNodeNames[aNodeInd] ); 247 248 if( aUrlUsr.size() == 2 ) 249 { 250 ::rtl::OUString aUrl = aUrlUsr[0]; 251 ::rtl::OUString aName = aUrlUsr[1]; 252 253 ::rtl::OUString aEPasswd; 254 aPropertyValues[aNodeInd] >>= aEPasswd; 255 256 PassMap::iterator aIter = aResult.find( aUrl ); 257 if( aIter != aResult.end() ) 258 aIter->second.push_back( NamePassRecord( aName, aEPasswd ) ); 259 else 260 { 261 NamePassRecord aNewRecord( aName, aEPasswd ); 262 list< NamePassRecord > listToAdd( 1, aNewRecord ); 263 264 aResult.insert( PairUrlRecord( aUrl, listToAdd ) ); 265 } 266 } 267 else 268 OSL_ENSURE( sal_False, "Wrong index sintax!\n" ); 269 } 270 271 return aResult; 272 } 273 274 //------------------------------------------------------------------------- 275 276 void StorageItem::setUseStorage( sal_Bool bUse ) 277 { 278 Sequence< ::rtl::OUString > sendNames(1); 279 Sequence< uno::Any > sendVals(1); 280 281 sendNames[0] = ::rtl::OUString::createFromAscii( "UseStorage" ); 282 283 sendVals[0] <<= bUse; 284 285 ConfigItem::SetModified(); 286 ConfigItem::PutProperties( sendNames, sendVals ); 287 } 288 289 //------------------------------------------------------------------------- 290 291 sal_Bool StorageItem::useStorage() 292 { 293 Sequence< ::rtl::OUString > aNodeNames( 1 ); 294 aNodeNames[0] = ::rtl::OUString::createFromAscii( "UseStorage" ); 295 296 Sequence< Any > aPropertyValues = ConfigItem::GetProperties( aNodeNames ); 297 298 if( aPropertyValues.getLength() != aNodeNames.getLength() ) 299 { 300 OSL_ENSURE( aPropertyValues.getLength() == aNodeNames.getLength(), "Problems during reading\n" ); 301 return sal_False; 302 } 303 304 sal_Bool aResult = false; 305 aPropertyValues[0] >>= aResult; 306 307 return aResult; 308 } 309 310 //------------------------------------------------------------------------- 311 312 sal_Bool StorageItem::getEncodedMP( ::rtl::OUString& aResult ) 313 { 314 if( hasEncoded ) 315 { 316 aResult = mEncoded; 317 return sal_True; 318 } 319 320 Sequence< ::rtl::OUString > aNodeNames( 2 ); 321 aNodeNames[0] = ::rtl::OUString::createFromAscii( "HasMaster" ); 322 aNodeNames[1] = ::rtl::OUString::createFromAscii( "Master" ); 323 324 Sequence< Any > aPropertyValues = ConfigItem::GetProperties( aNodeNames ); 325 326 if( aPropertyValues.getLength() != aNodeNames.getLength() ) 327 { 328 OSL_ENSURE( aPropertyValues.getLength() == aNodeNames.getLength(), "Problems during reading\n" ); 329 return sal_False; 330 } 331 332 aPropertyValues[0] >>= hasEncoded; 333 aPropertyValues[1] >>= mEncoded; 334 335 aResult = mEncoded; 336 337 return hasEncoded; 338 } 339 340 //------------------------------------------------------------------------- 341 342 void StorageItem::setEncodedMP( const ::rtl::OUString& aEncoded, sal_Bool bAcceptEmpty ) 343 { 344 Sequence< ::rtl::OUString > sendNames(2); 345 Sequence< uno::Any > sendVals(2); 346 347 sendNames[0] = ::rtl::OUString::createFromAscii( "HasMaster" ); 348 sendNames[1] = ::rtl::OUString::createFromAscii( "Master" ); 349 350 sal_Bool bHasMaster = ( aEncoded.getLength() > 0 || bAcceptEmpty ); 351 sendVals[0] <<= bHasMaster; 352 sendVals[1] <<= aEncoded; 353 354 ConfigItem::SetModified(); 355 ConfigItem::PutProperties( sendNames, sendVals ); 356 357 hasEncoded = bHasMaster; 358 mEncoded = aEncoded; 359 } 360 361 //------------------------------------------------------------------------- 362 363 void StorageItem::remove( const ::rtl::OUString& aURL, const ::rtl::OUString& aName ) 364 { 365 vector < ::rtl::OUString > forIndex; 366 forIndex.push_back( aURL ); 367 forIndex.push_back( aName ); 368 369 Sequence< ::rtl::OUString > sendSeq(1); 370 371 sendSeq[0] = createIndex( forIndex ); 372 // sendSeq[0] = ::rtl::OUString::createFromAscii( "Store/Passwordstorage['" ); 373 // sendSeq[0] += createIndex( forIndex ); 374 // sendSeq[0] += ::rtl::OUString::createFromAscii( "']" ); 375 376 ConfigItem::ClearNodeElements( ::rtl::OUString::createFromAscii( "Store" ), sendSeq ); 377 } 378 379 //------------------------------------------------------------------------- 380 381 void StorageItem::clear() 382 { 383 Sequence< ::rtl::OUString > sendSeq(1); 384 385 ConfigItem::ClearNodeSet( ::rtl::OUString::createFromAscii( "Store" ) ); 386 } 387 388 //------------------------------------------------------------------------- 389 390 void StorageItem::update( const ::rtl::OUString& aURL, const NamePassRecord& aRecord ) 391 { 392 if ( !aRecord.HasPasswords( PERSISTENT_RECORD ) ) 393 { 394 OSL_ASSERT( "Unexpected storing of a record!" ); 395 return; 396 } 397 398 vector < ::rtl::OUString > forIndex; 399 forIndex.push_back( aURL ); 400 forIndex.push_back( aRecord.GetUserName() ); 401 402 Sequence< beans::PropertyValue > sendSeq(1); 403 404 sendSeq[0].Name = ::rtl::OUString::createFromAscii( "Store/Passwordstorage['" ); 405 sendSeq[0].Name += createIndex( forIndex ); 406 sendSeq[0].Name += ::rtl::OUString::createFromAscii( "']/Password" ); 407 408 sendSeq[0].Value <<= aRecord.GetPersPasswords(); 409 410 ConfigItem::SetModified(); 411 ConfigItem::SetSetProperties( ::rtl::OUString::createFromAscii( "Store" ), sendSeq ); 412 } 413 414 //------------------------------------------------------------------------- 415 416 void StorageItem::Notify( const Sequence< ::rtl::OUString >& ) 417 { 418 // this feature still should not be used 419 if( mainCont ) 420 mainCont->Notify(); 421 } 422 423 //------------------------------------------------------------------------- 424 425 void StorageItem::Commit() 426 { 427 // Do nothing, we stored everything we want already 428 } 429 430 //------------------------------------------------------------------------- 431 //------------------------------------------------------------------------- 432 433 PasswordContainer::PasswordContainer( const Reference<XMultiServiceFactory>& xServiceFactory ): 434 m_pStorageFile( NULL ) 435 { 436 // m_pStorageFile->Notify() can be called 437 ::osl::MutexGuard aGuard( mMutex ); 438 439 mComponent = Reference< XComponent >( xServiceFactory, UNO_QUERY ); 440 mComponent->addEventListener( this ); 441 442 m_pStorageFile = new StorageItem( this, ::rtl::OUString::createFromAscii( "Office.Common/Passwords" ) ); 443 if( m_pStorageFile ) 444 if( m_pStorageFile->useStorage() ) 445 m_aContainer = m_pStorageFile->getInfo(); 446 } 447 448 //------------------------------------------------------------------------- 449 450 PasswordContainer::~PasswordContainer() 451 { 452 ::osl::MutexGuard aGuard( mMutex ); 453 454 if( m_pStorageFile ) 455 { 456 delete m_pStorageFile; 457 m_pStorageFile = NULL; 458 } 459 460 if( mComponent.is() ) 461 { 462 mComponent->removeEventListener(this); 463 mComponent = Reference< XComponent >(); 464 } 465 } 466 467 //------------------------------------------------------------------------- 468 469 void SAL_CALL PasswordContainer::disposing( const EventObject& ) throw(RuntimeException) 470 { 471 ::osl::MutexGuard aGuard( mMutex ); 472 473 if( m_pStorageFile ) 474 { 475 delete m_pStorageFile; 476 m_pStorageFile = NULL; 477 } 478 479 if( mComponent.is() ) 480 { 481 //mComponent->removeEventListener(this); 482 mComponent = Reference< XComponent >(); 483 } 484 } 485 486 //------------------------------------------------------------------------- 487 488 vector< ::rtl::OUString > PasswordContainer::DecodePasswords( const ::rtl::OUString& aLine, const ::rtl::OUString& aMasterPasswd ) throw(RuntimeException) 489 { 490 if( aMasterPasswd.getLength() ) 491 { 492 rtlCipher aDecoder = rtl_cipher_create (rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeStream ); 493 OSL_ENSURE( aDecoder, "Can't create decoder\n" ); 494 495 if( aDecoder ) 496 { 497 OSL_ENSURE( aMasterPasswd.getLength() == RTL_DIGEST_LENGTH_MD5 * 2, "Wrong master password format!\n" ); 498 499 unsigned char code[RTL_DIGEST_LENGTH_MD5]; 500 for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ ) 501 code[ ind ] = (char)(aMasterPasswd.copy( ind*2, 2 ).toInt32(16)); 502 503 rtlCipherError result = rtl_cipher_init ( 504 aDecoder, rtl_Cipher_DirectionDecode, 505 code, RTL_DIGEST_LENGTH_MD5, NULL, 0 ); 506 507 if( result == rtl_Cipher_E_None ) 508 { 509 ::rtl::ByteSequence aSeq = getBufFromAsciiLine( aLine ); 510 511 ::rtl::ByteSequence resSeq( aSeq.getLength() ); 512 513 result = rtl_cipher_decode ( aDecoder, (sal_uInt8*)aSeq.getArray(), aSeq.getLength(), 514 (sal_uInt8*)resSeq.getArray(), resSeq.getLength() ); 515 516 ::rtl::OUString aPasswd( ( sal_Char* )resSeq.getArray(), resSeq.getLength(), RTL_TEXTENCODING_UTF8 ); 517 518 rtl_cipher_destroy (aDecoder); 519 520 return getInfoFromInd( aPasswd ); 521 } 522 523 rtl_cipher_destroy (aDecoder); 524 } 525 } 526 else 527 { 528 OSL_ENSURE( sal_False, "No master password provided!\n" ); 529 // throw special exception 530 } 531 532 // problems with decoding 533 OSL_ENSURE( sal_False, "Problem with decoding\n" ); 534 throw RuntimeException( ::rtl::OUString::createFromAscii( "Can't decode!" ), Reference< XInterface >() ); 535 } 536 537 538 //------------------------------------------------------------------------- 539 540 ::rtl::OUString PasswordContainer::EncodePasswords( vector< ::rtl::OUString > lines, const ::rtl::OUString& aMasterPasswd ) throw(RuntimeException) 541 { 542 if( aMasterPasswd.getLength() ) 543 { 544 ::rtl::OString aSeq = ::rtl::OUStringToOString( createIndex( lines ), RTL_TEXTENCODING_UTF8 ); 545 546 rtlCipher aEncoder = rtl_cipher_create (rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeStream ); 547 OSL_ENSURE( aEncoder, "Can't create encoder\n" ); 548 549 if( aEncoder ) 550 { 551 OSL_ENSURE( aMasterPasswd.getLength() == RTL_DIGEST_LENGTH_MD5 * 2, "Wrong master password format!\n" ); 552 553 unsigned char code[RTL_DIGEST_LENGTH_MD5]; 554 for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ ) 555 code[ ind ] = (char)(aMasterPasswd.copy( ind*2, 2 ).toInt32(16)); 556 557 rtlCipherError result = rtl_cipher_init ( 558 aEncoder, rtl_Cipher_DirectionEncode, 559 code, RTL_DIGEST_LENGTH_MD5, NULL, 0 ); 560 561 if( result == rtl_Cipher_E_None ) 562 { 563 ::rtl::ByteSequence resSeq(aSeq.getLength()+1); 564 565 result = rtl_cipher_encode ( aEncoder, (sal_uInt8*)aSeq.getStr(), aSeq.getLength()+1, 566 (sal_uInt8*)resSeq.getArray(), resSeq.getLength() ); 567 568 /* 569 //test 570 rtlCipherError result = rtl_cipher_init ( 571 aEncoder, rtl_Cipher_DirectionDecode, 572 code, RTL_DIGEST_LENGTH_MD5, NULL, 0 ); 573 574 575 if( result == rtl_Cipher_E_None ) 576 { 577 ::rtl::OUString testOU = getAsciiLine( resSeq ); 578 ::rtl::ByteSequence aSeq1 = getBufFromAsciiLine( testOU ); 579 580 ::rtl::ByteSequence resSeq1( aSeq1.getLength() ); 581 582 if( resSeq.getLength() == aSeq1.getLength() ) 583 { 584 for( int ind = 0; ind < aSeq1.getLength(); ind++ ) 585 if( resSeq[ind] != aSeq1[ind] ) 586 testOU = ::rtl::OUString(); 587 } 588 589 result = rtl_cipher_decode ( aEncoder, (sal_uInt8*)aSeq1.getArray(), aSeq1.getLength(), 590 (sal_uInt8*)resSeq1.getArray(), resSeq1.getLength() ); 591 592 ::rtl::OUString aPasswd( ( sal_Char* )resSeq1.getArray(), resSeq1.getLength(), RTL_TEXTENCODING_UTF8 ); 593 } 594 */ 595 596 rtl_cipher_destroy (aEncoder); 597 598 if( result == rtl_Cipher_E_None ) 599 return getAsciiLine( resSeq ); 600 601 } 602 603 rtl_cipher_destroy (aEncoder); 604 } 605 } 606 else 607 { 608 OSL_ENSURE( sal_False, "No master password provided!\n" ); 609 // throw special exception 610 } 611 612 // problems with encoding 613 OSL_ENSURE( sal_False, "Problem with encoding\n" ); 614 throw RuntimeException( ::rtl::OUString::createFromAscii( "Can't encode!" ), Reference< XInterface >() ); 615 } 616 617 //------------------------------------------------------------------------- 618 619 void PasswordContainer::UpdateVector( const ::rtl::OUString& aURL, list< NamePassRecord >& toUpdate, NamePassRecord& aRecord, sal_Bool writeFile ) throw(RuntimeException) 620 { 621 for( list< NamePassRecord >::iterator aNPIter = toUpdate.begin(); aNPIter != toUpdate.end(); aNPIter++ ) 622 if( aNPIter->GetUserName().equals( aRecord.GetUserName() ) ) 623 { 624 if( aRecord.HasPasswords( MEMORY_RECORD ) ) 625 aNPIter->SetMemPasswords( aRecord.GetMemPasswords() ); 626 627 if( aRecord.HasPasswords( PERSISTENT_RECORD ) ) 628 { 629 aNPIter->SetPersPasswords( aRecord.GetPersPasswords() ); 630 631 if( writeFile ) 632 { 633 // the password must be already encoded 634 m_pStorageFile->update( aURL, aRecord ); // change existing ( aURL, aName ) record in the configfile 635 } 636 } 637 638 return; 639 } 640 641 642 if( aRecord.HasPasswords( PERSISTENT_RECORD ) && writeFile ) 643 { 644 // the password must be already encoded 645 m_pStorageFile->update( aURL, aRecord ); // add new aName to the existing url 646 } 647 648 toUpdate.insert( toUpdate.begin(), aRecord ); 649 } 650 651 //------------------------------------------------------------------------- 652 653 UserRecord PasswordContainer::CopyToUserRecord( const NamePassRecord& aRecord, sal_Bool& io_bTryToDecode, const Reference< XInteractionHandler >& aHandler ) 654 { 655 ::std::vector< ::rtl::OUString > aPasswords; 656 if( aRecord.HasPasswords( MEMORY_RECORD ) ) 657 aPasswords = aRecord.GetMemPasswords(); 658 659 if( io_bTryToDecode && aRecord.HasPasswords( PERSISTENT_RECORD ) ) 660 { 661 try 662 { 663 ::std::vector< ::rtl::OUString > aDecodedPasswords = DecodePasswords( aRecord.GetPersPasswords(), GetMasterPassword( aHandler ) ); 664 aPasswords.insert( aPasswords.end(), aDecodedPasswords.begin(), aDecodedPasswords.end() ); 665 } 666 catch( NoMasterException& ) 667 { 668 // if master password could not be detected the entry will be just ignored 669 io_bTryToDecode = sal_False; 670 } 671 } 672 673 return UserRecord( aRecord.GetUserName(), copyVectorToSequence( aPasswords ) ); 674 } 675 676 //------------------------------------------------------------------------- 677 678 Sequence< UserRecord > PasswordContainer::CopyToUserRecordSequence( const list< NamePassRecord >& original, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException) 679 { 680 Sequence< UserRecord > aResult( original.size() ); 681 sal_uInt32 nInd = 0; 682 sal_Bool bTryToDecode = sal_True; 683 684 for( list< NamePassRecord >::const_iterator aNPIter = original.begin(); 685 aNPIter != original.end(); 686 aNPIter++, nInd++ ) 687 { 688 aResult[nInd] = CopyToUserRecord( *aNPIter, bTryToDecode, aHandler ); 689 } 690 691 return aResult; 692 } 693 694 //------------------------------------------------------------------------- 695 696 void SAL_CALL PasswordContainer::add( const ::rtl::OUString& Url, const ::rtl::OUString& UserName, const Sequence< ::rtl::OUString >& Passwords, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException) 697 { 698 ::osl::MutexGuard aGuard( mMutex ); 699 700 PrivateAdd( Url, UserName, Passwords, MEMORY_RECORD, aHandler ); 701 } 702 703 //------------------------------------------------------------------------- 704 705 void SAL_CALL PasswordContainer::addPersistent( const ::rtl::OUString& Url, const ::rtl::OUString& UserName, const Sequence< ::rtl::OUString >& Passwords, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException) 706 { 707 ::osl::MutexGuard aGuard( mMutex ); 708 709 PrivateAdd( Url, UserName, Passwords, PERSISTENT_RECORD, aHandler ); 710 } 711 712 //------------------------------------------------------------------------- 713 714 void PasswordContainer::PrivateAdd( const ::rtl::OUString& Url, const ::rtl::OUString& UserName, const Sequence< ::rtl::OUString >& Passwords, char Mode, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException) 715 { 716 NamePassRecord aRecord( UserName ); 717 ::std::vector< ::rtl::OUString > aStorePass = copySequenceToVector( Passwords ); 718 719 if( Mode == PERSISTENT_RECORD ) 720 aRecord.SetPersPasswords( EncodePasswords( aStorePass, GetMasterPassword( aHandler ) ) ); 721 else if( Mode == MEMORY_RECORD ) 722 aRecord.SetMemPasswords( aStorePass ); 723 else 724 { 725 OSL_ASSERT( "Unexpected persistence status!" ); 726 return; 727 } 728 729 if( !m_aContainer.empty() ) 730 { 731 PassMap::iterator aIter = m_aContainer.find( Url ); 732 733 if( aIter != m_aContainer.end() ) 734 { 735 UpdateVector( aIter->first, aIter->second, aRecord, sal_True ); 736 return; 737 } 738 } 739 740 list< NamePassRecord > listToAdd( 1, aRecord ); 741 m_aContainer.insert( PairUrlRecord( Url, listToAdd ) ); 742 743 if( Mode == PERSISTENT_RECORD && m_pStorageFile && m_pStorageFile->useStorage() ) 744 m_pStorageFile->update( Url, aRecord ); 745 746 } 747 748 //------------------------------------------------------------------------- 749 750 751 UrlRecord SAL_CALL PasswordContainer::find( const ::rtl::OUString& aURL, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException) 752 { 753 return find( aURL, rtl::OUString(), false, aHandler ); 754 } 755 756 //------------------------------------------------------------------------- 757 758 UrlRecord SAL_CALL PasswordContainer::findForName( const ::rtl::OUString& aURL, const ::rtl::OUString& aName, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException) 759 { 760 return find( aURL, aName, true, aHandler ); 761 } 762 763 //------------------------------------------------------------------------- 764 765 Sequence< UserRecord > PasswordContainer::FindUsr( const list< NamePassRecord >& userlist, const ::rtl::OUString& aName, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException) 766 { 767 sal_uInt32 nInd = 0; 768 for( list< NamePassRecord >::const_iterator aNPIter = userlist.begin(); 769 aNPIter != userlist.end(); 770 aNPIter++, nInd++ ) 771 { 772 if( aNPIter->GetUserName().equals( aName ) ) 773 { 774 Sequence< UserRecord > aResult(1); 775 sal_Bool bTryToDecode = sal_True; 776 aResult[0] = CopyToUserRecord( *aNPIter, bTryToDecode, aHandler ); 777 778 return aResult; 779 } 780 } 781 782 return Sequence< UserRecord >(); 783 } 784 785 //------------------------------------------------------------------------- 786 787 bool PasswordContainer::createUrlRecord( 788 const PassMap::iterator & rIter, 789 bool bName, 790 const ::rtl::OUString & aName, 791 const Reference< XInteractionHandler >& aHandler, 792 UrlRecord & rRec ) 793 throw( RuntimeException ) 794 { 795 if ( bName ) 796 { 797 Sequence< UserRecord > aUsrRec 798 = FindUsr( rIter->second, aName, aHandler ); 799 if( aUsrRec.getLength() ) 800 { 801 rRec = UrlRecord( rIter->first, aUsrRec ); 802 return true; 803 } 804 } 805 else 806 { 807 rRec = UrlRecord( 808 rIter->first, 809 CopyToUserRecordSequence( rIter->second, aHandler ) ); 810 return true; 811 } 812 return false; 813 } 814 815 //------------------------------------------------------------------------- 816 817 UrlRecord PasswordContainer::find( 818 const ::rtl::OUString& aURL, 819 const ::rtl::OUString& aName, 820 bool bName, // only needed to support empty user names 821 const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException) 822 { 823 ::osl::MutexGuard aGuard( mMutex ); 824 825 if( !m_aContainer.empty() && aURL.getLength() ) 826 { 827 ::rtl::OUString aUrl( aURL ); 828 829 // each iteration remove last '/...' section from the aUrl 830 // while it's possible, up to the most left '://' 831 do 832 { 833 // first look for <url>/somename and then look for <url>/somename/... 834 PassMap::iterator aIter = m_aContainer.find( aUrl ); 835 if( aIter != m_aContainer.end() ) 836 { 837 UrlRecord aRec; 838 if ( createUrlRecord( aIter, bName, aName, aHandler, aRec ) ) 839 return aRec; 840 } 841 else 842 { 843 ::rtl::OUString tmpUrl( aUrl ); 844 if ( tmpUrl.getStr()[tmpUrl.getLength() - 1] != (sal_Unicode)'/' ) 845 tmpUrl += ::rtl::OUString::createFromAscii( "/" ); 846 847 aIter = m_aContainer.lower_bound( tmpUrl ); 848 if( aIter != m_aContainer.end() && aIter->first.match( tmpUrl ) ) 849 { 850 UrlRecord aRec; 851 if ( createUrlRecord( aIter, bName, aName, aHandler, aRec ) ) 852 return aRec; 853 } 854 } 855 } 856 while( shorterUrl( aUrl ) && aUrl.getLength() ); 857 } 858 859 return UrlRecord(); 860 } 861 862 //------------------------------------------------------------------------- 863 ::rtl::OUString PasswordContainer::GetDefaultMasterPassword() 864 { 865 ::rtl::OUString aResult; 866 for ( sal_Int32 nInd = 0; nInd < RTL_DIGEST_LENGTH_MD5; nInd++ ) 867 aResult += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "aa" ) ); 868 869 return aResult; 870 } 871 872 //------------------------------------------------------------------------- 873 ::rtl::OUString PasswordContainer::RequestPasswordFromUser( PasswordRequestMode aRMode, const uno::Reference< task::XInteractionHandler >& xHandler ) 874 { 875 // empty string means that the call was cancelled or just failed 876 ::rtl::OUString aResult; 877 878 if ( xHandler.is() ) 879 { 880 ::rtl::Reference< MasterPasswordRequest_Impl > xRequest = new MasterPasswordRequest_Impl( aRMode ); 881 882 xHandler->handle( xRequest.get() ); 883 884 ::rtl::Reference< ucbhelper::InteractionContinuation > xSelection = xRequest->getSelection(); 885 886 if ( xSelection.is() ) 887 { 888 Reference< XInteractionAbort > xAbort( xSelection.get(), UNO_QUERY ); 889 if ( !xAbort.is() ) 890 { 891 const ::rtl::Reference< ucbhelper::InteractionSupplyAuthentication > & xSupp 892 = xRequest->getAuthenticationSupplier(); 893 894 aResult = xSupp->getPassword(); 895 } 896 } 897 } 898 899 return aResult; 900 } 901 902 //------------------------------------------------------------------------- 903 904 ::rtl::OUString PasswordContainer::GetMasterPassword( const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException) 905 { 906 PasswordRequestMode aRMode = PasswordRequestMode_PASSWORD_ENTER; 907 if( !m_pStorageFile || !m_pStorageFile->useStorage() ) 908 throw NoMasterException( ::rtl::OUString::createFromAscii( "Password storing is not active!" ), Reference< XInterface >(), aRMode ); 909 910 if( !m_aMasterPasswd.getLength() && aHandler.is() ) 911 { 912 ::rtl::OUString aEncodedMP; 913 sal_Bool bAskAgain = sal_False; 914 sal_Bool bDefaultPassword = sal_False; 915 916 if( !m_pStorageFile->getEncodedMP( aEncodedMP ) ) 917 aRMode = PasswordRequestMode_PASSWORD_CREATE; 918 else if ( !aEncodedMP.getLength() ) 919 { 920 m_aMasterPasswd = GetDefaultMasterPassword(); 921 bDefaultPassword = sal_True; 922 } 923 924 if ( !bDefaultPassword ) 925 { 926 do { 927 bAskAgain = sal_False; 928 929 ::rtl::OUString aPass = RequestPasswordFromUser( aRMode, aHandler ); 930 if ( aPass.getLength() ) 931 { 932 if( aRMode == PasswordRequestMode_PASSWORD_CREATE ) 933 { 934 m_aMasterPasswd = aPass; 935 vector< ::rtl::OUString > aMaster( 1, m_aMasterPasswd ); 936 937 m_pStorageFile->setEncodedMP( EncodePasswords( aMaster, m_aMasterPasswd ) ); 938 } 939 else 940 { 941 vector< ::rtl::OUString > aRM( DecodePasswords( aEncodedMP, aPass ) ); 942 if( !aRM.size() || !aPass.equals( aRM[0] ) ) 943 { 944 bAskAgain = sal_True; 945 aRMode = PasswordRequestMode_PASSWORD_REENTER; 946 } 947 else 948 m_aMasterPasswd = aPass; 949 } 950 } 951 952 } while( bAskAgain ); 953 } 954 } 955 956 if ( !m_aMasterPasswd.getLength() ) 957 throw NoMasterException( ::rtl::OUString::createFromAscii( "No master password!" ), Reference< XInterface >(), aRMode ); 958 959 return m_aMasterPasswd; 960 } 961 962 //------------------------------------------------------------------------- 963 964 void SAL_CALL PasswordContainer::remove( const ::rtl::OUString& aURL, const ::rtl::OUString& aName ) throw(RuntimeException) 965 { 966 ::osl::MutexGuard aGuard( mMutex ); 967 968 ::rtl::OUString aUrl( aURL ); 969 if( !m_aContainer.empty() ) 970 { 971 PassMap::iterator aIter = m_aContainer.find( aUrl ); 972 973 if( aIter == m_aContainer.end() ) 974 { 975 sal_Int32 aInd = aUrl.lastIndexOf( sal_Unicode( '/' ) ); 976 if( aInd > 0 && aUrl.getLength()-1 == aInd ) 977 aUrl = aUrl.copy( 0, aUrl.getLength() - 1 ); 978 else 979 aUrl += ::rtl::OUString::createFromAscii( "/" ); 980 981 aIter = m_aContainer.find( aUrl ); 982 } 983 984 if( aIter != m_aContainer.end() ) 985 { 986 for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); aNPIter++ ) 987 if( aNPIter->GetUserName().equals( aName ) ) 988 { 989 if( aNPIter->HasPasswords( PERSISTENT_RECORD ) && m_pStorageFile ) 990 m_pStorageFile->remove( aURL, aName ); // remove record ( aURL, aName ) 991 992 // the iterator will not be used any more so it can be removed directly 993 aIter->second.erase( aNPIter ); 994 995 if( aIter->second.begin() == aIter->second.end() ) 996 m_aContainer.erase( aIter ); 997 998 return; 999 } 1000 } 1001 } 1002 } 1003 1004 //------------------------------------------------------------------------- 1005 1006 void SAL_CALL PasswordContainer::removePersistent( const ::rtl::OUString& aURL, const ::rtl::OUString& aName ) throw(RuntimeException) 1007 { 1008 ::osl::MutexGuard aGuard( mMutex ); 1009 1010 ::rtl::OUString aUrl( aURL ); 1011 if( !m_aContainer.empty() ) 1012 { 1013 PassMap::iterator aIter = m_aContainer.find( aUrl ); 1014 1015 if( aIter == m_aContainer.end() ) 1016 { 1017 sal_Int32 aInd = aUrl.lastIndexOf( sal_Unicode( '/' ) ); 1018 if( aInd > 0 && aUrl.getLength()-1 == aInd ) 1019 aUrl = aUrl.copy( 0, aUrl.getLength() - 1 ); 1020 else 1021 aUrl += ::rtl::OUString::createFromAscii( "/" ); 1022 1023 aIter = m_aContainer.find( aUrl ); 1024 } 1025 1026 if( aIter != m_aContainer.end() ) 1027 { 1028 for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); aNPIter++ ) 1029 if( aNPIter->GetUserName().equals( aName ) ) 1030 { 1031 if( aNPIter->HasPasswords( PERSISTENT_RECORD ) ) 1032 { 1033 // TODO/LATER: should the password be converted to MemoryPassword? 1034 aNPIter->RemovePasswords( PERSISTENT_RECORD ); 1035 1036 if ( m_pStorageFile ) 1037 m_pStorageFile->remove( aURL, aName ); // remove record ( aURL, aName ) 1038 } 1039 1040 if( !aNPIter->HasPasswords( MEMORY_RECORD ) ) 1041 aIter->second.erase( aNPIter ); 1042 1043 if( aIter->second.begin() == aIter->second.end() ) 1044 m_aContainer.erase( aIter ); 1045 1046 return; 1047 } 1048 } 1049 } 1050 } 1051 //------------------------------------------------------------------------- 1052 1053 void SAL_CALL PasswordContainer::removeAllPersistent() throw(RuntimeException) 1054 { 1055 ::osl::MutexGuard aGuard( mMutex ); 1056 1057 if( m_pStorageFile ) 1058 m_pStorageFile->clear(); 1059 1060 for( PassMap::iterator aIter = m_aContainer.begin(); aIter != m_aContainer.end(); ) 1061 { 1062 for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); ) 1063 { 1064 if( aNPIter->HasPasswords( PERSISTENT_RECORD ) ) 1065 { 1066 // TODO/LATER: should the password be converted to MemoryPassword? 1067 aNPIter->RemovePasswords( PERSISTENT_RECORD ); 1068 1069 if ( m_pStorageFile ) 1070 m_pStorageFile->remove( aIter->first, aNPIter->GetUserName() ); // remove record ( aURL, aName ) 1071 } 1072 1073 if( !aNPIter->HasPasswords( MEMORY_RECORD ) ) 1074 { 1075 list< NamePassRecord >::iterator aIterToDelete( aNPIter ); 1076 aNPIter++; 1077 aIter->second.erase( aIterToDelete ); 1078 } 1079 else 1080 aNPIter++; 1081 } 1082 1083 if( aIter->second.begin() == aIter->second.end() ) 1084 { 1085 PassMap::iterator aIterToDelete( aIter ); 1086 aIter++; 1087 m_aContainer.erase( aIterToDelete ); 1088 } 1089 else 1090 aIter++; 1091 } 1092 } 1093 //------------------------------------------------------------------------- 1094 1095 Sequence< UrlRecord > SAL_CALL PasswordContainer::getAllPersistent( const Reference< XInteractionHandler >& xHandler ) throw(RuntimeException) 1096 { 1097 Sequence< UrlRecord > aResult; 1098 1099 ::osl::MutexGuard aGuard( mMutex ); 1100 for( PassMap::iterator aIter = m_aContainer.begin(); aIter != m_aContainer.end(); aIter++ ) 1101 { 1102 Sequence< UserRecord > aUsers; 1103 for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); aNPIter++ ) 1104 if( aNPIter->HasPasswords( PERSISTENT_RECORD ) ) 1105 { 1106 sal_Int32 oldLen = aUsers.getLength(); 1107 aUsers.realloc( oldLen + 1 ); 1108 aUsers[ oldLen ] = UserRecord( aNPIter->GetUserName(), copyVectorToSequence( DecodePasswords( aNPIter->GetPersPasswords(), GetMasterPassword( xHandler ) ) ) ); 1109 } 1110 1111 if( aUsers.getLength() ) 1112 { 1113 sal_Int32 oldLen = aResult.getLength(); 1114 aResult.realloc( oldLen + 1 ); 1115 aResult[ oldLen ] = UrlRecord( aIter->first, aUsers ); 1116 } 1117 } 1118 1119 return aResult; 1120 } 1121 1122 //------------------------------------------------------------------------- 1123 sal_Bool SAL_CALL PasswordContainer::authorizateWithMasterPassword( const uno::Reference< task::XInteractionHandler >& xHandler ) 1124 throw (uno::RuntimeException) 1125 { 1126 sal_Bool bResult = sal_False; 1127 ::rtl::OUString aEncodedMP; 1128 uno::Reference< task::XInteractionHandler > xTmpHandler = xHandler; 1129 ::osl::MutexGuard aGuard( mMutex ); 1130 1131 // the method should fail if there is no master password 1132 if( m_pStorageFile && m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) ) 1133 { 1134 if ( !aEncodedMP.getLength() ) 1135 { 1136 // this is a default master password 1137 // no UI is necessary 1138 bResult = sal_True; 1139 } 1140 else 1141 { 1142 if ( !xTmpHandler.is() ) 1143 { 1144 uno::Reference< lang::XMultiServiceFactory > xFactory( mComponent, uno::UNO_QUERY_THROW ); 1145 xTmpHandler.set( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.InteractionHandler" ) ) ), uno::UNO_QUERY_THROW ); 1146 } 1147 1148 if ( m_aMasterPasswd.getLength() ) 1149 { 1150 // there is a password, it should be just rechecked 1151 PasswordRequestMode aRMode = PasswordRequestMode_PASSWORD_ENTER; 1152 ::rtl::OUString aPass; 1153 1154 do { 1155 aPass = RequestPasswordFromUser( aRMode, xTmpHandler ); 1156 bResult = ( aPass.getLength() && aPass.equals( m_aMasterPasswd ) ); 1157 aRMode = PasswordRequestMode_PASSWORD_REENTER; // further questions with error notification 1158 } while( !bResult && aPass.getLength() ); 1159 } 1160 else 1161 { 1162 try 1163 { 1164 // ask for the password, if user provide no correct password an exception will be thrown 1165 bResult = ( GetMasterPassword( xTmpHandler ).getLength() > 0 ); 1166 } 1167 catch( uno::Exception& ) 1168 {} 1169 } 1170 } 1171 } 1172 1173 return bResult; 1174 } 1175 1176 //------------------------------------------------------------------------- 1177 sal_Bool SAL_CALL PasswordContainer::changeMasterPassword( const uno::Reference< task::XInteractionHandler >& xHandler ) 1178 throw (uno::RuntimeException) 1179 { 1180 sal_Bool bResult = sal_False; 1181 uno::Reference< task::XInteractionHandler > xTmpHandler = xHandler; 1182 ::osl::MutexGuard aGuard( mMutex ); 1183 1184 if ( m_pStorageFile && m_pStorageFile->useStorage() ) 1185 { 1186 if ( !xTmpHandler.is() ) 1187 { 1188 uno::Reference< lang::XMultiServiceFactory > xFactory( mComponent, uno::UNO_QUERY_THROW ); 1189 xTmpHandler.set( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.InteractionHandler" ) ) ), uno::UNO_QUERY_THROW ); 1190 } 1191 1192 sal_Bool bCanChangePassword = sal_True; 1193 // if there is already a stored master password it should be entered by the user before the change happen 1194 ::rtl::OUString aEncodedMP; 1195 if( m_aMasterPasswd.getLength() || m_pStorageFile->getEncodedMP( aEncodedMP ) ) 1196 bCanChangePassword = authorizateWithMasterPassword( xTmpHandler ); 1197 1198 if ( bCanChangePassword ) 1199 { 1200 // ask for the new password, but do not set it 1201 PasswordRequestMode aRMode = PasswordRequestMode_PASSWORD_CREATE; 1202 ::rtl::OUString aPass = RequestPasswordFromUser( aRMode, xTmpHandler ); 1203 1204 if ( aPass.getLength() ) 1205 { 1206 // get all the persistent entries if it is possible 1207 Sequence< UrlRecord > aPersistent = getAllPersistent( uno::Reference< task::XInteractionHandler >() ); 1208 1209 // remove the master password and the entries persistence 1210 removeMasterPassword(); 1211 1212 // store the new master password 1213 m_aMasterPasswd = aPass; 1214 vector< ::rtl::OUString > aMaster( 1, m_aMasterPasswd ); 1215 m_pStorageFile->setEncodedMP( EncodePasswords( aMaster, m_aMasterPasswd ) ); 1216 1217 // store all the entries with the new password 1218 for ( int nURLInd = 0; nURLInd < aPersistent.getLength(); nURLInd++ ) 1219 for ( int nNameInd = 0; nNameInd< aPersistent[nURLInd].UserList.getLength(); nNameInd++ ) 1220 addPersistent( aPersistent[nURLInd].Url, 1221 aPersistent[nURLInd].UserList[nNameInd].UserName, 1222 aPersistent[nURLInd].UserList[nNameInd].Passwords, 1223 uno::Reference< task::XInteractionHandler >() ); 1224 1225 bResult = sal_True; 1226 } 1227 } 1228 } 1229 1230 return bResult; 1231 } 1232 1233 //------------------------------------------------------------------------- 1234 void SAL_CALL PasswordContainer::removeMasterPassword() 1235 throw (uno::RuntimeException) 1236 { 1237 // remove all the stored passwords and the master password 1238 removeAllPersistent(); 1239 1240 ::osl::MutexGuard aGuard( mMutex ); 1241 if ( m_pStorageFile ) 1242 { 1243 m_aMasterPasswd = ::rtl::OUString(); 1244 m_pStorageFile->setEncodedMP( ::rtl::OUString() ); // let the master password be removed from configuration 1245 } 1246 } 1247 1248 //------------------------------------------------------------------------- 1249 ::sal_Bool SAL_CALL PasswordContainer::hasMasterPassword( ) 1250 throw (::com::sun::star::uno::RuntimeException) 1251 { 1252 ::osl::MutexGuard aGuard( mMutex ); 1253 1254 if ( !m_pStorageFile ) 1255 throw uno::RuntimeException(); 1256 1257 ::rtl::OUString aEncodedMP; 1258 return ( m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) ); 1259 } 1260 1261 //------------------------------------------------------------------------- 1262 ::sal_Bool SAL_CALL PasswordContainer::allowPersistentStoring( ::sal_Bool bAllow ) 1263 throw (::com::sun::star::uno::RuntimeException) 1264 { 1265 ::osl::MutexGuard aGuard( mMutex ); 1266 1267 if ( !m_pStorageFile ) 1268 throw uno::RuntimeException(); 1269 1270 if ( !bAllow ) 1271 removeMasterPassword(); 1272 1273 if ( m_pStorageFile->useStorage() == bAllow ) 1274 return bAllow; 1275 1276 m_pStorageFile->setUseStorage( bAllow ); 1277 return !bAllow; 1278 } 1279 1280 //------------------------------------------------------------------------- 1281 ::sal_Bool SAL_CALL PasswordContainer::isPersistentStoringAllowed() 1282 throw (::com::sun::star::uno::RuntimeException) 1283 { 1284 ::osl::MutexGuard aGuard( mMutex ); 1285 1286 if ( !m_pStorageFile ) 1287 throw uno::RuntimeException(); 1288 1289 return m_pStorageFile->useStorage(); 1290 } 1291 1292 //------------------------------------------------------------------------- 1293 ::sal_Bool SAL_CALL PasswordContainer::useDefaultMasterPassword( const uno::Reference< task::XInteractionHandler >& xHandler ) 1294 throw ( uno::RuntimeException ) 1295 { 1296 sal_Bool bResult = sal_False; 1297 uno::Reference< task::XInteractionHandler > xTmpHandler = xHandler; 1298 ::osl::MutexGuard aGuard( mMutex ); 1299 1300 if ( m_pStorageFile && m_pStorageFile->useStorage() ) 1301 { 1302 if ( !xTmpHandler.is() ) 1303 { 1304 uno::Reference< lang::XMultiServiceFactory > xFactory( mComponent, uno::UNO_QUERY_THROW ); 1305 xTmpHandler.set( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.InteractionHandler" ) ) ), uno::UNO_QUERY_THROW ); 1306 } 1307 1308 sal_Bool bCanChangePassword = sal_True; 1309 // if there is already a stored nondefault master password it should be entered by the user before the change happen 1310 ::rtl::OUString aEncodedMP; 1311 if( m_pStorageFile->getEncodedMP( aEncodedMP ) && aEncodedMP.getLength() ) 1312 bCanChangePassword = authorizateWithMasterPassword( xTmpHandler ); 1313 1314 if ( bCanChangePassword ) 1315 { 1316 // generate the default password 1317 ::rtl::OUString aPass = GetDefaultMasterPassword(); 1318 if ( aPass.getLength() ) 1319 { 1320 // get all the persistent entries if it is possible 1321 Sequence< UrlRecord > aPersistent = getAllPersistent( uno::Reference< task::XInteractionHandler >() ); 1322 1323 // remove the master password and the entries persistence 1324 removeMasterPassword(); 1325 1326 // store the empty string to flag the default master password 1327 m_aMasterPasswd = aPass; 1328 m_pStorageFile->setEncodedMP( ::rtl::OUString(), sal_True ); 1329 1330 // store all the entries with the new password 1331 for ( int nURLInd = 0; nURLInd < aPersistent.getLength(); nURLInd++ ) 1332 for ( int nNameInd = 0; nNameInd< aPersistent[nURLInd].UserList.getLength(); nNameInd++ ) 1333 addPersistent( aPersistent[nURLInd].Url, 1334 aPersistent[nURLInd].UserList[nNameInd].UserName, 1335 aPersistent[nURLInd].UserList[nNameInd].Passwords, 1336 uno::Reference< task::XInteractionHandler >() ); 1337 1338 bResult = sal_True; 1339 } 1340 } 1341 } 1342 1343 return bResult; 1344 1345 } 1346 1347 //------------------------------------------------------------------------- 1348 ::sal_Bool SAL_CALL PasswordContainer::isDefaultMasterPasswordUsed() 1349 throw ( uno::RuntimeException ) 1350 { 1351 ::osl::MutexGuard aGuard( mMutex ); 1352 1353 if ( !m_pStorageFile ) 1354 throw uno::RuntimeException(); 1355 1356 ::rtl::OUString aEncodedMP; 1357 return ( m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) && !aEncodedMP.getLength() ); 1358 } 1359 1360 1361 //------------------------------------------------------------------------- 1362 void SAL_CALL PasswordContainer::addUrl( const ::rtl::OUString& Url, ::sal_Bool MakePersistent ) 1363 throw (uno::RuntimeException) 1364 { 1365 mUrlContainer.add( Url, MakePersistent ); 1366 } 1367 1368 //------------------------------------------------------------------------- 1369 ::rtl::OUString SAL_CALL PasswordContainer::findUrl( const ::rtl::OUString& Url ) 1370 throw (uno::RuntimeException) 1371 { 1372 return mUrlContainer.find( Url ); 1373 } 1374 1375 //------------------------------------------------------------------------- 1376 void SAL_CALL PasswordContainer::removeUrl( const ::rtl::OUString& Url ) 1377 throw (uno::RuntimeException) 1378 { 1379 mUrlContainer.remove( Url ); 1380 } 1381 1382 //------------------------------------------------------------------------- 1383 uno::Sequence< ::rtl::OUString > SAL_CALL PasswordContainer::getUrls( ::sal_Bool OnlyPersistent ) 1384 throw (uno::RuntimeException) 1385 { 1386 return mUrlContainer.list( OnlyPersistent ); 1387 } 1388 1389 //------------------------------------------------------------------------- 1390 1391 void PasswordContainer::Notify() 1392 { 1393 ::osl::MutexGuard aGuard( mMutex ); 1394 1395 PassMap::iterator aIter; 1396 1397 // remove the cached persistent values in the memory 1398 for( aIter = m_aContainer.begin(); aIter != m_aContainer.end(); aIter++ ) 1399 { 1400 for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); ) 1401 { 1402 if( aNPIter->HasPasswords( PERSISTENT_RECORD ) ) 1403 { 1404 aNPIter->RemovePasswords( PERSISTENT_RECORD ); 1405 1406 if ( m_pStorageFile ) 1407 m_pStorageFile->remove( aIter->first, aNPIter->GetUserName() ); // remove record ( aURL, aName ) 1408 } 1409 1410 if( !aNPIter->HasPasswords( MEMORY_RECORD ) ) 1411 { 1412 list< NamePassRecord >::iterator aIterToDelete( aNPIter ); 1413 aNPIter++; 1414 aIter->second.erase( aIterToDelete ); 1415 } 1416 else 1417 aNPIter++; 1418 } 1419 } 1420 1421 PassMap addon; 1422 if( m_pStorageFile ) 1423 addon = m_pStorageFile->getInfo(); 1424 1425 for( aIter = addon.begin(); aIter != addon.end(); aIter++ ) 1426 { 1427 PassMap::iterator aSearchIter = m_aContainer.find( aIter->first ); 1428 if( aSearchIter != m_aContainer.end() ) 1429 for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); aNPIter++ ) 1430 UpdateVector( aSearchIter->first, aSearchIter->second, *aNPIter, sal_False ); 1431 else 1432 m_aContainer.insert( PairUrlRecord( aIter->first, aIter->second ) ); 1433 } 1434 } 1435 1436 //------------------------------------------------------------------------- 1437 1438 ::rtl::OUString SAL_CALL PasswordContainer::getImplementationName( ) throw(uno::RuntimeException) 1439 { 1440 return impl_getStaticImplementationName(); 1441 } 1442 1443 //------------------------------------------------------------------------- 1444 1445 sal_Bool SAL_CALL PasswordContainer::supportsService( const ::rtl::OUString& ServiceName ) throw(uno::RuntimeException) 1446 { 1447 if ( ServiceName.compareToAscii("com.sun.star.task.PasswordContainer") == 0 ) 1448 return sal_True; 1449 else 1450 return sal_False; 1451 } 1452 1453 //------------------------------------------------------------------------- 1454 1455 Sequence< ::rtl::OUString > SAL_CALL PasswordContainer::getSupportedServiceNames( ) throw(uno::RuntimeException) 1456 { 1457 return impl_getStaticSupportedServiceNames(); 1458 } 1459 1460 //------------------------------------------------------------------------- 1461 1462 Sequence< ::rtl::OUString > SAL_CALL PasswordContainer::impl_getStaticSupportedServiceNames( ) throw(uno::RuntimeException) 1463 { 1464 Sequence< ::rtl::OUString > aRet(1); 1465 *aRet.getArray() = ::rtl::OUString::createFromAscii("com.sun.star.task.PasswordContainer"); 1466 return aRet; 1467 } 1468 1469 //------------------------------------------------------------------------- 1470 1471 ::rtl::OUString SAL_CALL PasswordContainer::impl_getStaticImplementationName() throw(uno::RuntimeException) 1472 { 1473 return ::rtl::OUString::createFromAscii("stardiv.svl.PasswordContainer"); 1474 } 1475 1476 //------------------------------------------------------------------------- 1477 1478 Reference< XInterface > SAL_CALL PasswordContainer::impl_createInstance( const Reference< XMultiServiceFactory >& xServiceManager ) throw( RuntimeException ) 1479 { 1480 return Reference< XInterface >( *new PasswordContainer( xServiceManager ) ); 1481 } 1482 1483 //------------------------------------------------------------------------- 1484 1485 Reference< XSingleServiceFactory > SAL_CALL PasswordContainer::impl_createFactory( const Reference< XMultiServiceFactory >& ServiceManager ) throw(RuntimeException) 1486 { 1487 Reference< XSingleServiceFactory > xReturn( ::cppu::createOneInstanceFactory( ServiceManager, 1488 PasswordContainer::impl_getStaticImplementationName(), 1489 PasswordContainer::impl_createInstance, 1490 PasswordContainer::impl_getStaticSupportedServiceNames())); 1491 return xReturn ; 1492 1493 } 1494 1495 //------------------------------------------------------------------------- 1496 //------------------------------------------------------------------------- 1497 1498 MasterPasswordRequest_Impl::MasterPasswordRequest_Impl( PasswordRequestMode Mode ) 1499 { 1500 MasterPasswordRequest aRequest; 1501 1502 aRequest.Classification = InteractionClassification_ERROR; 1503 aRequest.Mode = Mode; 1504 1505 setRequest( makeAny( aRequest ) ); 1506 1507 // Fill continuations... 1508 Sequence< RememberAuthentication > aRememberModes( 1 ); 1509 aRememberModes[ 0 ] = RememberAuthentication_NO; 1510 1511 m_xAuthSupplier 1512 = new ::ucbhelper::InteractionSupplyAuthentication( 1513 this, 1514 sal_False, // bCanSetRealm 1515 sal_False, // bCanSetUserName 1516 sal_True, // bCanSetPassword 1517 sal_False, // bCanSetAccount 1518 aRememberModes, // rRememberPasswordModes 1519 RememberAuthentication_NO, // eDefaultRememberPasswordMode 1520 aRememberModes, // rRememberAccountModes 1521 RememberAuthentication_NO, // eDefaultRememberAccountMode 1522 sal_False, // bCanUseSystemCredentials 1523 sal_False // bDefaultUseSystemCredentials 1524 ); 1525 1526 Sequence< 1527 Reference< XInteractionContinuation > > aContinuations( 3 ); 1528 aContinuations[ 0 ] = new ::ucbhelper::InteractionAbort( this ); 1529 aContinuations[ 1 ] = new ::ucbhelper::InteractionRetry( this ); 1530 aContinuations[ 2 ] = m_xAuthSupplier.get(); 1531 1532 setContinuations( aContinuations ); 1533 } 1534 1535 //------------------------------------------------------------------------- 1536 //------------------------------------------------------------------------- 1537 1538 extern "C" 1539 { 1540 SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment ( 1541 const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */) 1542 { 1543 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; 1544 } 1545 1546 SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory ( 1547 const sal_Char * pImplementationName, void * pServiceManager, void * /* pRegistryKey */) 1548 { 1549 void * pResult = 0; 1550 if (pServiceManager) 1551 { 1552 Reference< XSingleServiceFactory > xFactory; 1553 if (PasswordContainer::impl_getStaticImplementationName().compareToAscii (pImplementationName) == 0) 1554 { 1555 xFactory = PasswordContainer::impl_createFactory ( 1556 reinterpret_cast< XMultiServiceFactory* >(pServiceManager)); 1557 } 1558 if (xFactory.is()) 1559 { 1560 xFactory->acquire(); 1561 pResult = xFactory.get(); 1562 } 1563 } 1564 return pResult; 1565 } 1566 1567 } // extern "C" 1568