Example #1
0
/** Write the access.cnf file.
 * Writes out the access.cnf file from the linked list
 */
void
write_access_file(void)
{
  FILE *fp;
  char tmpf[BUFFER_LEN];
  struct access *ap;
  acsflag *c;

  snprintf(tmpf, BUFFER_LEN, "%s.tmp", ACCESS_FILE);
  /* Be sure we have a file descriptor */
  release_fd();
  fp = fopen(tmpf, FOPEN_WRITE);
  if (!fp) {
    do_log(LT_ERR, GOD, GOD, "Unable to open %s.", tmpf);
  } else {
    for (ap = access_top; ap; ap = ap->next) {
      if (strcmp(ap->host, "@sitelock") == 0) {
        fprintf(fp, "@sitelock\n");
        continue;
      }
      fprintf(fp, "%s %d ", ap->host, ap->who);
      switch (ap->can) {
      case ACS_SITELOCK:
        break;
      case ACS_DEFAULT:
        fprintf(fp, "DEFAULT ");
        break;
      default:
        for (c = acslist; c->name; c++)
          if (ap->can & c->flag)
            fprintf(fp, "%s ", c->name);
        break;
      }
      switch (ap->cant) {
      case ACS_DEFAULT:
        fprintf(fp, "NONE ");
        break;
      default:
        for (c = acslist; c->name; c++)
          if (c->toggle && (ap->cant & c->flag))
            fprintf(fp, "!%s ", c->name);
        break;
      }
      if (ap->comment)
        fprintf(fp, "# %s\n", ap->comment);
      else
        fputc('\n', fp);
    }
    fclose(fp);
    rename_file(tmpf, ACCESS_FILE);
  }
  reserve_fd();
  return;
}
Example #2
0
/** Read the access.cnf file.
 * Initialize the access rules linked list and read in the access.cnf file.
 * \return true if successful, false if not
 */
bool
read_access_file(void)
{
  FILE *fp;
  char buf[BUFFER_LEN];
  char *p;
  uint32_t can, cant;
  int retval;
  dbref who;
  char *comment;
  const char *errptr = NULL;

  if (access_top) {
    /* We're reloading the file, so we've got to delete any current
     * entries
     */
    free_access_list();
  }
  access_top = NULL;
  /* Be sure we have a file descriptor */
  release_fd();
  fp = fopen(ACCESS_FILE, FOPEN_READ);
  if (!fp) {
    do_rawlog(LT_ERR, "Access file %s not found.", ACCESS_FILE);
    retval = 0;
  } else {
    do_rawlog(LT_ERR, "Reading %s", ACCESS_FILE);
    while (fgets(buf, BUFFER_LEN, fp)) {
      /* Strip end of line if it's \r\n or \n */
      if ((p = strchr(buf, '\r')))
        *p = '\0';
      else if ((p = strchr(buf, '\n')))
        *p = '\0';
      /* Find beginning of line; ignore blank lines */
      p = buf;
      if (*p && isspace((unsigned char) *p))
        p++;
      if (*p && *p != '#') {
        can = cant = 0;
        comment = NULL;
        /* Is this the @sitelock entry? */
        if (!strncasecmp(p, "@sitelock", 9)) {
          if (!add_access_node("@sitelock", AMBIGUOUS, ACS_SITELOCK, 0, "",
                               &errptr))
            do_log(LT_ERR, GOD, GOD, "Failed to add sitelock node: %s", errptr);
        } else {
          if ((comment = strchr(p, '#'))) {
            *comment++ = '\0';
            while (*comment && isspace((unsigned char) *comment))
              comment++;
          }
          /* Move past the host name */
          while (*p && !isspace((unsigned char) *p))
            p++;
          if (*p)
            *p++ = '\0';
          if (!parse_access_options(p, &who, &can, &cant, NOTHING))
            /* Nothing listed, so assume we can't do anything! */
            cant = ACS_DEFAULT;
          if (!add_access_node(buf, who, can, cant, comment, &errptr))
            do_log(LT_ERR, GOD, GOD, "Failed to add access node: %s", errptr);
        }
      }
    }
    retval = 1;
    fclose(fp);
  }
  reserve_fd();
  return retval;
}
Example #3
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;
  }
}