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