1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.wss4j.dom.common;
21
22 import org.apache.wss4j.dom.WSConstants;
23 import org.apache.wss4j.common.crypto.Crypto;
24 import org.apache.wss4j.common.saml.SAMLCallback;
25 import org.apache.wss4j.common.saml.bean.ActionBean;
26 import org.apache.wss4j.common.saml.bean.AttributeBean;
27 import org.apache.wss4j.common.saml.bean.AttributeStatementBean;
28 import org.apache.wss4j.common.saml.bean.AuthDecisionStatementBean;
29 import org.apache.wss4j.common.saml.bean.AuthenticationStatementBean;
30 import org.apache.wss4j.common.saml.bean.ConditionsBean;
31 import org.apache.wss4j.common.saml.bean.KeyInfoBean;
32 import org.apache.wss4j.common.saml.bean.KeyInfoBean.CERT_IDENTIFIER;
33 import org.apache.wss4j.common.util.KeyUtils;
34 import org.apache.wss4j.common.saml.bean.NameIDBean;
35 import org.apache.wss4j.common.saml.bean.SubjectBean;
36 import org.apache.wss4j.common.saml.bean.SubjectConfirmationDataBean;
37 import org.apache.wss4j.common.saml.bean.SubjectLocalityBean;
38 import org.apache.wss4j.dom.message.WSSecEncryptedKey;
39 import org.w3c.dom.Document;
40 import org.w3c.dom.Element;
41
42 import javax.crypto.KeyGenerator;
43 import javax.crypto.SecretKey;
44 import javax.security.auth.callback.CallbackHandler;
45 import javax.xml.parsers.DocumentBuilder;
46 import javax.xml.parsers.DocumentBuilderFactory;
47
48 import java.security.cert.X509Certificate;
49 import java.time.Instant;
50 import java.util.ArrayList;
51 import java.util.Collections;
52 import java.util.List;
53
54
55
56
57
58 public abstract class AbstractSAMLCallbackHandler implements CallbackHandler {
59
60 public enum Statement {
61 AUTHN, ATTR, AUTHZ
62 }
63
64 protected String subjectName;
65 protected String subjectQualifier;
66 protected String confirmationMethod;
67 protected X509Certificate[] certs;
68 protected Statement statement = Statement.AUTHN;
69 protected CERT_IDENTIFIER certIdentifier = CERT_IDENTIFIER.X509_CERT;
70 protected byte[] ephemeralKey;
71 protected String issuer;
72 protected String issuerFormat;
73 protected String subjectNameIDFormat;
74 protected String subjectLocalityIpAddress;
75 protected String subjectLocalityDnsAddress;
76 protected Instant sessionNotOnOrAfter;
77 protected Instant authenticationInstant;
78 protected String resource;
79 protected List<Object> customAttributeValues;
80 protected ConditionsBean conditions;
81 protected SubjectConfirmationDataBean subjectConfirmationData;
82 private Crypto issuerCrypto;
83 private String issuerName;
84 private String issuerPassword;
85 private Element assertionAdviceElement;
86 private Element keyInfoElement;
87 protected NameIDBean subjectConfirmationNameID;
88 protected boolean signAssertion;
89
90 public boolean isSignAssertion() {
91 return signAssertion;
92 }
93
94 public void setSignAssertion(boolean signAssertion) {
95 this.signAssertion = signAssertion;
96 }
97
98 public void setSubjectName(String subjectName) {
99 this.subjectName = subjectName;
100 }
101
102 public NameIDBean getSubjectConfirmationNameID() {
103 return subjectConfirmationNameID;
104 }
105
106 public void setSubjectConfirmationNameID(NameIDBean subjectConfirmationNameID) {
107 this.subjectConfirmationNameID = subjectConfirmationNameID;
108 }
109
110 public void setSubjectConfirmationData(SubjectConfirmationDataBean subjectConfirmationData) {
111 this.subjectConfirmationData = subjectConfirmationData;
112 }
113
114 public void setConditions(ConditionsBean conditionsBean) {
115 this.conditions = conditionsBean;
116 }
117
118 public void setConfirmationMethod(String confMethod) {
119 confirmationMethod = confMethod;
120 }
121
122 public void setSessionNotOnOrAfter(Instant sessionNotOnOrAfter) {
123 this.sessionNotOnOrAfter = sessionNotOnOrAfter;
124 }
125
126 public void setStatement(Statement statement) {
127 this.statement = statement;
128 }
129
130 public void setCertIdentifier(CERT_IDENTIFIER certIdentifier) {
131 this.certIdentifier = certIdentifier;
132 }
133
134 public void setCerts(X509Certificate[] certs) {
135 this.certs = certs;
136 }
137
138 public byte[] getEphemeralKey() {
139 return ephemeralKey;
140 }
141
142 public void setIssuer(String issuer) {
143 this.issuer = issuer;
144 }
145
146 public void setIssuerFormat(String issuerFormat) {
147 this.issuerFormat = issuerFormat;
148 }
149
150 public void setSubjectNameIDFormat(String subjectNameIDFormat) {
151 this.subjectNameIDFormat = subjectNameIDFormat;
152 }
153
154 public void setSubjectLocality(String ipAddress, String dnsAddress) {
155 this.subjectLocalityIpAddress = ipAddress;
156 this.subjectLocalityDnsAddress = dnsAddress;
157 }
158
159 public void setResource(String resource) {
160 this.resource = resource;
161 }
162
163 public void setCustomAttributeValues(List<Object> customAttributeValues) {
164 this.customAttributeValues = customAttributeValues;
165 }
166
167 public Instant getAuthenticationInstant() {
168 return authenticationInstant;
169 }
170
171 public void setAuthenticationInstant(Instant authenticationInstant) {
172 this.authenticationInstant = authenticationInstant;
173 }
174
175
176
177
178 protected void createAndSetStatement(SubjectBean subjectBean, SAMLCallback callback) {
179 if (statement == Statement.AUTHN) {
180 AuthenticationStatementBean authBean = new AuthenticationStatementBean();
181 if (subjectBean != null) {
182 authBean.setSubject(subjectBean);
183 }
184 if (subjectLocalityIpAddress != null || subjectLocalityDnsAddress != null) {
185 SubjectLocalityBean subjectLocality = new SubjectLocalityBean();
186 subjectLocality.setIpAddress(subjectLocalityIpAddress);
187 subjectLocality.setDnsAddress(subjectLocalityDnsAddress);
188 authBean.setSubjectLocality(subjectLocality);
189 }
190 authBean.setAuthenticationMethod("Password");
191 authBean.setAuthenticationInstant(authenticationInstant);
192 authBean.setSessionNotOnOrAfter(sessionNotOnOrAfter);
193 callback.setAuthenticationStatementData(Collections.singletonList(authBean));
194 } else if (statement == Statement.ATTR) {
195 AttributeStatementBean attrBean = new AttributeStatementBean();
196 AttributeBean attributeBean = new AttributeBean();
197 if (subjectBean != null) {
198 attrBean.setSubject(subjectBean);
199 attributeBean.setSimpleName("role");
200 attributeBean.setQualifiedName("http://custom-ns");
201 } else {
202 attributeBean.setQualifiedName("role");
203 }
204 if (customAttributeValues != null) {
205 attributeBean.setAttributeValues(customAttributeValues);
206 } else {
207 List<Object> attributes = new ArrayList<>();
208 attributes.add("user");
209 attributeBean.setAttributeValues(attributes);
210 }
211 attrBean.setSamlAttributes(Collections.singletonList(attributeBean));
212 callback.setAttributeStatementData(Collections.singletonList(attrBean));
213 } else {
214 AuthDecisionStatementBean authzBean = new AuthDecisionStatementBean();
215 if (subjectBean != null) {
216 authzBean.setSubject(subjectBean);
217 }
218 ActionBean actionBean = new ActionBean();
219 actionBean.setContents("Read");
220 authzBean.setActions(Collections.singletonList(actionBean));
221 authzBean.setResource("endpoint");
222 authzBean.setDecision(AuthDecisionStatementBean.Decision.PERMIT);
223 authzBean.setResource(resource);
224 callback.setAuthDecisionStatementData(Collections.singletonList(authzBean));
225 }
226 }
227
228 protected KeyInfoBean createKeyInfo() throws Exception {
229 KeyInfoBean keyInfo = new KeyInfoBean();
230 if (keyInfoElement != null) {
231 keyInfo.setElement(keyInfoElement);
232 } else if (statement == Statement.AUTHN) {
233 keyInfo.setCertificate(certs[0]);
234 keyInfo.setCertIdentifer(certIdentifier);
235 } else if (statement == Statement.ATTR) {
236
237 DocumentBuilderFactory docBuilderFactory =
238 DocumentBuilderFactory.newInstance();
239 docBuilderFactory.setNamespaceAware(true);
240 DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
241 Document doc = docBuilder.newDocument();
242
243
244 WSSecEncryptedKey encrKey = new WSSecEncryptedKey(doc);
245 encrKey.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
246 encrKey.setUseThisCert(certs[0]);
247
248 KeyGenerator keyGen = KeyUtils.getKeyGenerator(WSConstants.AES_128);
249 SecretKey symmetricKey = keyGen.generateKey();
250 encrKey.prepare(null, symmetricKey);
251 ephemeralKey = symmetricKey.getEncoded();
252 Element encryptedKeyElement = encrKey.getEncryptedKeyElement();
253
254
255 Element kiElement =
256 doc.createElementNS(
257 WSConstants.SIG_NS, WSConstants.SIG_PREFIX + ":" + WSConstants.KEYINFO_LN
258 );
259 kiElement.setAttributeNS(
260 WSConstants.XMLNS_NS, "xmlns:" + WSConstants.SIG_PREFIX, WSConstants.SIG_NS
261 );
262 kiElement.appendChild(encryptedKeyElement);
263
264 keyInfo.setElement(kiElement);
265 }
266 return keyInfo;
267 }
268
269 public Crypto getIssuerCrypto() {
270 return issuerCrypto;
271 }
272
273 public void setIssuerCrypto(Crypto issuerCrypto) {
274 this.issuerCrypto = issuerCrypto;
275 }
276
277 public String getIssuerName() {
278 return issuerName;
279 }
280
281 public void setIssuerName(String issuerName) {
282 this.issuerName = issuerName;
283 }
284
285 public String getIssuerPassword() {
286 return issuerPassword;
287 }
288
289 public void setIssuerPassword(String issuerPassword) {
290 this.issuerPassword = issuerPassword;
291 }
292
293 public Element getAssertionAdviceElement() {
294 return assertionAdviceElement;
295 }
296
297 public void setAssertionAdviceElement(Element assertionAdviceElement) {
298 this.assertionAdviceElement = assertionAdviceElement;
299 }
300
301 public Element getKeyInfoElement() {
302 return keyInfoElement;
303 }
304
305 public void setKeyInfoElement(Element keyInfoElement) {
306 this.keyInfoElement = keyInfoElement;
307 }
308 }