CAS Unit Tests
Clover coverage report - CAS Unit Tests
Coverage timestamp: Mon Jul 4 2005 18:13:17 CDT
file stats: LOC: 459   Methods: 12
NCLOC: 352   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
CasProxyHelper.java 0% 0% 0% 0%
coverage
 1    /*
 2    * Portions of this file Copyright 1999-2005 University of Chicago
 3    * Portions of this file Copyright 1999-2005 The University of Southern California.
 4    *
 5    * This file or a portion of this file is licensed under the
 6    * terms of the Globus Toolkit Public License, found at
 7    * http://www.globus.org/toolkit/download/license.html.
 8    * If you redistribute this file, with or without
 9    * modifications, you must include this notice in the file.
 10    */
 11    package org.globus.cas.impl.client;
 12   
 13    import java.io.FileOutputStream;
 14    import java.io.PrintStream;
 15    import java.security.GeneralSecurityException;
 16    import java.security.cert.X509Certificate;
 17    import java.util.StringTokenizer;
 18    import java.util.Vector;
 19   
 20    import org.apache.axis.message.MessageElement;
 21   
 22    import org.opensaml.SAMLAction;
 23    import org.opensaml.SAMLAssertion;
 24    import org.opensaml.SAMLAuthorizationDecisionQuery;
 25    import org.opensaml.SAMLException;
 26    import org.opensaml.SAMLSubject;
 27    import org.w3c.dom.Element;
 28   
 29    import org.globus.axis.util.Util;
 30    import org.globus.cas.CASPortType;
 31    import org.globus.cas.faults.CasFault;
 32    import org.globus.cas.impl.CasConstants;
 33    import org.globus.wsrf.impl.security.SecurityMessageElement;
 34    import org.globus.cas.types.ArrayOfSAMLAuthzQueryType;
 35    import org.globus.cas.types.GetAssertionParam;
 36    import org.globus.cas.types.SAMLAuthzQueryType;
 37    import org.globus.common.CoGProperties;
 38    import org.globus.gsi.GSIConstants;
 39    import org.globus.gsi.GlobusCredential;
 40    import org.globus.gsi.GlobusCredentialException;
 41    import org.globus.gsi.X509Extension;
 42    import org.globus.gsi.X509ExtensionSet;
 43    import org.globus.gsi.bc.BouncyCastleCertProcessingFactory;
 44    import org.globus.wsrf.impl.security.authentication.Constants;
 45    import org.globus.wsrf.impl.security.SecurityMessageElement;
 46    import org.globus.wsrf.utils.FaultHelper;
 47   
 48    /**
 49    * Helper class to get a proxy embedded with CAS (SAML) assertions.
 50    */
 51    public class CasProxyHelper {
 52   
 53    boolean debug;
 54    String instanceURL;
 55    String serverIdentity;
 56   
 57    /**
 58    * @param instanceURL
 59    * Used to contact CAS service.
 60    * <br>Host authz is used and no debug information is printed.
 61    */
 62  0 public CasProxyHelper(String instanceURL) throws CasClientException {
 63  0 this(instanceURL, null, false);
 64    }
 65   
 66    /**
 67    * @param instanceURL
 68    * Used to contact CAS service.
 69    * @param debug
 70    * trace is printed is debug is set to true.
 71    * <br>Host authz is used.
 72    */
 73  0 public CasProxyHelper(String instanceURL, boolean debug)
 74    throws CasClientException {
 75  0 this(instanceURL, null, debug);
 76    }
 77   
 78    /**
 79    * @param instanceURL
 80    * Used to contact CAS service.
 81    * @param serverIdentity
 82    * Identity authz is done.
 83    * <br>No debug information is printed.
 84    */
 85  0 public CasProxyHelper(String instanceURL, String serverIdentity)
 86    throws CasClientException {
 87  0 this(instanceURL, serverIdentity, false);
 88    }
 89   
 90    /**
 91    * @param instanceURL
 92    * Used to contact CAS service.
 93    * @param serverIdentity
 94    * Identity authz is done.
 95    * @param debug
 96    * trace is printed is debug is set to true.
 97    */
 98  0 public CasProxyHelper(String instanceURL, String serverIdentity,
 99    boolean debug)
 100    throws CasClientException {
 101  0 if ((instanceURL == null) || (instanceURL.trim().equals("")))
 102  0 throw new CasClientException("Invalid instance URL "
 103    + instanceURL);
 104  0 this.instanceURL = instanceURL;
 105  0 this.serverIdentity = serverIdentity;
 106  0 this.debug = debug;
 107    }
 108   
 109    /**
 110    * @param debug
 111    * trace is printed if debug is set
 112    */
 113  0 public void setDebug(boolean debug) {
 114  0 this.debug = debug;
 115    }
 116   
 117    /**
 118    * @param params
 119    * Parameters for generating CAS assertion.
 120    * @return Path to the proxy file with embedded CAS assertions
 121    */
 122  0 public String getCasProxy(ClientParams params) throws CasClientException {
 123   
 124  0 String proxyFilename = params.getProxyFileName();
 125    // get credential
 126  0 GlobusCredential credential = getCredential(proxyFilename);
 127   
 128    // Set subject dn and trust anchor DN from proxy used.
 129  0 String clientDN = credential.getIdentity();
 130  0 printMessage(System.out, "Client DN is " + clientDN);
 131  0 String clientTADN = credential.getIssuer();
 132  0 printMessage(System.out, "Client cert TA DN is " + clientTADN);
 133   
 134    // Confirmation method
 135  0 Vector confMethods = new Vector(1);
 136  0 confMethods.add(CasConstants.X509_CONFIRMATION_METHOD);
 137   
 138    // SAML Subject
 139  0 SAMLSubject samlSubject = null;
 140  0 try {
 141  0 samlSubject =
 142    new SAMLSubject(clientDN, clientTADN, CasConstants.X509_FORMAT,
 143    confMethods, null, null);
 144    } catch (SAMLException exp) {
 145  0 String err = "Cannot constrct SAML Subject";
 146  0 printMessage(System.err, err + exp.toString());
 147    }
 148   
 149  0 ResourceActionsMap[] resActions = params.getResourceActionsMap();
 150    // Construct SAML query
 151  0 SAMLAuthzQueryType[] samlAnyQueries =
 152    getSAMLAuthzQueries(samlSubject, resActions);
 153   
 154  0 CasClientSetup clientSetup = new CasClientSetup();
 155    // Get casPort
 156  0 boolean trans = false;
 157  0 String securityType = params.getSecurityType();
 158  0 if (securityType == null) {
 159  0 if (instanceURL.startsWith("https")) {
 160  0 securityType = Constants.GSI_TRANSPORT;
 161    // register util.
 162  0 Util.registerTransport();
 163  0 trans = true;
 164    } else {
 165  0 securityType = Constants.GSI_SEC_MSG;
 166    }
 167    }
 168  0 String authzObject = clientSetup.getAuthzParamObject(trans);
 169  0 Object authzValue = clientSetup.getAuthzParamValue(trans,
 170    serverIdentity);
 171  0 CASPortType casPort =
 172    clientSetup.getCASPort(instanceURL, securityType,
 173    params.getProtectionType(), authzObject,
 174    authzValue);
 175   
 176  0 org.globus.cas.types.SAMLAssertion assertion = null;
 177  0 try {
 178  0 ArrayOfSAMLAuthzQueryType arrayOfSamlAuthz =
 179    new ArrayOfSAMLAuthzQueryType(samlAnyQueries);
 180   
 181  0 GetAssertionParam getAssertion = new GetAssertionParam();
 182  0 getAssertion.setLifetime(params.getAssertionLifetime());
 183  0 getAssertion.setSamlAuthzQuery(arrayOfSamlAuthz);
 184   
 185  0 assertion = casPort.getAssertion(getAssertion);
 186    } catch (CasFault casFault) {
 187  0 if (!debug) {
 188  0 String desc =
 189    (new FaultHelper(casFault)).getDescriptionAsString();
 190  0 System.err.println(desc);
 191    } else {
 192  0 System.err.println((new FaultHelper(casFault))
 193    .getStackTrace());
 194    }
 195  0 throw new CasClientException((new FaultHelper(casFault))
 196    .getDescriptionAsString());
 197    } catch (Exception exp) {
 198  0 if (debug) {
 199  0 System.err.println(exp.toString());
 200    } else {
 201  0 System.err.println(CasClientSetup.getErrorMsg(exp));
 202    }
 203  0 throw new CasClientException(exp);
 204    }
 205   
 206    // Get assertion.
 207  0 SAMLAssertion samlAssertion = parseAndVerifyAssertion(assertion);
 208    // Embed assertion
 209  0 return embedAssertionInCredential(samlAssertion, credential,
 210    proxyFilename,
 211    params.getCasProxyFileName(),
 212    params.getCasProxyTag());
 213    }
 214   
 215    // Embed assertion in the proxy.
 216  0 private String embedAssertionInCredential(SAMLAssertion samlAssertion,
 217    GlobusCredential credential,
 218    String proxyFilename,
 219    String casProxyFilename,
 220    String casProxyTag)
 221    throws CasClientException {
 222  0 if (samlAssertion == null) {
 223  0 System.out.println("Assertion is null.");
 224    // FIXME
 225  0 return null;
 226    }
 227   
 228  0 boolean critical = false;
 229  0 X509ExtensionSet extensionSet = new X509ExtensionSet();
 230  0 X509Extension extension =
 231    new X509Extension(CasConstants.OID, critical,
 232    samlAssertion.toString().getBytes());
 233  0 extensionSet.add(extension);
 234   
 235  0 BouncyCastleCertProcessingFactory certProcessingFactory =
 236    BouncyCastleCertProcessingFactory.getDefault();
 237   
 238    // Life time is set to the old proxy's life time
 239  0 Long lifetime = new Long(credential.getTimeLeft());
 240  0 printMessage(System.out, "lifetime " + lifetime);
 241  0 GlobusCredential newCredential = null;
 242  0 try {
 243  0 newCredential =
 244    certProcessingFactory.createCredential(
 245    credential.getCertificateChain(),
 246    credential.getPrivateKey(), 512 ,
 247    Integer.parseInt(lifetime.toString()),
 248    GSIConstants.GSI_3_IMPERSONATION_PROXY,
 249    extensionSet, null);
 250    } catch (GeneralSecurityException exp) {
 251  0 String err = "Error creating new credentials\n ";
 252  0 printMessage(System.err, err + exp.toString());
 253    }
 254   
 255  0 if (casProxyFilename == null) {
 256  0 if (casProxyTag == null)
 257  0 casProxyTag = CasConstants.CAS_PROXY_TAG;
 258  0 if (proxyFilename == null) {
 259  0 proxyFilename = CoGProperties.getDefault().getProxyFile();
 260    }
 261  0 casProxyFilename = proxyFilename + "." + casProxyTag;
 262    }
 263   
 264  0 printMessage(System.out, "New proxy filename " + casProxyFilename);
 265  0 try {
 266  0 newCredential.save(new FileOutputStream(casProxyFilename));
 267    } catch (Exception exp) {
 268  0 String err = "Error writing out CAS credential to "
 269    + casProxyFilename;
 270  0 printMessage(System.err, err + "\n" + exp.toString());
 271    }
 272   
 273  0 String permissionCommand = "chmod 600 " + casProxyFilename;
 274  0 Runtime runtime = Runtime.getRuntime();
 275  0 boolean success = true;
 276  0 try {
 277  0 Process process = runtime.exec(permissionCommand, null);
 278  0 int returnCode = process.waitFor();
 279  0 if (returnCode != 0)
 280  0 success = false;
 281    } catch(Exception e) {
 282  0 success = false;
 283    }
 284  0 if (!success) {
 285  0 System.out.println("Check permissions on proxy file, "
 286    + casProxyFilename);
 287    }
 288  0 printMessage(System.out, "New Proxy " + newCredential.toString());
 289   
 290  0 if (debug) {
 291  0 try {
 292  0 GlobusCredential newCred =
 293    new GlobusCredential(casProxyFilename);
 294  0 X509Certificate array[] = newCred.getCertificateChain();
 295  0 if ((array != null) && (array.length > 1)) {
 296  0 byte[] extensionVal =
 297    X509Extension.getExtensionValue(array[0],
 298    CasConstants.OID);
 299  0 if (extensionVal == null)
 300  0 System.out.println("No such OID found");
 301    else {
 302  0 String casPolicy = new String(extensionVal);
 303  0 System.out.println("CAS Policy " + casPolicy);
 304    }
 305    }
 306    else {
 307  0 System.err.println("Certificate array is null or "
 308    + "length < 1");
 309    }
 310    } catch (Exception exp) {
 311  0 System.err.println(exp);
 312    }
 313    }
 314  0 return casProxyFilename;
 315    }
 316   
 317    // Verify returned assertion signature.
 318  0 private SAMLAssertion
 319    parseAndVerifyAssertion(org.globus.cas.types.SAMLAssertion
 320    assertion) throws CasClientException {
 321  0 SAMLAssertion samlAssertion = null;
 322  0 if (assertion != null) {
 323  0 org.apache.xml.security.Init.init();
 324  0 try {
 325  0 MessageElement[] msgElement = assertion.get_any();
 326  0 samlAssertion = new SAMLAssertion(msgElement[0].getAsDOM());
 327    } catch (Exception exp) {
 328  0 String err = "Error extracting SAML Assertion object ";
 329  0 printMessage(System.err, err + "\n" + exp.toString());
 330  0 throw new CasClientException(err, exp);
 331    }
 332   
 333  0 printMessage(System.out, "SAML " + samlAssertion);
 334   
 335    // signature needs to be verified.
 336  0 try {
 337  0 samlAssertion.verify(false);
 338    } catch (SAMLException samlExp) {
 339  0 String err = "Could not verify signature on assertion. \n ";
 340  0 printMessage(System.err, err + samlExp.toString());
 341  0 throw new CasClientException(err, samlExp);
 342    }
 343    }
 344  0 return samlAssertion;
 345    }
 346   
 347    // Construct SAML Authz Query
 348  0 private SAMLAuthzQueryType[]
 349    getSAMLAuthzQueries(SAMLSubject samlSubject,
 350    ResourceActionsMap[] resActions)
 351    throws CasClientException {
 352   
 353  0 SAMLAuthzQueryType[] samlAnyQueries = null;
 354   
 355  0 if (resActions != null) {
 356  0 samlAnyQueries = new SAMLAuthzQueryType[resActions.length];
 357  0 for (int i=0; i<resActions.length; i++) {
 358  0 String resource = resActions[i].getResource();
 359  0 String[] actionStrs = resActions[i].getActions();
 360  0 Vector samlActions = new Vector(actionStrs.length);
 361  0 for (int j=0; j<actionStrs.length; j++) {
 362  0 samlActions.add(getSAMLActionObject(actionStrs[j]));
 363    }
 364  0 SAMLAuthorizationDecisionQuery samlAuthQuery = null;
 365  0 try {
 366  0 samlAuthQuery =
 367    new SAMLAuthorizationDecisionQuery(samlSubject,
 368    resource,
 369    samlActions,
 370    null);
 371    } catch (SAMLException samlExp) {
 372  0 String err = "Error constucting SAMLAuthzQuery \n";
 373  0 printMessage(System.err, err + "\n" + samlExp.toString());
 374  0 throw new CasClientException(err, samlExp);
 375    }
 376  0 samlAnyQueries[i] = new SAMLAuthzQueryType();
 377  0 samlAnyQueries[i].set_any(new MessageElement[] {
 378    new SecurityMessageElement((Element)samlAuthQuery.toDOM())});
 379    }
 380  0 return samlAnyQueries;
 381    } else {
 382    // set of all assertions
 383  0 String resourceWildcard = CasConstants.RESOURCE_WILDCARD;
 384  0 Vector wildCardActions = new Vector(1);
 385  0 SAMLAction wildCardAction = null;
 386  0 try {
 387  0 wildCardAction =
 388    new SAMLAction(CasConstants.ACTION_NS_WILDCARD,
 389    CasConstants.ACTION_WILDCARD);
 390    } catch (SAMLException samlExp) {
 391  0 String err = "Error constucting wildcard SAMLAction \n";
 392  0 printMessage(System.err, err + "\n" + samlExp.toString());
 393  0 throw new CasClientException(err, samlExp);
 394    }
 395  0 wildCardActions.add(wildCardAction);
 396  0 SAMLAuthorizationDecisionQuery samlAuthQuery = null;
 397  0 try {
 398  0 samlAuthQuery =
 399    new SAMLAuthorizationDecisionQuery(samlSubject,
 400    resourceWildcard,
 401    wildCardActions,
 402    null);
 403    } catch (SAMLException samlExp) {
 404  0 String err = "Error constucting SAML Authz decision query \n";
 405  0 printMessage(System.err, err + "\n" + samlExp.toString());
 406  0 throw new CasClientException(err, samlExp);
 407    }
 408  0 samlAnyQueries = new SAMLAuthzQueryType[1];
 409  0 samlAnyQueries[0] = new SAMLAuthzQueryType();
 410  0 samlAnyQueries[0].set_any(new MessageElement[] {
 411    new SecurityMessageElement((Element)samlAuthQuery.toDOM())});
 412    }
 413  0 return samlAnyQueries;
 414    }
 415   
 416    // Construct SAML Action
 417  0 private SAMLAction getSAMLActionObject(String actionStr)
 418    throws CasClientException {
 419   
 420  0 printMessage(System.out, "Action: " + actionStr);
 421  0 StringTokenizer strTok = new StringTokenizer(actionStr);
 422  0 try {
 423  0 if (strTok.countTokens() == 2) {
 424  0 return new SAMLAction(strTok.nextToken(),
 425    strTok.nextToken());
 426    }
 427    } catch (SAMLException samlExp) {
 428  0 String err = "Error constucting SAMLAction \n";
 429  0 printMessage(System.err, err + "\n" + samlExp.toString());
 430  0 throw new CasClientException(err, samlExp);
 431    }
 432  0 printMessage(System.err, "Bad action string: " + actionStr);
 433  0 throw new CasClientException("Bad action string: " + actionStr);
 434    }
 435   
 436  0 private GlobusCredential getCredential(String proxyFilename)
 437    throws CasClientException {
 438   
 439  0 GlobusCredential credential = null;
 440  0 try {
 441  0 if (proxyFilename == null) {
 442  0 credential = GlobusCredential.getDefaultCredential();
 443    } else {
 444  0 credential = new GlobusCredential(proxyFilename);
 445    }
 446    } catch (GlobusCredentialException exp) {
 447  0 String err = "Error loading default credential";
 448  0 printMessage(System.err, err + "/n" + exp.toString());
 449  0 throw new CasClientException(err, exp);
 450    }
 451  0 return credential;
 452    }
 453   
 454  0 private void printMessage(PrintStream stream, String msg) {
 455  0 if (debug) {
 456  0 stream.println(msg);
 457    }
 458    }
 459    }