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.

1075 lines
27 KiB

  1. /********************************************************************/
  2. /** Copyright(c) 1989 Microsoft Corporation. **/
  3. /********************************************************************/
  4. //***
  5. //
  6. // Filename: rascbcp.c
  7. //
  8. // Description: This module contains code to implement the PPP Callback
  9. // Control Protocol.
  10. //
  11. // History: April 11,1994. 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 <crypt.h>
  19. #include <windows.h>
  20. #include <lmcons.h>
  21. #include <string.h>
  22. #include <stdlib.h>
  23. #include <rasman.h>
  24. #include <pppcp.h>
  25. #define INCL_PWUTIL
  26. #define INCL_HOSTWIRE
  27. #include <ppputil.h>
  28. #include "rascbcp.h"
  29. #include <raserror.h>
  30. //**
  31. //
  32. // Call: CbCPGetInfo
  33. //
  34. // Returns: NO_ERROR
  35. //
  36. // Description: CbCPGetInfo entry point called by the PPP engine.
  37. // See RasCpGetInfo interface documentation.
  38. //
  39. DWORD
  40. CbCPGetInfo(
  41. IN DWORD dwProtocolId,
  42. OUT PPPCP_INFO* pInfo
  43. )
  44. {
  45. ZeroMemory( pInfo, sizeof(PPPCP_INFO) );
  46. pInfo->Protocol = (DWORD)PPP_CBCP_PROTOCOL;
  47. lstrcpy(pInfo->SzProtocolName, "CBCP");
  48. pInfo->Recognize = MAX_CBCP_CODE + 1;
  49. pInfo->RasCpBegin = CbCPBegin;
  50. pInfo->RasCpEnd = CbCPEnd;
  51. pInfo->RasApMakeMessage = CbCPMakeMessage;
  52. return( NO_ERROR );
  53. }
  54. //**
  55. //
  56. // Call: CbCPBegin
  57. //
  58. // Returns: NO_ERROR - success
  59. // non-zero return code - failure
  60. //
  61. // Description: RasCpBegin entry point called by the PPP engine thru the
  62. // passed address. See RasCp interface documentation. This is
  63. // called by the PPP engine before any other calls to CbCP is
  64. // made.
  65. //
  66. DWORD
  67. CbCPBegin(
  68. OUT VOID** ppWorkBuf,
  69. IN VOID* pInfo
  70. )
  71. {
  72. PPPCB_INPUT * pInput = (PPPCB_INPUT *)pInfo;
  73. CBCP_WORKBUFFER * pWorkBuf;
  74. DWORD dwRetCode;
  75. //
  76. // Allocate work buffer.
  77. //
  78. pWorkBuf = (CBCP_WORKBUFFER *)LocalAlloc(LPTR,sizeof(CBCP_WORKBUFFER));
  79. if ( pWorkBuf == NULL )
  80. {
  81. return( GetLastError() );
  82. }
  83. pWorkBuf->State = CBCP_STATE_INITIAL;
  84. pWorkBuf->fServer = pInput->fServer;
  85. //
  86. // If we are the server side then get all the callback information for
  87. // this user
  88. //
  89. if ( pWorkBuf->fServer )
  90. {
  91. pWorkBuf->fCallbackPrivilege = pInput->bfCallbackPrivilege;
  92. strcpy( pWorkBuf->szCallbackNumber, pInput->pszCallbackNumber );
  93. }
  94. else
  95. {
  96. pWorkBuf->CallbackDelay = pInput->CallbackDelay;
  97. }
  98. //
  99. // Register work buffer with engine.
  100. //
  101. *ppWorkBuf = pWorkBuf;
  102. return( NO_ERROR );
  103. }
  104. //**
  105. //
  106. // Call: CbCPEnd
  107. //
  108. // Returns: NO_ERROR - success
  109. //
  110. // Description: Called by the PPP engine to notify this Control Protocol to
  111. // clean up.
  112. //
  113. DWORD
  114. CbCPEnd(
  115. IN VOID* pWorkBuffer
  116. )
  117. {
  118. CBCP_WORKBUFFER * pWorkBuf = (CBCP_WORKBUFFER *)pWorkBuffer;
  119. if ( pWorkBuf->pRequest != (PPP_CONFIG *)NULL )
  120. {
  121. LocalFree( pWorkBuf->pRequest );
  122. }
  123. if ( pWorkBuf->pResponse != (PPP_CONFIG *)NULL )
  124. {
  125. LocalFree( pWorkBuf->pResponse );
  126. }
  127. if ( pWorkBuf != NULL )
  128. {
  129. LocalFree( pWorkBuf );
  130. }
  131. return( NO_ERROR );
  132. }
  133. //**
  134. //
  135. // Call: CbCPMakeMessage
  136. //
  137. // Returns: NO_ERROR - success
  138. // non-zero return code - failure
  139. //
  140. // Description: Called by the PPP engine to process a CbCP event. ie to send
  141. // a packet, to process a received packet or to process a timeout
  142. // event.
  143. //
  144. DWORD
  145. CbCPMakeMessage(
  146. IN VOID* pWorkBuffer,
  147. IN PPP_CONFIG* pReceiveBuf,
  148. OUT PPP_CONFIG* pSendBuf,
  149. IN DWORD cbSendBuf,
  150. OUT PPPAP_RESULT* pResult,
  151. IN PPPAP_INPUT* pInput
  152. )
  153. {
  154. CBCP_WORKBUFFER* pWorkBuf = (CBCP_WORKBUFFER *)pWorkBuffer;
  155. return( (pWorkBuf->fServer)
  156. ? CbCPSMakeMessage( pWorkBuf,
  157. pReceiveBuf,
  158. pSendBuf,
  159. cbSendBuf,
  160. (PPPCB_RESULT *)pResult,
  161. (PPPCB_INPUT *)pInput )
  162. : CbCPCMakeMessage( pWorkBuf,
  163. pReceiveBuf,
  164. pSendBuf,
  165. cbSendBuf,
  166. (PPPCB_RESULT *)pResult,
  167. (PPPCB_INPUT *)pInput ) );
  168. }
  169. //**
  170. //
  171. // Call: CbCPCMakeMessage
  172. //
  173. // Returns: NO_ERROR - success
  174. // non-zero return - failure
  175. //
  176. // Description: Called to process the client side of Callback Control
  177. // Protocol.
  178. //
  179. DWORD
  180. CbCPCMakeMessage(
  181. IN CBCP_WORKBUFFER * pWorkBuf,
  182. IN PPP_CONFIG* pReceiveBuf,
  183. OUT PPP_CONFIG* pSendBuf,
  184. IN DWORD cbSendBuf,
  185. OUT PPPCB_RESULT* pResult,
  186. IN PPPCB_INPUT* pInput
  187. )
  188. {
  189. DWORD dwRetCode;
  190. DWORD dwLength;
  191. switch( pWorkBuf->State )
  192. {
  193. case CBCP_STATE_INITIAL:
  194. //
  195. // Do nothing, wait for request
  196. //
  197. pWorkBuf->State = CBCP_STATE_WAIT_FOR_REQUEST;
  198. pResult->Action = APA_NoAction;
  199. pResult->fGetCallbackNumberFromUser = FALSE;
  200. break;
  201. case CBCP_STATE_WAIT_FOR_REQUEST:
  202. //
  203. // We have received a callback request from the server.
  204. // Save the callback request.
  205. //
  206. dwLength = WireToHostFormat16( pReceiveBuf->Length );
  207. if ( ( dwLength < PPP_CONFIG_HDR_LEN ) ||
  208. ( pReceiveBuf->Code != CBCP_CODE_Request ) )
  209. {
  210. return( ERROR_PPP_INVALID_PACKET );
  211. }
  212. pWorkBuf->pRequest = (PPP_CONFIG *)LocalAlloc( LPTR, dwLength );
  213. if ( pWorkBuf->pRequest == (PPP_CONFIG *)NULL )
  214. {
  215. return( GetLastError() );
  216. }
  217. memcpy( pWorkBuf->pRequest, pReceiveBuf, dwLength );
  218. //
  219. // Find out what kind of callback privileges we have.
  220. //
  221. dwRetCode = GetCallbackPrivilegeFromRequest(
  222. pWorkBuf->pRequest,
  223. &(pWorkBuf->fCallbackPrivilege));
  224. if ( dwRetCode != NO_ERROR )
  225. {
  226. return( dwRetCode );
  227. }
  228. //
  229. // If we have user specifiable callback, then we need to get this
  230. // information from the user.
  231. //
  232. if ( pWorkBuf->fCallbackPrivilege == RASPRIV_CallerSetCallback )
  233. {
  234. pResult->fGetCallbackNumberFromUser=TRUE;
  235. pResult->Action =APA_NoAction;
  236. pWorkBuf->State =CBCP_STATE_GET_CALLBACK_NUMBER;
  237. break;
  238. }
  239. //
  240. // Otherwise we make a reponse with preset or no callback
  241. //
  242. dwRetCode = MakeResponse( pWorkBuf->fCallbackPrivilege,
  243. (LPSTR)NULL,
  244. pWorkBuf->CallbackDelay,
  245. pWorkBuf->pRequest,
  246. pSendBuf,
  247. cbSendBuf );
  248. if ( dwRetCode != NO_ERROR )
  249. {
  250. return( dwRetCode );
  251. }
  252. //
  253. // Save the response sent
  254. //
  255. dwLength = WireToHostFormat16( pSendBuf->Length );
  256. pWorkBuf->pResponse = (PPP_CONFIG *)LocalAlloc( LPTR, dwLength );
  257. if ( pWorkBuf->pResponse == (PPP_CONFIG *)NULL )
  258. {
  259. return( GetLastError() );
  260. }
  261. memcpy( pWorkBuf->pResponse, pSendBuf, dwLength );
  262. pResult->Action = APA_SendWithTimeout;
  263. pResult->bIdExpected = pReceiveBuf->Id;
  264. pWorkBuf->State = CBCP_STATE_WAIT_FOR_ACK;
  265. break;
  266. case CBCP_STATE_GET_CALLBACK_NUMBER:
  267. //
  268. // If we have not received any packet when we are called that means
  269. // that we have got the callback number from the user.
  270. //
  271. if ( pReceiveBuf == (PPP_CONFIG *)NULL )
  272. {
  273. //
  274. // If no callback number was supplied then we do not want to
  275. // do callback
  276. //
  277. if ( *(pInput->pszCallbackNumber) == (CHAR)NULL )
  278. {
  279. pWorkBuf->fCallbackPrivilege = RASPRIV_NoCallback;
  280. }
  281. dwRetCode = MakeResponse( pWorkBuf->fCallbackPrivilege,
  282. pInput->pszCallbackNumber,
  283. pWorkBuf->CallbackDelay,
  284. pWorkBuf->pRequest,
  285. pSendBuf,
  286. cbSendBuf );
  287. if ( dwRetCode != NO_ERROR )
  288. {
  289. return( dwRetCode );
  290. }
  291. //
  292. // Save the response sent
  293. //
  294. dwLength = WireToHostFormat16( pSendBuf->Length );
  295. pWorkBuf->pResponse = (PPP_CONFIG*)LocalAlloc( LPTR, dwLength );
  296. if ( pWorkBuf->pResponse == NULL )
  297. {
  298. return( GetLastError() );
  299. }
  300. memcpy( pWorkBuf->pResponse, pSendBuf, dwLength );
  301. pResult->Action = APA_SendWithTimeout;
  302. pResult->bIdExpected = pWorkBuf->pResponse->Id;
  303. pWorkBuf->State = CBCP_STATE_WAIT_FOR_ACK;
  304. break;
  305. }
  306. else
  307. {
  308. if ( pReceiveBuf->Code == CBCP_CODE_Request )
  309. {
  310. //
  311. // If we received another callback request, just save the id.
  312. // If the current request is different than the previous one
  313. //
  314. dwLength = WireToHostFormat16( pWorkBuf->pRequest->Length );
  315. if (( WireToHostFormat16( pReceiveBuf->Length ) != dwLength ) ||
  316. ( memcmp( ((PBYTE)(pWorkBuf->pRequest))+PPP_CONFIG_HDR_LEN,
  317. ((PBYTE)pReceiveBuf) + PPP_CONFIG_HDR_LEN,
  318. dwLength - PPP_CONFIG_HDR_LEN ) ) )
  319. {
  320. return( ERROR_PPP_INVALID_PACKET );
  321. }
  322. pWorkBuf->pRequest->Id = pReceiveBuf->Id;
  323. }
  324. else
  325. {
  326. return( ERROR_PPP_INVALID_PACKET );
  327. }
  328. }
  329. pResult->Action = APA_NoAction;
  330. pResult->fGetCallbackNumberFromUser = FALSE;
  331. break;
  332. case CBCP_STATE_WAIT_FOR_ACK:
  333. //
  334. // If the receive buffer is NULL, then we have a timeout event,
  335. // resend the response
  336. //
  337. if ( pReceiveBuf == (PPP_CONFIG *)NULL )
  338. {
  339. dwLength = WireToHostFormat16( pWorkBuf->pResponse->Length );
  340. if ( dwLength > cbSendBuf )
  341. {
  342. return( ERROR_BUFFER_TOO_SMALL );
  343. }
  344. memcpy( pSendBuf, pWorkBuf->pResponse, dwLength );
  345. pResult->Action = APA_SendWithTimeout;
  346. break;
  347. }
  348. //
  349. // If we received another request then simply respond with
  350. // the same response except change the id.
  351. //
  352. if ( pReceiveBuf->Code == CBCP_CODE_Request )
  353. {
  354. //
  355. // If the current request is different than the previous one
  356. //
  357. dwLength = WireToHostFormat16( pWorkBuf->pRequest->Length );
  358. if ( ( WireToHostFormat16( pReceiveBuf->Length ) != dwLength ) ||
  359. ( memcmp( ((PBYTE)(pWorkBuf->pRequest)) + PPP_CONFIG_HDR_LEN,
  360. ((PBYTE)pReceiveBuf) + PPP_CONFIG_HDR_LEN,
  361. dwLength - PPP_CONFIG_HDR_LEN ) ) )
  362. {
  363. return( ERROR_PPP_INVALID_PACKET );
  364. }
  365. if ( dwLength > cbSendBuf )
  366. {
  367. return( ERROR_BUFFER_TOO_SMALL );
  368. }
  369. pWorkBuf->pRequest->Id = pReceiveBuf->Id;
  370. pWorkBuf->pResponse->Id = pReceiveBuf->Id;
  371. pResult->bIdExpected = pReceiveBuf->Id;
  372. pResult->Action = APA_SendWithTimeout;
  373. memcpy( pSendBuf,
  374. pWorkBuf->pResponse,
  375. WireToHostFormat16( pWorkBuf->pResponse->Length ) );
  376. break;
  377. }
  378. //
  379. // If this is an ACK, then validate it and then prepare for callback
  380. //
  381. if ( pReceiveBuf->Code == CBCP_CODE_Ack )
  382. {
  383. dwLength = WireToHostFormat16( pWorkBuf->pResponse->Length );
  384. if ( ( WireToHostFormat16( pReceiveBuf->Length ) != dwLength ) ||
  385. ( memcmp( ((PBYTE)(pWorkBuf->pResponse)) + PPP_CONFIG_HDR_LEN,
  386. ((PBYTE)pReceiveBuf) + PPP_CONFIG_HDR_LEN,
  387. dwLength - PPP_CONFIG_HDR_LEN ) ) )
  388. {
  389. //
  390. // If this Ack is invalid then we resend the response.
  391. //
  392. dwLength = WireToHostFormat16( pWorkBuf->pResponse->Length );
  393. if ( dwLength > cbSendBuf )
  394. {
  395. return( ERROR_BUFFER_TOO_SMALL );
  396. }
  397. memcpy( pSendBuf, pWorkBuf->pResponse, dwLength );
  398. pResult->Action = APA_SendWithTimeout;
  399. break;
  400. }
  401. //
  402. // We are done
  403. //
  404. pResult->Action = APA_Done;
  405. pResult->bfCallbackPrivilege = (BYTE)(pWorkBuf->fCallbackPrivilege);
  406. break;
  407. }
  408. else
  409. {
  410. return( ERROR_PPP_INVALID_PACKET );
  411. }
  412. //
  413. // Fall through
  414. //
  415. default:
  416. pResult->Action = APA_NoAction;
  417. pResult->fGetCallbackNumberFromUser = FALSE;
  418. break;
  419. }
  420. return( NO_ERROR );
  421. }
  422. //**
  423. //
  424. // Call: CbCPSMakeMessage
  425. //
  426. // Returns: NO_ERROR - success
  427. // non-zero return - failure
  428. //
  429. // Description: Will be called to process and server side Callback Control
  430. // Protocol event.
  431. //
  432. DWORD
  433. CbCPSMakeMessage(
  434. IN CBCP_WORKBUFFER * pWorkBuf,
  435. IN PPP_CONFIG* pReceiveBuf,
  436. OUT PPP_CONFIG* pSendBuf,
  437. IN DWORD cbSendBuf,
  438. OUT PPPCB_RESULT* pResult,
  439. IN PPPCB_INPUT* pInput
  440. )
  441. {
  442. DWORD dwRetCode;
  443. DWORD dwLength;
  444. switch( pWorkBuf->State )
  445. {
  446. case CBCP_STATE_INITIAL:
  447. //
  448. // Make the request based on the user's callback privelege
  449. //
  450. dwRetCode = MakeRequest( pWorkBuf->fCallbackPrivilege,
  451. pSendBuf,
  452. cbSendBuf );
  453. if ( dwRetCode != NO_ERROR )
  454. {
  455. return( dwRetCode );
  456. }
  457. //
  458. // Set the Id of the first request to 1
  459. //
  460. pSendBuf->Id = 1;
  461. //
  462. // Save the request
  463. //
  464. dwLength = WireToHostFormat16( pSendBuf->Length );
  465. pWorkBuf->pRequest = (PPP_CONFIG *)LocalAlloc( LPTR, dwLength );
  466. if ( pWorkBuf->pRequest == (PPP_CONFIG *)NULL )
  467. {
  468. return( GetLastError() );
  469. }
  470. memcpy( pWorkBuf->pRequest, pSendBuf, dwLength );
  471. pResult->Action = APA_SendWithTimeout2;
  472. pResult->bIdExpected = pWorkBuf->pRequest->Id;
  473. pWorkBuf->State = CBCP_STATE_WAIT_FOR_RESPONSE;
  474. break;
  475. case CBCP_STATE_WAIT_FOR_RESPONSE:
  476. //
  477. // If the Receive buffer is NULL that means that we got a timeout.
  478. // So resend the request.
  479. //
  480. if ( pReceiveBuf == (PPP_CONFIG *)NULL )
  481. {
  482. dwLength = WireToHostFormat16( pWorkBuf->pRequest->Length );
  483. if ( cbSendBuf < dwLength )
  484. {
  485. return( ERROR_BUFFER_TOO_SMALL );
  486. }
  487. //
  488. // Increment the request id
  489. //
  490. (pWorkBuf->pRequest->Id)++;
  491. memcpy( pSendBuf, pWorkBuf->pRequest, dwLength );
  492. pResult->Action = APA_SendWithTimeout2;
  493. pResult->bIdExpected = pWorkBuf->pRequest->Id;
  494. pWorkBuf->State = CBCP_STATE_WAIT_FOR_RESPONSE;
  495. break;
  496. }
  497. //
  498. // Fall through
  499. //
  500. case CBCP_STATE_DONE:
  501. if ( pReceiveBuf == NULL )
  502. {
  503. //
  504. // If we receive a timeout in the DONE state, we just ignore it.
  505. //
  506. pResult->Action = APA_NoAction;
  507. break;
  508. }
  509. //
  510. // If we have received a response from the client, then validate
  511. // it and send an ACK or another request.
  512. //
  513. if ( pReceiveBuf->Code == CBCP_CODE_Response )
  514. {
  515. //
  516. // Check the id of the response packet. If the Id is bad then
  517. // silently discard it
  518. //
  519. if ( pReceiveBuf->Id != pWorkBuf->pRequest->Id )
  520. {
  521. return( ERROR_PPP_INVALID_PACKET );
  522. }
  523. dwRetCode = ValidateResponse( pReceiveBuf, pWorkBuf );
  524. if ( dwRetCode == ERROR_PPP_INVALID_PACKET )
  525. {
  526. //
  527. // If the response received was invalid, resend the request
  528. //
  529. dwLength = WireToHostFormat16( pWorkBuf->pRequest->Length );
  530. if ( cbSendBuf < dwLength )
  531. {
  532. return( ERROR_BUFFER_TOO_SMALL );
  533. }
  534. //
  535. // Increment the request id
  536. //
  537. (pWorkBuf->pRequest->Id)++;
  538. memcpy( pSendBuf, pWorkBuf->pRequest, dwLength );
  539. pResult->Action = APA_SendWithTimeout2;
  540. pResult->bIdExpected = pWorkBuf->pRequest->Id;
  541. pWorkBuf->State = CBCP_STATE_WAIT_FOR_RESPONSE;
  542. break;
  543. }
  544. else if ( dwRetCode != NO_ERROR )
  545. {
  546. return( dwRetCode );
  547. }
  548. //
  549. // Send the Ack
  550. //
  551. dwLength = WireToHostFormat16( pReceiveBuf->Length );
  552. if ( cbSendBuf < dwLength )
  553. {
  554. return( ERROR_BUFFER_TOO_SMALL );
  555. }
  556. memcpy( pSendBuf, pReceiveBuf, dwLength );
  557. pSendBuf->Code = CBCP_CODE_Ack;
  558. pSendBuf->Id = pReceiveBuf->Id;
  559. pWorkBuf->State = CBCP_STATE_DONE;
  560. pResult->Action = APA_SendAndDone;
  561. pResult->bfCallbackPrivilege = (BYTE)(pWorkBuf->fCallbackPrivilege);
  562. pResult->CallbackDelay = pWorkBuf->CallbackDelay;
  563. strcpy( pResult->szCallbackNumber, pWorkBuf->szCallbackNumber );
  564. }
  565. else
  566. {
  567. return( ERROR_PPP_INVALID_PACKET );
  568. }
  569. break;
  570. default:
  571. break;
  572. }
  573. return( NO_ERROR );
  574. }
  575. //**
  576. //
  577. // Call: MakeRequest
  578. //
  579. // Returns: NO_ERROR - success
  580. // ERROR_BUFFER_TOO_SMALL - failure
  581. //
  582. // Description: Will make a callback request packet based on the user's
  583. // callback privilege. The Id will be filled in by the caller.
  584. //
  585. static DWORD
  586. MakeRequest(
  587. IN DWORD fCallbackPrivilege,
  588. IN OUT PPP_CONFIG * pSendBuf,
  589. IN DWORD cbSendBuf
  590. )
  591. {
  592. PPP_OPTION * pOption;
  593. DWORD dwLength = PPP_CONFIG_HDR_LEN;
  594. if ( cbSendBuf < PPP_CONFIG_HDR_LEN )
  595. {
  596. return( ERROR_BUFFER_TOO_SMALL );
  597. }
  598. pOption = (PPP_OPTION *)(pSendBuf->Data);
  599. pSendBuf->Code = CBCP_CODE_Request;
  600. if ( ( fCallbackPrivilege & RASPRIV_NoCallback ) ||
  601. ( fCallbackPrivilege & RASPRIV_CallerSetCallback ) )
  602. {
  603. if ( cbSendBuf < dwLength + PPP_OPTION_HDR_LEN )
  604. {
  605. return( ERROR_BUFFER_TOO_SMALL );
  606. }
  607. pOption->Type = CBCP_TYPE_NO_CALLBACK;
  608. pOption->Length = PPP_OPTION_HDR_LEN;
  609. dwLength += pOption->Length;
  610. pOption = (PPP_OPTION *)(((BYTE *)pOption) + pOption->Length);
  611. }
  612. if ( fCallbackPrivilege & RASPRIV_CallerSetCallback )
  613. {
  614. if ( cbSendBuf < dwLength + PPP_OPTION_HDR_LEN + 2 )
  615. {
  616. return( ERROR_BUFFER_TOO_SMALL );
  617. }
  618. pOption->Type = CBCP_TYPE_CALLER_SET;
  619. pOption->Length = PPP_OPTION_HDR_LEN + 3;
  620. *(pOption->Data) = 0; // Callback Delay
  621. *(pOption->Data+1) = CBCP_PSTN_NUMBER; // Callback Address type
  622. *(pOption->Data+2) = 0; // Callback Address terminating NULL
  623. dwLength += pOption->Length;
  624. pOption = (PPP_OPTION *)(((BYTE *)pOption) + pOption->Length);
  625. }
  626. if ( fCallbackPrivilege & RASPRIV_AdminSetCallback )
  627. {
  628. if ( cbSendBuf < dwLength + PPP_OPTION_HDR_LEN + 1)
  629. {
  630. return( ERROR_BUFFER_TOO_SMALL );
  631. }
  632. pOption->Type = CBCP_TYPE_CALLEE_SET;
  633. pOption->Length = PPP_OPTION_HDR_LEN + 1;
  634. *(pOption->Data) = 0; // Callback Delay
  635. dwLength += pOption->Length;
  636. }
  637. HostToWireFormat16( (WORD)dwLength, (PBYTE)(pSendBuf->Length) );
  638. return( NO_ERROR );
  639. }
  640. //**
  641. //
  642. // Call: GetCallbackPrivilegeFromRequest
  643. //
  644. // Returns: NO_ERROR - success
  645. //
  646. // Description: Will parse the callback request from the server and translate
  647. // the PPP callback privilege to what RAS understands.
  648. //
  649. DWORD
  650. GetCallbackPrivilegeFromRequest(
  651. IN PPP_CONFIG * pRequest,
  652. IN OUT DWORD * lpdwCallbackPriv
  653. )
  654. {
  655. PPP_OPTION * pOption = (PPP_OPTION *)(pRequest->Data);
  656. DWORD dwRequestLength = WireToHostFormat16( pRequest->Length )
  657. - PPP_CONFIG_HDR_LEN;
  658. *lpdwCallbackPriv = 0;
  659. //
  660. // Walk the options
  661. //
  662. while( dwRequestLength > 0 )
  663. {
  664. if ( dwRequestLength < PPP_OPTION_HDR_LEN )
  665. {
  666. return( ERROR_PPP_INVALID_PACKET );
  667. }
  668. switch( pOption->Type )
  669. {
  670. case CBCP_TYPE_NO_CALLBACK:
  671. *lpdwCallbackPriv |= RASPRIV_NoCallback;
  672. break;
  673. case CBCP_TYPE_CALLEE_SET:
  674. *lpdwCallbackPriv |= RASPRIV_AdminSetCallback;
  675. break;
  676. case CBCP_TYPE_CALLER_SET:
  677. *lpdwCallbackPriv |= RASPRIV_CallerSetCallback;
  678. break;
  679. default:
  680. //
  681. // Ignore anything else.
  682. //
  683. break;
  684. }
  685. dwRequestLength = dwRequestLength - pOption->Length;
  686. pOption = (PPP_OPTION *)(((BYTE *)pOption) + pOption->Length);
  687. }
  688. //
  689. // We accept Callback privleges in the following order.
  690. // 1) Caller settable.
  691. // 2) Admin settable
  692. // 3) No callback
  693. //
  694. if ( *lpdwCallbackPriv & RASPRIV_CallerSetCallback )
  695. {
  696. *lpdwCallbackPriv = RASPRIV_CallerSetCallback;
  697. }
  698. else if ( *lpdwCallbackPriv & RASPRIV_AdminSetCallback )
  699. {
  700. *lpdwCallbackPriv = RASPRIV_AdminSetCallback;
  701. }
  702. else if ( *lpdwCallbackPriv & RASPRIV_NoCallback )
  703. {
  704. *lpdwCallbackPriv = RASPRIV_NoCallback;
  705. }
  706. else
  707. {
  708. //
  709. // If we could not translate to any RAS callback privlege we simply drop
  710. // this packet.
  711. //
  712. return( ERROR_PPP_INVALID_PACKET );
  713. }
  714. return( NO_ERROR );
  715. }
  716. //**
  717. //
  718. // Call: MakeResponse
  719. //
  720. // Returns: NO_ERROR - success
  721. //
  722. // Description:
  723. //
  724. DWORD
  725. MakeResponse(
  726. IN DWORD fCallbackPrivilege,
  727. IN LPSTR szCallbackNumber,
  728. IN DWORD CallbackDelay,
  729. IN PPP_CONFIG * pRequest,
  730. IN OUT PPP_CONFIG * pSendBuf,
  731. IN DWORD cbSendBuf
  732. )
  733. {
  734. PPP_OPTION * pOption;
  735. DWORD dwLength;
  736. if ( cbSendBuf < PPP_CONFIG_HDR_LEN )
  737. {
  738. return( ERROR_BUFFER_TOO_SMALL );
  739. }
  740. pOption = (PPP_OPTION *)(pSendBuf->Data);
  741. pSendBuf->Code = CBCP_CODE_Response;
  742. pSendBuf->Id = pRequest->Id;
  743. if ( fCallbackPrivilege & RASPRIV_NoCallback )
  744. {
  745. dwLength = PPP_OPTION_HDR_LEN;
  746. if ( cbSendBuf < dwLength )
  747. {
  748. return( ERROR_BUFFER_TOO_SMALL );
  749. }
  750. pOption->Type = CBCP_TYPE_NO_CALLBACK;
  751. pOption->Length = (BYTE)dwLength;
  752. }
  753. else if ( fCallbackPrivilege & RASPRIV_CallerSetCallback )
  754. {
  755. dwLength = (DWORD)(PPP_OPTION_HDR_LEN + 3 + strlen( szCallbackNumber ));
  756. if ( cbSendBuf < dwLength )
  757. {
  758. return( ERROR_BUFFER_TOO_SMALL );
  759. }
  760. pOption->Type = CBCP_TYPE_CALLER_SET;
  761. pOption->Length = (BYTE)dwLength;
  762. *(pOption->Data) = (BYTE)CallbackDelay; // Callback Delay
  763. *(pOption->Data+1) = (BYTE)CBCP_PSTN_NUMBER; // Number Type
  764. strcpy( pOption->Data+2, szCallbackNumber ); // Callback Address
  765. }
  766. else if ( fCallbackPrivilege & RASPRIV_AdminSetCallback )
  767. {
  768. dwLength = PPP_OPTION_HDR_LEN + 1;
  769. if ( cbSendBuf < dwLength )
  770. {
  771. return( ERROR_BUFFER_TOO_SMALL );
  772. }
  773. pOption->Type = CBCP_TYPE_CALLEE_SET;
  774. pOption->Length = (BYTE)dwLength;
  775. *(pOption->Data)= (BYTE)CallbackDelay; // Callback Delay
  776. }
  777. else
  778. {
  779. return( ERROR_INVALID_PARAMETER );
  780. }
  781. dwLength += PPP_CONFIG_HDR_LEN;
  782. HostToWireFormat16( (WORD)dwLength, (PBYTE)(pSendBuf->Length) );
  783. return( NO_ERROR );
  784. }
  785. //**
  786. //
  787. // Call: ValidateResponse
  788. //
  789. // Returns: NO_ERROR - success
  790. // ERROR_PPP_INVALID_PACKET - failure
  791. //
  792. // Description: Will validate the reponse from the client. If the response
  793. // is valid, then the callback information is returned in the
  794. // CbCPWorkBuf.
  795. //
  796. DWORD
  797. ValidateResponse(
  798. IN PPP_CONFIG * pReceiveBuf,
  799. IN CBCP_WORKBUFFER * pWorkBuf
  800. )
  801. {
  802. PPP_OPTION * pOption = (PPP_OPTION *)(pReceiveBuf->Data);
  803. if ( WireToHostFormat16( pReceiveBuf->Length ) !=
  804. pOption->Length + PPP_CONFIG_HDR_LEN )
  805. {
  806. return( ERROR_PPP_INVALID_PACKET );
  807. }
  808. switch( pOption->Type )
  809. {
  810. case CBCP_TYPE_NO_CALLBACK:
  811. if ( !( ( pWorkBuf->fCallbackPrivilege & RASPRIV_NoCallback ) ||
  812. ( pWorkBuf->fCallbackPrivilege & RASPRIV_CallerSetCallback ) ) )
  813. {
  814. return( ERROR_PPP_INVALID_PACKET );
  815. }
  816. pWorkBuf->fCallbackPrivilege = RASPRIV_NoCallback;
  817. break;
  818. case CBCP_TYPE_CALLEE_SET:
  819. if ( !(pWorkBuf->fCallbackPrivilege & RASPRIV_AdminSetCallback) )
  820. {
  821. return( ERROR_PPP_INVALID_PACKET );
  822. }
  823. pWorkBuf->fCallbackPrivilege = RASPRIV_AdminSetCallback;
  824. pWorkBuf->CallbackDelay = *(pOption->Data);
  825. break;
  826. case CBCP_TYPE_CALLER_SET:
  827. if ( !(pWorkBuf->fCallbackPrivilege & RASPRIV_CallerSetCallback) )
  828. {
  829. return( ERROR_PPP_INVALID_PACKET );
  830. }
  831. pWorkBuf->fCallbackPrivilege = RASPRIV_CallerSetCallback;
  832. pWorkBuf->CallbackDelay = *(pOption->Data);
  833. if ( strlen( pWorkBuf->szCallbackNumber ) <= MAX_CALLBACKNUMBER_SIZE )
  834. {
  835. strcpy( pWorkBuf->szCallbackNumber, pOption->Data+2 );
  836. }
  837. else
  838. {
  839. return( ERROR_PPP_INVALID_PACKET );
  840. }
  841. break;
  842. default:
  843. return( ERROR_PPP_INVALID_PACKET );
  844. break;
  845. }
  846. return( NO_ERROR );
  847. }