Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
8 /*
eb16b8f roddi added BSD-style license; tweaked build settings; corrected pointer const...
authored
9 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
0d24338 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
10
eb16b8f roddi added BSD-style license; tweaked build settings; corrected pointer const...
authored
11 Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
0d24338 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
12
eb16b8f roddi added BSD-style license; tweaked build settings; corrected pointer const...
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 David Keegan 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 const...
authored
17 from this software without specific prior written permission.
0d24338 David Keegan 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 const...
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 compil...
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 const...
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 David Keegan 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 const...
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 David Keegan Moving VRCFRelease to a better place
kgn authored
64
1051075 David Keegan Adding CFRelease macro
kgn authored
65 #define VRCFRelease(object) if(object) CFRelease(object)
eb16b8f roddi added BSD-style license; tweaked build settings; corrected pointer const...
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 David Keegan 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 David Keegan Adding CFRelease macro
kgn authored
80 if(status){
81 VRCFRelease(keychain);
9fef320 roddi working certificate check
authored
82 return nil;
83 }
0d24338 David Keegan 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 Philipp Mayerhofer 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 David Keegan Adding CFRelease macro
kgn authored
91 VRCFRelease(keychain);
864f78c Philipp Mayerhofer Fixed reference count underflow warning
philippm authored
92 #endif
0d24338 David Keegan 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 David Keegan Adding CFRelease macro
kgn authored
96 if(status){
9e9f7d6 David Keegan Spaces to tabs
kgn authored
97 VRCFRelease(searchRef);
98 VRCFRelease(searchList);
9fef320 roddi working certificate check
authored
99 return nil;
100 }
0d24338 David Keegan 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 David Keegan 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 David Keegan 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 David Keegan 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 David Keegan 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 David Keegan 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 David Keegan 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 David Keegan Spaces to tabs
kgn authored
124 VRCFRelease(itemRef);
9fef320 roddi working certificate check
authored
125 }
e615ec8 David Keegan Removing un-needed release and status variable.
kgn authored
126
9e9f7d6 David Keegan Spaces to tabs
kgn authored
127 [name release];
9fef320 roddi working certificate check
authored
128 }
e615ec8 David Keegan Removing un-needed release and status variable.
kgn authored
129
9e9f7d6 David Keegan Spaces to tabs
kgn authored
130 VRCFRelease(searchList);
131 VRCFRelease(searchRef);
0d24338 David Keegan 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 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
140
141 enum ATTRIBUTES
bddbcd1 roddi initial commit
authored
142 {
9e9f7d6 David Keegan Spaces to tabs
kgn authored
143 ATTR_START = 1,
144 BUNDLE_ID,
145 VERSION,
146 OPAQUE_VALUE,
147 HASH,
148 ATTR_END
149 };
0d24338 David Keegan 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 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
154
9e9f7d6 David Keegan 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 David Keegan 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 David Keegan Spaces to tabs
kgn authored
160 FILE *fp = fopen(receiptPath, "rb");
161 if (fp == NULL)
162 return nil;
0d24338 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
163
9e9f7d6 David Keegan Spaces to tabs
kgn authored
164 PKCS7 *p7 = d2i_PKCS7_fp(fp, NULL);
165 fclose(fp);
0d24338 David Keegan 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 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
171
9e9f7d6 David Keegan Spaces to tabs
kgn authored
172 if (!PKCS7_type_is_signed(p7)) {
173 PKCS7_free(p7);
174 return nil;
175 }
0d24338 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
176
9e9f7d6 David Keegan Spaces to tabs
kgn authored
177 if (!PKCS7_type_is_data(p7->d.sign->contents)) {
178 PKCS7_free(p7);
179 return nil;
180 }
0d24338 David Keegan 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 David Keegan 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 const...
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 David Keegan 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 David Keegan Spaces to tabs
kgn authored
221 PKCS7_free(p7);
0d24338 David Keegan 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 David Keegan 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 David Keegan Changes from yene's fork, this fixes my issue with warnings: issue 7
kgn authored
226 const unsigned char *p = octets->data;
9e9f7d6 David Keegan Spaces to tabs
kgn authored
227 const unsigned char *end = p + octets->length;
0d24338 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
228
9e9f7d6 David Keegan Spaces to tabs
kgn authored
229 int type = 0;
230 int xclass = 0;
231 long length = 0;
0d24338 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
232
9e9f7d6 David Keegan 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 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
238
9e9f7d6 David Keegan Spaces to tabs
kgn authored
239 NSMutableDictionary *info = [NSMutableDictionary dictionary];
0d24338 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
240
9e9f7d6 David Keegan 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 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
245
9e9f7d6 David Keegan Spaces to tabs
kgn authored
246 const unsigned char *seq_end = p + length;
0d24338 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
247
9e9f7d6 David Keegan Spaces to tabs
kgn authored
248 int attr_type = 0;
249 int attr_version = 0;
0d24338 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
250
9e9f7d6 David Keegan 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 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
257
9e9f7d6 David Keegan 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 Dave Carlton Added new static library target validateAS.
tgunr authored
262 attr_version = attr_version;
9e9f7d6 David Keegan Spaces to tabs
kgn authored
263 }
264 p += length;
0d24338 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
265
9e9f7d6 David Keegan 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 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
269
9e9f7d6 David Keegan Spaces to tabs
kgn authored
270 ASN1_get_object(&p, &length, &type, &xclass, seq_end - p);
271 if (type == V_ASN1_OCTET_STRING) {
0d24338 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
272
9e9f7d6 David Keegan 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 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
276
9e9f7d6 David Keegan 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 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
289
9e9f7d6 David Keegan Spaces to tabs
kgn authored
290 [info setObject:data forKey:key];
291 }
0d24338 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
292
9e9f7d6 David Keegan 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 David Keegan Changes from yene's fork, this fixes my issue with warnings: issue 7
kgn authored
297 const unsigned char *str_p = p;
9e9f7d6 David Keegan 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 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
303
9e9f7d6 David Keegan 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 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
312
9e9f7d6 David Keegan Spaces to tabs
kgn authored
313 [info setObject:string forKey:key];
314 }
315 }
316 }
317 p += length;
318 }
0d24338 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
319
9e9f7d6 David Keegan 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 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
326
9e9f7d6 David Keegan Spaces to tabs
kgn authored
327 PKCS7_free(p7);
0d24338 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
328
9e9f7d6 David Keegan 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 David Keegan 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 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
343
9e9f7d6 David Keegan 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 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
349
9e9f7d6 David Keegan 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 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
355
9e9f7d6 David Keegan 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 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
361
9e9f7d6 David Keegan Spaces to tabs
kgn authored
362 while((service = IOIteratorNext(iterator)) != 0)
363 {
364 io_object_t parentService;
0d24338 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
365
9e9f7d6 David Keegan 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 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
376
9e9f7d6 David Keegan Spaces to tabs
kgn authored
377 IOObjectRelease(service);
378 }
0d24338 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
379
9e9f7d6 David Keegan 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 Fraser Hess Validate bundle identifier and bundle version
fraserhess authored
387 #ifndef USE_SAMPLE_RECEIPT
c7b6179 roddi receipt coping vulnerability fix (thanks to Sean Christmann for bringing...
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 David Keegan 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 bringing...
authored
401 @"whoops! check the hard-coded CFBundleShortVersionString!");
0d24338 David Keegan 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 bringing...
authored
403 @"whoops! check the hard-coded bundle identifier!");
6f35a9b David Keegan Moving bundleIdentifier and bundleVersion code above any returns so the ...
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 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
416
6f35a9b David Keegan Moving bundleIdentifier and bundleVersion code above any returns so the ...
kgn authored
417 if ([NSGarbageCollector defaultCollector])
418 [[NSGarbageCollector defaultCollector] enableCollectorForPointer:guidData];
419 else
420 [guidData autorelease];
421
422 if (!guidData)
423 return NO;
adf2ab5 Fraser Hess Validate bundle identifier and bundle version
fraserhess authored
424 #else
425 // Overwrite with example GUID for use with example receipt
0d24338 David Keegan cleaning code with spaces to tabs and removeing needless whitespace
kgn authored
426 unsigned char guid[] = { 0x00, 0x17, 0xf2, 0xc4, 0xbc, 0xc0 };
adf2ab5 Fraser Hess Validate bundle identifier and bundle version
fraserhess authored
427 guidData = [NSData dataWithBytes:guid length:sizeof(guid)];
8cce890 Dave Carlton Added new static library target validateAS.
tgunr authored
428 #endif
0d24338 David Keegan 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 David Keegan 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 Fraser Hess Validate bundle identifier and bundle version
fraserhess authored
437
438 if ([bundleIdentifer isEqualToString:[receipt objectForKey:kReceiptBundleIdentifer]] &&
439 [bundleVersion isEqualToString:[receipt objectForKey:kReceiptVersion]] &&
0d24338 David Keegan 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.