tripwire-open-source/src/tw/filemanipulator.cpp

358 lines
11 KiB
C++

//
// The developer of the original code and/or files is Tripwire, Inc.
// Portions created by Tripwire, Inc. are copyright (C) 2000 Tripwire,
// Inc. Tripwire is a registered trademark of Tripwire, Inc. All rights
// reserved.
//
// This program is free software. The contents of this file are subject
// to the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at your
// option) any later version. You may redistribute it and/or modify it
// only in compliance with the GNU General Public License.
//
// This program is distributed in the hope that it will be useful.
// However, this program is distributed AS-IS WITHOUT ANY
// WARRANTY; INCLUDING THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS
// FOR A PARTICULAR PURPOSE. Please see the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.
//
// Nothing in the GNU General Public License or any other license to use
// the code or files shall permit you to use Tripwire's trademarks,
// service marks, or other intellectual property without Tripwire's
// prior written consent.
//
// If you have any questions, please contact Tripwire, Inc. at either
// info@tripwire.org or www.tripwire.org.
//
///////////////////////////////////////////////////////////////////////////////
// filemanipulator.cpp -- Provides functionality to examine tripwire file headers
// for file type and encryption type. Also provides a mechanism for
// changing encryption keys or removing encryption.
//
#include "stdtw.h"
#include "filemanipulator.h"
#include "core/serializerimpl.h"
#include "twutil.h"
#include "fcodatabasefile.h"
#include "fcoreport.h"
#include "configfile.h"
#include "policyfile.h"
#include "headerinfo.h"
#include "core/usernotify.h"
#include "twcrypto/crypto.h"
#include "util/fileutil.h"
#include "tw/twstrings.h"
#include "core/displayencoder.h"
//=============================================================================
// class cFileManipulator
//=============================================================================
cFileManipulator::cFileManipulator(const TCHAR* filename)
{
mbInit = false;
mFileName = filename;
}
cFileManipulator::cFileManipulator(const cFileManipulator& rhs)
: mFileName(rhs.mFileName),
mFileHeader(rhs.mFileHeader)
{
}
cFileManipulator::~cFileManipulator()
{
}
void cFileManipulator::Init()
{
if (cFileUtil::FileExists(mFileName))
{
cFileArchive arch;
try
{
try
{
arch.OpenRead( mFileName.c_str() );
}
catch (eArchive&)
{
throw eFileManipFileRead( mFileName );
}
cSerializerImpl s(arch, cSerializerImpl::S_READ);
mFileHeader.Read(&s);
}
catch (eArchive&)
{
throw eFileManipHeaderNotFound( mFileName );
}
catch (eSerializer&)
{
throw eFileManipHeaderNotFound( mFileName );
}
}
else
{
throw eFileManipFileNotFound( mFileName );
}
mbInit = true;
}
const cFileHeaderID* cFileManipulator::GetHeaderID()
{
ASSERT( mbInit );
if (!mbInit)
{
// return NULL;
Init();
}
return &mFileHeader.GetID();
}
uint32 cFileManipulator::GetFileVersion()
{
ASSERT( mbInit );
if (!mbInit)
{
// return 0;
Init();
}
return mFileHeader.GetVersion();
}
cFileHeader::Encoding cFileManipulator::GetEncoding()
{
ASSERT( mbInit );
if (!mbInit)
{
// return (cFileHeader::Encoding)0;
Init();
}
return mFileHeader.GetEncoding();
}
// Try to decrypt the file using the given key. If thorough is true then
// the entire file is read into memory. Returns true if decryption was
// successful.
bool cFileManipulator::TestDecryption(const cElGamalSigPublicKey& key, bool thorough)
{
// TODO: pay attention to thorough flag. For now we will just always act thoroughly.
ASSERT( mbInit );
if (!mbInit)
{
return false;
}
bool fError = false;
// "turn down" the verbosity of iUserNotify to V_NORMAL it it is V_VERBOSE to make output a little cleaner
bool fChangedVerbosity = false;
int savedVerbosity = iUserNotify::GetInstance()->GetVerboseLevel();
if( savedVerbosity == iUserNotify::V_VERBOSE )
{
iUserNotify::GetInstance()->SetVerboseLevel( iUserNotify::V_NORMAL );
fChangedVerbosity = true;
}
try
{
if (mFileHeader.GetID() == cFCODatabaseFile::GetFileHeaderID())
{
cFCODatabaseFile db;
bool encrypted;
cTWUtil::ReadDatabase(mFileName.c_str(), db, &key, encrypted);
}
else if (mFileHeader.GetID() == cFCOReport::GetFileHeaderID())
{
cFCOReport rep;
cFCOReportHeader reph;
bool encrypted;
cTWUtil::ReadReport(mFileName.c_str(), reph, rep, &key, true, encrypted);
}
else if (mFileHeader.GetID() == cConfigFile::GetFileHeaderID())
{
// read the embedded key from config file and see if it is the same
// as the public key passed in.
cMemoryArchive memArch;
TSTRING configText; //not used
cTWUtil::ReadConfigText( mFileName.c_str(), configText, &memArch );
memArch.Seek( 0, cBidirArchive::BEGINNING );
// only do the test if there is baggage (indicating the cfg file is encrypted)
if( memArch.Length() > 0 )
{
// create the two public keys...
cElGamalSigPublicKey pubKey( memArch.GetMemory() );
// compare the two ....
if( ! pubKey.IsEqual( key ) )
throw ePoly();
}
}
else if (mFileHeader.GetID() == cPolicyFile::GetFileHeaderID())
{
std::string policyText;
cTWUtil::ReadPolicyText(mFileName.c_str(), policyText, &key);
}
else
throw ePoly();
}
catch (eError&)
{
fError = true;
}
// reset verbosity
if( fChangedVerbosity )
iUserNotify::GetInstance()->SetVerboseLevel( savedVerbosity );
return( fError == false );
}
// Change the encryption on a file.
// If pNewKey is NULL, then encryption on the file will be removed.
// If pOldKey is NULL and the file is currently encrypted, then the
// function will throw eFileManip;
// If pOldKey is not NULL and the file is encrypted, then the fuction
// will throw eFileManip;
// If pOldKey is NULL and pNewKey is NULL and the file is not
// currently encrypted, the function will not do anything and will just
// return.
// Returns on successful encryption change.
void cFileManipulator::ChangeEncryption(const cElGamalSigPublicKey* pOldKey, const cElGamalSigPrivateKey* pNewKey, bool backup)
{
ASSERT( mbInit );
if (!mbInit)
{
Init();
}
// check the pOldKey matches the current encryption state
if (mFileHeader.GetEncoding() != cFileHeader::ASYM_ENCRYPTION)
{
if (pOldKey != NULL)
throw eFileManipNotEncrypted( mFileName );
if (pNewKey == NULL)
return; // NOOP
}
else if (pOldKey == NULL)
throw eFileManipMissingKey();
if (!cFileUtil::FileWritable(mFileName))
throw eFileManipNotWritable( mFileName );
if (mFileHeader.GetID() == cFCODatabaseFile::GetFileHeaderID())
{
cFCODatabaseFile db;
bool encrypted;
cTWUtil::ReadDatabase(mFileName.c_str(), db, pOldKey, encrypted);
if (backup)
{
TSTRING backname = mFileName + iFSServices::GetInstance()->GetStandardBackupExtension();
iFSServices::GetInstance()->Rename(mFileName.c_str(), backname.c_str());
}
cTWUtil::WriteDatabase(mFileName.c_str(), db, pNewKey != NULL, pNewKey);
return;
}
else if (mFileHeader.GetID() == cFCOReport::GetFileHeaderID())
{
cFCOReport rep;
cFCOReportHeader reph;
bool encrypted;
cTWUtil::ReadReport(mFileName.c_str(), reph, rep, pOldKey, false, encrypted);
if (backup)
{
TSTRING backname = mFileName + iFSServices::GetInstance()->GetStandardBackupExtension();
iFSServices::GetInstance()->Rename(mFileName.c_str(), backname.c_str());
}
cTWUtil::WriteReport(mFileName.c_str(), reph, rep, pNewKey != NULL, pNewKey);
return;
}
else if (mFileHeader.GetID() == cConfigFile::GetFileHeaderID())
{
TSTRING configText;
iUserNotify::GetInstance()->Notify( iUserNotify::V_VERBOSE, _T("%s%s\n"),
TSS_GetString( cTW, tw::STR_OPEN_CONFIG_FILE).c_str(),
cDisplayEncoder::EncodeInline( mFileName ).c_str());
cTWUtil::ReadConfigText(mFileName.c_str(), configText);
if (backup)
{
TSTRING backname = mFileName + iFSServices::GetInstance()->GetStandardBackupExtension();
iFSServices::GetInstance()->Rename(mFileName.c_str(), backname.c_str());
}
cTWUtil::WriteConfigText(mFileName.c_str(), configText, pNewKey != NULL, pNewKey);
return;
}
else if (mFileHeader.GetID() == cPolicyFile::GetFileHeaderID())
{
std::string policyText;
iUserNotify::GetInstance()->Notify( iUserNotify::V_VERBOSE, _T("%s%s\n"),
TSS_GetString( cTW, tw::STR_OPEN_POLICY_FILE).c_str(),
cDisplayEncoder::EncodeInline( mFileName ).c_str());
cTWUtil::ReadPolicyText(mFileName.c_str(), policyText, pOldKey);
if (backup)
{
TSTRING backname = mFileName + iFSServices::GetInstance()->GetStandardBackupExtension();
iFSServices::GetInstance()->Rename(mFileName.c_str(), backname.c_str());
}
cTWUtil::WritePolicyText(mFileName.c_str(), policyText, pNewKey != NULL, pNewKey);
return;
}
}
// method for getting a list of manipulators
// returns number of files matched
int cFileManipulator::LoadFiles(std::list<cFileManipulator>& ret, TSTRING mask)
{
ret.clear();
// TODO: we need to be able to deal with masks for the NT version.
// Right now *.* will not work in NT. We should not get a '*' for unix.
try
{
ret.push_back(cFileManipulator(mask.c_str()));
}
catch (eError&)
{
// file does not exist
return 0;
}
return 1;
}
bool cFileManipulator::UseSiteKey(const cFileHeaderID& headerID)
{
if (headerID == cFCODatabaseFile::GetFileHeaderID() ||
headerID == cFCOReport::GetFileHeaderID())
return false;
else
if (headerID == cConfigFile::GetFileHeaderID() ||
headerID == cPolicyFile::GetFileHeaderID())
return true;
ASSERT(false); // what could it be? be careful not to en/decrypt keyfiles.
return false;
}