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