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