1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.opensaml.saml1.binding.encoding;
18
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.List;
22
23 import org.opensaml.Configuration;
24 import org.opensaml.common.SAMLObject;
25 import org.opensaml.common.SignableSAMLObject;
26 import org.opensaml.common.binding.SAMLMessageContext;
27 import org.opensaml.common.binding.encoding.SAMLMessageEncoder;
28 import org.opensaml.saml2.core.Response;
29 import org.opensaml.saml2.metadata.Endpoint;
30 import org.opensaml.util.URLBuilder;
31 import org.opensaml.ws.message.encoder.BaseMessageEncoder;
32 import org.opensaml.ws.message.encoder.MessageEncodingException;
33 import org.opensaml.xml.XMLObjectBuilder;
34 import org.opensaml.xml.io.Marshaller;
35 import org.opensaml.xml.io.MarshallingException;
36 import org.opensaml.xml.security.SecurityException;
37 import org.opensaml.xml.security.SecurityHelper;
38 import org.opensaml.xml.security.credential.Credential;
39 import org.opensaml.xml.signature.Signature;
40 import org.opensaml.xml.signature.SignatureException;
41 import org.opensaml.xml.signature.Signer;
42 import org.opensaml.xml.util.DatatypeHelper;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45
46
47
48
49 public abstract class BaseSAML1MessageEncoder extends BaseMessageEncoder implements SAMLMessageEncoder{
50
51
52 private final Logger log = LoggerFactory.getLogger(BaseSAML1MessageEncoder.class);
53
54
55 private List<String> allowedURLSchemes;
56
57 public BaseSAML1MessageEncoder() {
58 super();
59 setAllowedURLSchemes(new String[] { "http", "https" });
60 }
61
62
63
64
65
66
67 public List<String> getAllowedURLSchemes() {
68 return allowedURLSchemes;
69 }
70
71
72
73
74
75
76
77 public void setAllowedURLSchemes(String[] schemes) {
78 if (schemes == null || schemes.length == 0) {
79 allowedURLSchemes = Collections.emptyList();
80 } else {
81 List<String> temp = new ArrayList<String>();
82 for (String scheme : schemes) {
83 temp.add(scheme);
84 }
85 allowedURLSchemes = Collections.unmodifiableList(temp);
86 }
87 }
88
89
90
91
92
93
94
95
96
97
98
99
100 protected URLBuilder getEndpointURL(SAMLMessageContext messageContext) throws MessageEncodingException {
101 Endpoint endpoint = messageContext.getPeerEntityEndpoint();
102 if (endpoint == null) {
103 throw new MessageEncodingException("Endpoint for relying party was null.");
104 }
105
106 URLBuilder urlBuilder;
107 if (messageContext.getOutboundMessage() instanceof Response
108 && !DatatypeHelper.isEmpty(endpoint.getResponseLocation())) {
109 urlBuilder = new URLBuilder(endpoint.getResponseLocation());
110 } else {
111 if (DatatypeHelper.isEmpty(endpoint.getLocation())) {
112 throw new MessageEncodingException("Relying party endpoint location was null or empty.");
113 }
114 urlBuilder = new URLBuilder(endpoint.getLocation());
115 }
116
117 if(!getAllowedURLSchemes().contains(urlBuilder.getScheme())){
118 throw new MessageEncodingException("Relying party endpoint used the untrusted URL scheme " + urlBuilder.getScheme());
119 }
120 return urlBuilder;
121 }
122
123
124
125
126
127
128
129
130 @SuppressWarnings("unchecked")
131 protected void signMessage(SAMLMessageContext messageContext) throws MessageEncodingException {
132 SAMLObject outboundMessage = messageContext.getOutboundSAMLMessage();
133 if (outboundMessage instanceof SignableSAMLObject
134 && messageContext.getOuboundSAMLMessageSigningCredential() != null) {
135 log.debug("Signing outbound SAML message.");
136 SignableSAMLObject signableMessage = (SignableSAMLObject) outboundMessage;
137 Credential signingCredential = messageContext.getOuboundSAMLMessageSigningCredential();
138
139 XMLObjectBuilder<Signature> signatureBuilder = Configuration.getBuilderFactory().getBuilder(
140 Signature.DEFAULT_ELEMENT_NAME);
141 Signature signature = signatureBuilder.buildObject(Signature.DEFAULT_ELEMENT_NAME);
142 signature.setSigningCredential(signingCredential);
143
144 try {
145
146
147 SecurityHelper.prepareSignatureParams(signature, signingCredential, null, null);
148 } catch (SecurityException e) {
149 throw new MessageEncodingException("Error preparing signature for signing", e);
150 }
151
152 signableMessage.setSignature(signature);
153
154 try {
155 Marshaller marshaller = Configuration.getMarshallerFactory().getMarshaller(signableMessage);
156 marshaller.marshall(signableMessage);
157 Signer.signObject(signature);
158 } catch (MarshallingException e) {
159 log.error("Unable to marshall protocol message in preparation for signing", e);
160 throw new MessageEncodingException("Unable to marshall protocol message in preparation for signing", e);
161 } catch (SignatureException e) {
162 log.error("Unable to sign protocol message", e);
163 throw new MessageEncodingException("Unable to sign protocol message", e);
164 }
165 }
166 }
167 }