CAS Unit Tests
Clover coverage report - CAS Unit Tests
Coverage timestamp: Mon Jul 4 2005 18:13:17 CDT
file stats: LOC: 522   Methods: 12
NCLOC: 364   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
PermissionsEvaluator.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.databaseAccess;
 12   
 13    import java.util.Vector;
 14   
 15    import java.sql.ResultSet;
 16    import java.sql.SQLException;
 17    import java.sql.Connection;
 18    import java.sql.Statement;
 19   
 20    import org.globus.cas.utils.CasStringUtils;
 21   
 22    import org.globus.cas.impl.CasConstants;
 23   
 24    import org.globus.cas.types.PolicyData;
 25    import org.globus.cas.types.UserData;
 26    import org.globus.cas.types.ObjectData;
 27    import org.globus.cas.types.ArrayOfString;
 28   
 29    import org.globus.cas.impl.service.ObjectComparison;
 30   
 31    import org.apache.commons.logging.Log;
 32    import org.apache.commons.logging.LogFactory;
 33   
 34    import org.globus.util.I18n;
 35   
 36    /**
 37    * Checks for presence of policy in CAS database based on
 38    * super user, group presence of user, action or object.
 39    * These are only internal permissions and not used while assessing
 40    * external policies.
 41    */
 42    public class PermissionsEvaluator {
 43   
 44    static Log logger =
 45    LogFactory.getLog(PermissionsEvaluator.class.getName());
 46   
 47    private static I18n i18n =
 48    I18n.getI18n("org.globus.cas.impl.databaseAccess.errors",
 49    PermissionsEvaluator.class.getClassLoader());
 50   
 51    static final String baseQuery = ("select" + CasDBConstants.COL_POLICY_ID
 52    + " from" + CasDBConstants.TABLE_POLICY
 53    + " where ");
 54   
 55    /**
 56    * Method returns true if there is a policy in the CAS database that
 57    * sematically is equivalent to the policy data. The super user check
 58    * is done and if the user is a superuser then the policy is accepted
 59    */
 60  0 public static boolean userHasPermissions(String userNick,
 61    PolicyData policyData)
 62    throws CasDBException {
 63  0 logger.debug("userHasPermissions " + userNick + " does not ignore "
 64    + "super user");
 65  0 return userHasPermissions(userNick, policyData, false);
 66    }
 67   
 68    /**
 69    * Method returns true if there is a policy in the CAS databse that
 70    * sematically is equivalent to the policy data. The super user check
 71    * is done only if the boolean parameter is false. If the user is a
 72    * superuser then the policy is accepted
 73    */
 74  0 public static boolean userHasPermissions(String userNick,
 75    PolicyData policyData,
 76    boolean ignoreSuperUser)
 77    throws CasDBException {
 78  0 logger.debug("userHasPermissions " + userNick + " ignore super user "
 79    + ignoreSuperUser);
 80   
 81  0 UserData userData = (UserData)UserDataHandler.retrieveObject(userNick);
 82  0 ArrayOfString arrayOfGpnames = userData.getGroupNames();
 83  0 if (arrayOfGpnames != null) {
 84  0 logger.debug("gpNames is not null");
 85  0 String[] gpNames = arrayOfGpnames.getStrings();
 86  0 for (int i=0; i<gpNames.length; i++) {
 87  0 logger.debug("gpNames " + gpNames[i]);
 88  0 policyData.setUserGroupName(gpNames[i]);
 89  0 if (hasPermissions(policyData, ignoreSuperUser)) {
 90  0 return true;
 91    }
 92    }
 93    }
 94  0 return false;
 95    }
 96   
 97    /**
 98    * Returns true if the userGroup can perform actionSpec on objectSpec
 99    * Algorithm
 100    * If ignoreSuperUser is false
 101    * - Check if the given userGroup has cas/superuser on casServer.
 102    * Return true if yes.
 103    * Check if the community has permisions on objectSpec to do actionSpec
 104    * Return true if yes
 105    * Check if the actual userGroup itslef has permission on objectSpec
 106    * for actionSpec
 107    */
 108  0 public static boolean hasPermissions(PolicyData policyData,
 109    boolean ignoreSuperUser)
 110    throws CasDBException {
 111   
 112  0 logger.debug("hasPermissions called");
 113  0 logger.debug("Sent in policy Data " +
 114    CasStringUtils.policyToString(policyData));
 115   
 116  0 String userGroupName = policyData.getUserGroupName();
 117  0 logger.debug("userGroupName is " + userGroupName);
 118   
 119    // superuser - say yes always.
 120  0 String userQuery = queryStringForUser(userGroupName);
 121  0 logger.debug("User query " + userQuery);
 122   
 123  0 if (!ignoreSuperUser) {
 124  0 if (isSuperUser(userQuery))
 125  0 return true;
 126  0 logger.debug("not a superUser");
 127    }
 128    else
 129  0 logger.debug("Super user ignored");
 130   
 131    // grantAll - say yes always
 132  0 if (hasGrantAllPermissions(userQuery, policyData))
 133  0 return true;
 134  0 logger.debug("not grant all");
 135   
 136    // check if community permissions cover the action/object
 137  0 String actionQuery =
 138    queryStringForAction(policyData.getActionSpec(),
 139    policyData.getActionSpecDesc());
 140  0 logger.debug("action query " + actionQuery);
 141  0 if (hasCommunityPermissions(policyData, actionQuery))
 142  0 return true;
 143  0 logger.debug("no community permissions");
 144   
 145    // check if permission on the actual policy data covers it
 146  0 return userGroupHasPermissions(policyData, userQuery, actionQuery);
 147    }
 148   
 149    /**
 150    * Checks of the userGroupName given has cas/superuser permissions on
 151    * casServer. The object comparison has to be exact here and so no
 152    * wildcard issues.
 153    */
 154  0 private static boolean isSuperUser(String queryForUser)
 155    throws CasDBException {
 156   
 157  0 StringBuffer suBuf = new StringBuffer(baseQuery);
 158  0 suBuf.append(queryForUser);
 159   
 160    // FIXME - can cas/superuser be in an action group
 161    // and object "casServer"
 162    // be as a part of a group
 163    // get action id for "cas/superuser"
 164  0 int suActionId = ServiceTypeActionHandler.getServiceActionId(
 165    CasConstants.SERVICETYPE_CAS,
 166    CasConstants.ACTION_SU);
 167  0 if (suActionId == -1) {
 168  0 logger.debug(CasConstants.SERVICETYPE_CAS + "/"
 169    + CasConstants.ACTION_SU + " is not in the database");
 170  0 return false;
 171    }
 172  0 int suObjectId =
 173    ObjectDataHandler.getObjectId(
 174    CasConstants.OBJECT_SELF,
 175    CasConstants.NAMESPACE_SELF);
 176  0 if (suObjectId == -1) {
 177  0 logger.debug(CasConstants.OBJECT_SELF + "/"
 178    + CasConstants.NAMESPACE_SELF + "is not in database");
 179  0 return false;
 180    }
 181   
 182  0 String superuserQuery = " and ((" + CasDBConstants.COL_ACTION_SPEC
 183    + "='" + suActionId + "') and ("
 184    + CasDBConstants.COL_ACTION_SPEC_DESC
 185    + "='" + CasConstants.SERVICEACTION_SPEC + "')) and (("
 186    + CasDBConstants.COL_OBJECT_SPEC + "='" + suObjectId + "') and ("
 187    + CasDBConstants.COL_OBJECT_SPEC_DESC + "='"
 188    + CasConstants.OBJECT_SPEC + "'))";
 189   
 190  0 suBuf.append(superuserQuery);
 191  0 logger.debug("superUserQuery " + suBuf.toString());
 192  0 return (CasDBStorage.rowExists(suBuf.toString()));
 193    }
 194   
 195    /**
 196    * Returns true if the community or user has grantAll permissions on the
 197    * the object. Query needs to deal with "objects" differently since their
 198    * comparison is not trivial
 199    */
 200  0 private static boolean hasGrantAllPermissions(String userQuery,
 201    PolicyData policyData)
 202    throws CasDBException {
 203   
 204  0 StringBuffer grantAllBuf = new StringBuffer(baseQuery);
 205   
 206  0 int grantAllId = ServiceTypeActionHandler.getServiceActionId(
 207    CasConstants.SERVICETYPE_CAS,
 208    CasConstants.ACTION_GRANTALL);
 209  0 if (grantAllId == -1) {
 210  0 logger.debug(CasConstants.SERVICETYPE_CAS + "/"
 211    + CasConstants.ACTION_GRANTALL + " is not in the "
 212    + "database");
 213  0 return false;
 214    }
 215    // action query
 216  0 String actionQuery = "((" + CasDBConstants.COL_ACTION_SPEC + "='"
 217    + grantAllId + "') and (" + CasDBConstants.COL_ACTION_SPEC_DESC
 218    + "='" + CasConstants.SERVICEACTION_SPEC + "'))";
 219  0 grantAllBuf.append(userQuery).append(" and ");
 220  0 grantAllBuf.append(actionQuery);
 221  0 logger.debug("Grant all query before object " + grantAllBuf.toString());
 222  0 String objectSpecDesc = policyData.getObjectSpecDesc();
 223  0 String objectSpec = policyData.getObjectSpec();
 224    // check of object has permissions because of its group membership
 225  0 if (qualifiesOnGroupPermissions(userQuery, actionQuery, objectSpec,
 226    objectSpecDesc))
 227  0 return true;
 228  0 logger.debug("Does not qualify on group permissions");
 229    // if it is not object
 230  0 if (!objectSpecDesc.equals(CasConstants.OBJECT_SPEC)) {
 231  0 grantAllBuf.append(" and ").append(queryStringForNonObject(objectSpec,objectSpecDesc));
 232  0 logger.debug("If not object: grantAll query "
 233    + grantAllBuf.toString());
 234  0 return (CasDBStorage.rowExists(grantAllBuf.toString()));
 235    }
 236    else { // object
 237  0 logger.debug("Check permission on object");
 238    // check if object as such qualifies
 239  0 if (qualifiesOnObjectPermissions(userQuery, actionQuery,
 240    objectSpec))
 241  0 return true;
 242    }
 243  0 return false;
 244    }
 245   
 246    /**
 247    * Returns true if the community has permissions on objectSpec to do
 248    * actionSpec. Query needs to deal with "objects" differently since
 249    * their comparison is not trivial
 250    */
 251  0 private static boolean hasCommunityPermissions(PolicyData policyData,
 252    String actionQuery)
 253    throws CasDBException {
 254   
 255  0 StringBuffer communityBuf = new StringBuffer(baseQuery);
 256   
 257    // community user query
 258  0 String communityUserQuery = "(" + CasDBConstants.COL_USERGP_NAME + "='"
 259    + CasConstants.USER_COMMUNITY + "')";
 260  0 communityBuf.append(communityUserQuery).append(" and ");
 261  0 communityBuf.append(actionQuery);
 262  0 logger.debug("Community query before object "
 263    + communityBuf.toString());
 264  0 String objectSpec = policyData.getObjectSpec();
 265  0 String objectSpecDesc = policyData.getObjectSpecDesc();
 266    // check of object has permissions because of its group membership
 267  0 if (qualifiesOnGroupPermissions(communityUserQuery, actionQuery,
 268    objectSpec, objectSpecDesc))
 269  0 return true;
 270  0 logger.debug("Does not qualify on group permissions");
 271    // if it is not object
 272  0 if (!objectSpecDesc.equals(CasConstants.OBJECT_SPEC)) {
 273  0 communityBuf.append(" and ").append(queryStringForNonObject(objectSpec, objectSpecDesc));
 274  0 logger.debug("If not object: Community query "
 275    + communityBuf.toString());
 276  0 return (CasDBStorage.rowExists(communityBuf.toString()));
 277    }
 278    else { // object
 279  0 logger.debug("Check object permissions");
 280    // check if object as such qualifies
 281  0 if (qualifiesOnObjectPermissions(communityUserQuery, actionQuery,
 282    objectSpec))
 283  0 return true;
 284    }
 285  0 return false;
 286    }
 287   
 288    /**
 289    * Returns true if the actin userGroup in policyData has permission for
 290    * actionSpec on objectSpec. Query needs to deal with "objects" differently
 291    * since their comparison is not trivial
 292    */
 293  0 private static boolean userGroupHasPermissions(PolicyData policyData,
 294    String userQuery,
 295    String actionQuery)
 296    throws CasDBException {
 297   
 298  0 String objectSpec = policyData.getObjectSpec();
 299  0 String objectSpecDesc = policyData.getObjectSpecDesc();
 300    // check of object has permissions because of its group membership
 301  0 if (qualifiesOnGroupPermissions(userQuery, actionQuery, objectSpec,
 302    objectSpecDesc))
 303  0 return true;
 304   
 305    // objectSpec is not object
 306  0 if (!objectSpecDesc.equals(CasConstants.OBJECT_SPEC)) {
 307  0 StringBuffer permBuf = new StringBuffer(baseQuery);
 308  0 permBuf.append(userQuery).append(" and ").append(actionQuery);
 309  0 permBuf.append(" and ").append(queryStringForNonObject(objectSpec,objectSpecDesc));
 310  0 logger.debug("Perm query " + permBuf.toString());
 311  0 return (CasDBStorage.rowExists(permBuf.toString()));
 312    }
 313    else { // object
 314  0 logger.debug("Check for permissions on the object");
 315    // check if object as such qualifies
 316  0 if (qualifiesOnObjectPermissions(userQuery, actionQuery,
 317    objectSpec)) {
 318  0 return true;
 319    }
 320    }
 321  0 return false;
 322    }
 323   
 324    /**
 325    * Checks if this object has permission becuase a group it belongs to has
 326    * permissions.
 327    */
 328  0 private static boolean qualifiesOnGroupPermissions(String userQuery,
 329    String actionQuery,
 330    String objectSpec,
 331    String objectSpecDesc)
 332    throws CasDBException {
 333   
 334  0 String objectQuery = "((" + CasDBConstants.COL_OBJECT_SPEC_DESC + "='"
 335    + CasConstants.OBJECTGP_SPEC + "') and ("
 336    + CasDBConstants.COL_OBJECT_SPEC + " in (select"
 337    + CasDBConstants.COL_OBJECTGP_NAME + " from"
 338    + CasDBConstants.TABLE_OBJECTGP_ENTRY + " where"
 339    + CasDBConstants.COL_OBJECT_SPEC
 340    + "='" + objectSpec + "' and "
 341    + CasDBConstants.COL_OBJECT_SPEC_DESC + "='"
 342    + objectSpecDesc + "')))";
 343  0 StringBuffer query = new StringBuffer(baseQuery);
 344  0 query.append(userQuery).append(" and " ).append(actionQuery).append(" and ").append(objectQuery);
 345  0 logger.debug("Qualifies on groupPermission query " + objectQuery);
 346  0 return CasDBStorage.rowExists(query.toString());
 347    }
 348   
 349    // FIXME - split this as exact and non-exact comparison methods.
 350    /**
 351    * Checks if the object itself has permissions.
 352    * Needs to run through comparison using the algorithm specified
 353    */
 354  0 private static boolean qualifiesOnObjectPermissions(String userQuery,
 355    String actionQuery,
 356    String objectSpec)
 357    throws CasDBException {
 358   
 359    // get a list of all policyIds that satisfy user, action and are on
 360    // objects
 361  0 StringBuffer qualifiedObjectQuery =
 362    new StringBuffer("select * from" + CasDBConstants.TABLE_POLICY
 363    + " where ");
 364  0 String objectQuery = "(" + CasDBConstants.COL_OBJECT_SPEC_DESC + "='"
 365    + CasConstants.OBJECT_SPEC + "')";
 366  0 qualifiedObjectQuery.append(userQuery).append(" and ")
 367    .append(actionQuery).append(" and ").append(objectQuery);
 368  0 logger.debug("Qualifies object permissions: "
 369    + qualifiedObjectQuery.toString());
 370    // FIXME policy id is not need - left for debugging
 371  0 Vector policyIds = null;
 372  0 Vector objectIds = null;
 373  0 Connection connection = CasDBStorage.getDBConnection();
 374  0 Statement statement = null;
 375  0 ResultSet resultSet = null;
 376  0 try {
 377  0 statement = connection.createStatement();
 378  0 resultSet = statement.executeQuery(qualifiedObjectQuery.toString());
 379  0 if ((resultSet!=null) && (resultSet.next())) {
 380    // policy id is not needed
 381  0 policyIds = new Vector(resultSet.getFetchSize());
 382  0 objectIds = new Vector(resultSet.getFetchSize());
 383  0 int index = 0;
 384  0 do {
 385  0 policyIds.add(resultSet.getString(
 386    CasDBConstants.COL_POLICY_ID.trim()));
 387  0 objectIds.add(resultSet.getString(
 388    CasDBConstants.COL_OBJECT_SPEC.trim()));
 389  0 index++;
 390  0 } while (resultSet.next());
 391    }
 392    else {
 393  0 logger.debug("There are no policy Ids matching user/action "
 394    + " spec and are objects");
 395  0 return false;
 396    }
 397    }
 398    catch (SQLException exp) {
 399  0 logger.error(i18n.getMessage("policyErrObj",
 400    qualifiedObjectQuery.toString()),
 401    exp);
 402  0 throw new CasDBException(i18n.getMessage("policyErrObj",
 403    exp.getMessage()), exp);
 404    }
 405    finally {
 406    // returning connection irrespective of whether stmt
 407    // and result set are closed or not.
 408  0 CasDBStorage.returnDBConnection(connection);
 409  0 try {
 410  0 if (resultSet != null)
 411  0 resultSet.close();
 412  0 if (statement != null)
 413  0 statement.close();
 414    }
 415    catch (SQLException exp) {
 416  0 logger.warn(i18n.getMessage("policyErrObjClose"), exp);
 417    }
 418    }
 419   
 420    // run comparison on objects in PolicyData that satisfy user,
 421    // action and objectSpecDesc="object"
 422  0 ObjectData policyObjectData =
 423    ObjectDataHandler.retrieveObjectForId(objectSpec);
 424  0 String compAlgClassName =
 425    ObjectDataHandler.getComparisonAlg(
 426    policyObjectData.getObjectNamespace());
 427  0 if (compAlgClassName == null) {
 428  0 logger.error(i18n.getMessage("compAlgUnspec"));
 429  0 throw new CasDBException(i18n.getMessage("compAlgUnspec"));
 430    }
 431  0 logger.debug("Comparison alg is " + compAlgClassName);
 432    // Returned value is used as the name for class for comparison
 433  0 ObjectComparison objectComp =
 434    ObjectDataHandler.getComparisonClass(compAlgClassName);
 435  0 for (int i=0; i<objectIds.size(); i++) {
 436  0 if (objectComp.objectMatches(
 437    ObjectDataHandler.retrieveObjectForId(
 438    (String)objectIds.get(i)),
 439    policyObjectData)) {
 440  0 logger.debug("True because of policy Id "+ policyIds.get(i));
 441  0 return true;
 442    }
 443    }
 444  0 return false;
 445    }
 446   
 447    // Constructs query for user spec comparison
 448  0 private static String queryStringForUser(String userGroupName) {
 449  0 return "("+ CasDBConstants.COL_USERGP_NAME + "='" + userGroupName + "')";
 450    }
 451   
 452    // Constructs query for action spec comparison
 453  0 private static String queryStringForAction(String actionSpec,
 454    String actionSpecDesc) {
 455   
 456    // extra open bracket to be closed when appending
 457  0 String commonActionQuery = "(((" + CasDBConstants.COL_ACTION_SPEC
 458    + "='" + actionSpec + "') and ("
 459    + CasDBConstants.COL_ACTION_SPEC_DESC + "='" + actionSpecDesc
 460    + "'))";
 461  0 logger.debug("commonActionQuery " + commonActionQuery);
 462   
 463    // actionSpec
 464    // if its a serviceAction, check serviceAction and serviceActionGroup
 465  0 String actionQueryService = null;
 466  0 if (actionSpecDesc.equals(CasConstants.SERVICEACTION_SPEC)) {
 467  0 actionQueryService = " or (("+ CasDBConstants.COL_ACTION_SPEC_DESC
 468    + "='" + CasConstants.SERVICEACTIONGP_SPEC + "') and ("
 469    + CasDBConstants.COL_ACTION_SPEC + " in ( select "
 470    + CasDBConstants.COL_SERVICEACTIONGP_NAME + " from"
 471    + CasDBConstants.TABLE_SERVICEACTIONGP_ENTRY + " where"
 472    + CasDBConstants.COL_SERVICEACTION_ID + "=" + actionSpec + ")))";
 473  0 logger.debug("action actionQuery " + actionQueryService);
 474    }
 475   
 476  0 StringBuffer actionQuery = new StringBuffer(commonActionQuery);
 477  0 if (actionQueryService != null)
 478  0 actionQuery.append(actionQueryService).append(")");
 479    else
 480  0 actionQuery.append(")");
 481  0 return actionQuery.toString();
 482    }
 483   
 484    // Constructs query for objectSpec comparison provid objectSpecDesc is
 485    // not object
 486  0 private static String queryStringForNonObject(String objectSpec,
 487    String objectSpecDesc) {
 488   
 489    // Paranoid check: return null incase this method is called with
 490    // objectSpecDesc as object
 491  0 if (objectSpecDesc.equals(CasConstants.OBJECT_SPEC)) {
 492  0 logger.error("Cannot invoke this method with object spec");
 493  0 return null;
 494    }
 495   
 496    // extra bracket to be closed when appending
 497  0 String commonObjectQuery = "(((" + CasDBConstants.COL_OBJECT_SPEC
 498    + "='" + objectSpec + "') and ("
 499    + CasDBConstants.COL_OBJECT_SPEC_DESC + "='" + objectSpecDesc
 500    + "'))";
 501  0 logger.debug("commonObjectQuery " + commonObjectQuery);
 502   
 503    // if objectSpecDesc is user then include user groups
 504  0 String objectQueryUser = null;
 505  0 if (objectSpecDesc.equals(CasConstants.USER_SPEC)) {
 506  0 objectQueryUser = " or ((" + CasDBConstants.COL_OBJECT_SPEC_DESC
 507    + "='" + CasConstants.USERGP_SPEC + "') and ("
 508    + CasDBConstants.COL_OBJECT_SPEC + " in ( select "
 509    + CasDBConstants.COL_USERGP_NAME + " from"
 510    + CasDBConstants.TABLE_USERGP_ENTRY + " where"
 511    + CasDBConstants.COL_USER_NICKNAME + "='" + objectSpec + "')))";
 512  0 logger.debug("object userQuery " + objectQueryUser);
 513    }
 514   
 515  0 StringBuffer objectQuery = new StringBuffer(commonObjectQuery);
 516  0 if (objectQueryUser != null)
 517  0 objectQuery.append(objectQueryUser).append(")");
 518    else
 519  0 objectQuery.append(")");
 520  0 return objectQuery.toString();
 521    }
 522    }