Advertisement
Guest User

Untitled

a guest
Jul 31st, 2017
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.58 KB | None | 0 0
  1. //
  2. // LoginViewController.m
  3. // IKEv2_Demo
  4. //
  5. // Created by zqqf16 on 16/3/16.
  6. // Copyright © 2016年 zqqf16. All rights reserved.
  7. //
  8.  
  9. #import <NetworkExtension/NEVPNManager.h>
  10. #import <NetworkExtension/NEVPNConnection.h>
  11. #import <NetworkExtension/NEVPNProtocolIKEv2.h>
  12.  
  13. #import "LoginViewController.h"
  14.  
  15. @interface LoginViewController () <UITextFieldDelegate>
  16.  
  17. @property (weak, nonatomic) IBOutlet UITextField *server;
  18. @property (weak, nonatomic) IBOutlet UITextField *username;
  19. @property (weak, nonatomic) IBOutlet UITextField *password;
  20. @property (weak, nonatomic) IBOutlet UITextField *presharedKey;
  21. @property (weak, nonatomic) IBOutlet UITextField *remoteIdentifier;
  22. @property (weak, nonatomic) IBOutlet UITextField *localIdentifier;
  23.  
  24. @property (weak, nonatomic) IBOutlet UIButton *actionButton;
  25. @property (weak, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicator;
  26.  
  27. @property (strong, nonatomic) NEVPNManager *vpnManager;
  28.  
  29. @end
  30.  
  31. @implementation LoginViewController
  32.  
  33. - (void)viewDidLoad {
  34. [super viewDidLoad];
  35.  
  36. self.vpnManager = [NEVPNManager sharedManager];
  37.  
  38. NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
  39. [nc addObserver:self
  40. selector:@selector(vpnStatusDidChanged:)
  41. name:NEVPNStatusDidChangeNotification
  42. object:nil];
  43. }
  44.  
  45. - (void)didReceiveMemoryWarning {
  46. [super didReceiveMemoryWarning];
  47. }
  48.  
  49. #pragma mark - UITextField Delegate
  50.  
  51. - (BOOL)textFieldShouldReturn:(UITextField *)textField
  52. {
  53. NSArray *textFieldList = @[_server, _username, _password, _presharedKey, _remoteIdentifier, _localIdentifier];
  54. NSUInteger index = [textFieldList indexOfObject:textField];
  55.  
  56. [textField resignFirstResponder];
  57.  
  58. if (index < textFieldList.count - 1) {
  59. [(UITextField *)[textFieldList objectAtIndex:index+1] becomeFirstResponder];
  60. }
  61.  
  62. return YES;
  63. }
  64.  
  65. #pragma mark - VPN Control
  66.  
  67. - (void)installProfile {
  68. NSString *server = _server.text;
  69. NSString *username = _username.text;
  70. NSString *remoteIdentifier = _remoteIdentifier.text;
  71. NSString *localIdnetifier = _localIdentifier.text;
  72.  
  73. // Save password & psk
  74. [self createKeychainValue:_password.text forIdentifier:@"VPN_PASSWORD"];
  75. [self createKeychainValue:_presharedKey.text forIdentifier:@"PSK"];
  76.  
  77. // Load config from perference
  78. [_vpnManager loadFromPreferencesWithCompletionHandler:^(NSError *error) {
  79.  
  80. if (error) {
  81. NSLog(@"Load config failed [%@]", error.localizedDescription);
  82. return;
  83. }
  84.  
  85. NEVPNProtocolIKEv2 *p = (NEVPNProtocolIKEv2 *)_vpnManager.protocolConfiguration;
  86.  
  87. if (p) {
  88. // Protocol exists.
  89. // If you don't want to edit it, just return here.
  90. } else {
  91. // create a new one.
  92. p = [[NEVPNProtocolIKEv2 alloc] init];
  93. }
  94.  
  95. // config IPSec protocol
  96. p.username = username;
  97. p.serverAddress = server;
  98.  
  99. // Get password persistent reference from keychain
  100. // If password doesn't exist in keychain, should create it beforehand.
  101. // [self createKeychainValue:@"your_password" forIdentifier:@"VPN_PASSWORD"];
  102. p.passwordReference = [self searchKeychainCopyMatching:@"VPN_PASSWORD"];
  103.  
  104. // PSK
  105. p.authenticationMethod = NEVPNIKEAuthenticationMethodSharedSecret;
  106. // [self createKeychainValue:@"your_psk" forIdentifier:@"PSK"];
  107. p.sharedSecretReference = [self searchKeychainCopyMatching:@"PSK"];
  108.  
  109. /*
  110. // certificate
  111. p.identityData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"client" ofType:@"p12"]];
  112. p.identityDataPassword = @"[Your certificate import password]";
  113. */
  114.  
  115. p.localIdentifier = localIdnetifier;
  116. p.remoteIdentifier = remoteIdentifier;
  117.  
  118. p.useExtendedAuthentication = YES;
  119. p.disconnectOnSleep = NO;
  120.  
  121. _vpnManager.protocolConfiguration = p;
  122. _vpnManager.localizedDescription = @"IPSec IKEv2 Demo";
  123. _vpnManager.enabled = YES;
  124.  
  125. [_vpnManager saveToPreferencesWithCompletionHandler:^(NSError *error) {
  126. if (error) {
  127. NSLog(@"Save config failed [%@]", error.localizedDescription);
  128. }
  129. }];
  130. }];
  131. }
  132.  
  133. - (IBAction)changeVPNStatus:(id)sender
  134. {
  135. NEVPNStatus status = _vpnManager.connection.status;
  136. if (status == NEVPNStatusConnected
  137. || status == NEVPNStatusConnecting
  138. || status == NEVPNStatusReasserting) {
  139. [self disconnect];
  140. } else {
  141. [self connect];
  142. }
  143. }
  144.  
  145. - (void)connect {
  146. // Install profile
  147. [self installProfile];
  148.  
  149. NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
  150. [nc addObserver:self
  151. selector:@selector(vpnConfigDidChanged:)
  152. name:NEVPNConfigurationChangeNotification
  153. object:nil];
  154.  
  155. }
  156.  
  157. - (void)disconnect
  158. {
  159. [_vpnManager.connection stopVPNTunnel];
  160. }
  161.  
  162. - (void)vpnConfigDidChanged:(NSNotification *)notification
  163. {
  164. // TODO: Save configuration failed
  165. [self startConnecting];
  166. [[NSNotificationCenter defaultCenter] removeObserver:self
  167. name:NEVPNConfigurationChangeNotification
  168. object:nil];
  169. }
  170.  
  171. - (void)startConnecting
  172. {
  173. NSError *startError;
  174. [_vpnManager.connection startVPNTunnelAndReturnError:&startError];
  175. if (startError) {
  176. NSLog(@"Start VPN failed: [%@]", startError.localizedDescription);
  177. }
  178. }
  179.  
  180. - (void)vpnStatusDidChanged:(NSNotification *)notification
  181. {
  182. NEVPNStatus status = _vpnManager.connection.status;
  183. switch (status) {
  184. case NEVPNStatusConnected:
  185. _actionButton.enabled = YES;
  186. [_actionButton setTitle:@"Disconnect" forState:UIControlStateNormal];
  187. _activityIndicator.hidden = YES;
  188. break;
  189. case NEVPNStatusInvalid:
  190. case NEVPNStatusDisconnected:
  191. _actionButton.enabled = YES;
  192. [_actionButton setTitle:@"Connect" forState:UIControlStateNormal];
  193. _activityIndicator.hidden = YES;
  194. break;
  195. case NEVPNStatusConnecting:
  196. case NEVPNStatusReasserting:
  197. _actionButton.enabled = YES;
  198. [_actionButton setTitle:@"Connecting..." forState:UIControlStateNormal];
  199. _activityIndicator.hidden = NO;
  200. [_activityIndicator startAnimating];
  201. break;
  202. case NEVPNStatusDisconnecting:
  203. _actionButton.enabled = NO;
  204. [_actionButton setTitle:@"Disconnecting..." forState:UIControlStateDisabled];
  205. _activityIndicator.hidden = NO;
  206. [_activityIndicator startAnimating];
  207. break;
  208. default:
  209. break;
  210. }
  211. }
  212.  
  213. #pragma mark - KeyChain
  214.  
  215. static NSString * const serviceName = @"im.zorro.ipsec_demo.vpn_config";
  216.  
  217. - (NSMutableDictionary *)newSearchDictionary:(NSString *)identifier {
  218. NSMutableDictionary *searchDictionary = [[NSMutableDictionary alloc] init];
  219.  
  220. [searchDictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
  221.  
  222. NSData *encodedIdentifier = [identifier dataUsingEncoding:NSUTF8StringEncoding];
  223. [searchDictionary setObject:encodedIdentifier forKey:(__bridge id)kSecAttrGeneric];
  224. [searchDictionary setObject:encodedIdentifier forKey:(__bridge id)kSecAttrAccount];
  225. [searchDictionary setObject:serviceName forKey:(__bridge id)kSecAttrService];
  226.  
  227. return searchDictionary;
  228. }
  229.  
  230. - (NSData *)searchKeychainCopyMatching:(NSString *)identifier {
  231. NSMutableDictionary *searchDictionary = [self newSearchDictionary:identifier];
  232.  
  233. // Add search attributes
  234. [searchDictionary setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
  235.  
  236. // Add search return types
  237. // Must be persistent ref !!!!
  238. [searchDictionary setObject:@YES forKey:(__bridge id)kSecReturnPersistentRef];
  239.  
  240. CFTypeRef result = NULL;
  241. SecItemCopyMatching((__bridge CFDictionaryRef)searchDictionary, &result);
  242.  
  243. return (__bridge_transfer NSData *)result;
  244. }
  245.  
  246. - (BOOL)createKeychainValue:(NSString *)password forIdentifier:(NSString *)identifier {
  247. NSMutableDictionary *dictionary = [self newSearchDictionary:identifier];
  248.  
  249. OSStatus status = SecItemDelete((__bridge CFDictionaryRef)dictionary);
  250.  
  251. NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
  252. [dictionary setObject:passwordData forKey:(__bridge id)kSecValueData];
  253.  
  254. status = SecItemAdd((__bridge CFDictionaryRef)dictionary, NULL);
  255.  
  256. if (status == errSecSuccess) {
  257. return YES;
  258. }
  259. return NO;
  260. }
  261.  
  262. @end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement