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 <cppuhelper/supportsservice.hxx>
21 #include <osl/diagnose.h>
23 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
24 #include <com/sun/star/task/NoMasterException.hpp>
25 #include <com/sun/star/task/PasswordContainer.hpp>
26 #include <com/sun/star/task/XInteractionHandler2.hpp>
27 #include <com/sun/star/ucb/AuthenticationRequest.hpp>
28 #include <com/sun/star/ucb/URLAuthenticationRequest.hpp>
29 #include <com/sun/star/ucb/XInteractionSupplyAuthentication.hpp>
30 #include <com/sun/star/ucb/XInteractionSupplyAuthentication2.hpp>
31 #include <officecfg/Office/Common.hxx>
33 #include "passwordcontainer.hxx"
35 using namespace com::sun::star
;
40 bool fillContinuation(
41 bool bUseSystemCredentials
,
42 const ucb::AuthenticationRequest
& rRequest
,
43 const task::UrlRecord
& aRec
,
44 const uno::Reference
< ucb::XInteractionSupplyAuthentication
> &
45 xSupplyAuthentication
,
46 const uno::Reference
< ucb::XInteractionSupplyAuthentication2
> &
47 xSupplyAuthentication2
,
48 bool bCanUseSystemCredentials
,
49 bool bCheckForEqualPasswords
)
51 if ( bUseSystemCredentials
)
53 // "use system creds" record found.
54 // Wants client that we use it?
55 if ( xSupplyAuthentication2
.is() && bCanUseSystemCredentials
)
57 xSupplyAuthentication2
->setUseSystemCredentials( true );
62 else if (aRec
.UserList
.hasElements())
64 if (!aRec
.UserList
[0].Passwords
.hasElements())
66 // Password sequence can be empty, for instance if master
67 // password was not given (e.g. master pw dialog canceled)
68 // pw container does not throw NoMasterException in this case.
73 // "user/pass" record found.
74 if (!bCheckForEqualPasswords
|| !rRequest
.HasPassword
75 || rRequest
.Password
!= aRec
.UserList
[0].Passwords
[0]) // failed login attempt?
77 if (xSupplyAuthentication
->canSetUserName())
78 xSupplyAuthentication
->
79 setUserName(aRec
.UserList
[0].UserName
);
81 if (xSupplyAuthentication
->canSetPassword())
82 xSupplyAuthentication
->
83 setPassword(aRec
.UserList
[0].Passwords
[0]);
84 if (aRec
.UserList
[0].Passwords
.getLength() > 1)
86 if (rRequest
.HasRealm
)
88 if (xSupplyAuthentication
->canSetRealm())
89 xSupplyAuthentication
->
90 setRealm(aRec
.UserList
[0].Passwords
[1]);
92 else if (xSupplyAuthentication
->canSetAccount())
93 xSupplyAuthentication
->
94 setAccount(aRec
.UserList
[0].Passwords
[1]);
97 if ( xSupplyAuthentication2
.is() && bCanUseSystemCredentials
)
98 xSupplyAuthentication2
->setUseSystemCredentials( false );
111 PasswordContainerHelper::PasswordContainerHelper(
112 uno::Reference
< uno::XComponentContext
> const & xContext
):
113 m_xPasswordContainer(task::PasswordContainer::create(xContext
))
117 bool PasswordContainerHelper::handleAuthenticationRequest(
118 ucb::AuthenticationRequest
const & rRequest
,
119 uno::Reference
< ucb::XInteractionSupplyAuthentication
> const &
120 xSupplyAuthentication
,
121 OUString
const & rURL
,
122 uno::Reference
< task::XInteractionHandler2
> const & xIH
)
124 // Is continuation even a XInteractionSupplyAuthentication2, which
125 // is derived from XInteractionSupplyAuthentication?
126 uno::Reference
< ucb::XInteractionSupplyAuthentication2
>
127 xSupplyAuthentication2(xSupplyAuthentication
, uno::UNO_QUERY
);
129 bool bCanUseSystemCredentials
= false;
130 if (xSupplyAuthentication2
.is())
132 sal_Bool bDefaultUseSystemCredentials
;
133 bCanUseSystemCredentials
134 = xSupplyAuthentication2
->canUseSystemCredentials(
135 bDefaultUseSystemCredentials
);
138 if ( bCanUseSystemCredentials
)
140 // Does the configuration mandate that we try system credentials first?
141 bool bUseSystemCredentials
= ::officecfg::Office::Common::Passwords::TrySystemCredentialsFirst::get();
142 if (!bUseSystemCredentials
)
144 // Runtime / Persistent info avail for current auth request?
145 OUString aResult
= m_xPasswordContainer
->findUrl(
146 rURL
.isEmpty() ? rRequest
.ServerName
: rURL
);
147 bUseSystemCredentials
= !aResult
.isEmpty();
149 if ( bUseSystemCredentials
)
151 if ( fillContinuation( true,
154 xSupplyAuthentication
,
155 xSupplyAuthentication2
,
156 bCanUseSystemCredentials
,
164 // m_xPasswordContainer works with userName passwdSequences pairs:
165 if (rRequest
.HasUserName
&& rRequest
.HasPassword
)
169 if (rRequest
.UserName
.isEmpty())
171 task::UrlRecord aRec
;
172 if ( !rURL
.isEmpty() )
173 aRec
= m_xPasswordContainer
->find(rURL
, xIH
);
175 if ( !aRec
.UserList
.hasElements() )
177 // compat: try server name.
178 aRec
= m_xPasswordContainer
->find(rRequest
.ServerName
, xIH
);
181 if ( fillContinuation( false,
184 xSupplyAuthentication
,
185 xSupplyAuthentication2
,
186 bCanUseSystemCredentials
,
194 task::UrlRecord aRec
;
195 if ( !rURL
.isEmpty() )
196 aRec
= m_xPasswordContainer
->findForName(
197 rURL
, rRequest
.UserName
, xIH
);
199 if ( !aRec
.UserList
.hasElements() )
201 // compat: try server name.
202 aRec
= m_xPasswordContainer
->findForName(
203 rRequest
.ServerName
, rRequest
.UserName
, xIH
);
206 if ( fillContinuation( false,
209 xSupplyAuthentication
,
210 xSupplyAuthentication2
,
211 bCanUseSystemCredentials
,
218 catch (task::NoMasterException
const &)
219 {} // user did not enter master password
225 bool PasswordContainerHelper::addRecord(
226 OUString
const & rURL
,
227 OUString
const & rUsername
,
228 uno::Sequence
< OUString
> const & rPasswords
,
229 uno::Reference
< task::XInteractionHandler2
> const & xIH
,
234 if ( !rUsername
.isEmpty() )
236 OSL_ENSURE( m_xPasswordContainer
.is(),
237 "Got no XPasswordContainer!" );
238 if ( !m_xPasswordContainer
.is() )
243 // If persistent storing of passwords is not yet
244 // allowed, enable it.
245 if ( !m_xPasswordContainer
->isPersistentStoringAllowed() )
246 m_xPasswordContainer
->allowPersistentStoring( true );
248 m_xPasswordContainer
->addPersistent( rURL
,
254 m_xPasswordContainer
->add( rURL
,
261 m_xPasswordContainer
->addUrl( rURL
, bPersist
);
264 catch ( task::NoMasterException
const & )
266 // user did not enter master password
273 PasswordContainerInteractionHandler::PasswordContainerInteractionHandler(
274 const uno::Reference
< uno::XComponentContext
>& xContext
)
275 : m_aPwContainerHelper( xContext
)
281 PasswordContainerInteractionHandler::~PasswordContainerInteractionHandler()
286 // XServiceInfo methods.
291 PasswordContainerInteractionHandler::getImplementationName()
293 return "com.sun.star.comp.uui.PasswordContainerInteractionHandler";
299 PasswordContainerInteractionHandler::supportsService(
300 const OUString
& ServiceName
)
302 return cppu::supportsService(this, ServiceName
);
307 uno::Sequence
< OUString
> SAL_CALL
308 PasswordContainerInteractionHandler::getSupportedServiceNames()
310 return { "com.sun.star.task.PasswordContainerInteractionHandler" };
314 // XInteractionHandler2 methods.
319 PasswordContainerInteractionHandler::handle(
320 const uno::Reference
< task::XInteractionRequest
>& rRequest
)
322 handleInteractionRequest( rRequest
);
327 PasswordContainerInteractionHandler::handleInteractionRequest(
328 const uno::Reference
< task::XInteractionRequest
>& rRequest
)
330 if ( !rRequest
.is() )
333 uno::Any
aAnyRequest( rRequest
->getRequest() );
335 ucb::AuthenticationRequest aAuthenticationRequest
;
336 if ( !( aAnyRequest
>>= aAuthenticationRequest
) )
340 ucb::URLAuthenticationRequest aURLAuthenticationRequest
;
341 if ( aAnyRequest
>>= aURLAuthenticationRequest
)
342 aURL
= aURLAuthenticationRequest
.URL
;
344 const uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> >
345 rContinuations
= rRequest
->getContinuations();
347 uno::Reference
< ucb::XInteractionSupplyAuthentication
>
348 xSupplyAuthentication
;
350 for ( const auto& rContinuation
: rContinuations
)
352 xSupplyAuthentication
.set( rContinuation
, uno::UNO_QUERY
);
353 if( xSupplyAuthentication
.is() )
357 if ( !xSupplyAuthentication
.is() )
360 // Try to obtain credentials from password container.
361 if ( m_aPwContainerHelper
.
362 handleAuthenticationRequest( aAuthenticationRequest
,
363 xSupplyAuthentication
,
365 // @@@ FIXME: this not able to
366 // handle master pw request!
367 // master pw request is never
368 // solvable without UI!
371 // successfully handled
372 xSupplyAuthentication
->select();
381 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
382 com_sun_star_comp_uui_PasswordContainerInteractionHandler_get_implementation(
383 css::uno::XComponentContext
* context
, css::uno::Sequence
<css::uno::Any
> const&)
385 return cppu::acquire(new uui::PasswordContainerInteractionHandler(context
));
388 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */