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 #ifndef INCLUDED_COMPHELPER_PASSWORDCONTAINER_HXX
24 #define INCLUDED_COMPHELPER_PASSWORDCONTAINER_HXX
25 
26 #include <list>
27 #include <vector>
28 #include <map>
29 #include <com/sun/star/task/XPasswordContainer.hpp>
30 #include <com/sun/star/task/XUrlContainer.hpp>
31 #include <com/sun/star/task/PasswordRequestMode.hpp>
32 #include <com/sun/star/lang/XServiceInfo.hpp>
33 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
34 #include <com/sun/star/lang/XEventListener.hpp>
35 #include <com/sun/star/lang/XComponent.hpp>
36 #include <com/sun/star/task/XMasterPasswordHandling2.hpp>
37 #include <cppuhelper/implbase5.hxx>
38 #include <cppuhelper/typeprovider.hxx>
39 #include <cppuhelper/queryinterface.hxx>
40 #include <cppuhelper/factory.hxx>
41 
42 #include <tools/stream.hxx>
43 #include <unotools/configitem.hxx>
44 #include <ucbhelper/interactionrequest.hxx>
45 
46 #include <rtl/ref.hxx>
47 #include <osl/mutex.hxx>
48 
49 #include "syscreds.hxx"
50 
51 #define MEMORY_RECORD         0
52 #define PERSISTENT_RECORD     1
53 
54 //----------------------------------------------------------------------------------
55 
56 class NamePassRecord
57 {
58     ::rtl::OUString                                     m_aName;
59 
60     // there are two lists of passwords, memory passwords and persistent passwords
61     sal_Bool                                              m_bHasMemPass;
62     ::std::vector< ::rtl::OUString >                      m_aMemPass;
63 
64     // persistent passwords are encrypted in one string
65     sal_Bool                                              m_bHasPersPass;
66     ::rtl::OUString                                       m_aPersPass;
67 
InitArrays(sal_Bool bHasMemoryList,const::std::vector<::rtl::OUString> & aMemoryList,sal_Bool bHasPersistentList,const::rtl::OUString & aPersistentList)68     void InitArrays( sal_Bool bHasMemoryList, const ::std::vector< ::rtl::OUString >& aMemoryList,
69                      sal_Bool bHasPersistentList, const ::rtl::OUString& aPersistentList )
70     {
71         m_bHasMemPass = bHasMemoryList;
72         if ( bHasMemoryList )
73             m_aMemPass = aMemoryList;
74 
75         m_bHasPersPass = bHasPersistentList;
76         if ( bHasPersistentList )
77             m_aPersPass = aPersistentList;
78     }
79 
80 public:
81 
NamePassRecord(const::rtl::OUString & aName)82     NamePassRecord( const ::rtl::OUString& aName )
83         : m_aName( aName )
84         , m_bHasMemPass( sal_False )
85         , m_bHasPersPass( sal_False )
86     {
87     }
88 
NamePassRecord(const::rtl::OUString & aName,const::std::vector<::rtl::OUString> & aMemoryList)89     NamePassRecord( const ::rtl::OUString& aName, const ::std::vector< ::rtl::OUString >& aMemoryList )
90         : m_aName( aName )
91         , m_bHasMemPass( sal_True )
92         , m_aMemPass( aMemoryList )
93         , m_bHasPersPass( sal_False )
94     {
95     }
96 
NamePassRecord(const::rtl::OUString & aName,const::rtl::OUString & aPersistentList)97     NamePassRecord( const ::rtl::OUString& aName, const ::rtl::OUString& aPersistentList )
98         : m_aName( aName )
99         , m_bHasMemPass( sal_False )
100         , m_bHasPersPass( sal_True )
101         , m_aPersPass( aPersistentList )
102     {
103     }
104 
NamePassRecord(const::rtl::OUString & aName,sal_Bool bHasMemoryList,const::std::vector<::rtl::OUString> & aMemoryList,sal_Bool bHasPersistentList,const::rtl::OUString aPersistentList)105     NamePassRecord( const ::rtl::OUString& aName,
106                     sal_Bool bHasMemoryList, const ::std::vector< ::rtl::OUString >& aMemoryList,
107                     sal_Bool bHasPersistentList, const ::rtl::OUString aPersistentList )
108         : m_aName( aName )
109         , m_bHasMemPass( bHasMemoryList )
110         , m_bHasPersPass( bHasPersistentList )
111     {
112         InitArrays( bHasMemoryList, aMemoryList, bHasPersistentList, aPersistentList );
113     }
114 
NamePassRecord(const NamePassRecord & aRecord)115     NamePassRecord( const NamePassRecord& aRecord )
116         : m_aName( aRecord.m_aName )
117         , m_bHasMemPass( sal_False )
118         , m_bHasPersPass( sal_False )
119     {
120         InitArrays( aRecord.m_bHasMemPass, aRecord.m_aMemPass, aRecord.m_bHasPersPass, aRecord.m_aPersPass );
121     }
122 
operator =(const NamePassRecord & aRecord)123     NamePassRecord& operator=( const NamePassRecord& aRecord )
124     {
125         m_aName = aRecord.m_aName;
126 
127         m_aMemPass.clear();
128         m_aPersPass = ::rtl::OUString();
129         InitArrays( aRecord.m_bHasMemPass, aRecord.m_aMemPass, aRecord.m_bHasPersPass, aRecord.m_aPersPass );
130 
131         return *this;
132     }
133 
GetUserName() const134     ::rtl::OUString GetUserName() const
135     {
136         return m_aName;
137     }
138 
HasPasswords(sal_Int8 nStatus) const139     sal_Bool HasPasswords( sal_Int8 nStatus ) const
140     {
141         if ( nStatus == MEMORY_RECORD )
142             return m_bHasMemPass;
143         if ( nStatus == PERSISTENT_RECORD )
144             return m_bHasPersPass;
145 
146         return sal_False;
147     }
148 
GetMemPasswords() const149     ::std::vector< ::rtl::OUString > GetMemPasswords() const
150     {
151         if ( m_bHasMemPass )
152             return m_aMemPass;
153 
154         return ::std::vector< ::rtl::OUString >();
155     }
156 
GetPersPasswords() const157     ::rtl::OUString GetPersPasswords() const
158     {
159         if ( m_bHasPersPass )
160             return m_aPersPass;
161 
162         return ::rtl::OUString();
163     }
164 
SetMemPasswords(const::std::vector<::rtl::OUString> & aMemList)165     void SetMemPasswords( const ::std::vector< ::rtl::OUString >& aMemList )
166     {
167         m_aMemPass = aMemList;
168         m_bHasMemPass = sal_True;
169     }
170 
SetPersPasswords(const::rtl::OUString & aPersList)171     void SetPersPasswords( const ::rtl::OUString& aPersList )
172     {
173         m_aPersPass = aPersList;
174         m_bHasPersPass = sal_True;
175     }
176 
RemovePasswords(sal_Int8 nStatus)177     void RemovePasswords( sal_Int8 nStatus )
178     {
179         if ( nStatus == MEMORY_RECORD )
180         {
181             m_bHasMemPass = sal_False;
182             m_aMemPass.clear();
183         }
184         else if ( nStatus == PERSISTENT_RECORD )
185         {
186             m_bHasPersPass = sal_False;
187             m_aPersPass = ::rtl::OUString();
188         }
189     }
190 
191 };
192 
193 //----------------------------------------------------------------------------------
194 
195 typedef ::std::pair< const ::rtl::OUString, ::std::list< NamePassRecord > > PairUrlRecord;
196 typedef ::std::map< ::rtl::OUString, ::std::list< NamePassRecord > > PassMap;
197 
198 //----------------------------------------------------------------------------------
199 
200 class PasswordContainer;
201 
202 class StorageItem : public ::utl::ConfigItem {
203     PasswordContainer*  mainCont;
204     sal_Bool            hasEncoded;
205     ::rtl::OUString        mEncoded;
206 public:
StorageItem(PasswordContainer * point,const::rtl::OUString & path)207     StorageItem( PasswordContainer* point, const ::rtl::OUString& path ) :
208         ConfigItem( path, CONFIG_MODE_IMMEDIATE_UPDATE ),
209         mainCont( point ),
210         hasEncoded( sal_False )
211     {
212         ::com::sun::star::uno::Sequence< ::rtl::OUString > aNode( 1 );
213         *aNode.getArray()  = path;
214         *aNode.getArray() += ::rtl::OUString::createFromAscii( "/Store" );
215         EnableNotification( aNode );
216     }
217 
218     PassMap getInfo();
219     void update( const ::rtl::OUString& url, const NamePassRecord& rec );
220     void remove( const ::rtl::OUString& url, const ::rtl::OUString& rec );
221     void clear();
222 
223     sal_Bool getEncodedMP( ::rtl::OUString& aResult );
224     void setEncodedMP( const ::rtl::OUString& aResult, sal_Bool bAcceptEnmpty = sal_False );
225     void setUseStorage( sal_Bool bUse );
226     sal_Bool useStorage();
227 
228     virtual void            Notify( const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aPropertyNames );
229     virtual void            Commit();
230 };
231 
232 //----------------------------------------------------------------------------------
233 
234 enum PasswordState {
235     no_password,
236     entered,
237     cancelled
238 };
239 
240 class PasswordContainer : public ::cppu::WeakImplHelper5<
241         ::com::sun::star::task::XPasswordContainer,
242         ::com::sun::star::task::XMasterPasswordHandling2,
243         ::com::sun::star::task::XUrlContainer,
244         ::com::sun::star::lang::XServiceInfo,
245         ::com::sun::star::lang::XEventListener >
246 {
247 private:
248     PassMap      m_aContainer;
249     StorageItem* m_pStorageFile;
250     ::osl::Mutex mMutex;
251     ::rtl::OUString m_aMasterPasswd; // master password is set when the string is not empty
252     /// True if we detected the older password encoding (pre-4.1.13)
253     bool mOldPasswordEncoding;
254     ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > mComponent;
255     SysCredentialsConfig mUrlContainer;
256 
257     ::com::sun::star::uno::Sequence< ::com::sun::star::task::UserRecord > CopyToUserRecordSequence(
258                                         const ::std::list< NamePassRecord >& original,
259                                         const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& Handler )
260                                                         throw(::com::sun::star::uno::RuntimeException);
261 
262     ::com::sun::star::task::UserRecord CopyToUserRecord(
263                                         const NamePassRecord& aRecord,
264                                         sal_Bool& io_bTryToDecode,
265                                         const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& aHandler );
266 
267     ::com::sun::star::uno::Sequence< ::com::sun::star::task::UserRecord > FindUsr(
268                                         const ::std::list< NamePassRecord >& userlist,
269                                         const ::rtl::OUString& name,
270                                         const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& Handler )
271                                                         throw(::com::sun::star::uno::RuntimeException);
272 bool createUrlRecord(
273     const PairUrlRecord & rPair,
274     bool bName,
275     const ::rtl::OUString & aName,
276     const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& aHandler,
277     ::com::sun::star::task::UrlRecord & rRec  )
278         throw( ::com::sun::star::uno::RuntimeException );
279 
280 ::com::sun::star::task::UrlRecord find(
281     const ::rtl::OUString& aURL,
282     const ::rtl::OUString& aName,
283     bool bName, // only needed to support empty user names
284     const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& aHandler  ) throw(::com::sun::star::uno::RuntimeException);
285 
286     ::rtl::OUString GetDefaultMasterPassword();
287 
288     ::rtl::OUString RequestPasswordFromUser(
289                     ::com::sun::star::task::PasswordRequestMode aRMode,
290                     const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& xHandler );
291 
292     ::rtl::OUString GetMasterPassword( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& Handler )
293                                                         throw(::com::sun::star::uno::RuntimeException);
294 
295     void UpdateVector( const ::rtl::OUString& url, ::std::list< NamePassRecord >& toUpdate, NamePassRecord& rec, sal_Bool writeFile )
296                                                         throw(::com::sun::star::uno::RuntimeException);
297 
298     void PrivateAdd( const ::rtl::OUString& aUrl,
299                               const ::rtl::OUString& aUserName,
300                               const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aPasswords,
301                               char  aMode,
302                               const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& Handler )
303                                                         throw(::com::sun::star::uno::RuntimeException);
304 
305     /** Decode passwords on a line with the given master password.
306      *
307      * @param aName name for the passwords. It can be a user name, for example.
308      * @param aLine line with passwords to decode.
309      * @param aMasterPassword master password to use.
310      *
311      * The encoding is selected by mOldPasswordEncoding.
312      *
313      * @return the decoded passwords.
314      */
315     ::std::vector< ::rtl::OUString > DecodePasswords( const ::rtl::OUString& aName, const ::rtl::OUString& aLine, const ::rtl::OUString& aMasterPassword )
316                                                         throw(::com::sun::star::uno::RuntimeException);
317 
318     /** Encode passwords on a line with the given master password.
319      *
320      * @param aName name for the passwords. It can be a user name, for example.
321      * @param lines lines with passwords to decode.
322      * @param aMasterPassword master password to use.
323      *
324      * The encoding is selected by mOldPasswordEncoding.
325      *
326      * @return the decoded passwords.
327      */
328     ::rtl::OUString EncodePasswords( const ::rtl::OUString& aName, ::std::vector< ::rtl::OUString > lines, const ::rtl::OUString& aMasterPassword )
329                                                         throw(::com::sun::star::uno::RuntimeException);
330 
331     /** Actually change the master password, re-encoding all stored passwords.
332      *
333      * @param apass new password to set.
334      *
335      * Updates m_aMasterPasswd.
336      */
337     void doChangeMasterPassword(const ::rtl::OUString& aPass);
338 public:
339     PasswordContainer( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& );
340     ~PasswordContainer();
341 
342     virtual void SAL_CALL add( const ::rtl::OUString& aUrl,
343                                const ::rtl::OUString& aUserName,
344                                const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aPasswords,
345                                const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& Handler  )
346                                                         throw(::com::sun::star::uno::RuntimeException);
347 
348     virtual void SAL_CALL addPersistent( const ::rtl::OUString& aUrl,
349                                             const ::rtl::OUString& aUserName,
350                                          const ::com::sun::star::uno::Sequence< ::rtl::OUString >& aPasswords,
351                                           const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& Handler  )
352                                                         throw(::com::sun::star::uno::RuntimeException);
353 
354     virtual ::com::sun::star::task::UrlRecord SAL_CALL
355                             find( const ::rtl::OUString& aUrl,
356                                   const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& Handler  )
357                                                         throw(::com::sun::star::uno::RuntimeException);
358 
359     virtual ::com::sun::star::task::UrlRecord SAL_CALL
360                             findForName( const ::rtl::OUString& aUrl,
361                                          const ::rtl::OUString& aUserName,
362                                             const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& Handler  )
363                                                         throw(::com::sun::star::uno::RuntimeException);
364 
365     virtual void SAL_CALL remove( const ::rtl::OUString& aUrl,
366                                   const ::rtl::OUString& aUserName )
367                                                         throw(::com::sun::star::uno::RuntimeException);
368 
369     virtual void SAL_CALL removePersistent( const ::rtl::OUString& aUrl,
370                                             const ::rtl::OUString& aUserName )
371                                                         throw(::com::sun::star::uno::RuntimeException);
372 
373     virtual void SAL_CALL removeAllPersistent() throw(::com::sun::star::uno::RuntimeException);
374 
375     virtual ::com::sun::star::uno::Sequence< ::com::sun::star::task::UrlRecord > SAL_CALL
376                             getAllPersistent( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& Handler ) throw(::com::sun::star::uno::RuntimeException);
377 
378 
379     // provide factory
380     static ::rtl::OUString SAL_CALL        impl_getStaticImplementationName( ) throw(::com::sun::star::uno::RuntimeException);
381     static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL
382                     impl_getStaticSupportedServiceNames(  ) throw(::com::sun::star::uno::RuntimeException);
383     static ::com::sun::star::uno::Reference< ::com::sun::star::lang::XSingleServiceFactory > SAL_CALL
384                     impl_createFactory( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& ServiceManager ) throw(::com::sun::star::uno::RuntimeException);
385     static ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL
386                     impl_createInstance( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& xServiceManager ) throw( ::com::sun::star::uno::RuntimeException );
387 
388     // XServiceInfo
389     virtual ::rtl::OUString    SAL_CALL    getImplementationName(  ) throw(::com::sun::star::uno::RuntimeException);
390     virtual sal_Bool SAL_CALL            supportsService( const ::rtl::OUString& ServiceName ) throw(::com::sun::star::uno::RuntimeException);
391 
392     virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL
393                                         getSupportedServiceNames(  ) throw(::com::sun::star::uno::RuntimeException);
394 
395     // XEventListener
396     virtual void SAL_CALL        disposing( const ::com::sun::star::lang::EventObject& Source )
397                                     throw(::com::sun::star::uno::RuntimeException);
398 
399     // XMasterPasswordHandling
400     virtual ::sal_Bool SAL_CALL authorizateWithMasterPassword( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& xHandler )
401         throw (::com::sun::star::uno::RuntimeException);
402     virtual ::sal_Bool SAL_CALL changeMasterPassword( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& xHandler ) throw (::com::sun::star::uno::RuntimeException);
403     virtual void SAL_CALL removeMasterPassword() throw (::com::sun::star::uno::RuntimeException);
404     virtual ::sal_Bool SAL_CALL hasMasterPassword(  ) throw (::com::sun::star::uno::RuntimeException);
405     virtual ::sal_Bool SAL_CALL allowPersistentStoring( ::sal_Bool bAllow ) throw (::com::sun::star::uno::RuntimeException);
406     virtual ::sal_Bool SAL_CALL isPersistentStoringAllowed(  ) throw (::com::sun::star::uno::RuntimeException);
407 
408     // XMasterPasswordHandling2
409     virtual ::sal_Bool SAL_CALL useDefaultMasterPassword( const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& xHandler ) throw (::com::sun::star::uno::RuntimeException);
410     virtual ::sal_Bool SAL_CALL isDefaultMasterPasswordUsed(  ) throw (::com::sun::star::uno::RuntimeException);
411 
412     // XUrlContainer
413     virtual void SAL_CALL addUrl( const ::rtl::OUString& Url, ::sal_Bool MakePersistent ) throw (::com::sun::star::uno::RuntimeException);
414     virtual ::rtl::OUString SAL_CALL findUrl( const ::rtl::OUString& Url ) throw (::com::sun::star::uno::RuntimeException);
415     virtual void SAL_CALL removeUrl( const ::rtl::OUString& Url ) throw (::com::sun::star::uno::RuntimeException);
416     virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getUrls( ::sal_Bool OnlyPersistent ) throw (::com::sun::star::uno::RuntimeException);
417 
418     void            Notify();
419 };
420 
421 //----------------------------------------------------------------------------------
422 
423 class MasterPasswordRequest_Impl : public ucbhelper::InteractionRequest
424 {
425     ::rtl::Reference< ucbhelper::InteractionSupplyAuthentication > m_xAuthSupplier;
426 
427 public:
428     MasterPasswordRequest_Impl( ::com::sun::star::task::PasswordRequestMode Mode );
429 
430     const ::rtl::Reference< ucbhelper::InteractionSupplyAuthentication > &
getAuthenticationSupplier() const431     getAuthenticationSupplier() const { return m_xAuthSupplier; }
432 
433 };
434 
435 //----------------------------------------------------------------------------------
436 
437 class RW_SvMemoryStream : public SvMemoryStream {
438 public:
RW_SvMemoryStream(void * Buf,sal_uLong Size,StreamMode eMode)439     RW_SvMemoryStream( void* Buf, sal_uLong Size, StreamMode eMode ):
440             SvMemoryStream( Buf, Size, eMode){}
441 
RW_SvMemoryStream(sal_uLong InitSize=512,sal_uLong Resize=64)442     RW_SvMemoryStream( sal_uLong InitSize=512, sal_uLong Resize=64 ):
443             SvMemoryStream( InitSize, Resize ){}
444 
getActualSize()445     sal_uLong getActualSize(){ return nEndOfData; }
446 };
447 
448 
449 
450 #endif // #ifndef INCLUDED_COMPHELPER_PASSWORDCONTAINER_HXX
451 
452