#include "testclient.h"
#include "testutils.h"
#include <Security/osxsigner.h>
using namespace CodeSigning;
void acls()
{
printf("* Basic ACL tests\n");
CssmAllocator &alloc = CssmAllocator::standard();
ClientSession ss(alloc, alloc);
StringData initialAclPassphrase("very secret");
AclEntryPrototype initialAcl;
initialAcl.TypedSubject = TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_PASSWORD,
new(alloc) ListElement(initialAclPassphrase));
AclEntryInput initialAclInput(initialAcl);
AclTester tester(ss, &initialAclInput);
AclOwnerPrototype owner;
ss.getKeyOwner(tester.keyRef, owner);
assert(owner.subject().type() == CSSM_ACL_SUBJECT_TYPE_PASSWORD);
assert(owner.subject().length() == 1);
{
uint32 count;
AclEntryInfo *acls;
ss.getKeyAcl(tester.keyRef, NULL, count, acls);
assert(count == 1);
const AclEntryInfo &acl1 = acls[0];
const TypedList &subject1 = acl1.proto().subject();
assert(subject1.type() == CSSM_ACL_SUBJECT_TYPE_PASSWORD);
assert(subject1.length() == 1);
}
tester.testWrap(&nullCred, "ACCEPTING NULL CREDENTIAL");
AutoCredentials cred(alloc);
cred += TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD,
new(alloc) ListElement(StringData("wrongo")));
tester.testWrap(&cred, "ACCEPTING WRONG PASSWORD CREDENTIAL");
cred += TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD,
new(alloc) ListElement(StringData("very secret")));
tester.testWrap(&cred);
{
detail("Changing ACL");
uint32 count;
AclEntryInfo *infos;
ss.getKeyAcl(tester.keyRef, NULL, count, infos);
assert(count == 1);
AclEntryPrototype newAcl;
TypedList subject = TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_THRESHOLD,
new(alloc) ListElement(2), new(alloc) ListElement(3));
subject += new(alloc) ListElement(TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_PASSWORD,
new(alloc) ListElement(alloc, "check me!")));
subject += new(alloc) ListElement(TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_PASSWORD,
new(alloc) ListElement(alloc, "once again!")));
subject += new(alloc) ListElement(TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_PASSWORD,
new(alloc) ListElement(alloc, "hug me!")));
newAcl.TypedSubject = subject;
AclEntryInput input(newAcl);
AclEdit edit(infos[0].handle(), input);
try {
AutoCredentials nullCred(alloc);
ss.changeKeyAcl(tester.keyRef, nullCred, edit);
error("ALLOWED ACL EDIT WITHOUT CREDENTIALS");
} catch (CssmCommonError &err) {
detail(err, "Acl Edit rejected properly");
}
ss.changeKeyAcl(tester.keyRef, cred, edit);
detail("ACL changed OK");
}
tester.testWrap(&nullCred, "ACCEPTING NULL CREDENTIALS NOW");
tester.testWrap(&cred, "ACCEPTING OLD CREDENTIALS FOR NEW ACL");
{
AutoCredentials cred(alloc);
cred += TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD,
new(alloc) ListElement(alloc, "check me!"));
tester.testWrap(&cred, "ACCEPTING LEAF SAMPLE WITHOUT THRESHOLD FRAMEWORK");
}
{
detail("Testing threshold ACLs");
AutoCredentials cred(alloc);
TypedList &threshold = cred += TypedList(alloc, CSSM_SAMPLE_TYPE_THRESHOLD,
new(alloc) ListElement(TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD,
new(alloc) ListElement(alloc, "wrongo!")))
);
tester.testWrap(&cred, "ACCEPTING ALL WRONG SAMPLES IN THRESHOLD");
threshold += new(alloc) ListElement(TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD,
new(alloc) ListElement(alloc, "hug me!")));
tester.testWrap(&cred, "ACCEPTING TOO FEW THRESHOLD SAMPLES");
threshold += new(alloc) ListElement(TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD,
new(alloc) ListElement(alloc, "check me!")));
tester.testWrap(&cred);
threshold += new(alloc) ListElement(TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD,
new(alloc) ListElement(alloc, "and this!")));
threshold += new(alloc) ListElement(TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD,
new(alloc) ListElement(alloc, "and that!")));
threshold += new(alloc) ListElement(TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD,
new(alloc) ListElement(alloc, "and more!")));
#ifdef STRICT_THRESHOLD_SUBJECTS
tester.testWrap(&cred, "ACCEPTING OVER-STUFFED THRESHOLD");
#else
tester.testWrap(&cred);
#endif //STRICT_THRESHOLD_SUBJECTS
}
{
detail("Adding Comment entry");
AclEntryPrototype newAcl;
TypedList subject = TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_COMMENT,
new(alloc) ListElement(TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_THRESHOLD,
new(alloc) ListElement(alloc, "Robby Ray!"))),
new(alloc) ListElement(666));
newAcl.TypedSubject = subject;
strcpy(newAcl.EntryTag, "vamos");
AclEntryInput input(newAcl);
AclEdit edit(input);
ss.changeKeyAcl(tester.keyRef, cred, edit);
detail("Entry added");
uint32 count;
AclEntryInfo *infos;
ss.getKeyAcl(tester.keyRef, "vamos", count, infos);
assert(count == 1); const AclEntryInfo &acl = infos[0];
const TypedList &read = acl.proto().subject();
assert(read.type() == CSSM_ACL_SUBJECT_TYPE_COMMENT);
assert(read.length() == 3);
assert(read[2] == 666);
CssmList &sublist = read[1];
assert(sublist[0] == CSSM_ACL_SUBJECT_TYPE_THRESHOLD);
assert(string(sublist[1]) == "Robby Ray!");
detail("Comment entry retrieved okay");
}
}
void authAcls()
{
printf("* ACL authorizations test\n");
CssmAllocator &alloc = CssmAllocator::standard();
ClientSession ss(alloc, alloc);
CSSM_ACL_AUTHORIZATION_TAG wrapTag = CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR;
CSSM_ACL_AUTHORIZATION_TAG encryptTag = CSSM_ACL_AUTHORIZATION_ENCRYPT;
StringData initialAclPassphrase("very secret");
StringData the2ndAclPassword("most secret");
AclEntryPrototype initialAcl;
initialAcl.TypedSubject = TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_PASSWORD,
new(alloc) ListElement(initialAclPassphrase));
initialAcl.authorization().NumberOfAuthTags = 1;
initialAcl.authorization().AuthTags = &wrapTag;
AclEntryInput initialAclInput(initialAcl);
AclTester tester(ss, &initialAclInput);
AclOwnerPrototype owner;
ss.getKeyOwner(tester.keyRef, owner);
assert(owner.subject().type() == CSSM_ACL_SUBJECT_TYPE_PASSWORD);
assert(owner.subject().length() == 1);
{
uint32 count;
AclEntryInfo *acls;
ss.getKeyAcl(tester.keyRef, NULL, count, acls);
assert(count == 1);
const AclEntryInfo &acl1 = acls[0];
const TypedList &subject1 = acl1.proto().subject();
assert(subject1.type() == CSSM_ACL_SUBJECT_TYPE_PASSWORD);
assert(subject1.length() == 1);
const AuthorizationGroup &auths = acl1.proto().authorization();
assert(auths.count() == 1);
assert(auths[0] == CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR);
}
tester.testWrap(&nullCred, "ACCEPTING NULL CREDENTIAL");
AutoCredentials cred(alloc);
cred += TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD,
new(alloc) ListElement(StringData("wrongo")));
tester.testWrap(&cred, "ACCEPTING WRONG PASSWORD CREDENTIAL");
cred += TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD,
new(alloc) ListElement(initialAclPassphrase));
tester.testWrap(&cred);
tester.testEncrypt(&nullCred, "ACCEPTING NULL CREDENTIAL FOR UNAUTHORIZED OPERATION");
tester.testEncrypt(&cred, "ACCEPTING GOOD CREDENTIAL FOR UNAUTHORIZED OPERATION");
{
detail("Adding new ACL entry");
AclEntryPrototype newAcl;
newAcl.TypedSubject = TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_PASSWORD,
new(alloc) ListElement(the2ndAclPassword));
newAcl.authorization().NumberOfAuthTags = 1;
newAcl.authorization().AuthTags = &encryptTag;
AclEntryInput newInput(newAcl);
AclEdit edit(newInput);
try {
AutoCredentials nullCred(alloc);
ss.changeKeyAcl(tester.keyRef, nullCred, edit);
error("ALLOWED ACL EDIT WITHOUT CREDENTIALS");
} catch (CssmCommonError &err) {
detail(err, "Acl Edit rejected properly");
}
ss.changeKeyAcl(tester.keyRef, cred, edit);
detail("ACL changed OK");
{
uint32 count;
AclEntryInfo *acls;
ss.getKeyAcl(tester.keyRef, NULL, count, acls);
assert(count == 2);
const AclEntryInfo &acl1 = acls[0];
const TypedList &subject1 = acl1.proto().subject();
assert(subject1.type() == CSSM_ACL_SUBJECT_TYPE_PASSWORD);
assert(subject1.length() == 1);
const AuthorizationGroup &auths1 = acl1.proto().authorization();
assert(auths1.count() == 1);
assert(auths1[0] == CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR);
const AclEntryInfo &acl2 = acls[1];
const TypedList &subject2 = acl2.proto().subject();
assert(subject2.type() == CSSM_ACL_SUBJECT_TYPE_PASSWORD);
assert(subject2.length() == 1);
const AuthorizationGroup &auths2 = acl2.proto().authorization();
assert(auths2.count() == 1);
assert(auths2[0] == CSSM_ACL_AUTHORIZATION_ENCRYPT);
}
}
AutoCredentials cred2(alloc);
cred2 += TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD,
new(alloc) ListElement(the2ndAclPassword));
tester.testWrap(&nullCred, "ACCEPTING NULL CREDENTIALS FOR WRAPPING");
tester.testEncrypt(&nullCred, "ACCEPTING NULL CREDENTIALS FOR ENCRYPTION");
tester.testWrap(&cred); tester.testEncrypt(&cred2); tester.testWrap(&cred2, "ACCEPTING ENCRYPT CRED FOR WRAPPING");
tester.testEncrypt(&cred, "ACCEPTING WRAP CRED FOR ENCRYPTING");
}
void keychainAcls()
{
printf("* Keychain (interactive) ACL test\n");
CssmAllocator &alloc = CssmAllocator::standard();
ClientSession ss(alloc, alloc);
AclEntryPrototype initialAcl;
initialAcl.TypedSubject = TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT,
new(alloc) ListElement(alloc, "Test Key"));
AclEntryInput initialAclInput(initialAcl);
AclTester tester(ss, &initialAclInput);
AclOwnerPrototype owner;
ss.getKeyOwner(tester.keyRef, owner);
assert(owner.subject().type() == CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT);
assert(owner.subject().length() == 2);
{
uint32 count;
AclEntryInfo *acls;
ss.getKeyAcl(tester.keyRef, NULL, count, acls);
assert(count == 1);
const AclEntryInfo &acl1 = acls[0];
const TypedList &subject1 = acl1.proto().subject();
assert(subject1.type() == CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT);
assert(subject1.length() == 2);
assert(static_cast<string>(subject1[1]) == "Test Key");
}
tester.testWrap(NULL, "ACCEPTING NULL CREDENTIAL");
AutoCredentials cred(alloc);
cred += TypedList(alloc, CSSM_SAMPLE_TYPE_PASSWORD,
new(alloc) ListElement(StringData("Test Key")));
tester.testWrap(&cred, "ACCEPTING PASSWORD CREDENTIAL");
cred += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_PROMPT);
tester.testWrap(&cred);
tester.testWrap(&cred);
}
void codeSigning()
{
printf("* Code Signing ACL test\n");
CssmAllocator &alloc = CssmAllocator::standard();
ClientSession ss(alloc, alloc);
OSXSigner signer;
OSXCode *main = OSXCode::main();
Signature *mySignature = signer.sign(*main);
detail("Code signature for testclient obtained");
Signature *badSignature;
{
char buffer[512];
assert(mySignature->length() <= sizeof(buffer));
memcpy(buffer, mySignature->data(), mySignature->length());
memcpy(buffer, "xyz!", 4); badSignature = signer.restore(mySignature->type(), buffer, mySignature->length());
}
AclEntryPrototype initialAcl;
initialAcl.subject() = TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE,
new(alloc) ListElement(mySignature->type()),
new(alloc) ListElement(alloc.alloc(*mySignature)));
AclEntryInput initialAclInput(initialAcl);
AclTester tester(ss, &initialAclInput);
AclOwnerPrototype owner;
ss.getKeyOwner(tester.keyRef, owner);
assert(owner.subject().type() == CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE);
assert(owner.subject().length() == 3);
tester.testWrap(&nullCred);
AclEntryPrototype badAcl;
badAcl.TypedSubject = TypedList(alloc, CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE,
new(alloc) ListElement(badSignature->type()),
new(alloc) ListElement(alloc.alloc(*badSignature)));
AclEntryInput badAclInput(badAcl);
AclTester badTester(ss, &badAclInput);
badTester.testWrap(&nullCred, "BAD CODE SIGNATURE ACCEPTED");
StringData comment("Walla Walla Washington!\nAbra cadabra.\n\n");
initialAcl.subject() += new(alloc) ListElement(alloc, comment);
AclEntryInput initialAclInputWithComment(initialAcl);
AclTester commentTester(ss, &initialAclInputWithComment);
ss.getKeyOwner(commentTester.keyRef, owner);
assert(owner.subject().type() == CSSM_ACL_SUBJECT_TYPE_CODE_SIGNATURE);
assert(owner.subject().length() == 4);
assert(owner.subject()[3] == comment);
detail("Verified comment field intact");
}