adb_auth_client.c revision 345cb066d2e0c774c877a85d3035f298df1daf16
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 char *key_paths[] = { 38d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby "/adb_keys", 39d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby "/data/misc/adb/adb_keys", 40d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby NULL 41d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby}; 42d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 43d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobystatic fdevent listener_fde; 44d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobystatic int framework_fd = -1; 45d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 46d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 47d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobystatic void read_keys(const char *file, struct listnode *list) 48d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby{ 49d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby struct adb_public_key *key; 50d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby FILE *f; 51d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby char buf[MAX_PAYLOAD]; 52d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby char *sep; 53d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby int ret; 54d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 55d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby f = fopen(file, "r"); 56d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (!f) { 57d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("Can't open '%s'\n", file); 58d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby return; 59d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 60d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 61d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby while (fgets(buf, sizeof(buf), f)) { 62d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby /* Allocate 4 extra bytes to decode the base64 data in-place */ 63d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby key = calloc(1, sizeof(*key) + 4); 64d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (!key) { 65d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("Can't malloc key\n"); 66d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby break; 67d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 68d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 69d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby sep = strpbrk(buf, " \t"); 70d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (sep) 71d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby *sep = '\0'; 72d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 73d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby ret = __b64_pton(buf, (u_char *)&key->key, sizeof(key->key) + 4); 74d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (ret != sizeof(key->key)) { 75d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("%s: Invalid base64 data ret=%d\n", file, ret); 76d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby free(key); 77d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby continue; 78d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 79d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 80d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (key->key.len != RSANUMWORDS) { 81d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("%s: Invalid key len %d\n", file, key->key.len); 82d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby free(key); 83d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby continue; 84d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 85d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 86d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby list_add_tail(list, &key->node); 87d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 88d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 89d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby fclose(f); 90d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby} 91d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 92d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobystatic void free_keys(struct listnode *list) 93d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby{ 94d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby struct listnode *item; 95d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 96d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby while (!list_empty(list)) { 97d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby item = list_head(list); 98d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby list_remove(item); 99d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby free(node_to_item(item, struct adb_public_key, node)); 100d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 101d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby} 102d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 103345cb066d2e0c774c877a85d3035f298df1daf16Benoit Gobystatic void load_keys(struct listnode *list) 104d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby{ 105d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby char *path; 106d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby char **paths = key_paths; 107d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby struct stat buf; 108d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 109345cb066d2e0c774c877a85d3035f298df1daf16Benoit Goby list_init(list); 110d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 111d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby while ((path = *paths++)) { 112d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (!stat(path, &buf)) { 113d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("Loading keys from '%s'\n", path); 114345cb066d2e0c774c877a85d3035f298df1daf16Benoit Goby read_keys(path, list); 115d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 116d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 117d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby} 118d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 119d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobyint adb_auth_generate_token(void *token, size_t token_size) 120d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby{ 121d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby FILE *f; 122d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby int ret; 123d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 124d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby f = fopen("/dev/urandom", "r"); 125d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (!f) 126d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby return 0; 127d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 128d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby ret = fread(token, token_size, 1, f); 129d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 130d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby fclose(f); 131d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby return ret * token_size; 132d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby} 133d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 134d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobyint adb_auth_verify(void *token, void *sig, int siglen) 135d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby{ 136d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby struct listnode *item; 137d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby struct adb_public_key *key; 138345cb066d2e0c774c877a85d3035f298df1daf16Benoit Goby struct listnode key_list; 139345cb066d2e0c774c877a85d3035f298df1daf16Benoit Goby int ret = 0; 140d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 141d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (siglen != RSANUMBYTES) 142d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby return 0; 143d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 144345cb066d2e0c774c877a85d3035f298df1daf16Benoit Goby load_keys(&key_list); 145345cb066d2e0c774c877a85d3035f298df1daf16Benoit Goby 146d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby list_for_each(item, &key_list) { 147d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby key = node_to_item(item, struct adb_public_key, node); 148d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby ret = RSA_verify(&key->key, sig, siglen, token); 149d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (ret) 150345cb066d2e0c774c877a85d3035f298df1daf16Benoit Goby break; 151d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 152d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 153345cb066d2e0c774c877a85d3035f298df1daf16Benoit Goby free_keys(&key_list); 154345cb066d2e0c774c877a85d3035f298df1daf16Benoit Goby 155345cb066d2e0c774c877a85d3035f298df1daf16Benoit Goby return ret; 156d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby} 157d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 158d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobystatic void adb_auth_event(int fd, unsigned events, void *data) 159d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby{ 160d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby atransport *t = data; 161d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby char response[2]; 162d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby int ret; 163d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 164d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (events & FDE_READ) { 165d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby ret = unix_read(fd, response, sizeof(response)); 166d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (ret < 0) { 167d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("Disconnect"); 168d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby fdevent_remove(&t->auth_fde); 169d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby framework_fd = -1; 170d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 171d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby else if (ret == 2 && response[0] == 'O' && response[1] == 'K') { 172d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby adb_auth_verified(t); 173d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 174d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 175d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby} 176d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 177d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobyvoid adb_auth_confirm_key(unsigned char *key, size_t len, atransport *t) 178d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby{ 179d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby char msg[MAX_PAYLOAD]; 180d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby int ret; 181d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 182d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (framework_fd < 0) { 183d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("Client not connected\n"); 184d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby return; 185d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 186d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 187d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (key[len - 1] != '\0') { 188d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("Key must be a null-terminated string\n"); 189d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby return; 190d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 191d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 192d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby ret = snprintf(msg, sizeof(msg), "PK%s", key); 193d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (ret >= (signed)sizeof(msg)) { 194d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("Key too long. ret=%d", ret); 195d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby return; 196d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 197d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("Sending '%s'\n", msg); 198d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 199d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby ret = unix_write(framework_fd, msg, ret); 200d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (ret < 0) { 201d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("Failed to write PK, errno=%d\n", errno); 202d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby return; 203d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 204d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 205d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby fdevent_install(&t->auth_fde, framework_fd, adb_auth_event, t); 206d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby fdevent_add(&t->auth_fde, FDE_READ); 207d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby} 208d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 209d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobystatic void adb_auth_listener(int fd, unsigned events, void *data) 210d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby{ 211d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby struct sockaddr addr; 212d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby socklen_t alen; 213d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby int s; 214d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 215d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby alen = sizeof(addr); 216d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 217d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby s = adb_socket_accept(fd, &addr, &alen); 218d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (s < 0) { 219d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("Failed to accept: errno=%d\n", errno); 220d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby return; 221d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 222d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 223d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby framework_fd = s; 224d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby} 225d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 226d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobyvoid adb_auth_init(void) 227d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby{ 228d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby int fd, ret; 229d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 230d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby fd = android_get_control_socket("adbd"); 231d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (fd < 0) { 232d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("Failed to get adbd socket\n"); 233d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby return; 234d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 235d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 236d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby ret = listen(fd, 4); 237d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby if (ret < 0) { 238d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby D("Failed to listen on '%d'\n", fd); 239d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby return; 240d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby } 241d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby 242d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby fdevent_install(&listener_fde, fd, adb_auth_listener, NULL); 243d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby fdevent_add(&listener_fde, FDE_READ); 244d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby} 245