BSOne.SFC/Tocsg.Module/MgWinFW/Tocsg.Firewall.pas

449 lines
12 KiB
Plaintext

{*******************************************************}
{ }
{ Tocsg.Firewall }
{ }
{ Copyright (C) 2022 kku }
{ }
{*******************************************************}
unit Tocsg.Firewall;
interface
uses
Tocsg.Obj, System.SysUtils, System.Classes, Winapi.Windows,
System.Generics.Collections, NetFwTypeLib_TLB;
const
{
type
NET_FW_PROFILE_TYPE_ = TOleEnum;
const
NET_FW_PROFILE_DOMAIN = $00000000;
NET_FW_PROFILE_STANDARD = $00000001;
NET_FW_PROFILE_CURRENT = $00000002;
NET_FW_PROFILE_TYPE_MAX = $00000003;
// Constants for enum NET_FW_PROFILE_TYPE2_
type
NET_FW_PROFILE_TYPE2_ = TOleEnum;
const
NET_FW_PROFILE2_DOMAIN = $00000001;
NET_FW_PROFILE2_PRIVATE = $00000002;
NET_FW_PROFILE2_PUBLIC = $00000004;
NET_FW_PROFILE2_ALL = $7FFFFFFF;
}
FW_PROFILE_DOMAIN = 1; // 도메인
FW_PROFILE_PERSONAL = 2; // 개인
FW_PROFILE_DOMAIN_PERSONAL = 3; // 도메인, 개인
FW_PROFILE_PUBLIC = 4; // 공용
FW_PROFILE_DOMAIN_PUBLIC = 5; // 도메인, 공용
FW_PROFILE_PERSONAL_PUBLIC = 6; // 개인, 공용
FW_PROFILE_ANY = 7; // 모두
type
PFwRuleEnt = ^TFwRuleEnt;
TFwRuleEnt = record
sName,
sGroup,
sDesc,
sSvrName,
sAppName,
sLocalPorts,
sRemotePorts,
sLocalAddr,
sRemoteAddr,
sIcmpTypesAndCodes,
sInterfaceType: String;
bEnabled: Boolean;
nProfiles,
nProtocol,
nAction,
nDirection: Integer;
end;
TFwRule = record
sName,
sGroup,
sDesc,
sAppName,
sLocalPorts,
sLocalAddresses,
sRemotePorts,
sRemoteAddresses: String;
nProtocol,
nProfiles,
nAction,
nDirection: Integer;
bEnabled: Boolean;
end;
TFwRuleEntList = class(TList<PFwRuleEnt>)
protected
procedure Notify(const Item: PFwRuleEnt; Action: TCollectionNotification); override;
public
function GetFwRuleByName(sRuleName: String): PFwRuleEnt;
procedure AddAddedRule(aRule: TFwRule); // 추가한 룰을 새로고침 하지 않게 하기위해 임시 저장
procedure RemoveAddedRule(sFwName: String);
end;
function FwProfileToStr(nVal: Integer): String;
function FwProtocolToStr(nVal: Integer): String;
function GetFwRulesToList(aFwRules: INetFwRules; aList: TFwRuleEntList): Integer; overload;
function GetFwRulesToList(aFwPolicy: INetFwPolicy2; aList: TFwRuleEntList): Integer; overload;
function GetFwRulesToList(aList: TFwRuleEntList): Integer; overload;
function AddFwRule(aFwRules: INetFwRules; aRule: TFwRule): INetFwRule; overload;
function AddFwRule(aFwPolicy: INetFwPolicy2; aRule: TFwRule): INetFwRule; overload;
function AddFwRule(aRule: TFwRule): INetFwRule; overload;
function RemoveFwRule(aFwRules: INetFwRules; sRuleName: String): Boolean; overload;
function RemoveFwRule(aFwPolicy: INetFwPolicy2; sRuleName: String): Boolean; overload;
function RemoveFwRule(sRuleName: String): Boolean; overload;
procedure ClearCrmFwPolicy(aFwRules: INetFwRules = nil; bForce: Boolean = false; sHead: String = '');
implementation
uses
Tocsg.Exception, Winapi.ActiveX, System.Variants, Tocsg.Safe, Tocsg.Trace;
{ TFwRuleEntList }
procedure TFwRuleEntList.Notify(const Item: PFwRuleEnt; Action: TCollectionNotification);
begin
if Action = cnRemoved then
Dispose(Item);
end;
function TFwRuleEntList.GetFwRuleByName(sRuleName: String): PFwRuleEnt;
var
i: Integer;
begin
Result := nil;
for i := 0 to Count - 1 do
if CompareText(sRuleName, Items[i].sName) = 0 then
begin
Result := Items[i];
exit;
end;
end;
procedure TFwRuleEntList.AddAddedRule(aRule: TFwRule);
var
pEnt: PFwRuleEnt;
begin
New(pEnt);
ZeroMemory(pEnt, SizeOf(TFwRuleEnt));
with aRule do
begin
pEnt.sName := sName;
pEnt.sGroup := sGroup;
pEnt.sDesc := sDesc;
pEnt.sAppName := sAppName;
pEnt.sLocalPorts := sLocalPorts;
pEnt.sLocalAddr := sLocalAddresses;
pEnt.sRemotePorts := sRemotePorts;
pEnt.sRemoteAddr := sRemoteAddresses;
pEnt.nProtocol := nProtocol;
pEnt.nProfiles := nProfiles;
pEnt.nAction := nAction;
pEnt.nDirection := nDirection;
pEnt.bEnabled := bEnabled;
end;
Add(pEnt);
end;
procedure TFwRuleEntList.RemoveAddedRule(sFwName: String);
var
i: Integer;
begin
for i := 0 to Count - 1 do
if Items[i].sName = sFwName then
begin
Delete(i);
exit;
end;
end;
{ Function }
function FwProfileToStr(nVal: Integer): String;
begin
case nVal of
1 : Result := '도메인';
else Result := Format('Unknown(%d)', [nVal]);
end;
end;
function FwProtocolToStr(nVal: Integer): String;
begin
case nVal of
1 : Result := 'ICMPv4';
2 : Result := 'IGMP';
6 : Result := 'TCP';
17 : Result := 'UDP';
41 : Result := 'IPv6';
47 : Result := 'GRE';
58 : Result := 'ICMPv6';
256 : Result := '모두';
else Result := Format('Unknown(%d)', [nVal]);
end;
end;
function GetFwRulesToList(aFwRules: INetFwRules; aList: TFwRuleEntList): Integer;
var
fwRule: INetFwRule;
pEnum: IUnknown;
pVar: IEnumVARIANT;
v: OleVariant;
dwFetched: DWORD;
pEnt: PFwRuleEnt;
begin
aList.Clear;
Result := 0;
if aFwRules = nil then
exit;
try
pEnum := aFwRules.Get__NewEnum;
if pEnum = nil then
exit;
if SUCCEEDED(pEnum.QueryInterface(IEnumVARIANT, pVar)) then
begin
VariantClear(v);
while SUCCEEDED(pVar.Next(1, v, dwFetched)) do
begin
if VarIsEmpty(v) then
break;
if SUCCEEDED(IDispatch(v).QueryInterface(INetFwRule, fwRule)) then
begin
New(pEnt);
pEnt.sName := fwRule.Name;
pEnt.sGroup := fwRule.Grouping;
pEnt.sDesc := fwRule.Description;
pEnt.sSvrName := fwRule.serviceName;
pEnt.sAppName := fwRule.ApplicationName;
pEnt.sLocalPorts := fwRule.LocalPorts;
pEnt.sRemotePorts := fwRule.RemotePorts;
pEnt.sLocalAddr := fwRule.LocalAddresses;
pEnt.sRemoteAddr := fwRule.RemoteAddresses;
pEnt.sIcmpTypesAndCodes := fwRule.IcmpTypesAndCodes;
pEnt.sInterfaceType := fwRule.InterfaceTypes;
pEnt.bEnabled := fwRule.Enabled;
pEnt.nProfiles := fwRule.Profiles;
pEnt.nProtocol := fwRule.Protocol;
pEnt.nAction := fwRule.Action;
pEnt.nDirection := fwRule.Direction;
aList.Add(pEnt);
Inc(Result);
end;
VariantClear(v);
end;
end;
except
on E: Exception do
ETgException.TraceException(E, 'Fail .. GetFwRuleToList()');
end;
end;
function GetFwRulesToList(aFwPolicy: INetFwPolicy2; aList: TFwRuleEntList): Integer;
begin
aList.Clear;
Result := 0;
if aFwPolicy = nil then
exit;
Result := GetFwRulesToList(aFwPolicy.Rules, aList);
end;
function GetFwRulesToList(aList: TFwRuleEntList): Integer;
begin
Result := GetFwRulesToList(CoNetFwPolicy2.Create, aList);
end;
function AddFwRule(aFwRules: INetFwRules; aRule: TFwRule): INetFwRule;
var
FwMore: INetFwRule;
begin
Result := nil;
if aFwRules = nil then
exit;
try
Result := CoNetFwRule.Create;
with aRule do
begin
Result.Name := sName;
Result.Grouping := sGroup;
Result.Description := sDesc;
if sAppName <> '' then
Result.ApplicationName := sAppName;
if nProtocol = 0 then
Result.Protocol := NET_FW_IP_PROTOCOL_ANY
else
Result.Protocol := nProtocol;
Result.Profiles := nProfiles;
Result.Action := nAction;
if nDirection = 0 then
Result.Direction := NET_FW_RULE_DIR_OUT
else
Result.Direction := nDirection;
// fwRule.Protocol 설정전에 아래 포트들 설정하면
// 매개변수 잘못되었다는 오류나옴 22_0516 11:00:13 kku
if sLocalPorts <> '' then
Result.LocalPorts := sLocalPorts;
if sLocalAddresses <> '' then
Result.LocalAddresses := sLocalAddresses;
if sRemotePorts <> '' then
Result.RemotePorts := sRemotePorts;
if sRemoteAddresses <> '' then
Result.RemoteAddresses := sRemoteAddresses;
Result.Enabled := bEnabled;
aFwRules.Add(Result);
{$IFDEF _HE_}
// iexplore.exe는 하나 더 자동으로 등록해준다. 22_0726 13:16:13 kku
if (sAppName <> '') and (ExtractFileName(sAppName).ToLower = 'iexplore.exe') then
begin
if sAppName.Contains('(x86)') then
sAppName := StringReplace(sAppName, 'Files (x86)', 'Files', [rfReplaceAll, rfIgnoreCase])
else
sAppName := StringReplace(sAppName, 'Files', 'Files (x86)', [rfReplaceAll, rfIgnoreCase]);
if FileExists(sAppName) then
begin
FwMore := CoNetFwRule.Create;
FwMore.Name := sName + '2';
FwMore.Grouping := sGroup;
FwMore.Description := sDesc;
FwMore.ApplicationName := sAppName;
if nProtocol = 0 then
FwMore.Protocol := NET_FW_IP_PROTOCOL_ANY
else
FwMore.Protocol := nProtocol;
FwMore.Profiles := nProfiles;
FwMore.Action := nAction;
if nDirection = 0 then
FwMore.Direction := NET_FW_RULE_DIR_OUT
else
FwMore.Direction := nDirection;
// fwRule.Protocol 설정전에 아래 포트들 설정하면
// 매개변수 잘못되었다는 오류나옴 22_0516 11:00:13 kku
if sLocalPorts <> '' then
FwMore.LocalPorts := sLocalPorts;
if sLocalAddresses <> '' then
FwMore.LocalAddresses := sLocalAddresses;
if sRemotePorts <> '' then
FwMore.RemotePorts := sRemotePorts;
if sRemoteAddresses <> '' then
FwMore.RemoteAddresses := sRemoteAddresses;
FwMore.Enabled := bEnabled;
aFwRules.Add(FwMore);
end;
end;
TTgTrace.T('방화벽 규칙 추가. Name=%s', [sName], 2);
{$ENDIF}
end;
except
on E: Exception do
begin
Result := nil;
// ETgException.TraceException(E, 'Fail .. AddFwRule()');
ETgException.TraceException(E, Format('Fail .. AddFwRule(), RemoteAddresses=%s, RemotePorts=%s',
[aRule.sRemoteAddresses, aRule.sRemotePorts]));
end;
end;
end;
function AddFwRule(aFwPolicy: INetFwPolicy2; aRule: TFwRule): INetFwRule;
begin
Result := nil;
if aFwPolicy = nil then
exit;
if aRule.nProfiles = 0 then
aRule.nProfiles := FW_PROFILE_ANY;
// aRule.nProfiles := aFwPolicy.CurrentProfileTypes;
Result := AddFwRule(aFwPolicy.Rules, aRule);
end;
function AddFwRule(aRule: TFwRule): INetFwRule;
begin
Result := AddFwRule(CoNetFwPolicy2.Create, aRule);
end;
function RemoveFwRule(aFwRules: INetFwRules; sRuleName: String): Boolean;
begin
Result := false;
if aFwRules = nil then
exit;
try
if aFwRules.Item(sRuleName) <> nil then
aFwRules.Remove(sRuleName);
Result := true;
except
// on E: Exception do
// ETgException.TraceException(E, Format('Fail .. RemoveFwRule(), RuleName="%s"', [sRuleName]));
end;
end;
function RemoveFwRule(aFwPolicy: INetFwPolicy2; sRuleName: String): Boolean;
begin
Result := false;
if aFwPolicy = nil then
exit;
Result := RemoveFwRule(aFwPolicy.Rules, sRuleName);
end;
function RemoveFwRule(sRuleName: String): Boolean;
begin
Result := RemoveFwRule(CoNetFwPolicy2.Create, sRuleName);
end;
procedure ClearCrmFwPolicy(aFwRules: INetFwRules = nil; bForce: Boolean = false; sHead: String = '');
var
fwPolicy2: INetFwPolicy2;
FwRuleList: TFwRuleEntList;
i: Integer;
begin
try
if aFwRules = nil then
begin
fwPolicy2 := CoNetFwPolicy2.Create;
if fwPolicy2 = nil then
exit;
aFwRules := fwPolicy2.Rules;
end;
Guard(FwRuleList, TFwRuleEntList.Create);
if GetFwRulesToList(aFwRules, FwRuleList) = 0 then
exit;
for i := 0 to FwRuleList.Count - 1 do
begin
if FwRuleList[i].sName.StartsWith(sHead + 'eCrmHome') or
FwRuleList[i].sName.StartsWith(sHead + 'eCrmHE') or
(bForce and FwRuleList[i].sName.StartsWith('Tocsg')) then
RemoveFwRule(aFwRules, FwRuleList[i].sName);
end;
except
on E: Exception do
ETgException.TraceException(E, 'Fail .. ClearFwPolicy()');
end;
end;
end.