Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
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/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
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 .
18 : */
19 :
20 : #include <comphelper/processfactory.hxx>
21 : #include <cppuhelper/factory.hxx>
22 : #include <cppuhelper/supportsservice.hxx>
23 : #include <osl/diagnose.h>
24 :
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 :
34 : #include "passwordcontainer.hxx"
35 :
36 : using namespace com::sun::star;
37 :
38 : namespace {
39 :
40 :
41 0 : bool fillContinuation(
42 : bool bUseSystemCredentials,
43 : const ucb::AuthenticationRequest & rRequest,
44 : const task::UrlRecord & aRec,
45 : const uno::Reference< ucb::XInteractionSupplyAuthentication > &
46 : xSupplyAuthentication,
47 : const uno::Reference< ucb::XInteractionSupplyAuthentication2 > &
48 : xSupplyAuthentication2,
49 : bool bCanUseSystemCredentials,
50 : bool bCheckForEqualPasswords )
51 : {
52 0 : if ( bUseSystemCredentials )
53 : {
54 : // "use system creds" record found.
55 : // Wants client that we use it?
56 0 : if ( xSupplyAuthentication2.is() && bCanUseSystemCredentials )
57 : {
58 0 : xSupplyAuthentication2->setUseSystemCredentials( sal_True );
59 0 : return true;
60 : }
61 0 : return false;
62 : }
63 0 : else if (aRec.UserList.getLength() != 0)
64 : {
65 0 : if (aRec.UserList[0].Passwords.getLength() == 0)
66 : {
67 : // Password sequence can be empty, for instance if master
68 : // password was not given (e.g. master pw dialog canceled)
69 : // pw container does not throw NoMasterException in this case.
70 : // bug???
71 0 : return false;
72 : }
73 :
74 : // "user/pass" record found.
75 0 : if (!bCheckForEqualPasswords || !rRequest.HasPassword
76 0 : || rRequest.Password != aRec.UserList[0].Passwords[0]) // failed login attempt?
77 : {
78 0 : if (xSupplyAuthentication->canSetUserName())
79 0 : xSupplyAuthentication->
80 0 : setUserName(aRec.UserList[0].UserName.getStr());
81 :
82 0 : if (xSupplyAuthentication->canSetPassword())
83 0 : xSupplyAuthentication->
84 0 : setPassword(aRec.UserList[0].Passwords[0].getStr());
85 0 : if (aRec.UserList[0].Passwords.getLength() > 1)
86 : {
87 0 : if (rRequest.HasRealm)
88 : {
89 0 : if (xSupplyAuthentication->canSetRealm())
90 0 : xSupplyAuthentication->
91 0 : setRealm(aRec.UserList[0].Passwords[1].
92 0 : getStr());
93 : }
94 0 : else if (xSupplyAuthentication->canSetAccount())
95 0 : xSupplyAuthentication->
96 0 : setAccount(aRec.UserList[0].Passwords[1].
97 0 : getStr());
98 : }
99 :
100 0 : if ( xSupplyAuthentication2.is() && bCanUseSystemCredentials )
101 0 : xSupplyAuthentication2->setUseSystemCredentials( sal_False );
102 :
103 0 : return true;
104 : }
105 : }
106 0 : return false;
107 : }
108 :
109 : } // namespace
110 :
111 : namespace uui {
112 :
113 :
114 1 : PasswordContainerHelper::PasswordContainerHelper(
115 : uno::Reference< uno::XComponentContext > const & xContext ):
116 1 : m_xPasswordContainer(task::PasswordContainer::create(xContext))
117 1 : {}
118 :
119 :
120 0 : bool PasswordContainerHelper::handleAuthenticationRequest(
121 : ucb::AuthenticationRequest const & rRequest,
122 : uno::Reference< ucb::XInteractionSupplyAuthentication > const &
123 : xSupplyAuthentication,
124 : OUString const & rURL,
125 : uno::Reference< task::XInteractionHandler2 > const & xIH )
126 : {
127 0 : uno::Reference< task::XInteractionHandler > xIH1(xIH, uno::UNO_QUERY);
128 :
129 : // Is continuation even a XInteractionSupplyAuthentication2, which
130 : // is derived from XInteractionSupplyAuthentication?
131 : uno::Reference< ucb::XInteractionSupplyAuthentication2 >
132 0 : xSupplyAuthentication2(xSupplyAuthentication, uno::UNO_QUERY);
133 :
134 0 : bool bCanUseSystemCredentials = false;
135 0 : if (xSupplyAuthentication2.is())
136 : {
137 : sal_Bool bDefaultUseSystemCredentials;
138 : bCanUseSystemCredentials
139 0 : = xSupplyAuthentication2->canUseSystemCredentials(
140 0 : bDefaultUseSystemCredentials );
141 : }
142 :
143 0 : if ( bCanUseSystemCredentials )
144 : {
145 : // Runtime / Persistent info avail for current auth request?
146 :
147 0 : OUString aResult = m_xPasswordContainer->findUrl(
148 0 : rURL.isEmpty() ? rRequest.ServerName : rURL );
149 0 : if ( !aResult.isEmpty() )
150 : {
151 0 : if ( fillContinuation( true,
152 : rRequest,
153 : task::UrlRecord(),
154 : xSupplyAuthentication,
155 : xSupplyAuthentication2,
156 : bCanUseSystemCredentials,
157 0 : false ) )
158 : {
159 0 : return true;
160 : }
161 0 : }
162 : }
163 :
164 : // m_xPasswordContainer works with userName passwdSequences pairs:
165 0 : if (rRequest.HasUserName && rRequest.HasPassword)
166 : {
167 : try
168 : {
169 0 : if (rRequest.UserName.isEmpty())
170 : {
171 0 : task::UrlRecord aRec;
172 0 : if ( !rURL.isEmpty() )
173 0 : aRec = m_xPasswordContainer->find(rURL, xIH1);
174 :
175 0 : if ( aRec.UserList.getLength() == 0 )
176 : {
177 : // compat: try server name.
178 0 : aRec = m_xPasswordContainer->find(rRequest.ServerName, xIH1);
179 : }
180 :
181 0 : if ( fillContinuation( false,
182 : rRequest,
183 : aRec,
184 : xSupplyAuthentication,
185 : xSupplyAuthentication2,
186 : bCanUseSystemCredentials,
187 0 : false ) )
188 : {
189 0 : return true;
190 0 : }
191 : }
192 : else
193 : {
194 0 : task::UrlRecord aRec;
195 0 : if ( !rURL.isEmpty() )
196 0 : aRec = m_xPasswordContainer->findForName(
197 0 : rURL, rRequest.UserName, xIH1);
198 :
199 0 : if ( aRec.UserList.getLength() == 0 )
200 : {
201 : // compat: try server name.
202 0 : aRec = m_xPasswordContainer->findForName(
203 0 : rRequest.ServerName, rRequest.UserName, xIH1);
204 : }
205 :
206 0 : if ( fillContinuation( false,
207 : rRequest,
208 : aRec,
209 : xSupplyAuthentication,
210 : xSupplyAuthentication2,
211 : bCanUseSystemCredentials,
212 0 : true ) )
213 : {
214 0 : return true;
215 0 : }
216 : }
217 : }
218 0 : catch (task::NoMasterException const &)
219 : {} // user did not enter master password
220 : }
221 0 : return false;
222 : }
223 :
224 :
225 0 : bool PasswordContainerHelper::addRecord(
226 : OUString const & rURL,
227 : OUString const & rUsername,
228 : uno::Sequence< OUString > const & rPasswords,
229 : uno::Reference< task::XInteractionHandler2 > const & xIH,
230 : bool bPersist )
231 : {
232 0 : uno::Reference< task::XInteractionHandler > xIH1(xIH, uno::UNO_QUERY);
233 :
234 : try
235 : {
236 0 : if ( !rUsername.isEmpty() )
237 : {
238 : OSL_ENSURE( m_xPasswordContainer.is(),
239 : "Got no XPasswordContainer!" );
240 0 : if ( !m_xPasswordContainer.is() )
241 0 : return false;
242 :
243 0 : if ( bPersist )
244 : {
245 : // If persistent storing of passwords is not yet
246 : // allowed, enable it.
247 0 : if ( !m_xPasswordContainer->isPersistentStoringAllowed() )
248 0 : m_xPasswordContainer->allowPersistentStoring( sal_True );
249 :
250 0 : m_xPasswordContainer->addPersistent( rURL,
251 : rUsername,
252 : rPasswords,
253 0 : xIH1 );
254 : }
255 : else
256 0 : m_xPasswordContainer->add( rURL,
257 : rUsername,
258 : rPasswords,
259 0 : xIH1 );
260 : }
261 : else
262 : {
263 0 : m_xPasswordContainer->addUrl( rURL, bPersist );
264 : }
265 : }
266 0 : catch ( task::NoMasterException const & )
267 : {
268 : // user did not enter master password
269 0 : return false;
270 : }
271 0 : return true;
272 : }
273 :
274 :
275 :
276 :
277 :
278 1 : PasswordContainerInteractionHandler::PasswordContainerInteractionHandler(
279 : const uno::Reference< uno::XComponentContext >& xContext )
280 1 : : m_aPwContainerHelper( xContext )
281 : {
282 1 : }
283 :
284 :
285 : // virtual
286 2 : PasswordContainerInteractionHandler::~PasswordContainerInteractionHandler()
287 : {
288 2 : }
289 :
290 :
291 :
292 : // XServiceInfo methods.
293 :
294 :
295 :
296 : // virtual
297 : OUString SAL_CALL
298 1 : PasswordContainerInteractionHandler::getImplementationName()
299 : throw ( uno::RuntimeException, std::exception )
300 : {
301 1 : return getImplementationName_Static();
302 : }
303 :
304 :
305 : // virtual
306 : sal_Bool SAL_CALL
307 0 : PasswordContainerInteractionHandler::supportsService(
308 : const OUString& ServiceName )
309 : throw ( uno::RuntimeException, std::exception )
310 : {
311 0 : return cppu::supportsService(this, ServiceName);
312 : }
313 :
314 :
315 : // virtual
316 : uno::Sequence< OUString > SAL_CALL
317 1 : PasswordContainerInteractionHandler::getSupportedServiceNames()
318 : throw ( uno::RuntimeException, std::exception )
319 : {
320 1 : return getSupportedServiceNames_Static();
321 : }
322 :
323 :
324 : // static
325 : OUString
326 3 : PasswordContainerInteractionHandler::getImplementationName_Static()
327 : {
328 3 : return OUString( "com.sun.star.comp.uui.PasswordContainerInteractionHandler" );
329 : }
330 :
331 :
332 : // static
333 : uno::Sequence< OUString >
334 2 : PasswordContainerInteractionHandler::getSupportedServiceNames_Static()
335 : {
336 2 : uno::Sequence< OUString > aSNS( 1 );
337 2 : aSNS.getArray()[ 0 ] =
338 2 : "com.sun.star.task.PasswordContainerInteractionHandler";
339 2 : return aSNS;
340 : }
341 :
342 :
343 :
344 : // XInteractionHandler2 methods.
345 :
346 :
347 :
348 : // virtual
349 : void SAL_CALL
350 0 : PasswordContainerInteractionHandler::handle(
351 : const uno::Reference< task::XInteractionRequest >& rRequest )
352 : throw ( uno::RuntimeException, std::exception )
353 : {
354 0 : handleInteractionRequest( rRequest );
355 0 : }
356 :
357 : // virtual
358 : sal_Bool SAL_CALL
359 0 : PasswordContainerInteractionHandler::handleInteractionRequest(
360 : const uno::Reference< task::XInteractionRequest >& rRequest )
361 : throw ( uno::RuntimeException, std::exception )
362 : {
363 0 : if ( !rRequest.is() )
364 0 : return false;
365 :
366 0 : uno::Any aAnyRequest( rRequest->getRequest() );
367 :
368 0 : ucb::AuthenticationRequest aAuthenticationRequest;
369 0 : if ( !( aAnyRequest >>= aAuthenticationRequest ) )
370 0 : return false;
371 :
372 0 : OUString aURL;
373 0 : ucb::URLAuthenticationRequest aURLAuthenticationRequest;
374 0 : if ( aAnyRequest >>= aURLAuthenticationRequest )
375 0 : aURL = aURLAuthenticationRequest.URL;
376 :
377 : uno::Sequence< uno::Reference< task::XInteractionContinuation > >
378 0 : rContinuations = rRequest->getContinuations();
379 :
380 : uno::Reference< ucb::XInteractionSupplyAuthentication >
381 0 : xSupplyAuthentication;
382 :
383 0 : for ( sal_Int32 i = 0; i < rContinuations.getLength(); ++i )
384 : {
385 : xSupplyAuthentication
386 0 : = uno::Reference< ucb::XInteractionSupplyAuthentication >(
387 0 : rContinuations[i], uno::UNO_QUERY );
388 0 : if( xSupplyAuthentication.is() )
389 0 : break;
390 : }
391 :
392 0 : if ( !xSupplyAuthentication.is() )
393 0 : return false;
394 :
395 : // Try to obtain credentials from password container.
396 0 : if ( m_aPwContainerHelper.
397 : handleAuthenticationRequest( aAuthenticationRequest,
398 : xSupplyAuthentication,
399 : aURL,
400 : // @@@ FIXME: this not able to
401 : // handle master pw request!
402 : // master pw request is never
403 : // solvable without UI!
404 0 : this ) )
405 : {
406 : // successfully handled
407 0 : xSupplyAuthentication->select();
408 0 : return true;
409 : }
410 0 : return false;
411 : }
412 :
413 :
414 :
415 : // Service factory implementation.
416 :
417 :
418 :
419 : static uno::Reference< uno::XInterface > SAL_CALL
420 1 : PasswordContainerInteractionHandler_CreateInstance(
421 : const uno::Reference< lang::XMultiServiceFactory> & rSMgr )
422 : throw( uno::Exception )
423 : {
424 : lang::XServiceInfo * pX = static_cast< lang::XServiceInfo * >(
425 1 : new PasswordContainerInteractionHandler( comphelper::getComponentContext(rSMgr) ) );
426 1 : return uno::Reference< uno::XInterface >::query( pX );
427 : }
428 :
429 :
430 : // static
431 : uno::Reference< lang::XSingleServiceFactory >
432 1 : PasswordContainerInteractionHandler::createServiceFactory(
433 : const uno::Reference< lang::XMultiServiceFactory >& rxServiceMgr )
434 : {
435 : return uno::Reference< lang::XSingleServiceFactory >(
436 : cppu::createOneInstanceFactory(
437 : rxServiceMgr,
438 : PasswordContainerInteractionHandler::getImplementationName_Static(),
439 : PasswordContainerInteractionHandler_CreateInstance,
440 1 : PasswordContainerInteractionHandler::getSupportedServiceNames_Static() ) );
441 : }
442 :
443 : } // namespace uui
444 :
445 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|