/** Is a alias a valid player alias-list for thing?
 * It must be a semicolon-separated list of valid player names
 * with no more than than MAX_ALIASES names, if the player isn't
 * a wizard.
 * \param alias list to check.
 * \param player player for permission checks.
 * \param thing player who is being aliased.
 * \return One of the OPAE_* constants defined in hdrs/attrib.h
 */
enum opa_error
ok_player_alias(const char *alias, dbref player, dbref thing)
{
  char tbuf1[BUFFER_LEN], *s, *sp;
  int cnt = 0;

  if (!alias || !*alias)
    return OPAE_NULL;

  strncpy(tbuf1, alias, BUFFER_LEN - 1);
  tbuf1[BUFFER_LEN - 1] = '\0';
  s = trim_space_sep(tbuf1, ALIAS_DELIMITER);
  while (s) {
    sp = split_token(&s, ALIAS_DELIMITER);
    while (sp && *sp && *sp == ' ')
      sp++;
    if (!sp || !*sp)
      return OPAE_NULL;         /* No null aliases */
    if (!ok_player_name(sp, player, thing))
      return OPAE_INVALID;
    cnt++;
  }
  if (Wizard(player))
    return OPAE_SUCCESS;
  if (cnt > MAX_ALIASES)
    return OPAE_TOOMANY;
  return OPAE_SUCCESS;
}
Exemple #2
0
int
set_alias(dbref target, const char *alias, int rotate) {
    PData pdat;
    const char *p = alias;

    /* is the new alias legal? */
    while (*p && *p != ':' && *p != PROPDIR_DELIMITER) p++;
    if (*p || !ok_player_name(alias)) {
        return NOTHING;
    }

    /* is the new alias actually available? */
    if (lookup_alias(alias, 0) != NOTHING) {
        return AMBIGUOUS;
    }
    
    /* set the new alias */
    sprintf(abuf, ALIASDIR_CUR "%s", alias);
    pdat.flags = PROP_REFTYP;
    pdat.data.ref = target;
    set_property(0, abuf, &pdat);
    
    if (rotate) {
        rotate_alias(target, 0);
        /* set the "last alias" hint */
        sprintf(abuf, ALIASDIR_LAST "%d", (int) target);
        add_property(0, abuf, alias, 0);
    }

    return 0;
}
Exemple #3
0
/** Attempt to create a new player object.
 * \param d DESC the creation attempt is being made on (if from connect screen)
 * \param executor dbref of the object attempting to create a player (if
 * \@pcreate)
 * \param name name of player to create.
 * \param password initial password of created player.
 * \param host host from which creation is attempted.
 * \param ip ip address from which creation is attempted.
 * \return dbref of created player, NOTHING if invalid name, AMBIGUOUS if taken
 *  name, or HOME for a bad password
 *  password.
 */
