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 //========================================================================= 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 //========================================================================= 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 //========================================================================= 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 //========================================================================= 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 314 PasswordContainerInteractionHandler::PasswordContainerInteractionHandler( 315 const uno::Reference< lang::XMultiServiceFactory >& xSMgr ) 316 : m_aPwContainerHelper( xSMgr ) 317 { 318 } 319 320 //========================================================================= 321 // virtual 322 PasswordContainerInteractionHandler::~PasswordContainerInteractionHandler() 323 { 324 } 325 326 //========================================================================= 327 // 328 // XServiceInfo methods. 329 // 330 //========================================================================= 331 332 // virtual 333 ::rtl::OUString SAL_CALL 334 PasswordContainerInteractionHandler::getImplementationName() 335 throw ( uno::RuntimeException ) 336 { 337 return getImplementationName_Static(); 338 } 339 340 //========================================================================= 341 // virtual 342 sal_Bool SAL_CALL 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 360 PasswordContainerInteractionHandler::getSupportedServiceNames() 361 throw ( uno::RuntimeException ) 362 { 363 return getSupportedServiceNames_Static(); 364 } 365 366 //========================================================================= 367 // static 368 rtl::OUString 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 > 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 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 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 > 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