Mailing Lists: Apple Mailing Lists
Image of Mac OS face in stamp
Re: ACL configuration policy and interpretation
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: ACL configuration policy and interpretation

On Dec 11, 2007, at 11:59 PM, Wade Tregaskis wrote:

I apologise in advance for the barrage of questions. But I have been quiet otherwise for ages now, you have to admit... :) I'm going to test pretty much all of this anyway, but I'm hoping if someone has the time to pre-empt that it'll save me a bit of time & confusion on the spikier bits..

[all this is on Tiger, btw; I haven't tested on Leopard, but will]

The ACL system on Tiger and Leopard is the same, and no new subject types have been introduced. The only (and major!) change is that Leopard tracks application identity with Code Signing (if they're signed). Unsigned applications are treated pretty much the same as in Tiger. And we've kept the API astonishingly stable, given the changes underneath.

I've been poked by a couple of people recently about ACLs. In particular, people want to be able to pre-configure an arbitrary keychain item to be always accessible to their app, without requiring user input (e.g. their apps run unattended, in a shell session, or full screen, etc; no user input is possible). The API itself is perfectly functional (albeit a bit verbose), and that's all good... but there's a lot of questions I can't find answers for in the API or its documentation.

For example, here's a representative keychain item, from my keychain:

Touch-stone: secured data items are actually pairs of (key, data), and the ACL applies to the key. So storing (or modifying) a value is "encrypting", and retrieving a value is "decrypting".

AppleID: wadetregaskis @   ():
	0: AppleID
		Authorises: Encryption
		Applications: (none)

Everybody is allowed to modify the value.

1: AppleID (requires user authorisation)
Authorises: Decryption, Key derivation, Exporting clear, Exporting wrapped, MACing & Signing

Only Setup is allowed decrypt (retrieve) the value. Anyone else gets a confirmation dialog.

	2: AppleID
		Authorises: Changing Access
		Applications: (none)

No application is (pre)authorized to change the ACL. Any attempt to change the ACL requires a confirmation dialog.

I've noticed that this 2nd entry is basically what's shown in Keychain Access, and seems to control whether or not apps can use the contents of the password. Is this combination of authorisations significant, i.e. some kind of magic value? I guess it comes from how the item is used at a low level, so, my point perhaps more is... for the typical use of retrieving the password of the item, is it sufficient to have, say, just 'Exporting clear'
(CSSM_ACL_AUTHORIZATION_EXPORT_CLEAR) in the ACL? The documentation for SecKeychainItemCopyContent seems to indicate you need to have decryption access to the item, but that seems odd; wouldn't you need decryption access to the key that decrypts the item? [I haven't enumerated anything other than passwords & certificates yet, so I don't know what the ACL setup on other types of items is]

For data items, encryption and decryption are the only relevant operations. The others apply to key items; they are included for the sake of consistency (they don't hurt). Again, you *are* looking at the ACL of the key that encrypts the data. The Sec* layer unifies the (key, data) pair for you.

Next question is, well... the 3rd item above is pretty self- explanatory; any app in that ACL can modify the ACL itself without user auth, right? It's the first one which puzzles me more; what would 'encryption' auth on a password item (or any type, I guess) give you? It seems to be empty for all my keychain items, so I don't have an example to go from.

Item #2, the right to change the ACL, is given to NO application. This means that any application making such a request will throw up a dialog.
Item #0, the right to encrypt (i.e. to store a new value), is unrestricted. Anyone can do that.
(In the output you show, they look the same. They're not. #2 has an empty array-of-applications. #0 has a NULL array. Check the output of "security dump-keychain -a".)

Is there any way to get the "name"/"description" of the SecAccessRef itself? You specify one when you create it with SecAccessCreate, but there's no way to retrieve it in the public API. Is it just some kind of default value for the similar attribute of the ACLs, which is retrievable (as displayed in my output above).

The description string is stored (separately for each ACL entry) in the PROMPT ACL subject that triggers keychain dialog prompts. Each ACL entry has its own descriptor; by convention, they are all the same, but you can violate that convention if you're tricky (or careless). If you want the "most canonical" description for an item, take the one for the change-ACL right. At the SecACL layer, you get it as the "description" return of the SecACLCopySimpleContents API call. At the CSSM layer, it's the third list item in the CSSM_ACL_SUBJECT_TYPE_KEYCHAIN_PROMPT subject buried deeply inside.

(Yes, that means that there are (non-standard) ACLs that don't have "description" strings at all, because they don't issue dialogs that would need them. The meaning of "the" description of an item is fuzzy.)

I had to go poking through the 'data' of the SecTrustedApplicationRef to figure out that some part of it is the path to the app in question. I get that it's probably implementation dependent as to what the structure of this data is, and I'm not particularly interested in poking too much, but knowing the path of the app seems a pretty fundamental thing. (it'd be nice to be able to get the hash or signature or whatever it is that cryptographically protects the entry, too). Is the format spec'd anywhere, and is it wise to use it?

This was and is intentionally under-documented, to allow for future changes.

First, understand that this string is a *comment*. It has no bearing on ACL validation; it's just here for display purposes. Think of it as whatever the ACL's creator put there as a documentation hint as to the underlying ACL's behavior. Changing it has absolutely no effect on the ACL's meaning.

With all those caveats, you can get that string with the SecTrustedApplicationCopyData function. Here is the whole of the documented behavior:
The CFData returned by SecTrustedApplicationCopyData begins with a null-terminated UTF8 string. That string is a description of what kind of application should be acceptable to that SecTrustedApplication object. (Ignore any data after the null byte. Do not use the length of the CFData. Yes, there always is a null terminating byte.) If the string has URI-form (scheme://rest), then it is based on Code Signing validation, and the particular scheme used indicates its meaning (e.g. group:// for an application group). If the string is not in URI-form (no "://"), it's a path to where an acceptable application does or did or should reside. (Note that moving a program does not change validity.)
(The URI-scheme rule is new for Leopard. But it's good to check in Tiger and earlier; a keychain moved from Leopard to Tiger might contain such items.)

There is an undocumented private SPI (SecTrustedApplicationValidateWithPath, in SecTrustedApplicationPriv.h) to check whether an application at a given path on disk satisfies a SecTrustedApplication's requirement. It's been around since 10.3 at least. It magically works with Code Signing in Leopard. Did I mention it is NOT an official API? Good.

What's the payoff on all that secrecy and un-documentation? When we introduced Code Signing in 10.5, the innards of SecTrustedApplication were pretty much ripped out and replaced. Yet the officially documented behavior (above) remained intact, while imprudent assumptions ("SecTrustedApplications have a path that points to the application on disk") were true in 10.4 and earlier but may now fail.

Lastly in the technical questions, I noticed that SecKeychainCopyAccess returns "not implemented" on Tiger... I haven't tried on Leopard. It rings a bell, this error, but I can't remember why... so I just want to check: is it indeed not implemented on Tiger, or am I misusing it somehow?

It is indeed unimplemented (through 10.5), because we don't actually *use* ACLs on keychains (as opposed to keychain *items*) for anything. We store them at the CSSM layer, but nobody pays any attention to them. So currently, you'd have to use CSSM calls to handle them (but there's no reason to).

Now, some behavioural questions... nearly done, promise.. ;) ... so, getting back to the use case I opened with, what I'd like to know is two things:

a) how to add an internet password with an arbitrary app (not the caller) in the trusted accessor list. I presume you can provide any ACLs you like in the initial SecAccessRef you can pass to SecKeychainItemCreateFromContent? However, SecKeychainAddInternetPassword has no parameter for this, and I'm presuming that the default access it uses doesn't have the calling app in the "Changing Access" ACL, so trying to then modify the access would prompt the user, correct? If so, I guess it's necessary to use SecKeychainItemCreateFromContent instead, then?

Entirely correct, except that the default ACL created (if you don't specify your own) does give access (only) to the creating application. (Keychain Access intentionally does not use the default and doesn't give itself access for items it creates.)

b) given an arbitrary password, if I try to add my app to its ACL for password access, the user will be prompted to allow this modification, won't they? And this will happen for each item... is there any way to effectively batch these up into a single prompt of the user (or perhaps even no user prompting; provide a password programmatically)?

There is not. The keychain machinery contains no mechanism for bypassing the ACL check, and the default ACL says "ask the user before allowing editing an ACL." You can certainly create items whose change- ACL ACL allows more liberal modification, but there is (intentionally) no way to bypass an ACL of an item that doesn't allow you access. (No, not even as root.)

There is one trick: there is no ACL protection against deleting or creating keychain items. If you can read the item without dialogs (i.e. your application is on the decrypt ACL), you can read it, delete it, and recreate it with a different ACL. That allows an old, authorized application to add newer ones to the list in a crunch. On Leopard and beyond, application groups are a better way to do that. Of course, this won't work (well, will put up a dialog) if you're not authorized to read the item.

-- perry
Perry The Cynic email@hidden
To a blind optimist, an optimistic realist must seem like an Accursed Cynic.

Do not post admin requests to the list. They will be ignored.
Apple-cdsa mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden

 >ACL configuration policy and interpretation (From: Wade Tregaskis <email@hidden>)

Visit the Apple Store online or at retail locations.

Contact Apple | Terms of Use | Privacy Policy

Copyright © 2011 Apple Inc. All rights reserved.