### Example Usage of Documented Function Source: https://docs.rs/cross-krb5/latest/scrape-examples-help.html Shows how to call a documented function from another crate within an example file. ```rust // examples/ex.rs fn main() { a_crate::a_func(); } ``` -------------------------------- ### Kerberos 5 Client-Server Example Source: https://docs.rs/cross-krb5/latest/cross_krb5 Demonstrates a full client-server interaction using cross-krb5 for Kerberos authentication. Requires a service principal name (SPN) as a command-line argument. This example showcases context initiation, step-by-step context establishment, message wrapping, and unwrapping. ```rust use bytes::Bytes; use cross_krb5::{AcceptFlags, ClientCtx, InitiateFlags, K5Ctx, Step, ServerCtx}; use std::{env::args, process::exit, sync::mpsc, thread}; enum Msg { Token(Bytes), Msg(Bytes), } fn server(spn: String, input: mpsc::Receiver, output: mpsc::Sender) { let mut server = ServerCtx::new(AcceptFlags::empty(), Some(&spn), None).expect("new"); let mut server = loop { let token = match input.recv().expect("expected data") { Msg::Msg(_) => panic!("server not finished initializing"), Msg::Token(t) => t, }; match server.step(&*token).expect("step") { Step::Finished((ctx, token)) => { if let Some(token) = token { output.send(Msg::Token(Bytes::copy_from_slice(&*token))).expect("send"); } break ctx }, Step::Continue((ctx, token)) => { output.send(Msg::Token(Bytes::copy_from_slice(&*token))).expect("send"); server = ctx; } } }; match input.recv().expect("expected data msg") { Msg::Token(_) => panic!("unexpected extra token"), Msg::Msg(secret_msg) => println!( "{}", String::from_utf8_lossy(&server.unwrap(&*secret_msg).expect("unwrap")) ), } } fn client(spn: &str, input: mpsc::Receiver, output: mpsc::Sender) { let (mut client, token) = ClientCtx::new(InitiateFlags::empty(), None, spn, None).expect("new"); output.send(Msg::Token(Bytes::copy_from_slice(&*token))).expect("send"); let mut client = loop { let token = match input.recv().expect("expected data") { Msg::Msg(_) => panic!("client not finished initializing"), Msg::Token(t) => t, }; match client.step(&*token).expect("step") { Step::Finished((ctx, token)) => { if let Some(token) = token { output.send(Msg::Token(Bytes::copy_from_slice(&*token))).expect("send"); } break ctx }, Step::Continue((ctx, token)) => { output.send(Msg::Token(Bytes::copy_from_slice(&*token))).expect("send"); client = ctx; } } }; let msg = client.wrap(true, b"super secret message").expect("wrap"); output.send(Msg::Msg(Bytes::copy_from_slice(&*msg))).expect("send"); } fn main() { let args = args().collect::>(); if args.len() != 2 { println!("usage: {}: ", args[0]); exit(1); } let spn = String::from(&args[1]); let (server_snd, server_recv) = mpsc::channel(); let (client_snd, client_recv) = mpsc::channel(); thread::spawn(move || server(spn, server_recv, client_snd)); client(&args[1], client_recv, server_snd); } ``` -------------------------------- ### Kerberos Authentication Example in Rust Source: https://docs.rs/cross-krb5/latest/src/auth/auth.rs.html This example implements a full Kerberos authentication handshake between a client and server within the same process. It requires a Service Principal Name (SPN) as a command-line argument. Note the platform-specific considerations for Windows. ```rust use bytes::Bytes; use cross_krb5::{AcceptFlags, ClientCtx, InitiateFlags, K5Ctx, ServerCtx, Step}; use std::{env::args, process::exit, sync::mpsc, thread}; // The auth example pushes the server and the client in one process, which SSPI // has issues with because keytabs are not a thing in windows. You can work around // this by running it as SYSTEM and targeting the machine account, assuming you are // joined to a domain. // // ```` // schtasks /create /tn krbtest /ru SYSTEM /sc once /st 23:59 /f /tr "cmd /c cd /d C:\Users\eric\proj\cross-krb5 && .\target\debug\examples\auth.exe HOST/win11-test-vm.ryu-oh.org > C:\krbtest.txt 2>&1" // schtasks /run /tn krbtest & timeout 2 & type C:\krbtest.txt // schtasks /delete /tn krbtest /f // ```` enum Msg { Token(Bytes), Msg(Bytes), } fn server(spn: String, input: mpsc::Receiver, output: mpsc::Sender) { let mut server = ServerCtx::new(AcceptFlags::empty(), Some(&spn), None).expect("new"); let mut server = loop { let token = match input.recv().expect("expected data") { Msg::Msg(_) => panic!("server not finished initializing"), Msg::Token(t) => t, }; match server.step(&*token).expect("step") { Step::Finished((ctx, token)) => { if let Some(token) = token { output .send(Msg::Token(Bytes::copy_from_slice(&*token))) .expect("send"); } break ctx; } Step::Continue((ctx, token)) => { output.send(Msg::Token(Bytes::copy_from_slice(&*token))).expect("send"); server = ctx; } } }; match input.recv().expect("expected data msg") { Msg::Token(_) => panic!("unexpected extra token"), Msg::Msg(secret_msg) => println!( "{}", String::from_utf8_lossy(&server.unwrap(&*secret_msg).expect("unwrap")) ), } } fn client(spn: &str, input: mpsc::Receiver, output: mpsc::Sender) { let (mut client, token) = ClientCtx::new(InitiateFlags::empty(), None, spn, None).expect("new"); output.send(Msg::Token(Bytes::copy_from_slice(&*token))).expect("send"); let mut client = loop { let token = match input.recv().expect("expected data") { Msg::Msg(_) => panic!("client not finished initializing"), Msg::Token(t) => t, }; match client.step(&*token).expect("step") { Step::Finished((ctx, token)) => { if let Some(token) = token { output .send(Msg::Token(Bytes::copy_from_slice(&*token))) .expect("send"); } break ctx; } Step::Continue((ctx, token)) => { output.send(Msg::Token(Bytes::copy_from_slice(&*token))).expect("send"); client = ctx; } } }; let msg = client.wrap(true, b"super secret message").expect("wrap"); output.send(Msg::Msg(Bytes::copy_from_slice(&*msg))).expect("send"); } fn main() { let args = args().collect::>(); if args.len() != 2 { println!("usage: {}: ", args[0]); exit(1); } let spn = String::from(&args[1]); let (server_snd, server_recv) = mpsc::channel(); let (client_snd, client_recv) = mpsc::channel(); thread::spawn(move || server(spn, server_recv, client_snd)); client(&args[1], client_recv, server_snd); } ``` -------------------------------- ### Documented Function Example Source: https://docs.rs/cross-krb5/latest/scrape-examples-help.html Illustrates a basic public function in a crate that can be used in examples. ```rust // src/lib.rs pub fn a_func() {} ``` -------------------------------- ### Client Initialization Step Source: https://docs.rs/cross-krb5/latest/cross_krb5/struct.PendingClientCtx.html This example demonstrates how to feed a server-provided token to a client context to perform one step of the initialization process. It handles both continuing the initialization and finishing it, returning the established context or the pending context with the next token. ```rust fn client(spn: &str, input: mpsc::Receiver, output: mpsc::Sender) { let (mut client, token) = ClientCtx::new(InitiateFlags::empty(), None, spn, None).expect("new"); output.send(Msg::Token(Bytes::copy_from_slice(&*token))).expect("send"); let mut client = loop { let token = match input.recv().expect("expected data") { Msg::Msg(_) => panic!("client not finished initializing"), Msg::Token(t) => t, }; match client.step(&*token).expect("step") { Step::Finished((ctx, token)) => { if let Some(token) = token { output .send(Msg::Token(Bytes::copy_from_slice(&*token))) .expect("send"); } break ctx; } Step::Continue((ctx, token)) => { output.send(Msg::Token(Bytes::copy_from_slice(&*token))).expect("send"); client = ctx; } } }; let msg = client.wrap(true, b"super secret message").expect("wrap"); output.send(Msg::Msg(Bytes::copy_from_slice(&*msg))).expect("send"); } ``` -------------------------------- ### Full Kerberos 5 Client-Server Example Source: https://docs.rs/cross-krb5/latest/src/cross_krb5/lib.rs.html Demonstrates a complete client-server interaction using cross-krb5 for secure communication. Requires a service principal name as a command-line argument. ```rust use bytes::Bytes; use cross_krb5::{AcceptFlags, ClientCtx, InitiateFlags, K5Ctx, Step, ServerCtx}; use std::{env::args, process::exit, sync::mpsc, thread}; enum Msg { Token(Bytes), Msg(Bytes), } fn server(spn: String, input: mpsc::Receiver, output: mpsc::Sender) { let mut server = ServerCtx::new(AcceptFlags::empty(), Some(&spn), None).expect("new"); let mut server = loop { let token = match input.recv().expect("expected data") { Msg::Msg(_) => panic!("server not finished initializing"), Msg::Token(t) => t, }; match server.step(&*token).expect("step") { Step::Finished((ctx, token)) => { if let Some(token) = token { output.send(Msg::Token(Bytes::copy_from_slice(&*token))).expect("send"); } break ctx }, Step::Continue((ctx, token)) => { output.send(Msg::Token(Bytes::copy_from_slice(&*token))).expect("send"); server = ctx; } } }; match input.recv().expect("expected data msg") { Msg::Token(_) => panic!("unexpected extra token"), Msg::Msg(secret_msg) => println!( "{}", String::from_utf8_lossy(&server.unwrap(&*secret_msg).expect("unwrap")) ), } } fn client(spn: &str, input: mpsc::Receiver, output: mpsc::Sender) { let (mut client, token) = ClientCtx::new(InitiateFlags::empty(), None, spn, None).expect("new"); output.send(Msg::Token(Bytes::copy_from_slice(&*token))).expect("send"); let mut client = loop { let token = match input.recv().expect("expected data") { Msg::Msg(_) => panic!("client not finished initializing"), Msg::Token(t) => t, }; match client.step(&*token).expect("step") { Step::Finished((ctx, token)) => { if let Some(token) = token { output.send(Msg::Token(Bytes::copy_from_slice(&*token))).expect("send"); } break ctx }, Step::Continue((ctx, token)) => { output.send(Msg::Token(Bytes::copy_from_slice(&*token))).expect("send"); client = ctx; } } }; let msg = client.wrap(true, b"super secret message").expect("wrap"); output.send(Msg::Msg(Bytes::copy_from_slice(&*msg))).expect("send"); } fn main() { let args = args().collect::>(); if args.len() != 2 { println!("usage: {}: ", args[0]); exit(1); } let spn = String::from(&args[1]); let (server_snd, server_recv) = mpsc::channel(); let (client_snd, client_recv) = mpsc::channel(); thread::spawn(move || server(spn, server_recv, client_snd)); client(&args[1], client_recv, server_snd); } ``` -------------------------------- ### Server Initialization and Step Processing Source: https://docs.rs/cross-krb5/latest/cross_krb5/struct.PendingServerCtx.html This example demonstrates how a server context is initialized and how it processes incoming tokens using the `step` method. It handles both continuation and finished states of the authentication process. ```rust fn server(spn: String, input: mpsc::Receiver, output: mpsc::Sender) { let mut server = ServerCtx::new(AcceptFlags::empty(), Some(&spn), None).expect("new"); let mut server = loop { let token = match input.recv().expect("expected data") { Msg::Msg(_) => panic!("server not finished initializing"), Msg::Token(t) => t, }; match server.step(&*token).expect("step") { Step::Finished((ctx, token)) => { if let Some(token) = token { output .send(Msg::Token(Bytes::copy_from_slice(&*token))) .expect("send"); } break ctx; } Step::Continue((ctx, token)) => { output.send(Msg::Token(Bytes::copy_from_slice(&*token))).expect("send"); server = ctx; } } }; match input.recv().expect("expected data msg") { Msg::Token(_) => panic!("unexpected extra token"), Msg::Msg(secret_msg) => println!( "{}", String::from_utf8_lossy(&server.unwrap(&*secret_msg).expect("unwrap")) ), } } ``` -------------------------------- ### InitiateFlags Default Value and Extension Source: https://docs.rs/cross-krb5/latest/cross_krb5/struct.InitiateFlags.html Explains how to get the default `InitiateFlags` value and how to extend `InitiateFlags` with other flag values. ```APIDOC ## Default Value and Extension ### Default Value - **Function**: `default() -> Self` - **Description**: Returns the secure default `InitiateFlags`. In this default state, mutual authentication and confidentiality are both required, as nothing is disabled. ### Extension - **Function**: `extend>(&mut self, iterator: T)` - **Description**: Extends the current `InitiateFlags` by performing a bitwise OR with all flag values from the provided iterator. - **Function**: `extend_one(&mut self, item: A)` - **Description**: Extends the collection with a single `InitiateFlags` item. (Nightly-only experimental API) - **Function**: `extend_reserve(&mut self, additional: usize)` - **Description**: Reserves capacity for additional elements. (Nightly-only experimental API) ``` -------------------------------- ### Initialize Server Context with Empty AcceptFlags Source: https://docs.rs/cross-krb5/latest/cross_krb5/struct.AcceptFlags.html Demonstrates initializing a ServerCtx with empty AcceptFlags. This is typically used when starting a new server context without any pre-set flags. ```rust let mut server = ServerCtx::new(AcceptFlags::empty(), Some(&spn), None).expect("new"); ``` -------------------------------- ### InitiateFlags::empty Source: https://docs.rs/cross-krb5/latest/cross_krb5/struct.InitiateFlags.html Get a flags value with all bits unset. This is useful for starting with a clean slate. ```APIDOC ## InitiateFlags::empty ### Description Get a flags value with all bits unset. ### Method `const fn empty() -> Self` ``` -------------------------------- ### InitiateFlags::all Source: https://docs.rs/cross-krb5/latest/cross_krb5/struct.InitiateFlags.html Get a flags value with all known bits set. This is useful for representing a state where all possible options are enabled. ```APIDOC ## InitiateFlags::all ### Description Get a flags value with all known bits set. ### Method `const fn all() -> Self` ``` -------------------------------- ### AcceptFlags::bits Source: https://docs.rs/cross-krb5/latest/cross_krb5/struct.AcceptFlags.html Get the underlying bits value. ```APIDOC ## AcceptFlags::bits ### Description Get the underlying bits value. The returned value is exactly the bits set in this flags value. ### Method `const fn bits(&self) -> u32` ``` -------------------------------- ### Client Context Initialization Step Source: https://docs.rs/cross-krb5/latest/src/cross_krb5/lib.rs.html Feeds a server-provided token to the client context, performing one step of initialization. Returns the established context and an optional final token if initialization is complete, or a pending context and a token to send to the server otherwise. ```rust pub fn step( self, token: &[u8], ) -> Result< Step< (ClientCtx, Option>), (PendingClientCtx, impl Deref), >, > { Ok(match self.0.step(token)? { Step::Finished((ctx, tok)) => { Step::Finished((ClientCtx(ctx), tok)) } Step::Continue((ctx, tok)) => { Step::Continue((PendingClientCtx(ctx), tok)) } }) } ``` -------------------------------- ### AcceptFlags::empty Source: https://docs.rs/cross-krb5/latest/cross_krb5/struct.AcceptFlags.html Get a flags value with all bits unset. ```APIDOC ## AcceptFlags::empty ### Description Get a flags value with all bits unset. ### Method `const fn empty() -> Self` ### Examples ```rust // Example usage from repository: // let mut server = ServerCtx::new(AcceptFlags::empty(), Some(&spn), None).expect("new"); ``` ``` -------------------------------- ### InitiateFlags Implementations Source: https://docs.rs/cross-krb5/latest/cross_krb5/struct.InitiateFlags.html Details on the implementations for InitiateFlags, including FromIterator, IntoIterator, LowerHex, Not, Octal, PartialEq, and PublicFlags. ```APIDOC ### Implementations for InitiateFlags #### `impl FromIterator for InitiateFlags` - `from_iter>(iterator: T) -> Self` - The bitwise or (`|`) of the bits in each flags value. #### `impl IntoIterator for InitiateFlags` - `type Item = InitiateFlags` - The type of the elements being iterated over. - `type IntoIter = Iter` - Which kind of iterator are we turning this into? - `into_iter(self) -> Self::IntoIter` - Creates an iterator from a value. #### `impl LowerHex for InitiateFlags` - `fmt(&self, f: &mut Formatter<'_>) -> Result` - Formats the value using the given formatter. #### `impl Not for InitiateFlags` - `not(self) -> Self` - The bitwise negation (`!`) of the bits in `self`, truncating the result. - `type Output = InitiateFlags` - The resulting type after applying the `!` operator. #### `impl Octal for InitiateFlags` - `fmt(&self, f: &mut Formatter<'_>) -> Result` - Formats the value using the given formatter. #### `impl PartialEq for InitiateFlags` - `eq(&self, other: &InitiateFlags) -> bool` - Tests for `self` and `other` values to be equal, and is used by `==`. - `ne(&self, other: &Rhs) -> bool` - Tests for `!=`. #### `impl PublicFlags for InitiateFlags` - `type Primitive = u32` - The type of the underlying storage. - `type Internal = InternalBitFlags` - The type of the internal field on the generated flags type. ``` -------------------------------- ### AcceptFlags::all Source: https://docs.rs/cross-krb5/latest/cross_krb5/struct.AcceptFlags.html Get a flags value with all known bits set. ```APIDOC ## AcceptFlags::all ### Description Get a flags value with all known bits set. ### Method `const fn all() -> Self` ``` -------------------------------- ### ClientCtx::new Source: https://docs.rs/cross-krb5/latest/src/cross_krb5/unix.rs.html Creates a new client context, acquiring credentials and initiating the security context with the target principal. ```APIDOC ## ClientCtx::new ### Description Initializes a new Kerberos client security context. This method first acquires the necessary credentials using `Cred::client_acquire` and then proceeds to establish the context with the target principal. ### Parameters - **flags** (InitiateFlags) - Flags to control the initiation of the client context, such as disabling mutual authentication or confidentiality. - **principal** (Option<&str>) - The principal name of the client, if available. If `None`, the default client principal will be used. - **target_principal** (&str) - The principal name of the target service or server. - **channel_bindings** (Option<&[u8]>) - Optional channel bindings to enhance security. ### Returns - Result<(PendingClientCtx, impl Deref)> - A tuple containing the `PendingClientCtx` for subsequent steps and the initial security token to be sent to the server. ``` -------------------------------- ### AcceptFlags::from_name Source: https://docs.rs/cross-krb5/latest/cross_krb5/struct.AcceptFlags.html Get a flags value with the bits of a flag with the given name set. ```APIDOC ## AcceptFlags::from_name ### Description Get a flags value with the bits of a flag with the given name set. This method will return `None` if `name` is empty or doesn’t correspond to any named flag. ### Method `pub fn from_name(name: &str) -> Option` ``` -------------------------------- ### ServerCtx::new Source: https://docs.rs/cross-krb5/latest/src/cross_krb5/lib.rs.html Creates a new, pending server context for Kerberos authentication. ```APIDOC ## ServerCtx::new ### Description Creates a new server context for `principal`, which should be the service principal name assigned to the service the client will be requesting. If it is left as `None` it will use the user running the current process. The returned pending context must be initialized by exchanging one or more tokens with the client before it can be used. If present, `channel_bindings` must match the bindings the client supplied to `ClientCtx::new`; the mechanism rejects the context otherwise. Note that with a `None` acceptor binding the mechanism generally accepts whatever the client sent, so to actually enforce channel binding the server must pass its own expected bindings here. ### Method ```rust pub fn new( flags: AcceptFlags, principal: Option<&str>, channel_bindings: Option<&[u8]>, ) -> Result ``` ### Parameters - **flags** (AcceptFlags): Flags to control the context establishment. - **principal** (Option<&str>): The service principal name. If `None`, the current process user is used. - **channel_bindings** (Option<&[u8]>): Optional channel bindings to verify against the client. ### Returns - `Result`: A `PendingServerCtx` if successful, otherwise an error. ``` -------------------------------- ### InitiateFlags::bits Source: https://docs.rs/cross-krb5/latest/cross_krb5/struct.InitiateFlags.html Get the underlying bits value of the flags. This returns the raw integer representation of the set bits. ```APIDOC ## InitiateFlags::bits ### Description Get the underlying bits value. ### Method `const fn bits(&self) -> u32` ``` -------------------------------- ### InitiateFlags Bitwise Operations Source: https://docs.rs/cross-krb5/latest/cross_krb5/struct.InitiateFlags.html Demonstrates the bitwise AND, OR, and XOR operations available for InitiateFlags, allowing for manipulation and combination of flag values. ```APIDOC ## Bitwise Operations for InitiateFlags ### Bitwise AND (`&`) - **Function**: `bitand(self, other: Self) -> Self` - **Description**: Computes the bitwise AND of two `InitiateFlags` values. ### Bitwise OR (`|`) - **Function**: `bitor(self, other: InitiateFlags) -> Self` - **Description**: Computes the bitwise OR of two `InitiateFlags` values. ### Bitwise XOR (`^`) - **Function**: `bitxor(self, other: Self) -> Self` - **Description**: Computes the bitwise XOR of two `InitiateFlags` values. ### Bitwise AND Assignment (`&=`) - **Function**: `bitand_assign(&mut self, other: Self)` - **Description**: Assigns the result of a bitwise AND operation to the left-hand side operand. ### Bitwise OR Assignment (`|=`) - **Function**: `bitor_assign(&mut self, other: Self)` - **Description**: Assigns the result of a bitwise OR operation to the left-hand side operand. ### Bitwise XOR Assignment (`^=`) - **Function**: `bitxor_assign(&mut self, other: Self)` - **Description**: Assigns the result of a bitwise XOR operation to the left-hand side operand. ``` -------------------------------- ### InitiateFlags::from_name Source: https://docs.rs/cross-krb5/latest/cross_krb5/struct.InitiateFlags.html Get a flags value with the bits of a flag with the given name set. Returns `None` if the name is invalid. ```APIDOC ## InitiateFlags::from_name ### Description Get a flags value with the bits of a flag with the given name set. This method will return `None` if `name` is empty or doesn’t correspond to any named flag. ### Method `pub fn from_name(name: &str) -> Option` ``` -------------------------------- ### ServerCtx Step Method Source: https://docs.rs/cross-krb5/latest/src/cross_krb5/unix.rs.html Processes an incoming token during the Kerberos authentication handshake. It returns `Step::Continue` if more tokens are needed, or `Step::Finished` with the established context and optional token if authentication is complete. ```rust pub(crate) fn step( mut self, token: &[u8], ) -> Result< Step< (ServerCtx, Option>), (PendingServerCtx, impl Deref), >, > { fn cc(gss: GssServerCtx, confidential: bool) -> ServerCtx { ServerCtx { gss, confidential, header: BytesMut::new(), padding: BytesMut::new(), trailer: BytesMut::new(), } } let confidential = !self.flags.contains(AcceptFlags::DISABLE_CONFIDENTIALITY); let tok = self.gss.step(token, self.cb.as_deref())?; if self.gss.is_complete() { verify_granted( self.gss.flags()?, !self.flags.contains(AcceptFlags::DISABLE_MUTUAL_AUTH), confidential, )?; } Ok(match tok { None => Step::Finished((cc(self.gss, confidential), None)), Some(tok) if self.gss.is_complete() => { Step::Finished((cc(self.gss, confidential), Some(tok))) } Some(tok) => Step::Continue((self, tok)), }) } ``` -------------------------------- ### InitiateFlags Methods Source: https://docs.rs/cross-krb5/latest/cross_krb5/struct.InitiateFlags.html Provides an overview of the methods available for the InitiateFlags type, including bit manipulation, conversion, and iteration. ```APIDOC ## InitiateFlags ### Constants - `FLAGS`: &'static [Flag] - The set of defined flags. ### Type Aliases - `Bits`: u32 - The underlying bits type. ### Methods - `bits(&self) -> u32` - Get the underlying bits value. - `from_bits_retain(bits: u32) -> InitiateFlags` - Convert from a bits value exactly. - `empty() -> Self` - Get a flags value with all bits unset. - `all() -> Self` - Get a flags value with all known bits set. - `known_bits(&self) -> Self::Bits` - Get the known bits from a flags value. - `unknown_bits(&self) -> Self::Bits` - Get the unknown bits from a flags value. - `contains_unknown_bits(&self) -> bool` - Returns `true` if any unknown bits are set. - `from_bits(bits: Self::Bits) -> Option` - Convert from a bits value. - `from_bits_truncate(bits: Self::Bits) -> Self` - Convert from a bits value, unsetting any unknown bits. - `from_name(name: &str) -> Option` - Get a flags value with the bits of a flag with the given name set. - `iter(&self) -> Iter` - Yield a set of contained flags values. - `iter_names(&self) -> IterNames` - Yield a set of contained named flags values. - `iter_defined_names() -> IterDefinedNames` - Yield a set of all named flags defined by `Self::FLAGS`. - `is_empty(&self) -> bool` - Whether all bits in this flags value are unset. - `is_all(&self) -> bool` - Whether all known bits in this flags value are set. - `intersects(&self, other: Self) -> bool` - Whether any set bits in `other` are also set in `self`. - `contains(&self, other: Self) -> bool` - Whether all set bits in `other` are also set in `self`. - `truncate(&mut self)` - Remove any unknown bits from the flags. - `insert(&mut self, other: Self)` - The bitwise or (`|`) of the bits in `self` and `other`. - `remove(&mut self, other: Self)` - The intersection of `self` with the complement of `other` (`&!`). - `toggle(&mut self, other: Self)` - The bitwise exclusive-or (`^`) of the bits in `self` and `other`. - `set(&mut self, other: Self, value: bool)` - Call `Flags::insert` when `value` is `true` or `Flags::remove` when `value` is `false`. - `clear(&mut self)` - Unsets all bits in the flags. - `intersection(self, other: Self) -> Self` - The bitwise and (`&`) of the bits in `self` and `other`. - `union(self, other: Self) -> Self` - The bitwise or (`|`) of the bits in `self` and `other`. - `difference(self, other: Self) -> Self` - The intersection of `self` with the complement of `other` (`&!`). - `symmetric_difference(self, other: Self) -> Self` - The bitwise exclusive-or (`^`) of the bits in `self` and `other`. - `complement(self) -> Self` - The bitwise negation (`!`) of the bits in `self`, truncating the result. ``` -------------------------------- ### Get Underlying Bits Value of AcceptFlags Source: https://docs.rs/cross-krb5/latest/cross_krb5/struct.AcceptFlags.html Retrieves the raw `u32` representation of the flags. This is useful for debugging or when interacting with systems that expect raw bitmasks. ```rust pub const fn bits(&self) -> u32 ``` -------------------------------- ### Create New Client Context with Credentials Source: https://docs.rs/cross-krb5/latest/src/cross_krb5/lib.rs.html Creates a new client context using provided credentials. This method is an alternative to using the default credentials of the current process. ```rust pub fn new_with_cred( flags: InitiateFlags, cred: Cred, target_principal: &str, channel_bindings: Option<&[u8]>) -> Result<(PendingClientCtx, impl Deref)> { let (pending, token) = ClientCtxImpl::new_with_cred(flags, cred.0, target_principal, channel_bindings)?; Ok((PendingClientCtx(pending), token)) } ``` -------------------------------- ### InitiateFlags Cloning and Debugging Source: https://docs.rs/cross-krb5/latest/cross_krb5/struct.InitiateFlags.html Details the methods for cloning `InitiateFlags` to create duplicates and for formatting them for debugging purposes. ```APIDOC ## Cloning and Debugging ### Cloning - **Function**: `clone(&self) -> InitiateFlags` - **Description**: Creates a duplicate of the `InitiateFlags` value. - **Function**: `clone_from(&mut self, source: &Self)` - **Description**: Copies the value from `source` to `self`. ### Debug Formatting - **Function**: `fmt(&self, f: &mut Formatter<'_>) -> Result` - **Description**: Formats the `InitiateFlags` value for display in debug output. ``` -------------------------------- ### Create Client Security Context with Existing Credentials Source: https://docs.rs/cross-krb5/latest/src/cross_krb5/unix.rs.html Establishes a new client security context using pre-acquired credentials. It configures the GSSAPI context with requested flags (integrity, mutual auth, confidentiality) and performs the initial GSSAPI step to generate the first token. ```rust pub(crate) fn new_with_cred( flags: InitiateFlags, cred: Cred, target_principal: &str, channel_bindings: Option<&[u8]>, ) -> Result<(PendingClientCtx, impl Deref)> { let target = Name::new(target_principal.as_bytes(), Some(GSS_NT_KRB5_PRINCIPAL))? .canonicalize(Some(GSS_MECH_KRB5))?; // Integrity is fundamental to wrap/unwrap and always requested; mutual // auth and confidentiality are requested unless the caller disabled them. let mut req = CtxFlags::GSS_C_INTEG_FLAG; if !flags.contains(InitiateFlags::DISABLE_MUTUAL_AUTH) { req |= CtxFlags::GSS_C_MUTUAL_FLAG; } if !flags.contains(InitiateFlags::DISABLE_CONFIDENTIALITY) { req |= CtxFlags::GSS_C_CONF_FLAG; } let mut gss = GssClientCtx::new(Some(cred.0), target, req, Some(GSS_MECH_KRB5)); let token = gss.step(None, channel_bindings)?.ok_or_else(|| anyhow!( ``` -------------------------------- ### Create and Initialize ServerCtx Source: https://docs.rs/cross-krb5/latest/cross_krb5/struct.ServerCtx.html Creates a new server context for a given service principal name. This context must then be initialized by exchanging tokens with the client. Channel bindings can be optionally provided and must match those supplied by the client. ```rust let mut server = ServerCtx::new(AcceptFlags::empty(), Some(&spn), None).expect("new"); ``` -------------------------------- ### NEGOTIATE_TOKEN Flag Source: https://docs.rs/cross-krb5/latest/cross_krb5/struct.InitiateFlags.html Use the SSPI negotiate package instead of the Kerberos package on Windows. Some Windows servers expect these tokens instead of normal GSSAPI compatible tokens. ```rust pub const NEGOTIATE_TOKEN: Self ``` -------------------------------- ### ClientCtx::step Source: https://docs.rs/cross-krb5/latest/src/cross_krb5/lib.rs.html Feeds a server-provided token to the client context, advancing the initialization process. It returns either a completed client context with an optional final token, or a pending context with a token to be sent back to the server. ```APIDOC ## ClientCtx::step ### Description Feeds the server-provided token to the client context, performing one step of the initialization. If the initialization is complete, it returns the established context and optionally a final token that must be sent to the server. Otherwise, it returns the pending context and another token to pass to the server. ### Method Signature ```rust pub fn step(self, token: &[u8]) -> Result>), (PendingClientCtx, impl Deref)>> ``` ### Parameters * `token` (&[u8]): The token received from the server. ### Returns * `Result>`: An enum `Step` which is either `Step::Finished` containing the established `ClientCtx` and an optional final token, or `Step::Continue` containing a `PendingClientCtx` and the next token to send to the server. Returns an error if the step fails. ``` -------------------------------- ### Cloning and Copying AcceptFlags Source: https://docs.rs/cross-krb5/latest/cross_krb5/struct.AcceptFlags.html Explains how to create copies of `AcceptFlags` values using `clone` and `clone_from` methods. ```APIDOC ## Cloning and Copying AcceptFlags ### `clone()` #### Function Signature `fn clone(&self) -> AcceptFlags` #### Description Returns a duplicate of the `AcceptFlags` value. ### `clone_from()` #### Function Signature `fn clone_from(&mut self, source: &Self)` #### Description Performs copy-assignment from a source `AcceptFlags` value to the current one. ``` -------------------------------- ### Create PendingServerCtx with Credential Source: https://docs.rs/cross-krb5/latest/src/cross_krb5/unix.rs.html Initializes a new server context for pending authentication using provided credentials and optional channel bindings. This is used when the server already has acquired credentials. ```rust pub(crate) fn new_with_cred( flags: AcceptFlags, cred: Cred, channel_bindings: Option<&[u8]>, ) -> Result { Ok(PendingServerCtx { gss: GssServerCtx::new(Some(cred.0)), flags, cb: channel_bindings.map(|cb| cb.to_vec()), }) } ``` -------------------------------- ### Create New Client Context Source: https://docs.rs/cross-krb5/latest/src/cross_krb5/lib.rs.html Creates a new client context for communicating with a target principal. Optionally uses the current process's credentials if no principal is specified. Returns a pending client context and an initial token for the server. ```rust pub fn new( flags: InitiateFlags, principal: Option<&str>, target_principal: &str, channel_bindings: Option<&[u8]>, ) -> Result<(PendingClientCtx, impl Deref)> { let (pending, token) = ClientCtxImpl::new(flags, principal, target_principal, channel_bindings)?; Ok((PendingClientCtx(pending), token)) } ``` -------------------------------- ### ServerCtx::new Method Source: https://docs.rs/cross-krb5/latest/src/cross_krb5/lib.rs.html Creates a new pending server context. Specify the service principal name and optional channel bindings. If `principal` is `None`, the context uses the current process user. The returned context requires initialization via token exchange. ```rust impl ServerCtx { /// Create a new server context for `principal`, which should be /// the service principal name assigned to the service the client /// will be requesting. If it is left as `None` it will use the /// user running the current process. The returned pending context /// must be initiaized by exchanging one or more tokens with the /// client before it can be used. /// /// If present, `channel_bindings` must match the bindings the client /// supplied to `ClientCtx::new`; the mechanism rejects the context /// otherwise. Note that with a `None` acceptor binding the mechanism /// generally accepts whatever the client sent, so to actually enforce /// channel binding the server must pass its own expected bindings here. pub fn new( flags: AcceptFlags, principal: Option<&str>, channel_bindings: Option<&[u8]>, ) -> Result { Ok(PendingServerCtx(ServerCtxImpl::new(flags, principal, channel_bindings)?)) } // ... ``` -------------------------------- ### From and Into Implementations Source: https://docs.rs/cross-krb5/latest/cross_krb5/struct.Cred.html Allows conversion to and from the Cred struct, with availability restricted to Unix-like systems. ```APIDOC ### impl From for Cred **Available on Unix only.** #### fn from(value: Cred) -> Self Converts a `Cred` instance into itself. This is part of the `From` trait implementation, enabling conversions where the source and target types are the same. ### impl Into for Cred **Available on Unix only.** #### fn into(self) -> Cred Converts this `Cred` instance into a `Cred` instance. This is part of the `Into` trait implementation, allowing a `Cred` to be converted into another `Cred`. ``` -------------------------------- ### ClientCtx::step Source: https://docs.rs/cross-krb5/latest/src/cross_krb5/unix.rs.html Processes a security token as part of the Kerberos context establishment handshake. ```APIDOC ## PendingClientCtx::step ### Description Performs one step in the Kerberos security context establishment handshake. It takes an incoming token from the peer and returns either a new token to send back or indicates that the context is complete. ### Parameters - **token** (&[u8]) - The security token received from the peer. ### Returns - Result>), (PendingClientCtx, impl Deref)> > - An enum indicating whether the context is `Continue`ing with a new `PendingClientCtx` and token, or `Finished` with a `ClientCtx` and an optional final token. ``` -------------------------------- ### PendingServerCtx Step Method Source: https://docs.rs/cross-krb5/latest/src/cross_krb5/lib.rs.html Processes an incoming token to advance the server context's state. It handles both finished and continuation steps, returning the updated context and any associated token. ```rust impl PendingServerCtx { pub fn step( self, token: &[u8], ) -> Result< Step< (ServerCtx, Option>), (PendingServerCtx, impl Deref), >, > { Ok(match self.0.step(token)? { Step::Finished((ctx, tok)) => { Step::Finished((ServerCtx(ctx), tok)) } Step::Continue((ctx, tok)) => { Step::Continue((PendingServerCtx(ctx), tok)) } }) } } ``` -------------------------------- ### Client Context Wrap Method Source: https://docs.rs/cross-krb5/latest/src/cross_krb5/lib.rs.html Encrypts and/or signs a message using the Kerberos context. The `encrypt` parameter determines whether confidentiality is applied. ```rust fn wrap(&mut self, encrypt: bool, msg: &[u8]) -> Result { K5Ctx::wrap(&mut self.0, encrypt, msg) } ``` -------------------------------- ### Create PendingServerCtx with Principal Source: https://docs.rs/cross-krb5/latest/src/cross_krb5/unix.rs.html Creates a new server context for pending authentication, acquiring server credentials using the provided principal name and optional channel bindings. This is the primary method for initiating server-side authentication. ```rust pub(crate) fn new( flags: AcceptFlags, principal: Option<&str>, channel_bindings: Option<&[u8]>, ) -> Result { Self::new_with_cred(flags, Cred::server_acquire(flags, principal)?, channel_bindings) } ``` -------------------------------- ### Create New Client Security Context Source: https://docs.rs/cross-krb5/latest/src/cross_krb5/unix.rs.html Initiates a new client security context using provided flags, principal, target principal, and optional channel bindings. It first acquires credentials and then calls `new_with_cred` to establish the context. ```rust pub(crate) fn new( flags: InitiateFlags, principal: Option<&str>, target_principal: &str, channel_bindings: Option<&[u8]>, ) -> Result<(PendingClientCtx, impl Deref)> { let cred = Cred::client_acquire(flags, principal)?; Self::new_with_cred( flags, cred, target_principal, channel_bindings, ) } ``` -------------------------------- ### ServerCtx::new Source: https://docs.rs/cross-krb5/latest/src/cross_krb5/unix.rs.html Creates a new `PendingServerCtx` for establishing a server-side GSSAPI security context. It can optionally take a specific server principal and channel bindings. ```APIDOC ## ServerCtx::new ### Description Creates a new `PendingServerCtx` for establishing a server-side GSSAPI security context. It can optionally take a specific server principal and channel bindings. ### Parameters - `flags` (AcceptFlags): Flags controlling the context establishment, such as disabling confidentiality or mutual authentication. - `principal` (Option<&str>): The principal name of the server. If `None`, the default principal is used. - `channel_bindings` (Option<&[u8]>): Optional channel binding data to be used during context establishment. ### Returns - `Result`: A `PendingServerCtx` ready for the `step` method to process initial tokens. ### Example ```rust let server_flags = AcceptFlags::empty(); // Or other flags as needed let pending_ctx = ServerCtx::new(server_flags, Some("server/host.example.com"), None)?; ``` ``` -------------------------------- ### ServerCtx::new_with_cred Source: https://docs.rs/cross-krb5/latest/cross_krb5/struct.ServerCtx.html Creates a new server context using provided credentials. This is an alternative to specifying a principal name directly. ```APIDOC ## pub fn new_with_cred( flags: AcceptFlags, cred: Cred, channel_bindings: Option<&[u8]>, ) -> Result ### Description Creates a new server context using provided credentials (`Cred`). This method allows for more explicit control over the credentials used by the server context compared to `new()`. ### Parameters - **flags**: `AcceptFlags` - Flags to configure the server context. - **cred**: `Cred` - The credentials to use for the server context. - **channel_bindings**: `Option<&[u8]>` - Optional channel bindings to enforce security. ### Returns - `Result` - A `PendingServerCtx` if successful, or an error. ### Example ```rust use cross_krb5::{AcceptFlags, Cred}; // Assuming 'my_cred' is a Cred object obtained elsewhere // let my_cred: Cred = ...; // let server_ctx = ServerCtx::new_with_cred(AcceptFlags::empty(), my_cred, None).expect("Failed to create server context with credentials"); ``` ``` -------------------------------- ### CloneToUninit for T Source: https://docs.rs/cross-krb5/latest/cross_krb5/struct.AcceptFlags.html Provides an experimental, nightly-only API for performing copy-assignment from `self` to an uninitialized destination. ```APIDOC ## unsafe fn clone_to_uninit(&self, dest: *mut u8) 🔬This is a nightly-only experimental API. (`clone_to_uninit`) Performs copy-assignment from `self` to `dest`. Read more ```