I recently needed to be able to run a shell command that requires root/sudo access in order to complete successfully, and decided to see if I could use the Security Framework to accomplish this. Note that Apple's recommended approach to this is to create a privileged helper tool that actually performs the desired function(s). Not wanting to go down that rabbit hole yet, I put together the following example.
It creates 4 *.txt files in a restricted system area (/etc).
The code is a bit fugly, but does the job.
Comments welcome!
Code: Select all
; Parameter to pass to AuthorizationCreate when no environment is being provided.
#kAuthorizationEmptyEnvironment = 0
; AuthorizationFlags
Enumeration AuthorizationFlags
#kAuthorizationFlagDefaults = 0
#kAuthorizationFlagInteractionAllowed = (1 << 0)
#kAuthorizationFlagExtendRights = (1 << 1)
#kAuthorizationFlagPartialRights = (1 << 2)
#kAuthorizationFlagDestroyRights = (1 << 3)
#kAuthorizationFlagPreAuthorize = (1 << 4)
EndEnumeration
; Error codes returned by Authorization API.
Enumeration AuthorizationResult
#errAuthorizationSuccess = 0 ;/* The authorization was successful. */
#errAuthorizationInvalidSet = -60001 ;/* The authorization rights are invalid. */
#errAuthorizationInvalidRef = -60002 ;/* The authorization reference is invalid. */
#errAuthorizationInvalidTag = -60003 ;/* The authorization tag is invalid. */
#errAuthorizationInvalidPointer = -60004 ;/* The returned authorization is invalid. */
#errAuthorizationDenied = -60005 ;/* The authorization was denied. */
#errAuthorizationCanceled = -60006 ;/* The authorization was cancelled by the user. */
#errAuthorizationInteractionNotAllowed = -60007 ;/* The authorization was denied since no user interaction was possible. */
#errAuthorizationInternal = -60008 ;/* Unable To obtain authorization For this operation. */
#errAuthorizationExternalizeNotAllowed = -60009 ;/* The authorization is Not allowed To be converted To an external format. */
#errAuthorizationInternalizeNotAllowed = -60010 ;/* The authorization is Not allowed To be created from an external format. */
#errAuthorizationInvalidFlags = -60011 ;/* The provided option flag(s) are invalid For this authorization operation. */
#errAuthorizationToolExecuteFailure = -60031 ;/* The specified program could Not be executed. */
#errAuthorizationToolEnvironmenterror = -60032 ;/* An invalid status was returned during execution of a privileged tool. */
#errAuthorizationBadAddress = -60033 ;/* The requested socket address is invalid (must be 0-1023 inclusive). */
EndEnumeration
ImportC "/System/Library/Frameworks/Security.framework/Security"
AuthorizationCreate(rights, environment, flags, *AuthorizationRef)
AuthorizationExecuteWithPrivileges(AuthorizationRef, cmd, flags, *arguments, file_ptr)
AuthorizationFree(authRef,flags)
EndImport
Structure CMD
parameter1.s
parameter2.s
parameter3.s
parameter4.s
parameter5.s
parameter6.s
parameter7.s
parameter8.s
cmd_terminator.i
EndStructure
Procedure.s UTF8 (in$)
Protected s.s = Space(Len(in$) / 2)
PokeS(@s, in$, -1, #PB_UTF8)
ProcedureReturn s
EndProcedure
Procedure.l LaunchPrivilegedProcess(cmd.s,
arg1.s,
arg2.s=#Null$,
arg3.s=#Null$,
arg4.s=#Null$,
arg5.s=#Null$,
arg6.s=#Null$,
arg7.s=#Null$,
arg8.s=#Null$)
Protected AuthRef
Protected ArgList.CMD
Protected retval.l
ArgList\parameter1 = UTF8(arg1)
ArgList\parameter2 = UTF8(arg2)
ArgList\parameter3 = UTF8(arg3)
ArgList\parameter4 = UTF8(arg4)
ArgList\parameter5 = UTF8(arg5)
ArgList\parameter6 = UTF8(arg6)
ArgList\parameter7 = UTF8(arg7)
ArgList\parameter8 = UTF8(arg8)
status = AuthorizationCreate(NULL, #kAuthorizationEmptyEnvironment, #kAuthorizationFlagDefaults,@AuthRef)
If status = #errAuthorizationSuccess
status = AuthorizationExecuteWithPrivileges(AuthRef, UTF8(cmd), #kAuthorizationFlagDefaults, @ArgList,NULL)
retval = PeekL(@status)
AuthorizationFree(AuthRef, #kAuthorizationFlagDestroyRights)
Else
ProcedureReturn status
EndIf
ProcedureReturn retval
EndProcedure
result = LaunchPrivilegedProcess("/usr/bin/touch","/etc/00-test.txt","/etc/01-test.txt","/etc/02-test.txt","/etc/03-test.txt")
If result = #errAuthorizationSuccess
MessageRequester("Status","Authorization Successful")
EndIf