1/* 2 * Copyright (c) 2000-2001,2003-2004 Apple Computer, Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25// 26// Tester - test driver for securityserver client side. 27// 28#include "testclient.h" 29#include "testutils.h" 30#include <unistd.h> // getopt(3) 31#include <set> 32 33 34// 35// Global constants 36// 37const CssmData null; // zero pointer, zero length constant data 38const AccessCredentials nullCred; // null credentials 39 40CSSM_GUID ssguid = { 1,2,3 }; 41CssmSubserviceUid ssuid(ssguid); 42 43 44// 45// Local functions 46// 47static void usage(); 48static void runtest(char type); 49 50 51// 52// Default test set 53// 54static char testCodes[] = ".cesaAbdkKt"; 55 56 57// 58// Main program 59// 60int main(int argc, char *argv[]) 61{ 62 setbuf(stdout, NULL); 63 64 long ranseq = 0; // random stress test count 65 long ranseed = 1; // random seed for it 66 67 int arg; 68 while ((arg = getopt(argc, argv, "r:v")) != -1) { 69 switch (arg) { 70 case 'r': { 71 ranseq = atoi(optarg); 72 if (const char *colon = strchr(optarg, ':')) 73 ranseed = atoi(colon + 1); 74 else 75 ranseed = getpid() ^ time(NULL); 76 break; 77 } 78 case 'v': 79 verbose = true; 80 break; 81 default: 82 usage(); 83 } 84 } 85 if (optind < argc - 1) 86 usage(); 87 const char *sequence = argv[optind]; 88 if (sequence && !strcmp(sequence, "+")) 89 sequence = testCodes; 90 91 if (ranseq) { // repeated random (stress test) sequence 92 if (!sequence) 93 sequence = testCodes; 94 printf("*** Random stress test: %ld iterations from <%s> with seed=%ld\n", 95 ranseq, sequence, ranseed); 96 srandom(ranseed); 97 int setSize = strlen(sequence); 98 for (long n = 0; n < ranseq; n++) { 99 char type = sequence[random() % setSize]; 100 printf("\n[%ld:%c]", n, type); 101 runtest(type); 102 } 103 printf("*** Random test sequence complete.\n"); 104 exit(0); 105 } else { // single-pass selected tests sequence 106 if (!sequence) 107 sequence = "."; // default to ping test 108 for (const char *s = sequence; *s; s++) 109 runtest(*s); 110 printf("*** Test sequence complete.\n"); 111 exit(0); 112 } 113} 114 115void usage() 116{ 117 fprintf(stderr, "Usage: SSTester [-r count[:seed]] [-v] [%s|.|+]\n", 118 testCodes); 119 exit(2); 120} 121 122 123// 124// Run a single type test 125// 126void runtest(char type) 127{ 128 try { 129 debug("SStest", "Start test <%c>", type); 130 switch (type) { 131 case '.': // default 132 integrity(); 133 break; 134 case '-': 135 adhoc(); 136 break; 137 case 'a': 138 acls(); 139 break; 140 case 'A': 141 authAcls(); 142 break; 143 case 'b': 144 blobs(); 145 break; 146 case 'c': 147 codeSigning(); 148 break; 149 case 'd': 150 databases(); 151 break; 152 case 'e': 153 desEncryption(); 154 break; 155 case 'k': 156 keychainAcls(); 157 break; 158 case 'K': 159 keyBlobs(); 160 break; 161 case 's': 162 signWithRSA(); 163 break; 164 case 't': 165 authorizations(); 166 break; 167 case 'T': 168 timeouts(); 169 break; 170 default: 171 error("Invalid test selection (%c)", type); 172 } 173 printf("** Test step complete.\n"); 174 debug("SStest", "End test <%c>", type); 175 } catch (CssmCommonError &err) { 176 error(err, "Unexpected exception"); 177 } catch (...) { 178 error("Unexpected system exception"); 179 } 180} 181 182 183// 184// Basic integrity test. 185// 186void integrity() 187{ 188 ClientSession ss(CssmAllocator::standard(), CssmAllocator::standard()); 189 190 printf("* Generating random sample: "); 191 DataBuffer<11> sample; 192 ss.generateRandom(sample); 193 for (uint32 n = 0; n < sample.length(); n++) 194 printf("%.2x", ((unsigned char *)sample)[n]); 195 printf("\n"); 196} 197 198 199// 200// Database timeouts 201// @@@ Incomplete and not satisfactory 202// 203void timeouts() 204{ 205 printf("* Database timeout locks test\n"); 206 CssmAllocator &alloc = CssmAllocator::standard(); 207 ClientSession ss(alloc, alloc); 208 209 DLDbIdentifier dbId1(ssuid, "/tmp/one", NULL); 210 DLDbIdentifier dbId2(ssuid, "/tmp/two", NULL); 211 DBParameters initialParams1 = { 4, false }; // 4 seconds timeout 212 DBParameters initialParams2 = { 8, false }; // 8 seconds timeout 213 214 // credential to set keychain passphrase 215 AutoCredentials pwCred(alloc); 216 StringData password("mumbojumbo"); 217 pwCred += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_CHANGE_LOCK, 218 new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), 219 new(alloc) ListElement(password)); 220 221 DbHandle db1 = ss.createDb(dbId1, &pwCred, NULL, initialParams1); 222 DbHandle db2 = ss.createDb(dbId2, &pwCred, NULL, initialParams2); 223 detail("Databases created"); 224 225 // generate a key 226 const CssmCryptoData seed(StringData("rain tonight")); 227 FakeContext genContext(CSSM_ALGCLASS_KEYGEN, CSSM_ALGID_DES, 228 &::Context::Attr(CSSM_ATTRIBUTE_KEY_LENGTH, 64), 229 &::Context::Attr(CSSM_ATTRIBUTE_SEED, seed), 230 NULL); 231 KeyHandle key; 232 CssmKey::Header header; 233 ss.generateKey(db1, genContext, CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, 234 CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT, 235 /*cred*/NULL, NULL, key, header); 236 ss.generateKey(db2, genContext, CSSM_KEYUSE_ENCRYPT | CSSM_KEYUSE_DECRYPT, 237 CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_PERMANENT, 238 /*cred*/NULL, NULL, key, header); 239 detail("Keys generated and stored"); 240 241 // credential to provide keychain passphrase 242 AutoCredentials pwCred2(alloc); 243 pwCred += TypedList(alloc, CSSM_SAMPLE_TYPE_KEYCHAIN_LOCK, 244 new(alloc) ListElement(CSSM_SAMPLE_TYPE_PASSWORD), 245 new(alloc) ListElement(password)); 246 247 //@@@ incomplete 248 ss.releaseDb(db1); 249 ss.releaseDb(db2); 250} 251 252 253// 254// Ad-hoc test area. 255// Used for whatever is needed at the moment... 256// 257void adhoc() 258{ 259 printf("* Ad-hoc test sequence (now what does it do *this* time?)\n"); 260 261 Cssm cssm1; 262 Cssm cssm2; 263 cssm1->init(); 264 cssm2->init(); 265 266 { 267 Module m1(gGuidAppleCSP, cssm1); 268 Module m2(gGuidAppleCSP, cssm2); 269 CSP r1(m1); 270 CSP r2(m2); 271 272 Digest d1(r1, CSSM_ALGID_SHA1); 273 Digest d2(r2, CSSM_ALGID_SHA1); 274 275 StringData foo("foo de doo da blech"); 276 DataBuffer<30> digest1, digest2; 277 d1.digest(foo, digest1); 278 d2.digest(foo, digest2); 279 if (digest1 == digest2) 280 detail("Digests verify"); 281 else 282 error("Digests mismatch"); 283 } 284 285 cssm1->terminate(); 286 cssm2->terminate(); 287} 288