windows_lsa/lib.rs
1//! # windows-lsa
2//!
3//! Thin, safe wrapper around the Windows Local Security Authority (LSA)
4//! **Kerberos authentication package** primitives:
5//!
6//! - [`LsaConnectUntrusted`] — get a handle to LSA that non-privileged code can use.
7//! - [`LsaLookupAuthenticationPackage`] — resolve the `"Kerberos"` package id.
8//! - [`LsaCallAuthenticationPackage`] with:
9//! - `KerbRetrieveTicketMessage` — pull the current TGT.
10//! - `KerbQueryTicketCacheMessage` — enumerate the LSA ticket cache.
11//! - `KerbSubmitTicketMessage` — inject a KRB-CRED into the cache.
12//! - `KerbPurgeTicketCacheMessage` — purge specific / all entries.
13//!
14//! Status: **pre-alpha, 0.1.0-dev.** API surface is stable-ish, but structural
15//! parsing of the returned Kerberos payloads is minimal (raw byte extraction
16//! only — no ASN.1 decode, no KRB-CRED wrapping). Enough to prove the LSA
17//! plumbing works round-trip; not enough to be a drop-in Mimikatz replacement.
18//!
19//! On non-Windows targets the crate compiles to a stub that returns
20//! [`Error::Unsupported`] for every call, so downstream crates can `cfg`-gate
21//! at their own convenience.
22
23#![deny(unsafe_op_in_unsafe_fn)]
24#![warn(missing_debug_implementations)]
25
26mod error;
27mod types;
28
29pub use error::{Error, Result};
30pub use types::{AuthPackageId, KrbCred, Luid, TicketCacheInfo};
31
32#[cfg(windows)]
33mod sys;
34
35#[cfg(windows)]
36pub use sys::{Lsa, LsaHandle};
37
38#[cfg(not(windows))]
39mod stub;
40
41#[cfg(not(windows))]
42pub use stub::{Lsa, LsaHandle};
43
44/// Convenience: connect, look up Kerberos, retrieve the TGT for the current
45/// logon session (or the caller-supplied LUID if `luid` is `Some` and the
46/// caller holds `SeTcbPrivilege`).
47///
48/// This is what most callers actually want. It performs `LsaConnectUntrusted`,
49/// resolves the Kerberos package id, and issues `KerbRetrieveTicketMessage`.
50pub fn retrieve_tgt(luid: Option<Luid>) -> Result<KrbCred> {
51 let h = Lsa::connect_untrusted()?;
52 let pkg = h.kerberos_package()?;
53 h.retrieve_tgt(pkg, luid)
54}
55
56/// Convenience wrapper around `KerbQueryTicketCacheMessage`.
57pub fn query_ticket_cache(luid: Option<Luid>) -> Result<Vec<TicketCacheInfo>> {
58 let h = Lsa::connect_untrusted()?;
59 let pkg = h.kerberos_package()?;
60 h.query_ticket_cache(pkg, luid)
61}
62
63/// Convenience wrapper around `KerbSubmitTicketMessage`.
64///
65/// `cred.encoded` is passed through verbatim — it MUST already be a valid
66/// ASN.1-DER `KRB-CRED` structure. This crate does not yet build KRB-CRED
67/// wrappers for you.
68pub fn submit_ticket(cred: &KrbCred, luid: Option<Luid>) -> Result<()> {
69 let h = Lsa::connect_untrusted()?;
70 let pkg = h.kerberos_package()?;
71 h.submit_ticket(pkg, cred, luid)
72}
73
74/// Convenience wrapper around `KerbPurgeTicketCacheMessage`.
75///
76/// If `target_spn` is `None`, every ticket in the cache for `luid` is purged.
77pub fn purge_ticket_cache(luid: Option<Luid>, target_spn: Option<&str>) -> Result<()> {
78 let h = Lsa::connect_untrusted()?;
79 let pkg = h.kerberos_package()?;
80 h.purge_ticket_cache(pkg, luid, target_spn)
81}