Merge "Clean up key handling in adb." am: b859830450

am: 81a3f71e45

Change-Id: I7013113e72eefd68a9329d0da72a45946d860e14
This commit is contained in:
Josh Gao 2016-08-12 21:25:22 +00:00 committed by android-build-merger
commit f648fb4539
9 changed files with 237 additions and 340 deletions

View file

@ -354,21 +354,13 @@ void handle_packet(apacket *p, atransport *t)
case A_AUTH: case A_AUTH:
if (p->msg.arg0 == ADB_AUTH_TOKEN) { if (p->msg.arg0 == ADB_AUTH_TOKEN) {
t->connection_state = kCsUnauthorized; t->connection_state = kCsUnauthorized;
t->key = adb_auth_nextkey(t->key); send_auth_response(p->data, p->msg.data_length, t);
if (t->key) {
send_auth_response(p->data, p->msg.data_length, t);
} else {
/* No more private keys to try, send the public key */
send_auth_publickey(t);
}
} else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) { } else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) {
if (adb_auth_verify(t->token, sizeof(t->token), if (adb_auth_verify(t->token, sizeof(t->token), p->data, p->msg.data_length)) {
p->data, p->msg.data_length)) {
adb_auth_verified(t); adb_auth_verified(t);
t->failed_auth_attempts = 0; t->failed_auth_attempts = 0;
} else { } else {
if (t->failed_auth_attempts++ > 10) if (t->failed_auth_attempts++ > 10) adb_sleep_ms(1000);
adb_sleep_ms(1000);
send_auth_request(t); send_auth_request(t);
} }
} else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) { } else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) {

View file

@ -16,8 +16,9 @@
#define TRACE_TAG ADB #define TRACE_TAG ADB
#include "sysdeps.h" #include "adb.h"
#include "adb_auth.h" #include "adb_auth.h"
#include "transport.h"
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
@ -25,53 +26,28 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include "adb.h"
#include "transport.h"
bool auth_required = true; bool auth_required = true;
void send_auth_request(atransport *t) void send_auth_request(atransport *t)
{ {
D("Calling send_auth_request"); LOG(INFO) << "Calling send_auth_request...";
apacket *p;
int ret;
ret = adb_auth_generate_token(t->token, sizeof(t->token)); if (!adb_auth_generate_token(t->token, sizeof(t->token))) {
if (ret != sizeof(t->token)) { PLOG(ERROR) << "Error generating token";
D("Error generating token ret=%d", ret);
return; return;
} }
p = get_apacket(); apacket* p = get_apacket();
memcpy(p->data, t->token, ret); memcpy(p->data, t->token, sizeof(t->token));
p->msg.command = A_AUTH; p->msg.command = A_AUTH;
p->msg.arg0 = ADB_AUTH_TOKEN; p->msg.arg0 = ADB_AUTH_TOKEN;
p->msg.data_length = ret; p->msg.data_length = sizeof(t->token);
send_packet(p, t); send_packet(p, t);
} }
void send_auth_response(uint8_t *token, size_t token_size, atransport *t) static void send_auth_publickey(atransport* t) {
{ LOG(INFO) << "Calling send_auth_publickey";
D("Calling send_auth_response");
apacket *p = get_apacket();
int ret;
ret = adb_auth_sign(t->key, token, token_size, p->data);
if (!ret) {
D("Error signing the token");
put_apacket(p);
return;
}
p->msg.command = A_AUTH;
p->msg.arg0 = ADB_AUTH_SIGNATURE;
p->msg.data_length = ret;
send_packet(p, t);
}
void send_auth_publickey(atransport *t)
{
D("Calling send_auth_publickey");
std::string key = adb_auth_get_userkey(); std::string key = adb_auth_get_userkey();
if (key.empty()) { if (key.empty()) {
D("Failed to get user public key"); D("Failed to get user public key");
@ -92,6 +68,35 @@ void send_auth_publickey(atransport *t)
send_packet(p, t); send_packet(p, t);
} }
void send_auth_response(uint8_t* token, size_t token_size, atransport* t) {
RSA* key = t->NextKey();
if (key == nullptr) {
// No more private keys to try, send the public key.
send_auth_publickey(t);
return;
}
LOG(INFO) << "Calling send_auth_response";
apacket* p = get_apacket();
int ret = adb_auth_sign(key, token, token_size, p->data);
// Stop sharing this key.
RSA_free(key);
key = nullptr;
if (!ret) {
D("Error signing the token");
put_apacket(p);
return;
}
p->msg.command = A_AUTH;
p->msg.arg0 = ADB_AUTH_SIGNATURE;
p->msg.data_length = ret;
send_packet(p, t);
}
void adb_auth_verified(atransport *t) void adb_auth_verified(atransport *t)
{ {
handle_online(t); handle_online(t);

View file

@ -19,6 +19,10 @@
#include "adb.h" #include "adb.h"
#include <deque>
#include <openssl/rsa.h>
extern bool auth_required; extern bool auth_required;
int adb_auth_keygen(const char* filename); int adb_auth_keygen(const char* filename);
@ -26,7 +30,6 @@ void adb_auth_verified(atransport *t);
void send_auth_request(atransport *t); void send_auth_request(atransport *t);
void send_auth_response(uint8_t *token, size_t token_size, atransport *t); void send_auth_response(uint8_t *token, size_t token_size, atransport *t);
void send_auth_publickey(atransport *t);
/* AUTH packets first argument */ /* AUTH packets first argument */
/* Request */ /* Request */
@ -37,36 +40,25 @@ void send_auth_publickey(atransport *t);
#if ADB_HOST #if ADB_HOST
void adb_auth_init(void); void adb_auth_init();
int adb_auth_sign(void *key, const unsigned char* token, size_t token_size, int adb_auth_sign(RSA* key, const unsigned char* token, size_t token_size, unsigned char* sig);
unsigned char* sig);
void *adb_auth_nextkey(void *current);
std::string adb_auth_get_userkey(); std::string adb_auth_get_userkey();
std::deque<RSA*> adb_auth_get_private_keys();
static inline int adb_auth_generate_token(void *token, size_t token_size) { static inline bool adb_auth_generate_token(void*, size_t) { abort(); }
return 0; static inline bool adb_auth_verify(void*, size_t, void*, int) { abort(); }
} static inline void adb_auth_confirm_key(unsigned char*, size_t, atransport*) { abort(); }
static inline int adb_auth_verify(void *token, size_t token_size,
void *sig, int siglen) {
return 0;
}
static inline void adb_auth_confirm_key(unsigned char *data, size_t len,
atransport *t) {}
#else // !ADB_HOST #else // !ADB_HOST
static inline int adb_auth_sign(void* key, const unsigned char* token, static inline int adb_auth_sign(void*, const unsigned char*, size_t, unsigned char*) { abort(); }
size_t token_size, unsigned char* sig) { static inline std::string adb_auth_get_userkey() { abort(); }
return 0; static inline std::deque<RSA*> adb_auth_get_private_keys() { abort(); }
}
static inline void *adb_auth_nextkey(void *current) { return NULL; }
static inline std::string adb_auth_get_userkey() { return ""; }
void adbd_auth_init(void); void adbd_auth_init(void);
void adbd_cloexec_auth_socket(); void adbd_cloexec_auth_socket();
int adb_auth_generate_token(void *token, size_t token_size); bool adb_auth_generate_token(void* token, size_t token_size);
int adb_auth_verify(uint8_t* token, size_t token_size, bool adb_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int sig_len);
uint8_t* sig, int siglen);
void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t); void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t);
#endif // ADB_HOST #endif // ADB_HOST

View file

@ -16,37 +16,25 @@
#define TRACE_TAG AUTH #define TRACE_TAG AUTH
#include "sysdeps.h" #include "adb.h"
#include "adb_auth.h" #include "adb_auth.h"
#include "fdevent.h"
#include "sysdeps.h"
#include "transport.h"
#include <resolv.h> #include <resolv.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <memory>
#include <android-base/file.h>
#include <android-base/strings.h>
#include <crypto_utils/android_pubkey.h>
#include <openssl/obj_mac.h> #include <openssl/obj_mac.h>
#include <openssl/rsa.h> #include <openssl/rsa.h>
#include <openssl/sha.h> #include <openssl/sha.h>
#include <crypto_utils/android_pubkey.h>
#include "cutils/list.h"
#include "cutils/sockets.h"
#include "adb.h"
#include "fdevent.h"
#include "transport.h"
struct adb_public_key {
struct listnode node;
RSA* key;
};
static const char *key_paths[] = {
"/adb_keys",
"/data/misc/adb/adb_keys",
NULL
};
static fdevent listener_fde; static fdevent listener_fde;
static fdevent framework_fde; static fdevent framework_fde;
static int framework_fd = -1; static int framework_fd = -1;
@ -56,135 +44,71 @@ static struct adisconnect usb_disconnect = { usb_disconnected, nullptr};
static atransport* usb_transport; static atransport* usb_transport;
static bool needs_retry = false; static bool needs_retry = false;
static void read_keys(const char *file, struct listnode *list) bool adb_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int sig_len) {
{ static constexpr const char* key_paths[] = { "/adb_keys", "/data/misc/adb/adb_keys", nullptr };
FILE *f;
char buf[MAX_PAYLOAD_V1];
char *sep;
int ret;
f = fopen(file, "re"); for (const auto& path : key_paths) {
if (!f) { if (access(path, R_OK) == 0) {
D("Can't open '%s'", file); LOG(INFO) << "Loading keys from " << path;
return;
}
while (fgets(buf, sizeof(buf), f)) { std::string content;
auto key = reinterpret_cast<adb_public_key*>( if (!android::base::ReadFileToString(path, &content)) {
calloc(1, sizeof(adb_public_key))); PLOG(ERROR) << "Couldn't read " << path;
if (key == nullptr) { continue;
D("Can't malloc key"); }
break;
}
sep = strpbrk(buf, " \t"); for (const auto& line : android::base::Split(content, "\n")) {
if (sep) // TODO: do we really have to support both ' ' and '\t'?
*sep = '\0'; char* sep = strpbrk(const_cast<char*>(line.c_str()), " \t");
if (sep) *sep = '\0';
// b64_pton requires one additional byte in the target buffer for // b64_pton requires one additional byte in the target buffer for
// decoding to succeed. See http://b/28035006 for details. // decoding to succeed. See http://b/28035006 for details.
uint8_t keybuf[ANDROID_PUBKEY_ENCODED_SIZE + 1]; uint8_t keybuf[ANDROID_PUBKEY_ENCODED_SIZE + 1];
ret = __b64_pton(buf, keybuf, sizeof(keybuf)); if (__b64_pton(line.c_str(), keybuf, sizeof(keybuf)) != ANDROID_PUBKEY_ENCODED_SIZE) {
if (ret != ANDROID_PUBKEY_ENCODED_SIZE) { LOG(ERROR) << "Invalid base64 key " << line.c_str() << " in " << path;
D("%s: Invalid base64 data ret=%d", file, ret); continue;
free(key); }
continue;
}
if (!android_pubkey_decode(keybuf, ret, &key->key)) { RSA* key = nullptr;
D("%s: Failed to parse key", file); if (!android_pubkey_decode(keybuf, ANDROID_PUBKEY_ENCODED_SIZE, &key)) {
free(key); LOG(ERROR) << "Failed to parse key " << line.c_str() << " in " << path;
continue; continue;
} }
list_add_tail(list, &key->node); bool verified = (RSA_verify(NID_sha1, token, token_size, sig, sig_len, key) == 1);
} RSA_free(key);
if (verified) return true;
fclose(f); }
}
static void free_keys(struct listnode *list)
{
struct listnode *item;
while (!list_empty(list)) {
item = list_head(list);
list_remove(item);
adb_public_key* key = node_to_item(item, struct adb_public_key, node);
RSA_free(key->key);
free(key);
}
}
static void load_keys(struct listnode *list)
{
const char* path;
const char** paths = key_paths;
struct stat buf;
list_init(list);
while ((path = *paths++)) {
if (!stat(path, &buf)) {
D("Loading keys from '%s'", path);
read_keys(path, list);
} }
} }
return false;
} }
int adb_auth_generate_token(void *token, size_t token_size) bool adb_auth_generate_token(void* token, size_t token_size) {
{ FILE* fp = fopen("/dev/urandom", "re");
FILE *f; if (!fp) return false;
int ret; bool okay = (fread(token, token_size, 1, fp) == 1);
fclose(fp);
f = fopen("/dev/urandom", "re"); return okay;
if (!f)
return 0;
ret = fread(token, token_size, 1, f);
fclose(f);
return ret * token_size;
}
int adb_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int siglen)
{
struct listnode *item;
struct listnode key_list;
int ret = 0;
load_keys(&key_list);
list_for_each(item, &key_list) {
adb_public_key* key = node_to_item(item, struct adb_public_key, node);
ret = RSA_verify(NID_sha1, token, token_size, sig, siglen, key->key);
if (ret)
break;
}
free_keys(&key_list);
return ret;
} }
static void usb_disconnected(void* unused, atransport* t) { static void usb_disconnected(void* unused, atransport* t) {
D("USB disconnect"); LOG(INFO) << "USB disconnect";
usb_transport = NULL; usb_transport = NULL;
needs_retry = false; needs_retry = false;
} }
static void framework_disconnected() { static void framework_disconnected() {
D("Framework disconnect"); LOG(INFO) << "Framework disconnect";
fdevent_remove(&framework_fde); fdevent_remove(&framework_fde);
framework_fd = -1; framework_fd = -1;
} }
static void adb_auth_event(int fd, unsigned events, void*) { static void adb_auth_event(int fd, unsigned events, void*) {
char response[2];
int ret;
if (events & FDE_READ) { if (events & FDE_READ) {
ret = unix_read(fd, response, sizeof(response)); char response[2];
int ret = unix_read(fd, response, sizeof(response));
if (ret <= 0) { if (ret <= 0) {
framework_disconnected(); framework_disconnected();
} else if (ret == 2 && response[0] == 'O' && response[1] == 'K') { } else if (ret == 2 && response[0] == 'O' && response[1] == 'K') {
@ -195,51 +119,43 @@ static void adb_auth_event(int fd, unsigned events, void*) {
} }
} }
void adb_auth_confirm_key(unsigned char *key, size_t len, atransport *t) void adb_auth_confirm_key(unsigned char* key, size_t len, atransport* t) {
{
char msg[MAX_PAYLOAD_V1];
int ret;
if (!usb_transport) { if (!usb_transport) {
usb_transport = t; usb_transport = t;
t->AddDisconnect(&usb_disconnect); t->AddDisconnect(&usb_disconnect);
} }
if (framework_fd < 0) { if (framework_fd < 0) {
D("Client not connected"); LOG(ERROR) << "Client not connected";
needs_retry = true; needs_retry = true;
return; return;
} }
if (key[len - 1] != '\0') { if (key[len - 1] != '\0') {
D("Key must be a null-terminated string"); LOG(ERROR) << "Key must be a null-terminated string";
return; return;
} }
ret = snprintf(msg, sizeof(msg), "PK%s", key); char msg[MAX_PAYLOAD_V1];
if (ret >= (signed)sizeof(msg)) { int msg_len = snprintf(msg, sizeof(msg), "PK%s", key);
D("Key too long. ret=%d", ret); if (msg_len >= static_cast<int>(sizeof(msg))) {
LOG(ERROR) << "Key too long (" << msg_len << ")";
return; return;
} }
D("Sending '%s'", msg); LOG(DEBUG) << "Sending '" << msg << "'";
ret = unix_write(framework_fd, msg, ret); if (unix_write(framework_fd, msg, msg_len) == -1) {
if (ret < 0) { PLOG(ERROR) << "Failed to write PK";
D("Failed to write PK, errno=%d", errno);
return; return;
} }
} }
static void adb_auth_listener(int fd, unsigned events, void* data) { static void adb_auth_listener(int fd, unsigned events, void* data) {
sockaddr_storage addr; sockaddr_storage addr;
socklen_t alen; socklen_t alen = sizeof(addr);
int s; int s = adb_socket_accept(fd, reinterpret_cast<sockaddr*>(&addr), &alen);
alen = sizeof(addr);
s = adb_socket_accept(fd, reinterpret_cast<sockaddr*>(&addr), &alen);
if (s < 0) { if (s < 0) {
D("Failed to accept: errno=%d", errno); PLOG(ERROR) << "Failed to accept";
return; return;
} }
@ -261,7 +177,7 @@ static void adb_auth_listener(int fd, unsigned events, void* data) {
void adbd_cloexec_auth_socket() { void adbd_cloexec_auth_socket() {
int fd = android_get_control_socket("adbd"); int fd = android_get_control_socket("adbd");
if (fd == -1) { if (fd == -1) {
D("Failed to get adbd socket"); PLOG(ERROR) << "Failed to get adbd socket";
return; return;
} }
fcntl(fd, F_SETFD, FD_CLOEXEC); fcntl(fd, F_SETFD, FD_CLOEXEC);
@ -270,12 +186,12 @@ void adbd_cloexec_auth_socket() {
void adbd_auth_init(void) { void adbd_auth_init(void) {
int fd = android_get_control_socket("adbd"); int fd = android_get_control_socket("adbd");
if (fd == -1) { if (fd == -1) {
D("Failed to get adbd socket"); PLOG(ERROR) << "Failed to get adbd socket";
return; return;
} }
if (listen(fd, 4) == -1) { if (listen(fd, 4) == -1) {
D("Failed to listen on '%d'", fd); PLOG(ERROR) << "Failed to listen on '" << fd << "'";
return; return;
} }

View file

@ -16,23 +16,22 @@
#define TRACE_TAG AUTH #define TRACE_TAG AUTH
#include "sysdeps.h"
#include "adb_auth.h" #include "adb_auth.h"
#include "adb.h"
#include "adb_utils.h" #include "adb_utils.h"
#include "sysdeps.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "adb.h" #include <mutex>
#include <android-base/errors.h> #include <android-base/errors.h>
#include <android-base/file.h> #include <android-base/file.h>
#include <android-base/stringprintf.h> #include <android-base/stringprintf.h>
#include <android-base/strings.h> #include <android-base/strings.h>
#include <crypto_utils/android_pubkey.h> #include <crypto_utils/android_pubkey.h>
#include <cutils/list.h>
#include <openssl/base64.h> #include <openssl/base64.h>
#include <openssl/evp.h> #include <openssl/evp.h>
#include <openssl/objects.h> #include <openssl/objects.h>
@ -40,18 +39,14 @@
#include <openssl/rsa.h> #include <openssl/rsa.h>
#include <openssl/sha.h> #include <openssl/sha.h>
#define ANDROID_PATH ".android" #include "sysdeps/mutex.h"
#define ADB_KEY_FILE "adbkey"
struct adb_private_key {
struct listnode node;
RSA *rsa;
};
static struct listnode key_list;
static std::mutex& g_key_list_mutex = *new std::mutex;
static std::deque<RSA*>& g_key_list = *new std::deque<RSA*>;
static std::string get_user_info() { static std::string get_user_info() {
LOG(INFO) << "get_user_info...";
std::string hostname; std::string hostname;
if (getenv("HOSTNAME")) hostname = getenv("HOSTNAME"); if (getenv("HOSTNAME")) hostname = getenv("HOSTNAME");
#if !defined(_WIN32) #if !defined(_WIN32)
@ -71,6 +66,8 @@ static std::string get_user_info() {
} }
static bool write_public_keyfile(RSA* private_key, const std::string& private_key_path) { static bool write_public_keyfile(RSA* private_key, const std::string& private_key_path) {
LOG(INFO) << "write_public_keyfile...";
uint8_t binary_key_data[ANDROID_PUBKEY_ENCODED_SIZE]; uint8_t binary_key_data[ANDROID_PUBKEY_ENCODED_SIZE];
if (!android_pubkey_encode(private_key, binary_key_data, sizeof(binary_key_data))) { if (!android_pubkey_encode(private_key, binary_key_data, sizeof(binary_key_data))) {
LOG(ERROR) << "Failed to convert to public key"; LOG(ERROR) << "Failed to convert to public key";
@ -99,19 +96,18 @@ static bool write_public_keyfile(RSA* private_key, const std::string& private_ke
return true; return true;
} }
static int generate_key(const char *file) static int generate_key(const std::string& file) {
{ LOG(INFO) << "generate_key(" << file << ")...";
EVP_PKEY* pkey = EVP_PKEY_new();
BIGNUM* exponent = BN_new();
RSA* rsa = RSA_new();
mode_t old_mask; mode_t old_mask;
FILE *f = NULL; FILE *f = NULL;
int ret = 0; int ret = 0;
D("generate_key '%s'", file); EVP_PKEY* pkey = EVP_PKEY_new();
BIGNUM* exponent = BN_new();
RSA* rsa = RSA_new();
if (!pkey || !exponent || !rsa) { if (!pkey || !exponent || !rsa) {
D("Failed to allocate key"); LOG(ERROR) << "Failed to allocate key";
goto out; goto out;
} }
@ -121,9 +117,9 @@ static int generate_key(const char *file)
old_mask = umask(077); old_mask = umask(077);
f = fopen(file, "w"); f = fopen(file.c_str(), "w");
if (!f) { if (!f) {
D("Failed to open '%s'", file); PLOG(ERROR) << "Failed to open " << file;
umask(old_mask); umask(old_mask);
goto out; goto out;
} }
@ -143,110 +139,110 @@ static int generate_key(const char *file)
ret = 1; ret = 1;
out: out:
if (f) if (f) fclose(f);
fclose(f);
EVP_PKEY_free(pkey); EVP_PKEY_free(pkey);
RSA_free(rsa); RSA_free(rsa);
BN_free(exponent); BN_free(exponent);
return ret; return ret;
} }
static int read_key(const char *file, struct listnode *list) static bool read_key(const std::string& file) {
{ LOG(INFO) << "read_key '" << file << "'...";
D("read_key '%s'", file);
FILE* fp = fopen(file, "r"); std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(file.c_str(), "r"), fclose);
if (!fp) { if (!fp) {
D("Failed to open '%s': %s", file, strerror(errno)); PLOG(ERROR) << "Failed to open '" << file << "'";
return 0; return false;
} }
adb_private_key* key = new adb_private_key; RSA* key = RSA_new();
key->rsa = RSA_new(); if (!PEM_read_RSAPrivateKey(fp.get(), &key, nullptr, nullptr)) {
LOG(ERROR) << "Failed to read key";
if (!PEM_read_RSAPrivateKey(fp, &key->rsa, NULL, NULL)) { RSA_free(key);
D("Failed to read key"); return false;
fclose(fp);
RSA_free(key->rsa);
delete key;
return 0;
} }
fclose(fp); g_key_list.push_back(key);
list_add_tail(list, &key->node); return true;
return 1;
} }
static int get_user_keyfilepath(char *filename, size_t len) static std::string get_user_key_path() {
{
const std::string home = adb_get_homedir_path(true); const std::string home = adb_get_homedir_path(true);
D("home '%s'", home.c_str()); LOG(DEBUG) << "adb_get_homedir_path returned '" << home << "'";
const std::string android_dir = const std::string android_dir = android::base::StringPrintf("%s%c.android", home.c_str(),
android::base::StringPrintf("%s%c%s", home.c_str(), OS_PATH_SEPARATOR);
OS_PATH_SEPARATOR, ANDROID_PATH);
struct stat buf; struct stat buf;
if (stat(android_dir.c_str(), &buf)) { if (stat(android_dir.c_str(), &buf) == -1) {
if (adb_mkdir(android_dir.c_str(), 0750) < 0) { if (adb_mkdir(android_dir.c_str(), 0750) == -1) {
D("Cannot mkdir '%s'", android_dir.c_str()); PLOG(ERROR) << "Cannot mkdir '" << android_dir << "'";
return -1; return "";
} }
} }
return snprintf(filename, len, "%s%c%s", return android_dir + OS_PATH_SEPARATOR + "adbkey";
android_dir.c_str(), OS_PATH_SEPARATOR, ADB_KEY_FILE);
} }
static int get_user_key(struct listnode *list) static bool get_user_key() {
{ std::string path = get_user_key_path();
struct stat buf; if (path.empty()) {
char path[PATH_MAX]; PLOG(ERROR) << "Error getting user key filename";
int ret; return false;
ret = get_user_keyfilepath(path, sizeof(path));
if (ret < 0 || ret >= (signed)sizeof(path)) {
D("Error getting user key filename");
return 0;
} }
D("user key '%s'", path); struct stat buf;
if (stat(path.c_str(), &buf) == -1) {
if (stat(path, &buf) == -1) { LOG(INFO) << "User key '" << path << "' does not exist...";
if (!generate_key(path)) { if (!generate_key(path)) {
D("Failed to generate new key"); LOG(ERROR) << "Failed to generate new key";
return 0; return false;
} }
} }
return read_key(path, list); return read_key(path);
} }
static void get_vendor_keys(struct listnode* key_list) { static void get_vendor_keys() {
const char* adb_keys_path = getenv("ADB_VENDOR_KEYS"); const char* adb_keys_path = getenv("ADB_VENDOR_KEYS");
if (adb_keys_path == nullptr) { if (adb_keys_path == nullptr) {
return; return;
} }
for (const auto& path : android::base::Split(adb_keys_path, ENV_PATH_SEPARATOR_STR)) { for (const auto& path : android::base::Split(adb_keys_path, ENV_PATH_SEPARATOR_STR)) {
if (!read_key(path.c_str(), key_list)) { if (!read_key(path.c_str())) {
D("Failed to read '%s'", path.c_str()); PLOG(ERROR) << "Failed to read '" << path << "'";
} }
} }
} }
int adb_auth_sign(void *node, const unsigned char* token, size_t token_size, std::deque<RSA*> adb_auth_get_private_keys() {
unsigned char* sig) std::deque<RSA*> result;
{
unsigned int len;
struct adb_private_key *key = node_to_item(node, struct adb_private_key, node);
// Copy all the currently known keys, increasing their reference count so they're
// usable until both we and the caller have freed our pointers.
std::lock_guard<std::mutex> lock(g_key_list_mutex);
for (const auto& key : g_key_list) {
RSA_up_ref(key); // Since we're handing out another pointer to this key...
result.push_back(key);
}
// Add a sentinel to the list. Our caller uses this to mean "out of private keys,
// but try using the public key" (the empty deque could otherwise mean this _or_
// that this function hasn't been called yet to request the keys).
result.push_back(nullptr);
return result;
}
int adb_auth_sign(RSA* key, const unsigned char* token, size_t token_size, unsigned char* sig) {
if (token_size != TOKEN_SIZE) { if (token_size != TOKEN_SIZE) {
D("Unexpected token size %zd", token_size); D("Unexpected token size %zd", token_size);
return 0; return 0;
} }
if (!RSA_sign(NID_sha1, token, token_size, sig, &len, key->rsa)) { unsigned int len;
if (!RSA_sign(NID_sha1, token, token_size, sig, &len, key)) {
return 0; return 0;
} }
@ -254,40 +250,17 @@ int adb_auth_sign(void *node, const unsigned char* token, size_t token_size,
return (int)len; return (int)len;
} }
void *adb_auth_nextkey(void *current)
{
struct listnode *item;
if (list_empty(&key_list))
return NULL;
if (!current)
return list_head(&key_list);
list_for_each(item, &key_list) {
if (item == current) {
/* current is the last item, we tried all the keys */
if (item->next == &key_list)
return NULL;
return item->next;
}
}
return NULL;
}
std::string adb_auth_get_userkey() { std::string adb_auth_get_userkey() {
char path[PATH_MAX]; std::string path = get_user_key_path();
int ret = get_user_keyfilepath(path, sizeof(path) - 4); if (path.empty()) {
if (ret < 0 || ret >= (signed)(sizeof(path) - 4)) { PLOG(ERROR) << "Error getting user key filename";
D("Error getting user key filename");
return ""; return "";
} }
strcat(path, ".pub"); path += ".pub";
std::string content; std::string content;
if (!android::base::ReadFileToString(path, &content)) { if (!android::base::ReadFileToString(path, &content)) {
D("Can't load '%s'", path); PLOG(ERROR) << "Can't load '" << path << "'";
return ""; return "";
} }
return content; return content;
@ -297,19 +270,14 @@ int adb_auth_keygen(const char* filename) {
return (generate_key(filename) == 0); return (generate_key(filename) == 0);
} }
void adb_auth_init(void) void adb_auth_init() {
{ LOG(INFO) << "adb_auth_init...";
int ret;
D("adb_auth_init"); if (!get_user_key()) {
LOG(ERROR) << "Failed to get user key";
list_init(&key_list);
ret = get_user_key(&key_list);
if (!ret) {
D("Failed to get user key");
return; return;
} }
get_vendor_keys(&key_list); std::lock_guard<std::mutex> lock(g_key_list_mutex);
get_vendor_keys();
} }

View file

@ -110,7 +110,6 @@ int adb_server_main(int is_daemon, int server_port, int ack_reply_fd) {
usb_init(); usb_init();
local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT); local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
adb_auth_init();
std::string error; std::string error;
std::string local_name = android::base::StringPrintf("tcp:%d", server_port); std::string local_name = android::base::StringPrintf("tcp:%d", server_port);
@ -118,11 +117,14 @@ int adb_server_main(int is_daemon, int server_port, int ack_reply_fd) {
fatal("could not install *smartsocket* listener: %s", error.c_str()); fatal("could not install *smartsocket* listener: %s", error.c_str());
} }
// Inform our parent that we are up and running.
if (is_daemon) { if (is_daemon) {
close_stdin(); close_stdin();
setup_daemon_logging(); setup_daemon_logging();
}
adb_auth_init();
if (is_daemon) {
#if !defined(_WIN32) #if !defined(_WIN32)
// Start a new session for the daemon. Do this here instead of after the fork so // Start a new session for the daemon. Do this here instead of after the fork so
// that a ctrl-c between the "starting server" and "done starting server" messages // that a ctrl-c between the "starting server" and "done starting server" messages
@ -132,6 +134,8 @@ int adb_server_main(int is_daemon, int server_port, int ack_reply_fd) {
} }
#endif #endif
// Inform our parent that we are up and running.
// Any error output written to stderr now goes to adb.log. We could // Any error output written to stderr now goes to adb.log. We could
// keep around a copy of the stderr fd and use that to write any errors // keep around a copy of the stderr fd and use that to write any errors
// encountered by the following code, but that is probably overkill. // encountered by the following code, but that is probably overkill.

View file

@ -828,4 +828,9 @@ static inline void disable_tcp_nagle(int fd) {
// configured to drop after 10 missed keepalives. Returns true on success. // configured to drop after 10 missed keepalives. Returns true on success.
bool set_tcp_keepalive(int fd, int interval_sec); bool set_tcp_keepalive(int fd, int interval_sec);
#if defined(_WIN32)
// Win32 defines ERROR, which we don't need, but which conflicts with google3 logging.
#undef ERROR
#endif
#endif /* _ADB_SYSDEPS_H */ #endif /* _ADB_SYSDEPS_H */

View file

@ -35,6 +35,7 @@
#include <android-base/strings.h> #include <android-base/strings.h>
#include "adb.h" #include "adb.h"
#include "adb_auth.h"
#include "adb_utils.h" #include "adb_utils.h"
#include "diagnose_usb.h" #include "diagnose_usb.h"
@ -1072,3 +1073,11 @@ int check_data(apacket *p)
return 0; return 0;
} }
} }
RSA* atransport::NextKey() {
if (keys_.empty()) keys_ = adb_auth_get_private_keys();
RSA* result = keys_[0];
keys_.pop_front();
return result;
}

View file

@ -19,12 +19,15 @@
#include <sys/types.h> #include <sys/types.h>
#include <deque>
#include <list> #include <list>
#include <string> #include <string>
#include <unordered_set> #include <unordered_set>
#include "adb.h" #include "adb.h"
#include <openssl/rsa.h>
typedef std::unordered_set<std::string> FeatureSet; typedef std::unordered_set<std::string> FeatureSet;
const FeatureSet& supported_features(); const FeatureSet& supported_features();
@ -104,7 +107,8 @@ public:
return type == kTransportLocal && local_port_for_emulator_ == -1; return type == kTransportLocal && local_port_for_emulator_ == -1;
} }
void* key = nullptr; RSA* NextKey();
unsigned char token[TOKEN_SIZE] = {}; unsigned char token[TOKEN_SIZE] = {};
size_t failed_auth_attempts = 0; size_t failed_auth_attempts = 0;
@ -156,6 +160,8 @@ private:
// A list of adisconnect callbacks called when the transport is kicked. // A list of adisconnect callbacks called when the transport is kicked.
std::list<adisconnect*> disconnects_; std::list<adisconnect*> disconnects_;
std::deque<RSA*> keys_;
DISALLOW_COPY_AND_ASSIGN(atransport); DISALLOW_COPY_AND_ASSIGN(atransport);
}; };