2 * Copyright (C) 2006 Jilles Tjoelker
3 * Copyright (C) 2006 Stephen Bennett <spb@gentoo.org>
14 #include "s_newconf.h"
16 static int mo_grant(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[]);
17 static int me_grant(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[]);
19 static int do_grant(struct Client
*source_p
, struct Client
*target_p
, int addflags
, int removeflags
, int dooper
,
20 int dodeoper
, int add_snomask
, int remove_snomask
);
22 struct Message grant_msgtab
= {
23 "GRANT", 0, 0, 0, MFLG_SLOW
,
24 { mg_ignore
, mg_not_oper
, mg_ignore
, mg_ignore
, {me_grant
, 5}, {mo_grant
, 3}}
27 mapi_clist_av1 grant_clist
[] = { &grant_msgtab
, NULL
};
29 DECLARE_MODULE_AV1(grant
, NULL
, NULL
, grant_clist
, NULL
, NULL
, "$Revision$");
31 /* copied from src/newconf.c */
38 extern struct mode_table flag_table
[];
41 mo_grant(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
43 struct Client
*target_p
;
44 int addflags
= 0, removeflags
= 0;
45 int dooper
= 0, dodeoper
= 0;
50 int add_snomask
= 0, remove_snomask
= 0;
51 char oper_flag_changes
[32], snomask_changes
[64];
53 if(!IsOperGrant(source_p
))
55 sendto_one(source_p
, form_str(ERR_NOPRIVS
), me
.name
, source_p
->name
, "grant");
59 target_p
= find_named_person(parv
[1]);
62 sendto_one_numeric(source_p
, ERR_NOSUCHNICK
,
63 form_str(ERR_NOSUCHNICK
), parv
[1]);
67 for (i
= 2; i
< parc
; i
++)
76 if (!irccmp(p
, "oper"))
79 dooper
= 1, dodeoper
= 0;
81 dodeoper
= 1, dooper
= 0;
84 if (!irccmp(p
, "snomask"))
86 add_snomask
= parse_snobuf_to_mask(0, parv
[++i
]);
87 remove_snomask
= ~parse_snobuf_to_mask(~0, parv
[i
]);
91 for (j
= 0; flag_table
[j
].name
!= NULL
; j
++)
93 if (!irccmp(p
, flag_table
[j
].name
))
96 addflags
|= flag_table
[j
].mode
, removeflags
&= ~flag_table
[j
].mode
;
98 removeflags
|= flag_table
[j
].mode
, addflags
&= ~flag_table
[j
].mode
;
102 if (flag_table
[j
].name
== NULL
)
104 sendto_one_notice(source_p
, ":Unknown GRANT keyword '%s'", p
);
108 if (((addflags
| removeflags
) & source_p
->operflags
) != (addflags
| removeflags
))
110 sendto_one_notice(source_p
, ":You may not change flags you do not have access to");
114 if (MyClient(target_p
))
116 do_grant(source_p
, target_p
, addflags
, removeflags
, dooper
, dodeoper
,
117 add_snomask
, remove_snomask
);
121 q
= oper_flag_changes
;
123 for (i
= 0; oper_flagtable
[i
].flag
; ++i
)
125 if (addflags
& oper_flagtable
[i
].flag
)
126 *q
++ = oper_flagtable
[i
].has
;
127 else if (removeflags
& oper_flagtable
[i
].flag
)
128 *q
++ = oper_flagtable
[i
].hasnt
;
130 if(q
== oper_flag_changes
)
134 strlcpy(snomask_changes
, construct_snobuf_changes(add_snomask
, remove_snomask
), sizeof(snomask_changes
));
136 sendto_one(target_p
, ":%s ENCAP %s GRANT %s %s %d %d %s",
137 get_id(source_p
, target_p
), target_p
->servptr
->name
,
138 get_id(target_p
, target_p
), oper_flag_changes
, dooper
, dodeoper
,
145 static int me_grant(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
147 struct Client
*target_p
;
148 int addflags
= 0, removeflags
= 0, dooper
= 0, dodeoper
= 0, add_snomask
= 0, remove_snomask
= 0;
152 target_p
= find_person(parv
[1]);
153 if (target_p
== NULL
)
155 sendto_one_numeric(source_p
, ERR_NOSUCHNICK
,
156 form_str(ERR_NOSUCHNICK
), parv
[1]);
160 if (!find_client_shared_conf(source_p
, SHARED_GRANT
))
162 sendto_one(source_p
, ":%s NOTICE %s :*** You don't have an appropriate shared"
163 "block to grant privilege on this server.", me
.name
, source_p
->name
);
169 for (i
= 0; oper_flagtable
[i
].flag
; ++i
)
171 if (*p
== oper_flagtable
[i
].has
)
172 addflags
|= oper_flagtable
[i
].flag
;
173 else if (*p
== oper_flagtable
[i
].hasnt
)
174 removeflags
|= oper_flagtable
[i
].flag
;
175 else if (*p
== '\0' || *p
== '.')
182 dooper
= atoi(parv
[3]);
183 dodeoper
= atoi(parv
[4]);
185 add_snomask
= parse_snobuf_to_mask(0, parv
[5]);
186 remove_snomask
= ~parse_snobuf_to_mask(~0, parv
[5]);
188 do_grant(source_p
, target_p
, addflags
, removeflags
, dooper
, dodeoper
, add_snomask
, remove_snomask
);
194 static int do_grant(struct Client
*source_p
, struct Client
*target_p
, int addflags
, int removeflags
, int dooper
,
195 int dodeoper
, int add_snomask
, int remove_snomask
)
197 const char *newparv
[4];
198 struct oper_conf oper
;
200 int orig_snomask
= target_p
->allowed_snomask
;
206 if (!IsOper(target_p
))
207 sendto_one_notice(source_p
, ":%s is not an oper",
211 newparv
[0] = target_p
->name
;
212 newparv
[1] = target_p
->name
;
215 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
,
216 "%s is deopering %s",
217 get_oper_name(source_p
),
218 get_client_name(target_p
, HIDE_IP
));
219 sendto_one_notice(target_p
, ":%s is deopering you",
221 user_mode(target_p
, target_p
, 3, newparv
);
222 sendto_one_notice(source_p
, ":Deopered %s",
229 if (IsOper(target_p
))
230 sendto_one_notice(source_p
, ":%s is already an oper",
235 for (j
= 0; flag_table
[j
].name
!= NULL
; j
++)
237 if ((addflags
& flag_table
[j
].mode
) == flag_table
[j
].mode
)
240 strlcat(desc
, " ", sizeof desc
);
241 strlcat(desc
, "+", sizeof desc
);
242 strlcat(desc
, flag_table
[j
].name
, sizeof desc
);
246 strlcpy(desc
, "<none>", sizeof desc
);
247 oper
.name
= "<grant>";
251 oper
.flags
= addflags
;
254 oper
.allowed_snomask
= add_snomask
;
255 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
,
256 "%s is opering %s with flags %s and snomask %s",
257 get_oper_name(source_p
),
258 get_client_name(target_p
, HIDE_IP
),
260 construct_snobuf(oper
.allowed_snomask
));
261 sendto_one_notice(target_p
, ":%s is opering you",
263 oper_up(target_p
, &oper
);
264 sendto_one_notice(source_p
, ":Opered %s with flags %s and snomask %s",
265 target_p
->name
, desc
, construct_snobuf(oper
.allowed_snomask
));
269 removeflags
&= target_p
->operflags
;
270 addflags
&= ~target_p
->operflags
;
271 remove_snomask
&= target_p
->allowed_snomask
;
272 add_snomask
&= ~target_p
->allowed_snomask
;
273 if ((addflags
| removeflags
| add_snomask
| remove_snomask
) != 0)
275 if (!IsOper(target_p
))
277 sendto_one_notice(source_p
, ":%s is not an oper",
282 target_p
->operflags
|= addflags
;
283 target_p
->operflags
&= ~removeflags
;
284 target_p
->allowed_snomask
|= add_snomask
;
285 target_p
->allowed_snomask
&= ~remove_snomask
;
287 for (j
= 0; flag_table
[j
].name
!= NULL
; j
++)
289 if ((addflags
& flag_table
[j
].mode
) == flag_table
[j
].mode
)
292 strlcat(desc
, " ", sizeof desc
);
293 strlcat(desc
, "+", sizeof desc
);
294 strlcat(desc
, flag_table
[j
].name
, sizeof desc
);
296 else if ((removeflags
& flag_table
[j
].mode
) == flag_table
[j
].mode
)
299 strlcat(desc
, " ", sizeof desc
);
300 strlcat(desc
, "-", sizeof desc
);
301 strlcat(desc
, flag_table
[j
].name
, sizeof desc
);
305 strlcpy(desc
, "<none>", sizeof desc
);
306 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
,
307 "%s is changing oper flags on %s (%s, snomask %s)",
308 get_oper_name(source_p
),
309 get_client_name(target_p
, HIDE_IP
),
311 construct_snobuf_changes(target_p
->allowed_snomask
& ~orig_snomask
,
312 orig_snomask
& ~target_p
->allowed_snomask
));
313 sendto_one_notice(target_p
, ":%s is changing oper flags on you: %s, snomask %s",
314 source_p
->name
, desc
, construct_snobuf_changes(target_p
->allowed_snomask
& ~orig_snomask
,
315 orig_snomask
& ~target_p
->allowed_snomask
));
316 sendto_one_notice(source_p
, ":Changed oper flags on %s: %s, snomask %s",
317 target_p
->name
, desc
, construct_snobuf_changes(target_p
->allowed_snomask
& ~orig_snomask
,
318 orig_snomask
& ~target_p
->allowed_snomask
));
320 sendto_server(source_p
, NULL
, CAP_TS6
, NOCAPS
, ":%s ENCAP * OPER %s",
321 get_id(target_p
, target_p
), get_oper_privs(target_p
->operflags
));
323 sendto_server(source_p
, NULL
, NOCAPS
, CAP_TS6
, ":%s ENCAP * OPER %s",
324 target_p
->name
, get_oper_privs(target_p
->operflags
));
326 /* fix up any umodes/snomasks they may not have
328 newparv
[0] = target_p
->name
;
329 newparv
[1] = target_p
->name
;
332 user_mode(target_p
, target_p
, 3, newparv
);
337 sendto_one_notice(source_p
, ":Oper flags on %s unchanged",