< Previous PageNext Page > Hide TOC

Keychain Services Tasks for Mac OS X

This chapter describes and illustrates the use of basic Keychain Services functions in Mac OS X. For the use of Keychain Services in iPhone OS, see “iPhone OS Keychain Services Tasks.”

The functions described in this chapter enable you to:

“Keychain Services Concepts” provides an introduction to the concepts and terminology of Keychain Services. For detailed information about all Keychain Services functions, see Keychain Services Reference.

In this section:

Adding Simple Keychain Services to Your Application
Advanced Topics


Adding Simple Keychain Services to Your Application

Most applications need to use Keychain Services only to add a new password to a keychain or retrieve a password when needed. Keychain Services provides the following pairs of functions for accomplishing these tasks:

You use Internet passwords for accessing servers and websites over the Internet, and generic passwords for any other password-protected service (such as a database or scheduling application). AppleShare passwords (that is, keychain items with a class code of kSecAppleSharePasswordItemClass) are stored as generic passwords.

Note: AppleShare passwords created with the Keychain Manager function KCAddAppleSharePassword are stored as Internet password items. You can use the SecKeychainAddInternetPassword function to store an AppleShare password, but it will appear in the Keychain Access utility as an Internet password. To create a keychain item with a class code of kSecAppleSharePasswordItemClass, you must use the lower-level API described in Keychain Services Reference.

The “find” functions retrieve information (attributes or secure data) from an item in the keychain. The “add” functions add an item to a keychain. These functions call other Keychain Services functions to accomplish their tasks. Because Keychain Services allocates the buffers in which the item data and attributes are returned, you must call SecKeychainItemFreeContent to free these buffers after using one of the find functions to retrieve attributes or secure data from a keychain item. (If Keychain Services does not find the item or fails to return any data for some other reason, it does not allocate any buffers and you should not call the SecKeychainItemFreeContent function.)

Figure 2-1 shows a flowchart of how an application might use these functions to gain access to an Internet FTP server.


Figure 2-1  Accessing an Internet server using Mac OS X Keychain Services

Accessing an Internet server using Keychain Services

The user of the application starts by selecting a File Transfer Protocol (FTP) server. The application calls SecKeychainFindInternetPassword, passing it attributes that identify the service and the user to seek. If the password is on the keychain, the function returns the password to the application, which sends it to the FTP server to authenticate the user. The application then calls SecKeychainItemFreeContent to free the data buffer allocated for the password (note that you should not call this function if no data is returned). If the authentication succeeds, the routine is finished. If the authentication fails, the application displays a dialog to request the user name and password.

If the password is not on the keychain, then SecKeychainFindInternetPassword returns the errSecItemNotFound result code. In this case as well, the application displays a dialog to request the user name and password. (This dialog should also include a Cancel button, but that choice was omitted from the figure to keep the flowchart from becoming overly complex.)

Having obtained the password from the user, the application proceeds to authenticate the user to the FTP server. When the authentication has succeeded, the application can assume that the information entered by the user was valid. The application then displays another dialog asking the user whether to save the password on the keychain. If the user selects No, then the routine is finished. If the user selects Yes, then the application calls the SecKeychainAddInternetPassword function (if this is a new keychain item), or the SecKeychainItemModifyAttributesAndData function (to update an existing keychain item) before ending the routine.

If there is no keychain, the SecKeychainFindInternetPassword or SecKeychainAddInternetPassword function displays a dialog allowing the user to “reset to defaults” (see Figure 1-5), which creates a new keychain named login.keychain with the user’s login account password. If the keychain is locked, the function displays a dialog requesting the user to enter a password to unlock the keychain (Figure 1-6). The user can cancel the operation at this time as well.

“Getting and setting passwords in Mac OS X Keychain Services” shows how a typical application might use Keychain Services functions to get and set passwords for generic items. You can get and set keychain item attributes (such as user name or service name) using these same functions; see Listing 2-2 for an example.

Listing 2-1  Getting and setting passwords in Mac OS X Keychain Services

#include <CoreFoundation/CoreFoundation.h>
#include <Security/Security.h>
#include <CoreServices/CoreServices.h>
 
//Call SecKeychainAddGenericPassword to add a new password to the keychain:
OSStatus StorePasswordKeychain (void* password,UInt32 passwordLength)
{
 OSStatus status;
 status = SecKeychainAddGenericPassword (
                NULL,            // default keychain
                10,              // length of service name
                "SurfWriter",    // service name
                10,              // length of account name
                "MyUserAcct",    // account name
                passwordLength,  // length of password
                password,        // pointer to password data
                NULL             // the item reference
    );
    return (status);
 }
 
