Commit message: None
CVE: CVE-2013-2862
CWE: CWE-119
Vulnerability description: Skia, as used in Google Chrome before 27.0.1453.110, does not properly handle GPU acceleration, which allows remote attackers to cause a denial of service (memory corruption) or possibly have unspecified other impact via unknown vectors.

Project: Chrome

  bool ApplyConfig() {
    DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());

    if (!config_.GetString(kHostIdConfigPath, &host_id_)) {
      LOG(ERROR) << "host_id is not defined in the config.";
      return false;
    }

    if (!key_pair_.Load(config_)) {
      return false;
    }

    std::string host_secret_hash_string;
    if (!config_.GetString(kHostSecretHashConfigPath,
                           &host_secret_hash_string)) {
      host_secret_hash_string = "plain:";
    }

    if (!host_secret_hash_.Parse(host_secret_hash_string)) {
      LOG(ERROR) << "Invalid host_secret_hash.";
      return false;
    }

    if (!config_.GetString(kXmppLoginConfigPath, &xmpp_login_) ||
        !(config_.GetString(kXmppAuthTokenConfigPath, &xmpp_auth_token_) ||
          config_.GetString(kOAuthRefreshTokenConfigPath,
                            &oauth_refresh_token_))) {
      LOG(ERROR) << "XMPP credentials are not defined in the config.";
      return false;
    }

    config_.GetBoolean(kOAuthUseOfficialClientIdConfigPath,
                       &oauth_use_official_client_id_);

    if (!oauth_refresh_token_.empty()) {
      xmpp_auth_token_ = "";  // This will be set to the access token later.
      xmpp_auth_service_ = "oauth2";
    } else if (!config_.GetString(kXmppAuthServiceConfigPath,
                                  &xmpp_auth_service_)) {
      xmpp_auth_service_ = kChromotingTokenDefaultServiceName;
    }
    return true;
  }

Project: Chrome

  explicit HostProcess(scoped_ptr<ChromotingHostContext> context)
      : context_(context.Pass()),
        config_(FilePath()),
#ifdef OFFICIAL_BUILD
        oauth_use_official_client_id_(true),
#else
        oauth_use_official_client_id_(false),
#endif
        allow_nat_traversal_(true),
        restarting_(false),
        shutting_down_(false),
#if defined(OS_WIN)
        desktop_environment_factory_(new SessionDesktopEnvironmentFactory(
            context_->input_task_runner(), context_->ui_task_runner())),
#else  // !defined(OS_WIN)
        desktop_environment_factory_(new DesktopEnvironmentFactory(
            context_->input_task_runner(), context_->ui_task_runner())),
#endif  // !defined(OS_WIN)
        desktop_resizer_(DesktopResizer::Create()),
        exit_code_(kSuccessExitCode) {
    network_change_notifier_.reset(net::NetworkChangeNotifier::Create());
    curtain_ = CurtainMode::Create(
        base::Bind(&HostProcess::OnDisconnectRequested,
                   base::Unretained(this)),
        base::Bind(&HostProcess::OnDisconnectRequested,
                   base::Unretained(this)));
}

Project: Chrome

  bool InitWithCommandLine(const CommandLine* cmd_line) {
    std::string channel_name =
        cmd_line->GetSwitchValueASCII(kDaemonIpcSwitchName);

#if defined(REMOTING_MULTI_PROCESS)
    if (channel_name.empty())
      return false;
#endif  // defined(REMOTING_MULTI_PROCESS)

    if (!channel_name.empty()) {
      daemon_channel_.reset(new IPC::ChannelProxy(
          channel_name, IPC::Channel::MODE_CLIENT, this,
          context_->network_task_runner()));
    }

#if !defined(REMOTING_MULTI_PROCESS)
    FilePath default_config_dir = remoting::GetConfigDir();
    host_config_path_ = default_config_dir.Append(kDefaultHostConfigFile);
    if (cmd_line->HasSwitch(kHostConfigSwitchName)) {
      host_config_path_ = cmd_line->GetSwitchValuePath(kHostConfigSwitchName);
    }
#endif  // !defined(REMOTING_MULTI_PROCESS)

    return true;
  }

