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
createIndex(vector<::rtl::OUString> lines)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
getInfoFromInd(::rtl::OUString aInd)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
shorterUrl(::rtl::OUString & aURL)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
getAsciiLine(const::rtl::ByteSequence & buf)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
getBufFromAsciiLine(::rtl::OUString line)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
copyVectorToSequence(const vector<::rtl::OUString> & original)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
copySequenceToVector(const Sequence<::rtl::OUString> & original)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
getInfo()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
setUseStorage(sal_Bool bUse)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
useStorage()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
getEncodedMP(::rtl::OUString & aResult)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
setEncodedMP(const::rtl::OUString & aEncoded,sal_Bool bAcceptEmpty)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
remove(const::rtl::OUString & aURL,const::rtl::OUString & aName)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
clear()377 void StorageItem::clear()
378 {
379 Sequence< ::rtl::OUString > sendSeq(1);
380
381 ConfigItem::ClearNodeSet( ::rtl::OUString::createFromAscii( "Store" ) );
382 }
383
384 //-------------------------------------------------------------------------
385
update(const::rtl::OUString & aURL,const NamePassRecord & aRecord)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
Notify(const Sequence<::rtl::OUString> &)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
Commit()421 void StorageItem::Commit()
422 {
423 // Do nothing, we stored everything we want already
424 }
425
426 //-------------------------------------------------------------------------
427 //-------------------------------------------------------------------------
428
PasswordContainer(const Reference<XMultiServiceFactory> & xServiceFactory)429 PasswordContainer::PasswordContainer( const Reference<XMultiServiceFactory>& xServiceFactory ):
430 m_pStorageFile( NULL )
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
~PasswordContainer()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
disposing(const EventObject &)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
DecodePasswords(const::rtl::OUString & aLine,const::rtl::OUString & aMasterPasswd)484 vector< ::rtl::OUString > PasswordContainer::DecodePasswords( const ::rtl::OUString& aLine, const ::rtl::OUString& aMasterPasswd ) throw(RuntimeException)
485 {
486 if( aMasterPasswd.getLength() )
487 {
488 rtlCipher aDecoder = rtl_cipher_create (rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeStream );
489 OSL_ENSURE( aDecoder, "Can't create decoder\n" );
490
491 if( aDecoder )
492 {
493 OSL_ENSURE( aMasterPasswd.getLength() == RTL_DIGEST_LENGTH_MD5 * 2, "Wrong master password format!\n" );
494
495 unsigned char code[RTL_DIGEST_LENGTH_MD5];
496 for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ )
497 code[ ind ] = (char)(aMasterPasswd.copy( ind*2, 2 ).toInt32(16));
498
499 rtlCipherError result = rtl_cipher_init (
500 aDecoder, rtl_Cipher_DirectionDecode,
501 code, RTL_DIGEST_LENGTH_MD5, NULL, 0 );
502
503 if( result == rtl_Cipher_E_None )
504 {
505 ::rtl::ByteSequence aSeq = getBufFromAsciiLine( aLine );
506
507 ::rtl::ByteSequence resSeq( aSeq.getLength() );
508
509 result = rtl_cipher_decode ( aDecoder, (sal_uInt8*)aSeq.getArray(), aSeq.getLength(),
510 (sal_uInt8*)resSeq.getArray(), resSeq.getLength() );
511
512 ::rtl::OUString aPasswd( ( sal_Char* )resSeq.getArray(), resSeq.getLength(), RTL_TEXTENCODING_UTF8 );
513
514 rtl_cipher_destroy (aDecoder);
515
516 return getInfoFromInd( aPasswd );
517 }
518
519 rtl_cipher_destroy (aDecoder);
520 }
521 }
522 else
523 {
524 OSL_ENSURE( sal_False, "No master password provided!\n" );
525 // throw special exception
526 }
527
528 // problems with decoding
529 OSL_ENSURE( sal_False, "Problem with decoding\n" );
530 throw RuntimeException( ::rtl::OUString::createFromAscii( "Can't decode!" ), Reference< XInterface >() );
531 }
532
533
534 //-------------------------------------------------------------------------
535
EncodePasswords(vector<::rtl::OUString> lines,const::rtl::OUString & aMasterPasswd)536 ::rtl::OUString PasswordContainer::EncodePasswords( vector< ::rtl::OUString > lines, const ::rtl::OUString& aMasterPasswd ) throw(RuntimeException)
537 {
538 if( aMasterPasswd.getLength() )
539 {
540 ::rtl::OString aSeq = ::rtl::OUStringToOString( createIndex( lines ), RTL_TEXTENCODING_UTF8 );
541
542 rtlCipher aEncoder = rtl_cipher_create (rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeStream );
543 OSL_ENSURE( aEncoder, "Can't create encoder\n" );
544
545 if( aEncoder )
546 {
547 OSL_ENSURE( aMasterPasswd.getLength() == RTL_DIGEST_LENGTH_MD5 * 2, "Wrong master password format!\n" );
548
549 unsigned char code[RTL_DIGEST_LENGTH_MD5];
550 for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ )
551 code[ ind ] = (char)(aMasterPasswd.copy( ind*2, 2 ).toInt32(16));
552
553 rtlCipherError result = rtl_cipher_init (
554 aEncoder, rtl_Cipher_DirectionEncode,
555 code, RTL_DIGEST_LENGTH_MD5, NULL, 0 );
556
557 if( result == rtl_Cipher_E_None )
558 {
559 ::rtl::ByteSequence resSeq(aSeq.getLength()+1);
560
561 result = rtl_cipher_encode ( aEncoder, (sal_uInt8*)aSeq.getStr(), aSeq.getLength()+1,
562 (sal_uInt8*)resSeq.getArray(), resSeq.getLength() );
563
564 /*
565 //test
566 rtlCipherError result = rtl_cipher_init (
567 aEncoder, rtl_Cipher_DirectionDecode,
568 code, RTL_DIGEST_LENGTH_MD5, NULL, 0 );
569
570
571 if( result == rtl_Cipher_E_None )
572 {
573 ::rtl::OUString testOU = getAsciiLine( resSeq );
574 ::rtl::ByteSequence aSeq1 = getBufFromAsciiLine( testOU );
575
576 ::rtl::ByteSequence resSeq1( aSeq1.getLength() );
577
578 if( resSeq.getLength() == aSeq1.getLength() )
579 {
580 for( int ind = 0; ind < aSeq1.getLength(); ind++ )
581 if( resSeq[ind] != aSeq1[ind] )
582 testOU = ::rtl::OUString();
583 }
584
585 result = rtl_cipher_decode ( aEncoder, (sal_uInt8*)aSeq1.getArray(), aSeq1.getLength(),
586 (sal_uInt8*)resSeq1.getArray(), resSeq1.getLength() );
587
588 ::rtl::OUString aPasswd( ( sal_Char* )resSeq1.getArray(), resSeq1.getLength(), RTL_TEXTENCODING_UTF8 );
589 }
590 */
591
592 rtl_cipher_destroy (aEncoder);
593
594 if( result == rtl_Cipher_E_None )
595 return getAsciiLine( resSeq );
596
597 }
598
599 rtl_cipher_destroy (aEncoder);
600 }
601 }
602 else
603 {
604 OSL_ENSURE( sal_False, "No master password provided!\n" );
605 // throw special exception
606 }
607
608 // problems with encoding
609 OSL_ENSURE( sal_False, "Problem with encoding\n" );
610 throw RuntimeException( ::rtl::OUString::createFromAscii( "Can't encode!" ), Reference< XInterface >() );
611 }
612
613 //-------------------------------------------------------------------------
614
UpdateVector(const::rtl::OUString & aURL,list<NamePassRecord> & toUpdate,NamePassRecord & aRecord,sal_Bool writeFile)615 void PasswordContainer::UpdateVector( const ::rtl::OUString& aURL, list< NamePassRecord >& toUpdate, NamePassRecord& aRecord, sal_Bool writeFile ) throw(RuntimeException)
616 {
617 for( list< NamePassRecord >::iterator aNPIter = toUpdate.begin(); aNPIter != toUpdate.end(); aNPIter++ )
618 if( aNPIter->GetUserName().equals( aRecord.GetUserName() ) )
619 {
620 if( aRecord.HasPasswords( MEMORY_RECORD ) )
621 aNPIter->SetMemPasswords( aRecord.GetMemPasswords() );
622
623 if( aRecord.HasPasswords( PERSISTENT_RECORD ) )
624 {
625 aNPIter->SetPersPasswords( aRecord.GetPersPasswords() );
626
627 if( writeFile )
628 {
629 // the password must be already encoded
630 m_pStorageFile->update( aURL, aRecord ); // change existing ( aURL, aName ) record in the configfile
631 }
632 }
633
634 return;
635 }
636
637
638 if( aRecord.HasPasswords( PERSISTENT_RECORD ) && writeFile )
639 {
640 // the password must be already encoded
641 m_pStorageFile->update( aURL, aRecord ); // add new aName to the existing url
642 }
643
644 toUpdate.insert( toUpdate.begin(), aRecord );
645 }
646
647 //-------------------------------------------------------------------------
648
CopyToUserRecord(const NamePassRecord & aRecord,sal_Bool & io_bTryToDecode,const Reference<XInteractionHandler> & aHandler)649 UserRecord PasswordContainer::CopyToUserRecord( const NamePassRecord& aRecord, sal_Bool& io_bTryToDecode, const Reference< XInteractionHandler >& aHandler )
650 {
651 ::std::vector< ::rtl::OUString > aPasswords;
652 if( aRecord.HasPasswords( MEMORY_RECORD ) )
653 aPasswords = aRecord.GetMemPasswords();
654
655 if( io_bTryToDecode && aRecord.HasPasswords( PERSISTENT_RECORD ) )
656 {
657 try
658 {
659 ::std::vector< ::rtl::OUString > aDecodedPasswords = DecodePasswords( aRecord.GetPersPasswords(), GetMasterPassword( aHandler ) );
660 aPasswords.insert( aPasswords.end(), aDecodedPasswords.begin(), aDecodedPasswords.end() );
661 }
662 catch( NoMasterException& )
663 {
664 // if master password could not be detected the entry will be just ignored
665 io_bTryToDecode = sal_False;
666 }
667 }
668
669 return UserRecord( aRecord.GetUserName(), copyVectorToSequence( aPasswords ) );
670 }
671
672 //-------------------------------------------------------------------------
673
CopyToUserRecordSequence(const list<NamePassRecord> & original,const Reference<XInteractionHandler> & aHandler)674 Sequence< UserRecord > PasswordContainer::CopyToUserRecordSequence( const list< NamePassRecord >& original, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException)
675 {
676 Sequence< UserRecord > aResult( original.size() );
677 sal_uInt32 nInd = 0;
678 sal_Bool bTryToDecode = sal_True;
679
680 for( list< NamePassRecord >::const_iterator aNPIter = original.begin();
681 aNPIter != original.end();
682 aNPIter++, nInd++ )
683 {
684 aResult[nInd] = CopyToUserRecord( *aNPIter, bTryToDecode, aHandler );
685 }
686
687 return aResult;
688 }
689
690 //-------------------------------------------------------------------------
691
add(const::rtl::OUString & Url,const::rtl::OUString & UserName,const Sequence<::rtl::OUString> & Passwords,const Reference<XInteractionHandler> & aHandler)692 void SAL_CALL PasswordContainer::add( const ::rtl::OUString& Url, const ::rtl::OUString& UserName, const Sequence< ::rtl::OUString >& Passwords, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException)
693 {
694 ::osl::MutexGuard aGuard( mMutex );
695
696 PrivateAdd( Url, UserName, Passwords, MEMORY_RECORD, aHandler );
697 }
698
699 //-------------------------------------------------------------------------
700
addPersistent(const::rtl::OUString & Url,const::rtl::OUString & UserName,const Sequence<::rtl::OUString> & Passwords,const Reference<XInteractionHandler> & aHandler)701 void SAL_CALL PasswordContainer::addPersistent( const ::rtl::OUString& Url, const ::rtl::OUString& UserName, const Sequence< ::rtl::OUString >& Passwords, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException)
702 {
703 ::osl::MutexGuard aGuard( mMutex );
704
705 PrivateAdd( Url, UserName, Passwords, PERSISTENT_RECORD, aHandler );
706 }
707
708 //-------------------------------------------------------------------------
709
PrivateAdd(const::rtl::OUString & Url,const::rtl::OUString & UserName,const Sequence<::rtl::OUString> & Passwords,char Mode,const Reference<XInteractionHandler> & aHandler)710 void PasswordContainer::PrivateAdd( const ::rtl::OUString& Url, const ::rtl::OUString& UserName, const Sequence< ::rtl::OUString >& Passwords, char Mode, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException)
711 {
712 NamePassRecord aRecord( UserName );
713 ::std::vector< ::rtl::OUString > aStorePass = copySequenceToVector( Passwords );
714
715 if( Mode == PERSISTENT_RECORD )
716 aRecord.SetPersPasswords( EncodePasswords( aStorePass, GetMasterPassword( aHandler ) ) );
717 else if( Mode == MEMORY_RECORD )
718 aRecord.SetMemPasswords( aStorePass );
719 else
720 {
721 OSL_ASSERT( "Unexpected persistence status!" );
722 return;
723 }
724
725 if( !m_aContainer.empty() )
726 {
727 PassMap::iterator aIter = m_aContainer.find( Url );
728
729 if( aIter != m_aContainer.end() )
730 {
731 UpdateVector( aIter->first, aIter->second, aRecord, sal_True );
732 return;
733 }
734 }
735
736 list< NamePassRecord > listToAdd( 1, aRecord );
737 m_aContainer.insert( PairUrlRecord( Url, listToAdd ) );
738
739 if( Mode == PERSISTENT_RECORD && m_pStorageFile && m_pStorageFile->useStorage() )
740 m_pStorageFile->update( Url, aRecord );
741
742 }
743
744 //-------------------------------------------------------------------------
745
746
find(const::rtl::OUString & aURL,const Reference<XInteractionHandler> & aHandler)747 UrlRecord SAL_CALL PasswordContainer::find( const ::rtl::OUString& aURL, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException)
748 {
749 return find( aURL, rtl::OUString(), false, aHandler );
750 }
751
752 //-------------------------------------------------------------------------
753
findForName(const::rtl::OUString & aURL,const::rtl::OUString & aName,const Reference<XInteractionHandler> & aHandler)754 UrlRecord SAL_CALL PasswordContainer::findForName( const ::rtl::OUString& aURL, const ::rtl::OUString& aName, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException)
755 {
756 return find( aURL, aName, true, aHandler );
757 }
758
759 //-------------------------------------------------------------------------
760
FindUsr(const list<NamePassRecord> & userlist,const::rtl::OUString & aName,const Reference<XInteractionHandler> & aHandler)761 Sequence< UserRecord > PasswordContainer::FindUsr( const list< NamePassRecord >& userlist, const ::rtl::OUString& aName, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException)
762 {
763 sal_uInt32 nInd = 0;
764 for( list< NamePassRecord >::const_iterator aNPIter = userlist.begin();
765 aNPIter != userlist.end();
766 aNPIter++, nInd++ )
767 {
768 if( aNPIter->GetUserName().equals( aName ) )
769 {
770 Sequence< UserRecord > aResult(1);
771 sal_Bool bTryToDecode = sal_True;
772 aResult[0] = CopyToUserRecord( *aNPIter, bTryToDecode, aHandler );
773
774 return aResult;
775 }
776 }
777
778 return Sequence< UserRecord >();
779 }
780
781 //-------------------------------------------------------------------------
782
createUrlRecord(const PassMap::iterator & rIter,bool bName,const::rtl::OUString & aName,const Reference<XInteractionHandler> & aHandler,UrlRecord & rRec)783 bool PasswordContainer::createUrlRecord(
784 const PassMap::iterator & rIter,
785 bool bName,
786 const ::rtl::OUString & aName,
787 const Reference< XInteractionHandler >& aHandler,
788 UrlRecord & rRec )
789 throw( RuntimeException )
790 {
791 if ( bName )
792 {
793 Sequence< UserRecord > aUsrRec
794 = FindUsr( rIter->second, aName, aHandler );
795 if( aUsrRec.getLength() )
796 {
797 rRec = UrlRecord( rIter->first, aUsrRec );
798 return true;
799 }
800 }
801 else
802 {
803 rRec = UrlRecord(
804 rIter->first,
805 CopyToUserRecordSequence( rIter->second, aHandler ) );
806 return true;
807 }
808 return false;
809 }
810
811 //-------------------------------------------------------------------------
812
find(const::rtl::OUString & aURL,const::rtl::OUString & aName,bool bName,const Reference<XInteractionHandler> & aHandler)813 UrlRecord PasswordContainer::find(
814 const ::rtl::OUString& aURL,
815 const ::rtl::OUString& aName,
816 bool bName, // only needed to support empty user names
817 const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException)
818 {
819 ::osl::MutexGuard aGuard( mMutex );
820
821 if( !m_aContainer.empty() && aURL.getLength() )
822 {
823 ::rtl::OUString aUrl( aURL );
824
825 // each iteration remove last '/...' section from the aUrl
826 // while it's possible, up to the most left '://'
827 do
828 {
829 // first look for <url>/somename and then look for <url>/somename/...
830 PassMap::iterator aIter = m_aContainer.find( aUrl );
831 if( aIter != m_aContainer.end() )
832 {
833 UrlRecord aRec;
834 if ( createUrlRecord( aIter, bName, aName, aHandler, aRec ) )
835 return aRec;
836 }
837 else
838 {
839 ::rtl::OUString tmpUrl( aUrl );
840 if ( tmpUrl.getStr()[tmpUrl.getLength() - 1] != (sal_Unicode)'/' )
841 tmpUrl += ::rtl::OUString::createFromAscii( "/" );
842
843 aIter = m_aContainer.lower_bound( tmpUrl );
844 if( aIter != m_aContainer.end() && aIter->first.match( tmpUrl ) )
845 {
846 UrlRecord aRec;
847 if ( createUrlRecord( aIter, bName, aName, aHandler, aRec ) )
848 return aRec;
849 }
850 }
851 }
852 while( shorterUrl( aUrl ) && aUrl.getLength() );
853 }
854
855 return UrlRecord();
856 }
857
858 //-------------------------------------------------------------------------
GetDefaultMasterPassword()859 ::rtl::OUString PasswordContainer::GetDefaultMasterPassword()
860 {
861 ::rtl::OUString aResult;
862 for ( sal_Int32 nInd = 0; nInd < RTL_DIGEST_LENGTH_MD5; nInd++ )
863 aResult += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "aa" ) );
864
865 return aResult;
866 }
867
868 //-------------------------------------------------------------------------
RequestPasswordFromUser(PasswordRequestMode aRMode,const uno::Reference<task::XInteractionHandler> & xHandler)869 ::rtl::OUString PasswordContainer::RequestPasswordFromUser( PasswordRequestMode aRMode, const uno::Reference< task::XInteractionHandler >& xHandler )
870 {
871 // empty string means that the call was cancelled or just failed
872 ::rtl::OUString aResult;
873
874 if ( xHandler.is() )
875 {
876 ::rtl::Reference< MasterPasswordRequest_Impl > xRequest = new MasterPasswordRequest_Impl( aRMode );
877
878 xHandler->handle( xRequest.get() );
879
880 ::rtl::Reference< ucbhelper::InteractionContinuation > xSelection = xRequest->getSelection();
881
882 if ( xSelection.is() )
883 {
884 Reference< XInteractionAbort > xAbort( xSelection.get(), UNO_QUERY );
885 if ( !xAbort.is() )
886 {
887 const ::rtl::Reference< ucbhelper::InteractionSupplyAuthentication > & xSupp
888 = xRequest->getAuthenticationSupplier();
889
890 aResult = xSupp->getPassword();
891 }
892 }
893 }
894
895 return aResult;
896 }
897
898 //-------------------------------------------------------------------------
899
GetMasterPassword(const Reference<XInteractionHandler> & aHandler)900 ::rtl::OUString PasswordContainer::GetMasterPassword( const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException)
901 {
902 PasswordRequestMode aRMode = PasswordRequestMode_PASSWORD_ENTER;
903 if( !m_pStorageFile || !m_pStorageFile->useStorage() )
904 throw NoMasterException( ::rtl::OUString::createFromAscii( "Password storing is not active!" ), Reference< XInterface >(), aRMode );
905
906 if( !m_aMasterPasswd.getLength() && aHandler.is() )
907 {
908 ::rtl::OUString aEncodedMP;
909 sal_Bool bAskAgain = sal_False;
910 sal_Bool bDefaultPassword = sal_False;
911
912 if( !m_pStorageFile->getEncodedMP( aEncodedMP ) )
913 aRMode = PasswordRequestMode_PASSWORD_CREATE;
914 else if ( !aEncodedMP.getLength() )
915 {
916 m_aMasterPasswd = GetDefaultMasterPassword();
917 bDefaultPassword = sal_True;
918 }
919
920 if ( !bDefaultPassword )
921 {
922 do {
923 bAskAgain = sal_False;
924
925 ::rtl::OUString aPass = RequestPasswordFromUser( aRMode, aHandler );
926 if ( aPass.getLength() )
927 {
928 if( aRMode == PasswordRequestMode_PASSWORD_CREATE )
929 {
930 m_aMasterPasswd = aPass;
931 vector< ::rtl::OUString > aMaster( 1, m_aMasterPasswd );
932
933 m_pStorageFile->setEncodedMP( EncodePasswords( aMaster, m_aMasterPasswd ) );
934 }
935 else
936 {
937 vector< ::rtl::OUString > aRM( DecodePasswords( aEncodedMP, aPass ) );
938 if( !aRM.size() || !aPass.equals( aRM[0] ) )
939 {
940 bAskAgain = sal_True;
941 aRMode = PasswordRequestMode_PASSWORD_REENTER;
942 }
943 else
944 m_aMasterPasswd = aPass;
945 }
946 }
947
948 } while( bAskAgain );
949 }
950 }
951
952 if ( !m_aMasterPasswd.getLength() )
953 throw NoMasterException( ::rtl::OUString::createFromAscii( "No master password!" ), Reference< XInterface >(), aRMode );
954
955 return m_aMasterPasswd;
956 }
957
958 //-------------------------------------------------------------------------
959
remove(const::rtl::OUString & aURL,const::rtl::OUString & aName)960 void SAL_CALL PasswordContainer::remove( const ::rtl::OUString& aURL, const ::rtl::OUString& aName ) throw(RuntimeException)
961 {
962 ::osl::MutexGuard aGuard( mMutex );
963
964 ::rtl::OUString aUrl( aURL );
965 if( !m_aContainer.empty() )
966 {
967 PassMap::iterator aIter = m_aContainer.find( aUrl );
968
969 if( aIter == m_aContainer.end() )
970 {
971 sal_Int32 aInd = aUrl.lastIndexOf( sal_Unicode( '/' ) );
972 if( aInd > 0 && aUrl.getLength()-1 == aInd )
973 aUrl = aUrl.copy( 0, aUrl.getLength() - 1 );
974 else
975 aUrl += ::rtl::OUString::createFromAscii( "/" );
976
977 aIter = m_aContainer.find( aUrl );
978 }
979
980 if( aIter != m_aContainer.end() )
981 {
982 for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); aNPIter++ )
983 if( aNPIter->GetUserName().equals( aName ) )
984 {
985 if( aNPIter->HasPasswords( PERSISTENT_RECORD ) && m_pStorageFile )
986 m_pStorageFile->remove( aURL, aName ); // remove record ( aURL, aName )
987
988 // the iterator will not be used any more so it can be removed directly
989 aIter->second.erase( aNPIter );
990
991 if( aIter->second.begin() == aIter->second.end() )
992 m_aContainer.erase( aIter );
993
994 return;
995 }
996 }
997 }
998 }
999
1000 //-------------------------------------------------------------------------
1001
removePersistent(const::rtl::OUString & aURL,const::rtl::OUString & aName)1002 void SAL_CALL PasswordContainer::removePersistent( const ::rtl::OUString& aURL, const ::rtl::OUString& aName ) throw(RuntimeException)
1003 {
1004 ::osl::MutexGuard aGuard( mMutex );
1005
1006 ::rtl::OUString aUrl( aURL );
1007 if( !m_aContainer.empty() )
1008 {
1009 PassMap::iterator aIter = m_aContainer.find( aUrl );
1010
1011 if( aIter == m_aContainer.end() )
1012 {
1013 sal_Int32 aInd = aUrl.lastIndexOf( sal_Unicode( '/' ) );
1014 if( aInd > 0 && aUrl.getLength()-1 == aInd )
1015 aUrl = aUrl.copy( 0, aUrl.getLength() - 1 );
1016 else
1017 aUrl += ::rtl::OUString::createFromAscii( "/" );
1018
1019 aIter = m_aContainer.find( aUrl );
1020 }
1021
1022 if( aIter != m_aContainer.end() )
1023 {
1024 for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); aNPIter++ )
1025 if( aNPIter->GetUserName().equals( aName ) )
1026 {
1027 if( aNPIter->HasPasswords( PERSISTENT_RECORD ) )
1028 {
1029 // TODO/LATER: should the password be converted to MemoryPassword?
1030 aNPIter->RemovePasswords( PERSISTENT_RECORD );
1031
1032 if ( m_pStorageFile )
1033 m_pStorageFile->remove( aURL, aName ); // remove record ( aURL, aName )
1034 }
1035
1036 if( !aNPIter->HasPasswords( MEMORY_RECORD ) )
1037 aIter->second.erase( aNPIter );
1038
1039 if( aIter->second.begin() == aIter->second.end() )
1040 m_aContainer.erase( aIter );
1041
1042 return;
1043 }
1044 }
1045 }
1046 }
1047 //-------------------------------------------------------------------------
1048
removeAllPersistent()1049 void SAL_CALL PasswordContainer::removeAllPersistent() throw(RuntimeException)
1050 {
1051 ::osl::MutexGuard aGuard( mMutex );
1052
1053 if( m_pStorageFile )
1054 m_pStorageFile->clear();
1055
1056 for( PassMap::iterator aIter = m_aContainer.begin(); aIter != m_aContainer.end(); )
1057 {
1058 for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); )
1059 {
1060 if( aNPIter->HasPasswords( PERSISTENT_RECORD ) )
1061 {
1062 // TODO/LATER: should the password be converted to MemoryPassword?
1063 aNPIter->RemovePasswords( PERSISTENT_RECORD );
1064
1065 if ( m_pStorageFile )
1066 m_pStorageFile->remove( aIter->first, aNPIter->GetUserName() ); // remove record ( aURL, aName )
1067 }
1068
1069 if( !aNPIter->HasPasswords( MEMORY_RECORD ) )
1070 {
1071 list< NamePassRecord >::iterator aIterToDelete( aNPIter );
1072 aNPIter++;
1073 aIter->second.erase( aIterToDelete );
1074 }
1075 else
1076 aNPIter++;
1077 }
1078
1079 if( aIter->second.begin() == aIter->second.end() )
1080 {
1081 PassMap::iterator aIterToDelete( aIter );
1082 aIter++;
1083 m_aContainer.erase( aIterToDelete );
1084 }
1085 else
1086 aIter++;
1087 }
1088 }
1089 //-------------------------------------------------------------------------
1090
getAllPersistent(const Reference<XInteractionHandler> & xHandler)1091 Sequence< UrlRecord > SAL_CALL PasswordContainer::getAllPersistent( const Reference< XInteractionHandler >& xHandler ) throw(RuntimeException)
1092 {
1093 Sequence< UrlRecord > aResult;
1094
1095 ::osl::MutexGuard aGuard( mMutex );
1096 for( PassMap::iterator aIter = m_aContainer.begin(); aIter != m_aContainer.end(); aIter++ )
1097 {
1098 Sequence< UserRecord > aUsers;
1099 for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); aNPIter++ )
1100 if( aNPIter->HasPasswords( PERSISTENT_RECORD ) )
1101 {
1102 sal_Int32 oldLen = aUsers.getLength();
1103 aUsers.realloc( oldLen + 1 );
1104 aUsers[ oldLen ] = UserRecord( aNPIter->GetUserName(), copyVectorToSequence( DecodePasswords( aNPIter->GetPersPasswords(), GetMasterPassword( xHandler ) ) ) );
1105 }
1106
1107 if( aUsers.getLength() )
1108 {
1109 sal_Int32 oldLen = aResult.getLength();
1110 aResult.realloc( oldLen + 1 );
1111 aResult[ oldLen ] = UrlRecord( aIter->first, aUsers );
1112 }
1113 }
1114
1115 return aResult;
1116 }
1117
1118 //-------------------------------------------------------------------------
authorizateWithMasterPassword(const uno::Reference<task::XInteractionHandler> & xHandler)1119 sal_Bool SAL_CALL PasswordContainer::authorizateWithMasterPassword( const uno::Reference< task::XInteractionHandler >& xHandler )
1120 throw (uno::RuntimeException)
1121 {
1122 sal_Bool bResult = sal_False;
1123 ::rtl::OUString aEncodedMP;
1124 uno::Reference< task::XInteractionHandler > xTmpHandler = xHandler;
1125 ::osl::MutexGuard aGuard( mMutex );
1126
1127 // the method should fail if there is no master password
1128 if( m_pStorageFile && m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) )
1129 {
1130 if ( !aEncodedMP.getLength() )
1131 {
1132 // this is a default master password
1133 // no UI is necessary
1134 bResult = sal_True;
1135 }
1136 else
1137 {
1138 if ( !xTmpHandler.is() )
1139 {
1140 uno::Reference< lang::XMultiServiceFactory > xFactory( mComponent, uno::UNO_QUERY_THROW );
1141 xTmpHandler.set( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.InteractionHandler" ) ) ), uno::UNO_QUERY_THROW );
1142 }
1143
1144 if ( m_aMasterPasswd.getLength() )
1145 {
1146 // there is a password, it should be just rechecked
1147 PasswordRequestMode aRMode = PasswordRequestMode_PASSWORD_ENTER;
1148 ::rtl::OUString aPass;
1149
1150 do {
1151 aPass = RequestPasswordFromUser( aRMode, xTmpHandler );
1152 bResult = ( aPass.getLength() && aPass.equals( m_aMasterPasswd ) );
1153 aRMode = PasswordRequestMode_PASSWORD_REENTER; // further questions with error notification
1154 } while( !bResult && aPass.getLength() );
1155 }
1156 else
1157 {
1158 try
1159 {
1160 // ask for the password, if user provide no correct password an exception will be thrown
1161 bResult = ( GetMasterPassword( xTmpHandler ).getLength() > 0 );
1162 }
1163 catch( uno::Exception& )
1164 {}
1165 }
1166 }
1167 }
1168
1169 return bResult;
1170 }
1171
1172 //-------------------------------------------------------------------------
changeMasterPassword(const uno::Reference<task::XInteractionHandler> & xHandler)1173 sal_Bool SAL_CALL PasswordContainer::changeMasterPassword( const uno::Reference< task::XInteractionHandler >& xHandler )
1174 throw (uno::RuntimeException)
1175 {
1176 sal_Bool bResult = sal_False;
1177 uno::Reference< task::XInteractionHandler > xTmpHandler = xHandler;
1178 ::osl::MutexGuard aGuard( mMutex );
1179
1180 if ( m_pStorageFile && m_pStorageFile->useStorage() )
1181 {
1182 if ( !xTmpHandler.is() )
1183 {
1184 uno::Reference< lang::XMultiServiceFactory > xFactory( mComponent, uno::UNO_QUERY_THROW );
1185 xTmpHandler.set( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.InteractionHandler" ) ) ), uno::UNO_QUERY_THROW );
1186 }
1187
1188 sal_Bool bCanChangePassword = sal_True;
1189 // if there is already a stored master password it should be entered by the user before the change happen
1190 ::rtl::OUString aEncodedMP;
1191 if( m_aMasterPasswd.getLength() || m_pStorageFile->getEncodedMP( aEncodedMP ) )
1192 bCanChangePassword = authorizateWithMasterPassword( xTmpHandler );
1193
1194 if ( bCanChangePassword )
1195 {
1196 // ask for the new password, but do not set it
1197 PasswordRequestMode aRMode = PasswordRequestMode_PASSWORD_CREATE;
1198 ::rtl::OUString aPass = RequestPasswordFromUser( aRMode, xTmpHandler );
1199
1200 if ( aPass.getLength() )
1201 {
1202 // get all the persistent entries if it is possible
1203 Sequence< UrlRecord > aPersistent = getAllPersistent( uno::Reference< task::XInteractionHandler >() );
1204
1205 // remove the master password and the entries persistence
1206 removeMasterPassword();
1207
1208 // store the new master password
1209 m_aMasterPasswd = aPass;
1210 vector< ::rtl::OUString > aMaster( 1, m_aMasterPasswd );
1211 m_pStorageFile->setEncodedMP( EncodePasswords( aMaster, m_aMasterPasswd ) );
1212
1213 // store all the entries with the new password
1214 for ( int nURLInd = 0; nURLInd < aPersistent.getLength(); nURLInd++ )
1215 for ( int nNameInd = 0; nNameInd< aPersistent[nURLInd].UserList.getLength(); nNameInd++ )
1216 addPersistent( aPersistent[nURLInd].Url,
1217 aPersistent[nURLInd].UserList[nNameInd].UserName,
1218 aPersistent[nURLInd].UserList[nNameInd].Passwords,
1219 uno::Reference< task::XInteractionHandler >() );
1220
1221 bResult = sal_True;
1222 }
1223 }
1224 }
1225
1226 return bResult;
1227 }
1228
1229 //-------------------------------------------------------------------------
removeMasterPassword()1230 void SAL_CALL PasswordContainer::removeMasterPassword()
1231 throw (uno::RuntimeException)
1232 {
1233 // remove all the stored passwords and the master password
1234 removeAllPersistent();
1235
1236 ::osl::MutexGuard aGuard( mMutex );
1237 if ( m_pStorageFile )
1238 {
1239 m_aMasterPasswd = ::rtl::OUString();
1240 m_pStorageFile->setEncodedMP( ::rtl::OUString() ); // let the master password be removed from configuration
1241 }
1242 }
1243
1244 //-------------------------------------------------------------------------
hasMasterPassword()1245 ::sal_Bool SAL_CALL PasswordContainer::hasMasterPassword( )
1246 throw (::com::sun::star::uno::RuntimeException)
1247 {
1248 ::osl::MutexGuard aGuard( mMutex );
1249
1250 if ( !m_pStorageFile )
1251 throw uno::RuntimeException();
1252
1253 ::rtl::OUString aEncodedMP;
1254 return ( m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) );
1255 }
1256
1257 //-------------------------------------------------------------------------
allowPersistentStoring(::sal_Bool bAllow)1258 ::sal_Bool SAL_CALL PasswordContainer::allowPersistentStoring( ::sal_Bool bAllow )
1259 throw (::com::sun::star::uno::RuntimeException)
1260 {
1261 ::osl::MutexGuard aGuard( mMutex );
1262
1263 if ( !m_pStorageFile )
1264 throw uno::RuntimeException();
1265
1266 if ( !bAllow )
1267 removeMasterPassword();
1268
1269 if ( m_pStorageFile->useStorage() == bAllow )
1270 return bAllow;
1271
1272 m_pStorageFile->setUseStorage( bAllow );
1273 return !bAllow;
1274 }
1275
1276 //-------------------------------------------------------------------------
isPersistentStoringAllowed()1277 ::sal_Bool SAL_CALL PasswordContainer::isPersistentStoringAllowed()
1278 throw (::com::sun::star::uno::RuntimeException)
1279 {
1280 ::osl::MutexGuard aGuard( mMutex );
1281
1282 if ( !m_pStorageFile )
1283 throw uno::RuntimeException();
1284
1285 return m_pStorageFile->useStorage();
1286 }
1287
1288 //-------------------------------------------------------------------------
useDefaultMasterPassword(const uno::Reference<task::XInteractionHandler> & xHandler)1289 ::sal_Bool SAL_CALL PasswordContainer::useDefaultMasterPassword( const uno::Reference< task::XInteractionHandler >& xHandler )
1290 throw ( uno::RuntimeException )
1291 {
1292 sal_Bool bResult = sal_False;
1293 uno::Reference< task::XInteractionHandler > xTmpHandler = xHandler;
1294 ::osl::MutexGuard aGuard( mMutex );
1295
1296 if ( m_pStorageFile && m_pStorageFile->useStorage() )
1297 {
1298 if ( !xTmpHandler.is() )
1299 {
1300 uno::Reference< lang::XMultiServiceFactory > xFactory( mComponent, uno::UNO_QUERY_THROW );
1301 xTmpHandler.set( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.InteractionHandler" ) ) ), uno::UNO_QUERY_THROW );
1302 }
1303
1304 sal_Bool bCanChangePassword = sal_True;
1305 // if there is already a stored nondefault master password it should be entered by the user before the change happen
1306 ::rtl::OUString aEncodedMP;
1307 if( m_pStorageFile->getEncodedMP( aEncodedMP ) && aEncodedMP.getLength() )
1308 bCanChangePassword = authorizateWithMasterPassword( xTmpHandler );
1309
1310 if ( bCanChangePassword )
1311 {
1312 // generate the default password
1313 ::rtl::OUString aPass = GetDefaultMasterPassword();
1314 if ( aPass.getLength() )
1315 {
1316 // get all the persistent entries if it is possible
1317 Sequence< UrlRecord > aPersistent = getAllPersistent( uno::Reference< task::XInteractionHandler >() );
1318
1319 // remove the master password and the entries persistence
1320 removeMasterPassword();
1321
1322 // store the empty string to flag the default master password
1323 m_aMasterPasswd = aPass;
1324 m_pStorageFile->setEncodedMP( ::rtl::OUString(), sal_True );
1325
1326 // store all the entries with the new password
1327 for ( int nURLInd = 0; nURLInd < aPersistent.getLength(); nURLInd++ )
1328 for ( int nNameInd = 0; nNameInd< aPersistent[nURLInd].UserList.getLength(); nNameInd++ )
1329 addPersistent( aPersistent[nURLInd].Url,
1330 aPersistent[nURLInd].UserList[nNameInd].UserName,
1331 aPersistent[nURLInd].UserList[nNameInd].Passwords,
1332 uno::Reference< task::XInteractionHandler >() );
1333
1334 bResult = sal_True;
1335 }
1336 }
1337 }
1338
1339 return bResult;
1340
1341 }
1342
1343 //-------------------------------------------------------------------------
isDefaultMasterPasswordUsed()1344 ::sal_Bool SAL_CALL PasswordContainer::isDefaultMasterPasswordUsed()
1345 throw ( uno::RuntimeException )
1346 {
1347 ::osl::MutexGuard aGuard( mMutex );
1348
1349 if ( !m_pStorageFile )
1350 throw uno::RuntimeException();
1351
1352 ::rtl::OUString aEncodedMP;
1353 return ( m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) && !aEncodedMP.getLength() );
1354 }
1355
1356
1357 //-------------------------------------------------------------------------
addUrl(const::rtl::OUString & Url,::sal_Bool MakePersistent)1358 void SAL_CALL PasswordContainer::addUrl( const ::rtl::OUString& Url, ::sal_Bool MakePersistent )
1359 throw (uno::RuntimeException)
1360 {
1361 mUrlContainer.add( Url, MakePersistent );
1362 }
1363
1364 //-------------------------------------------------------------------------
findUrl(const::rtl::OUString & Url)1365 ::rtl::OUString SAL_CALL PasswordContainer::findUrl( const ::rtl::OUString& Url )
1366 throw (uno::RuntimeException)
1367 {
1368 return mUrlContainer.find( Url );
1369 }
1370
1371 //-------------------------------------------------------------------------
removeUrl(const::rtl::OUString & Url)1372 void SAL_CALL PasswordContainer::removeUrl( const ::rtl::OUString& Url )
1373 throw (uno::RuntimeException)
1374 {
1375 mUrlContainer.remove( Url );
1376 }
1377
1378 //-------------------------------------------------------------------------
getUrls(::sal_Bool OnlyPersistent)1379 uno::Sequence< ::rtl::OUString > SAL_CALL PasswordContainer::getUrls( ::sal_Bool OnlyPersistent )
1380 throw (uno::RuntimeException)
1381 {
1382 return mUrlContainer.list( OnlyPersistent );
1383 }
1384
1385 //-------------------------------------------------------------------------
1386
Notify()1387 void PasswordContainer::Notify()
1388 {
1389 ::osl::MutexGuard aGuard( mMutex );
1390
1391 PassMap::iterator aIter;
1392
1393 // remove the cached persistent values in the memory
1394 for( aIter = m_aContainer.begin(); aIter != m_aContainer.end(); aIter++ )
1395 {
1396 for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); )
1397 {
1398 if( aNPIter->HasPasswords( PERSISTENT_RECORD ) )
1399 {
1400 aNPIter->RemovePasswords( PERSISTENT_RECORD );
1401
1402 if ( m_pStorageFile )
1403 m_pStorageFile->remove( aIter->first, aNPIter->GetUserName() ); // remove record ( aURL, aName )
1404 }
1405
1406 if( !aNPIter->HasPasswords( MEMORY_RECORD ) )
1407 {
1408 list< NamePassRecord >::iterator aIterToDelete( aNPIter );
1409 aNPIter++;
1410 aIter->second.erase( aIterToDelete );
1411 }
1412 else
1413 aNPIter++;
1414 }
1415 }
1416
1417 PassMap addon;
1418 if( m_pStorageFile )
1419 addon = m_pStorageFile->getInfo();
1420
1421 for( aIter = addon.begin(); aIter != addon.end(); aIter++ )
1422 {
1423 PassMap::iterator aSearchIter = m_aContainer.find( aIter->first );
1424 if( aSearchIter != m_aContainer.end() )
1425 for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); aNPIter++ )
1426 UpdateVector( aSearchIter->first, aSearchIter->second, *aNPIter, sal_False );
1427 else
1428 m_aContainer.insert( PairUrlRecord( aIter->first, aIter->second ) );
1429 }
1430 }
1431
1432 //-------------------------------------------------------------------------
1433
getImplementationName()1434 ::rtl::OUString SAL_CALL PasswordContainer::getImplementationName( ) throw(uno::RuntimeException)
1435 {
1436 return impl_getStaticImplementationName();
1437 }
1438
1439 //-------------------------------------------------------------------------
1440
supportsService(const::rtl::OUString & ServiceName)1441 sal_Bool SAL_CALL PasswordContainer::supportsService( const ::rtl::OUString& ServiceName ) throw(uno::RuntimeException)
1442 {
1443 if ( ServiceName.compareToAscii("com.sun.star.task.PasswordContainer") == 0 )
1444 return sal_True;
1445 else
1446 return sal_False;
1447 }
1448
1449 //-------------------------------------------------------------------------
1450
getSupportedServiceNames()1451 Sequence< ::rtl::OUString > SAL_CALL PasswordContainer::getSupportedServiceNames( ) throw(uno::RuntimeException)
1452 {
1453 return impl_getStaticSupportedServiceNames();
1454 }
1455
1456 //-------------------------------------------------------------------------
1457
impl_getStaticSupportedServiceNames()1458 Sequence< ::rtl::OUString > SAL_CALL PasswordContainer::impl_getStaticSupportedServiceNames( ) throw(uno::RuntimeException)
1459 {
1460 Sequence< ::rtl::OUString > aRet(1);
1461 *aRet.getArray() = ::rtl::OUString::createFromAscii("com.sun.star.task.PasswordContainer");
1462 return aRet;
1463 }
1464
1465 //-------------------------------------------------------------------------
1466
impl_getStaticImplementationName()1467 ::rtl::OUString SAL_CALL PasswordContainer::impl_getStaticImplementationName() throw(uno::RuntimeException)
1468 {
1469 return ::rtl::OUString::createFromAscii("stardiv.svl.PasswordContainer");
1470 }
1471
1472 //-------------------------------------------------------------------------
1473
impl_createInstance(const Reference<XMultiServiceFactory> & xServiceManager)1474 Reference< XInterface > SAL_CALL PasswordContainer::impl_createInstance( const Reference< XMultiServiceFactory >& xServiceManager ) throw( RuntimeException )
1475 {
1476 return Reference< XInterface >( *new PasswordContainer( xServiceManager ) );
1477 }
1478
1479 //-------------------------------------------------------------------------
1480
impl_createFactory(const Reference<XMultiServiceFactory> & ServiceManager)1481 Reference< XSingleServiceFactory > SAL_CALL PasswordContainer::impl_createFactory( const Reference< XMultiServiceFactory >& ServiceManager ) throw(RuntimeException)
1482 {
1483 Reference< XSingleServiceFactory > xReturn( ::cppu::createOneInstanceFactory( ServiceManager,
1484 PasswordContainer::impl_getStaticImplementationName(),
1485 PasswordContainer::impl_createInstance,
1486 PasswordContainer::impl_getStaticSupportedServiceNames()));
1487 return xReturn ;
1488
1489 }
1490
1491 //-------------------------------------------------------------------------
1492 //-------------------------------------------------------------------------
1493
MasterPasswordRequest_Impl(PasswordRequestMode Mode)1494 MasterPasswordRequest_Impl::MasterPasswordRequest_Impl( PasswordRequestMode Mode )
1495 {
1496 MasterPasswordRequest aRequest;
1497
1498 aRequest.Classification = InteractionClassification_ERROR;
1499 aRequest.Mode = Mode;
1500
1501 setRequest( makeAny( aRequest ) );
1502
1503 // Fill continuations...
1504 Sequence< RememberAuthentication > aRememberModes( 1 );
1505 aRememberModes[ 0 ] = RememberAuthentication_NO;
1506
1507 m_xAuthSupplier
1508 = new ::ucbhelper::InteractionSupplyAuthentication(
1509 this,
1510 sal_False, // bCanSetRealm
1511 sal_False, // bCanSetUserName
1512 sal_True, // bCanSetPassword
1513 sal_False, // bCanSetAccount
1514 aRememberModes, // rRememberPasswordModes
1515 RememberAuthentication_NO, // eDefaultRememberPasswordMode
1516 aRememberModes, // rRememberAccountModes
1517 RememberAuthentication_NO, // eDefaultRememberAccountMode
1518 sal_False, // bCanUseSystemCredentials
1519 sal_False // bDefaultUseSystemCredentials
1520 );
1521
1522 Sequence<
1523 Reference< XInteractionContinuation > > aContinuations( 3 );
1524 aContinuations[ 0 ] = new ::ucbhelper::InteractionAbort( this );
1525 aContinuations[ 1 ] = new ::ucbhelper::InteractionRetry( this );
1526 aContinuations[ 2 ] = m_xAuthSupplier.get();
1527
1528 setContinuations( aContinuations );
1529 }
1530
1531 //-------------------------------------------------------------------------
1532 //-------------------------------------------------------------------------
1533
1534 extern "C"
1535 {
component_getImplementationEnvironment(const sal_Char ** ppEnvTypeName,uno_Environment **)1536 SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment (
1537 const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */)
1538 {
1539 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
1540 }
1541
component_getFactory(const sal_Char * pImplementationName,void * pServiceManager,void *)1542 SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory (
1543 const sal_Char * pImplementationName, void * pServiceManager, void * /* pRegistryKey */)
1544 {
1545 void * pResult = 0;
1546 if (pServiceManager)
1547 {
1548 Reference< XSingleServiceFactory > xFactory;
1549 if (PasswordContainer::impl_getStaticImplementationName().compareToAscii (pImplementationName) == 0)
1550 {
1551 xFactory = PasswordContainer::impl_createFactory (
1552 reinterpret_cast< XMultiServiceFactory* >(pServiceManager));
1553 }
1554 if (xFactory.is())
1555 {
1556 xFactory->acquire();
1557 pResult = xFactory.get();
1558 }
1559 }
1560 return pResult;
1561 }
1562
1563 } // extern "C"
1564