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 )
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 
DecodePasswords(const::rtl::OUString & aLine,const::rtl::OUString & aMasterPasswd)484 vector< ::rtl::OUString > PasswordContainer::DecodePasswords( const ::rtl::OUString& aLine, const ::rtl::OUString& aMasterPasswd ) throw(RuntimeException)
485 {
486     if( aMasterPasswd.getLength() )
487     {
488         rtlCipher aDecoder = rtl_cipher_create (rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeStream );
489         OSL_ENSURE( aDecoder, "Can't create decoder\n" );
490 
491         if( aDecoder )
492         {
493             OSL_ENSURE( aMasterPasswd.getLength() == RTL_DIGEST_LENGTH_MD5 * 2, "Wrong master password format!\n" );
494 
495             unsigned char code[RTL_DIGEST_LENGTH_MD5];
496             for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ )
497                 code[ ind ] = (char)(aMasterPasswd.copy( ind*2, 2 ).toInt32(16));
498 
499             rtlCipherError result = rtl_cipher_init (
500                     aDecoder, rtl_Cipher_DirectionDecode,
501                     code, RTL_DIGEST_LENGTH_MD5, NULL, 0 );
502 
503             if( result == rtl_Cipher_E_None )
504             {
505                 ::rtl::ByteSequence aSeq = getBufFromAsciiLine( aLine );
506 
507                 ::rtl::ByteSequence resSeq( aSeq.getLength() );
508 
509                 result = rtl_cipher_decode ( aDecoder, (sal_uInt8*)aSeq.getArray(), aSeq.getLength(),
510                                                         (sal_uInt8*)resSeq.getArray(), resSeq.getLength() );
511 
512                 ::rtl::OUString aPasswd( ( sal_Char* )resSeq.getArray(), resSeq.getLength(), RTL_TEXTENCODING_UTF8 );
513 
514                 rtl_cipher_destroy (aDecoder);
515 
516                 return getInfoFromInd( aPasswd );
517             }
518 
519             rtl_cipher_destroy (aDecoder);
520         }
521     }
522     else
523     {
524         OSL_ENSURE( sal_False, "No master password provided!\n" );
525         // throw special exception
526     }
527 
528     // problems with decoding
529     OSL_ENSURE( sal_False, "Problem with decoding\n" );
530     throw RuntimeException( ::rtl::OUString::createFromAscii( "Can't decode!" ), Reference< XInterface >() );
531 }
532 
533 
534 //-------------------------------------------------------------------------
535 
EncodePasswords(vector<::rtl::OUString> lines,const::rtl::OUString & aMasterPasswd)536 ::rtl::OUString PasswordContainer::EncodePasswords( vector< ::rtl::OUString > lines, const ::rtl::OUString& aMasterPasswd ) throw(RuntimeException)
537 {
538     if( aMasterPasswd.getLength() )
539     {
540         ::rtl::OString aSeq = ::rtl::OUStringToOString( createIndex( lines ), RTL_TEXTENCODING_UTF8 );
541 
542         rtlCipher aEncoder = rtl_cipher_create (rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeStream );
543         OSL_ENSURE( aEncoder, "Can't create encoder\n" );
544 
545         if( aEncoder )
546         {
547             OSL_ENSURE( aMasterPasswd.getLength() == RTL_DIGEST_LENGTH_MD5 * 2, "Wrong master password format!\n" );
548 
549             unsigned char code[RTL_DIGEST_LENGTH_MD5];
550             for( int ind = 0; ind < RTL_DIGEST_LENGTH_MD5; ind++ )
551                 code[ ind ] = (char)(aMasterPasswd.copy( ind*2, 2 ).toInt32(16));
552 
553             rtlCipherError result = rtl_cipher_init (
554                     aEncoder, rtl_Cipher_DirectionEncode,
555                     code, RTL_DIGEST_LENGTH_MD5, NULL, 0 );
556 
557             if( result == rtl_Cipher_E_None )
558             {
559                 ::rtl::ByteSequence resSeq(aSeq.getLength()+1);
560 
561                 result = rtl_cipher_encode ( aEncoder, (sal_uInt8*)aSeq.getStr(), aSeq.getLength()+1,
562                                                         (sal_uInt8*)resSeq.getArray(), resSeq.getLength() );
563 
564 /*
565                 //test
566                 rtlCipherError result = rtl_cipher_init (
567                     aEncoder, rtl_Cipher_DirectionDecode,
568                     code, RTL_DIGEST_LENGTH_MD5, NULL, 0 );
569 
570 
571                 if( result == rtl_Cipher_E_None )
572                 {
573                     ::rtl::OUString testOU = getAsciiLine( resSeq );
574                     ::rtl::ByteSequence aSeq1 = getBufFromAsciiLine( testOU );
575 
576                     ::rtl::ByteSequence resSeq1( aSeq1.getLength() );
577 
578                     if( resSeq.getLength() == aSeq1.getLength() )
579                     {
580                         for( int ind = 0; ind < aSeq1.getLength(); ind++ )
581                             if( resSeq[ind] != aSeq1[ind] )
582                                 testOU = ::rtl::OUString();
583                     }
584 
585                     result = rtl_cipher_decode ( aEncoder, (sal_uInt8*)aSeq1.getArray(), aSeq1.getLength(),
586                                                         (sal_uInt8*)resSeq1.getArray(), resSeq1.getLength() );
587 
588                     ::rtl::OUString aPasswd( ( sal_Char* )resSeq1.getArray(), resSeq1.getLength(), RTL_TEXTENCODING_UTF8 );
589                 }
590 */
591 
592                 rtl_cipher_destroy (aEncoder);
593 
594                 if( result == rtl_Cipher_E_None )
595                     return getAsciiLine( resSeq );
596 
597             }
598 
599             rtl_cipher_destroy (aEncoder);
600         }
601     }
602     else
603     {
604         OSL_ENSURE( sal_False, "No master password provided!\n" );
605         // throw special exception
606     }
607 
608     // problems with encoding
609     OSL_ENSURE( sal_False, "Problem with encoding\n" );
610     throw RuntimeException( ::rtl::OUString::createFromAscii( "Can't encode!" ), Reference< XInterface >() );
611 }
612 
613 //-------------------------------------------------------------------------
614 
UpdateVector(const::rtl::OUString & aURL,list<NamePassRecord> & toUpdate,NamePassRecord & aRecord,sal_Bool writeFile)615 void PasswordContainer::UpdateVector( const ::rtl::OUString& aURL, list< NamePassRecord >& toUpdate, NamePassRecord& aRecord, sal_Bool writeFile ) throw(RuntimeException)
616 {
617     for( list< NamePassRecord >::iterator aNPIter = toUpdate.begin(); aNPIter != toUpdate.end(); aNPIter++ )
618         if( aNPIter->GetUserName().equals( aRecord.GetUserName() ) )
619         {
620             if( aRecord.HasPasswords( MEMORY_RECORD ) )
621                 aNPIter->SetMemPasswords( aRecord.GetMemPasswords() );
622 
623             if( aRecord.HasPasswords( PERSISTENT_RECORD ) )
624             {
625                 aNPIter->SetPersPasswords( aRecord.GetPersPasswords() );
626 
627                 if( writeFile )
628                 {
629                     // the password must be already encoded
630                     m_pStorageFile->update( aURL, aRecord ); // change existing ( aURL, aName ) record in the configfile
631                 }
632             }
633 
634             return;
635         }
636 
637 
638     if( aRecord.HasPasswords( PERSISTENT_RECORD ) && writeFile )
639     {
640         // the password must be already encoded
641         m_pStorageFile->update( aURL, aRecord ); // add new aName to the existing url
642     }
643 
644     toUpdate.insert( toUpdate.begin(), aRecord );
645 }
646 
647 //-------------------------------------------------------------------------
648 
CopyToUserRecord(const NamePassRecord & aRecord,sal_Bool & io_bTryToDecode,const Reference<XInteractionHandler> & aHandler)649 UserRecord PasswordContainer::CopyToUserRecord( const NamePassRecord& aRecord, sal_Bool& io_bTryToDecode, const Reference< XInteractionHandler >& aHandler )
650 {
651     ::std::vector< ::rtl::OUString > aPasswords;
652     if( aRecord.HasPasswords( MEMORY_RECORD ) )
653         aPasswords = aRecord.GetMemPasswords();
654 
655     if( io_bTryToDecode && aRecord.HasPasswords( PERSISTENT_RECORD ) )
656     {
657         try
658         {
659             ::std::vector< ::rtl::OUString > aDecodedPasswords = DecodePasswords( aRecord.GetPersPasswords(), GetMasterPassword( aHandler ) );
660             aPasswords.insert( aPasswords.end(), aDecodedPasswords.begin(), aDecodedPasswords.end() );
661         }
662         catch( NoMasterException& )
663         {
664             // if master password could not be detected the entry will be just ignored
665             io_bTryToDecode = sal_False;
666         }
667     }
668 
669     return UserRecord( aRecord.GetUserName(), copyVectorToSequence( aPasswords ) );
670 }
671 
672 //-------------------------------------------------------------------------
673 
CopyToUserRecordSequence(const list<NamePassRecord> & original,const Reference<XInteractionHandler> & aHandler)674 Sequence< UserRecord > PasswordContainer::CopyToUserRecordSequence( const list< NamePassRecord >& original, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException)
675 {
676     Sequence< UserRecord >     aResult( original.size() );
677     sal_uInt32 nInd = 0;
678     sal_Bool bTryToDecode = sal_True;
679 
680     for( list< NamePassRecord >::const_iterator aNPIter = original.begin();
681          aNPIter != original.end();
682          aNPIter++, nInd++ )
683     {
684         aResult[nInd] = CopyToUserRecord( *aNPIter, bTryToDecode, aHandler );
685     }
686 
687     return aResult;
688 }
689 
690 //-------------------------------------------------------------------------
691 
add(const::rtl::OUString & Url,const::rtl::OUString & UserName,const Sequence<::rtl::OUString> & Passwords,const Reference<XInteractionHandler> & aHandler)692 void SAL_CALL PasswordContainer::add( const ::rtl::OUString& Url, const ::rtl::OUString& UserName, const Sequence< ::rtl::OUString >& Passwords, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException)
693 {
694     ::osl::MutexGuard aGuard( mMutex );
695 
696     PrivateAdd( Url, UserName, Passwords, MEMORY_RECORD, aHandler );
697 }
698 
699 //-------------------------------------------------------------------------
700 
addPersistent(const::rtl::OUString & Url,const::rtl::OUString & UserName,const Sequence<::rtl::OUString> & Passwords,const Reference<XInteractionHandler> & aHandler)701 void SAL_CALL PasswordContainer::addPersistent( const ::rtl::OUString& Url, const ::rtl::OUString& UserName, const Sequence< ::rtl::OUString >& Passwords, const Reference< XInteractionHandler >& aHandler  ) throw(RuntimeException)
702 {
703     ::osl::MutexGuard aGuard( mMutex );
704 
705     PrivateAdd( Url, UserName, Passwords, PERSISTENT_RECORD, aHandler );
706 }
707 
708 //-------------------------------------------------------------------------
709 
PrivateAdd(const::rtl::OUString & Url,const::rtl::OUString & UserName,const Sequence<::rtl::OUString> & Passwords,char Mode,const Reference<XInteractionHandler> & aHandler)710 void PasswordContainer::PrivateAdd( const ::rtl::OUString& Url, const ::rtl::OUString& UserName, const Sequence< ::rtl::OUString >& Passwords, char Mode, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException)
711 {
712     NamePassRecord aRecord( UserName );
713     ::std::vector< ::rtl::OUString > aStorePass = copySequenceToVector( Passwords );
714 
715     if( Mode == PERSISTENT_RECORD )
716         aRecord.SetPersPasswords( EncodePasswords( aStorePass, GetMasterPassword( aHandler ) ) );
717     else if( Mode == MEMORY_RECORD )
718         aRecord.SetMemPasswords( aStorePass );
719     else
720     {
721         OSL_ASSERT( "Unexpected persistence status!" );
722         return;
723     }
724 
725     if( !m_aContainer.empty() )
726     {
727         PassMap::iterator aIter = m_aContainer.find( Url );
728 
729         if( aIter != m_aContainer.end() )
730         {
731             UpdateVector( aIter->first, aIter->second, aRecord, sal_True );
732             return;
733         }
734     }
735 
736     list< NamePassRecord > listToAdd( 1, aRecord );
737     m_aContainer.insert( PairUrlRecord( Url, listToAdd ) );
738 
739     if( Mode == PERSISTENT_RECORD && m_pStorageFile && m_pStorageFile->useStorage() )
740         m_pStorageFile->update( Url, aRecord );
741 
742 }
743 
744 //-------------------------------------------------------------------------
745 
746 
find(const::rtl::OUString & aURL,const Reference<XInteractionHandler> & aHandler)747 UrlRecord SAL_CALL PasswordContainer::find( const ::rtl::OUString& aURL, const Reference< XInteractionHandler >& aHandler  ) throw(RuntimeException)
748 {
749     return find( aURL, rtl::OUString(), false, aHandler );
750 }
751 
752 //-------------------------------------------------------------------------
753 
findForName(const::rtl::OUString & aURL,const::rtl::OUString & aName,const Reference<XInteractionHandler> & aHandler)754 UrlRecord SAL_CALL PasswordContainer::findForName( const ::rtl::OUString& aURL, const ::rtl::OUString& aName, const Reference< XInteractionHandler >& aHandler  ) throw(RuntimeException)
755 {
756     return find( aURL, aName, true, aHandler );
757 }
758 
759 //-------------------------------------------------------------------------
760 
FindUsr(const list<NamePassRecord> & userlist,const::rtl::OUString & aName,const Reference<XInteractionHandler> & aHandler)761 Sequence< UserRecord > PasswordContainer::FindUsr( const list< NamePassRecord >& userlist, const ::rtl::OUString& aName, const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException)
762 {
763     sal_uInt32 nInd = 0;
764     for( list< NamePassRecord >::const_iterator aNPIter = userlist.begin();
765          aNPIter != userlist.end();
766          aNPIter++, nInd++ )
767     {
768         if( aNPIter->GetUserName().equals( aName ) )
769         {
770             Sequence< UserRecord > aResult(1);
771             sal_Bool bTryToDecode = sal_True;
772             aResult[0] = CopyToUserRecord( *aNPIter, bTryToDecode, aHandler );
773 
774             return aResult;
775         }
776     }
777 
778     return Sequence< UserRecord >();
779 }
780 
781 //-------------------------------------------------------------------------
782 
createUrlRecord(const PassMap::iterator & rIter,bool bName,const::rtl::OUString & aName,const Reference<XInteractionHandler> & aHandler,UrlRecord & rRec)783 bool PasswordContainer::createUrlRecord(
784     const PassMap::iterator & rIter,
785     bool bName,
786     const ::rtl::OUString & aName,
787     const Reference< XInteractionHandler >& aHandler,
788     UrlRecord & rRec )
789         throw( RuntimeException )
790 {
791     if ( bName )
792     {
793         Sequence< UserRecord > aUsrRec
794             = FindUsr( rIter->second, aName, aHandler );
795         if( aUsrRec.getLength() )
796         {
797             rRec = UrlRecord( rIter->first, aUsrRec );
798             return true;
799         }
800     }
801     else
802     {
803         rRec = UrlRecord(
804             rIter->first,
805             CopyToUserRecordSequence( rIter->second, aHandler ) );
806         return true;
807     }
808     return false;
809 }
810 
811 //-------------------------------------------------------------------------
812 
find(const::rtl::OUString & aURL,const::rtl::OUString & aName,bool bName,const Reference<XInteractionHandler> & aHandler)813 UrlRecord PasswordContainer::find(
814     const ::rtl::OUString& aURL,
815     const ::rtl::OUString& aName,
816     bool bName, // only needed to support empty user names
817     const Reference< XInteractionHandler >& aHandler  ) throw(RuntimeException)
818 {
819     ::osl::MutexGuard aGuard( mMutex );
820 
821     if( !m_aContainer.empty() && aURL.getLength() )
822     {
823         ::rtl::OUString aUrl( aURL );
824 
825         // each iteration remove last '/...' section from the aUrl
826         // while it's possible, up to the most left '://'
827         do
828         {
829             // first look for <url>/somename and then look for <url>/somename/...
830             PassMap::iterator aIter = m_aContainer.find( aUrl );
831             if( aIter != m_aContainer.end() )
832             {
833                 UrlRecord aRec;
834                 if ( createUrlRecord( aIter, bName, aName, aHandler, aRec ) )
835                   return aRec;
836             }
837             else
838             {
839                 ::rtl::OUString tmpUrl( aUrl );
840                 if ( tmpUrl.getStr()[tmpUrl.getLength() - 1] != (sal_Unicode)'/' )
841                     tmpUrl += ::rtl::OUString::createFromAscii( "/" );
842 
843                 aIter = m_aContainer.lower_bound( tmpUrl );
844                 if( aIter != m_aContainer.end() && aIter->first.match( tmpUrl ) )
845                 {
846                     UrlRecord aRec;
847                     if ( createUrlRecord( aIter, bName, aName, aHandler, aRec ) )
848                       return aRec;
849                 }
850             }
851         }
852         while( shorterUrl( aUrl ) && aUrl.getLength() );
853     }
854 
855     return UrlRecord();
856 }
857 
858 //-------------------------------------------------------------------------
GetDefaultMasterPassword()859 ::rtl::OUString PasswordContainer::GetDefaultMasterPassword()
860 {
861     ::rtl::OUString aResult;
862     for ( sal_Int32 nInd = 0; nInd < RTL_DIGEST_LENGTH_MD5; nInd++ )
863         aResult += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "aa" ) );
864 
865     return aResult;
866 }
867 
868 //-------------------------------------------------------------------------
RequestPasswordFromUser(PasswordRequestMode aRMode,const uno::Reference<task::XInteractionHandler> & xHandler)869 ::rtl::OUString PasswordContainer::RequestPasswordFromUser( PasswordRequestMode aRMode, const uno::Reference< task::XInteractionHandler >& xHandler )
870 {
871     // empty string means that the call was cancelled or just failed
872     ::rtl::OUString aResult;
873 
874     if ( xHandler.is() )
875     {
876         ::rtl::Reference< MasterPasswordRequest_Impl > xRequest = new MasterPasswordRequest_Impl( aRMode );
877 
878         xHandler->handle( xRequest.get() );
879 
880         ::rtl::Reference< ucbhelper::InteractionContinuation > xSelection = xRequest->getSelection();
881 
882         if ( xSelection.is() )
883         {
884             Reference< XInteractionAbort > xAbort( xSelection.get(), UNO_QUERY );
885             if ( !xAbort.is() )
886             {
887                 const ::rtl::Reference< ucbhelper::InteractionSupplyAuthentication > & xSupp
888                             = xRequest->getAuthenticationSupplier();
889 
890                 aResult = xSupp->getPassword();
891             }
892         }
893     }
894 
895     return aResult;
896 }
897 
898 //-------------------------------------------------------------------------
899 
GetMasterPassword(const Reference<XInteractionHandler> & aHandler)900 ::rtl::OUString PasswordContainer::GetMasterPassword( const Reference< XInteractionHandler >& aHandler ) throw(RuntimeException)
901 {
902     PasswordRequestMode aRMode = PasswordRequestMode_PASSWORD_ENTER;
903     if( !m_pStorageFile || !m_pStorageFile->useStorage() )
904         throw NoMasterException( ::rtl::OUString::createFromAscii( "Password storing is not active!" ), Reference< XInterface >(), aRMode );
905 
906     if( !m_aMasterPasswd.getLength() && aHandler.is() )
907     {
908         ::rtl::OUString aEncodedMP;
909         sal_Bool bAskAgain = sal_False;
910         sal_Bool bDefaultPassword = sal_False;
911 
912         if( !m_pStorageFile->getEncodedMP( aEncodedMP ) )
913             aRMode = PasswordRequestMode_PASSWORD_CREATE;
914         else if ( !aEncodedMP.getLength() )
915         {
916             m_aMasterPasswd = GetDefaultMasterPassword();
917             bDefaultPassword = sal_True;
918         }
919 
920         if ( !bDefaultPassword )
921         {
922             do {
923                 bAskAgain = sal_False;
924 
925                 ::rtl::OUString aPass = RequestPasswordFromUser( aRMode, aHandler );
926                 if ( aPass.getLength() )
927                 {
928                     if( aRMode == PasswordRequestMode_PASSWORD_CREATE )
929                     {
930                         m_aMasterPasswd = aPass;
931                         vector< ::rtl::OUString > aMaster( 1, m_aMasterPasswd );
932 
933                         m_pStorageFile->setEncodedMP( EncodePasswords( aMaster, m_aMasterPasswd ) );
934                     }
935                     else
936                     {
937                         vector< ::rtl::OUString > aRM( DecodePasswords( aEncodedMP, aPass ) );
938                         if( !aRM.size() || !aPass.equals( aRM[0] ) )
939                         {
940                             bAskAgain = sal_True;
941                             aRMode = PasswordRequestMode_PASSWORD_REENTER;
942                         }
943                         else
944                             m_aMasterPasswd = aPass;
945                     }
946                 }
947 
948             } while( bAskAgain );
949         }
950     }
951 
952     if ( !m_aMasterPasswd.getLength() )
953         throw NoMasterException( ::rtl::OUString::createFromAscii( "No master password!" ), Reference< XInterface >(), aRMode );
954 
955     return m_aMasterPasswd;
956 }
957 
958 //-------------------------------------------------------------------------
959 
remove(const::rtl::OUString & aURL,const::rtl::OUString & aName)960 void SAL_CALL PasswordContainer::remove( const ::rtl::OUString& aURL, const ::rtl::OUString& aName ) throw(RuntimeException)
961 {
962     ::osl::MutexGuard aGuard( mMutex );
963 
964     ::rtl::OUString aUrl( aURL );
965     if( !m_aContainer.empty() )
966     {
967         PassMap::iterator aIter = m_aContainer.find( aUrl );
968 
969         if( aIter == m_aContainer.end() )
970         {
971             sal_Int32 aInd = aUrl.lastIndexOf( sal_Unicode( '/' ) );
972             if( aInd > 0 && aUrl.getLength()-1 == aInd )
973                 aUrl = aUrl.copy( 0, aUrl.getLength() - 1 );
974             else
975                 aUrl += ::rtl::OUString::createFromAscii( "/" );
976 
977             aIter = m_aContainer.find( aUrl );
978         }
979 
980         if( aIter != m_aContainer.end() )
981         {
982             for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); aNPIter++ )
983                 if( aNPIter->GetUserName().equals( aName ) )
984                 {
985                     if( aNPIter->HasPasswords( PERSISTENT_RECORD ) && m_pStorageFile )
986                         m_pStorageFile->remove( aURL, aName ); // remove record ( aURL, aName )
987 
988                     // the iterator will not be used any more so it can be removed directly
989                     aIter->second.erase( aNPIter );
990 
991                     if( aIter->second.begin() == aIter->second.end() )
992                         m_aContainer.erase( aIter );
993 
994                     return;
995                 }
996         }
997     }
998 }
999 
1000 //-------------------------------------------------------------------------
1001 
removePersistent(const::rtl::OUString & aURL,const::rtl::OUString & aName)1002 void SAL_CALL PasswordContainer::removePersistent( const ::rtl::OUString& aURL, const ::rtl::OUString& aName ) throw(RuntimeException)
1003 {
1004     ::osl::MutexGuard aGuard( mMutex );
1005 
1006     ::rtl::OUString aUrl( aURL );
1007     if( !m_aContainer.empty() )
1008     {
1009         PassMap::iterator aIter = m_aContainer.find( aUrl );
1010 
1011         if( aIter == m_aContainer.end() )
1012         {
1013             sal_Int32 aInd = aUrl.lastIndexOf( sal_Unicode( '/' ) );
1014             if( aInd > 0 && aUrl.getLength()-1 == aInd )
1015                 aUrl = aUrl.copy( 0, aUrl.getLength() - 1 );
1016             else
1017                 aUrl += ::rtl::OUString::createFromAscii( "/" );
1018 
1019             aIter = m_aContainer.find( aUrl );
1020         }
1021 
1022         if( aIter != m_aContainer.end() )
1023         {
1024             for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); aNPIter++ )
1025                 if( aNPIter->GetUserName().equals( aName ) )
1026                 {
1027                     if( aNPIter->HasPasswords( PERSISTENT_RECORD ) )
1028                     {
1029                         // TODO/LATER: should the password be converted to MemoryPassword?
1030                         aNPIter->RemovePasswords( PERSISTENT_RECORD );
1031 
1032                         if ( m_pStorageFile )
1033                             m_pStorageFile->remove( aURL, aName ); // remove record ( aURL, aName )
1034                     }
1035 
1036                     if( !aNPIter->HasPasswords( MEMORY_RECORD ) )
1037                         aIter->second.erase( aNPIter );
1038 
1039                     if( aIter->second.begin() == aIter->second.end() )
1040                         m_aContainer.erase( aIter );
1041 
1042                     return;
1043                 }
1044         }
1045     }
1046 }
1047 //-------------------------------------------------------------------------
1048 
removeAllPersistent()1049 void SAL_CALL PasswordContainer::removeAllPersistent() throw(RuntimeException)
1050 {
1051     ::osl::MutexGuard aGuard( mMutex );
1052 
1053     if( m_pStorageFile )
1054         m_pStorageFile->clear();
1055 
1056     for( PassMap::iterator aIter = m_aContainer.begin(); aIter != m_aContainer.end(); )
1057     {
1058         for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); )
1059         {
1060             if( aNPIter->HasPasswords( PERSISTENT_RECORD ) )
1061             {
1062                 // TODO/LATER: should the password be converted to MemoryPassword?
1063                 aNPIter->RemovePasswords( PERSISTENT_RECORD );
1064 
1065                 if ( m_pStorageFile )
1066                     m_pStorageFile->remove( aIter->first, aNPIter->GetUserName() ); // remove record ( aURL, aName )
1067             }
1068 
1069             if( !aNPIter->HasPasswords( MEMORY_RECORD ) )
1070             {
1071                 list< NamePassRecord >::iterator aIterToDelete( aNPIter );
1072                 aNPIter++;
1073                 aIter->second.erase( aIterToDelete );
1074             }
1075             else
1076                 aNPIter++;
1077         }
1078 
1079         if( aIter->second.begin() == aIter->second.end() )
1080         {
1081             PassMap::iterator aIterToDelete( aIter );
1082             aIter++;
1083             m_aContainer.erase( aIterToDelete );
1084         }
1085         else
1086             aIter++;
1087     }
1088 }
1089 //-------------------------------------------------------------------------
1090 
getAllPersistent(const Reference<XInteractionHandler> & xHandler)1091 Sequence< UrlRecord > SAL_CALL PasswordContainer::getAllPersistent( const Reference< XInteractionHandler >& xHandler ) throw(RuntimeException)
1092 {
1093     Sequence< UrlRecord > aResult;
1094 
1095     ::osl::MutexGuard aGuard( mMutex );
1096     for( PassMap::iterator aIter = m_aContainer.begin(); aIter != m_aContainer.end(); aIter++ )
1097     {
1098         Sequence< UserRecord > aUsers;
1099         for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); aNPIter++ )
1100             if( aNPIter->HasPasswords( PERSISTENT_RECORD ) )
1101             {
1102                 sal_Int32 oldLen = aUsers.getLength();
1103                 aUsers.realloc( oldLen + 1 );
1104                 aUsers[ oldLen ] = UserRecord( aNPIter->GetUserName(), copyVectorToSequence( DecodePasswords( aNPIter->GetPersPasswords(), GetMasterPassword( xHandler ) ) ) );
1105             }
1106 
1107         if( aUsers.getLength() )
1108         {
1109             sal_Int32 oldLen = aResult.getLength();
1110             aResult.realloc( oldLen + 1 );
1111             aResult[ oldLen ] = UrlRecord( aIter->first, aUsers );
1112         }
1113     }
1114 
1115     return aResult;
1116 }
1117 
1118 //-------------------------------------------------------------------------
authorizateWithMasterPassword(const uno::Reference<task::XInteractionHandler> & xHandler)1119 sal_Bool SAL_CALL PasswordContainer::authorizateWithMasterPassword( const uno::Reference< task::XInteractionHandler >& xHandler )
1120     throw (uno::RuntimeException)
1121 {
1122     sal_Bool bResult = sal_False;
1123     ::rtl::OUString aEncodedMP;
1124     uno::Reference< task::XInteractionHandler > xTmpHandler = xHandler;
1125     ::osl::MutexGuard aGuard( mMutex );
1126 
1127     // the method should fail if there is no master password
1128     if( m_pStorageFile && m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) )
1129     {
1130         if ( !aEncodedMP.getLength() )
1131         {
1132             // this is a default master password
1133             // no UI is necessary
1134             bResult = sal_True;
1135         }
1136         else
1137         {
1138             if ( !xTmpHandler.is() )
1139             {
1140                 uno::Reference< lang::XMultiServiceFactory > xFactory( mComponent, uno::UNO_QUERY_THROW );
1141                 xTmpHandler.set( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.InteractionHandler" ) ) ), uno::UNO_QUERY_THROW );
1142             }
1143 
1144             if ( m_aMasterPasswd.getLength() )
1145             {
1146                 // there is a password, it should be just rechecked
1147                 PasswordRequestMode aRMode = PasswordRequestMode_PASSWORD_ENTER;
1148                 ::rtl::OUString aPass;
1149 
1150                 do {
1151                     aPass = RequestPasswordFromUser( aRMode, xTmpHandler );
1152                     bResult = ( aPass.getLength() && aPass.equals( m_aMasterPasswd ) );
1153                     aRMode = PasswordRequestMode_PASSWORD_REENTER; // further questions with error notification
1154                 } while( !bResult && aPass.getLength() );
1155             }
1156             else
1157             {
1158                 try
1159                 {
1160                     // ask for the password, if user provide no correct password an exception will be thrown
1161                     bResult = ( GetMasterPassword( xTmpHandler ).getLength() > 0 );
1162                 }
1163                 catch( uno::Exception& )
1164                 {}
1165             }
1166         }
1167     }
1168 
1169     return bResult;
1170 }
1171 
1172 //-------------------------------------------------------------------------
changeMasterPassword(const uno::Reference<task::XInteractionHandler> & xHandler)1173 sal_Bool SAL_CALL PasswordContainer::changeMasterPassword( const uno::Reference< task::XInteractionHandler >& xHandler )
1174     throw (uno::RuntimeException)
1175 {
1176     sal_Bool bResult = sal_False;
1177     uno::Reference< task::XInteractionHandler > xTmpHandler = xHandler;
1178     ::osl::MutexGuard aGuard( mMutex );
1179 
1180     if ( m_pStorageFile && m_pStorageFile->useStorage() )
1181     {
1182         if ( !xTmpHandler.is() )
1183         {
1184             uno::Reference< lang::XMultiServiceFactory > xFactory( mComponent, uno::UNO_QUERY_THROW );
1185             xTmpHandler.set( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.InteractionHandler" ) ) ), uno::UNO_QUERY_THROW );
1186         }
1187 
1188         sal_Bool bCanChangePassword = sal_True;
1189         // if there is already a stored master password it should be entered by the user before the change happen
1190         ::rtl::OUString aEncodedMP;
1191         if( m_aMasterPasswd.getLength() || m_pStorageFile->getEncodedMP( aEncodedMP ) )
1192             bCanChangePassword = authorizateWithMasterPassword( xTmpHandler );
1193 
1194         if ( bCanChangePassword )
1195         {
1196             // ask for the new password, but do not set it
1197             PasswordRequestMode aRMode = PasswordRequestMode_PASSWORD_CREATE;
1198             ::rtl::OUString aPass = RequestPasswordFromUser( aRMode, xTmpHandler );
1199 
1200             if ( aPass.getLength() )
1201             {
1202                 // get all the persistent entries if it is possible
1203                 Sequence< UrlRecord > aPersistent = getAllPersistent( uno::Reference< task::XInteractionHandler >() );
1204 
1205                 // remove the master password and the entries persistence
1206                 removeMasterPassword();
1207 
1208                 // store the new master password
1209                 m_aMasterPasswd = aPass;
1210                 vector< ::rtl::OUString > aMaster( 1, m_aMasterPasswd );
1211                 m_pStorageFile->setEncodedMP( EncodePasswords( aMaster, m_aMasterPasswd ) );
1212 
1213                 // store all the entries with the new password
1214                 for ( int nURLInd = 0; nURLInd < aPersistent.getLength(); nURLInd++ )
1215                     for ( int nNameInd = 0; nNameInd< aPersistent[nURLInd].UserList.getLength(); nNameInd++ )
1216                         addPersistent( aPersistent[nURLInd].Url,
1217                                        aPersistent[nURLInd].UserList[nNameInd].UserName,
1218                                        aPersistent[nURLInd].UserList[nNameInd].Passwords,
1219                                        uno::Reference< task::XInteractionHandler >() );
1220 
1221                 bResult = sal_True;
1222             }
1223         }
1224     }
1225 
1226     return bResult;
1227 }
1228 
1229 //-------------------------------------------------------------------------
removeMasterPassword()1230 void SAL_CALL PasswordContainer::removeMasterPassword()
1231     throw (uno::RuntimeException)
1232 {
1233     // remove all the stored passwords and the master password
1234     removeAllPersistent();
1235 
1236     ::osl::MutexGuard aGuard( mMutex );
1237     if ( m_pStorageFile )
1238     {
1239         m_aMasterPasswd = ::rtl::OUString();
1240         m_pStorageFile->setEncodedMP( ::rtl::OUString() ); // let the master password be removed from configuration
1241     }
1242 }
1243 
1244 //-------------------------------------------------------------------------
hasMasterPassword()1245 ::sal_Bool SAL_CALL PasswordContainer::hasMasterPassword(  )
1246     throw (::com::sun::star::uno::RuntimeException)
1247 {
1248     ::osl::MutexGuard aGuard( mMutex );
1249 
1250     if ( !m_pStorageFile )
1251         throw uno::RuntimeException();
1252 
1253     ::rtl::OUString aEncodedMP;
1254     return ( m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) );
1255 }
1256 
1257 //-------------------------------------------------------------------------
allowPersistentStoring(::sal_Bool bAllow)1258 ::sal_Bool SAL_CALL PasswordContainer::allowPersistentStoring( ::sal_Bool bAllow )
1259     throw (::com::sun::star::uno::RuntimeException)
1260 {
1261     ::osl::MutexGuard aGuard( mMutex );
1262 
1263     if ( !m_pStorageFile )
1264         throw uno::RuntimeException();
1265 
1266     if ( !bAllow )
1267         removeMasterPassword();
1268 
1269     if ( m_pStorageFile->useStorage() == bAllow )
1270         return bAllow;
1271 
1272     m_pStorageFile->setUseStorage( bAllow );
1273     return !bAllow;
1274 }
1275 
1276 //-------------------------------------------------------------------------
isPersistentStoringAllowed()1277 ::sal_Bool SAL_CALL PasswordContainer::isPersistentStoringAllowed()
1278     throw (::com::sun::star::uno::RuntimeException)
1279 {
1280     ::osl::MutexGuard aGuard( mMutex );
1281 
1282     if ( !m_pStorageFile )
1283         throw uno::RuntimeException();
1284 
1285     return m_pStorageFile->useStorage();
1286 }
1287 
1288 //-------------------------------------------------------------------------
useDefaultMasterPassword(const uno::Reference<task::XInteractionHandler> & xHandler)1289 ::sal_Bool SAL_CALL PasswordContainer::useDefaultMasterPassword( const uno::Reference< task::XInteractionHandler >& xHandler )
1290     throw ( uno::RuntimeException )
1291 {
1292     sal_Bool bResult = sal_False;
1293     uno::Reference< task::XInteractionHandler > xTmpHandler = xHandler;
1294     ::osl::MutexGuard aGuard( mMutex );
1295 
1296     if ( m_pStorageFile && m_pStorageFile->useStorage() )
1297     {
1298         if ( !xTmpHandler.is() )
1299         {
1300             uno::Reference< lang::XMultiServiceFactory > xFactory( mComponent, uno::UNO_QUERY_THROW );
1301             xTmpHandler.set( xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.task.InteractionHandler" ) ) ), uno::UNO_QUERY_THROW );
1302         }
1303 
1304         sal_Bool bCanChangePassword = sal_True;
1305         // if there is already a stored nondefault master password it should be entered by the user before the change happen
1306         ::rtl::OUString aEncodedMP;
1307         if( m_pStorageFile->getEncodedMP( aEncodedMP ) && aEncodedMP.getLength() )
1308             bCanChangePassword = authorizateWithMasterPassword( xTmpHandler );
1309 
1310         if ( bCanChangePassword )
1311         {
1312             // generate the default password
1313             ::rtl::OUString aPass = GetDefaultMasterPassword();
1314             if ( aPass.getLength() )
1315             {
1316                 // get all the persistent entries if it is possible
1317                 Sequence< UrlRecord > aPersistent = getAllPersistent( uno::Reference< task::XInteractionHandler >() );
1318 
1319                 // remove the master password and the entries persistence
1320                 removeMasterPassword();
1321 
1322                 // store the empty string to flag the default master password
1323                 m_aMasterPasswd = aPass;
1324                 m_pStorageFile->setEncodedMP( ::rtl::OUString(), sal_True );
1325 
1326                 // store all the entries with the new password
1327                 for ( int nURLInd = 0; nURLInd < aPersistent.getLength(); nURLInd++ )
1328                     for ( int nNameInd = 0; nNameInd< aPersistent[nURLInd].UserList.getLength(); nNameInd++ )
1329                         addPersistent( aPersistent[nURLInd].Url,
1330                                        aPersistent[nURLInd].UserList[nNameInd].UserName,
1331                                        aPersistent[nURLInd].UserList[nNameInd].Passwords,
1332                                        uno::Reference< task::XInteractionHandler >() );
1333 
1334                 bResult = sal_True;
1335             }
1336         }
1337     }
1338 
1339     return bResult;
1340 
1341 }
1342 
1343 //-------------------------------------------------------------------------
isDefaultMasterPasswordUsed()1344 ::sal_Bool SAL_CALL PasswordContainer::isDefaultMasterPasswordUsed()
1345     throw ( uno::RuntimeException )
1346 {
1347     ::osl::MutexGuard aGuard( mMutex );
1348 
1349     if ( !m_pStorageFile )
1350         throw uno::RuntimeException();
1351 
1352     ::rtl::OUString aEncodedMP;
1353     return ( m_pStorageFile->useStorage() && m_pStorageFile->getEncodedMP( aEncodedMP ) && !aEncodedMP.getLength() );
1354 }
1355 
1356 
1357 //-------------------------------------------------------------------------
addUrl(const::rtl::OUString & Url,::sal_Bool MakePersistent)1358 void SAL_CALL PasswordContainer::addUrl( const ::rtl::OUString& Url, ::sal_Bool MakePersistent )
1359     throw (uno::RuntimeException)
1360 {
1361     mUrlContainer.add( Url, MakePersistent );
1362 }
1363 
1364 //-------------------------------------------------------------------------
findUrl(const::rtl::OUString & Url)1365 ::rtl::OUString SAL_CALL PasswordContainer::findUrl( const ::rtl::OUString& Url )
1366     throw (uno::RuntimeException)
1367 {
1368     return mUrlContainer.find( Url );
1369 }
1370 
1371 //-------------------------------------------------------------------------
removeUrl(const::rtl::OUString & Url)1372 void SAL_CALL PasswordContainer::removeUrl( const ::rtl::OUString& Url )
1373     throw (uno::RuntimeException)
1374 {
1375     mUrlContainer.remove( Url );
1376 }
1377 
1378 //-------------------------------------------------------------------------
getUrls(::sal_Bool OnlyPersistent)1379 uno::Sequence< ::rtl::OUString > SAL_CALL PasswordContainer::getUrls( ::sal_Bool OnlyPersistent )
1380     throw (uno::RuntimeException)
1381 {
1382     return mUrlContainer.list( OnlyPersistent );
1383 }
1384 
1385 //-------------------------------------------------------------------------
1386 
Notify()1387 void PasswordContainer::Notify()
1388 {
1389     ::osl::MutexGuard aGuard( mMutex );
1390 
1391     PassMap::iterator aIter;
1392 
1393     // remove the cached persistent values in the memory
1394     for( aIter = m_aContainer.begin(); aIter != m_aContainer.end(); aIter++ )
1395     {
1396         for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); )
1397         {
1398             if( aNPIter->HasPasswords( PERSISTENT_RECORD ) )
1399             {
1400                 aNPIter->RemovePasswords( PERSISTENT_RECORD );
1401 
1402                 if ( m_pStorageFile )
1403                     m_pStorageFile->remove( aIter->first, aNPIter->GetUserName() ); // remove record ( aURL, aName )
1404             }
1405 
1406             if( !aNPIter->HasPasswords( MEMORY_RECORD ) )
1407             {
1408                 list< NamePassRecord >::iterator aIterToDelete( aNPIter );
1409                 aNPIter++;
1410                 aIter->second.erase( aIterToDelete );
1411             }
1412             else
1413                 aNPIter++;
1414         }
1415     }
1416 
1417     PassMap addon;
1418     if( m_pStorageFile )
1419         addon = m_pStorageFile->getInfo();
1420 
1421     for( aIter = addon.begin(); aIter != addon.end(); aIter++ )
1422     {
1423         PassMap::iterator aSearchIter = m_aContainer.find( aIter->first );
1424         if( aSearchIter != m_aContainer.end() )
1425             for( list< NamePassRecord >::iterator aNPIter = aIter->second.begin(); aNPIter != aIter->second.end(); aNPIter++ )
1426                 UpdateVector( aSearchIter->first, aSearchIter->second, *aNPIter, sal_False );
1427         else
1428             m_aContainer.insert( PairUrlRecord( aIter->first, aIter->second ) );
1429     }
1430 }
1431 
1432 //-------------------------------------------------------------------------
1433 
getImplementationName()1434 ::rtl::OUString SAL_CALL PasswordContainer::getImplementationName(  ) throw(uno::RuntimeException)
1435 {
1436     return impl_getStaticImplementationName();
1437 }
1438 
1439 //-------------------------------------------------------------------------
1440 
supportsService(const::rtl::OUString & ServiceName)1441 sal_Bool SAL_CALL PasswordContainer::supportsService( const ::rtl::OUString& ServiceName ) throw(uno::RuntimeException)
1442 {
1443     if ( ServiceName.compareToAscii("com.sun.star.task.PasswordContainer") == 0 )
1444         return sal_True;
1445     else
1446         return sal_False;
1447 }
1448 
1449 //-------------------------------------------------------------------------
1450 
getSupportedServiceNames()1451 Sequence< ::rtl::OUString > SAL_CALL PasswordContainer::getSupportedServiceNames(  ) throw(uno::RuntimeException)
1452 {
1453     return impl_getStaticSupportedServiceNames();
1454 }
1455 
1456 //-------------------------------------------------------------------------
1457 
impl_getStaticSupportedServiceNames()1458 Sequence< ::rtl::OUString > SAL_CALL PasswordContainer::impl_getStaticSupportedServiceNames(  ) throw(uno::RuntimeException)
1459 {
1460     Sequence< ::rtl::OUString > aRet(1);
1461     *aRet.getArray() = ::rtl::OUString::createFromAscii("com.sun.star.task.PasswordContainer");
1462     return aRet;
1463 }
1464 
1465 //-------------------------------------------------------------------------
1466 
impl_getStaticImplementationName()1467 ::rtl::OUString SAL_CALL PasswordContainer::impl_getStaticImplementationName() throw(uno::RuntimeException)
1468 {
1469     return ::rtl::OUString::createFromAscii("stardiv.svl.PasswordContainer");
1470 }
1471 
1472 //-------------------------------------------------------------------------
1473 
impl_createInstance(const Reference<XMultiServiceFactory> & xServiceManager)1474 Reference< XInterface > SAL_CALL PasswordContainer::impl_createInstance( const Reference< XMultiServiceFactory >& xServiceManager ) throw( RuntimeException )
1475 {
1476     return Reference< XInterface >( *new PasswordContainer( xServiceManager ) );
1477 }
1478 
1479 //-------------------------------------------------------------------------
1480 
impl_createFactory(const Reference<XMultiServiceFactory> & ServiceManager)1481 Reference< XSingleServiceFactory > SAL_CALL PasswordContainer::impl_createFactory( const Reference< XMultiServiceFactory >& ServiceManager ) throw(RuntimeException)
1482 {
1483     Reference< XSingleServiceFactory > xReturn( ::cppu::createOneInstanceFactory( ServiceManager,
1484                                                         PasswordContainer::impl_getStaticImplementationName(),
1485                                                         PasswordContainer::impl_createInstance,
1486                                                         PasswordContainer::impl_getStaticSupportedServiceNames()));
1487     return xReturn ;
1488 
1489 }
1490 
1491 //-------------------------------------------------------------------------
1492 //-------------------------------------------------------------------------
1493 
MasterPasswordRequest_Impl(PasswordRequestMode Mode)1494 MasterPasswordRequest_Impl::MasterPasswordRequest_Impl( PasswordRequestMode Mode )
1495 {
1496     MasterPasswordRequest aRequest;
1497 
1498     aRequest.Classification = InteractionClassification_ERROR;
1499     aRequest.Mode = Mode;
1500 
1501     setRequest( makeAny( aRequest ) );
1502 
1503     // Fill continuations...
1504     Sequence< RememberAuthentication > aRememberModes( 1 );
1505     aRememberModes[ 0 ] = RememberAuthentication_NO;
1506 
1507     m_xAuthSupplier
1508         = new ::ucbhelper::InteractionSupplyAuthentication(
1509                 this,
1510                 sal_False, // bCanSetRealm
1511                 sal_False,  // bCanSetUserName
1512                 sal_True,  // bCanSetPassword
1513                 sal_False, // bCanSetAccount
1514                 aRememberModes, // rRememberPasswordModes
1515                 RememberAuthentication_NO, // eDefaultRememberPasswordMode
1516                 aRememberModes, // rRememberAccountModes
1517                 RememberAuthentication_NO, // eDefaultRememberAccountMode
1518                 sal_False, // bCanUseSystemCredentials
1519                 sal_False  // bDefaultUseSystemCredentials
1520             );
1521 
1522     Sequence<
1523         Reference< XInteractionContinuation > > aContinuations( 3 );
1524     aContinuations[ 0 ] = new ::ucbhelper::InteractionAbort( this );
1525     aContinuations[ 1 ] = new ::ucbhelper::InteractionRetry( this );
1526     aContinuations[ 2 ] = m_xAuthSupplier.get();
1527 
1528     setContinuations( aContinuations );
1529 }
1530 
1531 //-------------------------------------------------------------------------
1532 //-------------------------------------------------------------------------
1533 
1534 extern "C"
1535 {
component_getImplementationEnvironment(const sal_Char ** ppEnvTypeName,uno_Environment **)1536 SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment (
1537     const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */)
1538 {
1539     *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
1540 }
1541 
component_getFactory(const sal_Char * pImplementationName,void * pServiceManager,void *)1542 SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory (
1543     const sal_Char * pImplementationName, void * pServiceManager, void * /* pRegistryKey */)
1544 {
1545     void * pResult = 0;
1546     if (pServiceManager)
1547     {
1548         Reference< XSingleServiceFactory > xFactory;
1549         if (PasswordContainer::impl_getStaticImplementationName().compareToAscii (pImplementationName) == 0)
1550         {
1551             xFactory = PasswordContainer::impl_createFactory (
1552                 reinterpret_cast< XMultiServiceFactory* >(pServiceManager));
1553         }
1554         if (xFactory.is())
1555         {
1556             xFactory->acquire();
1557             pResult = xFactory.get();
1558         }
1559     }
1560     return pResult;
1561 }
1562 
1563 } // extern "C"
1564