How can a Cocoa application add itself as a global login item? - cocoa

I tried
LSSharedFileListRef globalLoginItems = LSSharedFileListCreate(NULL, kLSSharedFileListGlobalLoginItems, NULL);
if (globalLoginItems) {
LSSharedFileListItemRef ourLoginItem = LSSharedFileListInsertItemURL(globalLoginItems,
kLSSharedFileListItemLast,
NULL, NULL,
(CFURLRef)[[NSBundle mainBundle] bundleURL],
NULL, NULL);
if (ourLoginItem) {
CFRelease(ourLoginItem);
} else {
NSLog(#"Could not insert ourselves as a global login item");
}
CFRelease(globalLoginItems);
} else {
NSLog(#"Could not get the global login items");
}
LSSharedFileListInsertItemURL() just returned NULL when I built and ran the application. Is there something else that I need to do? Some kind of authorization?
NOTE: The use-case here is for global login items, that is using kLSSharedFileListGlobalLoginItems and not kLSSharedFileListSessionLoginItems.

I got this working. All I had to do was add these lines before I insert the app into the login items:
AuthorizationRef auth = NULL;
AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &auth);
LSSharedFileListSetAuthorization(globalLoginItems, auth);
The docs for LSSharedFileListSetAuthorization say that we have to get the right system.global-login-items for this, but it worked nevertheless!
But this will fail if the user is not an administrator. For it to work then too, you'll have to do this:
AuthorizationItem right[1] = {{"system.global-login-items.", 0, NULL, 0}};
AuthorizationRights setOfRights = {1, right};
AuthorizationRef auth = NULL;
AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &auth);
AuthorizationCopyRights(auth, &setOfRights, kAuthorizationEmptyEnvironment,
(kAuthorizationFlagDefaults
| kAuthorizationFlagInteractionAllowed
| kAuthorizationFlagExtendRights), NULL);
It's also advisable to refer to the docs for details.

This works for me:
NSString * appPath = [[NSBundle mainBundle] bundlePath];
// This will retrieve the path for the application
CFURLRef url = (CFURLRef)[NSURL fileURLWithPath:appPath];
// Create a reference to the shared file list.
// We are adding it to the current user only.
// If we want to add it all users, use
// kLSSharedFileListGlobalLoginItems instead of
//kLSSharedFileListSessionLoginItems
LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL);
if (loginItems) {
//Insert an item to the list.
LSSharedFileListItemRef item = LSSharedFileListInsertItemURL(loginItems,kLSSharedFileListItemLast, NULL, NULL,url, NULL, NULL);
if (item){
CFRelease(item);
}
}
CFRelease(loginItems);

NSString * appPath = [[NSBundle mainBundle] bundlePath];
// This will retrieve the path for the application
CFURLRef url = (CFURLRef)[NSURL fileURLWithPath:appPath];
LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListGlobalLoginItems, NULL);
if (loginItems) {
//Insert an item to the list.
LSSharedFileListItemRef item = LSSharedFileListInsertItemURL(loginItems,kLSSharedFileListItemLast, NULL, NULL,url, NULL, NULL);
if (item){
CFRelease(item);
}
}
CFRelease(loginItems);
Doesn't work this code? I replaced kLSSharedFileListSessionLoginItems with kLSSharedFileListGlobalLoginItems

Related

OS X Application How to get allocation blocks(cluster size) of a volume

I want to get size (in bytes) of allocation blocks of a removable volume.
In my Macos application, I use FSGetVolumeInfo method to get FSVolumeInfo object.
In FSVolumeInfo object, attribute "blockSize" is the right one.
However, method FSGetVolumeInfo is deprecated after Macos10.8.
Is there any function to replace?
Below is sample code with FSVolumeInfo :
const char* path = "/Volumes/Untitled";
FSCatalogInfo volCatalogInfo;
FSVolumeRefNum realVolRefNum;
FSVolumeInfo myVolumeinfo;
if ('\0' != path[0]) {
CFStringRef pathStr = CFStringCreateWithCString(kCFAllocatorDefault, path, kCFStringEncodingUTF8);
CFURLRef volumePath = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, pathStr, kCFURLPOSIXPathStyle, false);
FSRef volumeRef;
if (CFURLGetFSRef(volumePath, &volumeRef)) {
OSStatus err = FSGetCatalogInfo(&volumeRef, kFSCatInfoVolume, &volCatalogInfo, NULL, NULL, NULL);
if (noErr == err) {
FSVolumeRefNum volRefNum = volCatalogInfo.volume;
err = FSGetVolumeInfo(volRefNum, 0, &realVolRefNum, kFSVolInfoGettableInfo, &myVolumeinfo, NULL, NULL);
if (noErr == err) {
printf("get volume info success!");
}
}
}
}
I would look into standard c function calls I think, statvfs() does what you want.

