1d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby/* 2d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * Copyright (C) 2012 The Android Open Source Project 3d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * 4d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * Licensed under the Apache License, Version 2.0 (the "License"); 5d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * you may not use this file except in compliance with the License. 6d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * You may obtain a copy of the License at 7d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * 8d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * http://www.apache.org/licenses/LICENSE-2.0 9d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * 10d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * Unless required by applicable law or agreed to in writing, software 11d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * distributed under the License is distributed on an "AS IS" BASIS, 12d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * See the License for the specific language governing permissions and 14d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * limitations under the License. 15d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby */ 16d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 17d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include <stdio.h> 18d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include <string.h> 19d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include <resolv.h> 20d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include <cutils/list.h> 21d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include <cutils/sockets.h> 22d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 23d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include "sysdeps.h" 24d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include "adb.h" 25d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include "adb_auth.h" 26d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include "fdevent.h" 27d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include "mincrypt/rsa.h" 28d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 29d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#define TRACE_TAG TRACE_AUTH 30d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 31d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 32d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobystruct adb_public_key { 33d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby struct listnode node; 34d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby RSAPublicKey key; 35d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby}; 36d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 37d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobystatic struct listnode key_list; 38d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 39d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobystatic char *key_paths[] = { 40d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby "/adb_keys", 41d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby "/data/misc/adb/adb_keys", 42d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby NULL 43d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby}; 44d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 45d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobystatic fdevent listener_fde; 46d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobystatic int framework_fd = -1; 47d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 48d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 49d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobystatic void read_keys(const char *file, struct listnode *list) 50d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby{ 51d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby struct adb_public_key *key; 52d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby FILE *f; 53d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby char buf[MAX_PAYLOAD]; 54d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby char *sep; 55d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby int ret; 56d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 57d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby f = fopen(file, "r"); 58d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (!f) { 59d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("Can't open '%s'\n", file); 60d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby return; 61d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 62d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 63d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby while (fgets(buf, sizeof(buf), f)) { 64d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby /* Allocate 4 extra bytes to decode the base64 data in-place */ 65d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby key = calloc(1, sizeof(*key) + 4); 66d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (!key) { 67d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("Can't malloc key\n"); 68d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby break; 69d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 70d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 71d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby sep = strpbrk(buf, " \t"); 72d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (sep) 73d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby *sep = '\0'; 74d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 75d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby ret = __b64_pton(buf, (u_char *)&key->key, sizeof(key->key) + 4); 76d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (ret != sizeof(key->key)) { 77d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("%s: Invalid base64 data ret=%d\n", file, ret); 78d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby free(key); 79d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby continue; 80d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 81d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 82d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (key->key.len != RSANUMWORDS) { 83d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("%s: Invalid key len %d\n", file, key->key.len); 84d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby free(key); 85d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby continue; 86d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 87d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 88d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby list_add_tail(list, &key->node); 89d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 90d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 91d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby fclose(f); 92d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby} 93d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 94d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobystatic void free_keys(struct listnode *list) 95d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby{ 96d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby struct listnode *item; 97d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 98d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby while (!list_empty(list)) { 99d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby item = list_head(list); 100d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby list_remove(item); 101d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby free(node_to_item(item, struct adb_public_key, node)); 102d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 103d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby} 104d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 105d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobyvoid adb_auth_reload_keys(void) 106d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby{ 107d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby char *path; 108d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby char **paths = key_paths; 109d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby struct stat buf; 110d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 111d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby free_keys(&key_list); 112d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 113d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby while ((path = *paths++)) { 114d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (!stat(path, &buf)) { 115d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("Loading keys from '%s'\n", path); 116d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby read_keys(path, &key_list); 117d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 118d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 119d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby} 120d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 121d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobyint adb_auth_generate_token(void *token, size_t token_size) 122d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby{ 123d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby FILE *f; 124d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby int ret; 125d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 126d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby f = fopen("/dev/urandom", "r"); 127d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (!f) 128d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby return 0; 129d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 130d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby ret = fread(token, token_size, 1, f); 131d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 132d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby fclose(f); 133d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby return ret * token_size; 134d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby} 135d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 136d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobyint adb_auth_verify(void *token, void *sig, int siglen) 137d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby{ 138d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby struct listnode *item; 139d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby struct adb_public_key *key; 140d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby int ret; 141d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 142d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (siglen != RSANUMBYTES) 143d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby return 0; 144d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 145d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby list_for_each(item, &key_list) { 146d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby key = node_to_item(item, struct adb_public_key, node); 147d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby ret = RSA_verify(&key->key, sig, siglen, token); 148d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (ret) 149d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby return 1; 150d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 151d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 152d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby return 0; 153d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby} 154d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 155d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobystatic void adb_auth_event(int fd, unsigned events, void *data) 156d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby{ 157d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby atransport *t = data; 158d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby char response[2]; 159d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby int ret; 160d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 161d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (events & FDE_READ) { 162d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby ret = unix_read(fd, response, sizeof(response)); 163d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (ret < 0) { 164d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("Disconnect"); 165d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby fdevent_remove(&t->auth_fde); 166d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby framework_fd = -1; 167d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 168d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby else if (ret == 2 && response[0] == 'O' && response[1] == 'K') { 169d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby adb_auth_reload_keys(); 170d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby adb_auth_verified(t); 171d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 172d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 173d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby} 174d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 175d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobyvoid adb_auth_confirm_key(unsigned char *key, size_t len, atransport *t) 176d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby{ 177d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby char msg[MAX_PAYLOAD]; 178d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby int ret; 179d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 180d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (framework_fd < 0) { 181d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("Client not connected\n"); 182d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby return; 183d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 184d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 185d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (key[len - 1] != '\0') { 186d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("Key must be a null-terminated string\n"); 187d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby return; 188d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 189d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 190d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby ret = snprintf(msg, sizeof(msg), "PK%s", key); 191d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (ret >= (signed)sizeof(msg)) { 192d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("Key too long. ret=%d", ret); 193d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby return; 194d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 195d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("Sending '%s'\n", msg); 196d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 197d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby ret = unix_write(framework_fd, msg, ret); 198d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (ret < 0) { 199d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("Failed to write PK, errno=%d\n", errno); 200d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby return; 201d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 202d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 203d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby fdevent_install(&t->auth_fde, framework_fd, adb_auth_event, t); 204d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby fdevent_add(&t->auth_fde, FDE_READ); 205d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby} 206d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 207d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobystatic void adb_auth_listener(int fd, unsigned events, void *data) 208d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby{ 209d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby struct sockaddr addr; 210d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby socklen_t alen; 211d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby int s; 212d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 213d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby alen = sizeof(addr); 214d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 215d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby s = adb_socket_accept(fd, &addr, &alen); 216d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (s < 0) { 217d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("Failed to accept: errno=%d\n", errno); 218d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby return; 219d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 220d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 221d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby framework_fd = s; 222d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby} 223d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 224d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobyvoid adb_auth_init(void) 225d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby{ 226d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby int fd, ret; 227d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 228d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby list_init(&key_list); 229d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby adb_auth_reload_keys(); 230d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 231d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby fd = android_get_control_socket("adbd"); 232d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (fd < 0) { 233d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("Failed to get adbd socket\n"); 234d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby return; 235d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 236d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 237d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby ret = listen(fd, 4); 238d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (ret < 0) { 239d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("Failed to listen on '%d'\n", fd); 240d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby return; 241d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 242d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 243d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby fdevent_install(&listener_fde, fd, adb_auth_listener, NULL); 244d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby fdevent_add(&listener_fde, FDE_READ); 245d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby} 246