blob: dae6eebaa526c39c664bc6310281105b61911395 [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
26#include <chrono>
27#include <deque>
28#include <string>
29#include <string_view>
30#include <tuple>
31#include <unordered_map>
32#include <utility>
33#include <variant>
34#include <vector>
35
36#include <android-base/file.h>
37#include <android-base/logging.h>
38#include <android-base/macros.h>
39#include <android-base/strings.h>
40#include <android-base/thread_annotations.h>
41#include <android-base/unique_fd.h>
42#include <cutils/sockets.h>
43
44using android::base::unique_fd;
45
Joshua Duong3d0860e2019-10-11 15:43:47 -070046static constexpr uint32_t kAuthVersion = 1;
47
Josh Gaob789fb12019-10-24 19:02:14 -070048struct AdbdAuthPacketAuthenticated {
49 std::string public_key;
50};
51
52struct AdbdAuthPacketDisconnected {
53 std::string public_key;
54};
55
56struct AdbdAuthPacketRequestAuthorization {
57 std::string public_key;
58};
59
Joshua Duong3d0860e2019-10-11 15:43:47 -070060struct AdbdPacketTlsDeviceConnected {
61 uint8_t transport_type;
62 std::string public_key;
63};
64
65struct AdbdPacketTlsDeviceDisconnected {
66 uint8_t transport_type;
67 std::string public_key;
68};
69
70using AdbdAuthPacket = std::variant<AdbdAuthPacketAuthenticated,
71 AdbdAuthPacketDisconnected,
72 AdbdAuthPacketRequestAuthorization,
73 AdbdPacketTlsDeviceConnected,
74 AdbdPacketTlsDeviceDisconnected>;
Josh Gaob789fb12019-10-24 19:02:14 -070075
76struct AdbdAuthContext {
77 static constexpr uint64_t kEpollConstSocket = 0;
78 static constexpr uint64_t kEpollConstEventFd = 1;
79 static constexpr uint64_t kEpollConstFramework = 2;
80
81public:
82 explicit AdbdAuthContext(AdbdAuthCallbacksV1* callbacks) : next_id_(0), callbacks_(*callbacks) {
Joshua Duong3d0860e2019-10-11 15:43:47 -070083 InitFrameworkHandlers();
Josh Gaob789fb12019-10-24 19:02:14 -070084 epoll_fd_.reset(epoll_create1(EPOLL_CLOEXEC));
85 if (epoll_fd_ == -1) {
Josh Gao975cee72020-06-24 16:10:55 -070086 PLOG(FATAL) << "adbd_auth: failed to create epoll fd";
Josh Gaob789fb12019-10-24 19:02:14 -070087 }
88
89 event_fd_.reset(eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK));
90 if (event_fd_ == -1) {
Josh Gao975cee72020-06-24 16:10:55 -070091 PLOG(FATAL) << "adbd_auth: failed to create eventfd";
Josh Gaob789fb12019-10-24 19:02:14 -070092 }
93
94 sock_fd_.reset(android_get_control_socket("adbd"));
95 if (sock_fd_ == -1) {
Josh Gao975cee72020-06-24 16:10:55 -070096 PLOG(ERROR) << "adbd_auth: failed to get adbd authentication socket";
Josh Gaob789fb12019-10-24 19:02:14 -070097 } else {
98 if (fcntl(sock_fd_.get(), F_SETFD, FD_CLOEXEC) != 0) {
Josh Gao975cee72020-06-24 16:10:55 -070099 PLOG(FATAL) << "adbd_auth: failed to make adbd authentication socket cloexec";
Josh Gaob789fb12019-10-24 19:02:14 -0700100 }
101
102 if (fcntl(sock_fd_.get(), F_SETFL, O_NONBLOCK) != 0) {
Josh Gao975cee72020-06-24 16:10:55 -0700103 PLOG(FATAL) << "adbd_auth: failed to make adbd authentication socket nonblocking";
Josh Gaob789fb12019-10-24 19:02:14 -0700104 }
105
106 if (listen(sock_fd_.get(), 4) != 0) {
Josh Gao975cee72020-06-24 16:10:55 -0700107 PLOG(FATAL) << "adbd_auth: failed to listen on adbd authentication socket";
Josh Gaob789fb12019-10-24 19:02:14 -0700108 }
109 }
110 }
111
112 AdbdAuthContext(const AdbdAuthContext& copy) = delete;
113 AdbdAuthContext(AdbdAuthContext&& move) = delete;
114 AdbdAuthContext& operator=(const AdbdAuthContext& copy) = delete;
115 AdbdAuthContext& operator=(AdbdAuthContext&& move) = delete;
116
117 uint64_t NextId() { return next_id_++; }
118
119 void DispatchPendingPrompt() REQUIRES(mutex_) {
120 if (dispatched_prompt_) {
121 LOG(INFO) << "adbd_auth: prompt currently pending, skipping";
122 return;
123 }
124
125 if (pending_prompts_.empty()) {
126 LOG(INFO) << "adbd_auth: no prompts to send";
127 return;
128 }
129
130 LOG(INFO) << "adbd_auth: prompting user for adb authentication";
131 auto [id, public_key, arg] = std::move(pending_prompts_.front());
132 pending_prompts_.pop_front();
133
134 this->output_queue_.emplace_back(
135 AdbdAuthPacketRequestAuthorization{.public_key = public_key});
136
137 Interrupt();
138 dispatched_prompt_ = std::make_tuple(id, public_key, arg);
139 }
140
141 void UpdateFrameworkWritable() REQUIRES(mutex_) {
142 // This might result in redundant calls to EPOLL_CTL_MOD if, for example, we get notified
143 // at the same time as a framework connection, but that's unlikely and this doesn't need to
144 // be fast anyway.
145 if (framework_fd_ != -1) {
146 struct epoll_event event;
147 event.events = EPOLLIN;
148 if (!output_queue_.empty()) {
Josh Gao975cee72020-06-24 16:10:55 -0700149 LOG(INFO) << "adbd_auth: marking framework writable";
Josh Gaob789fb12019-10-24 19:02:14 -0700150 event.events |= EPOLLOUT;
151 }
152 event.data.u64 = kEpollConstFramework;
153 CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_MOD, framework_fd_.get(), &event));
154 }
155 }
156
157 void ReplaceFrameworkFd(unique_fd new_fd) REQUIRES(mutex_) {
Josh Gao975cee72020-06-24 16:10:55 -0700158 LOG(INFO) << "adbd_auth: received new framework fd " << new_fd.get()
Josh Gaob789fb12019-10-24 19:02:14 -0700159 << " (current = " << framework_fd_.get() << ")";
160
161 // If we already had a framework fd, clean up after ourselves.
162 if (framework_fd_ != -1) {
163 output_queue_.clear();
164 dispatched_prompt_.reset();
165 CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_DEL, framework_fd_.get(), nullptr));
166 framework_fd_.reset();
167 }
168
169 if (new_fd != -1) {
170 struct epoll_event event;
171 event.events = EPOLLIN;
172 if (!output_queue_.empty()) {
Josh Gao975cee72020-06-24 16:10:55 -0700173 LOG(INFO) << "adbd_auth: marking framework writable";
Josh Gaob789fb12019-10-24 19:02:14 -0700174 event.events |= EPOLLOUT;
175 }
176 event.data.u64 = kEpollConstFramework;
177 CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, new_fd.get(), &event));
178 framework_fd_ = std::move(new_fd);
179 }
180 }
181
Joshua Duong3d0860e2019-10-11 15:43:47 -0700182 void HandlePacket(std::string_view packet) EXCLUDES(mutex_) {
Josh Gao975cee72020-06-24 16:10:55 -0700183 LOG(INFO) << "adbd_auth: received packet: " << packet;
Josh Gaob789fb12019-10-24 19:02:14 -0700184
Joshua Duong3d0860e2019-10-11 15:43:47 -0700185 if (packet.size() < 2) {
Josh Gao975cee72020-06-24 16:10:55 -0700186 LOG(ERROR) << "adbd_auth: received packet of invalid length";
Joshua Duong3d0860e2019-10-11 15:43:47 -0700187 std::lock_guard<std::mutex> lock(mutex_);
188 ReplaceFrameworkFd(unique_fd());
Josh Gaob789fb12019-10-24 19:02:14 -0700189 }
190
Joshua Duong3d0860e2019-10-11 15:43:47 -0700191 bool handled_packet = false;
192 for (size_t i = 0; i < framework_handlers_.size(); ++i) {
193 if (android::base::ConsumePrefix(&packet, framework_handlers_[i].code)) {
194 framework_handlers_[i].cb(packet);
195 handled_packet = true;
196 break;
197 }
Josh Gaob789fb12019-10-24 19:02:14 -0700198 }
Joshua Duong3d0860e2019-10-11 15:43:47 -0700199 if (!handled_packet) {
Josh Gao975cee72020-06-24 16:10:55 -0700200 LOG(ERROR) << "adbd_auth: unhandled packet: " << packet;
Joshua Duong3d0860e2019-10-11 15:43:47 -0700201 std::lock_guard<std::mutex> lock(mutex_);
202 ReplaceFrameworkFd(unique_fd());
203 }
204 }
205
206 void AllowUsbDevice(std::string_view buf) EXCLUDES(mutex_) {
207 std::lock_guard<std::mutex> lock(mutex_);
208 CHECK(buf.empty());
Joshua Duong3d0860e2019-10-11 15:43:47 -0700209
Josh Gao9653c9c2020-06-24 16:12:30 -0700210 if (dispatched_prompt_.has_value()) {
211 // It's possible for the framework to send us a response without our having sent a
212 // request to it: e.g. if adbd restarts while we have a pending request.
213 auto& [id, key, arg] = *dispatched_prompt_;
214 keys_.emplace(id, std::move(key));
215
216 callbacks_.key_authorized(arg, id);
217 dispatched_prompt_ = std::nullopt;
218 } else {
219 LOG(WARNING) << "adbd_auth: received authorization for unknown prompt, ignoring";
220 }
Joshua Duong3d0860e2019-10-11 15:43:47 -0700221
222 // We need to dispatch pending prompts here upon success as well,
223 // since we might have multiple queued prompts.
224 DispatchPendingPrompt();
225 }
226
227 void DenyUsbDevice(std::string_view buf) EXCLUDES(mutex_) {
228 std::lock_guard<std::mutex> lock(mutex_);
229 CHECK(buf.empty());
230 // TODO: Do we want a callback if the key is denied?
231 dispatched_prompt_ = std::nullopt;
232 DispatchPendingPrompt();
233 }
234
235 void KeyRemoved(std::string_view buf) EXCLUDES(mutex_) {
236 CHECK(!buf.empty());
237 callbacks_.key_removed(buf.data(), buf.size());
Josh Gaob789fb12019-10-24 19:02:14 -0700238 }
239
240 bool SendPacket() REQUIRES(mutex_) {
241 if (output_queue_.empty()) {
242 return false;
243 }
244
245 CHECK_NE(-1, framework_fd_.get());
246
247 auto& packet = output_queue_.front();
Joshua Duong3d0860e2019-10-11 15:43:47 -0700248 struct iovec iovs[3];
249 int iovcnt = 2;
Josh Gaob789fb12019-10-24 19:02:14 -0700250 if (auto* p = std::get_if<AdbdAuthPacketAuthenticated>(&packet)) {
251 iovs[0].iov_base = const_cast<char*>("CK");
252 iovs[0].iov_len = 2;
253 iovs[1].iov_base = p->public_key.data();
254 iovs[1].iov_len = p->public_key.size();
255 } else if (auto* p = std::get_if<AdbdAuthPacketDisconnected>(&packet)) {
256 iovs[0].iov_base = const_cast<char*>("DC");
257 iovs[0].iov_len = 2;
258 iovs[1].iov_base = p->public_key.data();
259 iovs[1].iov_len = p->public_key.size();
260 } else if (auto* p = std::get_if<AdbdAuthPacketRequestAuthorization>(&packet)) {
261 iovs[0].iov_base = const_cast<char*>("PK");
262 iovs[0].iov_len = 2;
263 iovs[1].iov_base = p->public_key.data();
264 iovs[1].iov_len = p->public_key.size();
Joshua Duong3d0860e2019-10-11 15:43:47 -0700265 } else if (auto* p = std::get_if<AdbdPacketTlsDeviceConnected>(&packet)) {
266 iovcnt = 3;
267 iovs[0].iov_base = const_cast<char*>("WE");
268 iovs[0].iov_len = 2;
269 iovs[1].iov_base = &p->transport_type;
270 iovs[1].iov_len = 1;
271 iovs[2].iov_base = p->public_key.data();
272 iovs[2].iov_len = p->public_key.size();
273 } else if (auto* p = std::get_if<AdbdPacketTlsDeviceDisconnected>(&packet)) {
274 iovcnt = 3;
275 iovs[0].iov_base = const_cast<char*>("WF");
276 iovs[0].iov_len = 2;
277 iovs[1].iov_base = &p->transport_type;
278 iovs[1].iov_len = 1;
279 iovs[2].iov_base = p->public_key.data();
280 iovs[2].iov_len = p->public_key.size();
Josh Gaob789fb12019-10-24 19:02:14 -0700281 } else {
Josh Gao975cee72020-06-24 16:10:55 -0700282 LOG(FATAL) << "adbd_auth: unhandled packet type?";
Josh Gaob789fb12019-10-24 19:02:14 -0700283 }
284
285 output_queue_.pop_front();
286
Joshua Duong3d0860e2019-10-11 15:43:47 -0700287 ssize_t rc = writev(framework_fd_.get(), iovs, iovcnt);
Josh Gaob789fb12019-10-24 19:02:14 -0700288 if (rc == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
Josh Gao975cee72020-06-24 16:10:55 -0700289 PLOG(ERROR) << "adbd_auth: failed to write to framework fd";
Josh Gaob789fb12019-10-24 19:02:14 -0700290 ReplaceFrameworkFd(unique_fd());
291 return false;
292 }
293
294 return true;
295 }
296
297 void Run() {
298 if (sock_fd_ == -1) {
Josh Gao975cee72020-06-24 16:10:55 -0700299 LOG(ERROR) << "adbd_auth: socket unavailable, disabling user prompts";
Josh Gaob789fb12019-10-24 19:02:14 -0700300 } else {
301 struct epoll_event event;
302 event.events = EPOLLIN;
303 event.data.u64 = kEpollConstSocket;
304 CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, sock_fd_.get(), &event));
305 }
306
307 {
308 struct epoll_event event;
309 event.events = EPOLLIN;
310 event.data.u64 = kEpollConstEventFd;
311 CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, event_fd_.get(), &event));
312 }
313
314 while (true) {
315 struct epoll_event events[3];
316 int rc = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd_.get(), events, 3, -1));
317 if (rc == -1) {
Josh Gao975cee72020-06-24 16:10:55 -0700318 PLOG(FATAL) << "adbd_auth: epoll_wait failed";
Josh Gaob789fb12019-10-24 19:02:14 -0700319 } else if (rc == 0) {
Josh Gao975cee72020-06-24 16:10:55 -0700320 LOG(FATAL) << "adbd_auth: epoll_wait returned 0";
Josh Gaob789fb12019-10-24 19:02:14 -0700321 }
322
323 bool restart = false;
324 for (int i = 0; i < rc; ++i) {
325 if (restart) {
326 break;
327 }
328
329 struct epoll_event& event = events[i];
330 switch (event.data.u64) {
331 case kEpollConstSocket: {
332 unique_fd new_framework_fd(accept4(sock_fd_.get(), nullptr, nullptr,
333 SOCK_CLOEXEC | SOCK_NONBLOCK));
334 if (new_framework_fd == -1) {
Josh Gao975cee72020-06-24 16:10:55 -0700335 PLOG(FATAL) << "adbd_auth: failed to accept framework fd";
Josh Gaob789fb12019-10-24 19:02:14 -0700336 }
337
338 LOG(INFO) << "adbd_auth: received a new framework connection";
339 std::lock_guard<std::mutex> lock(mutex_);
340 ReplaceFrameworkFd(std::move(new_framework_fd));
341
342 // Stop iterating over events: one of the later ones might be the old
343 // framework fd.
344 restart = false;
345 break;
346 }
347
348 case kEpollConstEventFd: {
349 // We were woken up to write something.
350 uint64_t dummy;
351 int rc = TEMP_FAILURE_RETRY(read(event_fd_.get(), &dummy, sizeof(dummy)));
352 if (rc != 8) {
Josh Gao975cee72020-06-24 16:10:55 -0700353 PLOG(FATAL)
354 << "adbd_auth: failed to read from eventfd (rc = " << rc << ")";
Josh Gaob789fb12019-10-24 19:02:14 -0700355 }
356
357 std::lock_guard<std::mutex> lock(mutex_);
358 UpdateFrameworkWritable();
359 break;
360 }
361
362 case kEpollConstFramework: {
363 char buf[4096];
364 if (event.events & EPOLLIN) {
365 int rc = TEMP_FAILURE_RETRY(read(framework_fd_.get(), buf, sizeof(buf)));
366 if (rc == -1) {
Josh Gao975cee72020-06-24 16:10:55 -0700367 LOG(FATAL) << "adbd_auth: failed to read from framework fd";
Josh Gaob789fb12019-10-24 19:02:14 -0700368 } else if (rc == 0) {
Josh Gao975cee72020-06-24 16:10:55 -0700369 LOG(INFO) << "adbd_auth: hit EOF on framework fd";
Josh Gaob789fb12019-10-24 19:02:14 -0700370 std::lock_guard<std::mutex> lock(mutex_);
371 ReplaceFrameworkFd(unique_fd());
372 } else {
Josh Gaob789fb12019-10-24 19:02:14 -0700373 HandlePacket(std::string_view(buf, rc));
374 }
375 }
376
377 if (event.events & EPOLLOUT) {
378 std::lock_guard<std::mutex> lock(mutex_);
379 while (SendPacket()) {
380 continue;
381 }
382 UpdateFrameworkWritable();
383 }
384
385 break;
386 }
387 }
388 }
389 }
390 }
391
392 static constexpr const char* key_paths[] = {"/adb_keys", "/data/misc/adb/adb_keys"};
Joshua Duong3d0860e2019-10-11 15:43:47 -0700393 void IteratePublicKeys(bool (*callback)(void*, const char*, size_t), void* opaque) {
Josh Gaob789fb12019-10-24 19:02:14 -0700394 for (const auto& path : key_paths) {
395 if (access(path, R_OK) == 0) {
Josh Gao975cee72020-06-24 16:10:55 -0700396 LOG(INFO) << "adbd_auth: loading keys from " << path;
Josh Gaob789fb12019-10-24 19:02:14 -0700397 std::string content;
398 if (!android::base::ReadFileToString(path, &content)) {
Josh Gao975cee72020-06-24 16:10:55 -0700399 PLOG(ERROR) << "adbd_auth: couldn't read " << path;
Josh Gaob789fb12019-10-24 19:02:14 -0700400 continue;
401 }
402 for (const auto& line : android::base::Split(content, "\n")) {
Joshua Duong3d0860e2019-10-11 15:43:47 -0700403 if (!callback(opaque, line.data(), line.size())) {
Josh Gaob789fb12019-10-24 19:02:14 -0700404 return;
405 }
406 }
407 }
408 }
409 }
410
411 uint64_t PromptUser(std::string_view public_key, void* arg) EXCLUDES(mutex_) {
412 uint64_t id = NextId();
413
414 std::lock_guard<std::mutex> lock(mutex_);
Josh Gao975cee72020-06-24 16:10:55 -0700415 LOG(INFO) << "adbd_auth: sending prompt with id " << id;
Josh Gaob789fb12019-10-24 19:02:14 -0700416 pending_prompts_.emplace_back(id, public_key, arg);
417 DispatchPendingPrompt();
418 return id;
419 }
420
421 uint64_t NotifyAuthenticated(std::string_view public_key) EXCLUDES(mutex_) {
422 uint64_t id = NextId();
423 std::lock_guard<std::mutex> lock(mutex_);
424 keys_.emplace(id, public_key);
425 output_queue_.emplace_back(
Joshua Duong3d0860e2019-10-11 15:43:47 -0700426 AdbdAuthPacketAuthenticated{.public_key = std::string(public_key)});
Josh Gaob789fb12019-10-24 19:02:14 -0700427 return id;
428 }
429
430 void NotifyDisconnected(uint64_t id) EXCLUDES(mutex_) {
431 std::lock_guard<std::mutex> lock(mutex_);
432 auto it = keys_.find(id);
433 if (it == keys_.end()) {
Josh Gao975cee72020-06-24 16:10:55 -0700434 LOG(DEBUG) << "adbd_auth: couldn't find public key to notify disconnection, skipping";
Josh Gaob789fb12019-10-24 19:02:14 -0700435 return;
436 }
437 output_queue_.emplace_back(AdbdAuthPacketDisconnected{.public_key = std::move(it->second)});
438 keys_.erase(it);
439 }
440
Joshua Duong3d0860e2019-10-11 15:43:47 -0700441 uint64_t NotifyTlsDeviceConnected(AdbTransportType type,
442 std::string_view public_key) EXCLUDES(mutex_) {
443 uint64_t id = NextId();
444 std::lock_guard<std::mutex> lock(mutex_);
445 keys_.emplace(id, public_key);
446 output_queue_.emplace_back(AdbdPacketTlsDeviceConnected{
447 .transport_type = static_cast<uint8_t>(type),
448 .public_key = std::string(public_key)});
449 Interrupt();
450 return id;
451 }
452
453 void NotifyTlsDeviceDisconnected(AdbTransportType type, uint64_t id) EXCLUDES(mutex_) {
454 std::lock_guard<std::mutex> lock(mutex_);
455 auto it = keys_.find(id);
456 if (it == keys_.end()) {
Josh Gao975cee72020-06-24 16:10:55 -0700457 LOG(DEBUG) << "adbd_auth: couldn't find public key to notify disconnection of tls "
458 "device, skipping";
Joshua Duong3d0860e2019-10-11 15:43:47 -0700459 return;
460 }
461 output_queue_.emplace_back(AdbdPacketTlsDeviceDisconnected{
462 .transport_type = static_cast<uint8_t>(type),
463 .public_key = std::move(it->second)});
464 keys_.erase(it);
465 Interrupt();
466 }
467
Josh Gaob789fb12019-10-24 19:02:14 -0700468 // Interrupt the worker thread to do some work.
469 void Interrupt() {
470 uint64_t value = 1;
471 ssize_t rc = write(event_fd_.get(), &value, sizeof(value));
472 if (rc == -1) {
Josh Gao975cee72020-06-24 16:10:55 -0700473 PLOG(FATAL) << "adbd_auth: write to eventfd failed";
Josh Gaob789fb12019-10-24 19:02:14 -0700474 } else if (rc != sizeof(value)) {
Josh Gao975cee72020-06-24 16:10:55 -0700475 LOG(FATAL) << "adbd_auth: write to eventfd returned short (" << rc << ")";
Josh Gaob789fb12019-10-24 19:02:14 -0700476 }
477 }
478
Joshua Duong3d0860e2019-10-11 15:43:47 -0700479 void InitFrameworkHandlers() {
480 // Framework wants to disconnect from a secured wifi device
481 framework_handlers_.emplace_back(
482 FrameworkPktHandler{
483 .code = "DD",
484 .cb = std::bind(&AdbdAuthContext::KeyRemoved, this, std::placeholders::_1)});
485 // Framework allows USB debugging for the device
486 framework_handlers_.emplace_back(
487 FrameworkPktHandler{
488 .code = "OK",
489 .cb = std::bind(&AdbdAuthContext::AllowUsbDevice, this, std::placeholders::_1)});
490 // Framework denies USB debugging for the device
491 framework_handlers_.emplace_back(
492 FrameworkPktHandler{
493 .code = "NO",
494 .cb = std::bind(&AdbdAuthContext::DenyUsbDevice, this, std::placeholders::_1)});
495 }
496
Josh Gaob789fb12019-10-24 19:02:14 -0700497 unique_fd epoll_fd_;
498 unique_fd event_fd_;
499 unique_fd sock_fd_;
500 unique_fd framework_fd_;
501
502 std::atomic<uint64_t> next_id_;
503 AdbdAuthCallbacksV1 callbacks_;
504
505 std::mutex mutex_;
506 std::unordered_map<uint64_t, std::string> keys_ GUARDED_BY(mutex_);
507
508 // We keep two separate queues: one to handle backpressure from the socket (output_queue_)
509 // and one to make sure we only dispatch one authrequest at a time (pending_prompts_).
Joshua Duong3d0860e2019-10-11 15:43:47 -0700510 std::deque<AdbdAuthPacket> output_queue_ GUARDED_BY(mutex_);
Josh Gaob789fb12019-10-24 19:02:14 -0700511
512 std::optional<std::tuple<uint64_t, std::string, void*>> dispatched_prompt_ GUARDED_BY(mutex_);
513 std::deque<std::tuple<uint64_t, std::string, void*>> pending_prompts_ GUARDED_BY(mutex_);
Joshua Duong3d0860e2019-10-11 15:43:47 -0700514
515 // This is a list of commands that the framework could send to us.
516 using FrameworkHandlerCb = std::function<void(std::string_view)>;
517 struct FrameworkPktHandler {
518 const char* code;
519 FrameworkHandlerCb cb;
520 };
521 std::vector<FrameworkPktHandler> framework_handlers_;
Josh Gaob789fb12019-10-24 19:02:14 -0700522};
523
524AdbdAuthContext* adbd_auth_new(AdbdAuthCallbacks* callbacks) {
Joshua Duong3d0860e2019-10-11 15:43:47 -0700525 if (callbacks->version == 1) {
526 return new AdbdAuthContext(reinterpret_cast<AdbdAuthCallbacksV1*>(callbacks));
527 } else {
Josh Gao975cee72020-06-24 16:10:55 -0700528 LOG(ERROR) << "adbd_auth: received unknown AdbdAuthCallbacks version "
529 << callbacks->version;
530 return nullptr;
Josh Gaob789fb12019-10-24 19:02:14 -0700531 }
Josh Gaob789fb12019-10-24 19:02:14 -0700532}
533
534void adbd_auth_delete(AdbdAuthContext* ctx) {
535 delete ctx;
536}
537
538void adbd_auth_run(AdbdAuthContext* ctx) {
539 return ctx->Run();
540}
541
542void adbd_auth_get_public_keys(AdbdAuthContext* ctx,
Joshua Duong3d0860e2019-10-11 15:43:47 -0700543 bool (*callback)(void* opaque, const char* public_key, size_t len),
544 void* opaque) {
545 ctx->IteratePublicKeys(callback, opaque);
Josh Gaob789fb12019-10-24 19:02:14 -0700546}
547
548uint64_t adbd_auth_notify_auth(AdbdAuthContext* ctx, const char* public_key, size_t len) {
549 return ctx->NotifyAuthenticated(std::string_view(public_key, len));
550}
551
552void adbd_auth_notify_disconnect(AdbdAuthContext* ctx, uint64_t id) {
553 return ctx->NotifyDisconnected(id);
554}
555
556void adbd_auth_prompt_user(AdbdAuthContext* ctx, const char* public_key, size_t len,
Joshua Duong3d0860e2019-10-11 15:43:47 -0700557 void* opaque) {
Josh Gao9e933c52020-06-24 16:11:21 -0700558 adbd_auth_prompt_user_with_id(ctx, public_key, len, opaque);
559}
560
561uint64_t adbd_auth_prompt_user_with_id(AdbdAuthContext* ctx, const char* public_key, size_t len,
562 void* opaque) {
563 return ctx->PromptUser(std::string_view(public_key, len), opaque);
Josh Gaob789fb12019-10-24 19:02:14 -0700564}
565
Joshua Duong3d0860e2019-10-11 15:43:47 -0700566uint64_t adbd_auth_tls_device_connected(AdbdAuthContext* ctx,
567 AdbTransportType type,
568 const char* public_key,
569 size_t len) {
570 return ctx->NotifyTlsDeviceConnected(type, std::string_view(public_key, len));
571}
572
573void adbd_auth_tls_device_disconnected(AdbdAuthContext* ctx,
574 AdbTransportType type,
575 uint64_t id) {
576 ctx->NotifyTlsDeviceDisconnected(type, id);
577}
578
579uint32_t adbd_auth_get_max_version() {
580 return kAuthVersion;
581}
582
583bool adbd_auth_supports_feature(AdbdAuthFeature f) {
584 UNUSED(f);
Josh Gaob789fb12019-10-24 19:02:14 -0700585 return false;
586}