Skip to content

Commit 8560251

Browse files
committed
Merge branch 'main' into pr/748
2 parents f58d389 + a3766cc commit 8560251

24 files changed

Lines changed: 1094 additions & 165 deletions

.all-contributorsrc

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -769,6 +769,33 @@
769769
"contributions": [
770770
"code"
771771
]
772+
},
773+
{
774+
"login": "PokAhonTAS911",
775+
"name": "PokAhonTAS911",
776+
"avatar_url": "https://avatars.githubusercontent.com/u/208599324?v=4",
777+
"profile": "https://github.com/PokAhonTAS911",
778+
"contributions": [
779+
"code"
780+
]
781+
},
782+
{
783+
"login": "ayamir",
784+
"name": "ayamir",
785+
"avatar_url": "https://avatars.githubusercontent.com/u/61657399?v=4",
786+
"profile": "http://ayamir.github.io",
787+
"contributions": [
788+
"code"
789+
]
790+
},
791+
{
792+
"login": "luizribeiro",
793+
"name": "Luiz Ribeiro",
794+
"avatar_url": "https://avatars.githubusercontent.com/u/112069?v=4",
795+
"profile": "http://l9o.dev",
796+
"contributions": [
797+
"code"
798+
]
772799
}
773800
],
774801
"contributorsPerLine": 7,

.github/pull_request_template.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
## Description
2+
3+
...
4+
5+
## AI Usage
6+
7+
Choose the level of AI involvement for this PR.
8+
9+
* [ ] Fully vibe coded
10+
* [ ] AI-designed, AI-coded, manually checked
11+
* [ ] Human-designed, AI-coded
12+
* [ ] Human-designed, human-coded (includes AI autocompletions and boilerplate gen)
13+
14+
*<sub>This is not to block AI contributions but rather to speed up PR review (saves time on trying to deduce the logic behind AI hallucinations).</sub>*

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Russh
22