Possible to programatically installed 'Untrusted Certificate' or 'P12' file in Keychain Access with 'Always Trust '?

I am new to the Keychain Access from mac.
I just have to installed Untrused Certificate or P12 file in keychain access programatically in Mac as 'Trust Always'.
I am using below code :
-(void)addCertificate
{
NSData *PKCS12Data = [[NSData alloc] initWithContentsOfFile:
#"/Users/Desktop/Certificates.p12"];
CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;
CFStringRef password = (CFStringRef)#"";
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };
CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys,
values, 1, NULL, NULL);
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
SecCertificateRef rootCert =
SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)
inPKCS12Data);
OSStatus securityError = SecPKCS12Import(inPKCS12Data,
optionsDictionary, &items);
if (securityError == 0) {
NSLog(#" *** Certificate install Success ***");
} else {
NSLog(#" *** Certificate install Failure ***");
}
OSStatus err = noErr;
CFTypeRef result;
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
(__bridge id)kSecClassCertificate, kSecClass,
rootCert, kSecValueRef,
nil];
err = SecItemAdd((__bridge CFDictionaryRef)dict, &result);
if(err!=noErr) NSLog(#"error while importing");
if (err==errSecDuplicateItem) NSLog(#"Cert already installed");
NSLog(#":%i",(int)err);
assert(err==noErr||err==errSecDuplicateItem);
// accept no errors other than duplicate
err = noErr;
SecTrustRef trust;
err = SecTrustCreateWithCertificates(rootCert,
SecPolicyCreateBasicX509() ,&trust);
assert(err==noErr);
err = noErr;
CFMutableArrayRef newAnchorArray =
CFArrayCreateMutable(kCFAllocatorDefault,0,&kCFTypeArrayCallBacks);
CFArrayAppendValue(newAnchorArray,rootCert);
err = SecTrustSetAnchorCertificates(trust, newAnchorArray);
assert(err==noErr);
SecTrustResultType trustResult;
err=SecTrustEvaluate(trust,&trustResult);
assert(err==noErr);
rootCert=nil; // Done with the policy object
}
By using this code we are adding certificate only
Please help me to out from this...

How to get attributes from SecKeyRef without Password dialog?

I need to get info about private kSecAttrKeyType, kSecAttrApplicationLabel, kSecAttrCanSign, kSecAttrCanDecrypt, kSecAttrCanUnwrap, kSecAttrIsExtractable
But I've got System password dialog on SecKeyCopyAttributes using
Is there any way to get this public info without System password dialog?
I tried to get some public info from public key. But I've got the same System dialog on SecKeyCopyPublicKey
It's possible to do via kSecReturnAttributes parameter of SecItemCopyMatching function
Here is C++ example which returns attributes for each key in keychain
CFMutableDictionaryRef matchAttr = CFDictionaryCreateMutable(kCFAllocatorDefault,
0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
CFDictionaryAddValue(matchAttr, kSecClass, kSecClassKey);
CFDictionaryAddValue(matchAttr, kSecMatchLimit, kSecMatchLimitAll);
CFDictionaryAddValue(matchAttr, kSecReturnAttributes, kCFBooleanTrue);
CFArrayRef result;
OSStatus status = SecItemCopyMatching(matchAttr, (CFTypeRef*)&result);
if (status == kCCSuccess) {
CFIndex arrayCount = CFArrayGetCount(result);
for (CFIndex index = 0; index < arrayCount; index++) {
CFShow(CFArrayGetValueAtIndex(result, index));
}
}

How to create certificate choosing window like one in Safari?

I was looking for a way to create a window like that one in my program, but I haven't found any implementation of that. All I can do for now is get all certificates from keychain, but I can't get a cert in pem or der format. It is needed to supply certificate to a particular site.
- (void)logMessageForStatus:(OSStatus)status
functionName:(NSString *)functionName
{
CFStringRef errorMessage;
errorMessage = SecCopyErrorMessageString(status, NULL);
NSLog(#"error after %#: %#", functionName, (__bridge NSString *)errorMessage);
CFRelease(errorMessage);
}
- (void)listCertificates
{
OSStatus status;
SecKeychainSearchRef search = NULL;
// The first argument being NULL indicates the user's current keychain list
status = SecKeychainSearchCreateFromAttributes(NULL,
kSecCertificateItemClass, NULL, &search);
if (status != errSecSuccess) {
[self logMessageForStatus:status
functionName:#"SecKeychainSearchCreateFromAttributes()"];
return;
}
SecKeychainItemRef searchItem = NULL;
while (SecKeychainSearchCopyNext(search, &searchItem) != errSecItemNotFound) {
SecKeychainAttributeList attrList;
CSSM_DATA certData;
attrList.count = 0;
attrList.attr = NULL;
status = SecKeychainItemCopyContent(searchItem, NULL, &attrList,
(UInt32 *)(&certData.Length),
(void **)(&certData.Data));
if (status != errSecSuccess) {
[self logMessageForStatus:status
functionName:#"SecKeychainItemCopyContent()"];
CFRelease(searchItem);
continue;
}
// At this point you should have a valid CSSM_DATA structure
// representing the certificate
SecCertificateRef certificate;
status = SecCertificateCreateFromData(&certData, CSSM_CERT_X_509v3,
CSSM_CERT_ENCODING_BER, &certificate);
if (status != errSecSuccess) {
[self logMessageForStatus:status
functionName:#"SecCertificateCreateFromData()"];
SecKeychainItemFreeContent(&attrList, certData.Data);
CFRelease(searchItem);
continue;
}
// Do whatever you want to do with the certificate
// For instance, print its common name (if there's one)
CFStringRef commonName = NULL;
CFErrorRef err = NULL;
///CFArrayRef arr = NULL;
SecCertificateCopyCommonName(certificate, &commonName);
certs = SecCertificateCopyValues(certificate, NULL, &err);
//NSLog(#"common name = %#", (__bridge NSString *)commonName);
//NSLog(#"data = %#", (__bridge NSArray *)arr);
//certs = arr;
if (commonName) CFRelease(commonName);
//if (arr) CFRelease(arr);
SecKeychainItemFreeContent(&attrList, certData.Data);
CFRelease(searchItem);
}
CFRelease(search);
}
example
Is there any standard api to call such window? Or maybe there is some library? And how can I get der data from SecCertificateRef.
Thank you in advance!

get disk number(s) before getting bsdName

I have just encountered one problem, I can get the bsdName with below code lines but if there are two partitions in a USB flash disk, then I can only get the last bsdName, can someone tell me how do I get all the bsdName from the USB drive? actually I would like to get the volume name of each partition... thanks in advance
CFStringRef bsdName = ( CFStringRef ) IORegistryEntrySearchCFProperty ( usbDevice,
kIOServicePlane,
CFSTR ( kIOBSDNameKey ),
kCFAllocatorDefault,
kIORegistryIterateRecursively );
NSLog(#"bsdName=%#",bsdName);
volumeName = deviceNameWithMountPath((NSString*)bsdName);
//find_hid_device(usbDevice);
NSLog(#"volume Name=%#",volumeName);
NSString *mediaType = FindWholeMedia(usbDevice);
NSLog(#"media type = %#",mediaType);
//CFRelease(bsdName);
// Done with this USB device; release the reference added by IOIteratorNext
kr = IOObjectRelease(usbDevice);
}
}
NSString *deviceNameWithMountPath(NSString *mountPath)
{
DASessionRef session = NULL;
DADiskRef disk = NULL;
CFDictionaryRef dd = NULL;
CFTypeRef val = nil;
session = DASessionCreate(kCFAllocatorDefault);
if (!session) {
NSLog(#"Can't create DiskArb session");
return nil;
}
// DASessionScheduleWithRunLoop(session,
// CFRunLoopGetCurrent(),
// kCFRunLoopDefaultMode);
//
// DARegisterDiskAppearedCallback(session, NULL, DiskAppeared, NULL);
disk = DADiskCreateFromBSDName(kCFAllocatorDefault, session, [mountPath UTF8String]);
if (!disk) {
NSLog(#"DADiskCreateFromBSDName(%s) failed", [mountPath UTF8String]);
return nil;
}
dd = DADiskCopyDescription(disk);
if (!dd) {
NSLog(#"DADiskCopyDescription(%s) failed", [mountPath UTF8String]);
return nil;
}
CFDictionaryGetValueIfPresent(dd, (kDADiskDescriptionVolumeNameKey), &val);
DiskAppeared(disk, NULL);
CFRelease(disk);
CFRelease(session);
return (NSString *)val;
}

Resources