Package org.eclipse.osgi.framework.internal.core

Source Code of org.eclipse.osgi.framework.internal.core.PermissionAdminImpl

/*******************************************************************************
* Copyright (c) 2003, 2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     IBM Corporation - initial API and implementation
*******************************************************************************/

package org.eclipse.osgi.framework.internal.core;

import java.io.*;
import java.net.URL;
import java.security.*;
import java.util.ArrayList;
import org.eclipse.osgi.framework.adaptor.BundleProtectionDomain;
import org.eclipse.osgi.framework.adaptor.PermissionStorage;
import org.eclipse.osgi.framework.debug.Debug;
import org.osgi.framework.AdminPermission;
import org.osgi.framework.FrameworkEvent;
import org.osgi.service.permissionadmin.PermissionAdmin;
import org.osgi.service.permissionadmin.PermissionInfo;

/**
* Permission Admin service for the OSGi specification.
*
* The Permission Admin service allows operators to
* manage the permissions of bundles. There is at most one Permission Admin
* service present in the Framework.
* <p>
* Access to the Permission Admin service is protected by
* corresponding
* <tt>ServicePermission</tt>. In addition the <tt>AdminPermission</tt>
* is required to actually set permissions.
*
* <p>Bundle permissions are managed using a permission table. A bundle's location
* serves as the key into this permission table. The value of a table entry is
* the set of permissions (of type <tt>PermissionInfo</tt>) granted to the
* bundle with the given location.
* A bundle may have an entry in the permission table prior to being installed
* in the Framework.
*
* <p>The permissions specified in <tt>setDefaultPermissions</tt> are used as the
* default
* permissions which are granted to all bundles that do not have an entry in
* the permission table.
*
* <p>Any changes to a bundle's permissions in the permission table will take
* effect no later than when bundle's <tt>java.security.ProtectionDomain</tt>
* is involved in a permission check, and will be made persistent.
*
* <p>Only permission classes on the system classpath or from an exported
* package are considered during a permission check.
* Additionally, only permission classes that are subclasses of
* <tt>java.security.Permission</tt> and define a 2-argument constructor
* that takes a <i>name</i> string and an <i>actions</i> string can be used.
* <p>
* Permissions implicitly granted by the Framework (for example, a bundle's
* permission to access its persistent storage area) cannot be changed, and
* are not reflected in the permissions returned by <tt>getPermissions</tt>
* and <tt>getDefaultPermissions</tt>.
*/
public class PermissionAdminImpl implements PermissionAdmin {
  private static final String ADMIN_IMPLIED_ACTIONS = AdminPermission.RESOURCE + ',' + AdminPermission.METADATA + ',' + AdminPermission.CLASS;

  /** framework object */
  protected Framework framework;

  /** permission storage object */
  protected PermissionStorage storage;

  /** The permissions to use if no other permissions can be determined */
  protected PermissionInfo[] defaultDefaultPermissionInfos;

  /** The basic implied permissions for a bundle */
  protected PermissionInfo[] baseImpliedPermissionInfos;

  /** The permission collection containing the default assigned permissions */
  protected BundleCombinedPermissions defaultAssignedPermissions;

  /**
   * Construstor.
   *
   * @param framework Framework object.
   */
  protected PermissionAdminImpl(Framework framework, PermissionStorage storage) {
    this.framework = framework;
    this.storage = storage;

    defaultDefaultPermissionInfos = getPermissionInfos(getClass().getResource(Constants.OSGI_DEFAULT_DEFAULT_PERMISSIONS));
    baseImpliedPermissionInfos = getPermissionInfos(getClass().getResource(Constants.OSGI_BASE_IMPLIED_PERMISSIONS));

    if (Debug.DEBUG && Debug.DEBUG_SECURITY) {
      Debug.println("Default default assigned bundle permissions"); //$NON-NLS-1$
      if (defaultDefaultPermissionInfos == null) {
        Debug.println("  <none>"); //$NON-NLS-1$
      } else {
        for (int i = 0; i < defaultDefaultPermissionInfos.length; i++) {
          Debug.println("  " + defaultDefaultPermissionInfos[i]); //$NON-NLS-1$
        }
      }

      Debug.println("Base implied bundle permissions"); //$NON-NLS-1$
      if (baseImpliedPermissionInfos == null) {
        Debug.println("  <none>"); //$NON-NLS-1$
      } else {
        for (int i = 0; i < baseImpliedPermissionInfos.length; i++) {
          Debug.println("  " + baseImpliedPermissionInfos[i]); //$NON-NLS-1$
        }
      }
    }

    defaultAssignedPermissions = new BundleCombinedPermissions(null);
    defaultAssignedPermissions.setAssignedPermissions(createDefaultAssignedPermissions(getDefaultPermissions()), true);
  }