dbref
create_player(DESC *d, dbref executor, const char *name, const char *password,
              const char *host, const char *ip)
{
  if (!ok_player_name(name, executor, NOTHING)) {
    do_log(LT_CONN, 0, 0, "Failed creation (bad name) from %s", host);
    if (d) {
      queue_event(SYSEVENT, "SOCKET`CREATEFAIL", "%d,%s,%d,%s,%s",
                  d->descriptor, ip, mark_failed(ip), "create: bad name", name);
    }
    return (lookup_player(name) == NOTHING ? NOTHING : AMBIGUOUS);
  }
  if (!ok_password(password)) {
    do_log(LT_CONN, 0, 0, "Failed creation (bad password) from %s", host);
    if (d) {
      queue_event(SYSEVENT, "SOCKET`CREATEFAIL", "%d,%s,%d,%s,%s",
                  d->descriptor, ip, mark_failed(ip), "create: bad password",
                  name);
    }
    return HOME;
  }
  if (DBTOP_MAX && (db_top >= DBTOP_MAX + 1) && (first_free == NOTHING)) {
    /* Oops, out of db space! */
    do_log(LT_CONN, 0, 0, "Failed creation (no db space) from %s", host);
    if (d) {
      queue_event(SYSEVENT, "SOCKET`CREATEFAIL", "%d,%s,%d,%s,%s",
                  d->descriptor, ip, mark_failed(ip),
                  "create: no db space left to create!", name);
    }
    return NOTHING;
  }
  /* else he doesn't already exist, create him */
  return make_player(name, password, host, ip);
}
dbref 
create_player(const char *name, const char *password)
{
    dbref   player;

    if (!ok_player_name(name) || !ok_password(password))
	return NOTHING;

    /* else he doesn't already exist, create him */
    player = new_object();

    /* initialize everything */
    NAME(player) = alloc_string(name);
    DBFETCH(player)->location = tp_player_start;	/* home */
    FLAGS(player) = TYPE_PLAYER | PCREATE_FLAGS;
    OWNER(player) = player;
    DBFETCH(player)->sp.player.home = tp_player_start;
    DBFETCH(player)->exits = NOTHING;
    DBFETCH(player)->sp.player.pennies = tp_start_pennies;
    DBFETCH(player)->sp.player.password = NULL; // handle this last
    DBFETCH(player)->sp.player.curr_prog = NOTHING;
    DBFETCH(player)->sp.player.insert_mode = 0;

    /* link him to tp_player_start */
    PUSH(player, DBFETCH(tp_player_start)->contents);
    add_player(player);
    DBDIRTY(player);
    DBDIRTY(tp_player_start);
    set_password(player, password);

    return player;
}
Exemple #5
0
void
prim_pname_okp(PRIM_PROTOTYPE)
{
    CHECKOP(1);
    oper1 = POP();
    if (oper1->type != PROG_STRING)
	abort_interp("Player name string expected.");
    if (!oper1->data.string)
	abort_interp("Cannot be an empty string.");
    result = ok_player_name(oper1->data.string->data);
    CLEAR(oper1);
    PushInt(result);
}
Exemple #6
0
dbref
create_player(const char *name, const char *password)
{
    char buf[80];
    dbref player;

    if (!ok_player_name(name) || !ok_password(password))
        return NOTHING;
    if (!tp_building || tp_db_readonly) return NOTHING;

    /* else he doesn't already exist, create him */
    player = new_object();

    /* initialize everything */
    NAME(player) = alloc_string(name);
    FLAGS(player) = TYPE_PLAYER | PCREATE_FLAGS;
    FLAG2(player) = PCREATE_FLAG2;
    DBFETCH(player)->location = RootRoom;	/* home */
    OWNER(player) = player;
    DBFETCH(player)->sp.player.home = RootRoom;
    DBFETCH(player)->exits = NOTHING;
    DBFETCH(player)->sp.player.pennies = tp_start_pennies;
    DBFETCH(player)->sp.player.password = alloc_string(password);
    DBFETCH(player)->sp.player.curr_prog = NOTHING;
    DBFETCH(player)->sp.player.insert_mode = 0;

    /* link him to tp_player_start */
    PUSH(player, DBFETCH(RootRoom)->contents);
    add_player(player);
    DBDIRTY(player);
    DBDIRTY(RootRoom);

    sprintf(buf, CNOTE "%s is born!", PNAME(player));
    anotify_except(DBFETCH(RootRoom)->contents, NOTHING, buf, player);

    return player;
}
/** Is name a valid new name for thing, when set by player?
 * \verbatim
 * Parses names and aliases for players/exits, validating each. If everything is valid,
 * the new name and alias are set into newname and newalias, with memory malloc'd as necessary.
 * For things/rooms, no parsing is done, and ok_name is called on the entire string to validate.
 * For players and exits, if name takes the format <name>; then newname is set to <name> and
 * newalias to ";", to signify that the existing alias should be cleared. If name contains a name and
 * valid aliases, newname and newalias are set accordingly.
 * \endverbatim
 * \param name the new name to set
 * \param player the player setting the name, for permission checks
 * \param thing object getting the name, or NOTHING for new objects
 * \param type type of object getting the name (necessary for new exits)
 * \param newname pointer to place the new name, once validated
 * \param newalias pointer to place the alias in, if any
 * \retval OPAE_SUCCESS name and any given aliases are valid
 * \retval OPAE_INVALID invalid name or aliases
 * \retval OPAE_TOOMANY too many aliases for player
 */
