1use crate::binding::MAX_DEFLATE_RAW_DECODE_BYTES;
2use crate::constants::MessageSignatureOrder;
3use crate::entity::SignatureConfig;
4use crate::error::SamlError;
5use crate::template::LoginResponseTemplate;
6use crate::xml::XmlLimits;
7
8use super::algorithms::{
9 DataEncryptionAlgorithm, KeyEncryptionAlgorithm, SignatureAlgorithm, TransformAlgorithm,
10};
11
12#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
14pub enum AssertionSignaturePolicy {
15 RequireSigned,
17 #[default]
19 AllowUnsignedForCompatibility,
20}
21
22#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
31pub enum ResponseSignaturePolicy {
32 #[default]
38 AllowUnsignedEncryptedCbcForCompatibility,
39 RequireForEncryptedCbc,
42 RequireSigned,
45}
46
47#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
49pub enum AuthnRequestSigningPolicy {
50 Sign,
52 #[default]
54 DoNotSignForCompatibility,
55}
56
57#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
59pub enum AuthnRequestValidationPolicy {
60 RequireSigned,
62 #[default]
64 AllowUnsignedForCompatibility,
65}
66
67#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
69pub enum LogoutSignaturePolicy {
70 #[default]
72 RequireSigned,
73 AllowUnsignedForCompatibility,
75}
76
77#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
79pub enum AudienceValidationPolicy {
80 #[default]
82 Validate,
83 SkipForCompatibility,
85}
86
87#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
89pub enum NameIdCreationPolicy {
90 AllowCreate,
92 #[default]
94 DoNotAllowCreate,
95}
96
97#[derive(Debug, Clone, PartialEq, Eq)]
99pub struct SpValidationPolicy {
100 pub assertions: AssertionSignaturePolicy,
102 pub responses: ResponseSignaturePolicy,
104 pub authn_requests: AuthnRequestSigningPolicy,
106 pub audience: AudienceValidationPolicy,
108 pub name_id_creation: NameIdCreationPolicy,
110 pub logout: LogoutPolicy,
112}
113
114impl SpValidationPolicy {
115 pub fn strict() -> Self {
117 Self {
118 assertions: AssertionSignaturePolicy::RequireSigned,
119 responses: ResponseSignaturePolicy::RequireForEncryptedCbc,
120 authn_requests: AuthnRequestSigningPolicy::Sign,
121 audience: AudienceValidationPolicy::Validate,
122 name_id_creation: NameIdCreationPolicy::DoNotAllowCreate,
123 logout: LogoutPolicy::strict(),
124 }
125 }
126
127 pub fn compatibility() -> Self {
129 Self {
130 assertions: AssertionSignaturePolicy::AllowUnsignedForCompatibility,
131 responses: ResponseSignaturePolicy::AllowUnsignedEncryptedCbcForCompatibility,
132 authn_requests: AuthnRequestSigningPolicy::DoNotSignForCompatibility,
133 audience: AudienceValidationPolicy::SkipForCompatibility,
134 name_id_creation: NameIdCreationPolicy::DoNotAllowCreate,
135 logout: LogoutPolicy::compatibility(),
136 }
137 }
138}
139
140impl Default for SpValidationPolicy {
141 fn default() -> Self {
142 Self::compatibility()
143 }
144}
145
146#[derive(Debug, Clone, PartialEq, Eq)]
148pub struct IdpValidationPolicy {
149 pub authn_requests: AuthnRequestValidationPolicy,
151 pub logout: LogoutPolicy,
153}
154
155impl IdpValidationPolicy {
156 pub fn strict() -> Self {
158 Self {
159 authn_requests: AuthnRequestValidationPolicy::RequireSigned,
160 logout: LogoutPolicy::strict(),
161 }
162 }
163
164 pub fn compatibility() -> Self {
166 Self {
167 authn_requests: AuthnRequestValidationPolicy::AllowUnsignedForCompatibility,
168 logout: LogoutPolicy::compatibility(),
169 }
170 }
171}
172
173impl Default for IdpValidationPolicy {
174 fn default() -> Self {
175 Self::compatibility()
176 }
177}
178
179#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
181pub struct LogoutPolicy {
182 pub requests: LogoutSignaturePolicy,
184 pub responses: LogoutSignaturePolicy,
186}
187
188impl LogoutPolicy {
189 pub fn strict() -> Self {
191 Self {
192 requests: LogoutSignaturePolicy::RequireSigned,
193 responses: LogoutSignaturePolicy::RequireSigned,
194 }
195 }
196
197 pub fn compatibility() -> Self {
199 Self {
200 requests: LogoutSignaturePolicy::AllowUnsignedForCompatibility,
201 responses: LogoutSignaturePolicy::AllowUnsignedForCompatibility,
202 }
203 }
204}
205
206#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
208pub enum AssertionEncryptionPolicy {
209 #[default]
211 PlaintextAssertions,
212 EncryptAssertions,
214}
215
216#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
238pub struct XmlEncryptionPolicy {
239 pub assertions: AssertionEncryptionPolicy,
241 allow_insecure_software_rsa_key_transport_decryption: bool,
242}
243
244impl XmlEncryptionPolicy {
245 pub fn encrypt_assertions() -> Self {
247 Self {
248 assertions: AssertionEncryptionPolicy::EncryptAssertions,
249 ..Self::default()
250 }
251 }
252
253 pub fn allow_insecure_software_rsa_key_transport_decryption() -> Self {
256 Self {
257 allow_insecure_software_rsa_key_transport_decryption: true,
258 ..Self::default()
259 }
260 }
261
262 pub fn with_insecure_software_rsa_key_transport_decryption_allowed(mut self) -> Self {
264 self.allow_insecure_software_rsa_key_transport_decryption = true;
265 self
266 }
267
268 pub(super) fn allows_insecure_software_rsa_key_transport_decryption(self) -> bool {
269 self.allow_insecure_software_rsa_key_transport_decryption
270 }
271}
272
273#[derive(Debug, Clone, Copy, PartialEq, Eq)]
298pub struct XmlPolicy {
299 pub clock_drifts: (i64, i64),
301 pub redirect_inflate_max_bytes: usize,
304 pub limits: XmlLimits,
306 pub encryption: XmlEncryptionPolicy,
308}
309
310impl Default for XmlPolicy {
311 fn default() -> Self {
312 Self {
313 clock_drifts: (0, 0),
314 redirect_inflate_max_bytes: MAX_DEFLATE_RAW_DECODE_BYTES,
315 limits: XmlLimits::default(),
316 encryption: XmlEncryptionPolicy::default(),
317 }
318 }
319}
320
321#[derive(Debug, Clone, PartialEq, Eq)]
323pub struct AlgorithmPolicy {
324 pub signature: SignatureAlgorithm,
326 pub data_encryption: DataEncryptionAlgorithm,
328 pub key_encryption: KeyEncryptionAlgorithm,
330 pub message_signing_order: MessageSignatureOrder,
332 pub signed_reference_transforms: Vec<TransformAlgorithm>,
334}
335
336impl Default for AlgorithmPolicy {
337 fn default() -> Self {
338 Self {
339 signature: SignatureAlgorithm::default(),
340 data_encryption: DataEncryptionAlgorithm::default(),
341 key_encryption: KeyEncryptionAlgorithm::default(),
342 message_signing_order: MessageSignatureOrder::SignThenEncrypt,
343 signed_reference_transforms: vec![
344 TransformAlgorithm::EnvelopedSignature,
345 TransformAlgorithm::ExclusiveCanonicalization,
346 ],
347 }
348 }
349}
350
351#[derive(Debug, Clone)]
353pub struct TemplatePolicy {
354 pub relay_state: String,
356 pub tag_prefix_protocol: String,
358 pub tag_prefix_assertion: String,
360 pub tag_prefix_encrypted_assertion: String,
362 pub login_response_template: Option<LoginResponseTemplate>,
364 pub login_request_template: Option<String>,
366 pub logout_request_template: Option<String>,
372 pub logout_response_template: Option<String>,
381 pub signature_config: Option<SignatureConfig>,
383}
384
385impl Default for TemplatePolicy {
386 fn default() -> Self {
387 Self {
388 relay_state: String::new(),
389 tag_prefix_protocol: "samlp".to_string(),
390 tag_prefix_assertion: "saml".to_string(),
391 tag_prefix_encrypted_assertion: "saml".to_string(),
392 login_response_template: None,
393 login_request_template: None,
394 logout_request_template: None,
395 logout_response_template: None,
396 signature_config: None,
397 }
398 }
399}
400pub(super) fn authn_request_signing_enabled(policy: AuthnRequestSigningPolicy) -> bool {
401 matches!(policy, AuthnRequestSigningPolicy::Sign)
402}
403
404pub(super) fn authn_request_signature_required(policy: AuthnRequestValidationPolicy) -> bool {
405 matches!(policy, AuthnRequestValidationPolicy::RequireSigned)
406}
407
408pub(super) fn assertion_signature_required(policy: AssertionSignaturePolicy) -> bool {
409 matches!(policy, AssertionSignaturePolicy::RequireSigned)
410}
411
412pub(super) fn response_signature_required(policy: ResponseSignaturePolicy) -> bool {
413 matches!(policy, ResponseSignaturePolicy::RequireSigned)
414}
415
416pub(super) fn encrypted_cbc_response_signature_required(policy: ResponseSignaturePolicy) -> bool {
417 matches!(policy, ResponseSignaturePolicy::RequireForEncryptedCbc)
418}
419
420pub(super) fn logout_signature_required(policy: LogoutSignaturePolicy) -> Result<bool, SamlError> {
421 match policy {
422 LogoutSignaturePolicy::RequireSigned => Ok(true),
423 LogoutSignaturePolicy::AllowUnsignedForCompatibility => Ok(false),
424 }
425}
426pub(super) fn name_id_creation_allowed(policy: NameIdCreationPolicy) -> bool {
427 matches!(policy, NameIdCreationPolicy::AllowCreate)
428}
429
430pub(super) fn audience_validation_enabled(policy: AudienceValidationPolicy) -> bool {
431 matches!(policy, AudienceValidationPolicy::Validate)
432}