Esempio n. 1
0
/** Can a player control a thing?
 * The control rules are, in order:
 *   Only God controls God.
 *   Wizards control everything else.
 *   Nothing else controls a wizard, and only royalty control royalty.
 *   Mistrusted objects control only themselves.
 *   Objects with the same owner control each other, unless the
 *     target object is TRUST and the would-be controller isn't.
 *   If ZMOs allow control, and you pass the ZMO, you control.
 *   If the owner is a Zone Master, and you pass the ZM, you control.
 *   If you pass the control lock, you control.
 *   Otherwise, no dice.
 * \param who object attempting to control.
 * \param what object to be controlled.
 * \retval 1 who controls what.
 * \retval 0 who doesn't control what.
 */
int
controls(dbref who, dbref what)
{
  boolexp c;

  if (!GoodObject(what))
    return 0;

  if (Guest(who))
    return 0;

  if (what == who)
    return 1;

  if (God(what))
    return 0;

  if (Wizard(who))
    return 1;

  if (Wizard(what) || (Hasprivs(what) && !Hasprivs(who)))
    return 0;

  if (Mistrust(who))
    return 0;

  if (Owns(who, what) && (!Inheritable(what) || Inheritable(who)))
    return 1;

  if (Inheritable(what) || IsPlayer(what))
    return 0;

  if (!ZONE_CONTROL_ZMP && (Zone(what) != NOTHING) &&
      eval_lock(who, Zone(what), Zone_Lock))
    return 1;

  if (ZMaster(Owner(what)) && !IsPlayer(what) &&
      eval_lock(who, Owner(what), Zone_Lock))
    return 1;

  c = getlock_noparent(what, Control_Lock);
  if (c != TRUE_BOOLEXP) {
    if (eval_boolexp(who, c, what, NULL))
      return 1;
  }
  return 0;
}
Esempio n. 2
0
/** Decide if a host can access someway.
 * \param hname a host or user+host pattern.
 * \param flag the access type we're testing.
 * \param who the player attempting access.
 * \retval 1 access permitted.
 * \retval 0 access denied.
 * \verbatim
 * Given a hostname and a flag decide if the host can do it.
 * Here's how it works:
 * We run the linked list and take the first match.
 *  (If the hostname is user@host, we try to match both user@host
 *   and just host to each line in the file.)
 * If we make a match, and the line tells us whether the site can/can't
 *   do the action, we're done.
 * Otherwise, we assume that the host can do any toggleable option
 *   (can create, connect, guest), and don't have any special
 *   flags (can't register, isn't suspect)
 * \endverbatim
 */
bool
site_can_access(const char *hname, uint32_t flag, dbref who)
{
  struct access *ap;
  acsflag *c;
  const char *p;

  if (!hname || !*hname)
    return 0;

  if ((p = strchr(hname, '@')))
    p++;

  for (ap = access_top; ap; ap = ap->next) {
    if (ap->can & ACS_SITELOCK)
      continue;
    if ((ap->can & ACS_REGEXP)
        ? (qcomp_regexp_match(ap->re, hname)
           || (p && qcomp_regexp_match(ap->re, p)))
        : (quick_wild(ap->host, hname)
           || (p && quick_wild(ap->host, p)))
        && (ap->who == AMBIGUOUS || ap->who == who)) {
      /* Got one */
      if (flag & ACS_CONNECT) {
        if ((ap->cant & ACS_GOD) && God(who))   /* God can't connect from here */
          return 0;
        else if ((ap->cant & ACS_WIZARD) && Wizard(who))
          /* Wiz can't connect from here */
          return 0;
        else if ((ap->cant & ACS_ADMIN) && Hasprivs(who))
          /* Wiz and roy can't connect from here */
          return 0;
      }
      if (ap->cant && ((ap->cant & flag) == flag))
        return 0;
      if (ap->can && (ap->can & flag))
        return 1;

      /* Hmm. We don't know if we can or not, so continue */
      break;
    }
  }

  /* Flag was neither set nor unset. If the flag was a toggle,
   * then the host can do it. If not, the host can't */
  for (c = acslist; c->name; c++) {
    if (flag & c->flag)
      return c->toggle ? 1 : 0;
  }
  /* Should never reach here, but just in case */
  return 1;
}
Esempio n. 3
0
/** Change an object's zone.
 * \verbatim
 * This implements @chzone.
 * \endverbatim
 * \param player the enactor.
 * \param name name of the object to change zone of.
 * \param newobj name of new ZMO.
 * \param noisy if 1, notify player about success and failure.
 * \param preserve was the /preserve switch given?
 * \param pe_info the pe_info for lock and permission checks
 * \retval 0 failed to change zone.
 * \retval 1 successfully changed zone.
 */
