#include <Security/SecBasePriv.h>
#include <Security/SecKeychainPriv.h>
#include "SecBridge.h"
static CFStringRef copyErrorMessageFromBundle(OSStatus status,CFStringRef tableName);
CFStringRef
SecCopyErrorMessageString(OSStatus status, void *reserved)
{
BEGIN_SECAPI
return copyErrorMessageFromBundle(status,CFSTR("SecErrorMessages"));
END_SECAPI1(NULL)
}
void
cssmPerror(const char *how, CSSM_RETURN error)
{
BEGIN_SECAPI
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());
}
END_SECAPI0
}
const char *
cssmErrorString(CSSM_RETURN error)
{
BEGIN_SECAPI
string err;
if (CFStringRef errs = copyErrorMessageFromBundle(error, CFSTR("SecErrorMessages"))) {
err = cfString(errs);
CFRelease(errs);
}
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();
END_SECAPI1("cannot interprete 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 (secBundle)
CFRelease(secBundle);
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;
}
}
}