Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ async fn flip_the_table(p: process::Process) -> process::ProcessResult<prettytab
table.add_row(row!["PID", p.pid()]);
table.add_row(row!["Parent PID", p.parent_pid().await?]);
table.add_row(row!["Name", p.name().await?]);
table.add_row(row!["User", p.user().await?.username()]);
Comment thread
sandorex marked this conversation as resolved.
table.add_row(row!["Exe", p.exe().await?.display()]);
#[cfg(not(target_os = "windows"))] // Not implemented yet
table.add_row(row!["Command", format!("{:?}", p.command().await?)]);
Expand Down
12 changes: 11 additions & 1 deletion heim-host/src/os/windows.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
//! Windows-specific extensions.

use std::net::IpAddr;
use winapi::um::winnt::PSID;

use heim_common::Result;

/// Extension for [User] struct.
///
/// [User]: ../../struct.User.html
pub trait UserExt {
pub trait UserExt: Sized {
#[doc(hidden)]
fn try_from_sid(sid: PSID) -> Result<Self>;
Comment thread
sandorex marked this conversation as resolved.

/// Domain name that the user belongs to.
fn domain(&self) -> &str;

Expand All @@ -26,6 +32,10 @@ pub trait UserExt {

#[cfg(target_os = "windows")]
impl UserExt for crate::User {
fn try_from_sid(sid: PSID) -> Result<Self> {
crate::sys::User::try_from_sid(sid).map(crate::User::from)
}

fn domain(&self) -> &str {
self.as_ref().domain()
}
Expand Down
42 changes: 42 additions & 0 deletions heim-host/src/sys/windows/users.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
use std::net::IpAddr;
use std::ptr;
use winapi::shared::minwindef::DWORD;
use winapi::um::winbase::LookupAccountSidW;
use winapi::um::winnt::{PSID, PSID_NAME_USE, SID_NAME_USE, WCHAR};

use super::wrappers::{Session, Sessions};
use heim_common::prelude::*;
Expand Down Expand Up @@ -27,6 +31,44 @@ impl User {
}))
}

pub fn try_from_sid(sid: PSID) -> Result<Self> {
// name and domain cannot be longer than 256
let mut name_cch: DWORD = 256;
let mut name: Vec<WCHAR> = Vec::with_capacity(name_cch as usize);
let mut domain_cch: DWORD = 256;
let mut domain: Vec<WCHAR> = Vec::with_capacity(domain_cch as usize);

// winapi does not have SID_NAME_USE enum
let mut account_type: SID_NAME_USE = 0;
Comment thread
sandorex marked this conversation as resolved.

let result = unsafe {
LookupAccountSidW(
ptr::null(),
sid,
name.as_mut_ptr(),
&mut name_cch,
domain.as_mut_ptr(),
&mut domain_cch,
&mut account_type as PSID_NAME_USE,
)
};

if result == 0 {
return Err(Error::last_os_error());
Comment thread
sandorex marked this conversation as resolved.
Outdated
}

unsafe {
name.set_len(name_cch as usize);
domain.set_len(domain_cch as usize);
}

Ok(Self {
domain: String::from_utf16(domain.as_slice()).unwrap(),
username: String::from_utf16(name.as_slice()).unwrap(),
Comment thread
sandorex marked this conversation as resolved.
Outdated
address: None,
})
}

pub fn domain(&self) -> &str {
self.domain.as_str()
}
Expand Down
6 changes: 3 additions & 3 deletions heim-process/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ github-actions = { repository = "heim-rs/heim", workflow = "Tier 1 CI" }
heim-common = { version = "0.1.0-alpha.1", path = "../heim-common" }
heim-runtime = { version = "0.1.0-alpha.1", path = "../heim-runtime", default-features = false }
heim-cpu = { version = "0.1.0-alpha.1", path = "../heim-cpu", default-features = false }
heim-host = { version = "0.1.0-alpha.1", path = "../heim-host", default-features = false }
cfg-if = "~0.1"
libc = "~0.2"
lazy_static = "1.3.0"
Expand All @@ -27,10 +28,8 @@ async-trait = "~0.1"

[target.'cfg(target_os = "linux")'.dependencies]
heim-net = { version = "0.1.0-alpha.1", path = "../heim-net", default-features = false }
heim-host = { version = "0.1.0-alpha.1", path = "../heim-host", default-features = false }

[target.'cfg(target_os = "windows")'.dependencies]
heim-host = { version = "0.1.0-alpha.1", path = "../heim-host", default-features = false }
ntapi = "0.3.3"

[target.'cfg(target_os = "windows")'.dependencies.winapi]
Expand All @@ -45,7 +44,8 @@ features = [
"psapi",
"processthreadsapi",
"winerror",
"tlhelp32"
"tlhelp32",
"securitybaseapi"
]

[target.'cfg(target_os = "macos")'.dependencies]
Expand Down
6 changes: 6 additions & 0 deletions heim-process/src/process/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use std::time::Instant;

use heim_common::prelude::*;
use heim_common::units::Time;
use heim_host::User;

use crate::{sys, Pid, ProcessResult};

Expand Down Expand Up @@ -165,6 +166,11 @@ impl Process {
self.as_ref().memory().await.map(Into::into)
}

/// Returns user who owns this process.
pub async fn user(&self) -> ProcessResult<User> {
self.as_ref().user().await.map(Into::into)
}

/// Checks if this `Process` is still running.
pub async fn is_running(&self) -> ProcessResult<bool> {
self.as_ref().is_running().await
Expand Down
9 changes: 9 additions & 0 deletions heim-process/src/sys/linux/process/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::path::{Path, PathBuf};

use heim_common::prelude::*;
use heim_common::units::Time;
use heim_host::User;
use heim_runtime as rt;

use super::{pid_exists, pids};
Expand Down Expand Up @@ -122,6 +123,14 @@ impl Process {
procfs::stat_memory(self.pid).await
}

pub async fn user(&self) -> ProcessResult<User> {
// TODO: implement
// 1. Read `/proc/{pid}/stat` or smth else
// 2. parse uid and gid
// 3. Construct `heim_host::User` from them
unimplemented!("https://github.com/heim-rs/heim/issues/194")
}

pub async fn is_running(&self) -> ProcessResult<bool> {
let other = get(self.pid).await?;

Expand Down
7 changes: 7 additions & 0 deletions heim-process/src/sys/macos/process/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use futures::future::BoxFuture;
use heim_common::prelude::*;
use heim_common::sys::IntoTime;
use heim_common::units::Time;
use heim_host::User;

use super::{bindings, pids, utils::catch_zombie};
use crate::os::unix::Signal;
Expand Down Expand Up @@ -114,6 +115,12 @@ impl Process {
}
}

pub async fn user(&self) -> ProcessResult<User> {
// Fetch user infomation with `darwin_libproc` help,
// construct user from this information somehow.
unimplemented!("https://github.com/heim-rs/heim/issues/194")
}

pub async fn is_running(&self) -> ProcessResult<bool> {
let other = get(self.pid).await?;

Expand Down
10 changes: 10 additions & 0 deletions heim-process/src/sys/windows/bindings/handle/limited_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ use winapi::um::{processthreadsapi, psapi, winbase, winnt};
use heim_common::sys::IntoTime;
use heim_common::units::{time, Time};
use heim_common::Error;
use heim_host::User;

use super::super::token::Token;
use super::{ProcessHandle, ProcessHandlePermissions};
use crate::sys::windows::process::CpuTime;
use crate::{Pid, ProcessError, ProcessResult};
Expand Down Expand Up @@ -139,4 +141,12 @@ impl ProcessHandle<QueryLimitedInformation> {
Ok((creation, exit, kernel, user))
}
}

pub fn owner(&self) -> ProcessResult<User> {
// TODO clean this up?
match Token::open(&self.handle)?.user() {
Ok(x) => Ok(x),
Err(e) => Err(e.into()),
}
Comment thread
sandorex marked this conversation as resolved.
Outdated
}
}
1 change: 1 addition & 0 deletions heim-process/src/sys/windows/bindings/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use heim_common::{Error, Result};
pub mod handle;
pub mod processes;
pub mod snapshot;
pub mod token;

pub use self::handle::ProcessHandle;

Expand Down
66 changes: 66 additions & 0 deletions heim-process/src/sys/windows/bindings/token.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
use std::ptr;
use winapi::shared::minwindef::{DWORD, LPVOID};
use winapi::um::handleapi::CloseHandle;
use winapi::um::processthreadsapi::OpenProcessToken;
use winapi::um::securitybaseapi::GetTokenInformation;
use winapi::um::winnt::{TokenUser, HANDLE, TOKEN_QUERY, TOKEN_USER};

use heim_common::prelude::*;
use heim_common::sys::windows::Handle;
use heim_common::Result;
use heim_host::os::windows::UserExt;
use heim_host::User;

pub struct Token(HANDLE);

impl Token {
pub fn open(process_handle: &Handle) -> Result<Self> {
let mut token_handle: HANDLE = ptr::null_mut();
Comment thread
sandorex marked this conversation as resolved.

let result = unsafe { OpenProcessToken(**process_handle, TOKEN_QUERY, &mut token_handle) };

if result == 0 {
return Err(Error::last_os_error().with_ffi("OpenProcessToken"));
}

Ok(Self(token_handle))
}

pub fn user(&self) -> Result<User> {
// data should always be 44 bytes
let mut data: Vec<u8> = Vec::with_capacity(64);
Comment thread
sandorex marked this conversation as resolved.
Outdated
let mut length: DWORD = 0;

let result = unsafe {
GetTokenInformation(
self.0,
TokenUser,
data.as_mut_ptr() as LPVOID,
data.capacity() as DWORD,
&mut length,
)
};

if result == 0 {
return Err(Error::last_os_error().with_ffi("GetTokenInformation"));
}

unsafe { data.set_len(length as usize) };

let token_user = unsafe { ptr::read(data.as_ptr() as *const TOKEN_USER) };

User::try_from_sid(token_user.User.Sid)
}
}

impl Drop for Token {
fn drop(&mut self) {
let result = unsafe { CloseHandle(self.0) };

assert!(
result != 0,
"{:?}",
Error::last_os_error().with_ffi("CloseHandle")
);
}
}
11 changes: 11 additions & 0 deletions heim-process/src/sys/windows/process/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use std::path::PathBuf;

use heim_common::prelude::*;
use heim_common::units::Time;
use heim_host::User;
use winapi::um::processthreadsapi;

use super::{bindings, pid_exists, pids};
Expand Down Expand Up @@ -142,6 +143,16 @@ impl Process {
}
}

pub async fn user(&self) -> ProcessResult<User> {
if self.pid == 0 || self.pid == 4 {
Err(ProcessError::AccessDenied(self.pid))
} else {
let handle = bindings::ProcessHandle::query_limited_info(self.pid)?;

handle.owner()
}
}

pub async fn is_running(&self) -> ProcessResult<bool> {
let other = get(self.pid).await?;

Expand Down
1 change: 1 addition & 0 deletions heim-process/tests/smoke.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ async fn smoke_processes() {
let _ = process.pid();
try_method!(process.parent_pid());
try_method!(process.name());
try_method!(process.user());
try_method!(process.command());
try_method!(process.exe());
#[cfg(not(target_os = "windows"))] // Not implemented yet
Expand Down