| /* |
| File: ConfigurationAuthority.c |
| |
| Abstract: Interface to system security framework that manages access |
| to protected resources like system configuration preferences. |
| |
| Copyright: (c) Copyright 2005 Apple Computer, Inc. All rights reserved. |
| |
| Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Computer, Inc. |
| ("Apple") in consideration of your agreement to the following terms, and your |
| use, installation, modification or redistribution of this Apple software |
| constitutes acceptance of these terms. If you do not agree with these terms, |
| please do not use, install, modify or redistribute this Apple software. |
| |
| In consideration of your agreement to abide by the following terms, and subject |
| to these terms, Apple grants you a personal, non-exclusive license, under Apple's |
| copyrights in this original Apple software (the "Apple Software"), to use, |
| reproduce, modify and redistribute the Apple Software, with or without |
| modifications, in source and/or binary forms; provided that if you redistribute |
| the Apple Software in its entirety and without modifications, you must retain |
| this notice and the following text and disclaimers in all such redistributions of |
| the Apple Software. Neither the name, trademarks, service marks or logos of |
| Apple Computer, Inc. may be used to endorse or promote products derived from the |
| Apple Software without specific prior written permission from Apple. Except as |
| expressly stated in this notice, no other rights or licenses, express or implied, |
| are granted by Apple herein, including but not limited to any patent rights that |
| may be infringed by your derivative works or by other works in which the Apple |
| Software may be incorporated. |
| |
| The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO |
| WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED |
| WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN |
| COMBINATION WITH YOUR PRODUCTS. |
| |
| IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR |
| CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
| GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION |
| OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT |
| (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN |
| ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "ConfigurationAuthority.h" |
| #include "ConfigurationRights.h" |
| |
| #include <AssertMacros.h> |
| |
| |
| static AuthorizationRef gAuthRef = 0; |
| |
| static AuthorizationItem gAuthorizations[] = { { UPDATE_SC_RIGHT, 0, NULL, 0 }, |
| { EDIT_SYS_KEYCHAIN_RIGHT, 0, NULL, 0 }}; |
| static AuthorizationRights gAuthSet = { sizeof gAuthorizations / sizeof gAuthorizations[0], gAuthorizations }; |
| |
| static CFDictionaryRef CreateRightsDict( CFStringRef prompt) |
| /* Create a CFDictionary decribing an auth right. See /etc/authorization for examples. */ |
| /* Specifies that the right requires admin authentication, which persists for 5 minutes. */ |
| { |
| CFMutableDictionaryRef dict = NULL, tmpDict; |
| CFMutableArrayRef mechanisms; |
| CFNumberRef timeout; |
| int val; |
| |
| tmpDict = CFDictionaryCreateMutable( (CFAllocatorRef) NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); |
| require( tmpDict != NULL, MakeDictFailed); |
| |
| CFDictionaryAddValue(tmpDict, CFSTR("class"), CFSTR("user")); |
| CFDictionaryAddValue(tmpDict, CFSTR("comment"), prompt); |
| CFDictionaryAddValue(tmpDict, CFSTR("group"), CFSTR("admin")); |
| |
| mechanisms = CFArrayCreateMutable((CFAllocatorRef) NULL, 1, &kCFTypeArrayCallBacks); |
| require( mechanisms != NULL, MakeArrayFailed); |
| CFArrayAppendValue( mechanisms, CFSTR("builtin:authenticate")); |
| CFDictionaryAddValue( tmpDict, CFSTR("mechanisms"), mechanisms); |
| |
| val = 300; // seconds |
| timeout = CFNumberCreate((CFAllocatorRef) NULL, kCFNumberIntType, &val); |
| require( timeout != NULL, MakeIntFailed); |
| CFDictionaryAddValue( tmpDict, CFSTR("timeout"), timeout); |
| CFDictionaryAddValue( tmpDict, CFSTR("shared"), kCFBooleanTrue); |
| |
| dict = tmpDict; |
| tmpDict = NULL; |
| |
| CFRelease( timeout); |
| MakeIntFailed: |
| CFRelease( mechanisms); |
| MakeArrayFailed: |
| if ( tmpDict) |
| CFRelease( tmpDict); |
| MakeDictFailed: |
| return dict; |
| } |
| |
| OSStatus InitConfigAuthority(void) |
| /* Initialize the authorization record-keeping */ |
| { |
| OSStatus err; |
| CFDictionaryRef dict; |
| CFStringRef rightInfo; |
| |
| err = AuthorizationCreate((AuthorizationRights*) NULL, (AuthorizationEnvironment*) NULL, |
| (AuthorizationFlags) 0, &gAuthRef); |
| require_noerr( err, NewAuthFailed); |
| |
| err = AuthorizationRightGet( UPDATE_SC_RIGHT, (CFDictionaryRef*) NULL); |
| if (err == errAuthorizationDenied) |
| { |
| rightInfo = CFCopyLocalizedString(CFSTR("Authentication required to set Dynamic DNS preferences."), |
| CFSTR("Describes operation that requires user authorization")); |
| require_action( rightInfo != NULL, GetStrFailed, err=coreFoundationUnknownErr;); |
| dict = CreateRightsDict(rightInfo); |
| require_action( dict != NULL, GetStrFailed, err=coreFoundationUnknownErr;); |
| |
| err = AuthorizationRightSet(gAuthRef, UPDATE_SC_RIGHT, dict, (CFStringRef) NULL, |
| (CFBundleRef) NULL, (CFStringRef) NULL); |
| CFRelease(rightInfo); |
| CFRelease(dict); |
| } |
| require_noerr( err, AuthSetFailed); |
| |
| err = AuthorizationRightGet( EDIT_SYS_KEYCHAIN_RIGHT, (CFDictionaryRef*) NULL); |
| if (err == errAuthorizationDenied) |
| { |
| rightInfo = CFCopyLocalizedString( CFSTR("Authentication required to edit System Keychain."), |
| CFSTR("Describes operation that requires user authorization")); |
| require_action( rightInfo != NULL, GetStrFailed, err=coreFoundationUnknownErr;); |
| dict = CreateRightsDict( rightInfo); |
| require_action( dict != NULL, GetStrFailed, err=coreFoundationUnknownErr;); |
| |
| err = AuthorizationRightSet(gAuthRef, EDIT_SYS_KEYCHAIN_RIGHT, dict, (CFStringRef) NULL, |
| (CFBundleRef) NULL, (CFStringRef) NULL); |
| CFRelease( rightInfo); |
| CFRelease( dict); |
| } |
| require_noerr( err, AuthSetFailed); |
| |
| AuthSetFailed: |
| GetStrFailed: |
| NewAuthFailed: |
| return err; |
| } |
| |
| OSStatus AttemptAcquireAuthority( Boolean allowUI) |
| /* Try to get permission for privileged ops, either implicitly or by asking the user for */ |
| /* authority to perform operations (if necessary) */ |
| { |
| AuthorizationFlags allowFlag = allowUI ? kAuthorizationFlagInteractionAllowed : 0; |
| OSStatus err; |
| |
| err = AuthorizationCopyRights( gAuthRef, &gAuthSet, (AuthorizationEnvironment*) NULL, |
| kAuthorizationFlagExtendRights | kAuthorizationFlagPreAuthorize | |
| allowFlag, |
| (AuthorizationRights**) NULL); |
| return err; |
| } |
| |
| OSStatus ReleaseAuthority(void) |
| /* Discard authority to perform operations */ |
| { |
| (void) AuthorizationFree( gAuthRef, kAuthorizationFlagDefaults); |
| gAuthRef = 0; |
| return AuthorizationCreate( (AuthorizationRights*) NULL, (AuthorizationEnvironment*) NULL, |
| (AuthorizationFlags) 0, &gAuthRef); |
| } |
| |
| Boolean CurrentlyAuthorized(void) |
| { |
| OSStatus err = AttemptAcquireAuthority(true); |
| return err == noErr; |
| } |
| |
| |
| OSStatus ExternalizeAuthority(AuthorizationExternalForm *pAuth) |
| /* Package up current authorizations for transfer to another process */ |
| { |
| return AuthorizationMakeExternalForm(gAuthRef, pAuth); |
| } |