Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / uui / source / passwordcontainer.cxx
bloba97725ef1ca324983ae19b3ac5af7b3d65cc5e7b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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;
39 namespace {
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 );
60 return true;
62 return false;
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.
71 // bug???
72 return false;
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 );
102 return true;
105 return false;
108 } // namespace
110 namespace uui {
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,
154 rRequest,
155 task::UrlRecord(),
156 xSupplyAuthentication,
157 xSupplyAuthentication2,
158 bCanUseSystemCredentials,
159 false ) )
161 return true;
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,
184 rRequest,
185 aRec,
186 xSupplyAuthentication,
187 xSupplyAuthentication2,
188 bCanUseSystemCredentials,
189 false ) )
191 return true;
194 else
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,
209 rRequest,
210 aRec,
211 xSupplyAuthentication,
212 xSupplyAuthentication2,
213 bCanUseSystemCredentials,
214 true ) )
216 return true;
220 catch (task::NoMasterException const &)
221 {} // user did not enter master password
223 return false;
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,
232 bool bPersist )
236 if ( !rUsername.isEmpty() )
238 OSL_ENSURE( m_xPasswordContainer.is(),
239 "Got no XPasswordContainer!" );
240 if ( !m_xPasswordContainer.is() )
241 return false;
243 if ( bPersist )
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,
251 rUsername,
252 rPasswords,
253 xIH );
255 else
256 m_xPasswordContainer->add( rURL,
257 rUsername,
258 rPasswords,
259 xIH );
261 else
263 m_xPasswordContainer->addUrl( rURL, bPersist );
266 catch ( task::NoMasterException const & )
268 // user did not enter master password
269 return false;
271 return true;
275 PasswordContainerInteractionHandler::PasswordContainerInteractionHandler(
276 const uno::Reference< uno::XComponentContext >& xContext )
277 : m_aPwContainerHelper( xContext )
282 // virtual
283 PasswordContainerInteractionHandler::~PasswordContainerInteractionHandler()
288 // XServiceInfo methods.
291 // virtual
292 OUString SAL_CALL
293 PasswordContainerInteractionHandler::getImplementationName()
295 return getImplementationName_Static();
299 // virtual
300 sal_Bool SAL_CALL
301 PasswordContainerInteractionHandler::supportsService(
302 const OUString& ServiceName )
304 return cppu::supportsService(this, ServiceName);
308 // virtual
309 uno::Sequence< OUString > SAL_CALL
310 PasswordContainerInteractionHandler::getSupportedServiceNames()
312 return getSupportedServiceNames_Static();
316 // static
317 OUString
318 PasswordContainerInteractionHandler::getImplementationName_Static()
320 return "com.sun.star.comp.uui.PasswordContainerInteractionHandler";
324 // static
325 uno::Sequence< OUString >
326 PasswordContainerInteractionHandler::getSupportedServiceNames_Static()
328 uno::Sequence< OUString > aSNS { "com.sun.star.task.PasswordContainerInteractionHandler" };
329 return aSNS;
333 // XInteractionHandler2 methods.
336 // virtual
337 void SAL_CALL
338 PasswordContainerInteractionHandler::handle(
339 const uno::Reference< task::XInteractionRequest >& rRequest )
341 handleInteractionRequest( rRequest );
344 // virtual
345 sal_Bool SAL_CALL
346 PasswordContainerInteractionHandler::handleInteractionRequest(
347 const uno::Reference< task::XInteractionRequest >& rRequest )
349 if ( !rRequest.is() )
350 return false;
352 uno::Any aAnyRequest( rRequest->getRequest() );
354 ucb::AuthenticationRequest aAuthenticationRequest;
355 if ( !( aAnyRequest >>= aAuthenticationRequest ) )
356 return false;
358 OUString aURL;
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() )
373 break;
376 if ( !xSupplyAuthentication.is() )
377 return false;
379 // Try to obtain credentials from password container.
380 if ( m_aPwContainerHelper.
381 handleAuthenticationRequest( aAuthenticationRequest,
382 xSupplyAuthentication,
383 aURL,
384 // @@@ FIXME: this not able to
385 // handle master pw request!
386 // master pw request is never
387 // solvable without UI!
388 this ) )
390 // successfully handled
391 xSupplyAuthentication->select();
392 return true;
394 return false;
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 );
411 // static
412 uno::Reference< lang::XSingleServiceFactory >
413 PasswordContainerInteractionHandler::createServiceFactory(
414 const uno::Reference< lang::XMultiServiceFactory >& rxServiceMgr )
416 return cppu::createOneInstanceFactory(
417 rxServiceMgr,
418 PasswordContainerInteractionHandler::getImplementationName_Static(),
419 PasswordContainerInteractionHandler_CreateInstance,
420 PasswordContainerInteractionHandler::getSupportedServiceNames_Static() );
423 } // namespace uui
425 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */