NeVPNManager No VPN Shared Secret was provided error

Hi,


I'am new on objective c programming.

Depends on the related documents, I've tried to create IPSEC VPN and connect automatically from my application.

I've used below code to create and connect IPSEC VPN but it is giving "No VPN Shared Secret was provided" error.

If I try to add vpn configuration from my Iphone with same parameters it's connecting succesfully.

I spent 3 days to solve this issue but didn't find anything.


[[NEVPNManager sharedManager] setEnabled:YES];

[[NEVPNManager sharedManager] loadFromPreferencesWithCompletionHandler: ^(NSError *error) {

NEVPNProtocolIPSec *p = [[NEVPNProtocolIPSec alloc] init];

p.serverAddress =@"server";

p.authenticationMethod = NEVPNIKEAuthenticationMethodSharedSecret;

p.useExtendedAuthentication = YES;

NSString *secret = @"secretCode";

NSData *secretData = [secret dataUsingEncoding:NSUTF8StringEncoding];

p.sharedSecretReference=secretData;

p.localIdentifier=@"identifier";

p.username=@"username";

p.passwordReference=[[SSKeychain passwordForService:@"service" account:@"passwordReference"] dataUsingEncoding:NSUTF8StringEncoding];

p.disconnectOnSleep = NO;

[NEVPNManager sharedManager].protocolConfiguration=p;

NSMutableArray *rules = [[NSMutableArray alloc] init];

NEOnDemandRuleConnect *connectRule = [NEOnDemandRuleConnect new];

[rules addObject:connectRule];

[[NEVPNManager sharedManager] setOnDemandRules:rules];

[[NEVPNManager sharedManager] setLocalizedDescription:@"vpn"];

[[NEVPNManager sharedManager] setEnabled:YES];

[[NEVPNManager sharedManager] saveToPreferencesWithCompletionHandler: ^(NSError *error) {

NSLog(@"Save VPN to preference complete");

if (error) {

NSLog(@"Save error: %@", error);

     }

}];

NSError *startError; [[NEVPNManager sharedManager].connection startVPNTunnelAndReturnError:&startError];

if(startError) { NSLog(@"Start error: %@", startError.localizedDescription); }

Accepted Reply

I'am creating key chain like below and in saveToPreferencesWithCompletionHandler event I'am logging shared secret referance and it's seems ok.

NSString* newStr = [[NSString alloc] initWithData:p.sharedSecretReference encoding:NSUTF8StringEncoding];
NSLog(@"kod: %@",newStr);

I’m not sure I fully understand your code but the above snippet makes no sense.

sharedSecretReference
is meant to be a keychain persistent reference. It’s an NSData which, on current systems, contains 12 bytes of binary goo. For example:
(lldb) po p.sharedSecretReference
<67_65_6e_70 00_00_00_00 00_00_01_4b>

Note I added some underscores to avoid the ire of the DevForums spam checker.

There’s no way you can convert that to a string using

-initWithData:encoding:
. Which means that if your log statement is showing a string, your shared secret persistent reference is not a persistent reference.

Pasted in below is the code that I use to set up my keychain items in my NEVPNManager test app.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
- (NSData *)persistentReferenceForSavedPassword:(NSString *)password service:(NSString *)service account:(NSString *)account {
    NSData *        result;
    NSData *        passwordData;
    OSStatus        err;
    CFTypeRef      secResult;

    NSParameterAssert(password != nil);
    NSParameterAssert(service != nil);
    NSParameterAssert(account != nil);

    result = nil;

    passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];

    err = SecItemCopyMatching( (__bridge CFDictionaryRef) @{
        (__bridge id) kSecClass:                (__bridge id) kSecClassGenericPassword,
        (__bridge id) kSecAttrService:          service,
        (__bridge id) kSecAttrAccount:          account,
        (__bridge id) kSecReturnPersistentRef:  @YES,
        (__bridge id) kSecReturnData:          @YES
    }, &secResult);
    if (err == errSecSuccess) {
        NSDictionary *  resultDict;
        NSData *        currentPasswordData;

        resultDict = CFBridgingRelease( secResult );
        assert([resultDict isKindOfClass:[NSDictionary class]]);

        result = resultDict[ (__bridge NSString *) kSecValuePersistentRef ];
        assert([result isKindOfClass:[NSData class]]);

        currentPasswordData = resultDict[ (__bridge NSString *) kSecValueData ];
        assert([currentPasswordData isKindOfClass:[NSData class]]);

        if ( ! [passwordData isEqual:currentPasswordData] ) {
            err = SecItemUpdate( (__bridge CFDictionaryRef) @{
                (__bridge id) kSecClass:        (__bridge id) kSecClassGenericPassword,
                (__bridge id) kSecAttrService:  service,
                (__bridge id) kSecAttrAccount:  account,
            }, (__bridge CFDictionaryRef) @{
                (__bridge id) kSecValueData:    passwordData
            } );
            if (err != errSecSuccess) {
                NSLog(@"Error %d saving password (SecItemUpdate)", (int) err);
                result = nil;
            }
        }
    } else if (err == errSecItemNotFound) {
        err = SecItemAdd( (__bridge CFDictionaryRef) @{
            (__bridge id) kSecClass:                (__bridge id) kSecClassGenericPassword,
            (__bridge id) kSecAttrService:          service,
            (__bridge id) kSecAttrAccount:          account,
            (__bridge id) kSecValueData:            passwordData,
            (__bridge id) kSecReturnPersistentRef:  @YES
        }, &secResult);
        if (err == errSecSuccess) {
            result = CFBridgingRelease( secResult );
            assert([result isKindOfClass:[NSData class]]);
        } else {
            NSLog(@"Error %d saving password (SecItemAdd)", (int) err);
        }
    } else {
        NSLog(@"Error %d saving password (SecItemCopyMatching)", (int) err);
    }
    return result;
}

Replies

sharedSecretReference
is meant to be a persistent reference to the shared secret in the keychain (like the similarly-named
passwordReference
), not the shared secret itself.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks for answer but I've tried with a persistent referance in keychain before but it didn't work.


I'am creating key chain like below and in saveToPreferencesWithCompletionHandler event I'am logging shared secret referance and it's seems ok.



NSString* newStr = [[NSString alloc] initWithData:p.sharedSecretReference encoding:NSUTF8StringEncoding];

NSLog(@"kod: %@",newStr);



NSString *sharedSecret = @"mysharedsecret";


NSMutableDictionary *keychainItem = [NSMutableDictionary dictionary];


keychainItem[(__bridge id)kSecClass] = (__bridge id)kSecClassGenericPassword;

keychainItem[(__bridge id)kSecAttrAccessible] = (__bridge id)kSecAttrAccessibleAlways;

keychainItem[(__bridge id)kSecValueData] = sharedSecret;


What am i doing wrong ?

I'am creating key chain like below and in saveToPreferencesWithCompletionHandler event I'am logging shared secret referance and it's seems ok.

NSString* newStr = [[NSString alloc] initWithData:p.sharedSecretReference encoding:NSUTF8StringEncoding];
NSLog(@"kod: %@",newStr);

I’m not sure I fully understand your code but the above snippet makes no sense.

sharedSecretReference
is meant to be a keychain persistent reference. It’s an NSData which, on current systems, contains 12 bytes of binary goo. For example:
(lldb) po p.sharedSecretReference
<67_65_6e_70 00_00_00_00 00_00_01_4b>

Note I added some underscores to avoid the ire of the DevForums spam checker.

There’s no way you can convert that to a string using

-initWithData:encoding:
. Which means that if your log statement is showing a string, your shared secret persistent reference is not a persistent reference.

Pasted in below is the code that I use to set up my keychain items in my NEVPNManager test app.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"
- (NSData *)persistentReferenceForSavedPassword:(NSString *)password service:(NSString *)service account:(NSString *)account {
    NSData *        result;
    NSData *        passwordData;
    OSStatus        err;
    CFTypeRef      secResult;

    NSParameterAssert(password != nil);
    NSParameterAssert(service != nil);
    NSParameterAssert(account != nil);

    result = nil;

    passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];

    err = SecItemCopyMatching( (__bridge CFDictionaryRef) @{
        (__bridge id) kSecClass:                (__bridge id) kSecClassGenericPassword,
        (__bridge id) kSecAttrService:          service,
        (__bridge id) kSecAttrAccount:          account,
        (__bridge id) kSecReturnPersistentRef:  @YES,
        (__bridge id) kSecReturnData:          @YES
    }, &secResult);
    if (err == errSecSuccess) {
        NSDictionary *  resultDict;
        NSData *        currentPasswordData;

        resultDict = CFBridgingRelease( secResult );
        assert([resultDict isKindOfClass:[NSDictionary class]]);

        result = resultDict[ (__bridge NSString *) kSecValuePersistentRef ];
        assert([result isKindOfClass:[NSData class]]);

        currentPasswordData = resultDict[ (__bridge NSString *) kSecValueData ];
        assert([currentPasswordData isKindOfClass:[NSData class]]);

        if ( ! [passwordData isEqual:currentPasswordData] ) {
            err = SecItemUpdate( (__bridge CFDictionaryRef) @{
                (__bridge id) kSecClass:        (__bridge id) kSecClassGenericPassword,
                (__bridge id) kSecAttrService:  service,
                (__bridge id) kSecAttrAccount:  account,
            }, (__bridge CFDictionaryRef) @{
                (__bridge id) kSecValueData:    passwordData
            } );
            if (err != errSecSuccess) {
                NSLog(@"Error %d saving password (SecItemUpdate)", (int) err);
                result = nil;
            }
        }
    } else if (err == errSecItemNotFound) {
        err = SecItemAdd( (__bridge CFDictionaryRef) @{
            (__bridge id) kSecClass:                (__bridge id) kSecClassGenericPassword,
            (__bridge id) kSecAttrService:          service,
            (__bridge id) kSecAttrAccount:          account,
            (__bridge id) kSecValueData:            passwordData,
            (__bridge id) kSecReturnPersistentRef:  @YES
        }, &secResult);
        if (err == errSecSuccess) {
            result = CFBridgingRelease( secResult );
            assert([result isKindOfClass:[NSData class]]);
        } else {
            NSLog(@"Error %d saving password (SecItemAdd)", (int) err);
        }
    } else {
        NSLog(@"Error %d saving password (SecItemCopyMatching)", (int) err);
    }
    return result;
}

Thanks, it solved my problem.