Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2131 lines
60 KiB

  1. /********************************************************************/
  2. /** Copyright(c) 1985-1997 Microsoft Corporation. **/
  3. /********************************************************************/
  4. //***
  5. //
  6. // Filename: raseap.c
  7. //
  8. // Description: Main module that will do interfacing between the PPP engine
  9. // and the various EAP modules.
  10. //
  11. // History: May 11,1997 NarenG Created original version.
  12. //
  13. #define UNICODE
  14. #include <nt.h>
  15. #include <ntrtl.h>
  16. #include <nturtl.h>
  17. #include <ntlsa.h>
  18. #include <ntmsv1_0.h>
  19. #include <ntsamp.h>
  20. #include <crypt.h>
  21. #include <windows.h>
  22. #include <lmcons.h>
  23. #include <string.h>
  24. #include <stdlib.h>
  25. #include <rasman.h>
  26. #include <pppcp.h>
  27. #include <mprlog.h>
  28. #include <mprerror.h>
  29. #include <raserror.h>
  30. #include <rtutils.h>
  31. #include <rasauth.h>
  32. #include <raseapif.h>
  33. #define INCL_PWUTIL
  34. #define INCL_HOSTWIRE
  35. #define INCL_RASAUTHATTRIBUTES
  36. #include <ppputil.h>
  37. #include <raseapif.h>
  38. #define RASEAPGLOBALS
  39. #include "raseap.h"
  40. #include "bltincps.h"
  41. VOID
  42. ProcessResumeNotification()
  43. {
  44. DWORD dwIndex;
  45. for(dwIndex = 0; dwIndex < gbldwNumEapProtocols; dwIndex++)
  46. {
  47. gblpEapTable[dwIndex].fFlags |= EAP_FLAG_RESUME_FROM_HIBERNATE;
  48. }
  49. }
  50. //**
  51. //
  52. // Call: LoadEapDlls
  53. //
  54. // Returns: NO_ERROR - Success
  55. // Non-zero returns - Failure
  56. //
  57. // Description: Will load all the EAP dlls installed.
  58. //
  59. DWORD
  60. LoadEapDlls(
  61. VOID
  62. )
  63. {
  64. HKEY hKeyEap = (HKEY)NULL;
  65. LPWSTR pEapDllPath = (LPWSTR)NULL;
  66. LPWSTR pEapDllExpandedPath = (LPWSTR)NULL;
  67. HKEY hKeyEapDll = (HKEY)NULL;
  68. DWORD dwRetCode;
  69. DWORD dwNumSubKeys;
  70. DWORD dwMaxSubKeySize;
  71. DWORD dwNumValues;
  72. DWORD cbMaxValNameLen;
  73. DWORD cbMaxValueDataSize;
  74. DWORD dwKeyIndex;
  75. WCHAR wchSubKeyName[200];
  76. HINSTANCE hInstance;
  77. FARPROC pRasEapGetInfo;
  78. DWORD cbSubKeyName;
  79. DWORD dwSecDescLen;
  80. DWORD cbSize;
  81. DWORD dwType;
  82. DWORD dwEapTypeId;
  83. gbldwNumEapProtocols = 0;
  84. //
  85. // Open the EAP key
  86. //
  87. dwRetCode = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  88. RAS_EAP_REGISTRY_LOCATION,
  89. 0,
  90. KEY_READ,
  91. &hKeyEap );
  92. if ( dwRetCode != NO_ERROR )
  93. {
  94. EapLogErrorString( ROUTERLOG_CANT_OPEN_PPP_REGKEY,0,NULL, dwRetCode,0);
  95. return( dwRetCode );
  96. }
  97. //
  98. // Find out how many EAP DLLs there are
  99. //
  100. dwRetCode = RegQueryInfoKey(
  101. hKeyEap,
  102. NULL,
  103. NULL,
  104. NULL,
  105. &dwNumSubKeys,
  106. &dwMaxSubKeySize,
  107. NULL,
  108. &dwNumValues,
  109. &cbMaxValNameLen,
  110. &cbMaxValueDataSize,
  111. NULL,
  112. NULL );
  113. if ( dwRetCode != NO_ERROR )
  114. {
  115. EapLogErrorString(ROUTERLOG_CANT_OPEN_PPP_REGKEY,0,NULL, dwRetCode,0);
  116. RegCloseKey( hKeyEap );
  117. return( dwRetCode );
  118. }
  119. //
  120. // Allocate space in the table to hold information for each one
  121. //
  122. gblpEapTable=(EAP_INFO*)LocalAlloc(LPTR,sizeof(EAP_INFO)*dwNumSubKeys);
  123. if ( gblpEapTable == NULL )
  124. {
  125. RegCloseKey( hKeyEap );
  126. return( GetLastError() );
  127. }
  128. //
  129. // Read the registry to find out the various EAPs to load.
  130. //
  131. for ( dwKeyIndex = 0; dwKeyIndex < dwNumSubKeys; dwKeyIndex++ )
  132. {
  133. cbSubKeyName = sizeof( wchSubKeyName ) / sizeof(TCHAR);
  134. dwRetCode = RegEnumKeyEx(
  135. hKeyEap,
  136. dwKeyIndex,
  137. wchSubKeyName,
  138. &cbSubKeyName,
  139. NULL,
  140. NULL,
  141. NULL,
  142. NULL );
  143. if ( ( dwRetCode != NO_ERROR ) &&
  144. ( dwRetCode != ERROR_MORE_DATA ) &&
  145. ( dwRetCode != ERROR_NO_MORE_ITEMS ) )
  146. {
  147. EapLogErrorString(ROUTERLOG_CANT_ENUM_REGKEYVALUES,0,
  148. NULL,dwRetCode,0);
  149. break;
  150. }
  151. else
  152. {
  153. if ( dwRetCode == ERROR_NO_MORE_ITEMS )
  154. {
  155. dwRetCode = NO_ERROR;
  156. break;
  157. }
  158. }
  159. dwRetCode = RegOpenKeyEx(
  160. hKeyEap,
  161. wchSubKeyName,
  162. 0,
  163. KEY_QUERY_VALUE,
  164. &hKeyEapDll );
  165. if ( dwRetCode != NO_ERROR )
  166. {
  167. EapLogErrorString( ROUTERLOG_CANT_OPEN_PPP_REGKEY,0,NULL,
  168. dwRetCode,0);
  169. break;
  170. }
  171. dwEapTypeId = _wtol( wchSubKeyName );
  172. //
  173. // Find out the size of the path value.
  174. //
  175. dwRetCode = RegQueryInfoKey(
  176. hKeyEapDll,
  177. NULL,
  178. NULL,
  179. NULL,
  180. NULL,
  181. NULL,
  182. NULL,
  183. NULL,
  184. &cbMaxValNameLen,
  185. &cbMaxValueDataSize,
  186. NULL,
  187. NULL
  188. );
  189. if ( dwRetCode != NO_ERROR )
  190. {
  191. EapLogErrorString(ROUTERLOG_CANT_OPEN_PPP_REGKEY,0,NULL,
  192. dwRetCode,0);
  193. break;
  194. }
  195. //
  196. // Allocate space for path and add one for NULL terminator
  197. //
  198. cbMaxValueDataSize += sizeof( WCHAR );
  199. pEapDllPath = (LPWSTR)LocalAlloc( LPTR, cbMaxValueDataSize );
  200. if ( pEapDllPath == (LPWSTR)NULL )
  201. {
  202. dwRetCode = GetLastError();
  203. EapLogError( ROUTERLOG_NOT_ENOUGH_MEMORY, 0, NULL, dwRetCode);
  204. break;
  205. }
  206. //
  207. // Read in the path
  208. //
  209. dwRetCode = RegQueryValueEx(
  210. hKeyEapDll,
  211. RAS_EAP_VALUENAME_PATH,
  212. NULL,
  213. &dwType,
  214. (LPBYTE)pEapDllPath,
  215. &cbMaxValueDataSize );
  216. if ( dwRetCode != NO_ERROR )
  217. {
  218. EapLogError(ROUTERLOG_CANT_GET_REGKEYVALUES, 0, NULL, dwRetCode );
  219. break;
  220. }
  221. if ( ( dwType != REG_EXPAND_SZ ) && ( dwType != REG_SZ ) )
  222. {
  223. dwRetCode = ERROR_REGISTRY_CORRUPT;
  224. EapLogError( ROUTERLOG_CANT_GET_REGKEYVALUES, 0, NULL, dwRetCode );
  225. break;
  226. }
  227. //
  228. // Replace the %SystemRoot% with the actual path.
  229. //
  230. cbSize = ExpandEnvironmentStrings( pEapDllPath, NULL, 0 );
  231. if ( cbSize == 0 )
  232. {
  233. dwRetCode = GetLastError();
  234. EapLogError( ROUTERLOG_CANT_GET_REGKEYVALUES, 0, NULL, dwRetCode );
  235. break;
  236. }
  237. pEapDllExpandedPath = (LPWSTR)LocalAlloc( LPTR, cbSize*sizeof(WCHAR) );
  238. if ( pEapDllExpandedPath == (LPWSTR)NULL )
  239. {
  240. dwRetCode = GetLastError();
  241. EapLogError( ROUTERLOG_NOT_ENOUGH_MEMORY, 0, NULL, dwRetCode);
  242. break;
  243. }
  244. cbSize = ExpandEnvironmentStrings( pEapDllPath,
  245. pEapDllExpandedPath,
  246. cbSize );
  247. if ( cbSize == 0 )
  248. {
  249. dwRetCode = GetLastError();
  250. EapLogError(ROUTERLOG_CANT_GET_REGKEYVALUES,0,NULL,dwRetCode);
  251. break;
  252. }
  253. hInstance = LoadLibrary( pEapDllExpandedPath );
  254. if ( hInstance == (HINSTANCE)NULL )
  255. {
  256. dwRetCode = GetLastError();
  257. EapLogErrorString( ROUTERLOG_PPP_CANT_LOAD_DLL,1,
  258. &pEapDllExpandedPath,dwRetCode, 1);
  259. break;
  260. }
  261. gblpEapTable[dwKeyIndex].hInstance = hInstance;
  262. gbldwNumEapProtocols++;
  263. pRasEapGetInfo = GetProcAddress( hInstance, "RasEapGetInfo" );
  264. if ( pRasEapGetInfo == (FARPROC)NULL )
  265. {
  266. dwRetCode = GetLastError();
  267. EapLogErrorString( ROUTERLOG_PPPCP_DLL_ERROR, 1,
  268. &pEapDllExpandedPath, dwRetCode, 1);
  269. break;
  270. }
  271. gblpEapTable[dwKeyIndex].RasEapInfo.dwSizeInBytes =
  272. sizeof( PPP_EAP_INFO );
  273. dwRetCode = (DWORD) (*pRasEapGetInfo)( dwEapTypeId,
  274. &(gblpEapTable[dwKeyIndex].RasEapInfo));
  275. if ( dwRetCode != NO_ERROR )
  276. {
  277. EapLogErrorString(ROUTERLOG_PPPCP_DLL_ERROR, 1,
  278. &pEapDllExpandedPath, dwRetCode, 1);
  279. break;
  280. }
  281. //
  282. // Also initialize the GetCredentials entrypoint if available.
  283. //
  284. gblpEapTable[dwKeyIndex].RasEapGetCredentials = (DWORD (*) (
  285. DWORD,VOID *, VOID **)) GetProcAddress(
  286. hInstance,
  287. "RasEapGetCredentials");
  288. #if DBG
  289. if(NULL != gblpEapTable[dwKeyIndex].RasEapGetCredentials)
  290. {
  291. EAP_TRACE1("GetCredentials entry point found for typeid %d",
  292. dwEapTypeId);
  293. }
  294. #endif
  295. if ( gblpEapTable[dwKeyIndex].RasEapInfo.RasEapInitialize != NULL )
  296. {
  297. dwRetCode = gblpEapTable[dwKeyIndex].RasEapInfo.RasEapInitialize(
  298. TRUE );
  299. if ( dwRetCode != NO_ERROR )
  300. {
  301. EapLogErrorString(ROUTERLOG_PPPCP_DLL_ERROR, 1,
  302. &pEapDllExpandedPath, dwRetCode, 1);
  303. break;
  304. }
  305. }
  306. EAP_TRACE1("Successfully loaded EAP DLL type id = %d", dwEapTypeId );
  307. RegCloseKey( hKeyEapDll );
  308. hKeyEapDll = (HKEY)NULL;
  309. LocalFree( pEapDllExpandedPath );
  310. pEapDllExpandedPath = NULL;
  311. LocalFree( pEapDllPath );
  312. pEapDllPath = (LPWSTR)NULL;
  313. }
  314. if ( hKeyEap != (HKEY)NULL )
  315. {
  316. RegCloseKey( hKeyEap );
  317. }
  318. if ( hKeyEapDll == (HKEY)NULL )
  319. {
  320. RegCloseKey( hKeyEapDll );
  321. }
  322. if ( pEapDllPath != (LPWSTR)NULL )
  323. {
  324. LocalFree( pEapDllPath );
  325. }
  326. if ( pEapDllExpandedPath != NULL )
  327. {
  328. LocalFree( pEapDllExpandedPath );
  329. }
  330. return( dwRetCode );
  331. }
  332. //**
  333. //
  334. // Call: EapInit
  335. //
  336. // Returns: NO_ERROR - Success
  337. // Non-zero returns - Failure
  338. //
  339. // Description: Called to initialize/uninitialize this CP. In the former case,
  340. // fInitialize will be TRUE; in the latter case, it will be FALSE.
  341. //
  342. DWORD
  343. EapInit(
  344. IN BOOL fInitialize
  345. )
  346. {
  347. DWORD dwError;
  348. if ( fInitialize )
  349. {
  350. g_dwTraceIdEap = TraceRegister( TEXT("RASEAP") );
  351. g_hLogEvents = RouterLogRegister( TEXT("RemoteAccess") );
  352. if ( ( dwError = LoadEapDlls() ) != NO_ERROR )
  353. {
  354. if ( g_dwTraceIdEap != INVALID_TRACEID )
  355. {
  356. TraceDeregister( g_dwTraceIdEap );
  357. g_dwTraceIdEap = INVALID_TRACEID;
  358. }
  359. if ( g_hLogEvents != NULL )
  360. {
  361. RouterLogDeregister( g_hLogEvents );
  362. g_hLogEvents = NULL;
  363. }
  364. if ( gblpEapTable != NULL )
  365. {
  366. LocalFree( gblpEapTable );
  367. gblpEapTable = NULL;
  368. }
  369. gbldwNumEapProtocols = 0;
  370. return( dwError );
  371. }
  372. }
  373. else
  374. {
  375. if ( g_dwTraceIdEap != INVALID_TRACEID )
  376. {
  377. TraceDeregister( g_dwTraceIdEap );
  378. g_dwTraceIdEap = INVALID_TRACEID;
  379. }
  380. if ( g_hLogEvents != NULL )
  381. {
  382. RouterLogDeregister( g_hLogEvents );
  383. g_hLogEvents = NULL;
  384. }
  385. if ( gblpEapTable != NULL )
  386. {
  387. DWORD dwIndex;
  388. //
  389. // Unload loaded DLLs
  390. //
  391. for ( dwIndex = 0; dwIndex < gbldwNumEapProtocols; dwIndex++ )
  392. {
  393. if ( gblpEapTable[dwIndex].hInstance != NULL )
  394. {
  395. if ( gblpEapTable[dwIndex].RasEapInfo.RasEapInitialize !=
  396. NULL )
  397. {
  398. dwError = gblpEapTable[dwIndex].RasEapInfo.
  399. RasEapInitialize(
  400. FALSE );
  401. if ( dwError != NO_ERROR )
  402. {
  403. EAP_TRACE2(
  404. "RasEapInitialize(%d) failed and returned %d",
  405. gblpEapTable[dwIndex].RasEapInfo.dwEapTypeId,
  406. dwError );
  407. }
  408. }
  409. FreeLibrary( gblpEapTable[dwIndex].hInstance );
  410. gblpEapTable[dwIndex].hInstance = NULL;
  411. }
  412. }
  413. LocalFree( gblpEapTable );
  414. gblpEapTable = NULL;
  415. }
  416. gbldwNumEapProtocols = 0;
  417. }
  418. return(NO_ERROR);
  419. }
  420. //**
  421. //
  422. // Call: EapGetInfo
  423. //
  424. // Returns: NO_ERROR - Success
  425. // Non-zero returns - Failure
  426. //
  427. // Description: Called to get information for all protocols supported in this
  428. // module
  429. //
  430. LONG_PTR
  431. EapGetInfo(
  432. IN DWORD dwProtocolId,
  433. OUT PPPCP_INFO* pInfo
  434. )
  435. {
  436. ZeroMemory( pInfo, sizeof( PPPCP_INFO ) );
  437. pInfo->Protocol = (DWORD )PPP_EAP_PROTOCOL;
  438. lstrcpyA(pInfo->SzProtocolName, "EAP");
  439. pInfo->Recognize = MAXEAPCODE + 1;
  440. pInfo->RasCpInit = EapInit;
  441. pInfo->RasCpBegin = EapBegin;
  442. pInfo->RasCpEnd = EapEnd;
  443. pInfo->RasApMakeMessage = EapMakeMessage;
  444. return( 0 );
  445. }
  446. //**
  447. //
  448. // Call: EapBegin
  449. //
  450. // Returns: NO_ERROR - Success
  451. // Non-zero returns - Failure
  452. //
  453. // Description: Called by the engine to begin a EAP PPP session.
  454. //
  455. DWORD
  456. EapBegin(
  457. OUT VOID** ppWorkBuf,
  458. IN VOID* pInfo
  459. )
  460. {
  461. DWORD dwRetCode;
  462. PPPAP_INPUT* pInput = (PPPAP_INPUT* )pInfo;
  463. EAPCB* pEapCb;
  464. EAP_TRACE1("EapBegin(fServer=%d)",pInput->fServer );
  465. if ( pInput->dwEapTypeToBeUsed != -1 )
  466. {
  467. //
  468. // First check if we support this EAP type
  469. //
  470. if ( GetEapTypeIndex( (BYTE)(pInput->dwEapTypeToBeUsed) ) == -1 )
  471. {
  472. return( ERROR_NOT_SUPPORTED );
  473. }
  474. }
  475. //
  476. // Allocate work buffer.
  477. //
  478. if ( ( pEapCb = (EAPCB* )LocalAlloc( LPTR, sizeof( EAPCB ) ) ) == NULL )
  479. {
  480. return( ERROR_NOT_ENOUGH_MEMORY );
  481. }
  482. pEapCb->hPort = pInput->hPort;
  483. pEapCb->fAuthenticator = pInput->fServer;
  484. pEapCb->fRouter = pInput->fRouter;
  485. pEapCb->fLogon = pInput->fLogon;
  486. pEapCb->fNonInteractive = pInput->fNonInteractive;
  487. pEapCb->fPortWillBeBundled = pInput->fPortWillBeBundled;
  488. pEapCb->fThisIsACallback = pInput->fThisIsACallback;
  489. pEapCb->hTokenImpersonateUser = pInput->hTokenImpersonateUser;
  490. pEapCb->pCustomAuthConnData = pInput->pCustomAuthConnData;
  491. pEapCb->pCustomAuthUserData = pInput->pCustomAuthUserData;
  492. pEapCb->EapState = EAPSTATE_Initial;
  493. pEapCb->dwEapIndex = (DWORD)-1;
  494. pEapCb->dwEapTypeToBeUsed = pInput->dwEapTypeToBeUsed;
  495. if ( !pEapCb->fAuthenticator )
  496. {
  497. DWORD dwErr;
  498. if ( ( pInput->pszDomain != NULL ) &&
  499. ( pInput->pszDomain[0] != (CHAR)NULL ) )
  500. {
  501. strcpy( pEapCb->szIdentity, pInput->pszDomain );
  502. strcat( pEapCb->szIdentity, "\\" );
  503. strcat( pEapCb->szIdentity, pInput->pszUserName );
  504. }
  505. else
  506. {
  507. strcpy( pEapCb->szIdentity, pInput->pszUserName );
  508. }
  509. //EncodePw( pEapCb->chSeed, pEapCb->szPassword );
  510. dwErr = EncodePassword(
  511. strlen(pInput->pszPassword) + 1,
  512. pInput->pszPassword,
  513. &pEapCb->DBPassword);
  514. if(dwErr != NO_ERROR)
  515. {
  516. return dwErr;
  517. }
  518. if ( pInput->EapUIData.pEapUIData != NULL )
  519. {
  520. PPP_EAP_UI_DATA EapUIData;
  521. EapUIData.dwSizeOfEapUIData = pInput->EapUIData.dwSizeOfEapUIData;
  522. EapUIData.dwContextId = pInput->EapUIData.dwContextId;
  523. EapUIData.pEapUIData = LocalAlloc( LPTR,
  524. EapUIData.dwSizeOfEapUIData );
  525. if ( NULL == EapUIData.pEapUIData )
  526. {
  527. LocalFree( pEapCb );
  528. return( ERROR_NOT_ENOUGH_MEMORY );
  529. }
  530. CopyMemory( EapUIData.pEapUIData, pInput->EapUIData.pEapUIData,
  531. EapUIData.dwSizeOfEapUIData );
  532. pEapCb->EapUIData = EapUIData;
  533. }
  534. if(pInput->fConfigInfo & PPPCFG_ResumeFromHibernate)
  535. {
  536. ProcessResumeNotification();
  537. }
  538. }
  539. //
  540. // Register work buffer with engine.
  541. //
  542. *ppWorkBuf = pEapCb;
  543. EAP_TRACE("EapBegin done");
  544. return( NO_ERROR );
  545. }
  546. //**
  547. //
  548. // Call: EapEnd
  549. //
  550. // Returns: NO_ERROR - Success
  551. // Non-zero returns - Failure
  552. //
  553. // Description: Called to end the Eap session initiated by an EapBegin
  554. //
  555. DWORD
  556. EapEnd(
  557. IN VOID* pWorkBuf
  558. )
  559. {
  560. EAPCB* pEapCb = (EAPCB* )pWorkBuf;
  561. EAP_TRACE("EapEnd");
  562. if ( pEapCb == NULL )
  563. {
  564. return( NO_ERROR );
  565. }
  566. EapDllEnd( pEapCb );
  567. if ( pEapCb->pUserAttributes != NULL )
  568. {
  569. RasAuthAttributeDestroy( pEapCb->pUserAttributes );
  570. }
  571. LocalFree( pEapCb->EapUIData.pEapUIData );
  572. //
  573. // Nuke any credentials in memory.
  574. //
  575. RtlSecureZeroMemory( pEapCb, sizeof(EAPCB) );
  576. LocalFree( pEapCb );
  577. return( NO_ERROR );
  578. }
  579. //**
  580. //
  581. // Call: EapExtractMessage
  582. //
  583. // Returns: VOID
  584. //
  585. // Description: If there is any message in the Request/Notification packet, then
  586. // save the string in pResult->szReplyMessage
  587. //
  588. VOID
  589. EapExtractMessage(
  590. IN PPP_CONFIG* pReceiveBuf,
  591. OUT PPPAP_RESULT* pResult )
  592. {
  593. DWORD dwNumBytes;
  594. CHAR* szReplyMessage = NULL;
  595. WORD cbPacket;
  596. cbPacket = WireToHostFormat16( pReceiveBuf->Length );
  597. if ( PPP_CONFIG_HDR_LEN + 1 >= cbPacket )
  598. {
  599. goto LDone;
  600. }
  601. dwNumBytes = cbPacket - PPP_CONFIG_HDR_LEN - 1;
  602. //
  603. // One more for the terminating NULL.
  604. //
  605. szReplyMessage = LocalAlloc( LPTR, dwNumBytes + 1 );
  606. if ( NULL == szReplyMessage )
  607. {
  608. EAP_TRACE( "LocalAlloc failed. Cannot extract server's message." );
  609. goto LDone;
  610. }
  611. CopyMemory( szReplyMessage, pReceiveBuf->Data + 1, dwNumBytes );
  612. LocalFree( pResult->szReplyMessage );
  613. pResult->szReplyMessage = szReplyMessage;
  614. szReplyMessage = NULL;
  615. LDone:
  616. LocalFree( szReplyMessage );
  617. return;
  618. }
  619. //**
  620. //
  621. // Call: EapMakeMessage
  622. //
  623. // Returns: NO_ERROR - Success
  624. // Non-zero returns - Failure
  625. //
  626. // Description: Called to process and/or to send an EAP packet.
  627. //
  628. DWORD
  629. EapMakeMessage(
  630. IN VOID* pWorkBuf,
  631. IN PPP_CONFIG* pReceiveBuf,
  632. OUT PPP_CONFIG* pSendBuf,
  633. IN DWORD cbSendBuf,
  634. OUT PPPAP_RESULT* pResult,
  635. IN PPPAP_INPUT* pInput
  636. )
  637. {
  638. EAPCB* pEapCb = (EAPCB* )pWorkBuf;
  639. EAP_TRACE1("EapMakeMessage,RBuf=%x",pReceiveBuf);
  640. if ( ( pReceiveBuf != NULL ) && ( pReceiveBuf->Code == EAPCODE_Request ) )
  641. {
  642. //
  643. // Always respond to notitication request, with a notification response
  644. //
  645. if ( pReceiveBuf->Data[0] == EAPTYPE_Notification )
  646. {
  647. pSendBuf->Code = EAPCODE_Response;
  648. pSendBuf->Id = pReceiveBuf->Id;
  649. HostToWireFormat16( PPP_CONFIG_HDR_LEN + 1, pSendBuf->Length );
  650. pSendBuf->Data[0] = EAPTYPE_Notification;
  651. pResult->Action = APA_Send;
  652. EapExtractMessage( pReceiveBuf, pResult );
  653. return( NO_ERROR );
  654. }
  655. //
  656. // Always respond to Identity request, with an Identity response
  657. //
  658. if ( pReceiveBuf->Data[0] == EAPTYPE_Identity )
  659. {
  660. pSendBuf->Code = EAPCODE_Response;
  661. pSendBuf->Id = pReceiveBuf->Id;
  662. if ( !pEapCb->fAuthenticator )
  663. {
  664. HostToWireFormat16(
  665. (WORD)(PPP_CONFIG_HDR_LEN+1+strlen(pEapCb->szIdentity)),
  666. pSendBuf->Length );
  667. strcpy( pSendBuf->Data+1, pEapCb->szIdentity );
  668. }
  669. else
  670. {
  671. HostToWireFormat16( (WORD)(PPP_CONFIG_HDR_LEN+1),
  672. pSendBuf->Length );
  673. }
  674. pSendBuf->Data[0] = EAPTYPE_Identity;
  675. pResult->Action = APA_Send;
  676. return( NO_ERROR );
  677. }
  678. }
  679. return
  680. (pEapCb->fAuthenticator)
  681. ? MakeAuthenticatorMessage(
  682. pEapCb, pReceiveBuf, pSendBuf, cbSendBuf, pResult, pInput )
  683. : MakeAuthenticateeMessage(
  684. pEapCb, pReceiveBuf, pSendBuf, cbSendBuf, pResult, pInput );
  685. }
  686. //**
  687. //
  688. // Call: MakeAuthenticateeMessage
  689. //
  690. // Returns: NO_ERROR - Success
  691. // Non-zero returns - Failure
  692. //
  693. // Description: EAP Authenticatee engine
  694. //
  695. DWORD
  696. MakeAuthenticateeMessage(
  697. IN EAPCB* pEapCb,
  698. IN PPP_CONFIG* pReceiveBuf,
  699. OUT PPP_CONFIG* pSendBuf,
  700. IN DWORD cbSendBuf,
  701. OUT PPPAP_RESULT* pResult,
  702. IN PPPAP_INPUT* pInput
  703. )
  704. {
  705. DWORD dwEapIndex;
  706. DWORD dwRetCode = NO_ERROR;
  707. EAP_TRACE("MakeAuthenticateeMessage...");
  708. switch( pEapCb->EapState )
  709. {
  710. case EAPSTATE_Initial:
  711. EAP_TRACE("EAPSTATE_Initial");
  712. if ( pReceiveBuf == NULL )
  713. {
  714. //
  715. // Do nothing. Wait for request from authenticator
  716. //
  717. pResult->Action = APA_NoAction;
  718. break;
  719. }
  720. else
  721. {
  722. if ( pReceiveBuf->Code != EAPCODE_Request )
  723. {
  724. //
  725. // We are authenticatee side so drop everything other than
  726. // requests, since we do not send requests
  727. //
  728. pResult->Action = APA_NoAction;
  729. break;
  730. }
  731. //
  732. // We got a packet, see if we support this EAP type, also that
  733. // we are authorized to use it
  734. //
  735. dwEapIndex = GetEapTypeIndex( pReceiveBuf->Data[0] );
  736. if (( dwEapIndex == -1 ) ||
  737. ( ( pEapCb->dwEapTypeToBeUsed != -1 ) &&
  738. ( dwEapIndex != GetEapTypeIndex( pEapCb->dwEapTypeToBeUsed))))
  739. {
  740. //
  741. // We do not support this type or we are not authorized to use
  742. // it so we NAK with a type we support
  743. //
  744. pSendBuf->Code = EAPCODE_Response;
  745. pSendBuf->Id = pReceiveBuf->Id;
  746. HostToWireFormat16( PPP_CONFIG_HDR_LEN + 2, pSendBuf->Length );
  747. pSendBuf->Data[0] = EAPTYPE_Nak;
  748. if ( pEapCb->dwEapTypeToBeUsed != -1 )
  749. {
  750. pSendBuf->Data[1] = (BYTE)pEapCb->dwEapTypeToBeUsed;
  751. }
  752. else
  753. {
  754. pSendBuf->Data[1] =
  755. (BYTE)gblpEapTable[0].RasEapInfo.dwEapTypeId;
  756. }
  757. pResult->Action = APA_Send;
  758. break;
  759. }
  760. else
  761. {
  762. //
  763. // The EAP type is acceptable to us so we begin authentication
  764. //
  765. if ( (dwRetCode = EapDllBegin(pEapCb, dwEapIndex)) != NO_ERROR )
  766. {
  767. break;
  768. }
  769. pEapCb->EapState = EAPSTATE_Working;
  770. //
  771. // Fall thru
  772. //
  773. }
  774. }
  775. case EAPSTATE_Working:
  776. EAP_TRACE("EAPSTATE_Working");
  777. if ( pReceiveBuf != NULL )
  778. {
  779. if ( ( pReceiveBuf->Code != EAPCODE_Request ) &&
  780. ( pReceiveBuf->Code != EAPCODE_Success ) &&
  781. ( pReceiveBuf->Code != EAPCODE_Failure ) )
  782. {
  783. //
  784. // We are authenticatee side so drop everything other than
  785. // request/success/failure
  786. //
  787. EAP_TRACE("Dropping invlid packet not request/success/failure");
  788. pResult->Action = APA_NoAction;
  789. break;
  790. }
  791. if ( ( pReceiveBuf->Code == EAPCODE_Request ) &&
  792. ( pReceiveBuf->Data[0] !=
  793. gblpEapTable[pEapCb->dwEapIndex].RasEapInfo.dwEapTypeId ) )
  794. {
  795. EAP_TRACE("Dropping invalid request packet with unknown Id");
  796. pResult->Action = APA_NoAction;
  797. break;
  798. }
  799. }
  800. dwRetCode = EapDllWork( pEapCb,
  801. pReceiveBuf,
  802. pSendBuf,
  803. cbSendBuf,
  804. pResult,
  805. pInput );
  806. break;
  807. default:
  808. RTASSERT( FALSE );
  809. break;
  810. }
  811. return( dwRetCode );
  812. }
  813. //**
  814. //
  815. // Call: MakeAuthenticatorMessage
  816. //
  817. // Returns: NO_ERROR - Success
  818. // Non-zero returns - Failure
  819. //
  820. // Description: EAP Authenticator engine
  821. //
  822. DWORD
  823. MakeAuthenticatorMessage(
  824. IN EAPCB* pEapCb,
  825. IN PPP_CONFIG* pReceiveBuf,
  826. OUT PPP_CONFIG* pSendBuf,
  827. IN DWORD cbSendBuf,
  828. OUT PPPAP_RESULT* pResult,
  829. IN PPPAP_INPUT* pInput
  830. )
  831. {
  832. DWORD dwRetCode = NO_ERROR;
  833. DWORD dwEapTypeIndex;
  834. CHAR * pszReplyMessage;
  835. DWORD dwNumBytes;
  836. WORD wLength;
  837. BYTE bCode;
  838. RAS_AUTH_ATTRIBUTE * pAttribute;
  839. EAP_TRACE("MakeAuthenticatorMessage...");
  840. pResult->dwEapTypeId = pEapCb->dwEapTypeToBeUsed;
  841. switch( pEapCb->EapState )
  842. {
  843. case EAPSTATE_IdentityRequestSent:
  844. EAP_TRACE("EAPSTATE_IdentityRequestSent");
  845. if ( pReceiveBuf != NULL )
  846. {
  847. //
  848. // If we received a response to our identity request, then process
  849. // it.
  850. //
  851. if ( ( pReceiveBuf->Code == EAPCODE_Response ) &&
  852. ( pReceiveBuf->Data[0] == EAPTYPE_Identity ) )
  853. {
  854. DWORD dwIdentityLength=WireToHostFormat16(pReceiveBuf->Length);
  855. dwIdentityLength -= ( PPP_CONFIG_HDR_LEN + 1 );
  856. //
  857. // Truncate the identity length if it is greater than UNLEN
  858. //
  859. if ( dwIdentityLength > UNLEN+DNLEN+1 )
  860. {
  861. dwIdentityLength = UNLEN+DNLEN+1;
  862. }
  863. CopyMemory( pEapCb->szIdentity,
  864. pReceiveBuf->Data+1,
  865. dwIdentityLength );
  866. pEapCb->szIdentity[dwIdentityLength] = (CHAR)NULL;
  867. dwRetCode = MakeRequestAttributes( pEapCb, pReceiveBuf );
  868. if ( dwRetCode == NO_ERROR )
  869. {
  870. pResult->pUserAttributes = pEapCb->pUserAttributes;
  871. pEapCb->EapState = EAPSTATE_EapPacketSentToAuthServer;
  872. pResult->Action = APA_Authenticate;
  873. }
  874. }
  875. else
  876. {
  877. //
  878. // Otherwise drop the packet
  879. //
  880. EAP_TRACE("Dropping invalid packet");
  881. pResult->Action = APA_NoAction;
  882. }
  883. break;
  884. }
  885. //
  886. // Else if If timed out, fallthru and resend
  887. //
  888. case EAPSTATE_Initial:
  889. EAP_TRACE("EAPSTATE_Initial");
  890. pEapCb->dwIdExpected = bNextId++;
  891. //
  892. // Create Identity request packet
  893. //
  894. pSendBuf->Code = EAPCODE_Request;
  895. pSendBuf->Id = (BYTE)pEapCb->dwIdExpected;
  896. HostToWireFormat16( PPP_CONFIG_HDR_LEN + 1, pSendBuf->Length );
  897. pSendBuf->Data[0] = EAPTYPE_Identity;
  898. pResult->Action = APA_SendWithTimeout;
  899. pResult->bIdExpected = (BYTE)pEapCb->dwIdExpected;
  900. pEapCb->EapState = EAPSTATE_IdentityRequestSent;
  901. break;
  902. case EAPSTATE_EapPacketSentToAuthServer:
  903. //
  904. // Wait for response from RADIUS authentication provider
  905. // drop all other packets received in the mean time.
  906. //
  907. if ( pInput == NULL )
  908. {
  909. pResult->Action = APA_NoAction;
  910. break;
  911. }
  912. if ( !pInput->fAuthenticationComplete )
  913. {
  914. //
  915. // If authentication was not complete then we do nothing
  916. //
  917. pResult->Action = APA_NoAction;
  918. break;
  919. }
  920. strncpy( pResult->szUserName, pEapCb->szIdentity, UNLEN );
  921. //
  922. // If authentication completed with an error, then we error out
  923. // now, otherwise we process the authentication completion
  924. // event below
  925. //
  926. if ( pInput->dwAuthError != NO_ERROR )
  927. {
  928. EAP_TRACE1("Error %d while processing Access-Request",
  929. pInput->dwAuthError );
  930. return( pInput->dwAuthError );
  931. }
  932. //
  933. // If we got here then the authentication completed successfully,
  934. // ie the RADIUS server returned attributes. First save the state
  935. // attribute from the access challenge if there was one.
  936. //
  937. if ( pEapCb->pStateAttribute != NULL )
  938. {
  939. LocalFree( pEapCb->pStateAttribute );
  940. pEapCb->pStateAttribute = NULL;
  941. }
  942. pAttribute = RasAuthAttributeGet(
  943. raatState,
  944. pInput->pAttributesFromAuthenticator );
  945. if ( pAttribute != NULL )
  946. {
  947. pEapCb->pStateAttribute =
  948. (PBYTE)LocalAlloc(LPTR, pAttribute->dwLength);
  949. if ( pEapCb->pStateAttribute == NULL )
  950. {
  951. return( GetLastError() );
  952. }
  953. CopyMemory( pEapCb->pStateAttribute,
  954. (PBYTE)(pAttribute->Value),
  955. pAttribute->dwLength );
  956. pEapCb->cbStateAttribute = pAttribute->dwLength;
  957. }
  958. //
  959. // Try to get the EAP Message if there is one
  960. //
  961. pAttribute = RasAuthAttributeGet(
  962. raatEAPMessage,
  963. pInput->pAttributesFromAuthenticator );
  964. if ( pAttribute != NULL )
  965. {
  966. //
  967. // Save the send buffer in case we have to resend
  968. //
  969. if ( pEapCb->pEAPSendBuf != NULL )
  970. {
  971. LocalFree( pEapCb->pEAPSendBuf );
  972. pEapCb->cbEAPSendBuf = 0;
  973. }
  974. pszReplyMessage = RasAuthAttributeGetConcatString(
  975. raatReplyMessage,
  976. pInput->pAttributesFromAuthenticator,
  977. &dwNumBytes );
  978. wLength = (USHORT) (PPP_CONFIG_HDR_LEN + 1 + dwNumBytes);
  979. bCode = ((PPP_CONFIG*)(pAttribute->Value))->Code;
  980. if ( ( NULL != pszReplyMessage ) &&
  981. ( wLength <= cbSendBuf ) &&
  982. ( ( bCode == EAPCODE_Success ) ||
  983. ( bCode == EAPCODE_Failure ) ) )
  984. {
  985. pEapCb->pEAPSendBuf = (PBYTE)LocalAlloc( LPTR, wLength );
  986. if ( pEapCb->pEAPSendBuf == NULL )
  987. {
  988. LocalFree( pszReplyMessage );
  989. return( GetLastError() );
  990. }
  991. pEapCb->cbEAPSendBuf = wLength;
  992. pSendBuf->Code = EAPCODE_Request;
  993. pSendBuf->Id = ++((PPP_CONFIG*)(pAttribute->Value))->Id;
  994. HostToWireFormat16( wLength, pSendBuf->Length );
  995. pSendBuf->Data[0] = EAPTYPE_Notification;
  996. CopyMemory( pSendBuf->Data + 1, pszReplyMessage, dwNumBytes );
  997. LocalFree( pszReplyMessage );
  998. CopyMemory( pEapCb->pEAPSendBuf, pSendBuf, wLength );
  999. pResult->Action = APA_SendWithTimeout;
  1000. pResult->bIdExpected = pSendBuf->Id;
  1001. pEapCb->fSendWithTimeoutInteractive = FALSE;
  1002. pEapCb->dwIdExpected = pSendBuf->Id;
  1003. pEapCb->EapState = EAPSTATE_NotificationSentToClient;
  1004. pEapCb->pSavedAttributesFromAuthenticator =
  1005. pInput->pAttributesFromAuthenticator;
  1006. pEapCb->dwSavedAuthResultCode = pInput->dwAuthResultCode;
  1007. EAP_TRACE("Sending notification to client");
  1008. break;
  1009. }
  1010. LocalFree( pszReplyMessage );
  1011. if ( pAttribute->dwLength > cbSendBuf )
  1012. {
  1013. EAP_TRACE( "Need a larger buffer to construct reply" );
  1014. // return( ERROR_BUFFER_TOO_SMALL );
  1015. }
  1016. pEapCb->pEAPSendBuf = (PBYTE)LocalAlloc(LPTR, pAttribute->dwLength);
  1017. if ( pEapCb->pEAPSendBuf == NULL )
  1018. {
  1019. return( GetLastError() );
  1020. }
  1021. EAP_TRACE("Sending packet to client");
  1022. pEapCb->cbEAPSendBuf = pAttribute->dwLength;
  1023. CopyMemory( pEapCb->pEAPSendBuf,
  1024. pAttribute->Value,
  1025. pAttribute->dwLength );
  1026. CopyMemory( pSendBuf, pAttribute->Value, pAttribute->dwLength );
  1027. }
  1028. else
  1029. {
  1030. //
  1031. // No EAP Message attribute returned so fail the authentication
  1032. //
  1033. EAP_TRACE("No EAP Message attribute received, failing auth");
  1034. if ( pInput->dwAuthResultCode == NO_ERROR )
  1035. {
  1036. pInput->dwAuthResultCode = ERROR_AUTHENTICATION_FAILURE;
  1037. }
  1038. }
  1039. if ( pInput->dwAuthResultCode != NO_ERROR )
  1040. {
  1041. //
  1042. // If we failed authentication
  1043. //
  1044. pResult->dwError = pInput->dwAuthResultCode;
  1045. if ( pAttribute == NULL )
  1046. {
  1047. //
  1048. // If there was no EAP packet then we are done
  1049. //
  1050. pResult->Action = APA_Done;
  1051. }
  1052. else
  1053. {
  1054. //
  1055. // If there was an EAP packet returned then simply send it
  1056. //
  1057. pResult->Action = APA_SendAndDone;
  1058. }
  1059. }
  1060. else
  1061. {
  1062. //
  1063. // Otherwise either we succeeded or for some reason, we don't have
  1064. // a success or failure packet.
  1065. //
  1066. if ( pAttribute == NULL )
  1067. {
  1068. //
  1069. // We succeeded but there was no packet to send, so we are
  1070. // done
  1071. //
  1072. pResult->Action = APA_Done;
  1073. }
  1074. else
  1075. {
  1076. //
  1077. // If we succeeded and there is a packet to send and that
  1078. // packet is a success packet, then send it and we are done
  1079. //
  1080. if ( pSendBuf->Code == EAPCODE_Success )
  1081. {
  1082. pResult->Action = APA_SendAndDone;
  1083. }
  1084. else
  1085. {
  1086. pResult->Action = APA_SendWithTimeout;
  1087. pEapCb->fSendWithTimeoutInteractive = FALSE;
  1088. pAttribute = RasAuthAttributeGet(
  1089. raatSessionTimeout,
  1090. pInput->pAttributesFromAuthenticator );
  1091. if ( pAttribute != NULL )
  1092. {
  1093. //
  1094. // If session timeout in Access-Challenge is
  1095. // greater then 10 then send with interactive
  1096. // timeout.
  1097. //
  1098. if ( PtrToUlong(pAttribute->Value) > 10 )
  1099. {
  1100. pResult->Action = APA_SendWithTimeout2;
  1101. pEapCb->fSendWithTimeoutInteractive = TRUE;
  1102. }
  1103. }
  1104. pEapCb->dwIdExpected = pSendBuf->Id;
  1105. pResult->bIdExpected = (BYTE)pEapCb->dwIdExpected;
  1106. pEapCb->EapState = EAPSTATE_EapPacketSentToClient;
  1107. }
  1108. }
  1109. pResult->dwError = NO_ERROR;
  1110. }
  1111. break;
  1112. case EAPSTATE_NotificationSentToClient:
  1113. if ( pReceiveBuf != NULL )
  1114. {
  1115. //
  1116. // Make sure the packet IDs match
  1117. //
  1118. if ( pReceiveBuf->Id != ((PPP_CONFIG*)(pEapCb->pEAPSendBuf))->Id )
  1119. {
  1120. EAP_TRACE("Id of packet recvd doesn't match one sent");
  1121. pResult->Action = APA_NoAction;
  1122. break;
  1123. }
  1124. strncpy( pResult->szUserName, pEapCb->szIdentity, UNLEN );
  1125. pAttribute = RasAuthAttributeGet(
  1126. raatEAPMessage,
  1127. pEapCb->pSavedAttributesFromAuthenticator );
  1128. if ( pAttribute != NULL )
  1129. {
  1130. //
  1131. // Save the send buffer in case we have to resend
  1132. //
  1133. if ( pEapCb->pEAPSendBuf != NULL )
  1134. {
  1135. LocalFree( pEapCb->pEAPSendBuf );
  1136. pEapCb->cbEAPSendBuf = 0;
  1137. }
  1138. if ( pAttribute->dwLength > cbSendBuf )
  1139. {
  1140. EAP_TRACE( "Need a larger buffer to construct reply" );
  1141. // return( ERROR_BUFFER_TOO_SMALL );
  1142. }
  1143. pEapCb->pEAPSendBuf = (PBYTE)LocalAlloc(LPTR, pAttribute->dwLength);
  1144. if ( pEapCb->pEAPSendBuf == NULL )
  1145. {
  1146. return( GetLastError() );
  1147. }
  1148. EAP_TRACE("Sending packet to client");
  1149. pEapCb->cbEAPSendBuf = pAttribute->dwLength;
  1150. CopyMemory( pEapCb->pEAPSendBuf,
  1151. pAttribute->Value,
  1152. pAttribute->dwLength );
  1153. CopyMemory( pSendBuf, pAttribute->Value, pAttribute->dwLength );
  1154. if ( pEapCb->dwSavedAuthResultCode != NO_ERROR )
  1155. {
  1156. //
  1157. // If we failed authentication
  1158. //
  1159. pResult->dwError = pEapCb->dwSavedAuthResultCode;
  1160. pResult->Action = APA_SendAndDone;
  1161. break;
  1162. }
  1163. else if ( EAPCODE_Success == pSendBuf->Code )
  1164. {
  1165. pResult->dwError = NO_ERROR;
  1166. pResult->Action = APA_SendAndDone;
  1167. break;
  1168. }
  1169. }
  1170. pResult->dwError = ERROR_AUTHENTICATION_FAILURE;
  1171. pResult->Action = APA_Done;
  1172. break;
  1173. }
  1174. //
  1175. // Fall thru
  1176. //
  1177. case EAPSTATE_EapPacketSentToClient:
  1178. //
  1179. // If we did not get any input structure, then we either received
  1180. // a packet or we timed out.
  1181. //
  1182. if ( pReceiveBuf != NULL )
  1183. {
  1184. //
  1185. // Make sure the packet IDs match
  1186. //
  1187. if ( pReceiveBuf->Id != ((PPP_CONFIG*)(pEapCb->pEAPSendBuf))->Id )
  1188. {
  1189. EAP_TRACE("Id of packet recvd doesn't match one sent");
  1190. pResult->Action = APA_NoAction;
  1191. break;
  1192. }
  1193. //
  1194. // Save the Eap Type. Make sure that the response from the client
  1195. // contains an authentication Type code, and not something like
  1196. // a Nak.
  1197. //
  1198. if ( ( pReceiveBuf->Code == EAPCODE_Response ) &&
  1199. ( pReceiveBuf->Data[0] > EAPTYPE_Nak ) )
  1200. {
  1201. pEapCb->dwEapTypeToBeUsed = pReceiveBuf->Data[0];
  1202. }
  1203. //
  1204. // We received a packet so simply send it to the RADIUS server
  1205. //
  1206. dwRetCode = MakeRequestAttributes( pEapCb, pReceiveBuf );
  1207. if ( dwRetCode == NO_ERROR )
  1208. {
  1209. pResult->pUserAttributes = pEapCb->pUserAttributes;
  1210. pResult->Action = APA_Authenticate;
  1211. pEapCb->EapState = EAPSTATE_EapPacketSentToAuthServer;
  1212. }
  1213. }
  1214. else
  1215. {
  1216. //
  1217. // We timed out and have to resend
  1218. //
  1219. EAP_TRACE("Timed out, resending packet to client");
  1220. CopyMemory(pSendBuf, pEapCb->pEAPSendBuf, pEapCb->cbEAPSendBuf);
  1221. if ( pEapCb->fSendWithTimeoutInteractive )
  1222. {
  1223. pResult->Action = APA_SendWithTimeout2;
  1224. }
  1225. else
  1226. {
  1227. pResult->Action = APA_SendWithTimeout;
  1228. }
  1229. pResult->bIdExpected = (BYTE)pEapCb->dwIdExpected;
  1230. }
  1231. break;
  1232. default:
  1233. RTASSERT( FALSE );
  1234. break;
  1235. }
  1236. return( dwRetCode );
  1237. }
  1238. //**
  1239. //
  1240. // Call: EapDllBegin
  1241. //
  1242. // Returns: NO_ERROR - Success
  1243. // Non-zero returns - Failure
  1244. //
  1245. // Description: Called to initiate an EAP session for a certain type
  1246. //
  1247. //
  1248. DWORD
  1249. EapDllBegin(
  1250. IN EAPCB * pEapCb,
  1251. IN DWORD dwEapIndex
  1252. )
  1253. {
  1254. PPP_EAP_INPUT PppEapInput;
  1255. WCHAR awszIdentity[DNLEN+UNLEN+2];
  1256. WCHAR awszPassword[PWLEN+1];
  1257. DWORD dwRetCode;
  1258. DWORD cbPassword;
  1259. PBYTE pbPassword;
  1260. EAP_TRACE1("EapDllBegin called for EAP Type %d",
  1261. gblpEapTable[dwEapIndex].RasEapInfo.dwEapTypeId);
  1262. if (0 == MultiByteToWideChar(
  1263. CP_ACP,
  1264. 0,
  1265. pEapCb->szIdentity,
  1266. -1,
  1267. awszIdentity,
  1268. DNLEN+UNLEN+2 ) )
  1269. {
  1270. dwRetCode = GetLastError();
  1271. EAP_TRACE2("MultiByteToWideChar(%s) failed: %d",
  1272. pEapCb->szIdentity,
  1273. dwRetCode);
  1274. return( dwRetCode );
  1275. }
  1276. ZeroMemory( &PppEapInput, sizeof( PppEapInput ) );
  1277. PppEapInput.dwSizeInBytes = sizeof( PPP_EAP_INPUT );
  1278. PppEapInput.fFlags = ( pEapCb->fRouter ?
  1279. RAS_EAP_FLAG_ROUTER : 0 );
  1280. PppEapInput.fFlags |= ( pEapCb->fLogon ?
  1281. RAS_EAP_FLAG_LOGON : 0 );
  1282. PppEapInput.fFlags |= ( pEapCb->fNonInteractive ?
  1283. RAS_EAP_FLAG_NON_INTERACTIVE : 0 );
  1284. if ( !pEapCb->fThisIsACallback && !pEapCb->fPortWillBeBundled )
  1285. {
  1286. PppEapInput.fFlags |= RAS_EAP_FLAG_FIRST_LINK;
  1287. }
  1288. PppEapInput.fAuthenticator = pEapCb->fAuthenticator;
  1289. PppEapInput.pwszIdentity = awszIdentity;
  1290. PppEapInput.pwszPassword = awszPassword;
  1291. PppEapInput.hTokenImpersonateUser = pEapCb->hTokenImpersonateUser;
  1292. PppEapInput.fAuthenticationComplete = FALSE;
  1293. PppEapInput.dwAuthResultCode = NO_ERROR;
  1294. if ( NULL != pEapCb->pCustomAuthConnData )
  1295. {
  1296. PppEapInput.pConnectionData =
  1297. pEapCb->pCustomAuthConnData->abCustomAuthData;
  1298. PppEapInput.dwSizeOfConnectionData =
  1299. pEapCb->pCustomAuthConnData->cbCustomAuthData;
  1300. }
  1301. if ( NULL != pEapCb->pCustomAuthUserData )
  1302. {
  1303. PppEapInput.pUserData =
  1304. pEapCb->pCustomAuthUserData->abCustomAuthData;
  1305. PppEapInput.dwSizeOfUserData =
  1306. pEapCb->pCustomAuthUserData->cbCustomAuthData;
  1307. }
  1308. if ( NULL != pEapCb->EapUIData.pEapUIData )
  1309. {
  1310. PppEapInput.pDataFromInteractiveUI =
  1311. pEapCb->EapUIData.pEapUIData;
  1312. PppEapInput.dwSizeOfDataFromInteractiveUI =
  1313. pEapCb->EapUIData.dwSizeOfEapUIData;
  1314. }
  1315. // DecodePw( pEapCb->chSeed, pEapCb->szPassword );
  1316. dwRetCode = DecodePassword(&pEapCb->DBPassword,
  1317. &cbPassword,
  1318. &pbPassword);
  1319. if(dwRetCode != NO_ERROR)
  1320. {
  1321. return dwRetCode;
  1322. }
  1323. MultiByteToWideChar(
  1324. CP_ACP,
  1325. 0,
  1326. // pEapCb->szPassword,
  1327. pbPassword,
  1328. -1,
  1329. awszPassword,
  1330. PWLEN+1 );
  1331. awszPassword[PWLEN] = 0;
  1332. if( (!pEapCb->fAuthenticator)
  1333. && (gblpEapTable[dwEapIndex].fFlags & EAP_FLAG_RESUME_FROM_HIBERNATE))
  1334. {
  1335. PppEapInput.fFlags |= RAS_EAP_FLAG_RESUME_FROM_HIBERNATE;
  1336. gblpEapTable[dwEapIndex].fFlags &= ~(EAP_FLAG_RESUME_FROM_HIBERNATE);
  1337. EAP_TRACE("Set hibernate flag");
  1338. }
  1339. dwRetCode = gblpEapTable[dwEapIndex].RasEapInfo.RasEapBegin(
  1340. &pEapCb->pWorkBuffer,
  1341. &PppEapInput );
  1342. // EncodePw( pEapCb->chSeed, pEapCb->szPassword );
  1343. RtlSecureZeroMemory(pbPassword, cbPassword);
  1344. LocalFree(pbPassword);
  1345. RtlSecureZeroMemory( awszPassword, sizeof(awszPassword) );
  1346. if ( dwRetCode == NO_ERROR )
  1347. {
  1348. pEapCb->dwEapIndex = dwEapIndex;
  1349. }
  1350. else
  1351. {
  1352. pEapCb->dwEapIndex = (DWORD)-1;
  1353. }
  1354. return( dwRetCode );
  1355. }
  1356. //**
  1357. //
  1358. // Call: EapDllEnd
  1359. //
  1360. // Returns: NO_ERROR - Success
  1361. // Non-zero returns - Failure
  1362. //
  1363. // Description: Called to end an EAP session for a certain type
  1364. //
  1365. //
  1366. DWORD
  1367. EapDllEnd(
  1368. EAPCB * pEapCb
  1369. )
  1370. {
  1371. DWORD dwRetCode = NO_ERROR;
  1372. EAP_TRACE1("EapDllEnd called for EAP Index %d", pEapCb->dwEapIndex );
  1373. if ( pEapCb->pWorkBuffer != NULL )
  1374. {
  1375. //
  1376. // On the server, pWorkBuffer must be NULL. IAS must call RasEapEnd.
  1377. //
  1378. if ( pEapCb->dwEapIndex != (DWORD)-1 )
  1379. {
  1380. dwRetCode = gblpEapTable[pEapCb->dwEapIndex].RasEapInfo.RasEapEnd(
  1381. pEapCb->pWorkBuffer );
  1382. }
  1383. pEapCb->pWorkBuffer = NULL;
  1384. }
  1385. if ( pEapCb->pEAPSendBuf != NULL )
  1386. {
  1387. LocalFree( pEapCb->pEAPSendBuf );
  1388. pEapCb->pEAPSendBuf = NULL;
  1389. pEapCb->cbEAPSendBuf = 0;
  1390. }
  1391. FreePassword(&pEapCb->DBPassword);
  1392. if ( pEapCb->pStateAttribute != NULL )
  1393. {
  1394. LocalFree( pEapCb->pStateAttribute );
  1395. pEapCb->pStateAttribute = NULL;
  1396. }
  1397. pEapCb->dwEapIndex = (DWORD)-1;
  1398. return( dwRetCode );
  1399. }
  1400. //**
  1401. //
  1402. // Call: EapDllWork
  1403. //
  1404. // Returns: NO_ERROR - Success
  1405. // Non-zero returns - Failure
  1406. //
  1407. // Description: Called to process an incomming packet or timeout etc
  1408. //
  1409. DWORD
  1410. EapDllWork(
  1411. IN EAPCB * pEapCb,
  1412. IN PPP_CONFIG* pReceiveBuf,
  1413. OUT PPP_CONFIG* pSendBuf,
  1414. IN DWORD cbSendBuf,
  1415. OUT PPPAP_RESULT* pResult,
  1416. IN PPPAP_INPUT* pInput
  1417. )
  1418. {
  1419. PPP_EAP_OUTPUT PppEapOutput;
  1420. PPP_EAP_INPUT PppEapInput;
  1421. DWORD dwRetCode;
  1422. CHAR * pChar = NULL;
  1423. EAP_TRACE1("EapDllWork called for EAP Type %d",
  1424. gblpEapTable[pEapCb->dwEapIndex].RasEapInfo.dwEapTypeId);
  1425. ZeroMemory( &PppEapOutput, sizeof( PppEapOutput ) );
  1426. PppEapOutput.dwSizeInBytes = sizeof( PppEapOutput );
  1427. ZeroMemory( &PppEapInput, sizeof( PppEapInput ) );
  1428. PppEapInput.dwSizeInBytes = sizeof( PPP_EAP_INPUT );
  1429. PppEapInput.fAuthenticator = pEapCb->fAuthenticator;
  1430. PppEapInput.hTokenImpersonateUser = pEapCb->hTokenImpersonateUser;
  1431. if ( pInput != NULL )
  1432. {
  1433. PppEapInput.fAuthenticationComplete = pInput->fAuthenticationComplete;
  1434. PppEapInput.dwAuthResultCode = pInput->dwAuthResultCode;
  1435. PppEapInput.fSuccessPacketReceived = pInput->fSuccessPacketReceived;
  1436. if ( pInput->fEapUIDataReceived )
  1437. {
  1438. //
  1439. // EapUIData.pEapUIData is allocated by rasman and freed by engine.
  1440. // raseap.c must not free it.
  1441. //
  1442. if ( pInput->EapUIData.dwContextId != pEapCb->dwUIInvocationId )
  1443. {
  1444. //
  1445. // Ignore this data received
  1446. //
  1447. EAP_TRACE("Out of date data received from UI" );
  1448. return( NO_ERROR );
  1449. }
  1450. PppEapInput.fDataReceivedFromInteractiveUI = TRUE;
  1451. PppEapInput.pDataFromInteractiveUI =
  1452. pInput->EapUIData.pEapUIData;
  1453. PppEapInput.dwSizeOfDataFromInteractiveUI =
  1454. pInput->EapUIData.dwSizeOfEapUIData;
  1455. }
  1456. }
  1457. dwRetCode = gblpEapTable[pEapCb->dwEapIndex].RasEapInfo.RasEapMakeMessage(
  1458. pEapCb->pWorkBuffer,
  1459. (PPP_EAP_PACKET *)pReceiveBuf,
  1460. (PPP_EAP_PACKET *)pSendBuf,
  1461. cbSendBuf,
  1462. &PppEapOutput,
  1463. &PppEapInput );
  1464. if ( dwRetCode != NO_ERROR )
  1465. {
  1466. switch( dwRetCode )
  1467. {
  1468. case ERROR_PPP_INVALID_PACKET:
  1469. EAP_TRACE("Silently discarding invalid EAP packet");
  1470. pResult->Action = APA_NoAction;
  1471. return( NO_ERROR );
  1472. default:
  1473. EAP_TRACE2("EapDLLMakeMessage for type %d returned %d",
  1474. gblpEapTable[pEapCb->dwEapIndex].RasEapInfo.dwEapTypeId,
  1475. dwRetCode );
  1476. break;
  1477. }
  1478. return( dwRetCode );
  1479. }
  1480. switch( PppEapOutput.Action )
  1481. {
  1482. case EAPACTION_NoAction:
  1483. pResult->Action = APA_NoAction;
  1484. EAP_TRACE( "EAP Dll returned Action=EAPACTION_NoAction" );
  1485. break;
  1486. case EAPACTION_Send:
  1487. pResult->Action = APA_Send;
  1488. EAP_TRACE( "EAP Dll returned Action=EAPACTION_Send" );
  1489. break;
  1490. case EAPACTION_Done:
  1491. case EAPACTION_SendAndDone:
  1492. if ( PppEapOutput.Action == EAPACTION_SendAndDone )
  1493. {
  1494. pResult->Action = APA_SendAndDone;
  1495. EAP_TRACE( "EAP Dll returned Action=EAPACTION_SendAndDone" );
  1496. }
  1497. else
  1498. {
  1499. pResult->Action = APA_Done;
  1500. EAP_TRACE( "EAP Dll returned Action=EAPACTION_Done" );
  1501. }
  1502. pResult->dwError = PppEapOutput.dwAuthResultCode;
  1503. pResult->pUserAttributes = PppEapOutput.pUserAttributes;
  1504. strncpy( pResult->szUserName, pEapCb->szIdentity, UNLEN );
  1505. break;
  1506. case EAPACTION_SendWithTimeout:
  1507. case EAPACTION_SendWithTimeoutInteractive:
  1508. case EAPACTION_Authenticate:
  1509. EAP_TRACE1( "EAP Dll returned disallowed Action=%d",
  1510. PppEapOutput.Action );
  1511. break;
  1512. default:
  1513. RTASSERT( FALSE );
  1514. EAP_TRACE1( "EAP Dll returned unknown Action=%d", PppEapOutput.Action );
  1515. break;
  1516. }
  1517. //
  1518. // Check to see if EAP dll wants to bring up UI
  1519. //
  1520. if ( PppEapOutput.fInvokeInteractiveUI )
  1521. {
  1522. if ( pEapCb->fAuthenticator )
  1523. {
  1524. EAP_TRACE( "EAP Dll wants to bring up UI on the server side" );
  1525. return( ERROR_INTERACTIVE_MODE );
  1526. }
  1527. if ( PppEapOutput.pUIContextData != NULL )
  1528. {
  1529. pResult->InvokeEapUIData.dwSizeOfUIContextData =
  1530. PppEapOutput.dwSizeOfUIContextData;
  1531. pResult->InvokeEapUIData.pUIContextData
  1532. = LocalAlloc(LPTR, PppEapOutput.dwSizeOfUIContextData);
  1533. if ( pResult->InvokeEapUIData.pUIContextData == NULL )
  1534. {
  1535. return( ERROR_NOT_ENOUGH_MEMORY );
  1536. }
  1537. CopyMemory( pResult->InvokeEapUIData.pUIContextData,
  1538. PppEapOutput.pUIContextData,
  1539. pResult->InvokeEapUIData.dwSizeOfUIContextData );
  1540. }
  1541. else
  1542. {
  1543. pResult->InvokeEapUIData.pUIContextData = NULL;
  1544. pResult->InvokeEapUIData.dwSizeOfUIContextData = 0;
  1545. }
  1546. pResult->fInvokeEapUI = TRUE;
  1547. pEapCb->dwUIInvocationId = gbldwGuid++;
  1548. pResult->InvokeEapUIData.dwContextId = pEapCb->dwUIInvocationId;
  1549. pResult->InvokeEapUIData.dwEapTypeId =
  1550. gblpEapTable[pEapCb->dwEapIndex].RasEapInfo.dwEapTypeId;
  1551. EAP_TRACE( "EAP Dll wants to invoke interactive UI" );
  1552. }
  1553. pResult->dwEapTypeId = pEapCb->dwEapTypeToBeUsed;
  1554. pResult->fSaveUserData = PppEapOutput.fSaveUserData;
  1555. pResult->pUserData = PppEapOutput.pUserData;
  1556. pResult->dwSizeOfUserData = PppEapOutput.dwSizeOfUserData;
  1557. pResult->fSaveConnectionData = PppEapOutput.fSaveConnectionData;
  1558. pResult->SetCustomAuthData.pConnectionData =
  1559. PppEapOutput.pConnectionData;
  1560. pResult->SetCustomAuthData.dwSizeOfConnectionData =
  1561. PppEapOutput.dwSizeOfConnectionData;
  1562. return( dwRetCode );
  1563. }
  1564. //**
  1565. //
  1566. // Call: GetEapIndex
  1567. //
  1568. // Returns: NO_ERROR - Success
  1569. // Non-zero returns - Failure
  1570. //
  1571. // Description: Will return the index into gblpEapTable of the specified
  1572. // EAP type
  1573. //
  1574. DWORD
  1575. GetEapTypeIndex(
  1576. IN DWORD dwEapTypeId
  1577. )
  1578. {
  1579. DWORD dwIndex;
  1580. for ( dwIndex = 0; dwIndex < gbldwNumEapProtocols; dwIndex++ )
  1581. {
  1582. if ( gblpEapTable[dwIndex].RasEapInfo.dwEapTypeId == dwEapTypeId )
  1583. {
  1584. return( dwIndex );
  1585. }
  1586. }
  1587. return( (DWORD)-1 );
  1588. }
  1589. //**
  1590. //
  1591. // Call: MakeRequestAttributes
  1592. //
  1593. // Returns: NO_ERROR - Success
  1594. // Non-zero returns - Failure
  1595. //
  1596. // Description: Will begin the RADIUS/EAP dialog by sending the caller's
  1597. // identity to the RADIUS server.
  1598. //
  1599. DWORD
  1600. MakeRequestAttributes(
  1601. IN EAPCB * pEapCb,
  1602. IN PPP_CONFIG * pReceiveBuf
  1603. )
  1604. {
  1605. DWORD dwIndex = 0;
  1606. DWORD dwRetCode;
  1607. EAP_TRACE("Sending EAP packet to RADIUS/IAS");
  1608. if ( pEapCb->pUserAttributes != NULL )
  1609. {
  1610. RasAuthAttributeDestroy( pEapCb->pUserAttributes );
  1611. pEapCb->pUserAttributes = NULL;
  1612. }
  1613. //
  1614. // Allocate the appropriate amount + 1 for Identity + 1 more for EAP packet
  1615. // +1 for State attribute (if any).
  1616. //
  1617. if ( ( pEapCb->pUserAttributes = RasAuthAttributeCreate(
  1618. ( pEapCb->pStateAttribute != NULL )
  1619. ? 3
  1620. : 2 ) ) == NULL )
  1621. {
  1622. return( GetLastError() );
  1623. }
  1624. //
  1625. // Insert EAP Message
  1626. //
  1627. dwRetCode = RasAuthAttributeInsert( dwIndex++,
  1628. pEapCb->pUserAttributes,
  1629. raatEAPMessage,
  1630. FALSE,
  1631. WireToHostFormat16(pReceiveBuf->Length),
  1632. pReceiveBuf );
  1633. if ( dwRetCode != NO_ERROR )
  1634. {
  1635. RasAuthAttributeDestroy( pEapCb->pUserAttributes );
  1636. pEapCb->pUserAttributes = NULL;
  1637. return( dwRetCode );
  1638. }
  1639. //
  1640. // Insert username
  1641. //
  1642. dwRetCode = RasAuthAttributeInsert( dwIndex++,
  1643. pEapCb->pUserAttributes,
  1644. raatUserName,
  1645. FALSE,
  1646. strlen( pEapCb->szIdentity ),
  1647. pEapCb->szIdentity );
  1648. if ( dwRetCode != NO_ERROR )
  1649. {
  1650. RasAuthAttributeDestroy( pEapCb->pUserAttributes );
  1651. pEapCb->pUserAttributes = NULL;
  1652. return( dwRetCode );
  1653. }
  1654. //
  1655. // Insert State attribute if we have one
  1656. //
  1657. if ( pEapCb->pStateAttribute != NULL )
  1658. {
  1659. dwRetCode = RasAuthAttributeInsert(
  1660. dwIndex++,
  1661. pEapCb->pUserAttributes,
  1662. raatState,
  1663. FALSE,
  1664. pEapCb->cbStateAttribute,
  1665. pEapCb->pStateAttribute );
  1666. if ( dwRetCode != NO_ERROR )
  1667. {
  1668. RasAuthAttributeDestroy( pEapCb->pUserAttributes );
  1669. pEapCb->pUserAttributes = NULL;
  1670. return( dwRetCode );
  1671. }
  1672. }
  1673. return( NO_ERROR );
  1674. }
  1675. DWORD
  1676. EapGetCredentials(
  1677. VOID * pWorkBuf,
  1678. VOID ** ppCredentials)
  1679. {
  1680. EAPCB *pEapCb = (EAPCB *) pWorkBuf;
  1681. DWORD dwRetCode = ERROR_SUCCESS;
  1682. if( (NULL == pEapCb)
  1683. || (NULL == ppCredentials))
  1684. {
  1685. return E_INVALIDARG;
  1686. }
  1687. if(NULL != gblpEapTable[pEapCb->dwEapIndex].RasEapGetCredentials)
  1688. {
  1689. //
  1690. // Invoke appropriate eap dll for credentials
  1691. //
  1692. dwRetCode =
  1693. gblpEapTable[pEapCb->dwEapIndex].RasEapGetCredentials(
  1694. pEapCb->dwEapTypeToBeUsed,
  1695. pEapCb->pWorkBuffer,
  1696. ppCredentials);
  1697. }
  1698. return dwRetCode;
  1699. }