Merge "Clean up key handling in adb." am: b859830450 am: 81a3f71e45
am: f648fb4539
Change-Id: I66e49d47f732677e234cd6dfa85d722fc0dae0f4
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 725aa91..45d26f8 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -354,21 +354,13 @@
case A_AUTH:
if (p->msg.arg0 == ADB_AUTH_TOKEN) {
t->connection_state = kCsUnauthorized;
- t->key = adb_auth_nextkey(t->key);
- 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);
- }
+ send_auth_response(p->data, p->msg.data_length, t);
} else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) {
- if (adb_auth_verify(t->token, sizeof(t->token),
- p->data, p->msg.data_length)) {
+ if (adb_auth_verify(t->token, sizeof(t->token), p->data, p->msg.data_length)) {
adb_auth_verified(t);
t->failed_auth_attempts = 0;
} else {
- if (t->failed_auth_attempts++ > 10)
- adb_sleep_ms(1000);
+ if (t->failed_auth_attempts++ > 10) adb_sleep_ms(1000);
send_auth_request(t);
}
} else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) {
diff --git a/adb/adb_auth.cpp b/adb/adb_auth.cpp
index 215bbe6..446c3df 100644
--- a/adb/adb_auth.cpp
+++ b/adb/adb_auth.cpp
@@ -16,8 +16,9 @@
#define TRACE_TAG ADB
-#include "sysdeps.h"
+#include "adb.h"
#include "adb_auth.h"
+#include "transport.h"
#include <errno.h>
#include <stdio.h>
@@ -25,53 +26,28 @@
#include <sys/types.h>
#include <unistd.h>
-#include "adb.h"
-#include "transport.h"
-
bool auth_required = true;
void send_auth_request(atransport *t)
{
- D("Calling send_auth_request");
- apacket *p;
- int ret;
+ LOG(INFO) << "Calling send_auth_request...";
- ret = adb_auth_generate_token(t->token, sizeof(t->token));
- if (ret != sizeof(t->token)) {
- D("Error generating token ret=%d", ret);
+ if (!adb_auth_generate_token(t->token, sizeof(t->token))) {
+ PLOG(ERROR) << "Error generating token";
return;
}
- p = get_apacket();
- memcpy(p->data, t->token, ret);
+ apacket* p = get_apacket();
+ memcpy(p->data, t->token, sizeof(t->token));
p->msg.command = A_AUTH;
p->msg.arg0 = ADB_AUTH_TOKEN;
- p->msg.data_length = ret;
+ p->msg.data_length = sizeof(t->token);
send_packet(p, t);
}
-void send_auth_response(uint8_t *token, size_t token_size, atransport *t)
-{
- D("Calling send_auth_response");
- apacket *p = get_apacket();
- int ret;
+static void send_auth_publickey(atransport* t) {
+ LOG(INFO) << "Calling send_auth_publickey";
- 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();
if (key.empty()) {
D("Failed to get user public key");
@@ -92,6 +68,35 @@
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)
{
handle_online(t);
diff --git a/adb/adb_auth.h b/adb/adb_auth.h
index 6363bb4..723ded5 100644
--- a/adb/adb_auth.h
+++ b/adb/adb_auth.h
@@ -19,6 +19,10 @@
#include "adb.h"
+#include <deque>
+
+#include <openssl/rsa.h>
+
extern bool auth_required;
int adb_auth_keygen(const char* filename);
@@ -26,7 +30,6 @@
void send_auth_request(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 */
/* Request */
@@ -37,36 +40,25 @@
#if ADB_HOST
-void adb_auth_init(void);
-int adb_auth_sign(void *key, const unsigned char* token, size_t token_size,
- unsigned char* sig);
-void *adb_auth_nextkey(void *current);
+void adb_auth_init();
+int adb_auth_sign(RSA* key, const unsigned char* token, size_t token_size, unsigned char* sig);
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) {
- return 0;
-}
-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) {}
+static inline bool adb_auth_generate_token(void*, size_t) { abort(); }
+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(); }
#else // !ADB_HOST
-static inline int adb_auth_sign(void* key, const unsigned char* token,
- size_t token_size, unsigned char* sig) {
- return 0;
-}
-static inline void *adb_auth_nextkey(void *current) { return NULL; }
-static inline std::string adb_auth_get_userkey() { return ""; }
+static inline int adb_auth_sign(void*, const unsigned char*, size_t, unsigned char*) { abort(); }
+static inline std::string adb_auth_get_userkey() { abort(); }
+static inline std::deque<RSA*> adb_auth_get_private_keys() { abort(); }
void adbd_auth_init(void);
void adbd_cloexec_auth_socket();
-int adb_auth_generate_token(void *token, size_t token_size);
-int adb_auth_verify(uint8_t* token, size_t token_size,
- uint8_t* sig, int siglen);
+bool adb_auth_generate_token(void* token, size_t token_size);
+bool adb_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int sig_len);
void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t);
#endif // ADB_HOST
diff --git a/adb/adb_auth_client.cpp b/adb/adb_auth_client.cpp
index 415ab8e..9d8dfc0 100644
--- a/adb/adb_auth_client.cpp
+++ b/adb/adb_auth_client.cpp
@@ -16,37 +16,25 @@
#define TRACE_TAG AUTH
-#include "sysdeps.h"
+#include "adb.h"
#include "adb_auth.h"
+#include "fdevent.h"
+#include "sysdeps.h"
+#include "transport.h"
#include <resolv.h>
#include <stdio.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/rsa.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 framework_fde;
static int framework_fd = -1;
@@ -56,135 +44,71 @@
static atransport* usb_transport;
static bool needs_retry = false;
-static void read_keys(const char *file, struct listnode *list)
-{
- FILE *f;
- char buf[MAX_PAYLOAD_V1];
- char *sep;
- int ret;
+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 };
- f = fopen(file, "re");
- if (!f) {
- D("Can't open '%s'", file);
- return;
- }
+ for (const auto& path : key_paths) {
+ if (access(path, R_OK) == 0) {
+ LOG(INFO) << "Loading keys from " << path;
- while (fgets(buf, sizeof(buf), f)) {
- auto key = reinterpret_cast<adb_public_key*>(
- calloc(1, sizeof(adb_public_key)));
- if (key == nullptr) {
- D("Can't malloc key");
- break;
- }
+ std::string content;
+ if (!android::base::ReadFileToString(path, &content)) {
+ PLOG(ERROR) << "Couldn't read " << path;
+ continue;
+ }
- sep = strpbrk(buf, " \t");
- if (sep)
- *sep = '\0';
+ for (const auto& line : android::base::Split(content, "\n")) {
+ // TODO: do we really have to support both ' ' and '\t'?
+ 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
- // decoding to succeed. See http://b/28035006 for details.
- uint8_t keybuf[ANDROID_PUBKEY_ENCODED_SIZE + 1];
- ret = __b64_pton(buf, keybuf, sizeof(keybuf));
- if (ret != ANDROID_PUBKEY_ENCODED_SIZE) {
- D("%s: Invalid base64 data ret=%d", file, ret);
- free(key);
- continue;
- }
+ // b64_pton requires one additional byte in the target buffer for
+ // decoding to succeed. See http://b/28035006 for details.
+ uint8_t keybuf[ANDROID_PUBKEY_ENCODED_SIZE + 1];
+ if (__b64_pton(line.c_str(), keybuf, sizeof(keybuf)) != ANDROID_PUBKEY_ENCODED_SIZE) {
+ LOG(ERROR) << "Invalid base64 key " << line.c_str() << " in " << path;
+ continue;
+ }
- if (!android_pubkey_decode(keybuf, ret, &key->key)) {
- D("%s: Failed to parse key", file);
- free(key);
- continue;
- }
+ RSA* key = nullptr;
+ if (!android_pubkey_decode(keybuf, ANDROID_PUBKEY_ENCODED_SIZE, &key)) {
+ LOG(ERROR) << "Failed to parse key " << line.c_str() << " in " << path;
+ continue;
+ }
- list_add_tail(list, &key->node);
- }
-
- 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);
+ bool verified = (RSA_verify(NID_sha1, token, token_size, sig, sig_len, key) == 1);
+ RSA_free(key);
+ if (verified) return true;
+ }
}
}
+ return false;
}
-int adb_auth_generate_token(void *token, size_t token_size)
-{
- FILE *f;
- int ret;
-
- f = fopen("/dev/urandom", "re");
- 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;
+bool adb_auth_generate_token(void* token, size_t token_size) {
+ FILE* fp = fopen("/dev/urandom", "re");
+ if (!fp) return false;
+ bool okay = (fread(token, token_size, 1, fp) == 1);
+ fclose(fp);
+ return okay;
}
static void usb_disconnected(void* unused, atransport* t) {
- D("USB disconnect");
+ LOG(INFO) << "USB disconnect";
usb_transport = NULL;
needs_retry = false;
}
static void framework_disconnected() {
- D("Framework disconnect");
+ LOG(INFO) << "Framework disconnect";
fdevent_remove(&framework_fde);
framework_fd = -1;
}
static void adb_auth_event(int fd, unsigned events, void*) {
- char response[2];
- int ret;
-
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) {
framework_disconnected();
} else if (ret == 2 && response[0] == 'O' && response[1] == 'K') {
@@ -195,51 +119,43 @@
}
}
-void adb_auth_confirm_key(unsigned char *key, size_t len, atransport *t)
-{
- char msg[MAX_PAYLOAD_V1];
- int ret;
-
+void adb_auth_confirm_key(unsigned char* key, size_t len, atransport* t) {
if (!usb_transport) {
usb_transport = t;
t->AddDisconnect(&usb_disconnect);
}
if (framework_fd < 0) {
- D("Client not connected");
+ LOG(ERROR) << "Client not connected";
needs_retry = true;
return;
}
if (key[len - 1] != '\0') {
- D("Key must be a null-terminated string");
+ LOG(ERROR) << "Key must be a null-terminated string";
return;
}
- ret = snprintf(msg, sizeof(msg), "PK%s", key);
- if (ret >= (signed)sizeof(msg)) {
- D("Key too long. ret=%d", ret);
+ char msg[MAX_PAYLOAD_V1];
+ int msg_len = snprintf(msg, sizeof(msg), "PK%s", key);
+ if (msg_len >= static_cast<int>(sizeof(msg))) {
+ LOG(ERROR) << "Key too long (" << msg_len << ")";
return;
}
- D("Sending '%s'", msg);
+ LOG(DEBUG) << "Sending '" << msg << "'";
- ret = unix_write(framework_fd, msg, ret);
- if (ret < 0) {
- D("Failed to write PK, errno=%d", errno);
+ if (unix_write(framework_fd, msg, msg_len) == -1) {
+ PLOG(ERROR) << "Failed to write PK";
return;
}
}
static void adb_auth_listener(int fd, unsigned events, void* data) {
sockaddr_storage addr;
- socklen_t alen;
- int s;
-
- alen = sizeof(addr);
-
- s = adb_socket_accept(fd, reinterpret_cast<sockaddr*>(&addr), &alen);
+ socklen_t alen = sizeof(addr);
+ int s = adb_socket_accept(fd, reinterpret_cast<sockaddr*>(&addr), &alen);
if (s < 0) {
- D("Failed to accept: errno=%d", errno);
+ PLOG(ERROR) << "Failed to accept";
return;
}
@@ -261,7 +177,7 @@
void adbd_cloexec_auth_socket() {
int fd = android_get_control_socket("adbd");
if (fd == -1) {
- D("Failed to get adbd socket");
+ PLOG(ERROR) << "Failed to get adbd socket";
return;
}
fcntl(fd, F_SETFD, FD_CLOEXEC);
@@ -270,12 +186,12 @@
void adbd_auth_init(void) {
int fd = android_get_control_socket("adbd");
if (fd == -1) {
- D("Failed to get adbd socket");
+ PLOG(ERROR) << "Failed to get adbd socket";
return;
}
if (listen(fd, 4) == -1) {
- D("Failed to listen on '%d'", fd);
+ PLOG(ERROR) << "Failed to listen on '" << fd << "'";
return;
}
diff --git a/adb/adb_auth_host.cpp b/adb/adb_auth_host.cpp
index dff874f..ce269cc 100644
--- a/adb/adb_auth_host.cpp
+++ b/adb/adb_auth_host.cpp
@@ -16,23 +16,22 @@
#define TRACE_TAG AUTH
-#include "sysdeps.h"
#include "adb_auth.h"
+#include "adb.h"
#include "adb_utils.h"
+#include "sysdeps.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "adb.h"
+#include <mutex>
#include <android-base/errors.h>
#include <android-base/file.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
#include <crypto_utils/android_pubkey.h>
-#include <cutils/list.h>
-
#include <openssl/base64.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
@@ -40,18 +39,14 @@
#include <openssl/rsa.h>
#include <openssl/sha.h>
-#define ANDROID_PATH ".android"
-#define ADB_KEY_FILE "adbkey"
+#include "sysdeps/mutex.h"
-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() {
+ LOG(INFO) << "get_user_info...";
+
std::string hostname;
if (getenv("HOSTNAME")) hostname = getenv("HOSTNAME");
#if !defined(_WIN32)
@@ -71,6 +66,8 @@
}
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];
if (!android_pubkey_encode(private_key, binary_key_data, sizeof(binary_key_data))) {
LOG(ERROR) << "Failed to convert to public key";
@@ -99,19 +96,18 @@
return true;
}
-static int generate_key(const char *file)
-{
- EVP_PKEY* pkey = EVP_PKEY_new();
- BIGNUM* exponent = BN_new();
- RSA* rsa = RSA_new();
+static int generate_key(const std::string& file) {
+ LOG(INFO) << "generate_key(" << file << ")...";
+
mode_t old_mask;
FILE *f = NULL;
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) {
- D("Failed to allocate key");
+ LOG(ERROR) << "Failed to allocate key";
goto out;
}
@@ -121,9 +117,9 @@
old_mask = umask(077);
- f = fopen(file, "w");
+ f = fopen(file.c_str(), "w");
if (!f) {
- D("Failed to open '%s'", file);
+ PLOG(ERROR) << "Failed to open " << file;
umask(old_mask);
goto out;
}
@@ -143,110 +139,110 @@
ret = 1;
out:
- if (f)
- fclose(f);
+ if (f) fclose(f);
EVP_PKEY_free(pkey);
RSA_free(rsa);
BN_free(exponent);
return ret;
}
-static int read_key(const char *file, struct listnode *list)
-{
- D("read_key '%s'", file);
+static bool read_key(const std::string& file) {
+ LOG(INFO) << "read_key '" << file << "'...";
- FILE* fp = fopen(file, "r");
+ std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(file.c_str(), "r"), fclose);
if (!fp) {
- D("Failed to open '%s': %s", file, strerror(errno));
- return 0;
+ PLOG(ERROR) << "Failed to open '" << file << "'";
+ return false;
}
- adb_private_key* key = new adb_private_key;
- key->rsa = RSA_new();
-
- if (!PEM_read_RSAPrivateKey(fp, &key->rsa, NULL, NULL)) {
- D("Failed to read key");
- fclose(fp);
- RSA_free(key->rsa);
- delete key;
- return 0;
+ RSA* key = RSA_new();
+ if (!PEM_read_RSAPrivateKey(fp.get(), &key, nullptr, nullptr)) {
+ LOG(ERROR) << "Failed to read key";
+ RSA_free(key);
+ return false;
}
- fclose(fp);
- list_add_tail(list, &key->node);
- return 1;
+ g_key_list.push_back(key);
+ return true;
}
-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);
- D("home '%s'", home.c_str());
+ LOG(DEBUG) << "adb_get_homedir_path returned '" << home << "'";
- const std::string android_dir =
- android::base::StringPrintf("%s%c%s", home.c_str(),
- OS_PATH_SEPARATOR, ANDROID_PATH);
+ const std::string android_dir = android::base::StringPrintf("%s%c.android", home.c_str(),
+ OS_PATH_SEPARATOR);
struct stat buf;
- if (stat(android_dir.c_str(), &buf)) {
- if (adb_mkdir(android_dir.c_str(), 0750) < 0) {
- D("Cannot mkdir '%s'", android_dir.c_str());
- return -1;
+ if (stat(android_dir.c_str(), &buf) == -1) {
+ if (adb_mkdir(android_dir.c_str(), 0750) == -1) {
+ PLOG(ERROR) << "Cannot mkdir '" << android_dir << "'";
+ return "";
}
}
- return snprintf(filename, len, "%s%c%s",
- android_dir.c_str(), OS_PATH_SEPARATOR, ADB_KEY_FILE);
+ return android_dir + OS_PATH_SEPARATOR + "adbkey";
}
-static int get_user_key(struct listnode *list)
-{
- struct stat buf;
- char path[PATH_MAX];
- int ret;
-
- ret = get_user_keyfilepath(path, sizeof(path));
- if (ret < 0 || ret >= (signed)sizeof(path)) {
- D("Error getting user key filename");
- return 0;
+static bool get_user_key() {
+ std::string path = get_user_key_path();
+ if (path.empty()) {
+ PLOG(ERROR) << "Error getting user key filename";
+ return false;
}
- D("user key '%s'", path);
-
- if (stat(path, &buf) == -1) {
+ struct stat buf;
+ if (stat(path.c_str(), &buf) == -1) {
+ LOG(INFO) << "User key '" << path << "' does not exist...";
if (!generate_key(path)) {
- D("Failed to generate new key");
- return 0;
+ LOG(ERROR) << "Failed to generate new key";
+ 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");
if (adb_keys_path == nullptr) {
return;
}
for (const auto& path : android::base::Split(adb_keys_path, ENV_PATH_SEPARATOR_STR)) {
- if (!read_key(path.c_str(), key_list)) {
- D("Failed to read '%s'", path.c_str());
+ if (!read_key(path.c_str())) {
+ PLOG(ERROR) << "Failed to read '" << path << "'";
}
}
}
-int adb_auth_sign(void *node, const unsigned char* token, size_t token_size,
- unsigned char* sig)
-{
- unsigned int len;
- struct adb_private_key *key = node_to_item(node, struct adb_private_key, node);
+std::deque<RSA*> adb_auth_get_private_keys() {
+ std::deque<RSA*> result;
+ // 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) {
D("Unexpected token size %zd", token_size);
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;
}
@@ -254,40 +250,17 @@
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() {
- char path[PATH_MAX];
- int ret = get_user_keyfilepath(path, sizeof(path) - 4);
- if (ret < 0 || ret >= (signed)(sizeof(path) - 4)) {
- D("Error getting user key filename");
+ std::string path = get_user_key_path();
+ if (path.empty()) {
+ PLOG(ERROR) << "Error getting user key filename";
return "";
}
- strcat(path, ".pub");
+ path += ".pub";
std::string content;
if (!android::base::ReadFileToString(path, &content)) {
- D("Can't load '%s'", path);
+ PLOG(ERROR) << "Can't load '" << path << "'";
return "";
}
return content;
@@ -297,19 +270,14 @@
return (generate_key(filename) == 0);
}
-void adb_auth_init(void)
-{
- int ret;
+void adb_auth_init() {
+ LOG(INFO) << "adb_auth_init...";
- D("adb_auth_init");
-
- list_init(&key_list);
-
- ret = get_user_key(&key_list);
- if (!ret) {
- D("Failed to get user key");
+ if (!get_user_key()) {
+ LOG(ERROR) << "Failed to get user key";
return;
}
- get_vendor_keys(&key_list);
+ std::lock_guard<std::mutex> lock(g_key_list_mutex);
+ get_vendor_keys();
}
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index 894ebd1..0c85fe5 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -111,7 +111,6 @@
usb_init();
local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
- adb_auth_init();
std::string error;
std::string local_name = android::base::StringPrintf("tcp:%d", server_port);
@@ -119,11 +118,14 @@
fatal("could not install *smartsocket* listener: %s", error.c_str());
}
- // Inform our parent that we are up and running.
if (is_daemon) {
close_stdin();
setup_daemon_logging();
+ }
+ adb_auth_init();
+
+ if (is_daemon) {
#if !defined(_WIN32)
// 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
@@ -133,6 +135,8 @@
}
#endif
+ // Inform our parent that we are up and running.
+
// 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
// encountered by the following code, but that is probably overkill.
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index 04df16f..333b861 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -828,4 +828,9 @@
// configured to drop after 10 missed keepalives. Returns true on success.
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 */
diff --git a/adb/transport.cpp b/adb/transport.cpp
index ad63a6a..0d376b1 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -35,6 +35,7 @@
#include <android-base/strings.h>
#include "adb.h"
+#include "adb_auth.h"
#include "adb_utils.h"
#include "diagnose_usb.h"
@@ -1072,3 +1073,11 @@
return 0;
}
}
+
+RSA* atransport::NextKey() {
+ if (keys_.empty()) keys_ = adb_auth_get_private_keys();
+
+ RSA* result = keys_[0];
+ keys_.pop_front();
+ return result;
+}
diff --git a/adb/transport.h b/adb/transport.h
index 46d472b..d41c8bd 100644
--- a/adb/transport.h
+++ b/adb/transport.h
@@ -19,12 +19,15 @@
#include <sys/types.h>
+#include <deque>
#include <list>
#include <string>
#include <unordered_set>
#include "adb.h"
+#include <openssl/rsa.h>
+
typedef std::unordered_set<std::string> FeatureSet;
const FeatureSet& supported_features();
@@ -104,7 +107,8 @@
return type == kTransportLocal && local_port_for_emulator_ == -1;
}
- void* key = nullptr;
+ RSA* NextKey();
+
unsigned char token[TOKEN_SIZE] = {};
size_t failed_auth_attempts = 0;
@@ -156,6 +160,8 @@
// A list of adisconnect callbacks called when the transport is kicked.
std::list<adisconnect*> disconnects_;
+ std::deque<RSA*> keys_;
+
DISALLOW_COPY_AND_ASSIGN(atransport);
};