Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 447 lines (356 sloc) 13.149 kB
bddbcd1 @roddi initial commit
authored
1 //
2 // validatereceipt.m
3 //
4 // Created by Ruotger Skupin on 23.10.10.
fcd6d2c @roddi cleaned up, added anlumo to copyright notice and README
authored
5 // Copyright 2010 Matthew Stevens, Ruotger Skupin, Apple, Dave Carlton, Fraser Hess, anlumo. All rights reserved.
bddbcd1 @roddi initial commit
authored
6 //
7
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
8 /*
eb16b8f @roddi added BSD-style license; tweaked build settings; corrected pointer co…
authored
9 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
10
eb16b8f @roddi added BSD-style license; tweaked build settings; corrected pointer co…
authored
11 Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
12
eb16b8f @roddi added BSD-style license; tweaked build settings; corrected pointer co…
authored
13 Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the distribution.
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
15
16 Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote products derived
eb16b8f @roddi added BSD-style license; tweaked build settings; corrected pointer co…
authored
17 from this software without specific prior written permission.
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
18
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
20 BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
21 SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
eb16b8f @roddi added BSD-style license; tweaked build settings; corrected pointer co…
authored
24 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
bddbcd1 @roddi initial commit
authored
27 #import "validatereceipt.h"
28
fcd6d2c @roddi cleaned up, added anlumo to copyright notice and README
authored
29 // link with Foundation.framework, IOKit.framework, Security.framework and libCrypto (via -lcrypto in Other Linker Flags)
bddbcd1 @roddi initial commit
authored
30
31 #import <IOKit/IOKitLib.h>
32 #import <Foundation/Foundation.h>
33
9fef320 @roddi working certificate check
authored
34 #import <Security/Security.h>
35
bddbcd1 @roddi initial commit
authored
36 #include <openssl/pkcs7.h>
37 #include <openssl/objects.h>
38 #include <openssl/sha.h>
9fef320 @roddi working certificate check
authored
39 #include <openssl/x509.h>
40 #include <openssl/err.h>
bddbcd1 @roddi initial commit
authored
41
f22472b cosmetic changes
yene authored
42 //#define USE_SAMPLE_RECEIPT // also defined in the debug build settings
9d599b3 @roddi added proto for copy_mac_address(); added warnings for when it is com…
authored
43
44 #ifdef USE_SAMPLE_RECEIPT
45 #warning ************************************
46 #warning ******* USES SAMPLE RECEIPT! *******
47 #warning ************************************
48 #endif
49
bddbcd1 @roddi initial commit
authored
50
eb16b8f @roddi added BSD-style license; tweaked build settings; corrected pointer co…
authored
51 #ifndef YES_I_HAVE_READ_THE_WARNING_AND_I_ACCEPT_THE_RISK
52
53 #warning --- DON'T USE THIS CODE AS IS! IF EVERYONE USES THE SAME CODE
54 #warning --- IT IS PRETTY EASY TO BUILD AN AUTOMATIC CRACKING TOOL
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
55 #warning --- FOR APPS USING THIS CODE!
56 #warning --- BY USING THIS CODE YOU ACCEPT TAKING THE RESPONSIBILITY FOR
57 #warning --- ANY DAMAGE!
58 #warning ---
eb16b8f @roddi added BSD-style license; tweaked build settings; corrected pointer co…
authored
59 #warning --- YOU HAVE BEEN WARNED!
60
61 // if you want to take that risk, add "-DYES_I_HAVE_READ_THE_WARNING_AND_I_ACCEPT_THE_RISK" in the build settings at "Other C Flags"
62
63 #endif // YES_I_HAVE_READ_THE_WARNING_AND_I_ACCEPT_THE_RISK
ec42914 @kgn Moving VRCFRelease to a better place
kgn authored
64
1051075 @kgn Adding CFRelease macro
kgn authored
65 #define VRCFRelease(object) if(object) CFRelease(object)
eb16b8f @roddi added BSD-style license; tweaked build settings; corrected pointer co…
authored
66
bddbcd1 @roddi initial commit
authored
67 NSString *kReceiptBundleIdentifer = @"BundleIdentifier";
68 NSString *kReceiptBundleIdentiferData = @"BundleIdentifierData";
69 NSString *kReceiptVersion = @"Version";
70 NSString *kReceiptOpaqueValue = @"OpaqueValue";
71 NSString *kReceiptHash = @"Hash";
72
9fef320 @roddi working certificate check
authored
73
f22472b cosmetic changes
yene authored
74 NSData * appleRootCert(void)
9fef320 @roddi working certificate check
authored
75 {
76 OSStatus status;
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
77
9fef320 @roddi working certificate check
authored
78 SecKeychainRef keychain = nil;
79 status = SecKeychainOpen("/System/Library/Keychains/SystemRootCertificates.keychain", &keychain);
1051075 @kgn Adding CFRelease macro
kgn authored
80 if(status){
81 VRCFRelease(keychain);
9fef320 @roddi working certificate check
authored
82 return nil;
83 }
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
84
9fef320 @roddi working certificate check
authored
85 CFArrayRef searchList = CFArrayCreate(kCFAllocatorDefault, (const void**)&keychain, 1, &kCFTypeArrayCallBacks);
86
864f78c @philippm Fixed reference count underflow warning
philippm authored
87 // For some reason we get a malloc reference underflow warning message when garbage collection
88 // is on. Perhaps a bug in SecKeychainOpen where the keychain reference isn't actually retained
89 // in GC?
90 #ifndef __OBJC_GC__
1051075 @kgn Adding CFRelease macro
kgn authored
91 VRCFRelease(keychain);
864f78c @philippm Fixed reference count underflow warning
philippm authored
92 #endif
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
93
9fef320 @roddi working certificate check
authored
94 SecKeychainSearchRef searchRef = nil;
95 status = SecKeychainSearchCreateFromAttributes(searchList, kSecCertificateItemClass, NULL, &searchRef);
1051075 @kgn Adding CFRelease macro
kgn authored
96 if(status){
9e9f7d6 @kgn Spaces to tabs
kgn authored
97 VRCFRelease(searchRef);
98 VRCFRelease(searchList);
9fef320 @roddi working certificate check
authored
99 return nil;
100 }
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
101
9fef320 @roddi working certificate check
authored
102 SecKeychainItemRef itemRef = nil;
103 NSData * resultData = nil;
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
104
9fef320 @roddi working certificate check
authored
105 while(SecKeychainSearchCopyNext(searchRef, &itemRef) == noErr && resultData == nil) {
106 // Grab the name of the certificate
107 SecKeychainAttributeList list;
108 SecKeychainAttribute attributes[1];
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
109
9fef320 @roddi working certificate check
authored
110 attributes[0].tag = kSecLabelItemAttr;
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
111
9fef320 @roddi working certificate check
authored
112 list.count = 1;
113 list.attr = attributes;
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
114
9fef320 @roddi working certificate check
authored
115 SecKeychainItemCopyContent(itemRef, nil, &list, nil, nil);
116 NSData *nameData = [NSData dataWithBytesNoCopy:attributes[0].data length:attributes[0].length freeWhenDone:NO];
117 NSString *name = [[NSString alloc] initWithData:nameData encoding:NSUTF8StringEncoding];
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
118
9fef320 @roddi working certificate check
authored
119 if([name isEqualToString:@"Apple Root CA"]) {
120 CSSM_DATA certData;
e615ec8 @kgn Removing un-needed release and status variable.
kgn authored
121 SecCertificateGetData((SecCertificateRef)itemRef, &certData);
9fef320 @roddi working certificate check
authored
122 resultData = [NSData dataWithBytes:certData.Data length:certData.Length];
123 SecKeychainItemFreeContent(&list, NULL);
9e9f7d6 @kgn Spaces to tabs
kgn authored
124 VRCFRelease(itemRef);
9fef320 @roddi working certificate check
authored
125 }
e615ec8 @kgn Removing un-needed release and status variable.
kgn authored
126
9e9f7d6 @kgn Spaces to tabs
kgn authored
127 [name release];
9fef320 @roddi working certificate check
authored
128 }
e615ec8 @kgn Removing un-needed release and status variable.
kgn authored
129
9e9f7d6 @kgn Spaces to tabs
kgn authored
130 VRCFRelease(searchList);
131 VRCFRelease(searchRef);
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
132
9fef320 @roddi working certificate check
authored
133 return resultData;
134 }
135
136
bddbcd1 @roddi initial commit
authored
137 NSDictionary * dictionaryWithAppStoreReceipt(NSString * path)
138 {
9fef320 @roddi working certificate check
authored
139 NSData * rootCertData = appleRootCert();
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
140
141 enum ATTRIBUTES
bddbcd1 @roddi initial commit
authored
142 {
9e9f7d6 @kgn Spaces to tabs
kgn authored
143 ATTR_START = 1,
144 BUNDLE_ID,
145 VERSION,
146 OPAQUE_VALUE,
147 HASH,
148 ATTR_END
149 };
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
150
9fef320 @roddi working certificate check
authored
151 ERR_load_PKCS7_strings();
152 ERR_load_X509_strings();
153 OpenSSL_add_all_digests();
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
154
9e9f7d6 @kgn Spaces to tabs
kgn authored
155 // Expected input is a PKCS7 container with signed data containing
156 // an ASN.1 SET of SEQUENCE structures. Each SEQUENCE contains
157 // two INTEGERS and an OCTET STRING.
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
158
bddbcd1 @roddi initial commit
authored
159 const char * receiptPath = [[path stringByStandardizingPath] fileSystemRepresentation];
9e9f7d6 @kgn Spaces to tabs
kgn authored
160 FILE *fp = fopen(receiptPath, "rb");
161 if (fp == NULL)
162 return nil;
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
163
9e9f7d6 @kgn Spaces to tabs
kgn authored
164 PKCS7 *p7 = d2i_PKCS7_fp(fp, NULL);
165 fclose(fp);
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
166
8d5c75d Fixed crash when the receipt file is invalid.
philippm authored
167 // Check if the receipt file was invalid (otherwise we go crashing and burning)
168 if (p7 == NULL) {
169 return nil;
170 }
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
171
9e9f7d6 @kgn Spaces to tabs
kgn authored
172 if (!PKCS7_type_is_signed(p7)) {
173 PKCS7_free(p7);
174 return nil;
175 }
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
176
9e9f7d6 @kgn Spaces to tabs
kgn authored
177 if (!PKCS7_type_is_data(p7->d.sign->contents)) {
178 PKCS7_free(p7);
179 return nil;
180 }
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
181
91a8697 Proper allocation checks and cleanup for bio and X509.
Philippe Casgrain authored
182 int verifyReturnValue = 0;
9fef320 @roddi working certificate check
authored
183 X509_STORE *store = X509_STORE_new();
91a8697 Proper allocation checks and cleanup for bio and X509.
Philippe Casgrain authored
184 if (store)
185 {
75f7b19 @kgn Changes from yene's fork, this fixes my issue with warnings: issue 7
kgn authored
186 const unsigned char *data = (unsigned char *)(rootCertData.bytes);
eb16b8f @roddi added BSD-style license; tweaked build settings; corrected pointer co…
authored
187 X509 *appleCA = d2i_X509(NULL, &data, (long)rootCertData.length);
91a8697 Proper allocation checks and cleanup for bio and X509.
Philippe Casgrain authored
188 if (appleCA)
189 {
190 BIO *payload = BIO_new(BIO_s_mem());
191 X509_STORE_add_cert(store, appleCA);
192
193 if (payload)
194 {
195 verifyReturnValue = PKCS7_verify(p7,NULL,store,NULL,payload,0);
196 BIO_free(payload);
197 }
9fef320 @roddi working certificate check
authored
198
91a8697 Proper allocation checks and cleanup for bio and X509.
Philippe Casgrain authored
199 // this code will come handy when the first real receipts arrive
9fef320 @roddi working certificate check
authored
200 #if 0
91a8697 Proper allocation checks and cleanup for bio and X509.
Philippe Casgrain authored
201 unsigned long err = ERR_get_error();
202 if(err)
203 printf("%lu: %s\n",err,ERR_error_string(err,NULL));
204 else {
205 STACK_OF(X509) *stack = PKCS7_get0_signers(p7, NULL, 0);
206 for(NSUInteger i = 0; i < sk_num(stack); i++) {
207 const X509 *signer = (X509*)sk_value(stack, i);
208 NSLog(@"name = %s", signer->name);
209 }
210 }
211 #endif
212
213 X509_free(appleCA);
9fef320 @roddi working certificate check
authored
214 }
91a8697 Proper allocation checks and cleanup for bio and X509.
Philippe Casgrain authored
215 X509_STORE_free(store);
9fef320 @roddi working certificate check
authored
216 }
217 EVP_cleanup();
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
218
9fef320 @roddi working certificate check
authored
219 if (verifyReturnValue != 1)
fcd6d2c @roddi cleaned up, added anlumo to copyright notice and README
authored
220 {
9e9f7d6 @kgn Spaces to tabs
kgn authored
221 PKCS7_free(p7);
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
222 return nil;
fcd6d2c @roddi cleaned up, added anlumo to copyright notice and README
authored
223 }
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
224
225 ASN1_OCTET_STRING *octets = p7->d.sign->contents->d.data;
75f7b19 @kgn Changes from yene's fork, this fixes my issue with warnings: issue 7
kgn authored
226 const unsigned char *p = octets->data;
9e9f7d6 @kgn Spaces to tabs
kgn authored
227 const unsigned char *end = p + octets->length;
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
228
9e9f7d6 @kgn Spaces to tabs
kgn authored
229 int type = 0;
230 int xclass = 0;
231 long length = 0;
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
232
9e9f7d6 @kgn Spaces to tabs
kgn authored
233 ASN1_get_object(&p, &length, &type, &xclass, end - p);
234 if (type != V_ASN1_SET) {
235 PKCS7_free(p7);
236 return nil;
237 }
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
238
9e9f7d6 @kgn Spaces to tabs
kgn authored
239 NSMutableDictionary *info = [NSMutableDictionary dictionary];
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
240
9e9f7d6 @kgn Spaces to tabs
kgn authored
241 while (p < end) {
242 ASN1_get_object(&p, &length, &type, &xclass, end - p);
243 if (type != V_ASN1_SEQUENCE)
244 break;
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
245
9e9f7d6 @kgn Spaces to tabs
kgn authored
246 const unsigned char *seq_end = p + length;
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
247
9e9f7d6 @kgn Spaces to tabs
kgn authored
248 int attr_type = 0;
249 int attr_version = 0;
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
250
9e9f7d6 @kgn Spaces to tabs
kgn authored
251 // Attribute type
252 ASN1_get_object(&p, &length, &type, &xclass, seq_end - p);
253 if (type == V_ASN1_INTEGER && length == 1) {
254 attr_type = p[0];
255 }
256 p += length;
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
257
9e9f7d6 @kgn Spaces to tabs
kgn authored
258 // Attribute version
259 ASN1_get_object(&p, &length, &type, &xclass, seq_end - p);
260 if (type == V_ASN1_INTEGER && length == 1) {
261 attr_version = p[0];
8cce890 @tgunr Added new static library target validateAS.
tgunr authored
262 attr_version = attr_version;
9e9f7d6 @kgn Spaces to tabs
kgn authored
263 }
264 p += length;
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
265
9e9f7d6 @kgn Spaces to tabs
kgn authored
266 // Only parse attributes we're interested in
267 if (attr_type > ATTR_START && attr_type < ATTR_END) {
268 NSString *key;
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
269
9e9f7d6 @kgn Spaces to tabs
kgn authored
270 ASN1_get_object(&p, &length, &type, &xclass, seq_end - p);
271 if (type == V_ASN1_OCTET_STRING) {
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
272
9e9f7d6 @kgn Spaces to tabs
kgn authored
273 // Bytes
274 if (attr_type == BUNDLE_ID || attr_type == OPAQUE_VALUE || attr_type == HASH) {
275 NSData *data = [NSData dataWithBytes:p length:(NSUInteger)length];
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
276
9e9f7d6 @kgn Spaces to tabs
kgn authored
277 switch (attr_type) {
278 case BUNDLE_ID:
279 // This is included for hash generation
280 key = kReceiptBundleIdentiferData;
281 break;
282 case OPAQUE_VALUE:
283 key = kReceiptOpaqueValue;
284 break;
285 case HASH:
286 key = kReceiptHash;
287 break;
288 }
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
289
9e9f7d6 @kgn Spaces to tabs
kgn authored
290 [info setObject:data forKey:key];
291 }
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
292
9e9f7d6 @kgn Spaces to tabs
kgn authored
293 // Strings
294 if (attr_type == BUNDLE_ID || attr_type == VERSION) {
295 int str_type = 0;
296 long str_length = 0;
75f7b19 @kgn Changes from yene's fork, this fixes my issue with warnings: issue 7
kgn authored
297 const unsigned char *str_p = p;
9e9f7d6 @kgn Spaces to tabs
kgn authored
298 ASN1_get_object(&str_p, &str_length, &str_type, &xclass, seq_end - str_p);
299 if (str_type == V_ASN1_UTF8STRING) {
300 NSString *string = [[[NSString alloc] initWithBytes:str_p
301 length:(NSUInteger)str_length
302 encoding:NSUTF8StringEncoding] autorelease];
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
303
9e9f7d6 @kgn Spaces to tabs
kgn authored
304 switch (attr_type) {
305 case BUNDLE_ID:
306 key = kReceiptBundleIdentifer;
307 break;
308 case VERSION:
309 key = kReceiptVersion;
310 break;
311 }
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
312
9e9f7d6 @kgn Spaces to tabs
kgn authored
313 [info setObject:string forKey:key];
314 }
315 }
316 }
317 p += length;
318 }
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
319
9e9f7d6 @kgn Spaces to tabs
kgn authored
320 // Skip any remaining fields in this SEQUENCE
321 while (p < seq_end) {
322 ASN1_get_object(&p, &length, &type, &xclass, seq_end - p);
323 p += length;
324 }
325 }
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
326
9e9f7d6 @kgn Spaces to tabs
kgn authored
327 PKCS7_free(p7);
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
328
9e9f7d6 @kgn Spaces to tabs
kgn authored
329 return info;
bddbcd1 @roddi initial commit
authored
330 }
331
332
333
334 // Returns a CFData object, containing the machine's GUID.
335 CFDataRef copy_mac_address(void)
336 {
9e9f7d6 @kgn Spaces to tabs
kgn authored
337 kern_return_t kernResult;
338 mach_port_t master_port;
339 CFMutableDictionaryRef matchingDict;
340 io_iterator_t iterator;
341 io_object_t service;
342 CFDataRef macAddress = nil;
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
343
9e9f7d6 @kgn Spaces to tabs
kgn authored
344 kernResult = IOMasterPort(MACH_PORT_NULL, &master_port);
345 if (kernResult != KERN_SUCCESS) {
346 printf("IOMasterPort returned %d\n", kernResult);
347 return nil;
348 }
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
349
9e9f7d6 @kgn Spaces to tabs
kgn authored
350 matchingDict = IOBSDNameMatching(master_port, 0, "en0");
351 if(!matchingDict) {
352 printf("IOBSDNameMatching returned empty dictionary\n");
353 return nil;
354 }
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
355
9e9f7d6 @kgn Spaces to tabs
kgn authored
356 kernResult = IOServiceGetMatchingServices(master_port, matchingDict, &iterator);
357 if (kernResult != KERN_SUCCESS) {
358 printf("IOServiceGetMatchingServices returned %d\n", kernResult);
359 return nil;
360 }
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
361
9e9f7d6 @kgn Spaces to tabs
kgn authored
362 while((service = IOIteratorNext(iterator)) != 0)
363 {
364 io_object_t parentService;
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
365
9e9f7d6 @kgn Spaces to tabs
kgn authored
366 kernResult = IORegistryEntryGetParentEntry(service, kIOServicePlane, &parentService);
367 if(kernResult == KERN_SUCCESS)
368 {
369 VRCFRelease(macAddress);
370 macAddress = IORegistryEntryCreateCFProperty(parentService, CFSTR("IOMACAddress"), kCFAllocatorDefault, 0);
371 IOObjectRelease(parentService);
372 }
373 else {
374 printf("IORegistryEntryGetParentEntry returned %d\n", kernResult);
375 }
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
376
9e9f7d6 @kgn Spaces to tabs
kgn authored
377 IOObjectRelease(service);
378 }
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
379
9e9f7d6 @kgn Spaces to tabs
kgn authored
380 return macAddress;
bddbcd1 @roddi initial commit
authored
381 }
382
383 BOOL validateReceiptAtPath(NSString * path)
384 {
2939033 @roddi initializing pointers to nil
authored
385 NSString *bundleVersion = nil;
386 NSString *bundleIdentifer = nil;
adf2ab5 @fraserhess Validate bundle identifier and bundle version
fraserhess authored
387 #ifndef USE_SAMPLE_RECEIPT
c7b6179 @roddi receipt coping vulnerability fix (thanks to Sean Christmann for bring…
authored
388 // it turns out, it's a bad idea, to use these two NSBundle methods in your app:
389 //
390 // bundleVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
391 // bundleIdentifer = [[NSBundle mainBundle] bundleIdentifier];
392 //
393 // http://www.craftymind.com/2011/01/06/mac-app-store-hacked-how-developers-can-better-protect-themselves/
394
395 // so use hard coded values instead (probably even somehow obfuscated)
396 bundleVersion = @"1.0.2";
397 bundleIdentifer = @"com.example.SampleApp";
398
399 // avoid making stupid mistakes --> check again
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
400 NSAssert([bundleVersion isEqualToString:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]],
c7b6179 @roddi receipt coping vulnerability fix (thanks to Sean Christmann for bring…
authored
401 @"whoops! check the hard-coded CFBundleShortVersionString!");
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
402 NSAssert([bundleIdentifer isEqualToString:[[NSBundle mainBundle] bundleIdentifier]],
c7b6179 @roddi receipt coping vulnerability fix (thanks to Sean Christmann for bring…
authored
403 @"whoops! check the hard-coded bundle identifier!");
6f35a9b @kgn Moving bundleIdentifier and bundleVersion code above any returns so t…
kgn authored
404 #else
405 bundleVersion = @"1.0.2";
406 bundleIdentifer = @"com.example.SampleApp";
407 #endif
408 NSDictionary * receipt = dictionaryWithAppStoreReceipt(path);
409
410 if (!receipt)
411 return NO;
412
413 NSData * guidData = nil;
414 #ifndef USE_SAMPLE_RECEIPT
415 guidData = (NSData*)copy_mac_address();
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
416
6f35a9b @kgn Moving bundleIdentifier and bundleVersion code above any returns so t…
kgn authored
417 if ([NSGarbageCollector defaultCollector])
418 [[NSGarbageCollector defaultCollector] enableCollectorForPointer:guidData];
419 else
420 [guidData autorelease];
421
422 if (!guidData)
423 return NO;
adf2ab5 @fraserhess Validate bundle identifier and bundle version
fraserhess authored
424 #else
425 // Overwrite with example GUID for use with example receipt
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
426 unsigned char guid[] = { 0x00, 0x17, 0xf2, 0xc4, 0xbc, 0xc0 };
adf2ab5 @fraserhess Validate bundle identifier and bundle version
fraserhess authored
427 guidData = [NSData dataWithBytes:guid length:sizeof(guid)];
8cce890 @tgunr Added new static library target validateAS.
tgunr authored
428 #endif
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
429
bddbcd1 @roddi initial commit
authored
430 NSMutableData *input = [NSMutableData data];
431 [input appendData:guidData];
432 [input appendData:[receipt objectForKey:kReceiptOpaqueValue]];
433 [input appendData:[receipt objectForKey:kReceiptBundleIdentiferData]];
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
434
bddbcd1 @roddi initial commit
authored
435 NSMutableData *hash = [NSMutableData dataWithLength:SHA_DIGEST_LENGTH];
436 SHA1([input bytes], [input length], [hash mutableBytes]);
adf2ab5 @fraserhess Validate bundle identifier and bundle version
fraserhess authored
437
438 if ([bundleIdentifer isEqualToString:[receipt objectForKey:kReceiptBundleIdentifer]] &&
439 [bundleVersion isEqualToString:[receipt objectForKey:kReceiptVersion]] &&
0d24338 @kgn cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
440 [hash isEqualToData:[receipt objectForKey:kReceiptHash]])
bddbcd1 @roddi initial commit
authored
441 {
442 return YES;
443 }
444
445 return NO;
446 }
Something went wrong with that request. Please try again.