1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #include "cppuhelper/factory.hxx"
25
26 #include "com/sun/star/lang/XMultiServiceFactory.hpp"
27 #include "com/sun/star/task/NoMasterException.hpp"
28 #include "com/sun/star/task/XInteractionHandler.hpp"
29 #include "com/sun/star/task/XMasterPasswordHandling.hpp"
30 #include "com/sun/star/task/XPasswordContainer.hpp"
31 #include "com/sun/star/task/XUrlContainer.hpp"
32 #include "com/sun/star/ucb/AuthenticationRequest.hpp"
33 #include "com/sun/star/ucb/URLAuthenticationRequest.hpp"
34 #include "com/sun/star/ucb/XInteractionSupplyAuthentication.hpp"
35 #include "com/sun/star/ucb/XInteractionSupplyAuthentication2.hpp"
36
37 #include "passwordcontainer.hxx"
38
39 using namespace com::sun::star;
40
41 namespace {
42
43 //=========================================================================
fillContinuation(bool bUseSystemCredentials,const ucb::AuthenticationRequest & rRequest,const task::UrlRecord & aRec,const uno::Reference<ucb::XInteractionSupplyAuthentication> & xSupplyAuthentication,const uno::Reference<ucb::XInteractionSupplyAuthentication2> & xSupplyAuthentication2,bool bCanUseSystemCredentials,bool bCheckForEqualPasswords)44 bool fillContinuation(
45 bool bUseSystemCredentials,
46 const ucb::AuthenticationRequest & rRequest,
47 const task::UrlRecord & aRec,
48 const uno::Reference< ucb::XInteractionSupplyAuthentication > &
49 xSupplyAuthentication,
50 const uno::Reference< ucb::XInteractionSupplyAuthentication2 > &
51 xSupplyAuthentication2,
52 bool bCanUseSystemCredentials,
53 bool bCheckForEqualPasswords )
54 {
55 if ( bUseSystemCredentials )
56 {
57 // "use system creds" record found.
58 // Wants client that we use it?
59 if ( xSupplyAuthentication2.is() && bCanUseSystemCredentials )
60 {
61 xSupplyAuthentication2->setUseSystemCredentials( sal_True );
62 return true;
63 }
64 return false;
65 }
66 else if (aRec.UserList.getLength() != 0)
67 {
68 if (aRec.UserList[0].Passwords.getLength() == 0)
69 {
70 // Password sequence can be empty, for instance if master
71 // password was not given (e.g. master pw dialog canceled)
72 // pw container does not throw NoMasterException in this case.
73 // bug???
74 return false;
75 }
76
77 // "user/pass" record found.
78 if (!bCheckForEqualPasswords || !rRequest.HasPassword
79 || rRequest.Password != aRec.UserList[0].Passwords[0]) // failed login attempt?
80 {
81 if (xSupplyAuthentication->canSetUserName())
82 xSupplyAuthentication->
83 setUserName(aRec.UserList[0].UserName.getStr());
84
85 if (xSupplyAuthentication->canSetPassword())
86 xSupplyAuthentication->
87 setPassword(aRec.UserList[0].Passwords[0].getStr());
88 if (aRec.UserList[0].Passwords.getLength() > 1)
89 {
90 if (rRequest.HasRealm)
91 {
92 if (xSupplyAuthentication->canSetRealm())
93 xSupplyAuthentication->
94 setRealm(aRec.UserList[0].Passwords[1].
95 getStr());
96 }
97 else if (xSupplyAuthentication->canSetAccount())
98 xSupplyAuthentication->
99 setAccount(aRec.UserList[0].Passwords[1].
100 getStr());
101 }
102
103 if ( xSupplyAuthentication2.is() && bCanUseSystemCredentials )
104 xSupplyAuthentication2->setUseSystemCredentials( sal_False );
105
106 return true;
107 }
108 }
109 return false;
110 }
111
112 } // namespace
113
114 namespace uui {
115
116 //=========================================================================
PasswordContainerHelper(uno::Reference<lang::XMultiServiceFactory> const & xServiceFactory)117 PasswordContainerHelper::PasswordContainerHelper(
118 uno::Reference< lang::XMultiServiceFactory > const & xServiceFactory )
119 {
120 OSL_ENSURE(xServiceFactory.is(), "no service factory given!");
121 if (xServiceFactory.is())
122 try
123 {
124 m_xPasswordContainer
125 = uno::Reference< task::XPasswordContainer >(
126 xServiceFactory->
127 createInstance(
128 rtl::OUString(
129 RTL_CONSTASCII_USTRINGPARAM(
130 "com.sun.star.task.PasswordContainer"))),
131 uno::UNO_QUERY);
132 }
133 catch (uno::Exception const &)
134 {}
135 OSL_ENSURE(m_xPasswordContainer.is(),
136 "unable to instanciate password container service");
137 }
138
139 //=========================================================================
handleAuthenticationRequest(ucb::AuthenticationRequest const & rRequest,uno::Reference<ucb::XInteractionSupplyAuthentication> const & xSupplyAuthentication,rtl::OUString const & rURL,uno::Reference<task::XInteractionHandler> const & xIH)140 bool PasswordContainerHelper::handleAuthenticationRequest(
141 ucb::AuthenticationRequest const & rRequest,
142 uno::Reference< ucb::XInteractionSupplyAuthentication > const &
143 xSupplyAuthentication,
144 rtl::OUString const & rURL,
145 uno::Reference< task::XInteractionHandler > const & xIH )
146 SAL_THROW((uno::RuntimeException))
147 {
148 // Is continuation even a XInteractionSupplyAuthentication2, which
149 // is derived from XInteractionSupplyAuthentication?
150 uno::Reference< ucb::XInteractionSupplyAuthentication2 >
151 xSupplyAuthentication2(xSupplyAuthentication, uno::UNO_QUERY);
152
153 sal_Bool bCanUseSystemCredentials = sal_False;
154 if (xSupplyAuthentication2.is())
155 {
156 sal_Bool bDefaultUseSystemCredentials;
157 bCanUseSystemCredentials
158 = xSupplyAuthentication2->canUseSystemCredentials(
159 bDefaultUseSystemCredentials );
160 }
161
162 uno::Reference< task::XPasswordContainer > xContainer(
163 m_xPasswordContainer );
164 uno::Reference< task::XUrlContainer > xUrlContainer(
165 m_xPasswordContainer, uno::UNO_QUERY );
166 OSL_ENSURE( xUrlContainer.is(), "Got no XUrlContainer!" );
167
168 if ( !xContainer.is() || !xUrlContainer.is() )
169 return false;
170
171 if ( bCanUseSystemCredentials )
172 {
173 // Runtime / Persistent info avail for current auth request?
174
175 rtl::OUString aResult = xUrlContainer->findUrl(
176 rURL.getLength() ? rURL : rRequest.ServerName );
177 if ( aResult.getLength() > 0 )
178 {
179 if ( fillContinuation( true,
180 rRequest,
181 task::UrlRecord(),
182 xSupplyAuthentication,
183 xSupplyAuthentication2,
184 bCanUseSystemCredentials,
185 false ) )
186 {
187 return true;
188 }
189 }
190 }
191
192 // xContainer works with userName passwdSequences pairs:
193 if (rRequest.HasUserName && rRequest.HasPassword)
194 {
195 try
196 {
197 if (rRequest.UserName.getLength() == 0)
198 {
199 task::UrlRecord aRec;
200 if ( rURL.getLength() )
201 aRec = xContainer->find(rURL, xIH);
202
203 if ( aRec.UserList.getLength() == 0 )
204 {
205 // compat: try server name.
206 aRec = xContainer->find(rRequest.ServerName, xIH);
207 }
208
209 if ( fillContinuation( false,
210 rRequest,
211 aRec,
212 xSupplyAuthentication,
213 xSupplyAuthentication2,
214 bCanUseSystemCredentials,
215 false ) )
216 {
217 return true;
218 }
219 }
220 else
221 {
222 task::UrlRecord aRec;
223 if ( rURL.getLength() )
224 aRec = xContainer->findForName(
225 rURL, rRequest.UserName, xIH);
226
227 if ( aRec.UserList.getLength() == 0 )
228 {
229 // compat: try server name.
230 aRec = xContainer->findForName(
231 rRequest.ServerName, rRequest.UserName, xIH);
232 }
233
234 if ( fillContinuation( false,
235 rRequest,
236 aRec,
237 xSupplyAuthentication,
238 xSupplyAuthentication2,
239 bCanUseSystemCredentials,
240 true ) )
241 {
242 return true;
243 }
244 }
245 }
246 catch (task::NoMasterException const &)
247 {} // user did not enter master password
248 }
249 return false;
250 }
251
252 //=========================================================================
addRecord(rtl::OUString const & rURL,rtl::OUString const & rUsername,uno::Sequence<rtl::OUString> const & rPasswords,uno::Reference<task::XInteractionHandler> const & xIH,bool bPersist)253 bool PasswordContainerHelper::addRecord(
254 rtl::OUString const & rURL,
255 rtl::OUString const & rUsername,
256 uno::Sequence< rtl::OUString > const & rPasswords,
257 uno::Reference< task::XInteractionHandler > const & xIH,
258 bool bPersist )
259 SAL_THROW((uno::RuntimeException))
260 {
261 try
262 {
263 if ( rUsername.getLength() )
264 {
265 OSL_ENSURE( m_xPasswordContainer.is(),
266 "Got no XPasswordContainer!" );
267 if ( !m_xPasswordContainer.is() )
268 return false;
269
270 if ( bPersist )
271 {
272 uno::Reference< task::XMasterPasswordHandling > xMPH(
273 m_xPasswordContainer, uno::UNO_QUERY_THROW );
274
275 // If persistent storing of passwords is not yet
276 // allowed, enable it.
277 if ( !xMPH->isPersistentStoringAllowed() )
278 xMPH->allowPersistentStoring( sal_True );
279
280 m_xPasswordContainer->addPersistent( rURL,
281 rUsername,
282 rPasswords,
283 xIH );
284 }
285 else
286 m_xPasswordContainer->add( rURL,
287 rUsername,
288 rPasswords,
289 xIH );
290 }
291 else
292 {
293 uno::Reference< task::XUrlContainer >
294 xContainer( m_xPasswordContainer, uno::UNO_QUERY );
295 OSL_ENSURE( xContainer.is(), "Got no XUrlContainer!" );
296 if ( !xContainer.is() )
297 return false;
298
299 xContainer->addUrl( rURL, bPersist );
300 }
301 }
302 catch ( task::NoMasterException const & )
303 {
304 // user did not enter master password
305 return false;
306 }
307 return true;
308 }
309
310 //=========================================================================
311 //=========================================================================
312 //=========================================================================
313
PasswordContainerInteractionHandler(const uno::Reference<lang::XMultiServiceFactory> & xSMgr)314 PasswordContainerInteractionHandler::PasswordContainerInteractionHandler(
315 const uno::Reference< lang::XMultiServiceFactory >& xSMgr )
316 : m_aPwContainerHelper( xSMgr )
317 {
318 }
319
320 //=========================================================================
321 // virtual
~PasswordContainerInteractionHandler()322 PasswordContainerInteractionHandler::~PasswordContainerInteractionHandler()
323 {
324 }
325
326 //=========================================================================
327 //
328 // XServiceInfo methods.
329 //
330 //=========================================================================
331
332 // virtual
333 ::rtl::OUString SAL_CALL
getImplementationName()334 PasswordContainerInteractionHandler::getImplementationName()
335 throw ( uno::RuntimeException )
336 {
337 return getImplementationName_Static();
338 }
339
340 //=========================================================================
341 // virtual
342 sal_Bool SAL_CALL
supportsService(const::rtl::OUString & ServiceName)343 PasswordContainerInteractionHandler::supportsService(
344 const ::rtl::OUString& ServiceName )
345 throw ( uno::RuntimeException )
346 {
347 uno::Sequence< rtl::OUString > aSNL = getSupportedServiceNames();
348 const rtl::OUString * pArray = aSNL.getConstArray();
349 for ( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
350 {
351 if ( pArray[ i ] == ServiceName )
352 return sal_True;
353 }
354 return sal_False;
355 }
356
357 //=========================================================================
358 // virtual
359 uno::Sequence< ::rtl::OUString > SAL_CALL
getSupportedServiceNames()360 PasswordContainerInteractionHandler::getSupportedServiceNames()
361 throw ( uno::RuntimeException )
362 {
363 return getSupportedServiceNames_Static();
364 }
365
366 //=========================================================================
367 // static
368 rtl::OUString
getImplementationName_Static()369 PasswordContainerInteractionHandler::getImplementationName_Static()
370 {
371 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
372 "com.sun.star.comp.uui.PasswordContainerInteractionHandler" ) );
373 }
374
375 //=========================================================================
376 // static
377 uno::Sequence< rtl::OUString >
getSupportedServiceNames_Static()378 PasswordContainerInteractionHandler::getSupportedServiceNames_Static()
379 {
380 uno::Sequence< rtl::OUString > aSNS( 1 );
381 aSNS.getArray()[ 0 ]
382 = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
383 "com.sun.star.task.PasswordContainerInteractionHandler" ) );
384 return aSNS;
385 }
386
387 //=========================================================================
388 //
389 // XInteractionHandler methods.
390 //
391 //=========================================================================
392
393 // virtual
394 void SAL_CALL
handle(const uno::Reference<task::XInteractionRequest> & rRequest)395 PasswordContainerInteractionHandler::handle(
396 const uno::Reference< task::XInteractionRequest >& rRequest )
397 throw ( uno::RuntimeException )
398 {
399 if ( !rRequest.is() )
400 return;
401
402 uno::Any aAnyRequest( rRequest->getRequest() );
403
404 ucb::AuthenticationRequest aAuthenticationRequest;
405 if ( !( aAnyRequest >>= aAuthenticationRequest ) )
406 return;
407
408 rtl::OUString aURL;
409 ucb::URLAuthenticationRequest aURLAuthenticationRequest;
410 if ( aAnyRequest >>= aURLAuthenticationRequest )
411 aURL = aURLAuthenticationRequest.URL;
412
413 uno::Sequence< uno::Reference< task::XInteractionContinuation > >
414 rContinuations = rRequest->getContinuations();
415
416 uno::Reference< ucb::XInteractionSupplyAuthentication >
417 xSupplyAuthentication;
418
419 for ( sal_Int32 i = 0; i < rContinuations.getLength(); ++i )
420 {
421 xSupplyAuthentication
422 = uno::Reference< ucb::XInteractionSupplyAuthentication >(
423 rContinuations[i], uno::UNO_QUERY );
424 if( xSupplyAuthentication.is() )
425 break;
426 }
427
428 if ( !xSupplyAuthentication.is() )
429 return;
430
431 // Try to obatin credentials from password container.
432 if ( m_aPwContainerHelper.
433 handleAuthenticationRequest( aAuthenticationRequest,
434 xSupplyAuthentication,
435 aURL,
436 // @@@ FIXME: this not able to
437 // handle master pw request!
438 // master pw request is never
439 // solvable without UI!
440 this ) )
441 {
442 // successfully handled
443 xSupplyAuthentication->select();
444 }
445 }
446
447 //=========================================================================
448 //
449 // Service factory implementation.
450 //
451 //=========================================================================
452
453 static uno::Reference< uno::XInterface > SAL_CALL
PasswordContainerInteractionHandler_CreateInstance(const uno::Reference<lang::XMultiServiceFactory> & rSMgr)454 PasswordContainerInteractionHandler_CreateInstance(
455 const uno::Reference< lang::XMultiServiceFactory> & rSMgr )
456 throw( uno::Exception )
457 {
458 lang::XServiceInfo * pX = static_cast< lang::XServiceInfo * >(
459 new PasswordContainerInteractionHandler( rSMgr ) );
460 return uno::Reference< uno::XInterface >::query( pX );
461 }
462
463 //=========================================================================
464 // static
465 uno::Reference< lang::XSingleServiceFactory >
createServiceFactory(const uno::Reference<lang::XMultiServiceFactory> & rxServiceMgr)466 PasswordContainerInteractionHandler::createServiceFactory(
467 const uno::Reference< lang::XMultiServiceFactory >& rxServiceMgr )
468 {
469 return uno::Reference< lang::XSingleServiceFactory >(
470 cppu::createOneInstanceFactory(
471 rxServiceMgr,
472 PasswordContainerInteractionHandler::getImplementationName_Static(),
473 PasswordContainerInteractionHandler_CreateInstance,
474 PasswordContainerInteractionHandler::getSupportedServiceNames_Static() ) );
475 }
476
477 } // namespace uui
478