1 /* Copyright (C) 2000-2004 Thomas Bopp, Thorsten Hampel, Ludger Merkens
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 * $Id: access.pike,v 1.2 2009/08/04 15:39:31 nicke Exp $
21 #include <attributes.h>
28 //! basic access functions...
29 //! the permissions of other objects on this object are stored
30 //! inside mSanction mapping. Each Entry in the mapping is an integer
31 //! (32 bits) and each bit represents one permission for the sanctioned
32 //! object. The first 16 bits are reserved for the system and include
33 //! standard checks that are done inside system code. The other 16 bits
34 //! are free for users to use in their own code.
42 private mapping mSanction; /*the right i have for this object */
43 private mapping mMetaSanction; /*the meta rights-to give away rights*/
44 private mapping mDataStorage;
46 private object oCreator;
47 object|function oAcquire;
49 int get_object_class();
50 object get_environment();
51 string get_identifier();
53 void require_save(void|string ident, void|string index);
56 * Initialize the access mappings for object, set acquiring to 0 and
57 * set the creator of this object.
65 mMetaSanction = ([ ]);
70 if ( !objectp(oCreator) )
71 oCreator = this_user();
73 if ( objectp(oCreator) )
74 mSanction = ([ oCreator : SANCTION_ALL ]);
80 * Set the object to acquire access from. That is not only the ACL of this
81 * object is used, but also the ACL of the object acquired from is used
84 * @param o - the object that variables and access is acquired from
88 set_acquire(function|object acquire)
92 if ( !_SECURITY->access_acquire(0, this_object(), CALLER, acquire) )
95 if ( functionp(acquire) )
100 while ( objectp(acq) ) {
101 if ( functionp(acq->get_object) )
102 acq = acq->get_object();
103 if ( acq == this_object() )
104 THROW("Acquire ended up in loop !", E_ERROR);
105 acq = acq->get_acquire();
109 require_save(STORE_ACCESS);
114 * Turn on access acquiring from the object's environment. You can turn this
115 * off again by calling set_acquire(0);
120 * @return 1 on success, 0 on failure
123 set_acquire_from_environment()
125 return set_acquire( this_object()->get_environment );
129 * Return the acquiring object or function. If acquiring is turned of for this
130 * object it returns 0.
132 * @return the object permissions and variables are acquired
135 final object|function
142 * Return the acquiring object. If acquiring is turned of for this
143 * object it returns 0.
145 * @return the object permissions and variables are acquired
151 if ( functionp(oAcquire) )
160 * Get the sanction integer for a given object.
162 * @param obj - the object
163 * @return the sanction status for obj
167 query_sanction(object obj)
169 return mSanction[obj];
173 * Returns the sanction mapping of this object, if the caller is privileged
174 * the pointer will be returned, otherwise a copy.
176 * @return the sanction mapping
182 if ( _SECURITY->trust(CALLER) )
184 return copy_value(mSanction);
188 * The indices of the sanction mapping are returned. The sanction map is
189 * in the form ([ object: access-bits, ])
191 * @return all objects in sanction array
194 query_sanctioned_objs()
196 return indices(mSanction);
200 * Get the meta-sanction mapping. Meta sanction contains access to
201 * give access permissions to other users or groups.
203 * @return copy of the meta sanction mapping
204 * @see query_meta_sanction
209 return copy_value(mMetaSanction);
213 * Return the meta sanction access bit for a given object (group or user).
215 * @param obj - the possible sanctioned object
216 * @return the meta sanction permissions of obj on this
217 * @see set_meta_sanction
220 query_meta_sanction(object obj)
222 return mMetaSanction[obj];
226 * Set the meta access permissions for a group or a user.
228 * @param obj - the object to sanction
229 * @param permission - meta sanction permissions
230 * @see query_meta_sanction
234 set_meta_sanction(object obj, int permission)
236 mMetaSanction[obj] = permission;
237 require_save(STORE_ACCESS);
243 * Set the access permissions for a given group or user to 'permission'.
245 * @param obj - object to sanction
246 * @param permission - new permissions for that object
251 set_sanction(object obj, int permission)
253 ASSERTINFO(_SECURITY->valid_proxy(obj), "set_sanction on invalid proxy!");
254 ASSERTINFO(mappingp(mSanction), "Mapping not initialized....");
256 if ( permission == 0 )
257 m_delete(mSanction, obj);
259 mSanction[obj] = permission;
260 require_save(STORE_ACCESS);
266 * This function returns whether a user or group has access permissions
267 * for 'accessBit'. The function also follows the acquiring path and
268 * calls try_access_object() in acquired objects too.
270 * @param user - who wants to access the object (user or group)
271 * @param accessBit - the Bit to check
272 * @param bool meta - check for meta access ?
273 * @return ACCESS_DENIED or ACCESS_GRANTED or event ACCESS_BLOCKED
274 * @see try_access_object_group
277 try_access_object(object user, int accessBit, bool meta)
280 ASSERTINFO(_SECURITY->valid_proxy(user), "Access on non-proxy !");
282 SECURITY_LOG("Sanction of user is:" + mSanction[user]+"(accBit="+accessBit+")");
283 if ( mSanction[user] & (accessBit << SANCTION_SHIFT_DENY) ) {
284 SECURITY_LOG("Access blocked !");
285 return ACCESS_BLOCKED;
287 if ( user == oCreator )
288 return ACCESS_GRANTED;
291 SECURITY_LOG("Sanction of user does match !");
292 if ( !meta || (mMetaSanction[user] & accessBit) )
293 return ACCESS_GRANTED;
295 /* the object must not be sanctioned at all
296 * if the acquiring object gives permission to the user -> ok */
297 if ( objectp(oAcquire) )
299 else if ( functionp(oAcquire) )
301 /* it is not possible to block access from acquiring objects ! */
302 if ( objectp(obj) ) {
303 SECURITY_LOG("Using acquiring path to "+obj->get_object_id());
304 return obj->try_access_object(user, accessBit, meta) == ACCESS_GRANTED?
305 ACCESS_GRANTED : ACCESS_DENIED;
308 return ACCESS_DENIED;
312 * Try to access the object by a group. The function recursively tries
313 * parent groups of the initial group. If one group succeeds, the call
314 * returns ACCESS_GRANTED.
316 * @param grp - the group that wants to write
317 * @return if successfull or not
318 * @see try_access_object
321 try_access_object_group(object grp, int accessBit, bool meta)
326 SECURITY_LOG("Group ["+grp->get_identifier()+"] access ("+
327 accessBit+") on "+get_identifier()+": sanction is "+
330 if ( mSanction[grp] & (accessBit << SANCTION_SHIFT_DENY) )
331 return ACCESS_BLOCKED;
333 if ( (mSanction[grp] & accessBit) )
335 if ( !meta || (mMetaSanction[grp] & accessBit) )
336 return ACCESS_GRANTED;
339 array grp_groups = grp->get_groups();
340 // LOG("Indirect group checking ... ");
341 if ( arrayp(grp_groups) ) {
342 foreach( grp_groups, object member ) {
343 if ( objectp(member) && _SECURITY->valid_group(member) ) {
344 LOG("Accessing with " + master()->describe_object(member));
345 result = try_access_object_group(member, accessBit, meta);
346 if ( result == ACCESS_GRANTED )
347 return ACCESS_GRANTED;
352 if ( objectp(oAcquire) )
354 else if ( functionp(oAcquire) )
356 if ( objectp(obj) ) {
357 return obj->try_access_object_group(grp, accessBit, meta);
360 return ACCESS_DENIED;
368 * Return all owners of this object.
369 * Owners are groups/users that have sanction permission to the
370 * object, eg are able to give permissions to other objects.
372 * @return a list of owners
381 ind = indices(mSanction);
382 for ( i = sizeof(ind) - 1, owner = ({ }); i >= 0; i-- ) {
383 if ( mSanction[ind[i]] & SANCTION_SANCTION ) {
384 owner += ({ ind[i] });
391 * Set the creator of the object. This is usually only done when
392 * the object was created, but for export functionality there is
393 * the possibility to change the creator later on. Apart from that the
394 * creator is the person calling the factory to create an instance.
396 * @param cr - the creator
400 set_creator(object cr)
402 object caller = CALLER;
403 if ( !objectp(caller) )
404 caller = this_object();
406 //! Remove second line - security hole: Only factories are able to set permissions
407 if ( objectp(oCreator) && !_Server->is_a_factory(CALLER) )
408 //!_SECURITY->access_set_creator(0, this_object(), caller) )
409 THROW("Unauthorized call to set_creator() by " +
410 master()->describe_object(caller)+" !", E_ACCESS);
413 require_save(STORE_ACCESS);
417 * Get the creator of the object. If no creator is set the root user
420 * @return the creator of the object
426 if ( !objectp(oCreator) )
433 * Add a functionpair for storage and retrieval of data. Database
434 * uses this to call the functions on loading and saving the object.
437 * @param retrieve_func - function to retrieve the object data
439 * @param restore_func - function to be called in the object for restoring
440 * @return false or true (failed or not)
441 * @see get_data_storage
446 add_data_storage(string ident, function retrieve_func,
448 function restore_func, int|void indexed)
450 if ( !mappingp(mDataStorage) )
451 THROW("Data Storage not initialized !", E_ERROR);
452 if ( strlen(ident)>15)
453 THROW("add_data_storage(): Illegal IDENT-Length > 15", E_ERROR);
454 if ( stringp(mDataStorage[ident]) )
455 THROW(sprintf("Data Storage %s already defined !",ident), E_ERROR);
457 mDataStorage[ident] = ({ retrieve_func, restore_func, indexed });
464 * Get the data storage mapping, but only the _Database object is able
465 * to call this functions.
467 * @return the storage functions pairs (mapping)
468 * @see add_data_storage
470 final mapping get_data_storage()
472 ASSERTINFO(CALLER == _Persistence,"Unauthorized call to get_data_storage()");
477 * The database object calls this function upon loading the object to
478 * restore the access data (ACLs)
480 * @param str - serialized access string
481 * @see unserialize_data
485 restore_access_data(mixed data, string|void index)
487 ASSERTINFO(CALLER == _Database, "Invalid call to restore_access_data()");
489 if (!zero_type(index))
492 case "Sanction" : mSanction = data; break;
493 case "MetaSanction" : mMetaSanction = data; break;
494 case "Creator" : oCreator = data; break;
495 case "Acquire" : oAcquire = data; break;
499 if ( mappingp(data->Sanction) )
500 mSanction = data["Sanction"];
501 if ( mappingp(data->MetaSanction) )
502 mMetaSanction = data["MetaSanction"];
503 oCreator = data["Creator"];
504 oAcquire = data["Acquire"];
511 * The function retrieves the relevant access data to be saved in database.
512 * Only the _Database object is able to call this function.
514 * @return array of access data to be saved
516 * @see restore_access_data
520 retrieve_access_data(string|void index)
522 if ( CALLER != _Database )
524 /* this data has to be stored */
525 if (!zero_type(index))
528 case "Sanction" : return mSanction;
529 case "MetaSanction" : return mMetaSanction;
530 case "Creator" : return oCreator;
531 case "Acquire" : return oAcquire;
537 "Sanction":mSanction,
538 "MetaSanction":mMetaSanction,