#include <Security/SecBasePriv.h>
#include <Security/SecKeychainPriv.h>
#include "SecBridge.h"
static CFStringRef copyErrorMessageFromBundle(OSStatus status,CFStringRef tableName);
CFStringRef
SecCopyErrorMessageString(OSStatus status, void *reserved)
{
try
{
return copyErrorMessageFromBundle(status,CFSTR("SecErrorMessages"));
}
catch (...)
{
return NULL;
}
}
void
cssmPerror(const char *how, CSSM_RETURN error)
{
try
{
string err;
if (CFStringRef errs = copyErrorMessageFromBundle(error, CFSTR("SecErrorMessages")))
{
err = cfString(errs);
CFRelease(errs);
}
if (err.empty())
{
fprintf(stderr, "%s: %ld\n", how ? how : "error", error);
}
else
{
fprintf(stderr, "%s: %s\n", how ? how : "error", err.c_str());
}
}
catch (...)
{
fprintf(stderr, "failed to print error: %ld\n", error);
}
}
const char *
cssmErrorString(CSSM_RETURN error)
{
try {
string err = cfString(copyErrorMessageFromBundle(error, CFSTR("SecErrorMessages")), true);
if (err.empty())
{
char buf[200];
snprintf(buf, sizeof(buf), "unknown error %ld=%lx", error, error);
err = buf;
}
static ThreadNexus<string> lastError;
lastError() = err;
return lastError().c_str();
}
catch (...)
{
return "cannot translate error code";
}
}
CFStringRef
copyErrorMessageFromBundle(OSStatus status,CFStringRef tableName)
{
CFStringRef errorString = nil;
CFStringRef keyString = nil;
CFBundleRef secBundle = NULL;
secBundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.security"));
if (!secBundle)
goto xit;
keyString = CFStringCreateWithFormat (kCFAllocatorDefault,NULL,CFSTR("%d"),status);
if (!keyString)
goto xit;
errorString = CFCopyLocalizedStringFromTableInBundle(keyString,tableName,secBundle,NULL);
xit:
if (keyString)
CFRelease(keyString);
return errorString;
}
OSStatus SecKeychainErrFromOSStatus(OSStatus osStatus)
{
if (CSSM_ERR_IS_CONVERTIBLE(osStatus))
{
switch (CSSM_ERRCODE(osStatus))
{
case CSSM_ERRCODE_SERVICE_NOT_AVAILABLE:
return errSecNotAvailable;
case CSSM_ERRCODE_USER_CANCELED:
return userCanceledErr;
case CSSM_ERRCODE_OPERATION_AUTH_DENIED:
return errSecAuthFailed;
case CSSM_ERRCODE_NO_USER_INTERACTION:
return errSecInteractionNotAllowed;
case CSSM_ERRCODE_OS_ACCESS_DENIED:
return wrPermErr;
default:
return osStatus;
}
}
else
{
switch (osStatus)
{
case CSSMERR_DL_OS_ACCESS_DENIED:
return wrPermErr;
case CSSMERR_DL_RECORD_NOT_FOUND:
return errSecItemNotFound;
case CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA:
return errSecDuplicateItem;
case CSSMERR_DL_DATABASE_CORRUPT:
return errSecInvalidKeychain;
case CSSMERR_DL_DATASTORE_DOESNOT_EXIST:
return errSecNoSuchKeychain;
case CSSMERR_DL_DATASTORE_ALREADY_EXISTS:
return errSecDuplicateKeychain;
case CSSMERR_DL_INVALID_FIELD_NAME:
return errSecNoSuchAttr;
default:
return osStatus;
}
}
}