]> jfr.im git - irc/quakenet/newserv.git/blame - trusts/trusts_commands.c
Add subset/set checking into trustadd, now handles moving of users between trusts...
[irc/quakenet/newserv.git] / trusts / trusts_commands.c
CommitLineData
d2c08930 1#include <stdio.h>
be2823bc 2#include "../control/control.h"
2d4ba67d 3#include "../lib/irc_string.h"
be2823bc
CP
4#include "trusts.h"
5
6int trusts_migration_start(TrustDBMigrationCallback, void *);
7void trusts_migration_stop(void);
83bccee3
CP
8static void registercommands(int, void *);
9static void deregistercommands(int, void *);
be2823bc 10
be2823bc
CP
11static void migrate_status(int errcode, void *tag) {
12 long sender = (long)tag;
13 nick *np = getnickbynumeric(sender);
14
15 if(!np)
16 return;
17
e00bb3fb
CP
18 if(!errcode || errcode == MIGRATION_LASTERROR) {
19 if(!errcode) {
20 controlreply(np, "Migration complete.");
21 controlreply(np, "Attempting to reload database. . .");
22 } else {
23 controlreply(np, "An error occured after the database was unloaded, attempting reload. . .");
24 }
25 if(trusts_loaddb()) {
26 controlreply(np, "Database reloaded successfully.");
27 } else {
28 controlreply(np, "An error occured, please reload the module manually.");
29 }
be2823bc 30 } else {
bf5b66e5 31 controlreply(np, "Error %d occured during migration, commands reregistered.", errcode);
a99a2041 32 registercommands(0, NULL);
be2823bc
CP
33 }
34}
35
36static int trusts_cmdmigrate(void *source, int cargc, char **cargv) {
37 nick *sender = source;
38 int ret;
39
40 /* iffy but temporary */
41 ret = trusts_migration_start(migrate_status, (void *)(sender->numeric));
42 if(!ret) {
bf5b66e5 43 controlreply(sender, "Migration started, commands deregistered.");
83bccee3 44 deregistercommands(0, NULL);
be2823bc
CP
45 } else {
46 controlreply(sender, "Error %d starting migration.", ret);
47 }
48
49 return CMD_OK;
50}
51
2d4ba67d
CP
52static int trusts_cmdtrustlist(void *source, int cargc, char **cargv) {
53 nick *sender = source;
54 trustgroup *tg;
55 trusthost *th;
56 time_t t;
57
58 if(cargc < 1)
59 return CMD_USAGE;
60
61 tg = tg_strtotg(cargv[0]);
62 if(!tg) {
63 controlreply(sender, "Couldn't find a trustgroup with that id.");
64 return CMD_ERROR;
65 }
66
67 t = time(NULL);
68
d36ca89c 69 /* abusing the ternary operator a bit :( */
4b003d19 70 controlreply(sender, "Name: : %s", tg->name->content);
2d4ba67d 71 controlreply(sender, "Trusted for : %d", tg->trustedfor);
1bbe1ac3 72 controlreply(sender, "Currently using : %d", tg->count);
2d4ba67d 73 controlreply(sender, "Clients per user : %d (%senforcing ident)", tg->maxperident, tg->mode?"":"not ");
4b003d19 74 controlreply(sender, "Contact: : %s", tg->contact->content);
d36ca89c 75 controlreply(sender, "Expires in : %s", (tg->expires>t)?longtoduration(tg->expires - t, 2):"(the past -- BUG)");
4b003d19
CP
76 controlreply(sender, "Last changed by : %s", tg->createdby->content);
77 controlreply(sender, "Comment: : %s", tg->comment->content);
2d4ba67d 78 controlreply(sender, "ID: : %u", tg->id);
d36ca89c 79 controlreply(sender, "Last used : %s", (tg->count>0)?"(now)":((tg->lastseen>0)?trusts_timetostr(tg->lastseen):"(never)"));
4be1aaf2 80 controlreply(sender, "Max usage : %d", tg->maxusage);
2d4ba67d
CP
81 controlreply(sender, "Last max reset : %s", tg->lastmaxuserreset?trusts_timetostr(tg->lastmaxuserreset):"(never)");
82
4be1aaf2 83 controlreply(sender, "Host Current Max Last seen");
2d4ba67d
CP
84
85 for(th=tg->hosts;th;th=th->next)
d36ca89c 86 controlreply(sender, " %-20s %-10d %-10d %s", trusts_cidr2str(th->ip, th->mask), th->count, th->maxusage, (th->count>0)?"(now)":((th->lastseen>0)?trusts_timetostr(th->lastseen):"(never)"));
2d4ba67d
CP
87
88 controlreply(sender, "End of list.");
89
90 return CMD_OK;
91}
92
d2c08930
CP
93static int trusts_cmdtrustadd(void *source, int cargc, char **cargv) {
94 trustgroup *tg;
95 nick *sender = source;
96 char *host;
97 uint32_t ip, mask;
9097ab05 98 trusthost *th, *superset, *subset;
d2c08930
CP
99
100 if(cargc < 2)
101 return CMD_USAGE;
102
103 tg = tg_strtotg(cargv[0]);
104 if(!tg) {
105 controlreply(sender, "Couldn't look up trustgroup.");
106 return CMD_ERROR;
107 }
108
109 host = cargv[1];
110 if(!trusts_str2cidr(host, &ip, &mask)) {
111 controlreply(sender, "Invalid host.");
112 return CMD_ERROR;
113 }
114
9097ab05
CP
115 /* OKAY! Lots of checking here!
116 *
117 * Need to check:
118 * - host isn't already covered by given group (reject if it is)
119 * - host doesn't already exist exactly already (reject if it does)
120 * - host is more specific than an existing one (warn if it is, fix up later)
121 * - host is less specific than an existing one (warn if it is, don't need to do anything special)
122 */
123
124 for(th=tg->hosts;th;th=th->next) {
125 if(th->ip == (ip & th->mask)) {
126 controlreply(sender, "This host (or part of it) is already covered in the given group.");
d2c08930
CP
127 return CMD_ERROR;
128 }
9097ab05 129 }
d2c08930 130
9097ab05
CP
131 if(th_getbyhostandmask(ip, mask)) {
132 controlreply(sender, "This host already exists in another group with the same mask.");
133 return CMD_ERROR;
134 }
135
136 /* this function will set both to NULL if it's equal, hence the check above */
137 th_getsuperandsubsets(ip, mask, &superset, &subset);
138 if(superset) {
139 /* a superset exists for us, we will be more specific than one existing host */
140
141 controlreply(sender, "Warning: this host already exists in another group, but this new host will override it as it has a smaller prefix.");
142 }
143 if(subset) {
144 /* a subset of us exists, we will be less specific than some existing hosts */
145
146 controlreply(sender, "Warning: this host already exists in at least one other group, the new host has a larger prefix and therefore will not override those hosts.");
d2c08930 147 }
9097ab05
CP
148 if(superset || subset)
149 controlreply(sender, "Adding anyway...");
d2c08930
CP
150
151 th = th_new(tg, host);
152 if(!th) {
153 controlreply(sender, "An error occured adding the host to the group.");
154 return CMD_ERROR;
155 }
156
157 controlreply(sender, "Host added.");
158 /* TODO: controlwall */
159
160 return CMD_OK;
161}
162
163static int trusts_cmdtrustgroupadd(void *source, int cargc, char **cargv) {
164 nick *sender = source;
165 char *name, *contact, *comment, createdby[ACCOUNTLEN + 2];
166 unsigned int howmany, maxperident, enforceident;
167 time_t howlong;
168 trustgroup *tg;
169
170 if(cargc < 6)
171 return CMD_USAGE;
172
173 name = cargv[0];
174 howmany = strtoul(cargv[1], NULL, 10);
175 if(!howmany || (howmany > 50000)) {
176 controlreply(sender, "Bad value maximum number of clients.");
177 return CMD_ERROR;
178 }
179
180 howlong = durationtolong(cargv[2]);
181 if((howlong <= 0) || (howlong > 365 * 86400 * 20)) {
182 controlreply(sender, "Invalid duration supplied.");
183 return CMD_ERROR;
184 }
185
186 maxperident = strtoul(cargv[3], NULL, 10);
187 if(!howmany || (maxperident > 1000)) {
188 controlreply(sender, "Bad value for max per ident.");
189 return CMD_ERROR;
190 }
191
192 if(cargv[4][0] != '1' && cargv[4][0] != '0') {
193 controlreply(sender, "Bad value for enforce ident (use 0 or 1).");
194 return CMD_ERROR;
195 }
196 enforceident = cargv[4][0] == '1';
197
198 contact = cargv[5];
199
200 if(cargc < 7) {
201 comment = "(no comment)";
202 } else {
203 comment = cargv[6];
204 }
205
206 /* don't allow #id or id forms */
207 if((name[0] == '#') || strtoul(name, NULL, 10)) {
208 controlreply(sender, "Invalid trustgroup name.");
209 return CMD_ERROR;
210 }
211
212 tg = tg_strtotg(name);
213 if(tg) {
214 controlreply(sender, "A group with that name already exists");
215 return CMD_ERROR;
216 }
217
218 snprintf(createdby, sizeof(createdby), "#%s", sender->authname);
219
220 tg = tg_new(name, howmany, enforceident, maxperident, howlong + time(NULL), createdby, contact, comment);
221 if(!tg) {
222 controlreply(sender, "An error occured adding the trustgroup.");
223 return CMD_ERROR;
224 }
225
226 controlreply(sender, "Group added.");
227 /* TODO: controlwall */
228
229 return CMD_OK;
230}
231
a99a2041
CP
232static int commandsregistered;
233
234static void registercommands(int hooknum, void *arg) {
235 if(commandsregistered)
236 return;
237 commandsregistered = 1;
238
239 registercontrolhelpcmd("trustmigrate", NO_DEVELOPER, 0, trusts_cmdmigrate, "Usage: trustmigrate\nCopies trust data from O and reloads the database.");
240 registercontrolhelpcmd("trustlist", NO_OPER, 1, trusts_cmdtrustlist, "Usage: trustlist <#id|name|id>\nShows trust data for the specified trust group.");
d2c08930
CP
241 registercontrolhelpcmd("trustgroupadd", NO_OPER, 6, trusts_cmdtrustgroupadd, "Usage: trustgroupadd <name> <howmany> <howlong> <maxperident> <enforceident> <contact> ?comment?");
242 registercontrolhelpcmd("trustadd", NO_OPER, 2, trusts_cmdtrustadd, "Usage: trustadd <#id|name|id> <host>");
a99a2041
CP
243}
244
83bccee3 245static void deregistercommands(int hooknum, void *arg) {
a99a2041
CP
246 if(!commandsregistered)
247 return;
248 commandsregistered = 0;
249
250 deregistercontrolcmd("trustmigrate", trusts_cmdmigrate);
251 deregistercontrolcmd("trustlist", trusts_cmdtrustlist);
d2c08930
CP
252 deregistercontrolcmd("trustgroupadd", trusts_cmdtrustgroupadd);
253 deregistercontrolcmd("trustadd", trusts_cmdtrustadd);
be2823bc
CP
254}
255
256void _init(void) {
a99a2041 257 registerhook(HOOK_TRUSTS_DB_LOADED, registercommands);
83bccee3 258 registerhook(HOOK_TRUSTS_DB_CLOSED, deregistercommands);
be2823bc
CP
259
260 if(trustsdbloaded)
a99a2041 261 registercommands(0, NULL);
be2823bc
CP
262}
263
264void _fini(void) {
a99a2041 265 deregisterhook(HOOK_TRUSTS_DB_LOADED, registercommands);
83bccee3 266 deregisterhook(HOOK_TRUSTS_DB_CLOSED, deregistercommands);
be2823bc
CP
267
268 trusts_migration_stop();
be2823bc 269
83bccee3
CP
270 deregistercommands(0, NULL);
271}