2 * Copyright (C) 2006 Jilles Tjoelker
3 * Copyright (C) 2006 Stephen Bennett <spb@gentoo.org>
16 #include "s_newconf.h"
18 static int mo_grant(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[]);
19 static int me_grant(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[]);
21 static int do_grant(struct Client
*source_p
, struct Client
*target_p
, int addflags
, int removeflags
, int dooper
,
22 int dodeoper
, int add_snomask
, int remove_snomask
);
24 struct Message grant_msgtab
= {
25 "GRANT", 0, 0, 0, MFLG_SLOW
,
26 { mg_ignore
, mg_not_oper
, mg_ignore
, mg_ignore
, {me_grant
, 5}, {mo_grant
, 3}}
29 mapi_clist_av1 grant_clist
[] = { &grant_msgtab
, NULL
};
31 DECLARE_MODULE_AV1(grant
, NULL
, NULL
, grant_clist
, NULL
, NULL
, "$Revision$");
33 /* copied from src/newconf.c */
40 extern struct mode_table flag_table
[];
43 mo_grant(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
45 struct Client
*target_p
;
46 int addflags
= 0, removeflags
= 0;
47 int dooper
= 0, dodeoper
= 0;
52 int add_snomask
= 0, remove_snomask
= 0;
53 char oper_flag_changes
[32], snomask_changes
[64];
55 if(!IsOperGrant(source_p
))
57 sendto_one(source_p
, form_str(ERR_NOPRIVS
), me
.name
, source_p
->name
, "grant");
61 target_p
= find_named_person(parv
[1]);
64 sendto_one_numeric(source_p
, ERR_NOSUCHNICK
,
65 form_str(ERR_NOSUCHNICK
), parv
[1]);
69 for (i
= 2; i
< parc
; i
++)
78 if (!irccmp(p
, "oper"))
81 dooper
= 1, dodeoper
= 0;
83 dodeoper
= 1, dooper
= 0;
86 if (!irccmp(p
, "snomask"))
88 add_snomask
= parse_snobuf_to_mask(0, parv
[++i
]);
89 remove_snomask
= ~parse_snobuf_to_mask(~0, parv
[i
]);
93 for (j
= 0; flag_table
[j
].name
!= NULL
; j
++)
95 if (!irccmp(p
, flag_table
[j
].name
))
98 addflags
|= flag_table
[j
].mode
, removeflags
&= ~flag_table
[j
].mode
;
100 removeflags
|= flag_table
[j
].mode
, addflags
&= ~flag_table
[j
].mode
;
104 if (flag_table
[j
].name
== NULL
)
106 sendto_one_notice(source_p
, ":Unknown GRANT keyword '%s'", p
);
110 if (((addflags
| removeflags
) & source_p
->operflags
) != (addflags
| removeflags
))
112 sendto_one_notice(source_p
, ":You may not change flags you do not have access to");
116 if (MyClient(target_p
))
118 do_grant(source_p
, target_p
, addflags
, removeflags
, dooper
, dodeoper
,
119 add_snomask
, remove_snomask
);
123 q
= oper_flag_changes
;
125 for (i
= 0; oper_flagtable
[i
].flag
; ++i
)
127 if (addflags
& oper_flagtable
[i
].flag
)
128 *q
++ = oper_flagtable
[i
].has
;
129 else if (removeflags
& oper_flagtable
[i
].flag
)
130 *q
++ = oper_flagtable
[i
].hasnt
;
132 if(q
== oper_flag_changes
)
136 strlcpy(snomask_changes
, construct_snobuf_changes(add_snomask
, remove_snomask
), sizeof(snomask_changes
));
138 sendto_one(target_p
, ":%s ENCAP %s GRANT %s %s %d %d %s",
139 get_id(source_p
, target_p
), target_p
->servptr
->name
,
140 get_id(target_p
, target_p
), oper_flag_changes
, dooper
, dodeoper
,
147 static int me_grant(struct Client
*client_p
, struct Client
*source_p
, int parc
, const char *parv
[])
149 struct Client
*target_p
;
150 int addflags
= 0, removeflags
= 0, dooper
= 0, dodeoper
= 0, add_snomask
= 0, remove_snomask
= 0;
154 target_p
= find_person(parv
[1]);
155 if (target_p
== NULL
)
157 sendto_one_numeric(source_p
, ERR_NOSUCHNICK
,
158 form_str(ERR_NOSUCHNICK
), parv
[1]);
162 if(!find_shared_conf(source_p
->username
, source_p
->host
,
163 source_p
->user
->server
, SHARED_GRANT
))
165 sendto_one(source_p
, ":%s NOTICE %s :*** You don't have an appropriate shared"
166 "block to grant privilege on this server.", me
.name
, source_p
->name
);
172 for (i
= 0; oper_flagtable
[i
].flag
; ++i
)
174 if (*p
== oper_flagtable
[i
].has
)
175 addflags
|= oper_flagtable
[i
].flag
;
176 else if (*p
== oper_flagtable
[i
].hasnt
)
177 removeflags
|= oper_flagtable
[i
].flag
;
178 else if (*p
== '\0' || *p
== '.')
185 dooper
= atoi(parv
[3]);
186 dodeoper
= atoi(parv
[4]);
188 add_snomask
= parse_snobuf_to_mask(0, parv
[5]);
189 remove_snomask
= ~parse_snobuf_to_mask(~0, parv
[5]);
191 do_grant(source_p
, target_p
, addflags
, removeflags
, dooper
, dodeoper
, add_snomask
, remove_snomask
);
197 static int do_grant(struct Client
*source_p
, struct Client
*target_p
, int addflags
, int removeflags
, int dooper
,
198 int dodeoper
, int add_snomask
, int remove_snomask
)
200 const char *newparv
[4];
201 struct oper_conf oper
;
203 int orig_snomask
= target_p
->allowed_snomask
;
209 if (!IsOper(target_p
))
210 sendto_one_notice(source_p
, ":%s is not an oper",
214 newparv
[0] = target_p
->name
;
215 newparv
[1] = target_p
->name
;
218 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
,
219 "%s is deopering %s",
220 get_oper_name(source_p
),
221 get_client_name(target_p
, HIDE_IP
));
222 sendto_one_notice(target_p
, ":%s is deopering you",
224 user_mode(target_p
, target_p
, 3, newparv
);
225 sendto_one_notice(source_p
, ":Deopered %s",
232 if (IsOper(target_p
))
233 sendto_one_notice(source_p
, ":%s is already an oper",
238 for (j
= 0; flag_table
[j
].name
!= NULL
; j
++)
240 if ((addflags
& flag_table
[j
].mode
) == flag_table
[j
].mode
)
243 strlcat(desc
, " ", sizeof desc
);
244 strlcat(desc
, "+", sizeof desc
);
245 strlcat(desc
, flag_table
[j
].name
, sizeof desc
);
249 strlcpy(desc
, "<none>", sizeof desc
);
250 oper
.name
= "<grant>";
254 oper
.flags
= addflags
;
257 oper
.allowed_snomask
= add_snomask
;
258 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
,
259 "%s is opering %s with flags %s and snomask %s",
260 get_oper_name(source_p
),
261 get_client_name(target_p
, HIDE_IP
),
263 construct_snobuf(oper
.allowed_snomask
));
264 sendto_one_notice(target_p
, ":%s is opering you",
266 oper_up(target_p
, &oper
);
267 sendto_one_notice(source_p
, ":Opered %s with flags %s and snomask %s",
268 target_p
->name
, desc
, construct_snobuf(oper
.allowed_snomask
));
272 removeflags
&= target_p
->operflags
;
273 addflags
&= ~target_p
->operflags
;
274 remove_snomask
&= target_p
->allowed_snomask
;
275 add_snomask
&= ~target_p
->allowed_snomask
;
276 if ((addflags
| removeflags
| add_snomask
| remove_snomask
) != 0)
278 if (!IsOper(target_p
))
280 sendto_one_notice(source_p
, ":%s is not an oper",
285 target_p
->operflags
|= addflags
;
286 target_p
->operflags
&= ~removeflags
;
287 target_p
->allowed_snomask
|= add_snomask
;
288 target_p
->allowed_snomask
&= ~remove_snomask
;
290 for (j
= 0; flag_table
[j
].name
!= NULL
; j
++)
292 if ((addflags
& flag_table
[j
].mode
) == flag_table
[j
].mode
)
295 strlcat(desc
, " ", sizeof desc
);
296 strlcat(desc
, "+", sizeof desc
);
297 strlcat(desc
, flag_table
[j
].name
, sizeof desc
);
299 else if ((removeflags
& flag_table
[j
].mode
) == flag_table
[j
].mode
)
302 strlcat(desc
, " ", sizeof desc
);
303 strlcat(desc
, "-", sizeof desc
);
304 strlcat(desc
, flag_table
[j
].name
, sizeof desc
);
308 strlcpy(desc
, "<none>", sizeof desc
);
309 sendto_realops_snomask(SNO_GENERAL
, L_NETWIDE
,
310 "%s is changing oper flags on %s (%s, snomask %s)",
311 get_oper_name(source_p
),
312 get_client_name(target_p
, HIDE_IP
),
314 construct_snobuf_changes(target_p
->allowed_snomask
& ~orig_snomask
,
315 orig_snomask
& ~target_p
->allowed_snomask
));
316 sendto_one_notice(target_p
, ":%s is changing oper flags on you: %s, snomask %s",
317 source_p
->name
, desc
, construct_snobuf_changes(target_p
->allowed_snomask
& ~orig_snomask
,
318 orig_snomask
& ~target_p
->allowed_snomask
));
319 sendto_one_notice(source_p
, ":Changed oper flags on %s: %s, snomask %s",
320 target_p
->name
, desc
, construct_snobuf_changes(target_p
->allowed_snomask
& ~orig_snomask
,
321 orig_snomask
& ~target_p
->allowed_snomask
));
323 sendto_server(source_p
, NULL
, CAP_TS6
, NOCAPS
, ":%s ENCAP * OPER %s",
324 get_id(target_p
, target_p
), get_oper_privs(target_p
->operflags
));
326 sendto_server(source_p
, NULL
, NOCAPS
, CAP_TS6
, ":%s ENCAP * OPER %s",
327 target_p
->name
, get_oper_privs(target_p
->operflags
));
329 /* fix up any umodes/snomasks they may not have
331 newparv
[0] = target_p
->name
;
332 newparv
[1] = target_p
->name
;
335 user_mode(target_p
, target_p
, 3, newparv
);
340 sendto_one_notice(source_p
, ":Oper flags on %s unchanged",