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

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