Merge changes I9761298a,I8d3312b2

am: 0b4fcb75d4

Change-Id: I330c467e408bc10ebdab0f5708d24d2297cf39a2
This commit is contained in:
Josh Gao 2016-08-22 21:38:53 +00:00 committed by android-build-merger
commit 8270912ed0
5 changed files with 194 additions and 40 deletions

View File

@ -64,12 +64,14 @@ static void send_auth_publickey(atransport* t) {
p->msg.command = A_AUTH;
p->msg.arg0 = ADB_AUTH_RSAPUBLICKEY;
p->msg.data_length = key.size();
// adbd expects a null-terminated string.
p->msg.data_length = key.size() + 1;
send_packet(p, t);
}
void send_auth_response(uint8_t* token, size_t token_size, atransport* t) {
RSA* key = t->NextKey();
std::shared_ptr<RSA> key = t->NextKey();
if (key == nullptr) {
// No more private keys to try, send the public key.
send_auth_publickey(t);
@ -79,12 +81,7 @@ void send_auth_response(uint8_t* token, size_t token_size, atransport* t) {
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;
int ret = adb_auth_sign(key.get(), token, token_size, p->data);
if (!ret) {
D("Error signing the token");
put_apacket(p);

View File

@ -20,6 +20,7 @@
#include "adb.h"
#include <deque>
#include <memory>
#include <openssl/rsa.h>
@ -43,7 +44,7 @@ void send_auth_response(uint8_t *token, size_t token_size, atransport *t);
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();
std::deque<std::shared_ptr<RSA>> adb_auth_get_private_keys();
static inline bool adb_auth_generate_token(void*, size_t) { abort(); }
static inline bool adb_auth_verify(void*, size_t, void*, int) { abort(); }
@ -53,7 +54,7 @@ static inline void adb_auth_confirm_key(unsigned char*, size_t, atransport*) { a
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(); }
static inline std::deque<std::shared_ptr<RSA>> adb_auth_get_private_keys() { abort(); }
void adbd_auth_init(void);
void adbd_cloexec_auth_socket();

View File

@ -16,16 +16,18 @@
#define TRACE_TAG AUTH
#include "adb_auth.h"
#include "adb.h"
#include "adb_utils.h"
#include "sysdeps.h"
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(__linux__)
#include <sys/inotify.h>
#endif
#include <map>
#include <mutex>
#include <set>
#include <string>
#include <android-base/errors.h>
#include <android-base/file.h>
@ -39,10 +41,16 @@
#include <openssl/rsa.h>
#include <openssl/sha.h>
#include "adb.h"
#include "adb_auth.h"
#include "adb_utils.h"
#include "sysdeps.h"
#include "sysdeps/mutex.h"
static std::mutex& g_key_list_mutex = *new std::mutex;
static std::deque<RSA*>& g_key_list = *new std::deque<RSA*>;
static std::mutex& g_keys_mutex = *new std::mutex;
static std::map<std::string, std::shared_ptr<RSA>>& g_keys =
*new std::map<std::string, std::shared_ptr<RSA>>;
static std::map<int, std::string>& g_monitored_paths = *new std::map<int, std::string>;
static std::string get_user_info() {
LOG(INFO) << "get_user_info...";
@ -146,8 +154,23 @@ out:
return ret;
}
static bool read_key(const std::string& file) {
LOG(INFO) << "read_key '" << file << "'...";
static std::string hash_key(RSA* key) {
unsigned char* pubkey = nullptr;
int len = i2d_RSA_PUBKEY(key, &pubkey);
if (len < 0) {
LOG(ERROR) << "failed to encode RSA public key";
return std::string();
}
std::string result;
result.resize(SHA256_DIGEST_LENGTH);
SHA256(pubkey, len, reinterpret_cast<unsigned char*>(&result[0]));
OPENSSL_free(pubkey);
return result;
}
static bool read_key_file(const std::string& file) {
LOG(INFO) << "read_key_file '" << file << "'...";
std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(file.c_str(), "r"), fclose);
if (!fp) {
@ -162,10 +185,66 @@ static bool read_key(const std::string& file) {
return false;
}
g_key_list.push_back(key);
std::lock_guard<std::mutex> lock(g_keys_mutex);
std::string fingerprint = hash_key(key);
if (g_keys.find(fingerprint) != g_keys.end()) {
LOG(INFO) << "ignoring already-loaded key: " << file;
RSA_free(key);
} else {
g_keys[fingerprint] = std::shared_ptr<RSA>(key, RSA_free);
}
return true;
}
static bool read_keys(const std::string& path, bool allow_dir = true) {
LOG(INFO) << "read_keys '" << path << "'...";
struct stat st;
if (stat(path.c_str(), &st) != 0) {
PLOG(ERROR) << "failed to stat '" << path << "'";
return false;
}
if (S_ISREG(st.st_mode)) {
if (!android::base::EndsWith(path, ".adb_key")) {
LOG(INFO) << "skipping non-adb_key '" << path << "'";
return false;
}
return read_key_file(path);
} else if (S_ISDIR(st.st_mode)) {
if (!allow_dir) {
// inotify isn't recursive. It would break expectations to load keys in nested
// directories but not monitor them for new keys.
LOG(WARNING) << "refusing to recurse into directory '" << path << "'";
return false;
}
std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir);
if (!dir) {
PLOG(ERROR) << "failed to open directory '" << path << "'";
return false;
}
bool result = false;
while (struct dirent* dent = readdir(dir.get())) {
std::string name = dent->d_name;
// We can't use dent->d_type here because it's not available on Windows.
if (name == "." || name == "..") {
continue;
}
result |= read_keys((path + OS_PATH_SEPARATOR + name).c_str(), false);
}
return result;
}
LOG(ERROR) << "unexpected type for '" << path << "': 0x" << std::hex << st.st_mode;
return false;
}
static std::string get_user_key_path() {
const std::string home = adb_get_homedir_path(true);
LOG(DEBUG) << "adb_get_homedir_path returned '" << home << "'";
@ -200,31 +279,29 @@ static bool get_user_key() {
}
}
return read_key(path);
return read_key_file(path);
}
static void get_vendor_keys() {
static std::set<std::string> get_vendor_keys() {
const char* adb_keys_path = getenv("ADB_VENDOR_KEYS");
if (adb_keys_path == nullptr) {
return;
return std::set<std::string>();
}
std::set<std::string> result;
for (const auto& path : android::base::Split(adb_keys_path, ENV_PATH_SEPARATOR_STR)) {
if (!read_key(path.c_str())) {
PLOG(ERROR) << "Failed to read '" << path << "'";
}
result.emplace(path);
}
return result;
}
std::deque<RSA*> adb_auth_get_private_keys() {
std::deque<RSA*> result;
std::deque<std::shared_ptr<RSA>> adb_auth_get_private_keys() {
std::deque<std::shared_ptr<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);
// Copy all the currently known keys.
std::lock_guard<std::mutex> lock(g_keys_mutex);
for (const auto& it : g_keys) {
result.push_back(it.second);
}
// Add a sentinel to the list. Our caller uses this to mean "out of private keys,
@ -270,6 +347,77 @@ int adb_auth_keygen(const char* filename) {
return (generate_key(filename) == 0);
}
#if defined(__linux__)
static void adb_auth_inotify_update(int fd, unsigned fd_event, void*) {
LOG(INFO) << "adb_auth_inotify_update called";
if (!(fd_event & FDE_READ)) {
return;
}
char buf[sizeof(struct inotify_event) + NAME_MAX + 1];
while (true) {
ssize_t rc = TEMP_FAILURE_RETRY(unix_read(fd, buf, sizeof(buf)));
if (rc == -1) {
if (errno == EAGAIN) {
LOG(INFO) << "done reading inotify fd";
break;
}
PLOG(FATAL) << "read of inotify event failed";
}
// The read potentially returned multiple events.
char* start = buf;
char* end = buf + rc;
while (start < end) {
inotify_event* event = reinterpret_cast<inotify_event*>(start);
auto root_it = g_monitored_paths.find(event->wd);
if (root_it == g_monitored_paths.end()) {
LOG(FATAL) << "observed inotify event for unmonitored path, wd = " << event->wd;
}
std::string path = root_it->second;
if (event->len > 0) {
path += '/';
path += event->name;
}
if (event->mask & (IN_CREATE | IN_MOVED_TO)) {
if (event->mask & IN_ISDIR) {
LOG(INFO) << "ignoring new directory at '" << path << "'";
} else {
LOG(INFO) << "observed new file at '" << path << "'";
read_keys(path, false);
}
} else {
LOG(WARNING) << "unmonitored event for " << path << ": 0x" << std::hex
<< event->mask;
}
start += sizeof(struct inotify_event) + event->len;
}
}
}
static void adb_auth_inotify_init(const std::set<std::string>& paths) {
LOG(INFO) << "adb_auth_inotify_init...";
int infd = inotify_init1(IN_CLOEXEC | IN_NONBLOCK);
for (const std::string& path : paths) {
int wd = inotify_add_watch(infd, path.c_str(), IN_CREATE | IN_MOVED_TO);
if (wd < 0) {
PLOG(ERROR) << "failed to inotify_add_watch on path '" << path;
continue;
}
g_monitored_paths[wd] = path;
LOG(INFO) << "watch descriptor " << wd << " registered for " << path;
}
fdevent* event = fdevent_create(infd, adb_auth_inotify_update, nullptr);
fdevent_add(event, FDE_READ);
}
#endif
void adb_auth_init() {
LOG(INFO) << "adb_auth_init...";
@ -278,6 +426,13 @@ void adb_auth_init() {
return;
}
std::lock_guard<std::mutex> lock(g_key_list_mutex);
get_vendor_keys();
const auto& key_paths = get_vendor_keys();
#if defined(__linux__)
adb_auth_inotify_init(key_paths);
#endif
for (const std::string& path : key_paths) {
read_keys(path.c_str());
}
}

View File

@ -1074,10 +1074,10 @@ int check_data(apacket *p)
}
}
RSA* atransport::NextKey() {
std::shared_ptr<RSA> atransport::NextKey() {
if (keys_.empty()) keys_ = adb_auth_get_private_keys();
RSA* result = keys_[0];
std::shared_ptr<RSA> result = keys_[0];
keys_.pop_front();
return result;
}

View File

@ -21,6 +21,7 @@
#include <deque>
#include <list>
#include <memory>
#include <string>
#include <unordered_set>
@ -107,7 +108,7 @@ public:
return type == kTransportLocal && local_port_for_emulator_ == -1;
}
RSA* NextKey();
std::shared_ptr<RSA> NextKey();
unsigned char token[TOKEN_SIZE] = {};
size_t failed_auth_attempts = 0;
@ -160,7 +161,7 @@ private:
// A list of adisconnect callbacks called when the transport is kicked.
std::list<adisconnect*> disconnects_;
std::deque<RSA*> keys_;
std::deque<std::shared_ptr<RSA>> keys_;
DISALLOW_COPY_AND_ASSIGN(atransport);
};