Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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