|
1 // Copyright (c) 1997-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 |
|
17 #include <in_iface.h> |
|
18 #include "PPPAUTH.H" |
|
19 |
|
20 #include "ppppap.h" |
|
21 #include "chapmd5.h" |
|
22 #include "MSCHAP.H" |
|
23 #include "mschap2.h" |
|
24 #include <commsdattypeinfov1_1.h> |
|
25 #include "PPPConfig.h" |
|
26 |
|
27 #if defined(_DEBUG) |
|
28 const TInt KLCPConfigOptionTypeFieldSize = 1; |
|
29 const TInt KLCPConfigOptionLengthFieldSize = 1; |
|
30 #endif |
|
31 const TInt KAuthenticationProtocolOptionFieldSize = 2; |
|
32 const TInt KChapAlgorithmFieldSize = 1; |
|
33 |
|
34 |
|
35 // |
|
36 |
|
37 void CPppAuthentication::InitL( |
|
38 CPppLcp* aPppLcp) |
|
39 /** |
|
40 Initializes the authentication protocol. |
|
41 @param aPppLcp Parent LCP instance |
|
42 @leave The method does not leave */ |
|
43 { |
|
44 MPppRecvr::Init(aPppLcp, PppPhase(), PppId()); |
|
45 } |
|
46 |
|
47 CPppAuthentication::~CPppAuthentication() |
|
48 /** |
|
49 Destructor, generates a CancelAuthenticate notification to the |
|
50 parent LCP instance */ |
|
51 { |
|
52 if (iPppLcp != 0) |
|
53 iPppLcp->CancelAuthenticate(this); |
|
54 } |
|
55 |
|
56 void CPppAuthentication::AuthenticateRequest() |
|
57 /** |
|
58 Generates an Authenticate notification to the parent LCP instance */ |
|
59 { |
|
60 ASSERT(iPppLcp != 0); |
|
61 iPppLcp->Authenticate(this); |
|
62 } |
|
63 |
|
64 void CPppAuthentication::CallAuthenticateComplete( |
|
65 TInt aRes) |
|
66 /** |
|
67 Notifies the derived class that the LCP authentication is completed |
|
68 @param aRes Code describing the authentication result |
|
69 (KErrNone: authentication OK) */ |
|
70 { |
|
71 ASSERT(iPppLcp != 0); |
|
72 iFlags |= KPppApAuthReqDone; |
|
73 AuthenticateComplete(aRes); |
|
74 } |
|
75 |
|
76 void CPppAuthentication::DoFail( |
|
77 TInt aErrorCode) |
|
78 /** |
|
79 Notifies the parent LCP instance of an error encountered |
|
80 during authentication |
|
81 @param aErrorCode Describes the authentication failure */ |
|
82 { |
|
83 ASSERT(iPppLcp != 0); |
|
84 iPppLcp->Progress(EPppProgressAuthenticationComplete, aErrorCode); |
|
85 iPppLcp->PhaseAborted(aErrorCode); |
|
86 } |
|
87 |
|
88 |
|
89 void CPppAuthentication::DoSucceed() |
|
90 /** |
|
91 Notifies the parent LCP instance that the |
|
92 authentication phase completed successfully */ |
|
93 { |
|
94 ASSERT(iPppLcp != 0); |
|
95 |
|
96 iPppLcp->Progress(EPppProgressAuthenticationComplete, KErrNone); |
|
97 iPppLcp->PhaseComplete(); |
|
98 } |
|
99 |
|
100 |
|
101 // |
|
102 |
|
103 static const TInt KOptionListLen = 1; |
|
104 static const TUint8 OptionList[KOptionListLen] = |
|
105 { |
|
106 KPppLcpOptAuthenticationProtocol |
|
107 }; |
|
108 |
|
109 CPppAcp* CPppAcp::NewL( |
|
110 CPppLcp* aLcp) |
|
111 /** |
|
112 Creates a new CPppAcp instance |
|
113 @param aLcp Parent LCP instance |
|
114 @return Newly created CPppAcp instance */ |
|
115 { |
|
116 CPppAcp* acp = new (ELeave) CPppAcp(aLcp); |
|
117 return acp; |
|
118 } |
|
119 |
|
120 CPppAcp::CPppAcp( |
|
121 CPppLcp* aLcp) |
|
122 : MPppOptionHandler() |
|
123 /** |
|
124 Constructor, register the current instance as a handler |
|
125 for the authentication option type |
|
126 @param aLcp Parent LCP instance */ |
|
127 { |
|
128 iPppLcp = aLcp; |
|
129 OptRegister(aLcp, OptionList, KOptionListLen); |
|
130 } |
|
131 |
|
132 CPppAcp::~CPppAcp() |
|
133 /** |
|
134 Destructor, deletes the protocol objects created by this instance */ |
|
135 { |
|
136 DeleteProtocols(); |
|
137 } |
|
138 |
|
139 void CPppAcp::DeleteProtocols() |
|
140 /** |
|
141 Deletes the member protocol objects if valid. */ |
|
142 { |
|
143 if (iServerProtocol) |
|
144 { |
|
145 delete iServerProtocol; |
|
146 iServerProtocol = NULL; |
|
147 } |
|
148 if (iClientProtocol) |
|
149 { |
|
150 delete iClientProtocol; |
|
151 iClientProtocol = NULL; |
|
152 } |
|
153 } |
|
154 |
|
155 void CPppAcp::OptNegotiationStarted() |
|
156 /** |
|
157 Initializes the option handler for a new LCP negotiation session */ |
|
158 { |
|
159 DeleteProtocols(); |
|
160 |
|
161 iClientId = KPppIdUnknown; |
|
162 iClientSubId = KPppIdUnknown; |
|
163 iServerId = KPppIdUnknown; |
|
164 iServerSubId = KPppIdUnknown; |
|
165 |
|
166 iProtocolOffered = 0; |
|
167 iCHAPTypeOffered = 0; |
|
168 |
|
169 // default to fallback |
|
170 } |
|
171 |
|
172 void CPppAcp::OptNegotiationAborted() |
|
173 /** |
|
174 Executed when the negotiation is aborted, |
|
175 resets the negotiable options */ |
|
176 { |
|
177 iClientId = KPppIdUnknown; |
|
178 iClientSubId = KPppIdUnknown; |
|
179 iServerId = KPppIdUnknown; |
|
180 iServerSubId = KPppIdUnknown; |
|
181 } |
|
182 |
|
183 void CPppAcp::OptNegotiationComplete() |
|
184 /** |
|
185 Executed when the negotiation is finalized, |
|
186 creates the protocol objects according to the |
|
187 negotiated options */ |
|
188 { |
|
189 TRAPD(ret, |
|
190 switch (iClientId) |
|
191 { |
|
192 case KPppIdPap: |
|
193 iClientProtocol = CPppPap::NewL(); |
|
194 break; |
|
195 |
|
196 case KPppIdChap: |
|
197 switch (iClientSubId) |
|
198 { |
|
199 case KPppChapMd5AlgorithmNumber: |
|
200 iClientProtocol = CPppChapMd5::NewL(); |
|
201 break; |
|
202 |
|
203 case KPppMsChapAlgorithmNumber: |
|
204 iClientProtocol = CPppMsChap::NewL(); |
|
205 break; |
|
206 |
|
207 case KPppMsChap2AlgorithmNumber: |
|
208 iClientProtocol = CPppMsChap2::NewL(); |
|
209 break; |
|
210 } |
|
211 break; |
|
212 } |
|
213 |
|
214 if (iClientProtocol) |
|
215 { |
|
216 iClientProtocol->iFlags = KPppApIsClient; |
|
217 if (iClientId==iServerId) |
|
218 iClientProtocol->iFlags |= KPppApIsServer; |
|
219 iClientProtocol->InitL(iPppLcp); |
|
220 } |
|
221 |
|
222 if (iClientId!=iServerId) |
|
223 { |
|
224 switch (iServerId) |
|
225 { |
|
226 case KPppIdPap: |
|
227 iServerProtocol = CPppPap::NewL(); |
|
228 break; |
|
229 |
|
230 case KPppIdChap: |
|
231 switch (iServerSubId) |
|
232 { |
|
233 case KPppChapMd5AlgorithmNumber: |
|
234 iServerProtocol = CPppChapMd5::NewL(); |
|
235 break; |
|
236 |
|
237 case KPppMsChapAlgorithmNumber: |
|
238 iServerProtocol = CPppMsChap::NewL(); |
|
239 break; |
|
240 |
|
241 case KPppMsChap2AlgorithmNumber: |
|
242 iServerProtocol = CPppMsChap2::NewL(); |
|
243 break; |
|
244 } |
|
245 break; |
|
246 } |
|
247 |
|
248 if (iServerProtocol) |
|
249 { |
|
250 iServerProtocol->iFlags = KPppApIsServer; |
|
251 iServerProtocol->InitL(iPppLcp); |
|
252 } |
|
253 } |
|
254 ); // TRAPD |
|
255 |
|
256 if (ret!=KErrNone) |
|
257 { |
|
258 iPppLcp->PhaseAborted(ret); |
|
259 return; |
|
260 } |
|
261 } |
|
262 |
|
263 void CPppAcp::OptFillinConfigRequestL( |
|
264 RPppOptionList& /*aRequestList*/) |
|
265 /** |
|
266 Called when the LCP state machine prepares the initial |
|
267 configuration request. No authentication protocol is proposed |
|
268 here. |
|
269 @param aRequestList Not used */ |
|
270 { |
|
271 // do not add anything to the list |
|
272 } |
|
273 |
|
274 TPppOptResponse CPppAcp::ProposeChap( |
|
275 RPppOption& aOption) |
|
276 /** |
|
277 Sets the option argument to CHAP and the next supported algorithm. |
|
278 The order of negotiation of PPP CHAP algorithms: |
|
279 |
|
280 MS-CHAP-V2 |
|
281 MS-CHAP-V1 |
|
282 CHAP with MD5 |
|
283 |
|
284 When all algorithms were tried the method returns EPppOptReject. |
|
285 @param aOption Returns the updated option |
|
286 @return EPppOptNak if aOption contains valid info |
|
287 EPppOptReject otherwise */ |
|
288 { |
|
289 switch (iCHAPTypeOffered) |
|
290 { |
|
291 case 0: |
|
292 iCHAPTypeOffered = KPppMsChap2AlgorithmNumber; |
|
293 break; |
|
294 case KPppMsChap2AlgorithmNumber: |
|
295 iCHAPTypeOffered = KPppMsChapAlgorithmNumber; |
|
296 break; |
|
297 case KPppMsChapAlgorithmNumber: |
|
298 iCHAPTypeOffered = KPppChapMd5AlgorithmNumber; |
|
299 break; |
|
300 case KPppChapMd5AlgorithmNumber: |
|
301 default: |
|
302 return EPppOptReject; |
|
303 } |
|
304 |
|
305 TUint8* p = aOption.ValuePtr(); |
|
306 |
|
307 BigEndian::Put16(p, (TUint16)KPppIdChap); |
|
308 |
|
309 // There is a problem here due to using aOption as an input/output |
|
310 // parameter if the size of the Data field in the |
|
311 // Authentication-Protocol Configuration Option received in the |
|
312 // aOption parameter is not large enough to allow suggesting CHAP |
|
313 // (i.e. the size is of Data field is 0). This is outside the scope |
|
314 // of the current work, so it is assumed here that RPppOption/RMBuf |
|
315 // meets the requirements. |
|
316 ASSERT(aOption.First()->Size() >= |
|
317 KLCPConfigOptionTypeFieldSize + |
|
318 KLCPConfigOptionLengthFieldSize + |
|
319 KAuthenticationProtocolOptionFieldSize + |
|
320 KChapAlgorithmFieldSize); |
|
321 |
|
322 aOption.SetValueLength( |
|
323 KAuthenticationProtocolOptionFieldSize + |
|
324 KChapAlgorithmFieldSize); |
|
325 p[2] = iCHAPTypeOffered; |
|
326 |
|
327 return EPppOptNak; |
|
328 } |
|
329 |
|
330 TPppOptResponse CPppAcp::ProposePap( |
|
331 RPppOption& aOption) |
|
332 /** |
|
333 Sets the option argument to PAP. |
|
334 @param aOption Returns the updated option |
|
335 @return EPppOptNak if aOption contains valid info |
|
336 EPppOptReject otherwise */ |
|
337 { |
|
338 aOption.SetValueLength(KAuthenticationProtocolOptionFieldSize); |
|
339 |
|
340 TUint8* p = aOption.ValuePtr(); |
|
341 BigEndian::Put16(p, (TUint16)KPppIdPap); |
|
342 |
|
343 return EPppOptNak; |
|
344 } |
|
345 |
|
346 TPppOptResponse CPppAcp::OptCheckConfigRequest( |
|
347 RPppOption& aOption) |
|
348 /** |
|
349 Checks the specified authentication option. The currently supported |
|
350 authentication mode/protocol is specified in the CDMA_SIMIP_AUTH_ALGORITHM |
|
351 field in the packet service table (TCommDbCdmaSimpIpAuthAlgorithm enum). |
|
352 @param aOption Returns the updated option |
|
353 @return EPppOptAck if the proposed authentication option is accepted |
|
354 EPppOptNak if the option is not accepted and another option is being proposed |
|
355 EPppOptReject if the option is not accepted and no other option is proposed */ |
|
356 { |
|
357 // MobileIP, Don't negotiate PAP or CHAP if CDMA MIP. |
|
358 if (iPppLcp->QueryExternalIPConfiguration()) |
|
359 { |
|
360 // Check if we must authenticate always, regardless of the mode. |
|
361 // If the SERVICE_IF_EXTERN_IP_CONFIG_ALWAYS_REJECT_AUTH field is not in CommDB, |
|
362 // doAlwaysAuthenticate remains EFalse. |
|
363 } |
|
364 |
|
365 TUint8* p = aOption.ValuePtr(); |
|
366 |
|
367 if (aOption.ValueLength() < |
|
368 KAuthenticationProtocolOptionFieldSize) |
|
369 return EPppOptReject; |
|
370 |
|
371 // always return from every conditional branch of the following |
|
372 switch (BigEndian::Get16(p)) |
|
373 { |
|
374 case KPppIdPap: |
|
375 if (aOption.ValueLength() != |
|
376 KAuthenticationProtocolOptionFieldSize) |
|
377 { |
|
378 // malformed PAP Authentication-Protocol Option - reject |
|
379 return EPppOptReject; |
|
380 } |
|
381 break; |
|
382 case KPppIdChap: |
|
383 if (aOption.ValueLength() != |
|
384 KAuthenticationProtocolOptionFieldSize + |
|
385 KChapAlgorithmFieldSize) |
|
386 { |
|
387 // malformed CHAP Authentication-Protocol Option - reject |
|
388 return EPppOptReject; |
|
389 } |
|
390 break; |
|
391 default: |
|
392 // unrecognized authentication protocol |
|
393 |
|
394 break; |
|
395 } |
|
396 #ifndef SYMBIAN_EXCLUDE_CDMA |
|
397 return TPppOptResponse(); |
|
398 #endif |
|
399 } |
|
400 |
|
401 void CPppAcp::OptApplyConfigRequest( |
|
402 RPppOption& aOption) |
|
403 /** |
|
404 The specified configuration option from the server config request |
|
405 has been accepted, the negotiation result is stored. |
|
406 @param aOption Accepted authentication option */ |
|
407 { |
|
408 iClientId = BigEndian::Get16(aOption.ValuePtr()); |
|
409 TInt n = aOption.ValueLength()-2; |
|
410 if (n>0) |
|
411 iClientSubId = *(aOption.ValuePtr()+2); |
|
412 } |
|
413 |
|
414 void CPppAcp::OptRecvConfigAck( |
|
415 RPppOption& aOption) |
|
416 /** |
|
417 The specified configuration option has been acked by the server, |
|
418 the negotiation result is stored. |
|
419 @param aOption Acked authentication option */ |
|
420 { |
|
421 iServerId = BigEndian::Get16(aOption.ValuePtr()); |
|
422 TInt n = aOption.ValueLength()-2; |
|
423 if (n>0) |
|
424 iServerSubId = *(aOption.ValuePtr()+2); |
|
425 } |
|
426 |
|
427 void CPppAcp::OptRecvConfigNak( |
|
428 RPppOption& aOption, |
|
429 RPppOptionList& aReqList) |
|
430 /** |
|
431 The specified configuration option has been nacked by the server, |
|
432 the option is replaced in the option list |
|
433 @param aOption Nacked authentication option |
|
434 @param aReqList List to be updated */ |
|
435 { |
|
436 aReqList.ReplaceOption(aOption); |
|
437 } |
|
438 |
|
439 void CPppAcp::OptRecvConfigReject( |
|
440 RPppOption& aOption, |
|
441 RPppOptionList& aReqList) |
|
442 /** |
|
443 The specified configuration option has been rejected by the server, |
|
444 the option is removed from the option list |
|
445 @param aOption Rejected authentication option |
|
446 @param aReqList List to be updated */ |
|
447 { |
|
448 aReqList.RemoveOption(aOption); |
|
449 } |