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 2 : PasswordContainerHelper::PasswordContainerHelper(
114 : uno::Reference< uno::XComponentContext > const & xContext ):
115 2 : m_xPasswordContainer(task::PasswordContainer::create(xContext))
116 2 : {}
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 : {
126 0 : uno::Reference< task::XInteractionHandler > xIH1(xIH, uno::UNO_QUERY);
127 :
128 : // Is continuation even a XInteractionSupplyAuthentication2, which
129 : // is derived from XInteractionSupplyAuthentication?
130 : uno::Reference< ucb::XInteractionSupplyAuthentication2 >
131 0 : xSupplyAuthentication2(xSupplyAuthentication, uno::UNO_QUERY);
132 :
133 0 : bool bCanUseSystemCredentials = false;
134 0 : if (xSupplyAuthentication2.is())
135 : {
136 : sal_Bool bDefaultUseSystemCredentials;
137 : bCanUseSystemCredentials
138 0 : = xSupplyAuthentication2->canUseSystemCredentials(
139 0 : bDefaultUseSystemCredentials );
140 : }
141 :
142 0 : if ( bCanUseSystemCredentials )
143 : {
144 : // Runtime / Persistent info avail for current auth request?
145 :
146 0 : OUString aResult = m_xPasswordContainer->findUrl(
147 0 : rURL.isEmpty() ? rRequest.ServerName : rURL );
148 0 : if ( !aResult.isEmpty() )
149 : {
150 0 : if ( fillContinuation( true,
151 : rRequest,
152 : task::UrlRecord(),
153 : xSupplyAuthentication,
154 : xSupplyAuthentication2,
155 : bCanUseSystemCredentials,
156 0 : false ) )
157 : {
158 0 : return true;
159 : }
160 0 : }
161 : }
162 :
163 : // m_xPasswordContainer works with userName passwdSequences pairs:
164 0 : if (rRequest.HasUserName && rRequest.HasPassword)
165 : {
166 : try
167 : {
168 0 : if (rRequest.UserName.isEmpty())
169 : {
170 0 : task::UrlRecord aRec;
171 0 : if ( !rURL.isEmpty() )
172 0 : aRec = m_xPasswordContainer->find(rURL, xIH1);
173 :
174 0 : if ( aRec.UserList.getLength() == 0 )
175 : {
176 : // compat: try server name.
177 0 : aRec = m_xPasswordContainer->find(rRequest.ServerName, xIH1);
178 : }
179 :
180 0 : if ( fillContinuation( false,
181 : rRequest,
182 : aRec,
183 : xSupplyAuthentication,
184 : xSupplyAuthentication2,
185 : bCanUseSystemCredentials,
186 0 : false ) )
187 : {
188 0 : return true;
189 0 : }
190 : }
191 : else
192 : {
193 0 : task::UrlRecord aRec;
194 0 : if ( !rURL.isEmpty() )
195 0 : aRec = m_xPasswordContainer->findForName(
196 0 : rURL, rRequest.UserName, xIH1);
197 :
198 0 : if ( aRec.UserList.getLength() == 0 )
199 : {
200 : // compat: try server name.
201 0 : aRec = m_xPasswordContainer->findForName(
202 0 : rRequest.ServerName, rRequest.UserName, xIH1);
203 : }
204 :
205 0 : if ( fillContinuation( false,
206 : rRequest,
207 : aRec,
208 : xSupplyAuthentication,
209 : xSupplyAuthentication2,
210 : bCanUseSystemCredentials,
211 0 : true ) )
212 : {
213 0 : return true;
214 0 : }
215 : }
216 : }
217 0 : catch (task::NoMasterException const &)
218 : {} // user did not enter master password
219 : }
220 0 : return false;
221 : }
222 :
223 :
224 0 : bool PasswordContainerHelper::addRecord(
225 : OUString const & rURL,
226 : OUString const & rUsername,
227 : uno::Sequence< OUString > const & rPasswords,
228 : uno::Reference< task::XInteractionHandler2 > const & xIH,
229 : bool bPersist )
230 : {
231 0 : uno::Reference< task::XInteractionHandler > xIH1(xIH, uno::UNO_QUERY);
232 :
233 : try
234 : {
235 0 : if ( !rUsername.isEmpty() )
236 : {
237 : OSL_ENSURE( m_xPasswordContainer.is(),
238 : "Got no XPasswordContainer!" );
239 0 : if ( !m_xPasswordContainer.is() )
240 0 : return false;
241 :
242 0 : if ( bPersist )
243 : {
244 : // If persistent storing of passwords is not yet
245 : // allowed, enable it.
246 0 : if ( !m_xPasswordContainer->isPersistentStoringAllowed() )
247 0 : m_xPasswordContainer->allowPersistentStoring( sal_True );
248 :
249 0 : m_xPasswordContainer->addPersistent( rURL,
250 : rUsername,
251 : rPasswords,
252 0 : xIH1 );
253 : }
254 : else
255 0 : m_xPasswordContainer->add( rURL,
256 : rUsername,
257 : rPasswords,
258 0 : xIH1 );
259 : }
260 : else
261 : {
262 0 : m_xPasswordContainer->addUrl( rURL, bPersist );
263 : }
264 : }
265 0 : catch ( task::NoMasterException const & )
266 : {
267 : // user did not enter master password
268 0 : return false;
269 : }
270 0 : return true;
271 : }
272 :
273 :
274 :
275 :
276 :
277 2 : PasswordContainerInteractionHandler::PasswordContainerInteractionHandler(
278 : const uno::Reference< uno::XComponentContext >& xContext )
279 2 : : m_aPwContainerHelper( xContext )
280 : {
281 2 : }
282 :
283 :
284 : // virtual
285 4 : PasswordContainerInteractionHandler::~PasswordContainerInteractionHandler()
286 : {
287 4 : }
288 :
289 :
290 :
291 : // XServiceInfo methods.
292 :
293 :
294 :
295 : // virtual
296 : OUString SAL_CALL
297 0 : PasswordContainerInteractionHandler::getImplementationName()
298 : throw ( uno::RuntimeException, std::exception )
299 : {
300 0 : return getImplementationName_Static();
301 : }
302 :
303 :
304 : // virtual
305 : sal_Bool SAL_CALL
306 0 : PasswordContainerInteractionHandler::supportsService(
307 : const OUString& ServiceName )
308 : throw ( uno::RuntimeException, std::exception )
309 : {
310 0 : return cppu::supportsService(this, ServiceName);
311 : }
312 :
313 :
314 : // virtual
315 : uno::Sequence< OUString > SAL_CALL
316 0 : PasswordContainerInteractionHandler::getSupportedServiceNames()
317 : throw ( uno::RuntimeException, std::exception )
318 : {
319 0 : return getSupportedServiceNames_Static();
320 : }
321 :
322 :
323 : // static
324 : OUString
325 4 : PasswordContainerInteractionHandler::getImplementationName_Static()
326 : {
327 4 : return OUString( "com.sun.star.comp.uui.PasswordContainerInteractionHandler" );
328 : }
329 :
330 :
331 : // static
332 : uno::Sequence< OUString >
333 2 : PasswordContainerInteractionHandler::getSupportedServiceNames_Static()
334 : {
335 2 : uno::Sequence< OUString > aSNS( 1 );
336 4 : aSNS.getArray()[ 0 ] = OUString(
337 2 : "com.sun.star.task.PasswordContainerInteractionHandler" );
338 2 : return aSNS;
339 : }
340 :
341 :
342 :
343 : // XInteractionHandler2 methods.
344 :
345 :
346 :
347 : // virtual
348 : void SAL_CALL
349 0 : PasswordContainerInteractionHandler::handle(
350 : const uno::Reference< task::XInteractionRequest >& rRequest )
351 : throw ( uno::RuntimeException, std::exception )
352 : {
353 0 : handleInteractionRequest( rRequest );
354 0 : }
355 :
356 : // virtual
357 : sal_Bool SAL_CALL
358 0 : PasswordContainerInteractionHandler::handleInteractionRequest(
359 : const uno::Reference< task::XInteractionRequest >& rRequest )
360 : throw ( uno::RuntimeException, std::exception )
361 : {
362 0 : if ( !rRequest.is() )
363 0 : return false;
364 :
365 0 : uno::Any aAnyRequest( rRequest->getRequest() );
366 :
367 0 : ucb::AuthenticationRequest aAuthenticationRequest;
368 0 : if ( !( aAnyRequest >>= aAuthenticationRequest ) )
369 0 : return false;
370 :
371 0 : OUString aURL;
372 0 : ucb::URLAuthenticationRequest aURLAuthenticationRequest;
373 0 : if ( aAnyRequest >>= aURLAuthenticationRequest )
374 0 : aURL = aURLAuthenticationRequest.URL;
375 :
376 : uno::Sequence< uno::Reference< task::XInteractionContinuation > >
377 0 : rContinuations = rRequest->getContinuations();
378 :
379 : uno::Reference< ucb::XInteractionSupplyAuthentication >
380 0 : xSupplyAuthentication;
381 :
382 0 : for ( sal_Int32 i = 0; i < rContinuations.getLength(); ++i )
383 : {
384 : xSupplyAuthentication
385 0 : = uno::Reference< ucb::XInteractionSupplyAuthentication >(
386 0 : rContinuations[i], uno::UNO_QUERY );
387 0 : if( xSupplyAuthentication.is() )
388 0 : break;
389 : }
390 :
391 0 : if ( !xSupplyAuthentication.is() )
392 0 : return false;
393 :
394 : // Try to obtain credentials from password container.
395 0 : if ( m_aPwContainerHelper.
396 : handleAuthenticationRequest( aAuthenticationRequest,
397 : xSupplyAuthentication,
398 : aURL,
399 : // @@@ FIXME: this not able to
400 : // handle master pw request!
401 : // master pw request is never
402 : // solvable without UI!
403 0 : this ) )
404 : {
405 : // successfully handled
406 0 : xSupplyAuthentication->select();
407 0 : return true;
408 : }
409 0 : return false;
410 : }
411 :
412 :
413 :
414 : // Service factory implementation.
415 :
416 :
417 :
418 : static uno::Reference< uno::XInterface > SAL_CALL
419 2 : PasswordContainerInteractionHandler_CreateInstance(
420 : const uno::Reference< lang::XMultiServiceFactory> & rSMgr )
421 : throw( uno::Exception )
422 : {
423 : lang::XServiceInfo * pX = static_cast< lang::XServiceInfo * >(
424 2 : new PasswordContainerInteractionHandler( comphelper::getComponentContext(rSMgr) ) );
425 2 : return uno::Reference< uno::XInterface >::query( pX );
426 : }
427 :
428 :
429 : // static
430 : uno::Reference< lang::XSingleServiceFactory >
431 2 : PasswordContainerInteractionHandler::createServiceFactory(
432 : const uno::Reference< lang::XMultiServiceFactory >& rxServiceMgr )
433 : {
434 : return uno::Reference< lang::XSingleServiceFactory >(
435 : cppu::createOneInstanceFactory(
436 : rxServiceMgr,
437 : PasswordContainerInteractionHandler::getImplementationName_Static(),
438 : PasswordContainerInteractionHandler_CreateInstance,
439 2 : PasswordContainerInteractionHandler::getSupportedServiceNames_Static() ) );
440 : }
441 :
442 : } // namespace uui
443 :
444 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|