bluetooth/btstack/common/btsap.cpp
changeset 0 29b1cd4cb562
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetooth/btstack/common/btsap.cpp	Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,290 @@
+// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// The base class for Bluetooth Saps
+// 
+//
+
+#include <es_prot.h>
+#include "BtSap.h"
+#include "secman.h"
+#include "codman.h"
+
+#include "BTSec.h"
+
+//Diagnostic string for security check failures, in builds without platsec
+//diagnostics this will be NULL.
+const char* const KBT_SAP_NAME_DIAG = __PLATSEC_DIAGNOSTIC_STRING("Bluetooth SAP");
+
+CBluetoothSAP::CBluetoothSAP(CBTSecMan& aSecMan, CBTCodServiceMan& aCodMan)
+: iSecMan(aSecMan), iCodMan(aCodMan)
+	{
+	}
+
+void CBluetoothSAP::ConstructL()
+	{
+	TCallBack accessDenied(AccessDeniedCallBack, this);
+	iAccessDeniedCallBack = new(ELeave) CAsyncCallBack(accessDenied, CActive::EPriorityStandard);
+	}
+
+TInt CBluetoothSAP::SetDeviceOverride(const TDesC8& aOption)
+/**
+	Provides for overriding of the general *service* security
+	for given devices.
+
+**/
+	{
+	if (aOption.Length() != sizeof(TBTServiceSecurityPerDevice))
+		{
+		return KErrArgument;
+		}
+
+	TBTServiceSecurityPerDevice override =
+		*reinterpret_cast<const TBTServiceSecurityPerDevice*>(aOption.Ptr());
+
+	// add this device into the array of overrides for this SAP
+	// if device is in the list, replace the entry
+	for (TInt i=0; i<=iDeviceOverrides.Count()-1; i++)
+		{
+		if (iDeviceOverrides[i].DeviceAddress() == override.DeviceAddress())
+			{
+			// update!
+			iDeviceOverrides[i].SetDeviceSecurity(override.DeviceSecurity());
+			return KErrNone;
+			}
+		}
+	// if here, this is a new entry
+	return iDeviceOverrides.Append(override);
+	}
+	
+TInt CBluetoothSAP::GetDeviceOverride(TDes8& aOption) const
+/**
+	Allows forgetful apps to give us an address, and we'll tell
+	them the overrides for this service for that device.
+*/
+	{
+	if (aOption.Length() != sizeof(TBTServiceSecurityPerDevice))
+		{
+		return KErrArgument;
+		}
+
+	TBTServiceSecurityPerDevice overrideBuf =
+		*reinterpret_cast<const TBTServiceSecurityPerDevice*>(aOption.Ptr());
+
+	const TBTServiceSecurityPerDevice* override = Override(overrideBuf.DeviceAddress());	
+	if (override)
+		{
+		overrideBuf.SetDeviceSecurity(override->DeviceSecurity());
+		aOption = TPtrC8(reinterpret_cast<TUint8*>(&overrideBuf), sizeof(TBTServiceSecurityPerDevice));
+		return KErrNone;
+		}
+	else
+		{
+		return KErrNotFound;
+		}
+	}
+	
+
+CBluetoothSAP::~CBluetoothSAP()
+	{
+	__ASSERT_DEBUG(!(iCodServiceBits & KBTCodBitsRegdFlag), User::Panic(KBTCodPanic, EBTCodBadDeregister));
+	iDeviceOverrides.Close();
+	delete iAccessDeniedCallBack;
+	}
+
+
+const TBTServiceSecurity& CBluetoothSAP::Security() const
+	{
+	return iSecurity;
+	}
+
+const TBTServiceSecurityPerDevice* CBluetoothSAP::Override(const TBTDevAddr& aAddress) const
+	{
+	//look through overrides for a device override
+	for (TInt i=0; i<iDeviceOverrides.Count(); i++)
+		{
+		if (iDeviceOverrides[i].DeviceAddress() == aAddress)
+			{
+			return &iDeviceOverrides[i];
+			}
+		}
+	return NULL;
+	}
+
+void CBluetoothSAP::IoctlComplete(TInt /*aErr*/, TUint /*aLevel*/, TUint /*aName*/, TDesC8* aBuf)
+	{
+	iSocket->IoctlComplete(aBuf);
+	}
+
+
+TInt CBluetoothSAP::SecurityCheck(MProvdSecurityChecker *aSecurityChecker)
+	{
+	__ASSERT_ALWAYS(aSecurityChecker, User::Panic(KSECURITY_PANIC, EBTPanicNullSecurityChecker));
+	
+	iSecurityChecker = aSecurityChecker;
+	return iSecurityChecker->CheckPolicy(KLOCAL_SERVICES, KBT_SAP_NAME_DIAG);
+	}
+
+void CBluetoothSAP::StartAccessRequest(const CBluetoothSAP& aSAPWithSecuritySettings, TBool aSecurityModeFourOutgoing)
+/**
+	Ask secman to do security
+	@param aSAPWithSecuritySettings contains the security details
+	@param aSecurityModeFourOutgoing indicates whether this is a security mode 4 request that comes before
+	a security mode 2 request.  This is to be used for establishing a suitable 
+
+	this SAP has the remote address connecting
+**/
+	{
+	const MAccessRequestResponseHandler& handler = *this;
+	
+	TBTServiceSecurity secReqs(aSAPWithSecuritySettings.Security());
+	if(aSecurityModeFourOutgoing)
+		{
+		// For security mode 4 requests we don't consider the authorisation and any pre-v2.1
+		// security settings.  Note this is only applicable for outgoing access requirements.
+		//So we set a concrete MITM protection value...
+		secReqs.SetAuthentication(secReqs.MitmProtection());
+		// ...then we remove any authorisation, authentication or encryption.
+		secReqs.SetAuthorisation(EFalse);
+		secReqs.SetAuthentication(EFalse);
+		secReqs.SetEncryption(EFalse);
+		}
+	// As a note, using the override as-is is infact safe as none of the override values 
+	// can really affect the security mode 4 aspects.
+
+	TRAPD(err, SecMan().AccessRequestL(secReqs,
+						aSAPWithSecuritySettings.Override(RemoteAddress()),
+						RemoteAddress(),
+						aSecurityModeFourOutgoing ? EGeneralBondingSecurityMode4Outgoing : EGeneralBonding, // We are doing general bonding
+						const_cast<MAccessRequestResponseHandler&>(handler)));
+
+	if (err != KErrNone)
+		{
+		// complete request now...
+		iAccessDeniedCallBack->CallBack();
+		}
+	}
+
+void CBluetoothSAP::CancelAccessRequest()
+	{
+	SecMan().CancelRequest(*this);
+	}
+
+void CBluetoothSAP::AccessRequestComplete(TInt /*aResult*/)
+/**
+	The SAP wasnt expecting security responses
+	Derivers normally would override (and forward to state)
+**/
+	{
+	_LIT(KBTSAPPanic, "BTSAP");
+	User::Panic(KBTSAPPanic, EBTSecUnexpectedSecurityResponse);
+	}
+
+/*static*/ TInt CBluetoothSAP::AccessDeniedCallBack(TAny* aBtSap)
+	{
+	CBluetoothSAP* btSap = static_cast<CBluetoothSAP*>(aBtSap);
+	btSap->AccessRequestComplete(EBTSecManAccessDenied);
+	return KErrNone;
+	}
+
+
+TInt CBluetoothSAP::SetCodServiceBits(TUint16 aNewCodServiceBits)
+/**
+	Allow SetOpts to set Service bits. These are written to the CoD
+	when the SAP becomes active.
+**/
+	{
+	TInt err = KErrNone;
+	if (aNewCodServiceBits & (~KBTCodValidServiceBits))
+		{
+		err = KErrArgument;		// SetOpt is attempting to set illegal bits
+		}
+	else
+		{
+		if (iCodServiceBits & KBTCodBitsRegdFlag)
+			{
+			err = KErrAlreadyExists; // This SAP has Service bits already registered
+			}
+		else
+			{
+			iCodServiceBits = aNewCodServiceBits; // These can be overwritten at this stage
+			}
+		}
+	return err;
+	}
+
+	
+void CBluetoothSAP::RegisterCodService()
+/**
+	Allows SAPs to register their Service(s)
+**/
+	{
+	if (iCodServiceBits && !(iCodServiceBits & KBTCodBitsRegdFlag))
+		{
+		// Only send to CodMan once
+		CodMan().RegisterCodService(iCodServiceBits);
+		}
+// Set the regd flag, even if no service bits, this will ensure that late SetOpts are errored
+	iCodServiceBits |= KBTCodBitsRegdFlag;
+	}
+
+
+void CBluetoothSAP::DeregisterCodService()
+/**
+	Allows SAPs to clear their Service bits
+**/
+	{
+	if (iCodServiceBits && (iCodServiceBits & KBTCodBitsRegdFlag))
+		{
+		iCodServiceBits &= (~KBTCodBitsRegdFlag);	// reset the registered flag, don't want to confuse CodMan
+		CodMan().RemoveCodService(iCodServiceBits);
+		}
+	iCodServiceBits = 0;	// tidy up these service bits + regd flag
+	}
+
+
+TInt CBluetoothSAP::SetOption(TUint aLevel,TUint aName,const TDesC8 &aOption)
+/**
+	This is now the default SetOpt handler for SAP protocols.
+	Common attributes are processed here and the protocol dependent SetOpts are passed on.
+**/
+	{
+	TInt rerr = KErrNone;
+	if(aLevel == KSolBtSAPBase)
+		{
+		switch (aName)
+			{
+			case KBTRegisterCodService:
+				{
+				if (aOption.Length() != sizeof(TDesC8))
+					return KErrArgument;
+				
+		        TUint16 newServiceBits = *reinterpret_cast<const TUint16*>(aOption.Ptr());
+				rerr = SetCodServiceBits(newServiceBits);	// The service bits are saved and then registered when SAP becomes live
+				}
+				break;	
+
+			default:
+				// Unhandled SetOpt name
+				rerr = KErrNotSupported;
+				break;
+			}
+		}
+	else
+		{
+		// Process SAP SetOpts
+		rerr = SAPSetOption(aLevel, aName, aOption);
+		}
+		
+	return rerr;
+	}