Version 6.1.4.1, tag libreoffice-6.1.4.1
[LibreOffice.git] / uui / source / passwordcontainer.cxx
blob82ee8ddf8b325744060065bfd4deeb032775c9d8
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.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.
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 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,
156 rRequest,
157 task::UrlRecord(),
158 xSupplyAuthentication,
159 xSupplyAuthentication2,
160 bCanUseSystemCredentials,
161 false ) )
163 return true;
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,
186 rRequest,
187 aRec,
188 xSupplyAuthentication,
189 xSupplyAuthentication2,
190 bCanUseSystemCredentials,
191 false ) )
193 return true;
196 else
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,
211 rRequest,
212 aRec,
213 xSupplyAuthentication,
214 xSupplyAuthentication2,
215 bCanUseSystemCredentials,
216 true ) )
218 return true;
222 catch (task::NoMasterException const &)
223 {} // user did not enter master password
225 return false;
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,
234 bool bPersist )
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() )
245 return false;
247 if ( bPersist )
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,
255 rUsername,
256 rPasswords,
257 xIH1 );
259 else
260 m_xPasswordContainer->add( rURL,
261 rUsername,
262 rPasswords,
263 xIH1 );
265 else
267 m_xPasswordContainer->addUrl( rURL, bPersist );
270 catch ( task::NoMasterException const & )
272 // user did not enter master password
273 return false;
275 return true;
279 PasswordContainerInteractionHandler::PasswordContainerInteractionHandler(
280 const uno::Reference< uno::XComponentContext >& xContext )
281 : m_aPwContainerHelper( xContext )
286 // virtual
287 PasswordContainerInteractionHandler::~PasswordContainerInteractionHandler()
292 // XServiceInfo methods.
295 // virtual
296 OUString SAL_CALL
297 PasswordContainerInteractionHandler::getImplementationName()
299 return getImplementationName_Static();
303 // virtual
304 sal_Bool SAL_CALL
305 PasswordContainerInteractionHandler::supportsService(
306 const OUString& ServiceName )
308 return cppu::supportsService(this, ServiceName);
312 // virtual
313 uno::Sequence< OUString > SAL_CALL
314 PasswordContainerInteractionHandler::getSupportedServiceNames()
316 return getSupportedServiceNames_Static();
320 // static
321 OUString
322 PasswordContainerInteractionHandler::getImplementationName_Static()
324 return OUString( "com.sun.star.comp.uui.PasswordContainerInteractionHandler" );
328 // static
329 uno::Sequence< OUString >
330 PasswordContainerInteractionHandler::getSupportedServiceNames_Static()
332 uno::Sequence< OUString > aSNS { "com.sun.star.task.PasswordContainerInteractionHandler" };
333 return aSNS;
337 // XInteractionHandler2 methods.
340 // virtual
341 void SAL_CALL
342 PasswordContainerInteractionHandler::handle(
343 const uno::Reference< task::XInteractionRequest >& rRequest )
345 handleInteractionRequest( rRequest );
348 // virtual
349 sal_Bool SAL_CALL
350 PasswordContainerInteractionHandler::handleInteractionRequest(
351 const uno::Reference< task::XInteractionRequest >& rRequest )
353 if ( !rRequest.is() )
354 return false;
356 uno::Any aAnyRequest( rRequest->getRequest() );
358 ucb::AuthenticationRequest aAuthenticationRequest;
359 if ( !( aAnyRequest >>= aAuthenticationRequest ) )
360 return false;
362 OUString aURL;
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() )
377 break;
380 if ( !xSupplyAuthentication.is() )
381 return false;
383 // Try to obtain credentials from password container.
384 if ( m_aPwContainerHelper.
385 handleAuthenticationRequest( aAuthenticationRequest,
386 xSupplyAuthentication,
387 aURL,
388 // @@@ FIXME: this not able to
389 // handle master pw request!
390 // master pw request is never
391 // solvable without UI!
392 this ) )
394 // successfully handled
395 xSupplyAuthentication->select();
396 return true;
398 return false;
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 );
415 // static
416 uno::Reference< lang::XSingleServiceFactory >
417 PasswordContainerInteractionHandler::createServiceFactory(
418 const uno::Reference< lang::XMultiServiceFactory >& rxServiceMgr )
420 return cppu::createOneInstanceFactory(
421 rxServiceMgr,
422 PasswordContainerInteractionHandler::getImplementationName_Static(),
423 PasswordContainerInteractionHandler_CreateInstance,
424 PasswordContainerInteractionHandler::getSupportedServiceNames_Static() );
427 } // namespace uui
429 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */