View Javadoc

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  package org.apache.chemistry.opencmis.client.bindings.spi;
20  
21  import java.lang.reflect.InvocationTargetException;
22  import java.lang.reflect.Method;
23  import java.text.SimpleDateFormat;
24  import java.util.Set;
25  import java.util.TimeZone;
26  
27  import javax.security.auth.Subject;
28  import javax.xml.parsers.ParserConfigurationException;
29  
30  import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
31  import org.apache.chemistry.opencmis.commons.impl.Base64;
32  import org.apache.chemistry.opencmis.commons.impl.ClassLoaderUtil;
33  import org.apache.chemistry.opencmis.commons.impl.XMLUtils;
34  import org.slf4j.Logger;
35  import org.slf4j.LoggerFactory;
36  import org.w3c.dom.Document;
37  import org.w3c.dom.Element;
38  
39  public class LTPAWSSecurityAuthenticationProvider extends StandardAuthenticationProvider {
40  
41      private static final long serialVersionUID = 1L;
42  
43      private static final Logger LOG = LoggerFactory.getLogger(LTPAWSSecurityAuthenticationProvider.class);
44  
45      @Override
46      public Element getSOAPHeaders(Object portObject) {
47  
48          String securityToken = getSecurityToken();
49  
50          // Exit if no security token found
51          if (securityToken == null) {
52              if (LOG.isDebugEnabled()) {
53                  LOG.debug("securityToken is null");
54              }
55              return null;
56          }
57  
58          // Set time
59          SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
60          sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
61          long created = System.currentTimeMillis();
62          long expires = created + 24 * 60 * 60 * 1000; // 24 hours
63  
64          // Create the SOAP WSSecurity header
65          try {
66              Document document = XMLUtils.newDomDocument();
67  
68              Element wsseSecurityElement = document.createElementNS(WSSE_NAMESPACE, "Security");
69  
70              Element wsuTimestampElement = document.createElementNS(WSU_NAMESPACE, "Timestamp");
71              wsseSecurityElement.appendChild(wsuTimestampElement);
72  
73              Element tsCreatedElement = document.createElementNS(WSU_NAMESPACE, "Created");
74              tsCreatedElement.appendChild(document.createTextNode(sdf.format(created)));
75              wsuTimestampElement.appendChild(tsCreatedElement);
76  
77              Element tsExpiresElement = document.createElementNS(WSU_NAMESPACE, "Expires");
78              tsExpiresElement.appendChild(document.createTextNode(sdf.format(expires)));
79              wsuTimestampElement.appendChild(tsExpiresElement);
80  
81              // Add the BinarySecurityToken (contains the LTPAv2 token)
82              Element wsseBinarySecurityTokenElement = document.createElementNS(WSSE_NAMESPACE, "BinarySecurityToken");
83              wsseBinarySecurityTokenElement.setAttribute("xmlns:wsu", WSU_NAMESPACE);
84              wsseBinarySecurityTokenElement.setAttribute("xmlns:wsst",
85                      "http://www.ibm.com/websphere/appserver/tokentype");
86              wsseBinarySecurityTokenElement.setAttribute("wsu:Id", "ltpa_20");
87              wsseBinarySecurityTokenElement.setAttribute("ValueType", "wsst:LTPAv2");
88              wsseBinarySecurityTokenElement.appendChild(document.createTextNode(securityToken));
89  
90              // Append BinarySecurityToken to Security section
91              wsseSecurityElement.appendChild(wsseBinarySecurityTokenElement);
92  
93              return wsseSecurityElement;
94          } catch (ParserConfigurationException e) {
95              // shouldn't happen...
96              throw new CmisRuntimeException("Could not build SOAP header: " + e.getMessage(), e);
97          }
98      }
99  
100     private String getSecurityToken() {
101         try {
102             Class<?> wsSubjectClass = ClassLoaderUtil.loadClass("com.ibm.websphere.security.auth.WSSubject");
103             Class<?> wsCredentialClass = ClassLoaderUtil.loadClass("com.ibm.websphere.security.cred.WSCredential");
104 
105             // Get current security subject
106             Method m = wsSubjectClass.getMethod("getRunAsSubject", new Class[0]);
107             Subject securitySubject = (Subject) m.invoke(null, new Object[0]);
108             if (securitySubject != null) {
109                 // Get all security credentials from the security subject
110                 Set<?> securityCredentials = securitySubject.getPublicCredentials(wsCredentialClass);
111 
112                 // Get the first credential
113                 Object securityCredential = securityCredentials.iterator().next();
114                 String user = invokeSecurityCredentialMethod(wsCredentialClass, securityCredential, "getSecurityName");
115 
116                 if (user.equalsIgnoreCase("UNAUTHENTICATED")) {
117                     if (LOG.isDebugEnabled()) {
118                         LOG.debug("User = UNAUTHENTICATED");
119                     }
120                     return null;
121                 }
122 
123                 byte[] token = invokeSecurityCredentialMethod(wsCredentialClass, securityCredential,
124                         "getCredentialToken");
125                 if (token == null) {
126                     return null;
127                 }
128 
129                 return Base64.encodeBytes(token);
130             }
131         } catch (Exception e) {
132             throw new CmisRuntimeException("Could not build SOAP header: " + e.getMessage(), e);
133         }
134 
135         return null;
136     }
137 
138     @SuppressWarnings("unchecked")
139     private <T> T invokeSecurityCredentialMethod(Class<?> credentialClass, Object securityCredential, String methodName)
140             throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
141         Method m = credentialClass.getMethod(methodName, new Class[0]);
142         return (T) m.invoke(securityCredential, new Object[0]);
143     }
144 
145     @Override
146     protected boolean getSendBasicAuth() {
147         return false;
148     }
149 
150     @Override
151     protected boolean getSendUsernameToken() {
152         return false;
153     }
154 }