alibi_plugins/sso/
encryption_algorithms.rs1use super::SsoDeprecatedAlgorithmBehavior;
3#[derive(Clone, Debug, Default)]
4pub struct SsoSamlEncryptionPolicy {
5 pub on_deprecated: SsoDeprecatedAlgorithmBehavior,
6 pub allowed_key_encryption_algorithms: Option<Vec<String>>,
7 pub allowed_data_encryption_algorithms: Option<Vec<String>>,
8}
9
10use super::saml_crypto::Failure;
11use bergshamra::xml::{Document, NodeId};
12const XMLENC: &str = "http://www.w3.org/2001/04/xmlenc#";
13fn algorithm(doc: &Document<'_>, root: NodeId, parent: &str) -> Option<String> {
14 let parent = doc.descendants(root).into_iter().find(|node| {
15 doc.element(*node)
16 .is_some_and(|element| element.name.matches(Some(XMLENC), parent))
17 })?;
18 let method = doc.children(parent).into_iter().find(|node| {
19 doc.element(*node)
20 .is_some_and(|element| element.name.matches(Some(XMLENC), "EncryptionMethod"))
21 })?;
22 doc.get_attribute(method, "Algorithm")
23 .filter(|value| !value.is_empty())
24 .map(str::to_owned)
25}
26pub(super) fn validate(xml: &str, policy: &SsoSamlEncryptionPolicy) -> Result<(), Failure> {
27 let Ok(doc) = bergshamra::xml::uppsala::parse(xml) else {
28 return Ok(());
29 };
30 let Some(root) = doc.document_element() else {
31 return Ok(());
32 };
33 for (value, label, allowed, deprecated, recommendation) in [
34 (
35 algorithm(&doc, root, "EncryptedKey"),
36 "key",
37 &policy.allowed_key_encryption_algorithms,
38 "http://www.w3.org/2001/04/xmlenc#rsa-1_5",
39 "RSA-OAEP",
40 ),
41 (
42 algorithm(&doc, root, "EncryptedData"),
43 "data",
44 &policy.allowed_data_encryption_algorithms,
45 "http://www.w3.org/2001/04/xmlenc#tripledes-cbc",
46 "AES-GCM",
47 ),
48 ] {
49 let Some(value) = value else { continue };
50 if let Some(allowed) = allowed {
51 if !allowed.contains(&value) {
52 return Err(Failure {
53 code: "saml_algorithm_not_allowed",
54 message: format!(
55 "SAML {label} encryption algorithm not in allow-list: {value}"
56 ),
57 });
58 }
59 } else if value == deprecated {
60 let message = format!(
61 "SAML response uses deprecated {label} encryption algorithm: {value}. Please configure your IdP to use {recommendation}."
62 );
63 match policy.on_deprecated {
64 SsoDeprecatedAlgorithmBehavior::Reject => {
65 return Err(Failure {
66 code: "saml_deprecated_algorithm",
67 message,
68 });
69 }
70 SsoDeprecatedAlgorithmBehavior::Warn => tracing::warn!("{message}"),
71 SsoDeprecatedAlgorithmBehavior::Allow => {}
72 }
73 }
74 }
75 Ok(())
76}