//Call SecKeychainFindGenericPassword to get a password from the keychain:
OSStatus GetPasswordKeychain (void *passwordData,UInt32 *passwordLength,
                                                SecKeychainItemRef *itemRef)
{
 OSStatus status1 ;
 
 
 status1 = SecKeychainFindGenericPassword (
                 NULL,           // default keychain
                 10,             // length of service name
                 "SurfWriter",   // service name
                 10,             // length of account name
                 "MyUserAcct",   // account name
                 passwordLength,  // length of password
                 passwordData,   // pointer to password data
                 itemRef         // the item reference
    );
     return (status1);
 }
 
//Call SecKeychainItemModifyAttributesAndData to change the password for
// an item already in the keychain:
OSStatus ChangePasswordKeychain (SecKeychainItemRef itemRef)
{
    OSStatus status;
    void * password = "myNewP4sSw0rD";
    UInt32 passwordLength = strlen(password);
 
 status = SecKeychainItemModifyAttributesAndData (
                 itemRef,         // the item reference
                 NULL,            // no change to attributes
                 passwordLength,  // length of password
                 password         // pointer to password data
    );
     return (status);
 }
 
 
/* ********************************************************************** */
 
int main (int argc, const char * argv[]) {
    OSStatus status;
    OSStatus status1;
 
     void * myPassword = "myP4sSw0rD";
     UInt32 myPasswordLength = strlen(myPassword);
 
     void *passwordData = nil; // will be allocated and filled in by
                               //SecKeychainFindGenericPassword
     SecKeychainItemRef itemRef = nil;
     UInt32 passwordLength = nil;
 
    status1 = GetPasswordKeychain (&passwordData,&passwordLength,&itemRef);  //Call
                                                //SecKeychainFindGenericPassword
        if (status1 == noErr)       //If call was successful, authenticate user
                                    //and continue.
        {
        //Free the data allocated by SecKeychainFindGenericPassword:
    status = SecKeychainItemFreeContent (
                 NULL,           //No attribute data to release
                 passwordData    //Release data buffer allocated by
                 //SecKeychainFindGenericPassword
    );
 }
 
    if (status1 == errSecItemNotFound) { //Is password on keychain?
    /*
    If password is not on keychain, display dialog to prompt user for
    name and password.
    Authenticate user.  If unsuccessful, prompt user again for name and password.
    If successful, ask user whether to store new password on keychain; if no, return.
    If yes, store password:
    */
    status = StorePasswordKeychain (myPassword,myPasswordLength); //Call
                                                      // SecKeychainAddGenericPassword
    return (status);
    }
 
    /*
    If password is on keychain, authenticate user.
    If authentication succeeds, return.
    If authentication fails, prompt user for new user name and password and
     authenticate again.
    If unsuccessful, prompt again.
    If successful, ask whether to update keychain with new information.  If no, return.
    If yes, store new information:
    */
    status = ChangePasswordKeychain (itemRef);  //Call
                                            // SecKeychainItemModifyAttributesAndData
    if (itemRef) CFRelease(itemRef);
    return (status);
 
 }

This example follows the same general sequence that was shown in Figure 2-1; however, unlike the figure, the example illustrates the use of generic passwords rather than Internet passwords.

Important: You should not cache passwords, because the user can change them using Keychain Access or another program and the data may no longer be valid. In addition, the long-term storage of passwords by applications negates the value of the keychain.

Although the example in “Getting and setting passwords in Mac OS X Keychain Services” is written in procedural C, you can call these same functions using Objective C. Listing 2-2 shows how you might create an Internet password item if you wanted some custom attribute values. Note that attribute strings should all be encoded in UTF-8 format.

Advanced Topics

Most applications need only the Keychain Services functions described in “Adding Simple Keychain Services to Your Application.” However, in certain circumstances you might want to use some of the other functions provided by Keychain Services. For example, you might want to display a custom label for your application in the Keychain Access utility. Or, if you are writing a server, you might want to disable the automatic display of dialogs and instead take care of unlocking the keychain within your application.

Creating a Custom Keychain Item

