sspi/lib.rs
1//! sspi-rs is a Rust implementation of [Security Support Provider Interface (SSPI)](https://docs.microsoft.com/en-us/windows/win32/rpc/security-support-provider-interface-sspi-).
2//! It ships with platform-independent implementations of [Security Support Providers (SSP)](https://docs.microsoft.com/en-us/windows/win32/rpc/security-support-providers-ssps-),
3//! and is able to utilize native Microsoft libraries when ran under Windows.
4//!
5//! The purpose of sspi-rs is to clean the original interface from cluttering and provide users with Rust-friendly SSPs for execution under Linux or any other platform that is
6//! able to compile Rust.
7//!
8//! # Getting started
9//!
10//! Here is a quick example how to start working with the crate. This is the first stage of the client-server authentication performed on the client side.
11//!
12//! ```rust
13//! use sspi::Sspi;
14//! use sspi::Username;
15//! use sspi::Ntlm;
16//! use sspi::builders::EmptyInitializeSecurityContext;
17//! use sspi::SspiImpl;
18//!
19//! let mut ntlm = Ntlm::new();
20//!
21//! let identity = sspi::AuthIdentity {
22//! username: Username::parse("user").unwrap(),
23//! password: "password".to_string().into(),
24//! };
25//!
26//! let mut acq_creds_handle_result = ntlm
27//! .acquire_credentials_handle()
28//! .with_credential_use(sspi::CredentialUse::Outbound)
29//! .with_auth_data(&identity)
30//! .execute(&mut ntlm)
31//! .expect("AcquireCredentialsHandle resulted in error");
32//!
33//! let mut output = vec![sspi::SecurityBuffer::new(
34//! Vec::new(),
35//! sspi::BufferType::Token,
36//! )];
37//!
38//! let mut builder = ntlm.initialize_security_context()
39//! .with_credentials_handle(&mut acq_creds_handle_result.credentials_handle)
40//! .with_context_requirements(
41//! sspi::ClientRequestFlags::CONFIDENTIALITY | sspi::ClientRequestFlags::ALLOCATE_MEMORY
42//! )
43//! .with_target_data_representation(sspi::DataRepresentation::Native)
44//! .with_output(&mut output);
45//!
46//! let result = ntlm.initialize_security_context_impl(&mut builder)
47//! .expect("InitializeSecurityContext resulted in error")
48//! .resolve_to_result()
49//! .expect("InitializeSecurityContext resulted in error");
50//!
51//! println!("Initialized security context with result status: {:?}", result.status);
52//! ```
53
54#[macro_use]
55extern crate tracing;
56
57pub mod builders;
58pub mod channel_bindings;
59pub mod credssp;
60pub mod generator;
61pub mod kerberos;
62pub mod negotiate;
63pub mod network_client;
64pub mod ntlm;
65mod pk_init;
66pub mod pku2u;
67
68mod auth_identity;
69mod ber;
70mod crypto;
71mod dns;
72mod kdc;
73mod krb;
74mod rustls;
75mod secret;
76mod security_buffer;
77mod smartcard;
78mod utils;
79
80#[cfg(all(feature = "tsssp", not(target_os = "windows")))]
81compile_error!("tsssp feature should be used only on Windows");
82
83use std::{error, fmt, io, result, str, string};
84
85use bitflags::bitflags;
86#[cfg(feature = "tsssp")]
87use credssp::sspi_cred_ssp;
88pub use generator::NetworkRequest;
89use generator::{GeneratorAcceptSecurityContext, GeneratorChangePassword, GeneratorInitSecurityContext};
90pub use network_client::NetworkProtocol;
91use num_derive::{FromPrimitive, ToPrimitive};
92use picky_asn1::restricted_string::CharSetError;
93use picky_asn1_der::Asn1DerError;
94use picky_asn1_x509::Certificate;
95use picky_krb::gss_api::GssApiMessageError;
96use picky_krb::messages::KrbError;
97#[cfg(feature = "__rustls-used")]
98pub use rustls::install_default_crypto_provider_if_necessary;
99pub use security_buffer::SecurityBufferRef;
100use utils::map_keb_error_code_to_sspi_error;
101pub use utils::{modpow, str_to_w_buff, string_to_utf16, utf16_bytes_to_utf8_string};
102
103pub use self::auth_identity::{
104 AuthIdentity, AuthIdentityBuffers, Credentials, CredentialsBuffers, UserNameFormat, Username,
105};
106#[cfg(feature = "scard")]
107pub use self::auth_identity::{SmartCardIdentity, SmartCardIdentityBuffers, SmartCardType};
108pub use self::builders::{
109 AcceptSecurityContextResult, AcquireCredentialsHandleResult, InitializeSecurityContextResult,
110};
111use self::builders::{
112 ChangePassword, FilledAcceptSecurityContext, FilledAcquireCredentialsHandle, FilledInitializeSecurityContext,
113};
114pub use self::kdc::{detect_kdc_host, detect_kdc_url};
115pub use self::kerberos::config::{KerberosConfig, KerberosServerConfig};
116pub use self::kerberos::{Kerberos, KerberosState, KERBEROS_VERSION};
117pub use self::negotiate::{Negotiate, NegotiateConfig, NegotiatedProtocol};
118pub use self::ntlm::{
119 hash::{NtlmHash, NtlmHashError, NTLM_HASH_PREFIX},
120 Ntlm,
121};
122pub use self::pku2u::{Pku2u, Pku2uConfig, Pku2uState};
123pub use self::secret::Secret;
124use crate::builders::{
125 EmptyAcceptSecurityContext, EmptyAcquireCredentialsHandle, EmptyInitializeSecurityContext,
126 InitializeSecurityContext,
127};
128
129/// Representation of SSPI-related result operation. Makes it easier to return a `Result` with SSPI-related `Error`.
130pub type Result<T> = result::Result<T, Error>;
131pub type Luid = u64;
132
133const PACKAGE_ID_NONE: u16 = 0xFFFF;
134
135/// Retrieves information about a specified security package. This information includes credentials and contexts.
136///
137/// # Returns
138///
139/// * `PackageInfo` containing the information about the security principal upon success
140/// * `Error` on error
141///
142/// # Example
143///
144/// ```
145/// let package_info = sspi::query_security_package_info(sspi::SecurityPackageType::Ntlm)
146/// .unwrap();
147/// println!("Package info:");
148/// println!("Name: {:?}", package_info.name);
149/// println!("Comment: {}", package_info.comment);
150/// ```
151///
152/// # MSDN
153///
154/// * [QuerySecurityPackageInfoW function](https://docs.microsoft.com/en-us/windows/win32/api/sspi/nf-sspi-querysecuritypackageinfow)
155pub fn query_security_package_info(package_type: SecurityPackageType) -> Result<PackageInfo> {
156 match package_type {
157 SecurityPackageType::Ntlm => Ok(ntlm::PACKAGE_INFO.clone()),
158 SecurityPackageType::Kerberos => Ok(kerberos::PACKAGE_INFO.clone()),
159 SecurityPackageType::Negotiate => Ok(negotiate::PACKAGE_INFO.clone()),
160 SecurityPackageType::Pku2u => Ok(pku2u::PACKAGE_INFO.clone()),
161 #[cfg(feature = "tsssp")]
162 SecurityPackageType::CredSsp => Ok(sspi_cred_ssp::PACKAGE_INFO.clone()),
163 SecurityPackageType::Other(s) => Err(Error::new(
164 ErrorKind::Unknown,
165 format!("queried info about unknown package: {:?}", s),
166 )),
167 }
168}
169
170/// Returns an array of `PackageInfo` structures that provide information about the security packages available to the client.
171///
172/// # Returns
173///
174/// * `Vec` of `PackageInfo` structures upon success
175/// * `Error` on error
176///
177/// # Example
178///
179/// ```
180/// let packages = sspi::enumerate_security_packages().unwrap();
181///
182/// println!("Available packages:");
183/// for ssp in packages {
184/// println!("{:?}", ssp.name);
185/// }
186/// ```
187///
188/// # MSDN
189///
190/// * [EnumerateSecurityPackagesW function](https://docs.microsoft.com/en-us/windows/win32/api/sspi/nf-sspi-enumeratesecuritypackagesw)
191pub fn enumerate_security_packages() -> Result<Vec<PackageInfo>> {
192 Ok(vec![
193 negotiate::PACKAGE_INFO.clone(),
194 kerberos::PACKAGE_INFO.clone(),
195 pku2u::PACKAGE_INFO.clone(),
196 ntlm::PACKAGE_INFO.clone(),
197 #[cfg(feature = "tsssp")]
198 sspi_cred_ssp::PACKAGE_INFO.clone(),
199 ])
200}
201
202/// This trait provides interface for all available SSPI functions. The `acquire_credentials_handle`,
203/// `initialize_security_context`, and `accept_security_context` methods return Builders that make it
204/// easier to assemble the list of arguments for the function and then execute it.
205///
206/// # MSDN
207///
208/// * [SSPI.h](https://docs.microsoft.com/en-us/windows/win32/api/sspi/)
209pub trait Sspi
210where
211 Self: Sized + SspiImpl,
212{
213 /// Acquires a handle to preexisting credentials of a security principal. The preexisting credentials are
214 /// available only for `sspi::winapi` module. This handle is required by the `initialize_security_context`
215 /// and `accept_security_context` functions. These can be either preexisting credentials, which are
216 /// established through a system logon, or the caller can provide alternative credentials. Alternative
217 /// credentials are always required to specify when using platform independent SSPs.
218 ///
219 /// # Returns
220 ///
221 /// * `AcquireCredentialsHandle` builder
222 ///
223 /// # Requirements for execution
224 ///
225 /// These methods are required to be called before calling the `execute` method of the `AcquireCredentialsHandle` builder:
226 /// * [`with_credential_use`](builders/struct.AcquireCredentialsHandle.html#method.with_credential_use)
227 ///
228 /// # Example
229 ///
230 /// ```
231 /// use sspi::Sspi;
232 /// use sspi::Username;
233 ///
234 /// let mut ntlm = sspi::Ntlm::new();
235 ///
236 /// let identity = sspi::AuthIdentity {
237 /// username: Username::parse("user").unwrap(),
238 /// password: "password".to_string().into(),
239 /// };
240 ///
241 /// #[allow(unused_variables)]
242 /// let result = ntlm
243 /// .acquire_credentials_handle()
244 /// .with_credential_use(sspi::CredentialUse::Outbound)
245 /// .with_auth_data(&identity)
246 /// .execute(&mut ntlm)
247 /// .unwrap();
248 /// ```
249 ///
250 /// # MSDN
251 ///
252 /// * [AcquireCredentialshandleW function](https://docs.microsoft.com/en-us/windows/win32/api/sspi/nf-sspi-acquirecredentialshandlew)
253 fn acquire_credentials_handle<'a>(
254 &mut self,
255 ) -> EmptyAcquireCredentialsHandle<'a, Self::CredentialsHandle, Self::AuthenticationData> {
256 EmptyAcquireCredentialsHandle::new()
257 }
258
259 /// Initiates the client side, outbound security context from a credential handle.
260 /// The function is used to build a security context between the client application and a remote peer. The function returns a token
261 /// that the client must pass to the remote peer, which the peer in turn submits to the local security implementation through the
262 /// `accept_security_context` call.
263 ///
264 /// # Returns
265 ///
266 /// * `InitializeSecurityContext` builder
267 ///
268 /// # Requirements for execution
269 ///
270 /// These methods are required to be called before calling the `execute` method
271 /// * [`with_credentials_handle`](builders/struct.InitializeSecurityContext.html#method.with_credentials_handle)
272 /// * [`with_context_requirements`](builders/struct.InitializeSecurityContext.html#method.with_context_requirements)
273 /// * [`with_target_data_representation`](builders/struct.InitializeSecurityContext.html#method.with_target_data_representation)
274 /// * [`with_output`](builders/struct.InitializeSecurityContext.html#method.with_output)
275 ///
276 /// # Example
277 ///
278 /// ```
279 /// use sspi::Sspi;
280 /// use sspi::Username;
281 /// use sspi::builders::EmptyInitializeSecurityContext;
282 /// use sspi::SspiImpl;
283 ///
284 /// let mut ntlm = sspi::Ntlm::new();
285 ///
286 /// let identity = sspi::AuthIdentity {
287 /// username: Username::new(&whoami::username(), Some(&whoami::hostname())).unwrap(),
288 /// password: String::from("password").into(),
289 /// };
290 ///
291 /// let mut acq_cred_result = ntlm
292 /// .acquire_credentials_handle()
293 /// .with_credential_use(sspi::CredentialUse::Outbound)
294 /// .with_auth_data(&identity)
295 /// .execute(&mut ntlm)
296 /// .unwrap();
297 ///
298 /// let mut credentials_handle = acq_cred_result.credentials_handle;
299 ///
300 /// let mut output_buffer = vec![sspi::SecurityBuffer::new(Vec::new(), sspi::BufferType::Token)];
301 ///
302 /// #[allow(unused_variables)]
303 /// let mut builder = ntlm.initialize_security_context()
304 /// .with_credentials_handle(&mut credentials_handle)
305 /// .with_context_requirements(
306 /// sspi::ClientRequestFlags::CONFIDENTIALITY | sspi::ClientRequestFlags::ALLOCATE_MEMORY,
307 /// )
308 /// .with_target_data_representation(sspi::DataRepresentation::Native)
309 /// .with_output(&mut output_buffer);
310 ///
311 /// let result = ntlm.initialize_security_context_impl(&mut builder)
312 /// .unwrap()
313 /// .resolve_to_result()
314 /// .unwrap();
315 /// ```
316 ///
317 /// # MSDN
318 ///
319 /// * [InitializeSecurityContextW function](https://docs.microsoft.com/en-us/windows/win32/api/sspi/nf-sspi-initializesecuritycontextw)
320 fn initialize_security_context<'a>(&mut self) -> EmptyInitializeSecurityContext<'a, Self::CredentialsHandle> {
321 InitializeSecurityContext::new()
322 }
323
324 /// Lets the server component of a transport application establish a security context between the server and a remote client.
325 /// The remote client calls the `initialize_security_context` function to start the process of establishing a security context.
326 /// The server can require one or more reply tokens from the remote client to complete establishing the security context.
327 ///
328 /// # Returns
329 ///
330 /// * `AcceptSecurityContext` builder
331 ///
332 /// # Requirements for execution
333 ///
334 /// These methods are required to be called before calling the `execute` method of the `AcceptSecurityContext` builder:
335 /// * [`with_credentials_handle`](builders/struct.AcceptSecurityContext.html#method.with_credentials_handle)
336 /// * [`with_context_requirements`](builders/struct.AcceptSecurityContext.html#method.with_context_requirements)
337 /// * [`with_target_data_representation`](builders/struct.AcceptSecurityContext.html#method.with_target_data_representation)
338 /// * [`with_output`](builders/struct.AcceptSecurityContext.html#method.with_output)
339 ///
340 /// # Example
341 ///
342 /// ```
343 /// use sspi::Sspi;
344 /// use sspi::Username;
345 /// use sspi::builders::EmptyInitializeSecurityContext;
346 /// use sspi::SspiImpl;
347 ///
348 /// let mut client_ntlm = sspi::Ntlm::new();
349 ///
350 /// let identity = sspi::AuthIdentity {
351 /// username: Username::parse("user").unwrap(),
352 /// password: "password".to_string().into(),
353 /// };
354 ///
355 /// let mut client_acq_cred_result = client_ntlm
356 /// .acquire_credentials_handle()
357 /// .with_credential_use(sspi::CredentialUse::Outbound)
358 /// .with_auth_data(&identity)
359 /// .execute(&mut client_ntlm)
360 /// .unwrap();
361 ///
362 /// let mut client_output_buffer = vec![sspi::SecurityBuffer::new(Vec::new(), sspi::BufferType::Token)];
363 ///
364 /// let mut builder = client_ntlm.initialize_security_context()
365 /// .with_credentials_handle(&mut client_acq_cred_result.credentials_handle)
366 /// .with_context_requirements(
367 /// sspi::ClientRequestFlags::CONFIDENTIALITY | sspi::ClientRequestFlags::ALLOCATE_MEMORY,
368 /// )
369 /// .with_target_data_representation(sspi::DataRepresentation::Native)
370 /// .with_target_name("user")
371 /// .with_output(&mut client_output_buffer);
372 ///
373 /// let _result = client_ntlm.initialize_security_context_impl(&mut builder)
374 /// .unwrap()
375 /// .resolve_to_result()
376 /// .unwrap();
377 ///
378 /// let mut ntlm = sspi::Ntlm::new();
379 /// let mut output_buffer = vec![sspi::SecurityBuffer::new(Vec::new(), sspi::BufferType::Token)];
380 ///
381 /// let mut server_acq_cred_result = ntlm
382 /// .acquire_credentials_handle()
383 /// .with_credential_use(sspi::CredentialUse::Inbound)
384 /// .with_auth_data(&identity)
385 /// .execute(&mut ntlm)
386 /// .unwrap();
387 ///
388 /// let mut credentials_handle = server_acq_cred_result.credentials_handle;
389 ///
390 /// #[allow(unused_variables)]
391 /// let result = ntlm
392 /// .accept_security_context()
393 /// .with_credentials_handle(&mut credentials_handle)
394 /// .with_context_requirements(sspi::ServerRequestFlags::ALLOCATE_MEMORY)
395 /// .with_target_data_representation(sspi::DataRepresentation::Native)
396 /// .with_input(&mut client_output_buffer)
397 /// .with_output(&mut output_buffer)
398 /// .execute(&mut ntlm)
399 /// .unwrap();
400 /// ```
401 ///
402 /// # MSDN
403 ///
404 /// * [AcceptSecurityContext function](https://docs.microsoft.com/en-us/windows/win32/api/sspi/nf-sspi-acceptsecuritycontext)
405 fn accept_security_context<'a>(&mut self) -> EmptyAcceptSecurityContext<'a, Self::CredentialsHandle> {
406 EmptyAcceptSecurityContext::new()
407 }
408
409 /// Completes an authentication token. This function is used by protocols, such as DCE,
410 /// that need to revise the security information after the transport application has updated some message parameters.
411 ///
412 /// # Parameters
413 ///
414 /// * `token`: `SecurityBufferRef` that contains the buffer descriptor for the entire message
415 ///
416 /// # Returns
417 ///
418 /// * `SspiOk` on success
419 /// * `Error` on error
420 ///
421 /// # Example
422 ///
423 /// ```
424 /// use sspi::Sspi;
425 /// use sspi::Username;
426 /// use sspi::builders::EmptyInitializeSecurityContext;
427 /// use sspi::SspiImpl;
428 ///
429 /// let mut client_ntlm = sspi::Ntlm::new();
430 /// let mut ntlm = sspi::Ntlm::new();
431 ///
432 /// let mut client_output_buffer = vec![sspi::SecurityBuffer::new(Vec::new(), sspi::BufferType::Token)];
433 /// let mut output_buffer = vec![sspi::SecurityBuffer::new(Vec::new(), sspi::BufferType::Token)];
434 ///
435 /// let identity = sspi::AuthIdentity {
436 /// username: Username::parse("user").unwrap(),
437 /// password: "password".to_string().into(),
438 /// };
439 ///
440 /// let mut client_acq_cred_result = client_ntlm
441 /// .acquire_credentials_handle()
442 /// .with_credential_use(sspi::CredentialUse::Outbound)
443 /// .with_auth_data(&identity)
444 /// .execute(&mut ntlm)
445 /// .unwrap();
446 ///
447 /// let mut server_acq_cred_result = ntlm
448 /// .acquire_credentials_handle()
449 /// .with_credential_use(sspi::CredentialUse::Inbound)
450 /// .with_auth_data(&identity)
451 /// .execute(&mut ntlm)
452 /// .unwrap();
453 ///
454 /// loop {
455 /// client_output_buffer[0].buffer.clear();
456 ///
457 /// let mut builder = client_ntlm.initialize_security_context()
458 /// .with_credentials_handle(&mut client_acq_cred_result.credentials_handle)
459 /// .with_context_requirements(
460 /// sspi::ClientRequestFlags::CONFIDENTIALITY | sspi::ClientRequestFlags::ALLOCATE_MEMORY,
461 /// )
462 /// .with_target_data_representation(sspi::DataRepresentation::Native)
463 /// .with_target_name("user")
464 /// .with_input(&mut output_buffer)
465 /// .with_output(&mut client_output_buffer);
466 ///
467 /// let _client_result = client_ntlm.initialize_security_context_impl(&mut builder)
468 /// .unwrap()
469 /// .resolve_to_result()
470 /// .unwrap();
471 ///
472 /// let builder = ntlm
473 /// .accept_security_context()
474 /// .with_credentials_handle(&mut server_acq_cred_result.credentials_handle)
475 /// .with_context_requirements(sspi::ServerRequestFlags::ALLOCATE_MEMORY)
476 /// .with_target_data_representation(sspi::DataRepresentation::Native)
477 /// .with_input(&mut client_output_buffer)
478 /// .with_output(&mut output_buffer);
479 /// let server_result = ntlm.accept_security_context_impl(builder)
480 /// .unwrap()
481 /// .resolve_to_result()
482 /// .unwrap();
483 ///
484 /// if server_result.status == sspi::SecurityStatus::CompleteAndContinue
485 /// || server_result.status == sspi::SecurityStatus::CompleteNeeded
486 /// {
487 /// break;
488 /// }
489 /// }
490 ///
491 /// #[allow(unused_variables)]
492 /// let result = ntlm
493 /// .complete_auth_token(&mut output_buffer)
494 /// .unwrap();
495 /// ```
496 ///
497 /// # MSDN
498 ///
499 /// * [CompleteAuthToken function](https://docs.microsoft.com/en-us/windows/win32/api/sspi/nf-sspi-completeauthtoken)
500 fn complete_auth_token(&mut self, token: &mut [SecurityBuffer]) -> Result<SecurityStatus>;
501
502 /// Encrypts a message to provide privacy. The function allows the application to choose among cryptographic algorithms supported by the chosen mechanism.
503 /// Some packages do not have messages to be encrypted or decrypted but rather provide an integrity hash that can be checked.
504 ///
505 /// # Parameters
506 ///
507 /// * `flags`: package-specific flags that indicate the quality of protection. A security package can use this parameter to enable the selection of cryptographic algorithms
508 /// * `message`: on input, the structure accepts one or more `SecurityBufferRef` structures that can be of type `BufferType::Data`.
509 /// That buffer contains the message to be encrypted. The message is encrypted in place, overwriting the original contents of the structure.
510 /// * `sequence_number`: the sequence number that the transport application assigned to the message. If the transport application does not maintain sequence numbers, this parameter must be zero
511 ///
512 /// # Example
513 ///
514 /// ```
515 /// use sspi::Sspi;
516 /// use sspi::Username;
517 /// use sspi::builders::EmptyInitializeSecurityContext;
518 /// use sspi::SspiImpl;
519 ///
520 /// let mut client_ntlm = sspi::Ntlm::new();
521 /// let mut ntlm = sspi::Ntlm::new();
522 ///
523 /// let mut client_output_buffer = vec![sspi::SecurityBuffer::new(Vec::new(), sspi::BufferType::Token)];
524 /// let mut server_output_buffer = vec![sspi::SecurityBuffer::new(Vec::new(), sspi::BufferType::Token)];
525 ///
526 /// let identity = sspi::AuthIdentity {
527 /// username: Username::parse("user").unwrap(),
528 /// password: "password".to_string().into(),
529 /// };
530 ///
531 /// let mut client_acq_cred_result = client_ntlm
532 /// .acquire_credentials_handle()
533 /// .with_credential_use(sspi::CredentialUse::Outbound)
534 /// .with_auth_data(&identity)
535 /// .execute(&mut client_ntlm)
536 /// .unwrap();
537 ///
538 /// let mut server_acq_cred_result = ntlm
539 /// .acquire_credentials_handle()
540 /// .with_credential_use(sspi::CredentialUse::Inbound)
541 /// .with_auth_data(&identity)
542 /// .execute(&mut ntlm)
543 /// .unwrap();
544 ///
545 /// loop {
546 /// client_output_buffer[0].buffer.clear();
547 ///
548 /// let mut builder = client_ntlm.initialize_security_context()
549 /// .with_credentials_handle(&mut client_acq_cred_result.credentials_handle)
550 /// .with_context_requirements(
551 /// sspi::ClientRequestFlags::CONFIDENTIALITY | sspi::ClientRequestFlags::ALLOCATE_MEMORY,
552 /// )
553 /// .with_target_data_representation(sspi::DataRepresentation::Native)
554 /// .with_target_name("user")
555 /// .with_input(&mut server_output_buffer)
556 /// .with_output(&mut client_output_buffer);
557 ///
558 /// let _client_result = client_ntlm.initialize_security_context_impl(&mut builder)
559 /// .unwrap()
560 /// .resolve_to_result()
561 /// .unwrap();
562 ///
563 /// let builder = ntlm
564 /// .accept_security_context()
565 /// .with_credentials_handle(&mut server_acq_cred_result.credentials_handle)
566 /// .with_context_requirements(sspi::ServerRequestFlags::ALLOCATE_MEMORY)
567 /// .with_target_data_representation(sspi::DataRepresentation::Native)
568 /// .with_input(&mut client_output_buffer)
569 /// .with_output(&mut server_output_buffer);
570 /// let server_result = ntlm.accept_security_context_impl(builder)
571 /// .unwrap()
572 /// .resolve_to_result()
573 /// .unwrap();
574 ///
575 /// if server_result.status == sspi::SecurityStatus::CompleteAndContinue
576 /// || server_result.status == sspi::SecurityStatus::CompleteNeeded
577 /// {
578 /// break;
579 /// }
580 /// }
581 ///
582 /// let _result = ntlm
583 /// .complete_auth_token(&mut server_output_buffer)
584 /// .unwrap();
585 ///
586 /// let mut token = [0; 128];
587 /// let mut data = "This is a message".as_bytes().to_vec();
588 /// let mut msg_buffer = vec![
589 /// sspi::SecurityBufferRef::token_buf(token.as_mut_slice()),
590 /// sspi::SecurityBufferRef::data_buf(data.as_mut_slice()),
591 /// ];
592 ///
593 /// println!("Unencrypted: {:?}", msg_buffer[1].data());
594 ///
595 /// # #[allow(unused_variables)]
596 /// let result = ntlm
597 /// .encrypt_message(sspi::EncryptionFlags::empty(), &mut msg_buffer, 0).unwrap();
598 ///
599 /// println!("Encrypted: {:?}", msg_buffer[1].data());
600 /// ```
601 ///
602 /// # Returns
603 ///
604 /// * `SspiOk` on success
605 /// * `Error` on error
606 ///
607 /// # MSDN
608 ///
609 /// * [EncryptMessage function](https://docs.microsoft.com/en-us/windows/win32/api/sspi/nf-sspi-encryptmessage)
610 fn encrypt_message(
611 &mut self,
612 flags: EncryptionFlags,
613 message: &mut [SecurityBufferRef<'_>],
614 sequence_number: u32,
615 ) -> Result<SecurityStatus>;
616
617 /// Generates a cryptographic checksum of the message, and also includes sequencing information to prevent message loss or insertion.
618 /// The function allows the application to choose between several cryptographic algorithms, if supported by the chosen mechanism.
619 ///
620 /// # Parameters
621 /// * `flags`: package-specific flags that indicate the quality of protection. A security package can use this parameter to enable the selection of cryptographic algorithms
622 /// * `message`: On input, the structure references one or more `SecurityBufferRef` structures of type `BufferType::Data` that contain the message to be signed,
623 /// and a `SecurityBufferRef` of type `BufferType::Token` that receives the signature.
624 /// * `sequence_number`: the sequence number that the transport application assigned to the message. If the transport application does not maintain sequence numbers, this parameter must be zero
625 ///
626 /// # Returns
627 /// * `SspiOk` on success
628 /// * `Error` on error
629 ///
630 /// # Example
631 ///
632 /// ```
633 /// use sspi::Sspi;
634 /// use sspi::Username;
635 /// use sspi::builders::EmptyInitializeSecurityContext;
636 /// use sspi::SspiImpl;
637 ///
638 /// let mut client_ntlm = sspi::Ntlm::new();
639 /// let mut ntlm = sspi::Ntlm::new();
640 ///
641 /// let mut client_output_buffer = vec![sspi::SecurityBuffer::new(Vec::new(), sspi::BufferType::Token)];
642 /// let mut server_output_buffer = vec![sspi::SecurityBuffer::new(Vec::new(), sspi::BufferType::Token)];
643 ///
644 /// let identity = sspi::AuthIdentity {
645 /// username: Username::parse("user").unwrap(),
646 /// password: "password".to_string().into(),
647 /// };
648 ///
649 /// let mut client_acq_cred_result = client_ntlm
650 /// .acquire_credentials_handle()
651 /// .with_credential_use(sspi::CredentialUse::Outbound)
652 /// .with_auth_data(&identity)
653 /// .execute(&mut client_ntlm)
654 /// .unwrap();
655 ///
656 /// let mut server_acq_cred_result = ntlm
657 /// .acquire_credentials_handle()
658 /// .with_credential_use(sspi::CredentialUse::Inbound)
659 /// .with_auth_data(&identity)
660 /// .execute(&mut ntlm)
661 /// .unwrap();
662 ///
663 /// loop {
664 /// client_output_buffer[0].buffer.clear();
665 ///
666 /// let mut builder = client_ntlm.initialize_security_context()
667 /// .with_credentials_handle(&mut client_acq_cred_result.credentials_handle)
668 /// .with_context_requirements(
669 /// sspi::ClientRequestFlags::CONFIDENTIALITY | sspi::ClientRequestFlags::ALLOCATE_MEMORY,
670 /// )
671 /// .with_target_data_representation(sspi::DataRepresentation::Native)
672 /// .with_target_name("user")
673 /// .with_input(&mut server_output_buffer)
674 /// .with_output(&mut client_output_buffer);
675 ///
676 /// let _client_result = client_ntlm.initialize_security_context_impl(&mut builder)
677 /// .unwrap()
678 /// .resolve_to_result()
679 /// .unwrap();
680 ///
681 /// let builder = ntlm
682 /// .accept_security_context()
683 /// .with_credentials_handle(&mut server_acq_cred_result.credentials_handle)
684 /// .with_context_requirements(sspi::ServerRequestFlags::ALLOCATE_MEMORY)
685 /// .with_target_data_representation(sspi::DataRepresentation::Native)
686 /// .with_input(&mut client_output_buffer)
687 /// .with_output(&mut server_output_buffer);
688 /// let server_result = ntlm.accept_security_context_impl(builder)
689 /// .unwrap()
690 /// .resolve_to_result()
691 /// .unwrap();
692 ///
693 /// if server_result.status == sspi::SecurityStatus::CompleteAndContinue
694 /// || server_result.status == sspi::SecurityStatus::CompleteNeeded
695 /// {
696 /// break;
697 /// }
698 /// }
699 ///
700 /// let _result = ntlm
701 /// .complete_auth_token(&mut server_output_buffer)
702 /// .unwrap();
703 ///
704 /// let mut token = [0; 128];
705 /// let mut data = "This is a message to be signed".as_bytes().to_vec();
706 /// let mut msg_buffer = vec![
707 /// sspi::SecurityBufferRef::token_buf(token.as_mut_slice()),
708 /// sspi::SecurityBufferRef::data_buf(data.as_mut_slice()),
709 /// ];
710 ///
711 /// println!("Input data: {:?}", msg_buffer[1].data());
712 ///
713 /// #[allow(unused_variables)]
714 /// let result = ntlm
715 /// .make_signature(0, &mut msg_buffer, 0).unwrap();
716 ///
717 /// println!("Data signature: {:?}", msg_buffer[0].data());
718 /// ```
719 ///
720 /// # MSDN
721 /// * [MakeSignature function](https://learn.microsoft.com/en-us/windows/win32/api/sspi/nf-sspi-makesignature)
722 fn make_signature(&mut self, flags: u32, message: &mut [SecurityBufferRef<'_>], sequence_number: u32)
723 -> Result<()>;
724
725 /// Verifies that a message signed by using the `make_signature` function was received in the correct sequence and has not been modified.
726 ///
727 /// # Parameters
728 /// * `message`: On input, the structure references one or more `SecurityBufferRef` structures of type `BufferType::Data` that contain the message to be verified,
729 /// and a `SecurityBufferRef` of type `BufferType::Token` that contains the signature.
730 /// * `sequence_number`: the sequence number that the transport application assigned to the message. If the transport application does not maintain sequence numbers, this parameter must be zero
731 ///
732 /// # Returns
733 /// * `u32` package-specific flags that indicate the quality of protection.
734 /// * `Error` on error
735 ///
736 /// # Example
737 ///
738 /// ```
739 /// use sspi::Sspi;
740 /// use sspi::Username;
741 /// use sspi::builders::EmptyInitializeSecurityContext;
742 /// use sspi::SspiImpl;
743 ///
744 /// let mut ntlm = sspi::Ntlm::new();
745 /// let mut server_ntlm = sspi::Ntlm::new();
746 ///
747 /// let mut client_output_buffer = vec![sspi::SecurityBuffer::new(Vec::new(), sspi::BufferType::Token)];
748 /// let mut server_output_buffer = vec![sspi::SecurityBuffer::new(Vec::new(), sspi::BufferType::Token)];
749 ///
750 /// let identity = sspi::AuthIdentity {
751 /// username: Username::parse("user").unwrap(),
752 /// password: "password".to_string().into(),
753 /// };
754 ///
755 /// let mut client_acq_cred_result = ntlm
756 /// .acquire_credentials_handle()
757 /// .with_credential_use(sspi::CredentialUse::Outbound)
758 /// .with_auth_data(&identity)
759 /// .execute(&mut ntlm)
760 /// .unwrap();
761 ///
762 /// let mut server_acq_cred_result = server_ntlm
763 /// .acquire_credentials_handle()
764 /// .with_credential_use(sspi::CredentialUse::Inbound)
765 /// .with_auth_data(&identity)
766 /// .execute(&mut server_ntlm)
767 /// .unwrap();
768 ///
769 /// loop {
770 /// client_output_buffer[0].buffer.clear();
771 ///
772 /// let mut builder = ntlm.initialize_security_context()
773 /// .with_credentials_handle(&mut client_acq_cred_result.credentials_handle)
774 /// .with_context_requirements(
775 /// sspi::ClientRequestFlags::CONFIDENTIALITY | sspi::ClientRequestFlags::ALLOCATE_MEMORY,
776 /// )
777 /// .with_target_data_representation(sspi::DataRepresentation::Native)
778 /// .with_target_name("user")
779 /// .with_input(&mut server_output_buffer)
780 /// .with_output(&mut client_output_buffer);
781 ///
782 /// let _client_result = ntlm.initialize_security_context_impl(&mut builder)
783 /// .unwrap()
784 /// .resolve_to_result()
785 /// .unwrap();
786 ///
787 /// let builder = server_ntlm
788 /// .accept_security_context()
789 /// .with_credentials_handle(&mut server_acq_cred_result.credentials_handle)
790 /// .with_context_requirements(sspi::ServerRequestFlags::ALLOCATE_MEMORY)
791 /// .with_target_data_representation(sspi::DataRepresentation::Native)
792 /// .with_input(&mut client_output_buffer)
793 /// .with_output(&mut server_output_buffer);
794 /// let server_result = server_ntlm.accept_security_context_impl(builder)
795 /// .unwrap()
796 /// .resolve_to_result()
797 /// .unwrap();
798 ///
799 /// if server_result.status == sspi::SecurityStatus::CompleteAndContinue
800 /// || server_result.status == sspi::SecurityStatus::CompleteNeeded
801 /// {
802 /// break;
803 /// }
804 /// }
805 ///
806 /// let _result = server_ntlm
807 /// .complete_auth_token(&mut server_output_buffer)
808 /// .unwrap();
809 ///
810 /// let mut token = [0; 128];
811 /// let mut data = "This is a message".as_bytes().to_vec();
812 /// let mut msg = [
813 /// sspi::SecurityBufferRef::token_buf(token.as_mut_slice()),
814 /// sspi::SecurityBufferRef::data_buf(data.as_mut_slice()),
815 /// ];
816 ///
817 /// let _result = server_ntlm
818 /// .make_signature(0, &mut msg, 0).unwrap();
819 ///
820 /// let [mut token, mut data] = msg;
821 ///
822 /// let mut msg_buffer = vec![
823 /// sspi::SecurityBufferRef::token_buf(token.take_data()),
824 /// sspi::SecurityBufferRef::data_buf(data.take_data()),
825 /// ];
826 ///
827 /// #[allow(unused_variables)]
828 /// let signature_flags = ntlm
829 /// .verify_signature(&mut msg_buffer, 0)
830 /// .unwrap();
831 ///
832 /// println!("Signature calculated and verified.");
833 /// ```
834 ///
835 /// # MSDN
836 /// * [VerifySignature function](https://learn.microsoft.com/en-us/windows/win32/api/sspi/nf-sspi-verifysignature)
837 fn verify_signature(&mut self, message: &mut [SecurityBufferRef<'_>], sequence_number: u32) -> Result<u32>;
838
839 /// Decrypts a message. Some packages do not encrypt and decrypt messages but rather perform and check an integrity hash.
840 ///
841 /// # Parameters
842 ///
843 /// * `message`: on input, the structure references one or more `SecurityBufferRef` structures.
844 /// At least one of these must be of type `BufferType::Data`.
845 /// That buffer contains the encrypted message. The encrypted message is decrypted in place, overwriting the original contents of its buffer
846 /// * `sequence_number`: the sequence number that the transport application assigned to the message. If the transport application does not maintain sequence numbers, this parameter must be zero
847 ///
848 /// # Returns
849 ///
850 /// * `DecryptionFlags` upon success
851 /// * `Error` on error
852 ///
853 /// # Example
854 ///
855 /// ```
856 /// use sspi::Sspi;
857 /// use sspi::Username;
858 /// use sspi::builders::EmptyInitializeSecurityContext;
859 /// use sspi::SspiImpl;
860 ///
861 /// let mut ntlm = sspi::Ntlm::new();
862 /// let mut server_ntlm = sspi::Ntlm::new();
863 ///
864 /// let mut client_output_buffer = vec![sspi::SecurityBuffer::new(Vec::new(), sspi::BufferType::Token)];
865 /// let mut server_output_buffer = vec![sspi::SecurityBuffer::new(Vec::new(), sspi::BufferType::Token)];
866 ///
867 /// let identity = sspi::AuthIdentity {
868 /// username: Username::parse("user").unwrap(),
869 /// password: "password".to_string().into(),
870 /// };
871 ///
872 /// let mut client_acq_cred_result = ntlm
873 /// .acquire_credentials_handle()
874 /// .with_credential_use(sspi::CredentialUse::Outbound)
875 /// .with_auth_data(&identity)
876 /// .execute(&mut ntlm)
877 /// .unwrap();
878 ///
879 /// let mut server_acq_cred_result = server_ntlm
880 /// .acquire_credentials_handle()
881 /// .with_credential_use(sspi::CredentialUse::Inbound)
882 /// .with_auth_data(&identity)
883 /// .execute(&mut server_ntlm)
884 /// .unwrap();
885 ///
886 /// loop {
887 /// client_output_buffer[0].buffer.clear();
888 ///
889 /// let mut builder = ntlm.initialize_security_context()
890 /// .with_credentials_handle(&mut client_acq_cred_result.credentials_handle)
891 /// .with_context_requirements(
892 /// sspi::ClientRequestFlags::CONFIDENTIALITY | sspi::ClientRequestFlags::ALLOCATE_MEMORY,
893 /// )
894 /// .with_target_data_representation(sspi::DataRepresentation::Native)
895 /// .with_target_name("user")
896 /// .with_input(&mut server_output_buffer)
897 /// .with_output(&mut client_output_buffer);
898 ///
899 /// let _client_result = ntlm.initialize_security_context_impl(&mut builder)
900 /// .unwrap()
901 /// .resolve_to_result()
902 /// .unwrap();
903 ///
904 /// let builder = server_ntlm
905 /// .accept_security_context()
906 /// .with_credentials_handle(&mut server_acq_cred_result.credentials_handle)
907 /// .with_context_requirements(sspi::ServerRequestFlags::ALLOCATE_MEMORY)
908 /// .with_target_data_representation(sspi::DataRepresentation::Native)
909 /// .with_input(&mut client_output_buffer)
910 /// .with_output(&mut server_output_buffer);
911 /// let server_result = server_ntlm.accept_security_context_impl(builder)
912 /// .unwrap()
913 /// .resolve_to_result()
914 /// .unwrap();
915 ///
916 /// if server_result.status == sspi::SecurityStatus::CompleteAndContinue
917 /// || server_result.status == sspi::SecurityStatus::CompleteNeeded
918 /// {
919 /// break;
920 /// }
921 /// }
922 ///
923 /// let _result = server_ntlm
924 /// .complete_auth_token(&mut server_output_buffer)
925 /// .unwrap();
926 ///
927 /// let mut token = [0; 128];
928 /// let mut data = "This is a message".as_bytes().to_vec();
929 /// let mut msg = [
930 /// sspi::SecurityBufferRef::token_buf(token.as_mut_slice()),
931 /// sspi::SecurityBufferRef::data_buf(data.as_mut_slice()),
932 /// ];
933 ///
934 /// let _result = server_ntlm
935 /// .encrypt_message(sspi::EncryptionFlags::empty(), &mut msg, 0).unwrap();
936 ///
937 /// let [mut token, mut data] = msg;
938 ///
939 /// let mut msg_buffer = vec![
940 /// sspi::SecurityBufferRef::token_buf(token.take_data()),
941 /// sspi::SecurityBufferRef::data_buf(data.take_data()),
942 /// ];
943 ///
944 /// #[allow(unused_variables)]
945 /// let encryption_flags = ntlm
946 /// .decrypt_message(&mut msg_buffer, 0)
947 /// .unwrap();
948 ///
949 /// println!("Decrypted message: {:?}", msg_buffer[1].data());
950 /// ```
951 ///
952 /// # MSDN
953 ///
954 /// * [DecryptMessage function](https://docs.microsoft.com/en-us/windows/win32/api/sspi/nf-sspi-decryptmessage)
955 fn decrypt_message(
956 &mut self,
957 message: &mut [SecurityBufferRef<'_>],
958 sequence_number: u32,
959 ) -> Result<DecryptionFlags>;
960
961 /// Retrieves information about the bounds of sizes of authentication information of the current security principal.
962 ///
963 /// # Returns
964 ///
965 /// * `ContextSizes` upon success
966 /// * `Error` on error
967 ///
968 /// # Example
969 ///
970 /// ```
971 /// use sspi::Sspi;
972 /// let mut ntlm = sspi::Ntlm::new();
973 /// let sizes = ntlm.query_context_sizes().unwrap();
974 /// println!("Max token: {}", sizes.max_token);
975 /// println!("Max signature: {}", sizes.max_signature);
976 /// println!("Block: {}", sizes.block);
977 /// println!("Security trailer: {}", sizes.security_trailer);
978 /// ```
979 ///
980 /// # MSDN
981 ///
982 /// * [QueryCredentialsAttributesW function](https://docs.microsoft.com/en-us/windows/win32/api/sspi/nf-sspi-querycredentialsattributesw)
983 fn query_context_sizes(&mut self) -> Result<ContextSizes>;
984
985 /// Retrieves the username of the credential associated to the context.
986 ///
987 /// # Returns
988 ///
989 /// * `ContextNames` upon success
990 /// * `Error` on error
991 ///
992 /// # Example
993 ///
994 /// ```
995 /// use sspi::Sspi;
996 /// use sspi::Username;
997 ///
998 /// let mut ntlm = sspi::Ntlm::new();
999 /// let identity = sspi::AuthIdentity {
1000 /// username: Username::parse("user").unwrap(),
1001 /// password: "password".to_string().into(),
1002 /// };
1003 ///
1004 /// let _acq_cred_result = ntlm
1005 /// .acquire_credentials_handle()
1006 /// .with_credential_use(sspi::CredentialUse::Inbound)
1007 /// .with_auth_data(&identity)
1008 /// .execute(&mut ntlm).unwrap();
1009 ///
1010 /// let names = ntlm.query_context_names().unwrap();
1011 /// println!("Username: {:?}", names.username.account_name());
1012 /// println!("Domain: {:?}", names.username.domain_name());
1013 /// ```
1014 ///
1015 /// # MSDN
1016 ///
1017 /// * [QuerySecurityPackageInfoW function](https://docs.microsoft.com/en-us/windows/win32/api/sspi/nf-sspi-querysecuritypackageinfow)
1018 fn query_context_names(&mut self) -> Result<ContextNames>;
1019
1020 /// Queries the sizes of the various parts of a stream used in the per-message functions. This function is implemented only for CredSSP security package.
1021 ///
1022 /// # MSDN
1023 ///
1024 /// * [QuerySecurityPackageInfoW function (`ulAttribute` parameter)](https://learn.microsoft.com/en-us/windows/win32/secauthn/querycontextattributes--schannel)
1025 fn query_context_stream_sizes(&mut self) -> Result<StreamSizes> {
1026 Err(Error::new(
1027 ErrorKind::UnsupportedFunction,
1028 "query_context_stream_sizes is not supported",
1029 ))
1030 }
1031
1032 /// Retrieves information about the specified security package. This information includes the bounds of sizes of authentication information, credentials, and contexts.
1033 ///
1034 /// # Returns
1035 ///
1036 /// * `PackageInfo` containing the information about the package
1037 /// * `Error` on error
1038 ///
1039 /// # Example
1040 ///
1041 /// ```
1042 /// use sspi::Sspi;
1043 /// let mut ntlm = sspi::Ntlm::new();
1044 /// let info = ntlm.query_context_package_info().unwrap();
1045 /// println!("Package name: {:?}", info.name);
1046 /// ```
1047 ///
1048 /// # MSDN
1049 ///
1050 /// * [QuerySecurityPackageInfoW function](https://docs.microsoft.com/en-us/windows/win32/api/sspi/nf-sspi-querysecuritypackageinfow)
1051 fn query_context_package_info(&mut self) -> Result<PackageInfo>;
1052
1053 /// Retrieves the trust information of the certificate.
1054 ///
1055 /// # Returns
1056 ///
1057 /// * `CertTrustStatus` on success
1058 ///
1059 /// # Example
1060 ///
1061 /// ```
1062 /// use sspi::Sspi;
1063 /// let mut ntlm = sspi::Ntlm::new();
1064 /// let cert_info = ntlm.query_context_package_info().unwrap();
1065 /// ```
1066 ///
1067 /// # MSDN
1068 ///
1069 /// * [QueryContextAttributes (CredSSP) function (`ulAttribute` parameter)](https://docs.microsoft.com/en-us/windows/win32/secauthn/querycontextattributes--credssp)
1070 fn query_context_cert_trust_status(&mut self) -> Result<CertTrustStatus>;
1071
1072 /// Retrieves the information about the end certificate supplied by the server. This function is implemented only for CredSSP security package.
1073 ///
1074 /// # Returns
1075 ///
1076 /// * `CertContext` on success
1077 ///
1078 /// # MSDN
1079 ///
1080 /// * [QueryContextAttributes (CredSSP) function (`ulAttribute` parameter)](https://docs.microsoft.com/en-us/windows/win32/secauthn/querycontextattributes--credssp)
1081 fn query_context_remote_cert(&mut self) -> Result<CertContext> {
1082 Err(Error::new(
1083 ErrorKind::UnsupportedFunction,
1084 "query_remote_cert_context is not supported",
1085 ))
1086 }
1087
1088 /// Retrieves the information about the negotiated security package. This function is implemented only for CredSSP security package.
1089 ///
1090 /// # Returns
1091 ///
1092 /// * `PackageInfo` on success
1093 ///
1094 /// # MSDN
1095 ///
1096 /// * [QueryContextAttributes (CredSSP) function (`ulAttribute` parameter)](https://learn.microsoft.com/en-us/windows/win32/api/sspi/nf-sspi-querycontextattributesw)
1097 fn query_context_negotiation_package(&mut self) -> Result<PackageInfo> {
1098 Err(Error::new(
1099 ErrorKind::UnsupportedFunction,
1100 "query_context_negotiation_package is not supported",
1101 ))
1102 }
1103
1104 /// Returns detailed information on the established connection. This function is implemented only for CredSSP security package.
1105 ///
1106 /// # Returns
1107 ///
1108 /// * `ConnectionInfo` on success
1109 ///
1110 /// # MSDN
1111 ///
1112 /// * [QueryContextAttributes (CredSSP) function (`ulAttribute` parameter)](https://docs.microsoft.com/en-us/windows/win32/secauthn/querycontextattributes--credssp)
1113 fn query_context_connection_info(&mut self) -> Result<ConnectionInfo> {
1114 Err(Error::new(
1115 ErrorKind::UnsupportedFunction,
1116 "query_context_connection_info is not supported",
1117 ))
1118 }
1119
1120 /// Returns information about the session key used for the security context.
1121 ///
1122 /// # Returns
1123 ///
1124 /// * `SessionKeys` on success
1125 ///
1126 /// # MSDN
1127 ///
1128 /// * [QueryContextAttributes function (`ulAttribute` parameter)](https://docs.microsoft.com/en-us/windows/win32/secauthn/querycontextattributes--general)
1129 fn query_context_session_key(&self) -> Result<SessionKeys> {
1130 Err(Error::new(
1131 ErrorKind::UnsupportedFunction,
1132 "query_context_session_key is not supported",
1133 ))
1134 }
1135
1136 /// Changes the password for a Windows domain account.
1137 ///
1138 /// # Returns
1139 ///
1140 /// * `()` on success
1141 ///
1142 /// # Example
1143 ///
1144 /// ```ignore
1145 /// use sspi::{Sspi, ChangePasswordBuilder};
1146 /// let mut ntlm = sspi::Ntlm::new();
1147 /// let mut output = [];
1148 /// let cert_info = ntlm.query_context_package_info().unwrap();
1149 /// let change_password = ChangePasswordBuilder::new()
1150 /// .with_domain_name("domain".into())
1151 /// .with_account_name("username".into())
1152 /// .with_old_password("old_password".into())
1153 /// .with_old_password("new_password".into())
1154 /// .with_output(&mut output)
1155 /// .build()
1156 /// .unwrap();
1157 /// ntlm.change_password(change_password).unwrap();
1158 /// ```
1159 ///
1160 /// # MSDN
1161 ///
1162 /// * [ChangeAccountPasswordW function](https://docs.microsoft.com/en-us/windows/win32/api/sspi/nf-sspi-changeaccountpasswordw)
1163 fn change_password<'a>(&'a mut self, change_password: ChangePassword<'a>) -> Result<GeneratorChangePassword<'a>>;
1164}
1165
1166/// Protocol used to establish connection.
1167///
1168/// # MSDN
1169///
1170/// [SecPkgContext_ConnectionInfo (`dwProtocol` field)](https://learn.microsoft.com/en-us/windows/win32/api/schannel/ns-schannel-secpkgcontext_connectioninfo)
1171#[derive(Debug, Clone, Eq, PartialEq, FromPrimitive, ToPrimitive)]
1172pub enum ConnectionProtocol {
1173 SpProtTls1Client = 0x80,
1174 SpProtTls1Server = 0x40,
1175 SpProtSsl3Client = 0x20,
1176 SpProtSsl3Server = 0x10,
1177 SpProtTls1_1Client = 0x200,
1178 SpProtTls1_1Server = 0x100,
1179 SpProtTls1_2Client = 0x800,
1180 SpProtTls1_2Server = 0x400,
1181 SpProtTls1_3Client = 0x00002000,
1182 SpProtTls1_3Server = 0x00001000,
1183 SpProtPct1Client = 0x2,
1184 SpProtPct1Server = 0x1,
1185 SpProtSsl2Client = 0x8,
1186 SpProtSsl2Server = 0x4,
1187}
1188
1189/// Algorithm identifier for the bulk encryption cipher used by the connection.
1190///
1191/// # MSDN
1192///
1193/// [SecPkgContext_ConnectionInfo (`aiCipher` field)](https://learn.microsoft.com/en-us/windows/win32/api/schannel/ns-schannel-secpkgcontext_connectioninfo)
1194#[derive(Debug, Clone, Eq, PartialEq, FromPrimitive, ToPrimitive)]
1195pub enum ConnectionCipher {
1196 Calg3des = 26115,
1197 CalgAes128 = 26126,
1198 CalgAes256 = 26128,
1199 CalgDes = 26113,
1200 CalgRc2 = 26114,
1201 CalgRc4 = 26625,
1202 NoEncryption = 0,
1203}
1204
1205/// ALG_ID indicating the hash used for generating Message Authentication Codes (MACs).
1206///
1207/// # MSDN
1208///
1209/// [SecPkgContext_ConnectionInfo (`aiHash` field)](https://learn.microsoft.com/en-us/windows/win32/api/schannel/ns-schannel-secpkgcontext_connectioninfo)
1210#[derive(Debug, Clone, Eq, PartialEq, FromPrimitive, ToPrimitive)]
1211pub enum ConnectionHash {
1212 CalgMd5 = 32771,
1213 CalgSha = 32772,
1214}
1215
1216/// ALG_ID indicating the key exchange algorithm used to generate the shared master secret.
1217///
1218/// # MSDN
1219///
1220/// [SecPkgContext_ConnectionInfo (`aiExch` field)](https://learn.microsoft.com/en-us/windows/win32/api/schannel/ns-schannel-secpkgcontext_connectioninfo)
1221#[derive(Debug, Clone, Eq, PartialEq, FromPrimitive, ToPrimitive)]
1222pub enum ConnectionKeyExchange {
1223 CalgRsaKeyx = 41984,
1224 CalgDhEphem = 43522,
1225}
1226
1227/// Type of certificate encoding used.
1228///
1229/// # MSDN
1230///
1231/// [CERT_CONTEXT (`dwCertEncodingType` field)](https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cert_context)
1232#[derive(Debug, Clone, Eq, PartialEq, FromPrimitive, ToPrimitive)]
1233pub enum CertEncodingType {
1234 Pkcs7AsnEncoding = 65536,
1235 X509AsnEncoding = 1,
1236}
1237
1238/// The CERT_CONTEXT structure contains both the encoded and decoded representations of a certificate.
1239///
1240/// # MSDN
1241///
1242/// [CERT_CONTEXT](https://learn.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cert_context)
1243#[derive(Debug, Clone, PartialEq)]
1244pub struct CertContext {
1245 pub encoding_type: CertEncodingType,
1246 pub raw_cert: Vec<u8>,
1247 pub cert: Certificate,
1248}
1249
1250/// This structure contains protocol and cipher information.
1251///
1252/// # MSDN
1253///
1254/// [SecPkgContext_ConnectionInfo](https://learn.microsoft.com/en-us/windows/win32/api/schannel/ns-schannel-secpkgcontext_connectioninfo)
1255#[derive(Debug, Clone, Eq, PartialEq)]
1256pub struct ConnectionInfo {
1257 pub protocol: ConnectionProtocol,
1258 pub cipher: ConnectionCipher,
1259 pub cipher_strength: u32,
1260 pub hash: ConnectionHash,
1261 pub hash_strength: u32,
1262 pub key_exchange: ConnectionKeyExchange,
1263 pub exchange_strength: u32,
1264}
1265
1266/// Trait for performing authentication on the client or server side
1267pub trait SspiImpl {
1268 /// Represents raw data for authentication
1269 type CredentialsHandle;
1270 /// Represents authentication data prepared for the authentication process
1271 type AuthenticationData;
1272
1273 fn acquire_credentials_handle_impl(
1274 &mut self,
1275 builder: FilledAcquireCredentialsHandle<'_, Self::CredentialsHandle, Self::AuthenticationData>,
1276 ) -> Result<AcquireCredentialsHandleResult<Self::CredentialsHandle>>;
1277
1278 fn initialize_security_context_impl<'ctx, 'b, 'g>(
1279 &'ctx mut self,
1280 builder: &'b mut FilledInitializeSecurityContext<'ctx, Self::CredentialsHandle>,
1281 ) -> Result<GeneratorInitSecurityContext<'g>>
1282 where
1283 'ctx: 'g,
1284 'b: 'g;
1285
1286 fn accept_security_context_impl<'a>(
1287 &'a mut self,
1288 builder: FilledAcceptSecurityContext<'a, Self::CredentialsHandle>,
1289 ) -> Result<GeneratorAcceptSecurityContext<'a>>;
1290}
1291
1292pub trait SspiEx
1293where
1294 Self: Sized + SspiImpl,
1295{
1296 fn custom_set_auth_identity(&mut self, identity: Self::AuthenticationData) -> Result<()>;
1297}
1298
1299pub type SspiPackage<'a, CredsHandle, AuthData> =
1300 &'a mut dyn SspiImpl<CredentialsHandle = CredsHandle, AuthenticationData = AuthData>;
1301
1302bitflags! {
1303 /// Indicate the quality of protection. Used in the `encrypt_message` method.
1304 ///
1305 /// # MSDN
1306 ///
1307 /// * [EncryptMessage function (`fQOP` parameter)](https://docs.microsoft.com/en-us/windows/win32/api/sspi/nf-sspi-encryptmessage)
1308 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1309 pub struct EncryptionFlags: u32 {
1310 const WRAP_OOB_DATA = 0x4000_0000;
1311 const WRAP_NO_ENCRYPT = 0x8000_0001;
1312 }
1313}
1314
1315bitflags! {
1316 /// Indicate the quality of protection. Returned by the `decrypt_message` method.
1317 ///
1318 /// # MSDN
1319 ///
1320 /// * [DecryptMessage function (`pfQOP` parameter)](https://docs.microsoft.com/en-us/windows/win32/api/sspi/nf-sspi-decryptmessage)
1321 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1322 pub struct DecryptionFlags: u32 {
1323 const SIGN_ONLY = 0x8000_0000;
1324 const WRAP_NO_ENCRYPT = 0x8000_0001;
1325 }
1326}
1327
1328bitflags! {
1329 /// Indicate requests for the context. Not all packages can support all requirements. Bit flags can be combined by using bitwise-OR operations.
1330 ///
1331 /// # MSDN
1332 ///
1333 /// * [Context Requirements](https://docs.microsoft.com/en-us/windows/win32/secauthn/context-requirements)
1334 /// * [InitializeSecurityContextW function (fContextReq parameter)](https://docs.microsoft.com/en-us/windows/win32/api/sspi/nf-sspi-initializesecuritycontextw)
1335 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1336 pub struct ClientRequestFlags: u32 {
1337 /// The server can use the context to authenticate to other servers as the client.
1338 /// The `MUTUAL_AUTH` flag must be set for this flag to work. Valid for Kerberos. Ignore this flag for constrained delegation.
1339 const DELEGATE = 0x1;
1340 /// The mutual authentication policy of the service will be satisfied.
1341 const MUTUAL_AUTH = 0x2;
1342 /// Detect replayed messages that have been encoded by using the `encrypt_message` or `make_signature` (TBI) functions.
1343 const REPLAY_DETECT = 0x4;
1344 /// Detect messages received out of sequence.
1345 const SEQUENCE_DETECT = 0x8;
1346 /// Encrypt messages by using the `encrypt_message` function.
1347 const CONFIDENTIALITY = 0x10;
1348 /// A new session key must be negotiated. This value is supported only by the Kerberos security package.
1349 const USE_SESSION_KEY = 0x20;
1350 const PROMPT_FOR_CREDS = 0x40;
1351 /// Schannel must not attempt to supply credentials for the client automatically.
1352 const USE_SUPPLIED_CREDS = 0x80;
1353 /// The security package allocates output buffers for you.
1354 const ALLOCATE_MEMORY = 0x100;
1355 const USE_DCE_STYLE = 0x200;
1356 const DATAGRAM = 0x400;
1357 /// The security context will not handle formatting messages. This value is the default for the Kerberos, Negotiate, and NTLM security packages.
1358 const CONNECTION = 0x800;
1359 const CALL_LEVEL = 0x1000;
1360 const FRAGMENT_SUPPLIED = 0x2000;
1361 /// When errors occur, the remote party will be notified.
1362 const EXTENDED_ERROR = 0x4000;
1363 /// Support a stream-oriented connection.
1364 const STREAM = 0x8000;
1365 /// Sign messages and verify signatures by using the `encrypt_message` and `make_signature` (TBI) functions.
1366 const INTEGRITY = 0x0001_0000;
1367 const IDENTIFY = 0x0002_0000;
1368 const NULL_SESSION = 0x0004_0000;
1369 /// Schannel must not authenticate the server automatically.
1370 const MANUAL_CRED_VALIDATION = 0x0008_0000;
1371 const RESERVED1 = 0x0010_0000;
1372 const FRAGMENT_TO_FIT = 0x0020_0000;
1373 const FORWARD_CREDENTIALS = 0x0040_0000;
1374 /// If this flag is set, the `Integrity` flag is ignored. This value is supported only by the Negotiate and Kerberos security packages.
1375 const NO_INTEGRITY = 0x0080_0000;
1376 const USE_HTTP_STYLE = 0x100_0000;
1377 const UNVERIFIED_TARGET_NAME = 0x2000_0000;
1378 const CONFIDENTIALITY_ONLY = 0x4000_0000;
1379 }
1380}
1381
1382bitflags! {
1383 /// Specify the attributes required by the server to establish the context. Bit flags can be combined by using bitwise-OR operations.
1384 ///
1385 /// # MSDN
1386 ///
1387 /// * [Context Requirements](https://docs.microsoft.com/en-us/windows/win32/secauthn/context-requirements)
1388 /// * [AcceptSecurityContext function function (fContextReq parameter)](https://docs.microsoft.com/en-us/windows/win32/api/sspi/nf-sspi-acceptsecuritycontext?redirectedfrom=MSDN)
1389 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1390 pub struct ServerRequestFlags: u32 {
1391 /// The server is allowed to impersonate the client. Ignore this flag for [constrained delegation](https://docs.microsoft.com/windows/desktop/SecGloss/c-gly).
1392 const DELEGATE = 0x1;
1393 const MUTUAL_AUTH = 0x2;
1394 /// Detect replayed packets.
1395 const REPLAY_DETECT = 0x4;
1396 /// Detect messages received out of sequence.
1397 const SEQUENCE_DETECT = 0x8;
1398 const CONFIDENTIALITY = 0x10;
1399 const USE_SESSION_KEY = 0x20;
1400 const SESSION_TICKET = 0x40;
1401 /// Credential Security Support Provider (CredSSP) will allocate output buffers.
1402 const ALLOCATE_MEMORY = 0x100;
1403 const USE_DCE_STYLE = 0x200;
1404 const DATAGRAM = 0x400;
1405 /// The security context will not handle formatting messages.
1406 const CONNECTION = 0x800;
1407 const CALL_LEVEL = 0x1000;
1408 const FRAGMENT_SUPPLIED = 0x2000;
1409 /// When errors occur, the remote party will be notified.
1410 const EXTENDED_ERROR = 0x8000;
1411 /// Support a stream-oriented connection.
1412 const STREAM = 0x0001_0000;
1413 const INTEGRITY = 0x0002_0000;
1414 const LICENSING = 0x0004_0000;
1415 const IDENTIFY = 0x0008_0000;
1416 const ALLOW_NULL_SESSION = 0x0010_0000;
1417 const ALLOW_NON_USER_LOGONS = 0x0020_0000;
1418 const ALLOW_CONTEXT_REPLAY = 0x0040_0000;
1419 const FRAGMENT_TO_FIT = 0x80_0000;
1420 const NO_TOKEN = 0x100_0000;
1421 const PROXY_BINDINGS = 0x400_0000;
1422 const ALLOW_MISSING_BINDINGS = 0x1000_0000;
1423 }
1424}
1425
1426bitflags! {
1427 /// Indicate the attributes of the established context.
1428 ///
1429 /// # MSDN
1430 ///
1431 /// * [Context Requirements](https://docs.microsoft.com/en-us/windows/win32/secauthn/context-requirements)
1432 /// * [InitializeSecurityContextW function (pfContextAttr parameter)](https://docs.microsoft.com/en-us/windows/win32/api/sspi/nf-sspi-initializesecuritycontextw)
1433 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1434 pub struct ClientResponseFlags: u32 {
1435 /// The server can use the context to authenticate to other servers as the client.
1436 /// The `MUTUAL_AUTH` flag must be set for this flag to work. Valid for Kerberos. Ignore this flag for constrained delegation.
1437 const DELEGATE = 0x1;
1438 /// The mutual authentication policy of the service will be satisfied.
1439 const MUTUAL_AUTH = 0x2;
1440 /// Detect replayed messages that have been encoded by using the `encrypt_message` or `make_signature` (TBI) functions.
1441 const REPLAY_DETECT = 0x4;
1442 /// Detect messages received out of sequence.
1443 const SEQUENCE_DETECT = 0x8;
1444 /// Encrypt messages by using the `encrypt_message` function.
1445 const CONFIDENTIALITY = 0x10;
1446 /// A new session key must be negotiated. This value is supported only by the Kerberos security package.
1447 const USE_SESSION_KEY = 0x20;
1448 const USED_COLLECTED_CREDS = 0x40;
1449 /// Schannel must not attempt to supply credentials for the client automatically.
1450 const USED_SUPPLIED_CREDS = 0x80;
1451 /// The security package allocates output buffers for you.
1452 const ALLOCATED_MEMORY = 0x100;
1453 const USED_DCE_STYLE = 0x200;
1454 const DATAGRAM = 0x400;
1455 /// The security context will not handle formatting messages. This value is the default for the Kerberos, Negotiate, and NTLM security packages.
1456 const CONNECTION = 0x800;
1457 const INTERMEDIATE_RETURN = 0x1000;
1458 const CALL_LEVEL = 0x2000;
1459 /// When errors occur, the remote party will be notified.
1460 const EXTENDED_ERROR = 0x4000;
1461 /// Support a stream-oriented connection.
1462 const STREAM = 0x8000;
1463 /// Sign messages and verify signatures by using the `encrypt_message` and `make_signature` (TBI) functions.
1464 const INTEGRITY = 0x0001_0000;
1465 const IDENTIFY = 0x0002_0000;
1466 const NULL_SESSION = 0x0004_0000;
1467 /// Schannel must not authenticate the server automatically.
1468 const MANUAL_CRED_VALIDATION = 0x0008_0000;
1469 const RESERVED1 = 0x10_0000;
1470 const FRAGMENT_ONLY = 0x0020_0000;
1471 const FORWARD_CREDENTIALS = 0x0040_0000;
1472 const USED_HTTP_STYLE = 0x100_0000;
1473 const NO_ADDITIONAL_TOKEN = 0x200_0000;
1474 const REAUTHENTICATION = 0x800_0000;
1475 const CONFIDENTIALITY_ONLY = 0x4000_0000;
1476 }
1477}
1478
1479bitflags! {
1480 /// Indicate the attributes of the established context.
1481 ///
1482 /// # MSDN
1483 ///
1484 /// * [Context Requirements](https://docs.microsoft.com/en-us/windows/win32/secauthn/context-requirements)
1485 /// * [AcceptSecurityContext function function (pfContextAttr parameter)](https://docs.microsoft.com/en-us/windows/win32/api/sspi/nf-sspi-acceptsecuritycontext?redirectedfrom=MSDN)
1486 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1487 pub struct ServerResponseFlags: u32 {
1488 /// The server is allowed to impersonate the client. Ignore this flag for [constrained delegation](https://docs.microsoft.com/windows/desktop/SecGloss/c-gly).
1489 const DELEGATE = 0x1;
1490 const MUTUAL_AUTH = 0x2;
1491 /// Detect replayed packets.
1492 const REPLAY_DETECT = 0x4;
1493 /// Detect messages received out of sequence.
1494 const SEQUENCE_DETECT = 0x8;
1495 const CONFIDENTIALITY = 0x10;
1496 const USE_SESSION_KEY = 0x20;
1497 const SESSION_TICKET = 0x40;
1498 /// Credential Security Support Provider (CredSSP) will allocate output buffers.
1499 const ALLOCATED_MEMORY = 0x100;
1500 const USED_DCE_STYLE = 0x200;
1501 const DATAGRAM = 0x400;
1502 /// The security context will not handle formatting messages.
1503 const CONNECTION = 0x800;
1504 const CALL_LEVEL = 0x2000;
1505 const THIRD_LEG_FAILED = 0x4000;
1506 /// When errors occur, the remote party will be notified.
1507 const EXTENDED_ERROR = 0x8000;
1508 /// Support a stream-oriented connection.
1509 const STREAM = 0x0001_0000;
1510 const INTEGRITY = 0x0002_0000;
1511 const LICENSING = 0x0004_0000;
1512 const IDENTIFY = 0x0008_0000;
1513 const NULL_SESSION = 0x0010_0000;
1514 const ALLOW_NON_USER_LOGONS = 0x0020_0000;
1515 const ALLOW_CONTEXT_REPLAY = 0x0040_0000;
1516 const FRAGMENT_ONLY = 0x0080_0000;
1517 const NO_TOKEN = 0x100_0000;
1518 const NO_ADDITIONAL_TOKEN = 0x200_0000;
1519 }
1520}
1521
1522/// The data representation, such as byte ordering, on the target.
1523///
1524/// # MSDN
1525///
1526/// * [AcceptSecurityContext function (TargetDataRep parameter)](https://docs.microsoft.com/en-us/windows/win32/api/sspi/nf-sspi-acceptsecuritycontext)
1527#[derive(Debug, Copy, Clone, Eq, PartialEq, FromPrimitive, ToPrimitive)]
1528pub enum DataRepresentation {
1529 Network = 0,
1530 Native = 0x10,
1531}
1532
1533/// Describes a buffer allocated by a transport application to pass to a security package.
1534///
1535/// # MSDN
1536///
1537/// * [SecBuffer structure](https://docs.microsoft.com/en-us/windows/win32/api/sspi/ns-sspi-secbuffer)
1538#[derive(Clone)]
1539pub struct SecurityBuffer {
1540 pub buffer: Vec<u8>,
1541 pub buffer_type: SecurityBufferType,
1542}
1543
1544impl fmt::Debug for SecurityBuffer {
1545 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1546 write!(
1547 f,
1548 "SecurityBufferRef {{ buffer_type: {:?}, buffer: 0x",
1549 self.buffer_type
1550 )?;
1551 self.buffer.iter().try_for_each(|byte| write!(f, "{byte:02X}"))?;
1552 write!(f, " }}")?;
1553
1554 Ok(())
1555 }
1556}
1557
1558impl SecurityBuffer {
1559 pub fn new(buffer: Vec<u8>, buffer_type: BufferType) -> Self {
1560 Self {
1561 buffer,
1562 buffer_type: SecurityBufferType {
1563 buffer_type,
1564 buffer_flags: SecurityBufferFlags::NONE,
1565 },
1566 }
1567 }
1568
1569 pub fn find_buffer(buffers: &[SecurityBuffer], buffer_type: BufferType) -> Result<&SecurityBuffer> {
1570 buffers
1571 .iter()
1572 .find(|b| b.buffer_type.buffer_type == buffer_type)
1573 .ok_or_else(|| {
1574 Error::new(
1575 ErrorKind::InvalidToken,
1576 format!("no buffer was provided with type {:?}", buffer_type),
1577 )
1578 })
1579 }
1580
1581 pub fn find_buffer_mut(buffers: &mut [SecurityBuffer], buffer_type: BufferType) -> Result<&mut SecurityBuffer> {
1582 buffers
1583 .iter_mut()
1584 .find(|b| b.buffer_type.buffer_type == buffer_type)
1585 .ok_or_else(|| {
1586 Error::new(
1587 ErrorKind::InvalidToken,
1588 format!("no buffer was provided with type {:?}", buffer_type),
1589 )
1590 })
1591 }
1592}
1593
1594/// Bit flags that indicate the type of buffer.
1595///
1596/// # MSDN
1597///
1598/// * [SecBuffer structure (BufferType parameter)](https://docs.microsoft.com/en-us/windows/win32/api/sspi/ns-sspi-secbuffer)
1599#[repr(u32)]
1600#[derive(Debug, Copy, Clone, Eq, PartialEq, Default, FromPrimitive, ToPrimitive)]
1601pub enum BufferType {
1602 #[default]
1603 Empty = 0,
1604 /// The buffer contains common data. The security package can read and write this data, for example, to encrypt some or all of it.
1605 Data = 1,
1606 /// The buffer contains the security token portion of the message. This is read-only for input parameters or read/write for output parameters.
1607 Token = 2,
1608 TransportToPackageParameters = 3,
1609 /// The security package uses this value to indicate the number of missing bytes in a particular message.
1610 Missing = 4,
1611 /// The security package uses this value to indicate the number of extra or unprocessed bytes in a message.
1612 Extra = 5,
1613 /// The buffer contains a protocol-specific trailer for a particular record. It is not usually of interest to callers.
1614 StreamTrailer = 6,
1615 /// The buffer contains a protocol-specific header for a particular record. It is not usually of interest to callers.
1616 StreamHeader = 7,
1617 NegotiationInfo = 8,
1618 Padding = 9,
1619 Stream = 10,
1620 ObjectIdsList = 11,
1621 ObjectIdsListSignature = 12,
1622 /// This flag is reserved. Do not use it.
1623 Target = 13,
1624 /// The buffer contains channel binding information.
1625 ChannelBindings = 14,
1626 /// The buffer contains a [DOMAIN_PASSWORD_INFORMATION](https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/ns-ntsecapi-domain_password_information) structure.
1627 ChangePasswordResponse = 15,
1628 /// The buffer specifies the [service principal name (SPN)](https://docs.microsoft.com/en-us/windows/win32/secgloss/s-gly) of the target.
1629 TargetHost = 16,
1630 /// The buffer contains an alert message.
1631 Alert = 17,
1632 /// The buffer contains a list of application protocol IDs, one list per application protocol negotiation extension type to be enabled.
1633 ApplicationProtocol = 18,
1634 /// The buffer contains a bitmask for a `ReadOnly` buffer.
1635 AttributeMark = 0xF000_0000,
1636 /// The buffer is read-only with no checksum. This flag is intended for sending header information to the security package for computing the checksum.
1637 /// The package can read this buffer, but cannot modify it.
1638 ReadOnly = 0x8000_0000,
1639 /// The buffer is read-only with a checksum.
1640 ReadOnlyWithChecksum = 0x1000_0000,
1641}
1642
1643bitflags! {
1644 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
1645 /// Security buffer flags.
1646 ///
1647 /// [`SecBuffer` structure (sspi.h)](https://learn.microsoft.com/en-us/windows/win32/api/sspi/ns-sspi-secbuffer).
1648 pub struct SecurityBufferFlags: u32 {
1649 /// There is no flags for the buffer.
1650 const NONE = 0x0;
1651 /// The buffer is read-only with no checksum. This flag is intended for sending header information to the security package for
1652 /// computing the checksum. The package can read this buffer, but cannot modify it.
1653 const SECBUFFER_READONLY = 0x80000000;
1654 /// The buffer is read-only with a checksum.
1655 const SECBUFFER_READONLY_WITH_CHECKSUM = 0x10000000;
1656 }
1657}
1658
1659/// Security buffer type.
1660///
1661/// Contains the actual security buffer type and its flags.
1662#[derive(Clone, Copy, Eq, PartialEq, Default)]
1663pub struct SecurityBufferType {
1664 /// Security buffer type.
1665 pub buffer_type: BufferType,
1666 /// Security buffer flags.
1667 pub buffer_flags: SecurityBufferFlags,
1668}
1669
1670impl SecurityBufferType {
1671 /// The buffer contains a bitmask for a `SECBUFFER_READONLY_WITH_CHECKSUM` buffer.
1672 ///
1673 /// [`SecBuffer` structure (sspi.h)](https://learn.microsoft.com/en-us/windows/win32/api/sspi/ns-sspi-secbuffer)
1674 pub const SECBUFFER_ATTRMASK: u32 = 0xf0000000;
1675}
1676
1677impl TryFrom<u32> for SecurityBufferType {
1678 type Error = Error;
1679
1680 fn try_from(value: u32) -> Result<Self> {
1681 use num_traits::cast::FromPrimitive;
1682
1683 let buffer_type = value & !Self::SECBUFFER_ATTRMASK;
1684 let buffer_type = BufferType::from_u32(buffer_type).ok_or_else(|| {
1685 Error::new(
1686 ErrorKind::InternalError,
1687 format!("u32({}) to UnflaggedSecurityBuffer conversion error", buffer_type),
1688 )
1689 })?;
1690
1691 let buffer_flags = value & Self::SECBUFFER_ATTRMASK;
1692 let buffer_flags = SecurityBufferFlags::from_bits(buffer_flags).ok_or_else(|| {
1693 Error::new(
1694 ErrorKind::InternalError,
1695 format!("invalid SecurityBufferFlags: {}", buffer_flags),
1696 )
1697 })?;
1698
1699 Ok(Self {
1700 buffer_type,
1701 buffer_flags,
1702 })
1703 }
1704}
1705
1706impl From<SecurityBufferType> for u32 {
1707 fn from(value: SecurityBufferType) -> u32 {
1708 use num_traits::cast::ToPrimitive;
1709
1710 value.buffer_type.to_u32().unwrap() | value.buffer_flags.bits()
1711 }
1712}
1713
1714impl fmt::Debug for SecurityBufferType {
1715 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1716 f.write_fmt(format_args!("({:?}, {:?})", self.buffer_type, self.buffer_flags))
1717 }
1718}
1719
1720/// A flag that indicates how the credentials are used.
1721///
1722/// # MSDN
1723///
1724/// * [AcquireCredentialsHandleW function (fCredentialUse parameter)](https://docs.microsoft.com/en-us/windows/win32/api/sspi/nf-sspi-acquirecredentialshandlew)
1725#[derive(Debug, Copy, Clone, Eq, PartialEq, FromPrimitive, ToPrimitive)]
1726pub enum CredentialUse {
1727 Inbound = 1,
1728 Outbound = 2,
1729 Both = 3,
1730 Default = 4,
1731}
1732
1733/// Represents the security principal in use.
1734#[derive(Debug, Clone)]
1735pub enum SecurityPackageType {
1736 Ntlm,
1737 Kerberos,
1738 Negotiate,
1739 Pku2u,
1740 #[cfg(feature = "tsssp")]
1741 CredSsp,
1742 Other(String),
1743}
1744
1745impl AsRef<str> for SecurityPackageType {
1746 fn as_ref(&self) -> &str {
1747 match self {
1748 SecurityPackageType::Ntlm => ntlm::PKG_NAME,
1749 SecurityPackageType::Kerberos => kerberos::PKG_NAME,
1750 SecurityPackageType::Negotiate => negotiate::PKG_NAME,
1751 SecurityPackageType::Pku2u => pku2u::PKG_NAME,
1752 #[cfg(feature = "tsssp")]
1753 SecurityPackageType::CredSsp => sspi_cred_ssp::PKG_NAME,
1754 SecurityPackageType::Other(name) => name.as_str(),
1755 }
1756 }
1757}
1758
1759impl fmt::Display for SecurityPackageType {
1760 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1761 match self {
1762 SecurityPackageType::Ntlm => write!(f, "{}", ntlm::PKG_NAME),
1763 SecurityPackageType::Kerberos => write!(f, "{}", kerberos::PKG_NAME),
1764 SecurityPackageType::Negotiate => write!(f, "{}", negotiate::PKG_NAME),
1765 SecurityPackageType::Pku2u => write!(f, "{}", pku2u::PKG_NAME),
1766 #[cfg(feature = "tsssp")]
1767 SecurityPackageType::CredSsp => write!(f, "{}", sspi_cred_ssp::PKG_NAME),
1768 SecurityPackageType::Other(name) => write!(f, "{name}"),
1769 }
1770 }
1771}
1772
1773impl str::FromStr for SecurityPackageType {
1774 type Err = Error;
1775
1776 fn from_str(s: &str) -> Result<Self> {
1777 match s {
1778 ntlm::PKG_NAME => Ok(SecurityPackageType::Ntlm),
1779 kerberos::PKG_NAME => Ok(SecurityPackageType::Kerberos),
1780 negotiate::PKG_NAME => Ok(SecurityPackageType::Negotiate),
1781 pku2u::PKG_NAME => Ok(SecurityPackageType::Pku2u),
1782 #[cfg(feature = "tsssp")]
1783 sspi_cred_ssp::PKG_NAME => Ok(SecurityPackageType::CredSsp),
1784 s => Ok(SecurityPackageType::Other(s.to_string())),
1785 }
1786 }
1787}
1788
1789/// General security principal information
1790///
1791/// Provides general information about a security package, such as its name and capabilities. Returned by `query_security_package_info`.
1792///
1793/// # MSDN
1794///
1795/// * [SecPkgInfoW structure](https://docs.microsoft.com/en-us/windows/win32/api/sspi/ns-sspi-secpkginfow)
1796#[derive(Debug, Clone)]
1797pub struct PackageInfo {
1798 pub capabilities: PackageCapabilities,
1799 pub rpc_id: u16,
1800 pub max_token_len: u32,
1801 pub name: SecurityPackageType,
1802 pub comment: String,
1803}
1804
1805bitflags! {
1806 /// Set of bit flags that describes the capabilities of the security package. It is possible to combine them.
1807 ///
1808 /// # MSDN
1809 ///
1810 /// * [SecPkgInfoW structure (`fCapabilities` parameter)](https://docs.microsoft.com/en-us/windows/win32/api/sspi/ns-sspi-secpkginfow)
1811 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1812 pub struct PackageCapabilities: u32 {
1813 /// The security package supports the `make_signature` (TBI) and `verify_signature` (TBI) functions.
1814 const INTEGRITY = 0x1;
1815 /// The security package supports the `encrypt_message` and `decrypt_message` functions.
1816 const PRIVACY = 0x2;
1817 /// The package is interested only in the security-token portion of messages, and will ignore any other buffers. This is a performance-related issue.
1818 const TOKEN_ONLY = 0x4;
1819 /// Supports [datagram](https://docs.microsoft.com/en-us/windows/win32/secgloss/d-gly)-style authentication.
1820 /// For more information, see [SSPI Context Semantics](https://docs.microsoft.com/en-us/windows/win32/secauthn/sspi-context-semantics).
1821 const DATAGRAM = 0x8;
1822 /// Supports connection-oriented style authentication. For more information, see [SSPI Context Semantics](https://docs.microsoft.com/en-us/windows/win32/secauthn/sspi-context-semantics).
1823 const CONNECTION = 0x10;
1824 /// Multiple legs are required for authentication.
1825 const MULTI_REQUIRED = 0x20;
1826 /// Server authentication support is not provided.
1827 const CLIENT_ONLY = 0x40;
1828 /// Supports extended error handling. For more information, see [Extended Error Information](https://docs.microsoft.com/en-us/windows/win32/secauthn/extended-error-information).
1829 const EXTENDED_ERROR = 0x80;
1830 /// Supports Windows impersonation in server contexts.
1831 const IMPERSONATION = 0x100;
1832 /// Understands Windows principal and target names.
1833 const ACCEPT_WIN32_NAME = 0x200;
1834 /// Supports stream semantics. For more information, see [SSPI Context Semantics](https://docs.microsoft.com/en-us/windows/win32/secauthn/sspi-context-semantics).
1835 const STREAM = 0x400;
1836 /// Can be used by the [Microsoft Negotiate](https://docs.microsoft.com/windows/desktop/SecAuthN/microsoft-negotiate) security package.
1837 const NEGOTIABLE = 0x800;
1838 /// Supports GSS compatibility.
1839 const GSS_COMPATIBLE = 0x1000;
1840 /// Supports [LsaLogonUser](https://docs.microsoft.com/windows/desktop/api/ntsecapi/nf-ntsecapi-lsalogonuser).
1841 const LOGON = 0x2000;
1842 /// Token buffers are in ASCII characters format.
1843 const ASCII_BUFFERS = 0x4000;
1844 /// Supports separating large tokens into smaller buffers so that applications can make repeated calls to
1845 /// `initialize_security_context` and `accept_security_context` with the smaller buffers to complete authentication.
1846 const FRAGMENT = 0x8000;
1847 /// Supports mutual authentication.
1848 const MUTUAL_AUTH = 0x1_0000;
1849 /// Supports delegation.
1850 const DELEGATION = 0x2_0000;
1851 /// The security package supports using a checksum instead of in-place encryption when calling the `encrypt_message` function.
1852 const READONLY_WITH_CHECKSUM = 0x4_0000;
1853 /// Supports callers with restricted tokens.
1854 const RESTRICTED_TOKENS = 0x8_0000;
1855 /// The security package extends the [Microsoft Negotiate](https://docs.microsoft.com/windows/desktop/SecAuthN/microsoft-negotiate) security package.
1856 /// There can be at most one package of this type.
1857 const NEGO_EXTENDER = 0x10_0000;
1858 /// This package is negotiated by the package of type `NEGO_EXTENDER`.
1859 const NEGOTIABLE2 = 0x20_0000;
1860 /// This package receives all calls from app container apps.
1861 const APP_CONTAINER_PASSTHROUGH = 0x40_0000;
1862 /// This package receives calls from app container apps if one of the following checks succeeds:
1863 /// * Caller has default credentials capability
1864 /// * The target is a proxy server
1865 /// * The caller has supplied credentials
1866 const APP_CONTAINER_CHECKS = 0x80_0000;
1867 }
1868}
1869
1870/// Indicates the sizes of the various parts of a stream for use with the message support functions.
1871/// `query_context_stream_sizes` function returns this structure.
1872///
1873/// # MSDN
1874///
1875/// * [SecPkgContext_StreamSizes](https://learn.microsoft.com/en-us/windows/win32/api/sspi/ns-sspi-secpkgcontext_streamsizes)
1876#[derive(Debug, Clone, Eq, PartialEq)]
1877pub struct StreamSizes {
1878 pub header: u32,
1879 pub trailer: u32,
1880 pub max_message: u32,
1881 pub buffers: u32,
1882 pub block_size: u32,
1883}
1884
1885/// Indicates the sizes of important structures used in the message support functions.
1886/// `query_context_sizes` function returns this structure.
1887///
1888/// # MSDN
1889///
1890/// * [SecPkgContext_Sizes structure](https://docs.microsoft.com/en-us/windows/win32/api/sspi/ns-sspi-secpkgcontext_sizes)
1891#[derive(Debug, Clone, Eq, PartialEq)]
1892pub struct ContextSizes {
1893 pub max_token: u32,
1894 pub max_signature: u32,
1895 pub block: u32,
1896 pub security_trailer: u32,
1897}
1898
1899/// Contains trust information about a certificate in a certificate chain,
1900/// summary trust information about a simple chain of certificates, or summary information about an array of simple chains.
1901/// `query_context_cert_trust_status` function returns this structure.
1902///
1903/// # MSDN
1904///
1905/// * [CERT_TRUST_STATUS structure](https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cert_trust_status)
1906#[derive(Debug, Clone)]
1907pub struct CertTrustStatus {
1908 pub error_status: CertTrustErrorStatus,
1909 pub info_status: CertTrustInfoStatus,
1910}
1911
1912bitflags! {
1913 /// Flags representing the error status codes used in `CertTrustStatus`.
1914 ///
1915 /// # MSDN
1916 ///
1917 /// * [CERT_TRUST_STATUS structure](https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cert_trust_status)
1918 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1919 pub struct CertTrustErrorStatus: u32 {
1920 /// No error found for this certificate or chain.
1921 const NO_ERROR = 0x0;
1922 /// This certificate or one of the certificates in the certificate chain is not time valid.
1923 const IS_NOT_TIME_VALID = 0x1;
1924 const IS_NOT_TIME_NESTED = 0x2;
1925 /// Trust for this certificate or one of the certificates in the certificate chain has been revoked.
1926 const IS_REVOKED = 0x4;
1927 /// The certificate or one of the certificates in the certificate chain does not have a valid signature.
1928 const IS_NOT_SIGNATURE_VALID = 0x8;
1929 /// The certificate or certificate chain is not valid for its proposed usage.
1930 const IS_NOT_VALID_FOR_USAGE = 0x10;
1931 /// The certificate or certificate chain is based on an untrusted root.
1932 const IS_UNTRUSTED_ROOT = 0x20;
1933 /// The revocation status of the certificate or one of the certificates in the certificate chain is unknown.
1934 const REVOCATION_STATUS_UNKNOWN = 0x40;
1935 /// One of the certificates in the chain was issued by a
1936 /// [`certification authority`](https://docs.microsoft.com/windows/desktop/SecGloss/c-gly)
1937 /// that the original certificate had certified.
1938 const IS_CYCLIC = 0x80;
1939 /// One of the certificates has an extension that is not valid.
1940 const INVALID_EXTENSION = 0x100;
1941 /// The certificate or one of the certificates in the certificate chain has a policy constraints extension,
1942 /// and one of the issued certificates has a disallowed policy mapping extension or does not have a
1943 /// required issuance policies extension.
1944 const INVALID_POLICY_CONSTRAINTS = 0x200;
1945 /// The certificate or one of the certificates in the certificate chain has a basic constraints extension,
1946 /// and either the certificate cannot be used to issue other certificates, or the chain path length has been exceeded.
1947 const INVALID_BASIC_CONSTRAINTS = 0x400;
1948 /// The certificate or one of the certificates in the certificate chain has a name constraints extension that is not valid.
1949 const INVALID_NAME_CONSTRAINTS = 0x800;
1950 /// The certificate or one of the certificates in the certificate chain has a name constraints extension that contains
1951 /// unsupported fields. The minimum and maximum fields are not supported.
1952 /// Thus minimum must always be zero and maximum must always be absent. Only UPN is supported for an Other Name.
1953 /// The following alternative name choices are not supported:
1954 /// * X400 Address
1955 /// * EDI Party Name
1956 /// * Registered Id
1957 const HAS_NOT_SUPPORTED_NAME_CONSTRAINT = 0x1000;
1958 /// The certificate or one of the certificates in the certificate chain has a name constraints extension and a name
1959 /// constraint is missing for one of the name choices in the end certificate.
1960 const HAS_NOT_DEFINED_NAME_CONSTRAINT = 0x2000;
1961 /// The certificate or one of the certificates in the certificate chain has a name constraints extension,
1962 /// and there is not a permitted name constraint for one of the name choices in the end certificate.
1963 const HAS_NOT_PERMITTED_NAME_CONSTRAINT = 0x4000;
1964 /// The certificate or one of the certificates in the certificate chain has a name constraints extension,
1965 /// and one of the name choices in the end certificate is explicitly excluded.
1966 const HAS_EXCLUDED_NAME_CONSTRAINT = 0x8000;
1967 /// The certificate chain is not complete.
1968 const IS_PARTIAL_CHAIN = 0x0001_0000;
1969 /// A [certificate trust list](https://docs.microsoft.com/windows/desktop/SecGloss/c-gly)
1970 /// (CTL) used to create this chain was not time valid.
1971 const CTL_IS_NOT_TIME_VALID = 0x0002_0000;
1972 /// A CTL used to create this chain did not have a valid signature.
1973 const CTL_IS_NOT_SIGNATURE_VALID = 0x0004_0000;
1974 /// A CTL used to create this chain is not valid for this usage.
1975 const CTL_IS_NOT_VALID_FOR_USAGE = 0x0008_0000;
1976 /// The revocation status of the certificate or one of the certificates in the certificate chain is either offline or stale.
1977 const IS_OFFLINE_REVOCATION = 0x100_0000;
1978 /// The end certificate does not have any resultant issuance policies, and one of the issuing
1979 /// [certification authority](https://docs.microsoft.com/windows/desktop/SecGloss/c-gly)
1980 /// certificates has a policy constraints extension requiring it.
1981 const NO_ISSUANCE_CHAIN_POLICY = 0x200_0000;
1982 }
1983}
1984
1985bitflags! {
1986 /// Flags representing the info status codes used in `CertTrustStatus`.
1987 ///
1988 /// # MSDN
1989 ///
1990 /// * [CERT_TRUST_STATUS structure](https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/ns-wincrypt-cert_trust_status)
1991 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1992 pub struct CertTrustInfoStatus: u32 {
1993 /// An exact match issuer certificate has been found for this certificate. This status code applies to certificates only.
1994 const HAS_EXACT_MATCH_ISSUER = 0x1;
1995 /// A key match issuer certificate has been found for this certificate. This status code applies to certificates only.
1996 const HAS_KEY_MATCH_ISSUER = 0x2;
1997 /// A name match issuer certificate has been found for this certificate. This status code applies to certificates only.
1998 const HAS_NAME_MATCH_ISSUER = 0x4;
1999 /// This certificate is self-signed. This status code applies to certificates only.
2000 const IS_SELF_SIGNED = 0x8;
2001 const AUTO_UPDATE_CA_REVOCATION = 0x10;
2002 const AUTO_UPDATE_END_REVOCATION = 0x20;
2003 const NO_OCSP_FAILOVER_TO_CRL = 0x40;
2004 const IS_KEY_ROLLOVER = 0x80;
2005 /// The certificate or chain has a preferred issuer. This status code applies to certificates and chains.
2006 const HAS_PREFERRED_ISSUER = 0x100;
2007 /// An issuance chain policy exists. This status code applies to certificates and chains.
2008 const HAS_ISSUANCE_CHAIN_POLICY = 0x200;
2009 /// A valid name constraints for all namespaces, including UPN. This status code applies to certificates and chains.
2010 const HAS_VALID_NAME_CONSTRAINTS = 0x400;
2011 /// This certificate is peer trusted. This status code applies to certificates only.
2012 const IS_PEER_TRUSTED = 0x800;
2013 /// This certificate's [certificate revocation list](https://docs.microsoft.com/windows/desktop/SecGloss/c-gly)
2014 /// (CRL) validity has been extended. This status code applies to certificates only.
2015 const HAS_CRL_VALIDITY_EXTENDED = 0x1000;
2016 const IS_FROM_EXCLUSIVE_TRUST_STORE = 0x2000;
2017 const IS_CA_TRUSTED = 0x4000;
2018 const HAS_AUTO_UPDATE_WEAK_SIGNATURE = 0x8000;
2019 const SSL_HANDSHAKE_OCSP = 0x0004_0000;
2020 const SSL_TIME_VALID_OCSP = 0x0008_0000;
2021 const SSL_RECONNECT_OCSP = 0x0010_0000;
2022 const IS_COMPLEX_CHAIN = 0x0001_0000;
2023 const HAS_ALLOW_WEAK_SIGNATURE = 0x0002_0000;
2024 const SSL_TIME_VALID = 0x100_0000;
2025 const NO_TIME_CHECK = 0x200_0000;
2026 }
2027}
2028
2029/// Indicates the name of the user associated with a security context.
2030/// `query_context_names` function returns this structure.
2031///
2032/// # MSDN
2033///
2034/// * [SecPkgContext_NamesW structure](https://docs.microsoft.com/en-us/windows/win32/api/sspi/ns-sspi-secpkgcontext_namesw)
2035#[derive(Debug, Clone)]
2036pub struct ContextNames {
2037 pub username: Username,
2038}
2039
2040/// Contains information about the session key used for the security context.
2041/// `query_context_session_key` function returns this structure.
2042///
2043/// # MSDN
2044///
2045/// * [SecPkgContext_SessionKey structure](https://learn.microsoft.com/en-us/windows/win32/api/sspi/ns-sspi-secpkgcontext_sessionkey)
2046#[derive(Debug, Clone)]
2047pub struct SessionKeys {
2048 pub session_key: Secret<Vec<u8>>,
2049}
2050
2051/// The kind of an SSPI related error. Enables to specify an error based on its type.
2052///
2053/// [SSPI Status Codes](https://learn.microsoft.com/en-us/windows/win32/secauthn/sspi-status-codes).
2054#[repr(u32)]
2055#[derive(Debug, Copy, Clone, Eq, PartialEq, FromPrimitive, ToPrimitive)]
2056pub enum ErrorKind {
2057 Unknown = 0,
2058 InsufficientMemory = 0x8009_0300,
2059 InvalidHandle = 0x8009_0301,
2060 UnsupportedFunction = 0x8009_0302,
2061 TargetUnknown = 0x8009_0303,
2062 /// May correspond to any internal error (I/O error, server error, etc.).
2063 InternalError = 0x8009_0304,
2064 SecurityPackageNotFound = 0x8009_0305,
2065 NotOwned = 0x8009_0306,
2066 CannotInstall = 0x8009_0307,
2067 /// Used in cases when supplied data is missing or invalid.
2068 InvalidToken = 0x8009_0308,
2069 CannotPack = 0x8009_0309,
2070 OperationNotSupported = 0x8009_030A,
2071 NoImpersonation = 0x8009_030B,
2072 LogonDenied = 0x8009_030C,
2073 UnknownCredentials = 0x8009_030D,
2074 NoCredentials = 0x8009_030E,
2075 /// Used in contexts of supplying invalid credentials.
2076 MessageAltered = 0x8009_030F,
2077 /// Used when a required NTLM state does not correspond to the current.
2078 OutOfSequence = 0x8009_0310,
2079 NoAuthenticatingAuthority = 0x8009_0311,
2080 BadPackageId = 0x8009_0316,
2081 ContextExpired = 0x8009_0317,
2082 IncompleteMessage = 0x8009_0318,
2083 IncompleteCredentials = 0x8009_0320,
2084 BufferTooSmall = 0x8009_0321,
2085 WrongPrincipalName = 0x8009_0322,
2086 TimeSkew = 0x8009_0324,
2087 UntrustedRoot = 0x8009_0325,
2088 IllegalMessage = 0x8009_0326,
2089 CertificateUnknown = 0x8009_0327,
2090 CertificateExpired = 0x8009_0328,
2091 EncryptFailure = 0x8009_0329,
2092 DecryptFailure = 0x8009_0330,
2093 AlgorithmMismatch = 0x8009_0331,
2094 SecurityQosFailed = 0x8009_0332,
2095 UnfinishedContextDeleted = 0x8009_0333,
2096 NoTgtReply = 0x8009_0334,
2097 NoIpAddress = 0x8009_0335,
2098 WrongCredentialHandle = 0x8009_0336,
2099 CryptoSystemInvalid = 0x8009_0337,
2100 MaxReferralsExceeded = 0x8009_0338,
2101 MustBeKdc = 0x8009_0339,
2102 StrongCryptoNotSupported = 0x8009_033A,
2103 TooManyPrincipals = 0x8009_033B,
2104 NoPaData = 0x8009_033C,
2105 PkInitNameMismatch = 0x8009_033D,
2106 SmartCardLogonRequired = 0x8009_033E,
2107 ShutdownInProgress = 0x8009_033F,
2108 KdcInvalidRequest = 0x8009_0340,
2109 KdcUnknownEType = 0x8009_0341,
2110 KdcUnknownEType2 = 0x8009_0342,
2111 UnsupportedPreAuth = 0x8009_0343,
2112 DelegationRequired = 0x8009_0345,
2113 BadBindings = 0x8009_0346,
2114 MultipleAccounts = 0x8009_0347,
2115 NoKerbKey = 0x8009_0348,
2116 CertWrongUsage = 0x8009_0349,
2117 DowngradeDetected = 0x8009_0350,
2118 SmartCardCertificateRevoked = 0x8009_0351,
2119 IssuingCAUntrusted = 0x8009_0352,
2120 RevocationOffline = 0x8009_0353,
2121 PkInitClientFailure = 0x8009_0354,
2122 SmartCardCertExpired = 0x8009_0355,
2123 NoS4uProtSupport = 0x8009_0356,
2124 CrossRealmDelegationFailure = 0x8009_0357,
2125 RevocationOfflineKdc = 0x8009_0358,
2126 IssuingCaUntrustedKdc = 0x8009_0359,
2127 KdcCertExpired = 0x8009_035A,
2128 KdcCertRevoked = 0x8009_035B,
2129 InvalidParameter = 0x8009_035D,
2130 DelegationPolicy = 0x8009_035E,
2131 PolicyNtlmOnly = 0x8009_035F,
2132 NoContext = 0x8009_0361,
2133 Pku2uCertFailure = 0x8009_0362,
2134 MutualAuthFailed = 0x8009_0363,
2135 OnlyHttpsAllowed = 0x8009_0365,
2136 ApplicationProtocolMismatch = 0x8009_0367,
2137}
2138
2139/// Holds the `ErrorKind` and the description of the SSPI-related error.
2140#[derive(Debug, Clone)]
2141pub struct Error {
2142 pub error_type: ErrorKind,
2143 pub description: String,
2144 pub nstatus: Option<credssp::NStatusCode>,
2145}
2146
2147/// The success status of SSPI-related operation.
2148#[derive(Debug, Copy, Clone, Eq, PartialEq, FromPrimitive, ToPrimitive)]
2149pub enum SecurityStatus {
2150 Ok = 0,
2151 ContinueNeeded = 0x0009_0312,
2152 CompleteNeeded = 0x0009_0313,
2153 CompleteAndContinue = 0x0009_0314,
2154 LocalLogon = 0x0009_0315,
2155 ContextExpired = 0x0009_0317,
2156 IncompleteCredentials = 0x0009_0320,
2157 Renegotiate = 0x0009_0321,
2158 NoLsaContext = 0x0009_0323,
2159}
2160
2161impl Error {
2162 /// Allows to fill a new error easily, supplying it with a coherent description.
2163 pub fn new(error_type: ErrorKind, description: impl ToString) -> Self {
2164 Self {
2165 error_type,
2166 description: description.to_string(),
2167 nstatus: None,
2168 }
2169 }
2170
2171 pub fn new_with_nstatus(
2172 error_type: ErrorKind,
2173 description: impl Into<String>,
2174 status_code: credssp::NStatusCode,
2175 ) -> Self {
2176 Self {
2177 error_type,
2178 description: description.into(),
2179 nstatus: Some(status_code),
2180 }
2181 }
2182}
2183
2184impl error::Error for Error {}
2185
2186impl fmt::Display for Error {
2187 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2188 write!(f, "{:?}: {}", self.error_type, self.description)?;
2189
2190 if let Some(nstatus) = self.nstatus {
2191 write!(f, "; status is {}", nstatus)?;
2192 }
2193
2194 Ok(())
2195 }
2196}
2197
2198impl From<auth_identity::UsernameError> for Error {
2199 fn from(value: auth_identity::UsernameError) -> Self {
2200 Error::new(ErrorKind::UnknownCredentials, value)
2201 }
2202}
2203
2204impl From<rsa::Error> for Error {
2205 fn from(value: rsa::Error) -> Self {
2206 Error::new(
2207 ErrorKind::InternalError,
2208 format!("an unexpected RsaError happened: {}", value),
2209 )
2210 }
2211}
2212
2213impl From<Asn1DerError> for Error {
2214 fn from(err: Asn1DerError) -> Self {
2215 Self::new(ErrorKind::InvalidToken, format!("ASN1 DER error: {:?}", err))
2216 }
2217}
2218
2219impl From<KrbError> for Error {
2220 fn from(krb_error: KrbError) -> Self {
2221 let (error_kind, mut description) = map_keb_error_code_to_sspi_error(krb_error.0.error_code.0);
2222
2223 // https://www.rfc-editor.org/rfc/rfc4120#section-5.9.1
2224
2225 // This field contains additional text to help explain the error code
2226 // associated with the failed request
2227 if let Some(e_text) = krb_error.0.e_text.0 {
2228 description.push_str(&format!(". Additional error text: {:?}", e_text.0));
2229 }
2230
2231 // This field contains additional data about the error for use by the
2232 // application to help it recover from or handle the error.
2233 if let Some(e_data) = krb_error.0.e_data.0 {
2234 description.push_str(&format!(". Additional error data: {:?}", e_data.0));
2235 }
2236
2237 Error::new(error_kind, description)
2238 }
2239}
2240
2241impl From<picky_krb::crypto::KerberosCryptoError> for Error {
2242 fn from(err: picky_krb::crypto::KerberosCryptoError) -> Self {
2243 use picky_krb::crypto::KerberosCryptoError;
2244
2245 match err {
2246 KerberosCryptoError::KeyLength(actual, expected) => Self::new(
2247 ErrorKind::InvalidParameter,
2248 format!("invalid key length. actual: {}. expected: {}", actual, expected),
2249 ),
2250 KerberosCryptoError::CipherLength(actual, expected) => Self::new(
2251 ErrorKind::InvalidParameter,
2252 format!("invalid cipher length. actual: {}. expected: {}", actual, expected),
2253 ),
2254 KerberosCryptoError::AlgorithmIdentifier(identifier) => Self::new(
2255 ErrorKind::InvalidParameter,
2256 format!("unknown algorithm identifier: {}", identifier),
2257 ),
2258 KerberosCryptoError::IntegrityCheck => Self::new(ErrorKind::MessageAltered, err.to_string()),
2259 KerberosCryptoError::CipherError(description) => Self::new(ErrorKind::InvalidParameter, description),
2260 KerberosCryptoError::CipherPad(description) => {
2261 Self::new(ErrorKind::InvalidParameter, description.to_string())
2262 }
2263 KerberosCryptoError::CipherUnpad(description) => {
2264 Self::new(ErrorKind::InvalidParameter, description.to_string())
2265 }
2266 KerberosCryptoError::SeedBitLen(description) => Self::new(ErrorKind::InvalidParameter, description),
2267 KerberosCryptoError::AlgorithmIdentifierData(identifier) => Self::new(
2268 ErrorKind::InvalidParameter,
2269 format!("unknown algorithm identifier: {:?}", identifier),
2270 ),
2271 KerberosCryptoError::RandError(rand) => {
2272 Self::new(ErrorKind::InvalidParameter, format!("random error: {:?}", rand))
2273 }
2274 KerberosCryptoError::TooSmallBuffer(inout) => {
2275 Self::new(ErrorKind::InvalidParameter, format!("too small buffer: {:?}", inout))
2276 }
2277 KerberosCryptoError::ArrayTryFromSliceError(array) => Self::new(
2278 ErrorKind::InvalidParameter,
2279 format!("array try from slice error: {:?}", array),
2280 ),
2281 }
2282 }
2283}
2284
2285impl From<picky_krb::crypto::diffie_hellman::DiffieHellmanError> for Error {
2286 fn from(error: picky_krb::crypto::diffie_hellman::DiffieHellmanError) -> Self {
2287 use picky_krb::crypto::diffie_hellman::DiffieHellmanError;
2288
2289 match error {
2290 DiffieHellmanError::BitLen(description) => Self::new(ErrorKind::InternalError, description),
2291 error => Self::new(ErrorKind::InternalError, error.to_string()),
2292 }
2293 }
2294}
2295
2296impl From<CharSetError> for Error {
2297 fn from(err: CharSetError) -> Self {
2298 Self::new(ErrorKind::InternalError, err.to_string())
2299 }
2300}
2301
2302impl From<GssApiMessageError> for Error {
2303 fn from(err: GssApiMessageError) -> Self {
2304 match err {
2305 GssApiMessageError::IoError(err) => Self::from(err),
2306 GssApiMessageError::InvalidId(_, _) => Self::new(ErrorKind::InvalidToken, err.to_string()),
2307 GssApiMessageError::InvalidMicFiller(_) => Self::new(ErrorKind::InvalidToken, err.to_string()),
2308 GssApiMessageError::InvalidWrapFiller(_) => Self::new(ErrorKind::InvalidToken, err.to_string()),
2309 GssApiMessageError::Asn1Error(_) => Self::new(ErrorKind::InvalidToken, err.to_string()),
2310 }
2311 }
2312}
2313
2314impl From<io::Error> for Error {
2315 fn from(err: io::Error) -> Self {
2316 Self::new(ErrorKind::InternalError, format!("IO error: {:?}", err))
2317 }
2318}
2319
2320impl From<getrandom::Error> for Error {
2321 fn from(err: getrandom::Error) -> Self {
2322 Self::new(ErrorKind::InternalError, format!("rand error: {:?}", err))
2323 }
2324}
2325
2326impl From<str::Utf8Error> for Error {
2327 fn from(err: str::Utf8Error) -> Self {
2328 Self::new(ErrorKind::InternalError, err)
2329 }
2330}
2331
2332impl From<string::FromUtf8Error> for Error {
2333 fn from(err: string::FromUtf8Error) -> Self {
2334 Self::new(ErrorKind::InternalError, format!("UTF-8 error: {:?}", err))
2335 }
2336}
2337
2338impl From<string::FromUtf16Error> for Error {
2339 fn from(err: string::FromUtf16Error) -> Self {
2340 Self::new(ErrorKind::InternalError, format!("UTF-16 error: {:?}", err))
2341 }
2342}
2343
2344impl From<Error> for io::Error {
2345 fn from(err: Error) -> io::Error {
2346 io::Error::new(
2347 io::ErrorKind::Other,
2348 format!("{:?}: {}", err.error_type, err.description),
2349 )
2350 }
2351}
2352
2353impl From<std::num::TryFromIntError> for Error {
2354 fn from(_: std::num::TryFromIntError) -> Self {
2355 Self::new(ErrorKind::InternalError, "integer conversion error")
2356 }
2357}
2358
2359impl<T> From<std::sync::PoisonError<T>> for Error {
2360 fn from(_: std::sync::PoisonError<T>) -> Self {
2361 Self::new(ErrorKind::InternalError, "can not lock SspiHandle mutex")
2362 }
2363}
2364
2365impl From<picky::key::KeyError> for Error {
2366 fn from(err: picky::key::KeyError) -> Self {
2367 Self::new(ErrorKind::InternalError, format!("RSA key error: {:?}", err))
2368 }
2369}
2370
2371#[cfg(feature = "scard")]
2372impl From<winscard::Error> for Error {
2373 fn from(value: winscard::Error) -> Self {
2374 Self::new(
2375 ErrorKind::InternalError,
2376 format!("Error while using a smart card: {}", value),
2377 )
2378 }
2379}
2380
2381#[cfg(all(feature = "scard", not(target_arch = "wasm32")))]
2382impl From<cryptoki::error::Error> for Error {
2383 fn from(value: cryptoki::error::Error) -> Self {
2384 Self::new(
2385 ErrorKind::NoCredentials,
2386 format!("Error while using a smart card: {}", value),
2387 )
2388 }
2389}