1 |
|
package org.kuali.student.security.trust.service; |
2 |
|
|
3 |
|
import java.io.BufferedReader; |
4 |
|
import java.io.InputStreamReader; |
5 |
|
import java.io.StringWriter; |
6 |
|
import java.io.UnsupportedEncodingException; |
7 |
|
import java.net.HttpURLConnection; |
8 |
|
import java.net.URL; |
9 |
|
import java.net.URLEncoder; |
10 |
|
import java.util.HashMap; |
11 |
|
import java.util.List; |
12 |
|
import java.util.Map; |
13 |
|
|
14 |
|
import javax.jws.WebService; |
15 |
|
import javax.xml.bind.JAXBElement; |
16 |
|
import javax.xml.parsers.DocumentBuilder; |
17 |
|
import javax.xml.parsers.DocumentBuilderFactory; |
18 |
|
import javax.xml.transform.Transformer; |
19 |
|
import javax.xml.transform.TransformerFactory; |
20 |
|
import javax.xml.transform.dom.DOMSource; |
21 |
|
import javax.xml.transform.stream.StreamResult; |
22 |
|
|
23 |
|
import org.jasig.cas.client.util.CommonUtils; |
24 |
|
import org.jasig.cas.client.util.XmlUtils; |
25 |
|
import org.kuali.student.security.exceptions.KSSecurityException; |
26 |
|
import org.kuali.student.security.trust.dto.RequestSecurityTokenResponseCollectionType; |
27 |
|
import org.kuali.student.security.trust.dto.RequestSecurityTokenResponseType; |
28 |
|
import org.kuali.student.security.trust.dto.RequestSecurityTokenType; |
29 |
|
import org.kuali.student.security.util.SamlUtils; |
30 |
|
import org.opensaml.SAMLAssertion; |
31 |
|
import org.w3c.dom.Document; |
32 |
|
import org.w3c.dom.Element; |
33 |
|
import org.w3c.dom.Node; |
34 |
|
|
35 |
|
|
36 |
|
|
37 |
|
|
38 |
|
|
39 |
|
|
40 |
|
|
41 |
|
|
42 |
|
@WebService(endpointInterface = "org.kuali.student.security.trust.service.SecurityTokenService", serviceName = "SecurityTokenService", |
43 |
|
portName = "SecurityTokenService", targetNamespace = "http://schemas.xmlsoap.org/ws/2005/02/trust/wsdl") |
|
|
| 45.7% |
Uncovered Elements: 89 (164) |
Complexity: 38 |
Complexity Density: 0.34 |
|
44 |
|
public class SecurityTokenServiceImpl implements SecurityTokenService { |
45 |
|
|
46 |
|
public static final String WST_NS_05_02 = "http://schemas.xmlsoap.org/ws/2005/02/trust"; |
47 |
|
public static final String SAML_11_NS = "urn:oasis:names:tc:SAML:1.0:assertion"; |
48 |
|
|
49 |
|
|
50 |
|
private String casServerUrl; |
51 |
|
private String samlIssuerForUser; |
52 |
|
private String proxyCallBackUrl; |
53 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
54 |
1
|
public RequestSecurityTokenResponseCollectionType requestSecurityToken2(RequestSecurityTokenType request) throws KSSecurityException... |
55 |
|
{ |
56 |
1
|
return null; |
57 |
|
} |
58 |
|
|
|
|
| 65.6% |
Uncovered Elements: 31 (90) |
Complexity: 20 |
Complexity Density: 0.34 |
|
59 |
1
|
public RequestSecurityTokenResponseType requestSecurityToken(RequestSecurityTokenType request) throws KSSecurityException... |
60 |
|
{ |
61 |
|
|
62 |
1
|
String context = request.getContext(); |
63 |
1
|
List<Object> objects = request.getAny(); |
64 |
|
|
65 |
1
|
String tokenTypeUri = null; |
66 |
1
|
String requestTypeUri = null; |
67 |
1
|
String proxyTicketId = null; |
68 |
1
|
String proxyTargetService = null; |
69 |
|
|
70 |
1
|
for(Object o : objects){ |
71 |
|
|
72 |
4
|
if(o instanceof JAXBElement){ |
73 |
0
|
JAXBElement<?> e = (JAXBElement<?>)o; |
74 |
0
|
if( e.getName().getLocalPart().equalsIgnoreCase("TokenType")){ |
75 |
0
|
tokenTypeUri = (String)e.getValue(); |
76 |
|
} |
77 |
0
|
else if(e.getName().getLocalPart().equalsIgnoreCase("RequestType")) { |
78 |
0
|
requestTypeUri = (String)e.getValue(); |
79 |
|
} |
80 |
0
|
else if(e.getName().getLocalPart().equalsIgnoreCase("CasProxyTicket")) { |
81 |
0
|
proxyTicketId = (String)e.getValue(); |
82 |
|
} |
83 |
0
|
else if(e.getName().getLocalPart().equalsIgnoreCase("CasProxyTargetService")) { |
84 |
0
|
proxyTargetService = (String)e.getValue(); |
85 |
|
} |
86 |
|
|
87 |
|
|
88 |
4
|
} else if(o instanceof Element){ |
89 |
4
|
Element e = (Element)o; |
90 |
4
|
if( e.getLocalName().equalsIgnoreCase("TokenType")){ |
91 |
1
|
tokenTypeUri = e.getTextContent(); |
92 |
|
} |
93 |
3
|
else if(e.getLocalName().equalsIgnoreCase("RequestType")) { |
94 |
1
|
requestTypeUri = e.getTextContent(); |
95 |
|
} |
96 |
2
|
else if(e.getLocalName().equalsIgnoreCase("CasProxyTicket")) { |
97 |
1
|
proxyTicketId = e.getTextContent(); |
98 |
|
} |
99 |
1
|
else if(e.getLocalName().equalsIgnoreCase("CasProxyTargetService")) { |
100 |
1
|
proxyTargetService = e.getTextContent(); |
101 |
|
} |
102 |
|
} |
103 |
|
} |
104 |
|
|
105 |
|
|
106 |
|
|
107 |
1
|
RequestSecurityTokenResponseType rstr = new RequestSecurityTokenResponseType(); |
108 |
|
|
109 |
1
|
if(requestTypeUri == null){ |
110 |
0
|
throw new KSSecurityException("The element RequestType is required"); |
111 |
|
} |
112 |
1
|
if(proxyTicketId == null || proxyTargetService == null){ |
113 |
0
|
throw new KSSecurityException("The elements CasProxyTicket and CasProxyTargetService are required"); |
114 |
|
} |
115 |
|
|
116 |
|
|
117 |
|
|
118 |
1
|
if(context != null){ |
119 |
1
|
rstr.setContext(context); |
120 |
|
} |
121 |
|
|
122 |
1
|
if(tokenTypeUri == null){ |
123 |
|
|
124 |
0
|
tokenTypeUri = SAML_11_NS; |
125 |
|
} |
126 |
|
|
127 |
|
|
128 |
1
|
if(tokenTypeUri.equals(SAML_11_NS) && requestTypeUri.endsWith("/Issue") ){ |
129 |
|
|
130 |
1
|
Element tokenType = null; |
131 |
1
|
Element requestedSecurityToken = null; |
132 |
1
|
Document signedSAMLDoc = null; |
133 |
1
|
try{ |
134 |
|
|
135 |
1
|
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); |
136 |
|
|
137 |
|
|
138 |
1
|
dbf.setNamespaceAware(true); |
139 |
|
|
140 |
1
|
DocumentBuilder db = dbf.newDocumentBuilder(); |
141 |
1
|
Document doc = db.newDocument(); |
142 |
|
|
143 |
1
|
tokenType = doc.createElementNS(WST_NS_05_02, "TokenType"); |
144 |
1
|
tokenType.setTextContent(tokenTypeUri); |
145 |
|
|
146 |
1
|
requestedSecurityToken = doc.createElementNS(WST_NS_05_02, "RequestedSecurityToken"); |
147 |
|
|
148 |
1
|
String testProperty = System.getProperty("ks.test.securityTokenService.useCas", "true"); |
149 |
|
|
150 |
1
|
if(Boolean.valueOf(testProperty)){ |
151 |
0
|
signedSAMLDoc = validateCasProxyTicket(proxyTicketId, proxyTargetService); |
152 |
|
} else { |
153 |
|
|
154 |
1
|
signedSAMLDoc = getSamlPrincipal("WS Trust Service is in test mode"); |
155 |
|
} |
156 |
1
|
Node signedSAMLAssertion = signedSAMLDoc.getDocumentElement(); |
157 |
1
|
requestedSecurityToken.appendChild(doc.importNode(signedSAMLAssertion, true)); |
158 |
|
|
159 |
|
} catch(Exception e){ |
160 |
0
|
throw new KSSecurityException(e); |
161 |
|
} |
162 |
1
|
rstr.getAny().add(tokenType); |
163 |
1
|
rstr.getAny().add(requestedSecurityToken); |
164 |
|
} |
165 |
|
|
166 |
1
|
return rstr; |
167 |
|
} |
168 |
|
|
|
|
| 0% |
Uncovered Elements: 36 (36) |
Complexity: 5 |
Complexity Density: 0.17 |
|
169 |
0
|
private Document validateCasProxyTicket(String proxyTicketId, String proxyTargetService) throws KSSecurityException{... |
170 |
|
|
171 |
0
|
String url = constructUrl(proxyTicketId, proxyTargetService); |
172 |
0
|
HttpURLConnection conn = null; |
173 |
|
|
174 |
0
|
try { |
175 |
0
|
URL constructedUrl = new URL(url); |
176 |
0
|
conn = (HttpURLConnection) constructedUrl.openConnection(); |
177 |
|
|
178 |
0
|
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream())); |
179 |
|
|
180 |
0
|
String line; |
181 |
0
|
StringBuffer stringBuffer = new StringBuffer(255); |
182 |
0
|
String response; |
183 |
|
|
184 |
0
|
while ((line = in.readLine()) != null) { |
185 |
0
|
stringBuffer.append(line); |
186 |
|
} |
187 |
|
|
188 |
0
|
response = stringBuffer.toString(); |
189 |
0
|
String error = XmlUtils.getTextForElement(response, "authenticationFailure"); |
190 |
|
|
191 |
0
|
if (CommonUtils.isNotEmpty(error)) { |
192 |
|
|
193 |
0
|
throw new KSSecurityException(error); |
194 |
|
} |
195 |
|
|
196 |
0
|
String user = XmlUtils.getTextForElement(response, "user"); |
197 |
0
|
String pgt = XmlUtils.getTextForElement(response, "proxyGrantingTicket"); |
198 |
0
|
String proxies = XmlUtils.getTextForElement(response, "proxies"); |
199 |
|
|
200 |
0
|
Map<String,String> samlProperties = new HashMap<String,String>(); |
201 |
0
|
samlProperties.put("user", user.trim()); |
202 |
0
|
samlProperties.put("proxyGrantingTicket", pgt.trim()); |
203 |
0
|
samlProperties.put("proxies", proxies.trim()); |
204 |
0
|
samlProperties.put("samlIssuerForUser", samlIssuerForUser.trim()); |
205 |
|
|
206 |
0
|
SamlUtils.setSamlProperties(samlProperties); |
207 |
0
|
SAMLAssertion samlAssertion = SamlUtils.createAssertion(); |
208 |
|
|
209 |
0
|
Document signedSAML = SamlUtils.signAssertion(samlAssertion); |
210 |
0
|
return signedSAML; |
211 |
|
|
212 |
|
|
213 |
|
|
214 |
|
|
215 |
|
|
216 |
|
|
217 |
|
|
218 |
|
|
219 |
|
|
220 |
|
|
221 |
|
|
222 |
|
|
223 |
|
|
224 |
|
|
225 |
|
|
226 |
|
|
227 |
|
} catch (final Exception e) { |
228 |
0
|
throw new KSSecurityException(e); |
229 |
|
} finally { |
230 |
0
|
if (conn != null) { |
231 |
0
|
conn.disconnect(); |
232 |
|
} |
233 |
|
} |
234 |
|
} |
235 |
|
|
|
|
| 0% |
Uncovered Elements: 5 (5) |
Complexity: 3 |
Complexity Density: 1 |
|
236 |
0
|
private String constructUrl(String proxyTicketId, String proxyTargetService) throws KSSecurityException{... |
237 |
0
|
try { |
238 |
0
|
return this.casServerUrl + (this.casServerUrl.endsWith("/") ? "" : "/") + "proxyValidate" + "?ticket=" |
239 |
|
+ proxyTicketId + "&service=" + URLEncoder.encode(proxyTargetService, "UTF-8") |
240 |
|
+ "&pgtUrl=" + URLEncoder.encode(proxyCallBackUrl, "UTF-8"); |
241 |
|
} catch (UnsupportedEncodingException e) { |
242 |
0
|
throw new KSSecurityException(e); |
243 |
|
} |
244 |
|
} |
245 |
|
|
|
|
| 80% |
Uncovered Elements: 3 (15) |
Complexity: 3 |
Complexity Density: 0.23 |
|
246 |
1
|
private Document getSamlPrincipal(String principal) throws KSSecurityException{... |
247 |
1
|
try { |
248 |
1
|
Map<String,String> samlProperties = new HashMap<String,String>(); |
249 |
1
|
samlProperties.put("user", principal); |
250 |
1
|
samlProperties.put("proxyGrantingTicket", ""); |
251 |
1
|
samlProperties.put("proxies", ""); |
252 |
1
|
if(samlIssuerForUser == null){ |
253 |
1
|
samlProperties.put("samlIssuerForUser", "org.kuali.student.trust.sts"); |
254 |
|
}else{ |
255 |
0
|
samlProperties.put("samlIssuerForUser", samlIssuerForUser.trim()); |
256 |
|
} |
257 |
|
|
258 |
1
|
SamlUtils.setSamlProperties(samlProperties); |
259 |
1
|
SAMLAssertion samlAssertion = SamlUtils.createAssertion(); |
260 |
|
|
261 |
1
|
Document signedSAML = SamlUtils.signAssertion(samlAssertion); |
262 |
|
|
263 |
1
|
return signedSAML; |
264 |
|
|
265 |
|
} catch (final Exception e) { |
266 |
0
|
throw new KSSecurityException(e); |
267 |
|
} |
268 |
|
|
269 |
|
} |
270 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
271 |
0
|
public String getCasServerUrl() {... |
272 |
0
|
return casServerUrl; |
273 |
|
} |
274 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
275 |
0
|
public void setCasServerUrl(String casServerUrl) {... |
276 |
0
|
this.casServerUrl = casServerUrl; |
277 |
|
} |
278 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
279 |
0
|
public String getSamlIssuerForUser() {... |
280 |
0
|
return samlIssuerForUser; |
281 |
|
} |
282 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
283 |
0
|
public void setSamlIssuerForUser(String samlIssuerForUser) {... |
284 |
0
|
this.samlIssuerForUser = samlIssuerForUser; |
285 |
|
} |
286 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
287 |
0
|
public String getProxyCallBackUrl() {... |
288 |
0
|
return proxyCallBackUrl; |
289 |
|
} |
290 |
|
|
|
|
| 0% |
Uncovered Elements: 1 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
291 |
0
|
public void setProxyCallBackUrl(String proxyCallBackUrl) {... |
292 |
0
|
this.proxyCallBackUrl = proxyCallBackUrl; |
293 |
|
} |
294 |
|
} |