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