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
.hasElements())
66 if (!aRec
.UserList
[0].Passwords
.hasElements())
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 // Is continuation even a XInteractionSupplyAuthentication2, which
127 // is derived from XInteractionSupplyAuthentication?
128 uno::Reference
< ucb::XInteractionSupplyAuthentication2
>
129 xSupplyAuthentication2(xSupplyAuthentication
, uno::UNO_QUERY
);
131 bool bCanUseSystemCredentials
= false;
132 if (xSupplyAuthentication2
.is())
134 sal_Bool bDefaultUseSystemCredentials
;
135 bCanUseSystemCredentials
136 = xSupplyAuthentication2
->canUseSystemCredentials(
137 bDefaultUseSystemCredentials
);
140 if ( bCanUseSystemCredentials
)
142 // Does the configuration mandate that we try system credentials first?
143 bool bUseSystemCredentials
= ::officecfg::Office::Common::Passwords::TrySystemCredentialsFirst::get();
144 if (!bUseSystemCredentials
)
146 // Runtime / Persistent info avail for current auth request?
147 OUString aResult
= m_xPasswordContainer
->findUrl(
148 rURL
.isEmpty() ? rRequest
.ServerName
: rURL
);
149 bUseSystemCredentials
= !aResult
.isEmpty();
151 if ( bUseSystemCredentials
)
153 if ( fillContinuation( true,
156 xSupplyAuthentication
,
157 xSupplyAuthentication2
,
158 bCanUseSystemCredentials
,
166 // m_xPasswordContainer works with userName passwdSequences pairs:
167 if (rRequest
.HasUserName
&& rRequest
.HasPassword
)
171 if (rRequest
.UserName
.isEmpty())
173 task::UrlRecord aRec
;
174 if ( !rURL
.isEmpty() )
175 aRec
= m_xPasswordContainer
->find(rURL
, xIH
);
177 if ( !aRec
.UserList
.hasElements() )
179 // compat: try server name.
180 aRec
= m_xPasswordContainer
->find(rRequest
.ServerName
, xIH
);
183 if ( fillContinuation( false,
186 xSupplyAuthentication
,
187 xSupplyAuthentication2
,
188 bCanUseSystemCredentials
,
196 task::UrlRecord aRec
;
197 if ( !rURL
.isEmpty() )
198 aRec
= m_xPasswordContainer
->findForName(
199 rURL
, rRequest
.UserName
, xIH
);
201 if ( !aRec
.UserList
.hasElements() )
203 // compat: try server name.
204 aRec
= m_xPasswordContainer
->findForName(
205 rRequest
.ServerName
, rRequest
.UserName
, xIH
);
208 if ( fillContinuation( false,
211 xSupplyAuthentication
,
212 xSupplyAuthentication2
,
213 bCanUseSystemCredentials
,
220 catch (task::NoMasterException
const &)
221 {} // user did not enter master password
227 bool PasswordContainerHelper::addRecord(
228 OUString
const & rURL
,
229 OUString
const & rUsername
,
230 uno::Sequence
< OUString
> const & rPasswords
,
231 uno::Reference
< task::XInteractionHandler2
> const & xIH
,
236 if ( !rUsername
.isEmpty() )
238 OSL_ENSURE( m_xPasswordContainer
.is(),
239 "Got no XPasswordContainer!" );
240 if ( !m_xPasswordContainer
.is() )
245 // If persistent storing of passwords is not yet
246 // allowed, enable it.
247 if ( !m_xPasswordContainer
->isPersistentStoringAllowed() )
248 m_xPasswordContainer
->allowPersistentStoring( true );
250 m_xPasswordContainer
->addPersistent( rURL
,
256 m_xPasswordContainer
->add( rURL
,
263 m_xPasswordContainer
->addUrl( rURL
, bPersist
);
266 catch ( task::NoMasterException
const & )
268 // user did not enter master password
275 PasswordContainerInteractionHandler::PasswordContainerInteractionHandler(
276 const uno::Reference
< uno::XComponentContext
>& xContext
)
277 : m_aPwContainerHelper( xContext
)
283 PasswordContainerInteractionHandler::~PasswordContainerInteractionHandler()
288 // XServiceInfo methods.
293 PasswordContainerInteractionHandler::getImplementationName()
295 return getImplementationName_Static();
301 PasswordContainerInteractionHandler::supportsService(
302 const OUString
& ServiceName
)
304 return cppu::supportsService(this, ServiceName
);
309 uno::Sequence
< OUString
> SAL_CALL
310 PasswordContainerInteractionHandler::getSupportedServiceNames()
312 return getSupportedServiceNames_Static();
318 PasswordContainerInteractionHandler::getImplementationName_Static()
320 return "com.sun.star.comp.uui.PasswordContainerInteractionHandler";
325 uno::Sequence
< OUString
>
326 PasswordContainerInteractionHandler::getSupportedServiceNames_Static()
328 uno::Sequence
< OUString
> aSNS
{ "com.sun.star.task.PasswordContainerInteractionHandler" };
333 // XInteractionHandler2 methods.
338 PasswordContainerInteractionHandler::handle(
339 const uno::Reference
< task::XInteractionRequest
>& rRequest
)
341 handleInteractionRequest( rRequest
);
346 PasswordContainerInteractionHandler::handleInteractionRequest(
347 const uno::Reference
< task::XInteractionRequest
>& rRequest
)
349 if ( !rRequest
.is() )
352 uno::Any
aAnyRequest( rRequest
->getRequest() );
354 ucb::AuthenticationRequest aAuthenticationRequest
;
355 if ( !( aAnyRequest
>>= aAuthenticationRequest
) )
359 ucb::URLAuthenticationRequest aURLAuthenticationRequest
;
360 if ( aAnyRequest
>>= aURLAuthenticationRequest
)
361 aURL
= aURLAuthenticationRequest
.URL
;
363 const uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> >
364 rContinuations
= rRequest
->getContinuations();
366 uno::Reference
< ucb::XInteractionSupplyAuthentication
>
367 xSupplyAuthentication
;
369 for ( const auto& rContinuation
: rContinuations
)
371 xSupplyAuthentication
.set( rContinuation
, uno::UNO_QUERY
);
372 if( xSupplyAuthentication
.is() )
376 if ( !xSupplyAuthentication
.is() )
379 // Try to obtain credentials from password container.
380 if ( m_aPwContainerHelper
.
381 handleAuthenticationRequest( aAuthenticationRequest
,
382 xSupplyAuthentication
,
384 // @@@ FIXME: this not able to
385 // handle master pw request!
386 // master pw request is never
387 // solvable without UI!
390 // successfully handled
391 xSupplyAuthentication
->select();
398 // Service factory implementation.
400 /// @throws uno::Exception
401 static uno::Reference
< uno::XInterface
>
402 PasswordContainerInteractionHandler_CreateInstance(
403 const uno::Reference
< lang::XMultiServiceFactory
> & rSMgr
)
405 lang::XServiceInfo
* pX
406 = new PasswordContainerInteractionHandler(comphelper::getComponentContext(rSMgr
));
407 return uno::Reference
< uno::XInterface
>::query( pX
);
412 uno::Reference
< lang::XSingleServiceFactory
>
413 PasswordContainerInteractionHandler::createServiceFactory(
414 const uno::Reference
< lang::XMultiServiceFactory
>& rxServiceMgr
)
416 return cppu::createOneInstanceFactory(
418 PasswordContainerInteractionHandler::getImplementationName_Static(),
419 PasswordContainerInteractionHandler_CreateInstance
,
420 PasswordContainerInteractionHandler::getSupportedServiceNames_Static() );
425 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */