Example #1
0
/** Set the privileges for a client.
 * @param[in] client Client who has become an operator.
 * @param[in] oper Configuration item describing oper's privileges.
 */
void
client_set_privs(struct Client *client, struct ConfItem *oper)
{
  struct Privs *source, *defaults;
  enum Priv priv;

  if (!MyConnect(client))
    return;

  /* Clear out client's privileges. */
  memset(cli_privs(client), 0, sizeof(struct Privs));

  if (!IsAnOper(client) || !oper)
      return;

  if (!privs_defaults_set)
  {
    memset(&privs_global, -1, sizeof(privs_global));
    FlagClr(&privs_global, PRIV_WALK_LCHAN);
    FlagClr(&privs_global, PRIV_UNLIMIT_QUERY);
    FlagClr(&privs_global, PRIV_SET);
    FlagClr(&privs_global, PRIV_BADCHAN);
    FlagClr(&privs_global, PRIV_LOCAL_BADCHAN);
#if defined(UNDERNET)
    FlagClr(&privs_global, PRIV_APASS_OPMODE);
#endif

    memset(&privs_local, 0, sizeof(privs_local));
    FlagSet(&privs_local, PRIV_CHAN_LIMIT);
    FlagSet(&privs_local, PRIV_MODE_LCHAN);
    FlagSet(&privs_local, PRIV_SHOW_INVIS);
    FlagSet(&privs_local, PRIV_SHOW_ALL_INVIS);
    FlagSet(&privs_local, PRIV_LOCAL_KILL);
    FlagSet(&privs_local, PRIV_REHASH);
    FlagSet(&privs_local, PRIV_LOCAL_GLINE);
    FlagSet(&privs_local, PRIV_LOCAL_JUPE);
    FlagSet(&privs_local, PRIV_LOCAL_OPMODE);
    FlagSet(&privs_local, PRIV_WHOX);
    FlagSet(&privs_local, PRIV_DISPLAY);
    FlagSet(&privs_local, PRIV_FORCE_LOCAL_OPMODE);

    privs_defaults_set = 1;
  }

  /* Decide whether to use global or local oper defaults. */
  if (FlagHas(&oper->privs_dirty, PRIV_PROPAGATE))
    defaults = FlagHas(&oper->privs, PRIV_PROPAGATE) ? &privs_global : &privs_local;
  else if (FlagHas(&oper->conn_class->privs_dirty, PRIV_PROPAGATE))
    defaults = FlagHas(&oper->conn_class->privs, PRIV_PROPAGATE) ? &privs_global : &privs_local;
  else {
    assert(0 && "Oper has no propagation and neither does connection class");
    return;
  }

  /* For each feature, figure out whether it comes from the operator
   * conf, the connection class conf, or the defaults, then apply it.
   */
  for (priv = 0; priv < PRIV_LAST_PRIV; ++priv)
  {
    /* Figure out most applicable definition for the privilege. */
    if (FlagHas(&oper->privs_dirty, priv))
      source = &oper->privs;
    else if (FlagHas(&oper->conn_class->privs_dirty, priv))
      source = &oper->conn_class->privs;
    else
      source = defaults;

    /* Set it if necessary (privileges were already cleared). */
    if (FlagHas(source, priv))
      SetPriv(client, priv);
  }

  /* This should be handled in the config, but lets be sure... */
  if (HasPriv(client, PRIV_PROPAGATE))
  {
    /* force propagating opers to display */
    SetPriv(client, PRIV_DISPLAY);
  }
  else
  {
    /* if they don't propagate oper status, prevent desyncs */
    ClrPriv(client, PRIV_KILL);
    ClrPriv(client, PRIV_GLINE);
    ClrPriv(client, PRIV_JUPE);
    ClrPriv(client, PRIV_OPMODE);
    ClrPriv(client, PRIV_BADCHAN);
  }
}
Example #2
0
int can_oper(struct Client *cptr, struct Client *sptr, char *name,
             char *password, struct ConfItem **_aconf)
{
  struct ConfItem *aconf;

  aconf = find_conf_exact(name, sptr, CONF_OPERATOR);
  if (!aconf || IsIllegal(aconf))
  {
    send_reply(sptr, ERR_NOOPERHOST);
    sendto_opmask_butone_global(&me, SNO_OLDREALOP, "Failed %sOPER attempt by %s (%s@%s) "
                         "(no operator block)", (!MyUser(sptr) ? "remote " : ""),
                         cli_name(sptr), cli_user(sptr)->username, cli_user(sptr)->realhost);
    return 0;
  }
  assert(0 != (aconf->status & CONF_OPERATOR));

  if (!MyUser(sptr)) {
    if (FlagHas(&aconf->privs, PRIV_REMOTE)) {
    } else if (aconf->conn_class && FlagHas(&aconf->conn_class->privs, PRIV_REMOTE)) {
    } else {
      send_reply(sptr, ERR_NOOPERHOST);
      sendto_opmask_butone_global(&me, SNO_OLDREALOP, "Failed %sOPER attempt by %s (%s@%s) "
                           "(no remote oper priv)", (!MyUser(sptr) ? "remote " : ""),
                           cli_name(sptr), cli_user(sptr)->username, cli_user(sptr)->realhost);
      return 0;
    }
  }

  if (!verify_sslclifp(sptr, aconf))
  {
    send_reply(sptr, ERR_SSLCLIFP);
    sendto_opmask_butone_global(&me, SNO_OLDREALOP, "Failed %sOPER attempt by %s "
                                "(%s@%s) (SSL fingerprint mismatch)",
                                (!MyUser(sptr) ? "remote " : ""), cli_name(sptr),
                                cli_user(sptr)->username, cli_user(sptr)->realhost);
    return 0;
  }

  if (oper_password_match(password, aconf->passwd))
  {
    if (MyUser(sptr))
    {
      int attach_result = attach_conf(sptr, aconf);
      if ((ACR_OK != attach_result) && (ACR_ALREADY_AUTHORIZED != attach_result)) {
        send_reply(sptr, ERR_NOOPERHOST);
        sendto_opmask_butone_global(&me, SNO_OLDREALOP, "Failed %sOPER attempt by %s "
                                    "(%s@%s) (no operator block)",
                                    (!MyUser(sptr) ? "remote " : ""), cli_name(sptr),
                                    cli_user(sptr)->username, cli_user(sptr)->realhost);
        return 0;
      }
    }
    *_aconf = aconf;
    return -1;
  }
  else
  {
    send_reply(sptr, ERR_PASSWDMISMATCH);
    sendto_opmask_butone_global(&me, SNO_OLDREALOP, "Failed %sOPER attempt by %s (%s@%s) "
                                 "(password mis-match)", (!MyUser(sptr) ? "remote " : ""),
                                 cli_name(sptr), cli_user(sptr)->username,
                                 cli_user(sptr)->realhost);
    return 0;
  }
}