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.

861 lines
22 KiB

  1. /* Copyright (c) 1993, Microsoft Corporation, all rights reserved
  2. **
  3. ** raspap.c
  4. ** Remote Access PPP Password Authentication Protocol
  5. ** Core routines
  6. **
  7. ** 11/05/93 Steve Cobb
  8. */
  9. #include <nt.h>
  10. #include <ntrtl.h>
  11. #include <nturtl.h>
  12. #include <ntlsa.h>
  13. #include <ntmsv1_0.h>
  14. #include <crypt.h>
  15. #include <windows.h>
  16. #include <lmcons.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include <rasman.h>
  20. #include <pppcp.h>
  21. #include <rtutils.h>
  22. #define INCL_PWUTIL
  23. #define INCL_HOSTWIRE
  24. #define INCL_RASAUTHATTRIBUTES
  25. #define INCL_MISC
  26. #include <ppputil.h>
  27. #include <rasauth.h>
  28. #define SDEBUGGLOBALS
  29. #define RASPAPGLOBALS
  30. #include "raspap.h"
  31. #include <raserror.h>
  32. #define TRACE_RASPAP (0x00010000|TRACE_USE_MASK)
  33. #define TRACE(a) TracePrintfExA(g_dwTraceIdPap,TRACE_RASPAP,a )
  34. #define TRACE1(a,b) TracePrintfExA(g_dwTraceIdPap,TRACE_RASPAP,a,b )
  35. #define TRACE2(a,b,c) TracePrintfExA(g_dwTraceIdPap,TRACE_RASPAP,a,b,c )
  36. #define TRACE3(a,b,c,d) TracePrintfExA(g_dwTraceIdPap,TRACE_RASPAP,a,b,c,d )
  37. #define DUMPW(X,Y) TraceDumpExA(g_dwTraceIdPap,1,(LPBYTE)X,Y,4,1,NULL)
  38. #define DUMPB(X,Y) TraceDumpExA(g_dwTraceIdPap,1,(LPBYTE)X,Y,1,1,NULL)
  39. #define REGKEY_Pap \
  40. "SYSTEM\\CurrentControlSet\\Services\\RasMan\\PPP\\ControlProtocols\\BuiltIn"
  41. #define REGVAL_FollowStrictSequencing "FollowStrictSequencing"
  42. /*---------------------------------------------------------------------------
  43. ** External entry points
  44. **---------------------------------------------------------------------------
  45. */
  46. DWORD
  47. PapInit(
  48. BOOL fInitialize)
  49. {
  50. if (fInitialize)
  51. {
  52. HKEY hkey;
  53. DWORD dwType;
  54. DWORD dwValue;
  55. DWORD cb = sizeof(DWORD);
  56. if (RegOpenKey( HKEY_LOCAL_MACHINE, REGKEY_Pap, &hkey ) == 0)
  57. {
  58. if (RegQueryValueEx(
  59. hkey, REGVAL_FollowStrictSequencing, NULL,
  60. &dwType, (LPBYTE )&dwValue, &cb ) == 0
  61. && dwType == REG_DWORD
  62. && cb == sizeof(DWORD)
  63. && dwValue)
  64. {
  65. fFollowStrictSequencing = TRUE;
  66. }
  67. RegCloseKey( hkey );
  68. }
  69. g_dwTraceIdPap = TraceRegisterA( "RASPAP" );
  70. }
  71. else
  72. {
  73. if ( g_dwTraceIdPap != INVALID_TRACEID )
  74. {
  75. TraceDeregisterA( g_dwTraceIdPap );
  76. g_dwTraceIdPap = INVALID_TRACEID;
  77. }
  78. }
  79. return(NO_ERROR);
  80. }
  81. DWORD
  82. PapGetInfo(
  83. IN DWORD dwProtocolId,
  84. OUT PPPCP_INFO* pInfo )
  85. /* PapGetInfo entry point called by the PPP engine. See RasCp
  86. ** interface documentation.
  87. */
  88. {
  89. TRACE(("PAP: PapGetInfo\n"));
  90. ZeroMemory( pInfo, sizeof(*pInfo) );
  91. pInfo->Protocol = (DWORD )PPP_PAP_PROTOCOL;
  92. pInfo->Recognize = MAXPAPCODE + 1;
  93. pInfo->RasCpInit = PapInit;
  94. pInfo->RasCpBegin = PapBegin;
  95. pInfo->RasCpEnd = PapEnd;
  96. pInfo->RasApMakeMessage = PapMakeMessage;
  97. return 0;
  98. }
  99. DWORD
  100. PapBegin(
  101. OUT VOID** ppWorkBuf,
  102. IN VOID* pInfo )
  103. /* RasCpBegin entry point called by the PPP engine thru the passed
  104. ** address. See RasCp interface documentation.
  105. */
  106. {
  107. PPPAP_INPUT* pInput = (PPPAP_INPUT* )pInfo;
  108. PAPWB* pwb;
  109. /* Allocate work buffer.
  110. */
  111. if (!(pwb = (PAPWB* )LocalAlloc( LPTR, sizeof(PAPWB) )))
  112. return ERROR_NOT_ENOUGH_MEMORY;
  113. pwb->fServer = pInput->fServer;
  114. pwb->chSeed = GEN_RAND_ENCODE_SEED;
  115. if (!pwb->fServer)
  116. {
  117. TRACE2("PAP: PapBegin(u=%s,d=%s\n",pInput->pszUserName
  118. ,pInput->pszDomain);
  119. /* Validate credential lengths. The credential strings will never be
  120. ** NULL, but may be "".
  121. **
  122. ** !!! PAP requires the domain\username length to fit in a byte.
  123. ** Currently, UNLEN is defined as 256 and DNLEN is defined as 15.
  124. ** This means that some valid domain\username combinations cannot
  125. ** be validated over PAP, but it's only on *really* long
  126. ** usernames. Likewise, a password of exactly 256 characters
  127. ** cannot be validated.
  128. */
  129. {
  130. DWORD cbUserName = strlen( pInput->pszUserName );
  131. DWORD cbPassword = strlen( pInput->pszPassword );
  132. DWORD cbDomain = strlen( pInput->pszDomain );
  133. if (cbUserName > UNLEN
  134. || cbDomain > DNLEN
  135. || cbDomain + 1 + cbUserName > 255
  136. || cbPassword > max( PWLEN, 255 ))
  137. {
  138. LocalFree( pwb );
  139. return ERROR_INVALID_PARAMETER;
  140. }
  141. }
  142. /* "Account" refers to the domain\username format. When domain is "",
  143. ** no "\" is sent (to facilitate connecting to foreign systems which
  144. ** use a simple string identifier). Otherwise when username is "",
  145. ** the "\" is sent, i.e. "domain\". This form will currently fail,
  146. ** but could be mapped to some sort of "guest" access in the future.
  147. */
  148. if (*(pInput->pszDomain) != '\0')
  149. {
  150. strcpy( pwb->szAccount, pInput->pszDomain );
  151. strcat( pwb->szAccount, "\\" );
  152. }
  153. strcat( pwb->szAccount, pInput->pszUserName );
  154. strcpy( pwb->szPassword, pInput->pszPassword );
  155. EncodePw( pwb->chSeed, pwb->szPassword );
  156. }
  157. else
  158. {
  159. pwb->hPort = pInput->hPort;
  160. }
  161. pwb->state = PS_Initial;
  162. /* Register work buffer with engine.
  163. */
  164. *ppWorkBuf = pwb;
  165. return 0;
  166. }
  167. DWORD
  168. PapEnd(
  169. IN VOID* pWorkBuf )
  170. /* RasCpEnd entry point called by the PPP engine thru the passed address.
  171. ** See RasCp interface documentation.
  172. */
  173. {
  174. TRACE("PAP: PapEnd\n");
  175. if ( pWorkBuf != NULL )
  176. {
  177. PAPWB* pwb = (PAPWB* )pWorkBuf;
  178. if ( pwb->pUserAttributes != NULL )
  179. {
  180. RasAuthAttributeDestroy( pwb->pUserAttributes );
  181. pwb->pUserAttributes = NULL;
  182. }
  183. ZeroMemory( pWorkBuf, sizeof(PAPWB) );
  184. LocalFree( (HLOCAL )pWorkBuf );
  185. }
  186. return 0;
  187. }
  188. DWORD
  189. PapMakeMessage(
  190. IN VOID* pWorkBuf,
  191. IN PPP_CONFIG* pReceiveBuf,
  192. OUT PPP_CONFIG* pSendBuf,
  193. IN DWORD cbSendBuf,
  194. OUT PPPAP_RESULT* pResult,
  195. IN PPPAP_INPUT* pInput )
  196. /* RasApMakeMessage entry point called by the PPP engine thru the passed
  197. ** address. See RasCp interface documentation.
  198. */
  199. {
  200. PAPWB* pwb = (PAPWB* )pWorkBuf;
  201. TRACE1("PAP: PapMakeMessage,RBuf=%p\n",pReceiveBuf);
  202. (void )pInput;
  203. return
  204. (pwb->fServer)
  205. ? PapSMakeMessage(pwb, pReceiveBuf, pSendBuf, cbSendBuf, pInput,
  206. pResult)
  207. : PapCMakeMessage( pwb, pReceiveBuf, pSendBuf, cbSendBuf, pResult );
  208. }
  209. /*---------------------------------------------------------------------------
  210. ** Internal routines (alphabetically)
  211. **---------------------------------------------------------------------------
  212. */
  213. DWORD
  214. PapCMakeMessage(
  215. IN PAPWB* pwb,
  216. IN PPP_CONFIG* pReceiveBuf,
  217. OUT PPP_CONFIG* pSendBuf,
  218. IN DWORD cbSendBuf,
  219. OUT PPPAP_RESULT* pResult )
  220. /* Client side "make message" entry point. See RasCp interface
  221. ** documentation.
  222. */
  223. {
  224. /* Start over if timeout waiting for a reply.
  225. */
  226. if (!pReceiveBuf && pwb->state != PS_Initial)
  227. pwb->state = PS_Initial;
  228. switch (pwb->state)
  229. {
  230. case PS_Initial:
  231. {
  232. /* Send an Authenticate-Req packet, then wait for the reply.
  233. */
  234. pResult->bIdExpected = BNextIdPap;
  235. PapMakeRequestMessage( pwb, pSendBuf, cbSendBuf );
  236. pResult->Action = APA_SendWithTimeout;
  237. pwb->state = PS_RequestSent;
  238. break;
  239. }
  240. case PS_RequestSent:
  241. {
  242. if (pReceiveBuf->Id != pwb->bIdSent)
  243. {
  244. //
  245. // See bug # 22508
  246. //
  247. if ( fFollowStrictSequencing )
  248. {
  249. /* Received a packet out of sequence. Silently discard it.
  250. */
  251. pResult->Action = APA_NoAction;
  252. break;
  253. }
  254. }
  255. pResult->fRetry = FALSE;
  256. PapExtractMessage( pReceiveBuf, pResult );
  257. if (pReceiveBuf->Code == PAPCODE_Ack)
  258. {
  259. /* Passed authentication.
  260. */
  261. pResult->Action = APA_Done;
  262. pResult->dwError = 0;
  263. pwb->state = PS_Done;
  264. }
  265. else if (pReceiveBuf->Code == PAPCODE_Nak)
  266. {
  267. /* Failed authentication.
  268. */
  269. pResult->Action = APA_Done;
  270. pResult->dwError = GetErrorFromNak( pReceiveBuf );
  271. pwb->state = PS_Done;
  272. }
  273. else
  274. {
  275. /* Received an Authenticate-Req packet. The engine filters
  276. ** all others. Shouldn't happen, but silently discard it.
  277. */
  278. RTASSERT(!"Bogus pReceiveBuf->Code");
  279. pResult->Action = APA_NoAction;
  280. break;
  281. }
  282. break;
  283. }
  284. }
  285. return 0;
  286. }
  287. DWORD
  288. GetCredentialsFromRequest(
  289. IN PPP_CONFIG* pReceiveBuf,
  290. OUT CHAR* pszIdentity,
  291. OUT CHAR* pszPassword
  292. )
  293. /* Fill caller's 'pszIdentity' and 'pszPassword' buffers
  294. ** with the username and password in the request packet.
  295. ** Caller's buffers should be at least UNLEN+DNLEN+1 and PWLEN bytes long,
  296. ** respectively.
  297. **
  298. ** Returns 0 if successful, or ERRORBADPACKET if the packet is
  299. ** misformatted in any way.
  300. */
  301. {
  302. BYTE* pcbPeerId;
  303. CHAR* pchPeerId;
  304. BYTE* pcbPassword;
  305. CHAR* pchPassword;
  306. WORD cbPacket;
  307. cbPacket = WireToHostFormat16( pReceiveBuf->Length );
  308. /* Parse out username and domain from the peer ID (domain\username or
  309. ** username format).
  310. */
  311. if (cbPacket < PPP_CONFIG_HDR_LEN + 1)
  312. return ERRORBADPACKET;
  313. pcbPeerId = pReceiveBuf->Data;
  314. pchPeerId = pcbPeerId + 1;
  315. if (cbPacket < PPP_CONFIG_HDR_LEN + 1 + *pcbPeerId)
  316. {
  317. return ERRORBADPACKET;
  318. }
  319. /* Extract the username.
  320. */
  321. RTASSERT(*pcbPeerId <= (UNLEN+DNLEN+1));
  322. CopyMemory( pszIdentity, pchPeerId, *pcbPeerId );
  323. pszIdentity[ *pcbPeerId ] = '\0';
  324. /* Extract the password.
  325. */
  326. if (cbPacket < PPP_CONFIG_HDR_LEN + 1 + *pcbPeerId + 1)
  327. return ERRORBADPACKET;
  328. pcbPassword = pchPeerId + *pcbPeerId;
  329. pchPassword = pcbPassword + 1;
  330. RTASSERT(*pcbPassword<=PWLEN);
  331. if (cbPacket < PPP_CONFIG_HDR_LEN + 1 + *pcbPeerId + 1 + *pcbPassword)
  332. return ERRORBADPACKET;
  333. CopyMemory( pszPassword, pchPassword, *pcbPassword );
  334. pszPassword[ *pcbPassword ] = '\0';
  335. return 0;
  336. }
  337. DWORD
  338. GetErrorFromNak(
  339. IN PPP_CONFIG* pReceiveBuf )
  340. /* Returns the RAS error number out of the Message portion of the
  341. ** Authenticate-Nak message buffer 'pReceiveBuf' or 0 if none.
  342. */
  343. {
  344. DWORD dwError = 0;
  345. CHAR szBuf[ 255 + 1 ];
  346. BYTE* pcbMsg = pReceiveBuf->Data;
  347. WORD cbPacket = WireToHostFormat16( pReceiveBuf->Length );
  348. TRACE("PAP: GetErrorFromNak...\n");
  349. if (cbPacket > PPP_CONFIG_HDR_LEN && *pcbMsg)
  350. {
  351. CHAR* pchBuf = szBuf;
  352. CHAR* pchMsg = pcbMsg + 1;
  353. BYTE i;
  354. if (*pcbMsg > 2 && pchMsg[ 0 ] == 'E' || pchMsg[ 1 ] == '=')
  355. {
  356. for (i = 2; i < *pcbMsg; ++i)
  357. {
  358. if (pchMsg[ i ] < '0' || pchMsg[ i ] > '9')
  359. break;
  360. *pchBuf++ = pchMsg[ i ];
  361. }
  362. *pchBuf = '\0';
  363. dwError = (DWORD )atol( szBuf );
  364. }
  365. }
  366. if (dwError == 0)
  367. {
  368. TRACE("PAP: Error code not found.\n");
  369. dwError = ERROR_AUTHENTICATION_FAILURE;
  370. }
  371. TRACE1("PAP: GetErrorFromNak done(%d)\n",dwError);
  372. return dwError;
  373. }
  374. VOID
  375. PapMakeRequestMessage(
  376. IN PAPWB* pwb,
  377. OUT PPP_CONFIG* pSendBuf,
  378. IN DWORD cbSendBuf )
  379. /* Builds a request packet in caller's 'pSendBuf' buffer. 'cbSendBuf' is
  380. ** the length of caller's buffer. 'pwb' is the address of the work
  381. ** buffer associated with the port.
  382. */
  383. {
  384. BYTE* pcbPeerId;
  385. CHAR* pchPeerId;
  386. BYTE* pcbPassword;
  387. CHAR* pchPassword;
  388. RTASSERT(cbSendBuf>=PPP_CONFIG_HDR_LEN+1+UNLEN+1+DNLEN+1+PWLEN);
  389. (void )cbSendBuf;
  390. /* Fill in the peer ID, i.e. the account.
  391. */
  392. pcbPeerId = pSendBuf->Data;
  393. *pcbPeerId = (BYTE )strlen( pwb->szAccount );
  394. pchPeerId = pcbPeerId + 1;
  395. strcpy( pchPeerId, pwb->szAccount );
  396. /* Fill in the password.
  397. */
  398. pcbPassword = pchPeerId + *pcbPeerId;
  399. *pcbPassword = (BYTE )strlen( pwb->szPassword );
  400. pchPassword = pcbPassword + 1;
  401. strcpy( pchPassword, pwb->szPassword );
  402. DecodePw( pwb->chSeed, pchPassword );
  403. /* Fill in the header.
  404. */
  405. pSendBuf->Code = (BYTE )PAPCODE_Req;
  406. pSendBuf->Id = pwb->bIdSent = BNextIdPap++;
  407. {
  408. WORD wLength =
  409. (WORD )(PPP_CONFIG_HDR_LEN + 1 + *pcbPeerId + 1 + *pcbPassword);
  410. HostToWireFormat16( wLength, pSendBuf->Length );
  411. TRACE("PAP: Request...\n");//DUMPB(pSendBuf,(DWORD )wLength);
  412. }
  413. }
  414. VOID
  415. PapMakeResultMessage(
  416. IN DWORD dwError,
  417. IN BYTE bId,
  418. OUT PPP_CONFIG* pSendBuf,
  419. IN DWORD cbSendBuf,
  420. IN RAS_AUTH_ATTRIBUTE* pAttributesFromAuthenticator)
  421. /* Builds a result packet (Ack or Nak) in caller's 'pSendBuf' buffer.
  422. ** 'cbSendBuf' is the length of caller's buffer. 'dwError' indicates
  423. ** whether an Ack (0) or Nak (!0) should be generated, and for Nak the
  424. ** failure code to include. 'bId' is the packet sequence number of the
  425. ** corresponding request packet. pAttributesFromAuthenticator points to
  426. ** attributes returned by the authenticator.
  427. */
  428. {
  429. BYTE* pcbMsg;
  430. BYTE cbMsg;
  431. CHAR* pchMsg;
  432. CHAR* pszReplyMessage = NULL;
  433. DWORD dwNumBytes;
  434. RTASSERT(cbSendBuf>=PPP_CONFIG_HDR_LEN+1+10);
  435. /* Fill in the header and message. If unsuccessful, the message is the
  436. ** decimal RAS error code in ASCII.
  437. */
  438. pSendBuf->Id = bId;
  439. pcbMsg = pSendBuf->Data;
  440. pchMsg = pcbMsg + 1;
  441. if (dwError == 0)
  442. {
  443. pSendBuf->Code = PAPCODE_Ack;
  444. cbMsg = 0;
  445. }
  446. else
  447. {
  448. pSendBuf->Code = PAPCODE_Nak;
  449. strcpy( pchMsg, "E=" );
  450. _ltoa( (long )dwError, (char* )pchMsg + 2, 10 );
  451. cbMsg = (BYTE )strlen( pchMsg );
  452. }
  453. if (pAttributesFromAuthenticator != NULL)
  454. {
  455. pszReplyMessage = RasAuthAttributeGetConcatString(
  456. raatReplyMessage,
  457. pAttributesFromAuthenticator, &dwNumBytes );
  458. }
  459. if (NULL != pszReplyMessage)
  460. {
  461. if (dwNumBytes + cbMsg > 0xFF)
  462. {
  463. dwNumBytes = 0xFF - cbMsg;
  464. }
  465. if (dwNumBytes > cbSendBuf - PPP_CONFIG_HDR_LEN - 1 - cbMsg)
  466. {
  467. dwNumBytes = cbSendBuf - PPP_CONFIG_HDR_LEN - 1 - cbMsg;
  468. }
  469. CopyMemory(pchMsg + cbMsg, pszReplyMessage, dwNumBytes);
  470. cbMsg += (BYTE)dwNumBytes;
  471. }
  472. LocalFree(pszReplyMessage);
  473. {
  474. WORD wLength = (WORD )(PPP_CONFIG_HDR_LEN + 1 + cbMsg);
  475. HostToWireFormat16( wLength, (PBYTE )pSendBuf->Length );
  476. *pcbMsg = cbMsg;
  477. TRACE("PAP: Result...\n");DUMPB(pSendBuf,(DWORD )wLength);
  478. }
  479. }
  480. VOID
  481. PapExtractMessage(
  482. IN PPP_CONFIG* pReceiveBuf,
  483. OUT PPPAP_RESULT* pResult )
  484. {
  485. DWORD dwNumBytes;
  486. CHAR* pszReplyMessage = NULL;
  487. WORD cbPacket;
  488. cbPacket = WireToHostFormat16(pReceiveBuf->Length);
  489. if (PPP_CONFIG_HDR_LEN >= cbPacket)
  490. {
  491. goto LDone;
  492. }
  493. //
  494. // There is one extra byte for Msg-Length
  495. //
  496. dwNumBytes = cbPacket - PPP_CONFIG_HDR_LEN - 1;
  497. //
  498. // One more for the terminating NULL.
  499. //
  500. pszReplyMessage = LocalAlloc(LPTR, dwNumBytes + 1);
  501. if (NULL == pszReplyMessage)
  502. {
  503. TRACE("LocalAlloc failed. Cannot extract server's message.");
  504. goto LDone;
  505. }
  506. CopyMemory(pszReplyMessage, pReceiveBuf->Data + 1, dwNumBytes);
  507. LocalFree(pResult->szReplyMessage);
  508. pResult->szReplyMessage = pszReplyMessage;
  509. pszReplyMessage = NULL;
  510. LDone:
  511. LocalFree(pszReplyMessage);
  512. return;
  513. }
  514. DWORD
  515. PapSMakeMessage(
  516. IN PAPWB* pwb,
  517. IN PPP_CONFIG* pReceiveBuf,
  518. OUT PPP_CONFIG* pSendBuf,
  519. IN DWORD cbSendBuf,
  520. IN PPPAP_INPUT* pInput,
  521. OUT PPPAP_RESULT* pResult )
  522. /* Server side "make message" entry point. See RasCp interface
  523. ** documentation.
  524. */
  525. {
  526. DWORD dwErr;
  527. switch (pwb->state)
  528. {
  529. case PS_Initial:
  530. {
  531. /* Tell engine we're waiting for the client to initiate the
  532. ** conversation.
  533. */
  534. pResult->Action = APA_NoAction;
  535. pwb->state = PS_WaitForRequest;
  536. break;
  537. }
  538. case PS_WaitForRequest:
  539. {
  540. CHAR szIdentity[ UNLEN + DNLEN + 2 ];
  541. CHAR szPassword[ PWLEN + 1 ];
  542. //
  543. // Only process events where we received a packet, igore all other
  544. // events in this state.
  545. //
  546. if ( pReceiveBuf == NULL )
  547. {
  548. pResult->Action = APA_NoAction;
  549. break;
  550. }
  551. if (pReceiveBuf->Code != PAPCODE_Req)
  552. {
  553. /* Silently discard Ack or Nak. Engine catches the one's that
  554. ** aren't even valid codes.
  555. */
  556. RTASSERT(pReceiveBuf->Code!=PAPCODE_Req);
  557. pResult->Action = APA_NoAction;
  558. break;
  559. }
  560. /* Extract user's credentials from received packet.
  561. */
  562. if ((dwErr = GetCredentialsFromRequest(
  563. pReceiveBuf, szIdentity, szPassword )) != 0)
  564. {
  565. if (dwErr == ERRORBADPACKET)
  566. {
  567. /* The packet is corrupt. Silently discard it.
  568. */
  569. RTASSERT(dwErr!=ERRORBADPACKET);
  570. pResult->Action = APA_NoAction;
  571. break;
  572. }
  573. return dwErr;
  574. }
  575. pwb->bLastIdReceived = pReceiveBuf->Id;
  576. //
  577. // Make credentials attributes that will be used to authenticate
  578. // the client.
  579. //
  580. if ( pwb->pUserAttributes != NULL )
  581. {
  582. RasAuthAttributeDestroy( pwb->pUserAttributes );
  583. pwb->pUserAttributes = NULL;
  584. }
  585. if (( pwb->pUserAttributes = RasAuthAttributeCreate( 2 ) ) == NULL)
  586. {
  587. return( GetLastError() );
  588. }
  589. dwErr = RasAuthAttributeInsert( 0,
  590. pwb->pUserAttributes,
  591. raatUserName,
  592. FALSE,
  593. strlen( szIdentity ),
  594. szIdentity );
  595. if ( dwErr != NO_ERROR )
  596. {
  597. RasAuthAttributeDestroy( pwb->pUserAttributes );
  598. pwb->pUserAttributes = NULL;
  599. return( dwErr );
  600. }
  601. dwErr = RasAuthAttributeInsert( 1,
  602. pwb->pUserAttributes,
  603. raatUserPassword,
  604. FALSE,
  605. strlen( szPassword ),
  606. szPassword );
  607. if ( dwErr != NO_ERROR )
  608. {
  609. RasAuthAttributeDestroy( pwb->pUserAttributes );
  610. pwb->pUserAttributes = NULL;
  611. return( dwErr );
  612. }
  613. //
  614. // Start authentication with back-end module
  615. //
  616. strcpy( pwb->result.szUserName, szIdentity );
  617. pResult->pUserAttributes = pwb->pUserAttributes;
  618. pResult->Action = APA_Authenticate;
  619. pwb->state = PS_WaitForAuthenticationToComplete;
  620. break;
  621. }
  622. case PS_WaitForAuthenticationToComplete:
  623. {
  624. if ( pInput != NULL )
  625. {
  626. if ( pInput->fAuthenticationComplete )
  627. {
  628. strcpy( pResult->szUserName, pwb->result.szUserName );
  629. if ( pInput->dwAuthError != NO_ERROR )
  630. {
  631. return( pInput->dwAuthError );
  632. }
  633. if ( pInput->dwAuthResultCode != NO_ERROR )
  634. {
  635. pwb->result.dwError = pInput->dwAuthResultCode;
  636. }
  637. pwb->result.Action = APA_SendAndDone;
  638. pwb->state = PS_Done;
  639. /* ...fall thru...
  640. */
  641. }
  642. }
  643. if ( ( pInput == NULL ) || ( !pInput->fAuthenticationComplete ) )
  644. {
  645. //
  646. // Ignore everything if authentication is not complete
  647. //
  648. if ( pReceiveBuf != NULL )
  649. {
  650. pwb->bLastIdReceived = pReceiveBuf->Id;
  651. }
  652. pResult->Action = APA_NoAction;
  653. break;
  654. }
  655. }
  656. case PS_Done:
  657. {
  658. //
  659. // If we received a packet or the back-end authenticator completed
  660. //
  661. if ( ( pReceiveBuf != NULL ) ||
  662. ( ( pInput != NULL ) && ( pInput->fAuthenticationComplete ) ) )
  663. {
  664. //
  665. // Build the Ack or Nak packet. The same packet sent in
  666. // response to the first Authenticate-Req packet is sent in
  667. // response to all subsequent Authenticate-Req packets
  668. // regardless of credentials (per PAP spec).
  669. //
  670. if ( pReceiveBuf != NULL )
  671. {
  672. pwb->bLastIdReceived = pReceiveBuf->Id;
  673. }
  674. PapMakeResultMessage( pwb->result.dwError,
  675. pwb->bLastIdReceived,
  676. pSendBuf,
  677. cbSendBuf,
  678. (pInput != NULL) ?
  679. pInput->pAttributesFromAuthenticator :
  680. NULL );
  681. CopyMemory( pResult, &pwb->result, sizeof(*pResult) );
  682. }
  683. else
  684. {
  685. pResult->Action = APA_NoAction;
  686. break;
  687. }
  688. break;
  689. }
  690. }
  691. return 0;
  692. }