blob: d31cb3dff08e8fdfd67108dbfee3bb7d86dba85f [file] [log] [blame]
Josh Gaob789fb12019-10-24 19:02:14 -07001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define ANDROID_BASE_UNIQUE_FD_DISABLE_IMPLICIT_CONVERSION
18
19#include "include/adbd_auth.h"
20
21#include <inttypes.h>
22#include <sys/epoll.h>
23#include <sys/eventfd.h>
24#include <sys/uio.h>
25
Arnaud Ferrariseaae22a2022-09-22 14:31:24 +020026#include <atomic>
Josh Gaob789fb12019-10-24 19:02:14 -070027#include <chrono>
28#include <deque>
Arnaud Ferrariseaae22a2022-09-22 14:31:24 +020029#include <optional>
Josh Gaob789fb12019-10-24 19:02:14 -070030#include <string>
31#include <string_view>
32#include <tuple>
33#include <unordered_map>
34#include <utility>
35#include <variant>
36#include <vector>
37
38#include <android-base/file.h>
39#include <android-base/logging.h>
40#include <android-base/macros.h>
41#include <android-base/strings.h>
42#include <android-base/thread_annotations.h>
43#include <android-base/unique_fd.h>
44#include <cutils/sockets.h>
45
46using android::base::unique_fd;
47
Joshua Duong3d0860e2019-10-11 15:43:47 -070048static constexpr uint32_t kAuthVersion = 1;
49
Josh Gaob789fb12019-10-24 19:02:14 -070050struct AdbdAuthPacketAuthenticated {
51 std::string public_key;
52};
53
54struct AdbdAuthPacketDisconnected {
55 std::string public_key;
56};
57
58struct AdbdAuthPacketRequestAuthorization {
59 std::string public_key;
60};
61
Joshua Duong3d0860e2019-10-11 15:43:47 -070062struct AdbdPacketTlsDeviceConnected {
63 uint8_t transport_type;
64 std::string public_key;
65};
66
67struct AdbdPacketTlsDeviceDisconnected {
68 uint8_t transport_type;
69 std::string public_key;
70};
71
72using AdbdAuthPacket = std::variant<AdbdAuthPacketAuthenticated,
73 AdbdAuthPacketDisconnected,
74 AdbdAuthPacketRequestAuthorization,
75 AdbdPacketTlsDeviceConnected,
76 AdbdPacketTlsDeviceDisconnected>;
Josh Gaob789fb12019-10-24 19:02:14 -070077
78struct AdbdAuthContext {
79 static constexpr uint64_t kEpollConstSocket = 0;
80 static constexpr uint64_t kEpollConstEventFd = 1;
81 static constexpr uint64_t kEpollConstFramework = 2;
82
83public:
84 explicit AdbdAuthContext(AdbdAuthCallbacksV1* callbacks) : next_id_(0), callbacks_(*callbacks) {
Joshua Duong3d0860e2019-10-11 15:43:47 -070085 InitFrameworkHandlers();
Josh Gaob789fb12019-10-24 19:02:14 -070086 epoll_fd_.reset(epoll_create1(EPOLL_CLOEXEC));
87 if (epoll_fd_ == -1) {
Josh Gao975cee72020-06-24 16:10:55 -070088 PLOG(FATAL) << "adbd_auth: failed to create epoll fd";
Josh Gaob789fb12019-10-24 19:02:14 -070089 }
90
91 event_fd_.reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
92 if (event_fd_ == -1) {
Josh Gao975cee72020-06-24 16:10:55 -070093 PLOG(FATAL) << "adbd_auth: failed to create eventfd";
Josh Gaob789fb12019-10-24 19:02:14 -070094 }
95
96 sock_fd_.reset(android_get_control_socket("adbd"));
97 if (sock_fd_ == -1) {
Josh Gao975cee72020-06-24 16:10:55 -070098 PLOG(ERROR) << "adbd_auth: failed to get adbd authentication socket";
Josh Gaob789fb12019-10-24 19:02:14 -070099 } else {
100 if (fcntl(sock_fd_.get(), F_SETFD, FD_CLOEXEC) != 0) {
Josh Gao975cee72020-06-24 16:10:55 -0700101 PLOG(FATAL) << "adbd_auth: failed to make adbd authentication socket cloexec";
Josh Gaob789fb12019-10-24 19:02:14 -0700102 }
103
104 if (fcntl(sock_fd_.get(), F_SETFL, O_NONBLOCK) != 0) {
Josh Gao975cee72020-06-24 16:10:55 -0700105 PLOG(FATAL) << "adbd_auth: failed to make adbd authentication socket nonblocking";
Josh Gaob789fb12019-10-24 19:02:14 -0700106 }
107
108 if (listen(sock_fd_.get(), 4) != 0) {
Josh Gao975cee72020-06-24 16:10:55 -0700109 PLOG(FATAL) << "adbd_auth: failed to listen on adbd authentication socket";
Josh Gaob789fb12019-10-24 19:02:14 -0700110 }
111 }
112 }
113
114 AdbdAuthContext(const AdbdAuthContext& copy) = delete;
115 AdbdAuthContext(AdbdAuthContext&& move) = delete;
116 AdbdAuthContext& operator=(const AdbdAuthContext& copy) = delete;
117 AdbdAuthContext& operator=(AdbdAuthContext&& move) = delete;
118
119 uint64_t NextId() { return next_id_++; }
120
121 void DispatchPendingPrompt() REQUIRES(mutex_) {
122 if (dispatched_prompt_) {
123 LOG(INFO) << "adbd_auth: prompt currently pending, skipping";
124 return;
125 }
126
127 if (pending_prompts_.empty()) {
128 LOG(INFO) << "adbd_auth: no prompts to send";
129 return;
130 }
131
132 LOG(INFO) << "adbd_auth: prompting user for adb authentication";
133 auto [id, public_key, arg] = std::move(pending_prompts_.front());
134 pending_prompts_.pop_front();
135
136 this->output_queue_.emplace_back(
137 AdbdAuthPacketRequestAuthorization{.public_key = public_key});
138
139 Interrupt();
140 dispatched_prompt_ = std::make_tuple(id, public_key, arg);
141 }
142
143 void UpdateFrameworkWritable() REQUIRES(mutex_) {
144 // This might result in redundant calls to EPOLL_CTL_MOD if, for example, we get notified
145 // at the same time as a framework connection, but that's unlikely and this doesn't need to
146 // be fast anyway.
147 if (framework_fd_ != -1) {
148 struct epoll_event event;
149 event.events = EPOLLIN;
150 if (!output_queue_.empty()) {
Josh Gao975cee72020-06-24 16:10:55 -0700151 LOG(INFO) << "adbd_auth: marking framework writable";
Josh Gaob789fb12019-10-24 19:02:14 -0700152 event.events |= EPOLLOUT;
153 }
154 event.data.u64 = kEpollConstFramework;
155 CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_MOD, framework_fd_.get(), &event));
156 }
157 }
158
159 void ReplaceFrameworkFd(unique_fd new_fd) REQUIRES(mutex_) {
Josh Gao975cee72020-06-24 16:10:55 -0700160 LOG(INFO) << "adbd_auth: received new framework fd " << new_fd.get()
Josh Gaob789fb12019-10-24 19:02:14 -0700161 << " (current = " << framework_fd_.get() << ")";
162
163 // If we already had a framework fd, clean up after ourselves.
164 if (framework_fd_ != -1) {
165 output_queue_.clear();
166 dispatched_prompt_.reset();
167 CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_DEL, framework_fd_.get(), nullptr));
168 framework_fd_.reset();
169 }
170
171 if (new_fd != -1) {
172 struct epoll_event event;
173 event.events = EPOLLIN;
174 if (!output_queue_.empty()) {
Josh Gao975cee72020-06-24 16:10:55 -0700175 LOG(INFO) << "adbd_auth: marking framework writable";
Josh Gaob789fb12019-10-24 19:02:14 -0700176 event.events |= EPOLLOUT;
177 }
178 event.data.u64 = kEpollConstFramework;
179 CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, new_fd.get(), &event));
180 framework_fd_ = std::move(new_fd);
181 }
182 }
183
Joshua Duong3d0860e2019-10-11 15:43:47 -0700184 void HandlePacket(std::string_view packet) EXCLUDES(mutex_) {
Josh Gao975cee72020-06-24 16:10:55 -0700185 LOG(INFO) << "adbd_auth: received packet: " << packet;
Josh Gaob789fb12019-10-24 19:02:14 -0700186
Joshua Duong3d0860e2019-10-11 15:43:47 -0700187 if (packet.size() < 2) {
Josh Gao975cee72020-06-24 16:10:55 -0700188 LOG(ERROR) << "adbd_auth: received packet of invalid length";
Joshua Duong3d0860e2019-10-11 15:43:47 -0700189 std::lock_guard<std::mutex> lock(mutex_);
190 ReplaceFrameworkFd(unique_fd());
Josh Gaob789fb12019-10-24 19:02:14 -0700191 }
192
Joshua Duong3d0860e2019-10-11 15:43:47 -0700193 bool handled_packet = false;
194 for (size_t i = 0; i < framework_handlers_.size(); ++i) {
195 if (android::base::ConsumePrefix(&packet, framework_handlers_[i].code)) {
196 framework_handlers_[i].cb(packet);
197 handled_packet = true;
198 break;
199 }
Josh Gaob789fb12019-10-24 19:02:14 -0700200 }
Joshua Duong3d0860e2019-10-11 15:43:47 -0700201 if (!handled_packet) {
Josh Gao975cee72020-06-24 16:10:55 -0700202 LOG(ERROR) << "adbd_auth: unhandled packet: " << packet;
Joshua Duong3d0860e2019-10-11 15:43:47 -0700203 std::lock_guard<std::mutex> lock(mutex_);
204 ReplaceFrameworkFd(unique_fd());
205 }
206 }
207
208 void AllowUsbDevice(std::string_view buf) EXCLUDES(mutex_) {
209 std::lock_guard<std::mutex> lock(mutex_);
210 CHECK(buf.empty());
Joshua Duong3d0860e2019-10-11 15:43:47 -0700211
Josh Gao9653c9c2020-06-24 16:12:30 -0700212 if (dispatched_prompt_.has_value()) {
213 // It's possible for the framework to send us a response without our having sent a
214 // request to it: e.g. if adbd restarts while we have a pending request.
215 auto& [id, key, arg] = *dispatched_prompt_;
216 keys_.emplace(id, std::move(key));
217
218 callbacks_.key_authorized(arg, id);
219 dispatched_prompt_ = std::nullopt;
220 } else {
221 LOG(WARNING) << "adbd_auth: received authorization for unknown prompt, ignoring";
222 }
Joshua Duong3d0860e2019-10-11 15:43:47 -0700223
224 // We need to dispatch pending prompts here upon success as well,
225 // since we might have multiple queued prompts.
226 DispatchPendingPrompt();
227 }
228
229 void DenyUsbDevice(std::string_view buf) EXCLUDES(mutex_) {
230 std::lock_guard<std::mutex> lock(mutex_);
231 CHECK(buf.empty());
232 // TODO: Do we want a callback if the key is denied?
233 dispatched_prompt_ = std::nullopt;
234 DispatchPendingPrompt();
235 }
236
237 void KeyRemoved(std::string_view buf) EXCLUDES(mutex_) {
238 CHECK(!buf.empty());
239 callbacks_.key_removed(buf.data(), buf.size());
Josh Gaob789fb12019-10-24 19:02:14 -0700240 }
241
242 bool SendPacket() REQUIRES(mutex_) {
243 if (output_queue_.empty()) {
244 return false;
245 }
246
247 CHECK_NE(-1, framework_fd_.get());
248
249 auto& packet = output_queue_.front();
Joshua Duong3d0860e2019-10-11 15:43:47 -0700250 struct iovec iovs[3];
251 int iovcnt = 2;
Josh Gaob789fb12019-10-24 19:02:14 -0700252 if (auto* p = std::get_if<AdbdAuthPacketAuthenticated>(&packet)) {
253 iovs[0].iov_base = const_cast<char*>("CK");
254 iovs[0].iov_len = 2;
255 iovs[1].iov_base = p->public_key.data();
256 iovs[1].iov_len = p->public_key.size();
257 } else if (auto* p = std::get_if<AdbdAuthPacketDisconnected>(&packet)) {
258 iovs[0].iov_base = const_cast<char*>("DC");
259 iovs[0].iov_len = 2;
260 iovs[1].iov_base = p->public_key.data();
261 iovs[1].iov_len = p->public_key.size();
262 } else if (auto* p = std::get_if<AdbdAuthPacketRequestAuthorization>(&packet)) {
263 iovs[0].iov_base = const_cast<char*>("PK");
264 iovs[0].iov_len = 2;
265 iovs[1].iov_base = p->public_key.data();
266 iovs[1].iov_len = p->public_key.size();
Joshua Duong3d0860e2019-10-11 15:43:47 -0700267 } else if (auto* p = std::get_if<AdbdPacketTlsDeviceConnected>(&packet)) {
268 iovcnt = 3;
269 iovs[0].iov_base = const_cast<char*>("WE");
270 iovs[0].iov_len = 2;
271 iovs[1].iov_base = &p->transport_type;
272 iovs[1].iov_len = 1;
273 iovs[2].iov_base = p->public_key.data();
274 iovs[2].iov_len = p->public_key.size();
275 } else if (auto* p = std::get_if<AdbdPacketTlsDeviceDisconnected>(&packet)) {
276 iovcnt = 3;
277 iovs[0].iov_base = const_cast<char*>("WF");
278 iovs[0].iov_len = 2;
279 iovs[1].iov_base = &p->transport_type;
280 iovs[1].iov_len = 1;
281 iovs[2].iov_base = p->public_key.data();
282 iovs[2].iov_len = p->public_key.size();
Josh Gaob789fb12019-10-24 19:02:14 -0700283 } else {
Josh Gao975cee72020-06-24 16:10:55 -0700284 LOG(FATAL) << "adbd_auth: unhandled packet type?";
Josh Gaob789fb12019-10-24 19:02:14 -0700285 }
286
Joshua Duong3d0860e2019-10-11 15:43:47 -0700287 ssize_t rc = writev(framework_fd_.get(), iovs, iovcnt);
Daniel Micaye3e1cd52021-01-02 20:17:35 -0500288 output_queue_.pop_front();
Josh Gaob789fb12019-10-24 19:02:14 -0700289 if (rc == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
Josh Gao975cee72020-06-24 16:10:55 -0700290 PLOG(ERROR) << "adbd_auth: failed to write to framework fd";
Josh Gaob789fb12019-10-24 19:02:14 -0700291 ReplaceFrameworkFd(unique_fd());
292 return false;
293 }
294
295 return true;
296 }
297
298 void Run() {
299 if (sock_fd_ == -1) {
Josh Gao975cee72020-06-24 16:10:55 -0700300 LOG(ERROR) << "adbd_auth: socket unavailable, disabling user prompts";
Josh Gaob789fb12019-10-24 19:02:14 -0700301 } else {
302 struct epoll_event event;
303 event.events = EPOLLIN;
304 event.data.u64 = kEpollConstSocket;
305 CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, sock_fd_.get(), &event));
306 }
307
308 {
309 struct epoll_event event;
310 event.events = EPOLLIN;
311 event.data.u64 = kEpollConstEventFd;
312 CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, event_fd_.get(), &event));
313 }
314
315 while (true) {
316 struct epoll_event events[3];
317 int rc = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd_.get(), events, 3, -1));
318 if (rc == -1) {
Josh Gao975cee72020-06-24 16:10:55 -0700319 PLOG(FATAL) << "adbd_auth: epoll_wait failed";
Josh Gaob789fb12019-10-24 19:02:14 -0700320 } else if (rc == 0) {
Josh Gao975cee72020-06-24 16:10:55 -0700321 LOG(FATAL) << "adbd_auth: epoll_wait returned 0";
Josh Gaob789fb12019-10-24 19:02:14 -0700322 }
323
324 bool restart = false;
325 for (int i = 0; i < rc; ++i) {
326 if (restart) {
327 break;
328 }
329
330 struct epoll_event& event = events[i];
331 switch (event.data.u64) {
332 case kEpollConstSocket: {
333 unique_fd new_framework_fd(accept4(sock_fd_.get(), nullptr, nullptr,
334 SOCK_CLOEXEC | SOCK_NONBLOCK));
335 if (new_framework_fd == -1) {
Josh Gao975cee72020-06-24 16:10:55 -0700336 PLOG(FATAL) << "adbd_auth: failed to accept framework fd";
Josh Gaob789fb12019-10-24 19:02:14 -0700337 }
338
339 LOG(INFO) << "adbd_auth: received a new framework connection";
340 std::lock_guard<std::mutex> lock(mutex_);
341 ReplaceFrameworkFd(std::move(new_framework_fd));
342
343 // Stop iterating over events: one of the later ones might be the old
344 // framework fd.
345 restart = false;
346 break;
347 }
348
349 case kEpollConstEventFd: {
350 // We were woken up to write something.
351 uint64_t dummy;
352 int rc = TEMP_FAILURE_RETRY(read(event_fd_.get(), &dummy, sizeof(dummy)));
353 if (rc != 8) {
Josh Gao975cee72020-06-24 16:10:55 -0700354 PLOG(FATAL)
355 << "adbd_auth: failed to read from eventfd (rc = " << rc << ")";
Josh Gaob789fb12019-10-24 19:02:14 -0700356 }
357
358 std::lock_guard<std::mutex> lock(mutex_);
359 UpdateFrameworkWritable();
360 break;
361 }
362
363 case kEpollConstFramework: {
364 char buf[4096];
365 if (event.events & EPOLLIN) {
366 int rc = TEMP_FAILURE_RETRY(read(framework_fd_.get(), buf, sizeof(buf)));
367 if (rc == -1) {
Elliott Hughes7b1bc2c2024-06-14 13:22:01 +0000368 PLOG(FATAL) << "adbd_auth: failed to read from framework fd";
Josh Gaob789fb12019-10-24 19:02:14 -0700369 } else if (rc == 0) {
Josh Gao975cee72020-06-24 16:10:55 -0700370 LOG(INFO) << "adbd_auth: hit EOF on framework fd";
Josh Gaob789fb12019-10-24 19:02:14 -0700371 std::lock_guard<std::mutex> lock(mutex_);
372 ReplaceFrameworkFd(unique_fd());
373 } else {
Josh Gaob789fb12019-10-24 19:02:14 -0700374 HandlePacket(std::string_view(buf, rc));
375 }
376 }
377
378 if (event.events & EPOLLOUT) {
379 std::lock_guard<std::mutex> lock(mutex_);
380 while (SendPacket()) {
381 continue;
382 }
383 UpdateFrameworkWritable();
384 }
385
386 break;
387 }
388 }
389 }
390 }
391 }
392
Inseob Kim4b9fcd92024-08-28 17:21:27 +0900393 static constexpr std::pair<const char*, bool> key_paths[] = {
394 {"/adb_keys", true /* follow symlinks */ },
395 {"/data/misc/adb/adb_keys", false /* don't follow symlinks */ },
396 };
Joshua Duong3d0860e2019-10-11 15:43:47 -0700397 void IteratePublicKeys(bool (*callback)(void*, const char*, size_t), void* opaque) {
Inseob Kim4b9fcd92024-08-28 17:21:27 +0900398 for (const auto& [path, follow_symlinks] : key_paths) {
Josh Gaob789fb12019-10-24 19:02:14 -0700399 if (access(path, R_OK) == 0) {
Josh Gao975cee72020-06-24 16:10:55 -0700400 LOG(INFO) << "adbd_auth: loading keys from " << path;
Josh Gaob789fb12019-10-24 19:02:14 -0700401 std::string content;
Inseob Kim4b9fcd92024-08-28 17:21:27 +0900402 if (!android::base::ReadFileToString(path, &content, follow_symlinks)) {
Josh Gao975cee72020-06-24 16:10:55 -0700403 PLOG(ERROR) << "adbd_auth: couldn't read " << path;
Josh Gaob789fb12019-10-24 19:02:14 -0700404 continue;
405 }
406 for (const auto& line : android::base::Split(content, "\n")) {
Joshua Duong3d0860e2019-10-11 15:43:47 -0700407 if (!callback(opaque, line.data(), line.size())) {
Josh Gaob789fb12019-10-24 19:02:14 -0700408 return;
409 }
410 }
411 }
412 }
413 }
414
415 uint64_t PromptUser(std::string_view public_key, void* arg) EXCLUDES(mutex_) {
416 uint64_t id = NextId();
417
418 std::lock_guard<std::mutex> lock(mutex_);
Josh Gao975cee72020-06-24 16:10:55 -0700419 LOG(INFO) << "adbd_auth: sending prompt with id " << id;
Josh Gaob789fb12019-10-24 19:02:14 -0700420 pending_prompts_.emplace_back(id, public_key, arg);
421 DispatchPendingPrompt();
422 return id;
423 }
424
425 uint64_t NotifyAuthenticated(std::string_view public_key) EXCLUDES(mutex_) {
426 uint64_t id = NextId();
427 std::lock_guard<std::mutex> lock(mutex_);
428 keys_.emplace(id, public_key);
429 output_queue_.emplace_back(
Joshua Duong3d0860e2019-10-11 15:43:47 -0700430 AdbdAuthPacketAuthenticated{.public_key = std::string(public_key)});
Josh Gaob789fb12019-10-24 19:02:14 -0700431 return id;
432 }
433
434 void NotifyDisconnected(uint64_t id) EXCLUDES(mutex_) {
435 std::lock_guard<std::mutex> lock(mutex_);
436 auto it = keys_.find(id);
437 if (it == keys_.end()) {
Josh Gao975cee72020-06-24 16:10:55 -0700438 LOG(DEBUG) << "adbd_auth: couldn't find public key to notify disconnection, skipping";
Josh Gaob789fb12019-10-24 19:02:14 -0700439 return;
440 }
441 output_queue_.emplace_back(AdbdAuthPacketDisconnected{.public_key = std::move(it->second)});
442 keys_.erase(it);
443 }
444
Joshua Duong3d0860e2019-10-11 15:43:47 -0700445 uint64_t NotifyTlsDeviceConnected(AdbTransportType type,
446 std::string_view public_key) EXCLUDES(mutex_) {
447 uint64_t id = NextId();
448 std::lock_guard<std::mutex> lock(mutex_);
449 keys_.emplace(id, public_key);
450 output_queue_.emplace_back(AdbdPacketTlsDeviceConnected{
451 .transport_type = static_cast<uint8_t>(type),
452 .public_key = std::string(public_key)});
453 Interrupt();
454 return id;
455 }
456
457 void NotifyTlsDeviceDisconnected(AdbTransportType type, uint64_t id) EXCLUDES(mutex_) {
458 std::lock_guard<std::mutex> lock(mutex_);
459 auto it = keys_.find(id);
460 if (it == keys_.end()) {
Josh Gao975cee72020-06-24 16:10:55 -0700461 LOG(DEBUG) << "adbd_auth: couldn't find public key to notify disconnection of tls "
462 "device, skipping";
Joshua Duong3d0860e2019-10-11 15:43:47 -0700463 return;
464 }
465 output_queue_.emplace_back(AdbdPacketTlsDeviceDisconnected{
466 .transport_type = static_cast<uint8_t>(type),
467 .public_key = std::move(it->second)});
468 keys_.erase(it);
469 Interrupt();
470 }
471
Josh Gaob789fb12019-10-24 19:02:14 -0700472 // Interrupt the worker thread to do some work.
473 void Interrupt() {
474 uint64_t value = 1;
475 ssize_t rc = write(event_fd_.get(), &value, sizeof(value));
476 if (rc == -1) {
Josh Gao975cee72020-06-24 16:10:55 -0700477 PLOG(FATAL) << "adbd_auth: write to eventfd failed";
Josh Gaob789fb12019-10-24 19:02:14 -0700478 } else if (rc != sizeof(value)) {
Josh Gao975cee72020-06-24 16:10:55 -0700479 LOG(FATAL) << "adbd_auth: write to eventfd returned short (" << rc << ")";
Josh Gaob789fb12019-10-24 19:02:14 -0700480 }
481 }
482
Joshua Duong3d0860e2019-10-11 15:43:47 -0700483 void InitFrameworkHandlers() {
484 // Framework wants to disconnect from a secured wifi device
485 framework_handlers_.emplace_back(
486 FrameworkPktHandler{
487 .code = "DD",
488 .cb = std::bind(&AdbdAuthContext::KeyRemoved, this, std::placeholders::_1)});
489 // Framework allows USB debugging for the device
490 framework_handlers_.emplace_back(
491 FrameworkPktHandler{
492 .code = "OK",
493 .cb = std::bind(&AdbdAuthContext::AllowUsbDevice, this, std::placeholders::_1)});
494 // Framework denies USB debugging for the device
495 framework_handlers_.emplace_back(
496 FrameworkPktHandler{
497 .code = "NO",
498 .cb = std::bind(&AdbdAuthContext::DenyUsbDevice, this, std::placeholders::_1)});
499 }
500
Josh Gaob789fb12019-10-24 19:02:14 -0700501 unique_fd epoll_fd_;
502 unique_fd event_fd_;
503 unique_fd sock_fd_;
504 unique_fd framework_fd_;
505
506 std::atomic<uint64_t> next_id_;
507 AdbdAuthCallbacksV1 callbacks_;
508
509 std::mutex mutex_;
510 std::unordered_map<uint64_t, std::string> keys_ GUARDED_BY(mutex_);
511
512 // We keep two separate queues: one to handle backpressure from the socket (output_queue_)
513 // and one to make sure we only dispatch one authrequest at a time (pending_prompts_).
Joshua Duong3d0860e2019-10-11 15:43:47 -0700514 std::deque<AdbdAuthPacket> output_queue_ GUARDED_BY(mutex_);
Josh Gaob789fb12019-10-24 19:02:14 -0700515
516 std::optional<std::tuple<uint64_t, std::string, void*>> dispatched_prompt_ GUARDED_BY(mutex_);
517 std::deque<std::tuple<uint64_t, std::string, void*>> pending_prompts_ GUARDED_BY(mutex_);
Joshua Duong3d0860e2019-10-11 15:43:47 -0700518
519 // This is a list of commands that the framework could send to us.
520 using FrameworkHandlerCb = std::function<void(std::string_view)>;
521 struct FrameworkPktHandler {
522 const char* code;
523 FrameworkHandlerCb cb;
524 };
525 std::vector<FrameworkPktHandler> framework_handlers_;
Josh Gaob789fb12019-10-24 19:02:14 -0700526};
527
528AdbdAuthContext* adbd_auth_new(AdbdAuthCallbacks* callbacks) {
Joshua Duong3d0860e2019-10-11 15:43:47 -0700529 if (callbacks->version == 1) {
530 return new AdbdAuthContext(reinterpret_cast<AdbdAuthCallbacksV1*>(callbacks));
531 } else {
Josh Gao975cee72020-06-24 16:10:55 -0700532 LOG(ERROR) << "adbd_auth: received unknown AdbdAuthCallbacks version "
533 << callbacks->version;
534 return nullptr;
Josh Gaob789fb12019-10-24 19:02:14 -0700535 }
Josh Gaob789fb12019-10-24 19:02:14 -0700536}
537
538void adbd_auth_delete(AdbdAuthContext* ctx) {
539 delete ctx;
540}
541
542void adbd_auth_run(AdbdAuthContext* ctx) {
543 return ctx->Run();
544}
545
546void adbd_auth_get_public_keys(AdbdAuthContext* ctx,
Joshua Duong3d0860e2019-10-11 15:43:47 -0700547 bool (*callback)(void* opaque, const char* public_key, size_t len),
548 void* opaque) {
549 ctx->IteratePublicKeys(callback, opaque);
Josh Gaob789fb12019-10-24 19:02:14 -0700550}
551
552uint64_t adbd_auth_notify_auth(AdbdAuthContext* ctx, const char* public_key, size_t len) {
553 return ctx->NotifyAuthenticated(std::string_view(public_key, len));
554}
555
556void adbd_auth_notify_disconnect(AdbdAuthContext* ctx, uint64_t id) {
557 return ctx->NotifyDisconnected(id);
558}
559
560void adbd_auth_prompt_user(AdbdAuthContext* ctx, const char* public_key, size_t len,
Joshua Duong3d0860e2019-10-11 15:43:47 -0700561 void* opaque) {
Josh Gao9e933c52020-06-24 16:11:21 -0700562 adbd_auth_prompt_user_with_id(ctx, public_key, len, opaque);
563}
564
565uint64_t adbd_auth_prompt_user_with_id(AdbdAuthContext* ctx, const char* public_key, size_t len,
566 void* opaque) {
567 return ctx->PromptUser(std::string_view(public_key, len), opaque);
Josh Gaob789fb12019-10-24 19:02:14 -0700568}
569
Joshua Duong3d0860e2019-10-11 15:43:47 -0700570uint64_t adbd_auth_tls_device_connected(AdbdAuthContext* ctx,
571 AdbTransportType type,
572 const char* public_key,
573 size_t len) {
574 return ctx->NotifyTlsDeviceConnected(type, std::string_view(public_key, len));
575}
576
577void adbd_auth_tls_device_disconnected(AdbdAuthContext* ctx,
578 AdbTransportType type,
579 uint64_t id) {
580 ctx->NotifyTlsDeviceDisconnected(type, id);
581}
582
583uint32_t adbd_auth_get_max_version() {
584 return kAuthVersion;
585}
586
587bool adbd_auth_supports_feature(AdbdAuthFeature f) {
588 UNUSED(f);
Josh Gaob789fb12019-10-24 19:02:14 -0700589 return false;
590}