how to set Authentication setting data? VPN Mac OS Programatically - objective-c

i am using this https://github.com/halo/macosvpn. Code run successfully and create new network but it's not showing Authentication Setting data which i Password e.g Shared Secret.
- (CFDictionaryRef) L2TPPPPConfig {
CFStringRef keys[4] = { NULL, NULL, NULL, NULL };
CFStringRef vals[4] = { NULL, NULL, NULL, NULL };
CFIndex count = 0;
keys[count] = kSCPropNetPPPCommRemoteAddress;
vals[count++] = (__bridge CFStringRef)self.endpoint;
keys[count] = kSCPropNetPPPAuthName;
vals[count++] = (__bridge CFStringRef)self.username;
keys[count] = kSCPropNetPPPAuthPassword;
vals[count++] = (__bridge CFStringRef)self.serviceID;
keys[count] = kSCPropNetPPPAuthPasswordEncryption;
vals[count++] = kSCValNetPPPAuthPasswordEncryptionKeychain;
return CFDictionaryCreate(NULL, (const void **)&keys, (const void **)&vals, count, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
Furthermore Server Address and Account Name set Successfully. i

These two lines look very suspicious:
keys[count] = kSCPropNetPPPAuthPassword;
vals[count++] = (__bridge CFStringRef)self.serviceID;
Shouldn't that second line be something like: "self.password"?
serviceID is something totally different than a password.

Related

How to Add a Cert to System.keychain Without SecKeychainCopyDomainDefault

As of MacOS 10.10 SecKeychainCopyDomainDefault was deprecated. The SecItemAdd key kSecUseKeychain is however not deprecated. kSecUseKeychain requires a SecKeychainRef as a value, but I do not see any non-deprecated way of obtaining one.
I need to add a CA to the System keychain. The following code is a working example when ran as root.
SecKeychainRef system;
OSStatus keychainError = SecKeychainCopyDomainDefault(kSecPreferencesDomainSystem, &system);
CFDataRef data = CFDataCreate(kCFAllocatorDefault, nsdataCert.bytes, nsdataCert.length);
SecCertificateRef test = SecCertificateCreateWithData(kCFAllocatorDefault, data);
const void *keys[] = { kSecClass, kSecAttrLabel, kSecValueRef, kSecUseKeychain};
const void *values[] = { kSecClassCertificate , #"Test Certificate", test, system};
CFDictionaryRef query = CFDictionaryCreate(kCFAllocatorDefau1lt, keys, values, 4, NULL, NULL);
int status = SecItemAdd ((CFDictionaryRef)query, NULL);
NSLog(#"status=%d", status);

Remove All trusted applications from a keychain item

I wrote the below code to add a generic password from my app. SecKeychainAddGenericPassword() adds the app as a trusted application in the keychain by design.
I want to remove my app from the list of trusted apps. I called SecKeychainItemSetAccess () to do that but I still see my app listed as a trusted app.
addgenericpassword(const std::string& service,const std::string& account,
const std::string& password) {
SecKeychainItemRef item_ref;
OSStatus status = SecKeychainAddGenericPassword(NULL,
service.length(),
service.data(),
account.length(),
account.data(),
password.length(),
password.data(),
&item_ref);
//Creating an secAccess object that has an empty trusted application list
//https://developer.apple.com/documentation/security/1393522-secaccesscreate?language=objc
CFArrayRef applicationList=CFArrayCreate (NULL,NULL,0,NULL);
SecAccessRef accessref;
CFStringRef description=CFStringCreateWithCString(NULL, "Generic description", kCFStringEncodingASCII);
status = SecAccessCreate(description,applicationList,&accessref);
//Set the access of a keychain item "item_ref".
status = SecKeychainItemSetAccess(item_ref,accessref);
CFRelease(item_ref);
CFRelease(accessref);
CFRelease(applicationList);
CFRelease(description);
return 0;
}
Update:
Changed description to match the service name. Still no luck
CFStringRef description=CFStringCreateWithCString(NULL, service.data(), kCFStringEncodingASCII);
I have been able to get the functionality I was looking for.I am not sure if this is the right method to do it though.
SecAccessRef accessref;
SecKeychainItemCopyAccess(item_ref, &accessref);
CFArrayRef aclList;
SecAccessCopyACLList(accessref, &aclList);
CFIndex count = CFArrayGetCount(aclList);
//Array with 0 Applications / Empty Array . Not the same as passing NULL
CFArrayRef zero_applications = CFArrayCreate(NULL, NULL, 0, NULL);
for (int i = 0; i < count; i++) {
SecACLRef acl = (SecACLRef) CFArrayGetValueAtIndex(aclList, i);
CFArrayRef applicationList;
CFStringRef description;
CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR promptSelector;
SecACLCopySimpleContents(acl, &applicationList, &description,
&promptSelector);
if (applicationList == NULL) {
continue;
}
CFIndex appCount = CFArrayGetCount(applicationList);
for (int j = 0; j < appCount; j++) {
status= SecACLSetContents(acl, zero_applications, description, 1);
break;
}
CFRelease(applicationList);
CFRelease(description);
}
// Set the modified copy to the item now
status = SecKeychainItemSetAccess(item_ref, accessref);

How verify account's password

I am asking account's password(password for login in mac) in my application. How can I verify password which is entered user?
I think something like it, but it doesn't work:
-(BOOL)authenticatePassword:(char *)password adminName:(char *)userName
{
BOOL retValue = NO;
OSStatus status,status1;
AuthorizationFlags flag;
AuthorizationItem items[2];
items[0].name = kAuthorizationEnvironmentPassword;
items[0].value = password;
items[0].valueLength = strlen(password);
items[0].flags = 0;
items[1].name = kAuthorizationEnvironmentUsername;
items[1].value = userName;
items[1].valueLength = strlen(userName);
items[1].flags = 0;
AuthorizationItemSet itemSet = {2,items};
status = AuthorizationCreate(NULL, &itemSet, kAuthorizationFlagDefaults, &authorization_);
if(status == errAuthorizationSuccess) {
AuthorizationRights rights = {2,&items};
//AuthorizationEnvironment kEnviroment = {2, items};
AuthorizationFlags flag1 = kAuthorizationFlagDefaults;
status1 = AuthorizationCopyRights(authorization_, &rights,NULL, flag1, NULL);
if(status1 == errAuthorizationSuccess) {
retValue = YES;
}
}
return retValue;
}
In the AuthorizationCopyRightscall the user credentials for the validation should be in the environment parameter (your commented out line) and the rights parameter really should contain the rights you would like to gain using this user credentials.
The rights can contain built in rights or user created rights, it's simpler to use a built in one because creating a user defined right requires admin privilege.
This code bellow will do the trick for you, just call AuthenticateForRight with the username/password parameter and it will try to gain the allow right that is a built in one in the authorizationDB and requires a valid user credential.
To use with a custom right you should once call SetupAuthorizationForRight with admin rights for the right be created in the authenticationDB, after that you can check the user credentials anytime via AuthenticateForRight as a normal user just pass the rightName param also you passed for SetupAuthorizationForRight first time.
// original code: https://developer.apple.com/library/mac/#technotes/tn2095/_index.html
// https://developer.apple.com/library/mac/documentation/Security/Conceptual/authorization_concepts/03authtasks/authtasks.html#//apple_ref/doc/uid/TP30000995-CH206-BCIGEHDI
bool SetupAuthorizationForRight(const char* rightName)
// Called as the application starts up. Creates a connection
// to Authorization Services and then makes sure that our
// right is defined.
{
OSStatus err;
// Connect to Authorization Services.
AuthorizationRef authorization = NULL;
err = AuthorizationCreate(NULL, NULL, 0, &authorization);
// Set up our rights.
if (err == noErr) {
// Check whether our right is already defined.
err = AuthorizationRightGet(rightName, NULL);
if (err == noErr) {
// A right already exists, either set up in advance by
// the system administrator or because this is the second
// time we've run. Either way, there's nothing more for
// us to do.
} else if (err == errAuthorizationDenied) {
// The right is not already defined. Let's create a
// right definition based on the custom (not canned) rule defined
// in the dictionary below.
// The system administrator can modify this right as they
// see fit.
CFStringRef keys[2] = {CFSTR("class"), CFSTR("group")};
CFStringRef values[2] = {CFSTR("user"), CFSTR("everyone")};
// Allow access for every user - all of local and remote users are in the
// 'everyone' group, so this is a safe rule
CFDictionaryRef aDict = CFDictionaryCreate(NULL, (const void **)keys, (const void **)values, 2,
&kCFCopyStringDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
err = AuthorizationRightSet(
authorization, // authRef
rightName, // rightName
aDict, // rightDefinition
CFSTR("Authenticate to log in via YourAppName."), // descriptionKey
NULL, // bundle, NULL indicates main
NULL // localeTableName,
); // NULL indicates "Localizable.strings"
if (aDict) {
CFRelease(aDict);
}
if (err != noErr) {
NSLog(#"Cannot set up authorization entry. Error: %d", err);
}
}
} else {
NSLog(#"Cannot open authorization database. Error: %d", err);
}
return (err == noErr);
}
bool AuthenticateForRight(const char* username, const char* password, const char* rightName)
{
OSStatus status = noErr;
if (rightName) {
if ((status = SetupAuthorizationForRight(rightName)) != noErr)
return false;
}
else
rightName = "allow"; // Allow right rule always defined by default and only authenticated users has this right
AuthorizationRef authRef = 0;
AuthorizationItem environment[2] = {{NULL, 0, NULL, 0}, {NULL, 0, NULL, 0}};
int numItems = 0;
if (username) {
AuthorizationItem item = { kAuthorizationEnvironmentUsername, strlen(username), (char*)username, 0 };
environment[numItems++] = item;
if (password) {
AuthorizationItem passItem = { kAuthorizationEnvironmentPassword, strlen(password), (char*)password, 0 };
environment[numItems++] = passItem;
}
}
AuthorizationItem right = {NULL, 0, NULL, 0};
right.name = rightName;
right.valueLength = 0;
right.value = 0;
AuthorizationRights rightSet = { 1, &right };
AuthorizationRights environmentSet = { static_cast<unsigned int>(numItems), environment };
status = AuthorizationCreate(NULL, &environmentSet, kAuthorizationFlagDefaults, &authRef);
if (status != noErr) {
NSLog(#"Cannot create authorization reference. Error: %d", status);
return false;
}
AuthorizationFlags flags = kAuthorizationFlagExtendRights | kAuthorizationFlagPreAuthorize; // | kAuthorizationFlagInteractionAllowed; <- Just for debugging, will display the OS auth dialog if needed!!!
status = AuthorizationCopyRights(authRef, &rightSet, &environmentSet, flags, NULL );
AuthorizationFree(authRef,kAuthorizationFlagDestroyRights);
return (status == noErr);
}
authorization services API will verify and prompt again if password is wrong.
Here is my code for your reference.
char *password = "password";
char *userName = "account";
AuthorizationRef authorization = NULL;
AuthorizationItem items[2];
items[0].name = kAuthorizationEnvironmentPassword;
items[0].value = password;
items[0].valueLength = strlen(password);
items[0].flags = 0;
items[1].name = kAuthorizationEnvironmentUsername;
items[1].value = userName;
items[1].valueLength = strlen(userName);
items[1].flags = 0;
AuthorizationRights rights = {2, items};
AuthorizationEnvironment enviroment = {2, items};
// Creates a new authorization reference and provides an option to authorize or preauthorize rights.
AuthorizationCreate(NULL, &enviroment, kAuthorizationFlagDefaults, &authorization);
AuthorizationFlags flag = kAuthorizationFlagDefaults| kAuthorizationFlagExtendRights;
OSStatus status = AuthorizationCopyRights(authorization, &rights, &enviroment, flag, NULL);
if(status == errAuthorizationSuccess)
{
NSLog(#"Pass");
}
else
{
NSLog(#"Fail");
}

SecKeychain load item

I want to store SMTP-Data from my Mac OSX application using the keychain. I read the Keychain Services Programming Guide of Apple and wrote this method to store the data:
- (BOOL)saveSMPTData
{
OSStatus err;
SecKeychainItemRef item = nil;
SecProtocolType protocol = kSecProtocolTypeSMTP;
const char *accessLabelUTF8 = [KEYCHAIN_NAME UTF8String];
const char *serverNameUTF8 = [self.serverName UTF8String];
const char *usernameUTF8 = [self.username UTF8String];
const char *passwordUTF8 = [self.password UTF8String];
SecAccessRef access = createAccess(KEYCHAIN_NAME);
SecKeychainAttribute attrs[] = {
{ kSecLabelItemAttr, (int)strlen(accessLabelUTF8), (char *)accessLabelUTF8 },
{ kSecAccountItemAttr, (int)strlen(usernameUTF8), (char *)usernameUTF8 },
{ kSecServerItemAttr, (int)strlen(serverNameUTF8), (char *)serverNameUTF8 },
{ kSecProtocolItemAttr, sizeof(SecProtocolType), (SecProtocolType *)&protocol }
};
SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]), attrs };
err = SecKeychainItemCreateFromContent(kSecInternetPasswordItemClass,
&attributes,
(int)strlen(passwordUTF8),
passwordUTF8,
NULL,
access,
&item);
if (access) CFRelease(access);
if (item) CFRelease(item);
return (err == noErr);
}
SecAccessRef createAccess(NSString *accessLabel)
{
OSStatus err;
SecAccessRef access = nil;
NSArray *trustedApplications = nil;
SecTrustedApplicationRef myself;
err = SecTrustedApplicationCreateFromPath(NULL, &myself);
trustedApplications = [NSArray arrayWithObjects:(__bridge id)myself, nil];
err = SecAccessCreate((__bridge CFStringRef)accessLabel,
(__bridge CFArrayRef)trustedApplications, &access);
if (err) return nil;
return access;
}
Of course I also want to load them. My first try looks like this:
- (BOOL)loadDataFromKeychain
{
uint32_t serverNameLength = 0;
const char *serverName = NULL;
uint32_t usernameLength = 0;
const char *username = NULL;
uint32_t passwordLength = 0;
void **password = NULL;
OSStatus err = SecKeychainFindInternetPassword(NULL,
serverNameLength, serverName,
0, NULL,
usernameLength, username,
0, NULL,
0, 0,
0,
&passwordLength, password,
NULL); // How do I get the ItemRef?
return (err == noErr);
}
But this does not work, and I think I know why not. I don’t know how to get the SecKeychainItemRef for the SecKeychainFindInternetPassword method.
Maybe anyone can help me?
Instead of declaring password a void **, declare it a void * and pass &password for the second-to-last parameter.
You probably don't need the SecKeychainItemRef for what you're trying to accomplish.
By the way, have you tried using Keychain Access to verify the items are getting into the keychain?

SecKeychainFindInternetPassword is not working

I have a problem with storing and reading from my keychain. First I tried to store use a char like this "account_name" in the Method SecKeychainFindInternetPassword for accountname and this runs. But now i would like to store a variable inside. But if i run this code the Programm cannot find the Keychain Item.
Please Help me.
(Sorry for my bad Englisch, i am a german student)
-(void)StorePasswordKeychain:(void*)password :(UInt32)passwordLength
{
char *userString;
userString = (char *)[_username UTF8String];
SecKeychainAddInternetPassword(
NULL,
StrLength("myserver.com"),
"myserver.com",
0,
NULL,
StrLength(userString),
userString,
0,
nil,
0,
kSecProtocolTypeHTTPS,
kSecAuthenticationTypeHTMLForm,
passwordLength,
password,
NULL
);
}
-(OSStatus)GetPasswordKeychain:(void *)passwordData :(UInt32 *)passwordLength
{
OSStatus status;
char *userString;
userString = (char *)[_username UTF8String];
status = SecKeychainFindInternetPassword(
NULL,
StrLength("myserver.com"),
"myserver.com",
0,
NULL,
StrLength(userString),
userString,
0,
nil,
0,
kSecProtocolTypeHTTPS,
kSecAuthenticationTypeHTMLForm,
passwordLength,
passwordData,
NULL
);
return status;
}
Two suggestions.. don't pass null into itemRef (the last arg). Then you'll have a pointer to the keychain you wish to modify.
Also, you should really check the error code to see if your add function worked.
OSStatus result = SecKeychainAddInternetPassword(
NULL,
StrLength("myserver.com"),
"myserver.com",
0,
NULL,
StrLength(userString),
userString,
0,
nil,
0,
kSecProtocolTypeHTTPS,
kSecAuthenticationTypeHTMLForm,
passwordLength,
password,
NULL
);
if(result != noErr){
NSLog(#"Error AddPassword result=:%d", result );
}
This is my sample program with the same code that you provided and it works fine.
int main(int argc, const char * argv[])
{
#autoreleasepool {
char *inputpassword = "topsecret";
UInt32 inputpassLength = strlen(inputpassword);
OSStatus status;
NSString *_username = #"account_name";
char *userString;
userString = (char *)[_username UTF8String];
status = SecKeychainAddInternetPassword(
NULL,
StrLength("myserver.com"),
"myserver.com",
0,
NULL,
StrLength(userString),
userString,
0,
nil,
0,
kSecProtocolTypeHTTPS,
kSecAuthenticationTypeHTMLForm,
inputpassLength,
inputpassword,
NULL
);
NSLog(#"Adding Status:%d", status);
UInt32 returnpasswordLength = 0;
char *passwordData;
status = SecKeychainFindInternetPassword(
NULL,
StrLength("myserver.com"),
"myserver.com",
0,
NULL,
StrLength(userString),
userString,
0,
nil,
0,
kSecProtocolTypeHTTPS,
kSecAuthenticationTypeHTMLForm,
&returnpasswordLength,
(void *)&passwordData,
NULL
);
NSLog(#"Retrieving status:%d", status);
NSLog(#"Password:%#", [[NSString alloc] initWithBytes:passwordData
length:returnpasswordLength
encoding:NSUTF8StringEncoding]);
}
return 0;
}