#include "testclient.h"
#include "testutils.h"
#include <unistd.h> // getopt(3)
#include <set>
const CssmData null; const AccessCredentials nullCred;
CSSM_GUID ssguid = { 1,2,3 };
CssmSubserviceUid ssuid(ssguid);
static void usage();
static void runtest(char type);
static char testCodes[] = ".cesaAbdkKt";
int main(int argc, char *argv[])
{
setbuf(stdout, NULL);
long ranseq = 0; long ranseed = 1;
int arg;
while ((arg = getopt(argc, argv, "r:v")) != -1) {
switch (arg) {
case 'r': {
ranseq = atoi(optarg);
if (const char *colon = strchr(optarg, ':'))
ranseed = atoi(colon + 1);
else
ranseed = getpid() ^ time(NULL);
break;
}
case 'v':
verbose = true;
break;
default:
usage();
}
}
if (optind < argc - 1)
usage();
const char *sequence = argv[optind];
if (sequence && !strcmp(sequence, "+"))
sequence = testCodes;
if (ranseq) { if (!sequence)
sequence = testCodes;
printf("*** Random stress test: %ld iterations from <%s> with seed=%ld\n",
ranseq, sequence, ranseed);
srandom(ranseed);
int setSize = strlen(sequence);
for (long n = 0; n < ranseq; n++) {
char type = sequence[random() % setSize];
printf("\n[%ld:%c]", n, type);
runtest(type);
}
printf("*** Random test sequence complete.\n");
exit(0);
} else { if (!sequence)
sequence = "."; for (const char *s = sequence; *s; s++)
runtest(*s);
printf("*** Test sequence complete.\n");
exit(0);
}
}
void usage()
{
fprintf(stderr, "Usage: SSTester [-r count[:seed]] [-v] [%s|.|+]\n",
testCodes);
exit(2);
}
void runtest(char type)
{
try {
debug("SStest", "Start test <%c>", type);
switch (type) {
case '.': integrity();
break;
case '-':
adhoc();
break;
case 'a':
acls();
break;
case 'A':
authAcls();
break;
case 'b':
blobs();
break;
case 'c':
codeSigning();
break;
case 'd':
databases();
break;
case 'e':
desEncryption();
break;
case 'k':
keychainAcls();
break;
case 'K':
keyBlobs();
break;
case 's':
signWithRSA();
break;
case 't':
authorizations();
break;
case 'T':
timeouts();
break;
default:
error("Invalid test selection (%c)", type);
}
printf("** Test step complete.\n");
debug("SStest", "End test <%c>", type);
} catch (CssmCommonError &err) {
error(err, "Unexpected exception");
} catch (...) {
error("Unexpected system exception");
}
}
void integrity()
{
ClientSession ss(CssmAllocator::standard(), CssmAllocator::standard());
printf("* Generating random sample: ");
DataBuffer<11> sample;
ss.generateRandom(sample);
for (uint32 n = 0; n < sample.length(); n++)
printf("%.2x", ((unsigned char *)sample)[n]);
printf("\n");
}
void timeouts()
{
printf("* Database timeout locks test\n");
CssmAllocator &alloc = CssmAllocator::standard();
ClientSession ss(alloc, alloc);
DLDbIdentifier dbId1(ssuid, "/tmp/one", NULL);
DLDbIdentifier dbId2(ssuid, "/tmp/two", NULL);
DBParameters initialParams1 = { 4, false }; DBParameters initialParams2 = { 8, false };
AutoCredentials pwCred(alloc);
StringData password("mumbojumbo");
pwCred += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK,
new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD),
new(alloc) ListElement(password));
DbHandle db1 = ss.createDb(dbId1, &pwCred, NULL, initialParams1);
DbHandle db2 = ss.createDb(dbId2, &pwCred, NULL, initialParams2);
detail("Databases created");
const CssmCryptoData seed(StringData("rain tonight"));
FakeContext genContext(CSSM_ALGCLASS_KEYGEN, CSSM_ALGID_DES,
&::Context::Attr(CSSM_ATTRIBUTE_KEY_LENGTH, 64),
&::Context::Attr(CSSM_ATTRIBUTE_SEED, seed),
NULL);
KeyHandle key;
CssmKey::Header header;
ss.generateKey(db1, genContext, CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT,
CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT,
NULL, NULL, key, header);
ss.generateKey(db2, genContext, CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT,
CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT,
NULL, NULL, key, header);
detail("Keys generated and stored");
AutoCredentials pwCred2(alloc);
pwCred += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK,
new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD),
new(alloc) ListElement(password));
ss.releaseDb(db1);
ss.releaseDb(db2);
}
void adhoc()
{
printf("* Ad-hoc test sequence (now what does it do *this* time?)\n");
Cssm cssm1;
Cssm cssm2;
cssm1->init();
cssm2->init();
{
Module m1(gGuidAppleCSP, cssm1);
Module m2(gGuidAppleCSP, cssm2);
CSP r1(m1);
CSP r2(m2);
Digest d1(r1, CSSM_ALGID_SHA1);
Digest d2(r2, CSSM_ALGID_SHA1);
StringData foo("foo de doo da blech");
DataBuffer<30> digest1, digest2;
d1.digest(foo, digest1);
d2.digest(foo, digest2);
if (digest1 == digest2)
detail("Digests verify");
else
error("Digests mismatch");
}
cssm1->terminate();
cssm2->terminate();
}