Clover Coverage Report - Kuali Student 1.1-SNAPSHOT (Aggregated)
Coverage timestamp: Thu Mar 3 2011 04:02:59 EST
../../../../../img/srcFileCovDistChart7.png 38% of files have more coverage
96   337   25   5.33
12   189   0.26   18
18     1.39  
1    
 
  SamlUtils       Line # 63 96 0% 25 49 61.1% 0.6111111
 
  (1)
 
1    /**
2    * Copyright 2010 The Kuali Foundation Licensed under the
3    * Educational Community License, Version 2.0 (the "License"); you may
4    * not use this file except in compliance with the License. You may
5    * obtain a copy of the License at
6    *
7    * http://www.osedu.org/licenses/ECL-2.0
8    *
9    * Unless required by applicable law or agreed to in writing,
10    * software distributed under the License is distributed on an "AS IS"
11    * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12    * or implied. See the License for the specific language governing
13    * permissions and limitations under the License.
14    */
15   
16    package org.kuali.student.security.util;
17   
18    import java.io.IOException;
19    import java.net.URL;
20    import java.security.KeyStore;
21    import java.security.KeyStoreException;
22    import java.security.NoSuchAlgorithmException;
23    import java.security.PrivateKey;
24    import java.security.PublicKey;
25    import java.security.UnrecoverableKeyException;
26    import java.security.cert.CertificateException;
27    import java.security.cert.X509Certificate;
28    import java.util.Arrays;
29    import java.util.Date;
30    import java.util.Map;
31   
32    import javax.xml.parsers.DocumentBuilder;
33    import javax.xml.parsers.DocumentBuilderFactory;
34    import javax.xml.parsers.ParserConfigurationException;
35    import javax.xml.transform.TransformerException;
36   
37    import org.apache.xml.security.exceptions.XMLSecurityException;
38    import org.apache.xml.security.keys.KeyInfo;
39    import org.apache.xml.security.signature.XMLSignature;
40    import org.apache.xml.security.signature.XMLSignatureException;
41    import org.apache.xml.security.transforms.Transforms;
42    import org.apache.xml.security.utils.Constants;
43    import org.apache.xpath.XPathAPI;
44    import org.opensaml.SAMLAssertion;
45    import org.opensaml.SAMLAttribute;
46    import org.opensaml.SAMLAttributeStatement;
47    import org.opensaml.SAMLAuthenticationStatement;
48    import org.opensaml.SAMLException;
49    import org.opensaml.SAMLNameIdentifier;
50    import org.opensaml.SAMLSubject;
51    import org.w3c.dom.DOMException;
52    import org.w3c.dom.Document;
53    import org.w3c.dom.Element;
54    import org.w3c.dom.Node;
55    import org.w3c.dom.NodeList;
56   
57    /**
58    * This is a description of what this class does - Rich don't forget to fill this in.
59    *
60    * @author Kuali Rice Team (kuali-rice@googlegroups.com)
61    *
62    */
 
