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