]> jfr.im git - irc/quakenet/newserv.git/blame - control/control_management.c
BUILD: add require-all build mode
[irc/quakenet/newserv.git] / control / control_management.c
CommitLineData
3e3692bf
CP
1/*
2 * NOperserv v0.01
3 *
4 * A replacement for Germania's ageing Operservice2
5 *
6 * Copyright (C) 2005 Chris Porter.
7 */
8
9#include "../localuser/localuser.h"
10#include "../lib/irc_string.h"
d7a70850 11#include "../lib/strlfunc.h"
87698d77 12#include "../lib/version.h"
fb17e427 13#include "../authext/authext.h"
aef920fc
GB
14#include "../control/control.h"
15#include "../control/control_db.h"
16#include "../control/control_policy.h"
3e3692bf
CP
17
18#include <stdio.h>
19#include <string.h>
20#include <stdarg.h>
21
70b0a4e5 22MODULE_VERSION("");
87698d77 23
3e3692bf
CP
24#define FLAGBUFLEN 100
25
26#define NO_FOUND_NICKNAME 1
27#define NO_FOUND_AUTHNAME 2
28
3e3692bf 29/* @test */
aef920fc 30static int noperserv_hello(void *sender, int cargc, char **cargv) {
7078aa50 31 authname *newaccount = NULL;
3e3692bf 32 no_autheduser *au;
3e3692bf
CP
33 nick *np = (nick *)sender, *np2, *target = NULL;
34
35 if(cargc == 0) {
7078aa50 36 newaccount = np->auth;
3e3692bf
CP
37 } else {
38 if(cargv[0][0] == '#') {
7b1a4a73 39 authname *a = getauthbyname(cargv[0] + 1);
fb17e427 40 if(!a) {
3e3692bf
CP
41 controlreply(np, "Cannot find anyone with that authname on the network.");
42 return CMD_ERROR;
43 }
7078aa50 44 newaccount = a;
3e3692bf
CP
45 } else {
46 target = getnickbynick(cargv[0]);
47 if(!target) {
48 controlreply(np, "Supplied nickname is not on the network.");
49 return CMD_ERROR;
50 }
7078aa50 51 newaccount = target->auth;
3e3692bf
CP
52 }
53 }
7078aa50
GB
54 if(!newaccount) {
55 controlreply(np, "Supplied user is not authed with the network.");
56 return CMD_ERROR;
57 }
3e3692bf
CP
58 au = noperserv_get_autheduser(newaccount);
59 if(au) {
60 controlreply(np, "Authname already registered.");
61 return CMD_ERROR;
62 }
63
7078aa50 64 au = noperserv_new_autheduser(newaccount->userid, newaccount->name);
3e3692bf
CP
65 if(!au) {
66 controlreply(np, "Memory allocation error.");
67 return CMD_ERROR;
68 }
69
70 if(noperserv_get_autheduser_count() == 1) {
71 au->authlevel = NO_FIRST_USER_LEVEL;
72 au->noticelevel = NO_FIRST_USER_DEFAULT_NOTICELEVEL;
73 } else {
74 au->authlevel = NO_DEFAULT_LEVEL;
75 au->noticelevel = NO_DEFAULT_NOTICELEVEL;
76 }
77
3e3692bf
CP
78 noperserv_update_autheduser(au);
79
7078aa50
GB
80 for(np2=newaccount->nicks;np2;np2=np2->nextbyauthname) {
81 controlreply(np2, "An account has been created for you (auth %s).", au->authname->name);
82 if(NOGetAuthLevel(au))
83 controlreply(np2, "User flags: %s", printflags(NOGetAuthLevel(au), no_userflags));
84 controlreply(np2, "Notice flags: %s", printflags(NOGetNoticeLevel(au), no_noticeflags));
85 }
3e3692bf 86
7078aa50
GB
87 if(np->auth==newaccount) { /* send a message to the person who HELLO'ed if we haven't already been told */
88 controlreply(np, "Account created for auth %s.", au->authname->name);
3e3692bf
CP
89 if(NOGetAuthLevel(au))
90 controlreply(np, "User flags: %s", printflags(NOGetAuthLevel(au), no_userflags));
91 controlreply(np, "Notice flags: %s", printflags(NOGetNoticeLevel(au), no_noticeflags));
92 controlreply(np, "Instructions sent to all authed users.");
7078aa50 93 } else if(newaccount->nicks && newaccount->nicks->next) { /* if we have already been told, tell the user it was sent to more than themselves */
3e3692bf
CP
94 controlreply(np, "Instructions sent to all authed users.");
95 }
96
7078aa50 97 controlwall(NO_OPERED, NL_MANAGEMENT, "%s/%s just HELLO'ed: %s", np->nick, np->authname, au->authname->name);
3e3692bf
CP
98 return CMD_OK;
99}
100
aef920fc 101static no_autheduser *noperserv_autheduser_from_command(nick *np, char *command, int *typefound, char **returned) {
3e3692bf 102 no_autheduser *au;
7078aa50 103 authname *anp;
3e3692bf 104 if(command[0] == '#') {
7078aa50
GB
105 anp = findauthnamebyname(command + 1);
106 if(!anp) {
107 controlreply(np, "Authname not found.");
108 return NULL;
109 }
110 au = noperserv_get_autheduser(anp);
3e3692bf
CP
111 if(!au) {
112 controlreply(np, "Authname not found.");
113 } else {
114 *typefound = NO_FOUND_AUTHNAME;
7078aa50 115 *returned = au->authname->name;
3e3692bf
CP
116 return au;
117 }
118 } else {
119 nick *np2 = getnickbynick(command);
120 if(!np2) {
121 controlreply(np, "Nickname not on the network.");
7078aa50 122 return NULL;
3e3692bf
CP
123 }
124 if(!IsAccount(np2)) {
125 controlreply(np, "User is not authed with the network.");
7078aa50 126 return NULL;
3e3692bf
CP
127 }
128 au = NOGetAuthedUser(np2);
129 if(!au) {
130 controlreply(np, "User does not have an account.");
131 } else {
132 *typefound = NO_FOUND_NICKNAME;
133 *returned = np2->nick;
134 return au;
135 }
136 }
137
138 return NULL;
139}
140
aef920fc 141static int noperserv_noticeflags(void *sender, int cargc, char **cargv) {
7078aa50 142 nick *np2, *np = (nick *)sender;
3e3692bf
CP
143 no_autheduser *au;
144
145 if(cargc == 1) {
146 if((cargv[0][0] == '+') || (cargv[0][0] == '-')) {
147 int ret;
148 au = NOGetAuthedUser(np);
149 flag_t fwas = NOGetNoticeLevel(au), permittedchanges = noperserv_policy_permitted_noticeflags(au);
150
151 ret = setflags(&au->noticelevel, permittedchanges, cargv[0], no_noticeflags, REJECT_DISALLOWED | REJECT_UNKNOWN);
152 if(ret != REJECT_UNKNOWN) {
153 if(ret == REJECT_DISALLOWED) {
154 flag_t fnow = fwas;
155 setflags(&fnow, NL_ALL, cargv[0], no_noticeflags, REJECT_NONE);
156 if(fnow == fwas) {
157 controlreply(np, "No changes made to existing flags.");
158 } else {
159 char ourflags[FLAGBUFLEN], ournoticeflags[FLAGBUFLEN];
160 controlreply(np, "Flag alterations denied.");
161
162 strlcpy(ourflags, printflags(NOGetAuthLevel(au), no_userflags), sizeof(ourflags));
163 strlcpy(ournoticeflags, printflags(NOGetNoticeLevel(au), no_noticeflags), sizeof(ournoticeflags));
164 controlwall(NO_OPER, NL_MANAGEMENT, "%s/%s (%s) attempted to NOTICEFLAGS (%s): %s", np->nick, np->authname, ourflags, ournoticeflags, printflagdiff(fwas, fnow, no_noticeflags));
165 return CMD_ERROR;
166 }
167 } else if(ret == REJECT_NONE) {
168 if(NOGetNoticeLevel(au) == fwas) {
169 controlreply(np, "No changes made to existing flags.");
170 } else {
171 char ourflags[FLAGBUFLEN], ournoticeflags[FLAGBUFLEN], diff[FLAGBUFLEN * 2 + 1], finalflags[FLAGBUFLEN];
3e3692bf
CP
172 noperserv_update_autheduser(au);
173 controlreply(np, "Flag alterations complete.");
174
175 strlcpy(ourflags, printflags(NOGetAuthLevel(au), no_userflags), sizeof(ourflags));
176 strlcpy(ournoticeflags, printflags(fwas, no_noticeflags), sizeof(ournoticeflags));
177 strlcpy(diff, printflagdiff(fwas, NOGetNoticeLevel(au), no_noticeflags), sizeof(diff));
178 controlwall(NO_OPER, NL_MANAGEMENT, "%s/%s (%s) successfully used NOTICEFLAGS (%s): %s", np->nick, np->authname, ourflags, ournoticeflags, diff);
179
180 strlcpy(finalflags, printflags(NOGetNoticeLevel(au), no_noticeflags), sizeof(finalflags));
7078aa50
GB
181 for(np2=au->authname->nicks;np2;np2=np2->nextbyauthname)
182 if(np2 != np) {
183 controlreply(np2, "!!! %s just used NOTICEFLAGS (%s): %s", np->nick, ournoticeflags, diff);
184 controlreply(np2, "Your notice flags are %s", finalflags);
3e3692bf
CP
185 }
186 }
187 }
188 } else {
189 controlreply(np, "Unknown flag(s) supplied.");
190 return CMD_ERROR;
191 }
192 } else {
193 int typefound;
194 char *itemfound;
195 au = noperserv_autheduser_from_command(np, cargv[0], &typefound, &itemfound);
196 if(!au)
197 return CMD_ERROR;
198
199 if(au != NOGetAuthedUser(np)) {
200 controlreply(np, "Notice flags for %s %s are: %s", typefound==NO_FOUND_NICKNAME?"user":"authname", itemfound, printflags(NOGetNoticeLevel(au), no_noticeflags));
201 return CMD_OK;
202 }
203 }
204 } else {
205 au = NOGetAuthedUser(np);
206 }
207
208 if(!au) /* shouldn't happen */
209 return CMD_ERROR;
210
211 controlreply(np, "Your notice flags are: %s", printflags(NOGetNoticeLevel(au), no_noticeflags));
212
213 return CMD_OK;
214}
215
216/* @test */
aef920fc 217static int noperserv_deluser(void *sender, int cargc, char **cargv) {
7078aa50 218 nick *np2, *np = (nick *)sender;
3e3692bf
CP
219 no_autheduser *target /* target user */, *au = NOGetAuthedUser(np); /* user executing command */
220 char *userreturned = NULL; /* nickname or authname of the target, pulled from the db */
221 int typefound; /* whether it was an authname or a username */
3e3692bf
CP
222 char targetflags[FLAGBUFLEN], ourflags[FLAGBUFLEN], deleteduser[NOMax(ACCOUNTLEN, NICKLEN) + 1];
223
224 if(cargc != 1)
225 return CMD_USAGE;
226
227 target = noperserv_autheduser_from_command(np, cargv[0], &typefound, &userreturned);
228 if(!target)
229 return CMD_ERROR;
230
231 strlcpy(targetflags, printflags(NOGetAuthLevel(target), no_userflags), sizeof(targetflags));
232 strlcpy(ourflags, printflags(NOGetAuthLevel(au), no_userflags), sizeof(ourflags));
233
234 /* we have to copy it as it might point to an autheduser, which we're about to delete */
235 strlcpy(deleteduser, userreturned, sizeof(deleteduser));
236
237 /* we have to check if target != au, because if successful policy_modification_permitted just returns the flags we're allowed
238 to modify, if we have no flags we won't be able to delete ourselves */
239 if((target != au) && !noperserv_policy_permitted_modifications(au, target)) {
240 controlreply(np, "Deletion denied.");
7078aa50 241 controlwall(NO_OPER, NL_MANAGEMENT, "%s/%s (%s) attempted to DELUSER %s (%s)", np->nick, np->authname, ourflags, target->authname->name, targetflags);
3e3692bf
CP
242
243 return CMD_ERROR;
244 }
245
7078aa50
GB
246 for(np2=target->authname->nicks;np2;np2=np2->nextbyauthname)
247 if(np2 != np)
248 controlreply(np2, "!!! %s/%s (%s) just DELUSERed you.", np->nick, np->authname, ourflags);
3e3692bf
CP
249
250 noperserv_delete_autheduser(target);
251
7078aa50 252 controlwall(NO_OPER, NL_MANAGEMENT, "%s/%s (%s) successfully used DELUSER on %s (%s)", np->nick, np->authname, ourflags, deleteduser, targetflags);
3e3692bf
CP
253
254 if(target == au) {
255 controlreply(np, "You have been deleted.");
256 } else {
257 controlreply(np, "%s %s deleted.", typefound==NO_FOUND_AUTHNAME?"Auth":"User", deleteduser);
258 }
259
260 return CMD_OK;
261}
262
263/* @test */
264/* this command needs LOTS of checking */
aef920fc 265static int noperserv_userflags(void *sender, int cargc, char **cargv) {
7078aa50 266 nick *np2, *np = (nick *)sender;
3e3692bf
CP
267 no_autheduser *au = NOGetAuthedUser(np), *target = NULL;
268 char *flags = NULL, *nicktarget = NULL;
269 int typefound;
270
271 if(cargc == 0) {
272 target = au;
273 } else if(cargc == 1) {
274 if((cargv[0][0] == '+') || (cargv[0][0] == '-')) { /* modify our own */
275 flags = cargv[0];
276 target = au;
277 } else { /* viewing someone elses */
278 nicktarget = cargv[0];
279 }
280 } else if(cargc == 2) {
281 nicktarget = cargv[0];
282 flags = cargv[1];
283 } else {
284 return CMD_USAGE;
285 }
286
287 if(nicktarget) {
288 target = noperserv_autheduser_from_command(np, nicktarget, &typefound, &nicktarget);
289 if(!target)
290 return CMD_ERROR;
291 }
292
293 if(flags) {
294 int ret;
295 flag_t permitted = noperserv_policy_permitted_modifications(au, target), fwas = NOGetAuthLevel(target), fours = NOGetAuthLevel(au);
296
297 ret = setflags(&target->authlevel, permitted, flags, no_userflags, REJECT_DISALLOWED | REJECT_UNKNOWN);
298 if(ret != REJECT_UNKNOWN) {
299 if(ret == REJECT_DISALLOWED) {
300 flag_t fnow = fwas;
301 setflags(&fnow, NO_ALL_FLAGS, flags, no_userflags, REJECT_NONE);
302 if(fnow == fwas) {
303 controlreply(np, "No changes made to existing flags.");
304 } else {
305 char targetflags[FLAGBUFLEN], ourflags[FLAGBUFLEN];
306 controlreply(np, "Flag alterations denied.");
307
308 strlcpy(targetflags, printflags(fwas, no_userflags), sizeof(targetflags));
309 strlcpy(ourflags, printflags(fours, no_userflags), sizeof(ourflags));
310
7078aa50 311 controlwall(NO_OPER, NL_MANAGEMENT, "%s/%s (%s) attempted to use USERFLAGS on %s (%s): %s", np->nick, np->authname, ourflags, target->authname->name, targetflags, printflagdiff(fwas, fnow, no_userflags));
3e3692bf
CP
312 return CMD_ERROR;
313 }
314 } else if(ret == REJECT_NONE) {
315 if(NOGetAuthLevel(target) == fwas) {
316 controlreply(np, "No changes made to existing flags.");
317 } else {
318 char targetflags[FLAGBUFLEN], ourflags[FLAGBUFLEN], finalflags[FLAGBUFLEN];
3e3692bf
CP
319
320 noperserv_policy_update_noticeflags(fwas, target);
321 noperserv_update_autheduser(target);
322
323 controlreply(np, "Flag alterations complete.");
324
325 strlcpy(targetflags, printflags(fwas, no_userflags), sizeof(targetflags));
326 strlcpy(ourflags, printflags(fours, no_userflags), sizeof(ourflags));
327
7078aa50 328 controlwall(NO_OPER, NL_MANAGEMENT, "%s/%s (%s) successfully used USERFLAGS on %s (%s): %s", np->nick, np->authname, ourflags, target->authname->name, targetflags, printflagdiff(fwas, NOGetAuthLevel(target), no_userflags));
3e3692bf
CP
329
330 strlcpy(finalflags, printflags(NOGetAuthLevel(target), no_userflags), sizeof(finalflags));
7078aa50
GB
331 for(np2=target->authname->nicks;np2;np2=np2->nextbyauthname)
332 if(np2 != np) {
333 controlreply(np2, "!!! %s/%s (%s) just used USERFLAGS on you (%s): %s", np->nick, np->authname, ourflags, targetflags, printflagdiff(fwas, NOGetAuthLevel(target), no_userflags));
334 controlreply(np2, "Your user flags are now: %s", finalflags);
335 controlreply(np2, "Your notice flags are now: %s", printflags(target->noticelevel, no_noticeflags));
3e3692bf
CP
336 }
337 }
338 }
339 } else {
340 controlreply(np, "Unknown flag(s) supplied.");
341 return CMD_ERROR;
342 }
343 }
344
345 if(target != au) {
346 controlreply(np, "User flags for %s %s: %s", typefound==NO_FOUND_AUTHNAME?"auth":"user", nicktarget, printflags(NOGetAuthLevel(target), no_userflags));
347 controlreply(np, "Notice flags for %s %s: %s", typefound==NO_FOUND_AUTHNAME?"auth":"user", nicktarget, printflags(target->noticelevel, no_noticeflags));
348 } else {
349 controlreply(np, "Your user flags are: %s", printflags(NOGetAuthLevel(target), no_userflags));
350 controlreply(np, "Your notice flags are: %s", printflags(target->noticelevel, no_noticeflags));
351 }
352
353 return CMD_OK;
354}
355
aef920fc
GB
356void _init() {
357 registercontrolhelpcmd("hello", NO_OPERED | NO_AUTHED, 1, &noperserv_hello, "Syntax: HELLO ?nickname|#authname?\nCreates an account on the service for the specified nick, or if one isn't supplied, your nickname.");
358 registercontrolhelpcmd("userflags", NO_ACCOUNT, 2, &noperserv_userflags,
359 "Syntax: USERFLAGS <nickname|#authname> ?modifications?\n"
360 " Views and modifies user permissions.\n"
361 " If no nickname or authname is supplied, you are substituted for it.\n"
362 " If no flags are supplied, flags are just displayed instead of modified."
363 " Flags:\n"
364 " +o: Operator\n"
365 " +s: Staff member\n"
366 " +S: Security team member\n"
367 " +d: NOperserv developer\n"
368 " +t: Trust queue worker\n"
369 " +Y: Relay\n"
370 " Additional flags may show up in SHOWCOMMANDS but are not userflags as such:\n"
371 " +r: Authed user\n"
372 " +R: Registered NOperserv user\n"
373 " +O: Must be /OPER'ed\n"
374 " +L: Legacy command\n"
375 );
376 registercontrolhelpcmd("noticeflags", NO_ACCOUNT, 1, &noperserv_noticeflags,
377 "Syntax: NOTICEFLAGS ?(nickname|#authname)|flags?\n"
378 " This command can view and modify your own notice flags, and view that of other users.\n"
379 " Flags:\n"
380 " +m: Management (hello, password, userflags, noticeflags)\n"
381 " +t: Trusts\n"
382 " +k: KICK/KILL commands\n"
383 " +g: GLINE commands\n"
4d64f9c6 384 " +G: automated gline messages\n"
aef920fc
GB
385 " +h: Shows when glines are set by code (hits)\n"
386 " +c: Clone information\n"
387 " +C: CLEARCHAN command\n"
388 " +f: FAKEUSER commands\n"
389 " +b: BROADCAST commands\n"
390 " +o: Operation commands, such as insmod, rmmod, die, etc\n"
391 " +O: /OPER\n"
392 " +I: Misc commands (resync, etc)\n"
7834e8e5 393 " +a: Automated cleanup notices\n"
aef920fc
GB
394 " +n: Sends notices instead of privmsgs\n"
395 " +A: Every single command sent to the service (spammy)\n"
396 );
3e3692bf 397
aef920fc
GB
398 registercontrolhelpcmd("deluser", NO_OPERED | NO_ACCOUNT, 2, &noperserv_deluser, "Syntax: DELUSER <nickname|#authname>\nDeletes the specified user.");
399}
400
401void _fini() {
402 deregistercontrolcmd("noticeflags", &noperserv_noticeflags);
403 deregistercontrolcmd("userflags", &noperserv_userflags);
404 deregistercontrolcmd("noticeflags", &noperserv_noticeflags);
405 deregistercontrolcmd("hello", &noperserv_hello);
406 deregistercontrolcmd("deluser", &noperserv_deluser);
3e3692bf 407}
aef920fc 408