|
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 } |