1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.wss4j.stax.impl.securityToken;
20
21 import java.io.IOException;
22 import java.security.Key;
23 import java.security.Principal;
24 import java.security.PrivateKey;
25 import java.security.PublicKey;
26 import java.security.cert.X509Certificate;
27 import java.util.Collection;
28 import java.util.List;
29 import java.util.regex.Pattern;
30
31 import javax.crypto.spec.SecretKeySpec;
32 import javax.security.auth.Subject;
33 import javax.security.auth.callback.Callback;
34 import javax.security.auth.callback.UnsupportedCallbackException;
35
36 import org.w3c.dom.Element;
37 import org.apache.wss4j.common.crypto.Crypto;
38 import org.apache.wss4j.common.ext.WSPasswordCallback;
39 import org.apache.wss4j.common.ext.WSSecurityException;
40 import org.apache.wss4j.common.principal.SAMLTokenPrincipal;
41 import org.apache.wss4j.common.saml.OpenSAMLUtil;
42 import org.apache.wss4j.common.saml.SAMLKeyInfo;
43 import org.apache.wss4j.common.saml.SAMLUtil;
44 import org.apache.wss4j.common.saml.SamlAssertionWrapper;
45 import org.apache.wss4j.stax.ext.WSInboundSecurityContext;
46 import org.apache.wss4j.stax.ext.WSSConstants;
47 import org.apache.wss4j.stax.ext.WSSSecurityProperties;
48 import org.apache.wss4j.stax.securityToken.SamlSecurityToken;
49 import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
50 import org.apache.xml.security.algorithms.JCEMapper;
51 import org.apache.xml.security.exceptions.XMLSecurityException;
52 import org.apache.xml.security.stax.ext.XMLSecurityConstants;
53 import org.apache.xml.security.stax.impl.securityToken.AbstractInboundSecurityToken;
54 import org.apache.xml.security.stax.securityToken.InboundSecurityToken;
55 import org.opensaml.saml.common.SAMLVersion;
56
57 public class SamlSecurityTokenImpl extends AbstractInboundSecurityToken implements SamlSecurityToken {
58
59 private final SamlAssertionWrapper samlAssertionWrapper;
60 private InboundSecurityToken subjectSecurityToken;
61 private Crypto crypto;
62 private WSSSecurityProperties securityProperties;
63 private Principal principal;
64 private SAMLKeyInfo subjectKeyInfo;
65 private byte[] secret;
66 private Key key;
67
68 public SamlSecurityTokenImpl(WSInboundSecurityContext wsInboundSecurityContext, String id,
69 WSSecurityTokenConstants.KeyIdentifier keyIdentifier,
70 WSSSecurityProperties securityProperties) throws WSSecurityException {
71 super(wsInboundSecurityContext, id, keyIdentifier, false);
72 this.securityProperties = securityProperties;
73 if (securityProperties.getCallbackHandler() != null) {
74
75 WSPasswordCallback pwcb =
76 new WSPasswordCallback(id, WSPasswordCallback.CUSTOM_TOKEN);
77 try {
78 securityProperties.getCallbackHandler().handle(new Callback[]{pwcb});
79 } catch (IOException | UnsupportedCallbackException e) {
80 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e, "noPassword");
81 }
82
83 secret = pwcb.getKey();
84 key = pwcb.getKeyObject();
85 if (this.key instanceof PrivateKey) {
86 super.setAsymmetric(true);
87 }
88
89 Element assertionElem = pwcb.getCustomToken();
90 if (assertionElem != null && "Assertion".equals(assertionElem.getLocalName())
91 && (WSSConstants.NS_SAML.equals(assertionElem.getNamespaceURI())
92 || WSSConstants.NS_SAML2.equals(assertionElem.getNamespaceURI()))) {
93 this.samlAssertionWrapper = new SamlAssertionWrapper(assertionElem);
94
95 subjectKeyInfo =
96 SAMLUtil.getCredentialFromSubject(samlAssertionWrapper, null,
97 securityProperties.getSignatureVerificationCrypto());
98 } else {
99
100 this.samlAssertionWrapper = null;
101 }
102
103 if (this.samlAssertionWrapper == null && secret == null && key == null) {
104 throw new WSSecurityException(
105 WSSecurityException.ErrorCode.SECURITY_TOKEN_UNAVAILABLE, "noToken",
106 new Object[] {id}
107 );
108 }
109 } else {
110 throw new WSSecurityException(
111 WSSecurityException.ErrorCode.SECURITY_TOKEN_UNAVAILABLE, "noToken",
112 new Object[] {id}
113 );
114 }
115 }
116
117 public SamlSecurityTokenImpl(SamlAssertionWrapper samlAssertionWrapper, InboundSecurityToken subjectSecurityToken,
118 WSInboundSecurityContext wsInboundSecurityContext, Crypto crypto,
119 WSSecurityTokenConstants.KeyIdentifier keyIdentifier,
120 WSSSecurityProperties securityProperties) {
121 super(wsInboundSecurityContext, samlAssertionWrapper.getId(), keyIdentifier, true);
122 this.samlAssertionWrapper = samlAssertionWrapper;
123 this.crypto = crypto;
124 this.subjectSecurityToken = subjectSecurityToken;
125 this.securityProperties = securityProperties;
126 }
127
128 @Override
129 public boolean isAsymmetric() throws XMLSecurityException {
130 if (this.subjectSecurityToken != null && this.subjectSecurityToken.isAsymmetric()) {
131 return true;
132 }
133 return super.isAsymmetric();
134 }
135
136 @Override
137 protected Key getKey(String algorithmURI, XMLSecurityConstants.AlgorithmUsage algorithmUsage, String correlationID)
138 throws XMLSecurityException {
139 Key key = null;
140 if (this.key != null) {
141 key = this.key;
142 } else if (secret != null) {
143 String keyAlgorithm = JCEMapper.getJCEKeyAlgorithmFromURI(algorithmURI);
144 key = new SecretKeySpec(secret, keyAlgorithm);
145 } else if (this.subjectSecurityToken != null) {
146 key = subjectSecurityToken.getSecretKey(algorithmURI, algorithmUsage, correlationID);
147 } else if (subjectKeyInfo != null && subjectKeyInfo.getSecret() != null) {
148 String keyAlgorithm = JCEMapper.getJCEKeyAlgorithmFromURI(algorithmURI);
149 key = new SecretKeySpec(subjectKeyInfo.getSecret(), keyAlgorithm);
150 }
151 if (key != null) {
152 super.setSecretKey(algorithmURI, key);
153 return key;
154 }
155 return super.getKey(algorithmURI, algorithmUsage, correlationID);
156 }
157
158 @Override
159 protected PublicKey getPubKey(String algorithmURI, XMLSecurityConstants.AlgorithmUsage algorithmUsage, String correlationID)
160 throws XMLSecurityException {
161 if (this.subjectSecurityToken != null) {
162 return subjectSecurityToken.getPublicKey(algorithmURI, algorithmUsage, correlationID);
163 } else if (subjectKeyInfo != null && subjectKeyInfo.getPublicKey() != null) {
164 return subjectKeyInfo.getPublicKey();
165 }
166 return super.getPubKey(algorithmURI, algorithmUsage, correlationID);
167 }
168
169 @Override
170 public PublicKey getPublicKey() throws XMLSecurityException {
171 if (this.subjectSecurityToken != null) {
172 return subjectSecurityToken.getPublicKey();
173 } else if (subjectKeyInfo != null && subjectKeyInfo.getPublicKey() != null) {
174 return subjectKeyInfo.getPublicKey();
175 }
176 return super.getPublicKey();
177 }
178
179 @Override
180 public X509Certificate[] getX509Certificates() throws XMLSecurityException {
181 if (this.subjectSecurityToken != null) {
182 return subjectSecurityToken.getX509Certificates();
183 } else if (subjectKeyInfo != null && subjectKeyInfo.getCerts() != null) {
184 return subjectKeyInfo.getCerts();
185 }
186 return super.getX509Certificates();
187 }
188
189 @Override
190 public void verify() throws XMLSecurityException {
191
192
193 if (samlAssertionWrapper == null) {
194 return;
195 }
196 String confirmMethod = null;
197 List<String> methods = samlAssertionWrapper.getConfirmationMethods();
198 if (methods != null && !methods.isEmpty()) {
199 confirmMethod = methods.get(0);
200 }
201
202
203 if (!OpenSAMLUtil.isMethodHolderOfKey(confirmMethod) && !samlAssertionWrapper.isSigned()) {
204 X509Certificate[] x509Certificates = getX509Certificates();
205 if (x509Certificates != null && x509Certificates.length > 0) {
206 boolean enableRevocation = false;
207 Collection<Pattern> subjectCertConstraints = null;
208 Collection<Pattern> issuerCertConstraints = null;
209 if (securityProperties != null) {
210 enableRevocation = securityProperties.isEnableRevocation();
211 subjectCertConstraints = securityProperties.getSubjectCertConstraints();
212 issuerCertConstraints = securityProperties.getIssuerDNConstraints();
213
214 }
215 crypto.verifyTrust(x509Certificates, enableRevocation, subjectCertConstraints, issuerCertConstraints);
216 }
217 PublicKey publicKey = getPublicKey();
218 if (publicKey != null) {
219 crypto.verifyTrust(publicKey);
220 }
221 }
222 }
223
224 @Override
225 public WSSecurityTokenConstants.TokenType getTokenType() {
226 if (samlAssertionWrapper != null
227 && samlAssertionWrapper.getSamlVersion() == SAMLVersion.VERSION_10) {
228 return WSSecurityTokenConstants.SAML_10_TOKEN;
229 } else if (samlAssertionWrapper != null
230 && samlAssertionWrapper.getSamlVersion() == SAMLVersion.VERSION_11) {
231 return WSSecurityTokenConstants.SAML_11_TOKEN;
232 }
233 return WSSecurityTokenConstants.SAML_20_TOKEN;
234 }
235
236 @Override
237 public Subject getSubject() throws WSSecurityException {
238 return null;
239 }
240
241 @Override
242 public Principal getPrincipal() throws WSSecurityException {
243 if (this.principal == null) {
244 this.principal = new SAMLTokenPrincipal() {
245 @Override
246 public SamlAssertionWrapper getToken() {
247 return samlAssertionWrapper;
248 }
249
250 @Override
251 public String getName() {
252 return samlAssertionWrapper.getSubjectName();
253 }
254
255 @Override
256 public String getId() {
257 return samlAssertionWrapper.getId();
258 }
259 };
260 }
261 return this.principal;
262 }
263
264 @Override
265 public SamlAssertionWrapper getSamlAssertionWrapper() {
266 return samlAssertionWrapper;
267 }
268 }