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