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