bluetooth/btstack/common/secman.cpp
changeset 0 29b1cd4cb562
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include <bluetooth/logger.h>
       
    17 #include "secman.h"
       
    18 #include "hostresolver.h"
       
    19 #ifdef BT_LINKMGR_V2
       
    20 #include "physicallinks.h"
       
    21 #include "physicallinksmanager.h"
       
    22 #else
       
    23 #include "PhysicalLinks.h"
       
    24 #include "PhysicalLinksManager.h"
       
    25 #endif
       
    26 
       
    27 #ifdef __FLOG_ACTIVE
       
    28 _LIT8(KLogComponent, LOG_COMPONENT_SECMAN);
       
    29 #endif
       
    30 
       
    31 #ifdef _DEBUG
       
    32 PANICCATEGORY("secman");
       
    33 #endif
       
    34 
       
    35 #pragma warning (disable: 4355) //'this' in base init list - is OK for our usage
       
    36 
       
    37 static const TInt KBTSecManAccessRequesterArrayGranularity = 4;
       
    38 static const TInt KBTSecManNotifierRequesterArrayGranularity = 4;
       
    39 
       
    40 
       
    41 //------------------------------------------------------------------------//
       
    42 //class CBTSecMan
       
    43 //------------------------------------------------------------------------//
       
    44 void Panic(TBTSecPanic aPanic)
       
    45 	{
       
    46 	LOG_FUNC
       
    47 	User::Panic(KBTSecPanic, aPanic);
       
    48 	}
       
    49 
       
    50 CBTSecMan* CBTSecMan::NewL()
       
    51 	{
       
    52 	LOG_FUNC
       
    53 	CBTSecMan* self = CBTSecMan::NewLC();
       
    54 	CleanupStack::Pop();	//self
       
    55 	return self;
       
    56 	}
       
    57 
       
    58 CBTSecMan* CBTSecMan::NewLC()
       
    59 	{
       
    60 	LOG_FUNC
       
    61 	CBTSecMan* self = new(ELeave) CBTSecMan();
       
    62 	CleanupStack::PushL(self);
       
    63 	self->ConstructL();
       
    64 	return self;
       
    65 	}
       
    66 
       
    67 CBTSecMan::CBTSecMan()
       
    68 	: iAccessRequesters(KBTSecManAccessRequesterArrayGranularity),
       
    69 	  iNotifierRequesters(KBTSecManNotifierRequesterArrayGranularity)
       
    70 	{
       
    71 	LOG_FUNC
       
    72 	}
       
    73 
       
    74 void CBTSecMan::ConstructL()
       
    75 	{
       
    76 	LOG_FUNC
       
    77 	}
       
    78 
       
    79 void CBTSecMan::SetPhysicalLinksMgr(const CPhysicalLinksManager& aConnectionsMgr)
       
    80 	{
       
    81 	LOG_FUNC
       
    82 	iPhysicalLinksManager = &const_cast<CPhysicalLinksManager&>(aConnectionsMgr);
       
    83 	}
       
    84 
       
    85 CPhysicalLinksManager& CBTSecMan::ConnectionsManager() const
       
    86 	{
       
    87 	LOG_FUNC
       
    88 	return *iPhysicalLinksManager;
       
    89 	}
       
    90 
       
    91 
       
    92 CBTSecMan::~CBTSecMan()
       
    93 	{
       
    94 	LOG_FUNC
       
    95 
       
    96 	iAccessRequesters.ResetAndDestroy();
       
    97 	iAccessRequesters.Close();
       
    98 
       
    99 	iNotifierRequesters.ResetAndDestroy();
       
   100 	iNotifierRequesters.Close();
       
   101 	}
       
   102 
       
   103 void CBTSecMan::AccessRequestL(const TBTServiceSecurity& aSecurity,
       
   104 							   const TBTServiceSecurityPerDevice* const aOverride,
       
   105 							   const TBTDevAddr& aBDAddr,
       
   106 							   MAccessRequestResponseHandler& aRequester)
       
   107 /**
       
   108 Handle an access request...
       
   109 Create a new CBTAccessRequester object to handle the request.
       
   110 **/
       
   111 	{
       
   112 	LOG_FUNC
       
   113 	// find the baseband this SAP is running on
       
   114 	CPhysicalLink& con = *iPhysicalLinksManager->FindPhysicalLink(aBDAddr);
       
   115 	CBTAccessRequester* p = CBTAccessRequester::NewLC(con, aSecurity,
       
   116 													  aOverride,
       
   117 													  aRequester,
       
   118 													  *this);
       
   119 	User::LeaveIfError(iAccessRequesters.Append(p));
       
   120 	CleanupStack::Pop(); //clean up of p now handled by iAccessRequesters
       
   121 	// Try to start- it may not happen (depends on if device retreived from registry
       
   122 	p->DoRequest();
       
   123 	
       
   124 	}
       
   125 
       
   126 void CBTSecMan::CancelRequest(MAccessRequestResponseHandler& aRequester)
       
   127 	{
       
   128 	LOG_FUNC
       
   129 	// search through access requesters to find correct one
       
   130 	LOG1(_L("sec\tCBTSecMan::CancelRequest from SAP 0x%08x"), &aRequester)
       
   131 	TInt count = iAccessRequesters.Count();
       
   132 
       
   133 	for (TInt i=(count-1); i>=0; i--)
       
   134 		{
       
   135 		CBTAccessRequester* requester = iAccessRequesters[i];
       
   136 		if(&requester->ServiceRequester() == &aRequester)
       
   137 			{
       
   138 			// should assert that aRequester is the same as in AccessRequester?
       
   139 			LOG(_L("sec\tRemoving AccessRequester..."))
       
   140 			iAccessRequesters.Remove(i);
       
   141 			delete requester;
       
   142 			break;
       
   143 			}
       
   144 		}
       
   145 	}
       
   146 	
       
   147 void CBTSecMan::GetPassKeyLengthAndOriginator(const TBTDevAddr& aAddr, TUint& aPasskeyMinLength,
       
   148 				   	   					      TBool& aLocallyInitiatedAuthentication)
       
   149 
       
   150 /**
       
   151 If authorisation request was initiated locally it will return true and will
       
   152 return the passkey minimal length requred by user
       
   153 **/
       
   154 	{
       
   155 	LOG_FUNC
       
   156 
       
   157 	TUint tmpPasskeyLength = 0;
       
   158 	TBool locallyInitiated = EFalse;
       
   159 	TInt count = iAccessRequesters.Count();
       
   160 
       
   161 	if (count == 0)
       
   162 		{
       
   163 		aLocallyInitiatedAuthentication = EFalse;
       
   164 		return;
       
   165 		}
       
   166 
       
   167 	// find all pending AccessRequesters for given BTAddr and find maximum of PasskeyMinLength
       
   168 	
       
   169 	for (TInt i=0; i<count;i++)
       
   170 		{
       
   171 		CBTAccessRequester* requester = iAccessRequesters[i];
       
   172 		if (requester->IsAuthenticationReqPending(aAddr, tmpPasskeyLength))
       
   173 			{
       
   174 			locallyInitiated = ETrue;
       
   175 			if (aPasskeyMinLength < tmpPasskeyLength)
       
   176 				{
       
   177 				aPasskeyMinLength = tmpPasskeyLength;
       
   178 				}
       
   179 			}	
       
   180 		}
       
   181 	
       
   182 	aLocallyInitiatedAuthentication = locallyInitiated;		
       
   183 	}
       
   184 	
       
   185 void CBTSecMan::AuthenticationInProgress()
       
   186 /**
       
   187 When authorisation request was sent to HW, HCI will notify SecMan
       
   188 **/
       
   189 	{
       
   190 	LOG_FUNC
       
   191 	
       
   192 	// find first pending AccessRequesters and set AuthenticationInProgress flag
       
   193 	for (TInt i=0; i<iAccessRequesters.Count(); i++)
       
   194 		{
       
   195 		CBTAccessRequester* requester = iAccessRequesters[i];
       
   196 		
       
   197 		if (requester->AuthenticationRequired() && !requester->AuthenticationInProgress())
       
   198 			{
       
   199 			requester->SetAuthenticationInProgress();
       
   200 			break;
       
   201 			}		
       
   202 		}
       
   203 	}
       
   204 
       
   205 void CBTSecMan::AccessRequestComplete(CBTAccessRequester* aAccessRequester, TInt aResult)
       
   206 /**
       
   207 The access request has been fully completed.
       
   208 Delete the CBTAccessRequester that was handling the request.
       
   209 **/
       
   210 	{
       
   211 	LOG_FUNC
       
   212 
       
   213 	TInt count = iAccessRequesters.Count();
       
   214 
       
   215 	ASSERT_DEBUG(count);
       
   216 
       
   217 	// find the originating service *now*
       
   218 	MAccessRequestResponseHandler& service = const_cast<MAccessRequestResponseHandler&>
       
   219 											(aAccessRequester->ServiceRequester());
       
   220 
       
   221 	// clean up the AccessRequester object
       
   222 	TInt i;
       
   223 	for (i=(count-1); i>=0; i--)
       
   224 		{
       
   225 		//find aRequester in iAccessRequesters and delete it
       
   226 		if(iAccessRequesters[i] == aAccessRequester)
       
   227 			{
       
   228 			iAccessRequesters.Remove(i);
       
   229 			delete aAccessRequester;
       
   230 			aAccessRequester = NULL;
       
   231 			break;
       
   232 			}
       
   233 		}
       
   234 	//compress the array if needs be
       
   235 	if ((count!=0) && (i!=count))
       
   236 		{
       
   237 		iAccessRequesters.GranularCompress();
       
   238 		}
       
   239 
       
   240 	// now tell the service
       
   241 	service.AccessRequestComplete(aResult);
       
   242 	}
       
   243 
       
   244 
       
   245 void CBTSecMan::AddNotifierRequestToQueL(CSecNotifierRequester& aRequest)
       
   246 /**
       
   247 Add notifier request to front of queue.  If there are no other requests already in the queue,
       
   248 initiate this request.
       
   249 **/
       
   250 	{
       
   251 	LOG_FUNC
       
   252 	TInt count = iNotifierRequesters.Count();
       
   253 	User::LeaveIfError(iNotifierRequesters.Insert(&aRequest,0));	//add to front of queue since requests are taken from the back
       
   254 	if (count == 0)	//ok since count was calculated before we inserted the new element
       
   255 		{
       
   256 		iActiveNotifierRequester = &aRequest;
       
   257 		aRequest.DoRequest();
       
   258 		}
       
   259 	else
       
   260 		{
       
   261 		LOG(_L("Secman: Request NOT initiated, should start later..."));
       
   262 		}
       
   263 	}
       
   264 
       
   265 void CBTSecMan::RemoveNotifierRequestFromQue(CSecNotifierRequester& aRequest)
       
   266 /**
       
   267 Remove the request from the queue.  If aRequest is the currently active request then we can activate
       
   268 the next one in the queue.  Otherwise, aRequest is being deleted prematurely and we must simply
       
   269 remove it from the array.
       
   270 **/
       
   271 	{
       
   272 	LOG_FUNC
       
   273 	LOG(_L("sec\tCBTSecMan - removing notifier request from queue"));
       
   274 	TInt count = iNotifierRequesters.Count();
       
   275 	TInt found = 0;
       
   276 	for (TInt i=(count-1); i>=0; i--)
       
   277 		{
       
   278 		if (iNotifierRequesters[i] == &aRequest)
       
   279 			{
       
   280 			found++;
       
   281 			iNotifierRequesters.Remove(i);
       
   282 			}
       
   283 		}
       
   284 	__ASSERT_DEBUG(found, User::Panic(KBTSecPanic, EBTSecBadNotifierArray));
       
   285 
       
   286 	if (&aRequest == iActiveNotifierRequester)
       
   287 		{
       
   288 		//start the next request if there is one...
       
   289 		count = iNotifierRequesters.Count();
       
   290 		if (count > 0)
       
   291 			{
       
   292 			LOG(_L("sec\tCBTSecMan - auto-starting next notifier request from queue"));
       
   293 			iActiveNotifierRequester = iNotifierRequesters[count-1];
       
   294 			iActiveNotifierRequester->DoRequest();
       
   295 			}
       
   296 		}
       
   297 	}
       
   298 
       
   299 
       
   300 CSecNotifierRequester::CSecNotifierRequester(CBTSecMan& aSecMan)
       
   301 : CActive(EPriorityStandard),
       
   302   iInquiryMgr(aSecMan.ConnectionsManager().LinkManagerProtocol().InquiryMgr()),
       
   303   iSecMgr(aSecMan)
       
   304 	{
       
   305 	LOG_FUNC
       
   306 	}
       
   307 
       
   308 void CSecNotifierRequester::ConstructL(const TBTDevAddr& aAddr)
       
   309 	{
       
   310 	LOG_FUNC
       
   311 	User::LeaveIfError(iNotifier.Connect());
       
   312 
       
   313 	// find the name at this stage for this device - may not be there yet
       
   314 	iDeviceName = iInquiryMgr.DeviceNameFromCache(aAddr);
       
   315 
       
   316 	if (!iDeviceName || iDeviceName->Length() ==0)
       
   317 		{
       
   318 		// cache didn't have name - so we'll ask for it as a HR action
       
   319 		TRAP_IGNORE(iHR = iInquiryMgr.NewHostResolverL());
       
   320 		iHRNameRecord = new TNameRecord;
       
   321 
       
   322 		// ignore error - only an optimisation - don't want to leave if there's
       
   323 		// a problem doing this optimisation
       
   324 		if (iHR && iHRNameRecord)
       
   325 			{
       
   326 			iHR->SetNotify(this);
       
   327 
       
   328 			TInquirySockAddr i;
       
   329 			i.SetAction(KHostResName);
       
   330 			i.SetBTAddr(aAddr);
       
   331 			iHRNameRecord->iAddr = i;
       
   332 			iHR->GetByAddress(*iHRNameRecord);
       
   333 			}
       
   334 		}
       
   335 		
       
   336 	iDevAddr = aAddr;
       
   337 	
       
   338 	iSecMgr.AddNotifierRequestToQueL(*this);
       
   339 	iIsAddedToNotifierQue = ETrue;
       
   340 	}
       
   341 
       
   342 CSecNotifierRequester::~CSecNotifierRequester()
       
   343 	{
       
   344 	LOG_FUNC
       
   345 	Cancel();
       
   346 	
       
   347 	//remove ourself from the notifier que if we're still on it.
       
   348 	if (iIsAddedToNotifierQue)
       
   349 		{
       
   350 		iSecMgr.RemoveNotifierRequestFromQue(*this);
       
   351 		iIsAddedToNotifierQue = EFalse;
       
   352 		}
       
   353 
       
   354 	delete iHR;
       
   355 	delete iHRNameRecord;
       
   356 	delete iUpdateNotifierAO; 
       
   357 	
       
   358 	iNotifier.Close();
       
   359 	}
       
   360 
       
   361 void CSecNotifierRequester::QueryComplete(TInt aErr)
       
   362 	{
       
   363 	LOG_FUNC
       
   364 	if ( (aErr==KErrNone) && (iHRNameRecord!=NULL) )
       
   365 		{
       
   366 		// now have device name - update notifiers
       
   367 		// we do have a copy of the name - but it is now wide :-|
       
   368 		// and also we have iDeviceName that is still NULL, so best bet is
       
   369 		// to just set our pointer and use the cache one (which we *know* is there!)
       
   370 		TBTDevAddr a = TBTSockAddr::Cast(iHRNameRecord->iAddr).BTAddr();
       
   371 		iDeviceName = iInquiryMgr.DeviceNameFromCache(a);
       
   372 		DoUpdateNotifier();
       
   373 		}
       
   374 
       
   375 	delete iHRNameRecord;
       
   376 	iHRNameRecord = NULL;
       
   377 	}
       
   378 
       
   379 //------------------------------------------------------------------------//
       
   380 //class CBTPinRequester
       
   381 //------------------------------------------------------------------------//
       
   382 
       
   383 
       
   384 CBTPinRequester* CBTPinRequester::NewL(CPhysicalLink& aParent,
       
   385 									   MPINCodeResponseHandler& aRequester,
       
   386 									   CBTSecMan& aSecMan,
       
   387 									   TUint aPasskeyMinLength,
       
   388 									   TBool aInternallyInitiated)
       
   389 	{
       
   390 	LOG_FUNC
       
   391 	CBTPinRequester* s = CBTPinRequester::NewLC(aParent, aRequester, aSecMan,
       
   392 	                                            aPasskeyMinLength, aInternallyInitiated);
       
   393 	CleanupStack::Pop();
       
   394 	return s;
       
   395 	}
       
   396 
       
   397 CBTPinRequester* CBTPinRequester::NewLC(CPhysicalLink& aParent,
       
   398 										MPINCodeResponseHandler& aRequester,
       
   399 										CBTSecMan& aSecMan,
       
   400 										TUint aPasskeyMinLength,
       
   401 										TBool aInternallyInitiated)
       
   402 	{
       
   403 	LOG_FUNC
       
   404 	CBTPinRequester* s = new(ELeave) CBTPinRequester(aParent, aRequester, aSecMan,
       
   405 	                                                 aPasskeyMinLength, aInternallyInitiated);
       
   406 	CleanupStack::PushL(s);
       
   407 	s->ConstructL(aParent.BDAddr());
       
   408 	return s;
       
   409 	}
       
   410 
       
   411 CBTPinRequester::CBTPinRequester(CPhysicalLink& aParent,
       
   412 								 MPINCodeResponseHandler& aRequester,
       
   413 								 CBTSecMan& aSecMan,
       
   414 								 TUint aPasskeyMinLength,
       
   415 								 TBool aInternallyInitiated) :
       
   416 	CSecNotifierRequester(aSecMan),
       
   417 	iParent(aParent),
       
   418 	iRequester(aRequester),
       
   419 	iSecMan(aSecMan),
       
   420 	iPasskeyMinLength(aPasskeyMinLength),
       
   421 	iInternallyInitiated(aInternallyInitiated)
       
   422 	{
       
   423 	LOG_FUNC
       
   424 	// a lot of inlines
       
   425 	CActiveScheduler::Add(this);
       
   426 	}
       
   427 
       
   428 CBTPinRequester::~CBTPinRequester()
       
   429 	{
       
   430 	LOG_FUNC
       
   431 	Cancel();
       
   432 	}
       
   433 
       
   434 
       
   435 void CBTPinRequester::DoUpdateNotifier()
       
   436 	{
       
   437 	LOG_FUNC
       
   438  	if(IsActive())
       
   439  		{	
       
   440  		if(!iUpdateNotifierAO)
       
   441  			{
       
   442  			//Create a new CSecNotifierUpdateAO object
       
   443  			TRAP_IGNORE(iUpdateNotifierAO = CSecNotifierUpdateAO::NewL(iNotifier, KBTManPinNotifierUid));
       
   444  			}
       
   445  		
       
   446  		if( (iUpdateNotifierAO) && (!iUpdateNotifierAO->IsActive()) )
       
   447  			{
       
   448  			TBTNotifierUpdateParamsPckg pckg;
       
   449  			if(iDeviceName)
       
   450  				{
       
   451  				TRAPD(err, pckg().iName = BTDeviceNameConverter::ToUnicodeL(*iDeviceName));
       
   452  				pckg().iResult = err; 	// Error code can be KErrNone 
       
   453  				if (err!=KErrNone)
       
   454 	 				{
       
   455 	 				pckg().iName = KNullDesC;
       
   456 	 				}
       
   457  				}
       
   458  			else
       
   459  				{
       
   460  				pckg().iName = KNullDesC;
       
   461  				pckg().iResult = KErrNotFound;
       
   462  				}
       
   463  	
       
   464  			iUpdateNotifierAO->DoUpdate(pckg);
       
   465  			}
       
   466    		}
       
   467 	}
       
   468 
       
   469 void CBTPinRequester::DoRequest()
       
   470 /**
       
   471 It's our turn...start the RNotifier plugin that deals with authorisation.
       
   472 **/
       
   473 	{
       
   474 	LOG_FUNC
       
   475 	ASSERT_DEBUG(iDevAddr == iParent.BDAddr());
       
   476 	
       
   477 	iPasskeyParamsPckg().iBDAddr = iDevAddr;
       
   478 	if (iDeviceName)
       
   479 		{
       
   480 		TRAPD(err, iPasskeyParamsPckg().iName =	BTDeviceNameConverter::ToUnicodeL(*iDeviceName));
       
   481 		if (err!=KErrNone)
       
   482 			{
       
   483 			iPasskeyParamsPckg().iName = KNullDesC;
       
   484 			}
       
   485 		}
       
   486 	else
       
   487 		{
       
   488 		iPasskeyParamsPckg().iName = KNullDesC;	
       
   489 		}			
       
   490 	iPasskeyParamsPckg().iPasskeyMinLength = iPasskeyMinLength;	
       
   491 	iPasskeyParamsPckg().iLocallyInitiated = iInternallyInitiated;	
       
   492 
       
   493 	iNotifier.StartNotifierAndGetResponse(iStatus, KBTManPinNotifierUid, iPasskeyParamsPckg, iPassKey);
       
   494 	SetActive();
       
   495 	}
       
   496 
       
   497 void CBTPinRequester::FriendlyNameRetrieved(const TDesC& /*aName*/, TInt /*aResult*/)
       
   498 	{
       
   499 	LOG_FUNC
       
   500 	// do nothing for now 
       
   501 	}
       
   502 
       
   503 
       
   504 void CBTPinRequester::DoCancel()
       
   505 	{
       
   506 	LOG_FUNC
       
   507 	iNotifier.CancelNotifier(KBTManPinNotifierUid);
       
   508 	if (iUpdateNotifierAO)
       
   509 		{
       
   510 	 	iUpdateNotifierAO->Cancel();
       
   511 		}
       
   512 	}
       
   513 
       
   514 void CBTPinRequester::RunL()
       
   515 	{
       
   516 	LOG_FUNC
       
   517 	//got a PIN or error, so finish off: unload the plugin
       
   518 	iNotifier.CancelNotifier(KBTManPinNotifierUid);
       
   519 
       
   520 	//remove ourself from the notifier que, allowing the next notifier to be activated
       
   521 	iSecMan.RemoveNotifierRequestFromQue(*this);
       
   522 	iIsAddedToNotifierQue = EFalse;
       
   523 
       
   524 	ASSERT_DEBUG(iPasskeyParamsPckg().iBDAddr == iParent.BDAddr());
       
   525 	if (iStatus.Int())
       
   526 		{
       
   527 		// it failed - be unpairable
       
   528 		iRequester.PINCodeRequestNegativeReply((iParent.BDAddr()));
       
   529 		}
       
   530 	else
       
   531 		{
       
   532 		// got a PIN
       
   533 		iRequester.PINCodeRequestReply(iParent.BDAddr(),iPassKey);		
       
   534 		iParent.SetPassKey(iPassKey);
       
   535 		iParent.PinRequestSent();
       
   536 		iParent.DeleteLinkKeyL(); //only delete link key when user has entered PIN
       
   537 		}
       
   538 	// in either case tell parent as we're done.
       
   539 	iParent.PinRequestComplete();
       
   540 	}
       
   541 
       
   542 #ifdef __FLOG_ACTIVE
       
   543 TInt CBTPinRequester::RunError(TInt aError) 
       
   544 #else
       
   545 TInt CBTPinRequester::RunError(TInt /*aError*/)
       
   546 #endif
       
   547 	{
       
   548 	LOG_FUNC
       
   549 	ASSERT_DEBUG(iPasskeyParamsPckg().iBDAddr == iParent.BDAddr());
       
   550 	LOG1(_L("sec\tCBTPinRequester::RunError(%d)"), aError);
       
   551 	iRequester.PINCodeRequestNegativeReply(iParent.BDAddr());
       
   552 	iParent.PinRequestComplete();
       
   553 	return KErrNone;
       
   554 	}
       
   555 
       
   556 //------------------------------------------------------------------------//
       
   557 //class CBTAuthorisor
       
   558 //------------------------------------------------------------------------//
       
   559 
       
   560 CBTAuthorisor* CBTAuthorisor::NewL(CBTAccessRequester& aParent, TUid aServiceUID)
       
   561 	{
       
   562 	LOG_FUNC
       
   563 	CBTAuthorisor* s = CBTAuthorisor::NewLC(aParent, aServiceUID);
       
   564 	CleanupStack::Pop();
       
   565 	return s;
       
   566 	}
       
   567 
       
   568 CBTAuthorisor* CBTAuthorisor::NewLC(CBTAccessRequester& aParent, TUid aServiceUID)
       
   569 	{
       
   570 	LOG_FUNC
       
   571 	CBTAuthorisor* s = new(ELeave) CBTAuthorisor(aParent, aServiceUID);
       
   572 	CleanupStack::PushL(s);
       
   573 	s->ConstructL(aParent.DeviceAddress());
       
   574 	return s;
       
   575 	}
       
   576 
       
   577 CBTAuthorisor::CBTAuthorisor(CBTAccessRequester& aAccessRequester, TUid aServiceUID) :
       
   578 	CSecNotifierRequester(aAccessRequester.SecMan()),iAccessRequester(aAccessRequester)
       
   579 	{
       
   580 	LOG_FUNC
       
   581 	iAuthorisationParamsPckg().iUid = aServiceUID;
       
   582 	CActiveScheduler::Add(this);
       
   583 	}
       
   584 
       
   585 CBTAuthorisor::~CBTAuthorisor()
       
   586 	{
       
   587 	LOG_FUNC
       
   588 	Cancel();
       
   589 	}
       
   590 
       
   591 
       
   592 void CBTAuthorisor::DoUpdateNotifier()
       
   593 	{
       
   594 	LOG_FUNC 
       
   595  	if(IsActive())
       
   596  		{	
       
   597  		if(!iUpdateNotifierAO)
       
   598    			{
       
   599  			//Create a new CSecNotifierUpdateAO object
       
   600  			TRAP_IGNORE(iUpdateNotifierAO = CSecNotifierUpdateAO::NewL(iNotifier, KBTManAuthNotifierUid));
       
   601    			}
       
   602 	
       
   603  		if( (iUpdateNotifierAO) && (!iUpdateNotifierAO->IsActive()) )
       
   604    			{
       
   605  			TBTNotifierUpdateParamsPckg pckg;
       
   606  			if(iDeviceName)
       
   607  				{
       
   608  				TRAPD(err, pckg().iName = BTDeviceNameConverter::ToUnicodeL(*iDeviceName));
       
   609  				pckg().iResult = err; 	// Error code can be KErrNone 
       
   610  				if (err!=KErrNone)
       
   611 	 				{
       
   612 	 				pckg().iName = KNullDesC;
       
   613 	 				}
       
   614  				}
       
   615  			else
       
   616  				{
       
   617  				pckg().iName = KNullDesC;
       
   618  				pckg().iResult = KErrNotFound;
       
   619  				}
       
   620  				
       
   621  			iUpdateNotifierAO->DoUpdate(pckg);
       
   622  			}
       
   623  		}
       
   624 	}
       
   625 
       
   626 void CBTAuthorisor::DoRequest()
       
   627 /**
       
   628 Start the RNotifier plugin that deals with authorisation.
       
   629 **/
       
   630 	{
       
   631 	LOG_FUNC
       
   632 	TInt err(KErrNone);
       
   633 	
       
   634 	if (iDeviceName)
       
   635 		{
       
   636 		TRAP(err, iAuthorisationParamsPckg().iName = BTDeviceNameConverter::ToUnicodeL(*iDeviceName));
       
   637 		if (err!=KErrNone)
       
   638 			{
       
   639 			iAuthorisationParamsPckg().iName = KNullDesC;
       
   640 			}
       
   641 		}
       
   642 	else
       
   643 		{
       
   644 		iAuthorisationParamsPckg().iName = KNullDesC;
       
   645 		}			
       
   646 	iAuthorisationParamsPckg().iBDAddr  = iDevAddr;
       
   647 
       
   648 	iNotifier.StartNotifierAndGetResponse(iStatus, KBTManAuthNotifierUid, iAuthorisationParamsPckg, iResultPckg);
       
   649 	SetActive();
       
   650 	}
       
   651 
       
   652 
       
   653 void CBTAuthorisor::DoCancel()
       
   654 	{
       
   655 	LOG_FUNC
       
   656 
       
   657 	iNotifier.CancelNotifier(KBTManAuthNotifierUid);
       
   658 		
       
   659 	}
       
   660 
       
   661 void CBTAuthorisor::RunL()
       
   662 	{
       
   663 	LOG_FUNC
       
   664 	//unload the plugin
       
   665 	iNotifier.CancelNotifier(KBTManAuthNotifierUid);
       
   666 	//remove ourself from the notifier que, allowing the next notifier to be activated
       
   667 	iAccessRequester.SecMan().RemoveNotifierRequestFromQue(*this);
       
   668 	iIsAddedToNotifierQue = EFalse;
       
   669 	//check for errors + notify owner of completion
       
   670 	LOG1(_L("sec\tCBTAuthorisor::RunL(): iStatus = %d"), iStatus.Int());
       
   671 	if (iStatus.Int()!=KErrNone)
       
   672 		{
       
   673 		//error
       
   674 		iAccessRequester.CompleteRequest(iStatus.Int());
       
   675 		}
       
   676 	else
       
   677 		{
       
   678 		iAccessRequester.AuthorisationComplete(iResultPckg());
       
   679 		}
       
   680 	}
       
   681 
       
   682 TInt CBTAuthorisor::RunError(TInt aError)
       
   683 	{
       
   684 	LOG_FUNC
       
   685 	//will never get called as our RunL doesn't leave.
       
   686 	LOG1(_L("sec\tCBTAuthorisor::RunError(%d)"), aError);
       
   687 	return aError;
       
   688 	}
       
   689 
       
   690 
       
   691 /**
       
   692 	class CBTAccessRequester
       
   693 
       
   694 
       
   695 	The access requester handles the state machine involved in allowing accesses:
       
   696 	setting authentication, entering PINs, asking for authorisation and encrypting
       
   697 
       
   698 	This class deals only with security procedures we initiate (which could be for
       
   699 	inbound or outbound connections)
       
   700 
       
   701 */
       
   702 
       
   703 CBTAccessRequester* CBTAccessRequester::NewLC(CPhysicalLink& aConnection,
       
   704 											  const TBTServiceSecurity& aSecurityRequired,
       
   705   			  							      const TBTServiceSecurityPerDevice* const aOverride,
       
   706 											  MAccessRequestResponseHandler& aRequester,
       
   707 											  CBTSecMan& aParent)
       
   708 	{
       
   709 	LOG_FUNC
       
   710 	CBTAccessRequester* s = new(ELeave) CBTAccessRequester(aConnection, aSecurityRequired,
       
   711 															aOverride, aRequester, aParent);
       
   712 	CleanupStack::PushL(s);
       
   713 	s->ConstructL();
       
   714 	return s;
       
   715 	}
       
   716 
       
   717 
       
   718 CBTAccessRequester::CBTAccessRequester(CPhysicalLink& aConnection,
       
   719 									   const TBTServiceSecurity& aServiceSecurity,
       
   720  	  							       const TBTServiceSecurityPerDevice* const aOverride,
       
   721 									   MAccessRequestResponseHandler& aRequester,
       
   722 									   CBTSecMan& aParent) :
       
   723 	iRequester(aRequester),
       
   724 	iSecMan(aParent),
       
   725 	iBaseband(aConnection),
       
   726 	iServiceRequirements(aServiceSecurity),
       
   727 	iOverride(aOverride),
       
   728 	iIsSubscribedToConnection(EFalse),
       
   729 	iDeviceRetrievedFromRegistry(EFalse),
       
   730 	iQueLink(this),
       
   731 	iAuthenticationInProgress(EFalse)
       
   732 	{
       
   733 	LOG_FUNC
       
   734 	// try to get name for UI dialogs
       
   735 	SetDeviceName();
       
   736 	}
       
   737 
       
   738 void CBTAccessRequester::ConstructL()
       
   739 	{
       
   740 	LOG_FUNC
       
   741 	LOG2(_L("sec\tCBTAccessRequester 0x%08x constructed; sizeof %d"), this, sizeof(*this));
       
   742 	}
       
   743 
       
   744 void CBTAccessRequester::SetDeviceName()
       
   745 	{
       
   746 	LOG_FUNC
       
   747 	// not *that* bad - mostly inlines
       
   748 
       
   749 	iDeviceName = iSecMan.ConnectionsManager().
       
   750 					LinkManagerProtocol().InquiryMgr().
       
   751 					  DeviceNameFromCache(iBaseband.BDAddr());
       
   752 	}
       
   753 
       
   754 
       
   755 const MAccessRequestResponseHandler& CBTAccessRequester::ServiceRequester() const
       
   756 	{
       
   757 	LOG_FUNC
       
   758 	return iRequester;
       
   759 	}
       
   760 
       
   761 const TBTDevAddr& CBTAccessRequester::DeviceAddress() const
       
   762 	{
       
   763 	LOG_FUNC
       
   764 	return (iBaseband.BDAddr());
       
   765 	}
       
   766 
       
   767 void CBTAccessRequester::DoRequest()
       
   768 /**
       
   769 Subscribe to the baseband link notifier to find out about the link state.
       
   770 This will kick off the state machine.
       
   771 **/
       
   772 	{
       
   773 	LOG_FUNC
       
   774 	LOG1(_L("sec\tAccessRequester 0x%08x DoRequest"),this);
       
   775 	iBaseband.SubscribeLinkObserver(*this);
       
   776 	iIsSubscribedToConnection = ETrue;
       
   777 
       
   778 	// if the link is already up (e.g. we're SecMode 2 for L2CAP/RFCOMM) then proceed
       
   779 	if (iBaseband.IsConnected())
       
   780 		{
       
   781 		TBTBasebandEventNotification event(ENotifyPhysicalLinkUp);
       
   782 		PhysicalLinkChange(event); // kick statemachine
       
   783 		}
       
   784 	// else wait until it is retrieved
       
   785 	}
       
   786 
       
   787 void CBTAccessRequester::CompleteRequest(TInt aResult)
       
   788 	{
       
   789 	LOG_FUNC
       
   790 	LOG2(_L("sec\tAccessRequester 0x%08x CompleteRequest, result %d"),this,aResult);
       
   791 	iSecMan.AccessRequestComplete(this, aResult);
       
   792 	}
       
   793 
       
   794 CBTAccessRequester::~CBTAccessRequester()
       
   795 	{
       
   796 	LOG_FUNC
       
   797 	LOG1(_L("sec\tAccessRequester 0x%08x Destroying"),this);
       
   798 	if (iIsSubscribedToConnection)
       
   799 		{
       
   800 		iBaseband.UnsubscribeLinkObserver(*this);
       
   801 		}
       
   802 	delete iAuthorisor;
       
   803 	}
       
   804 
       
   805 
       
   806 void CBTAccessRequester::NewStateL()
       
   807 /**
       
   808 This access request has entered a new state.  Work out what we should do next.
       
   809 **/
       
   810 	{
       
   811 	LOG_FUNC
       
   812 	
       
   813  	// We should ensure that at each iteration through the state machine the requirements
       
   814  	// are up-to-date.  This is needed as the physical link may have changed
       
   815  	// some internal state e.g. as a result of the Registry having been modified.
       
   816  	iRequirements = OverallRequirements(iServiceRequirements, iBaseband.RemoteDevice());
       
   817  	
       
   818 #ifdef _DEBUG
       
   819 	_LIT(KRequestNone,					"Not Request.     ");
       
   820 	_LIT(KRequestPending,				"Request Pending. ");
       
   821 	_LIT(KRequestFailed,				"Request Failed.  ");
       
   822 	_LIT(KRequestComplete,				"Request Complete.");
       
   823 
       
   824 	TBuf<20> iStateName[4] = 
       
   825 		{
       
   826 		KRequestNone(),
       
   827 		KRequestPending(),
       
   828 		KRequestFailed(),
       
   829 		KRequestComplete(),
       
   830 		};
       
   831 
       
   832 	TBTDevAddr addr = iBaseband.BDAddr();
       
   833 	LOG3(_L("sec\tCBTAccessRequester::NewStateL(Authorised[%S] Authenticated[%S] Encrypted[%S])"),
       
   834 		&iStateName[iState.AuthorisationState()],
       
   835 		&iStateName[iState.AuthenticationState()], 
       
   836 		&iStateName[iState.EncryptionState()]);
       
   837 	LOG6(_L("\t\taddr[0x%02x%02x%02x%02x%02x%02x]"),
       
   838 		addr[0],addr[1],addr[2],addr[3],addr[4],addr[5]);
       
   839 	LOG4(_L("\t\tRequirements: a[%d] p[%d] e[%d] d[%d]"), iRequirements.AuthenticationRequired(),
       
   840 		iRequirements.AuthorisationRequired(), iRequirements.EncryptionRequired(), iRequirements.Denied());
       
   841 #endif
       
   842 
       
   843 	if (iRequirements.AuthenticationRequired() && iRequirements.PasskeyMinLength() &&
       
   844 	       iBaseband.Authenticated() )
       
   845 		{
       
   846 		LOG(_L("sec\tCheck min passkey length")) // for remotly initiated connection
       
   847 		TBTPinCode passKey = iBaseband.PassKey();
       
   848 		if ( passKey().iLength < iRequirements.PasskeyMinLength())
       
   849 			{
       
   850 			// the remote device is authenticated, but longer passkey is required
       
   851 			LOG(_L("sec\tCBTAccessRequester::Complete(ACCESS DENIED) Passkey min length requirement is longer, then current used for authentication"));
       
   852 			CompleteRequest(EBTSecManAccessDenied);
       
   853 			return;			
       
   854 			}		
       
   855 		}
       
   856 
       
   857 	//1. Check for any failures or for "Denied" in iRequirements
       
   858 	//If anything that was required has failed, complete the request with EBTManAccessDenied and delete this.
       
   859 	if ((iState.AuthenticationState() == TBTAccessRequestState::ERequestFailed && iRequirements.AuthenticationRequired()) 
       
   860 		|| (iState.EncryptionState() == TBTAccessRequestState::ERequestFailed && iRequirements.EncryptionRequired())
       
   861 		|| (iState.AuthorisationState() == TBTAccessRequestState::ERequestFailed && iRequirements.AuthorisationRequired())
       
   862 		|| iRequirements.Denied())
       
   863 		{
       
   864 		LOG(_L("sec\tCBTAccessRequester::Complete(ACCESS DENIED)"));
       
   865 		CompleteRequest(EBTSecManAccessDenied);
       
   866 		}
       
   867 	//2. Check for authentication
       
   868 	else if (iRequirements.AuthenticationRequired() && 
       
   869 			 !iBaseband.Authenticated() && !iBaseband.Encrypted())
       
   870 		{
       
   871 		// might have been encrypted by remote side - so no need to reauthenticate
       
   872 		// this makes us more interoperable with controllers that don't honour erratum E2244
       
   873 		LOG(_L("sec\tAuthentication required..."))
       
   874 		//if we don't have a pending authentication request, start authentication.
       
   875 		if (iState.AuthenticationState() != TBTAccessRequestState::ERequestPending)
       
   876 			{
       
   877 			LOG(_L("sec\tStarting Authentication..."));
       
   878 			iState.SetAuthenticationState(TBTAccessRequestState::ERequestPending);
       
   879 			User::LeaveIfError(iBaseband.Authenticate());
       
   880 			}
       
   881 		}	
       
   882 	//3. Check for encryption
       
   883 	else if (iRequirements.EncryptionRequired() && !iBaseband.Encrypted())
       
   884 		{
       
   885 		LOG(_L("sec\tEncryption required..."))
       
   886 
       
   887 		if (!iBaseband.IsEncryptionDisabledForRoleSwitch())
       
   888 			{
       
   889 			//if we don't have a pending encryption request, start encryption.
       
   890 			if (iState.EncryptionState() != TBTAccessRequestState::ERequestPending)
       
   891 				{
       
   892 				LOG(_L("sec\tStarting Encryption..."))
       
   893 				iState.SetEncryptionState(TBTAccessRequestState::ERequestPending);
       
   894 				User::LeaveIfError(iBaseband.ChangeEncryption(EPointToPointEncryption));
       
   895 				}			
       
   896 			}
       
   897 		}
       
   898 	//4. Check for authorisation
       
   899 	else if (iRequirements.AuthorisationRequired() && 
       
   900 	        (iState.AuthorisationState() == TBTAccessRequestState::ERequestNone || iState.AuthorisationState() == TBTAccessRequestState::ERequestPending))
       
   901 		{
       
   902 		//if we don't have a pending authorisation request, start authorisation.
       
   903 		LOG(_L("sec\tAuthorisation required..."))
       
   904 		if (iState.AuthorisationState() != TBTAccessRequestState::ERequestPending)
       
   905 			{
       
   906 			LOG(_L("sec\tStarting Authorisation..."))
       
   907 			__ASSERT_ALWAYS(!iAuthorisor, User::Panic(KBTSecPanic,EBTSecAuthorisationRequestAlreadyExists));
       
   908 			iAuthorisor = CBTAuthorisor::NewL(*this, iServiceRequirements.Uid());
       
   909 			iState.SetAuthorisationState(TBTAccessRequestState::ERequestPending);
       
   910 			}
       
   911 		}
       
   912 	//5. Before EBTManAccessGranted, doublecheck all the checks were done
       
   913 	else
       
   914 		{
       
   915 		TBool authenticationComplete;
       
   916 		TBool encryptionComplete;
       
   917 		TBool authorisationComplete;
       
   918 		
       
   919 		authenticationComplete = !iRequirements.AuthenticationRequired() || 
       
   920 		                         (iRequirements.AuthenticationRequired() && 
       
   921 		                           (iBaseband.Authenticated() || iBaseband.Encrypted()));
       
   922 		                         
       
   923 		                         
       
   924 		                         
       
   925 		encryptionComplete = !iRequirements.EncryptionRequired() ||
       
   926 							 (iRequirements.EncryptionRequired() && iBaseband.Encrypted());
       
   927 							 
       
   928 							 
       
   929 		authorisationComplete = !iRequirements.AuthorisationRequired() ||
       
   930 								(iRequirements.AuthorisationRequired()  && iState.AuthorisationState()==TBTAccessRequestState::ERequestComplete);
       
   931 		
       
   932 		                
       
   933 		if (authenticationComplete && encryptionComplete && authorisationComplete)
       
   934 			{
       
   935 			LOG(_L("sec\tEBTManAccessGranted"))
       
   936 			CompleteRequest(EBTSecManAccessGranted);	
       
   937 			}
       
   938 		else
       
   939 			{
       
   940 			LOG(_L("sec\tCBTAccessRequester::Complete(ACCESS DENIED) during double check"));
       
   941 			CompleteRequest(EBTSecManAccessDenied);			
       
   942 			}
       
   943 		}
       
   944 	}
       
   945 
       
   946 TBTAccessRequirements CBTAccessRequester::OverallRequirements(const TBTServiceSecurity& aServiceSecurity,
       
   947 														 const TBTNamelessDevice& aDevice)
       
   948 /**
       
   949 Take the access requirements of the service and compare them with the permissions given 
       
   950 to the device by the user.  This results in a list of tasks to be carried out by the 
       
   951 access requester before it may let the connection proceed.
       
   952 **/
       
   953 	{
       
   954 	LOG_FUNC
       
   955 	//Create the initial stab at the access requirements from the requirements of this service...
       
   956 	TBTAccessRequirements req;
       
   957 	req.SetAuthentication(aServiceSecurity.AuthenticationRequired());
       
   958 	req.SetAuthorisation(aServiceSecurity.AuthorisationRequired());
       
   959 	req.SetEncryption(aServiceSecurity.EncryptionRequired());
       
   960 	req.SetDenied(aServiceSecurity.Denied());
       
   961 	req.SetPasskeyMinLength(aServiceSecurity.PasskeyMinLength());
       
   962 
       
   963 	//Look at the global security setting of the device...
       
   964 	if (aDevice.IsValidGlobalSecurity())
       
   965 		{
       
   966 		LOG(_L("sec\tDevice has global security settings"));
       
   967 		TBTDeviceSecurity devSec = aDevice.GlobalSecurity();
       
   968 		if (devSec.Banned())
       
   969 			req.SetDenied(ETrue);
       
   970 		if (devSec.Encrypt())
       
   971 			req.SetEncryption(ETrue);
       
   972 		if (devSec.NoAuthenticate())
       
   973 			req.SetAuthentication(EFalse);
       
   974 		if (devSec.NoAuthorise())
       
   975 			req.SetAuthorisation(EFalse);
       
   976 		if (devSec.PasskeyMinLength() && devSec.PasskeyMinLength() > req.PasskeyMinLength())
       
   977 			req.SetPasskeyMinLength(devSec.PasskeyMinLength());
       
   978 		}
       
   979 
       
   980 	//Check to see if the device has anything specific about this service...
       
   981 
       
   982 	if (iOverride)
       
   983 		{
       
   984 		// get the device security from the override (the override points to the correct device)
       
   985 		LOG(_L("sec\tSAP has overriden global security settings for device"));
       
   986 		const TBTDeviceSecurity& servSec = iOverride->DeviceSecurity();
       
   987 		if (servSec.Banned())
       
   988 			req.SetDenied(ETrue);
       
   989 		if (servSec.Encrypt())
       
   990 			req.SetEncryption(ETrue);
       
   991 		if (servSec.NoAuthenticate())
       
   992 			req.SetAuthentication(EFalse);
       
   993 		if (servSec.NoAuthorise())
       
   994 			req.SetAuthorisation(EFalse);
       
   995 		if (servSec.PasskeyMinLength() && servSec.PasskeyMinLength() > req.PasskeyMinLength() )
       
   996 		    req.SetPasskeyMinLength(servSec.PasskeyMinLength());
       
   997 		}
       
   998 
       
   999 	// if only encryption is required, then must need authentication
       
  1000 	if (req.EncryptionRequired())
       
  1001 		{
       
  1002 		req.SetAuthentication(ETrue);
       
  1003 		}
       
  1004 
       
  1005 	return req;
       
  1006 	}
       
  1007 
       
  1008 void CBTAccessRequester::FriendlyNameRetrieved(const TDesC& /*aName*/, TInt /*aResult*/)
       
  1009 
       
  1010 	{
       
  1011 	LOG_FUNC
       
  1012 	// do nothing for now
       
  1013 	}
       
  1014 
       
  1015 void CBTAccessRequester::DeviceRetrieved(const TBTNamelessDevice& aDevice, TInt aError)
       
  1016 /**
       
  1017 	A device has been retrieved from the registry
       
  1018 	If it's for us we need to continue the access request based on the overrides it has
       
  1019 
       
  1020 	This object chooses not to keep a copy of the device, but notes its availability
       
  1021 **/
       
  1022 	{
       
  1023 	LOG_FUNC
       
  1024 	if (aDevice.Address() != iBaseband.BDAddr())
       
  1025 		{
       
  1026 		return; // wasn't for us
       
  1027 		}
       
  1028 	
       
  1029 	TInt err = aError;
       
  1030 
       
  1031 	iDeviceRetrievedFromRegistry = ETrue;
       
  1032 
       
  1033 	if (err == KErrNone || err == KErrNotFound)
       
  1034 		{
       
  1035 		// proceed with the security check...
       
  1036 		iRequirements = OverallRequirements(iServiceRequirements, aDevice);
       
  1037 		}
       
  1038 
       
  1039 	if (err!=KErrNone)
       
  1040 		{
       
  1041 		CompleteRequest(err);
       
  1042 		}
       
  1043 	}
       
  1044 
       
  1045 
       
  1046 void CBTAccessRequester::AuthorisationComplete(TBool aResult)
       
  1047 /**
       
  1048 We have a new authorisation state.
       
  1049 **/
       
  1050 	{
       
  1051 	LOG_FUNC
       
  1052 	LOG1(_L("sec\tCBTAccessRequester::AuthorisationComplete(%d)"), aResult);
       
  1053 	if (aResult)
       
  1054 		{
       
  1055 		iState.SetAuthorisationState(TBTAccessRequestState::ERequestComplete);
       
  1056 		}
       
  1057 	else
       
  1058 		{
       
  1059 		iState.SetAuthorisationState(TBTAccessRequestState::ERequestFailed);
       
  1060 		}
       
  1061 	TRAPD(err,NewStateL());
       
  1062 	if (err)
       
  1063 		{
       
  1064 		CompleteRequest(err);
       
  1065 		}
       
  1066 	}
       
  1067 
       
  1068 
       
  1069 void CBTAccessRequester::PhysicalLinkChange(const TBTBasebandEventNotification & aEvent, CPhysicalLink& /*aPhysicalLink*/)
       
  1070 	{
       
  1071 	LOG_FUNC
       
  1072 	// only forward events that secman is interested in
       
  1073 	// linkup, linkdown, encryption, authentication, error
       
  1074 	// Care needed: other events may harm operation of secman 
       
  1075 	// and open security hole, such as ENotifySniffMode, ENotifyParkMode
       
  1076  	// and ENotifyHoldMode
       
  1077  	TBTPhysicalLinkStateNotifier secmanEvents = static_cast<TBTPhysicalLinkStateNotifier>
       
  1078  	           (ENotifyPhysicalLinkUp |
       
  1079  	            ENotifyPhysicalLinkDown |
       
  1080 	            ENotifyPhysicalLinkError |
       
  1081 	            ENotifyAuthenticationComplete |
       
  1082 	            ENotifyEncryptionChangeOn |
       
  1083  	            ENotifyEncryptionChangeOff);
       
  1084 		            
       
  1085 	if (aEvent.EventType() & secmanEvents)
       
  1086 		{  
       
  1087 		PhysicalLinkChange(aEvent); 		}
       
  1088  	// else drop
       
  1089 	}
       
  1090 
       
  1091 void CBTAccessRequester::PhysicalLinkChange(const TBTBasebandEventNotification & aEvent)
       
  1092 	{
       
  1093 	LOG_FUNC
       
  1094 	if(aEvent.EventType() & (ENotifyPhysicalLinkDown | ENotifyPhysicalLinkError))
       
  1095 		{
       
  1096 		CompleteRequest(aEvent.ErrorCode());
       
  1097 		return;
       
  1098 		}
       
  1099 
       
  1100 	if (iState.AuthenticationState() == TBTAccessRequestState::ERequestPending && 
       
  1101 		aEvent.EventType() == ENotifyAuthenticationComplete)
       
  1102 		{
       
  1103 		LOG(_L("sec\tAuthentication complete..."))
       
  1104 
       
  1105 		if(aEvent.ErrorCode() != KErrNone)
       
  1106 			{
       
  1107 			iState.SetAuthenticationState(TBTAccessRequestState::ERequestFailed);
       
  1108 			//if Auth fail then ensure any previously stored Linkkey is removed
       
  1109 			//Don't know which AccessRequester initiated this so can't complete
       
  1110 			//the request with the error code, only thing to do is trap this error
       
  1111 			//Deleting a LinkKey is not Critical merely cosmetic
       
  1112 			LOG(_L("CPhysicalLink: Deleting link key due to failed Authentication"))
       
  1113 			TRAP_IGNORE(iBaseband.DeleteLinkKeyL());
       
  1114 			}
       
  1115 		else
       
  1116 			{
       
  1117 			iState.SetAuthenticationState(TBTAccessRequestState::ERequestComplete);
       
  1118 			}
       
  1119 		}
       
  1120 
       
  1121 	if (iState.EncryptionState() == TBTAccessRequestState::ERequestPending && 
       
  1122 		(aEvent.EventType() == ENotifyEncryptionChangeOn || aEvent.EventType() == ENotifyEncryptionChangeOff))
       
  1123 		{
       
  1124 		LOG(_L("sec\tEncryption Change complete..."))
       
  1125 		
       
  1126 		// We can try again as there was a race with some other PHY modification
       
  1127 		// Curiously, the firmware always return ELMPErrorTransactionCollision (0x23) for both
       
  1128 		// kinds of transaction collisions (0x23,0x2a), we guard against both situations here
       
  1129 		// anyway just to be safe.
       
  1130 		if(aEvent.ErrorCode() == ELMPErrorTransactionCollision || aEvent.ErrorCode() == EDifferentTransactionCollision)
       
  1131 			{	
       
  1132 			// This will force the state machine logic to try sending the command again
       
  1133 			iState.SetEncryptionState(TBTAccessRequestState::ERequestNone);
       
  1134 			}
       
  1135 		else if(aEvent.ErrorCode() != KErrNone)
       
  1136 			{
       
  1137 			
       
  1138 			iState.SetEncryptionState(TBTAccessRequestState::ERequestFailed);
       
  1139 			}
       
  1140 		else
       
  1141 			{
       
  1142 			iState.SetEncryptionState(TBTAccessRequestState::ERequestComplete);
       
  1143 			}
       
  1144 		}
       
  1145 
       
  1146 	TRAPD(err,NewStateL());
       
  1147 	if (err)
       
  1148 		{
       
  1149 		CompleteRequest(err);
       
  1150 		}
       
  1151 	}
       
  1152 
       
  1153 
       
  1154 CBTSecMan& CBTAccessRequester::SecMan()
       
  1155 	{
       
  1156 	LOG_FUNC
       
  1157 	return iSecMan;
       
  1158 	}
       
  1159 
       
  1160 TBool CBTAccessRequester::IsAuthenticationReqPending(const TBTDevAddr& aAddr, TUint& aPasskeyMinLength)
       
  1161 	{
       
  1162 	LOG_FUNC
       
  1163 		if (iState.AuthenticationState() == TBTAccessRequestState::ERequestPending &&
       
  1164 		    iAuthenticationInProgress && aAddr == iBaseband.BDAddr())
       
  1165 			{
       
  1166 			aPasskeyMinLength = iServiceRequirements.PasskeyMinLength();
       
  1167 			return ETrue;
       
  1168 			}
       
  1169 		else 
       
  1170 			{
       
  1171 			aPasskeyMinLength = 0;
       
  1172 			return EFalse;
       
  1173 			}
       
  1174 	}
       
  1175 
       
  1176 TBool CBTAccessRequester::AuthenticationRequired() const
       
  1177 	{
       
  1178 	LOG_FUNC
       
  1179 	return iRequirements.AuthenticationRequired();
       
  1180 	}
       
  1181 
       
  1182 TBool CBTAccessRequester::AuthenticationInProgress() const
       
  1183 	{
       
  1184 	LOG_FUNC
       
  1185 	return iAuthenticationInProgress;
       
  1186 	}
       
  1187 
       
  1188 void  CBTAccessRequester::SetAuthenticationInProgress()
       
  1189 	{
       
  1190 	LOG_FUNC
       
  1191 	iAuthenticationInProgress = ETrue;
       
  1192 	}
       
  1193 	
       
  1194 	 
       
  1195  //------------------------------------------------------------------------//
       
  1196  //class CSecNotifierUpdateAO
       
  1197  //------------------------------------------------------------------------//
       
  1198  
       
  1199 CSecNotifierUpdateAO* CSecNotifierUpdateAO::NewL(RNotifier& aNotifier, TUid aNotifierUid)
       
  1200  	{
       
  1201 	LOG_FUNC
       
  1202  	CSecNotifierUpdateAO* s = CSecNotifierUpdateAO::NewLC(aNotifier, aNotifierUid);
       
  1203  	CleanupStack::Pop();
       
  1204  	return s;
       
  1205  	}
       
  1206  
       
  1207 CSecNotifierUpdateAO* CSecNotifierUpdateAO::NewLC(RNotifier& aNotifier, TUid aNotifierUid)
       
  1208  	{
       
  1209 	LOG_FUNC
       
  1210  	LOG(_L("sec\tCSecNotifierUpdateAO::NewLC()"));
       
  1211  	CSecNotifierUpdateAO* s = new(ELeave) CSecNotifierUpdateAO();
       
  1212  	CleanupStack::PushL(s);
       
  1213  	s->ConstructL(aNotifier, aNotifierUid);
       
  1214  	return s;
       
  1215  	}
       
  1216  
       
  1217 CSecNotifierUpdateAO::CSecNotifierUpdateAO()
       
  1218 : CActive(EPriorityStandard)
       
  1219  	{
       
  1220 	LOG_FUNC
       
  1221  	CActiveScheduler::Add(this);
       
  1222  	}
       
  1223  
       
  1224 CSecNotifierUpdateAO::~CSecNotifierUpdateAO()
       
  1225  	{
       
  1226 	LOG_FUNC
       
  1227  	Cancel();
       
  1228  	}
       
  1229  
       
  1230 void CSecNotifierUpdateAO::ConstructL(RNotifier& aNotifier, TUid aNotifierUid)
       
  1231  	{
       
  1232 	LOG_FUNC
       
  1233  	iNotifier = aNotifier;
       
  1234  	iNotifierUid = aNotifierUid;	
       
  1235  	}
       
  1236  	
       
  1237 void CSecNotifierUpdateAO::DoUpdate(const TBTNotifierUpdateParamsPckg& aPckg)
       
  1238  	{
       
  1239 	LOG_FUNC
       
  1240  	//Retain a copy so that it does not go out of memory scope
       
  1241  	iPckg = aPckg;
       
  1242  	
       
  1243  	//we're not expecting an answer...
       
  1244 	iNotifier.UpdateNotifierAndGetResponse(iStatus, iNotifierUid, iPckg, iAnswer);
       
  1245  	SetActive();	
       
  1246  	}
       
  1247  	
       
  1248 void CSecNotifierUpdateAO::RunL()
       
  1249  	{
       
  1250 	LOG_FUNC
       
  1251  	//We can't do anything if an error is returned - just make sure we haven't done anything stupid...	
       
  1252  	__ASSERT_DEBUG((iStatus==KErrNone)||(iStatus==KErrNoMemory)||(iStatus==KErrNotReady), User::Panic(KBTSecPanic, EBTSecBadNotifierUpdate));
       
  1253  	}
       
  1254  	
       
  1255 void CSecNotifierUpdateAO::DoCancel()
       
  1256  	{
       
  1257 	LOG_FUNC
       
  1258  	LOG(_L("sec\tCSecNotifierUpdateAO::DoCancel()"));
       
  1259 	iNotifier.CancelNotifier(iNotifierUid); // no other API on Notifier to just cancel the update; but typically we'll want to cancel the whole notifier at this point(?)
       
  1260 	}
       
  1261  	
       
  1262 TInt CSecNotifierUpdateAO::RunError(TInt aError)
       
  1263  	{
       
  1264 	LOG_FUNC
       
  1265  	LOG1(_L("sec\tCSecNotifierUpdateAO::RunError(%d)"), aError);
       
  1266  	
       
  1267  	#ifndef __FLOGGING__
       
  1268  		aError += 0; //Remove Compiler warning
       
  1269  	#endif
       
  1270  	 
       
  1271  	return KErrNone;	
       
  1272  	}