/* * Copyright (c) 2011 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Portions Copyright (c) 2011 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of KTH nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include static void run_tests(void) { dispatch_queue_t q = dispatch_queue_create("test_gsscf", NULL); dispatch_semaphore_t sema = dispatch_semaphore_create(0); CFErrorRef error = NULL; printf("[TEST] add\n"); CFMutableDictionaryRef attrs = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionaryAddValue(attrs, kGSSAttrClass, kGSSAttrClassKerberos); CFDictionaryAddValue(attrs, kGSSAttrNameType, kGSSAttrNameTypeGSSUsername); CFDictionaryAddValue(attrs, kGSSAttrName, CFSTR("ktestuser@ADS.APPLE.COM")); GSSItemRef item = GSSItemAdd(attrs, NULL); if (item == NULL) { printf("[FAIL] failed to add\n"); } else { CFShow(item); CFRelease(item); } CFArrayRef items = GSSItemCopyMatching(attrs, &error); if (items == NULL) { printf("[FAIL] failed to find what was just added\n"); exit(1); } CFIndex n, count = CFArrayGetCount(items); for (n = 0; n < count; n++) { item = (GSSItemRef)CFArrayGetValueAtIndex(items, n); CFMutableDictionaryRef opts = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionaryAddValue(opts, kGSSAttrCredentialPassword, CFSTR("foobar")); GSSItemOperation(item, kGSSOperationAcquire, opts, q, ^(CFTypeRef type, CFErrorRef e) { if (type) { CFShow(CFSTR("Managed to acquire credential\n")); CFShow(type); } if (e) CFShow(e); dispatch_semaphore_signal(sema); }); dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); CFRelease(opts); } CFRelease(items); items = GSSItemCopyMatching(attrs, NULL); if (items) { count = CFArrayGetCount(items); for (n = 0; n < count; n++) { printf("index: %lu\n", n); item = (GSSItemRef)CFArrayGetValueAtIndex(items, n); CFShow(item); GSSItemOperation(item, kGSSOperationCredentialDiagnostics, NULL, q, ^(CFTypeRef type, CFErrorRef e) { if (type && CFGetTypeID(type) == CFDataGetTypeID()) printf("diag: \n%.*s\n", (int)CFDataGetLength(type), CFDataGetBytePtr(type)); dispatch_semaphore_signal(sema); }); dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); } CFRelease(items); } printf("[PASS] add\n"); /* delete */ printf("[TEST] delete\n"); if (!GSSItemDelete(attrs, NULL)) { printf("failed to delete\n"); exit(1); } printf("[PASS] delete\n"); /* * Try with password in keychain */ printf("[TEST] keychain\n"); CFDictionaryAddValue(attrs, kGSSAttrCredentialPassword, CFSTR("foobar")); item = GSSItemAdd(attrs, NULL); if (item == NULL) { printf("failed to add\n"); exit(1); } GSSItemOperation(item, kGSSOperationAcquire, NULL, q, ^(CFTypeRef type, CFErrorRef e) { if (type) { CFShow(CFSTR("Managed to acquire credential\n")); CFShow(type); } else { CFShow(CFSTR("failed to acquire credential\n")); exit(1); } if (e) CFShow(e); dispatch_semaphore_signal(sema); }); dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); CFRelease(item); printf("[PASS] keychain\n"); /* * */ printf("[TEST] delete2\n"); if (!GSSItemDelete(attrs, NULL)) { printf("failed to delete (second try)\n"); exit(1); } printf("[PASS] delete2\n"); /* * */ CFRelease(attrs); printf("[TEST] keychain2\n"); /* * Test entries in keychain */ attrs = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionaryAddValue(attrs, kGSSAttrClass, kGSSAttrClassKerberos); CFDictionaryAddValue(attrs, kGSSAttrNameType, kGSSAttrNameTypeGSSUsername); CFDictionaryAddValue(attrs, kGSSAttrName, CFSTR("lha@SU.SE")); item = GSSItemAdd(attrs, NULL); if (item == NULL) { printf("failed to add lha@SU.SE\n"); } else { CFShow(item); CFRelease(item); } items = GSSItemCopyMatching(attrs, &error); if (items == NULL) { printf("[FAIL] failed to find lha@SU.SE\n"); exit(1); } if (items) { count = CFArrayGetCount(items); for (n = 0; n < count; n++) { printf("index: %lu\n", n); item = (GSSItemRef)CFArrayGetValueAtIndex(items, n); CFShow(item); GSSItemOperation(item, kGSSOperationAcquire, NULL, q, ^(CFTypeRef type, CFErrorRef e) { if (type) { CFShow(CFSTR("Managed to acquire credential\n")); CFShow(type); } if (e) CFShow(e); dispatch_semaphore_signal(sema); }); dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); } CFRelease(items); } printf("[PASS] keychain2\n"); printf("[TEST] delete3\n"); if (!GSSItemDelete(attrs, NULL)) { printf("[FAIL] failed to delete (third try)\n"); exit(1); } printf("[PASS] delete3\n"); CFRelease(attrs); dispatch_release(sema); } static void change_password(const char *user, const char *oldpassword, const char *newpassword) { CFStringRef u = CFStringCreateWithCString(kCFAllocatorDefault, user, kCFStringEncodingUTF8); CFStringRef oldpw = CFStringCreateWithCString(kCFAllocatorDefault, oldpassword, kCFStringEncodingUTF8); CFStringRef newpw = CFStringCreateWithCString(kCFAllocatorDefault, newpassword, kCFStringEncodingUTF8); dispatch_queue_t q = dispatch_queue_create("test_gsscf-cpw", NULL); dispatch_semaphore_t sema = dispatch_semaphore_create(0); CFErrorRef error = NULL; CFMutableDictionaryRef attrs = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionaryAddValue(attrs, kGSSAttrClass, kGSSAttrClassKerberos); CFDictionaryAddValue(attrs, kGSSAttrNameType, kGSSAttrNameTypeGSSUsername); CFDictionaryAddValue(attrs, kGSSAttrName, u); printf("foo\n"); GSSItemRef item = GSSItemAdd(attrs, NULL); if (item == NULL) { printf("[FAIL] failed to add\n"); } else { CFShow(item); CFRelease(item); } CFArrayRef items = GSSItemCopyMatching(attrs, &error); if (items == NULL) { printf("failed to find what was just added\n"); exit(1); } CFIndex n, count = CFArrayGetCount(items); for (n = 0; n < count; n++) { item = (GSSItemRef)CFArrayGetValueAtIndex(items, n); CFShow(item); CFMutableDictionaryRef opts = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionaryAddValue(opts, kGSSOperationChangePasswordOldPassword, oldpw); CFDictionaryAddValue(opts, kGSSOperationChangePasswordNewPassword, newpw); GSSItemOperation(item, kGSSOperationChangePassword, opts, q, ^(CFTypeRef type, CFErrorRef e) { if (e == NULL) { CFShow(CFSTR("Managed to change password\n")); } else { CFShow(CFSTR("Failed to change password\n")); CFShow(e); } dispatch_semaphore_signal(sema); }); dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); CFRelease(opts); } CFRelease(items); CFRelease(attrs); CFRelease(u); CFRelease(newpw); CFRelease(oldpw); } static void checkRules(void) { CFMutableDictionaryRef rules; CFStringRef match; rules = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (rules == NULL) { printf("[FAIL] ENOMEM\n"); exit(1); } CFStringRef hostrule = CFSTR("hostrule"); CFStringRef domainrule = CFSTR("domainrule"); CFStringRef domainrule2 = CFSTR("domainrule2"); GSSRuleAddMatch(rules, CFSTR("https://host.apple.com"), hostrule); GSSRuleAddMatch(rules, CFSTR("https://.apple.com"), domainrule); GSSRuleAddMatch(rules, CFSTR("https://host.icloud.com/"), hostrule); GSSRuleAddMatch(rules, CFSTR("https://.icloud.com/"), domainrule); GSSRuleAddMatch(rules, CFSTR("https://.icloud.com/foo/"), domainrule2); printf("[TEST] hostrule\n"); match = GSSRuleGetMatch(rules, CFSTR("https://HOST.apple.com")); if (match == NULL || CFStringCompare(match, hostrule, 0) != kCFCompareEqualTo) { printf("[FAIL] hostrule\n"); exit(1); } printf("[PASS] hostrule\n"); printf("[TEST] hostrule2\n"); match = GSSRuleGetMatch(rules, CFSTR("https://host.apple.com")); if (match == NULL || CFStringCompare(match, hostrule, 0) != kCFCompareEqualTo) { printf("[FAIL] hostrule2\n"); exit(1); } printf("[PASS] hostrule2\n"); printf("[TEST] domainrule\n"); match = GSSRuleGetMatch(rules, CFSTR("https://host2.apple.com/")); if (match == NULL || CFStringCompare(match, domainrule, 0) != kCFCompareEqualTo) { printf("[FAIL] domainrule\n"); exit(1); } printf("[PASS] domainrule\n"); printf("[TEST] hostrule3\n"); match = GSSRuleGetMatch(rules, CFSTR("https://HOST.icloud.com")); if (match == NULL || CFStringCompare(match, hostrule, 0) != kCFCompareEqualTo) { printf("[FAIL] hostrule3\n"); exit(1); } printf("[PASS] hostrule3\n"); printf("[TEST] hostrule4\n"); match = GSSRuleGetMatch(rules, CFSTR("https://host.icloud.com")); if (match == NULL || CFStringCompare(match, hostrule, 0) != kCFCompareEqualTo) { printf("[FAIL] hostrule4\n"); exit(1); } printf("[PASS] hostrule4\n"); printf("[TEST] domainrule2\n"); match = GSSRuleGetMatch(rules, CFSTR("https://host2.icloud.com")); if (match == NULL || CFStringCompare(match, domainrule, 0) != kCFCompareEqualTo) { printf("[FAIL] domainrule2\n"); exit(1); } printf("[PASS] domainrule2\n"); printf("[TEST] domainrule3\n"); match = GSSRuleGetMatch(rules, CFSTR("https://host2.icloud.com/foo/")); if (match == NULL || CFStringCompare(match, domainrule2, 0) != kCFCompareEqualTo) { printf("[FAIL] domainrule3\n"); exit(1); } printf("[PASS] domainrule2\n"); printf("[TEST] domainrule3\n"); match = GSSRuleGetMatch(rules, CFSTR("https://host2.icloud.com/foo")); if (match == NULL || CFStringCompare(match, domainrule, 0) != kCFCompareEqualTo) { printf("[FAIL] domainrule3\n"); exit(1); } printf("[PASS] domainrule3\n"); printf("[TEST] domainrule4\n"); match = GSSRuleGetMatch(rules, CFSTR("https://host2.icloud.com/bar/")); if (match == NULL || CFStringCompare(match, domainrule, 0) != kCFCompareEqualTo) { printf("[FAIL] domainrule4\n"); exit(1); } printf("[PASS] domainrule4\n"); printf("[TEST] no match\n"); match = GSSRuleGetMatch(rules, CFSTR("host.h5l.org")); if (match != NULL) { printf("[FAIL] no match"); exit(1); } printf("[PASS] no match\n"); CFRelease(rules); } int main(int argc, char **argv) { if (argc > 3) change_password(argv[1], argv[2], argv[3]); else { run_tests(); checkRules(); } return 0; }