int
do_chzone(dbref player, char const *name, char const *newobj, bool noisy,
          bool preserve, NEW_PE_INFO *pe_info)
{
  dbref thing;
  dbref zone;
  int has_lock;

  if ((thing = noisy_match_result(player, name, NOTYPE, MAT_NEARBY)) == NOTHING)
    return 0;

  if (!newobj || !*newobj || !strcasecmp(newobj, "none"))
    zone = NOTHING;
  else {
    if ((zone = noisy_match_result(player, newobj, NOTYPE, MAT_EVERYTHING))
        == NOTHING)
      return 0;
  }

  if (Zone(thing) == zone) {
    if (noisy)
      notify(player, T("That object is already in that zone."));
    return 0;
  }


  if (!controls(player, thing)) {
    if (noisy)
      notify(player, T("You don't have the power to shift reality."));
    return 0;
  }
  /* a player may change an object's zone to:
   * 1.  NOTHING
   * 2.  an object he controls
   * 3.  an object with a chzone-lock that the player passes.
   * Note that an object with no chzone-lock isn't valid
   */
  has_lock = (getlock(zone, Chzone_Lock) != TRUE_BOOLEXP);
  if (!(Wizard(player) || (zone == NOTHING) || controls(player, zone) ||
        (has_lock && eval_lock_with(player, zone, Chzone_Lock, pe_info)))) {
    if (noisy) {
      if (has_lock) {
        fail_lock(player, zone, Chzone_Lock,
                  T("You cannot move that object to that zone."), NOTHING);
      } else {
        notify(player, T("You cannot move that object to that zone."));
      }
    }
    return 0;
  }
  /* Don't chzone object to itself for mortals! */
  if ((zone == thing) && !Hasprivs(player)) {
    if (noisy)
      notify(player, T("You shouldn't zone objects to themselves!"));
    return 0;
  }
  /* Don't allow circular zones */
  if (GoodObject(zone)) {
    dbref tmp;
    int zone_depth = MAX_ZONES;
    for (tmp = Zone(zone); GoodObject(tmp); tmp = Zone(tmp)) {
      if (tmp == thing) {
        notify(player, T("You can't make circular zones!"));
        return 0;
      }
      if (tmp == Zone(tmp))     /* Ran into an object zoned to itself */
        break;
      zone_depth--;
      if (!zone_depth) {
        notify(player, T("Overly deep zone chain."));
        return 0;
      }
    }
  }

  /* Don't allow chzone to objects without elocks!
   * If no lock is set, set a default lock (warn if zmo are used for control)
   * This checks for many trivial elocks (canuse/1, where &canuse=1)
   */
  if (zone != NOTHING)
    check_zone_lock(player, zone, noisy);

  /* Warn Wiz/Royals when they zone their stuff */
  if ((zone != NOTHING) && Hasprivs(Owner(thing))) {
    if (noisy)
      notify(player, T("Warning: @chzoning admin-owned object!"));
  }
  /* everything is okay, do the change */
  Zone(thing) = zone;

  /* If we're not unzoning, and we're working with a non-player object,
   * we'll remove wizard, royalty, inherit, and powers, for security, unless
   * a wizard is changing the zone and explicitly says not to.
   */
  if (!Wizard(player))
    preserve = 0;
  if (!preserve && ((zone != NOTHING) && !IsPlayer(thing))) {
    /* if the object is a player, resetting these flags is rather
     * inconvenient -- although this may pose a bit of a security
     * risk. Be careful when @chzone'ing wizard or royal players.
     */
    clear_flag_internal(thing, "WIZARD");
    clear_flag_internal(thing, "ROYALTY");
    clear_flag_internal(thing, "TRUST");
    destroy_flag_bitmask("POWER", Powers(thing));
    Powers(thing) = new_flag_bitmask("POWER");
  } else {
    if (noisy && (zone != NOTHING)) {
      if (Hasprivs(thing))
        notify(player, T("Warning: @chzoning a privileged player."));
      if (Inherit(thing))
        notify(player, T("Warning: @chzoning a TRUST player."));
    }
  }
  if (noisy)
    notify(player, T("Zone changed."));
  return 1;
}
Esempio n. 4
0
/** Change an object's owner.
 * \verbatim
 * This implements @chown.
 * \endverbatim
 * \param player the enactor.
 * \param name name of object to change owner of.
 * \param newobj name of new owner for object.
 * \param preserve if 1, preserve privileges and don't halt the object.
 * \param pe_info the pe_info for lock checks
 */
void
do_chown(dbref player, const char *name, const char *newobj, int preserve,
         NEW_PE_INFO *pe_info)
{
  dbref thing;
  dbref newowner = NOTHING;
  long match_flags = MAT_POSSESSION | MAT_HERE | MAT_EXIT | MAT_ABSOLUTE;


  /* check for '@chown <object>/<atr>=<player>'  */
  if (strchr(name, '/')) {
    do_atrchown(player, name, newobj);
    return;
  }
  if (Wizard(player))
    match_flags |= MAT_PLAYER;

  if ((thing = noisy_match_result(player, name, TYPE_THING, match_flags))
      == NOTHING)
    return;

  if (!*newobj || !strcasecmp(newobj, "me")) {
    newowner = player;
  } else {
    if ((newowner = lookup_player(newobj)) == NOTHING) {
      notify(player, T("I couldn't find that player."));
      return;
    }
  }

  if (IsPlayer(thing) && !God(player)) {
    notify(player, T("Players always own themselves."));
    return;
  }
  /* Permissions checking */
  if (!chown_ok(player, thing, newowner, pe_info)) {
    notify(player, T("Permission denied."));
    return;
  }
  if (IsThing(thing) && !Hasprivs(player) &&
      !(GoodObject(Location(thing)) && (Location(thing) == player))) {
    notify(player, T("You must carry the object to @chown it."));
    return;
  }
  if (preserve && !Wizard(player)) {
    notify(player, T("You cannot @CHOWN/PRESERVE. Use normal @CHOWN."));
    return;
  }
  /* chowns to the zone master don't count towards fees */
  if (!ZMaster(newowner)) {
    /* Debit the owner-to-be */
    if (!can_pay_fees(newowner, Pennies(thing))) {
      /* not enough money or quota */
      if (newowner != player)
        notify(player,
               T
               ("That player doesn't have enough money or quota to receive that object."));
      return;
    }
    /* Credit the current owner */
    giveto(Owner(thing), Pennies(thing));
    change_quota(Owner(thing), QUOTA_COST);
  }
  chown_object(player, thing, newowner, preserve);
  notify(player, T("Owner changed."));
}