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