  /**
   * Gets the permissions assigned to the bundle with the specified
   * location.
   *
   * @param location The location of the bundle whose permissions are to
   * be returned.
   *
   * @return The permissions assigned to the bundle with the specified
   * location, or <tt>null</tt> if that bundle has not been assigned any
   * permissions.
   */
  public PermissionInfo[] getPermissions(String location) {
    if (location == null) {
      throw new NullPointerException();
    }

    PermissionStorage storage = new org.eclipse.osgi.framework.internal.core.SecurePermissionStorage(this.storage);

    try {
      String[] data = storage.getPermissionData(location);

      if (Debug.DEBUG && Debug.DEBUG_SECURITY) {
        Debug.println("Getting permissions for location: " + location); //$NON-NLS-1$
        if (data == null) {
          Debug.println("  <none>"); //$NON-NLS-1$
        } else {
          for (int i = 0; i < data.length; i++) {
            Debug.println("  " + data[i]); //$NON-NLS-1$
          }
        }
      }

      return makePermissionInfo(data);
    } catch (IOException e) {
      framework.publishFrameworkEvent(FrameworkEvent.ERROR, framework.systemBundle, e);

      return null;
    }
  }

  /**
   * Assigns the specified permissions to the bundle with the specified
   * location.
   *
   * @param location The location of the bundle that will be assigned the
   *                 permissions.
   * @param permissions The permissions to be assigned, or <tt>null</tt>
   * if the specified location is to be removed from the permission table.
   * @exception SecurityException if the caller does not have the
   * <tt>AllPermission</tt>.
   */
  public void setPermissions(String location, PermissionInfo[] permissions) {
    SecurityManager sm = System.getSecurityManager();
    if (sm != null)
      sm.checkPermission(new AllPermission());
    if (location == null) {
      throw new NullPointerException();
    }

    PermissionStorage storage = new org.eclipse.osgi.framework.internal.core.SecurePermissionStorage(this.storage);

    try {
      String[] data = makePermissionData(permissions);

      if (Debug.DEBUG && Debug.DEBUG_SECURITY) {
        Debug.println("Setting permissions for location: " + location); //$NON-NLS-1$
        if (data == null) {
          Debug.println("  <none>"); //$NON-NLS-1$
        } else {
          for (int i = 0; i < data.length; i++) {
            Debug.println("  " + data[i]); //$NON-NLS-1$
          }
        }
      }

      storage.setPermissionData(location, data);
    } catch (IOException e) {
      framework.publishFrameworkEvent(FrameworkEvent.ERROR, framework.systemBundle, e);

      return;
    }

    AbstractBundle bundle = framework.getBundleByLocation(location);

    if ((bundle != null) && (bundle.getBundleId() != 0)) {
      ProtectionDomain domain = bundle.getProtectionDomain();

      if (domain != null) {
        BundleCombinedPermissions combined = (BundleCombinedPermissions) domain.getPermissions();

        if (permissions == null) {
          combined.setAssignedPermissions(defaultAssignedPermissions, true);
        } else {
          combined.setAssignedPermissions(createPermissions(permissions, bundle, false), false);
        }
      }
    }
  }

  /**
   * Returns the bundle locations that have permissions assigned to them,
   * that is, bundle locations for which an entry
   * exists in the permission table.
   *
   * @return The locations of bundles that have been assigned any
   * permissions, or <tt>null</tt> if the permission table is empty.
   */
  public String[] getLocations() {
    PermissionStorage storage = new org.eclipse.osgi.framework.internal.core.SecurePermissionStorage(this.storage);

    try {
      String[] locations = storage.getLocations();

      return locations;
    } catch (IOException e) {
      framework.publishFrameworkEvent(FrameworkEvent.ERROR, framework.systemBundle, e);

      return null;
    }
  }

  /**
   * Gets the default permissions.
   *
   * <p>These are the permissions granted to any bundle that does not
   * have permissions assigned to its location.
   *
   * @return The default permissions, or <tt>null</tt> if default
   * permissions have not been defined.
   */
  public PermissionInfo[] getDefaultPermissions() {
    PermissionStorage storage = new org.eclipse.osgi.framework.internal.core.SecurePermissionStorage(this.storage);

    try {
      String[] data = storage.getPermissionData(null);

      if (Debug.DEBUG && Debug.DEBUG_SECURITY) {
        Debug.println("Getting default permissions"); //$NON-NLS-1$
        if (data == null) {
          Debug.println("  <none>"); //$NON-NLS-1$
        } else {
          for (int i = 0; i < data.length; i++) {
            Debug.println("  " + data[i]); //$NON-NLS-1$
          }
        }
      }

      return makePermissionInfo(data);
    } catch (IOException e) {
      framework.publishFrameworkEvent(FrameworkEvent.ERROR, framework.systemBundle, e);

      return null;
    }
  }

