Question

First of all, please take note that I'm looking for a solution that works within the MAS review guidelines and, in particular, app sandboxing.

I would like to know if there is any way to authenticate a user before allowing them to make changes to sensitive preferences. For example, the System Preferences app does this with a lock icon: enter image description here

I suspect System Preferences needs to do that because some preference files actually need root permissions to be modified.

In my case, I do not need to run any such 'sudo-esque' operation so I do not require privilege escalation. All I want to do is to make sure the person who wants to change my app's preferences is actually the guy who owns the mac or created the current mac account (in short, knows the password for the current logged-in user).

Any ideas?

Was it helpful?

Solution 2

There is no supported API to do this, and even if you found a work-around, your app would likely be rejected from the Mac App Store for asking the user for their password.

In addition, you don't actually gain any real security by doing this. Preferences are stored in the sandbox with write permissions for the user that owns them. That means that, even if your App's UI prevents users from modifying preferences without a password, users can still use other apps (such as the defaults command-line tool) to change your app's preferences without a password.

The lock icon you see in the System Preferences app exists to allow users to write to preferences that affect all users on the system. That is why they require authentication, and more importantly, privilege escalation to unlock. But since your users already have permissions to write to your app's preferences in their sandbox, including the lock would only serve to give your users a false impression that the permissions for those preferences are more secure, presumably because those preferences affect multiple users.

The only way to implement your own password check would be to ask the user for their password, hash it, and then compare the hash against the has stored in the user's shadow file (see http://www.defenceindepth.net/2011/09/cracking-os-x-lion-passwords.html ). However, to get access to the shadow file, you need root privileges, which sandboxed apps cannot get.

Even if you could get the password hash, your authentication mechanism is likely to harm the user's security. The authentication services API goes to a lot of trouble to store the password securely in memory, disable software keyloggers, and make sure that the password does not remain in memory when it is finished. This requires the use of low-level APIs not available to sandboxed users.

Apple also has a vested interest in rejecting apps that ask for the user's password outside of the authorization services API. If an app gets a user's password, there's nothing preventing that app from sending that password over the network back to the app's author.

If Apple made an API, parallel to authentication services, that prompted the user for their password, but without privilege escalation, then they could be confident that the app did not get the password. However, because this API would not add any real protection to user preferences or data, and because it would give the false impression of security, I doubt they will add such an API.

OTHER TIPS

Despite the issues outlined by Michael Buckley, I opted to use Apple's SFAuthorizationView to create the same functionality you were describing in your question.

SFAuthorizationView : https://developer.apple.com/library/mac/documentation/security/Reference/SecurityInterfaceFramework/Classes/SFAuthorizationView_Class/Reference/Reference.html

I created a SFAuthorizationView, and in my delegate respond to authorizationDidAuthorize at which point I unlock preferences for the end user. Works great.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top