This section discusses how to create a keychain item if you want lower-level control than is provided by SecKeychainAddInternetPassword or SecKeychainAddGenericPassword. For example, you might want to have the Keychain Access application display a custom label for your keychain item or you might want to specify more than one trusted application that can access the item. Specifically, this section illustrates the use of the SecKeychainItemCreateFromContent function to create a keychain item and the SecAccessCreate function to set up an access list. For more details about these and other low-level functions, see Keychain Services Reference.

When you use SecKeychainAddInternetPassword or SecKeychainAddGenericPassword, the function creates a label for the keychain item automatically. For an Internet password, it uses the URL, minus the scheme name, colon, and leading slashes. For example, the label (displayed in the Name field in Keychain Access) for a new Internet password for the URL http://www.apple.com becomes www.apple.com. For a generic password, the function uses the service attribute for the label. In both cases, the Name and Where fields in Keychain access are identical. If you want a unique name for the keychain item that is different from the URL or service name, you can specify the label (kSecLabelItemAttr) attribute when you call SecKeychainItemCreateFromContent.

The SecKeychainAddInternetPassword and SecKeychainAddGenericPassword functions create an initial access list for you. This default access list includes only one trusted application (that is, one application that can access the keychain item whenever the keychain is unlocked), namely the application that created the keychain item. The SecKeychainItemCreateFromContent function accepts an access list as input. However, if you pass NULL, this function creates an access list consisting of the single application calling the function. Therefore, you must call the SecAccessCreate function before calling the SecKeychainItemCreateFromContent function if you want an access list with more than one trusted application. Alternatively, you can alter the access list of an existing keychain item; see “Modifying the Access List of an Existing Keychain Item.”

Listing 2-2 illustrates the creation of an Internet keychain item with a custom label and an access list that includes two trusted applications. This listing also illustrates the use of the Keychain Services API from an Objective-C application.

Listing 2-2  Creating a keychain item with custom attributes

#import <Cocoa/Cocoa.h>
 
#include <Security/SecKeychain.h>
#include <Security/SecKeychainItem.h>
#include <Security/SecAccess.h>
#include <Security/SecTrustedApplication.h>
#include <Security/SecACL.h>
 
SecAccessRef createAccess(NSString *accessLabel)
{
    OSStatus err;
    SecAccessRef access=nil;
    NSArray *trustedApplications=nil;
 
    //Make an exception list of trusted applications; that is,
    // applications that are allowed to access the item without
    // requiring user confirmation:
    SecTrustedApplicationRef myself, someOther;
//Create trusted application references; see SecTrustedApplications.h:
    err = SecTrustedApplicationCreateFromPath(NULL, &myself);
    err = SecTrustedApplicationCreateFromPath("/Applications/Mail.app",
                                                            &someOther);
    trustedApplications = [NSArray arrayWithObjects:(id)myself,
                                                    (id)someOther, nil];
//Create an access object:
    err = SecAccessCreate((CFStringRef)accessLabel,
                            (CFArrayRef)trustedApplications, &access);
    if (err) return nil;
 
    return access;
}
 
 
void addInternetPassword(NSString *password, NSString *account,
                    NSString *server, NSString *itemLabel, NSString *path,
                    SecProtocolType protocol, int port)
{
    OSStatus err;
    SecKeychainItemRef item = nil;
    const char *pathUTF8 = [path UTF8String];
    const char *serverUTF8 = [server UTF8String];
    const char *accountUTF8 = [account UTF8String];
    const char *passwordUTF8 = [password UTF8String];
    const char *itemLabelUTF8 = [itemLabel UTF8String];
 
    //Create initial access control settings for the item:
    SecAccessRef access = createAccess(itemLabel);
 
    //Following is the lower-level equivalent to the
    // SecKeychainAddInternetPassword function:
 
    //Set up the attribute vector (each attribute consists
    // of {tag, length, pointer}):
    SecKeychainAttribute attrs[] = {
        { kSecLabelItemAttr, strlen(itemLabelUTF8), (char *)itemLabelUTF8 },
        { kSecAccountItemAttr, strlen(accountUTF8), (char *)accountUTF8 },
        { kSecServerItemAttr, strlen(serverUTF8), (char *)serverUTF8 },
        { kSecPortItemAttr, sizeof(int), (int *)&port },
        { kSecProtocolItemAttr, sizeof(SecProtocolType),
                                        (SecProtocolType *)&protocol },
        { kSecPathItemAttr, strlen(pathUTF8), (char *)pathUTF8 }
    };
    SecKeychainAttributeList attributes = { sizeof(attrs) / sizeof(attrs[0]),
                                                                attrs };
 
    err = SecKeychainItemCreateFromContent(
        kSecInternetPasswordItemClass,
        &attributes,
        strlen(passwordUTF8),
        passwordUTF8,
        NULL, // use the default keychain
        access,
        &item);
 
    if (access) CFRelease(access);
    if (item) CFRelease(item);
}
 
 
int main(int argc, const char *argv[])
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 
    //Add an example password to the keychain:
    addInternetPassword(@"sample password", @"sample account",
        @"samplehost.apple.com", @"sampleName", @"cgi-bin/bogus/testpath",
                                            kSecProtocolTypeHTTP, 8080);
 
    [pool release];
 
    return 0;
}