  /**
   * Sets the default permissions.
   *
   * <p>These are the permissions granted to any bundle that does not
   * have permissions assigned to its location.
   *
   * @param permissions The default permissions.
   * @exception SecurityException if the caller does not have the
   * <tt>AllPermission</tt>.
   */
  public void setDefaultPermissions(PermissionInfo[] permissions) {
    SecurityManager sm = System.getSecurityManager();
    if (sm != null)
      sm.checkPermission(new AllPermission());
    PermissionStorage storage = new org.eclipse.osgi.framework.internal.core.SecurePermissionStorage(this.storage);

    try {
      String[] data = makePermissionData(permissions);

      if (Debug.DEBUG && Debug.DEBUG_SECURITY) {
        Debug.println("Setting default permissions"); //$NON-NLS-1$
        if (data == null) {
          Debug.println("  <none>"); //$NON-NLS-1$
        } else {
          for (int i = 0; i < data.length; i++) {
            Debug.println("  " + data[i]); //$NON-NLS-1$
          }
        }
      }

      storage.setPermissionData(null, data);
    } catch (IOException e) {
      framework.publishFrameworkEvent(FrameworkEvent.ERROR, framework.systemBundle, e);

      return;
    }

    defaultAssignedPermissions.setAssignedPermissions(createDefaultAssignedPermissions(permissions), true);
  }

  /**
   * Make a PermissionInfo array from an array of encoded permission Strings.
   *
   * @param data Array of encoded permission Strings
   * @return Array of PermissionInfo objects.
   */
  protected PermissionInfo[] makePermissionInfo(String[] data) {
    if (data == null) {
      return null;
    }

    int size = data.length;

    PermissionInfo[] permissions = new PermissionInfo[size];

    for (int i = 0; i < size; i++) {
      permissions[i] = new PermissionInfo(data[i]);
    }

    return permissions;
  }

  /**
   * Make an array of encoded permission Strings from a PermissionInfo array.
   *
   * @param permissions Array of PermissionInfor objects.
   * @return Array of encoded permission Strings
   */
  protected String[] makePermissionData(PermissionInfo[] permissions) {
    if (permissions == null) {
      return null;
    }

    int size = permissions.length;

    String[] data = new String[size];

    for (int i = 0; i < size; i++) {
      data[i] = permissions[i].getEncoded();
    }

    return data;
  }

  /**
   * This method is called by the Bundle object to create the
   * PermissionCollection used by the bundle's ProtectionDomain.
   *
   * @param bundle the bundle object
   * @return BundleCombinedPermission object with the bundle's
   * dynamic permissions.
   */
  protected BundleProtectionDomain createProtectionDomain(AbstractBundle bundle) {
    BundlePermissionCollection implied = getImpliedPermissions(bundle);

    BundleCombinedPermissions combined = new BundleCombinedPermissions(implied);

    BundlePermissionCollection assigned = getAssignedPermissions(bundle);

    combined.setAssignedPermissions(assigned, assigned == defaultAssignedPermissions);

    combined.setConditionalPermissions(new ConditionalPermissions(bundle, framework.condPermAdmin));

    /* now process the permissions.perm file, if it exists, and build the
     * restrictedPermissions using it. */
    PermissionInfo[] permInfos = getPermissionInfos(bundle.getEntry("OSGI-INF/permissions.perm")); //$NON-NLS-1$
    if (permInfos != null) {
      ConditionalPermissionInfoImpl cpiArray[] = new ConditionalPermissionInfoImpl[1];
      cpiArray[0] = new ConditionalPermissionInfoImpl(null, ConditionalPermissionAdminImpl.EMPTY_COND_INFO, permInfos);
      ConditionalPermissionSet cps = new ConditionalPermissionSet(bundle, cpiArray, ConditionalPermissionAdminImpl.EMPTY_COND);
      combined.setRestrictedPermissions(cps);
    }

    return new BundleProtectionDomainImpl(bundle, combined);
  }

  /**
   * Creates the default assigned permissions for bundles that
   * have no assigned permissions.
   * The default permissions are assigned via the PermissionAdmin service
   * and may change dynamically.
   *
   * @return A PermissionCollection of the default assigned permissions.
   */
  protected BundlePermissionCollection createDefaultAssignedPermissions(PermissionInfo[] info) {
    if (Debug.DEBUG && Debug.DEBUG_SECURITY) {
      Debug.println("Creating default assigned permissions"); //$NON-NLS-1$
    }

    if (info == null) {
      info = defaultDefaultPermissionInfos;
    }

    return createPermissions(info, null, false);
  }

  /**
   * Returns the assigned permissions for a bundle.
   * These permissions are assigned via the PermissionAdmin service
   * and may change dynamically.
   *
   * @param bundle The bundle to create the permissions for.
   * @return A PermissionCollection of the assigned permissions.
   */
  protected BundlePermissionCollection getAssignedPermissions(AbstractBundle bundle) {
    String location = bundle.getLocation();

    PermissionInfo[] info = getPermissions(location);

    if (info == null) {
      return defaultAssignedPermissions;
    }

    if (Debug.DEBUG && Debug.DEBUG_SECURITY) {
      Debug.println("Creating assigned permissions for " + bundle); //$NON-NLS-1$
    }

    return createPermissions(info, bundle, false);
  }

  /**
   * Returns the implied permissions for a bundle.
   * These permissions never change.
   *
   * @param bundle The bundle to create the permissions for.
   * @return A PermissionCollection of the implied permissions.
   */
  protected BundlePermissionCollection getImpliedPermissions(AbstractBundle bundle) {
    if (Debug.DEBUG && Debug.DEBUG_SECURITY)
      Debug.println("Creating implied permissions for " + bundle); //$NON-NLS-1$

    return createPermissions(baseImpliedPermissionInfos, bundle, true);
  }

  /**
   * Read the permissions from the specified resource.
   *
   * @return An array of PermissionInfo objects from the specified
   * resource.
   */
  protected PermissionInfo[] getPermissionInfos(URL resource) {
    if (resource == null)
      return null;
    PermissionInfo[] info = ConditionalPermissionAdminImpl.EMPTY_PERM_INFO;
    DataInputStream in = null;
    try {
      in = new DataInputStream(resource.openStream());
      ArrayList permissions = new ArrayList();
      BufferedReader reader;
      try {
        reader = new BufferedReader(new InputStreamReader(in, "UTF8")); //$NON-NLS-1$
      } catch (UnsupportedEncodingException e) {
        reader = new BufferedReader(new InputStreamReader(in));
      }

      while (true) {
        String line = reader.readLine();
        if (line == null) /* EOF */
          break;
        line = line.trim();
        if ((line.length() == 0) || line.startsWith("#") || line.startsWith("//")) /* comments */ //$NON-NLS-1$ //$NON-NLS-2$
          continue;

        try {
          permissions.add(new PermissionInfo(line));
        } catch (IllegalArgumentException iae) {
          /* incorrectly encoded permission */
          framework.publishFrameworkEvent(FrameworkEvent.ERROR, framework.systemBundle, iae);
        }
      }
      int size = permissions.size();
      if (size > 0)
        info = (PermissionInfo[]) permissions.toArray(new PermissionInfo[size]);
    } catch (IOException e) {
      // do nothing
    } finally {
      try {
        if (in != null)
          in.close();
      } catch (IOException ee) {
        // do nothing
      }
    }
    return info;
  }

  /**
   * Create a PermissionCollection from a PermissionInfo array.
   *
   * @param info Array of PermissionInfo objects.
   * @param bundle The target bundle for the permissions.
   * @return A PermissionCollection containing Permission objects.
   */
  protected BundlePermissionCollection createPermissions(PermissionInfo[] info, final AbstractBundle bundle, boolean implied) {
    if (info == null)
      info = new PermissionInfo[0];
    if (implied) {
      // create the implied AdminPermission actions for this bundle
      PermissionInfo impliedInfo = new PermissionInfo(AdminPermission.class.getName(), "(id=" + bundle.getBundleId() + ")", ADMIN_IMPLIED_ACTIONS); //$NON-NLS-1$ //$NON-NLS-2$
      if (Debug.DEBUG && Debug.DEBUG_SECURITY)
        Debug.println("Created permission: " + impliedInfo); //$NON-NLS-1$
      PermissionInfo[] impliedInfos = new PermissionInfo[info.length + 1];
      System.arraycopy(info, 0, impliedInfos, 0, info.length);
      impliedInfos[info.length] = impliedInfo;
      info = impliedInfos;
    }
    ConditionalPermissionInfoImpl cpiArray[] = new ConditionalPermissionInfoImpl[1];
    cpiArray[0] = new ConditionalPermissionInfoImpl(null, ConditionalPermissionAdminImpl.EMPTY_COND_INFO, info);
    return new ConditionalPermissionSet(bundle, cpiArray, ConditionalPermissionAdminImpl.EMPTY_COND);
  }

}
TOP

Related Classes of org.eclipse.osgi.framework.internal.core.PermissionAdminImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.