Acl.cpp
上传用户:zhuzhu0204
上传日期:2020-07-13
资源大小:13165k
文件大小:14k
开发平台:

Visual C++

  1. ///////////////////////////////////////////////////
  2. // Acl.cpp文件
  3. #define UNICODE
  4. #define _UNICODE
  5. #include <winsock2.h>
  6. #include <windows.h>
  7. #include <stdio.h>
  8. #include <tchar.h>
  9. #include "Acl.h"
  10. #include "../common/Debug.h"
  11. #include "../common/PMacRes.h"
  12. ///////////////////////////////////////
  13. // 共享内存
  14. // 所有使用Winsock访问网络的应用程序都共享initdata和uinitdata段的变量
  15. #pragma data_seg(".initdata")
  16. HWND g_hWnd = NULL; // 主窗口句柄
  17. UCHAR g_ucWorkMode = PF_QUERY_ALL; // 工作模式
  18. #pragma data_seg()
  19. #pragma bss_seg(".uinitdata") 
  20. RULE_ITEM g_Rule[MAX_RULE_COUNT];   // 应用层规则
  21. ULONG g_RuleCount;
  22. SESSION g_SessionBuffer[MAX_SESSION_BUFFER];  // 向主程序发送会话信息时使用
  23. TCHAR g_szFireWallPath[MAX_PATH];   // 记录主程序路径
  24. #pragma bss_seg()
  25. extern TCHAR g_szCurrentApp[MAX_PATH];
  26. CRITICAL_SECTION g_csGetAccess;
  27. CAcl::CAcl()
  28. {
  29. ODS(L"CAcl()...");
  30. m_nSessionCount = 0;
  31. // 为会话结构预申请内存空间
  32. m_nSessionMaxCount = INIT_SESSION_BUFFER;
  33. m_pSession = new SESSION[m_nSessionMaxCount];
  34. ::InitializeCriticalSection(&g_csGetAccess);
  35. }
  36. CAcl::~CAcl()
  37. {
  38. ODS(L" CAcl::~CAcl send CODE_APP_EXIT ... ");
  39. // 通知主模块,当前应用程序正在退出
  40. int nIndex = CreateSession(0, 0);
  41. NotifySession(&m_pSession[nIndex], CODE_APP_EXIT);
  42. delete[] m_pSession;
  43. ::DeleteCriticalSection(&g_csGetAccess);
  44. }
  45. /////////////////////////////////////////////////////////
  46. // 检查函数
  47. void CAcl::CheckSocket(SOCKET s, int af, int type, int protocol)
  48. {
  49. ODS(L"CheckSocket {");
  50. if (af != AF_INET) // 仅支持IPv4
  51. return;
  52. // 先判断基本协议类型
  53. int nProtocol = RULE_SERVICE_TYPE_ALL;
  54. if(protocol == 0)
  55. {
  56. if(type ==  SOCK_STREAM)
  57. nProtocol = RULE_SERVICE_TYPE_TCP;
  58. else if(type == SOCK_DGRAM)
  59. nProtocol = RULE_SERVICE_TYPE_UDP;
  60. }
  61. else if(protocol == IPPROTO_TCP)
  62. nProtocol = RULE_SERVICE_TYPE_TCP;
  63. else if(protocol == IPPROTO_UDP)
  64. nProtocol = RULE_SERVICE_TYPE_UDP;
  65. // 为新套节字创建会话,指明协议类型
  66. CreateSession(s, nProtocol);
  67. ODS(L"} CheckSocket");
  68. }
  69. void CAcl::CheckCloseSocket(SOCKET s)
  70. {
  71. // 删除会话
  72. DeleteSession(s);
  73. }
  74. void CAcl::CheckBind(SOCKET s, const struct sockaddr *addr)
  75. {
  76. ODS(L"CheckBind {");
  77. int nIndex;
  78. if((nIndex = FindSession(s)) >= m_nSessionCount)
  79. return;
  80. // 设置会话
  81. sockaddr_in *pLocal = (sockaddr_in *)addr;
  82. m_pSession[nIndex].usLocalPort = ntohs(pLocal->sin_port);
  83. if(pLocal->sin_addr.S_un.S_addr != ADDR_ANY)
  84. m_pSession[nIndex].ulLocalIP = *((DWORD*)&pLocal->sin_addr);
  85. ODS(L"} CheckBind");
  86. }
  87. int CAcl::CheckAccept(SOCKET s, SOCKET sNew, sockaddr FAR *addr)
  88. {
  89. ODS(L"CheckAccept {");
  90. int nIndex;
  91. if((nIndex = FindSession(s)) >= m_nSessionCount)
  92. return PF_PASS;
  93. nIndex = CreateSession(sNew, RULE_SERVICE_TYPE_TCP);
  94. // 设置会话
  95. if(addr != NULL)
  96. {
  97. sockaddr_in *pRemote = (sockaddr_in *)addr;
  98. USHORT usPort = ntohs(pRemote->sin_port);
  99. DWORD dwIP = *((DWORD*)&pRemote->sin_addr);
  100. SetSession(&m_pSession[nIndex], usPort, dwIP, RULE_DIRECTION_IN_OUT);
  101. }
  102. return GetAccessInfo(&m_pSession[nIndex]);
  103. ODS(L"} CheckAccept");
  104. }
  105. int CAcl::CheckConnect(SOCKET s, const struct sockaddr FAR *addr)
  106. {
  107. ODS(L"CheckConnect {");
  108. int nIndex;
  109. if((nIndex = FindSession(s)) >= m_nSessionCount)
  110. return PF_PASS;
  111. // 设置会话远程地址
  112. sockaddr_in *pRemote = (sockaddr_in *)addr;
  113. USHORT usPort = ntohs(pRemote->sin_port);
  114. DWORD dwIP = *((DWORD*)&pRemote->sin_addr);
  115. SetSession(&m_pSession[nIndex], usPort, dwIP, RULE_DIRECTION_IN_OUT);
  116. return GetAccessInfo(&m_pSession[nIndex]);
  117. ODS(L"} CheckConnect");
  118. }
  119. int CAcl::CheckSendTo(SOCKET s, const SOCKADDR *pTo)
  120. {
  121. ODS(L"CheckSendTo {");
  122. int nIndex;
  123. if((nIndex = FindSession(s)) >= m_nSessionCount)
  124. return PF_PASS;
  125. if(pTo != NULL)
  126. {
  127. // 设置会话远程地址
  128. sockaddr_in *pRemote = (sockaddr_in *)pTo;
  129. USHORT usPort = ntohs(pRemote->sin_port);
  130. DWORD dwIP = *((DWORD*)&pRemote->sin_addr);
  131. SetSession(&m_pSession[nIndex], usPort, dwIP, RULE_DIRECTION_OUT);
  132. }
  133. return GetAccessInfo(&m_pSession[nIndex]);
  134. ODS(L"} CheckSendTo");
  135. }
  136. int CAcl::CheckRecvFrom(SOCKET s, SOCKADDR *pFrom)
  137. {
  138. ODS(L"CheckRecvFrom {");
  139. int nIndex;
  140. if((nIndex = FindSession(s)) >= m_nSessionCount)
  141. return PF_PASS;
  142. if(pFrom != NULL)
  143. {
  144. // 设置会话远程地址
  145. sockaddr_in *pRemote = (sockaddr_in *)pFrom;
  146. USHORT usPort = ntohs(pRemote->sin_port);
  147. DWORD dwIP = *((DWORD*)&pRemote->sin_addr);
  148. SetSession(&m_pSession[nIndex], usPort, dwIP, RULE_DIRECTION_IN);
  149. }
  150. return GetAccessInfo(&m_pSession[nIndex]);
  151. ODS(L"} CheckRecvFrom");
  152. }
  153. /////////////////////////////////////////////////////////////
  154. // 查看访问权限
  155. int CAcl::GetAccessInfo(SESSION *pSession)
  156. {
  157. ODS(L"GetAccessInfo {");
  158. // 如果是主模块访问网络,放行
  159. if(wcsicmp(g_szCurrentApp, g_szFireWallPath) == 0)
  160. {
  161. return PF_PASS;
  162. }
  163. // 先查看工作模式
  164. int nRet;
  165. if((nRet = GetAccessFromWorkMode(pSession)) != PF_FILTER)
  166. {
  167. ODS(L" GetAccessInfo return from WorkMode n");
  168. return nRet;
  169. }
  170. // 工作模式为过滤,则按照文件中记录的规则过滤之
  171. ::EnterCriticalSection(&g_csGetAccess);
  172. RULE_ITEM *pItem = NULL;
  173. int nIndex = 0;
  174. nRet = PF_PASS;
  175. while(TRUE)
  176. {
  177. // 如果不是第一次查询,则加1,避免查找相同的规则
  178. if(nIndex > 0) 
  179. nIndex++;
  180. nIndex = FindRule(g_szCurrentApp, nIndex);
  181. if(nIndex >= (int)g_RuleCount)
  182. {
  183. ODS(L"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
  184. if(pItem == NULL) // 一个记录项也没有,则查询
  185. {
  186. // 询问主模块怎么办
  187. if(QueryAccess(pSession) == RULE_ACTION_DENY)
  188. {
  189. nRet = PF_DENY;
  190. }
  191. break;
  192. }
  193. else // 按照上一个记录项处理
  194. {
  195. if(pItem->ucAction != RULE_ACTION_PASS)
  196. {
  197. nRet = PF_DENY;
  198. }
  199. break;
  200. }
  201. }
  202. ODS(L" Find a rule in GetAccessInfo ");
  203. // 查看规则和会话的属性是否一致
  204. pItem = &g_Rule[nIndex];
  205. /*
  206. // 方向
  207. if(pItem->ucDirection != RULE_DIRECTION_IN_OUT &&
  208. pItem->ucDirection != pSession->ucDirection)
  209. continue;
  210. // 服务类型
  211. if(pItem->ucServiceType != RULE_SERVICE_TYPE_ALL &&
  212. pItem->ucServiceType != pSession->nProtocol)
  213. continue;
  214. // 服务端口
  215. if(pItem->usServicePort != RULE_SERVICE_PORT_ALL &&
  216.  pItem->usServicePort != pSession->usRemotePort)
  217.  continue;
  218. */
  219. // 程序运行到这里,说明找到了一个和会话属性完全相同的规则
  220. if(pItem->ucAction != RULE_ACTION_PASS)
  221. {
  222. nRet = PF_DENY;
  223. }
  224. break;
  225. }
  226. ::LeaveCriticalSection(&g_csGetAccess);
  227. if(nRet == PF_PASS)
  228. pSession->ucAction = RULE_ACTION_PASS;
  229. else
  230. pSession->ucAction =  RULE_ACTION_DENY;
  231. ODS(L"} GetAccessInfo 哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈");
  232. return nRet;
  233. }
  234. int CAcl::GetAccessFromWorkMode(SESSION *pSession)
  235. {
  236. ODS(L"GetAccessFromWorkMode {");
  237. if(g_ucWorkMode == PF_PASS_ALL)
  238. return PF_PASS;
  239. if(g_ucWorkMode == PF_DENY_ALL)
  240. return PF_DENY;
  241. if(g_ucWorkMode == PF_QUERY_ALL)
  242. return PF_FILTER;
  243. ODS(L"} GetAccessFromWorkMode");
  244. return PF_UNKNOWN;
  245. }
  246. int CAcl::FindRule(TCHAR *szAppName, int nStart)
  247. {
  248. ODS(L"FindRule {");
  249. // 从指定位置开始查找,返回规则的索引
  250. for(int nIndex = nStart; nIndex < (int)g_RuleCount; nIndex++)
  251. {
  252. if(wcsicmp(szAppName, g_Rule[nIndex].szApplication) == 0)
  253. break;
  254. }
  255. ODS(L"} FindRule");
  256. return nIndex;
  257. }
  258. UCHAR CAcl::QueryAccess(SESSION *pSession)
  259. {
  260. ODS(L"QueryAccess {");
  261. if(g_hWnd != NULL)
  262. {
  263. // 在g_SessionBuffer数组中查找一个未使用的成员
  264. for(int i=0; i<MAX_SESSION_BUFFER; i++)
  265. {
  266. if(g_SessionBuffer[i].s == 0)
  267. {
  268. g_SessionBuffer[i] = *pSession;
  269. break;
  270. }
  271. }
  272. ODS(L" QueryAccess: 发送 PM_QUERY_ACL_NOTIFY 消息!");
  273. // 将会话发送给主模块
  274. if(i<MAX_SESSION_BUFFER && !::PostMessage(g_hWnd, PM_QUERY_ACL_NOTIFY, i, 0))
  275. {
  276. // 如果发送失败,恢复成员标识
  277. g_SessionBuffer[i].s = 0;
  278. ODS(L" QueryAccess: 消息发送失败!");
  279. return RULE_ACTION_PASS;
  280. }
  281. int n = 0;
  282. while (g_SessionBuffer[i].ucAction == RULE_ACTION_NOT_SET)
  283. {
  284. if (n++ > 3000)
  285. {
  286. ODS(L"5分钟过后,用户还未做出决定!!!!!!!!");
  287. return RULE_ACTION_DENY; // 等1分钟,如果用户还不决定,就禁止
  288. }
  289. ::Sleep(100);
  290. }
  291. // 执行到此,表明用户在1分钟内做出了决定
  292. ODS(L"用户在1分钟内做出了决定!!!!!!!!");
  293. g_SessionBuffer[i].s = 0;
  294. return g_SessionBuffer[i].ucAction;
  295. }
  296. }
  297. /////////////////////////////////////////////////////////////////////////////////////
  298. // 会话操作
  299. int CAcl::CreateSession(SOCKET s, int nProtocol)
  300. {
  301. for(int i=0; i<m_nSessionCount; i++)
  302. {
  303. ODS1(L"计数:%d", i);
  304. if(m_pSession[i].s == s)
  305. {
  306. ODS1(L" m_pSession[i].s == s    m_nSessionCount = %d n", m_nSessionCount);
  307. return i;
  308. }
  309. }
  310. // 确保有足够的内存空间
  311. if(m_nSessionCount >= m_nSessionMaxCount) // 已经达到最大数量
  312. {
  313. SESSION *pTmp = new SESSION[m_nSessionMaxCount];
  314. memcpy(pTmp, m_pSession, m_nSessionMaxCount);
  315. delete[] m_pSession;
  316. m_pSession = new SESSION[m_nSessionMaxCount*2];
  317. memcpy(m_pSession, pTmp,  m_nSessionMaxCount);
  318. delete[] pTmp;
  319. m_nSessionMaxCount = m_nSessionMaxCount*2;
  320. }
  321. // 初始化新的会话
  322. InitializeSession(&m_pSession[m_nSessionCount]);
  323. // 设置会话属性
  324. m_pSession[m_nSessionCount].s = s;
  325. m_pSession[m_nSessionCount].nProtocol = nProtocol;
  326. wcscpy(m_pSession[m_nSessionCount].szPathName, g_szCurrentApp);
  327. m_nSessionCount++;
  328. ODS1(L" CreateSession m_nSessionCount = %d n", m_nSessionCount);
  329. // 返回会话索引
  330. return m_nSessionCount - 1;
  331. }
  332. void CAcl::InitializeSession(SESSION *pSession)
  333. {
  334. memset(pSession, 0, sizeof(SESSION));
  335. pSession->ucDirection = RULE_DIRECTION_NOT_SET;
  336. pSession->ucAction = RULE_ACTION_NOT_SET;
  337. }
  338. void CAcl::DeleteSession(SOCKET s)
  339. {
  340. for(int i=0; i<m_nSessionCount; i++)
  341. {
  342. if(m_pSession[i].s == s)
  343. {
  344. // 通知应用程序,有一个会话销毁了
  345. NotifySession(&m_pSession[i], CODE_DELETE_SESSION);
  346. memcpy(&m_pSession[i], &m_pSession[i+1], m_nSessionCount - i - 1);
  347. m_nSessionCount --;
  348. break;
  349. }
  350. }
  351. }
  352. void CAcl::SetSession(SESSION *pSession, USHORT usRemotePort, ULONG ulRemoteIP, UCHAR ucDirection)
  353. {
  354. pSession->ucDirection = ucDirection;
  355. if((pSession->usRemotePort != usRemotePort) || (pSession->ulRemoteIP != ulRemoteIP))
  356. {
  357. // 根据远程端口号设置远程服务类型
  358. if(pSession->nProtocol == RULE_SERVICE_TYPE_TCP)
  359. {
  360. if(usRemotePort == RULE_SERVICE_PORT_FTP)
  361. pSession->nProtocol = RULE_SERVICE_TYPE_FTP;
  362. else if(usRemotePort == RULE_SERVICE_PORT_TELNET)
  363. pSession->nProtocol = RULE_SERVICE_TYPE_TELNET;
  364. else if(usRemotePort == RULE_SERVICE_PORT_POP3)
  365. pSession->nProtocol = RULE_SERVICE_TYPE_POP3;
  366. else if(usRemotePort == RULE_SERVICE_PORT_SMTP)
  367. pSession->nProtocol = RULE_SERVICE_TYPE_SMTP;
  368. else if(usRemotePort  == RULE_SERVICE_PORT_NNTP)
  369. pSession->nProtocol = RULE_SERVICE_TYPE_NNTP;
  370. else if(usRemotePort  == RULE_SERVICE_PORT_HTTP)
  371. pSession->nProtocol = RULE_SERVICE_TYPE_HTTP;
  372. }
  373. // 设置其它
  374. pSession->usRemotePort = usRemotePort;
  375. pSession->ulRemoteIP = ulRemoteIP;
  376. // 通知主程序
  377. NotifySession(pSession, CODE_CHANGE_SESSION);
  378. }
  379. }
  380. int CAcl::FindSession(SOCKET s)
  381. {
  382. for(int i=0; i<m_nSessionCount; i++)
  383. {
  384. if(m_pSession[i].s == s)
  385. {
  386. break;
  387. }
  388. }
  389. return i;
  390. }
  391. void CAcl::NotifySession(SESSION *pSession, int nCode)
  392. {
  393. ODS(L" NotifySession... ");
  394. if(g_hWnd != NULL)
  395. {
  396. // 在g_SessionBuffer数组中查找一个未使用的成员
  397. for(int i=0; i<MAX_SESSION_BUFFER; i++)
  398. {
  399. if(g_SessionBuffer[i].s == 0)
  400. {
  401. g_SessionBuffer[i] = *pSession;
  402. break;
  403. }
  404. }
  405. ODS(L" NotifySession: 发送 PM_SESSION_NOTIFY 消息!");
  406. // 将会话发送给主模块
  407. if(i<MAX_SESSION_BUFFER &&
  408. !::PostMessage(g_hWnd, PM_SESSION_NOTIFY, i, nCode))
  409. {
  410. // 如果发送失败,恢复成员标识
  411. g_SessionBuffer[i].s = 0;
  412. ODS(L" NotifySession: 消息发送失败!");
  413. }
  414. }
  415. }
  416. ////////////////////////////////////////////////////////////
  417. int __stdcall PLSPIoControl(LSP_IO_CONTROL *pIoControl, int nType)
  418. {
  419. switch(nType)
  420. {
  421. case IO_CONTROL_SET_RULE_FILE: // 设置应用层规则
  422. {
  423. if(pIoControl->pRuleFile->header.ulLspRuleCount <= MAX_RULE_COUNT)
  424. {
  425. g_RuleCount = pIoControl->pRuleFile->header.ulLspRuleCount;
  426. memcpy(g_Rule, pIoControl->pRuleFile->LspRules, g_RuleCount * sizeof(RULE_ITEM));
  427. }
  428. }
  429. break; 
  430. case IO_CONTROL_SET_WORK_MODE: // 设置工作模式
  431. {
  432. g_ucWorkMode = pIoControl->ucWorkMode;
  433. }
  434. break;
  435. case IO_CONTROL_GET_WORK_MODE: // 获取工作模式
  436. {
  437. return g_ucWorkMode;
  438. }
  439. break;
  440. case IO_CONTROL_SET_INSTANCE: // 设置主模块信息
  441. {
  442. g_hWnd = pIoControl->hWnd;
  443. wcscpy(g_szFireWallPath, pIoControl->szPath);
  444. }
  445. break;
  446. case IO_CONTROL_GET_SESSION: // 获取一个会话
  447. {
  448. *pIoControl->pSession = g_SessionBuffer[pIoControl->nSessionIndex];
  449. // 标识已经不再使用这个成员了
  450. g_SessionBuffer[pIoControl->nSessionIndex].s = 0;
  451. }
  452. break; 
  453. case IO_CONTROL_SET_QUERY_SESSION: // 返回DLL询问的结果
  454. {
  455. //设置返回的动作
  456. g_SessionBuffer[pIoControl->nSessionIndex].ucAction = pIoControl->ucWorkMode;
  457. }
  458. break;
  459. case IO_CONTROL_GET_QUERY_SESSION: // 获取发出询问的会话
  460. {
  461. *pIoControl->pSession = g_SessionBuffer[pIoControl->nSessionIndex];
  462. }
  463. break;
  464. }
  465. return 0;
  466. }
  467. /*
  468. int CAcl::CheckSend(SOCKET s, const char *buf, DWORD dwTransed)
  469. {
  470. int nIndex;
  471. if(nIndex = FindSession(s) >= m_nSessionCount)
  472. return PF_PASS;
  473. return GetAccessInfo(&m_pSession[nIndex]);
  474. }
  475. int CheckSend(SOCKET s,  const char *buf, DWORD dwTransed);
  476. int CheckRecv(SOCKET s,  const char *buf, DWORD dwTransed);
  477. int CAcl::CheckRecv(SOCKET s, const char *buf, DWORD dwTransed)
  478. {
  479. int nIndex;
  480. if(nIndex = FindSession(s) >= m_nSessionCount)
  481. return PF_PASS;
  482. return GetAccessInfo(&m_pSession[nIndex]);
  483. }
  484. BOOL CAcl::IsLocalIP(DWORD dwIP)
  485. {
  486. if(dwIP == 0 || ((BYTE*)&dwIP)[3] == 127)
  487. return TRUE;
  488. return FALSE;
  489. }
  490. // 保持线程同步,首先检查有没有其它线程正在发送这个询问
  491. for(int i=0; i<MAX_QUERY_SESSION; i++)
  492. {
  493. if(g_QuerySession[i].bUsed && 
  494. (wcscmp(g_QuerySession[i].szPathName, g_szCurrentApp) == 0)) // 已经有会话发出询问,等待
  495. {
  496. // 等待
  497. ODS(L"已经有会话发出询问,等待");
  498. int n=0;
  499. while(g_QuerySession[i].bUsed)
  500. {
  501. if(n++ > 3000) // 等5分钟,如果用户还不决定,就禁止
  502. return FALSE;
  503. ::Sleep(100);
  504. }
  505. if(g_QuerySession[i].nReturnValue == 0)
  506. return FALSE;
  507. return TRUE;
  508. }
  509. }
  510.   */