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