int tests_end(int result) { setup("tests_end"); /* Restore previous cwd and remove scratch dir. */ return (ok_unix(fchdir(current_dir), "fchdir") && ok_unix(close(current_dir), "close") && ok_unix(rmdir_recursive(scratch_dir), "rmdir_recursive")); }
void secd_test_setup_temp_keychain(const char* test_prefix, dispatch_block_t do_before_reset) { CFStringRef tmp_dir = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("/tmp/%s.%X/"), test_prefix, arc4random()); CFStringRef keychain_dir = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@Library/Keychains"), tmp_dir); CFStringPerformWithCString(keychain_dir, ^(const char *keychain_dir_string) { ok_unix(mkpath_np(keychain_dir_string, 0755), "Create temp dir %s", keychain_dir_string); });
/* Create an empty keychain file that can't be read or written and make sure securityd can deal with it. */ static void tests(void) { #ifndef NO_SERVER plan_skip_all("No testing against server."); #else const char *home_dir = getenv("HOME"); char keychain_dir[1000]; char keychain_name[1000]; sprintf(keychain_dir, "%s/Library/Keychains", home_dir); sprintf(keychain_name, "%s/keychain-2-debug.db", keychain_dir); ensureKeychainExists(); int fd; ok_unix(fd = open(keychain_name, O_RDWR | O_CREAT | O_TRUNC, 0644), "create keychain file '%s'", keychain_name); ok_unix(fchmod(fd, 0), " keychain file '%s'", keychain_name); ok_unix(close(fd), "close keychain file '%s'", keychain_name); kc_dbhandle_reset(); int v_eighty = 80; CFNumberRef eighty = CFNumberCreate(NULL, kCFNumberSInt32Type, &v_eighty); const char *v_data = "test"; CFDataRef pwdata = CFDataCreate(NULL, (UInt8 *)v_data, strlen(v_data)); CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); CFDictionaryAddValue(query, kSecClass, kSecClassInternetPassword); CFDictionaryAddValue(query, kSecAttrServer, CFSTR("members.spamcop.net")); CFDictionaryAddValue(query, kSecAttrAccount, CFSTR("smith")); CFDictionaryAddValue(query, kSecAttrPort, eighty); CFDictionaryAddValue(query, kSecAttrProtocol, kSecAttrProtocolHTTP); CFDictionaryAddValue(query, kSecAttrAuthenticationType, kSecAttrAuthenticationTypeDefault); CFDictionaryAddValue(query, kSecValueData, pwdata); ok_status(SecItemAdd(query, NULL), "add internet password"); is_status(SecItemAdd(query, NULL), errSecDuplicateItem, "add internet password again"); ok_status(SecItemCopyMatching(query, NULL), "Found the item we added"); ok_status(SecItemDelete(query),"Deleted the item we added"); CFReleaseSafe(eighty); CFReleaseSafe(pwdata); CFReleaseSafe(query); #endif }
static int tests_end(void) { #ifdef NO_SERVER setup("tests_end"); /* Restore previous cwd and remove scratch dir. */ int ok = ok_unix(fchdir(current_dir), "fchdir"); if (ok) ok = ok_unix(close(current_dir), "close"); if (ok) { if (!keep_scratch_dir) { ok = ok_unix(rmdir_recursive(scratch_dir), "rmdir_recursive"); } } return ok; #else return 0; #endif }
static int tests_init(void) { int ok = 0; #ifdef NO_SERVER char preferences_dir[80]; char library_dir[70]; setup("tests_init"); /* Create scratch dir for tests to run in. */ sprintf(scratch_dir, "/tmp/tst-%d", getpid()); if (keep_scratch_dir) { printf("running tests with HOME=%s\n", scratch_dir); } sprintf(library_dir, "%s/Library", scratch_dir); sprintf(preferences_dir, "%s/Preferences", library_dir); ok = (ok_unix(mkdir(scratch_dir, 0755), "mkdir") && ok_unix(current_dir = open(".", O_RDONLY), "open") && ok_unix(chdir(scratch_dir), "chdir") && ok_unix(setenv("HOME", scratch_dir, 1), "setenv") && /* @@@ Work around a bug that the prefs code in libsecurity_keychain never creates the Library/Preferences dir. */ ok_unix(mkdir(library_dir, 0755), "mkdir") && ok_unix(mkdir(preferences_dir, 0755), "mkdir") && ok(home_var = getenv("HOME"), "getenv")); if (ok > 0) securityd_init(scratch_dir); #endif return ok; }
int tests_begin(int argc, char * const *argv) { char library_dir[70]; char preferences_dir[80]; setup("tests_begin"); /* Create scratch dir for tests to run in. */ sprintf(scratch_dir, "/tmp/tst-%d", getpid()); sprintf(library_dir, "%s/Library", scratch_dir); sprintf(preferences_dir, "%s/Preferences", library_dir); return (ok_unix(mkdir(scratch_dir, 0755), "mkdir") && ok_unix(current_dir = open(".", O_RDONLY), "open") && ok_unix(chdir(scratch_dir), "chdir") && ok_unix(setenv("HOME", scratch_dir, 1), "setenv") && /* @@@ Work around a bug that the prefs code in libsecurity_keychain never creates the Library/Preferences dir. */ ok_unix(mkdir(library_dir, 0755), "mkdir") && ok_unix(mkdir(preferences_dir, 0755), "mkdir") && ok_unix(home_var = getenv("HOME"), "getenv")); }
int test_leaks(void) { return 0; #if 0 int leaks = 0; pid_t child; pid_t parent; setup("leaks"); /* Work around the fact that CF calls setenv, which leaks. */ cf_user_text_encoding_var = getenv("__CF_USER_TEXT_ENCODING"); ok_unix(parent = getpid(), "getpid"); int cld_stdout[2] = {}; ok_unix(child = pipe(cld_stdout), "pipe"); ok_unix(child = fork(), "fork"); switch (child) { case -1: break; case 0: { /* child. */ /* Set childs stdout and stderr to pipe. */ ok_unix(close(cld_stdout[0]), "close parent end of pipe"); ok_unix(dup2(cld_stdout[1], 1), "reopen stdout on pipe"); #if 0 ok_unix(dup2(cld_stdout[1], 2), "reopen stderr on pipe"); #endif int argc = 0; char *const *argv = NULL; char **argvec = (char **)malloc((argc + 2) * sizeof(char *)); char pidstr[8]; int ix; sprintf(pidstr, "%d", parent); argvec[0] = "/usr/bin/leaks"; for (ix = 1; ix < argc; ++ix) argvec[ix] = argv[ix]; argvec[ix] = pidstr; argvec[ix + 1] = NULL; ok_unix(execv(argvec[0], argvec), "execv"); _exit(1); break; } default: { /* Parent. */ ok_unix(close(cld_stdout[1]), "close child end of pipe"); /* Set statemachine initial state to 0. */ int state = 0; /* True iff the last char read was a newline. */ int newline = 1; char buf[4098]; for (;;) { char *p = buf + 2; ssize_t bytes_read; bytes_read = read(cld_stdout[0], p, 4096); if (bytes_read <= 0) break; int start = newline ? -2 : 0; int ix = 0; for (ix = 0; ix < bytes_read; ++ix) { /* Simple state machine for parsing leaks output. * Looks for * '[^\n]*\n[^:]*: ([0-9]*)' * and sets leaks to atoi of the ([0-9]*) bit. */ switch (state) { case 0: if (p[ix] == '\n') state = 1; break; case 1: if (p[ix] == ':') state = 2; break; case 2: if (p[ix] == ' ') state = 3; break; case 3: if (p[ix] <= '0' || p[ix] >='9') state = 4; else leaks = leaks * 10 + p[ix] - '0'; break; case 4: break; } /* If there is a newline in the input or we are looking at the last char of the buffer it's time to write the output. */ if (p[ix] == '\n' || ix + 1 >= bytes_read) { /* If the previous char was a newline we prefix the output with "# ". */ if (newline) { p[start] = '#'; p[start + 1] = ' '; } fwrite(p + start, ix + 1 - start, 1, stdout); if (p[ix] == '\n') { start = ix - 1; newline = 1; } else newline = 0; } } } int status = 0; for (;;) { /* Wait for the child to exit. */ pid_t waited_pid = waitpid(child, &status, 0); if (waited_pid == -1) { int error = errno; /* Keep going if we get interupted but bail out on any other error. */ if (error == EINTR) continue; ok_unix(waited_pid, "waitpid"); break; } if (WIFEXITED(status)) { is(WEXITSTATUS(status), 0, "leaks exit status"); break; } else if (WIFSIGNALED(status)) { is(WTERMSIG(status), 0, "leaks terminated by"); break; } } break; } } return leaks; #endif }
static void tests(void) { char *home = getenv("HOME"); char kcname1[256], kcname2[256]; SecKeychainStatus status1, status2; if (!home || strlen(home) > 200) plan_skip_all("home too big"); sprintf(kcname1, "%s/kctests/kc1/kc1", home); SecKeychainRef kc1 = NULL, kc2 = NULL; kc1 = createNewKeychainAt(kcname1, "test"); ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); is(status1, kSecUnlockStateStatus|kSecReadPermStatus|kSecWritePermStatus, "status unlocked readable writable"); ok_status(SecKeychainLock(kc1), "SecKeychainLock kc1"); ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); TODO: { todo("<rdar://problem/2668794> KeychainImpl::status() returns " "incorrect status (always writable?)"); is(status1, kSecReadPermStatus|kSecWritePermStatus, "status (locked) readable writable"); } /* Make keychain non writable. */ char kcdir1[256]; sprintf(kcdir1, "%s/kctests/kc1", home); ok_unix(chmod(kcdir1, 0555), "chmod kcdir1 0555"); ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); is(status1, kSecReadPermStatus, "status (locked) readable"); ok_status(SecKeychainUnlock(kc1, 4, "test", TRUE), "SecKeychainLock kc1"); ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); TODO: { todo("<rdar://problem/2668794> KeychainImpl::status() returns " "incorrect status (always writable?)"); is(status1, kSecUnlockStateStatus|kSecReadPermStatus, "status unlocked readable"); } /* Reopen the keychain. */ CFRelease(kc1); ok_status(SecKeychainOpen(kcname1, &kc1), "SecKeychainOpen kc1"); ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); TODO: { todo("<rdar://problem/2668794> KeychainImpl::status() returns " "incorrect status (always writable?)"); is(status1, kSecUnlockStateStatus|kSecReadPermStatus, "status unlocked readable"); } sprintf(kcname2, "%s/kctests/kc2/kc2", home); kc2 = createNewKeychainAt(kcname2, "test"); ok_unix(chmod(kcname2, 0444), "chmod kc2 0444"); ok_status(SecKeychainGetStatus(kc2, &status2), "get kc2 status"); is(status2, kSecUnlockStateStatus|kSecReadPermStatus|kSecWritePermStatus, "status unlocked readable writable"); /* Reopen the keychain. */ CFRelease(kc2); ok_status(SecKeychainOpen(kcname2, &kc2), "SecKeychainOpen kc2"); ok_status(SecKeychainGetStatus(kc2, &status2), "get kc2 status"); is(status2, kSecUnlockStateStatus|kSecReadPermStatus|kSecWritePermStatus, "status unlocked readable writable"); /* Restore dir to writable so cleanup code will work ok. */ ok_unix(chmod(kcdir1, 0755), "chmod kcdir1 0755"); ok_status(SecKeychainDelete(kc1), "%s: SecKeychainDelete", testName); CFRelease(kc1); ok_status(SecKeychainDelete(kc2), "%s: SecKeychainDelete", testName); CFRelease(kc2); bool testWithFreshlyCreatedKeychain = true; SecKeychainRef keychain = createNewKeychain("test", "test"); ok_status(SecKeychainLock(keychain), "SecKeychainLock"); do { SecKeychainStatus keychainStatus = 0; is_status(SecKeychainUnlock(keychain, 0, NULL, true), -25293, "SecKeychainUnlock with NULL password (incorrect)"); ok_status(SecKeychainGetStatus(keychain, &keychainStatus), "SecKeychainGetStatus"); is( (keychainStatus & kSecUnlockStateStatus), 0, "Check it's not unlocked"); keychainStatus = 0; ok_status(SecKeychainUnlock(keychain, strlen("test"), "test", true), "SecKeychainUnlock with correct password"); ok_status(SecKeychainGetStatus(keychain, &keychainStatus), "SecKeychainGetStatus"); is( (keychainStatus & kSecUnlockStateStatus), kSecUnlockStateStatus, "Check it's unlocked"); ok_status(SecKeychainLock(keychain), "SecKeychainLock"); if (testWithFreshlyCreatedKeychain) { CFRelease(keychain); testWithFreshlyCreatedKeychain = false; ok_status(SecKeychainOpen("test", &keychain), "SecKeychainOpen"); } else { testWithFreshlyCreatedKeychain = true; ok_status(SecKeychainDelete(keychain), "%s: SecKeychainDelete", testName); CFReleaseNull(keychain); } } while(!testWithFreshlyCreatedKeychain); }