-
-
Save duoduoyi/41a916428c3b1504ee8598a2c237a190 to your computer and use it in GitHub Desktop.
Start IPSec programmatically in iOS 8
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- (void)viewDidLoad | |
{ | |
[super viewDidLoad]; | |
// init VPN manager | |
self.vpnManager = [NEVPNManager sharedManager]; | |
// load config from perference | |
[_vpnManager loadFromPreferencesWithCompletionHandler:^(NSError *error) { | |
if (error) { | |
NSLog(@"Load config failed [%@]", error.localizedDescription); | |
return; | |
} | |
NEVPNProtocolIPSec *p = _vpnManager.protocol; | |
if (p) { | |
// Protocol exists. | |
// If you don't want to edit it, just return here. | |
} else { | |
// create a new one. | |
p = [[NEVPNProtocolIPSec alloc] init]; | |
} | |
// config IPSec protocol | |
p.username = @"[Your username]"; | |
p.serverAddress = @"[Your server address]";; | |
// Get password persistent reference from keychain | |
// If password doesn't exist in keychain, should create it beforehand. | |
// [self createKeychainValue:@"your_password" forIdentifier:@"VPN_PASSWORD"]; | |
p.passwordReference = [self searchKeychainCopyMatching:@"VPN_PASSWORD"]; | |
// PSK | |
p.authenticationMethod = NEVPNIKEAuthenticationMethodSharedSecret; | |
// [self createKeychainValue:@"your_psk" forIdentifier:@"PSK"]; | |
p.sharedSecretReference = [self searchKeychainCopyMatching:@"PSK"]; | |
/* | |
// certificate | |
p.identityData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"client" ofType:@"p12"]]; | |
p.identityDataPassword = @"[Your certificate import password]"; | |
*/ | |
p.localIdentifier = @"[VPN local identifier]"; | |
p.remoteIdentifier = @"[VPN remote identifier]"; | |
p.useExtendedAuthentication = YES; | |
p.disconnectOnSleep = NO; | |
_vpnManager.protocol = p; | |
_vpnManager.localizedDescription = @"IPSec Demo"; | |
[_vpnManager saveToPreferencesWithCompletionHandler:^(NSError *error) { | |
if (error) { | |
NSLog(@"Save config failed [%@]", error.localizedDescription); | |
} | |
}]; | |
}]; | |
} | |
- (IBAction)startVPNConnection:(id)sender { | |
//[[VodManager sharedManager] installVPNProfile]; | |
NSError *startError; | |
[_vpnManager.connection startVPNTunnelAndReturnError:&startError]; | |
if (startError) { | |
NSLog(@"Start VPN failed: [%@]", startError.localizedDescription); | |
} | |
} | |
#pragma mark - KeyChain | |
static NSString * const serviceName = @"im.zorro.ipsec_demo.vpn_config"; | |
- (NSMutableDictionary *)newSearchDictionary:(NSString *)identifier { | |
NSMutableDictionary *searchDictionary = [[NSMutableDictionary alloc] init]; | |
[searchDictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; | |
NSData *encodedIdentifier = [identifier dataUsingEncoding:NSUTF8StringEncoding]; | |
[searchDictionary setObject:encodedIdentifier forKey:(__bridge id)kSecAttrGeneric]; | |
[searchDictionary setObject:encodedIdentifier forKey:(__bridge id)kSecAttrAccount]; | |
[searchDictionary setObject:serviceName forKey:(__bridge id)kSecAttrService]; | |
return searchDictionary; | |
} | |
- (NSData *)searchKeychainCopyMatching:(NSString *)identifier { | |
NSMutableDictionary *searchDictionary = [self newSearchDictionary:identifier]; | |
// Add search attributes | |
[searchDictionary setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit]; | |
// Add search return types | |
// Must be persistent ref !!!! | |
[searchDictionary setObject:@YES forKey:(__bridge id)kSecReturnPersistentRef]; | |
CFTypeRef result = NULL; | |
SecItemCopyMatching((__bridge CFDictionaryRef)searchDictionary, &result); | |
return (__bridge_transfer NSData *)result; | |
} | |
- (BOOL)createKeychainValue:(NSString *)password forIdentifier:(NSString *)identifier { | |
NSMutableDictionary *dictionary = [self newSearchDictionary:identifier]; | |
OSStatus status = SecItemDelete((__bridge CFDictionaryRef)dictionary); | |
NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding]; | |
[dictionary setObject:passwordData forKey:(__bridge id)kSecValueData]; | |
status = SecItemAdd((__bridge CFDictionaryRef)dictionary, NULL); | |
if (status == errSecSuccess) { | |
return YES; | |
} | |
return NO; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment