PageRenderTime 62ms CodeModel.GetById 18ms app.highlight 40ms RepoModel.GetById 1ms app.codeStats 0ms

/core/autoinstaller/UpdateEngineExtensions/PlistSigner.m

http://macfuse.googlecode.com/
Objective C | 130 lines | 79 code | 35 blank | 16 comment | 9 complexity | 3c417820f699ddc73353b1fc2318cb25 MD5 | raw file
  1//
  2//  SignedPlist.m
  3//  autoinstaller
  4//
  5//  Created by Greg Miller on 7/18/08.
  6//  Copyright 2008 Google Inc. All rights reserved.
  7//
  8
  9#import "PlistSigner.h"
 10#import "Signer.h"
 11
 12
 13static NSString *const kSignatureKey = @"Signature";
 14
 15
 16@interface PlistSigner (PrivateMethods)
 17
 18- (void)setPlist:(NSDictionary *)plist;
 19
 20// Returns an opaque blob of data generated from |plist|. This blob of data can
 21// be used for signing and signature verification. However, it should NOT be
 22// interpreted in any way.
 23- (NSData *)blobFromDictionary:(NSDictionary *)plist;
 24
 25@end
 26
 27
 28@implementation PlistSigner
 29
 30- (id)init {
 31  return [self initWithSigner:nil plist:nil];
 32}
 33
 34- (id)initWithSigner:(Signer *)signer plist:(NSDictionary *)plist {
 35  if ((self = [super init])) {
 36    signer_ = [signer retain];
 37    [self setPlist:plist];
 38    if (signer_ == nil || plist_ == nil) {
 39      [self release];
 40      return nil;
 41    }
 42  }
 43  return self;
 44}
 45
 46- (void)dealloc {
 47  [signer_ release];
 48  [plist_ release];
 49  [super dealloc];
 50}
 51
 52- (NSDictionary *)plist {
 53  return [[plist_ copy] autorelease];
 54}
 55
 56- (BOOL)isPlistSigned {
 57  NSMutableDictionary *mutablePlist = [[plist_ mutableCopy] autorelease];
 58  NSData *signature = [mutablePlist objectForKey:kSignatureKey];
 59  [mutablePlist removeObjectForKey:kSignatureKey];
 60  
 61  NSData *blob = [self blobFromDictionary:mutablePlist];
 62  
 63  return [signer_ isSignature:signature validForData:blob];
 64}
 65
 66- (BOOL)signPlist {
 67  if ([self isPlistSigned]) return YES;
 68  
 69  NSMutableDictionary *mutablePlist = [[plist_ mutableCopy] autorelease];
 70  [mutablePlist removeObjectForKey:kSignatureKey];
 71  
 72  NSData *blob = [self blobFromDictionary:mutablePlist];
 73  
 74  NSData *signature = [signer_ signData:blob];
 75  BOOL ok = NO;
 76  
 77  if (signature != nil) {
 78    [mutablePlist setObject:signature forKey:kSignatureKey];
 79    [self setPlist:mutablePlist];
 80    ok = YES;
 81  }
 82  
 83  return ok;
 84}
 85
 86- (BOOL)unsignedPlist {
 87  if (![self isPlistSigned]) return YES;
 88  NSMutableDictionary *mutablePlist = [[plist_ mutableCopy] autorelease];
 89  [mutablePlist removeObjectForKey:kSignatureKey];
 90  [self setPlist:mutablePlist];
 91  return YES;
 92}
 93
 94@end
 95
 96
 97@implementation PlistSigner (PrivateMethods)
 98
 99- (void)setPlist:(NSDictionary *)plist {
100  [plist_ autorelease];
101  plist_ = [plist copy];
102}
103
104- (NSData *)blobFromDictionary:(NSDictionary *)plist {
105  // In order to sign/very plists on both Tiger and Leoaprd, we need to
106  // serialize the plist into an NSData, but this will contain an XML comment
107  // of either "Apple" or "Apple Computer" (Tiger), which will screw up 
108  // signatures. So, we need to convert this XML to a big string, strip off
109  // the first two lines (which are comments), then return the remainder of the
110  // XML as a big data blob.
111  
112  NSData *plistData = [NSPropertyListSerialization
113                       dataFromPropertyList:plist
114                       format:NSPropertyListXMLFormat_v1_0
115                       errorDescription:NULL];
116  
117  NSString *plistString = [[[NSString alloc]
118                            initWithData:plistData
119                                encoding:NSUTF8StringEncoding] autorelease];
120  
121  NSArray *lines = [plistString componentsSeparatedByString:@"\n"];
122  
123  NSRange range = NSMakeRange(2, [lines count] - 2);
124  NSArray *trimmedLines = [lines subarrayWithRange:range];
125  
126  NSString *trimmedString = [trimmedLines componentsJoinedByString:@"\n"];
127  return [trimmedString dataUsingEncoding:NSUTF8StringEncoding];
128}
129
130@end