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.

757 lines
18 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. NULL);
  302. if ( pIfObject == (ROUTER_INTERFACE_OBJECT *)NULL )
  303. {
  304. //
  305. // Error log this and stop the connection.
  306. //
  307. DDMLogError( ROUTERLOG_NOT_ENOUGH_MEMORY, 1, NULL, GetLastError() );
  308. DevStartClosing( pDeviceObj );
  309. return;
  310. }
  311. //
  312. // Insert in table now
  313. //
  314. dwRetCode = IfObjectInsertInTable( pIfObject );
  315. if ( dwRetCode != NO_ERROR )
  316. {
  317. LOCAL_FREE( pIfObject );
  318. DDMLogError( ROUTERLOG_NOT_ENOUGH_MEMORY, 1, NULL, dwRetCode );
  319. DevStartClosing( pDeviceObj );
  320. return;
  321. }
  322. pConnObj->hDIMInterface = pIfObject->hDIMInterface;
  323. //
  324. // Reduce the media count for this device
  325. //
  326. if ( !(pDeviceObj->fFlags & DEV_OBJ_MARKED_AS_INUSE) )
  327. {
  328. if ( pDeviceObj->fFlags & DEV_OBJ_ALLOW_ROUTERS )
  329. {
  330. MediaObjRemoveFromTable( pDeviceObj->wchDeviceType );
  331. }
  332. pDeviceObj->fFlags |= DEV_OBJ_MARKED_AS_INUSE;
  333. gblDeviceTable.NumDevicesInUse++;
  334. //
  335. // Possibly need to notify the router managers of unreachability
  336. //
  337. EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) );
  338. IfObjectNotifyAllOfReachabilityChange( FALSE,
  339. INTERFACE_OUT_OF_RESOURCES );
  340. LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) );
  341. }
  342. //
  343. // Stop authentication timer (this will be running in case of callback)
  344. //
  345. TimerQRemove( (HANDLE)pDeviceObj->hPort, SvAuthTimeout );
  346. //
  347. // if a session timeout is specified in the policy, put this connection on
  348. // the timer queue so the user gets kicked off after the session timeout
  349. //
  350. if (SessTimeOut != (DWORD)-1)
  351. {
  352. TimerQInsert( (HANDLE)pDeviceObj->hPort, SessTimeOut, ArapDDMTimeOut);
  353. }
  354. //
  355. // log authentication success
  356. //
  357. if ( pDeviceObj->wchDomainName[0] != TEXT('\0') )
  358. {
  359. wcscpy( wchFullUserName, pDeviceObj->wchDomainName );
  360. wcscat( wchFullUserName, TEXT("\\") );
  361. wcscat( wchFullUserName, pDeviceObj->wchUserName );
  362. }
  363. else
  364. {
  365. wcscpy( wchFullUserName, pDeviceObj->wchUserName );
  366. }
  367. lpstrAudit[0] = wchFullUserName;
  368. lpstrAudit[1] = pDeviceObj->wchPortName;
  369. DDMLogInformation( ROUTERLOG_AUTH_SUCCESS, 2, lpstrAudit);
  370. //
  371. // and finaly go to ACTIVE state
  372. //
  373. pDeviceObj->DeviceState = DEV_OBJ_ACTIVE;
  374. pDeviceObj->dwTotalNumberOfCalls++;
  375. //
  376. // and initialize the active time
  377. //
  378. GetSystemTimeAsFileTime( (FILETIME*)&(pConnObj->qwActiveTime) );
  379. GetSystemTimeAsFileTime( (FILETIME*)&(pDeviceObj->qwActiveTime) );
  380. return;
  381. }
  382. //***
  383. //
  384. // Function: ArapDDMFailure
  385. // Closes the dcb, and logs an event depending on why connection failed
  386. //
  387. // Parameters: pDeviceObj - the dcb for this connection
  388. // pFailInfo - info about who disconnected and how (or why)
  389. //
  390. // Return: Nothing
  391. //
  392. //
  393. //***$
  394. VOID
  395. ArapDDMFailure(
  396. IN PDEVICE_OBJECT pDeviceObj,
  397. IN ARAPDDM_DISCONNECT *pFailInfo
  398. )
  399. {
  400. LPWSTR auditstrp[3];
  401. WCHAR wchErrorString[256+1];
  402. WCHAR wchUserName[UNLEN+1];
  403. WCHAR wchDomainName[DNLEN+1];
  404. DWORD dwRetCode;
  405. DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
  406. "ArapDDMFailure: Entered, hPort=%d\n", pDeviceObj->hPort);
  407. //
  408. // ignore the DeviceState here: disconnect can happen at any time during
  409. // the connection
  410. //
  411. switch( pFailInfo->dwError )
  412. {
  413. case ERROR_AUTHENTICATION_FAILURE:
  414. wcscpy( wchUserName, pFailInfo->wchUserName );
  415. auditstrp[0] = wchUserName;
  416. auditstrp[1] = pDeviceObj->wchPortName;
  417. DDMLogWarning(ROUTERLOG_AUTH_FAILURE,2,auditstrp );
  418. break;
  419. case ERROR_PASSWD_EXPIRED:
  420. wcscpy( wchUserName, pFailInfo->wchUserName );
  421. wcscpy( wchDomainName, pFailInfo->wchLogonDomain );
  422. auditstrp[0] = wchDomainName;
  423. auditstrp[1] = wchUserName;
  424. auditstrp[2] = pDeviceObj->wchPortName;
  425. DDMLogWarning( ROUTERLOG_PASSWORD_EXPIRED,3,auditstrp );
  426. break;
  427. case ERROR_ACCT_EXPIRED:
  428. wcscpy( wchUserName, pFailInfo->wchUserName );
  429. wcscpy( wchDomainName, pFailInfo->wchLogonDomain );
  430. auditstrp[0] = wchDomainName;
  431. auditstrp[1] = wchUserName;
  432. auditstrp[2] = pDeviceObj->wchPortName;
  433. DDMLogWarning( ROUTERLOG_ACCT_EXPIRED, 3, auditstrp );
  434. break;
  435. case ERROR_NO_DIALIN_PERMISSION:
  436. wcscpy( wchUserName, pFailInfo->wchUserName );
  437. wcscpy( wchDomainName, pFailInfo->wchLogonDomain );
  438. auditstrp[0] = wchDomainName;
  439. auditstrp[1] = wchUserName;
  440. auditstrp[2] = pDeviceObj->wchPortName;
  441. DDMLogWarning( ROUTERLOG_NO_DIALIN_PRIVILEGE,3,auditstrp );
  442. break;
  443. default:
  444. auditstrp[0] = pDeviceObj->wchPortName;
  445. auditstrp[1] = wchErrorString;
  446. DDMLogErrorString( ROUTERLOG_ARAP_FAILURE, 2, auditstrp,
  447. pFailInfo->dwError, 2 );
  448. break;
  449. }
  450. DevStartClosing( pDeviceObj );
  451. }
  452. //***
  453. //
  454. // Function: ArapDDMTimeOut
  455. // Closes the connection when the timeout specified in policy elapses
  456. //
  457. // Parameters: hPort
  458. //
  459. // Return: Nothing
  460. //
  461. //
  462. //***$
  463. VOID
  464. ArapDDMTimeOut(
  465. IN HANDLE hPort
  466. )
  467. {
  468. PDEVICE_OBJECT pDeviceObj;
  469. EnterCriticalSection( &(gblDeviceTable.CriticalSection) );
  470. pDeviceObj = DeviceObjGetPointer( (HPORT)hPort );
  471. if ( pDeviceObj == NULL )
  472. {
  473. LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
  474. return;
  475. }
  476. ArapDisconnect((HPORT)pDeviceObj->hPort);
  477. LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
  478. }
  479. //
  480. // The following two structures (and the RasSetDevConfig call) copied from
  481. // ras\ui\common\nouiutil\rasman.c, courtesy SteveC
  482. //
  483. /* These types are described in MSDN and appear in Win95's unimdm.h private
  484. ** header (complete with typo) but not in any SDK headers.
  485. */
  486. typedef struct tagDEVCFGGDR
  487. {
  488. DWORD dwSize;
  489. DWORD dwVersion;
  490. WORD fwOptions;
  491. WORD wWaitBong;
  492. }DEVCFGHDR;
  493. typedef struct tagDEVCFG
  494. {
  495. DEVCFGHDR dfgHdr;
  496. COMMCONFIG commconfig;
  497. } DEVCFG;
  498. VOID
  499. ArapSetModemParms(
  500. IN PVOID pDevObjPtr,
  501. IN BOOLEAN TurnItOff
  502. )
  503. {
  504. DWORD dwErr;
  505. DWORD dwBlobSize=0;
  506. RAS_DEVCONFIG *pRasDevCfg;
  507. PDEVICE_OBJECT pDeviceObj;
  508. MODEMSETTINGS *pModemSettings;
  509. DEVCFG *pDevCfg;
  510. pDeviceObj = (PDEVICE_OBJECT)pDevObjPtr;
  511. //
  512. // if this was not a callback case, we never messed with modem settings:
  513. // don't do anything here
  514. //
  515. if (pDeviceObj->wchCallbackNumber[0] == 0)
  516. {
  517. return;
  518. }
  519. dwErr = RasGetDevConfig(NULL, pDeviceObj->hPort,"modem",NULL,&dwBlobSize);
  520. if (dwErr != ERROR_BUFFER_TOO_SMALL)
  521. {
  522. // what else can we do here? callback will faile, that's about it
  523. DbgPrint("ArapSetModemParms: RasGetDevConfig failed with %ld\n",dwErr);
  524. return;
  525. }
  526. pRasDevCfg = (RAS_DEVCONFIG *)LOCAL_ALLOC(LPTR,dwBlobSize);
  527. if (pRasDevCfg == NULL)
  528. {
  529. // what else can we do here? callback will faile, that's about it
  530. DbgPrint("ArapSetModemParms: alloc failed\n");
  531. return;
  532. }
  533. dwErr = RasGetDevConfig(NULL, pDeviceObj->hPort,"modem",(PBYTE)pRasDevCfg,&dwBlobSize);
  534. if (dwErr != 0)
  535. {
  536. // what else can we do here? callback will faile, that's about it
  537. DbgPrint("ArapSetModemParms: RasGetDevConfig failed with %ld\n",dwErr);
  538. LOCAL_FREE((PBYTE)pRasDevCfg);
  539. return;
  540. }
  541. pDevCfg = (DEVCFG *) ((PBYTE) pRasDevCfg + pRasDevCfg->dwOffsetofModemSettings);
  542. pModemSettings = (MODEMSETTINGS* )(((PBYTE)&pDevCfg->commconfig)
  543. + pDevCfg->commconfig.dwProviderOffset);
  544. //
  545. // is this routine called to turn the compression and errorcontrol off?
  546. //
  547. if (TurnItOff)
  548. {
  549. //
  550. // turn error-control and compression off if it's on
  551. //
  552. pModemSettings->dwPreferredModemOptions &=
  553. ~(MDM_COMPRESSION | MDM_ERROR_CONTROL);
  554. }
  555. //
  556. // no, it's called to turn it back on: just do it
  557. //
  558. else
  559. {
  560. pModemSettings->dwPreferredModemOptions |=
  561. (MDM_COMPRESSION | MDM_ERROR_CONTROL);
  562. }
  563. RasSetDevConfig(pDeviceObj->hPort,"modem",(PBYTE)pRasDevCfg,dwBlobSize);
  564. LOCAL_FREE((PBYTE)pRasDevCfg);
  565. }
  566.