use crate::binding::MAX_DEFLATE_RAW_DECODE_BYTES;
use crate::constants::MessageSignatureOrder;
use crate::entity::SignatureConfig;
use crate::error::SamlError;
use crate::template::LoginResponseTemplate;
use crate::xml::XmlLimits;
use super::algorithms::{
DataEncryptionAlgorithm, KeyEncryptionAlgorithm, SignatureAlgorithm, TransformAlgorithm,
};
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum AssertionSignaturePolicy {
RequireSigned,
#[default]
AllowUnsignedForCompatibility,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum MessageSignaturePolicy {
RequireSigned,
#[default]
AllowUnsignedForCompatibility,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum AuthnRequestSigningPolicy {
Sign,
#[default]
DoNotSignForCompatibility,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum AuthnRequestValidationPolicy {
RequireSigned,
#[default]
AllowUnsignedForCompatibility,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum LogoutSignaturePolicy {
#[default]
RequireSigned,
AllowUnsignedForCompatibility,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum AudienceValidationPolicy {
#[default]
Validate,
SkipForCompatibility,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum NameIdCreationPolicy {
AllowCreate,
#[default]
DoNotAllowCreate,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SpValidationPolicy {
pub assertions: AssertionSignaturePolicy,
pub messages: MessageSignaturePolicy,
pub authn_requests: AuthnRequestSigningPolicy,
pub audience: AudienceValidationPolicy,
pub name_id_creation: NameIdCreationPolicy,
pub logout: LogoutPolicy,
}
impl SpValidationPolicy {
pub fn strict() -> Self {
Self {
assertions: AssertionSignaturePolicy::RequireSigned,
messages: MessageSignaturePolicy::RequireSigned,
authn_requests: AuthnRequestSigningPolicy::Sign,
audience: AudienceValidationPolicy::Validate,
name_id_creation: NameIdCreationPolicy::DoNotAllowCreate,
logout: LogoutPolicy::strict(),
}
}
pub fn compatibility() -> Self {
Self {
assertions: AssertionSignaturePolicy::AllowUnsignedForCompatibility,
messages: MessageSignaturePolicy::AllowUnsignedForCompatibility,
authn_requests: AuthnRequestSigningPolicy::DoNotSignForCompatibility,
audience: AudienceValidationPolicy::SkipForCompatibility,
name_id_creation: NameIdCreationPolicy::DoNotAllowCreate,
logout: LogoutPolicy::compatibility(),
}
}
}
impl Default for SpValidationPolicy {
fn default() -> Self {
Self::compatibility()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct IdpValidationPolicy {
pub authn_requests: AuthnRequestValidationPolicy,
pub logout: LogoutPolicy,
}
impl IdpValidationPolicy {
pub fn strict() -> Self {
Self {
authn_requests: AuthnRequestValidationPolicy::RequireSigned,
logout: LogoutPolicy::strict(),
}
}
pub fn compatibility() -> Self {
Self {
authn_requests: AuthnRequestValidationPolicy::AllowUnsignedForCompatibility,
logout: LogoutPolicy::compatibility(),
}
}
}
impl Default for IdpValidationPolicy {
fn default() -> Self {
Self::compatibility()
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct LogoutPolicy {
pub requests: LogoutSignaturePolicy,
pub responses: LogoutSignaturePolicy,
}
impl LogoutPolicy {
pub fn strict() -> Self {
Self {
requests: LogoutSignaturePolicy::RequireSigned,
responses: LogoutSignaturePolicy::RequireSigned,
}
}
pub fn compatibility() -> Self {
Self {
requests: LogoutSignaturePolicy::AllowUnsignedForCompatibility,
responses: LogoutSignaturePolicy::AllowUnsignedForCompatibility,
}
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub enum AssertionEncryptionPolicy {
#[default]
PlaintextAssertions,
EncryptAssertions,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct XmlEncryptionPolicy {
pub assertions: AssertionEncryptionPolicy,
allow_insecure_software_rsa_key_transport_decryption: bool,
}
impl XmlEncryptionPolicy {
pub fn encrypt_assertions() -> Self {
Self {
assertions: AssertionEncryptionPolicy::EncryptAssertions,
..Self::default()
}
}
pub fn allow_insecure_software_rsa_key_transport_decryption() -> Self {
Self {
allow_insecure_software_rsa_key_transport_decryption: true,
..Self::default()
}
}
pub fn with_insecure_software_rsa_key_transport_decryption_allowed(mut self) -> Self {
self.allow_insecure_software_rsa_key_transport_decryption = true;
self
}
pub(super) fn allows_insecure_software_rsa_key_transport_decryption(self) -> bool {
self.allow_insecure_software_rsa_key_transport_decryption
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct XmlPolicy {
pub clock_drifts: (i64, i64),
pub redirect_inflate_max_bytes: usize,
pub limits: XmlLimits,
pub encryption: XmlEncryptionPolicy,
}
impl Default for XmlPolicy {
fn default() -> Self {
Self {
clock_drifts: (0, 0),
redirect_inflate_max_bytes: MAX_DEFLATE_RAW_DECODE_BYTES,
limits: XmlLimits::default(),
encryption: XmlEncryptionPolicy::default(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AlgorithmPolicy {
pub signature: SignatureAlgorithm,
pub data_encryption: DataEncryptionAlgorithm,
pub key_encryption: KeyEncryptionAlgorithm,
pub message_signing_order: MessageSignatureOrder,
pub signed_reference_transforms: Vec<TransformAlgorithm>,
}
impl Default for AlgorithmPolicy {
fn default() -> Self {
Self {
signature: SignatureAlgorithm::default(),
data_encryption: DataEncryptionAlgorithm::default(),
key_encryption: KeyEncryptionAlgorithm::default(),
message_signing_order: MessageSignatureOrder::SignThenEncrypt,
signed_reference_transforms: vec![
TransformAlgorithm::EnvelopedSignature,
TransformAlgorithm::ExclusiveCanonicalization,
],
}
}
}
#[derive(Debug, Clone)]
pub struct TemplatePolicy {
pub relay_state: String,
pub tag_prefix_protocol: String,
pub tag_prefix_assertion: String,
pub tag_prefix_encrypted_assertion: String,
pub login_response_template: Option<LoginResponseTemplate>,
pub login_request_template: Option<String>,
pub logout_request_template: Option<String>,
pub logout_response_template: Option<String>,
pub signature_config: Option<SignatureConfig>,
}
impl Default for TemplatePolicy {
fn default() -> Self {
Self {
relay_state: String::new(),
tag_prefix_protocol: "samlp".to_string(),
tag_prefix_assertion: "saml".to_string(),
tag_prefix_encrypted_assertion: "saml".to_string(),
login_response_template: None,
login_request_template: None,
logout_request_template: None,
logout_response_template: None,
signature_config: None,
}
}
}
pub(super) fn authn_request_signing_enabled(policy: AuthnRequestSigningPolicy) -> bool {
matches!(policy, AuthnRequestSigningPolicy::Sign)
}
pub(super) fn authn_request_signature_required(policy: AuthnRequestValidationPolicy) -> bool {
matches!(policy, AuthnRequestValidationPolicy::RequireSigned)
}
pub(super) fn assertion_signature_required(policy: AssertionSignaturePolicy) -> bool {
matches!(policy, AssertionSignaturePolicy::RequireSigned)
}
pub(super) fn message_signature_required(policy: MessageSignaturePolicy) -> bool {
matches!(policy, MessageSignaturePolicy::RequireSigned)
}
pub(super) fn logout_signature_required(policy: LogoutSignaturePolicy) -> Result<bool, SamlError> {
match policy {
LogoutSignaturePolicy::RequireSigned => Ok(true),
LogoutSignaturePolicy::AllowUnsignedForCompatibility => Ok(false),
}
}
pub(super) fn name_id_creation_allowed(policy: NameIdCreationPolicy) -> bool {
matches!(policy, NameIdCreationPolicy::AllowCreate)
}
pub(super) fn audience_validation_enabled(policy: AudienceValidationPolicy) -> bool {
matches!(policy, AudienceValidationPolicy::Validate)
}