/******************************************************************************* * Copyright (c) 2001, 2008 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.equinox.internal.useradmin; import java.util.*; import org.osgi.framework.*; import org.osgi.service.log.LogService; import org.osgi.service.prefs.BackingStoreException; import org.osgi.service.prefs.PreferencesService; import org.osgi.service.useradmin.UserAdminEvent; import org.osgi.service.useradmin.UserAdminPermission; /** * This interface is used to manage a database of named roles, which can * be used for authentication and authorization purposes. *

* This version of UserAdmin defines two types of roles: "User" and * "Group". Each type of role is represented by an "int" constant and an * interface. The range of positive integers is reserved for new types of * roles that may be added in the future. When defining proprietary role * types, negative constant values must be used. *

* Every role has a name and a type. *

* A {@link User} role can be configured with credentials (e.g., a password) * and properties (e.g., a street address, phone number, etc.). *

* A {@link Group} role represents an aggregation of {@link User} and * {@link Group} roles. In * other words, the members of a Group role are roles themselves. *

* Every UserAdmin manages and maintains its own * namespace of roles, in which each role has a unique name. */ public class UserAdmin implements org.osgi.service.useradmin.UserAdmin { protected Vector users; protected Vector roles; protected BundleContext context; protected UserAdminEventProducer eventProducer; protected boolean alive; protected UserAdminStore userAdminStore; protected UserAdminPermission adminPermission; protected ServiceReference reference; protected LogTracker log; protected UserAdmin(PreferencesService preferencesService, BundleContext context) throws Exception { roles = new Vector(); users = new Vector(); this.context = context; log = new LogTracker(context, System.out); alive = true; //This handles user admin persistence try { userAdminStore = new UserAdminStore(preferencesService, this, log); userAdminStore.init(); } catch (Exception e) { log.log(LogService.LOG_ERROR, UserAdminMsg.Backing_Store_Read_Exception, e); throw e; } } protected void setServiceReference(ServiceReference reference) { if (this.reference == null) { this.reference = reference; eventProducer = new UserAdminEventProducer(reference, context, log); } } /** * Creates a role with the given name and of the given type. * *

If a role was created, a UserAdminEvent of type * {@link UserAdminEvent#ROLE_CREATED} is broadcast to any * UserAdminListener. * * @param name The name of the role to create. * @param type The type of the role to create. Must be either * {@link Role#USER} or {@link Role#GROUP}. * * @return The newly created role, or null if a role with * the given name already exists. * * @throws IllegalArgumentException if type is invalid. * * @throws SecurityException If a security manager exists and the caller * does not have the UserAdminPermission with name admin. */ public org.osgi.service.useradmin.Role createRole(String name, int type) { checkAlive(); checkAdminPermission(); if (name == null) { throw (new IllegalArgumentException(UserAdminMsg.CREATE_NULL_ROLE_EXCEPTION)); } if ((type != org.osgi.service.useradmin.Role.GROUP) && (type != org.osgi.service.useradmin.Role.USER)) { throw (new IllegalArgumentException(UserAdminMsg.CREATE_INVALID_TYPE_ROLE_EXCEPTION)); } //if the role already exists, return null if (getRole(name) != null) { return (null); } synchronized (this) { return createRole(name, type, true); } } protected org.osgi.service.useradmin.Role createRole(String name, int type, boolean store) { Role newRole = null; if (type == org.osgi.service.useradmin.Role.ROLE) { newRole = new Role(name, this); } else if (type == org.osgi.service.useradmin.Role.USER) { newRole = new User(name, this); } else if (type == org.osgi.service.useradmin.Role.GROUP) { newRole = new Group(name, this); } else //unknown type { return (null); } if (store) { try { userAdminStore.addRole(newRole); } catch (BackingStoreException ex) { return (null); } if (eventProducer != null) { eventProducer.generateEvent(UserAdminEvent.ROLE_CREATED, newRole); } } if (type == org.osgi.service.useradmin.Role.GROUP || type == org.osgi.service.useradmin.Role.USER) { users.addElement(newRole); } roles.addElement(newRole); return (newRole); } /** * Removes the role with the given name from this UserAdmin. * *

If the role was removed, a UserAdminEvent of type * {@link UserAdminEvent#ROLE_REMOVED} is broadcast to any * UserAdminListener. * * @param name The name of the role to remove. * * @return true If a role with the given name is present in this * UserAdmin and could be removed, otherwise false. * * @throws SecurityException If a security manager exists and the caller * does not have the UserAdminPermission with name admin. */ public boolean removeRole(String name) { checkAlive(); checkAdminPermission(); if (name.equals(Role.anyoneString)) { //silently ignore return (true); } synchronized (this) { Role role = (org.eclipse.equinox.internal.useradmin.Role) getRole(name); if (role != null) { try { userAdminStore.removeRole(role); } catch (BackingStoreException ex) { return (false); } roles.removeElement(role); users.removeElement(role); role.destroy(); eventProducer.generateEvent(UserAdminEvent.ROLE_REMOVED, role); role = null; return (true); } return (false); } } /** * Gets the role with the given name from this UserAdmin. * * @param name The name of the role to get. * * @return The requested role, or null if this UserAdmin does * not have a role with the given name. */ public org.osgi.service.useradmin.Role getRole(String name) { checkAlive(); if (name == null) { return (null); } synchronized (this) { Enumeration e = roles.elements(); while (e.hasMoreElements()) { Role role = (Role) e.nextElement(); if (role.getName().equals(name)) { return (role); } } return (null); } } /** * Gets the roles managed by this UserAdmin that have properties matching * the specified LDAP filter criteria. See * org.osgi.framework.Filter or IETF RFC 2254 for a * description of the filter syntax. If a null filter is * specified, all roles managed by this UserAdmin are returned. * * @param filterString The filter criteria to match. * * @return The roles managed by this UserAdmin whose properties * match the specified filter criteria, or all roles if a * null filter is specified. * */ public org.osgi.service.useradmin.Role[] getRoles(String filterString) throws InvalidSyntaxException { checkAlive(); Vector returnedRoles; synchronized (this) { if (filterString == null) { returnedRoles = roles; } else { Filter filter = context.createFilter(filterString); //We do this first so an //InvalidSyntaxException will be //thrown even if there are no roles //present. returnedRoles = new Vector(); for (int i = 0; i < roles.size(); i++) { Role role = (Role) roles.elementAt(i); if (filter.match(role.getProperties())) { returnedRoles.addElement(role); } } } int size = returnedRoles.size(); if (size == 0) { return (null); } Role[] roleArray = new Role[size]; returnedRoles.copyInto(roleArray); return (roleArray); } } /** * Gets the user with the given property key-value pair from the UserAdmin * database. This is a convenience method for retrieving a user based on * a property for which every user is supposed to have a unique value * (within the scope of this UserAdmin), such as a user's * X.500 distinguished name. * * @param key The property key to look for. * @param value The property value to compare with. * * @return A matching user, if exactly one is found. If zero or * more than one matching users are found, null is returned. */ public org.osgi.service.useradmin.User getUser(String key, String value) { checkAlive(); if (key == null) { return (null); } User user; User foundUser = null; Dictionary props; String keyValue; synchronized (this) { Enumeration e = users.elements(); while (e.hasMoreElements()) { user = (User) e.nextElement(); props = user.getProperties(); keyValue = (String) props.get(key); if (keyValue != null && keyValue.equals(value)) { if (foundUser != null) { return (null); //we found more than one match } foundUser = user; } } return (foundUser); } } /** * Creates an Authorization object that encapsulates the specified user * and the roles it possesses. The null user is interpreted * as the anonymous user. * * @param user The user to create an Authorization object for, or * null for the anonymous user. * * @return the Authorization object for the specified user. */ public org.osgi.service.useradmin.Authorization getAuthorization(org.osgi.service.useradmin.User user) { checkAlive(); return (new Authorization((User) user, this)); } protected synchronized void destroy() { alive = false; eventProducer.close(); userAdminStore.destroy(); log.close(); } public void checkAdminPermission() { SecurityManager sm = System.getSecurityManager(); if (sm != null) { if (adminPermission == null) { adminPermission = new UserAdminPermission(UserAdminPermission.ADMIN, null); } sm.checkPermission(adminPermission); } } public void checkGetCredentialPermission(String credential) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(new org.osgi.service.useradmin.UserAdminPermission(credential, org.osgi.service.useradmin.UserAdminPermission.GET_CREDENTIAL)); } } public void checkChangeCredentialPermission(String credential) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(new org.osgi.service.useradmin.UserAdminPermission(credential, org.osgi.service.useradmin.UserAdminPermission.CHANGE_CREDENTIAL)); } } public void checkChangePropertyPermission(String property) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(new org.osgi.service.useradmin.UserAdminPermission(property, org.osgi.service.useradmin.UserAdminPermission.CHANGE_PROPERTY)); } } public void checkAlive() { if (!alive) { throw (new IllegalStateException(UserAdminMsg.USERADMIN_UNREGISTERED_EXCEPTION)); } } }