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)]
55pub enum XmlSignatureProfile {
56 StrictRsaSha2,
61 #[default]
64 AllowProviderSupportedForCompatibility,
65}
66
67#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
69pub enum AuthnRequestSigningPolicy {
70 Sign,
72 #[default]
74 DoNotSignForCompatibility,
75}
76
77#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
79pub enum AuthnRequestValidationPolicy {
80 RequireSigned,
82 #[default]
84 AllowUnsignedForCompatibility,
85}
86
87#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
89pub enum LogoutSignaturePolicy {
90 #[default]
92 RequireSigned,
93 AllowUnsignedForCompatibility,
95}
96
97#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
99pub enum AudienceValidationPolicy {
100 #[default]
102 Validate,
103 SkipForCompatibility,
105}
106
107#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
109pub enum NameIdCreationPolicy {
110 AllowCreate,
112 #[default]
114 DoNotAllowCreate,
115}
116
117#[derive(Debug, Clone, PartialEq, Eq)]
119pub struct SpValidationPolicy {
120 pub assertions: AssertionSignaturePolicy,
122 pub responses: ResponseSignaturePolicy,
124 pub xml_signatures: XmlSignatureProfile,
126 pub authn_requests: AuthnRequestSigningPolicy,
128 pub audience: AudienceValidationPolicy,
130 pub name_id_creation: NameIdCreationPolicy,
132 pub logout: LogoutPolicy,
134}
135
136impl SpValidationPolicy {
137 pub fn strict() -> Self {
139 Self {
140 assertions: AssertionSignaturePolicy::RequireSigned,
141 responses: ResponseSignaturePolicy::RequireForEncryptedCbc,
142 xml_signatures: XmlSignatureProfile::AllowProviderSupportedForCompatibility,
143 authn_requests: AuthnRequestSigningPolicy::Sign,
144 audience: AudienceValidationPolicy::Validate,
145 name_id_creation: NameIdCreationPolicy::DoNotAllowCreate,
146 logout: LogoutPolicy::strict(),
147 }
148 }
149
150 pub fn compatibility() -> Self {
152 Self {
153 assertions: AssertionSignaturePolicy::AllowUnsignedForCompatibility,
154 responses: ResponseSignaturePolicy::AllowUnsignedEncryptedCbcForCompatibility,
155 xml_signatures: XmlSignatureProfile::AllowProviderSupportedForCompatibility,
156 authn_requests: AuthnRequestSigningPolicy::DoNotSignForCompatibility,
157 audience: AudienceValidationPolicy::SkipForCompatibility,
158 name_id_creation: NameIdCreationPolicy::DoNotAllowCreate,
159 logout: LogoutPolicy::compatibility(),
160 }
161 }
162}
163
164impl Default for SpValidationPolicy {
165 fn default() -> Self {
166 Self::compatibility()
167 }
168}
169
170#[derive(Debug, Clone, PartialEq, Eq)]
172pub struct IdpValidationPolicy {
173 pub authn_requests: AuthnRequestValidationPolicy,
175 pub logout: LogoutPolicy,
177}
178
179impl IdpValidationPolicy {
180 pub fn strict() -> Self {
182 Self {
183 authn_requests: AuthnRequestValidationPolicy::RequireSigned,
184 logout: LogoutPolicy::strict(),
185 }
186 }
187
188 pub fn compatibility() -> Self {
190 Self {
191 authn_requests: AuthnRequestValidationPolicy::AllowUnsignedForCompatibility,
192 logout: LogoutPolicy::compatibility(),
193 }
194 }
195}
196
197impl Default for IdpValidationPolicy {
198 fn default() -> Self {
199 Self::compatibility()
200 }
201}
202
203#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
205pub struct LogoutPolicy {
206 pub requests: LogoutSignaturePolicy,
208 pub responses: LogoutSignaturePolicy,
210}
211
212impl LogoutPolicy {
213 pub fn strict() -> Self {
215 Self {
216 requests: LogoutSignaturePolicy::RequireSigned,
217 responses: LogoutSignaturePolicy::RequireSigned,
218 }
219 }
220
221 pub fn compatibility() -> Self {
223 Self {
224 requests: LogoutSignaturePolicy::AllowUnsignedForCompatibility,
225 responses: LogoutSignaturePolicy::AllowUnsignedForCompatibility,
226 }
227 }
228}
229
230#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
232pub enum AssertionEncryptionPolicy {
233 #[default]
235 PlaintextAssertions,
236 EncryptAssertions,
238}
239
240#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
262pub struct XmlEncryptionPolicy {
263 pub assertions: AssertionEncryptionPolicy,
265 allow_insecure_software_rsa_key_transport_decryption: bool,
266}
267
268impl XmlEncryptionPolicy {
269 pub fn encrypt_assertions() -> Self {
271 Self {
272 assertions: AssertionEncryptionPolicy::EncryptAssertions,
273 ..Self::default()
274 }
275 }
276
277 pub fn allow_insecure_software_rsa_key_transport_decryption() -> Self {
280 Self {
281 allow_insecure_software_rsa_key_transport_decryption: true,
282 ..Self::default()
283 }
284 }
285
286 pub fn with_insecure_software_rsa_key_transport_decryption_allowed(mut self) -> Self {
288 self.allow_insecure_software_rsa_key_transport_decryption = true;
289 self
290 }
291
292 pub(super) fn allows_insecure_software_rsa_key_transport_decryption(self) -> bool {
293 self.allow_insecure_software_rsa_key_transport_decryption
294 }
295}
296
297#[derive(Debug, Clone, Copy, PartialEq, Eq)]
322pub struct XmlPolicy {
323 pub clock_drifts: (i64, i64),
325 pub redirect_inflate_max_bytes: usize,
328 pub limits: XmlLimits,
330 pub encryption: XmlEncryptionPolicy,
332}
333
334impl Default for XmlPolicy {
335 fn default() -> Self {
336 Self {
337 clock_drifts: (0, 0),
338 redirect_inflate_max_bytes: MAX_DEFLATE_RAW_DECODE_BYTES,
339 limits: XmlLimits::default(),
340 encryption: XmlEncryptionPolicy::default(),
341 }
342 }
343}
344
345#[derive(Debug, Clone, PartialEq, Eq)]
347pub struct AlgorithmPolicy {
348 pub signature: SignatureAlgorithm,
350 pub data_encryption: DataEncryptionAlgorithm,
352 pub key_encryption: KeyEncryptionAlgorithm,
354 pub message_signing_order: MessageSignatureOrder,
356 pub signed_reference_transforms: Vec<TransformAlgorithm>,
358}
359
360impl Default for AlgorithmPolicy {
361 fn default() -> Self {
362 Self {
363 signature: SignatureAlgorithm::default(),
364 data_encryption: DataEncryptionAlgorithm::default(),
365 key_encryption: KeyEncryptionAlgorithm::default(),
366 message_signing_order: MessageSignatureOrder::SignThenEncrypt,
367 signed_reference_transforms: vec![
368 TransformAlgorithm::EnvelopedSignature,
369 TransformAlgorithm::ExclusiveCanonicalization,
370 ],
371 }
372 }
373}
374
375#[derive(Debug, Clone)]
377pub struct TemplatePolicy {
378 pub relay_state: String,
380 pub tag_prefix_protocol: String,
382 pub tag_prefix_assertion: String,
384 pub tag_prefix_encrypted_assertion: String,
386 pub login_response_template: Option<LoginResponseTemplate>,
388 pub login_request_template: Option<String>,
390 pub logout_request_template: Option<String>,
396 pub logout_response_template: Option<String>,
405 pub signature_config: Option<SignatureConfig>,
407}
408
409impl Default for TemplatePolicy {
410 fn default() -> Self {
411 Self {
412 relay_state: String::new(),
413 tag_prefix_protocol: "samlp".to_string(),
414 tag_prefix_assertion: "saml".to_string(),
415 tag_prefix_encrypted_assertion: "saml".to_string(),
416 login_response_template: None,
417 login_request_template: None,
418 logout_request_template: None,
419 logout_response_template: None,
420 signature_config: None,
421 }
422 }
423}
424pub(super) fn authn_request_signing_enabled(policy: AuthnRequestSigningPolicy) -> bool {
425 matches!(policy, AuthnRequestSigningPolicy::Sign)
426}
427
428pub(super) fn authn_request_signature_required(policy: AuthnRequestValidationPolicy) -> bool {
429 matches!(policy, AuthnRequestValidationPolicy::RequireSigned)
430}
431
432pub(super) fn assertion_signature_required(policy: AssertionSignaturePolicy) -> bool {
433 matches!(policy, AssertionSignaturePolicy::RequireSigned)
434}
435
436pub(super) fn response_signature_required(policy: ResponseSignaturePolicy) -> bool {
437 matches!(policy, ResponseSignaturePolicy::RequireSigned)
438}
439
440pub(super) fn encrypted_cbc_response_signature_required(policy: ResponseSignaturePolicy) -> bool {
441 matches!(policy, ResponseSignaturePolicy::RequireForEncryptedCbc)
442}
443
444pub(super) fn logout_signature_required(policy: LogoutSignaturePolicy) -> Result<bool, SamlError> {
445 match policy {
446 LogoutSignaturePolicy::RequireSigned => Ok(true),
447 LogoutSignaturePolicy::AllowUnsignedForCompatibility => Ok(false),
448 }
449}
450pub(super) fn name_id_creation_allowed(policy: NameIdCreationPolicy) -> bool {
451 matches!(policy, NameIdCreationPolicy::AllowCreate)
452}
453
454pub(super) fn audience_validation_enabled(policy: AudienceValidationPolicy) -> bool {
455 matches!(policy, AudienceValidationPolicy::Validate)
456}