]> jfr.im git - solanum.git/blobdiff - modules/m_grant.c
m_list: fail on invalid parameters
[solanum.git] / modules / m_grant.c
index bbad72c96dbb2bc8928bc6e8e0a86f4ca6b517b8..0f41f4c72e1a609efea3c67cc1a68de651316f05 100644 (file)
 /*
- *  charybdis: an advanced ircd
- *  m_grant: handle services grant commands
+ * Copyright (C) 2006 Jilles Tjoelker
+ * Copyright (C) 2006 Stephen Bennett <spb@gentoo.org>
  */
 
 #include "stdinc.h"
+#include "modules.h"
+#include "numeric.h"
 #include "client.h"
 #include "ircd.h"
-#include "numeric.h"
-#include "s_serv.h"
 #include "send.h"
-#include "msg.h"
-#include "parse.h"
-#include "modules.h"
+#include "s_user.h"
+#include "s_serv.h"
 #include "s_conf.h"
-#include "hash.h"
-
-struct flag_list
-{
-       char *name;
-       int flag;
-};
+#include "s_newconf.h"
+#include "msgbuf.h"
 
-static struct flag_list flaglist[] = {
-       {"kick",        CHANROLE_KICK},
-       {"grant",       CHANROLE_GRANT},
-       {"mode",        CHANROLE_MODE},
-       {"topic",       CHANROLE_TOPIC},
-       {"status",      CHANROLE_STATUS},
-       {NULL,          0},
-};
+static void mo_grant(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
+static void me_grant(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[]);
 
-static int me_grant(struct Client *, struct Client *, int, const char **);
+static int do_grant(struct Client *source_p, struct Client *target_p, const char *new_privset);
 
 struct Message grant_msgtab = {
-       "GRANT", 0, 0, 0, MFLG_SLOW,
-       {mg_ignore, mg_ignore, mg_ignore, mg_ignore, {me_grant, 4}, mg_ignore}
+  "GRANT", 0, 0, 0, 0,
+  { mg_ignore, mg_not_oper, mg_ignore, mg_ignore, {me_grant, 3}, {mo_grant, 3}}
 };
 
 mapi_clist_av1 grant_clist[] = { &grant_msgtab, NULL };
-DECLARE_MODULE_AV1(grant, NULL, NULL, grant_clist, NULL, NULL, "Charybdis development team");
 
-/*
- * me_grant
- *
- * parv[1] = channel
- * parv[2] = target UID
- * parv[3] = flag spec
-*/
-static int
-me_grant(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
+static const char grant_desc[] = "Allows operators to set or remove operator privileges on other users";
+
+DECLARE_MODULE_AV2(grant, NULL, NULL, grant_clist, NULL, NULL, NULL, NULL, grant_desc);
+
+static void
+mo_grant(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
 {
-       struct Channel *chptr;
        struct Client *target_p;
-       struct membership *msptr;
-       char *s, *t, *p;
 
-       if (!(chptr = find_channel(parv[1])))
-               return 0;
+       if(!HasPrivilege(source_p, "oper:grant"))
+       {
+               sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "grant");
+               return;
+       }
 
-       if (!(target_p = find_person(parv[2])))
-               return 0;
+       target_p = find_named_person(parv[1]);
+       if (target_p == NULL)
+       {
+               sendto_one_numeric(source_p, ERR_NOSUCHNICK,
+                               form_str(ERR_NOSUCHNICK), parv[1]);
+               return;
+       }
 
-       /* Makes no sense to do this for non-local users */
-       if(!MyClient(target_p))
-               return 0;
+       if (MyClient(target_p))
+       {
+               do_grant(source_p, target_p, parv[2]);
+       }
+       else
+       {
+               sendto_one(target_p, ":%s ENCAP %s GRANT %s %s",
+                               get_id(source_p, target_p), target_p->servptr->name,
+                               get_id(target_p, target_p), parv[2]);
+       }
+}
 
-       if (!(msptr = find_channel_membership(chptr, target_p)))
-               return 0;
+static void
+me_grant(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
+{
+       struct Client *target_p;
+
+       target_p = find_person(parv[1]);
+       if (target_p == NULL)
+       {
+               sendto_one_numeric(source_p, ERR_NOSUCHNICK,
+                               form_str(ERR_NOSUCHNICK), parv[1]);
+               return;
+       }
+
+       do_grant(source_p, target_p, parv[2]);
+}
+
+
+static int do_grant(struct Client *source_p, struct Client *target_p, const char *new_privset)
+{
+       int dooper = 0, dodeoper = 0;
+       struct PrivilegeSet *privset = NULL, *old_privset = NULL;
 
-       /* unset all chanroles as we're setting new ones */
-       msptr->roles = 0;
+       if (!strcasecmp(new_privset, "deoper"))
+       {
+               if (!IsOper(target_p))
+               {
+                       sendto_one_notice(source_p, ":You can't deoper someone who isn't an oper.");
+                       return 0;
+               }
+               dodeoper = 1;
 
-       t = LOCAL_COPY(parv[3]);
-       for (s = rb_strtok_r(t, " ", &p); s; s = rb_strtok_r(NULL, " ", &p))
+               sendto_one_notice(target_p, ":%s is deopering you.", source_p->name);
+               sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is deopering %s.", get_oper_name(source_p), target_p->name);
+       }
+       else
        {
-               const char *priv = s + 1;       /* The actual priv */
-               struct flag_list *fl;
-               int flag = 0;
+               if (!(privset = privilegeset_get(new_privset)))
+               {
+                       sendto_one_notice(source_p, ":There is no privilege set named '%s'.", new_privset);
+                       return 0;
+               }
+
+               if (privset == target_p->user->privset)
+               {
+                       sendto_one_notice(source_p, ":%s already has privilege set %s.", target_p->name, target_p->user->privset->name);
+                       return 0;
+               }
 
-               /* Go through the flags list... */
-               for(fl = flaglist; fl->name != NULL; fl++)
+               if (ConfigFileEntry.oper_secure_only && !IsSecureClient(target_p))
                {
-                       if (strcasecmp(fl->name, priv) == 0)
-                       {
-                               flag = fl->flag;
-                               break;
-                       }
+                       sendto_one_notice(source_p, ":Cannot GRANT %s, opers must be using secure connections.", target_p->name);
+                       return 0;
                }
+       }
+
+       if (!dodeoper)
+       {
+               if (!IsOper(target_p))
+               {
+                       sendto_one_notice(target_p, ":%s is opering you with privilege set %s", source_p->name, privset->name);
+                       sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is opering %s with privilege set %s", get_oper_name(source_p), target_p->name, privset->name);
+                       dooper = 1;
+               }
+               else
+               {
+                       sendto_one_notice(target_p, ":%s is changing your privilege set to %s", source_p->name, privset->name);
+                       sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "%s is changing the privilege set of %s to %s", get_oper_name(source_p), target_p->name, privset->name);
+               }
+
+               if (!IsOper(target_p))
+               {
+                       dooper = 1;
+               }
+       }
+
+       if (dodeoper)
+       {
+               const char *modeparv[4];
+               modeparv[0] = modeparv[1] = target_p->name;
+               modeparv[2] = "-o";
+               modeparv[3] = NULL;
+               user_mode(target_p, target_p, 3, modeparv);
+
+               return 0;
+       }
+
+       if (dooper)
+       {
+               struct oper_conf oper = {0};
+               oper.name = "<grant>";
+               oper.privset = privset;
+
+               oper_up(target_p, &oper);
+       }
+       else
+       {
+               if (privset != NULL)
+                       privilegeset_ref(privset);
+
+               if (target_p->user->privset != NULL)
+                       old_privset = target_p->user->privset;
+
+               target_p->user->privset = privset;
+
+               if (privset != NULL)
+                       sendto_server(NULL, NULL, CAP_TS6, NOCAPS, ":%s OPER %s %s",
+                                       use_id(target_p), target_p->user->opername, privset->name);
+
+               report_priv_change(target_p, old_privset, privset);
 
-               /* Ack no flag! */
-               if (!flag)
-                       continue;
+               if (old_privset != NULL)
+                       privilegeset_unref(old_privset);
 
-               if (s[0] == '-')
-                       RemoveChanRole(msptr, flag);
-               else if (s[0] == '+')
-                       SetChanRole(msptr, flag);
+               const char *modeparv[4];
+               modeparv[0] = modeparv[1] = target_p->name;
+               modeparv[2] = "+";
+               modeparv[3] = NULL;
+               user_mode(target_p, target_p, 3, modeparv);
        }
 
        return 0;