Project: Chrome

  void ListenForShutdownSignal() {
#if defined(OS_POSIX)
    remoting::RegisterSignalHandler(
        SIGTERM,
        base::Bind(&HostProcess::SigTermHandler, base::Unretained(this)));
#endif  // OS_POSIX
  }

Project: Chrome

  bool OnCurtainPolicyUpdate(bool curtain_required) {
    DCHECK(context_->network_task_runner()->BelongsToCurrentThread());

#if defined(OS_MACOSX)
    if (curtain_required) {
      if (getuid() == 0) {
        Shutdown(kLoginScreenNotSupportedExitCode);
        return false;
      }
    }
#endif
    if (curtain_->required() != curtain_required) {
      LOG(INFO) << "Updated curtain policy.";
      curtain_->set_required(curtain_required);
      return true;
    }
    return false;
  }

Project: Chrome

  void OnDisconnectRequested() {
    if (!context_->network_task_runner()->BelongsToCurrentThread()) {
      context_->network_task_runner()->PostTask(FROM_HERE, base::Bind(
          &HostProcess::OnDisconnectRequested, base::Unretained(this)));
      return;
    }
    if (host_) {
      host_->DisconnectAllClients();
    }
  }

Project: Chrome

  bool OnHostDomainPolicyUpdate(const std::string& host_domain) {
    DCHECK(context_->network_task_runner()->BelongsToCurrentThread());

    if (!host_domain.empty() &&
        !EndsWith(xmpp_login_, std::string("@") + host_domain, false)) {
      Shutdown(kInvalidHostDomainExitCode);
    }
    return false;
  }

Project: Chrome

  bool OnHostTalkGadgetPrefixPolicyUpdate(
      const std::string& talkgadget_prefix) {
    DCHECK(context_->network_task_runner()->BelongsToCurrentThread());

    if (talkgadget_prefix != talkgadget_prefix_) {
      LOG(INFO) << "Updated talkgadget policy.";
      talkgadget_prefix_ = talkgadget_prefix;
      return true;
    }
    return false;
  }

Project: Chrome

  virtual bool OnMessageReceived(const IPC::Message& message) {
    DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());

#if defined(REMOTING_MULTI_PROCESS)
    bool handled = true;
    IPC_BEGIN_MESSAGE_MAP(HostProcess, message)
        IPC_MESSAGE_HANDLER(ChromotingDaemonNetworkMsg_Configuration,
                            OnConfigUpdated)
        IPC_MESSAGE_UNHANDLED(handled = false)
    IPC_END_MESSAGE_MAP()
    return handled;
#else  // !defined(REMOTING_MULTI_PROCESS)
    return false;
#endif  // !defined(REMOTING_MULTI_PROCESS)
  }

Project: Chrome

  void OnPolicyUpdate(scoped_ptr<base::DictionaryValue> policies) {
    if (!context_->network_task_runner()->BelongsToCurrentThread()) {
      context_->network_task_runner()->PostTask(FROM_HERE, base::Bind(
          &HostProcess::OnPolicyUpdate, base::Unretained(this),
          base::Passed(&policies)));
      return;
    }

    bool restart_required = false;
    bool bool_value;
    std::string string_value;
    if (policies->GetString(policy_hack::PolicyWatcher::kHostDomainPolicyName,
                            &string_value)) {
      restart_required |= OnHostDomainPolicyUpdate(string_value);
    }
    if (policies->GetBoolean(policy_hack::PolicyWatcher::kNatPolicyName,
                             &bool_value)) {
      restart_required |= OnNatPolicyUpdate(bool_value);
    }
    if (policies->GetString(
            policy_hack::PolicyWatcher::kHostTalkGadgetPrefixPolicyName,
            &string_value)) {
      restart_required |= OnHostTalkGadgetPrefixPolicyUpdate(string_value);
    }
    if (policies->GetBoolean(
            policy_hack::PolicyWatcher::kHostRequireCurtainPolicyName,
            &bool_value)) {
      restart_required |= OnCurtainPolicyUpdate(bool_value);
    }
    if (!host_) {
      StartHost();
    } else if (restart_required) {
      RestartHost();
    }
  }