Modifying the Access List of an Existing Keychain Item

By default, a keychain item’s access list contains only the application that created the keychain item. Listing 2-2 illustrates the creation of an Internet keychain item with an access list that includes two trusted applications. Listing 2-3 illustrates how to modify an existing keychain item. The listing finds a specific keychain item, extracts the access object, including the list of trusted applications, authorization tags, and other information (see “ACL Entries”), adds a trusted application to the list, reconstitutes the access object, and writes the new access object back to the keychain item. Although this sample illustrates modifying the list of trusted applications, you can use a similar sequence to modify any of the information in the access object—for example, to add or remove an authorization tag.

Listing 2-3 starts by calling the SecKeychainSearchCreateFromAttributes function to create a search reference. In this example, the code looks for a keychain item by its label (as seen in the Keychain Access application); you can search for other attributes, however, such as modification date. Using this search reference, the sample calls SecKeychainSearchCopyNext to find the keychain item.

The listing next calls SecKeychainItemCopyAccess to retrieve the keychain item’s access object. As discussed in “Keychain Access Controls,” the access object includes one or more ACL entries. The listing calls the SecAccessCopySelectedACLList function and passes it an authorization tag value of CSSM_ACL_AUTHORIZATION_DECRYPT. This authorization tag is one of the tags normally associated with the access list used for sensitive operations and is the list displayed by the Keychain Access application. To retrieve all the ACL entries for an access object, use the SecAccessCopyACLList function instead.

The SecAccessCopySelectedACLList function returns a CFArrayRef object containing all of the ACL entries that meet the selection criteria. In this case, the code is assuming that there should be only one ACL entry that employs the CSSM_ACL_AUTHORIZATION_DECRYPT tag. The listing calls the CFArrayGetValues function to create a C array of SecACLRef objects from the CFArrayRef and then calls the SecACLCopySimpleContents function, passing it the first (and presumably only) item in the array. The SecACLCopySimpleContents function also retrieves a CFArrayRef containing the list of trusted applications, the keychain item description string, and the prompt selector flag. These values are needed in order to reconstitute the ACL entry after adding a trusted application to the list.

Next, the listing uses the CFArrayGetValues function again, this time to extract the array of trusted applications from the CFArrayRef. The listing calls the SecTrustedApplicationCreateFromPath function to create a new trusted application object, appends the new application to the list, and calls CFArrayCreate to create a new CFArrayRef.

Before adding a new ACL entry to the access object, the listing calls the SecACLGetAuthorizations function to get the list of authorization tags from the old access object. Then, having extracted all the information from the old ACL entry, the code calls the SecACLRemove function to remove the old ACL entry from the access object. The listing then calls the SecACLCreateFromSimpleContents function to create a new ACL entry for the access object. This function automatically adds the entry to the access object; there is no separate call for that purpose. The new ACL entry has only the default authorization list, however, so the listing calls the SecACLSetAuthorizations function, passing in the authorization list extracted from the old ACL entry.

The access object is now complete, with the new ACL entry containing all of the trusted applications in the old entry plus the new one added here. Only two steps remain: First, the listing calls the SecKeychainItemSetAccess function to replace the access object in the keychain item with the new access object; then the listing calls the CFRelease function for each core foundation object that is no longer needed, in order to release the memory.

Note that this sample routine causes the user to be prompted twice for permission: once when the old ACL entry is deleted from the access object, and once when the new access object is written to the keychain item.

Listing 2-3  Modifying a keychain item access list

#include <CoreFoundation/CoreFoundation.h>
#include <Security/Security.h>
#include <CoreServices/CoreServices.h>
 
