blob: 15bd5c39136c3d7b27a256c59a076133b1c3de8f [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
Joshua Duong3d0860e2019-10-11 15:43:47 -0700285 ssize_t rc = writev(framework_fd_.get(), iovs, iovcnt);
Daniel Micaye3e1cd52021-01-02 20:17:35 -0500286 output_queue_.pop_front();
Josh Gaob789fb12019-10-24 19:02:14 -0700287 if (rc == -1 && errno != EAGAIN && errno != EWOULDBLOCK) {
Josh Gao975cee72020-06-24 16:10:55 -0700288 PLOG(ERROR) << "adbd_auth: failed to write to framework fd";
Josh Gaob789fb12019-10-24 19:02:14 -0700289 ReplaceFrameworkFd(unique_fd());
290 return false;
291 }
292
293 return true;
294 }
295
296 void Run() {
297 if (sock_fd_ == -1) {
Josh Gao975cee72020-06-24 16:10:55 -0700298 LOG(ERROR) << "adbd_auth: socket unavailable, disabling user prompts";
Josh Gaob789fb12019-10-24 19:02:14 -0700299 } else {
300 struct epoll_event event;
301 event.events = EPOLLIN;
302 event.data.u64 = kEpollConstSocket;
303 CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, sock_fd_.get(), &event));
304 }
305
306 {
307 struct epoll_event event;
308 event.events = EPOLLIN;
309 event.data.u64 = kEpollConstEventFd;
310 CHECK_EQ(0, epoll_ctl(epoll_fd_.get(), EPOLL_CTL_ADD, event_fd_.get(), &event));
311 }
312
313 while (true) {
314 struct epoll_event events[3];
315 int rc = TEMP_FAILURE_RETRY(epoll_wait(epoll_fd_.get(), events, 3, -1));
316 if (rc == -1) {
Josh Gao975cee72020-06-24 16:10:55 -0700317 PLOG(FATAL) << "adbd_auth: epoll_wait failed";
Josh Gaob789fb12019-10-24 19:02:14 -0700318 } else if (rc == 0) {
Josh Gao975cee72020-06-24 16:10:55 -0700319 LOG(FATAL) << "adbd_auth: epoll_wait returned 0";
Josh Gaob789fb12019-10-24 19:02:14 -0700320 }
321
322 bool restart = false;
323 for (int i = 0; i < rc; ++i) {
324 if (restart) {
325 break;
326 }
327
328 struct epoll_event& event = events[i];
329 switch (event.data.u64) {
330 case kEpollConstSocket: {
331 unique_fd new_framework_fd(accept4(sock_fd_.get(), nullptr, nullptr,
332 SOCK_CLOEXEC | SOCK_NONBLOCK));
333 if (new_framework_fd == -1) {
Josh Gao975cee72020-06-24 16:10:55 -0700334 PLOG(FATAL) << "adbd_auth: failed to accept framework fd";
Josh Gaob789fb12019-10-24 19:02:14 -0700335 }
336
337 LOG(INFO) << "adbd_auth: received a new framework connection";
338 std::lock_guard<std::mutex> lock(mutex_);
339 ReplaceFrameworkFd(std::move(new_framework_fd));
340
341 // Stop iterating over events: one of the later ones might be the old
342 // framework fd.
343 restart = false;
344 break;
345 }
346
347 case kEpollConstEventFd: {
348 // We were woken up to write something.
349 uint64_t dummy;
350 int rc = TEMP_FAILURE_RETRY(read(event_fd_.get(), &dummy, sizeof(dummy)));
351 if (rc != 8) {
Josh Gao975cee72020-06-24 16:10:55 -0700352 PLOG(FATAL)
353 << "adbd_auth: failed to read from eventfd (rc = " << rc << ")";
Josh Gaob789fb12019-10-24 19:02:14 -0700354 }
355
356 std::lock_guard<std::mutex> lock(mutex_);
357 UpdateFrameworkWritable();
358 break;
359 }
360
361 case kEpollConstFramework: {
362 char buf[4096];
363 if (event.events & EPOLLIN) {
364 int rc = TEMP_FAILURE_RETRY(read(framework_fd_.get(), buf, sizeof(buf)));
365 if (rc == -1) {
Josh Gao975cee72020-06-24 16:10:55 -0700366 LOG(FATAL) << "adbd_auth: failed to read from framework fd";
Josh Gaob789fb12019-10-24 19:02:14 -0700367 } else if (rc == 0) {
Josh Gao975cee72020-06-24 16:10:55 -0700368 LOG(INFO) << "adbd_auth: hit EOF on framework fd";
Josh Gaob789fb12019-10-24 19:02:14 -0700369 std::lock_guard<std::mutex> lock(mutex_);
370 ReplaceFrameworkFd(unique_fd());
371 } else {
Josh Gaob789fb12019-10-24 19:02:14 -0700372 HandlePacket(std::string_view(buf, rc));
373 }
374 }
375
376 if (event.events & EPOLLOUT) {
377 std::lock_guard<std::mutex> lock(mutex_);
378 while (SendPacket()) {
379 continue;
380 }
381 UpdateFrameworkWritable();
382 }
383
384 break;
385 }
386 }
387 }
388 }
389 }
390
391 static constexpr const char* key_paths[] = {"/adb_keys", "/data/misc/adb/adb_keys"};
Joshua Duong3d0860e2019-10-11 15:43:47 -0700392 void IteratePublicKeys(bool (*callback)(void*, const char*, size_t), void* opaque) {
Josh Gaob789fb12019-10-24 19:02:14 -0700393 for (const auto& path : key_paths) {
394 if (access(path, R_OK) == 0) {
Josh Gao975cee72020-06-24 16:10:55 -0700395 LOG(INFO) << "adbd_auth: loading keys from " << path;
Josh Gaob789fb12019-10-24 19:02:14 -0700396 std::string content;
397 if (!android::base::ReadFileToString(path, &content)) {
Josh Gao975cee72020-06-24 16:10:55 -0700398 PLOG(ERROR) << "adbd_auth: couldn't read " << path;
Josh Gaob789fb12019-10-24 19:02:14 -0700399 continue;
400 }
401 for (const auto& line : android::base::Split(content, "\n")) {
Joshua Duong3d0860e2019-10-11 15:43:47 -0700402 if (!callback(opaque, line.data(), line.size())) {
Josh Gaob789fb12019-10-24 19:02:14 -0700403 return;
404 }
405 }
406 }
407 }
408 }
409
410 uint64_t PromptUser(std::string_view public_key, void* arg) EXCLUDES(mutex_) {
411 uint64_t id = NextId();
412
413 std::lock_guard<std::mutex> lock(mutex_);
Josh Gao975cee72020-06-24 16:10:55 -0700414 LOG(INFO) << "adbd_auth: sending prompt with id " << id;
Josh Gaob789fb12019-10-24 19:02:14 -0700415 pending_prompts_.emplace_back(id, public_key, arg);
416 DispatchPendingPrompt();
417 return id;
418 }
419
420 uint64_t NotifyAuthenticated(std::string_view public_key) EXCLUDES(mutex_) {
421 uint64_t id = NextId();
422 std::lock_guard<std::mutex> lock(mutex_);
423 keys_.emplace(id, public_key);
424 output_queue_.emplace_back(
Joshua Duong3d0860e2019-10-11 15:43:47 -0700425 AdbdAuthPacketAuthenticated{.public_key = std::string(public_key)});
Josh Gaob789fb12019-10-24 19:02:14 -0700426 return id;
427 }
428
429 void NotifyDisconnected(uint64_t id) EXCLUDES(mutex_) {
430 std::lock_guard<std::mutex> lock(mutex_);
431 auto it = keys_.find(id);
432 if (it == keys_.end()) {
Josh Gao975cee72020-06-24 16:10:55 -0700433 LOG(DEBUG) << "adbd_auth: couldn't find public key to notify disconnection, skipping";
Josh Gaob789fb12019-10-24 19:02:14 -0700434 return;
435 }
436 output_queue_.emplace_back(AdbdAuthPacketDisconnected{.public_key = std::move(it->second)});
437 keys_.erase(it);
438 }
439
Joshua Duong3d0860e2019-10-11 15:43:47 -0700440 uint64_t NotifyTlsDeviceConnected(AdbTransportType type,
441 std::string_view public_key) EXCLUDES(mutex_) {
442 uint64_t id = NextId();
443 std::lock_guard<std::mutex> lock(mutex_);
444 keys_.emplace(id, public_key);
445 output_queue_.emplace_back(AdbdPacketTlsDeviceConnected{
446 .transport_type = static_cast<uint8_t>(type),
447 .public_key = std::string(public_key)});
448 Interrupt();
449 return id;
450 }
451
452 void NotifyTlsDeviceDisconnected(AdbTransportType type, uint64_t id) EXCLUDES(mutex_) {
453 std::lock_guard<std::mutex> lock(mutex_);
454 auto it = keys_.find(id);
455 if (it == keys_.end()) {
Josh Gao975cee72020-06-24 16:10:55 -0700456 LOG(DEBUG) << "adbd_auth: couldn't find public key to notify disconnection of tls "
457 "device, skipping";
Joshua Duong3d0860e2019-10-11 15:43:47 -0700458 return;
459 }
460 output_queue_.emplace_back(AdbdPacketTlsDeviceDisconnected{
461 .transport_type = static_cast<uint8_t>(type),
462 .public_key = std::move(it->second)});
463 keys_.erase(it);
464 Interrupt();
465 }
466
Josh Gaob789fb12019-10-24 19:02:14 -0700467 // Interrupt the worker thread to do some work.
468 void Interrupt() {
469 uint64_t value = 1;
470 ssize_t rc = write(event_fd_.get(), &value, sizeof(value));
471 if (rc == -1) {
Josh Gao975cee72020-06-24 16:10:55 -0700472 PLOG(FATAL) << "adbd_auth: write to eventfd failed";
Josh Gaob789fb12019-10-24 19:02:14 -0700473 } else if (rc != sizeof(value)) {
Josh Gao975cee72020-06-24 16:10:55 -0700474 LOG(FATAL) << "adbd_auth: write to eventfd returned short (" << rc << ")";
Josh Gaob789fb12019-10-24 19:02:14 -0700475 }
476 }
477
Joshua Duong3d0860e2019-10-11 15:43:47 -0700478 void InitFrameworkHandlers() {
479 // Framework wants to disconnect from a secured wifi device
480 framework_handlers_.emplace_back(
481 FrameworkPktHandler{
482 .code = "DD",
483 .cb = std::bind(&AdbdAuthContext::KeyRemoved, this, std::placeholders::_1)});
484 // Framework allows USB debugging for the device
485 framework_handlers_.emplace_back(
486 FrameworkPktHandler{
487 .code = "OK",
488 .cb = std::bind(&AdbdAuthContext::AllowUsbDevice, this, std::placeholders::_1)});
489 // Framework denies USB debugging for the device
490 framework_handlers_.emplace_back(
491 FrameworkPktHandler{
492 .code = "NO",
493 .cb = std::bind(&AdbdAuthContext::DenyUsbDevice, this, std::placeholders::_1)});
494 }
495
Josh Gaob789fb12019-10-24 19:02:14 -0700496 unique_fd epoll_fd_;
497 unique_fd event_fd_;
498 unique_fd sock_fd_;
499 unique_fd framework_fd_;
500
501 std::atomic<uint64_t> next_id_;
502 AdbdAuthCallbacksV1 callbacks_;
503
504 std::mutex mutex_;
505 std::unordered_map<uint64_t, std::string> keys_ GUARDED_BY(mutex_);
506
507 // We keep two separate queues: one to handle backpressure from the socket (output_queue_)
508 // and one to make sure we only dispatch one authrequest at a time (pending_prompts_).
Joshua Duong3d0860e2019-10-11 15:43:47 -0700509 std::deque<AdbdAuthPacket> output_queue_ GUARDED_BY(mutex_);
Josh Gaob789fb12019-10-24 19:02:14 -0700510
511 std::optional<std::tuple<uint64_t, std::string, void*>> dispatched_prompt_ GUARDED_BY(mutex_);
512 std::deque<std::tuple<uint64_t, std::string, void*>> pending_prompts_ GUARDED_BY(mutex_);
Joshua Duong3d0860e2019-10-11 15:43:47 -0700513
514 // This is a list of commands that the framework could send to us.
515 using FrameworkHandlerCb = std::function<void(std::string_view)>;
516 struct FrameworkPktHandler {
517 const char* code;
518 FrameworkHandlerCb cb;
519 };
520 std::vector<FrameworkPktHandler> framework_handlers_;
Josh Gaob789fb12019-10-24 19:02:14 -0700521};
522
523AdbdAuthContext* adbd_auth_new(AdbdAuthCallbacks* callbacks) {
Joshua Duong3d0860e2019-10-11 15:43:47 -0700524 if (callbacks->version == 1) {
525 return new AdbdAuthContext(reinterpret_cast<AdbdAuthCallbacksV1*>(callbacks));
526 } else {
Josh Gao975cee72020-06-24 16:10:55 -0700527 LOG(ERROR) << "adbd_auth: received unknown AdbdAuthCallbacks version "
528 << callbacks->version;
529 return nullptr;
Josh Gaob789fb12019-10-24 19:02:14 -0700530 }
Josh Gaob789fb12019-10-24 19:02:14 -0700531}
532
533void adbd_auth_delete(AdbdAuthContext* ctx) {
534 delete ctx;
535}
536
537void adbd_auth_run(AdbdAuthContext* ctx) {
538 return ctx->Run();
539}
540
541void adbd_auth_get_public_keys(AdbdAuthContext* ctx,
Joshua Duong3d0860e2019-10-11 15:43:47 -0700542 bool (*callback)(void* opaque, const char* public_key, size_t len),
543 void* opaque) {
544 ctx->IteratePublicKeys(callback, opaque);
Josh Gaob789fb12019-10-24 19:02:14 -0700545}
546
547uint64_t adbd_auth_notify_auth(AdbdAuthContext* ctx, const char* public_key, size_t len) {
548 return ctx->NotifyAuthenticated(std::string_view(public_key, len));
549}
550
551void adbd_auth_notify_disconnect(AdbdAuthContext* ctx, uint64_t id) {
552 return ctx->NotifyDisconnected(id);
553}
554
555void adbd_auth_prompt_user(AdbdAuthContext* ctx, const char* public_key, size_t len,
Joshua Duong3d0860e2019-10-11 15:43:47 -0700556 void* opaque) {
Josh Gao9e933c52020-06-24 16:11:21 -0700557 adbd_auth_prompt_user_with_id(ctx, public_key, len, opaque);
558}
559
560uint64_t adbd_auth_prompt_user_with_id(AdbdAuthContext* ctx, const char* public_key, size_t len,
561 void* opaque) {
562 return ctx->PromptUser(std::string_view(public_key, len), opaque);
Josh Gaob789fb12019-10-24 19:02:14 -0700563}
564
Joshua Duong3d0860e2019-10-11 15:43:47 -0700565uint64_t adbd_auth_tls_device_connected(AdbdAuthContext* ctx,
566 AdbTransportType type,
567 const char* public_key,
568 size_t len) {
569 return ctx->NotifyTlsDeviceConnected(type, std::string_view(public_key, len));
570}
571
572void adbd_auth_tls_device_disconnected(AdbdAuthContext* ctx,
573 AdbTransportType type,
574 uint64_t id) {
575 ctx->NotifyTlsDeviceDisconnected(type, id);
576}
577
578uint32_t adbd_auth_get_max_version() {
579 return kAuthVersion;
580}
581
582bool adbd_auth_supports_feature(AdbdAuthFeature f) {
583 UNUSED(f);
Josh Gaob789fb12019-10-24 19:02:14 -0700584 return false;
585}