security._pike
Go to the documentation of this file.
1 /* Copyright (C) 2000-2006 Thomas Bopp, Thorsten Hampel, Ludger Merkens
2  *
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.
7  *
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.
12  *
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
16  *
17  * $Id: security.pike,v 1.3 2009/06/19 16:13:59 astra Exp $
18  */
19 inherit "/kernel/module";
20 #include <macros.h>
21 #include <access.h>
22 #include <assert.h>
23 #include <attributes.h>
24 #include <roles.h>
25 #include <database.h>
26 #include <classes.h>
27 #include <events.h>
28 //! The security module handles all security issues in sTeam. It
29 //! listens to almost any event globally and tries to block events
30 //! if permission checks fail.
31 class security : public module{
32 public:
33 
34 
35 
36 import Roles;
37 
38 
39 
40 private array sRegisteredPermissions;
41 private mapping mValidObjects = ([ ]);
42 private object security_cache;
43 
44 #define CACHE_AVAILABLE (objectp(security_cache) && objectp(obj))
45 
46 /**
47  * Load this security module and add all global events which
48  * are relevant for security. E.g. should have callback functions
49  * in this module.
50  *
51  */
52 void post_load_module()
53 {
54  security_cache = get_module("Security:cache");
55 }
56 
57 protected:
58  void load_module()
59 {
60  add_global_event(EVENT_MOVE, access_move, PHASE_BLOCK);
61  add_global_event(EVENT_GET_INVENTORY, access_read, PHASE_BLOCK);
62  add_global_event(EVENT_ATTRIBUTES_CHANGE, access_attribute_change,
63  PHASE_BLOCK);
64  add_global_event(EVENT_ATTRIBUTES_ACQUIRE, access_attribute_acquire,
65  PHASE_BLOCK);
66  add_global_event(EVENT_ATTRIBUTES_LOCK, access_attribute_lock,
67  PHASE_BLOCK);
68  add_global_event(EVENT_DOWNLOAD, access_read, PHASE_BLOCK);
69  add_global_event(EVENT_DUPLICATE, access_read, PHASE_BLOCK);
70  add_global_event(EVENT_UPLOAD, access_write, PHASE_BLOCK);
71  add_global_event(EVENT_LOCK, access_write, PHASE_BLOCK);
72  add_global_event(EVENT_UNLOCK, access_write, PHASE_BLOCK);
73  add_global_event(EVENT_ATTRIBUTES_QUERY,access_read_attribute,PHASE_BLOCK);
74  add_global_event(EVENT_DELETE, access_delete, PHASE_BLOCK);
75  add_global_event(EVENT_REGISTER_ATTRIBUTE, access_register_attribute,
76  PHASE_BLOCK);
77  add_global_event(EVENT_EXECUTE, access_execute, PHASE_BLOCK);
78  add_global_event(EVENT_REMOVE_MEMBER, access_group_remove_member,
79  PHASE_BLOCK);
80  add_global_event(EVENT_ADD_MEMBER, access_group_add_member, PHASE_BLOCK);
81  add_global_event(EVENT_GRP_ADD_PERMISSION, access_group_add_permission,
82  PHASE_BLOCK);
83  add_global_event(EVENT_GRP_ADDMUTUAL, access_group_addmutual, PHASE_BLOCK);
84  add_global_event(EVENT_USER_CHANGE_PW, access_change_password,
85  PHASE_BLOCK);
86  add_global_event(EVENT_SANCTION, access_sanction_object, PHASE_BLOCK);
87  add_global_event(EVENT_SANCTION_META, access_sanction_object_meta,
88  PHASE_BLOCK);
89  add_global_event(EVENT_ANNOTATE, access_annotate, PHASE_BLOCK);
90  add_global_event(EVENT_ARRANGE_OBJECT, access_arrange, PHASE_BLOCK);
91 
92  sRegisteredPermissions = allocate(16);
93  for ( int i = 0; i < 16; i++ )
94  sRegisteredPermissions[i] = "free";
95  sRegisteredPermissions[8] = "sanction";
96  sRegisteredPermissions[0] = "read";
97  sRegisteredPermissions[1] = "execute";
98  sRegisteredPermissions[2] = "move";
99  sRegisteredPermissions[3] = "write";
100  sRegisteredPermissions[4] = "insert";
101  sRegisteredPermissions[5] = "annotate";
102 }
103 
104 public:
105 
106 /**
107  * This is a callback function called from the master() object when this
108  * module is upgraded. The master() object is a concept of the pike
109  * programming language. Upgrading is a key concept of sTeam.
110  *
111  */
112 void upgrade()
113 {
114  if ( CALLER != master() )
115  return;
116  remove_global_events();
117 }
118 
119  program pAccess = (program)"/base/access.pike";
120  program pUser = (program)"/net/coal/login.pike";
121 
122 int is_valid(object obj)
123 {
124  function|program prg = object_program(obj);
125  if ( functionp(prg) )
126  return 0;
127  if ( Program.inherits(prg, pAccess) || Program.inherits(prg, pUser) )
128  return 1;
129  return 0;
130 }
131 
132 object get_valid_caller(object obj, mixed bt)
133 {
134  int sz = sizeof(bt);
135  object caller;
136  int foundobj = 0;
137 
138  sz -= 2;
139  for ( ; sz >= 0; sz-- ) {
140  if ( functionp(bt[sz][2]) ) {
141  function f = bt[sz][2];
142  caller = function_object(f);
143  if ( caller == obj ) {
144  foundobj = 1;
145  }
146  else if ( foundobj ) {
147  if ( IS_SOCKET(caller) )
148  return caller->get_user_object();
149  if ( is_valid(caller) )
150  return caller;
151  }
152  }
153  }
154  steam_error(sprintf("No valid object found for %O in \n%O\n",
155  obj, bt));
156 }
157 
158 
159 /**
160  * check if the given object is a valid proxy
161  *
162  * @param obj - the object to check
163  * @return if valid or not
164  * @see valid_object
165  * @see valid_user
166  * @see valid_group
167  */
168 bool valid_proxy(object obj)
169 {
170  object o;
171 
172  if ( obj == 0 || !functionp(obj->get_object) )
173  return false;
174 
175  o = obj->get_object();
176  if ( !objectp(o) )
177  return true;
178 
179  return o->trust(obj);
180 }
181 
182 /**
183  * check if the given object is a valid user
184  *
185  * @param obj - the object to check
186  * @return if object is valid user or not
187  * @see valid_object
188  * @see valid_user
189  * @see valid_group
190  */
191 bool valid_user(object obj)
192 {
193  if ( valid_proxy(obj) )
194  obj = obj->get_object();
195 
196  program pUser = (program)"/classes/User.pike"; // cache User
197 
198  if ( object_program(obj) == pUser ) {
199  SECURITY_LOG("[%s] is valid user !", obj->get_identifier());
200  return true;
201  }
202  return false;
203 }
204 
205 /**
206  * check if the object is a valid object, that is inherits access.pike
207  *
208  * @param obj - the object to check
209  * @return true or false
210  * @see valid_object
211  * @see valid_user
212  * @see valid_group
213  */
214 bool valid_object(object obj)
215 {
216  program pObject, pAccess;
217  function|program prg;
218 
219  if ( !objectp(obj) ) {
220  werror("valid_object(0) by %O\n", backtrace());
221  return false;
222  }
223  if ( valid_proxy(obj) ) {
224  obj = obj->get_object();
225  }
226  if ( !objectp(obj) )
227  return false;
228 
229  prg = object_program(obj);
230  if ( functionp(prg) )
231  prg = function_program(prg);
232 
233  if ( !programp(prg) )
234  werror("Warning prg is not a valid prorgram: %O for object: %O\n", prg, obj);
235 
236  if ( mValidObjects[prg] )
237  return true;
238 
239  pObject = (program)"/classes/Object.pike";
240  pAccess = (program)"/base/access.pike";
241  /* see if it inherits the access object to make sure
242  * access functions are from the right place
243  * or if the object is /classes/Object.pike clone itself */
244  if ( Program.inherits(prg, pAccess) || Program.inherits(prg, pUser) ||
245  prg == pObject )
246  {
247  mValidObjects[prg] = true;
248  return true;
249  }
250  return false;
251 }
252 
253 /**
254  * see if the object is a valid group, that is clone of Group.pike
255  *
256  * @param obj - the object to check
257  * @return true or false
258  * @see valid_object
259  * @see valid_user
260  * @see valid_group
261  */
262 bool valid_group(object obj)
263 {
264  if ( valid_proxy(obj) ) obj = obj->get_object();
265  program pGroup = (program)"/classes/Group.pike";
266  if ( object_program(obj) == pGroup )
267  return true;
268 
269  return false;
270 }
271 
272 
273 /**
274  * check role permission of user groups recursively
275  *
276  * @param grp - the group that wants to write
277  * @param accessRole - the role that the group must feature
278  * @return if successfull or not
279  * @see try_access_object
280  */
281 final bool
282 check_role_permission(object grp, int roleBit, void|mixed ctx)
283 {
284  object obj = 0;
285 
286  if ( roleBit == 0 ) // no special role permission granted
287  return false;
288 
289  grp = grp->get_object();
290  if ( !objectp(grp) )
291  return false;
292 
293  ASSERTINFO(valid_group(grp), "Group:" + grp->get_identifier() +
294  " is not a valid group");
295  SECURITY_LOG("Checking role permissions on %s" +
296  "(permission="+grp->get_permission()+")",
297  grp->get_identifier() );
298 
299  if ( grp->features(roleBit, ctx) )
300  return true; // group has permission itself
301 
302  array grp_groups = grp->get_groups();
303  foreach( grp_groups, object member ) {
304  LOG("Accessing indirectly by " + member->get_identifier());
305  if ( objectp(member) && valid_group(member) ) {
306  if ( check_role_permission(member, roleBit, ctx) )
307  return true;
308  }
309  }
310  /* check the parent group for permission otherwise */
311  return false;
312 }
313 
314 /**
315  * try to access an object by one of the users groups
316  *
317  * @param obj - the object accessed
318  * @param user - the active user
319  * @param accessBit - the access Bit used
320  * @return true or false
321  * @see check_access
322  */
323 private:
324 private bool
325 check_access_user(object obj, object user, int accBit, int roleBit,bool meta,void|RoleContext ctx)
326 {
327  int i;
328  array groups;
329 
330  int userAcc = ACCESS_GRANTED;
331  int groupAcc = ACCESS_GRANTED;
332 
333  SECURITY_LOG("check_access_user(%s %s,"+
334  accBit + ","+ roleBit+","+ meta+")",
335  (objectp(obj) ? obj->get_identifier() +
336  "["+obj->get_object_id()+"]," : "null,"),
337  user->get_identifier());
338 
339  if ( CACHE_AVAILABLE && !meta ) {
340  if ( security_cache->get_permission(obj, user) &
341  (accBit<<SANCTION_SHIFT_DENY) )
342  return false;
343  else if ( security_cache->get_permission(obj, user) & accBit ) {
344  SECURITY_LOG("Cache hit: true !")
345  return true;
346  }
347  }
348  if ( objectp(obj) )
349  {
350  userAcc = obj->try_access_object(user, accBit, meta);
351  if ( userAcc == ACCESS_GRANTED ) {
352  if ( CACHE_AVAILABLE ) {
353  security_cache->add_permission(obj, user, accBit);
354  }
355  return true;
356  }
357  }
358 
359  groups = user->get_groups();
360 
361  SECURITY_LOG("Checking access for " + sizeof(groups) +
362  " groups (accessbit="+accBit+",rolebit="+roleBit+")!");
363  /* go through all groups and see if the general roleBit works
364  * or if the group is able to access the object */
365  for ( i = sizeof(groups) - 1; i >= 0; i-- ) {
366  if ( !objectp(groups[i]) )
367  THROW("User is in 0-group - this should not happen !", E_ERROR);
368 
369  if ( roleBit > 0 ) {
370  if ( check_role_permission(groups[i], roleBit, ctx) ) {
371  SECURITY_LOG("Role permission success !");
372  if ( CACHE_AVAILABLE && !meta )
373  security_cache->add_permission(obj, user, accBit);
374  return true;
375  }
376  }
377  /* if user/group access is once blocked only the above role
378  * permission might work
379  * this is to still have the admin groups do everything
380  */
381  if ( accBit > 0 && userAcc != ACCESS_BLOCKED )
382  {
383  groupAcc = obj->try_access_object_group(groups[i], accBit, meta);
384  if ( groupAcc == ACCESS_GRANTED ) {
385  if ( CACHE_AVAILABLE && !meta )
386  security_cache->add_permission(obj, user, accBit);
387  SECURITY_LOG("Group direct access !");
388  return true;
389  }
390  }
391  }
392  if ( CACHE_AVAILABLE && !meta )
393  security_cache->add_permission(obj,user,accBit<<SANCTION_SHIFT_DENY);
394  return false;
395 }
396 
397 public:
398 
399 private:
400 private mapping join_permissions(mapping p1, mapping p2)
401 {
402  array sanctioned = indices(p1) | indices(p2);
403  mapping permissions = ([ ]);
404  foreach(sanctioned, object s) {
405  permissions[s] = p1[s] | p2[s];
406  }
407  return permissions;
408 }
409 
410 public:
411 
412 mapping|int get_permissions(object obj, void|object grp)
413 {
414 
415  if ( objectp(grp) ) {
416  mapping permissions = get_permissions(obj);
417  int p = permissions[grp];
418  foreach(grp->get_groups(), object g) {
419  p |= permissions[g];
420  object pgroup = g->get_parent();
421  while (objectp(pgroup)) {
422  p |= permissions[pgroup];
423  pgroup = pgroup->get_parent();
424  }
425  }
426  return p;
427  }
428 
429  mapping permission = obj->get_sanction();
430  mixed acquire = obj->get_acquire();
431  // function or object
432  if (functionp(acquire))
433  acquire=acquire();
434  // if acquire is set we get the acquired permissions
435  if (objectp(acquire))
436  permission = join_permissions(permission, get_permissions(acquire));
437 
438  object creator = obj->get_creator() || USER("root");
439  permission[creator] = SANCTION_ALL;
440 
441  return permission;
442 }
443 
444 
445 /**
446  * check on some accessBit/roleBit. Object can be null when just
447  * the roleBit of an user should be checked.
448  *
449  * @param obj - the object accessed (must be proxy)
450  * @param caller - the calling object (must be the proxy or socket)
451  * @param accessBit - the bit used for access
452  * @return true or false
453  * @see check_access_group
454  */
455 bool
456 check_access(object obj,object caller,int accessBit,int roleBit,bool meta, void|mixed data)
457 {
458  object read_user;
459  string sanctions;
460  int i;
461 
462  sanctions = " for (ROLE="+roleBit+"), ";
463  for ( i = 0; i <= 8; i++ )
464  if ( accessBit & (1<<i) )
465  sanctions += sRegisteredPermissions[i] + ",";
466 
467  SECURITY_LOG("----------------------------------------------------------"+
468  "\n--- "+(meta?"META":"")+" Access checking "+
469  sanctions+ " by " +
470  function_name(backtrace()[-3][2]) + "() on " +ctime(time()));
471  SECURITY_LOG("params: %O %O", obj, caller);
472  if ( objectp(obj) )
473  SECURITY_LOG("Checking access on [%O, %d]",
474  obj->get_identifier(),
475  obj->get_object_id());
476 
477  if ( trust(caller) )
478  return true; // some objects are allowed to do everything
479  SECURITY_LOG("CALLER: %O", caller);
480 
481  SECURITY_LOG("EUID: %s",(objectp(geteuid()) ? geteuid()->get_identifier() :
482  "---"));
483 
484  // access for world-user-group, no login required
485  object grp = _WORLDUSER;
486  if ( objectp(obj) && objectp(grp) &&
487  obj->try_access_object(grp, accessBit, meta) )
488  {
489  SECURITY_LOG("Access granted################################\n");
490  return true;
491  }
492 
493  object euid = geteuid();
494  if ( objectp(euid) )
495  read_user = euid;
496  else
497  read_user = this_user();
498  if ( !objectp(read_user) ) {
499  SECURITY_LOG("Access Granted - no active user object #####\n");
500  return true; // the server is rebooting, so no active user
501  }
502 
503  SECURITY_LOG("ACTIVE:" + master()->stupid_describe(read_user, 255)+",%O",
504  read_user->get_identifier());
505 
506 
507  RoleContext ctx = RoleContext(obj, data);
508 
509  if ( check_access_user(obj, read_user, accessBit, roleBit, meta, ctx) )
510  return true;
511 
512  SECURITY_LOG("** Access denied **");
513  THROW(sprintf("Access denied for user %O(%O) accessing %O using %d called by %O",
514  this_user(), read_user, obj, accessBit, caller),
515  E_ACCESS);
516  return false;
517 }
518 
519 /**
520  * check for read access
521  *
522  * @param obj - the object accessed
523  * @param caller - the calling object
524  * @return true or false
525  * @see access_write
526  */
527 bool access_read(int e, object obj, object caller)
528 {
529  mixed err;
530  err = catch(check_access(obj, caller,SANCTION_READ,ROLE_READ_ALL,false));
531  if ( err ) {
532  if (objectp(obj) && functionp(obj->get_identifier) ) {
533  string message = sprintf("\nNo READ access on %O for %O (%O)",
534  (objectp(obj)?obj->get_identifier():"none"),
535  this_user(), geteuid());
536  if ( objectp(err) && functionp(err->set_message) )
537  err->set_message(err->message()+"\n"+message);
538  else if ( arrayp(err) )
539  err[0] += message;
540  }
541  throw(err);
542  }
543  return true;
544 }
545 
546 /**
547  * check for write access
548  *
549  * @param obj - the object accessed
550  * @param caller - the calling object
551  * @return true or false
552  * @see access_read
553  */
554 bool access_write(int e, object obj, object caller)
555 {
556  mixed err;
557  err = catch(check_access(obj,caller,SANCTION_WRITE, ROLE_WRITE_ALL,false));
558  if ( err ) {
559  if ( objectp(obj) ) {
560  string message = sprintf("\nNo WRITE access on %O for %O (%O)",
561  (objectp(obj)?obj->get_identifier():"none"),
562  this_user(), geteuid());
563  if ( objectp(err) && functionp(err->set_message) )
564  err->set_message(err->message()+"\n"+message);
565  else if ( arrayp(err) )
566  err[0] += message;
567  }
568  throw(err);
569  }
570  return true;
571 }
572 
573 /**
574  * Check whether an object is able to set the creator of object obj.
575  * Usually the creator is only set when the object is created, but
576  * export/import functionality requires to change such values.
577  *
578  * @param object obj - the object with a new creator
579  * @param object caller - the calling object
580  * @return true or throws an error.
581  */
582 bool access_set_creator(int e, object obj, object caller)
583 {
584  if ( _Server->is_a_factory(CALLER) )
585  return true;
586  return check_access(obj, caller, SANCTION_ALL, ROLE_ALL_ROLES, true);
587 }
588 
589 /**
590  * check access for deleting objects. Same as write access currently.
591  *
592  */
593 bool access_delete(int e, object obj, object caller)
594 {
595  return check_access(obj, caller, SANCTION_WRITE, ROLE_WRITE_ALL, false);
596 }
597 
598 /**
599  * check access for deleting objects. Same as write access currently.
600  *
601  */
602 bool access_register_module(int e, object obj, object caller)
603 {
604  return check_access(0, caller, 0, ROLE_REGISTER_MODULES, false);
605 }
606 /**
607  * check access for deleting objects. Same as write access currently.
608  *
609  * @param
610  * @return
611  * @see
612  */
613 bool access_register_class(int e, object obj, object caller)
614 {
615  return check_access(0, caller, 0, ROLE_REGISTER_CLASSES, false);
616 }
617 
618 /**
619  * access_move
620  *
621  * @param obj - the object accessed
622  * @param caller - the calling object
623  * @param dest - destination of movement
624  * @return true or false
625  * @see access_read
626  */
627 bool access_move(int e, object obj, object caller, object from, object dest)
628 {
629 #if 0
630  if ( caller == obj->get_environment() )
631  return true;
632 #endif
633 
634  /* if the caller is the object, then the user moves herself !
635  * otherwise check insert access */
636  LOG("CALLER is user ?:"+valid_user(caller));
637 
638  if ( !valid_user(obj) ) {
639  // Inserting objects into a room requires insert permissions
640  if (!check_access(dest, caller, SANCTION_INSERT, ROLE_INSERT_ALL, false))
641  return false;
642  }
643  else if ( objectp(dest) ) {
644  // moving the user somewhere only requires permissions for the user
645  if (!check_access(dest, obj, SANCTION_READ, ROLE_READ_ALL, false))
646  return false;
647  }
648 
649  object env = obj->get_environment();
650 
651  mixed err;
652 
653  // if the user/caller is able to move the room, she can move the
654  // object in the container/room too
655  if ( objectp(env) ) {
656  // catch this block - access failure is no problem
657  err = catch {
658  if ( check_access(env, caller,SANCTION_MOVE,ROLE_MOVE_ALL,false) ) {
659  if ( CACHE_AVAILABLE ) {
660  security_cache->remove_permission(obj);
661  }
662  return true;
663  }
664  };
665  }
666 
667  err = catch(check_access(obj, caller, SANCTION_MOVE,ROLE_MOVE_ALL,false));
668  if ( err ) {
669  if ( objectp(obj) ) {
670  string message = sprintf("\n%s %s\n",
671  "No access to MOVE", obj->get_identifier());
672  if ( objectp(err) && functionp(err->set_message) )
673  err->set_message(err->message()+"\n"+message);
674  else if ( arrayp(err) )
675  err[0] += message;
676  }
677  throw(err);
678  }
679 
680 
681  if ( CACHE_AVAILABLE )
682  security_cache->remove_permission(obj);
683  return true;
684 }
685 
686 /**
687  * Check if a user/object is able to annotated an object.
688  *
689  * @param object obj - the object to annotate
690  * @param object caller - the calling object
691  * @param annotation - the added annotation
692  * @return true or throws an error
693  */
694 bool access_annotate(int e, object obj, object caller, object annotation)
695 {
696  if ( _Server->is_a_factory(caller) ) // trust any factory for creation
697  return true; // ok, for any factory
698 
699  mixed err = catch(check_access(obj, caller, SANCTION_ANNOTATE,
700  ROLE_ANNOTATE_ALL, false));
701  if ( err ) {
702  if ( objectp(obj) ) {
703  string message = sprintf("\n%s %s\n",
704  "No access to ANNOTATE", obj->get_identifier());
705  if ( objectp(err) && functionp(err->set_message) )
706  err->set_message(message+"\n"+err->message());
707  else if ( arrayp(err) )
708  err[0] += message;
709  }
710  throw(err);
711  }
712  return true;
713 }
714 
715 /**
716  * Check if arranging an object is allowed.
717  *
718  * @param object obj - the object to arrange
719  * @param object caller - the calling object
720  * @param float x - the new x position
721  * @param float y - the new y position
722  * @param float z - the new z position
723  * @param bool locked - is the position already locked (returns false)
724  * @return true or false or throws an error
725  */
726 bool access_arrange(int e, object obj, object caller, float x, float y, float z,
727  bool locked)
728 {
729  if ( locked ) return false;
730 
731  if ( !check_access(obj, caller, SANCTION_WRITE, ROLE_WRITE_ALL, false) )
732  return false;
733  return true;
734 }
735 
736 /**
737  * check access for creating an object
738  *
739  * @param caller - the calling object
740  * @return true or false
741  * @see access_create_group
742  */
743 bool access_create_object(int e, object caller)
744 {
745  if ( _Server->is_a_factory(caller) ) // trust any factory for creation
746  return true; // ok, for any factory
747  if ( caller->get_object_class() & CLASS_DOCLPC ) {
748  // in general means its a factory,but only for the object to be created
749  if ( object_program(CALLER) == caller->get_program() )
750  if ( check_access(caller, caller, SANCTION_EXECUTE, ROLE_EXECUTE_ALL, false) )
751  return true; // need access on the DocLPC in this case !
752  }
753  object factory = _Server->get_factory(caller->get_object_class());
754  if ( !objectp(factory) )
755  factory = _Server->get_factory(CLASS_DOCUMENT);
756  if ( !check_access(factory, caller, SANCTION_EXECUTE, ROLE_EXECUTE_ALL, false) )
757  return false;
758  return true;
759 }
760 
761 /**
762  * Check if its valid to add an object to the group grp.
763  *
764  * @param grp - the group to add someone to
765  * @param caller - the calling object
766  * @param add - the group/user to add
767  * @param bool pw - group password check was done and successfull
768  * @return true or false or throws an error
769  */
770 bool access_group_add_member(int e, object grp, object caller, object add, bool pw)
771 {
772  if ( pw ) {
773  if ( security_cache )
774  security_cache->remove_permission_user(add);
775  return true;
776  }
777 
778  if ( _Server->is_a_factory(caller) || _Server->is_module(caller) ) {
779  if ( security_cache )
780  security_cache->remove_permission_user(add);
781  return true;
782  }
783 
784  if ( !check_access(grp, caller, SANCTION_INSERT, ROLE_INSERT_ALL, false) )
785  return false;
786  if ( security_cache )
787  security_cache->remove_permission_user(add);
788  return true;
789 
790 }
791 
792 /**
793  * Check if a user is allowed to add users to all groups in a
794  * mutual exclusive group cluster.
795  *
796  * @param grp - the group to add "add" to
797  * @param caller - the calling object
798  * @add add - the group to add to "grp"
799  * @return true - access is granted
800  * false - access denied
801  * throws an error according to check_access
802  * @see check_access
803  */
804 bool access_group_addmutual(int e, object grp, object caller, object add)
805 {
806  if (!valid_group(grp) || !valid_group(add))
807  return false;
808  array need_access = grp->get_mutual_list();
809 
810  foreach(need_access, object g)
811  if (!check_access(g, caller, SANCTION_INSERT,
812  ROLE_INSERT_ALL, true))
813  return false;
814  return check_access(add, caller, SANCTION_INSERT, ROLE_INSERT_ALL, true);
815 }
816 
817 /**
818  * Check if the calling object and the current user are
819  * allowed to create a new group.
820  *
821  * @param object caller - the calling object
822  * @return true or false or throws an access error
823  */
824 bool access_create_group(int e, object caller)
825 {
826  if ( _Server->is_a_factory(caller) )
827  return true;
828  object factory = _Server->get_factory(CLASS_GROUP);
829  if ( !check_access(factory, caller, SANCTION_EXECUTE, ROLE_EXECUTE_ALL, false))
830  return false;
831  return true;
832 }
833 
834 /**
835  * Check whether a calling object and the current user
836  * are able to create a new user. Usually this is allowed since
837  * people are able to register their user themself.
838  *
839  * @param object caller - the calling object
840  * @return true or false or throws access error
841  */
842 bool access_create_user(int e, object caller)
843 {
844  if ( _Server->is_a_factory(caller) )
845  return true;
846  object factory = _Server->get_factory(CLASS_USER);
847  if ( !check_access(factory, caller, SANCTION_EXECUTE, ROLE_EXECUTE_ALL , false))
848  return false;
849  return true;
850 }
851 
852 /**
853  * Check if the calling object is allowed to create a new document.
854  *
855  * @param object caller - the calling object
856  * @return true or false or throws an access error.
857  */
858 bool access_create_document(int e, object caller)
859 {
860  if ( _Server->is_a_factory(caller) )
861  return true;
862  object factory = _Server->get_factory(CLASS_DOCUMENT);
863  if ( !check_access(factory, caller, SANCTION_EXECUTE, ROLE_EXECUTE_ALL , false))
864  return false;
865  return true;
866 }
867 
868 /**
869  * Check if meta sanction is changeable by caller.
870  *
871  * @param object obj - the object to change meta sanction access
872  * @param object caller - the calling object
873  * @param object grp - the group to sanction
874  * @param int p - the meta access persmissions
875  *
876  * @return true, false or throw access
877  */
878 bool access_sanction_object_meta(int e, object obj, object caller, object grp, int p)
879 {
880  if ( _Server->is_a_factory(caller) )
881  return true;
882  check_access(obj, caller, p, ROLE_SANCTION_ALL, false);
883  check_access(obj, caller, SANCTION_SANCTION, ROLE_SANCTION_ALL, true);
884  check_access(obj, caller, p, ROLE_SANCTION_ALL, true);
885 }
886 
887 /**
888  * Check if caller has permissions to sanction group grp with access
889  * 'p'.
890  *
891  * @param object obj - the object to change meta sanction access
892  * @param object caller - the calling object
893  * @param object grp - the group to sanction
894  * @param int p - the access persmissions
895  * @return true or false or throw access error
896  */
897 bool access_sanction_object(int e, object obj, object caller, object grp, int p)
898 {
899  if ( _Server->is_a_factory(caller) )
900  return true;
901 
902  check_access(obj, caller, p|SANCTION_SANCTION, ROLE_SANCTION_ALL, true);
903  check_access(obj, caller, p|SANCTION_SANCTION, ROLE_SANCTION_ALL, false);
904  if ( CACHE_AVAILABLE )
905  security_cache->remove_permission(obj);
906 }
907 
908 /**
909  *
910  * Check if the calling object has permission to listen to events on obj.
911  *
912  * @param obj - the object accessed
913  * @param caller - the calling object
914  * @return true or false
915  * @see access_read
916  */
917 bool access_event_listen(int e, object obj, object caller)
918 {
919  return check_access(obj, caller, SANCTION_READ, ROLE_READ_ALL, false);
920 }
921 
922 /**
923  * Check if calling object is able to change data in object 'obj'. This
924  * usually means changing a documents content.
925  *
926  * @param obj - the object accessed
927  * @param caller - the calling object
928  * @return true or false
929  * @see access_read
930  */
931 bool access_data_change(int e, object obj, object caller, mixed id, mixed data)
932 {
933  if ( _Server->is_a_factory(caller) ) // trust any factory for creation
934  return true; // ok, for any factory
935 
936  if ( !access_write(e, obj, caller) )
937  THROW("No Access to change data !", E_ACCESS);
938  return true;
939 }
940 
941 /**
942  * Check if caller is able to change attributes in object 'obj'.
943  *
944  * @param object obj - the object to change an attribute.
945  * @param object caller - the calling object.
946  * @param attr - the attribute to change
947  * @return true or false or throw access error
948  */
949 bool
950 access_attribute_change(int e, object obj, object caller, mixed attr)
951 {
952  // LOG("Access for changing the attribute ?");
953  if ( _Server->is_a_factory(caller) ) // trust any factory for creation
954  return true; // ok, for any factory
955  // LOG("not a factory ");
956 
957  if ( !access_write(e, obj, caller) )
958  THROW("No Access to change attributes !", E_ACCESS);
959  return true;
960 }
961 
962 /**
963  * Check whether an object has permissions to lock attributes in object 'obj'.
964  *
965  * @param object obj - the object to lock attributes in.
966  * @param object caller - the calling object.
967  * @param bool l_or_ul - lock or unlock attributes.
968  * @return true or false or throw an access error.
969  */
970 bool access_attribute_lock(int e, object obj, object caller, bool l_or_ul)
971 {
972  if ( _Server->is_a_factory(caller) ) // trust any factory for creation
973  return true; // ok, for any factory
974  if ( !access_write(e, obj, caller) )
975  THROW("No Access to lock/unlock attributes !", E_ACCESS);
976  return true;
977 }
978 
979 /**
980  * Check if caller is able to change acquiring setting for an attribute.
981  *
982  * @param object obj - the object.
983  * @param object caller - the calling object.
984  * @param mixed key - the attribute to change acquiring for.
985  * @param mixed acquire - new acquiring setting.
986  * @return true or false or throw access error.
987  */
988 bool
989 access_attribute_acquire(int e, object obj, object caller, mixed key, mixed acquire)
990 {
991  if ( objectp(acquire) && !valid_proxy(acquire) )
992  THROW("Acquring must point to proxy !", E_ERROR);
993 
994  if ( _Server->is_a_factory(caller) ) // trust any factory for creation
995  return true; // ok, for any factory
996  if ( _Server->is_module(caller) )
997  return true;
998 
999  if ( !access_write(e, obj, caller) )
1000  THROW("No Access to write data !", E_ACCESS);
1001  return true;
1002 }
1003 
1004 /**
1005  * Check if the caller is able to read an attribute.
1006  *
1007  * @param object obj - the object to read.
1008  * @param object caller - the calling object.
1009  * @param mixed key - the attribute to read.
1010  * @return true or false or throw access denied.
1011  */
1012 bool
1013 access_read_attribute(int e, object obj, object caller, mixed key)
1014 {
1015  if ( !check_access(obj, caller, SANCTION_READ, ROLE_READ_ALL, false, key) )
1016  THROW("No Access to read data !", E_ACCESS);
1017  return true;
1018 }
1019 
1020 /**
1021  * Check whether the calling object is able to register attributes.
1022  *
1023  * @param object obj - the object to register an attribute.
1024  * @param object caller - the calling object.
1025  * @param mixed key - the attribute to register.
1026  * @return true or false or throw access denied.
1027  */
1028 bool
1029 access_register_attribute(int e, object obj, object caller, mixed key)
1030 {
1031  object factory = _Server->get_factory(obj->get_object_class());
1032  if ( caller == factory ) return true;
1033 
1034  if ( !access_write(e, obj, caller) )
1035  THROW("No Access to register data !", E_ACCESS);
1036  return true;
1037 }
1038 
1039 /**
1040  * access_execute
1041  *
1042  * @param obj - the object accessed
1043  * @param caller - the calling object
1044  * @return true or false
1045  * @see access_read
1046  */
1047 bool access_execute(int e, object obj, object caller)
1048 {
1049  if ( _Server->is_a_factory(caller) ) // trust any factory for creation
1050  return true; // ok, for any factory
1051 
1052  mixed err =
1053  catch(check_access(obj,caller,SANCTION_EXECUTE,ROLE_EXECUTE_ALL,false));
1054  if ( err ) {
1055  if ( objectp(obj) ) {
1056  FATAL("Access error: %O", err);
1057  string message = sprintf("%s %s",
1058  "No access to EXECUTE", obj->get_identifier());
1059  if ( objectp(err) && functionp(err->set_message) )
1060  err->set_message(message+"\n"+err->message());
1061  else if ( arrayp(err) )
1062  err[0] += message;
1063  }
1064  throw(err);
1065  }
1066 }
1067 
1068 /**
1069  * Check if the caller is able to add permissions to the group 'grp'.
1070  *
1071  * @param object grp - the group to add permissions.
1072  * @param object caller - the calling object.
1073  * @param int permission - permissions to add.
1074  * @return true or false or throw access denied.
1075  */
1076 bool
1077 access_group_add_permission(int e, object grp, object caller, int permission)
1078 {
1079  ASSERTINFO(valid_group(grp), "No valid group in group_add_permission()");
1080  if ( !check_access(0, caller, 0, ROLE_GIVE_ROLES, false) )
1081  return false;
1082  if ( !check_access(grp, caller, SANCTION_WRITE, ROLE_WRITE_ALL, false) )
1083  return false;
1084  return true;
1085 }
1086 
1087 /**
1088  * add a user or list of users to a group
1089  *
1090  * @param object grp - the group to remove a member
1091  * @param object caller - the calling object.
1092  * @param object user - the user or group to remove.
1093  * @return number of users successfully added
1094  */
1095 bool access_group_remove_member(int e, object grp, object caller, object user)
1096 {
1097  if ( user == this_user() )
1098  return true;
1099  if ( !check_access(grp, caller, SANCTION_INSERT, ROLE_INSERT_ALL, false) )
1100  return false;
1101  if ( security_cache )
1102  security_cache->remove_permission_user(user);
1103  return true;
1104 }
1105 
1106 /**
1107  * set acquiring object for object "obj"
1108  *
1109  * @param obj - the object that acquires
1110  * @param from - the object to acquire from
1111  * @return successfully or not
1112  */
1113 bool access_acquire(int e, object obj, object caller, object from)
1114 {
1115  if ( _Server->is_a_factory(caller) )
1116  return true;
1117  if ( !check_access(obj,caller,SANCTION_WRITE, ROLE_WRITE_ALL,true) )
1118  return false;
1119  if ( !check_access(obj,caller,SANCTION_SANCTION, ROLE_SANCTION_ALL,true) )
1120  return false;
1121  if ( CACHE_AVAILABLE )
1122  security_cache->remove_permission(obj);
1123  return true;
1124 }
1125 
1126 
1127 /**
1128  * Check if caller has permissions to change password for user.
1129  *
1130  * @param object user - the user object.
1131  * @param object caller - the calling object.
1132  * @return true or false or throw access denied.
1133  */
1134 bool access_change_password(int e, object user, object caller)
1135 {
1136  object factory = _Server->get_factory(user->get_object_class());
1137  LOG("Caller:"+master()->describe_object(caller) + ", Factory:"+
1138  master()->describe_object(factory));
1139  if ( caller == factory ) return true;
1140 
1141  if ( caller != user &&
1142  (!IS_SOCKET(caller) || user != caller->get_user_object()) &&
1143  !check_access(user, caller, 0, ROLE_CHANGE_PWS, false) )
1144  return false;
1145  return true;
1146 }
1147 
1148 /**
1149  * Get the identifier string for this module.
1150  *
1151  * @return The module identifier.
1152  */
1153 string get_identifier()
1154 {
1155  return "security";
1156 }
1157 
1158 /**
1159  * The function returns if some object is especially trusted.
1160  *
1161  * @param object obj - the object to check.
1162  * @return true or false.
1163  */
1164 final bool trust(object obj)
1165 {
1166  if ( obj == this_object() ) return true;
1167  if ( ::trust(obj) ) return true;
1168  if ( obj == master() ) return true;
1169  if ( obj == _Database ) return true;
1170  if ( obj == _Persistence ) return true;
1171  if ( obj == _Server ) return true;
1172  if ( obj == _FILEPATH ) return true;
1173  return false;
1174 }
1175 
1176 /**
1177  * Check if a user is allowed to access the given objects.
1178  *
1179  * @param array objs - an array of objects to check access for.
1180  * @return Mapping with object:permissions of current user.
1181  * @see check_access
1182  */
1183 mapping
1184 check(array objs)
1185 {
1186  int i;
1187  object user;
1188  mapping m;
1189 
1190  foreach(objs, object obj) {
1191  m[obj] = 0;
1192  for ( i = sizeof(sRegisteredPermissions) - 1 ; i >= 0; i-- ) {
1193  m[obj] |= 1<<i;
1194  }
1195  }
1196  return m;
1197 }
1198 
1199 /**
1200  * Check access for a given user for accessBit and roleBit.
1201  *
1202  * @param object obj - the object to check.
1203  * @param object user - the user to check access for.
1204  * @param int accBit - the access bit to check.
1205  * @param int roleBit - the roleBit to check.
1206  * @param bool meta - if normal or meta permissions are to check.
1207  * @return true or false or throw an access error.
1208  */
1209 bool
1210 check_user_access(object obj, object user, int accBit, int roleBit, bool meta)
1211 {
1212  if ( !objectp(user) )
1213  THROW("User undefined !", E_ACCESS);
1214  object grp = _WORLDUSER;
1215  if ( objectp(obj) && objectp(grp) &&
1216  obj->try_access_object(grp, accBit, meta) )
1217  return 1;
1218 
1219  if ( accBit >= (1<<16) )
1220  steam_error("Wrong accBit check for check_access_user(), only 16 Bits "+
1221  "allowed !");
1222 
1223  if ( !roleBit )
1224  roleBit = accBit; // use corresponding roleBit
1225 
1226  return result;
1227 }
1228 
1229 /**
1230  * Get the meta access of object 'obj' for user 'user'.
1231  *
1232  * @param object obj - the object to get meta access for.
1233  * @param object user - the user to get meta access for.
1234  * @return the meta access bit string.
1235  */
1236 int get_meta_access(object obj, object user)
1237 {
1238  int meta = obj->query_meta_sanction(user);
1239  for ( int i = 0; i < 16; i++ )
1240  if ( check_user_access(obj, user, 1<<i,1<<i, true) )
1241  meta |= (1<<i);
1242  return meta;
1243 }
1244 
1245 
1246 
1247 /**
1248  * Get an array of string descriptions for permissions.
1249  *
1250  * @return array of string descriptions.
1251  */
1252 array get_sanction_strings()
1253 {
1254  return sRegisteredPermissions;
1255 }
1256 
1257 /**
1258  * Get the user permissions for object 'obj' and user 'user' with
1259  * access mask 'mask'.
1260  *
1261  * @param object obj - the object to get user permissions for.
1262  * @param object user - object user.
1263  * @param int mask - the access mask.
1264  * @return user permission bit string.
1265  */
1266 int get_user_permissions(object obj, object user, int mask)
1267 {
1268  int res = security_cache->get_permission(obj, user);
1269  int a, b, r;
1270  if ( !objectp(obj) || !objectp(user) )
1271  return 0;
1272 
1273  a = res & mask;
1274  b = (res & ( mask<<SANCTION_SHIFT_DENY)) >> SANCTION_SHIFT_DENY;
1275  r = ( a | b );
1276  if ( r == mask ) {
1277  return res & mask;
1278  }
1279  // not all permissions are cached here !
1280  for ( int i = 0; i < SANCTION_SHIFT_DENY; i++ ) {
1281  if ( ((1<<i) & mask) && !(r & (1<<i)) )
1282  }
1283  return security_cache->get_permission(obj, user) & mask;
1284 }
1285 
1286 protected:
1287  mapping get_acq_permissions(mixed acq)
1288 {
1289  mapping res, ares;
1290  res = ([ ]);
1291  ares = ([ ]);
1292 
1293  if ( functionp(acq) ) {
1294  object obj = acq();
1295  if ( objectp(obj) ) {
1296  res = obj->get_sanction();
1297  ares = get_acq_permissions(obj->get_acquire());
1298  }
1299  }
1300  else if ( objectp(acq) ) {
1301  res = acq->get_sanction();
1302  ares = get_acq_permissions(acq->get_acquire());
1303  }
1304  else
1305  return res;
1306 
1307  foreach(indices(ares), mixed idx) {
1308  if ( res[idx] )
1309  res[idx] |= ares[idx];
1310  else
1311  res[idx] = ares[idx];
1312  }
1313  return res;
1314 }
1315 
1316 public:
1317 
1318 mapping get_inherited_permissions(object obj)
1319 {
1320  mapping res;
1321  mixed acq = obj->get_acquire();
1322  res = get_acq_permissions(acq);
1323  return res;
1324 }
1325 
1326 
1327 };