Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mumble-voip/mumble-iphoneos.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikkel Krautz <mikkel@krautz.dk>2012-03-21 18:42:54 +0400
committerMikkel Krautz <mikkel@krautz.dk>2012-03-21 18:42:54 +0400
commit15c86c2a995951dc0a455e733204958d2a18341d (patch)
tree1eb1d70ec988465e05db4e81a1fb0b3fef38dcd3
parenta797defff1f8375005a027dee0af8fdb00ffe27c (diff)
MUCertificate*: import all intermediates; show then in UI.
-rwxr-xr-xMumble.xcodeproj/project.pbxproj8
m---------MumbleKit0
-rw-r--r--Source/Classes/MUCertificateCell.h3
-rw-r--r--Source/Classes/MUCertificateCell.m20
-rw-r--r--Source/Classes/MUCertificateController.m30
-rw-r--r--Source/Classes/MUCertificateDiskImportViewController.m20
-rw-r--r--Source/Classes/MUCertificatePreferencesViewController.m87
-rw-r--r--Source/Classes/MUCertificateViewController.m3
-rw-r--r--Source/Classes/MUConnectionController.m2
9 files changed, 153 insertions, 20 deletions
diff --git a/Mumble.xcodeproj/project.pbxproj b/Mumble.xcodeproj/project.pbxproj
index 306fc16..76b74be 100755
--- a/Mumble.xcodeproj/project.pbxproj
+++ b/Mumble.xcodeproj/project.pbxproj
@@ -42,6 +42,8 @@
2861C2B2116BE9B7002B8514 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2861C2B1116BE9B7002B8514 /* CFNetwork.framework */; };
2861C2B6116BE9BA002B8514 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2861C2B5116BE9BA002B8514 /* Security.framework */; };
286E9260148452A000B13593 /* MUVoiceActivitySetupViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 286E925F148452A000B13593 /* MUVoiceActivitySetupViewController.m */; };
+ 287172AB151A041A00153D74 /* certificatecell-intermediate.png in Resources */ = {isa = PBXBuildFile; fileRef = 287172A9151A041A00153D74 /* certificatecell-intermediate.png */; };
+ 287172AC151A041A00153D74 /* certificatecell-intermediate@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 287172AA151A041A00153D74 /* certificatecell-intermediate@2x.png */; };
287639F911D29D99009DB8B6 /* MUCertificateCreationProgressView.m in Sources */ = {isa = PBXBuildFile; fileRef = 287639F811D29D99009DB8B6 /* MUCertificateCreationProgressView.m */; };
287639FF11D2A242009DB8B6 /* MUCertificateCreationProgressView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 287639FE11D2A242009DB8B6 /* MUCertificateCreationProgressView.xib */; };
28763A4511D2AA91009DB8B6 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 28763A4411D2AA91009DB8B6 /* QuartzCore.framework */; };
@@ -263,6 +265,8 @@
2861C2B5116BE9BA002B8514 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
286E925E148452A000B13593 /* MUVoiceActivitySetupViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MUVoiceActivitySetupViewController.h; sourceTree = "<group>"; };
286E925F148452A000B13593 /* MUVoiceActivitySetupViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MUVoiceActivitySetupViewController.m; sourceTree = "<group>"; };
+ 287172A9151A041A00153D74 /* certificatecell-intermediate.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "certificatecell-intermediate.png"; path = "Resources/certificatecell-intermediate.png"; sourceTree = "<group>"; };
+ 287172AA151A041A00153D74 /* certificatecell-intermediate@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "certificatecell-intermediate@2x.png"; path = "Resources/certificatecell-intermediate@2x.png"; sourceTree = "<group>"; };
287639F711D29D99009DB8B6 /* MUCertificateCreationProgressView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MUCertificateCreationProgressView.h; sourceTree = "<group>"; };
287639F811D29D99009DB8B6 /* MUCertificateCreationProgressView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MUCertificateCreationProgressView.m; sourceTree = "<group>"; };
287639FE11D2A242009DB8B6 /* MUCertificateCreationProgressView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MUCertificateCreationProgressView.xib; sourceTree = "<group>"; };
@@ -739,6 +743,8 @@
28DC1C1B13DE596B0037CDC2 /* certificate512.png */,
28DC1C1C13DE596B0037CDC2 /* certificatecell-selected.png */,
28DC1C1D13DE596B0037CDC2 /* certificatecell-selected@2x.png */,
+ 287172A9151A041A00153D74 /* certificatecell-intermediate.png */,
+ 287172AA151A041A00153D74 /* certificatecell-intermediate@2x.png */,
28DC1C1E13DE596B0037CDC2 /* certificatecell.png */,
28DC1C1F13DE596B0037CDC2 /* certificatecell@2x.png */,
28DC1C2013DE596B0037CDC2 /* channel.png */,
@@ -1073,6 +1079,8 @@
285E2A69150D729B008AE185 /* Release.xcconfig in Resources */,
280256381510D70D00178B08 /* Localizable.strings in Resources */,
2802563C1510DDCA00178B08 /* Localizable.strings in Resources */,
+ 287172AB151A041A00153D74 /* certificatecell-intermediate.png in Resources */,
+ 287172AC151A041A00153D74 /* certificatecell-intermediate@2x.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/MumbleKit b/MumbleKit
-Subproject bd4913ca76113977d1df931da025f2e81d16234
+Subproject f9f2957119e7090ce187d7338df65d9f8a22d8f
diff --git a/Source/Classes/MUCertificateCell.h b/Source/Classes/MUCertificateCell.h
index 47fcecb..cc32229 100644
--- a/Source/Classes/MUCertificateCell.h
+++ b/Source/Classes/MUCertificateCell.h
@@ -37,6 +37,9 @@
- (void) setIssuerText:(NSString *)issuerText;
- (void) setExpiryText:(NSString *)expiryText;
+- (BOOL) isIntermediate;
+- (void) setIsIntermediate:(BOOL)isIntermediate;
+
- (BOOL) isCurrentCertificate;
- (void) setIsCurrentCertificate:(BOOL)isSelected;
diff --git a/Source/Classes/MUCertificateCell.m b/Source/Classes/MUCertificateCell.m
index 37a445b..ccb4e80 100644
--- a/Source/Classes/MUCertificateCell.m
+++ b/Source/Classes/MUCertificateCell.m
@@ -38,6 +38,7 @@
IBOutlet UILabel *_issuerLabel;
IBOutlet UILabel *_expiryLabel;
BOOL _isCurrentCert;
+ BOOL _isIntermediate;
}
@end
@@ -64,6 +65,19 @@
_expiryLabel.text = expiryText;
}
+- (void) setIsIntermediate:(BOOL)isIntermediate {
+ _isIntermediate = isIntermediate;
+ if (_isIntermediate) {
+ [_certImage setImage:[UIImage imageNamed:@"certificatecell-intermediate"]];
+ } else {
+ [_certImage setImage:[UIImage imageNamed:@"certificatecell"]];
+ }
+}
+
+- (BOOL) isIntermediate {
+ return _isIntermediate;
+}
+
- (void) setIsCurrentCertificate:(BOOL)isCurrent {
_isCurrentCert = isCurrent;
if (isCurrent) {
@@ -71,7 +85,11 @@
[_nameLabel setTextColor:[MUColor selectedTextColor]];
[_emailLabel setTextColor:[MUColor selectedTextColor]];
} else {
- [_certImage setImage:[UIImage imageNamed:@"certificatecell"]];
+ if (_isIntermediate) {
+ [_certImage setImage:[UIImage imageNamed:@"certificatecell-intermediate"]];
+ } else {
+ [_certImage setImage:[UIImage imageNamed:@"certificatecell"]];
+ }
[_nameLabel setTextColor:[UIColor blackColor]];
[_emailLabel setTextColor:[UIColor blackColor]];
}
diff --git a/Source/Classes/MUCertificateController.m b/Source/Classes/MUCertificateController.m
index 0988be6..523d8d5 100644
--- a/Source/Classes/MUCertificateController.m
+++ b/Source/Classes/MUCertificateController.m
@@ -40,14 +40,25 @@
kCFBooleanTrue, kSecReturnRef,
kSecMatchLimitOne, kSecMatchLimit,
nil];
- SecIdentityRef identity = NULL;
+ CFTypeRef thing = NULL;
MKCertificate *cert = nil;
- if (SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&identity) == noErr && identity != NULL) {
- SecCertificateRef secCert;
- if (SecIdentityCopyCertificate(identity, &secCert) == noErr) {
+ if (SecItemCopyMatching((CFDictionaryRef)query, &thing) == noErr && thing != NULL) {
+ CFTypeID receivedType = CFGetTypeID(thing);
+ if (receivedType == SecIdentityGetTypeID()) {
+ SecIdentityRef identity = (SecIdentityRef) thing;
+ SecCertificateRef secCert = NULL;
+ if (SecIdentityCopyCertificate(identity, &secCert) == noErr) {
+ NSData *secData = (NSData *)SecCertificateCopyData(secCert);
+ cert = [MKCertificate certificateWithCertificate:secData privateKey:nil];
+ [secData release];
+ }
+ } else if (receivedType == SecCertificateGetTypeID()) {
+ SecCertificateRef secCert = (SecCertificateRef) thing;
NSData *secData = (NSData *)SecCertificateCopyData(secCert);
cert = [MKCertificate certificateWithCertificate:secData privateKey:nil];
[secData release];
+ } else {
+ return nil;
}
}
return cert;
@@ -60,13 +71,16 @@
kCFBooleanTrue, kSecReturnRef,
kSecMatchLimitOne, kSecMatchLimit,
nil];
- SecIdentityRef identity = NULL;
+ CFTypeRef thing = NULL;
MKCertificate *cert = nil;
- if (SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&identity) == noErr && identity != NULL) {
+ if (SecItemCopyMatching((CFDictionaryRef)query, &thing) == noErr && thing != NULL) {
+ // Only identities can have private keys.
+ if (CFGetTypeID(thing) != SecIdentityGetTypeID())
+ return nil;
SecCertificateRef secCert;
- if (SecIdentityCopyCertificate(identity, &secCert) == noErr) {
+ if (SecIdentityCopyCertificate((SecIdentityRef) thing, &secCert) == noErr) {
SecKeyRef secKey;
- if (SecIdentityCopyPrivateKey(identity, &secKey) == noErr) {
+ if (SecIdentityCopyPrivateKey((SecIdentityRef) thing, &secKey) == noErr) {
NSData *certData = (NSData *)SecCertificateCopyData(secCert);
NSData *pkeyData = nil;
query = [NSDictionary dictionaryWithObjectsAndKeys:
diff --git a/Source/Classes/MUCertificateDiskImportViewController.m b/Source/Classes/MUCertificateDiskImportViewController.m
index 5446d7c..e8cb718 100644
--- a/Source/Classes/MUCertificateDiskImportViewController.m
+++ b/Source/Classes/MUCertificateDiskImportViewController.m
@@ -205,9 +205,25 @@ static void ShowAlertDialog(NSString *title, NSString *msg) {
NSArray *items = nil;
OSStatus err = SecPKCS12Import((CFDataRef)transformedPkcs12Data, (CFDictionaryRef)dict, (CFArrayRef *)&items);
- if (err == errSecSuccess && [items count] > 0) {
+ if (err == errSecSuccess && [items count] > 0) {
+ // Add all elements except the leaf certificate to the keychain
NSDictionary *pkcsDict = [items objectAtIndex:0];
- // Get the SecIdentityRef
+ NSArray *chain = [pkcsDict objectForKey:(NSString *)kSecImportItemCertChain];
+ for (int i = 1; i < [chain count]; i++) {
+ NSDictionary *op = [NSDictionary dictionaryWithObjectsAndKeys:
+ [chain objectAtIndex:i], kSecValueRef, nil];
+ err = SecItemAdd((CFDictionaryRef)op, NULL);
+ if (err != noErr) {
+ if (err == errSecDuplicateItem) {
+ // Duplicates are OK in this case.
+ } else {
+ ShowAlertDialog(NSLocalizedString(@"Import Error", nil),
+ NSLocalizedString(@"Mumble was unable to import one of the intermediate certificates in the certificate chain.", nil));
+ }
+ }
+ }
+
+ // Get the SecIdentityRef, and add it to the keychain
SecIdentityRef identity = (SecIdentityRef)[pkcsDict objectForKey:(id)kSecImportItemIdentity];
NSDictionary *op = [NSDictionary dictionaryWithObjectsAndKeys:
(id)identity, kSecValueRef,
diff --git a/Source/Classes/MUCertificatePreferencesViewController.m b/Source/Classes/MUCertificatePreferencesViewController.m
index 26ab80d..c061b47 100644
--- a/Source/Classes/MUCertificatePreferencesViewController.m
+++ b/Source/Classes/MUCertificatePreferencesViewController.m
@@ -41,6 +41,7 @@
NSMutableArray *_certificateItems;
BOOL _picker;
NSUInteger _selectedIndex;
+ BOOL _showAll;
}
- (void) fetchCertificates;
- (void) deleteCertificateForRow:(NSUInteger)row;
@@ -54,6 +55,7 @@
- (id) init {
if ((self = [super init])) {
[self setContentSizeForViewInPopover:CGSizeMake(320, 480)];
+ _showAll = [[[NSUserDefaults standardUserDefaults] objectForKey:@"CertificatesShowIntermediates"] boolValue];
}
return self;
}
@@ -97,7 +99,6 @@
cell = [MUCertificateCell loadFromNib];
// Configure the cell...
- cell.selectionStyle = UITableViewCellSelectionStyleGray;
NSDictionary *dict = [_certificateItems objectAtIndex:[indexPath row]];
MKCertificate *cert = [dict objectForKey:@"cert"];
[cell setSubjectName:[cert subjectName]];
@@ -108,13 +109,21 @@
NSData *persistentRef = [dict objectForKey:@"persistentRef"];
NSData *curPersistentRef = [[NSUserDefaults standardUserDefaults] objectForKey:@"DefaultCertificate"];
+ if ([[dict objectForKey:@"isIdentity"] boolValue]) {
+ [cell setIsIntermediate:NO];
+ cell.selectionStyle = UITableViewCellSelectionStyleGray;
+ } else {
+ [cell setIsIntermediate:YES];
+ cell.selectionStyle = UITableViewCellSelectionStyleNone;
+ }
+
if ([persistentRef isEqualToData:curPersistentRef]) {
_selectedIndex = [indexPath row];
[cell setIsCurrentCertificate:YES];
} else {
[cell setIsCurrentCertificate:NO];
}
-
+
[cell setAccessoryType:UITableViewCellAccessoryDetailDisclosureButton];
return (UITableViewCell *) cell;
@@ -129,6 +138,12 @@
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *dict = [_certificateItems objectAtIndex:[indexPath row]];
+
+ // Don't allow selection of intermediates.
+ if (![[dict objectForKey:@"isIdentity"] boolValue]) {
+ return;
+ }
+
NSData *persistentRef = [dict objectForKey:@"persistentRef"];
[[NSUserDefaults standardUserDefaults] setObject:persistentRef forKey:@"DefaultCertificate"];
@@ -164,12 +179,14 @@
#pragma mark Target/actions
- (void) addButtonClicked:(UIBarButtonItem *)addButton {
- NSString *title = NSLocalizedString(@"Add Certificate", @"Add certificate UIActionSheet");
- UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:title
+ NSString *showAllCerts = NSLocalizedString(@"Show All Certificates", nil);
+ NSString *showIdentities = NSLocalizedString(@"Show Identities Only", nil);
+ UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:nil
delegate:self
cancelButtonTitle:NSLocalizedString(@"Cancel", nil)
destructiveButtonTitle:nil
otherButtonTitles:NSLocalizedString(@"Generate New Certificate", nil),
+ _showAll ? showIdentities : showAllCerts,
NSLocalizedString(@"Import From iTunes", nil),
nil];
[sheet setActionSheetStyle:UIActionSheetStyleBlackOpaque];
@@ -189,7 +206,12 @@
[certGen release];
[[self navigationController] presentModalViewController:navCtrl animated:YES];
[navCtrl release];
- } else if (idx == 1) { // Import From Disk
+ } else if (idx == 1) { // Show All Certificates; Show Identities Only
+ _showAll = !_showAll;
+ [[NSUserDefaults standardUserDefaults] setBool:_showAll forKey:@"CertificatesShowIntermediates"];
+ [self fetchCertificates];
+ [self.tableView reloadData];
+ } else if (idx == 2) { // Import From Disk
MUCertificateDiskImportViewController *diskImportViewController = [[MUCertificateDiskImportViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:diskImportViewController];
[[self navigationController] presentModalViewController:navController animated:YES];
@@ -213,7 +235,60 @@
MKCertificate *cert = [MUCertificateController certificateWithPersistentRef:persistentRef];
if (cert) {
[_certificateItems addObject:[NSDictionary dictionaryWithObjectsAndKeys:
- cert, @"cert", persistentRef, @"persistentRef", nil]];
+ cert, @"cert",
+ persistentRef, @"persistentRef",
+ [NSNumber numberWithBool:YES], @"isIdentity",
+ nil]];
+ }
+ }
+ }
+
+ if (_showAll) {
+ // Extract hashes of identity certs
+ NSMutableArray *identityCertHashes = [[[NSMutableArray alloc] init] autorelease];
+ for (NSDictionary *item in _certificateItems) {
+ [identityCertHashes addObject:[[item objectForKey:@"cert"] digest]];
+ }
+
+ // Extract all intermediates
+ NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys:
+ kSecClassCertificate, kSecClass,
+ kCFBooleanTrue, kSecReturnPersistentRef,
+ kSecMatchLimitAll, kSecMatchLimit, nil];
+ NSArray *persistentRefs = nil;
+ SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&persistentRefs);
+ [persistentRefs autorelease];
+
+ for (NSData *ref in persistentRefs) {
+ NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys:
+ ref, kSecValuePersistentRef,
+ kCFBooleanTrue, kSecReturnRef,
+ kSecMatchLimitOne, kSecMatchLimit,
+ nil];
+ SecCertificateRef secCert;
+ if (SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&secCert) == noErr && secCert != NULL) {
+ NSData *certData = (NSData *) SecCertificateCopyData(secCert);
+ CFRelease(secCert);
+
+ MKCertificate *consideredCert = [MKCertificate certificateWithCertificate:certData privateKey:nil];
+ NSData *consideredDigest = [consideredCert digest];
+ [certData release];
+
+ BOOL alreadyPresent = NO;
+ for (NSData *digest in identityCertHashes) {
+ if ([consideredDigest isEqualToData:digest]) {
+ alreadyPresent = YES;
+ break;
+ }
+ }
+
+ if (!alreadyPresent) {
+ [_certificateItems addObject:[NSDictionary dictionaryWithObjectsAndKeys:
+ consideredCert, @"cert",
+ ref, @"persistentRef",
+ [NSNumber numberWithBool:NO], @"isIdentity",
+ nil]];
+ }
}
}
}
diff --git a/Source/Classes/MUCertificateViewController.m b/Source/Classes/MUCertificateViewController.m
index d684d0c..0e6320f 100644
--- a/Source/Classes/MUCertificateViewController.m
+++ b/Source/Classes/MUCertificateViewController.m
@@ -58,8 +58,7 @@ static const NSUInteger CertificateViewSectionTotal = 2;
- (id) initWithPersistentRef:(NSData *)persistentRef {
if ((self = [super initWithStyle:UITableViewStyleGrouped])) {
- [MUCertificateController certificateWithPersistentRef:persistentRef];
- _certificates = [[NSArray arrayWithObject:[MUCertificateController certificateAndPrivateKeyWithPersistentRef:persistentRef]] retain];
+ _certificates = [[NSArray arrayWithObject:[MUCertificateController certificateWithPersistentRef:persistentRef]] retain];
_allowExportAndDelete = YES;
_persistentRef = [persistentRef retain];
diff --git a/Source/Classes/MUConnectionController.m b/Source/Classes/MUConnectionController.m
index 5c3e0b2..3e9fad7 100644
--- a/Source/Classes/MUConnectionController.m
+++ b/Source/Classes/MUConnectionController.m
@@ -147,7 +147,7 @@
kSecMatchLimitOne, kSecMatchLimit,
nil];
if (SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&secIdentity) == noErr && secIdentity != NULL) {
- [_connection setClientIdentity:secIdentity];
+ [_connection setCertificateChain:[NSArray arrayWithObject:(id)secIdentity]];
CFRelease(secIdentity);
}
}