1/*
2 * Copyright (c) 2013-2014 Apple 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#include <SecureObjectSync/SOSManifest.h>
26#include <SecureObjectSync/SOSMessage.h>
27
28#include "SOSCircle_regressions.h"
29
30#include <utilities/SecCFWrappers.h>
31#include <utilities/der_plist.h>
32#include <SecureObjectSync/SOSDigestVector.h>
33#include <securityd/SecDbItem.h>
34
35static int kTestTestCount = 68;
36
37static void testNullMessage(uint64_t msgid)
38{
39    SOSMessageRef sentMessage = NULL;
40    SOSMessageRef rcvdMessage = NULL;
41    SOSManifestRef sender = NULL;
42    CFErrorRef error = NULL;
43    CFDataRef data = NULL;
44
45    // Encode
46    ok(sender = SOSManifestCreateWithBytes(NULL, 0, &error), "empty sender manifest create: %@", error);
47    CFReleaseNull(error);
48    ok(sentMessage = SOSMessageCreateWithManifests(kCFAllocatorDefault, sender, NULL, NULL, false, &error), "sentMessage create: %@", error);
49    CFReleaseNull(error);
50    ok(data = SOSMessageCreateData(sentMessage, msgid, &error), "sentMessage data create: %@", error);
51    CFReleaseNull(error);
52
53    // Decode
54    ok(rcvdMessage = SOSMessageCreateWithData(kCFAllocatorDefault, data, &error), "rcvdMessage create: %@", error);
55    CFReleaseNull(error);
56    __block size_t numObjects = 0;
57    SOSMessageWithObjects(sentMessage, &error,  ^(CFDataRef object, bool *stop) {
58        numObjects++;
59    });
60    ok(numObjects == 0, "no objects");
61
62    // Check if we got what we started with
63    ok(sentMessage && rcvdMessage && CFEqual(sentMessage, rcvdMessage), "sent %@ == rcvd %@", sentMessage, rcvdMessage);
64
65    CFReleaseNull(data);
66    CFReleaseNull(sentMessage);
67    CFReleaseNull(rcvdMessage);
68    CFReleaseNull(sender);
69}
70
71__unused static void testFlaggedMessage(uint64_t msgid, SOSMessageFlags flags)
72{
73    SOSMessageRef sentMessage = NULL;
74    SOSMessageRef rcvdMessage = NULL;
75    SOSManifestRef sender = NULL;
76    CFErrorRef error = NULL;
77    CFDataRef data = NULL;
78
79    ok(sender = SOSManifestCreateWithBytes(NULL, 0, &error), "empty sender manifest create: %@", error);
80    CFReleaseNull(error);
81    ok(sentMessage = SOSMessageCreateWithManifests(kCFAllocatorDefault, sender, NULL, NULL, false, &error), "sentMessage create: %@", error);
82    CFReleaseNull(error);
83    SOSMessageSetFlags(sentMessage, flags);
84    ok(data = SOSMessageCreateData(sentMessage, msgid, &error), "sentMessage data create: %@", error);
85    CFReleaseNull(error);
86
87    // Decode
88    ok(rcvdMessage = SOSMessageCreateWithData(kCFAllocatorDefault, data, &error), "rcvdMessage create: %@", error);
89    CFReleaseNull(error);
90    __block size_t numObjects = 0;
91    SOSMessageWithObjects(sentMessage, &error,  ^(CFDataRef object, bool *stop) {
92        numObjects++;
93    });
94    ok(numObjects == 0, "no objects");
95
96    is(SOSMessageGetFlags(sentMessage), flags, "flags match after roundtrip");
97    ok(sentMessage && rcvdMessage && CFEqual(sentMessage, rcvdMessage), "sent %@ == rcvd %@", sentMessage, rcvdMessage);
98
99    CFReleaseNull(data);
100    CFReleaseNull(sentMessage);
101    CFReleaseNull(rcvdMessage);
102    CFReleaseNull(sender);
103}
104
105__unused static void testDeltaManifestMessage(uint64_t msgid)
106{
107    SOSMessageRef sentMessage = NULL;
108    SOSMessageRef rcvdMessage = NULL;
109    SOSManifestRef sender = NULL;
110    SOSManifestRef proposed = NULL;
111    SOSManifestRef base = NULL;
112    CFErrorRef error = NULL;
113    CFDataRef data = NULL;
114
115    struct SOSDigestVector dv = SOSDigestVectorInit;
116    SOSDigestVectorAppend(&dv, (const uint8_t *)"sha1 hash that is 20 bytes long or so and stuff");
117    SOSDigestVectorAppend(&dv, (const uint8_t *)"sha1 hash that was 23 bytes long or so and stuff");
118    SOSDigestVectorSort(&dv);
119    base = SOSManifestCreateWithBytes((const uint8_t *)dv.digest, dv.count * SOSDigestSize, &error);
120    SOSDigestVectorAppend(&dv, (const uint8_t *)"so much more is good to see here is another one for me");
121    SOSDigestVectorAppend(&dv, (const uint8_t *)"sha1 hash that was 23 bytes long or so and stuff!");
122    SOSDigestVectorAppend(&dv, (const uint8_t *)"so much for is good to see here is another one for me");
123    SOSDigestVectorSort(&dv);
124    if (msgid)
125        proposed = SOSManifestCreateWithBytes((const uint8_t *)dv.digest, dv.count * SOSDigestSize, &error);
126
127    CFReleaseNull(error);
128    ok(sentMessage = SOSMessageCreateWithManifests(kCFAllocatorDefault, proposed, base, proposed, true, &error), "sentMessage create: %@", error);
129    CFReleaseNull(error);
130    ok(data = SOSMessageCreateData(sentMessage, msgid, &error), "sentMessage data create: %@ .. %@", error, sentMessage);
131    CFReleaseNull(error);
132
133    // Decode
134    ok(rcvdMessage = SOSMessageCreateWithData(kCFAllocatorDefault, data, &error), "rcvdMessage create: %@", error);
135    CFReleaseNull(error);
136    __block size_t numObjects = 0;
137    SOSMessageWithObjects(sentMessage, &error,  ^(CFDataRef object, bool *stop) {
138        numObjects++;
139    });
140    ok(numObjects == 0, "no objects");
141
142    ok(sentMessage && rcvdMessage && CFEqual(sentMessage, rcvdMessage), "sent %@ == rcvd %@", sentMessage, rcvdMessage);
143
144    CFReleaseNull(data);
145    CFReleaseNull(sentMessage);
146    CFReleaseNull(rcvdMessage);
147    CFReleaseNull(sender);
148}
149
150static CFDataRef testCopyAddedObject(SOSMessageRef message, CFPropertyListRef plist)
151{
152    CFErrorRef error = NULL;
153    CFDataRef der;
154    ok(der = kc_plist_copy_der(plist, &error), "copy der: %@", error);
155    CFReleaseNull(error);
156    ok(SOSMessageAppendObject(message, der, &error), "likes object: %@", error);
157    CFReleaseNull(error);
158    return der;
159}
160
161__unused static void testObjectsMessage(uint64_t msgid)
162{
163    SOSMessageRef sentMessage = NULL;
164    SOSMessageRef rcvdMessage = NULL;
165    SOSManifestRef sender = NULL;
166    SOSManifestRef proposed = NULL;
167    SOSManifestRef base = NULL;
168    CFErrorRef error = NULL;
169    CFDataRef data = NULL;
170
171    struct SOSDigestVector dv1 = SOSDigestVectorInit;
172    struct SOSDigestVector dv2 = SOSDigestVectorInit;
173    SOSDigestVectorAppend(&dv1, (const uint8_t *)"sha1 hash that is 20 bytes long or so and stuff");
174    SOSDigestVectorAppend(&dv2, (const uint8_t *)"sha1 hash that was 23 bytes long or so and stuff");
175    SOSDigestVectorAppend(&dv1, (const uint8_t *)"so much more is good to see here is another one for me");
176    SOSDigestVectorAppend(&dv2, (const uint8_t *)"so much more is good to see here is another one for me");
177    SOSDigestVectorAppend(&dv1, (const uint8_t *)"sha1 hash that was 23 bytes long or so and stuff");
178    SOSDigestVectorAppend(&dv1, (const uint8_t *)"sha1 hash that was 23 bytes long or so and stuff!");
179    SOSDigestVectorAppend(&dv2, (const uint8_t *)"so much for is good to see here is another one for me");
180    SOSDigestVectorSort(&dv1);
181    SOSDigestVectorSort(&dv2);
182    base = SOSManifestCreateWithBytes((const uint8_t *)dv1.digest, dv1.count * SOSDigestSize, &error);
183    if (msgid)
184        proposed = SOSManifestCreateWithBytes((const uint8_t *)dv2.digest, dv2.count * SOSDigestSize, &error);
185    CFReleaseNull(error);
186    ok(sentMessage = SOSMessageCreateWithManifests(kCFAllocatorDefault, proposed, base, proposed, true, &error), "sentMessage create: %@", error);
187    CFDataRef O0, O1, O2, O3;
188    CFDataRef o0 = CFDataCreate(kCFAllocatorDefault, NULL, 0);
189    O0 = testCopyAddedObject(sentMessage, o0);
190    CFDataRef o1 = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)"test", 4);
191    O1 = testCopyAddedObject(sentMessage, o1);
192    CFDataRef o2 = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)"what an object", 14);
193    O2 = testCopyAddedObject(sentMessage, o2);
194    CFDataRef o3 = CFDataCreate(kCFAllocatorDefault, (const UInt8 *)"This one even has shiny stripe.", 31);
195    O3 = testCopyAddedObject(sentMessage, o3);
196    ok(data = SOSMessageCreateData(sentMessage, msgid, &error), "sentMessage data create: %@ .. %@", error, sentMessage);
197    CFReleaseNull(error);
198
199    // Decode
200    ok(rcvdMessage = SOSMessageCreateWithData(kCFAllocatorDefault, data, &error), "rcvdMessage create: %@", error);
201    CFReleaseNull(error);
202    __block size_t numObjects = 0;
203    __block bool f0, f1, f2, f3;
204    f0 = f1 = f2 = f3 = false;
205    SOSMessageWithObjects(rcvdMessage, &error,  ^(CFDataRef object, bool *stop) {
206        if (CFEqualSafe(object, O0)) f0 = true;
207        if (CFEqualSafe(object, O1)) f1 = true;
208        if (CFEqualSafe(object, O2)) f2 = true;
209        if (CFEqualSafe(object, O3)) f3 = true;
210        numObjects++;
211    });
212    ok(f0, "got O0");
213    ok(f1, "got O1");
214    ok(f2, "got O2");
215    ok(f3, "got O3");
216
217    ok(sentMessage && rcvdMessage && CFEqual(sentMessage, rcvdMessage), "sent %@ == rcvd %@", sentMessage, rcvdMessage);
218
219    CFReleaseNull(o0);
220    CFReleaseNull(o1);
221    CFReleaseNull(o2);
222    CFReleaseNull(o3);
223    CFReleaseNull(O0);
224    CFReleaseNull(O1);
225    CFReleaseNull(O2);
226    CFReleaseNull(O3);
227    CFReleaseNull(data);
228    CFReleaseNull(sentMessage);
229    CFReleaseNull(rcvdMessage);
230    CFReleaseNull(sender);
231}
232
233static void tests(void)
234{
235
236
237    testNullMessage(0); // v0
238
239#if 0
240    todo("V2 doesn't work");
241    TODO: {
242    uint64_t msgid = 0;
243    testNullMessage(++msgid); // v2
244    testFlaggedMessage(++msgid, 0x865);
245    testFlaggedMessage(++msgid, 0xdeadbeef);
246    testDeltaManifestMessage(0);
247    testDeltaManifestMessage(++msgid);
248    testObjectsMessage(0);
249    testObjectsMessage(++msgid);
250    }
251#endif
252}
253
254int sc_50_message(int argc, char *const *argv)
255{
256    plan_tests(kTestTestCount);
257
258    tests();
259
260	return 0;
261}
262