Project: Chrome

  void OnShutdownFinished() {
    DCHECK(context_->network_task_runner()->BelongsToCurrentThread());

    host_ = NULL;
    ResetHost();

    context_->ui_task_runner()->PostTask(
        FROM_HERE,
        base::Bind(&HostProcess::ShutdownHostProcess,
                   base::Unretained(this)));
  }

Project: Chrome

void QuitMessageLoop(MessageLoop* message_loop) {
  message_loop->PostTask(FROM_HERE, MessageLoop::QuitClosure());
}

Project: Chrome

  void ResetHost() {
    DCHECK(context_->network_task_runner()->BelongsToCurrentThread());

    curtaining_host_observer_.reset();
    host_event_logger_.reset();
    log_to_server_.reset();
    heartbeat_sender_.reset();
    signaling_connector_.reset();
    signal_strategy_.reset();
    resizing_host_observer_.reset();
  }

Project: Chrome

  void RestartOnHostShutdown() {
    DCHECK(context_->network_task_runner()->BelongsToCurrentThread());

    if (shutting_down_)
      return;

    restarting_ = false;
    host_ = NULL;
    ResetHost();

    StartHost();
  }

Project: Chrome

  void Shutdown(int exit_code) {
    DCHECK(context_->network_task_runner()->BelongsToCurrentThread());

    if (shutting_down_)
      return;

    shutting_down_ = true;
    exit_code_ = exit_code;
    if (host_) {
      host_->Shutdown(base::Bind(
          &HostProcess::OnShutdownFinished, base::Unretained(this)));
    } else {
      OnShutdownFinished();
    }
  }

Project: Chrome

  void ShutdownHostProcess() {
    DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());

    config_watcher_.reset();
    daemon_channel_.reset();
    desktop_environment_factory_.reset();
    host_user_interface_.reset();

    if (policy_watcher_.get()) {
      base::WaitableEvent done_event(true, false);
      policy_watcher_->StopWatching(&done_event);
      done_event.Wait();
      policy_watcher_.reset();
    }

    context_.reset();
  }

Project: Chrome

  void StartHost() {
    DCHECK(context_->network_task_runner()->BelongsToCurrentThread());
    DCHECK(!host_);
    DCHECK(!signal_strategy_.get());

    if (shutting_down_)
      return;

    signal_strategy_.reset(
        new XmppSignalStrategy(context_->url_request_context_getter(),
                               xmpp_login_, xmpp_auth_token_,
                               xmpp_auth_service_));

    scoped_ptr<DnsBlackholeChecker> dns_blackhole_checker(
        new DnsBlackholeChecker(context_->url_request_context_getter(),
                                talkgadget_prefix_));

    signaling_connector_.reset(new SignalingConnector(
        signal_strategy_.get(),
        context_->url_request_context_getter(),
        dns_blackhole_checker.Pass(),
        base::Bind(&HostProcess::OnAuthFailed, base::Unretained(this))));

    if (!oauth_refresh_token_.empty()) {
      OAuthClientInfo client_info = {
        kUnofficialOAuth2ClientId,
        kUnofficialOAuth2ClientSecret
      };

#ifdef OFFICIAL_BUILD
      if (oauth_use_official_client_id_) {
        OAuthClientInfo official_client_info = {
            google_apis::GetOAuth2ClientID(google_apis::CLIENT_REMOTING),
            google_apis::GetOAuth2ClientSecret(google_apis::CLIENT_REMOTING)
        };

        client_info = official_client_info;
      }
#endif  // OFFICIAL_BUILD

      scoped_ptr<SignalingConnector::OAuthCredentials> oauth_credentials(
          new SignalingConnector::OAuthCredentials(
              xmpp_login_, oauth_refresh_token_, client_info));
      signaling_connector_->EnableOAuth(oauth_credentials.Pass());
    }

    NetworkSettings network_settings(
        allow_nat_traversal_ ?
        NetworkSettings::NAT_TRAVERSAL_ENABLED :
        NetworkSettings::NAT_TRAVERSAL_DISABLED);
    if (!allow_nat_traversal_) {
      network_settings.min_port = NetworkSettings::kDefaultMinPort;
      network_settings.max_port = NetworkSettings::kDefaultMaxPort;
    }

    host_ = new ChromotingHost(
        signal_strategy_.get(),
        desktop_environment_factory_.get(),
        CreateHostSessionManager(network_settings,
                                 context_->url_request_context_getter()),
        context_->capture_task_runner(),
        context_->encode_task_runner(),
        context_->network_task_runner());

#if defined(OS_LINUX)
    host_->SetMaximumSessionDuration(base::TimeDelta::FromHours(20));
#endif

    heartbeat_sender_.reset(new HeartbeatSender(
        this, host_id_, signal_strategy_.get(), &key_pair_));

    log_to_server_.reset(
        new LogToServer(host_, ServerLogEntry::ME2ME, signal_strategy_.get()));
    host_event_logger_ = HostEventLogger::Create(host_, kApplicationName);

    resizing_host_observer_.reset(
        new ResizingHostObserver(desktop_resizer_.get(), host_));

    curtaining_host_observer_.reset(new CurtainingHostObserver(
          curtain_.get(), host_));

    if (host_user_interface_.get()) {
      host_user_interface_->Start(
          host_, base::Bind(&HostProcess::OnDisconnectRequested,
                            base::Unretained(this)));
    }

    host_->Start(xmpp_login_);

    CreateAuthenticatorFactory();
  }

