blob: 28cb29cd66f4fc853cd6bdce467fa13f00e1e65c [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
#include "cppuhelper/factory.hxx"
#include "com/sun/star/lang/XMultiServiceFactory.hpp"
#include "com/sun/star/task/NoMasterException.hpp"
#include "com/sun/star/task/XInteractionHandler.hpp"
#include "com/sun/star/task/XMasterPasswordHandling.hpp"
#include "com/sun/star/task/XPasswordContainer.hpp"
#include "com/sun/star/task/XUrlContainer.hpp"
#include "com/sun/star/ucb/AuthenticationRequest.hpp"
#include "com/sun/star/ucb/URLAuthenticationRequest.hpp"
#include "com/sun/star/ucb/XInteractionSupplyAuthentication.hpp"
#include "com/sun/star/ucb/XInteractionSupplyAuthentication2.hpp"
#include "passwordcontainer.hxx"
using namespace com::sun::star;
namespace {
//=========================================================================
bool 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 )
{
if ( bUseSystemCredentials )
{
// "use system creds" record found.
// Wants client that we use it?
if ( xSupplyAuthentication2.is() && bCanUseSystemCredentials )
{
xSupplyAuthentication2->setUseSystemCredentials( sal_True );
return true;
}
return false;
}
else if (aRec.UserList.getLength() != 0)
{
if (aRec.UserList[0].Passwords.getLength() == 0)
{
// Password sequence can be empty, for instance if master
// password was not given (e.g. master pw dialog canceled)
// pw container does not throw NoMasterException in this case.
// bug???
return false;
}
// "user/pass" record found.
if (!bCheckForEqualPasswords || !rRequest.HasPassword
|| rRequest.Password != aRec.UserList[0].Passwords[0]) // failed login attempt?
{
if (xSupplyAuthentication->canSetUserName())
xSupplyAuthentication->
setUserName(aRec.UserList[0].UserName.getStr());
if (xSupplyAuthentication->canSetPassword())
xSupplyAuthentication->
setPassword(aRec.UserList[0].Passwords[0].getStr());
if (aRec.UserList[0].Passwords.getLength() > 1)
{
if (rRequest.HasRealm)
{
if (xSupplyAuthentication->canSetRealm())
xSupplyAuthentication->
setRealm(aRec.UserList[0].Passwords[1].
getStr());
}
else if (xSupplyAuthentication->canSetAccount())
xSupplyAuthentication->
setAccount(aRec.UserList[0].Passwords[1].
getStr());
}
if ( xSupplyAuthentication2.is() && bCanUseSystemCredentials )
xSupplyAuthentication2->setUseSystemCredentials( sal_False );
return true;
}
}
return false;
}
} // namespace
namespace uui {
//=========================================================================
PasswordContainerHelper::PasswordContainerHelper(
uno::Reference< lang::XMultiServiceFactory > const & xServiceFactory )
{
OSL_ENSURE(xServiceFactory.is(), "no service factory given!");
if (xServiceFactory.is())
try
{
m_xPasswordContainer
= uno::Reference< task::XPasswordContainer >(
xServiceFactory->
createInstance(
rtl::OUString(
RTL_CONSTASCII_USTRINGPARAM(
"com.sun.star.task.PasswordContainer"))),
uno::UNO_QUERY);
}
catch (uno::Exception const &)
{}
OSL_ENSURE(m_xPasswordContainer.is(),
"unable to instanciate password container service");
}
//=========================================================================
bool PasswordContainerHelper::handleAuthenticationRequest(
ucb::AuthenticationRequest const & rRequest,
uno::Reference< ucb::XInteractionSupplyAuthentication > const &
xSupplyAuthentication,
rtl::OUString const & rURL,
uno::Reference< task::XInteractionHandler > const & xIH )
SAL_THROW((uno::RuntimeException))
{
// Is continuation even a XInteractionSupplyAuthentication2, which
// is derived from XInteractionSupplyAuthentication?
uno::Reference< ucb::XInteractionSupplyAuthentication2 >
xSupplyAuthentication2(xSupplyAuthentication, uno::UNO_QUERY);
sal_Bool bCanUseSystemCredentials = sal_False;
if (xSupplyAuthentication2.is())
{
sal_Bool bDefaultUseSystemCredentials;
bCanUseSystemCredentials
= xSupplyAuthentication2->canUseSystemCredentials(
bDefaultUseSystemCredentials );
}
uno::Reference< task::XPasswordContainer > xContainer(
m_xPasswordContainer );
uno::Reference< task::XUrlContainer > xUrlContainer(
m_xPasswordContainer, uno::UNO_QUERY );
OSL_ENSURE( xUrlContainer.is(), "Got no XUrlContainer!" );
if ( !xContainer.is() || !xUrlContainer.is() )
return false;
if ( bCanUseSystemCredentials )
{
// Runtime / Persistent info avail for current auth request?
rtl::OUString aResult = xUrlContainer->findUrl(
rURL.getLength() ? rURL : rRequest.ServerName );
if ( aResult.getLength() > 0 )
{
if ( fillContinuation( true,
rRequest,
task::UrlRecord(),
xSupplyAuthentication,
xSupplyAuthentication2,
bCanUseSystemCredentials,
false ) )
{
return true;
}
}
}
// xContainer works with userName passwdSequences pairs:
if (rRequest.HasUserName && rRequest.HasPassword)
{
try
{
if (rRequest.UserName.getLength() == 0)
{
task::UrlRecord aRec;
if ( rURL.getLength() )
aRec = xContainer->find(rURL, xIH);
if ( aRec.UserList.getLength() == 0 )
{
// compat: try server name.
aRec = xContainer->find(rRequest.ServerName, xIH);
}
if ( fillContinuation( false,
rRequest,
aRec,
xSupplyAuthentication,
xSupplyAuthentication2,
bCanUseSystemCredentials,
false ) )
{
return true;
}
}
else
{
task::UrlRecord aRec;
if ( rURL.getLength() )
aRec = xContainer->findForName(
rURL, rRequest.UserName, xIH);
if ( aRec.UserList.getLength() == 0 )
{
// compat: try server name.
aRec = xContainer->findForName(
rRequest.ServerName, rRequest.UserName, xIH);
}
if ( fillContinuation( false,
rRequest,
aRec,
xSupplyAuthentication,
xSupplyAuthentication2,
bCanUseSystemCredentials,
true ) )
{
return true;
}
}
}
catch (task::NoMasterException const &)
{} // user did not enter master password
}
return false;
}
//=========================================================================
bool PasswordContainerHelper::addRecord(
rtl::OUString const & rURL,
rtl::OUString const & rUsername,
uno::Sequence< rtl::OUString > const & rPasswords,
uno::Reference< task::XInteractionHandler > const & xIH,
bool bPersist )
SAL_THROW((uno::RuntimeException))
{
try
{
if ( rUsername.getLength() )
{
OSL_ENSURE( m_xPasswordContainer.is(),
"Got no XPasswordContainer!" );
if ( !m_xPasswordContainer.is() )
return false;
if ( bPersist )
{
uno::Reference< task::XMasterPasswordHandling > xMPH(
m_xPasswordContainer, uno::UNO_QUERY_THROW );
// If persistent storing of passwords is not yet
// allowed, enable it.
if ( !xMPH->isPersistentStoringAllowed() )
xMPH->allowPersistentStoring( sal_True );
m_xPasswordContainer->addPersistent( rURL,
rUsername,
rPasswords,
xIH );
}
else
m_xPasswordContainer->add( rURL,
rUsername,
rPasswords,
xIH );
}
else
{
uno::Reference< task::XUrlContainer >
xContainer( m_xPasswordContainer, uno::UNO_QUERY );
OSL_ENSURE( xContainer.is(), "Got no XUrlContainer!" );
if ( !xContainer.is() )
return false;
xContainer->addUrl( rURL, bPersist );
}
}
catch ( task::NoMasterException const & )
{
// user did not enter master password
return false;
}
return true;
}
//=========================================================================
//=========================================================================
//=========================================================================
PasswordContainerInteractionHandler::PasswordContainerInteractionHandler(
const uno::Reference< lang::XMultiServiceFactory >& xSMgr )
: m_aPwContainerHelper( xSMgr )
{
}
//=========================================================================
// virtual
PasswordContainerInteractionHandler::~PasswordContainerInteractionHandler()
{
}
//=========================================================================
//
// XServiceInfo methods.
//
//=========================================================================
// virtual
::rtl::OUString SAL_CALL
PasswordContainerInteractionHandler::getImplementationName()
throw ( uno::RuntimeException )
{
return getImplementationName_Static();
}
//=========================================================================
// virtual
sal_Bool SAL_CALL
PasswordContainerInteractionHandler::supportsService(
const ::rtl::OUString& ServiceName )
throw ( uno::RuntimeException )
{
uno::Sequence< rtl::OUString > aSNL = getSupportedServiceNames();
const rtl::OUString * pArray = aSNL.getConstArray();
for ( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
{
if ( pArray[ i ] == ServiceName )
return sal_True;
}
return sal_False;
}
//=========================================================================
// virtual
uno::Sequence< ::rtl::OUString > SAL_CALL
PasswordContainerInteractionHandler::getSupportedServiceNames()
throw ( uno::RuntimeException )
{
return getSupportedServiceNames_Static();
}
//=========================================================================
// static
rtl::OUString
PasswordContainerInteractionHandler::getImplementationName_Static()
{
return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
"com.sun.star.comp.uui.PasswordContainerInteractionHandler" ) );
}
//=========================================================================
// static
uno::Sequence< rtl::OUString >
PasswordContainerInteractionHandler::getSupportedServiceNames_Static()
{
uno::Sequence< rtl::OUString > aSNS( 1 );
aSNS.getArray()[ 0 ]
= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(
"com.sun.star.task.PasswordContainerInteractionHandler" ) );
return aSNS;
}
//=========================================================================
//
// XInteractionHandler methods.
//
//=========================================================================
// virtual
void SAL_CALL
PasswordContainerInteractionHandler::handle(
const uno::Reference< task::XInteractionRequest >& rRequest )
throw ( uno::RuntimeException )
{
if ( !rRequest.is() )
return;
uno::Any aAnyRequest( rRequest->getRequest() );
ucb::AuthenticationRequest aAuthenticationRequest;
if ( !( aAnyRequest >>= aAuthenticationRequest ) )
return;
rtl::OUString aURL;
ucb::URLAuthenticationRequest aURLAuthenticationRequest;
if ( aAnyRequest >>= aURLAuthenticationRequest )
aURL = aURLAuthenticationRequest.URL;
uno::Sequence< uno::Reference< task::XInteractionContinuation > >
rContinuations = rRequest->getContinuations();
uno::Reference< ucb::XInteractionSupplyAuthentication >
xSupplyAuthentication;
for ( sal_Int32 i = 0; i < rContinuations.getLength(); ++i )
{
xSupplyAuthentication
= uno::Reference< ucb::XInteractionSupplyAuthentication >(
rContinuations[i], uno::UNO_QUERY );
if( xSupplyAuthentication.is() )
break;
}
if ( !xSupplyAuthentication.is() )
return;
// Try to obatin credentials from password container.
if ( m_aPwContainerHelper.
handleAuthenticationRequest( aAuthenticationRequest,
xSupplyAuthentication,
aURL,
// @@@ FIXME: this not able to
// handle master pw request!
// master pw request is never
// solvable without UI!
this ) )
{
// successfully handled
xSupplyAuthentication->select();
}
}
//=========================================================================
//
// Service factory implementation.
//
//=========================================================================
static uno::Reference< uno::XInterface > SAL_CALL
PasswordContainerInteractionHandler_CreateInstance(
const uno::Reference< lang::XMultiServiceFactory> & rSMgr )
throw( uno::Exception )
{
lang::XServiceInfo * pX = static_cast< lang::XServiceInfo * >(
new PasswordContainerInteractionHandler( rSMgr ) );
return uno::Reference< uno::XInterface >::query( pX );
}
//=========================================================================
// static
uno::Reference< lang::XSingleServiceFactory >
PasswordContainerInteractionHandler::createServiceFactory(
const uno::Reference< lang::XMultiServiceFactory >& rxServiceMgr )
{
return uno::Reference< lang::XSingleServiceFactory >(
cppu::createOneInstanceFactory(
rxServiceMgr,
PasswordContainerInteractionHandler::getImplementationName_Static(),
PasswordContainerInteractionHandler_CreateInstance,
PasswordContainerInteractionHandler::getSupportedServiceNames_Static() ) );
}
} // namespace uui