enum opa_error
ok_object_name(char *name, dbref player, dbref thing, int type, char **newname,
               char **newalias)
{
  char *bon, *eon;
  char nbuff[BUFFER_LEN], abuff[BUFFER_LEN];
  char *ap = abuff;
  int aliases = 0;
  int empty = 0;

  strncpy(nbuff, name, BUFFER_LEN - 1);
  nbuff[BUFFER_LEN - 1] = '\0';
  memset(abuff, 0, BUFFER_LEN);

  /* First, check for a quoted player name */
  if (type == TYPE_PLAYER && *name == '"') {
    /* Quoted player name, no aliases allowed */
    bon = nbuff;
    bon++;
    eon = bon;
    while (*eon && *eon != '"')
      eon++;
    if (*eon)
      *eon = '\0';
    if (!ok_player_name(bon, player, thing))
      return OPAE_INVALID;
    *newname = mush_strdup(bon, "name.newname");
    return OPAE_SUCCESS;
  }

  if (type & (TYPE_THING | TYPE_ROOM)) {
    /* No aliases in the name */
    if (!ok_name(nbuff, 0))
      return OPAE_INVALID;
    *newname = mush_strdup(nbuff, "name.newname");
    return OPAE_SUCCESS;
  }

  /* A player or exit name, with aliases allowed.
   * Possible things to parse:
   * <name>  - just a new name
   * <name>; - new name with trailing ; to clear alias
   * <name>;<alias1>[;<aliasN>] - name with one or more aliases, separated by ;
   */

  /* Validate name first */
  bon = nbuff;
  if ((eon = strchr(bon, ALIAS_DELIMITER))) {
    *eon++ = '\0';
    aliases++;
  }
  if (!
      (type ==
       TYPE_PLAYER ? ok_player_name(bon, player, thing) : ok_name(bon, 1)))
    return OPAE_INVALID;

  *newname = mush_strdup(bon, "name.newname");

  if (aliases) {
    /* We had aliases, so parse them */
    while (eon) {
      if (empty)
        return OPAE_NULL;       /* Null alias only valid as a single, final alias */
      bon = eon;
      if ((eon = strchr(bon, ALIAS_DELIMITER))) {
        *eon++ = '\0';
      }
      while (*bon && *bon == ' ')
        bon++;
      if (!*bon) {
        empty = 1;              /* empty alias, should only happen if we have no proper aliases */
        continue;
      }
      if (!
          (type ==
           TYPE_PLAYER ? ok_player_name(bon, player, thing) : ok_name(bon,
                                                                      1))) {
        *newalias = mush_strdup(bon, "name.newname");   /* So we can report the invalid alias */
        return OPAE_INVALID;
      }
      if (aliases > 1) {
        safe_chr(ALIAS_DELIMITER, abuff, &ap);
      }
      safe_str(bon, abuff, &ap);
      aliases++;
    }
  }
  *ap = '\0';

  if (aliases) {
    if (!Wizard(player) && type == TYPE_PLAYER && aliases > MAX_ALIASES)
      return OPAE_TOOMANY;
    if (*abuff) {
      /* We have actual aliases */
      *newalias = mush_strdup(abuff, "name.newname");
    } else {
      ap = abuff;
      safe_chr(ALIAS_DELIMITER, abuff, &ap);
      *ap = '\0';
      /* We just want to clear the existing alias */
      *newalias = mush_strdup(abuff, "name.newname");
    }
  }

  return OPAE_SUCCESS;
}
Exemple #8
0
dbref
create_player(dbref creator, const char *name, const char *password)
{
    char buf[BUFFER_LEN];

    struct object *newp;

    dbref player;

    if (!ok_player_name(name) || !ok_password(password) || tp_db_readonly)
        return NOTHING;

    /* remove any existing alias with this name */
    clear_alias(0, name);

    /* else he doesn't already exist, create him */
    player = new_object(creator);
    newp = DBFETCH(player);

    /* initialize everything */
    NAME(player) = alloc_string(name);
    FLAGS(player) = TYPE_PLAYER;

    if (OkObj(tp_player_prototype)
        && (Typeof(tp_player_prototype) == TYPE_PLAYER)) {
        FLAGS(player) = FLAGS(tp_player_prototype);
        FLAG2(player) = FLAG2(tp_player_prototype);

        if (tp_pcreate_copy_props) {
            newp->properties = copy_prop(tp_player_prototype);
#ifdef DISKBASE
            newp->propsfpos = 0;
            newp->propsmode = PROPS_UNLOADED;
            newp->propstime = 0;
            newp->nextold = NOTHING;
            newp->prevold = NOTHING;
            dirtyprops(player);
#endif
        }
    }

    if (OkObj(tp_player_start)) {
        DBFETCH(player)->location = tp_player_start;
        DBFETCH(player)->sp.player.home = tp_player_start;
    } else {
        DBFETCH(player)->location = GLOBAL_ENVIRONMENT;
        DBFETCH(player)->sp.player.home = GLOBAL_ENVIRONMENT;
    }

    OWNER(player) = player;
    newp->exits = NOTHING;
    newp->sp.player.pennies = tp_start_pennies;
    newp->sp.player.password = NULL; /* this has to stay here. -hinoserm */
    newp->sp.player.curr_prog = NOTHING;
    newp->sp.player.insert_mode = 0;
#ifdef IGNORE_SUPPORT
    newp->sp.player.ignoretime = 0;
#endif /* IGNORE_SUPPORT */

    /* set password */
    set_password(player, password);

    /* link him to tp_player_start */
    PUSH(player, DBFETCH(tp_player_start)->contents);
    add_player(player);
    DBDIRTY(player);
    DBDIRTY(tp_player_start);

    sprintf(buf, CNOTE "%s is born!", NAME(player));
    anotify_except(DBFETCH(tp_player_start)->contents, NOTHING, buf, player);

    return player;
}
Exemple #9
0
/** Attempt to register a new player at the connect screen.
 * If registration is allowed, a new player object is created with
 * a random password which is emailed to the registering player.
 * \param name name of player to register.
 * \param email email address to send registration details.
 * \param host host from which registration is being attempted.
 * \param ip ip address from which registration is being attempted.
 * \return dbref of created player or NOTHING if creation failed.
 */
