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.

5602 lines
168 KiB

  1. /********************************************************************/
  2. /** Copyright(c) 1985-1997 Microsoft Corporation. **/
  3. /********************************************************************/
  4. //***
  5. //
  6. // Filename: eapchap.c
  7. //
  8. // Description: Will do MD5 CHAP for EAP. This module is a EAP wrapper
  9. // around CHAP
  10. //
  11. // History: May 11,1997 NarenG Created original version.
  12. //
  13. #include <nt.h>
  14. #include <ntrtl.h>
  15. #include <nturtl.h>
  16. #include <ntlsa.h>
  17. #include <ntmsv1_0.h>
  18. #include <ntsamp.h>
  19. #define SECURITY_WIN32
  20. #include <security.h> // For GetUserNameExW
  21. #include <crypt.h>
  22. #include <windows.h>
  23. #include <lmcons.h>
  24. #include <string.h>
  25. #include <stdlib.h>
  26. #include <rasman.h>
  27. #include <pppcp.h>
  28. #include <raserror.h>
  29. #include <rtutils.h>
  30. #include <md5.h>
  31. #include <raseapif.h>
  32. #include <eaptypeid.h>
  33. #include <pppcp.h>
  34. #define INCL_RASAUTHATTRIBUTES
  35. #define INCL_PWUTIL
  36. #define INCL_HOSTWIRE
  37. #include <ppputil.h>
  38. #include <raschap.h>
  39. #include <wincrypt.h>
  40. #include <wintrust.h>
  41. #include <softpub.h>
  42. #include <mscat.h>
  43. #include <ezlogon.h>
  44. #include "resource.h"
  45. #define STRSAFE_NO_DEPRECATE
  46. #include <strsafe.h>
  47. #define EAPTYPE_MD5Challenge 4
  48. //
  49. // We need to move this definition to pppcp.h
  50. //
  51. #define VENDOR_MICROSOFT 311
  52. //
  53. // Various states that EAPMSCHAPv2 can be in.
  54. //
  55. #define EAPMSCHAPv2STATE enum tagEAPMSCHAPv2STATE
  56. EAPMSCHAPv2STATE
  57. {
  58. EMV2_Initial,
  59. EMV2_RequestSend,
  60. EMV2_ResponseSend,
  61. EMV2_CHAPAuthSuccess,
  62. EMV2_CHAPAuthFail,
  63. EMV2_Success,
  64. EMV2_Failure
  65. };
  66. //
  67. // These ids are pulled in from rasdlg. Need them for the
  68. // change password dialog in case of winlogon scenario
  69. //
  70. #define DID_CP_ChangePassword2 109
  71. #define CID_CP_EB_ConfirmPassword_RASDLG 1058
  72. #define CID_CP_EB_OldPassword_RASDLG 1059
  73. #define CID_CP_EB_Password_RASDLG 1060
  74. //
  75. // Reg Key for EAPMSCHAPv2
  76. //
  77. #define EAPMSCHAPv2_KEY "System\\CurrentControlSet\\Services\\Rasman\\PPP\\EAP\\26"
  78. #define EAPMSCHAPv2_VAL_SERVER_CONFIG_DATA "ServerConfigData"
  79. //
  80. //
  81. // Flags for EAPMSChapv2
  82. //
  83. //
  84. /*
  85. ** SaveUid and password
  86. */
  87. #define EAPMSCHAPv2_FLAG_SAVE_UID_PWD 0x00000001
  88. /*
  89. ** Use Winlogon Credentials
  90. */
  91. #define EAPMSCHAPv2_FLAG_USE_WINLOGON_CREDS 0x00000002
  92. /*
  93. ** Allow Change password - server side only.
  94. */
  95. #define EAPMSCHAPv2_FLAG_ALLOW_CHANGEPWD 0x00000004
  96. /*
  97. ** MACHINE Auth is happening
  98. */
  99. #define EAPMSCHAPv2_FLAG_MACHINE_AUTH 0x00000008
  100. #define EAPMSCHAPv2_FLAG_CALLED_WITHIN_WINLOGON 0x00000010
  101. #define EAPMSCHAPv2_FLAG_8021x 0x00000020
  102. typedef struct _EAPMSCHAPv2_USER_PROPERTIES
  103. {
  104. DWORD dwVersion; //Version = 2
  105. DWORD fFlags;
  106. //This is a server config property. Tells the server
  107. //how many retris are allowed
  108. DWORD dwMaxRetries;
  109. CHAR szUserName[UNLEN+1];
  110. CHAR szPassword[PWLEN+1];
  111. CHAR szDomain[DNLEN+1];
  112. DWORD cbEncPassword; //Number of bytes in encrypted password
  113. BYTE bEncPassword[1]; //Encrypted Password if any ...
  114. }EAPMSCHAPv2_USER_PROPERTIES, *PEAPMSCHAPv2_USER_PROPERTIES;
  115. //
  116. // USER properties for EAPMSCHAPv2
  117. //
  118. typedef struct _EAPMSCHAPv2_USER_PROPERTIES_v1
  119. {
  120. DWORD dwVersion;
  121. DWORD fFlags;
  122. //This is a server config property. Tells the server
  123. //how many retris are allowed
  124. DWORD dwMaxRetries;
  125. CHAR szUserName[UNLEN+1];
  126. CHAR szPassword[PWLEN+1];
  127. CHAR szDomain[DNLEN+1];
  128. }EAPMSCHAPv2_USER_PROPERTIES_v1, *PEAPMSCHAPv2_USER_PROPERTIES_v1;
  129. //
  130. // CONNECTION properties for EAPMSCHAPv2
  131. //
  132. typedef struct _EAPMSCHAPv2_CONN_PROPERTIES
  133. {
  134. DWORD dwVersion;
  135. //This is the only field for now. Maybe more will come in later.
  136. DWORD fFlags;
  137. }EAPMSCHAPv2_CONN_PROPERTIES, * PEAPMSCHAPv2_CONN_PROPERTIES;
  138. //
  139. // Interactive UI for EAPMSCHAPv2
  140. //
  141. // Flag for retry password ui
  142. #define EAPMSCHAPv2_INTERACTIVE_UI_FLAG_RETRY 0x00000001
  143. //
  144. // flag indicating show the change password in case
  145. // the old password is provided
  146. #define EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD 0x00000002
  147. //
  148. // flag indicating that change password was invoked in
  149. // winlogon context
  150. //
  151. #define EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD_WINLOGON 0x00000004
  152. typedef struct _EAPMSCHAPv2_INTERACTIVE_UI
  153. {
  154. DWORD dwVersion;
  155. DWORD fFlags;
  156. EAPMSCHAPv2_USER_PROPERTIES UserProp;
  157. CHAR szNewPassword[PWLEN+1];
  158. }EAPMSCHAPv2_INTERACTIVE_UI, * PEAPMSCHAPv2_INTERACTIVE_UI;
  159. #define EAPMSCHAPv2WB struct tagEAPMSCHAPv2WB
  160. EAPMSCHAPv2WB
  161. {
  162. EAPMSCHAPv2STATE EapState;
  163. DWORD fFlags;
  164. DWORD dwInteractiveUIOperation;
  165. BYTE IdToSend;
  166. BYTE IdToExpect;
  167. PEAPMSCHAPv2_INTERACTIVE_UI pUIContextData;
  168. PEAPMSCHAPv2_USER_PROPERTIES pUserProp;
  169. CHAR szOldPassword[PWLEN+1];
  170. //We need to save this for auth purposes.
  171. WCHAR wszRadiusUserName[UNLEN+DNLEN+1];
  172. PEAPMSCHAPv2_CONN_PROPERTIES pConnProp;
  173. CHAPWB * pwb;
  174. RAS_AUTH_ATTRIBUTE * pUserAttributes;
  175. DWORD dwAuthResultCode;
  176. DWORD dwLSARetCode; //Return value from LSA
  177. };
  178. //
  179. // This structure is shared between retry and
  180. // logon dialog
  181. //
  182. typedef struct _EAPMSCHAPv2_LOGON_DIALOG
  183. {
  184. PEAPMSCHAPv2_USER_PROPERTIES pUserProp;
  185. HWND hWndUserName;
  186. HWND hWndPassword;
  187. HWND hWndDomain;
  188. HWND hWndSavePassword;
  189. }EAPMSCHAPv2_LOGON_DIALOG, * PEAPMSCHAPv2_LOGON_DIALOG;
  190. //
  191. // This stuct is used for client config UI.
  192. //
  193. typedef struct _EAPMSCHAPv2_CLIENTCONFIG_DIALOG
  194. {
  195. PEAPMSCHAPv2_CONN_PROPERTIES pConnProp;
  196. }EAPMSCHAPv2_CLIENTCONFIG_DIALOG, * PEAPMSCHAPv2_CLIENTCONFIG_DIALOG;
  197. typedef struct _EAPMSCHAPv2_SERVERCONFIG_DIALOG
  198. {
  199. PEAPMSCHAPv2_USER_PROPERTIES pUserProp;
  200. HWND hWndRetries;
  201. }EAPMSCHAPv2_SERVERCONFIG_DIALOG, *PEAPMSCHAPv2_SERVERCONFIG_DIALOG;
  202. typedef struct _EAPMSCHAPv2_CHANGEPWD_DIALOG
  203. {
  204. PEAPMSCHAPv2_INTERACTIVE_UI pInteractiveUIData;
  205. HWND hWndNewPassword;
  206. HWND hWndConfirmNewPassword;
  207. HWND hWndOldPassword;
  208. }EAPMSCHAPv2_CHANGEPWD_DIALOG, *PEAPMSCHAPv2_CHANGEPWD_DIALOG;
  209. DWORD
  210. AllocateUserDataWithEncPwd ( EAPMSCHAPv2WB * pEapwb, DATA_BLOB * pDBPassword );
  211. DWORD
  212. EapMSCHAPv2Initialize(
  213. IN BOOL fInitialize
  214. );
  215. INT_PTR CALLBACK
  216. LogonDialogProc(
  217. IN HWND hWnd,
  218. IN UINT unMsg,
  219. IN WPARAM wParam,
  220. IN LPARAM lParam
  221. );
  222. INT_PTR CALLBACK
  223. RetryDialogProc(
  224. IN HWND hWnd,
  225. IN UINT unMsg,
  226. IN WPARAM wParam,
  227. IN LPARAM lParam
  228. );
  229. INT_PTR CALLBACK
  230. ClientConfigDialogProc(
  231. IN HWND hWnd,
  232. IN UINT unMsg,
  233. IN WPARAM wParam,
  234. IN LPARAM lParam
  235. );
  236. INT_PTR CALLBACK
  237. ServerConfigDialogProc(
  238. IN HWND hWnd,
  239. IN UINT unMsg,
  240. IN WPARAM wParam,
  241. IN LPARAM lParam
  242. );
  243. INT_PTR CALLBACK
  244. ChangePasswordDialogProc(
  245. IN HWND hWnd,
  246. IN UINT unMsg,
  247. IN WPARAM wParam,
  248. IN LPARAM lParam
  249. );
  250. HINSTANCE
  251. GetHInstance(
  252. VOID
  253. );
  254. HINSTANCE
  255. GetRasDlgDLLHInstance(
  256. VOID
  257. );
  258. extern DWORD g_dwTraceIdChap;
  259. DWORD
  260. ReadUserData(
  261. IN BYTE* pUserDataIn,
  262. IN DWORD dwSizeOfUserDataIn,
  263. OUT PEAPMSCHAPv2_USER_PROPERTIES* ppUserProp
  264. );
  265. DWORD
  266. ReadConnectionData(
  267. IN BOOL fWirelessConnection,
  268. IN BYTE* pConnectionDataIn,
  269. IN DWORD dwSizeOfConnectionDataIn,
  270. OUT PEAPMSCHAPv2_CONN_PROPERTIES* ppConnProp
  271. );
  272. DWORD
  273. ServerConfigDataIO(
  274. IN BOOL fRead,
  275. IN CHAR* pszMachineName,
  276. IN OUT BYTE** ppData,
  277. IN DWORD dwNumBytes
  278. );
  279. //**
  280. //
  281. // Call: MapEapInputToApInput
  282. //
  283. // Returns: NO_ERROR - Success
  284. // Non-zero returns - Failure
  285. //
  286. // Description:
  287. //
  288. VOID
  289. MapEapInputToApInput(
  290. IN PPP_EAP_INPUT* pPppEapInput,
  291. OUT PPPAP_INPUT * pInput
  292. )
  293. {
  294. pInput->fServer = pPppEapInput->fAuthenticator;
  295. pInput->APDataSize = 1;
  296. pInput->fAuthenticationComplete = pPppEapInput->fAuthenticationComplete;
  297. pInput->dwAuthResultCode = pPppEapInput->dwAuthResultCode;
  298. pInput->dwAuthError = NO_ERROR;
  299. pInput->pUserAttributes = NULL;
  300. pInput->pAttributesFromAuthenticator= pPppEapInput->pUserAttributes;
  301. pInput->fSuccessPacketReceived = pPppEapInput->fSuccessPacketReceived;
  302. pInput->dwInitialPacketId = pPppEapInput->bInitialId;
  303. //
  304. // These are used only for MS-CHAP
  305. //
  306. pInput->pszOldPassword = "";
  307. pInput->dwRetries = 0;
  308. }
  309. //**
  310. //
  311. // Call: MapApInputToEapInput
  312. //
  313. // Returns: NONE
  314. //
  315. //
  316. // Description: $TODO: Put in the correct mapping here
  317. //
  318. VOID
  319. MapApResultToEapOutput(
  320. IN PPPAP_RESULT * pApResult,
  321. OUT PPP_EAP_OUTPUT* pPppEapOutput
  322. )
  323. {
  324. //
  325. //Action is already taken care of. So dont set it here
  326. //
  327. pPppEapOutput->dwAuthResultCode = pApResult->dwError;
  328. pPppEapOutput->pUserAttributes = pApResult->pUserAttributes;
  329. }
  330. //**
  331. //
  332. // Call: EapChapBeginCommon
  333. //
  334. // Returns: NO_ERROR - Success
  335. // Non-zero returns - Failure
  336. //
  337. // Description: Wrapper around ChapBegin
  338. //
  339. DWORD
  340. EapChapBeginCommon(
  341. IN DWORD dwEapType,
  342. IN BOOL fUseWinLogon,
  343. IN DWORD dwRetries,
  344. IN EAPMSCHAPv2WB * pWB,
  345. OUT VOID ** ppWorkBuffer,
  346. IN PPP_EAP_INPUT * pPppEapInput
  347. )
  348. {
  349. PPPAP_INPUT Input;
  350. DWORD dwRetCode;
  351. PPP_EAP_INPUT* pInput = (PPP_EAP_INPUT* )pPppEapInput;
  352. BYTE bMD5 = 0x05;
  353. BYTE bMSChapNew = 0x81;
  354. BYTE bInvalid = 0xFF;
  355. WCHAR * pWchar = NULL;
  356. CHAR szDomain[DNLEN+1];
  357. CHAR szUserName[UNLEN+1];
  358. CHAR szPassword[PWLEN+1];
  359. PPPAP_RESULT ApResult;
  360. TRACE("EapChapBeginCommon");
  361. ZeroMemory( &Input, sizeof( PPPAP_INPUT ) );
  362. ZeroMemory( szDomain, sizeof( szDomain ) );
  363. ZeroMemory( szUserName, sizeof( szUserName ) );
  364. ZeroMemory( szPassword, sizeof( szPassword ) );
  365. ZeroMemory( &ApResult, sizeof(ApResult) );
  366. MapEapInputToApInput( pPppEapInput, &Input );
  367. if ( dwEapType == EAPTYPE_MD5Challenge )
  368. {
  369. Input.pAPData = &bMD5;
  370. }
  371. else if ( dwEapType == PPP_EAP_MSCHAPv2 )
  372. {
  373. Input.pAPData = &bMSChapNew;
  374. }
  375. else
  376. //Set the value to invalid type and let ChapBegin Fail
  377. Input.pAPData = &bInvalid;
  378. //
  379. // If we dont have to use winlogon or we have to do machine auth
  380. //
  381. if ( !fUseWinLogon ||
  382. ( pPppEapInput->fFlags & RAS_EAP_FLAG_MACHINE_AUTH )
  383. )
  384. {
  385. if ( NULL != pPppEapInput->pwszIdentity )
  386. {
  387. pWchar = wcschr( pPppEapInput->pwszIdentity, L'\\' );
  388. if ( pWchar == NULL )
  389. {
  390. if ( 0 == WideCharToMultiByte(
  391. CP_ACP,
  392. 0,
  393. pPppEapInput->pwszIdentity,
  394. -1,
  395. szUserName,
  396. UNLEN + 1,
  397. NULL,
  398. NULL ) )
  399. {
  400. return( GetLastError() );
  401. }
  402. }
  403. else
  404. {
  405. *pWchar = 0;
  406. if ( 0 == WideCharToMultiByte(
  407. CP_ACP,
  408. 0,
  409. pPppEapInput->pwszIdentity,
  410. -1,
  411. szDomain,
  412. DNLEN + 1,
  413. NULL,
  414. NULL ) )
  415. {
  416. return( GetLastError() );
  417. }
  418. *pWchar = L'\\';
  419. if ( 0 == WideCharToMultiByte(
  420. CP_ACP,
  421. 0,
  422. pWchar + 1,
  423. -1,
  424. szUserName,
  425. UNLEN + 1,
  426. NULL,
  427. NULL ) )
  428. {
  429. return( GetLastError() );
  430. }
  431. }
  432. }
  433. if ( dwEapType == EAPTYPE_MD5Challenge )
  434. {
  435. if ( NULL != pPppEapInput->pwszPassword )
  436. {
  437. if ( 0 == WideCharToMultiByte(
  438. CP_ACP,
  439. 0,
  440. pPppEapInput->pwszPassword,
  441. -1,
  442. szPassword,
  443. PWLEN + 1,
  444. NULL,
  445. NULL ) )
  446. {
  447. return( GetLastError() );
  448. }
  449. }
  450. }
  451. else
  452. {
  453. // if this is not a server then copy the user props
  454. if ( !pPppEapInput->fAuthenticator )
  455. {
  456. strncpy( szPassword, pWB->pUserProp->szPassword, PWLEN );
  457. }
  458. }
  459. }
  460. else
  461. {
  462. if ( !pPppEapInput->fAuthenticator &&
  463. !(pPppEapInput->fFlags & RAS_EAP_FLAG_MACHINE_AUTH )
  464. )
  465. {
  466. //Set up the Luid for the logged on user
  467. TOKEN_STATISTICS TokenStats;
  468. DWORD TokenStatsSize;
  469. if (!GetTokenInformation(pPppEapInput->hTokenImpersonateUser,
  470. TokenStatistics,
  471. &TokenStats,
  472. sizeof(TOKEN_STATISTICS),
  473. &TokenStatsSize))
  474. {
  475. dwRetCode = GetLastError();
  476. return dwRetCode;
  477. }
  478. //
  479. // "This will tell us if there was an API failure
  480. // (means our buffer wasn't big enough)"
  481. //
  482. if (TokenStatsSize > sizeof(TOKEN_STATISTICS))
  483. {
  484. dwRetCode = GetLastError();
  485. return dwRetCode;
  486. }
  487. Input.Luid = TokenStats.AuthenticationId;
  488. }
  489. }
  490. Input.dwRetries = dwRetries;
  491. Input.pszDomain = szDomain;
  492. Input.pszUserName = szUserName;
  493. Input.pszPassword = szPassword;
  494. if ( (pPppEapInput->fFlags & RAS_EAP_FLAG_MACHINE_AUTH) )
  495. Input.fConfigInfo |= PPPCFG_MachineAuthentication;
  496. dwRetCode = ChapBegin( ppWorkBuffer, &Input );
  497. if ( NO_ERROR != dwRetCode )
  498. return dwRetCode;
  499. RtlSecureZeroMemory( szPassword, sizeof( szPassword ) );
  500. if ( ! (Input.fServer) )
  501. {
  502. //if this is a client then call ChapMakeMessage to
  503. //move the state from Initial to WaitForChallange
  504. dwRetCode = ChapMakeMessage(
  505. *ppWorkBuffer,
  506. NULL,
  507. NULL,
  508. 0,
  509. &ApResult,
  510. &Input );
  511. }
  512. return( dwRetCode );
  513. }
  514. DWORD EapMSChapv2Begin (
  515. OUT VOID ** ppWorkBuffer,
  516. IN PPP_EAP_INPUT * pPppEapInput
  517. )
  518. {
  519. DWORD dwRetCode = NO_ERROR;
  520. EAPMSCHAPv2WB * pWB = NULL;
  521. TRACE("EapChapBeginMSChapV2");
  522. //
  523. // Allocate a work buffer here and send it back as our
  524. // work buffer.
  525. //
  526. pWB = (EAPMSCHAPv2WB *)LocalAlloc(LPTR, sizeof(EAPMSCHAPv2WB) );
  527. if ( NULL == pWB )
  528. {
  529. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  530. goto done;
  531. }
  532. if ( (pPppEapInput->fFlags & RAS_EAP_FLAG_MACHINE_AUTH) )
  533. {
  534. pWB->fFlags |= EAPMSCHAPv2_FLAG_MACHINE_AUTH;
  535. }
  536. if ( pPppEapInput->fAuthenticator )
  537. {
  538. #if 0
  539. dwRetCode = ServerConfigDataIO(
  540. TRUE /* fRead */,
  541. NULL /* pwszMachineName */,
  542. (BYTE**)&(pWB->pUserProp),
  543. 0);
  544. #endif
  545. //
  546. // pConnectionData should have the config data which
  547. // was supplied in InvokeConfigUI2 routine.
  548. //
  549. if( (NULL == pPppEapInput->pConnectionData)
  550. || (pPppEapInput->dwSizeOfConnectionData <
  551. sizeof(EAPMSCHAPv2_USER_PROPERTIES)))
  552. {
  553. pWB->pUserProp = LocalAlloc(LPTR,
  554. sizeof(EAPMSCHAPv2_USER_PROPERTIES));
  555. if(NULL == pWB->pUserProp)
  556. {
  557. dwRetCode = E_OUTOFMEMORY;
  558. goto done;
  559. }
  560. pWB->pUserProp->dwVersion = 1;
  561. //Set Defaults here
  562. pWB->pUserProp->dwMaxRetries = 2;
  563. pWB->pUserProp->fFlags |= EAPMSCHAPv2_FLAG_ALLOW_CHANGEPWD;
  564. }
  565. else
  566. {
  567. pWB->pUserProp = (EAPMSCHAPv2_USER_PROPERTIES *)
  568. LocalAlloc(LPTR, pPppEapInput->dwSizeOfConnectionData);
  569. if(NULL == pWB->pUserProp)
  570. {
  571. dwRetCode = E_OUTOFMEMORY;
  572. goto done;
  573. }
  574. CopyMemory(pWB->pUserProp,
  575. pPppEapInput->pConnectionData,
  576. pPppEapInput->dwSizeOfConnectionData);
  577. }
  578. }
  579. else
  580. {
  581. dwRetCode = ReadUserData( pPppEapInput->pUserData,
  582. pPppEapInput->dwSizeOfUserData,
  583. &(pWB->pUserProp)
  584. );
  585. }
  586. if ( ERROR_SUCCESS != dwRetCode )
  587. {
  588. goto done;
  589. }
  590. //
  591. // Check to see if we got password field set. If so, we use that password
  592. // It means that the user has chosen to save the password. If not,
  593. // szpassword field should be empty.
  594. if ( !( pPppEapInput->fFlags & RAS_EAP_FLAG_8021X_AUTH ) )
  595. {
  596. if ( pPppEapInput->pwszPassword &&
  597. *(pPppEapInput->pwszPassword) &&
  598. wcscmp (pPppEapInput->pwszPassword, L"****************")
  599. )
  600. {
  601. WideCharToMultiByte( CP_ACP,
  602. 0,
  603. pPppEapInput->pwszPassword ,
  604. -1,
  605. pWB->pUserProp->szPassword,
  606. PWLEN+1,
  607. NULL,
  608. NULL );
  609. }
  610. }
  611. dwRetCode = ReadConnectionData ( ( pPppEapInput->fFlags & RAS_EAP_FLAG_8021X_AUTH ),
  612. pPppEapInput->pConnectionData,
  613. pPppEapInput->dwSizeOfConnectionData,
  614. &(pWB->pConnProp )
  615. );
  616. if ( ERROR_SUCCESS != dwRetCode )
  617. {
  618. goto done;
  619. }
  620. dwRetCode = EapChapBeginCommon( PPP_EAP_MSCHAPv2,
  621. (pWB->pConnProp->fFlags & EAPMSCHAPv2_FLAG_USE_WINLOGON_CREDS ),
  622. (pWB->pUserProp->dwMaxRetries ),
  623. pWB,
  624. &pWB->pwb,
  625. pPppEapInput
  626. );
  627. if ( NO_ERROR != dwRetCode )
  628. {
  629. goto done;
  630. }
  631. if ( pPppEapInput->pwszIdentity )
  632. {
  633. wcsncpy ( pWB->wszRadiusUserName, pPppEapInput->pwszIdentity, UNLEN+DNLEN );
  634. }
  635. *ppWorkBuffer = (PVOID)pWB;
  636. done:
  637. if ( NO_ERROR != dwRetCode )
  638. {
  639. if ( pWB )
  640. {
  641. LocalFree(pWB->pUserProp);
  642. LocalFree(pWB->pConnProp);
  643. LocalFree(pWB);
  644. }
  645. }
  646. return dwRetCode;
  647. }
  648. DWORD CheckCallerIdentity ( HANDLE hWVTStateData )
  649. {
  650. DWORD dwRetCode = ERROR_ACCESS_DENIED;
  651. PCRYPT_PROVIDER_DATA pProvData = NULL;
  652. PCCERT_CHAIN_CONTEXT pChainContext = NULL;
  653. PCRYPT_PROVIDER_SGNR pProvSigner = NULL;
  654. CERT_CHAIN_POLICY_PARA chainpolicyparams;
  655. CERT_CHAIN_POLICY_STATUS chainpolicystatus;
  656. if (!(pProvData = WTHelperProvDataFromStateData(hWVTStateData)))
  657. {
  658. goto done;
  659. }
  660. if (!(pProvSigner = WTHelperGetProvSignerFromChain(pProvData, 0, FALSE, 0)))
  661. {
  662. goto done;
  663. }
  664. chainpolicyparams.cbSize = sizeof(CERT_CHAIN_POLICY_PARA);
  665. //
  666. //
  667. // We do want to test for microsoft test root flags. and dont care
  668. // for revocation flags...
  669. //
  670. chainpolicyparams.dwFlags = CERT_CHAIN_POLICY_ALLOW_TESTROOT_FLAG |
  671. CERT_CHAIN_POLICY_TRUST_TESTROOT_FLAG |
  672. CERT_CHAIN_POLICY_IGNORE_ALL_REV_UNKNOWN_FLAGS;
  673. pChainContext = pProvSigner->pChainContext;
  674. if (!CertVerifyCertificateChainPolicy (
  675. CERT_CHAIN_POLICY_MICROSOFT_ROOT,
  676. pChainContext,
  677. &chainpolicyparams,
  678. &chainpolicystatus))
  679. {
  680. goto done;
  681. }
  682. else
  683. {
  684. if ( S_OK == chainpolicystatus.dwError )
  685. {
  686. dwRetCode = NO_ERROR;
  687. }
  688. else
  689. {
  690. //
  691. // Check the base policy to see if this
  692. // is a Microsoft test root
  693. //
  694. if (!CertVerifyCertificateChainPolicy (
  695. CERT_CHAIN_POLICY_BASE,
  696. pChainContext,
  697. &chainpolicyparams,
  698. &chainpolicystatus))
  699. {
  700. goto done;
  701. }
  702. else
  703. {
  704. if ( S_OK == chainpolicystatus.dwError )
  705. {
  706. dwRetCode = NO_ERROR;
  707. }
  708. }
  709. }
  710. }
  711. done:
  712. return dwRetCode;
  713. }
  714. DWORD VerifyCallerTrust ( LPWSTR lpszCaller )
  715. {
  716. DWORD dwRetCode = NO_ERROR;
  717. HRESULT hr = S_OK;
  718. WINTRUST_DATA wtData;
  719. WINTRUST_FILE_INFO wtFileInfo;
  720. WINTRUST_CATALOG_INFO wtCatalogInfo;
  721. BOOL fRet = FALSE;
  722. HCATADMIN hCATAdmin = NULL;
  723. GUID guidPublishedSoftware = WINTRUST_ACTION_GENERIC_VERIFY_V2;
  724. //
  725. // Following GUID is Mirosoft's Catalog System Root
  726. //
  727. GUID guidCatSystemRoot = { 0xf750e6c3, 0x38ee, 0x11d1,{ 0x85, 0xe5, 0x0, 0xc0, 0x4f, 0xc2, 0x95, 0xee } };
  728. HCATINFO hCATInfo = NULL;
  729. CATALOG_INFO CatInfo;
  730. HANDLE hFile = INVALID_HANDLE_VALUE;
  731. BYTE bHash[40];
  732. DWORD cbHash = 40;
  733. if ( NULL == lpszCaller )
  734. {
  735. dwRetCode = ERROR_INVALID_PARAMETER;
  736. goto done;
  737. }
  738. //
  739. //
  740. // Try and see if WinVerifyTrust will verify
  741. // the signature as a standalone file
  742. //
  743. //
  744. ZeroMemory ( &wtData, sizeof(wtData) );
  745. ZeroMemory ( &wtFileInfo, sizeof(wtFileInfo) );
  746. wtData.cbStruct = sizeof(wtData);
  747. wtData.dwUIChoice = WTD_UI_NONE;
  748. wtData.fdwRevocationChecks = WTD_REVOKE_NONE;
  749. wtData.dwStateAction = WTD_STATEACTION_VERIFY;
  750. wtData.dwUnionChoice = WTD_CHOICE_FILE;
  751. wtData.pFile = &wtFileInfo;
  752. wtFileInfo.cbStruct = sizeof( wtFileInfo );
  753. wtFileInfo.pcwszFilePath = lpszCaller;
  754. hr = WinVerifyTrust ( NULL,
  755. &guidPublishedSoftware,
  756. &wtData
  757. );
  758. if ( ERROR_SUCCESS == hr )
  759. {
  760. //
  761. // Check to see if this is indeed microsoft
  762. // signed caller
  763. //
  764. dwRetCode = CheckCallerIdentity( wtData.hWVTStateData);
  765. wtData.dwStateAction = WTD_STATEACTION_CLOSE;
  766. WinVerifyTrust(NULL, &guidPublishedSoftware, &wtData);
  767. goto done;
  768. }
  769. wtData.dwStateAction = WTD_STATEACTION_CLOSE;
  770. WinVerifyTrust(NULL, &guidPublishedSoftware, &wtData);
  771. //
  772. // We did not find the file was signed.
  773. // So check the system catalog to see if
  774. // the file is in the catalog and the catalog
  775. // is signed
  776. //
  777. //
  778. // Open the file
  779. //
  780. hFile = CreateFileW ( lpszCaller,
  781. GENERIC_READ,
  782. FILE_SHARE_READ,
  783. NULL,
  784. OPEN_EXISTING,
  785. FILE_ATTRIBUTE_NORMAL,
  786. NULL
  787. );
  788. if ( INVALID_HANDLE_VALUE == hFile )
  789. {
  790. dwRetCode = GetLastError();
  791. goto done;
  792. }
  793. fRet = CryptCATAdminAcquireContext( &hCATAdmin,
  794. &guidCatSystemRoot,
  795. 0
  796. );
  797. if ( !fRet )
  798. {
  799. dwRetCode = GetLastError();
  800. goto done;
  801. }
  802. //
  803. // Get the hash of the file here
  804. //
  805. fRet = CryptCATAdminCalcHashFromFileHandle ( hFile,
  806. &cbHash,
  807. bHash,
  808. 0
  809. );
  810. if ( !fRet )
  811. {
  812. dwRetCode = GetLastError();
  813. goto done;
  814. }
  815. ZeroMemory(&CatInfo, sizeof(CatInfo));
  816. CatInfo.cbStruct = sizeof(CatInfo);
  817. ZeroMemory( &wtCatalogInfo, sizeof(wtCatalogInfo) );
  818. wtData.dwUnionChoice = WTD_CHOICE_CATALOG;
  819. wtData.dwStateAction = WTD_STATEACTION_VERIFY;
  820. wtData.pCatalog = &wtCatalogInfo;
  821. wtCatalogInfo.cbStruct = sizeof(wtCatalogInfo);
  822. wtCatalogInfo.hMemberFile = hFile;
  823. wtCatalogInfo.pbCalculatedFileHash = bHash;
  824. wtCatalogInfo.cbCalculatedFileHash = cbHash;
  825. while ( ( hCATInfo = CryptCATAdminEnumCatalogFromHash ( hCATAdmin,
  826. bHash,
  827. cbHash,
  828. 0,
  829. &hCATInfo
  830. )
  831. )
  832. )
  833. {
  834. if (!(CryptCATCatalogInfoFromContext(hCATInfo, &CatInfo, 0)))
  835. {
  836. // should do something (??)
  837. continue;
  838. }
  839. wtCatalogInfo.pcwszCatalogFilePath = CatInfo.wszCatalogFile;
  840. hr = WinVerifyTrust ( NULL,
  841. &guidPublishedSoftware,
  842. &wtData
  843. );
  844. if ( ERROR_SUCCESS == hr )
  845. {
  846. //
  847. // Verify that this file is trusted
  848. //
  849. dwRetCode = CheckCallerIdentity( wtData.hWVTStateData);
  850. wtData.dwStateAction = WTD_STATEACTION_CLOSE;
  851. WinVerifyTrust(NULL, &guidPublishedSoftware, &wtData);
  852. goto done;
  853. }
  854. }
  855. //
  856. // File not found in any of the catalogs
  857. //
  858. dwRetCode = ERROR_ACCESS_DENIED;
  859. done:
  860. if ( hCATInfo )
  861. {
  862. CryptCATAdminReleaseCatalogContext( hCATAdmin, hCATInfo, 0 );
  863. }
  864. if ( hCATAdmin )
  865. {
  866. CryptCATAdminReleaseContext( hCATAdmin, 0 );
  867. }
  868. if ( hFile )
  869. {
  870. CloseHandle(hFile);
  871. }
  872. return dwRetCode;
  873. }
  874. #define TEST_VIVEKK_PRIVATE 0
  875. DWORD
  876. EapChapBegin(
  877. OUT VOID ** ppWorkBuffer,
  878. IN PPP_EAP_INPUT * pPppEapInput
  879. )
  880. {
  881. void* callersAddress;
  882. DWORD dwRetCode;
  883. MEMORY_BASIC_INFORMATION mbi;
  884. SIZE_T nbyte;
  885. DWORD nchar;
  886. wchar_t callersModule[MAX_PATH + 1];
  887. #ifdef TEST_VIVEKK_PRIVATE
  888. static BOOL fCallerTrusted = TRUE;
  889. #else
  890. static BOOL fCallerTrusted = FALSE;
  891. #endif
  892. //
  893. //Verify the caller first and then proceed with
  894. //other business
  895. //
  896. if ( !fCallerTrusted )
  897. {
  898. //
  899. //First Verify the caller and then
  900. //proceed with initialization
  901. //
  902. callersAddress = _ReturnAddress();
  903. nbyte = VirtualQuery(
  904. callersAddress,
  905. &mbi,
  906. sizeof(mbi)
  907. );
  908. if (nbyte < sizeof(mbi))
  909. {
  910. dwRetCode = ERROR_ACCESS_DENIED;
  911. goto done;
  912. }
  913. nchar = GetModuleFileNameW(
  914. (HMODULE)(mbi.AllocationBase),
  915. callersModule,
  916. MAX_PATH
  917. );
  918. if (nchar == 0)
  919. {
  920. dwRetCode = GetLastError();
  921. goto done;
  922. }
  923. dwRetCode = VerifyCallerTrust(callersModule);
  924. if ( NO_ERROR != dwRetCode )
  925. {
  926. goto done;
  927. }
  928. fCallerTrusted = TRUE;
  929. }
  930. dwRetCode = EapChapBeginCommon( EAPTYPE_MD5Challenge,
  931. FALSE,
  932. 0,
  933. NULL,
  934. ppWorkBuffer,
  935. pPppEapInput
  936. );
  937. done:
  938. return dwRetCode;
  939. }
  940. DWORD
  941. EapMSChapv2End ( IN VOID * pWorkBuf )
  942. {
  943. DWORD dwRetCode = NO_ERROR;
  944. EAPMSCHAPv2WB * pWB = (EAPMSCHAPv2WB *)pWorkBuf;
  945. TRACE("EapMSChapv2End");
  946. if ( pWB )
  947. {
  948. dwRetCode = ChapEnd( pWB->pwb );
  949. LocalFree ( pWB->pUIContextData );
  950. LocalFree ( pWB->pUserProp );
  951. LocalFree ( pWB->pConnProp );
  952. if ( pWB->pUserAttributes )
  953. RasAuthAttributeDestroy(pWB->pUserAttributes);
  954. LocalFree( pWB );
  955. }
  956. return dwRetCode;
  957. }
  958. //**
  959. //
  960. // Call: EapChapEnd
  961. //
  962. // Returns: NO_ERROR - Success
  963. // Non-zero returns - Failure
  964. //
  965. // Description: Wrapper around ChapEnd.
  966. //
  967. DWORD
  968. EapChapEnd(
  969. IN VOID* pWorkBuf
  970. )
  971. {
  972. return( ChapEnd( pWorkBuf ) );
  973. }
  974. DWORD
  975. GetIdentityFromUserName (
  976. LPSTR lpszUserName,
  977. LPSTR lpszDomain,
  978. LPWSTR * ppwszIdentity
  979. )
  980. {
  981. DWORD dwRetCode = NO_ERROR;
  982. DWORD dwNumBytes;
  983. //domain+ user + '\' + null
  984. dwNumBytes = (strlen(lpszUserName) + strlen(lpszDomain) + 1 + 1) * sizeof(WCHAR);
  985. *ppwszIdentity = LocalAlloc ( LPTR, dwNumBytes);
  986. if ( NULL == *ppwszIdentity )
  987. {
  988. dwRetCode = ERROR_OUTOFMEMORY;
  989. goto LDone;
  990. }
  991. if ( *lpszDomain )
  992. {
  993. MultiByteToWideChar( CP_ACP,
  994. 0,
  995. lpszDomain,
  996. -1,
  997. *ppwszIdentity,
  998. dwNumBytes/sizeof(WCHAR) );
  999. wcscat( *ppwszIdentity, L"\\");
  1000. }
  1001. MultiByteToWideChar( CP_ACP,
  1002. 0,
  1003. lpszUserName,
  1004. -1,
  1005. *lpszDomain? *ppwszIdentity + strlen(lpszDomain) + 1:*ppwszIdentity,
  1006. dwNumBytes/sizeof(WCHAR) - strlen(lpszDomain) );
  1007. LDone:
  1008. return dwRetCode;
  1009. }
  1010. // Convert a number to a hex representation.
  1011. BYTE num2Digit(BYTE num)
  1012. {
  1013. return (num < 10) ? num + '0' : num + ('A' - 10);
  1014. }
  1015. //
  1016. DWORD
  1017. ChangePassword ( IN OUT EAPMSCHAPv2WB * pEapwb,
  1018. PPP_EAP_OUTPUT* pEapOutput,
  1019. PPPAP_INPUT* pApInput)
  1020. {
  1021. DWORD dwRetCode = NO_ERROR;
  1022. RAS_AUTH_ATTRIBUTE * pAttribute = NULL;
  1023. WCHAR wszUserName[UNLEN + DNLEN +1] = {0};
  1024. LPWSTR lpwszHashUserName = NULL;
  1025. CHAR szHashUserName[UNLEN+1] = {0};
  1026. WCHAR wszDomainName[DNLEN +1] = {0};
  1027. PBYTE pbEncHash = NULL;
  1028. BYTE bEncPassword[550] = {0};
  1029. HANDLE hAttribute;
  1030. int i;
  1031. //
  1032. // check to see if change password attribute is present in
  1033. // User Attributes
  1034. //
  1035. pAttribute = RasAuthAttributeGetVendorSpecific(
  1036. VENDOR_MICROSOFT,
  1037. MS_VSA_CHAP2_CPW,
  1038. pEapOutput->pUserAttributes );
  1039. if ( NULL == pAttribute )
  1040. {
  1041. TRACE ( "no change password attribute");
  1042. goto LDone;
  1043. }
  1044. //Get encrypted Hash
  1045. pbEncHash = (PBYTE)pAttribute->Value + 8;
  1046. //
  1047. // Get the user name and domain name
  1048. //
  1049. pAttribute = RasAuthAttributeGet ( raatUserName,
  1050. pEapOutput->pUserAttributes
  1051. );
  1052. if ( NULL == pAttribute )
  1053. {
  1054. //Need a better way of sending error
  1055. TRACE ( "UserName missing");
  1056. dwRetCode = ERROR_AUTHENTICATION_FAILURE;
  1057. goto LDone;
  1058. }
  1059. //
  1060. // Convert the username to unicode
  1061. //
  1062. MultiByteToWideChar( CP_ACP,
  1063. 0,
  1064. pAttribute->Value,
  1065. pAttribute->dwLength,
  1066. wszUserName,
  1067. UNLEN + DNLEN + 1 );
  1068. //
  1069. // Get the hash user name and domain name
  1070. //
  1071. lpwszHashUserName = wcschr ( wszUserName, '\\' );
  1072. if ( lpwszHashUserName )
  1073. {
  1074. wcsncpy ( wszDomainName, wszUserName, lpwszHashUserName - wszUserName );
  1075. lpwszHashUserName ++;
  1076. }
  1077. else
  1078. {
  1079. lpwszHashUserName = wszUserName;
  1080. }
  1081. /*
  1082. //Convert hash user name to multibyte
  1083. WideCharToMultiByte( CP_ACP,
  1084. 0,
  1085. lpwszHashUserName,
  1086. -1,
  1087. szHashUserName,
  1088. DNLEN+1,
  1089. NULL,
  1090. NULL );
  1091. */
  1092. //
  1093. // Get encrypted password
  1094. //
  1095. pAttribute = RasAuthAttributeGetFirst( raatVendorSpecific,
  1096. pEapOutput->pUserAttributes,
  1097. &hAttribute );
  1098. while ( pAttribute )
  1099. {
  1100. if ( *((PBYTE)pAttribute->Value + 4) == MS_VSA_CHAP_NT_Enc_PW )
  1101. {
  1102. //
  1103. // check to see the sequence number and copy it
  1104. // proper place in our buffer.
  1105. //
  1106. switch ( WireToHostFormat16 ( (PBYTE) pAttribute->Value + 8 ) )
  1107. {
  1108. case 1:
  1109. CopyMemory( bEncPassword,
  1110. (PBYTE)pAttribute->Value + 10,
  1111. 243
  1112. );
  1113. break;
  1114. case 2:
  1115. CopyMemory( bEncPassword+ 243,
  1116. (PBYTE)pAttribute->Value + 10,
  1117. 243
  1118. );
  1119. break;
  1120. case 3:
  1121. CopyMemory( bEncPassword+ 486,
  1122. (PBYTE)pAttribute->Value + 10,
  1123. 30
  1124. );
  1125. break;
  1126. default:
  1127. TRACE("Invalid enc password attribute");
  1128. break;
  1129. }
  1130. }
  1131. //
  1132. // Check to see if this is enc password
  1133. // and also get the sequence number.
  1134. //
  1135. pAttribute = RasAuthAttributeGetNext( &hAttribute,
  1136. raatVendorSpecific );
  1137. }
  1138. //
  1139. // Call Change password function
  1140. //
  1141. dwRetCode = IASChangePassword3( lpwszHashUserName,
  1142. wszDomainName,
  1143. pbEncHash,
  1144. bEncPassword
  1145. );
  1146. pEapwb->dwLSARetCode = dwRetCode;
  1147. LDone:
  1148. return dwRetCode;
  1149. }
  1150. DWORD
  1151. AuthenticateUser ( IN OUT EAPMSCHAPv2WB * pEapwb,
  1152. IN PPP_EAP_OUTPUT* pEapOutput,
  1153. PPPAP_INPUT * pApInput
  1154. )
  1155. {
  1156. DWORD dwRetCode = NO_ERROR;
  1157. RAS_AUTH_ATTRIBUTE * pAttribute = NULL;
  1158. WCHAR wszUserName[UNLEN + DNLEN +1] = {0};
  1159. WCHAR wszHashUserName[UNLEN+DNLEN+1] = {0};
  1160. //Hash user name is taken from chapwb
  1161. CHAR szHashUserName[UNLEN+1] = {0};
  1162. WCHAR* lpszRover = NULL;
  1163. WCHAR wszDomainName[DNLEN +1] = {0};
  1164. //Format is Type + Length + identity + "S=" + 40 bytes response
  1165. UCHAR szAuthSuccessResponse[1+1+1+2+40] ={0};
  1166. //Domain Name Type + Length+Domainname
  1167. CHAR szDomainName[1+1+1+DNLEN+1] ={0};
  1168. //MPPE Keys Type+Length+Salt+KeyLength+NTkey(16)+PAdding(15)
  1169. BYTE bMPPEKey[1+1+2+1+16+15]={0};
  1170. PBYTE pbChapChallenge = NULL;
  1171. DWORD cbChallenge = 0;
  1172. PBYTE pbResponse = NULL;
  1173. PBYTE pbPeerChallenge = NULL;
  1174. IAS_MSCHAP_V2_PROFILE Profile;
  1175. HANDLE hToken = INVALID_HANDLE_VALUE;
  1176. DWORD dwCurAttr = 0;
  1177. DWORD dwCount=0;
  1178. DWORD dwChapRetCode = NO_ERROR;
  1179. //Type +
  1180. CHAR szChapError[64] = {0};
  1181. TRACE("Authenticate User");
  1182. //
  1183. // Authenticate the user by calling the IASLogonUser function here
  1184. // This is stolen from IAS.
  1185. //
  1186. //Extract the attribs from pUserAttributes
  1187. //
  1188. // We need following attribs
  1189. // raatUserName,
  1190. // MS_VSA_CHAP_Challenge
  1191. // MS_VSA_CHAP2_Response
  1192. //
  1193. //We dont use the user name got from EAP for auth. We use the one got from
  1194. //Radius
  1195. #if 0
  1196. pAttribute = RasAuthAttributeGet ( raatUserName,
  1197. pEapOutput->pUserAttributes
  1198. );
  1199. if ( NULL == pAttribute )
  1200. {
  1201. //Need a better way of sending error
  1202. TRACE ( "UserName missing");
  1203. dwRetCode = ERROR_AUTHENTICATION_FAILURE;
  1204. goto done;
  1205. }
  1206. //
  1207. // Convert the username to unicode
  1208. //
  1209. MultiByteToWideChar( CP_ACP,
  1210. 0,
  1211. pAttribute->Value,
  1212. pAttribute->dwLength,
  1213. wszUserName,
  1214. UNLEN + DNLEN + 1 );
  1215. #endif
  1216. //Get the chap challenge and chap response
  1217. pAttribute = RasAuthAttributeGetVendorSpecific(
  1218. VENDOR_MICROSOFT,
  1219. MS_VSA_CHAP_Challenge,
  1220. pEapOutput->pUserAttributes );
  1221. if ( NULL == pAttribute )
  1222. {
  1223. TRACE ( "Challenge missing");
  1224. dwRetCode = ERROR_AUTHENTICATION_FAILURE;
  1225. goto done;
  1226. }
  1227. pbChapChallenge = (PBYTE)pAttribute->Value + 6;
  1228. cbChallenge = ((DWORD)(*((PBYTE)pAttribute->Value + 5))) - 2;
  1229. pAttribute = RasAuthAttributeGetVendorSpecific(
  1230. VENDOR_MICROSOFT,
  1231. MS_VSA_CHAP2_Response,
  1232. pEapOutput->pUserAttributes );
  1233. if ( NULL == pAttribute )
  1234. {
  1235. //
  1236. // Try and see if this is a change password response
  1237. //
  1238. pAttribute = RasAuthAttributeGetVendorSpecific(
  1239. VENDOR_MICROSOFT,
  1240. MS_VSA_CHAP2_CPW,
  1241. pEapOutput->pUserAttributes );
  1242. if ( NULL == pAttribute )
  1243. {
  1244. TRACE("Response missing");
  1245. dwRetCode = ERROR_AUTHENTICATION_FAILURE;
  1246. goto done;
  1247. }
  1248. //
  1249. // Setup response and peer challenge here
  1250. //
  1251. pbPeerChallenge = (PBYTE)pAttribute->Value + 8 + 16;
  1252. pbResponse = (PBYTE)pAttribute->Value + 8 + 16 + 24;
  1253. }
  1254. else
  1255. {
  1256. //
  1257. // Get the peer challenge and response from
  1258. // the VSA
  1259. //
  1260. pbPeerChallenge = (PBYTE)pAttribute->Value + 8;
  1261. pbResponse = (PBYTE)pAttribute->Value + 8 + 16 + 8;
  1262. }
  1263. //
  1264. // Get the hash user name and domain name
  1265. //
  1266. MultiByteToWideChar( CP_ACP,
  1267. 0,
  1268. pEapwb->pwb->szUserName,
  1269. -1,
  1270. wszHashUserName,
  1271. UNLEN+DNLEN );
  1272. //
  1273. // Get the domain if any
  1274. //
  1275. lpszRover = wcschr ( wszHashUserName, '\\' );
  1276. if ( lpszRover )
  1277. {
  1278. lpszRover++;
  1279. }
  1280. else
  1281. {
  1282. lpszRover = wszHashUserName;
  1283. }
  1284. //Convert hash user name to multibyte
  1285. WideCharToMultiByte( CP_ACP,
  1286. 0,
  1287. lpszRover,
  1288. -1,
  1289. szHashUserName,
  1290. UNLEN+1,
  1291. NULL,
  1292. NULL );
  1293. lpszRover = wcschr ( pEapwb->wszRadiusUserName, '\\');
  1294. if ( lpszRover )
  1295. {
  1296. wcsncpy ( wszDomainName, pEapwb->wszRadiusUserName, lpszRover - pEapwb->wszRadiusUserName );
  1297. lpszRover++;
  1298. }
  1299. else
  1300. {
  1301. lpszRover = pEapwb->wszRadiusUserName;
  1302. }
  1303. dwRetCode = IASLogonMSCHAPv2( (PCWSTR)lpszRover,
  1304. (PCWSTR)wszDomainName,
  1305. szHashUserName,
  1306. pbChapChallenge,
  1307. cbChallenge,
  1308. pbResponse,
  1309. pbPeerChallenge,
  1310. &Profile,
  1311. &hToken
  1312. );
  1313. //
  1314. // Map the return errors to correct errors
  1315. // create a set of attributes to be sent back to raschap
  1316. //
  1317. if ( NO_ERROR == dwRetCode )
  1318. {
  1319. //
  1320. // Setup the authenticator attributes here
  1321. // Following attributes will be send back.
  1322. // 1. SendKey
  1323. // 2. RecvKey
  1324. // 3. AuthResponse
  1325. // 4. MSCHAPDomain
  1326. //
  1327. pApInput->dwAuthResultCode = NO_ERROR;
  1328. pApInput->fAuthenticationComplete = TRUE;
  1329. pAttribute = RasAuthAttributeCreate ( 4 );
  1330. if ( NULL == pAttribute )
  1331. {
  1332. TRACE("RasAuthAttributeCreate failed");
  1333. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1334. goto done;
  1335. }
  1336. for ( dwCurAttr = 0; dwCurAttr < 4; dwCurAttr ++ )
  1337. {
  1338. switch ( dwCurAttr )
  1339. {
  1340. case 0:
  1341. {
  1342. CHAR * p = szDomainName;
  1343. //
  1344. // Setup MSCHAP Domain name here
  1345. //
  1346. *p++ = (BYTE)MS_VSA_CHAP_Domain;
  1347. *p++ = (BYTE)wcslen(Profile.LogonDomainName)+1+1;
  1348. *p++ = 1;
  1349. WideCharToMultiByte( CP_ACP,
  1350. 0,
  1351. Profile.LogonDomainName,
  1352. -1,
  1353. p,
  1354. DNLEN+1,
  1355. NULL,
  1356. NULL );
  1357. dwRetCode = RasAuthAttributeInsertVSA(
  1358. dwCurAttr,
  1359. pAttribute,
  1360. VENDOR_MICROSOFT,
  1361. (DWORD)szDomainName[1],
  1362. szDomainName );
  1363. break;
  1364. }
  1365. case 1:
  1366. case 2:
  1367. {
  1368. //SEtup MPPE SEnd Key attributes here
  1369. PBYTE p = bMPPEKey;
  1370. ZeroMemory(bMPPEKey, sizeof(bMPPEKey) );
  1371. if ( dwCurAttr == 1 )
  1372. *p++ = (BYTE)MS_VSA_MPPE_Send_Key; //Type
  1373. else
  1374. *p++ = (BYTE)MS_VSA_MPPE_Recv_Key; //Type
  1375. *p++ = (BYTE)36; //Length
  1376. p++;p++; //Salt is 0
  1377. *p++ = 16; //Key Length
  1378. if ( dwCurAttr == 1 )
  1379. CopyMemory(p, Profile.SendSessionKey, 16 );
  1380. else
  1381. CopyMemory(p, Profile.RecvSessionKey, 16 );
  1382. dwRetCode = RasAuthAttributeInsertVSA(
  1383. dwCurAttr,
  1384. pAttribute,
  1385. VENDOR_MICROSOFT,
  1386. 36,
  1387. bMPPEKey );
  1388. break;
  1389. }
  1390. case 3:
  1391. {
  1392. UCHAR * p = szAuthSuccessResponse;
  1393. *p++ = (BYTE)MS_VSA_CHAP2_Success; //Type of attr
  1394. *p++ = (BYTE)45; //Length of the VSA
  1395. *p++ = (BYTE)1; //ID ignored by out implementation of MSCHAPv2
  1396. *p++ = 'S';
  1397. *p++ = '=';
  1398. for ( dwCount = 0; dwCount < 20; dwCount++ )
  1399. {
  1400. *p++ = num2Digit(Profile.AuthResponse[dwCount] >> 4);
  1401. *p++ = num2Digit(Profile.AuthResponse[dwCount] & 0xF);
  1402. }
  1403. //
  1404. // Setup the value field here
  1405. //
  1406. dwRetCode = RasAuthAttributeInsertVSA(
  1407. dwCurAttr,
  1408. pAttribute,
  1409. VENDOR_MICROSOFT,
  1410. 45,
  1411. szAuthSuccessResponse );
  1412. break;
  1413. }
  1414. default:
  1415. break;
  1416. }
  1417. if ( NO_ERROR != dwRetCode )
  1418. {
  1419. TRACE("RasAuthAttributeInsetVSA failed");
  1420. goto done;
  1421. }
  1422. }
  1423. pApInput->pAttributesFromAuthenticator = pAttribute;
  1424. //
  1425. // Also save the attributes in the WB to send across later.
  1426. //
  1427. pEapwb->pUserAttributes = pAttribute;
  1428. pEapwb->dwAuthResultCode = NO_ERROR;
  1429. pEapwb->dwLSARetCode = NO_ERROR;
  1430. pApInput->fAuthenticationComplete = TRUE;
  1431. pApInput->dwAuthResultCode = pApInput->dwAuthError = NO_ERROR;
  1432. }
  1433. else
  1434. {
  1435. pEapwb->dwLSARetCode = dwRetCode;
  1436. //
  1437. // Handle the failure by sending
  1438. //
  1439. switch ( dwRetCode )
  1440. {
  1441. case ERROR_INVALID_LOGON_HOURS:
  1442. dwChapRetCode = ERROR_RESTRICTED_LOGON_HOURS;
  1443. break;
  1444. case ERROR_ACCOUNT_DISABLED:
  1445. dwChapRetCode = ERROR_ACCT_DISABLED;
  1446. break;
  1447. case ERROR_PASSWORD_EXPIRED:
  1448. case ERROR_PASSWORD_MUST_CHANGE:
  1449. dwChapRetCode = ERROR_PASSWD_EXPIRED;
  1450. break;
  1451. case ERROR_ILL_FORMED_PASSWORD:
  1452. case ERROR_PASSWORD_RESTRICTION:
  1453. dwChapRetCode = ERROR_CHANGING_PASSWORD;
  1454. break;
  1455. default:
  1456. dwChapRetCode = ERROR_AUTHENTICATION_FAILURE;
  1457. }
  1458. pAttribute = RasAuthAttributeCreate ( 1 );
  1459. if ( NULL == pAttribute )
  1460. {
  1461. TRACE("RasAuthAttributeCreate failed");
  1462. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1463. goto done;
  1464. }
  1465. //Make a VSA out of this and send it back
  1466. wsprintf ( &szChapError[3], "E=%lu R=0 V=3", dwChapRetCode );
  1467. szChapError[0] = MS_VSA_CHAP_Error;
  1468. szChapError[1] = 3 + strlen(&szChapError[3]);
  1469. szChapError[2] = pEapwb->IdToExpect;
  1470. dwRetCode = RasAuthAttributeInsertVSA(
  1471. 0,
  1472. pAttribute,
  1473. VENDOR_MICROSOFT,
  1474. szChapError[1],
  1475. szChapError );
  1476. pApInput->fAuthenticationComplete = TRUE;
  1477. pApInput->pAttributesFromAuthenticator = pAttribute;
  1478. pApInput->dwAuthError = NO_ERROR;
  1479. pApInput->dwAuthResultCode = dwChapRetCode;
  1480. }
  1481. done:
  1482. if ( INVALID_HANDLE_VALUE != hToken )
  1483. CloseHandle(hToken);
  1484. if ( NO_ERROR != dwRetCode )
  1485. {
  1486. RasAuthAttributeDestroy(pAttribute);
  1487. pApInput->pAttributesFromAuthenticator = NULL;
  1488. }
  1489. return dwRetCode;
  1490. }
  1491. DWORD
  1492. CallMakeMessageAndSetEAPState(
  1493. IN PVOID pWorkBuf,
  1494. IN PPP_CONFIG* pReceiveBuf,
  1495. IN OUT PPP_CONFIG* pSendBuf,
  1496. IN DWORD cbSendBuf,
  1497. PPPAP_RESULT * pApResult,
  1498. PPPAP_INPUT * pApInput,
  1499. OUT PPP_EAP_OUTPUT* pEapOutput
  1500. )
  1501. {
  1502. DWORD dwRetCode = NO_ERROR;
  1503. CHAPWB * pwb = (CHAPWB *)pWorkBuf;
  1504. dwRetCode = ChapMakeMessage(
  1505. pWorkBuf,
  1506. pReceiveBuf,
  1507. pSendBuf,
  1508. cbSendBuf,
  1509. pApResult,
  1510. pApInput );
  1511. if ( dwRetCode != NO_ERROR )
  1512. {
  1513. goto done;
  1514. }
  1515. switch( pApResult->Action )
  1516. {
  1517. case APA_NoAction:
  1518. pEapOutput->Action = EAPACTION_NoAction;
  1519. break;
  1520. case APA_Done:
  1521. pEapOutput->Action = EAPACTION_Done;
  1522. break;
  1523. case APA_SendAndDone:
  1524. case APA_Send:
  1525. pEapOutput->Action = EAPACTION_Send;
  1526. break;
  1527. case APA_SendWithTimeout:
  1528. pEapOutput->Action = ( pwb->fServer )
  1529. ? EAPACTION_SendWithTimeout
  1530. : EAPACTION_Send;
  1531. break;
  1532. case APA_SendWithTimeout2:
  1533. pEapOutput->Action = ( pwb->fServer )
  1534. ? EAPACTION_SendWithTimeoutInteractive
  1535. : EAPACTION_Send;
  1536. break;
  1537. case APA_Authenticate:
  1538. pEapOutput->pUserAttributes = pApResult->pUserAttributes;
  1539. pEapOutput->Action = EAPACTION_Authenticate;
  1540. break;
  1541. default:
  1542. RTASSERT(FALSE);
  1543. break;
  1544. }
  1545. done:
  1546. return dwRetCode;
  1547. }
  1548. DWORD
  1549. EapMSChapv2SMakeMessage(
  1550. IN VOID* pWorkBuf,
  1551. IN PPP_EAP_PACKET* pReceivePacket,
  1552. OUT PPP_EAP_PACKET* pSendPacket,
  1553. IN DWORD cbSendPacket,
  1554. OUT PPP_EAP_OUTPUT* pEapOutput,
  1555. IN PPP_EAP_INPUT* pEapInput
  1556. )
  1557. {
  1558. DWORD dwRetCode = NO_ERROR;
  1559. PPP_CONFIG * pReceiveBuf = NULL;
  1560. PPP_CONFIG * pSendBuf = NULL;
  1561. DWORD cbSendBuf = 1500;
  1562. PPPAP_INPUT ApInput;
  1563. PPPAP_RESULT ApResult;
  1564. WORD cbPacket = 0;
  1565. EAPMSCHAPv2WB * pEapwb = (EAPMSCHAPv2WB * ) pWorkBuf;
  1566. TRACE("EapMSChapv2SMakeMessage");
  1567. //
  1568. //Do default processing here.
  1569. //
  1570. ZeroMemory( &ApResult, sizeof(ApResult) );
  1571. if ( ( pSendBuf = LocalAlloc( LPTR, cbSendBuf ) ) == NULL )
  1572. {
  1573. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1574. goto done;
  1575. }
  1576. if ( pEapInput != NULL )
  1577. {
  1578. MapEapInputToApInput( pEapInput, &ApInput );
  1579. }
  1580. switch ( pEapwb->EapState )
  1581. {
  1582. case EMV2_Initial:
  1583. TRACE("EMV2_Initial");
  1584. //
  1585. // This is the first time this has been invoked.
  1586. // So we make a MACHAPv2 chap challenge and send
  1587. // back a response
  1588. //
  1589. dwRetCode = CallMakeMessageAndSetEAPState(
  1590. pEapwb->pwb,
  1591. pReceiveBuf,
  1592. pSendBuf,
  1593. cbSendBuf,
  1594. &ApResult,
  1595. ( pEapInput ? &ApInput : NULL ),
  1596. pEapOutput
  1597. );
  1598. //
  1599. // We got the CHAP Challenge now. If all's fine
  1600. // package the result back and send it to the client
  1601. //
  1602. //
  1603. // Translate MSCHAPv2 packet to EAP packet
  1604. //
  1605. if ( NO_ERROR == dwRetCode && pSendBuf )
  1606. {
  1607. pSendPacket->Code = EAPCODE_Request;
  1608. pEapwb->IdToExpect = pEapwb->IdToSend =
  1609. pSendPacket->Id = pEapwb->pwb->bIdToSend;
  1610. //
  1611. // Length = sizeof Header + sizeof MSCHAP packet to send
  1612. // This includes the first byte of
  1613. cbPacket = WireToHostFormat16( pSendBuf->Length );
  1614. CopyMemory ( pSendPacket->Data+1, pSendBuf, cbPacket);
  1615. cbPacket += sizeof(PPP_EAP_PACKET);
  1616. HostToWireFormat16( cbPacket, pSendPacket->Length );
  1617. pSendPacket->Data[0] = (BYTE)PPP_EAP_MSCHAPv2;
  1618. pEapwb->EapState = EMV2_RequestSend;
  1619. }
  1620. break;
  1621. case EMV2_RequestSend:
  1622. TRACE("EMV2_RequestSend");
  1623. //
  1624. // We should only get a response here.
  1625. // If not discard this packet.
  1626. //
  1627. if ( NULL != pReceivePacket )
  1628. {
  1629. if ( pReceivePacket->Code != EAPCODE_Response )
  1630. {
  1631. TRACE("Got unexpected packet. Does not have response");
  1632. dwRetCode = ERROR_PPP_INVALID_PACKET;
  1633. break;
  1634. }
  1635. if ( pReceivePacket->Id != pEapwb->IdToExpect )
  1636. {
  1637. TRACE("received packet id does not match");
  1638. dwRetCode = ERROR_PPP_INVALID_PACKET;
  1639. break;
  1640. }
  1641. //
  1642. // Translate the packet received to
  1643. // MSCHAP v2 format
  1644. //
  1645. cbPacket = WireToHostFormat16(pReceivePacket->Length);
  1646. if ( cbPacket > sizeof( PPP_EAP_PACKET ) )
  1647. {
  1648. pReceiveBuf = (PPP_CONFIG *)( pReceivePacket->Data + 1);
  1649. dwRetCode = CallMakeMessageAndSetEAPState(
  1650. pEapwb->pwb,
  1651. pReceiveBuf,
  1652. pSendBuf,
  1653. cbSendBuf,
  1654. &ApResult,
  1655. ( pEapInput ? &ApInput : NULL ),
  1656. pEapOutput
  1657. );
  1658. if ( NO_ERROR == dwRetCode )
  1659. {
  1660. //Check to see if we are asked to authenticate
  1661. if ( pEapOutput->Action == EAPACTION_Authenticate )
  1662. {
  1663. //
  1664. // If we have come this far pEapInput cannot be NULL
  1665. // Or else it is a bug in the client.
  1666. //
  1667. //
  1668. // Check to see if this is a change password request
  1669. // If so first change tha password and then authenticate.
  1670. //
  1671. dwRetCode = ChangePassword (pEapwb, pEapOutput, &ApInput);
  1672. if ( NO_ERROR == dwRetCode )
  1673. {
  1674. //
  1675. // Now authenticate user
  1676. //
  1677. dwRetCode = AuthenticateUser (pEapwb, pEapOutput, &ApInput );
  1678. }
  1679. else
  1680. {
  1681. //
  1682. // Change password operation failed.
  1683. //
  1684. pSendPacket->Code = EAPCODE_Failure;
  1685. HostToWireFormat16 ( (WORD)4, pSendPacket->Length );
  1686. pEapwb->EapState = EMV2_Failure;
  1687. //pEapOutput->dwAuthResultCode = pEapwb->pwb->result.dwError;
  1688. pEapOutput->dwAuthResultCode = pEapwb->dwLSARetCode;
  1689. pEapOutput->Action = EAPACTION_SendAndDone;
  1690. dwRetCode = NO_ERROR;
  1691. break;
  1692. }
  1693. //
  1694. // We will get a set of auth attributes back
  1695. // that we need to send back to the mschap
  1696. // protocol.
  1697. //
  1698. dwRetCode = CallMakeMessageAndSetEAPState
  1699. (
  1700. pEapwb->pwb,
  1701. pReceiveBuf,
  1702. pSendBuf,
  1703. cbSendBuf,
  1704. &ApResult,
  1705. &ApInput,
  1706. pEapOutput
  1707. );
  1708. }
  1709. //
  1710. // Check to see if auth was success or fail.
  1711. // If Auth was success then set state to EMV2_CHAPAuthSuccess
  1712. //
  1713. if ( NO_ERROR == dwRetCode && pSendBuf )
  1714. {
  1715. pSendPacket->Code = EAPCODE_Request;
  1716. pEapwb->IdToSend ++;
  1717. pEapwb->IdToExpect = pSendPacket->Id = pEapwb->IdToSend;
  1718. //
  1719. // Length = sizeof Header + sizeof MSCHAP packet to send
  1720. // This includes the first byte of
  1721. cbPacket = WireToHostFormat16( pSendBuf->Length );
  1722. CopyMemory ( pSendPacket->Data+1, pSendBuf, cbPacket);
  1723. cbPacket += sizeof(PPP_EAP_PACKET);
  1724. HostToWireFormat16( cbPacket, pSendPacket->Length );
  1725. pSendPacket->Data[0] = (BYTE)PPP_EAP_MSCHAPv2;
  1726. if ( pEapwb->pwb->result.dwError == NO_ERROR )
  1727. {
  1728. //
  1729. // We succeeded in auth
  1730. //
  1731. pEapwb->EapState = EMV2_CHAPAuthSuccess;
  1732. pEapOutput->Action = EAPACTION_SendWithTimeout;
  1733. }
  1734. else
  1735. {
  1736. //
  1737. // Could be a retryable failure. So we need to send
  1738. // with interactive timeout.
  1739. //
  1740. if ( pEapwb->pwb->result.fRetry )
  1741. {
  1742. pEapwb->EapState = EMV2_RequestSend;
  1743. pEapOutput->Action = EAPACTION_SendWithTimeoutInteractive;
  1744. }
  1745. else if ( pEapwb->pwb->result.dwError == ERROR_PASSWD_EXPIRED )
  1746. {
  1747. if ( pEapwb->pUserProp->fFlags & EAPMSCHAPv2_FLAG_ALLOW_CHANGEPWD )
  1748. {
  1749. //
  1750. // Check to see if this is allowed
  1751. //
  1752. pEapwb->EapState = EMV2_RequestSend;
  1753. pEapOutput->Action = EAPACTION_SendWithTimeoutInteractive;
  1754. }
  1755. else
  1756. {
  1757. pSendPacket->Code = EAPCODE_Failure;
  1758. HostToWireFormat16 ( (WORD)4, pSendPacket->Length );
  1759. pEapwb->EapState = EMV2_Failure;
  1760. //pEapOutput->dwAuthResultCode = pEapwb->pwb->result.dwError;
  1761. pEapOutput->dwAuthResultCode = pEapwb->dwLSARetCode;
  1762. pEapOutput->Action = EAPACTION_SendAndDone;
  1763. }
  1764. }
  1765. else
  1766. {
  1767. pSendPacket->Code = EAPCODE_Failure;
  1768. HostToWireFormat16 ( (WORD)4, pSendPacket->Length );
  1769. pEapwb->EapState = EMV2_Failure;
  1770. //pEapOutput->dwAuthResultCode = pEapwb->pwb->result.dwError;
  1771. pEapOutput->dwAuthResultCode = pEapwb->dwLSARetCode;
  1772. pEapOutput->Action = EAPACTION_SendAndDone;
  1773. }
  1774. }
  1775. }
  1776. }
  1777. }
  1778. else
  1779. {
  1780. //
  1781. // We should never get an empty response in
  1782. //
  1783. dwRetCode = ERROR_PPP_INVALID_PACKET;
  1784. }
  1785. }
  1786. else
  1787. {
  1788. dwRetCode = ERROR_PPP_INVALID_PACKET;
  1789. }
  1790. break;
  1791. case EMV2_CHAPAuthSuccess:
  1792. TRACE("EMV2_CHAPAuthSuccess");
  1793. //
  1794. // We should only get an response here indicating
  1795. // if the client could validate the server successfully.
  1796. // Then we can send back a EAP_SUCCESS or EAP_FAIL.
  1797. //
  1798. if ( NULL != pReceivePacket )
  1799. {
  1800. if ( pReceivePacket->Code != EAPCODE_Response )
  1801. {
  1802. dwRetCode = ERROR_PPP_INVALID_PACKET;
  1803. break;
  1804. }
  1805. if ( pReceivePacket->Id != pEapwb->IdToExpect )
  1806. {
  1807. //Invalid packet id
  1808. dwRetCode = ERROR_PPP_INVALID_PACKET;
  1809. break;
  1810. }
  1811. //
  1812. // Translate the packet received to
  1813. // MSCHAP v2 format
  1814. //
  1815. cbPacket = WireToHostFormat16(pReceivePacket->Length);
  1816. if ( cbPacket == sizeof( PPP_EAP_PACKET ) + 1 )
  1817. {
  1818. //
  1819. // Check to see if the data is CHAPCODE_Success
  1820. // or CHAPCode Fail and send appropriate packet
  1821. //
  1822. if ( *(pReceivePacket->Data+1) == CHAPCODE_Success )
  1823. {
  1824. //
  1825. //peer could auth successfully
  1826. //
  1827. pSendPacket->Code = EAPCODE_Success;
  1828. }
  1829. else
  1830. {
  1831. pSendPacket->Code = EAPCODE_Failure;
  1832. }
  1833. pEapwb->IdToSend++;
  1834. pEapwb->IdToExpect =
  1835. pSendPacket->Id = pEapwb->IdToSend;
  1836. HostToWireFormat16( (WORD)4, pSendPacket->Length );
  1837. pEapwb->EapState = EMV2_Success;
  1838. //Set the Out attributes here
  1839. pEapOutput->pUserAttributes = pEapwb->pUserAttributes;
  1840. pEapOutput->dwAuthResultCode = pEapwb->dwAuthResultCode;
  1841. pEapOutput->Action = EAPACTION_SendAndDone;
  1842. }
  1843. else
  1844. {
  1845. dwRetCode = ERROR_PPP_INVALID_PACKET;
  1846. }
  1847. }
  1848. break;
  1849. case EMV2_CHAPAuthFail:
  1850. TRACE("EMV2_CHAPAuthFail");
  1851. //
  1852. // We could get a retry or a change password packet here
  1853. // Again we should get only a EAPCODE_Response here...
  1854. //
  1855. //Got a response. So send it to MSCHAP and see what happens
  1856. //
  1857. break;
  1858. case EMV2_Success:
  1859. TRACE("EMV2_Success");
  1860. //
  1861. // See the CS_Done state in raschap for this state to be here.
  1862. //
  1863. break;
  1864. case EMV2_Failure:
  1865. TRACE("EMV2_Failure");
  1866. break;
  1867. case EMV2_ResponseSend:
  1868. default:
  1869. TRACE1("Why is this EAPMschapv2 in this state? %d",pEapwb->EapState );
  1870. break;
  1871. }
  1872. done:
  1873. if ( pSendBuf )
  1874. {
  1875. LocalFree(pSendBuf);
  1876. }
  1877. return dwRetCode;
  1878. }
  1879. DWORD
  1880. GetClientMPPEKeys ( EAPMSCHAPv2WB *pEapwb, PPPAP_RESULT * pApResult )
  1881. {
  1882. DWORD dwRetCode = NO_ERROR;
  1883. BYTE bRecvKey[16] = {0};
  1884. BYTE bSendKey[16] = {0};
  1885. RAS_AUTH_ATTRIBUTE * pAttribute;
  1886. RAS_AUTH_ATTRIBUTE * pSendRecvKeyAttr = NULL;
  1887. //MPPE Keys Type+Length+Salt+KeyLength+NTkey(16)+PAdding(15)
  1888. BYTE bMPPEKey[1+1+2+1+16+15]={0};
  1889. TRACE("GetClientMPPEKeys");
  1890. pEapwb->pUserAttributes = NULL;
  1891. pAttribute = RasAuthAttributeGetVendorSpecific(
  1892. 311, MS_VSA_CHAP_MPPE_Keys,
  1893. pApResult->pUserAttributes);
  1894. if ( NULL == pAttribute )
  1895. {
  1896. TRACE("No User Session Key");
  1897. dwRetCode = ERROR_NOT_FOUND;
  1898. goto done;
  1899. }
  1900. dwRetCode = IASGetSendRecvSessionKeys( ((PBYTE)(pAttribute->Value))+6+8,
  1901. 16,
  1902. pApResult->abResponse,
  1903. 24,
  1904. bSendKey,
  1905. bRecvKey
  1906. );
  1907. if ( NO_ERROR != dwRetCode )
  1908. {
  1909. TRACE("Failed to generate send/recv keys");
  1910. goto done;
  1911. }
  1912. pSendRecvKeyAttr = RasAuthAttributeCreate ( 2 );
  1913. if ( NULL == pSendRecvKeyAttr )
  1914. {
  1915. TRACE("RasAuthAttributeCreate failed");
  1916. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1917. goto done;
  1918. }
  1919. bMPPEKey[0] = MS_VSA_MPPE_Send_Key;
  1920. bMPPEKey[1] = 36;
  1921. bMPPEKey[4] = 16;
  1922. CopyMemory(&bMPPEKey[5], bSendKey, 16 );
  1923. dwRetCode = RasAuthAttributeInsertVSA(
  1924. 0,
  1925. pSendRecvKeyAttr,
  1926. VENDOR_MICROSOFT,
  1927. 36,
  1928. bMPPEKey );
  1929. if ( NO_ERROR != dwRetCode )
  1930. {
  1931. TRACE("Failed to insert send key");
  1932. goto done;
  1933. }
  1934. bMPPEKey[0] = MS_VSA_MPPE_Recv_Key;
  1935. CopyMemory(&bMPPEKey[5], bRecvKey, 16 );
  1936. dwRetCode = RasAuthAttributeInsertVSA(
  1937. 1,
  1938. pSendRecvKeyAttr,
  1939. VENDOR_MICROSOFT,
  1940. 36,
  1941. bMPPEKey );
  1942. if ( NO_ERROR != dwRetCode )
  1943. {
  1944. TRACE("Failed to insert recv key");
  1945. goto done;
  1946. }
  1947. pEapwb->pUserAttributes = pSendRecvKeyAttr;
  1948. done:
  1949. if ( NO_ERROR != dwRetCode )
  1950. {
  1951. if ( pSendRecvKeyAttr )
  1952. RasAuthAttributeDestroy(pSendRecvKeyAttr);
  1953. }
  1954. return dwRetCode;
  1955. }
  1956. DWORD
  1957. EapMSChapv2CMakeMessage(
  1958. IN VOID* pWorkBuf,
  1959. IN PPP_EAP_PACKET* pReceivePacket,
  1960. OUT PPP_EAP_PACKET* pSendPacket,
  1961. IN DWORD cbSendPacket,
  1962. OUT PPP_EAP_OUTPUT* pEapOutput,
  1963. IN PPP_EAP_INPUT* pEapInput
  1964. )
  1965. {
  1966. DWORD dwRetCode = NO_ERROR;
  1967. PPP_CONFIG* pReceiveBuf = NULL;
  1968. PPP_CONFIG* pSendBuf = NULL;
  1969. DWORD cbSendBuf = 1500;
  1970. PPPAP_INPUT ApInput;
  1971. PPPAP_RESULT ApResult;
  1972. WORD cbPacket = 0;
  1973. EAPMSCHAPv2WB * pEapwb = (EAPMSCHAPv2WB * ) pWorkBuf;
  1974. TRACE("EapMSChapv2CMakeMessage");
  1975. //
  1976. //Do default processing here.
  1977. //
  1978. ZeroMemory( &ApResult, sizeof(ApResult) );
  1979. if ( ( pSendBuf = LocalAlloc( LPTR, cbSendBuf ) ) == NULL )
  1980. {
  1981. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  1982. goto done;
  1983. }
  1984. if ( pEapInput != NULL )
  1985. {
  1986. MapEapInputToApInput( pEapInput, &ApInput );
  1987. }
  1988. switch ( pEapwb->EapState )
  1989. {
  1990. case EMV2_Initial:
  1991. TRACE("EMV2_Initial");
  1992. //
  1993. // We can oly get a request here...
  1994. //
  1995. if ( NULL != pReceivePacket )
  1996. {
  1997. if ( pReceivePacket->Code != EAPCODE_Request )
  1998. {
  1999. dwRetCode = ERROR_PPP_INVALID_PACKET;
  2000. break;
  2001. }
  2002. //
  2003. // Translate the packet received to
  2004. // MSCHAP v2 format
  2005. //
  2006. cbPacket = WireToHostFormat16(pReceivePacket->Length);
  2007. if ( cbPacket > sizeof( PPP_EAP_PACKET ) )
  2008. {
  2009. pReceiveBuf = (PPP_CONFIG *) (pReceivePacket->Data + 1);
  2010. dwRetCode = CallMakeMessageAndSetEAPState(
  2011. pEapwb->pwb,
  2012. pReceiveBuf,
  2013. pSendBuf,
  2014. cbSendBuf,
  2015. &ApResult,
  2016. ( pEapInput ? &ApInput : NULL ),
  2017. pEapOutput
  2018. );
  2019. // Translate MSCHAPv2 packet to EAP packet
  2020. //
  2021. if ( NO_ERROR == dwRetCode && pSendBuf )
  2022. {
  2023. pSendPacket->Code = EAPCODE_Response;
  2024. pEapwb->IdToExpect = pEapwb->IdToSend =
  2025. pSendPacket->Id = pEapwb->pwb->bIdToSend;
  2026. //
  2027. // Length = sizeof Header + sizeof MSCHAP packet to send
  2028. // This includes the first byte of
  2029. cbPacket = WireToHostFormat16( pSendBuf->Length );
  2030. CopyMemory ( pSendPacket->Data+1, pSendBuf, cbPacket);
  2031. cbPacket += sizeof(PPP_EAP_PACKET);
  2032. HostToWireFormat16( cbPacket, pSendPacket->Length );
  2033. pSendPacket->Data[0] = (BYTE)PPP_EAP_MSCHAPv2;
  2034. pEapwb->EapState = EMV2_ResponseSend;
  2035. }
  2036. }
  2037. }
  2038. break;
  2039. case EMV2_ResponseSend:
  2040. TRACE("EMV2_ResponseSend");
  2041. //
  2042. // We should get either a CHAP auth success or CHAP Auth fail here
  2043. // for the initial challenge send out.
  2044. //
  2045. if ( NULL != pReceivePacket )
  2046. {
  2047. if ( pReceivePacket->Code != EAPCODE_Request &&
  2048. pReceivePacket->Code != EAPCODE_Failure
  2049. )
  2050. {
  2051. dwRetCode = ERROR_PPP_INVALID_PACKET;
  2052. break;
  2053. }
  2054. if ( pReceivePacket->Code == EAPCODE_Failure )
  2055. {
  2056. TRACE("Got a Code Failure when expecting Response. Failing Auth");
  2057. pEapwb->EapState = EMV2_Failure;
  2058. pEapOutput->Action = EAPACTION_Done;
  2059. pEapOutput->fSaveUserData = FALSE;
  2060. ZeroMemory ( pEapwb->pUserProp->szPassword, sizeof( pEapwb->pUserProp->szPassword ) );
  2061. pEapOutput->dwAuthResultCode = ERROR_AUTHENTICATION_FAILURE;
  2062. break;
  2063. }
  2064. //
  2065. // Translate the packet received to
  2066. // MSCHAP v2 format
  2067. //
  2068. cbPacket = WireToHostFormat16(pReceivePacket->Length);
  2069. if ( cbPacket > sizeof( PPP_EAP_PACKET ) )
  2070. {
  2071. pReceiveBuf = (PPP_CONFIG *) (pReceivePacket->Data + 1);
  2072. dwRetCode = CallMakeMessageAndSetEAPState(
  2073. pEapwb->pwb,
  2074. pReceiveBuf,
  2075. pSendBuf,
  2076. cbSendBuf,
  2077. &ApResult,
  2078. ( pEapInput ? &ApInput : NULL ),
  2079. pEapOutput
  2080. );
  2081. //
  2082. // Translate MSCHAPv2 packet to EAP packet
  2083. //
  2084. if ( NO_ERROR == dwRetCode && pSendBuf )
  2085. {
  2086. if ( ApResult.dwError == NO_ERROR )
  2087. {
  2088. if ( ApResult.Action == APA_NoAction )
  2089. {
  2090. pEapOutput->Action = EAPACTION_NoAction;
  2091. pEapOutput->dwAuthResultCode = NO_ERROR;
  2092. break;
  2093. }
  2094. //
  2095. // We need to change MSCHAP keys to MPPE send recv keys
  2096. // This is needed because there is no way to pass the
  2097. // MSCHAP challenge response back
  2098. //
  2099. dwRetCode = GetClientMPPEKeys ( pEapwb, &ApResult );
  2100. if ( NO_ERROR != dwRetCode )
  2101. {
  2102. break;
  2103. }
  2104. //
  2105. //Client could successfully validate the server
  2106. //
  2107. pSendPacket->Code = EAPCODE_Response;
  2108. pEapwb->IdToSend ++;
  2109. //send the same id as received packet back
  2110. pEapwb->IdToExpect = pSendPacket->Id = pReceivePacket->Id;
  2111. //
  2112. // Length = sizeof Header + sizeof MSCHAP packet to send
  2113. // This includes the first byte of
  2114. * (pSendPacket->Data+1) = CHAPCODE_Success;
  2115. cbPacket = sizeof(PPP_EAP_PACKET) + 1;
  2116. HostToWireFormat16( cbPacket, pSendPacket->Length );
  2117. pSendPacket->Data[0] = (BYTE)PPP_EAP_MSCHAPv2;
  2118. pEapwb->EapState = EMV2_CHAPAuthSuccess;
  2119. //
  2120. // Set the out attributes and the response
  2121. //
  2122. pEapOutput->Action = EAPACTION_Send;
  2123. pEapwb->dwAuthResultCode = ApResult.dwError;
  2124. }
  2125. else
  2126. {
  2127. //
  2128. // Based on what MSCHAPV2 has send back
  2129. // we need to Invoke appropriate interactive UI
  2130. // Retry password or change password here.
  2131. // If both retry and change pwd are not
  2132. // applicable then just send a fail message.
  2133. // and wait for EAP_Failure message from server.
  2134. // And Auth state goes to CHAPAuthFailed
  2135. //
  2136. // If this is a failure with rety then show
  2137. // interactive UI.
  2138. if ( pEapwb->fFlags & EAPMSCHAPv2_FLAG_MACHINE_AUTH )
  2139. {
  2140. //
  2141. // This is a machine auth. So we dont to show any
  2142. // retry or any of that stuff even though the server
  2143. // might have send such things back.
  2144. //
  2145. pEapOutput->dwAuthResultCode = ERROR_AUTHENTICATION_FAILURE;
  2146. pEapOutput->Action = EAPACTION_Done;
  2147. pEapwb->EapState = EMV2_Failure;
  2148. }
  2149. else
  2150. {
  2151. if ( ApResult.fRetry )
  2152. {
  2153. pEapOutput->fInvokeInteractiveUI = TRUE;
  2154. //
  2155. // Setup the UI Context data
  2156. //
  2157. pEapwb->pUIContextData =
  2158. (PEAPMSCHAPv2_INTERACTIVE_UI) LocalAlloc ( LPTR,
  2159. sizeof(EAPMSCHAPv2_INTERACTIVE_UI) );
  2160. if ( NULL == pEapwb->pUIContextData )
  2161. {
  2162. TRACE ("Error allocating memory for UI context data");
  2163. dwRetCode = ERROR_OUTOFMEMORY;
  2164. goto done;
  2165. }
  2166. pEapwb->pUIContextData->dwVersion = 1;
  2167. pEapwb->pUIContextData->fFlags |= EAPMSCHAPv2_INTERACTIVE_UI_FLAG_RETRY;
  2168. pEapwb->dwInteractiveUIOperation |= EAPMSCHAPv2_INTERACTIVE_UI_FLAG_RETRY;
  2169. if ( pEapwb->pUserProp )
  2170. {
  2171. CopyMemory( &(pEapwb->pUIContextData->UserProp),
  2172. pEapwb->pUserProp,
  2173. sizeof(EAPMSCHAPv2_USER_PROPERTIES)
  2174. );
  2175. }
  2176. if ( pEapwb->pConnProp->fFlags & EAPMSCHAPv2_FLAG_USE_WINLOGON_CREDS )
  2177. {
  2178. //We are using winlogon creds
  2179. // and this is a retryable failure
  2180. // so copy over the username and domain
  2181. // from chap wb to eapchap wb
  2182. WCHAR * pWchar = NULL;
  2183. pWchar = wcschr( pEapwb->wszRadiusUserName, L'\\' );
  2184. if ( pWchar == NULL )
  2185. {
  2186. WideCharToMultiByte(
  2187. CP_ACP,
  2188. 0,
  2189. pEapwb->wszRadiusUserName,
  2190. -1,
  2191. pEapwb->pUIContextData->UserProp.szUserName,
  2192. UNLEN + 1,
  2193. NULL,
  2194. NULL );
  2195. }
  2196. else
  2197. {
  2198. *pWchar = 0;
  2199. WideCharToMultiByte(
  2200. CP_ACP,
  2201. 0,
  2202. pEapwb->wszRadiusUserName,
  2203. -1,
  2204. pEapwb->pUIContextData->UserProp.szDomain,
  2205. DNLEN + 1,
  2206. NULL,
  2207. NULL );
  2208. *pWchar = L'\\';
  2209. WideCharToMultiByte(
  2210. CP_ACP,
  2211. 0,
  2212. pWchar + 1,
  2213. -1,
  2214. pEapwb->pUIContextData->UserProp.szUserName,
  2215. UNLEN + 1,
  2216. NULL,
  2217. NULL );
  2218. }
  2219. }
  2220. pEapOutput->Action = EAPACTION_NoAction;
  2221. pEapOutput->pUIContextData = (PBYTE)pEapwb->pUIContextData;
  2222. pEapOutput->dwSizeOfUIContextData = sizeof(EAPMSCHAPv2_INTERACTIVE_UI);
  2223. pEapwb->EapState = EMV2_CHAPAuthFail;
  2224. }
  2225. else if ( ApResult.dwError == ERROR_PASSWD_EXPIRED )
  2226. {
  2227. //
  2228. // show the change password GUI.
  2229. //
  2230. pEapOutput->fInvokeInteractiveUI = TRUE;
  2231. //
  2232. // Setup the UI Context data
  2233. //
  2234. pEapwb->pUIContextData =
  2235. (PEAPMSCHAPv2_INTERACTIVE_UI) LocalAlloc ( LPTR,
  2236. sizeof(EAPMSCHAPv2_INTERACTIVE_UI) );
  2237. if ( NULL == pEapwb->pUIContextData )
  2238. {
  2239. TRACE ("Error allocating memory for UI context data");
  2240. dwRetCode = ERROR_OUTOFMEMORY;
  2241. goto done;
  2242. }
  2243. pEapwb->pUIContextData->dwVersion = 1;
  2244. if ( pEapwb->pConnProp->fFlags & EAPMSCHAPv2_FLAG_USE_WINLOGON_CREDS )
  2245. {
  2246. //
  2247. // Show the dialog with old pwd, new pwd and conf pwd
  2248. //
  2249. pEapwb->pUIContextData->fFlags |= EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD_WINLOGON;
  2250. pEapwb->dwInteractiveUIOperation |= EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD_WINLOGON;
  2251. }
  2252. else
  2253. {
  2254. //
  2255. // We have the old password. So show the dialog with new pwd and conf pwd.
  2256. //
  2257. pEapwb->pUIContextData->fFlags |= EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD;
  2258. pEapwb->dwInteractiveUIOperation |= EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD;
  2259. }
  2260. if ( pEapwb->pUserProp )
  2261. {
  2262. CopyMemory( &(pEapwb->pUIContextData->UserProp),
  2263. pEapwb->pUserProp,
  2264. sizeof(EAPMSCHAPv2_USER_PROPERTIES)
  2265. );
  2266. }
  2267. pEapOutput->Action = EAPACTION_NoAction;
  2268. pEapOutput->pUIContextData = (PBYTE)pEapwb->pUIContextData;
  2269. pEapOutput->dwSizeOfUIContextData = sizeof(EAPMSCHAPv2_INTERACTIVE_UI);
  2270. pEapwb->EapState = EMV2_CHAPAuthFail;
  2271. }
  2272. else
  2273. {
  2274. //
  2275. // this is not a retryable failure
  2276. // So we are done with Auth and failed.
  2277. //
  2278. pEapOutput->dwAuthResultCode = ApResult.dwError;
  2279. pEapOutput->Action = EAPACTION_Done;
  2280. pEapwb->EapState = EMV2_Failure;
  2281. }
  2282. }
  2283. }
  2284. }
  2285. else
  2286. {
  2287. // Something went wrong here.
  2288. TRACE1("Error returned by MSCHAPv2 protocol 0x%x", dwRetCode);
  2289. }
  2290. }
  2291. else
  2292. {
  2293. dwRetCode = ERROR_PPP_INVALID_PACKET;
  2294. }
  2295. }
  2296. else
  2297. {
  2298. dwRetCode = ERROR_PPP_INVALID_PACKET;
  2299. }
  2300. break;
  2301. case EMV2_CHAPAuthFail:
  2302. TRACE("EMV2_CHAPAuthFail");
  2303. //
  2304. // We come here in case of a retryable
  2305. // failure from chap and after we have popped
  2306. // interactive UI.
  2307. //
  2308. //
  2309. // Check to see if we have got data from user
  2310. //
  2311. if ( pEapInput->fDataReceivedFromInteractiveUI )
  2312. {
  2313. //
  2314. // Copy the new uid/pwd and then call chap make message again.
  2315. // adjust our state
  2316. LocalFree(pEapwb->pUIContextData);
  2317. pEapwb->pUIContextData = NULL;
  2318. LocalFree(pEapwb->pUserProp);
  2319. pEapwb->pUserProp = (PEAPMSCHAPv2_USER_PROPERTIES)LocalAlloc(LPTR,
  2320. sizeof(EAPMSCHAPv2_USER_PROPERTIES) );
  2321. if (NULL == pEapwb->pUserProp )
  2322. {
  2323. TRACE("Failed to allocate memory for user props.");
  2324. dwRetCode = ERROR_OUTOFMEMORY;
  2325. break;
  2326. }
  2327. CopyMemory( pEapwb->pUserProp,
  2328. &(((PEAPMSCHAPv2_INTERACTIVE_UI)(pEapInput->pDataFromInteractiveUI))->UserProp),
  2329. sizeof(EAPMSCHAPv2_USER_PROPERTIES)
  2330. );
  2331. //
  2332. // Call into mschap here
  2333. //
  2334. ApInput.pszDomain = pEapwb->pUserProp->szDomain;
  2335. if ( ((PEAPMSCHAPv2_INTERACTIVE_UI)(pEapInput->pDataFromInteractiveUI))->fFlags &
  2336. EAPMSCHAPv2_INTERACTIVE_UI_FLAG_RETRY
  2337. )
  2338. {
  2339. ApInput.pszUserName = pEapwb->pUserProp->szUserName;
  2340. ApInput.pszPassword = pEapwb->pUserProp->szPassword;
  2341. }
  2342. else
  2343. {
  2344. if ( pEapwb->pConnProp->fFlags & EAPMSCHAPv2_FLAG_USE_WINLOGON_CREDS )
  2345. {
  2346. CopyMemory ( pEapwb->pUserProp->szPassword,
  2347. ((PEAPMSCHAPv2_INTERACTIVE_UI)(pEapInput->pDataFromInteractiveUI))->UserProp.szPassword,
  2348. PWLEN
  2349. );
  2350. }
  2351. CopyMemory ( pEapwb->szOldPassword,
  2352. pEapwb->pUserProp->szPassword,
  2353. PWLEN
  2354. );
  2355. CopyMemory ( pEapwb->pUserProp->szPassword,
  2356. ((PEAPMSCHAPv2_INTERACTIVE_UI)(pEapInput->pDataFromInteractiveUI))->szNewPassword,
  2357. PWLEN
  2358. );
  2359. ApInput.pszUserName = pEapwb->pUserProp->szUserName;
  2360. ApInput.pszPassword = pEapwb->pUserProp->szPassword;
  2361. ApInput.pszOldPassword = pEapwb->szOldPassword;
  2362. }
  2363. dwRetCode = CallMakeMessageAndSetEAPState(
  2364. pEapwb->pwb,
  2365. pReceiveBuf,
  2366. pSendBuf,
  2367. cbSendBuf,
  2368. &ApResult,
  2369. ( pEapInput ? &ApInput : NULL ),
  2370. pEapOutput
  2371. );
  2372. if ( NO_ERROR == dwRetCode && pSendBuf )
  2373. {
  2374. pSendPacket->Code = EAPCODE_Response;
  2375. pSendPacket->Id = pEapwb->pwb->bIdToSend;
  2376. //
  2377. // Length = sizeof Header + sizeof MSCHAP packet to send
  2378. // This includes the first byte of
  2379. cbPacket = WireToHostFormat16( pSendBuf->Length );
  2380. CopyMemory ( pSendPacket->Data+1, pSendBuf, cbPacket);
  2381. cbPacket += sizeof(PPP_EAP_PACKET);
  2382. HostToWireFormat16( cbPacket, pSendPacket->Length );
  2383. pSendPacket->Data[0] = (BYTE)PPP_EAP_MSCHAPv2;
  2384. pEapwb->EapState = EMV2_ResponseSend;
  2385. pEapOutput->dwAuthResultCode = ApResult.dwError;
  2386. pEapOutput->Action = EAPACTION_Send;
  2387. }
  2388. }
  2389. else
  2390. {
  2391. TRACE("No Data received from interactive UI when expecting some");
  2392. //Work around for PPP misbehavior. We have invoked
  2393. //interactive UI and ppp is sending stuff to us all the time...
  2394. if ( !pEapwb->pUIContextData )
  2395. {
  2396. pEapOutput->dwAuthResultCode = ApResult.dwError;
  2397. pEapOutput->Action = EAPACTION_Done;
  2398. pEapwb->EapState = EMV2_Failure;
  2399. }
  2400. }
  2401. break;
  2402. case EMV2_CHAPAuthSuccess:
  2403. TRACE("EMV2_CHAPAuthSuccess");
  2404. //We should get an EAPSUCCESS here
  2405. if ( NULL != pReceivePacket )
  2406. {
  2407. if ( pReceivePacket->Code != EAPCODE_Success )
  2408. {
  2409. dwRetCode = ERROR_PPP_INVALID_PACKET;
  2410. pEapwb->EapState = EMV2_Failure;
  2411. break;
  2412. }
  2413. if ( ( pEapwb->dwInteractiveUIOperation &
  2414. EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD_WINLOGON
  2415. ) ||
  2416. ( ( pEapwb->dwInteractiveUIOperation &
  2417. EAPMSCHAPv2_INTERACTIVE_UI_FLAG_RETRY ) &&
  2418. ( pEapwb->pConnProp->fFlags &
  2419. EAPMSCHAPv2_FLAG_USE_WINLOGON_CREDS
  2420. )
  2421. )
  2422. )
  2423. {
  2424. //
  2425. // We need to plumb creds in winlogon.
  2426. //
  2427. dwRetCode = RasSetCachedCredentials ( pEapwb->pUserProp->szUserName,
  2428. pEapwb->pUserProp->szDomain,
  2429. pEapwb->pUserProp->szPassword
  2430. );
  2431. if ( NO_ERROR != dwRetCode )
  2432. {
  2433. TRACE1("RasSetCachedCredentials failed with error 0x%x", dwRetCode);
  2434. TRACE("Change password operation could not apply changes to winlogon.");
  2435. dwRetCode = NO_ERROR;
  2436. }
  2437. //since we entered this mode in winlogon mode
  2438. //wipe out the uid pwd if set
  2439. //
  2440. ZeroMemory ( pEapwb->pUserProp->szUserName, sizeof(pEapwb->pUserProp->szUserName) );
  2441. ZeroMemory ( pEapwb->pUserProp->szDomain, sizeof(pEapwb->pUserProp->szDomain) );
  2442. }
  2443. pEapwb->EapState = EMV2_Success;
  2444. pEapOutput->Action = EAPACTION_Done;
  2445. pEapOutput->fSaveUserData = TRUE;
  2446. if ( pEapwb->pUserProp->szPassword[0] )
  2447. {
  2448. DATA_BLOB DBPassword;
  2449. //Encode the password to send back.
  2450. dwRetCode = EncodePassword( strlen(pEapwb->pUserProp->szPassword) + 1,
  2451. pEapwb->pUserProp->szPassword,
  2452. &(DBPassword)
  2453. );
  2454. if ( NO_ERROR == dwRetCode )
  2455. {
  2456. AllocateUserDataWithEncPwd ( pEapwb, &DBPassword );
  2457. FreePassword ( &DBPassword );
  2458. }
  2459. else
  2460. {
  2461. TRACE1("EncodePassword failed with errror 0x%x.", dwRetCode);
  2462. dwRetCode = NO_ERROR;
  2463. }
  2464. }
  2465. RtlSecureZeroMemory ( pEapwb->pUserProp->szPassword, sizeof( pEapwb->pUserProp->szPassword ) );
  2466. LocalFree ( pEapOutput->pUserData );
  2467. pEapOutput->pUserData = (PBYTE)pEapwb->pUserProp;
  2468. pEapOutput->dwSizeOfUserData =
  2469. sizeof( EAPMSCHAPv2_USER_PROPERTIES) + pEapwb->pUserProp->cbEncPassword -1 ;
  2470. pEapOutput->pUserAttributes = pEapwb->pUserAttributes;
  2471. pEapOutput->dwAuthResultCode = pEapwb->dwAuthResultCode;
  2472. }
  2473. else
  2474. {
  2475. dwRetCode = ERROR_PPP_INVALID_PACKET;
  2476. }
  2477. break;
  2478. case EMV2_Success:
  2479. TRACE("EMV2_Success");
  2480. break;
  2481. case EMV2_Failure:
  2482. TRACE("EMV2_Failure");
  2483. break;
  2484. case EMV2_RequestSend:
  2485. default:
  2486. TRACE1("Why is this EAPMschapv2 in this state? %d", pEapwb->EapState);
  2487. break;
  2488. }
  2489. done:
  2490. if ( pSendBuf )
  2491. {
  2492. LocalFree(pSendBuf);
  2493. }
  2494. return dwRetCode;
  2495. }
  2496. //**
  2497. //
  2498. // Call: EapMSChapv2MakeMessage
  2499. //
  2500. // Returns: NO_ERROR - Success
  2501. // Non-zero returns - Failure
  2502. //
  2503. // Description:
  2504. //
  2505. DWORD
  2506. EapMSChapv2MakeMessage(
  2507. IN VOID* pWorkBuf,
  2508. IN PPP_EAP_PACKET* pReceivePacket,
  2509. OUT PPP_EAP_PACKET* pSendPacket,
  2510. IN DWORD cbSendPacket,
  2511. OUT PPP_EAP_OUTPUT* pEapOutput,
  2512. IN PPP_EAP_INPUT* pEapInput
  2513. )
  2514. {
  2515. DWORD dwRetCode = NO_ERROR;
  2516. EAPMSCHAPv2WB * pwb = (EAPMSCHAPv2WB *)pWorkBuf;
  2517. TRACE("EapMSChapv2MakeMessage");
  2518. //
  2519. // There may not be a real pressing need to split
  2520. // this function but it is just cleaner.
  2521. if ( pwb->pwb->fServer )
  2522. {
  2523. dwRetCode = EapMSChapv2SMakeMessage ( pWorkBuf,
  2524. pReceivePacket,
  2525. pSendPacket,
  2526. cbSendPacket,
  2527. pEapOutput,
  2528. pEapInput
  2529. );
  2530. }
  2531. else
  2532. {
  2533. dwRetCode = EapMSChapv2CMakeMessage ( pWorkBuf,
  2534. pReceivePacket,
  2535. pSendPacket,
  2536. cbSendPacket,
  2537. pEapOutput,
  2538. pEapInput
  2539. );
  2540. }
  2541. return dwRetCode;
  2542. }
  2543. //**
  2544. //
  2545. // Call: EapChapMakeMessage
  2546. //
  2547. // Returns: NO_ERROR - Success
  2548. // Non-zero returns - Failure
  2549. //
  2550. // Description:
  2551. //
  2552. DWORD
  2553. EapChapMakeMessage(
  2554. IN VOID* pWorkBuf,
  2555. IN PPP_EAP_PACKET* pReceivePacket,
  2556. OUT PPP_EAP_PACKET* pSendPacket,
  2557. IN DWORD cbSendPacket,
  2558. OUT PPP_EAP_OUTPUT* pEapOutput,
  2559. IN PPP_EAP_INPUT* pEapInput
  2560. )
  2561. {
  2562. DWORD dwRetCode;
  2563. PPP_CONFIG* pReceiveBuf = NULL;
  2564. PPP_CONFIG* pSendBuf = NULL;
  2565. DWORD cbSendBuf = 1500;
  2566. PPPAP_INPUT ApInput;
  2567. PPPAP_RESULT ApResult;
  2568. CHAPWB * pwb = (CHAPWB *)pWorkBuf;
  2569. ZeroMemory( &ApResult, sizeof(ApResult) );
  2570. if ( ( pSendBuf = LocalAlloc( LPTR, cbSendBuf ) ) == NULL )
  2571. {
  2572. return( ERROR_NOT_ENOUGH_MEMORY );
  2573. }
  2574. //
  2575. // Convert EAP to CHAP packet.
  2576. //
  2577. if ( pReceivePacket != NULL )
  2578. {
  2579. WORD cbPacket = WireToHostFormat16( pReceivePacket->Length );
  2580. if ( ( pReceiveBuf = LocalAlloc( LPTR, cbPacket ) ) == NULL )
  2581. {
  2582. LocalFree( pSendBuf );
  2583. return( ERROR_NOT_ENOUGH_MEMORY );
  2584. }
  2585. switch( pReceivePacket->Code )
  2586. {
  2587. case EAPCODE_Request:
  2588. //
  2589. // CHAP challenge code
  2590. //
  2591. pReceiveBuf->Code = 1;
  2592. //
  2593. // Length is EAP length - 1 for type
  2594. //
  2595. cbPacket--;
  2596. break;
  2597. case EAPCODE_Response:
  2598. //
  2599. // CHAP response code
  2600. //
  2601. pReceiveBuf->Code = 2;
  2602. //
  2603. // Length is EAP length - 1 for type
  2604. //
  2605. cbPacket--;
  2606. break;
  2607. case EAPCODE_Success:
  2608. //
  2609. // CHAP success code
  2610. //
  2611. pReceiveBuf->Code = 3;
  2612. break;
  2613. case EAPCODE_Failure:
  2614. //
  2615. // CHAP failure code
  2616. //
  2617. pReceiveBuf->Code = 4;
  2618. break;
  2619. default:
  2620. //
  2621. // Unknown code
  2622. //
  2623. LocalFree( pSendBuf );
  2624. LocalFree( pReceiveBuf );
  2625. return( ERROR_PPP_INVALID_PACKET );
  2626. }
  2627. //
  2628. // Set the Id
  2629. //
  2630. pReceiveBuf->Id = pReceivePacket->Id;
  2631. //
  2632. // Set the length
  2633. //
  2634. HostToWireFormat16( (WORD)cbPacket, pReceiveBuf->Length );
  2635. if ( cbPacket > PPP_EAP_PACKET_HDR_LEN )
  2636. {
  2637. if ( ( pReceivePacket->Code == EAPCODE_Request ) ||
  2638. ( pReceivePacket->Code == EAPCODE_Response ) )
  2639. {
  2640. //
  2641. // Do not copy EAP type
  2642. //
  2643. CopyMemory( pReceiveBuf->Data,
  2644. pReceivePacket->Data+1,
  2645. cbPacket - PPP_EAP_PACKET_HDR_LEN );
  2646. }
  2647. else
  2648. {
  2649. //
  2650. // As per the EAP spec, there shouldn't be any data but
  2651. // copy it anyway if there is.
  2652. //
  2653. CopyMemory( pReceiveBuf->Data,
  2654. pReceivePacket->Data,
  2655. cbPacket - PPP_EAP_PACKET_HDR_LEN );
  2656. }
  2657. }
  2658. }
  2659. if ( pEapInput != NULL )
  2660. {
  2661. MapEapInputToApInput( pEapInput, &ApInput );
  2662. //
  2663. // On the client side, if we received an indication that a success
  2664. // packet was received, then simply create a success packet and
  2665. // pass it in
  2666. //
  2667. if ( pEapInput->fSuccessPacketReceived )
  2668. {
  2669. if ( ( pReceiveBuf = LocalAlloc( LPTR, 4 ) ) == NULL )
  2670. {
  2671. LocalFree( pSendBuf );
  2672. return( ERROR_NOT_ENOUGH_MEMORY );
  2673. }
  2674. pReceiveBuf->Code = 3; // CHAP success code
  2675. pReceiveBuf->Id = pwb->bIdExpected;
  2676. HostToWireFormat16( (WORD)4, pReceiveBuf->Length );
  2677. }
  2678. }
  2679. dwRetCode = ChapMakeMessage(
  2680. pWorkBuf,
  2681. pReceiveBuf,
  2682. pSendBuf,
  2683. cbSendBuf,
  2684. &ApResult,
  2685. ( pEapInput == NULL ) ? NULL : &ApInput );
  2686. if ( dwRetCode != NO_ERROR )
  2687. {
  2688. LocalFree( pSendBuf );
  2689. LocalFree( pReceiveBuf );
  2690. return( dwRetCode );
  2691. }
  2692. //
  2693. // Convert ApResult to pEapOutput
  2694. //
  2695. switch( ApResult.Action )
  2696. {
  2697. case APA_NoAction:
  2698. pEapOutput->Action = EAPACTION_NoAction;
  2699. break;
  2700. case APA_Done:
  2701. pEapOutput->Action = EAPACTION_Done;
  2702. break;
  2703. case APA_SendAndDone:
  2704. pEapOutput->Action = EAPACTION_SendAndDone;
  2705. break;
  2706. case APA_Send:
  2707. pEapOutput->Action = EAPACTION_Send;
  2708. break;
  2709. case APA_SendWithTimeout:
  2710. pEapOutput->Action = ( pwb->fServer )
  2711. ? EAPACTION_SendWithTimeout
  2712. : EAPACTION_Send;
  2713. break;
  2714. case APA_SendWithTimeout2:
  2715. pEapOutput->Action = ( pwb->fServer )
  2716. ? EAPACTION_SendWithTimeoutInteractive
  2717. : EAPACTION_Send;
  2718. break;
  2719. case APA_Authenticate:
  2720. pEapOutput->pUserAttributes = ApResult.pUserAttributes;
  2721. pEapOutput->Action = EAPACTION_Authenticate;
  2722. break;
  2723. default:
  2724. RTASSERT(FALSE);
  2725. break;
  2726. }
  2727. switch( pEapOutput->Action )
  2728. {
  2729. case EAPACTION_SendAndDone:
  2730. case EAPACTION_Send:
  2731. case EAPACTION_SendWithTimeout:
  2732. case EAPACTION_SendWithTimeoutInteractive:
  2733. {
  2734. //
  2735. // Convert CHAP to EAP packet
  2736. // Length is CHAP length + 1 for EAP type
  2737. //
  2738. WORD cbPacket = WireToHostFormat16( pSendBuf->Length );
  2739. switch( pSendBuf->Code )
  2740. {
  2741. case 1: // CHAPCODE_Challenge
  2742. pSendPacket->Code = EAPCODE_Request;
  2743. cbPacket++; // Add one octect for EAP type
  2744. break;
  2745. case 2: // CHAPCODE_Response
  2746. pSendPacket->Code = EAPCODE_Response;
  2747. cbPacket++; // Add one octect for EAP type
  2748. break;
  2749. case 3: // CHAPCODE_Success
  2750. pSendPacket->Code = EAPCODE_Success;
  2751. break;
  2752. case 4: // CHAPCODE_Failure
  2753. pSendPacket->Code = EAPCODE_Failure;
  2754. break;
  2755. default:
  2756. RTASSERT( FALSE );
  2757. break;
  2758. }
  2759. pSendPacket->Id = pSendBuf->Id;
  2760. //
  2761. // Need to copy the payload and the EAP type in the data field
  2762. //
  2763. if ( ( pSendPacket->Code == EAPCODE_Request ) ||
  2764. ( pSendPacket->Code == EAPCODE_Response ) )
  2765. {
  2766. HostToWireFormat16( (WORD)cbPacket, pSendPacket->Length );
  2767. *pSendPacket->Data = EAPTYPE_MD5Challenge; // EAPTYPE_MD5Challenge;
  2768. //
  2769. // If there is a payload, copy it
  2770. //
  2771. if ( ( cbPacket - 1 ) > PPP_CONFIG_HDR_LEN )
  2772. {
  2773. CopyMemory( pSendPacket->Data+1,
  2774. pSendBuf->Data,
  2775. cbPacket - 1 - PPP_CONFIG_HDR_LEN );
  2776. }
  2777. }
  2778. else
  2779. {
  2780. //
  2781. // Success or failure should not have any data bytes.
  2782. //
  2783. HostToWireFormat16( (WORD)4, pSendPacket->Length );
  2784. }
  2785. //
  2786. // Fall thru...
  2787. //
  2788. }
  2789. default:
  2790. pEapOutput->dwAuthResultCode = ApResult.dwError;
  2791. break;
  2792. }
  2793. LocalFree( pSendBuf );
  2794. if ( pReceiveBuf != NULL )
  2795. {
  2796. LocalFree( pReceiveBuf );
  2797. }
  2798. return( dwRetCode );
  2799. }
  2800. //**
  2801. //
  2802. // Call: EapChapInitialize
  2803. //
  2804. // Returns: NO_ERROR - Success
  2805. // Non-zero returns - Failure
  2806. //
  2807. // Description:
  2808. //
  2809. DWORD
  2810. EapChapInitialize(
  2811. IN BOOL fInitialize
  2812. )
  2813. {
  2814. return ChapInit( fInitialize );
  2815. }
  2816. //**
  2817. //
  2818. // Call: RasEapGetInfo
  2819. //
  2820. // Returns: NO_ERROR - Success
  2821. // Non-zero returns - Failure
  2822. //
  2823. // Description:
  2824. //
  2825. DWORD
  2826. RasEapGetInfo(
  2827. IN DWORD dwEapTypeId,
  2828. OUT PPP_EAP_INFO* pEapInfo
  2829. )
  2830. {
  2831. if ( dwEapTypeId != PPP_EAP_MSCHAPv2 &&
  2832. dwEapTypeId != EAPTYPE_MD5Challenge
  2833. )
  2834. {
  2835. //
  2836. // We support 4 (MD5) eap type
  2837. //
  2838. //
  2839. // and now we support MSCHAP V2 also
  2840. //
  2841. //
  2842. return( ERROR_NOT_SUPPORTED );
  2843. }
  2844. ZeroMemory( pEapInfo, sizeof( PPP_EAP_INFO ) );
  2845. //
  2846. // Fill in the required information
  2847. //
  2848. pEapInfo->dwEapTypeId = dwEapTypeId;
  2849. if ( dwEapTypeId == EAPTYPE_MD5Challenge ) //MD5 CHAP
  2850. {
  2851. pEapInfo->RasEapInitialize = EapChapInitialize;
  2852. pEapInfo->RasEapBegin = EapChapBegin;
  2853. pEapInfo->RasEapEnd = EapChapEnd;
  2854. pEapInfo->RasEapMakeMessage = EapChapMakeMessage;
  2855. }
  2856. else
  2857. {
  2858. pEapInfo->RasEapInitialize = EapMSCHAPv2Initialize;
  2859. pEapInfo->RasEapBegin = EapMSChapv2Begin;
  2860. pEapInfo->RasEapEnd = EapMSChapv2End;
  2861. pEapInfo->RasEapMakeMessage = EapMSChapv2MakeMessage;
  2862. }
  2863. return( NO_ERROR );
  2864. }
  2865. DWORD
  2866. RasEapGetCredentials(
  2867. DWORD dwTypeId,
  2868. VOID * pWorkBuf,
  2869. VOID ** ppCredentials)
  2870. {
  2871. RASMAN_CREDENTIALS *pCreds = NULL;
  2872. DWORD dwRetCode = NO_ERROR;
  2873. EAPMSCHAPv2WB *pWB = (EAPMSCHAPv2WB *)pWorkBuf;
  2874. DWORD cbPassword;
  2875. PBYTE pbPassword = NULL;
  2876. if(PPP_EAP_MSCHAPv2 != dwTypeId)
  2877. {
  2878. dwRetCode = E_NOTIMPL;
  2879. goto done;
  2880. }
  2881. if(NULL == pWorkBuf)
  2882. {
  2883. dwRetCode = E_INVALIDARG;
  2884. goto done;
  2885. }
  2886. //
  2887. // Retrieve the password and return. Its important that
  2888. // the allocation below is made from process heap.
  2889. //
  2890. pCreds = LocalAlloc(LPTR, sizeof(RASMAN_CREDENTIALS));
  2891. if(NULL == pCreds)
  2892. {
  2893. dwRetCode = GetLastError();
  2894. goto done;
  2895. }
  2896. (VOID) StringCchCopyA(pCreds->szUserName, UNLEN, pWB->pwb->szUserName);
  2897. (VOID) StringCchCopyA(pCreds->szDomain, DNLEN, pWB->pwb->szDomain);
  2898. // DecodePw( pWB->pwb->chSeed, pWB->pwb->szPassword );
  2899. dwRetCode = DecodePassword(&pWB->pwb->DBPassword, &cbPassword,
  2900. &pbPassword);
  2901. if(NO_ERROR != dwRetCode)
  2902. {
  2903. goto done;
  2904. }
  2905. //
  2906. // Convert the password to unicode
  2907. //
  2908. if(!MultiByteToWideChar(CP_ACP,
  2909. 0,
  2910. pWB->pwb->szPassword,
  2911. -1,
  2912. pCreds->wszPassword,
  2913. PWLEN))
  2914. {
  2915. TRACE("RasEapGetCredentials: multibytetowidechar failed");
  2916. }
  2917. // EncodePw(pWB->pwb->chSeed, pWB->pwb->szPassword);
  2918. RtlSecureZeroMemory(pbPassword, cbPassword);
  2919. LocalFree(pbPassword);
  2920. done:
  2921. *ppCredentials = (VOID *) pCreds;
  2922. return dwRetCode;
  2923. }
  2924. DWORD
  2925. ReadConnectionData(
  2926. IN BOOL fWireless,
  2927. IN BYTE* pConnectionDataIn,
  2928. IN DWORD dwSizeOfConnectionDataIn,
  2929. OUT PEAPMSCHAPv2_CONN_PROPERTIES* ppConnProp
  2930. )
  2931. {
  2932. DWORD dwErr = NO_ERROR;
  2933. PEAPMSCHAPv2_CONN_PROPERTIES pConnProp = NULL;
  2934. TRACE("ReadConnectionData");
  2935. RTASSERT(NULL != ppConnProp);
  2936. if ( dwSizeOfConnectionDataIn < sizeof(EAPMSCHAPv2_CONN_PROPERTIES) )
  2937. {
  2938. pConnProp = LocalAlloc(LPTR, sizeof(EAPMSCHAPv2_CONN_PROPERTIES));
  2939. if (NULL == pConnProp)
  2940. {
  2941. dwErr = GetLastError();
  2942. TRACE1("LocalAlloc failed and returned %d", dwErr);
  2943. goto LDone;
  2944. }
  2945. //This is a new structure
  2946. pConnProp->dwVersion = 1;
  2947. if ( fWireless )
  2948. {
  2949. //Set the use winlogon default flag
  2950. pConnProp->fFlags = EAPMSCHAPv2_FLAG_USE_WINLOGON_CREDS;
  2951. }
  2952. }
  2953. else
  2954. {
  2955. RTASSERT(NULL != pConnectionDataIn);
  2956. //
  2957. //Check to see if this is a version 0 structure
  2958. //If it is a version 0 structure then we migrate it to version1
  2959. //
  2960. pConnProp = LocalAlloc(LPTR, dwSizeOfConnectionDataIn);
  2961. if (NULL == pConnProp)
  2962. {
  2963. dwErr = GetLastError();
  2964. TRACE1("LocalAlloc failed and returned %d", dwErr);
  2965. goto LDone;
  2966. }
  2967. // If the user has mucked with the phonebook, we mustn't be affected.
  2968. // The size must be correct.
  2969. CopyMemory(pConnProp, pConnectionDataIn, dwSizeOfConnectionDataIn);
  2970. }
  2971. *ppConnProp = pConnProp;
  2972. pConnProp = NULL;
  2973. LDone:
  2974. LocalFree(pConnProp);
  2975. return(dwErr);
  2976. }
  2977. DWORD
  2978. AllocateUserDataWithEncPwd ( EAPMSCHAPv2WB * pEapwb, DATA_BLOB * pDBPassword )
  2979. {
  2980. DWORD dwRetCode = NO_ERROR;
  2981. PEAPMSCHAPv2_USER_PROPERTIES pUserProp = NULL;
  2982. TRACE("AllocateUserDataWithEncPwd");
  2983. pUserProp = LocalAlloc ( LPTR, sizeof( EAPMSCHAPv2_USER_PROPERTIES) + pDBPassword->cbData - 1 );
  2984. if ( NULL == pUserProp )
  2985. {
  2986. TRACE("LocalAlloc failed");
  2987. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  2988. goto LDone;
  2989. }
  2990. //
  2991. // Set the fields here
  2992. //
  2993. pUserProp->dwVersion = pEapwb->pUserProp->dwVersion;
  2994. pUserProp->fFlags = pEapwb->pUserProp->fFlags;
  2995. pUserProp->dwMaxRetries = pEapwb->pUserProp->dwMaxRetries;
  2996. strncpy ( pUserProp->szUserName, pEapwb->pUserProp->szUserName, UNLEN );
  2997. strncpy ( pUserProp->szPassword, pEapwb->pUserProp->szPassword, PWLEN );
  2998. strncpy ( pUserProp->szDomain, pEapwb->pUserProp->szDomain, DNLEN );
  2999. pUserProp->cbEncPassword = pDBPassword->cbData;
  3000. CopyMemory (pUserProp->bEncPassword,
  3001. pDBPassword->pbData,
  3002. pDBPassword->cbData
  3003. );
  3004. LocalFree ( pEapwb->pUserProp );
  3005. pEapwb->pUserProp = pUserProp;
  3006. LDone:
  3007. return dwRetCode;
  3008. }
  3009. DWORD
  3010. ReadUserData(
  3011. IN BYTE* pUserDataIn,
  3012. IN DWORD dwSizeOfUserDataIn,
  3013. OUT PEAPMSCHAPv2_USER_PROPERTIES* ppUserProp
  3014. )
  3015. {
  3016. DWORD dwRetCode = NO_ERROR;
  3017. PEAPMSCHAPv2_USER_PROPERTIES pUserProp = NULL;
  3018. DATA_BLOB DBPassword;
  3019. DWORD cbPassword = 0;
  3020. PBYTE pbPassword = NULL;
  3021. TRACE("ReadUserData");
  3022. RTASSERT(NULL != ppUserProp);
  3023. if (dwSizeOfUserDataIn < sizeof(EAPMSCHAPv2_USER_PROPERTIES_v1))
  3024. {
  3025. pUserProp = LocalAlloc(LPTR, sizeof(EAPMSCHAPv2_USER_PROPERTIES));
  3026. if (NULL == pUserProp)
  3027. {
  3028. dwRetCode = GetLastError();
  3029. TRACE1("LocalAlloc failed and returned %d", dwRetCode);
  3030. goto LDone;
  3031. }
  3032. pUserProp->dwVersion = 2;
  3033. //Set Defaults here
  3034. pUserProp->dwMaxRetries = 2;
  3035. pUserProp->fFlags |= EAPMSCHAPv2_FLAG_ALLOW_CHANGEPWD;
  3036. }
  3037. else
  3038. {
  3039. DWORD dwSizeToAllocate = dwSizeOfUserDataIn;
  3040. RTASSERT(NULL != pUserDataIn);
  3041. if ( dwSizeOfUserDataIn == sizeof( EAPMSCHAPv2_USER_PROPERTIES_v1 ) )
  3042. {
  3043. //This is the old struct so allocation new number of bytes.
  3044. dwSizeToAllocate = sizeof( EAPMSCHAPv2_USER_PROPERTIES );
  3045. }
  3046. pUserProp = LocalAlloc(LPTR, dwSizeToAllocate);
  3047. if (NULL == pUserProp)
  3048. {
  3049. dwRetCode = GetLastError();
  3050. TRACE1("LocalAlloc failed and returned %d", dwRetCode);
  3051. goto LDone;
  3052. }
  3053. CopyMemory(pUserProp, pUserDataIn, dwSizeOfUserDataIn);
  3054. pUserProp->dwVersion = 2;
  3055. if ( pUserProp->cbEncPassword )
  3056. {
  3057. // We have the encrypted password.
  3058. DBPassword.cbData = pUserProp->cbEncPassword;
  3059. DBPassword.pbData = pUserProp->bEncPassword;
  3060. DecodePassword( &(DBPassword),
  3061. &cbPassword,
  3062. &pbPassword
  3063. );
  3064. if ( cbPassword )
  3065. {
  3066. CopyMemory ( pUserProp->szPassword,
  3067. pbPassword,
  3068. cbPassword
  3069. );
  3070. RtlSecureZeroMemory(pbPassword, cbPassword);
  3071. LocalFree(pbPassword);
  3072. }
  3073. }
  3074. }
  3075. *ppUserProp = pUserProp;
  3076. pUserProp = NULL;
  3077. LDone:
  3078. LocalFree(pUserProp);
  3079. return dwRetCode;
  3080. }
  3081. DWORD
  3082. OpenEapEAPMschapv2RegistryKey(
  3083. IN LPSTR pszMachineName,
  3084. IN REGSAM samDesired,
  3085. OUT HKEY* phKeyEapMschapv2
  3086. )
  3087. {
  3088. HKEY hKeyLocalMachine = NULL;
  3089. BOOL fHKeyLocalMachineOpened = FALSE;
  3090. BOOL fHKeyEapMschapv2Opened = FALSE;
  3091. LONG lRet;
  3092. DWORD dwErr = NO_ERROR;
  3093. RTASSERT(NULL != phKeyEapMschapv2);
  3094. lRet = RegConnectRegistry(pszMachineName, HKEY_LOCAL_MACHINE,
  3095. &hKeyLocalMachine);
  3096. if (ERROR_SUCCESS != lRet)
  3097. {
  3098. dwErr = lRet;
  3099. TRACE2("RegConnectRegistry(%s) failed and returned %d",
  3100. pszMachineName ? pszMachineName : "NULL", dwErr);
  3101. goto LDone;
  3102. }
  3103. fHKeyLocalMachineOpened = TRUE;
  3104. lRet = RegOpenKeyEx(hKeyLocalMachine, EAPMSCHAPv2_KEY, 0, samDesired,
  3105. phKeyEapMschapv2);
  3106. if (ERROR_SUCCESS != lRet)
  3107. {
  3108. dwErr = lRet;
  3109. TRACE2("RegOpenKeyEx(%s) failed and returned %d",
  3110. EAPMSCHAPv2_KEY, dwErr);
  3111. goto LDone;
  3112. }
  3113. fHKeyEapMschapv2Opened = TRUE;
  3114. LDone:
  3115. if ( fHKeyEapMschapv2Opened
  3116. && (ERROR_SUCCESS != dwErr))
  3117. {
  3118. RegCloseKey(*phKeyEapMschapv2);
  3119. }
  3120. if (fHKeyLocalMachineOpened)
  3121. {
  3122. RegCloseKey(hKeyLocalMachine);
  3123. }
  3124. return(dwErr);
  3125. }
  3126. DWORD
  3127. ServerConfigDataIO(
  3128. IN BOOL fRead,
  3129. IN CHAR* pszMachineName,
  3130. IN OUT BYTE** ppData,
  3131. IN DWORD dwNumBytes
  3132. )
  3133. {
  3134. HKEY hKeyEapMschapv2;
  3135. PEAPMSCHAPv2_USER_PROPERTIES pUserProp;
  3136. BOOL fHKeyEapMsChapv2Opened = FALSE;
  3137. BYTE* pData = NULL;
  3138. DWORD dwSize = 0;
  3139. LONG lRet;
  3140. DWORD dwType;
  3141. DWORD dwErr = NO_ERROR;
  3142. RTASSERT(NULL != ppData);
  3143. dwErr = OpenEapEAPMschapv2RegistryKey(pszMachineName,
  3144. fRead ? KEY_READ : KEY_WRITE, &hKeyEapMschapv2);
  3145. if (ERROR_SUCCESS != dwErr)
  3146. {
  3147. goto LDone;
  3148. }
  3149. fHKeyEapMsChapv2Opened = TRUE;
  3150. if (fRead)
  3151. {
  3152. lRet = RegQueryValueEx(hKeyEapMschapv2, EAPMSCHAPv2_VAL_SERVER_CONFIG_DATA, NULL,
  3153. &dwType, NULL, &dwSize);
  3154. if ( (ERROR_SUCCESS != lRet)
  3155. || (REG_BINARY != dwType)
  3156. || (sizeof(EAPMSCHAPv2_USER_PROPERTIES) != dwSize))
  3157. {
  3158. pData = LocalAlloc(LPTR, sizeof(EAPMSCHAPv2_USER_PROPERTIES));
  3159. if (NULL == pData)
  3160. {
  3161. dwErr = GetLastError();
  3162. TRACE1("LocalAlloc failed and returned %d", dwErr);
  3163. goto LDone;
  3164. }
  3165. pUserProp = (EAPMSCHAPv2_USER_PROPERTIES*)pData;
  3166. pUserProp->dwVersion = 1;
  3167. }
  3168. else
  3169. {
  3170. pData = LocalAlloc(LPTR, dwSize);
  3171. if (NULL == pData)
  3172. {
  3173. dwErr = GetLastError();
  3174. TRACE1("LocalAlloc failed and returned %d", dwErr);
  3175. goto LDone;
  3176. }
  3177. lRet = RegQueryValueEx(hKeyEapMschapv2, EAPMSCHAPv2_VAL_SERVER_CONFIG_DATA,
  3178. NULL, &dwType, pData, &dwSize);
  3179. if (ERROR_SUCCESS != lRet)
  3180. {
  3181. dwErr = lRet;
  3182. TRACE2("RegQueryValueEx(%s) failed and returned %d",
  3183. EAPMSCHAPv2_VAL_SERVER_CONFIG_DATA, dwErr);
  3184. goto LDone;
  3185. }
  3186. }
  3187. pUserProp = (EAPMSCHAPv2_USER_PROPERTIES*)pData;
  3188. *ppData = pData;
  3189. pData = NULL;
  3190. }
  3191. else
  3192. {
  3193. lRet = RegSetValueEx(hKeyEapMschapv2, EAPMSCHAPv2_VAL_SERVER_CONFIG_DATA, 0,
  3194. REG_BINARY, *ppData, dwNumBytes);
  3195. if (ERROR_SUCCESS != lRet)
  3196. {
  3197. dwErr = lRet;
  3198. TRACE2("RegSetValueEx(%s) failed and returned %d",
  3199. EAPMSCHAPv2_VAL_SERVER_CONFIG_DATA, dwErr);
  3200. goto LDone;
  3201. }
  3202. }
  3203. LDone:
  3204. if (fHKeyEapMsChapv2Opened)
  3205. {
  3206. RegCloseKey(hKeyEapMschapv2);
  3207. }
  3208. LocalFree(pData);
  3209. return(dwErr);
  3210. }
  3211. DWORD
  3212. InvokeServerConfigUI (
  3213. HWND hWnd,
  3214. LPSTR pszMachineName,
  3215. BOOL fConfigDataInRegistry,
  3216. const BYTE* pConfigDataIn,
  3217. DWORD dwSizeofConfigDataIn,
  3218. BYTE** ppConfigDataOut,
  3219. DWORD* pdwSizeofConfigDataOut
  3220. )
  3221. {
  3222. DWORD dwRetCode = NO_ERROR;
  3223. INT_PTR nRet = 0;
  3224. EAPMSCHAPv2_SERVERCONFIG_DIALOG EapServerConfig;
  3225. BOOL fLocal = FALSE;
  3226. if (0 == *pszMachineName)
  3227. {
  3228. fLocal = TRUE;
  3229. }
  3230. if(fConfigDataInRegistry)
  3231. {
  3232. //Read the information from registry here
  3233. dwRetCode = ServerConfigDataIO(
  3234. TRUE /* fRead */,
  3235. fLocal ? NULL : pszMachineName,
  3236. (BYTE**)&(EapServerConfig.pUserProp), 0);
  3237. if (NO_ERROR != dwRetCode)
  3238. {
  3239. goto LDone;
  3240. }
  3241. }
  3242. else
  3243. {
  3244. if(dwSizeofConfigDataIn < sizeof(EAPMSCHAPv2_USER_PROPERTIES))
  3245. {
  3246. dwRetCode = ReadUserData(NULL,0,
  3247. &EapServerConfig.pUserProp);
  3248. }
  3249. else
  3250. {
  3251. EapServerConfig.pUserProp = LocalAlloc(LPTR, dwSizeofConfigDataIn);
  3252. if(NULL == EapServerConfig.pUserProp)
  3253. {
  3254. dwRetCode = E_OUTOFMEMORY;
  3255. goto LDone;
  3256. }
  3257. CopyMemory(EapServerConfig.pUserProp, pConfigDataIn,
  3258. dwSizeofConfigDataIn);
  3259. }
  3260. if(NO_ERROR != dwRetCode)
  3261. {
  3262. goto LDone;
  3263. }
  3264. }
  3265. //Show the server config UI here
  3266. nRet = DialogBoxParam(
  3267. GetHInstance(),
  3268. MAKEINTRESOURCE(IDD_DIALOG_SERVER_CONFIG),
  3269. hWnd,
  3270. ServerConfigDialogProc,
  3271. (LPARAM)&EapServerConfig);
  3272. if (-1 == nRet)
  3273. {
  3274. dwRetCode = GetLastError();
  3275. goto LDone;
  3276. }
  3277. else if (IDOK != nRet)
  3278. {
  3279. dwRetCode = ERROR_CANCELLED;
  3280. goto LDone;
  3281. }
  3282. if(fConfigDataInRegistry)
  3283. {
  3284. //Read the information from registry here
  3285. dwRetCode = ServerConfigDataIO(
  3286. FALSE/* fRead */,
  3287. fLocal ? NULL : pszMachineName,
  3288. (BYTE**)&(EapServerConfig.pUserProp),
  3289. sizeof(EAPMSCHAPv2_USER_PROPERTIES));
  3290. LocalFree(EapServerConfig.pUserProp);
  3291. }
  3292. else
  3293. {
  3294. *ppConfigDataOut = (BYTE *) EapServerConfig.pUserProp;
  3295. *pdwSizeofConfigDataOut = sizeof(EAPMSCHAPv2_USER_PROPERTIES);
  3296. }
  3297. LDone:
  3298. return dwRetCode;
  3299. }
  3300. BOOL FFormatMachineIdentity1 ( LPWSTR lpszMachineNameRaw, LPWSTR * lppszMachineNameFormatted )
  3301. {
  3302. BOOL fRetVal = FALSE;
  3303. LPWSTR lpwszPrefix = L"host/";
  3304. RTASSERT(NULL != lpszMachineNameRaw );
  3305. RTASSERT(NULL != lppszMachineNameFormatted );
  3306. //
  3307. // Prepend host/ to the UPN name
  3308. //
  3309. *lppszMachineNameFormatted =
  3310. (LPWSTR)LocalAlloc ( LPTR, ( wcslen ( lpszMachineNameRaw ) + wcslen ( lpwszPrefix ) + 2 ) * sizeof(WCHAR) );
  3311. if ( NULL == *lppszMachineNameFormatted )
  3312. {
  3313. goto done;
  3314. }
  3315. wcscpy( *lppszMachineNameFormatted, lpwszPrefix );
  3316. wcscat ( *lppszMachineNameFormatted, lpszMachineNameRaw );
  3317. fRetVal = TRUE;
  3318. done:
  3319. return fRetVal;
  3320. }
  3321. BOOL FFormatMachineIdentity ( LPWSTR lpszMachineNameRaw, LPWSTR * lppszMachineNameFormatted )
  3322. {
  3323. BOOL fRetVal = TRUE;
  3324. LPWSTR s1 = lpszMachineNameRaw;
  3325. LPWSTR s2 = NULL;
  3326. RTASSERT(NULL != lpszMachineNameRaw );
  3327. RTASSERT(NULL != lppszMachineNameFormatted );
  3328. //Need to add 2 more chars. One for NULL and other for $ sign
  3329. *lppszMachineNameFormatted = (LPWSTR )LocalAlloc ( LPTR, (wcslen(lpszMachineNameRaw) + 2)* sizeof(WCHAR) );
  3330. if ( NULL == *lppszMachineNameFormatted )
  3331. {
  3332. return FALSE;
  3333. }
  3334. //find the first "." and that is the identity of the machine.
  3335. //the second "." is the domain.
  3336. //check to see if there at least 2 dots. If not the raw string is
  3337. //the output string
  3338. while ( *s1 )
  3339. {
  3340. if ( *s1 == '.' )
  3341. {
  3342. if ( !s2 ) //First dot
  3343. s2 = s1;
  3344. else //second dot
  3345. break;
  3346. }
  3347. s1++;
  3348. }
  3349. //can perform several additional checks here
  3350. if ( *s1 != '.' ) //there are no 2 dots so raw = formatted
  3351. {
  3352. wcscpy ( *lppszMachineNameFormatted, lpszMachineNameRaw );
  3353. goto done;
  3354. }
  3355. if ( s1-s2 < 2 )
  3356. {
  3357. wcscpy ( *lppszMachineNameFormatted, lpszMachineNameRaw );
  3358. goto done;
  3359. }
  3360. memcpy ( *lppszMachineNameFormatted, s2+1, ( s1-s2-1) * sizeof(WCHAR));
  3361. memcpy ( (*lppszMachineNameFormatted) + (s1-s2-1) , L"\\", sizeof(WCHAR));
  3362. wcsncpy ( (*lppszMachineNameFormatted) + (s1-s2), lpszMachineNameRaw, s2-lpszMachineNameRaw );
  3363. done:
  3364. //Append the $ sign no matter what...
  3365. wcscat ( *lppszMachineNameFormatted, L"$" );
  3366. //upper case the identity
  3367. _wcsupr ( *lppszMachineNameFormatted );
  3368. return fRetVal;
  3369. }
  3370. DWORD
  3371. GetLocalMachineName (
  3372. OUT WCHAR ** ppLocalMachineName
  3373. )
  3374. {
  3375. DWORD dwRetCode = NO_ERROR;
  3376. WCHAR * pLocalMachineName = NULL;
  3377. DWORD dwLocalMachineNameLen = 0;
  3378. if ( !GetComputerNameExW ( ComputerNameDnsFullyQualified,
  3379. pLocalMachineName,
  3380. &dwLocalMachineNameLen
  3381. )
  3382. )
  3383. {
  3384. dwRetCode = GetLastError();
  3385. if ( ERROR_MORE_DATA != dwRetCode )
  3386. goto LDone;
  3387. dwRetCode = NO_ERROR;
  3388. }
  3389. pLocalMachineName = (WCHAR *)LocalAlloc( LPTR, (dwLocalMachineNameLen * sizeof(WCHAR)) + sizeof(WCHAR) );
  3390. if ( NULL == pLocalMachineName )
  3391. {
  3392. dwRetCode = GetLastError();
  3393. goto LDone;
  3394. }
  3395. if ( !GetComputerNameExW ( ComputerNameDnsFullyQualified,
  3396. pLocalMachineName,
  3397. &dwLocalMachineNameLen
  3398. )
  3399. )
  3400. {
  3401. dwRetCode = GetLastError();
  3402. goto LDone;
  3403. }
  3404. *ppLocalMachineName = pLocalMachineName;
  3405. pLocalMachineName = NULL;
  3406. LDone:
  3407. LocalFree(pLocalMachineName);
  3408. return dwRetCode;
  3409. }
  3410. DWORD
  3411. RasEapGetIdentity(
  3412. IN DWORD dwEapTypeId,
  3413. IN HWND hwndParent,
  3414. IN DWORD dwFlags,
  3415. IN const WCHAR* pwszPhonebook,
  3416. IN const WCHAR* pwszEntry,
  3417. IN BYTE* pConnectionDataIn,
  3418. IN DWORD dwSizeOfConnectionDataIn,
  3419. IN BYTE* pUserDataIn,
  3420. IN DWORD dwSizeOfUserDataIn,
  3421. OUT BYTE** ppUserDataOut,
  3422. OUT DWORD* pdwSizeOfUserDataOut,
  3423. OUT WCHAR** ppwszIdentityOut
  3424. )
  3425. {
  3426. DWORD dwRetCode = NO_ERROR;
  3427. PEAPMSCHAPv2_USER_PROPERTIES pUserProp = NULL;
  3428. PEAPMSCHAPv2_CONN_PROPERTIES pConnProp = NULL;
  3429. EAPMSCHAPv2_LOGON_DIALOG EapMsChapv2LogonDialog;
  3430. INT_PTR nRet = 0;
  3431. LPWSTR lpwszLocalMachineName = NULL;
  3432. RASCREDENTIALSW RasCredentials;
  3433. CHAR szOldPwd[PWLEN+1]= {0};
  3434. BOOL fShowUI = TRUE;
  3435. TRACE("RasEapGetIdentity");
  3436. RTASSERT(NULL != ppUserDataOut);
  3437. RTASSERT(NULL != pdwSizeOfUserDataOut);
  3438. *ppUserDataOut = NULL;
  3439. ZeroMemory( &EapMsChapv2LogonDialog,
  3440. sizeof(EapMsChapv2LogonDialog) );
  3441. //
  3442. // Read User data first
  3443. //
  3444. dwRetCode = ReadUserData ( pUserDataIn,
  3445. dwSizeOfUserDataIn,
  3446. &pUserProp
  3447. );
  3448. if ( NO_ERROR != dwRetCode )
  3449. {
  3450. goto LDone;
  3451. }
  3452. //
  3453. // ReadConnectionData and see if we have been setup to use winlogon
  3454. // credentials. If so, just call to get user id and send back
  3455. // information.
  3456. //
  3457. dwRetCode = ReadConnectionData ( ( dwFlags & RAS_EAP_FLAG_8021X_AUTH ),
  3458. pConnectionDataIn,
  3459. dwSizeOfConnectionDataIn,
  3460. &pConnProp
  3461. );
  3462. if ( NO_ERROR != dwRetCode )
  3463. {
  3464. TRACE("Error reading connection properties");
  3465. goto LDone;
  3466. }
  3467. //MAchine Auth
  3468. if ( (dwFlags & RAS_EAP_FLAG_MACHINE_AUTH) )
  3469. {
  3470. //Send the identity back as domain\machine$
  3471. dwRetCode = GetLocalMachineName(&lpwszLocalMachineName );
  3472. if ( NO_ERROR != dwRetCode )
  3473. {
  3474. TRACE("Failed to get computer name");
  3475. goto LDone;
  3476. }
  3477. if ( ! FFormatMachineIdentity1 ( lpwszLocalMachineName,
  3478. ppwszIdentityOut )
  3479. )
  3480. {
  3481. TRACE("Failed to format machine identity");
  3482. }
  3483. *ppUserDataOut = (PBYTE)pUserProp;
  3484. *pdwSizeOfUserDataOut = sizeof(EAPMSCHAPv2_USER_PROPERTIES);
  3485. pUserProp = NULL;
  3486. goto LDone;
  3487. }
  3488. if ( !(pConnProp->fFlags & EAPMSCHAPv2_FLAG_USE_WINLOGON_CREDS) &&
  3489. dwFlags & RAS_EAP_FLAG_NON_INTERACTIVE
  3490. )
  3491. {
  3492. if ( (dwFlags & RAS_EAP_FLAG_8021X_AUTH ) )
  3493. {
  3494. // Wireless case - If there is no username or password cached
  3495. // we need to show the interactive UI
  3496. if( !pUserProp->szUserName[0] ||
  3497. !pUserProp->cbEncPassword
  3498. )
  3499. {
  3500. TRACE("Passed non interactive mode when interactive mode expected.");
  3501. dwRetCode = ERROR_INTERACTIVE_MODE;
  3502. goto LDone;
  3503. }
  3504. }
  3505. else
  3506. {
  3507. //VPN case
  3508. dwRetCode = ERROR_INTERACTIVE_MODE;
  3509. goto LDone;
  3510. }
  3511. }
  3512. //User Auth
  3513. if ( pConnProp->fFlags & EAPMSCHAPv2_FLAG_USE_WINLOGON_CREDS )
  3514. {
  3515. WCHAR wszUserName[UNLEN + DNLEN + 2];
  3516. DWORD dwNumChars = UNLEN + DNLEN;
  3517. if ( dwFlags & RAS_EAP_FLAG_LOGON)
  3518. {
  3519. //
  3520. // This is not allowed.
  3521. //
  3522. dwRetCode = ERROR_INVALID_MSCHAPV2_CONFIG;
  3523. goto LDone;
  3524. }
  3525. //Get currently logged on user name for identity
  3526. if (!GetUserNameExW(NameSamCompatible, wszUserName, &dwNumChars))
  3527. {
  3528. dwRetCode = GetLastError();
  3529. TRACE1("GetUserNameExW failed and returned %d", dwRetCode );
  3530. goto LDone;
  3531. }
  3532. *ppwszIdentityOut = (WCHAR *)LocalAlloc(LPTR,
  3533. dwNumChars * sizeof(WCHAR) + sizeof(WCHAR) );
  3534. if ( NULL == *ppwszIdentityOut )
  3535. {
  3536. TRACE("Failed to allocate memory for identity");
  3537. dwRetCode = ERROR_OUTOFMEMORY;
  3538. goto LDone;
  3539. }
  3540. CopyMemory(*ppwszIdentityOut, wszUserName, dwNumChars * sizeof(WCHAR) );
  3541. //All other fields in user prop remains blank
  3542. }
  3543. else
  3544. {
  3545. EapMsChapv2LogonDialog.pUserProp = pUserProp;
  3546. //
  3547. // Show the logon dialog for credentials
  3548. //
  3549. // if Machine Auth flag is passed in, we dont show
  3550. // the logon dialog. If Get Credentials from winlogon
  3551. // is passed in dont show logon dialog. else show
  3552. // logon dialog.
  3553. //
  3554. // Check to see if we have the password saved in LSA
  3555. // It should not matter if it is not.
  3556. if ( !(dwFlags & RAS_EAP_FLAG_LOGON ) )
  3557. {
  3558. #if 0
  3559. ZeroMemory(&RasCredentials, sizeof(RasCredentials));
  3560. RasCredentials.dwSize = sizeof(RasCredentials);
  3561. RasCredentials.dwMask = RASCM_Password;
  3562. dwRetCode = RasGetCredentialsW(pwszPhonebook, pwszEntry,
  3563. &RasCredentials);
  3564. if ( (dwRetCode == NO_ERROR)
  3565. && (RasCredentials.dwMask & RASCM_Password))
  3566. {
  3567. //Set the password
  3568. WideCharToMultiByte(
  3569. CP_ACP,
  3570. 0,
  3571. RasCredentials.szPassword,
  3572. -1,
  3573. pUserProp->szPassword,
  3574. PWLEN + 1,
  3575. NULL,
  3576. NULL );
  3577. strncpy (szOldPwd, pUserProp->szPassword, PWLEN );
  3578. }
  3579. dwRetCode = NO_ERROR;
  3580. #endif
  3581. }
  3582. else
  3583. {
  3584. EapMsChapv2LogonDialog.pUserProp->fFlags |= EAPMSCHAPv2_FLAG_CALLED_WITHIN_WINLOGON;
  3585. if ( pUserProp->fFlags & EAPMSCHAPv2_FLAG_SAVE_UID_PWD )
  3586. pUserProp->fFlags &= ~EAPMSCHAPv2_FLAG_SAVE_UID_PWD;
  3587. }
  3588. if ( dwFlags & RAS_EAP_FLAG_8021X_AUTH )
  3589. {
  3590. EapMsChapv2LogonDialog.pUserProp->fFlags |= EAPMSCHAPv2_FLAG_8021x;
  3591. }
  3592. // Check to see if our existing user props are cached? If so,
  3593. // there is no need to show the dialog
  3594. if ( (dwFlags & RAS_EAP_FLAG_8021X_AUTH ) &&
  3595. pUserProp->szUserName[0] &&
  3596. pUserProp->cbEncPassword
  3597. )
  3598. {
  3599. fShowUI = FALSE;
  3600. }
  3601. if ( fShowUI )
  3602. {
  3603. //Either we have an empty user name
  3604. //or password
  3605. nRet = DialogBoxParam(
  3606. GetHInstance(),
  3607. MAKEINTRESOURCE(IDD_DIALOG_LOGON),
  3608. hwndParent,
  3609. LogonDialogProc,
  3610. (LPARAM)&EapMsChapv2LogonDialog);
  3611. if (-1 == nRet)
  3612. {
  3613. dwRetCode = GetLastError();
  3614. goto LDone;
  3615. }
  3616. else if (IDOK != nRet)
  3617. {
  3618. dwRetCode = ERROR_CANCELLED;
  3619. goto LDone;
  3620. }
  3621. }
  3622. if ( !(dwFlags & RAS_EAP_FLAG_ROUTER ) )
  3623. {
  3624. //
  3625. // Setup the identity parameter here
  3626. //
  3627. dwRetCode = GetIdentityFromUserName ( pUserProp->szUserName,
  3628. pUserProp->szDomain,
  3629. ppwszIdentityOut
  3630. );
  3631. if ( NO_ERROR != dwRetCode )
  3632. {
  3633. goto LDone;
  3634. }
  3635. }
  3636. }
  3637. #if 0
  3638. if ( !(dwFlags & RAS_EAP_FLAG_LOGON ) )
  3639. {
  3640. ZeroMemory(&RasCredentials, sizeof(RasCredentials));
  3641. RasCredentials.dwSize = sizeof(RasCredentials);
  3642. RasCredentials.dwMask = RASCM_Password;
  3643. if ( pUserProp->fFlags & EAPMSCHAPv2_FLAG_SAVE_UID_PWD )
  3644. {
  3645. //
  3646. // Check to see if the new password is different from the old one
  3647. //
  3648. if ( strcmp ( szOldPwd, pUserProp->szPassword ) )
  3649. {
  3650. //
  3651. // There is a new password for us to save.
  3652. //
  3653. MultiByteToWideChar( CP_ACP,
  3654. 0,
  3655. pUserProp->szPassword,
  3656. -1,
  3657. RasCredentials.szPassword,
  3658. sizeof(RasCredentials.szPassword)/sizeof(WCHAR) );
  3659. RasSetCredentialsW(pwszPhonebook, pwszEntry, &RasCredentials,
  3660. FALSE /* fClearCredentials */);
  3661. }
  3662. }
  3663. else
  3664. {
  3665. RasSetCredentialsW(pwszPhonebook, pwszEntry, &RasCredentials,
  3666. TRUE /* fClearCredentials */);
  3667. }
  3668. }
  3669. #endif
  3670. *ppUserDataOut = (PBYTE)pUserProp;
  3671. *pdwSizeOfUserDataOut = sizeof(EAPMSCHAPv2_USER_PROPERTIES);
  3672. pUserProp = NULL;
  3673. LDone:
  3674. if ( lpwszLocalMachineName )
  3675. LocalFree(lpwszLocalMachineName);
  3676. LocalFree(pUserProp);
  3677. return dwRetCode;
  3678. }
  3679. DWORD
  3680. RasEapInvokeConfigUI(
  3681. IN DWORD dwEapTypeId,
  3682. IN HWND hwndParent,
  3683. IN DWORD dwFlags,
  3684. IN BYTE* pConnectionDataIn,
  3685. IN DWORD dwSizeOfConnectionDataIn,
  3686. OUT BYTE** ppConnectionDataOut,
  3687. OUT DWORD* pdwSizeOfConnectionDataOut
  3688. )
  3689. {
  3690. DWORD dwRetCode = NO_ERROR;
  3691. EAPMSCHAPv2_CLIENTCONFIG_DIALOG ClientConfigDialog;
  3692. INT_PTR nRet;
  3693. TRACE("RasEapInvokeConfigUI");
  3694. *ppConnectionDataOut = NULL;
  3695. *pdwSizeOfConnectionDataOut = 0;
  3696. //
  3697. // In case of Router there is nothing to configure
  3698. //
  3699. if ( dwFlags & RAS_EAP_FLAG_ROUTER )
  3700. {
  3701. CHAR szMessage[512] = {0};
  3702. CHAR szHeader[64] = {0};
  3703. //
  3704. // Load resource from res file
  3705. //
  3706. LoadString( GetHInstance(),
  3707. IDS_NO_ROUTER_CONFIG,
  3708. szMessage,
  3709. sizeof(szMessage)-1
  3710. );
  3711. LoadString( GetHInstance(),
  3712. IDS_MESSAGE_HEADER,
  3713. szHeader,
  3714. sizeof(szHeader)-1
  3715. );
  3716. MessageBox (hwndParent,
  3717. szMessage,
  3718. szHeader,
  3719. MB_OK
  3720. );
  3721. goto LDone;
  3722. }
  3723. //
  3724. // If we are a client, read connection data and call
  3725. // the dialog to do the config.
  3726. //
  3727. dwRetCode = ReadConnectionData ( ( dwFlags & RAS_EAP_FLAG_8021X_AUTH ),
  3728. pConnectionDataIn,
  3729. dwSizeOfConnectionDataIn,
  3730. &(ClientConfigDialog.pConnProp)
  3731. );
  3732. if ( NO_ERROR != dwRetCode )
  3733. {
  3734. TRACE("Error reading conn prop");
  3735. goto LDone;
  3736. }
  3737. //
  3738. // Call in the dialog to show connection props
  3739. //
  3740. nRet = DialogBoxParam(
  3741. GetHInstance(),
  3742. MAKEINTRESOURCE(IDD_DIALOG_CLEINT_CONFIG),
  3743. hwndParent,
  3744. ClientConfigDialogProc,
  3745. (LPARAM)&ClientConfigDialog);
  3746. if (-1 == nRet)
  3747. {
  3748. dwRetCode = GetLastError();
  3749. goto LDone;
  3750. }
  3751. else if (IDOK != nRet)
  3752. {
  3753. dwRetCode = ERROR_CANCELLED;
  3754. goto LDone;
  3755. }
  3756. //
  3757. // Setup the out parameters in the ppDataFromInteractiveUI
  3758. // so that we can send the new uid/pwd back
  3759. //
  3760. * ppConnectionDataOut = LocalAlloc( LPTR, sizeof(EAPMSCHAPv2_CONN_PROPERTIES) );
  3761. if ( NULL == * ppConnectionDataOut )
  3762. {
  3763. TRACE("Error allocating memory for pConnectionDataOut");
  3764. dwRetCode = ERROR_OUTOFMEMORY;
  3765. goto LDone;
  3766. }
  3767. CopyMemory( *ppConnectionDataOut,
  3768. ClientConfigDialog.pConnProp,
  3769. sizeof(EAPMSCHAPv2_CONN_PROPERTIES)
  3770. );
  3771. * pdwSizeOfConnectionDataOut = sizeof(EAPMSCHAPv2_CONN_PROPERTIES);
  3772. LDone:
  3773. LocalFree(ClientConfigDialog.pConnProp);
  3774. return dwRetCode;
  3775. }
  3776. DWORD
  3777. RasEapFreeMemory(
  3778. IN BYTE* pMemory
  3779. )
  3780. {
  3781. LocalFree(pMemory);
  3782. return(NO_ERROR);
  3783. }
  3784. DWORD
  3785. RasEapInvokeInteractiveUI(
  3786. IN DWORD dwEapTypeId,
  3787. IN HWND hWndParent,
  3788. IN BYTE* pUIContextData,
  3789. IN DWORD dwSizeofUIContextData,
  3790. OUT BYTE** ppDataFromInteractiveUI,
  3791. OUT DWORD* pdwSizeOfDataFromInteractiveUI
  3792. )
  3793. {
  3794. DWORD dwRetCode = NO_ERROR;
  3795. PEAPMSCHAPv2_USER_PROPERTIES pUserProp = NULL;
  3796. PEAPMSCHAPv2_INTERACTIVE_UI pEapMschapv2InteractiveUI = NULL;
  3797. EAPMSCHAPv2_CHANGEPWD_DIALOG EapMsChapv2ChangePwdDialog;
  3798. EAPMSCHAPv2_LOGON_DIALOG EapMsChapv2LogonDialog;
  3799. INT_PTR nRet = 0;
  3800. TRACE("RasEapInvokeInteractiveUI");
  3801. RTASSERT(NULL != pUIContextData);
  3802. RTASSERT(dwSizeofUIContextData == sizeof(EAPMSCHAPv2_INTERACTIVE_UI));
  3803. * ppDataFromInteractiveUI = NULL;
  3804. * pdwSizeOfDataFromInteractiveUI = 0;
  3805. pEapMschapv2InteractiveUI = (PEAPMSCHAPv2_INTERACTIVE_UI)pUIContextData;
  3806. if ( pEapMschapv2InteractiveUI->fFlags & EAPMSCHAPv2_INTERACTIVE_UI_FLAG_RETRY )
  3807. {
  3808. ZeroMemory( &EapMsChapv2LogonDialog,
  3809. sizeof(EapMsChapv2LogonDialog) );
  3810. EapMsChapv2LogonDialog.pUserProp =
  3811. &(pEapMschapv2InteractiveUI->UserProp);
  3812. //
  3813. // Show the retry dialog for credentials
  3814. //
  3815. nRet = DialogBoxParam(
  3816. GetHInstance(),
  3817. MAKEINTRESOURCE(IDD_DIALOG_RETRY_LOGON),
  3818. hWndParent,
  3819. RetryDialogProc,
  3820. (LPARAM)&EapMsChapv2LogonDialog);
  3821. if (-1 == nRet)
  3822. {
  3823. dwRetCode = GetLastError();
  3824. goto LDone;
  3825. }
  3826. else if (IDOK != nRet)
  3827. {
  3828. dwRetCode = ERROR_CANCELLED;
  3829. goto LDone;
  3830. }
  3831. //
  3832. // Setup the out parameters in the ppDataFromInteractiveUI
  3833. // so that we can send the new uid/pwd back
  3834. //
  3835. * ppDataFromInteractiveUI = LocalAlloc( LPTR, sizeof(EAPMSCHAPv2_INTERACTIVE_UI) );
  3836. if ( NULL == * ppDataFromInteractiveUI )
  3837. {
  3838. TRACE("Error allocating memory for pDataFromInteractiveUI");
  3839. dwRetCode = ERROR_OUTOFMEMORY;
  3840. goto LDone;
  3841. }
  3842. CopyMemory ( *ppDataFromInteractiveUI,
  3843. pEapMschapv2InteractiveUI,
  3844. sizeof( EAPMSCHAPv2_INTERACTIVE_UI )
  3845. );
  3846. pEapMschapv2InteractiveUI = (PEAPMSCHAPv2_INTERACTIVE_UI)*ppDataFromInteractiveUI;
  3847. CopyMemory( &(pEapMschapv2InteractiveUI->UserProp),
  3848. EapMsChapv2LogonDialog.pUserProp,
  3849. sizeof(EAPMSCHAPv2_USER_PROPERTIES)
  3850. );
  3851. * pdwSizeOfDataFromInteractiveUI = sizeof(EAPMSCHAPv2_INTERACTIVE_UI);
  3852. }
  3853. else if ( ( pEapMschapv2InteractiveUI->fFlags & EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD )||
  3854. ( pEapMschapv2InteractiveUI->fFlags & EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD_WINLOGON )
  3855. )
  3856. {
  3857. //
  3858. // Change password
  3859. //
  3860. ZeroMemory( &EapMsChapv2ChangePwdDialog,
  3861. sizeof(EapMsChapv2ChangePwdDialog)
  3862. );
  3863. EapMsChapv2ChangePwdDialog.pInteractiveUIData = (PEAPMSCHAPv2_INTERACTIVE_UI)pUIContextData;
  3864. //
  3865. // Show the retry dialog for credentials
  3866. //
  3867. if ( pEapMschapv2InteractiveUI->fFlags & EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD )
  3868. {
  3869. nRet = DialogBoxParam(
  3870. GetHInstance(),
  3871. MAKEINTRESOURCE(IDD_DIALOG_CHANGE_PASSWORD),
  3872. hWndParent,
  3873. ChangePasswordDialogProc,
  3874. (LPARAM)&EapMsChapv2ChangePwdDialog);
  3875. }
  3876. else
  3877. {
  3878. //
  3879. // We need to get this dialog from rasdlg because
  3880. // in XPSP1 no more resources can be added.
  3881. //
  3882. nRet = DialogBoxParam(
  3883. GetRasDlgDLLHInstance(),
  3884. MAKEINTRESOURCE(DID_CP_ChangePassword2),
  3885. hWndParent,
  3886. ChangePasswordDialogProc,
  3887. (LPARAM)&EapMsChapv2ChangePwdDialog);
  3888. }
  3889. if (-1 == nRet)
  3890. {
  3891. dwRetCode = GetLastError();
  3892. goto LDone;
  3893. }
  3894. else if (IDOK != nRet)
  3895. {
  3896. dwRetCode = ERROR_CANCELLED;
  3897. goto LDone;
  3898. }
  3899. //
  3900. // Setup the out parameters in the ppDataFromInteractiveUI
  3901. // so that we can send the new uid/pwd back
  3902. //
  3903. * ppDataFromInteractiveUI = LocalAlloc( LPTR, sizeof(EAPMSCHAPv2_INTERACTIVE_UI) );
  3904. if ( NULL == * ppDataFromInteractiveUI )
  3905. {
  3906. TRACE("Error allocating memory for pDataFromInteractiveUI");
  3907. dwRetCode = ERROR_OUTOFMEMORY;
  3908. goto LDone;
  3909. }
  3910. CopyMemory( *ppDataFromInteractiveUI,
  3911. EapMsChapv2ChangePwdDialog.pInteractiveUIData,
  3912. sizeof(EAPMSCHAPv2_INTERACTIVE_UI)
  3913. );
  3914. * pdwSizeOfDataFromInteractiveUI = sizeof(EAPMSCHAPv2_INTERACTIVE_UI);
  3915. }
  3916. LDone:
  3917. return dwRetCode;
  3918. }
  3919. DWORD
  3920. EapMSCHAPv2Initialize(
  3921. IN BOOL fInitialize
  3922. )
  3923. {
  3924. static DWORD dwRefCount = 0;
  3925. DWORD dwRetCode = NO_ERROR;
  3926. if ( fInitialize )
  3927. {
  3928. //Initialize
  3929. if (0 == dwRefCount)
  3930. {
  3931. dwRetCode = IASLogonInitialize();
  3932. }
  3933. dwRefCount ++;
  3934. }
  3935. else
  3936. {
  3937. dwRefCount --;
  3938. if (0 == dwRefCount)
  3939. {
  3940. IASLogonShutdown();
  3941. }
  3942. }
  3943. dwRetCode = ChapInit( fInitialize );
  3944. return dwRetCode;
  3945. }
  3946. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  3947. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  3948. // All the dialogs required for EAPMSCHAPv2 go here. Move into it's own file later.
  3949. ////////////////////////////////////////////////////////////////////////////////////////////////////////
  3950. static const DWORD g_adwHelp[] =
  3951. {
  3952. 0, 0
  3953. };
  3954. VOID
  3955. ContextHelp(
  3956. IN const DWORD* padwMap,
  3957. IN HWND hWndDlg,
  3958. IN UINT unMsg,
  3959. IN WPARAM wParam,
  3960. IN LPARAM lParam
  3961. )
  3962. {
  3963. return;
  3964. }
  3965. BOOL
  3966. LogonInitDialog(
  3967. IN HWND hWnd,
  3968. IN LPARAM lParam
  3969. )
  3970. {
  3971. PEAPMSCHAPv2_LOGON_DIALOG pMSCHAPv2LogonDialog;
  3972. PEAPMSCHAPv2_USER_PROPERTIES pUserProp;
  3973. SetWindowLongPtr(hWnd, DWLP_USER, lParam);
  3974. pMSCHAPv2LogonDialog = (PEAPMSCHAPv2_LOGON_DIALOG)lParam;
  3975. pUserProp = pMSCHAPv2LogonDialog->pUserProp;
  3976. pMSCHAPv2LogonDialog->hWndUserName =
  3977. GetDlgItem(hWnd, IDC_EDIT_USERNAME);
  3978. pMSCHAPv2LogonDialog->hWndPassword =
  3979. GetDlgItem(hWnd, IDC_EDIT_PASSWORD);
  3980. pMSCHAPv2LogonDialog->hWndDomain =
  3981. GetDlgItem(hWnd, IDC_EDIT_DOMAIN);
  3982. pMSCHAPv2LogonDialog->hWndSavePassword =
  3983. GetDlgItem(hWnd, IDC_CHECK_SAVE_UID_PWD);
  3984. //Setup upper limit on text boxes
  3985. SendMessage(pMSCHAPv2LogonDialog->hWndUserName,
  3986. EM_LIMITTEXT,
  3987. UNLEN,
  3988. 0L
  3989. );
  3990. SendMessage(pMSCHAPv2LogonDialog->hWndPassword,
  3991. EM_LIMITTEXT,
  3992. PWLEN,
  3993. 0L
  3994. );
  3995. SendMessage(pMSCHAPv2LogonDialog->hWndDomain,
  3996. EM_LIMITTEXT,
  3997. DNLEN,
  3998. 0L
  3999. );
  4000. if ( pUserProp->fFlags & EAPMSCHAPv2_FLAG_CALLED_WITHIN_WINLOGON )
  4001. {
  4002. EnableWindow ( pMSCHAPv2LogonDialog->hWndSavePassword, FALSE );
  4003. }
  4004. else if ( pUserProp->fFlags & EAPMSCHAPv2_FLAG_8021x )
  4005. {
  4006. ShowWindow ( pMSCHAPv2LogonDialog->hWndSavePassword, SW_HIDE );
  4007. }
  4008. else
  4009. {
  4010. if ( pUserProp->fFlags & EAPMSCHAPv2_FLAG_SAVE_UID_PWD )
  4011. {
  4012. CheckDlgButton(hWnd, IDC_CHECK_SAVE_UID_PWD, BST_CHECKED);
  4013. }
  4014. }
  4015. if ( pUserProp->szUserName[0] )
  4016. {
  4017. SetWindowText( pMSCHAPv2LogonDialog->hWndUserName,
  4018. pUserProp->szUserName
  4019. );
  4020. }
  4021. if ( pUserProp->szPassword[0] )
  4022. {
  4023. SetWindowText( pMSCHAPv2LogonDialog->hWndPassword,
  4024. pUserProp->szPassword
  4025. );
  4026. }
  4027. if ( pUserProp->szDomain[0] )
  4028. {
  4029. SetWindowText( pMSCHAPv2LogonDialog->hWndDomain,
  4030. pUserProp->szDomain
  4031. );
  4032. }
  4033. if ( !pUserProp->szUserName[0] )
  4034. {
  4035. SetFocus(pMSCHAPv2LogonDialog->hWndUserName);
  4036. }
  4037. else
  4038. {
  4039. SetFocus(pMSCHAPv2LogonDialog->hWndPassword);
  4040. }
  4041. return FALSE;
  4042. }
  4043. BOOL
  4044. LogonCommand(
  4045. IN PEAPMSCHAPv2_LOGON_DIALOG pMSCHAPv2LogonDialog,
  4046. IN WORD wNotifyCode,
  4047. IN WORD wId,
  4048. IN HWND hWndDlg,
  4049. IN HWND hWndCtrl
  4050. )
  4051. {
  4052. BOOL fRetVal = FALSE;
  4053. PEAPMSCHAPv2_USER_PROPERTIES pUserProp = pMSCHAPv2LogonDialog->pUserProp;
  4054. switch(wId)
  4055. {
  4056. case IDC_CHECK_SAVE_UID_PWD:
  4057. if ( pUserProp->fFlags & EAPMSCHAPv2_FLAG_SAVE_UID_PWD )
  4058. {
  4059. //
  4060. // We got the creds from rasman. So toggle the display
  4061. //
  4062. if ( BST_CHECKED ==
  4063. IsDlgButtonChecked ( hWndDlg, IDC_CHECK_SAVE_UID_PWD )
  4064. )
  4065. {
  4066. SetWindowText( pMSCHAPv2LogonDialog->hWndPassword,
  4067. pUserProp->szPassword
  4068. );
  4069. }
  4070. else
  4071. {
  4072. SetWindowText( pMSCHAPv2LogonDialog->hWndPassword,
  4073. ""
  4074. );
  4075. }
  4076. }
  4077. break;
  4078. case IDOK:
  4079. //
  4080. //grab info from the fields and set it in
  4081. //the logon dialog structure
  4082. //
  4083. GetWindowText( pMSCHAPv2LogonDialog->hWndUserName,
  4084. pUserProp->szUserName,
  4085. UNLEN+1
  4086. );
  4087. GetWindowText( pMSCHAPv2LogonDialog->hWndPassword,
  4088. pUserProp->szPassword,
  4089. PWLEN+1
  4090. );
  4091. GetWindowText ( pMSCHAPv2LogonDialog->hWndDomain,
  4092. pUserProp->szDomain,
  4093. DNLEN+1
  4094. );
  4095. if ( !(pUserProp->fFlags & EAPMSCHAPv2_FLAG_CALLED_WITHIN_WINLOGON )
  4096. && !(pUserProp->fFlags & EAPMSCHAPv2_FLAG_8021x) )
  4097. {
  4098. if ( BST_CHECKED ==
  4099. IsDlgButtonChecked ( hWndDlg, IDC_CHECK_SAVE_UID_PWD )
  4100. )
  4101. {
  4102. pUserProp->fFlags |= EAPMSCHAPv2_FLAG_SAVE_UID_PWD;
  4103. }
  4104. else
  4105. {
  4106. pUserProp->fFlags &= ~EAPMSCHAPv2_FLAG_SAVE_UID_PWD;
  4107. }
  4108. }
  4109. else if ( pUserProp->fFlags & EAPMSCHAPv2_FLAG_8021x )
  4110. {
  4111. pUserProp->fFlags |= EAPMSCHAPv2_FLAG_SAVE_UID_PWD;
  4112. }
  4113. case IDCANCEL:
  4114. EndDialog(hWndDlg, wId);
  4115. fRetVal = TRUE;
  4116. break;
  4117. default:
  4118. break;
  4119. }
  4120. return fRetVal;
  4121. }
  4122. INT_PTR CALLBACK
  4123. LogonDialogProc(
  4124. IN HWND hWnd,
  4125. IN UINT unMsg,
  4126. IN WPARAM wParam,
  4127. IN LPARAM lParam
  4128. )
  4129. {
  4130. PEAPMSCHAPv2_LOGON_DIALOG pMSCHAPv2LogonDialog;
  4131. switch (unMsg)
  4132. {
  4133. case WM_INITDIALOG:
  4134. return(LogonInitDialog(hWnd, lParam));
  4135. case WM_HELP:
  4136. case WM_CONTEXTMENU:
  4137. {
  4138. ContextHelp(g_adwHelp, hWnd, unMsg, wParam, lParam);
  4139. break;
  4140. }
  4141. case WM_COMMAND:
  4142. pMSCHAPv2LogonDialog = (PEAPMSCHAPv2_LOGON_DIALOG)GetWindowLongPtr(hWnd, DWLP_USER);
  4143. return(LogonCommand(pMSCHAPv2LogonDialog,
  4144. HIWORD(wParam),
  4145. LOWORD(wParam),
  4146. hWnd,
  4147. (HWND)lParam)
  4148. );
  4149. }
  4150. return(FALSE);
  4151. }
  4152. BOOL
  4153. RetryInitDialog(
  4154. IN HWND hWnd,
  4155. IN LPARAM lParam
  4156. )
  4157. {
  4158. PEAPMSCHAPv2_LOGON_DIALOG pMSCHAPv2LogonDialog;
  4159. PEAPMSCHAPv2_USER_PROPERTIES pUserProp;
  4160. SetWindowLongPtr(hWnd, DWLP_USER, lParam);
  4161. pMSCHAPv2LogonDialog = (PEAPMSCHAPv2_LOGON_DIALOG)lParam;
  4162. pUserProp = pMSCHAPv2LogonDialog->pUserProp;
  4163. pMSCHAPv2LogonDialog->hWndUserName =
  4164. GetDlgItem(hWnd, IDC_RETRY_USERNAME);
  4165. pMSCHAPv2LogonDialog->hWndPassword =
  4166. GetDlgItem(hWnd, IDC_RETRY_PASSWORD);
  4167. pMSCHAPv2LogonDialog->hWndDomain =
  4168. GetDlgItem(hWnd, IDC_RETRY_DOMAIN);
  4169. //Setup upper limit on text boxes
  4170. SendMessage(pMSCHAPv2LogonDialog->hWndUserName,
  4171. EM_LIMITTEXT,
  4172. UNLEN,
  4173. 0L
  4174. );
  4175. SendMessage(pMSCHAPv2LogonDialog->hWndPassword,
  4176. EM_LIMITTEXT,
  4177. PWLEN,
  4178. 0L
  4179. );
  4180. SendMessage(pMSCHAPv2LogonDialog->hWndDomain,
  4181. EM_LIMITTEXT,
  4182. DNLEN,
  4183. 0L
  4184. );
  4185. if ( pUserProp->fFlags & EAPMSCHAPv2_FLAG_SAVE_UID_PWD )
  4186. {
  4187. CheckDlgButton(hWnd, IDC_CHECK_SAVE_UID_PWD, BST_CHECKED);
  4188. }
  4189. if ( pUserProp->szUserName[0] )
  4190. {
  4191. SetWindowText( pMSCHAPv2LogonDialog->hWndUserName,
  4192. pUserProp->szUserName
  4193. );
  4194. }
  4195. if ( pUserProp->szPassword[0] )
  4196. {
  4197. SetWindowText( pMSCHAPv2LogonDialog->hWndPassword,
  4198. pUserProp->szPassword
  4199. );
  4200. }
  4201. if ( pUserProp->szDomain[0] )
  4202. {
  4203. SetWindowText( pMSCHAPv2LogonDialog->hWndDomain,
  4204. pUserProp->szDomain
  4205. );
  4206. }
  4207. SetFocus(pMSCHAPv2LogonDialog->hWndUserName);
  4208. return FALSE;
  4209. }
  4210. BOOL
  4211. RetryCommand(
  4212. IN PEAPMSCHAPv2_LOGON_DIALOG pMSCHAPv2LogonDialog,
  4213. IN WORD wNotifyCode,
  4214. IN WORD wId,
  4215. IN HWND hWndDlg,
  4216. IN HWND hWndCtrl
  4217. )
  4218. {
  4219. BOOL fRetVal = FALSE;
  4220. PEAPMSCHAPv2_USER_PROPERTIES pUserProp = pMSCHAPv2LogonDialog->pUserProp;
  4221. switch(wId)
  4222. {
  4223. case IDC_CHECK_SAVE_UID_PWD:
  4224. if ( BST_CHECKED ==
  4225. IsDlgButtonChecked ( hWndDlg, IDC_CHECK_SAVE_UID_PWD )
  4226. )
  4227. {
  4228. pUserProp->fFlags |= EAPMSCHAPv2_FLAG_SAVE_UID_PWD;
  4229. }
  4230. else
  4231. {
  4232. pUserProp->fFlags &= ~EAPMSCHAPv2_FLAG_SAVE_UID_PWD;
  4233. }
  4234. break;
  4235. case IDOK:
  4236. //
  4237. //grab new password from the dialog and set it in
  4238. //the logon dialog structure
  4239. //
  4240. GetWindowText( pMSCHAPv2LogonDialog->hWndPassword,
  4241. pUserProp->szPassword,
  4242. PWLEN+1
  4243. );
  4244. case IDCANCEL:
  4245. EndDialog(hWndDlg, wId);
  4246. fRetVal = TRUE;
  4247. break;
  4248. default:
  4249. break;
  4250. }
  4251. return fRetVal;
  4252. }
  4253. INT_PTR CALLBACK
  4254. RetryDialogProc(
  4255. IN HWND hWnd,
  4256. IN UINT unMsg,
  4257. IN WPARAM wParam,
  4258. IN LPARAM lParam
  4259. )
  4260. {
  4261. PEAPMSCHAPv2_LOGON_DIALOG pMSCHAPv2LogonDialog;
  4262. switch (unMsg)
  4263. {
  4264. case WM_INITDIALOG:
  4265. return(RetryInitDialog(hWnd, lParam));
  4266. case WM_HELP:
  4267. case WM_CONTEXTMENU:
  4268. {
  4269. ContextHelp(g_adwHelp, hWnd, unMsg, wParam, lParam);
  4270. break;
  4271. }
  4272. case WM_COMMAND:
  4273. pMSCHAPv2LogonDialog = (PEAPMSCHAPv2_LOGON_DIALOG)GetWindowLongPtr(hWnd, DWLP_USER);
  4274. return(RetryCommand(pMSCHAPv2LogonDialog,
  4275. HIWORD(wParam),
  4276. LOWORD(wParam),
  4277. hWnd,
  4278. (HWND)lParam)
  4279. );
  4280. }
  4281. return(FALSE);
  4282. }
  4283. ///
  4284. /// Client configuration dialog
  4285. ///
  4286. BOOL
  4287. ClientConfigInitDialog(
  4288. IN HWND hWnd,
  4289. IN LPARAM lParam
  4290. )
  4291. {
  4292. PEAPMSCHAPv2_CLIENTCONFIG_DIALOG pClientConfigDialog;
  4293. PEAPMSCHAPv2_CONN_PROPERTIES pConnProp;
  4294. SetWindowLongPtr(hWnd, DWLP_USER, lParam);
  4295. pClientConfigDialog = (PEAPMSCHAPv2_CLIENTCONFIG_DIALOG)lParam;
  4296. pConnProp = pClientConfigDialog->pConnProp;
  4297. if ( pConnProp ->fFlags & EAPMSCHAPv2_FLAG_USE_WINLOGON_CREDS )
  4298. {
  4299. CheckDlgButton(hWnd, IDC_CHK_USE_WINLOGON, BST_CHECKED);
  4300. }
  4301. return FALSE;
  4302. }
  4303. BOOL
  4304. ClientConfigCommand(
  4305. IN PEAPMSCHAPv2_CLIENTCONFIG_DIALOG pClientConfigDialog,
  4306. IN WORD wNotifyCode,
  4307. IN WORD wId,
  4308. IN HWND hWndDlg,
  4309. IN HWND hWndCtrl
  4310. )
  4311. {
  4312. BOOL fRetVal = FALSE;
  4313. PEAPMSCHAPv2_CONN_PROPERTIES pConnProp = pClientConfigDialog->pConnProp;
  4314. switch(wId)
  4315. {
  4316. case IDC_CHK_USE_WINLOGON:
  4317. if ( BST_CHECKED ==
  4318. IsDlgButtonChecked ( hWndDlg, IDC_CHK_USE_WINLOGON )
  4319. )
  4320. {
  4321. pConnProp->fFlags |= EAPMSCHAPv2_FLAG_USE_WINLOGON_CREDS;
  4322. }
  4323. else
  4324. {
  4325. pConnProp->fFlags &= ~EAPMSCHAPv2_FLAG_USE_WINLOGON_CREDS;
  4326. }
  4327. break;
  4328. case IDOK:
  4329. case IDCANCEL:
  4330. EndDialog(hWndDlg, wId);
  4331. fRetVal = TRUE;
  4332. break;
  4333. default:
  4334. break;
  4335. }
  4336. return fRetVal;
  4337. }
  4338. INT_PTR CALLBACK
  4339. ClientConfigDialogProc(
  4340. IN HWND hWnd,
  4341. IN UINT unMsg,
  4342. IN WPARAM wParam,
  4343. IN LPARAM lParam
  4344. )
  4345. {
  4346. PEAPMSCHAPv2_CLIENTCONFIG_DIALOG pClientConfigDialog;
  4347. switch (unMsg)
  4348. {
  4349. case WM_INITDIALOG:
  4350. return(ClientConfigInitDialog(hWnd, lParam));
  4351. case WM_HELP:
  4352. case WM_CONTEXTMENU:
  4353. {
  4354. ContextHelp(g_adwHelp, hWnd, unMsg, wParam, lParam);
  4355. break;
  4356. }
  4357. case WM_COMMAND:
  4358. pClientConfigDialog = (PEAPMSCHAPv2_CLIENTCONFIG_DIALOG)GetWindowLongPtr(hWnd, DWLP_USER);
  4359. return(ClientConfigCommand(pClientConfigDialog,
  4360. HIWORD(wParam),
  4361. LOWORD(wParam),
  4362. hWnd,
  4363. (HWND)lParam)
  4364. );
  4365. }
  4366. return(FALSE);
  4367. }
  4368. //// Server Configuration
  4369. //
  4370. BOOL
  4371. ServerConfigInitDialog(
  4372. IN HWND hWnd,
  4373. IN LPARAM lParam
  4374. )
  4375. {
  4376. PEAPMSCHAPv2_SERVERCONFIG_DIALOG pServerConfigDialog;
  4377. PEAPMSCHAPv2_USER_PROPERTIES pUserProp;
  4378. CHAR szRetries[10] = {0};
  4379. SetWindowLongPtr(hWnd, DWLP_USER, lParam);
  4380. pServerConfigDialog = (PEAPMSCHAPv2_SERVERCONFIG_DIALOG)lParam;
  4381. pUserProp = pServerConfigDialog->pUserProp;
  4382. pServerConfigDialog->hWndRetries =
  4383. GetDlgItem(hWnd, IDC_EDIT_RETRIES);
  4384. SendMessage(pServerConfigDialog->hWndRetries ,
  4385. EM_LIMITTEXT,
  4386. 2,
  4387. 0L
  4388. );
  4389. if ( pUserProp->fFlags & EAPMSCHAPv2_FLAG_ALLOW_CHANGEPWD )
  4390. {
  4391. CheckDlgButton(hWnd, IDC_CHECK_ALLOW_CHANGEPWD, BST_CHECKED);
  4392. }
  4393. SetWindowText( pServerConfigDialog->hWndRetries,
  4394. _ltoa(pUserProp->dwMaxRetries, szRetries, 10)
  4395. );
  4396. return FALSE;
  4397. }
  4398. BOOL
  4399. ServerConfigCommand(
  4400. IN PEAPMSCHAPv2_SERVERCONFIG_DIALOG pServerConfigDialog,
  4401. IN WORD wNotifyCode,
  4402. IN WORD wId,
  4403. IN HWND hWndDlg,
  4404. IN HWND hWndCtrl
  4405. )
  4406. {
  4407. BOOL fRetVal = FALSE;
  4408. PEAPMSCHAPv2_USER_PROPERTIES pUserProp = pServerConfigDialog->pUserProp;
  4409. switch(wId)
  4410. {
  4411. case IDC_CHECK_ALLOW_CHANGEPWD:
  4412. if ( BST_CHECKED ==
  4413. IsDlgButtonChecked ( hWndDlg, IDC_CHECK_ALLOW_CHANGEPWD )
  4414. )
  4415. {
  4416. pUserProp->fFlags |= EAPMSCHAPv2_FLAG_ALLOW_CHANGEPWD;
  4417. }
  4418. else
  4419. {
  4420. pUserProp->fFlags &= ~EAPMSCHAPv2_FLAG_ALLOW_CHANGEPWD;
  4421. }
  4422. fRetVal = TRUE;
  4423. break;
  4424. case IDOK:
  4425. {
  4426. CHAR szRetries[10] = {0};
  4427. //
  4428. // Get the new value for retries
  4429. //
  4430. GetWindowText ( pServerConfigDialog->hWndRetries,
  4431. szRetries,
  4432. 9
  4433. );
  4434. pUserProp->dwMaxRetries = atol(szRetries);
  4435. }
  4436. case IDCANCEL:
  4437. EndDialog(hWndDlg, wId);
  4438. fRetVal = TRUE;
  4439. break;
  4440. default:
  4441. break;
  4442. }
  4443. return fRetVal;
  4444. }
  4445. INT_PTR CALLBACK
  4446. ServerConfigDialogProc(
  4447. IN HWND hWnd,
  4448. IN UINT unMsg,
  4449. IN WPARAM wParam,
  4450. IN LPARAM lParam
  4451. )
  4452. {
  4453. PEAPMSCHAPv2_SERVERCONFIG_DIALOG pServerConfigDialog;
  4454. switch (unMsg)
  4455. {
  4456. case WM_INITDIALOG:
  4457. return(ServerConfigInitDialog(hWnd, lParam));
  4458. case WM_HELP:
  4459. case WM_CONTEXTMENU:
  4460. {
  4461. ContextHelp(g_adwHelp, hWnd, unMsg, wParam, lParam);
  4462. break;
  4463. }
  4464. case WM_COMMAND:
  4465. pServerConfigDialog = (PEAPMSCHAPv2_SERVERCONFIG_DIALOG)GetWindowLongPtr(hWnd, DWLP_USER);
  4466. return(ServerConfigCommand(pServerConfigDialog,
  4467. HIWORD(wParam),
  4468. LOWORD(wParam),
  4469. hWnd,
  4470. (HWND)lParam)
  4471. );
  4472. }
  4473. return(FALSE);
  4474. }
  4475. //// Change Password Dialog
  4476. //
  4477. BOOL
  4478. ChangePasswordInitDialog(
  4479. IN HWND hWnd,
  4480. IN LPARAM lParam
  4481. )
  4482. {
  4483. PEAPMSCHAPv2_CHANGEPWD_DIALOG pChangePwdDialog;
  4484. SetWindowLongPtr(hWnd, DWLP_USER, lParam);
  4485. pChangePwdDialog = (PEAPMSCHAPv2_CHANGEPWD_DIALOG)lParam;
  4486. if ( pChangePwdDialog->pInteractiveUIData->fFlags & EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD )
  4487. {
  4488. pChangePwdDialog->hWndNewPassword =
  4489. GetDlgItem(hWnd, IDC_NEW_PASSWORD);
  4490. pChangePwdDialog->hWndConfirmNewPassword =
  4491. GetDlgItem(hWnd, IDC_CONFIRM_NEW_PASSWORD);
  4492. SetWindowText( pChangePwdDialog->hWndNewPassword,
  4493. ""
  4494. );
  4495. }
  4496. else
  4497. {
  4498. pChangePwdDialog->hWndNewPassword =
  4499. GetDlgItem(hWnd, CID_CP_EB_Password_RASDLG);
  4500. pChangePwdDialog->hWndConfirmNewPassword =
  4501. GetDlgItem(hWnd, CID_CP_EB_ConfirmPassword_RASDLG);
  4502. pChangePwdDialog->hWndOldPassword =
  4503. GetDlgItem(hWnd,CID_CP_EB_OldPassword_RASDLG);
  4504. SetWindowText ( pChangePwdDialog->hWndOldPassword,
  4505. ""
  4506. );
  4507. SetFocus( pChangePwdDialog->hWndOldPassword );
  4508. }
  4509. SendMessage ( pChangePwdDialog->hWndNewPassword,
  4510. EM_LIMITTEXT,
  4511. PWLEN-1,
  4512. 0L
  4513. );
  4514. SendMessage ( pChangePwdDialog->hWndConfirmNewPassword,
  4515. EM_LIMITTEXT,
  4516. PWLEN-1,
  4517. 0L
  4518. );
  4519. SetWindowText( pChangePwdDialog->hWndNewPassword,
  4520. ""
  4521. );
  4522. SetWindowText( pChangePwdDialog->hWndConfirmNewPassword,
  4523. ""
  4524. );
  4525. return FALSE;
  4526. }
  4527. BOOL
  4528. ChangePasswordCommand(
  4529. IN PEAPMSCHAPv2_CHANGEPWD_DIALOG pChangePwdDialog,
  4530. IN WORD wNotifyCode,
  4531. IN WORD wId,
  4532. IN HWND hWndDlg,
  4533. IN HWND hWndCtrl
  4534. )
  4535. {
  4536. BOOL fRetVal = FALSE;
  4537. switch(wId)
  4538. {
  4539. case IDOK:
  4540. {
  4541. CHAR szOldPassword[PWLEN+1] = {0};
  4542. CHAR szNewPassword[PWLEN+1] = {0};
  4543. CHAR szConfirmNewPassword[PWLEN+1] = {0};
  4544. CHAR szMessage[512] = {0};
  4545. CHAR szHeader[64] = {0};
  4546. LoadString( GetHInstance(),
  4547. IDS_MESSAGE_HEADER,
  4548. szHeader,
  4549. sizeof(szHeader)-1
  4550. );
  4551. if ( pChangePwdDialog->pInteractiveUIData->fFlags &
  4552. EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD_WINLOGON
  4553. )
  4554. {
  4555. GetWindowText ( pChangePwdDialog->hWndOldPassword,
  4556. szOldPassword,
  4557. PWLEN
  4558. );
  4559. }
  4560. //
  4561. // Get the new value for retries
  4562. //
  4563. GetWindowText ( pChangePwdDialog->hWndNewPassword,
  4564. szNewPassword,
  4565. PWLEN
  4566. );
  4567. GetWindowText ( pChangePwdDialog->hWndConfirmNewPassword,
  4568. szConfirmNewPassword,
  4569. PWLEN
  4570. );
  4571. if ( szNewPassword[0] == 0 )
  4572. {
  4573. //
  4574. // Load resource from res file
  4575. //
  4576. LoadString( GetHInstance(),
  4577. IDS_PASSWORD_REQUIRED,
  4578. szMessage,
  4579. sizeof(szMessage)-1
  4580. );
  4581. MessageBox (hWndDlg,
  4582. szMessage,
  4583. szHeader,
  4584. MB_OK
  4585. );
  4586. break;
  4587. }
  4588. if ( pChangePwdDialog->pInteractiveUIData->fFlags &
  4589. EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD_WINLOGON
  4590. )
  4591. {
  4592. if ( szOldPassword[0] == 0 )
  4593. {
  4594. LoadString( GetHInstance(),
  4595. IDS_PASSWORD_REQUIRED,
  4596. szMessage,
  4597. sizeof(szMessage)-1
  4598. );
  4599. MessageBox (hWndDlg,
  4600. szMessage,
  4601. szHeader,
  4602. MB_OK
  4603. );
  4604. break;
  4605. }
  4606. }
  4607. if ( strncmp ( szNewPassword, szConfirmNewPassword, PWLEN ) )
  4608. {
  4609. LoadString( GetHInstance(),
  4610. IDS_PASSWORD_MISMATCH,
  4611. szMessage,
  4612. sizeof(szMessage)-1
  4613. );
  4614. MessageBox (hWndDlg,
  4615. szMessage,
  4616. szHeader,
  4617. MB_OK
  4618. );
  4619. break;
  4620. }
  4621. if ( pChangePwdDialog->pInteractiveUIData->fFlags &
  4622. EAPMSCHAPv2_INTERACTIVE_UI_FLAG_CHANGE_PWD_WINLOGON
  4623. )
  4624. {
  4625. //Save the old paswword.
  4626. CopyMemory ( pChangePwdDialog->pInteractiveUIData->UserProp.szPassword,
  4627. szOldPassword,
  4628. PWLEN
  4629. );
  4630. }
  4631. CopyMemory ( pChangePwdDialog->pInteractiveUIData->szNewPassword,
  4632. szNewPassword,
  4633. PWLEN
  4634. );
  4635. //fall thru
  4636. }
  4637. case IDCANCEL:
  4638. EndDialog(hWndDlg, wId);
  4639. fRetVal = TRUE;
  4640. break;
  4641. default:
  4642. break;
  4643. }
  4644. return fRetVal;
  4645. }
  4646. DWORD
  4647. DwGetGlobalConfig(
  4648. IN DWORD dwEapTypeId,
  4649. OUT PBYTE* ppConfigDataOut,
  4650. OUT DWORD* pdwSizeOfConfigDataOut
  4651. )
  4652. {
  4653. DWORD dwErr = NO_ERROR;
  4654. PBYTE pbData = NULL;
  4655. dwErr = ServerConfigDataIO(
  4656. TRUE,
  4657. NULL,
  4658. ppConfigDataOut,
  4659. 0);
  4660. if(NO_ERROR != dwErr)
  4661. {
  4662. goto done;
  4663. }
  4664. *pdwSizeOfConfigDataOut = sizeof(EAPMSCHAPv2_USER_PROPERTIES);
  4665. done:
  4666. return HRESULT_FROM_WIN32(dwErr);
  4667. }
  4668. INT_PTR CALLBACK
  4669. ChangePasswordDialogProc(
  4670. IN HWND hWnd,
  4671. IN UINT unMsg,
  4672. IN WPARAM wParam,
  4673. IN LPARAM lParam
  4674. )
  4675. {
  4676. PEAPMSCHAPv2_CHANGEPWD_DIALOG pChangePwdDialog;
  4677. switch (unMsg)
  4678. {
  4679. case WM_INITDIALOG:
  4680. return(ChangePasswordInitDialog(hWnd, lParam));
  4681. case WM_HELP:
  4682. case WM_CONTEXTMENU:
  4683. {
  4684. ContextHelp(g_adwHelp, hWnd, unMsg, wParam, lParam);
  4685. break;
  4686. }
  4687. case WM_COMMAND:
  4688. pChangePwdDialog = (PEAPMSCHAPv2_CHANGEPWD_DIALOG)GetWindowLongPtr(hWnd, DWLP_USER);
  4689. return(ChangePasswordCommand(pChangePwdDialog,
  4690. HIWORD(wParam),
  4691. LOWORD(wParam),
  4692. hWnd,
  4693. (HWND)lParam)
  4694. );
  4695. }
  4696. return(FALSE);
  4697. }