63    public class SamlUtils {
64   
 
65  1 toggle static {
66  1 org.apache.xml.security.Init.init();
67    }
68   
69    //All the parameters for the keystore
70    private static String keystoreType;
71    private static String keystoreFile;
72    private static String keystorePass;
73    private static String privateKeyAlias;
74    private static String privateKeyPass;
75    private static String certificateAlias;
76   
77    private static ThreadLocal<Map<String,String>> samlPropertiesHolder = new ThreadLocal<Map<String,String>>();
78   
 
79  1 toggle public static SAMLAssertion createAssertion() throws SAMLException, CloneNotSupportedException{
80   
81  1 String user = getSamlProperties().get("user");
82  1 String pgt = getSamlProperties().get("proxyGrantingTicket");
83  1 String proxies = getSamlProperties().get("proxies");
84  1 String issuer = getSamlProperties().get("samlIssuerForUser");
85  1 String nameQualifier = getSamlProperties().get("samlIssuerForUser");
86   
87  1 SAMLAssertion assertion = new SAMLAssertion();
88  1 assertion.setIssuer(issuer);
89   
90    // prepare subject
91  1 SAMLNameIdentifier nameId = new SAMLNameIdentifier(user, nameQualifier, "");
92  1 String[] confirmationMethods = {SAMLSubject.CONF_SENDER_VOUCHES};
93  1 SAMLSubject subject = new SAMLSubject();
94  1 subject.setNameIdentifier(nameId);
95  1 subject.setConfirmationMethods(Arrays.asList(confirmationMethods));
96   
97    // prepare auth statement
98  1 SAMLAuthenticationStatement authStmt = new SAMLAuthenticationStatement();
99  1 authStmt.setAuthInstant(new Date());
100  1 authStmt.setAuthMethod(SAMLAuthenticationStatement.AuthenticationMethod_Password);
101  1 authStmt.setSubject(subject);
102   
103    // prepare attributes
104  1 SAMLAttributeStatement attrStatement = new SAMLAttributeStatement();
105  1 SAMLAttribute attr1 = new SAMLAttribute();
106  1 attr1.setName("proxyGrantingTicket");
107  1 attr1.setNamespace("http://student.kuali.org/wsdl/security/saml");
108   
109  1 SAMLAttribute attr2 = new SAMLAttribute();
110  1 attr2.setName("proxies");
111  1 attr2.setNamespace("http://student.kuali.org/wsdl/security/saml");
112   
113  1 attr1.addValue(pgt);
114  1 attr2.addValue(proxies);
115   
116  1 attrStatement.addAttribute(attr1);
117  1 attrStatement.addAttribute(attr2);
118   
119  1 SAMLSubject subjectInAttr = (SAMLSubject)subject.clone();
120  1 attrStatement.setSubject(subjectInAttr);
121   
122    // prepare Assertion
123  1 assertion.addStatement(authStmt);
124  1 assertion.addStatement(attrStatement);
125   
126  1 return assertion;
127    }
128   
 
129  1 toggle public static void setSamlProperties(Map<String, String> samlProperties){
130    //this.samlProperties = samlProperties;
131  1 SamlUtils.samlPropertiesHolder.set(samlProperties);
132    }
133   
 
134  5 toggle public static Map<String, String> getSamlProperties() {
135    //return samlProperties;
136  5 return SamlUtils.samlPropertiesHolder.get();
137    }
138   
 
139  1 toggle public static Document signAssertion(SAMLAssertion assertion) throws XMLSecurityException, KeyStoreException,
140    NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableKeyException,
141    ParserConfigurationException, DOMException, SAMLException {
142  1 Constants.setSignatureSpecNSprefix("ds");
143   
144  1 ClassLoader classLoader = SamlUtils.class.getClassLoader();
145  1 URL url = classLoader.getResource(keystoreFile);
146   
147    //load the keystore
148  1 KeyStore ks = KeyStore.getInstance(keystoreType);
149  1 ks.load(url.openStream(), keystorePass.toCharArray());
150   
151    //get the private key for signing.
152  1 PrivateKey privateKey = (PrivateKey) ks.getKey(privateKeyAlias, privateKeyPass.toCharArray());
153   
154  1 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
155   
156    //XML Signature needs to be namespace aware
157  1 dbf.setNamespaceAware(true);
158   
159  1 DocumentBuilder db = dbf.newDocumentBuilder();
160  1 Document doc = db.newDocument();
161   
162  1 Element root = doc.createElementNS("http://student.kuali.org", "ks:KSSecureToken");
163  1 root.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:ks", "http://student.kuali.org");
164   
165  1 doc.appendChild(root);
166    // append the SAML assertion to the root.
167  1 root.appendChild(assertion.toDOM(doc));
168   
169  1 XMLSignature sig = new XMLSignature(doc, null, XMLSignature.ALGO_ID_SIGNATURE_RSA);
170    //XMLSignature.ALGO_ID_SIGNATURE_DSA);
171   
172    //Append the signature element to the root element before signing because
173    //this is going to be an enveloped signature.
174    //This means the signature is going to be enveloped by the document.
175    //Two other possible forms are enveloping where the document is inside the
176    //signature and detached where they are seperate.
177    //Note that they can be mixed in 1 signature with seperate references as
178    //shown below.
179  1 root.appendChild(sig.getElement());
180   
181    //create the transforms object for the Document/Reference
182  1 Transforms transforms = new Transforms(doc);
183   
184    //First we have to strip away the signature element (it's not part of the
185    //signature calculations). The enveloped transform can be used for this.
186  1 transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE);
187    //Part of the signature element needs to be canonicalized. It is a kind
188    //of normalizing algorithm for XML. For more information please take a
189    //look at the W3C XML Digital Signature webpage.
190  1 transforms.addTransform(Transforms.TRANSFORM_C14N_WITH_COMMENTS);
191    //Add the above Document/Reference
192  1 sig.addDocument("", transforms, Constants.ALGO_ID_DIGEST_SHA1);
193   
194   
195    //Add in the KeyInfo for the certificate that we used the private key of
196  1 X509Certificate cert = (X509Certificate) ks.getCertificate(certificateAlias);
197   
198  1 sig.addKeyInfo(cert);
199  1 sig.addKeyInfo(cert.getPublicKey());
200    // Sign the document
201  1 sig.sign(privateKey);
202   
203  1 return doc;
204    }
205   
 