//Call SecKeychainSearchCreateFromAttributes to get a search reference:
OSStatus GetSearchRef (SecKeychainAttributeList *attrList,
                         SecKeychainSearchRef *searchReference)
{
    OSStatus status;
 
    status = SecKeychainSearchCreateFromAttributes (
        NULL,                           // default keychain search list
        kSecInternetPasswordItemClass,  // search for an Internet password
        attrList,                       // match attributes
        searchReference                 // search reference to return
        );
 
    return (status);
 
}
 
//Call SecKeychainSearchCopyNext to find an item on the keychain:
OSStatus FindItem (SecKeychainSearchRef searchReference,
                                SecKeychainItemRef *itemRef)
{
    OSStatus status1 ;
 
    status1 = SecKeychainSearchCopyNext (
        searchReference,                    // search reference
        itemRef                             // the item reference
        );
 
    return (status1);
}
 
//Get an ACL out of a CFArray:
SecACLRef GetACL (CFIndex numACLs, CFArrayRef ACLList,
                CFArrayRef *applicationList, CFStringRef *description,
                CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR *promptSelector)
{
    OSStatus status;
    SecACLRef aclArray[numACLs];
    CFRange aclRange;
    aclRange.location = (CFIndex) 0;
    aclRange.length = numACLs;
 
    CFArrayGetValues (
        ACLList,            // the CFArrayRef we got from the keychain item
        aclRange,           // the size of the array
        (void *) aclArray   // a SecACLRef containing the values from the
                            // CFArrayRef
        );
    //Extract the application list from the ACL.
    //Because we limited our search to ACLs used for decryption, we
    // expect only one ACL for this item. Therefore, we extract the
    // application list from the first ACL in the array.
    status = SecACLCopySimpleContents (
        aclArray[0],            // the ACL from which to extract
                                //  the list of trusted apps
        applicationList,        // the list of trusted apps
        description,            // the description string
        promptSelector          // the value of the prompt selector flag
                                        );
 
    return aclArray[0];
}
 
 
int main (int argc, const char * argv[]) {
    OSStatus status;
    OSStatus status1;
    OSStatus status2;
    OSStatus status3;
 
    SecKeychainSearchRef searchReference = nil;
    SecKeychainItemRef itemRef = nil;
 
     SecAccessRef itemAccess = nil;
     SecACLRef oldACL, newACL;
 
     CFIndex arrayCount;
     CFRange arrayRange;
     SecTrustedApplicationRef trustedAppArray[10];
     CSSM_ACL_KEYCHAIN_PROMPT_SELECTOR promptSelector;
     CFStringRef description;
     CFArrayRef newTrustedAppArray;
 
      CSSM_ACL_AUTHORIZATION_TAG tags[20];
      uint32 tagCount;
      tagCount = 20;
 
     const char *path = "/Applications/Mail.app";       //path to
                                        // trusted app to add to ACL
     SecTrustedApplicationRef trustedApp;
 
     SecKeychainAttributeList attrList;
     SecKeychainAttribute attrib;
 
     attrList.count = 1;
     attrib.tag = kSecLabelItemAttr;
 
     attrib.data = "www.TestItem.com";              //label of keychain item
 
     attrib.length = strlen(attrib.data);
     attrList.attr  = &attrib;
 
     CFArrayRef aclList;
     CFIndex numACLs;
     CFArrayRef applicationList;
     CSSM_ACL_AUTHORIZATION_TAG authorizationTag =
        CSSM_ACL_AUTHORIZATION_DECRYPT;  // the authorization tag
                                        //  to search for.
 
    // Obtain a search reference object to use for finding the item
    //  in the keychain.
    // This returns a SecKeychainSearchRef, which we must release when
    //  we're finished using it.
    status = GetSearchRef (&attrList, &searchReference);
 
    // Find the keychain item and obtain a keychain item reference object.
    // This returns a SecKeychainItemRef, which we must release when
    //  we're finished using it.
    status1 = FindItem (searchReference, &itemRef);
 
    if (status1 == noErr)
        {
        // Obtain the access reference object for the keychain item.
        // This returns a SecAccessRef, which we must release when
        //  we're finished using it.
        status2 = SecKeychainItemCopyAccess (itemRef, &itemAccess);
        // Obtain an array of ACL entry objects for the access object.
        // Limit the search to ACL entries with the specified
        //  authorization tag.
        status3 = SecAccessCopySelectedACLList (itemAccess,
                                     authorizationTag, &aclList);
        numACLs = CFArrayGetCount (aclList);
        // Extract the ACL entry object from the array of ACL entries,
        //  along with the ACL entry's list of trusted applications,
        //  its description, and its prompt selector flag setting.
        // This returns a SecACLRef and a CFArrayRef, which we must
        //  release we're finished using them.
        oldACL = GetACL (numACLs, aclList, &applicationList,
                                    &description, &promptSelector);
        arrayCount = CFArrayGetCount (applicationList);
 
        //  The application list is a CFArray.  Extract the list of
        //  applications from the CFArray.
        arrayRange.location = (CFIndex) 0;
        arrayRange.length = arrayCount;
        CFArrayGetValues (applicationList, arrayRange,
                                            (void *) trustedAppArray);
        // Create a new trusted application reference object for
        //  the application to be added to the list.
        status2 = SecTrustedApplicationCreateFromPath (path, &trustedApp);
        if (status2 == noErr)   // the function fails if the application is
                                // not found.
        {
            // Append the new application to the array and create a
            //  new CFArray.
            trustedAppArray[arrayCount] = trustedApp;
            newTrustedAppArray = CFArrayCreate (NULL,
                                (void *)trustedAppArray, arrayCount+1,
                                                &kCFTypeArrayCallBacks);
            // Get the authorizations from the old ACL.
            status3 = SecACLGetAuthorizations (oldACL, tags, &tagCount);
            // Delete the old ACL from the access object. The user is
            // prompted for permission to alter the keychain item.
            status3 = SecACLRemove (oldACL);
            // Create a new ACL with the same attributes as the old
            //  one, except use the new CFArray of trusted applications.
            status3 = SecACLCreateFromSimpleContents (itemAccess,
                        newTrustedAppArray, description, &promptSelector,
                                                            &newACL);
            // Set the authorizations for the new ACL to be the same as
            //  those for the old ACL.
            status3 = SecACLSetAuthorizations (newACL, tags, tagCount);
            // Replace the access object in the keychain item with the
            //  new access object. The user is prompted for permission
            //  to alter the keychain item.
            status3 = SecKeychainItemSetAccess (itemRef, itemAccess);
        }
        else
            ...; //Handle the error if the application was not found.
 
    // Release the objects we allocated or retrieved
    if (searchReference)
        CFRelease(searchReference);     //SecKeychainSearchRef
    if (itemRef)
        CFRelease(itemRef);             //SecKeychainItemRef
    if (itemAccess)
        CFRelease(itemAccess);          //SecAccessRef
    if (oldACL)
        CFRelease(oldACL);              //SecACLRef
    if (newACL)
        CFRelease(newACL);              //SecACLRef
    if (description)
        CFRelease(description);         //CFStringRef
    if (newTrustedAppArray)
        CFRelease(newTrustedAppArray);  //CFArrayRef
    if (trustedApp)
        CFRelease(trustedApp);          //SecTrustedApplicationRef
    if (aclList)
        CFRelease(aclList);             //CFArrayRef
    if (applicationList)
        CFRelease(applicationList);     //CFArrayRef
    }
    return (status3);
 
}

