1//
2//  si-76-shared-credentials.c
3//  sec
4//
5
6
7#include <CoreFoundation/CoreFoundation.h>
8#include <Security/SecBasePriv.h>
9#include <Security/SecCertificate.h>
10#include <Security/SecCertificatePriv.h>
11#include <Security/SecCertificateInternal.h>
12#include <Security/SecItem.h>
13#include <Security/SecItemPriv.h>
14#include <Security/SecIdentityPriv.h>
15#include <Security/SecIdentity.h>
16#include <Security/SecPolicy.h>
17#include <Security/SecPolicyPriv.h>
18#include <Security/SecPolicyInternal.h>
19#include <Security/SecSharedCredential.h>
20#include <Security/SecCMS.h>
21#include <utilities/SecCFWrappers.h>
22#include <stdlib.h>
23#include <unistd.h>
24
25#include "Security_regressions.h"
26
27#define WAIT_WHILE(X) { while ((X)) { (void)CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.1, TRUE); } }
28
29static bool expected_failure(OSStatus status)
30{
31    return ((status == errSecMissingEntitlement) ||
32            (status == errSecBadReq));
33}
34
35static void tests(void)
36{
37    // look up our entry for localhost
38    CFStringRef acct1 = CFSTR("local");
39    CFStringRef acct2 = CFSTR("admin");
40    CFStringRef fqdn = CFSTR("localhost");
41    CFStringRef not_my_fqdn = CFSTR("store.apple.com"); // something we aren't entitled to share
42    __block bool adding;
43    __block bool requesting;
44    __block bool deleting;
45
46//  UInt8 buf[6] = { 'l', 'o', 'c', 'a', 'l', '\0' };
47//  CFDataRef cred = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)&buf, sizeof(buf));
48    CFStringRef cred = CFStringCreateCopy(kCFAllocatorDefault, CFSTR("local"));
49
50    // should get denied if we request a fqdn which is not in our entitlement
51    requesting = true;
52    SecRequestSharedWebCredential(not_my_fqdn, NULL, ^void (CFArrayRef credentials, CFErrorRef error) {
53        OSStatus status = (OSStatus)((error) ? CFErrorGetCode(error) : errSecSuccess);
54        is(status == errSecItemNotFound || expected_failure(status), true, "fqdn not entitled");
55        is(CFArrayGetCount(credentials) > 0, false, "returned credential array == 0");
56        requesting = false;
57    });
58    WAIT_WHILE(requesting);
59
60    // add (or update) credentials for two different accounts on the same server
61    adding = true;
62    SecAddSharedWebCredential(fqdn, acct1, cred, ^void (CFErrorRef error) {
63        OSStatus status = (OSStatus)((error) ? CFErrorGetCode(error) : errSecSuccess);
64        // TODO: need a proper teamID-enabled application identifier to succeed; expect auth failure
65        if (status == errSecAuthFailed || expected_failure(status)) { status = errSecSuccess; }
66        ok_status(status);
67        adding = false;
68    });
69    WAIT_WHILE(adding);
70
71    adding = true;
72    SecAddSharedWebCredential(fqdn, acct2, cred, ^void (CFErrorRef error) {
73        OSStatus status = (OSStatus)((error) ? CFErrorGetCode(error) : errSecSuccess);
74        // TODO: need a proper teamID-enabled application identifier to succeed; expect auth failure
75        if (status == errSecAuthFailed || expected_failure(status)) { status = errSecSuccess; }
76        ok_status(status);
77        adding = false;
78    });
79    WAIT_WHILE(adding);
80
81    // look up credential with specific account
82    requesting = true;
83    SecRequestSharedWebCredential(fqdn, acct1, ^void (CFArrayRef credentials, CFErrorRef error) {
84        OSStatus status = (OSStatus)((error) ? CFErrorGetCode(error) : errSecSuccess);
85        // TODO: need a proper teamID-enabled application identifier to succeed; expect no items
86        bool notFound = false;
87        if (status == errSecItemNotFound || expected_failure(status)) {
88            status = errSecSuccess; notFound = true;
89        }
90        ok_status(status);
91
92        // should find only one credential if a specific account is provided
93        CFIndex credentialCount = CFArrayGetCount(credentials);
94        // TODO: need a proper teamID-enabled application identifier to succeed; expect 0 items
95        if (credentialCount == 0 && notFound) { credentialCount = 1; }
96        is(credentialCount == 1, true, "returned credentials == 1");
97        requesting = false;
98    });
99    WAIT_WHILE(requesting);
100
101    // look up credential with NULL account parameter
102    requesting = true;
103    SecRequestSharedWebCredential(fqdn, NULL, ^void (CFArrayRef credentials, CFErrorRef error) {
104        OSStatus status = (OSStatus)((error) ? CFErrorGetCode(error) : errSecSuccess);
105        // TODO: need a proper teamID-enabled application identifier to succeed; expect auth failure
106        bool notFound = false;
107        if (status == errSecItemNotFound || expected_failure(status)) {
108            status = errSecSuccess; notFound = true;
109        }
110        ok_status(status);
111
112        // should find only one credential if no account is provided
113        // (since UI dialog only permits one credential to be selected)
114        CFIndex credentialCount = CFArrayGetCount(credentials);
115        // TODO: need a proper teamID-enabled application identifier to succeed
116        if (credentialCount == 0 && notFound) { credentialCount = 1; }
117        is(credentialCount == 1, true, "returned credentials == 1");
118        requesting = false;
119    });
120    WAIT_WHILE(requesting);
121
122    // pass NULL to delete our credentials
123    deleting = true;
124    SecAddSharedWebCredential(fqdn, acct1, NULL, ^void (CFErrorRef error) {
125        OSStatus status = (OSStatus)((error) ? CFErrorGetCode(error) : errSecSuccess);
126        // TODO: need a proper teamID-enabled application identifier to succeed; expect auth failure
127        if (status == errSecAuthFailed || expected_failure(status)) { status = errSecSuccess; }
128        ok_status(status);
129        deleting = false;
130    });
131    WAIT_WHILE(deleting);
132
133    deleting = true;
134    SecAddSharedWebCredential(fqdn, acct2, NULL, ^void (CFErrorRef error) {
135        OSStatus status = (OSStatus)((error) ? CFErrorGetCode(error) : errSecSuccess);
136        // TODO: need a proper teamID-enabled application identifier to succeed; expect auth failure
137        if (status == errSecAuthFailed || expected_failure(status)) { status = errSecSuccess; }
138        ok_status(status);
139        deleting = false;
140    });
141    WAIT_WHILE(deleting);
142
143    // look up credentials again; should find nothing this time
144    requesting = true;
145    SecRequestSharedWebCredential(fqdn, NULL, ^void (CFArrayRef credentials, CFErrorRef error) {
146        OSStatus status = (OSStatus)((error) ? CFErrorGetCode(error) : errSecSuccess);
147        // TODO: need a proper teamID-enabled application identifier to succeed; expect auth failure
148        if (status == errSecAuthFailed || expected_failure(status)) { status = errSecItemNotFound; }
149        is_status(status, errSecItemNotFound);
150        is(CFArrayGetCount(credentials) > 0, false, "returned credential array == 0");
151        requesting = false;
152    });
153    WAIT_WHILE(requesting);
154
155    CFRelease(cred);
156}
157
158int si_76_shared_credentials(int argc, char *const *argv)
159{
160		plan_tests(12);
161		tests();
162		return 0;
163}
164