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