blob: 4bda7e5d41a251098316b33320aaa712e1efa68e [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
9#include <base/files/file_path.h>
10#include <base/files/file_util.h>
11#include <chromeos/dbus/service_constants.h>
12
13#include "debugd/src/process_with_output.h"
14
15namespace debugd {
16
17namespace {
18
19typedef ProcessWithOutput::ArgList ArgList;
20
David Pursellab8412f2014-12-09 13:41:12 -080021const char kDefaultRootPassword[] = "test0000";
22
David Purselle5ebdae2014-11-04 08:51:37 -080023const char kDevFeaturesErrorString[] = "org.chromium.debugd.error.DevFeatures";
24const char kRootfsLockedErrorString[] =
25 "Rootfs verification must be removed first";
26
27// Executes a helper process with the expectation that any message printed to
28// stderr indicates a failure that should be passed back over the D-Bus.
29int RunHelper(const std::string& command,
30 const ArgList& arguments,
31 bool requires_root,
32 const std::string* stdin,
33 DBus::Error* error) {
34 std::string stderr;
35 int result = ProcessWithOutput::RunHelper(command,
36 arguments,
37 requires_root,
38 stdin,
39 nullptr, // Don't need stdout.
40 &stderr,
41 error);
42 if (!stderr.empty()) {
43 if (error && !error->is_set()) {
44 error->set(kDevFeaturesErrorString, stderr.c_str());
45 }
46 }
47 return result;
48}
49
50} // namespace
51
52void DevFeaturesTool::RemoveRootfsVerification(DBus::Error* error) const {
53 RunHelper("dev_features_rootfs_verification", ArgList{},
54 true, // requires root for make_dev_ssd.sh script.
55 nullptr, // no stdin.
56 error);
57}
58
59bool DevFeaturesTool::RemoveRootfsVerificationQuery(DBus::Error* error) const {
60 return RunHelper("dev_features_rootfs_verification", ArgList{"-q"},
61 true, // requires root to check if / is writable by root.
62 nullptr, // no stdin.
63 error) == 0;
64}
65
66void DevFeaturesTool::EnableBootFromUsb(DBus::Error* error) const {
67 RunHelper("dev_features_usb_boot", ArgList{},
68 true, // requires root for enable_dev_usb_boot script.
69 nullptr, // no stdin.
70 error);
71}
72
73bool DevFeaturesTool::EnableBootFromUsbQuery(DBus::Error* error) const {
74 return RunHelper("dev_features_usb_boot", ArgList{"-q"},
75 true, // requires root for crossystem queries.
76 nullptr, // no stdin.
77 error) == 0;
78}
79
80void DevFeaturesTool::ConfigureSshServer(DBus::Error* error) const {
81 // SSH server configuration requires writing to rootfs.
82 if (RemoveRootfsVerificationQuery(error)) {
83 RunHelper("dev_features_ssh", ArgList{},
84 true, // requires root to write to rootfs directories.
85 nullptr, // no stdin.
86 error);
87 } else if (!error->is_set()) {
88 error->set(kDevFeaturesErrorString, kRootfsLockedErrorString);
89 }
90}
91
92bool DevFeaturesTool::ConfigureSshServerQuery(DBus::Error* error) const {
93 return RunHelper("dev_features_ssh", ArgList{"-q"},
94 true, // needs root to check for files in 700 folders.
95 nullptr, // no stdin.
96 error) == 0;
97}
98
Xiaohui Chena8bced82015-02-27 10:35:26 -080099void DevFeaturesTool::EnableChromeRemoteDebugging(DBus::Error* error) const {
100 if (RemoveRootfsVerificationQuery(error)) {
101 RunHelper("dev_features_chrome_remote_debugging", ArgList{},
102 true, // requires root to write to rootfs directories.
103 nullptr, // no stdin.
104 error);
105 } else if (!error->is_set()) {
106 error->set(kDevFeaturesErrorString, kRootfsLockedErrorString);
107 }
108}
109
110bool DevFeaturesTool::EnableChromeRemoteDebuggingQuery(
111 DBus::Error* error) const {
112 return RunHelper("dev_features_chrome_remote_debugging", ArgList{"-q"},
113 false,
114 nullptr, // no stdin.
115 error) == 0;
116}
117
David Purselle5ebdae2014-11-04 08:51:37 -0800118void DevFeaturesTool::SetUserPassword(const std::string& username,
119 const std::string& password,
120 DBus::Error* error) const {
121 ArgList args{"--user=" + username};
122
123 // Set the devmode password regardless of rootfs verification state.
124 RunHelper("dev_features_password", args,
125 true, // requires root to write devmode password file.
126 &password, // pipe the password through stdin.
127 error);
128 if (!error->is_set()) {
129 // If rootfs is unlocked, we should set the system password as well.
130 if (RemoveRootfsVerificationQuery(error)) {
131 args.push_back("--system");
132 RunHelper("dev_features_password", args,
133 true, // requires root to write system password file.
134 &password, // pipe the password through stdin.
135 error);
136 }
137 }
138}
139
140bool DevFeaturesTool::SetUserPasswordQuery(const std::string& username,
141 bool system,
142 DBus::Error* error) const {
143 ArgList args{"-q", "--user=" + username};
144 if (system) {
145 args.push_back("--system");
146 }
147 return RunHelper("dev_features_password", args,
148 true, // requires root to read either password file.
149 nullptr, // no stdin.
150 error) == 0;
151}
152
153void DevFeaturesTool::EnableChromeDevFeatures(const std::string& root_password,
154 DBus::Error* error) const {
155 EnableBootFromUsb(error);
156 if (error->is_set()) {
157 return;
158 }
159 ConfigureSshServer(error);
160 if (error->is_set()) {
161 return;
162 }
David Pursellab8412f2014-12-09 13:41:12 -0800163 SetUserPassword("root",
164 root_password.empty() ? kDefaultRootPassword : root_password,
165 error);
David Purselle5ebdae2014-11-04 08:51:37 -0800166}
167
168namespace {
169
170struct Query {
171 typedef std::function<bool(void)> Function;
172
173 Query(Function _function, DevFeatureFlag _flag)
174 : function(_function), flag(_flag) {
175 }
176
177 Function function;
178 DevFeatureFlag flag;
179};
180
181} // namespace
182
183int32_t DevFeaturesTool::QueryDevFeatures(DBus::Error* error) const {
184 Query queries[] = {
185 Query(std::bind(&DevFeaturesTool::RemoveRootfsVerificationQuery,
186 this, error),
187 DEV_FEATURE_ROOTFS_VERIFICATION_REMOVED),
188 Query(std::bind(&DevFeaturesTool::EnableBootFromUsbQuery,
189 this, error),
190 DEV_FEATURE_BOOT_FROM_USB_ENABLED),
Xiaohui Chena8bced82015-02-27 10:35:26 -0800191 Query(std::bind(&DevFeaturesTool::EnableChromeRemoteDebuggingQuery,
192 this, error),
193 DEV_FEATURE_CHROME_REMOTE_DEBUGGING_ENABLED),
David Purselle5ebdae2014-11-04 08:51:37 -0800194 Query(std::bind(&DevFeaturesTool::ConfigureSshServerQuery,
195 this, error),
196 DEV_FEATURE_SSH_SERVER_CONFIGURED),
197 Query(std::bind(&DevFeaturesTool::SetUserPasswordQuery,
198 this, "root", false, error), // false = devmode password.
199 DEV_FEATURE_DEV_MODE_ROOT_PASSWORD_SET),
200 Query(std::bind(&DevFeaturesTool::SetUserPasswordQuery,
201 this, "root", true, error), // true = system password.
202 DEV_FEATURE_SYSTEM_ROOT_PASSWORD_SET)
203 };
204
205 int32_t flags = 0;
206 for (const auto& query : queries) {
207 if (query.function()) {
208 flags |= query.flag;
209 }
210 // D-Bus is only set up to handle a single error so exit as soon as we
211 // hit one.
212 if (error->is_set()) {
213 return 0;
214 }
215 }
216 return flags;
217}
218
219} // namespace debugd