file audit

Signed-off-by: 21pages <pages21@163.com>
This commit is contained in:
21pages 2022-12-18 16:17:10 +08:00
parent 8c86a82422
commit b3114d4147
7 changed files with 90 additions and 25 deletions

View File

@ -571,7 +571,8 @@ class _RemoteMenubarState extends State<RemoteMenubar> {
),
]);
// {handler.get_audit_server() && <li #note>{translate('Note')}</li>}
final auditServer = bind.sessionGetAuditServerSync(id: widget.id);
final auditServer =
bind.sessionGetAuditServerSync(id: widget.id, typ: "conn");
if (auditServer.isNotEmpty) {
displayMenu.add(
MenuEntryButton<String>(

View File

@ -620,12 +620,12 @@ pub fn get_api_server(api: String, custom: String) -> String {
"https://admin.rustdesk.com".to_owned()
}
pub fn get_audit_server(api: String, custom: String) -> String {
pub fn get_audit_server(api: String, custom: String, typ: String) -> String {
let url = get_api_server(api, custom);
if url.is_empty() || url.contains("rustdesk.com") {
return "".to_owned();
}
format!("{}/api/audit", url)
format!("{}/api/audit/{}", url, typ)
}
pub async fn post_request(url: String, body: String, header: &str) -> ResultType<String> {

View File

@ -894,9 +894,9 @@ pub fn session_restart_remote_device(id: String) {
}
}
pub fn session_get_audit_server_sync(id: String) -> SyncReturn<String> {
pub fn session_get_audit_server_sync(id: String, typ: String) -> SyncReturn<String> {
let res = if let Some(session) = SESSIONS.read().unwrap().get(&id) {
session.get_audit_server()
session.get_audit_server(typ)
} else {
"".to_owned()
};

View File

@ -93,7 +93,8 @@ pub struct Connection {
tx_input: std_mpsc::Sender<MessageInput>, // handle input messages
video_ack_required: bool,
peer_info: (String, String),
api_server: String,
server_audit_conn: String,
server_audit_file: String,
lr: LoginRequest,
last_recv_time: Arc<Mutex<Instant>>,
chat_unanswered: bool,
@ -184,7 +185,8 @@ impl Connection {
tx_input,
video_ack_required: false,
peer_info: Default::default(),
api_server: "".to_owned(),
server_audit_conn: "".to_owned(),
server_audit_file: "".to_owned(),
lr: Default::default(),
last_recv_time: Arc::new(Mutex::new(Instant::now())),
chat_unanswered: false,
@ -384,7 +386,7 @@ impl Connection {
} else {
conn.timer = time::interval_at(Instant::now() + SEC30, SEC30);
}
conn.post_audit(json!({})); // heartbeat
conn.post_conn_audit(json!({})); // heartbeat
},
Some((instant, value)) = rx_video.recv() => {
if !conn.video_ack_required {
@ -497,7 +499,7 @@ impl Connection {
conn.on_close(&err.to_string(), false).await;
}
conn.post_audit(json!({
conn.post_conn_audit(json!({
"action": "close",
}));
log::info!("#{} connection loop exited", id);
@ -601,7 +603,7 @@ impl Connection {
if last_recv_time.elapsed() >= H1 {
bail!("Timeout");
}
self.post_audit(json!({})); // heartbeat
self.post_conn_audit(json!({})); // heartbeat
}
}
}
@ -650,7 +652,7 @@ impl Connection {
msg_out.set_hash(self.hash.clone());
self.send(msg_out).await;
self.get_api_server();
self.post_audit(json!({
self.post_conn_audit(json!({
"ip": addr.ip(),
"action": "new",
}));
@ -658,17 +660,23 @@ impl Connection {
}
fn get_api_server(&mut self) {
self.api_server = crate::get_audit_server(
self.server_audit_conn = crate::get_audit_server(
Config::get_option("api-server"),
Config::get_option("custom-rendezvous-server"),
"conn".to_owned(),
);
self.server_audit_file = crate::get_audit_server(
Config::get_option("api-server"),
Config::get_option("custom-rendezvous-server"),
"file".to_owned(),
);
}
fn post_audit(&self, v: Value) {
if self.api_server.is_empty() {
fn post_conn_audit(&self, v: Value) {
if self.server_audit_conn.is_empty() {
return;
}
let url = self.api_server.clone();
let url = self.server_audit_conn.clone();
let mut v = v;
v["id"] = json!(Config::get_id());
v["uuid"] = json!(base64::encode(hbb_common::get_uuid()));
@ -678,6 +686,41 @@ impl Connection {
});
}
fn post_file_audit(&self, action: &str, path: &str, files: Vec<(String, i64)>, info: Value) {
if self.server_audit_file.is_empty() {
return;
}
let url = self.server_audit_file.clone();
let file_num = files.len();
let mut files = files;
files.sort_by(|a, b| b.1.cmp(&a.1));
files.truncate(10);
let is_file = match action {
"send" | "receive" => files.len() == 1 && files[0].0.is_empty(),
"remove_dir" | "create_dir" => false,
"remove_file" => true,
_ => true,
};
let mut info = info;
info["ip"] = json!(self.ip.clone());
info["name"] = json!(self.lr.my_name.clone());
info["num"] = json!(file_num);
info["files"] = json!(files);
let v = json!({
"id":json!(Config::get_id()),
"uuid":json!(base64::encode(hbb_common::get_uuid())),
"Id":json!(self.inner.id),
"peer_id":json!(self.lr.my_id),
"action": action,
"path":path,
"is_file":is_file,
"info":json!(info).to_string(),
});
tokio::spawn(async move {
allow_err!(Self::post_audit_async(url, v).await);
});
}
#[inline]
async fn post_audit_async(url: String, v: Value) -> ResultType<()> {
crate::post_request(url, v.to_string(), "").await?;
@ -695,7 +738,7 @@ impl Connection {
} else {
0
};
self.post_audit(json!({"peer": self.peer_info, "Type": conn_type}));
self.post_conn_audit(json!({"peer": self.peer_info, "Type": conn_type}));
#[allow(unused_mut)]
let mut username = crate::platform::get_active_username();
let mut res = LoginResponse::new();
@ -1225,8 +1268,18 @@ impl Connection {
Ok(job) => {
self.send(fs::new_dir(id, path, job.files().to_vec()))
.await;
let mut files = job.files().to_owned();
self.read_jobs.push(job);
self.timer = time::interval(MILLI1);
self.post_file_audit(
"send",
&s.path,
files
.drain(..)
.map(|f| (f.name, f.size as _))
.collect(),
json!({}),
);
}
}
}
@ -1237,7 +1290,7 @@ impl Connection {
&self.lr.version,
));
self.send_fs(ipc::FS::NewWrite {
path: r.path,
path: r.path.clone(),
id: r.id,
file_num: r.file_num,
files: r
@ -1248,6 +1301,16 @@ impl Connection {
.collect(),
overwrite_detection: od,
});
self.post_file_audit(
"receive",
&r.path,
r.files
.to_vec()
.drain(..)
.map(|f| (f.name, f.size as _))
.collect(),
json!({}),
);
}
Some(file_action::Union::RemoveDir(d)) => {
self.send_fs(ipc::FS::RemoveDir {

View File

@ -208,7 +208,7 @@ class Header: Reactor.Component {
{keyboard_enabled ? <li #os-password>{translate('OS Password')}<EditOsPassword /></li> : ""}
<li #transfer-file>{translate('Transfer File')}</li>
<li #tunnel>{translate('TCP Tunneling')}</li>
{handler.get_audit_server() && <li #note>{translate('Note')}</li>}
{handler.get_audit_server("conn") && <li #note>{translate('Note')}</li>}
<div .separator />
{keyboard_enabled && (pi.platform == "Linux" || pi.sas_enabled) ? <li #ctrl-alt-del>{translate('Insert')} Ctrl + Alt + Del</li> : ""}
{restart_enabled && (pi.platform == "Linux" || pi.platform == "Windows" || pi.platform == "Mac OS") ? <li #restart_remote_device>{translate('Restart Remote Device')}</li> : ""}

View File

@ -233,12 +233,12 @@ impl InvokeUiSession for SciterHandler {
fn on_connected(&self, conn_type: ConnType) {
match conn_type {
ConnType::RDP => {},
ConnType::PORT_FORWARD => {},
ConnType::FILE_TRANSFER => {},
ConnType::RDP => {}
ConnType::PORT_FORWARD => {}
ConnType::FILE_TRANSFER => {}
ConnType::DEFAULT_CONN => {
crate::keyboard::client::start_grab_loop();
},
}
}
}
@ -348,7 +348,7 @@ impl sciter::EventHandler for SciterSession {
}
sciter::dispatch_script_call! {
fn get_audit_server();
fn get_audit_server(String);
fn send_note(String);
fn is_xfce();
fn get_id();

View File

@ -173,7 +173,7 @@ impl<T: InvokeUiSession> Session<T> {
self.send(Data::Message(msg));
}
pub fn get_audit_server(&self) -> String {
pub fn get_audit_server(&self, typ: String) -> String {
if self.lc.read().unwrap().conn_id <= 0
|| LocalConfig::get_option("access_token").is_empty()
{
@ -182,11 +182,12 @@ impl<T: InvokeUiSession> Session<T> {
crate::get_audit_server(
Config::get_option("api-server"),
Config::get_option("custom-rendezvous-server"),
typ,
)
}
pub fn send_note(&self, note: String) {
let url = self.get_audit_server();
let url = self.get_audit_server("conn".to_string());
let id = self.id.clone();
let conn_id = self.lc.read().unwrap().conn_id;
std::thread::spawn(move || {