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.

756 lines
17 KiB

  1. /*******************************************************************/
  2. /* Copyright(c) 1996 Microsoft Corporation */
  3. /*******************************************************************/
  4. //***
  5. //
  6. // Filename: arapif.c
  7. //
  8. // Description: This module contains the procedures for the
  9. // DDM-Arap interface
  10. //
  11. // Author: Shirish Koti Sep 9, 1996
  12. //
  13. // Revision History:
  14. //
  15. //***
  16. #include "ddm.h"
  17. #include "util.h"
  18. #include "isdn.h"
  19. #include "objects.h"
  20. #include "rasmanif.h"
  21. #include "handlers.h"
  22. #include <ddmif.h>
  23. #include "arapif.h"
  24. #include <timer.h>
  25. #include <ctype.h>
  26. #include <memory.h>
  27. #include <string.h>
  28. //
  29. // prototypes for functions used in this file
  30. //
  31. VOID
  32. ArapDDMAuthenticated(
  33. IN PDEVICE_OBJECT pDeviceObj,
  34. IN ARAPDDM_AUTH_RESULT * pAuthResult
  35. );
  36. VOID
  37. ArapDDMCallbackRequest(
  38. IN PDEVICE_OBJECT pDeviceObj,
  39. IN ARAPDDM_CALLBACK_REQUEST *pCbReq
  40. );
  41. VOID
  42. ArapDDMDone(
  43. IN PDEVICE_OBJECT pDeviceObj,
  44. IN DWORD NetAddress,
  45. IN DWORD SessTimeOut
  46. );
  47. VOID
  48. ArapDDMFailure(
  49. IN PDEVICE_OBJECT pDeviceObj,
  50. IN ARAPDDM_DISCONNECT *pFailInfo
  51. );
  52. VOID
  53. ArapDDMTimeOut(
  54. IN HANDLE hObject
  55. );
  56. //***
  57. //
  58. // Function: ArapEventHandler
  59. // Waits for a message from Arap and depending on the message
  60. // type, executes the appropriate routine Loads Arap.dll and
  61. // gets all the entry points
  62. //
  63. // Parameters: None
  64. //
  65. // Return: Nothing
  66. //
  67. //
  68. //***$
  69. VOID
  70. ArapEventHandler(
  71. IN VOID
  72. )
  73. {
  74. ARAP_MESSAGE ArapMsg;
  75. PDEVICE_OBJECT pDevObj;
  76. LPWSTR portnamep;
  77. //
  78. // loop to get all messages
  79. //
  80. while( ServerReceiveMessage( MESSAGEQ_ID_ARAP, (BYTE *)&ArapMsg) )
  81. {
  82. EnterCriticalSection( &(gblDeviceTable.CriticalSection) );
  83. //
  84. // identify the message recipient
  85. //
  86. if ( ( pDevObj = DeviceObjGetPointer( ArapMsg.hPort ) ) == NULL )
  87. {
  88. LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
  89. return;
  90. }
  91. //
  92. // action on the message type
  93. //
  94. switch( ArapMsg.dwMsgId )
  95. {
  96. case ARAPDDMMSG_Authenticated:
  97. ArapDDMAuthenticated(
  98. pDevObj,
  99. &ArapMsg.ExtraInfo.AuthResult);
  100. break;
  101. case ARAPDDMMSG_CallbackRequest:
  102. ArapDDMCallbackRequest(
  103. pDevObj,
  104. &ArapMsg.ExtraInfo.CallbackRequest);
  105. break;
  106. case ARAPDDMMSG_Done:
  107. pDevObj->fFlags &= (~DEV_OBJ_AUTH_ACTIVE);
  108. ArapDDMDone(pDevObj,
  109. ArapMsg.ExtraInfo.Done.NetAddress,
  110. ArapMsg.ExtraInfo.Done.SessTimeOut);
  111. break;
  112. case ARAPDDMMSG_Inactive:
  113. //
  114. // Client has been inactive on all protocols for time
  115. // specified in the registry. We disconnect the client.
  116. //
  117. portnamep = pDevObj->wchPortName;
  118. DDMLogInformation( ROUTERLOG_AUTODISCONNECT, 1, &portnamep );
  119. // break intentionally omitted here
  120. case ARAPDDMMSG_Disconnected:
  121. // in case we had this puppy sitting in the timer queue
  122. TimerQRemove( (HANDLE)pDevObj->hPort, ArapDDMTimeOut);
  123. DevStartClosing(pDevObj);
  124. break;
  125. case ARAPDDMMSG_Failure:
  126. pDevObj->fFlags &= (~DEV_OBJ_AUTH_ACTIVE);
  127. ArapDDMFailure(pDevObj, &ArapMsg.ExtraInfo.FailureInfo);
  128. break;
  129. default:
  130. RTASSERT(FALSE);
  131. break;
  132. }
  133. LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
  134. }
  135. }
  136. //***
  137. //
  138. // Function: ArapDDMAuthenticated
  139. // Retrieves username and domain from the message and stores it
  140. // in the dcb.
  141. //
  142. // Parameters: pDeviceObj - the dcb for this connection
  143. // pAuthResult - info for the user who is authenticated
  144. //
  145. // Return: Nothing
  146. //
  147. //
  148. //***$
  149. VOID
  150. ArapDDMAuthenticated(
  151. IN PDEVICE_OBJECT pDeviceObj,
  152. IN ARAPDDM_AUTH_RESULT * pAuthResult
  153. )
  154. {
  155. DWORD dwRetCode;
  156. WCHAR wchUserName[UNLEN+1];
  157. PCONNECTION_OBJECT pConnObj;
  158. DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  159. "ArapDDMAuthenticated: Entered, hPort=%d", pDeviceObj->hPort);
  160. if ( pDeviceObj->DeviceState != DEV_OBJ_AUTH_IS_ACTIVE )
  161. {
  162. return;
  163. }
  164. pConnObj = ConnObjGetPointer( pDeviceObj->hConnection );
  165. RTASSERT( pConnObj != NULL );
  166. // this shouldn't happen, but if it does, just ignore this call
  167. if (pConnObj == NULL)
  168. {
  169. return;
  170. }
  171. //
  172. // Stop authentication timer
  173. //
  174. TimerQRemove( (HANDLE)pDeviceObj->hPort, SvAuthTimeout );
  175. //
  176. // devObj: copy the user name, domain name
  177. //
  178. if ( wcslen( pAuthResult->wchUserName ) > 0 )
  179. {
  180. wcscpy(wchUserName, pAuthResult->wchUserName);
  181. }
  182. else
  183. {
  184. wcscpy( wchUserName, gblpszUnknown );
  185. }
  186. wcscpy( pDeviceObj->wchUserName, wchUserName );
  187. wcscpy( pDeviceObj->wchDomainName, pAuthResult->wchLogonDomain );
  188. //
  189. // connObj: copy the user name, domain name, etc.
  190. //
  191. wcscpy( pConnObj->wchUserName, wchUserName );
  192. wcscpy( pConnObj->wchDomainName, pAuthResult->wchLogonDomain );
  193. wcscpy( pConnObj->wchInterfaceName, pDeviceObj->wchUserName );
  194. pConnObj->hPort = pDeviceObj->hPort;
  195. }
  196. //***
  197. //
  198. // Function: ArapDDMCallbackRequest
  199. // Disconnects the connection, setting it up for a callback
  200. //
  201. // Parameters: pDeviceObj - the dcb for this connection
  202. // pCbReq - call back info
  203. //
  204. // Return: Nothing
  205. //
  206. //
  207. //***$
  208. VOID
  209. ArapDDMCallbackRequest(
  210. IN PDEVICE_OBJECT pDeviceObj,
  211. IN ARAPDDM_CALLBACK_REQUEST *pCbReq
  212. )
  213. {
  214. DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  215. "ArapDDMCallbackRequest: Entered, hPort = %d\n",
  216. pDeviceObj->hPort);
  217. //
  218. // check the state
  219. //
  220. if (pDeviceObj->DeviceState != DEV_OBJ_AUTH_IS_ACTIVE)
  221. {
  222. return;
  223. }
  224. TimerQRemove( (HANDLE)pDeviceObj->hPort, SvAuthTimeout );
  225. //
  226. // copy relevant fields in our dcb
  227. //
  228. if (pCbReq->fUseCallbackDelay)
  229. {
  230. pDeviceObj->dwCallbackDelay = pCbReq->dwCallbackDelay;
  231. }
  232. else
  233. {
  234. pDeviceObj->dwCallbackDelay = gblDDMConfigInfo.dwCallbackTime;
  235. }
  236. mbstowcs(pDeviceObj->wchCallbackNumber, pCbReq->szCallbackNumber,
  237. MAX_PHONE_NUMBER_LEN + 1 );
  238. //
  239. // Disconnect the line and change the state
  240. //
  241. pDeviceObj->DeviceState = DEV_OBJ_CALLBACK_DISCONNECTING;
  242. //
  243. // Wait to enable the client to get the message
  244. //
  245. TimerQRemove( (HANDLE)pDeviceObj->hPort, SvDiscTimeout );
  246. TimerQInsert( (HANDLE)pDeviceObj->hPort,
  247. DISC_TIMEOUT_CALLBACK, SvDiscTimeout );
  248. }
  249. //***
  250. //
  251. // Function: ArapDDMDone
  252. // Logs an event, marks the state
  253. //
  254. // Parameters: pDeviceObj - the dcb for this connection
  255. //
  256. // Return: Nothing
  257. //
  258. //
  259. //***$
  260. VOID
  261. ArapDDMDone(
  262. IN PDEVICE_OBJECT pDeviceObj,
  263. IN DWORD NetAddress,
  264. IN DWORD SessTimeOut
  265. )
  266. {
  267. LPWSTR lpstrAudit[2];
  268. PCONNECTION_OBJECT pConnObj;
  269. WCHAR wchFullUserName[UNLEN+DNLEN+2];
  270. ROUTER_INTERFACE_OBJECT * pIfObject;
  271. DWORD dwRetCode;
  272. DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  273. "ArapDDMDone: Entered, hPort=%d", pDeviceObj->hPort);
  274. if ( pDeviceObj->DeviceState != DEV_OBJ_AUTH_IS_ACTIVE )
  275. {
  276. return;
  277. }
  278. //
  279. // Get connection object for this connection
  280. //
  281. pConnObj = ConnObjGetPointer( pDeviceObj->hConnection );
  282. RTASSERT( pConnObj != NULL );
  283. // this shouldn't happen, but if it does, just ignore this call
  284. if (pConnObj == NULL)
  285. {
  286. return;
  287. }
  288. pConnObj->PppProjectionResult.at.dwError = NO_ERROR;
  289. pConnObj->PppProjectionResult.at.dwRemoteAddress = NetAddress;
  290. //
  291. // Create client interface object for this connection
  292. //
  293. pIfObject = IfObjectAllocateAndInit( pConnObj->wchUserName,
  294. RISTATE_CONNECTED,
  295. ROUTER_IF_TYPE_CLIENT,
  296. pConnObj->hConnection,
  297. TRUE,
  298. 0,
  299. 0,
  300. NULL );
  301. if ( pIfObject == (ROUTER_INTERFACE_OBJECT *)NULL )
  302. {
  303. //
  304. // Error log this and stop the connection.
  305. //
  306. DDMLogError( ROUTERLOG_NOT_ENOUGH_MEMORY, 1, NULL, GetLastError() );
  307. DevStartClosing( pDeviceObj );
  308. return;
  309. }
  310. //
  311. // Insert in table now
  312. //
  313. dwRetCode = IfObjectInsertInTable( pIfObject );
  314. if ( dwRetCode != NO_ERROR )
  315. {
  316. LOCAL_FREE( pIfObject );
  317. DDMLogError( ROUTERLOG_NOT_ENOUGH_MEMORY, 1, NULL, dwRetCode );
  318. DevStartClosing( pDeviceObj );
  319. return;
  320. }
  321. pConnObj->hDIMInterface = pIfObject->hDIMInterface;
  322. //
  323. // Reduce the media count for this device
  324. //
  325. if ( !(pDeviceObj->fFlags & DEV_OBJ_MARKED_AS_INUSE) )
  326. {
  327. if ( pDeviceObj->fFlags & DEV_OBJ_ALLOW_ROUTERS )
  328. {
  329. MediaObjRemoveFromTable( pDeviceObj->wchDeviceType );
  330. }
  331. pDeviceObj->fFlags |= DEV_OBJ_MARKED_AS_INUSE;
  332. gblDeviceTable.NumDevicesInUse++;
  333. //
  334. // Possibly need to notify the router managers of unreachability
  335. //
  336. EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) );
  337. IfObjectNotifyAllOfReachabilityChange( FALSE,
  338. INTERFACE_OUT_OF_RESOURCES );
  339. LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) );
  340. }
  341. //
  342. // Stop authentication timer (this will be running in case of callback)
  343. //
  344. TimerQRemove( (HANDLE)pDeviceObj->hPort, SvAuthTimeout );
  345. //
  346. // if a session timeout is specified in the policy, put this connection on
  347. // the timer queue so the user gets kicked off after the session timeout
  348. //
  349. if (SessTimeOut != (DWORD)-1)
  350. {
  351. TimerQInsert( (HANDLE)pDeviceObj->hPort, SessTimeOut, ArapDDMTimeOut);
  352. }
  353. //
  354. // log authentication success
  355. //
  356. if ( pDeviceObj->wchDomainName[0] != TEXT('\0') )
  357. {
  358. wcscpy( wchFullUserName, pDeviceObj->wchDomainName );
  359. wcscat( wchFullUserName, TEXT("\\") );
  360. wcscat( wchFullUserName, pDeviceObj->wchUserName );
  361. }
  362. else
  363. {
  364. wcscpy( wchFullUserName, pDeviceObj->wchUserName );
  365. }
  366. lpstrAudit[0] = wchFullUserName;
  367. lpstrAudit[1] = pDeviceObj->wchPortName;
  368. DDMLogInformation( ROUTERLOG_AUTH_SUCCESS, 2, lpstrAudit);
  369. //
  370. // and finaly go to ACTIVE state
  371. //
  372. pDeviceObj->DeviceState = DEV_OBJ_ACTIVE;
  373. pDeviceObj->dwTotalNumberOfCalls++;
  374. //
  375. // and initialize the active time
  376. //
  377. GetSystemTimeAsFileTime( (FILETIME*)&(pConnObj->qwActiveTime) );
  378. GetSystemTimeAsFileTime( (FILETIME*)&(pDeviceObj->qwActiveTime) );
  379. return;
  380. }
  381. //***
  382. //
  383. // Function: ArapDDMFailure
  384. // Closes the dcb, and logs an event depending on why connection failed
  385. //
  386. // Parameters: pDeviceObj - the dcb for this connection
  387. // pFailInfo - info about who disconnected and how (or why)
  388. //
  389. // Return: Nothing
  390. //
  391. //
  392. //***$
  393. VOID
  394. ArapDDMFailure(
  395. IN PDEVICE_OBJECT pDeviceObj,
  396. IN ARAPDDM_DISCONNECT *pFailInfo
  397. )
  398. {
  399. LPWSTR auditstrp[3];
  400. WCHAR wchErrorString[256+1];
  401. WCHAR wchUserName[UNLEN+1];
  402. WCHAR wchDomainName[DNLEN+1];
  403. DWORD dwRetCode;
  404. DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  405. "ArapDDMFailure: Entered, hPort=%d\n", pDeviceObj->hPort);
  406. //
  407. // ignore the DeviceState here: disconnect can happen at any time during
  408. // the connection
  409. //
  410. switch( pFailInfo->dwError )
  411. {
  412. case ERROR_AUTHENTICATION_FAILURE:
  413. wcscpy( wchUserName, pFailInfo->wchUserName );
  414. auditstrp[0] = wchUserName;
  415. auditstrp[1] = pDeviceObj->wchPortName;
  416. DDMLogWarning(ROUTERLOG_AUTH_FAILURE,2,auditstrp );
  417. break;
  418. case ERROR_PASSWD_EXPIRED:
  419. wcscpy( wchUserName, pFailInfo->wchUserName );
  420. wcscpy( wchDomainName, pFailInfo->wchLogonDomain );
  421. auditstrp[0] = wchDomainName;
  422. auditstrp[1] = wchUserName;
  423. auditstrp[2] = pDeviceObj->wchPortName;
  424. DDMLogWarning( ROUTERLOG_PASSWORD_EXPIRED,3,auditstrp );
  425. break;
  426. case ERROR_ACCT_EXPIRED:
  427. wcscpy( wchUserName, pFailInfo->wchUserName );
  428. wcscpy( wchDomainName, pFailInfo->wchLogonDomain );
  429. auditstrp[0] = wchDomainName;
  430. auditstrp[1] = wchUserName;
  431. auditstrp[2] = pDeviceObj->wchPortName;
  432. DDMLogWarning( ROUTERLOG_ACCT_EXPIRED, 3, auditstrp );
  433. break;
  434. case ERROR_NO_DIALIN_PERMISSION:
  435. wcscpy( wchUserName, pFailInfo->wchUserName );
  436. wcscpy( wchDomainName, pFailInfo->wchLogonDomain );
  437. auditstrp[0] = wchDomainName;
  438. auditstrp[1] = wchUserName;
  439. auditstrp[2] = pDeviceObj->wchPortName;
  440. DDMLogWarning( ROUTERLOG_NO_DIALIN_PRIVILEGE,3,auditstrp );
  441. break;
  442. default:
  443. auditstrp[0] = pDeviceObj->wchPortName;
  444. auditstrp[1] = wchErrorString;
  445. DDMLogErrorString( ROUTERLOG_ARAP_FAILURE, 2, auditstrp,
  446. pFailInfo->dwError, 2 );
  447. break;
  448. }
  449. DevStartClosing( pDeviceObj );
  450. }
  451. //***
  452. //
  453. // Function: ArapDDMTimeOut
  454. // Closes the connection when the timeout specified in policy elapses
  455. //
  456. // Parameters: hPort
  457. //
  458. // Return: Nothing
  459. //
  460. //
  461. //***$
  462. VOID
  463. ArapDDMTimeOut(
  464. IN HANDLE hPort
  465. )
  466. {
  467. PDEVICE_OBJECT pDeviceObj;
  468. EnterCriticalSection( &(gblDeviceTable.CriticalSection) );
  469. pDeviceObj = DeviceObjGetPointer( (HPORT)hPort );
  470. if ( pDeviceObj == NULL )
  471. {
  472. LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
  473. return;
  474. }
  475. ArapDisconnect((HPORT)pDeviceObj->hPort);
  476. LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
  477. }
  478. //
  479. // The following two structures (and the RasSetDevConfig call) copied from
  480. // ras\ui\common\nouiutil\rasman.c, courtesy SteveC
  481. //
  482. /* These types are described in MSDN and appear in Win95's unimdm.h private
  483. ** header (complete with typo) but not in any SDK headers.
  484. */
  485. typedef struct tagDEVCFGGDR
  486. {
  487. DWORD dwSize;
  488. DWORD dwVersion;
  489. WORD fwOptions;
  490. WORD wWaitBong;
  491. }DEVCFGHDR;
  492. typedef struct tagDEVCFG
  493. {
  494. DEVCFGHDR dfgHdr;
  495. COMMCONFIG commconfig;
  496. } DEVCFG;
  497. VOID
  498. ArapSetModemParms(
  499. IN PVOID pDevObjPtr,
  500. IN BOOLEAN TurnItOff
  501. )
  502. {
  503. DWORD dwErr;
  504. DWORD dwBlobSize=0;
  505. RAS_DEVCONFIG *pRasDevCfg;
  506. PDEVICE_OBJECT pDeviceObj;
  507. MODEMSETTINGS *pModemSettings;
  508. DEVCFG *pDevCfg;
  509. pDeviceObj = (PDEVICE_OBJECT)pDevObjPtr;
  510. //
  511. // if this was not a callback case, we never messed with modem settings:
  512. // don't do anything here
  513. //
  514. if (pDeviceObj->wchCallbackNumber[0] == 0)
  515. {
  516. return;
  517. }
  518. dwErr = RasGetDevConfig(NULL, pDeviceObj->hPort,"modem",NULL,&dwBlobSize);
  519. if (dwErr != ERROR_BUFFER_TOO_SMALL)
  520. {
  521. // what else can we do here? callback will faile, that's about it
  522. DbgPrint("ArapSetModemParms: RasGetDevConfig failed with %ld\n",dwErr);
  523. return;
  524. }
  525. pRasDevCfg = (RAS_DEVCONFIG *)LOCAL_ALLOC(LPTR,dwBlobSize);
  526. if (pRasDevCfg == NULL)
  527. {
  528. // what else can we do here? callback will faile, that's about it
  529. DbgPrint("ArapSetModemParms: alloc failed\n");
  530. return;
  531. }
  532. dwErr = RasGetDevConfig(NULL, pDeviceObj->hPort,"modem",(PBYTE)pRasDevCfg,&dwBlobSize);
  533. if (dwErr != 0)
  534. {
  535. // what else can we do here? callback will faile, that's about it
  536. DbgPrint("ArapSetModemParms: RasGetDevConfig failed with %ld\n",dwErr);
  537. LOCAL_FREE((PBYTE)pRasDevCfg);
  538. return;
  539. }
  540. pDevCfg = (DEVCFG *) ((PBYTE) pRasDevCfg + pRasDevCfg->dwOffsetofModemSettings);
  541. pModemSettings = (MODEMSETTINGS* )(((PBYTE)&pDevCfg->commconfig)
  542. + pDevCfg->commconfig.dwProviderOffset);
  543. //
  544. // is this routine called to turn the compression and errorcontrol off?
  545. //
  546. if (TurnItOff)
  547. {
  548. //
  549. // turn error-control and compression off if it's on
  550. //
  551. pModemSettings->dwPreferredModemOptions &=
  552. ~(MDM_COMPRESSION | MDM_ERROR_CONTROL);
  553. }
  554. //
  555. // no, it's called to turn it back on: just do it
  556. //
  557. else
  558. {
  559. pModemSettings->dwPreferredModemOptions |=
  560. (MDM_COMPRESSION | MDM_ERROR_CONTROL);
  561. }
  562. RasSetDevConfig(pDeviceObj->hPort,"modem",(PBYTE)pRasDevCfg,dwBlobSize);
  563. LOCAL_FREE((PBYTE)pRasDevCfg);
  564. }
  565.