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