/* * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.2 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ #import "Authorization.h" @implementation authorization + sharedInstance { static id sharedTask = nil; if(sharedTask==nil) { sharedTask = [[self alloc]init]; } return sharedTask; } //============================================================================ // - (BOOL)isAuthenticated //============================================================================ // Find out if the user has the appropriate authorization rights. // This really needs to be called each time you need to know whether the user // is authorized, since the AuthorizationRef can be invalidated elsewhere, or // may expire after a short period of time. // As far as I know, there is no way to be notified when your AuthorizationRef // expires. // - (BOOL)isAuthenticated { AuthorizationRights rights; AuthorizationRights *authorizedRights; AuthorizationFlags flags; AuthorizationItem items[1]; char sysctlPath[] = "/usr/sbin/kmodstat"; OSStatus err = 0; BOOL authorized = NO; if(authorizationRef==NULL) { //If we haven't created an AuthorizationRef yet, create one now with the //kAuthorizationFlagDefaults flags only to get the user's current //authorization rights. rights.count=0; rights.items = NULL; flags = kAuthorizationFlagDefaults; err = AuthorizationCreate(&rights, kAuthorizationEmptyEnvironment, flags, &authorizationRef); } //There should be one item in the AuthorizationItems array for each //type of right you want to acquire. //The data in the value and valueLength is dependant on which right you //want to acquire. For the right to execute tools as root, //kAuthorizationRightExecute, they should hold a pointer to a C string //containing the path to the tool you want to execute, and //the length of the C string path. //There needs to be one item for each tool you want to execute. items[0].name = kAuthorizationRightExecute; items[0].value = sysctlPath; items[0].valueLength = strlen(sysctlPath); items[0].flags = 0; rights.count=1; rights.items = items; flags = kAuthorizationFlagExtendRights; //Since we've specified kAuthorizationFlagExtendRights and //haven't specified kAuthorizationFlagInteractionAllowed, if the //user isn't currently authorized to execute tools as root, //they won't be asked for a password and err will indicate //an authorization failure. err = AuthorizationCopyRights(authorizationRef,&rights, kAuthorizationEmptyEnvironment, flags,&authorizedRights); authorized = (errAuthorizationSuccess==err); if(authorized) { //we don't need these items, and they need to be disposed of. AuthorizationFreeItemSet(authorizedRights); } return authorized; } //============================================================================ // - (void)deauthenticate //============================================================================ // Invalidate the user's AuthorizationRef to dispose of any acquired rights. // It's a good idea to do this before you quit your application, else they // will stay authorized as of the current time (4K78). // - (void)deauthenticate { if(authorizationRef) { //dispose of any rights our AuthorizationRef has acquired, and null it out //so we get a new one next time we need one. AuthorizationFree(authorizationRef,kAuthorizationFlagDestroyRights); authorizationRef = NULL; ////////////// // [[NSNotificationCenter defaultCenter]postNotificationName:SysctlDeauthenticatedNotification /////////// object:self]; } } //============================================================================ // - (BOOL)fetchPassword //============================================================================ // Fetch user's password if needed. If the user is already authorized, they // will not be asked for their password again. // - (BOOL)fetchPassword { AuthorizationRights rights; AuthorizationRights *authorizedRights; AuthorizationFlags flags; AuthorizationItem item[1]; char sysctlPath[] = "/usr/sbin/sysctl"; OSStatus err = 0; BOOL authorized = NO; item[0].name = kAuthorizationRightExecute; item[0].value = sysctlPath; item[0].valueLength = strlen(sysctlPath); item[0].flags = 0; rights.count=1; rights.items = item; flags = kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights; //Here, since we've specified kAuthorizationFlagExtendRights and //have also specified kAuthorizationFlagInteractionAllowed, if the //user isn't currently authorized to execute tools as root //(kAuthorizationRightExecute),they will be asked for their password. //The err return value will indicate authorization success or failure. err = AuthorizationCopyRights(authorizationRef,&rights, kAuthorizationEmptyEnvironment, flags,&authorizedRights); authorized = (errAuthorizationSuccess==err); if(authorized) { AuthorizationFreeItemSet(authorizedRights); ///// [[NSNotificationCenter defaultCenter]postNotificationName:SysctlAuthenticatedNotification /////////// object:self]; } return authorized; } //============================================================================ // - (BOOL)authenticate //============================================================================ // if the user is not already authorized, ask them to authenticate. // return YES if the user is (or becomes) authorized. // - (BOOL)authenticate { if(![self isAuthenticated]) { [self fetchPassword]; } return [self isAuthenticated]; } //============================================================================ // - (void)setValue:(NSString*)inValue forVariable:(NSString*)inVariable //============================================================================ // Execute the sysctl tool with the given arguments using // AuthorizationExecuteWithPrivileges. // Attempt to authorize the user if necessary. // - (void)setValue:(NSString*)inValue forVariable:(NSString*)inVariable { char* args[3]; OSStatus err = 0; NSString* argValue = nil; if(![self authenticate]) return; argValue = [NSString stringWithFormat:@"%@=%@",inVariable,inValue]; //the arguments parameter to AuthorizationExecuteWithPrivileges is //a NULL terminated array of C string pointers. args[0] = "-w"; args[1]=(char*)[argValue cString]; args[2]=NULL; err = AuthorizationExecuteWithPrivileges(authorizationRef, "/usr/sbin/sysctl", 0, args, NULL); if(err!=0) { NSBeep(); NSLog(@"Error %d in AuthorizationExecuteWithPrivileges",err); } } -(AuthorizationRef)returnAuthorizationRef { return authorizationRef; } @end