1cc290419Sopenharmony_ci/* 2cc290419Sopenharmony_ci * Copyright (C) 2023 Huawei Device Co., Ltd. 3cc290419Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4cc290419Sopenharmony_ci * you may not use this file except in compliance with the License. 5cc290419Sopenharmony_ci * You may obtain a copy of the License at 6cc290419Sopenharmony_ci * 7cc290419Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8cc290419Sopenharmony_ci * 9cc290419Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10cc290419Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11cc290419Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12cc290419Sopenharmony_ci * See the License for the specific language governing permissions and 13cc290419Sopenharmony_ci * limitations under the License. 14cc290419Sopenharmony_ci */ 15cc290419Sopenharmony_ci//! auth 16cc290419Sopenharmony_ci#![allow(missing_docs)] 17cc290419Sopenharmony_ci 18cc290419Sopenharmony_ciuse crate::common::base::Base; 19cc290419Sopenharmony_ciuse crate::common::hdctransfer::echo_client; 20cc290419Sopenharmony_ciuse crate::config::{self, *}; 21cc290419Sopenharmony_ciuse crate::serializer::native_struct; 22cc290419Sopenharmony_ciuse crate::serializer::serialize::Serialization; 23cc290419Sopenharmony_ciuse crate::{transfer, utils}; 24cc290419Sopenharmony_ci 25cc290419Sopenharmony_ciuse openssl::base64; 26cc290419Sopenharmony_ciuse openssl::rsa::{Padding, Rsa}; 27cc290419Sopenharmony_ciuse ylong_runtime::sync::RwLock; 28cc290419Sopenharmony_ci 29cc290419Sopenharmony_ciuse crate::daemon_lib::sys_para::*; 30cc290419Sopenharmony_ciuse crate::utils::hdc_log::*; 31cc290419Sopenharmony_ciuse std::collections::HashMap; 32cc290419Sopenharmony_ciuse std::fs::File; 33cc290419Sopenharmony_ciuse std::io::{self, prelude::*, Error, ErrorKind, Write}; 34cc290419Sopenharmony_ciuse std::path::Path; 35cc290419Sopenharmony_ciuse std::process::Command; 36cc290419Sopenharmony_ciuse std::string::ToString; 37cc290419Sopenharmony_ciuse std::sync::Arc; 38cc290419Sopenharmony_ci 39cc290419Sopenharmony_ci#[derive(Clone, PartialEq, Eq, Debug)] 40cc290419Sopenharmony_cipub enum AuthStatus { 41cc290419Sopenharmony_ci BasC(bool), // basic channel created 42cc290419Sopenharmony_ci Init(String), // with plain 43cc290419Sopenharmony_ci Pubk(String, String, String), // with (plain, pubkey, confirm msg) 44cc290419Sopenharmony_ci Reject(String), // with notify msg 45cc290419Sopenharmony_ci Ok, 46cc290419Sopenharmony_ci Fail, 47cc290419Sopenharmony_ci} 48cc290419Sopenharmony_ci 49cc290419Sopenharmony_cipub enum UserPermit { 50cc290419Sopenharmony_ci Refuse = 0, 51cc290419Sopenharmony_ci AllowOnce = 1, 52cc290419Sopenharmony_ci AllowForever = 2, 53cc290419Sopenharmony_ci} 54cc290419Sopenharmony_ci 55cc290419Sopenharmony_citype AuthStatusMap_ = Arc<RwLock<HashMap<u32, AuthStatus>>>; 56cc290419Sopenharmony_ci 57cc290419Sopenharmony_cipub struct AuthStatusMap {} 58cc290419Sopenharmony_ciimpl AuthStatusMap { 59cc290419Sopenharmony_ci fn get_instance() -> AuthStatusMap_ { 60cc290419Sopenharmony_ci static mut AUTH_STATUS_MAP: Option<AuthStatusMap_> = None; 61cc290419Sopenharmony_ci unsafe { 62cc290419Sopenharmony_ci AUTH_STATUS_MAP 63cc290419Sopenharmony_ci .get_or_insert_with(|| Arc::new(RwLock::new(HashMap::new()))) 64cc290419Sopenharmony_ci .clone() 65cc290419Sopenharmony_ci } 66cc290419Sopenharmony_ci } 67cc290419Sopenharmony_ci 68cc290419Sopenharmony_ci pub async fn get(session_id: u32) -> AuthStatus { 69cc290419Sopenharmony_ci let instance = Self::get_instance(); 70cc290419Sopenharmony_ci let map = instance.read().await; 71cc290419Sopenharmony_ci map.get(&session_id) 72cc290419Sopenharmony_ci .unwrap_or(&AuthStatus::BasC(false)) 73cc290419Sopenharmony_ci .clone() 74cc290419Sopenharmony_ci } 75cc290419Sopenharmony_ci 76cc290419Sopenharmony_ci async fn put(session_id: u32, auth_status: AuthStatus) { 77cc290419Sopenharmony_ci crate::info!( 78cc290419Sopenharmony_ci "update auth status {:?} for session {}", 79cc290419Sopenharmony_ci auth_status, 80cc290419Sopenharmony_ci session_id 81cc290419Sopenharmony_ci ); 82cc290419Sopenharmony_ci let instance = Self::get_instance(); 83cc290419Sopenharmony_ci let mut map = instance.write().await; 84cc290419Sopenharmony_ci map.insert(session_id, auth_status); 85cc290419Sopenharmony_ci } 86cc290419Sopenharmony_ci 87cc290419Sopenharmony_ci pub async fn remove(session_id: u32) { 88cc290419Sopenharmony_ci crate::info!( 89cc290419Sopenharmony_ci "remove auth status for session {}", 90cc290419Sopenharmony_ci session_id 91cc290419Sopenharmony_ci ); 92cc290419Sopenharmony_ci let instance = Self::get_instance(); 93cc290419Sopenharmony_ci let mut map = instance.write().await; 94cc290419Sopenharmony_ci let _ = map.remove(&session_id); 95cc290419Sopenharmony_ci } 96cc290419Sopenharmony_ci} 97cc290419Sopenharmony_ci 98cc290419Sopenharmony_cipub async fn handshake_init(task_message: TaskMessage) -> io::Result<(u32, TaskMessage)> { 99cc290419Sopenharmony_ci if task_message.command != HdcCommand::KernelHandshake { 100cc290419Sopenharmony_ci return Err(Error::new(ErrorKind::Other, "unknown command flag")); 101cc290419Sopenharmony_ci } 102cc290419Sopenharmony_ci 103cc290419Sopenharmony_ci let mut recv = native_struct::SessionHandShake::default(); 104cc290419Sopenharmony_ci recv.parse(task_message.payload)?; 105cc290419Sopenharmony_ci 106cc290419Sopenharmony_ci crate::info!("recv handshake: {:#?}", recv); 107cc290419Sopenharmony_ci if recv.banner != HANDSHAKE_MESSAGE { 108cc290419Sopenharmony_ci return Err(Error::new(ErrorKind::Other, "Recv server-hello failed")); 109cc290419Sopenharmony_ci } 110cc290419Sopenharmony_ci 111cc290419Sopenharmony_ci let session_id = recv.session_id; 112cc290419Sopenharmony_ci let channel_id = task_message.channel_id; 113cc290419Sopenharmony_ci let host_ver = recv.version.as_str(); 114cc290419Sopenharmony_ci 115cc290419Sopenharmony_ci crate::info!("client version({}) for session:{}", host_ver, session_id); 116cc290419Sopenharmony_ci create_basic_channel(session_id, channel_id, host_ver).await; 117cc290419Sopenharmony_ci 118cc290419Sopenharmony_ci if host_ver < AUTH_BASE_VERSDION { 119cc290419Sopenharmony_ci crate::info!( 120cc290419Sopenharmony_ci "client version({}) is too low, return OK for session:{}", 121cc290419Sopenharmony_ci host_ver, 122cc290419Sopenharmony_ci recv.session_id 123cc290419Sopenharmony_ci ); 124cc290419Sopenharmony_ci send_reject_message(session_id, channel_id, host_ver).await; 125cc290419Sopenharmony_ci return Ok(( 126cc290419Sopenharmony_ci recv.session_id, 127cc290419Sopenharmony_ci make_channel_close_message(channel_id).await, 128cc290419Sopenharmony_ci )); 129cc290419Sopenharmony_ci } 130cc290419Sopenharmony_ci if !is_auth_enable() { 131cc290419Sopenharmony_ci crate::info!( 132cc290419Sopenharmony_ci "auth enable is false, return OK for session:{}", 133cc290419Sopenharmony_ci recv.session_id 134cc290419Sopenharmony_ci ); 135cc290419Sopenharmony_ci return Ok(( 136cc290419Sopenharmony_ci recv.session_id, 137cc290419Sopenharmony_ci make_ok_message(session_id, channel_id).await, 138cc290419Sopenharmony_ci )); 139cc290419Sopenharmony_ci } 140cc290419Sopenharmony_ci 141cc290419Sopenharmony_ci // auth is required 142cc290419Sopenharmony_ci let buf = generate_token_wait().await; 143cc290419Sopenharmony_ci 144cc290419Sopenharmony_ci AuthStatusMap::put(session_id, AuthStatus::Init(buf.clone())).await; 145cc290419Sopenharmony_ci 146cc290419Sopenharmony_ci let send = native_struct::SessionHandShake { 147cc290419Sopenharmony_ci banner: HANDSHAKE_MESSAGE.to_string(), 148cc290419Sopenharmony_ci session_id, 149cc290419Sopenharmony_ci connect_key: "".to_string(), 150cc290419Sopenharmony_ci buf, 151cc290419Sopenharmony_ci auth_type: AuthType::Publickey as u8, 152cc290419Sopenharmony_ci version: get_version(), 153cc290419Sopenharmony_ci }; 154cc290419Sopenharmony_ci 155cc290419Sopenharmony_ci crate::info!("send handshake: {:?}", send); 156cc290419Sopenharmony_ci let message = TaskMessage { 157cc290419Sopenharmony_ci channel_id, 158cc290419Sopenharmony_ci command: HdcCommand::KernelHandshake, 159cc290419Sopenharmony_ci payload: send.serialize(), 160cc290419Sopenharmony_ci }; 161cc290419Sopenharmony_ci Ok((session_id, message)) 162cc290419Sopenharmony_ci} 163cc290419Sopenharmony_ci 164cc290419Sopenharmony_ciasync fn make_sign_message(session_id: u32, token: String, channel_id: u32) -> TaskMessage { 165cc290419Sopenharmony_ci let send = native_struct::SessionHandShake { 166cc290419Sopenharmony_ci banner: HANDSHAKE_MESSAGE.to_string(), 167cc290419Sopenharmony_ci session_id, 168cc290419Sopenharmony_ci connect_key: "".to_string(), 169cc290419Sopenharmony_ci buf: token, 170cc290419Sopenharmony_ci auth_type: AuthType::Signature as u8, 171cc290419Sopenharmony_ci version: get_version(), 172cc290419Sopenharmony_ci }; 173cc290419Sopenharmony_ci TaskMessage { 174cc290419Sopenharmony_ci channel_id, 175cc290419Sopenharmony_ci command: HdcCommand::KernelHandshake, 176cc290419Sopenharmony_ci payload: send.serialize(), 177cc290419Sopenharmony_ci } 178cc290419Sopenharmony_ci} 179cc290419Sopenharmony_ci 180cc290419Sopenharmony_ciasync fn make_bypass_message(session_id: u32, channel_id: u32, host_ver: &str) -> TaskMessage { 181cc290419Sopenharmony_ci let mut handshake_msg = "".to_string(); 182cc290419Sopenharmony_ci let hostname = get_hostname(); 183cc290419Sopenharmony_ci if host_ver < AUTH_BASE_VERSDION { 184cc290419Sopenharmony_ci handshake_msg = hostname; 185cc290419Sopenharmony_ci } else { 186cc290419Sopenharmony_ci handshake_msg = Base::tlv_append(handshake_msg, config::TAG_DEVNAME, hostname.as_str()); 187cc290419Sopenharmony_ci if is_auth_enable() { 188cc290419Sopenharmony_ci handshake_msg = Base::tlv_append(handshake_msg, config::TAG_DAEOMN_AUTHSTATUS, DAEOMN_UNAUTHORIZED); 189cc290419Sopenharmony_ci } 190cc290419Sopenharmony_ci } 191cc290419Sopenharmony_ci 192cc290419Sopenharmony_ci let send = native_struct::SessionHandShake { 193cc290419Sopenharmony_ci banner: HANDSHAKE_MESSAGE.to_string(), 194cc290419Sopenharmony_ci session_id, 195cc290419Sopenharmony_ci connect_key: "".to_string(), 196cc290419Sopenharmony_ci auth_type: AuthType::OK as u8, 197cc290419Sopenharmony_ci version: get_version(), 198cc290419Sopenharmony_ci buf: handshake_msg, 199cc290419Sopenharmony_ci }; 200cc290419Sopenharmony_ci TaskMessage { 201cc290419Sopenharmony_ci channel_id, 202cc290419Sopenharmony_ci command: HdcCommand::KernelHandshake, 203cc290419Sopenharmony_ci payload: send.serialize(), 204cc290419Sopenharmony_ci } 205cc290419Sopenharmony_ci} 206cc290419Sopenharmony_ci 207cc290419Sopenharmony_ciasync fn create_basic_channel(session_id: u32, channel_id: u32, host_ver: &str) { 208cc290419Sopenharmony_ci if let AuthStatus::BasC(created) = AuthStatusMap::get(session_id).await { 209cc290419Sopenharmony_ci if !created { 210cc290419Sopenharmony_ci transfer::put( 211cc290419Sopenharmony_ci session_id, 212cc290419Sopenharmony_ci make_bypass_message(session_id, channel_id, host_ver).await, 213cc290419Sopenharmony_ci ) 214cc290419Sopenharmony_ci .await; 215cc290419Sopenharmony_ci crate::info!( 216cc290419Sopenharmony_ci "create_basic_channel created success for session {}", 217cc290419Sopenharmony_ci session_id 218cc290419Sopenharmony_ci ); 219cc290419Sopenharmony_ci AuthStatusMap::put(session_id, AuthStatus::BasC(true)).await; 220cc290419Sopenharmony_ci } 221cc290419Sopenharmony_ci } 222cc290419Sopenharmony_ci crate::info!( 223cc290419Sopenharmony_ci "create_basic_channel already created for session {}", 224cc290419Sopenharmony_ci session_id 225cc290419Sopenharmony_ci ); 226cc290419Sopenharmony_ci} 227cc290419Sopenharmony_ci 228cc290419Sopenharmony_ciasync fn make_emg_message(session_id: u32, channel_id: u32, emgmsg: &str) -> TaskMessage { 229cc290419Sopenharmony_ci let mut handshake_msg = "".to_string(); 230cc290419Sopenharmony_ci let hostname = get_hostname(); 231cc290419Sopenharmony_ci 232cc290419Sopenharmony_ci handshake_msg = Base::tlv_append(handshake_msg, config::TAG_DEVNAME, hostname.as_str()); 233cc290419Sopenharmony_ci handshake_msg = Base::tlv_append(handshake_msg, config::TAG_EMGMSG, emgmsg); 234cc290419Sopenharmony_ci handshake_msg = Base::tlv_append(handshake_msg, config::TAG_DAEOMN_AUTHSTATUS, DAEOMN_UNAUTHORIZED); 235cc290419Sopenharmony_ci 236cc290419Sopenharmony_ci let send = native_struct::SessionHandShake { 237cc290419Sopenharmony_ci banner: HANDSHAKE_MESSAGE.to_string(), 238cc290419Sopenharmony_ci session_id, 239cc290419Sopenharmony_ci connect_key: "".to_string(), 240cc290419Sopenharmony_ci auth_type: AuthType::OK as u8, 241cc290419Sopenharmony_ci version: get_version(), 242cc290419Sopenharmony_ci buf: handshake_msg, 243cc290419Sopenharmony_ci }; 244cc290419Sopenharmony_ci TaskMessage { 245cc290419Sopenharmony_ci channel_id, 246cc290419Sopenharmony_ci command: HdcCommand::KernelHandshake, 247cc290419Sopenharmony_ci payload: send.serialize(), 248cc290419Sopenharmony_ci } 249cc290419Sopenharmony_ci} 250cc290419Sopenharmony_ci 251cc290419Sopenharmony_ciasync fn make_reject_message( 252cc290419Sopenharmony_ci session_id: u32, 253cc290419Sopenharmony_ci channel_id: u32, 254cc290419Sopenharmony_ci host_ver: &str, 255cc290419Sopenharmony_ci emgmsg: &str, 256cc290419Sopenharmony_ci) -> TaskMessage { 257cc290419Sopenharmony_ci let mut handshake_msg = "".to_string(); 258cc290419Sopenharmony_ci let hostname = get_hostname(); 259cc290419Sopenharmony_ci if host_ver < AUTH_BASE_VERSDION { 260cc290419Sopenharmony_ci handshake_msg = hostname; 261cc290419Sopenharmony_ci } else { 262cc290419Sopenharmony_ci handshake_msg = Base::tlv_append(handshake_msg, config::TAG_DEVNAME, hostname.as_str()); 263cc290419Sopenharmony_ci handshake_msg = Base::tlv_append(handshake_msg, config::TAG_EMGMSG, emgmsg); 264cc290419Sopenharmony_ci } 265cc290419Sopenharmony_ci 266cc290419Sopenharmony_ci let send = native_struct::SessionHandShake { 267cc290419Sopenharmony_ci banner: HANDSHAKE_MESSAGE.to_string(), 268cc290419Sopenharmony_ci session_id, 269cc290419Sopenharmony_ci connect_key: "".to_string(), 270cc290419Sopenharmony_ci auth_type: AuthType::OK as u8, 271cc290419Sopenharmony_ci version: get_version(), 272cc290419Sopenharmony_ci buf: handshake_msg, 273cc290419Sopenharmony_ci }; 274cc290419Sopenharmony_ci TaskMessage { 275cc290419Sopenharmony_ci channel_id, 276cc290419Sopenharmony_ci command: HdcCommand::KernelHandshake, 277cc290419Sopenharmony_ci payload: send.serialize(), 278cc290419Sopenharmony_ci } 279cc290419Sopenharmony_ci} 280cc290419Sopenharmony_ci 281cc290419Sopenharmony_ciasync fn send_reject_message(session_id: u32, channel_id: u32, host_ver: &str) { 282cc290419Sopenharmony_ci crate::info!("send_reject_message for session {}", session_id); 283cc290419Sopenharmony_ci let msg = "[E000001]:The sdk hdc.exe version is too low, please upgrade to the latest version."; 284cc290419Sopenharmony_ci echo_client(session_id, channel_id, msg, MessageLevel::Fail).await; 285cc290419Sopenharmony_ci transfer::put( 286cc290419Sopenharmony_ci session_id, 287cc290419Sopenharmony_ci make_reject_message(session_id, channel_id, host_ver, msg).await, 288cc290419Sopenharmony_ci ) 289cc290419Sopenharmony_ci .await; 290cc290419Sopenharmony_ci AuthStatusMap::put(session_id, AuthStatus::Reject(msg.to_string())).await; 291cc290419Sopenharmony_ci} 292cc290419Sopenharmony_ci 293cc290419Sopenharmony_ciasync fn make_ok_message(session_id: u32, channel_id: u32) -> TaskMessage { 294cc290419Sopenharmony_ci crate::info!("make_ok_message for session {}", session_id); 295cc290419Sopenharmony_ci AuthStatusMap::put(session_id, AuthStatus::Ok).await; 296cc290419Sopenharmony_ci 297cc290419Sopenharmony_ci let mut succmsg = "".to_string(); 298cc290419Sopenharmony_ci let hostname = get_hostname(); 299cc290419Sopenharmony_ci succmsg = Base::tlv_append(succmsg, config::TAG_DEVNAME, hostname.as_str()); 300cc290419Sopenharmony_ci if succmsg.is_empty() { 301cc290419Sopenharmony_ci crate::error!( 302cc290419Sopenharmony_ci "append {} failed for session {}", 303cc290419Sopenharmony_ci config::TAG_DEVNAME, 304cc290419Sopenharmony_ci session_id 305cc290419Sopenharmony_ci ); 306cc290419Sopenharmony_ci } 307cc290419Sopenharmony_ci succmsg = Base::tlv_append( 308cc290419Sopenharmony_ci succmsg, 309cc290419Sopenharmony_ci config::TAG_DAEOMN_AUTHSTATUS, 310cc290419Sopenharmony_ci config::DAEOMN_AUTH_SUCCESS, 311cc290419Sopenharmony_ci ); 312cc290419Sopenharmony_ci if succmsg.is_empty() { 313cc290419Sopenharmony_ci crate::error!( 314cc290419Sopenharmony_ci "append {} failed for session {}", 315cc290419Sopenharmony_ci config::TAG_DAEOMN_AUTHSTATUS, 316cc290419Sopenharmony_ci session_id 317cc290419Sopenharmony_ci ); 318cc290419Sopenharmony_ci } 319cc290419Sopenharmony_ci succmsg = Base::tlv_append(succmsg, config::TAG_EMGMSG, ""); 320cc290419Sopenharmony_ci if succmsg.is_empty() { 321cc290419Sopenharmony_ci crate::error!( 322cc290419Sopenharmony_ci "append {} failed for session {}", 323cc290419Sopenharmony_ci config::TAG_EMGMSG, 324cc290419Sopenharmony_ci session_id 325cc290419Sopenharmony_ci ); 326cc290419Sopenharmony_ci } 327cc290419Sopenharmony_ci 328cc290419Sopenharmony_ci let send = native_struct::SessionHandShake { 329cc290419Sopenharmony_ci banner: HANDSHAKE_MESSAGE.to_string(), 330cc290419Sopenharmony_ci session_id, 331cc290419Sopenharmony_ci connect_key: "".to_string(), 332cc290419Sopenharmony_ci auth_type: AuthType::OK as u8, 333cc290419Sopenharmony_ci version: get_version(), 334cc290419Sopenharmony_ci buf: succmsg, 335cc290419Sopenharmony_ci }; 336cc290419Sopenharmony_ci TaskMessage { 337cc290419Sopenharmony_ci channel_id, 338cc290419Sopenharmony_ci command: HdcCommand::KernelHandshake, 339cc290419Sopenharmony_ci payload: send.serialize(), 340cc290419Sopenharmony_ci } 341cc290419Sopenharmony_ci} 342cc290419Sopenharmony_cipub async fn get_auth_msg(session_id: u32) -> String { 343cc290419Sopenharmony_ci match AuthStatusMap::get(session_id).await { 344cc290419Sopenharmony_ci AuthStatus::BasC(_) => "Error request.".to_string(), 345cc290419Sopenharmony_ci AuthStatus::Init(_) => "Wait handshake init finish.".to_string(), 346cc290419Sopenharmony_ci AuthStatus::Pubk(_, _, confirm) => { 347cc290419Sopenharmony_ci if confirm.is_empty() { 348cc290419Sopenharmony_ci "Wait handshake public key and signure.".to_string() 349cc290419Sopenharmony_ci } else { 350cc290419Sopenharmony_ci confirm 351cc290419Sopenharmony_ci } 352cc290419Sopenharmony_ci } 353cc290419Sopenharmony_ci AuthStatus::Reject(reject) => reject, 354cc290419Sopenharmony_ci AuthStatus::Ok => "There seems nothing wrong.".to_string(), 355cc290419Sopenharmony_ci AuthStatus::Fail => "Internal error.".to_string(), 356cc290419Sopenharmony_ci } 357cc290419Sopenharmony_ci} 358cc290419Sopenharmony_cipub async fn make_channel_close_message(channel_id: u32) -> TaskMessage { 359cc290419Sopenharmony_ci crate::debug!("make_channel_close_message: channel {channel_id}"); 360cc290419Sopenharmony_ci TaskMessage { 361cc290419Sopenharmony_ci channel_id, 362cc290419Sopenharmony_ci command: HdcCommand::KernelChannelClose, 363cc290419Sopenharmony_ci payload: vec![0], 364cc290419Sopenharmony_ci } 365cc290419Sopenharmony_ci} 366cc290419Sopenharmony_cipub fn get_host_pubkey_info(buf: &str) -> (String, String) { 367cc290419Sopenharmony_ci if let Some((hostname, pubkey)) = buf.split_once(HDC_HOST_DAEMON_BUF_SEPARATOR) { 368cc290419Sopenharmony_ci (hostname.to_string(), pubkey.to_string()) 369cc290419Sopenharmony_ci } else { 370cc290419Sopenharmony_ci ("".to_string(), "".to_string()) 371cc290419Sopenharmony_ci } 372cc290419Sopenharmony_ci} 373cc290419Sopenharmony_ci 374cc290419Sopenharmony_cipub async fn get_session_id_from_msg(task_message: &TaskMessage) -> io::Result<u32> { 375cc290419Sopenharmony_ci let mut recv = native_struct::SessionHandShake::default(); 376cc290419Sopenharmony_ci recv.parse(task_message.payload.clone())?; 377cc290419Sopenharmony_ci Ok(recv.session_id) 378cc290419Sopenharmony_ci} 379cc290419Sopenharmony_ci 380cc290419Sopenharmony_cipub async fn handshake_init_new(session_id: u32, channel_id: u32) -> io::Result<()> { 381cc290419Sopenharmony_ci let buf = generate_token_wait().await; 382cc290419Sopenharmony_ci AuthStatusMap::put(session_id, AuthStatus::Init(buf.clone())).await; 383cc290419Sopenharmony_ci 384cc290419Sopenharmony_ci let send = native_struct::SessionHandShake { 385cc290419Sopenharmony_ci banner: HANDSHAKE_MESSAGE.to_string(), 386cc290419Sopenharmony_ci session_id, 387cc290419Sopenharmony_ci connect_key: "".to_string(), 388cc290419Sopenharmony_ci buf, 389cc290419Sopenharmony_ci auth_type: AuthType::Publickey as u8, 390cc290419Sopenharmony_ci version: get_version(), 391cc290419Sopenharmony_ci }; 392cc290419Sopenharmony_ci 393cc290419Sopenharmony_ci crate::info!("send handshake: {:?}", send); 394cc290419Sopenharmony_ci let message = TaskMessage { 395cc290419Sopenharmony_ci channel_id, 396cc290419Sopenharmony_ci command: HdcCommand::KernelHandshake, 397cc290419Sopenharmony_ci payload: send.serialize(), 398cc290419Sopenharmony_ci }; 399cc290419Sopenharmony_ci 400cc290419Sopenharmony_ci transfer::put(session_id, message).await; 401cc290419Sopenharmony_ci Ok(()) 402cc290419Sopenharmony_ci} 403cc290419Sopenharmony_ci 404cc290419Sopenharmony_cipub async fn handshake_deal_pubkey( 405cc290419Sopenharmony_ci session_id: u32, 406cc290419Sopenharmony_ci channel_id: u32, 407cc290419Sopenharmony_ci token: String, 408cc290419Sopenharmony_ci buf: String, 409cc290419Sopenharmony_ci) -> io::Result<()> { 410cc290419Sopenharmony_ci let (hostname, pubkey) = get_host_pubkey_info(buf.trim()); 411cc290419Sopenharmony_ci if pubkey.is_empty() { 412cc290419Sopenharmony_ci crate::error!("get public key from host failed"); 413cc290419Sopenharmony_ci handshake_fail( 414cc290419Sopenharmony_ci session_id, 415cc290419Sopenharmony_ci channel_id, 416cc290419Sopenharmony_ci "no public key, you may need update your hdc client".to_string(), 417cc290419Sopenharmony_ci ) 418cc290419Sopenharmony_ci .await; 419cc290419Sopenharmony_ci return Ok(()); 420cc290419Sopenharmony_ci } 421cc290419Sopenharmony_ci if hostname.is_empty() { 422cc290419Sopenharmony_ci crate::error!("get hostname from host failed"); 423cc290419Sopenharmony_ci handshake_fail( 424cc290419Sopenharmony_ci session_id, 425cc290419Sopenharmony_ci channel_id, 426cc290419Sopenharmony_ci "no hostname, you may need update your hdc client".to_string(), 427cc290419Sopenharmony_ci ) 428cc290419Sopenharmony_ci .await; 429cc290419Sopenharmony_ci return Ok(()); 430cc290419Sopenharmony_ci } 431cc290419Sopenharmony_ci 432cc290419Sopenharmony_ci let known_hosts = read_known_hosts_pubkey(); 433cc290419Sopenharmony_ci if known_hosts.contains(&pubkey) { 434cc290419Sopenharmony_ci crate::info!("pubkey matches known host({})", hostname); 435cc290419Sopenharmony_ci AuthStatusMap::put( 436cc290419Sopenharmony_ci session_id, 437cc290419Sopenharmony_ci AuthStatus::Pubk(token.clone(), pubkey, "".to_string()), 438cc290419Sopenharmony_ci ) 439cc290419Sopenharmony_ci .await; 440cc290419Sopenharmony_ci transfer::put( 441cc290419Sopenharmony_ci session_id, 442cc290419Sopenharmony_ci make_sign_message(session_id, token.clone(), channel_id).await, 443cc290419Sopenharmony_ci ) 444cc290419Sopenharmony_ci .await; 445cc290419Sopenharmony_ci return Ok(()); 446cc290419Sopenharmony_ci } 447cc290419Sopenharmony_ci let confirmmsg = concat!( 448cc290419Sopenharmony_ci "[E000002]:The device unauthorized.\n", 449cc290419Sopenharmony_ci "This server's public key is not set.\n", 450cc290419Sopenharmony_ci "Please check for a confirmation dialog on your device.\n", 451cc290419Sopenharmony_ci "Otherwise try 'hdc kill' if that seems wrong." 452cc290419Sopenharmony_ci ); 453cc290419Sopenharmony_ci AuthStatusMap::put( 454cc290419Sopenharmony_ci session_id, 455cc290419Sopenharmony_ci AuthStatus::Pubk(token.clone(), pubkey.clone(), confirmmsg.to_string()), 456cc290419Sopenharmony_ci ) 457cc290419Sopenharmony_ci .await; 458cc290419Sopenharmony_ci utils::spawn(async move { 459cc290419Sopenharmony_ci echo_client( 460cc290419Sopenharmony_ci session_id, 461cc290419Sopenharmony_ci channel_id, 462cc290419Sopenharmony_ci confirmmsg, 463cc290419Sopenharmony_ci MessageLevel::Fail, 464cc290419Sopenharmony_ci ) 465cc290419Sopenharmony_ci .await; 466cc290419Sopenharmony_ci transfer::put( 467cc290419Sopenharmony_ci session_id, 468cc290419Sopenharmony_ci make_emg_message(session_id, channel_id, confirmmsg).await, 469cc290419Sopenharmony_ci ) 470cc290419Sopenharmony_ci .await; 471cc290419Sopenharmony_ci transfer::put(session_id, make_channel_close_message(channel_id).await).await; 472cc290419Sopenharmony_ci }); 473cc290419Sopenharmony_ci match require_user_permittion(&hostname).await { 474cc290419Sopenharmony_ci UserPermit::AllowForever => { 475cc290419Sopenharmony_ci crate::info!("allow forever"); 476cc290419Sopenharmony_ci if write_known_hosts_pubkey(&pubkey).is_err() { 477cc290419Sopenharmony_ci handshake_fail( 478cc290419Sopenharmony_ci session_id, 479cc290419Sopenharmony_ci channel_id, 480cc290419Sopenharmony_ci "write public key failed".to_string(), 481cc290419Sopenharmony_ci ) 482cc290419Sopenharmony_ci .await; 483cc290419Sopenharmony_ci 484cc290419Sopenharmony_ci crate::error!("write public key failed"); 485cc290419Sopenharmony_ci return Ok(()); 486cc290419Sopenharmony_ci } 487cc290419Sopenharmony_ci AuthStatusMap::put( 488cc290419Sopenharmony_ci session_id, 489cc290419Sopenharmony_ci AuthStatus::Pubk(token.clone(), pubkey, "".to_string()), 490cc290419Sopenharmony_ci ) 491cc290419Sopenharmony_ci .await; 492cc290419Sopenharmony_ci transfer::put( 493cc290419Sopenharmony_ci session_id, 494cc290419Sopenharmony_ci make_sign_message(session_id, token.clone(), channel_id).await, 495cc290419Sopenharmony_ci ) 496cc290419Sopenharmony_ci .await; 497cc290419Sopenharmony_ci } 498cc290419Sopenharmony_ci UserPermit::AllowOnce => { 499cc290419Sopenharmony_ci crate::info!("allow once"); 500cc290419Sopenharmony_ci AuthStatusMap::put( 501cc290419Sopenharmony_ci session_id, 502cc290419Sopenharmony_ci AuthStatus::Pubk(token.clone(), pubkey, "".to_string()), 503cc290419Sopenharmony_ci ) 504cc290419Sopenharmony_ci .await; 505cc290419Sopenharmony_ci transfer::put( 506cc290419Sopenharmony_ci session_id, 507cc290419Sopenharmony_ci make_sign_message(session_id, token.clone(), channel_id).await, 508cc290419Sopenharmony_ci ) 509cc290419Sopenharmony_ci .await; 510cc290419Sopenharmony_ci } 511cc290419Sopenharmony_ci _ => { 512cc290419Sopenharmony_ci crate::info!("user refuse"); 513cc290419Sopenharmony_ci let denymsg = concat!( 514cc290419Sopenharmony_ci "[E000003]:The device unauthorized.\n", 515cc290419Sopenharmony_ci "The user denied the access for the device.\n", 516cc290419Sopenharmony_ci "Please execute 'hdc kill' and redo your command, ", 517cc290419Sopenharmony_ci "then check for a confirmation dialog on your device." 518cc290419Sopenharmony_ci ); 519cc290419Sopenharmony_ci AuthStatusMap::put(session_id, AuthStatus::Reject(denymsg.to_string())).await; 520cc290419Sopenharmony_ci echo_client(session_id, channel_id, denymsg, MessageLevel::Fail).await; 521cc290419Sopenharmony_ci transfer::put( 522cc290419Sopenharmony_ci session_id, 523cc290419Sopenharmony_ci make_emg_message(session_id, channel_id, denymsg).await, 524cc290419Sopenharmony_ci ) 525cc290419Sopenharmony_ci .await; 526cc290419Sopenharmony_ci transfer::put(session_id, make_channel_close_message(channel_id).await).await; 527cc290419Sopenharmony_ci return Ok(()); 528cc290419Sopenharmony_ci } 529cc290419Sopenharmony_ci } 530cc290419Sopenharmony_ci Ok(()) 531cc290419Sopenharmony_ci} 532cc290419Sopenharmony_ci 533cc290419Sopenharmony_cipub async fn handshake_deal_signature( 534cc290419Sopenharmony_ci session_id: u32, 535cc290419Sopenharmony_ci channel_id: u32, 536cc290419Sopenharmony_ci token: String, 537cc290419Sopenharmony_ci pubkey: String, 538cc290419Sopenharmony_ci buf: String, 539cc290419Sopenharmony_ci) -> io::Result<()> { 540cc290419Sopenharmony_ci match validate_signature(token, pubkey, buf).await { 541cc290419Sopenharmony_ci Ok(()) => { 542cc290419Sopenharmony_ci crate::info!("user Signature"); 543cc290419Sopenharmony_ci transfer::put(session_id, make_ok_message(session_id, channel_id).await).await; 544cc290419Sopenharmony_ci transfer::put(session_id, make_channel_close_message(channel_id).await).await; 545cc290419Sopenharmony_ci Ok(()) 546cc290419Sopenharmony_ci } 547cc290419Sopenharmony_ci Err(e) => { 548cc290419Sopenharmony_ci let errlog = e.to_string(); 549cc290419Sopenharmony_ci crate::error!("validate signature failed: {}", &errlog); 550cc290419Sopenharmony_ci handshake_fail(session_id, channel_id, errlog).await; 551cc290419Sopenharmony_ci Err(Error::new(ErrorKind::Other, "validate signature failed")) 552cc290419Sopenharmony_ci } 553cc290419Sopenharmony_ci } 554cc290419Sopenharmony_ci} 555cc290419Sopenharmony_ci 556cc290419Sopenharmony_cipub async fn handshake_task(task_message: TaskMessage, session_id: u32) -> io::Result<()> { 557cc290419Sopenharmony_ci if let AuthStatus::Ok = AuthStatusMap::get(session_id).await { 558cc290419Sopenharmony_ci crate::info!("session {} already auth ok", session_id); 559cc290419Sopenharmony_ci return Ok(()); 560cc290419Sopenharmony_ci } 561cc290419Sopenharmony_ci 562cc290419Sopenharmony_ci let mut recv = native_struct::SessionHandShake::default(); 563cc290419Sopenharmony_ci recv.parse(task_message.payload)?; 564cc290419Sopenharmony_ci crate::info!("recv handshake: {:?}", recv); 565cc290419Sopenharmony_ci if recv.banner != HANDSHAKE_MESSAGE { 566cc290419Sopenharmony_ci return Err(Error::new(ErrorKind::Other, "Recv server-hello failed")); 567cc290419Sopenharmony_ci } 568cc290419Sopenharmony_ci 569cc290419Sopenharmony_ci let session_id = recv.session_id; 570cc290419Sopenharmony_ci let channel_id = task_message.channel_id; 571cc290419Sopenharmony_ci let host_ver = recv.version.as_str(); 572cc290419Sopenharmony_ci 573cc290419Sopenharmony_ci crate::info!("client version({}) for session:{}", host_ver, session_id); 574cc290419Sopenharmony_ci 575cc290419Sopenharmony_ci if !is_auth_enable() { 576cc290419Sopenharmony_ci crate::info!("auth enable is false, return OK for session:{}", session_id); 577cc290419Sopenharmony_ci transfer::put(session_id, make_ok_message(session_id, channel_id).await).await; 578cc290419Sopenharmony_ci return Ok(()); 579cc290419Sopenharmony_ci } 580cc290419Sopenharmony_ci create_basic_channel(session_id, channel_id, host_ver).await; 581cc290419Sopenharmony_ci 582cc290419Sopenharmony_ci if host_ver < AUTH_BASE_VERSDION { 583cc290419Sopenharmony_ci crate::info!( 584cc290419Sopenharmony_ci "client version({}) is too low, cannt access for session:{}", 585cc290419Sopenharmony_ci host_ver, 586cc290419Sopenharmony_ci recv.session_id 587cc290419Sopenharmony_ci ); 588cc290419Sopenharmony_ci send_reject_message(session_id, channel_id, host_ver).await; 589cc290419Sopenharmony_ci transfer::put(session_id, make_channel_close_message(channel_id).await).await; 590cc290419Sopenharmony_ci return Err(Error::new(ErrorKind::Other, "client version is too low")); 591cc290419Sopenharmony_ci } 592cc290419Sopenharmony_ci 593cc290419Sopenharmony_ci match AuthStatusMap::get(session_id).await { 594cc290419Sopenharmony_ci AuthStatus::BasC(created) => { 595cc290419Sopenharmony_ci crate::info!( 596cc290419Sopenharmony_ci "auth status is BasC({}) for session {}", 597cc290419Sopenharmony_ci created, 598cc290419Sopenharmony_ci session_id 599cc290419Sopenharmony_ci ); 600cc290419Sopenharmony_ci if !created { 601cc290419Sopenharmony_ci create_basic_channel(session_id, channel_id, host_ver).await; 602cc290419Sopenharmony_ci } 603cc290419Sopenharmony_ci handshake_init_new(session_id, channel_id).await 604cc290419Sopenharmony_ci } 605cc290419Sopenharmony_ci AuthStatus::Init(token) => { 606cc290419Sopenharmony_ci crate::info!("auth status is Init() for session {}", session_id); 607cc290419Sopenharmony_ci if recv.auth_type != AuthType::Publickey as u8 { 608cc290419Sopenharmony_ci return Err(Error::new( 609cc290419Sopenharmony_ci ErrorKind::Other, 610cc290419Sopenharmony_ci "wrong command, need pubkey now", 611cc290419Sopenharmony_ci )); 612cc290419Sopenharmony_ci } 613cc290419Sopenharmony_ci handshake_deal_pubkey(session_id, channel_id, token, recv.buf).await 614cc290419Sopenharmony_ci } 615cc290419Sopenharmony_ci AuthStatus::Pubk(token, pubkey, confirm) => { 616cc290419Sopenharmony_ci crate::info!( 617cc290419Sopenharmony_ci "auth status is Pubk({}) for session {}", 618cc290419Sopenharmony_ci confirm, 619cc290419Sopenharmony_ci session_id 620cc290419Sopenharmony_ci ); 621cc290419Sopenharmony_ci if recv.auth_type != AuthType::Signature as u8 { 622cc290419Sopenharmony_ci return Err(Error::new( 623cc290419Sopenharmony_ci ErrorKind::Other, 624cc290419Sopenharmony_ci "wrong command, need signature now", 625cc290419Sopenharmony_ci )); 626cc290419Sopenharmony_ci } 627cc290419Sopenharmony_ci handshake_deal_signature(session_id, channel_id, token, pubkey, recv.buf).await 628cc290419Sopenharmony_ci } 629cc290419Sopenharmony_ci AuthStatus::Reject(reject) => { 630cc290419Sopenharmony_ci crate::info!( 631cc290419Sopenharmony_ci "auth status is Reject({}) for session {}", 632cc290419Sopenharmony_ci reject, 633cc290419Sopenharmony_ci session_id 634cc290419Sopenharmony_ci ); 635cc290419Sopenharmony_ci Ok(()) 636cc290419Sopenharmony_ci } 637cc290419Sopenharmony_ci AuthStatus::Ok => { 638cc290419Sopenharmony_ci crate::info!("auth status is Ok() for session {}", session_id); 639cc290419Sopenharmony_ci Ok(()) 640cc290419Sopenharmony_ci } 641cc290419Sopenharmony_ci AuthStatus::Fail => { 642cc290419Sopenharmony_ci crate::info!("auth status is Fail() for session {}", session_id); 643cc290419Sopenharmony_ci Ok(()) 644cc290419Sopenharmony_ci } 645cc290419Sopenharmony_ci } 646cc290419Sopenharmony_ci} 647cc290419Sopenharmony_ci 648cc290419Sopenharmony_ciasync fn validate_signature(plain: String, pubkey: String, signature: String) -> io::Result<()> { 649cc290419Sopenharmony_ci let signature_bytes = if let Ok(bytes) = base64::decode_block(&signature) { 650cc290419Sopenharmony_ci bytes 651cc290419Sopenharmony_ci } else { 652cc290419Sopenharmony_ci return Err(Error::new(ErrorKind::Other, "signature decode failed")); 653cc290419Sopenharmony_ci }; 654cc290419Sopenharmony_ci 655cc290419Sopenharmony_ci let rsa = if let Ok(cipher) = Rsa::public_key_from_pem(pubkey.as_bytes()) { 656cc290419Sopenharmony_ci cipher 657cc290419Sopenharmony_ci } else { 658cc290419Sopenharmony_ci return Err(Error::new(ErrorKind::Other, "pubkey convert failed")); 659cc290419Sopenharmony_ci }; 660cc290419Sopenharmony_ci 661cc290419Sopenharmony_ci let mut buf = vec![0_u8; config::RSA_BIT_NUM]; 662cc290419Sopenharmony_ci let dec_size = rsa 663cc290419Sopenharmony_ci .public_decrypt(&signature_bytes, &mut buf, Padding::PKCS1) 664cc290419Sopenharmony_ci .unwrap_or(0); 665cc290419Sopenharmony_ci 666cc290419Sopenharmony_ci if plain.as_bytes() == &buf[..dec_size] { 667cc290419Sopenharmony_ci Ok(()) 668cc290419Sopenharmony_ci } else { 669cc290419Sopenharmony_ci Err(Error::new(ErrorKind::Other, "signature not match")) 670cc290419Sopenharmony_ci } 671cc290419Sopenharmony_ci} 672cc290419Sopenharmony_ci 673cc290419Sopenharmony_cipub fn clear_auth_pub_key_file() { 674cc290419Sopenharmony_ci if !is_auth_enable() { 675cc290419Sopenharmony_ci return; 676cc290419Sopenharmony_ci } 677cc290419Sopenharmony_ci 678cc290419Sopenharmony_ci let (_, auth_cancel) = get_dev_item("persist.hdc.daemon.auth_cancel", "_"); 679cc290419Sopenharmony_ci if auth_cancel.trim().to_lowercase() != "true" { 680cc290419Sopenharmony_ci crate::info!("auth_cancel is {}, no need clear pubkey file", auth_cancel); 681cc290419Sopenharmony_ci return; 682cc290419Sopenharmony_ci } 683cc290419Sopenharmony_ci 684cc290419Sopenharmony_ci if !set_dev_item("persist.hdc.daemon.auth_cancel", "false") { 685cc290419Sopenharmony_ci crate::error!("clear param auth_cancel failed."); 686cc290419Sopenharmony_ci } 687cc290419Sopenharmony_ci 688cc290419Sopenharmony_ci let file_name = Path::new(config::RSA_PUBKEY_PATH).join(config::RSA_PUBKEY_NAME); 689cc290419Sopenharmony_ci match std::fs::remove_file(&file_name) { 690cc290419Sopenharmony_ci Ok(_) => { 691cc290419Sopenharmony_ci crate::info!("remove pubkey file {:?} success", file_name); 692cc290419Sopenharmony_ci } 693cc290419Sopenharmony_ci Err(err) => { 694cc290419Sopenharmony_ci crate::error!("remove pubkey file {:?} failed: {}", file_name, err); 695cc290419Sopenharmony_ci } 696cc290419Sopenharmony_ci } 697cc290419Sopenharmony_ci} 698cc290419Sopenharmony_ci 699cc290419Sopenharmony_cifn read_known_hosts_pubkey() -> Vec<String> { 700cc290419Sopenharmony_ci let file_name = Path::new(config::RSA_PUBKEY_PATH).join(config::RSA_PUBKEY_NAME); 701cc290419Sopenharmony_ci if let Ok(keys) = std::fs::read_to_string(&file_name) { 702cc290419Sopenharmony_ci let mut key_vec = vec![]; 703cc290419Sopenharmony_ci let mut tmp_vec = vec![]; 704cc290419Sopenharmony_ci 705cc290419Sopenharmony_ci for line in keys.split('\n') { 706cc290419Sopenharmony_ci if line.contains("BEGIN PUBLIC KEY") { 707cc290419Sopenharmony_ci tmp_vec.clear(); 708cc290419Sopenharmony_ci } 709cc290419Sopenharmony_ci tmp_vec.push(line); 710cc290419Sopenharmony_ci if line.contains("END PUBLIC KEY") { 711cc290419Sopenharmony_ci key_vec.push(tmp_vec.join("\n")); 712cc290419Sopenharmony_ci } 713cc290419Sopenharmony_ci } 714cc290419Sopenharmony_ci 715cc290419Sopenharmony_ci crate::debug!("read {} known hosts from file", key_vec.len()); 716cc290419Sopenharmony_ci key_vec 717cc290419Sopenharmony_ci } else { 718cc290419Sopenharmony_ci crate::info!("pubkey file {:?} not exists", file_name); 719cc290419Sopenharmony_ci vec![] 720cc290419Sopenharmony_ci } 721cc290419Sopenharmony_ci} 722cc290419Sopenharmony_ci 723cc290419Sopenharmony_cifn write_known_hosts_pubkey(pubkey: &String) -> io::Result<()> { 724cc290419Sopenharmony_ci let file_name = Path::new(config::RSA_PUBKEY_PATH).join(config::RSA_PUBKEY_NAME); 725cc290419Sopenharmony_ci if !file_name.exists() { 726cc290419Sopenharmony_ci crate::info!("will create pubkeys file at {:?}", file_name); 727cc290419Sopenharmony_ci 728cc290419Sopenharmony_ci if let Err(e) = std::fs::create_dir_all(config::RSA_PUBKEY_PATH) { 729cc290419Sopenharmony_ci log::error!("create pubkeys dir: {}", e.to_string()); 730cc290419Sopenharmony_ci } 731cc290419Sopenharmony_ci if let Err(e) = std::fs::File::create(&file_name) { 732cc290419Sopenharmony_ci log::error!("create pubkeys file: {}", e.to_string()); 733cc290419Sopenharmony_ci } 734cc290419Sopenharmony_ci } 735cc290419Sopenharmony_ci 736cc290419Sopenharmony_ci let _ = match std::fs::File::options().append(true).open(file_name) { 737cc290419Sopenharmony_ci Ok(mut f) => writeln!(&mut f, "{}", pubkey), 738cc290419Sopenharmony_ci Err(e) => { 739cc290419Sopenharmony_ci crate::error!("write pubkey err: {}", e.to_string()); 740cc290419Sopenharmony_ci return Err(e); 741cc290419Sopenharmony_ci } 742cc290419Sopenharmony_ci }; 743cc290419Sopenharmony_ci Ok(()) 744cc290419Sopenharmony_ci} 745cc290419Sopenharmony_ci 746cc290419Sopenharmony_cifn show_permit_dialog() -> bool { 747cc290419Sopenharmony_ci let cmd = "/system/bin/hdcd_user_permit"; 748cc290419Sopenharmony_ci let result = Command::new(cmd).output(); 749cc290419Sopenharmony_ci match result { 750cc290419Sopenharmony_ci Ok(output) => { 751cc290419Sopenharmony_ci let msg = [output.stdout, output.stderr].concat(); 752cc290419Sopenharmony_ci let mut str = match String::from_utf8(msg) { 753cc290419Sopenharmony_ci Ok(s) => s, 754cc290419Sopenharmony_ci Err(e) => { 755cc290419Sopenharmony_ci crate::error!("show dialog over, {}.", e.to_string()); 756cc290419Sopenharmony_ci return false; 757cc290419Sopenharmony_ci } 758cc290419Sopenharmony_ci }; 759cc290419Sopenharmony_ci str = str.replace('\n', " "); 760cc290419Sopenharmony_ci crate::error!("show dialog over, {}.", str); 761cc290419Sopenharmony_ci true 762cc290419Sopenharmony_ci } 763cc290419Sopenharmony_ci Err(e) => { 764cc290419Sopenharmony_ci crate::error!("show dialog failed, {}.", e.to_string()); 765cc290419Sopenharmony_ci false 766cc290419Sopenharmony_ci } 767cc290419Sopenharmony_ci } 768cc290419Sopenharmony_ci} 769cc290419Sopenharmony_ci 770cc290419Sopenharmony_cipub fn is_auth_enable() -> bool { 771cc290419Sopenharmony_ci #[cfg(feature = "emulator")] 772cc290419Sopenharmony_ci return false; 773cc290419Sopenharmony_ci 774cc290419Sopenharmony_ci let (_, auth_enable) = get_dev_item("const.hdc.secure", "_"); 775cc290419Sopenharmony_ci crate::error!("const.hdc.secure is {}.", auth_enable); 776cc290419Sopenharmony_ci if auth_enable.trim().to_lowercase() != "1" { 777cc290419Sopenharmony_ci return false; 778cc290419Sopenharmony_ci } 779cc290419Sopenharmony_ci 780cc290419Sopenharmony_ci // if persist.hdc.auth_bypass is set "1", will not auth, 781cc290419Sopenharmony_ci // otherwhise must be auth 782cc290419Sopenharmony_ci // the auto upgrade test will set persist.hdc.auth_bypass 1 783cc290419Sopenharmony_ci let (_, auth_bypass) = get_dev_item("persist.hdc.auth_bypass", "_"); 784cc290419Sopenharmony_ci crate::error!("persist.hdc.auth_bypass is {}.", auth_bypass); 785cc290419Sopenharmony_ci auth_bypass.trim().to_lowercase() != "1" 786cc290419Sopenharmony_ci} 787cc290419Sopenharmony_ci 788cc290419Sopenharmony_ciasync fn require_user_permittion(hostname: &str) -> UserPermit { 789cc290419Sopenharmony_ci // todo debug 790cc290419Sopenharmony_ci let default_permit = "auth_result_none"; 791cc290419Sopenharmony_ci // clear result first 792cc290419Sopenharmony_ci if !set_dev_item("persist.hdc.daemon.auth_result", default_permit) { 793cc290419Sopenharmony_ci crate::error!("debug auth result failed, so refuse this connect."); 794cc290419Sopenharmony_ci return UserPermit::Refuse; 795cc290419Sopenharmony_ci } 796cc290419Sopenharmony_ci 797cc290419Sopenharmony_ci // then write para for setting 798cc290419Sopenharmony_ci if !set_dev_item("persist.hdc.client.hostname", hostname) { 799cc290419Sopenharmony_ci crate::error!("set param({}) failed.", hostname); 800cc290419Sopenharmony_ci return UserPermit::Refuse; 801cc290419Sopenharmony_ci } 802cc290419Sopenharmony_ci if !show_permit_dialog() { 803cc290419Sopenharmony_ci crate::error!("show dialog failed, so refuse this connect."); 804cc290419Sopenharmony_ci return UserPermit::Refuse; 805cc290419Sopenharmony_ci } 806cc290419Sopenharmony_ci let permit_result = match get_dev_item("persist.hdc.daemon.auth_result", "_") { 807cc290419Sopenharmony_ci (false, _) => { 808cc290419Sopenharmony_ci crate::error!("get_dev_item auth_result failed"); 809cc290419Sopenharmony_ci UserPermit::Refuse 810cc290419Sopenharmony_ci } 811cc290419Sopenharmony_ci (true, auth_result) => { 812cc290419Sopenharmony_ci crate::error!("user permit result is:({})", auth_result); 813cc290419Sopenharmony_ci match auth_result.strip_prefix("auth_result:") { 814cc290419Sopenharmony_ci Some(result) => match result.trim() { 815cc290419Sopenharmony_ci "1" => UserPermit::AllowOnce, 816cc290419Sopenharmony_ci "2" => UserPermit::AllowForever, 817cc290419Sopenharmony_ci _ => UserPermit::Refuse, 818cc290419Sopenharmony_ci }, 819cc290419Sopenharmony_ci None => { 820cc290419Sopenharmony_ci crate::error!("get_dev_item auth_result failed"); 821cc290419Sopenharmony_ci UserPermit::Refuse 822cc290419Sopenharmony_ci } 823cc290419Sopenharmony_ci } 824cc290419Sopenharmony_ci } 825cc290419Sopenharmony_ci }; 826cc290419Sopenharmony_ci permit_result 827cc290419Sopenharmony_ci} 828cc290419Sopenharmony_ci 829cc290419Sopenharmony_ciasync fn handshake_fail(session_id: u32, channel_id: u32, msg: String) { 830cc290419Sopenharmony_ci AuthStatusMap::put(session_id, AuthStatus::Fail).await; 831cc290419Sopenharmony_ci let send = native_struct::SessionHandShake { 832cc290419Sopenharmony_ci banner: HANDSHAKE_MESSAGE.to_string(), 833cc290419Sopenharmony_ci session_id, 834cc290419Sopenharmony_ci auth_type: AuthType::Fail as u8, 835cc290419Sopenharmony_ci buf: msg, 836cc290419Sopenharmony_ci ..Default::default() 837cc290419Sopenharmony_ci }; 838cc290419Sopenharmony_ci transfer::put( 839cc290419Sopenharmony_ci session_id, 840cc290419Sopenharmony_ci TaskMessage { 841cc290419Sopenharmony_ci channel_id, 842cc290419Sopenharmony_ci command: config::HdcCommand::KernelHandshake, 843cc290419Sopenharmony_ci payload: send.serialize(), 844cc290419Sopenharmony_ci }, 845cc290419Sopenharmony_ci ) 846cc290419Sopenharmony_ci .await; 847cc290419Sopenharmony_ci} 848cc290419Sopenharmony_ci 849cc290419Sopenharmony_ciasync fn generate_token() -> io::Result<String> { 850cc290419Sopenharmony_ci let mut random_file = File::open("/dev/random")?; 851cc290419Sopenharmony_ci let mut buffer = [0; HDC_HANDSHAKE_TOKEN_LEN]; 852cc290419Sopenharmony_ci random_file.read_exact(&mut buffer)?; 853cc290419Sopenharmony_ci let random_vec: Vec<_> = buffer.iter().map(|h| format!("{:02X}", h)).collect(); 854cc290419Sopenharmony_ci let token = random_vec.join(""); 855cc290419Sopenharmony_ci Ok(token) 856cc290419Sopenharmony_ci} 857cc290419Sopenharmony_ci 858cc290419Sopenharmony_ciasync fn generate_token_wait() -> String { 859cc290419Sopenharmony_ci loop { 860cc290419Sopenharmony_ci match generate_token().await { 861cc290419Sopenharmony_ci Ok(token) => { 862cc290419Sopenharmony_ci break token; 863cc290419Sopenharmony_ci } 864cc290419Sopenharmony_ci Err(e) => { 865cc290419Sopenharmony_ci let errlog = e.to_string(); 866cc290419Sopenharmony_ci crate::error!("generate token failed: {}", &errlog); 867cc290419Sopenharmony_ci } 868cc290419Sopenharmony_ci } 869cc290419Sopenharmony_ci } 870cc290419Sopenharmony_ci} 871cc290419Sopenharmony_ci 872cc290419Sopenharmony_cifn get_hostname() -> String { 873cc290419Sopenharmony_ci use libc::{c_char, sysconf, _SC_HOST_NAME_MAX}; 874cc290419Sopenharmony_ci let maxlen = unsafe { sysconf(_SC_HOST_NAME_MAX) }; 875cc290419Sopenharmony_ci let mut out = vec![0; (maxlen as usize) + 1]; 876cc290419Sopenharmony_ci let ret = unsafe { libc::gethostname(out.as_mut_ptr() as *mut c_char, out.len()) }; 877cc290419Sopenharmony_ci if ret != 0 { 878cc290419Sopenharmony_ci crate::error!("get hostname failed, {}.", std::io::Error::last_os_error()); 879cc290419Sopenharmony_ci return "".to_string(); 880cc290419Sopenharmony_ci } 881cc290419Sopenharmony_ci let len = out.iter().position(|&c| c == 0).unwrap_or(out.len()); 882cc290419Sopenharmony_ci out.resize(len, 0); 883cc290419Sopenharmony_ci let output = String::from_utf8(out) 884cc290419Sopenharmony_ci .unwrap_or("".to_string()) 885cc290419Sopenharmony_ci .trim() 886cc290419Sopenharmony_ci .to_string(); 887cc290419Sopenharmony_ci crate::info!("get hostname is {}", output); 888cc290419Sopenharmony_ci output 889cc290419Sopenharmony_ci} 890