#ifndef _H_SIGNERUTILS
#define _H_SIGNERUTILS
#include "CodeSigner.h"
#include "sigblob.h"
#include "cdbuilder.h"
#include <security_utilities/utilities.h>
#include <security_utilities/blob.h>
#include <security_utilities/unix++.h>
#include <security_utilities/unixchild.h>
extern "C" {
#include <copyfile.h>
}
namespace Security {
namespace CodeSigning {
class InternalRequirements : public Requirements::Maker {
public:
InternalRequirements() : mReqs(NULL) { }
~InternalRequirements() { ::free((void *)mReqs); }
void operator () (const Requirements *given, const Requirements *defaulted);
operator const Requirements * () const { return mReqs; }
private:
const Requirements *mReqs;
};
class BlobWriter : public DiskRep::Writer, public EmbeddedSignatureBlob::Maker {
public:
void component(CodeDirectory::SpecialSlot slot, CFDataRef data);
};
class DetachedBlobWriter : public BlobWriter {
public:
DetachedBlobWriter(SecCodeSigner::Signer &s) : signer(s) { }
SecCodeSigner::Signer &signer;
void flush();
};
class ArchEditor : public DiskRep::Writer {
public:
ArchEditor(Universal &fat, uint32_t attrs = 0);
virtual ~ArchEditor();
public:
struct Arch : public BlobWriter {
Architecture architecture; auto_ptr<MachO> source; CodeDirectory::Builder cdbuilder; InternalRequirements ireqs; size_t blobSize;
Arch(const Architecture &arch) : architecture(arch) { }
};
typedef std::map<Architecture, Arch *> ArchMap;
typedef ArchMap::iterator Iterator;
ArchMap::iterator begin() { return architecture.begin(); }
ArchMap::iterator end() { return architecture.end(); }
unsigned count() const { return architecture.size(); }
virtual void allocate() = 0; virtual void reset(Arch &arch) = 0; virtual void write(Arch &arch, EmbeddedSignatureBlob *blob) = 0; virtual void commit() = 0;
protected:
ArchMap architecture;
};
class BlobEditor : public ArchEditor {
public:
BlobEditor(Universal &fat, SecCodeSigner::Signer &s) : ArchEditor(fat), signer(s) { }
~BlobEditor() { }
SecCodeSigner::Signer &signer;
void component(CodeDirectory::SpecialSlot slot, CFDataRef data);
void allocate() { }
void reset(Arch &arch) { }
void write(Arch &arch, EmbeddedSignatureBlob *blob);
void commit();
private:
DetachedSignatureBlob::Maker mMaker;
EmbeddedSignatureBlob::Maker mGlobal;
};
class MachOEditor : public ArchEditor, private UnixPlusPlus::Child {
public:
MachOEditor(DiskRep::Writer *w, Universal &code, std::string srcPath);
~MachOEditor();
const RefPointer<DiskRep::Writer> writer;
const std::string sourcePath;
const std::string tempPath;
void component(CodeDirectory::SpecialSlot slot, CFDataRef data);
void allocate();
void reset(Arch &arch);
void write(Arch &arch, EmbeddedSignatureBlob *blob);
void commit();
private:
void childAction();
void parentAction();
Universal *mNewCode;
UnixPlusPlus::AutoFileDesc mFd;
bool mTempMayExist;
const char *mHelperPath;
bool mHelperOverridden;
};
class Copyfile {
public:
Copyfile();
~Copyfile() { copyfile_state_free(mState); }
operator copyfile_state_t () const { return mState; }
void set(uint32_t flag, const void *value);
void get(uint32_t flag, void *value);
void operator () (const char *src, const char *dst, copyfile_flags_t flags);
private:
void check(int rc);
private:
copyfile_state_t mState;
};
class UidGuard {
public:
UidGuard() : mPrevious(-1) { }
UidGuard(uid_t uid) : mPrevious(-1) { seteuid(uid); }
~UidGuard()
{
if (active())
UnixError::check(::seteuid(mPrevious));
}
bool seteuid(uid_t uid)
{
if (uid == geteuid())
return true; if (!active())
mPrevious = ::geteuid();
return ::seteuid(uid) == 0;
}
bool active() const { return mPrevious != uid_t(-1); }
operator bool () const { return active(); }
uid_t saved() const { assert(active()); return mPrevious; }
private:
uid_t mPrevious;
};
} }
#endif // !_H_SIGNERUTILS