{*******************************************************} { } { ManagerService } { } { Copyright (C) 2022 kku } { } {*******************************************************} unit ManagerService; interface uses Tocsg.Obj, System.SysUtils, System.Classes, HandleConfig, ThdEvent, System.SyncObjs, ManagerModel, NicService, Winapi.Windows, Winapi.Messages, System.Generics.Collections, Tocsg.Thread, IdHTTP, IdSSLOpenSSL, IdIOHandler, FileService, VulnerabilityService, Tocsg.USB, ThdFirewall, ThdInstMon, ThdWebUrl, Tocsg.MSAA, Winapi.oleacc, ManagerPattern, Tocsg.Printer, ThdMtpMon, Tocsg.Bluetooth, CttSchDefine, ThdSchFileScan, Tocsg.Clipboard, ThdUsbMon, ManagerHook, ThdSendFiles, ThdWinUpdateScan, ThdRouteMon, Tocsg.Process, HandleSecurity, AppCtrlDefine, Tocsg.WndUtil, ManagerCampaign, ManagerRule, superobject, Define, ThdReaction, Vcl.Graphics, DSchPiNoti, Tocsg.Win32, Tocsg.Fasoo, ThdPrintWork, xPrintLogService, ManagerPrint, ThdScreenRecord, ProcessRecentDoc, Bs1FltCtrl, DeviceGuard.Logic; {$I Define.inc} const JSON_PI_TEST = 'PersonalInfo.json'; WM_POPUP_MSG = WM_USER + 3938; WM_POPUP_LICENSE = WM_POPUP_MSG + 1; WM_POPUP_MSG_SYSTEM = WM_POPUP_MSG + 2; WM_POPUP_AFTERREPORT = WM_POPUP_MSG + 3; WM_REFRESH_VIEW = WM_USER + 3951; WM_SCREENLOCK = WM_REFRESH_VIEW + 1; WM_REFRESH_CLIPBOARDCHAIN = WM_SCREENLOCK + 1; WM_REQ_AGENT_UNINSTALL = WM_REFRESH_CLIPBOARDCHAIN + 1; WM_REQ_FILETAG_CONTROL = WM_REQ_AGENT_UNINSTALL + 1; WM_REQ_KWDSCH_CONTROL = WM_REQ_FILETAG_CONTROL + 1; WM_UPDATE_SCREENLOGO = WM_REQ_KWDSCH_CONTROL + 1; WM_REQ_OUTLOOK_CONTROL = WM_UPDATE_SCREENLOGO + 1; WM_POPUP_PRINTWATER_PROGRESS = WM_REQ_OUTLOOK_CONTROL + 1; WM_POPUP_MSG2 = WM_POPUP_PRINTWATER_PROGRESS + 1; WM_POPUP_MSG_PI = WM_POPUP_MSG2 + 1; type TCheckAgentInfo = packed record sAgentId, sIp, sIps, sMAC, sAccount, sHostName, // sStatusType, sEulaCon, sLocation, sPwSet, sPwSetTermOk, sScrnLock, sOsVer, sAvInfo, // sAsInfo, sFwInfo, sOsSafe, sPatchExist, sAvSafe, sFwSafe, sAvUptodate, sPiSafe, // sSafeBlock, sModeName, sEmpNo: String; // bSafePcSHCD: Boolean; // 나중에 삭제 예정 23_0313 16:19:12 kku // 제거 24_0521 13:26:33 kku bJoinAD: Boolean; // AD 이행 여부 확인 for HEC, GEC 24_0521 13:27:02 kku end; TExpFun = record bUsb, bMtp, bBT, bWifi, bCB: Boolean; nUseMin: Integer; end; PFileExpEnt = ^TFileExpEnt; TFileExpEnt = record sPath, sHash: String; dtReg: TDateTime; end; TFileExpEntList = TList; PRecentFnd = ^TRecentFnd; TRecentFnd = record dtReg: TDateTime; curAppType: TCurAppType; sMName, sPath, sFounds, sFoundsC: String; bResult: Boolean; end; TRecentFndList = TList; PDpEnt = ^TDpEnt; TDpEnt = record dwTick, dwDSec: DWORD; sId: String; end; TDelayProcList = TList; TBS1ModeKind = (hmkSleep, hmkSecurity, hmkVulnerability, hmkOffline, hmkException); TManagerService = class(TTgObject) private CS_, CSDev_: TCriticalSection; // Force 설정 nForceLogLv_: Integer; bFirstAip_: Boolean; // DEV 버전에서 AIP 우선 적용할지 25_0909 14:52:52 kku HTTP_: TIdHTTP; SSL_: TIdSSLIOHandlerSocketOpenSSL; BS1ModeKind_: TBS1ModeKind; hRcvHwnd_: HWND; IgrEjectDrives_, ServerUrlList_, ActiveConnectList_: TStringList; nDestSvrIdx_: Integer; dwUNameChkTick_: DWORD; wURole_: WORD; // 사용자 역할, 0 : none, 1 : 결재자, 2 : 위임자 sUName_, // 현재 KOCES에서만 사용한다. 사용하려면 TimerProcessStatus()에서 업체 추가해야함 23_0328 07:44:45 kku, 2.7 신규서버 이상에서 사용 sEmail_, // 2.7 sDeptName_, // 2.7 신규서버 이상에서 사용 sEmpNo_, sAgentId_, sDestIPort_, sDestSvrUrl_, sVpnClient_, sExtraPort_, sAutoRunBlockKey_, sRecentPrintDocName_, // 가장 최근에 워터마크 또는 보안적용된 출력 문서 이름 23_0329 10:18:54 kku sNetworkPreventValue_, sNetworkExceptValue_, sNetworkPreventType_: String; bDoCbUpdate_, bIsEmpNoOk_, bDoEmpNoCheck_, bIsRouterOn_, bIsVpnNicOn_, bIsConnected_, bIsUninstall_, bIsTemporaryConn_, // 보안모드 임시 연결 // bIsNexgVpnRegistered_, bIsNetworkPrevent_: Boolean; dtCreateMg_, dtConnected_, dtChangeMode_: TDateTime; dwCheckSafePC_, // 신한카드 safePC 체크, 나중에 삭제해야함 23_0109 14:56:17 kku dwTempConnBegin_: DWORD; sEulaContent_, // 사용 동의서 내용 가지고 있게 22_0503 10:01:13 kku sNoticeContent_: String; // 한번 보여준 공지사항을 갖고 있는다, 업데이트 되면 비교해서 다시 보여주기 위함 22_0503 10:20:20 kku sModeName_, sDomain_, sComName_, sAccount_, sUserName_: String; bIsSafeExitImpossible_, bIsVpnClientON_, bIsRestricMac_: Boolean; bTryUnsafeActionsMin_, bIsPatchUptoDate_, // HandlePatch.isPatch bIsServiceAvailable_: Boolean; PrefModel_, PrefIdlModel_, PrefVulModel_, PrefOffline_, PrefExpPolicy_: TPrefModel; AgentModel_: TAgentModel; dtOldLogCheck_, dtSoftInstTick_, dtInfoFileCheck_: TDateTime; // 소프트웨어 설치 수집 체크 시간 MgCttSch_: TManagerCttSch; MgCttSchExp_: TManagerCttSchExcept; // MgCltFld_: TManagerCltFld; HandleConfig_: THandleConfig; HandleSecurity_: THandleSecurity; NicService_: TNicService; VulService_: TVulnerabilityService; ThdOsUpdateScan_: TThdWinUpdateScan; ThdEvent_: TThdEvent; ThdFW_: TThdFirewall; FileService_: TFileService; UsbNoti_: TTgUSBEventNotify; ThdInstMon_: TThdInstMon; ThdWebUrl_: TThdWebUrl; ThdBlueMon_: TThdBtDevNotify; ThdMtpMon_: TThdMtpMon; ThdPrinter_: TTgPrtSpoolWatch; ThdPrintWork_: TThdPrintWork; ThdUsbMonRO_: TThdUsbMon; EmDriveList_: TStringList; ThdRouteMon_: TThdRouteMon; ThdCapAppMon_, ThdBlockAppMon_: TThdProcessWatch; ThdCltFld_: TThdSendFilesFromDir; ThdScreenRecord_: TThdScreenRecord; MgHook_: TManagerHook; CapAppList_, MonAppList_, BlockAppList_, BlockAppWList_: TStringList; bIsMonApp_, bIsBlockApp_: Boolean; sMonApps_, sBlockApps_: String; ThdScanSch_: TThdSchFileScan; MgFnd_: TManagerFound; bTerminateThdScanSch_: Boolean; sSchRstPath_, sSchRstExpPath_: String; ThdTaskTimer_, ThdDevTaskTimer_, // 장치 차단이 오래 걸리는 경우가 있어서 별도 스레드 추가 25_1113 11:05:53 kku ThdStatusTimer_: TThdTaskTimer; sRecentUserSid_, sAgentPatchVersion_: String; dwSecuExitWaitTick_: DWORD; // 보안모드 해제 대기 23_1107 16:00:30 kku // 유프리즘 화상 회의 감지를 위함 22_0621 15:20:31 kku AccObj_SubTitle_: IAccessible; varSubTitle_: OleVariant; hEditWnd_: HWND; MgCampn_: TManagerCampaign; // 캠패인 관리 MgRule_: TManagerRule; // 룰 관리 bSchRstVul_, // 개인정보 임계치 bRcvRemoveAgent_, // 삭제 명령 받음 bPreNacChk_: Boolean; // 최근 NAC 연결 체크 dwSLSaveTick_, // SL 저장 간격 dwNacChkTick_: DWORD; // NAC 체크 간격 MgPtn_: TManagerPattern; PatternEntList_: TPatternEntList; // 상태전송, 정책 수신 주기 dwStatusInterval_: DWORD; // 컨텐츠 필터를 위함 sCbPatterns_, sPrintPatterns_, sWebABPatterns_, sEtcABPatterns_, sOutABPatterns_: String; CbPatternEnts_: TPatternEntList; BtcontentsFilter_list_, UsbcontentsFilter_list_, CdromcontentsFilter_list_, MtpcontentsFilter_list_, UsbToUsbcontentsFilter_list_: string; agentStatTime_: string; // RDP 로그인된 상태 체크 23_0926 08:58:58 kku bIsRdpLogon_: Boolean; // Shell context menu DRM mtxDrmEnc_, mtxDrmDec_, mtxPrtWater_: TTgMutex; // DRM 열람 권한 // mtxDrmOpen_: TTgMutex; // 백신 정보확인 주기 설정을 위함 (신한카드) // dtLastAvCheck_: TDateTime; // 상시로고, 화면 캡쳐 앱 제어 발동 APP sScreenLogoChkApps_, sScreenLogoChkUrls_, sScreenBlockChkApps_: String; ScreenLogoChkAppList, ScreenLogoChkUrlList, ScreenBlockChkAppList: TStringList; bForceScreenLogo_, bForceScreenCapAppBlock_: Boolean; nMonitorCnt_: Integer; sScreenLogoData_: String; wScreenVI_: WORD; // 문서 열람 관리 DcOpenDoc_: TDictionary; // 오프라인 정책 bIsOffline_: Boolean; dtApDisconn_, dtSvrDisconn_: TDateTime; // 예외 정책 bIsExpPolicy_: Boolean; nExpPoMin_: Integer; llChkTimeSec_: LONGLONG; dtExpPoBegin_: TDateTime; // 아웃룩 정책 // bInitOutMail_, bBlockOutlook_: Boolean; ThdWndMon_: TThdActiveWndMon; ThdAppMon_: TThdProcessWatch; // 프린트 워터마크 qWaterEnts_: TQueue; // tifHelp1_, // tifHelp2_: TWICImage; MgPwe_: TManagerPrtWaterExcept; // 프린트 워터마크 예외 sRecentLabel_: String; // GEC에서 최근 레이블값 사용 24_0513 15:53:58 kku // USB 최근 연결 USB sExceptUsbDev_, sExceptUsbDevKn_, sRecentUsbDrv_: String; UsbConnList_: TStringList; // 연결된 USB드라이브 목록 DriveList_: TStringList; // CD/DVD 예외 처리 정보 sCdException_, sCdExcepedList_, sFailCdBlock_: String; // API New, Old 구분 23_0801 14:40:13 kku bIsNewApi_, bCheckedFixDisk_: Boolean; sLastPolicy_: String; dtLastChangePW_, dtLastLogOn_: TDateTime; UseOptCodeList_: TStringList; // HttpPost() 오류 nHttpError_: Integer; sHttpError_: String; // 작업중인 캠패인 pProcCampn_: PCampnEnt; bClearCampn_, // 테스트를 위해 추가 bIsStopCampn_, // 캠페인 중지 됐나 bIgrLastWorkCampn_: Boolean; // 증분검사 테스트를 위함 llCampnEncCnt_, llCampnEncFailCnt_: LONGLONG; // 작업 스레드가 끝난 후에도 진행, 결과값을 알기 위해 백업 23_1214 16:31:27 kku DlgEncCampn_: TDlgSchPiNoti; NoMatchList_: TStringList; ThdReact_: TThdReaction; // 대응 스레드 dtLastChk_: TDateTime; // 시간 변경 체크 // 스크린 로고 진하게 bIsAppUseScreenLogo_, // 프로그램 사용 시 상시로고 진하게 추가 24_1016 19:19:46 kku bIsScreenLogoBold_, bIsIdleScreenLogo_, bIsIpMatchScreenLogo_, bIsRdpLogonScreenLogo_: Boolean; // 윈도우 7버전인가 bWin7Ver_: Boolean; // 프린트 마스킹... sPrtMaskingStr_: String; // RDP 해상도 체크, 조정 nRdpW_, nRdpH_: Integer; // 서브원 파일 생성 차단 알림은 최대 1분에 한번만 뜨게해야함 24_0718 10:57:03 kku dtSV1FileBlockNoti_: TDateTime; // AIP 모듈 실행 3번 실패 시 10분 다시 시도하도록 기능 추가 dwAipExeTick_: DWORD; // 출력 대기 MgPrint_: TManagerPrint; // UTC 시간 계산 (한국=+09:00) sUtcOffset_: String; // WM_ENDSESSION 처리 bIsEndSession_: Boolean; // 파일 반출 FileExpEntList_: TFileExpEntList; // 프린트 워터마크 1회 예외 bPrtWaterExcept_: Boolean; // 컨텐츠 필터를 통해 브라우저, 아웃룩, 프로세스 파일 차단 시 검출정보 25_0325 08:48:59 kku RecentFndList_: TRecentFndList; // 컨텐츠 룰 준비 bInitRule_: Boolean; // 파수 DRM 복호화를 위해 사용 fas_: TTgFasoo; // HW 정보 전송 bIsSendHWInfo_: Boolean; // xPrint 로그 처리 xPrintLogService_: TxPrintLogService; xPrintVer_: String; // 서버 연결 상태 체크 nChkConnSec_: Integer; dwTickChkConn_: DWORD; // 일정시간 이후 처리를 위한 체크 확인용 DelayProcList_: TDelayProcList; // 문서 파일 열람 확인 (임시, for LG디스플레이) 25_1106 RecentDocWatch_: TRecentDocWatch; // 필터 드라이버를 통한 장치제어 FltCtrl_: TBs1fltControl; bFltCtrlInit_ : Boolean; FltCtrlPolicy_: DWORD; DcFltCtrlEnt_: TDictionary; DeviceGuard_: TDeviceGuardEngine; sEjectWbDrive_: String; hEjectWbDrive_: THandle; bIgrPrtPause_: Boolean; procedure Lock; procedure Unlock; procedure DevLock; procedure DevUnlock; procedure UpdateEmptyUsbInfo; procedure CatchDriveSatate; function GetConnected: Boolean; function GetTemporaryConn: Boolean; procedure DoEjectCDROM; procedure DoEjectUsbDrive(sDrive: String; nType: Integer = -1); procedure DoEjectUsbDrives; procedure CheckHostAndUserInfo; procedure ProcessCampaign; procedure ProcessStatusOld(bFailChangeDestUrl: Boolean = true); procedure TimerCheckOsConfig(aSender: TObject); // // procedure TimerCheckConnect(aSender: TObject); procedure TimerCheckServiceAvailable(aSender: TObject); // procedure TimerCheckTemporaryConn(aSender: TObject); // << procedure TimerCheckConnect(aSender: TObject); // << procedure TimerProcessStatus(aSender: TObject); // << procedure TimerCheckSecurity(aSender: TObject); // procedure TimerCheckExpPo(aSender: TObject); // << procedure TimerProcessDevTask(aSender: TObject); // << function GetModePolicy: TPrefModel; procedure DeactivePolicyAll; function IsRunProcess(sChkProc: String; var sOldProc: String; OldProcList: TStringList; var bDetectProc: String): Boolean; function IsUseProcess(sChkProc: String; var sOldProc: String; OldProcList: TStringList; var bDetectProc: String): Boolean; function IsUseUrl(sChkUrl: String; var sOldUrl: String; OldUrlList: TStringList; var bDetectUrl: String): Boolean; procedure UpdatePolicyActive(aPrefModel: TPrefModel); procedure SetSchRstVul(bVal: Boolean); procedure LoadSchRstVul; function GetIsRestricDate: Boolean; procedure ProcessReleaseQuarantineFiles; function GetLastPolicy: String; procedure SetLastPolicy(sLP: String); procedure UpdateIgrUsbSerial4FltCtr(sData: String ; FltCtrlPolicy : DWORD); procedure UpdateFltCtrlEnts(sDrive, sDevInfo: String); function GetFltCrltEntInfo(sDrive: String): String; procedure ProcessUSBArrival(sDrive: String); procedure OnUSBArrival(Sender: TObject; pInfo: PDevBroadcastVolume); procedure OnUSBQueryRemove(Sender: TObject; sDrive: String; var bAccept: Boolean); procedure ProcessUSBRemove(sDrive: String); procedure OnUSBRemove(Sender: TObject; pInfo: PDevBroadcastVolume); function ProcessPreventBT(pEnt: PBtDevEnt; var bExcept: Boolean): Boolean; procedure OnBtDevEntNotify(pEnt: PBtDevEnt; csBT: TBTChangeStates; var bPrevent: Boolean); procedure OnPtrJobNotify(Sender: TThdPrtSpoolWatch; Job: TPrtJobInfo); procedure OnCapAppNotify(aSender: TThdProcessWatch; pEnt: PPwEnt; aKind: TProcessWatchKind); procedure OnBlockAppNotify(aSender: TThdProcessWatch; pEnt: PPwEnt; aKind: TProcessWatchKind); procedure OnWndNotify(aSender: TObject; hActiveWnd: HWND); procedure OnAppNotify(aSender: TThdProcessWatch; pEnt: PPwEnt; aKind: TProcessWatchKind); procedure OnWaterEntNotify(Sender: TObject; const Item: PPrtWaterEnt; Action: TCollectionNotification); procedure OnFileExpNotify(Sender: TObject; const Item: PFileExpEnt; Action: TCollectionNotification); procedure OnRecentFndNotify(Sender: TObject; const Item: PRecentFnd; Action: TCollectionNotification); procedure OnDpEntNotify(Sender: TObject; const Item: PDpEnt; Action: TCollectionNotification); // function FindAipMdWnd(bForceUp: Boolean = false): HWND; function IsUsbDrvConn: Boolean; // 티맵 사번 체크 보정 23_1212 18:39:24 kku procedure CheckEmpNo_TMAP; function GetModeKind: TBS1ModeKind; procedure SetModeKind(aKind: TBS1ModeKind); procedure SetModeName(sModeName: String); function GetModeName: String; public AgentInfo: TCheckAgentInfo; UpdateTick: DWORD; // AIP AipFailCnt: Integer; // 모듈 실행/연동 실패 카운트 24_0704 08:51:53 kku UseApproval: Boolean; // xPrint Data Update Datetime dtOneDay_: TDateTime; // 하루 한번만 업데이트 체크, 임시 25_0924 14:56:30 kku EmpsUpDt, PrtsUpDt, BillUpDt, MkcdUpDt, LumpUpDt: String; sTmpAcc_: String; // 테스트 기능 SharePcPrintBlock, WSDPortPrintBlock, TcpIpPrintBlock, PrintSavingBlock: Boolean; Constructor Create(hRcvHwnd: HWND); Destructor Destroy; override; function RecentUserSid: String; procedure ChangeDestinationUrl; procedure DoClipboardUpdate; procedure StopService; procedure SetConnected(bVal: Boolean; bNewApi: Boolean); function HttpPost(sDest, sRqType, sParam: String; pnRespCode: PInteger = nil): String; function MakeComponentId(sTail: String): String; function GetCbFoundContentToJsonObj(sText: String; var sResultStr: String): ISuperObject; procedure UpdateInternalInfo; procedure OgnRecentFndList; function GetRecentFnd(sPath: String; var aEnt: TRecentFnd): Boolean; procedure AddDelayProcEnt(sId: String; dwDSec: DWORD); function HasDelayProcEntById(sId: String): Boolean; procedure AddRecentFnd(aEnt: TRecentFnd); procedure DelRecentFnd(sPath: String); procedure SetPatternList(sPatternOpt: String; var aList: TPatternEntList); procedure SetRuleToPtrnList(sRuleIds: String; var aList: TPatternEntList; bUseRName: Boolean = false); function GetAipUPN: String; function FindAipMdWnd(bForceUp: Boolean = false): HWND; // 문서 열람 관리 (LGD) function AddOpenDoc(dwPid: DWORD; sPath: String): Boolean; procedure DelOpenDocProc(dwPid: DWORD); function SendPrintImgFiles(sImgPath, sImgOutDir: String; nCollectMax: Integer = 0; aRespaction: TCampnRespaction = crtNone): String; function SendPrintEmfFiles(sEmfDir, sImgOutDir: String; nCollectMax: Integer = 0; aRespaction: TCampnRespaction = crtNone): String; procedure SetRouterOn(bVal: Boolean); procedure SetVpnNicOn(bVal: Boolean); procedure SetPatchUpdate(bIsUptoDate: Boolean); procedure SetServiceAvailable(bVal: Boolean); procedure SetTemporaryConn(bVal: Boolean); // procedure SetNexgVpnRegistered(bVal: Boolean); procedure SetNetworkPrevent(bVal: Boolean); procedure SetNetworkPreventVal(sVal: String); procedure SetNetworkExceptVal(sVal: String); procedure SetNetworkPreventType(sVal: String); procedure SetExtraPort(sVal: String); procedure SetRecentPrintDocName(sVal: String); procedure AddPrtHookJob(aO: ISuperObject); procedure UpdateAgentInfo; procedure SendEventLog(sUri, sCode, sMsg: String; bPrevent: Boolean = true); procedure SendEventLogEx(pInfo: PLogInfo; bPrevent: Boolean = true; dtLog: TDateTime = 0); overload; procedure SendEventLogEx(sCode, sSummary: String; bPrevent: Boolean = true; dtLog: TDateTime = 0); overload; procedure SendRequest(sCode: String; aExptInfo: TReqDevExceptInfo; sComment, sBeginDate, sDueDate: String; nTarget: Integer; sMsg: String); // target : 0 - 해당 pc, 1 - 해당 사용자, 2 - 해당 부서, 3-전체 procedure SendFile(var LogInfo: TLogInfo; sApi, sPath: String; nMinMB: Integer = 0; nLimitMB: Integer = 50; aRespaction: TCampnRespaction = crtNone; nRespDelaySec: Integer = 0); procedure SendFileNor(bSendBin: Boolean; sCompId, sApi, sPath: String; nMinMB: Integer = 0; nLimitMB: Integer = 50; aRespaction: TCampnRespaction = crtNone; nRespDelaySec: Integer = 0); procedure SendCttSchProgInfo(aProg: TCttSchProg); procedure SendCampnProgInfo(aProg: TCttSchProg); procedure SendCttSchDetailInfo(sTaskId: String; pResult: PSchResult; nProcType: Integer); procedure SendAppInstInfo; function SendHwInfo: Boolean; procedure SendScreenRecord(sReason, sMp4Path: String; nMilSec: Integer); //mgkim procedure SendAuditLog(const JsonReport: string); function SendApproval(nType: Integer; pData: Pointer; bUpFileCnt: Integer = 0): String; procedure SendAgreeInfo; function GetApprovalUrl(sReqType: String): String; function GetRegPerInfoUrl: String; function GetPostData(sUrl, sData: String; sReqType: String = ''): String; function DirectSendEventLog(sUri, sCode, sMsg: String; bPrevent: Boolean = false): Boolean; procedure PopupMessage(nType: Integer; sData: String = ''); procedure PopupSystemMsg(nType: Integer); procedure PopupLicensed; procedure PopupAfterReport; procedure RefreshView; procedure UpdateScreenLogo(bForce: Boolean = false); procedure DoCheckOsUpdate; procedure ProcessVpnConnect; procedure ProcessVpnDisconnect; function IsOfflineMode: Boolean; procedure OnUnzipProgress(Sender : TObject; Progress : Byte; var Abort : Boolean); procedure OnPwdEvent(Sender : TObject; var NewPassword : String); function HasContentInfo(sMName, sPath: String; aAppType: TCurAppType): Boolean; function IsSearchingPersonalInfo: Boolean; // 구 개인정보 검사 procedure StartPiSchTask(aOpt: TFileScanOpt; dtScan: TDateTime; bSendEvent: Boolean = true); procedure StopPiSchTask; procedure OnPiSchTaskBegin(aSender: TObject); procedure OnPiSchTaskEnd(aSender: TObject); procedure ProcessPiSchFound(pResult: PSchResult); // 캠패인 검사 procedure StartCampaignTask(pCamEnt: PCampnEnt); procedure StopCampaignTask; procedure OnCampaignTaskBegin(aSender: TObject); procedure OnCampaignTaskEnd(aSender: TObject); procedure ProcessCampnFound(pResult: PSchResult); procedure UpdateCttSchVulState(bForce: Boolean = false); function ProcessMergeCampaignBkData(OInfo: ISuperObject): Integer; procedure AddFileExpEnt(sPath, sHash: String); procedure SaveFileExpEnt; procedure LoadFileExpEnt; procedure OrganizeFileExpEnt; function HasFileExp(sPath: String): Boolean; procedure DoPrint(pEnt: PPrtEnt); function IsScreenLogo: Boolean; procedure SetExpPolicyActive(aFun: TExpFun); procedure ClearExpPolicy; procedure AddPrintWaterEnt(pWEnt: PPrtWaterEnt); procedure ProcessPrintWaterEnt; procedure ResetPersonalScan; procedure RetryPersonalScan; // function IsHecDev: Boolean; // HEC 개발계인가? function GetAipPath: String; function GetUrlBlockList: String; procedure AddEncIgr(sPath: String); procedure AddAfterEnc(sPath: String); function HasEncIgr(sPath: String; bChkDel: Boolean = false): Boolean; procedure ProcessEndSession; property RcvHwnd: HWND read hRcvHwnd_; property DestServerUrl: String read sDestSvrUrl_; property Connected: Boolean read GetConnected; property VpnClient: String read sVpnClient_; property IsRouterOn: Boolean read bIsRouterOn_; property IsVpnNicOn: Boolean read bIsVpnNicOn_; property IsUninstall: Boolean read bIsUninstall_; property IsTemporaryConn: Boolean read GetTemporaryConn; property IsVpnClientON: Boolean read bIsVpnClientON_ write bIsVpnClientON_; property IsSafeExitImpossible: Boolean read bIsSafeExitImpossible_ write bIsSafeExitImpossible_; property IsRestricMac: Boolean read bIsRestricMac_; property IsRestricDate: Boolean read GetIsRestricDate; property TempConnBegin: DWORD read dwTempConnBegin_; // property IsNexgVpnRegistered: Boolean read bIsNexgVpnRegistered_; property ActiveConnectList: TStringList read ActiveConnectList_; // property RouterDefList: TRouterList read RouterDefList_; property ExtraPort: String read sExtraPort_; property IsEmpNoOk: Boolean read bIsEmpNoOk_ write bIsEmpNoOk_; // [사검] property UName: String read sUName_ write sUName_; property Email: String read sEmail_; property DeptName: String read sDeptName_ write sDeptName_; property EmpNo: String read sEmpNo_; property Domain: String read sDomain_; property UserName: String read sUserName_; property ComName: String read sComName_; property Account: String read sAccount_; property AgentId: String read sAgentId_; // property ActiveThdreadProcess: Boolean write SetActiveThdreadProcess; property IsServiceAvailable: Boolean read bIsServiceAvailable_; property IsPatchUptoDate: Boolean read bIsPatchUptoDate_; property EulaContent: String read sEulaContent_; property HandleConfig: THandleConfig read HandleConfig_; property HandleSecurity: THandleSecurity read HandleSecurity_; property NicService: TNicService read NicService_; property VulService: TVulnerabilityService read VulService_; property AgentModel: TAgentModel read AgentModel_; property PrefModel: TPrefModel read PrefModel_; property SleepPolicy: TPrefModel read PrefIdlModel_; property VulPolicy: TPrefModel read PrefVulModel_; property ModePolicy: TPrefModel read GetModePolicy; property HeModeKind: TBS1ModeKind read GetModeKind; property ThdScanSch: TThdSchFileScan read ThdScanSch_; property ThdWebUrl: TThdWebUrl read ThdWebUrl_; property ThdPrintWork: TThdPrintWork read ThdPrintWork_; property ThdOsUpdateScan: TThdWinUpdateScan read ThdOsUpdateScan_; property IsSchRstVul: Boolean read bSchRstVul_ write SetSchRstVul; property MgHook: TManagerHook read MgHook_; property ChangeModeDT: TDateTime read dtChangeMode_ write dtChangeMode_; property ServerUrlList: TStringList read ServerUrlList_; property MgCttSch: TManagerCttSch read MgCttSch_; property MgCttSchExp: TManagerCttSchExcept read MgCttSchExp_; property MgPwe: TManagerPrtWaterExcept read MgPwe_; property MgPrt: TManagerPrint read MgPrint_; property DoEmpNoCheck: Boolean read bDoEmpNoCheck_ write bDoEmpNoCheck_; // property ApDisconnDT: TDateTime read dtApDisconn_ write dtApDisconn_; property LastChangePwDT: TDateTime read dtLastChangePW_; // property IsOffline: Boolean read bIsOffline_ write bIsOffline_; property IsOfflineExp: Boolean read bIsExpPolicy_; property OffPolicy: TPrefModel read PrefOffline_; property ExpPolicy: TPrefModel read PrefExpPolicy_; property ExpPolicyBeginDT: TDateTime read dtExpPoBegin_; property ExpPolicyUseMin: Integer read nExpPoMin_; property UseOptCodeList: TStringList read UseOptCodeList_; property DestIPort: String read sDestIPort_; property HTTP: TIdHTTP read HTTP_; // property LastPolicy: String read sLastPolicy_ write sLastPolicy_; property LastPolicy: String read GetLastPolicy write SetLastPolicy; property HttpErrorCode: Integer read nHttpError_; property HttpErrorMsg: String read sHttpError_; property EventLog: TThdEvent read ThdEvent_; property IsScreenLogoBold: Boolean read bIsScreenLogoBold_; property IsIpMatchScreenLogo: Boolean read bIsIpMatchScreenLogo_ write bIsIpMatchScreenLogo_; property IsWin7Ver: Boolean read bWin7Ver_; property IsStopCampn: Boolean read bIsStopCampn_; property CampnEnc: LONGLONG read llCampnEncCnt_; property CampnEncFail: LONGLONG read llCampnEncFailCnt_; property DlgEncCampn: TDlgSchPiNoti read DlgEncCampn_ write DlgEncCampn_; property RcvRemoveAgent: Boolean read bRcvRemoveAgent_ write bRcvRemoveAgent_; property UserRole: WORD read wURole_ write wURole_; property IsPrtWaterExcept: Boolean read bPrtWaterExcept_ write bPrtWaterExcept_; property PrtMaskingStr: String read sPrtMaskingStr_ write sPrtMaskingStr_; property PrintPatterns: String read sPrintPatterns_; property RecentLabel: String read sRecentLabel_ write sRecentLabel_; property RecentPrintDocName: String read sRecentPrintDocName_; property xPrintVer: String read xPrintVer_ write xPrintVer_; property ThdxPrintLog: TxPrintLogService read xPrintLogService_; property ForceLogLv: Integer read nForceLogLv_; property FirstAip: Boolean read bFirstAip_; property IsNewApi: Boolean read bIsNewApi_; property MgCampn: TManagerCampaign read MgCampn_; property MgRule: TManagerRule read MgRule_; property MgPrint: TManagerPrint read MgPrint_; property ProcCampn: PCampnEnt read pProcCampn_; property ThdReact: TThdReaction read ThdReact_; property IsRdpLogon: Boolean read bIsRdpLogon_; property FileService: TFileService read FileService_; property ModeName: String read GetModeName; property UtcOffset: String read sUtcOffset_; end; function ExtrTextFromFile(sPath: String; bIgrImg: Boolean = false): String; function GetDefAipLabelId(bEncCamp: Boolean = false): String; function ExtrTextFromPrintImgFiles(sImgPath: String; aAngle: Extended = 0): String; function ExtrTextFromPrintEmfFiles(sEmfDir: String; aAngle: Extended = 0): String; procedure SetPrtJobFromHelperApp(aJob: TPrtJobInfo; dwCmd: DWORD); function EmfToPng(const sEmfPath, sPngPath: string; nDPI: Integer = 96; aBackColor: TColor = clWhite): Boolean; function GetFileToSha1Str_BS1(sPath: String): String; var gMgSvc: TManagerService = nil; resourcestring RS_SleepMode = '수면모드'; RS_HEC_SleepMode = '사외모드'; RS_SecuMode = '보안모드'; RS_HEC_SecuMode = '사내모드'; RS_VulMode = '취약모드'; RS_OfflineMode = '오프라인'; RS_UnverifiedMode = '미인증'; RS_OfflineExpMode = '예외사용'; RS_MsgChangeMode = '"%s" 로 변경 되었습니다.'; RS_MsgChangeMode2 = '"%s" 모드로 변경 되었습니다.'; RS_WatchNetState = '네트워크 연결상태를 확인해주세요.'; implementation uses //GlobalSLCore, SearchLightClient, Tocsg.Safe, Tocsg.Strings, Condition, CrmLogger, CrmUtil, Tocsg.Convert, Tocsg.Exception, License, Tocsg.WTS, IdGlobal, IdTCPClient, Tocsg.Disk, Tocsg.Driver, Tocsg.Path, GlobalDefine, Tocsg.WscApi, System.DateUtils, System.Zip, Tocsg.Files, Tocsg.WinInfo, Tocsg.DateTime, Tocsg.Registry, Tocsg.Trace, Winapi.ActiveX, Tocsg.Network, Winapi.WinSpool, EM.jwabluetoothapis, Tocsg.PCRE, Tocsg.AppInfo, System.Variants, Tocsg.Json, Tocsg.Shell, ManagerPerInfo, Tocsg.Encrypt, Tocsg.DRM.Encrypt, ParserLinkFile, IdMultipartFormData, Tocsg.Packet, System.IniFiles, IdExceptionCore, SecureApp, BsKwdSchKvCttSchClient, GlobalOutAddInDefine, OutlookMonClient, IdException, Tocsg.Url, ThdExecuteEndNoti, SynPdf, Vcl.Printers, Vcl.Imaging.pngimage, aes_type, Tocsg.Hex, aes_cbc, ProcessServerAPI, System.Hash, imageen, hyieutils, ManagerFixedDisk, Tocsg.Delete, Tocsg.Graphic, Winapi.GDIPAPI, Vcl.Imaging.jpeg, ManagerImgMskData, Vcl.Forms, STLabGuardModule, System.Win.Registry, System.Generics.Defaults, Tocsg.Kess, DefineHelper, System.TimeSpan, ProcessSoftcampDRM, Tocsg.Hash, Tocsg.Fasoo.Global, ProcessDecompress, Tocsg.WMI, System.IOUtils, Tocsg.Valid, EM.PdfiumCore, System.Math, Tocsg.Service, Winapi.WinSvc, ThdRcvPolicy, Tocsg.AIP, IdStack, ThdInitProc, ProcessPrint, ProcessPrintWater, Tocsg.FileInfo, System.Masks; var // _bmpWaterP: TBitmap = nil; _bmpST: TBitmap = nil; //const // JSON_CONNCHECK = '{"Request : ConnectionCheck"}'; var _CheckVpnProcs: String = ''; _CheckVpnList: TStringList = nil; function GetDefAipLabelId(bEncCamp: Boolean = false): String; begin case CUSTOMER_TYPE of CUSTOMER_DEV : begin if bEncCamp then Result := 'a86ece2e-0ab0-4e24-8aca-c410c0ecab59' // 대외비 else Result := '946ee615-f74c-4312-ac00-17ccc40d3504'; // 대외비 개인정보 end; CUSTOMER_GEC, CUSTOMER_HDENG : begin if bEncCamp then Result := 'cdcaf456-5176-400c-b0e6-6301b2c47597' // 대외비 else Result := '9877e059-3e04-4eba-ad87-888eb0c7e9ba'; // 대외비 개인정보 end; // CUSTOMER_HAE : Opt.CttSchOpt.sAipLabelId := 'a5b98469-3cf3-4f5e-ad43-b098cf00ed03'; // CUSTOMER_JUVIS : Result := '2e3dfd6a-d02d-4d3a-9b4e-7566f8653478'; // 대외비 CUSTOMER_HCA : Result := 'c4742a8b-ba73-461d-b4fd-1adcac5fcdde'; // 평문 CUSTOMER_KDNVN : Result := 'e7bd3a2c-b905-4bdb-8892-e6cd8d1eb00b'; // 대외비 CUSTOMER_UNITUS : Result := 'afd3f50f-3ef1-4996-bd1b-16799f799fe2'; // 개인정보(Privacy) 25_0325 09:39:25 kku, '486b827d-7fb1-48c7-a363-db75665f1ecd'; // Secret CUSTOMER_MOTRAS : Result := '49459909-2e25-4650-b7cf-dfff204b8977'; // 개인정보(Privacy) 25_0416 10:07:22 kku, 'dca5269d-a66f-4bbb-9ee0-593c30687184'; // 대외비 (Employee Only) CUSTOMER_SKEC : Result := 'b460538c-150a-470c-8f77-8a530e2f607f';// 사내 한 //' b31df88e-5819-4d7e-8cd4-caebd9b5e897'; // 보호문서 CUSTOMER_CJONS : Result := 'a7082a6c-0558-48a5-a82a-128def7f07c5'; // 그룹한 CUSTOMER_WHANIN : Result := 'f7514e58-6d0e-452b-bd2a-dde9e2bd3b93'; // Internal > Whanin else Result := ''; end; end; procedure InstallOutlookPlugIn_forHD(h: HWND); inline; var sDir, sHlpExe: String; begin try sDir := GetRunExePathDir + DIR_CONF; sHlpExe := sDir + EXE_HLP; if FileExists(sHlpExe) then begin var O: ISuperObject := SO; O.I['RcvWnd'] := h; O.B['RunAs'] := true; O.I['Cmd'] := HPCMD_INSTALL_OUTLOOK_ADDIN; O.S['MdDir'] := sDir; SaveJsonObjToFile(O, sDir + DAT_PARAM); if FileExists(sDir + DAT_PARAM) then begin {$IFDEF DEBUG} ExecutePath(sHlpExe); TTgTrace.T('Outlook 플러그인 설치 시도..', 3); {$ELSE} ExecuteAppAsUser('explorer.exe', sHlpExe, '', SW_SHOWNORMAL); ExecuteAppAsUser('msedge.exe', sHlpExe, '', SW_SHOWNORMAL); TTgTrace.T('Outlook 플러그인 설치 시도...', 3); {$ENDIF} end else TTgTrace.T('Error .. Outlook 플러그인 설치 파라메터 오류..', 3); if FileExists(sDir + 'PATCH.exe') then begin TTgTrace.T('Outlook 플러그인 설치 PATCH..', 3); ExecuteAppAsUser('explorer.exe', sDir + 'PATCH.exe', '', SW_SHOWNORMAL); ExecuteAppAsUser('msedge.exe', sDir + 'PATCH.exe', '', SW_SHOWNORMAL); end; end else TTgTrace.T('[InstOutPlug] Helper 프로세스를 찾을 수 없습니다.', 1); except on E: Exception do ETgException.TraceException(E, 'Fail .. InstallOutlookPlugIn_forHD()'); end; end; function ExtractLogValue(const Source, Key: string): string; var P, PEnd: Integer; begin Result := ''; P := Pos(Key, Source); if P > 0 then begin Inc(P, Length(Key)); PEnd := P; while (PEnd <= Length(Source)) and (Source[PEnd] <> ',') do Inc(PEnd); Result := Trim(Copy(Source, P, PEnd - P)); end; end; procedure ProcessUsbLogString(const sRecvMsg: string); var sVid, sPid: string; sFriendlyName, sBlkSerial, sDrive, sType, sClassGuid: string; llSize: Int64; nPos : Int32; begin if Pos('DISABLE(1)', sRecvMsg) = 0 then Exit; sDrive:= 'USB:'; llSize:= 0; // 예: sRecvMsg = '... Vid: 0x346D, Pid : 0x5678, Serial : 8328501217610604362' sVid := ExtractLogValue(sRecvMsg, 'Vid:'); sPid := ExtractLogValue(sRecvMsg, 'Pid :'); // 원본 문자열의 공백 주의 sBlkSerial := ExtractLogValue(sRecvMsg, 'Serial :'); // Vid와 Pid를 조합하여 장치 식별 이름(FriendlyName) 생성 sVid := StringReplace(sVid, '0x', '', [rfReplaceAll, rfIgnoreCase]); sPid := StringReplace(sPid, '0x', '', [rfReplaceAll, rfIgnoreCase]); sFriendlyName := Format('USB_VID_%s&PID_%s', [sVid, sPid]); if gMgSvc.ModePolicy.USBPopup then begin var sRegSerial: String := sBlkSerial; gMgSvc.PopupMessage(TYPE_MSG_PREVENT_USBDISCONN, sDrive + '*9*' + ByteSizeToStr(llSize) + '*9*' + sFriendlyName + '*9*' + sType + '*9*' + sRegSerial); end; var sMsg: String := Format('USB Blocked : Name=%s, Drive=%s (%s), Type=%s, Serial=%s', [sFriendlyName, sDrive, ByteSizeToStr(llSize), sType, sBlkSerial]); if gMgSvc.bIsNewApi_ then begin var LogInfo: TLogInfo; ZeroMemory(@LogInfo, SizeOf(LogInfo)); LogInfo.sCode := LOGCODE_PREVENT_USB; LogInfo.sDevName := sFriendlyName; LogInfo.sDevSerial := sBlkSerial; LogInfo.sDevClassId := sClassGuid; LogInfo.sSummary := sMsg; gMgSvc.SendEventLogEx(@LogInfo); end else gMgSvc.SendEventLog(URI_USER_ACTION, LOGCODE_PREVENT_USB, sMsg); end; function FltCtrlCallback(sContext: Pointer): DWORD; stdcall; var sLog: String; nPos: Integer; O: ISuperObject; begin if sContext = nil then exit; sLog := String(PChar(sContext)); TThread.Queue(nil, procedure begin {$IFDEF DEBUG} gMgSvc._Trace(sLog, 1); {$ELSE} gMgSvc._Trace('[MGKIM] %s', [sLog], 5); {$ENDIF} nPos := Pos('{', sLog); if nPos > 0 then begin Delete(sLog, 1, nPos - 1); O := SO(sLog); if O.S['name'] <> '' then gMgSvc.UpdateFltCtrlEnts(O.S['name'] + '\', Trim(O.S['vid']) + '§' + Trim(O.S['pid']) + '§' + Trim(O.S['serial'])); end else begin ProcessUsbLogString(sLog) end end); Result := 0; end; { TManagerService } Constructor TManagerService.Create(hRcvHwnd: HWND); procedure InitHttp; begin try SSL_ := TIdSSLIOHandlerSocketOpenSSL.Create(nil); SSL_.SSLOptions.Method := sslvSSLv23; SSL_.SSLOptions.SSLVersions := [sslvTLSv1_2, sslvTLSv1_1, sslvTLSv1]; HTTP_ := TIdHTTP.Create(nil); HTTP_.IOHandler := SSL_; with HTTP_ do begin // HandleRedirects := true; // Request.BasicAuthentication := true; Request.Clear; Request.UserAgent := 'Mozilla/5.0'; Request.ContentType := 'application/json; charset=utf-8'; //'application/xml'; Request.Accept := 'application/json; charset=utf-8'; Request.Charset := 'utf-8'; // Request.Connection := 'Keep-Alive'; // Request.CustomHeaders.Values['Keep-Alive'] := 'timeout=300, max=100'; Request.Connection := 'close'; HTTPOptions := HTTPOptions - [hoKeepOrigProtocol]; case CUSTOMER_TYPE of CUSTOMER_DEMO : begin ConnectTimeout := 3000; ReadTimeout := 10000; end; CUSTOMER_KFTC : begin ConnectTimeout := 3000; ReadTimeout := 30000; end; CUSTOMER_KR : begin ConnectTimeout := 10000; ReadTimeout := 60000; end; CUSTOMER_SHCD : begin // 신한카드 타임아웃 180초 23_0327 14:18:03 kku // 다시 30, 60초로 변경 23_0410 08:28:17 kku ConnectTimeout := 30000; ReadTimeout := 60000; end; else begin ConnectTimeout := 5000; ReadTimeout := 30000; end; end; end; except end; {$IFDEF DEBUG} var O: ISuperObject; var sRes := GetEmpNoInfo(DestServerUrl, HTTP_, sEmpNo_); if sRes = '' then exit; try O := SO(sRes); except exit; end; if (O.S['result'] = 'false') or (O.S['deleteyn'] <> 'false') then begin // 에이전트 사번 정보가 없거나 삭제 상태라면 설치 로그를 보내준다 23_0403 09:43:04 kku // SendEventLog(URI_CONNECT, SYSEVT_AGENT_INSTALL, '[TEST] Agent first connected'); // 서버에서 마지막 모드 로그로 현재 에이전트 모드를 판별하게 되는데 최초 정보가 없으면 에이전트 목록에 보이지 않게 된다. 23_0403 13:22:43 kku SendEventLog(URI_USER_ACTION, MODE_SECURITY_END, '[DEBUG..REG] Sleep mode'); end; {$ENDIF} end; procedure InitAgentInfo; var sPath: String; ss: TStringStream; StrList: TStringList; begin UpdateAgentInfo; if (sEmpNo_ = '') or (sAgentId_ = '') then begin _Trace('InitAgentInfo() .. Not found AgentInfo ..'); if IsAccountEmpNo then exit; // todo : 앞으로 eCrmManager 업데이트 후 에이전트 정보와 정책을 받아와야 한다. 22_0502 16:23:28 kku {$IFDEF DEBUG} sEmpNo_ := 'kjkim'; {$ELSE} sEmpNo_ := 'Empty'; // GetRandomString(8); {$ENDIF} sPath := GetProgramFilesDir + DIR_HE + DIR_CONF + PROP_USERINFO; if FileExists(sPath) then begin Guard(ss, TStringStream.Create('', TEncoding.UTF8)); ss.LoadFromFile(sPath); Guard(StrList, TStringList.Create); if SplitString(DecryptStr(ss.DataString), '---', StrList) > 1 then begin sEmpNo_ := StrList[0]; // sVpnId_ := StrList[1]; end; end; sAgentId_ := GetAgentId(sEmpNo_); with AgentModel_ do begin if NicService_ <> nil then begin IP := NicService_.GetIP; MAC := NicService_.GetMAC; end else begin IP := '1.2.3.4'; MAC := 'aaaaaaaa'; end; if IsUseHostNameOnly then HostName := sComName_ else if VulService_ <> nil then HostName := VulService_.WindowsAccount else HostName := 'hostname'; LastConn := Now; Version := SdkVersion; AgentId := sAgentId_; EulaDT := 0; Location := 'Unknown'; // VpnInfo := sVpnId_; _Trace('[05] 사번 변경, %s > %s', [EmpNo, sEmpNo_]); // SendEventLogEx(LOG_CHANGE_EMPNO, Format('[Init] EmpId Changed. (%s > %s)', [EmpNo, sEmpNo_]), false); EmpNo := sEmpNo_; end; // AgentModel_.Save; 아래에서 함 22_0721 15:24:12 kku end; if CUSTOMER_TYPE = CUSTOMER_LOTTEMART then begin // 실행마다 NAC에서 유저 ID값 가져오기 sPath := GetRegValueAsString(HKEY_LOCAL_MACHINE, 'SOFTWARE\Geni\Genian\Common', 'Auth'); if sPath.Length > 2 then begin // MT는 롯데마트, SP는 롯데슈퍼 if sPath.ToUpper.StartsWith('MT') or sPath.ToUpper.StartsWith('SP') then Delete(sPath, 1, 2); if AgentModel_.EmpNo <> sPath then begin _Trace('[04] 사번 변경, %s > %s', [AgentModel_.EmpNo, sPath]); SendEventLogEx(LOG_CHANGE_EMPNO, Format('[LT_Init] EmpId Changed. (%s > %s)', [AgentModel_.EmpNo, sPath]), false); AgentModel_.EmpNo := sPath; AgentModel_.Save; end; end; end; end; procedure InitDefCttPattern; const TAG_INFOS = '주민등록번호|전화번호|차량번호|이메일주소'; var StrList: TStringList; PtrnEnt: TPatternEnt; i: Integer; begin MgPtn_ := TManagerPattern.Create; MgPtn_.LangId := $0412; PatternEntList_ := TPatternEntList.Create(false); Guard(StrList, TStringList.Create); SplitString(TAG_INFOS, '|', StrList); for i := 0 to StrList.Count - 1 do begin PtrnEnt := MgPtn_.GetPatternEntByName(StrList[i]); PatternEntList_.Add(PtrnEnt); end; MgPtn_.LangId := 1; // 컨텐츠 필터 사용을 위함 end; procedure LoadSetting; var ini: TIniFile; sTemp: String; begin Guard(ini, TiniFile.Create(GetProgramFilesDir + DIR_TG + INI_FORCEHE)); nForceLogLv_ := ini.ReadInteger('Force', 'LogLv', 0); if nForceLogLv_ > 0 then begin gTrace.Level := nForceLogLv_; gTrace.LevelLock := true; end; if CUSTOMER_TYPE = CUSTOMER_DEV then bFirstAip_ := ini.ReadBool('Force', '1AIP', false); // dtLastAvCheck_ := ini.ReadDateTime('Customer', 'LastAvCheck', 0); sTemp := RecentUserSid + '\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced'; if CUSTOMER_TYPE = CUSTOMER_KIMCHANG then begin SetRegValueInteger(HKEY_USERS, sTemp, 'DisablePreviewDesktop', 0, true); SetRegValueInteger(HKEY_USERS, sTemp, 'DisablePreviewWindow', 0, true); end else begin if GetRegValueAsInteger(HKEY_USERS, sTemp, 'ExtendedUIHoverTime') <> $10000 then begin SetRegValueInteger(HKEY_USERS, sTemp, 'ExtendedUIHoverTime', $10000, true); _Trace('작업표시줄 미리보기 OFF 설정 1', 1); end; // 작업표시줄 포커스 기능 해제. 상시로고가 무력화 되는것을 방지 25_0618 15:16:13 kku SetRegValueInteger(HKEY_USERS, sTemp, 'DisablePreviewDesktop', 1, true); SetRegValueInteger(HKEY_USERS, sTemp, 'DisablePreviewWindow', 1, true); end; end; begin Inherited Create; ASSERT(gMgSvc = nil); // CoInitialize(nil); // 프린트 워터마크 파일 분석을 위해 FindPrintingFile() 서 사용 24_0513 16:02:49 kku SetRegValueInteger(HKEY_USERS, RecentUserSid + '\' + REG_HE, 'CT', CUSTOMER_TYPE, true); SetRegValueString(HKEY_USERS, RecentUserSid + '\' + REG_HE, 'RW', IntToStr(hRcvHwnd), true); sTmpAcc_ := ''; FormatSettings.ShortDateFormat := 'YYYY-MM-DD'; FormatSettings.LongDateFormat := 'YYYY-MM-DD'; FormatSettings.ShortTimeFormat := 'hh:mm:ss'; FormatSettings.LongTimeFormat := 'hh:mm:ss'; FormatSettings.DateSeparator := '-'; FormatSettings.TimeSeparator := ':'; dtCreateMg_ := Now; PDFiumDllDir := GetRunExePathDir; UpdateTick := 0; sPrtMaskingStr_ := ''; sRecentUserSid_ := ''; sAgentPatchVersion_ := ''; gMgSvc := Self; CS_ := TCriticalSection.Create; CSDev_ := TCriticalSection.Create; hRcvHwnd_ := hRcvHwnd; IgrEjectDrives_ := TStringList.Create; IgrEjectDrives_.CaseSensitive := false; ServerUrlList_ := TStringList.Create; GetDestServerList(ServerUrlList_); ASSERT(ServerUrlList_.Count > 0); ActiveConnectList_ := TStringList.Create; dtConnected_ := 0; dtChangeMode_ := Now; nDestSvrIdx_ := 99999; // ChangeDestinationUrl() 사용 시 초기화를 위함 bIsEmpNoOk_ := false; //(CUSTOMER_TYPE = CUSTOMER_CJOV_GLOBAL); // false; bDoEmpNoCheck_ := false; bIsConnected_ := false; bIsRouterOn_ := false; bIsVpnNicOn_ := false; sVpnClient_ := GetVpnClient; bIsUninstall_ := false; bIsTemporaryConn_ := false; // bIsNexgVpnRegistered_ := true; bIsNetworkPrevent_ := false; sNetworkPreventValue_ := ''; sNetworkExceptValue_ := ''; sNetworkPreventType_ := ''; sAutoRunBlockKey_ := ''; dtLastChk_ := 0; sUName_ := ''; sEmail_ := ''; dwUNameChkTick_ := 0; sExtraPort_ := ''; sEulaContent_ := ''; dwCheckSafePC_ := 0; dwTempConnBegin_ := 0; bIsVpnClientON_ := false; bIsSafeExitImpossible_ := false; bIsRestricMac_ := false; BS1ModeKind_ := hmkSleep; dtSoftInstTick_ := 0; dtOldLogCheck_ := 0; bTryUnsafeActionsMin_ := false; dtInfoFileCheck_ := Now; sSchRstPath_ := ''; sSchRstExpPath_ := ''; ZeroMemory(@AgentInfo, SizeOf(AgentInfo)); sLastPolicy_ := ''; sRecentPrintDocName_ := ''; // dtLastAvCheck_ := 0; dtLastChangePW_ := 0; dtLastLogOn_ := JavaToDelphiDateTime(StrToInt64Def(GetRegValueAsString(HKEY_LOCAL_MACHINE, REG_HE, 'LLO'), 0)); bIsOffline_ := false; bIsExpPolicy_ := false; dtApDisconn_ := 0; dtSvrDisconn_ := Now; dtExpPoBegin_ := 0; nExpPoMin_ := 0; llChkTimeSec_ := 0; qWaterEnts_ := TQueue.Create; sRecentUsbDrv_ := ''; sExceptUsbDev_ := ''; sExceptUsbDevKn_ := ''; UsbConnList_ := TStringList.Create; UsbConnList_.CaseSensitive := false; DriveList_ := TStringList.Create; DriveList_.CaseSensitive := false; sCdException_ := ''; sCdExcepedList_ := ''; sFailCdBlock_ := ''; bCheckedFixDisk_ := false; nHttpError_ := 0; sHttpError_ := ''; pProcCampn_ := nil; bIsStopCampn_ := false; llCampnEncCnt_ := 0; llCampnEncFailCnt_ := 0; DlgEncCampn_ := nil; bClearCampn_ := false; bIgrLastWorkCampn_ := false; bIsIdleScreenLogo_ := false; bIsIpMatchScreenLogo_ := false; bIsRdpLogonScreenLogo_ := false; bIsAppUseScreenLogo_ := false; bIsScreenLogoBold_ := false; dwSecuExitWaitTick_ := 0; sModeName_ := RS_SleepMode; nRdpW_ := 0; nRdpH_ := 0; AipFailCnt := 0; dwAipExeTick_ := 0; dtSV1FileBlockNoti_ := 0; wURole_ := 0; UseApproval := false; bIgrPrtPause_ := false; bIsEndSession_ := false; FileExpEntList_ := TFileExpEntList.Create; FileExpEntList_.OnNotify := OnFileExpNotify; LoadFileExpEnt; sRecentLabel_ := ''; sScreenLogoChkApps_ := ''; sScreenLogoChkUrls_ := ''; sScreenBlockChkApps_ := ''; bForceScreenLogo_ := false; nMonitorCnt_ := 0; sScreenLogoData_ := ''; wScreenVI_ := 0; case CUSTOMER_TYPE of CUSTOMER_DEV, CUSTOMER_DEMO, CUSTOMER_LGD : DcOpenDoc_ := TDictionary.Create; else DcOpenDoc_ := nil; end; bForceScreenCapAppBlock_ := false; ScreenLogoChkAppList := TStringList.Create; ScreenLogoChkAppList.CaseSensitive := false; ScreenLogoChkUrlList := TStringList.Create; ScreenLogoChkUrlList.CaseSensitive := false; ScreenBlockChkAppList := TStringList.Create; ScreenBlockChkAppList.CaseSensitive := false; NoMatchList_ := TStringList.Create; NoMatchList_.CaseSensitive := false; MgPrint_ := TManagerPrint.Create; UseOptCodeList_ := TStringList.Create; RecentFndList_ := TRecentFndList.Create; RecentFndList_.OnNotify := OnRecentFndNotify; DelayProcList_ := TDelayProcList.Create; DelayProcList_.OnNotify := OnDpEntNotify; bInitRule_ := false; bIsSendHWInfo_ := false; nChkConnSec_ := 10; dwTickChkConn_ := 0; // bInitOutMail_ := false; bBlockOutlook_ := false; ThdWndMon_ := nil; ThdAppMon_ := nil; xPrintLogService_ := nil; sUtcOffset_ := '+00:00'; try var TS: TTimeSpan := TTimeZone.Local.GetUtcOffset(Now); sUtcOffset_ := Format('%s%.2d:%.2d', [BooleanToStr(TS.Ticks >= 0, '+', '-'), Abs(TS.Hours), Abs(TS.Minutes)]); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. GetUtcOffset()'); end; // DRM, AIP 아이콘 오버레이 추가 24_0227 08:52:01 kku if IsUsingIconOverlay then begin var sShellDll: String; if IsSupportAIP then begin sShellDll := GetRunExePathDir + DIR_CONF + DLL_OVI_AIP; if not ExistsKey(HKEY_LOCAL_MACHINE, REG_BS1_OVI_AIP) and FileExists(sShellDll) then ExecutePath_hide('regsvr32.exe', '/s /i "' + sShellDll + '"'); end; if not NotUseDRM then begin sShellDll := GetRunExePathDir + DIR_CONF + DLL_OVI_DRM; if not ExistsKey(HKEY_LOCAL_MACHINE, REG_BS1_OVI_DRM) and FileExists(sShellDll) then ExecutePath_hide('regsvr32.exe', '/s /i "' + sShellDll + '"'); end; end else begin var sDir: String := GetRunExePathDir + DIR_CONF; if ExistsKey(HKEY_LOCAL_MACHINE, REG_BS1_OVI_DRM) and FileExists(sDir + DLL_OVI_DRM) then ExecutePath_hide('regsvr32.exe', Format('/u /s "%s"', [sDir + DLL_OVI_DRM])); if ExistsKey(HKEY_LOCAL_MACHINE, REG_BS1_OVI_AIP) and FileExists(sDir + DLL_OVI_AIP) then ExecutePath_hide('regsvr32.exe', Format('/u /s "%s"', [sDir + DLL_OVI_AIP])); end; // if IsExplorerDrmMenu or (CUSTOMER_TYPE = CUSTOMER_HAE) then if IsExplorerDrmMenu then begin var sShellDll: String := GetRunExePathDir + DIR_CONF + DLL_SHELL; if not ExistsKey(HKEY_CLASSES_ROOT, REG_BS1_SHELL) and FileExists(sShellDll) then ExecutePath_hide('regsvr32.exe', '/s /i "' + sShellDll + '"'); if CUSTOMER_TYPE = CUSTOMER_SKEC then mtxDrmEnc_ := TTgMutex.Create(MUTEX_SHELL_MIPENC) else if not NotUseDRM then mtxDrmEnc_ := TTgMutex.Create(MUTEX_SHELL_DRMENC); end else mtxDrmEnc_ := nil; mtxDrmDec_ := nil; mtxPrtWater_ := nil; // mtxDrmOpen_ := nil; AccObj_SubTitle_ := nil; VariantClear(varSubTitle_); hEditWnd_ := 0; AgentModel_ := TAgentModel.Create; AgentModel_.Load; MgCttSch_ := TManagerCttSch.Create; MgCttSchExp_ := TManagerCttSchExcept.Create; MgPwe_ := TManagerPrtWaterExcept.Create; // MgPwe_.AddFileHash('C:\Users\kku\Desktop\BSOne_OutTest.docx'); // MgCltFld_ := TManagerCltFld.Create; sComName_ := GetComName; PrefModel_ := TPrefModel.Create('01'); // 수면 모드 PrefIdlModel_ := TPrefModel.Create('02', true, false); // 기본 로드 하도록 변경 23_0907 11:34:45 kku if PrefModel_.IdlPolicy <> '' then PrefIdlModel_.SetPrefModel(SO(PrefModel_.IdlPolicy)); // 취약 모드 PrefVulModel_ := TPrefModel.Create('03', true, false); if PrefModel_.VulPolicy <> '' then PrefVulModel_.SetPrefModel(SO(PrefModel_.VulPolicy)); // 오프라인 모드 PrefOffline_ := TPrefModel.Create('04', true, false); if PrefModel_.OffPolicy <> '' then PrefOffline_.SetPrefModel(SO(PrefModel_.OffPolicy)); // 예외 모드 PrefExpPolicy_ := TPrefModel.Create('05', true, false); // if PrefModel_.ExpPolicy <> '' then // PrefExpPolicy_.SetPrefModel(SO(PrefModel_.ExpPolicy)); MgCampn_ := TManagerCampaign.Create; MgRule_ := TManagerRule.Create; bIsNewApi_ := not PrefModel_.IsOldPolicy; if PrefModel_.VpnAppName <> '' then sVpnClient_ := PrefModel_.VpnAppName; sNoticeContent_ := PrefModel_.NoticeContent; bFirstAip_ := false; LoadSetting; bIsPatchUptoDate_ := true; // bIsPatchUptoDate_ := false; // OS 패치 취약 테스트 bIsServiceAvailable_ := false; HandleConfig_ := THandleConfig.Create; HandleSecurity_ := THandleSecurity.Create(HandleConfig_.OsVersion); NicService_ := TNicService.Create; VulService_ := TVulnerabilityService.Create; UsbNoti_ := TTgUSBEventNotify.Create; UsbNoti_.OnUSBArrival := OnUSBArrival; UsbNoti_.OnUSBQueryRemove := OnUSBQueryRemove; UsbNoti_.OnUSBRemove := OnUSBRemove; ThdFW_ := TThdFirewall.Create; ThdFW_.StartThread; ThdReact_ := TThdReaction.Create; ThdReact_.StartThread; ThdEvent_ := TThdEvent.Create; ThdEvent_.StartThread; sCbPatterns_ := ''; CbPatternEnts_ := TPatternEntList.Create; sPrintPatterns_ := ''; sWebABPatterns_ := ''; sEtcABPatterns_ := ''; sOutABPatterns_ := ''; InitDefCttPattern; RecentDocWatch_ := nil; ThdOsUpdateScan_ := nil; FileService_ := nil; ThdInstMon_ := nil; // TThdInstMon.Create(hRcvHwnd); ThdWebUrl_ := nil; // TThdWebUrl.Create; ThdPrinter_ := nil; ThdPrintWork_ := nil; ThdBlueMon_ := nil; ThdMtpMon_ := nil; ThdUsbMonRO_ := nil; EmDriveList_ := TStringList.Create; EmDriveList_.CaseSensitive := false; UpdateEmptyUsbInfo; ThdRouteMon_ := nil; ThdCapAppMon_ := nil; ThdBlockAppMon_ := nil; ThdScanSch_ := nil; ThdCltFld_ := nil; ThdScreenRecord_ := nil; MgFnd_ := nil; MgHook_ := nil; bTerminateThdScanSch_ := false; CapAppList_ := TStringList.Create; CapAppList_.CaseSensitive := false; SplitString(CAPTURE_APPS, '|', CapAppList_); MonAppList_ := TStringList.Create; MonAppList_.CaseSensitive := false; BlockAppList_ := TStringList.Create; BlockAppList_.CaseSensitive := false; BlockAppWList_ := TStringList.Create; bIsMonApp_ := false; bIsBlockApp_ := false; sMonApps_ := ''; sBlockApps_ := ''; ChangeDestinationUrl; fas_ := nil; if UseFasooDecrypt and not IsCJ_Affiliates then // CJ에서는 DLL 로드하지 않도록 수정 25_0812 09:12:16 kku begin if not ExistsKey(HKEY_CLASSES_ROOT, 'TypeLib\{D3135A34-059E-4A47-AAD4-0D84F41DC165}\1.0\0\win64') then begin // 롯데마트는 기본 64DLL이 등록되지 않음 24_1104 11:22:41 kku // 다른 고객사는 확인필요... var sFsDll: String := 'C:\Program Files\Fasoo DRM\CW-Packager\WorkPackagerV3.dll'; if not FileExists(sFsDll) then sFsDll := GetRunExePathDir + DLL_FAS64; if not FileExists(sFsDll) then sFsDll := GetRunExePathDir + DIR_CONF + DLL_FAS64; if FileExists(sFsDll) then ExecutePath_hide('regsvr32.exe', Format('/s "%s"', [sFsDll])); end; var bInitFs: Boolean := true; case CUSTOMER_TYPE of CUSTOMER_WELFNI : SetDSD_CODE(DSD_CODE_WFNI); CUSTOMER_WELFND : SetDSD_CODE(DSD_CODE_WFND); else bInitFs := false; end; if bInitFs then begin var sFsDir: String := GetRunExePathDir + 'fsdinit'; if not DirectoryExists(sFsDir) then sFsDir := GetRunExePathDir + DIR_CONF + 'fsdinit'; if DirectoryExists(sFsDir) then begin CoInitializeEx(nil, COINIT_APARTMENTTHREADED); fas_ := TTgFasoo.Create(sFsDir); end; end; end; // 외부 DRM 사용준비 case CUSTOMER_TYPE of CUSTOMER_KDNVN : begin var dwResult: DWORD := KCT_Init(GetRunExePathDir + DIR_CONF, 'kdnavien'); if dwResult <> RESULT_SUCCESS then _Trace('Fail .. Init KESS .. Code=%x', [dwResult]) else _Trace('Success .. Init KESS'); end; CUSTOMER_CJONS : begin // 컴퓨터\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Classes\TypeLib\{D3135A34-059E-4A47-AAD4-0D84F41DC165} - 여기에도 있다고 한다 25_0812 16:06:21 kku if ExistsKey(HKEY_CLASSES_ROOT, 'TypeLib\{D3135A34-059E-4A47-AAD4-0D84F41DC165}\1.0\0\win64') then begin var sTemp: String := GetRunExePathDir + DIR_CONF + DLL_FAS64; if FileExists(sTemp) then ExecutePath_hide('regsvr32.exe', Format('/u /s "%s"', [sTemp])); end; end; end; InitAgentInfo; bSchRstVul_ := false; LoadSchRstVul; bRcvRemoveAgent_ := false; bPreNacChk_ := false; // 계정 암호 설정 정보를 가져오려면 최초 계정 정보를 가져와야 한다. // 예) 원래 tocsg 계정을 kjkim으로 계정 변경 했는데 tocsg로 LogonUser()에 넣어야 잘 동작함 22_0526 10:17:05 kku sDomain_ := ''; sAccount_ := ''; sUserName_ := ''; CheckHostAndUserInfo; InitHttp; if CUSTOMER_TYPE = CUSTOMER_DEV then begin if bFirstAip_ and (sAccount_ <> '') then begin _Trace('Force .. FindAipMdWnd(Dev)', 1); FindAipMdWnd(true); end; end else if IsSupportAIP and (sAccount_ <> '') then begin _Trace('Force .. FindAipMdWnd()', 1); FindAipMdWnd(true); end; //mgkim bs1flt load bFltCtrlInit_ := false; FltCtrlPolicy_ := 0; FltCtrl_ := TBs1fltControl.Create; DcFltCtrlEnt_ := TDictionary.Create; // IgnoreDriverLoad _Trace('에이전트 시작 시간: %s',[agentStatTime_], 1); agentStatTime_:= FormatDateTime('yyyy-mm-dd"T"hh:nn:ss"+09:00"', Now); if UseFltCtrl then begin var state : DWORD; state := FltCtrl_.InitDriver(GetRunExePathDir, FltCtrlCallback); if state = 0 then begin var PPid: DWORD; var parentDir: string; var programdataDir: string; _Trace('장치 접근 제어 준비 .. OK', 1); FltCtrl_.BeginControl(1); //폴더 보호 적용 PPid:= GetProcessPPidByPid(GetCurrentProcessId()); parentDir:= ExtractFileDir(ExcludeTrailingPathDelimiter(GetRunExePathDir)); programdataDir := parentDir[1] + ':\ProgramData\Tocsg'; _Trace('장치 접근 제어 준비 .. 폴더 보호 시작 : %s, PPid : %d',[parentDir, PPid], 1); FltCtrl_.SetPid(PG_PID_ALLOW, PPid); FltCtrl_.SetPath(PG_PATH_BLACK, Pchar(programdataDir)); FltCtrl_.SetPath(PG_PATH_BLACK, Pchar(parentDir)); FltCtrl_.SetProcessPath(PG_PID_ALLOW, Pchar('eCrmHeHelper.exe')); FltCtrl_.SetProcessPath(PG_PID_ALLOW, Pchar('KvCttSch.exe')); FltCtrl_.SetProcessPath(PG_PID_ALLOW, Pchar('KvCttSchW.exe')); FltCtrl_.SetProcessPath(PG_PID_ALLOW, Pchar('BSWmcr.exe')); FltCtrl_.SetProcessPath(PG_PID_ALLOW, Pchar('BSOne-AIP-Decrypt14.exe')); FltCtrl_.SetProcessPath(PG_PID_ALLOW, Pchar('BSOne-AIP-Decrypt.exe')); FltCtrl_.SetProcessPath(PG_PID_ALLOW, Pchar('Bs1tri.exe')); FltCtrl_.SetProcessPath(PG_PID_ALLOW, Pchar('eCrmInterCaller.exe')); FltCtrl_.SetProcessPath(PG_PID_ALLOW, Pchar('filter.exe')); FltCtrl_.SetProcessPath(PG_PID_ALLOW, Pchar('kvoop.exe')); FltCtrl_.SetProcessPath(PG_PID_ALLOW, Pchar('tstxtract.exe')); FltCtrl_.SetProcessPath(PG_PID_ALLOW, Pchar('FilterTestDotNet.exe')); FltCtrl_.SetFileName(PG_FILE_ALLOW, Pchar('Bs1ovi.dll')); FltCtrl_.SetFileName(PG_FILE_ALLOW, Pchar('Bs1ovm.dll')); FltCtrl_.SetFileName(PG_FILE_ALLOW, Pchar('eCrmHeHelper.dll')); FltCtrl_.SetFileName(PG_FILE_ALLOW, Pchar('eCrmHeHelper32.dll')); FltCtrl_.SetFileName(PG_FILE_ALLOW, Pchar('Bs1shl.dll')); FltCtrl_.SetFileName(PG_FILE_ALLOW, Pchar('Bs1ovi64.dll')); FltCtrl_.SetFileName(PG_FILE_ALLOW, Pchar('libeay32.dll')); FltCtrl_.SetFileName(PG_FILE_ALLOW, Pchar('ssleay32.dll')); FltCtrl_.SetFileName(PG_FILE_ALLOW, Pchar('bsonex64.sys')); FltCtrl_.SetFileName(PG_FILE_ALLOW, Pchar('hpli.dat')); _Trace('장치 접근 제어 준비 .. 폴더 보호 끝', 1); FltCtrl_.FolderProtectControl(1); //장치 차단 FltCtrl_.SetDeviceProtect(1); FltCtrl_.SetHook(DWORD(BDC_USB), 1); FltCtrl_.SetHook(DWORD(BDC_BLUETOOTH), 1); //프로세스 보호 FltCtrl_.ProcessCreate(1); FltCtrl_.ProcessProtect(1); FltCtrl_.SetProcessProtectId(GetCurrentProcessId); _Trace('프로세스 보호 끝', 1); //레지스트리 보호 FltCtrl_.SetRegProtect(1); bFltCtrlInit_ := true; end else _Trace('장치 접근 제어 준비 .. Fail : %d',[state],1); end; DeviceGuard_:= TDeviceGuardEngine.Create; // DeviceGuard_.CreateDefaultPolicies; // 에이전트 최초 상태정보 보낼때 참조할 수 있도록 미리 실행 시켜줌 23_0411 12:30:37 kku TimerCheckOsConfig(nil); TimerCheckSecurity(nil); dwSLSaveTick_ := 0; dwNacChkTick_ := 0; ThdTaskTimer_ := TThdTaskTimer.Create(1000, true); ThdTaskTimer_.AddTask(TimerCheckOsConfig, 1000, true); ThdTaskTimer_.AddTask(TimerCheckServiceAvailable, 1000, true); ThdTaskTimer_.AddTask(TimerCheckTemporaryConn, 1000, true); ThdTaskTimer_.AddTask(TimerCheckExpPo, 1000, false); ThdTaskTimer_.AddTask(TimerCheckSecurity, 3000, true); ThdTaskTimer_.StartTimerThread; ThdDevTaskTimer_ := TThdTaskTimer.Create(500, true); ThdDevTaskTimer_.AddTask(TimerProcessDevTask, 500, true); ThdDevTaskTimer_.StartTimerThread; ThdStatusTimer_ := TThdTaskTimer.Create(1000, true); dwStatusInterval_ := 2000; case CUSTOMER_TYPE of CUSTOMER_SHCD : dwStatusInterval_ := 4000; CUSTOMER_KR : dwStatusInterval_ := 30000; end; if (PrefModel_.HealthCheckMilSec >= 1000) and (PrefModel_.HealthCheckMilSec <> dwStatusInterval_) then dwStatusInterval_ := PrefModel_.HealthCheckMilSec; ThdStatusTimer_.AddTask(TimerProcessStatus, dwStatusInterval_, true, CUSTOMER_TYPE = CUSTOMER_KR); ThdStatusTimer_.AddTask(TimerCheckConnect, 1000, true, false); ThdStatusTimer_.StartTimerThread; TThdInitProc.Create; if HandleConfig_ <> nil then begin bWin7Ver_ := HandleConfig_.OsVersion = '7'; _Trace('WinVersion : %s (%s)', [HandleConfig_.OsVersion, HandleConfig_.OsMajorVer]); end else bWin7Ver_ := false; UpdateCttSchVulState(true); var sDT: String := GetRegValueAsString(HKEY_LOCAL_MACHINE, REG_HE, 'EDT'); if (sDT <> '') then begin DelRegValue(HKEY_LOCAL_MACHINE, REG_HE, 'EDT'); if PrefModel_.IsPcStatePower or SleepPolicy.IsPcStatePower then SendEventLogEx(MONITOR_PC_POWER, 'Power Off', false, JavaToDelphiDateTime(StrToIntDef(sDT, 0))); end; if PrefModel_.IsPcStatePower or SleepPolicy.IsPcStatePower then begin var dtBoot: TDateTime := GetBootTime; sDT := FormatDateTime('yyyymmddhhnnss', dtBoot); var sLastBDT: String := GetRegValueAsString(HKEY_LOCAL_MACHINE, REG_HE, 'BDT'); if sDT <> sLastBDT then // 부팅 후 5분 이내 실행이면 begin SetRegValueString(HKEY_LOCAL_MACHINE, REG_HE, 'BDT', sDT, true); SendEventLogEx(MONITOR_PC_POWER, 'Power On', false, dtBoot); end; end; xPrintVer_ := ''; dtOneDay_ := 0; EmpsUpDt := ''; PrtsUpDt := ''; BillUpDt := ''; MkcdUpDt := ''; LumpUpDt := ''; case CUSTOMER_TYPE of CUSTOMER_DEV, CUSTOMER_DEMO, CUSTOMER_LGD, CUSTOMER_WELFNI, CUSTOMER_WELFND : begin ThdAppMon_ := TThdProcessWatch.Create; ThdAppMon_.OnProcessWatchNotify := OnAppNotify; ThdAppMon_.StartThread; end; CUSTOMER_KIMCHANG : begin var sXprtInfo: String := 'C:\ProgramData\bsoneprint\package.yml'; if FileExists(sXprtInfo) then begin var StrList: TStringList; Guard(StrList, TStringList.Create); StrList.LoadFromFile(sXprtInfo, TEncoding.UTF8); var i, nPos: Integer; var sLine: String; for i := 0 to StrList.Count - 1 do begin sLine := StrList[i]; nPos := Pos('version:', sLine); if nPos = 1 then begin Delete(sLine, 1, 8); xPrintVer_ := Trim(sLine); break; end; end; var ini: TIniFile; Guard(ini, TIniFile.Create(GetRunExePathDir + 'xPrint.ini')); dtOneDay_ := ini.ReadDateTime('DateTime', 'xOneDayDT', 0); EmpsUpDt := ini.ReadString('DateTime', 'EmpsUpDt', ''); PrtsUpDt := ini.ReadString('DateTime', 'PrtsUpDt', ''); BillUpDt := ini.ReadString('DateTime', 'BillUpDt', ''); MkcdUpDt := ini.ReadString('DateTime', 'MkcdUpDt', ''); LumpUpDt := ini.ReadString('DateTime', 'LumpUpDt', ''); // case GetServiceStatus('BSonePrintService') of // SERVICE_RUNNING, // SERVICE_START_PENDING : ; // else begin // // ExecutePath_hide(sXprtPath, '-install'); // end; // end; end; end; end; if NotUseUAC then InstallOutlookPlugIn_forHD(hRcvHwnd_); end; Destructor TManagerService.Destroy; begin if VulService_ <> nil then VulService_.StopWork; // ThdStatusTimer_.StopTimerThread; // ThdTaskTimer_.StopTimerThread; FreeAndNil(ThdStatusTimer_); FreeAndNil(ThdDevTaskTimer_); FreeAndNil(ThdTaskTimer_); if mtxDrmEnc_ <> nil then FreeAndNil(mtxDrmEnc_); if mtxDrmDec_ <> nil then FreeAndNil(mtxDrmDec_); if mtxPrtWater_ <> nil then FreeAndNil(mtxPrtWater_); // if mtxDrmOpen_ <> nil then // FreeAndNil(mtxDrmOpen_); // FreeAndNil(ThdMgRcver_); // if ThdMsgAutoClose_ <> nil then // FreeAndNil(ThdMsgAutoClose_); FreeAndNil(UseOptCodeList_); FreeAndNil(NoMatchList_); FreeAndNil(ScreenBlockChkAppList); FreeAndNil(ScreenLogoChkUrlList); FreeAndNil(ScreenLogoChkAppList); if DcOpenDoc_ <> nil then FreeAndNil(DcOpenDoc_); FreeAndNil(ThdFW_); FreeAndNil(ThdEvent_); FreeAndNil(ThdReact_); DeactivePolicyAll; FreeAndNil(UsbNoti_); // FreeAndNil(MgCltFld_); FreeAndNil(MgPwe_); FreeAndNil(MgCttSchExp_); FreeAndNil(MgCttSch_); FreeAndNil(AgentModel_); FreeAndNil(ActiveConnectList_); FreeAndNil(ServerUrlList_); FreeAndNil(HTTP_); FreeANDNil(SSL_); FreeAndNil(MonAppList_); FreeAndNil(BlockAppWList_); FreeAndNil(BlockAppList_); FreeAndNil(CapAppList_); FreeAndNil(PatternEntList_); FreeAndNil(CbPatternEnts_); FreeAndNil(MgPtn_); // FreeAndNil(SSLCtx_); FreeAndNil(IgrEjectDrives_); if ThdOsUpdateScan_ <> nil then FreeAndNil(ThdOsUpdateScan_); if RecentDocWatch_ <> nil then FreeAndNil(RecentDocWatch_); FreeAndNil(NicService_); FreeAndNil(VulService_); if fas_ <> nil then FreeAndNil(fas_); FreeAndNil(DelayProcList_); FreeAndNil(RecentFndList_); if xPrintLogService_ <> nil then FreeAndNil(xPrintLogService_); // CoUninitialize; gMgSvc := nil; Inherited; FltCtrl_.Cleanup; FreeAndNil(FltCtrl_); FreeAndNil(DeviceGuard_); FreeAndNil(DcFltCtrlEnt_); FreeAndNil(MgPrint_); FreeAndNil(DriveList_); FreeAndNil(UsbConnList_); qWaterEnts_.OnNotify := OnWaterEntNotify; FreeAndNil(qWaterEnts_); FreeAndNil(PrefModel_); FreeAndNil(PrefIdlModel_); FreeAndNil(PrefVulModel_); FreeAndNil(PrefOffline_); FreeAndNil(PrefExpPolicy_); FreeAndNil(HandleSecurity_); FreeAndNil(HandleConfig_); FreeAndNil(MgRule_); FreeAndNil(FileExpEntList_); FreeAndNil(MgCampn_); FreeAndNil(CSDev_); FreeAndNil(CS_); end; procedure TManagerService.Lock; begin CS_.Acquire; end; procedure TManagerService.Unlock; begin CS_.Release; end; procedure TManagerService.DevLock; begin CSDev_.Acquire; end; procedure TManagerService.DevUnlock; begin CSDev_.Release; end; procedure TManagerService.UpdateEmptyUsbInfo; var i: Integer; dwLogicalDrv: DWORD; sDrive: String; begin try dwLogicalDrv := GetLogicalDrives; for i := 0 to 31 do if (dwLogicalDrv and (1 shl i)) > 0 then begin sDrive := Format('%s:\', [Char(Integer('A')+i)]); if not DirectoryExists(sDrive) then begin if EmDriveList_.IndexOf(sDrive) = -1 then EmDriveList_.Add(sDrive); end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. UpdateEmptyUsbInfo()'); end; end; procedure TManagerService.CatchDriveSatate; var CurDrvList: TStringList; i: Integer; begin try if DriveList_.Count = 0 then begin DriveList_.CommaText := GetDrivesFromMask(GetLogicalDrives); exit; end; Guard(CurDrvList, TStringList.Create); CurDrvList.CommaText := GetDrivesFromMask(GetLogicalDrives); // _Trace('DriveList_ = %s, CurDrvList = %s', [DriveList_.CommaText, CurDrvList.CommaText]); for i := 0 to CurDrvList.Count - 1 do if DriveList_.IndexOf(CurDrvList[i]) = -1 then ProcessUSBArrival(CurDrvList[i]); for i := 0 to DriveList_.Count - 1 do if CurDrvList.IndexOf(DriveList_[i]) = -1 then ProcessUSBRemove(DriveList_[i]); DriveList_.CommaText := CurDrvList.CommaText; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. CatchDriveSatate()'); end; end; procedure TManagerService.CheckHostAndUserInfo; begin try if (sUserName_ = '') or (sDomain_ = '') or (sAccount_ = '') then begin // 로그인/로그아웃으로 사용자 계정 변경 감지를 위해 재활용하지 않는다 24_0207 17:31:06 kku // if AgentModel_.AModelVer > 0 then // begin // // AD 사용 시 재활용하지 않도록 보완 24_0110 08:18:45 kku // if not IsUseActiveDirectory then // begin // sDomain_ := AgentModel_.DomainName; // sUserName_ := AgentModel_.UserName; // sAccount_ := AgentModel_.Account; // end; // end; if (sUserName_ <> '') and (sDomain_ <> '') and (sAccount_ <> '') then exit; if sDomain_ = '' then begin // 다이이찌산쿄에서 부팅 후 종종 계정이 짤려서 보이는 문제 확인됨. 보완 22_0707 08:54:50 kku sDomain_ := StringReplace(GetUserNameFromExplorer, '\\', '', [rfReplaceAll]); if (sDomain_ <> '') and (sAccount_ <> '') then sUserName_ := ExtractFilePath(sDomain_) + sAccount_; end; if CUSTOMER_TYPE = CUSTOMER_KBIZ then begin if sAccount_ = '' then begin sAccount_ := GetRegValueAsString(HKEY_LOCAL_MACHINE, 'Software\Microsoft\Windows\CurrentVersion\Authentication\LogonUI', 'LastLoggedOnSAMUser'); if sAccount_ = '' then sAccount_ := GetRegValueAsString(HKEY_LOCAL_MACHINE, 'Software\Microsoft\Windows\CurrentVersion\Authentication\LogonUI', 'LastLoggedOnUser'); if sAccount_ <> '' then begin sAccount_ := StringReplace(sAccount_, '.\', '', [rfReplaceAll]); sAccount_ := ExtractFileName(sAccount_); end; end; end; if sAccount_ = '' then begin sAccount_ := WTS_GetCurrentUserName; if IsUseActiveDirectory then begin // AD 환경 로그온 상태에서 WTS_GetCurrentUserName 안되는 경우가 있는지 확인이 필요하다.. 22_0905 08:49:45 kku if sAccount_ <> '' then sUserName_ := ExtractFilePath(sDomain_) + sAccount_ else sUserName_ := sDomain_; end else begin if (sDomain_ <> '') and (sAccount_ <> '') then sUserName_ := ExtractFilePath(sDomain_) + sAccount_; end; end; if (sUserName_ = '') and (sDomain_ <> '') and (sAccount_ <> '') then begin sUserName_ := ExtractFilePath(sDomain_) + sAccount_; AgentModel_.DomainName := sDomain_; AgentModel_.Account := sAccount_; AgentModel_.UserName := sUserName_; AgentModel_.Save; end; if IsAccountEmpNo then begin if (sAccount_ <> '') and (AgentModel_.EmpNo <> sAccount_) then begin _Trace('[06] 사번 변경, %s > %s', [AgentModel_.EmpNo, sAccount_]); SendEventLogEx(LOG_CHANGE_EMPNO, Format('[Fixed] EmpId Changed. (%s > %s)', [AgentModel_.EmpNo, sAccount_]), false); AgentModel_.EmpNo := sAccount_; // AgentModel_.VpnInfo := AgentModel_.EmpNo; AgentModel_.Save; UpdateAgentInfo; end; end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. CheckHostAndUserInfo()'); end; end; function TManagerService.HttpPost(sDest, sRqType, sParam: String; pnRespCode: PInteger = nil): String; var ss: TStringStream; begin Result := ''; nHttpError_ := 0; sHttpError_ := ''; try Guard(ss, TStringStream.Create(sParam, TEncoding.UTF8)); HTTP_.Request.CustomHeaders.Values['requestType'] := sRqType; Result := HTTP_.Post(sDest, ss); if (Result = '') and (HTTP_.ResponseCode = 200) then Result := 'true'; if pnRespCode <> nil then pnRespCode^ := HTTP_.ResponseCode; except on E: EIdReadTimeout do begin _Trace('HttpPost() .. ReadTimeout ..'); Result := POST_TIMEOUT; sHttpError_ := E.Message; nHttpError_ := GetLastError; exit; end; on E: Exception do begin {$IFDEF TRACE1} ETgException.TraceException(Self, E, Format('Fail .. HttpPost(), RqType=%s', [sRqType])); {$ENDIF} sHttpError_ := E.Message; nHttpError_ := HTTP_.ResponseCode; if pnRespCode <> nil then pnRespCode^ := nHttpError_; end; end; end; function TManagerService.MakeComponentId(sTail: String): String; var nLen: Integer; begin sTail := StrsReplace(sTail, [';', ' '], ''); Result := sComName_ + '\' + FormatDateTime('yymmddhhnnss', Now) + '_' + sTail; nLen := Length(Result); if nLen > 60 then begin Result := Copy(Result, nLen - 59, 60); // Result := THashSHA1.GetHashString(Result); end; end; function TManagerService.GetCbFoundContentToJsonObj(sText: String; var sResultStr: String): ISuperObject; var i, nHits, nOrCnt, nAndCnt, nHighCnt: Integer; sFound, sResult: String; O, OA: ISuperObject; begin Result := nil; sResult := ''; sResultStr := ''; OA := TSuperObject.Create(stArray); nOrCnt := 0; nAndCnt := 0; nHighCnt := 0; try for i := 0 to CbPatternEnts_.Count - 1 do begin nHits := TTgPcre.GetMatchValues(sText, CbPatternEnts_[i].GetSearchText, sFound); if nHits > 0 then begin if bIsNewApi_ then begin var pRule: PRuleEnt := MgRule_.GetRuleFromId(CbPatternEnts_[i].Name); if (pRule <> nil) and (pRule.nCnt > nHits) then continue; if CbPatternEnts_[i].RSeverity = ManagerPattern.rsHigh then Inc(nHighCnt) else if CbPatternEnts_[i].IsAnd then Inc(nAndCnt) else Inc(nOrCnt); SumString(sResult, Format('%s(%d)', [MgRule_.GetRuleNameFromId(CbPatternEnts_[i].Name), nHits]), ',') end else SumString(sResult, Format('%s(%d)', [CttCodeToStr(CbPatternEnts_[i].Name), nHits]), ','); O := SO; O.S['RULE_ID'] := CbPatternEnts_[i].Name; O.S['CNT'] := IntToStr(nHits); O.S['TEXT'] := RemoveOverlapWords(sFound); OA.AsArray.Add(O); end; end; if OA.AsArray.Length > 0 then begin if bIsNewApi_ then begin if (nHighCnt = 0) and (CbPatternEnts_.AndCount > 0) then begin // AND 갯수가 다르다면 X if nAndCnt <> CbPatternEnts_.AndCount then exit; // OR가 조건으로 있는데 검출된 OR가 없다면 X if (CbPatternEnts_.AndCount <> CbPatternEnts_.Count) and (nOrCnt = 0) then exit; end; end; sResultStr := sResult; Result := OA; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. CheckCbContent()'); end; end; function TManagerService.GetConnected: Boolean; begin Lock; try Result := bIsConnected_; finally Unlock; end; end; procedure TManagerService.SetConnected(bVal: Boolean; bNewApi: Boolean); begin Lock; try if bIsConnected_ <> bVal then begin bIsConnected_ := bVal; if bIsConnected_ then begin bIsNewApi_ := bNewApi; if IsCJ_Affiliates then // CJ 사번 미인증이 오프라인 모드 24_1218 13:53:13 kku bIsOffline_ := false; dtSvrDisconn_ := 0; dtApDisconn_ := 0; dwNacChkTick_ := 0; dtConnected_ := Now; AgentModel_.LastConn := Now; AgentModel_.Save; _Trace('서버 연결됨', 1); if CUSTOMER_TYPE = CUSTOMER_KIMCHANG then begin if not FileExists('C:\ProgramData\bsoneprint\data\xBil.dat') then TThdRcvPolicy.Create(0); if xPrintLogService_ = nil then begin xPrintLogService_ := TxPrintLogService.Create; xPrintLogService_.StartService; _Trace('xPrint 로그 처리 시작.', 1); end; end; end else begin if CUSTOMER_TYPE = CUSTOMER_KIMCHANG then begin if xPrintLogService_ <> nil then begin FreeAndNil(xPrintLogService_); _Trace('xPrint 로그 처리 종료.', 1); end; end; dtConnected_ := 0; dtSvrDisconn_ := Now; sPrintPatterns_ := ''; _Trace('서버 연결 해제됨', 1); end; end; finally Unlock; end; end; function TManagerService.GetTemporaryConn: Boolean; begin Lock; try Result := bIsTemporaryConn_; finally Unlock; end; end; procedure TManagerService.DoEjectCDROM; var i: Integer; dwLogicalDrv: DWORD; sDrive, sBlkSerial, sMsg: String; IgrList: TStringList; DriveInfo: TDriveInfo; LogInfo: TLogInfo; begin try if ModePolicy.CdromBlockKind = dbkBlock then begin Guard(IgrList, TStringList.Create); IgrList.CaseSensitive := false; if sCdException_ <> ModePolicy.CdromExcept then begin sCdException_ := ModePolicy.CdromExcept; sCdExcepedList_ := ''; sFailCdBlock_ := ''; end; SplitString(sCdException_, ';', IgrList); FltCtrl_.SetPolicy(DWORD(BDC_CDROM), DWORD(dsDisable), 0); dwLogicalDrv := GetLogicalDrives; for i := 0 to 31 do begin sBlkSerial := ''; if (dwLogicalDrv and (1 shl i)) > 0 then begin sDrive := Format('%s:\', [Char(Integer('A')+i)]); if GetDriveType(PChar(sDrive)) = DRIVE_CDROM then begin if FileService_ <> nil then FileService_.DelDriveWatch(sDrive); GetDriveDetail(sDrive, @DriveInfo); // 일단 디스크인데 GetDriveType()이 DRIVE_CDROM로 나오는 현상이 있다고 함 (솔리데오) 24_0718 10:48:59 kku if (DriveInfo.sClass <> '') and (DriveInfo.sClass.ToUpper <> 'CDROM') then continue; // 도시바 내장 디스크가 자꾸 차단이 되는 현상이 있다... (솔리데오) 24_0809 10:55:03 kku if CompareText(DriveInfo.sFriendlyName, 'TOSHIBA DT01ACA100') = 0 then continue; if CUSTOMER_TYPE = CUSTOMER_GEC then begin // GEC에서 사원들에게 제공되는 C-Type USB 허브에서 // 드라이버 설치 경로가 CD/DVD로 잡히는데 차단이 안되는 현상 있음 24_0620 18:02:22 kku var sVolName: String := UpperCase(GetVolumeName(sDrive)); // if (Pos('WCHUSBNIC', sVolName) > 0) and (DriveInfo.sSerial <> '') then // IgrList.Add(DriveInfo.sSerial) if Pos('WCHUSBNIC', sVolName) > 0 then continue; end; // 실패한거 자꾸 차단 시도하지 않도록 위로 추가 24_1210 13:45:28 kku // 가상 CDROM의 경우 초기 차단이 실패할 수 있다. // 계속 반복해서 시도 하도록 아래에서 처리, 실패하면 한번만 로그 남도록 변경 25_0915 13:22:00 kku // if Pos(sDrive, sFailCdBlock_) > 0 then // continue; if IgrList.Count > 0 then begin if IgrList.IndexOf(DriveInfo.sSerial) <> -1 then continue; end; // if IsWin7Ver then // begin // if ForceEjectDrive(sDrive) then // begin // if DriveInfo.sSerial <> '' then // sBlkSerial := DriveInfo.sSerial // else // sBlkSerial := sEmpNo_; // end else // sBlkSerial := FAIL_EJECT; // end else begin // sBlkSerial := EjectDrive(sDrive, IgrList, false, true); // //// if CUSTOMER_TYPE <> CUSTOMER_WELCAPI then //// begin //// // 아래꺼 하면... 인덱싱 색인이 사라지는 문제가 있다... 웰컴캐피탈에서 발견됨 24_1210 14:53:57 kku //// if (sBlkSerial = '') or (sBlkSerial = FAIL_EJECT) then //// sBlkSerial := EjectDrive2(sDrive, IgrList, false, true); //// end; // // // 추가 24_1210 13:43:41 kku // if (sBlkSerial = '') or (sBlkSerial = FAIL_EJECT) then // begin // if (DriveInfo.sSerial <> '') and ForceEjectDrive(sDrive) then // sBlkSerial := DriveInfo.sSerial; // end; // end; _Trace('.. sSerial(%s)', [DriveInfo.sSerial]); sBlkSerial := DriveInfo.sSerial; ZeroMemory(@LogInfo, SizeOf(LogInfo)); LogInfo.sCode := PREVENT_CDROM; LogInfo.sDevName := DriveInfo.sFriendlyName; LogInfo.sDevSerial := DriveInfo.sSerial; LogInfo.sDevClassId := DriveInfo.sClassGuid; with DriveInfo do begin if sBlkSerial = FAIL_EJECT then begin if Pos(sDrive, sFailCdBlock_) = 0 then begin sMsg := Format('Fail .. CD/DVD Block : Drive=%s, Name=%s, Serial=%s', [sDrive, sFriendlyName, sSerial]); if bIsNewApi_ then begin LogInfo.sSummary := sMsg; SendEventLogEx(@LogInfo); end else SendEventLog(URI_USER_ACTION, PREVENT_CDROM, sMsg, false); SumString(sFailCdBlock_, sDrive, '|'); end; end else if sBlkSerial <> '' then begin if GetModePolicy.CDPopup then PopupMessage(TYPE_MSG_PREVENT_CDROM, sDrive + '|' + sFriendlyName + '|' + sBlkSerial); sMsg := Format('CD/DVD Blocked : Drive=%s, Name=%s, Serial=%s', [sDrive, sFriendlyName, sBlkSerial]); if Pos(sDrive, sFailCdBlock_) > 0 then begin sFailCdBlock_ := StringReplace(sFailCdBlock_, sDrive + '|', '', [rfReplaceAll]); sFailCdBlock_ := StringReplace(sFailCdBlock_, '|' + sDrive, '', [rfReplaceAll]); end; if bIsNewApi_ then begin LogInfo.sSummary := sMsg; SendEventLogEx(@LogInfo); end else SendEventLog(URI_USER_ACTION, PREVENT_CDROM, sMsg); end else begin if Pos(sSerial, sCdExcepedList_) = 0 then begin if IsDivPopup and GetModePolicy.CdAllowPopup then PopupMessage(TYPE_MSG_MONITOR_CDROM, sDrive); SumString(sCdExcepedList_, sSerial, '|'); sMsg := Format('Excepted, CD/DVD Block : Drive=%s, Name=%s, Serial=%s', [sDrive, sFriendlyName, sSerial]); if bIsNewApi_ then begin LogInfo.sSummary := sMsg; SendEventLogEx(@LogInfo); end else SendEventLog(URI_USER_ACTION, PREVENT_CDROM, sMsg, false); end; end; end; end; end; end; end else begin FltCtrl_.SetPolicy(DWORD(BDC_CDROM), DWORD(dsEnable), 0); end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. DoEjectCDROM()'); end; end; function FindAlyacScanWindow: HWND; var hMainDialog: HWND; hCandidate, hStatic: HWND; mainDialogClass: string; mainDialogTitle: string; validationStaticClass: string; validationStaticText: string; begin Result := 0; try // 메인창 정보 mainDialogClass := '#32770'; mainDialogTitle := '검사'; validationStaticClass := 'Static'; validationStaticText := '이동식 디스크 검사'; hMainDialog := 0; hCandidate := 0; hCandidate := FindWindowEx(0, hCandidate, PChar(mainDialogClass), PChar(mainDialogTitle)); if hCandidate <> 0 then begin hStatic := FindWindowEx(hCandidate, 0, PChar(validationStaticClass), PChar(validationStaticText)); if hStatic <> 0 then begin Result := hCandidate; exit; end; end; except on E: Exception do ETgException.TraceException(E, 'Fail .. FindAlyacScanWindow()'); end; end; function CloseAlyacScanWindow: Boolean; var hMainDialog, hStopButton, hPopup, hYesButton: HWND; hCandidate: HWND; retries: Integer; stopButtonText: string; popupDialogClass: string; popupDialogTitle: string; popupYesButtonText: string; begin Result := false; try // 메인창 정보 stopButtonText := '중지(&S)'; // 팝업 창 정보 popupDialogClass := '#32770'; popupDialogTitle := '검사'; popupYesButtonText := '예(&Y)'; hMainDialog := 0; // hCandidate := 0; retries := 30; while (hMainDialog = 0) and (retries > 0) do begin Sleep(100); hMainDialog := FindAlyacScanWindow; if hMainDialog <> 0 then break; Dec(retries); end; if hMainDialog = 0 then exit; // "중지(S)" 버튼 클릭 시도 hStopButton := FindWindowEx(hMainDialog, 0, 'Button', PChar(stopButtonText)); if hStopButton <> 0 then begin PostMessage(hStopButton, BM_CLICK, 0, 0); end else begin PostMessage(hMainDialog, WM_CLOSE, 0, 0); end; hPopup := 0; retries := 30; // var nTO: Integer := 0; // while IsWindow(hMainDialog) do // begin // // 3 // if nTO > 10 then // break; while (hPopup = 0) and (retries > 0) do begin Sleep(100); // FindWindowEx(0, hPrev, ...)는 hPrev *다음*의 최상위 창을 검색합니다. hCandidate := 0; while True do begin hCandidate := FindWindowEx(0, hCandidate, PChar(popupDialogClass), PChar(popupDialogTitle)); if hCandidate = 0 then // 더 이상 없음 Break; // 찾은 창의 핸들(hCandidate)이 메인 창의 핸들(hMainDialog)과 다른지 확인 if hCandidate <> hMainDialog then begin // 찾았다 hPopup := hCandidate; Break; end; end; if hPopup <> 0 then Break; Dec(retries); end; if hPopup <> 0 then begin hYesButton := FindWindowEx(hPopup, 0, 'Button', PChar(popupYesButtonText)); if hYesButton <> 0 then begin PostMessage(hYesButton, BM_CLICK, 0, 0); Result := true; end; end; // Sleep(300); // Inc(nTO); // end; except on E: Exception do ETgException.TraceException(E, 'Fail .. CloseAlyacScanWindow()'); end; end; procedure TManagerService.DoEjectUsbDrive(sDrive: String; nType: Integer = -1); var sUsbExceptVender, sIgrUsbSerialList, sType, sBlkSerial, sVenders: String; DriveInfo: TDriveInfo; bNoLogPop: Boolean; begin try DevLock; try if (sDrive = '') or (sDrive[1] = 'C') then exit; sUsbExceptVender := ModePolicy.UsbExceptVender; sIgrUsbSerialList := ModePolicy.IgrUsbSerials; if sExceptUsbDev_ <> (sUsbExceptVender + sIgrUsbSerialList) then begin sExceptUsbDev_ := sUsbExceptVender + sIgrUsbSerialList; IgrEjectDrives_.Clear; end; if IgrEjectDrives_.IndexOf(sDrive) <> -1 then exit; if nType = -1 then nType := GetDriveType(PChar(sDrive)); if nType = DRIVE_CDROM then exit; GetDriveDetail(sDrive, @DriveInfo); if Pos('USB', UpperCase(DriveInfo.sSerial)) <> 1 then begin // USB 디바이스 아니면 넘기도록 보완 // 여기서 고정 디스크를 걸러준다 22_1109 08:09:41 kku IgrEjectDrives_.Add(sDrive); exit; end; bNoLogPop := DriveInfo.llSize = 0; if bNoLogPop then _Trace('빈 드라이브로 확인됨 .. Drive=%s, Size=0', [sDrive], 1); sVenders := ModePolicy.UsbExceptVender; if (sVenders <> '') and (DriveInfo.sFriendlyName <> '') then begin var VenderList: TStringList; Guard(VenderList, TStringList.Create); SplitString(UpperCase(sVenders), ';', VenderList); sBlkSerial := UpperCase(DriveInfo.sFriendlyName); var i: Integer; for i := 0 to VenderList.Count - 1 do if sBlkSerial.Contains(VenderList[i]) then exit; end; //sBlkSerial := EjectDrive2(sDrive, ModePolicy.IgrUsbSerialList, true, true); if bNoLogPop then exit; sType := GetDriveTypeToStr(nType); with DriveInfo do begin if sBlkSerial <> '' then begin if sBlkSerial = FAIL_EJECT then begin // SendEventLog(URI_USER_ACTION, LOGCODE_PREVENT_USB, // Format('Fail .. USB Block : Name=%s, Drive=%s (%s), Type=%s, Serial=%s', // [sFriendlyName, sDrive, ByteSizeToStr(llSize), sType, sBlkSerial])); end else begin sBlkSerial := ExtractFileName(sBlkSerial); // MAC 호환을 위해 VID, PID 등 제외 25_0324 09:54:27 kku if ModePolicy.USBPopup then begin var sRegSerial: String := sBlkSerial; if (UseFltCtrl) and ((FltCtrlPolicy_ = 1) or (FltCtrlPolicy_ = 2)) then SumString(sRegSerial, GetFltCrltEntInfo(sDrive), '***'); PopupMessage(TYPE_MSG_PREVENT_USBDISCONN, sDrive + '*9*' + ByteSizeToStr(llSize) + '*9*' + sFriendlyName + '*9*' + sType + '*9*' + sRegSerial); end; var sMsg: String := Format('USB Blocked : Name=%s, Drive=%s (%s), Type=%s, Serial=%s', [sFriendlyName, sDrive, ByteSizeToStr(llSize), sType, sBlkSerial]); if bIsNewApi_ then begin var LogInfo: TLogInfo; ZeroMemory(@LogInfo, SizeOf(LogInfo)); LogInfo.sCode := LOGCODE_PREVENT_USB; LogInfo.sDevName := sFriendlyName; LogInfo.sDevSerial := sBlkSerial; LogInfo.sDevClassId := sClassGuid; LogInfo.sSummary := sMsg; SendEventLogEx(@LogInfo); end else SendEventLog(URI_USER_ACTION, LOGCODE_PREVENT_USB, sMsg); end; end else // if sRecentUsbDrv_ = sDrive then begin sRecentUsbDrv_ := ''; // D 드라이브를 계속 Eject 시도 하는데 이때 파일 감시도 계속 꺼진다. // 그래서 보완... 22_1027 15:19:51 kku if IgrEjectDrives_.IndexOf(sDrive) = -1 then IgrEjectDrives_.Add(sDrive); var sMsg: String := Format('Excepted, USB Block : Name=%s, Drive=%s (%s), Type=%s, Serial=%s', [sFriendlyName, sDrive, ByteSizeToStr(llSize), sType, sSerial]); if bIsNewApi_ then begin var LogInfo: TLogInfo; ZeroMemory(@LogInfo, SizeOf(LogInfo)); LogInfo.sCode := MONITOR_USB_EXCEPTED; LogInfo.sDevName := sFriendlyName; LogInfo.sDevSerial := sSerial; LogInfo.sDevClassId := sClassGuid; LogInfo.sSummary := sMsg; SendEventLogEx(@LogInfo, false); end else SendEventLog(URI_USER_ACTION, MONITOR_USB_EXCEPTED, sMsg); end; end; finally DevUnlock; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. DoEjectUsbDrive()'); end; end; procedure TManagerService.DoEjectUsbDrives; var i: Integer; dwLogicalDrv: DWORD; begin if ModePolicy.UsbBlockKind = ubkBlock then begin dwLogicalDrv := GetLogicalDrives; for i := 0 to 31 do begin if (dwLogicalDrv and (1 shl i)) > 0 then DoEjectUsbDrive(Format('%s:\', [Char(Integer('A')+i)])); end; end; end; procedure TManagerService.ProcessCampaign; var pEnt: PCampnEnt; begin try if bTerminateThdScanSch_ then begin bTerminateThdScanSch_ := false; if ThdScanSch_ <> nil then FreeAndNil(ThdScanSch_); end; if ThdScanSch_ <> nil then begin case ThdScanSch_.WorkState of tsStop, tsFail : begin _Trace('Fail.. ProcessCampaign .. Result=%d', [Integer(ThdScanSch_.WorkState)]); bTerminateThdScanSch_ := true; bIsStopCampn_ := true; llCampnEncCnt_ := ThdScanSch_.TotalEncCount; llCampnEncFailCnt_ := ThdScanSch_.TotalEncFailCount; if DlgEncCampn_ <> nil then begin DlgEncCampn_.Show; DlgEncCampn_ := nil; end; end; end; exit; end else if bClearCampn_ then begin bClearCampn_ := false; MgCampn_.ClearScanDate; MgCampn_.Save; end; if pProcCampn_ <> nil then exit; StartCampaignTask(MgCampn_.GetWorkableCampaign(bIgrLastWorkCampn_)); if bIgrLastWorkCampn_ then bIgrLastWorkCampn_ := false; pEnt := MgCampn_.GetDelayNotiCampaign; if pEnt <> nil then begin if pEnt.Info.bDelayNotice and (pEnt.Info.DelayCond = cdnOnce) then pEnt.dtLastNoti := 0 else pEnt.dtLastNoti := Now; MgCampn_.Save; pProcCampn_ := pEnt; // 구리지만 일단... 23_1114 15:35:16 kku try if pProcCampn_.Info.bNoActionVul then SetSchRstVul(true); PopupMessage(TYPE_MSG_CTTSCH_COMPLETE, '00:00:00|' + IntToStr(GetExistPiFileCount(pEnt.Info.sId))); finally pProcCampn_ := nil; end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. ProcessCampaign()'); end; end; procedure TManagerService.UpdateInternalInfo; var i: Integer; begin try {$IFNDEF DEBUG} if not bInitRule_ and GetConnected then begin _Trace('UpdateInternalInfo() .. ContentRule Init ..', 1); // 컨텐츠 룰을 서버에 등록된거와 같은지 체크 및 정리 25_0415 13:56:35 kku // 이전 버전에서 컨텐츠 룰 삭제 시 반영이 안되는 문제가 있어서 추가함 // 추후에 삭제 해도됨 var sDest: String := StringReplace(sDestSvrUrl_, 'agentLogRequest.do', 'open-api/content-rules?type=idOnly', [rfReplaceAll]); sDest := StringReplace(sDest, 'agentLogRequests.do', 'open-api/content-rules?type=idOnly', [rfReplaceAll]); var ss: TStringStream; Guard(ss, TStringStream.Create('', TEncoding.UTF8)); try HTTP_.Get(sDest, ss); if ss.DataString <> '' then begin var IdList: TStringList; Guard(IdList, TStringList.Create); var O: ISuperObject := SO(ss.DataString); IdList.CommaText := O.S['ids']; if IdList.Count > 0 then begin MgRule_.RefineRuleList(IdList); bInitRule_ := true; _Trace('UpdateInternalInfo() .. ContentRule Init .. OK', 1); end; end; except // .. end; end; {$ENDIF} if not bIsSendHWInfo_ then SendHwInfo; if PrefModel_.VpnAppName <> sVpnClient_ then sVpnClient_ := PrefModel_.VpnAppName; if (PrefModel_.NoticeContent <> '') and (sNoticeContent_ <> PrefModel_.NoticeContent) then begin // 공지사항 변경 감지 후 팝업 sNoticeContent_ := PrefModel_.NoticeContent; PopupMessage(TYPE_MSG_NOTIFICATION, sNoticeContent_); end; // if IsCheckPreventMac then // 전체 업체에서 사용가능 하도록 확대 22_0829 10:39:54 kku if not IsNewApi or PrefModel_.CheckAllowMAC then begin // 보안모드 진입 시 허용되지 않은 MAC 제한 체크 if IsNewApi or (Length(PrefModel_.RestricMac) >= 12) then begin var MacList: TStringList; var bAllowAccess: Boolean := false; Guard(MacList, TStringList.Create); if SplitString(PrefModel_.RestricMac, ';', MacList) > 0 then begin for i := 0 to MacList.Count - 1 do begin if (NicService_ <> nil) and NicService_.ContainMac(MacList[i]) then begin bAllowAccess := true; break; end; end; end; bIsRestricMac_ := not bAllowAccess; end else bIsRestricMac_ := false; end else if bIsRestricMac_ then bIsRestricMac_ := false; if UpdateTick = 0 then begin var dtNow: TDateTime := Now; if SecondsBetween(dtInfoFileCheck_, dtNow) >= 30 then begin dtInfoFileCheck_ := dtNow; var sRes: String := GetRunExePathDir + DIR_CONF; if not FileExists(sRes + DAT_AGENT) then begin _Trace('Lost .. agent info .. try recover.'); AgentModel_.Save; end; if bIsNewApi_ then begin if PrefModel_.Loaded and not FileExists(sRes + NAME_PREF + '-' + PrefModel_.PoFileName + EXT_PROP) then begin _Trace('Lost .. policy info .. try recover-1'); PrefModel_.Save; end; if PrefIdlModel_.Loaded and not FileExists(sRes + NAME_PREF + '-' + PrefIdlModel_.PoFileName + EXT_PROP) then begin _Trace('Lost .. policy info .. try recover-2'); PrefIdlModel_.Save; end; if PrefVulModel_.Loaded and not FileExists(sRes + NAME_PREF + '-' + PrefVulModel_.PoFileName + EXT_PROP) then begin _Trace('Lost .. policy info .. try recover-3'); PrefVulModel_.Save; end; if PrefOffline_.Loaded and not FileExists(sRes + NAME_PREF + '-' + PrefOffline_.PoFileName + EXT_PROP) then begin _Trace('Lost .. policy info .. try recover-4'); PrefOffline_.Save; end; if PrefExpPolicy_.Loaded and not FileExists(sRes + NAME_PREF + '-' + PrefExpPolicy_.PoFileName + EXT_PROP) then begin _Trace('Lost .. policy info .. try recover-5'); PrefExpPolicy_.Save; end; end else if not FileExists(sRes + DAT_PREF) then begin _Trace('Lost .. policy info .. try recover.'); PrefModel_.Save; end; if not FileExists(sRes + DAT_COMPANY) then begin _Trace('Lost .. company info .. try recover.'); var CompModel: TCompanyModel; Guard(CompModel, TCompanyModel.Create); CompModel.CustomerType := CUSTOMER_TYPE; CompModel.CustomerSubType := CUSTOMER_SUB_TYPE; CompModel.SvrDestList.AddStrings(ServerUrlList_); CompModel.Save(sRes + DAT_COMPANY); end; end; if (dtSoftInstTick_ = 0) or (HoursBetween(dtSoftInstTick_, dtNow) >= 4) then begin dtSoftInstTick_ := dtNow; // 4시간에 한번 소프트웨어 설치 정보 전송 22_0819 11:14:46 kku SendAppInstInfo; end; if (dtOldLogCheck_ = 0) or (HoursBetween(dtOldLogCheck_, dtNow) >= 12) then begin if gTrace <> nil then gTrace.DeleteOldLogs(PrefModel_.LogKeepDays); end; if EmDriveList_.Count > 0 then begin var sDrive: String; for i := EmDriveList_.Count - 1 downto 0 do begin sDrive := EmDriveList_[i]; if DirectoryExists(sDrive) then begin EmDriveList_.Delete(i); ProcessUSBArrival(sDrive); end; end; end; CatchDriveSatate; if not bCheckedFixDisk_ or ModePolicy.HdMonPopup then begin if bIsConnected_ or (PrefModel_.OffLogKind <> olkNone) or ((CUSTOMER_TYPE = CUSTOMER_WELFND) and (GetProcessPidByName('SUSBClient') <> 0)) then begin // 주기적으로 체크하도록 변경 // PC가 켜져있는 상태에도 고정 디스크를 제거할 수 있다 23_1206 17:33:37 kku bCheckedFixDisk_ := true; var MgFixDisk: TManagerFixedDisk; Guard(MgFixDisk, TManagerFixedDisk.Create); var ChgDiskList: TDetectDiskList; Guard(ChgDiskList, MgFixDisk.DetectChangeDisk); if ModePolicy.DetectFixedDisk and (ChgDiskList.Count > 0) then begin var LogInfo: TLogInfo; for i := 0 to ChgDiskList.Count - 1 do begin ZeroMemory(@LogInfo, SizeOf(LogInfo)); LogInfo.sCode := MONITOR_EMBEDDEDHARDDISK; LogInfo.sDevName := ChgDiskList[i].DInfo.sFriendlyName; LogInfo.sDevSerial := ChgDiskList[i].DInfo.sSerial; LogInfo.sDevClassId := ChgDiskList[i].DInfo.sClassGuid; LogInfo.sSummary := Format('[%s] Fixed Disk', [BooleanToStr(ChgDiskList[i].DType = ddtAdd, 'Add', 'Remove')]); LogInfo.sResInfo := IntToStr(ChgDiskList[i].DInfo.llSize); LogInfo.sAppPath := ChgDiskList[i].DInfo.sDrive; LogInfo.sComment := Format('%s, %s', [ChgDiskList[i].DInfo.sClass, ChgDiskList[i].DInfo.sDesc]); SendEventLogEx(@LogInfo); if IsDivPopup and ModePolicy.HdMonPopup then PopupMessage(TYPE_MSG_MONITOR_HARDDISK, LogInfo.sDevName); // if ChgDiskList[i].DType = ddtAdd then // ProcessUSBArrival(ChgDiskList[i].DInfo.sDrive) // else // ProcessUSBRemove(ChgDiskList[i].DInfo.sDrive); end; end; end; end; // 레지스트리 정보 확인, 복구 if // (CUSTOMER_TYPE = CUSTOMER_ALADIN) and (CountRegKeyValue(HKEY_LOCAL_MACHINE, REG_HE) < 9) then begin SetRegValueString(HKEY_LOCAL_MACHINE, REG_HE, 'Version', SdkVersion, true); SetRegValueInteger(HKEY_LOCAL_MACHINE, REG_HE, 'CT', CUSTOMER_TYPE, true); SetRegValueInteger(HKEY_LOCAL_MACHINE, REG_HE, 'CST', CUSTOMER_SUB_TYPE, true); SetRegValueInteger(HKEY_USERS, RecentUserSid + '\' + REG_HE, 'CT', CUSTOMER_TYPE, true); SetRegValueString(HKEY_LOCAL_MACHINE, REG_HE, 'EmpNo', AgentModel_.EmpNo, true); SetRegValueString(HKEY_LOCAL_MACHINE, REG_HE, 'UserName', AgentModel_.UserName, true); SetRegValueString(HKEY_LOCAL_MACHINE, REG_HE, 'HostName', AgentModel_.HostName, true); SetRegValueString(HKEY_LOCAL_MACHINE, REG_HE, 'DomainName', AgentModel_.DomainName, true); SetRegValueString(HKEY_LOCAL_MACHINE, REG_HE, 'LLO', IntToStr(DelphiToJavaDateTime(dtLastLogOn_)), true); // if sLastPolicy_ <> '' then begin SetRegValueString(HKEY_LOCAL_MACHINE, REG_HE, 'LP', IntToStr(DelphiToJavaDateTime(StrToDateTime(sLastPolicy_))), true); end; end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. UpdateInternalInfo()'); end; end; procedure TManagerService.OgnRecentFndList; var i, nTO: Integer; dtNow: TDateTime; begin try if RecentFndList_.Count = 0 then exit; dtNow := Now; Lock; try for i := RecentFndList_.Count - 1 downto 0 do begin if (RecentFndList_[i].sMName <> '') and (CompareText(RecentFndList_[i].sMName, 'CiscoCollabHost.exe') = 0) then nTO := 190 else nTO := 4; if SecondsBetween(RecentFndList_[i].dtReg, dtNow) > nTO then RecentFndList_.Delete(i); end; finally Unlock; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. OgnRecentFndList()'); end; end; function TManagerService.GetRecentFnd(sPath: String; var aEnt: TRecentFnd): Boolean; var i: Integer; begin Result := false; try if RecentFndList_.Count = 0 then exit; Lock; try for i := RecentFndList_.Count - 1 downto 0 do begin if CompareText(RecentFndList_[i].sPath, sPath) = 0 then begin aEnt := RecentFndList_[i]^; Result := true; exit; end; end; finally Unlock; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. GetRecentFnd()'); end; end; procedure TManagerService.AddDelayProcEnt(sId: String; dwDSec: DWORD); var pEnt: PDpEnt; begin try New(pEnt); pEnt.dwTick := GetTickCount; pEnt.dwDSec := dwDSec; pEnt.sId := sId; Lock; try DelayProcList_.Add(pEnt); finally Unlock; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. AddDelayProcEnt()'); end; end; function TManagerService.HasDelayProcEntById(sId: String): Boolean; var i: Integer; dwTick: DWORD; pEnt: PDpEnt; begin Result := false; try dwTick := GetTickCount; Lock; try for i := DelayProcList_.Count - 1 downto 0 do begin pEnt := DelayProcList_[i]; if (dwTick - pEnt.dwTick) > (pEnt.dwDSec * 1000) then begin DelayProcList_.Delete(i); continue; end; if sId = pEnt.sId then begin Result := true; exit; end; end; finally Unlock; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. HasDelayProcEntById()'); end; end; procedure TManagerService.AddRecentFnd(aEnt: TRecentFnd); var pEnt: PRecentFnd; begin try New(pEnt); pEnt^ := aEnt; Lock; try RecentFndList_.Add(pEnt); finally Unlock; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. AddRecentFnd()'); end; end; procedure TManagerService.DelRecentFnd(sPath: String); var i: Integer; begin try if RecentFndList_.Count = 0 then exit; Lock; try for i := RecentFndList_.Count - 1 downto 0 do begin if CompareText(RecentFndList_[i].sPath, sPath) = 0 then begin RecentFndList_.Delete(i); exit; end; end; finally Unlock; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. GetRecentFnd()'); end; end; procedure TManagerService.ProcessStatusOld(bFailChangeDestUrl: Boolean = true); function CheckUpdateAble(sNewVer, sCurVer: String): Boolean; var CurVers, NewVers: TStringList; ullNew, ullCur: ULONGLONG; i: Integer; begin Result := false; try if sNewVer = sCurVer then exit; Guard(NewVers, TStringList.Create); Guard(CurVers, TStringList.Create); if SplitString(sNewVer, '.', NewVers) = 0 then exit; if SplitString(sCurVer, '.', CurVers) = 0 then begin Result := StrToIntDef(NewVers[0], 0) > StrToIntDef(sCurVer, 0); exit; end; for i := 0 to NewVers.Count - 1 do begin if i >= CurVers.Count then begin Result := true; exit; end; if StrToIntDef(NewVers[i], 0) < StrToIntDef(CurVers[i], 0) then exit; if StrToIntDef(NewVers[i], 0) > StrToIntDef(CurVers[i], 0) then begin Result := true; exit; end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. CheckUpdateAble()'); end; end; procedure ProcessCttSchSchedule(sOpt: String); var O: ISuperObject; SchOpt: TFileScanOpt; OptList: TStringList; i, nPos: Integer; dtScan, dtRecent: TDateTime; sName: String; begin if ThdScanSch_ <> nil then begin case ThdScanSch_.WorkState of tsStop, tsFail : begin _Trace('Fail.. ScanPersonalInfo .. Result=%d', [Integer(ThdScanSch_.WorkState)]); bTerminateThdScanSch_ := true; bIsStopCampn_ := true; llCampnEncCnt_ := ThdScanSch_.TotalEncCount; llCampnEncFailCnt_ := ThdScanSch_.TotalEncFailCount; if DlgEncCampn_ <> nil then begin DlgEncCampn_.Show; DlgEncCampn_ := nil; end; end; end; exit; end; if IsSchRstVul and (PrefModel_.PersonalInfoFileMax = 0) then begin DeleteDir(GetRunExePathDir + DIR_CTTSCHRST); SetSchRstVul(GetPersonalInfoResults <> 0); end; if sOpt = '' then exit; // 개인정보 검사는 수면모드에서도 동작하도록 다시 동작 롤백 // 현재 서버에서 검사 정책 송신 시 한번만 하기 때문에 수면모드에서 무시하면 // 무시한 날은 개인정보 검사가 되지 않음 22_1121 09:26:30 kku // {$IFNDEF DEBUG} // if BS1ModeKind_ = hmkSleep then // exit; // {$ENDIF} // if CUSTOMER_TYPE <> CUSTOMER_LOCAL then // exit; try Guard(OptList, TStringList.Create); SplitString(sOpt, '|', OptList); if OptList.Count < 4 then exit; // 사용자 지정 패턴, 키워드에 | 값이 들어갈 수 있다.. // 이 값이 들어가면 값들이 옵션으로 나눠져서 제대로 설정한 값이 대입되지 않음.. // 그래서 한번 정제해준다, 서버 쪽에서 옵션 구분 값을 | 가 아닌 값으로 바꾸면 되긴 하는데.. // 일단 이렇게 처리한다. 22_1111 13:52:53 kku for i := OptList.Count - 1 downto 0 do begin if (i - 1) = -1 then break; sOpt := OptList[i]; if not sOpt.StartsWith('scanid:') and not sOpt.StartsWith('scandate:') and not sOpt.StartsWith('scantype:') and not sOpt.StartsWith('scanoption:') and not sOpt.StartsWith('scandrm:') and not sOpt.StartsWith('scanzip:') and not sOpt.StartsWith('custom__') and not sOpt.StartsWith('scansizelimit') and not sOpt.StartsWith('scantimelimit') and not sOpt.StartsWith('exceptfolder') and not sOpt.StartsWith('scanname') and not sOpt.StartsWith('scannamedisplay') and not sOpt.StartsWith('scanoutlook') then begin OptList[i - 1] := OptList[i - 1] + '|' + sOpt; end; end; ZeroMemory(@SchOpt, SizeOf(SchOpt)); for i := 0 to OptList.Count - 1 do begin sOpt := OptList[i]; if sOpt.StartsWith('scanid:') then begin Delete(sOpt, 1, 7); SchOpt.sScanId := sOpt; end else if sOpt.StartsWith('scandate:') then begin Delete(sOpt, 1, 9); dtScan := StrToDateTimeDef(sOpt, 0); end else if sOpt.StartsWith('scantype:') then begin Delete(sOpt, 1, 9); SchOpt.bPartScan := sOpt.ToLower = 'part'; end else if sOpt.StartsWith('scandrm:') then begin Delete(sOpt, 1, 8); SchOpt.CttSchOpt.bIncDrm := sOpt.ToLower = 'true'; end else if sOpt.StartsWith('scanzip:') then begin Delete(sOpt, 1, 8); SchOpt.CttSchOpt.bIncZip := sOpt.ToLower = 'true'; end else if sOpt.StartsWith('scanoption:') then begin Delete(sOpt, 1, 11); SchOpt.sSchPtrns := StringReplace(sOpt, ';', '|', [rfReplaceAll]); end else if sOpt.StartsWith('scansizelimit:') then begin Delete(sOpt, 1, 14); SchOpt.nLimitSizeMB := StrToIntDef(sOpt, 0); end else if sOpt.StartsWith('scantimelimit:') then begin Delete(sOpt, 1, 14); SchOpt.nSchTimeoutSec := StrToIntDef(sOpt, 0); if SchOpt.nSchTimeoutSec = 0 then SchOpt.nSchTimeoutSec := 20; end else if sOpt.StartsWith('exceptfolder:') then begin Delete(sOpt, 1, 13); SchOpt.sIgrWordPath := StrListToCommaStr(sOpt, '|', false, true); end else if sOpt.StartsWith('scanname:') then begin Delete(sOpt, 1, 9); SchOpt.sSchTitle := sOpt; end else if sOpt.StartsWith('scannamedisplay:') then begin Delete(sOpt, 1, 16); SchOpt.bShowSchTitle := sOpt.ToLower = 'true'; // end else // if sOpt.StartsWith('scanoutlook:') then // begin // Delete(sOpt, 1, 12); // SchOpt.bSchOutlook_ := sOpt.ToLower = 'true'; end else if sOpt.StartsWith('custom__') then begin sOpt := StringReplace(sOpt, ';', '|', [rfReplaceAll]); sOpt := StringReplace(sOpt, #13#10, '|', [rfReplaceAll]); Delete(sOpt, 1, 8); nPos := Pos('__keyword:', sOpt); if nPos = 0 then nPos := Pos('__pattern:', sOpt); if nPos > 0 then begin sName := Copy(sOpt, 1, nPos - 1); Delete(sOpt, 1, nPos + 9); // 9는 __pattern: 또는 __keyword: 길이 - 1 SumString(SchOpt.CttSchOpt.sCustomKwdPtrn, sName + '::' + sOpt, '**'); end; end; end; if SchOpt.sScanId = '' then begin _Trace('Fail .. ProcessCttSchSchedule() .. No ScanId'); exit; end; if dtScan = 0 then begin _Trace('Fail .. ProcessCttSchSchedule() .. No ScanDate'); exit; end; if (SchOpt.sSchPtrns = '') and (SchOpt.CttSchOpt.sCustomKwdPtrn = '') then begin _Trace('Fail .. ProcessCttSchSchedule() .. No ScanPatterns'); exit; end; if SchOpt.sSchPtrns = '' then begin // 여기 비어 있으면 "ptnsch.dat" 기본 체크된 패턴이 검색되므로 임의로 채워준다. 22_1114 16:29:51 kku SchOpt.sSchPtrns := ''; end; dtRecent := MgCttSch_.GetTastRecentDT(SchOpt.sScanId); if dtRecent <> 0 then begin if CompareDate(dtScan, dtRecent) <> 1 then exit; if SchOpt.bPartScan then SchOpt.dtRecent := MgCttSch_.GetTastRecentLcDT(SchOpt.sScanId); end else SchOpt.bPartScan := false; _Trace('ProcessCttSchSchedule() Begin .. RcvScanDate=%s, ScanId=%s', [DateTimeToStr(dtScan), SchOpt.sScanId]); var PO: TPrefModel := GetModePolicy; SchOpt.sScanExt := DOC_EXTS; SchOpt.nLangId := 1; SchOpt.nLimitSizeMB := PO.CfLimitMB; SchOpt.nSchTimeoutSec := PO.CfTimeoutSec; SchOpt.CttSchOpt.nUnzipDepth := PO.CfZipDepth; SchOpt.CttSchOpt.hRcvHwnd := hRcvHwnd_; SchOpt.CttSchOpt.nWorkPriority := -1; SchOpt.CttSchOpt.sKvMdPath := GetRunExePathDir + 'bin\'; StartPiSchTask(SchOpt, dtScan); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. ProcessCttSchSchedule()'); end; end; procedure ProcessCltFldSchedule; var bCollectAble: Boolean; FileCollectPlan: TFileCollectPlan; FileCollectKind: TFileCollectKind; sDate: String; dtNow: TDateTime; begin try if ThdCltFld_ <> nil then begin case ThdCltFld_.WorkState of tsCompleted : begin FreeAndNil(ThdCltFld_); AgentModel_.RecentCltFldDT := Now; AgentModel_.Save; end; tsStop, tsFail : end; exit; end; FileCollectPlan := PrefModel_.FileCollectPlan; FileCollectKind := PrefModel_.FileCollectKind; if (FileCollectPlan = fcpNone) or (FileCollectKind = fckNone) then begin AgentModel_.RecentCltFldDT := 0; AgentModel_.Save; exit; end; // {$IFDEF DEBUG} // AgentModel_.RecentCltFldDT := 0; // {$ENDIF} if GetModeKind = hmkSleep then exit; dtNow := Now; if (AgentModel_.RecentCltFldDT <> 0) and IsSameDay(TDate(AgentModel_.RecentCltFldDT), TDate(dtNow)) then exit; if PrefModel_.FileCollectDate = 0 then exit; if FileCollectKind = fckFile then begin if not FileExists(PrefModel_.TgFileCollect) then exit; end else begin if not DirectoryExists(PrefModel_.TgFileCollect) then exit; end; case FileCollectPlan of fcpNone : exit; fcpOnce : bCollectAble := IsSameDay(PrefModel_.FileCollectDate, TDate(dtNow)); fcpWeek : bCollectAble := DayOfWeek(PrefModel_.FileCollectDate) = DayOfWeek(TDate(dtNow)); fcpMonthDate : bCollectAble := DayOf(PrefModel_.FileCollectDate) = DayOf(dtNow); fcpMonthWeek : bCollectAble := (WeekOfTheMonth(PrefModel_.FileCollectDate) = WeekOfTheMonth(dtNow)) and (DayOfWeek(PrefModel_.FileCollectDate) = DayOfWeek(TDate(dtNow))); end; // {$IFDEF DEBUG} // bCollectAble := true; // {$ENDIF} if bCollectAble then begin _Trace('Start .. Collect files from folder="%s"', [PrefModel_.TgFileCollect], 1); // todo : 나중에 감춰준다 22_1101 15:47:15 kku ThdCltFld_ := TThdSendFilesFromDir.Create(PrefModel_.TgFileCollect, FileCollectKind = fckFolderIncSub); ThdCltFld_.StartThread; end else begin AgentModel_.RecentCltFldDT := dtNow; AgentModel_.Save; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. ProcessCltFldSchedule()'); end; end; procedure ProcessUpdate(sNewVer: String); var sUrl, sPtPath: String; fs: TFileStream; nOldTO: Integer; begin try sUrl := StringReplace(DestServerUrl, 'agentLogRequest.do', 'agentDownloadReq/', [rfReplaceAll]); sUrl := StringReplace(sUrl, 'agentLogRequests.do', 'agentDownloadReq/', [rfReplaceAll]) + DOWNLOAD_TYPE_PATCH; nOldTO := HTTP_.ReadTimeout; HTTP_.ReadTimeout := 120000; sPtPath := GetProgramFilesDir + DIR_TG; fs := TFileStream.Create(sPtPath + 'patch.zip', fmCreate); try HTTP_.Get(sUrl, fs); Sleep(500); if FileExists(sPtPath + ZIP_PT) then begin FreeAndNil(fs); if GetFileSize_path(sPtPath + ZIP_PT) = 0 then begin DeleteFile(PChar(sPtPath + ZIP_PT)); exit; end; TZipFile.ExtractZipFile(sPtPath + ZIP_PT, sPtPath); DeleteFile(PChar(sPtPath + ZIP_PT)); if FileExists(sPtPath + EXE_PT) then begin SendEventLog(URI_USERUPDATE, SYSEVT_AGENT_PATCH, 'Patch Downloaded : ' + sNewVer); ExecuteApp(sPtPath + EXE_PT, '', SW_HIDE); UpdateTick := GetTickCount; end; end; finally if fs <> nil then FreeAndNil(fs); HTTP_.ReadTimeout := nOldTO; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. ProcessUpdate()'); end; end; var sIp, sMac, sEulaCon, sHostName, sScanPolicy, sDirCollect, sAvInfo, sAsInfo, sFwInfo, sRes: String; O, OSub: ISuperObject; i: Integer; bChangedPolicy: Boolean; dtNow: TDateTime; NewAgentInfo: TCheckAgentInfo; bChangeAgentInfo: Boolean; Label LB_ProcessPolicy; function IsChangeAgentInfo: Boolean; begin Result := true; with AgentInfo do begin if sAgentId <> NewAgentInfo.sAgentId then exit; if sIp <> NewAgentInfo.sIp then exit; if sIps <> NewAgentInfo.sIps then exit; if sMAC <> NewAgentInfo.sMAC then exit; if sHostName <> NewAgentInfo.sHostName then exit; // if sStatusType <> NewAgentInfo.sStatusType then exit; if sEulaCon <> NewAgentInfo.sEulaCon then exit; if sLocation <> NewAgentInfo.sLocation then exit; if sPwSet <> NewAgentInfo.sPwSet then exit; if sPwSetTermOk <> NewAgentInfo.sPwSetTermOk then exit; if sScrnLock <> NewAgentInfo.sScrnLock then exit; if sOsVer <> NewAgentInfo.sOsVer then exit; if sAvInfo <> NewAgentInfo.sAvInfo then exit; // if sAsInfo <> NewAgentInfo.sAsInfo then exit; if sFwInfo <> NewAgentInfo.sFwInfo then exit; if sOsSafe <> NewAgentInfo.sOsSafe then exit; if sPatchExist <> NewAgentInfo.sPatchExist then exit; if sAvSafe <> NewAgentInfo.sAvSafe then exit; if sAvUptodate <> NewAgentInfo.sAvUptodate then exit; if sFwSafe <> NewAgentInfo.sFwSafe then exit; if sPiSafe <> NewAgentInfo.sPiSafe then exit; // if sSafeBlock <> NewAgentInfo.sSafeBlock then exit; if sEmpNo <> NewAgentInfo.sEmpNo then exit; // if bSafePcSHCD <> NewAgentInfo.bSafePcSHCD then exit; if sModeName <> NewAgentInfo.sModeName then exit; end; Result := false; end; var bConnected, bPrevConnected: Boolean; SecuApp: TSecureApp; begin try sScanPolicy := ''; sDirCollect := ''; // 접속 상태 처리를 TimerCheckConnect()에서 여기로 옮김 23_0324 12:04:45 kku // if not Connected then // goto LB_ProcessPolicy; if sEmpNo_ = '' then begin _Trace('StatusOld() Init .. Empty EmpNo ..'); Sleep(3000); exit; end; sHostName := sUserName_; if sHostName = '' then begin _Trace('StatusOld() Init .. Empty HostName?? .. GetComAct=%s', [GetComName + '\' + GetAccount]); Sleep(5000); exit; // sHostName := GetComName + '\' + GetAccount; end; if IsOfflineMode then exit; // if IsServiceAvailable and // ((VulService_.IsSafeMode and VulService_.IsWhiteApp) or IsTemporaryConn) then // sStatusType := 'Connected' // else // sStatusType := 'Disconnected'; SecuApp := HandleSecurity_.GetMainAv; if (SecuApp <> nil) and (SecuApp.Name <> '') then begin sAvInfo := SecuApp.Name + MODEL_SEPARATOR + // MODEL_SEPARATOR + SecuApp.Path + MODEL_SEPARATOR + SecuApp.Timestamp; end else sAvInfo := 'null'; SecuApp := HandleSecurity_.GetMainAs; if (SecuApp <> nil) and (SecuApp.Name <> '') then begin sAsInfo := SecuApp.Name + MODEL_SEPARATOR + SecuApp.Path + MODEL_SEPARATOR + SecuApp.Timestamp; end else sAsInfo := 'null'; SecuApp := HandleSecurity_.GetMainFw; if (SecuApp <> nil) and (SecuApp.Name <> '') then begin sFwInfo := SecuApp.Name + MODEL_SEPARATOR + SecuApp.Path + MODEL_SEPARATOR + SecuApp.Timestamp; end else sFwInfo := 'null'; sEulaCon := 'disagree'; if AgentModel_.EulaDT <> 0 then sEulaCon := FormatDateTime('yyyy-mm-dd hh:nn:ss', AgentModel_.EulaDT); sIp := NicService_.GetIP; sMac := NicService_.GetMAC; NewAgentInfo.sAgentId := sAgentId_; NewAgentInfo.sIp := sIp; NewAgentInfo.sIps := NicService_.IpAll; NewAgentInfo.sMAC := sMac; if IsUseHostNameOnly then NewAgentInfo.sHostName := sComName_ else NewAgentInfo.sHostName := sHostName; // NewAgentInfo.sStatusType := sStatusType; NewAgentInfo.sEulaCon := sEulaCon; if PrefModel_.PolicyGroup <> '' then NewAgentInfo.sLocation := PrefModel_.PolicyGroup else NewAgentInfo.sLocation := PrefModel_.PolicyName; NewAgentInfo.sPwSet := BooleanToStr(VulService_.IsPasswordSet, 'true', 'false'); NewAgentInfo.sPwSetTermOk := BooleanToStr(VulService_.IsPasswordSetTermOk, 'true', 'false'); NewAgentInfo.sScrnLock := BooleanToStr(VulService_.IsScreenSaverSet, 'true', 'false'); if HandleConfig_.OsMajorVer <> '' then NewAgentInfo.sOsVer := Format('%s (%s)', [HandleConfig_.OsVersion, HandleConfig_.OsMajorVer]) // VulService_.OsVersion; else NewAgentInfo.sOsVer := HandleConfig_.OsVersion; NewAgentInfo.sAvInfo := sAvInfo; // NewAgentInfo.sAsInfo := sAsInfo; NewAgentInfo.sFwInfo := sFwInfo; NewAgentInfo.sOsSafe := BooleanToStr(VulService_.IsOsSafe, 'true', 'false'); NewAgentInfo.sPatchExist := BooleanToStr(VulService_.IsOsPatchUptoDate, 'true', 'false'); NewAgentInfo.sAvUptodate := BooleanToStr(VulService_.IsAntiVirusUpToDate, 'true', 'false'); NewAgentInfo.sAvSafe := BooleanToStr(VulService_.IsAvOn, 'true', 'false'); NewAgentInfo.sFwSafe := BooleanToStr(VulService_.IsFirewallOn, 'true', 'false'); NewAgentInfo.sPiSafe := BooleanToStr(bSchRstVul_, 'false', 'true'); case GetModeKind of hmkSleep : NewAgentInfo.sModeName := 'Sleep'; hmkSecurity : NewAgentInfo.sModeName := 'Secu'; hmkVulnerability : NewAgentInfo.sModeName := 'Vul'; hmkOffline : NewAgentInfo.sModeName := 'Offline'; hmkException : NewAgentInfo.sModeName := 'Exption'; end; // NewAgentInfo.sSafeBlock := BooleanToStr(VulService_.IsSafeMode, 'true', 'false'); NewAgentInfo.sEmpNo := sEmpNo_; // NewAgentInfo.bSafePcSHCD := (CUSTOMER_TYPE = CUSTOMER_SHCD) and FileExists(GetRunExePathDir + EXE_SafePCUninst); O := SO; bPrevConnected := GetConnected; bChangeAgentInfo := IsChangeAgentInfo; // 공통 O.S['mwAKey_AGENTID'] := NewAgentInfo.sAgentId; O.S['mwAKey_LOCATION'] := NewAgentInfo.sLocation; O.S['mwAKey_EMPNO'] := NewAgentInfo.sEmpNo; O.S['mwAKey_IP'] := NewAgentInfo.sIp; O.S['mwAKey_HOSTNAME'] := NewAgentInfo.sHostName; O.S['mwAKey_MAC'] := NewAgentInfo.sMAC; O.S['KEY_MODE'] := NewAgentInfo.sModeName; if not bPrevConnected or bChangeAgentInfo then begin O.S['MODEL_ID'] := NewAgentInfo.sAgentId; O.S['mwAKey_IPS'] := NewAgentInfo.sIps; // O.S['mwAKey_STATUS'] := NewAgentInfo.sStatusType; O.S['mwAKey_COLLASTCONN'] := FormatDateTime('yyyy-mm-dd hh:nn:ss', Now); O.S['mwAKey_COLVERSION'] := SdkVersion; O.S['mwAKey_EULACONFIRMED'] := NewAgentInfo.sEulaCon; O.S['mwAKey_PWDSET'] := NewAgentInfo.sPwSet; if NewAgentInfo.sPwSetTermOk <> 'true' then begin var nOver: Integer := DaysBetween(Now, dtLastChangePW_); if (nOver > 0) and (nOver > PrefModel_.PwChkTermDay) then O.S['mwAKey_PWDEXPIRED'] := IntToStr(nOver - PrefModel_.PwChkTermDay) else O.S['mwAKey_PWDEXPIRED'] := 'true'; end else O.S['mwAKey_PWDEXPIRED'] := NewAgentInfo.sPwSetTermOk; O.S['mwAKey_SCRNLOCK'] := NewAgentInfo.sScrnLock; O.S['mwAKey_OSVER'] := NewAgentInfo.sOsVer; O.S['mwAKey_PATCHES'] := 'null'; O.S['mwAKey_AVINFORM'] := NewAgentInfo.sAvInfo; // _Trace('NewAgentInfo.sAvInfo="%s"', [NewAgentInfo.sAvInfo]); O.S['mwAKey_ASINFORM'] := 'null'; // NewAgentInfo.sAsInfo; O.S['mwAKey_FIREWALLINFO'] := NewAgentInfo.sFwInfo; O.S['mwAKey_SOFTWAREINFO'] := 'null'; O.S['mwAKey_ADDEULACONFIRM'] := 'false'; O.S['mwAKey_OSSAFE'] := NewAgentInfo.sOsSafe; O.S['mwAKey_PATCHEXIST'] := NewAgentInfo.sPatchExist; O.S['mwAKey_AVSAFE'] := NewAgentInfo.sAvSafe; O.S['mwAKey_ASSAFE'] := 'true'; O.S['mwAKey_FWSAFE'] := NewAgentInfo.sFwSafe; O.S['mwAKey_PISAFE'] := NewAgentInfo.sPiSafe; // O.S['mwAKey_SAFEBLOCKSETTING'] := NewAgentInfo.sSafeBlock; // O.S['mwAKey_VPNINFO'] := NewAgentInfo.sEmpNo; // O.S['mwAKey_AGENTTYPE'] := ''; // PC, VDI 여부 // if NewAgentInfo.bSafePcSHCD then O.S['mwAKey_SAFEPC'] := 'true'; end else begin O.S['KEY_LASTPOLICY'] := sLastPolicy_; end; // {$IFDEF DEBUG} SaveJsonObjToFile(O, 'c:\a.json'); {$ENDIF} sRes := HttpPost(sDestSvrUrl_, '123120', O.AsString); // 접속 상태 처리를 TimerCheckConnect()에서 여기로 옮김 23_0324 12:04:45 kku try // bConnected := (sRes <> '') or (sRes <> 'true'); bConnected := (sRes = POST_TIMEOUT) or ( (sRes <> '') and (sRes <> 'true') and (sRes <> '404') and sRes.Contains('KEY_LASTPOLICY') ); if not bConnected then begin if not bPrevConnected then begin if bFailChangeDestUrl then ChangeDestinationUrl; end else SetConnected(false, false); end else if not bPrevConnected then begin if (sRes = POST_TIMEOUT) or (Pos('mwPKey_LOCNAME', sRes) = 0) then // 2.7에서 요청시 "KEY_LASTPOLICY" 키 값만 떨어지는데 접속해제 거르기 위해 추가 begin bConnected := false; if bFailChangeDestUrl then ChangeDestinationUrl; // 음... 타임아웃 되도 이전 접속이 false라면 접속 정보 변경 시도해준다 23_0608 13:49:09 kku end else SetConnected(true, false); end; if bConnected then begin if VulService_.IsVpnOn and bDoEmpNoCheck_ then begin // 사번검증을 통해 미검증 시 보안모드 진입을 막을 예정이었으나... // 일단 그렇게까지 동작하지 않도록 함 22_0531 16:04:58 kku bIsEmpNoOk_ := VerifyEmpNo(DestServerUrl, HTTP_, sEmpNo_); bDoEmpNoCheck_ := false; if not bIsEmpNoOk_ then begin PopupMessage(TYPE_MSG_VUL_EMPNO); if CUSTOMER_TYPE = CUSTOMER_KFTC then begin // 금융결제원의 경우 사번이 유효하지 않은 경우 (인사연동 안된 사번) // 보안모드 차단 되도록 기능 추가 23_0425 12:52:05 kku VulService_.SetDisconnect(true); end; end; end else bIsEmpNoOk_ := true; end; except _Trace('Fail .. ConnectionCheck'); end; if not bConnected or (sRes = POST_TIMEOUT) then goto LB_ProcessPolicy; // 접속 상태 처리 끝 --------------------------------------------------------- try O := SO(sRes); if O = nil then begin _Trace('Invalid PolicyData ... 2'); exit; end; except _Trace('Invalid PolicyData ... 1'); exit; end; // SaveJsonObjToFile(O, 'c:\b.json'); if CUSTOMER_TYPE = CUSTOMER_SHCD then begin // if ( (sEmpNo_ = '') or (CompareText(sEmpNo_, 'Empty') = 0) ) and // ( (O.S['mwPKey_EMPNO'] <> '') and (CompareText(O.S['mwPKey_EMPNO'], 'Empty') <> 0) ) then // 서버에서 내려주는 사번과 항상 동일하게 맞추도록 보완 23_0328 15:36:34 kku var sSvrEmpNo: String := O.S['mwPKey_EMPNO']; if (sSvrEmpNo <> '') and (sSvrEmpNo <> sEmpNo_) then begin // _Trace('Change EmpNo .. %s > %s', [sEmpNo_, sSvrEmpNo]); _Trace('[07] 사번 변경, %s > %s', [sEmpNo_, sSvrEmpNo]); SendEventLogEx(LOG_CHANGE_EMPNO, Format('[Server] EmpId Changed. (%s > %s)', [sEmpNo_, sSvrEmpNo]), false); AgentModel_.EmpNo := sSvrEmpNo; AgentModel_.Save; UpdateAgentInfo; end; end; if O.S['KEY_QUARANTINE'].ToLower = 'true' then begin _Trace('격리 해제된 파일 발견', 1); ProcessReleaseQuarantineFiles; end; // {$IFDEF DEBUG} SaveJsonObjToFile(O, 'c:\s.json'); {$ENDIF} if O.S['mwPKey_LOCNAME'] = '' then begin // 시그널 전송이 와도 정책 적용 되도록 보완 // UpdatePolicyActive() 안에 정책 스레드 활성화도 있지만 직접 처리하는 정책도 있음 23_0322 07:53:21 kku // TimerCheckServiceAvailable()로 이동 23_0322 08:01:46 kku // UpdatePolicyActive(ModePolicy); // ReadTimeout으로 결과를 못가져왔을때 처리 22_0615 14:38:06 kku // _Trace('Faill .. ReadPolicy .. Empty?=[%s]', [O.AsString]); exit; end; _Trace('정책 수신됨', 1); if CUSTOMER_TYPE = CUSTOMER_KOCES then begin if sUName_ = '' then begin // 사용자 이름 가져오기 추가 23_0327 16:34:28 kku if (dwUNameChkTick_ = 0) or ((GetTickCount - dwUNameChkTick_) > 7200000) then // 2시간 마다 체크 begin dwUNameChkTick_ := GetTickCount; try var sInfo: String := GetEmpNoInfo(DestServerUrl, HTTP_, sEmpNo_); if sInfo <> '' then begin var OInfo: ISuperObject := SO(sInfo); sUName_ := OInfo.S['name']; end; except // end; end; end; end; O.S['mwPKey_ISOSPATCHSELECT'] := O.S['mwPKey_BLOCKPENDING']; // O.S['mwPKey_OPTIONH'] := O.S['mwPKey_BLOCKPORT']; // O.S['mwPKey_BLOCKPORT'] := 'false'; // O.Delete('mwPKey_BLOCKPENDING'); if AgentModel_.Location <> O.S['mwPKey_LOCNAME'] then begin AgentModel_.Location := O.S['mwPKey_LOCNAME']; AgentModel_.Save; _Trace('그룹 정책 변경됨', 1); end; if ((AgentModel_.IP = '') or (AgentModel_.IP = IP_NULL)) and ((sIp <> '') and (sIp <> IP_NULL)) then begin AgentModel_.IP := sIp; AgentModel_.MAC := sMac; if IsUseHostNameOnly then AgentModel_.HostName := sComName_ else AgentModel_.HostName := sUserName_; if AgentModel_.FirstConn then begin SendEventLog(URI_CONNECT, SYSEVT_AGENT_INSTALL, 'Agent first connected'); AgentModel_.FirstConn := false; end; AgentModel_.Save; end; try // 전역 포트 블럭으로 사용동의서 가져오기 전에 짤릴 수 있어서 미리 받아놓는다 22_0503 10:02:52 kku if (sEulaContent_ = '') and (AgentModel_.AgentId <> '') then begin var sDest: String := StringReplace(sDestSvrUrl_, 'agentLogRequest.do', 'agentEulaContent', [rfReplaceAll]); sDest := StringReplace(sDest, 'agentLogRequests.do', 'agentEulaContent', [rfReplaceAll]); sDest := sDest + '/' + AgentModel_.AgentId; // sDest := 'https://192.168.14.125:8443/agentEulaContent/김진아'; sEulaContent_ := HTTP_.Get(sDest); // 보안서약서 비어 있는지 체크 22_0727 16:19:51 kku if (sEulaContent_ <> '') and not sEulaContent_.EndsWith('null}') then begin if AgentModel_.EulaTxt <> sEulaContent_ then begin AgentModel_.EulaTxt := sEulaContent_; AgentModel_.Save; end; end else sEulaContent_ := ''; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. GetEulaContent ..'); end; {$IFNDEF DEBUG} if not bRcvRemoveAgent_ and (Trim(O.S['KEY_FORCEUNINSTALL']).ToLower = 'true') then begin _Trace('Req .. AgentUninstall ..'); bRcvRemoveAgent_ := true; SendEventLog(URI_USER_ACTION, SYSEVT_REQ_AGENT_UNINSTALL, '[Req] Uninstall Agent'); if hRcvHwnd_ <> 0 then PostMessage(hRcvHwnd_, WM_REQ_AGENT_UNINSTALL, 0, 0); end; {$ENDIF} sScanPolicy := O.S['KEY_SCANSCHEDULE']; O.S['KEY_SCANSCHEDULE'] := ''; sDirCollect := O.S['KEY_DIRCOLLECT']; O.S['KEY_DIRCOLLECT'] := ''; if bChangeAgentInfo then AgentInfo := NewAgentInfo; sLastPolicy_ := O.S['KEY_LASTPOLICY']; bChangedPolicy := PrefModel.SetPrefModel(O); if bChangedPolicy then begin if PrefModel_.IdlPolicy <> '' then begin try OSub := SO(PrefModel_.IdlPolicy); PrefIdlModel_.SetPrefModel(OSub); except _Trace('Invalid SubPolicyData ... 1'); end; end else if PrefIdlModel_.Loaded then PrefIdlModel_.Clear; if PrefModel_.VulPolicy <> '' then begin try OSub := SO(PrefModel_.VulPolicy); PrefVulModel_.SetPrefModel(OSub); except _Trace('Invalid SubPolicyData ... 2'); end; end else if PrefVulModel_.Loaded then PrefVulModel_.Clear; if PrefModel_.OffPolicy <> '' then begin try OSub := SO(PrefModel_.OffPolicy); PrefOffline_.SetPrefModel(OSub); except _Trace('Invalid SubPolicyData ... 3'); end; end else if PrefOffline_.Loaded then PrefOffline_.Clear; // if PrefModel_.ExpPolicy <> '' then // begin // try // OSub := SO(PrefModel_.ExpPolicy); // PrefExpPolicy_.SetPrefModel(OSub); // except // _Trace('Invalid SubPolicyData ... 4'); // end; // end else // if PrefExpPolicy_.Loaded then // PrefExpPolicy_.Clear; if PrefModel.VpnAppName <> sVpnClient_ then sVpnClient_ := PrefModel.VpnAppName; _Trace('정책 업데이트 완료', 1); end; sAgentPatchVersion_ := PrefModel.AgentPatchVersion; LB_ProcessPolicy : //// if IsCheckExpireDate then // 전체 업체에서 사용가능 하도록 확대 22_0803 12:56:03 kku // begin // // 보안모드 진입 시 날짜 제한 체크 // try // if (PrefModel.RestricDate <> '') then // begin // var dt: TDateTime := AppendTime(TDate(ConvStrToDateTime(PrefModel.RestricDate)), 23, 59, 59, 0); // bIsRestricDate_ := (dt <> 0) and (CompareDateTime(dt, Now) = -1); // if bIsRestricDate_ then // PrefModel.IsAllowAccess := false; // end else // bIsRestricDate_ := false; // except // on E: Exception do // ETgException.TraceException(Self, E, 'Fail .. IsCheckExpireDate()'); // end; // end; // 네트워크 카드 내렸다 올렸을때 정책 다시 받아오면서 // PrefModel.IsOsPatchCheck = false로 바뀌는 바람에 초기화 되는 현상 있음 22_0614 09:37:37 kku // if IsOsPatchCheckWeek then // begin // if not PrefModel.IsOsPatchCheck and (AgentModel_.LastOsPatchDT <> 0) then // begin // // OS 패치 확인 Off되면 초기화 // AgentModel_.LastOsPatchDT := 0; // AgentModel_.Save; // end; // end; UpdateInternalInfo; // if IsUseAfterReport and PrefModel.IsUseAfterReport then if PrefModel.IsUseAfterReport then begin if AgentModel_.AfterRptDT <> 0 then PopupAfterReport; end; // 보안 정책 활성화 // TimerCheckServiceAvailable()로 이동 23_0322 08:01:57 kku // UpdatePolicyActive(ModePolicy); if UpdateTick <> 0 then begin // 10분간 업데이트 시도가 끝나지 않으면 // 다시 시도 하기 위해 초기화 해준다 23_0830 13:41:36 kku if (GetTickCount - UpdateTick) >= 600000 then UpdateTick := 0; end; if (UpdateTick = 0) and (sAgentPatchVersion_ <> '') and CheckUpdateAble(sAgentPatchVersion_, SdkVersion) then begin ProcessUpdate(sAgentPatchVersion_); end else begin ProcessCttSchSchedule(sScanPolicy); ProcessCltFldSchedule; end; // ProcessCttSchSchedule('scanid:kuedcebztckkbblkkkzt|scandate:2022-08-10 09:14:27|scantype:part|scanoption:1056002;1056006;1057010;'); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. TimerProcessStatus()'); end; end; procedure TManagerService.TimerCheckOsConfig(aSender: TObject); procedure ProcessIdleLock; var LastInput: TLastInputInfo; dwTick: DWORD; begin if ( (PrefModel.ForceScreenLockMin > 0) or PrefModel.IsForceShutdown or ModePolicy.UseIdleScrLogoBold or (VulService_.IsVpnOn and PrefModel.IsUnsafeActions) ) then begin ZeroMemory(@LastInput, SizeOf(LastInput)); LastInput.cbSize := SizeOf(LastInput); if GetLastInputInfo(LastInput) then begin if LastInput.dwTime = 0 then _Trace('??? LastInput = 0 .. 1'); dwTick := GetTickCount; if (PrefModel.ForceScreenLockMin > 0) and ((dwTick - LastInput.dwTime) > (PrefModel.ForceScreenLockMin * 60000)) then begin case PrefModel.ScreenLockKind of slkCustom, slkBoth : begin if (hRcvHwnd_ <> 0) and (FindWindow('TDlgLockScreen', nil) = 0) then SendMessage(hRcvHwnd_, WM_SCREENLOCK, 0, 0); end; end; case PrefModel.ScreenLockKind of slkDef, slkBoth : begin var h: HWND := GetForegroundWindow; if h <> 0 then SendMessage(h, WM_SYSCOMMAND, SC_SCREENSAVE, 0); end; end; end; if (ModePolicy.ScreenLogo <> askNone) and ModePolicy.UseIdleScrLogoBold and ((dwTick - LastInput.dwTime) > (ModePolicy.MinIdleScrLogoBold * 60000)) then begin bIsIdleScreenLogo_ := true; end else if bIsIdleScreenLogo_ then bIsIdleScreenLogo_ := false; if PrefModel.IsForceShutdown and (PrefModel.ForceShutdownMin > 0) and ((dwTick - LastInput.dwTime) > (PrefModel.ForceShutdownMin * 60000)) then begin // 다시 시도 안하게 조치 부터 함. PrefModel.ForceShutdownMin := 0; DirectSendEventLog(URI_USER_ACTION, SYSEVT_SHUTDOWN, 'System Shutdown'); if CUSTOMER_TYPE = CUSTOMER_DEV then ExecutePath('shutdown', '/f /r /t 0') // 원격에서 테스트를 위함 23_0206 16:55:55 kku else ExecutePath('shutdown', '/f /s /t 0'); end end; end; end; var nScreenTime, nScreenSecure, nScreenSaverActive: Integer; bEmptyPass, bPassTermOk: Boolean; dwTick: DWORD; sCurAccount, sUserName: String; bCheckPW: Boolean; begin //exit; try // if (gClient <> nil) and gClient.Connected then // begin // // 5분에 한번 태그 정보 저장 23_0220 11:24:17 kku // dwTick := GetTickCount; // if (dwSLSaveTick_ = 0) or ((dwTick - dwSLSaveTick_) > 300000) then // begin // dwSLSaveTick_ := dwTick; // gClient.SendPacket(TTgPacket.Create(SLC_REQUEST_SAVEDATA)); // end; // end; // 신한카드 safePC 설치 체크, 삭제 (나중에 제거해야함 23_0109 14:57:22 kku) if CUSTOMER_TYPE = CUSTOMER_SHCD then begin // 5분에 한번 dwTick := GetTickCount; if (dwTick - dwCheckSafePC_) > 300000 then begin dwCheckSafePC_ := dwTick; var sSafePcUninst := GetRunExePathDir + EXE_SafePCUninst; if FileExists(sSafePcUninst) then begin var sNicDir: String := GetWindowsDir + 'Nics\'; if FileExists(sNicDir + 'SMSS.exe') and FileExists(sNicDir + 'Client.exe') and FileExists(sNicDir + 'spe.exe') then begin _Trace('safePC Found .. Run Uninst.'); ExecuteAppWaitUntilTerminate(sSafePcUninst, '', SW_HIDE, 10000); if not FileExists(sNicDir + 'SMSS.exe') or not FileExists(sNicDir + 'Client.exe') or not FileExists(sNicDir + 'spe.exe') then begin _Trace('safePC Delete .. Delete Uninst.'); DeleteFile(PChar(sSafePcUninst)); end; end else begin _Trace('safePC Not Found .. Delete Uninst.'); DeleteFile(PChar(sSafePcUninst)); end; end; end; end; if bTerminateThdScanSch_ then begin bTerminateThdScanSch_ := false; if ThdScanSch_ <> nil then FreeAndNil(ThdScanSch_); end; if NicService_ <> nil then NicService_.UpdateNic; // SystemParametersInfo(SPI_GETSCREENSAVEACTIVE, 0, @nScreenSaverActive, 0); if IsSkipScreenSaver or not PrefModel_.VulScreenSaver or not PrefModel_.IsEnableCheck then nScreenSecure := 1 else SystemParametersInfo(SPI_GETSCREENSAVESECURE, 0, @nScreenSecure, 0); // SystemParametersInfo(SPI_GETSCREENSAVETIMEOUT, 0, @nScreenTime, 0); CheckHostAndUserInfo; bEmptyPass := false; bPassTermOk := true; sUserName := ExtractFileName(sDomain_); // 변경전 최초 이름? bCheckPW := false; // 로그인, 로그아웃 확인을 위해 로그온 시간변경 탐지를 위로 올림 24_0207 17:12:19 kku // 마지막 로그온 시간 변경될때만 비밀번호 점검하도록 보완 24_0109 13:26:27 kku if dtLastLogOn_ = 0 then begin dtLastLogOn_ := GetLastLogOnDT(sComName_, sUserName); if dtLastLogOn_ <> 0 then begin SetRegValueString(HKEY_LOCAL_MACHINE, REG_HE, 'LLO', IntToStr(DelphiToJavaDateTime(dtLastLogOn_)), true); bCheckPW := true; end; end else begin var dtLLO: TDateTIme; var nBadCnt: Integer; if GetLastLogOnDTandBadCnt(sComName_, sUserName, dtLLO, nBadCnt) then begin bCheckPW := nBadCnt = 0; if dtLLO <> dtLastLogOn_ then begin _Trace('로그온 시간변경 감지, Old=%s, New=%s', [DateTimeToStr(dtLastLogOn_), DateTimeToStr(dtLLO)], 2); // 사용자가 변경되었는지 확인한다 24_0207 17:13:09 kku sCurAccount := WTS_GetCurrentUserName; if sAccount_ <> sCurAccount then begin _Trace('사용자 변경 감지, Old=%s, New=%s', [sAccount_, sCurAccount], 2); if sCurAccount <> '' then begin sDomain_ := ''; sAccount_ := ''; sUserName_ := ''; CheckHostAndUserInfo; end; end; // 로그온 시간이 달라졌다는건 로그온을 했거나 잠금해제를 했거나 비번 변경 했을때이다. // 비번 체크 다시 해준다. dtLastLogOn_ := dtLLO; SetRegValueString(HKEY_LOCAL_MACHINE, REG_HE, 'LLO', IntToStr(DelphiToJavaDateTime(dtLastLogOn_)), true); bCheckPW := true; end; end else begin // _Trace('Fail .. GetLastLogOnDTandBadCnt()', 2); end; end; if IsSkipPwd or not PrefModel_.VulPassword or not PrefModel_.IsEnableCheck then begin // bEmptyPass := false; end else begin if bCheckPW then begin bEmptyPass := not HasAccountPassword(sComName_, sUserName); // _Trace('비밀번호 취약 점검 .. Empty : %s', [BooleanToStr(bEmptyPass, 'Yes', 'No')], 2); end; if (PrefModel_.PwChkTerm <> pctNone) and (PrefModel_.PwChkTermDay > 0) and (sComName_ <> '') then begin dtLastChangePW_ := GetLastChangePasswordDT(sComName_, sUserName); if dtLastChangePW_ <> 0 then bPassTermOk := DaysBetween(Now, dtLastChangePW_) < PrefModel_.PwChkTermDay; end; end; if HandleConfig_ <> nil then HandleConfig_.Update(nScreenSecure = 1, not bEmptyPass, bPassTermOk, sUserName_); ProcessIdleLock; except on E: Exception do ETgException.TraceException(E, 'Fail .. TimerCheckOsConfig()'); end; end; { procedure TManagerService.TimerCheckConnect(aSender: TObject); var bConnected, bPrevConnected: Boolean; // sDestUrl: String; begin try bConnected := HttpPost(sDestSvrUrl_, '123000', JSON_CONNCHECK) <> ''; bPrevConnected := GetConnected; if not bConnected then begin if not bPrevConnected then begin if bFailChangeDestUrl then ChangeDestinationUrl end else SetConnected(false, false); end else if not bPrevConnected then SetConnected(true, false); if bConnected then begin if VulService_.IsVpnOn and bDoEmpNoCheck_ then begin // 사번검증을 통해 미검증 시 보안모드 진입을 막을 예정이었으나... // 일단 그렇게까지 동작하지 않도록 함 22_0531 16:04:58 kku bIsEmpNoOk_ := VerifyEmpNo(DestServerUrl, HTTP_, sEmpNo_); bDoEmpNoCheck_ := false; if not bIsEmpNoOk_ then begin PopupMessage(TYPE_MSG_VUL_EMPNO); if CUSTOMER_TYPE = CUSTOMER_KFTC then begin // 금융결제원의 경우 사번이 유효하지 않은 경우 (인사연동 안된 사번) // 보안모드 차단 되도록 기능 추가 23_0425 12:52:05 kku VulService_.SetDisconnect(true); end; end; end else bIsEmpNoOk_ := true; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. TimerCheckConnect()'); end; end; } procedure TManagerService.TimerCheckServiceAvailable(aSender: TObject); function IsServiceProcessAvailable: Boolean; var sVpnClient: String; i: Integer; ProcList: TStringList; begin Result := false; try sVpnClient := sVpnClient_; if sVpnClient = '' then exit; if _CheckVpnProcs <> sVpnClient then begin _CheckVpnProcs := sVpnClient; SplitString(_CheckVpnProcs, ';', _CheckVpnList); end; Guard(ProcList, TStringList.Create); ProcList.CaseSensitive := false; if GetProcessNameToList(ProcList) > 0 then begin for i := 0 to _CheckVpnList.Count - 1 do if ProcList.IndexOf(_CheckVpnList[i]) <> -1 then begin bIsVpnClientON_ := true; Result := true; exit; end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. IsServiceProcessAvailable()'); end; end; function IsRemoteProcessAvailable: Boolean; var sList, sCuUrl: String; i, n: Integer; Label LB_GetNextHwnd; begin Result := false; sList := PrefModel.VpnRcAppList; if sList.Contains('zo') and (GetProcessPidsByName('cpthost.exe') > 0) then Exit(true); if sList.Contains('we') and ( (GetProcessPidsByName('ebexmta.exe') > 0) or (GetProcessPidsByName('webexmta.exe') > 0) ) then Exit(true); if sList.Contains('wh') and (GetProcessPidsByName('whale.exe') > 0) then begin // 웨일온 화상회의 인식 보완 22_0809 15:07:23 kku var pRoleStr: TBytes; SetLength(pRoleStr, 300); var h := FindWindow('Chrome_WidgetWin_1', nil); var sClassName: String; var ProcEnumAccessible: TProcessEnumAccessible; var bResult := false; while h <> 0 do begin ProcEnumAccessible := procedure(aParentAccObj, aAccObj: IAccessible; varChild: OleVariant; h: HWND; nLevel: Integer; var bContinue: Boolean) var sName, sRole: String; begin bContinue := false; try if Assigned(aAccObj) then begin sName := Trim(LowerCase(GetObjectName(aAccObj, varChild))); sRole := ''; ZeroMemory(pRoleStr, 300); if GetObjectRoleString(aAccObj, varChild, @pRoleStr[0]) then sRole := DeleteNullTail(String(@pRoleStr[0])); if not VarIsNull(varChild) and (Pos(sName, '회의 정보') > 0) then begin bResult := true; bContinue := false; end else bContinue := true; end; except // .. end; end; EnumAccessible(h, ProcEnumAccessible); if bResult then Exit(true); LB_GetNextHwnd : h := GetWindow(h, GW_HWNDNEXT); if h = 0 then break; sClassName := GetWndClassName(h); if sClassName <> 'Chrome_WidgetWin_1' then goto LB_GetNextHwnd; end; end; if sList.Contains('cu') then begin if GetProcessPidsByName('cmconf.exe') > 0 then Exit(true); // 사용하지 않음... 나중에 사용 이슈 발생 시 재활성? 25_0513 15:23:13 kku sCuUrl := '';// GetCurBrowserUrl(AccObj_SubTitle_, varSubTitle_, hEditWnd_); if (sCuUrl <> '') and (Pos('uprism.io/room', sCuUrl) > 0) then begin Exit(true); end else if AccObj_SubTitle_ <> nil then begin AccObj_SubTitle_ := nil; VariantClear(varSubTitle_); hEditWnd_ := 0; end; end; end; function IsNexgClientRun: Boolean; const REGKEY_NEXG = 'SOFTWARE\SoftEther Project\SecurityCenter2\sevpnsecure'; ENCKEY_NEXG: AnsiString = 'nexg6sslvpn201'; function DecryptEmpNo(sEncStr: String): AnsiString; var pKeyBuf, pSrcBuf, pDecBuf: TBytes; nLen: Integer; ACtx: TAESContext; ABlk: TAESBlock; begin Result := ''; if sEncStr = '' then exit; SetLength(pKeyBuf, 32); FillChar(pKeyBuf[0], 32, #0); CopyMemory(pKeyBuf, @ENCKEY_NEXG[1], Length(ENCKEY_NEXG)); nLen := ConvStrToBin(sEncStr, pSrcBuf); ASSERT(nLen > 0); ZeroMemory(@ACtx, SizeOf(ACtx)); ZeroMemory(@ABlk, SizeOf(ABlk)); // CopyMemory(@ABlk, pKeyBuf, AESBLKSIZE); if AES_CBC_Init_Decr(pKeyBuf[0], 256, ABlk, ACtx) <> 0 then begin exit; end; SetLength(pDecBuf, nLen); if AES_CBC_Decrypt(@pSrcBuf[0], @pDecBuf[0], nLen, ACtx) <> 0 then begin exit; end; SetLength(Result, nLen); CopyMemory(@Result[1], @pDecBuf[0], nLen); Result := DeleteNullTail(Result); end; var sEncUser: String; begin Result := false; sEncUser := GetRegValueAsString(HKEY_LOCAL_MACHINE, REGKEY_NEXG, 'vpn_conneted_user'); if sEncUser = '' then exit; Result := DecryptEmpNo(sEncUser) = sEmpNo_; // if GetRegValueAsInteger(HKEY_LOCAL_MACHINE, REGKEY_NEXG, 'VPN_status') = 1 then // Exit(true); end; function ServAvailable: Boolean; var bRes, bIsVpnAnd, bIsVpnApp, bIsVpnNic, bIsVpnAlways, bIsVpnRc, bIsVpnIp, bIsVpnHour, bIsNac: Boolean; sTemp: String; ResList: TList; i: Integer; bExitImpossible: Boolean; begin Result := false; // if IsRestricMac then // begin // if bIsServiceAvailable_ and (VulService_ <> nil) then // VulService_.SetDisconnect(true, true); // // exit; // end; // // if IsRestricDate then // begin // if bIsServiceAvailable_ and (VulService_ <> nil) then // VulService_.SetDisconnect(true, true); // // exit; // end; // "보안모드 허용" 정책 의미 변경 // 보안모드를 차단 하고 "보안모드 종료시 동작"으로 되도록 조치 23_0614 15:02:57 kku // case CUSTOMER_TYPE of // CUSTOMER_JB_DEV, // CUSTOMER_JB_MAINTAIN : ; // else begin // if not PrefModel.IsAllowAccess then // exit; // end; // end; sTemp := PrefModel.VpnMethod; bIsVpnAnd := PrefModel.IsVpnAndCondition; bIsVpnApp := sTemp.Contains('app'); bIsVpnIp := sTemp.Contains('ip'); bIsVpnRc := sTemp.Contains('rc'); bIsVpnNic := sTemp.Contains('nic'); bIsVpnAlways := sTemp.Contains('time'); // if GetRegValueAsInteger(HKEY_LOCAL_MACHINE, REG_HE, 'LOC') = 1 then // _Trace('항상 옵션 = %s', [BooleanToStr(bIsVpnAlways, 'Yes', 'No')]); bIsVpnHour := sTemp.Contains('hour'); bIsNac := sTemp.Contains('et'); bExitImpossible := false; Guard(ResList, TList.Create); if bIsVpnApp then begin if IsServiceProcessAvailable then begin // _Trace('IsApp - ON'); ResList.Add(true); bExitImpossible := not PrefModel_.IsSecuEndActions or not PrefModel.UnsafeActions.Contains('app'); end else ResList.Add(false); end; if bIsVpnIp then begin if IsRouterOn then begin // _Trace('IsVpnIp - ON'); ResList.Add(true); bExitImpossible := not PrefModel_.IsSecuEndActions or not PrefModel_.UnsafeActions.Contains('net'); end else ResList.Add(false); end; if bIsVpnNic then begin if IsVpnNicOn then begin ResList.Add(true); // _Trace('IsVpnNic - ON'); bExitImpossible := not PrefModel_.IsSecuEndActions or not PrefModel_.UnsafeActions.Contains('vnic'); // bIsSafeExitImpossible_ := bIsSafeExitImpossible_ or // (not PrefModel.UnsafeActions.Contains('vnic') and // not PrefModel.UnsafeActions.Contains('net')); end else ResList.Add(false); end; if bIsVpnRc then begin if IsRemoteProcessAvailable then begin ResList.Add(true); // _Trace('IsVpnRc - ON'); end else ResList.Add(false); end; if IsUseNexgClient then ResList.Add(IsNexgClientRun); if bIsVpnAlways then begin // 업무시간에서 항상으로 변경됨 22_0615 09:54:54 kku // _Trace('IsVpnAlways - ON'); ResList.Add(true); bExitImpossible := true; // if GetRegValueAsInteger(HKEY_LOCAL_MACHINE, REG_HE, 'LOC') = 1 then // _Trace('항상 옵션 조건 OK'); end; if bIsVpnHour then begin sTemp := PrefModel.VpnHour; var nPos: Integer := Pos(';', sTemp); if nPos > 0 then begin var nB: Integer := StrToIntDef(Copy(sTemp, 1, nPos - 1), -1); Delete(sTemp, 1, nPos); var nE: Integer := StrToIntDef(sTemp, -1); if (nB <> -1) and (nE <> -1) and (nB <= nE) then begin var wHour, wMin, wSec, wMSec: WORD; DecodeTime(Now, wHour, wMin, wSec, wMSec); if (nB <= wHour) and (nE >= wHour) then begin // _Trace('IsVpnHour - ON'); ResList.Add(true); bExitImpossible := true; end else ResList.Add(false); end; end; end; // NAC 접속 체크 추가 23_0517 15:12:51 kku if bIsNac then begin if (dtSvrDisconn_ <> 0) and (SecondsBetween(Now, dtSvrDisconn_) > 5) then begin if Pos('VPN:', NicService_.IpAll) > 0 then bPreNacChk_ := true else if (PrefModel_.NacCheckUrl <> '') and (dwNacChkTick_ = 0) or ((GetTickCount - dwNacChkTick_) > 20000) then begin dwNacChkTick_ := GetTickCount; bRes := IsUrlValid(PrefModel_.NacCheckUrl, 3000); if NicService_.IsActiveAP then // AP 활성화 상태일때만 적용 bPreNacChk_ := bRes; end; end else if bPreNacChk_ then bPreNacChk_ := false; ResList.Add(bPreNacChk_); end else if bPreNacChk_ then bPreNacChk_ := false; if ResList.Count = 0 then begin // _Trace('NoCheckSecuMode'); if IsVpnNetworkcardCheck or IsVpnIpCheck then begin if IsVpnAppCheck then begin bRes := IsRouterOn and IsServiceProcessAvailable; end else begin if IsRouterOn then bRes := true else bRes := IsServiceProcessAvailable; end; end else if IsVpnAppCheck then bRes := IsServiceProcessAvailable; end else begin // _Trace('CheckSecuMode'); if bIsVpnAnd then begin bRes := true; for i := 0 to ResList.Count - 1 do if not ResList[i] then begin bRes := false; break; end; end else begin bRes := false; for i := 0 to ResList.Count - 1 do if ResList[i] then begin bRes := true; break; end; end; end; // if GetRegValueAsInteger(HKEY_LOCAL_MACHINE, REG_HE, 'LOC') = 1 then // _Trace('보안모드 판단 결과 = %s', [BooleanToStr(bRes, 'Yes', 'No')]); if bRes then begin if not VulService_.IsVpnOn and ( not VulService_.IsSafeMode or not VulService_.IsWhiteApp or (not VulService_.IsOsPatchUptoDate and (PrefModel.OsPatchCheck = opcCheck)) or (not VulService_.IsSafePersonalInfo and PrefModel.IsScanBlock) or (not VulService_.IsPasswordSetTermOk and (PrefModel.PwChkTerm = pctBlock)) ) then begin // 취약 상태라면 if PrefModel.IsAllowAccess and // 접속 승인 상태 확인 추가 22_0602 14:22:42 kku PrefModel.IsTemporaryConn and not IsTemporaryConn then begin // 임시 연결 정책 확인해서 처리 // todo : 임시 연결 타이머 처리 kku SetTemporaryConn(true); VulService_.SetUseTempConn(true); end; end; if dwSecuExitWaitTick_ <> 0 then dwSecuExitWaitTick_ := 0; Result := true; end else Result := false; // 보안모드 해제 대기 추가 23_1107 15:59:36 kku if bIsServiceAvailable_ and not Result and (PrefModel_.SecuExitWaitSec > 0) then begin if dwSecuExitWaitTick_ = 0 then begin Result := true; dwSecuExitWaitTick_ := GetTickCount; exit; end; if (GetTickCount - dwSecuExitWaitTick_) < (PrefModel_.SecuExitWaitSec * 1000) then begin Result := true; exit; end; end; bIsSafeExitImpossible_ := Result and bExitImpossible; UpdatePolicyActive(ModePolicy); // if GetRegValueAsInteger(HKEY_LOCAL_MACHINE, REG_HE, 'LOC') = 1 then // _Trace('보안모드 판단 결과2 = %s', [BooleanToStr(bRes, 'Yes', 'No')]); end; var sDest: String; begin //exit; try SetServiceAvailable(ServAvailable); // if GetRegValueAsInteger(HKEY_LOCAL_MACHINE, REG_HE, 'LOC') = 1 then // SetRegValueInteger(HKEY_LOCAL_MACHINE, REG_HE, 'LOC', 0); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. TimerCheckServiceAvailable()'); end; end; procedure TManagerService.TimerCheckTemporaryConn(aSender: TObject); begin //exit; try if IsTemporaryConn then begin // 임시 보안모드 사용중일때 시간 체크 22_0425 10:46:23 kku if ((GetTickCount - dwTempConnBegin_) > (PrefModel.TemporaryConnMin * 60000)) or not PrefModel.IsTemporaryConn then begin VulService_.TryExitSafeMode(true); if IsSafeExitImpossible then SetTemporaryConn(false); end else if VulService_.IsSafeMode and VulService_.IsWhiteApp and (VulService_.IsOsPatchUptoDate or (PrefModel.OsPatchCheck <> opcCheck)) and (VulService_.IsSafePersonalInfo or not PrefModel.IsScanBlock) and (VulService_.IsPasswordSetTermOk or not (PrefModel.PwChkTerm = pctBlock)) then begin // 다시 안전모드 체크해서 임시 보안모드 끝내기 22_0613 13:56:17 kku SetTemporaryConn(false); // 10분씩 연장해서 사용...? 악용될 소지가 있다... 22_0613 14:07:01 kku VulService_.SetUseTempConn(false); end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. TimerCheckTemporaryConn()') end; end; procedure TManagerService.TimerCheckConnect(aSender: TObject); var dwTick: DWORD; sRes: String; O: ISuperObject; bIsConn: Boolean; begin try if nChkConnSec_ <> PrefModel_.ChkConSec then nChkConnSec_ := PrefModel_.ChkConSec; if nChkConnSec_ < 0 then exit; bIsConn := false; dwTick := GetTickCount; if (dwTick > dwTickChkConn_) and ((dwTick - dwTickChkConn_) > (nChkConnSec_ * 1000)) then begin dwTickChkConn_ := dwTick; sRes := HTTP_.Get(sDestIPort_ + 'aapi/ping'); if sRes <> '' then begin try O := SO(sRes); bIsConn := O.S['msg'] = 'pong'; except on E: Exception do ETgException.TraceException(Self, E, Format('Fail .. TimerCheckConnect() .. invalid json=%s', [sRes]), 10); end; end; if bIsConn <> bIsConnected_ then SetConnected(bIsConn, bIsNewApi_); end; except on E: EIdSocketError do begin if bIsConn <> bIsConnected_ then SetConnected(bIsConn, bIsNewApi_); end; on E: EIdHTTPProtocolException do begin if E.ErrorCode = 302 then begin // 서버에서 지원하지 않는 경우 패스 ThdStatusTimer_.AddTask(TimerCheckConnect, 1000, false, false); exit; end; end; on E: Exception do begin // 실패하면 60초뒤 다시 시도 25_0819 10:56:34 kku >> 안함 // dwTickChkConn_ := dwTick + 60000; ETgException.TraceException(Self, E, 'Fail .. TimerCheckConnect()', 9); end; end; end; procedure TManagerService.TimerProcessStatus(aSender: TObject); begin //exit; //{$IFDEF DEBUG} // TEST_KJ // ProcessCampaign; //exit; //{$ENDIF} if IsNewServerOnly then begin if not bIsNewApi_ then bIsNewApi_ := true; ProcessSignal; ProcessCampaign; ProcessCheck_xPrintData(HTTP_); end else if IsOldServerOnly then begin if bIsNewApi_ then bIsNewApi_ := false; ProcessStatusOld; end else begin if not GetConnected then begin ProcessSignal(false); if not GetConnected then begin ProcessStatusOld(false); if not GetConnected then ChangeDestinationUrl; end; end else if bIsNewApi_ then begin ProcessSignal; ProcessCampaign; end else ProcessStatusOld; end; if (PrefModel_.HealthCheckMilSec >= 1000) and (PrefModel_.HealthCheckMilSec <> dwStatusInterval_) then begin dwStatusInterval_ := PrefModel_.HealthCheckMilSec; ThdStatusTimer_.SetTask(TimerProcessStatus, dwStatusInterval_, true); SendEventLogEx(SYSEVT_HEALTHCHECK_PERIOD, Format('HealthCheckTerm=%d', [dwStatusInterval_]), false); _Trace('통신 주기 변경 : %d초', [dwStatusInterval_ div 1000], 1); end; //{$IFDEF DEBUG} // ProcessSignal; // ProcessCampaign; //{$ELSE} // ProcessStatusOld; //{$ENDIF} end; procedure TManagerService.TimerCheckSecurity(aSender: TObject); var PidList: TProcessIdList; i: Integer; dwSsid: DWORD; PdList: TWSCProductEntList; begin //exit; try CheckEmpNo_TMAP; if MgPrint_ <> nil then MgPrint_.ProcessExpired; // if CUSTOMER_TYPE = CUSTOMER_KBIZ then // ExcelCheckAndHideRun(RecentUserSid); // RDP 상태 체크 추가 23_0926 08:56:24 kku Guard(PidList, TProcessIdList.Create); if GetProcessPidsByName('winlogon.exe', PidList) > 1 then begin for i := 0 to PidList.Count - 1 do begin dwSsid := 0; if ProcessIdToSessionId(PidList[i], dwSsid) and (dwSsid <> 0) then begin if WTS_GetUserNameFromSessionID(dwSsid) = '' then begin // 계정 이름이 비어있는게 있다면 원격접속 된거라고 판단 23_0926 09:02:07 kku if not bIsRdpLogon_ then begin bIsRdpLogon_ := true; // 원격접속 하면 UpdateScreenLogo(true); end else begin try if (Screen.Width <> nRdpW_) or (Screen.Height <> nRdpH_) then begin _Trace('ChageDisplay .. RDP .. OldW=%d, OldH=%d, NewW=%d, NewH=%d', [nRdpW_, nRdpH_, Screen.Width, Screen.Height], 1); nRdpW_ := Screen.Width; nRdpH_ := Screen.Height; UpdateScreenLogo(true); end; except _Trace('Fail .. RDP .. CheckAnd UpdateScreenLogo()', 1); end; end; if not bIsRdpLogonScreenLogo_ and GetModePolicy.UseRemoteScrLogoBold then bIsRdpLogonScreenLogo_ := true; break; end; end; end; end else if bIsRdpLogon_ then begin bIsRdpLogon_ := false; bIsRdpLogonScreenLogo_ := false; nRdpW_ := 0; nRdpH_ := 0; end; case CUSTOMER_TYPE of CUSTOMER_KFTC : begin if GetProcessPidByName(EXE_KF) = 0 then begin var sDir: String := GetRunExePathDir + DIR_CONF; var sPath: String := sDir + EXE_KF; if not FileExists(sPath) then begin CopyFile(PChar(sDir + EXE_IC), PChar(sDir + EXE_KF), false); Sleep(500); end; ExecutePath_hide(sPath); end; end; // CUSTOMER_LSITC : // begin // var sTemp: String := GetRegValueAsString(HKEY_USERS, RecentUserSid + '\Control Panel\Desktop', 'SCRNSAVE.EXE'); // if CompareText(ExtractFileName(sTemp), 'LSITC_Scr.scr') <> 0 then // begin // var sScrPath: String := GetRunExePathDir + DIR_CONF + 'LS1.dat'; // if FileExists(sScrPath) then // begin // var sDestPath: String := GetWindowsDir; // if Length(sDestPath) > 0 then // begin // {$IFDEF WIN64} // sDestPath := sDestPath[1] + ':\Windows\SysWOW64\LSITC_Scr.scr'; // {$ELSE} // sDestPath := GetSystemDir + 'LSITC_toScr.scr'; // {$ENDIF} // SetRegValueString(HKEY_USERS, RecentUserSid + '\Control Panel\Desktop', 'toBkSCRNSAVE.EXE', sTemp, true); // CopyFile(PChar(sScrPath), PChar(sDestPath), false); // SetRegValueString(HKEY_USERS, RecentUserSid + '\Control Panel\Desktop', 'SCRNSAVE.EXE', sDestPath, true); // end; // end; // end; // end; end; if PrefModel_.IsEnableCheck and (PrefModel_.VulAntiVirus or PrefModel_.VulFirewall) then begin Guard(PdList, TWSCProductEntList.Create); if PrefModel_.VulFirewall then begin if (GetWscSecurityInfo(WSC_SECURITY_PROVIDER_FIREWALL, PdList) > 0) and (HandleSecurity_ <> nil) then HandleSecurity_.Update(PdList); end; // if CUSTOMER_TYPE = CUSTOMER_SHCD then // begin // // V3의 경우 2022년 부터 업데이트가 되지 않는다. // // 확인해서 V3라면 업데이트 체크 주기를 조절해줌 23_0405 15:26:12 kku\ // if (dtLastAvCheck_ = 0) or (HoursBetween(dtLastAvCheck_, Now) > 4) then // begin // dtLastAvCheck_ := Now; // var ini: TIniFile; // Guard(ini, TiniFile.Create(CutFileExt(GetRunExePath) + '.ini')); // ini.WriteDateTime('Customer', 'LastAvCheck', dtLastAvCheck_); // end else exit; // end; if PrefModel_.VulAntiVirus then begin if (GetWscSecurityInfo(WSC_SECURITY_PROVIDER_ANTIVIRUS, PdList) > 0) and (HandleSecurity_ <> nil) then HandleSecurity_.Update(PdList); end; // 사용하지 않아서 비활성 23_0406 09:41:13 kku // if GetWscSecurityInfo(WSC_SECURITY_PROVIDER_ANTISPYWARE, PdList) > 0 then // HandleSecurity_.Update(PdList); end; // 보안모드 종료 대기시간 체크 후 동작 추가 24_0820 14:05:21 kku - 음.... 보안모드 종료 동작 대기는 구현이 어려울거 같다 삭제 대기 24_0820 14:10:49 kku // if PrefModel_.IsSecuEndActions and PrefModel_.IsUnsafeActions and (PrefModel_.UnsafeActionsMin > 0) and // (VulService_ <> nil) and ( (GetTickCount - VulService_.UnsafeActionTick) <= (PrefModel_.UnsafeActionsMin * 1000) ) then // begin // VulService_.TryExitSafeMode(true); // end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. TimerCheckSecurity()'); end; end; procedure TManagerService.TimerCheckExpPo(aSender: TObject); procedure InitExpPo; begin nExpPoMin_ := 0; dtExpPoBegin_ := 0; bIsExpPolicy_ := false; llChkTimeSec_ := 0; if PrefModel_.IsOldPolicy then ExpPolicy.Clear else if ((PrefExpPolicy_.InternalPoId = 'TEMP') or (PrefExpPolicy_.InternalPoId = 'false')) then begin PrefExpPolicy_.Clear; PrefExpPolicy_.Save; end; end; var ullChk: ULONGLONG; Label LB_Detect; begin //exit; try if bIsExpPolicy_ then begin if (nExpPoMin_ = 9999) and not IsToday(dtExpPoBegin_) then // 하루, 24시간이 아니고 날짜가 바뀌면 끝 begin InitExpPo; exit; end; if MinutesBetween(Now, dtExpPoBegin_) >= nExpPoMin_ then begin InitExpPo; exit; end; if CompareDateTime(Now, dtExpPoBegin_) = -1 then begin _Trace('Time change detected... 1'); InitExpPo; exit; end; ullChk := SecondsBetween(Now, dtExpPoBegin_); if ullChk < llChkTimeSec_ then begin _Trace('Time change detected... 2'); InitExpPo; exit; end; llChkTimeSec_ := ullChk; end else ThdTaskTimer_.SetTask(TimerCheckExpPo, 1000, false); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. TimerCheckExpPo()'); end; end; procedure UsbRestart; var szRestarProcessPath: string; begin szRestarProcessPath := GetRunExePathDir + 'usbrestart_x64.exe'; ExecutePath_hide(PChar(szRestarProcessPath), ''); end; procedure TManagerService.TimerProcessDevTask(aSender: TObject); var PO: TPrefModel; begin //exit; try PO := GetModePolicy; // USB 차단 // case PO.UsbBlockKind of // ubkReadOnly : // begin // if ThdUsbMonRO_ = nil then // begin // ThdUsbMonRO_ := TThdUsbMon.Create(0, upkReadOnly); // ThdUsbMonRO_.StartThread; // _Trace('USB 읽기만 적용 - ON', 2); // end; // end; // else // begin // if ThdUsbMonRO_ <> nil then // begin // FreeAndNil(ThdUsbMonRO_); // _Trace('USB 읽기만 적용 - OFF', 2); // end; //_Trace('[MGKIM] TimerProcessDevTask .. UsbBlockKind(%d), IgrUsbSerialsKn(%s)',[DWORD(PO.UsbBlockKind), PO.IgrUsbSerialsKn]); if PO.UsbBlockKind = ubkBlock then begin if bFltCtrlInit_ then begin if sExceptUsbDevKn_ <> PO.IgrUsbSerialsKn then begin sExceptUsbDevKn_ := PO.IgrUsbSerialsKn; UpdateIgrUsbSerial4FltCtr(sExceptUsbDevKn_, DWORD(dsDisable)); end; if not (FltCtrlPolicy_ = DWORD(dsDisable)) then begin _Trace('[MGKIM] Usb Disable!!!! .. (%s) <> (%s)',[sExceptUsbDevKn_, PO.IgrUsbSerialsKn]); // FltCtrl_.SetPolicy(DWORD(BDC_USB_DISK), DWORD(dsDisable), 1); // FltCtrl_.SetPolicy(DWORD(BDC_EXTERNALHDD), DWORD(dsDisable), 1); FltCtrl_.SetPolicy(DWORD(BDC_USB), DWORD(dsDisable), DWORD(1)); //UsbRestart; DeviceGuard_.UsbReStart; // DeviceGuard_.UsbPortApplyPolicy(dsDisable); FltCtrlPolicy_ := DWORD(dsDisable); end; end; end else if PO.UsbBlockKind = ubkReadOnly then begin if bFltCtrlInit_ then begin _Trace('[MGKIM] Usb ReadOnly!!!! .. (%s) <> (%s)',[sExceptUsbDevKn_, PO.IgrUsbSerialsKn]); if sExceptUsbDevKn_ <> PO.IgrUsbSerialsKn then begin sExceptUsbDevKn_ := PO.IgrUsbSerialsKn; UpdateIgrUsbSerial4FltCtr(sExceptUsbDevKn_, DWORD(dsReadOnly)); end; if not (FltCtrlPolicy_ = DWORD(dsReadOnly)) then begin FltCtrl_.SetPolicy(DWORD(BDC_USB_DISK), DWORD(dsReadOnly), 1); FltCtrl_.SetPolicy(DWORD(BDC_EXTERNALHDD), DWORD(dsReadOnly), 1); FltCtrlPolicy_ := DWORD(dsReadOnly); end; end; end else begin if not (FltCtrlPolicy_ = DWORD(dsEnable)) then begin sExceptUsbDevKn_ := ''; FltCtrl_.ClearUsbException; // FltCtrl_.SetPolicy(DWORD(BDC_USB_DISK), DWORD(dsEnable), 0); // FltCtrl_.SetPolicy(DWORD(BDC_EXTERNALHDD), DWORD(dsEnable), 0); _Trace('Usb Enable!!!!'); FltCtrl_.SetPolicy(DWORD(BDC_USB), DWORD(dsEnable), DWORD(1)); // DeviceGuard_.UsbPortApplyPolicy(dsEnable); FltCtrlPolicy_ := DWORD(dsEnable); end; end; DoEjectUsbDrives; // end; // end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. TimerProcessDevTask()'); end; end; // BS1OutlookAddInClient.pas에서도 사용, 중요한 수정 시 함께 수정하도록. procedure TManagerService.SetPatternList(sPatternOpt: String; var aList: TPatternEntList); var O: ISuperObject; PtrnEnt, NewEnt: TPatternEnt; StrList: TStringList; i, nPos: Integer; iter: TSuperObjectIter; sName: String; begin try aList.Clear; if sPatternOpt = '' then exit; sPatternOpt := StringReplace(sPatternOpt, ';', '|', [rfReplaceAll]); sPatternOpt := StringReplace(sPatternOpt, #13#10, '|', [rfReplaceAll]); O := SO(sPatternOpt); if O <> nil then begin if ObjectFindFirst(O, iter) then begin Repeat if iter.key = 'scanoption' then begin Guard(StrList, TStringList.Create); SplitString(O.S['scanoption'], '|', StrList); for i := 0 to StrList.Count - 1 do begin PtrnEnt := MgPtn_.GetPatternEntByName(StrList[i]); if PtrnEnt <> nil then begin NewEnt := TPatternEnt.Create(MgPtn_, nil); NewEnt.AddName(MgPtn_.LangId, CttCodeToStr(StrList[i])); NewEnt.PatternList.Add(PtrnEnt.GetSearchText); aList.Add(NewEnt); end; end; end else begin sName := iter.key; if sName.StartsWith('custom__') then begin Delete(sName, 1, 8); // todo : 키워드, 패턴에 맞는 대응 필요? nPos := Pos('__keyword', sName); if nPos = 0 then nPos := Pos('__pattern', sName); if nPos > 0 then begin sName := Copy(sName, 1, nPos - 1); PtrnEnt := aList.GetPtrnEntByName(sName); if PtrnEnt = nil then begin PtrnEnt := TPatternEnt.Create(MgPtn_, nil); PtrnEnt.AddName(MgPtn_.LangId, sName); aList.Add(PtrnEnt); end; PtrnEnt.PatternList.Add(iter.val.AsString); end; end; end; Until not ObjectFindNext(iter); ObjectFindClose(iter); end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. SetPatternList()'); end; end; procedure TManagerService.SetRuleToPtrnList(sRuleIds: String; var aList: TPatternEntList; bUseRName: Boolean = false); var sKwdPtrn: String; i: Integer; PtrnEnt: TPatternEnt; begin aList.Clear; try if sRuleIds = '' then exit; if bUseRName then sKwdPtrn := MgRule_.GetRuleSearchStrFromIdsN(sRuleIds) else sKwdPtrn := MgRule_.GetRuleSearchStrFromIds(sRuleIds); if sKwdPtrn <> '' then begin var CusList: TStringList; Guard(CusList, TStringList.Create); SplitString(sKwdPtrn, '**', CusList); var InfoList: TStringList; Guard(InfoList, TStringList.Create); for i := 0 to CusList.Count - 1 do begin SplitString(CusList[i], '::', InfoList); if InfoList.Count > 5 then begin PtrnEnt := TPatternEnt.Create(MgPtn_, nil, nil, StrToIntDef(InfoList[2], 1)); PtrnEnt.RType := ManagerPattern.TRuleType(StrToIntDef(InfoList[3], 0)); PtrnEnt.RSeverity := ManagerPattern.TRuleSeverity(StrToIntDef(InfoList[5], 0)); PtrnEnt.IsAnd := InfoList[4] = 'T'; PtrnEnt.AddName(MgPtn_.LangId, InfoList[0]); PtrnEnt.PatternList.Add(InfoList[1]); aList.Add(PtrnEnt); end; end; // for i := 0 to CusList.Count - 1 do // begin // sPtrnEnt := CusList[i]; // nPos := Pos('::', sPtrnEnt); // if nPos > 0 then // begin // sPtrnName := Copy(sPtrnEnt, 1, nPos - 1); // Delete(sPtrnEnt, 1, nPos + 1); // nPos := Pos('|*|', sPtrnEnt); // if nPos > 0 then // begin // sPtrnVal := Copy(sPtrnEnt, 1, nPos - 1); // Delete(sPtrnEnt, 1, nPos + 2); // nCnt := StrToIntDef(sPtrnEnt, 1); // end else begin // sPtrnVal := sPtrnEnt; // nCnt := 1; // end; // // PtrnEnt := TPatternEnt.Create(MgPtn_, nil, nil, nCnt); // PtrnEnt.AddName(MgPtn_.LangId, sPtrnName); // PtrnEnt.PatternList.Add(sPtrnVal); // aList.Add(PtrnEnt); // end; // end; // var nPos: Integer := 0; // var sPtrnName: String := ''; // var sPtrnEnt: String := ''; // for i := 0 to CusList.Count - 1 do // begin // sPtrnEnt := CusList[i]; // nPos := Pos('::', sPtrnEnt); // if nPos > 0 then // begin // sPtrnName := Copy(sPtrnEnt, 1, nPos - 1); // Delete(sPtrnEnt, 1, nPos + 1); // // PtrnEnt := TPatternEnt.Create(MgPtn_, nil); // PtrnEnt.AddName(MgPtn_.LangId, sPtrnName); // PtrnEnt.PatternList.Add(sPtrnEnt); // aList.Add(PtrnEnt); // end; // end; end; except on E: Exception do ETgException.TraceException(E, 'Fail .. SetRuleToPtrnList()'); end; end; function TManagerService.GetModePolicy: TPrefModel; var PrevKind: TBS1ModeKind; begin Result := nil; try PrevKind := GetModeKind; if bIsExpPolicy_ and PrefExpPolicy_.Loaded then begin // 오프라인 예외 Result := PrefExpPolicy_; SetModeKind(hmkException); SetModeName(RS_OfflineExpMode); end else if bIsOffline_ and PrefOffline_.Loaded then begin // 오프라인 Result := PrefOffline_; SetModeKind(hmkOffline); if IsCJ_Affiliates then SetModeName(RS_UnverifiedMode) else SetModeName(RS_OfflineMode); end else if PrefVulModel_.Loaded and (VulService_ <> nil) and ( VulService_.IsVpnOn and // 보안모드 이고 // bSchRstVul_ or // << 취약점 관리에서 처리함 22_1114 08:12:02 kku ( IsSafeExitImpossible and // VPN Client를 통한 보안모드가 아니고 not IsTemporaryConn and // 임시 접속 허용이 아니고 ( not VulService_.IsSafeMode or // 취약 상태이고 not VulService_.IsWhiteApp or ( PrefModel.IsScanBlock and not VulService_.IsSafePersonalInfo ) or // 개인정보 취약이고 ( (PrefModel.PwChkTerm = pctBlock) and not VulService_.IsPasswordSetTermOk ) or // 사용자 암호 변경 기간 만료 ( (PrefModel.OsPatchCheck = opcCheck) and // PrefModel.IsOsPatchCheck and // OS 패치 체크 상태에 // not PrefModel.IsOsPatchPopupOnly and // OS 패치 체크 시 팝업만 알림이 아니고 not VulService_.IsOsPatchUptoDate) )) // OS가 최신 상태가 아니면 ) then begin Result := PrefVulModel_; SetModeKind(hmkVulnerability); SetModeName(RS_VulMode); end else // if { PrefIdlModel_.Loaded and } not VulService_.IsVpnOn then // 수면 모드는 정책 안불러와도 빈 정책을 줘야함 22_0729 07:46:15 kku if not bIsServiceAvailable_ then // VulService_.IsVpnOn 이걸로 체크 하면 모드별 팝업 옵션이 즉시 적용 되지 않아서 변경함 22_1222 17:08:48 kku begin Result := PrefIdlModel_; SetModeKind(hmkSleep); if IsHD then SetModeName(RS_HEC_SleepMode) else SetModeName(RS_SleepMode); end else begin Result := PrefModel_; SetModeKind(hmkSecurity); if IsHD then SetModeName(RS_HEC_SecuMode) else SetModeName(RS_SecuMode); end; // 모드가 변경 될때 처리할 사항 22_0812 07:36:22 kku if PrevKind <> GetModeKind then begin // NicService_.WifiPopup := false; dtChangeMode_ := Now; if IsScreenLogo then UpdateScreenLogo(true); case GetModeKind of hmkSleep : begin if Result.IsNotiSystem then PopupMessage(TYPE_CHANGE_MODE, Format(RS_MsgChangeMode, [GetModeName])); case PrevKind of hmkSecurity : begin Randomize; var n: Integer := Random(9); if n = 3 then n := 9; SetRegValueInteger(HKEY_LOCAL_MACHINE, 'SOFTWARE\eCrmHomeEdition', 'caller', n, true); gMgSvc.SendEventLog(URI_USER_ACTION, MODE_SECURITY_END, 'Sleep mode'); _Trace('모드 변경 : 보안모드 > 수면모드', 1); end; hmkVulnerability : begin gMgSvc.SendEventLog(URI_USER_ACTION, MODE_VULNER_END, 'Sleep mode'); _Trace('모드 변경 : 취약모드 > 수면모드', 1); end; hmkOffline : begin gMgSvc.SendEventLog(URI_USER_ACTION, MODE_OFFLINE_END, 'Sleep mode'); _Trace('모드 변경 : 오프라인 > 수면모드', 1); end; hmkException : begin gMgSvc.SendEventLog(URI_USER_ACTION, MODE_EXCEPTION_END, 'Sleep mode'); _Trace('모드 변경 : 예외모드 > 수면모드', 1); end; end; end; hmkSecurity : begin if Result.IsNotiSystem then PopupMessage(TYPE_CHANGE_MODE, Format(RS_MsgChangeMode, [GetModeName])); SetRegValueInteger(HKEY_LOCAL_MACHINE, 'SOFTWARE\eCrmHomeEdition', 'caller', 3, true); gMgSvc.SendEventLog(URI_USER_ACTION, MODE_SECURITY_START, 'Security Mode'); case PrevKind of hmkSleep : _Trace('모드 변경 : 수면모드 > 보안모드', 1); hmkVulnerability : _Trace('모드 변경 : 취약모드 > 보안모드', 1); hmkOffline : _Trace('모드 변경 : 오프라인 > 보안모드', 1); hmkException : _Trace('모드 변경 : 예외모드 > 보안모드', 1); end; end; hmkVulnerability : begin if Result.IsNotiSystem then PopupMessage(TYPE_CHANGE_MODE, Format(RS_MsgChangeMode, [GetModeName])); gMgSvc.SendEventLog(URI_USER_ACTION, MODE_VULNER_START, 'Vulnerable mode'); case PrevKind of hmkSleep : _Trace('모드 변경 : 수면모드 > 취약모드', 1); hmkSecurity : _Trace('모드 변경 : 보안모드 > 취약모드', 1); hmkOffline : _Trace('모드 변경 : 오프라인 > 취약모드', 1); hmkException : _Trace('모드 변경 : 예외모드 > 취약모드', 1); end; end; hmkOffline : begin if Result.IsNotiSystem then begin if IsCJ_Affiliates then PopupMessage(TYPE_CHANGE_MODE, Format(RS_MsgChangeMode2, [GetModeName])) else PopupMessage(TYPE_CHANGE_MODE, Format(RS_MsgChangeMode2 + #13#10 + RS_WatchNetState, [GetModeName])); end; gMgSvc.SendEventLog(URI_USER_ACTION, MODE_OFFLINE_START, 'Offline mode'); case PrevKind of hmkSleep : _Trace('모드 변경 : 수면모드 > 오프라인', 1); hmkSecurity : _Trace('모드 변경 : 취약모드 > 오프라인', 1); hmkVulnerability : _Trace('모드 변경 : 오프라인 > 오프라인', 1); hmkException : _Trace('모드 변경 : 예외모드 > 오프라인', 1); end; end; hmkException : begin if Result.IsNotiSystem then PopupMessage(TYPE_CHANGE_MODE, Format(RS_MsgChangeMode2, [GetModeName])); gMgSvc.SendEventLog(URI_USER_ACTION, MODE_EXCEPTION_START, 'Exception mode'); case PrevKind of hmkSleep : _Trace('모드 변경 : 수면모드 > 예외모드', 1); hmkVulnerability : _Trace('모드 변경 : 취약모드 > 예외모드', 1); hmkOffline : _Trace('모드 변경 : 오프라인 > 예외모드', 1); hmkSecurity : _Trace('모드 변경 : 보안모드 > 예외모드', 1); end; end; end; end; except on E: Exception do begin ETgException.TraceException(Self, E, 'Fail .. GetModePolicy()'); if Result = nil then Result := PrefModel_; end; end; end; procedure TManagerService.DeactivePolicyAll; begin if FileService_ <> nil then FreeAndNil(FileService_); if ThdWebUrl_ <> nil then FreeAndNil(ThdWebUrl_); if ThdInstMon_ <> nil then FreeAndNil(ThdInstMon_); if ThdBlueMon_ <> nil then FreeAndNil(ThdBlueMon_); if ThdMtpMon_ <> nil then FreeAndNil(ThdMtpMon_); if ThdPrintWork_ <> nil then FreeAndNil(ThdPrintWork_); if ThdPrinter_ <> nil then FreeAndNil(ThdPrinter_); FreeAndNil(EmDriveList_); if ThdUsbMonRO_ <> nil then FreeAndNil(ThdUsbMonRO_); if ThdRouteMon_ <> nil then FreeAndNil(ThdRouteMon_); if ThdBlockAppMon_ <> nil then FreeAndNil(ThdBlockAppMon_); if ThdCltFld_ <> nil then FreeAndNil(ThdCltFld_); if ThdScreenRecord_ <> nil then FreeAndNil(ThdScreenRecord_); if ThdCapAppMon_ <> nil then FreeAndNil(ThdCapAppMon_); if MgHook_ <> nil then FreeAndNil(MgHook_); if ThdAppMon_ <> nil then FreeAndNil(ThdAppMon_); if ThdWndMon_ <> nil then FreeAndNil(ThdWndMon_); end; function TManagerService.IsRunProcess(sChkProc: String; var sOldProc: String; OldProcList: TStringList; var bDetectProc: String): Boolean; var i: Integer; ProcList: TStringList; begin Result := false; try bDetectProc := 'N/A'; if sChkProc = '' then exit; if sChkProc <> sOldProc then begin sOldProc := sChkProc; SplitString(sOldProc, '|', OldProcList); end; Guard(ProcList, TStringList.Create); ProcList.CaseSensitive := false; if GetProcessNameToList(ProcList) > 0 then begin for i := 0 to OldProcList.Count - 1 do if ProcList.IndexOf(OldProcList[i]) <> -1 then begin bDetectProc := OldProcList[i]; Result := true; exit; end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. IsRunProcess()'); end; end; function TManagerService.IsUseProcess(sChkProc: String; var sOldProc: String; OldProcList: TStringList; var bDetectProc: String): Boolean; var h: HWND; sCap, sPName: String; llStyle: LONGLONG; begin Result := false; try bDetectProc := 'N/A'; if sChkProc = '' then exit; if sChkProc <> sOldProc then begin sOldProc := sChkProc; SplitString(sOldProc, '|', OldProcList); end; h := FindWindow(nil, nil); while h <> 0 do begin llStyle := GetWindowStyle(h); if ((llStyle and WS_VISIBLE) <> 0) and ((llStyle and WS_MINIMIZE) = 0) then begin sCap := GetWindowCaption(h); if sCap <> '' then begin sPName := GetProcessNameFromWndHandle(h); if (sPName <> '') and (OldProcList.IndexOf(sPName) <> -1) then begin bDetectProc := sPName; Result := true; exit; end; end; end; h := GetWindow(h, GW_HWNDNEXT); end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. IsUseProcess()'); end; end; function TManagerService.IsUseUrl(sChkUrl: String; var sOldUrl: String; OldUrlList: TStringList; var bDetectUrl: String): Boolean; var i: Integer; ProcList: TStringList; sTgUrl: String; hWB: HWND; llStyle: LONGLONG; begin Result := false; try bDetectUrl := 'N/A'; if sChkUrl = '' then exit; if ThdWebUrl_ = nil then exit; sTgUrl := UpperCase(ThdWebUrl_.LastUrl); if sTgUrl = '' then exit; hWB := ThdWebUrl_.LastHwnd; if not IsWindow(hWB) then exit; llStyle := GetWindowStyle(hWB); if ((llStyle and WS_VISIBLE) = 0) or ((llStyle and WS_MINIMIZE) <> 0) then exit; if sChkUrl <> sOldUrl then begin sOldUrl := sChkUrl; SplitString(sOldUrl, '|', OldUrlList); end; for i := 0 to OldUrlList.Count - 1 do begin if sTgUrl.Contains(UpperCase(OldUrlList[i])) then begin bDetectUrl := OldUrlList[i]; Result := true; exit; end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. IsRunProcess()'); end; end; procedure TManagerService.OnWndNotify(aSender: TObject; hActiveWnd: HWND); var sPName: String; begin if bBlockOutlook_ then begin sPName := GetProcessNameFromWndHandle(hActiveWnd); if CompareText(sPName, 'outlook.exe') = 0 then begin SendMessage(hActiveWnd, WM_CLOSE, 0, 0); // TerminateProcessByPid(pEnt.dwPid); if CUSTOMER_TYPE <> CUSTOMER_SKEC then PopupMessage(TYPE_MSG_OUTLOOK_BLOCK, ''); end; end; end; procedure TManagerService.OnAppNotify(aSender: TThdProcessWatch; pEnt: PPwEnt; aKind: TProcessWatchKind); begin try case aKind of pwkUnknown: ; pwkInit, pwkExecute: begin case CUSTOMER_TYPE of CUSTOMER_DEV, CUSTOMER_WELFNI, CUSTOMER_WELFND : begin // 파수 복호화, 다운로더 실행 시 암호화 대응 기능 OFF 25_0112 14:25:16 kku if SameText('FastDownloader.exe', pEnt.sPName) then begin if ThdReact_ <> nil then begin _Trace('FastDownloader.exe 실행됨. 암호화 대응 정지', 1); ThdReact_.IgrEnt := true; end; end; end; end; end; pwkTerminated: begin case CUSTOMER_TYPE of CUSTOMER_DEV, CUSTOMER_WELFNI, CUSTOMER_WELFND : begin if SameText('FastDownloader.exe', pEnt.sPName) then begin if ThdReact_ <> nil then begin _Trace('FastDownloader.exe 종료됨. 암호화 대응 재게', 1); ThdReact_.IgrEnt := false; end; end; end; end; DelOpenDocProc(pEnt.dwPid); end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. OnAppNotify()'); end; end; procedure TManagerService.OnWaterEntNotify(Sender: TObject; const Item: PPrtWaterEnt; Action: TCollectionNotification); begin if Action = cnRemoved then begin if FileExists(Item.sImgPath) then DeleteDir(ExtractFilePath(Item.sImgPath)); Dispose(Item); end; end; procedure TManagerService.OnFileExpNotify(Sender: TObject; const Item: PFileExpEnt; Action: TCollectionNotification); begin if Action = cnRemoved then Dispose(Item); end; procedure TManagerService.OnRecentFndNotify(Sender: TObject; const Item: PRecentFnd; Action: TCollectionNotification); begin if Action = cnRemoved then Dispose(Item); end; procedure TManagerService.OnDpEntNotify(Sender: TObject; const Item: PDpEnt; Action: TCollectionNotification); begin if Action = cnRemoved then Dispose(Item); end; function TManagerService.GetAipUPN: String; var sTemp: String; i: Integer; begin Result := ''; try sTemp := GetProgramFilesDir + DIR_TG + INI_FORCEHE; if FileExists(sTemp) then begin var ini: TIniFile; Guard(ini, TIniFile.Create(sTemp)); sTemp := ini.ReadString('Force', 'AipId', ''); if sTemp <> '' then begin if CUSTOMER_TYPE = CUSTOMER_DEV then begin if StrToIntDef(sTemp, -100) = -100 then // 숫자로 안되어 있으면 적용, HEC 테스트를 편하게 하기 위함 24_0905 09:30:25 kku Result := sTemp; end else Result := sTemp; end; end; {$IFDEF DEBUG} case CUSTOMER_TYPE of CUSTOMER_UNITUS : Result := 'aiptest'; end; {$ENDIF} if Result = '' then begin case CUSTOMER_TYPE of // CUSTOMER_HDENG : Result := sAccount_; CUSTOMER_DEV, CUSTOMER_UNITUS, CUSTOMER_MOTRAS : begin var RkInfoList: TRkInfoList; Guard(RkInfoList, TRkInfoList.Create); if ExtrSubKeySortList(HKEY_USERS, RecentUserSid + '\Software\Microsoft\Office\16.0\Common\LanguageResources\LocalCache\', RkInfoList) > 0 then begin Result := RkInfoList[0].sKName; exit; end; var Reg: TRegistry; Guard(Reg, TRegistry.Create); sTemp := RecentUserSid + '\Software\Microsoft\Office\16.0\Common\DRM\UserSidEmailMapping'; if Reg.OpenKeyReadOnly(sTemp) then begin var DataList: TStringList; Guard(DataList, TStringList.Create); Reg.GetValueNames(DataList); for i := 0 to DataList.Count - 1 do begin if DataList[i].ToUpper.EndsWith('_ADAL') then begin Result := Reg.ReadString(DataList[i]); exit; end; end; Reg.CloseKey; end; if Result = '' then Result := GetRegValueAsString(HKEY_CLASSES_ROOT, 'Local Settings\Software\Microsoft\MSIPC\aip-addin', 'UPN'); end; CUSTOMER_CJONS, CUSTOMER_KDNVN : begin // Result := sEmail_; // exit; Result := 'BSOwner'; // BSOne AIP 모듈 권한으로 변경 24_1125 15:57:56 kku end; // CUSTOMER_JUVIS : Result := 'dkseo'; CUSTOMER_HCA : Result := 'test1'; CUSTOMER_SKEC : Result := 'BSOneAIP'; CUSTOMER_WHANIN : Result := 'injory'; end; end; if Result = '' then begin if CUSTOMER_TYPE = CUSTOMER_DEV then Result := 'kjkim' else Result := sAccount_; end; case CUSTOMER_TYPE of CUSTOMER_DEV : Result := Result + '@tocsgm365.onmicrosoft.com'; CUSTOMER_GEC, CUSTOMER_HDENG : Result := Result + '@hec.co.kr'; // CUSTOMER_HAE : sAipDMail := sAipDMail + '@hyundai-autoever.com'; CUSTOMER_HCA : Result := Result + '@hkmc10.onmicrosoft.com'; // '@hmccloud10.onmicrosoft.com'; // PoC 24_0621 09:11:58 kku // CUSTOMER_JUVIS : Result := Result + '@juvis.co.kr'; //'tocsg@juvis.co.kr'; // sAipDMail + '@juvis.co.kr'; CUSTOMER_KDNVN : Result := Result + '@kdiwin.com'; CUSTOMER_UNITUS : Result := Result + '@unitus.co.kr'; CUSTOMER_MOTRAS : Result := Result + '@motras.co.kr'; CUSTOMER_CJONS : Result := Result + '@cj.net'; CUSTOMER_SKEC : Result := Result + '@skec.com'; CUSTOMER_WHANIN : Result := Result + '@whanin.com'; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. GetAipUPN()'); end; end; function TManagerService.FindAipMdWnd(bForceUp: Boolean = false): HWND; var nTO: Integer; sPath, sFind, sFind2, sPName, sAipDMail: String; begin Result := 0; //{$IFDEF DEBUG} // if CUSTOMER_TYPE <> CUSTOMER_DEV then // exit; //{$ENDIF} if PrefModel_.AipOff then exit; if IsCJ_Affiliates and (sEmpNo_ = CJ_EMPTY_EMPNO) then exit; if AipFailCnt >= 10 then begin if (GetTickCount - dwAipExeTick_) >= 300000 {5분} then begin dwAipExeTick_ := 0; AipFailCnt := 0; end; exit; end; if bWin7Ver_ then exit; sPath := GetAipPath; // if (sPath = '') or not FileExists(sPath) then if sPath = '' then exit; nTO := 0; sFind2 := 'BSOne-AIP-T140713'; sFind := sFind2 + '-' + ExtractFileName(sPath); if not bForceUp then begin Result := FindWindow(nil, PChar(sFind)); if Result = 0 then Result := FindWindow(nil, PChar(sFind2)); // todo : 업데이트가 바로 안될경우를 대비해서 이전 식별자로 한번더 해준다.. 나중에 정리 필요 end; if bForceUp or (Result = 0) then begin // 업데이트 확인 var sCurDir: String := GetRunExePathDir; if FileExists(sCurDir + DIR_AIP17 + 'Microsoft.InformationProtection.dll') then begin if FileExists(sCurDir + DAT_AIPUP17) then begin if not FileExists(sCurDir + DIR_AIP17 + EXE_AIP) then begin DeleteFile(PChar(sCurDir + DAT_AIPUP17)); exit; end; end else begin TerminateProcessByName(EXE_AIP); // Sleep(1000); if DeleteFile_wait(sCurDir + DIR_AIP17 + EXE_AIP) and CopyFile(PChar(sCurDir + DIR_CONF + EXE_AIP17), PChar(sCurDir + DIR_AIP17 + EXE_AIP), false) and FileExists(sCurDir + DIR_CONF + EXE_AIP17) then begin WriteLnFileEndUTF8(sCurDir + DAT_AIPUP17, DateTimeToStr(Now)); end; // 이게 왜 사라지는지 모르겠지만... 보완 처리 23_1204 09:55:26 kku if not FileExists(sCurDir + DIR_AIP17 + 'Newtonsoft.Json.dll') then CopyFile(PChar(sCurDir + DIR_CONF + 'Newtonsoft.Json.dll'), PChar(sCurDir + DIR_AIP17 + 'Newtonsoft.Json.dll'), false); end; end else if FileExists(sCurDir + DIR_AIP14 + 'Microsoft.InformationProtection.dll') then begin if FileExists(sCurDir + DAT_AIPUP) then begin if not FileExists(sCurDir + DIR_AIP14 + EXE_AIP) then begin DeleteFile(PChar(sCurDir + DAT_AIPUP)); exit; end; end else begin TerminateProcessByName(EXE_AIP); // Sleep(1000); if DeleteFile_wait(sCurDir + DIR_AIP14 + EXE_AIP) and CopyFile(PChar(sCurDir + DIR_CONF + EXE_AIP14), PChar(sCurDir + DIR_AIP14 + EXE_AIP), false) and FileExists(sCurDir + DIR_CONF + EXE_AIP14) then begin WriteLnFileEndUTF8(sCurDir + DAT_AIPUP, DateTimeToStr(Now)); // DeleteFile(PChar(sCurDir + DIR_CONF + EXE_AIP14)); end; // 이게 왜 사라지는지 모르겠지만... 보완 처리 23_1204 09:55:26 kku if not FileExists(sCurDir + DIR_AIP14 + 'Newtonsoft.Json.dll') then CopyFile(PChar(sCurDir + DIR_CONF + 'Newtonsoft.Json.dll'), PChar(sCurDir + DIR_AIP14 + 'Newtonsoft.Json.dll'), false); end; end; // 모듈들 정상인지 크기로 확인 24_0221 15:12:34 kku // CheckAip14Module() 보완 필요 25_0318 13:45:00 kku // if FileExists(sCurDir + DIR_CONF + EXE_AIP14) and not CheckAip14Module then // 백신등으로 파일 복사 시 간섭때문에 제대로 복사가 안되는 경우 크기가 0인 상태가 되는 경우가 있다 25_0806 08:59:46 kku if GetFileSize_path(sPath) = 0 then begin DeleteFile(PChar(sCurDir + DAT_AIPUP17)); DeleteDir(sCurDir + DIR_AIP17); DeleteFile(PChar(sCurDir + DAT_AIPUP)); DeleteDir(sCurDir + DIR_AIP14); exit; end; sAipDMail := GetAipUPN; if sAipDMail = '' then exit; _Trace('AIP 모듈 실행 .. %d', [AipFailCnt + 1], 1); sPName := ExtractFileName(sPath); while Result = 0 do begin if nTO > 10 then break; if GetProcessPidByName(sPName) = 0 then begin if not FileExists(sPath) then break; // {$IFDEF DEBUG} // ExecuteApp(sPath, '-r', SW_HIDE); // {$ELSE} // ExecuteAppAsUser('explorer.exe', sPath, '-r', SW_HIDE); // {$ENDIF} // ExecutePath_hide(sPath, Format('-r %s', [sAipDMail])); // 차단으로 연결이 안되는 경우가 있다... // ExecutePath(sPath, Format('-r %s', [sAipDMail])); // 차단으로 연결이 안되는 경우가 있다... {$IFDEF DEBUG} if ExecuteApp(sPath, Format('-r %s', [sAipDMail]), SW_SHOWNORMAL).hProcess <> 0 then _Trace('AIP 모듈 실행 .. OK', [AipFailCnt + 1], 2); {$ELSE} if ExecuteApp(sPath, Format('-r %s', [sAipDMail]), SW_HIDE).hProcess <> 0 then _Trace('AIP 모듈 실행 .. OK', [AipFailCnt + 1], 2); {$ENDIF} Sleep(1000); end else _Trace('AIP 모듈 실행 되어 있음', [AipFailCnt + 1], 3); _Trace('AIP 모듈 핸들 검출중...', [AipFailCnt + 1], 3); Result := FindWindow(nil, PChar(sFind)); if Result = 0 then begin Result := FindWindow(nil, PChar(sFind2)); // todo : 업데이트가 바로 안될경우를 대비해서 이전 식별자로 한번더 해준다.. 나중에 정리 필요 _Trace('AIP 모듈 핸들 검출 실패', [AipFailCnt + 1], 3); end else _Trace('AIP 모듈 핸들 검출 성공', [AipFailCnt + 1], 3); Sleep(1000); Inc(nTO); end; if Result = 0 then begin Inc(AipFailCnt); dwAipExeTick_ := GetTickCount; TerminateProcessByName(sPName); _Trace('AIP 모듈 실행 .. 실패, DMail=%s, Path=%s', [sAipDMail, sPath], 1); end else begin AipFailCnt := 0; dwAipExeTick_ := 0; _Trace('AIP 모듈 실행 .. 성공', 1); end; end; end; // 음... 파일 변경 감시, 파일 생성 차단에서 "USB 연결 시에만" 옵션 사용 시 // 감시 기능 ON/OFF를 생각하고 만들었지만 이미 USB 파일만 수집, 처리되도록 만들어져서 그대로 진행함. // 현재 아래 함수는 사용하지 않음 24_0213 14:27:47 kku function TManagerService.IsUsbDrvConn: Boolean; begin Result := false; try if UsbConnList_ <> nil then Result := UsbConnList_.Count > 0; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. IsUsbDrvConn()'); end; end; procedure TManagerService.UpdatePolicyActive(aPrefModel: TPrefModel); var i: Integer; sTemp, sPath: String; begin try if bDoCbUpdate_ then begin bDoCbUpdate_ := false; if hRcvHwnd_ <> 0 then PostMessage(hRcvHwnd_, WM_REFRESH_CLIPBOARDCHAIN, 0, 0); end; // OS 업데이트 패치 확인 if PrefModel_.OsPatchCheck <> opcNone then begin if ThdOsUpdateScan_ = nil then begin ThdOsUpdateScan_ := TThdWinUpdateScan.Create(hRcvHwnd_); ThdOsUpdateScan_.StartThread; _Trace('OS 업데이트 체크 - ON', 2); end; end else if ThdOsUpdateScan_ <> nil then begin FreeAndNil(ThdOsUpdateScan_); _Trace('OS 업데이트 체크 - OFF', 2); end; // 파일 태그 기능 if IsUsingFileTag then begin // if PrefModel_.UseFileTag then // begin // if (gClient = nil) {$IFNDEF DEBUG} and FileExists(GetRunExePathDir + EXE_SLCore) {$ENDIF} then // begin // SendMessage(hRcvHwnd_, WM_REQ_FILETAG_CONTROL, 1, 0); // _Trace('파일 태그 - ON', 2); // end; // end else // if gClient <> nil then // begin // SendMessage(hRcvHwnd_, WM_REQ_FILETAG_CONTROL, 0, 0); // _Trace('파일 태그 - OFF', 2); // end; end; if sTmpAcc_ <> WTS_GetActiveSessionUserName then begin // _Trace('활성 계정 변경 .. Old=%s, New=%s', [sTmpAcc_, WTS_GetActiveSessionUserName], 1); _Trace('활성 계정 변경 .. %s', [WTS_GetActiveSessionUserName], 1); if IsAccountEmpNo and (sTmpAcc_ <> '') then begin // 현재 세션의 explorer을 모두 종료 // todo : explorer 권한으로 실행 시 현재 세션 권한으로 실행하는 기능으로 보완 필요 25_1215 13:56:18 kku TerminateProcessByName('explorer.exe'); Sleep(500); ExecutePath_runAs('explorer.exe'); TerminateProcess(GetCurrentProcess, 10); end else _Trace('활성 계정 SID .. %s', [RecentUserSid], 1); sTmpAcc_ := WTS_GetActiveSessionUserName; end; with aPrefModel do begin // 아웃룩 정책 if OutPo.bActive or (not IsOutlookABMonitorHook and (OutlookAB.Kind <> abkNone)) then begin if not ExistsKey(HKEY_CLASSES_ROOT, REG_BS1OutlookAddInKey) or (not PrefModel_.NoOutlRcvr and not ExistsKey(HKEY_USERS, RecentUserSid + '\' + REG_OUTPLUG)) then begin if ExistsKey(HKEY_CLASSES_ROOT, REG_BS1OutlookAddInKey) then begin var sDir: String := GetRunExePathDir; ExecutePath_hide('regsvr32.exe', Format('/u /s "%s"', [sDir + DIR_CONF + DLL_ADDIN])); ExecutePath_hide('regsvr32.exe', Format('/u /s "%s"', [sDir + DIR_CONF + DLL_ADDIN64])); end; bBlockOutlook_ := true; // not bInitOutMail_; end else begin bBlockOutlook_ := false; if gOutClient = nil then begin if hRcvHwnd_ <> 0 then begin SendMessage(hRcvHwnd_, WM_REQ_OUTLOOK_CONTROL, 1, 0); _Trace('아웃룩 본문 탐지 - ON', 2); end; end else if gOutClient.Connected then begin OutPo.bAttachLog := (not IsOutlookABMonitorHook and (OutlookAB.Kind = abkLog)); gOutClient.UpdateOutPo(aPrefModel); end else if not PrefModel_.NoOutlRcvr then begin i := GetRegValueAsInteger(HKEY_USERS, RecentUserSid + '\' + REG_OUTPLUG, 'LoadBehavior', -1); if (i <> -1) and (i <> 3) then begin // 추가 기능에서 사용안함으로 변경 감지 25_1203 17:34:15 kku SetRegValueInteger(HKEY_USERS, RecentUserSid + '\' + REG_OUTPLUG, 'LoadBehavior', 3); TerminateProcessByName('outlook.exe'); _Trace('아웃룩 플러그인 사용안함 감지 ... 종료 처리', 2); end; end; // if not gOutClient.Connected and (gOutClient.DeactiveW2W) then // begin // SendMessage(hRcvHwnd_, WM_REQ_OUTLOOK_CONTROL, 0, 0); // _Trace('아웃룩 종료됨, 본문 탐지 - OFF', 2); end; end else if gOutClient <> nil then begin bBlockOutlook_ := false; if hRcvHwnd_ <> 0 then begin SendMessage(hRcvHwnd_, WM_REQ_OUTLOOK_CONTROL, 0, 0); _Trace('아웃룩 본문 탐지 - OFF', 2); end; end else if bBlockOutlook_ then begin bBlockOutlook_ := false; end else if CUSTOMER_TYPE = CUSTOMER_KIMCHANG then begin if ExistsKey(HKEY_CLASSES_ROOT, REG_BS1OutlookAddInKey) and (GetProcessPidByName('outlook.exe') = 0) then begin _Trace('아웃룩 플러그인 감지, 제거 시도', 1); var sDir: String := GetRunExePathDir; ExecutePath_hide('regsvr32.exe', Format('/u /s "%s"', [sDir + DIR_CONF + DLL_ADDIN])); ExecutePath_hide('regsvr32.exe', Format('/u /s "%s"', [sDir + DIR_CONF + DLL_ADDIN64])); end; end; // 기타 처리 if bBlockOutlook_ and not IsOutlookABMonitorHook then // 아웃룩 보안 플러그인 체크 추가 23_0504 12:53:49 kku begin if NotUseUAC then begin // 현대엔지니어링은 UAC 사용하지 않아서 일반 사용자 권한으로 설치 시도 25_1113 16:36:34 kku if GetProcessPidByName('outlook.exe') = 0 then InstallOutlookPlugIn_forHD(hRcvHwnd_); end else if ThdWndMon_ = nil then begin ThdWndMon_ := TThdActiveWndMon.Create; ThdWndMon_.OnActiveWndNotify := OnWndNotify; ThdWndMon_.StartThread; _Trace('아웃룩 플러그인 미설치, 차단 활성 - ON', 2); end; end else if ThdWndMon_ <> nil then begin FreeAndNil(ThdWndMon_); _Trace('아웃룩 플러그인 미설치, 차단 활성 - OFF', 2); end; // if (FileMon.Kind <> fmkNone) and FileOpenMon then // begin // if RecentDocWatch_ = nil then // begin // RecentDocWatch_ := TRecentDocWatch.Create; // RecentDocWatch_.StartService; // _Trace('문서 열람, 감지 활성 - ON', 2); // end; // end else // if RecentDocWatch_ <> nil then // begin // FreeAndNil(RecentDocWatch_); // _Trace('문서 열람, 감지 활성 - OFF', 2); // end; // 상시로고 정책 (APP 조건) if (ScreenLogo <> askNone) and (ScreenLogo <> askAlways) then begin var bOldVal := bForceScreenLogo_; case ScreenLogo of askNone : bForceScreenLogo_ := false; askRunTargetOn : begin bForceScreenLogo_ := IsRunProcess(ScreenLogoApps, sScreenLogoChkApps_, ScreenLogoChkAppList, sTemp) or (IsUrlCatchLogo and IsUseUrl(LogoUrlList, sScreenLogoChkUrls_, ScreenLogoChkUrlList, sTemp)); end; askRunTargetOff : begin bForceScreenLogo_ := not IsRunProcess(ScreenLogoApps, sScreenLogoChkApps_, ScreenLogoChkAppList, sTemp) and (IsUrlCatchLogo and not IsUseUrl(LogoUrlList, sScreenLogoChkUrls_, ScreenLogoChkUrlList, sTemp)); end; askUseTargetOn : begin bForceScreenLogo_ := IsUseProcess(ScreenLogoApps, sScreenLogoChkApps_, ScreenLogoChkAppList, sTemp) or (IsUrlCatchLogo and IsUseUrl(LogoUrlList, sScreenLogoChkUrls_, ScreenLogoChkUrlList, sTemp)); end; askUseTargetOff : begin bForceScreenLogo_ := (not IsUseProcess(ScreenLogoApps, sScreenLogoChkApps_, ScreenLogoChkAppList, sTemp)) and (IsUrlCatchLogo and not IsUseUrl(LogoUrlList, sScreenLogoChkUrls_, ScreenLogoChkUrlList, sTemp)); end; end; if (bOldVal <> bForceScreenLogo_) and (hRcvHwnd_ <> 0) then begin if bForceScreenLogo_ then begin SendEventLog(URI_USER_ACTION, PREVENT_SCREENLOGO_IF, 'Detected : ' + sTemp); _Trace('상시 로고 (APP조건) - ON', 2); end else begin if sTemp = 'N/A' then sTemp := 'ScreenLogo Clear'; SendEventLog(URI_USER_ACTION, RELEASE_SCREENLOGO_IF, sTemp); _Trace('상시 로고 (APP조건) - OFF', 2); end; UpdateScreenLogo; end; end else if (CUSTOMER_TYPE = CUSTOMER_DEMO) and (ScreenLogo = askAlways) then begin if ScreenLogoApps <> '' then bIsAppUseScreenLogo_ := IsUseProcess(ScreenLogoApps, sScreenLogoChkApps_, ScreenLogoChkAppList, sTemp) else if bIsAppUseScreenLogo_ then bIsAppUseScreenLogo_ := false; end else if bForceScreenLogo_ then begin bForceScreenLogo_ := false; UpdateScreenLogo; end; if IsScreenLogo then begin var bUpdate: Boolean := false; // 모니터 연결/해제 감지 추가 23_1016 14:18:30 kku if nMonitorCnt_ = 0 then nMonitorCnt_ := GetSystemMetrics(SM_CMONITORS) else if nMonitorCnt_ <> GetSystemMetrics(SM_CMONITORS) then begin nMonitorCnt_ := 0; bUpdate := true; end; if sScreenLogoData_ <> ScreenLogoData then begin sScreenLogoData_ := ScreenLogoData; bUpdate := true; end; var wScreenVI: WORD := 0; if ScreenLogoVisible then wScreenVI := wScreenVI or 1; if ScreenLogoInvisible then wScreenVI := wScreenVI or (1 shl 1); if wScreenVI_ = 0 then wScreenVI_ := wScreenVI else if wScreenVI_ <> wScreenVI then begin wScreenVI_ := wScreenVI; bUpdate := true; end; if bUpdate then UpdateScreenLogo(true); end; // 캡쳐 APP 차단 정책 (APP 조건) if (ScreenBlockAppExp <> askNone) and (ScreenBlockAppExp <> askAlways) then begin var bOldVal := bForceScreenCapAppBlock_; case ScreenBlockAppExp of askRunTargetOn : bForceScreenCapAppBlock_ := IsRunProcess(ScreenBlockAppsExp, sScreenBlockChkApps_, ScreenBlockChkAppList, sTemp); askRunTargetOff : bForceScreenCapAppBlock_ := not IsRunProcess(ScreenBlockAppsExp, sScreenBlockChkApps_, ScreenBlockChkAppList, sTemp); askUseTargetOn : bForceScreenCapAppBlock_ := IsUseProcess(ScreenBlockAppsExp, sScreenBlockChkApps_, ScreenBlockChkAppList, sTemp); askUseTargetOff : bForceScreenCapAppBlock_ := not IsUseProcess(ScreenBlockAppsExp, sScreenBlockChkApps_, ScreenBlockChkAppList, sTemp); end; if bForceScreenCapAppBlock_ and (bOldVal <> bForceScreenCapAppBlock_) then begin if bForceScreenLogo_ then begin SendEventLog(URI_USER_ACTION, PREVENT_CAPTUREAPP_IF, sTemp); _Trace('캡쳐 APP 차단 (APP조건) - ON', 2); end else begin SendEventLog(URI_USER_ACTION, RELEASE_CAPTUREAPP_IF, sTemp); _Trace('캡쳐 APP 차단 (APP조건) - OFF', 2); end; try var ProcList: TStringList; Guard(ProcList, TStringList.Create); ProcList.CaseSensitive := false; if GetProcessNameToList(ProcList) > 0 then begin for i := 0 to CapAppList_.Count - 1 do begin if ProcList.IndexOf(CapAppList_[i]) <> -1 then begin TerminateProcessByName(CapAppList_[i]); if IsNotiBCA then PopupMessage(TYPE_MSG_PREVENT_CAPAPP, CapAppList_[i] + '|PV'); SendEventLog(URI_USER_ACTION, PREVENT_CAPTURE_APP, 'Software Blocked : ' + CapAppList_[i]); end; end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. ForceScreenCapAppBlock'); end; end; end else bForceScreenCapAppBlock_ := false; // 컨텐츠 필터 기능 ON/OFF (파일 쓰기 감시, 파일 생성 차단, DRM) if ((FileMon.Kind <> fmkNone) and FileMon.ContentFilter.bActive) or ((FileBlock.Kind <> fmkNone) and FileBlock.ContentFilter.bActive) or DrmCF.bActive then begin if gKvKwdSch = nil then SendMessage(hRcvHwnd_, WM_REQ_KWDSCH_CONTROL, 1, 0); end else if gKvKwdSch <> nil then SendMessage(hRcvHwnd_, WM_REQ_KWDSCH_CONTROL, 0, 0); // 파일 관련 정책 if (FileMon.Kind <> fmkNone) or (FileBlock.Kind <> fmkNone) or ((GetModeKind = hmkSecurity) and PrefModel_.DrmCF.bActive) or IsMasking or IsWaterMark or ((BlockFRename <> bfrFalse) and (BlockFRenames <> '')) or ((BlockFdRename <> bdrFalse) and (BlockDirFileRenames <> '')) or IsPreventDownloads then begin if FileService_ = nil then begin FileService_ := TFileService.Create; FileService_.StartService; _Trace('파일 감시 활성화 (이름변경, 생성, 저장 감시등) - ON', 2); end; end else if FileService_ <> nil then begin FreeAndNil(FileService_); _Trace('파일 감시 활성화 (이름변경, 생성, 저장 감시등) - OFF', 2); end; // WIFI 무선네트워크 정보 확인을 위한 위치 서비스 강제 ON 25_0827 14:16:08 kku if (WifiCtrlKind <> wckNone) and WifiGpsOn then begin i := 0; if IsWifiPublicBlock then i := 1 else case WifiCtrlKind of wckBlockName, wckWhiteName: i := 1; end; if (i <> 0) then begin if GetRegValueAsInteger(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Microsoft\Windows\AppPrivacy', 'LetAppsAccessLocation') <> 1 then begin SetRegValueInteger(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Microsoft\Windows\AppPrivacy', 'LetAppsAccessLocation', 1, true); SetRegValueInteger(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Microsoft\Windows\AppPrivacy', 'BsLaal', 1, true); end; end; end else if GetRegValueAsInteger(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Microsoft\Windows\AppPrivacy', 'BsLaal') = 1 then begin DelRegValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Microsoft\Windows\AppPrivacy', 'LetAppsAccessLocation'); DelRegValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Microsoft\Windows\AppPrivacy', 'BsLaal'); end; // 반출 파일 목록 정리 if IsApproveSupport and ExFApproval then OrganizeFileExpEnt; // 설치 프로그램 감시 if AppInstKind <> aikNone then begin if ThdInstMon_ = nil then begin ThdInstMon_ := TThdInstMon.Create; ThdInstMon_.StartService; _Trace('소프트웨어 설치 감시 - ON', 2); end; end else if ThdInstMon_ <> nil then begin FreeAndNil(ThdInstMon_); _Trace('소프트웨어 설치 감시 - OFF', 2); end; // 도메인(URL) 수집 if (WebbMonKind <> wmkNone) or ( (Print.PrintKind <> pkNone) and ((Print.sPrintUrlExcepts <> '') or (PrtApvExpUrl <> '') or (PrtWtExpUrl <> '')) ) or // ( ((WebbAB.Kind = abkUrlBlock) or (WebbAB.Kind = abkUrlAllow)) and // (WebABUrlList <> '') ) or (WebbAB.Kind <> abkNone) or // URL 수집을 위해 항상처리 IsUrlCatchLogo or // URL 조건 상시로고 추가 24_1218 10:50:38 kku (CaptureBlockUrlKind <> bkNone) then begin if ThdWebUrl_ = nil then begin ThdWebUrl_ := TThdWebUrl.Create; ThdWebUrl_.StartService; _Trace('웹브라우저 감시 - ON', 2); end; end else if ThdWebUrl_ <> nil then begin FreeAndNil(ThdWebUrl_); _Trace('웹브라우저 감시 - OFF', 2); end; // 블루투스 감시, 차단 if BlueBlockKind <> dbkNone then begin if ThdBlueMon_ = nil then begin var bPvreventCurBT: Boolean := false; var bExcept: Boolean; var BTDevice: TBluetoothDevice; Guard(BTDevice, TBluetoothDevice.Create); BTDevice.RefreshBTDevice; for i := 0 to BTDevice.Count - 1 do bPvreventCurBT := bPvreventCurBT or ProcessPreventBT(BTDevice[i], bExcept); ThdBlueMon_ := TThdBtDevNotify.Create; ThdBlueMon_.PreventBtDevs := bPvreventCurBT; ThdBlueMon_.OnChangeBTDevice := OnBtDevEntNotify; ThdBlueMon_.StartThread; _Trace('블루투스 감시 - ON', 2); end; end else if ThdBlueMon_ <> nil then begin FreeAndNil(ThdBlueMon_); _Trace('블루투스 감시 - OFF', 2); end; // MTP 감시, 차단 // todo : ThdMtpMon.pas에 정책 옵션 적용 필요 if MtpBlockKind <> ubkNone then begin if ThdMtpMon_ = nil then begin ThdMtpMon_ := TThdMtpMon.Create; ThdMtpMon_.StartThread; _Trace('MTP 감시 - ON', 2); end; end else if ThdMtpMon_ <> nil then begin FreeAndNil(ThdMtpMon_); _Trace('MTP 감시 - OFF', 2); end; // 프린트 워터마크 처리 추가 23_0627 15:22:59 kku ProcessPrintWaterEnt; // 프린터 감시, 차단 if (Print.PrintKind <> pkNone) or (Print.PrintWater <> pwNone) then // todo : 프린터 사용 감시 설정 확인 begin if sPrintPatterns_ <> Print.ContentFilter.sPatterns then sPrintPatterns_ := Print.ContentFilter.sPatterns; if Print.PrintWater <> pwNone then begin if IsUsePrintWatermarkExpFile then begin if mtxPrtWater_ = nil then mtxPrtWater_ := TTgMutex.Create(MUTEX_SHELL_EXPT_PRTWATER); end; end; // if IsHD then begin // 최신 문서 확인 기능 ON sTemp := RecentUserSid + '\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced'; if GetRegValueAsInteger(HKEY_USERS, sTemp, 'Start_TrackDocs', -99) <> 1 then begin if SetRegValueInteger(HKEY_USERS, sTemp, 'Start_TrackDocs', 1, true) then _Trace('최신 문서 확인 ON 설정', 1) else _Trace('최신 문서 확인 ON 설정 실패..', 1); end; end; if ThdPrinter_ = nil then begin // if IsHD then // begin // // 프린트 파일 경로를 잘 가져오기 위해 점프리스트 초기화 23_1220 08:42:30 kku // ClearAutoJumpLists(GetUserNameFromReg); // end; ThdPrinter_ := TTgPrtSpoolWatch.Create(false); ThdPrinter_.OnPrtNotificationEvent := OnPtrJobNotify; ThdPrinter_.StartThread; ThdPrintWork_ := TThdPrintWork.Crate; ThdPrintWork_.StartThread; _Trace('프린터 감시 - ON', 2); end; end else if ThdPrinter_ <> nil then begin if ThdPrintWork_ <> nil then FreeAndNil(ThdPrintWork_); FreeAndNil(ThdPrinter_); if mtxPrtWater_ <> nil then FreeAndNil(mtxPrtWater_); _Trace('프린터 감시 - OFF', 2); end; // 클립보드 컨텐츠 필터 업데이트 if (ClipBlockKind <> cbkNone) and CbCF.bActive then begin // DoClipboardUpdate; if CbCF.bActive then begin if sCbPatterns_ <> CbCF.sPatterns then begin sCbPatterns_ := CbCF.sPatterns; SetRuleToPtrnList(sCbPatterns_, CbPatternEnts_) end; end; end; // DRM 열람 권한 // if (GetModeKind = hmkSecurity) and (DrmAccessKind <> dakNone) then // begin // if mtxDrmOpen_ = nil then // mtxDrmOpen_ := TTgMutex.Create(MUTEX_SHELL_DRMOPEN); // end else // if mtxDrmOpen_ <> nil then // FreeAndNil(mtxDrmOpen_); // API 훅 관련 정책 체크 // DRM, 프린트 워터마크, 파일 첨부/사용 차단 // if IsNeedHook or // MutexExists(MUTEX_SHELL_DRMOPEN) then // 서버 정책에 DRM 정책이 들어간다면 IsNeedHook에 포함 시켜야 함 // 경동 나비엔은 훅 기능 없어도 항상 실행 체크 24_1126 14:22:50 kku // if CUSTOMER_TYPE = CUSTOMER_KDNVN then if CUSTOMER_TYPE = CUSTOMER_DEV then begin if bFirstAip_ then FindAipMdWnd; end else if IsSupportAIP or IsUseEncOnlyAIP then FindAipMdWnd; {$IFNDEF DEBUG1} if IsNeedHook then begin // if IsSupportAIP and (CUSTOMER_TYPE <> CUSTOMER_KDNVN) then // FindAipMdWnd; if sWebABPatterns_ <> WebbAB.ContentFilter.sPatterns then sWebABPatterns_ := WebbAB.ContentFilter.sPatterns; if sEtcABPatterns_ <> EtcAB.ContentFilter.sPatterns then sEtcABPatterns_ := EtcAB.ContentFilter.sPatterns; if sOutABPatterns_ <> OutlookAB.ContentFilter.sPatterns then sOutABPatterns_ := OutlookAB.ContentFilter.sPatterns; if IntBtBlockNewFile.contentsFilter_use then begin if BtcontentsFilter_list_ <> IntBtBlockNewFile.contentsFilter_list then BtcontentsFilter_list_ := IntBtBlockNewFile.contentsFilter_list end else BtcontentsFilter_list_ := ''; if IntUsbBlockNewFile.contentsFilter_use then begin if UsbcontentsFilter_list_ <> IntUsbBlockNewFile.contentsFilter_list then UsbcontentsFilter_list_ := IntUsbBlockNewFile.contentsFilter_list end else UsbcontentsFilter_list_ := ''; if IntUsbToUsbBlockNewFile.contentsFilter_use then begin if UsbToUsbcontentsFilter_list_ <> IntUsbToUsbBlockNewFile.contentsFilter_list then UsbToUsbcontentsFilter_list_ := IntUsbToUsbBlockNewFile.contentsFilter_list end else UsbToUsbcontentsFilter_list_ := ''; if IntCdromBlockNewFile.contentsFilter_use then begin if CdromcontentsFilter_list_ <> IntCdromBlockNewFile.contentsFilter_list then CdromcontentsFilter_list_ := IntCdromBlockNewFile.contentsFilter_list end else CdromcontentsFilter_list_ := ''; if IntMtpBlockNewFile.contentsFilter_use then begin if MtpcontentsFilter_list_ <> IntMtpBlockNewFile.contentsFilter_list then MtpcontentsFilter_list_ := IntMtpBlockNewFile.contentsFilter_list end else MtpcontentsFilter_list_ := ''; if MgHook_ = nil then begin if DrmAccessKind <> dakNone then begin // Acrobat DLL후킹 보안 해제 24_0130 10:41:29 kku var sRegPath: String := RecentUserSid + '\Software\Adobe\Adobe Acrobat\DC\'; // var ini: TIniFile; // Guard(ini, TiniFile.Create(CutFileExt(GetRunExePath) + '.ini')); if ExistsKey(HKEY_USERS, sRegPath) then begin SetRegValueInteger(HKEY_USERS, sRegPath + 'TrustManager', 'bEnhancedSecurityInBrowser', 0, true); SetRegValueInteger(HKEY_USERS, sRegPath + 'TrustManager', 'bEnhancedSecurityStandalone', 0, true); SetRegValueInteger(HKEY_USERS, sRegPath + 'Privileged', 'bProtectedMode', 0, true); end; end; MgHook_ := TManagerHook.Create; MgHook_.StartHookWatch; _Trace('APP 제어 (Hook) - ON', 2); // var NpClient: TTgNpClient; // Guard(NpClient, TTgNpClient.Create(PIPE_NAME)); // if NpClient.Connect then // begin // // NpClient.Disconnect; // end; end else begin if MgHook_.IsChangeHookPolicy(aPrefModel) then MgHook_.UpdateHookTarget; end; end else if (MgHook_ <> nil) then begin FreeAndNil(MgHook_); sWebABPatterns_ := ''; sEtcABPatterns_ := ''; sOutABPatterns_ := ''; _Trace('APP 제어 (Hook) - OFF', 2); end; {$ENDIF} // USB 차단 // TimerProcessDevTask() 여기서 처리하도록 변경 25_1113 11:11:24 kku // case UsbBlockKind of // ubkReadOnly : // begin // if ThdUsbMonRO_ = nil then // begin // ThdUsbMonRO_ := TThdUsbMon.Create(0, upkReadOnly); // ThdUsbMonRO_.StartThread; // _Trace('USB 읽기만 적용 - ON', 2); // end; // end; // else // begin // if ThdUsbMonRO_ <> nil then // begin // FreeAndNil(ThdUsbMonRO_); // _Trace('USB 읽기만 적용 - OFF', 2); // end; // // if UsbBlockKind = ubkBlock then // DoEjectUsbDrives; // end; // end; // if sEjectWbDrive_ <> '' then // begin // if hEjectWbDrive_ <> 0 then // begin // CloseHandle(hEjectWbDrive_); // hEjectWbDrive_ := 0; // end; // // if IsReadOnlyByWriteProbe(sEjectWbDrive_) = 1 then // begin // if ThdUsbMonRO_ <> nil then // ThdUsbMonRO_.SetRecoverWB(false); // try // var DriveInfo: TDriveInfo; // GetDriveDetail(sEjectWbDrive_, @DriveInfo); // SetReadOnly(sEjectWbDrive_, DriveInfo.nDiskNum, false); // Sleep(500); // if IsReadOnlyByWriteProbe(sEjectWbDrive_) <> 1 then // EjectDrive(sEjectWbDrive_, nil, false, true); // finally // if ThdUsbMonRO_ <> nil then // ThdUsbMonRO_.SetRecoverWB(true); // end; // end; // sEjectWbDrive_ := ''; // end; // CD/DVD 차단 if CdromBlockKind = dbkBlock then DoEjectCDROM; // 라우팅테이블 변경 차단 if RouteEnable then begin if ThdRouteMon_ = nil then begin ThdRouteMon_ := TThdRouteMon.Create; ThdRouteMon_.StartThread; _Trace('라우팅 테이블 감시 - ON', 2); end; end else if ThdRouteMon_ <> nil then begin FreeAndNil(ThdRouteMon_); _Trace('라우팅 테이블 감시 - OFF', 2); end; // 캡쳐 앱 차단 >> 순서 중요 : 캡쳐 APP 차단 정책 (APP 조건) 보다 아래여야 함 if bForceScreenCapAppBlock_ or (CapAppMonKind <> camNone) then begin if ThdCapAppMon_ = nil then begin ThdCapAppMon_ := TThdProcessWatch.Create(false); ThdCapAppMon_.OnProcessWatchNotify := OnCapAppNotify; ThdCapAppMon_.StartThread; _Trace('캡쳐 APP 차단 - ON', 2); end; end else if ThdCapAppMon_ <> nil then begin FreeAndNil(ThdCapAppMon_); _Trace('캡쳐 APP 차단 - OFF', 2); end; // 소프트웨어 실행 차단 if IsBlockApp or IsMonApp then begin bIsMonApp_ := IsMonApp; bIsBlockApp_ := IsBlockApp; if bIsMonApp_ and (sMonApps_ <> MonAppList) then begin sMonApps_ := MonAppList; SplitString(sMonApps_, '|', MonAppList_); end; if bIsBlockApp_ and (sBlockApps_ <> SoftwareListB) then begin sBlockApps_ := SoftwareListB; if Pos(';', sBlockApps_) > 0 then SplitString(sBlockApps_, '|', BlockAppList_) // |로 바꿨는데 이전 버전에서 저장된 정책 호환을 위해 잠시만 이렇게 처리하는거 추가, todo : 나중에 삭제 필요 25_0121 15:46:20 kku else SplitString(sBlockApps_, '|', BlockAppList_); BlockAppWList_.Clear; for i := BlockAppList_.Count - 1 downto 0 do begin if BlockAppList_[i].Contains('*') then begin BlockAppWList_.Add(BlockAppList_[i]); BlockAppList_.Delete(i); end; end; end; if ThdBlockAppMon_ = nil then begin ThdBlockAppMon_ := TThdProcessWatch.Create(false, true); ThdBlockAppMon_.OnProcessWatchNotify := OnBlockAppNotify; ThdBlockAppMon_.StartThread; _Trace('APP 실행 차단, 사용 감시 - ON', 2); end; end else if ThdBlockAppMon_ <> nil then begin bIsMonApp_ := false; bIsBlockApp_ := false; FreeAndNil(ThdBlockAppMon_); _Trace('APP 실행 차단, 사용 감시 - OFF', 2); end; // APP 동영상 녹화 if (ShowTestFun or (CUSTOMER_TYPE = CUSTOMER_LGD)) and AppRcdActive and DirectoryExists(GetRunExePathDir + DIR_CONF + 'avlib\') then begin if ThdScreenRecord_ = nil then begin ThdScreenRecord_ := TThdScreenRecord.Create(hRcvHwnd_); ThdScreenRecord_.StartThread; _Trace('APP 동영상 녹화 - ON', 2); end; end else if ThdScreenRecord_ <> nil then begin FreeAndNil(ThdScreenRecord_); _Trace('APP 동영상 녹화 - OFF', 2); end; // 복호화 가능 여부 if IsExplorerDrmMenu and IsDrmDecrypt then begin if mtxDrmDec_ = nil then mtxDrmDec_ := TTgMutex.Create(MUTEX_SHELL_DRMDEC); end else if mtxDrmDec_ <> nil then FreeAndNil(mtxDrmDec_); // AutoRun 방지 if AutoRunBlock then begin if sAutoRunBlockKey_ = '' then begin var sSid: String := RecentUserSid; if sSid <> '' then sAutoRunBlockKey_ := sSid + '\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer'; end; if sAutoRunBlockKey_ <> '' then begin if GetRegValueAsInteger(HKEY_USERS, sAutoRunBlockKey_, 'NoDriveTypeAutoRun') <> $FF then begin SetRegValueInteger(HKEY_USERS, sAutoRunBlockKey_, 'NoDriveTypeAutoRun', $FF, true); _Trace('USB AutoRun 방지 - ON', 2); end; end; end else if sAutoRunBlockKey_ <> '' then begin DelRegValue(HKEY_USERS, sAutoRunBlockKey_, 'NoDriveTypeAutoRun'); sAutoRunBlockKey_ := ''; _Trace('USB AutoRun 방지 - OFF', 2); end; if bIsScreenLogoBold_ <> (bIsIdleScreenLogo_ or bIsIpMatchScreenLogo_ or bIsRdpLogonScreenLogo_ or bIsAppUseScreenLogo_) then begin if bIsScreenLogoBold_ then SendEventLog(URI_USER_ACTION, PREVENT_SCREENLOGO_BOLD, 'Screen Logo : Normal') else SendEventLog(URI_USER_ACTION, PREVENT_SCREENLOGO_THIN, 'Screen Logo : Bold'); bIsScreenLogoBold_ := bIsIdleScreenLogo_ or bIsIpMatchScreenLogo_ or bIsRdpLogonScreenLogo_ or bIsAppUseScreenLogo_; UpdateScreenLogo(true); end; // 시간 변경 체크 if dtLastChk_ <> 0 then begin var dtNow: TDateTime := Now; var bChangeDT: Boolean := CompareDateTime(Now, dtLastChk_) = -1; if bChangeDT or (SecondsBetween(dtNow, dtLastChk_) > 120) then begin _Trace('시간 변경 감지됨. OldDT=%s, NewDT=%s', [DateTimeToStr(dtLastChk_), DateTimeToStr(dtNow)]); if PrefModel_.BlockChangeTime then begin if SetLocalTime(ConvDateTimeToSystemTime_Local(IncSecond(dtLastChk_))) then // todo : 개선필요... begin _Trace('시간 변경 차단 성공 .. %s', [DateTimeToStr(Now)]); SendEventLog(URI_USER_ACTION, SYSEVT_PROTECT_PCTIME, Format('OldDT=%s, NewDT=%s', [DateTimeToStr(dtLastChk_), DateTimeToStr(dtNow)])) end else _Trace('시간 변경 차단 실패 .. Error=%d', [GetLastError]); end; end; end; dtLastChk_ := Now; {$IFNDEF DEBUG} // 크롬, 엣지 시작페이지 변경 for 알라딘 if CUSTOMER_TYPE = CUSTOMER_ALADIN then begin if PrefModel_.IsShowAInfo then begin var bMakeRKey: Boolean; bMakeRKey := ExistsKey(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Microsoft\Edge'); if not bMakeRKey then SetRegValueInteger(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Microsoft\Edge', 'BS1', 9, true); if GetRegValueAsInteger(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Microsoft\Edge', 'RestoreOnStartup') <> 5 then SetRegValueInteger(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Microsoft\Edge', 'RestoreOnStartup', 5, true); if GetRegValueAsString(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Microsoft\Edge', 'NewTabPageLocation') <> 'about:blank' then SetRegValueString(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Microsoft\Edge', 'NewTabPageLocation', 'about:blank', true); bMakeRKey := ExistsKey(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Google\Chrome'); if not bMakeRKey then SetRegValueInteger(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Google\Chrome', 'BS1', 9, true); if GetRegValueAsInteger(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Google\Chrome', 'RestoreOnStartup') <> 5 then SetRegValueInteger(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Google\Chrome', 'RestoreOnStartup', 5, true); if GetRegValueAsString(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Google\Chrome', 'NewTabPageLocation') <> 'about:blank' then SetRegValueString(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Google\Chrome', 'NewTabPageLocation', 'about:blank', true); end else begin if GetRegValueAsInteger(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Microsoft\Edge', 'BS1') = 9 then DelRegKey(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Microsoft\Edge'); if GetRegValueAsInteger(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Google\Chrome', 'BS1') = 9 then DelRegKey(HKEY_LOCAL_MACHINE, 'SOFTWARE\Policies\Google\Chrome'); end; end; {$ENDIF} end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. UpdatePolicyActive()'); end; end; procedure TManagerService.SetSchRstVul(bVal: Boolean); begin if bSchRstVul_ <> bVal then begin bSchRstVul_ := bVal; AgentModel_.ForceVulMode := bSchRstVul_; AgentModel_.Save; // if bSchRstVul_ then // SetRegValueInteger(HKEY_LOCAL_MACHINE, REG_HE, 'SchRstVul', 1, true) // else // DelRegValue(HKEY_LOCAL_MACHINE, REG_HE, 'SchRstVul'); RefreshView; end; end; procedure TManagerService.LoadSchRstVul; begin SetSchRstVul(AgentModel_.ForceVulMode and (PrefModel_.PersonalInfoFileMax > 0)); // or // (GetRegValueAsInteger(HKEY_LOCAL_MACHINE, REG_HE, 'SchRstVul') = 1)); end; function TManagerService.GetIsRestricDate: Boolean; begin // 접속 승인과 만료일이 AND에서 OR로 바껴서 // 만료일 표시가 의미 없어졌다. // 접속 승인 OFF 했는데 만료일도 끝났다면 무조건 만료일 문제로 뜨기 때문에 // 사용하지 않는걸로 보완 22_1111 09:05:03 kku Result := false; // PrefModel_.IsRestricDate; end; procedure TManagerService.ProcessReleaseQuarantineFiles; var sInfo, sPath, sDestUrl: String; O: ISuperObject; i: Integer; ms: TMemoryStream; begin try sInfo := GetQuarantineInfo(DestServerUrl, HTTP_, sUserName_); if sInfo = '' then exit; O := SO(sInfo); if O.S['result'] <> 'true' then begin _Trace('Fail .. ReleaseQuarantineFiles() .. result = false', 2); exit; end; if O.O['rtnMap'] = nil then begin _Trace('Fail .. ReleaseQuarantineFiles() .. List Empty', 2); exit; end; if O.O['rtnMap'].DataType <> stArray then begin _Trace('Fail .. ReleaseQuarantineFiles() .. Invalid List', 2); exit; end; sDestUrl := StringReplace(DestServerUrl, 'agentLogRequest.do', 'quarantineFileDownload/', [rfReplaceAll]); sDestUrl := StringReplace(sDestUrl, 'agentLogRequests.do', 'quarantineFileDownload/', [rfReplaceAll]); Guard(ms, TMemoryStream.Create); for i := 0 to O.A['rtnMap'].Length - 1 do begin if O.A['rtnMap'].O[i].S['offYn'] = 'T' then begin sPath := O.A['rtnMap'].O[i].S['filepath']; // if FileExists(sPath) then // DeleteFileForce(sPath); ms.Clear; try HTTP_.Get(sDestUrl + IntToStr(O.A['rtnMap'].O[i].I['idx']), ms); // if not FileExists(sPath) and (ms.Size > 0) then // ms.SaveToFile(sPath); if FileExists(sPath) then DeleteFileForce(sPath); ms.SaveToFile(sPath); gMgSvc.PopupMessage(TYPE_MSG_RELEASE_QUARANTINE_FILE, sPath); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. QuarantineFile Download .. FName=%s', [ExtractFileName(sPath)]) end; end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. ProcessReleaseQuarantineFiles()'); end; end; function TManagerService.GetLastPolicy: String; begin if sLastPolicy_ = '' then begin var dt: TDateTime := JavaToDelphiDateTime(StrToInt64Def(GetRegValueAsString(HKEY_LOCAL_MACHINE, REG_HE, 'LP'), 0)); if PrefModel_.Loaded and (dt <> 0) then sLastPolicy_ := FormatDateTime('yyyy-mm-dd hh:nn:ss', dt) else sLastPolicy_ := '1999-01-01 01:01:01'; end; Result := sLastPolicy_; end; procedure TManagerService.SetLastPolicy(sLP: String); begin if sLastPolicy_ <> sLP then begin sLastPolicy_ := sLP; SetRegValueString(HKEY_LOCAL_MACHINE, REG_HE, 'LP', IntToStr(DelphiToJavaDateTime(StrToDateTime(sLastPolicy_))), true); end; end; procedure TManagerService.UpdateIgrUsbSerial4FltCtr(sData: String ; FltCtrlPolicy : DWORD); var ExpList, InfoList: TStringList; i: Integer; DevInfo: TDevInfo; begin // _Trace('[MGKIM] UpdateIgrUsbSerial4FltCtr .. begin bFltCtrlInit(%d)(%d)',[DWORD(bFltCtrlInit_), FltCtrlPolicy]); if not bFltCtrlInit_ or (FltCtrlPolicy = 0) then exit; try FltCtrl_.ClearUsbException; Guard(ExpList, TStringList.Create); SplitString(sData, '|', ExpList, false, true); Guard(InfoList, TStringList.Create); // _Trace('[MGKIM] UpdateIgrUsbSerial4FltCtr .. (%s), ExpList.Count(%d)',[sData, ExpList.Count]); for i := 0 to ExpList.Count - 1 do begin SplitString(ExpList[i], '&', InfoList); // _Trace('[MGKIM] UpdateIgrUsbSerial4FltCtr .. InfoList.Count(%d)',[InfoList.Count]); if InfoList.Count = 3 then begin var vid: DWORD; var pid: DWORD; // _Trace('[MGKIM] UpdateIgrUsbSerial4FltCtr.. PID: %s, VID: %s, Serial: %s',[InfoList[0], InfoList[1],InfoList[2]]); vid:= StrToIntDef('$' + InfoList[0], 0); pid:= StrToIntDef('$' + InfoList[1], 0); DeviceGuard_.AddUsbPortExcept(InfoList[0], InfoList[1],InfoList[2]); if (vid <> 0) and (pid <> 0) then begin // _Trace('[MGKIM] UpdateIgrUsbSerial4FltCtr.. Port PID: %x, VID: %x, Serial: %s',[vid, pid,InfoList[2]]); FltCtrl_.SetUsbPortException(vid, pid, 0, PChar(InfoList[2])); end; FltCtrl_.SetUsbException(PChar(InfoList[0]), PChar(InfoList[1]), 0, PChar(InfoList[2])); // _Trace('[MGKIM] UpdateIgrUsbSerial4FltCtr.. end'); end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. UpdateIgrUsbSerial4FltCtr()'); end; end; procedure TManagerService.UpdateFltCtrlEnts(sDrive, sDevInfo: String); begin Lock; try sDrive := sDrive.ToUpper; if DcFltCtrlEnt_.ContainsKey(sDrive) then DcFltCtrlEnt_[sDrive] := sDevInfo else DcFltCtrlEnt_.Add(sDrive, sDevInfo); finally Unlock; end; end; function TManagerService.GetFltCrltEntInfo(sDrive: String): String; function GetSameSerialDevs(sSerial: String; var nSameCnt: Integer): String; var enum: TEnumerator; begin Result := ''; Lock; try Guard(enum, DcFltCtrlEnt_.Values.GetEnumerator); while enum.MoveNext do begin if enum.Current.EndsWith(sSerial) then begin SumString(Result, enum.Current, ''); Inc(nSameCnt); end; end; finally Unlock; end; end; begin Result := ''; Lock; try sDrive := sDrive.ToUpper; if DcFltCtrlEnt_.ContainsKey(sDrive) then Result := DcFltCtrlEnt_[sDrive]; finally Unlock; end; if Result <> '' then begin var nSameCnt: Integer := 0; var sSerial: String := ExtrLastDelimiterStr(Result, '§'); var sSame: String; // 오래된 SD 멀티 허브의 경우 빈드라이브가 여러개 생성되는데 // 이거 모두 동일한 시리얼로 인식될 경우 정보 모두 처리하도록 보완 25_0202 14:43:43 kku sSame := GetSameSerialDevs(sSerial, nSameCnt); if nSameCnt > 1 then Result := sSame; end; end; procedure TManagerService.ProcessUSBArrival(sDrive: String); var nType: Integer; sMsg: String; llSize: LONGLONG; UsbBlockKind: TUsbBlockKind; DevBlockKind: TDevBlockKind; bCdrom: Boolean; DriveInfo: TDriveInfo; Label LB_ProcCDROM; begin // _Trace('ProcessUSBArrival() .. 1'); try try // 보안, 가상 드라이브의 경우 연결 이벤트가 여러번 발생한다. // 이를 보완하기 위해 추가 25_0423 09:05:48 kku if UsbConnList_.IndexOf(sDrive) <> -1 then exit; except on E: Exception do ETgException.TraceException(Self, E, 'Error .. ProcessUSBArrival() .. Check UsbConnList()'); end; // _Trace('ProcessUSBArrival() .. 2'); // if GetDriveExtent(sDrive).liExtentLength.QuadPart = 0 then if not DirectoryExists(sDrive) then begin if ThdUsbMonRO_ <> nil then ThdUsbMonRO_.AddEmptyDrive(sDrive) else if EmDriveList_.IndexOf(sDrive) = -1 then EmDriveList_.Add(sDrive); if GetDriveType(PChar(sDrive)) = DRIVE_CDROM then begin llSize := 0; goto LB_ProcCDROM; end; exit; end; llSize := GetDriveSize(sDrive); // _Trace('ProcessUSBArrival() .. 3, Size=%d, VName=%s', [llSize, GetVolumeName(sDrive)]); if llSize <> 0 then begin nType := Integer(GetDriveType(PChar(sDrive))); _Trace('[%s] 드라이브 연결, Drive=%s, Size=%s', [GetDriveTypeToStr(nType), sDrive, ByteSizeToStr(llSize)], 1); sRecentUsbDrv_ := sDrive; bCdrom := false; case nType of DRIVE_CDROM : begin bCdrom := true; // PopupMessage(TYPE_MSG_PREVENT_CDROM, sDrive + '|' + // ByteSizeToStr(llSize) + '|' + sFriendlyName + '|CD/DVD|' + sSerial); // // SendEventLog(URI_USER_ACTION, PREVENT_CDROM, // Format('CD/DVD Blocked : Name=%s, Drive=%s (%s), Serial=%s', // [sFriendlyName, sDrive, ByteSizeToStr(llSize), sSerial])); // SendEventLog(URI_USER_ACTION, LOGCODE_PREVENT_USB, // Format('USB Connected : Drive=%s, Type=%s', // [sDriveInfo, sType])); end; DRIVE_FIXED, DRIVE_REMOVABLE : begin // if nType = DRIVE_REMOVABLE then // Fixed 도 적용 되도록 롤백 (4005) 25_0917 17:39:41 kku begin if ModePolicy.UsbBlockKind = ubkReadOnly then begin if ThdUsbMonRO_ = nil then begin if IsReadOnlyByWriteProbe(sDrive) <> 1 then begin GetDriveDetail(sDrive, @DriveInfo); SetReadOnly(sDrive, DriveInfo.nDiskNum, false); end; end else ThdUsbMonRO_.AddDrive(sDrive); end else if ModePolicy.UsbBlockKind <> ubkBlock then begin if IsReadOnlyByWriteProbe(sDrive) = 1 then begin _Trace('읽기전용 속성 감지됨 .. Drive=%s', [sDrive], 2); GetDriveDetail(sDrive, @DriveInfo); SetReadOnly(sDrive, DriveInfo.nDiskNum, false); _Trace('읽기전용 속성 해제 .. Drive=%s', [sDrive], 2); end; end; end; try if UsbConnList_.IndexOf(sDrive) = -1 then UsbConnList_.Add(sDrive); except // .. end; if (FileService_ <> nil) and FileService_.IsWorking then begin var bExpUsb: Boolean := false; if ModePolicy.IgrUsbSerialList.Count > 0 then begin GetDriveDetail(sDrive, @DriveInfo); bExpUsb := ModePolicy.IgrUsbSerialList.IndexOf(DriveInfo.sSerial) <> -1; end; FileService_.AddDriveWatch(sDrive, true, bExpUsb); end; end; else _Trace('GetDriveType() .. Unknown .. %d', [nType], 1); end; if bCdrom then begin LB_ProcCDROM : DevBlockKind := ModePolicy.CdromBlockKind; case DevBlockKind of _dbkPopup, dbkLog : begin var sDriveInfo: String := sDrive; // Format('%s (%s)', [sDrive, ByteSizeToStr(llSize)]); var sType: String := GetDriveTypeToStr(nType); if IsDivPopup then begin if ModePolicy.CdAllowPopup then PopupMessage(TYPE_MSG_MONITOR_CDROM, sDriveInfo); end else begin if DevBlockKind = _dbkPopup then PopupMessage(TYPE_MSG_MONITOR_CDROM, sDriveInfo); end; sMsg := Format('CD/DVD Connected : Drive=%s', [sDriveInfo]); if bIsNewApi_ then begin GetDriveDetail(sDrive, @DriveInfo); var LogInfo: TLogInfo; ZeroMemory(@LogInfo, SizeOf(LogInfo)); LogInfo.sCode := MONITOR_CDROM; LogInfo.sDevName := DriveInfo.sFriendlyName; LogInfo.sDevSerial := DriveInfo.sSerial; LogInfo.sDevClassId := DriveInfo.sClassGuid; LogInfo.sSummary := sMsg; SendEventLogEx(@LogInfo, false); end else SendEventLog(URI_USER_ACTION, MONITOR_CDROM, sMsg, false); end; end; end else begin UsbBlockKind := ModePolicy.UsbBlockKind; case UsbBlockKind of ubkLog : begin var sDriveInfo: String := Format('%s (%s)', [sDrive, ByteSizeToStr(llSize)]); var sType: String := GetDriveTypeToStr(nType); if IsDivPopup then begin if ModePolicy.UsbAllowPopup then PopupMessage(TYPE_MSG_MONITOR_USB, sDriveInfo + '|' + sType); end else begin if ModePolicy.USBPopup then PopupMessage(TYPE_MSG_MONITOR_USB, sDriveInfo + '|' + sType); end; sMsg := Format('USB Connected : Drive=%s, Type=%s', [sDriveInfo, sType]); if bIsNewApi_ then begin GetDriveDetail(sDrive, @DriveInfo); var LogInfo: TLogInfo; ZeroMemory(@LogInfo, SizeOf(LogInfo)); LogInfo.sCode := MONITOR_USB; LogInfo.sDevName := DriveInfo.sFriendlyName; LogInfo.sDevSerial := DriveInfo.sSerial; LogInfo.sDevClassId := DriveInfo.sClassGuid; LogInfo.sSummary := sMsg; SendEventLogEx(@LogInfo, false); end else SendEventLog(URI_USER_ACTION, MONITOR_USB, sMsg, false); end; ubkBlock : begin // 바로 차단 시도 추가 25_0929 13:20:09 kku // _Trace('연결 감지 .. 차단 시도 .. Drive=%s', [sDrive], 2); // DoEjectUsbDrive(sDrive, nType); end; end; end; end; // _Trace('ProcessUSBArrival() .. 4'); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. ProcessUSBArrival()'); end; end; procedure TManagerService.OnUSBArrival(Sender: TObject; pInfo: PDevBroadcastVolume); begin try ProcessUSBArrival(GetDriveFromMask(pInfo.dwUnitmask)); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. OnUSBArrival()'); end; end; procedure TManagerService.OnUSBQueryRemove(Sender: TObject; sDrive: String; var bAccept: Boolean); var i: Integer; begin try i := UsbConnList_.IndexOf(sDrive); if i <> -1 then UsbConnList_.Delete(i); if FileService_ <> nil then FileService_.DelDriveWatch(sDrive); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. OnUSBQueryRemove()'); end; bAccept := true; end; procedure TManagerService.ProcessUSBRemove(sDrive: String); var i: Integer; b: Boolean; begin // 보안, 가상 드라이브는 OnUSBQueryRemove 이걸 거치지 않아서 추가 25_0423 09:11:42 kku OnUSBQueryRemove(nil, sDrive, b); _Trace('USB 드라이브 해제, Drive=%s', [sDrive], 1); i := IgrEjectDrives_.IndexOf(sDrive); if i <> -1 then IgrEjectDrives_.Delete(i); i := EmDriveList_.IndexOf(sDrive); if i <> -1 then EmDriveList_.Delete(i); if FileService_ <> nil then FileService_.DelDriveWatch(sDrive); if ThdUsbMonRO_ <> nil then ThdUsbMonRO_.DelDrive(sDrive); end; procedure TManagerService.OnUSBRemove(Sender: TObject; pInfo: PDevBroadcastVolume); begin ProcessUSBRemove(GetDriveFromMask(pInfo.dwUnitmask)); end; function TManagerService.ProcessPreventBT(pEnt: PBtDevEnt; var bExcept: Boolean): Boolean; const EXPT_BLUE_VENDER = ';keychron'; // 기본으로 예외할 벤더사 var sTemp1, sTemp2: String; i: Integer; PvMajorList: TStringList; begin Result := false; if ModePolicy.BlueBlockKind <> dbkBlock then exit; bExcept := false; if not pEnt.dInfo.fConnected then exit; sTemp1 := ModePolicy.BlueExceptVender + EXPT_BLUE_VENDER; sTemp2 := UpperCase(pEnt.dInfo.szName); if (sTemp1 <> '') and (sTemp2 <> '') then begin var VenderList: TStringList; Guard(VenderList, TStringList.Create); SplitString(UpperCase(sTemp1), ';', VenderList); for i := 0 to VenderList.Count - 1 do if sTemp2.Contains(VenderList[i]) then begin bExcept := true; exit; end; end; Guard(PvMajorList, TStringList.Create); PvMajorList.CaseSensitive := false; SplitString(ModePolicy.BlueExcept, ';', PvMajorList); if PvMajorList.IndexOf(pEnt.sAddress) > -1 then begin bExcept := true; exit; end; BtDevTypeToStr(pEnt.dInfo.ulClassofDevice, sTemp1, sTemp2); if PvMajorList.IndexOf(sTemp1) = -1 then begin // BluetoothRemoveDevice() 함수는 단순히 연결을 끊는 것이 아니라, // 장치 페어링 정보 자체를 시스템에서 제거합니다. 따라서 // 이 함수를 호출하면 해당 장치와의 연결이 끊어지는 것은 물론, // 페어링 되었던 다른 장치와의 연결 정보에도 영향을 줄 수 있습니다. Result := BluetoothRemoveDevice(pEnt.dInfo.Address) = 0; if not Result then _Trace('Fail .. ProcessPreventBT(), Name="%s", sTemp1=%s', [pEnt.dInfo.szName, sTemp1]); Result := true; // 차단 대상이면 위 작업과 별개로 장치 차단을 하도록 함 22_0630 09:15:10 kku exit; end; end; procedure TManagerService.OnBtDevEntNotify(pEnt: PBtDevEnt; csBT: TBTChangeStates; var bPrevent: Boolean); var h: HWND; bExcept, bPopup: Boolean; sMajor, sMinor, sData, sLog: String; PO: TPrefModel; begin if (csConnected in csBT) or (csAuthenticated in csBT) then begin // "장치 추가" 창이 떠있는 경우 팝업 안함 24_0702 15:33:22 kku // "장치 추가" 창이 떠있는 경우 팝업, 차단, 로깅 안함 25_0930 08:45:26 kku h := FindWindow('NativeHWNDHost', '장치 추가'); if h = 0 then h := FindWindow('NativeHWNDHost', 'Add a device'); if h = 0 then h := FindWindow('ApplicationFrameWindow', '디바이스 추가'); if h = 0 then h := FindWindow('ApplicationFrameWindow', 'Add a device'); if h <> 0 then exit; bExcept := false; bPrevent := ProcessPreventBT(pEnt, bExcept); // if bExcept then // exit; BtDevTypeToStr(pEnt.dInfo.ulClassofDevice, sMajor, sMinor); sLog := Format('Name : %s, Type : %s (%s), Address : %s', [pEnt.dInfo.szName, sMajor, sMinor, pEnt.sAddress]); TTgTrace.T('OnBtDevEntNotify() .. sLog=%s', [sLog], 4); PO := GetModePolicy; bPopup := PO.BTPopup; sData := String(pEnt.dInfo.szName) + '|' + Format('%s (%s)', [sMajor, sMinor]) + '|' + pEnt.sAddress; if bPrevent then begin // FltCtrl_.SetPolicy(DWORD(BDC_BLUETOOTH), DWORD(bPrevent), DWORD(1)); sData := sData + '|PV'; if bPopup then PopupMessage(TYPE_MSG_PREVENT_BLUETOOTH, sData); if bIsNewApi_ then begin var LogInfo: TLogInfo; ZeroMemory(@LogInfo, SizeOf(LogInfo)); LogInfo.sCode := PREVENT_BLUETOOTH; LogInfo.sDevName := pEnt.dInfo.szName; LogInfo.sDevSerial := pEnt.sAddress; LogInfo.sDevClassId := Format('%s (%s)', [sMajor, sMinor]); LogInfo.sSummary := 'Blocked : ' + pEnt.dInfo.szName; SendEventLogEx(@LogInfo); end else SendEventLog(URI_USER_ACTION, PREVENT_BLUETOOTH, sLog); end else begin // FltCtrl_.SetPolicy(DWORD(BDC_BLUETOOTH), DWORD(bPrevent), DWORD(1)); if PrefModel_.BtConNotiDSec > 0 then begin // 일정 시간동안 다시 알림 하지 않도록 기능 보완 if HasDelayProcEntById('BT:' + pEnt.sAddress) then exit; AddDelayProcEnt('BT:' + pEnt.sAddress, PrefModel_.BtConNotiDSec); end; case PO.BlueBlockKind of dbkBlock, dbkLog : begin if IsDivPopup then bPopup := PO.BtAllowPopup; if bExcept then sLog := 'Excepted, ' + sLog; if bPopup then PopupMessage(TYPE_MSG_PREVENT_BLUETOOTH, sData); end; end; if bIsNewApi_ then begin var LogInfo: TLogInfo; ZeroMemory(@LogInfo, SizeOf(LogInfo)); LogInfo.sCode := MONITOR_BLUETOOTH; LogInfo.sDevName := pEnt.dInfo.szName; LogInfo.sDevSerial := pEnt.sAddress; LogInfo.sDevClassId := Format('%s (%s)', [sMajor, sMinor]); LogInfo.sSummary := 'Detected : ' + pEnt.dInfo.szName; SendEventLogEx(@LogInfo); end else SendEventLog(URI_USER_ACTION, MONITOR_BLUETOOTH, sLog, false); end; end; end; function ExtrTextFromFile(sPath: String; bIgrImg: Boolean = false): String; function ExtrTxtData(sSrcPath, sDestPath: String): Boolean; var sExe, sParam: String; O: ISuperObject; Opt: TCttSimpleOpt; nTry: Integer; Label LB_Retry; begin Result := false; try if not FileExists(sSrcPath) then exit; sExe := GetRunExePathDir + EXE_KVCTTSCH; if not FileExists(sExe) then exit; Opt.sSrcPath := sSrcPath; Opt.sDestPath := sDestPath; Opt.sAssocInfo := ''; sParam := GetRunExePathDir + '$kvcs.dat'; O := SO; O.I['CSTT'] := Integer(csttExtrSimple); O.O['SOpt'] := TTgJson.ValueToJsonObject(Opt); nTry := 0; LB_Retry : if SaveJsonObjToFile(O, sParam) then begin if ExecuteAppWaitUntilTerminate(sExe, Format('-p "%s"', [sParam]), SW_HIDE, 20000) then begin if not FileExists(sDestPath) then begin Inc(nTry); if nTry < 2 then begin TTgTrace.T('Fail .. ExtrTextFromFile() .. ExecuteModule', 4); Sleep(500); goto LB_Retry; end else exit; end; Result := true; end else TTgTrace.T('Fail .. ExtrTextFromFile() .. 1', 4); end else TTgTrace.T('Fail .. ExtrTextFromFile() .. 2', 4); except on E: Exception do ETgException.TraceException(E, 'Fail .. ExtrTextFromFile() .. ExtrTxtData()'); end; end; var sExt, sDestPath: String; StrList: TStringList; ss: TStringStream; begin Result := ''; sExt := GetFileExt(sPath).ToUpper; // todo : 압축파일도 내용 추출 추가 필요 25_0410 20:04:49 kku if Pos(sExt, COMPRESS_EXTS) > 0 then exit; if bIgrImg and (Pos(sExt, IMAGE_EXTS) > 0) then exit; if Pos(sExt, AIP_EXTS) > 0 then begin if IsSupportAIP and IsAipEncryted(sPath) then exit; end; sDestPath := GetRunExePathDir + 'Task\'; if ForceDirectories(sDestPath) then begin // 파일 이름에 "문서 출력", "문서출력"이 포함되어 있으면 깨져서 내보내기가 된다... 25_0409 15:33:44 kku // sDestPath := sDestPath + ExtractFileName(sPath) + '.$kv'; sDestPath := sDestPath + FormatDateTime('yymmddhhnnss', Now) + IntToStr(Length(sPath)) + '.' + GetFileExt(sPath) + '.$kv'; if ExtrTxtData(sPath, sDestPath) then begin Result := ExtractTextSafe(sDestPath); {$IFDEF DEBUG} if Result = '' then begin TTgTrace.T('Fail .. ExtrTextFromFile() .. empty', 4); exit; end; {$ENDIF} DeleteFile(PChar(sDestPath)); // TTgTrace.T('ExtrTextFromFile() .. Length = %d', [Length(Result)], 4); end; end else TTgTrace.T('Fail .. ExtrTextFromFile() .. not found', 4); end; procedure TManagerService.OnUnzipProgress(Sender : TObject; Progress : Byte; var Abort : Boolean); begin end; procedure TManagerService.OnPwdEvent(Sender : TObject; var NewPassword : String); begin NewPassword := ''; end; function TManagerService.HasContentInfo(sMName, sPath: String; aAppType: TCurAppType): Boolean; var PatternEntList: TPatternEntList; nHitLimit, nLimitMB, nUnzipDepth, nDecompDepth: Integer; ExtList: TStringList; function FindContent(var unable : string ; fileNameChk: Boolean; sTgPath: String; var sFounds, sFoundsC: String): Boolean; var sExtrTxt, sSchTxt, sFound: String; i, nHits, nOrCnt, nAndCnt, nHighCnt, nTotalHits: Integer; begin try Result:= False; unable := ''; sExtrTxt := ExtrTextFromFile(sTgPath); //검사 불가 파일... kvcttSch.exe를 통해 문서 txt로 변환... if sExtrTxt = '' then begin unable := 'unable to analysis'; exit; end; if fileNameChk then sExtrTxt := 'FileName : ' + ExtractFileName(sTgPath) + #13#10#13#10 + sExtrTxt else sExtrTxt := sExtrTxt; sFounds := ''; sFoundsC := ''; sFound := ''; nTotalHits := 0; nOrCnt := 0; nAndCnt := 0; nHighCnt := 0; for i := 0 to PatternEntList.Count - 1 do begin sSchTxt := PatternEntList[i].GetSearchText; nHits := TTgPcre.GetMatchValues(sExtrTxt, sSchTxt, sFound); if nHits > 0 then begin if bIsNewApi_ then begin if nHits < PatternEntList[i].IfCount then continue; if sSchTxt.StartsWith('(? 0) then begin // AND 갯수가 다르다면 X if nAndCnt <> PatternEntList.AndCount then exit; // OR가 조건으로 있는데 검출된 OR가 없다면 X if (PatternEntList.AndCount <> PatternEntList.Count) and (nOrCnt = 0) then exit; end; end; Result := true; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. FindContent()'); end; end; function ProcessDecompFile(var unable : string ; fileNameChk: Boolean; sPath, sExportDir: String; var sFounds, sFoundsC: String; sOrgCompPath: String; sParentFile: String = ''): Boolean; var i: Integer; sExt, sUpDirName: String; begin Result := False; unable := ''; try // 압축파일 처리 22_1201 14:54:18 kku DeleteDir(sExportDir, true, true); if ForceDirectories(sExportDir) then begin Inc(nDecompDepth); try if (nUnzipDepth > 0) and (nUnzipDepth < nDecompDepth) then exit; var FList: TStringList; Guard(FList, TStringList.Create); try var ReslutString: string; ReslutString:= DecompressFile(sPath, sExportDir, OnUnzipProgress, OnPwdEvent); if ReslutString <> '' then begin unable:= ReslutString; Exit; end; ExtrFilesPathFromDir(sExportDir, FList, true); for i := 0 to FList.Count - 1 do begin sExt := GetFileExt(FList[i]).ToUpper; sUpDirName := StringReplace(ExtractFilePath(FList[i]), sExportDir, '', [rfReplaceAll]); if sUpDirName <> '' then sUpDirName := sParentFile + ' > ' + sUpDirName else sUpDirName := sParentFile; if Pos(sExt, COMPRESS_EXTS) > 0 then begin Result := ProcessDecompFile(unable, fileNameChk, FList[i], Format('%s%d\', [sExportDir, nDecompDepth]), sFounds, sFoundsC, sOrgCompPath, sUpDirName + ' > ' + ExtractFileName(FList[i])); end else begin if (ExtList.Count > 0) and (ExtList.IndexOf(sExt) = -1) then continue; if CUSTOMER_TYPE = CUSTOMER_LOTTEMART then begin case GetFileTypeW_r(FList[i]) of 103, 106 : continue; // begin // _Trace('HasContentInfo() .. Fasoo DRM 적용됨2. Path=%s', [FList[i]], 9); // exit; // end; end; end; Result := FindContent(unable, fileNameChk, FList[i], sFounds, sFoundsC); end; if unable <> '' then exit; if Result then exit; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. Unzip'); end; finally DeleteDir(sExportDir, true, true); Dec(nDecompDepth); end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. ProcessDecompFile()'); end; end; var ModePolify: TPrefModel; sExt, sExportDir, sFounds, sFoundsC: String; REnt: TRecentFnd; nTO: Integer; fileNameChk: Boolean; begin Result := false; try sExt := GetFileExt(sPath).ToUpper; sFounds := PrefModel_.CfFblkExts; if sFounds <> '' then begin Guard(ExtList, TStringList.Create); SplitString(UpperCase(sFounds), '|', ExtList); if ExtList.IndexOf(sExt) > -1 then begin Result := true; REnt.dtReg := Now; REnt.sMName := sMName; REnt.sPath := sPath; REnt.sFounds := 'Blocked by file extension policy.'; REnt.sFoundsC := 'Blocked by file extension policy.'; REnt.bResult := Result; REnt.curAppType := aAppType; AddRecentFnd(REnt); exit; end; end; if CUSTOMER_TYPE = CUSTOMER_LOTTEMART then begin case GetFileTypeW_r(sPath) of 103, 106 : begin _Trace('HasContentInfo() .. Fasoo DRM 적용됨. Path=%s', [sPath], 9); exit; end; end; end; // else // if CUSTOMER_TYPE = CUSTOMER_CJONS then // begin // case GetFileType_r(pData.sDir + pData.sFName) of // 109, // 이거 뭔지 모르지만 GetFileTypeW_r()로 FED5 암호화파일에서 검출됨.. 25_0217 18:54:27 kku // 26, 103, 105, 106 : pData.State := resEnc; // end; // end; if CheckSign(sPath, @SIGN_SOFTCAMP_DRM[0], 7) then begin _Trace('HasContentInfo() .. SC DRM 적용됨. Path=%s', [sPath], 9); exit; end; if CheckSign(sPath, @SIG_DRM[1], Length(SIG_DRM)) then begin _Trace('HasContentInfo() .. BS DRM 적용됨. Path=%s', [sPath], 9); exit; end; ModePolify := GetModePolicy; OgnRecentFndList; // 일단.. 여기에 놓자 25_0325 09:14:49 kku if GetRecentFnd(sPath, REnt) then begin // WebEx는 동일경로 파일 3분동안 무시 25_0512 10:56:15 kku if (REnt.sMName <> '') and (CompareText(REnt.sMName, 'CiscoCollabHost.exe') = 0) then nTO := 180 else nTO := 2; if SecondsBetween(REnt.dtReg, Now) <= nTO then begin Result := REnt.bResult; exit; end; end; _Trace('HasContentInfo() .. Path=%s', [sPath], 4); DelRecentFnd(sPath); ZeroMemory(@REnt, SizeOf(REnt)); fileNameChk:= True; Guard(PatternEntList, TPatternEntList.Create); case aAppType of catOutlook : begin if sOutABPatterns_.Contains('scanoption') then SetPatternList(sOutABPatterns_, PatternEntList) else SetRuleToPtrnList(sOutABPatterns_, PatternEntList, true); nHitLimit := ModePolify.OutlookAB.ContentFilter.nHitLimit; end; catWebb : begin if sWebABPatterns_.Contains('scanoption') then SetPatternList(sWebABPatterns_, PatternEntList) else SetRuleToPtrnList(sWebABPatterns_, PatternEntList, true); nHitLimit := ModePolify.WebbAB.ContentFilter.nHitLimit; end; catFquirt : begin if BtcontentsFilter_list_.Contains('scanoption') then SetPatternList(BtcontentsFilter_list_, PatternEntList) else SetRuleToPtrnList(BtcontentsFilter_list_, PatternEntList, true); nHitLimit := 1; fileNameChk:= ModePolify.IntBtBlockNewFile.fileNameChk; end; catLINKENGKM : begin if UsbToUsbcontentsFilter_list_.Contains('scanoption') then SetPatternList(UsbToUsbcontentsFilter_list_, PatternEntList) else SetRuleToPtrnList(UsbToUsbcontentsFilter_list_, PatternEntList, true); nHitLimit := 1; fileNameChk:= ModePolify.IntUsbToUsbBlockNewFile.fileNameChk; end; catUsb : begin if UsbcontentsFilter_list_.Contains('scanoption') then SetPatternList(UsbcontentsFilter_list_, PatternEntList) else SetRuleToPtrnList(UsbcontentsFilter_list_, PatternEntList, true); nHitLimit := 1; fileNameChk:= ModePolify.IntUsbBlockNewFile.fileNameChk; end; catCdrom : begin if CdromcontentsFilter_list_.Contains('scanoption') then SetPatternList(CdromcontentsFilter_list_, PatternEntList) else SetRuleToPtrnList(CdromcontentsFilter_list_, PatternEntList, true); nHitLimit := 1; fileNameChk:= ModePolify.IntCdromBlockNewFile.fileNameChk; end; catMtp : begin if MtpcontentsFilter_list_.Contains('scanoption') then SetPatternList(MtpcontentsFilter_list_, PatternEntList) else SetRuleToPtrnList(MtpcontentsFilter_list_, PatternEntList, true); nHitLimit := 1; fileNameChk:= ModePolify.IntMtpBlockNewFile.fileNameChk; end; else begin if sEtcABPatterns_.Contains('scanoption') then SetPatternList(sEtcABPatterns_, PatternEntList) else SetRuleToPtrnList(sEtcABPatterns_, PatternEntList, true); nHitLimit := ModePolify.EtcAB.ContentFilter.nHitLimit; end; end; var unable : string; nLimitMB := ModePolify.CfLimitMB; if (nLimitMB > 0) and (GetFileSize_path(sPath) >= (LONGLONG(nLimitMB) * 1048576)) then begin Result:= true; sFounds := 'File size exceeded.'; sFoundsC := 'File size exceeded.'; end else if Pos(sExt, COMPRESS_EXTS) > 0 then begin Guard(ExtList, TStringList.Create); case aAppType of catOutlook : ; catWebb : SplitString(UpperCase(PrefModel_.WebAbExts), '|', ExtList); else SplitString(UpperCase(PrefModel_.EtcAbExts), '|', ExtList); end; nDecompDepth := 0; nUnzipDepth := ModePolify.CfZipDepth; sExportDir := GetRunExePathDir + 'STask\@etr2\'; Result := ProcessDecompFile(unable, fileNameChk, sPath, sExportDir, sFounds, sFoundsC, sPath, ExtractFileName(sPath)); DeleteDir(sExportDir, true, true); if unable <> '' then begin sFounds := unable; sFoundsC := unable; Result:= True; end; end else begin Result := FindContent(unable, fileNameChk, sPath, sFounds, sFoundsC); if unable <> '' then begin sFounds := unable; sFoundsC := unable; Result:= True; end; end; REnt.dtReg := Now; REnt.sMName := sMName; REnt.sPath := sPath; REnt.sFounds := sFounds; REnt.sFoundsC := sFoundsC; REnt.bResult := Result; REnt.curAppType := aAppType; AddRecentFnd(REnt); _Trace('HasContentInfo() .. OK, (%s), (%s), (%s)', [sPath, sFounds, sFoundsC], 4); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. HasContentInfo()'); end; end; function TManagerService.SendPrintImgFiles(sImgPath, sImgOutDir: String; nCollectMax: Integer = 0; aRespaction: TCampnRespaction = crtNone): String; var sFName, sCompId: String; i: Integer; begin Result := ''; try sImgOutDir := IncludeTrailingPathDelimiter(sImgOutDir); if not ForceDirectories(sImgOutDir) then exit; if (GetFileExt(sImgPath).ToUpper = 'PDF') and (CountFileExt(ExtractFilePath(sImgPath), ['png']) = 0) then begin var pdf: EM.PdfiumCore.TPdfDocument; Guard(pdf, EM.PdfiumCore.TPdfDocument.Create); pdf.LoadFromFile(sImgPath); var sOutPath: String := CutFileExt(sImgPath) + '_%.4d.png'; for i := 0 to pdf.PageCount - 1 do begin if (nCollectMax > 0) and ((i + 1) > nCollectMax) then break; if not PageToPng(pdf.Pages[i], Format(sOutPath, [i + 1]), 150) then break; end; end; if CountFileExt(ExtractFilePath(sImgPath), ['png']) > 0 then begin sFName := StringReplace(CutFileExt(sImgPath), '_0001', '', [rfReplaceAll]); // png에서 추가 분할된건 _0001이 붙을 수 있는데, 제거해준다 i := 1; while True do begin if (nCollectMax > 0) and (i > nCollectMax) then break; sImgPath := Format('%s_%.4d.png', [sFName, i]); if FileExists(sImgPath) then begin sFName := FormatDateTime('yymmddhhnnss_', Now) + ExtractFileName(sImgPath); if CopyFile(PChar(sImgPath), PChar(sImgOutDir + sFName), false) then begin sCompId := MakeComponentId(ExtractFileName(sImgPath)); SendFileNor(false, sCompId, 'printLogCollect.do', sImgOutDir + sFName, 0, 20, aRespaction); SumString(Result, sCompId, ';'); end; end else exit; Inc(i); end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. SendPrintImgFiles()'); end; end; function EmfToPng(const sEmfPath, sPngPath: string; nDPI: Integer = 96; aBackColor: TColor = clWhite): Boolean; var mf: TMetafile; bmp: TBitmap; png: TPngImage; nW, nH: Integer; begin Result := false; try if nDPI = 0 then nDPI := 96; Guard(mf, TMetafile.Create); mf.LoadFromFile(sEmfPath); // TMetafile.MMWidth/MMHeight는 0.01mm 단위 if (mf.MMWidth = 0) or (mf.MMHeight = 0) then exit; nW := MulDiv(mf.MMWidth, nDPI, 2540); // 2540 = 25.4(mm) * 100 nH := MulDiv(mf.MMHeight, nDPI, 2540); Guard(bmp, TBitmap.Create); bmp.SetSize(nW, nH); bmp.PixelFormat := pf24bit; bmp.Canvas.Brush.Color := aBackColor; bmp.Canvas.FillRect(Rect(0, 0, nW, nH)); // 간단히 벡터를 래스터로 그려 넣기 bmp.Canvas.StretchDraw(Rect(0, 0, nW, nH), mf); Guard(png, TPngImage.Create); png.Assign(bmp); png.SaveToFile(sPngPath); Result := true; except on E: Exception do ETgException.TraceException(E, 'Fail .. EmfToPng()'); end; end; // BS1OutlookAddIn_IMPL.pas에 똑같은거 있음. 변경 시 참고 function GetFileToSha1Str_BS1(sPath: String): String; var dtCreate, dtModify, dtAccess: TDateTime; begin if IsUseFastHash then begin if not GetFileDateTime_Local(sPath, dtCreate, dtModify, dtAccess) then begin dtCreate := 0; dtModify := 0; dtAccess := 0; end; sPath := FormatDateTime('yymmddhhnnss+', dtModify) + IntToStr(GetFileSize_path(sPath)); Result := ConvStrToSha1W(sPath); end else Result := GetFileToSha1Str(sPath); end; function TManagerService.SendPrintEmfFiles(sEmfDir, sImgOutDir: String; nCollectMax: Integer = 0; aRespaction: TCampnRespaction = crtNone): String; var sCompId, sImgPath: String; i: Integer; EmfList: TStringList; begin Result := ''; try sImgOutDir := IncludeTrailingPathDelimiter(sImgOutDir); if not ForceDirectories(sImgOutDir) then exit; sEmfDir := IncludeTrailingPathDelimiter(sEmfDir); Guard(EmfList, TStringList.Create); ExtrFilesFromDir(sEmfDir, EmfList, false, 'em1'); if EmfList.Count > 0 then begin EmfList.Sort; for i := 0 to EmfList.Count - 1 do begin if (nCollectMax > 0) and (i >= nCollectMax) then break; sImgPath := sImgOutDir + FormatDateTime('yymmddhhnnss_', Now) + Format('%s.png', [CutFileExt(EmfList[i]), i]); if EmfToPng(sEmfDir + EmfList[i], sImgPath, 200) then begin // {$IFDEF DEBUG} // if i = 0 then // begin // CopyFile(PChar(sImgPath), 'C:\Users\kku\Desktop\test.png', false); // CopyFile(PChar(sEmfDir + EmfList[i]), 'C:\Users\kku\Desktop\test.emf', false); // end; // {$ENDIF} sCompId := MakeComponentId(Format('%.4d', [i])); SendFileNor(false, sCompId, 'printLogCollect.do', sImgPath, 0, 20, aRespaction); SumString(Result, sCompId, ';'); end; end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. SendPrintImgFiles()'); end; end; function ExtrTextFromPrintImgFiles(sImgPath: String; aAngle: Extended = 0): String; var sFName, sTxt: String; i, nCnt: Integer; begin Result := ''; try try if GetFileExt(sImgPath).ToUpper = 'PDF' then begin var pdf: EM.PdfiumCore.TPdfDocument; Guard(pdf, EM.PdfiumCore.TPdfDocument.Create); pdf.LoadFromFile(sImgPath); var sOcr: String := GetRunExePathDir + DIR_CONF + EXE_OCR; var sOutPath: String := CutFileExt(sImgPath) + '_%.4d.png'; // var sTaskDir: String := sOcr[1] + ':\ProgramData\HE\Task\'; // if not ForceDirectories(sTaskDir) then // begin // TTgTrace.T('Fail .. ExtrTextFromPrintImgFiles() .. create taskDir ..', 1); // exit; // end; for i := 0 to pdf.PageCount - 1 do begin sFName := Format(sOutPath, [i + 1]); if PageToBitmap(pdf.Pages[i], sFName, 150) then begin sTxt := ExtrTextFromImage(sFName, aAngle); if sTxt <> '' then SumString(Result, sTxt, #13#10); SendMessage(gMgSvc.RcvHwnd, WM_POPUP_PRTW_PROGRESS, 0, i); end; end; end else begin // TTgTrace.T('ExtrTextFromPrintImgFiles() .. 1'); if FileExists(sImgPath) then begin sTxt := ExtrTextFromImage(sImgPath, aAngle); // if sTxt = '' then // begin // TTgTrace.T('ExtrTextFromPrintImgFiles() .. 1 .. Text empty'); // CopyFile(PChar(sImgPath), PChar('c:\test0.' + GetFileExt(sImgPath)), false); // end; SumString(Result, sTxt, #13#10); end; nCnt := CountFileExt(ExtractFilePath(sImgPath), ['png']); SendMessage(gMgSvc.RcvHwnd, WM_POPUP_PRINTWATER_PROGRESS, 5, nCnt); // TTgTrace.T('ExtrTextFromPrintImgFiles() .. 2'); sFName := CutFileExt(sImgPath); i := 1; while True do begin sImgPath := Format('%s_%.4d.png', [sFName, i]); if FileExists(sImgPath) then begin sTxt := ExtrTextFromImage(sImgPath, aAngle); // if sTxt = '' then // begin // TTgTrace.T('ExtrTextFromPrintImgFiles() .. 2 .. Text empty'); // CopyFile(PChar(sImgPath), PChar(Format('c:\test%d.', [i]) + GetFileExt(sImgPath)), false); // end; SumString(Result, sTxt, #13#10); SendMessage(gMgSvc.RcvHwnd, WM_POPUP_PRINTWATER_PROGRESS, 6, i); SendMessage(gMgSvc.RcvHwnd, WM_POPUP_PRTW_PROGRESS, 0, i); end else exit; Inc(i); end; end; finally SendMessage(gMgSvc.RcvHwnd, WM_POPUP_PRINTWATER_PROGRESS, 0, 0); if Result <> '' then begin case CUSTOMER_TYPE of CUSTOMER_SHCI, CUSTOMER_SHSC : Result := StrsReplace(Result, ['01 ', '11 ', '21 ', '31 ', '41 ', '51 ', '61 ', '71 ', '81 ', '91 '], ['01', '11', '21', '31', '41', '51', '61', '71', '81', '91']); end; end; end; except on E: Exception do ETgException.TraceException(E, 'Fail .. ExtrTextFromPrintImgFiles()'); end; end; function ExtrTextFromPrintEmfFiles(sEmfDir: String; aAngle: Extended = 0): String; var sTxt, sImgPath: String; i: Integer; EmfList: TStringList; nDPI: Integer; begin Result := ''; try try Guard(EmfList, TStringList.Create); ExtrFilesFromDir(sEmfDir, EmfList, false, 'em1'); SendMessage(gMgSvc.RcvHwnd, WM_POPUP_PRINTWATER_PROGRESS, 5, EmfList.Count); EmfList.Sort; nDPI := gMgSvc.PrefModel_.PrtDPI; for i := 0 to EmfList.Count - 1 do begin sImgPath := sEmfDir + CutFileExt(EmfList[i]) + '.png'; if EmfToPng(sEmfDir + EmfList[i], sImgPath, nDPI) then begin sTxt := ExtrTextFromImage(sImgPath, aAngle); SumString(Result, sTxt, #13#10); DeleteFile(PChar(sImgPath)); SendMessage(gMgSvc.RcvHwnd, WM_POPUP_PRINTWATER_PROGRESS, 6, i); SendMessage(gMgSvc.RcvHwnd, WM_POPUP_PRTW_PROGRESS, 0, i); end; end; finally SendMessage(gMgSvc.RcvHwnd, WM_POPUP_PRINTWATER_PROGRESS, 0, 0); if Result <> '' then begin case CUSTOMER_TYPE of CUSTOMER_SHCI, CUSTOMER_SHSC : Result := StrsReplace(Result, ['01 ', '11 ', '21 ', '31 ', '41 ', '51 ', '61 ', '71 ', '81 ', '91 '], ['01', '11', '21', '31', '41', '51', '61', '71', '81', '91']); end; end; end; except on E: Exception do ETgException.TraceException(E, 'Fail .. ExtrTextFromPrintImgFiles()'); end; end; //procedure TManagerService.SendPrintLog(sCode, sPrtName, sDoc, sExtrTxt, // sExtrOcrTxt, sDocPath, sThumbIds: String; OVio: ISuperObject); //var // O, OSub: ISuperObject; // sCompId: String; // sMsg: String; //begin // try // sMsg := Format('Printer : %s, Document : %s', [sPrtName, sDoc]); // // _Trace('SendPrintLog > Code=%s, Msg=%s', [sCode, sMsg], 3); // // O := SO; // if sCode = LOGCODE_EVENT_PRINTER then // O.S['TYP_MSG'] := '@(!)_IC_M' // else // O.S['TYP_MSG'] := '@(!)_IC_P'; // O.S['KEY_AGENTID'] := sAgentId_; // O.S['KEY_EMPNO'] := sEmpNo_; // O.S['KEY_HOSTNAME'] := sUserName_; // O.S['KEY_SUBMITTIME'] := FormatDateTime('yyyy-mm-dd hh:nn:ss', Now); // O.S['KEY_LOGCODE'] := sCode; // O.S['DETECTION_DATE'] := O.S['KEY_SUBMITTIME']; // 이벤트 발생 시각. REQUEST의 경우, 예외 신청할 이벤트의 발생 시각 // O.S['KEY_SUMMARY'] := sMsg; //// O.S['PARENT_LA_ID'] // 상위 이벤트 // O.S['POLICY_ID'] := GetModePolicy.PolicyId; //// O.S['POLICY_KEY'] // 정책 위반한 경우 (PREVENT, MONITOR), 위반한 정책의 정책 키 값, 수집인 경우 (DEPLOY), 수집 요청 ID // if GetModePolicy.Print.bCollectOutput then // begin // O.S['MESSAGE_BODY'] := sExtrTxt; // 정책 위반한 경우 (PREVENT, MONITOR), 원문 (본문) 컨텐츠, 수집인 경우 (DEPLOY), 수집 결과 내용, 원문 수집 정책이 비활성화인경우 수집하지 않음 // O.S['OCR_BODY'] := sExtrOcrTxt; // 이미지 OCR 추출된 컨텐츠, 원문 수집 정책이 비활성화인 경우 수집하지 않음 // end; // // if OVio <> nil then // O.O['RULE_VIOLATED'] := OVio; // 정책 위반 규칙과 위반 개수. (LIST) // // if GetModePolicy.Print.bCollectFile and FileExists(sDocPath) then // begin // sCompId := MakeComponentId(ExtractFileName(sDocPath)); // SendFile(sCompId, 'printLogCollect.do', sDocPath); // // O.S['COMPONENT_ID'] := sCompId; // 파일 고유값. 에이전트에서 임의 생성. (이벤트간 동일 파일 판단은 서버에서 하겠습니다.) // O.S['COMPONENT_FILENAME'] := ExtractFileName(sDocPath); // 파일명 // O.S['COMPONENT_PATH'] := ExtractFilePath(sDocPath);// 파일 절대 경로 //// O.S['COMPONENT_METADATA'] //// O.S['COMPONENT_LASTACCESS'] // 파일 최종 접근 일시 // end; // // O.S['COMPONENT_THUMBNAIL_ID'] := sThumbIds; // 이미지 미리보기 혹은 이미지가 있는경우, 이미지 파일의 파일 고유값. (출력물의 경우 첫 3장 이미지, 캡쳐 이미지 등), 복수개 허용, ";" 구분 //// O.S['SOURCE_IP'] // 이벤트 발생 시점의 에이전트 IP. 단, 외부에서 수신하는 이벤트의 경우, 발송지의 IP가 되고, DESTINATION_URL이 에이전트 IP가 된다 //// O.S['SOURCE_PORT'] // 송신지 사용 포트 //// O.S['EMAIL_SENDER'] // 메일 발신자 //// O.S['DESTINATION_URL'] // 수신지 URL (혹은 IP) //// O.S['DESTINATION_PORT'] // 수신지 포트 //// O.S['EMAIL_RECIPIENT'] // 메일 수신자 ; 로 구분 //// O.S['EMAIL_SUBJECT'] // 메일 제목 // O.S['APPLICATION_NAME'] := sPName; // 사용 APP 이름 // O.S['APPLICATION_PATH'] := sPPath;// 사용 APP 절대 경로 (실행 파일 exe의 절대 경로) // O.S['PRINTER_JOBNAME'] := Job.Document; // OSub := SO; // OSub.S['PAGEINFO'] := Format('%d/%d', [PrtInfo.dwTotalPage, PrtInfo.dwTotalPage]); // OSub.S['COLOR'] := BooleanToStr(PrtInfo.bColor, 'true', 'false'); // OSub.S['WARTERMARK'] := BooleanToStr(bWaterMark, 'true', 'false'); // OSub.S['PAPERINFO'] := PrtInfo.sPaperInfo; // O.O['PRINTER_METADATA'] := OSub; // '{"PAGEINFO": "2/2", "COLOR": "true", "WARTERMARK": "false"}'; // O.S['REMOVABLE_NAME'] := Job.PrinterName; // USB등과 같은 매체 혹은 프린터 등과 같은 외부 장치 이름 //// O.S['REMOVABLE_DEVICEID'] := aExptInfo.sSerial; // USB등과 같은 매체 혹은 프린터 등과 같은 외부 장치 Device ID //// O.S['DEVICE_TYPE'] := IntToStr(Integer(aExptInfo.ReqDevType)); // 의미 없어서 제외 23_0822 12:40:55 kku //// O.S['REMOVABLE_CLASSID'] // USB등과 같은 매체 혹은 프린터 등과 같은 외부 장치 Class ID //// O.S['RESPONSE_INFO'] // 적용된 대응 정보 (DELETE, DRM, POPUP, LOG, EXCEPT 등) //// O.S['RESPONSE_RESULT'] // 적용된 대응 적용 결과 (true / false / pending / decline) //// O.S['REQUEST_COMMENT'] := sComment; // 사용자가 기입하는 요청 코멘트 //// O.S['REQUEST_DUEDATE'] := sDueDate; // 사용자가 기입하는 예외 기간 (언제 까지. 최종일) //// O.S['REQUEST_TARGET'] := IntToStr(nTarget); // 사용자가 기입하는 예외 대상 (0 - 해당 pc, 1 - 해당 사용자, 2 - 해당 부서, 3-전체) // // gMgSvc.EventLog.Push(O.AsJSon); // except // on E: Exception do // ETgException.TraceException(Self, E, 'Fail .. SendEventLog()'); // end; //end; procedure SetPrtJobFromHelperApp(aJob: TPrtJobInfo; dwCmd: DWORD); var sHpExe, sPrtName: String; begin // sPrtName := aJob.PrinterName; // if sPrtName = '' then // begin // var PrtInfo: TPrtJobDevInfo; // aJob.GetJobDevInfo(PrtInfo); // sPrtName := PrtInfo.sPtrName; // end; // // var hPrt: THandle := 0; // if OpenPrinter(PChar(sPrtName), hPrt, nil) then // SetJob(hPrt, aJob.ID, 0, nil, dwCmd); // // if (dwCmd = JOB_CONTROL_PAUSE) and ((aJob.Status and JOB_STATUS_SPOOLING) <> 0) then // aJob.IsCustomPause := true; // // exit; try TTgTrace.T('SetPrtJobFromHelperApp() .. cmd=%d', [dwCmd], 1); sHpExe := GetRunExePathDir + DIR_CONF + EXE_HP; if FileExists(sHpExe) then begin sPrtName := aJob.PrinterName; if sPrtName = '' then begin var PrtInfo: TPrtJobDevInfo; aJob.GetJobDevInfo(PrtInfo); sPrtName := PrtInfo.sPtrName; end; {$IFDEF DEBUG} ExecuteApp(sHpExe, Format('-pjob "%s" -c %d -j %d', [sPrtName, dwCmd, aJob.ID]), SW_SHOWNORMAL); {$ELSE} ExecuteAppAsUser('explorer.exe', sHpExe, Format('-pjob "%s" -c %d -j %d', [sPrtName, dwCmd, aJob.ID]), SW_SHOWNORMAL); {$ENDIF} if not aJob.WorkEnd and (dwCmd = JOB_CONTROL_PAUSE) and ((aJob.Status and JOB_STATUS_SPOOLING) <> 0) then begin aJob.IsCustomPause := true; TTgTrace.T('SetPrtJobFromHelperApp() .. cmd=%d .. CustomPause', [dwCmd], 1); end; end; except on E: Exception do ETgException.TraceException(E, 'Fail SetPrtJobFromHelperApp()'); end; end; procedure TManagerService.OnPtrJobNotify(Sender: TThdPrtSpoolWatch; Job: TPrtJobInfo); begin try if Job.WorkEnd then exit; if not Job.IsCustomPause and Job.IsSpooling then begin if bIgrPrtPause_ then exit; if (Job.Document <> '') and Job.Document.Contains(' *BSOne') then begin // 보안 출력중이면 그냥 통과 25_0522 16:22:54 kku // exit; end else begin // SetPrtJobFromHelperApp(Job, JOB_CONTROL_PAUSE); Job.PausePrtJob; end; exit; end; if Job.IsCustomPause then begin if (Job.Document <> '') and Job.Document.Contains(' *BSOne') then begin // SetPrtJobFromHelperApp(Job, JOB_CONTROL_RESUME); Job.ResumePrtJob; exit; end; if ThdPrintWork_ <> nil then begin if ThdPrintWork_.HasJob(Job) then exit; if ThdPrintWork_.IsWorking then begin // _Trace('보안출력 중 새로운 출력 감지 .. 차단. Printer=%s, Doc=%s', [Job.PrinterName, Job.Document], 2); // CancelJob; // HEC에서 스풀을 두번 생성해서 처리하는 현상 확인됨. 25_0714 09:31:43 kku // 이유는 모르겠는데 복합기 드라이버에서 그렇게 처리하는거 같음 (롯데 캐논) _Trace('보안출력 중 새로운 출력 감지 .. 무시. Printer=%s, Doc=%s', [Job.PrinterName, Job.Document], 2); exit; end else if not Job.WorkEnd then begin Job.Wnd := GetForegroundWindow; // Job.PID := GetProcessPIDFromWndHandle(Job.Wnd); // Job.PName := GetProcessNameByPid(Job.PID); ThdPrintWork_.AddJob(Job); end; end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. OnPtrJobNotify()'); end; end; procedure TManagerService.OnCapAppNotify(aSender: TThdProcessWatch; pEnt: PPwEnt; aKind: TProcessWatchKind); var CapAppMonKind: TCapAppMonKind; PO: TPrefModel; begin try case aKind of pwkUnknown : _Trace('OnCapAppNotify() .. Unknown'); pwkInit, pwkExecute : begin if CapAppList_.IndexOf(pEnt.sPName) <> -1 then begin PO := GetModePolicy; if bForceScreenCapAppBlock_ then begin if IsNewApi then begin var IgrAppList: TStringList; Guard(IgrAppList, TStringList.Create); IgrAppList.CaseSensitive := false; SplitString(PO.IgrCaptureApps, '|', IgrAppList); if IgrAppList.IndexOf(pEnt.sPName) = -1 then begin TerminateProcessByPid(pEnt.dwPid); if PO.IsNotiBCA then PopupMessage(TYPE_MSG_PREVENT_CAPAPP, pEnt.sPName + '|PV'); SendEventLog(URI_USER_ACTION, PREVENT_CAPTURE_APP, 'Software Blocked : ' + pEnt.sPName); end else SendEventLog(URI_USER_ACTION, MONITOR_CAPTURE_APP, 'Software Detected : ' + pEnt.sPName, false); end else begin TerminateProcessByPid(pEnt.dwPid); if PO.IsNotiBCA then PopupMessage(TYPE_MSG_PREVENT_CAPAPP, pEnt.sPName + '|PV'); SendEventLog(URI_USER_ACTION, PREVENT_CAPTURE_APP, 'Software Blocked : ' + pEnt.sPName); end; exit; end; CapAppMonKind := PO.CapAppMonKind; case CapAppMonKind of camBlockAll : begin TerminateProcessByPid(pEnt.dwPid); if PO.IsNotiBCA then PopupMessage(TYPE_MSG_PREVENT_CAPAPP, pEnt.sPName + '|PV'); SendEventLog(URI_USER_ACTION, PREVENT_CAPTURE_APP, 'Software Blocked : ' + pEnt.sPName); end; camIncAllow : begin var IgrAppList: TStringList; Guard(IgrAppList, TStringList.Create); IgrAppList.CaseSensitive := false; SplitString(PO.IgrCaptureApps, '|', IgrAppList); if IgrAppList.IndexOf(pEnt.sPName) = -1 then begin TerminateProcessByPid(pEnt.dwPid); if PO.IsNotiBCA then PopupMessage(TYPE_MSG_PREVENT_CAPAPP, pEnt.sPName + '|PV'); SendEventLog(URI_USER_ACTION, PREVENT_CAPTURE_APP, 'Software Blocked : ' + pEnt.sPName); end else SendEventLog(URI_USER_ACTION, MONITOR_CAPTURE_APP, 'Software Detected : ' + pEnt.sPName, false); end; camLog, camPopup : begin if (CapAppMonKind = camPopup) or PO.IsNotiBCA then PopupMessage(TYPE_MSG_PREVENT_CAPAPP, pEnt.sPName); SendEventLog(URI_USER_ACTION, MONITOR_CAPTURE_APP, 'Software Detected : ' + pEnt.sPName, false); end; end; end; end; pwkTerminated : ; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. OnCapAppNotify()'); end; end; procedure TManagerService.OnBlockAppNotify(aSender: TThdProcessWatch; pEnt: PPwEnt; aKind: TProcessWatchKind); var PO: TPrefModel; bBlock, bChkBlackApp: Boolean; dtNow: TDateTime; sPath: String; procedure SendMonAppLog(bExecute: Boolean); var LogInfo: TLogInfo; begin ZeroMemory(@LogInfo, SizeOf(LogInfo)); sPath := GetProcessPathByPid(pEnt.dwPid); LogInfo.sAppName := pEnt.sPName; LogInfo.sAppPath := ExtractFilePath(sPath); LogInfo.sPath := sPath; if bExecute then begin LogInfo.sCode := MONITOR_SOFTWARE;//EXECUTE_APP; LogInfo.sSummary := pEnt.sPName + ' executed.'; end else begin LogInfo.sCode := MONITOR_SOFTWARE;//TERMINATE_APP; LogInfo.sSummary := pEnt.sPName + ' terminated.'; end; gMgSvc.SendEventLogEx(@LogInfo, false); if ModePolicy.IsMonAppNoti then begin var O: ISuperObject; O := SO; O.S['PName'] := pEnt.sPName; O.B['E'] := bExecute; PopupMessage(TYPE_MSG_MONITOR_APP, O.AsJSon); end; end; begin try case aKind of pwkUnknown : _Trace('OnBlockAppNotify() .. Unknown'); pwkInit, pwkExecute : begin if aKind <> pwkInit then begin _Trace('APP 실행됨. PName=%s', [pEnt.sPName], 100); if bIsMonApp_ and (MonAppList_.IndexOf(pEnt.sPName) <> -1) then SendMonAppLog(true); end; bBlock := bIsBlockApp_ and (BlockAppList_.IndexOf(pEnt.sPName) <> -1); if not bBlock and (BlockAppWList_.Count > 0) then begin var i: Integer; for i := 0 to BlockAppWList_.Count - 1 do begin if MatchesMask(pEnt.sPName, BlockAppWList_[i]) then begin bBlock := true; break; end; end; end; if bBlock then begin PO := GetModePolicy; bChkBlackApp := true; dtNow := Now; // for Test // gMgSvc.ModePolicy.AppBlackDateB := StrToDateDef('2022-08-22', 0); // if gMgSvc.ModePolicy.AppBlackDateB <> 0 then // gMgSvc.ModePolicy.AppBlackDateB := AppendTime(gMgSvc.ModePolicy.AppBlackDateB, 0, 0, 0, 0); // gMgSvc.ModePolicy.AppBlackDateE := StrToDateDef('2022-08-23', 0); // if gMgSvc.ModePolicy.AppBlackDateE <> 0 then // gMgSvc.ModePolicy.AppBlackDateE := AppendTime(gMgSvc.ModePolicy.AppBlackDateE, 23, 59, 59, 0); if PO.IsAppBlackDate then begin bChkBlackApp := (CompareDateTime(PO.AppBlackDateB, dtNow) = -1 ) and (CompareDateTime(PO.AppBlackDateE, dtNow) = 1); end; if bChkBlackApp and PO.IsAppBlackTime then begin var wHour, wMin, wSec, wMSec: WORD; DecodeTime(dtNow, wHour, wMin, wSec, wMSec); if PO.AppBlackTimeB <= PO.AppBlackTimeE then bChkBlackApp := (PO.AppBlackTimeB <= wHour) and (PO.AppBlackTimeE >= wHour) else bChkBlackApp := (PO.AppBlackTimeB <= wHour) or (PO.AppBlackTimeE > wHour); end; if bChkBlackApp then begin sPath := GetProcessPathByPid(pEnt.dwPid); if not PO.IsBlockAppLog then TerminateProcessByName(pEnt.sPName); if PO.IsBlockAppNotice then gMgSvc.PopupMessage(TYPE_MSG_PREVENT_BLACKAPP, pEnt.sPName + BooleanToStr(PO.IsBlockAppLog, '', '|PV')); if gMgSvc.IsNewApi then begin var LogInfo: TLogInfo; ZeroMemory(@LogInfo, SizeOf(LogInfo)); LogInfo.sAppName := pEnt.sPName; LogInfo.sAppPath := ExtractFilePath(sPath); LogInfo.sPath := sPath; if PO.IsBlockAppLog then begin LogInfo.sCode := MONITOR_SOFTWARE; LogInfo.sSummary := 'Software Execute : ' + pEnt.sPName; end else begin LogInfo.sCode := LOGCODE_PREVENT_SOFTWARE; LogInfo.sSummary := 'Software Blocked : ' + pEnt.sPName; end; gMgSvc.SendEventLogEx(@LogInfo, not PO.IsBlockAppLog); end else gMgSvc.SendEventLog(URI_USER_ACTION, LOGCODE_PREVENT_SOFTWARE, 'Software Blocked : ' + pEnt.sPName); _Trace('Block App .. Name="%s"', [pEnt.sPName]); end; end; end; pwkTerminated : begin _Trace('APP 종료됨. PName=%s', [pEnt.sPName], 100); // if bIsMonApp_ and (MonAppList_.IndexOf(pEnt.sPName) <> -1) then // SendMonAppLog(false); end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. OnBlockAppNotify()'); end; end; function TManagerService.RecentUserSid: String; begin if sRecentUserSid_ = '' then sRecentUserSid_ := GetRegRecentUserSid; Result := sRecentUserSid_; if not ExistsKey(HKEY_USERS, sRecentUserSid_) then begin _Trace('현재 사용자 Sid를 찾을 수 없음 .. Sid=%s', [sRecentUserSid_], 2); sRecentUserSid_ := ''; end; end; procedure TManagerService.ChangeDestinationUrl; begin try Inc(nDestSvrIdx_); if (nDestSvrIdx_ < 99999) and (CUSTOMER_TYPE = CUSTOMER_HDENG) then // 초기화 직후에는 무시 25_1016 19:24:49 kku begin // 보안모드 조건이 IP조건이고, PC가 내부망 IP를 사용중일때 내부망만 접속 시도, // 내부망 IP가 아니면 DMZ 만 접속 시도록하도록 기능 추가 // 보안모드 조건이 IP 조건이 아닐 경우 기존 처럼 동작 25_0911 20:31:18 kku if PrefModel.VpnMethod.Contains('ip') then begin if bIsRouterOn_ then nDestSvrIdx_ := 0 // 내부망 else nDestSvrIdx_ := 1; // DMZ망 end; end; if nDestSvrIdx_ >= ServerUrlList_.Count then nDestSvrIdx_ := 0; sDestSvrUrl_ := ServerUrlList_[nDestSvrIdx_]; if (Pos(sDestSvrUrl_, 'https://') <> 1) and (Pos(sDestSvrUrl_, 'http://') <> 1) then begin sDestSvrUrl_ := StrsReplace(sDestSvrUrl_, ['/'], ''); var sIp: String; var nPort: Integer; if ExtractIPPort(sDestSvrUrl_, sIp, nPort) then sDestSvrUrl_ := Format('https://%s:%d/agentLogRequests.do', [sIp, nPort]) else if IsValidIP(sDestSvrUrl_) then sDestSvrUrl_ := Format('https://%s:443/agentLogRequests.do', [sDestSvrUrl_]) else sDestSvrUrl_ := ServerUrlList_[nDestSvrIdx_]; end; sDestIPort_ := StringReplace(sDestSvrUrl_, 'agentLogRequest.do', '', [rfReplaceAll]); sDestIPort_ := StringReplace(sDestIPort_, 'agentLogRequests.do', '', [rfReplaceAll]); // bSSLCouldNotLoad_ := false; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. ChangeDestinationUrl()'); end; end; procedure TManagerService.DoClipboardUpdate; begin bDoCbUpdate_ := true; end; // 삭제, 업데이트를 위해 안전한 종료를 위해 추가 23_0331 09:14:05 kku procedure TManagerService.StopService; begin ThdTaskTimer_.StopTimerThread; ThdStatusTimer_.StopTimerThread; if MgHook_ <> nil then FreeAndNil(MgHook_); if FltCtrl_ <> nil then FltCtrl_.Cleanup; end; procedure TManagerService.SetRouterOn(bVal: Boolean); begin bIsRouterOn_ := bVal; end; procedure TManagerService.SetVpnNicOn(bVal: Boolean); begin bIsVpnNicOn_ := bVal; end; procedure TManagerService.SetPatchUpdate(bIsUptoDate: Boolean); var nTerm: Integer; begin // 네트워크 통신이 안되는 상태에서 sData가 무조건 'true'가 된다. // 그래서 보완 하기 위해 서버와 접속중이 아니거나 // 접속 후 5초 이내는 결과를 무시한다. 22_1025 17:39:57 kku // (접속 후 5초 안에 나온 결과값은 무조건 'true' 때문에 무시해야한다.) // MG.exe에서 HE.exe로 업데이트 기능 옮긴 후 15초에서 5초로 변경 22_1124 15:36:18 kku if (dtConnected_ = 0) or (bIsUptoDate and (SecondsBetween(Now, dtConnected_) < 5)) then exit; if bIsPatchUptoDate_ <> bIsUptoDate then begin nTerm := GetOsPatchCheckTerm; if nTerm > 0 then begin // 1주에 한번 패치체크 추가 22_0609 08:52:21 kku if (AgentModel_.LastOsPatchDT = 0) or (DaysBetween(AgentModel_.LastOsPatchDT, Now) >= nTerm) then begin bIsPatchUptoDate_ := bIsUptoDate; if bIsPatchUptoDate_ then begin AgentModel_.LastOsPatchDT := Now; AgentModel_.Save; end; end else bIsPatchUptoDate_ := true; end else bIsPatchUptoDate_ := bIsUptoDate; end; end; procedure TManagerService.SetServiceAvailable(bVal: Boolean); begin bIsServiceAvailable_ := bVal; end; procedure TManagerService.SetTemporaryConn(bVal: Boolean); begin Lock; try if bIsTemporaryConn_ = bVal then exit; bIsTemporaryConn_ := bVal; finally Unlock; end; if bVal then begin if VulService_ <> nil then VulService_.CallPopup(true); dwTempConnBegin_ := GetTickCount; PopupMessage(TYPE_MSG_PREVENT_TEMPCONN); end else dwTempConnBegin_ := 0; end; //procedure TManagerService.SetNexgVpnRegistered(bVal: Boolean); //begin // bIsNexgVpnRegistered_ := bVal; //end; procedure TManagerService.SetNetworkPrevent(bVal: Boolean); begin bIsNetworkPrevent_ := bVal; end; procedure TManagerService.SetNetworkPreventVal(sVal: String); begin sNetworkPreventValue_ := sVal; end; procedure TManagerService.SetNetworkExceptVal(sVal: String); begin sNetworkExceptValue_ := sVal; end; procedure TManagerService.SetNetworkPreventType(sVal: String); begin sNetworkPreventType_ := sVal; end; procedure TManagerService.SetExtraPort(sVal: String); begin sExtraPort_ := sVal; end; procedure TManagerService.SetRecentPrintDocName(sVal: String); begin sRecentPrintDocName_ := sVal; end; procedure TManagerService.AddPrtHookJob(aO: ISuperObject); begin try _Trace('AddPrtHookJob() ..', 2); if aO.S['DocName'] = '' then exit; if aO.S['PName'] = '' then exit; if ThdPrintWork_ <> nil then ThdPrintWork_.AddHookJob(aO.S['PName'], aO.S['PrtName'], aO.S['DocName'], aO.S['PrtDocId'], aO.I['PID']); _Trace('AddPrtHookJob() .. OK', 2); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. AddPrtHookJob()'); end; end; procedure TManagerService.UpdateAgentInfo; begin sEmpNo_ := AgentModel_.EmpNo; // sVpnId_ := AgentModel_.VpnInfo; sAgentId_ := GetAgentId(sEmpNo_); sUName_ := AgentModel_.UName; sEmail_ := AgentModel_.Email; sDeptName_ := AgentModel_.DeptName; end; procedure TManagerService.SendEventLog(sUri, sCode, sMsg: String; bPrevent: Boolean = true); var O: ISuperObject; dt: TDateTime; begin try // 접속상태 체크하지 않음 22_0908 07:47:44 kku // 이렇게 하면 서버 통신 안될때 굉장히 버벅된다 (알림팝업등) // if not Connected then // Sleep(3000); if sAgentId_ = '' then exit; if ThdEvent_ = nil then exit; _Trace('SendEventLog > Uri=%s, Code=%s, Msg=%s', [sUri, sCode, sMsg], 3); dt := Now; O := SO; if bIsNewApi_ then begin if bPrevent then O.S['TYP_MSG'] := '@(!)_IC_P' else O.S['TYP_MSG'] := '@(!)_IC_M'; O.S['KEY_AGENTID'] := sAgentId_; O.S['KEY_EMPNO'] := sEmpNo_; O.S['KEY_ACCOUNT'] := sAccount_; if IsUseHostNameOnly then O.S['KEY_HOSTNAME'] := sComName_ else O.S['KEY_HOSTNAME'] := sUserName_; O.S['KEY_SUBMITTIME'] := FormatDateTime('yyyy-mm-dd hh:nn:ss', dt); O.S['key_submitTime'] := FormatDateTime('yyyy-MM-dd"T"hh:nn:ss.zzz', dt) + sUtcOffset_; O.S['KEY_LOGCODE'] := sCode; O.S['DETECTION_DATE'] := O.S['KEY_SUBMITTIME']; // 이벤트 발생 시각. REQUEST의 경우, 예외 신청할 이벤트의 발생 시각 O.S['detectionDate'] := O.S['key_submitTime']; // 이벤트 발생 시각. REQUEST의 경우, 예외 신청할 이벤트의 발생 시각 O.S['KEY_SUMMARY'] := sMsg; // O.S['PARENT_LA_ID'] // 상위 이벤트 O.S['POLICY_ID'] := GetModePolicy.PolicyId; // O.['attachList'] := '' // O.S['POLICY_KEY'] // 정책 위반한 경우 (PREVENT, MONITOR), 위반한 정책의 정책 키 값, 수집인 경우 (DEPLOY), 수집 요청 ID // O.S['MESSAGE_BODY'] // 정책 위반한 경우 (PREVENT, MONITOR), 원문 (본문) 컨텐츠, 수집인 경우 (DEPLOY), 수집 결과 내용, 원문 수집 정책이 비활성화인경우 수집하지 않음 // O.S['OCR_BODY'] // 이미지 OCR 추출된 컨텐츠, 원문 수집 정책이 비활성화인 경우 수집하지 않음 // O.S['RULE_VIOLATED'] // 정책 위반 규칙과 위반 개수. (LIST) // O.S['COMPONENT_ID'] // 파일 고유값. 에이전트에서 임의 생성. (이벤트간 동일 파일 판단은 서버에서 하겠습니다.) // O.S['COMPONENT_FILENAME'] // 파일명 // O.S['COMPONENT_PATH'] // 파일 절대 경로 // O.S['COMPONENT_METADATA'] // O.S['COMPONENT_LASTACCESS'] // 파일 최종 접근 일시 // O.S['COMPONENT_THUMBNAIL_ID'] // 이미지 미리보기 혹은 이미지가 있는경우, 이미지 파일의 파일 고유값. (출력물의 경우 첫 3장 이미지, 캡쳐 이미지 등), 복수개 허용, ";" 구분 // O.S['SOURCE_IP'] // 이벤트 발생 시점의 에이전트 IP. 단, 외부에서 수신하는 이벤트의 경우, 발송지의 IP가 되고, DESTINATION_URL이 에이전트 IP가 된다 // O.S['SOURCE_PORT'] // 송신지 사용 포트 // O.S['EMAIL_SENDER'] // 메일 발신자 // O.S['DESTINATION_URL'] // 수신지 URL (혹은 IP) // O.S['DESTINATION_PORT'] // 수신지 포트 // O.S['EMAIL_RECIPIENT'] // 메일 수신자 ; 로 구분 // O.S['EMAIL_SUBJECT'] // 메일 제목 // O.S['APPLICATION_NAME'] // 사용 APP 이름 // O.S['APPLICATION_PATH'] // 사용 APP 절대 경로 (실행 파일 exe의 절대 경로) // O.S['PRINTER_JOBNAME'] // 프린터 잡 이름 // O.S['PRINTER_METADATA'] // O.S['REMOVABLE_NAME'] // USB등과 같은 매체 혹은 프린터 등과 같은 외부 장치 이름 // O.S['REMOVABLE_DEVICEID'] // USB등과 같은 매체 혹은 프린터 등과 같은 외부 장치 Device ID // O.S['REMOVABLE_CLASSID'] // USB등과 같은 매체 혹은 프린터 등과 같은 외부 장치 Class ID // O.S['RESPONSE_INFO'] // 적용된 대응 정보 (DELETE, DRM, POPUP, LOG, EXCEPT 등) // O.S['RESPONSE_RESULT'] // 적용된 대응 적용 결과 (true / false / pending / decline) // O.S['REQUEST_COMMENT'] // 사용자가 기입하는 요청 코멘트 // O.S['REQUEST_DUEDATE'] // 사용자가 기입하는 예외 기간 (언제 까지. 최종일) // O.S['REQUEST_TARGET'] // 사용자가 기입하는 예외 대상 (0 - 해당 pc, 1 - 해당 사용자, 2 - 해당 부서, 3-전체) end else begin O.S['MODEL_ID'] := sAgentId_; O.S['TOCSG_LA_IFNAME'] := sUri; O.S['TOCSG_LA_ID'] := sAgentId_; O.S['TOCSG_LA_EMPID'] := sEmpNo_; O.S['TOCSG_LA_CODE'] := sCode; O.S['TOCSG_LA_DATA'] := sMsg; if IsUseHostNameOnly then O.S['TOCSG_LA_HOSTNAME'] := sComName_ else O.S['TOCSG_LA_HOSTNAME'] := sUserName_; O.S['TOCSG_LA_LASTCONNDATE'] := FormatDateTime('yyyy-mm-dd hh:nn:ss', Now); if NicService_ <> nil then begin O.S['TOCSG_LA_MACADDR'] := NicService_.GetIP; O.S['TOCSG_LA_REMOTEIP'] := NicService_.GetMAC; end else begin O.S['TOCSG_LA_MACADDR'] := 'ip'; O.S['TOCSG_LA_REMOTEIP'] := 'mac'; end; end; ThdEvent_.Push(O.AsString); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. SendEventLog()'); end; end; procedure TManagerService.SendEventLogEx(pInfo: PLogInfo; bPrevent: Boolean = true; dtLog: TDateTime = 0); var PO: TPrefModel; O: ISuperObject; dt: TDateTime; begin try // 접속상태 체크하지 않음 22_0908 07:47:44 kku // 이렇게 하면 서버 통신 안될때 굉장히 버벅된다 (알림팝업등) // if not Connected then // Sleep(3000); if sAgentId_ = '' then exit; if ThdEvent_ = nil then exit; _Trace('SendEventLogEx > Code=%s, Summary=%s', [pInfo.sCode, pInfo.sSummary], 3); PO := GetModePolicy; if (pInfo.sCode = LOGCODE_PREVENT_FILEMONITOR) and PO.FileMonNoLog then exit; if dtLog <> 0 then dt := dtLog else dt := Now; O := SO; if bIsNewApi_ then begin if bPrevent then O.S['TYP_MSG'] := '@(!)_IC_P' else O.S['TYP_MSG'] := '@(!)_IC_M'; O.S['KEY_AGENTID'] := sAgentId_; O.S['KEY_EMPNO'] := sEmpNo_; O.S['KEY_ACCOUNT'] := sAccount_; if IsUseHostNameOnly then O.S['KEY_HOSTNAME'] := sComName_ else O.S['KEY_HOSTNAME'] := sUserName_; O.S['KEY_SUBMITTIME'] := FormatDateTime('yyyy-mm-dd hh:nn:ss', dt); O.S['key_submitTime'] := FormatDateTime('yyyy-MM-dd"T"hh:nn:ss.zzz', dt) + sUtcOffset_; O.S['KEY_LOGCODE'] := pInfo.sCode; O.S['DETECTION_DATE'] := O.S['KEY_SUBMITTIME']; // 이벤트 발생 시각. REQUEST의 경우, 예외 신청할 이벤트의 발생 시각 O.S['detectionDate'] := O.S['key_submitTime']; // 이벤트 발생 시각. REQUEST의 경우, 예외 신청할 이벤트의 발생 시각 if pInfo.sLogId <> '' then O.S['logId'] := pInfo.sLogId; if pInfo.sSummary <> '' then begin if (PrefModel_.TextLimit > 0) and (Length(pInfo.sSummary) > PrefModel_.TextLimit) then SetLength(pInfo.sSummary, PrefModel_.TextLimit); O.S['KEY_SUMMARY'] := pInfo.sSummary; end; // O.S['PARENT_LA_ID'] // 상위 이벤트 O.S['POLICY_ID'] := PO.PolicyId; // O.S['POLICY_KEY'] // 정책 위반한 경우 (PREVENT, MONITOR), 위반한 정책의 정책 키 값, 수집인 경우 (DEPLOY), 수집 요청 ID if pInfo.sBody <> '' then begin if (PrefModel_.TextLimit > 0) and (Length(pInfo.sBody) > PrefModel_.TextLimit) then SetLength(pInfo.sBody, PrefModel_.TextLimit); O.S['MESSAGE_BODY'] := pInfo.sBody; // 정책 위반한 경우 (PREVENT, MONITOR), 원문 (본문) 컨텐츠, 수집인 경우 (DEPLOY), 수집 결과 내용, 원문 수집 정책이 비활성화인경우 수집하지 않음 end; if pInfo.sOcrBody <> '' then begin if (PrefModel_.TextLimit > 0) and (Length(pInfo.sOcrBody) > PrefModel_.TextLimit) then SetLength(pInfo.sOcrBody, PrefModel_.TextLimit); O.S['OCR_BODY'] := pInfo.sOcrBody; // 이미지 OCR 추출된 컨텐츠, 원문 수집 정책이 비활성화인 경우 수집하지 않음 end; if pInfo.OVio <> nil then O.O['RULE_VIOLATED'] := pInfo.OVio; // 정책 위반 규칙과 위반 개수. (LIST) if pInfo.sFileCompId <> '' then O.S['COMPONENT_ID'] := pInfo.sFileCompId; // 파일 고유값. 에이전트에서 임의 생성. (이벤트간 동일 파일 판단은 서버에서 하겠습니다.) if pInfo.sPath <> '' then begin O.S['COMPONENT_FILENAME'] := ExtractFileName(pInfo.sPath); // 파일명 O.S['COMPONENT_PATH'] := ExtractFilePath(pInfo.sPath); // 파일 절대 경로 if FileExists(pInfo.sPath) then begin var dtCreate, dtModify, dtAccess: TDateTime; GetFileDateTime_Local(pInfo.sPath, dtCreate, dtModify, dtAccess); var dwAttr: DWORD := GetFileAttributes(PChar(pInfo.sPath)); var OTemp: ISuperObject := SO; OTemp.S['FILESIZE'] := IntToStr(GetFileSize_path(pInfo.sPath)); OTemp.S['LASTMODIFIED'] := FormatDateTime('yyyy-mm-dd hh:nn:ss', dtModify); if dwAttr <> DWORD(-1) then OTemp.S['READONLY'] := BooleanToStr((dwAttr and FILE_ATTRIBUTE_READONLY) <> 0, 'true', 'false'); if dwAttr <> DWORD(-1) then OTemp.S['HIDDEN'] := BooleanToStr((dwAttr and FILE_ATTRIBUTE_HIDDEN) <> 0, 'true', 'false'); // OTemp.S['AUTHOR'] // {만든 이} // OTemp.S['LASTUSER'] // {마지막으로 저장한 사람} // OTemp.S['FILETYPE'] // {컨텐츠 타입} // OTemp.S['FILECLS'] // {컨텐츠 형식} // OTemp.S['PASSWORD'] // {암호적용여부} // OTemp.S['ENCRYPTED'] := BooleanToStr(pInfo.bDrm, 'true', 'false'); // OTemp.S['CORRUPT'] // {깨진파일/정상파일여부} case StrToIntDef(pInfo.sCode, 0) of 52605, // EXECUTE_APP 52606, // TERMINATE_APP 50022, // LOGCODE_PREVENT_SOFTWARE 50503, // MONITOR_SOFTWARE 50009, // LOGCODE_PREVENT_FILEIO 50026 : // LOGCODE_PREVENT_FILEMONITOR begin var sExt: String := GetFileExt(pInfo.sPath); if (sExt <> '') and (sExt.ToUpper = 'EXE') then begin var FI: TTgFileInfo; Guard(FI, TTgFileInfo.Create(pInfo.sPath)); if FI.Version <> '' then OTemp.S['version'] := FI.Version; if FI.InternalName <> '' then OTemp.S['internalName'] := FI.InternalName; if FI.LegalCopyright <> '' then OTemp.S['copyright'] := FI.LegalCopyright; if FI.LegalTradeMarks <> '' then OTemp.S['tradeMarks'] := FI.LegalTradeMarks; if FI.OriginalFileName <> '' then OTemp.S['originalName'] := FI.OriginalFileName; if FI.ProductName <> '' then OTemp.S['productName'] := FI.ProductName; if FI.Comments <> '' then OTemp.S['comments'] := FI.Comments; if FI.Company <> '' then OTemp.S['company'] := FI.Company; if FI.Description <> '' then OTemp.S['description'] := FI.Description; end else begin var i: Integer; var StrList: TStringList; Guard(StrList, TStringList.Create); GetFileProp_all(pInfo.sPath, StrList, true); for i := 0 to StrList.Count - 1 do OTemp.S[StrsReplace(StrList.KeyNames[i], [' '], '_')] := StrList.ValueFromIndex[i]; end; end; end; O.O['COMPONENT_METADATA'] := OTemp; O.S['COMPONENT_LASTACCESS'] := FormatDateTime('yyyy-mm-dd hh:nn:ss', dtAccess); end; end; // O.S['COMPONENT_METADATA'] // O.S['COMPONENT_LASTACCESS'] // 파일 최종 접근 일시 if pInfo.sThumbIds <> '' then begin if pInfo.sCode = MONITOR_appScreenRec then begin var OA: ISuperObject := SO(pInfo.sThumbIds); O.O['attachList'] := OA; end else O.S['COMPONENT_THUMBNAIL_ID'] := pInfo.sThumbIds; // 이미지 미리보기 혹은 이미지가 있는경우, 이미지 파일의 파일 고유값. (출력물의 경우 첫 3장 이미지, 캡쳐 이미지 등), 복수개 허용, ";" 구분 end; if NicService_ <> nil then O.S['SOURCE_IP'] := NicService_.GetIP // 이벤트 발생 시점의 에이전트 IP. 단, 외부에서 수신하는 이벤트의 경우, 발송지의 IP가 되고, DESTINATION_URL이 에이전트 IP가 된다 else O.S['SOURCE_IP'] := 'src_ip'; // O.S['SOURCE_PORT'] // 송신지 사용 포트 if pInfo.sSender <> '' then O.S['EMAIL_SENDER'] := pInfo.sSender; // 메일 발신자 if pInfo.sDestIpUrl <> '' then begin if Length(pInfo.sDestIpUrl) > 512 then SetLength(pInfo.sDestIpUrl, 512); O.S['DESTINATION_URL'] := pInfo.sDestIpUrl; // 수신지 URL (혹은 IP) end; if pInfo.sDestPort <> '' then O.S['DESTINATION_PORT'] := pInfo.sDestPort; // 수신지 포트 if pInfo.sRecipient <> '' then O.S['EMAIL_RECIPIENT'] := pInfo.sRecipient; // 메일 수신자 ; 로 구분 if pInfo.sSubject <> '' then O.S['EMAIL_SUBJECT'] := pInfo.sSubject; // 메일 제목 if pInfo.sAppName <> '' then O.S['APPLICATION_NAME'] := pInfo.sAppName; // 사용 APP 이름 if pInfo.sAppPath <> '' then O.S['APPLICATION_PATH'] := pInfo.sAppPath; // 사용 APP 절대 경로 (실행 파일 exe의 절대 경로) // O.S['PRINTER_JOBNAME'] // 프린터 잡 이름 // O.S['PRINTER_METADATA'] if pInfo.sDevName <> '' then begin if (PrefModel_.TextLimit > 0) and (Length(pInfo.sDevName) > PrefModel_.TextLimit) then SetLength(pInfo.sDevName, PrefModel_.TextLimit); O.S['REMOVABLE_NAME'] := pInfo.sDevName; // USB등과 같은 매체 혹은 프린터 등과 같은 외부 장치 이름 end; if pInfo.sDevSerial <> '' then O.S['REMOVABLE_DEVICEID'] := pInfo.sDevSerial; // USB등과 같은 매체 혹은 프린터 등과 같은 외부 장치 Device ID if pInfo.sDevClassId <> '' then O.S['REMOVABLE_CLASSID'] := pInfo.sDevClassId; // USB등과 같은 매체 혹은 프린터 등과 같은 외부 장치 Class ID if pInfo.sResInfo <> '' then O.S['RESPONSE_INFO'] := pInfo.sResInfo; // 적용된 대응 정보 (DELETE, DRM, POPUP, LOG, EXCEPT 등) // O.S['RESPONSE_RESULT'] // 적용된 대응 적용 결과 (true / false / pending / decline) if pInfo.sComment <> '' then O.S['REQUEST_COMMENT'] := pInfo.sComment; // 사용자가 기입하는 요청 코멘트 // O.S['REQUEST_DUEDATE'] // 사용자가 기입하는 예외 기간 (언제 까지. 최종일) // O.S['REQUEST_TARGET'] // 사용자가 기입하는 예외 대상 (0 - 해당 pc, 1 - 해당 사용자, 2 - 해당 부서, 3-전체) end; if pInfo.sActionId <> '' then O.S['actionGroupId'] := pInfo.sActionId; // {$IFDEF DEBUG} SaveJsonObjToFile(O, 'c:\lx.json'); {$ENDIF} // ThdEvent_.Push(O.AsString); // JSON 포맷으로 잘 변환되서 보내도록 보완 24_0716 10:32:32 kku ThdEvent_.Push(O.AsJSon); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. SendEventLog()'); end; end; procedure TManagerService.SendEventLogEx(sCode, sSummary: String; bPrevent: Boolean = true; dtLog: TDateTime = 0); var LogInfo: TLogInfo; begin ZeroMemory(@LogInfo, SizeOf(LogInfo)); LogInfo.sCode := sCode; LogInfo.sSummary := sSummary; SendEventLogEx(@LogInfo, bPrevent, dtLog); end; function TManagerService.SendApproval(nType: Integer; pData: Pointer; bUpFileCnt: Integer = 0): String; var O: ISuperObject; begin Result := ''; try O := SO; O.S['KEY_AGENTID'] := sAgentId_; O.S['KEY_EMPNO'] := sEmpNo_; O.S['KEY_HOSTNAME'] := sUserName_; O.S['type'] := IntToStr(nType); case nType of 0, 13 : // 출력물 결재 요청 (0), 사후 결재 (13) begin with PPrtEnt(pData)^ do begin O.S['taskId'] := sId; O.S['data1'] := sVioText; O.S['data2'] := BooleanToStr(sFPath <> '', sFPath, WInfo.sDocName); O.S['data3'] := sThumbIds; O.S['data4'] := sText; O.S['data5'] := sOcrText; end; end; 1, 5, 6, 7 : // USB, MTP, Bluetooth, CD/DVD 예외 요청 begin var OInfo: ISuperObject := SO; OInfo.S['deviceName'] := PReqDevExceptInfo(pData).sDevName; OInfo.S['deviceId'] := PReqDevExceptInfo(pData).sSerial; O.S['data2'] := OInfo.AsJSon; end; 2 : // 브라우저 접근 차단 예외 요청 begin O.S['data2'] := String(pData); end; 3 : // DRM 해제 요청 begin O.S['data2'] := ISuperObject(pData).AsJSon; end; 4, 9 : // 파일 반출 요청 begin O.S['data2'] := PReqDevExceptInfo(pData).sSerial; if GetFileExt(PReqDevExceptInfo(pData).sDevName).ToUpper <> 'EXE' then O.S['originEvtUrl'] := PReqDevExceptInfo(pData).sDevName else O.S['originEvtApp'] := PReqDevExceptInfo(pData).sDevName; end; 12 : // 캡처 APP 예외 결재 begin var OInfo: ISuperObject := SO; OInfo.S['appName'] := PReqDevExceptInfo(pData).sSerial; O.S['data2'] := OInfo.AsJSon; end; end; // ss.SaveToFile('c:\reqData.json'); if bUpFileCnt > 0 then Result := GetPostData(Format('approvalRequest.do?reqUploadUrlCnt=%d', [bUpFileCnt]), O.AsJSon, '0') else Result := GetPostData('approvalRequest.do', O.AsJSon, '0'); if Result.Contains('error') then begin // 오류 반환됨 24_1002 14:32:08 kku _Trace('Error .. SendApprovalPrint() .. Msg="%s"', [Result]); Result := ''; end else begin try O := SO(Result); except // .. O := nil; end; if O = nil then begin _Trace('Error2 .. SendApprovalPrint() .. Msg="%s"', [Result]); Result := ''; end else if bUpFileCnt = 0 then begin Result := O.S['url']; if (Result <> '') and (Result[1] = '/') then Delete(Result, 1, 1); end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. SendApprovalPrint()'); end; end; procedure TManagerService.SendAgreeInfo; var // HTTP: TIdHTTP; // SSL: TIdSSLIOHandlerSocketOpenSSL; // ss: TStringStream; O: ISuperObject; begin try // Guard(SSL, TIdSSLIOHandlerSocketOpenSSL.Create(nil)); // SSL.SSLOptions.Method := sslvSSLv23; // SSL.SSLOptions.SSLVersions := [sslvTLSv1_2, sslvTLSv1_1, sslvTLSv1]; // // Guard(HTTP, TIdHTTP.Create(nil)); // HTTP.IOHandler := SSL; // with HTTP do // begin // HandleRedirects := true; // Request.Clear; // Request.UserAgent := 'Mozilla/5.0'; // Request.ContentType := 'application/xml'; // Request.AcceptCharSet := 'UTF-8'; // Request.Connection := 'Keep-Alive'; // Request.CustomHeaders.Values['Keep-Alive'] := 'timeout=300, max=100'; // Request.CustomHeaders.Values['requestType'] := '1'; // HTTPOptions := HTTP.HTTPOptions + [hoForceEncodeParams]; // ConnectTimeout := 5000; // ReadTimeout := 5000; // end; AgentModel_.EulaDT := Now; AgentModel_.Save; O := SO; O.S['TYP_MSG'] := '@(!)_LOG1'; O.S['KEY_AGENTID'] := sAgentId_; O.S['KEY_LOGCODE'] := SYSEVT_AGREEINFO; O.S['KEY_EMPNO'] := sEmpNo_; O.S['DETECTION_DATE'] := FormatDateTime('yyyy-mm-dd hh:nn:ss', AgentModel_.EulaDT); ThdEvent_.Push(O.AsString); // Guard(ss, TStringStream.Create(O.AsJSon, TEncoding.UTF8)); // Result := HTTP.Post(sDestIPort_ + 'eventLog.do', ss); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. SendAgreeInfo()'); end; end; function TManagerService.GetApprovalUrl(sReqType: String): String; var O: ISuperObject; begin Result := ''; try O := SO; O.S['KEY_AGENTID'] := sAgentId_; O.S['KEY_EMPNO'] := sEmpNo_; O.S['KEY_HOSTNAME'] := sUserName_; O.S['type'] := '0'; Result := GetPostData('approvalRequest.do', O.AsJSon, sReqType); if Result.Contains('error') then begin _Trace('Error .. GetApprovalUrl() .. Msg="%s"', [Result]); Result := ''; end else begin try O := SO(Result); except // .. O := nil; end; if O = nil then begin _Trace('Error2 .. GetApprovalUrl() .. Msg="%s"', [Result]); Result := ''; end else Result := O.S['url']; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. GetApprovalUrl()'); end; end; function TManagerService.GetRegPerInfoUrl: String; var HTTP: TIdHTTP; SSL: TIdSSLIOHandlerSocketOpenSSL; O: ISuperObject; begin Result := ''; try O := SO; O.S['agentId'] := sAgentId_; Result := GetPostData('empEditUrlRequest.do', O.AsJSon); if Result.Contains('error') then begin _Trace('Error .. GetRegPerInfoUrl() .. Msg="%s"', [Result]); Result := ''; end else begin try O := SO(Result); except // .. O := nil; end; if O = nil then begin _Trace('Error2 .. GetRegPerInfoUrl() .. Msg="%s"', [Result]); Result := ''; end else Result := O.S['url']; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. GetRegPerInfoUrl()'); end; end; function TManagerService.GetPostData(sUrl, sData: String; sReqType: String = ''): String; var HTTP: TIdHTTP; SSL: TIdSSLIOHandlerSocketOpenSSL; ss: TStringStream; begin Result := ''; try if sUrl = '' then exit; if sUrl[1] = '/' then Delete(sUrl, 1, 1); Guard(SSL, TIdSSLIOHandlerSocketOpenSSL.Create(nil)); SSL.SSLOptions.Method := sslvSSLv23; SSL.SSLOptions.SSLVersions := [sslvTLSv1_2, sslvTLSv1_1, sslvTLSv1]; Guard(HTTP, TIdHTTP.Create(nil)); HTTP.IOHandler := SSL; with HTTP do begin HandleRedirects := true; Request.Clear; Request.UserAgent := 'Mozilla/5.0'; Request.ContentType := 'application/xml'; Request.AcceptCharSet := 'UTF-8'; // Request.Connection := 'Keep-Alive'; // Request.CustomHeaders.Values['Keep-Alive'] := 'timeout=300, max=100'; Request.Connection := 'close'; HTTPOptions := HTTPOptions - [hoKeepOrigProtocol]; if sReqType <> '' then Request.CustomHeaders.Values['requestType'] := sReqType; HTTPOptions := HTTP.HTTPOptions + [hoForceEncodeParams]; ConnectTimeout := 5000; ReadTimeout := 5000; end; Guard(ss, TStringStream.Create(sData, TEncoding.UTF8)); Result := HTTP.Post(sDestIPort_ + sUrl, ss); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. GetPostData()'); end; end; procedure TManagerService.SendRequest(sCode: String; aExptInfo: TReqDevExceptInfo; sComment, sBeginDate, sDueDate: String; nTarget: Integer; sMsg: String); var O: ISuperObject; dt: TDateTime; begin try if sAgentId_ = '' then exit; _Trace('SendRequest > Code=%s, Msg=%s', [sCode, sMsg], 3); dt := Now; O := SO; if CUSTOMER_TYPE = CUSTOMER_TMAP then begin case aExptInfo.ReqDevType of rdtUsbDrive : O.S['TYP_MSG'] := '@(!)_REQ_TMAP_1'; // rdtMtp : ; // rdtBluetooth : ; // rdtCdrom : ; rdtDrm : begin // 별도 처리 23_1212 16:44:34 kku O.S['TYP_MSG'] := '@(!)_REQ_TMAP_6'; O.S['KEY_AGENTID'] := sAgentId_; O.S['KEY_EMPNO'] := sEmpNo_; if IsUseHostNameOnly then O.S['KEY_HOSTNAME'] := sComName_ else O.S['KEY_HOSTNAME'] := sUserName_; O.S['KEY_SUBMITTIME'] := FormatDateTime('yyyy-mm-dd hh:nn:ss', dt); O.S['key_submitTime'] := FormatDateTime('yyyy-MM-dd"T"hh:nn:ss.zzz', dt) + sUtcOffset_; O.S['KEY_SUMMARY'] := sMsg; O.S['MESSAGE_BODY'] := aExptInfo.sDevName; O.S['REQUEST_COMMENT'] := sComment; O.S['REQUEST_TARGET'] := '0'; // 0 : 요청 PC, 요청 사용자, 부서, 전체, nTarget O.S['REQUEST_TYPE'] := 'INTERNAL-DRM'; O.S['REQUEST_DUEDATE'] := O.S['KEY_SUBMITTIME']; O.S['REQUEST_DUEDATE_U'] := O.S['key_submitTime']; ThdEvent_.Push(O.AsString); exit; end; rdtPrintWater : begin // 별도 처리 23_1212 16:44:34 kku O.S['TYP_MSG'] := '@(!)_REQ_TMAP_7'; O.S['KEY_AGENTID'] := sAgentId_; O.S['KEY_EMPNO'] := sEmpNo_; if IsUseHostNameOnly then O.S['KEY_HOSTNAME'] := sComName_ else O.S['KEY_HOSTNAME'] := sUserName_; O.S['KEY_SUBMITTIME'] := FormatDateTime('yyyy-mm-dd hh:nn:ss', dt); O.S['key_submitTime'] := FormatDateTime('yyyy-MM-dd"T"hh:nn:ss.zzz', dt) + sUtcOffset_; O.S['KEY_SUMMARY'] := sMsg; O.S['MESSAGE_BODY'] := aExptInfo.sDevName; O.S['REQUEST_COMMENT'] := sComment; O.S['REQUEST_TARGET'] := '0'; // 0 : 요청 PC, 요청 사용자, 부서, 전체, nTarget O.S['REQUEST_TYPE'] := 'INTERNAL-WATER'; O.S['REQUEST_DUEDATE'] := O.S['KEY_SUBMITTIME']; O.S['REQUEST_DUEDATE_U'] := O.S['key_submitTime']; ThdEvent_.Push(O.AsString); exit; end; rdtPiFile : begin O.S['TYP_MSG'] := '@(!)_REQ_EXPT_PI'; O.S['KEY_AGENTID'] := sAgentId_; O.S['KEY_EMPNO'] := sEmpNo_; if IsUseHostNameOnly then O.S['KEY_HOSTNAME'] := sComName_ else O.S['KEY_HOSTNAME'] := sUserName_; O.S['KEY_SUBMITTIME'] := FormatDateTime('yyyy-mm-dd hh:nn:ss', dt); O.S['key_submitTime'] := FormatDateTime('yyyy-MM-dd"T"hh:nn:ss.zzz', dt) + sUtcOffset_; O.S['KEY_SUMMARY'] := sMsg; O.S['MESSAGE_BODY'] := aExptInfo.sDevName; O.S['REQUEST_COMMENT'] := sComment; O.S['REQUEST_TARGET'] := '0'; // 0 : 요청 PC, 요청 사용자, 부서, 전체, nTarget O.S['REQUEST_TYPE'] := 'INTERNAL-PI'; // INTERNAL-WATER O.S['REQUEST_DUEDATE'] := O.S['KEY_SUBMITTIME']; O.S['REQUEST_DUEDATE_U'] := O.S['key_submitTime']; ThdEvent_.Push(O.AsString); exit; end; else O.S['TYP_MSG'] := '@(!)_REQ'; end; end else O.S['TYP_MSG'] := '@(!)_REQ'; O.S['KEY_AGENTID'] := sAgentId_; O.S['KEY_EMPNO'] := sEmpNo_; if IsUseHostNameOnly then O.S['KEY_HOSTNAME'] := sComName_ else O.S['KEY_HOSTNAME'] := sUserName_; O.S['KEY_SUBMITTIME'] := FormatDateTime('yyyy-mm-dd hh:nn:ss', dt); O.S['key_submitTime'] := FormatDateTime('yyyy-MM-dd"T"hh:nn:ss.zzz', dt) + sUtcOffset_; O.S['KEY_LOGCODE'] := sCode; O.S['DETECTION_DATE'] := O.S['KEY_SUBMITTIME']; // 이벤트 발생 시각. REQUEST의 경우, 예외 신청할 이벤트의 발생 시각 O.S['detectionDate'] := O.S['key_submitTime']; // 이벤트 발생 시각. REQUEST의 경우, 예외 신청할 이벤트의 발생 시각 O.S['KEY_SUMMARY'] := sMsg; // O.S['PARENT_LA_ID'] // 상위 이벤트 O.S['POLICY_ID'] := GetModePolicy.PolicyId; // O.S['POLICY_KEY'] // 정책 위반한 경우 (PREVENT, MONITOR), 위반한 정책의 정책 키 값, 수집인 경우 (DEPLOY), 수집 요청 ID // O.S['MESSAGE_BODY'] // 정책 위반한 경우 (PREVENT, MONITOR), 원문 (본문) 컨텐츠, 수집인 경우 (DEPLOY), 수집 결과 내용, 원문 수집 정책이 비활성화인경우 수집하지 않음 // O.S['OCR_BODY'] // 이미지 OCR 추출된 컨텐츠, 원문 수집 정책이 비활성화인 경우 수집하지 않음 // O.S['RULE_VIOLATED'] // 정책 위반 규칙과 위반 개수. (LIST) // O.S['COMPONENT_ID'] // 파일 고유값. 에이전트에서 임의 생성. (이벤트간 동일 파일 판단은 서버에서 하겠습니다.) // O.S['COMPONENT_FILENAME'] // 파일명 // O.S['COMPONENT_PATH'] // 파일 절대 경로 // O.S['COMPONENT_METADATA'] // O.S['COMPONENT_LASTACCESS'] // 파일 최종 접근 일시 // O.S['COMPONENT_THUMBNAIL_ID'] // 이미지 미리보기 혹은 이미지가 있는경우, 이미지 파일의 파일 고유값. (출력물의 경우 첫 3장 이미지, 캡쳐 이미지 등), 복수개 허용, ";" 구분 // O.S['SOURCE_IP'] // 이벤트 발생 시점의 에이전트 IP. 단, 외부에서 수신하는 이벤트의 경우, 발송지의 IP가 되고, DESTINATION_URL이 에이전트 IP가 된다 // O.S['SOURCE_PORT'] // 송신지 사용 포트 // O.S['EMAIL_SENDER'] // 메일 발신자 // O.S['DESTINATION_URL'] // 수신지 URL (혹은 IP) // O.S['DESTINATION_PORT'] // 수신지 포트 // O.S['EMAIL_RECIPIENT'] // 메일 수신자 ; 로 구분 // O.S['EMAIL_SUBJECT'] // 메일 제목 // O.S['APPLICATION_NAME'] // 사용 APP 이름 // O.S['APPLICATION_PATH'] // 사용 APP 절대 경로 (실행 파일 exe의 절대 경로) // O.S['PRINTER_JOBNAME'] // 프린터 잡 이름 // O.S['PRINTER_METADATA'] O.S['REMOVABLE_NAME'] := aExptInfo.sDevName; // USB등과 같은 매체 혹은 프린터 등과 같은 외부 장치 이름 O.S['REMOVABLE_DEVICEID'] := aExptInfo.sSerial; // USB등과 같은 매체 혹은 프린터 등과 같은 외부 장치 Device ID // O.S['DEVICE_TYPE'] := IntToStr(Integer(aExptInfo.ReqDevType)); // 의미 없어서 제외 23_0822 12:40:55 kku // O.S['REMOVABLE_CLASSID'] // USB등과 같은 매체 혹은 프린터 등과 같은 외부 장치 Class ID // O.S['RESPONSE_INFO'] // 적용된 대응 정보 (DELETE, DRM, POPUP, LOG, EXCEPT 등) // O.S['RESPONSE_RESULT'] // 적용된 대응 적용 결과 (true / false / pending / decline) O.S['REQUEST_COMMENT'] := sComment; // 사용자가 기입하는 요청 코멘트 O.S['REQUEST_STARTDATE'] := sBeginDate; // 시작일 추가 24_1205 10:20:44 kku O.S['REQUEST_DUEDATE'] := sDueDate; // 사용자가 기입하는 예외 기간 (언제 까지. 최종일) O.S['REQUEST_TARGET'] := IntToStr(nTarget); // 사용자가 기입하는 예외 대상 (0 - 해당 pc, 1 - 해당 사용자, 2 - 해당 부서, 3 - 전체) ThdEvent_.Push(O.AsString); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. SendEventLog()'); end; end; function GetSendFileJsonObj(sCompId, sApi, sPath: String; nMinMB, nLimitMB: Integer; aRespaction: TCampnRespaction; nRespDelaySec: Integer): ISuperObject; begin try Result := SO; Result.S['TYP_MSG'] := '@(!)_SF'; Result.S['CompId'] := sCompId; Result.S['Path'] := sPath; Result.S['API'] := sApi; Result.I['MSize'] := nMinMB; Result.I['LSize'] := nLimitMB; Result.I['DSec'] := nRespDelaySec; if aRespaction <> crtNone then Result.I['AFW'] := Integer(aRespaction); except on E: Exception do ETgException.TraceException(E, 'Fail .. GetSendFileJsonObj()'); end; end; procedure TManagerService.SendFile(var LogInfo: TLogInfo; sApi, sPath: String; nMinMB: Integer = 0; nLimitMB: Integer = 50; aRespaction: TCampnRespaction = crtNone; nRespDelaySec: Integer = 0); var O: ISuperObject; bSendBin: Boolean; sCompId, sData: String; begin try bSendBin := false; sCompId := LogInfo.sFileCompId; if sApi = 'quarantineLogCollect.do' then begin // 원본 수집 시 대용량 업로드 방식으로 변경 25_1208 15:46:14 kku LogInfo.sLogId := StrsReplace(TGUID.NewGuid.ToString, ['{', '}'], ''); sData := GetPostData(Format('aapi/files/bin/issue?logId=%s&type=incOrgFile&fileName=%s', [LogInfo.sLogId, UrlEncodeUTF8(ExtractFileName(sPath))]), ''); try if sData <> '' then begin var ORst: ISuperObject := SO(sData); if ORst.S['uploadUrl'] <> '' then begin LogInfo.sFileCompId := ORst.S['fileId']; sCompId := 'file'; sApi := ORst.S['uploadUrl']; bSendBin := true; end; end; except // end; end; if (sApi <> '') and (sApi[1] = '/') then Delete(sApi, 1, 1); O := GetSendFileJsonObj(sCompId, sApi, sPath, nMinMB, nLimitMB, aRespaction, nRespDelaySec); if bSendBin then O.B['SB'] := true; ThdEvent_.Push(O.AsString); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. SendFile()'); end; end; procedure TManagerService.SendFileNor(bSendBin: Boolean; sCompId, sApi, sPath: String; nMinMB: Integer = 0; nLimitMB: Integer = 50; aRespaction: TCampnRespaction = crtNone; nRespDelaySec: Integer = 0); var O: ISuperObject; begin try if (sApi <> '') and (sApi[1] = '/') then Delete(sApi, 1, 1); O := GetSendFileJsonObj(sCompId, sApi, sPath, nMinMB, nLimitMB, aRespaction, nRespDelaySec); if bSendBin or sApi.Contains('/bin?') then O.B['SB'] := true; ThdEvent_.Push(O.AsString); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. SendFileNor()'); end; end; procedure TManagerService.SendCttSchProgInfo(aProg: TCttSchProg); var O: ISuperObject; begin try // if not Connected then // Sleep(3000); if sAgentId_ = '' then exit; O := SO; O.S['KEY_SCAN_ID'] := aProg.sScanId; O.S['KEY_SCAN_TASK_ID'] := aProg.sTaskId; O.S['KEY_SCAN_AGENT_ID'] := sAgentId_; if IsUseHostNameOnly then O.S['KEY_SCAN_HOSTNAME'] := sComName_ else O.S['KEY_SCAN_HOSTNAME'] := sUserName_; O.S['KEY_SCAN_EMP_ID'] := sEmpNo_; O.S['KEY_SCAN_STATUS'] := aProg.sStatus; O.S['KEY_SCAN_TOTAL'] := IntToStr(aProg.llTotal); O.S['KEY_SCAN_COMPLETED'] := IntToStr(aProg.llProc); O.S['KEY_SCAN_STARTTIME'] := FormatDateTime('yyyy-mm-dd hh:nn:ss', aProg.dtStart); O.S['KEY_SCAN_RESULT'] := aProg.sResult; ThdEvent_.Push(O.AsString); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. SendEventLogCttSchProg()'); end; end; procedure TManagerService.SendCampnProgInfo(aProg: TCttSchProg); begin try if pProcCampn_ = nil then exit; MgCampn_.SendCampaignProgress(pProcCampn_, aProg); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. SendCampnProgInfo()'); end; end; procedure TManagerService.SendCttSchDetailInfo(sTaskId: String; pResult: PSchResult; nProcType: Integer); var O: ISuperObject; dtCreate, dtModify, dtAccess: TDateTime; sPath: String; nPos: Integer; begin try // if not Connected then // Sleep(3000); if sAgentId_ = '' then exit; sPath := pResult.sPath; nPos := Pos(' > ', sPath); if nPos > 0 then SetLength(sPath, nPos - 1); GetFileDateTime_Local(sPath, dtCreate, dtModify, dtAccess); O := SO; O.S['KEY_SCAN_TASK_ID'] := sTaskId; if IsUseHostNameOnly then O.S['KEY_SCAN_HOSTNAME'] := sComName_ else O.S['KEY_SCAN_HOSTNAME'] := sUserName_; O.S['KEY_SCAN_EMP_ID'] := sEmpNo_; O.S['KEY_SCAN_PATH'] := pResult.sPath; O.S['KEY_SCAN_FILENAME'] := pResult.sFName; // ExtractFileName(pResult.sPath); O.S['KEY_SCAN_VIOLATE_TEXT'] := pResult.sResultStr; O.S['KEY_SCAN_VIOLATE_POLICY'] := pResult.sSchName; O.S['KEY_SCAN_VIOLATE_COUNT'] := IntToStr(pResult.nHitCnt); if pResult.bDrm then O.S['KEY_SCAN_ENCRYPT'] := 'true'; case nProcType of 1 : O.S['KEY_SCAN_FORCE_ENC'] := 'true'; 2 : O.S['KEY_SCAN_FORCE_DEL'] := 'true'; 3 : O.S['KEY_SCAN_EXCEPT'] := 'true'; end; O.S['KEY_SCAN_LASTMODIFIED'] := FormatDateTime('yyyy-mm-dd hh:nn:ss', dtModify); O.S['KEY_SCAN_LASTACCESS'] := FormatDateTime('yyyy-mm-dd hh:nn:ss', dtAccess); ThdEvent_.Push(O.AsString); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. SendEventLogCttSchDetail()'); end; end; procedure TManagerService.SendAppInstInfo; var O: ISuperObject; InstList: TTgInstAppList; sPath, sData: String; i, nPos: Integer; begin try if IsNewServerOnly then exit; // if not Connected then // Sleep(3000); if sAgentId_ = '' then exit; // _Trace('SendAppInstInfo() ..'); _Trace('SendAppInstInfo(-) .. OldTime=%s, NewTime=%s', [DateTimeToStr(dtSoftInstTick_), DateTimeToStr(Now)]); Guard(InstList, TTgInstAppList.Create); InstList.UpdateInstAppList; sData := ''; for i := 0 to InstList.Count - 1 do with InstList[i]^ do begin sPath := StringReplace(sIconPath, '"', '', [rfReplaceAll]); nPos := Pos('.EXE', UpperCase(sPath)); if nPos > 0 then begin SetLength(sPath, nPos + 3); if not FileExists(sPath) then sPath := ''; end else sPath := ''; SumString(sData, Format('appName:%s|updateTime:%s|procName:%s|ver:%s|company:%s', [sName, FormatDateTime('yyyy-mm-dd hh:nn:ss', dtInst), ExtractFileName(sPath), sVersion, sPublisher]), '*'); end; sPath := GetRunExePathDir + 'AppInstInfo.txt'; if FileExists(sPath) then DeleteFile(PChar(sPath)); if CUSTOMER_TYPE = CUSTOMER_DEV then WriteLnFileEndUTF8(sPath, sData); O := SO; O.S['KEY_APP_AGENT_ID'] := sAgentId_; if IsUseHostNameOnly then O.S['KEY_APP_HOSTNAME'] := sComName_ else O.S['KEY_APP_HOSTNAME'] := sUserName_; O.S['KEY_APP_EMP_ID'] := sEmpNo_; O.S['KEY_APP_LIST'] := sData; ThdEvent_.Push(O.AsString); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. SendAppInstInfo()'); end; end; function TManagerService.SendHwInfo: Boolean; var O, OA, OInfo: ISuperObject; ItemList: TStringList; i: Integer; HTTP: TIdHTTP; SSL: TIdSSLIOHandlerSocketOpenSSL; ss: TStringStream; sResult: String; begin {$IFDEF DEBUG} Result := true; bIsSendHWInfo_ := true; exit; {$ENDIF} Result := false; try Guard(ItemList, TStringList.Create); O := SO; O.S['cpu'] := WMI_GetCpuInfo; O.S['mainboard'] := WMI_GetBaseboardInfo; O.S['biosVer'] := WMI_GetBiosVersion; ItemList.CommaText := StringReplace(WMI_GetVideoController, ', ', ',', [rfReplaceAll]); OA := TSuperObject.Create(stArray); for i := 0 to ItemList.Count - 1 do OA.AsArray.Add(ItemList[i]); O.O['graphics'] := OA; O.S['memory'] := ByteSizeToStr(WMI_GetMemory); ItemList.CommaText := StringReplace(WMI_GetMonitor, ', ', ',', [rfReplaceAll]); OA := TSuperObject.Create(stArray); for i := 0 to ItemList.Count - 1 do OA.AsArray.Add(ItemList[i]); O.O['monitors'] := OA; OA := TSuperObject.Create(stArray); Guard(ItemList, TStringList.Create); ItemList.CommaText := GetDrivesFromMask(GetLogicalDrives); for i := 0 to ItemList.Count - 1 do begin OInfo := SO; OInfo.S['path'] := ItemList[i]; OInfo.I['sizeMb'] := GetDriveSize(ItemList[i]); OA.AsArray.Add(OInfo); end; O.O['drives'] := OA; O.S['osInstallDate'] := FormatDateTime('yyyy-mm-dd hh:nn:ss', WMI_GetOSInstallDateTime); Guard(SSL, TIdSSLIOHandlerSocketOpenSSL.Create(nil)); SSL.SSLOptions.Method := sslvSSLv23; SSL.SSLOptions.SSLVersions := [sslvTLSv1_2, sslvTLSv1_1, sslvTLSv1]; Guard(HTTP, TIdHTTP.Create(nil)); HTTP.IOHandler := SSL; with HTTP do begin HandleRedirects := true; Request.Clear; Request.UserAgent := 'Mozilla/5.0'; Request.ContentType := 'application/xml'; Request.AcceptCharSet := 'UTF-8'; // Request.Connection := 'Keep-Alive'; // Request.CustomHeaders.Values['Keep-Alive'] := 'timeout=300, max=100'; Request.Connection := 'close'; HTTPOptions := HTTPOptions - [hoKeepOrigProtocol]; Request.CustomHeaders.Values['requestType'] := '0'; HTTPOptions := HTTP.HTTPOptions + [hoForceEncodeParams]; ConnectTimeout := 5000; ReadTimeout := 5000; end; Guard(ss, TStringStream.Create(O.AsJSon, TEncoding.UTF8)); sResult := sDestIPort_ + Format('api/agents/%s/hw-info?agentMode=1', [sAgentId_]); sResult := HTTP.Put(sResult, ss); // var StrList: TStringList; // Guard(StrList, TStringList.Create); // StrList.Text := sResult; // StrList.SaveToFile('c:\test.html', TEncoding.UTF8); Result := (HTTP.ResponseCode = 200) and (sResult = '{"result":"success"}'); bIsSendHWInfo_ := Result; except on E: EIdHTTPProtocolException do begin if E.ErrorCode = 304 then begin bIsSendHWInfo_ := true; exit; end; end; on E: Exception do begin bIsSendHWInfo_ := true; ETgException.TraceException(Self, E, 'Fail .. SendHwInfo()'); end; end; end; function TManagerService.DirectSendEventLog(sUri, sCode, sMsg: String; bPrevent: Boolean = false): Boolean; var HTTP: TIdHTTP; SSL: TIdSSLIOHandlerSocketOpenSSL; ss: TStringStream; O: ISuperObject; sReq, sResult: String; dt: TDateTime; begin Result := false; try // Uninstall 이벤트 처리처럼 바로 처리해야 할 경우... 보통 없을듯 22_0624 09:11:06 kku Guard(SSL, TIdSSLIOHandlerSocketOpenSSL.Create(nil)); SSL.SSLOptions.Method := sslvSSLv23; SSL.SSLOptions.SSLVersions := [sslvTLSv1_2, sslvTLSv1_1, sslvTLSv1]; Guard(HTTP, TIdHTTP.Create(nil)); HTTP.IOHandler := SSL; with HTTP do begin HandleRedirects := true; Request.Clear; Request.UserAgent := 'Mozilla/5.0'; Request.ContentType := 'application/xml'; Request.AcceptCharSet := 'UTF-8'; // Request.Connection := 'Keep-Alive'; // Request.CustomHeaders.Values['Keep-Alive'] := 'timeout=300, max=100'; Request.Connection := 'close'; HTTPOptions := HTTPOptions - [hoKeepOrigProtocol]; HTTPOptions := HTTP.HTTPOptions + [hoForceEncodeParams]; ConnectTimeout := 5000; ReadTimeout := 5000; end; dt := Now; O := SO; if bIsNewApi_ then begin if bPrevent then sReq := 'prevent' else sReq := 'monitor'; O.S['KEY_AGENTID'] := sAgentId_; O.S['KEY_EMPNO'] := sEmpNo_; O.S['KEY_ACCOUNT'] := sAccount_; if IsUseHostNameOnly then O.S['KEY_HOSTNAME'] := sComName_ else O.S['KEY_HOSTNAME'] := sUserName_; O.S['KEY_SUBMITTIME'] := FormatDateTime('yyyy-mm-dd hh:nn:ss', dt); O.S['key_submitTime'] := FormatDateTime('yyyy-MM-dd"T"hh:nn:ss.zzz', dt) + sUtcOffset_; O.S['KEY_LOGCODE'] := sCode; O.S['DETECTION_DATE'] := O.S['KEY_SUBMITTIME']; // 이벤트 발생 시각. REQUEST의 경우, 예외 신청할 이벤트의 발생 시각 O.S['detectionDate'] := O.S['key_submitTime']; // 이벤트 발생 시각. REQUEST의 경우, 예외 신청할 이벤트의 발생 시각 O.S['KEY_SUMMARY'] := sMsg; O.S['POLICY_ID'] := GetModePolicy.PolicyId; end else begin O.S['MODEL_ID'] := sAgentId_; O.S['TOCSG_LA_IFNAME'] := sUri; O.S['TOCSG_LA_ID'] := sAgentId_; O.S['TOCSG_LA_EMPID'] := sEmpNo_; O.S['TOCSG_LA_CODE'] := sCode; O.S['TOCSG_LA_DATA'] := sMsg; if IsUseHostNameOnly then O.S['TOCSG_LA_HOSTNAME'] := sComName_ else O.S['TOCSG_LA_HOSTNAME'] := sUserName_; O.S['TOCSG_LA_LASTCONNDATE'] := FormatDateTime('yyyy-mm-dd hh:nn:ss', Now); if NicService_ <> nil then begin O.S['TOCSG_LA_MACADDR'] := NicService_.GetIP; O.S['TOCSG_LA_REMOTEIP'] := NicService_.GetMAC; end else begin O.S['TOCSG_LA_MACADDR'] := 'ip'; O.S['TOCSG_LA_REMOTEIP'] := 'mac'; end; end; Guard(ss, TStringStream.Create(O.AsJSon, TEncoding.UTF8)); if bIsNewApi_ then begin HTTP.Request.CustomHeaders.Values['requestType'] := sReq; sResult := HTTP.Post(sDestIPort_ + 'eventIncident.do', ss); end else begin HTTP.Request.CustomHeaders.Values['requestType'] := '123119'; sResult := HTTP.Post(sDestSvrUrl_, ss); end; if (sResult = '') and (HTTP.ResponseCode = 200) then Result := true; except {$IFDEF TRACE1} on E: Exception do ETgException.TraceException(Self, E, 'Fail .. DirectSendEventLog()'); {$ENDIF} end; end; procedure TManagerService.SendScreenRecord(sReason, sMp4Path: String; nMilSec: Integer); var LogInfo: TLogInfo; O, OA: ISuperObject; sFid, sUpUrl: String; begin try ZeroMemory(@LogInfo, SizeOf(LogInfo)); LogInfo.sCode := MONITOR_appScreenRec; LogInfo.sLogId := StrsReplace(TGUID.NewGuid.ToString, ['{', '}'], ''); var sData: String := GetPostData(Format('aapi/files/issue?origin=inc.%s&type=appScreenRec', [LogInfo.sLogId]), ''); if sData = '' then begin _Trace('SendScreenRecord() .. Fail .. Upload URL 가져오기 실패'); exit; end; O := SO(sData); sFid := O.S['fileId']; sUpUrl := O.S['uploadUrl']; SendFileNor(false, 'file', sUpUrl, sMp4Path, 0, 200, crtDelete); OA := TSuperObject.Create(stArray); OA.AsArray.Add(sFid); LogInfo.sThumbIds := OA.AsJSon; LogInfo.sAppName := sReason; LogInfo.sSummary := Format('App Screen Record (MilSec=%d)', [nMilSec]); SendEventLogEx(@LogInfo); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. SendScreenRecord()'); end; end; procedure TManagerService.SendAuditLog(const JsonReport: string); var KeyPath, ExpectedHash, ActualHash, Reason: string; Root, FileObj, SuccessArray, FailArray: ISuperObject; JsonLog, sHostName, sEmpId: string; IsSuccess: Boolean; begin _Trace('[MGKIM] SendAuditLog.. 서버 전송: %s', [JsonReport]); try Root := SO(JsonReport); if Root = nil then begin _Trace('[MGKIM] 파싱 오류: 전달받은 JsonReport가 올바른 포맷이 아닙니다.'); Exit; end; sEmpId := gMgSvc.AgentModel.EmpNo; if IsUseHostNameOnly then sHostName := gMgSvc.ComName else sHostName := gMgSvc.UserName; Root.S['type'] := 'integrity'; Root.S['hostname'] := sHostName; Root.S['empId'] := sEmpId; Root.S['loggedAt'] := FormatDateTime('yyyy-mm-dd"T"hh:nn:ss"+09:00"', Now); Root.S['startedAt'] := agentStatTime_; ThdEvent_.Push(Root.AsString); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. SendAuditLog()'); end; end; procedure TManagerService.PopupMessage(nType: Integer; sData: String = ''); var O: ISuperObject; bVulMsg, bApproval: Boolean; sTemp: String; begin if hRcvHwnd_ = 0 then exit; if (CUSTOMER_TYPE = CUSTOMER_SERVE1) and (nType = TYPE_MSG_PREVENT_FILEWRITE) then begin // 파일 생성 차단 알림은 1분에 한번만 뜨게 해야함 24_0718 10:58:54 kku if SecondsBetween(dtSV1FileBlockNoti_, Now) < 60 then exit; dtSV1FileBlockNoti_ := Now; end; // 화면 잠금 상태에서는 팝업 되지 않도록 보완 22_1118 08:03:28 kku // 현재 화면 잠금 상태에서 팝업되면 에디트 박스에 포커스가 가기전까지 텍스트가 표시 되지 않는 문제 있음 if FindWindow('TDlgLockScreen', nil) <> 0 then exit; bApproval := false; case nType of TYPE_MSG_CTTSCH_START : begin // if (pProcCampn_ <> nil) and pProcCampn_.Info.bScanNotice then begin O := SO; O.I['T'] := nType; if sData <> '' then O.S['D'] := sData; SendMessage(hRcvHwnd_, WM_POPUP_MSG2, 0, NativeInt(O.AsString)); end; exit; end; TYPE_MSG_CTTSCH_COMPLETE : begin if (pProcCampn_ <> nil) and (pProcCampn_.Info.nNotiIfCnt > 0) then begin var StrList: TStringList; Guard(StrList, TStringList.Create); SplitString(sData, '|', StrList); if (StrList.Count > 1) and (StrToIntDef(StrList[1], 0) >= pProcCampn_.Info.nNotiIfCnt) then begin O := SO; O.I['T'] := nType; if sData <> '' then O.S['D'] := sData; SendMessage(hRcvHwnd_, WM_POPUP_MSG_PI, 0, NativeInt(O.AsString)); end; end {$IFDEF DEBUG} else begin // for Test O := SO; O.I['T'] := nType; if sData <> '' then O.S['D'] := sData; SendMessage(hRcvHwnd_, WM_POPUP_MSG_PI, 0, NativeInt(O.AsString)); end {$ENDIF}; exit; end; TYPE_MSG_CAMPN_FILEENC : begin if pProcCampn_ <> nil then begin O := SO; O.I['T'] := nType; SendMessage(hRcvHwnd_, WM_POPUP_MSG_PI, 0, NativeInt(O.AsString)); end; exit; end; end; case nType of TYPE_MSG_NOTIFICATION : begin if not PrefModel.IsNoticeEnable then exit; end; TYPE_REQ_APPROVAL, TYPE_RES_APPROVAL : bApproval := true; else begin {$IFNDEF DEBUG} // TEST_KJ if ModePolicy.NotifyKind = nfkNone then // if (ModePolicy.NotifyKind = nfkNone) and (nType <> TYPE_MSG_UPDATE) then exit; {$ENDIF} // 팝업 중복 거르기 case nType of TYPE_MSG_PREVENT_FILECHANGE, TYPE_MSG_PREVENT_FILEWRITE : begin sTemp := StringReplace(sData, ':', '_', [rfReplaceAll]); sTemp := StringReplace(sTemp, '\', '_', [rfReplaceAll]); sTemp := 'Global\PV_' + sTemp; if MutexExists(sTemp) then exit; end; end; bVulMsg := false; case nType of TYPE_MSG_SAFEAPPLIED, TYPE_MSG_OLD_WINDOWS, TYPE_MSG_VUL_OS, TYPE_MSG_VUL_PW, TYPE_MSG_VUL_AV, TYPE_MSG_VUL_FW, TYPE_MSG_VUL_SCREEN, TYPE_MSG_VUL_ALLOWACCESS, TYPE_MSG_VUL_EMPNO : bVulMsg := true; // TYPE_MSG_NOTIFICATION, TYPE_MSG_UPDATE, TYPE_MSG_AFTERREPORT : begin // 항상 표시되기 위해 조치한다. 22_0819 13:50:29 kku case ModePolicy.NotifyKind of nfkVul: bVulMsg := true; nfkPol: bVulMsg := false; end; end; end; case ModePolicy.NotifyKind of // nfkNone : if nType <> TYPE_MSG_UPDATE then exit; nfkNone : exit; nfkVul: if not bVulMsg then exit; nfkPol: if bVulMsg then exit; end; end; end; if (nType = TYPE_MSG_PREVENT_CAPAPP) and IsHD then begin // 별도 팝업 처리 O := SO; O.I['T'] := nType; if sData <> '' then O.S['D'] := sData; SendMessage(hRcvHwnd_, WM_POPUP_MSG2, 0, NativeInt(O.AsString)); exit; end; // todo : 알림 세부 정책 추가 시 삭제해야함 23_0403 13:59:37 kku if (nType = TYPE_MSG_PREVENT_FILECHANGE) and ModePolicy.FileMonOnlyLog then exit; O := SO; O.I['T'] := nType; O.B['A'] := bApproval; if sData <> '' then O.S['D'] := sData; SendMessage(hRcvHwnd_, WM_POPUP_MSG, 0, NativeInt(O.AsString)); end; procedure TManagerService.PopupSystemMsg(nType: Integer); begin if IsNewApi then exit; if CUSTOMER_TYPE = CUSTOMER_SANKYO then begin // 다이이찌산쿄의 경우 "알림팝업 여부" 정책 OFF 시 모든 알림 차단 22_0615 08:49:19 kku if ModePolicy.NotifyKind = nfkNone then exit; end; if hRcvHwnd_ <> 0 then SendMessage(hRcvHwnd_, WM_POPUP_MSG_SYSTEM, nType, 0); end; procedure TManagerService.PopupLicensed; var HTTP: TIdHTTP; SSL: TIdSSLIOHandlerSocketOpenSSL; sTemp: String; begin try if hRcvHwnd_ = 0 then exit; if PrefModel.NoticeContent <> '' then begin // 공지사항 sNoticeContent_ := PrefModel.NoticeContent; PopupMessage(TYPE_MSG_NOTIFICATION, sNoticeContent_); end; if PrefModel.IsDailyEulaCheck then begin if IsToday(AgentModel.EulaDT) then exit; end else begin if (AgentModel_.EulaDT <> 0) then exit; end; if not PrefModel.IsEulaSubmit then exit; if MutexExists(MUTEX_LICENSE) then exit; sTemp := ''; // 보안서약서 보여주기전에 내용 업데이트 해줌 22_1129 09:59:17 kku try if bIsNewApi_ then begin // 신규서버에서는 팝업 시 값을 채워주게 했지만 // 2.6 방식으로 맞춘다 23_0830 13:06:16 kku sTemp := PrefModel_.EulaBody; end else // 전역 포트 블럭으로 사용동의서 가져오기 전에 짤릴 수 있어서 미리 받아놓는다 22_0503 10:02:52 kku if sAgentId_ <> '' then begin var sDest: String := StringReplace(sDestSvrUrl_, 'agentLogRequest.do', 'agentEulaContent', [rfReplaceAll]); sDest := StringReplace(sDest, 'agentLogRequests.do', 'agentEulaContent', [rfReplaceAll]); sDest := sDest + '/' + sAgentId_; Guard(SSL, TIdSSLIOHandlerSocketOpenSSL.Create(nil)); SSL.SSLOptions.Method := sslvSSLv23; SSL.SSLOptions.SSLVersions := [sslvTLSv1_2, sslvTLSv1_1, sslvTLSv1]; Guard(HTTP, TIdHTTP.Create(nil)); HTTP.IOHandler := SSL; with HTTP do begin HandleRedirects := true; Request.Clear; Request.UserAgent := 'Mozilla/5.0'; Request.ContentType := 'application/xml'; Request.AcceptCharSet := 'UTF-8'; // Request.Connection := 'Keep-Alive'; // Request.CustomHeaders.Values['Keep-Alive'] := 'timeout=300, max=100'; Request.Connection := 'close'; HTTPOptions := HTTPOptions - [hoKeepOrigProtocol]; HTTPOptions := HTTP.HTTPOptions + [hoForceEncodeParams]; ConnectTimeout := 3000; ReadTimeout := 3000; end; sTemp := HTTP.Get(sDest); // 보안서약서 비어 있는지 체크 22_0727 16:19:51 kku if (sTemp <> '') and sTemp.EndsWith('null}') then sEulaContent_ := ''; end; if (sTemp <> '') and (sEulaContent_ <> sTemp) then begin sEulaContent_ := sTemp; if AgentModel_.EulaTxt <> sEulaContent_ then begin AgentModel_.EulaTxt := sEulaContent_; AgentModel_.Save; end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. PopupLicensed() .. GetEulaContent ..'); end; if sEulaContent_ <> '' then sTemp := sEulaContent_ else sTemp := AgentModel_.EulaTxt; SendMessage(hRcvHwnd_, WM_POPUP_LICENSE, 0, NativeInt(sTemp)); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. PopupLicensed()'); end; end; procedure TManagerService.PopupAfterReport; begin try if hRcvHwnd_ = 0 then exit; // if not IsUseAfterReport then // exit; if MutexExists(MUTEX_AFTERREPORT) then exit; if AgentModel_.AfterRptDT = 0 then begin AgentModel_.AfterRptDT := Now; AgentModel_.Save; end; SendMessage(hRcvHwnd_, WM_POPUP_AFTERREPORT, 0, 0); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. PopupAfterReport()'); end; end; procedure TManagerService.RefreshView; begin if (hRcvHwnd_ <> 0) then SendMessage(hRcvHwnd_, WM_REFRESH_VIEW, 0, 0); end; procedure TManagerService.UpdateScreenLogo(bForce: Boolean = false); begin if (hRcvHwnd_ <> 0) then SendMessage(hRcvHwnd_, WM_UPDATE_SCREENLOGO, BooleanToInt(bForce, 1, 0), 0); end; procedure TManagerService.DoCheckOsUpdate; begin if ThdOsUpdateScan_ <> nil then ThdOsUpdateScan_.DoCheckUpdate; end; procedure TManagerService.ProcessVpnConnect; var sPath: String; begin if IsUseCaller then begin sPath := GetRunExePathDir + DIR_CONF + EXE_IC; if FileExists(sPath) then ExecutePath_hide(sPath); end; if hRcvHwnd_ <> 0 then PostMessage(hRcvHwnd_, WM_REFRESH_CLIPBOARDCHAIN, 0, 0); bDoEmpNoCheck_ := IsCheckEmpNo and PrefModel.IsEmpVerify; if ModePolicy.UsbBlockKind = ubkBlock then DoEjectUsbDrives; PopupLicensed; end; procedure TManagerService.ProcessVpnDisconnect; begin ActiveConnectList.Clear; bIsTemporaryConn_ := false; bIsServiceAvailable_ := false; if IsUseCaller then TerminateProcessByName(EXE_IC); end; function TManagerService.IsOfflineMode: Boolean; var sIp, sMac: String; nOffIfSec: Integer; begin Result := false; try // 매니저 연결 해제 후 5분 후에 Offline 모드로 변경 24_0619 09:38:57 kku if bIsNewApi_ then begin // 2.7의 경우 항상 Result가 false로 처리됨. if IsCJ_Affiliates then begin // CJ는 사번 미인증 상태가 오프라인 모드 24_1218 13:53:43 kku bIsOffline_ := (sEmpNo_ = CJ_EMPTY_EMPNO); // or not bIsEmpNoOk_; end else if not bIsConnected_ and not bIsOffline_ then begin if dtApDisconn_ = 0 then dtApDisconn_ := Now; case CUSTOMER_TYPE of CUSTOMER_KDNVN : nOffIfSec := 60; else nOffIfSec := 300; end; var dwOverSec: DWORD := dwStatusInterval_; if dwOverSec = 0 then dwOverSec := PrefModel_.HealthCheckMilSec; if dwOverSec > 1000 then dwOverSec := ((dwOverSec div 1000) * 2) + nOffIfSec else dwOverSec := nOffIfSec; // 5분동안 서버 미접이면 오프라인 24_0422 09:50:46 kku // 기존 nOffIfSec에서 (통신주기 * 2) + nOffIfSec으로 변경 24_0919 14:49:55 kku if SecondsBetween(Now, dtApDisconn_) > dwOverSec then bIsOffline_ := true; end; end else begin sIp := NicService.GetIP; sMac := NicService.GetMAC; if bIsOffline_ then begin if gMgSvc.NicService.IsActiveAP then begin bIsOffline_ := false; dtApDisconn_ := 0; end else Result := true; end else if not gMgSvc.NicService.IsActiveAP or (sIp = '') or (sIp = IP_NULL) or (sMac = '') or (sMac = MAC_NULL) then begin gMgSvc.SetConnected(false, false); if not bIsOffline_ and PrefOffline_.Loaded then begin if dtApDisconn_ = 0 then dtApDisconn_ := Now; if SecondsBetween(Now, dtApDisconn_) > 60 then bIsOffline_ := true; end; Result := true; end; end; // case CUSTOMER_TYPE of // CUSTOMER_INZENT : // begin // if not bIsConnected_ and not bIsOffline_ then // begin // if dtApDisconn_ = 0 then // dtApDisconn_ := Now; // // // 5분동안 서버 미접이면 오프라인 24_0422 09:50:46 kku // if SecondsBetween(Now, dtApDisconn_) > 300 then // bIsOffline_ := true; // end; // end; // else begin // sIp := NicService.GetIP; // sMac := NicService.GetMAC; // if bIsOffline_ then // begin // if gMgSvc.NicService.IsActiveAP then // begin // bIsOffline_ := false; // dtApDisconn_ := 0; // end else // Result := true; // end else // if not gMgSvc.NicService.IsActiveAP or // (sIp = '') or (sIp = IP_NULL) or // (sMac = '') or (sMac = MAC_NULL) then // begin // gMgSvc.SetConnected(false, false); // if not bIsOffline_ and PrefOffline_.Loaded then // begin // if dtApDisconn_ = 0 then // dtApDisconn_ := Now; // // if SecondsBetween(Now, dtApDisconn_) > 60 then // bIsOffline_ := true; // end; // // Result := true; // end; // end; // end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. IsOfflineMode()'); end; end; function TManagerService.IsSearchingPersonalInfo: Boolean; begin try Result := not bTerminateThdScanSch_ and (ThdScanSch_ <> nil); if Result then case ThdScanSch_.WorkState of tsInit, tsWorking: ; else begin llCampnEncCnt_ := ThdScanSch_.TotalEncCount; llCampnEncFailCnt_ := ThdScanSch_.TotalEncFailCount; if DlgEncCampn_ <> nil then begin DlgEncCampn_.Show; DlgEncCampn_ := nil; end; Result := false; end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. IsSearchingPersonalInfo()'); end; end; procedure TManagerService.StartPiSchTask(aOpt: TFileScanOpt; dtScan: TDateTime; bSendEvent: Boolean = true); var DrvList: TStringList; i: Integer; DrvEx: TTgDriveExtent; sInfoDir: String; begin try if ThdScanSch_ <> nil then FreeAndNil(ThdScanSch_); aOpt.CttSchOpt.sMK := GetMK(false); if dtScan = 0 then dtScan := MgCttSch_.GetTastRecentDT(aOpt.sScanId); if aOpt.CttSchOpt.bIncZip then aOpt.sScanExt := aOpt.sScanExt + '|' + COMPRESS_EXTS; // '|zip'; if aOpt.sTgDirs = '' then begin aOpt.sTgDirs := GetDrivesFromMask(GetLogicalDrives, false, true); if aOpt.sTgDirs = '' then begin _Trace('Fail .. StartPiSchTask(), Not found drive'); exit; end; Guard(DrvEx, TTgDriveExtent.Create); Guard(DrvList, TStringList.Create); SplitString(aOpt.sTgDirs, ',', DrvList); aOpt.sTgDirs := ''; for i := 0 to DrvList.Count - 1 do begin if GetDriveExtent(DrvList[i]).liExtentLength.QuadPart <> 0 then SumString(aOpt.sTgDirs, DrvList[i], '|'); end; if aOpt.sTgDirs = '' then begin _Trace('Fail .. StartPiSchTask(), Not found drive 2'); exit; end; end; sInfoDir := GetRunExePathDir + DIR_CTTSCHRST; if not ForceDirectories(sInfoDir) then _Trace('Fail .. Create sch workdir ..'); sSchRstPath_ := sInfoDir + Format('%s.%s', [aOpt.sScanId, DAT_CTTSCHRSTDATA]); sSchRstExpPath_ := sInfoDir + Format('%s.%s', [aOpt.sScanId, DAT_CTTSCHRSTDATA_EXP]); DeleteFile(PChar(sSchRstPath_)); DeleteFile(PChar(sSchRstExpPath_)); if not FileExists(sInfoDir + Format('%s.%s', [aOpt.sScanId, DAT_CTTSCHOPT])) then begin // DeleteFile(PChar(Format('%s%s.%s', [sInfoDir, aOpt.sScanId, DAT_CTTSCHRST]))); // DeleteFile(PChar(Format('%s%s.%s', [sInfoDir, aOpt.sScanId, DAT_CTTSCHRSTDATA]))); // DeleteFile(PChar(Format('%s%s.%s', [sInfoDir, aOpt.sScanId, DAT_CTTSCHOPT]))); SaveJsonObjToEncFile(TTgJson.ValueToJsonObject(aOpt), sInfoDir + Format('%s.%s', [aOpt.sScanId, DAT_CTTSCHOPT]), PASS_STRENC); end; ThdScanSch_ := TThdSchFileScan.Create(aOpt.sTgDirs, aOpt, dtScan, bSendEvent); ThdScanSch_.OnScanSearchBegin := OnPiSchTaskBegin; ThdScanSch_.OnScanSearchEnd := OnPiSchTaskEnd; ThdScanSch_.StartThread; RefreshView; PopupMessage(TYPE_MSG_CTTSCH_START); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. StartPiSchTask()'); end; end; procedure TManagerService.StopPiSchTask; begin try if ThdScanSch_ <> nil then begin // 다시 검색 되지 않도록 해줌 22_0817 13:21:48 kku if (ThdScanSch_.WorkState = tsWorking) and (ThdScanSch_.CttSchProg.sScanId <> '') then MgCttSch_.CompleteTask(ThdScanSch_.CttSchProg.sScanId, ThdScanSch_.ScanDate); FreeAndNil(ThdScanSch_); RefreshView; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. StopPiSchTask()'); end; end; procedure TManagerService.OnPiSchTaskBegin(aSender: TObject); begin if MgFnd_ <> nil then FreeAndNil(MgFnd_); {$IFDEF DEBUG} DeleteFile(PChar(GetRunExePathDir + JSON_PI_TEST)); {$ENDIF} MgFnd_ := TManagerFound.Create; end; procedure TManagerService.OnPiSchTaskEnd(aSender: TObject); var dtEnd: TDateTime; O, OA: ISuperObject; sCurDir, sScanId, sPath, sTime, sResult: String; bClearData: Boolean; ScanBlockKind: TScanBlockKind; nPersonalInfoFileMax: Integer; begin try if ThdScanSch_ = nil then exit; sScanId := ThdScanSch_.CttSchProg.sScanId; dtEnd := Now; sTime := ConvSecBetweenToProgTime(ThdScanSch_.BeginDT, dtEnd); O := SO; O.S['ID'] := sScanId; O.S['TID'] := ThdScanSch_.CttSchProg.sTaskId; O.S['BeginDT'] := FormatDateTime('yyyy-mm-dd hh:nn:ss', ThdScanSch_.BeginDT); O.S['EndDT'] := FormatDateTime('yyyy-mm-dd hh:nn:ss', dtEnd); O.I['WorkSec'] := SecondsBetween(ThdScanSch_.BeginDT, dtEnd); O.S['WorkTime'] := sTime; O.I['TotalFileCount'] := ThdScanSch_.TotalFileCount; O.I['TargetFileCount'] := ThdScanSch_.TotalTgFileCount; O.I['FoundFileCount'] := ThdScanSch_.FoundFileCount; O.S['FoundSInfo'] := MgFnd_.ToEntInfoStr; O.O['FoundInfo'] := MgFnd_.ToJsonObj; sCurDir := GetRunExePathDir; {$IFDEF DEBUG} SaveJsonObjToFile(O, sCurDir + JSON_PI_TEST); {$ENDIF} sResult := MgFnd_.ToEntInfoStr; if ForceDirectories(sCurDir + DIR_CTTSCHRST) then begin if sScanId <> '' then SaveJsonObjToFile(O, Format('%s%s.%s', [sCurDir + DIR_CTTSCHRST, sScanId, DAT_CTTSCHRST])) else SaveJsonObjToFile(O, sCurDir + DIR_CTTSCHRST + DAT_CTTSCHRST); PopupMessage(TYPE_MSG_CTTSCH_COMPLETE, sTime + '|' + IntToStr(ThdScanSch_.FoundFileCount)); end; bClearData := true; ScanBlockKind := PrefModel_.ScanBlockKind; nPersonalInfoFileMax := PrefModel_.PersonalInfoFileMax; if sScanId <> '' then begin ThdScanSch_.UpdateProgress('complete', true, sResult); MgCttSch_.CompleteTask(sScanId, ThdScanSch_.ScanDate); if (nPersonalInfoFileMax > 0) and (nPersonalInfoFileMax <= ThdScanSch_.FoundFileCount) then begin SetSchRstVul(true); bClearData := false; SendEventLog(URI_USER_ACTION, STATUS_FILESCAN, Format('Found=%d, File=%d', [ThdScanSch_.FoundCount, ThdScanSch_.FoundFileCount])); PopupMessage(TYPE_MSG_CTTSCH_VULMODE); end; end; if nPersonalInfoFileMax = 0 then begin DeleteDir(sCurDir + DIR_CTTSCHRST); end else if bClearData then begin DeleteFile(PChar(Format('%s%s.%s', [sCurDir + DIR_CTTSCHRST, sScanId, DAT_CTTSCHRST]))); DeleteFile(PChar(Format('%s%s.%s', [sCurDir + DIR_CTTSCHRST, sScanId, DAT_CTTSCHRSTDATA]))); DeleteFile(PChar(Format('%s%s.%s', [sCurDir + DIR_CTTSCHRST, sScanId, DAT_CTTSCHOPT]))); end; if bSchRstVul_ and (GetPersonalInfoResults = 0) then SetSchRstVul(false); {$IFDEF DEBUG} sPath := GetRunExePathDir + 'PersonalInfo.txt'; if FileExists(sPath) then DeleteFile(PChar(sPath)); WriteLnFileEndUTF8(sPath, sResult); {$ENDIF} if sScanId <> '' then _Trace('ProcessCttSchSchedule() End .. ScanId=%s', [sScanId]); if MgFnd_ <> nil then FreeAndNil(MgFnd_); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. OnPiSchTaskEnd()'); end; llCampnEncCnt_ := ThdScanSch_.TotalEncCount; llCampnEncFailCnt_ := ThdScanSch_.TotalEncFailCount; bTerminateThdScanSch_ := true; RefreshView; end; procedure TManagerService.ProcessPiSchFound(pResult: PSchResult); var StrList, RstList: TStringList; i: Integer; begin try Guard(StrList, TStringList.Create); SplitString(pResult.sSchName, RESULT_SEPARATOR, StrList); Guard(RstList, TStringList.Create); SplitString(pResult.sResultStr, RESULT_SEPARATOR, RstList); {$IFDEF DEBUG} ASSERT(StrList.Count = RstList.Count); {$ELSE} if StrList.Count <> RstList.Count then begin _Trace('Fail .. ProcessPersonalInfoFound() .. SchName <> RstCount'); exit; end; {$ENDIF} pResult.sSchName := ''; // 보정해준다. for i := 0 to StrList.Count - 1 do begin if (i = 0) and (StrList[i] = '*KWD*') then begin MgFnd_.PushFoundKeyword(RstList[i]); end else begin MgFnd_.PushFoundPattern(StrList[i], GetCountOverlapWordsCount(RstList[i])); SumString(pResult.sSchName, ExtractFileName(StrList[i]), ';'); end; end; if ThdScanSch_ <> nil then begin var nProcType: Integer := 0; if IsForcePI and not pResult.bDrm and (PrefModel_.ScanBlockKind = sbkDrmEnc) and FileExists(pResult.sPath) then begin try var sTaskDir: String := 'C:\ProgramData\HE\EncTask\'; if ForceDirectories(sTaskDir) then begin if not TTgEncrypt.CheckSign(pResult.sPath, SIG_DRM) then begin var sTgEncPath: String := GetSameFileNameInc(sTaskDir + '$Tmp' + ExtractFileName(pResult.sPath)); if CopyFile(PChar(pResult.sPath), PChar(sTgEncPath), false) then begin DeleteFile(PChar(pResult.sPath)); SaveStrToFile(sTgEncPath + '.i', pResult.sPath, TEncoding.UTF8); var enc: TTgDrmEnc; var sDept: String := sDeptName_; if sDept = '' then sDept := PrefModel_.DeptName; var bResult: Boolean := false; enc := TTgDrmEnc.Create(pResult.sPath); try enc.SetHaed(PASS_DRM_HEAD, SIG_DRM, sEmpNo_, sUserName_, sDept, PrefModel_.PolicyName, CUSTOMER_TYPE); bResult := enc.EncryptFromFile(GetMK, sTgEncPath); finally FreeAndNil(enc); end; if bResult then begin DeleteFile(PChar(sTgEncPath)); DeleteFile(PChar(sTgEncPath + '.i')); nProcType := 1; SendEventLog(URI_USER_ACTION, PREVENT_DRM_ENCRYPT, pResult.sPath); end else begin // MoveFile_wait(sTgEncPath, pResult.sPath, 3); if CopyFile(PChar(sTgEncPath), PChar(pResult.sPath), false) then DeleteFile(PChar(sTgEncPath)); DeleteFile(PChar(sTgEncPath + '.i')); TTgTrace.T('Fail .. MgSvc.ProcessPiSchFound.EncFile(), Path=%s', [pResult.sPath]); end; end; end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. ProcessPersonalInfoFound() .. enc'); end; end else if IsForcePI and not pResult.bDrm and (PrefModel_.ScanBlockKind = sbkDelete) and FileExists(pResult.sPath) then begin if PerfectDeleteFile(pResult.sPath, 3) then nProcType := 2; end else if (ThdScanSch_.CttSchProg.sScanId <> '') and MgCttSchExp_.HasFileHash(pResult.sPath) then // 파일 해시로 예외 체크 추가 23_0414 09:58:24 kku nProcType := 3; if (nProcType = 0) and not pResult.bDrm then begin // DRM 파일은 취약 카운트에 포함하지 않음 22_1123 15:27:15 kku ThdScanSch_.IncFoundCount(pResult.nHitCnt); ThdScanSch_.IncFoundFileCount; end; if ThdScanSch_.CttSchProg.sScanId <> '' then begin if ThdScanSch_.IsSendEvent then SendCttSchDetailInfo(ThdScanSch_.CttSchProg.sTaskId, pResult, nProcType); if sSchRstPath_ <> '' then with pResult^ do WriteLnFileEndUTF8(sSchRstPath_, Format('%s%d%s%s%s', [sSchName, nHitCnt, sPath, RstList.CommaText, sFName])); if (nProcType = 3) and (sSchRstExpPath_ <> '') then with pResult^ do WriteLnFileEndUTF8(sSchRstExpPath_, pResult.sPath); end else begin with pResult^ do WriteLnFileEndUTF8(GetRunExePathDir + DIR_CTTSCHRST + DAT_CTTSCHRSTDATA, Format('%s%d%s%s%s', [sSchName, nHitCnt, sPath, RstList.CommaText, sFName])); end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. ProcessPersonalInfoFound()'); end; end; procedure TManagerService.ProcessCampnFound(pResult: PSchResult); var i: Integer; StrList, RNameList, RstList: TStringList; bCollectFile: Boolean; Respaction: TCampnRespaction; sTemp: String; begin try if ThdScanSch_ = nil then exit; if pProcCampn_ = nil then exit; Guard(StrList, TStringList.Create); SplitString(pResult.sSchName, RESULT_SEPARATOR, StrList); Guard(RstList, TStringList.Create); SplitString(pResult.sResultStr, RESULT_SEPARATOR, RstList); Guard(RNameList, TStringList.Create); for i := 0 to StrList.Count - 1 do begin if (i = 0) and (StrList[i] = '*KWD*') then begin MgFnd_.PushFoundKeyword(RstList[i]); end else begin sTemp := MgRule_.GetRuleNameFromId(StrList[i]); RNameList.Add(sTemp); MgFnd_.PushFoundPattern(sTemp, GetCountOverlapWordsCount(RstList[i])); // SumString(pResult.sSchName, ExtractFileName(StrList[i]), ';'); end; end; if pResult.nHitCnt > 0 then begin bCollectFile := pProcCampn_.Info.bGetFile; // and not pResult.bDrm; Respaction := pProcCampn_.Info.Respaction; ThdScanSch_.IncFoundCount(pResult.nHitCnt); ThdScanSch_.IncFoundFileCount; // if not pResult.bDrm then // _Trace('CampnFound .. Path=%s', [pResult.sPath], 9); end else begin bCollectFile := false; if pProcCampn_.Info.CampnType = ctForceEnc then begin if IsUseEncOnlyAIP or bFirstAip_ then Respaction := crtAIP else if not NotUseDRM then Respaction := crtDRM; end; end; case Respaction of crtDRM, crtAIP: begin if pResult.bMakeDrm or pResult.bDrm then ThdScanSch_.IncEncFileCount else ThdScanSch_.IncEncFailFileCount; end; crtDelete, crtPerDel : ThdScanSch_.IncDelFileCount; else begin if pResult.bDrm then ThdScanSch_.IncEncFileCount; end; end; if pResult.sResultStr = '*NoMatch*' then // 증분 재검사 시 검출된거 없는거 구분... 24_0620 18:19:09 kku begin // 증분검사, 기본결과유지 - 재검사 시 검출 안된 경우 목록에서 빼주기 24_0611 10:10:04 kku NoMatchList_.Add(pResult.sPath); exit; end else begin var unableFile: Boolean; unableFile:= False; if Pos('unable to analysis', pResult.sResultStr) > 0 then begin bCollectFile:= True; unableFile:= True; _Trace('[MGKIM] unable to analysis ok'); end; MgCampn_.SendCampaignResultFile(ThdScanSch_.CttSchProg.sTaskId, pResult, ThdScanSch_.FoundFileCount, bCollectFile, pProcCampn_.Info.CttSchLimitMB, Respaction); // llProc 이거 값 업데이트 확인 // if pResult.bMakeDrm and (pResult.nHitCnt = 0) then if (pResult.nHitCnt = 0) and not unableFile then // 일반파일 암호화 실패시 목록에 포함되지 않도록 수정 24_0112 08:48:44 kku exit; end; if not bCollectFile then begin case Respaction of // 암호화 이미 처리됨 crtDelete, crtPerDel: ThdReact_.AddEnt(Respaction, pResult.sPath); end; end; case pProcCampn_.Info.CampnType of ctScan, ctScanPatial : begin if ThdScanSch_.CttSchProg.sScanId <> '' then begin if pProcCampn_.sSchRstPath <> '' then begin with pResult^ do begin WriteLnFileEndUTF8(pProcCampn_.sSchRstPath, Format('%s%d%s%s%s%s%s', [RNameList.CommaText, nHitCnt, sPath, RstList.CommaText, sFName, pResult.sSchName, pResult.sResultStr])); // 증분검사 결과에서 결과 정보 합치기를 위해 추가 24_0423 13:54:42 kku end; end; // if (nProcType = 3) and (sSchRstExpPath_ <> '') then // with pResult^ do // WriteLnFileEndUTF8(sSchRstExpPath_, pResult.sPath); end; end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. ProcessCampnFound()'); end; end; procedure TManagerService.UpdateCttSchVulState(bForce: Boolean = false); begin if not IsUsePiVul then exit; if bForce or bSchRstVul_ then begin // 개인정보검출결과 초과 취약 체크 24_0311 15:20:05 kku SetSchRstVul(MgCampn_.GetNoActionVulCampaign <> nil); end; end; function TManagerService.ProcessMergeCampaignBkData(OInfo: ISuperObject): Integer; var sInfoDir, sSchRstPath, sInfoPath, sInfoPathBk, sSchRstPathBk: String; StrList, DataList, SchList, RstList: TStringList; i, c: Integer; sPath, sFrName, sLine: String; MgCampExpt: TManagerCampExcept; MgFnd: TManagerFound; DcData: TDictionary; ONew, OOld: ISuperObject; enum: TEnumerator; bCatLine: Boolean; begin Result := 0; try if ThdScanSch_ <> nil then Result := ThdScanSch_.FoundFileCount; if pProcCampn_ = nil then exit; sSchRstPathBk := GetRunExePathDir + DIR_CTTSCHRST_BACKUP + Format('%s.%s', [pProcCampn_.Info.sId, DAT_CTTSCHRSTDATA]); if not FileExists(sSchRstPathBk) then exit; sInfoPathBk := GetRunExePathDir + DIR_CTTSCHRST_BACKUP + Format('%s.%s', [pProcCampn_.Info.sId, DAT_CTTSCHRST]); sInfoDir := GetRunExePathDir + DIR_CTTSCHRST; if not ForceDirectories(sInfoDir) then exit; sSchRstPath := sInfoDir + Format('%s.%s', [pProcCampn_.Info.sId, DAT_CTTSCHRSTDATA]); sInfoPath := sInfoDir + Format('%s.%s', [pProcCampn_.Info.sId, DAT_CTTSCHRST]); if not FileExists(sSchRstPath) and (NoMatchList_.Count = 0) then begin CopyFile(PChar(sSchRstPathBk), PChar(sSchRstPath), false); // MoveFile_wait(sSchRstPathBk, sSchRstPath); if FileExists(sInfoPathBk) then CopyFileAfOpenCheck(sInfoPathBk, sInfoPath); // MoveFile_wait(sInfoPathBk, GetRunExePathDir + DIR_CTTSCHRST + Format('%s.%s', [pProcCampn_.Info.sId, DAT_CTTSCHRST])); if LoadJsonObjFromFile(OOld, sInfoPath) then begin OOld.S['BeginDT'] := OInfo.S['BeginDT']; OOld.S['EndDT'] := OInfo.S['EndDT']; OOld.I['WorkSec'] := OInfo.I['WorkSec']; OOld.S['WorkTime'] := OInfo.S['WorkTime']; OOld.B['INC'] := true; SaveJsonObjToFile(OOld, sInfoPath); end; exit; end; Guard(StrList, TStringList.Create); Guard(DataList, TStringList.Create); Guard(SchList, TStringList.Create); Guard(RstList, TStringList.Create); Guard(MgCampExpt, TManagerCampExcept.Create); Guard(MgFnd, TManagerFound.Create); Guard(DcData, TDictionary.Create); sLine := ''; bCatLine := false; // 직전 데이터 추출 StrList.LoadFromFile(sSchRstPathBk, TEncoding.UTF8); for i := 0 to StrList.Count - 1 do begin if StrList[i] = '' then continue; if bCatLine then begin sLine := sLine + StringReplace(StrList[i], #13#10, ' ', [rfReplaceAll]); bCatLine := false; end else sLine := StringReplace(StrList[i], #13#10, ' ', [rfReplaceAll]); SplitString(sLine, '', DataList, true); if (DataList.Count < 7) or ( (i < StrList.Count - 1) and (Pos('', StrList[i + 1]) = 0) ) then begin bCatLine := true; continue; end; sPath := UpperCase(DataList[2]); if (not sPath.StartsWith('\\') and not FileExists(sPath)) or MgCampExpt.IsExceptFile(sPath) then continue; if (NoMatchList_.Count > 0) and (NoMatchList_.IndexOf(sPath) <> -1) then continue; if (DataList.Count >= 5) and (DataList[4] <> '') then sPath := sPath + ':' + DataList[4]; // 압축파일에 포함된 파일정보의 경우 존재 try DcData.Add(sPath, sLine); except // 중복등 예외 넘김 continue; end; end; NoMatchList_.Clear; sLine := ''; bCatLine := false; // 증분검사 데이터 추출 if FileExists(sSchRstPath) then begin StrList.LoadFromFile(sSchRstPath, TEncoding.UTF8); for i := 0 to StrList.Count - 1 do begin if StrList[i] = '' then continue; if bCatLine then begin sLine := sLine + StringReplace(StrList[i], #13#10, ' ', [rfReplaceAll]); bCatLine := false; end else sLine := StringReplace(StrList[i], #13#10, ' ', [rfReplaceAll]); SplitString(sLine, '', DataList, true); if (DataList.Count < 7) or ( (i < StrList.Count - 1) and (Pos('', StrList[i + 1]) = 0) ) then begin bCatLine := true; continue; end; sPath := UpperCase(DataList[2]); if not FileExists(sPath) or MgCampExpt.IsExceptFile(sPath) then continue; if (DataList.Count >= 5) and (DataList[4] <> '') then sPath := sPath + ':' + DataList[4]; // 압축파일에 포함된 파일정보의 경우 존재 if DcData.ContainsKey(sPath) then begin // 이전에 있던거라면 과거 데이터를 삭제 DcData.Remove(sPath); end; DcData.Add(sPath, sLine); end; end; Result := DcData.Count; StrList.Clear; if Result > 0 then begin Guard(enum, DcData.Values.GetEnumerator); while enum.MoveNext do begin StrList.Add(enum.Current); SplitString(enum.Current, '', DataList, true); if DataList.Count > 6 then begin SplitString(DataList[5], RESULT_SEPARATOR, SchList); SplitString(DataList[6], RESULT_SEPARATOR, RstList); for c := 0 to SchList.Count - 1 do begin if (c = 0) and (SchList[c] = '*KWD*') then MgFnd.PushFoundKeyword(RstList[c]) else MgFnd.PushFoundPattern(MgRule_.GetRuleNameFromId(SchList[c]), GetCountOverlapWordsCount(RstList[c])); end; end; end; end; StrList.SaveToFile(sSchRstPath, TEncoding.UTF8); if LoadJsonObjFromFile(ONew, sInfoPath) and LoadJsonObjFromFile(OOld, sInfoPathBk) then begin // O.I['TotalFileCount'] := ThdScanSch_.TotalFileCount; // O.I['TargetFileCount'] := ThdScanSch_.TotalTgFileCount; ONew.S['BeginDT'] := OInfo.S['BeginDT']; ONew.S['EndDT'] := OInfo.S['EndDT']; ONew.I['WorkSec'] := OInfo.I['WorkSec']; ONew.S['WorkTime'] := OInfo.S['WorkTime']; ONew.I['FoundFileCount'] := Result; ONew.S['FoundSInfo'] := MgFnd.ToEntInfoStr; ONew.O['FoundInfo'] := MgFnd.ToJsonObj; ONew.B['INC'] := true; SaveJsonObjToFile(ONew, sInfoPath); end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. ProcessMergeCampaignBkData()'); end; end; procedure TManagerService.AddFileExpEnt(sPath, sHash: String); var i: Integer; pEnt: PFileExpEnt; begin try Lock; try for i := 0 to FileExpEntList_.Count - 1 do begin pEnt := FileExpEntList_[i]; if CompareText(sPath, pEnt.sPath) = 0 then begin pEnt.sHash := sHash; pEnt.dtReg := Now; exit; end; end; New(pEnt); pEnt.sPath := sPath; pEnt.sHash := sHash; pEnt.dtReg := Now; FileExpEntList_.Add(pEnt); finally Unlock; SaveFileExpEnt; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. AddFileExpEnt()'); end; end; procedure TManagerService.SaveFileExpEnt; var O, OA: ISuperObject; i: Integer; begin try OA := TSuperObject.Create(stArray); Lock; try for i := 0 to FileExpEntList_.Count - 1 do OA.AsArray.Add(TTgJson.ValueToJsonObject(FileExpEntList_[i]^)); finally Unlock; end; O := SO; O.O['List'] := OA; SaveJsonObjToEncFile(O, GetRunExePathDir + DIR_CONF + DAT_FILEEXP, PASS_STRENC); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. SaveFileExpEnt()'); end; end; procedure TManagerService.LoadFileExpEnt; var sPath: String; O: ISuperObject; i: Integer; pEnt: PFileExpEnt; begin try Lock; try FileExpEntList_.Clear; finally Unlock; end; sPath := GetRunExePathDir + DIR_CONF + DAT_FILEEXP; if LoadJsonObjFromEncFile(O, sPath, PASS_STRENC) then begin if (O.O['List'] = nil) or (O.O['List'].DataType <> stArray) then exit; Lock; try for i := 0 to O.A['List'].Length - 1 do begin New(pEnt); pEnt^ := TTgJson.GetDataAsType(O.A['List'].O[i]); FileExpEntList_.Add(pEnt); end; finally Unlock; end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. LoadFileExpEnt()'); end; end; procedure TManagerService.OrganizeFileExpEnt; var i, nLimitMin: Integer; pEnt: PFileExpEnt; dwNow: TDateTime; bSave: Boolean; begin try bSave := false; dwNow := Now; nLimitMin := PrefModel_.FileExpMin; Lock; try for i := FileExpEntList_.Count - 1 downto 0 do begin pEnt := FileExpEntList_[i]; if MinutesBetween(pEnt.dtReg, dwNow) >= nLimitMin then begin FileExpEntList_.Delete(i); bSave := true; end; end; finally Unlock; end; if bSave then SaveFileExpEnt; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. OrganizeFileExpEnt()'); end; end; function TManagerService.HasFileExp(sPath: String): Boolean; var i: Integer; pEnt: PFileExpEnt; bOutlook: Boolean; StrList: TStringList; sHash: String; begin Result := false; StrList := nil; bOutlook := Pos('|', sPath) > 0; if bOutlook then begin // 아웃룩 첨부 확인 추가 25_1112 14:58:02 kku StrList := TStringList.Create; SplitString(sPath, '|', StrList); if StrList.Count <= 1 then begin // 서명, 본문 이미지의 경우 해시값이 없이 들어온다, 이 경우 예외 처리 25_1203 11:01:18 kku Result := true; exit; end; sHash := StrList[0]; var sExt: String := GetFileExt(sHash).ToUpper; // 서명등 본문에 들어가는 이미지를 식별해서 예외 25_1203 10:49:17 kku if sHash.ToLower.StartsWith('image0') and ( (sExt = 'PNG') or (sExt = 'JPG') or (sExt = 'JPEG') or (sExt = 'BMP')) then Exit(true); sHash := StrList[1]; end else begin if not FileExists(sPath) then exit; sHash := GetFileToSha1Str_BS1(sPath); end; _Trace('HasFileExp() .. Path=%s, Hash=%s, FileExpCount=%d', [sPath, sHash, FileExpEntList_.Count], 5); Lock; try for i := 0 to FileExpEntList_.Count - 1 do begin pEnt := FileExpEntList_[i]; // if bOutlook then // begin // if (CompareText(StrList[0], pEnt.sPath) = 0) and // (CompareText(StrList[1], pEnt.sHash) = 0) then // begin // Result := true; // exit; // end; // end else // if (CompareText(sPath, pEnt.sPath) = 0) and // (CompareText(GetFileToSha1Str(sPath), pEnt.sHash) = 0) then // begin // Result := true; // exit; // end; if CompareText(sHash, pEnt.sHash) = 0 then begin _Trace('HasFileExp() .. Found', 5); Result := true; exit; end; end; finally Unlock; end; end; procedure TManagerService.DoPrint(pEnt: PPrtEnt); function GetPrintLog: ISuperObject; var O, OSub, OLog: ISuperObject; sCompId: String; sMsg: String; PO: TPrefModel; dt: TDateTime; begin Result := nil; try sMsg := Format('Printer : %s, Document : %s', [pEnt.WInfo.sPtrName, pEnt.WInfo.sDocName]); PO := GetModePolicy; dt := Now; O := SO; O.S['TYP_MSG'] := '@(!)_IC_P'; O.S['KEY_AGENTID'] := sAgentId_; O.S['KEY_EMPNO'] := sEmpNo_; O.S['KEY_HOSTNAME'] := sUserName_; O.S['KEY_SUBMITTIME'] := FormatDateTime('yyyy-mm-dd hh:nn:ss', dt); O.S['key_submitTime'] := FormatDateTime('yyyy-MM-dd"T"hh:nn:ss.zzz', dt) + sUtcOffset_; O.S['KEY_LOGCODE'] := LOGCODE_EVENT_PRINTER; O.S['DETECTION_DATE'] := O.S['KEY_SUBMITTIME']; // 이벤트 발생 시각. REQUEST의 경우, 예외 신청할 이벤트의 발생 시각 O.S['detectionDate'] := O.S['key_submitTime']; // 이벤트 발생 시각. REQUEST의 경우, 예외 신청할 이벤트의 발생 시각 O.S['KEY_SUMMARY'] := sMsg; // O.S['PARENT_LA_ID'] // 상위 이벤트 O.S['POLICY_ID'] := PO.PolicyId; // O.S['POLICY_KEY'] // 정책 위반한 경우 (PREVENT, MONITOR), 위반한 정책의 정책 키 값, 수집인 경우 (DEPLOY), 수집 요청 ID if PO.Print.bCollectOutput then begin O.S['MESSAGE_BODY'] := pEnt.sText; // 정책 위반한 경우 (PREVENT, MONITOR), 원문 (본문) 컨텐츠, 수집인 경우 (DEPLOY), 수집 결과 내용, 원문 수집 정책이 비활성화인경우 수집하지 않음 O.S['OCR_BODY'] := pEnt.sOcrText; // 이미지 OCR 추출된 컨텐츠, 원문 수집 정책이 비활성화인 경우 수집하지 않음 end; if pEnt.sVioText <> '' then O.S['RULE_VIOLATED'] := pEnt.sVioText; // 정책 위반 규칙과 위반 개수. (LIST) if FileExists(pEnt.sFPath) then begin if PO.Print.bCollectFile then begin sCompId := MakeComponentId(ExtractFileName(pEnt.sFPath)); // SendFile(sCompId, 'printLogCollect.do', sDocPath); // 원본 파일 수집은 이걸로 하면 안됨 24_0122 16:52:00 kku SendFileNor(false, sCompId, 'quarantineLogCollect.do', pEnt.sFPath, PO.PrtMinMB, PO.PrtMaxMB); O.S['COMPONENT_ID'] := sCompId; // 파일 고유값. 에이전트에서 임의 생성. (이벤트간 동일 파일 판단은 서버에서 하겠습니다.) end; O.S['COMPONENT_FILENAME'] := ExtractFileName(pEnt.sFPath); // 파일명 O.S['COMPONENT_PATH'] := ExtractFilePath(pEnt.sFPath);// 파일 절대 경로 var dtCreate, dtModify, dtAccess: TDateTime; GetFileDateTime_Local(pEnt.sFPath, dtCreate, dtModify, dtAccess); var dwAttr: DWORD := GetFileAttributes(PChar(pEnt.sFPath)); var OTemp: ISuperObject := SO; OTemp.S['FILESIZE'] := IntToStr(GetFileSize_path(pEnt.sFPath)); OTemp.S['LASTMODIFIED'] := FormatDateTime('yyyy-mm-dd hh:nn:ss', dtModify); if dwAttr <> DWORD(-1) then OTemp.S['READONLY'] := BooleanToStr((dwAttr and FILE_ATTRIBUTE_READONLY) <> 0, 'true', 'false'); if dwAttr <> DWORD(-1) then OTemp.S['HIDDEN'] := BooleanToStr((dwAttr and FILE_ATTRIBUTE_HIDDEN) <> 0, 'true', 'false'); // OTemp.S['AUTHOR'] // {만든 이} // OTemp.S['LASTUSER'] // {마지막으로 저장한 사람} // OTemp.S['FILETYPE'] // {컨텐츠 타입} // OTemp.S['FILECLS'] // {컨텐츠 형식} // OTemp.S['PASSWORD'] // {암호적용여부} // OTemp.S['ENCRYPTED'] := BooleanToStr(pInfo.bDrm, 'true', 'false'); // OTemp.S['CORRUPT'] // {깨진파일/정상파일여부} O.O['COMPONENT_METADATA'] := OTemp; O.S['COMPONENT_LASTACCESS'] := FormatDateTime('yyyy-mm-dd hh:nn:ss', dtAccess); end; O.S['COMPONENT_THUMBNAIL_ID'] := pEnt.sThumbIds; // 이미지 미리보기 혹은 이미지가 있는경우, 이미지 파일의 파일 고유값. (출력물의 경우 첫 3장 이미지, 캡쳐 이미지 등), 복수개 허용, ";" 구분 // O.S['APPLICATION_NAME'] := sPName; // 사용 APP 이름 // O.S['APPLICATION_PATH'] := sPPath;// 사용 APP 절대 경로 (실행 파일 exe의 절대 경로) O.S['PRINTER_JOBNAME'] := pEnt.WInfo.sDocName; if pEnt.WInfo.bUseWM then O.S['RESPONSE_INFO'] := 'WATERMARK'; // OSub.S['PAPERINFO'] := pEnt.WInfo.OLog; O.S['DESTINATION_PORT'] := pEnt.WInfo.sPrtIp; OSub := SO; OSub.S['PAGEINFO'] := Format('%d/%d', [pEnt.WInfo.dwTotalPage, pEnt.WInfo.dwTotalPage]); OSub.S['COLOR'] := BooleanToStr(pEnt.WInfo.bColor, 'true', 'false'); OSub.S['WARTERMARK'] := BooleanToStr(pEnt.WInfo.bUseWM, 'true', 'false'); OSub.S['PAPERINFO'] := pEnt.WInfo.sPaperInfo; O.O['PRINTER_METADATA'] := OSub; // '{"PAGEINFO": "2/2", "COLOR": "true", "WARTERMARK": "false"}'; O.S['REMOVABLE_NAME'] := pEnt.WInfo.sPtrName; // USB등과 같은 매체 혹은 프린터 등과 같은 외부 장치 이름 O.S['actionGroupId'] := pEnt.WInfo.sPrtDocId; // 문서번호 O.I['printCopyCnt'] := pEnt.WInfo.dwCopy; // 부수 O.I['printPageCnt'] := pEnt.WInfo.dwTotalPage; // 장수 Result := O; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. SendEventLog()'); end; end; var sConv, sEmfZip, sEmfDir, sSplPath, sDecPath, sExportPath: String; dec : TTgDrmDec; bDecResult: Boolean; begin try sConv := GetRunExePathDir + DIR_CONF + EXE_SPL; if not FileExists(sConv) then begin _Trace('Fail .. DoPrint() .. NotFoundConv'); exit; end; // 최대 출력수 확인 // if pEnt.nPrtCnt > 3 then // begin // MgPrint_.DelPrintInfo(pEnt.sId, true); // exit; // end; // // Inc(pEnt.nPrtCnt); // MgPrint_.Save; sEmfZip := MgPrint_.DataDir + pEnt.sId + '.dat'; if FileExists(sEmfZip) then begin var zip: TZipFile; Guard(zip, TZipFile.Create); zip.Open(sEmfZip, zmRead); sEmfDir := MgPrint_.DataDir + pEnt.sId + '\'; if not ForceDirectories(sEmfDir) then begin _Trace('Fail .. DoPrint() .. CreateDir(zip)'); exit; end; zip.ExtractAll(sEmfDir); SendMessage(hRcvHwnd_, WM_POPUP_PRINTWATER_PROGRESS, 1, NativeUInt(PChar(IntToStr(pEnt.WInfo.dwTotalPage) + '|' + ExtractFilePath(sDecPath) + '|' + pEnt.sFPath))); SendMessage(gMgSvc.RcvHwnd, WM_POPUP_PRTW_PROGRESS, 1, 0); TThdExecuteEndNoti.Create(hRcvHwnd_, GetPrintLog, pEnt, '', '', '', '', nil).StartThread; // SendMessage(hRcvHwnd_, WM_NOTIEXECUTE_END, 1, NativeUInt(pEnt)); end else begin // 복호화 24_1002 15:37:38 kku sSplPath := MgPrint_.DataDir + pEnt.sId + '.pdt'; sDecPath := MgPrint_.DataDir + pEnt.sId + '\Tdel.dsp'; if not ForceDirectories(ExtractFilePath(sDecPath)) then begin _Trace('Fail .. DoPrint() .. MakeTaskDir'); exit; end; dec := TTgDrmDec.Create(sSplPath); bDecResult := true; try if not dec.CheckSig(SIG_DRM) then bDecResult := false; if bDecResult and not dec.ExtrHead(PASS_DRM_HEAD) then bDecResult := false; if bDecResult and (dec.Head.dwCustomerCode <> CUSTOMER_TYPE) then bDecResult := false; // todo : 권한 체크 if bDecResult then begin // 암호화 대응 제외 gMgSvc.AddEncIgr(sDecPath); bDecResult := dec.DecryptToFile(GetMK + '&PtR', sDecPath); end; finally FreeAndNil(dec); end; if not bDecResult then begin _Trace('Fail .. DoPrint() .. DecryptSpool'); exit; end; sExportPath := ExtractFilePath(sDecPath) + ExtractFileName(pEnt.sFPath) + '.png'; // {$IFNDEF DEBUG} if IsPrtSpl2Pdf then begin case CUSTOMER_TYPE of CUSTOMER_SHCI, CUSTOMER_SHSC : begin if (CompareText('InsideBank.exe', pEnt.sPName) <> 0) and (CompareText('excel.exe', pEnt.sPName) <> 0) and (CompareText('POWERPNT.EXE', pEnt.sPName) <> 0) and (CompareText('Hwp.exe', pEnt.sPName) <> 0) then sExportPath := CutFileExt(sExportPath) + '.pdf'; end; // CUSTOMER_SHCI : // begin // if (CompareText('InsideBank.exe', pEnt.sPName) <> 0) and // (CompareText('Hwp.exe', pEnt.sPName) <> 0) then // sExportPath := CutFileExt(sExportPath) + '.pdf'; // end; end; end; // {$ENDIF} SendMessage(hRcvHwnd_, WM_POPUP_PRINTWATER_PROGRESS, 1, NativeUInt(PChar(IntToStr(pEnt.WInfo.dwTotalPage) + '|' + ExtractFilePath(sDecPath) + '|' + pEnt.sFPath))); SendMessage(gMgSvc.RcvHwnd, WM_POPUP_PRTW_PROGRESS, 1, 0); var sParam: String := Format('-$ 65XSD4234455S4PLET58 -unicode -imgbitcount 24 -imgxres %d -imgyres %d', [PrefModel_.PrtDPI, PrefModel_.PrtDPI]) + ' "%s" "%s"'; TThdExecuteEndNoti.Create(hRcvHwnd_, GetPrintLog, pEnt, sConv, sParam, sDecPath, sExportPath, nil).StartThread; // SendMessage(gMgSvc.RcvHwnd, WM_POPUP_PRTW_PROGRESS, 2, 0); end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. DoPrint()'); end; end; procedure TManagerService.StartCampaignTask(pCamEnt: PCampnEnt); var Opt: TFileScanOpt; DrvList: TStringList; i: Integer; DrvEx: TTgDriveExtent; sInfoDir: String; PO: TPrefModel; bContinue: Boolean; begin //exit; try if pCamEnt = nil then exit; if pProcCampn_ <> nil then exit; if ThdScanSch_ <> nil then FreeAndNil(ThdScanSch_); {$IFNDEF DEBUG} // 프로그램 시작 후 30초 후에 동작하도록 보완 24_0516 09:47:58 kku if SecondsBetween(dtCreateMg_, Now) < 30 then exit; {$ENDIF} if CUSTOMER_TYPE = CUSTOMER_DEV then begin if bFirstAip_ then FindAipMdWnd; end else if IsSupportAIP then FindAipMdWnd; if pCamEnt.Info.CampnType = ctVul then begin // 현재 지원하지 않음 23_1113 13:04:17 kku pCamEnt.dtLastWork := Now; MgCampn_.Save; exit; end; // sInfoDir := ExtractFilePath(pCamEnt.sSchRstPath); //// if pCamEnt.Info.CampnType <> ctScanPatial then // 증분 검사 시 이전기록 삭제안하게 23_1122 15:08:26 kku // begin // if (sInfoDir <> '') and DirectoryExists(sInfoDir) then // DeleteDir(sInfoDir); // end; pCamEnt.sSchRstPath := ''; pCamEnt.sSchRstExpPath := ''; NoMatchList_.Clear; PO := GetModePolicy; bIsStopCampn_ := false; llCampnEncCnt_ := 0; llCampnEncFailCnt_ := 0; ZeroMemory(@Opt, SizeOf(Opt)); Opt.sSchPtrns := ''; // 이거 비어 있으면 ptnsch.dat 파일에서 체크된 항목 검사됨 Opt.sScanId := pCamEnt.Info.sId; Opt.sSchTitle := pCamEnt.Info.sName; Opt.bShowSchTitle := pCamEnt.Info.bShowScan; Opt.nLimitSizeMB := pCamEnt.Info.nLimitSizeMB; // PO.CfLimitMB; Opt.nSchTimeoutSec := pCamEnt.Info.nTimeoutSec; // PO.CfTimeoutSec; Opt.sIgrWordPath := pCamEnt.Info.sExpFolders; Opt.bPartScan := pCamEnt.Info.CampnType = ctScanPatial; Opt.dtRecent := pCamEnt.dtLastWork; Opt.sScanExt := pCamEnt.Info.sExts; if Opt.sScanExt = '' then Opt.sScanExt := DOC_EXTS; Opt.sTgDirs := pCamEnt.Info.sTgFolders; if Opt.sTgDirs = '' then begin Opt.sTgDirs := GetDrivesFromMask(GetLogicalDrives, false, true); if Opt.sTgDirs = '' then begin _Trace('Fail .. StartCampaignTask(), Not found drive'); exit; end; Guard(DrvEx, TTgDriveExtent.Create); Guard(DrvList, TStringList.Create); SplitString(Opt.sTgDirs, ',', DrvList); Opt.sTgDirs := ''; for i := 0 to DrvList.Count - 1 do begin if GetDriveExtent(DrvList[i]).liExtentLength.QuadPart <> 0 then SumString(Opt.sTgDirs, DrvList[i], '|'); end; if Opt.sTgDirs = '' then begin _Trace('Fail .. StartCampaignTask(), Not found drive 2'); exit; end; end; Opt.nLangId := 1; Opt.CttSchOpt.nUnzipDepth := PO.CfZipDepth; Opt.CttSchOpt.hRcvHwnd := hRcvHwnd_; Opt.CttSchOpt.nWorkPriority := -1; Opt.CttSchOpt.sKvMdPath := GetRunExePathDir + 'bin\'; Opt.CttSchOpt.nKvTimeoutSec := Opt.nSchTimeoutSec; Opt.CttSchOpt.sMK := GetMK(false); Opt.CttSchOpt.bIncFName := pCamEnt.Info.bIncFName; Opt.CttSchOpt.bIncZip := pCamEnt.Info.bDecompress and (pCamEnt.Info.CampnType <> ctForceEnc); Opt.CttSchOpt.nAipEncMSec := PrefModel_.AipEncMSec; if Opt.CttSchOpt.bIncZip then Opt.CttSchOpt.sZipExts := Opt.sScanExt; // SumString(Opt.sScanExt, COMPRESS_EXTS, '|'); Opt.CttSchOpt.bIncDrm := true; // todo : DRM 옵션 추가 필요 23_1024 09:25:42 kku if pCamEnt.Info.CampnType = ctForceEnc then begin Opt.CttSchOpt.sSchTxt := '|*FORCEDRM*|'; Opt.nLimitSizeMB := 0; // 암호화는 제한없음 Opt.nSchTimeoutSec := 300; // 암호화는 5분 고정 Opt.CttSchOpt.nKvTimeoutSec := Opt.nSchTimeoutSec; pCamEnt.Info.Respaction := crtDRM; if IsUseEncOnlyAIP then begin pCamEnt.Info.Respaction := crtAIP end else if IsSupportAIP then begin if bFirstAip_ then pCamEnt.Info.Respaction := crtAIP; end; end; if IsSupportAIP then begin Opt.CttSchOpt.sAipMdPath := GetAipPath; Opt.CttSchOpt.sAipDMail := sAccount_; Opt.CttSchOpt.sAipPxMail := sEmail_; Opt.CttSchOpt.sAipExt := AIP_EXTS; end; case pCamEnt.Info.Respaction of crtAIP : begin if Opt.CttSchOpt.sAipLabelId = '' then Opt.CttSchOpt.sAipLabelId := GetDefAipLabelId(pCamEnt.Info.CampnType = ctForceEnc); // Opt.CttSchOpt.sTaskDir := 'C:\ProgramData\HE\Task\'; Opt.CttSchOpt.bMakeDrm := Opt.CttSchOpt.sAipMdPath <> ''; Opt.CttSchOpt.bMakeDrmN := pCamEnt.Info.bNoFindEnc; end; crtDRM : begin if not NotUseDRM then begin Opt.CttSchOpt.sAipMdPath := ''; var sDept: String := ''; if sDeptName_ <> '' then sDept := sDeptName_ else if PrefModel_.DeptName <> '' then sDept := PrefModel_.DeptName; Opt.CttSchOpt.sAipDMail := Format('%s|%s|%s|%s|%d', [sEmpNo_, sUserName_, sDept, PrefModel_.PolicyName, CUSTOMER_TYPE]); Opt.CttSchOpt.bMakeDrm := true; end else if (CUSTOMER_TYPE = CUSTOMER_LOTTEMART) or (CUSTOMER_TYPE = CUSTOMER_WELFNI) or (CUSTOMER_TYPE = CUSTOMER_WELFND) then Opt.CttSchOpt.bMakeDrm := true; end; end; if pCamEnt.Info.bUseFilter then begin _Trace('StartCampaignTask() .. CRList=%s', [pCamEnt.Info.sCRList], 9); Opt.CttSchOpt.sCustomKwdPtrn := MgRule_.GetRuleSearchStrFromIds(pCamEnt.Info.sCRList); _Trace('StartCampaignTask() .. Ptrn=%s', [Opt.CttSchOpt.sCustomKwdPtrn], 9); end; Opt.CttSchOpt.bExtrTxt := pCamEnt.Info.bGetContents; sInfoDir := GetRunExePathDir + DIR_CTTSCHRST; pCamEnt.sSchRstPath := sInfoDir + Format('%s.%s', [Opt.sScanId, DAT_CTTSCHRSTDATA]); pCamEnt.sSchRstExpPath := sInfoDir + Format('%s.%s', [Opt.sScanId, DAT_CTTSCHRSTDATA_EXP]); // 증분검사, 기존결과유지 사용 시 활성화 되서 검출되지 않은 파일 정보 전달 24_0611 08:50:05 kku Opt.CttSchOpt.bNoMatchNoti := (pCamEnt.Info.CampnType = ctScanPatial) and pCamEnt.Info.bIncOldRst and FileExists(pCamEnt.sSchRstPath); bContinue := GetRegValueAsString(HKEY_LOCAL_MACHINE, REG_HE, 'cppn') <> ''; if (pCamEnt.Info.CampnType <> ctForceEnc) and DirectoryExists(sInfoDir) then begin if not bContinue then //진행중 값이 있을때 지우지 않는다 25_0515 16:19:37 kku begin if (pCamEnt.Info.CampnType = ctScanPatial) and pCamEnt.Info.bIncOldRst then begin var sBkPath: String := GetRunExePathDir + DIR_CTTSCHRST_BACKUP; if not FileExists(sBkPath) and ForceDirectories(sBkPath) then begin // 검색중 재부팅 가능성이 있기 때문에 이전 파일을 확인해준다. 24_0423 11:07:06 kku var sSchRstPathBk: String := sBkPath + Format('%s.%s', [Opt.sScanId, DAT_CTTSCHRSTDATA]); var sInfoPathBk: String := sBkPath + Format('%s.%s', [Opt.sScanId, DAT_CTTSCHRST]); // 증분 검사 시 이전 기록 백업 후 재사용 24_0423 10:45:32 kku if FileExists(pCamEnt.sSchRstPath) and not FileExists(sSchRstPathBk) then CopyFile(PChar(pCamEnt.sSchRstPath), PChar(sSchRstPathBk), true); var sInfoPath: String := sInfoDir + Format('%s.%s', [Opt.sScanId, DAT_CTTSCHRST]); if FileExists(sInfoPath) and not FileExists(sInfoPathBk) then CopyFile(PChar(sInfoPath), PChar(sInfoPathBk), true); end; end; DeleteDir(sInfoDir); end; end; if not ForceDirectories(sInfoDir) then _Trace('Fail .. Create sch workdir ..'); // DeleteFile(PChar(pCamEnt.sSchRstPath)); // DeleteFile(PChar(pCamEnt.sSchRstExpPath)); if not FileExists(sInfoDir + Format('%s.%s', [Opt.sScanId, DAT_CTTSCHOPT])) then begin // DeleteFile(PChar(Format('%s%s.%s', [sInfoDir, aOpt.sScanId, DAT_CTTSCHRST]))); // DeleteFile(PChar(Format('%s%s.%s', [sInfoDir, aOpt.sScanId, DAT_CTTSCHRSTDATA]))); // DeleteFile(PChar(Format('%s%s.%s', [sInfoDir, aOpt.sScanId, DAT_CTTSCHOPT]))); SaveJsonObjToEncFile(TTgJson.ValueToJsonObject(Opt), sInfoDir + Format('%s.%s', [Opt.sScanId, DAT_CTTSCHOPT]), PASS_STRENC); end; pProcCampn_ := pCamEnt; ThdScanSch_ := TThdSchFileScan.Create(Opt.sTgDirs, Opt, 0, true); ThdScanSch_.OnScanSearchBegin := OnCampaignTaskBegin; ThdScanSch_.OnScanSearchEnd := OnCampaignTaskEnd; case CUSTOMER_TYPE of CUSTOMER_DEV : ThdScanSch_.IgrAipDrm := pCamEnt.Info.CampnType = ctForceEnc; CUSTOMER_SHSC, CUSTOMER_SHCI, CUSTOMER_GEC, CUSTOMER_HDENG : begin ThdScanSch_.IgrScDrm := pCamEnt.Info.CampnType = ctForceEnc; ThdScanSch_.IgrAipDrm := pCamEnt.Info.CampnType = ctForceEnc; end; // CUSTOMER_HAE : ThdScanSch_.IgrScDrm := true; CUSTOMER_HCA : ThdScanSch_.IgrScDrm := true; end; if UseFasooDecrypt then ThdScanSch_.IgrFasDrm := pCamEnt.Info.CampnType = ctForceEnc; ThdScanSch_.IgrAipDrm := IsSupportAIP and (pCamEnt.Info.CampnType = ctForceEnc); ThdScanSch_.IgrExcept := true; if Opt.CttSchOpt.bIncFName then ThdScanSch_.IgrSizeZero := false else ThdScanSch_.IgrSizeZero := not Opt.CttSchOpt.bNoMatchNoti; ThdScanSch_.StartThread; RefreshView; if pProcCampn_.Info.bShowScan then begin if not bContinue then begin case pCamEnt.Info.CampnType of ctScan, ctScanPatial : begin if CUSTOMER_TYPE = CUSTOMER_HDENG then begin if GetHecVer = 2 then PopupMessage(TYPE_MSG_CTTSCH_START); end else PopupMessage(TYPE_MSG_CTTSCH_START); end; ctForceEnc : begin // if not IsHD then // HEC에서 숨김 PopupMessage(TYPE_MSG_CAMPN_FILEENC); end; end; end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. StartCampaignTask()'); end; end; procedure TManagerService.StopCampaignTask; begin try if ThdScanSch_ <> nil then begin if pProcCampn_ <> nil then begin pProcCampn_.dtLastWork := Now; pProcCampn_.dtLastNoti := pProcCampn_.dtLastWork; MgCampn_.Save; pProcCampn_ := nil; NoMatchList_.Clear; end; bIsStopCampn_ := true; llCampnEncCnt_ := ThdScanSch_.TotalEncCount; llCampnEncFailCnt_ := ThdScanSch_.TotalEncFailCount; FreeAndNil(ThdScanSch_); if MgFnd_ <> nil then FreeAndNil(MgFnd_); DelRegValue(HKEY_LOCAL_MACHINE, REG_HE, 'cppn'); DelRegValue(HKEY_LOCAL_MACHINE, REG_HE, 'cptd'); DelRegValue(HKEY_LOCAL_MACHINE, REG_HE, 'cpid'); RefreshView; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. StopPiSchTask()'); end; end; procedure TManagerService.OnCampaignTaskBegin(aSender: TObject); begin if MgFnd_ <> nil then FreeAndNil(MgFnd_); {$IFDEF DEBUG} DeleteFile(PChar(GetRunExePathDir + JSON_PI_TEST)); {$ENDIF} MgFnd_ := TManagerFound.Create; end; procedure TManagerService.OnCampaignTaskEnd(aSender: TObject); var dtEnd: TDateTime; O, OA: ISuperObject; sCurDir, sScanId, sPath, sTime, sResult: String; bClearData: Boolean; nFoundFileCnt: Integer; ScanBlockKind: TScanBlockKind; nPersonalInfoFileMax: Integer; begin try if ThdScanSch_ = nil then exit; if pProcCampn_ = nil then begin _Trace('Fail .. OnCampaignTaskEnd() .. Invalid Campaign info ..'); exit; end; sScanId := ThdScanSch_.CttSchProg.sScanId; dtEnd := Now; sTime := ConvSecBetweenToProgTime(ThdScanSch_.BeginDT, dtEnd); O := SO; O.S['ID'] := sScanId; O.S['TID'] := ThdScanSch_.CttSchProg.sTaskId; O.S['BeginDT'] := FormatDateTime('yyyy-mm-dd hh:nn:ss', ThdScanSch_.BeginDT); O.S['EndDT'] := FormatDateTime('yyyy-mm-dd hh:nn:ss', dtEnd); O.I['WorkSec'] := SecondsBetween(ThdScanSch_.BeginDT, dtEnd); O.S['WorkTime'] := sTime; O.I['TotalFileCount'] := ThdScanSch_.TotalFileCount; O.I['TargetFileCount'] := ThdScanSch_.TotalTgFileCount; O.I['FoundFileCount'] := ThdScanSch_.FoundFileCount; O.I['EncFileCount'] := ThdScanSch_.TotalEncCount; O.S['FoundSInfo'] := MgFnd_.ToEntInfoStr; O.O['FoundInfo'] := MgFnd_.ToJsonObj; sCurDir := GetRunExePathDir; {$IFDEF DEBUG} SaveJsonObjToFile(O, sCurDir + JSON_PI_TEST); {$ENDIF} sResult := MgFnd_.ToEntInfoStr; if ForceDirectories(sCurDir + DIR_CTTSCHRST) then begin if sScanId <> '' then SaveJsonObjToFile(O, Format('%s%s.%s', [sCurDir + DIR_CTTSCHRST, sScanId, DAT_CTTSCHRST])) else SaveJsonObjToFile(O, sCurDir + DIR_CTTSCHRST + DAT_CTTSCHRST); nFoundFileCnt := ThdScanSch_.FoundFileCount - ThdScanSch_.TotalEncCount - ThdScanSch_.TotalDelCount; _Trace('OnCampaignTaskEnd() .. Found=%d, Enc=%d, Del=%d, Result=%d', [ThdScanSch_.FoundFileCount, ThdScanSch_.TotalEncCount, ThdScanSch_.TotalDelCount, nFoundFileCnt]); if gMgSvc.IsNewApi and (pProcCampn_.Info.CampnType = ctScanPatial) then begin var sBkPath: String := GetRunExePathDir + DIR_CTTSCHRST_BACKUP; if DirectoryExists(sBkPath) then begin if pProcCampn_.Info.bIncOldRst then begin // 개인정보 증분검사 라면 이전 데이터 확인해서 합치도록 기능 추가 24_0423 13:36:35 kku nFoundFileCnt := ProcessMergeCampaignBkData(O); end; DeleteDir(sBkPath); end; end; // 캠페인 시작 팝업 있으면 닫기 var h: HWND := FindWindow('TDlgNoticeImg', nil); if h <> 0 then PostMessage(h, WM_CLOSE, 0, 0); if pProcCampn_.Info.bShowScan then begin // if pProcCampn_.Info.bPopupResult then case pProcCampn_.Info.CampnType of ctScan : begin if pProcCampn_.Info.nNotiIfCnt <= nFoundFileCnt then PopupMessage(TYPE_MSG_CTTSCH_COMPLETE, sTime + '|' + IntToStr(nFoundFileCnt)); end; ctScanPatial : begin if pProcCampn_.Info.bIncOldRst then begin var nRCnt: Integer := GetExistPiFileCount(pProcCampn_.Info.sId); _Trace('OnCampaignTaskEnd(), FCnt=%d, RCnt=%d', [nFoundFileCnt, nRCnt], 1); PopupMessage(TYPE_MSG_CTTSCH_COMPLETE, sTime + '|' + IntToStr(nRCnt)); end else if pProcCampn_.Info.nNotiIfCnt <= nFoundFileCnt then PopupMessage(TYPE_MSG_CTTSCH_COMPLETE, sTime + '|' + IntToStr(nFoundFileCnt)); end; end; end; end; bClearData := pProcCampn_.Info.CampnType = ctForceEnc; // ScanBlockKind := PrefModel_.ScanBlockKind; // nPersonalInfoFileMax := PrefModel_.PersonalInfoFileMax; // if sScanId <> '' then // begin // ThdScanSch_.UpdateProgress('complete', true, sResult); // MgCttSch_.CompleteTask(sScanId, ThdScanSch_.ScanDate); // // if (nPersonalInfoFileMax > 0) and // (nPersonalInfoFileMax <= ThdScanSch_.FoundFileCount) then // begin // SetSchRstVul(true); // bClearData := false; // SendEventLog(URI_USER_ACTION, STATUS_FILESCAN, // Format('Found=%d, File=%d', [ThdScanSch_.FoundCount, ThdScanSch_.FoundFileCount])); // // PopupMessage(TYPE_MSG_CTTSCH_VULMODE); // end; // end; // if nPersonalInfoFileMax = 0 then // begin // DeleteDir(sCurDir + DIR_CTTSCHRST); // end else if bClearData then begin DeleteFile(PChar(Format('%s%s.%s', [sCurDir + DIR_CTTSCHRST, sScanId, DAT_CTTSCHRST]))); DeleteFile(PChar(Format('%s%s.%s', [sCurDir + DIR_CTTSCHRST, sScanId, DAT_CTTSCHRSTDATA]))); DeleteFile(PChar(Format('%s%s.%s', [sCurDir + DIR_CTTSCHRST, sScanId, DAT_CTTSCHOPT]))); end; // if bSchRstVul_ and (GetPersonalInfoResults = 0) then // SetSchRstVul(false); {$IFDEF DEBUG} sPath := GetRunExePathDir + 'PersonalInfo.txt'; if FileExists(sPath) then DeleteFile(PChar(sPath)); WriteLnFileEndUTF8(sPath, sResult); {$ENDIF} if sScanId <> '' then _Trace('OnCampaignTaskEnd() End .. Campaign ID=%s', [sScanId]); if MgFnd_ <> nil then FreeAndNil(MgFnd_); pProcCampn_.dtLastWork := Now; pProcCampn_.dtLastNoti := pProcCampn_.dtLastWork; if pProcCampn_.Info.bNoActionVul then UpdateCttSchVulState(true); MgCampn_.Save; pProcCampn_ := nil; NoMatchList_.Clear; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. CampaignTaskEnd()'); end; llCampnEncCnt_ := ThdScanSch_.TotalEncCount; llCampnEncFailCnt_ := ThdScanSch_.TotalEncFailCount; bTerminateThdScanSch_ := true; RefreshView; end; function TManagerService.IsScreenLogo: Boolean; begin Result := bForceScreenLogo_ or (ModePolicy.ScreenLogo = askAlways); if not Result and (nMonitorCnt_ > 0) then nMonitorCnt_ := 0; end; procedure TManagerService.SetExpPolicyActive(aFun: TExpFun); var O: ISuperObject; begin // if llChkTimeSec_ = -1 then // exit; try if bIsExpPolicy_ then exit; // todo : 예외 정책 세팅 try if PrefModel_.IsOldPolicy then begin if PrefModel_.ExpPolicy = '' then begin case GetModeKind of hmkSleep : O := SO(PrefModel_.IdlPolicy); hmkSecurity : begin O := PrefModel_.GetPrefModeToJsonObj; if O = nil then O := SO; end; hmkVulnerability : O := SO(PrefModel_.VulPolicy); hmkOffline : O := SO(PrefModel_.OffPolicy); else {$IFDEF DEBUG} ASSERT(false); {$ELSE} exit {$ENDIF}; end; end else O := SO(PrefModel_.ExpPolicy); if aFun.bUsb then O.S['mwOKey_OPTIONB'] := 'logonly'; if aFun.bMtp then O.S['KEY_MTPBLOCK'] := 'logonly'; if aFun.bBT then O.S['KEY_BLUETOOTHBLOCK'] := 'logonly'; if aFun.bWifi then O.S['mwPKey_WIFIPREVENT'] := 'logonly'; if aFun.bCB then O.S['mwPKey_CLIPBOARDENABLE'] := 'logonly'; ExpPolicy.SetPrefModel(O); end else begin if not PrefExpPolicy_.Loaded then begin case GetModeKind of hmkSleep : O := PrefIdlModel_.GetPolicyToJsonObj; hmkSecurity : O := PrefModel_.GetPolicyToJsonObj; hmkVulnerability : O := PrefVulModel_.GetPolicyToJsonObj; hmkOffline : O := PrefVulModel_.GetPolicyToJsonObj; else {$IFDEF DEBUG} ASSERT(false); {$ELSE} exit {$ENDIF}; end; O.S['sPoId_'] := 'TEMP'; O.S['PolicyId'] := 'TEMP'; if aFun.bUsb then O.I['UsbBlockKind'] := Integer(ubkLog); if aFun.bMtp then O.I['MtpBlockKind'] := Integer(dbkLog); if aFun.bBT then O.I['BlueBlockKind'] := Integer(dbkLog); if aFun.bWifi then O.I['WifiCtrlKind'] := Integer(wckLog); if aFun.bCB then O.I['ClipBlockKind'] := Integer(cbkLog); PrefExpPolicy_.SetPolicy('TEMP', O, false); end; end; except on E: Exception do begin ETgException.TraceException(Self, E, 'Fail .. SetExpPolicyActive() .. SetPrefModel()'); exit; end; end; llChkTimeSec_ := 0; nExpPoMin_ := aFun.nUseMin; dtExpPoBegin_ := Now; bIsExpPolicy_ := true; ThdTaskTimer_.SetTask(TimerCheckExpPo, 1000, true); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. SetExpPolicyActive()'); end; end; procedure TManagerService.ClearExpPolicy; begin // 예외 정책이 초기화될 경우 끝내기 위해 추가 24_0711 09:38:19 kku dtExpPoBegin_ := 0; end; procedure TManagerService.AddPrintWaterEnt(pWEnt: PPrtWaterEnt); begin qWaterEnts_.Enqueue(pWEnt); end; procedure TManagerService.ProcessPrintWaterEnt; procedure ExtrPrintImgFiles(sImgPath: String; aList: TStrings); var sFName: string; i: Integer; begin aList.Clear; sFName := StringReplace(CutFileExt(sImgPath), '_0001', '', [rfReplaceAll]); if not FileExists(sImgPath) and not FileExists(Format('%s_%.4d.png', [sFName, 1])) then exit; if FileExists(sImgPath) then aList.Add(sImgPath); i := 1; while True do begin sImgPath := Format('%s_%.4d.png', [sFName, i]); if FileExists(sImgPath) then begin if aList.IndexOf(sImgPath) = -1 then aList.Add(sImgPath); end else exit; Inc(i); end; end; { Returns grayscale version of a color. } function RgbToGray(C: TColor): TColor; begin C := Round(C and $FF * 0.3 + C and $00FF00 shr 8 * 0.59 + C shr 16 * 0.11); Result := RGB(C, C, C); end; { Converts whole PNG image to grayscale. } procedure ToGrayscale(PNG: TPNGObject); var X, Y: Integer; begin for X := 0 to PNG.Width - 1 do for Y := 0 to PNG.Height - 1 do PNG.Pixels[X, Y] := RgbToGray(PNG.Pixels[X, Y]); end; const WORD_GAP = ' '; type TProcType = (ptPng, ptPdf, ptEmf); var pInfo: PPrtWaterEnt; WInfo: TPrtWaterEnt; pi, i, nLeft, nTop, nW, nH: Integer; ImgList: TStringList; ProcType: TProcType; bIsWatchPtr: Boolean; png: TPngImage; mf: TMetaFile; // bmp: TBitmap; bf: BLENDFUNCTION; sExt, sPrtDocId, sImgDir, sImgPath, sWImgPath, sTopText, sBottomText: String; bProcGrayW: Boolean; fST: Double; sOutCode: AnsiString; OLog: ISuperObject; PO: TPrefModel; arrDevice, arrDriver, arrPort: array [0..255] of Char; hDev: THandle; DevMode: PDeviceMode; OrgDevMode: TDeviceMode; pdf: SynPdf.TPdfDocumentGDI; pdfPage: SynPdf.TPdfPage; bmpWaterP: TBitmap; // ImgEn: TImageEn; procedure DoMasking(pEnt: PMskEnt); var R: TRect; i: Integer; sText: String; x, y: Integer; begin R.Left := pEnt.x; R.Top := pEnt.y; R.Width := pEnt.w; R.Height := pEnt.h; png.Canvas.Pen.Color := clWhite; png.Canvas.Pen.Style := psSolid; png.Canvas.Brush.Color := clWhite; png.Canvas.Brush.Style := bsSolid;// bsBDiagonal; png.Canvas.FillRect(R); sText := 'Hidden by BSOne'; for i := 1 to 99 do begin png.Canvas.Font.Size := i; if (png.Canvas.TextHeight(sText) - 1) >= (R.Height - 2) then begin break; end; end; png.Canvas.TextRect(R, sText, [tfCenter, tfEndEllipsis, tfVerticalCenter]); png.Canvas.Pen.Color := clBlack; png.Canvas.Pen.Style := psDot; png.Canvas.MoveTo(R.Left, R.Top); png.Canvas.LineTo(R.Left + R.Width, R.Top); png.Canvas.LineTo(R.Left + R.Width, R.Top + R.Height); png.Canvas.LineTo(R.Left, R.Top + R.Height); png.Canvas.LineTo(R.Left, R.Top); end; function MaskPrtST: Boolean; var sStKey, sStPng: String; nResult: Integer; begin try if not FileExists(GetRunExePathDir + DIR_CONF + DLL_ST) then exit; sStKey := GetRunExePathDir + DIR_CONF + DAT_SNAPTAGKEY_P; if not FileExists(sStKey) then begin var StrList: TStringList; Guard(StrList, TStringList.Create); StrList.Text := ST_Key_S; StrList.SaveToFile(sStKey, TEncoding.ANSI); end; sStPng := GetRunExePathDir + DIR_CONF + PNG_SNAPTAGDATA_PRT; nResult := labGuardPS(sStKey, sStPng, 2, 1{3블루}, 1 {유저코드?}, FormatDateTime('yyyy/mm/dd hh:nn', Now), sOutCode); Result := nResult = 0; if not Result then TTgTrace.T('Fail .. MaskPrtST() .. Snaptag .. code = %d', [nResult], 1); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. MaskPrtST()'); end; end; procedure ProcessSnaptag; var sStPng: String; pngST: TPngImage; nsX, nsY: Integer; begin if not IsUseSnaptag then exit; if not MaskPrtST then exit; try if _bmpST = nil then begin sStPng := GetRunExePathDir + DIR_CONF + PNG_SNAPTAGDATA_PRT; if FileExists(sStPng) then begin Guard(pngST, TPngImage.Create); pngST.LoadFromFile(sStPng); _bmpST := TBitmap.Create; _bmpST.PixelFormat := pf4bit; _bmpST.SetSize(png.Width div 5, png.Height div 5); nsX := 0; while nsX < (_bmpST.Width + pngST.Width) do begin nsY := 0; while nsY < (_bmpST.Height + pngST.Height) do begin _bmpST.Canvas.Draw(nsX, nsY, pngST); Inc(nsY, pngST.Height); end; Inc(nsX, pngST.Width); end; end; end; if _bmpST <> nil then begin // _bmpST.SaveToFile('C:\Users\kku\Desktop\이전 바탕화면\출력 추출 데이터\test.bmp'); var cTrMatrix: TColorMatrix; ZeroMemory(@cTrMatrix, SizeOf(cTrMatrix)); // 회색 // cTrMatrix[0][0] := 0.299; // cTrMatrix[0][1] := 0.299; // cTrMatrix[0][2] := 0.299; // cTrMatrix[1][0] := 0.587; // cTrMatrix[1][1] := 0.587; // cTrMatrix[1][2] := 0.587; // cTrMatrix[2][0] := 0.114; // cTrMatrix[2][1] := 0.114; // cTrMatrix[2][2] := 0.114; // cTrMatrix[3][3] := 0.10; // 투명도 1.0 ~ 2.22 // cTrMatrix[4][4] := 1.0; cTrMatrix := MakeColorMatrix(0.2, 0.2, 0.2, fST); DrawBitmapWaterEx(png.Canvas.Handle, 0, 0, _bmpST, @cTrMatrix, png.Width, png.Height); end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. ProcessSnaptag()'); end; end; Label LB_DoPrintHere, LB_CollatePng, LB_CollatePdf, LB_CollateEmf, LB_Collate1; begin try if FindWindow('TDlgWaitExtrProcPrt', nil) <> 0 then exit; if Printer.Printing then exit; if qWaterEnts_.Count = 0 then exit; pInfo := qWaterEnts_.Dequeue; if pInfo = nil then exit; PO := GetModePolicy; fST := 0.03; if IsUseSnaptag then begin var sIni := GetProgramFilesDir + DIR_TG + INI_FORCEHE; if FileExists(sIni) then begin var ini: TIniFile; Guard(ini, TIniFile.Create(sIni)); fST := ini.ReadFloat('Force', 'StBold', fST); end; end; bmpWaterP := nil; sOutCode := ''; WInfo := pInfo^; sExt := GetFileExt(WInfo.sImgPath).ToUpper; if sExt = 'PDF' then ProcType := ptPdf else if sExt = 'EM1' then ProcType := ptEmf else ProcType := ptPng; sPrtDocId := WInfo.sPrtDocId; if sPrtDocId = '' then sPrtDocId := 'Unknown'; Dispose(pInfo); if WInfo.LogJson <> '' then OLog := SO(WInfo.LogJson) else OLog := nil; // {$IFDEF DEBUG} // var sExtDir: String := ExtractFilePath(WInfo.sImgPath); // var sImgDir: String := 'C:\Users\kku\Desktop\OutSpoolImg'; // if DirectoryExists(sExtDir) and DirectoryExists(sImgDir) then // begin // DeleteDirSub(sImgDir); // CopyDirSub(sExtDir, sImgDir); // DeleteDir(sExtDir); // end; // exit; // {$ENDIF} OrgDevMode := TTgRtti.StrToSetType(WInfo.DevMode); if (CUSTOMER_TYPE = CUSTOMER_GEC) and (Pos('HP', WInfo.sPtrName) = 1) then goto LB_DoPrintHere; // if IsPrtSpl2Pdf then // WInfo.bUseWM := false; {$IFDEF DEBUG} // if IsUserModePrint or IsPrtSpl2Pdf then // if IsPrtSpl2Pdf then // if false then if true then {$ELSE} // if IsUserModePrint and ((WInfo.sPdfPath = '') or IsPrtSpl2Pdf) then if IsUserModePrint or IsPrtSpl2Pdf then {$ENDIF} begin // 티맵에서 시스템 권한으로 프린트 요청 시 차단된다 24_0119 10:39:58 kku var sKvCsPath: String := GetRunExePathDir + EXE_KVCTTSCH; if FileExists(sKvCsPath) then begin _Trace('외부 모듈로 프린트 시도.', 1); case CUSTOMER_TYPE of CUSTOMER_DEMO, CUSTOMER_WELFND, CUSTOMER_WELFNI, CUSTOMER_SHCI, CUSTOMER_SHSC, CUSTOMER_WINSTN, CUSTOMER_SKEC, CUSTOMER_SANKYO, CUSTOMER_KORENTAL : begin sImgPath := GetRunExePathDir + DIR_CONF + 'CI.bmp'; if FileExists(sImgPath) and not FileExists('C:\ProgramData\HE\CI.bmp') then CopyFile(PChar(sImgPath), 'C:\ProgramData\HE\CI.bmp', false); end; end; {$IFDEF PRT_STOP} bIsWatchPtr := (ThdPrinter_ <> nil) and ThdPrinter_.IsWatch; if bIsWatchPtr then ThdPrinter_.StopWatch; {$ENDIF} sTopText := GetRunExePathDir + '$KvCttSchOpt.dat'; try var O: ISuperObject := SO; O.I['CSTT'] := Integer(csttPrint); O.O['POpt'] := TTgJson.ValueToJsonObject(WInfo); O.S['EN'] := sEmpNo_; O.S['UN'] := sUName_; O.S['DEPT'] := sDeptName_; O.S['IP'] := NicService.GetIP; O.I['CT'] := CUSTOMER_TYPE; O.I['PrtDPI'] := PrefModel_.PrtDPI; O.B['WM'] := WInfo.bUseWM; if PO.PrtWaterCfg.bActive then O.O['WMCfg'] := TTgJson.ValueToJsonObject(PO.PrtWaterCfg); O.B['S2P'] := IsAdvancePrtProg; O.B['ST'] := IsUseSnaptag and MaskPrtST; O.D['STV'] := fST; O.S['DPW'] := GetPrtWaterText(sPrtDocId); O.S['PRTID'] := sPrtDocId; O.I['RcvWnd'] := hRcvHwnd_; if PrefModel_.PrtPopupNo then O.B['NoPrtPopup'] := true; if IsUsePrintMask then begin O.S['MskStr'] := sPrtMaskingStr_; O.B['IsMask'] := true; end; // {$IFDEF DEBUG} // // PDF로 강제 출력 추가 25_0602 14:36:14 kku // O.S['FPDF'] := Format('C:\ProgramData\HE\%s.pdf', [FormatDateTime('yymmddhhnnss', Now)]); // {$ENDIF} if CUSTOMER_TYPE = CUSTOMER_GEC then O.S['LB'] := sRecentLabel_; var nRunCnt: Integer := 0; if SaveJsonObjToFile(O, sTopText) then begin Inc(nRunCnt); bIgrPrtPause_ := true; {$IFDEF DEBUG} ExecuteAppWaitUntilTerminate(sKvCsPath, Format('-p "%s"', [sTopText]), SW_SHOWNORMAL, 600000); _Trace('외부 모듈로 프린트 시도... 종료', 1); {$ELSE} _Trace(Format('[MGKIM] kvcs run : %s, %s',[sKvCsPath, sTopText])); var ProcInfo: TProcessInformation := ExecuteAppAsUser('explorer.exe', sKvCsPath, Format('-p "%s"', [sTopText]), SW_SHOWNORMAL); if ProcInfo.dwProcessId <> 0 then begin _Trace('외부 모듈로 프린트 시도...성공', 1); var dwExecuteTick: DWORD := GetTickCount; while true do begin var dwWaitResult: DWORD := WaitForSingleObject(ProcInfo.hProcess, 50); if dwWaitResult <> WAIT_TIMEOUT then break; // 메세지 없이 계속 돌아가는 상황을 위해서 빠져나오는 타임아웃을 추가함 (tcptunnel.exe 관련을 위해 추가) if (GetTickCount - dwExecuteTick) > 600000 then begin TerminateProcess(ProcInfo.hProcess, 999); exit; end; end; _Trace('외부 모듈로 프린트 시도...성공 후 종료', 1); end else _Trace('외부 모듈로 프린트 시도...실패', 1); {$ENDIF} SendMessage(gMgSvc.RcvHwnd, WM_POPUP_PRTW_PROGRESS, 3, 0); bIgrPrtPause_ := false; if bIsNewApi_ then begin if OLog <> nil then begin if sOutCode <> '' then begin OLog.S['KEY_SUMMARY'] := 'ST=' + sOutCode + ', ' + OLog.S['KEY_SUMMARY']; ThdEvent_.Push(OLog.AsJSon); end else ThdEvent_.Push(WInfo.LogJson); end; end else begin SendEventLog(URI_USER_ACTION, LOGCODE_EVENT_PRINTER, Format('Printer : %s, Document : %s', [WInfo.sPtrName, WInfo.sDocName]), false); end; var bPopup: Boolean := PO.Print.bPopup; if IsDivPopup then bPopup := PO.PrtAllowPopup; if bPopup then begin if WInfo.bUseWM and PrefModel_.PrtWaterPop then PopupMessage(TYPE_MSG_EVENT_PRINTWATER, WInfo.sPtrName + '|' + WInfo.sDocName) else if IsDivPopup or (PO.Print.PrintKind = pkLog) then PopupMessage(TYPE_MSG_PREVENT_PRINTER, WInfo.sPtrName + '|' + WInfo.sDocName); end; end; if WInfo.sPostApvId <> '' then MgPrint_.DelPrintInfo(WInfo.sPostApvId, true); finally DeleteDir(ExtractFilePath(WInfo.sImgPath)); ///mgkim // if FileExists(sTopText) then // DeleteFile(PChar(sTopText)); {$IFDEF PRT_STOP} if bIsWatchPtr and (ThdPrinter_ <> nil) then ThdPrinter_.StartWatch; {$ENDIF} // 작업이 오래걸리면... 시간 처리에 문제가 생긴다 23_0912 18:23:39 kku dtLastChk_ := Now; end; exit; end; end; SendMessage(gMgSvc.RcvHwnd, WM_POPUP_PRTW_PROGRESS, 2, 0); LB_DoPrintHere : _Trace('PrtPDF Path = %s', [WInfo.sPdfPath], 3); SendMessage(hRcvHwnd_, WM_POPUP_PRINTWATER_PROGRESS, 2, WInfo.dwTotalPage); {$IFDEF PRT_STOP} bIsWatchPtr := (ThdPrinter_ <> nil) and ThdPrinter_.IsWatch; if bIsWatchPtr then ThdPrinter_.StopWatch; {$ENDIF} png := nil; mf := nil; try Guard(ImgList, TStringList.Create); case ProcType of ptPdf : ; ptPng : begin ExtrPrintImgFiles(WInfo.sImgPath, ImgList); if ImgList.Count = 0 then exit; png := TPngImage.Create; sImgPath := ImgList[0]; png.LoadFromFile(sImgPath); end; ptEmf : begin sImgDir := ExtractFilePath(WInfo.sImgPath); ExtrFilesFromDir(sImgDir, ImgList, false, 'em1'); if ImgList.Count = 0 then exit; mf := TMetafile.Create; sImgPath := ImgList[0]; mf.LoadFromFile(sImgPath); end; end; sTopText := ''; //Trim(edTopText.Text); sBottomText := GetPrtWaterText(sPrtDocId); ZeroMemory(@bf, SizeOf(bf)); bf.AlphaFormat := 0; // 일반 비트맵 0, 32비트 비트맵 AC_SRC_ALPHA bf.BlendFlags := 0; // 무조건 0 bf.BlendOp := AC_SRC_OVER; // AC_SRC_OVER bf.SourceConstantAlpha := 125; // 투명도(투명 0 - 불투명 255) bProcGrayW := false; // Guard(ImgEn, TImageEn.Create(nil)); // Guard(F, TFont.Create); // F.Size := 200; // 400 // F.Color := clSilver; // $F1F1F1; // clSilver; // clGray; // F.Style := png.Canvas.Font.Style + [fsBold]; // Guard(bmp, TBitmap.Create); {$IF false} if (WInfo.sPdfPath <> '') and not bIsOutPdf then begin Guard(pdf, SynPdf.TPdfDocumentGDI.Create); // pdf.UseUniscribe := true; // pdf.StandardFontsReplace := true; // pdf.UseFontFallBack := false; // pdf.FontFallBackName := 'Tahoma'; pdf.ScreenLogPixels := 300; // 600; case OrgDevMode.dmPaperSize of DMPAPER_LETTERSMALL : begin pdf.DefaultPaperSize := psUserDefined; pdf.DefaultPageWidth := 216 * 72; pdf.DefaultPageHeight := 280 * 72; end; DMPAPER_LETTER : pdf.DefaultPaperSize := psLetter; DMPAPER_LEGAL : pdf.DefaultPaperSize := psLegal; DMPAPER_A3 : pdf.DefaultPaperSize := psA3; DMPAPER_A4 : pdf.DefaultPaperSize := psA4; DMPAPER_A4SMALL : begin pdf.DefaultPaperSize := psUserDefined; pdf.DefaultPageWidth := 210 * 72; pdf.DefaultPageHeight := 297 * 72; end; DMPAPER_A5 : pdf.DefaultPaperSize := psA5; DMPAPER_B4 : begin pdf.DefaultPaperSize := psUserDefined; pdf.DefaultPageWidth := 250 * 72; pdf.DefaultPageHeight := 354 * 72; end; DMPAPER_B5 : begin pdf.DefaultPaperSize := psUserDefined; pdf.DefaultPageWidth := 182 * 72; pdf.DefaultPageHeight := 257 * 72; end; end; if not bIsOutPdf then begin if png.Width > png.Height then begin var nSizeTemp: Integer := pdf.DefaultPageHeight; pdf.DefaultPageHeight := pdf.DefaultPageWidth; pdf.DefaultPageWidth := nSizeTemp; end; end; pdfPage := pdf.AddPage; pdf.VCLCanvas.Brush.Style := bsClear; pdf.VCLCanvas.Font.Name := 'Tahoma'; nW := pdf.VCLCanvasSize.Width; nH := pdf.VCLCanvasSize.Height; if bIsOutPdf then begin end else begin for i := 0 to ImgList.Count - 1 do begin try if i <> 0 then begin try if png <> nil then FreeAndNil(png); // i = 0은 위에서 미리 불러옴 png := TPngImage.Create; sImgPath := ImgList[i]; png.LoadFromFile(sImgPath); except break; end; pdfPage := pdf.AddPage; end; // bmp.Assign(png); // bmp.SaveToFile('C:\Users\kku\Desktop\0.bmp'); // png.SaveToFile('C:\Users\kku\Desktop\0.png'); PostMessage(hRcvHwnd_, WM_POPUP_PRINTWATER_PROGRESS, 3, i + 1); if not ProcessWatermark(pdf.VCLCanvas.Handle, sImgPath) then begin // png.SaveToFile('C:\Users\kku\Desktop\이전 바탕화면\출력 추출 데이터\test.png'); // pdf.VCLCanvas.StretchDraw(pngRect, png); // pdf.VCLCanvas.StretchDraw() - 이게 어느날 갑자기 안되기 시작했다;;; 24_0930 15:30:53 kku StretchBlt(pdf.VCLCanvas.Handle, 0, 0, nW, nH, png.Canvas.Handle, 0, 0, png.Width, png.Height, SRCCOPY); end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. PrintPDF .. 1'); end; end; end; try pdf.SaveToFile(WInfo.sPdfPath); except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. PrintPDF .. 2'); end; end else {$IFEND} begin pi := -1; for i := 0 to Printer.Printers.Count - 1 do begin if Printer.Printers[i] = WInfo.sPtrName then pi := i; end; if pi = -1 then begin TTgTrace.T('프린터 찾기 실패 .. Name=%s', [WInfo.sPtrName]); exit; end; Printer.PrinterIndex := pi; if not WInfo.bUseWM then Printer.Title := WInfo.sDocName + ' *BSOne-' else Printer.Title := WInfo.sDocName + ' *BSOne'; hDev := 0; Printer.GetPrinter(arrDevice, arrDriver, arrPort, hDev); if hDev = 0 then exit; // for Test // OrgDevMode.dmCopies := 2; // OrgDevMode.dmCollate := 1; var nCopies: Integer := OrgDevMode.dmCopies; var nCopies0: Integer; var dmCollate: DWORD := OrgDevMode.dmCollate; DevMode := GlobalLock(hDev); try // OrgDevMode.dmCopies // OrgDevMode.dmCollate : 0 이면 11 22 33 이렇게 출력, 1 이면 123 123 이렇게 출력 // 항상 1부로 나오도록 조정, 설정된 출력은 별도 처리 25_0604 13:01:05 kku OrgDevMode.dmCopies := 1; if ProcType <> ptPdf then begin if WInfo.bPaperV then OrgDevMode.dmOrientation := DMORIENT_PORTRAIT else OrgDevMode.dmOrientation := DMORIENT_LANDSCAPE; end; // DevMode.dmPaperSize := WInfo.dwPageSizeT; DevMode^ := OrgDevMode; // DevMode.dmColor := DMCOLOR_COLOR; // DMCOLOR_MONOCHROME // DevMode.dmColor := DMCOLOR_MONOCHROME; // DMCOLOR_MONOCHROME Printer.SetPrinter(arrDevice, arrDriver, arrPort, hDev); finally GlobalUnlock(hDev); end; // 용지 가로, 세로 돌릴려면 Printer.BeginDoc 전에 해야한다.. // 일부 프로그램에서 오류남 23_0623 08:45:27 kku // try // if not bIsOutPdf then // begin // if not WInfo.bPaperV then // Printer.Orientation := poLandscape // else // Printer.Orientation := poPortrait; // end; // except // on E: Exception do // ETgException.TraceException(Self, E, 'Fail .. Set Printer.Orientation'); // end; // Guard(bmpW, Vcl.Graphics.TBitmap.Create); // if pngW.Width > 0 then // begin // bmpW.Assign(pngW); //// bmpW.Transparent := true; //// bmpW.TransparentMode := tmFixed; //// bmpW.TransparentColor := clWhite; // end; if (WInfo.dwTotalPage > 0) and (WInfo.dwTotalPage < ImgList.Count) then begin nCopies := ImgList.Count div WInfo.dwTotalPage; dmCollate := 1; // 한 부씩 인쇄로 고정... // TTgTrace.T('ProcessPrint() .. 2, SetCopies..%d', [nCopies]); // 총 출력 부스만큼 이미지가 추출된 경우 처리... 25_0604 19:15:34 kku for i := ImgList.Count - 1 downto 0 do begin if (i mod nCopies) > 0 then ImgList.Delete(i); end; end; nW := 0; nH := 0; Printer.BeginDoc; try if not Printer.Printing or Printer.Aborted then begin SendMessage(gMgSvc.RcvHwnd, WM_POPUP_PRINTWATER_PROGRESS, 0, 0); exit; end; LB_Collate1 : case ProcType of ptPdf : begin TTgTrace.T('ProcessPrint() ... 7'); var doc: EM.PdfiumCore.TPdfDocument; Guard(doc, EM.PdfiumCore.TPdfDocument.Create); doc.LoadFromFile(WInfo.sImgPath); nW := GetDeviceCaps(Printer.Canvas.Handle, HORZRES); nH := GetDeviceCaps(Printer.Canvas.Handle, VERTRES); var page: EM.PdfiumCore.TPdfPage; var bIsPageLoad, bPagePortraitOrientation: Boolean; var nPageW, nPageH: Integer; bPagePortraitOrientation := nW > nH; TTgTrace.T('ProcessPrint() ... 8'); // FPU 예외 마스킹 (부동소수점 예외를 무시하게 함) >> PDFium 버그... 25_0612 16:12:04 kku // 현재 FPU 컨트롤 워드 저장 var SavedCW: WORD := Get8087CW; try // 모든 FPU 예외 마스크 SetExceptionMask([exInvalidOp, exDenormalized, exZeroDivide, exOverflow, exUnderflow, exPrecision]); // var bmp: TBitmap := nil; // Guard(bmp, TBitmap.Create); // bmp.PixelFormat := pf32bit; // bmp.Canvas.Brush.Color := clWhite; // bmp.SetSize(nW, nH); for i := 0 to doc.PageCount - 1 do begin if not Printer.Printing or Printer.Aborted then break; nPageW := nW; nPageH := nH; if i <> 0 then Printer.NewPage; // bIsPageLoad := doc.IsPageLoaded(i); try page := doc.Pages[i]; // if bPagePortraitOrientation <> (Trunc(page.Width) > Trunc(page.Height)) then // begin // var nTmp: Integer := nPageW; // nPageW := nPageH; // nPageH := nTmp; // end; TTgTrace.T('ProcessPrint() ... 9 - %d', [i]); nCopies0 := nCopies; PostMessage(hRcvHwnd_, WM_POPUP_PRINTWATER_PROGRESS, 3, i + 1); SendMessage(gMgSvc.RcvHwnd, WM_POPUP_PRTW_PROGRESS, 0, i + 1); LB_CollatePdf : // page.Draw(Printer.Handle, 0, 0, nPageW, nPageH, prNormal, [proPrinting, proNoNativeText, proNoCatch]); if bPagePortraitOrientation <> (Trunc(page.Width) > Trunc(page.Height)) then page.Draw(Printer.Handle, 0, 0, nPageW, nPageH, pr90Clockwise, [proPrinting, proNoCatch]) else page.Draw(Printer.Handle, 0, 0, nPageW, nPageH, prNormal, [proPrinting, proNoCatch]); // if bmp <> nil then // begin // if bPagePortraitOrientation <> (Trunc(page.Width) > Trunc(page.Height)) then // page.Draw(bmp.Canvas.Handle, 0, 0, nPageW, nPageH, pr90Clockwise, [proPrinting, proNoCatch]) // else // page.Draw(bmp.Canvas.Handle, 0, 0, nPageW, nPageH, prNormal, [proPrinting, proNoCatch]); // bmp.SaveToFile(Format('C:\test\%d.bmp', [i])); // bmp.Canvas.FillRect(Rect(0, 0, bmp.Width, bmp.Height)); // end; Dec(nCopies0); if (dmCollate = 0) and (nCopies0 > 0) then begin Printer.NewPage; goto LB_CollatePdf end; finally // if not bIsPageLoad and (page <> nil) then // page.Close; end; end; finally // 원래 상태 복원 Set8087CW(SavedCW); end; Dec(nCopies); if (dmCollate <> 0) and (nCopies > 0) then begin Printer.NewPage; goto LB_Collate1; end; TTgTrace.T('ProcessPrint() ... 10'); end; ptPng : begin for i := 0 to ImgList.Count - 1 do begin if not Printer.Printing or Printer.Aborted then break; try if i <> 0 then begin try if png <> nil then FreeAndNil(png); // i = 0은 위에서 미리 불러옴 png := TPngImage.Create; sImgPath := ImgList[i]; png.LoadFromFile(sImgPath); except {$IFDEF DEBUG} ASSERT(false); {$ENDIF} break; end; Printer.NewPage; end; nW := GetDeviceCaps(Printer.Canvas.Handle, HORZRES); nH := GetDeviceCaps(Printer.Canvas.Handle, VERTRES); nCopies0 := nCopies; PostMessage(hRcvHwnd_, WM_POPUP_PRINTWATER_PROGRESS, 3, i + 1); SendMessage(gMgSvc.RcvHwnd, WM_POPUP_PRTW_PROGRESS, 0, i + 1); LB_CollatePng : // if not ProcessWatermark(Printer.Canvas.Handle, sImgPath) then if (ProcType <> ptPng) or not ProcessWatermarkToImage(png, Printer.Canvas.Handle, nW, nH, WInfo, fST, sTopText, sBottomText, bmpWaterP, sImgPath) then begin // png.SaveToFile(Format('c:\test\test-%d.png', [i + 1])); StretchBlt(Printer.Canvas.Handle, 0, 0, nW, nH, png.Canvas.Handle, 0, 0, png.Width, png.Height, SRCCOPY); end; Dec(nCopies0); if (dmCollate = 0) and (nCopies0 > 0) then begin Printer.NewPage; goto LB_CollatePng; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. DoPrint ..'); end; end; Dec(nCopies); if (dmCollate <> 0) and (nCopies > 0) then begin if png <> nil then FreeAndNil(png); png := TPngImage.Create; sImgPath := ImgList[0]; png.LoadFromFile(sImgPath); Printer.NewPage; goto LB_Collate1; end; end; ptEmf : begin for i := 0 to ImgList.Count - 1 do begin if not Printer.Printing or Printer.Aborted then break; try if i <> 0 then begin try if mf <> nil then FreeAndNil(mf); // i = 0은 위에서 미리 불러옴 mf := TMetafile.Create; sImgPath := ImgList[i]; mf.LoadFromFile(sImgPath); if (mf.MMWidth = 0) or (mf.MMHeight = 0) then continue; except {$IFDEF DEBUG} ASSERT(false); {$ENDIF} break; end; Printer.NewPage; end; nW := GetDeviceCaps(Printer.Canvas.Handle, HORZRES); nH := GetDeviceCaps(Printer.Canvas.Handle, VERTRES); nCopies0 := nCopies; PostMessage(hRcvHwnd_, WM_POPUP_PRINTWATER_PROGRESS, 3, i + 1); SendMessage(gMgSvc.RcvHwnd, WM_POPUP_PRTW_PROGRESS, 0, i + 1); LB_CollateEmf : Printer.Canvas.StretchDraw(Rect(0, 0, nW, nH), mf); Dec(nCopies0); if (dmCollate = 0) and (nCopies0 > 0) then begin Printer.NewPage; goto LB_CollateEmf; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. DoPrint ..'); end; end; Dec(nCopies); if (dmCollate <> 0) and (nCopies > 0) then begin if mf <> nil then FreeAndNil(mf); mf := TMetafile.Create; sImgPath := ImgList[0]; mf.LoadFromFile(sImgPath); Printer.NewPage; goto LB_Collate1; end; end; end; finally if Printer.Printing then Printer.EndDoc; end; end; if bIsNewApi_ then begin if OLog <> nil then begin if sOutCode <> '' then begin OLog.S['KEY_SUMMARY'] := 'ST=' + sOutCode + ', ' + OLog.S['KEY_SUMMARY']; ThdEvent_.Push(OLog.AsJSon); end else ThdEvent_.Push(WInfo.LogJson); end; end else begin SendEventLog(URI_USER_ACTION, LOGCODE_EVENT_PRINTER, Format('Printer : %s, Document : %s', [WInfo.sPtrName, WInfo.sDocName]), false); end; var bPopup: Boolean := PO.Print.bPopup; if IsDivPopup then bPopup := PO.PrtAllowPopup; if bPopup then begin if WInfo.bUseWM and PrefModel_.PrtWaterPop then PopupMessage(TYPE_MSG_EVENT_PRINTWATER, WInfo.sPtrName + '|' + WInfo.sDocName) else if IsDivPopup or (PO.Print.PrintKind = pkLog) then PopupMessage(TYPE_MSG_PREVENT_PRINTER, WInfo.sPtrName + '|' + WInfo.sDocName); end; finally if png <> nil then FreeAndNil(png); if mf <> nil then FreeAndNil(mf); if bmpWaterP <> nil then FreeAndNil(bmpWaterP); DeleteDir(ExtractFilePath(WInfo.sImgPath)); SendMessage(hRcvHwnd_, WM_POPUP_PRINTWATER_PROGRESS, 0, 0); SendMessage(gMgSvc.RcvHwnd, WM_POPUP_PRTW_PROGRESS, 3, 0); {$IFDEF PRT_STOP} if bIsWatchPtr and (ThdPrinter_ <> nil) then ThdPrinter_.StartWatch; {$ENDIF} // 작업이 오래걸리면... 시간 처리에 문제가 생긴다 23_0912 18:23:39 kku dtLastChk_ := Now; end; except on E: Exception do begin ETgException.TraceException(Self, E, 'Fail .. ProcessPrintWaterEnt()'); SendMessage(hRcvHwnd_, WM_POPUP_PRINTWATER_PROGRESS, 0, 0); {$IFDEF PRT_STOP} if bIsWatchPtr and (ThdPrinter_ <> nil) then ThdPrinter_.StartWatch; {$ENDIF} end; end; end; procedure TManagerService.ResetPersonalScan; begin DelRegValue(HKEY_LOCAL_MACHINE, REG_HE, 'cppn'); DelRegValue(HKEY_LOCAL_MACHINE, REG_HE, 'cptd'); DelRegValue(HKEY_LOCAL_MACHINE, REG_HE, 'cpid'); DeleteDir(GetRunExePathDir + DIR_CTTSCHRST); if not IsNewApi then SetSchRstVul(false); MgCttSch_.Clear; bClearCampn_ := true; end; procedure TManagerService.RetryPersonalScan; begin bIgrLastWorkCampn_ := true; end; //function TManagerService.IsHecDev: Boolean; // HEC 개발계인가? //begin // Result := IsHD and (Pos('10.10.144.113:8443', gMgSvc.DestIPort) = 0); //end; function TManagerService.GetAipPath: String; var sAipExe: String; begin Result := ''; if PrefModel_.AipOff then exit; if not IsSupportAIP then exit; if bWin7Ver_ then exit; sAipExe := EXE_AIP; {$IFDEF DEBUG} case CUSTOMER_TYPE of CUSTOMER_DEV : sAipExe := 'dev_BSOne-AIP-Decrypt.exe'; CUSTOMER_UNITUS : sAipExe := 'unitus_BSOne-AIP-Decrypt.exe'; end; {$ENDIF} //{$IFNDEF DEBUG} Result := GetRunExePathDir + DIR_AIP17 + sAipExe; if not FileExists(Result) then //{$ENDIF} Result := GetRunExePathDir + DIR_AIP14 + sAipExe; if not FileExists(Result) then Result := GetRunExePathDir + DIR_AIP12 + sAipExe; end; function TManagerService.GetUrlBlockList: String; var PO: TPrefModel; begin Result := ''; try PO := GetModePolicy; if PrefModel_.UrlBlkRuleList <> '' then begin if PO.WebbMonKind = wmkIncBlock then Result := PO.UrlBlockList + '|' + PrefModel_.UrlBlkRuleList; end; if Result = '' then Result := PO.UrlBlockList; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. GetUrlBlockList()'); end; end; procedure TManagerService.AddEncIgr(sPath: String); begin if ThdReact_ <> nil then ThdReact_.AddEncIgr(sPath); end; procedure TManagerService.AddAfterEnc(sPath: String); begin if ThdReact_ <> nil then ThdReact_.AddAfterEnc(sPath); end; function TManagerService.HasEncIgr(sPath: String; bChkDel: Boolean = false): Boolean; begin if ThdReact_ <> nil then Result := ThdReact_.HasEncIgr(sPath, bChkDel); end; function TManagerService.GetModeKind: TBS1ModeKind; begin Lock; try Result := BS1ModeKind_; finally Unlock; end; end; procedure TManagerService.SetModeKind(aKind: TBS1ModeKind); begin Lock; try if BS1ModeKind_ <> aKind then BS1ModeKind_ := aKind; finally Unlock; end; end; procedure TManagerService.SetModeName(sModeName: String); begin Lock; try if sModeName_ <> sModeName then sModeName_ := sModeName; finally Unlock; end; end; function TManagerService.GetModeName: String; begin Lock; try Result := sModeName_; finally Unlock; end; end; function TManagerService.AddOpenDoc(dwPid: DWORD; sPath: String): Boolean; begin Result := false; if DcOpenDoc_ = nil then exit; Lock; try if not DcOpenDoc_.ContainsKey(dwPid) then begin DcOpenDoc_.Add(dwPid, sPath); Result := true; end else begin Result := not SameText(DcOpenDoc_[dwPid], sPath); if Result then DcOpenDoc_[dwPid] := sPath; end; finally Unlock; end; end; procedure TManagerService.DelOpenDocProc(dwPid: DWORD); begin if DcOpenDoc_ = nil then exit; Lock; try if DcOpenDoc_.ContainsKey(dwPid) then DcOpenDoc_.Remove(dwPid); finally Unlock; end; end; procedure TManagerService.CheckEmpNo_TMAP; var sTemp, sAccount: String; begin if CUSTOMER_TYPE <> CUSTOMER_TMAP then exit; try sAccount := WTS_GetCurrentUserName; if (sAccount <> '') and (sAccount_ <> sAccount) then begin _Trace('[07] 사번 변경, %s > %s', [AgentModel_.EmpNo, sAccount], 1); SendEventLogEx(LOG_CHANGE_EMPNO, Format('[Fixed] EmpId Changed. (%s > %s)', [AgentModel_.EmpNo, sAccount]), false); sAccount_ := sAccount; AgentModel_.EmpNo := sAccount_; AgentModel_.Save; UpdateAgentInfo; end; if (sEmpNo_ <> '') and (sEmpNo_ <> 'Temp') then begin try sTemp := sEmpNo_.ToUpper; if (sTemp[1] <> 'T') and (sTemp[1] <> 'Y') then begin sTemp := 'Temp'; exit; end; Delete(sTemp, 1, 1); if StrToIntDef(sTemp, 0) = 0 then sTemp := 'Temp'; finally if sTemp = 'Temp' then begin _Trace('[08] 사번 변경, %s > %s', [AgentModel_.EmpNo, sTemp], 1); SendEventLogEx(LOG_CHANGE_EMPNO, Format('[Fixed] EmpId Changed. (%s > %s)', [AgentModel_.EmpNo, sTemp]), false); AgentModel_.EmpNo := sTemp; AgentModel_.Save; UpdateAgentInfo; end; end; end; except on E: Exception do ETgException.TraceException(Self, E, 'Fail .. CheckEmpNo_TMAP()'); end; end; procedure TManagerService.ProcessEndSession; begin _Trace('ProcessEndSession() ..'); if not bIsEndSession_ then begin _Trace('ProcessEndSession() .. 1'); bIsEndSession_ := true; if ThdEvent_ <> nil then ThdEvent_.IsEndSession := true; if GetModePolicy.IsPcStatePower then begin if Connected then gMgSvc.DirectSendEventLog('none', MONITOR_PC_POWER, 'Power Off', false) else SetRegValueString(HKEY_LOCAL_MACHINE, REG_HE, 'EDT', IntToStr(DelphiToJavaDateTime(Now)), true); end; end; end; initialization if _CheckVpnList = nil then _CheckVpnList := TStringList.Create; Finalization if _CheckVpnList <> nil then FreeAndNil(_CheckVpnList); // if _bmpWaterP <> nil then FreeAndNil(_bmpWaterP); end.