1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.opensaml.saml2.binding.security;
18
19 import java.io.ByteArrayInputStream;
20 import java.io.UnsupportedEncodingException;
21 import java.util.ArrayList;
22 import java.util.List;
23
24 import javax.servlet.http.HttpServletRequest;
25
26 import org.opensaml.common.binding.SAMLMessageContext;
27 import org.opensaml.common.binding.security.BaseSAMLSimpleSignatureSecurityPolicyRule;
28 import org.opensaml.ws.security.SecurityPolicyException;
29 import org.opensaml.xml.Configuration;
30 import org.opensaml.xml.io.Unmarshaller;
31 import org.opensaml.xml.io.UnmarshallingException;
32 import org.opensaml.xml.parse.ParserPool;
33 import org.opensaml.xml.parse.XMLParserException;
34 import org.opensaml.xml.security.CriteriaSet;
35 import org.opensaml.xml.security.SecurityException;
36 import org.opensaml.xml.security.credential.Credential;
37 import org.opensaml.xml.security.keyinfo.KeyInfoCredentialResolver;
38 import org.opensaml.xml.security.keyinfo.KeyInfoCriteria;
39 import org.opensaml.xml.signature.KeyInfo;
40 import org.opensaml.xml.signature.SignatureTrustEngine;
41 import org.opensaml.xml.util.Base64;
42 import org.opensaml.xml.util.DatatypeHelper;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45 import org.w3c.dom.Document;
46
47
48
49
50 public class SAML2HTTPPostSimpleSignRule extends BaseSAMLSimpleSignatureSecurityPolicyRule {
51
52
53 private Logger log = LoggerFactory.getLogger(SAML2HTTPPostSimpleSignRule.class);
54
55
56 private ParserPool parser;
57
58
59 private KeyInfoCredentialResolver keyInfoResolver;
60
61
62
63
64
65
66
67
68
69 public SAML2HTTPPostSimpleSignRule(SignatureTrustEngine engine, ParserPool parserPool,
70 KeyInfoCredentialResolver keyInfoCredResolver) {
71 super(engine);
72 parser = parserPool;
73 keyInfoResolver = keyInfoCredResolver;
74 }
75
76
77 protected boolean ruleHandles(HttpServletRequest request, SAMLMessageContext samlMsgCtx) {
78 return "POST".equals(request.getMethod());
79 }
80
81
82 protected byte[] getSignedContent(HttpServletRequest request) throws SecurityPolicyException {
83 StringBuilder builder = new StringBuilder();
84 String samlMsg;
85 try {
86 if (request.getParameter("SAMLRequest") != null) {
87 samlMsg = new String(Base64.decode(request.getParameter("SAMLRequest")), "UTF-8");
88 builder.append("SAMLRequest=" + samlMsg);
89 } else if (request.getParameter("SAMLResponse") != null) {
90 samlMsg = new String(Base64.decode(request.getParameter("SAMLResponse")), "UTF-8");
91 builder.append("SAMLResponse=" + samlMsg);
92 } else {
93 log.warn("Could not extract either a SAMLRequest or a SAMLResponse from the form control data");
94 throw new SecurityPolicyException("Extract of SAMLRequest or SAMLResponse from form control data");
95 }
96 } catch (UnsupportedEncodingException e) {
97
98 }
99
100 if (request.getParameter("RelayState") != null) {
101 builder.append("&RelayState=" + request.getParameter("RelayState"));
102 }
103
104 builder.append("&SigAlg=" + request.getParameter("SigAlg"));
105
106 String constructed = builder.toString();
107 if (DatatypeHelper.isEmpty(constructed)) {
108 log.warn("Could not construct signed content string from form control data");
109 return null;
110 }
111 log.debug("Constructed signed content string for HTTP-Post-SimpleSign {}", constructed);
112
113 try {
114 return constructed.getBytes("UTF-8");
115 } catch (UnsupportedEncodingException e) {
116
117 }
118 return null;
119 }
120
121
122 protected List<Credential> getRequestCredentials(HttpServletRequest request, SAMLMessageContext samlContext)
123 throws SecurityPolicyException {
124
125 String kiBase64 = request.getParameter("KeyInfo");
126 if (DatatypeHelper.isEmpty(kiBase64)) {
127 log.debug("Form control data did not contain a KeyInfo");
128 return null;
129 } else {
130 log.debug("Found a KeyInfo in form control data, extracting validation credentials");
131 }
132
133 Unmarshaller unmarshaller = Configuration.getUnmarshallerFactory()
134 .getUnmarshaller(KeyInfo.DEFAULT_ELEMENT_NAME);
135 if (unmarshaller == null) {
136 throw new SecurityPolicyException("Could not obtain a KeyInfo unmarshaller");
137 }
138
139 ByteArrayInputStream is = new ByteArrayInputStream(Base64.decode(kiBase64));
140 KeyInfo keyInfo = null;
141 try {
142 Document doc = parser.parse(is);
143 keyInfo = (KeyInfo) unmarshaller.unmarshall(doc.getDocumentElement());
144 } catch (XMLParserException e) {
145 log.warn("Error parsing KeyInfo data", e);
146 throw new SecurityPolicyException("Error parsing KeyInfo data", e);
147 } catch (UnmarshallingException e) {
148 log.warn("Error unmarshalling KeyInfo data", e);
149 throw new SecurityPolicyException("Error unmarshalling KeyInfo data", e);
150 }
151
152 if (keyInfo == null) {
153 log.warn("Could not successfully extract KeyInfo object from the form control data");
154 return null;
155 }
156
157 List<Credential> credentials = new ArrayList<Credential>();
158 CriteriaSet criteriaSet = new CriteriaSet(new KeyInfoCriteria(keyInfo));
159 try {
160 for (Credential cred : keyInfoResolver.resolve(criteriaSet)) {
161 credentials.add(cred);
162 }
163 } catch (SecurityException e) {
164 log.warn("Error resolving credentials from KeyInfo", e);
165 throw new SecurityPolicyException("Error resolving credentials from KeyInfo", e);
166 }
167
168 return credentials;
169 }
170
171 }