001: /*
002: * The contents of this file are subject to the terms
003: * of the Common Development and Distribution License
004: * (the "License"). You may not use this file except
005: * in compliance with the License.
006: *
007: * You can obtain a copy of the license at
008: * https://jwsdp.dev.java.net/CDDLv1.0.html
009: * See the License for the specific language governing
010: * permissions and limitations under the License.
011: *
012: * When distributing Covered Code, include this CDDL
013: * HEADER in each file and include the License file at
014: * https://jwsdp.dev.java.net/CDDLv1.0.html If applicable,
015: * add the following below this CDDL HEADER, with the
016: * fields enclosed by brackets "[]" replaced with your
017: * own identifying information: Portions Copyright [yyyy]
018: * [name of copyright owner]
019: */
020: /*
021: * AssertionUtil.java
022: *
023: * Created on August 18, 2005, 6:40 PM
024: *
025: * To change this template, choose Tools | Options and locate the template under
026: * the Source Creation and Management node. Right-click the template and choose
027: * Open. You can then make changes to the template in the Source Editor.
028: */
029:
030: package com.sun.xml.wss.saml;
031:
032: import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
033: import com.sun.org.apache.xml.internal.security.keys.KeyInfo;
034: import com.sun.org.apache.xml.internal.security.keys.content.X509Data;
035: import com.sun.org.apache.xml.internal.security.keys.content.KeyValue;
036: import com.sun.org.apache.xml.internal.security.utils.EncryptionConstants;
037: import com.sun.org.apache.xml.internal.security.encryption.EncryptedKey;
038: import com.sun.org.apache.xml.internal.security.encryption.XMLCipher;
039: import com.sun.xml.wss.impl.MessageConstants;
040: import com.sun.xml.wss.XWSSecurityException;
041: import com.sun.xml.wss.saml.internal.saml11.jaxb20.AssertionType;
042: import java.math.BigInteger;
043: import java.security.Key;
044: import java.security.cert.X509Certificate;
045: import javax.security.auth.callback.Callback;
046: import javax.security.auth.callback.CallbackHandler;
047: import javax.xml.bind.JAXBElement;
048: import org.w3c.dom.DOMException;
049: import org.w3c.dom.Element;
050: import org.w3c.dom.NodeList;
051:
052: import java.util.logging.Level;
053: import java.util.logging.Logger;
054:
055: import com.sun.xml.wss.SecurityEnvironment;
056: import com.sun.xml.wss.impl.misc.DefaultSecurityEnvironmentImpl;
057: import com.sun.xml.wss.core.ReferenceElement;
058: import com.sun.xml.wss.core.SecurityTokenReference;
059: import com.sun.xml.wss.core.KeyInfoHeaderBlock;
060: import com.sun.xml.wss.core.reference.KeyIdentifier;
061: import com.sun.xml.wss.core.reference.X509IssuerSerial;
062: import com.sun.xml.wss.logging.LogDomainConstants;
063:
064: import com.sun.xml.wss.impl.callback.*;
065: import com.sun.xml.wss.saml.util.SAMLJAXBUtil;
066: import com.sun.xml.wss.saml.util.SAML20JAXBUtil;
067: import javax.xml.bind.JAXBContext;
068:
069: /**
070: *
071: * @author abhijit.das@Sun.COM
072: */
073:
074: public class AssertionUtil {
075:
076: private static Logger log = Logger.getLogger(
077: LogDomainConstants.WSS_API_DOMAIN,
078: LogDomainConstants.WSS_API_DOMAIN_BUNDLE);
079:
080: /** Creates a new instance of AssertionUtil */
081: private AssertionUtil(CallbackHandler callbackHandler) {
082: //do nothing
083: }
084:
085: /**
086: * Retrive the key from HOK SAML Assertion
087: *
088: * @param assertion An <code>org.w3c.dom.Element</code> representation of SAML Assertion
089: *
090: * @param callbackHandler A <code>javax.security.auth.callback.CallbackHandler</code> object used to retrive the key
091: *
092: * @return java.security.Key
093: * @throws XWSSecurityException
094: *
095: */
096: public static Key getSubjectConfirmationKey(Element assertion,
097: CallbackHandler callbackHandler)
098: throws XWSSecurityException {
099:
100: NodeList nl1 = assertion
101: .getElementsByTagName("SubjectConfirmation");
102:
103: if (nl1.getLength() == 0) {
104: throw new XWSSecurityException(
105: "SAML Assertion does not contain a key");
106: }
107:
108: NodeList nl = ((Element) (nl1.item(0))).getElementsByTagNameNS(
109: MessageConstants.DSIG_NS, "KeyInfo");
110:
111: if (nl.getLength() == 0) {
112: throw new XWSSecurityException(
113: "SAML Assertion does not contain a key");
114: }
115:
116: try {
117: Element keyInfoElem = (Element) nl.item(0);
118:
119: KeyInfo keyInfo = new KeyInfo(keyInfoElem, null);
120:
121: if (keyInfo.containsKeyValue()) {
122: return keyInfo.itemKeyValue(0).getPublicKey();
123: } else if (keyInfo.containsX509Data()) {
124: return resolveX509Data(keyInfo.itemX509Data(0),
125: callbackHandler);
126: } else if (keyInfo.length(
127: EncryptionConstants.EncryptionSpecNS,
128: EncryptionConstants._TAG_ENCRYPTEDKEY) > 0) {
129: return resolveEncryptedKey(keyInfo.itemEncryptedKey(0),
130: callbackHandler);
131: } else {
132: throw new XWSSecurityException(
133: "Unsupported Key Information");
134: }
135: } catch (Exception e) {
136: throw new XWSSecurityException(e);
137: }
138: }
139:
140: public static Key resolveX509Data(X509Data x509Data,
141: CallbackHandler callbackHandler)
142: throws XWSSecurityException {
143: x509Data.getElement().normalize();
144: X509Certificate cert = null;
145:
146: try {
147: if (x509Data.containsCertificate()) {
148: cert = (x509Data.itemCertificate(0))
149: .getX509Certificate();
150: } else if (x509Data.containsSKI()) {
151: byte[] keyIdentifier = x509Data.itemSKI(0)
152: .getSKIBytes();
153: SignatureVerificationKeyCallback.X509CertificateRequest certRequest = new SignatureVerificationKeyCallback.X509SubjectKeyIdentifierBasedRequest(
154: keyIdentifier);
155: SignatureVerificationKeyCallback verifyKeyCallback = new SignatureVerificationKeyCallback(
156: certRequest);
157:
158: Callback[] callbacks = new Callback[] { verifyKeyCallback };
159: try {
160: callbackHandler.handle(callbacks);
161: } catch (Exception e) {
162: throw new XWSSecurityException(e);
163: }
164:
165: cert = certRequest.getX509Certificate();
166:
167: if (cert == null) {
168: throw new XWSSecurityException(
169: "No Matching public key for "
170: + Base64.encode(keyIdentifier)
171: + " subject key identifier found");
172: }
173: } else if (x509Data.containsIssuerSerial()) {
174:
175: String issuerName = x509Data.itemIssuerSerial(0)
176: .getIssuerName();
177: BigInteger serialNumber = x509Data.itemIssuerSerial(0)
178: .getSerialNumber();
179:
180: SignatureVerificationKeyCallback.X509CertificateRequest certRequest = new SignatureVerificationKeyCallback.X509IssuerSerialBasedRequest(
181: issuerName, serialNumber);
182: SignatureVerificationKeyCallback verifyKeyCallback = new SignatureVerificationKeyCallback(
183: certRequest);
184:
185: Callback[] callbacks = new Callback[] { verifyKeyCallback };
186:
187: try {
188: callbackHandler.handle(callbacks);
189: } catch (Exception e) {
190: throw new XWSSecurityException(e);
191: }
192:
193: cert = certRequest.getX509Certificate();
194:
195: if (cert == null) {
196: throw new XWSSecurityException(
197: "No Matching public key for serial number "
198: + serialNumber
199: + " and issuer name " + issuerName
200: + " found");
201: }
202: } else {
203: throw new XWSSecurityException(
204: "Unsupported child element of X509Data encountered");
205: }
206:
207: return cert.getPublicKey();
208: } catch (Exception e) {
209: throw new XWSSecurityException(e);
210: }
211: }
212:
213: public static Key resolveEncryptedKey(EncryptedKey encryptedKey,
214: CallbackHandler callbackHandler)
215: throws XWSSecurityException {
216:
217: //Get the private key to decrypt the encrypted key
218: KeyInfo keyInfo = encryptedKey.getKeyInfo();
219: KeyInfoHeaderBlock keyInfoHb = new KeyInfoHeaderBlock(keyInfo);
220: Key kek = null;
221: try {
222: if (keyInfoHb.containsSecurityTokenReference()) {
223: kek = processSecurityTokenReference(keyInfoHb,
224: callbackHandler);
225: } else if (keyInfoHb.containsKeyValue()) {
226:
227: SecurityEnvironment secEnv = new DefaultSecurityEnvironmentImpl(
228: callbackHandler);
229: KeyValue keyValue = keyInfoHb.getKeyValue(0);
230: keyValue.getElement().normalize();
231: kek = secEnv.getPrivateKey(null, keyValue
232: .getPublicKey(), false);
233:
234: } else if (keyInfoHb.containsX509Data()) {
235: kek = processX509Data(keyInfoHb, callbackHandler);
236: } else {
237: throw new XWSSecurityException(
238: "Unsupported Key Information");
239: }
240: // Decrypt the encrypted secret key and return
241: String algorithmURI = encryptedKey.getEncryptionMethod()
242: .getAlgorithm();
243: XMLCipher xmlCipher = XMLCipher.getInstance();
244: xmlCipher.init(XMLCipher.UNWRAP_MODE, null);
245: xmlCipher.setKEK(kek);
246:
247: return xmlCipher.decryptKey(encryptedKey, algorithmURI);
248: } catch (Exception e) {
249: throw new XWSSecurityException(e);
250: }
251:
252: }
253:
254: private static Key processSecurityTokenReference(
255: KeyInfoHeaderBlock keyInfo, CallbackHandler callbackHandler)
256: throws XWSSecurityException {
257: Key returnKey = null;
258:
259: SecurityEnvironment secEnv = new DefaultSecurityEnvironmentImpl(
260: callbackHandler);
261:
262: SecurityTokenReference str = keyInfo
263: .getSecurityTokenReference(0);
264: ReferenceElement refElement = str.getReference();
265:
266: if (refElement instanceof KeyIdentifier) {
267: KeyIdentifier keyId = (KeyIdentifier) refElement;
268: byte[] decodedValue = keyId.getDecodedReferenceValue()
269: .getBytes();
270: if (MessageConstants.X509SubjectKeyIdentifier_NS
271: .equals(keyId.getValueType())
272: || MessageConstants.X509v3SubjectKeyIdentifier_NS
273: .equals(keyId.getValueType())) {
274: returnKey = secEnv.getPrivateKey(null, decodedValue);
275: } else if (MessageConstants.ThumbPrintIdentifier_NS
276: .equals(keyId.getValueType())) {
277: throw new XWSSecurityException(
278: "Unsupported KeyValueType :"
279: + keyId.getValueType());
280: }
281:
282: } /*else if(refElement instanceof DirectReference){
283: String uri = ((DirectReference) refElement).getURI();
284:
285:
286: }*/else if (refElement instanceof X509IssuerSerial) {
287: BigInteger serialNumber = ((X509IssuerSerial) refElement)
288: .getSerialNumber();
289: String issuerName = ((X509IssuerSerial) refElement)
290: .getIssuerName();
291:
292: returnKey = secEnv.getPrivateKey(null, serialNumber,
293: issuerName);
294: } else {
295: log.log(Level.SEVERE,
296: "WSS0338.unsupported.reference.mechanism");
297: throw new XWSSecurityException(
298: "Key reference mechanism not supported");
299: }
300: return returnKey;
301: }
302:
303: private static Key processX509Data(KeyInfoHeaderBlock keyInfo,
304: CallbackHandler callbackHandler)
305: throws XWSSecurityException {
306: SecurityEnvironment secEnv = new DefaultSecurityEnvironmentImpl(
307: callbackHandler);
308: X509Data x509Data = keyInfo.getX509Data(0);
309: X509Certificate cert = null;
310: try {
311: if (x509Data.containsCertificate()) {
312: cert = (x509Data.itemCertificate(0))
313: .getX509Certificate();
314: } else if (x509Data.containsSKI()) {
315: return secEnv.getPrivateKey(null, x509Data.itemSKI(0)
316: .getSKIBytes());
317: } else if (x509Data.containsIssuerSerial()) {
318: return secEnv.getPrivateKey(null, x509Data
319: .itemIssuerSerial(0).getSerialNumber(),
320: x509Data.itemIssuerSerial(0).getIssuerName());
321: } else {
322: log.log(Level.SEVERE, "WSS0339.unsupported.keyinfo");
323: throw new XWSSecurityException(
324: "Unsupported child element of X509Data encountered");
325: }
326: return secEnv.getPrivateKey(null, cert);
327:
328: } catch (Exception e) {
329: log.log(Level.SEVERE, "WSS0602.illegal.x509.data", e
330: .getMessage());
331: throw new XWSSecurityException(e);
332: }
333: }
334:
335: public static Assertion fromElement(org.w3c.dom.Element element)
336: throws SAMLException {
337: try {
338: if (System.getProperty("com.sun.xml.wss.saml.binding.jaxb") != null) {
339: JAXBContext jc = SAMLJAXBUtil.getJAXBContext();
340:
341: javax.xml.bind.Unmarshaller u = jc.createUnmarshaller();
342: return new com.sun.xml.wss.saml.assertion.saml11.jaxb10.Assertion(
343: (com.sun.xml.wss.saml.internal.saml11.jaxb10.impl.AssertionImpl) u
344: .unmarshal(element));
345: } else {
346: if (element.getAttributeNode("ID") != null) {
347: JAXBContext jc = SAML20JAXBUtil.getJAXBContext();
348:
349: javax.xml.bind.Unmarshaller u = jc
350: .createUnmarshaller();
351: Object el = u.unmarshal(element);
352: return new com.sun.xml.wss.saml.assertion.saml20.jaxb20.Assertion(
353: (com.sun.xml.wss.saml.internal.saml20.jaxb20.AssertionType) ((JAXBElement) el)
354: .getValue());
355: } else {
356: JAXBContext jc = SAMLJAXBUtil.getJAXBContext();
357:
358: javax.xml.bind.Unmarshaller u = jc
359: .createUnmarshaller();
360: Object el = u.unmarshal(element);
361: return new com.sun.xml.wss.saml.assertion.saml11.jaxb20.Assertion(
362: (AssertionType) ((JAXBElement) el)
363: .getValue());
364: }
365: }
366: } catch (Exception ex) {
367: // log here
368: throw new SAMLException(ex);
369: }
370: }
371:
372: public static String getConfirmationMethod(Element assertion) {
373: NodeList nl = null;
374:
375: if (assertion.getAttributeNode("ID") != null) {
376: nl = assertion.getElementsByTagNameNS(
377: MessageConstants.SAML_v2_0_NS,
378: "SubjectConfirmation");
379: } else {
380: nl = assertion
381: .getElementsByTagNameNS(
382: MessageConstants.SAML_v1_0_NS,
383: "ConfirmationMethod");
384: }
385: if (nl.getLength() == 0)
386: return null;
387:
388: Element confirmationMethod = (Element) nl.item(0);
389: try {
390: if (assertion.getAttributeNode("ID") != null) {
391: return confirmationMethod.getAttribute("Method");
392: } else {
393: return confirmationMethod.getTextContent();
394: }
395: } catch (DOMException ex) {
396: //ignore
397: return null;
398: }
399: }
400:
401: public static Element getSubjectConfirmationKeyInfo(
402: Element assertion) throws XWSSecurityException {
403:
404: try {
405: NodeList nl1 = null;
406: if (assertion.getAttributeNode("ID") != null) {
407: nl1 = assertion.getElementsByTagNameNS(
408: MessageConstants.SAML_v2_0_NS,
409: "SubjectConfirmationData");
410: } else {
411: nl1 = assertion.getElementsByTagNameNS(
412: MessageConstants.SAML_v1_0_NS,
413: "SubjectConfirmation");
414: }
415:
416: if (nl1.getLength() == 0) {
417: throw new XWSSecurityException(
418: "SAML Assertion does not contain a key");
419: }
420:
421: NodeList nl = ((Element) (nl1.item(0)))
422: .getElementsByTagNameNS(MessageConstants.DSIG_NS,
423: "KeyInfo");
424:
425: if (nl.getLength() == 0) {
426: throw new XWSSecurityException(
427: "SAML Assertion does not contain a key");
428: }
429:
430: //NodeList nl = assertion.getElementsByTagNameNS(MessageConstants.DSIG_NS, "KeyInfo");
431: if (nl.getLength() != 0) {
432: Element keyInfo = (Element) nl.item(0);
433: if (keyInfo != null) {
434: return keyInfo;
435: }
436: }
437: } catch (Exception e) {
438: throw new XWSSecurityException(e);
439: }
440: throw new XWSSecurityException(
441: "Unable to locate KeyInfo inside SubjectConfirmation of SAML Assertion");
442: }
443: }
|