Source code of Windows XP (NT5)
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.

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