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 :
24 : #include "com/sun/star/lang/XMultiServiceFactory.hpp"
25 : #include "com/sun/star/task/NoMasterException.hpp"
26 : #include "com/sun/star/task/PasswordContainer.hpp"
27 : #include "com/sun/star/task/XInteractionHandler2.hpp"
28 : #include "com/sun/star/ucb/AuthenticationRequest.hpp"
29 : #include "com/sun/star/ucb/URLAuthenticationRequest.hpp"
30 : #include "com/sun/star/ucb/XInteractionSupplyAuthentication.hpp"
31 : #include "com/sun/star/ucb/XInteractionSupplyAuthentication2.hpp"
32 :
33 : #include "passwordcontainer.hxx"
34 :
35 : using namespace com::sun::star;
36 :
37 : namespace {
38 :
39 :
40 0 : 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 )
50 : {
51 0 : if ( bUseSystemCredentials )
52 : {
53 : // "use system creds" record found.
54 : // Wants client that we use it?
55 0 : if ( xSupplyAuthentication2.is() && bCanUseSystemCredentials )
56 : {
57 0 : xSupplyAuthentication2->setUseSystemCredentials( sal_True );
58 0 : return true;
59 : }
60 0 : return false;
61 : }
62 0 : else if (aRec.UserList.getLength() != 0)
63 : {
64 0 : if (aRec.UserList[0].Passwords.getLength() == 0)
65 : {
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.
69 : // bug???
70 0 : return false;
71 : }
72 :
73 : // "user/pass" record found.
74 0 : if (!bCheckForEqualPasswords || !rRequest.HasPassword
75 0 : || rRequest.Password != aRec.UserList[0].Passwords[0]) // failed login attempt?
76 : {
77 0 : if (xSupplyAuthentication->canSetUserName())
78 0 : xSupplyAuthentication->
79 0 : setUserName(aRec.UserList[0].UserName.getStr());
80 :
81 0 : if (xSupplyAuthentication->canSetPassword())
82 0 : xSupplyAuthentication->
83 0 : setPassword(aRec.UserList[0].Passwords[0].getStr());
84 0 : if (aRec.UserList[0].Passwords.getLength() > 1)
85 : {
86 0 : if (rRequest.HasRealm)
87 : {
88 0 : if (xSupplyAuthentication->canSetRealm())
89 0 : xSupplyAuthentication->
90 0 : setRealm(aRec.UserList[0].Passwords[1].
91 0 : getStr());
92 : }
93 0 : else if (xSupplyAuthentication->canSetAccount())
94 0 : xSupplyAuthentication->
95 0 : setAccount(aRec.UserList[0].Passwords[1].
96 0 : getStr());
97 : }
98 :
99 0 : if ( xSupplyAuthentication2.is() && bCanUseSystemCredentials )
100 0 : xSupplyAuthentication2->setUseSystemCredentials( sal_False );
101 :
102 0 : return true;
103 : }
104 : }
105 0 : return false;
106 : }
107 :
108 : } // namespace
109 :
110 : namespace uui {
111 :
112 :
113 0 : PasswordContainerHelper::PasswordContainerHelper(
114 : uno::Reference< uno::XComponentContext > const & xContext ):
115 0 : m_xPasswordContainer(task::PasswordContainer::create(xContext))
116 0 : {}
117 :
118 :
119 0 : 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 )
125 : SAL_THROW((uno::RuntimeException))
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 : sal_Bool bCanUseSystemCredentials = sal_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 : SAL_THROW((uno::RuntimeException))
232 : {
233 0 : uno::Reference< task::XInteractionHandler > xIH1(xIH, uno::UNO_QUERY);
234 :
235 : try
236 : {
237 0 : if ( !rUsername.isEmpty() )
238 : {
239 : OSL_ENSURE( m_xPasswordContainer.is(),
240 : "Got no XPasswordContainer!" );
241 0 : if ( !m_xPasswordContainer.is() )
242 0 : return false;
243 :
244 0 : if ( bPersist )
245 : {
246 : // If persistent storing of passwords is not yet
247 : // allowed, enable it.
248 0 : if ( !m_xPasswordContainer->isPersistentStoringAllowed() )
249 0 : m_xPasswordContainer->allowPersistentStoring( sal_True );
250 :
251 0 : m_xPasswordContainer->addPersistent( rURL,
252 : rUsername,
253 : rPasswords,
254 0 : xIH1 );
255 : }
256 : else
257 0 : m_xPasswordContainer->add( rURL,
258 : rUsername,
259 : rPasswords,
260 0 : xIH1 );
261 : }
262 : else
263 : {
264 0 : m_xPasswordContainer->addUrl( rURL, bPersist );
265 : }
266 : }
267 0 : catch ( task::NoMasterException const & )
268 : {
269 : // user did not enter master password
270 0 : return false;
271 : }
272 0 : return true;
273 : }
274 :
275 :
276 :
277 :
278 :
279 0 : PasswordContainerInteractionHandler::PasswordContainerInteractionHandler(
280 : const uno::Reference< uno::XComponentContext >& xContext )
281 0 : : m_aPwContainerHelper( xContext )
282 : {
283 0 : }
284 :
285 :
286 : // virtual
287 0 : PasswordContainerInteractionHandler::~PasswordContainerInteractionHandler()
288 : {
289 0 : }
290 :
291 :
292 :
293 : // XServiceInfo methods.
294 :
295 :
296 :
297 : // virtual
298 : OUString SAL_CALL
299 0 : PasswordContainerInteractionHandler::getImplementationName()
300 : throw ( uno::RuntimeException, std::exception )
301 : {
302 0 : return getImplementationName_Static();
303 : }
304 :
305 :
306 : // virtual
307 : sal_Bool SAL_CALL
308 0 : PasswordContainerInteractionHandler::supportsService(
309 : const OUString& ServiceName )
310 : throw ( uno::RuntimeException, std::exception )
311 : {
312 0 : return cppu::supportsService(this, ServiceName);
313 : }
314 :
315 :
316 : // virtual
317 : uno::Sequence< OUString > SAL_CALL
318 0 : PasswordContainerInteractionHandler::getSupportedServiceNames()
319 : throw ( uno::RuntimeException, std::exception )
320 : {
321 0 : return getSupportedServiceNames_Static();
322 : }
323 :
324 :
325 : // static
326 : OUString
327 0 : PasswordContainerInteractionHandler::getImplementationName_Static()
328 : {
329 0 : return OUString( "com.sun.star.comp.uui.PasswordContainerInteractionHandler" );
330 : }
331 :
332 :
333 : // static
334 : uno::Sequence< OUString >
335 0 : PasswordContainerInteractionHandler::getSupportedServiceNames_Static()
336 : {
337 0 : uno::Sequence< OUString > aSNS( 1 );
338 0 : aSNS.getArray()[ 0 ] = OUString(
339 0 : "com.sun.star.task.PasswordContainerInteractionHandler" );
340 0 : return aSNS;
341 : }
342 :
343 :
344 :
345 : // XInteractionHandler2 methods.
346 :
347 :
348 :
349 : // virtual
350 : void SAL_CALL
351 0 : PasswordContainerInteractionHandler::handle(
352 : const uno::Reference< task::XInteractionRequest >& rRequest )
353 : throw ( uno::RuntimeException, std::exception )
354 : {
355 0 : handleInteractionRequest( rRequest );
356 0 : }
357 :
358 : // virtual
359 : sal_Bool SAL_CALL
360 0 : PasswordContainerInteractionHandler::handleInteractionRequest(
361 : const uno::Reference< task::XInteractionRequest >& rRequest )
362 : throw ( uno::RuntimeException, std::exception )
363 : {
364 0 : if ( !rRequest.is() )
365 0 : return false;
366 :
367 0 : uno::Any aAnyRequest( rRequest->getRequest() );
368 :
369 0 : ucb::AuthenticationRequest aAuthenticationRequest;
370 0 : if ( !( aAnyRequest >>= aAuthenticationRequest ) )
371 0 : return false;
372 :
373 0 : OUString aURL;
374 0 : ucb::URLAuthenticationRequest aURLAuthenticationRequest;
375 0 : if ( aAnyRequest >>= aURLAuthenticationRequest )
376 0 : aURL = aURLAuthenticationRequest.URL;
377 :
378 : uno::Sequence< uno::Reference< task::XInteractionContinuation > >
379 0 : rContinuations = rRequest->getContinuations();
380 :
381 : uno::Reference< ucb::XInteractionSupplyAuthentication >
382 0 : xSupplyAuthentication;
383 :
384 0 : for ( sal_Int32 i = 0; i < rContinuations.getLength(); ++i )
385 : {
386 : xSupplyAuthentication
387 0 : = uno::Reference< ucb::XInteractionSupplyAuthentication >(
388 0 : rContinuations[i], uno::UNO_QUERY );
389 0 : if( xSupplyAuthentication.is() )
390 0 : break;
391 : }
392 :
393 0 : if ( !xSupplyAuthentication.is() )
394 0 : return false;
395 :
396 : // Try to obtain credentials from password container.
397 0 : if ( m_aPwContainerHelper.
398 : handleAuthenticationRequest( aAuthenticationRequest,
399 : xSupplyAuthentication,
400 : aURL,
401 : // @@@ FIXME: this not able to
402 : // handle master pw request!
403 : // master pw request is never
404 : // solvable without UI!
405 0 : this ) )
406 : {
407 : // successfully handled
408 0 : xSupplyAuthentication->select();
409 0 : return true;
410 : }
411 0 : return false;
412 : }
413 :
414 :
415 :
416 : // Service factory implementation.
417 :
418 :
419 :
420 : static uno::Reference< uno::XInterface > SAL_CALL
421 0 : PasswordContainerInteractionHandler_CreateInstance(
422 : const uno::Reference< lang::XMultiServiceFactory> & rSMgr )
423 : throw( uno::Exception )
424 : {
425 : lang::XServiceInfo * pX = static_cast< lang::XServiceInfo * >(
426 0 : new PasswordContainerInteractionHandler( comphelper::getComponentContext(rSMgr) ) );
427 0 : return uno::Reference< uno::XInterface >::query( pX );
428 : }
429 :
430 :
431 : // static
432 : uno::Reference< lang::XSingleServiceFactory >
433 0 : PasswordContainerInteractionHandler::createServiceFactory(
434 : const uno::Reference< lang::XMultiServiceFactory >& rxServiceMgr )
435 : {
436 : return uno::Reference< lang::XSingleServiceFactory >(
437 : cppu::createOneInstanceFactory(
438 : rxServiceMgr,
439 : PasswordContainerInteractionHandler::getImplementationName_Static(),
440 : PasswordContainerInteractionHandler_CreateInstance,
441 0 : PasswordContainerInteractionHandler::getSupportedServiceNames_Static() ) );
442 : }
443 :
444 : } // namespace uui
445 :
446 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|