/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define TRACE_TAG AUTH

#include "adb.h"
#include "adb_auth.h"
#include "adb_io.h"
#include "fdevent/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>

static fdevent* listener_fde = nullptr;
static fdevent* framework_fde = nullptr;
static int framework_fd = -1;

static void usb_disconnected(void* unused, atransport* t);
static struct adisconnect usb_disconnect = { usb_disconnected, nullptr};
static atransport* usb_transport;
static bool needs_retry = false;

bool auth_required = true;

bool adbd_auth_verify(const char* token, size_t token_size, const std::string& sig) {
    static constexpr const char* key_paths[] = { "/adb_keys", "/data/misc/adb/adb_keys", nullptr };

    for (const auto& path : key_paths) {
        if (access(path, R_OK) == 0) {
            LOG(INFO) << "Loading keys from " << path;

            std::string content;
            if (!android::base::ReadFileToString(path, &content)) {
                PLOG(ERROR) << "Couldn't read " << path;
                continue;
            }

            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];
                if (b64_pton(line.c_str(), keybuf, sizeof(keybuf)) != ANDROID_PUBKEY_ENCODED_SIZE) {
                    LOG(ERROR) << "Invalid base64 key " << line.c_str() << " in " << path;
                    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;
                }

                bool verified =
                    (RSA_verify(NID_sha1, reinterpret_cast<const uint8_t*>(token), token_size,
                                reinterpret_cast<const uint8_t*>(sig.c_str()), sig.size(),
                                key) == 1);
                RSA_free(key);
                if (verified) return true;
            }
        }
    }
    return false;
}

static bool adbd_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) {
    LOG(INFO) << "USB disconnect";
    usb_transport = nullptr;
    needs_retry = false;
}

static void framework_disconnected() {
    LOG(INFO) << "Framework disconnect";
    if (framework_fde) {
        fdevent_destroy(framework_fde);
        framework_fd = -1;
    }
}

static void adbd_auth_event(int fd, unsigned events, void*) {
    if (events & FDE_READ) {
        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') {
            if (usb_transport) {
                adbd_auth_verified(usb_transport);
            }
        }
    }
}

void adbd_auth_confirm_key(const char* key, size_t len, atransport* t) {
    if (!usb_transport) {
        usb_transport = t;
        t->AddDisconnect(&usb_disconnect);
    }

    if (framework_fd < 0) {
        LOG(ERROR) << "Client not connected";
        needs_retry = true;
        return;
    }

    if (key[len - 1] != '\0') {
        LOG(ERROR) << "Key must be a null-terminated string";
        return;
    }

    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;
    }
    LOG(DEBUG) << "Sending '" << msg << "'";

    if (unix_write(framework_fd, msg, msg_len) == -1) {
        PLOG(ERROR) << "Failed to write PK";
        return;
    }
}

static void adbd_auth_listener(int fd, unsigned events, void* data) {
    int s = adb_socket_accept(fd, nullptr, nullptr);
    if (s < 0) {
        PLOG(ERROR) << "Failed to accept";
        return;
    }

    if (framework_fd >= 0) {
        LOG(WARNING) << "adb received framework auth socket connection again";
        framework_disconnected();
    }

    framework_fd = s;
    framework_fde = fdevent_create(framework_fd, adbd_auth_event, nullptr);
    fdevent_add(framework_fde, FDE_READ);

    if (needs_retry) {
        needs_retry = false;
        send_auth_request(usb_transport);
    }
}

void adbd_cloexec_auth_socket() {
    int fd = android_get_control_socket("adbd");
    if (fd == -1) {
        PLOG(ERROR) << "Failed to get adbd socket";
        return;
    }
    fcntl(fd, F_SETFD, FD_CLOEXEC);
}

void adbd_auth_init(void) {
    int fd = android_get_control_socket("adbd");
    if (fd == -1) {
        PLOG(ERROR) << "Failed to get adbd socket";
        return;
    }

    if (listen(fd, 4) == -1) {
        PLOG(ERROR) << "Failed to listen on '" << fd << "'";
        return;
    }

    listener_fde = fdevent_create(fd, adbd_auth_listener, nullptr);
    fdevent_add(listener_fde, FDE_READ);
}

void send_auth_request(atransport* t) {
    LOG(INFO) << "Calling send_auth_request...";

    if (!adbd_auth_generate_token(t->token, sizeof(t->token))) {
        PLOG(ERROR) << "Error generating token";
        return;
    }

    apacket* p = get_apacket();
    p->msg.command = A_AUTH;
    p->msg.arg0 = ADB_AUTH_TOKEN;
    p->msg.data_length = sizeof(t->token);
    p->payload.assign(t->token, t->token + sizeof(t->token));
    send_packet(p, t);
}

void adbd_auth_verified(atransport* t) {
    LOG(INFO) << "adb client authorized";
    handle_online(t);
    send_connect(t);
}
