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& ) throw(RuntimeException)
466 {
467 ::osl::MutexGuard aGuard( mMutex );
468
469 if( m_pStorageFile )
470 {
471 delete m_pStorageFile;
472 m_pStorageFile = NULL;
473 }
474
475 if( mComponent.is() )
476 {
477 //mComponent->removeEventListener(this);
478 mComponent = Reference< XComponent >();
479 }
480 }
481
482 //-------------------------------------------------------------------------
483
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 ) throw(RuntimeException)
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 ) throw(RuntimeException)
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 ) throw(RuntimeException)
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 ) throw(RuntimeException)
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 ) throw(RuntimeException)
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 ) throw(RuntimeException)
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 ) throw(RuntimeException)
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 ) throw(RuntimeException)
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 ) throw(RuntimeException)
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 ) throw(RuntimeException)
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 throw( RuntimeException )
868 {
869 if ( bName )
870 {
871 Sequence< UserRecord > aUsrRec
872 = FindUsr( rPair.second, aName, aHandler );
873 if( aUsrRec.getLength() )
874 {
875 rRec = UrlRecord( rPair.first, aUsrRec );
876 return true;
877 }
878 }
879 else
880 {
881 rRec = UrlRecord(
882 rPair.first,
883 CopyToUserRecordSequence( rPair.second, aHandler ) );
884 return true;
885 }
886 return false;
887 }
888
889 //-------------------------------------------------------------------------
890
find(const::rtl::OUString & aURL,const::rtl::OUString & aName,bool bName,const Reference<XInteractionHandler> & aHandler)891 UrlRecord PasswordContainer::find(
892 const ::rtl::OUString& aURL,
893 const ::rtl::OUString& aName,
894 bool bName, // only needed to support empty user names
895 const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException)
896 {
897 ::osl::MutexGuard aGuard( mMutex );
898
899 if( !m_aContainer.empty() && aURL.getLength() )
900 {
901 ::rtl::OUString aUrl( aURL );
902
903 // each iteration remove last '/...' section from the aUrl
904 // while it's possible, up to the most left '://'
905 do
906 {
907 // first look for <url>/somename and then look for <url>/somename/...
908 PassMap::iterator aIter = m_aContainer.find( aUrl );
909 // Note that this iterator may be invalidated by the
910 // side-effects of createUrlRecord(), so we have to work with a
911 // copy of the pointed elements
912 if( aIter != m_aContainer.end() )
913 {
914 const PairUrlRecord rPairUrlRecord = *aIter;
915 UrlRecord aRec;
916 if ( createUrlRecord( rPairUrlRecord, bName, aName, aHandler, aRec ) )
917 return aRec;
918 }
919 else
920 {
921 ::rtl::OUString tmpUrl( aUrl );
922 if ( tmpUrl.getStr()[tmpUrl.getLength() - 1] != (sal_Unicode)'/' )
923 tmpUrl += ::rtl::OUString::createFromAscii( "/" );
924
925 aIter = m_aContainer.lower_bound( tmpUrl );
926 if( aIter != m_aContainer.end() && aIter->first.match( tmpUrl ) )
927 {
928 const PairUrlRecord rPairUrlRecord = *aIter;
929 UrlRecord aRec;
930 if ( createUrlRecord( rPairUrlRecord, bName, aName, aHandler, aRec ) )
931 return aRec;
932 }
933 }
934 }
935 while( shorterUrl( aUrl ) && aUrl.getLength() );
936 }
937
938 return UrlRecord();
939 }
940
941 //-------------------------------------------------------------------------
GetDefaultMasterPassword()942 ::rtl::OUString PasswordContainer::GetDefaultMasterPassword()
943 {
944 ::rtl::OUString aResult;
945 for ( sal_Int32 nInd = 0; nInd < RTL_DIGEST_LENGTH_MD5; nInd++ )
946 aResult += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "aa" ) );
947
948 return aResult;
949 }
950
951 //-------------------------------------------------------------------------
RequestPasswordFromUser(PasswordRequestMode aRMode,const uno::Reference<task::XInteractionHandler> & xHandler)952 ::rtl::OUString PasswordContainer::RequestPasswordFromUser( PasswordRequestMode aRMode, const uno::Reference< task::XInteractionHandler >& xHandler )
953 {
954 // empty string means that the call was cancelled or just failed
955 ::rtl::OUString aResult;
956
957 if ( xHandler.is() )
958 {
959 ::rtl::Reference< MasterPasswordRequest_Impl > xRequest = new MasterPasswordRequest_Impl( aRMode );
960
961 xHandler->handle( xRequest.get() );
962
963 ::rtl::Reference< ucbhelper::InteractionContinuation > xSelection = xRequest->getSelection();
964
965 if ( xSelection.is() )
966 {
967 Reference< XInteractionAbort > xAbort( xSelection.get(), UNO_QUERY );
968 if ( !xAbort.is() )
969 {
970 const ::rtl::Reference< ucbhelper::InteractionSupplyAuthentication > & xSupp
971 = xRequest->getAuthenticationSupplier();
972
973 aResult = xSupp->getPassword();
974 }
975 }
976 }
977
978 return aResult;
979 }
980
981 //-------------------------------------------------------------------------
982
GetMasterPassword(const Reference<XInteractionHandler> & aHandler)983 ::rtl::OUString PasswordContainer::GetMasterPassword( const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException)
984 {
985 PasswordRequestMode aRMode = PasswordRequestMode_PASSWORD_ENTER;
986 if( !m_pStorageFile || !m_pStorageFile->useStorage() )
987 throw NoMasterException( ::rtl::OUString::createFromAscii( "Password storing is not active!" ), Reference< XInterface >(), aRMode );
988
989 if( !m_aMasterPasswd.getLength() && aHandler.is() )
990 {
991 ::rtl::OUString aEncodedMP;
992 sal_Bool bAskAgain = sal_False;
993 sal_Bool bDefaultPassword = sal_False;
994
995 if( !m_pStorageFile->getEncodedMP( aEncodedMP ) )
996 aRMode = PasswordRequestMode_PASSWORD_CREATE;
997 else if ( !aEncodedMP.getLength() )
998 {
999 m_aMasterPasswd = GetDefaultMasterPassword();
1000 bDefaultPassword = sal_True;
1001 }
1002
1003 if ( !bDefaultPassword )
1004 {
1005 do {
1006 bAskAgain = sal_False;
1007
1008 ::rtl::OUString aPass = RequestPasswordFromUser( aRMode, aHandler );
1009 if ( aPass.getLength() )
1010 {
1011 if( aRMode == PasswordRequestMode_PASSWORD_CREATE )
1012 {
1013 m_aMasterPasswd = aPass;
1014 vector< ::rtl::OUString > aMaster( 1, m_aMasterPasswd );
1015
1016 m_pStorageFile->setEncodedMP( EncodePasswords( getMasterPasswordName(), aMaster, m_aMasterPasswd ) );
1017 }
1018 else
1019 {
1020 vector< ::rtl::OUString > aRM( DecodePasswords( getMasterPasswordName(), aEncodedMP, aPass ) );
1021 if( !aRM.size() || !aPass.equals( aRM[0] ) )
1022 {
1023 // Try the old encoding
1024 mOldPasswordEncoding = true;
1025 try {
1026 aRM = DecodePasswords( getMasterPasswordName(), aEncodedMP, aPass );
1027 if (aRM.size() && aPass.equals(aRM[0])) {
1028 // Update all passwords to the new encoding
1029 m_aMasterPasswd = aPass;
1030 doChangeMasterPassword(aPass);
1031 }
1032 mOldPasswordEncoding = false;
1033 } catch (...) {
1034 mOldPasswordEncoding = false;
1035 throw;
1036 }
1037 }
1038 if( !aRM.size() || !aPass.equals( aRM[0] ) )
1039 {
1040 bAskAgain = sal_True;
1041 aRMode = PasswordRequestMode_PASSWORD_REENTER;
1042 }
1043 else
1044 m_aMasterPasswd = aPass;
1045 }
1046 }
1047
1048 } while( bAskAgain );
1049 }
1050 }
1051
1052 if ( !m_aMasterPasswd.getLength() )
1053 throw NoMasterException( ::rtl::OUString::createFromAscii( "No master password!" ), Reference< XInterface >(), aRMode );
1054
1055 return m_aMasterPasswd;
1056 }
1057
1058 //-------------------------------------------------------------------------
1059
remove(const::rtl::OUString & aURL,const::rtl::OUString & aName)1060 void SAL_CALL PasswordContainer::remove( const ::rtl::OUString& aURL, const ::rtl::OUString& aName ) throw(RuntimeException)
1061 {
1062 ::osl::MutexGuard aGuard( mMutex );
1063
1064 ::rtl::OUString aUrl( aURL );
1065 if( !m_aContainer.empty() )
1066 {
1067 PassMap::iterator aIter = m_aContainer.find( aUrl );
1068
1069 if( aIter == m_aContainer.end() )
1070 {
1071 sal_Int32 aInd = aUrl.lastIndexOf( sal_Unicode( '/' ) );
1072 if( aInd > 0 && aUrl.getLength()-1 == aInd )
1073 aUrl = aUrl.copy( 0, aUrl.getLength() - 1 );
1074 else
1075 aUrl += ::rtl::OUString::createFromAscii( "/" );
1076
1077 aIter = m_aContainer.find( aUrl );
1078 }
1079
1080 if( aIter != m_aContainer.end() )
1081 {
1082 for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); aNPIter++ )
1083 if( aNPIter->GetUserName().equals( aName ) )
1084 {
1085 if( aNPIter->HasPasswords( PERSISTENT_RECORD ) && m_pStorageFile )
1086 m_pStorageFile->remove( aURL, aName ); // remove record ( aURL, aName )
1087
1088 // the iterator will not be used any more so it can be removed directly
1089 aIter->second.erase( aNPIter );
1090
1091 if( aIter->second.begin() == aIter->second.end() )
1092 m_aContainer.erase( aIter );
1093
1094 return;
1095 }
1096 }
1097 }
1098 }
1099
1100 //-------------------------------------------------------------------------
1101
removePersistent(const::rtl::OUString & aURL,const::rtl::OUString & aName)1102 void SAL_CALL PasswordContainer::removePersistent( const ::rtl::OUString& aURL, const ::rtl::OUString& aName ) throw(RuntimeException)
1103 {
1104 ::osl::MutexGuard aGuard( mMutex );
1105
1106 ::rtl::OUString aUrl( aURL );
1107 if( !m_aContainer.empty() )
1108 {
1109 PassMap::iterator aIter = m_aContainer.find( aUrl );
1110
1111 if( aIter == m_aContainer.end() )
1112 {
1113 sal_Int32 aInd = aUrl.lastIndexOf( sal_Unicode( '/' ) );
1114 if( aInd > 0 && aUrl.getLength()-1 == aInd )
1115 aUrl = aUrl.copy( 0, aUrl.getLength() - 1 );
1116 else
1117 aUrl += ::rtl::OUString::createFromAscii( "/" );
1118
1119 aIter = m_aContainer.find( aUrl );
1120 }
1121
1122 if( aIter != m_aContainer.end() )
1123 {
1124 for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); aNPIter++ )
1125 if( aNPIter->GetUserName().equals( aName ) )
1126 {
1127 if( aNPIter->HasPasswords( PERSISTENT_RECORD ) )
1128 {
1129 // TODO/LATER: should the password be converted to MemoryPassword?
1130 aNPIter->RemovePasswords( PERSISTENT_RECORD );
1131
1132 if ( m_pStorageFile )
1133 m_pStorageFile->remove( aURL, aName ); // remove record ( aURL, aName )
1134 }
1135
1136 if( !aNPIter->HasPasswords( MEMORY_RECORD ) )
1137 aIter->second.erase( aNPIter );
1138
1139 if( aIter->second.begin() == aIter->second.end() )
1140 m_aContainer.erase( aIter );
1141
1142 return;
1143 }
1144 }
1145 }
1146 }
1147 //-------------------------------------------------------------------------
1148
removeAllPersistent()1149 void SAL_CALL PasswordContainer::removeAllPersistent() throw(RuntimeException)
1150 {
1151 ::osl::MutexGuard aGuard( mMutex );
1152
1153 if( m_pStorageFile )
1154 m_pStorageFile->clear();
1155
1156 for( PassMap::iterator aIter = m_aContainer.begin(); aIter != m_aContainer.end(); )
1157 {
1158 for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); )
1159 {
1160 if( aNPIter->HasPasswords( PERSISTENT_RECORD ) )
1161 {
1162 // TODO/LATER: should the password be converted to MemoryPassword?
1163 aNPIter->RemovePasswords( PERSISTENT_RECORD );
1164 }
1165
1166 if( !aNPIter->HasPasswords( MEMORY_RECORD ) )
1167 {
1168 list< NamePassRecord >::iterator aIterToDelete( aNPIter );
1169 aNPIter++;
1170 aIter->second.erase( aIterToDelete );
1171 }
1172 else
1173 aNPIter++;
1174 }
1175
1176 if( aIter->second.begin() == aIter->second.end() )
1177 {
1178 PassMap::iterator aIterToDelete( aIter );
1179 aIter++;
1180 m_aContainer.erase( aIterToDelete );
1181 }
1182 else
1183 aIter++;
1184 }
1185 }
1186 //-------------------------------------------------------------------------
1187
getAllPersistent(const Reference<XInteractionHandler> & xHandler)1188 Sequence< UrlRecord > SAL_CALL PasswordContainer::getAllPersistent( const Reference< XInteractionHandler >& xHandler ) throw(RuntimeException)
1189 {
1190 Sequence< UrlRecord > aResult;
1191
1192 ::osl::MutexGuard aGuard( mMutex );
1193 for( PassMap::iterator aIter = m_aContainer.begin(); aIter != m_aContainer.end(); aIter++ )
1194 {
1195 Sequence< UserRecord > aUsers;
1196 for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); aNPIter++ )
1197 if( aNPIter->HasPasswords( PERSISTENT_RECORD ) )
1198 {
1199 sal_Int32 oldLen = aUsers.getLength();
1200 aUsers.realloc( oldLen + 1 );
1201 aUsers[ oldLen ] = UserRecord( aNPIter->GetUserName(), copyVectorToSequence( DecodePasswords( aNPIter->GetUserName(), aNPIter->GetPersPasswords(), GetMasterPassword( xHandler ) ) ) );
1202 }
1203
1204 if( aUsers.getLength() )
1205 {
1206 sal_Int32 oldLen = aResult.getLength();
1207 aResult.realloc( oldLen + 1 );
1208 aResult[ oldLen ] = UrlRecord( aIter->first, aUsers );
1209 }
1210 }
1211
1212 return aResult;
1213 }
1214
1215 //-------------------------------------------------------------------------
authorizateWithMasterPassword(const uno::Reference<task::XInteractionHandler> & xHandler)1216 sal_Bool SAL_CALL PasswordContainer::authorizateWithMasterPassword( const uno::Reference< task::XInteractionHandler >& xHandler )
1217 throw (uno::RuntimeException)
1218 {
1219 sal_Bool bResult = sal_False;
1220 ::rtl::OUString aEncodedMP;
1221 uno::Reference< task::XInteractionHandler > xTmpHandler = xHandler;
1222 ::osl::MutexGuard aGuard( mMutex );
1223
1224 // the method should fail if there is no master password
1225 if( m_pStorageFile && m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) )
1226 {
1227 if ( !aEncodedMP.getLength() )
1228 {
1229 // this is a default master password
1230 // no UI is necessary
1231 bResult = sal_True;
1232 }
1233 else
1234 {
1235 if ( !xTmpHandler.is() )
1236 {
1237 uno::Reference< lang::XMultiServiceFactory > xFactory( mComponent, uno::UNO_QUERY_THROW );
1238 xTmpHandler.set( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.InteractionHandler" ) ) ), uno::UNO_QUERY_THROW );
1239 }
1240
1241 if ( m_aMasterPasswd.getLength() )
1242 {
1243 // there is a password, it should be just rechecked
1244 PasswordRequestMode aRMode = PasswordRequestMode_PASSWORD_ENTER;
1245 ::rtl::OUString aPass;
1246
1247 do {
1248 aPass = RequestPasswordFromUser( aRMode, xTmpHandler );
1249 bResult = ( aPass.getLength() && aPass.equals( m_aMasterPasswd ) );
1250 aRMode = PasswordRequestMode_PASSWORD_REENTER; // further questions with error notification
1251 } while( !bResult && aPass.getLength() );
1252 }
1253 else
1254 {
1255 try
1256 {
1257 // ask for the password, if user provide no correct password an exception will be thrown
1258 bResult = ( GetMasterPassword( xTmpHandler ).getLength() > 0 );
1259 }
1260 catch( uno::Exception& )
1261 {}
1262 }
1263 }
1264 }
1265
1266 return bResult;
1267 }
1268
1269 //-------------------------------------------------------------------------
changeMasterPassword(const uno::Reference<task::XInteractionHandler> & xHandler)1270 sal_Bool SAL_CALL PasswordContainer::changeMasterPassword( const uno::Reference< task::XInteractionHandler >& xHandler )
1271 throw (uno::RuntimeException)
1272 {
1273 sal_Bool bResult = sal_False;
1274 uno::Reference< task::XInteractionHandler > xTmpHandler = xHandler;
1275 ::osl::MutexGuard aGuard( mMutex );
1276
1277 if ( m_pStorageFile && m_pStorageFile->useStorage() )
1278 {
1279 if ( !xTmpHandler.is() )
1280 {
1281 uno::Reference< lang::XMultiServiceFactory > xFactory( mComponent, uno::UNO_QUERY_THROW );
1282 xTmpHandler.set( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.InteractionHandler" ) ) ), uno::UNO_QUERY_THROW );
1283 }
1284
1285 sal_Bool bCanChangePassword = sal_True;
1286 // if there is already a stored master password it should be entered by the user before the change happen
1287 ::rtl::OUString aEncodedMP;
1288 if( m_aMasterPasswd.getLength() || m_pStorageFile->getEncodedMP( aEncodedMP ) )
1289 bCanChangePassword = authorizateWithMasterPassword( xTmpHandler );
1290
1291 if ( bCanChangePassword )
1292 {
1293 // ask for the new password, but do not set it
1294 PasswordRequestMode aRMode = PasswordRequestMode_PASSWORD_CREATE;
1295 ::rtl::OUString aPass = RequestPasswordFromUser( aRMode, xTmpHandler );
1296
1297 if ( aPass.getLength() )
1298 {
1299 doChangeMasterPassword(aPass);
1300 bResult = sal_True;
1301 }
1302 }
1303 }
1304
1305 return bResult;
1306 }
1307
1308 //-------------------------------------------------------------------------
removeMasterPassword()1309 void SAL_CALL PasswordContainer::removeMasterPassword()
1310 throw (uno::RuntimeException)
1311 {
1312 // remove all the stored passwords and the master password
1313 removeAllPersistent();
1314
1315 // Make sure we will not use the older encoding in the future
1316 mOldPasswordEncoding = false;
1317
1318 ::osl::MutexGuard aGuard( mMutex );
1319 if ( m_pStorageFile )
1320 {
1321 m_aMasterPasswd = ::rtl::OUString();
1322 m_pStorageFile->setEncodedMP( ::rtl::OUString() ); // let the master password be removed from configuration
1323 }
1324 }
1325
1326 //-------------------------------------------------------------------------
hasMasterPassword()1327 ::sal_Bool SAL_CALL PasswordContainer::hasMasterPassword( )
1328 throw (::com::sun::star::uno::RuntimeException)
1329 {
1330 ::osl::MutexGuard aGuard( mMutex );
1331
1332 if ( !m_pStorageFile )
1333 throw uno::RuntimeException();
1334
1335 ::rtl::OUString aEncodedMP;
1336 return ( m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) );
1337 }
1338
1339 //-------------------------------------------------------------------------
allowPersistentStoring(::sal_Bool bAllow)1340 ::sal_Bool SAL_CALL PasswordContainer::allowPersistentStoring( ::sal_Bool bAllow )
1341 throw (::com::sun::star::uno::RuntimeException)
1342 {
1343 ::osl::MutexGuard aGuard( mMutex );
1344
1345 if ( !m_pStorageFile )
1346 throw uno::RuntimeException();
1347
1348 if ( !bAllow )
1349 removeMasterPassword();
1350
1351 if ( m_pStorageFile->useStorage() == bAllow )
1352 return bAllow;
1353
1354 m_pStorageFile->setUseStorage( bAllow );
1355 return !bAllow;
1356 }
1357
1358 //-------------------------------------------------------------------------
isPersistentStoringAllowed()1359 ::sal_Bool SAL_CALL PasswordContainer::isPersistentStoringAllowed()
1360 throw (::com::sun::star::uno::RuntimeException)
1361 {
1362 ::osl::MutexGuard aGuard( mMutex );
1363
1364 if ( !m_pStorageFile )
1365 throw uno::RuntimeException();
1366
1367 return m_pStorageFile->useStorage();
1368 }
1369
1370 //-------------------------------------------------------------------------
useDefaultMasterPassword(const uno::Reference<task::XInteractionHandler> & xHandler)1371 ::sal_Bool SAL_CALL PasswordContainer::useDefaultMasterPassword( const uno::Reference< task::XInteractionHandler >& xHandler )
1372 throw ( uno::RuntimeException )
1373 {
1374 sal_Bool bResult = sal_False;
1375 uno::Reference< task::XInteractionHandler > xTmpHandler = xHandler;
1376 ::osl::MutexGuard aGuard( mMutex );
1377
1378 if ( m_pStorageFile && m_pStorageFile->useStorage() )
1379 {
1380 if ( !xTmpHandler.is() )
1381 {
1382 uno::Reference< lang::XMultiServiceFactory > xFactory( mComponent, uno::UNO_QUERY_THROW );
1383 xTmpHandler.set( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.InteractionHandler" ) ) ), uno::UNO_QUERY_THROW );
1384 }
1385
1386 sal_Bool bCanChangePassword = sal_True;
1387 // if there is already a stored nondefault master password it should be entered by the user before the change happen
1388 ::rtl::OUString aEncodedMP;
1389 if( m_pStorageFile->getEncodedMP( aEncodedMP ) && aEncodedMP.getLength() )
1390 bCanChangePassword = authorizateWithMasterPassword( xTmpHandler );
1391
1392 if ( bCanChangePassword )
1393 {
1394 // generate the default password
1395 ::rtl::OUString aPass = GetDefaultMasterPassword();
1396 if ( aPass.getLength() )
1397 {
1398 // get all the persistent entries if it is possible
1399 Sequence< UrlRecord > aPersistent = getAllPersistent( uno::Reference< task::XInteractionHandler >() );
1400
1401 // remove the master password and the entries persistence
1402 removeMasterPassword();
1403
1404 // store the empty string to flag the default master password
1405 m_aMasterPasswd = aPass;
1406 m_pStorageFile->setEncodedMP( ::rtl::OUString(), sal_True );
1407
1408 // store all the entries with the new password
1409 for ( int nURLInd = 0; nURLInd < aPersistent.getLength(); nURLInd++ )
1410 for ( int nNameInd = 0; nNameInd< aPersistent[nURLInd].UserList.getLength(); nNameInd++ )
1411 addPersistent( aPersistent[nURLInd].Url,
1412 aPersistent[nURLInd].UserList[nNameInd].UserName,
1413 aPersistent[nURLInd].UserList[nNameInd].Passwords,
1414 uno::Reference< task::XInteractionHandler >() );
1415
1416 bResult = sal_True;
1417 }
1418 }
1419 }
1420
1421 return bResult;
1422
1423 }
1424
1425 //-------------------------------------------------------------------------
isDefaultMasterPasswordUsed()1426 ::sal_Bool SAL_CALL PasswordContainer::isDefaultMasterPasswordUsed()
1427 throw ( uno::RuntimeException )
1428 {
1429 ::osl::MutexGuard aGuard( mMutex );
1430
1431 if ( !m_pStorageFile )
1432 throw uno::RuntimeException();
1433
1434 ::rtl::OUString aEncodedMP;
1435 return ( m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) && !aEncodedMP.getLength() );
1436 }
1437
1438
1439 //-------------------------------------------------------------------------
addUrl(const::rtl::OUString & Url,::sal_Bool MakePersistent)1440 void SAL_CALL PasswordContainer::addUrl( const ::rtl::OUString& Url, ::sal_Bool MakePersistent )
1441 throw (uno::RuntimeException)
1442 {
1443 mUrlContainer.add( Url, MakePersistent );
1444 }
1445
1446 //-------------------------------------------------------------------------
findUrl(const::rtl::OUString & Url)1447 ::rtl::OUString SAL_CALL PasswordContainer::findUrl( const ::rtl::OUString& Url )
1448 throw (uno::RuntimeException)
1449 {
1450 return mUrlContainer.find( Url );
1451 }
1452
1453 //-------------------------------------------------------------------------
removeUrl(const::rtl::OUString & Url)1454 void SAL_CALL PasswordContainer::removeUrl( const ::rtl::OUString& Url )
1455 throw (uno::RuntimeException)
1456 {
1457 mUrlContainer.remove( Url );
1458 }
1459
1460 //-------------------------------------------------------------------------
getUrls(::sal_Bool OnlyPersistent)1461 uno::Sequence< ::rtl::OUString > SAL_CALL PasswordContainer::getUrls( ::sal_Bool OnlyPersistent )
1462 throw (uno::RuntimeException)
1463 {
1464 return mUrlContainer.list( OnlyPersistent );
1465 }
1466
1467 //-------------------------------------------------------------------------
1468
Notify()1469 void PasswordContainer::Notify()
1470 {
1471 ::osl::MutexGuard aGuard( mMutex );
1472
1473 PassMap::iterator aIter;
1474
1475 // remove the cached persistent values in the memory
1476 for( aIter = m_aContainer.begin(); aIter != m_aContainer.end(); aIter++ )
1477 {
1478 for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); )
1479 {
1480 if( aNPIter->HasPasswords( PERSISTENT_RECORD ) )
1481 {
1482 aNPIter->RemovePasswords( PERSISTENT_RECORD );
1483
1484 if ( m_pStorageFile )
1485 m_pStorageFile->remove( aIter->first, aNPIter->GetUserName() ); // remove record ( aURL, aName )
1486 }
1487
1488 if( !aNPIter->HasPasswords( MEMORY_RECORD ) )
1489 {
1490 list< NamePassRecord >::iterator aIterToDelete( aNPIter );
1491 aNPIter++;
1492 aIter->second.erase( aIterToDelete );
1493 }
1494 else
1495 aNPIter++;
1496 }
1497 }
1498
1499 PassMap addon;
1500 if( m_pStorageFile )
1501 addon = m_pStorageFile->getInfo();
1502
1503 for( aIter = addon.begin(); aIter != addon.end(); aIter++ )
1504 {
1505 PassMap::iterator aSearchIter = m_aContainer.find( aIter->first );
1506 if( aSearchIter != m_aContainer.end() )
1507 for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); aNPIter++ )
1508 UpdateVector( aSearchIter->first, aSearchIter->second, *aNPIter, sal_False );
1509 else
1510 m_aContainer.insert( PairUrlRecord( aIter->first, aIter->second ) );
1511 }
1512 }
1513
1514 //-------------------------------------------------------------------------
1515
getImplementationName()1516 ::rtl::OUString SAL_CALL PasswordContainer::getImplementationName( ) throw(uno::RuntimeException)
1517 {
1518 return impl_getStaticImplementationName();
1519 }
1520
1521 //-------------------------------------------------------------------------
1522
supportsService(const::rtl::OUString & ServiceName)1523 sal_Bool SAL_CALL PasswordContainer::supportsService( const ::rtl::OUString& ServiceName ) throw(uno::RuntimeException)
1524 {
1525 if ( ServiceName.compareToAscii("com.sun.star.task.PasswordContainer") == 0 )
1526 return sal_True;
1527 else
1528 return sal_False;
1529 }
1530
1531 //-------------------------------------------------------------------------
1532
getSupportedServiceNames()1533 Sequence< ::rtl::OUString > SAL_CALL PasswordContainer::getSupportedServiceNames( ) throw(uno::RuntimeException)
1534 {
1535 return impl_getStaticSupportedServiceNames();
1536 }
1537
1538 //-------------------------------------------------------------------------
1539
impl_getStaticSupportedServiceNames()1540 Sequence< ::rtl::OUString > SAL_CALL PasswordContainer::impl_getStaticSupportedServiceNames( ) throw(uno::RuntimeException)
1541 {
1542 Sequence< ::rtl::OUString > aRet(1);
1543 *aRet.getArray() = ::rtl::OUString::createFromAscii("com.sun.star.task.PasswordContainer");
1544 return aRet;
1545 }
1546
1547 //-------------------------------------------------------------------------
1548
impl_getStaticImplementationName()1549 ::rtl::OUString SAL_CALL PasswordContainer::impl_getStaticImplementationName() throw(uno::RuntimeException)
1550 {
1551 return ::rtl::OUString::createFromAscii("stardiv.svl.PasswordContainer");
1552 }
1553
1554 //-------------------------------------------------------------------------
1555
impl_createInstance(const Reference<XMultiServiceFactory> & xServiceManager)1556 Reference< XInterface > SAL_CALL PasswordContainer::impl_createInstance( const Reference< XMultiServiceFactory >& xServiceManager ) throw( RuntimeException )
1557 {
1558 return Reference< XInterface >( *new PasswordContainer( xServiceManager ) );
1559 }
1560
1561 //-------------------------------------------------------------------------
1562
impl_createFactory(const Reference<XMultiServiceFactory> & ServiceManager)1563 Reference< XSingleServiceFactory > SAL_CALL PasswordContainer::impl_createFactory( const Reference< XMultiServiceFactory >& ServiceManager ) throw(RuntimeException)
1564 {
1565 Reference< XSingleServiceFactory > xReturn( ::cppu::createOneInstanceFactory( ServiceManager,
1566 PasswordContainer::impl_getStaticImplementationName(),
1567 PasswordContainer::impl_createInstance,
1568 PasswordContainer::impl_getStaticSupportedServiceNames()));
1569 return xReturn ;
1570
1571 }
1572
1573 //-------------------------------------------------------------------------
1574 //-------------------------------------------------------------------------
1575
MasterPasswordRequest_Impl(PasswordRequestMode Mode)1576 MasterPasswordRequest_Impl::MasterPasswordRequest_Impl( PasswordRequestMode Mode )
1577 {
1578 MasterPasswordRequest aRequest;
1579
1580 aRequest.Classification = InteractionClassification_ERROR;
1581 aRequest.Mode = Mode;
1582
1583 setRequest( makeAny( aRequest ) );
1584
1585 // Fill continuations...
1586 Sequence< RememberAuthentication > aRememberModes( 1 );
1587 aRememberModes[ 0 ] = RememberAuthentication_NO;
1588
1589 m_xAuthSupplier
1590 = new ::ucbhelper::InteractionSupplyAuthentication(
1591 this,
1592 sal_False, // bCanSetRealm
1593 sal_False, // bCanSetUserName
1594 sal_True, // bCanSetPassword
1595 sal_False, // bCanSetAccount
1596 aRememberModes, // rRememberPasswordModes
1597 RememberAuthentication_NO, // eDefaultRememberPasswordMode
1598 aRememberModes, // rRememberAccountModes
1599 RememberAuthentication_NO, // eDefaultRememberAccountMode
1600 sal_False, // bCanUseSystemCredentials
1601 sal_False // bDefaultUseSystemCredentials
1602 );
1603
1604 Sequence<
1605 Reference< XInteractionContinuation > > aContinuations( 3 );
1606 aContinuations[ 0 ] = new ::ucbhelper::InteractionAbort( this );
1607 aContinuations[ 1 ] = new ::ucbhelper::InteractionRetry( this );
1608 aContinuations[ 2 ] = m_xAuthSupplier.get();
1609
1610 setContinuations( aContinuations );
1611 }
1612
1613 //-------------------------------------------------------------------------
1614 //-------------------------------------------------------------------------
1615
1616 extern "C"
1617 {
component_getImplementationEnvironment(const sal_Char ** ppEnvTypeName,uno_Environment **)1618 SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment (
1619 const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */)
1620 {
1621 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
1622 }
1623
component_getFactory(const sal_Char * pImplementationName,void * pServiceManager,void *)1624 SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory (
1625 const sal_Char * pImplementationName, void * pServiceManager, void * /* pRegistryKey */)
1626 {
1627 void * pResult = 0;
1628 if (pServiceManager)
1629 {
1630 Reference< XSingleServiceFactory > xFactory;
1631 if (PasswordContainer::impl_getStaticImplementationName().compareToAscii (pImplementationName) == 0)
1632 {
1633 xFactory = PasswordContainer::impl_createFactory (
1634 reinterpret_cast< XMultiServiceFactory* >(pServiceManager));
1635 }
1636 if (xFactory.is())
1637 {
1638 xFactory->acquire();
1639 pResult = xFactory.get();
1640 }
1641 }
1642 return pResult;
1643 }
1644
1645 } // extern "C"
1646