Servers and the Keychain

Several Keychain Services functions automatically display a dialog requesting that the user unlock the keychain or create a new keychain when necessary. Keychain Services also displays dialogs to confirm that the user wants the application to access the keychain (Figure 2-2) and for other reasons. If you are writing a server application that must run unattended, you might want to disable the automatic display of dialogs and programatically unlock or create keychains.


Figure 2-2  Confirm access dialog

Confirm access dialog

Use the SecKeychainSetUserInteractionAllowed function to enable or disable the automatic display of dialogs. When you call this function with a value of FALSE for the state parameter, any Keychain Services functions that ordinarily open dialogs instead return immediately with the result errSecInteractionRequired. You can use the SecKeychainGetStatus function to find out whether the keychain exists and is unlocked. You can then use the SecKeychainUnlock function to unlock the keychain, or the SecKeychainCreate function to create a new keychain, as necessary.

Important: After you have disabled the automatic display of dialogs, no Keychain Services function called by any application displays dialogs until someone calls the SecKeychainSetUserInteractionAllowed function to reenable dialogs, or until the system is restarted. Therefore, if there might be other applications operating on the same computer, you should be careful to reenable this feature once you are finished opening or creating a keychain.



< Previous PageNext Page > Hide TOC


© 2003, 2009 Apple Inc. All Rights Reserved. (Last updated: 2009-03-12)


Did this document help you?
Yes: Tell us what works for you.
It’s good, but: Report typos, inaccuracies, and so forth.
It wasn’t helpful: Tell us what would have helped.