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