// Copyright 2020, 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.

//! This module implements the Android Protected Confirmation (APC) service as defined
//! in the android.security.apc AIDL spec.

use std::{
    cmp::PartialEq,
    collections::HashMap,
    sync::{mpsc::Sender, Arc, Mutex},
};

use crate::error::anyhow_error_to_cstring;
use crate::ks_err;
use crate::utils::{compat_2_response_code, ui_opts_2_compat, watchdog as wd};
use android_security_apc::aidl::android::security::apc::{
    IConfirmationCallback::IConfirmationCallback,
    IProtectedConfirmation::{BnProtectedConfirmation, IProtectedConfirmation},
    ResponseCode::ResponseCode,
};
use android_security_apc::binder::{
    BinderFeatures, ExceptionCode, Interface, Result as BinderResult, SpIBinder,
    Status as BinderStatus, Strong, ThreadState,
};
use anyhow::{Context, Result};
use keystore2_apc_compat::ApcHal;
use keystore2_selinux as selinux;
use std::time::{Duration, Instant};

/// This is the main APC error type, it wraps binder exceptions and the
/// APC ResponseCode.
#[derive(Debug, thiserror::Error, PartialEq, Eq)]
pub enum Error {
    /// Wraps an Android Protected Confirmation (APC) response code as defined by the
    /// android.security.apc AIDL interface specification.
    #[error("Error::Rc({0:?})")]
    Rc(ResponseCode),
    /// Wraps a Binder exception code other than a service specific exception.
    #[error("Binder exception code {0:?}, {1:?}")]
    Binder(ExceptionCode, i32),
}

impl Error {
    /// Short hand for `Error::Rc(ResponseCode::SYSTEM_ERROR)`
    pub fn sys() -> Self {
        Error::Rc(ResponseCode::SYSTEM_ERROR)
    }

    /// Short hand for `Error::Rc(ResponseCode::OPERATION_PENDING)`
    pub fn pending() -> Self {
        Error::Rc(ResponseCode::OPERATION_PENDING)
    }

    /// Short hand for `Error::Rc(ResponseCode::IGNORED)`
    pub fn ignored() -> Self {
        Error::Rc(ResponseCode::IGNORED)
    }

    /// Short hand for `Error::Rc(ResponseCode::UNIMPLEMENTED)`
    pub fn unimplemented() -> Self {
        Error::Rc(ResponseCode::UNIMPLEMENTED)
    }
}

/// Translate an error into a service-specific exception, logging along the way.
///
/// `Error::Rc(x)` variants get mapped onto a service specific error code of `x`.
/// `selinux::Error::perm()` is mapped on `ResponseCode::PERMISSION_DENIED`.
///
/// All non `Error` error conditions get mapped onto ResponseCode::SYSTEM_ERROR`.
pub fn into_logged_binder(e: anyhow::Error) -> BinderStatus {
    log::error!("{:#?}", e);
    let root_cause = e.root_cause();
    let rc = match root_cause.downcast_ref::<Error>() {
        Some(Error::Rc(rcode)) => rcode.0,
        Some(Error::Binder(_, _)) => ResponseCode::SYSTEM_ERROR.0,
        None => match root_cause.downcast_ref::<selinux::Error>() {
            Some(selinux::Error::PermissionDenied) => ResponseCode::PERMISSION_DENIED.0,
            _ => ResponseCode::SYSTEM_ERROR.0,
        },
    };
    BinderStatus::new_service_specific_error(rc, anyhow_error_to_cstring(&e).as_deref())
}

/// Rate info records how many failed attempts a client has made to display a protected
/// confirmation prompt. Clients are penalized for attempts that get declined by the user
/// or attempts that get aborted by the client itself.
///
/// After the third failed attempt the client has to cool down for 30 seconds before it
/// it can retry. After the sixth failed attempt, the time doubles with every failed attempt
/// until it goes into saturation at 24h.
///
/// A successful user prompt resets the counter.
#[derive(Debug, Clone)]
struct RateInfo {
    counter: u32,
    timestamp: Instant,
}

impl RateInfo {
    const ONE_DAY: Duration = Duration::from_secs(60u64 * 60u64 * 24u64);

    fn get_remaining_back_off(&self) -> Option<Duration> {
        let back_off = match self.counter {
            // The first three attempts come without penalty.
            0..=2 => return None,
            // The next three attempts are are penalized with 30 seconds back off time.
            3..=5 => Duration::from_secs(30),
            // After that we double the back off time the with every additional attempt
            // until we reach 1024m (~17h).
            6..=16 => Duration::from_secs(60)
                .checked_mul(1u32 << (self.counter - 6))
                .unwrap_or(Self::ONE_DAY),
            // After that we cap of at 24h between attempts.
            _ => Self::ONE_DAY,
        };
        let elapsed = self.timestamp.elapsed();
        // This does exactly what we want.
        // `back_off - elapsed` is the remaining back off duration or None if elapsed is larger
        // than back_off. Also, this operation cannot overflow as long as elapsed is less than
        // back_off, which is all that we care about.
        back_off.checked_sub(elapsed)
    }
}

impl Default for RateInfo {
    fn default() -> Self {
        Self { counter: 0u32, timestamp: Instant::now() }
    }
}

/// The APC session state represents the state of an APC session.
struct ApcSessionState {
    /// A reference to the APC HAL backend.
    hal: Arc<ApcHal>,
    /// The client callback object.
    cb: SpIBinder,
    /// The uid of the owner of this APC session.
    uid: u32,
    /// The time when this session was started.
    start: Instant,
    /// This is set when the client calls abort.
    /// This is used by the rate limiting logic to determine
    /// if the client needs to be penalized for this attempt.
    client_aborted: bool,
}

struct ApcState {
    session: Option<ApcSessionState>,
    rate_limiting: HashMap<u32, RateInfo>,
    confirmation_token_sender: Sender<Vec<u8>>,
}

impl ApcState {
    fn new(confirmation_token_sender: Sender<Vec<u8>>) -> Self {
        Self { session: None, rate_limiting: Default::default(), confirmation_token_sender }
    }
}

/// Implementation of the APC service.
pub struct ApcManager {
    state: Arc<Mutex<ApcState>>,
}

impl Interface for ApcManager {}

impl ApcManager {
    /// Create a new instance of the Android Protected Confirmation service.
    pub fn new_native_binder(
        confirmation_token_sender: Sender<Vec<u8>>,
    ) -> Result<Strong<dyn IProtectedConfirmation>> {
        Ok(BnProtectedConfirmation::new_binder(
            Self { state: Arc::new(Mutex::new(ApcState::new(confirmation_token_sender))) },
            BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
        ))
    }

    fn result(
        state: Arc<Mutex<ApcState>>,
        rc: u32,
        data_confirmed: Option<&[u8]>,
        confirmation_token: Option<&[u8]>,
    ) {
        let mut state = state.lock().unwrap();
        let (callback, uid, start, client_aborted) = match state.session.take() {
            None => return, // Nothing to do
            Some(ApcSessionState { cb: callback, uid, start, client_aborted, .. }) => {
                (callback, uid, start, client_aborted)
            }
        };

        let rc = compat_2_response_code(rc);

        // Update rate limiting information.
        match (rc, client_aborted, confirmation_token) {
            // If the user confirmed the dialog.
            (ResponseCode::OK, _, Some(confirmation_token)) => {
                // Reset counter.
                state.rate_limiting.remove(&uid);
                // Send confirmation token to the enforcement module.
                if let Err(e) = state.confirmation_token_sender.send(confirmation_token.to_vec()) {
                    log::error!("Got confirmation token, but receiver would not have it. {:?}", e);
                }
            }
            // If cancelled by the user or if aborted by the client.
            (ResponseCode::CANCELLED, _, _) | (ResponseCode::ABORTED, true, _) => {
                // Penalize.
                let rate_info = state.rate_limiting.entry(uid).or_default();
                rate_info.counter += 1;
                rate_info.timestamp = start;
            }
            (ResponseCode::OK, _, None) => {
                log::error!(
                    "Confirmation prompt was successful but no confirmation token was returned."
                );
            }
            // In any other case this try does not count at all.
            _ => {}
        }
        drop(state);

        if let Ok(listener) = callback.into_interface::<dyn IConfirmationCallback>() {
            if let Err(e) = listener.onCompleted(rc, data_confirmed) {
                log::error!("Reporting completion to client failed {:?}", e)
            }
        } else {
            log::error!("SpIBinder is not a IConfirmationCallback.");
        }
    }

