528 lines
16 KiB
Plaintext
528 lines
16 KiB
Plaintext
{*******************************************************}
|
||
{ }
|
||
{ Tocsg.Fasoo }
|
||
{ }
|
||
{ Copyright (C) 2024 kku }
|
||
{ }
|
||
{*******************************************************}
|
||
|
||
unit Tocsg.Fasoo;
|
||
|
||
interface
|
||
|
||
uses
|
||
Tocsg.Obj, System.SysUtils, Winapi.Windows, System.Classes;
|
||
|
||
const
|
||
{$IFDEF WIN64}
|
||
DLL_FASOO = 'WorkPackagerV3_64.dll';
|
||
{$ELSE}
|
||
DLL_FASOO = 'WorkPackagerV3.dll';
|
||
{$ENDIF}
|
||
FASOO_COM_OLD = 'WorkPackager.WorkPackagerADK'; // 구버전, CJ에서 사용
|
||
FASOO_COM = 'WorkPackagerV3.WorkPackagerADK'; // 새버전, 2020년 4월 부터 변경됐다고 함, 삼성중공업에서 사용
|
||
|
||
DSD_CODE_LOTTEMART = '0100000000002054'; // 롯데마트
|
||
DSD_CODE_SHI = '0000000000001833'; // 삼성중공업
|
||
DSD_CODE_CJ = '0000000000002519'; // CJ
|
||
DSD_CODE_WFNI = '0100000000004457'; // 웰릭스에프앤아이 (구 웰컴에프앤디)
|
||
DSD_CODE_WFND = '0100000000001803'; // 웰컴에프앤디
|
||
DSD_CODE_GIORDANO = '0100000000004318'; // 지오다노
|
||
|
||
const
|
||
// Error Code (FED4.0, FED5.0 공통)
|
||
E_SERVERID_NOT_EXIST = 3; // server id가 입력되지 않았을 경우
|
||
E_INVALID_PARAM = 4; // 필수 인자값이 입력되지 않았을 경우
|
||
E_REQ_INFO_NOT_EXIST = 16; // Home Dir이 입력되지 않거나 필수 속성이 존재하지 않을 경우
|
||
E_INVALID_FILE_EXT_NSPRT = 11; // 지원하지 않는 파일 확장자
|
||
E_FILE_NOT_EXIST = 20; // 파일이 존재하지 않을 경우.
|
||
E_FILE_SIZE_ZERO = 21; // 파일 크기가 0일 경우
|
||
E_FILE_OPEN_FAIL = 22; // 파일 열람에 실패할 경우.
|
||
E_FILE_READ_FAIL = 23; // 파일 읽기에 실패할 경우
|
||
E_PACKAGED_FILE = 26; // FSD 파일
|
||
E_OLD_OLE_FILE = 27; // 지원하지 않는 OLE 파일 타입.
|
||
E_NOT_PACKAGED_FILE = 29; // 일반 파일
|
||
E_FILE_DELETE_FAIL = 30; // 파일 삭제에 실패할 경우
|
||
E_CHECK_CERTIFICATE_FAIL = 40; // 인증서가 없거나 유효하지 않을 경우
|
||
E_COCREATE_INST_FAIL = 41; // COM 객체 생성 실패
|
||
E_DECODING_FAIL = 51; // 디코딩 실패
|
||
E_SYMMDEC_FAIL = 54; // 암호화 실패
|
||
E_MEMALLOCFAIL = 70; // 메모리 할당 실패
|
||
E_NOT_INITIALIZE = 72; // 메모리 초기화 실패
|
||
|
||
// Error Code 참조 (FED5.0 전용)
|
||
SC_FILE_FED5_PACKAGED = 1150; // FED5.0 FSD 문서
|
||
SC_FILE_FED5_FSN_PACKAGED = 1151; // FED5.0 FSN 문서
|
||
SC_FILE_FED5_FSE_PACKAGED = 1152; // FED5.0 FSE 문서
|
||
SC_FILE_FED5_NX_PACKAGED = 1153; // FED5.0 NX 문서
|
||
SC_NOT_SUPPORT_RIGHT = 1166; // 문서 타입 변환시 해당 문서에 ‘CONVERSION’ 또는 ‘SAVE’ 권한이 없을 경우
|
||
SC_DISABLED_LOGGING = 1167; // 로그 전송 설정이 되어 있지 않거나 인증서가 설정되어 있지 않을 경우
|
||
SC_NOT_FED_VERSION = 1176; // conf 파일의 [PACKAGER] 필드에 VERSION 값이 존재하지 않을 경우 (FED4.0 conf 파일에는 해당값이 존재하지 않음)
|
||
SC_FAILED_GET_RIGHTS = 1178; // 문서 복호화시 서버나 클라이언트에 복호화 권한 확인시 권한이 없거나 권한 확인에 실패할 경우
|
||
SC_NOT_SUPPORT_ALGORITHM = 1180; // 지원하지 않는 알고리즘
|
||
SC_FAILED_SECTION_FIND = 1201; // 문서 헤더에서 섹션을 찾는데 실패할 경우
|
||
SC_FAILED_HMAC_COMPARE = 1205; // 문서 헤더의 HMAC 확인에 실패할 경우 (문서 헤더 위변조 여부 확인)
|
||
SC_FAILED_GET_DOMAINKEY = 1214; // 인증서에서 도메인키를 가져오는데 실패할 경우
|
||
SC_DISCARD_APPCERT = 1216; // 폐기된 인증서를 호출할 경우
|
||
SC_DISCARD_DKCOUNT = 1217; // 폐기된 도메인키 카운트를 적용할 경우
|
||
SC_FAILED_CERT_SIGN = 1500; // cert에 실패할 경우
|
||
SC_FAILED_GET_KEY = 1501; // 키를 가져오는데 실패할 경우
|
||
SC_FAILED_PFX_LOAD = 1502; // 인증서 로드에 실패할 경우
|
||
SC_FAILED_GET_APPKEY = 1503; // 응용서버 인증서 디코드에 실패할 경우
|
||
|
||
type
|
||
TTgFasoo = class(TTgObject)
|
||
private
|
||
nVer_: Integer; // 0 = COM 개체 획득 못함, 1 = 올드, 2 = 2020년 4월 이후
|
||
ComObj_: Variant;
|
||
sFsdFsnPath_, // FSN 문서 복호화 키(폴더) 경로
|
||
sFsdNxPath_, // NX 문서 복호화 키(폴더) 경로
|
||
sFixedCPID_: String; // CPID(구 Server ID)를 고정해서 사용할때 사용
|
||
public
|
||
Constructor Create(sFsdFsnPath: String; sFsdNxPath: String = '');
|
||
function IsReady: Boolean;
|
||
|
||
function GetFileType(sEncPath: String): Integer;
|
||
function GetFileHeader(sEncPath: String): String;
|
||
function IsPackageFile(sEncPath: String): Boolean;
|
||
|
||
// 복호화
|
||
function DoExtract(sEncPath, sDecPath: String; bLogonUser: Boolean = false; pnResult: PInteger = nil): Boolean;
|
||
|
||
// 암호화
|
||
function DoPackagingFsn(sSrcPath, sDestPath: String; pnResult: PInteger = nil): Boolean;
|
||
function DoPackagingFsn2(sSrcPath, sDestPath: String; pnResult: PInteger = nil): Boolean;
|
||
|
||
function DoPackaging(sSrcPath, sDestPath: String; pnResult: PInteger = nil): Boolean;
|
||
end;
|
||
|
||
{$IFDEF _CJ_}
|
||
function IsFasooLogon: Integer;
|
||
function GetFasooUserID: String;
|
||
{$ENDIF}
|
||
|
||
procedure SetDSD_CODE(sCode: String);
|
||
|
||
var
|
||
DSD_CODE: String = DSD_CODE_LOTTEMART;
|
||
|
||
// 암호화 시 사용
|
||
_sWriteId_: String = 'dlpadmin';// 'csm_tocsg';;
|
||
_sWriteName: String = 'dlpadmin';//'최성민';
|
||
_sWriteDeptCode: String = 'COMPANY';
|
||
_sWriteDeptName: String = 'DeptName';
|
||
_sSecurityLevel: String = 'a890dab1a2964ddfba69a04c3d4431ba';
|
||
|
||
implementation
|
||
|
||
uses
|
||
{$IFDEF _CJ_}
|
||
Winapi.ActiveX, F_SSOLib_TLB,
|
||
{$ENDIF}
|
||
System.Win.ComObj, System.Variants, Tocsg.Safe, Tocsg.Exception, Tocsg.Strings;
|
||
|
||
procedure SetDSD_CODE(sCode: String);
|
||
begin
|
||
DSD_CODE := sCode;
|
||
|
||
if DSD_CODE = DSD_CODE_LOTTEMART then
|
||
begin
|
||
_sWriteDeptName := '롯데마트';
|
||
_sSecurityLevel := 'a890dab1a2964ddfba69a04c3d4431ba';
|
||
end else
|
||
if DSD_CODE = DSD_CODE_WFNI then
|
||
begin
|
||
_sWriteId_ := 'admin';
|
||
_sWriteName := 'admin';
|
||
_sWriteDeptName := '웰릭스에프앤아이'; //'웰컴에프앤디';
|
||
// _sSecurityLevel := '39e43183f99f4170be6227255a07dadd'; // 기본보안등급
|
||
_sSecurityLevel := '320ce4ed95a34221be960d8f362cbcce'; // 개인정보등급
|
||
end else
|
||
if DSD_CODE = DSD_CODE_WFND then
|
||
begin
|
||
_sWriteId_ := 'admin';
|
||
_sWriteName := 'admin';
|
||
_sWriteDeptName := '웰컴에프앤디';
|
||
// _sSecurityLevel := '39e43183f99f4170be6227255a07dadd'; // 기본보안등급
|
||
_sSecurityLevel := '320ce4ed95a34221be960d8f362cbcce'; // 개인정보등급
|
||
end else begin
|
||
_sWriteDeptName := 'Unknown';
|
||
_sSecurityLevel := '';
|
||
end;
|
||
end;
|
||
|
||
{ TTgFasoo }
|
||
|
||
Constructor TTgFasoo.Create(sFsdFsnPath: String; sFsdNxPath: String = '');
|
||
|
||
procedure Init;
|
||
begin
|
||
// try
|
||
// ComObj_ := CreateOleObject(FASOO_COM_OLD);
|
||
// nVer_ := 1;
|
||
// except
|
||
// on E: Exception do
|
||
// ETgException.TraceException(Self, E, Format('Create() .. Fail load .. "%s"', [FASOO_COM_OLD]));
|
||
// end;
|
||
|
||
if nVer_ <= 0 then
|
||
begin
|
||
try
|
||
ComObj_ := CreateOleObject(FASOO_COM);
|
||
nVer_ := 2;
|
||
_Trace('Create() .. Success');
|
||
except
|
||
on E: Exception do
|
||
ETgException.TraceException(Self, E, Format('Create() .. Fail load .. "%s"', [FASOO_COM]));
|
||
end;
|
||
end;
|
||
end;
|
||
|
||
begin
|
||
Inherited Create;
|
||
nVer_ := -1;
|
||
ComObj_ := varEmpty;
|
||
sFixedCPID_ := '';
|
||
sFsdFsnPath_ := sFsdFsnPath;
|
||
if sFsdNxPath = '' then
|
||
sFsdNxPath := sFsdFsnPath;
|
||
sFsdNxPath_ := sFsdNxPath;
|
||
Init;
|
||
|
||
if (nVer_ = 2) and (DirectoryExists(sFsdNxPath_)) then // 2020년 이후 신버전
|
||
sFixedCPID_ := DSD_CODE;
|
||
end;
|
||
|
||
function TTgFasoo.IsReady: Boolean;
|
||
begin
|
||
Result := nVer_ <> -1;
|
||
end;
|
||
|
||
function TTgFasoo.GetFileType(sEncPath: String): Integer;
|
||
begin
|
||
try
|
||
if not VarIsEmpty(ComObj_) then
|
||
Result := ComObj_.GetFileType(sEncPath)
|
||
else
|
||
Result := -1;
|
||
except
|
||
on E: Exception do
|
||
ETgException.TraceException(E, 'Fail .. GetFileType()');
|
||
end;
|
||
end;
|
||
|
||
function TTgFasoo.GetFileHeader(sEncPath: String): String;
|
||
begin
|
||
if not VarIsEmpty(ComObj_) then
|
||
Result := ComObj_.GetFileHeader(sEncPath)
|
||
else
|
||
Result := '';
|
||
end;
|
||
|
||
function TTgFasoo.IsPackageFile(sEncPath: String): Boolean;
|
||
begin
|
||
if not VarIsEmpty(ComObj_) then
|
||
Result := ComObj_.IsPackageFile(sEncPath) = 1
|
||
else
|
||
Result := false;
|
||
end;
|
||
|
||
function TTgFasoo.DoExtract(sEncPath, sDecPath: String; bLogonUser: Boolean = false; pnResult: PInteger = nil): Boolean;
|
||
var
|
||
nType, nResult: Integer;
|
||
sCPID,
|
||
sFHeader,
|
||
sFsdPath: String;
|
||
FHeaderList: TStringList;
|
||
begin
|
||
Result := false;
|
||
|
||
try
|
||
nResult := -1;
|
||
if pnResult <> nil then
|
||
pnResult^ := -1;
|
||
|
||
if nVer_ = 0 then
|
||
exit;
|
||
|
||
if VarIsEmpty(ComObj_) then
|
||
exit;
|
||
|
||
if not FileExists(sEncPath) then
|
||
exit;
|
||
|
||
sFsdPath := '';
|
||
nType := GetFileType(sEncPath);
|
||
case nType of
|
||
103 : // FSN
|
||
begin
|
||
if DirectoryExists(sFsdFsnPath_) then
|
||
sFsdPath := sFsdFsnPath_;
|
||
end;
|
||
106 : // NX
|
||
begin
|
||
if DirectoryExists(sFsdNxPath_) then
|
||
sFsdPath := sFsdNxPath_;
|
||
end
|
||
else exit;
|
||
end;
|
||
|
||
if sFsdPath = '' then
|
||
exit;
|
||
|
||
if FileExists(sDecPath) then
|
||
DeleteFile(PChar(sDecPath));
|
||
|
||
// 타사 고객사/계열사 암호화 파일인지 체크하도록 변경 25_0414 13:58:51 kku
|
||
// sCPID := sFixedCPID_;
|
||
// if sCPID = '' then
|
||
begin
|
||
sFHeader := GetFileHeader(sEncPath);
|
||
if sFHeader = '' then
|
||
exit;
|
||
Guard(FHeaderList, TStringList.Create);
|
||
|
||
SplitString(sFHeader, ';', FHeaderList, true);
|
||
if FHeaderList.Count < 18 then
|
||
exit;
|
||
sCPID := FHeaderList[17]; // 18번째에 있음
|
||
end;
|
||
|
||
// ServerID 체크 추가 25_0408 09:23:39 kku
|
||
// ServerID가 다른 암호화 파일을 복호화 시도하면 "타사 제품으로 암호화된 문서이므로 열람 할 수 없습니다."라는 메시지가 나온다고 함
|
||
if DSD_CODE <> sCPID then
|
||
begin
|
||
if pnResult <> nil then
|
||
pnResult^ := -2;
|
||
_Trace('Fail .. DoExtract() .. Invalid ServerID, Get=%s, Chk=%s', [sCPID, DSD_CODE], 3);
|
||
exit;
|
||
end;
|
||
|
||
if bLogonUser then
|
||
nResult := ComObj_.DoExtract_c(sFsdPath, sCPID, sEncPath, sDecPath, 'VIEW')
|
||
else
|
||
nResult := ComObj_.DoExtract(sFsdPath, sCPID, sEncPath, sDecPath);
|
||
|
||
if pnResult <> nil then
|
||
pnResult^ := nResult;
|
||
Result := FileExists(sDecPath);
|
||
except
|
||
on E: Exception do
|
||
ETgException.TraceException(Self, E, 'Fail .. DoExtract()');
|
||
end;
|
||
end;
|
||
|
||
function TTgFasoo.DoPackagingFsn(sSrcPath, sDestPath: String; pnResult: PInteger = nil): Boolean;
|
||
var
|
||
nResult: Integer;
|
||
begin
|
||
Result := false;
|
||
nResult := -1;
|
||
if pnResult <> nil then
|
||
pnResult^ := -1;
|
||
|
||
if nVer_ = 0 then
|
||
exit;
|
||
|
||
if _sSecurityLevel = '' then
|
||
exit;
|
||
|
||
if VarIsEmpty(ComObj_) then
|
||
exit;
|
||
|
||
if not FileExists(sSrcPath) then
|
||
exit;
|
||
|
||
if not DirectoryExists(sFsdFsnPath_) then
|
||
exit;
|
||
|
||
case GetFileType(sSrcPath) of
|
||
103 : exit; // FSN
|
||
106 : exit; // NX
|
||
end;
|
||
|
||
if FileExists(sDestPath) then
|
||
DeleteFile(PChar(sDestPath));
|
||
|
||
try
|
||
nResult := ComObj_.DoPackagingFsn(sFsdFsnPath_, DSD_CODE,
|
||
sSrcPath, sDestPath,
|
||
ExtractFileName(sSrcPath), _sWriteId_,
|
||
_sWriteName, _sWriteId_,
|
||
_sWriteName, _sWriteDeptCode,
|
||
_sWriteDeptName, _sWriteId_,
|
||
_sWriteName, _sWriteDeptCode,
|
||
_sWriteDeptName,
|
||
_sSecurityLevel);
|
||
|
||
if pnResult <> nil then
|
||
pnResult^ := nResult;
|
||
Result := FileExists(sDestPath);
|
||
except
|
||
on E: Exception do
|
||
ETgException.TraceException(Self, E, 'Fail .. DoPackagingFsn()');
|
||
end;
|
||
end;
|
||
|
||
function TTgFasoo.DoPackagingFsn2(sSrcPath, sDestPath: String; pnResult: PInteger = nil): Boolean;
|
||
var
|
||
nType,
|
||
nResult: Integer;
|
||
begin
|
||
Result := false;
|
||
nResult := -1;
|
||
if pnResult <> nil then
|
||
pnResult^ := -1;
|
||
|
||
if nVer_ = 0 then
|
||
exit;
|
||
|
||
if _sSecurityLevel = '' then
|
||
exit;
|
||
|
||
if VarIsEmpty(ComObj_) then
|
||
exit;
|
||
|
||
if not FileExists(sSrcPath) then
|
||
exit;
|
||
|
||
if not DirectoryExists(sFsdFsnPath_) then
|
||
exit;
|
||
|
||
nType := GetFileType(sSrcPath);
|
||
// _Trace('DoPackagingFsn2() .. 5, Type=%d', [nType]);
|
||
|
||
case GetFileType(sSrcPath) of
|
||
103 : exit; // FSN
|
||
106 : exit; // NX
|
||
end;
|
||
|
||
// _Trace('DoPackagingFsn2() .. 6');
|
||
|
||
if FileExists(sDestPath) then
|
||
DeleteFile(PChar(sDestPath));
|
||
|
||
try
|
||
nResult := ComObj_.DoPackagingFsn2(sFsdFsnPath_, DSD_CODE,
|
||
sSrcPath, sDestPath,
|
||
ExtractFileName(sSrcPath), _sWriteId_,
|
||
_sWriteName, _sWriteId_,
|
||
_sWriteName, _sWriteDeptCode,
|
||
_sWriteDeptName, _sWriteId_,
|
||
_sWriteName, _sWriteDeptCode,
|
||
_sWriteDeptName,
|
||
_sSecurityLevel);
|
||
|
||
if pnResult <> nil then
|
||
pnResult^ := nResult;
|
||
Result := FileExists(sDestPath);
|
||
|
||
// _Trace('DoPackagingFsn2() .. 7');
|
||
except
|
||
on E: Exception do
|
||
ETgException.TraceException(Self, E, 'Fail .. DoPackagingFsn2()');
|
||
end;
|
||
end;
|
||
|
||
function TTgFasoo.DoPackaging(sSrcPath, sDestPath: String; pnResult: PInteger = nil): Boolean;
|
||
var
|
||
nResult: Integer;
|
||
begin
|
||
Result := false;
|
||
nResult := -1;
|
||
if pnResult <> nil then
|
||
pnResult^ := -1;
|
||
|
||
if nVer_ = 0 then
|
||
exit;
|
||
|
||
if _sSecurityLevel = '' then
|
||
exit;
|
||
|
||
if VarIsEmpty(ComObj_) then
|
||
exit;
|
||
|
||
if not FileExists(sSrcPath) then
|
||
exit;
|
||
|
||
if not DirectoryExists(sFsdFsnPath_) then
|
||
exit;
|
||
|
||
case GetFileType(sSrcPath) of
|
||
103 : exit; // FSN
|
||
106 : exit; // NX
|
||
end;
|
||
|
||
if FileExists(sDestPath) then
|
||
DeleteFile(PChar(sDestPath));
|
||
|
||
try
|
||
nResult := ComObj_.DoPackaging(sFsdFsnPath_, DSD_CODE,
|
||
sSrcPath, sDestPath,
|
||
ExtractFileName(sSrcPath),
|
||
_sWriteId_, _sWriteName,
|
||
'', '', '', '', '');
|
||
|
||
if pnResult <> nil then
|
||
pnResult^ := nResult;
|
||
Result := FileExists(sDestPath);
|
||
except
|
||
on E: Exception do
|
||
ETgException.TraceException(Self, E, 'Fail .. DoPackagingFsn2()');
|
||
end;
|
||
end;
|
||
|
||
{$IFDEF _CJ_}
|
||
var
|
||
USER_KEY: String = 'CUID';
|
||
|
||
// 실패 : -1
|
||
// 로그온 : 1
|
||
// 로그오프 : 0
|
||
function IsFasooLogon: Integer;
|
||
var
|
||
hr: HResult;
|
||
iSSO: IxSSO;
|
||
begin
|
||
Result := -1;
|
||
try
|
||
CoInitializeEx(nil, COINIT_APARTMENTTHREADED);
|
||
try
|
||
iSSO := nil;
|
||
hr := CoCreateInstance(CLASS_FasooSSO, nil, CLSCTX_INPROC_SERVER, IID_IxSSO, iSSO);
|
||
if SUCCEEDED(hr) and (iSSO <> nil) then
|
||
Result := iSSO.IsLogon(DSD_CODE);
|
||
finally
|
||
CoUninitialize;
|
||
end;
|
||
except
|
||
// ..
|
||
end;
|
||
end;
|
||
|
||
// 로그 아웃 상태에서 시도하면 파수 로그인창이 뜨면서 "빈값"을 반환함
|
||
function GetFasooUserID: String;
|
||
var
|
||
hr: HResult;
|
||
iSSO: IxSSO;
|
||
begin
|
||
Result := '*Fail%_';
|
||
// Result := '';
|
||
try
|
||
CoInitializeEx(nil, COINIT_APARTMENTTHREADED);
|
||
try
|
||
iSSO := nil;
|
||
hr := CoCreateInstance(CLASS_FasooSSO, nil, CLSCTX_INPROC_SERVER, IID_IxSSO, iSSO);
|
||
if SUCCEEDED(hr) and (iSSO <> nil) then
|
||
Result := iSSO.GetUserInfo(DSD_CODE, USER_KEY);
|
||
finally
|
||
CoUninitialize;
|
||
end;
|
||
except
|
||
// ..
|
||
end;
|
||
end;
|
||
{$ENDIF}
|
||
|
||
end.
|