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