001: /* Copyright (c) 1995-2000, The Hypersonic SQL Group.
002: * All rights reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * Redistributions of source code must retain the above copyright notice, this
008: * list of conditions and the following disclaimer.
009: *
010: * Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * Neither the name of the Hypersonic SQL Group nor the names of its
015: * contributors may be used to endorse or promote products derived from this
016: * software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
020: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
021: * ARE DISCLAIMED. IN NO EVENT SHALL THE HYPERSONIC SQL GROUP,
022: * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
026: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: *
030: * This software consists of voluntary contributions made by many individuals
031: * on behalf of the Hypersonic SQL Group.
032: *
033: *
034: * For work added by the HSQL Development Group:
035: *
036: * Copyright (c) 2001-2005, The HSQL Development Group
037: * All rights reserved.
038: *
039: * Redistribution and use in source and binary forms, with or without
040: * modification, are permitted provided that the following conditions are met:
041: *
042: * Redistributions of source code must retain the above copyright notice, this
043: * list of conditions and the following disclaimer.
044: *
045: * Redistributions in binary form must reproduce the above copyright notice,
046: * this list of conditions and the following disclaimer in the documentation
047: * and/or other materials provided with the distribution.
048: *
049: * Neither the name of the HSQL Development Group nor the names of its
050: * contributors may be used to endorse or promote products derived from this
051: * software without specific prior written permission.
052: *
053: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
054: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
055: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
056: * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
057: * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
058: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
059: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
060: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
061: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
062: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
063: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
064: */
065:
066: package org.hsqldb;
067:
068: import org.hsqldb.lib.HashMappedList;
069: import org.hsqldb.lib.HsqlArrayList;
070: import org.hsqldb.HsqlNameManager.HsqlName;
071: import org.hsqldb.SchemaManager.Schema;
072:
073: // fredt@users 20020130 - patch 497872 by Nitin Chauhan - loop optimisation
074: // fredt@users 20020320 - doc 1.7.0 - update
075: // fredt@users 20021103 - patch 1.7.2 - allow for drop table, etc.
076: // fredt@users 20030613 - patch 1.7.2 - simplified data structures and reporting
077: // unsaved@users - patch 1.8.0 moved right managament to new classes
078:
079: /**
080: *
081: * Manages the User objects for a Database instance.
082: * The special users PUBLIC_USER_NAME and SYSTEM_AUTHORIZATION_NAME
083: * are created and managed here. SYSTEM_AUTHORIZATION_NAME is also
084: * special in that the name is not kept in the user "list"
085: * (PUBLIC_USER_NAME is kept in the list because it's needed by MetaData
086: * routines via "listVisibleUsers(x, true)").
087: *
088: * Partly based on Hypersonic code.
089: *
090: * @author Thomas Mueller (Hypersonic SQL Group)
091: * @author boucherb@users
092: * @author fredt@users
093: *
094: * @version 1.8.0
095: * @since 1.7.2
096: * @see User
097: */
098: class UserManager implements GrantConstants {
099:
100: /**
101: * We keep a link to the SYSTEM_AUTHORIZATION_NAME user because it is
102: * the only User with no entry in the User map.
103: */
104: User sysUser = null;
105:
106: /**
107: * This object's set of User objects. <p>
108: *
109: * Note: The special _SYSTEM role
110: * is not included in this list but the special PUBLIC
111: * User object is kept in the list because it's needed by MetaData
112: * routines via "listVisibleUsers(x, true)".
113: */
114: private HashMappedList userList;
115: private GranteeManager granteeManager;
116:
117: /**
118: * Construction happens once for each Database object.
119: *
120: * Creates special users PUBLIC_USER_NAME and SYSTEM_AUTHORIZATION_NAME.
121: * Sets up association with the GranteeManager for this database.
122: */
123: UserManager(Database database) throws HsqlException {
124:
125: granteeManager = database.getGranteeManager();
126: userList = new HashMappedList();
127:
128: createUser(GranteeManager.PUBLIC_ROLE_NAME, null);
129:
130: sysUser = createUser(GranteeManager.SYSTEM_AUTHORIZATION_NAME,
131: null);
132:
133: // Don't know whether to grant ADMIN to SYS directly, or to grant
134: // role DBA. The former seems safer as it doesn't depend on any role.
135: //granteeManager.grant(SYSTEM_AUTHORIZATION_NAME, RoleManager.ADMIN_ROLE_NAME);
136: sysUser.getGrantee().setAdminDirect();
137: }
138:
139: /**
140: * Creates a new User object under management of this object. <p>
141: *
142: * A set of constraints regarding user creation is imposed: <p>
143: *
144: * <OL>
145: * <LI>If the specified name is null, then an
146: * ASSERTION_FAILED exception is thrown stating that
147: * the name is null.
148: *
149: * <LI>If this object's collection already contains an element whose
150: * name attribute equals the name argument, then
151: * a GRANTEE_ALREADY_EXISTS exception is thrown.
152: * (This will catch attempts to create Reserved grantee names).
153: * </OL>
154: */
155: User createUser(String name, String password) throws HsqlException {
156:
157: if (name == null) {
158: Trace.doAssert(false, Trace.getMessage(Trace.NULL_NAME));
159: }
160:
161: // TODO:
162: // checkComplexity(password);
163: // requires special: createSAUser(), createPublicUser()
164: // boucherb@users 20020815 - disallow user-land creation of SYS user
165: // -------------------------------------------------------
166: // This will throw an appropriate Trace if grantee already exists,
167: // regardless of whether the name is in any User, Role, etc. list.
168: Grantee g = granteeManager.addGrantee(name);
169: User u = new User(name, password, g);
170:
171: // ONLY!! SYSTEM_AUTHORIZATION_NAME is not stored in our User list.
172: if (GranteeManager.SYSTEM_AUTHORIZATION_NAME.equals(name)) {
173: return u;
174: }
175:
176: boolean success = userList.add(name, u);
177:
178: if (!success) {
179: throw Trace.error(Trace.USER_ALREADY_EXISTS, name);
180: }
181:
182: return u;
183: }
184:
185: /**
186: * Attempts to drop a User object with the specified name
187: * from this object's set. <p>
188: *
189: * A successful drop action consists of: <p>
190: *
191: * <UL>
192: *
193: * <LI>removing the User object with the specified name
194: * from the set.
195: *
196: * <LI>revoking all rights from the removed object<br>
197: * (this ensures that in case there are still references to the
198: * just dropped User object, those references
199: * cannot be used to erronously access database objects).
200: *
201: * </UL> <p>
202: *
203: */
204: void dropUser(String name) throws HsqlException {
205:
206: boolean reservedUser = GranteeManager.isReserved(name);
207:
208: Trace.check(!reservedUser, Trace.NONMOD_ACCOUNT, name);
209:
210: boolean result = granteeManager.removeGrantee(name);
211:
212: Trace.check(result, Trace.NO_SUCH_GRANTEE, name);
213:
214: User u = (User) userList.remove(name);
215:
216: Trace.check(u != null, Trace.USER_NOT_FOUND, name);
217: }
218:
219: /**
220: * Returns the User object with the specified name and
221: * password from this object's set.
222: */
223: User getUser(String name, String password) throws HsqlException {
224:
225: if (name == null) {
226: name = "";
227: }
228:
229: if (password == null) {
230: password = "";
231: }
232:
233: // Don't have to worry about SYSTEM_AUTHORIZATION_NAME, since get()
234: // will fail below (because it's not in the list).
235: if (name.equals(GranteeManager.PUBLIC_ROLE_NAME)) {
236: throw Trace.error(Trace.ACCESS_IS_DENIED);
237: }
238:
239: name = name.toUpperCase();
240: password = password.toUpperCase();
241:
242: User u = get(name);
243:
244: u.checkPassword(password);
245:
246: return u;
247: }
248:
249: /**
250: * Retrieves this object's set of User objects as
251: * an HsqlArrayList. <p>
252: */
253: HashMappedList getUsers() {
254: return userList;
255: }
256:
257: boolean exists(String name) {
258: return userList.get(name) == null ? false : true;
259: }
260:
261: /**
262: * Returns the User object identified by the
263: * name argument. <p>
264: */
265: User get(String name) throws HsqlException {
266:
267: User u = (User) userList.get(name);
268:
269: if (u == null) {
270: throw Trace.error(Trace.USER_NOT_FOUND, name);
271: }
272:
273: return u;
274: }
275:
276: /**
277: * Retrieves the <code>User</code> objects representing the database
278: * users that are visible to the <code>User</code> object
279: * represented by the <code>session</code> argument. <p>
280: *
281: * If the <code>session</code> argument's <code>User</code> object
282: * attribute has isAdmin() true (directly or by virtue of a Role),
283: * then all of the
284: * <code>User</code> objects in this collection are considered visible.
285: * Otherwise, only this object's special <code>PUBLIC</code>
286: * <code>User</code> object attribute and the session <code>User</code>
287: * object, if it exists in this collection, are considered visible. <p>
288: *
289: * @param session The <code>Session</code> object used to determine
290: * visibility
291: * @param andPublicUser whether to include the special <code>PUBLIC</code>
292: * <code>User</code> object in the retrieved list
293: * @return a list of <code>User</code> objects visible to
294: * the <code>User</code> object contained by the
295: * <code>session</code> argument.
296: *
297: */
298: HsqlArrayList listVisibleUsers(Session session,
299: boolean andPublicUser) {
300:
301: HsqlArrayList list;
302: User user;
303: boolean isAdmin;
304: String sessName;
305: String userName;
306:
307: list = new HsqlArrayList();
308: isAdmin = session.isAdmin();
309: sessName = session.getUsername();
310:
311: if (userList == null || userList.size() == 0) {
312: return list;
313: }
314:
315: for (int i = 0; i < userList.size(); i++) {
316: user = (User) userList.get(i);
317:
318: if (user == null) {
319: continue;
320: }
321:
322: userName = user.getName();
323:
324: if (GranteeManager.PUBLIC_ROLE_NAME.equals(userName)) {
325: if (andPublicUser) {
326: list.add(user);
327: }
328: } else if (isAdmin) {
329: list.add(user);
330: } else if (sessName.equals(userName)) {
331: list.add(user);
332: }
333: }
334:
335: return list;
336: }
337:
338: // Legacy wrappers
339: static String[] getRightsArray(int rights) {
340: return GranteeManager.getRightsArray(rights);
341: }
342:
343: /**
344: * Removes all rights mappings for the database object identified by
345: * the dbobject argument from all Grantee objects in the set.
346: */
347: void removeDbObject(Object dbobject) {
348: granteeManager.removeDbObject(dbobject);
349: }
350:
351: /**
352: * Returns the specially constructed
353: * <code>SYSTEM_AUTHORIZATION_NAME</code>
354: * <code>User</code> object for the current <code>Database</code> object.
355: *
356: * @throws HsqlException - if the specified <code>Database</code>
357: * has no <code>SYS_AUTHORIZATION_NAME</code>
358: * <code>User</code> object.
359: * @return the <code>SYS_AUTHORIZATION_NAME</code>
360: * <code>User</code> object
361: *
362: */
363: User getSysUser() {
364: return sysUser;
365: }
366:
367: public synchronized void removeSchemaReference(Schema schema) {
368:
369: for (int i = 0; i < userList.size(); i++) {
370: User user = (User) userList.get(i);
371:
372: if (user.getInitialSchema() == schema.name) {
373: user.setInitialSchema(null);
374: }
375: }
376: }
377: }
|