dbref
email_register_player(DESC *d, const char *name, const char *email,
                      const char *host, const char *ip)
{
  char *p;
  char passwd[20];
  static char elems[] =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  int i, len;
  bool resend = 0;
  dbref player = NOTHING;
  FILE *fp;
  size_t NELEMS = sizeof(elems) - 1;
  char sbuff[260];

  if (!check_fails(ip)) {
    return NOTHING;
  }

  if (strlen(options.sendmail_prog) == 0)
    return NOTHING;

  if (!ok_player_name(name, NOTHING, NOTHING)) {
    /* Check for re-registration request */
    player = lookup_player(name);
    if (GoodObject(player)) {
      ATTR *a;
      a = atr_get(player, "LASTLOGOUT");
      if (!a) {
        a = atr_get(player, "REGISTERED_EMAIL");
        if (a && !strcasecmp(atr_value(a), email))
          resend = 1;
      }
    }
    if (!resend) {
      do_log(LT_CONN, 0, 0, "Failed registration (bad name) from %s", host);
      queue_event(SYSEVENT, "SOCKET`CREATEFAIL", "%d,%s,%d,%s,%s",
                  d->descriptor, ip, mark_failed(ip), "register: bad name",
                  name);
      return NOTHING;
    }
  }
  if (!resend) {
    /* Make sure that the email address is kind of valid. A valid
     * address must contain a @. Let the mailer sort it out beyond
     * that.  Also, to prevent someone from using the MUSH to mailbomb
     * another site, let's make sure that the site to which the user
     * wants the email sent is also allowed to use the register
     * command.  If there's an @, we check whatever's after the last @
     * (since @foo.bar:user@host is a valid email).
     */
    if ((p = strrchr(email, '@'))) {
      p++;
      if (!Site_Can_Register(p)) {
        if (!Deny_Silent_Site(p, AMBIGUOUS)) {
          do_log(LT_CONN, 0, 0,
                 "Failed registration (bad site in email: %s) from %s", email,
                 host);
          queue_event(SYSEVENT, "SOCKET`CREATEFAIL", "%d,%s,%d,%s,%s",
                      d->descriptor, ip, mark_failed(ip),
                      "register: bad site in email", name);
        }
        return NOTHING;
      }
    } else {
      if (!Deny_Silent_Site(host, AMBIGUOUS)) {
        do_log(LT_CONN, 0, 0, "Failed registration (bad email: %s) from %s",
               email, host);
        queue_event(SYSEVENT, "SOCKET`CREATEFAIL", "%d,%s,%d,%s,%s",
                    d->descriptor, ip, mark_failed(ip),
                    "register: sitelocked host", name);
      }
      return NOTHING;
    }

    if (DBTOP_MAX && (db_top >= DBTOP_MAX + 1) && (first_free == NOTHING)) {
      /* Oops, out of db space! */
      do_log(LT_CONN, 0, 0, "Failed registration (no db space) from %s", host);
      queue_event(SYSEVENT, "SOCKET`CREATEFAIL", "%d,%s,%d,%s,%s",
                  d->descriptor, ip, count_failed(ip),
                  "register: no db space left to create!", name);
      return NOTHING;
    }
  }

  /* Come up with a random password of length 7-12 chars */
  len = get_random_u32(7, 12);
  for (i = 0; i < len; i++)
    passwd[i] = elems[get_random_u32(0, NELEMS - 1)];
  passwd[len] = '\0';

  /* If we've made it here, we can send the email and create the
   * character. Email first, since that's more likely to go bad.
   * Some security precautions we'll take:
   *  1) We'll use sendmail -t, so we don't pass user-given values to a shell.
   *  2) We'll cross our fingers and hope nobody uses this to spam.
   */

  release_fd();
  snprintf(sbuff, sizeof sbuff, "%s -t", options.sendmail_prog);
  if ((fp = popen(sbuff, "w")) == NULL) {
    do_log(LT_CONN, 0, 0,
           "Failed registration of %s by %s: unable to open sendmail", name,
           email);
    queue_event(SYSEVENT, "SOCKET`CREATEFAIL", "%d,%s,%d,%s,%s,%d",
                d->descriptor, ip, count_failed(ip),
                "register: Unable to open sendmail!", name, 1);
    reserve_fd();
    return NOTHING;
  }
  fprintf(fp, "Subject: ");
  fprintf(fp, T("[%s] Registration of %s\n"), MUDNAME, name);
  fprintf(fp, "To: %s\n", email);
  fprintf(fp, "Precedence: junk\n");
  fprintf(fp, "\n");
  fprintf(fp, T("This is an automated message.\n"));
  fprintf(fp, "\n");
  fprintf(fp, T("Your requested player, %s, has been created.\n"), name);
  fprintf(fp, T("The password is %s\n"), passwd);
  fprintf(fp, "\n");
  fprintf(fp, T("To access this character, connect to %s and type:\n"),
          MUDNAME);
  fprintf(fp, "\tconnect \"%s\" %s\n", name, passwd);
  fprintf(fp, "\n");
  i = pclose(fp);
  reserve_fd();

  if (i != 0) {
    /* Mailer exited with an error code. Log it. */
    do_rawlog(
      LT_CONN,
      "When attempting to email a password to a newly registered player,\n"
      "\tthe mailer exited with error code %d.\n"
      "\t(Check /usr/include/sysexits.h if present for the meaning.)",
      i);
    queue_event(SYSEVENT, "SOCKET`CREATEFAIL", "%d,%s,%d,%s,%s,%d",
                d->descriptor, ip, count_failed(ip),
                "register: Unable to send email", name, i);
    return NOTHING;
  } else if (resend) {
    /* Reset the password */
    (void) atr_add(player, pword_attr, password_hash(passwd, NULL), GOD, 0);
    return player;
  } else {
    /* Ok, all's well, make a player */
    player = make_player(name, passwd, host, ip);
    queue_event(SYSEVENT, "PLAYER`CREATE", "%s,%s,%s,%d,%s",
                unparse_objid(player), name, "register", d->descriptor, email);
    (void) atr_add(player, "REGISTERED_EMAIL", email, GOD, 0);
    return player;
  }
}