1 /**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20 package dk.sosi.seal.transform.internal;
21
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.apache.ws.security.WSConstants;
25 import org.apache.ws.security.WSDocInfo;
26 import org.apache.ws.security.WSSecurityException;
27 import org.apache.ws.security.message.token.X509Security;
28 import org.apache.ws.security.util.Base64;
29 import org.apache.ws.security.util.WSSecurityUtil;
30 import org.w3c.dom.Document;
31 import org.w3c.dom.Element;
32 import org.w3c.dom.Text;
33
34 import java.security.cert.CertificateEncodingException;
35 import java.security.cert.X509Certificate;
36
37 /**
38 * Utility class exposing the dereferencing logic of the {@link STRTransform} implementation.
39 */
40 public class STRTransformUtil {
41 private static Log log = LogFactory.getLog(STRTransformUtil.class.getName());
42
43 /**
44 * Retrieves the element representing the referenced content of a STR.
45 *
46 * @return the element representing the referenced content. The element is either
47 * extracted from {@code doc} or a new element is created in the
48 * case of a key identifier or issuer serial STR. {@code null} if
49 * {@code secRef} does not contain a direct reference, key identifier, or
50 * issuer serial.
51 * @throws WSSecurityException
52 * If an issuer serial or key identifier is used in the STR and
53 * the certificate cannot be resolved from the crypto
54 * configuration or if there is an error working with the resolved
55 * cert
56 */
57 public static Element dereferenceSTR(Document doc,
58 SecurityTokenReference secRef, WSDocInfo wsDocInfo) throws WSSecurityException
59 {
60
61 // NOTE: Here step numbers refer to the overall step in the complete processing
62 // of the STRTransform. See STRTransform for the lead up to these steps.
63 //
64 // Third step: locate the security token referenced by the STR element.
65 // Either the Token is contained in the document as a
66 // BinarySecurityToken or stored in some key storage.
67 //
68 // Fourth step: after security token was located, prepare it. If its
69 // reference via a direct reference, i.e. a relative URI that references
70 // the BST directly in the message then just return that element.
71 // Otherwise wrap the located token in a newly created BST element as
72 // described in WSS Specification.
73 //
74 //
75 Element tokElement = null;
76
77 //
78 // First case: direct reference, according to chap 7.2 of OASIS WS
79 // specification (main document). Only in this case return a true
80 // reference to the BST. Copying is done by the caller.
81 //
82 if (secRef.containsReference()) {
83 if (log.isDebugEnabled()) {
84 log.debug("STR: Reference");
85 }
86 tokElement = secRef.getTokenElement(doc, wsDocInfo, null);
87 }
88 //
89 // second case: IssuerSerial, lookup in keystore, wrap in BST according
90 // to specification
91 //
92 else if (secRef.containsX509Data() || secRef.containsX509IssuerSerial()) {
93 if (log.isDebugEnabled()) {
94 log.debug("STR: IssuerSerial");
95 }
96 X509Certificate cert = null;
97 X509Certificate[] certs =
98 secRef.getX509IssuerSerial(wsDocInfo.getCrypto());
99 if (certs == null || certs.length == 0 || certs[0] == null) {
100 throw new WSSecurityException(WSSecurityException.FAILED_CHECK);
101 }
102 cert = certs[0];
103 tokElement = createBSTX509(doc, cert, secRef.getElement());
104 }
105 //
106 // third case: KeyIdentifier. For SKI, lookup in keystore, wrap in
107 // BST according to specification. Otherwise if it's a wsse:KeyIdentifier it could
108 // be a SAML assertion, so try and find the referenced element.
109 //
110 else if (secRef.containsKeyIdentifier()) {
111 if (log.isDebugEnabled()) {
112 log.debug("STR: KeyIdentifier");
113 }
114 if (WSConstants.WSS_SAML_KI_VALUE_TYPE.equals(secRef.getKeyIdentifierValueType())
115 // Start added by Seal
116 || WSConstants.WSS_SAML2_KI_VALUE_TYPE.equals(secRef.getKeyIdentifierValueType())
117 // End added by Seal
118 ) {
119 tokElement = secRef.getKeyIdentifierTokenElement(doc, wsDocInfo, null);
120 } else {
121 X509Certificate cert = null;
122 X509Certificate[] certs = secRef.getKeyIdentifier(wsDocInfo.getCrypto());
123 if (certs == null || certs.length == 0 || certs[0] == null) {
124 throw new WSSecurityException(WSSecurityException.FAILED_CHECK);
125 }
126 cert = certs[0];
127 tokElement = createBSTX509(doc, cert, secRef.getElement());
128 }
129 }
130 return tokElement;
131 }
132
133 protected static Element createBSTX509(Document doc, X509Certificate cert, Element secRefE)
134 throws WSSecurityException {
135 byte data[];
136 try {
137 data = cert.getEncoded();
138 } catch (CertificateEncodingException e) {
139 throw new WSSecurityException(
140 WSSecurityException.SECURITY_TOKEN_UNAVAILABLE, "encodeError", null, e
141 );
142 }
143 String prefix = WSSecurityUtil.getPrefixNS(WSConstants.WSSE_NS, secRefE);
144 Element elem = doc.createElementNS(WSConstants.WSSE_NS, prefix + ":BinarySecurityToken");
145 WSSecurityUtil.setNamespace(elem, WSConstants.WSSE_NS, prefix);
146 // elem.setAttributeNS(WSConstants.XMLNS_NS, "xmlns", "");
147 elem.setAttributeNS(null, "ValueType", X509Security.X509_V3_TYPE);
148 Text certText = doc.createTextNode(Base64.encode(data)); // no line wrap
149 elem.appendChild(certText);
150 return elem;
151 }
152
153 /**
154 * Hidden in utility class.
155 */
156 private STRTransformUtil() {
157 }
158
159 }