adb_auth_host.cpp revision 2e671202c38a9b17b0b034438a305e3067abb4ab
1/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define TRACE_TAG AUTH
18
19#include <dirent.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#if defined(__linux__)
24#include <sys/inotify.h>
25#endif
26
27#include <map>
28#include <mutex>
29#include <set>
30#include <string>
31
32#include <android-base/errors.h>
33#include <android-base/file.h>
34#include <android-base/stringprintf.h>
35#include <android-base/strings.h>
36#include <crypto_utils/android_pubkey.h>
37#include <openssl/base64.h>
38#include <openssl/evp.h>
39#include <openssl/objects.h>
40#include <openssl/pem.h>
41#include <openssl/rsa.h>
42#include <openssl/sha.h>
43
44#include "adb.h"
45#include "adb_auth.h"
46#include "adb_utils.h"
47#include "sysdeps.h"
48#include "sysdeps/mutex.h"
49
50static std::mutex& g_keys_mutex = *new std::mutex;
51static std::map<std::string, std::shared_ptr<RSA>>& g_keys =
52    *new std::map<std::string, std::shared_ptr<RSA>>;
53static std::map<int, std::string>& g_monitored_paths = *new std::map<int, std::string>;
54
55static std::string get_user_info() {
56    LOG(INFO) << "get_user_info...";
57
58    std::string hostname;
59    if (getenv("HOSTNAME")) hostname = getenv("HOSTNAME");
60#if !defined(_WIN32)
61    char buf[64];
62    if (hostname.empty() && gethostname(buf, sizeof(buf)) != -1) hostname = buf;
63#endif
64    if (hostname.empty()) hostname = "unknown";
65
66    std::string username;
67    if (getenv("LOGNAME")) username = getenv("LOGNAME");
68#if !defined _WIN32 && !defined ADB_HOST_ON_TARGET
69    if (username.empty() && getlogin()) username = getlogin();
70#endif
71    if (username.empty()) hostname = "unknown";
72
73    return " " + username + "@" + hostname;
74}
75
76static bool write_public_keyfile(RSA* private_key, const std::string& private_key_path) {
77    LOG(INFO) << "write_public_keyfile...";
78
79    uint8_t binary_key_data[ANDROID_PUBKEY_ENCODED_SIZE];
80    if (!android_pubkey_encode(private_key, binary_key_data, sizeof(binary_key_data))) {
81        LOG(ERROR) << "Failed to convert to public key";
82        return false;
83    }
84
85    size_t base64_key_length;
86    if (!EVP_EncodedLength(&base64_key_length, sizeof(binary_key_data))) {
87        LOG(ERROR) << "Public key too large to base64 encode";
88        return false;
89    }
90
91    std::string content;
92    content.resize(base64_key_length);
93    base64_key_length = EVP_EncodeBlock(reinterpret_cast<uint8_t*>(&content[0]), binary_key_data,
94                                        sizeof(binary_key_data));
95
96    content += get_user_info();
97
98    std::string path(private_key_path + ".pub");
99    if (!android::base::WriteStringToFile(content, path)) {
100        PLOG(ERROR) << "Failed to write public key to '" << path << "'";
101        return false;
102    }
103
104    return true;
105}
106
107static int generate_key(const std::string& file) {
108    LOG(INFO) << "generate_key(" << file << ")...";
109
110    mode_t old_mask;
111    FILE *f = NULL;
112    int ret = 0;
113
114    EVP_PKEY* pkey = EVP_PKEY_new();
115    BIGNUM* exponent = BN_new();
116    RSA* rsa = RSA_new();
117    if (!pkey || !exponent || !rsa) {
118        LOG(ERROR) << "Failed to allocate key";
119        goto out;
120    }
121
122    BN_set_word(exponent, RSA_F4);
123    RSA_generate_key_ex(rsa, 2048, exponent, NULL);
124    EVP_PKEY_set1_RSA(pkey, rsa);
125
126    old_mask = umask(077);
127
128    f = fopen(file.c_str(), "w");
129    if (!f) {
130        PLOG(ERROR) << "Failed to open " << file;
131        umask(old_mask);
132        goto out;
133    }
134
135    umask(old_mask);
136
137    if (!PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) {
138        D("Failed to write key");
139        goto out;
140    }
141
142    if (!write_public_keyfile(rsa, file)) {
143        D("Failed to write public key");
144        goto out;
145    }
146
147    ret = 1;
148
149out:
150    if (f) fclose(f);
151    EVP_PKEY_free(pkey);
152    RSA_free(rsa);
153    BN_free(exponent);
154    return ret;
155}
156
157static std::string hash_key(RSA* key) {
158    unsigned char* pubkey = nullptr;
159    int len = i2d_RSA_PUBKEY(key, &pubkey);
160    if (len < 0) {
161        LOG(ERROR) << "failed to encode RSA public key";
162        return std::string();
163    }
164
165    std::string result;
166    result.resize(SHA256_DIGEST_LENGTH);
167    SHA256(pubkey, len, reinterpret_cast<unsigned char*>(&result[0]));
168    OPENSSL_free(pubkey);
169    return result;
170}
171
172static bool read_key_file(const std::string& file) {
173    LOG(INFO) << "read_key_file '" << file << "'...";
174
175    std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(file.c_str(), "r"), fclose);
176    if (!fp) {
177        PLOG(ERROR) << "Failed to open '" << file << "'";
178        return false;
179    }
180
181    RSA* key = RSA_new();
182    if (!PEM_read_RSAPrivateKey(fp.get(), &key, nullptr, nullptr)) {
183        LOG(ERROR) << "Failed to read key";
184        RSA_free(key);
185        return false;
186    }
187
188    std::lock_guard<std::mutex> lock(g_keys_mutex);
189    std::string fingerprint = hash_key(key);
190    if (g_keys.find(fingerprint) != g_keys.end()) {
191        LOG(INFO) << "ignoring already-loaded key: " << file;
192        RSA_free(key);
193    } else {
194        g_keys[fingerprint] = std::shared_ptr<RSA>(key, RSA_free);
195    }
196
197    return true;
198}
199
200static bool read_keys(const std::string& path, bool allow_dir = true) {
201    LOG(INFO) << "read_keys '" << path << "'...";
202
203    struct stat st;
204    if (stat(path.c_str(), &st) != 0) {
205        PLOG(ERROR) << "failed to stat '" << path << "'";
206        return false;
207    }
208
209    if (S_ISREG(st.st_mode)) {
210        if (!android::base::EndsWith(path, ".adb_key")) {
211            LOG(INFO) << "skipping non-adb_key '" << path << "'";
212            return false;
213        }
214
215        return read_key_file(path);
216    } else if (S_ISDIR(st.st_mode)) {
217        if (!allow_dir) {
218            // inotify isn't recursive. It would break expectations to load keys in nested
219            // directories but not monitor them for new keys.
220            LOG(WARNING) << "refusing to recurse into directory '" << path << "'";
221            return false;
222        }
223
224        std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir);
225        if (!dir) {
226            PLOG(ERROR) << "failed to open directory '" << path << "'";
227            return false;
228        }
229
230        bool result = false;
231        while (struct dirent* dent = readdir(dir.get())) {
232            std::string name = dent->d_name;
233
234            // We can't use dent->d_type here because it's not available on Windows.
235            if (name == "." || name == "..") {
236                continue;
237            }
238
239            result |= read_keys((path + OS_PATH_SEPARATOR + name).c_str(), false);
240        }
241        return result;
242    }
243
244    LOG(ERROR) << "unexpected type for '" << path << "': 0x" << std::hex << st.st_mode;
245    return false;
246}
247
248static std::string get_user_key_path() {
249    const std::string home = adb_get_homedir_path(true);
250    LOG(DEBUG) << "adb_get_homedir_path returned '" << home << "'";
251
252    const std::string android_dir = android::base::StringPrintf("%s%c.android", home.c_str(),
253                                                                OS_PATH_SEPARATOR);
254
255    struct stat buf;
256    if (stat(android_dir.c_str(), &buf) == -1) {
257        if (adb_mkdir(android_dir.c_str(), 0750) == -1) {
258            PLOG(ERROR) << "Cannot mkdir '" << android_dir << "'";
259            return "";
260        }
261    }
262
263    return android_dir + OS_PATH_SEPARATOR + "adbkey";
264}
265
266static bool get_user_key() {
267    std::string path = get_user_key_path();
268    if (path.empty()) {
269        PLOG(ERROR) << "Error getting user key filename";
270        return false;
271    }
272
273    struct stat buf;
274    if (stat(path.c_str(), &buf) == -1) {
275        LOG(INFO) << "User key '" << path << "' does not exist...";
276        if (!generate_key(path)) {
277            LOG(ERROR) << "Failed to generate new key";
278            return false;
279        }
280    }
281
282    return read_key_file(path);
283}
284
285static std::set<std::string> get_vendor_keys() {
286    const char* adb_keys_path = getenv("ADB_VENDOR_KEYS");
287    if (adb_keys_path == nullptr) {
288        return std::set<std::string>();
289    }
290
291    std::set<std::string> result;
292    for (const auto& path : android::base::Split(adb_keys_path, ENV_PATH_SEPARATOR_STR)) {
293        result.emplace(path);
294    }
295    return result;
296}
297
298std::deque<std::shared_ptr<RSA>> adb_auth_get_private_keys() {
299    std::deque<std::shared_ptr<RSA>> result;
300
301    // Copy all the currently known keys.
302    std::lock_guard<std::mutex> lock(g_keys_mutex);
303    for (const auto& it : g_keys) {
304        result.push_back(it.second);
305    }
306
307    // Add a sentinel to the list. Our caller uses this to mean "out of private keys,
308    // but try using the public key" (the empty deque could otherwise mean this _or_
309    // that this function hasn't been called yet to request the keys).
310    result.push_back(nullptr);
311
312    return result;
313}
314
315int adb_auth_sign(RSA* key, const unsigned char* token, size_t token_size, unsigned char* sig) {
316    if (token_size != TOKEN_SIZE) {
317        D("Unexpected token size %zd", token_size);
318        return 0;
319    }
320
321    unsigned int len;
322    if (!RSA_sign(NID_sha1, token, token_size, sig, &len, key)) {
323        return 0;
324    }
325
326    D("adb_auth_sign len=%d", len);
327    return (int)len;
328}
329
330std::string adb_auth_get_userkey() {
331    std::string path = get_user_key_path();
332    if (path.empty()) {
333        PLOG(ERROR) << "Error getting user key filename";
334        return "";
335    }
336    path += ".pub";
337
338    std::string content;
339    if (!android::base::ReadFileToString(path, &content)) {
340        PLOG(ERROR) << "Can't load '" << path << "'";
341        return "";
342    }
343    return content;
344}
345
346int adb_auth_keygen(const char* filename) {
347    return (generate_key(filename) == 0);
348}
349
350#if defined(__linux__)
351static void adb_auth_inotify_update(int fd, unsigned fd_event, void*) {
352    LOG(INFO) << "adb_auth_inotify_update called";
353    if (!(fd_event & FDE_READ)) {
354        return;
355    }
356
357    char buf[sizeof(struct inotify_event) + NAME_MAX + 1];
358    while (true) {
359        ssize_t rc = TEMP_FAILURE_RETRY(unix_read(fd, buf, sizeof(buf)));
360        if (rc == -1) {
361            if (errno == EAGAIN) {
362                LOG(INFO) << "done reading inotify fd";
363                break;
364            }
365            PLOG(FATAL) << "read of inotify event failed";
366        }
367
368        // The read potentially returned multiple events.
369        char* start = buf;
370        char* end = buf + rc;
371
372        while (start < end) {
373            inotify_event* event = reinterpret_cast<inotify_event*>(start);
374            auto root_it = g_monitored_paths.find(event->wd);
375            if (root_it == g_monitored_paths.end()) {
376                LOG(FATAL) << "observed inotify event for unmonitored path, wd = " << event->wd;
377            }
378
379            std::string path = root_it->second;
380            if (event->len > 0) {
381                path += '/';
382                path += event->name;
383            }
384
385            if (event->mask & (IN_CREATE | IN_MOVED_TO)) {
386                if (event->mask & IN_ISDIR) {
387                    LOG(INFO) << "ignoring new directory at '" << path << "'";
388                } else {
389                    LOG(INFO) << "observed new file at '" << path << "'";
390                    read_keys(path, false);
391                }
392            } else {
393                LOG(WARNING) << "unmonitored event for " << path << ": 0x" << std::hex
394                             << event->mask;
395            }
396
397            start += sizeof(struct inotify_event) + event->len;
398        }
399    }
400}
401
402static void adb_auth_inotify_init(const std::set<std::string>& paths) {
403    LOG(INFO) << "adb_auth_inotify_init...";
404    int infd = inotify_init1(IN_CLOEXEC | IN_NONBLOCK);
405    for (const std::string& path : paths) {
406        int wd = inotify_add_watch(infd, path.c_str(), IN_CREATE | IN_MOVED_TO);
407        if (wd < 0) {
408            PLOG(ERROR) << "failed to inotify_add_watch on path '" << path;
409            continue;
410        }
411
412        g_monitored_paths[wd] = path;
413        LOG(INFO) << "watch descriptor " << wd << " registered for " << path;
414    }
415
416    fdevent* event = fdevent_create(infd, adb_auth_inotify_update, nullptr);
417    fdevent_add(event, FDE_READ);
418}
419#endif
420
421void adb_auth_init() {
422    LOG(INFO) << "adb_auth_init...";
423
424    if (!get_user_key()) {
425        LOG(ERROR) << "Failed to get user key";
426        return;
427    }
428
429    const auto& key_paths = get_vendor_keys();
430
431#if defined(__linux__)
432    adb_auth_inotify_init(key_paths);
433#endif
434
435    for (const std::string& path : key_paths) {
436        read_keys(path.c_str());
437    }
438}
439