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