adb_auth_client.c revision 045a4a9c3a317e60ab1078f5a689bf302ee2ab19
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#include <stdio.h> 18#include <string.h> 19#include <resolv.h> 20#include <cutils/list.h> 21#include <cutils/sockets.h> 22 23#include "sysdeps.h" 24#include "adb.h" 25#include "adb_auth.h" 26#include "fdevent.h" 27#include "mincrypt/rsa.h" 28 29#define TRACE_TAG TRACE_AUTH 30 31 32struct adb_public_key { 33 struct listnode node; 34 RSAPublicKey key; 35}; 36 37static char *key_paths[] = { 38 "/adb_keys", 39 "/data/misc/adb/adb_keys", 40 NULL 41}; 42 43static fdevent listener_fde; 44static int framework_fd = -1; 45 46static void usb_disconnected(void* unused, atransport* t); 47static struct adisconnect usb_disconnect = { usb_disconnected, 0, 0, 0 }; 48static atransport* usb_transport; 49static bool needs_retry = false; 50 51static void read_keys(const char *file, struct listnode *list) 52{ 53 struct adb_public_key *key; 54 FILE *f; 55 char buf[MAX_PAYLOAD]; 56 char *sep; 57 int ret; 58 59 f = fopen(file, "r"); 60 if (!f) { 61 D("Can't open '%s'\n", file); 62 return; 63 } 64 65 while (fgets(buf, sizeof(buf), f)) { 66 /* Allocate 4 extra bytes to decode the base64 data in-place */ 67 key = calloc(1, sizeof(*key) + 4); 68 if (!key) { 69 D("Can't malloc key\n"); 70 break; 71 } 72 73 sep = strpbrk(buf, " \t"); 74 if (sep) 75 *sep = '\0'; 76 77 ret = __b64_pton(buf, (u_char *)&key->key, sizeof(key->key) + 4); 78 if (ret != sizeof(key->key)) { 79 D("%s: Invalid base64 data ret=%d\n", file, ret); 80 free(key); 81 continue; 82 } 83 84 if (key->key.len != RSANUMWORDS) { 85 D("%s: Invalid key len %d\n", file, key->key.len); 86 free(key); 87 continue; 88 } 89 90 list_add_tail(list, &key->node); 91 } 92 93 fclose(f); 94} 95 96static void free_keys(struct listnode *list) 97{ 98 struct listnode *item; 99 100 while (!list_empty(list)) { 101 item = list_head(list); 102 list_remove(item); 103 free(node_to_item(item, struct adb_public_key, node)); 104 } 105} 106 107static void load_keys(struct listnode *list) 108{ 109 char *path; 110 char **paths = key_paths; 111 struct stat buf; 112 113 list_init(list); 114 115 while ((path = *paths++)) { 116 if (!stat(path, &buf)) { 117 D("Loading keys from '%s'\n", path); 118 read_keys(path, list); 119 } 120 } 121} 122 123int adb_auth_generate_token(void *token, size_t token_size) 124{ 125 FILE *f; 126 int ret; 127 128 f = fopen("/dev/urandom", "r"); 129 if (!f) 130 return 0; 131 132 ret = fread(token, token_size, 1, f); 133 134 fclose(f); 135 return ret * token_size; 136} 137 138int adb_auth_verify(void *token, void *sig, int siglen) 139{ 140 struct listnode *item; 141 struct adb_public_key *key; 142 struct listnode key_list; 143 int ret = 0; 144 145 if (siglen != RSANUMBYTES) 146 return 0; 147 148 load_keys(&key_list); 149 150 list_for_each(item, &key_list) { 151 key = node_to_item(item, struct adb_public_key, node); 152 ret = RSA_verify(&key->key, sig, siglen, token); 153 if (ret) 154 break; 155 } 156 157 free_keys(&key_list); 158 159 return ret; 160} 161 162static void usb_disconnected(void* unused, atransport* t) 163{ 164 D("USB disconnect"); 165 remove_transport_disconnect(usb_transport, &usb_disconnect); 166 usb_transport = NULL; 167 needs_retry = false; 168} 169 170static void adb_auth_event(int fd, unsigned events, void *data) 171{ 172 char response[2]; 173 int ret; 174 175 if (events & FDE_READ) { 176 ret = unix_read(fd, response, sizeof(response)); 177 if (ret < 0) { 178 D("Framework disconnect"); 179 if (usb_transport) 180 fdevent_remove(&usb_transport->auth_fde); 181 framework_fd = -1; 182 } 183 else if (ret == 2 && response[0] == 'O' && response[1] == 'K') { 184 if (usb_transport) 185 adb_auth_verified(usb_transport); 186 } 187 } 188} 189 190void adb_auth_confirm_key(unsigned char *key, size_t len, atransport *t) 191{ 192 char msg[MAX_PAYLOAD]; 193 int ret; 194 195 usb_transport = t; 196 add_transport_disconnect(t, &usb_disconnect); 197 198 if (framework_fd < 0) { 199 D("Client not connected\n"); 200 needs_retry = true; 201 return; 202 } 203 204 if (key[len - 1] != '\0') { 205 D("Key must be a null-terminated string\n"); 206 return; 207 } 208 209 ret = snprintf(msg, sizeof(msg), "PK%s", key); 210 if (ret >= (signed)sizeof(msg)) { 211 D("Key too long. ret=%d", ret); 212 return; 213 } 214 D("Sending '%s'\n", msg); 215 216 ret = unix_write(framework_fd, msg, ret); 217 if (ret < 0) { 218 D("Failed to write PK, errno=%d\n", errno); 219 return; 220 } 221 222 fdevent_install(&t->auth_fde, framework_fd, adb_auth_event, t); 223 fdevent_add(&t->auth_fde, FDE_READ); 224} 225 226static void adb_auth_listener(int fd, unsigned events, void *data) 227{ 228 struct sockaddr addr; 229 socklen_t alen; 230 int s; 231 232 alen = sizeof(addr); 233 234 s = adb_socket_accept(fd, &addr, &alen); 235 if (s < 0) { 236 D("Failed to accept: errno=%d\n", errno); 237 return; 238 } 239 240 framework_fd = s; 241 242 if (needs_retry) { 243 needs_retry = false; 244 send_auth_request(usb_transport); 245 } 246} 247 248void adb_auth_init(void) 249{ 250 int fd, ret; 251 252 fd = android_get_control_socket("adbd"); 253 if (fd < 0) { 254 D("Failed to get adbd socket\n"); 255 return; 256 } 257 258 ret = listen(fd, 4); 259 if (ret < 0) { 260 D("Failed to listen on '%d'\n", fd); 261 return; 262 } 263 264 fdevent_install(&listener_fde, fd, adb_auth_listener, NULL); 265 fdevent_add(&listener_fde, FDE_READ); 266} 267