#include "testutils.h"
using namespace CssmClient;
bool verbose = false;
void error(const char *msg = NULL, ...)
{
if (msg) {
va_list args;
va_start(args, msg);
vfprintf(stderr, msg, args);
va_end(args);
putc('\n', stderr);
}
abort();
}
void error(const CssmCommonError &err, const char *msg = NULL, ...)
{
if (msg) {
va_list args;
va_start(args, msg);
vfprintf(stderr, msg, args);
va_end(args);
fprintf(stderr, ": %s", cssmErrorString(err.cssmError()).c_str());
putc('\n', stderr);
}
abort();
}
void detail(const char *msg = NULL, ...)
{
if (verbose) {
va_list args;
va_start(args, msg);
vfprintf(stdout, msg, args);
va_end(args);
putc('\n', stdout);
}
}
void detail(const CssmCommonError &err, const char *msg)
{
if (verbose)
printf("%s (ok): %s\n", msg, cssmErrorString(err).c_str());
}
void prompt(const char *msg)
{
if (isatty(fileno(stdin)))
printf("[%s]", msg);
}
void prompt()
{
if (isatty(fileno(stdin)))
printf(" OK\n");
}
FakeContext::FakeContext(CSSM_CONTEXT_TYPE type, CSSM_ALGORITHMS alg, uint32 count)
: Context(type, alg)
{
NumberOfAttributes = count;
ContextAttributes = new Attr[count];
}
FakeContext::FakeContext(CSSM_CONTEXT_TYPE type, CSSM_ALGORITHMS alg, ...)
: Context(type, alg)
{
va_list args;
va_start(args, alg);
uint32 count = 0;
while (va_arg(args, Attr *))
count++;
va_end(args);
NumberOfAttributes = count;
ContextAttributes = new Attr[count];
va_start(args, alg);
for (uint32 n = 0; n < count; n++)
(*this)[n] = *va_arg(args, Attr *);
va_end(args);
}
AclTester::AclTester(ClientSession &ss, const AclEntryInput *acl) : session(ss)
{
StringData keyBits("Tweedle!");
CssmKey key(keyBits);
key.header().KeyClass = CSSM_KEYCLASS_SESSION_KEY;
CssmData unwrappedData;
FakeContext unwrapContext(CSSM_ALGCLASS_SYMMETRIC, CSSM_ALGID_NONE, 0);
CssmKey::Header keyHeader;
ss.unwrapKey(noDb, unwrapContext, noKey, noKey,
key,
CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT,
CSSM_KEYATTR_EXTRACTABLE,
NULL , acl,
unwrappedData, keyRef, keyHeader);
detail("Key seeded with ACL");
}
void AclTester::testWrap(const AccessCredentials *cred, const char *howWrong)
{
FakeContext wrapContext(CSSM_ALGCLASS_SYMMETRIC, CSSM_ALGID_NONE, 0);
CssmWrappedKey wrappedKey;
try {
session.wrapKey(wrapContext, noKey, keyRef,
cred, NULL , wrappedKey);
if (howWrong) {
error("WRAP MISTAKENLY SUCCEEDED: %s", howWrong);
}
detail("extract OK");
} catch (const CssmCommonError &err) {
if (!howWrong)
error(err, "FAILED TO EXTRACT KEY");
detail(err, "extract failed OK");
}
}
void AclTester::testEncrypt(const AccessCredentials *cred, const char *howWrong)
{
CssmKey keyForm; memset(&keyForm, 0, sizeof(keyForm));
StringData iv("Aardvark");
StringData clearText("blah");
CssmData remoteCipher;
try {
if (cred) {
FakeContext cryptoContext(CSSM_ALGCLASS_SYMMETRIC, CSSM_ALGID_DES,
&::Context::Attr(CSSM_ATTRIBUTE_KEY, keyForm),
&::Context::Attr(CSSM_ATTRIBUTE_INIT_VECTOR, iv),
&::Context::Attr(CSSM_ATTRIBUTE_MODE, CSSM_ALGMODE_CBC_IV8),
&::Context::Attr(CSSM_ATTRIBUTE_PADDING, CSSM_PADDING_PKCS1),
&::Context::Attr(CSSM_ATTRIBUTE_ACCESS_CREDENTIALS, *cred),
NULL);
session.encrypt(cryptoContext, keyRef, clearText, remoteCipher);
} else {
FakeContext cryptoContext(CSSM_ALGCLASS_SYMMETRIC, CSSM_ALGID_DES,
&::Context::Attr(CSSM_ATTRIBUTE_KEY, keyForm),
&::Context::Attr(CSSM_ATTRIBUTE_INIT_VECTOR, iv),
&::Context::Attr(CSSM_ATTRIBUTE_MODE, CSSM_ALGMODE_CBC_IV8),
&::Context::Attr(CSSM_ATTRIBUTE_PADDING, CSSM_PADDING_PKCS1),
NULL);
session.encrypt(cryptoContext, keyRef, clearText, remoteCipher);
}
if (howWrong) {
error("ENCRYPT MISTAKENLY SUCCEEDED: %s", howWrong);
}
detail("encrypt OK");
} catch (CssmCommonError &err) {
if (!howWrong)
error(err, "FAILED TO ENCRYPT");
detail(err, "encrypt failed");
}
}
DbTester::DbTester(ClientSession &ss, const char *path,
const AccessCredentials *cred, int timeout, bool sleepLock)
: session(ss), dbId(ssuid, path, NULL)
{
params.idleTimeout = timeout;
params.lockOnSleep = sleepLock;
dbRef = ss.createDb(dbId, cred, NULL, params);
detail("Database %s created", path);
}
void DbTester::unlock(const char *howWrong)
{
session.lock(dbRef);
try {
session.unlock(dbRef);
if (howWrong)
error("DATABASE MISTAKENLY UNLOCKED: %s", howWrong);
} catch (CssmError &err) {
if (!howWrong)
error(err, howWrong);
detail(err, howWrong);
}
}
void DbTester::changePassphrase(const AccessCredentials *cred, const char *howWrong)
{
session.lock(dbRef);
try {
session.changePassphrase(dbRef, cred);
if (howWrong)
error("PASSPHRASE CHANGE MISTAKENLY SUCCEEDED: %s", howWrong);
} catch (CssmError &err) {
if (!howWrong)
error(err, howWrong);
detail(err, howWrong);
}
}