    fn present_prompt(
        &self,
        listener: &binder::Strong<dyn IConfirmationCallback>,
        prompt_text: &str,
        extra_data: &[u8],
        locale: &str,
        ui_option_flags: i32,
    ) -> Result<()> {
        let mut state = self.state.lock().unwrap();
        if state.session.is_some() {
            return Err(Error::pending()).context(ks_err!("APC Session pending."));
        }

        // Perform rate limiting.
        let uid = ThreadState::get_calling_uid();
        match state.rate_limiting.get(&uid) {
            None => {}
            Some(rate_info) => {
                if let Some(back_off) = rate_info.get_remaining_back_off() {
                    return Err(Error::sys()).context(ks_err!(
                        "APC Cooling down. Remaining back-off: {}s",
                        back_off.as_secs()
                    ));
                }
            }
        }

        let hal = ApcHal::try_get_service();
        let hal = match hal {
            None => {
                return Err(Error::unimplemented()).context(ks_err!("APC not supported."));
            }
            Some(h) => Arc::new(h),
        };

        let ui_opts = ui_opts_2_compat(ui_option_flags);

        let state_clone = self.state.clone();
        hal.prompt_user_confirmation(
            prompt_text,
            extra_data,
            locale,
            ui_opts,
            move |rc, data_confirmed, confirmation_token| {
                Self::result(state_clone, rc, data_confirmed, confirmation_token)
            },
        )
        .map_err(|rc| Error::Rc(compat_2_response_code(rc)))
        .context(ks_err!("APC Failed to present prompt."))?;
        state.session = Some(ApcSessionState {
            hal,
            cb: listener.as_binder(),
            uid,
            start: Instant::now(),
            client_aborted: false,
        });
        Ok(())
    }

    fn cancel_prompt(&self, listener: &binder::Strong<dyn IConfirmationCallback>) -> Result<()> {
        let mut state = self.state.lock().unwrap();
        let hal = match &mut state.session {
            None => {
                return Err(Error::ignored())
                    .context(ks_err!("Attempt to cancel non existing session. Ignoring."));
            }
            Some(session) => {
                if session.cb != listener.as_binder() {
                    return Err(Error::ignored()).context(ks_err!(
                        "Attempt to cancel session not belonging to caller. Ignoring."
                    ));
                }
                session.client_aborted = true;
                session.hal.clone()
            }
        };
        drop(state);
        hal.abort();
        Ok(())
    }

    fn is_supported() -> Result<bool> {
        Ok(ApcHal::try_get_service().is_some())
    }
}

impl IProtectedConfirmation for ApcManager {
    fn presentPrompt(
        &self,
        listener: &binder::Strong<dyn IConfirmationCallback>,
        prompt_text: &str,
        extra_data: &[u8],
        locale: &str,
        ui_option_flags: i32,
    ) -> BinderResult<()> {
        // presentPrompt can take more time than other operations.
        let _wp = wd::watch_millis("IProtectedConfirmation::presentPrompt", 3000);
        self.present_prompt(listener, prompt_text, extra_data, locale, ui_option_flags)
            .map_err(into_logged_binder)
    }
    fn cancelPrompt(
        &self,
        listener: &binder::Strong<dyn IConfirmationCallback>,
    ) -> BinderResult<()> {
        let _wp = wd::watch("IProtectedConfirmation::cancelPrompt");
        self.cancel_prompt(listener).map_err(into_logged_binder)
    }
    fn isSupported(&self) -> BinderResult<bool> {
        let _wp = wd::watch("IProtectedConfirmation::isSupported");
        Self::is_supported().map_err(into_logged_binder)
    }
}
