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