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 #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 
     32 struct adb_public_key {
     33     struct listnode node;
     34     RSAPublicKey key;
     35 };
     36 
     37 static char *key_paths[] = {
     38     "/adb_keys",
     39     "/data/misc/adb/adb_keys",
     40     NULL
     41 };
     42 
     43 static fdevent listener_fde;
     44 static int framework_fd = -1;
     45 
     46 static void usb_disconnected(void* unused, atransport* t);
     47 static struct adisconnect usb_disconnect = { usb_disconnected, 0, 0, 0 };
     48 static atransport* usb_transport;
     49 static bool needs_retry = false;
     50 
     51 static 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 
     96 static 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 
    107 static 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 
    123 int 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 
    138 int 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 
    162 static void usb_disconnected(void* unused, atransport* t)
    163 {
    164     D("USB disconnect\n");
    165     remove_transport_disconnect(usb_transport, &usb_disconnect);
    166     usb_transport = NULL;
    167     needs_retry = false;
    168 }
    169 
    170 static 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\n");
    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 
    190 void adb_auth_confirm_key(unsigned char *key, size_t len, atransport *t)
    191 {
    192     char msg[MAX_PAYLOAD];
    193     int ret;
    194 
    195     if (!usb_transport) {
    196         usb_transport = t;
    197         add_transport_disconnect(t, &usb_disconnect);
    198     }
    199 
    200     if (framework_fd < 0) {
    201         D("Client not connected\n");
    202         needs_retry = true;
    203         return;
    204     }
    205 
    206     if (key[len - 1] != '\0') {
    207         D("Key must be a null-terminated string\n");
    208         return;
    209     }
    210 
    211     ret = snprintf(msg, sizeof(msg), "PK%s", key);
    212     if (ret >= (signed)sizeof(msg)) {
    213         D("Key too long. ret=%d", ret);
    214         return;
    215     }
    216     D("Sending '%s'\n", msg);
    217 
    218     ret = unix_write(framework_fd, msg, ret);
    219     if (ret < 0) {
    220         D("Failed to write PK, errno=%d\n", errno);
    221         return;
    222     }
    223 
    224     fdevent_install(&t->auth_fde, framework_fd, adb_auth_event, t);
    225     fdevent_add(&t->auth_fde, FDE_READ);
    226 }
    227 
    228 static void adb_auth_listener(int fd, unsigned events, void *data)
    229 {
    230     struct sockaddr addr;
    231     socklen_t alen;
    232     int s;
    233 
    234     alen = sizeof(addr);
    235 
    236     s = adb_socket_accept(fd, &addr, &alen);
    237     if (s < 0) {
    238         D("Failed to accept: errno=%d\n", errno);
    239         return;
    240     }
    241 
    242     framework_fd = s;
    243 
    244     if (needs_retry) {
    245         needs_retry = false;
    246         send_auth_request(usb_transport);
    247     }
    248 }
    249 
    250 void adb_auth_init(void)
    251 {
    252     int fd, ret;
    253 
    254     fd = android_get_control_socket("adbd");
    255     if (fd < 0) {
    256         D("Failed to get adbd socket\n");
    257         return;
    258     }
    259 
    260     ret = listen(fd, 4);
    261     if (ret < 0) {
    262         D("Failed to listen on '%d'\n", fd);
    263         return;
    264     }
    265 
    266     fdevent_install(&listener_fde, fd, adb_auth_listener, NULL);
    267     fdevent_add(&listener_fde, FDE_READ);
    268 }
    269