diff options
author | Kristian Monsen <kristianm@google.com> | 2011-05-11 20:53:37 +0100 |
---|---|---|
committer | Kristian Monsen <kristianm@google.com> | 2011-05-16 13:54:48 +0100 |
commit | 21d179b334e59e9a3bfcaed4c4430bef1bc5759d (patch) | |
tree | 64e2bb6da27af6a5c93ca34f6051584aafbfcb9e /chrome/browser/ui/cocoa/authorization_util.mm | |
parent | 0c63f00edd6ed0482fd5cbcea937ca088baf7858 (diff) | |
download | external_chromium-21d179b334e59e9a3bfcaed4c4430bef1bc5759d.zip external_chromium-21d179b334e59e9a3bfcaed4c4430bef1bc5759d.tar.gz external_chromium-21d179b334e59e9a3bfcaed4c4430bef1bc5759d.tar.bz2 |
Merge Chromium at 10.0.621.0: Initial merge by git.
Change-Id: I070cc91c608dfa4a968a5a54c173260765ac8097
Diffstat (limited to 'chrome/browser/ui/cocoa/authorization_util.mm')
-rw-r--r-- | chrome/browser/ui/cocoa/authorization_util.mm | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/chrome/browser/ui/cocoa/authorization_util.mm b/chrome/browser/ui/cocoa/authorization_util.mm new file mode 100644 index 0000000..5893711 --- /dev/null +++ b/chrome/browser/ui/cocoa/authorization_util.mm @@ -0,0 +1,183 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/cocoa/authorization_util.h" + +#import <Foundation/Foundation.h> +#include <sys/wait.h> + +#include <string> + +#include "base/basictypes.h" +#include "base/eintr_wrapper.h" +#include "base/logging.h" +#import "base/mac_util.h" +#include "base/string_number_conversions.h" +#include "base/string_util.h" +#include "chrome/browser/ui/cocoa/scoped_authorizationref.h" + +namespace authorization_util { + +AuthorizationRef AuthorizationCreateToRunAsRoot(CFStringRef prompt) { + // Create an empty AuthorizationRef. + scoped_AuthorizationRef authorization; + OSStatus status = AuthorizationCreate(NULL, + kAuthorizationEmptyEnvironment, + kAuthorizationFlagDefaults, + &authorization); + if (status != errAuthorizationSuccess) { + LOG(ERROR) << "AuthorizationCreate: " << status; + return NULL; + } + + // Specify the "system.privilege.admin" right, which allows + // AuthorizationExecuteWithPrivileges to run commands as root. + AuthorizationItem right_items[] = { + {kAuthorizationRightExecute, 0, NULL, 0} + }; + AuthorizationRights rights = {arraysize(right_items), right_items}; + + // product_logo_32.png is used instead of app.icns because Authorization + // Services can't deal with .icns files. + NSString* icon_path = + [mac_util::MainAppBundle() pathForResource:@"product_logo_32" + ofType:@"png"]; + const char* icon_path_c = [icon_path fileSystemRepresentation]; + size_t icon_path_length = icon_path_c ? strlen(icon_path_c) : 0; + + // The OS will append " Type an administrator's name and password to allow + // <CFBundleDisplayName> to make changes." + NSString* prompt_ns = mac_util::CFToNSCast(prompt); + const char* prompt_c = [prompt_ns UTF8String]; + size_t prompt_length = prompt_c ? strlen(prompt_c) : 0; + + AuthorizationItem environment_items[] = { + {kAuthorizationEnvironmentIcon, icon_path_length, (void*)icon_path_c, 0}, + {kAuthorizationEnvironmentPrompt, prompt_length, (void*)prompt_c, 0} + }; + + AuthorizationEnvironment environment = {arraysize(environment_items), + environment_items}; + + AuthorizationFlags flags = kAuthorizationFlagDefaults | + kAuthorizationFlagInteractionAllowed | + kAuthorizationFlagExtendRights | + kAuthorizationFlagPreAuthorize; + + status = AuthorizationCopyRights(authorization, + &rights, + &environment, + flags, + NULL); + if (status != errAuthorizationSuccess) { + if (status != errAuthorizationCanceled) { + LOG(ERROR) << "AuthorizationCopyRights: " << status; + } + return NULL; + } + + return authorization.release(); +} + +OSStatus ExecuteWithPrivilegesAndGetPID(AuthorizationRef authorization, + const char* tool_path, + AuthorizationFlags options, + const char** arguments, + FILE** pipe, + pid_t* pid) { + // pipe may be NULL, but this function needs one. In that case, use a local + // pipe. + FILE* local_pipe; + FILE** pipe_pointer; + if (pipe) { + pipe_pointer = pipe; + } else { + pipe_pointer = &local_pipe; + } + + // AuthorizationExecuteWithPrivileges wants |char* const*| for |arguments|, + // but it doesn't actually modify the arguments, and that type is kind of + // silly and callers probably aren't dealing with that. Put the cast here + // to make things a little easier on callers. + OSStatus status = AuthorizationExecuteWithPrivileges(authorization, + tool_path, + options, + (char* const*)arguments, + pipe_pointer); + if (status != errAuthorizationSuccess) { + return status; + } + + int line_pid = -1; + size_t line_length = 0; + char* line_c = fgetln(*pipe_pointer, &line_length); + if (line_c) { + if (line_length > 0 && line_c[line_length - 1] == '\n') { + // line_c + line_length is the start of the next line if there is one. + // Back up one character. + --line_length; + } + std::string line(line_c, line_length); + if (!base::StringToInt(line, &line_pid)) { + // StringToInt may have set line_pid to something, but if the conversion + // was imperfect, use -1. + LOG(ERROR) << "ExecuteWithPrivilegesAndGetPid: funny line: " << line; + line_pid = -1; + } + } else { + LOG(ERROR) << "ExecuteWithPrivilegesAndGetPid: no line"; + } + + if (!pipe) { + fclose(*pipe_pointer); + } + + if (pid) { + *pid = line_pid; + } + + return status; +} + +OSStatus ExecuteWithPrivilegesAndWait(AuthorizationRef authorization, + const char* tool_path, + AuthorizationFlags options, + const char** arguments, + FILE** pipe, + int* exit_status) { + pid_t pid; + OSStatus status = ExecuteWithPrivilegesAndGetPID(authorization, + tool_path, + options, + arguments, + pipe, + &pid); + if (status != errAuthorizationSuccess) { + return status; + } + + // exit_status may be NULL, but this function needs it. In that case, use a + // local version. + int local_exit_status; + int* exit_status_pointer; + if (exit_status) { + exit_status_pointer = exit_status; + } else { + exit_status_pointer = &local_exit_status; + } + + if (pid != -1) { + pid_t wait_result = HANDLE_EINTR(waitpid(pid, exit_status_pointer, 0)); + if (wait_result != pid) { + PLOG(ERROR) << "waitpid"; + *exit_status_pointer = -1; + } + } else { + *exit_status_pointer = -1; + } + + return status; +} + +} // namespace authorization_util |