#include <security_utilities/errors.h>
#include <security_utilities/debugging.h>
#include <security_utilities/utility_config.h>
#include <security_utilities/debugging_internal.h>
#include <typeinfo>
#include <stdio.h>
#include <Security/SecBase.h>
#include <execinfo.h>
#include <cxxabi.h>
#define errSecErrnoBase 100000
#define errSecErrnoLimit 100255
CommonError::CommonError() : whatBuffer("CommonError")
{
}
CommonError::CommonError(const CommonError &source)
{
strlcpy(whatBuffer, source.whatBuffer, whatBufferSize);
}
CommonError::~CommonError() throw ()
{
}
void CommonError::LogBacktrace() {
if(secinfoenabled("security_exception")) {
const size_t maxsize = 32;
void* callstack[maxsize];
int size = backtrace(callstack, maxsize);
char** names = backtrace_symbols(callstack, size);
const char* delim = " ";
string build;
char * token = NULL;
char * line = NULL;
for(int i = 0; i < size; i++) {
build = "";
line = names[i];
while((token = strsep(&line, delim))) {
if(*token == '\0') {
build += " ";
} else {
int status = 0;
char * demangled = abi::__cxa_demangle(token, NULL, NULL, &status);
if(status == 0) {
build += demangled;
} else {
build += token;
}
build += " ";
if(demangled) {
free(demangled);
}
}
}
secinfo("security_exception", "%s", build.c_str());
}
free(names);
}
}
UnixError::UnixError() : error(errno)
{
SECURITY_EXCEPTION_THROW_UNIX(this, errno);
snprintf(whatBuffer, whatBufferSize, "UNIX errno exception: %d", this->error);
secnotice("security_exception", "%s", what());
LogBacktrace();
}
UnixError::UnixError(int err, bool suppresslogging) : error(err)
{
SECURITY_EXCEPTION_THROW_UNIX(this, err);
if(!suppresslogging || secinfoenabled("security_exception")) {
snprintf(whatBuffer, whatBufferSize, "UNIX error exception: %d", this->error);
secnotice("security_exception", "%s", what());
LogBacktrace();
}
}
const char *UnixError::what() const throw ()
{
return whatBuffer;
}
OSStatus UnixError::osStatus() const
{
return error + errSecErrnoBase;
}
int UnixError::unixError() const
{ return error; }
void UnixError::throwMe(int err) { throw UnixError(err, false); }
void UnixError::throwMeNoLogging(int err) { throw UnixError(err, true); }
UnixError UnixError::make(int err) { return UnixError(err, false); }
MacOSError::MacOSError(int err) : error(err)
{
SECURITY_EXCEPTION_THROW_OSSTATUS(this, err);
snprintf(whatBuffer, whatBufferSize, "MacOS error: %d", this->error);
secnotice("security_exception", "%s", what());
LogBacktrace();
}
const char *MacOSError::what() const throw ()
{
return whatBuffer;
}
OSStatus MacOSError::osStatus() const
{ return error; }
int MacOSError::unixError() const
{
if (error >= errSecErrnoBase && error <= errSecErrnoLimit)
return error - errSecErrnoBase;
switch (error) {
default:
return -1;
}
}
void MacOSError::throwMe(int error)
{ throw MacOSError(error); }
MacOSError MacOSError::make(int error)
{ return MacOSError(error); }
CFError::CFError()
{
SECURITY_EXCEPTION_THROW_CF(this);
secnotice("security_exception", "CFError");
LogBacktrace();
}
const char *CFError::what() const throw ()
{ return "CoreFoundation error"; }
OSStatus CFError::osStatus() const
{ return errSecCoreFoundationUnknown; }
int CFError::unixError() const
{
return EFAULT; }
void CFError::throwMe()
{ throw CFError(); }
void ModuleNexusError::throwMe()
{
throw ModuleNexusError();
}
OSStatus ModuleNexusError::osStatus() const
{
return errSecParam;
}
int ModuleNexusError::unixError() const
{
return EINVAL;
}