1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <comphelper/processfactory.hxx>
21 #include <cppuhelper/factory.hxx>
22 #include <cppuhelper/supportsservice.hxx>
23 #include <osl/diagnose.h>
25 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
26 #include <com/sun/star/task/NoMasterException.hpp>
27 #include <com/sun/star/task/PasswordContainer.hpp>
28 #include <com/sun/star/task/XInteractionHandler2.hpp>
29 #include <com/sun/star/ucb/AuthenticationRequest.hpp>
30 #include <com/sun/star/ucb/URLAuthenticationRequest.hpp>
31 #include <com/sun/star/ucb/XInteractionSupplyAuthentication.hpp>
32 #include <com/sun/star/ucb/XInteractionSupplyAuthentication2.hpp>
33 #include <officecfg/Office/Common.hxx>
35 #include "passwordcontainer.hxx"
37 using namespace com::sun::star
;
42 bool fillContinuation(
43 bool bUseSystemCredentials
,
44 const ucb::AuthenticationRequest
& rRequest
,
45 const task::UrlRecord
& aRec
,
46 const uno::Reference
< ucb::XInteractionSupplyAuthentication
> &
47 xSupplyAuthentication
,
48 const uno::Reference
< ucb::XInteractionSupplyAuthentication2
> &
49 xSupplyAuthentication2
,
50 bool bCanUseSystemCredentials
,
51 bool bCheckForEqualPasswords
)
53 if ( bUseSystemCredentials
)
55 // "use system creds" record found.
56 // Wants client that we use it?
57 if ( xSupplyAuthentication2
.is() && bCanUseSystemCredentials
)
59 xSupplyAuthentication2
->setUseSystemCredentials( true );
64 else if (aRec
.UserList
.getLength() != 0)
66 if (aRec
.UserList
[0].Passwords
.getLength() == 0)
68 // Password sequence can be empty, for instance if master
69 // password was not given (e.g. master pw dialog canceled)
70 // pw container does not throw NoMasterException in this case.
75 // "user/pass" record found.
76 if (!bCheckForEqualPasswords
|| !rRequest
.HasPassword
77 || rRequest
.Password
!= aRec
.UserList
[0].Passwords
[0]) // failed login attempt?
79 if (xSupplyAuthentication
->canSetUserName())
80 xSupplyAuthentication
->
81 setUserName(aRec
.UserList
[0].UserName
);
83 if (xSupplyAuthentication
->canSetPassword())
84 xSupplyAuthentication
->
85 setPassword(aRec
.UserList
[0].Passwords
[0]);
86 if (aRec
.UserList
[0].Passwords
.getLength() > 1)
88 if (rRequest
.HasRealm
)
90 if (xSupplyAuthentication
->canSetRealm())
91 xSupplyAuthentication
->
92 setRealm(aRec
.UserList
[0].Passwords
[1]);
94 else if (xSupplyAuthentication
->canSetAccount())
95 xSupplyAuthentication
->
96 setAccount(aRec
.UserList
[0].Passwords
[1]);
99 if ( xSupplyAuthentication2
.is() && bCanUseSystemCredentials
)
100 xSupplyAuthentication2
->setUseSystemCredentials( false );
113 PasswordContainerHelper::PasswordContainerHelper(
114 uno::Reference
< uno::XComponentContext
> const & xContext
):
115 m_xPasswordContainer(task::PasswordContainer::create(xContext
))
119 bool PasswordContainerHelper::handleAuthenticationRequest(
120 ucb::AuthenticationRequest
const & rRequest
,
121 uno::Reference
< ucb::XInteractionSupplyAuthentication
> const &
122 xSupplyAuthentication
,
123 OUString
const & rURL
,
124 uno::Reference
< task::XInteractionHandler2
> const & xIH
)
126 uno::Reference
< task::XInteractionHandler
> xIH1(xIH
, uno::UNO_QUERY
);
128 // Is continuation even a XInteractionSupplyAuthentication2, which
129 // is derived from XInteractionSupplyAuthentication?
130 uno::Reference
< ucb::XInteractionSupplyAuthentication2
>
131 xSupplyAuthentication2(xSupplyAuthentication
, uno::UNO_QUERY
);
133 bool bCanUseSystemCredentials
= false;
134 if (xSupplyAuthentication2
.is())
136 sal_Bool bDefaultUseSystemCredentials
;
137 bCanUseSystemCredentials
138 = xSupplyAuthentication2
->canUseSystemCredentials(
139 bDefaultUseSystemCredentials
);
142 if ( bCanUseSystemCredentials
)
144 // Does the configuration mandate that we try system credentials first?
145 bool bUseSystemCredentials
= ::officecfg::Office::Common::Passwords::TrySystemCredentialsFirst::get();
146 if (!bUseSystemCredentials
)
148 // Runtime / Persistent info avail for current auth request?
149 OUString aResult
= m_xPasswordContainer
->findUrl(
150 rURL
.isEmpty() ? rRequest
.ServerName
: rURL
);
151 bUseSystemCredentials
= !aResult
.isEmpty();
153 if ( bUseSystemCredentials
)
155 if ( fillContinuation( true,
158 xSupplyAuthentication
,
159 xSupplyAuthentication2
,
160 bCanUseSystemCredentials
,
168 // m_xPasswordContainer works with userName passwdSequences pairs:
169 if (rRequest
.HasUserName
&& rRequest
.HasPassword
)
173 if (rRequest
.UserName
.isEmpty())
175 task::UrlRecord aRec
;
176 if ( !rURL
.isEmpty() )
177 aRec
= m_xPasswordContainer
->find(rURL
, xIH1
);
179 if ( aRec
.UserList
.getLength() == 0 )
181 // compat: try server name.
182 aRec
= m_xPasswordContainer
->find(rRequest
.ServerName
, xIH1
);
185 if ( fillContinuation( false,
188 xSupplyAuthentication
,
189 xSupplyAuthentication2
,
190 bCanUseSystemCredentials
,
198 task::UrlRecord aRec
;
199 if ( !rURL
.isEmpty() )
200 aRec
= m_xPasswordContainer
->findForName(
201 rURL
, rRequest
.UserName
, xIH1
);
203 if ( aRec
.UserList
.getLength() == 0 )
205 // compat: try server name.
206 aRec
= m_xPasswordContainer
->findForName(
207 rRequest
.ServerName
, rRequest
.UserName
, xIH1
);
210 if ( fillContinuation( false,
213 xSupplyAuthentication
,
214 xSupplyAuthentication2
,
215 bCanUseSystemCredentials
,
222 catch (task::NoMasterException
const &)
223 {} // user did not enter master password
229 bool PasswordContainerHelper::addRecord(
230 OUString
const & rURL
,
231 OUString
const & rUsername
,
232 uno::Sequence
< OUString
> const & rPasswords
,
233 uno::Reference
< task::XInteractionHandler2
> const & xIH
,
236 uno::Reference
< task::XInteractionHandler
> xIH1(xIH
, uno::UNO_QUERY
);
240 if ( !rUsername
.isEmpty() )
242 OSL_ENSURE( m_xPasswordContainer
.is(),
243 "Got no XPasswordContainer!" );
244 if ( !m_xPasswordContainer
.is() )
249 // If persistent storing of passwords is not yet
250 // allowed, enable it.
251 if ( !m_xPasswordContainer
->isPersistentStoringAllowed() )
252 m_xPasswordContainer
->allowPersistentStoring( true );
254 m_xPasswordContainer
->addPersistent( rURL
,
260 m_xPasswordContainer
->add( rURL
,
267 m_xPasswordContainer
->addUrl( rURL
, bPersist
);
270 catch ( task::NoMasterException
const & )
272 // user did not enter master password
279 PasswordContainerInteractionHandler::PasswordContainerInteractionHandler(
280 const uno::Reference
< uno::XComponentContext
>& xContext
)
281 : m_aPwContainerHelper( xContext
)
287 PasswordContainerInteractionHandler::~PasswordContainerInteractionHandler()
292 // XServiceInfo methods.
297 PasswordContainerInteractionHandler::getImplementationName()
299 return getImplementationName_Static();
305 PasswordContainerInteractionHandler::supportsService(
306 const OUString
& ServiceName
)
308 return cppu::supportsService(this, ServiceName
);
313 uno::Sequence
< OUString
> SAL_CALL
314 PasswordContainerInteractionHandler::getSupportedServiceNames()
316 return getSupportedServiceNames_Static();
322 PasswordContainerInteractionHandler::getImplementationName_Static()
324 return OUString( "com.sun.star.comp.uui.PasswordContainerInteractionHandler" );
329 uno::Sequence
< OUString
>
330 PasswordContainerInteractionHandler::getSupportedServiceNames_Static()
332 uno::Sequence
< OUString
> aSNS
{ "com.sun.star.task.PasswordContainerInteractionHandler" };
337 // XInteractionHandler2 methods.
342 PasswordContainerInteractionHandler::handle(
343 const uno::Reference
< task::XInteractionRequest
>& rRequest
)
345 handleInteractionRequest( rRequest
);
350 PasswordContainerInteractionHandler::handleInteractionRequest(
351 const uno::Reference
< task::XInteractionRequest
>& rRequest
)
353 if ( !rRequest
.is() )
356 uno::Any
aAnyRequest( rRequest
->getRequest() );
358 ucb::AuthenticationRequest aAuthenticationRequest
;
359 if ( !( aAnyRequest
>>= aAuthenticationRequest
) )
363 ucb::URLAuthenticationRequest aURLAuthenticationRequest
;
364 if ( aAnyRequest
>>= aURLAuthenticationRequest
)
365 aURL
= aURLAuthenticationRequest
.URL
;
367 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> >
368 rContinuations
= rRequest
->getContinuations();
370 uno::Reference
< ucb::XInteractionSupplyAuthentication
>
371 xSupplyAuthentication
;
373 for ( sal_Int32 i
= 0; i
< rContinuations
.getLength(); ++i
)
375 xSupplyAuthentication
.set( rContinuations
[i
], uno::UNO_QUERY
);
376 if( xSupplyAuthentication
.is() )
380 if ( !xSupplyAuthentication
.is() )
383 // Try to obtain credentials from password container.
384 if ( m_aPwContainerHelper
.
385 handleAuthenticationRequest( aAuthenticationRequest
,
386 xSupplyAuthentication
,
388 // @@@ FIXME: this not able to
389 // handle master pw request!
390 // master pw request is never
391 // solvable without UI!
394 // successfully handled
395 xSupplyAuthentication
->select();
402 // Service factory implementation.
404 /// @throws uno::Exception
405 static uno::Reference
< uno::XInterface
>
406 PasswordContainerInteractionHandler_CreateInstance(
407 const uno::Reference
< lang::XMultiServiceFactory
> & rSMgr
)
409 lang::XServiceInfo
* pX
= static_cast< lang::XServiceInfo
* >(
410 new PasswordContainerInteractionHandler( comphelper::getComponentContext(rSMgr
) ) );
411 return uno::Reference
< uno::XInterface
>::query( pX
);
416 uno::Reference
< lang::XSingleServiceFactory
>
417 PasswordContainerInteractionHandler::createServiceFactory(
418 const uno::Reference
< lang::XMultiServiceFactory
>& rxServiceMgr
)
420 return cppu::createOneInstanceFactory(
422 PasswordContainerInteractionHandler::getImplementationName_Static(),
423 PasswordContainerInteractionHandler_CreateInstance
,
424 PasswordContainerInteractionHandler::getSupportedServiceNames_Static() );
429 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */