1 /******************************************************************************* 2 * Copyright (c) 2001, 2008 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.equinox.internal.useradmin; 15 16 import java.util.*; 17 import org.osgi.framework.*; 18 import org.osgi.service.log.LogService; 19 import org.osgi.service.prefs.BackingStoreException; 20 import org.osgi.service.prefs.PreferencesService; 21 import org.osgi.service.useradmin.UserAdminEvent; 22 import org.osgi.service.useradmin.UserAdminPermission; 23 24 /** 25 * This interface is used to manage a database of named roles, which can 26 * be used for authentication and authorization purposes. 27 * <p> 28 * This version of UserAdmin defines two types of roles: "User" and 29 * "Group". Each type of role is represented by an "int" constant and an 30 * interface. The range of positive integers is reserved for new types of 31 * roles that may be added in the future. When defining proprietary role 32 * types, negative constant values must be used. 33 * <p> 34 * Every role has a name and a type. 35 * <p> 36 * A {@link User} role can be configured with credentials (e.g., a password) 37 * and properties (e.g., a street address, phone number, etc.). 38 * <p> 39 * A {@link Group} role represents an aggregation of {@link User} and 40 * {@link Group} roles. In 41 * other words, the members of a Group role are roles themselves. 42 * <p> 43 * Every UserAdmin manages and maintains its own 44 * namespace of roles, in which each role has a unique name. 45 */ 46 47 public class UserAdmin implements org.osgi.service.useradmin.UserAdmin { 48 49 protected Vector users; 50 protected Vector roles; 51 protected BundleContext context; 52 protected UserAdminEventProducer eventProducer; 53 protected boolean alive; 54 protected UserAdminStore userAdminStore; 55 protected UserAdminPermission adminPermission; 56 protected ServiceReference reference; 57 protected LogTracker log; 58 UserAdmin(PreferencesService preferencesService, BundleContext context)59 protected UserAdmin(PreferencesService preferencesService, BundleContext context) throws Exception { 60 roles = new Vector(); 61 users = new Vector(); 62 this.context = context; 63 64 log = new LogTracker(context, System.out); 65 alive = true; 66 //This handles user admin persistence 67 try { 68 userAdminStore = new UserAdminStore(preferencesService, this, log); 69 userAdminStore.init(); 70 } catch (Exception e) { 71 log.log(LogService.LOG_ERROR, UserAdminMsg.Backing_Store_Read_Exception, e); 72 throw e; 73 } 74 } 75 setServiceReference(ServiceReference reference)76 protected void setServiceReference(ServiceReference reference) { 77 if (this.reference == null) { 78 this.reference = reference; 79 80 eventProducer = new UserAdminEventProducer(reference, context, log); 81 } 82 } 83 84 /** 85 * Creates a role with the given name and of the given type. 86 * 87 * <p> If a role was created, a UserAdminEvent of type 88 * {@link UserAdminEvent#ROLE_CREATED} is broadcast to any 89 * UserAdminListener. 90 * 91 * @param name The name of the role to create. 92 * @param type The type of the role to create. Must be either 93 * {@link Role#USER} or {@link Role#GROUP}. 94 * 95 * @return The newly created role, or <code>null</code> if a role with 96 * the given name already exists. 97 * 98 * @throws IllegalArgumentException if <tt>type</tt> is invalid. 99 * 100 * @throws SecurityException If a security manager exists and the caller 101 * does not have the <tt>UserAdminPermission</tt> with name <tt>admin</tt>. 102 */ createRole(String name, int type)103 public org.osgi.service.useradmin.Role createRole(String name, int type) { 104 checkAlive(); 105 checkAdminPermission(); 106 if (name == null) { 107 throw (new IllegalArgumentException(UserAdminMsg.CREATE_NULL_ROLE_EXCEPTION)); 108 } 109 if ((type != org.osgi.service.useradmin.Role.GROUP) && (type != org.osgi.service.useradmin.Role.USER)) { 110 throw (new IllegalArgumentException(UserAdminMsg.CREATE_INVALID_TYPE_ROLE_EXCEPTION)); 111 } 112 //if the role already exists, return null 113 if (getRole(name) != null) { 114 return (null); 115 } 116 117 synchronized (this) { 118 return createRole(name, type, true); 119 } 120 } 121 createRole(String name, int type, boolean store)122 protected org.osgi.service.useradmin.Role createRole(String name, int type, boolean store) { 123 Role newRole = null; 124 if (type == org.osgi.service.useradmin.Role.ROLE) { 125 newRole = new Role(name, this); 126 } else if (type == org.osgi.service.useradmin.Role.USER) { 127 newRole = new User(name, this); 128 } else if (type == org.osgi.service.useradmin.Role.GROUP) { 129 newRole = new Group(name, this); 130 } else //unknown type 131 { 132 return (null); 133 } 134 if (store) { 135 try { 136 userAdminStore.addRole(newRole); 137 } catch (BackingStoreException ex) { 138 return (null); 139 } 140 if (eventProducer != null) { 141 eventProducer.generateEvent(UserAdminEvent.ROLE_CREATED, newRole); 142 } 143 } 144 if (type == org.osgi.service.useradmin.Role.GROUP || type == org.osgi.service.useradmin.Role.USER) { 145 users.addElement(newRole); 146 } 147 roles.addElement(newRole); 148 return (newRole); 149 } 150 151 /** 152 * Removes the role with the given name from this UserAdmin. 153 * 154 * <p> If the role was removed, a UserAdminEvent of type 155 * {@link UserAdminEvent#ROLE_REMOVED} is broadcast to any 156 * UserAdminListener. 157 * 158 * @param name The name of the role to remove. 159 * 160 * @return <code>true</code> If a role with the given name is present in this 161 * UserAdmin and could be removed, otherwise <code>false</code>. 162 * 163 * @throws SecurityException If a security manager exists and the caller 164 * does not have the <tt>UserAdminPermission</tt> with name <tt>admin</tt>. 165 */ removeRole(String name)166 public boolean removeRole(String name) { 167 checkAlive(); 168 checkAdminPermission(); 169 if (name.equals(Role.anyoneString)) { 170 //silently ignore 171 return (true); 172 } 173 synchronized (this) { 174 Role role = (org.eclipse.equinox.internal.useradmin.Role) getRole(name); 175 if (role != null) { 176 try { 177 userAdminStore.removeRole(role); 178 } catch (BackingStoreException ex) { 179 return (false); 180 } 181 roles.removeElement(role); 182 users.removeElement(role); 183 role.destroy(); 184 eventProducer.generateEvent(UserAdminEvent.ROLE_REMOVED, role); 185 role = null; 186 return (true); 187 } 188 return (false); 189 } 190 } 191 192 /** 193 * Gets the role with the given name from this UserAdmin. 194 * 195 * @param name The name of the role to get. 196 * 197 * @return The requested role, or <code>null</code> if this UserAdmin does 198 * not have a role with the given name. 199 */ getRole(String name)200 public org.osgi.service.useradmin.Role getRole(String name) { 201 checkAlive(); 202 if (name == null) { 203 return (null); 204 } 205 synchronized (this) { 206 Enumeration e = roles.elements(); 207 while (e.hasMoreElements()) { 208 Role role = (Role) e.nextElement(); 209 if (role.getName().equals(name)) { 210 return (role); 211 } 212 } 213 return (null); 214 } 215 } 216 217 /** 218 * Gets the roles managed by this UserAdmin that have properties matching 219 * the specified LDAP filter criteria. See 220 * <code>org.osgi.framework.Filter</code> or IETF RFC 2254 for a 221 * description of the filter syntax. If a <code>null</code> filter is 222 * specified, all roles managed by this UserAdmin are returned. 223 * 224 * @param filterString The filter criteria to match. 225 * 226 * @return The roles managed by this UserAdmin whose properties 227 * match the specified filter criteria, or all roles if a 228 * <code>null</code> filter is specified. 229 * 230 */ getRoles(String filterString)231 public org.osgi.service.useradmin.Role[] getRoles(String filterString) throws InvalidSyntaxException { 232 checkAlive(); 233 Vector returnedRoles; 234 synchronized (this) { 235 if (filterString == null) { 236 returnedRoles = roles; 237 } else { 238 Filter filter = context.createFilter(filterString); //We do this first so an 239 //InvalidSyntaxException will be 240 //thrown even if there are no roles 241 //present. 242 returnedRoles = new Vector(); 243 for (int i = 0; i < roles.size(); i++) { 244 Role role = (Role) roles.elementAt(i); 245 if (filter.match(role.getProperties())) { 246 returnedRoles.addElement(role); 247 } 248 } 249 } 250 int size = returnedRoles.size(); 251 if (size == 0) { 252 return (null); 253 } 254 Role[] roleArray = new Role[size]; 255 returnedRoles.copyInto(roleArray); 256 return (roleArray); 257 } 258 } 259 260 /** 261 * Gets the user with the given property key-value pair from the UserAdmin 262 * database. This is a convenience method for retrieving a user based on 263 * a property for which every user is supposed to have a unique value 264 * (within the scope of this UserAdmin), such as a user's 265 * X.500 distinguished name. 266 * 267 * @param key The property key to look for. 268 * @param value The property value to compare with. 269 * 270 * @return A matching user, if <em>exactly</em> one is found. If zero or 271 * more than one matching users are found, <code>null</code> is returned. 272 */ getUser(String key, String value)273 public org.osgi.service.useradmin.User getUser(String key, String value) { 274 checkAlive(); 275 if (key == null) { 276 return (null); 277 } 278 User user; 279 User foundUser = null; 280 Dictionary props; 281 String keyValue; 282 synchronized (this) { 283 Enumeration e = users.elements(); 284 while (e.hasMoreElements()) { 285 user = (User) e.nextElement(); 286 props = user.getProperties(); 287 keyValue = (String) props.get(key); 288 if (keyValue != null && keyValue.equals(value)) { 289 if (foundUser != null) { 290 return (null); //we found more than one match 291 } 292 foundUser = user; 293 } 294 } 295 return (foundUser); 296 } 297 } 298 299 /** 300 * Creates an Authorization object that encapsulates the specified user 301 * and the roles it possesses. The <code>null</code> user is interpreted 302 * as the anonymous user. 303 * 304 * @param user The user to create an Authorization object for, or 305 * <code>null</code> for the anonymous user. 306 * 307 * @return the Authorization object for the specified user. 308 */ getAuthorization(org.osgi.service.useradmin.User user)309 public org.osgi.service.useradmin.Authorization getAuthorization(org.osgi.service.useradmin.User user) { 310 checkAlive(); 311 return (new Authorization((User) user, this)); 312 } 313 destroy()314 protected synchronized void destroy() { 315 alive = false; 316 eventProducer.close(); 317 userAdminStore.destroy(); 318 319 log.close(); 320 } 321 checkAdminPermission()322 public void checkAdminPermission() { 323 SecurityManager sm = System.getSecurityManager(); 324 if (sm != null) { 325 if (adminPermission == null) { 326 adminPermission = new UserAdminPermission(UserAdminPermission.ADMIN, null); 327 } 328 sm.checkPermission(adminPermission); 329 } 330 } 331 checkGetCredentialPermission(String credential)332 public void checkGetCredentialPermission(String credential) { 333 SecurityManager sm = System.getSecurityManager(); 334 if (sm != null) { 335 sm.checkPermission(new org.osgi.service.useradmin.UserAdminPermission(credential, org.osgi.service.useradmin.UserAdminPermission.GET_CREDENTIAL)); 336 } 337 } 338 checkChangeCredentialPermission(String credential)339 public void checkChangeCredentialPermission(String credential) { 340 SecurityManager sm = System.getSecurityManager(); 341 if (sm != null) { 342 sm.checkPermission(new org.osgi.service.useradmin.UserAdminPermission(credential, org.osgi.service.useradmin.UserAdminPermission.CHANGE_CREDENTIAL)); 343 } 344 } 345 checkChangePropertyPermission(String property)346 public void checkChangePropertyPermission(String property) { 347 SecurityManager sm = System.getSecurityManager(); 348 if (sm != null) { 349 sm.checkPermission(new org.osgi.service.useradmin.UserAdminPermission(property, org.osgi.service.useradmin.UserAdminPermission.CHANGE_PROPERTY)); 350 } 351 } 352 checkAlive()353 public void checkAlive() { 354 if (!alive) { 355 throw (new IllegalStateException(UserAdminMsg.USERADMIN_UNREGISTERED_EXCEPTION)); 356 } 357 } 358 359 } 360