1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.opensaml.common.binding.security;
18
19 import org.opensaml.common.SAMLObject;
20 import org.opensaml.common.SignableSAMLObject;
21 import org.opensaml.common.binding.SAMLMessageContext;
22 import org.opensaml.security.SAMLSignatureProfileValidator;
23 import org.opensaml.ws.message.MessageContext;
24 import org.opensaml.ws.security.SecurityPolicyException;
25 import org.opensaml.xml.security.trust.TrustEngine;
26 import org.opensaml.xml.signature.Signature;
27 import org.opensaml.xml.validation.ValidationException;
28 import org.opensaml.xml.validation.Validator;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 public class SAMLProtocolMessageXMLSignatureSecurityPolicyRule extends BaseSAMLXMLSignatureSecurityPolicyRule {
51
52
53 private final Logger log = LoggerFactory.getLogger(SAMLProtocolMessageXMLSignatureSecurityPolicyRule.class);
54
55
56 private Validator<Signature> sigValidator;
57
58
59
60
61
62
63
64
65 public SAMLProtocolMessageXMLSignatureSecurityPolicyRule(TrustEngine<Signature> engine) {
66 super(engine);
67 sigValidator = new SAMLSignatureProfileValidator();
68 }
69
70
71
72
73
74
75
76
77 public SAMLProtocolMessageXMLSignatureSecurityPolicyRule(TrustEngine<Signature> engine,
78 Validator<Signature> signatureValidator) {
79 super(engine);
80 sigValidator = signatureValidator;
81 }
82
83
84 public void evaluate(MessageContext messageContext) throws SecurityPolicyException {
85 if (!(messageContext instanceof SAMLMessageContext)) {
86 log.debug("Invalid message context type, this policy rule only supports SAMLMessageContext");
87 return;
88 }
89
90 SAMLMessageContext samlMsgCtx = (SAMLMessageContext) messageContext;
91
92 SAMLObject samlMsg = samlMsgCtx.getInboundSAMLMessage();
93 if (!(samlMsg instanceof SignableSAMLObject)) {
94 log.debug("Extracted SAML message was not a SignableSAMLObject, can not process signature");
95 return;
96 }
97 SignableSAMLObject signableObject = (SignableSAMLObject) samlMsg;
98 if (!signableObject.isSigned()) {
99 log.info("SAML protocol message was not signed, skipping XML signature processing");
100 return;
101 }
102 Signature signature = signableObject.getSignature();
103
104 performPreValidation(signature);
105
106 doEvaluate(signature, signableObject, samlMsgCtx);
107 }
108
109
110
111
112
113
114
115
116
117
118 protected void doEvaluate(Signature signature, SignableSAMLObject signableObject, SAMLMessageContext samlMsgCtx)
119 throws SecurityPolicyException {
120
121 String contextIssuer = samlMsgCtx.getInboundMessageIssuer();
122 if (contextIssuer != null) {
123 String msgType = signableObject.getElementQName().toString();
124 log.debug("Attempting to verify signature on signed SAML protocol message using context issuer message type: {}",
125 msgType);
126
127 if (evaluate(signature, contextIssuer, samlMsgCtx)) {
128 log.info("Validation of protocol message signature succeeded, message type: {}", msgType);
129 if (!samlMsgCtx.isInboundSAMLMessageAuthenticated()) {
130 log.info("Authentication via protocol message signature succeeded for context issuer entity ID {}",
131 contextIssuer);
132 samlMsgCtx.setInboundSAMLMessageAuthenticated(true);
133 }
134 } else {
135 log.warn("Validation of protocol message signature failed for context issuer '" + contextIssuer
136 + "', message type: " + msgType);
137 throw new SecurityPolicyException("Validation of protocol message signature failed");
138 }
139 } else {
140 log.warn("Context issuer unavailable, can not attempt SAML protocol message signature validation");
141 throw new SecurityPolicyException("Context issuer unavailable, can not validate signature");
142 }
143 }
144
145
146
147
148
149
150 protected Validator<Signature> getSignaturePrevalidator() {
151 return sigValidator;
152 }
153
154
155
156
157
158
159
160 protected void performPreValidation(Signature signature) throws SecurityPolicyException {
161 if (getSignaturePrevalidator() != null) {
162 try {
163 getSignaturePrevalidator().validate(signature);
164 } catch (ValidationException e) {
165 log.warn("Protocol message signature failed signature pre-validation", e);
166 throw new SecurityPolicyException("Protocol message signature failed signature pre-validation", e);
167 }
168 }
169 }
170 }