Merge pull request #2820 from 21pages/logonW

elevation request
This commit is contained in:
RustDesk 2023-01-14 23:01:29 +08:00 committed by GitHub
commit b466bb013f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 900 additions and 59 deletions

View File

@ -549,6 +549,10 @@ class OverlayDialogManager {
hideMobileActionsOverlay();
}
}
bool existing(String tag) {
return _dialogs.keys.contains(tag);
}
}
void showToast(String text, {Duration timeout = const Duration(seconds: 2)}) {
@ -983,7 +987,7 @@ Widget getPlatformImage(String platform, {double size = 50}) {
platform != kPeerPlatformAndroid) {
platform = 'win';
} else {
platform = platform.toLowerCase();
platform = platform.toLowerCase();
}
return SvgPicture.asset('assets/$platform.svg', height: size, width: size);
}

View File

@ -1,6 +1,7 @@
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import '../../common.dart';
import '../../models/model.dart';
@ -367,6 +368,247 @@ void showServerSettingsWithValue(
});
}
void showWaitUacDialog(String id, OverlayDialogManager dialogManager) {
dialogManager.dismissAll();
dialogManager.show(
tag: '$id-wait-uac',
(setState, close) => CustomAlertDialog(
title: Text(translate('Wait')),
content: Text(translate('wait_accept_uac_tip')).marginAll(10),
));
}
void _showRequestElevationDialog(
String id, OverlayDialogManager dialogManager) {
RxString groupValue = ''.obs;
RxString errUser = ''.obs;
RxString errPwd = ''.obs;
TextEditingController userController = TextEditingController();
TextEditingController pwdController = TextEditingController();
void onRadioChanged(String? value) {
if (value != null) {
groupValue.value = value;
}
}
const minTextStyle = TextStyle(fontSize: 14);
var content = Obx(() => Column(children: [
Row(
children: [
Radio(
value: '',
groupValue: groupValue.value,
onChanged: onRadioChanged),
Expanded(
child:
Text(translate('Ask the remote user for authentication'))),
],
),
Align(
alignment: Alignment.centerLeft,
child: Text(
translate(
'Choose this if the remote account is administrator'),
style: TextStyle(fontSize: 13))
.marginOnly(left: 40),
).marginOnly(bottom: 15),
Row(
children: [
Radio(
value: 'logon',
groupValue: groupValue.value,
onChanged: onRadioChanged),
Expanded(
child: Text(translate(
'Transmit the username and password of administrator')),
)
],
),
Row(
children: [
Expanded(
flex: 1,
child: Text(
'${translate('Username')}:',
style: minTextStyle,
).marginOnly(right: 10)),
Expanded(
flex: 3,
child: TextField(
controller: userController,
style: minTextStyle,
decoration: InputDecoration(
isDense: true,
contentPadding: EdgeInsets.symmetric(vertical: 15),
hintText: 'eg: admin',
errorText: errUser.isEmpty ? null : errUser.value),
onChanged: (s) {
if (s.isNotEmpty) {
errUser.value = '';
}
},
),
)
],
).marginOnly(left: 40),
Row(
children: [
Expanded(
flex: 1,
child: Text(
'${translate('Password')}:',
style: minTextStyle,
).marginOnly(right: 10)),
Expanded(
flex: 3,
child: TextField(
controller: pwdController,
obscureText: true,
style: minTextStyle,
decoration: InputDecoration(
isDense: true,
contentPadding: EdgeInsets.symmetric(vertical: 15),
errorText: errPwd.isEmpty ? null : errPwd.value),
onChanged: (s) {
if (s.isNotEmpty) {
errPwd.value = '';
}
},
),
),
],
).marginOnly(left: 40),
Align(
alignment: Alignment.centerLeft,
child: Text(translate('still_click_uac_tip'),
style: TextStyle(fontSize: 13, fontWeight: FontWeight.bold))
.marginOnly(top: 20)),
]));
dialogManager.dismissAll();
dialogManager.show(tag: '$id-request-elevation', (setState, close) {
void submit() {
if (groupValue.value == 'logon') {
if (userController.text.isEmpty) {
errUser.value = translate('Empty Username');
return;
}
if (pwdController.text.isEmpty) {
errPwd.value = translate('Empty Password');
return;
}
bind.sessionElevateWithLogon(
id: id,
username: userController.text,
password: pwdController.text);
} else {
bind.sessionElevateDirect(id: id);
}
}
return CustomAlertDialog(
title: Text(translate('Request Elevation')),
content: content,
actions: [
ElevatedButton(
style: ElevatedButton.styleFrom(elevation: 0),
onPressed: submit,
child: Text(translate('OK')),
),
OutlinedButton(
onPressed: () {
close();
},
child: Text(translate('Cancel')),
),
],
onSubmit: submit,
onCancel: close,
);
});
}
void showOnBlockDialog(
String id,
String type,
String title,
String text,
OverlayDialogManager dialogManager,
) {
if (dialogManager.existing('$id-wait-uac') ||
dialogManager.existing('$id-request-elevation')) {
return;
}
var content = Column(children: [
Align(
alignment: Alignment.centerLeft,
child: Text(
"${translate(text)}${type.contains('uac') ? '\n' : '\n\n'}${translate('request_elevation_tip')}",
textAlign: TextAlign.left,
style: TextStyle(fontWeight: FontWeight.w400),
).marginSymmetric(vertical: 15),
),
]);
dialogManager.show(tag: '$id-$type', (setState, close) {
void submit() {
close();
_showRequestElevationDialog(id, dialogManager);
}
return CustomAlertDialog(
title: Text(translate(title)),
content: content,
actions: [
ElevatedButton(
style: ElevatedButton.styleFrom(elevation: 0),
onPressed: submit,
child: Text(translate('Request Elevation')),
),
OutlinedButton(
onPressed: () {
close();
},
child: Text(translate('Wait')),
),
],
onSubmit: submit,
onCancel: close,
);
});
}
void showElevationError(String id, String type, String title, String text,
OverlayDialogManager dialogManager) {
dialogManager.show(tag: '$id-$type', (setState, close) {
void submit() {
close();
_showRequestElevationDialog(id, dialogManager);
}
return CustomAlertDialog(
title: Text(translate(title)),
content: Text(translate(text)),
actions: [
ElevatedButton(
style: ElevatedButton.styleFrom(elevation: 0),
onPressed: submit,
child: Text(translate('Retry')),
),
OutlinedButton(
onPressed: () {
close();
},
child: Text(translate('Cancel')),
),
],
onSubmit: submit,
onCancel: close,
);
});
}
Future<String?> validateAsync(String value) async {
value = value.trim();
if (value.isEmpty) {

View File

@ -272,6 +272,12 @@ class FfiModel with ChangeNotifier {
} else if (type == 'wait-remote-accept-nook') {
msgBoxCommon(dialogManager, title, Text(translate(text)),
[msgBoxButton("Cancel", closeConnection)]);
} else if (type == 'on-uac' || type == 'on-foreground-elevated') {
showOnBlockDialog(id, type, title, text, dialogManager);
} else if (type == 'wait-uac') {
showWaitUacDialog(id, dialogManager);
} else if (type == 'elevation-error') {
showElevationError(id, type, title, text, dialogManager);
} else {
var hasRetry = evt['hasRetry'] == 'true';
showMsgBox(id, type, title, text, link, hasRetry, dialogManager);

View File

@ -552,6 +552,18 @@ message BackNotification {
}
}
message ElevationRequestWithLogon {
string username = 1;
string password = 2;
}
message ElevationRequest {
oneof union {
bool direct = 1;
ElevationRequestWithLogon logon = 2;
}
}
message Misc {
oneof union {
ChatMessage chat_message = 4;
@ -567,6 +579,9 @@ message Misc {
bool uac = 15;
bool foreground_window_elevated = 16;
bool stop_service = 17;
ElevationRequest elevation_request = 18;
string elevation_response = 19;
bool portable_service_running = 20;
}
}

View File

@ -1890,6 +1890,8 @@ pub enum Data {
AddJob((i32, String, String, i32, bool, bool)),
ResumeJob((i32, bool)),
RecordScreen(bool, i32, i32, String),
ElevateDirect,
ElevateWithLogon(String, String),
}
/// Keycode for key events.

View File

@ -632,6 +632,28 @@ impl<T: InvokeUiSession> Remote<T> {
.video_sender
.send(MediaData::RecordScreen(start, w, h, id));
}
Data::ElevateDirect => {
let mut request = ElevationRequest::new();
request.set_direct(true);
let mut misc = Misc::new();
misc.set_elevation_request(request);
let mut msg = Message::new();
msg.set_misc(misc);
allow_err!(peer.send(&msg).await);
}
Data::ElevateWithLogon(username, password) => {
let mut request = ElevationRequest::new();
request.set_logon(ElevationRequestWithLogon {
username,
password,
..Default::default()
});
let mut misc = Misc::new();
misc.set_elevation_request(request);
let mut msg = Message::new();
msg.set_misc(misc);
allow_err!(peer.send(&msg).await);
}
_ => {}
}
true
@ -989,8 +1011,13 @@ impl<T: InvokeUiSession> Remote<T> {
self.handler.ui_handler.switch_display(&s);
self.video_sender.send(MediaData::Reset).ok();
if s.width > 0 && s.height > 0 {
self.handler
.set_display(s.x, s.y, s.width, s.height, s.cursor_embedded);
self.handler.set_display(
s.x,
s.y,
s.width,
s.height,
s.cursor_embedded,
);
}
}
Some(misc::Union::CloseReason(c)) => {
@ -1003,31 +1030,85 @@ impl<T: InvokeUiSession> Remote<T> {
}
}
Some(misc::Union::Uac(uac)) => {
let msgtype = "custom-uac-nocancel";
let title = "Prompt";
let text = "Please wait for confirmation of UAC...";
let link = "";
if uac {
self.handler.msgbox(msgtype, title, text, link);
} else {
self.handler
.cancel_msgbox(
&format!("{}-{}-{}-{}", msgtype, title, text, link,),
#[cfg(feature = "flutter")]
{
if uac {
self.handler.msgbox(
"on-uac",
"Prompt",
"Please wait for confirmation of UAC...",
"",
);
} else {
self.handler.cancel_msgbox("on-uac");
self.handler.cancel_msgbox("wait-uac");
self.handler.cancel_msgbox("elevation-error");
}
}
#[cfg(not(feature = "flutter"))]
{
let msgtype = "custom-uac-nocancel";
let title = "Prompt";
let text = "Please wait for confirmation of UAC...";
let link = "";
if uac {
self.handler.msgbox(msgtype, title, text, link);
} else {
self.handler.cancel_msgbox(&format!(
"{}-{}-{}-{}",
msgtype, title, text, link,
));
}
}
}
Some(misc::Union::ForegroundWindowElevated(elevated)) => {
let msgtype = "custom-elevated-foreground-nocancel";
let title = "Prompt";
let text = "elevated_foreground_window_tip";
let link = "";
if elevated {
self.handler.msgbox(msgtype, title, text, link);
#[cfg(feature = "flutter")]
{
if elevated {
self.handler.msgbox(
"on-foreground-elevated",
"Prompt",
"elevated_foreground_window_tip",
"",
);
} else {
self.handler.cancel_msgbox("on-foreground-elevated");
self.handler.cancel_msgbox("wait-uac");
self.handler.cancel_msgbox("elevation-error");
}
}
#[cfg(not(feature = "flutter"))]
{
let msgtype = "custom-elevated-foreground-nocancel";
let title = "Prompt";
let text = "elevated_foreground_window_tip";
let link = "";
if elevated {
self.handler.msgbox(msgtype, title, text, link);
} else {
self.handler.cancel_msgbox(&format!(
"{}-{}-{}-{}",
msgtype, title, text, link,
));
}
}
}
Some(misc::Union::ElevationResponse(err)) => {
if err.is_empty() {
self.handler.msgbox("wait-uac", "", "", "");
} else {
self.handler
.cancel_msgbox(
&format!("{}-{}-{}-{}", msgtype, title, text, link,),
);
.msgbox("elevation-error", "Elevation Error", &err, "");
}
}
Some(misc::Union::PortableServiceRunning(b)) => {
if b {
self.handler.msgbox(
"custom-nocancel",
"Successful",
"Elevate successfully",
"",
);
}
}
_ => {}

View File

@ -106,7 +106,8 @@ pub fn core_main() -> Option<Vec<String>> {
&& !_is_elevate
&& !_is_run_as_system
{
if let Err(e) = crate::portable_service::client::start_portable_service() {
use crate::portable_service::client;
if let Err(e) = client::start_portable_service(client::StartPara::Direct) {
log::error!("Failed to start portable service:{:?}", e);
}
}

View File

@ -492,6 +492,18 @@ pub fn session_resume_job(id: String, act_id: i32, is_remote: bool) {
}
}
pub fn session_elevate_direct(id: String) {
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
session.elevate_direct();
}
}
pub fn session_elevate_with_logon(id: String, username: String, password: String) {
if let Some(session) = SESSIONS.read().unwrap().get(&id) {
session.elevate_with_logon(username, password);
}
}
pub fn main_get_sound_inputs() -> Vec<String> {
#[cfg(not(any(target_os = "android", target_os = "ios")))]
return get_sound_inputs();

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", ""),
("Always use software rendering", ""),
("config_input", ""),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", "如果你使用英伟达显卡, 并且远程窗口在会话建立后会立刻关闭, 那么安装nouveau驱动并且选择使用软件渲染可能会有帮助。重启软件后生效。"),
("Always use software rendering", "使用软件渲染"),
("config_input", "为了能够通过键盘控制远程桌面, 请给予 RustDesk \"输入监控\" 权限。"),
("request_elevation_tip", "如果对面有人, 也可以请求提升权限。"),
("Wait","等待"),
("Elevation Error", "提权失败"),
("Ask the remote user for authentication", "请求远端用户授权"),
("Choose this if the remote account is administrator", "当对面电脑是管理员账号时选择该选项"),
("Transmit the username and password of administrator", "发送管理员账号的用户名密码"),
("still_click_uac_tip", "依然需要被控端用戶在運行RustDesk的UAC窗口點擊確認。"),
("Request Elevation", "请求提权"),
("wait_accept_uac_tip", "请等待远端用户确认UAC对话框。"),
("Elevate successfully", "提权成功"),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", ""),
("Always use software rendering", ""),
("config_input", ""),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", ""),
("Always use software rendering", ""),
("config_input", ""),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", "Wenn Sie eine Nvidia-Grafikkarte haben und sich das entfernte Fenster sofort nach dem Herstellen der Verbindung schließt, kann es helfen, den Nouveau-Treiber zu installieren und Software-Rendering zu verwenden. Ein Neustart der Software ist erforderlich."),
("Always use software rendering", "Software-Rendering immer verwenden"),
("config_input", "Um den entfernten Desktop mit der Tastatur steuern zu können, müssen Sie RustDesk \"Input Monitoring\"-Rechte erteilen."),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -39,5 +39,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("verification_tip", "A new device has been detected, and a verification code has been sent to the registered email address, enter the verification code to continue logging in."),
("software_render_tip", "If you have an Nvidia graphics card and the remote window closes immediately after connecting, installing the nouveau driver and choosing to use software rendering may help. A software restart is required."),
("config_input", "In order to control remote desktop with keyboard, you need to grant RustDesk \"Input Monitoring\" permissions."),
("request_elevation_tip","You can also request elevation if there is someone on the remote side."),
("wait_accept_uac_tip","Please wait for the remote user to accept the UAC dialog."),
("still_click_uac_tip", "Still requires the remote user to click OK on the UAC window of running RustDesk.")
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", ""),
("Always use software rendering", ""),
("config_input", ""),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", "Si tienes una gráfica Nvidia y la ventana remota se cierra inmediatamente, instalar el driver nouveau y elegir renderizado por software podría ayudar. Se requiere reiniciar la aplicación."),
("Always use software rendering", "Usar siempre renderizado por software"),
("config_input", "Para controlar el escritorio remoto con el teclado necesitas dar a RustDesk permisos de \"Monitorización de entrada\"."),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", ""),
("Always use software rendering", ""),
("config_input", ""),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", "Si vous avez une carte graphique NVIDIA et que la fenêtre distante se ferme immédiatement après la connexion, l'installation du pilote Nouveau et le choix d'utiliser le rendu du logiciel peuvent aider. Un redémarrage du logiciel est requis."),
("Always use software rendering", "Utiliser toujours le rendu logiciel"),
("config_input", "Afin de contrôler le bureau à distance avec le clavier, vous devez accorder à Rustdesk l'autorisation \"Surveillance de lentrée\"."),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", ""),
("Always use software rendering", ""),
("config_input", ""),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", ""),
("Always use software rendering", ""),
("config_input", ""),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", ""),
("Always use software rendering", ""),
("config_input", ""),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", ""),
("Always use software rendering", "Usa sempre il render Software"),
("config_input", ""),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", ""),
("Always use software rendering", ""),
("config_input", ""),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", ""),
("Always use software rendering", ""),
("config_input", ""),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", ""),
("Always use software rendering", ""),
("config_input", ""),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", ""),
("Always use software rendering", ""),
("config_input", ""),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", ""),
("Always use software rendering", ""),
("config_input", ""),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", ""),
("Always use software rendering", ""),
("config_input", ""),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", "Если у вас видеокарта Nvidia и удалённое окно закрывается сразу после подключения, может помочь установка драйвера Nouveau и выбор использования программной визуализации. Потребуется перезапуск."),
("Always use software rendering", "Использовать программную визуализацию"),
("config_input", "Чтобы управлять удалённым рабочим столом с помощью клавиатуры, необходимо предоставить RustDesk разрешения \"Мониторинг ввода\"."),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", ""),
("Always use software rendering", ""),
("config_input", ""),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", ""),
("Always use software rendering", ""),
("config_input", ""),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", ""),
("Always use software rendering", ""),
("config_input", ""),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", ""),
("Always use software rendering", ""),
("config_input", ""),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", ""),
("Always use software rendering", ""),
("config_input", ""),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", ""),
("Always use software rendering", ""),
("config_input", ""),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", ""),
("Always use software rendering", ""),
("config_input", ""),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", ""),
("Always use software rendering", ""),
("config_input", ""),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", "如果你使用英偉達顯卡, 並且遠程窗口在會話建立後會立刻關閉, 那麼安裝nouveau驅動並且選擇使用軟件渲染可能會有幫助。重啟軟件後生效。"),
("Always use software rendering", "使用軟件渲染"),
("config_input", ""),
("request_elevation_tip", "如果對面有人, 也可以請求提升權限。"),
("Wait","等待"),
("Elevation Error", "提權失敗"),
("Ask the remote user for authentication", "請求遠端用戶授權"),
("Choose this if the remote account is administrator", "當對面電腦是管理員賬號時選擇該選項"),
("Transmit the username and password of administrator", "發送管理員賬號的用戶名密碼"),
("still_click_uac_tip", "依然需要被控端用戶在UAC窗口點擊確認。"),
("Request Elevation", "請求提權"),
("wait_accept_uac_tip", "請等待遠端用戶確認UAC對話框。"),
("Elevate successfully", "提權成功"),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", ""),
("Always use software rendering", ""),
("config_input", ""),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -413,5 +413,15 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("software_render_tip", ""),
("Always use software rendering", ""),
("config_input", ""),
("request_elevation_tip", ""),
("Wait",""),
("Elevation Error", ""),
("Ask the remote user for authentication", ""),
("Choose this if the remote account is administrator", ""),
("Transmit the username and password of administrator", ""),
("still_click_uac_tip", ""),
("Request Elevation", ""),
("wait_accept_uac_tip", ""),
("Elevate successfully", ""),
].iter().cloned().collect();
}

View File

@ -24,7 +24,7 @@ use winapi::{
minwinbase::STILL_ACTIVE,
processthreadsapi::{
GetCurrentProcess, GetCurrentProcessId, GetExitCodeProcess, OpenProcess,
OpenProcessToken,
OpenProcessToken, PROCESS_INFORMATION, STARTUPINFOW,
},
securitybaseapi::GetTokenInformation,
shellapi::ShellExecuteW,
@ -1714,3 +1714,42 @@ pub fn send_message_to_hnwd(
}
return true;
}
pub fn create_process_with_logon(user: &str, pwd: &str, exe: &str, arg: &str) -> ResultType<()> {
unsafe {
let wuser = wide_string(user);
let wpc = wide_string("");
let wpwd = wide_string(pwd);
let cmd = if arg.is_empty() {
format!("\"{}\"", exe)
} else {
format!("\"{}\" {}", exe, arg)
};
let mut wcmd = wide_string(&cmd);
let mut si: STARTUPINFOW = mem::zeroed();
si.wShowWindow = SW_HIDE as _;
si.lpDesktop = NULL as _;
si.cb = std::mem::size_of::<STARTUPINFOW>() as _;
si.dwFlags = STARTF_USESHOWWINDOW;
let mut pi: PROCESS_INFORMATION = mem::zeroed();
let wexe = wide_string(exe);
if FALSE
== CreateProcessWithLogonW(
wuser.as_ptr(),
wpc.as_ptr(),
wpwd.as_ptr(),
LOGON_WITH_PROFILE,
wexe.as_ptr(),
wcmd.as_mut_ptr(),
CREATE_UNICODE_ENVIRONMENT,
NULL,
NULL as _,
&mut si as *mut STARTUPINFOW,
&mut pi as *mut PROCESS_INFORMATION,
)
{
bail!("CreateProcessWithLogonW failed, errno={}", GetLastError());
}
}
return Ok(());
}

View File

@ -101,6 +101,7 @@ pub struct Connection {
last_recv_time: Arc<Mutex<Instant>>,
chat_unanswered: bool,
close_manually: bool,
elevation_requested: bool,
}
impl Subscriber for ConnInner {
@ -196,6 +197,7 @@ impl Connection {
last_recv_time: Arc::new(Mutex::new(Instant::now())),
chat_unanswered: false,
close_manually: false,
elevation_requested: false,
};
#[cfg(not(any(target_os = "android", target_os = "ios")))]
tokio::spawn(async move {
@ -247,6 +249,8 @@ impl Connection {
#[cfg(windows)]
let mut last_foreground_window_elevated = false;
#[cfg(windows)]
let mut last_portable_service_running = false;
#[cfg(windows)]
let is_installed = crate::platform::is_installed();
loop {
@ -353,7 +357,8 @@ impl Connection {
}
#[cfg(windows)]
ipc::Data::DataPortableService(ipc::DataPortableService::RequestStart) => {
if let Err(e) = crate::portable_service::client::start_portable_service() {
use crate::portable_service::client;
if let Err(e) = client::start_portable_service(client::StartPara::Direct) {
log::error!("Failed to start portable service from cm:{:?}", e);
}
}
@ -440,8 +445,18 @@ impl Connection {
_ = second_timer.tick() => {
#[cfg(windows)]
{
if !is_installed {
let portable_service_running = crate::portable_service::client::PORTABLE_SERVICE_RUNNING.lock().unwrap().clone();
if !is_installed && conn.file_transfer.is_none() && conn.port_forward_socket.is_none(){
let portable_service_running = crate::portable_service::client::running();
if portable_service_running != last_portable_service_running {
last_portable_service_running = portable_service_running;
if portable_service_running && conn.elevation_requested {
let mut misc = Misc::new();
misc.set_portable_service_running(portable_service_running);
let mut msg = Message::new();
msg.set_misc(misc);
conn.inner.send(msg.into());
}
}
let uac = crate::video_service::IS_UAC_RUNNING.lock().unwrap().clone();
if last_uac != uac {
last_uac = uac;
@ -1476,6 +1491,51 @@ impl Connection {
}
}
}
Some(misc::Union::ElevationRequest(r)) => match r.union {
Some(elevation_request::Union::Direct(_)) => {
#[cfg(windows)]
{
let mut err = "No need to elevate".to_string();
if !crate::platform::is_installed()
&& !crate::portable_service::client::running()
{
use crate::portable_service::client;
err = client::start_portable_service(client::StartPara::Direct)
.err()
.map_or("".to_string(), |e| e.to_string());
}
self.elevation_requested = err.is_empty();
let mut misc = Misc::new();
misc.set_elevation_response(err);
let mut msg = Message::new();
msg.set_misc(misc);
self.send(msg).await;
}
}
Some(elevation_request::Union::Logon(r)) => {
#[cfg(windows)]
{
let mut err = "No need to elevate".to_string();
if !crate::platform::is_installed()
&& !crate::portable_service::client::running()
{
use crate::portable_service::client;
err = client::start_portable_service(client::StartPara::Logon(
r.username, r.password,
))
.err()
.map_or("".to_string(), |e| e.to_string());
}
self.elevation_requested = err.is_empty();
let mut misc = Misc::new();
misc.set_elevation_response(err);
let mut msg = Message::new();
msg.set_misc(misc);
self.send(msg).await;
}
}
_ => {}
},
_ => {}
},
_ => {}

View File

@ -451,18 +451,24 @@ pub mod server {
// functions called in main process.
pub mod client {
use hbb_common::anyhow::Context;
use std::path::PathBuf;
use super::*;
lazy_static::lazy_static! {
pub static ref PORTABLE_SERVICE_RUNNING: Arc<Mutex<bool>> = Default::default();
static ref RUNNING: Arc<Mutex<bool>> = Default::default();
static ref SHMEM: Arc<Mutex<Option<SharedMemory>>> = Default::default();
static ref SENDER : Mutex<mpsc::UnboundedSender<ipc::Data>> = Mutex::new(client::start_ipc_server());
}
pub(crate) fn start_portable_service() -> ResultType<()> {
pub enum StartPara {
Direct,
Logon(String, String),
}
pub(crate) fn start_portable_service(para: StartPara) -> ResultType<()> {
log::info!("start portable service");
if PORTABLE_SERVICE_RUNNING.lock().unwrap().clone() {
if RUNNING.lock().unwrap().clone() {
bail!("already running");
}
if SHMEM.lock().unwrap().is_none() {
@ -491,14 +497,60 @@ pub mod client {
unsafe {
libc::memset(shmem.as_ptr() as _, 0, shmem.len() as _);
}
if crate::platform::run_background(
&std::env::current_exe()?.to_string_lossy().to_string(),
"--portable-service",
)
.is_err()
{
*SHMEM.lock().unwrap() = None;
bail!("Failed to run portable service process");
drop(option);
match para {
StartPara::Direct => {
if let Err(e) = crate::platform::run_background(
&std::env::current_exe()?.to_string_lossy().to_string(),
"--portable-service",
) {
*SHMEM.lock().unwrap() = None;
bail!("Failed to run portable service process:{}", e);
}
}
StartPara::Logon(username, password) => {
#[allow(unused_mut)]
let mut exe = std::env::current_exe()?.to_string_lossy().to_string();
#[cfg(feature = "flutter")]
{
if let Some(dir) = PathBuf::from(&exe).parent() {
if !set_dir_permission(&PathBuf::from(dir)) {
*SHMEM.lock().unwrap() = None;
bail!("Failed to set permission of {:?}", dir);
}
}
}
#[cfg(not(feature = "flutter"))]
match hbb_common::directories_next::UserDirs::new() {
Some(user_dir) => {
let dir = user_dir
.home_dir()
.join("AppData")
.join("Local")
.join("rustdesk-sciter");
if std::fs::create_dir_all(&dir).is_ok() {
let dst = dir.join("rustdesk.exe");
if std::fs::copy(&exe, &dst).is_ok() {
if dst.exists() {
if set_dir_permission(&dir) {
exe = dst.to_string_lossy().to_string();
}
}
}
}
}
None => {}
}
if let Err(e) = crate::platform::windows::create_process_with_logon(
username.as_str(),
password.as_str(),
&exe,
"--portable-service",
) {
*SHMEM.lock().unwrap() = None;
bail!("Failed to run portable service process:{}", e);
}
}
}
let _sender = SENDER.lock().unwrap();
Ok(())
@ -509,6 +561,16 @@ pub mod client {
*SHMEM.lock().unwrap() = None;
}
fn set_dir_permission(dir: &PathBuf) -> bool {
// // give Everyone RX permission
std::process::Command::new("icacls")
.arg(dir.as_os_str())
.arg("/grant")
.arg("Everyone:(OI)(CI)RX")
.arg("/T")
.spawn()
.is_ok()
}
pub struct CapturerPortable;
impl CapturerPortable {
@ -668,7 +730,7 @@ pub mod client {
}
Pong => {
nack = 0;
*PORTABLE_SERVICE_RUNNING.lock().unwrap() = true;
*RUNNING.lock().unwrap() = true;
},
ConnCount(None) => {
if !quick_support {
@ -699,7 +761,7 @@ pub mod client {
}
}
}
*PORTABLE_SERVICE_RUNNING.lock().unwrap() = false;
*RUNNING.lock().unwrap() = false;
});
}
Err(err) => {
@ -752,7 +814,7 @@ pub mod client {
use_yuv: bool,
portable_service_running: bool,
) -> ResultType<Box<dyn TraitCapturer>> {
if portable_service_running != PORTABLE_SERVICE_RUNNING.lock().unwrap().clone() {
if portable_service_running != RUNNING.lock().unwrap().clone() {
log::info!("portable service status mismatch");
}
if portable_service_running {
@ -767,7 +829,7 @@ pub mod client {
}
pub fn get_cursor_info(pci: PCURSORINFO) -> BOOL {
if PORTABLE_SERVICE_RUNNING.lock().unwrap().clone() {
if RUNNING.lock().unwrap().clone() {
get_cursor_info_(&mut SHMEM.lock().unwrap().as_mut().unwrap(), pci)
} else {
unsafe { winuser::GetCursorInfo(pci) }
@ -775,7 +837,7 @@ pub mod client {
}
pub fn handle_mouse(evt: &MouseEvent) {
if PORTABLE_SERVICE_RUNNING.lock().unwrap().clone() {
if RUNNING.lock().unwrap().clone() {
handle_mouse_(evt).ok();
} else {
crate::input_service::handle_mouse_(evt);
@ -783,12 +845,16 @@ pub mod client {
}
pub fn handle_key(evt: &KeyEvent) {
if PORTABLE_SERVICE_RUNNING.lock().unwrap().clone() {
if RUNNING.lock().unwrap().clone() {
handle_key_(evt).ok();
} else {
crate::input_service::handle_key_(evt);
}
}
pub fn running() -> bool {
RUNNING.lock().unwrap().clone()
}
}
#[repr(C)]

View File

@ -20,14 +20,10 @@
use super::{video_qos::VideoQoS, *};
#[cfg(windows)]
use crate::portable_service::client::PORTABLE_SERVICE_RUNNING;
#[cfg(windows)]
use hbb_common::get_version_number;
use hbb_common::{
tokio::sync::{
mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
Mutex as TokioMutex,
},
use hbb_common::tokio::sync::{
mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
Mutex as TokioMutex,
};
#[cfg(not(windows))]
use scrap::Capturer;
@ -419,7 +415,7 @@ fn run(sp: GenericService) -> ResultType<()> {
#[cfg(target_os = "linux")]
super::wayland::ensure_inited()?;
#[cfg(windows)]
let last_portable_service_running = PORTABLE_SERVICE_RUNNING.lock().unwrap().clone();
let last_portable_service_running = crate::portable_service::client::running();
#[cfg(not(windows))]
let last_portable_service_running = false;
@ -518,14 +514,14 @@ fn run(sp: GenericService) -> ResultType<()> {
bail!("SWITCH");
}
#[cfg(windows)]
if last_portable_service_running != PORTABLE_SERVICE_RUNNING.lock().unwrap().clone() {
if last_portable_service_running != crate::portable_service::client::running() {
bail!("SWITCH");
}
check_privacy_mode_changed(&sp, c.privacy_mode_id)?;
#[cfg(windows)]
{
if crate::platform::windows::desktop_changed()
&& !PORTABLE_SERVICE_RUNNING.lock().unwrap().clone()
&& !crate::portable_service::client::running()
{
bail!("Desktop changed");
}

View File

@ -780,11 +780,7 @@ fn cm_inner_send(id: i32, data: Data) {
pub fn can_elevate() -> bool {
#[cfg(windows)]
{
return !crate::platform::is_installed()
&& !crate::portable_service::client::PORTABLE_SERVICE_RUNNING
.lock()
.unwrap()
.clone();
return !crate::platform::is_installed() && !crate::portable_service::client::running();
}
#[cfg(not(windows))]
return false;

View File

@ -608,6 +608,14 @@ impl<T: InvokeUiSession> Session<T> {
}
self.update_transfer_list();
}
pub fn elevate_direct(&self) {
self.send(Data::ElevateDirect);
}
pub fn elevate_with_logon(&self, username: String, password: String) {
self.send(Data::ElevateWithLogon(username, password));
}
}
pub trait InvokeUiSession: Send + Sync + Clone + 'static + Sized + Default {