206  0 toggle public static SAMLAssertion unsignAssertion(Document doc) throws TransformerException, XMLSecurityException, SAMLException {
207  0 boolean validSig = false;
208  0 Element nscontext = doc.createElementNS(null, "namespaceContext");
209  0 nscontext.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:ds", Constants.SignatureSpecNS);
210   
211  0 Element sigElement = (Element) XPathAPI.selectSingleNode(doc, "//ds:Signature[1]", nscontext);
212   
213  0 XMLSignature signature = new XMLSignature(sigElement, null);
214   
215  0 KeyInfo ki = signature.getKeyInfo();
216   
217  0 if (ki != null) {
218  0 X509Certificate cert = ki.getX509Certificate();
219   
220  0 if (cert != null) {
221  0 validSig = signature.checkSignatureValue(cert);
222   
223    } else {
224  0 PublicKey pk = ki.getPublicKey();
225   
226  0 if (pk != null) {
227  0 validSig = signature.checkSignatureValue(pk);
228   
229    } else {
230  0 throw new XMLSignatureException("Could not find a certificate or a public key in the message, can't check the signature");
231    }
232    }
233    } else {
234  0 throw new XMLSignatureException("Could not find a KeyInfo element in message");
235    }
236   
237    // if the signature is valid get the assertion and return it.
238  0 if(validSig){
239  0 NodeList nodeList = doc.getDocumentElement().getChildNodes();
240  0 Node childNode = null;
241   
242  0 for(int i=0; i < nodeList.getLength(); i++){
243  0 childNode = nodeList.item(i);
244  0 if((childNode.getNodeName().equals("Assertion")) && (childNode.getNodeType() == Node.ELEMENT_NODE)){
245  0 SAMLAssertion assertion = new SAMLAssertion((Element)childNode);
246  0 return assertion;
247    }
248    }
249    }
250   
251  0 throw new XMLSignatureException("The message signature was invalid");
252    }
253   
254    /**
255    * @return the keystoreType
256    */
 
257  0 toggle public String getKeystoreType() {
258  0 return keystoreType;
259    }
260   
261    /**
262    * @param keystoreType the keystoreType to set
263    */
 
264  1 toggle public void setKeystoreType(String keystoreType) {
265  1 SamlUtils.keystoreType = keystoreType;
266    }
267   
268    /**
269    * @return the keystoreFile
270    */
 
271  0 toggle public String getKeystoreFile() {
272  0 return keystoreFile;
273    }
274   
275    /**
276    * @param keystoreFile the keystoreFile to set
277    */
 
278  1 toggle public void setKeystoreFile(String keystoreFile) {
279  1 SamlUtils.keystoreFile = keystoreFile;
280    }
281   
282    /**
283    * @return the keystorePass
284    */
 
285  0 toggle public String getKeystorePass() {
286  0 return keystorePass;
287    }
288   
289    /**
290    * @param keystorePass the keystorePass to set
291    */
 
292  1 toggle public void setKeystorePass(String keystorePass) {
293  1 SamlUtils.keystorePass = keystorePass;
294    }
295   
296    /**
297    * @return the privateKeyAlias
298    */
 
299  0 toggle public String getPrivateKeyAlias() {
300  0 return privateKeyAlias;
301    }
302   
303    /**
304    * @param privateKeyAlias the privateKeyAlias to set
305    */
 
306  1 toggle public void setPrivateKeyAlias(String privateKeyAlias) {
307  1 SamlUtils.privateKeyAlias = privateKeyAlias;
308    }
309   
310    /**
311    * @return the privateKeyPass
312    */
 
313  0 toggle public String getPrivateKeyPass() {
314  0 return privateKeyPass;
315    }
316   
317    /**
318    * @param privateKeyPass the privateKeyPass to set
319    */
 
320  1 toggle public void setPrivateKeyPass(String privateKeyPass) {
321  1 SamlUtils.privateKeyPass = privateKeyPass;
322    }
323   
324    /**
325    * @return the certificateAlias
326    */
 
327  0 toggle public String getCertificateAlias() {
328  0 return certificateAlias;
329    }
330   
331    /**
332    * @param certificateAlias the certificateAlias to set
333    */
 
334  1 toggle public void setCertificateAlias(String certificateAlias) {
335  1 SamlUtils.certificateAlias = certificateAlias;
336    }
337    }