4 * A replacement for Germania's ageing Operservice2
6 * Copyright (C) 2005 Chris Porter.
9 #include "../localuser/localuser.h"
10 #include "../lib/irc_string.h"
11 #include "../lib/strlfunc.h"
12 #include "../lib/version.h"
13 #include "../authext/authext.h"
14 #include "../control/control.h"
15 #include "../control/control_db.h"
16 #include "../control/control_policy.h"
24 #define FLAGBUFLEN 100
26 #define NO_FOUND_NICKNAME 1
27 #define NO_FOUND_AUTHNAME 2
30 static int noperserv_hello(void *sender
, int cargc
, char **cargv
) {
31 authname
*newaccount
= NULL
;
33 nick
*np
= (nick
*)sender
, *np2
, *target
= NULL
;
36 newaccount
= np
->auth
;
38 if(cargv
[0][0] == '#') {
39 authname
*a
= getauthbyname(cargv
[0] + 1);
41 controlreply(np
, "Cannot find anyone with that authname on the network.");
46 target
= getnickbynick(cargv
[0]);
48 controlreply(np
, "Supplied nickname is not on the network.");
51 newaccount
= target
->auth
;
55 controlreply(np
, "Supplied user is not authed with the network.");
58 au
= noperserv_get_autheduser(newaccount
);
60 controlreply(np
, "Authname already registered.");
64 au
= noperserv_new_autheduser(newaccount
->userid
, newaccount
->name
);
66 controlreply(np
, "Memory allocation error.");
70 if(noperserv_get_autheduser_count() == 1) {
71 au
->authlevel
= NO_FIRST_USER_LEVEL
;
72 au
->noticelevel
= NO_FIRST_USER_DEFAULT_NOTICELEVEL
;
74 au
->authlevel
= NO_DEFAULT_LEVEL
;
75 au
->noticelevel
= NO_DEFAULT_NOTICELEVEL
;
78 noperserv_update_autheduser(au
);
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
));
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
);
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.");
93 } else if(newaccount
->nicks
&& newaccount
->nicks
->next
) { /* if we have already been told, tell the user it was sent to more than themselves */
94 controlreply(np
, "Instructions sent to all authed users.");
97 controlwall(NO_OPERED
, NL_MANAGEMENT
, "%s/%s just HELLO'ed: %s", np
->nick
, np
->authname
, au
->authname
->name
);
101 static no_autheduser
*noperserv_autheduser_from_command(nick
*np
, char *command
, int *typefound
, char **returned
) {
104 if(command
[0] == '#') {
105 anp
= findauthnamebyname(command
+ 1);
107 controlreply(np
, "Authname not found.");
110 au
= noperserv_get_autheduser(anp
);
112 controlreply(np
, "Authname not found.");
114 *typefound
= NO_FOUND_AUTHNAME
;
115 *returned
= au
->authname
->name
;
119 nick
*np2
= getnickbynick(command
);
121 controlreply(np
, "Nickname not on the network.");
124 if(!IsAccount(np2
)) {
125 controlreply(np
, "User is not authed with the network.");
128 au
= NOGetAuthedUser(np2
);
130 controlreply(np
, "User does not have an account.");
132 *typefound
= NO_FOUND_NICKNAME
;
133 *returned
= np2
->nick
;
141 static int noperserv_noticeflags(void *sender
, int cargc
, char **cargv
) {
142 nick
*np2
, *np
= (nick
*)sender
;
146 if((cargv
[0][0] == '+') || (cargv
[0][0] == '-')) {
148 au
= NOGetAuthedUser(np
);
149 flag_t fwas
= NOGetNoticeLevel(au
), permittedchanges
= noperserv_policy_permitted_noticeflags(au
);
151 ret
= setflags(&au
->noticelevel
, permittedchanges
, cargv
[0], no_noticeflags
, REJECT_DISALLOWED
| REJECT_UNKNOWN
);
152 if(ret
!= REJECT_UNKNOWN
) {
153 if(ret
== REJECT_DISALLOWED
) {
155 setflags(&fnow
, NL_ALL
, cargv
[0], no_noticeflags
, REJECT_NONE
);
157 controlreply(np
, "No changes made to existing flags.");
159 char ourflags
[FLAGBUFLEN
], ournoticeflags
[FLAGBUFLEN
];
160 controlreply(np
, "Flag alterations denied.");
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
));
167 } else if(ret
== REJECT_NONE
) {
168 if(NOGetNoticeLevel(au
) == fwas
) {
169 controlreply(np
, "No changes made to existing flags.");
171 char ourflags
[FLAGBUFLEN
], ournoticeflags
[FLAGBUFLEN
], diff
[FLAGBUFLEN
* 2 + 1], finalflags
[FLAGBUFLEN
];
172 noperserv_update_autheduser(au
);
173 controlreply(np
, "Flag alterations complete.");
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
);
180 strlcpy(finalflags
, printflags(NOGetNoticeLevel(au
), no_noticeflags
), sizeof(finalflags
));
181 for(np2
=au
->authname
->nicks
;np2
;np2
=np2
->nextbyauthname
)
183 controlreply(np2
, "!!! %s just used NOTICEFLAGS (%s): %s", np
->nick
, ournoticeflags
, diff
);
184 controlreply(np2
, "Your notice flags are %s", finalflags
);
189 controlreply(np
, "Unknown flag(s) supplied.");
195 au
= noperserv_autheduser_from_command(np
, cargv
[0], &typefound
, &itemfound
);
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
));
205 au
= NOGetAuthedUser(np
);
208 if(!au
) /* shouldn't happen */
211 controlreply(np
, "Your notice flags are: %s", printflags(NOGetNoticeLevel(au
), no_noticeflags
));
217 static int noperserv_deluser(void *sender
, int cargc
, char **cargv
) {
218 nick
*np2
, *np
= (nick
*)sender
;
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 */
222 char targetflags
[FLAGBUFLEN
], ourflags
[FLAGBUFLEN
], deleteduser
[NOMax(ACCOUNTLEN
, NICKLEN
) + 1];
227 target
= noperserv_autheduser_from_command(np
, cargv
[0], &typefound
, &userreturned
);
231 strlcpy(targetflags
, printflags(NOGetAuthLevel(target
), no_userflags
), sizeof(targetflags
));
232 strlcpy(ourflags
, printflags(NOGetAuthLevel(au
), no_userflags
), sizeof(ourflags
));
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
));
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.");
241 controlwall(NO_OPER
, NL_MANAGEMENT
, "%s/%s (%s) attempted to DELUSER %s (%s)", np
->nick
, np
->authname
, ourflags
, target
->authname
->name
, targetflags
);
246 for(np2
=target
->authname
->nicks
;np2
;np2
=np2
->nextbyauthname
)
248 controlreply(np2
, "!!! %s/%s (%s) just DELUSERed you.", np
->nick
, np
->authname
, ourflags
);
250 noperserv_delete_autheduser(target
);
252 controlwall(NO_OPER
, NL_MANAGEMENT
, "%s/%s (%s) successfully used DELUSER on %s (%s)", np
->nick
, np
->authname
, ourflags
, deleteduser
, targetflags
);
255 controlreply(np
, "You have been deleted.");
257 controlreply(np
, "%s %s deleted.", typefound
==NO_FOUND_AUTHNAME
?"Auth":"User", deleteduser
);
264 /* this command needs LOTS of checking */
265 static int noperserv_userflags(void *sender
, int cargc
, char **cargv
) {
266 nick
*np2
, *np
= (nick
*)sender
;
267 no_autheduser
*au
= NOGetAuthedUser(np
), *target
= NULL
;
268 char *flags
= NULL
, *nicktarget
= NULL
;
273 } else if(cargc
== 1) {
274 if((cargv
[0][0] == '+') || (cargv
[0][0] == '-')) { /* modify our own */
277 } else { /* viewing someone elses */
278 nicktarget
= cargv
[0];
280 } else if(cargc
== 2) {
281 nicktarget
= cargv
[0];
288 target
= noperserv_autheduser_from_command(np
, nicktarget
, &typefound
, &nicktarget
);
295 flag_t permitted
= noperserv_policy_permitted_modifications(au
, target
), fwas
= NOGetAuthLevel(target
), fours
= NOGetAuthLevel(au
);
297 ret
= setflags(&target
->authlevel
, permitted
, flags
, no_userflags
, REJECT_DISALLOWED
| REJECT_UNKNOWN
);
298 if(ret
!= REJECT_UNKNOWN
) {
299 if(ret
== REJECT_DISALLOWED
) {
301 setflags(&fnow
, NO_ALL_FLAGS
, flags
, no_userflags
, REJECT_NONE
);
303 controlreply(np
, "No changes made to existing flags.");
305 char targetflags
[FLAGBUFLEN
], ourflags
[FLAGBUFLEN
];
306 controlreply(np
, "Flag alterations denied.");
308 strlcpy(targetflags
, printflags(fwas
, no_userflags
), sizeof(targetflags
));
309 strlcpy(ourflags
, printflags(fours
, no_userflags
), sizeof(ourflags
));
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
));
314 } else if(ret
== REJECT_NONE
) {
315 if(NOGetAuthLevel(target
) == fwas
) {
316 controlreply(np
, "No changes made to existing flags.");
318 char targetflags
[FLAGBUFLEN
], ourflags
[FLAGBUFLEN
], finalflags
[FLAGBUFLEN
];
320 noperserv_policy_update_noticeflags(fwas
, target
);
321 noperserv_update_autheduser(target
);
323 controlreply(np
, "Flag alterations complete.");
325 strlcpy(targetflags
, printflags(fwas
, no_userflags
), sizeof(targetflags
));
326 strlcpy(ourflags
, printflags(fours
, no_userflags
), sizeof(ourflags
));
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
));
330 strlcpy(finalflags
, printflags(NOGetAuthLevel(target
), no_userflags
), sizeof(finalflags
));
331 for(np2
=target
->authname
->nicks
;np2
;np2
=np2
->nextbyauthname
)
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
));
340 controlreply(np
, "Unknown flag(s) supplied.");
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
));
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
));
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."
365 " +s: Staff member\n"
366 " +S: Security team member\n"
367 " +d: NOperserv developer\n"
368 " +t: Trust queue worker\n"
370 " Additional flags may show up in SHOWCOMMANDS but are not userflags as such:\n"
372 " +R: Registered NOperserv user\n"
373 " +O: Must be /OPER'ed\n"
374 " +L: Legacy command\n"
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"
380 " +m: Management (hello, password, userflags, noticeflags)\n"
382 " +k: KICK/KILL commands\n"
383 " +g: GLINE commands\n"
384 " +h: Shows when glines are set by code (hits)\n"
385 " +c: Clone information\n"
386 " +C: CLEARCHAN command\n"
387 " +f: FAKEUSER commands\n"
388 " +b: BROADCAST commands\n"
389 " +o: Operation commands, such as insmod, rmmod, die, etc\n"
391 " +I: Misc commands (resync, etc)\n"
392 " +n: Sends notices instead of privmsgs\n"
393 " +A: Every single command sent to the service (spammy)\n"
396 registercontrolhelpcmd("deluser", NO_OPERED
| NO_ACCOUNT
, 2, &noperserv_deluser
, "Syntax: DELUSER <nickname|#authname>\nDeletes the specified user.");
400 deregistercontrolcmd("noticeflags", &noperserv_noticeflags
);
401 deregistercontrolcmd("userflags", &noperserv_userflags
);
402 deregistercontrolcmd("noticeflags", &noperserv_noticeflags
);
403 deregistercontrolcmd("hello", &noperserv_hello
);
404 deregistercontrolcmd("deluser", &noperserv_deluser
);