33
[![Rust](https://github.com/warp-tech/russh/actions/workflows/rust.yml/badge.svg)](https://github.com/warp-tech/russh/actions/workflows/rust.yml) <!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
4-
[![All Contributors](https://img.shields.io/badge/all_contributors-85-orange.svg?style=flat-square)](#contributors-)
4+
[![All Contributors](https://img.shields.io/badge/all_contributors-88-orange.svg?style=flat-square)](#contributors-)
55
<!-- ALL-CONTRIBUTORS-BADGE:END -->
66

77
Low-level Tokio SSH2 client and server implementation.
@@ -247,6 +247,9 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
247247
</tr>
248248
<tr>
249249
<td align="center" valign="top" width="14.28%"><a href="https://jkshin.nubimaru.com"><img src="https://avatars.githubusercontent.com/u/949915?v=4?s=100" width="100px;" alt="Jeongkyu Shin"/><br /><sub><b>Jeongkyu Shin</b></sub></a><br /><a href="https://github.com/Eugeny/russh/commits?author=inureyes" title="Code">💻</a></td>
250+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/PokAhonTAS911"><img src="https://avatars.githubusercontent.com/u/208599324?v=4?s=100" width="100px;" alt="PokAhonTAS911"/><br /><sub><b>PokAhonTAS911</b></sub></a><br /><a href="https://github.com/Eugeny/russh/commits?author=PokAhonTAS911" title="Code">💻</a></td>
251+
<td align="center" valign="top" width="14.28%"><a href="http://ayamir.github.io"><img src="https://avatars.githubusercontent.com/u/61657399?v=4?s=100" width="100px;" alt="ayamir"/><br /><sub><b>ayamir</b></sub></a><br /><a href="https://github.com/Eugeny/russh/commits?author=ayamir" title="Code">💻</a></td>
252+
<td align="center" valign="top" width="14.28%"><a href="http://l9o.dev"><img src="https://avatars.githubusercontent.com/u/112069?v=4?s=100" width="100px;" alt="Luiz Ribeiro"/><br /><sub><b>Luiz Ribeiro</b></sub></a><br /><a href="https://github.com/Eugeny/russh/commits?author=luizribeiro" title="Code">💻</a></td>
250253
</tr>
251254
</tbody>
252255
</table>

cryptovec/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,6 @@ wasm-bindgen-test = "0.3.46"
2929

3030
[features]
3131
ssh-encoding = ["dep:ssh-encoding"]
32+
33+
[lints.rust]
34+
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_os, values("motor"))'] }

cryptovec/src/platform/mod.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,24 @@ mod windows;
33

44
#[cfg(not(windows))]
55
#[cfg(not(target_arch = "wasm32"))]
6+
#[cfg(not(target_os = "motor"))]
67
mod unix;
78

8-
#[cfg(target_arch = "wasm32")]
9+
// Motor OS has no memory-locking API; it uses the wasm no-op implementation.
10+
#[cfg(any(target_arch = "wasm32", target_os = "motor"))]
911
mod wasm;
1012

1113
// Re-export functions based on the platform
1214
#[cfg(not(windows))]
1315
#[cfg(not(target_arch = "wasm32"))]
16+
#[cfg(not(target_os = "motor"))]
1417
pub use unix::{mlock, munlock};
15-
#[cfg(target_arch = "wasm32")]
18+
#[cfg(any(target_arch = "wasm32", target_os = "motor"))]
1619
pub use wasm::{mlock, munlock};
1720
#[cfg(windows)]
1821
pub use windows::{mlock, munlock};
1922

20-
#[cfg(not(target_arch = "wasm32"))]
23+
#[cfg(not(any(target_arch = "wasm32", target_os = "motor")))]
2124
mod error {
2225
use std::error::Error;
2326
use std::fmt::Display;
@@ -56,5 +59,5 @@ mod error {
5659
impl Error for MemoryLockError {}
5760
}
5861

59-
#[cfg(not(target_arch = "wasm32"))]
62+
#[cfg(not(any(target_arch = "wasm32", target_os = "motor")))]
6063
pub use error::MemoryLockError;

pageant/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ edition = "2024"
66
license = "Apache-2.0"
77
name = "pageant"
88
repository = "https://github.com/warp-tech/russh"
9-
version = "0.2.1"
9+
version = "0.2.2"
1010
rust-version = "1.85"
1111

1212
[dependencies]
@@ -45,4 +45,5 @@ namedpipes = [
4545
"dep:windows-strings",
4646
"windows/Win32_Security_Authentication_Identity",
4747
"windows/Win32_Security_Cryptography",
48+
"windows/Win32_System_WindowsProgramming",
4849
]

pageant/src/namedpipes.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ use windows::Win32::Security::Authentication::Identity::{GetUserNameExA, NameUse
1414
use windows::Win32::Security::Cryptography::{
1515
CRYPTPROTECTMEMORY_BLOCK_SIZE, CRYPTPROTECTMEMORY_CROSS_PROCESS, CryptProtectMemory,
1616
};
17+
use windows::Win32::System::WindowsProgramming::GetUserNameA;
1718
use windows_strings::PSTR;
1819

1920
use crate::Error;
@@ -65,11 +66,17 @@ impl PageantStream {
6566
Some(PSTR(name_buf.as_mut_ptr())),
6667
&mut name_length,
6768
) {
68-
// Pageant falls back to GetUserNameA here,
69-
// but as far as I can tell, all Versions of Windows supported by Rust today
70-
// should be able to answer the UserNameEx request - the comments in Pageant source
71-
// point to Windows XP and earlier compatibility...
72-
return Err(Error::from_win32());
69+
// GetUserNameExA fails on non-domain-joined machines, where no UPN
70+
// (NameUserPrincipal) is configured. Fall back to GetUserNameA
71+
// (the SAM account name), like the original PuTTY Pageant.
72+
debug!("GetUserNameExA failed, falling back to GetUserNameA");
73+
74+
let mut name_length = 0;
75+
// don't check result on this, always returns ERROR_INSUFFICIENT_BUFFER
76+
let _ = GetUserNameA(None, &mut name_length);
77+
78+
name_buf = vec![0u8; name_length as usize];
79+
GetUserNameA(Some(PSTR(name_buf.as_mut_ptr())), &mut name_length)?;
7380
}
7481

7582
//remove terminating null

pageant/src/wmmessage.rs

Lines changed: 8 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,11 @@ use delegate::delegate;
99
use log::debug;
1010
use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, DuplexStream, ReadBuf};
1111
use windows::Win32::Foundation::{CloseHandle, HANDLE, HWND, INVALID_HANDLE_VALUE, LPARAM, WPARAM};
12-
use windows::Win32::Security::{
13-
GetTokenInformation, InitializeSecurityDescriptor, PSECURITY_DESCRIPTOR, SECURITY_ATTRIBUTES,
14-
SECURITY_DESCRIPTOR, SetSecurityDescriptorOwner, TOKEN_QUERY, TOKEN_USER, TokenUser,
15-
};
1612
use windows::Win32::System::DataExchange::COPYDATASTRUCT;
1713
use windows::Win32::System::Memory::{
1814
CreateFileMappingW, FILE_MAP_WRITE, MEMORY_MAPPED_VIEW_ADDRESS, MapViewOfFile, PAGE_READWRITE,
1915
UnmapViewOfFile,
2016
};
21-
use windows::Win32::System::Threading::{GetCurrentProcess, OpenProcessToken};
2217
use windows::Win32::UI::WindowsAndMessaging::{FindWindowW, SendMessageA, WM_COPYDATA};
2318
use windows::core::HSTRING;
2419

@@ -112,15 +107,13 @@ struct MemoryMap {
112107
}
113108

114109
impl MemoryMap {
115-
fn new(
116-
name: String,
117-
length: usize,
118-
security_attributes: Option<SECURITY_ATTRIBUTES>,
119-
) -> Result<Self, Error> {
110+
fn new(name: String, length: usize) -> Result<Self, Error> {
120111
let filemap = unsafe {
121112
CreateFileMappingW(
122113
INVALID_HANDLE_VALUE,
123-
security_attributes.map(|sa| &sa as *const _),
114+
// Default security descriptor from the process token: owned by the
115+
// current user, which is what Pageant's owner check expects
116+
None,
124117
PAGE_READWRITE,
125118
0,
126119
length as u32,
@@ -202,61 +195,20 @@ pub fn is_pageant_running() -> bool {
202195
find_pageant_window().is_ok()
203196
}
204197

205-
fn get_current_process_user() -> Result<TOKEN_USER, Error> {
206-
unsafe {
207-
let mut process_token = HANDLE::default();
208-
OpenProcessToken(
209-
GetCurrentProcess(),
210-
TOKEN_QUERY,
211-
&mut process_token as *mut _,
212-
)?;
213-
214-
let mut info_size = 0;
215-
let _ = GetTokenInformation(process_token, TokenUser, None, 0, &mut info_size);
216-
217-
let mut buffer = vec![0; info_size as usize];
218-
GetTokenInformation(
219-
process_token,
220-
TokenUser,
221-
Some(buffer.as_mut_ptr() as *mut _),
222-
buffer.len() as u32,
223-
&mut info_size,
224-
)?;
225-
let user: TOKEN_USER = *(buffer.as_ptr() as *const _);
226-
let _ = CloseHandle(process_token);
227-
Ok(user)
228-
}
229-
}
230-
231198
/// Send a one-off query to Pageant and return a response.
232199
pub fn query_pageant_direct(cookie: String, msg: &[u8]) -> Result<Vec<u8>, Error> {
233200
let hwnd = find_pageant_window()?;
234201
let map_name = format!("PageantRequest{cookie}");
235202

236-
let user = get_current_process_user()?;
237-
238-
let mut sd = SECURITY_DESCRIPTOR::default();
239-
let sa = SECURITY_ATTRIBUTES {
240-
lpSecurityDescriptor: &mut sd as *mut _ as *mut _,
241-
bInheritHandle: true.into(),
242-
nLength: size_of::<SECURITY_ATTRIBUTES>() as u32,
243-
};
244-
245-
let psd = PSECURITY_DESCRIPTOR(&mut sd as *mut _ as *mut _);
246-
247-
unsafe {
248-
InitializeSecurityDescriptor(psd, 1)?;
249-
SetSecurityDescriptorOwner(psd, Some(user.User.Sid), false)?;
250-
}
251-
252-
let mut map: MemoryMap = MemoryMap::new(map_name.clone(), _AGENT_MAX_MSGLEN, Some(sa))?;
203+
let mut map: MemoryMap = MemoryMap::new(map_name.clone(), _AGENT_MAX_MSGLEN)?;
253204
map.write(msg)?;
254205

255206
let char_buffer = CString::new(map_name.as_bytes()).map_err(|_| Error::InvalidCookie)?;
207+
let char_buffer_bytes = char_buffer.as_bytes_with_nul();
256208
let cds = COPYDATASTRUCT {
257209
dwData: _AGENT_COPYDATA_ID as usize,
258-
cbData: char_buffer.as_bytes().len() as u32,
259-
lpData: char_buffer.as_bytes().as_ptr() as *mut _,
210+
cbData: char_buffer_bytes.len() as u32,
211+
lpData: char_buffer_bytes.as_ptr() as *mut _,
260212
};
261213

262214
let response = unsafe {

russh/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ license = "Apache-2.0"
99
name = "russh"
1010
readme = "../README.md"
1111
repository = "https://github.com/warp-tech/russh"
12-
version = "0.62.5"
12+
version = "0.62.7"
1313
rust-version = "1.85"
1414

1515
[features]

0 commit comments

Comments
 (0)