Project: Chrome

  void StartHostProcess() {
    DCHECK(context_->ui_task_runner()->BelongsToCurrentThread());

    if (!InitWithCommandLine(CommandLine::ForCurrentProcess())) {
      OnConfigWatcherError();
      return;
    }

    context_->network_task_runner()->PostTask(
        FROM_HERE,
        base::Bind(&HostProcess::ListenForShutdownSignal,
                   base::Unretained(this)));

    StartWatchingConfigChanges();
  }

Project: Chrome

  void StartWatchingConfigChanges() {
#if !defined(REMOTING_MULTI_PROCESS)
    config_watcher_.reset(new ConfigFileWatcher(context_->ui_task_runner(),
                                                context_->file_task_runner(),
                                                this));
    config_watcher_->Watch(host_config_path_);
#endif  // !defined(REMOTING_MULTI_PROCESS)
  }

Project: Chrome

  void StartWatchingPolicy() {
    policy_watcher_.reset(
        policy_hack::PolicyWatcher::Create(context_->file_task_runner()));
    policy_watcher_->StartWatching(
        base::Bind(&HostProcess::OnPolicyUpdate, base::Unretained(this)));
  }

Project: Chrome

int CALLBACK WinMain(HINSTANCE instance,
                     HINSTANCE previous_instance,
                     LPSTR command_line,
                     int show_command) {
#ifdef OFFICIAL_BUILD
  if (remoting::IsUsageStatsAllowed()) {
    remoting::InitializeCrashReporting();
  }
#endif  // OFFICIAL_BUILD

  g_hModule = instance;

  INITCOMMONCONTROLSEX info;
  info.dwSize = sizeof(info);
  info.dwICC = ICC_STANDARD_CLASSES;
  InitCommonControlsEx(&info);

  if (base::win::GetVersion() >= base::win::VERSION_VISTA) {
    FilePath path(base::GetNativeLibraryName(UTF8ToUTF16("user32")));
    base::ScopedNativeLibrary user32(path);
    CHECK(user32.is_valid());

    typedef BOOL (WINAPI * SetProcessDPIAwareFn)();
    SetProcessDPIAwareFn set_process_dpi_aware =
        static_cast<SetProcessDPIAwareFn>(
            user32.GetFunctionPointer("SetProcessDPIAware"));
    set_process_dpi_aware();
  }

  return main(0, NULL);
}