blob: 789f9bf7cace01980d6ada7dff9acc1fa857c683 [file] [log] [blame]
David Purselle5ebdae2014-11-04 08:51:37 -08001// Copyright 2014 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "debugd/src/dev_features_tool.h"
6
7#include <functional>
8
Eric Caruso75eda082017-04-25 11:37:26 -07009#include <base/bind.h>
10#include <base/callback.h>
David Purselle5ebdae2014-11-04 08:51:37 -080011#include <chromeos/dbus/service_constants.h>
12
Eric Carusocc7106c2017-04-27 14:22:42 -070013#include "debugd/src/error_utils.h"
David Purselle5ebdae2014-11-04 08:51:37 -080014#include "debugd/src/process_with_output.h"
15
16namespace debugd {
17
18namespace {
19
Ben Chan81905fb2017-02-08 22:03:11 -080020using ArgList = ProcessWithOutput::ArgList;
David Purselle5ebdae2014-11-04 08:51:37 -080021
David Pursellab8412f2014-12-09 13:41:12 -080022const char kDefaultRootPassword[] = "test0000";
23
David Purselle5ebdae2014-11-04 08:51:37 -080024const char kDevFeaturesErrorString[] = "org.chromium.debugd.error.DevFeatures";
25const char kRootfsLockedErrorString[] =
26 "Rootfs verification must be removed first";
27
28// Executes a helper process with the expectation that any message printed to
29// stderr indicates a failure that should be passed back over the D-Bus.
Eric Caruso8fe49c72017-04-25 10:43:59 -070030// Returns false if any errors launching the process occur. Returns true
31// otherwise, and sets |exit_status| if it isn't null.
32bool RunHelper(const std::string& command,
33 const ArgList& arguments,
34 bool requires_root,
35 const std::string* stdin,
36 int* exit_status,
Eric Carusocc7106c2017-04-27 14:22:42 -070037 brillo::ErrorPtr* error) {
David Purselle5ebdae2014-11-04 08:51:37 -080038 std::string stderr;
Tom Hughesd6c2d392020-08-24 18:12:11 -070039 int result =
40 ProcessWithOutput::RunHelper(command, arguments, requires_root, stdin,
41 nullptr, // Don't need stdout.
42 &stderr, error);
David Purselle5ebdae2014-11-04 08:51:37 -080043 if (!stderr.empty()) {
Eric Carusocc7106c2017-04-27 14:22:42 -070044 DEBUGD_ADD_ERROR(error, kDevFeaturesErrorString, stderr.c_str());
Eric Caruso8fe49c72017-04-25 10:43:59 -070045 return false;
David Purselle5ebdae2014-11-04 08:51:37 -080046 }
Eric Caruso8fe49c72017-04-25 10:43:59 -070047
48 if (exit_status)
49 *exit_status = result;
50 return true;
David Purselle5ebdae2014-11-04 08:51:37 -080051}
52
Eric Carusocc7106c2017-04-27 14:22:42 -070053bool RemoveRootfsVerificationQuery(int* exit_status, brillo::ErrorPtr* error) {
Eric Caruso75eda082017-04-25 11:37:26 -070054 return RunHelper("dev_features_rootfs_verification", ArgList{"-q"},
Tom Hughesd6c2d392020-08-24 18:12:11 -070055 true, // requires root to check if / is writable by root.
Eric Caruso75eda082017-04-25 11:37:26 -070056 nullptr, // no stdin.
Tom Hughesd6c2d392020-08-24 18:12:11 -070057 exit_status, error);
Eric Caruso75eda082017-04-25 11:37:26 -070058}
59
Eric Carusocc7106c2017-04-27 14:22:42 -070060bool EnableBootFromUsbQuery(int* exit_status, brillo::ErrorPtr* error) {
Eric Caruso75eda082017-04-25 11:37:26 -070061 return RunHelper("dev_features_usb_boot", ArgList{"-q"},
Tom Hughesd6c2d392020-08-24 18:12:11 -070062 true, // requires root for crossystem queries.
Eric Caruso75eda082017-04-25 11:37:26 -070063 nullptr, // no stdin.
Tom Hughesd6c2d392020-08-24 18:12:11 -070064 exit_status, error);
Eric Caruso75eda082017-04-25 11:37:26 -070065}
66
Eric Carusocc7106c2017-04-27 14:22:42 -070067bool ConfigureSshServerQuery(int* exit_status, brillo::ErrorPtr* error) {
Eric Caruso75eda082017-04-25 11:37:26 -070068 return RunHelper("dev_features_ssh", ArgList{"-q"},
Tom Hughesd6c2d392020-08-24 18:12:11 -070069 true, // needs root to check for files in 700 folders.
Eric Caruso75eda082017-04-25 11:37:26 -070070 nullptr, // no stdin.
Tom Hughesd6c2d392020-08-24 18:12:11 -070071 exit_status, error);
Eric Caruso75eda082017-04-25 11:37:26 -070072}
73
Eric Carusocc7106c2017-04-27 14:22:42 -070074bool EnableChromeRemoteDebuggingQuery(int* exit_status,
75 brillo::ErrorPtr* error) {
Tom Hughesd6c2d392020-08-24 18:12:11 -070076 return RunHelper("dev_features_chrome_remote_debugging", ArgList{"-q"}, false,
Eric Caruso75eda082017-04-25 11:37:26 -070077 nullptr, // no stdin.
Tom Hughesd6c2d392020-08-24 18:12:11 -070078 exit_status, error);
Eric Caruso75eda082017-04-25 11:37:26 -070079}
80
81bool SetUserPasswordQuery(const std::string& username,
82 bool system,
Eric Caruso8fe49c72017-04-25 10:43:59 -070083 int* exit_status,
Eric Carusocc7106c2017-04-27 14:22:42 -070084 brillo::ErrorPtr* error) {
Eric Caruso75eda082017-04-25 11:37:26 -070085 ArgList args{"-q", "--user=" + username};
86 if (system)
87 args.push_back("--system");
88
89 return RunHelper("dev_features_password", args,
Tom Hughesd6c2d392020-08-24 18:12:11 -070090 true, // requires root to read either password file.
Eric Caruso75eda082017-04-25 11:37:26 -070091 nullptr, // no stdin.
Tom Hughesd6c2d392020-08-24 18:12:11 -070092 exit_status, error);
Eric Caruso75eda082017-04-25 11:37:26 -070093}
94
David Purselle5ebdae2014-11-04 08:51:37 -080095} // namespace
96
Eric Carusocc7106c2017-04-27 14:22:42 -070097bool DevFeaturesTool::RemoveRootfsVerification(brillo::ErrorPtr* error) const {
Eric Caruso8fe49c72017-04-25 10:43:59 -070098 return RunHelper("dev_features_rootfs_verification", ArgList{},
Tom Hughesd6c2d392020-08-24 18:12:11 -070099 true, // requires root for make_dev_ssd.sh script.
Eric Caruso8fe49c72017-04-25 10:43:59 -0700100 nullptr, // no stdin.
101 nullptr, // exit status doesn't matter.
102 error);
David Purselle5ebdae2014-11-04 08:51:37 -0800103}
104
Eric Carusocc7106c2017-04-27 14:22:42 -0700105bool DevFeaturesTool::EnableBootFromUsb(brillo::ErrorPtr* error) const {
Eric Caruso8fe49c72017-04-25 10:43:59 -0700106 return RunHelper("dev_features_usb_boot", ArgList{},
Tom Hughesd6c2d392020-08-24 18:12:11 -0700107 true, // requires root for enable_dev_usb_boot script.
Eric Caruso8fe49c72017-04-25 10:43:59 -0700108 nullptr, // no stdin.
109 nullptr, // exit status doesn't matter.
110 error);
David Purselle5ebdae2014-11-04 08:51:37 -0800111}
112
Eric Carusocc7106c2017-04-27 14:22:42 -0700113bool DevFeaturesTool::ConfigureSshServer(brillo::ErrorPtr* error) const {
David Purselle5ebdae2014-11-04 08:51:37 -0800114 // SSH server configuration requires writing to rootfs.
Eric Caruso8fe49c72017-04-25 10:43:59 -0700115 int exit_status;
116 if (!RemoveRootfsVerificationQuery(&exit_status, error) || exit_status != 0) {
Eric Carusocc7106c2017-04-27 14:22:42 -0700117 DEBUGD_ADD_ERROR(error, kDevFeaturesErrorString, kRootfsLockedErrorString);
Eric Caruso8fe49c72017-04-25 10:43:59 -0700118 return false;
David Purselle5ebdae2014-11-04 08:51:37 -0800119 }
Eric Caruso8fe49c72017-04-25 10:43:59 -0700120
121 return RunHelper("dev_features_ssh", ArgList{},
Tom Hughesd6c2d392020-08-24 18:12:11 -0700122 true, // requires root to write to rootfs directories.
Eric Caruso8fe49c72017-04-25 10:43:59 -0700123 nullptr, // no stdin.
124 nullptr, // exit status doesn't matter.
125 error);
David Purselle5ebdae2014-11-04 08:51:37 -0800126}
127
Tom Hughesd6c2d392020-08-24 18:12:11 -0700128bool DevFeaturesTool::EnableChromeRemoteDebugging(
129 brillo::ErrorPtr* error) const {
Eric Caruso8fe49c72017-04-25 10:43:59 -0700130 int exit_status;
131 if (!RemoveRootfsVerificationQuery(&exit_status, error) || exit_status != 0) {
Eric Carusocc7106c2017-04-27 14:22:42 -0700132 DEBUGD_ADD_ERROR(error, kDevFeaturesErrorString, kRootfsLockedErrorString);
Eric Caruso8fe49c72017-04-25 10:43:59 -0700133 return false;
Xiaohui Chena8bced82015-02-27 10:35:26 -0800134 }
Eric Caruso8fe49c72017-04-25 10:43:59 -0700135
136 return RunHelper("dev_features_chrome_remote_debugging", ArgList{},
Tom Hughesd6c2d392020-08-24 18:12:11 -0700137 true, // requires root to write to rootfs directories.
Eric Caruso8fe49c72017-04-25 10:43:59 -0700138 nullptr, // no stdin.
139 nullptr, // exit status doesn't matter.
140 error);
Xiaohui Chena8bced82015-02-27 10:35:26 -0800141}
142
Eric Caruso8fe49c72017-04-25 10:43:59 -0700143bool DevFeaturesTool::SetUserPassword(const std::string& username,
David Purselle5ebdae2014-11-04 08:51:37 -0800144 const std::string& password,
Eric Carusocc7106c2017-04-27 14:22:42 -0700145 brillo::ErrorPtr* error) const {
David Purselle5ebdae2014-11-04 08:51:37 -0800146 ArgList args{"--user=" + username};
147
148 // Set the devmode password regardless of rootfs verification state.
Eric Caruso8fe49c72017-04-25 10:43:59 -0700149 if (!RunHelper("dev_features_password", args,
Tom Hughesd6c2d392020-08-24 18:12:11 -0700150 true, // requires root to write devmode password file.
Eric Caruso8fe49c72017-04-25 10:43:59 -0700151 &password, // pipe the password through stdin.
Tom Hughesd6c2d392020-08-24 18:12:11 -0700152 nullptr, // exit status doesn't matter.
Eric Caruso8fe49c72017-04-25 10:43:59 -0700153 error)) {
154 return false;
David Purselle5ebdae2014-11-04 08:51:37 -0800155 }
Eric Caruso8fe49c72017-04-25 10:43:59 -0700156
157 // If rootfs is locked, don't bother setting the system password.
158 int exit_status;
159 if (!RemoveRootfsVerificationQuery(&exit_status, error) || exit_status != 0)
160 return true;
161
162 args.push_back("--system");
163 return RunHelper("dev_features_password", args,
Tom Hughesd6c2d392020-08-24 18:12:11 -0700164 true, // requires root to write system password file.
Eric Caruso8fe49c72017-04-25 10:43:59 -0700165 &password, // pipe the password through stdin.
Tom Hughesd6c2d392020-08-24 18:12:11 -0700166 nullptr, // exit status doesn't matter.
Eric Caruso8fe49c72017-04-25 10:43:59 -0700167 error);
David Purselle5ebdae2014-11-04 08:51:37 -0800168}
169
Eric Caruso8fe49c72017-04-25 10:43:59 -0700170bool DevFeaturesTool::EnableChromeDevFeatures(const std::string& root_password,
Eric Carusocc7106c2017-04-27 14:22:42 -0700171 brillo::ErrorPtr* error) const {
Eric Caruso8fe49c72017-04-25 10:43:59 -0700172 if (!EnableBootFromUsb(error))
173 return false;
174
175 if (!ConfigureSshServer(error))
176 return false;
177
178 return SetUserPassword(
Tom Hughesd6c2d392020-08-24 18:12:11 -0700179 "root", root_password.empty() ? kDefaultRootPassword : root_password,
Eric Caruso8fe49c72017-04-25 10:43:59 -0700180 error);
David Purselle5ebdae2014-11-04 08:51:37 -0800181}
182
183namespace {
184
185struct Query {
Eric Caruso8fe49c72017-04-25 10:43:59 -0700186 // The callback should launch the query program. If launching fails, return
187 // false and set the error. If it succeeds, put the exit status in the
188 // integer out-argument.
Eric Carusocc7106c2017-04-27 14:22:42 -0700189 using Function = base::Callback<bool(int*, brillo::ErrorPtr*)>;
David Purselle5ebdae2014-11-04 08:51:37 -0800190
191 Function function;
192 DevFeatureFlag flag;
193};
194
195} // namespace
196
Eric Caruso8fe49c72017-04-25 10:43:59 -0700197bool DevFeaturesTool::QueryDevFeatures(int32_t* flags,
Eric Carusocc7106c2017-04-27 14:22:42 -0700198 brillo::ErrorPtr* error) const {
Eric Caruso8fe49c72017-04-25 10:43:59 -0700199 DCHECK(flags);
David Purselle5ebdae2014-11-04 08:51:37 -0800200 Query queries[] = {
Eric Caruso75eda082017-04-25 11:37:26 -0700201 {base::Bind(&RemoveRootfsVerificationQuery),
Tom Hughesd6c2d392020-08-24 18:12:11 -0700202 DEV_FEATURE_ROOTFS_VERIFICATION_REMOVED},
203 {base::Bind(&EnableBootFromUsbQuery), DEV_FEATURE_BOOT_FROM_USB_ENABLED},
Eric Caruso75eda082017-04-25 11:37:26 -0700204 {base::Bind(&EnableChromeRemoteDebuggingQuery),
Tom Hughesd6c2d392020-08-24 18:12:11 -0700205 DEV_FEATURE_CHROME_REMOTE_DEBUGGING_ENABLED},
206 {base::Bind(&ConfigureSshServerQuery), DEV_FEATURE_SSH_SERVER_CONFIGURED},
Eric Caruso75eda082017-04-25 11:37:26 -0700207 {base::Bind(&SetUserPasswordQuery, "root", /* system = */ false),
Tom Hughesd6c2d392020-08-24 18:12:11 -0700208 DEV_FEATURE_DEV_MODE_ROOT_PASSWORD_SET},
Eric Caruso75eda082017-04-25 11:37:26 -0700209 {base::Bind(&SetUserPasswordQuery, "root", /* system = */ true),
Tom Hughesd6c2d392020-08-24 18:12:11 -0700210 DEV_FEATURE_SYSTEM_ROOT_PASSWORD_SET}};
David Purselle5ebdae2014-11-04 08:51:37 -0800211
Eric Caruso8fe49c72017-04-25 10:43:59 -0700212 int32_t result_flags = 0;
David Purselle5ebdae2014-11-04 08:51:37 -0800213 for (const auto& query : queries) {
Eric Caruso8fe49c72017-04-25 10:43:59 -0700214 int exit_status;
215 if (!query.function.Run(&exit_status, error)) {
216 // D-Bus is only set up to handle a single error so exit as soon as we
217 // hit one.
218 return false;
219 }
220 if (exit_status == 0)
221 result_flags |= query.flag;
David Purselle5ebdae2014-11-04 08:51:37 -0800222 }
Eric Caruso8fe49c72017-04-25 10:43:59 -0700223 *flags = result_flags;
224 return true;
David Purselle5ebdae2014-11-04 08:51:37 -0800225}
226
227} // namespace debugd