From c1c71e80fbb885941e5ea4ee7be6daf8752bd236 Mon Sep 17 00:00:00 2001 From: Mariotaku Date: Fri, 22 Sep 2023 17:41:04 +0900 Subject: [PATCH] improved for webOS 1.x TV/emulator --- src-tauri/Cargo.lock | 6 +-- src-tauri/Cargo.toml | 4 ++ src-tauri/src/conn_pool/connection.rs | 40 +++++++++++++++++-- src/app/core/services/app-manager.service.ts | 10 ++++- .../core/services/device-manager.service.ts | 4 +- src/app/core/services/remote-luna.service.ts | 9 +++++ src/app/debug/pmlog/pmlog.component.ts | 2 +- 7 files changed, 62 insertions(+), 13 deletions(-) diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 1b1f7573..3beb534d 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1744,8 +1744,7 @@ checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" [[package]] name = "libssh-rs" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff892c443aa43a8e305913da313b5234bf33a7f17eae378f9c9ae4419dbbaa74" +source = "git+https://github.com/mariotaku/libssh-rs.git?branch=feature/more-auth-options#1f046b2800ff08de4b791927d1491426b275fcd5" dependencies = [ "bitflags", "libssh-rs-sys", @@ -1756,8 +1755,7 @@ dependencies = [ [[package]] name = "libssh-rs-sys" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aad2e95f77dde4d6a636ca1c713f3efdaa46bb2dae33d7d2abeea992baeb9cb3" +source = "git+https://github.com/mariotaku/libssh-rs.git?branch=feature/more-auth-options#1f046b2800ff08de4b791927d1491426b275fcd5" dependencies = [ "cc", "libz-sys", diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 83738f9d..b3b6f0c8 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -65,3 +65,7 @@ default = ["custom-protocol"] # DO NOT remove this custom-protocol = ["tauri/custom-protocol"] vendored-openssl = ["libssh-rs-sys/vendored-openssl", "reqwest/native-tls-vendored"] + +[patch.crates-io] +libssh-rs = { git = "https://github.com/mariotaku/libssh-rs.git", branch = "feature/more-auth-options" } +libssh-rs-sys = { git = "https://github.com/mariotaku/libssh-rs.git", branch = "feature/more-auth-options" } diff --git a/src-tauri/src/conn_pool/connection.rs b/src-tauri/src/conn_pool/connection.rs index b99866e3..93deebc5 100644 --- a/src-tauri/src/conn_pool/connection.rs +++ b/src-tauri/src/conn_pool/connection.rs @@ -4,7 +4,7 @@ use std::ops::{Deref, DerefMut}; use std::sync::Mutex; use std::time::Duration; -use libssh_rs::{AuthStatus, Session, SshKey, SshOption}; +use libssh_rs::{AuthStatus, LogLevel, Session, SshKey, SshOption}; use tauri::regex::Regex; use uuid::Uuid; @@ -14,13 +14,47 @@ use crate::error::Error; impl DeviceConnection { pub(crate) fn new(device: Device) -> Result { + let kex = vec![ + "curve25519-sha256", + "curve25519-sha256@libssh.org", + "ecdh-sha2-nistp256", + "ecdh-sha2-nistp384", + "ecdh-sha2-nistp521", + "diffie-hellman-group18-sha512", + "diffie-hellman-group16-sha512", + "diffie-hellman-group-exchange-sha256", + "diffie-hellman-group14-sha256", + "diffie-hellman-group1-sha1", + "diffie-hellman-group14-sha1", + ]; + let hmac = vec![ + "hmac-sha2-256-etm@openssh.com", + "hmac-sha2-512-etm@openssh.com", + "hmac-sha2-256", + "hmac-sha2-512", + "hmac-sha1-96", + "hmac-sha1", + "hmac-md5", + ]; + let key_types = vec![ + "ssh-ed25519", + "ecdsa-sha2-nistp521", + "ecdsa-sha2-nistp384", + "ecdsa-sha2-nistp256", + "rsa-sha2-512", + "rsa-sha2-256", + "ssh-rsa", + ]; let session = Session::new()?; session.set_option(SshOption::Timeout(Duration::from_secs(10)))?; session.set_option(SshOption::Hostname(device.host.clone()))?; session.set_option(SshOption::Port(device.port.clone()))?; session.set_option(SshOption::User(Some(device.username.clone())))?; - session.set_option(SshOption::HostKeys(format!("ssh-ed25519,ecdsa-sha2-nistp521,ecdsa-sha2-nistp384,ecdsa-sha2-nistp256,rsa-sha2-512,rsa-sha2-256,ssh-rsa")))?; - session.set_option(SshOption::PublicKeyAcceptedTypes(format!("ssh-ed25519,ecdsa-sha2-nistp521,ecdsa-sha2-nistp384,ecdsa-sha2-nistp256,rsa-sha2-512,rsa-sha2-256,ssh-rsa")))?; + session.set_option(SshOption::KeyExchange(kex.join(",")))?; + session.set_option(SshOption::HmacCS(hmac.join(",")))?; + session.set_option(SshOption::HmacSC(hmac.join(",")))?; + session.set_option(SshOption::HostKeys(key_types.join(",")))?; + session.set_option(SshOption::PublicKeyAcceptedTypes(key_types.join(",")))?; session.set_option(SshOption::ProcessConfig(false))?; #[cfg(windows)] { diff --git a/src/app/core/services/app-manager.service.ts b/src/app/core/services/app-manager.service.ts index 8532626a..908a7eb8 100644 --- a/src/app/core/services/app-manager.service.ts +++ b/src/app/core/services/app-manager.service.ts @@ -1,7 +1,7 @@ import {Injectable} from '@angular/core'; import {BehaviorSubject, catchError, firstValueFrom, lastValueFrom, mergeMap, noop, Observable, Subject} from 'rxjs'; import {Device, PackageInfo, RawPackageInfo} from '../../types'; -import {LunaResponse, LunaResponseError, RemoteLunaService} from "./remote-luna.service"; +import {LunaResponse, LunaResponseError, LunaUnknownMethodError, RemoteLunaService} from "./remote-luna.service"; import {escapeSingleQuoteString, RemoteCommandService} from "./remote-command.service"; import {filter, map} from "rxjs/operators"; import * as path from "path"; @@ -44,6 +44,12 @@ export class AppManagerService { async list(device: Device): Promise { return this.luna.call(device, 'luna://com.webos.applicationManager/dev/listApps') + .catch((e) => { + if (e instanceof LunaUnknownMethodError) { + return this.luna.call(device, 'luna://com.webos.applicationManager/listApps', undefined, false); + } + throw e; + }) .then(resp => resp['apps'] as RawPackageInfo[]) .then((result) => Promise.all(result.map(item => this.completeIcon(device, item)))); } @@ -142,7 +148,7 @@ export class AppManagerService { await this.file.put(device, path, location); break; default: - await this.cmd.exec(device, `curl -sL ${escapeSingleQuoteString(location)} --output ${escapeSingleQuoteString(path)}`); + await this.cmd.exec(device, `curl -ksL ${escapeSingleQuoteString(location)} --output ${escapeSingleQuoteString(path)}`); break; } return path; diff --git a/src/app/core/services/device-manager.service.ts b/src/app/core/services/device-manager.service.ts index ba61da6d..673f1398 100644 --- a/src/app/core/services/device-manager.service.ts +++ b/src/app/core/services/device-manager.service.ts @@ -113,9 +113,7 @@ export class DeviceManagerService extends BackendClient { const param: Record = { path: tmpPath, method: method, - format: "PNG", - width: 1920, - height: 1080 + format: "PNG" }; await (this.luna.call(device, 'luna://com.webos.service.capture/executeOneShot', param, false) .catch((e) => { diff --git a/src/app/core/services/remote-luna.service.ts b/src/app/core/services/remote-luna.service.ts index c417d75b..195288e7 100644 --- a/src/app/core/services/remote-luna.service.ts +++ b/src/app/core/services/remote-luna.service.ts @@ -42,6 +42,9 @@ export class RemoteLunaService { throw new Error(`Bad response ${out}`); } if (typed.returnValue === false) { + if (typed['errorText']?.startsWith('Unknown method')) { + throw new LunaUnknownMethodError(typed); + } throw new LunaResponseError(typed); } return typed; @@ -134,3 +137,9 @@ export class LunaResponseError extends Error { } } + +export class LunaUnknownMethodError extends LunaResponseError { + constructor(payload: Record) { + super(payload); + } +} diff --git a/src/app/debug/pmlog/pmlog.component.ts b/src/app/debug/pmlog/pmlog.component.ts index 190f2961..59cc02fc 100644 --- a/src/app/debug/pmlog/pmlog.component.ts +++ b/src/app/debug/pmlog/pmlog.component.ts @@ -63,7 +63,7 @@ export class PmLogComponent { const info = await this.deviceManager.getSystemInfo(device); if (semver.satisfies(info.sdkVersion || '', '>=4.0')) { await this.luna.call(device, 'luna://com.webos.service.config/setConfigs', {configs: {"system.collectDevLogs": true}}, false); - } else { + } else if (semver.satisfies(info.sdkVersion || '', '>=2.0')) { await this.luna.call(device, 'luna://com.webos.pmlogd/setdevlogstatus', {recordDevLogs: true}, false); } return this.log.logread(device, LogReaderComponent.retainLogs);