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