OSDN Git Service

File header cleanup.
[android-x86/system-core.git] / adb / adb_auth_client.cpp
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 }