1 /* 2 * Copyright (C) 2012 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 TRACE_TAG AUTH 18 19 #include "adb.h" 20 #include "adb_auth.h" 21 #include "fdevent.h" 22 #include "sysdeps.h" 23 #include "transport.h" 24 25 #include <resolv.h> 26 #include <stdio.h> 27 #include <string.h> 28 29 #include <memory> 30 31 #include <android-base/file.h> 32 #include <android-base/strings.h> 33 #include <crypto_utils/android_pubkey.h> 34 #include <openssl/obj_mac.h> 35 #include <openssl/rsa.h> 36 #include <openssl/sha.h> 37 38 static fdevent listener_fde; 39 static fdevent framework_fde; 40 static int framework_fd = -1; 41 42 static void usb_disconnected(void* unused, atransport* t); 43 static struct adisconnect usb_disconnect = { usb_disconnected, nullptr}; 44 static atransport* usb_transport; 45 static bool needs_retry = false; 46 47 bool auth_required = true; 48 49 bool adbd_auth_verify(const char* token, size_t token_size, const char* sig, int sig_len) { 50 static constexpr const char* key_paths[] = { "/adb_keys", "/data/misc/adb/adb_keys", nullptr }; 51 52 for (const auto& path : key_paths) { 53 if (access(path, R_OK) == 0) { 54 LOG(INFO) << "Loading keys from " << path; 55 56 std::string content; 57 if (!android::base::ReadFileToString(path, &content)) { 58 PLOG(ERROR) << "Couldn't read " << path; 59 continue; 60 } 61 62 for (const auto& line : android::base::Split(content, "\n")) { 63 // TODO: do we really have to support both ' ' and '\t'? 64 char* sep = strpbrk(const_cast<char*>(line.c_str()), " \t"); 65 if (sep) *sep = '\0'; 66 67 // b64_pton requires one additional byte in the target buffer for 68 // decoding to succeed. See http://b/28035006 for details. 69 uint8_t keybuf[ANDROID_PUBKEY_ENCODED_SIZE + 1]; 70 if (__b64_pton(line.c_str(), keybuf, sizeof(keybuf)) != ANDROID_PUBKEY_ENCODED_SIZE) { 71 LOG(ERROR) << "Invalid base64 key " << line.c_str() << " in " << path; 72 continue; 73 } 74 75 RSA* key = nullptr; 76 if (!android_pubkey_decode(keybuf, ANDROID_PUBKEY_ENCODED_SIZE, &key)) { 77 LOG(ERROR) << "Failed to parse key " << line.c_str() << " in " << path; 78 continue; 79 } 80 81 bool verified = 82 (RSA_verify(NID_sha1, reinterpret_cast<const uint8_t*>(token), token_size, 83 reinterpret_cast<const uint8_t*>(sig), sig_len, key) == 1); 84 RSA_free(key); 85 if (verified) return true; 86 } 87 } 88 } 89 return false; 90 } 91 92 static bool adbd_auth_generate_token(void* token, size_t token_size) { 93 FILE* fp = fopen("/dev/urandom", "re"); 94 if (!fp) return false; 95 bool okay = (fread(token, token_size, 1, fp) == 1); 96 fclose(fp); 97 return okay; 98 } 99 100 static void usb_disconnected(void* unused, atransport* t) { 101 LOG(INFO) << "USB disconnect"; 102 usb_transport = NULL; 103 needs_retry = false; 104 } 105 106 static void framework_disconnected() { 107 LOG(INFO) << "Framework disconnect"; 108 fdevent_remove(&framework_fde); 109 framework_fd = -1; 110 } 111 112 static void adbd_auth_event(int fd, unsigned events, void*) { 113 if (events & FDE_READ) { 114 char response[2]; 115 int ret = unix_read(fd, response, sizeof(response)); 116 if (ret <= 0) { 117 framework_disconnected(); 118 } else if (ret == 2 && response[0] == 'O' && response[1] == 'K') { 119 if (usb_transport) { 120 adbd_auth_verified(usb_transport); 121 } 122 } 123 } 124 } 125 126 void adbd_auth_confirm_key(const char* key, size_t len, atransport* t) { 127 if (!usb_transport) { 128 usb_transport = t; 129 t->AddDisconnect(&usb_disconnect); 130 } 131 132 if (framework_fd < 0) { 133 LOG(ERROR) << "Client not connected"; 134 needs_retry = true; 135 return; 136 } 137 138 if (key[len - 1] != '\0') { 139 LOG(ERROR) << "Key must be a null-terminated string"; 140 return; 141 } 142 143 char msg[MAX_PAYLOAD_V1]; 144 int msg_len = snprintf(msg, sizeof(msg), "PK%s", key); 145 if (msg_len >= static_cast<int>(sizeof(msg))) { 146 LOG(ERROR) << "Key too long (" << msg_len << ")"; 147 return; 148 } 149 LOG(DEBUG) << "Sending '" << msg << "'"; 150 151 if (unix_write(framework_fd, msg, msg_len) == -1) { 152 PLOG(ERROR) << "Failed to write PK"; 153 return; 154 } 155 } 156 157 static void adbd_auth_listener(int fd, unsigned events, void* data) { 158 int s = adb_socket_accept(fd, nullptr, nullptr); 159 if (s < 0) { 160 PLOG(ERROR) << "Failed to accept"; 161 return; 162 } 163 164 if (framework_fd >= 0) { 165 LOG(WARNING) << "adb received framework auth socket connection again"; 166 framework_disconnected(); 167 } 168 169 framework_fd = s; 170 fdevent_install(&framework_fde, framework_fd, adbd_auth_event, nullptr); 171 fdevent_add(&framework_fde, FDE_READ); 172 173 if (needs_retry) { 174 needs_retry = false; 175 send_auth_request(usb_transport); 176 } 177 } 178 179 void adbd_cloexec_auth_socket() { 180 int fd = android_get_control_socket("adbd"); 181 if (fd == -1) { 182 PLOG(ERROR) << "Failed to get adbd socket"; 183 return; 184 } 185 fcntl(fd, F_SETFD, FD_CLOEXEC); 186 } 187 188 void adbd_auth_init(void) { 189 int fd = android_get_control_socket("adbd"); 190 if (fd == -1) { 191 PLOG(ERROR) << "Failed to get adbd socket"; 192 return; 193 } 194 195 if (listen(fd, 4) == -1) { 196 PLOG(ERROR) << "Failed to listen on '" << fd << "'"; 197 return; 198 } 199 200 fdevent_install(&listener_fde, fd, adbd_auth_listener, NULL); 201 fdevent_add(&listener_fde, FDE_READ); 202 } 203 204 void send_auth_request(atransport* t) { 205 LOG(INFO) << "Calling send_auth_request..."; 206 207 if (!adbd_auth_generate_token(t->token, sizeof(t->token))) { 208 PLOG(ERROR) << "Error generating token"; 209 return; 210 } 211 212 apacket* p = get_apacket(); 213 memcpy(p->data, t->token, sizeof(t->token)); 214 p->msg.command = A_AUTH; 215 p->msg.arg0 = ADB_AUTH_TOKEN; 216 p->msg.data_length = sizeof(t->token); 217 send_packet(p, t); 218 } 219 220 void adbd_auth_verified(atransport *t) 221 { 222 handle_online(t); 223 send_connect(t); 224 } 225