blob: 458d3fc5577cc6339987d81ff23f660ef2e9d630 [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());
209 CHECK(dispatched_prompt_.has_value());
210 auto& [id, key, arg] = *dispatched_prompt_;
211 keys_.emplace(id, std::move(key));
212
213 callbacks_.key_authorized(arg, id);
214 dispatched_prompt_ = std::nullopt;
215
216 // We need to dispatch pending prompts here upon success as well,
217 // since we might have multiple queued prompts.
218 DispatchPendingPrompt();
219 }
220
221 void DenyUsbDevice(std::string_view buf) EXCLUDES(mutex_) {
222 std::lock_guard<std::mutex> lock(mutex_);
223 CHECK(buf.empty());
224 // TODO: Do we want a callback if the key is denied?
225 dispatched_prompt_ = std::nullopt;
226 DispatchPendingPrompt();
227 }
228
229 void KeyRemoved(std::string_view buf) EXCLUDES(mutex_) {
230 CHECK(!buf.empty());
231 callbacks_.key_removed(buf.data(), buf.size());
Josh Gaob789fb12019-10-24 19:02:14 -0700232 }
233
234 bool SendPacket() REQUIRES(mutex_) {
235 if (output_queue_.empty()) {
236 return false;
237 }
238
239 CHECK_NE(-1, framework_fd_.get());
240
241 auto& packet = output_queue_.front();
Joshua Duong3d0860e2019-10-11 15:43:47 -0700242 struct iovec iovs[3];
243 int iovcnt = 2;
Josh Gaob789fb12019-10-24 19:02:14 -0700244 if (auto* p = std::get_if<AdbdAuthPacketAuthenticated>(&packet)) {
245 iovs[0].iov_base = const_cast<char*>("CK");
246 iovs[0].iov_len = 2;
247 iovs[1].iov_base = p->public_key.data();
248 iovs[1].iov_len = p->public_key.size();
249 } else if (auto* p = std::get_if<AdbdAuthPacketDisconnected>(&packet)) {
250 iovs[0].iov_base = const_cast<char*>("DC");
251 iovs[0].iov_len = 2;
252 iovs[1].iov_base = p->public_key.data();
253 iovs[1].iov_len = p->public_key.size();
254 } else if (auto* p = std::get_if<AdbdAuthPacketRequestAuthorization>(&packet)) {
255 iovs[0].iov_base = const_cast<char*>("PK");
256 iovs[0].iov_len = 2;
257 iovs[1].iov_base = p->public_key.data();
258 iovs[1].iov_len = p->public_key.size();
Joshua Duong3d0860e2019-10-11 15:43:47 -0700259 } else if (auto* p = std::get_if<AdbdPacketTlsDeviceConnected>(&packet)) {
260 iovcnt = 3;
261 iovs[0].iov_base = const_cast<char*>("WE");
262 iovs[0].iov_len = 2;
263 iovs[1].iov_base = &p->transport_type;
264 iovs[1].iov_len = 1;
265 iovs[2].iov_base = p->public_key.data();
266 iovs[2].iov_len = p->public_key.size();
267 } else if (auto* p = std::get_if<AdbdPacketTlsDeviceDisconnected>(&packet)) {
268 iovcnt = 3;
269 iovs[0].iov_base = const_cast<char*>("WF");
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();
Josh Gaob789fb12019-10-24 19:02:14 -0700275 } else {
Josh Gao975cee72020-06-24 16:10:55 -0700276 LOG(FATAL) << "adbd_auth: unhandled packet type?";
Josh Gaob789fb12019-10-24 19:02:14 -0700277 }
278
279 output_queue_.pop_front();
280
Joshua Duong3d0860e2019-10-11 15:43:47 -0700281 ssize_t rc = writev(framework_fd_.get(), iovs, iovcnt);
Josh Gaob789fb12019-10-24 19:02:14 -0700282 if (rc == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
Josh Gao975cee72020-06-24 16:10:55 -0700283 PLOG(ERROR) << "adbd_auth: failed to write to framework fd";
Josh Gaob789fb12019-10-24 19:02:14 -0700284 ReplaceFrameworkFd(unique_fd());
285 return false;
286 }
287
288 return true;
289 }
290
291 void Run() {
292 if (sock_fd_ == -1) {
Josh Gao975cee72020-06-24 16:10:55 -0700293 LOG(ERROR) << "adbd_auth: socket unavailable, disabling user prompts";
Josh Gaob789fb12019-10-24 19:02:14 -0700294 } else {
295 struct epoll_event event;
296 event.events = EPOLLIN;
297 event.data.u64 = kEpollConstSocket;
298 CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, sock_fd_.get(), &event));
299 }
300
301 {
302 struct epoll_event event;
303 event.events = EPOLLIN;
304 event.data.u64 = kEpollConstEventFd;
305 CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, event_fd_.get(), &event));
306 }
307
308 while (true) {
309 struct epoll_event events[3];
310 int rc = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd_.get(), events, 3, -1));
311 if (rc == -1) {
Josh Gao975cee72020-06-24 16:10:55 -0700312 PLOG(FATAL) << "adbd_auth: epoll_wait failed";
Josh Gaob789fb12019-10-24 19:02:14 -0700313 } else if (rc == 0) {
Josh Gao975cee72020-06-24 16:10:55 -0700314 LOG(FATAL) << "adbd_auth: epoll_wait returned 0";
Josh Gaob789fb12019-10-24 19:02:14 -0700315 }
316
317 bool restart = false;
318 for (int i = 0; i < rc; ++i) {
319 if (restart) {
320 break;
321 }
322
323 struct epoll_event& event = events[i];
324 switch (event.data.u64) {
325 case kEpollConstSocket: {
326 unique_fd new_framework_fd(accept4(sock_fd_.get(), nullptr, nullptr,
327 SOCK_CLOEXEC | SOCK_NONBLOCK));
328 if (new_framework_fd == -1) {
Josh Gao975cee72020-06-24 16:10:55 -0700329 PLOG(FATAL) << "adbd_auth: failed to accept framework fd";
Josh Gaob789fb12019-10-24 19:02:14 -0700330 }
331
332 LOG(INFO) << "adbd_auth: received a new framework connection";
333 std::lock_guard<std::mutex> lock(mutex_);
334 ReplaceFrameworkFd(std::move(new_framework_fd));
335
336 // Stop iterating over events: one of the later ones might be the old
337 // framework fd.
338 restart = false;
339 break;
340 }
341
342 case kEpollConstEventFd: {
343 // We were woken up to write something.
344 uint64_t dummy;
345 int rc = TEMP_FAILURE_RETRY(read(event_fd_.get(), &dummy, sizeof(dummy)));
346 if (rc != 8) {
Josh Gao975cee72020-06-24 16:10:55 -0700347 PLOG(FATAL)
348 << "adbd_auth: failed to read from eventfd (rc = " << rc << ")";
Josh Gaob789fb12019-10-24 19:02:14 -0700349 }
350
351 std::lock_guard<std::mutex> lock(mutex_);
352 UpdateFrameworkWritable();
353 break;
354 }
355
356 case kEpollConstFramework: {
357 char buf[4096];
358 if (event.events & EPOLLIN) {
359 int rc = TEMP_FAILURE_RETRY(read(framework_fd_.get(), buf, sizeof(buf)));
360 if (rc == -1) {
Josh Gao975cee72020-06-24 16:10:55 -0700361 LOG(FATAL) << "adbd_auth: failed to read from framework fd";
Josh Gaob789fb12019-10-24 19:02:14 -0700362 } else if (rc == 0) {
Josh Gao975cee72020-06-24 16:10:55 -0700363 LOG(INFO) << "adbd_auth: hit EOF on framework fd";
Josh Gaob789fb12019-10-24 19:02:14 -0700364 std::lock_guard<std::mutex> lock(mutex_);
365 ReplaceFrameworkFd(unique_fd());
366 } else {
Josh Gaob789fb12019-10-24 19:02:14 -0700367 HandlePacket(std::string_view(buf, rc));
368 }
369 }
370
371 if (event.events & EPOLLOUT) {
372 std::lock_guard<std::mutex> lock(mutex_);
373 while (SendPacket()) {
374 continue;
375 }
376 UpdateFrameworkWritable();
377 }
378
379 break;
380 }
381 }
382 }
383 }
384 }
385
386 static constexpr const char* key_paths[] = {"/adb_keys", "/data/misc/adb/adb_keys"};
Joshua Duong3d0860e2019-10-11 15:43:47 -0700387 void IteratePublicKeys(bool (*callback)(void*, const char*, size_t), void* opaque) {
Josh Gaob789fb12019-10-24 19:02:14 -0700388 for (const auto& path : key_paths) {
389 if (access(path, R_OK) == 0) {
Josh Gao975cee72020-06-24 16:10:55 -0700390 LOG(INFO) << "adbd_auth: loading keys from " << path;
Josh Gaob789fb12019-10-24 19:02:14 -0700391 std::string content;
392 if (!android::base::ReadFileToString(path, &content)) {
Josh Gao975cee72020-06-24 16:10:55 -0700393 PLOG(ERROR) << "adbd_auth: couldn't read " << path;
Josh Gaob789fb12019-10-24 19:02:14 -0700394 continue;
395 }
396 for (const auto& line : android::base::Split(content, "\n")) {
Joshua Duong3d0860e2019-10-11 15:43:47 -0700397 if (!callback(opaque, line.data(), line.size())) {
Josh Gaob789fb12019-10-24 19:02:14 -0700398 return;
399 }
400 }
401 }
402 }
403 }
404
405 uint64_t PromptUser(std::string_view public_key, void* arg) EXCLUDES(mutex_) {
406 uint64_t id = NextId();
407
408 std::lock_guard<std::mutex> lock(mutex_);
Josh Gao975cee72020-06-24 16:10:55 -0700409 LOG(INFO) << "adbd_auth: sending prompt with id " << id;
Josh Gaob789fb12019-10-24 19:02:14 -0700410 pending_prompts_.emplace_back(id, public_key, arg);
411 DispatchPendingPrompt();
412 return id;
413 }
414
415 uint64_t NotifyAuthenticated(std::string_view public_key) EXCLUDES(mutex_) {
416 uint64_t id = NextId();
417 std::lock_guard<std::mutex> lock(mutex_);
418 keys_.emplace(id, public_key);
419 output_queue_.emplace_back(
Joshua Duong3d0860e2019-10-11 15:43:47 -0700420 AdbdAuthPacketAuthenticated{.public_key = std::string(public_key)});
Josh Gaob789fb12019-10-24 19:02:14 -0700421 return id;
422 }
423
424 void NotifyDisconnected(uint64_t id) EXCLUDES(mutex_) {
425 std::lock_guard<std::mutex> lock(mutex_);
426 auto it = keys_.find(id);
427 if (it == keys_.end()) {
Josh Gao975cee72020-06-24 16:10:55 -0700428 LOG(DEBUG) << "adbd_auth: couldn't find public key to notify disconnection, skipping";
Josh Gaob789fb12019-10-24 19:02:14 -0700429 return;
430 }
431 output_queue_.emplace_back(AdbdAuthPacketDisconnected{.public_key = std::move(it->second)});
432 keys_.erase(it);
433 }
434
Joshua Duong3d0860e2019-10-11 15:43:47 -0700435 uint64_t NotifyTlsDeviceConnected(AdbTransportType type,
436 std::string_view public_key) EXCLUDES(mutex_) {
437 uint64_t id = NextId();
438 std::lock_guard<std::mutex> lock(mutex_);
439 keys_.emplace(id, public_key);
440 output_queue_.emplace_back(AdbdPacketTlsDeviceConnected{
441 .transport_type = static_cast<uint8_t>(type),
442 .public_key = std::string(public_key)});
443 Interrupt();
444 return id;
445 }
446
447 void NotifyTlsDeviceDisconnected(AdbTransportType type, uint64_t id) EXCLUDES(mutex_) {
448 std::lock_guard<std::mutex> lock(mutex_);
449 auto it = keys_.find(id);
450 if (it == keys_.end()) {
Josh Gao975cee72020-06-24 16:10:55 -0700451 LOG(DEBUG) << "adbd_auth: couldn't find public key to notify disconnection of tls "
452 "device, skipping";
Joshua Duong3d0860e2019-10-11 15:43:47 -0700453 return;
454 }
455 output_queue_.emplace_back(AdbdPacketTlsDeviceDisconnected{
456 .transport_type = static_cast<uint8_t>(type),
457 .public_key = std::move(it->second)});
458 keys_.erase(it);
459 Interrupt();
460 }
461
Josh Gaob789fb12019-10-24 19:02:14 -0700462 // Interrupt the worker thread to do some work.
463 void Interrupt() {
464 uint64_t value = 1;
465 ssize_t rc = write(event_fd_.get(), &value, sizeof(value));
466 if (rc == -1) {
Josh Gao975cee72020-06-24 16:10:55 -0700467 PLOG(FATAL) << "adbd_auth: write to eventfd failed";
Josh Gaob789fb12019-10-24 19:02:14 -0700468 } else if (rc != sizeof(value)) {
Josh Gao975cee72020-06-24 16:10:55 -0700469 LOG(FATAL) << "adbd_auth: write to eventfd returned short (" << rc << ")";
Josh Gaob789fb12019-10-24 19:02:14 -0700470 }
471 }
472
Joshua Duong3d0860e2019-10-11 15:43:47 -0700473 void InitFrameworkHandlers() {
474 // Framework wants to disconnect from a secured wifi device
475 framework_handlers_.emplace_back(
476 FrameworkPktHandler{
477 .code = "DD",
478 .cb = std::bind(&AdbdAuthContext::KeyRemoved, this, std::placeholders::_1)});
479 // Framework allows USB debugging for the device
480 framework_handlers_.emplace_back(
481 FrameworkPktHandler{
482 .code = "OK",
483 .cb = std::bind(&AdbdAuthContext::AllowUsbDevice, this, std::placeholders::_1)});
484 // Framework denies USB debugging for the device
485 framework_handlers_.emplace_back(
486 FrameworkPktHandler{
487 .code = "NO",
488 .cb = std::bind(&AdbdAuthContext::DenyUsbDevice, this, std::placeholders::_1)});
489 }
490
Josh Gaob789fb12019-10-24 19:02:14 -0700491 unique_fd epoll_fd_;
492 unique_fd event_fd_;
493 unique_fd sock_fd_;
494 unique_fd framework_fd_;
495
496 std::atomic<uint64_t> next_id_;
497 AdbdAuthCallbacksV1 callbacks_;
498
499 std::mutex mutex_;
500 std::unordered_map<uint64_t, std::string> keys_ GUARDED_BY(mutex_);
501
502 // We keep two separate queues: one to handle backpressure from the socket (output_queue_)
503 // and one to make sure we only dispatch one authrequest at a time (pending_prompts_).
Joshua Duong3d0860e2019-10-11 15:43:47 -0700504 std::deque<AdbdAuthPacket> output_queue_ GUARDED_BY(mutex_);
Josh Gaob789fb12019-10-24 19:02:14 -0700505
506 std::optional<std::tuple<uint64_t, std::string, void*>> dispatched_prompt_ GUARDED_BY(mutex_);
507 std::deque<std::tuple<uint64_t, std::string, void*>> pending_prompts_ GUARDED_BY(mutex_);
Joshua Duong3d0860e2019-10-11 15:43:47 -0700508
509 // This is a list of commands that the framework could send to us.
510 using FrameworkHandlerCb = std::function<void(std::string_view)>;
511 struct FrameworkPktHandler {
512 const char* code;
513 FrameworkHandlerCb cb;
514 };
515 std::vector<FrameworkPktHandler> framework_handlers_;
Josh Gaob789fb12019-10-24 19:02:14 -0700516};
517
518AdbdAuthContext* adbd_auth_new(AdbdAuthCallbacks* callbacks) {
Joshua Duong3d0860e2019-10-11 15:43:47 -0700519 if (callbacks->version == 1) {
520 return new AdbdAuthContext(reinterpret_cast<AdbdAuthCallbacksV1*>(callbacks));
521 } else {
Josh Gao975cee72020-06-24 16:10:55 -0700522 LOG(ERROR) << "adbd_auth: received unknown AdbdAuthCallbacks version "
523 << callbacks->version;
524 return nullptr;
Josh Gaob789fb12019-10-24 19:02:14 -0700525 }
Josh Gaob789fb12019-10-24 19:02:14 -0700526}
527
528void adbd_auth_delete(AdbdAuthContext* ctx) {
529 delete ctx;
530}
531
532void adbd_auth_run(AdbdAuthContext* ctx) {
533 return ctx->Run();
534}
535
536void adbd_auth_get_public_keys(AdbdAuthContext* ctx,
Joshua Duong3d0860e2019-10-11 15:43:47 -0700537 bool (*callback)(void* opaque, const char* public_key, size_t len),
538 void* opaque) {
539 ctx->IteratePublicKeys(callback, opaque);
Josh Gaob789fb12019-10-24 19:02:14 -0700540}
541
542uint64_t adbd_auth_notify_auth(AdbdAuthContext* ctx, const char* public_key, size_t len) {
543 return ctx->NotifyAuthenticated(std::string_view(public_key, len));
544}
545
546void adbd_auth_notify_disconnect(AdbdAuthContext* ctx, uint64_t id) {
547 return ctx->NotifyDisconnected(id);
548}
549
550void adbd_auth_prompt_user(AdbdAuthContext* ctx, const char* public_key, size_t len,
Joshua Duong3d0860e2019-10-11 15:43:47 -0700551 void* opaque) {
552 ctx->PromptUser(std::string_view(public_key, len), opaque);
Josh Gaob789fb12019-10-24 19:02:14 -0700553}
554
Joshua Duong3d0860e2019-10-11 15:43:47 -0700555uint64_t adbd_auth_tls_device_connected(AdbdAuthContext* ctx,
556 AdbTransportType type,
557 const char* public_key,
558 size_t len) {
559 return ctx->NotifyTlsDeviceConnected(type, std::string_view(public_key, len));
560}
561
562void adbd_auth_tls_device_disconnected(AdbdAuthContext* ctx,
563 AdbTransportType type,
564 uint64_t id) {
565 ctx->NotifyTlsDeviceDisconnected(type, id);
566}
567
568uint32_t adbd_auth_get_max_version() {
569 return kAuthVersion;
570}
571
572bool adbd_auth_supports_feature(AdbdAuthFeature f) {
573 UNUSED(f);
Josh Gaob789fb12019-10-24 19:02:14 -0700574 return false;
575}