macOSのアプリ内で指定したコマンドを管理者権限で実行する。
関数の実装
// Authorization系APIの返り値をチェックする // @param status 返り値 // @param apiName 実行したAPI名 void checkAuthorizationStatus(OSStatus status, NSString* apiName) { if (status != errAuthorizationSuccess) { NSString* errorMessage = [NSString stringWithFormat:@"Error %@: %d", apiName, status]; @throw [NSException exceptionWithName:@"ExecWithAdminPrivilegeException" reason:errorMessage userInfo:nil]; } } // 指定されたコマンドを管理者権限で実行する // @param cmd 実行するコマンド // @param args コマンドに渡すパラメータ void execWithAdminPrivilege(const char* cmd, char* args[]) { // Create authorization reference OSStatus status; AuthorizationRef authorizationRef; // AuthorizationCreate and pass NULL as the initial // AuthorizationRights set so that the AuthorizationRef gets created // successfully, and then later call AuthorizationCopyRights to // determine or extend the allowable rights. // http://developer.apple.com/qa/qa2001/qa1172.html status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationRef); checkAuthorizationStatus(status, @"AuthorizationCreate"); // kAuthorizationRightExecute == "system.privilege.admin" AuthorizationItem right = {kAuthorizationRightExecute, 0, NULL, 0}; AuthorizationRights rights = {1, &right}; AuthorizationFlags flags = kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed | kAuthorizationFlagPreAuthorize | kAuthorizationFlagExtendRights; // Call AuthorizationCopyRights to determine or extend the allowable rights. status = AuthorizationCopyRights(authorizationRef, &rights, kAuthorizationEmptyEnvironment, flags, NULL); checkAuthorizationStatus(status, @"AuthorizationCopyRights"); status = AuthorizationExecuteWithPrivileges(authorizationRef, cmd, kAuthorizationFlagDefaults, args, NULL); checkAuthorizationStatus(status, @"AuthorizationExecuteWithPrivileges"); // The only way to guarantee that a credential acquired when you // request a right is not shared with other authorization instances is // to destroy the credential. To do so, call the AuthorizationFree // function with the flag kAuthorizationFlagDestroyRights. // http://developer.apple.com/documentation/Security/Conceptual/authorization_concepts/02authconcepts/chapter_2_section_7.html status = AuthorizationFree(authorizationRef, kAuthorizationFlagDestroyRights); checkAuthorizationStatus(status, @"AuthorizationFree"); }
実行例
- execWithAdminPrivilege()関数のパラメータの注意点。
cmd
には実行するコマンドをフルパスで指定する。
*/bin/cp
など。args
にはコマンドに指定するパラメータを指定する。配列の最後はNULL
にすること。
const char* cmd = "/usr/bin/touch"; char* args[] = {"/Applications/test", NULL}; execWithAdminPrivilege(cmd, args);
実行すると以下のダイアログが表示され、管理者ユーザで認証できれば実行される。
※"App Sandbox"が有効になっていると、AuthorizationCopyRights関数でerrAuthorizationDeniedエラーが発生する。